From 9c1c8125845a870e1e07be37001a0264af53a07e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Mon, 9 Mar 2026 18:51:35 +0200 Subject: [PATCH 1/2] Normalize source code to UTF-8 with LF line endings. --- CMakeSettings.json | 116 +- LICENSES/LICENSE-I386C.TXT | 2 +- LICENSES/LICENSE-TGUI9680.TXT | 4 +- LICENSES/LICENSE.TXT | 2 +- LICENSES/dosbox-fpu/LICENSE-GPL.TXT | 4 +- LICENSES/fmgen/fmgen_readme.txt | 118 +- LICENSES/mame/LICENSE-MAME-GPL.TXT | 4 +- LICENSES/mamebsd/LICENSE-MAME-BSD.TXT | 4 +- LICENSES/softfloat/README2.txt | 4 +- LICENSES/softfloat3/README2.txt | 4 +- ...0\344\275\223\350\252\254\346\230\216.txt" | 4 +- accessories/bin2txt.c | 226 +- accessories/lzxpack.c | 540 +- accessories/textout.c | 182 +- accessories/textout.h | 10 +- bios/bios.h | 294 +- bios/bios09.c | 268 +- bios/bios0c.c | 198 +- bios/bios12.c | 142 +- bios/bios13.c | 142 +- bios/bios18.c | 2638 +-- bios/bios19.c | 386 +- bios/bios1a.c | 944 +- bios/bios1b.c | 2174 +-- bios/bios1c.c | 166 +- bios/biosmem.h | 212 +- bios/fdfmt.h | 50 +- bios/rsbios.h | 110 +- bios/sxsibios.c | 1574 +- bios/sxsibios.h | 74 +- calendar.c | 528 +- calendar.h | 54 +- cbus/amd98.c | 1092 +- cbus/amd98.h | 102 +- cbus/atapicmd.c | 3232 ++-- cbus/atapicmd.h | 124 +- cbus/board118.c | 1944 +- cbus/board118.h | 44 +- cbus/board14.c | 510 +- cbus/board14.h | 106 +- cbus/board26k.c | 174 +- cbus/board26k.h | 42 +- cbus/board86.c | 378 +- cbus/board86.h | 42 +- cbus/boardlol.c | 4 +- cbus/boardmo.c | 4 +- cbus/boardpx.c | 1014 +- cbus/boardpx.h | 58 +- cbus/boardsb16.c | 1296 +- cbus/boardso.c | 224 +- cbus/boardso.h | 42 +- cbus/boardspb.c | 470 +- cbus/boardspb.h | 50 +- cbus/boardx2.c | 460 +- cbus/boardx2.h | 42 +- cbus/cbuscore.c | 300 +- cbus/cbuscore.h | 30 +- cbus/cs4231io.c | 1052 +- cbus/cs4231io.h | 124 +- cbus/ct1741io.c | 1462 +- cbus/ct1741io.h | 42 +- cbus/ct1745io.c | 514 +- cbus/ct1745io.h | 84 +- cbus/gpibio.c | 818 +- cbus/gpibio.h | 76 +- cbus/ideio.c | 4204 ++--- cbus/ideio.h | 422 +- cbus/mpu98ii.c | 2482 +-- cbus/mpu98ii.h | 222 +- cbus/pc9861k.c | 700 +- cbus/pc9861k.h | 112 +- cbus/pcm86io.c | 1034 +- cbus/pcm86io.h | 28 +- cbus/sasiio.c | 966 +- cbus/sasiio.h | 86 +- cbus/scsicmd.c | 558 +- cbus/scsicmd.h | 40 +- cbus/scsiio.c | 1546 +- cbus/scsiio.h | 830 +- cbus/smpu98.c | 3430 ++-- cbus/smpu98.h | 256 +- codecnv/codecnv.h | 150 +- codecnv/eucsjis.c | 264 +- codecnv/eucucs2.c | 154 +- codecnv/sjiseuc.c | 256 +- codecnv/sjisucs2.c | 2740 +-- codecnv/tcswap16.c | 38 +- codecnv/tcswap32.c | 46 +- codecnv/textcnv.c | 186 +- codecnv/textcnv.h | 82 +- codecnv/ucs2sjis.c | 5940 +++--- codecnv/ucs2ucs4.c | 230 +- codecnv/ucs2utf8.c | 178 +- codecnv/utf8ucs4.c | 242 +- common.h | 432 +- common/_memory.c | 454 +- common/_memory.h | 102 +- common/bmpdata.c | 374 +- common/bmpdata.h | 150 +- common/lstarray.c | 302 +- common/lstarray.h | 62 +- common/milstr.c | 2018 +- common/milstr.h | 318 +- common/mimpidef.c | 272 +- common/mimpidef.h | 50 +- common/parts.c | 210 +- common/parts.h | 36 +- common/profile.c | 2380 +-- common/profile.h | 206 +- common/rect.c | 310 +- common/rect.h | 108 +- common/resize.c | 1238 +- common/resize.h | 84 +- common/strres.c | 140 +- common/strres.h | 156 +- common/textfile.c | 1178 +- common/textfile.h | 34 +- common/wavefile.c | 512 +- common/wavefile.h | 42 +- compiler_base.h | 882 +- debugsub.c | 366 +- debugsub.h | 30 +- debugsub386.c | 490 +- diskimage/cd/cdd_ccd.c | 344 +- diskimage/cd/cdd_ccd.h | 26 +- diskimage/cd/cdd_cue.c | 370 +- diskimage/cd/cdd_cue.h | 26 +- diskimage/cd/cdd_iso.c | 160 +- diskimage/cd/cdd_iso.h | 18 +- diskimage/cd/cdd_mds.c | 566 +- diskimage/cd/cdd_mds.h | 22 +- diskimage/cd/cdd_nrg.c | 698 +- diskimage/cd/cdd_nrg.h | 22 +- diskimage/cd/cdd_real.c | 1244 +- diskimage/cd/cdd_real.h | 100 +- diskimage/cddfile.c | 1620 +- diskimage/cddfile.h | 86 +- diskimage/fd/fdd_bkdsk.c | 190 +- diskimage/fd/fdd_bkdsk.h | 22 +- diskimage/fd/fdd_d88.c | 2832 +-- diskimage/fd/fdd_d88.h | 140 +- diskimage/fd/fdd_dcp.c | 918 +- diskimage/fd/fdd_dcp.h | 28 +- diskimage/fd/fdd_head_d88.h | 132 +- diskimage/fd/fdd_head_dcp.h | 74 +- diskimage/fd/fdd_head_nfd.h | 376 +- diskimage/fd/fdd_head_vfdd.h | 188 +- diskimage/fd/fdd_nfd.c | 1942 +- diskimage/fd/fdd_nfd.h | 44 +- diskimage/fd/fdd_vfdd.c | 552 +- diskimage/fd/fdd_vfdd.h | 30 +- diskimage/fd/fdd_xdf.c | 1694 +- diskimage/fd/fdd_xdf.h | 114 +- diskimage/fddfile.c | 1668 +- diskimage/fddfile.h | 574 +- diskimage/img_common.h | 10 +- diskimage/img_strres.c | 36 +- diskimage/img_strres.h | 38 +- diskimage/win9x/img_dosio.c | 56 +- diskimage/win9x/img_dosio.h | 36 +- embed/menu/dlgabout.c | 158 +- embed/menu/dlgabout.h | 48 +- embed/menu/dlgcfg.h | 48 +- embed/menu/dlgscr.c | 852 +- embed/menu/dlgscr.h | 46 +- embed/menu/dlgwab.c | 894 +- embed/menu/dlgwab.h | 40 +- embed/menu/filesel.h | 24 +- embed/menu/menustr.c | 92 +- embed/menu/menustr.h | 32 +- embed/menubase/menubase.h | 164 +- embed/menubase/menudeco.inc | 368 +- embed/menubase/menudlg.c | 4846 ++--- embed/menubase/menudlg.h | 290 +- embed/menubase/menuicon.c | 566 +- embed/menubase/menuicon.h | 54 +- embed/menubase/menumbox.c | 476 +- embed/menubase/menumbox.h | 48 +- embed/menubase/menures.c | 686 +- embed/menubase/menures.h | 60 +- embed/menubase/menusys.c | 2356 +-- embed/menubase/menusys.h | 156 +- embed/menubase/menuvram.c | 2458 +-- embed/menubase/menuvram.h | 124 +- embed/readme.txt | 16 +- embed/vramhdl.c | 1502 +- embed/vramhdl.h | 182 +- embed/vrammix.c | 7682 ++++---- embed/vrammix.h | 190 +- fdd/d88head.h | 126 +- fdd/diskdrv.c | 572 +- fdd/diskdrv.h | 56 +- fdd/fdd_mtr.h | 74 +- fdd/hdd_vhd.h | 362 +- fdd/hdd_vpc.h | 134 +- fdd/newdisk.c | 1092 +- fdd/newdisk.h | 56 +- fdd/sxsi.c | 1228 +- fdd/sxsi.h | 230 +- fdd/sxsicd.c | 1208 +- fdd/sxsicd.h | 356 +- fdd/sxsihdd.c | 648 +- fdd/sxsihdd.h | 162 +- fdd/sxsihdd_nvl.c | 1012 +- font/font.h | 94 +- font/fontdata.c | 178 +- font/fontdata.h | 138 +- font/fontfm7.c | 252 +- font/fontmake.c | 1320 +- font/fontmake.h | 22 +- font/fontpc88.c | 388 +- font/fontpc98.c | 284 +- font/fontv98.c | 192 +- font/fontx1.c | 254 +- font/fontx68k.c | 224 +- font/readme.txt | 38 +- generic/cmjasts.c | 296 +- generic/cmjasts.h | 26 +- generic/cmndraw.c | 944 +- generic/cmndraw.h | 130 +- generic/cmver.c | 924 +- generic/cmver.h | 50 +- generic/dipswbmp.c | 906 +- generic/dipswbmp.h | 48 +- generic/hostdrv.c | 4196 ++--- generic/hostdrv.h | 166 +- generic/hostdrvs.c | 1192 +- generic/hostdrvs.h | 148 +- generic/keydisp.c | 2640 +-- generic/keydisp.h | 210 +- generic/memdbg32.c | 318 +- generic/memdbg32.h | 86 +- generic/np2info.c | 1258 +- generic/np2info.h | 44 +- generic/readme.txt | 14 +- generic/softkbd.c | 310 +- generic/softkbd.h | 72 +- generic/unasm.c | 1182 +- generic/unasm.h | 34 +- i286c/cpumem.h | 236 +- i286c/i286c.h | 322 +- i286c/i286c.mcr | 1016 +- i286c/i286c_0f.c | 576 +- i286c/i286c_8x.c | 748 +- i286c/i286c_ea.c | 1982 +- i286c/i286c_f6.c | 658 +- i286c/i286c_fe.c | 444 +- i286c/i286c_rp.c | 846 +- i286c/i286c_sf.c | 1234 +- i286c/i286c_sf.mcr | 698 +- i286x/cpucore.h | 624 +- i286x/cpucore.inc | 124 +- i286x/cpumem.h | 238 +- i286x/i286x.cpp | 11078 +++++------ i286x/i286x.h | 206 +- i286x/i286xadr.cpp | 2054 +- i286x/i286xadr.h | 10 +- i286x/i286xcts.cpp | 774 +- i286x/i286xcts.h | 6 +- i286x/i286xrep.h | 40 +- i286x/i286xs.h | 48 +- i386c/cpucore.c | 196 +- i386c/cpucore.h | 18 +- i386c/cpumem.c | 3620 ++-- i386c/cpumem.h | 320 +- i386c/ia32/cpu.c | 1266 +- i386c/ia32/cpu.h | 2960 +-- i386c/ia32/cpu_io.c | 238 +- i386c/ia32/cpu_mem.c | 1216 +- i386c/ia32/cpu_mem.h | 182 +- i386c/ia32/cpu_mem.mcr | 284 +- i386c/ia32/ctrlxfer.c | 2872 +-- i386c/ia32/ctrlxfer.h | 84 +- i386c/ia32/debug.c | 804 +- i386c/ia32/disasm.c | 1726 +- i386c/ia32/exception.c | 1326 +- i386c/ia32/exception.h | 150 +- i386c/ia32/groups.c | 976 +- i386c/ia32/groups.h | 160 +- i386c/ia32/ia32.c | 670 +- i386c/ia32/ia32.mcr | 1966 +- i386c/ia32/ia32weak.txt | 154 +- i386c/ia32/ia32xc.mcr | 3420 ++-- i386c/ia32/ia32xc_msc.mcr | 1094 +- i386c/ia32/inst_table.c | 9412 +++++----- i386c/ia32/inst_table.h | 214 +- i386c/ia32/instructions/arith.mcr | 1048 +- i386c/ia32/instructions/bin_arith.c | 1508 +- i386c/ia32/instructions/bin_arith.h | 390 +- i386c/ia32/instructions/bit_byte.c | 2110 +-- i386c/ia32/instructions/bit_byte.h | 198 +- i386c/ia32/instructions/ctrl_trans.c | 3204 ++-- i386c/ia32/instructions/ctrl_trans.h | 306 +- i386c/ia32/instructions/data_trans.c | 3524 ++-- i386c/ia32/instructions/data_trans.h | 568 +- i386c/ia32/instructions/dec_arith.c | 598 +- i386c/ia32/instructions/dec_arith.h | 94 +- i386c/ia32/instructions/flag_ctrl.c | 642 +- i386c/ia32/instructions/flag_ctrl.h | 102 +- i386c/ia32/instructions/fpu.c | 864 +- i386c/ia32/instructions/fpu/fp.h | 188 +- i386c/ia32/instructions/fpu/fpdummy.c | 320 +- i386c/ia32/instructions/fpu/fpemul.c | 2658 +-- i386c/ia32/instructions/fpu/fpemul_dosbox.c | 4012 ++-- i386c/ia32/instructions/fpu/fpemul_dosbox2.c | 4426 ++--- .../ia32/instructions/fpu/fpemul_softfloat.c | 3702 ++-- .../instructions/fpu/fpemul_softfloat3.cpp | 150 +- i386c/ia32/instructions/fpu/fpumem.h | 164 +- .../instructions/fpu/softfloat/README.txt | 166 +- .../fpu/softfloat/SoftFloat-history.txt | 130 +- .../fpu/softfloat/SoftFloat-source.txt | 800 +- .../instructions/fpu/softfloat/SoftFloat.txt | 778 +- .../fpu/softfloat/softfloat-macros.h | 1426 +- .../fpu/softfloat/softfloat-specialize.h | 938 +- .../instructions/fpu/softfloat/softfloat.c | 10874 +++++------ .../instructions/fpu/softfloat/softfloat.h | 534 +- .../instructions/fpu/softfloat/softfloatdef.h | 44 +- .../fpu/softfloat3/include/stdbool.h | 2 +- i386c/ia32/instructions/logic_arith.c | 104 +- i386c/ia32/instructions/logic_arith.h | 202 +- i386c/ia32/instructions/misc_inst.c | 802 +- i386c/ia32/instructions/misc_inst.h | 132 +- i386c/ia32/instructions/mmx/3dnow.c | 1726 +- i386c/ia32/instructions/mmx/3dnow.h | 140 +- i386c/ia32/instructions/mmx/mmx.c | 4178 ++--- i386c/ia32/instructions/mmx/mmx.h | 234 +- i386c/ia32/instructions/mmx/mmx2.txt | 4180 ++--- i386c/ia32/instructions/seg_reg.c | 460 +- i386c/ia32/instructions/seg_reg.h | 96 +- i386c/ia32/instructions/shift_rotate.c | 100 +- i386c/ia32/instructions/shift_rotate.h | 330 +- i386c/ia32/instructions/shift_rotate.mcr | 2218 +-- i386c/ia32/instructions/shift_rotatexc.mcr | 4286 ++--- .../ia32/instructions/shift_rotatexc_msc.mcr | 1276 +- i386c/ia32/instructions/sse/sse.c | 3538 ++-- i386c/ia32/instructions/sse/sse.h | 246 +- i386c/ia32/instructions/sse2/sse2.c | 6986 +++---- i386c/ia32/instructions/sse2/sse2.h | 426 +- i386c/ia32/instructions/sse3/sse3.c | 598 +- i386c/ia32/instructions/sse3/sse3.h | 106 +- i386c/ia32/instructions/string_inst.c | 2582 +-- i386c/ia32/instructions/string_inst.h | 178 +- i386c/ia32/instructions/system_inst.c | 2596 +-- i386c/ia32/instructions/system_inst.h | 210 +- i386c/ia32/interface.c | 674 +- i386c/ia32/interface.h | 196 +- i386c/ia32/paging.c | 1870 +- i386c/ia32/paging.h | 754 +- i386c/ia32/resolve.c | 1254 +- i386c/ia32/resolve.h | 104 +- i386c/ia32/segments.c | 832 +- i386c/ia32/segments.h | 382 +- i386c/ia32/task.c | 1092 +- i386c/ia32/task.h | 102 +- i386hax/haxcore.c | 3176 ++-- i386hax/haxcore.h | 228 +- i386hax/haxfunc.c | 1040 +- i386hax/haxfunc.h | 1058 +- io/artic.c | 216 +- io/artic.h | 42 +- io/cgrom.c | 454 +- io/cgrom.h | 50 +- io/cpuio.c | 280 +- io/cpuio.h | 22 +- io/crtc.c | 210 +- io/crtc.h | 84 +- io/dipsw.c | 230 +- io/dipsw.h | 24 +- io/egc.c | 382 +- io/egc.h | 114 +- io/emsio.c | 154 +- io/emsio.h | 40 +- io/epsonio.c | 258 +- io/epsonio.h | 36 +- io/fdc.c | 2352 +-- io/fdc.h | 276 +- io/fdd320.c | 78 +- io/fdd320.h | 24 +- io/gdc.c | 2386 +-- io/gdc_cmd.h | 94 +- io/gdc_pset.c | 348 +- io/gdc_pset.h | 64 +- io/gdc_sub.c | 1366 +- io/gdc_sub.h | 110 +- io/iocore.c | 1690 +- io/iocore.h | 268 +- io/lsidef.h | 36 +- io/mouseif.c | 674 +- io/mouseif.h | 68 +- io/necio.c | 118 +- io/necio.h | 34 +- io/nmiio.c | 80 +- io/nmiio.h | 34 +- io/np2sysp.c | 1854 +- io/np2sysp.h | 56 +- io/pci/98graphbridge.c | 166 +- io/pci/98graphbridge.h | 44 +- io/pci/cbusbridge.c | 398 +- io/pci/cbusbridge.h | 44 +- io/pcidev.c | 1578 +- io/pcidev.h | 350 +- io/pegc.c | 770 +- io/pegc.h | 94 +- io/pic.c | 904 +- io/pic.h | 140 +- io/pit.c | 1094 +- io/pit.h | 134 +- io/printif.c | 166 +- io/printif.h | 26 +- io/serial.c | 1900 +- io/serial.h | 176 +- io/sysport.c | 218 +- io/sysport.h | 34 +- io/upd4990.c | 478 +- keystat.c | 1440 +- lio/gcircle.c | 184 +- lio/gline.c | 726 +- lio/gpset.c | 180 +- lio/gput1.c | 1308 +- lio/gscreen.c | 622 +- lio/lio.c | 576 +- lio/lio.h | 198 +- mem/dmav30.c | 92 +- mem/dmav30.h | 22 +- mem/dmax86.c | 92 +- mem/dmax86.h | 22 +- mem/memegc.c | 2848 +-- mem/memegc.h | 46 +- mem/memems.c | 116 +- mem/memems.h | 32 +- mem/memepp.c | 178 +- mem/memepp.h | 42 +- mem/memtram.c | 360 +- mem/memtram.h | 32 +- mem/memvga.c | 1342 +- mem/memvga.h | 86 +- mem/memvram.c | 568 +- mem/memvram.h | 86 +- misc/test_codecnv.c | 204 +- misc/test_milstr.c | 158 +- network/lgy98.c | 2250 +-- network/lgy98.h | 114 +- network/lgy98dev.h | 222 +- network/net.c | 1414 +- network/net.h | 54 +- network/readme.txt | 14 +- nevent.c | 922 +- nevent.h | 306 +- np2tool/HOSTDRV.INC | 52 +- np2tool/HOSTDRV.TXT | 54 +- np2tool/NP2IDLE.TXT | 36 +- np2tool/NP2TOOL.INC | 8 +- np2tool/NP2TOOL.X86 | 64 +- np2tool/PWOFF.TXT | 6 +- np2tool/README.TXT | 6 +- np2tool/hostdrvnt/hdrvmnt.c | 36 +- np2tool/hostdrvnt/hostdrv.c | 322 +- np2tool/hostdrvnt/irplock.c | 40 +- np2tool/hostdrvnt/irplock.h | 28 +- np2tool/hostdrvnt/miniifs.h | 4 +- np2tool/hostdrvnt/minisop.c | 104 +- np2tool/hostdrvnt/minisop.h | 40 +- np2tool/hostdrvnt/readme.txt | 222 +- np2tool/hostdrvnt/test/fstestA.c | 12 +- np2tool/hostdrvnt/test/fstestB.c | 16 +- np2tool/hostdrvnt/test/fstestC.c | 10 +- np2tool/hostdrvnt/test/fstestD.c | 22 +- np2tool/hostdrvnt/test/fstestE.c | 24 +- np2tool/nasmmemo.txt | 2 +- np2tool/npmouse/readme.txt | 136 +- np2tool/npmouse/w2k/npmouse.c | 74 +- np2tool/npmouse/wnt/npmouse.c | 62 +- np2tool/npstor/npstor.c | 10 +- np2tool/npstor/readme.txt | 152 +- np2tool/npstor/wnt/npstor.c | 14 +- np2tool/npsysprt/npcngclk.c | 16 +- np2tool/npsysprt/npgetpos.c | 10 +- np2tool/npsysprt/npsyscmd.c | 22 +- np2tool/npsysprt/npsysprt.c | 80 +- np2tool/npsysprt/npsysprt.h | 18 +- np2tool/npsysprt/readme.txt | 96 +- np2ver.h | 22 +- pccore.c | 3872 ++-- pccore.h | 950 +- readme.txt | 538 +- romimage/BEEP.X86 | 70 +- romimage/BIOS/BIOSMAIN.X86 | 180 +- romimage/BIOS/EOI.X86 | 50 +- romimage/BIOS/VECT02.X86 | 70 +- romimage/BIOS/VECT08.X86 | 60 +- romimage/BIOS/VECT13.X86 | 202 +- romimage/BIOS/VECT1A.X86 | 28 +- romimage/BIOS/VECT1F.X86 | 172 +- romimage/BIOS/vect09.x86 | 82 +- romimage/DATASEG.INC | 58 +- romimage/DIPSW.X86 | 238 +- romimage/FIRMWARE.X86 | 140 +- romimage/ITF.INC | 98 +- romimage/ITFSUB.X86 | 30 +- romimage/KEYBOARD.INC | 114 +- romimage/KEYBOARD.X86 | 168 +- romimage/MEMCHK.X86 | 480 +- romimage/MEMSW.X86 | 34 +- romimage/NP2.X86 | 146 +- romimage/PC98.INC | 34 +- romimage/RESOURCE.TXT | 722 +- romimage/SSP.X86 | 310 +- romimage/SSP_DIP.X86 | 328 +- romimage/SSP_MSW.X86 | 1054 +- romimage/SSP_RES.X86 | 624 +- romimage/SSP_SUB.X86 | 112 +- romimage/TEXTDISP.X86 | 546 +- romimage/readme.txt | 12 +- romimage/tool/BIN2TXT.C | 116 +- romimage/tool/COMMON.H | 30 +- romimage/tool/DOSIO.H | 120 +- romimage/tool/MIL.INC | 232 +- romimage/tool/TXTPACK.C | 658 +- sdl/commng.c | 382 +- sdl/fontmng.c | 1402 +- sdl/fontmng.h | 102 +- sdl/ini.c | 2018 +- sdl/inputmng.h | 66 +- sdl/libretro/compiler.h | 64 +- .../include/glsym/rglgen_private_headers.h | 152 +- sdl/libretro/libretro.c | 3804 ++-- sdl/libretro/libretro_core_options.h | 4046 ++-- sdl/libretro/rsemaphore.h | 108 +- sdl/np2.c | 1768 +- sdl/oemtext.h | 38 +- sdl/sysmenu.h | 38 +- sdl/sysmng.h | 120 +- sdl/taskmng.h | 34 +- sdl/timemng.h | 50 +- sdl/trace.c | 66 +- sdl/trace.h | 58 +- sdl/windows/main.c | 66 +- sound/adpcm.h | 170 +- sound/adpcmc.c | 258 +- sound/adpcmg.c | 720 +- sound/beep.h | 166 +- sound/beepc.c | 352 +- sound/beepg.c | 354 +- sound/cs4231.h | 366 +- sound/cs4231c.c | 976 +- sound/cs4231g.c | 760 +- sound/fmboard.c | 1220 +- sound/fmboard.h | 122 +- sound/fmgen/fmgen_diag.h | 38 +- sound/fmgen/fmgen_file.cpp | 388 +- sound/fmgen/fmgen_file.h | 138 +- sound/fmgen/fmgen_fmgen.cpp | 2178 +-- sound/fmgen/fmgen_fmgen.h | 680 +- sound/fmgen/fmgen_fmgeninl.h | 546 +- sound/fmgen/fmgen_fmtimer.cpp | 440 +- sound/fmgen/fmgen_fmtimer.h | 144 +- sound/fmgen/fmgen_headers.h | 60 +- sound/fmgen/fmgen_misc.h | 148 +- sound/fmgen/fmgen_opm.cpp | 1136 +- sound/fmgen/fmgen_opm.h | 412 +- sound/fmgen/fmgen_opna.h | 1044 +- sound/fmgen/fmgen_psg.cpp | 796 +- sound/fmgen/fmgen_psg.h | 238 +- sound/fmgen/fmgen_readme.txt | 186 +- sound/fmgen/fmgen_types.h | 66 +- sound/getsnd/getmp3.c | 226 +- sound/getsnd/getogg.c | 528 +- sound/getsnd/getsmix.c | 306 +- sound/getsnd/getsnd.c | 204 +- sound/getsnd/getsnd.h | 114 +- sound/getsnd/getsndmn.mcr | 320 +- sound/getsnd/getsndst.mcr | 346 +- sound/getsnd/getwave.c | 1152 +- sound/mamebsdsub/np2compatible.cpp | 14 +- sound/mamebsdsub/np2interop.cpp | 26 +- sound/mamebsdsub/np2ymfm.h | 2 +- sound/opl3.c | 626 +- sound/opl3.h | 154 +- sound/oplgen.h | 170 +- sound/oplgenc.c | 1152 +- sound/oplgencfg.h | 124 +- sound/oplgeng.c | 612 +- sound/opngen.h | 204 +- sound/opngenc.c | 1334 +- sound/opngencfg.h | 156 +- sound/opngeng.c | 570 +- sound/opntimer.c | 450 +- sound/opntimer.h | 46 +- sound/pcm86.h | 318 +- sound/pcm86c.c | 994 +- sound/pcm86g.c | 786 +- sound/pcmmix.c | 328 +- sound/pcmmix.h | 104 +- sound/psggen.h | 176 +- sound/psggenc.c | 348 +- sound/psggeng.c | 248 +- sound/rhythm.h | 68 +- sound/rhythmc.c | 318 +- sound/sndcsec.c | 26 +- sound/sndcsec.h | 70 +- sound/sound.c | 878 +- sound/sound.h | 126 +- sound/tms3631.h | 104 +- sound/tms3631c.c | 132 +- sound/tms3631g.c | 124 +- sound/vermouth/midimod.c | 1194 +- sound/vermouth/midimod.h | 86 +- sound/vermouth/midinst.c | 1198 +- sound/vermouth/midinst.h | 142 +- sound/vermouth/midiout.c | 2500 +-- sound/vermouth/midiout.h | 298 +- sound/vermouth/midtable.c | 336 +- sound/vermouth/midtable.h | 134 +- sound/vermouth/midvoice.c | 1766 +- sound/vermouth/midvoice.h | 316 +- sound/vermouth/vermouth.h | 134 +- statsave.c | 4206 ++--- statsave.h | 128 +- timing.c | 206 +- timing.h | 42 +- trap/inttrap.c | 572 +- trap/inttrap.h | 42 +- trap/steptrap.c | 476 +- trap/steptrap.h | 44 +- update.txt | 1568 +- vram/dispsync.c | 302 +- vram/dispsync.h | 62 +- vram/makegrex.c | 642 +- vram/makegrex.h | 30 +- vram/makegrph.c | 906 +- vram/makegrph.h | 36 +- vram/makegrph.mcr | 160 +- vram/maketext.c | 1530 +- vram/maketext.h | 88 +- vram/maketgrp.c | 1070 +- vram/maketgrp.h | 24 +- vram/palettes.c | 1114 +- vram/palettes.h | 156 +- vram/scrndraw.h | 74 +- vram/scrnsave.c | 1856 +- vram/scrnsave.h | 94 +- vram/sdraw.c | 348 +- vram/sdraw.h | 76 +- vram/sdraw.mcr | 2108 +-- vram/sdrawex.mcr | 604 +- vram/sdrawq16.c | 612 +- vram/vram.c | 48 +- vram/vram.h | 146 +- wab/cirrus_vga.c | 15622 ++++++++-------- wab/cirrus_vga.h | 432 +- wab/cirrus_vga_extern.h | 478 +- wab/cirrus_vga_rop.h | 386 +- wab/cirrus_vga_rop2.h | 596 +- wab/tgui9680.c | 3606 ++-- wab/tgui9680_wrapper.h | 616 +- wab/vga_int.h | 1046 +- wab/wab.c | 2100 +-- wab/wab.h | 194 +- wab/wab_rly.h | 60 +- wab/wabbmpsave.h | 44 +- windows/commng.cpp | 278 +- windows/commng.h | 266 +- windows/commng/cmbase.cpp | 246 +- windows/commng/cmbase.h | 168 +- windows/commng/cmmidi.cpp | 82 +- windows/commng/cmmidi.h | 30 +- windows/commng/cmmidiin32.cpp | 400 +- windows/commng/cmmidiin32.h | 74 +- windows/commng/cmmidiout.h | 74 +- windows/commng/cmmidiout32.cpp | 272 +- windows/commng/cmmidiout32.h | 64 +- windows/commng/cmmidioutmt32sound.cpp | 154 +- windows/commng/cmmidioutmt32sound.h | 66 +- windows/commng/cmmidioutvermouth.cpp | 188 +- windows/commng/cmmidioutvermouth.h | 64 +- windows/commng/cmmidioutvst.cpp | 362 +- windows/commng/cmmidioutvst.h | 90 +- windows/commng/cmnull.cpp | 126 +- windows/commng/cmnull.h | 46 +- windows/commng/cmpara.cpp | 214 +- windows/commng/cmpara.h | 60 +- windows/commng/cmpipe.cpp | 626 +- windows/commng/cmpipe.h | 84 +- windows/commng/cmserial.cpp | 1438 +- windows/commng/cmserial.h | 124 +- windows/commng/cmwacom.cpp | 160 +- windows/commng/cmwacom.h | 326 +- windows/commng/vsthost/vstbuffer.cpp | 24 +- windows/commng/vsthost/vstbuffer.h | 14 +- windows/commng/vsthost/vsteditwnd.cpp | 84 +- windows/commng/vsthost/vsteditwnd.h | 12 +- windows/commng/vsthost/vsteditwndbase.h | 4 +- windows/commng/vsthost/vsteffect.cpp | 46 +- windows/commng/vsthost/vsteffect.h | 12 +- windows/commng/vsthost/vstmidievent.cpp | 34 +- windows/commng/vsthost/vstmidievent.h | 10 +- windows/commonfix.h | 934 +- windows/compiler.cpp | 10 +- windows/compiler.h | 162 +- windows/debuguty/view1mb.cpp | 324 +- windows/debuguty/view1mb.h | 66 +- windows/debuguty/viewasm.cpp | 364 +- windows/debuguty/viewasm.h | 70 +- windows/debuguty/viewer.cpp | 118 +- windows/debuguty/viewer.h | 136 +- windows/debuguty/viewitem.cpp | 282 +- windows/debuguty/viewitem.h | 84 +- windows/debuguty/viewmem.cpp | 420 +- windows/debuguty/viewmem.h | 40 +- windows/debuguty/viewreg.cpp | 406 +- windows/debuguty/viewreg.h | 58 +- windows/debuguty/viewseg.cpp | 334 +- windows/debuguty/viewseg.h | 68 +- windows/debuguty/viewsnd.cpp | 376 +- windows/debuguty/viewsnd.h | 58 +- windows/dialog/c_combodata.cpp | 272 +- windows/dialog/c_combodata.h | 86 +- windows/dialog/c_dipsw.cpp | 110 +- windows/dialog/c_dipsw.h | 36 +- windows/dialog/c_midi.cpp | 260 +- windows/dialog/c_midi.h | 76 +- windows/dialog/c_slidervalue.cpp | 96 +- windows/dialog/c_slidervalue.h | 66 +- windows/dialog/d_about.cpp | 282 +- windows/dialog/d_bmp.cpp | 220 +- windows/dialog/d_cfgload.cpp | 176 +- windows/dialog/d_cfgsave.cpp | 226 +- windows/dialog/d_clnd.cpp | 434 +- windows/dialog/d_config.cpp | 66 +- windows/dialog/d_disk.cpp | 264 +- windows/dialog/d_font.cpp | 4 +- windows/dialog/d_hostdrv.cpp | 58 +- windows/dialog/d_ide.cpp | 642 +- windows/dialog/d_mpu98.cpp | 1630 +- windows/dialog/d_network.cpp | 1054 +- windows/dialog/d_pci.cpp | 396 +- windows/dialog/d_screen.cpp | 1528 +- windows/dialog/d_serial.cpp | 1708 +- windows/dialog/d_sound.cpp | 400 +- windows/dialog/d_soundlog.cpp | 266 +- windows/dialog/d_txt.cpp | 412 +- windows/dialog/d_wab.cpp | 768 +- windows/dialog/dialog.h | 170 +- windows/dialog/np2class.cpp | 372 +- windows/dialog/np2class.h | 50 +- windows/dosio.cpp | 1158 +- windows/dosio.h | 286 +- windows/ext/c86ctl/c86ctl.h | 370 +- windows/ext/c86ctl/c86ctlif.cpp | 622 +- windows/ext/c86ctl/c86ctlif.h | 118 +- windows/ext/c86ctl/cbus_boardtype.h | 556 +- windows/ext/externalchip.h | 150 +- windows/ext/externalchipmanager.cpp | 412 +- windows/ext/externalchipmanager.h | 98 +- windows/ext/externalopl3.cpp | 210 +- windows/ext/externalopl3.h | 58 +- windows/ext/externalopm.cpp | 270 +- windows/ext/externalopm.h | 62 +- windows/ext/externalopna.cpp | 342 +- windows/ext/externalopna.h | 130 +- windows/ext/externalpsg.cpp | 204 +- windows/ext/externalpsg.h | 58 +- windows/ext/mt32snd.cpp | 418 +- windows/ext/mt32snd.h | 168 +- windows/ext/opna.cpp | 1694 +- windows/ext/romeo/juliet.cpp | 678 +- windows/ext/romeo/juliet.h | 178 +- windows/ext/romeo/romeo.h | 102 +- windows/ext/scci2/readme.txt | 2 +- windows/ext/scci2/scci2.h | 82 +- windows/ext/scci2/scci2if.cpp | 78 +- windows/ext/scci2/scci2if.h | 14 +- windows/fontmng.cpp | 628 +- windows/fontmng.h | 70 +- windows/ini.cpp | 1776 +- windows/ini.h | 66 +- windows/joymng.cpp | 226 +- windows/joymng.h | 36 +- windows/menu.cpp | 1082 +- windows/menu.h | 38 +- windows/misc/DlgProc.cpp | 450 +- windows/misc/DlgProc.h | 472 +- windows/misc/PropProc.cpp | 514 +- windows/misc/PropProc.h | 118 +- windows/misc/WndBase.h | 1058 +- windows/misc/WndProc.cpp | 1024 +- windows/misc/WndProc.h | 222 +- windows/misc/extrom.cpp | 478 +- windows/misc/extrom.h | 58 +- windows/misc/guard.h | 56 +- windows/misc/threadbase.cpp | 206 +- windows/misc/threadbase.h | 104 +- windows/misc/tickcounter.cpp | 412 +- windows/misc/tickcounter.h | 56 +- windows/misc/trace.cpp | 966 +- windows/misc/trace.h | 78 +- windows/misc/tstring.cpp | 174 +- windows/misc/tstring.h | 40 +- windows/misc/vc6macros.h | 126 +- windows/mousemng.cpp | 1144 +- windows/mousemng.h | 138 +- windows/np2.cpp | 9426 +++++----- windows/np2.h | 410 +- windows/np2arg.cpp | 244 +- windows/np2arg.h | 224 +- windows/np2mt.h | 22 +- windows/oemtext.cpp | 516 +- windows/oemtext.h | 64 +- windows/readme.txt | 566 +- windows/recvideo.cpp | 780 +- windows/recvideo.h | 182 +- windows/resource.h | 1740 +- windows/resources/resource.cpp | 24 +- windows/scrnmng.cpp | 62 +- windows/scrnmng.h | 324 +- windows/scrnmng_d3d.cpp | 98 +- windows/scrnmng_d3d.h | 108 +- windows/scrnmng_dd.cpp | 46 +- windows/scrnmng_dd.h | 106 +- windows/soundmng.cpp | 1252 +- windows/soundmng.h | 248 +- windows/soundmng/asio/asiodriverlist.cpp | 242 +- windows/soundmng/asio/asiodriverlist.h | 66 +- windows/soundmng/asio/asiosdk.h | 314 +- windows/soundmng/sdasio.cpp | 704 +- windows/soundmng/sdasio.h | 84 +- windows/soundmng/sdbase.h | 356 +- windows/soundmng/sddsound3.cpp | 1512 +- windows/soundmng/sddsound3.h | 150 +- windows/soundmng/sdwasapi.cpp | 872 +- windows/soundmng/sdwasapi.h | 120 +- windows/subwnd/dclock.cpp | 1338 +- windows/subwnd/dclock.h | 172 +- windows/subwnd/dd2.cpp | 40 +- windows/subwnd/dd2.h | 26 +- windows/subwnd/kdispwnd.cpp | 838 +- windows/subwnd/kdispwnd.h | 136 +- windows/subwnd/mdbgwnd.cpp | 544 +- windows/subwnd/mdbgwnd.h | 136 +- windows/subwnd/skbdwnd.cpp | 62 +- windows/subwnd/skbdwnd.h | 16 +- windows/subwnd/subwnd.cpp | 72 +- windows/subwnd/subwnd.h | 60 +- windows/subwnd/toolwnd.cpp | 26 +- windows/subwnd/toolwnd.h | 212 +- windows/sysmng.cpp | 654 +- windows/sysmng.h | 168 +- windows/targetver.h | 50 +- windows/taskmng.cpp | 30 +- windows/taskmng.h | 22 +- windows/timemng.cpp | 20 +- windows/timemng.h | 52 +- windows/winkbd.cpp | 546 +- windows/winkbd.h | 30 +- windows/winloc.cpp | 1830 +- windows/winloc.h | 112 +- windows/x64/pccore.inc | 16 +- windows/x64/vram.inc | 50 +- windows/x64/vs2019/x64.xml | 312 +- windows/x86/cputype.h | 22 +- windows/x86/cputype.x86 | 50 +- windows/x86/makegrph.x86 | 510 +- windows/x86/np2asm.inc | 26 +- windows/x86/opngeng.x86 | 1004 +- windows/x86/parts.x86 | 278 +- windows/x86/pccore.inc | 16 +- windows/x86/vram.inc | 50 +- windows/x86/vs2019/x86.xml | 360 +- 868 files changed, 257464 insertions(+), 257464 deletions(-) mode change 100755 => 100644 accessories/bin2txt.c mode change 100755 => 100644 accessories/lzxpack.c mode change 100755 => 100644 accessories/textout.c mode change 100755 => 100644 accessories/textout.h mode change 100755 => 100644 bios/bios09.c mode change 100755 => 100644 bios/bios0c.c mode change 100755 => 100644 bios/bios12.c mode change 100755 => 100644 bios/bios13.c mode change 100755 => 100644 bios/bios19.c mode change 100755 => 100644 bios/bios1a.c mode change 100755 => 100644 bios/bios1b.c mode change 100755 => 100644 bios/bios1c.c mode change 100755 => 100644 bios/biosmem.h mode change 100755 => 100644 bios/fdfmt.h mode change 100755 => 100644 bios/rsbios.h mode change 100755 => 100644 bios/sxsibios.c mode change 100755 => 100644 bios/sxsibios.h mode change 100755 => 100644 calendar.c mode change 100755 => 100644 calendar.h mode change 100755 => 100644 cbus/amd98.c mode change 100755 => 100644 cbus/amd98.h mode change 100755 => 100644 cbus/atapicmd.h mode change 100755 => 100644 cbus/board118.c mode change 100755 => 100644 cbus/board118.h mode change 100755 => 100644 cbus/board14.c mode change 100755 => 100644 cbus/board14.h mode change 100755 => 100644 cbus/board26k.c mode change 100755 => 100644 cbus/board26k.h mode change 100755 => 100644 cbus/board86.c mode change 100755 => 100644 cbus/board86.h mode change 100755 => 100644 cbus/boardlol.c mode change 100755 => 100644 cbus/boardmo.c mode change 100755 => 100644 cbus/boardpx.c mode change 100755 => 100644 cbus/boardpx.h mode change 100755 => 100644 cbus/boardsb16.c mode change 100755 => 100644 cbus/boardso.c mode change 100755 => 100644 cbus/boardso.h mode change 100755 => 100644 cbus/boardspb.c mode change 100755 => 100644 cbus/boardspb.h mode change 100755 => 100644 cbus/boardx2.c mode change 100755 => 100644 cbus/boardx2.h mode change 100755 => 100644 cbus/cbuscore.c mode change 100755 => 100644 cbus/cbuscore.h mode change 100755 => 100644 cbus/cs4231io.c mode change 100755 => 100644 cbus/cs4231io.h mode change 100755 => 100644 cbus/ct1741io.c mode change 100755 => 100644 cbus/ct1741io.h mode change 100755 => 100644 cbus/ct1745io.c mode change 100755 => 100644 cbus/ct1745io.h mode change 100755 => 100644 cbus/gpibio.c mode change 100755 => 100644 cbus/gpibio.h mode change 100755 => 100644 cbus/ideio.c mode change 100755 => 100644 cbus/ideio.h mode change 100755 => 100644 cbus/mpu98ii.c mode change 100755 => 100644 cbus/mpu98ii.h mode change 100755 => 100644 cbus/pc9861k.c mode change 100755 => 100644 cbus/pc9861k.h mode change 100755 => 100644 cbus/pcm86io.c mode change 100755 => 100644 cbus/pcm86io.h mode change 100755 => 100644 cbus/sasiio.c mode change 100755 => 100644 cbus/sasiio.h mode change 100755 => 100644 cbus/scsicmd.c mode change 100755 => 100644 cbus/scsicmd.h mode change 100755 => 100644 cbus/scsiio.c mode change 100755 => 100644 cbus/scsiio.h mode change 100755 => 100644 codecnv/codecnv.h mode change 100755 => 100644 codecnv/eucsjis.c mode change 100755 => 100644 codecnv/eucucs2.c mode change 100755 => 100644 codecnv/sjiseuc.c mode change 100755 => 100644 codecnv/sjisucs2.c mode change 100755 => 100644 codecnv/tcswap16.c mode change 100755 => 100644 codecnv/tcswap32.c mode change 100755 => 100644 codecnv/textcnv.c mode change 100755 => 100644 codecnv/textcnv.h mode change 100755 => 100644 codecnv/ucs2sjis.c mode change 100755 => 100644 codecnv/ucs2ucs4.c mode change 100755 => 100644 codecnv/ucs2utf8.c mode change 100755 => 100644 codecnv/utf8ucs4.c mode change 100755 => 100644 common.h mode change 100755 => 100644 common/_memory.c mode change 100755 => 100644 common/_memory.h mode change 100755 => 100644 common/bmpdata.c mode change 100755 => 100644 common/bmpdata.h mode change 100755 => 100644 common/lstarray.c mode change 100755 => 100644 common/lstarray.h mode change 100755 => 100644 common/milstr.c mode change 100755 => 100644 common/milstr.h mode change 100755 => 100644 common/mimpidef.c mode change 100755 => 100644 common/mimpidef.h mode change 100755 => 100644 common/parts.c mode change 100755 => 100644 common/parts.h mode change 100755 => 100644 common/profile.c mode change 100755 => 100644 common/profile.h mode change 100755 => 100644 common/rect.c mode change 100755 => 100644 common/rect.h mode change 100755 => 100644 common/resize.c mode change 100755 => 100644 common/resize.h mode change 100755 => 100644 common/strres.c mode change 100755 => 100644 common/strres.h mode change 100755 => 100644 common/textfile.c mode change 100755 => 100644 common/textfile.h mode change 100755 => 100644 common/wavefile.c mode change 100755 => 100644 common/wavefile.h mode change 100755 => 100644 debugsub.c mode change 100755 => 100644 debugsub.h mode change 100755 => 100644 debugsub386.c mode change 100755 => 100644 diskimage/cd/cdd_ccd.c mode change 100755 => 100644 diskimage/cd/cdd_ccd.h mode change 100755 => 100644 diskimage/cd/cdd_cue.c mode change 100755 => 100644 diskimage/cd/cdd_cue.h mode change 100755 => 100644 diskimage/cd/cdd_iso.c mode change 100755 => 100644 diskimage/cd/cdd_iso.h mode change 100755 => 100644 diskimage/cd/cdd_mds.c mode change 100755 => 100644 diskimage/cd/cdd_mds.h mode change 100755 => 100644 diskimage/cd/cdd_nrg.c mode change 100755 => 100644 diskimage/cd/cdd_nrg.h mode change 100755 => 100644 diskimage/cd/cdd_real.c mode change 100755 => 100644 diskimage/cddfile.c mode change 100755 => 100644 diskimage/cddfile.h mode change 100755 => 100644 diskimage/fd/fdd_bkdsk.c mode change 100755 => 100644 diskimage/fd/fdd_bkdsk.h mode change 100755 => 100644 diskimage/fd/fdd_d88.c mode change 100755 => 100644 diskimage/fd/fdd_d88.h mode change 100755 => 100644 diskimage/fd/fdd_dcp.c mode change 100755 => 100644 diskimage/fd/fdd_dcp.h mode change 100755 => 100644 diskimage/fd/fdd_head_d88.h mode change 100755 => 100644 diskimage/fd/fdd_head_dcp.h mode change 100755 => 100644 diskimage/fd/fdd_head_nfd.h mode change 100755 => 100644 diskimage/fd/fdd_head_vfdd.h mode change 100755 => 100644 diskimage/fd/fdd_nfd.c mode change 100755 => 100644 diskimage/fd/fdd_nfd.h mode change 100755 => 100644 diskimage/fd/fdd_vfdd.c mode change 100755 => 100644 diskimage/fd/fdd_vfdd.h mode change 100755 => 100644 diskimage/fd/fdd_xdf.c mode change 100755 => 100644 diskimage/fd/fdd_xdf.h mode change 100755 => 100644 diskimage/fddfile.c mode change 100755 => 100644 diskimage/fddfile.h mode change 100755 => 100644 diskimage/img_common.h mode change 100755 => 100644 diskimage/img_strres.c mode change 100755 => 100644 diskimage/img_strres.h mode change 100755 => 100644 diskimage/win9x/img_dosio.c mode change 100755 => 100644 diskimage/win9x/img_dosio.h mode change 100755 => 100644 embed/menu/dlgabout.c mode change 100755 => 100644 embed/menu/dlgabout.h mode change 100755 => 100644 embed/menu/dlgcfg.h mode change 100755 => 100644 embed/menu/dlgscr.c mode change 100755 => 100644 embed/menu/dlgscr.h mode change 100755 => 100644 embed/menu/dlgwab.c mode change 100755 => 100644 embed/menu/dlgwab.h mode change 100755 => 100644 embed/menu/filesel.h mode change 100755 => 100644 embed/menu/menustr.c mode change 100755 => 100644 embed/menu/menustr.h mode change 100755 => 100644 embed/menubase/menubase.h mode change 100755 => 100644 embed/menubase/menudeco.inc mode change 100755 => 100644 embed/menubase/menudlg.c mode change 100755 => 100644 embed/menubase/menudlg.h mode change 100755 => 100644 embed/menubase/menuicon.c mode change 100755 => 100644 embed/menubase/menuicon.h mode change 100755 => 100644 embed/menubase/menumbox.c mode change 100755 => 100644 embed/menubase/menumbox.h mode change 100755 => 100644 embed/menubase/menures.c mode change 100755 => 100644 embed/menubase/menures.h mode change 100755 => 100644 embed/menubase/menusys.c mode change 100755 => 100644 embed/menubase/menusys.h mode change 100755 => 100644 embed/menubase/menuvram.c mode change 100755 => 100644 embed/menubase/menuvram.h mode change 100755 => 100644 embed/readme.txt mode change 100755 => 100644 embed/vramhdl.c mode change 100755 => 100644 embed/vramhdl.h mode change 100755 => 100644 embed/vrammix.c mode change 100755 => 100644 embed/vrammix.h mode change 100755 => 100644 fdd/d88head.h mode change 100755 => 100644 fdd/diskdrv.c mode change 100755 => 100644 fdd/diskdrv.h mode change 100755 => 100644 fdd/fdd_mtr.h mode change 100755 => 100644 fdd/hdd_vhd.h mode change 100755 => 100644 fdd/hdd_vpc.h mode change 100755 => 100644 fdd/newdisk.c mode change 100755 => 100644 fdd/newdisk.h mode change 100755 => 100644 fdd/sxsi.c mode change 100755 => 100644 fdd/sxsi.h mode change 100755 => 100644 fdd/sxsicd.c mode change 100755 => 100644 fdd/sxsicd.h mode change 100755 => 100644 fdd/sxsihdd.c mode change 100755 => 100644 fdd/sxsihdd.h mode change 100755 => 100644 fdd/sxsihdd_nvl.c mode change 100755 => 100644 font/font.h mode change 100755 => 100644 font/fontdata.c mode change 100755 => 100644 font/fontdata.h mode change 100755 => 100644 font/fontfm7.c mode change 100755 => 100644 font/fontmake.c mode change 100755 => 100644 font/fontmake.h mode change 100755 => 100644 font/fontpc88.c mode change 100755 => 100644 font/fontpc98.c mode change 100755 => 100644 font/fontv98.c mode change 100755 => 100644 font/fontx1.c mode change 100755 => 100644 font/fontx68k.c mode change 100755 => 100644 font/readme.txt mode change 100755 => 100644 generic/cmjasts.c mode change 100755 => 100644 generic/cmjasts.h mode change 100755 => 100644 generic/cmndraw.c mode change 100755 => 100644 generic/cmndraw.h mode change 100755 => 100644 generic/cmver.c mode change 100755 => 100644 generic/cmver.h mode change 100755 => 100644 generic/dipswbmp.c mode change 100755 => 100644 generic/dipswbmp.h mode change 100755 => 100644 generic/hostdrv.c mode change 100755 => 100644 generic/hostdrv.h mode change 100755 => 100644 generic/hostdrvs.c mode change 100755 => 100644 generic/hostdrvs.h mode change 100755 => 100644 generic/keydisp.c mode change 100755 => 100644 generic/keydisp.h mode change 100755 => 100644 generic/memdbg32.c mode change 100755 => 100644 generic/memdbg32.h mode change 100755 => 100644 generic/np2info.c mode change 100755 => 100644 generic/np2info.h mode change 100755 => 100644 generic/readme.txt mode change 100755 => 100644 generic/softkbd.c mode change 100755 => 100644 generic/softkbd.h mode change 100755 => 100644 generic/unasm.c mode change 100755 => 100644 generic/unasm.h mode change 100755 => 100644 i286c/cpumem.h mode change 100755 => 100644 i286c/i286c.h mode change 100755 => 100644 i286c/i286c.mcr mode change 100755 => 100644 i286c/i286c_0f.c mode change 100755 => 100644 i286c/i286c_8x.c mode change 100755 => 100644 i286c/i286c_ea.c mode change 100755 => 100644 i286c/i286c_f6.c mode change 100755 => 100644 i286c/i286c_fe.c mode change 100755 => 100644 i286c/i286c_rp.c mode change 100755 => 100644 i286c/i286c_sf.c mode change 100755 => 100644 i286c/i286c_sf.mcr mode change 100755 => 100644 i286x/cpucore.h mode change 100755 => 100644 i286x/cpucore.inc mode change 100755 => 100644 i286x/cpumem.h mode change 100755 => 100644 i286x/i286x.cpp mode change 100755 => 100644 i286x/i286x.h mode change 100755 => 100644 i286x/i286xadr.cpp mode change 100755 => 100644 i286x/i286xadr.h mode change 100755 => 100644 i286x/i286xcts.cpp mode change 100755 => 100644 i286x/i286xcts.h mode change 100755 => 100644 i286x/i286xrep.h mode change 100755 => 100644 i286x/i286xs.h mode change 100755 => 100644 i386c/cpucore.c mode change 100755 => 100644 i386c/cpucore.h mode change 100755 => 100644 i386c/cpumem.c mode change 100755 => 100644 i386c/cpumem.h mode change 100755 => 100644 i386c/ia32/cpu.c mode change 100755 => 100644 i386c/ia32/cpu.h mode change 100755 => 100644 i386c/ia32/cpu_io.c mode change 100755 => 100644 i386c/ia32/cpu_mem.c mode change 100755 => 100644 i386c/ia32/cpu_mem.h mode change 100755 => 100644 i386c/ia32/cpu_mem.mcr mode change 100755 => 100644 i386c/ia32/ctrlxfer.c mode change 100755 => 100644 i386c/ia32/ctrlxfer.h mode change 100755 => 100644 i386c/ia32/debug.c mode change 100755 => 100644 i386c/ia32/disasm.c mode change 100755 => 100644 i386c/ia32/exception.c mode change 100755 => 100644 i386c/ia32/exception.h mode change 100755 => 100644 i386c/ia32/groups.c mode change 100755 => 100644 i386c/ia32/groups.h mode change 100755 => 100644 i386c/ia32/ia32.c mode change 100755 => 100644 i386c/ia32/ia32.mcr mode change 100755 => 100644 i386c/ia32/ia32weak.txt mode change 100755 => 100644 i386c/ia32/ia32xc.mcr mode change 100755 => 100644 i386c/ia32/ia32xc_msc.mcr mode change 100755 => 100644 i386c/ia32/inst_table.c mode change 100755 => 100644 i386c/ia32/inst_table.h mode change 100755 => 100644 i386c/ia32/instructions/arith.mcr mode change 100755 => 100644 i386c/ia32/instructions/bin_arith.c mode change 100755 => 100644 i386c/ia32/instructions/bin_arith.h mode change 100755 => 100644 i386c/ia32/instructions/bit_byte.c mode change 100755 => 100644 i386c/ia32/instructions/bit_byte.h mode change 100755 => 100644 i386c/ia32/instructions/ctrl_trans.c mode change 100755 => 100644 i386c/ia32/instructions/ctrl_trans.h mode change 100755 => 100644 i386c/ia32/instructions/data_trans.c mode change 100755 => 100644 i386c/ia32/instructions/data_trans.h mode change 100755 => 100644 i386c/ia32/instructions/dec_arith.c mode change 100755 => 100644 i386c/ia32/instructions/dec_arith.h mode change 100755 => 100644 i386c/ia32/instructions/flag_ctrl.c mode change 100755 => 100644 i386c/ia32/instructions/flag_ctrl.h mode change 100755 => 100644 i386c/ia32/instructions/fpu.c mode change 100755 => 100644 i386c/ia32/instructions/fpu/fp.h mode change 100755 => 100644 i386c/ia32/instructions/fpu/fpdummy.c mode change 100755 => 100644 i386c/ia32/instructions/fpu/fpemul.c mode change 100755 => 100644 i386c/ia32/instructions/fpu/fpemul_dosbox.c mode change 100755 => 100644 i386c/ia32/instructions/fpu/fpemul_dosbox2.c mode change 100755 => 100644 i386c/ia32/instructions/fpu/fpemul_softfloat.c mode change 100755 => 100644 i386c/ia32/instructions/fpu/fpumem.h mode change 100755 => 100644 i386c/ia32/instructions/logic_arith.c mode change 100755 => 100644 i386c/ia32/instructions/logic_arith.h mode change 100755 => 100644 i386c/ia32/instructions/misc_inst.c mode change 100755 => 100644 i386c/ia32/instructions/misc_inst.h mode change 100755 => 100644 i386c/ia32/instructions/mmx/3dnow.c mode change 100755 => 100644 i386c/ia32/instructions/mmx/3dnow.h mode change 100755 => 100644 i386c/ia32/instructions/mmx/mmx.c mode change 100755 => 100644 i386c/ia32/instructions/mmx/mmx.h mode change 100755 => 100644 i386c/ia32/instructions/mmx/mmx2.txt mode change 100755 => 100644 i386c/ia32/instructions/seg_reg.c mode change 100755 => 100644 i386c/ia32/instructions/seg_reg.h mode change 100755 => 100644 i386c/ia32/instructions/shift_rotate.c mode change 100755 => 100644 i386c/ia32/instructions/shift_rotate.h mode change 100755 => 100644 i386c/ia32/instructions/shift_rotate.mcr mode change 100755 => 100644 i386c/ia32/instructions/shift_rotatexc.mcr mode change 100755 => 100644 i386c/ia32/instructions/shift_rotatexc_msc.mcr mode change 100755 => 100644 i386c/ia32/instructions/sse/sse.c mode change 100755 => 100644 i386c/ia32/instructions/sse/sse.h mode change 100755 => 100644 i386c/ia32/instructions/sse2/sse2.h mode change 100755 => 100644 i386c/ia32/instructions/sse3/sse3.c mode change 100755 => 100644 i386c/ia32/instructions/sse3/sse3.h mode change 100755 => 100644 i386c/ia32/instructions/string_inst.c mode change 100755 => 100644 i386c/ia32/instructions/string_inst.h mode change 100755 => 100644 i386c/ia32/instructions/system_inst.c mode change 100755 => 100644 i386c/ia32/instructions/system_inst.h mode change 100755 => 100644 i386c/ia32/interface.c mode change 100755 => 100644 i386c/ia32/interface.h mode change 100755 => 100644 i386c/ia32/paging.c mode change 100755 => 100644 i386c/ia32/paging.h mode change 100755 => 100644 i386c/ia32/resolve.c mode change 100755 => 100644 i386c/ia32/resolve.h mode change 100755 => 100644 i386c/ia32/segments.c mode change 100755 => 100644 i386c/ia32/segments.h mode change 100755 => 100644 i386c/ia32/task.c mode change 100755 => 100644 i386c/ia32/task.h mode change 100755 => 100644 io/artic.c mode change 100755 => 100644 io/artic.h mode change 100755 => 100644 io/cgrom.c mode change 100755 => 100644 io/cgrom.h mode change 100755 => 100644 io/cpuio.c mode change 100755 => 100644 io/cpuio.h mode change 100755 => 100644 io/crtc.c mode change 100755 => 100644 io/crtc.h mode change 100755 => 100644 io/dipsw.c mode change 100755 => 100644 io/dipsw.h mode change 100755 => 100644 io/egc.c mode change 100755 => 100644 io/egc.h mode change 100755 => 100644 io/emsio.c mode change 100755 => 100644 io/emsio.h mode change 100755 => 100644 io/epsonio.c mode change 100755 => 100644 io/epsonio.h mode change 100755 => 100644 io/fdc.c mode change 100755 => 100644 io/fdc.h mode change 100755 => 100644 io/fdd320.c mode change 100755 => 100644 io/fdd320.h mode change 100755 => 100644 io/gdc.c mode change 100755 => 100644 io/gdc_cmd.h mode change 100755 => 100644 io/gdc_pset.c mode change 100755 => 100644 io/gdc_pset.h mode change 100755 => 100644 io/gdc_sub.c mode change 100755 => 100644 io/gdc_sub.h mode change 100755 => 100644 io/iocore.c mode change 100755 => 100644 io/iocore.h mode change 100755 => 100644 io/lsidef.h mode change 100755 => 100644 io/mouseif.c mode change 100755 => 100644 io/mouseif.h mode change 100755 => 100644 io/necio.c mode change 100755 => 100644 io/necio.h mode change 100755 => 100644 io/nmiio.c mode change 100755 => 100644 io/nmiio.h mode change 100755 => 100644 io/np2sysp.h mode change 100755 => 100644 io/pci/98graphbridge.c mode change 100755 => 100644 io/pci/98graphbridge.h mode change 100755 => 100644 io/pci/cbusbridge.c mode change 100755 => 100644 io/pci/cbusbridge.h mode change 100755 => 100644 io/pcidev.c mode change 100755 => 100644 io/pcidev.h mode change 100755 => 100644 io/pegc.c mode change 100755 => 100644 io/pic.c mode change 100755 => 100644 io/pic.h mode change 100755 => 100644 io/pit.c mode change 100755 => 100644 io/pit.h mode change 100755 => 100644 io/printif.c mode change 100755 => 100644 io/printif.h mode change 100755 => 100644 io/serial.h mode change 100755 => 100644 io/sysport.c mode change 100755 => 100644 io/sysport.h mode change 100755 => 100644 io/upd4990.c mode change 100755 => 100644 keystat.c mode change 100755 => 100644 lio/gcircle.c mode change 100755 => 100644 lio/gline.c mode change 100755 => 100644 lio/gpset.c mode change 100755 => 100644 lio/gput1.c mode change 100755 => 100644 lio/gscreen.c mode change 100755 => 100644 lio/lio.c mode change 100755 => 100644 lio/lio.h mode change 100755 => 100644 mem/dmav30.c mode change 100755 => 100644 mem/dmav30.h mode change 100755 => 100644 mem/dmax86.c mode change 100755 => 100644 mem/dmax86.h mode change 100755 => 100644 mem/memegc.c mode change 100755 => 100644 mem/memegc.h mode change 100755 => 100644 mem/memems.c mode change 100755 => 100644 mem/memems.h mode change 100755 => 100644 mem/memepp.c mode change 100755 => 100644 mem/memepp.h mode change 100755 => 100644 mem/memtram.c mode change 100755 => 100644 mem/memtram.h mode change 100755 => 100644 mem/memvga.c mode change 100755 => 100644 mem/memvga.h mode change 100755 => 100644 mem/memvram.c mode change 100755 => 100644 mem/memvram.h mode change 100755 => 100644 misc/test_codecnv.c mode change 100755 => 100644 misc/test_milstr.c mode change 100755 => 100644 network/lgy98.c mode change 100755 => 100644 network/lgy98.h mode change 100755 => 100644 network/lgy98dev.h mode change 100755 => 100644 network/net.c mode change 100755 => 100644 network/net.h mode change 100755 => 100644 network/readme.txt mode change 100755 => 100644 nevent.c mode change 100755 => 100644 nevent.h mode change 100755 => 100644 np2ver.h mode change 100755 => 100644 pccore.h mode change 100755 => 100644 readme.txt mode change 100755 => 100644 sdl/commng.c mode change 100755 => 100644 sdl/fontmng.h mode change 100755 => 100644 sdl/ini.c mode change 100755 => 100644 sdl/inputmng.h mode change 100755 => 100644 sdl/libretro/compiler.h mode change 100755 => 100644 sdl/libretro/libretro.c mode change 100755 => 100644 sdl/np2.c mode change 100755 => 100644 sdl/oemtext.h mode change 100755 => 100644 sdl/sysmenu.h mode change 100755 => 100644 sdl/sysmng.h mode change 100755 => 100644 sdl/taskmng.h mode change 100755 => 100644 sdl/timemng.h mode change 100755 => 100644 sdl/trace.c mode change 100755 => 100644 sdl/trace.h mode change 100755 => 100644 sdl/windows/main.c mode change 100755 => 100644 sound/adpcm.h mode change 100755 => 100644 sound/adpcmc.c mode change 100755 => 100644 sound/adpcmg.c mode change 100755 => 100644 sound/beep.h mode change 100755 => 100644 sound/beepc.c mode change 100755 => 100644 sound/beepg.c mode change 100755 => 100644 sound/cs4231.h mode change 100755 => 100644 sound/cs4231c.c mode change 100755 => 100644 sound/cs4231g.c mode change 100755 => 100644 sound/fmboard.c mode change 100755 => 100644 sound/fmboard.h mode change 100755 => 100644 sound/fmgen/fmgen_diag.h mode change 100755 => 100644 sound/fmgen/fmgen_file.cpp mode change 100755 => 100644 sound/fmgen/fmgen_file.h mode change 100755 => 100644 sound/fmgen/fmgen_fmgen.cpp mode change 100755 => 100644 sound/fmgen/fmgen_fmgen.h mode change 100755 => 100644 sound/fmgen/fmgen_fmgeninl.h mode change 100755 => 100644 sound/fmgen/fmgen_fmtimer.cpp mode change 100755 => 100644 sound/fmgen/fmgen_fmtimer.h mode change 100755 => 100644 sound/fmgen/fmgen_headers.h mode change 100755 => 100644 sound/fmgen/fmgen_misc.h mode change 100755 => 100644 sound/fmgen/fmgen_opm.cpp mode change 100755 => 100644 sound/fmgen/fmgen_opm.h mode change 100755 => 100644 sound/fmgen/fmgen_opna.h mode change 100755 => 100644 sound/fmgen/fmgen_psg.cpp mode change 100755 => 100644 sound/fmgen/fmgen_psg.h mode change 100755 => 100644 sound/fmgen/fmgen_readme.txt mode change 100755 => 100644 sound/getsnd/getmp3.c mode change 100755 => 100644 sound/getsnd/getogg.c mode change 100755 => 100644 sound/getsnd/getsmix.c mode change 100755 => 100644 sound/getsnd/getsnd.c mode change 100755 => 100644 sound/getsnd/getsnd.h mode change 100755 => 100644 sound/getsnd/getsndmn.mcr mode change 100755 => 100644 sound/getsnd/getsndst.mcr mode change 100755 => 100644 sound/getsnd/getwave.c mode change 100755 => 100644 sound/opl3.c mode change 100755 => 100644 sound/opl3.h mode change 100755 => 100644 sound/oplgen.h mode change 100755 => 100644 sound/oplgencfg.h mode change 100755 => 100644 sound/oplgeng.c mode change 100755 => 100644 sound/opngen.h mode change 100755 => 100644 sound/opngenc.c mode change 100755 => 100644 sound/opngencfg.h mode change 100755 => 100644 sound/opngeng.c mode change 100755 => 100644 sound/opntimer.c mode change 100755 => 100644 sound/opntimer.h mode change 100755 => 100644 sound/pcm86.h mode change 100755 => 100644 sound/pcm86c.c mode change 100755 => 100644 sound/pcm86g.c mode change 100755 => 100644 sound/pcmmix.c mode change 100755 => 100644 sound/pcmmix.h mode change 100755 => 100644 sound/psggen.h mode change 100755 => 100644 sound/psggenc.c mode change 100755 => 100644 sound/psggeng.c mode change 100755 => 100644 sound/rhythm.h mode change 100755 => 100644 sound/rhythmc.c mode change 100755 => 100644 sound/sndcsec.c mode change 100755 => 100644 sound/sndcsec.h mode change 100755 => 100644 sound/sound.c mode change 100755 => 100644 sound/sound.h mode change 100755 => 100644 sound/tms3631.h mode change 100755 => 100644 sound/tms3631c.c mode change 100755 => 100644 sound/tms3631g.c mode change 100755 => 100644 sound/vermouth/midimod.c mode change 100755 => 100644 sound/vermouth/midimod.h mode change 100755 => 100644 sound/vermouth/midinst.c mode change 100755 => 100644 sound/vermouth/midinst.h mode change 100755 => 100644 sound/vermouth/midiout.c mode change 100755 => 100644 sound/vermouth/midiout.h mode change 100755 => 100644 sound/vermouth/midtable.c mode change 100755 => 100644 sound/vermouth/midtable.h mode change 100755 => 100644 sound/vermouth/midvoice.c mode change 100755 => 100644 sound/vermouth/midvoice.h mode change 100755 => 100644 sound/vermouth/vermouth.h mode change 100755 => 100644 statsave.c mode change 100755 => 100644 statsave.h mode change 100755 => 100644 timing.c mode change 100755 => 100644 timing.h mode change 100755 => 100644 trap/inttrap.c mode change 100755 => 100644 trap/inttrap.h mode change 100755 => 100644 trap/steptrap.c mode change 100755 => 100644 trap/steptrap.h mode change 100755 => 100644 update.txt mode change 100755 => 100644 vram/dispsync.c mode change 100755 => 100644 vram/dispsync.h mode change 100755 => 100644 vram/makegrex.c mode change 100755 => 100644 vram/makegrex.h mode change 100755 => 100644 vram/makegrph.c mode change 100755 => 100644 vram/makegrph.h mode change 100755 => 100644 vram/makegrph.mcr mode change 100755 => 100644 vram/maketext.c mode change 100755 => 100644 vram/maketext.h mode change 100755 => 100644 vram/maketgrp.c mode change 100755 => 100644 vram/maketgrp.h mode change 100755 => 100644 vram/palettes.c mode change 100755 => 100644 vram/palettes.h mode change 100755 => 100644 vram/scrndraw.h mode change 100755 => 100644 vram/scrnsave.c mode change 100755 => 100644 vram/scrnsave.h mode change 100755 => 100644 vram/sdraw.c mode change 100755 => 100644 vram/sdraw.h mode change 100755 => 100644 vram/sdraw.mcr mode change 100755 => 100644 vram/sdrawex.mcr mode change 100755 => 100644 vram/sdrawq16.c mode change 100755 => 100644 vram/vram.c mode change 100755 => 100644 vram/vram.h mode change 100755 => 100644 wab/cirrus_vga.c mode change 100755 => 100644 wab/cirrus_vga.h mode change 100755 => 100644 wab/cirrus_vga_extern.h mode change 100755 => 100644 wab/cirrus_vga_rop.h mode change 100755 => 100644 wab/cirrus_vga_rop2.h mode change 100755 => 100644 wab/vga_int.h mode change 100755 => 100644 wab/wab.c mode change 100755 => 100644 wab/wab.h mode change 100755 => 100644 wab/wab_rly.h mode change 100755 => 100644 wab/wabbmpsave.h mode change 100755 => 100644 windows/commng.h mode change 100755 => 100644 windows/commng/cmmidiin32.cpp mode change 100755 => 100644 windows/commng/cmmidiin32.h mode change 100755 => 100644 windows/commng/cmmidiout.h mode change 100755 => 100644 windows/commng/cmmidiout32.cpp mode change 100755 => 100644 windows/commng/cmmidiout32.h mode change 100755 => 100644 windows/commng/cmmidioutmt32sound.cpp mode change 100755 => 100644 windows/commng/cmmidioutmt32sound.h mode change 100755 => 100644 windows/commng/cmmidioutvermouth.cpp mode change 100755 => 100644 windows/commng/cmmidioutvermouth.h mode change 100755 => 100644 windows/commng/cmmidioutvst.cpp mode change 100755 => 100644 windows/commng/cmmidioutvst.h mode change 100755 => 100644 windows/commng/cmnull.cpp mode change 100755 => 100644 windows/commng/cmnull.h mode change 100755 => 100644 windows/commng/cmpara.cpp mode change 100755 => 100644 windows/commng/cmpara.h mode change 100755 => 100644 windows/commng/cmpipe.cpp mode change 100755 => 100644 windows/commonfix.h mode change 100755 => 100644 windows/compiler.cpp mode change 100755 => 100644 windows/compiler.h mode change 100755 => 100644 windows/debuguty/view1mb.cpp mode change 100755 => 100644 windows/debuguty/view1mb.h mode change 100755 => 100644 windows/debuguty/viewasm.cpp mode change 100755 => 100644 windows/debuguty/viewasm.h mode change 100755 => 100644 windows/debuguty/viewer.h mode change 100755 => 100644 windows/debuguty/viewitem.cpp mode change 100755 => 100644 windows/debuguty/viewitem.h mode change 100755 => 100644 windows/debuguty/viewmem.cpp mode change 100755 => 100644 windows/debuguty/viewmem.h mode change 100755 => 100644 windows/debuguty/viewreg.cpp mode change 100755 => 100644 windows/debuguty/viewreg.h mode change 100755 => 100644 windows/debuguty/viewseg.cpp mode change 100755 => 100644 windows/debuguty/viewseg.h mode change 100755 => 100644 windows/debuguty/viewsnd.cpp mode change 100755 => 100644 windows/debuguty/viewsnd.h mode change 100755 => 100644 windows/dialog/c_combodata.cpp mode change 100755 => 100644 windows/dialog/c_combodata.h mode change 100755 => 100644 windows/dialog/c_dipsw.cpp mode change 100755 => 100644 windows/dialog/c_dipsw.h mode change 100755 => 100644 windows/dialog/c_midi.cpp mode change 100755 => 100644 windows/dialog/c_midi.h mode change 100755 => 100644 windows/dialog/c_slidervalue.cpp mode change 100755 => 100644 windows/dialog/c_slidervalue.h mode change 100755 => 100644 windows/dialog/d_about.cpp mode change 100755 => 100644 windows/dialog/d_bmp.cpp mode change 100755 => 100644 windows/dialog/d_cfgload.cpp mode change 100755 => 100644 windows/dialog/d_cfgsave.cpp mode change 100755 => 100644 windows/dialog/d_clnd.cpp mode change 100755 => 100644 windows/dialog/d_ide.cpp mode change 100755 => 100644 windows/dialog/d_network.cpp mode change 100755 => 100644 windows/dialog/d_pci.cpp mode change 100755 => 100644 windows/dialog/d_screen.cpp mode change 100755 => 100644 windows/dialog/d_soundlog.cpp mode change 100755 => 100644 windows/dialog/d_txt.cpp mode change 100755 => 100644 windows/dialog/d_wab.cpp mode change 100755 => 100644 windows/dialog/dialog.h mode change 100755 => 100644 windows/dialog/np2class.cpp mode change 100755 => 100644 windows/dialog/np2class.h mode change 100755 => 100644 windows/dosio.cpp mode change 100755 => 100644 windows/dosio.h mode change 100755 => 100644 windows/ext/c86ctl/c86ctl.h mode change 100755 => 100644 windows/ext/c86ctl/c86ctlif.cpp mode change 100755 => 100644 windows/ext/c86ctl/c86ctlif.h mode change 100755 => 100644 windows/ext/c86ctl/cbus_boardtype.h mode change 100755 => 100644 windows/ext/externalchip.h mode change 100755 => 100644 windows/ext/externalchipmanager.cpp mode change 100755 => 100644 windows/ext/externalchipmanager.h mode change 100755 => 100644 windows/ext/externalopl3.cpp mode change 100755 => 100644 windows/ext/externalopl3.h mode change 100755 => 100644 windows/ext/externalopm.cpp mode change 100755 => 100644 windows/ext/externalopm.h mode change 100755 => 100644 windows/ext/externalopna.cpp mode change 100755 => 100644 windows/ext/externalopna.h mode change 100755 => 100644 windows/ext/externalpsg.cpp mode change 100755 => 100644 windows/ext/externalpsg.h mode change 100755 => 100644 windows/ext/mt32snd.cpp mode change 100755 => 100644 windows/ext/mt32snd.h mode change 100755 => 100644 windows/ext/romeo/juliet.cpp mode change 100755 => 100644 windows/ext/romeo/juliet.h mode change 100755 => 100644 windows/ext/romeo/romeo.h mode change 100755 => 100644 windows/fontmng.cpp mode change 100755 => 100644 windows/fontmng.h mode change 100755 => 100644 windows/ini.h mode change 100755 => 100644 windows/joymng.h mode change 100755 => 100644 windows/menu.h mode change 100755 => 100644 windows/misc/DlgProc.cpp mode change 100755 => 100644 windows/misc/DlgProc.h mode change 100755 => 100644 windows/misc/PropProc.cpp mode change 100755 => 100644 windows/misc/PropProc.h mode change 100755 => 100644 windows/misc/WndBase.h mode change 100755 => 100644 windows/misc/WndProc.cpp mode change 100755 => 100644 windows/misc/WndProc.h mode change 100755 => 100644 windows/misc/extrom.cpp mode change 100755 => 100644 windows/misc/extrom.h mode change 100755 => 100644 windows/misc/guard.h mode change 100755 => 100644 windows/misc/threadbase.cpp mode change 100755 => 100644 windows/misc/threadbase.h mode change 100755 => 100644 windows/misc/tickcounter.cpp mode change 100755 => 100644 windows/misc/tickcounter.h mode change 100755 => 100644 windows/misc/trace.cpp mode change 100755 => 100644 windows/misc/trace.h mode change 100755 => 100644 windows/misc/tstring.cpp mode change 100755 => 100644 windows/misc/tstring.h mode change 100755 => 100644 windows/misc/vc6macros.h mode change 100755 => 100644 windows/mousemng.h mode change 100755 => 100644 windows/np2.h mode change 100755 => 100644 windows/np2arg.cpp mode change 100755 => 100644 windows/np2arg.h mode change 100755 => 100644 windows/oemtext.cpp mode change 100755 => 100644 windows/oemtext.h mode change 100755 => 100644 windows/readme.txt mode change 100755 => 100644 windows/recvideo.cpp mode change 100755 => 100644 windows/recvideo.h mode change 100755 => 100644 windows/resources/resource.cpp mode change 100755 => 100644 windows/soundmng/asio/asiodriverlist.cpp mode change 100755 => 100644 windows/soundmng/asio/asiodriverlist.h mode change 100755 => 100644 windows/soundmng/asio/asiosdk.h mode change 100755 => 100644 windows/soundmng/sdasio.cpp mode change 100755 => 100644 windows/soundmng/sdasio.h mode change 100755 => 100644 windows/soundmng/sdbase.h mode change 100755 => 100644 windows/soundmng/sddsound3.h mode change 100755 => 100644 windows/soundmng/sdwasapi.cpp mode change 100755 => 100644 windows/soundmng/sdwasapi.h mode change 100755 => 100644 windows/subwnd/dclock.cpp mode change 100755 => 100644 windows/subwnd/dclock.h mode change 100755 => 100644 windows/subwnd/kdispwnd.cpp mode change 100755 => 100644 windows/subwnd/kdispwnd.h mode change 100755 => 100644 windows/subwnd/mdbgwnd.cpp mode change 100755 => 100644 windows/subwnd/mdbgwnd.h mode change 100755 => 100644 windows/subwnd/subwnd.h mode change 100755 => 100644 windows/subwnd/toolwnd.h mode change 100755 => 100644 windows/targetver.h mode change 100755 => 100644 windows/taskmng.h mode change 100755 => 100644 windows/timemng.cpp mode change 100755 => 100644 windows/timemng.h mode change 100755 => 100644 windows/winkbd.h mode change 100755 => 100644 windows/winloc.cpp mode change 100755 => 100644 windows/winloc.h mode change 100755 => 100644 windows/x64/pccore.inc mode change 100755 => 100644 windows/x64/vram.inc mode change 100755 => 100644 windows/x64/vs2019/x64.xml mode change 100755 => 100644 windows/x86/cputype.h mode change 100755 => 100644 windows/x86/cputype.x86 mode change 100755 => 100644 windows/x86/makegrph.x86 mode change 100755 => 100644 windows/x86/np2asm.inc mode change 100755 => 100644 windows/x86/opngeng.x86 mode change 100755 => 100644 windows/x86/parts.x86 mode change 100755 => 100644 windows/x86/pccore.inc mode change 100755 => 100644 windows/x86/vram.inc mode change 100755 => 100644 windows/x86/vs2019/x86.xml diff --git a/CMakeSettings.json b/CMakeSettings.json index 314ab8a8..5028d199 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -1,58 +1,58 @@ -{ - "configurations": [ - { - "name": "x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "-v", - "ctestCommandArgs": "", - "variables": [ - { - "name": "CMAKE_TOOLCHAIN_FILE", - "value": "C:\\dev\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake" - }, - { - "name": "BUILD_I286", - "value": "False", - "type": "BOOL" - }, - { - "name": "USE_SDL2", - "value": "False", - "type": "BOOL" - } - ] - }, - { - "name": "x64-Release", - "generator": "Ninja", - "configurationType": "RelWithDebInfo", - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "-v", - "ctestCommandArgs": "", - "inheritEnvironments": [ "msvc_x64_x64" ], - "variables": [ - { - "name": "CMAKE_TOOLCHAIN_FILE", - "value": "C:\\dev\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake" - }, - { - "name": "BUILD_I286", - "value": "False", - "type": "BOOL" - }, - { - "name": "USE_SDL2", - "value": "False", - "type": "BOOL" - } - ] - } - ] -} +{ + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "variables": [ + { + "name": "CMAKE_TOOLCHAIN_FILE", + "value": "C:\\dev\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake" + }, + { + "name": "BUILD_I286", + "value": "False", + "type": "BOOL" + }, + { + "name": "USE_SDL2", + "value": "False", + "type": "BOOL" + } + ] + }, + { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [ + { + "name": "CMAKE_TOOLCHAIN_FILE", + "value": "C:\\dev\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake" + }, + { + "name": "BUILD_I286", + "value": "False", + "type": "BOOL" + }, + { + "name": "USE_SDL2", + "value": "False", + "type": "BOOL" + } + ] + } + ] +} diff --git a/LICENSES/LICENSE-I386C.TXT b/LICENSES/LICENSE-I386C.TXT index cc2b9a7b..b3f60bee 100644 --- a/LICENSES/LICENSE-I386C.TXT +++ b/LICENSES/LICENSE-I386C.TXT @@ -1,4 +1,4 @@ -/i386cȉɓKpBAȉ +/i386c以下に適用。ただし、以下を除く /i386c/ia32/instructions/fpu /i386c/ia32/instructions/mmx /i386c/ia32/instructions/sse diff --git a/LICENSES/LICENSE-TGUI9680.TXT b/LICENSES/LICENSE-TGUI9680.TXT index 4581309e..2299a425 100644 --- a/LICENSES/LICENSE-TGUI9680.TXT +++ b/LICENSES/LICENSE-TGUI9680.TXT @@ -4,9 +4,9 @@ /wab/tgui9680_extern.h /wab/tgui9680_wrapper.h -vvZbT +プリプロセッサ SUPPORT_TRIDENT_TGUI -`Ȃꍇ͏O +を定義しない場合は除外 GNU GENERAL PUBLIC LICENSE diff --git a/LICENSES/LICENSE.TXT b/LICENSES/LICENSE.TXT index 5c0eeeb3..c44e1771 100644 --- a/LICENSES/LICENSE.TXT +++ b/LICENSES/LICENSE.TXT @@ -1,4 +1,4 @@ -LICENSEŊYĂȂ\[XR[h֓Kp +他のLICENSE文書で該当していないソースコードへ適用 Copyright (c) 1999-2025, NP2 developer team All rights reserved. diff --git a/LICENSES/dosbox-fpu/LICENSE-GPL.TXT b/LICENSES/dosbox-fpu/LICENSE-GPL.TXT index 54ac600e..474143ed 100644 --- a/LICENSES/dosbox-fpu/LICENSE-GPL.TXT +++ b/LICENSES/dosbox-fpu/LICENSE-GPL.TXT @@ -2,10 +2,10 @@ /i386c/ia32/instructions/fpu/fpemul_dosbox.c /i386c/ia32/instructions/fpu/fpemul_dosbox2.c -vvZbT +プリプロセッサ SUPPORT_FPU_DOSBOX SUPPORT_FPU_DOSBOX2 -`Ȃꍇ͏O +を定義しない場合は除外 Copyright (C) 2002-2015 The DOSBox Team diff --git a/LICENSES/fmgen/fmgen_readme.txt b/LICENSES/fmgen/fmgen_readme.txt index 8a79604b..1d42c245 100644 --- a/LICENSES/fmgen/fmgen_readme.txt +++ b/LICENSES/fmgen/fmgen_readme.txt @@ -3,91 +3,91 @@ Copyright (C) by cisc 1998, 2003. ------------------------------------------------------------------------------ -yTvz - C++ ɂ FM/PSG ̎łB +【概要】 + C++ による FM/PSG 音源の実装です。 - AY8910, YM2203, YM2151, YM2608, YM2610 ̃C^[tF[X - Ă܂B + AY8910, YM2203, YM2151, YM2608, YM2610 相当のインターフェースも + 実装してあります。 -ygz - (TODO:g) +【使い方】 + (TODO:中身を書く) -yӁz - ȑÕo[W܂BC^[tF[X - ĂȂ‚łÃoOBĂ邩܂B +【注意】 + 以前のバージョンから幾分手を加えました。インターフェースは + いじっていないつもりですが、何かしらのバグが隠れているかもしれません。 - YM2610 ͓`FbN炵Ă܂B + YM2610 は動作チェックすらしていません。 - `⊮[h(interpolation)͔p~܂B - Init() ̈dl͕ςĂ܂񂪁Ainterpolation = true ɂĂ - ͕ς܂B + 線形補完モード(interpolation)は廃止されました。 + Init() の引数仕様は変わっていませんが、interpolation = true にしても + 動作は変わりません。 - OPNA::Init/SetRate ŗ^`bvNbN̒l̎dl - ȑO M88 ɓڂĂo[WƈقȂĂ܂D + OPNA::Init/SetRate で与えるチップクロックの値の仕様が + 以前の M88 に搭載されていたバージョンと異なっています. -y쌠AƐӋKz +【著作権、免責規定】 - E{\[XR[h͍(cisc@retropc.net) 쌠LĂ܂B + ・本ソースコードは作者(cisc@retropc.net) が著作権を所有しています。 - E{\[XR[h͂邪܂܂ɒ񋟂̂łC - ÖًyіIȕۏ؂؊܂݂܂D + ・本ソースコードはあるがままに提供されるものであり, + 暗黙及び明示的な保証を一切含みません. - E{\[XR[h𗘗pƁCpȂƁC - płȂƂɊւĐ邢͐Ɨ\ - Qɂ‚āC҂͈ؐӔC𕉂܂D + ・本ソースコードを利用したこと,利用しなかったこと, + 利用できなかったことに関して生じたあるいは生じると予測される + 損害について,作者は一切責任を負いません. - E{\[XR[h́Cȉ̐𖞂莩RɉρEgݍ݁E - zzEp邱Ƃł܂D + ・本ソースコードは,以下の制限を満たす限り自由に改変・組み込み・ + 配布・利用することができます. - 1. {\tg̗R(, 쌠)𖾋L邱. - 2. zzۂɂ̓t[\tgƂ邱ƁD - 3. ς\[XR[hzzۂ͉ϓe𖾎邱. - 4. \[XR[hzzۂɂ͂̃eLXg؉ς - ̂܂ܓYt邱ƁD + 1. 本ソフトの由来(作者, 著作権)を明記すること. + 2. 配布する際にはフリーソフトとすること. + 3. 改変したソースコードを配布する際は改変内容を明示すること. + 4. ソースコードを配布する際にはこのテキストを一切改変せずに + そのまま添付すること. - EJ̍ۂɍ҂ւ̘A𒸂΍KłD + ・公開の際に作者への連絡を頂ければ幸いです. - Ep\tg(VFAEFA܂) ɖ{\[XR[ḧꕔC܂ - Sgݍލۂɂ́COɍ҂̍ӂ𓾂Kv܂D + ・商用ソフト(シェアウェア含む) に本ソースコードの一部,または + 全部を組み込む際には,事前に作者の合意を得る必要があります. -yύX_z -008 030902 Eo̓TvO[g̐ݒA`bv̍Tv - O[gƈقȂݒɂƃGx[v - ȂCB +【変更点】 +008 030902 ・出力サンプリングレートの設定を、チップ元来の合成サンプ + リングレートと異なる設定にするとエンベロープがおかしく + なる問題を修正。 -007a 030608 ËOANZX̂C (Thanks to ohDl) +007a 030608 ・領域外アクセスがあったのを修正 (Thanks to PI.様) -007 030607 EČ̌ - EOPN: SSG-EG ̃T|[g - E`⊮̔p~ - Easm ł̔p~ - E}`Xbht[ɂȂH +007 030607 ・再現性の向上 + ・OPN: SSG-EG のサポート + ・線形補完の廃止 + ・asm 版の廃止 + ・マルチスレッドフリーになった? -006 010330 EČɊւĂ炩蒼(gCo̓^C~O) +006 010330 ・再現性に関していくらか手直し(正弦波,出力タイミング等) -005 010317 EOPN: FM ̍go͎gႢƂɁC - ⊮gƉsɂȂ/܂ƂɏoȂȂC. - EFM: ⊮gȂ̐xグĂ݂D - 肪N fmgeninl.h FM_RATIOBITS 8 ɖ߂ƋgD +005 010317 ・OPN: FM 音源の合成周波数が出力周波数よりも低いときに, + 補完を使うと音痴になる/音がまともに出なくなる問題を修正. + ・FM: 補完を使わない時の精度を上げてみる. + 問題が起きたら fmgeninl.h の FM_RATIOBITS を 8 に戻すと吉. -004a 010311 EOPM: mCY郌x(H)܂ŏC. - EOPNA/OPM: FM_USE_CALC2 p~. - EfOC, Ȃ̂߂ cvs ŊǗĂ񂾂c(T-T - OPNB: ADPCMB ROM }XN쐬~X. - OPNB: ADPCMA Xe[^XtO֌W̋C. - OPM: LFO p[^̏YĂ̂C. +004a 010311 ・OPM: ノイズをそこそこ聞けるレベル(?)まで修正. + ・OPNA/OPM: FM_USE_CALC2 廃止. + ・デグレ修正, なんのために cvs で管理しているんだか…(T-T + OPNB: ADPCMB ROM マスク作成ミス. + OPNB: ADPCMA ステータスフラグ関係の挙動修復. + OPM: LFO パラメータの初期化を忘れていたのを修正. -003 010124 EOPNA/OPMF ۂɂ͕⊮O̒lo͂ĂoOC. +003 010124 ・OPNA/OPM: 実際には補完前の値を出力していたバグを修正. -002 010123 Ego͎gႢƂłԂ悤ɂ. - EOPN: ԎɃvXP[̐ݒύXƂɉ - oOC. - EOPNA/B: LFO ȂoOC. +002 010123 ・合成周波数が出力周波数より低いときでも補間が効くようにする. + ・OPN: 補間時にプリスケーラの設定を変更したときに音化けする + バグを修正. + ・OPNA/B: LFO が効かないバグを修正. -001 000928 Eo[W +001 000928 ・初期バージョン $Id: readme.txt,v 1.1 2003/06/07 08:25:20 cisc Exp $ diff --git a/LICENSES/mame/LICENSE-MAME-GPL.TXT b/LICENSES/mame/LICENSE-MAME-GPL.TXT index d7dc6c0b..28eab343 100644 --- a/LICENSES/mame/LICENSE-MAME-GPL.TXT +++ b/LICENSES/mame/LICENSE-MAME-GPL.TXT @@ -1,7 +1,7 @@ -------------------------------------- -/sound/mameȉɓKp +/sound/mame以下に適用 -vvZbT USE_MAME_BSD`邩AUSE_MAME`Ȃꍇ͏O +プリプロセッサ USE_MAME_BSDを定義するか、USE_MAMEを定義しない場合は除外 license:GPL-2.0+ copyright-holders:Jarek Burczynski diff --git a/LICENSES/mamebsd/LICENSE-MAME-BSD.TXT b/LICENSES/mamebsd/LICENSE-MAME-BSD.TXT index 607c2112..28c951e7 100644 --- a/LICENSES/mamebsd/LICENSE-MAME-BSD.TXT +++ b/LICENSES/mamebsd/LICENSE-MAME-BSD.TXT @@ -1,7 +1,7 @@ -------------------------------------- -/sound/mamebsd, /sound/mamebsdsubȉɓKp +/sound/mamebsd, /sound/mamebsdsub以下に適用 -vvZbT USE_MAME_BSD`Ȃꍇ͏O +プリプロセッサ USE_MAME_BSDを定義しない場合は除外 BSD 3-Clause License diff --git a/LICENSES/softfloat/README2.txt b/LICENSES/softfloat/README2.txt index a5673927..6820c668 100644 --- a/LICENSES/softfloat/README2.txt +++ b/LICENSES/softfloat/README2.txt @@ -1,5 +1,5 @@ -------------------------------------- -/i386c/ia32/instructions/fpu/softfloatȉɓKp +/i386c/ia32/instructions/fpu/softfloat以下に適用 -SUPPORT_FPU_SOFTFLOAT`Ȃꍇ͏O +SUPPORT_FPU_SOFTFLOATを定義しない場合は除外 diff --git a/LICENSES/softfloat3/README2.txt b/LICENSES/softfloat3/README2.txt index 293c37e2..c89324e8 100644 --- a/LICENSES/softfloat3/README2.txt +++ b/LICENSES/softfloat3/README2.txt @@ -1,5 +1,5 @@ -------------------------------------- -/i386c/ia32/instructions/fpu/softfloat3ȉɓKp +/i386c/ia32/instructions/fpu/softfloat3以下に適用 -SUPPORT_FPU_SOFTFLOAT3`Ȃꍇ͏O +SUPPORT_FPU_SOFTFLOAT3を定義しない場合は除外 diff --git "a/LICENSES/\345\205\250\344\275\223\350\252\254\346\230\216.txt" "b/LICENSES/\345\205\250\344\275\223\350\252\254\346\230\216.txt" index 0eb36738..d7c5632a 100644 --- "a/LICENSES/\345\205\250\344\275\223\350\252\254\346\230\216.txt" +++ "b/LICENSES/\345\205\250\344\275\223\350\252\254\346\230\216.txt" @@ -1,6 +1,6 @@ -Neko Project 21/W̑唼̃R[h͏CBSDCZXłAꕔ̃t@C͈ڐÂ߃CZXقȂĂ܂B܂߂ăRpCƑŜƂẴCZXς܂̂łӂB +Neko Project 21/Wの大半のコードは修正BSDライセンスですが、一部のファイルは移植のためライセンスが異なっています。これらを含めてコンパイルすると全体としてのライセンスが変わりますのでご注意ください。 -ڍׂ⏜O@ɂ‚ĂNeko Project 21/WTCǵuCZXɂ‚āvB +詳細や除外方法についてはNeko Project 21/Wサイトの「ライセンスについて」をご覧ください。 https://simk98.github.io/np21w/download.html diff --git a/accessories/bin2txt.c b/accessories/bin2txt.c old mode 100755 new mode 100644 index 8ddc3dd7..60399971 --- a/accessories/bin2txt.c +++ b/accessories/bin2txt.c @@ -1,113 +1,113 @@ -#include -#include -#include "textout.h" - -enum { - _NOERROR = 0, - ERROR_INPUT, - ERROR_OUTPUT, - ERROR_MEMORY, - ERROR_SYSTEM -}; - -static int cnvmain(const char *srcfile, const char *dstfile, - const char *sym) { - - int ret; - FILEH fh; - void *dst; - char work[256]; - BYTE buf[12]; - UINT size; - UINT i; - - ret = _NOERROR; - fh = file_open(srcfile); - if (fh == FILEH_INVALID) { - printf("... open error\n"); - ret = ERROR_INPUT; - goto c_err1; - } - dst = textout_open(dstfile, 256); - - if (sym == NULL) { - sym = srcfile; - } - SPRINTF(work, "static const unsigned char %s[] = {\n", sym); - textout_write(dst, work); - - while(1) { - size = file_read(fh, buf, 12); - if (size == 0) { - break; - } - for (i=0; i= 1) { - prog = argv[0]; - } - src = NULL; - dst = NULL; - sym = NULL; - pos = 1; - while(pos < argc) { - p = argv[pos++]; - if (p[0] == '-') { - if (((p[1] == 'S') || (p[1] == 's')) && (sym == NULL)) { - sym = p + 2; - } - } - else if (src == NULL) { - src = p; - } - else if (dst == NULL) { - dst = p; - } - } - - if (src == NULL) { - printf("%s: error: no input file\n", prog); - ret = ERROR_SYSTEM; - goto main_exit; - } - ret = cnvmain(src, dst, sym); - -main_exit: - dosio_term(); - return(ret); -} - +#include +#include +#include "textout.h" + +enum { + _NOERROR = 0, + ERROR_INPUT, + ERROR_OUTPUT, + ERROR_MEMORY, + ERROR_SYSTEM +}; + +static int cnvmain(const char *srcfile, const char *dstfile, + const char *sym) { + + int ret; + FILEH fh; + void *dst; + char work[256]; + BYTE buf[12]; + UINT size; + UINT i; + + ret = _NOERROR; + fh = file_open(srcfile); + if (fh == FILEH_INVALID) { + printf("... open error\n"); + ret = ERROR_INPUT; + goto c_err1; + } + dst = textout_open(dstfile, 256); + + if (sym == NULL) { + sym = srcfile; + } + SPRINTF(work, "static const unsigned char %s[] = {\n", sym); + textout_write(dst, work); + + while(1) { + size = file_read(fh, buf, 12); + if (size == 0) { + break; + } + for (i=0; i= 1) { + prog = argv[0]; + } + src = NULL; + dst = NULL; + sym = NULL; + pos = 1; + while(pos < argc) { + p = argv[pos++]; + if (p[0] == '-') { + if (((p[1] == 'S') || (p[1] == 's')) && (sym == NULL)) { + sym = p + 2; + } + } + else if (src == NULL) { + src = p; + } + else if (dst == NULL) { + dst = p; + } + } + + if (src == NULL) { + printf("%s: error: no input file\n", prog); + ret = ERROR_SYSTEM; + goto main_exit; + } + ret = cnvmain(src, dst, sym); + +main_exit: + dosio_term(); + return(ret); +} + diff --git a/accessories/lzxpack.c b/accessories/lzxpack.c old mode 100755 new mode 100644 index bc6fc57c..e764a7a7 --- a/accessories/lzxpack.c +++ b/accessories/lzxpack.c @@ -1,270 +1,270 @@ -#include -#include -#include "textout.h" - -enum { - _NOERROR = 0, - ERROR_INPUT, - ERROR_OUTPUT, - ERROR_MEMORY, - ERROR_SYSTEM -}; - -typedef struct { - BYTE *ptr; - int size; -} _PACK, *PACK; - -static int lzpacking(const BYTE *data, int datasize, PACK lz, int level) { - - int maxlen; - int maxhis; - BYTE *ptr; - BYTE *ctrl; - BYTE bit; - int pos; - int back; - int rem; -const BYTE *p; -const BYTE *q; - int r; - int minback; - int minr; - UINT tmp; - - maxlen = 1 << level; - maxhis = 1 << (16 - level); - - ptr = lz->ptr; - ptr[0] = (BYTE)datasize; - ptr[1] = (BYTE)(datasize >> 8); - ptr[2] = (BYTE)(datasize >> 16); - ptr[3] = (BYTE)level; - ptr += 4; - bit = 0; - pos = 0; - while(pos < datasize) { - if (bit == 0) { - bit = 0x80; - ctrl = ptr; - *ptr++ = 0x00; - } - back = MIN(pos, maxhis); - rem = MIN(datasize - pos, maxlen); - minback = back; - minr = rem; - while(back) { - p = data - back; - q = data; - r = rem; - while(r) { - if (*p++ != *q++) { - break; - } - r--; - } - if (minr >= r) { - minr = r; - minback = back; - } - back--; - } - r = rem - minr; - if (r > 2) { - data += r; - pos += r; - tmp = ((minback - 1) << level) | (r - 1); - *ctrl |= bit; - *ptr++ = (BYTE)(tmp >> 8); - *ptr++ = (BYTE)tmp; - } - else { - *ptr++ = *data++; - pos++; - } - bit >>= 1; - } - lz->size = ptr - lz->ptr; - return(lz->size); -} - -static PACK lzpack(const BYTE *data, int datasize) { - - PACK ret; - int memsize; - int i; - int level; - int minsize; - - memsize = (datasize + 7) / 8; - memsize *= 9; - memsize += 8; - ret = (PACK)_MALLOC(sizeof(_PACK) + memsize, "LZ"); - if (ret == NULL) { - goto lz_exit; - } - ret->ptr = (BYTE *)(ret + 1); - - level = 0; - minsize = memsize; - for (i=0; i<=16; i++) { - lzpacking(data, datasize, ret, i); - if (minsize > ret->size) { - minsize = ret->size; - level = i; - } - printf("."); - } - lzpacking(data, datasize, ret, level); - -lz_exit: - return(ret); -} - - -// ---- - -static void stringout(void *dst, const BYTE *ptr, UINT size) { - - int step; - char work[16]; - - step = 0; - while(size--) { - if (!step) { - textout_write(dst, "\t\t"); - } - SPRINTF(work, "0x%02x,", (BYTE)*ptr++); - textout_write(dst, work); - step++; - if (step > 12) { - textout_write(dst, "\n"); - step = 0; - } - } - if (step) { - textout_write(dst, "\n"); - } -} - - -// ---- - -static int packmain(const char *srcfile, const char *dstfile, - const char *sym) { - - int ret; - FILEH src; - void *dst; - BYTE *tmp; - UINT size; - PACK lz; - char work[256]; - - ret = _NOERROR; - printf("%s", srcfile); - src = file_open(srcfile); - if (src == FILEH_INVALID) { - printf("... open error\n"); - ret = ERROR_INPUT; - goto rf_err1; - } - size = file_getsize(src); - if (size == 0) { - printf("... size zero\n"); - ret = ERROR_INPUT; - goto rf_err2; - } - tmp = (BYTE *)_MALLOC(size, filename); - if (tmp == NULL) { - printf("... memory error\n"); - ret = ERROR_MEMORY; - goto rf_err2; - } - if (file_read(src, tmp, size) != size) { - printf("... read error\n"); - ret = ERROR_INPUT; - goto rf_err3; - } - - dst = textout_open(dstfile, 256); - - lz = lzpack(tmp, size); - printf("done\n"); - - if (lz) { - if (sym == NULL) { - sym = srcfile; - } - SPRINTF(work, "static const BYTE %s[%d] = {\n", sym, lz->size); - textout_write(dst, work); - stringout(dst, lz->ptr, lz->size); - textout_write(dst, "};\n"); - _MFREE(lz); - } - - textout_close(dst); - -rf_err3: - _MFREE(tmp); - -rf_err2: - file_close(src); - -rf_err1: - return(ret); -} - - -// ---- - -static const char progorg[] = "lzxpack"; - -int main(int argc, char *argv[], char *envp[]) { - - int ret; -const char *prog; -const char *src; -const char *dst; -const char *sym; - int pos; -const char *p; - - dosio_init(); - - ret = _NOERROR; - prog = progorg; - if (argc >= 1) { - prog = argv[0]; - } - src = NULL; - dst = NULL; - sym = NULL; - pos = 1; - while(pos < argc) { - p = argv[pos++]; - if (p[0] == '-') { - if (((p[1] == 'S') || (p[1] == 's')) && (sym == NULL)) { - sym = p + 2; - } - } - else if (src == NULL) { - src = p; - } - else if (dst == NULL) { - dst = p; - } - } - - if (src == NULL) { - printf("%s: error: no input file\n", prog); - ret = ERROR_SYSTEM; - goto main_exit; - } - ret = packmain(src, dst, sym); - -main_exit: - dosio_term(); - return(ret); -} - +#include +#include +#include "textout.h" + +enum { + _NOERROR = 0, + ERROR_INPUT, + ERROR_OUTPUT, + ERROR_MEMORY, + ERROR_SYSTEM +}; + +typedef struct { + BYTE *ptr; + int size; +} _PACK, *PACK; + +static int lzpacking(const BYTE *data, int datasize, PACK lz, int level) { + + int maxlen; + int maxhis; + BYTE *ptr; + BYTE *ctrl; + BYTE bit; + int pos; + int back; + int rem; +const BYTE *p; +const BYTE *q; + int r; + int minback; + int minr; + UINT tmp; + + maxlen = 1 << level; + maxhis = 1 << (16 - level); + + ptr = lz->ptr; + ptr[0] = (BYTE)datasize; + ptr[1] = (BYTE)(datasize >> 8); + ptr[2] = (BYTE)(datasize >> 16); + ptr[3] = (BYTE)level; + ptr += 4; + bit = 0; + pos = 0; + while(pos < datasize) { + if (bit == 0) { + bit = 0x80; + ctrl = ptr; + *ptr++ = 0x00; + } + back = MIN(pos, maxhis); + rem = MIN(datasize - pos, maxlen); + minback = back; + minr = rem; + while(back) { + p = data - back; + q = data; + r = rem; + while(r) { + if (*p++ != *q++) { + break; + } + r--; + } + if (minr >= r) { + minr = r; + minback = back; + } + back--; + } + r = rem - minr; + if (r > 2) { + data += r; + pos += r; + tmp = ((minback - 1) << level) | (r - 1); + *ctrl |= bit; + *ptr++ = (BYTE)(tmp >> 8); + *ptr++ = (BYTE)tmp; + } + else { + *ptr++ = *data++; + pos++; + } + bit >>= 1; + } + lz->size = ptr - lz->ptr; + return(lz->size); +} + +static PACK lzpack(const BYTE *data, int datasize) { + + PACK ret; + int memsize; + int i; + int level; + int minsize; + + memsize = (datasize + 7) / 8; + memsize *= 9; + memsize += 8; + ret = (PACK)_MALLOC(sizeof(_PACK) + memsize, "LZ"); + if (ret == NULL) { + goto lz_exit; + } + ret->ptr = (BYTE *)(ret + 1); + + level = 0; + minsize = memsize; + for (i=0; i<=16; i++) { + lzpacking(data, datasize, ret, i); + if (minsize > ret->size) { + minsize = ret->size; + level = i; + } + printf("."); + } + lzpacking(data, datasize, ret, level); + +lz_exit: + return(ret); +} + + +// ---- + +static void stringout(void *dst, const BYTE *ptr, UINT size) { + + int step; + char work[16]; + + step = 0; + while(size--) { + if (!step) { + textout_write(dst, "\t\t"); + } + SPRINTF(work, "0x%02x,", (BYTE)*ptr++); + textout_write(dst, work); + step++; + if (step > 12) { + textout_write(dst, "\n"); + step = 0; + } + } + if (step) { + textout_write(dst, "\n"); + } +} + + +// ---- + +static int packmain(const char *srcfile, const char *dstfile, + const char *sym) { + + int ret; + FILEH src; + void *dst; + BYTE *tmp; + UINT size; + PACK lz; + char work[256]; + + ret = _NOERROR; + printf("%s", srcfile); + src = file_open(srcfile); + if (src == FILEH_INVALID) { + printf("... open error\n"); + ret = ERROR_INPUT; + goto rf_err1; + } + size = file_getsize(src); + if (size == 0) { + printf("... size zero\n"); + ret = ERROR_INPUT; + goto rf_err2; + } + tmp = (BYTE *)_MALLOC(size, filename); + if (tmp == NULL) { + printf("... memory error\n"); + ret = ERROR_MEMORY; + goto rf_err2; + } + if (file_read(src, tmp, size) != size) { + printf("... read error\n"); + ret = ERROR_INPUT; + goto rf_err3; + } + + dst = textout_open(dstfile, 256); + + lz = lzpack(tmp, size); + printf("done\n"); + + if (lz) { + if (sym == NULL) { + sym = srcfile; + } + SPRINTF(work, "static const BYTE %s[%d] = {\n", sym, lz->size); + textout_write(dst, work); + stringout(dst, lz->ptr, lz->size); + textout_write(dst, "};\n"); + _MFREE(lz); + } + + textout_close(dst); + +rf_err3: + _MFREE(tmp); + +rf_err2: + file_close(src); + +rf_err1: + return(ret); +} + + +// ---- + +static const char progorg[] = "lzxpack"; + +int main(int argc, char *argv[], char *envp[]) { + + int ret; +const char *prog; +const char *src; +const char *dst; +const char *sym; + int pos; +const char *p; + + dosio_init(); + + ret = _NOERROR; + prog = progorg; + if (argc >= 1) { + prog = argv[0]; + } + src = NULL; + dst = NULL; + sym = NULL; + pos = 1; + while(pos < argc) { + p = argv[pos++]; + if (p[0] == '-') { + if (((p[1] == 'S') || (p[1] == 's')) && (sym == NULL)) { + sym = p + 2; + } + } + else if (src == NULL) { + src = p; + } + else if (dst == NULL) { + dst = p; + } + } + + if (src == NULL) { + printf("%s: error: no input file\n", prog); + ret = ERROR_SYSTEM; + goto main_exit; + } + ret = packmain(src, dst, sym); + +main_exit: + dosio_term(); + return(ret); +} + diff --git a/accessories/textout.c b/accessories/textout.c old mode 100755 new mode 100644 index 26bbd186..f02ba28d --- a/accessories/textout.c +++ b/accessories/textout.c @@ -1,91 +1,91 @@ -#include -#include -#include "textout.h" - - -typedef struct { - FILEH fh; - int pos; - int size; -} _TEXTOUT, *TEXTOUT; - - -void *textout_open(const char *filename, int bufsize) { - - TEXTOUT to; - FILEH fh; - - to = NULL; - if (filename == NULL) { - goto toope_exit; - } - fh = file_create(filename); - if (fh == NULL) { - goto toope_exit; - } - bufsize = MAX(bufsize, 256); - to = (TEXTOUT)_MALLOC(sizeof(_TEXTOUT) + bufsize, filename); - if (to == NULL) { - goto toope_exit; - } - to->fh = fh; - to->pos = 0; - to->size = bufsize; - -toope_exit: - return((void *)to); -} - -static void writechar(TEXTOUT to, char c) { - - ((BYTE *)(to + 1))[to->pos] = c; - to->pos++; - if (to->pos >= to->size) { - to->pos = 0; - file_write(to->fh, to + 1, to->size); - } -} - -void textout_write(void *hdl, const char *string) { - - TEXTOUT to; - char c; - - if (string == NULL) { - return; - } - to = (TEXTOUT)hdl; - if (to == NULL) { - printf("%s", string); - } - else { - while(*string) { - c = *string++; -#if defined(OSLINEBREAK_CR) - if (c == '\n') { - c = '\r'; - } -#elif defined(OSLINEBREAK_CRLF) - if (c == '\n') { - writechar(to, '\r'); - } -#endif - writechar(to, c); - } - } -} - -void textout_close(void *hdl) { - - TEXTOUT to; - - to = (TEXTOUT)hdl; - if (to) { - if (to->pos) { - file_write(to->fh, to + 1, to->pos); - } - file_close(to->fh); - _MFREE(to); - } -} - +#include +#include +#include "textout.h" + + +typedef struct { + FILEH fh; + int pos; + int size; +} _TEXTOUT, *TEXTOUT; + + +void *textout_open(const char *filename, int bufsize) { + + TEXTOUT to; + FILEH fh; + + to = NULL; + if (filename == NULL) { + goto toope_exit; + } + fh = file_create(filename); + if (fh == NULL) { + goto toope_exit; + } + bufsize = MAX(bufsize, 256); + to = (TEXTOUT)_MALLOC(sizeof(_TEXTOUT) + bufsize, filename); + if (to == NULL) { + goto toope_exit; + } + to->fh = fh; + to->pos = 0; + to->size = bufsize; + +toope_exit: + return((void *)to); +} + +static void writechar(TEXTOUT to, char c) { + + ((BYTE *)(to + 1))[to->pos] = c; + to->pos++; + if (to->pos >= to->size) { + to->pos = 0; + file_write(to->fh, to + 1, to->size); + } +} + +void textout_write(void *hdl, const char *string) { + + TEXTOUT to; + char c; + + if (string == NULL) { + return; + } + to = (TEXTOUT)hdl; + if (to == NULL) { + printf("%s", string); + } + else { + while(*string) { + c = *string++; +#if defined(OSLINEBREAK_CR) + if (c == '\n') { + c = '\r'; + } +#elif defined(OSLINEBREAK_CRLF) + if (c == '\n') { + writechar(to, '\r'); + } +#endif + writechar(to, c); + } + } +} + +void textout_close(void *hdl) { + + TEXTOUT to; + + to = (TEXTOUT)hdl; + if (to) { + if (to->pos) { + file_write(to->fh, to + 1, to->pos); + } + file_close(to->fh); + _MFREE(to); + } +} + diff --git a/accessories/textout.h b/accessories/textout.h old mode 100755 new mode 100644 index 61f5b472..3c944805 --- a/accessories/textout.h +++ b/accessories/textout.h @@ -1,5 +1,5 @@ - -void *textout_open(const char *filename, int bufsize); -void textout_write(void *hdl, const char *string); -void textout_close(void *hdl); - + +void *textout_open(const char *filename, int bufsize); +void textout_write(void *hdl, const char *string); +void textout_close(void *hdl); + diff --git a/bios/bios.h b/bios/bios.h index f1325353..30728673 100644 --- a/bios/bios.h +++ b/bios/bios.h @@ -1,147 +1,147 @@ -/** - * @file bios.h - * @brief Interface of BIOS - */ - -#pragma once - -#include "cpumem.h" - -enum { - BIOS_SEG = 0xfd80, - BIOS_BASE = (BIOS_SEG << 4), - - BIOS_TABLE = 0x0040, - - BIOSOFST_ITF = 0x0080, - BIOSOFST_INIT = 0x0084, - - BIOSOFST_09 = 0x0088, // Keyboard - BIOSOFST_0c = 0x008c, // Serial - BIOSOFST_10 = 0x008e, // (PC/AT VGA) - - BIOSOFST_12 = 0x0090, // FDC - BIOSOFST_13 = 0x0094, // FDC - - BIOSOFST_18 = 0x0098, // Common - BIOSOFST_19 = 0x009c, // RS-232C - BIOSOFST_CMT = 0x00a0, // CMT - BIOSOFST_PRT = 0x00a4, // Printer - BIOSOFST_1b = 0x00a8, // Disk - BIOSOFST_1c = 0x00ac, // Timer - BIOSOFST_1f = 0x00b0, // Ext - - BIOSOFST_WAIT = 0x00b4 // FDD waiting - -}; - -#ifdef USE_CUSTOM_HOOKINST -#define HOOKINST_DEFAULT 0x90 // NOP - -typedef struct { - UINT8 hookinst; // BIOStbN閽 default:NOP(0x90) -} BIOSHOOKINFO; -#endif - -#if defined(BIOS_IO_EMULATION) -// np21w ver0.86 rev46 BIOS I/O emulation - -// XXX: I/OANZX͍ő20񕪂炢Ώ\Ǝv̂Ōߑł -#define BIOSIOEMU_DATA_MAX 20 - -enum { - BIOSIOEMU_FLAG_NONE = 0x0, - BIOSIOEMU_FLAG_MB = 0x1, // rbg𗧂ĂDX, AX(16bit)܂DX, EAX(32bit)ɂȂiĂȂ8bitANZXj - BIOSIOEMU_FLAG_READ = 0x2, // rbg𗧂ĂƋǂ݂ -}; -typedef struct { - UINT8 flag; // ANZXtO(łBIOSIOEMU_FLAG_NONÊ) - UINT16 port; // o͐|[g - UINT32 data; // o̓f[^(ł8bitl̂ݗL) -} BIOSIOEMU_IODATA; - -typedef struct { - UINT8 enable; // BIOS I/O G~[VL - UINT8 count; // o̓f[^ - UINT32 oldEAX; // EAXޔp - UINT32 oldEDX; // EDXޔp - BIOSIOEMU_IODATA data[BIOSIOEMU_DATA_MAX]; // o͐|[gƃ|[gɏo͂f[^Bf[^LIFOȂ̂Œ -} BIOSIOEMU; - -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -// extern BOOL biosrom; - -#ifdef USE_CUSTOM_HOOKINST -extern BIOSHOOKINFO bioshookinfo; -#endif -#if defined(BIOS_IO_EMULATION) -// np21w ver0.86 rev46 BIOS I/O emulation -extern BIOSIOEMU biosioemu; -#endif - -void bios_initialize(void); -UINT MEMCALL biosfunc(UINT32 adrs); -#ifdef SUPPORT_PCI -UINT MEMCALL bios32func(UINT32 adrs); -#endif - -void bios0x09(void); -void bios0x09_init(void); - -void bios0x0c(void); - -void bios0x12(void); -void bios0x13(void); - -void bios0x18(void); -void bios0x18_0a(REG8 mode); -void bios0x18_0c(void); -void bios0x18_10(REG8 curdel); -REG16 bios0x18_14(REG16 seg, REG16 off, REG16 code); -void bios0x18_16(REG8 chr, REG8 atr); -void bios0x18_40(void); -void bios0x18_41(void); -void bios0x18_42(REG8 mode); - -void bios0x19(void); - -void bios0x1a_cmt(void); -void bios0x1a_prt(void); -#if defined(SUPPORT_PCI) -void bios0x1a_pci_part(int is32bit); -void bios0x1a_pci(void); -void bios0x1a_pcipnp(void); -#endif - -void bios0x1b(void); -UINT bios0x1b_wait(void); -void fddbios_equip(REG8 type, BOOL clear); - -REG16 bootstrapload(void); - -void bios0x1c(void); - -void bios0x1f(void); - -#if defined(BIOS_IO_EMULATION) -// np21w ver0.86 rev46-69 BIOS I/O emulation -void biosioemu_push8(UINT16 port, UINT8 data); -void biosioemu_push16(UINT16 port, UINT32 data); -void biosioemu_push8_read(UINT16 port); -void biosioemu_push16_read(UINT16 port); -void biosioemu_enq8(UINT16 port, UINT8 data); -void biosioemu_enq16(UINT16 port, UINT32 data); -void biosioemu_enq8_read(UINT16 port); -void biosioemu_enq16_read(UINT16 port); -#endif - -#ifdef __cplusplus -} -#endif - +/** + * @file bios.h + * @brief Interface of BIOS + */ + +#pragma once + +#include "cpumem.h" + +enum { + BIOS_SEG = 0xfd80, + BIOS_BASE = (BIOS_SEG << 4), + + BIOS_TABLE = 0x0040, + + BIOSOFST_ITF = 0x0080, + BIOSOFST_INIT = 0x0084, + + BIOSOFST_09 = 0x0088, // Keyboard + BIOSOFST_0c = 0x008c, // Serial + BIOSOFST_10 = 0x008e, // (PC/AT VGA) + + BIOSOFST_12 = 0x0090, // FDC + BIOSOFST_13 = 0x0094, // FDC + + BIOSOFST_18 = 0x0098, // Common + BIOSOFST_19 = 0x009c, // RS-232C + BIOSOFST_CMT = 0x00a0, // CMT + BIOSOFST_PRT = 0x00a4, // Printer + BIOSOFST_1b = 0x00a8, // Disk + BIOSOFST_1c = 0x00ac, // Timer + BIOSOFST_1f = 0x00b0, // Ext + + BIOSOFST_WAIT = 0x00b4 // FDD waiting + +}; + +#ifdef USE_CUSTOM_HOOKINST +#define HOOKINST_DEFAULT 0x90 // NOP命令 + +typedef struct { + UINT8 hookinst; // BIOSフックする命令 default:NOP(0x90) +} BIOSHOOKINFO; +#endif + +#if defined(BIOS_IO_EMULATION) +// np21w ver0.86 rev46 BIOS I/O emulation + +// XXX: I/Oアクセスは最大20回分くらいあれば十分だと思うので決め打ち +#define BIOSIOEMU_DATA_MAX 20 + +enum { + BIOSIOEMU_FLAG_NONE = 0x0, + BIOSIOEMU_FLAG_MB = 0x1, // ビットを立てるとDX, AX(16bit)またはDX, EAX(32bit)になる(立てなければ8bitアクセス) + BIOSIOEMU_FLAG_READ = 0x2, // ビットを立てると空読みする +}; +typedef struct { + UINT8 flag; // アクセスフラグ(現状ではBIOSIOEMU_FLAG_NONEのみ) + UINT16 port; // 入出力先ポート + UINT32 data; // 出力データ(現状では8bit値のみ有効) +} BIOSIOEMU_IODATA; + +typedef struct { + UINT8 enable; // BIOS I/O エミュレーション有効 + UINT8 count; // 出力データ数 + UINT32 oldEAX; // EAX退避用 + UINT32 oldEDX; // EDX退避用 + BIOSIOEMU_IODATA data[BIOSIOEMU_DATA_MAX]; // 出力先ポートとポートに出力したいデータ。データ順がLIFOなので注意 +} BIOSIOEMU; + +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +// extern BOOL biosrom; + +#ifdef USE_CUSTOM_HOOKINST +extern BIOSHOOKINFO bioshookinfo; +#endif +#if defined(BIOS_IO_EMULATION) +// np21w ver0.86 rev46 BIOS I/O emulation +extern BIOSIOEMU biosioemu; +#endif + +void bios_initialize(void); +UINT MEMCALL biosfunc(UINT32 adrs); +#ifdef SUPPORT_PCI +UINT MEMCALL bios32func(UINT32 adrs); +#endif + +void bios0x09(void); +void bios0x09_init(void); + +void bios0x0c(void); + +void bios0x12(void); +void bios0x13(void); + +void bios0x18(void); +void bios0x18_0a(REG8 mode); +void bios0x18_0c(void); +void bios0x18_10(REG8 curdel); +REG16 bios0x18_14(REG16 seg, REG16 off, REG16 code); +void bios0x18_16(REG8 chr, REG8 atr); +void bios0x18_40(void); +void bios0x18_41(void); +void bios0x18_42(REG8 mode); + +void bios0x19(void); + +void bios0x1a_cmt(void); +void bios0x1a_prt(void); +#if defined(SUPPORT_PCI) +void bios0x1a_pci_part(int is32bit); +void bios0x1a_pci(void); +void bios0x1a_pcipnp(void); +#endif + +void bios0x1b(void); +UINT bios0x1b_wait(void); +void fddbios_equip(REG8 type, BOOL clear); + +REG16 bootstrapload(void); + +void bios0x1c(void); + +void bios0x1f(void); + +#if defined(BIOS_IO_EMULATION) +// np21w ver0.86 rev46-69 BIOS I/O emulation +void biosioemu_push8(UINT16 port, UINT8 data); +void biosioemu_push16(UINT16 port, UINT32 data); +void biosioemu_push8_read(UINT16 port); +void biosioemu_push16_read(UINT16 port); +void biosioemu_enq8(UINT16 port, UINT8 data); +void biosioemu_enq16(UINT16 port, UINT32 data); +void biosioemu_enq8_read(UINT16 port); +void biosioemu_enq16_read(UINT16 port); +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/bios/bios09.c b/bios/bios09.c old mode 100755 new mode 100644 index 986f8797..61e355f6 --- a/bios/bios09.c +++ b/bios/bios09.c @@ -1,134 +1,134 @@ -#include -#include -#include -#include -#include -#include -#include - - -void bios0x09_init(void) { - - iocore_out8(0x43, 0x3a); // keyboard reset-high - iocore_out8(0x43, 0x32); // keyboard reset-low - iocore_out8(0x43, 0x16); // error reset - ZeroMemory(mem + 0x00502, 0x20); - ZeroMemory(mem + 0x00528, 0x13); - SETBIOSMEM16(MEMW_KB_SHIFT_TBL, 0x0e00); - SETBIOSMEM16(MEMW_KB_BUF_HEAD, 0x0502); - SETBIOSMEM16(MEMW_KB_BUF_TAIL, 0x0502); - SETBIOSMEM16(MEMW_KB_CODE_OFF, 0x0e00); - SETBIOSMEM16(MEMW_KB_CODE_SEG, 0xfd80); -} - -static void updateshiftkey(void) { - - UINT8 shiftsts; - UINT base; - - shiftsts = mem[MEMB_SHIFT_STS]; - mem[MEMB_MSW6] &= 0x3f; // KEYBOARD LED - mem[MEMB_MSW6] |= (UINT8)(shiftsts << 5); - if (shiftsts & 0x10) { - base = 7; - } - else if (shiftsts & 0x08) { - base = 6; - } - else { - base = shiftsts & 7; - if (base >= 6) { - base -= 2; - } - } - base = 0x0e00 + (base * 0x60); - SETBIOSMEM16(MEMW_KB_SHIFT_TBL, base); -} - -void bios0x09(void) { - - UINT8 key; - UINT pos; - UINT8 bit; - UINT16 code; - UINT32 base; - UINT kbbuftail; - - key = CPU_AL; - pos = (key & 0x7f) >> 3; - bit = 1 << (key & 7); - if (!(key & 0x80)) { - mem[MEMX_KB_KY_STS + pos] |= bit; - code = 0xffff; - base = GETBIOSMEM16(MEMW_KB_SHIFT_TBL); - base += 0xfd800; - if (key <= 0x51) { - if ((key == 0x51) || (key == 0x35) || (key == 0x3e)) { - code = mem[base + key] << 8; - if (code == 0xff00) { - code = 0xffff; - } - } - else { - code = mem[base + key]; - if (code != 0xff) { - code += key << 8; - } - else { - code = 0xffff; - } - } - } - else if (key < 0x60) { - if (key == 0x5e) { // home - code = 0xae00; - } - } - else { - if (key == 0x60) { -// CPU_INTERRUPT(6, -1); - } - else if (key == 0x61) { -// CPU_INTERRUPT(5, -1); - } - else if (key < 0x70) { - code = mem[base + key - 0x0c] << 8; - if (code == 0xff00) { - code = 0xffff; - } - } - else if (key == 0x70 || key == 0x7d) { // シフトキーの場合左右の区別をしない - mem[MEMB_SHIFT_STS] |= 0x1; - updateshiftkey(); - } - else if (key < 0x75) { - mem[MEMB_SHIFT_STS] |= bit; - updateshiftkey(); - } - } - if (code != 0xffff) { - if (mem[MEMB_KB_COUNT] < 0x10) { - mem[MEMB_KB_COUNT]++; - kbbuftail = GETBIOSMEM16(MEMW_KB_BUF_TAIL); - SETBIOSMEM16(kbbuftail, code); - kbbuftail += 2; - if (kbbuftail >= 0x522) { - kbbuftail = 0x502; - } - SETBIOSMEM16(MEMW_KB_BUF_TAIL, kbbuftail); - } - } - } - else { - mem[MEMX_KB_KY_STS + pos] &= ~bit; - if (((key >= 0xf0) && (key < 0xf5)) || key == 0xfd) { - if (key == 0xf0 || key == 0xfd) { // シフトキーの場合左右の区別をしない - mem[MEMB_SHIFT_STS] &= ~0x1; - }else{ - mem[MEMB_SHIFT_STS] &= ~bit; - } - updateshiftkey(); - } - } -} - +#include +#include +#include +#include +#include +#include +#include + + +void bios0x09_init(void) { + + iocore_out8(0x43, 0x3a); // keyboard reset-high + iocore_out8(0x43, 0x32); // keyboard reset-low + iocore_out8(0x43, 0x16); // error reset + ZeroMemory(mem + 0x00502, 0x20); + ZeroMemory(mem + 0x00528, 0x13); + SETBIOSMEM16(MEMW_KB_SHIFT_TBL, 0x0e00); + SETBIOSMEM16(MEMW_KB_BUF_HEAD, 0x0502); + SETBIOSMEM16(MEMW_KB_BUF_TAIL, 0x0502); + SETBIOSMEM16(MEMW_KB_CODE_OFF, 0x0e00); + SETBIOSMEM16(MEMW_KB_CODE_SEG, 0xfd80); +} + +static void updateshiftkey(void) { + + UINT8 shiftsts; + UINT base; + + shiftsts = mem[MEMB_SHIFT_STS]; + mem[MEMB_MSW6] &= 0x3f; // KEYBOARD LED + mem[MEMB_MSW6] |= (UINT8)(shiftsts << 5); + if (shiftsts & 0x10) { + base = 7; + } + else if (shiftsts & 0x08) { + base = 6; + } + else { + base = shiftsts & 7; + if (base >= 6) { + base -= 2; + } + } + base = 0x0e00 + (base * 0x60); + SETBIOSMEM16(MEMW_KB_SHIFT_TBL, base); +} + +void bios0x09(void) { + + UINT8 key; + UINT pos; + UINT8 bit; + UINT16 code; + UINT32 base; + UINT kbbuftail; + + key = CPU_AL; + pos = (key & 0x7f) >> 3; + bit = 1 << (key & 7); + if (!(key & 0x80)) { + mem[MEMX_KB_KY_STS + pos] |= bit; + code = 0xffff; + base = GETBIOSMEM16(MEMW_KB_SHIFT_TBL); + base += 0xfd800; + if (key <= 0x51) { + if ((key == 0x51) || (key == 0x35) || (key == 0x3e)) { + code = mem[base + key] << 8; + if (code == 0xff00) { + code = 0xffff; + } + } + else { + code = mem[base + key]; + if (code != 0xff) { + code += key << 8; + } + else { + code = 0xffff; + } + } + } + else if (key < 0x60) { + if (key == 0x5e) { // home + code = 0xae00; + } + } + else { + if (key == 0x60) { +// CPU_INTERRUPT(6, -1); + } + else if (key == 0x61) { +// CPU_INTERRUPT(5, -1); + } + else if (key < 0x70) { + code = mem[base + key - 0x0c] << 8; + if (code == 0xff00) { + code = 0xffff; + } + } + else if (key == 0x70 || key == 0x7d) { // シフトキーの場合左右の区別をしない + mem[MEMB_SHIFT_STS] |= 0x1; + updateshiftkey(); + } + else if (key < 0x75) { + mem[MEMB_SHIFT_STS] |= bit; + updateshiftkey(); + } + } + if (code != 0xffff) { + if (mem[MEMB_KB_COUNT] < 0x10) { + mem[MEMB_KB_COUNT]++; + kbbuftail = GETBIOSMEM16(MEMW_KB_BUF_TAIL); + SETBIOSMEM16(kbbuftail, code); + kbbuftail += 2; + if (kbbuftail >= 0x522) { + kbbuftail = 0x502; + } + SETBIOSMEM16(MEMW_KB_BUF_TAIL, kbbuftail); + } + } + } + else { + mem[MEMX_KB_KY_STS + pos] &= ~bit; + if (((key >= 0xf0) && (key < 0xf5)) || key == 0xfd) { + if (key == 0xf0 || key == 0xfd) { // シフトキーの場合左右の区別をしない + mem[MEMB_SHIFT_STS] &= ~0x1; + }else{ + mem[MEMB_SHIFT_STS] &= ~bit; + } + updateshiftkey(); + } + } +} + diff --git a/bios/bios0c.c b/bios/bios0c.c old mode 100755 new mode 100644 index fa8a0677..450f52f1 --- a/bios/bios0c.c +++ b/bios/bios0c.c @@ -1,99 +1,99 @@ -#include -#include -#include -#include -#include -#include -#include "rsbios.h" - - -void bios0x0c(void) { - - UINT16 doff; - UINT16 dseg; - REG8 flag; - UINT8 data; - UINT8 status; - REG16 pos; - REG16 cnt; - - doff = GETBIOSMEM16(MEMW_RS_CH0_OFST); - dseg = GETBIOSMEM16(MEMW_RS_CH0_SEG); - - flag = MEMR_READ8(dseg, doff + R_FLAG); - data = iocore_inp8(0x30); // データ引き取り - status = iocore_inp8(0x32) & 0xfc; // ステータス - status |= (iocore_inp8(0x33) & 3); - -#if 0 - if (status & 0x38) { - iocore_out8(0x32, flag | 0x10); - } -#endif - - if (!(flag & RFLAG_BFULL)) { - // SI/SO変換 - if (mem[MEMB_RS_S_FLAG] & 0x80) { - if (data >= 0x20) { - if (mem[MEMB_RS_S_FLAG] & 0x10) { - data |= 0x80; - } - else { - data &= 0x7f; - } - } - else if (data == RSCODE_SO) { - mem[MEMB_RS_S_FLAG] |= 0x10; - iocore_out8(0x00, 0x20); - return; - } - else if (data == RSCODE_SI) { - mem[MEMB_RS_S_FLAG] &= ~0x10; - iocore_out8(0x00, 0x20); - return; - } - } - - // DELコードの扱い - if (mem[MEMB_RS_D_FLAG] & 0x01) { // CH0 -> bit0 - if (((data & 0x7f) == 0x7f) && (mem[MEMB_MSW3] & 0x80)) { - data = 0; - } - } - // データ投棄 - pos = MEMR_READ16(dseg, doff + R_PUTP); - MEMR_WRITE16(dseg, pos, (UINT16)((data << 8) | status)); - - // 次のポインタをストア - pos = (UINT16)(pos + 2); - if (pos >= MEMR_READ16(dseg, doff + R_TAILP)) { - pos = MEMR_READ16(dseg, doff + R_HEADP); - } - MEMR_WRITE16(dseg, doff + R_PUTP, pos); - - // カウンタのインクリメント - cnt = (UINT16)(MEMR_READ16(dseg, doff + R_CNT) + 1); - MEMR_WRITE16(dseg, doff + R_CNT, cnt); - - // オーバーフローを見張る - if (pos == MEMR_READ16(dseg, doff + R_GETP)) { - flag |= RFLAG_BFULL; - } - - // XOFFを送信? - if (((flag & (RFLAG_XON | RFLAG_XOFF)) == RFLAG_XON) && - (cnt >= MEMR_READ16(dseg, doff + R_XON))) { - iocore_out8(0x30, RSCODE_XOFF); - flag |= RFLAG_XOFF; - } - } - else { - MEMR_WRITE8(dseg, doff + R_CMD, - (REG8)(MEMR_READ8(dseg, doff + R_CMD) | RFLAG_BOVF)); - } - MEMR_WRITE8(dseg, doff + R_INT, - (REG8)(MEMR_READ8(dseg, doff + R_INT) | RINT_INT)); - MEMR_WRITE8(dseg, doff + R_FLAG, flag); - iocore_out8(0x00, 0x20); -} - +#include +#include +#include +#include +#include +#include +#include "rsbios.h" + + +void bios0x0c(void) { + + UINT16 doff; + UINT16 dseg; + REG8 flag; + UINT8 data; + UINT8 status; + REG16 pos; + REG16 cnt; + + doff = GETBIOSMEM16(MEMW_RS_CH0_OFST); + dseg = GETBIOSMEM16(MEMW_RS_CH0_SEG); + + flag = MEMR_READ8(dseg, doff + R_FLAG); + data = iocore_inp8(0x30); // データ引き取り + status = iocore_inp8(0x32) & 0xfc; // ステータス + status |= (iocore_inp8(0x33) & 3); + +#if 0 + if (status & 0x38) { + iocore_out8(0x32, flag | 0x10); + } +#endif + + if (!(flag & RFLAG_BFULL)) { + // SI/SO変換 + if (mem[MEMB_RS_S_FLAG] & 0x80) { + if (data >= 0x20) { + if (mem[MEMB_RS_S_FLAG] & 0x10) { + data |= 0x80; + } + else { + data &= 0x7f; + } + } + else if (data == RSCODE_SO) { + mem[MEMB_RS_S_FLAG] |= 0x10; + iocore_out8(0x00, 0x20); + return; + } + else if (data == RSCODE_SI) { + mem[MEMB_RS_S_FLAG] &= ~0x10; + iocore_out8(0x00, 0x20); + return; + } + } + + // DELコードの扱い + if (mem[MEMB_RS_D_FLAG] & 0x01) { // CH0 -> bit0 + if (((data & 0x7f) == 0x7f) && (mem[MEMB_MSW3] & 0x80)) { + data = 0; + } + } + // データ投棄 + pos = MEMR_READ16(dseg, doff + R_PUTP); + MEMR_WRITE16(dseg, pos, (UINT16)((data << 8) | status)); + + // 次のポインタをストア + pos = (UINT16)(pos + 2); + if (pos >= MEMR_READ16(dseg, doff + R_TAILP)) { + pos = MEMR_READ16(dseg, doff + R_HEADP); + } + MEMR_WRITE16(dseg, doff + R_PUTP, pos); + + // カウンタのインクリメント + cnt = (UINT16)(MEMR_READ16(dseg, doff + R_CNT) + 1); + MEMR_WRITE16(dseg, doff + R_CNT, cnt); + + // オーバーフローを見張る + if (pos == MEMR_READ16(dseg, doff + R_GETP)) { + flag |= RFLAG_BFULL; + } + + // XOFFを送信? + if (((flag & (RFLAG_XON | RFLAG_XOFF)) == RFLAG_XON) && + (cnt >= MEMR_READ16(dseg, doff + R_XON))) { + iocore_out8(0x30, RSCODE_XOFF); + flag |= RFLAG_XOFF; + } + } + else { + MEMR_WRITE8(dseg, doff + R_CMD, + (REG8)(MEMR_READ8(dseg, doff + R_CMD) | RFLAG_BOVF)); + } + MEMR_WRITE8(dseg, doff + R_INT, + (REG8)(MEMR_READ8(dseg, doff + R_INT) | RINT_INT)); + MEMR_WRITE8(dseg, doff + R_FLAG, flag); + iocore_out8(0x00, 0x20); +} + diff --git a/bios/bios12.c b/bios/bios12.c old mode 100755 new mode 100644 index e1d35778..2a7731f9 --- a/bios/bios12.c +++ b/bios/bios12.c @@ -1,71 +1,71 @@ -#include -#include -#include -#include -#include -#include - - -#define baseport 0x00c8 - -void bios0x12(void) { - - UINT8 status; - UINT8 result; - UINT8 *p; - UINT8 drv; - UINT8 drvbit; - -// TRACE_("BIOS", 0x12); - iocore_out8(0x08, 0x20); - if (!pic.pi[1].isr) { - iocore_out8(0x00, 0x20); - } - - /* @TODO: 本来はセンスするまでベクタをセットしてはいけない (ココに来てはならない) */ - if (((baseport >> 4) ^ fdc.chgreg) & 1) - { - return; - } - - status = iocore_inp8(baseport); - while(1) { - if (!(status & FDCSTAT_CB)) { - if ((status & (FDCSTAT_RQM | FDCSTAT_DIO)) != FDCSTAT_RQM) { - break; - } - iocore_out8(baseport+2, 0x08); - status = iocore_inp8(baseport); - } - if ((status & (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) - != (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) { - break; - } - result = iocore_inp8(baseport+2); - if (result == FDCRLT_IC1) { - if (mem[0x005d7]) { - mem[0x005d7]--; - } - break; - } - drv = result & 3; - drvbit = 0x10 << drv; - if (result & (FDCRLT_IC1 | FDCRLT_SE)) { - p = mem + 0x005d8 + (drv * 2); - } - else { - p = mem + 0x005d0; - } - while(1) { - *p++ = result; - status = iocore_inp8(baseport); - if ((status & (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) - != (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) { - break; - } - result = iocore_inp8(baseport+2); - } - mem[MEMB_DISK_INTH] |= drvbit; - } -} - +#include +#include +#include +#include +#include +#include + + +#define baseport 0x00c8 + +void bios0x12(void) { + + UINT8 status; + UINT8 result; + UINT8 *p; + UINT8 drv; + UINT8 drvbit; + +// TRACE_("BIOS", 0x12); + iocore_out8(0x08, 0x20); + if (!pic.pi[1].isr) { + iocore_out8(0x00, 0x20); + } + + /* @TODO: 本来はセンスするまでベクタをセットしてはいけない (ココに来てはならない) */ + if (((baseport >> 4) ^ fdc.chgreg) & 1) + { + return; + } + + status = iocore_inp8(baseport); + while(1) { + if (!(status & FDCSTAT_CB)) { + if ((status & (FDCSTAT_RQM | FDCSTAT_DIO)) != FDCSTAT_RQM) { + break; + } + iocore_out8(baseport+2, 0x08); + status = iocore_inp8(baseport); + } + if ((status & (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) + != (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) { + break; + } + result = iocore_inp8(baseport+2); + if (result == FDCRLT_IC1) { + if (mem[0x005d7]) { + mem[0x005d7]--; + } + break; + } + drv = result & 3; + drvbit = 0x10 << drv; + if (result & (FDCRLT_IC1 | FDCRLT_SE)) { + p = mem + 0x005d8 + (drv * 2); + } + else { + p = mem + 0x005d0; + } + while(1) { + *p++ = result; + status = iocore_inp8(baseport); + if ((status & (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) + != (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) { + break; + } + result = iocore_inp8(baseport+2); + } + mem[MEMB_DISK_INTH] |= drvbit; + } +} + diff --git a/bios/bios13.c b/bios/bios13.c old mode 100755 new mode 100644 index 412e8a1e..f6c51e5d --- a/bios/bios13.c +++ b/bios/bios13.c @@ -1,71 +1,71 @@ -#include -#include -#include -#include -#include -#include - - -#define baseport 0x0090 - -void bios0x13(void) { - - UINT8 status; - UINT8 result; - UINT8 *p; - UINT8 drv; - UINT8 drvbit; - -// TRACE_("BIOS", 0x13); - iocore_out8(0x08, 0x20); - if (!pic.pi[1].isr) { - iocore_out8(0x00, 0x20); - } - - status = iocore_inp8(baseport); - while(1) { - if (!(status & FDCSTAT_CB)) { - if ((status & (FDCSTAT_RQM | FDCSTAT_DIO)) != FDCSTAT_RQM) { - break; - } - iocore_out8(baseport+2, 0x08); - status = iocore_inp8(baseport); - } - if ((status & (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) - != (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) { - break; - } - result = iocore_inp8(baseport+2); - if (result == FDCRLT_IC1) { - break; - } - drv = result & 3; - drvbit = 1 << drv; -#if 0 - if (result & FDCRLT_IC1) { - if (mem[MEMB_DISK_INTL] & drvbit) { - continue; - } - drvbit = 0; - } -#endif - p = mem + MEMX_DISK_RESULT + (drv * 8); - while(1) { - *p++ = result; - status = iocore_inp8(baseport); - if ((status & (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) - != (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) { - break; - } - result = iocore_inp8(baseport+2); - } - mem[MEMB_DISK_INTL] |= drvbit; - } - if (mem[MEMB_SYS_TYPE] & 0x10) { - if (mem[0x00485]) { - if (!(--mem[0x00485])) { - mem[0x005a4] |= 0x0f; - } - } - } -} +#include +#include +#include +#include +#include +#include + + +#define baseport 0x0090 + +void bios0x13(void) { + + UINT8 status; + UINT8 result; + UINT8 *p; + UINT8 drv; + UINT8 drvbit; + +// TRACE_("BIOS", 0x13); + iocore_out8(0x08, 0x20); + if (!pic.pi[1].isr) { + iocore_out8(0x00, 0x20); + } + + status = iocore_inp8(baseport); + while(1) { + if (!(status & FDCSTAT_CB)) { + if ((status & (FDCSTAT_RQM | FDCSTAT_DIO)) != FDCSTAT_RQM) { + break; + } + iocore_out8(baseport+2, 0x08); + status = iocore_inp8(baseport); + } + if ((status & (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) + != (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) { + break; + } + result = iocore_inp8(baseport+2); + if (result == FDCRLT_IC1) { + break; + } + drv = result & 3; + drvbit = 1 << drv; +#if 0 + if (result & FDCRLT_IC1) { + if (mem[MEMB_DISK_INTL] & drvbit) { + continue; + } + drvbit = 0; + } +#endif + p = mem + MEMX_DISK_RESULT + (drv * 8); + while(1) { + *p++ = result; + status = iocore_inp8(baseport); + if ((status & (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) + != (FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB)) { + break; + } + result = iocore_inp8(baseport+2); + } + mem[MEMB_DISK_INTL] |= drvbit; + } + if (mem[MEMB_SYS_TYPE] & 0x10) { + if (mem[0x00485]) { + if (!(--mem[0x00485])) { + mem[0x005a4] |= 0x0f; + } + } + } +} diff --git a/bios/bios18.c b/bios/bios18.c index 61a60dce..455c06cd 100644 --- a/bios/bios18.c +++ b/bios/bios18.c @@ -1,1319 +1,1319 @@ -#include -#include -#include -#include -#include -#include -#include -#include - - -typedef struct { - UINT8 GBON_PTN; - UINT8 GBBCC; - UINT8 GBDOTU; - UINT8 GBDSP; - UINT8 GBCPC[4]; - UINT8 GBSX1[2]; - UINT8 GBSY1[2]; - UINT8 GBLNG1[2]; - UINT8 GBWDPA[2]; - UINT8 GBRBUF[2][3]; - UINT8 GBSX2[2]; - UINT8 GBSY2[2]; - UINT8 GBMDOT[2]; - UINT8 GBCIR[2]; - UINT8 GBLNG2[2]; - UINT8 GBMDOTI[8]; - UINT8 GBDTYP; - UINT8 GBFILL; -} UCWTBL; - -typedef struct { - UINT8 raster; - UINT8 pl; - UINT8 bl; - UINT8 cl; -} CRTDATA; - -static const UINT8 modenum[4] = {3, 1, 0, 2}; - -static const CRTDATA crtdata[7] = { - {0x09, 0x1f, 0x08, 0x08}, // 200-20 - {0x07, 0x00, 0x07, 0x08}, // 200-25 - {0x13, 0x1e, 0x11, 0x10}, // 400-20 - {0x0f, 0x00, 0x0f, 0x10}, // 400-25 - {0x17, 0x1c, 0x13, 0x10}, // 480-20 - {0x12, 0x1f, 0x11, 0x10}, // 480-25 - {0x0f, 0x00, 0x0f, 0x10}}; // 480-30 - -#if defined(SUPPORT_CRT31KHZ) -static const UINT8 gdcmastersync[6][8] = { - {0x10,0x4e,0x07,0x25,0x0d,0x0f,0xc8,0x94}, /* 15 */ - {0x10,0x4e,0x07,0x25,0x07,0x07,0x90,0x65}, /* 24 */ - {0x10,0x4e,0x47,0x0c,0x07,0x0d,0x90,0x89}, /* 31 */ - {0x10,0x4e,0x4b,0x0c,0x03,0x06,0xe0,0x95}, /* 31-480:20 */ - {0x10,0x4e,0x4b,0x0c,0x03,0x0b,0xdb,0x95}, /* 31-480:25 */ - {0x10,0x4e,0x4b,0x0c,0x03,0x06,0xe0,0x95}}; /* 31-480:30 */ -#endif /* defined(SUPPORT_CRT31KHZ) */ - -static const UINT8 gdcslavesync[6][8] = { - {0x02,0x26,0x03,0x11,0x86,0x0f,0xc8,0x94}, // 15-L - {0x02,0x4e,0x4b,0x0c,0x83,0x06,0xe0,0x95}, // 31-H - {0x02,0x26,0x03,0x11,0x83,0x07,0x90,0x65}, // 24-L - {0x02,0x4e,0x07,0x25,0x87,0x07,0x90,0x65}, // 24-M - {0x02,0x26,0x41,0x0c,0x83,0x0d,0x90,0x89}, // 31-L - {0x02,0x4e,0x47,0x0c,0x87,0x0d,0x90,0x89}}; // 31-M - -typedef struct { - UINT8 lr; - UINT8 cfi; -} CSRFORM; - -static const CSRFORM csrform[4] = { - {0x07, 0x3b}, {0x09, 0x4b}, - {0x0f, 0x7b}, {0x13, 0x9b}}; - -#if 0 -static const UINT8 sync200l[8] = {0x02,0x26,0x03,0x11,0x86,0x0f,0xc8,0x94}; -static const UINT8 sync200m[8] = {0x02,0x26,0x03,0x11,0x83,0x07,0x90,0x65}; -static const UINT8 sync400m[8] = {0x02,0x4e,0x07,0x25,0x87,0x07,0x90,0x65}; -#endif /* 0 */ - -static UINT16 keyget(void) { - - UINT pos; - UINT kbbufhead; - - if (mem[MEMB_KB_COUNT]) { - mem[MEMB_KB_COUNT]--; - pos = GETBIOSMEM16(MEMW_KB_BUF_HEAD); - kbbufhead = pos + 2; - if (kbbufhead >= 0x522) { - kbbufhead = 0x502; - } - SETBIOSMEM16(MEMW_KB_BUF_HEAD, kbbufhead); - return(GETBIOSMEM16(pos)); - } - return(0xffff); -} - - -// ---- master - -void bios0x18_0a(REG8 mode) { - -const CRTDATA *crt; - - gdc_forceready(GDCWORK_MASTER); - - gdc.mode1 &= ~(0x2d); - mem[MEMB_CRT_STS_FLAG] = mode; - crt = crtdata; - if (!(pccore.dipsw[0] & 1)) { - mem[MEMB_CRT_STS_FLAG] |= 0x80; - gdc.mode1 |= 0x08; - crt += 2; - } - if (!(mode & 0x01)) { - crt += 1; // 25�s - } - if (mode & 0x02) { - gdc.mode1 |= 0x04; // 40�� - } - if (mode & 0x04) { - gdc.mode1 |= 0x01; // �A�g���r���[�g - } - if (mode & 0x08) { - gdc.mode1 |= 0x20; // �R�[�h�A�N�Z�X - } - mem[MEMB_CRT_RASTER] = crt->raster; - crtc.reg.pl = crt->pl; - crtc.reg.bl = crt->bl; - crtc.reg.cl = crt->cl; - crtc.reg.ssl = 0; - gdc_restorekacmode(); - bios0x18_10(0); -//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) -// // np21w ver0.86 rev62 BIOS I/O emulation -// if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { -// if (!(pccore.dipsw[0] & 1)) { -// biosioemu_enq8(0x68, 0x08|0x01); -// }else{ -// biosioemu_enq8(0x68, 0x08|0x00); -// } -// if (mode & 0x02) { -// biosioemu_enq8(0x68, 0x04|0x01); -// }else{ -// biosioemu_enq8(0x68, 0x04|0x00); -// } -// if (mode & 0x04) { -// biosioemu_enq8(0x68, 0x00|0x01); -// }else{ -// biosioemu_enq8(0x68, 0x00|0x00); -// } -// if (mode & 0x08) { -// biosioemu_enq8(0x68, 0x20|0x01); -// }else{ -// biosioemu_enq8(0x68, 0x20|0x00); -// } -// } -//#endif -} - -void bios0x18_0c(void) { - - if (!(gdcs.textdisp & GDCSCRN_ENABLE)) { - gdcs.textdisp |= GDCSCRN_ENABLE; - pcstat.screenupdate |= 2; - } -} - -static void bios0x18_0f(UINT seg, UINT off, REG8 num, REG8 cnt) { - - UINT8 *p; - UINT raster; - UINT t; - - SETBIOSMEM16(0x0053e, (UINT16)off); - SETBIOSMEM16(0x00540, (UINT16)seg); - mem[0x00547] = num; - mem[0x0053D] = cnt; - p = gdc.m.para + GDC_SCROLL + (num << 2); - -#if defined(SUPPORT_CRT31KHZ) - if (mem[MEMB_CRT_BIOS] & 0x80) { - raster = (mem[MEMB_CRT_RASTER] + 1) << 4; - } - else { -#endif - if (!(mem[MEMB_CRT_STS_FLAG] & 0x01)) { // 25 - raster = 8 << 4; - } - else { // 20 - raster = 16 << 4; - } - if (mem[MEMB_CRT_STS_FLAG] & 0x80) { - raster <<= 1; - } -#if defined(SUPPORT_CRT31KHZ) - } -#endif - - while((cnt--) && (p < (gdc.m.para + GDC_SCROLL + 0x10))) { - t = MEMR_READ16(seg, off); - t >>= 1; - STOREINTELWORD(p, t); - t = MEMR_READ16(seg, off + 2); - t *= raster; - STOREINTELWORD(p + 2, t); - off += 4; - p += 4; - } - gdcs.textdisp |= GDCSCRN_ALLDRAW2; - pcstat.screenupdate |= 2; -} - -void bios0x18_10(REG8 curdel) { - - UINT8 sts; - UINT pos; - - sts = mem[MEMB_CRT_STS_FLAG]; - mem[MEMB_CRT_STS_FLAG] = sts & (~0x40); - pos = sts & 0x01; - if (sts & 0x80) { - pos += 2; - } - mem[MEMB_CRT_CNT] = (curdel << 5); - gdc.m.para[GDC_CSRFORM + 0] = csrform[pos].lr; - gdc.m.para[GDC_CSRFORM + 1] = curdel << 5; - gdc.m.para[GDC_CSRFORM + 2] = csrform[pos].cfi; - gdcs.textdisp |= GDCSCRN_ALLDRAW2 | GDCSCRN_EXT; -} - -REG16 bios0x18_14(REG16 seg, REG16 off, REG16 code) { - - UINT16 size; -const UINT8 *p; - UINT8 buf[32]; - UINT i; - - switch(code >> 8) { - case 0x00: // 8x8 - size = 0x0101; - MEMR_WRITE16(seg, off, 0x0101); - p = fontrom + 0x82000 + ((code & 0xff) << 4); - MEMR_WRITES(seg, off + 2, p, 8); - break; - -// case 0x28: - case 0x29: // 8x16 KANJI - case 0x2a: - case 0x2b: - size = 0x0102; - MEMR_WRITE16(seg, off, 0x0102); - p = fontrom; - p += (code & 0x7f) << 12; - p += (((code >> 8) - 0x20) & 0x7f) << 4; - MEMR_WRITES(seg, off + 2, p, 16); - break; - - case 0x80: // 8x16 ANK - size = 0x0102; - p = fontrom + 0x80000 + ((code & 0xff) << 4); - MEMR_WRITES(seg, off + 2, p, 16); - break; - - default: - size = 0x0202; - p = fontrom; - p += (code & 0x7f) << 12; - p += (((code >> 8) - 0x20) & 0x7f) << 4; - for (i=0; i<16; i++, p++) { - buf[i*2+0] = *p; - buf[i*2+1] = *(p+0x800); - } - MEMR_WRITES(seg, off + 2, buf, 32); - break; - } - MEMR_WRITE16(seg, off, size); - return(size); -} - -static void bios0x18_1a(REG16 seg, REG16 off, REG16 code) { - - UINT8 *p; - UINT8 buf[32]; - UINT i; - - if (((code >> 8) & 0x7e) == 0x76) { - MEMR_READS(seg, off + 2, buf, 32); - p = fontrom; - p += (code & 0x7f) << 12; - p += (((code >> 8) - 0x20) & 0x7f) << 4; - for (i=0; i<16; i++, p++) { - *p = buf[i*2+0]; - *(p+0x800) = buf[i*2+1]; - } - cgwindow.writable |= 0x80; - } -} - -void bios0x18_16(REG8 chr, REG8 atr) { - - UINT32 i; - - for (i=0xa0000; i<0xa2000; i+=2) { - mem[i+0] = chr; - mem[i+1] = 0; - } - for (; i<0xa3fe0; i+=2) { - mem[i] = atr; - } - gdcs.textdisp |= GDCSCRN_ALLDRAW; -} - - -// ---- 31khz - -#if defined(SUPPORT_CRT31KHZ) -static REG8 bios0x18_30(REG8 rate, REG8 scrn) { - - int crt; - int master; - int slave; -const CRTDATA *p; - - if (((rate & 0xf8) != 0x08) || (scrn & (~0x33)) || ((scrn & 3) == 3)) { - return(0); - } - if ((scrn & 0x30) == 0x30) { // 640x480 -#if defined(SUPPORT_PC9821) - //if (rate & 4) { - if (rate & 0xc) { // np21w ver0.86 rev47 workaround -//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) -// // XXX: Windows3.1 DOS�v�����v�g�p ������� -// if (CPU_STAT_PM && CPU_STAT_VM86) { -// biosioemu_enq8(0x6a, 0x21); -// mem[MEMB_PRXDUPD] |= 0x80; -// crt = 4; -// master = 3 + (scrn & 3); -// slave = 1; -// biosioemu_enq8(0x6a, 0x69); -// }else -//#endif - { - gdc_analogext(TRUE); - mem[MEMB_PRXDUPD] |= 0x80; - crt = 4; - master = 3 + (scrn & 3); - slave = 1; - gdc.analog |= (1 << GDCANALOG_256E); - } - } - else -#endif - return(0); - } - else { - if ((scrn & 3) >= 2) { - return(0); - } - if (rate & 4) { // 31khz - crt = 2; - master = 2; - slave = 4; - } - else if (mem[MEMB_PRXCRT] & 0x40) { // 24khz - crt = 2; - master = 1; - slave = 2; - } - else { - crt = 0; - master = 0; - slave = 0; - } - if ((scrn & 0x20) && (mem[MEMB_PRXDUPD] & 0x04)) { - slave += 1; - } -#if defined(SUPPORT_PC9821) - else { -//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) -// // XXX: Windows3.1 DOS�v�����v�g�p ������� -// if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { -// biosioemu_enq8(0x6a, 0x20); // ����͑ʖ� -// }else -//#endif - { - gdc_analogext(FALSE); - } - mem[MEMB_PRXDUPD] &= ~0x80; - } -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - // XXX: Windows3.1 DOS�v�����v�g�p ������� - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - biosioemu_enq8(0x6a, 0x68); - }else -#endif - { - gdc.analog &= ~(1 << (GDCANALOG_256E)); - } -#endif - } - crt += (scrn & 3); - -//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) -// // XXX: Windows3.1 DOS�v�����v�g�p ������� -// if (CPU_STAT_PM && CPU_STAT_VM86) { -// if (rate & 4) { -// biosioemu_push8(0x09a8, 0x01); -// } -// else { -// biosioemu_push8(0x09a8, 0x00); -// } -// }else -//#endif - { - if (rate & 4) { - gdc.display |= (1 << GDCDISP_31); - } - else { - gdc.display &= ~(1 << GDCDISP_31); - } - } - - CopyMemory(gdc.m.para + GDC_SYNC, gdcmastersync[master], 8); - ZeroMemory(gdc.m.para + GDC_SCROLL, 4); - gdc.m.para[GDC_PITCH] = 80; - - p = crtdata + crt; - gdc.m.para[GDC_CSRFORM + 0] = p->raster; - gdc.m.para[GDC_CSRFORM + 1] = 0; - gdc.m.para[GDC_CSRFORM + 2] = (p->raster << 3) + 3; - crtc.reg.pl = p->pl; - crtc.reg.bl = p->bl; - crtc.reg.cl = p->cl; - crtc.reg.ssl = 0; - crtc.reg.sur = 1; - crtc.reg.sdr = 0; - - CopyMemory(gdc.s.para + GDC_SYNC, gdcslavesync[slave], 8); - ZeroMemory(gdc.s.para + GDC_SCROLL, 4); - if (slave & 1) { -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - // XXX: Windows3.1 DOS�v�����v�g�p ������� - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - biosioemu_enq8(0xa2, CMD_PITCH); - biosioemu_enq8(0xa0, 80); - }else -#endif - { - gdc.s.para[GDC_PITCH] = 80; - } - gdc.clock |= 3; - mem[MEMB_PRXDUPD] |= 0x04; - gdc.s.para[GDC_SCROLL+3] = 0x40; - } - else { -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - // XXX: Windows3.1 DOS�v�����v�g�p ������� - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - biosioemu_enq8(0xa2, CMD_PITCH); - biosioemu_enq8(0xa0, 40); - }else -#endif - { - gdc.s.para[GDC_PITCH] = 40; - } - gdc.clock &= ~3; - mem[MEMB_PRXDUPD] &= ~0x04; - } - if ((scrn & 0x30) == 0x10) { - gdc.s.para[GDC_SCROLL+0] = (200*40) & 0xff; - gdc.s.para[GDC_SCROLL+1] = (200*40) >> 8; - } - if ((scrn & 0x20) || (!(mem[MEMB_PRXCRT] & 0x40))) { - gdc.mode1 &= ~(0x10); - gdc.s.para[GDC_CSRFORM] = 0; - } - else { - gdc.mode1 |= 0x10; - gdc.s.para[GDC_CSRFORM] = 1; - } - -#if defined(BIOS_IO_EMULATION) - // XXX: Windows3.1 DOS�v�����v�g�p ������� - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - biosioemu_enq8(0x6a, 0x40 | ((gdc.display & (1 << GDCDISP_PLAZMA)) ? 1 : 0)); // gdcs.textdisp |= GDCSCRN_EXT; �̑���E�E�E - biosioemu_enq8(0x6a, 0x82 | (gdc.clock & 1)); // gdcs.grphdisp |= GDCSCRN_EXT; - biosioemu_enq8(0x62, CMD_STOP); // gdcs.textdisp &= ~GDCSCRN_ENABLE; pcstat.screenupdate |= 2; - }else -#endif - { - gdcs.textdisp &= ~GDCSCRN_ENABLE; - gdcs.textdisp |= GDCSCRN_EXT; - gdcs.grphdisp |= GDCSCRN_EXT; - pcstat.screenupdate |= 2; - } - gdcs.textdisp |= GDCSCRN_ALLDRAW2; - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - - mem[0x597] &= ~3; - mem[0x597] |= (scrn >> 4) & 3; - mem[MEMB_CRT_STS_FLAG] &= ~0x11; - if (!(scrn & 1)) { - mem[MEMB_CRT_STS_FLAG] |= 0x01; - } - if (scrn & 2) { - mem[MEMB_CRT_STS_FLAG] |= 0x10; - } - return(5); // �Ō��GDC�֑������f�[�^�c -} - -static REG8 bios0x18_31al(void) { - - UINT8 rate; - - rate = 0x08 + ((gdc.display >> (GDCDISP_31 - 5)) & 4); - return(rate); -} - -static REG8 bios0x18_31bh(void) { - - UINT8 scrn; - - scrn = (mem[0x597] & 3) << 4; - if (!(mem[MEMB_CRT_STS_FLAG] & 0x01)) { - scrn |= 0x01; - } - if (mem[MEMB_CRT_STS_FLAG] & 0x10) { - scrn |= 0x02; - } - return(scrn); -} -#endif - - -// ---- slave - -void bios0x18_40(void) { - - gdc_forceready(GDCWORK_SLAVE); - if (!(gdcs.grphdisp & GDCSCRN_ENABLE)) { - gdcs.grphdisp |= GDCSCRN_ENABLE; - pcstat.screenupdate |= 2; - } - mem[MEMB_PRXCRT] |= 0x80; -} - -void bios0x18_41(void) { - - gdc_forceready(GDCWORK_SLAVE); - if (gdcs.grphdisp & GDCSCRN_ENABLE) { - gdcs.grphdisp &= ~(GDCSCRN_ENABLE); - pcstat.screenupdate |= 2; - } - mem[MEMB_PRXCRT] &= 0x7f; -} - -void bios0x18_42(REG8 mode) { - - UINT8 crtmode; -#if defined(SUPPORT_CRT31KHZ) - UINT8 rate; - UINT8 scrn; -#endif - int slave; - - gdc_forceready(GDCWORK_MASTER); - gdc_forceready(GDCWORK_SLAVE); - - crtmode = modenum[mode >> 6]; -#if defined(SUPPORT_CRT31KHZ) - rate = bios0x18_31al(); - scrn = bios0x18_31bh(); - if ((mem[MEMB_CRT_BIOS] & 0x80) && - (((scrn & 0x30) == 0x30) || (crtmode == 3))) { - bios0x18_30(rate, (REG8)((crtmode << 4) + 1)); - } - else { -#endif - ZeroMemory(gdc.s.para + GDC_SCROLL, 4); - if (crtmode == 2) { // ALL - crtmode = 2; - if ((mem[MEMB_PRXDUPD] & 0x24) == 0x20) { - mem[MEMB_PRXDUPD] ^= 4; - gdc.clock |= 3; - CopyMemory(gdc.s.para + GDC_SYNC, gdcslavesync[3], 8); - gdc.s.para[GDC_PITCH] = 80; - gdcs.grphdisp |= GDCSCRN_EXT; - mem[MEMB_PRXDUPD] |= 0x08; - } -//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) -// if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { -// biosioemu_enq8(0x6a, 0x83); -// biosioemu_enq8(0x6a, 0x85); -// } -//#endif - } - else { - if ((mem[MEMB_PRXDUPD] & 0x24) == 0x24) { - mem[MEMB_PRXDUPD] ^= 4; - gdc.clock &= ~3; -#if defined(SUPPORT_CRT31KHZ) - if (rate & 4) slave = 4; - else -#endif - slave = (mem[MEMB_PRXCRT] & 0x40)?2:0; - CopyMemory(gdc.s.para + GDC_SYNC, gdcslavesync[slave], 8); - gdc.s.para[GDC_PITCH] = 40; - gdcs.grphdisp |= GDCSCRN_EXT; - mem[MEMB_PRXDUPD] |= 0x08; -//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) -// if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { -// biosioemu_enq8(0x6a, 0x82); -// biosioemu_enq8(0x6a, 0x84); -// } -//#endif - } - if (crtmode & 1) { // UPPER - gdc.s.para[GDC_SCROLL+0] = (200*40) & 0xff; - gdc.s.para[GDC_SCROLL+1] = (200*40) >> 8; - } - } - if (mem[MEMB_PRXDUPD] & 4) { - gdc.s.para[GDC_SCROLL+3] = 0x40; - } - if ((crtmode == 2) || (!(mem[MEMB_PRXCRT] & 0x40))) { -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - biosioemu_enq8(0x68, 0x08); - biosioemu_enq8(0xa2, CMD_CSRFORM); - biosioemu_enq8(0xa0, 0x40); - biosioemu_enq8(0xa0, 0x00); - biosioemu_enq8(0xa0, 0x00); - }else -#endif - { - gdc.mode1 &= ~(0x10); - gdc.s.para[GDC_CSRFORM] = 0; - } - } - else { -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - biosioemu_enq8(0x68, 0x09); - biosioemu_enq8(0xa2, CMD_CSRFORM); - biosioemu_enq8(0xa0, 0x41); - biosioemu_enq8(0xa0, 0x00); - biosioemu_enq8(0xa0, 0x00); - }else -#endif - { - gdc.mode1 |= 0x10; - gdc.s.para[GDC_CSRFORM] = 1; - } - } -#if defined(SUPPORT_CRT31KHZ) - mem[MEMB_CRT_BIOS] &= ~3; - mem[MEMB_CRT_BIOS] |= crtmode; - } -#endif - if (crtmode != 3) { - gdcs.disp = (mode >> 4) & 1; -//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) -// // np21w ver0.86 rev62 BIOS I/O emulation -// if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { -// biosioemu_enq8(0xa4, (mode >> 4)); -// } -//#endif - } - if (!(mode & 0x20)) { - gdc.mode1 &= ~0x02; - gdc.mode2 &= ~0x04; -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) - { - biosioemu_enq8(0x68, 0x02); - } -#endif -} - else { - gdc.mode1 |= 0x02; - gdc.mode2 |= 0x04; -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) - { - biosioemu_enq8(0x68, 0x03); - } -#endif - } - gdcs.mode2 = gdc.mode2; - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - pcstat.screenupdate |= 2; -} - -static void setbiosgdc(UINT32 csrw, const GDCVECT *vect, UINT8 ope) { - - gdc.s.para[GDC_CSRW + 0] = (UINT8)csrw; - gdc.s.para[GDC_CSRW + 1] = (UINT8)(csrw >> 8); - gdc.s.para[GDC_CSRW + 2] = (UINT8)(csrw >> 16); - - gdc.s.para[GDC_VECTW] = vect->ope; - gdc_vectreset(&gdc.s); - - gdc.s.para[GDC_WRITE] = ope; - mem[MEMB_PRXDUPD] &= ~3; - mem[MEMB_PRXDUPD] |= ope; -} - -/* ���������� ������(2ch?)�Ō��J���ꂽ�\�[�X */ -static void bios0x18_45(void) { - - UCWTBL ucw; - UINT i; - UINT8 pat[2]; - UINT16 tmp; - GDCVECT vect; - UINT16 GBSX1; - UINT16 GBSY1; - UINT16 GBLNG1; - UINT16 GBWDPA; - UINT32 csrw; - UINT8 ope; - - //�X���[�u�̏����� - gdc_forceready(GDCWORK_SLAVE); - - //BX�ǂݍ��� - MEMR_READS(CPU_DS, CPU_BX, &ucw, sizeof(ucw)); - - //��� - GBSX1 = LOADINTELWORD(ucw.GBSX1); - GBSY1 = LOADINTELWORD(ucw.GBSY1); - GBWDPA = LOADINTELWORD(ucw.GBWDPA); - GBLNG1 = LOADINTELWORD(ucw.GBLNG1); - - //200���C���ł��炷 - if ((CPU_CH & 0xc0) == 0x40) { - GBSY1 += 200; - } - - //�`��������E���ɐݒ� - vect.ope =0x02 ; - - i = 0; - for(;;){ - //�p�^�[���ǂݍ��� - MEMR_READS(CPU_DS, GBWDPA+i, pat, 1); - - //�[������(gdcsub_setvect�̕K�v�Ȓl�������g���Č�͓K��) - if((GBLNG1 - i*8) < 8){ - gdcsub_setvectl(&vect, 1, 1, (GBLNG1 - i*8), 1); - tmp = 0xFF << (8- (GBLNG1 - i*8)); - tmp &= 0xFF; - tmp &= pat[0]; - tmp = GDCPATREVERSE(tmp) & 0xFF; - }else{ - gdcsub_setvectl(&vect, 1, 1, 8, 1); - tmp = GDCPATREVERSE(pat[0]) & 0xFF; - } - - - //�`��J�n(0x49�̐^��) - csrw = (GBSY1 * 40) + ((GBSX1 + i*8) >> 4); - csrw += ((GBSX1 + i*8) & 0xf) << 20; - - if ((CPU_CH & 0x30) == 0x30) { - ope = (ucw.GBON_PTN & 1)?GDCOPE_SET:GDCOPE_CLEAR; - gdcsub_vectl(csrw + 0x4000, &vect, tmp, ope); - ope = (ucw.GBON_PTN & 2)?GDCOPE_SET:GDCOPE_CLEAR; - gdcsub_vectl(csrw + 0x8000, &vect, tmp, ope); - ope = (ucw.GBON_PTN & 4)?GDCOPE_SET:GDCOPE_CLEAR; - csrw += 0xc000; - gdcsub_vectl(csrw, &vect, tmp, ope); - } - else { - ope = ucw.GBDOTU & 3; - csrw += 0x4000 + ((CPU_CH & 0x30) << 10); - gdcsub_vectl(csrw, &vect, tmp, ope); - } - - //���̃f�[�^��������Δ����� - i++; - if(i*8 >= GBLNG1) break; - } - - // �Ō�Ɏg�����z���L�� - setbiosgdc(csrw, &vect, ope); -} -/* �������܂� ������(2ch?)�Ō��J���ꂽ�\�[�X */ - -static void bios0x18_47(void) { - - UCWTBL ucw; - GDCVECT vect; - UINT16 GBSX1; - UINT16 GBSY1; - UINT16 GBSX2; - UINT16 GBSY2; - GDCSUBFN func; - UINT32 csrw; - UINT16 data; - UINT16 data2; - UINT16 GBMDOTI; - UINT8 ope; - SINT16 dx; - SINT16 dy; - - gdc_forceready(GDCWORK_SLAVE); - MEMR_READS(CPU_DS, CPU_BX, &ucw, sizeof(ucw)); - GBSX1 = LOADINTELWORD(ucw.GBSX1); - GBSY1 = LOADINTELWORD(ucw.GBSY1); - GBSX2 = LOADINTELWORD(ucw.GBSX2); - GBSY2 = LOADINTELWORD(ucw.GBSY2); - ZeroMemory(&vect, sizeof(vect)); - data = 0; - data2 = 0; - if (ucw.GBDTYP == 0x01) { - func = gdcsub_vectl; - gdcsub_setvectl(&vect, GBSX1, GBSY1, GBSX2, GBSY2); - } - else if (ucw.GBDTYP <= 0x02) { - func = gdcsub_vectr; - vect.ope = 0x40 + (ucw.GBDSP & 7); - dx = GBSX2 - GBSX1; - if (dx < 0) { - dx = 0 - dx; - } - dy = GBSY2 - GBSY1; - if (dy < 0) { - dy = 0 - dy; - } - switch(ucw.GBDSP & 3) { - case 0: - data = dy; - data2 = dx; - break; - - case 1: - data2 = (UINT16)dx + (UINT16)dy; - data2 >>= 1; - data = (UINT16)dx - (UINT16)dy; - data = (data >> 1) & 0x3fff; - break; - - case 2: - data = dx; - data2 = dy; - break; - - case 3: - data2 = (UINT16)dx + (UINT16)dy; - data2 >>= 1; - data = (UINT16)dy - (UINT16)dx; - data = (data >> 1) & 0x3fff; - break; - } - STOREINTELWORD(vect.DC, 3); - STOREINTELWORD(vect.D, data); - STOREINTELWORD(vect.D2, data2); - STOREINTELWORD(vect.D1, 0xffff); - STOREINTELWORD(vect.DM, data); - } - else { - func = gdcsub_vectc; - vect.ope = 0x20 + (ucw.GBDSP & 7); - vect.DC[0] = ucw.GBLNG1[0]; - vect.DC[1] = ucw.GBLNG1[1]; -// data = LOADINTELWORD(ucw.GBLNG2) - 1; - data = LOADINTELWORD(ucw.GBCIR) - 1; - STOREINTELWORD(vect.D, data); - data >>= 1; - STOREINTELWORD(vect.D2, data); - STOREINTELWORD(vect.D1, 0x3fff); - if (ucw.GBDTYP == 0x04) { - vect.DM[0] = ucw.GBMDOT[0]; - vect.DM[1] = ucw.GBMDOT[1]; - } - } - if ((CPU_CH & 0xc0) == 0x40) { - GBSY1 += 200; - } - csrw = (GBSY1 * 40) + (GBSX1 >> 4); - csrw += (GBSX1 & 0xf) << 20; - GBMDOTI = (GDCPATREVERSE(ucw.GBMDOTI[0]) << 8) + - GDCPATREVERSE(ucw.GBMDOTI[1]); - if ((CPU_CH & 0x30) == 0x30) { - ope = (ucw.GBON_PTN & 1)?GDCOPE_SET:GDCOPE_CLEAR; - func(csrw + 0x4000, &vect, GBMDOTI, ope); - ope = (ucw.GBON_PTN & 2)?GDCOPE_SET:GDCOPE_CLEAR; - func(csrw + 0x8000, &vect, GBMDOTI, ope); - ope = (ucw.GBON_PTN & 4)?GDCOPE_SET:GDCOPE_CLEAR; - csrw += 0xc000; - func(csrw, &vect, GBMDOTI, ope); - } - else { - ope = ucw.GBDOTU & 3; - csrw += 0x4000 + ((CPU_CH & 0x30) << 10); - func(csrw, &vect, GBMDOTI, ope); - } - - // �Ō�Ɏg�����z���L�� - *(UINT16 *)(mem + MEMW_PRXGLS) = *(UINT16 *)(ucw.GBMDOTI); - STOREINTELWORD(mem + GDC_TEXTW, GBMDOTI); - setbiosgdc(csrw, &vect, ope); -} - -static void bios0x18_49(void) { - - UCWTBL ucw; - UINT i; - UINT8 pat[8]; - UINT16 tmp; - GDCVECT vect; - UINT16 GBSX1; - UINT16 GBSY1; - UINT32 csrw; - UINT8 ope; - - gdc_forceready(GDCWORK_SLAVE); - - MEMR_READS(CPU_DS, CPU_BX, &ucw, sizeof(ucw)); - for (i=0; i<8; i++) { - mem[MEMW_PRXGLS + i] = ucw.GBMDOTI[i]; - pat[i] = GDCPATREVERSE(ucw.GBMDOTI[i]); - gdc.s.para[GDC_TEXTW + i] = pat[i]; - } - vect.ope = 0x10 + (ucw.GBDSP & 7); - if (*(UINT16 *)ucw.GBLNG1) { - tmp = (LOADINTELWORD(ucw.GBLNG2) - 1) & 0x3fff; - STOREINTELWORD(vect.DC, tmp); - vect.D[0] = ucw.GBLNG1[0]; - vect.D[1] = ucw.GBLNG1[1]; - } - else { - STOREINTELWORD(vect.DC, 7); - STOREINTELWORD(vect.D, 7); - } - - GBSX1 = LOADINTELWORD(ucw.GBSX1); - GBSY1 = LOADINTELWORD(ucw.GBSY1); - if ((CPU_CH & 0xc0) == 0x40) { - GBSY1 += 200; - } - csrw = (GBSY1 * 40) + (GBSX1 >> 4); - csrw += (GBSX1 & 0xf) << 20; - if ((CPU_CH & 0x30) == 0x30) { - ope = (ucw.GBON_PTN & 1)?GDCOPE_SET:GDCOPE_CLEAR; - gdcsub_text(csrw + 0x4000, &vect, pat, ope); - ope = (ucw.GBON_PTN & 2)?GDCOPE_SET:GDCOPE_CLEAR; - gdcsub_text(csrw + 0x8000, &vect, pat, ope); - ope = (ucw.GBON_PTN & 4)?GDCOPE_SET:GDCOPE_CLEAR; - csrw += 0xc000; - gdcsub_text(csrw, &vect, pat, ope); - } - else { - ope = ucw.GBDOTU & 3; - csrw += 0x4000 + ((CPU_CH & 0x30) << 10); - gdcsub_text(csrw, &vect, pat, ope); - } - - // �Ō�Ɏg�����z���L�� - setbiosgdc(csrw, &vect, ope); -} - - -// ---- PC-9821 - -#if defined(SUPPORT_PC9821) -static void bios0x18_4d(REG8 mode) { - - if ((mem[0x45c] & 0x40) && - ((mem[MEMB_CRT_BIOS] & 3) == 2)) { - if (mode == 0) { - gdc_analogext(FALSE); - mem[MEMB_PRXDUPD] &= ~0x7f; - mem[MEMB_PRXDUPD] |= 0x04; - } - else if (mode == 1) { - gdc_analogext(TRUE); - mem[MEMB_PRXDUPD] |= 0x80; - } - else { - mem[MEMB_PRXDUPD] |= 0x04; - } - } -} -#endif - - -// ---- - -void bios0x18(void) { - - union { - BOOL b; - REG8 r8; - UINT16 w; - UINT32 d; - UINT8 col[4]; - } tmp; - int i; - -#if 0 - TRACEOUT(("int18 AX=%.4x %.4x:%.4x", CPU_AX, - MEMR_READ16(CPU_SS, CPU_SP+2), - MEMR_READ16(CPU_SS, CPU_SP))); -#endif - - switch(CPU_AH) { - case 0x00: // �L�[�E�f�[�^�̓ǂ݂��� - if (mem[MEMB_KB_COUNT]) { - CPU_AX = keyget(); - } - else { - CPU_IP--; - CPU_REMCLOCK = -1; - break; - } - break; - - case 0x01: // �L�[�E�o�b�t�@��Ԃ̃Z���X - if (mem[MEMB_KB_COUNT]) { - tmp.d = GETBIOSMEM16(MEMW_KB_BUF_HEAD); - CPU_AX = GETBIOSMEM16(tmp.d); - CPU_BH = 1; - } - else { - CPU_BH = 0; - } - break; - - case 0x02: // �V�t�g�E�L�[��Ԃ̃Z���X - CPU_AL = mem[MEMB_SHIFT_STS]; - break; - - case 0x03: // �L�[�{�[�h�E�C���^�t�F�C�X�̏����� -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - // np21w ver0.86 rev47 BIOS I/O emulation - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - biosioemu_enq8(0x43, 0x3a); - biosioemu_enq8(0x43, 0x32); - biosioemu_enq8(0x43, 0x16); - ZeroMemory(mem + 0x00502, 0x20); - ZeroMemory(mem + 0x00528, 0x13); - SETBIOSMEM16(MEMW_KB_SHIFT_TBL, 0x0e00); - SETBIOSMEM16(MEMW_KB_BUF_HEAD, 0x0502); - SETBIOSMEM16(MEMW_KB_BUF_TAIL, 0x0502); - SETBIOSMEM16(MEMW_KB_CODE_OFF, 0x0e00); - SETBIOSMEM16(MEMW_KB_CODE_SEG, 0xfd80); - }else -#endif - { - bios0x09_init(); - } - break; - - case 0x04: // �L�[���͏�Ԃ̃Z���X - CPU_AH = mem[MEMX_KB_KY_STS + (CPU_AL & 0x0f)]; - break; - - case 0x05: // �L�[���̓Z���X - if (mem[MEMB_KB_COUNT]) { - CPU_AX = keyget(); - CPU_BH = 1; - } - else { - CPU_BH = 0; - } - break; - - case 0x0a: // CRT���[�h�̐ݒ�(15/24khz) - bios0x18_0a(CPU_AL); - break; - - case 0x0b: // CRT���[�h�̃Z���X - CPU_AL = mem[MEMB_CRT_STS_FLAG]; - break; - - case 0x0c: // �e�L�X�g��ʂ̕\���J�n -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - // np21w ver0.86 rev47 BIOS I/O emulation - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - if (!(gdcs.textdisp & GDCSCRN_ENABLE)) { - pcstat.screenupdate |= 2; - } - biosioemu_push8(0x62, CMD_START); - } else -#endif - { - bios0x18_0c(); - } - break; - - case 0x0d: // �e�L�X�g��ʂ̕\���I�� -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - // np21w ver0.86 rev47 BIOS I/O emulation - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - if (gdcs.textdisp & GDCSCRN_ENABLE) { - pcstat.screenupdate |= 2; - } - biosioemu_push8(0x62, CMD_STOP); - } else -#endif - { - if (gdcs.textdisp & GDCSCRN_ENABLE) { - gdcs.textdisp &= ~(GDCSCRN_ENABLE); - pcstat.screenupdate |= 2; - } - } - break; - - case 0x0e: // ��‚̕\���̈�̐ݒ� - gdc_forceready(GDCWORK_MASTER); - ZeroMemory(&gdc.m.para[GDC_SCROLL], 16); - tmp.w = CPU_DX >> 1; - SETBIOSMEM16(MEMW_CRT_W_VRAMADR, tmp.w); - STOREINTELWORD(gdc.m.para + GDC_SCROLL + 0, tmp.w); - tmp.w = 200 << 4; - if (mem[MEMB_CRT_STS_FLAG] & 0x80) { - tmp.w <<= 1; - } - SETBIOSMEM16(MEMW_CRT_W_RASTER, tmp.w); - STOREINTELWORD(gdc.m.para + GDC_SCROLL + 2, tmp.w); - gdcs.textdisp |= GDCSCRN_ALLDRAW2; -// pcstat.screenupdate |= 2; - break; - - case 0x0f: // �����̕\���̈�̐ݒ� - gdc_forceready(GDCWORK_MASTER); - bios0x18_0f(CPU_BX, CPU_CX, CPU_DH, CPU_DL); - break; - - case 0x10: // �J�[�\���^�C�v�̐ݒ�(15/24khz) - gdc_forceready(GDCWORK_MASTER); - bios0x18_10((REG8)(CPU_AL & 1)); - break; - - case 0x11: // �J�[�\���̕\���J�n - gdc_forceready(GDCWORK_MASTER); - if (gdc.m.para[GDC_CSRFORM] != (mem[MEMB_CRT_RASTER] | 0x80)) { - gdc.m.para[GDC_CSRFORM] = mem[MEMB_CRT_RASTER] | 0x80; - } - gdcs.textdisp |= GDCSCRN_ALLDRAW | GDCSCRN_EXT; - break; - - case 0x12: // �J�[�\���̕\����~ - gdc_forceready(GDCWORK_MASTER); - if (gdc.m.para[GDC_CSRFORM] != mem[MEMB_CRT_RASTER]) { - gdc.m.para[GDC_CSRFORM] = mem[MEMB_CRT_RASTER]; - gdcs.textdisp |= GDCSCRN_ALLDRAW | GDCSCRN_EXT; - } - break; - - case 0x13: // �J�[�\���ʒu�̐ݒ� - gdc_forceready(GDCWORK_MASTER); - tmp.w = CPU_DX >> 1; - if (LOADINTELWORD(gdc.m.para + GDC_CSRW) != tmp.w) { - STOREINTELWORD(gdc.m.para + GDC_CSRW, tmp.w); - gdcs.textdisp |= GDCSCRN_EXT; - } - break; - - case 0x14: // �t�H���g�p�^�[���̓ǂݏo�� - bios0x18_14(CPU_BX, CPU_CX, CPU_DX); - break; - - case 0x15: // ���C�g�y���ʒu�ǂ݂��� - break; - - case 0x16: // �e�L�X�gVRAM�̏����� - bios0x18_16(CPU_DL, CPU_DH); - break; - - case 0x17: // �u�U�[�̋N�� - iocore_out8(0x37, 0x06); - break; - - case 0x18: // �u�U�[�̒�~ - iocore_out8(0x37, 0x07); - break; - - case 0x19: // ���C�g�y��������Ԃ̏����� - break; - - case 0x1a: // ���[�U�[�����̒�` - bios0x18_1a(CPU_BX, CPU_CX, CPU_DX); - break; - - case 0x1b: // KCG�A�N�Z�X���[�h�̐ݒ� - switch(CPU_AL) { - case 0: - mem[MEMB_CRT_STS_FLAG] &= ~0x08; - gdc.mode1 &= ~0x20; - gdc_restorekacmode(); - break; - - case 1: - mem[MEMB_CRT_STS_FLAG] |= 0x08; - gdc.mode1 |= 0x20; - gdc_restorekacmode(); - break; - } - break; -#if defined(SUPPORT_CRT31KHZ) - case 0x30: - if (mem[MEMB_CRT_BIOS] & 0x80) { - gdc_forceready(GDCWORK_MASTER); - gdc_forceready(GDCWORK_SLAVE); - tmp.r8 = bios0x18_30(CPU_AL, CPU_BH); - CPU_AH = tmp.r8; - if (tmp.r8 == 0x05) { - CPU_AL = 0; - CPU_BH = 0; - } - else { - CPU_AL = 1; - CPU_BH = 1; - } - } - break; - - case 0x31: - if (mem[MEMB_CRT_BIOS] & 0x80) { - CPU_AL = bios0x18_31al(); - CPU_BH = bios0x18_31bh(); - } - break; -#endif - case 0x40: // �O���t�B�b�N��ʂ̕\���J�n -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - // np21w ver0.86 rev47 BIOS I/O emulation - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - gdc_forceready(GDCWORK_SLAVE); - if (!(gdcs.grphdisp & GDCSCRN_ENABLE)) { - pcstat.screenupdate |= 2; - } - biosioemu_push8(0xa2, CMD_START); - mem[MEMB_PRXCRT] |= 0x80; - } else -#endif - { - bios0x18_40(); - } - break; - - case 0x41: // �O���t�B�b�N��ʂ̕\���I�� -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - // np21w ver0.86 rev47 BIOS I/O emulation - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - gdc_forceready(GDCWORK_SLAVE); - if (gdcs.grphdisp & GDCSCRN_ENABLE) { - pcstat.screenupdate |= 2; - } - biosioemu_push8(0xa2, CMD_STOP); - mem[MEMB_PRXCRT] &= 0x7f; - } else -#endif - { - bios0x18_41(); - } - break; - - case 0x42: // �\���̈�̐ݒ� - bios0x18_42(CPU_CH); - break; - - case 0x43: // �p���b�g�̐ݒ� - MEMR_READS(CPU_DS, CPU_BX + offsetof(UCWTBL, GBCPC), tmp.col, 4); - for (i=0; i<4; i++) { - gdc_setdegitalpal(6 - (i*2), (REG8)(tmp.col[i] >> 4)); - gdc_setdegitalpal(7 - (i*2), (REG8)(tmp.col[i] & 15)); - } - break; - - case 0x44: // �{�[�_�J���[�̐ݒ� -// if (!(mem[MEMB_PRXCRT] & 0x40)) { -// color = MEMR_READ8(CPU_DS, CPU_BX + 1); -// } - break; - case 0x45: /* int18,45h��lj�(from Kai2, np21w ver0.86 rev16) */ - bios0x18_45(); - break; - case 0x46: - TRACEOUT(("unsupport bios 18-%.2x", CPU_AH)); - break; - - case 0x47: // �����A��`�̕`�� - case 0x48: // �~�̕`�� - bios0x18_47(); - break; - - case 0x49: // �O���t�B�b�N�����̕`�� - bios0x18_49(); - break; - - case 0x4a: // �`�惂�[�h�̐ݒ� - if (!(mem[MEMB_PRXCRT] & 0x01)) { - gdc.s.para[GDC_SYNC] = CPU_CH; - gdcs.grphdisp |= GDCSCRN_EXT; - if (CPU_CH & 0x10) { - mem[MEMB_PRXDUPD] &= ~0x08; - } - else { - mem[MEMB_PRXDUPD] |= 0x08; - } - } - break; -#if defined(SUPPORT_PC9821) - case 0x4d: - bios0x18_4d(CPU_CH); - break; -#endif - } -} - - +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct { + UINT8 GBON_PTN; + UINT8 GBBCC; + UINT8 GBDOTU; + UINT8 GBDSP; + UINT8 GBCPC[4]; + UINT8 GBSX1[2]; + UINT8 GBSY1[2]; + UINT8 GBLNG1[2]; + UINT8 GBWDPA[2]; + UINT8 GBRBUF[2][3]; + UINT8 GBSX2[2]; + UINT8 GBSY2[2]; + UINT8 GBMDOT[2]; + UINT8 GBCIR[2]; + UINT8 GBLNG2[2]; + UINT8 GBMDOTI[8]; + UINT8 GBDTYP; + UINT8 GBFILL; +} UCWTBL; + +typedef struct { + UINT8 raster; + UINT8 pl; + UINT8 bl; + UINT8 cl; +} CRTDATA; + +static const UINT8 modenum[4] = {3, 1, 0, 2}; + +static const CRTDATA crtdata[7] = { + {0x09, 0x1f, 0x08, 0x08}, // 200-20 + {0x07, 0x00, 0x07, 0x08}, // 200-25 + {0x13, 0x1e, 0x11, 0x10}, // 400-20 + {0x0f, 0x00, 0x0f, 0x10}, // 400-25 + {0x17, 0x1c, 0x13, 0x10}, // 480-20 + {0x12, 0x1f, 0x11, 0x10}, // 480-25 + {0x0f, 0x00, 0x0f, 0x10}}; // 480-30 + +#if defined(SUPPORT_CRT31KHZ) +static const UINT8 gdcmastersync[6][8] = { + {0x10,0x4e,0x07,0x25,0x0d,0x0f,0xc8,0x94}, /* 15 */ + {0x10,0x4e,0x07,0x25,0x07,0x07,0x90,0x65}, /* 24 */ + {0x10,0x4e,0x47,0x0c,0x07,0x0d,0x90,0x89}, /* 31 */ + {0x10,0x4e,0x4b,0x0c,0x03,0x06,0xe0,0x95}, /* 31-480:20 */ + {0x10,0x4e,0x4b,0x0c,0x03,0x0b,0xdb,0x95}, /* 31-480:25 */ + {0x10,0x4e,0x4b,0x0c,0x03,0x06,0xe0,0x95}}; /* 31-480:30 */ +#endif /* defined(SUPPORT_CRT31KHZ) */ + +static const UINT8 gdcslavesync[6][8] = { + {0x02,0x26,0x03,0x11,0x86,0x0f,0xc8,0x94}, // 15-L + {0x02,0x4e,0x4b,0x0c,0x83,0x06,0xe0,0x95}, // 31-H + {0x02,0x26,0x03,0x11,0x83,0x07,0x90,0x65}, // 24-L + {0x02,0x4e,0x07,0x25,0x87,0x07,0x90,0x65}, // 24-M + {0x02,0x26,0x41,0x0c,0x83,0x0d,0x90,0x89}, // 31-L + {0x02,0x4e,0x47,0x0c,0x87,0x0d,0x90,0x89}}; // 31-M + +typedef struct { + UINT8 lr; + UINT8 cfi; +} CSRFORM; + +static const CSRFORM csrform[4] = { + {0x07, 0x3b}, {0x09, 0x4b}, + {0x0f, 0x7b}, {0x13, 0x9b}}; + +#if 0 +static const UINT8 sync200l[8] = {0x02,0x26,0x03,0x11,0x86,0x0f,0xc8,0x94}; +static const UINT8 sync200m[8] = {0x02,0x26,0x03,0x11,0x83,0x07,0x90,0x65}; +static const UINT8 sync400m[8] = {0x02,0x4e,0x07,0x25,0x87,0x07,0x90,0x65}; +#endif /* 0 */ + +static UINT16 keyget(void) { + + UINT pos; + UINT kbbufhead; + + if (mem[MEMB_KB_COUNT]) { + mem[MEMB_KB_COUNT]--; + pos = GETBIOSMEM16(MEMW_KB_BUF_HEAD); + kbbufhead = pos + 2; + if (kbbufhead >= 0x522) { + kbbufhead = 0x502; + } + SETBIOSMEM16(MEMW_KB_BUF_HEAD, kbbufhead); + return(GETBIOSMEM16(pos)); + } + return(0xffff); +} + + +// ---- master + +void bios0x18_0a(REG8 mode) { + +const CRTDATA *crt; + + gdc_forceready(GDCWORK_MASTER); + + gdc.mode1 &= ~(0x2d); + mem[MEMB_CRT_STS_FLAG] = mode; + crt = crtdata; + if (!(pccore.dipsw[0] & 1)) { + mem[MEMB_CRT_STS_FLAG] |= 0x80; + gdc.mode1 |= 0x08; + crt += 2; + } + if (!(mode & 0x01)) { + crt += 1; // 25�s + } + if (mode & 0x02) { + gdc.mode1 |= 0x04; // 40�� + } + if (mode & 0x04) { + gdc.mode1 |= 0x01; // �A�g���r���[�g + } + if (mode & 0x08) { + gdc.mode1 |= 0x20; // �R�[�h�A�N�Z�X + } + mem[MEMB_CRT_RASTER] = crt->raster; + crtc.reg.pl = crt->pl; + crtc.reg.bl = crt->bl; + crtc.reg.cl = crt->cl; + crtc.reg.ssl = 0; + gdc_restorekacmode(); + bios0x18_10(0); +//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) +// // np21w ver0.86 rev62 BIOS I/O emulation +// if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { +// if (!(pccore.dipsw[0] & 1)) { +// biosioemu_enq8(0x68, 0x08|0x01); +// }else{ +// biosioemu_enq8(0x68, 0x08|0x00); +// } +// if (mode & 0x02) { +// biosioemu_enq8(0x68, 0x04|0x01); +// }else{ +// biosioemu_enq8(0x68, 0x04|0x00); +// } +// if (mode & 0x04) { +// biosioemu_enq8(0x68, 0x00|0x01); +// }else{ +// biosioemu_enq8(0x68, 0x00|0x00); +// } +// if (mode & 0x08) { +// biosioemu_enq8(0x68, 0x20|0x01); +// }else{ +// biosioemu_enq8(0x68, 0x20|0x00); +// } +// } +//#endif +} + +void bios0x18_0c(void) { + + if (!(gdcs.textdisp & GDCSCRN_ENABLE)) { + gdcs.textdisp |= GDCSCRN_ENABLE; + pcstat.screenupdate |= 2; + } +} + +static void bios0x18_0f(UINT seg, UINT off, REG8 num, REG8 cnt) { + + UINT8 *p; + UINT raster; + UINT t; + + SETBIOSMEM16(0x0053e, (UINT16)off); + SETBIOSMEM16(0x00540, (UINT16)seg); + mem[0x00547] = num; + mem[0x0053D] = cnt; + p = gdc.m.para + GDC_SCROLL + (num << 2); + +#if defined(SUPPORT_CRT31KHZ) + if (mem[MEMB_CRT_BIOS] & 0x80) { + raster = (mem[MEMB_CRT_RASTER] + 1) << 4; + } + else { +#endif + if (!(mem[MEMB_CRT_STS_FLAG] & 0x01)) { // 25 + raster = 8 << 4; + } + else { // 20 + raster = 16 << 4; + } + if (mem[MEMB_CRT_STS_FLAG] & 0x80) { + raster <<= 1; + } +#if defined(SUPPORT_CRT31KHZ) + } +#endif + + while((cnt--) && (p < (gdc.m.para + GDC_SCROLL + 0x10))) { + t = MEMR_READ16(seg, off); + t >>= 1; + STOREINTELWORD(p, t); + t = MEMR_READ16(seg, off + 2); + t *= raster; + STOREINTELWORD(p + 2, t); + off += 4; + p += 4; + } + gdcs.textdisp |= GDCSCRN_ALLDRAW2; + pcstat.screenupdate |= 2; +} + +void bios0x18_10(REG8 curdel) { + + UINT8 sts; + UINT pos; + + sts = mem[MEMB_CRT_STS_FLAG]; + mem[MEMB_CRT_STS_FLAG] = sts & (~0x40); + pos = sts & 0x01; + if (sts & 0x80) { + pos += 2; + } + mem[MEMB_CRT_CNT] = (curdel << 5); + gdc.m.para[GDC_CSRFORM + 0] = csrform[pos].lr; + gdc.m.para[GDC_CSRFORM + 1] = curdel << 5; + gdc.m.para[GDC_CSRFORM + 2] = csrform[pos].cfi; + gdcs.textdisp |= GDCSCRN_ALLDRAW2 | GDCSCRN_EXT; +} + +REG16 bios0x18_14(REG16 seg, REG16 off, REG16 code) { + + UINT16 size; +const UINT8 *p; + UINT8 buf[32]; + UINT i; + + switch(code >> 8) { + case 0x00: // 8x8 + size = 0x0101; + MEMR_WRITE16(seg, off, 0x0101); + p = fontrom + 0x82000 + ((code & 0xff) << 4); + MEMR_WRITES(seg, off + 2, p, 8); + break; + +// case 0x28: + case 0x29: // 8x16 KANJI + case 0x2a: + case 0x2b: + size = 0x0102; + MEMR_WRITE16(seg, off, 0x0102); + p = fontrom; + p += (code & 0x7f) << 12; + p += (((code >> 8) - 0x20) & 0x7f) << 4; + MEMR_WRITES(seg, off + 2, p, 16); + break; + + case 0x80: // 8x16 ANK + size = 0x0102; + p = fontrom + 0x80000 + ((code & 0xff) << 4); + MEMR_WRITES(seg, off + 2, p, 16); + break; + + default: + size = 0x0202; + p = fontrom; + p += (code & 0x7f) << 12; + p += (((code >> 8) - 0x20) & 0x7f) << 4; + for (i=0; i<16; i++, p++) { + buf[i*2+0] = *p; + buf[i*2+1] = *(p+0x800); + } + MEMR_WRITES(seg, off + 2, buf, 32); + break; + } + MEMR_WRITE16(seg, off, size); + return(size); +} + +static void bios0x18_1a(REG16 seg, REG16 off, REG16 code) { + + UINT8 *p; + UINT8 buf[32]; + UINT i; + + if (((code >> 8) & 0x7e) == 0x76) { + MEMR_READS(seg, off + 2, buf, 32); + p = fontrom; + p += (code & 0x7f) << 12; + p += (((code >> 8) - 0x20) & 0x7f) << 4; + for (i=0; i<16; i++, p++) { + *p = buf[i*2+0]; + *(p+0x800) = buf[i*2+1]; + } + cgwindow.writable |= 0x80; + } +} + +void bios0x18_16(REG8 chr, REG8 atr) { + + UINT32 i; + + for (i=0xa0000; i<0xa2000; i+=2) { + mem[i+0] = chr; + mem[i+1] = 0; + } + for (; i<0xa3fe0; i+=2) { + mem[i] = atr; + } + gdcs.textdisp |= GDCSCRN_ALLDRAW; +} + + +// ---- 31khz + +#if defined(SUPPORT_CRT31KHZ) +static REG8 bios0x18_30(REG8 rate, REG8 scrn) { + + int crt; + int master; + int slave; +const CRTDATA *p; + + if (((rate & 0xf8) != 0x08) || (scrn & (~0x33)) || ((scrn & 3) == 3)) { + return(0); + } + if ((scrn & 0x30) == 0x30) { // 640x480 +#if defined(SUPPORT_PC9821) + //if (rate & 4) { + if (rate & 0xc) { // np21w ver0.86 rev47 workaround +//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) +// // XXX: Windows3.1 DOS�v�����v�g�p ������� +// if (CPU_STAT_PM && CPU_STAT_VM86) { +// biosioemu_enq8(0x6a, 0x21); +// mem[MEMB_PRXDUPD] |= 0x80; +// crt = 4; +// master = 3 + (scrn & 3); +// slave = 1; +// biosioemu_enq8(0x6a, 0x69); +// }else +//#endif + { + gdc_analogext(TRUE); + mem[MEMB_PRXDUPD] |= 0x80; + crt = 4; + master = 3 + (scrn & 3); + slave = 1; + gdc.analog |= (1 << GDCANALOG_256E); + } + } + else +#endif + return(0); + } + else { + if ((scrn & 3) >= 2) { + return(0); + } + if (rate & 4) { // 31khz + crt = 2; + master = 2; + slave = 4; + } + else if (mem[MEMB_PRXCRT] & 0x40) { // 24khz + crt = 2; + master = 1; + slave = 2; + } + else { + crt = 0; + master = 0; + slave = 0; + } + if ((scrn & 0x20) && (mem[MEMB_PRXDUPD] & 0x04)) { + slave += 1; + } +#if defined(SUPPORT_PC9821) + else { +//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) +// // XXX: Windows3.1 DOS�v�����v�g�p ������� +// if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { +// biosioemu_enq8(0x6a, 0x20); // ����͑ʖ� +// }else +//#endif + { + gdc_analogext(FALSE); + } + mem[MEMB_PRXDUPD] &= ~0x80; + } +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + // XXX: Windows3.1 DOS�v�����v�g�p ������� + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + biosioemu_enq8(0x6a, 0x68); + }else +#endif + { + gdc.analog &= ~(1 << (GDCANALOG_256E)); + } +#endif + } + crt += (scrn & 3); + +//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) +// // XXX: Windows3.1 DOS�v�����v�g�p ������� +// if (CPU_STAT_PM && CPU_STAT_VM86) { +// if (rate & 4) { +// biosioemu_push8(0x09a8, 0x01); +// } +// else { +// biosioemu_push8(0x09a8, 0x00); +// } +// }else +//#endif + { + if (rate & 4) { + gdc.display |= (1 << GDCDISP_31); + } + else { + gdc.display &= ~(1 << GDCDISP_31); + } + } + + CopyMemory(gdc.m.para + GDC_SYNC, gdcmastersync[master], 8); + ZeroMemory(gdc.m.para + GDC_SCROLL, 4); + gdc.m.para[GDC_PITCH] = 80; + + p = crtdata + crt; + gdc.m.para[GDC_CSRFORM + 0] = p->raster; + gdc.m.para[GDC_CSRFORM + 1] = 0; + gdc.m.para[GDC_CSRFORM + 2] = (p->raster << 3) + 3; + crtc.reg.pl = p->pl; + crtc.reg.bl = p->bl; + crtc.reg.cl = p->cl; + crtc.reg.ssl = 0; + crtc.reg.sur = 1; + crtc.reg.sdr = 0; + + CopyMemory(gdc.s.para + GDC_SYNC, gdcslavesync[slave], 8); + ZeroMemory(gdc.s.para + GDC_SCROLL, 4); + if (slave & 1) { +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + // XXX: Windows3.1 DOS�v�����v�g�p ������� + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + biosioemu_enq8(0xa2, CMD_PITCH); + biosioemu_enq8(0xa0, 80); + }else +#endif + { + gdc.s.para[GDC_PITCH] = 80; + } + gdc.clock |= 3; + mem[MEMB_PRXDUPD] |= 0x04; + gdc.s.para[GDC_SCROLL+3] = 0x40; + } + else { +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + // XXX: Windows3.1 DOS�v�����v�g�p ������� + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + biosioemu_enq8(0xa2, CMD_PITCH); + biosioemu_enq8(0xa0, 40); + }else +#endif + { + gdc.s.para[GDC_PITCH] = 40; + } + gdc.clock &= ~3; + mem[MEMB_PRXDUPD] &= ~0x04; + } + if ((scrn & 0x30) == 0x10) { + gdc.s.para[GDC_SCROLL+0] = (200*40) & 0xff; + gdc.s.para[GDC_SCROLL+1] = (200*40) >> 8; + } + if ((scrn & 0x20) || (!(mem[MEMB_PRXCRT] & 0x40))) { + gdc.mode1 &= ~(0x10); + gdc.s.para[GDC_CSRFORM] = 0; + } + else { + gdc.mode1 |= 0x10; + gdc.s.para[GDC_CSRFORM] = 1; + } + +#if defined(BIOS_IO_EMULATION) + // XXX: Windows3.1 DOS�v�����v�g�p ������� + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + biosioemu_enq8(0x6a, 0x40 | ((gdc.display & (1 << GDCDISP_PLAZMA)) ? 1 : 0)); // gdcs.textdisp |= GDCSCRN_EXT; �̑���E�E�E + biosioemu_enq8(0x6a, 0x82 | (gdc.clock & 1)); // gdcs.grphdisp |= GDCSCRN_EXT; + biosioemu_enq8(0x62, CMD_STOP); // gdcs.textdisp &= ~GDCSCRN_ENABLE; pcstat.screenupdate |= 2; + }else +#endif + { + gdcs.textdisp &= ~GDCSCRN_ENABLE; + gdcs.textdisp |= GDCSCRN_EXT; + gdcs.grphdisp |= GDCSCRN_EXT; + pcstat.screenupdate |= 2; + } + gdcs.textdisp |= GDCSCRN_ALLDRAW2; + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + + mem[0x597] &= ~3; + mem[0x597] |= (scrn >> 4) & 3; + mem[MEMB_CRT_STS_FLAG] &= ~0x11; + if (!(scrn & 1)) { + mem[MEMB_CRT_STS_FLAG] |= 0x01; + } + if (scrn & 2) { + mem[MEMB_CRT_STS_FLAG] |= 0x10; + } + return(5); // �Ō��GDC�֑������f�[�^�c +} + +static REG8 bios0x18_31al(void) { + + UINT8 rate; + + rate = 0x08 + ((gdc.display >> (GDCDISP_31 - 5)) & 4); + return(rate); +} + +static REG8 bios0x18_31bh(void) { + + UINT8 scrn; + + scrn = (mem[0x597] & 3) << 4; + if (!(mem[MEMB_CRT_STS_FLAG] & 0x01)) { + scrn |= 0x01; + } + if (mem[MEMB_CRT_STS_FLAG] & 0x10) { + scrn |= 0x02; + } + return(scrn); +} +#endif + + +// ---- slave + +void bios0x18_40(void) { + + gdc_forceready(GDCWORK_SLAVE); + if (!(gdcs.grphdisp & GDCSCRN_ENABLE)) { + gdcs.grphdisp |= GDCSCRN_ENABLE; + pcstat.screenupdate |= 2; + } + mem[MEMB_PRXCRT] |= 0x80; +} + +void bios0x18_41(void) { + + gdc_forceready(GDCWORK_SLAVE); + if (gdcs.grphdisp & GDCSCRN_ENABLE) { + gdcs.grphdisp &= ~(GDCSCRN_ENABLE); + pcstat.screenupdate |= 2; + } + mem[MEMB_PRXCRT] &= 0x7f; +} + +void bios0x18_42(REG8 mode) { + + UINT8 crtmode; +#if defined(SUPPORT_CRT31KHZ) + UINT8 rate; + UINT8 scrn; +#endif + int slave; + + gdc_forceready(GDCWORK_MASTER); + gdc_forceready(GDCWORK_SLAVE); + + crtmode = modenum[mode >> 6]; +#if defined(SUPPORT_CRT31KHZ) + rate = bios0x18_31al(); + scrn = bios0x18_31bh(); + if ((mem[MEMB_CRT_BIOS] & 0x80) && + (((scrn & 0x30) == 0x30) || (crtmode == 3))) { + bios0x18_30(rate, (REG8)((crtmode << 4) + 1)); + } + else { +#endif + ZeroMemory(gdc.s.para + GDC_SCROLL, 4); + if (crtmode == 2) { // ALL + crtmode = 2; + if ((mem[MEMB_PRXDUPD] & 0x24) == 0x20) { + mem[MEMB_PRXDUPD] ^= 4; + gdc.clock |= 3; + CopyMemory(gdc.s.para + GDC_SYNC, gdcslavesync[3], 8); + gdc.s.para[GDC_PITCH] = 80; + gdcs.grphdisp |= GDCSCRN_EXT; + mem[MEMB_PRXDUPD] |= 0x08; + } +//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) +// if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { +// biosioemu_enq8(0x6a, 0x83); +// biosioemu_enq8(0x6a, 0x85); +// } +//#endif + } + else { + if ((mem[MEMB_PRXDUPD] & 0x24) == 0x24) { + mem[MEMB_PRXDUPD] ^= 4; + gdc.clock &= ~3; +#if defined(SUPPORT_CRT31KHZ) + if (rate & 4) slave = 4; + else +#endif + slave = (mem[MEMB_PRXCRT] & 0x40)?2:0; + CopyMemory(gdc.s.para + GDC_SYNC, gdcslavesync[slave], 8); + gdc.s.para[GDC_PITCH] = 40; + gdcs.grphdisp |= GDCSCRN_EXT; + mem[MEMB_PRXDUPD] |= 0x08; +//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) +// if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { +// biosioemu_enq8(0x6a, 0x82); +// biosioemu_enq8(0x6a, 0x84); +// } +//#endif + } + if (crtmode & 1) { // UPPER + gdc.s.para[GDC_SCROLL+0] = (200*40) & 0xff; + gdc.s.para[GDC_SCROLL+1] = (200*40) >> 8; + } + } + if (mem[MEMB_PRXDUPD] & 4) { + gdc.s.para[GDC_SCROLL+3] = 0x40; + } + if ((crtmode == 2) || (!(mem[MEMB_PRXCRT] & 0x40))) { +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + biosioemu_enq8(0x68, 0x08); + biosioemu_enq8(0xa2, CMD_CSRFORM); + biosioemu_enq8(0xa0, 0x40); + biosioemu_enq8(0xa0, 0x00); + biosioemu_enq8(0xa0, 0x00); + }else +#endif + { + gdc.mode1 &= ~(0x10); + gdc.s.para[GDC_CSRFORM] = 0; + } + } + else { +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + biosioemu_enq8(0x68, 0x09); + biosioemu_enq8(0xa2, CMD_CSRFORM); + biosioemu_enq8(0xa0, 0x41); + biosioemu_enq8(0xa0, 0x00); + biosioemu_enq8(0xa0, 0x00); + }else +#endif + { + gdc.mode1 |= 0x10; + gdc.s.para[GDC_CSRFORM] = 1; + } + } +#if defined(SUPPORT_CRT31KHZ) + mem[MEMB_CRT_BIOS] &= ~3; + mem[MEMB_CRT_BIOS] |= crtmode; + } +#endif + if (crtmode != 3) { + gdcs.disp = (mode >> 4) & 1; +//#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) +// // np21w ver0.86 rev62 BIOS I/O emulation +// if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { +// biosioemu_enq8(0xa4, (mode >> 4)); +// } +//#endif + } + if (!(mode & 0x20)) { + gdc.mode1 &= ~0x02; + gdc.mode2 &= ~0x04; +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) + { + biosioemu_enq8(0x68, 0x02); + } +#endif +} + else { + gdc.mode1 |= 0x02; + gdc.mode2 |= 0x04; +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) + { + biosioemu_enq8(0x68, 0x03); + } +#endif + } + gdcs.mode2 = gdc.mode2; + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + pcstat.screenupdate |= 2; +} + +static void setbiosgdc(UINT32 csrw, const GDCVECT *vect, UINT8 ope) { + + gdc.s.para[GDC_CSRW + 0] = (UINT8)csrw; + gdc.s.para[GDC_CSRW + 1] = (UINT8)(csrw >> 8); + gdc.s.para[GDC_CSRW + 2] = (UINT8)(csrw >> 16); + + gdc.s.para[GDC_VECTW] = vect->ope; + gdc_vectreset(&gdc.s); + + gdc.s.para[GDC_WRITE] = ope; + mem[MEMB_PRXDUPD] &= ~3; + mem[MEMB_PRXDUPD] |= ope; +} + +/* ���������� ������(2ch?)�Ō��J���ꂽ�\�[�X */ +static void bios0x18_45(void) { + + UCWTBL ucw; + UINT i; + UINT8 pat[2]; + UINT16 tmp; + GDCVECT vect; + UINT16 GBSX1; + UINT16 GBSY1; + UINT16 GBLNG1; + UINT16 GBWDPA; + UINT32 csrw; + UINT8 ope; + + //�X���[�u�̏����� + gdc_forceready(GDCWORK_SLAVE); + + //BX�ǂݍ��� + MEMR_READS(CPU_DS, CPU_BX, &ucw, sizeof(ucw)); + + //��� + GBSX1 = LOADINTELWORD(ucw.GBSX1); + GBSY1 = LOADINTELWORD(ucw.GBSY1); + GBWDPA = LOADINTELWORD(ucw.GBWDPA); + GBLNG1 = LOADINTELWORD(ucw.GBLNG1); + + //200���C���ł��炷 + if ((CPU_CH & 0xc0) == 0x40) { + GBSY1 += 200; + } + + //�`��������E���ɐݒ� + vect.ope =0x02 ; + + i = 0; + for(;;){ + //�p�^�[���ǂݍ��� + MEMR_READS(CPU_DS, GBWDPA+i, pat, 1); + + //�[������(gdcsub_setvect�̕K�v�Ȓl�������g���Č�͓K��) + if((GBLNG1 - i*8) < 8){ + gdcsub_setvectl(&vect, 1, 1, (GBLNG1 - i*8), 1); + tmp = 0xFF << (8- (GBLNG1 - i*8)); + tmp &= 0xFF; + tmp &= pat[0]; + tmp = GDCPATREVERSE(tmp) & 0xFF; + }else{ + gdcsub_setvectl(&vect, 1, 1, 8, 1); + tmp = GDCPATREVERSE(pat[0]) & 0xFF; + } + + + //�`��J�n(0x49�̐^��) + csrw = (GBSY1 * 40) + ((GBSX1 + i*8) >> 4); + csrw += ((GBSX1 + i*8) & 0xf) << 20; + + if ((CPU_CH & 0x30) == 0x30) { + ope = (ucw.GBON_PTN & 1)?GDCOPE_SET:GDCOPE_CLEAR; + gdcsub_vectl(csrw + 0x4000, &vect, tmp, ope); + ope = (ucw.GBON_PTN & 2)?GDCOPE_SET:GDCOPE_CLEAR; + gdcsub_vectl(csrw + 0x8000, &vect, tmp, ope); + ope = (ucw.GBON_PTN & 4)?GDCOPE_SET:GDCOPE_CLEAR; + csrw += 0xc000; + gdcsub_vectl(csrw, &vect, tmp, ope); + } + else { + ope = ucw.GBDOTU & 3; + csrw += 0x4000 + ((CPU_CH & 0x30) << 10); + gdcsub_vectl(csrw, &vect, tmp, ope); + } + + //���̃f�[�^��������Δ����� + i++; + if(i*8 >= GBLNG1) break; + } + + // �Ō�Ɏg�����z���L�� + setbiosgdc(csrw, &vect, ope); +} +/* �������܂� ������(2ch?)�Ō��J���ꂽ�\�[�X */ + +static void bios0x18_47(void) { + + UCWTBL ucw; + GDCVECT vect; + UINT16 GBSX1; + UINT16 GBSY1; + UINT16 GBSX2; + UINT16 GBSY2; + GDCSUBFN func; + UINT32 csrw; + UINT16 data; + UINT16 data2; + UINT16 GBMDOTI; + UINT8 ope; + SINT16 dx; + SINT16 dy; + + gdc_forceready(GDCWORK_SLAVE); + MEMR_READS(CPU_DS, CPU_BX, &ucw, sizeof(ucw)); + GBSX1 = LOADINTELWORD(ucw.GBSX1); + GBSY1 = LOADINTELWORD(ucw.GBSY1); + GBSX2 = LOADINTELWORD(ucw.GBSX2); + GBSY2 = LOADINTELWORD(ucw.GBSY2); + ZeroMemory(&vect, sizeof(vect)); + data = 0; + data2 = 0; + if (ucw.GBDTYP == 0x01) { + func = gdcsub_vectl; + gdcsub_setvectl(&vect, GBSX1, GBSY1, GBSX2, GBSY2); + } + else if (ucw.GBDTYP <= 0x02) { + func = gdcsub_vectr; + vect.ope = 0x40 + (ucw.GBDSP & 7); + dx = GBSX2 - GBSX1; + if (dx < 0) { + dx = 0 - dx; + } + dy = GBSY2 - GBSY1; + if (dy < 0) { + dy = 0 - dy; + } + switch(ucw.GBDSP & 3) { + case 0: + data = dy; + data2 = dx; + break; + + case 1: + data2 = (UINT16)dx + (UINT16)dy; + data2 >>= 1; + data = (UINT16)dx - (UINT16)dy; + data = (data >> 1) & 0x3fff; + break; + + case 2: + data = dx; + data2 = dy; + break; + + case 3: + data2 = (UINT16)dx + (UINT16)dy; + data2 >>= 1; + data = (UINT16)dy - (UINT16)dx; + data = (data >> 1) & 0x3fff; + break; + } + STOREINTELWORD(vect.DC, 3); + STOREINTELWORD(vect.D, data); + STOREINTELWORD(vect.D2, data2); + STOREINTELWORD(vect.D1, 0xffff); + STOREINTELWORD(vect.DM, data); + } + else { + func = gdcsub_vectc; + vect.ope = 0x20 + (ucw.GBDSP & 7); + vect.DC[0] = ucw.GBLNG1[0]; + vect.DC[1] = ucw.GBLNG1[1]; +// data = LOADINTELWORD(ucw.GBLNG2) - 1; + data = LOADINTELWORD(ucw.GBCIR) - 1; + STOREINTELWORD(vect.D, data); + data >>= 1; + STOREINTELWORD(vect.D2, data); + STOREINTELWORD(vect.D1, 0x3fff); + if (ucw.GBDTYP == 0x04) { + vect.DM[0] = ucw.GBMDOT[0]; + vect.DM[1] = ucw.GBMDOT[1]; + } + } + if ((CPU_CH & 0xc0) == 0x40) { + GBSY1 += 200; + } + csrw = (GBSY1 * 40) + (GBSX1 >> 4); + csrw += (GBSX1 & 0xf) << 20; + GBMDOTI = (GDCPATREVERSE(ucw.GBMDOTI[0]) << 8) + + GDCPATREVERSE(ucw.GBMDOTI[1]); + if ((CPU_CH & 0x30) == 0x30) { + ope = (ucw.GBON_PTN & 1)?GDCOPE_SET:GDCOPE_CLEAR; + func(csrw + 0x4000, &vect, GBMDOTI, ope); + ope = (ucw.GBON_PTN & 2)?GDCOPE_SET:GDCOPE_CLEAR; + func(csrw + 0x8000, &vect, GBMDOTI, ope); + ope = (ucw.GBON_PTN & 4)?GDCOPE_SET:GDCOPE_CLEAR; + csrw += 0xc000; + func(csrw, &vect, GBMDOTI, ope); + } + else { + ope = ucw.GBDOTU & 3; + csrw += 0x4000 + ((CPU_CH & 0x30) << 10); + func(csrw, &vect, GBMDOTI, ope); + } + + // �Ō�Ɏg�����z���L�� + *(UINT16 *)(mem + MEMW_PRXGLS) = *(UINT16 *)(ucw.GBMDOTI); + STOREINTELWORD(mem + GDC_TEXTW, GBMDOTI); + setbiosgdc(csrw, &vect, ope); +} + +static void bios0x18_49(void) { + + UCWTBL ucw; + UINT i; + UINT8 pat[8]; + UINT16 tmp; + GDCVECT vect; + UINT16 GBSX1; + UINT16 GBSY1; + UINT32 csrw; + UINT8 ope; + + gdc_forceready(GDCWORK_SLAVE); + + MEMR_READS(CPU_DS, CPU_BX, &ucw, sizeof(ucw)); + for (i=0; i<8; i++) { + mem[MEMW_PRXGLS + i] = ucw.GBMDOTI[i]; + pat[i] = GDCPATREVERSE(ucw.GBMDOTI[i]); + gdc.s.para[GDC_TEXTW + i] = pat[i]; + } + vect.ope = 0x10 + (ucw.GBDSP & 7); + if (*(UINT16 *)ucw.GBLNG1) { + tmp = (LOADINTELWORD(ucw.GBLNG2) - 1) & 0x3fff; + STOREINTELWORD(vect.DC, tmp); + vect.D[0] = ucw.GBLNG1[0]; + vect.D[1] = ucw.GBLNG1[1]; + } + else { + STOREINTELWORD(vect.DC, 7); + STOREINTELWORD(vect.D, 7); + } + + GBSX1 = LOADINTELWORD(ucw.GBSX1); + GBSY1 = LOADINTELWORD(ucw.GBSY1); + if ((CPU_CH & 0xc0) == 0x40) { + GBSY1 += 200; + } + csrw = (GBSY1 * 40) + (GBSX1 >> 4); + csrw += (GBSX1 & 0xf) << 20; + if ((CPU_CH & 0x30) == 0x30) { + ope = (ucw.GBON_PTN & 1)?GDCOPE_SET:GDCOPE_CLEAR; + gdcsub_text(csrw + 0x4000, &vect, pat, ope); + ope = (ucw.GBON_PTN & 2)?GDCOPE_SET:GDCOPE_CLEAR; + gdcsub_text(csrw + 0x8000, &vect, pat, ope); + ope = (ucw.GBON_PTN & 4)?GDCOPE_SET:GDCOPE_CLEAR; + csrw += 0xc000; + gdcsub_text(csrw, &vect, pat, ope); + } + else { + ope = ucw.GBDOTU & 3; + csrw += 0x4000 + ((CPU_CH & 0x30) << 10); + gdcsub_text(csrw, &vect, pat, ope); + } + + // �Ō�Ɏg�����z���L�� + setbiosgdc(csrw, &vect, ope); +} + + +// ---- PC-9821 + +#if defined(SUPPORT_PC9821) +static void bios0x18_4d(REG8 mode) { + + if ((mem[0x45c] & 0x40) && + ((mem[MEMB_CRT_BIOS] & 3) == 2)) { + if (mode == 0) { + gdc_analogext(FALSE); + mem[MEMB_PRXDUPD] &= ~0x7f; + mem[MEMB_PRXDUPD] |= 0x04; + } + else if (mode == 1) { + gdc_analogext(TRUE); + mem[MEMB_PRXDUPD] |= 0x80; + } + else { + mem[MEMB_PRXDUPD] |= 0x04; + } + } +} +#endif + + +// ---- + +void bios0x18(void) { + + union { + BOOL b; + REG8 r8; + UINT16 w; + UINT32 d; + UINT8 col[4]; + } tmp; + int i; + +#if 0 + TRACEOUT(("int18 AX=%.4x %.4x:%.4x", CPU_AX, + MEMR_READ16(CPU_SS, CPU_SP+2), + MEMR_READ16(CPU_SS, CPU_SP))); +#endif + + switch(CPU_AH) { + case 0x00: // �L�[�E�f�[�^�̓ǂ݂��� + if (mem[MEMB_KB_COUNT]) { + CPU_AX = keyget(); + } + else { + CPU_IP--; + CPU_REMCLOCK = -1; + break; + } + break; + + case 0x01: // �L�[�E�o�b�t�@��Ԃ̃Z���X + if (mem[MEMB_KB_COUNT]) { + tmp.d = GETBIOSMEM16(MEMW_KB_BUF_HEAD); + CPU_AX = GETBIOSMEM16(tmp.d); + CPU_BH = 1; + } + else { + CPU_BH = 0; + } + break; + + case 0x02: // �V�t�g�E�L�[��Ԃ̃Z���X + CPU_AL = mem[MEMB_SHIFT_STS]; + break; + + case 0x03: // �L�[�{�[�h�E�C���^�t�F�C�X�̏����� +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + // np21w ver0.86 rev47 BIOS I/O emulation + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + biosioemu_enq8(0x43, 0x3a); + biosioemu_enq8(0x43, 0x32); + biosioemu_enq8(0x43, 0x16); + ZeroMemory(mem + 0x00502, 0x20); + ZeroMemory(mem + 0x00528, 0x13); + SETBIOSMEM16(MEMW_KB_SHIFT_TBL, 0x0e00); + SETBIOSMEM16(MEMW_KB_BUF_HEAD, 0x0502); + SETBIOSMEM16(MEMW_KB_BUF_TAIL, 0x0502); + SETBIOSMEM16(MEMW_KB_CODE_OFF, 0x0e00); + SETBIOSMEM16(MEMW_KB_CODE_SEG, 0xfd80); + }else +#endif + { + bios0x09_init(); + } + break; + + case 0x04: // �L�[���͏�Ԃ̃Z���X + CPU_AH = mem[MEMX_KB_KY_STS + (CPU_AL & 0x0f)]; + break; + + case 0x05: // �L�[���̓Z���X + if (mem[MEMB_KB_COUNT]) { + CPU_AX = keyget(); + CPU_BH = 1; + } + else { + CPU_BH = 0; + } + break; + + case 0x0a: // CRT���[�h�̐ݒ�(15/24khz) + bios0x18_0a(CPU_AL); + break; + + case 0x0b: // CRT���[�h�̃Z���X + CPU_AL = mem[MEMB_CRT_STS_FLAG]; + break; + + case 0x0c: // �e�L�X�g��ʂ̕\���J�n +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + // np21w ver0.86 rev47 BIOS I/O emulation + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + if (!(gdcs.textdisp & GDCSCRN_ENABLE)) { + pcstat.screenupdate |= 2; + } + biosioemu_push8(0x62, CMD_START); + } else +#endif + { + bios0x18_0c(); + } + break; + + case 0x0d: // �e�L�X�g��ʂ̕\���I�� +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + // np21w ver0.86 rev47 BIOS I/O emulation + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + if (gdcs.textdisp & GDCSCRN_ENABLE) { + pcstat.screenupdate |= 2; + } + biosioemu_push8(0x62, CMD_STOP); + } else +#endif + { + if (gdcs.textdisp & GDCSCRN_ENABLE) { + gdcs.textdisp &= ~(GDCSCRN_ENABLE); + pcstat.screenupdate |= 2; + } + } + break; + + case 0x0e: // ��‚̕\���̈�̐ݒ� + gdc_forceready(GDCWORK_MASTER); + ZeroMemory(&gdc.m.para[GDC_SCROLL], 16); + tmp.w = CPU_DX >> 1; + SETBIOSMEM16(MEMW_CRT_W_VRAMADR, tmp.w); + STOREINTELWORD(gdc.m.para + GDC_SCROLL + 0, tmp.w); + tmp.w = 200 << 4; + if (mem[MEMB_CRT_STS_FLAG] & 0x80) { + tmp.w <<= 1; + } + SETBIOSMEM16(MEMW_CRT_W_RASTER, tmp.w); + STOREINTELWORD(gdc.m.para + GDC_SCROLL + 2, tmp.w); + gdcs.textdisp |= GDCSCRN_ALLDRAW2; +// pcstat.screenupdate |= 2; + break; + + case 0x0f: // �����̕\���̈�̐ݒ� + gdc_forceready(GDCWORK_MASTER); + bios0x18_0f(CPU_BX, CPU_CX, CPU_DH, CPU_DL); + break; + + case 0x10: // �J�[�\���^�C�v�̐ݒ�(15/24khz) + gdc_forceready(GDCWORK_MASTER); + bios0x18_10((REG8)(CPU_AL & 1)); + break; + + case 0x11: // �J�[�\���̕\���J�n + gdc_forceready(GDCWORK_MASTER); + if (gdc.m.para[GDC_CSRFORM] != (mem[MEMB_CRT_RASTER] | 0x80)) { + gdc.m.para[GDC_CSRFORM] = mem[MEMB_CRT_RASTER] | 0x80; + } + gdcs.textdisp |= GDCSCRN_ALLDRAW | GDCSCRN_EXT; + break; + + case 0x12: // �J�[�\���̕\����~ + gdc_forceready(GDCWORK_MASTER); + if (gdc.m.para[GDC_CSRFORM] != mem[MEMB_CRT_RASTER]) { + gdc.m.para[GDC_CSRFORM] = mem[MEMB_CRT_RASTER]; + gdcs.textdisp |= GDCSCRN_ALLDRAW | GDCSCRN_EXT; + } + break; + + case 0x13: // �J�[�\���ʒu�̐ݒ� + gdc_forceready(GDCWORK_MASTER); + tmp.w = CPU_DX >> 1; + if (LOADINTELWORD(gdc.m.para + GDC_CSRW) != tmp.w) { + STOREINTELWORD(gdc.m.para + GDC_CSRW, tmp.w); + gdcs.textdisp |= GDCSCRN_EXT; + } + break; + + case 0x14: // �t�H���g�p�^�[���̓ǂݏo�� + bios0x18_14(CPU_BX, CPU_CX, CPU_DX); + break; + + case 0x15: // ���C�g�y���ʒu�ǂ݂��� + break; + + case 0x16: // �e�L�X�gVRAM�̏����� + bios0x18_16(CPU_DL, CPU_DH); + break; + + case 0x17: // �u�U�[�̋N�� + iocore_out8(0x37, 0x06); + break; + + case 0x18: // �u�U�[�̒�~ + iocore_out8(0x37, 0x07); + break; + + case 0x19: // ���C�g�y��������Ԃ̏����� + break; + + case 0x1a: // ���[�U�[�����̒�` + bios0x18_1a(CPU_BX, CPU_CX, CPU_DX); + break; + + case 0x1b: // KCG�A�N�Z�X���[�h�̐ݒ� + switch(CPU_AL) { + case 0: + mem[MEMB_CRT_STS_FLAG] &= ~0x08; + gdc.mode1 &= ~0x20; + gdc_restorekacmode(); + break; + + case 1: + mem[MEMB_CRT_STS_FLAG] |= 0x08; + gdc.mode1 |= 0x20; + gdc_restorekacmode(); + break; + } + break; +#if defined(SUPPORT_CRT31KHZ) + case 0x30: + if (mem[MEMB_CRT_BIOS] & 0x80) { + gdc_forceready(GDCWORK_MASTER); + gdc_forceready(GDCWORK_SLAVE); + tmp.r8 = bios0x18_30(CPU_AL, CPU_BH); + CPU_AH = tmp.r8; + if (tmp.r8 == 0x05) { + CPU_AL = 0; + CPU_BH = 0; + } + else { + CPU_AL = 1; + CPU_BH = 1; + } + } + break; + + case 0x31: + if (mem[MEMB_CRT_BIOS] & 0x80) { + CPU_AL = bios0x18_31al(); + CPU_BH = bios0x18_31bh(); + } + break; +#endif + case 0x40: // �O���t�B�b�N��ʂ̕\���J�n +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + // np21w ver0.86 rev47 BIOS I/O emulation + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + gdc_forceready(GDCWORK_SLAVE); + if (!(gdcs.grphdisp & GDCSCRN_ENABLE)) { + pcstat.screenupdate |= 2; + } + biosioemu_push8(0xa2, CMD_START); + mem[MEMB_PRXCRT] |= 0x80; + } else +#endif + { + bios0x18_40(); + } + break; + + case 0x41: // �O���t�B�b�N��ʂ̕\���I�� +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + // np21w ver0.86 rev47 BIOS I/O emulation + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + gdc_forceready(GDCWORK_SLAVE); + if (gdcs.grphdisp & GDCSCRN_ENABLE) { + pcstat.screenupdate |= 2; + } + biosioemu_push8(0xa2, CMD_STOP); + mem[MEMB_PRXCRT] &= 0x7f; + } else +#endif + { + bios0x18_41(); + } + break; + + case 0x42: // �\���̈�̐ݒ� + bios0x18_42(CPU_CH); + break; + + case 0x43: // �p���b�g�̐ݒ� + MEMR_READS(CPU_DS, CPU_BX + offsetof(UCWTBL, GBCPC), tmp.col, 4); + for (i=0; i<4; i++) { + gdc_setdegitalpal(6 - (i*2), (REG8)(tmp.col[i] >> 4)); + gdc_setdegitalpal(7 - (i*2), (REG8)(tmp.col[i] & 15)); + } + break; + + case 0x44: // �{�[�_�J���[�̐ݒ� +// if (!(mem[MEMB_PRXCRT] & 0x40)) { +// color = MEMR_READ8(CPU_DS, CPU_BX + 1); +// } + break; + case 0x45: /* int18,45h��lj�(from Kai2, np21w ver0.86 rev16) */ + bios0x18_45(); + break; + case 0x46: + TRACEOUT(("unsupport bios 18-%.2x", CPU_AH)); + break; + + case 0x47: // �����A��`�̕`�� + case 0x48: // �~�̕`�� + bios0x18_47(); + break; + + case 0x49: // �O���t�B�b�N�����̕`�� + bios0x18_49(); + break; + + case 0x4a: // �`�惂�[�h�̐ݒ� + if (!(mem[MEMB_PRXCRT] & 0x01)) { + gdc.s.para[GDC_SYNC] = CPU_CH; + gdcs.grphdisp |= GDCSCRN_EXT; + if (CPU_CH & 0x10) { + mem[MEMB_PRXDUPD] &= ~0x08; + } + else { + mem[MEMB_PRXDUPD] |= 0x08; + } + } + break; +#if defined(SUPPORT_PC9821) + case 0x4d: + bios0x18_4d(CPU_CH); + break; +#endif + } +} + + diff --git a/bios/bios19.c b/bios/bios19.c old mode 100755 new mode 100644 index cd2e3e6c..7e24a625 --- a/bios/bios19.c +++ b/bios/bios19.c @@ -1,193 +1,193 @@ -#include -#include -#include -#include -#include -#include -#include "rsbios.h" - - -static const UINT rs_speed[] = { - // 5MHz - 0x0800, 0x0400, 0x0200, 0x0100, - 0x0080, 0x0040, 0x0020, 0x0010, - 0x0008, 0x0004, 0x0002, 0x0001, - // 4MHz - 0x0680, 0x0340, 0x01a0, 0x00d0, - 0x0068, 0x0034, 0x001a, 0x000d}; - - -void bios0x19(void) { - - UINT8 speed; - UINT8 mode; - RSBIOS rsb; - UINT16 doff; - UINT16 cnt; - UINT16 dseg; - UINT8 flag; - - if (CPU_AH < 2) { - // 通信速度… - mode = CPU_CH | 0x02; - speed = CPU_AL; - if (speed >= 8) { - speed = 4; // 1200bps - } - if (mem[MEMB_BIOS_FLAG1] & 0x80) { // 4MHz? - speed += 12; - } - -#if 1 // NP2では未サポートの為 強行(汗 - mode &= ~1; -#else - if (mode & 1) { - if (speed < (12 + 6)) { - speed += 2; - } - else { - mode &= ~1; - } - } - // シリアルリセット - iocore_out8(0x32, 0x00); // dummy instruction - iocore_out8(0x32, 0x00); // dummy instruction - iocore_out8(0x32, 0x00); // dummy instruction - iocore_out8(0x32, 0x40); // reset - iocore_out8(0x32, mode); // mode - iocore_out8(0x32, CPU_CL); // cmd -#endif - iocore_out8(0x77, 0xb6); - iocore_out8(0x75, (UINT8)rs_speed[speed]); - iocore_out8(0x75, (UINT8)(rs_speed[speed] >> 8)); - - ZeroMemory(&rsb, sizeof(rsb)); - rsb.FLAG = (CPU_AH << 4); - rsb.CMD = CPU_CL; - sysport.c &= ~7; - if (!(CPU_CL & RCMD_IR)) { - rsb.FLAG |= RFLAG_INIT; - if (CPU_CL & RCMD_RXE) { - sysport.c |= 1; - pic.pi[0].imr &= ~PIC_RS232C; - } - } - - rsb.STIME = CPU_BH; - if (!rsb.STIME) { - rsb.STIME = 0x04; - } - rsb.RTIME = CPU_BL; - if (!rsb.RTIME) { - rsb.RTIME = 0x40; - } - doff = CPU_DI + sizeof(RSBIOS); - STOREINTELWORD(rsb.HEADP, doff); - STOREINTELWORD(rsb.PUTP, doff); - STOREINTELWORD(rsb.GETP, doff); - doff += CPU_DX; - STOREINTELWORD(rsb.TAILP, doff); - cnt = CPU_DX >> 3; - STOREINTELWORD(rsb.XOFF, cnt); - cnt += CPU_DX >> 2; - STOREINTELWORD(rsb.XON, cnt); - - // ポインタ〜 - SETBIOSMEM16(MEMW_RS_CH0_OFST, CPU_DI); - SETBIOSMEM16(MEMW_RS_CH0_SEG, CPU_ES); - MEMR_WRITES(CPU_ES, CPU_DI, &rsb, sizeof(rsb)); - - CPU_AH = 0; - } - else if (CPU_AH < 7) { - doff = GETBIOSMEM16(MEMW_RS_CH0_OFST); - dseg = GETBIOSMEM16(MEMW_RS_CH0_SEG); - if ((!doff) && (!dseg)) { - CPU_AH = 1; - return; - } - flag = MEMR_READ8(dseg, doff + R_FLAG); - if (!(flag & RFLAG_INIT)) { - CPU_AH = 1; - return; - } - switch(CPU_AH) { - case 0x02: - CPU_CX = MEMR_READ16(dseg, doff + R_CNT); - break; - - case 0x03: - iocore_out8(0x30, CPU_AL); - break; - - case 0x04: - cnt = MEMR_READ16(dseg, doff + R_CNT); - if (cnt) { - UINT16 pos; - - // データ引き取り - pos = MEMR_READ16(dseg, doff + R_GETP); - CPU_CX = MEMR_READ16(dseg, pos); - - // 次のポインタをストア - pos += 2; - if (pos >= MEMR_READ16(dseg, doff + R_TAILP)) { - pos = MEMR_READ16(dseg, doff + R_HEADP); - } - MEMR_WRITE16(dseg, doff + R_GETP, pos); - - // カウンタをデクリメント - cnt--; - MEMR_WRITE16(dseg, doff + R_CNT, cnt); - - // XONを送信? - if ((flag & RFLAG_XOFF) && - (cnt < MEMR_READ16(dseg, doff + R_XOFF))) { - iocore_out8(0x30, RSCODE_XON); - flag &= ~RFLAG_XOFF; - } - flag &= ~RFLAG_BOVF; - CPU_AH = 0; - MEMR_WRITE8(dseg, doff + R_FLAG, flag); - return; - } - else { - CPU_AH = 3; - } - break; - - case 0x05: - iocore_out8(0x32, CPU_AL); - if (CPU_AL & RCMD_IR) { - flag &= ~RFLAG_INIT; - MEMR_WRITE8(dseg, doff + R_FLAG, flag); - sysport.c &= ~1; - pic.pi[0].imr |= PIC_RS232C; - } - else if (!(CPU_AL & RCMD_RXE)) { - sysport.c &= ~1; - pic.pi[0].imr |= PIC_RS232C; - } - else { - sysport.c |= 1; - pic.pi[0].imr &= ~PIC_RS232C; - } - MEMR_WRITE8(dseg, doff + R_CMD, CPU_AL); - break; - - case 0x06: - CPU_CH = iocore_inp8(0x32); - CPU_CL = iocore_inp8(0x33); - break; - } - CPU_AH = 0; - if (flag & RFLAG_BOVF) { - MEMR_WRITE8(dseg, doff + R_FLAG, (UINT8)(flag & (~RFLAG_BOVF))); - CPU_AH = 2; - } - } - else { - CPU_AH = 0; - } -} - +#include +#include +#include +#include +#include +#include +#include "rsbios.h" + + +static const UINT rs_speed[] = { + // 5MHz + 0x0800, 0x0400, 0x0200, 0x0100, + 0x0080, 0x0040, 0x0020, 0x0010, + 0x0008, 0x0004, 0x0002, 0x0001, + // 4MHz + 0x0680, 0x0340, 0x01a0, 0x00d0, + 0x0068, 0x0034, 0x001a, 0x000d}; + + +void bios0x19(void) { + + UINT8 speed; + UINT8 mode; + RSBIOS rsb; + UINT16 doff; + UINT16 cnt; + UINT16 dseg; + UINT8 flag; + + if (CPU_AH < 2) { + // 通信速度… + mode = CPU_CH | 0x02; + speed = CPU_AL; + if (speed >= 8) { + speed = 4; // 1200bps + } + if (mem[MEMB_BIOS_FLAG1] & 0x80) { // 4MHz? + speed += 12; + } + +#if 1 // NP2では未サポートの為 強行(汗 + mode &= ~1; +#else + if (mode & 1) { + if (speed < (12 + 6)) { + speed += 2; + } + else { + mode &= ~1; + } + } + // シリアルリセット + iocore_out8(0x32, 0x00); // dummy instruction + iocore_out8(0x32, 0x00); // dummy instruction + iocore_out8(0x32, 0x00); // dummy instruction + iocore_out8(0x32, 0x40); // reset + iocore_out8(0x32, mode); // mode + iocore_out8(0x32, CPU_CL); // cmd +#endif + iocore_out8(0x77, 0xb6); + iocore_out8(0x75, (UINT8)rs_speed[speed]); + iocore_out8(0x75, (UINT8)(rs_speed[speed] >> 8)); + + ZeroMemory(&rsb, sizeof(rsb)); + rsb.FLAG = (CPU_AH << 4); + rsb.CMD = CPU_CL; + sysport.c &= ~7; + if (!(CPU_CL & RCMD_IR)) { + rsb.FLAG |= RFLAG_INIT; + if (CPU_CL & RCMD_RXE) { + sysport.c |= 1; + pic.pi[0].imr &= ~PIC_RS232C; + } + } + + rsb.STIME = CPU_BH; + if (!rsb.STIME) { + rsb.STIME = 0x04; + } + rsb.RTIME = CPU_BL; + if (!rsb.RTIME) { + rsb.RTIME = 0x40; + } + doff = CPU_DI + sizeof(RSBIOS); + STOREINTELWORD(rsb.HEADP, doff); + STOREINTELWORD(rsb.PUTP, doff); + STOREINTELWORD(rsb.GETP, doff); + doff += CPU_DX; + STOREINTELWORD(rsb.TAILP, doff); + cnt = CPU_DX >> 3; + STOREINTELWORD(rsb.XOFF, cnt); + cnt += CPU_DX >> 2; + STOREINTELWORD(rsb.XON, cnt); + + // ポインタ〜 + SETBIOSMEM16(MEMW_RS_CH0_OFST, CPU_DI); + SETBIOSMEM16(MEMW_RS_CH0_SEG, CPU_ES); + MEMR_WRITES(CPU_ES, CPU_DI, &rsb, sizeof(rsb)); + + CPU_AH = 0; + } + else if (CPU_AH < 7) { + doff = GETBIOSMEM16(MEMW_RS_CH0_OFST); + dseg = GETBIOSMEM16(MEMW_RS_CH0_SEG); + if ((!doff) && (!dseg)) { + CPU_AH = 1; + return; + } + flag = MEMR_READ8(dseg, doff + R_FLAG); + if (!(flag & RFLAG_INIT)) { + CPU_AH = 1; + return; + } + switch(CPU_AH) { + case 0x02: + CPU_CX = MEMR_READ16(dseg, doff + R_CNT); + break; + + case 0x03: + iocore_out8(0x30, CPU_AL); + break; + + case 0x04: + cnt = MEMR_READ16(dseg, doff + R_CNT); + if (cnt) { + UINT16 pos; + + // データ引き取り + pos = MEMR_READ16(dseg, doff + R_GETP); + CPU_CX = MEMR_READ16(dseg, pos); + + // 次のポインタをストア + pos += 2; + if (pos >= MEMR_READ16(dseg, doff + R_TAILP)) { + pos = MEMR_READ16(dseg, doff + R_HEADP); + } + MEMR_WRITE16(dseg, doff + R_GETP, pos); + + // カウンタをデクリメント + cnt--; + MEMR_WRITE16(dseg, doff + R_CNT, cnt); + + // XONを送信? + if ((flag & RFLAG_XOFF) && + (cnt < MEMR_READ16(dseg, doff + R_XOFF))) { + iocore_out8(0x30, RSCODE_XON); + flag &= ~RFLAG_XOFF; + } + flag &= ~RFLAG_BOVF; + CPU_AH = 0; + MEMR_WRITE8(dseg, doff + R_FLAG, flag); + return; + } + else { + CPU_AH = 3; + } + break; + + case 0x05: + iocore_out8(0x32, CPU_AL); + if (CPU_AL & RCMD_IR) { + flag &= ~RFLAG_INIT; + MEMR_WRITE8(dseg, doff + R_FLAG, flag); + sysport.c &= ~1; + pic.pi[0].imr |= PIC_RS232C; + } + else if (!(CPU_AL & RCMD_RXE)) { + sysport.c &= ~1; + pic.pi[0].imr |= PIC_RS232C; + } + else { + sysport.c |= 1; + pic.pi[0].imr &= ~PIC_RS232C; + } + MEMR_WRITE8(dseg, doff + R_CMD, CPU_AL); + break; + + case 0x06: + CPU_CH = iocore_inp8(0x32); + CPU_CL = iocore_inp8(0x33); + break; + } + CPU_AH = 0; + if (flag & RFLAG_BOVF) { + MEMR_WRITE8(dseg, doff + R_FLAG, (UINT8)(flag & (~RFLAG_BOVF))); + CPU_AH = 2; + } + } + else { + CPU_AH = 0; + } +} + diff --git a/bios/bios1a.c b/bios/bios1a.c old mode 100755 new mode 100644 index a3dcb592..f46d3666 --- a/bios/bios1a.c +++ b/bios/bios1a.c @@ -1,472 +1,472 @@ -#include -#include -#include -#include -#include - -#if defined(SUPPORT_PCI) -#include -#include "ia32/instructions/data_trans.h" -#endif - -// ---- CMT - -void bios0x1a_cmt(void) { - - if (CPU_AH == 0x04) { - CPU_AH = 0x02; - } - else { - CPU_AH = 0x00; - } -} - - -// ---- Printer - -static void printerbios_11(void) { - - if (iocore_inp8(0x42) & 0x04) { // busy? - CPU_AH = 0x01; - iocore_out8(0x40, CPU_AL); -#if 0 - iocore_out8(0x46, 0x0e); - iocore_out8(0x46, 0x0f); -#endif - } - else { - CPU_AH = 0x02; - } -} - -void bios0x1a_prt(void) { - - switch(CPU_AH & 0x0f) { - case 0x00: - if (CPU_AH == 0x30) { - if (CPU_CX) { - do { - CPU_AL = MEMR_READ8(CPU_ES, CPU_BX); - printerbios_11(); - if (CPU_AH & 0x02) { - CPU_AH = 0x02; - return; - } - CPU_BX++; - } while(--CPU_CX); - CPU_AH = 0x00; - } - else { - CPU_AH = 0x02; - } - } - else { - iocore_out8(0x37, 0x0d); // printer f/f - iocore_out8(0x46, 0x82); // reset - iocore_out8(0x46, 0x0f); // PSTB inactive - iocore_out8(0x37, 0x0c); // printer f/f - CPU_AH = (iocore_inp8(0x42) >> 2) & 1; - } - break; - - case 0x01: - printerbios_11(); - break; - - case 0x02: - CPU_AH = (iocore_inp8(0x42) >> 2) & 1; - break; - - default: - CPU_AH = 0x00; - break; - } -} - - -#if defined(SUPPORT_PCI) - -// ---- PCI - -enum { - PCIBIOS_STATUS_SUCCESSFUL = 0x00, - PCIBIOS_STATUS_UNSUPPORTED_FUNCTION = 0x81, - PCIBIOS_STATUS_BAD_VENDOR_ID = 0x83, - PCIBIOS_STATUS_DEVICE_NOT_FOUND = 0x86, - PCIBIOS_STATUS_BAD_PCI_REG_NUMBER = 0x87, - PCIBIOS_STATUS_SET_FAILED = 0x88, - PCIBIOS_STATUS_BUFFER_TOO_SMALL = 0x89, -}; - -void bios0x1a_pci_part(int is32bit) { - - int i; - int idx; - int devnum; - int funcnum; - - switch(CPU_AL & 0x7f) { - case 0x01: // INSTALLATION CHECK - CPU_AH = 0x00; - CPU_FLAGL &= ~C_FLAG; - CPU_EDX = 0x20494350; // " ICP" - //CPU_EDI = 0; // XXX: physical address of protected-mode entry point - CPU_AL = 0x01; // configuration space access mechanism 1 supported - CPU_BH = 0x02; // PCI interface level major version (BCD) - CPU_BL = 0x00; // PCI interface level minor version (BCD) - CPU_CL = 0x0; // number of last PCI bus in system - - pcidev_updateBIOS32data(); - break; - - case 0x02: // FIND PCI DEVICE - // デバイスを探す - for(i=0;i> 3; - funcnum = CPU_BL & 0x7; - if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ - if(CPU_DI <= 0xff){ - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - CPU_CL = pcidev.devices[devnum].cfgreg8[CPU_DI]; - }else{ - CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; - CPU_FLAGL |= C_FLAG; - CPU_CL = 0xff; - } - }else{ - //CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; - //CPU_FLAGL |= C_FLAG; - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - CPU_CL = 0xff; - } - break; - case 0x09: // READ CONFIGURATION WORD - devnum = CPU_BL >> 3; - funcnum = CPU_BL & 0x7; - if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ - if(CPU_DI <= 0xff){ - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - CPU_CX = *((UINT16*)(pcidev.devices[devnum].cfgreg8 + CPU_DI)); // XXX: 2の倍数のレジスタ番号でなくても読めちゃうけどまあいいかー - }else{ - CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; - CPU_FLAGL |= C_FLAG; - CPU_CX = 0xffff; - } - }else{ - //CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; - //CPU_FLAGL |= C_FLAG; - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - CPU_CX = 0xffff; - } - break; - case 0x0A: // READ CONFIGURATION DWORD - devnum = CPU_BL >> 3; - funcnum = CPU_BL & 0x7; - if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ - if(CPU_DI <= 0xff){ - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - CPU_ECX = *((UINT32*)(pcidev.devices[devnum].cfgreg8 + CPU_DI)); // XXX: 4の倍数のレジスタ番号でなくても読めちゃうけどまあいいかー - }else{ - CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; - CPU_FLAGL |= C_FLAG; - CPU_ECX = 0xffffffff; - } - }else{ - //CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; - //CPU_FLAGL |= C_FLAG; - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - CPU_ECX = 0xffffffff; - } - break; - - case 0x0B: // WRITE CONFIGURATION BYTE - devnum = CPU_BL >> 3; - funcnum = CPU_BL & 0x7; - if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ - if(CPU_DI <= 0xff){ - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - pcidev.devices[devnum].cfgreg8[CPU_DI] = CPU_CL; - }else{ - CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; - CPU_FLAGL |= C_FLAG; - } - }else{ - CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; - CPU_FLAGL |= C_FLAG; - } - break; - case 0x0C: // WRITE CONFIGURATION WORD - devnum = CPU_BL >> 3; - funcnum = CPU_BL & 0x7; - if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ - if(CPU_DI <= 0xff){ - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - *((UINT16*)(pcidev.devices[devnum].cfgreg8 + CPU_DI)) = CPU_CX; // XXX: 2の倍数のレジスタ番号でなくても書けちゃうけどまあいいかー - }else{ - CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; - CPU_FLAGL |= C_FLAG; - } - }else{ - CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; - CPU_FLAGL |= C_FLAG; - } - break; - case 0x0D: // WRITE CONFIGURATION DWORD - devnum = CPU_BL >> 3; - funcnum = CPU_BL & 0x7; - if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ - if(CPU_DI <= 0xff){ - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - *((UINT32*)(pcidev.devices[devnum].cfgreg8 + CPU_DI)) = CPU_ECX; // XXX: 4の倍数のレジスタ番号でなくても書けちゃうけどまあいいかー - }else{ - CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; - CPU_FLAGL |= C_FLAG; - } - }else{ - CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; - CPU_FLAGL |= C_FLAG; - } - break; - - case 0x0E: // GET IRQ ROUTING INFORMATION - if(CPU_BX == 0x0000){ - UINT16 dataSize = 0; - UINT32 dataAddress = 0; // seg:ofs - pcidev_updateBIOS32data(); - if(is32bit){ - // 32bit - dataSize = MEMR_READ16(CPU_ES, CPU_EDI); - dataAddress = (UINT32)MEMR_READ16(CPU_ES, CPU_EDI+2)|(((UINT32)MEMR_READ16(CPU_ES, CPU_EDI+4)) << 16); - if(dataSize < pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)){ - MEMR_WRITE16(CPU_ES, CPU_EDI, pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)); - CPU_AH = PCIBIOS_STATUS_BUFFER_TOO_SMALL; - CPU_FLAGL |= C_FLAG; - }else{ - dataSize = pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY); - MEMR_WRITE16(CPU_ES, CPU_EDI, dataSize); - MEMR_WRITES((dataAddress >> 16) & 0xffff, dataAddress & 0xffff, pcidev.biosdata.data, dataSize); - CPU_BX = pcidev.allirqbitmap; - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - } - }else{ - // 16bit - dataSize = MEMR_READ16(CPU_ES, CPU_DI); - dataAddress = (UINT32)MEMR_READ16(CPU_ES, CPU_DI+2)|(((UINT32)MEMR_READ16(CPU_ES, CPU_DI+4)) << 16); - if(dataSize < pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)){ - MEMR_WRITE16(CPU_ES, CPU_DI, pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)); - CPU_AH = PCIBIOS_STATUS_BUFFER_TOO_SMALL; - CPU_FLAGL |= C_FLAG; - }else{ - dataSize = pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY); - MEMR_WRITE16(CPU_ES, CPU_DI, dataSize); - MEMR_WRITES((dataAddress >> 16) & 0xffff, dataAddress & 0xffff, pcidev.biosdata.data, dataSize); - CPU_BX = pcidev.allirqbitmap; - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - } - } - }else{ - CPU_AH = PCIBIOS_STATUS_UNSUPPORTED_FUNCTION; - CPU_FLAGL |= C_FLAG; - } - break; - - case 0x0F: // SET PCI IRQ - devnum = CPU_BL >> 3; - funcnum = CPU_BL & 0x7; - //if(CPU_BH==0 && 0x0A <= CPU_CL && CPU_CL <= 0x0D && (CPU_CH & 0xf0)==0 && pcidev.devices[devnum].enable){ - // UINT8 intpinidx = CPU_CL - 0x0A; - // CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - // CPU_FLAGL &= ~C_FLAG; - //}else{ - CPU_AH = PCIBIOS_STATUS_SET_FAILED; - CPU_FLAGL |= C_FLAG; - //} - break; - - default: - if(CPU_EAX==0x49435024){ - // Find BIOS32 Service Directory Entry Point by using $PCI signature - CPU_EBX = (pcidev.bios32entrypoint & 0xff000); - CPU_ECX = 1; - CPU_EDX = (pcidev.bios32entrypoint & 0xfff); - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_AL = 0; - CPU_FLAGL &= ~C_FLAG; - }else{ - CPU_AH = PCIBIOS_STATUS_UNSUPPORTED_FUNCTION; - CPU_FLAGL |= C_FLAG; - } - break; - } -} -void bios0x1a_pci(void) { - - UINT32 oldDX; - oldDX = CPU_DX; - - if(pcidev.enable){ -#if !defined(SUPPORT_IA32_HAXM) - // XXX: np2 BIOSがDXレジスタをPUSH/POPしてしまうので、DXレジスタの内容をスタックから強引に拾ってくる - CPU_DX = cpu_vmemoryread_w(CPU_SS_INDEX, CPU_SP + 2); -#endif - - // 16bit PCI BIOS処理 - bios0x1a_pci_part(0); - -#if !defined(SUPPORT_IA32_HAXM) - // XXX: np2 BIOSがDXレジスタをPUSH/POPしてしまうので、DXレジスタの内容をスタックに強引に書き込む - cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_SP + 2, (UINT16)CPU_DX); - - // DXレジスタの値を元に戻す - CPU_DX = oldDX; -#endif - } -} -void bios0x1a_pcipnp(void) { - - UINT32 oldDX; - oldDX = CPU_DX; - - if(pcidev.enable){ -#if !defined(SUPPORT_IA32_HAXM) - // XXX: np2 BIOSがDXレジスタをPUSH/POPしてしまうので、DXレジスタの内容をスタックから強引に拾ってくる - CPU_DX = cpu_vmemoryread_w(CPU_SS_INDEX, CPU_SP + 2); -#endif - - switch(CPU_AL & 0x7f) { - case 0x00: // Intel Plug-and-Play AUTO-CONFIGURATION - INSTALLATION CHECK - CPU_AX = 0x0000; - CPU_FLAGL &= ~C_FLAG; - CPU_EDX = 0x47464341; // "GFCA" - CPU_BH = 0x02; // ACFG major version (02h) - CPU_BL = 0x08; // ACFG minor version (08h) - CPU_CX = 0x0002; - CPU_SI = 0x001F; - - pcidev_updateBIOS32data(); - - break; - case 0x06: // Intel Plug-and-Play AUTO-CONFIGURATION - GET PCI IRQ ROUTING TABLE - if(CPU_BX == 0x0000){ - UINT16 dataSize = 0; - UINT32 dataAddress = 0; - pcidev_updateBIOS32data(); - if(CPU_AL & 0x80){ - // 32bit - dataSize = MEMR_READ16(CPU_ES, CPU_EDI); - dataAddress = (UINT32)MEMR_READ16(CPU_ES, CPU_EDI+2)|(((UINT32)MEMR_READ16(CPU_ES, CPU_EDI+4)) << 16); - if(dataSize < pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)){ - MEMR_WRITE16(CPU_ES, CPU_EDI, pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)); - CPU_AH = PCIBIOS_STATUS_BUFFER_TOO_SMALL; - CPU_FLAGL |= C_FLAG; - }else{ - dataSize = pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY); - MEMR_WRITE16(CPU_ES, CPU_EDI, dataSize); - MEMR_WRITES((dataAddress >> 16) & 0xffff, dataAddress & 0xffff, pcidev.biosdata.data, dataSize); - CPU_BX = pcidev.allirqbitmap; - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - } - }else{ - // 16bit - dataSize = MEMR_READ16(CPU_ES, CPU_DI); - dataAddress = (UINT32)MEMR_READ16(CPU_ES, CPU_DI+2)|(((UINT32)MEMR_READ16(CPU_ES, CPU_DI+4)) << 16); - if(dataSize < pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)){ - MEMR_WRITE16(CPU_ES, CPU_DI, pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)); - CPU_AH = PCIBIOS_STATUS_BUFFER_TOO_SMALL; - CPU_FLAGL |= C_FLAG; - }else{ - dataSize = pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY); - MEMR_WRITE16(CPU_ES, CPU_DI, dataSize); - MEMR_WRITES((dataAddress >> 16) & 0xffff, dataAddress & 0xffff, pcidev.biosdata.data, dataSize); - CPU_BX = pcidev.allirqbitmap; - CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; - CPU_FLAGL &= ~C_FLAG; - } - } - }else{ - CPU_AH = PCIBIOS_STATUS_UNSUPPORTED_FUNCTION; - CPU_FLAGL |= C_FLAG; - } - break; - - default: - CPU_AH = PCIBIOS_STATUS_UNSUPPORTED_FUNCTION; - CPU_FLAGL |= C_FLAG; - break; - } - -#if !defined(SUPPORT_IA32_HAXM) - // XXX: np2 BIOSがDXレジスタをPUSH/POPしてしまうので、DXレジスタの内容をスタックに強引に書き込む - cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_SP + 2, (UINT16)CPU_DX); - - // DXレジスタの値を元に戻す - CPU_DX = oldDX; -#endif - } -} - -#endif +#include +#include +#include +#include +#include + +#if defined(SUPPORT_PCI) +#include +#include "ia32/instructions/data_trans.h" +#endif + +// ---- CMT + +void bios0x1a_cmt(void) { + + if (CPU_AH == 0x04) { + CPU_AH = 0x02; + } + else { + CPU_AH = 0x00; + } +} + + +// ---- Printer + +static void printerbios_11(void) { + + if (iocore_inp8(0x42) & 0x04) { // busy? + CPU_AH = 0x01; + iocore_out8(0x40, CPU_AL); +#if 0 + iocore_out8(0x46, 0x0e); + iocore_out8(0x46, 0x0f); +#endif + } + else { + CPU_AH = 0x02; + } +} + +void bios0x1a_prt(void) { + + switch(CPU_AH & 0x0f) { + case 0x00: + if (CPU_AH == 0x30) { + if (CPU_CX) { + do { + CPU_AL = MEMR_READ8(CPU_ES, CPU_BX); + printerbios_11(); + if (CPU_AH & 0x02) { + CPU_AH = 0x02; + return; + } + CPU_BX++; + } while(--CPU_CX); + CPU_AH = 0x00; + } + else { + CPU_AH = 0x02; + } + } + else { + iocore_out8(0x37, 0x0d); // printer f/f + iocore_out8(0x46, 0x82); // reset + iocore_out8(0x46, 0x0f); // PSTB inactive + iocore_out8(0x37, 0x0c); // printer f/f + CPU_AH = (iocore_inp8(0x42) >> 2) & 1; + } + break; + + case 0x01: + printerbios_11(); + break; + + case 0x02: + CPU_AH = (iocore_inp8(0x42) >> 2) & 1; + break; + + default: + CPU_AH = 0x00; + break; + } +} + + +#if defined(SUPPORT_PCI) + +// ---- PCI + +enum { + PCIBIOS_STATUS_SUCCESSFUL = 0x00, + PCIBIOS_STATUS_UNSUPPORTED_FUNCTION = 0x81, + PCIBIOS_STATUS_BAD_VENDOR_ID = 0x83, + PCIBIOS_STATUS_DEVICE_NOT_FOUND = 0x86, + PCIBIOS_STATUS_BAD_PCI_REG_NUMBER = 0x87, + PCIBIOS_STATUS_SET_FAILED = 0x88, + PCIBIOS_STATUS_BUFFER_TOO_SMALL = 0x89, +}; + +void bios0x1a_pci_part(int is32bit) { + + int i; + int idx; + int devnum; + int funcnum; + + switch(CPU_AL & 0x7f) { + case 0x01: // INSTALLATION CHECK + CPU_AH = 0x00; + CPU_FLAGL &= ~C_FLAG; + CPU_EDX = 0x20494350; // " ICP" + //CPU_EDI = 0; // XXX: physical address of protected-mode entry point + CPU_AL = 0x01; // configuration space access mechanism 1 supported + CPU_BH = 0x02; // PCI interface level major version (BCD) + CPU_BL = 0x00; // PCI interface level minor version (BCD) + CPU_CL = 0x0; // number of last PCI bus in system + + pcidev_updateBIOS32data(); + break; + + case 0x02: // FIND PCI DEVICE + // デバイスを探す + for(i=0;i> 3; + funcnum = CPU_BL & 0x7; + if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ + if(CPU_DI <= 0xff){ + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + CPU_CL = pcidev.devices[devnum].cfgreg8[CPU_DI]; + }else{ + CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; + CPU_FLAGL |= C_FLAG; + CPU_CL = 0xff; + } + }else{ + //CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; + //CPU_FLAGL |= C_FLAG; + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + CPU_CL = 0xff; + } + break; + case 0x09: // READ CONFIGURATION WORD + devnum = CPU_BL >> 3; + funcnum = CPU_BL & 0x7; + if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ + if(CPU_DI <= 0xff){ + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + CPU_CX = *((UINT16*)(pcidev.devices[devnum].cfgreg8 + CPU_DI)); // XXX: 2の倍数のレジスタ番号でなくても読めちゃうけどまあいいかー + }else{ + CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; + CPU_FLAGL |= C_FLAG; + CPU_CX = 0xffff; + } + }else{ + //CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; + //CPU_FLAGL |= C_FLAG; + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + CPU_CX = 0xffff; + } + break; + case 0x0A: // READ CONFIGURATION DWORD + devnum = CPU_BL >> 3; + funcnum = CPU_BL & 0x7; + if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ + if(CPU_DI <= 0xff){ + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + CPU_ECX = *((UINT32*)(pcidev.devices[devnum].cfgreg8 + CPU_DI)); // XXX: 4の倍数のレジスタ番号でなくても読めちゃうけどまあいいかー + }else{ + CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; + CPU_FLAGL |= C_FLAG; + CPU_ECX = 0xffffffff; + } + }else{ + //CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; + //CPU_FLAGL |= C_FLAG; + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + CPU_ECX = 0xffffffff; + } + break; + + case 0x0B: // WRITE CONFIGURATION BYTE + devnum = CPU_BL >> 3; + funcnum = CPU_BL & 0x7; + if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ + if(CPU_DI <= 0xff){ + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + pcidev.devices[devnum].cfgreg8[CPU_DI] = CPU_CL; + }else{ + CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; + CPU_FLAGL |= C_FLAG; + } + }else{ + CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; + CPU_FLAGL |= C_FLAG; + } + break; + case 0x0C: // WRITE CONFIGURATION WORD + devnum = CPU_BL >> 3; + funcnum = CPU_BL & 0x7; + if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ + if(CPU_DI <= 0xff){ + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + *((UINT16*)(pcidev.devices[devnum].cfgreg8 + CPU_DI)) = CPU_CX; // XXX: 2の倍数のレジスタ番号でなくても書けちゃうけどまあいいかー + }else{ + CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; + CPU_FLAGL |= C_FLAG; + } + }else{ + CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; + CPU_FLAGL |= C_FLAG; + } + break; + case 0x0D: // WRITE CONFIGURATION DWORD + devnum = CPU_BL >> 3; + funcnum = CPU_BL & 0x7; + if(CPU_BH==0/* && funcnum==0*/ && pcidev.devices[devnum].enable){ + if(CPU_DI <= 0xff){ + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + *((UINT32*)(pcidev.devices[devnum].cfgreg8 + CPU_DI)) = CPU_ECX; // XXX: 4の倍数のレジスタ番号でなくても書けちゃうけどまあいいかー + }else{ + CPU_AH = PCIBIOS_STATUS_BAD_PCI_REG_NUMBER; + CPU_FLAGL |= C_FLAG; + } + }else{ + CPU_AH = PCIBIOS_STATUS_DEVICE_NOT_FOUND; + CPU_FLAGL |= C_FLAG; + } + break; + + case 0x0E: // GET IRQ ROUTING INFORMATION + if(CPU_BX == 0x0000){ + UINT16 dataSize = 0; + UINT32 dataAddress = 0; // seg:ofs + pcidev_updateBIOS32data(); + if(is32bit){ + // 32bit + dataSize = MEMR_READ16(CPU_ES, CPU_EDI); + dataAddress = (UINT32)MEMR_READ16(CPU_ES, CPU_EDI+2)|(((UINT32)MEMR_READ16(CPU_ES, CPU_EDI+4)) << 16); + if(dataSize < pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)){ + MEMR_WRITE16(CPU_ES, CPU_EDI, pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)); + CPU_AH = PCIBIOS_STATUS_BUFFER_TOO_SMALL; + CPU_FLAGL |= C_FLAG; + }else{ + dataSize = pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY); + MEMR_WRITE16(CPU_ES, CPU_EDI, dataSize); + MEMR_WRITES((dataAddress >> 16) & 0xffff, dataAddress & 0xffff, pcidev.biosdata.data, dataSize); + CPU_BX = pcidev.allirqbitmap; + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + } + }else{ + // 16bit + dataSize = MEMR_READ16(CPU_ES, CPU_DI); + dataAddress = (UINT32)MEMR_READ16(CPU_ES, CPU_DI+2)|(((UINT32)MEMR_READ16(CPU_ES, CPU_DI+4)) << 16); + if(dataSize < pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)){ + MEMR_WRITE16(CPU_ES, CPU_DI, pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)); + CPU_AH = PCIBIOS_STATUS_BUFFER_TOO_SMALL; + CPU_FLAGL |= C_FLAG; + }else{ + dataSize = pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY); + MEMR_WRITE16(CPU_ES, CPU_DI, dataSize); + MEMR_WRITES((dataAddress >> 16) & 0xffff, dataAddress & 0xffff, pcidev.biosdata.data, dataSize); + CPU_BX = pcidev.allirqbitmap; + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + } + } + }else{ + CPU_AH = PCIBIOS_STATUS_UNSUPPORTED_FUNCTION; + CPU_FLAGL |= C_FLAG; + } + break; + + case 0x0F: // SET PCI IRQ + devnum = CPU_BL >> 3; + funcnum = CPU_BL & 0x7; + //if(CPU_BH==0 && 0x0A <= CPU_CL && CPU_CL <= 0x0D && (CPU_CH & 0xf0)==0 && pcidev.devices[devnum].enable){ + // UINT8 intpinidx = CPU_CL - 0x0A; + // CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + // CPU_FLAGL &= ~C_FLAG; + //}else{ + CPU_AH = PCIBIOS_STATUS_SET_FAILED; + CPU_FLAGL |= C_FLAG; + //} + break; + + default: + if(CPU_EAX==0x49435024){ + // Find BIOS32 Service Directory Entry Point by using $PCI signature + CPU_EBX = (pcidev.bios32entrypoint & 0xff000); + CPU_ECX = 1; + CPU_EDX = (pcidev.bios32entrypoint & 0xfff); + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_AL = 0; + CPU_FLAGL &= ~C_FLAG; + }else{ + CPU_AH = PCIBIOS_STATUS_UNSUPPORTED_FUNCTION; + CPU_FLAGL |= C_FLAG; + } + break; + } +} +void bios0x1a_pci(void) { + + UINT32 oldDX; + oldDX = CPU_DX; + + if(pcidev.enable){ +#if !defined(SUPPORT_IA32_HAXM) + // XXX: np2 BIOSがDXレジスタをPUSH/POPしてしまうので、DXレジスタの内容をスタックから強引に拾ってくる + CPU_DX = cpu_vmemoryread_w(CPU_SS_INDEX, CPU_SP + 2); +#endif + + // 16bit PCI BIOS処理 + bios0x1a_pci_part(0); + +#if !defined(SUPPORT_IA32_HAXM) + // XXX: np2 BIOSがDXレジスタをPUSH/POPしてしまうので、DXレジスタの内容をスタックに強引に書き込む + cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_SP + 2, (UINT16)CPU_DX); + + // DXレジスタの値を元に戻す + CPU_DX = oldDX; +#endif + } +} +void bios0x1a_pcipnp(void) { + + UINT32 oldDX; + oldDX = CPU_DX; + + if(pcidev.enable){ +#if !defined(SUPPORT_IA32_HAXM) + // XXX: np2 BIOSがDXレジスタをPUSH/POPしてしまうので、DXレジスタの内容をスタックから強引に拾ってくる + CPU_DX = cpu_vmemoryread_w(CPU_SS_INDEX, CPU_SP + 2); +#endif + + switch(CPU_AL & 0x7f) { + case 0x00: // Intel Plug-and-Play AUTO-CONFIGURATION - INSTALLATION CHECK + CPU_AX = 0x0000; + CPU_FLAGL &= ~C_FLAG; + CPU_EDX = 0x47464341; // "GFCA" + CPU_BH = 0x02; // ACFG major version (02h) + CPU_BL = 0x08; // ACFG minor version (08h) + CPU_CX = 0x0002; + CPU_SI = 0x001F; + + pcidev_updateBIOS32data(); + + break; + case 0x06: // Intel Plug-and-Play AUTO-CONFIGURATION - GET PCI IRQ ROUTING TABLE + if(CPU_BX == 0x0000){ + UINT16 dataSize = 0; + UINT32 dataAddress = 0; + pcidev_updateBIOS32data(); + if(CPU_AL & 0x80){ + // 32bit + dataSize = MEMR_READ16(CPU_ES, CPU_EDI); + dataAddress = (UINT32)MEMR_READ16(CPU_ES, CPU_EDI+2)|(((UINT32)MEMR_READ16(CPU_ES, CPU_EDI+4)) << 16); + if(dataSize < pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)){ + MEMR_WRITE16(CPU_ES, CPU_EDI, pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)); + CPU_AH = PCIBIOS_STATUS_BUFFER_TOO_SMALL; + CPU_FLAGL |= C_FLAG; + }else{ + dataSize = pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY); + MEMR_WRITE16(CPU_ES, CPU_EDI, dataSize); + MEMR_WRITES((dataAddress >> 16) & 0xffff, dataAddress & 0xffff, pcidev.biosdata.data, dataSize); + CPU_BX = pcidev.allirqbitmap; + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + } + }else{ + // 16bit + dataSize = MEMR_READ16(CPU_ES, CPU_DI); + dataAddress = (UINT32)MEMR_READ16(CPU_ES, CPU_DI+2)|(((UINT32)MEMR_READ16(CPU_ES, CPU_DI+4)) << 16); + if(dataSize < pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)){ + MEMR_WRITE16(CPU_ES, CPU_DI, pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY)); + CPU_AH = PCIBIOS_STATUS_BUFFER_TOO_SMALL; + CPU_FLAGL |= C_FLAG; + }else{ + dataSize = pcidev.biosdata.datacount * sizeof(_PCIPNP_IRQTBL_ENTRY); + MEMR_WRITE16(CPU_ES, CPU_DI, dataSize); + MEMR_WRITES((dataAddress >> 16) & 0xffff, dataAddress & 0xffff, pcidev.biosdata.data, dataSize); + CPU_BX = pcidev.allirqbitmap; + CPU_AH = PCIBIOS_STATUS_SUCCESSFUL; + CPU_FLAGL &= ~C_FLAG; + } + } + }else{ + CPU_AH = PCIBIOS_STATUS_UNSUPPORTED_FUNCTION; + CPU_FLAGL |= C_FLAG; + } + break; + + default: + CPU_AH = PCIBIOS_STATUS_UNSUPPORTED_FUNCTION; + CPU_FLAGL |= C_FLAG; + break; + } + +#if !defined(SUPPORT_IA32_HAXM) + // XXX: np2 BIOSがDXレジスタをPUSH/POPしてしまうので、DXレジスタの内容をスタックに強引に書き込む + cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_SP + 2, (UINT16)CPU_DX); + + // DXレジスタの値を元に戻す + CPU_DX = oldDX; +#endif + } +} + +#endif diff --git a/bios/bios1b.c b/bios/bios1b.c old mode 100755 new mode 100644 index a7216790..b3df172c --- a/bios/bios1b.c +++ b/bios/bios1b.c @@ -1,1087 +1,1087 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -enum { - CACHE_TABLES = 4, - CACHE_BUFFER = 32768 -}; - -extern int sxsi_unittbl[]; - - -// ---- FDD - -static BRESULT setfdcmode(REG8 drv, REG8 type, REG8 rpm) { - - if (drv >= 4) { - return(FAILURE); - } - if ((rpm) && (!fdc.support144)) { - return(FAILURE); - } - if ((fdc.chgreg ^ type) & 1) { - return(FAILURE); - } - fdc.chgreg = type; - fdc.rpm[drv] = rpm; - if (type & 2) { - CTRL_FDMEDIA = DISKTYPE_2HD; - } - else { - CTRL_FDMEDIA = DISKTYPE_2DD; - } - return(SUCCESS); -} - -void fddbios_equip(REG8 type, BOOL clear) { - - REG16 diskequip; - - diskequip = GETBIOSMEM16(MEMW_DISK_EQUIP); - if (clear) { - diskequip &= 0x0f00; - } - if (type & 1) { - diskequip &= 0xfff0; - diskequip |= (fdc.equip & 0x0f); - } - else { - diskequip &= 0x0fff; - diskequip |= (fdc.equip & 0x0f) << 12; - } - SETBIOSMEM16(MEMW_DISK_EQUIP, diskequip); -} - -static void biosfd_setchrn(void) { - - fdc.C = CPU_CL; - fdc.H = CPU_DH; - fdc.R = CPU_DL; - fdc.N = CPU_CH; -} - -#if 0 -static void biosfd_resultout(UINT32 result) { - - UINT8 *ptr; - - ptr = mem + 0x00564 + (fdc.us*8); - ptr[0] = (UINT8)(result & 0xff) | (fdc.hd << 2) | fdc.us; - ptr[1] = (UINT8)(result >> 8); - ptr[2] = (UINT8)(result >> 16); - ptr[3] = fdc.C; - ptr[4] = fdc.H; - ptr[5] = fdc.R; - ptr[6] = fdc.N; - ptr[7] = fdc.ncn; -} -#endif - -static BRESULT biosfd_seek(REG8 track, BOOL ndensity) { - - if (ndensity) { - if (track < 42) { - track <<= 1; - } - else { - track = 42 * 2; - } - } - fdc.ncn = track; - if (fdd_seek()) { - return(FAILURE); - } - return(SUCCESS); -} - -static UINT16 fdfmt_biospara(REG8 type, REG8 rpm, REG8 fmt) { - - UINT seg; - UINT off; - UINT16 n; - - n = fdc.N; - if (n >= 4) { - n = 3; - } - if (type & 2) { - seg = GETBIOSMEM16(MEMW_F2HD_P_SEG); - off = GETBIOSMEM16(MEMW_F2HD_P_OFF); - } - else { - seg = GETBIOSMEM16(MEMW_F2DD_P_SEG); - off = GETBIOSMEM16(MEMW_F2DD_P_OFF); - } - if (rpm) { - off = 0x2361; // see bios.cpp - } - off += fdc.us * 2; - off = MEMR_READ16(seg, off); - off += n * 8; - if (!(CPU_AH & 0x40)) { - off += 4; - } - if (fmt) { - off += 2; - } - return(MEMR_READ16(seg, off)); -} - - -enum { - FDCBIOS_NORESULT, - FDCBIOS_SUCCESS, - FDCBIOS_SEEKSUCCESS, - FDCBIOS_ERROR, - FDCBIOS_SEEKERROR, - FDCBIOS_READERROR, - FDCBIOS_WRITEERROR, - FDCBIOS_NONREADY, - FDCBIOS_WRITEPROTECT -}; - -static void fdd_int(int result) { - - if (result == FDCBIOS_NORESULT) { - return; - } - switch(CPU_AH & 0x0f) { - case 0x00: // シーク - case 0x01: // ベリファイ - case 0x02: // 診断の為の読み込み - case 0x05: // データの書き込み - case 0x06: // データの読み込み -// case 0x07: // シリンダ0へシーク - case 0x0a: // READ ID - case 0x0d: // フォーマット - break; - - default: - return; - } -// kaiD - if (fdd_fdcresult() == FALSE) { - fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; - } -// - switch(result) { - case FDCBIOS_SUCCESS: - fdcsend_success7(); - break; - - case FDCBIOS_SEEKSUCCESS: - case FDCBIOS_SEEKERROR: - fdc.stat[fdc.us] |= FDCRLT_SE; - fdc_interrupt(); - fdc.event = FDCEVENT_NEUTRAL; - fdc.status = FDCSTAT_RQM; - break; - - case FDCBIOS_READERROR: - fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_ND; - fdcsend_error7(); - break; - - case FDCBIOS_WRITEERROR: - fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_EN; - fdcsend_error7(); - break; - - case FDCBIOS_NONREADY: - fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_NR; - fdcsend_error7(); - break; - - case FDCBIOS_WRITEPROTECT: - fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_NW; - fdcsend_error7(); - break; - - default: - return; - } - if (fdc.chgreg & 1) { - mem[MEMB_DISK_INTL] &= ~(0x01 << fdc.us); - } - else { - mem[MEMB_DISK_INTH] &= ~(0x10 << fdc.us); - } - CPU_IP = BIOSOFST_WAIT; -} - -#if 1 -static struct { - BOOL flg; - UINT16 cx; - UINT16 dx; - UINT pos; -// UINT cnt; -} b0p; - -static void b0patch(void) { - - if ((!b0p.flg) || (b0p.cx != CPU_CX) || (b0p.dx != CPU_DX)) { - b0p.flg = TRUE; - b0p.pos = 0; - b0p.cx = CPU_CX; - b0p.dx = CPU_DX; - } - else { - if (!b0p.pos) { - UINT32 addr; - UINT size; - UINT cnt; - REG8 c; - REG8 cl; - REG8 last; - addr = CPU_BP; - size = CPU_BX; - cnt = 0; - last = 0; - while(size--) { - c = MEMR_READ8(CPU_ES, addr++); - cl = 0; - do { - REG8 now = c & 0x80; - c <<= 1; - b0p.pos++; - if (now == last) { - cnt++; - if (cnt > 4) { - break; - } - } - else { - cnt = 0; - last = now; - } - cl++; - } while(cl < 8); - if (cnt > 4) { - break; - } - } - } - if ((b0p.pos >> 3) < CPU_BX) { - UINT addr; - REG8 c; - addr = CPU_BP + (b0p.pos >> 3); - c = MEMR_READ8(CPU_ES, addr); - c ^= (1 << (b0p.pos & 7)); - b0p.pos++; - MEMR_WRITE8(CPU_ES, addr, c); - } - } -} - -static void b0clr(void) { - b0p.flg = FALSE; -} -#endif - -static REG8 fdd_operate(REG8 type, REG8 rpm, BOOL ndensity) { - - REG8 ret_ah = 0x60; - UINT16 size; - UINT16 pos; - UINT16 accesssize; - UINT16 secsize; - UINT16 para; - UINT8 s; - UINT8 ID[4]; - UINT8 hd; - int result = FDCBIOS_NORESULT; - UINT32 addr; - UINT8 mtr_c; - UINT mtr_r; - UINT fmode; - - mtr_c = fdc.ncn; - mtr_r = 0; - - // とりあえずBIOSの時は無視する - fdc.mf = 0xff; - -// TRACE_("int 1Bh", CPU_AH); - - if (setfdcmode((REG8)(CPU_AL & 3), type, rpm) != SUCCESS) { - return(0x40); - } - - if ((CPU_AH & 0x0f) != 0x0a) { - fdc.crcn = 0; - } - if ((CPU_AH & 0x0f) != 0x03) { - if (type & 2) { - if (pic.pi[1].imr & PIC_INT42) { - return(0x40); - } - } - else { - if (pic.pi[1].imr & PIC_INT41) { - return(0x40); - } - } - if (fdc.us != (CPU_AL & 0x03)) { - fdc.us = CPU_AL & 0x03; - fdc.crcn = 0; - } - hd = ((CPU_DH) ^ (CPU_AL >> 2)) & 1; - if (fdc.hd != hd) { - fdc.hd = hd; - fdc.crcn = 0; - } - if (!fdd_diskready(fdc.us)) { - fdd_int(FDCBIOS_NONREADY); - ret_ah = 0x60; - if ((CPU_AX & 0x8f40) == 0x8400) { - ret_ah |= 8; // 1MB/640KB両用ドライブ - if ((CPU_AH & 0x40) && (fdc.support144)) { - ret_ah |= 4; // 1.44対応ドライブ - } - } - return(ret_ah); - } - } - - // モード選択 // ver0.78 - fmode = (type & 1)?MEMB_F2HD_MODE:MEMB_F2DD_MODE; - if (!(CPU_AL & 0x80)) { - if (!(mem[fmode] & (0x10 << fdc.us))) { - ndensity = TRUE; - } - } - - switch(CPU_AH & 0x0f) { - case 0x00: // シーク - if (CPU_AH & 0x10) { - if (biosfd_seek(CPU_CL, ndensity) == SUCCESS) { - result = FDCBIOS_SEEKSUCCESS; - } - else { - result = FDCBIOS_SEEKERROR; - } - } - ret_ah = 0x00; - break; - - case 0x01: // ベリファイ - if (CPU_AH & 0x10) { - if (biosfd_seek(CPU_CL, ndensity) == SUCCESS) { - result = FDCBIOS_SEEKSUCCESS; - } - else { - ret_ah = 0xe0; - result = FDCBIOS_SEEKERROR; - break; - } - } - biosfd_setchrn(); - para = fdfmt_biospara(type, rpm, 0); - if (!para) { - ret_ah = 0xd0; - break; - } - if (fdc.N < 8) { - secsize = 128 << fdc.N; - } - else { - secsize = 128 << 8; - } - size = CPU_BX; - while(size) { - if (size > secsize) { - accesssize = secsize; - } - else { - accesssize = size; - } - if (fdd_read()) { - break; - } - size -= accesssize; - mtr_r += accesssize; - if ((fdc.R++ == (UINT8)para) && - (CPU_AH & 0x80) && (!fdc.hd)) { - fdc.hd = 1; - fdc.H = 1; - fdc.R = 1; - if (biosfd_seek(fdc.treg[fdc.us], 0) != SUCCESS) { - break; - } - } - } - if (!size) { - ret_ah = 0x00; - result = FDCBIOS_SUCCESS; - } - else { - ret_ah = 0xc0; - result = FDCBIOS_READERROR; - } - break; - - case 0x03: // 初期化 - fddbios_equip(type, FALSE); - ret_ah = 0x00; - break; - - case 0x04: // センス - ret_ah = 0x00; - if (fdd_diskprotect(fdc.us)) - { - ret_ah = 0x10; - } - if (CPU_AL & 0x80) { // 2HD - ret_ah |= 0x01; - } - else { // 2DD - if (mem[fmode] & (0x01 << fdc.us)) { - ret_ah |= 0x01; - } - if (mem[fmode] & (0x10 << fdc.us)) { - ret_ah |= 0x04; - } - } - if ((CPU_AX & 0x8f40) == 0x8400) { - ret_ah |= 8; // 1MB/640KB両用ドライブ - if ((CPU_AH & 0x40) && (fdc.support144)) { - ret_ah |= 4; // 1.44対応ドライブ - } - } - break; - - case 0x05: // データの書き込み - if (CPU_AH & 0x10) { - if (biosfd_seek(CPU_CL, ndensity) == SUCCESS) { - result = FDCBIOS_SEEKSUCCESS; - } - else { - ret_ah = 0xe0; - result = FDCBIOS_SEEKERROR; - break; - } - } - biosfd_setchrn(); - para = fdfmt_biospara(type, rpm, 0); - if (!para) { - ret_ah = 0xd0; - break; - } - if (fdd_diskprotect(fdc.us)) { - ret_ah = 0x70; - result = FDCBIOS_WRITEPROTECT; - break; - } - if (fdc.N < 8) { - secsize = 128 << fdc.N; - } - else { - secsize = 128 << 8; - } - size = CPU_BX; - addr = ES_BASE + CPU_BP; - while(size) { - if (size > secsize) { - accesssize = secsize; - } - else { - accesssize = size; - } - MEML_READS(addr, fdc.buf, accesssize); - if (fdd_write()) { - break; - } - addr += accesssize; - size -= accesssize; - mtr_r += accesssize; - if ((fdc.R++ == (UINT8)para) && - (CPU_AH & 0x80) && (!fdc.hd)) { - fdc.hd = 1; - fdc.H = 1; - fdc.R = 1; - if (biosfd_seek(fdc.treg[fdc.us], 0) != SUCCESS) { - break; - } - } - } - if (!size) { - ret_ah = 0x00; - result = FDCBIOS_SUCCESS; - } - else { - ret_ah = fddlasterror; // 0xc0 - result = FDCBIOS_WRITEERROR; - } - break; - - case 0x02: // 診断の為の読み込み - case 0x06: // データの読み込み - if (CPU_AH & 0x10) { - if (biosfd_seek(CPU_CL, ndensity) == SUCCESS) { - result = FDCBIOS_SEEKSUCCESS; - } - else { - ret_ah = 0xe0; - result = FDCBIOS_SEEKERROR; - break; - } - } - biosfd_setchrn(); - para = fdfmt_biospara(type, rpm, 0); - if (!para) { - ret_ah = 0xd0; - break; - } -#if 0 - if (fdc.R >= 0xf4) { - ret_ah = 0xb0; - break; - } -#endif - if (fdc.N < 8) { - secsize = 128 << fdc.N; - } - else { - secsize = 128 << 8; - } - size = CPU_BX; - addr = ES_BASE + CPU_BP; - while(size) { - if (size > secsize) { - accesssize = secsize; - } - else { - accesssize = size; - } - if (fdd_read()) { - break; - } - MEML_WRITES(addr, fdc.buf, accesssize); - addr += accesssize; - size -= accesssize; - mtr_r += accesssize; - if (fdc.R++ == (UINT8)para) { - if ((CPU_AH & 0x80) && (!fdc.hd)) { - fdc.hd = 1; - fdc.H = 1; - fdc.R = 1; - if (biosfd_seek(fdc.treg[fdc.us], 0) != SUCCESS) { - break; - } - } -#if 1 - else { - fdc.C++; - fdc.R = 1; - break; - } -#endif - } - } - if (!size) { - ret_ah = fddlasterror; // 0x00; - result = FDCBIOS_SUCCESS; -#if 1 - if (ret_ah == 0xb0) { - b0patch(); - } - else { - b0clr(); - } -#endif - } -#if 1 - else if ((CPU_AH & 0x0f) == 0x02) { // ARS対策… - ret_ah = 0x00; - result = FDCBIOS_READERROR; - } -#endif - else { - ret_ah = fddlasterror; // 0xc0; - result = FDCBIOS_READERROR; - } - break; - - case 0x07: // シリンダ0へシーク - biosfd_seek(0, 0); - ret_ah = 0x00; - result = FDCBIOS_SEEKSUCCESS; - break; - - case 0x09: - // 1001b WRITE DELETED DATA - TRACEOUT(("\tWRITE DELETED DATA not Support")); - break; - - case 0x0a: // READ ID - fdc.mf = CPU_AH & 0x40; - if (CPU_AH & 0x10) { - if (biosfd_seek(CPU_CL, ndensity) == SUCCESS) { - result = FDCBIOS_SEEKSUCCESS; - } - else { - ret_ah = 0xe0; - result = FDCBIOS_SEEKERROR; - break; - } - } - if (fdd_readid()) { - ret_ah = fddlasterror; // 0xa0; - break; - } - if (fdc.N < 8) { - mtr_r += 128 << fdc.N; - } - else { - mtr_r += 128 << 8; - } - ret_ah = 0x00; - CPU_CL = fdc.C; - CPU_DH = fdc.H; - CPU_DL = fdc.R; - CPU_CH = fdc.N; - result = FDCBIOS_SUCCESS; - break; - - case 0x0c: - // 1100b READ DELETED DATA - TRACEOUT(("\tREAD DELETED DATA not Support")); - break; - - case 0x0d: // フォーマット - if (CPU_AH & 0x10) { - biosfd_seek(CPU_CL, ndensity); - } - if (fdd_diskprotect(fdc.us)) { - ret_ah = 0x70; - break; - } - fdc.d = CPU_DL; - fdc.N = CPU_CH; - para = fdfmt_biospara(type, rpm, 1); - if (!para) { - ret_ah = 0xd0; - break; - } - fdc.sc = (UINT8)para; - fdd_formatinit(); - pos = CPU_BP; - for (s=0; s> 4); - while(remain) { - if (fdd_read()) { - return(0); - } - if (fdc.N < 3) { - size = 128 << fdc.N; - } - else { - size = 128 << 3; - } - if (remain < size) { - CopyMemory(mem + pos, fdc.buf, remain); - break; - } - else { - CopyMemory(mem + pos, fdc.buf, size); - pos += size; - remain -= size; - fdc.R++; - } - } - return(bootseg); -} - -static UINT16 boot_fd(REG8 drv, REG8 type) { - - UINT16 bootseg; - - if (drv >= 4) { - return(0); - } - fdc.us = drv; - if (!fdd_diskready(fdc.us)) { - return(0); - } - - // 2HD - if (type & 1) { - fdc.chgreg |= 0x01; - // 1.25MB - bootseg = boot_fd1(3, 0); - if (bootseg) { - mem[MEMB_DISK_BOOT] = (UINT8)(0x90 + drv); - fddbios_equip(3, TRUE); - return(bootseg); - } - // 1.44MB - bootseg = boot_fd1(3, 1); - if (bootseg) { - mem[MEMB_DISK_BOOT] = (UINT8)(0x30 + drv); - fddbios_equip(3, TRUE); - return(bootseg); - } - } - if (type & 2) { - fdc.chgreg &= ~0x01; - // 2DD - bootseg = boot_fd1(0, 0); - if (bootseg) { - mem[MEMB_DISK_BOOT] = (UINT8)(0x70 + drv); - fddbios_equip(0, TRUE); - return(bootseg); - } - } - fdc.chgreg |= 0x01; - return(0); -} - -static REG16 boot_hd(REG8 drv) { - - REG8 ret; - - if(pccore.hddif & PCHDD_IDE){ - ret = sxsi_read((drv & 0xf0)==0x80 ? (0x80 | sxsi_unittbl[drv & 0x3]) : drv, 0, mem + 0x1fc00, 0x400); - }else{ - ret = sxsi_read(drv, 0, mem + 0x1fc00, 0x400); - } - if (ret < 0x20) { - mem[MEMB_DISK_BOOT] = drv; - return(0x1fc0); - } - return(0); -} - -static REG16 boot_cd(REG8 drv) { - - REG8 ret; - UINT8 buf[0x400]; - - if(pccore.hddif & PCHDD_IDE){ - ret = sxsi_read((drv & 0xf0)==0x80 ? (0x80 | sxsi_unittbl[drv & 0x3]) : drv, 0, buf, sizeof(buf)); - }else{ - ret = sxsi_read(drv, 0, buf, sizeof(buf)); - } - if (buf[sizeof(buf) - 2] != 0x55 || buf[sizeof(buf) - 1] != 0xAA) - { - // ブータブルではない - return(0); - } - CopyMemory(mem + 0x1fc00, buf, sizeof(buf)); - if (ret < 0x20) { - mem[MEMB_DISK_BOOT] = drv; - return(0x1fc0); - } - return(0); -} - -REG16 bootstrapload(void) { - - UINT8 i; - REG16 bootseg; - -// fdmode = 0; - bootseg = 0; - switch(mem[MEMB_MSW5] & 0xf0) { // うぐぅ…本当はALレジスタの値から - case 0x00: // ノーマル - break; - - case 0x20: // 640KB FDD - for (i=0; (i<4) && (!bootseg); i++) { - if (fdd_diskready(i)) { - bootseg = boot_fd(i, 2); - } - } - break; - - case 0x40: // 1.2MB FDD - for (i=0; (i<4) && (!bootseg); i++) { - if (fdd_diskready(i)) { - bootseg = boot_fd(i, 1); - } - } - break; - - case 0x60: // MO - break; - - case 0xa0: // SASI 1 - bootseg = boot_hd(0x80); - break; - - case 0xb0: // SASI 2 - bootseg = boot_hd(0x81); - break; - - case 0xc0: // SCSI - for (i=0; (i<4) && (!bootseg); i++) { - bootseg = boot_hd((REG8)(0xa0 + i)); - } - break; - - default: // ROM - return(0); - } - for (i=0; (i<4) && (!bootseg); i++) { - if (fdd_diskready(i)) { - bootseg = boot_fd(i, 3); - } - } - if(pccore.hddif & PCHDD_IDE){ - for (i=0; (i<4) && (!bootseg); i++) { - if (sxsi_getptr(sxsi_unittbl[i])->devtype == SXSIDEV_CDROM && (sxsi_getptr(sxsi_unittbl[i])->flag & SXSIFLAG_READY)){ - bootseg = boot_cd((REG8)(0x80 + i)); - // MEMW_DISK_EQUIPにブート対象のCD-ROMを含める - if(bootseg) { - UINT16 diskequip; - diskequip = GETBIOSMEM16(MEMW_DISK_EQUIP); - diskequip |= 0x0100 << i; - SETBIOSMEM16(MEMW_DISK_EQUIP, diskequip); - } - } - } - for (i=0; (i<4) && (!bootseg); i++) { - if(sxsi_getptr(sxsi_unittbl[i])->devtype == SXSIDEV_HDD){ - bootseg = boot_hd((REG8)(0x80 + i)); - } - } - }else if(pccore.hddif & PCHDD_SASI){ - for (i=0; (i<2) && (!bootseg); i++) { - bootseg = boot_hd((REG8)(0x80 + i)); - } - } - for (i=0; (i<4) && (!bootseg); i++) { - bootseg = boot_hd((REG8)(0xa0 + i)); - } - return(bootseg); -} - - -// -------------------------------------------------------------------------- - -void bios0x1b(void) { - - REG8 ret_ah; - REG8 flag; - -#if 1 // bypass to disk bios - if ((CPU_AL & 0xf0) != 0x20 && (CPU_AL & 0xf0) != 0xa0 && (CPU_AL & 0xf0) != 0xc0) // SCSIは除外 - { - REG8 seg; - UINT sp; - - seg = mem[MEMX_DISK_XROM + (CPU_AL >> 4)]; - if (seg) { - sp = CPU_SP; - MEMR_WRITE16(CPU_SS, sp - 2, CPU_DS); - MEMR_WRITE16(CPU_SS, sp - 4, CPU_SI); - MEMR_WRITE16(CPU_SS, sp - 6, CPU_DI); - MEMR_WRITE16(CPU_SS, sp - 8, CPU_ES); // +a - MEMR_WRITE16(CPU_SS, sp - 10, CPU_BP); // +8 - MEMR_WRITE16(CPU_SS, sp - 12, CPU_DX); // +6 - MEMR_WRITE16(CPU_SS, sp - 14, CPU_CX); // +4 - MEMR_WRITE16(CPU_SS, sp - 16, CPU_BX); // +2 - MEMR_WRITE16(CPU_SS, sp - 18, CPU_AX); // +0 -#if 0 - TRACEOUT(("call by %.4x:%.4x", - MEMR_READ16(CPU_SS, CPU_SP+2), - MEMR_READ16(CPU_SS, CPU_SP))); - TRACEOUT(("bypass to %.4x:0018", seg << 8)); - TRACEOUT(("AX=%04x BX=%04x %02x:%02x:%02x:%02x ES=%04x BP=%04x", - CPU_AX, CPU_BX, CPU_CL, CPU_DH, CPU_DL, CPU_CH, - CPU_ES, CPU_BP)); -#endif - sp -= 18; - CPU_SP = sp; - CPU_BP = sp; - CPU_DS = 0x0000; - CPU_BX = 0x04B0; - CPU_AX = seg << 8; - CPU_CS = seg << 8; - CPU_IP = 0x18; - return; - } - } -#endif - -#if defined(SUPPORT_SCSI) - if ((CPU_AL & 0xf0) == 0xc0) { - TRACEOUT(("%.4x:%.4x AX=%.4x BX=%.4x CX=%.4x DX=%.4 ES=%.4x BP=%.4x", - MEMR_READ16(CPU_SS, CPU_SP+2), - MEMR_READ16(CPU_SS, CPU_SP), - CPU_AX, CPU_BX, CPU_CX, CPU_DX, CPU_ES, CPU_BP)); - scsicmd_bios(); - return; - } -#endif - - switch(CPU_AL & 0xf0) { - case 0x90: - ret_ah = fdd_operate(3, 0, FALSE); - break; - - case 0x30: - case 0xb0: - ret_ah = fdd_operate(3, 1, FALSE); - break; - - case 0x10: - ret_ah = fdd_operate(1, 0, FALSE); - break; - - case 0x70: - ret_ah = fdd_operate(0, 0, FALSE); - break; - - case 0xf0: - ret_ah = fdd_operate(2, 0, FALSE); - break; - - case 0x50: - ret_ah = fdd_operate(0, 0, TRUE); - break; - - case 0x00: - case 0x80: - ret_ah = sasibios_operate(); - break; - -#if defined(SUPPORT_SCSI) - case 0x20: - case 0xa0: - ret_ah = scsibios_operate(); - break; -#endif - - default: - ret_ah = 0x40; - break; - } -#if 0 - TRACEOUT(("%04x:%04x AX=%04x BX=%04x %02x:%02x:%02x:%02x\n" \ - "ES=%04x BP=%04x \nret=%02x", - MEMR_READ16(CPU_SS, CPU_SP+2), - MEMR_READ16(CPU_SS, CPU_SP), - CPU_AX, CPU_BX, CPU_CL, CPU_DH, CPU_DL, CPU_CH, - CPU_ES, CPU_BP, ret_ah)); -#endif - CPU_AH = ret_ah; - flag = MEMR_READ8(CPU_SS, CPU_SP+4) & 0xfe; - if (ret_ah >= 0x20) { - flag += 1; - } - MEMR_WRITE8(CPU_SS, CPU_SP + 4, flag); -} - -UINT bios0x1b_wait(void) { - - UINT addr; - REG8 bit; - static UINT32 int_timeout = 0; // np21w ver0.86 rev51 Win3.1用 暫定無限ループ回避 - - if (fddmtr.busy) { - CPU_REMCLOCK = -1; - } - else { - if (fdc.chgreg & 1) { - addr = MEMB_DISK_INTL; - bit = 0x01; - } - else { - addr = MEMB_DISK_INTH; - bit = 0x10; - } - bit <<= fdc.us; - if ((mem[addr] & bit) || int_timeout > pccore.realclock*3) { - mem[addr] &= ~bit; - int_timeout = 0; - return(0); - } - else { - CPU_REMCLOCK -= 1000; -#if defined(CPUCORE_IA32) - // np21w ver0.86 rev51 Win3.1用 暫定無限ループ回避 - if (CPU_STAT_PM && CPU_STAT_VM86) { - int_timeout += 1000; - } -#endif - } - } - CPU_IP--; - return(1); -} - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +enum { + CACHE_TABLES = 4, + CACHE_BUFFER = 32768 +}; + +extern int sxsi_unittbl[]; + + +// ---- FDD + +static BRESULT setfdcmode(REG8 drv, REG8 type, REG8 rpm) { + + if (drv >= 4) { + return(FAILURE); + } + if ((rpm) && (!fdc.support144)) { + return(FAILURE); + } + if ((fdc.chgreg ^ type) & 1) { + return(FAILURE); + } + fdc.chgreg = type; + fdc.rpm[drv] = rpm; + if (type & 2) { + CTRL_FDMEDIA = DISKTYPE_2HD; + } + else { + CTRL_FDMEDIA = DISKTYPE_2DD; + } + return(SUCCESS); +} + +void fddbios_equip(REG8 type, BOOL clear) { + + REG16 diskequip; + + diskequip = GETBIOSMEM16(MEMW_DISK_EQUIP); + if (clear) { + diskequip &= 0x0f00; + } + if (type & 1) { + diskequip &= 0xfff0; + diskequip |= (fdc.equip & 0x0f); + } + else { + diskequip &= 0x0fff; + diskequip |= (fdc.equip & 0x0f) << 12; + } + SETBIOSMEM16(MEMW_DISK_EQUIP, diskequip); +} + +static void biosfd_setchrn(void) { + + fdc.C = CPU_CL; + fdc.H = CPU_DH; + fdc.R = CPU_DL; + fdc.N = CPU_CH; +} + +#if 0 +static void biosfd_resultout(UINT32 result) { + + UINT8 *ptr; + + ptr = mem + 0x00564 + (fdc.us*8); + ptr[0] = (UINT8)(result & 0xff) | (fdc.hd << 2) | fdc.us; + ptr[1] = (UINT8)(result >> 8); + ptr[2] = (UINT8)(result >> 16); + ptr[3] = fdc.C; + ptr[4] = fdc.H; + ptr[5] = fdc.R; + ptr[6] = fdc.N; + ptr[7] = fdc.ncn; +} +#endif + +static BRESULT biosfd_seek(REG8 track, BOOL ndensity) { + + if (ndensity) { + if (track < 42) { + track <<= 1; + } + else { + track = 42 * 2; + } + } + fdc.ncn = track; + if (fdd_seek()) { + return(FAILURE); + } + return(SUCCESS); +} + +static UINT16 fdfmt_biospara(REG8 type, REG8 rpm, REG8 fmt) { + + UINT seg; + UINT off; + UINT16 n; + + n = fdc.N; + if (n >= 4) { + n = 3; + } + if (type & 2) { + seg = GETBIOSMEM16(MEMW_F2HD_P_SEG); + off = GETBIOSMEM16(MEMW_F2HD_P_OFF); + } + else { + seg = GETBIOSMEM16(MEMW_F2DD_P_SEG); + off = GETBIOSMEM16(MEMW_F2DD_P_OFF); + } + if (rpm) { + off = 0x2361; // see bios.cpp + } + off += fdc.us * 2; + off = MEMR_READ16(seg, off); + off += n * 8; + if (!(CPU_AH & 0x40)) { + off += 4; + } + if (fmt) { + off += 2; + } + return(MEMR_READ16(seg, off)); +} + + +enum { + FDCBIOS_NORESULT, + FDCBIOS_SUCCESS, + FDCBIOS_SEEKSUCCESS, + FDCBIOS_ERROR, + FDCBIOS_SEEKERROR, + FDCBIOS_READERROR, + FDCBIOS_WRITEERROR, + FDCBIOS_NONREADY, + FDCBIOS_WRITEPROTECT +}; + +static void fdd_int(int result) { + + if (result == FDCBIOS_NORESULT) { + return; + } + switch(CPU_AH & 0x0f) { + case 0x00: // シーク + case 0x01: // ベリファイ + case 0x02: // 診断の為の読み込み + case 0x05: // データの書き込み + case 0x06: // データの読み込み +// case 0x07: // シリンダ0へシーク + case 0x0a: // READ ID + case 0x0d: // フォーマット + break; + + default: + return; + } +// kaiD + if (fdd_fdcresult() == FALSE) { + fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; + } +// + switch(result) { + case FDCBIOS_SUCCESS: + fdcsend_success7(); + break; + + case FDCBIOS_SEEKSUCCESS: + case FDCBIOS_SEEKERROR: + fdc.stat[fdc.us] |= FDCRLT_SE; + fdc_interrupt(); + fdc.event = FDCEVENT_NEUTRAL; + fdc.status = FDCSTAT_RQM; + break; + + case FDCBIOS_READERROR: + fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_ND; + fdcsend_error7(); + break; + + case FDCBIOS_WRITEERROR: + fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_EN; + fdcsend_error7(); + break; + + case FDCBIOS_NONREADY: + fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_NR; + fdcsend_error7(); + break; + + case FDCBIOS_WRITEPROTECT: + fdc.stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_NW; + fdcsend_error7(); + break; + + default: + return; + } + if (fdc.chgreg & 1) { + mem[MEMB_DISK_INTL] &= ~(0x01 << fdc.us); + } + else { + mem[MEMB_DISK_INTH] &= ~(0x10 << fdc.us); + } + CPU_IP = BIOSOFST_WAIT; +} + +#if 1 +static struct { + BOOL flg; + UINT16 cx; + UINT16 dx; + UINT pos; +// UINT cnt; +} b0p; + +static void b0patch(void) { + + if ((!b0p.flg) || (b0p.cx != CPU_CX) || (b0p.dx != CPU_DX)) { + b0p.flg = TRUE; + b0p.pos = 0; + b0p.cx = CPU_CX; + b0p.dx = CPU_DX; + } + else { + if (!b0p.pos) { + UINT32 addr; + UINT size; + UINT cnt; + REG8 c; + REG8 cl; + REG8 last; + addr = CPU_BP; + size = CPU_BX; + cnt = 0; + last = 0; + while(size--) { + c = MEMR_READ8(CPU_ES, addr++); + cl = 0; + do { + REG8 now = c & 0x80; + c <<= 1; + b0p.pos++; + if (now == last) { + cnt++; + if (cnt > 4) { + break; + } + } + else { + cnt = 0; + last = now; + } + cl++; + } while(cl < 8); + if (cnt > 4) { + break; + } + } + } + if ((b0p.pos >> 3) < CPU_BX) { + UINT addr; + REG8 c; + addr = CPU_BP + (b0p.pos >> 3); + c = MEMR_READ8(CPU_ES, addr); + c ^= (1 << (b0p.pos & 7)); + b0p.pos++; + MEMR_WRITE8(CPU_ES, addr, c); + } + } +} + +static void b0clr(void) { + b0p.flg = FALSE; +} +#endif + +static REG8 fdd_operate(REG8 type, REG8 rpm, BOOL ndensity) { + + REG8 ret_ah = 0x60; + UINT16 size; + UINT16 pos; + UINT16 accesssize; + UINT16 secsize; + UINT16 para; + UINT8 s; + UINT8 ID[4]; + UINT8 hd; + int result = FDCBIOS_NORESULT; + UINT32 addr; + UINT8 mtr_c; + UINT mtr_r; + UINT fmode; + + mtr_c = fdc.ncn; + mtr_r = 0; + + // とりあえずBIOSの時は無視する + fdc.mf = 0xff; + +// TRACE_("int 1Bh", CPU_AH); + + if (setfdcmode((REG8)(CPU_AL & 3), type, rpm) != SUCCESS) { + return(0x40); + } + + if ((CPU_AH & 0x0f) != 0x0a) { + fdc.crcn = 0; + } + if ((CPU_AH & 0x0f) != 0x03) { + if (type & 2) { + if (pic.pi[1].imr & PIC_INT42) { + return(0x40); + } + } + else { + if (pic.pi[1].imr & PIC_INT41) { + return(0x40); + } + } + if (fdc.us != (CPU_AL & 0x03)) { + fdc.us = CPU_AL & 0x03; + fdc.crcn = 0; + } + hd = ((CPU_DH) ^ (CPU_AL >> 2)) & 1; + if (fdc.hd != hd) { + fdc.hd = hd; + fdc.crcn = 0; + } + if (!fdd_diskready(fdc.us)) { + fdd_int(FDCBIOS_NONREADY); + ret_ah = 0x60; + if ((CPU_AX & 0x8f40) == 0x8400) { + ret_ah |= 8; // 1MB/640KB両用ドライブ + if ((CPU_AH & 0x40) && (fdc.support144)) { + ret_ah |= 4; // 1.44対応ドライブ + } + } + return(ret_ah); + } + } + + // モード選択 // ver0.78 + fmode = (type & 1)?MEMB_F2HD_MODE:MEMB_F2DD_MODE; + if (!(CPU_AL & 0x80)) { + if (!(mem[fmode] & (0x10 << fdc.us))) { + ndensity = TRUE; + } + } + + switch(CPU_AH & 0x0f) { + case 0x00: // シーク + if (CPU_AH & 0x10) { + if (biosfd_seek(CPU_CL, ndensity) == SUCCESS) { + result = FDCBIOS_SEEKSUCCESS; + } + else { + result = FDCBIOS_SEEKERROR; + } + } + ret_ah = 0x00; + break; + + case 0x01: // ベリファイ + if (CPU_AH & 0x10) { + if (biosfd_seek(CPU_CL, ndensity) == SUCCESS) { + result = FDCBIOS_SEEKSUCCESS; + } + else { + ret_ah = 0xe0; + result = FDCBIOS_SEEKERROR; + break; + } + } + biosfd_setchrn(); + para = fdfmt_biospara(type, rpm, 0); + if (!para) { + ret_ah = 0xd0; + break; + } + if (fdc.N < 8) { + secsize = 128 << fdc.N; + } + else { + secsize = 128 << 8; + } + size = CPU_BX; + while(size) { + if (size > secsize) { + accesssize = secsize; + } + else { + accesssize = size; + } + if (fdd_read()) { + break; + } + size -= accesssize; + mtr_r += accesssize; + if ((fdc.R++ == (UINT8)para) && + (CPU_AH & 0x80) && (!fdc.hd)) { + fdc.hd = 1; + fdc.H = 1; + fdc.R = 1; + if (biosfd_seek(fdc.treg[fdc.us], 0) != SUCCESS) { + break; + } + } + } + if (!size) { + ret_ah = 0x00; + result = FDCBIOS_SUCCESS; + } + else { + ret_ah = 0xc0; + result = FDCBIOS_READERROR; + } + break; + + case 0x03: // 初期化 + fddbios_equip(type, FALSE); + ret_ah = 0x00; + break; + + case 0x04: // センス + ret_ah = 0x00; + if (fdd_diskprotect(fdc.us)) + { + ret_ah = 0x10; + } + if (CPU_AL & 0x80) { // 2HD + ret_ah |= 0x01; + } + else { // 2DD + if (mem[fmode] & (0x01 << fdc.us)) { + ret_ah |= 0x01; + } + if (mem[fmode] & (0x10 << fdc.us)) { + ret_ah |= 0x04; + } + } + if ((CPU_AX & 0x8f40) == 0x8400) { + ret_ah |= 8; // 1MB/640KB両用ドライブ + if ((CPU_AH & 0x40) && (fdc.support144)) { + ret_ah |= 4; // 1.44対応ドライブ + } + } + break; + + case 0x05: // データの書き込み + if (CPU_AH & 0x10) { + if (biosfd_seek(CPU_CL, ndensity) == SUCCESS) { + result = FDCBIOS_SEEKSUCCESS; + } + else { + ret_ah = 0xe0; + result = FDCBIOS_SEEKERROR; + break; + } + } + biosfd_setchrn(); + para = fdfmt_biospara(type, rpm, 0); + if (!para) { + ret_ah = 0xd0; + break; + } + if (fdd_diskprotect(fdc.us)) { + ret_ah = 0x70; + result = FDCBIOS_WRITEPROTECT; + break; + } + if (fdc.N < 8) { + secsize = 128 << fdc.N; + } + else { + secsize = 128 << 8; + } + size = CPU_BX; + addr = ES_BASE + CPU_BP; + while(size) { + if (size > secsize) { + accesssize = secsize; + } + else { + accesssize = size; + } + MEML_READS(addr, fdc.buf, accesssize); + if (fdd_write()) { + break; + } + addr += accesssize; + size -= accesssize; + mtr_r += accesssize; + if ((fdc.R++ == (UINT8)para) && + (CPU_AH & 0x80) && (!fdc.hd)) { + fdc.hd = 1; + fdc.H = 1; + fdc.R = 1; + if (biosfd_seek(fdc.treg[fdc.us], 0) != SUCCESS) { + break; + } + } + } + if (!size) { + ret_ah = 0x00; + result = FDCBIOS_SUCCESS; + } + else { + ret_ah = fddlasterror; // 0xc0 + result = FDCBIOS_WRITEERROR; + } + break; + + case 0x02: // 診断の為の読み込み + case 0x06: // データの読み込み + if (CPU_AH & 0x10) { + if (biosfd_seek(CPU_CL, ndensity) == SUCCESS) { + result = FDCBIOS_SEEKSUCCESS; + } + else { + ret_ah = 0xe0; + result = FDCBIOS_SEEKERROR; + break; + } + } + biosfd_setchrn(); + para = fdfmt_biospara(type, rpm, 0); + if (!para) { + ret_ah = 0xd0; + break; + } +#if 0 + if (fdc.R >= 0xf4) { + ret_ah = 0xb0; + break; + } +#endif + if (fdc.N < 8) { + secsize = 128 << fdc.N; + } + else { + secsize = 128 << 8; + } + size = CPU_BX; + addr = ES_BASE + CPU_BP; + while(size) { + if (size > secsize) { + accesssize = secsize; + } + else { + accesssize = size; + } + if (fdd_read()) { + break; + } + MEML_WRITES(addr, fdc.buf, accesssize); + addr += accesssize; + size -= accesssize; + mtr_r += accesssize; + if (fdc.R++ == (UINT8)para) { + if ((CPU_AH & 0x80) && (!fdc.hd)) { + fdc.hd = 1; + fdc.H = 1; + fdc.R = 1; + if (biosfd_seek(fdc.treg[fdc.us], 0) != SUCCESS) { + break; + } + } +#if 1 + else { + fdc.C++; + fdc.R = 1; + break; + } +#endif + } + } + if (!size) { + ret_ah = fddlasterror; // 0x00; + result = FDCBIOS_SUCCESS; +#if 1 + if (ret_ah == 0xb0) { + b0patch(); + } + else { + b0clr(); + } +#endif + } +#if 1 + else if ((CPU_AH & 0x0f) == 0x02) { // ARS対策… + ret_ah = 0x00; + result = FDCBIOS_READERROR; + } +#endif + else { + ret_ah = fddlasterror; // 0xc0; + result = FDCBIOS_READERROR; + } + break; + + case 0x07: // シリンダ0へシーク + biosfd_seek(0, 0); + ret_ah = 0x00; + result = FDCBIOS_SEEKSUCCESS; + break; + + case 0x09: + // 1001b WRITE DELETED DATA + TRACEOUT(("\tWRITE DELETED DATA not Support")); + break; + + case 0x0a: // READ ID + fdc.mf = CPU_AH & 0x40; + if (CPU_AH & 0x10) { + if (biosfd_seek(CPU_CL, ndensity) == SUCCESS) { + result = FDCBIOS_SEEKSUCCESS; + } + else { + ret_ah = 0xe0; + result = FDCBIOS_SEEKERROR; + break; + } + } + if (fdd_readid()) { + ret_ah = fddlasterror; // 0xa0; + break; + } + if (fdc.N < 8) { + mtr_r += 128 << fdc.N; + } + else { + mtr_r += 128 << 8; + } + ret_ah = 0x00; + CPU_CL = fdc.C; + CPU_DH = fdc.H; + CPU_DL = fdc.R; + CPU_CH = fdc.N; + result = FDCBIOS_SUCCESS; + break; + + case 0x0c: + // 1100b READ DELETED DATA + TRACEOUT(("\tREAD DELETED DATA not Support")); + break; + + case 0x0d: // フォーマット + if (CPU_AH & 0x10) { + biosfd_seek(CPU_CL, ndensity); + } + if (fdd_diskprotect(fdc.us)) { + ret_ah = 0x70; + break; + } + fdc.d = CPU_DL; + fdc.N = CPU_CH; + para = fdfmt_biospara(type, rpm, 1); + if (!para) { + ret_ah = 0xd0; + break; + } + fdc.sc = (UINT8)para; + fdd_formatinit(); + pos = CPU_BP; + for (s=0; s> 4); + while(remain) { + if (fdd_read()) { + return(0); + } + if (fdc.N < 3) { + size = 128 << fdc.N; + } + else { + size = 128 << 3; + } + if (remain < size) { + CopyMemory(mem + pos, fdc.buf, remain); + break; + } + else { + CopyMemory(mem + pos, fdc.buf, size); + pos += size; + remain -= size; + fdc.R++; + } + } + return(bootseg); +} + +static UINT16 boot_fd(REG8 drv, REG8 type) { + + UINT16 bootseg; + + if (drv >= 4) { + return(0); + } + fdc.us = drv; + if (!fdd_diskready(fdc.us)) { + return(0); + } + + // 2HD + if (type & 1) { + fdc.chgreg |= 0x01; + // 1.25MB + bootseg = boot_fd1(3, 0); + if (bootseg) { + mem[MEMB_DISK_BOOT] = (UINT8)(0x90 + drv); + fddbios_equip(3, TRUE); + return(bootseg); + } + // 1.44MB + bootseg = boot_fd1(3, 1); + if (bootseg) { + mem[MEMB_DISK_BOOT] = (UINT8)(0x30 + drv); + fddbios_equip(3, TRUE); + return(bootseg); + } + } + if (type & 2) { + fdc.chgreg &= ~0x01; + // 2DD + bootseg = boot_fd1(0, 0); + if (bootseg) { + mem[MEMB_DISK_BOOT] = (UINT8)(0x70 + drv); + fddbios_equip(0, TRUE); + return(bootseg); + } + } + fdc.chgreg |= 0x01; + return(0); +} + +static REG16 boot_hd(REG8 drv) { + + REG8 ret; + + if(pccore.hddif & PCHDD_IDE){ + ret = sxsi_read((drv & 0xf0)==0x80 ? (0x80 | sxsi_unittbl[drv & 0x3]) : drv, 0, mem + 0x1fc00, 0x400); + }else{ + ret = sxsi_read(drv, 0, mem + 0x1fc00, 0x400); + } + if (ret < 0x20) { + mem[MEMB_DISK_BOOT] = drv; + return(0x1fc0); + } + return(0); +} + +static REG16 boot_cd(REG8 drv) { + + REG8 ret; + UINT8 buf[0x400]; + + if(pccore.hddif & PCHDD_IDE){ + ret = sxsi_read((drv & 0xf0)==0x80 ? (0x80 | sxsi_unittbl[drv & 0x3]) : drv, 0, buf, sizeof(buf)); + }else{ + ret = sxsi_read(drv, 0, buf, sizeof(buf)); + } + if (buf[sizeof(buf) - 2] != 0x55 || buf[sizeof(buf) - 1] != 0xAA) + { + // ブータブルではない + return(0); + } + CopyMemory(mem + 0x1fc00, buf, sizeof(buf)); + if (ret < 0x20) { + mem[MEMB_DISK_BOOT] = drv; + return(0x1fc0); + } + return(0); +} + +REG16 bootstrapload(void) { + + UINT8 i; + REG16 bootseg; + +// fdmode = 0; + bootseg = 0; + switch(mem[MEMB_MSW5] & 0xf0) { // うぐぅ…本当はALレジスタの値から + case 0x00: // ノーマル + break; + + case 0x20: // 640KB FDD + for (i=0; (i<4) && (!bootseg); i++) { + if (fdd_diskready(i)) { + bootseg = boot_fd(i, 2); + } + } + break; + + case 0x40: // 1.2MB FDD + for (i=0; (i<4) && (!bootseg); i++) { + if (fdd_diskready(i)) { + bootseg = boot_fd(i, 1); + } + } + break; + + case 0x60: // MO + break; + + case 0xa0: // SASI 1 + bootseg = boot_hd(0x80); + break; + + case 0xb0: // SASI 2 + bootseg = boot_hd(0x81); + break; + + case 0xc0: // SCSI + for (i=0; (i<4) && (!bootseg); i++) { + bootseg = boot_hd((REG8)(0xa0 + i)); + } + break; + + default: // ROM + return(0); + } + for (i=0; (i<4) && (!bootseg); i++) { + if (fdd_diskready(i)) { + bootseg = boot_fd(i, 3); + } + } + if(pccore.hddif & PCHDD_IDE){ + for (i=0; (i<4) && (!bootseg); i++) { + if (sxsi_getptr(sxsi_unittbl[i])->devtype == SXSIDEV_CDROM && (sxsi_getptr(sxsi_unittbl[i])->flag & SXSIFLAG_READY)){ + bootseg = boot_cd((REG8)(0x80 + i)); + // MEMW_DISK_EQUIPにブート対象のCD-ROMを含める + if(bootseg) { + UINT16 diskequip; + diskequip = GETBIOSMEM16(MEMW_DISK_EQUIP); + diskequip |= 0x0100 << i; + SETBIOSMEM16(MEMW_DISK_EQUIP, diskequip); + } + } + } + for (i=0; (i<4) && (!bootseg); i++) { + if(sxsi_getptr(sxsi_unittbl[i])->devtype == SXSIDEV_HDD){ + bootseg = boot_hd((REG8)(0x80 + i)); + } + } + }else if(pccore.hddif & PCHDD_SASI){ + for (i=0; (i<2) && (!bootseg); i++) { + bootseg = boot_hd((REG8)(0x80 + i)); + } + } + for (i=0; (i<4) && (!bootseg); i++) { + bootseg = boot_hd((REG8)(0xa0 + i)); + } + return(bootseg); +} + + +// -------------------------------------------------------------------------- + +void bios0x1b(void) { + + REG8 ret_ah; + REG8 flag; + +#if 1 // bypass to disk bios + if ((CPU_AL & 0xf0) != 0x20 && (CPU_AL & 0xf0) != 0xa0 && (CPU_AL & 0xf0) != 0xc0) // SCSIは除外 + { + REG8 seg; + UINT sp; + + seg = mem[MEMX_DISK_XROM + (CPU_AL >> 4)]; + if (seg) { + sp = CPU_SP; + MEMR_WRITE16(CPU_SS, sp - 2, CPU_DS); + MEMR_WRITE16(CPU_SS, sp - 4, CPU_SI); + MEMR_WRITE16(CPU_SS, sp - 6, CPU_DI); + MEMR_WRITE16(CPU_SS, sp - 8, CPU_ES); // +a + MEMR_WRITE16(CPU_SS, sp - 10, CPU_BP); // +8 + MEMR_WRITE16(CPU_SS, sp - 12, CPU_DX); // +6 + MEMR_WRITE16(CPU_SS, sp - 14, CPU_CX); // +4 + MEMR_WRITE16(CPU_SS, sp - 16, CPU_BX); // +2 + MEMR_WRITE16(CPU_SS, sp - 18, CPU_AX); // +0 +#if 0 + TRACEOUT(("call by %.4x:%.4x", + MEMR_READ16(CPU_SS, CPU_SP+2), + MEMR_READ16(CPU_SS, CPU_SP))); + TRACEOUT(("bypass to %.4x:0018", seg << 8)); + TRACEOUT(("AX=%04x BX=%04x %02x:%02x:%02x:%02x ES=%04x BP=%04x", + CPU_AX, CPU_BX, CPU_CL, CPU_DH, CPU_DL, CPU_CH, + CPU_ES, CPU_BP)); +#endif + sp -= 18; + CPU_SP = sp; + CPU_BP = sp; + CPU_DS = 0x0000; + CPU_BX = 0x04B0; + CPU_AX = seg << 8; + CPU_CS = seg << 8; + CPU_IP = 0x18; + return; + } + } +#endif + +#if defined(SUPPORT_SCSI) + if ((CPU_AL & 0xf0) == 0xc0) { + TRACEOUT(("%.4x:%.4x AX=%.4x BX=%.4x CX=%.4x DX=%.4 ES=%.4x BP=%.4x", + MEMR_READ16(CPU_SS, CPU_SP+2), + MEMR_READ16(CPU_SS, CPU_SP), + CPU_AX, CPU_BX, CPU_CX, CPU_DX, CPU_ES, CPU_BP)); + scsicmd_bios(); + return; + } +#endif + + switch(CPU_AL & 0xf0) { + case 0x90: + ret_ah = fdd_operate(3, 0, FALSE); + break; + + case 0x30: + case 0xb0: + ret_ah = fdd_operate(3, 1, FALSE); + break; + + case 0x10: + ret_ah = fdd_operate(1, 0, FALSE); + break; + + case 0x70: + ret_ah = fdd_operate(0, 0, FALSE); + break; + + case 0xf0: + ret_ah = fdd_operate(2, 0, FALSE); + break; + + case 0x50: + ret_ah = fdd_operate(0, 0, TRUE); + break; + + case 0x00: + case 0x80: + ret_ah = sasibios_operate(); + break; + +#if defined(SUPPORT_SCSI) + case 0x20: + case 0xa0: + ret_ah = scsibios_operate(); + break; +#endif + + default: + ret_ah = 0x40; + break; + } +#if 0 + TRACEOUT(("%04x:%04x AX=%04x BX=%04x %02x:%02x:%02x:%02x\n" \ + "ES=%04x BP=%04x \nret=%02x", + MEMR_READ16(CPU_SS, CPU_SP+2), + MEMR_READ16(CPU_SS, CPU_SP), + CPU_AX, CPU_BX, CPU_CL, CPU_DH, CPU_DL, CPU_CH, + CPU_ES, CPU_BP, ret_ah)); +#endif + CPU_AH = ret_ah; + flag = MEMR_READ8(CPU_SS, CPU_SP+4) & 0xfe; + if (ret_ah >= 0x20) { + flag += 1; + } + MEMR_WRITE8(CPU_SS, CPU_SP + 4, flag); +} + +UINT bios0x1b_wait(void) { + + UINT addr; + REG8 bit; + static UINT32 int_timeout = 0; // np21w ver0.86 rev51 Win3.1用 暫定無限ループ回避 + + if (fddmtr.busy) { + CPU_REMCLOCK = -1; + } + else { + if (fdc.chgreg & 1) { + addr = MEMB_DISK_INTL; + bit = 0x01; + } + else { + addr = MEMB_DISK_INTH; + bit = 0x10; + } + bit <<= fdc.us; + if ((mem[addr] & bit) || int_timeout > pccore.realclock*3) { + mem[addr] &= ~bit; + int_timeout = 0; + return(0); + } + else { + CPU_REMCLOCK -= 1000; +#if defined(CPUCORE_IA32) + // np21w ver0.86 rev51 Win3.1用 暫定無限ループ回避 + if (CPU_STAT_PM && CPU_STAT_VM86) { + int_timeout += 1000; + } +#endif + } + } + CPU_IP--; + return(1); +} + diff --git a/bios/bios1c.c b/bios/bios1c.c old mode 100755 new mode 100644 index 695f3778..98c18dd0 --- a/bios/bios1c.c +++ b/bios/bios1c.c @@ -1,83 +1,83 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void bios0x1c(void) { - - UINT8 buf[6]; - - switch(CPU_AH) { - case 0x00: // get system timer - calendar_get(buf); - MEMR_WRITES(CPU_ES, CPU_BX, buf, 6); - break; - - case 0x01: // put system timer - MEMR_READS(CPU_ES, CPU_BX, buf, 6); - mem[MEMB_MSW8] = buf[0]; - calendar_set(buf); - break; - - case 0x02: // set interval timer (single) - SETBIOSMEM16(0x0001c, CPU_BX); - SETBIOSMEM16(0x0001e, CPU_ES); - SETBIOSMEM16(0x0058a, CPU_CX); -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - biosioemu_enq8(0x77, 0x36); - } else -#endif - { - iocore_out8(0x77, 0x36); - } - /*FALLTHROUGH*/ - - case 0x03: // continue interval timer -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { - biosioemu_enq8(0x71, 0x00); - if (pccore.cpumode & CPUMODE_8MHZ) { - biosioemu_enq8(0x71, 0x4e); // 4MHz - } - else { - biosioemu_enq8(0x71, 0x60); // 5MHz - } - } else -#endif - { - iocore_out8(0x71, 0x00); - if (pccore.cpumode & CPUMODE_8MHZ) { - iocore_out8(0x71, 0x4e); // 4MHz - } - else { - iocore_out8(0x71, 0x60); // 5MHz - } - } - pic.pi[0].imr &= ~(PIC_SYSTEMTIMER); - break; - -#if defined(SUPPORT_HRTIMER) - case 0x80: // hrtimer read - CPU_AL = ((mem[0x04F3] >> 6) - 1) & 0x3; // 経過日数 - { - UINT32 hrtimertimeuint; - hrtimertimeuint = LOADINTELDWORD(mem+0x04F1) & 0x3fffff; - CPU_CX = (UINT16)((hrtimertimeuint >> 16) & 0x3f); - CPU_DX = (UINT16)(hrtimertimeuint & 0xffff); - } - break; - - case 0x81: // hrtimer write - mem[0x04F3] = (CPU_CX & 0x3f) | ((CPU_AL & 0x3) << 6); - STOREINTELWORD(mem+0x04F1, CPU_DX); - break; -#endif - } -} - +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void bios0x1c(void) { + + UINT8 buf[6]; + + switch(CPU_AH) { + case 0x00: // get system timer + calendar_get(buf); + MEMR_WRITES(CPU_ES, CPU_BX, buf, 6); + break; + + case 0x01: // put system timer + MEMR_READS(CPU_ES, CPU_BX, buf, 6); + mem[MEMB_MSW8] = buf[0]; + calendar_set(buf); + break; + + case 0x02: // set interval timer (single) + SETBIOSMEM16(0x0001c, CPU_BX); + SETBIOSMEM16(0x0001e, CPU_ES); + SETBIOSMEM16(0x0058a, CPU_CX); +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + biosioemu_enq8(0x77, 0x36); + } else +#endif + { + iocore_out8(0x77, 0x36); + } + /*FALLTHROUGH*/ + + case 0x03: // continue interval timer +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { + biosioemu_enq8(0x71, 0x00); + if (pccore.cpumode & CPUMODE_8MHZ) { + biosioemu_enq8(0x71, 0x4e); // 4MHz + } + else { + biosioemu_enq8(0x71, 0x60); // 5MHz + } + } else +#endif + { + iocore_out8(0x71, 0x00); + if (pccore.cpumode & CPUMODE_8MHZ) { + iocore_out8(0x71, 0x4e); // 4MHz + } + else { + iocore_out8(0x71, 0x60); // 5MHz + } + } + pic.pi[0].imr &= ~(PIC_SYSTEMTIMER); + break; + +#if defined(SUPPORT_HRTIMER) + case 0x80: // hrtimer read + CPU_AL = ((mem[0x04F3] >> 6) - 1) & 0x3; // 経過日数 + { + UINT32 hrtimertimeuint; + hrtimertimeuint = LOADINTELDWORD(mem+0x04F1) & 0x3fffff; + CPU_CX = (UINT16)((hrtimertimeuint >> 16) & 0x3f); + CPU_DX = (UINT16)(hrtimertimeuint & 0xffff); + } + break; + + case 0x81: // hrtimer write + mem[0x04F3] = (CPU_CX & 0x3f) | ((CPU_AL & 0x3) << 6); + STOREINTELWORD(mem+0x04F1, CPU_DX); + break; +#endif + } +} + diff --git a/bios/biosmem.h b/bios/biosmem.h old mode 100755 new mode 100644 index bdb881b5..e2413bd3 --- a/bios/biosmem.h +++ b/bios/biosmem.h @@ -1,106 +1,106 @@ -/** - * @file biosmem.h - * @brief Defines of BIOS memory - */ - -#pragma once - -enum { - MEMB_EXPMMSZ = 0x00401, - MEMB_SYS_TYPE = 0x00480, - MEMB_BIOS_FLAG3 = 0x00481, - MEMB_DISK_EQUIPS = 0x00482, - MEMB_F2HD_MODE = 0x00493, - - MEMB_BIOS_FLAG0 = 0x00500, - MEMB_BIOS_FLAG1 = 0x00501, - MEMB_KB_COUNT = 0x00528, - MEMB_KB_RETRY = 0x00529, - MEMB_SHIFT_STS = 0x0053a, - MEMB_CRT_RASTER = 0x0053b, - MEMB_CRT_STS_FLAG = 0x0053c, - MEMB_CRT_CNT = 0x0053d, - MEMB_PRXCRT = 0x0054c, - MEMB_PRXDUPD = 0x0054d, - MEMB_RS_S_FLAG = 0x0055b, - MEMB_DISK_INTL = 0x0055e, - MEMB_DISK_INTH = 0x0055f, - MEMB_DISK_BOOT = 0x00584, - MEMB_CRT_BIOS = 0x00597, - MEMB_F144_SUP = 0x005ae, - MEMB_RS_D_FLAG = 0x005c1, - MEMB_F2DD_MODE = 0x005ca, - - MEMW_KB_BUF = 0x00502, - MEMW_KB_SHIFT_TBL = 0x00522, - MEMW_KB_BUF_HEAD = 0x00524, - MEMW_KB_BUF_TAIL = 0x00526, - MEMW_CRT_W_VRAMADR = 0x00548, - MEMW_CRT_W_RASTER = 0x0054a, - MEMW_PRXGLS = 0x0054e, - MEMW_PRXGCPTN = 0x0054e, - MEMW_RS_CH0_OFST = 0x00556, - MEMW_RS_CH0_SEG = 0x00558, - MEMW_DISK_EQUIP = 0x0055c, - MEMW_CA_TIM_CNT = 0x0058a, - MEMW_KB_CODE_OFF = 0x005c6, - MEMW_KB_CODE_SEG = 0x005c8, - MEMW_F2DD_P_OFF = 0x005cc, - MEMW_F2DD_P_SEG = 0x005ce, - MEMW_F2HD_P_OFF = 0x005f8, - MEMW_F2HD_P_SEG = 0x005fa, - - MEMD_F2DD_POINTER = 0x005cc, - MEMD_F2HD_POINTER = 0x005f8, - - MEMX_DISK_XROM = 0x004b0, - MEMX_KB_KY_STS = 0x0052a, - MEMX_DISK_RESULT = 0x00564 -}; - -enum { - MEMB_MSW1 = 0xa3fe2, - MEMB_MSW2 = 0xa3fe6, - MEMB_MSW3 = 0xa3fea, - MEMB_MSW4 = 0xa3fee, - MEMB_MSW5 = 0xa3ff2, - MEMB_MSW6 = 0xa3ff6, - MEMB_MSW7 = 0xa3ffa, - MEMB_MSW8 = 0xa3ffe, - - MEMX_MSW = 0xa3fe2 -}; - - -#define GETBIOSMEM8(a) (mem[(a)]) -#define SETBIOSMEM8(a, b) mem[(a)] = (b) - -#if defined(BYTESEX_LITTLE) - -#define GETBIOSMEM16(a) (*(UINT16 *)(mem + (a))) -#define SETBIOSMEM16(a, b) *(UINT16 *)(mem + (a)) = (b) - -#define GETBIOSMEM32(a) (*(UINT32 *)(mem + (a))) -#define SETBIOSMEM32(a, b) *(UINT32 *)(mem + (a)) = (b) - -#elif defined(BYTESEX_BIG) - -#define GETBIOSMEM16(a) ((UINT16)(mem[(a)+0] + (mem[(a)+1] << 8))) -#define SETBIOSMEM16(a, b) \ - do { \ - mem[(a)+0] = (UINT8)(b); \ - mem[(a)+1] = (UINT8)((b) >> 8); \ - } while(0) - -#define GETBIOSMEM32(a) ((UINT32)(mem[(a)+0] + (mem[(a)+1] << 8) + \ - (mem[(a)+2] << 16) + (mem[(a)+3] << 24))) -#define SETBIOSMEM32(a, b) \ - do { \ - mem[(a)+0] = (UINT8)(b); \ - mem[(a)+1] = (UINT8)((b) >> 8); \ - mem[(a)+2] = (UINT8)((b) >> 16); \ - mem[(a)+3] = (UINT8)((b) >> 24); \ - } while(0) - -#endif - +/** + * @file biosmem.h + * @brief Defines of BIOS memory + */ + +#pragma once + +enum { + MEMB_EXPMMSZ = 0x00401, + MEMB_SYS_TYPE = 0x00480, + MEMB_BIOS_FLAG3 = 0x00481, + MEMB_DISK_EQUIPS = 0x00482, + MEMB_F2HD_MODE = 0x00493, + + MEMB_BIOS_FLAG0 = 0x00500, + MEMB_BIOS_FLAG1 = 0x00501, + MEMB_KB_COUNT = 0x00528, + MEMB_KB_RETRY = 0x00529, + MEMB_SHIFT_STS = 0x0053a, + MEMB_CRT_RASTER = 0x0053b, + MEMB_CRT_STS_FLAG = 0x0053c, + MEMB_CRT_CNT = 0x0053d, + MEMB_PRXCRT = 0x0054c, + MEMB_PRXDUPD = 0x0054d, + MEMB_RS_S_FLAG = 0x0055b, + MEMB_DISK_INTL = 0x0055e, + MEMB_DISK_INTH = 0x0055f, + MEMB_DISK_BOOT = 0x00584, + MEMB_CRT_BIOS = 0x00597, + MEMB_F144_SUP = 0x005ae, + MEMB_RS_D_FLAG = 0x005c1, + MEMB_F2DD_MODE = 0x005ca, + + MEMW_KB_BUF = 0x00502, + MEMW_KB_SHIFT_TBL = 0x00522, + MEMW_KB_BUF_HEAD = 0x00524, + MEMW_KB_BUF_TAIL = 0x00526, + MEMW_CRT_W_VRAMADR = 0x00548, + MEMW_CRT_W_RASTER = 0x0054a, + MEMW_PRXGLS = 0x0054e, + MEMW_PRXGCPTN = 0x0054e, + MEMW_RS_CH0_OFST = 0x00556, + MEMW_RS_CH0_SEG = 0x00558, + MEMW_DISK_EQUIP = 0x0055c, + MEMW_CA_TIM_CNT = 0x0058a, + MEMW_KB_CODE_OFF = 0x005c6, + MEMW_KB_CODE_SEG = 0x005c8, + MEMW_F2DD_P_OFF = 0x005cc, + MEMW_F2DD_P_SEG = 0x005ce, + MEMW_F2HD_P_OFF = 0x005f8, + MEMW_F2HD_P_SEG = 0x005fa, + + MEMD_F2DD_POINTER = 0x005cc, + MEMD_F2HD_POINTER = 0x005f8, + + MEMX_DISK_XROM = 0x004b0, + MEMX_KB_KY_STS = 0x0052a, + MEMX_DISK_RESULT = 0x00564 +}; + +enum { + MEMB_MSW1 = 0xa3fe2, + MEMB_MSW2 = 0xa3fe6, + MEMB_MSW3 = 0xa3fea, + MEMB_MSW4 = 0xa3fee, + MEMB_MSW5 = 0xa3ff2, + MEMB_MSW6 = 0xa3ff6, + MEMB_MSW7 = 0xa3ffa, + MEMB_MSW8 = 0xa3ffe, + + MEMX_MSW = 0xa3fe2 +}; + + +#define GETBIOSMEM8(a) (mem[(a)]) +#define SETBIOSMEM8(a, b) mem[(a)] = (b) + +#if defined(BYTESEX_LITTLE) + +#define GETBIOSMEM16(a) (*(UINT16 *)(mem + (a))) +#define SETBIOSMEM16(a, b) *(UINT16 *)(mem + (a)) = (b) + +#define GETBIOSMEM32(a) (*(UINT32 *)(mem + (a))) +#define SETBIOSMEM32(a, b) *(UINT32 *)(mem + (a)) = (b) + +#elif defined(BYTESEX_BIG) + +#define GETBIOSMEM16(a) ((UINT16)(mem[(a)+0] + (mem[(a)+1] << 8))) +#define SETBIOSMEM16(a, b) \ + do { \ + mem[(a)+0] = (UINT8)(b); \ + mem[(a)+1] = (UINT8)((b) >> 8); \ + } while(0) + +#define GETBIOSMEM32(a) ((UINT32)(mem[(a)+0] + (mem[(a)+1] << 8) + \ + (mem[(a)+2] << 16) + (mem[(a)+3] << 24))) +#define SETBIOSMEM32(a, b) \ + do { \ + mem[(a)+0] = (UINT8)(b); \ + mem[(a)+1] = (UINT8)((b) >> 8); \ + mem[(a)+2] = (UINT8)((b) >> 16); \ + mem[(a)+3] = (UINT8)((b) >> 24); \ + } while(0) + +#endif + diff --git a/bios/fdfmt.h b/bios/fdfmt.h old mode 100755 new mode 100644 index c8456ff0..e2ebe878 --- a/bios/fdfmt.h +++ b/bios/fdfmt.h @@ -1,25 +1,25 @@ - -static const UINT8 fdfmt144[] = { // ver0.31 -// MFM R/W MFM FMT FM R/W FM FMT -// EOT GPL SC GPL EOT GPL SC GPL - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x12, 0x1b, 0x12, 0x54, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -static const UINT8 fdfmt2hd[] = { -// MFM R/W MFM FMT FM R/W FM FMT -// EOT GPL SC GPL EOT GPL SC GPL - 0x00, 0x00, 0x00, 0x00, 0x1a, 0x07, 0x1a, 0x1b, - 0x1a, 0x0e, 0x1a, 0x36, 0x0f, 0x0e, 0x0f, 0x2a, - 0x0f, 0x1b, 0x0f, 0x50, 0x08, 0x1b, 0x08, 0x3a, - 0x08, 0x35, 0x08, 0x74, 0x00, 0x00, 0x00, 0x00}; - -static const UINT8 fdfmt2dd[] = { -// MFM R/W MFM FMT FM R/W FM FMT -// EOT GPL SC GPL EOT GPL SC GPL - 0x00, 0x00, 0x00, 0x00, 0x10, 0x07, 0x10, 0x1b, - 0x10, 0x0e, 0x10, 0x36, 0x09, 0x0e, 0x09, 0x2a, - 0x09, 0x2a, 0x09, 0x50, 0x05, 0x1b, 0x05, 0x3a, - 0x05, 0x35, 0x05, 0x74, 0x00, 0x00, 0x00, 0x00}; - + +static const UINT8 fdfmt144[] = { // ver0.31 +// MFM R/W MFM FMT FM R/W FM FMT +// EOT GPL SC GPL EOT GPL SC GPL + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x1b, 0x12, 0x54, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const UINT8 fdfmt2hd[] = { +// MFM R/W MFM FMT FM R/W FM FMT +// EOT GPL SC GPL EOT GPL SC GPL + 0x00, 0x00, 0x00, 0x00, 0x1a, 0x07, 0x1a, 0x1b, + 0x1a, 0x0e, 0x1a, 0x36, 0x0f, 0x0e, 0x0f, 0x2a, + 0x0f, 0x1b, 0x0f, 0x50, 0x08, 0x1b, 0x08, 0x3a, + 0x08, 0x35, 0x08, 0x74, 0x00, 0x00, 0x00, 0x00}; + +static const UINT8 fdfmt2dd[] = { +// MFM R/W MFM FMT FM R/W FM FMT +// EOT GPL SC GPL EOT GPL SC GPL + 0x00, 0x00, 0x00, 0x00, 0x10, 0x07, 0x10, 0x1b, + 0x10, 0x0e, 0x10, 0x36, 0x09, 0x0e, 0x09, 0x2a, + 0x09, 0x2a, 0x09, 0x50, 0x05, 0x1b, 0x05, 0x3a, + 0x05, 0x35, 0x05, 0x74, 0x00, 0x00, 0x00, 0x00}; + diff --git a/bios/rsbios.h b/bios/rsbios.h old mode 100755 new mode 100644 index 11a60ac5..a6843af3 --- a/bios/rsbios.h +++ b/bios/rsbios.h @@ -1,55 +1,55 @@ -// BIOS0C.CPP, BIOS19.CPP - -enum { - R_INT = 0x00, - R_BFLG = 0x01, - R_FLAG = 0x02, - R_CMD = 0x03, - R_STIME = 0x04, - R_RTIME = 0x05, - R_XOFF = 0x06, - R_XON = 0x08, - R_HEADP = 0x0a, - R_TAILP = 0x0c, - R_CNT = 0x0e, - R_PUTP = 0x10, - R_GETP = 0x12, - - RINT_INT = 0x80, - - RFLAG_INIT = 0x80, - RFLAG_BFULL = 0x40, - RFLAG_BOVF = 0x20, - RFLAG_XON = 0x10, - RFLAG_XOFF = 0x08, - - RCMD_IR = 0x40, - RCMD_RTS = 0x20, - RCMD_ER = 0x10, - RCMD_SBRK = 0x08, - RCMD_RXE = 0x04, - RCMD_DTR = 0x02, - RCMD_TXEN = 0x01, - - RSCODE_XON = 0x11, - RSCODE_XOFF = 0x13, - RSCODE_SO = 0x0e, - RSCODE_SI = 0x0f -}; - -typedef struct { - UINT8 INT; // + 0 - UINT8 BFLG; // + 1 - UINT8 FLAG; // + 2 - UINT8 CMD; // + 3 - UINT8 STIME; // + 4 - UINT8 RTIME; // + 5 - UINT8 XOFF[2]; // + 6 - UINT8 XON[2]; // + 8 - UINT8 HEADP[2]; // + a - UINT8 TAILP[2]; // + c - UINT8 CNT[2]; // + e - UINT8 PUTP[2]; // +10 - UINT8 GETP[2]; // +12 -} RSBIOS; - +// BIOS0C.CPP, BIOS19.CPP + +enum { + R_INT = 0x00, + R_BFLG = 0x01, + R_FLAG = 0x02, + R_CMD = 0x03, + R_STIME = 0x04, + R_RTIME = 0x05, + R_XOFF = 0x06, + R_XON = 0x08, + R_HEADP = 0x0a, + R_TAILP = 0x0c, + R_CNT = 0x0e, + R_PUTP = 0x10, + R_GETP = 0x12, + + RINT_INT = 0x80, + + RFLAG_INIT = 0x80, + RFLAG_BFULL = 0x40, + RFLAG_BOVF = 0x20, + RFLAG_XON = 0x10, + RFLAG_XOFF = 0x08, + + RCMD_IR = 0x40, + RCMD_RTS = 0x20, + RCMD_ER = 0x10, + RCMD_SBRK = 0x08, + RCMD_RXE = 0x04, + RCMD_DTR = 0x02, + RCMD_TXEN = 0x01, + + RSCODE_XON = 0x11, + RSCODE_XOFF = 0x13, + RSCODE_SO = 0x0e, + RSCODE_SI = 0x0f +}; + +typedef struct { + UINT8 INT; // + 0 + UINT8 BFLG; // + 1 + UINT8 FLAG; // + 2 + UINT8 CMD; // + 3 + UINT8 STIME; // + 4 + UINT8 RTIME; // + 5 + UINT8 XOFF[2]; // + 6 + UINT8 XON[2]; // + 8 + UINT8 HEADP[2]; // + a + UINT8 TAILP[2]; // + c + UINT8 CNT[2]; // + e + UINT8 PUTP[2]; // +10 + UINT8 GETP[2]; // +12 +} RSBIOS; + diff --git a/bios/sxsibios.c b/bios/sxsibios.c old mode 100755 new mode 100644 index c089785f..6c422fd6 --- a/bios/sxsibios.c +++ b/bios/sxsibios.c @@ -1,787 +1,787 @@ -/** - * @file sxsibios.c - * @brief Implementation of SxSI BIOS - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) -#include -#endif -// XXX: WORKAROUND for Win9x boot menu & PC-98 HDD boot menu -#include - -#define SXSIBIOS_WORKSIZE 4096 - -extern int sxsi_unittbl[]; - -extern int sxsi_workaround_bootwait; - -typedef REG8 (*SXSIFUNC)(UINT type, SXSIDEV sxsi); - -static REG8 sxsi_pos(UINT type, SXSIDEV sxsi, FILEPOS *ppos) { - - REG8 ret; - FILEPOS pos; - - ret = 0; - pos = 0; - if (CPU_AL & 0x80) { -#if defined(SUPPORT_IDEIO_48BIT) - if(sxsi->totals > 65535*16*255){ - if (CPU_CX >= sxsi->totals / 255 / 255) { - ret = 0xd0; - } - pos = ((FILEPOS)(CPU_CX * 255) + CPU_DH) * 255 + CPU_DL; - }else -#endif - { - if ((CPU_DL >= sxsi->sectors) || - (CPU_DH >= sxsi->surfaces) || - (CPU_CX >= sxsi->cylinders)) { - ret = 0xd0; - } - pos = (((FILEPOS)CPU_CX * sxsi->surfaces) + CPU_DH) * sxsi->sectors - + CPU_DL; - } - } - else { - if(sxsi->totals > 0xffffff){ - // 大容量ディスク用 - pos = ((FILEPOS)CPU_DX << 16) | CPU_CX; - }else{ - pos = (CPU_DL << 16) | CPU_CX; - } - if (type == SXSIBIOS_SASI) { - pos &= 0x1fffff; - } - if (pos >= sxsi->totals) { - ret = 0xd0; - } - } - - *ppos = pos; - if (sxsi->size > SXSIBIOS_WORKSIZE) { - ret = 0xd0; - } - return(ret); -} - -static REG8 sasibios_write(UINT type, SXSIDEV sxsi) { - - REG8 ret; - UINT size; - FILEPOS pos; - UINT32 addr; - UINT r; - UINT8 work[SXSIBIOS_WORKSIZE]; - - size = CPU_BX; - if (!size) { - size = 0x10000; - } - ret = sxsi_pos(type, sxsi, &pos); - if (!ret) { - addr = (CPU_ES << 4) + CPU_BP; - while(size) { - r = MIN(size, sxsi->size); - MEML_READS(addr, work, r); - ret = sxsi_write(sxsi_unittbl[CPU_AL & 0x3], pos, work, r); - if (ret >= 0x20) { - break; - } - addr += r; - size -= r; - pos++; - } - } - return(ret); -} -static REG8 scsibios_write(UINT type, SXSIDEV sxsi) { - - REG8 ret; - UINT size; - FILEPOS pos; - UINT32 addr; - UINT r; - UINT8 work[SXSIBIOS_WORKSIZE]; - - size = CPU_BX; - if (!size) { - size = 0x10000; - } - ret = sxsi_pos(type, sxsi, &pos); - if (!ret) { - addr = (CPU_ES << 4) + CPU_BP; - while(size) { - r = MIN(size, sxsi->size); - MEML_READS(addr, work, r); - ret = sxsi_write(CPU_AL, pos, work, r); - if (ret >= 0x20) { - break; - } - addr += r; - size -= r; - pos++; - } - } - return(ret); -} - -static REG8 sasibios_read(UINT type, SXSIDEV sxsi) { - - REG8 ret; - UINT size; - FILEPOS pos; - UINT32 addr; - UINT r; - UINT8 work[SXSIBIOS_WORKSIZE]; - FILEPOS posbase; - UINT8 oldAL = CPU_AL; - - size = CPU_BX; - if (!size) { - size = 0x10000; - } - ret = sxsi_pos(type, sxsi, &pos); - posbase = pos; - if (!ret) { - addr = (CPU_ES << 4) + CPU_BP; - while(size) { - r = MIN(size, sxsi->size); - ret = sxsi_read(sxsi_unittbl[CPU_AL & 0x3], pos, work, r); - if (ret >= 0x20) { - break; - } - MEML_WRITES(addr, work, r); - addr += r; - size -= r; - pos++; - } - } -#ifdef SUPPORT_IDEIO - if((oldAL & 0xf0) == 0x80){ -#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) - if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { -#if defined(SUPPORT_IDEIO_48BIT) - if(sxsi->totals > 0xffffff){ - // 大容量ディスク用 - // for Windows 9x IDE Driver - UINT8 sn; - UINT16 cy; - UINT8 hd; - sn = (posbase % 255) + 1; - posbase /= 255; - hd = (posbase % 255); - posbase /= 255; - cy = posbase & 0xffff; - // LIFOなので逆順注意 - biosioemu_push8(0x644, (CPU_BX / 512) & 0xff); - biosioemu_push8(0x646, sn); - biosioemu_push8(0x64a, ((cy >> 8) & 0xff)); - biosioemu_push8(0x648, (cy & 0xff)); - biosioemu_push8_read(0x64e); - biosioemu_push8(0x64c, 0xA0|((sxsi_unittbl[oldAL & 0x3] & 0x1) << 4)|(hd & 0x0f)); - biosioemu_push8_read(0x432); - if ((sxsi_unittbl[oldAL & 0x3] & 0xf) >= 0x2) { - biosioemu_push8(0x432, 0x01); // BANK #2 - }else{ - biosioemu_push8(0x432, 0x00); // BANK #1 - } - biosioemu_push8_read(0x430); - }else -#endif - { - // for Windows 9x IDE Driver - UINT8 sn; - UINT16 cy; - UINT8 hd; - sn = (posbase % sxsi->sectors) + 1; - posbase /= sxsi->sectors; - hd = (posbase % sxsi->surfaces); - posbase /= sxsi->surfaces; - cy = posbase & 0xffff; - // LIFOなので逆順注意 - biosioemu_push8(0x644, (CPU_BX / 512) & 0xff); - biosioemu_push8(0x646, sn); - biosioemu_push8(0x64a, ((cy >> 8) & 0xff)); - biosioemu_push8(0x648, (cy & 0xff)); - biosioemu_push8_read(0x64e); - biosioemu_push8(0x64c, 0xA0|((sxsi_unittbl[oldAL & 0x3] & 0x1) << 4)|(hd & 0x0f)); - biosioemu_push8_read(0x432); - if ((sxsi_unittbl[oldAL & 0x3] & 0xf) >= 0x2) { - biosioemu_push8(0x432, 0x01); // BANK #2 - }else{ - biosioemu_push8(0x432, 0x00); // BANK #1 - } - biosioemu_push8_read(0x430); - } - - // XXX: WORKAROUND for WinNT4.0 正常な接続フラグに書き戻す - if(mem[0x05bb]){ - mem[0x05ba] = mem[0x05bb]; - mem[0x05bb] = 0; - } - } -#endif - } -#endif - return(ret); -} -static REG8 scsibios_read(UINT type, SXSIDEV sxsi) { - - REG8 ret; - UINT size; - FILEPOS pos; - UINT32 addr; - UINT r; - UINT8 work[SXSIBIOS_WORKSIZE]; - FILEPOS posbase; - UINT8 oldAL = CPU_AL; - - size = CPU_BX; - if (!size) { - size = 0x10000; - } - ret = sxsi_pos(type, sxsi, &pos); - posbase = pos; - if (!ret) { - addr = (CPU_ES << 4) + CPU_BP; - while(size) { - r = MIN(size, sxsi->size); - ret = sxsi_read(CPU_AL, pos, work, r); - if (ret >= 0x20) { - break; - } - MEML_WRITES(addr, work, r); - addr += r; - size -= r; - pos++; - } - } - return(ret); -} - -static REG8 sasibios_format(UINT type, SXSIDEV sxsi) { - - REG8 ret; - FILEPOS pos; - - if (CPU_AH & 0x80) { - if (type == SXSIBIOS_SCSI) { // とりあえずSCSIのみ - UINT count; - FILEPOS posmax; - count = timing_getcount(); // 時間を止める - ret = 0; - pos = 0; - posmax = (FILEPOS)sxsi->surfaces * sxsi->cylinders; - while(pos < posmax) { - ret = sxsi_format(sxsi_unittbl[CPU_AL & 0x3], pos * sxsi->sectors); - if (ret) { - break; - } - pos++; - } - timing_setcount(count); // 再開 - } - else { - ret = 0xd0; - } - } - else { - if (CPU_DL) { - ret = 0x30; - } - else { -// i286_memstr_read(CPU_ES, CPU_BP, work, CPU_BX); - ret = sxsi_pos(type, sxsi, &pos); - if (!ret) { - ret = sxsi_format(sxsi_unittbl[CPU_AL & 0x3], pos); - } - } - } - return(ret); -} -static REG8 scsibios_format(UINT type, SXSIDEV sxsi) { - - REG8 ret; - FILEPOS pos; - - if (CPU_AH & 0x80) { - if (type == SXSIBIOS_SCSI) { // とりあえずSCSIのみ - UINT count; - FILEPOS posmax; - count = timing_getcount(); // 時間を止める - ret = 0; - pos = 0; - posmax = (FILEPOS)sxsi->surfaces * sxsi->cylinders; - while(pos < posmax) { - ret = sxsi_format(CPU_AL, pos * sxsi->sectors); - if (ret) { - break; - } - pos++; - } - timing_setcount(count); // 再開 - } - else { - ret = 0xd0; - } - } - else { - if (CPU_DL) { - ret = 0x30; - } - else { -// i286_memstr_read(CPU_ES, CPU_BP, work, CPU_BX); - ret = sxsi_pos(type, sxsi, &pos); - if (!ret) { - ret = sxsi_format(CPU_AL, pos); - } - } - } - return(ret); -} - -static REG8 sxsibios_succeed(UINT type, SXSIDEV sxsi) { - - (void)type; - (void)sxsi; - return(0x00); -} - -static REG8 sxsibios_failed(UINT type, SXSIDEV sxsi) { - - (void)type; - (void)sxsi; - return(0x40); -} - - -// ---- sasi & IDE - -static REG8 sasibios_init(UINT type, SXSIDEV sxsi) { - - UINT16 diskequip; - UINT8 i; - UINT16 bit; - - diskequip = GETBIOSMEM16(MEMW_DISK_EQUIP); - diskequip &= 0xf0ff; - -#if defined(SUPPORT_IDEIO) - for (i=0x00, bit=0x0100; i<0x04; i++, bit<<=1) { -#else - for (i=0x00, bit=0x0100; i<0x02; i++, bit<<=1) { -#endif - //sxsi = sxsi_getptr(i); - //if ((sxsi) && ((sxsi->flag & SXSIFLAG_READY) && sxsi->devtype==SXSIDEV_HDD || sxsi->devtype==SXSIDEV_CDROM)) { - // diskequip |= bit; - //} - sxsi = sxsi_getptr(sxsi_unittbl[i]); - if ((sxsi) && ((sxsi->flag & SXSIFLAG_READY) && sxsi->devtype==SXSIDEV_HDD)) { - diskequip |= bit; - } - } - SETBIOSMEM16(MEMW_DISK_EQUIP, diskequip); - - (void)type; - return(0x00); -} - -static REG8 sasibios_sense(UINT type, SXSIDEV sxsi) { - - if (type == SXSIBIOS_SASI) { - return((REG8)(sxsi->mediatype & 7)); - } - else { - unsigned long lbasize; - if (CPU_AH == 0x84) { -#if defined(SUPPORT_IDEIO_48BIT) - if(sxsi->totals > 65535*16*255){ - FILELEN tmpCyl = (UINT32)(sxsi->totals / 255 / 255); - CPU_BX = sxsi->size; - CPU_CX = (UINT16)(tmpCyl < 0xffff ? tmpCyl : 0xffff); - CPU_DH = 255; - CPU_DL = 255; - }else -#endif - { - CPU_BX = sxsi->size; - CPU_CX = sxsi->cylinders; - CPU_DH = sxsi->surfaces; - CPU_DL = sxsi->sectors; - } - } - if(sxsi->sectors==33 && sxsi->surfaces <= 8){ - // SASIっぽい - lbasize = sxsi->cylinders * sxsi->surfaces * sxsi->sectors * sxsi->size; - if (lbasize < 10475520) return 0;//10MB未満 4*33*310 - else if (lbasize < 15713280) return 1;//15MB未満 6*33*310 - else if (lbasize < 20275200) return 2;//20MB未満 8*33*310 →thdの20MBは8:33:300なので調整 - else if (lbasize < 41564160) return 3;//40MB未満 8*33*615 - else if (lbasize == 41564160) return 4;//40MB 8*33*615 - else return 0x0f; - }else{ - return 0x0f; - } - } -} - -static const SXSIFUNC sasifunc[16] = { - sxsibios_failed, // SASI 0: - sxsibios_succeed, // SASI 1: ベリファイ - sxsibios_failed, // SASI 2: - sasibios_init, // SASI 3: イニシャライズ - sasibios_sense, // SASI 4: センス - sasibios_write, // SASI 5: データの書き込み - sasibios_read, // SASI 6: データの読み込み - sxsibios_succeed, // SASI 7: リトラクト - sxsibios_failed, // SASI 8: - sxsibios_failed, // SASI 9: - sxsibios_failed, // SASI a: - sxsibios_failed, // SASI b: - sxsibios_failed, // SASI c: - sasibios_format, // SASI d: フォーマット - sxsibios_failed, // SASI e: - sxsibios_succeed}; // SASI f: リトラクト - -REG8 sasibios_operate(void) { - - UINT type; - SXSIDEV sxsi; - - if (pccore.hddif & PCHDD_IDE) { - type = SXSIBIOS_IDE; - } -#if defined(SUPPORT_SASI) - else if (pccore.hddif & PCHDD_SASI) { - type = SXSIBIOS_SASI; - } -#endif - else { - return(0x60); - } - //sxsi = sxsi_getptr(CPU_AL); - sxsi = sxsi_getptr(sxsi_unittbl[CPU_AL & 0x3]); - if (sxsi == NULL) { - return(0x60); - } - if (sxsi->devtype == SXSIDEV_CDROM && !(sxsi->flag & SXSIFLAG_READY)) { - return(0x60); - } - // XXX: WORKAROUND for Win9x boot menu & PC-98 HDD boot menu - if(sxsi_workaround_bootwait > 0){ - sxsi_workaround_bootwait--; - if(keystat.ref[0x1c] != NKEYREF_NC || keystat.ref[0x0f] != NKEYREF_NC){ - CPU_REMCLOCK = -1; - if((CPU_AH & 0x0f) == 4){ // sasibios_sense - keystat.ref[0x1c] = NKEYREF_NC;//keystat_keyup(0x1c); - sxsi_workaround_bootwait = 0; - } - } - } - return((*sasifunc[CPU_AH & 0x0f])(type, sxsi)); -} - - -// ---- scsi - -#if defined(SUPPORT_SCSI) - -static void scsibios_set(REG8 drv, REG8 sectors, REG8 surfaces, - REG16 cylinders, REG16 size, BOOL hwsec) { - - UINT8 *scsiinf; - UINT16 inf; - - scsiinf = mem + 0x00460 + ((drv & 7) * 4); - inf = 0; - - inf = (UINT16)(cylinders & 0xfff); - if (cylinders >= 0x1000) { - inf |= 0x4000; - surfaces |= (cylinders >> 8) & 0xf0; - } - if (size == 512) { - inf |= 0x1000; - } - else if (size == 1024) { - inf |= 0x2000; - } - if (hwsec) { - inf |= 0x8000; - } - scsiinf[0] = (UINT8)sectors; - scsiinf[1] = (UINT8)surfaces; - STOREINTELWORD(scsiinf + 2, inf); -} - -static REG8 scsibios_init(UINT type, SXSIDEV sxsi) { - - UINT8 i; - UINT8 bit; - - mem[MEMB_DISK_EQUIPS] = 0; - ZeroMemory(&mem[0x00460], 0x20); - for (i=0, bit=1; i<4; i++, bit<<=1) { - sxsi = sxsi_getptr((REG8)(0x20 + i)); - if ((sxsi) && (sxsi->flag & SXSIFLAG_READY)) { - mem[MEMB_DISK_EQUIPS] |= bit; - scsibios_set(i, sxsi->sectors, sxsi->surfaces, - sxsi->cylinders, sxsi->size, TRUE); - } - } - (void)type; - return(0x00); -} - -static REG8 scsibios_sense(UINT type, SXSIDEV sxsi) { - - UINT8 *scsiinf; - - scsiinf = mem + 0x00460 + ((CPU_AL & 7) * 4); - if (CPU_AH == 0x24) { - scsibios_set(CPU_AL, CPU_DL, CPU_DH, CPU_CX, CPU_BX, FALSE); - } - else if (CPU_AH == 0x44) { - CPU_BX = (scsiinf[3] & 0x80)?2:1; - } - else if (CPU_AH == 0x84) { - CPU_DL = scsiinf[0]; - CPU_DH = scsiinf[1] & 0x0f; - CPU_CX = scsiinf[2] + ((scsiinf[3] & 0xf) << 8); - if (scsiinf[3] & 0x40) { - CPU_CX += (scsiinf[1] & 0xf0) << 8; - } - CPU_BX = 256 << ((scsiinf[3] >> 4) & 3); - } - (void)type; - (void)sxsi; - return(0x00); -} - -static REG8 scsibios_setsec(UINT type, SXSIDEV sxsi) { - - if (sxsi->size != (128 << (CPU_BH & 3))) { - return(0x40); - } - (void)type; - return(0x00); -} - -static REG8 scsibios_chginf(UINT type, SXSIDEV sxsi) { - - CPU_CX = 0; - (void)type; - (void)sxsi; - return(0x00); -} - -static const SXSIFUNC scsifunc[16] = { - sxsibios_failed, // SCSI 0: - sxsibios_succeed, // SCSI 1: ベリファイ - sxsibios_failed, // SCSI 2: - scsibios_init, // SCSI 3: イニシャライズ - scsibios_sense, // SCSI 4: センス - scsibios_write, // SCSI 5: データの書き込み - scsibios_read, // SCSI 6: データの読み込み - sxsibios_succeed, // SCSI 7: リトラクト - sxsibios_failed, // SCSI 8: - sxsibios_failed, // SCSI 9: - scsibios_setsec, // SCSI a: セクタ長設定 - sxsibios_failed, // SCSI b: - scsibios_chginf, // SCSI c: 代替情報取得 - scsibios_format, // SCSI d: フォーマット - sxsibios_failed, // SCSI e: - sxsibios_succeed}; // SCSI f: リトラクト - -REG8 scsibios_operate(void) { - - SXSIDEV sxsi; - - if (!(pccore.hddif & PCHDD_SCSI)) { - return(0x60); - } - sxsi = sxsi_getptr(CPU_AL); - if (sxsi == NULL) { - return(0x60); - } - return((*scsifunc[CPU_AH & 0x0f])(SXSIBIOS_SCSI, sxsi)); -} - - -// あとで scsicmdから移動 -#endif - - -// ---- np2sysp - -#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) || defined(SUPPORT_SCSI) -typedef struct { - UINT16 ax; - UINT16 cx; - UINT16 dx; - UINT16 bx; - UINT16 bp; - UINT16 si; - UINT16 di; - UINT16 es; - UINT16 ds; - UINT16 flag; -} REGBAK; - -static void reg_push(REGBAK *r) { - - r->ax = CPU_AX; - r->cx = CPU_CX; - r->dx = CPU_DX; - r->bx = CPU_BX; - r->bp = CPU_BP; - r->si = CPU_SI; - r->di = CPU_DI; - r->es = CPU_ES; - r->ds = CPU_DS; - r->flag = CPU_FLAG; -} - -static void reg_pop(const REGBAK *r) { - - CPU_AX = r->ax; - CPU_CX = r->cx; - CPU_DX = r->dx; - CPU_BX = r->bx; - CPU_BP = r->bp; - CPU_SI = r->si; - CPU_DI = r->di; - CPU_ES = r->es; - CPU_DS = r->ds; - CPU_FLAG = r->flag; -} - -typedef struct { - UINT8 r_ax[2]; - UINT8 r_bx[2]; - UINT8 r_cx[2]; - UINT8 r_dx[2]; - UINT8 r_bp[2]; - UINT8 r_es[2]; - UINT8 r_di[2]; - UINT8 r_si[2]; - UINT8 r_ds[2]; -} B1BREG; - -static void reg_load(UINT seg, UINT off) { - - B1BREG r; - - MEMR_READS(seg, off, &r, sizeof(r)); - CPU_FLAGL = MEMR_READ8(seg, off + 0x16); - CPU_AX = LOADINTELWORD(r.r_ax); - CPU_BX = LOADINTELWORD(r.r_bx); - CPU_CX = LOADINTELWORD(r.r_cx); - CPU_DX = LOADINTELWORD(r.r_dx); - CPU_BP = LOADINTELWORD(r.r_bp); - CPU_ES = LOADINTELWORD(r.r_es); - CPU_DI = LOADINTELWORD(r.r_di); - CPU_SI = LOADINTELWORD(r.r_si); - CPU_DS = LOADINTELWORD(r.r_ds); -} - -static void reg_store(UINT seg, UINT off) { - - B1BREG r; - - STOREINTELWORD(r.r_ax, CPU_AX); - STOREINTELWORD(r.r_bx, CPU_BX); - STOREINTELWORD(r.r_cx, CPU_CX); - STOREINTELWORD(r.r_dx, CPU_DX); - STOREINTELWORD(r.r_bp, CPU_BP); - STOREINTELWORD(r.r_es, CPU_ES); - STOREINTELWORD(r.r_di, CPU_DI); - STOREINTELWORD(r.r_si, CPU_SI); - STOREINTELWORD(r.r_ds, CPU_DS); - MEMR_WRITES(seg, off, &r, sizeof(r)); - MEMR_WRITE8(seg, off + 0x16, CPU_FLAGL); -} -#endif - -#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) -void np2sysp_sasi(const void *arg1, long arg2) { - - UINT seg; - UINT off; - REGBAK regbak; - REG8 ret; - - seg = CPU_SS; - off = CPU_BP; - reg_push(®bak); - reg_load(seg, off); - - ret = sasibios_operate(); - CPU_AH = ret; - CPU_FLAGL &= ~C_FLAG; - if (ret >= 0x20) { - CPU_FLAGL |= C_FLAG; - } - - reg_store(seg, off); - reg_pop(®bak); - (void)arg1; - (void)arg2; -} -#endif - -#if defined(SUPPORT_SCSI) -void np2sysp_scsi(const void *arg1, long arg2) { - - UINT seg; - UINT off; - REGBAK regbak; - REG8 ret; - - seg = CPU_SS; - off = CPU_BP; - reg_push(®bak); - reg_load(seg, off); - - ret = scsibios_operate(); - CPU_AH = ret; - CPU_FLAGL &= ~C_FLAG; - if (ret >= 0x20) { - CPU_FLAGL |= C_FLAG; - } - - reg_store(seg, off); - reg_pop(®bak); - (void)arg1; - (void)arg2; -} - -void np2sysp_scsidev(const void *arg1, long arg2) { - - UINT seg; - UINT off; - REGBAK regbak; - - seg = CPU_SS; - off = CPU_BP; - reg_push(®bak); - reg_load(seg, off); - - scsicmd_bios(); - - reg_store(seg, off); - reg_pop(®bak); - (void)arg1; - (void)arg2; -} -#endif - +/** + * @file sxsibios.c + * @brief Implementation of SxSI BIOS + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) +#include +#endif +// XXX: WORKAROUND for Win9x boot menu & PC-98 HDD boot menu +#include + +#define SXSIBIOS_WORKSIZE 4096 + +extern int sxsi_unittbl[]; + +extern int sxsi_workaround_bootwait; + +typedef REG8 (*SXSIFUNC)(UINT type, SXSIDEV sxsi); + +static REG8 sxsi_pos(UINT type, SXSIDEV sxsi, FILEPOS *ppos) { + + REG8 ret; + FILEPOS pos; + + ret = 0; + pos = 0; + if (CPU_AL & 0x80) { +#if defined(SUPPORT_IDEIO_48BIT) + if(sxsi->totals > 65535*16*255){ + if (CPU_CX >= sxsi->totals / 255 / 255) { + ret = 0xd0; + } + pos = ((FILEPOS)(CPU_CX * 255) + CPU_DH) * 255 + CPU_DL; + }else +#endif + { + if ((CPU_DL >= sxsi->sectors) || + (CPU_DH >= sxsi->surfaces) || + (CPU_CX >= sxsi->cylinders)) { + ret = 0xd0; + } + pos = (((FILEPOS)CPU_CX * sxsi->surfaces) + CPU_DH) * sxsi->sectors + + CPU_DL; + } + } + else { + if(sxsi->totals > 0xffffff){ + // 大容量ディスク用 + pos = ((FILEPOS)CPU_DX << 16) | CPU_CX; + }else{ + pos = (CPU_DL << 16) | CPU_CX; + } + if (type == SXSIBIOS_SASI) { + pos &= 0x1fffff; + } + if (pos >= sxsi->totals) { + ret = 0xd0; + } + } + + *ppos = pos; + if (sxsi->size > SXSIBIOS_WORKSIZE) { + ret = 0xd0; + } + return(ret); +} + +static REG8 sasibios_write(UINT type, SXSIDEV sxsi) { + + REG8 ret; + UINT size; + FILEPOS pos; + UINT32 addr; + UINT r; + UINT8 work[SXSIBIOS_WORKSIZE]; + + size = CPU_BX; + if (!size) { + size = 0x10000; + } + ret = sxsi_pos(type, sxsi, &pos); + if (!ret) { + addr = (CPU_ES << 4) + CPU_BP; + while(size) { + r = MIN(size, sxsi->size); + MEML_READS(addr, work, r); + ret = sxsi_write(sxsi_unittbl[CPU_AL & 0x3], pos, work, r); + if (ret >= 0x20) { + break; + } + addr += r; + size -= r; + pos++; + } + } + return(ret); +} +static REG8 scsibios_write(UINT type, SXSIDEV sxsi) { + + REG8 ret; + UINT size; + FILEPOS pos; + UINT32 addr; + UINT r; + UINT8 work[SXSIBIOS_WORKSIZE]; + + size = CPU_BX; + if (!size) { + size = 0x10000; + } + ret = sxsi_pos(type, sxsi, &pos); + if (!ret) { + addr = (CPU_ES << 4) + CPU_BP; + while(size) { + r = MIN(size, sxsi->size); + MEML_READS(addr, work, r); + ret = sxsi_write(CPU_AL, pos, work, r); + if (ret >= 0x20) { + break; + } + addr += r; + size -= r; + pos++; + } + } + return(ret); +} + +static REG8 sasibios_read(UINT type, SXSIDEV sxsi) { + + REG8 ret; + UINT size; + FILEPOS pos; + UINT32 addr; + UINT r; + UINT8 work[SXSIBIOS_WORKSIZE]; + FILEPOS posbase; + UINT8 oldAL = CPU_AL; + + size = CPU_BX; + if (!size) { + size = 0x10000; + } + ret = sxsi_pos(type, sxsi, &pos); + posbase = pos; + if (!ret) { + addr = (CPU_ES << 4) + CPU_BP; + while(size) { + r = MIN(size, sxsi->size); + ret = sxsi_read(sxsi_unittbl[CPU_AL & 0x3], pos, work, r); + if (ret >= 0x20) { + break; + } + MEML_WRITES(addr, work, r); + addr += r; + size -= r; + pos++; + } + } +#ifdef SUPPORT_IDEIO + if((oldAL & 0xf0) == 0x80){ +#if defined(BIOS_IO_EMULATION) && defined(CPUCORE_IA32) + if (CPU_STAT_PM && CPU_STAT_VM86 && biosioemu.enable) { +#if defined(SUPPORT_IDEIO_48BIT) + if(sxsi->totals > 0xffffff){ + // 大容量ディスク用 + // for Windows 9x IDE Driver + UINT8 sn; + UINT16 cy; + UINT8 hd; + sn = (posbase % 255) + 1; + posbase /= 255; + hd = (posbase % 255); + posbase /= 255; + cy = posbase & 0xffff; + // LIFOなので逆順注意 + biosioemu_push8(0x644, (CPU_BX / 512) & 0xff); + biosioemu_push8(0x646, sn); + biosioemu_push8(0x64a, ((cy >> 8) & 0xff)); + biosioemu_push8(0x648, (cy & 0xff)); + biosioemu_push8_read(0x64e); + biosioemu_push8(0x64c, 0xA0|((sxsi_unittbl[oldAL & 0x3] & 0x1) << 4)|(hd & 0x0f)); + biosioemu_push8_read(0x432); + if ((sxsi_unittbl[oldAL & 0x3] & 0xf) >= 0x2) { + biosioemu_push8(0x432, 0x01); // BANK #2 + }else{ + biosioemu_push8(0x432, 0x00); // BANK #1 + } + biosioemu_push8_read(0x430); + }else +#endif + { + // for Windows 9x IDE Driver + UINT8 sn; + UINT16 cy; + UINT8 hd; + sn = (posbase % sxsi->sectors) + 1; + posbase /= sxsi->sectors; + hd = (posbase % sxsi->surfaces); + posbase /= sxsi->surfaces; + cy = posbase & 0xffff; + // LIFOなので逆順注意 + biosioemu_push8(0x644, (CPU_BX / 512) & 0xff); + biosioemu_push8(0x646, sn); + biosioemu_push8(0x64a, ((cy >> 8) & 0xff)); + biosioemu_push8(0x648, (cy & 0xff)); + biosioemu_push8_read(0x64e); + biosioemu_push8(0x64c, 0xA0|((sxsi_unittbl[oldAL & 0x3] & 0x1) << 4)|(hd & 0x0f)); + biosioemu_push8_read(0x432); + if ((sxsi_unittbl[oldAL & 0x3] & 0xf) >= 0x2) { + biosioemu_push8(0x432, 0x01); // BANK #2 + }else{ + biosioemu_push8(0x432, 0x00); // BANK #1 + } + biosioemu_push8_read(0x430); + } + + // XXX: WORKAROUND for WinNT4.0 正常な接続フラグに書き戻す + if(mem[0x05bb]){ + mem[0x05ba] = mem[0x05bb]; + mem[0x05bb] = 0; + } + } +#endif + } +#endif + return(ret); +} +static REG8 scsibios_read(UINT type, SXSIDEV sxsi) { + + REG8 ret; + UINT size; + FILEPOS pos; + UINT32 addr; + UINT r; + UINT8 work[SXSIBIOS_WORKSIZE]; + FILEPOS posbase; + UINT8 oldAL = CPU_AL; + + size = CPU_BX; + if (!size) { + size = 0x10000; + } + ret = sxsi_pos(type, sxsi, &pos); + posbase = pos; + if (!ret) { + addr = (CPU_ES << 4) + CPU_BP; + while(size) { + r = MIN(size, sxsi->size); + ret = sxsi_read(CPU_AL, pos, work, r); + if (ret >= 0x20) { + break; + } + MEML_WRITES(addr, work, r); + addr += r; + size -= r; + pos++; + } + } + return(ret); +} + +static REG8 sasibios_format(UINT type, SXSIDEV sxsi) { + + REG8 ret; + FILEPOS pos; + + if (CPU_AH & 0x80) { + if (type == SXSIBIOS_SCSI) { // とりあえずSCSIのみ + UINT count; + FILEPOS posmax; + count = timing_getcount(); // 時間を止める + ret = 0; + pos = 0; + posmax = (FILEPOS)sxsi->surfaces * sxsi->cylinders; + while(pos < posmax) { + ret = sxsi_format(sxsi_unittbl[CPU_AL & 0x3], pos * sxsi->sectors); + if (ret) { + break; + } + pos++; + } + timing_setcount(count); // 再開 + } + else { + ret = 0xd0; + } + } + else { + if (CPU_DL) { + ret = 0x30; + } + else { +// i286_memstr_read(CPU_ES, CPU_BP, work, CPU_BX); + ret = sxsi_pos(type, sxsi, &pos); + if (!ret) { + ret = sxsi_format(sxsi_unittbl[CPU_AL & 0x3], pos); + } + } + } + return(ret); +} +static REG8 scsibios_format(UINT type, SXSIDEV sxsi) { + + REG8 ret; + FILEPOS pos; + + if (CPU_AH & 0x80) { + if (type == SXSIBIOS_SCSI) { // とりあえずSCSIのみ + UINT count; + FILEPOS posmax; + count = timing_getcount(); // 時間を止める + ret = 0; + pos = 0; + posmax = (FILEPOS)sxsi->surfaces * sxsi->cylinders; + while(pos < posmax) { + ret = sxsi_format(CPU_AL, pos * sxsi->sectors); + if (ret) { + break; + } + pos++; + } + timing_setcount(count); // 再開 + } + else { + ret = 0xd0; + } + } + else { + if (CPU_DL) { + ret = 0x30; + } + else { +// i286_memstr_read(CPU_ES, CPU_BP, work, CPU_BX); + ret = sxsi_pos(type, sxsi, &pos); + if (!ret) { + ret = sxsi_format(CPU_AL, pos); + } + } + } + return(ret); +} + +static REG8 sxsibios_succeed(UINT type, SXSIDEV sxsi) { + + (void)type; + (void)sxsi; + return(0x00); +} + +static REG8 sxsibios_failed(UINT type, SXSIDEV sxsi) { + + (void)type; + (void)sxsi; + return(0x40); +} + + +// ---- sasi & IDE + +static REG8 sasibios_init(UINT type, SXSIDEV sxsi) { + + UINT16 diskequip; + UINT8 i; + UINT16 bit; + + diskequip = GETBIOSMEM16(MEMW_DISK_EQUIP); + diskequip &= 0xf0ff; + +#if defined(SUPPORT_IDEIO) + for (i=0x00, bit=0x0100; i<0x04; i++, bit<<=1) { +#else + for (i=0x00, bit=0x0100; i<0x02; i++, bit<<=1) { +#endif + //sxsi = sxsi_getptr(i); + //if ((sxsi) && ((sxsi->flag & SXSIFLAG_READY) && sxsi->devtype==SXSIDEV_HDD || sxsi->devtype==SXSIDEV_CDROM)) { + // diskequip |= bit; + //} + sxsi = sxsi_getptr(sxsi_unittbl[i]); + if ((sxsi) && ((sxsi->flag & SXSIFLAG_READY) && sxsi->devtype==SXSIDEV_HDD)) { + diskequip |= bit; + } + } + SETBIOSMEM16(MEMW_DISK_EQUIP, diskequip); + + (void)type; + return(0x00); +} + +static REG8 sasibios_sense(UINT type, SXSIDEV sxsi) { + + if (type == SXSIBIOS_SASI) { + return((REG8)(sxsi->mediatype & 7)); + } + else { + unsigned long lbasize; + if (CPU_AH == 0x84) { +#if defined(SUPPORT_IDEIO_48BIT) + if(sxsi->totals > 65535*16*255){ + FILELEN tmpCyl = (UINT32)(sxsi->totals / 255 / 255); + CPU_BX = sxsi->size; + CPU_CX = (UINT16)(tmpCyl < 0xffff ? tmpCyl : 0xffff); + CPU_DH = 255; + CPU_DL = 255; + }else +#endif + { + CPU_BX = sxsi->size; + CPU_CX = sxsi->cylinders; + CPU_DH = sxsi->surfaces; + CPU_DL = sxsi->sectors; + } + } + if(sxsi->sectors==33 && sxsi->surfaces <= 8){ + // SASIっぽい + lbasize = sxsi->cylinders * sxsi->surfaces * sxsi->sectors * sxsi->size; + if (lbasize < 10475520) return 0;//10MB未満 4*33*310 + else if (lbasize < 15713280) return 1;//15MB未満 6*33*310 + else if (lbasize < 20275200) return 2;//20MB未満 8*33*310 →thdの20MBは8:33:300なので調整 + else if (lbasize < 41564160) return 3;//40MB未満 8*33*615 + else if (lbasize == 41564160) return 4;//40MB 8*33*615 + else return 0x0f; + }else{ + return 0x0f; + } + } +} + +static const SXSIFUNC sasifunc[16] = { + sxsibios_failed, // SASI 0: + sxsibios_succeed, // SASI 1: ベリファイ + sxsibios_failed, // SASI 2: + sasibios_init, // SASI 3: イニシャライズ + sasibios_sense, // SASI 4: センス + sasibios_write, // SASI 5: データの書き込み + sasibios_read, // SASI 6: データの読み込み + sxsibios_succeed, // SASI 7: リトラクト + sxsibios_failed, // SASI 8: + sxsibios_failed, // SASI 9: + sxsibios_failed, // SASI a: + sxsibios_failed, // SASI b: + sxsibios_failed, // SASI c: + sasibios_format, // SASI d: フォーマット + sxsibios_failed, // SASI e: + sxsibios_succeed}; // SASI f: リトラクト + +REG8 sasibios_operate(void) { + + UINT type; + SXSIDEV sxsi; + + if (pccore.hddif & PCHDD_IDE) { + type = SXSIBIOS_IDE; + } +#if defined(SUPPORT_SASI) + else if (pccore.hddif & PCHDD_SASI) { + type = SXSIBIOS_SASI; + } +#endif + else { + return(0x60); + } + //sxsi = sxsi_getptr(CPU_AL); + sxsi = sxsi_getptr(sxsi_unittbl[CPU_AL & 0x3]); + if (sxsi == NULL) { + return(0x60); + } + if (sxsi->devtype == SXSIDEV_CDROM && !(sxsi->flag & SXSIFLAG_READY)) { + return(0x60); + } + // XXX: WORKAROUND for Win9x boot menu & PC-98 HDD boot menu + if(sxsi_workaround_bootwait > 0){ + sxsi_workaround_bootwait--; + if(keystat.ref[0x1c] != NKEYREF_NC || keystat.ref[0x0f] != NKEYREF_NC){ + CPU_REMCLOCK = -1; + if((CPU_AH & 0x0f) == 4){ // sasibios_sense + keystat.ref[0x1c] = NKEYREF_NC;//keystat_keyup(0x1c); + sxsi_workaround_bootwait = 0; + } + } + } + return((*sasifunc[CPU_AH & 0x0f])(type, sxsi)); +} + + +// ---- scsi + +#if defined(SUPPORT_SCSI) + +static void scsibios_set(REG8 drv, REG8 sectors, REG8 surfaces, + REG16 cylinders, REG16 size, BOOL hwsec) { + + UINT8 *scsiinf; + UINT16 inf; + + scsiinf = mem + 0x00460 + ((drv & 7) * 4); + inf = 0; + + inf = (UINT16)(cylinders & 0xfff); + if (cylinders >= 0x1000) { + inf |= 0x4000; + surfaces |= (cylinders >> 8) & 0xf0; + } + if (size == 512) { + inf |= 0x1000; + } + else if (size == 1024) { + inf |= 0x2000; + } + if (hwsec) { + inf |= 0x8000; + } + scsiinf[0] = (UINT8)sectors; + scsiinf[1] = (UINT8)surfaces; + STOREINTELWORD(scsiinf + 2, inf); +} + +static REG8 scsibios_init(UINT type, SXSIDEV sxsi) { + + UINT8 i; + UINT8 bit; + + mem[MEMB_DISK_EQUIPS] = 0; + ZeroMemory(&mem[0x00460], 0x20); + for (i=0, bit=1; i<4; i++, bit<<=1) { + sxsi = sxsi_getptr((REG8)(0x20 + i)); + if ((sxsi) && (sxsi->flag & SXSIFLAG_READY)) { + mem[MEMB_DISK_EQUIPS] |= bit; + scsibios_set(i, sxsi->sectors, sxsi->surfaces, + sxsi->cylinders, sxsi->size, TRUE); + } + } + (void)type; + return(0x00); +} + +static REG8 scsibios_sense(UINT type, SXSIDEV sxsi) { + + UINT8 *scsiinf; + + scsiinf = mem + 0x00460 + ((CPU_AL & 7) * 4); + if (CPU_AH == 0x24) { + scsibios_set(CPU_AL, CPU_DL, CPU_DH, CPU_CX, CPU_BX, FALSE); + } + else if (CPU_AH == 0x44) { + CPU_BX = (scsiinf[3] & 0x80)?2:1; + } + else if (CPU_AH == 0x84) { + CPU_DL = scsiinf[0]; + CPU_DH = scsiinf[1] & 0x0f; + CPU_CX = scsiinf[2] + ((scsiinf[3] & 0xf) << 8); + if (scsiinf[3] & 0x40) { + CPU_CX += (scsiinf[1] & 0xf0) << 8; + } + CPU_BX = 256 << ((scsiinf[3] >> 4) & 3); + } + (void)type; + (void)sxsi; + return(0x00); +} + +static REG8 scsibios_setsec(UINT type, SXSIDEV sxsi) { + + if (sxsi->size != (128 << (CPU_BH & 3))) { + return(0x40); + } + (void)type; + return(0x00); +} + +static REG8 scsibios_chginf(UINT type, SXSIDEV sxsi) { + + CPU_CX = 0; + (void)type; + (void)sxsi; + return(0x00); +} + +static const SXSIFUNC scsifunc[16] = { + sxsibios_failed, // SCSI 0: + sxsibios_succeed, // SCSI 1: ベリファイ + sxsibios_failed, // SCSI 2: + scsibios_init, // SCSI 3: イニシャライズ + scsibios_sense, // SCSI 4: センス + scsibios_write, // SCSI 5: データの書き込み + scsibios_read, // SCSI 6: データの読み込み + sxsibios_succeed, // SCSI 7: リトラクト + sxsibios_failed, // SCSI 8: + sxsibios_failed, // SCSI 9: + scsibios_setsec, // SCSI a: セクタ長設定 + sxsibios_failed, // SCSI b: + scsibios_chginf, // SCSI c: 代替情報取得 + scsibios_format, // SCSI d: フォーマット + sxsibios_failed, // SCSI e: + sxsibios_succeed}; // SCSI f: リトラクト + +REG8 scsibios_operate(void) { + + SXSIDEV sxsi; + + if (!(pccore.hddif & PCHDD_SCSI)) { + return(0x60); + } + sxsi = sxsi_getptr(CPU_AL); + if (sxsi == NULL) { + return(0x60); + } + return((*scsifunc[CPU_AH & 0x0f])(SXSIBIOS_SCSI, sxsi)); +} + + +// あとで scsicmdから移動 +#endif + + +// ---- np2sysp + +#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) || defined(SUPPORT_SCSI) +typedef struct { + UINT16 ax; + UINT16 cx; + UINT16 dx; + UINT16 bx; + UINT16 bp; + UINT16 si; + UINT16 di; + UINT16 es; + UINT16 ds; + UINT16 flag; +} REGBAK; + +static void reg_push(REGBAK *r) { + + r->ax = CPU_AX; + r->cx = CPU_CX; + r->dx = CPU_DX; + r->bx = CPU_BX; + r->bp = CPU_BP; + r->si = CPU_SI; + r->di = CPU_DI; + r->es = CPU_ES; + r->ds = CPU_DS; + r->flag = CPU_FLAG; +} + +static void reg_pop(const REGBAK *r) { + + CPU_AX = r->ax; + CPU_CX = r->cx; + CPU_DX = r->dx; + CPU_BX = r->bx; + CPU_BP = r->bp; + CPU_SI = r->si; + CPU_DI = r->di; + CPU_ES = r->es; + CPU_DS = r->ds; + CPU_FLAG = r->flag; +} + +typedef struct { + UINT8 r_ax[2]; + UINT8 r_bx[2]; + UINT8 r_cx[2]; + UINT8 r_dx[2]; + UINT8 r_bp[2]; + UINT8 r_es[2]; + UINT8 r_di[2]; + UINT8 r_si[2]; + UINT8 r_ds[2]; +} B1BREG; + +static void reg_load(UINT seg, UINT off) { + + B1BREG r; + + MEMR_READS(seg, off, &r, sizeof(r)); + CPU_FLAGL = MEMR_READ8(seg, off + 0x16); + CPU_AX = LOADINTELWORD(r.r_ax); + CPU_BX = LOADINTELWORD(r.r_bx); + CPU_CX = LOADINTELWORD(r.r_cx); + CPU_DX = LOADINTELWORD(r.r_dx); + CPU_BP = LOADINTELWORD(r.r_bp); + CPU_ES = LOADINTELWORD(r.r_es); + CPU_DI = LOADINTELWORD(r.r_di); + CPU_SI = LOADINTELWORD(r.r_si); + CPU_DS = LOADINTELWORD(r.r_ds); +} + +static void reg_store(UINT seg, UINT off) { + + B1BREG r; + + STOREINTELWORD(r.r_ax, CPU_AX); + STOREINTELWORD(r.r_bx, CPU_BX); + STOREINTELWORD(r.r_cx, CPU_CX); + STOREINTELWORD(r.r_dx, CPU_DX); + STOREINTELWORD(r.r_bp, CPU_BP); + STOREINTELWORD(r.r_es, CPU_ES); + STOREINTELWORD(r.r_di, CPU_DI); + STOREINTELWORD(r.r_si, CPU_SI); + STOREINTELWORD(r.r_ds, CPU_DS); + MEMR_WRITES(seg, off, &r, sizeof(r)); + MEMR_WRITE8(seg, off + 0x16, CPU_FLAGL); +} +#endif + +#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) +void np2sysp_sasi(const void *arg1, long arg2) { + + UINT seg; + UINT off; + REGBAK regbak; + REG8 ret; + + seg = CPU_SS; + off = CPU_BP; + reg_push(®bak); + reg_load(seg, off); + + ret = sasibios_operate(); + CPU_AH = ret; + CPU_FLAGL &= ~C_FLAG; + if (ret >= 0x20) { + CPU_FLAGL |= C_FLAG; + } + + reg_store(seg, off); + reg_pop(®bak); + (void)arg1; + (void)arg2; +} +#endif + +#if defined(SUPPORT_SCSI) +void np2sysp_scsi(const void *arg1, long arg2) { + + UINT seg; + UINT off; + REGBAK regbak; + REG8 ret; + + seg = CPU_SS; + off = CPU_BP; + reg_push(®bak); + reg_load(seg, off); + + ret = scsibios_operate(); + CPU_AH = ret; + CPU_FLAGL &= ~C_FLAG; + if (ret >= 0x20) { + CPU_FLAGL |= C_FLAG; + } + + reg_store(seg, off); + reg_pop(®bak); + (void)arg1; + (void)arg2; +} + +void np2sysp_scsidev(const void *arg1, long arg2) { + + UINT seg; + UINT off; + REGBAK regbak; + + seg = CPU_SS; + off = CPU_BP; + reg_push(®bak); + reg_load(seg, off); + + scsicmd_bios(); + + reg_store(seg, off); + reg_pop(®bak); + (void)arg1; + (void)arg2; +} +#endif + diff --git a/bios/sxsibios.h b/bios/sxsibios.h old mode 100755 new mode 100644 index 83fcad4f..2bb7ccd6 --- a/bios/sxsibios.h +++ b/bios/sxsibios.h @@ -1,37 +1,37 @@ -/** - * @file sxsibios.h - * @brief Interface of SxSI BIOS - */ - -#pragma once - -enum { - SXSIBIOS_SASI = 0, - SXSIBIOS_IDE = 1, - SXSIBIOS_SCSI = 2 -}; - -#ifdef __cplusplus -extern "C" { -#endif - -REG8 sasibios_operate(void); - -#if defined(SUPPORT_SCSI) -REG8 scsibios_operate(void); -#endif - -#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) -void np2sysp_sasi(const void *arg1, long arg2); -#endif - -#if defined(SUPPORT_SCSI) -void np2sysp_scsi(const void *arg1, long arg2); -void np2sysp_scsidev(const void *arg1, long arg2); -#endif - -void np2sysp_scsidev(const void *arg1, long arg2); - -#ifdef __cplusplus -} -#endif +/** + * @file sxsibios.h + * @brief Interface of SxSI BIOS + */ + +#pragma once + +enum { + SXSIBIOS_SASI = 0, + SXSIBIOS_IDE = 1, + SXSIBIOS_SCSI = 2 +}; + +#ifdef __cplusplus +extern "C" { +#endif + +REG8 sasibios_operate(void); + +#if defined(SUPPORT_SCSI) +REG8 scsibios_operate(void); +#endif + +#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) +void np2sysp_sasi(const void *arg1, long arg2); +#endif + +#if defined(SUPPORT_SCSI) +void np2sysp_scsi(const void *arg1, long arg2); +void np2sysp_scsidev(const void *arg1, long arg2); +#endif + +void np2sysp_scsidev(const void *arg1, long arg2); + +#ifdef __cplusplus +} +#endif diff --git a/calendar.c b/calendar.c old mode 100755 new mode 100644 index 2ff26987..6dd85eea --- a/calendar.c +++ b/calendar.c @@ -1,264 +1,264 @@ -#include -#include -#include -#include -#include - - - _CALENDAR cal; - - -static const UINT8 days[12] = { 31, 28, 31, 30, 31, 30, - 31, 31, 30, 31, 30, 31}; - -static int isLeapYear(int year) -{ - if (year % 400 == 0) - return 1; - if (year % 100 == 0) - return 0; - if (year % 4 == 0) - return 1; - return 0; -} - -static int daysInMonth(int year, int month) -{ - if (month == 2 && isLeapYear(year)) - { - return 29; - } - - return days[month - 1]; -} - -static SINT64 convertDateTimeToSeconds(const _SYSTIME *dt) -{ - int y, m; - SINT64 total_seconds; - SINT64 total_days = 0; - - for (y = 0; y < dt->year; y++) - { - total_days += isLeapYear(y) ? 366 : 365; - } - - for (m = 1; m < dt->month; m++) - { - total_days += daysInMonth(dt->year, m); - } - - total_days += (dt->day - 1); - - total_seconds = total_days * 86400LL; - total_seconds += dt->hour * 3600LL; - total_seconds += dt->minute * 60LL; - total_seconds += dt->second; - - return total_seconds; -} - -static void convertSecondsToDateTime(SINT64 total_seconds, _SYSTIME *dt) -{ - SINT64 total_days = total_seconds / 86400; - SINT64 remaining_seconds = total_seconds % 86400; - - // 時・分・秒の計算 - dt->hour = remaining_seconds / 3600; - remaining_seconds %= 3600; - - dt->minute = remaining_seconds / 60; - dt->second = remaining_seconds % 60; - - // 年の計算 - dt->year = 0; - while (1) - { - int days_in_year = isLeapYear(dt->year) ? 366 : 365; - if (total_days >= days_in_year) - { - total_days -= days_in_year; - (dt->year)++; - } - else - { - break; - } - } - - // 月の計算 - dt->month = 1; - while (1) - { - int dim = daysInMonth(dt->year, dt->month); - if (total_days >= dim) - { - total_days -= dim; - (dt->month)++; - } - else - { - break; - } - } - - // 日の計算(1日始まりに直す) - dt->day = (int)total_days + 1; -} - -static void secinc(_SYSTIME *dt) { - - UINT month; - UINT16 daylimit; - - dt->second++; - if (dt->second < 60) { - goto secinc_exit; - } - dt->second = 0; - dt->minute++; - if (dt->minute < 60) { - goto secinc_exit; - } - dt->minute = 0; - dt->hour++; - if (dt->hour < 24) { - goto secinc_exit; - } - dt->hour = 0; - - month = dt->month - 1; - if (month < 12) { - daylimit = days[month]; - if ((daylimit == 28) && (!(dt->year & 3))) { - daylimit++; // = 29; - } - } - else { - daylimit = 30; - } - dt->week = (UINT16)((dt->week + 1) % 7); - dt->day++; - if (dt->day <= daylimit) { - goto secinc_exit; - } - dt->day = 1; - dt->month++; - if (dt->month <= 12) { - goto secinc_exit; - } - dt->month = 1; - dt->year++; - -secinc_exit: - return; -} - -static void date2deg(_SYSTIME *t, const UINT8 *bcd) { - - UINT16 year; - - year = 1900 + AdjustBeforeDivision(bcd[0]); - if (year < 1980) { - year += 100; - } - t->year = (UINT16)year; - t->week = (UINT16)((bcd[1]) & 0x0f); - t->month = (UINT16)((bcd[1]) >> 4); - t->day = (UINT16)AdjustBeforeDivision(bcd[2]); - t->hour = (UINT16)AdjustBeforeDivision(bcd[3]); - t->minute = (UINT16)AdjustBeforeDivision(bcd[4]); - t->second = (UINT16)AdjustBeforeDivision(bcd[5]); -} - -static void date2bcd(UINT8 *bcd, const _SYSTIME *t) { - - bcd[0] = AdjustAfterMultiply((UINT8)(t->year % 100)); - bcd[1] = (UINT8)((t->month << 4) + t->week); - bcd[2] = AdjustAfterMultiply((UINT8)t->day); - bcd[3] = AdjustAfterMultiply((UINT8)t->hour); - bcd[4] = AdjustAfterMultiply((UINT8)t->minute); - bcd[5] = AdjustAfterMultiply((UINT8)t->second); -} - -static SINT64 calctimediff(const _SYSTIME *time1, const _SYSTIME *time2) { - return (SINT64)(convertDateTimeToSeconds(time1) - convertDateTimeToSeconds(time2)); -} -static void addtimediff(_SYSTIME *timebase, const SINT64 totalseconds) { - convertSecondsToDateTime(convertDateTimeToSeconds(timebase) + totalseconds, timebase); -} - -// ----- - -void calendar_initialize(void) { - - timemng_gettime(&cal.dt); - addtimediff(&cal.dt, np2cfg.cal_vofs); // 仮想カレンダオフセット適用 - cal.steps = 0; - cal.realchg = 1; -} - -void calendar_inc(void) { - - cal.realchg = 1; - - // 56.4Hzだから… - cal.steps += 10; - if (cal.steps < 564) { - return; - } - cal.steps -= 564; - secinc(&cal.dt); -} - -void calendar_set(const UINT8 *bcd) { - - _SYSTIME realc; - - date2deg(&cal.dt, bcd); - - if (!np2cfg.calendar) - { - timemng_gettime(&realc); - np2cfg.cal_vofs = calctimediff(&cal.dt, &realc); // 仮想カレンダオフセット記憶 - } -} - -void calendar_getvir(UINT8 *bcd) { - - date2bcd(bcd, &cal.dt); -} - -void calendar_getreal(UINT8 *bcd) { - - timemng_gettime(&cal.realc); - date2bcd(bcd, &cal.realc); -} - -void calendar_get(UINT8 *bcd) { - - if (!np2cfg.calendar) { - date2bcd(bcd, &cal.dt); - } - else { - if (cal.realchg) { - cal.realchg = 0; - timemng_gettime(&cal.realc); - } - date2bcd(bcd, &cal.realc); - } -} - -void calendar_getdt(_SYSTIME* dt) { - - if (!np2cfg.calendar) { - *dt = cal.dt; - } - else { - if (cal.realchg) { - cal.realchg = 0; - timemng_gettime(&cal.realc); - } - *dt = cal.realc; - } -} +#include +#include +#include +#include +#include + + + _CALENDAR cal; + + +static const UINT8 days[12] = { 31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; + +static int isLeapYear(int year) +{ + if (year % 400 == 0) + return 1; + if (year % 100 == 0) + return 0; + if (year % 4 == 0) + return 1; + return 0; +} + +static int daysInMonth(int year, int month) +{ + if (month == 2 && isLeapYear(year)) + { + return 29; + } + + return days[month - 1]; +} + +static SINT64 convertDateTimeToSeconds(const _SYSTIME *dt) +{ + int y, m; + SINT64 total_seconds; + SINT64 total_days = 0; + + for (y = 0; y < dt->year; y++) + { + total_days += isLeapYear(y) ? 366 : 365; + } + + for (m = 1; m < dt->month; m++) + { + total_days += daysInMonth(dt->year, m); + } + + total_days += (dt->day - 1); + + total_seconds = total_days * 86400LL; + total_seconds += dt->hour * 3600LL; + total_seconds += dt->minute * 60LL; + total_seconds += dt->second; + + return total_seconds; +} + +static void convertSecondsToDateTime(SINT64 total_seconds, _SYSTIME *dt) +{ + SINT64 total_days = total_seconds / 86400; + SINT64 remaining_seconds = total_seconds % 86400; + + // 時・分・秒の計算 + dt->hour = remaining_seconds / 3600; + remaining_seconds %= 3600; + + dt->minute = remaining_seconds / 60; + dt->second = remaining_seconds % 60; + + // 年の計算 + dt->year = 0; + while (1) + { + int days_in_year = isLeapYear(dt->year) ? 366 : 365; + if (total_days >= days_in_year) + { + total_days -= days_in_year; + (dt->year)++; + } + else + { + break; + } + } + + // 月の計算 + dt->month = 1; + while (1) + { + int dim = daysInMonth(dt->year, dt->month); + if (total_days >= dim) + { + total_days -= dim; + (dt->month)++; + } + else + { + break; + } + } + + // 日の計算(1日始まりに直す) + dt->day = (int)total_days + 1; +} + +static void secinc(_SYSTIME *dt) { + + UINT month; + UINT16 daylimit; + + dt->second++; + if (dt->second < 60) { + goto secinc_exit; + } + dt->second = 0; + dt->minute++; + if (dt->minute < 60) { + goto secinc_exit; + } + dt->minute = 0; + dt->hour++; + if (dt->hour < 24) { + goto secinc_exit; + } + dt->hour = 0; + + month = dt->month - 1; + if (month < 12) { + daylimit = days[month]; + if ((daylimit == 28) && (!(dt->year & 3))) { + daylimit++; // = 29; + } + } + else { + daylimit = 30; + } + dt->week = (UINT16)((dt->week + 1) % 7); + dt->day++; + if (dt->day <= daylimit) { + goto secinc_exit; + } + dt->day = 1; + dt->month++; + if (dt->month <= 12) { + goto secinc_exit; + } + dt->month = 1; + dt->year++; + +secinc_exit: + return; +} + +static void date2deg(_SYSTIME *t, const UINT8 *bcd) { + + UINT16 year; + + year = 1900 + AdjustBeforeDivision(bcd[0]); + if (year < 1980) { + year += 100; + } + t->year = (UINT16)year; + t->week = (UINT16)((bcd[1]) & 0x0f); + t->month = (UINT16)((bcd[1]) >> 4); + t->day = (UINT16)AdjustBeforeDivision(bcd[2]); + t->hour = (UINT16)AdjustBeforeDivision(bcd[3]); + t->minute = (UINT16)AdjustBeforeDivision(bcd[4]); + t->second = (UINT16)AdjustBeforeDivision(bcd[5]); +} + +static void date2bcd(UINT8 *bcd, const _SYSTIME *t) { + + bcd[0] = AdjustAfterMultiply((UINT8)(t->year % 100)); + bcd[1] = (UINT8)((t->month << 4) + t->week); + bcd[2] = AdjustAfterMultiply((UINT8)t->day); + bcd[3] = AdjustAfterMultiply((UINT8)t->hour); + bcd[4] = AdjustAfterMultiply((UINT8)t->minute); + bcd[5] = AdjustAfterMultiply((UINT8)t->second); +} + +static SINT64 calctimediff(const _SYSTIME *time1, const _SYSTIME *time2) { + return (SINT64)(convertDateTimeToSeconds(time1) - convertDateTimeToSeconds(time2)); +} +static void addtimediff(_SYSTIME *timebase, const SINT64 totalseconds) { + convertSecondsToDateTime(convertDateTimeToSeconds(timebase) + totalseconds, timebase); +} + +// ----- + +void calendar_initialize(void) { + + timemng_gettime(&cal.dt); + addtimediff(&cal.dt, np2cfg.cal_vofs); // 仮想カレンダオフセット適用 + cal.steps = 0; + cal.realchg = 1; +} + +void calendar_inc(void) { + + cal.realchg = 1; + + // 56.4Hzだから… + cal.steps += 10; + if (cal.steps < 564) { + return; + } + cal.steps -= 564; + secinc(&cal.dt); +} + +void calendar_set(const UINT8 *bcd) { + + _SYSTIME realc; + + date2deg(&cal.dt, bcd); + + if (!np2cfg.calendar) + { + timemng_gettime(&realc); + np2cfg.cal_vofs = calctimediff(&cal.dt, &realc); // 仮想カレンダオフセット記憶 + } +} + +void calendar_getvir(UINT8 *bcd) { + + date2bcd(bcd, &cal.dt); +} + +void calendar_getreal(UINT8 *bcd) { + + timemng_gettime(&cal.realc); + date2bcd(bcd, &cal.realc); +} + +void calendar_get(UINT8 *bcd) { + + if (!np2cfg.calendar) { + date2bcd(bcd, &cal.dt); + } + else { + if (cal.realchg) { + cal.realchg = 0; + timemng_gettime(&cal.realc); + } + date2bcd(bcd, &cal.realc); + } +} + +void calendar_getdt(_SYSTIME* dt) { + + if (!np2cfg.calendar) { + *dt = cal.dt; + } + else { + if (cal.realchg) { + cal.realchg = 0; + timemng_gettime(&cal.realc); + } + *dt = cal.realc; + } +} diff --git a/calendar.h b/calendar.h old mode 100755 new mode 100644 index e31e7aac..5fbb0411 --- a/calendar.h +++ b/calendar.h @@ -1,27 +1,27 @@ - -typedef struct { - _SYSTIME dt; - _SYSTIME realc; - UINT steps; - UINT realchg; -} _CALENDAR, *CALENDAR; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern _CALENDAR cal; - -void calendar_initialize(void); -void calendar_inc(void); -void calendar_set(const UINT8 *bcd); -void calendar_get(UINT8 *bcd); -void calendar_getdt(_SYSTIME* dt); -void calendar_getreal(UINT8 *bcd); -void calendar_getvir(UINT8 *bcd); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + _SYSTIME dt; + _SYSTIME realc; + UINT steps; + UINT realchg; +} _CALENDAR, *CALENDAR; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _CALENDAR cal; + +void calendar_initialize(void); +void calendar_inc(void); +void calendar_set(const UINT8 *bcd); +void calendar_get(UINT8 *bcd); +void calendar_getdt(_SYSTIME* dt); +void calendar_getreal(UINT8 *bcd); +void calendar_getvir(UINT8 *bcd); + +#ifdef __cplusplus +} +#endif + diff --git a/cbus/amd98.c b/cbus/amd98.c old mode 100755 new mode 100644 index 42202644..11b07d03 --- a/cbus/amd98.c +++ b/cbus/amd98.c @@ -1,546 +1,546 @@ -/** - * @file amd98.c - * @brief Implementation of AMD-98 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - AMD98 g_amd98; - -/* ないよりあったほーが良い程度のリズム… */ -static struct -{ - PMIXHDR hdr; - PMIXTRK trk[4]; - UINT rate; - UINT enable; -} amd98r; - -static REG8 rapids = 0; - -REG8 amd98_getjoy(UINT no) -{ - REG8 ret; - - rapids ^= 0xf0; - ret = 0xff; - if (no == 1) - { - ret &= (joymng_getstat() | (rapids & 0x30)); - if (np2cfg.KEY_MODE == 1) - { - ret &= keystat_getjoy(); - } - } - else - { - if (np2cfg.KEY_MODE == 2) - { - ret &= keystat_getjoy(); - } - } - if (np2cfg.BTN_RAPID) - { - ret |= rapids; - } - - /* rapidと非rapidを合成 */ - ret &= ((ret >> 2) | (~0x30)); - - if (np2cfg.BTN_MODE) - { - UINT8 bit1 = (ret & 0x20) >> 1; - UINT8 bit2 = (ret & 0x10) << 1; - ret = (ret & (~0x30)) | bit1 | bit2; - } - - return ret; -} - -static void pcmmake1(PMIXDAT *dat, UINT rate, int vol, double hz, double env) -{ - - UINT i; - double x; - double y; - double slast; - double s; - double v; - UINT size; - SINT16 *ptr; - - x = 44100.0 * 2.0 * M_PI / ((double)rate * hz); - y = 44100.0 / 256.0 / (double)rate; - slast = 0.0; - for (i = 0; i < rate; i++) - { - s = sin(x * (double)i); - v = pow(env, (double)i * y) * (double)vol; - if ((v < 128.0) && (slast < 0.0) && (s >= 0.0)) - { - break; - } - slast = s; - } - size = i; - if (!size) - { - return; - } - ptr = (SINT16 *)_MALLOC(size * sizeof(SINT16), "AMD98"); - if (ptr == NULL) - { - return; - } - for (i=0; isample = ptr; - dat->samples = size; -} - -static void pcmmake2(PMIXDAT *dat, UINT rate, int vol, double hz, double env, double k) -{ - - UINT i; - double x; - double y; - double p; - double s; - double slast; - double v; - UINT size; - SINT16 *ptr; - - x = 2.0 * M_PI * hz / (double)rate; - y = 44100.0 / 256.0 / (double)rate; - p = 0.0; - slast = 0.0; - for (i = 0; i < rate; i++) - { - p += x * pow(k, (double)i * y); - s = sin(p); - v = pow(env, (double)i * y) * (double)vol; - if ((v < 128.0) && (slast < 0.0) && (s >= 0.0)) - { - break; - } - slast = s; - } - size = i; - if (!size) - { - return; - } - ptr = (SINT16 *)_MALLOC(size * sizeof(SINT16), "AMD98"); - if (ptr == NULL) - { - return; - } - p = 0.0; - for (i = 0; i < size; i++) - { - p += x * pow(k, (double)i * y); - s = sin(p); - v = pow(env, (double)i * y) * (double)vol; - ptr[i] = (SINT16)(s * v); - } - dat->sample = ptr; - dat->samples = size; -} - -/** - * Initialize - * @param[in] rate The sample rate, in samples per second (hertz) - */ -void amd98_initialize(UINT rate) -{ - memset(&amd98r, 0, sizeof(amd98r)); - amd98r.rate = rate; -} - -/** - * Deinitialize - */ -void amd98_deinitialize(void) -{ - int i; - void *ptr; - - amd98r.hdr.enable = 0; - for (i = 0; i < 4; i++) - { - ptr = amd98r.trk[i].data.sample; - amd98r.trk[i].data.sample = NULL; - if (ptr) - { - _MFREE(ptr); - } - } -} - -static void amd98_rhythmload(void) -{ - UINT i; - - if (!amd98r.hdr.enable) - { - TRACEOUT(("AMD98 Rhythm load")); - amd98r.hdr.enable = 0x0f; - /* bd */ - pcmmake1(&amd98r.trk[0].data, amd98r.rate, - 24000, 889.0476190476, 0.9446717478); - /* lt */ - pcmmake2(&amd98r.trk[1].data, amd98r.rate, - 6400, 172.9411764706, 0.8665145391, 0.9960000000); - /* ht */ - pcmmake2(&amd98r.trk[2].data, amd98r.rate, - 9600, 213.0000000000, 0.8665145391, 0.9960000000); - /* sd */ - pcmmake1(&amd98r.trk[3].data, amd98r.rate, - 12000, 255.4400000000, 0.8538230481); - for (i = 0; i < 4; i++) - { - amd98r.trk[i].flag = PMIXFLAG_L | PMIXFLAG_R; - amd98r.trk[i].volume = 1 << 12; - } - } -} - - -/* ---- */ - -static void amd98_rhythm(UINT map) -{ - PMIXTRK *trk; - UINT bit; - - map &= 0x0f; - if (map == 0) - { - return; - } - sound_sync(); - trk = amd98r.trk; - bit = 0x01; - do - { - if ((map & bit) && (trk->data.sample)) - { - trk->pcm = trk->data.sample; - trk->remain = trk->data.samples; - amd98r.hdr.playing |= bit; - } - trk++; - bit <<= 1; - } while (bit < 0x10); -} - - -/* ---- */ - -static void setamd98event(UINT32 cnt, NEVENTPOSITION absolute) -{ - if (cnt > 8) /* 根拠なし*/ - { - cnt *= pccore.multiple; - } - else - { - cnt = pccore.multiple << 16; - } - if (!(pccore.cpumode & CPUMODE_8MHZ)) - { - cnt = cnt * 16 / 13; // cnt * 2457600 / 1996800 - } - nevent_set(NEVENT_MUSICGEN, cnt, amd98int, absolute); -} - -/** - * Interrupt - * @param[in] item A pointer to an event-item structure - */ -void amd98int(NEVENTITEM item) -{ - PITCH pitch; - - if (item->flag & NEVENT_SETEVENT) - { - pitch = pit.ch + 4; - if ((pitch->ctrl & 0x0c) == 0x04) - { - /* レートジェネレータ */ - setamd98event(pitch->value, NEVENT_RELATIVE); - } - } - pic_setirq(0x0d); -} - - -/* ---- I/O */ - -static void IOOUTCALL amd_od8(UINT port, REG8 dat) -{ - g_amd98.s.psg1reg = dat; - (void)port; -} - -static void IOOUTCALL amd_od9(UINT port, REG8 dat) -{ - g_amd98.s.psg2reg = dat; - (void)port; -} - -static void IOOUTCALL amd_oda(UINT port, REG8 dat) -{ - UINT addr; - - addr = g_amd98.s.psg1reg; - if (addr < 0x10) - { - S98_put(NORMAL2608, addr, dat); - psggen_setreg(&g_amd98.psg[0], addr, dat); - keydisp_psg((UINT8 *)&g_amd98.psg[0].reg, addr); - } - (void)port; -} - -static void IOOUTCALL amd_odb(UINT port, REG8 dat) -{ - UINT addr; - - addr = g_amd98.s.psg2reg; - if (addr < 0x0e) - { - S98_put(NORMAL2608_2, addr, dat); - psggen_setreg(&g_amd98.psg[1], addr, dat); - keydisp_psg((UINT8 *)&g_amd98.psg[1].reg, addr); - } - else if (addr == 0x0f) - { - REG8 b; - b = g_amd98.psg[1].reg.io2; - if ((b & 1) > (dat & 1)) - { - b &= 0xc2; - if (b == 0x42) - { - g_amd98.s.psg3reg = g_amd98.psg[0].reg.io2; - } - else if (b == 0x40) - { - if (g_amd98.s.psg3reg < 0x0e) - { - S98_put(NORMAL2608_3, g_amd98.s.psg3reg, g_amd98.psg[0].reg.io2); - psggen_setreg(&g_amd98.psg[2], g_amd98.s.psg3reg, g_amd98.psg[0].reg.io2); - keydisp_psg((UINT8 *)&g_amd98.psg[2].reg, g_amd98.s.psg3reg); - } - else if (g_amd98.s.psg3reg == 0x0f) - { - amd98_rhythm(g_amd98.psg[0].reg.io2); - } - } - } - g_amd98.psg[1].reg.io2 = dat; - } - (void)port; -} - -static void IOOUTCALL amd_odc(UINT port, REG8 dat) -{ - PITCH pitch; - - pitch = pit.ch + 4; - if (pit_setcount(pitch, dat)) - { - return; - } - setamd98event(pitch->value, NEVENT_ABSOLUTE); - (void)port; -} - -static void IOOUTCALL amd_ode(UINT port, REG8 dat) -{ - pit_setflag(pit.ch + 4, dat); - (void)port; -} - -static REG8 IOINPCALL amd_ida(UINT port) -{ - UINT addr; - - addr = g_amd98.s.psg1reg; - if (addr < 0x0e) - { - return psggen_getreg(&g_amd98.psg[0], addr); - } - else if (addr == 0x0e) - { - return amd98_getjoy(1); - } - else if (addr == 0x0f) - { - return g_amd98.psg[0].reg.io2; - } - (void)port; - return 0xff; -} - -static REG8 IOINPCALL amd_idb(UINT port) -{ - UINT addr; - - addr = g_amd98.s.psg2reg; - if (addr < 0x0e) - { - return psggen_getreg(&g_amd98.psg[1], addr); - } - else if (addr == 0x0e) - { - return amd98_getjoy(2); - } - else if (addr == 0x0f) - { - return g_amd98.psg[1].reg.io2; - } - (void)port; - return 0xff; -} - -#if defined(TRACE) -static REG8 IOINPCALL amd_inp(UINT port) -{ - TRACEOUT(("amd inp - %.4x", port)); - return 0xff; -} -#endif - -/* ---- Interface */ - -static void psgpanset(PSGGEN psg) -{ - psggen_setpan(psg, 0, 1); - psggen_setpan(psg, 1, 0); - psggen_setpan(psg, 2, 2); -} - -/** - * Reset - * @param[in] pConfig A pointer to a configure structure - */ -void amd98_reset(const NP2CFG *pConfig) -{ - UINT i; - - memset(&g_amd98, 0, sizeof(g_amd98)); - - for (i = 0; i < NELEMENTS(g_amd98.psg); i++) - { - psggen_reset(&g_amd98.psg[i]); - } - - (void)pConfig; -} - -/** - * Bind - */ -void amd98_bind(void) -{ - UINT i; - - amd98_rhythmload(); - - for (i = 0; i < NELEMENTS(g_amd98.psg); i++) - { - keydisp_bindpsg((UINT8 *)&g_amd98.psg[i].reg, 3993600); - psgpanset(&g_amd98.psg[i]); - psggen_restore(&g_amd98.psg[i]); - sound_streamregist(&g_amd98.psg[i], (SOUNDCB)psggen_getpcm); - } - sound_streamregist(&amd98r, (SOUNDCB)pcmmix_getpcm); - iocore_attachout(0xd8, amd_od8); - iocore_attachout(0xd9, amd_od9); - iocore_attachout(0xda, amd_oda); - iocore_attachout(0xdb, amd_odb); - iocore_attachout(0xdc, amd_odc); - iocore_attachout(0xde, amd_ode); - - iocore_attachinp(0xda, amd_ida); - iocore_attachinp(0xdb, amd_idb); -#if defined(TRACE) - iocore_attachinp(0xd8, amd_inp); - iocore_attachinp(0xd9, amd_inp); - iocore_attachinp(0xdc, amd_inp); - iocore_attachinp(0xde, amd_inp); -#endif -} -void amd98_unbind(void) -{ - iocore_detachout(0xd8); - iocore_detachout(0xd9); - iocore_detachout(0xda); - iocore_detachout(0xdb); - iocore_detachout(0xdc); - iocore_detachout(0xde); - - iocore_detachinp(0xda); - iocore_detachinp(0xdb); -#if defined(TRACE) - iocore_detachinp(0xd8); - iocore_detachinp(0xd9); - iocore_detachinp(0xdc); - iocore_detachinp(0xde); -#endif -} - -/** - * state save - */ -int amd98_sfsave(STFLAGH sfh, const SFENTRY *tbl) -{ - int ret; - UINT i; - - /* register */ - ret = statflag_write(sfh, &g_amd98.s, sizeof(g_amd98.s)); - - /* psg */ - for (i = 0; i < NELEMENTS(g_amd98.psg); i++) - { - ret |= statflag_write(sfh, &g_amd98.psg[i].reg, sizeof(g_amd98.psg[i].reg)); - } - return ret; -} - -/** - * state load - */ -int amd98_sfload(STFLAGH sfh, const SFENTRY *tbl) -{ - int ret; - UINT i; - - /* register */ - ret = statflag_read(sfh, &g_amd98.s, sizeof(g_amd98.s)); - - /* psg */ - for (i = 0; i < NELEMENTS(g_amd98.psg); i++) - { - ret |= statflag_read(sfh, &g_amd98.psg[i].reg, sizeof(g_amd98.psg[i].reg)); - } - return ret; -} +/** + * @file amd98.c + * @brief Implementation of AMD-98 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + AMD98 g_amd98; + +/* ないよりあったほーが良い程度のリズム… */ +static struct +{ + PMIXHDR hdr; + PMIXTRK trk[4]; + UINT rate; + UINT enable; +} amd98r; + +static REG8 rapids = 0; + +REG8 amd98_getjoy(UINT no) +{ + REG8 ret; + + rapids ^= 0xf0; + ret = 0xff; + if (no == 1) + { + ret &= (joymng_getstat() | (rapids & 0x30)); + if (np2cfg.KEY_MODE == 1) + { + ret &= keystat_getjoy(); + } + } + else + { + if (np2cfg.KEY_MODE == 2) + { + ret &= keystat_getjoy(); + } + } + if (np2cfg.BTN_RAPID) + { + ret |= rapids; + } + + /* rapidと非rapidを合成 */ + ret &= ((ret >> 2) | (~0x30)); + + if (np2cfg.BTN_MODE) + { + UINT8 bit1 = (ret & 0x20) >> 1; + UINT8 bit2 = (ret & 0x10) << 1; + ret = (ret & (~0x30)) | bit1 | bit2; + } + + return ret; +} + +static void pcmmake1(PMIXDAT *dat, UINT rate, int vol, double hz, double env) +{ + + UINT i; + double x; + double y; + double slast; + double s; + double v; + UINT size; + SINT16 *ptr; + + x = 44100.0 * 2.0 * M_PI / ((double)rate * hz); + y = 44100.0 / 256.0 / (double)rate; + slast = 0.0; + for (i = 0; i < rate; i++) + { + s = sin(x * (double)i); + v = pow(env, (double)i * y) * (double)vol; + if ((v < 128.0) && (slast < 0.0) && (s >= 0.0)) + { + break; + } + slast = s; + } + size = i; + if (!size) + { + return; + } + ptr = (SINT16 *)_MALLOC(size * sizeof(SINT16), "AMD98"); + if (ptr == NULL) + { + return; + } + for (i=0; isample = ptr; + dat->samples = size; +} + +static void pcmmake2(PMIXDAT *dat, UINT rate, int vol, double hz, double env, double k) +{ + + UINT i; + double x; + double y; + double p; + double s; + double slast; + double v; + UINT size; + SINT16 *ptr; + + x = 2.0 * M_PI * hz / (double)rate; + y = 44100.0 / 256.0 / (double)rate; + p = 0.0; + slast = 0.0; + for (i = 0; i < rate; i++) + { + p += x * pow(k, (double)i * y); + s = sin(p); + v = pow(env, (double)i * y) * (double)vol; + if ((v < 128.0) && (slast < 0.0) && (s >= 0.0)) + { + break; + } + slast = s; + } + size = i; + if (!size) + { + return; + } + ptr = (SINT16 *)_MALLOC(size * sizeof(SINT16), "AMD98"); + if (ptr == NULL) + { + return; + } + p = 0.0; + for (i = 0; i < size; i++) + { + p += x * pow(k, (double)i * y); + s = sin(p); + v = pow(env, (double)i * y) * (double)vol; + ptr[i] = (SINT16)(s * v); + } + dat->sample = ptr; + dat->samples = size; +} + +/** + * Initialize + * @param[in] rate The sample rate, in samples per second (hertz) + */ +void amd98_initialize(UINT rate) +{ + memset(&amd98r, 0, sizeof(amd98r)); + amd98r.rate = rate; +} + +/** + * Deinitialize + */ +void amd98_deinitialize(void) +{ + int i; + void *ptr; + + amd98r.hdr.enable = 0; + for (i = 0; i < 4; i++) + { + ptr = amd98r.trk[i].data.sample; + amd98r.trk[i].data.sample = NULL; + if (ptr) + { + _MFREE(ptr); + } + } +} + +static void amd98_rhythmload(void) +{ + UINT i; + + if (!amd98r.hdr.enable) + { + TRACEOUT(("AMD98 Rhythm load")); + amd98r.hdr.enable = 0x0f; + /* bd */ + pcmmake1(&amd98r.trk[0].data, amd98r.rate, + 24000, 889.0476190476, 0.9446717478); + /* lt */ + pcmmake2(&amd98r.trk[1].data, amd98r.rate, + 6400, 172.9411764706, 0.8665145391, 0.9960000000); + /* ht */ + pcmmake2(&amd98r.trk[2].data, amd98r.rate, + 9600, 213.0000000000, 0.8665145391, 0.9960000000); + /* sd */ + pcmmake1(&amd98r.trk[3].data, amd98r.rate, + 12000, 255.4400000000, 0.8538230481); + for (i = 0; i < 4; i++) + { + amd98r.trk[i].flag = PMIXFLAG_L | PMIXFLAG_R; + amd98r.trk[i].volume = 1 << 12; + } + } +} + + +/* ---- */ + +static void amd98_rhythm(UINT map) +{ + PMIXTRK *trk; + UINT bit; + + map &= 0x0f; + if (map == 0) + { + return; + } + sound_sync(); + trk = amd98r.trk; + bit = 0x01; + do + { + if ((map & bit) && (trk->data.sample)) + { + trk->pcm = trk->data.sample; + trk->remain = trk->data.samples; + amd98r.hdr.playing |= bit; + } + trk++; + bit <<= 1; + } while (bit < 0x10); +} + + +/* ---- */ + +static void setamd98event(UINT32 cnt, NEVENTPOSITION absolute) +{ + if (cnt > 8) /* 根拠なし*/ + { + cnt *= pccore.multiple; + } + else + { + cnt = pccore.multiple << 16; + } + if (!(pccore.cpumode & CPUMODE_8MHZ)) + { + cnt = cnt * 16 / 13; // cnt * 2457600 / 1996800 + } + nevent_set(NEVENT_MUSICGEN, cnt, amd98int, absolute); +} + +/** + * Interrupt + * @param[in] item A pointer to an event-item structure + */ +void amd98int(NEVENTITEM item) +{ + PITCH pitch; + + if (item->flag & NEVENT_SETEVENT) + { + pitch = pit.ch + 4; + if ((pitch->ctrl & 0x0c) == 0x04) + { + /* レートジェネレータ */ + setamd98event(pitch->value, NEVENT_RELATIVE); + } + } + pic_setirq(0x0d); +} + + +/* ---- I/O */ + +static void IOOUTCALL amd_od8(UINT port, REG8 dat) +{ + g_amd98.s.psg1reg = dat; + (void)port; +} + +static void IOOUTCALL amd_od9(UINT port, REG8 dat) +{ + g_amd98.s.psg2reg = dat; + (void)port; +} + +static void IOOUTCALL amd_oda(UINT port, REG8 dat) +{ + UINT addr; + + addr = g_amd98.s.psg1reg; + if (addr < 0x10) + { + S98_put(NORMAL2608, addr, dat); + psggen_setreg(&g_amd98.psg[0], addr, dat); + keydisp_psg((UINT8 *)&g_amd98.psg[0].reg, addr); + } + (void)port; +} + +static void IOOUTCALL amd_odb(UINT port, REG8 dat) +{ + UINT addr; + + addr = g_amd98.s.psg2reg; + if (addr < 0x0e) + { + S98_put(NORMAL2608_2, addr, dat); + psggen_setreg(&g_amd98.psg[1], addr, dat); + keydisp_psg((UINT8 *)&g_amd98.psg[1].reg, addr); + } + else if (addr == 0x0f) + { + REG8 b; + b = g_amd98.psg[1].reg.io2; + if ((b & 1) > (dat & 1)) + { + b &= 0xc2; + if (b == 0x42) + { + g_amd98.s.psg3reg = g_amd98.psg[0].reg.io2; + } + else if (b == 0x40) + { + if (g_amd98.s.psg3reg < 0x0e) + { + S98_put(NORMAL2608_3, g_amd98.s.psg3reg, g_amd98.psg[0].reg.io2); + psggen_setreg(&g_amd98.psg[2], g_amd98.s.psg3reg, g_amd98.psg[0].reg.io2); + keydisp_psg((UINT8 *)&g_amd98.psg[2].reg, g_amd98.s.psg3reg); + } + else if (g_amd98.s.psg3reg == 0x0f) + { + amd98_rhythm(g_amd98.psg[0].reg.io2); + } + } + } + g_amd98.psg[1].reg.io2 = dat; + } + (void)port; +} + +static void IOOUTCALL amd_odc(UINT port, REG8 dat) +{ + PITCH pitch; + + pitch = pit.ch + 4; + if (pit_setcount(pitch, dat)) + { + return; + } + setamd98event(pitch->value, NEVENT_ABSOLUTE); + (void)port; +} + +static void IOOUTCALL amd_ode(UINT port, REG8 dat) +{ + pit_setflag(pit.ch + 4, dat); + (void)port; +} + +static REG8 IOINPCALL amd_ida(UINT port) +{ + UINT addr; + + addr = g_amd98.s.psg1reg; + if (addr < 0x0e) + { + return psggen_getreg(&g_amd98.psg[0], addr); + } + else if (addr == 0x0e) + { + return amd98_getjoy(1); + } + else if (addr == 0x0f) + { + return g_amd98.psg[0].reg.io2; + } + (void)port; + return 0xff; +} + +static REG8 IOINPCALL amd_idb(UINT port) +{ + UINT addr; + + addr = g_amd98.s.psg2reg; + if (addr < 0x0e) + { + return psggen_getreg(&g_amd98.psg[1], addr); + } + else if (addr == 0x0e) + { + return amd98_getjoy(2); + } + else if (addr == 0x0f) + { + return g_amd98.psg[1].reg.io2; + } + (void)port; + return 0xff; +} + +#if defined(TRACE) +static REG8 IOINPCALL amd_inp(UINT port) +{ + TRACEOUT(("amd inp - %.4x", port)); + return 0xff; +} +#endif + +/* ---- Interface */ + +static void psgpanset(PSGGEN psg) +{ + psggen_setpan(psg, 0, 1); + psggen_setpan(psg, 1, 0); + psggen_setpan(psg, 2, 2); +} + +/** + * Reset + * @param[in] pConfig A pointer to a configure structure + */ +void amd98_reset(const NP2CFG *pConfig) +{ + UINT i; + + memset(&g_amd98, 0, sizeof(g_amd98)); + + for (i = 0; i < NELEMENTS(g_amd98.psg); i++) + { + psggen_reset(&g_amd98.psg[i]); + } + + (void)pConfig; +} + +/** + * Bind + */ +void amd98_bind(void) +{ + UINT i; + + amd98_rhythmload(); + + for (i = 0; i < NELEMENTS(g_amd98.psg); i++) + { + keydisp_bindpsg((UINT8 *)&g_amd98.psg[i].reg, 3993600); + psgpanset(&g_amd98.psg[i]); + psggen_restore(&g_amd98.psg[i]); + sound_streamregist(&g_amd98.psg[i], (SOUNDCB)psggen_getpcm); + } + sound_streamregist(&amd98r, (SOUNDCB)pcmmix_getpcm); + iocore_attachout(0xd8, amd_od8); + iocore_attachout(0xd9, amd_od9); + iocore_attachout(0xda, amd_oda); + iocore_attachout(0xdb, amd_odb); + iocore_attachout(0xdc, amd_odc); + iocore_attachout(0xde, amd_ode); + + iocore_attachinp(0xda, amd_ida); + iocore_attachinp(0xdb, amd_idb); +#if defined(TRACE) + iocore_attachinp(0xd8, amd_inp); + iocore_attachinp(0xd9, amd_inp); + iocore_attachinp(0xdc, amd_inp); + iocore_attachinp(0xde, amd_inp); +#endif +} +void amd98_unbind(void) +{ + iocore_detachout(0xd8); + iocore_detachout(0xd9); + iocore_detachout(0xda); + iocore_detachout(0xdb); + iocore_detachout(0xdc); + iocore_detachout(0xde); + + iocore_detachinp(0xda); + iocore_detachinp(0xdb); +#if defined(TRACE) + iocore_detachinp(0xd8); + iocore_detachinp(0xd9); + iocore_detachinp(0xdc); + iocore_detachinp(0xde); +#endif +} + +/** + * state save + */ +int amd98_sfsave(STFLAGH sfh, const SFENTRY *tbl) +{ + int ret; + UINT i; + + /* register */ + ret = statflag_write(sfh, &g_amd98.s, sizeof(g_amd98.s)); + + /* psg */ + for (i = 0; i < NELEMENTS(g_amd98.psg); i++) + { + ret |= statflag_write(sfh, &g_amd98.psg[i].reg, sizeof(g_amd98.psg[i].reg)); + } + return ret; +} + +/** + * state load + */ +int amd98_sfload(STFLAGH sfh, const SFENTRY *tbl) +{ + int ret; + UINT i; + + /* register */ + ret = statflag_read(sfh, &g_amd98.s, sizeof(g_amd98.s)); + + /* psg */ + for (i = 0; i < NELEMENTS(g_amd98.psg); i++) + { + ret |= statflag_read(sfh, &g_amd98.psg[i].reg, sizeof(g_amd98.psg[i].reg)); + } + return ret; +} diff --git a/cbus/amd98.h b/cbus/amd98.h old mode 100755 new mode 100644 index da05d2ec..cfc84b59 --- a/cbus/amd98.h +++ b/cbus/amd98.h @@ -1,51 +1,51 @@ -/** - * @file amd98.h - * @brief Interface of AMD-98 - */ - -#pragma once - -#include -#include -#include "sound/psggen.h" - -/** - * @breif The sturecture of AMD-98 - */ -struct amd98_t -{ - struct - { - UINT8 psg1reg; - UINT8 psg2reg; - UINT8 psg3reg; - UINT8 rhythm; - } s; - _PSGGEN psg[3]; -}; - -typedef struct amd98_t AMD98; - -#ifdef __cplusplus -extern "C" -{ -#endif - -extern AMD98 g_amd98; - -void amd98_initialize(UINT rate); -void amd98_deinitialize(void); - -void amd98int(NEVENTITEM item); - -void amd98_reset(const NP2CFG *pConfig); -void amd98_bind(void); -void amd98_unbind(void); - -int amd98_sfsave(STFLAGH sfh, const SFENTRY *tbl); -int amd98_sfload(STFLAGH sfh, const SFENTRY *tbl); - -#ifdef __cplusplus -} -#endif - +/** + * @file amd98.h + * @brief Interface of AMD-98 + */ + +#pragma once + +#include +#include +#include "sound/psggen.h" + +/** + * @breif The sturecture of AMD-98 + */ +struct amd98_t +{ + struct + { + UINT8 psg1reg; + UINT8 psg2reg; + UINT8 psg3reg; + UINT8 rhythm; + } s; + _PSGGEN psg[3]; +}; + +typedef struct amd98_t AMD98; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern AMD98 g_amd98; + +void amd98_initialize(UINT rate); +void amd98_deinitialize(void); + +void amd98int(NEVENTITEM item); + +void amd98_reset(const NP2CFG *pConfig); +void amd98_bind(void); +void amd98_unbind(void); + +int amd98_sfsave(STFLAGH sfh, const SFENTRY *tbl); +int amd98_sfload(STFLAGH sfh, const SFENTRY *tbl); + +#ifdef __cplusplus +} +#endif + diff --git a/cbus/atapicmd.c b/cbus/atapicmd.c index e9dc38f0..649b4fc7 100644 --- a/cbus/atapicmd.c +++ b/cbus/atapicmd.c @@ -1,1616 +1,1616 @@ -#include - -#if 0 -#undef TRACEOUT -static void trace_fmt_ex(const char* fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#else -#define TRACEOUT(s) (void)(s) -#endif /* 1 */ - -// これ、scsicmdとどう統合するのよ? - -#if defined(SUPPORT_IDEIO) -#if defined(NP2_WIN) -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#define YUIDEBUG - -#define SUPPORT_NECCDD - -#define HEX2BCD(hex) ( (((hex/10)%10)<<4)|((hex)%10) ) -#define BCD2HEX(bcd) ( (((bcd>>4)&0xf)*10)+((bcd)&0xf) ) - -#if defined(NP2_WIN) -static int atapi_thread_initialized = 0; -static HANDLE atapi_thread = NULL; -static IDEDRV atapi_thread_drv = NULL; -static HANDLE atapi_thread_event_request = NULL; -static HANDLE atapi_thread_event_complete = NULL; - // TODO: 非Windows用コードを書く -#endif - -// INQUIRY -static const UINT8 cdrom_inquiry[] = { -#ifdef YUIDEBUG - // うちのドライブの奴 NECCDは Product Level 3.00以上で modesense10のコードがちげー - 0x05, // CD-ROM - 0x80, // bit7: Removable Medium Bit, other: Reserved - 0x00, // version [7-6: ISO, ECMA: 5-3, 2-0: ANSI(00)] - 0x21, // 7-4: ATAPI version, 3-0: Response Data Format - 0x1f, // Additional length - 0x00,0x00,0x00, // Reserved - 'N', 'E', 'C', ' ', ' ', ' ', ' ', ' ', // Vendor ID - 'C', 'D', '-', 'R', 'O', 'M', ' ', 'D', // Product ID - 'R', 'I', 'V', 'E', ':', '9', '8', ' ', // Product ID - '1', '.', '0', ' ' // Product Revision Level -#else - 0x05, // CD-ROM - 0x80, // bit7: Removable Medium Bit, other: Reserved - 0x00, // version [7-6: ISO, ECMA: 5-3, 2-0: ANSI(00)] - 0x21, // 7-4: ATAPI version, 3-0: Response Data Format - 0x1f, // Additional length - 0x00,0x00,0x00, // Reserved - 'N', 'E', 'C', ' ', ' ', ' ', ' ', ' ', // Vendor ID - 'C', 'D', '-', 'R', 'O', 'M', ' ', 'D', // Product ID - 'R', 'I', 'V', 'E', ' ', ' ', ' ', ' ', // Product ID - '1', '.', '0', ' ' // Product Revision Level -#endif -}; - -static void senddata(IDEDRV drv, UINT size, UINT limit) { - - size = MIN(size, limit); - drv->sc = IDEINTR_IO; - drv->cy = size; - drv->status &= ~(IDESTAT_BSY|IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_CHK); - drv->status |= IDESTAT_DRQ|IDESTAT_DSC; // XXX: set Drive Seek Complete bit np21w ver0.86 rev29 - drv->error = 0; - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); - drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; - drv->bufdir = IDEDIR_IN; - drv->buftc = IDETC_TRANSFEREND; - drv->bufpos = 0; - drv->bufsize = size; - - if (!(drv->ctrl & IDECTRL_NIEN)) { - //TRACEOUT(("atapicmd: senddata()")); - ideio.bank[0] = ideio.bank[1] | 0x80; // ???? - pic_setirq(IDE_IRQ); - } -} - -static void cmddone(IDEDRV drv) { - - drv->sc = IDEINTR_IO|IDEINTR_CD; - drv->status &= ~(IDESTAT_BSY|IDESTAT_DRQ|IDESTAT_SERV|IDESTAT_CHK); - drv->status |= IDESTAT_DRDY|IDESTAT_DSC; // XXX: set Drive Seek Complete bit np21w ver0.86 rev13 - drv->error = 0; - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); - drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; - - if (!(drv->ctrl & IDECTRL_NIEN)) { - //TRACEOUT(("atapicmd: cmddone()")); - ideio.bank[0] = ideio.bank[1] | 0x80; // ???? - pic_setirq(IDE_IRQ); - } -} - -static void senderror(IDEDRV drv) { - - //drv->sc = IDEINTR_IO; - drv->sc = IDEINTR_IO | IDEINTR_CD; // set Command or Data bit np21w ver0.86 rev38 - drv->status &= ~(IDESTAT_BSY|IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_DRQ); // clear DRQ bit np21w ver0.86 rev38 - drv->status |= IDESTAT_CHK|IDESTAT_DSC; - - if (!(drv->ctrl & IDECTRL_NIEN)) { - //TRACEOUT(("atapicmd: senderror()")); - ideio.bank[0] = ideio.bank[1] | 0x80; // ???? - pic_setirq(IDE_IRQ); - } -} - -static void sendabort(IDEDRV drv) { - - drv->sk = ATAPI_SK_ABORTED_COMMAND; - drv->error = IDEERR_ABRT; - senderror(drv); -} - -static void stop_daplay(IDEDRV drv) -{ - - /* - "Play operation SHALL stopped" commands (INF-8090) - 0xA1 blank - 0x5B close track/session - 0x04 format unit - 0xA6 load/unload medium - 0x28 read(10) - 0xA8 read(12) - 0x58 repair rzone - 0x2B seek - 0x1B start/stop unit - 0x4E stop play/scan - 0x2F verify(10) - 0x2A write(10) - 0xAA write(12) - 0x2E write and verify(10) - - "Play operation SHALL NOT stopped" commands (INF-8090) - 0x46 get configuration - 0x4A get event/status notification - 0x12 inquiry - 0xBD mechanism status - 0x55 mode select - 0x5A mode sense - 0x1E prevent allow medium removal - 0x5C read buffer capacity - 0x25 read capacity - 0x03 request sense - 0xA7 set read ahead - 0x35 synchronize cache(10) - 0x00 test unit ready - */ - if (ideio.daplaying & (1 << (drv->sxsidrv & 3))) { - /* stop playing audio */ - ideio.daplaying &= ~(1 << (drv->sxsidrv & 3)); - drv->daflag = 0x13; - drv->dacurpos = 0; - drv->dalength = 0; - } -} - -// ----- ATAPI packet command - -static void atapi_cmd_start_stop_unit(IDEDRV drv); -static void atapi_cmd_prevent_allow_medium_removal(IDEDRV drv); -static void atapi_cmd_read_capacity(IDEDRV drv); -static void atapi_cmd_read(IDEDRV drv, UINT32 lba, UINT32 leng); -static void atapi_cmd_read_cd(IDEDRV drv, UINT32 lba, UINT32 leng); -static void atapi_cmd_read_cd_msf(IDEDRV drv); -static void atapi_cmd_mode_select(IDEDRV drv); -static void atapi_cmd_mode_sense(IDEDRV drv); -static void atapi_cmd_readsubch(IDEDRV drv); -static void atapi_cmd_readtoc(IDEDRV drv); -static void atapi_cmd_playaudio(IDEDRV drv); -static void atapi_cmd_playaudiomsf(IDEDRV drv); -static void atapi_cmd_pauseresume(IDEDRV drv); -static void atapi_cmd_seek(IDEDRV drv, UINT32 lba); -static void atapi_cmd_mechanismstatus(IDEDRV drv); - -#define MEDIA_CHANGE_WAIT 6 // Waitを入れないとWinNT系で正しくメディア交換出来ない -static int mediachangeflag = 0; - -extern REG8 cdchange_drv; -void cdchange_timeoutproc(NEVENTITEM item); - -void atapicmd_a0(IDEDRV drv) { - - UINT32 lba, leng; - UINT8 cmd; - - cmd = drv->buf[0]; - switch (cmd) { - case 0x00: // test unit ready - TRACEOUT(("atapicmd: test unit ready")); - if (!(drv->media & IDEIO_MEDIA_LOADED)) { - /* medium not present */ - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NOT_READY); - drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; - if(drv->sxsidrv==cdchange_drv && g_nevent.item[NEVENT_CDWAIT].clock > 0){ - if(mediachangeflag==MEDIA_CHANGE_WAIT){ - nevent_set(NEVENT_CDWAIT, 500, cdchange_timeoutproc, NEVENT_ABSOLUTE); // OS側がCDを催促しているようなので更に急いで交換 - }else if(mediachangeflag==0){ - nevent_setbyms(NEVENT_CDWAIT, 1000, cdchange_timeoutproc, NEVENT_ABSOLUTE); // OS側がCDが無いと認識したようなので急いで交換 - } - } - if(mediachangeflag < MEDIA_CHANGE_WAIT) mediachangeflag++; - //drv->status |= IDESTAT_ERR; - //drv->error = IDEERR_MCNG; - senderror(drv); - break; - } - if (drv->media & IDEIO_MEDIA_CHANGED) { - UINT8 olderror = drv->error; - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NOT_READY); - if(drv->damsfbcd){ - // NECCDD.SYS - //if(mediachangeflag){ - //if(mediachangeflag >= MEDIA_CHANGE_WAIT){ - drv->media &= ~IDEIO_MEDIA_CHANGED; - drv->asc = ATAPI_ASC_NOT_READY_TO_READY_TRANSITION; - //drv->error &= ~IDEERR_MCRQ; - //}else{ - // drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; - // mediachangeflag++; - // //drv->status |= IDESTAT_ERR; - // //drv->error |= IDEERR_MCRQ; - //} - }else{ - // for WinNT,2000 setup - //if(mediachangeflag >= MEDIA_CHANGE_WAIT){ - drv->media &= ~IDEIO_MEDIA_CHANGED; - drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; - //drv->asc = 0x0204; // LOGICAL DRIVE NOT READY - INITIALIZING COMMAND REQUIRED - //}else if(mediachangeflag >= 1){ - // drv->asc = 0x0204; // LOGICAL DRIVE NOT READY - INITIALIZING COMMAND REQUIRED - // mediachangeflag++; -// }else{ -// drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; -////#if defined(CPUCORE_IA32) -//// // Workaround for WinNT -//// if (CPU_STAT_PM && !CPU_STAT_VM86) { -// //mediachangeflag++; -//// } else -////#endif -//// { -// mediachangeflag = MEDIA_CHANGE_WAIT; -// //} -// } - } - senderror(drv); - break; - } - mediachangeflag = 0; - //if(drv->error & IDEERR_MCNG){ - // drv->status &= ~IDESTAT_ERR; - // drv->error &= ~IDEERR_MCNG; - //} - - cmddone(drv); - break; - - case 0x03: // request sense - TRACEOUT(("atapicmd: request sense")); - leng = drv->buf[4]; - ZeroMemory(drv->buf, 18); - drv->buf[0] = 0x70; - drv->buf[2] = drv->sk; - drv->buf[7] = 11; // length - drv->buf[12] = (UINT8)(drv->asc & 0xff); // Additional Sense Code - drv->buf[13] = (UINT8)((drv->asc>>8) & 0xff); // Additional Sense Code Qualifier (Optional) - senddata(drv, 18, leng); - break; - - case 0x12: // inquiry - TRACEOUT(("atapicmd: inquiry")); - leng = drv->buf[4]; - CopyMemory(drv->buf, cdrom_inquiry, sizeof(cdrom_inquiry)); - senddata(drv, sizeof(cdrom_inquiry), leng); - break; - - case 0x1b: // start stop unit - TRACEOUT(("atapicmd: start stop unit")); - atapi_cmd_start_stop_unit(drv); - break; - - case 0x1e: // prevent allow medium removal - TRACEOUT(("atapicmd: prevent allow medium removal")); - atapi_cmd_prevent_allow_medium_removal(drv); - break; - - case 0x25: // read capacity - TRACEOUT(("atapicmd: read capacity")); - atapi_cmd_read_capacity(drv); - break; - - case 0x28: // read(10) - //TRACEOUT(("atapicmd: read(10)")); - lba = (drv->buf[2] << 24) + (drv->buf[3] << 16) + (drv->buf[4] << 8) + drv->buf[5]; - leng = (drv->buf[7] << 8) + drv->buf[8]; - atapi_cmd_read(drv, lba, leng); - break; - - case 0xbe: // read cd - lba = (drv->buf[2] << 24) + (drv->buf[3] << 16) + (drv->buf[4] << 8) + drv->buf[5]; - leng = (drv->buf[6] << 16) + (drv->buf[7] << 8) + drv->buf[8]; - atapi_cmd_read_cd(drv, lba, leng); - break; - - case 0xb9: // read cd msf - atapi_cmd_read_cd_msf(drv); - break; - - case 0x2b: // Seek - lba = (drv->buf[2] << 24) + (drv->buf[3] << 16) + (drv->buf[4] << 8) + drv->buf[5]; - atapi_cmd_seek(drv, lba); - break; - - case 0x55: // mode select - TRACEOUT(("atapicmd: mode select")); - atapi_cmd_mode_select(drv); - break; - - case 0x5a: // mode sense(10) - TRACEOUT(("atapicmd: mode sense(10)")); - atapi_cmd_mode_sense(drv); - break; - - case 0x42: - TRACEOUT(("atapicmd: read sub channel")); - atapi_cmd_readsubch(drv); - break; - - case 0x43: // read TOC - TRACEOUT(("atapicmd: read TOC")); - atapi_cmd_readtoc(drv); - break; - - case 0x45: // Play Audio - TRACEOUT(("atapicmd: Play Audio")); - atapi_cmd_playaudio(drv); - break; - - case 0x46: // get config? - TRACEOUT(("atapicmd: get config")); - leng = drv->buf[7]|(drv->buf[8] << 8); - ZeroMemory(drv->buf, 512); - drv->buf[10] = 3; - drv->buf[6] = 8; - if(leng == 0) leng = 12; - senddata(drv, 512, leng); - break; - - case 0x47: // Play Audio MSF - TRACEOUT(("atapicmd: Play Audio MSF")); - atapi_cmd_playaudiomsf(drv); - break; - - case 0x4b: - TRACEOUT(("atapicmd: pause resume")); - atapi_cmd_pauseresume(drv); - break; - - case 0xbd: // mechanism status - TRACEOUT(("atapicmd: mechanism status")); - atapi_cmd_mechanismstatus(drv); - break; - - default: - TRACEOUT(("atapicmd: unknown command = %.2x", cmd)); - sendabort(drv); - break; - } -} - - -//-- command - -// 0x1b: START/STOP UNIT -#ifdef SUPPORT_PHYSICAL_CDDRV -void atapi_cmd_traycmd_eject_threadfunc(void* vdParam) { -#if defined(NP2_WIN) - HANDLE handle; - DWORD dwRet = 0; - wchar_t wpath[MAX_PATH]; - codecnv_utf8toucs2(wpath, MAX_PATH, np2cfg.idecd[(int)vdParam], -1); - handle = CreateFileW(wpath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if(handle != INVALID_HANDLE_VALUE){ - if(DeviceIoControl(handle, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &dwRet, 0)){ - if(DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &dwRet, 0)){ - DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, &dwRet, 0); - } - } - CloseHandle(handle); - } -#else - // TODO: Windows以外のコードを書く -#endif -} -void atapi_cmd_traycmd_close_threadfunc(void* vdParam) { -#if defined(NP2_WIN) - HANDLE handle; - DWORD dwRet = 0; - wchar_t wpath[MAX_PATH]; - codecnv_utf8toucs2(wpath, MAX_PATH, np2cfg.idecd[(int)vdParam], -1); - handle = CreateFileW(wpath, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); - if(handle != INVALID_HANDLE_VALUE){ - DeviceIoControl(handle, IOCTL_STORAGE_LOAD_MEDIA, 0, 0, 0, 0, &dwRet, 0); - CloseHandle(handle); - } -#else - // TODO: Windows以外のコードを書く -#endif -} -#endif -static void atapi_cmd_start_stop_unit(IDEDRV drv) { - - UINT power; - SXSIDEV sxsi; - - sxsi = sxsi_getptr(drv->sxsidrv); - - stop_daplay(drv); - - power = (drv->buf[4] >> 4); - if (power != 0) { - /* power control is not supported */ - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); - drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; - goto send_error; - } - switch(drv->buf[4] & 3){ - case 0: // Stop the Disc - break; - case 1: // Start the Disc and read the TOC - if (!(drv->media & IDEIO_MEDIA_LOADED)) { - atapi_cmd_readtoc(drv); - return; - } - break; - case 2: // Eject the Disc if possible -#ifdef SUPPORT_PHYSICAL_CDDRV - if(np2cfg.allowcdtraycmd && _tcsnicmp(np2cfg.idecd[sxsi->drv], OEMTEXT("\\\\.\\"), 4)==0){ -#if defined(NP2_WIN) - _beginthread(atapi_cmd_traycmd_eject_threadfunc, 0, (void*)sxsi->drv); -#else - // TODO: Windows以外のコードを書く -#endif - }else -#endif - { - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); - drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; - goto send_error; - } - break; - case 3: // Load the Disc (Close Tray) -#ifdef SUPPORT_PHYSICAL_CDDRV - if(np2cfg.allowcdtraycmd && _tcsnicmp(np2cfg.idecd[sxsi->drv], OEMTEXT("\\\\.\\"), 4)==0){ -#if defined(NP2_WIN) - _beginthread(atapi_cmd_traycmd_close_threadfunc, 0, (void*)sxsi->drv); -#else - // TODO: Windows以外のコードを書く -#endif - }else -#endif - { - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); - drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; - goto send_error; - } - break; - } - if (!(drv->media & IDEIO_MEDIA_LOADED)) { - /* medium not present */ - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NOT_READY); - drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; - goto send_error; - } - - /* XXX play/read TOC, stop */ - - cmddone(drv); - - return; - -send_error: - senderror(drv); -} - -// 0x1e: PREVENT/ALLOW MEDIUM REMOVAL -static void atapi_cmd_prevent_allow_medium_removal(IDEDRV drv) { - - /* XXX */ - cmddone(drv); -} - -// 0x25: READ CAPACITY -static void atapi_cmd_read_capacity(IDEDRV drv) { - - /* XXX */ - UINT32 blklen = 2048; // drv->secsize; - UINT8 *b = drv->buf; - SXSIDEV sxsi; - UINT32 totals; - - sxsi = sxsi_getptr(drv->sxsidrv); - if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY) && drv->device != IDETYPE_CDROM)) { - senderror(drv); - return; - } - totals = (UINT32)sxsi->totals; - - b[0] = (UINT8)(totals >> 24); - b[1] = (UINT8)(totals >> 16); - b[2] = (UINT8)(totals >> 8); - b[3] = (UINT8)(totals); - b[4] = (UINT8)(blklen >> 24); - b[5] = (UINT8)(blklen >> 16); - b[6] = (UINT8)(blklen >> 8); - b[7] = (UINT8)(blklen); - - senddata(drv, 8, 8); - - //cmddone(drv); -} - -// 0x28: READ(10) -#if defined(NP2_WIN) -static int atapi_dataread_error = -1; -void atapi_dataread_threadfunc_part(IDEDRV drv) { - - SXSIDEV sxsi; - sxsi = sxsi_getptr(drv->sxsidrv); - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; - - if (sxsi_read(drv->sxsidrv, drv->sector, drv->buf, 2048) != 0) { - atapi_dataread_error = 1; - return; - } - - // EDC/ECC check - if(np2cfg.usecdecc && (sxsi->cdflag_ecc & CD_ECC_BITMASK)==CD_ECC_ERROR){ - atapi_dataread_error = 2; - return; - } - - atapi_dataread_error = 0; -} -void atapi_dataread_asyncwait(int wait) { - if(atapi_dataread_error!=-1 && atapi_thread_drv && (!np2cfg.useasynccd || !atapi_thread || WaitForSingleObject(atapi_thread_event_complete, wait) == WAIT_OBJECT_0)){ - IDEDRV drv = atapi_thread_drv; - SXSIDEV sxsi; - sxsi = sxsi_getptr(drv->sxsidrv); - drv->status &= ~(IDESTAT_DRQ); - - switch(atapi_dataread_error){ - case 1: - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); - drv->asc = 0x21; - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; - senderror(drv); - TRACEOUT(("atapicmd: read error at sector %d", drv->sector)); - break; - case 2: - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_MEDIUM_ERROR); - drv->sk = 0x03; - drv->asc = 0x11; - drv->status |= IDESTAT_ERR; - drv->error |= IDEERR_UNC; - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; - senderror(drv); - TRACEOUT(("atapicmd: EDC/ECC error detected at sector %d", drv->sector)); - break; - case 0: - drv->sector++; - drv->nsectors--; - - drv->sc = IDEINTR_IO; - drv->cy = 2048; - drv->status &= ~(IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_CHK); - drv->status |= IDESTAT_DRQ; - drv->error = 0; - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); - drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; - drv->bufdir = IDEDIR_IN; - drv->buftc = (drv->nsectors)?IDETC_ATAPIREAD:IDETC_TRANSFEREND; - drv->bufpos = 0; - drv->bufsize = 2048; - - if(np2cfg.usecdecc && (sxsi->cdflag_ecc & CD_ECC_BITMASK)==CD_ECC_RECOVERED){ - drv->status |= IDESTAT_CORR; - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_RECOVERED_ERROR); - drv->asc = 0x18; - } - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; - - drv->status &= ~(IDESTAT_BSY); // 念のため直前で解除 - if (!(drv->ctrl & IDECTRL_NIEN)) { - //TRACEOUT(("atapicmd: senddata()")); - ideio.bank[0] = ideio.bank[1] | 0x80; // ???? - pic_setirq(IDE_IRQ); - } - - break; - } - atapi_dataread_error = -1; - } -} -unsigned int __stdcall atapi_dataread_threadfunc(void* vdParam) { - IDEDRV drv = NULL; - - SetEvent(atapi_thread_event_complete); - while(WaitForSingleObject(atapi_thread_event_request, INFINITE) == WAIT_OBJECT_0){ - if(!atapi_thread_initialized) break; - drv = atapi_thread_drv; - atapi_dataread_threadfunc_part(drv); - SetEvent(atapi_thread_event_complete); - } - SetEvent(atapi_thread_event_complete); - _endthreadex(0); - return 0; - -} -void atapi_dataread(IDEDRV drv) { - - if(drv->status & IDESTAT_BSY) { - return; - } - - // エラー処理目茶苦茶〜 - if (drv->nsectors == 0) { - sendabort(drv); - return; - } - - drv->status |= IDESTAT_BSY; - - if(np2cfg.useasynccd){ - if(atapi_thread){ - atapi_dataread_asyncwait(INFINITE); - ResetEvent(atapi_thread_event_complete); - atapi_dataread_error = -1; - atapi_thread_drv = drv; - SetEvent(atapi_thread_event_request); - atapi_dataread_asyncwait(2); - }else{ - atapi_dataread_error = -1; - atapi_thread_drv = drv; - atapi_dataread_threadfunc_part(drv); - atapi_dataread_asyncwait(0); - } - }else{ - if(atapi_thread){ - atapi_dataread_asyncwait(INFINITE); - } - atapi_dataread_error = -1; - atapi_thread_drv = drv; - atapi_dataread_threadfunc_part(drv); - atapi_dataread_asyncwait(0); - } -} -#else -void atapi_dataread(IDEDRV drv) { - - SXSIDEV sxsi; - sxsi = sxsi_getptr(drv->sxsidrv); - - // エラー処理目茶苦茶〜 - if (drv->nsectors == 0) { - sendabort(drv); - return; - } - - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; - - if (sxsi_read(drv->sxsidrv, drv->sector, drv->buf, 2048) != 0) { - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); - drv->asc = 0x21; - senderror(drv); - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; - return; - } - - // EDC/ECC check - if(np2cfg.usecdecc && (sxsi->cdflag_ecc & CD_ECC_BITMASK)==CD_ECC_ERROR){ - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_MEDIUM_ERROR); - drv->sk = 0x03; - drv->asc = 0x11; - drv->status |= IDESTAT_ERR; - drv->error |= IDEERR_UNC; - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; - senderror(drv); - return; - } - - drv->sector++; - drv->nsectors--; - - drv->sc = IDEINTR_IO; - drv->cy = 2048; - drv->status &= ~(IDESTAT_BSY|IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_CHK); - drv->status |= IDESTAT_DRQ; - drv->error = 0; - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); - drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; - drv->bufdir = IDEDIR_IN; - drv->buftc = (drv->nsectors)?IDETC_ATAPIREAD:IDETC_TRANSFEREND; - drv->bufpos = 0; - drv->bufsize = 2048; - - if(np2cfg.usecdecc && (sxsi->cdflag_ecc & CD_ECC_BITMASK)==CD_ECC_RECOVERED){ - drv->status |= IDESTAT_CORR; - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_RECOVERED_ERROR); - drv->asc = 0x18; - } - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; - - if (!(drv->ctrl & IDECTRL_NIEN)) { - //TRACEOUT(("atapicmd: senddata()")); - ideio.bank[0] = ideio.bank[1] | 0x80; // ???? - pic_setirq(IDE_IRQ); - } -} -#endif - -void atapi_dataread_end(IDEDRV drv) { - SXSIDEV sxsi; - sxsi = sxsi_getptr(drv->sxsidrv); - - drv->sector++; - drv->nsectors--; - - drv->sc = IDEINTR_IO; - drv->cy = 2048; - drv->status &= ~(IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_CHK); - drv->status |= IDESTAT_DRQ; - drv->error = 0; - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); - drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; - drv->bufdir = IDEDIR_IN; - drv->buftc = (drv->nsectors)?IDETC_ATAPIREAD:IDETC_TRANSFEREND; - drv->bufpos = 0; - drv->bufsize = 2048; - - if(np2cfg.usecdecc && (sxsi->cdflag_ecc & CD_ECC_BITMASK)==CD_ECC_RECOVERED){ - drv->status |= IDESTAT_CORR; - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_RECOVERED_ERROR); - drv->asc = 0x18; - } - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; - - drv->status &= ~(IDESTAT_BSY); // 念のため直前で解除 - if (!(drv->ctrl & IDECTRL_NIEN)) { - //TRACEOUT(("atapicmd: senddata()")); - ideio.bank[0] = ideio.bank[1] | 0x80; // ???? - pic_setirq(IDE_IRQ); - } -#if defined(NP2_WIN) - atapi_dataread_error = -1; -#endif -} -void atapi_dataread_errorend(IDEDRV drv) { - SXSIDEV sxsi; - sxsi = sxsi_getptr(drv->sxsidrv); - - drv->status &= ~(IDESTAT_DRQ); - - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); - drv->asc = 0x21; - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; - senderror(drv); - TRACEOUT(("atapicmd: read error at sector %d", drv->sector)); -#if defined(NP2_WIN) - atapi_dataread_error = -1; -#endif -} - -static void atapi_cmd_read(IDEDRV drv, UINT32 lba, UINT32 nsec) { - - drv->sector = lba; - drv->nsectors = nsec; - atapi_dataread(drv); -} -static void atapi_cmd_read_cd(IDEDRV drv, UINT32 lba, UINT32 nsec) { - - int i; - SXSIDEV sxsi; - CDTRK trk; - UINT tracks; - UINT8 *bufptr; - UINT bufsize; - - UINT8 rawdata[2352]; - - UINT8 hassync; - UINT8 hashead; - UINT8 hassubhead; - UINT8 hasdata; - UINT8 hasedcecc; - - UINT16 isCDDA = 1; - -#if defined(NP2_WIN) - atapi_thread_drv = drv; -#endif - sxsi = sxsi_getptr(drv->sxsidrv); - - hassync = (drv->buf[9] & 0x80) ? 1 : 0; - hassubhead = (drv->buf[9] & 0x40) ? 1 : 0; - hashead = (drv->buf[9] & 0x20) ? 1 : 0; - hasdata = (drv->buf[9] & 0x10) ? 1 : 0; - hasedcecc = (drv->buf[9] & 0x08) ? 1 : 0; - - drv->sector = lba; - drv->nsectors = nsec; - - // エラー処理目茶苦茶〜 - if (drv->nsectors == 0) { - cmddone(drv); - return; - } - - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; - - trk = sxsicd_gettrk(sxsi, &tracks); - for (i = 0; i < tracks; i++) { - if (trk[i].str_sec <= (UINT32)drv->sector && (UINT32)drv->sector <= trk[i].end_sec) { - isCDDA = (trk[i].adr_ctl == TRACKTYPE_AUDIO); - break; - } - } - - if(isCDDA){ - // Audio - if (sxsicd_readraw(sxsi, drv->sector, drv->buf) != SUCCESS) { - atapi_dataread_errorend(0); - return; - } - bufsize = 2352; - }else{ - // 条件がかなり複雑。 - // ATAPI CD-ROM Specificationの - // Table 99 - Number of Bytes Returned Based on Data Selection Field - // を参照 - - // MODE1決め打ち - if (sxsicd_readraw(sxsi, drv->sector, rawdata) != SUCCESS) { - atapi_dataread_errorend(0); - return; - } - - bufsize = 0; - bufptr = drv->buf; - if (hassync){ - if(hashead){ - // Headerがいるときだけ有効 - memcpy(bufptr, rawdata, 12); - bufptr += 12; - bufsize += 12; - } - } - if (hashead){ - memcpy(bufptr, rawdata + 12, 4); - bufptr += 4; - bufsize += 4; - } - if (hassubhead){ - // MODE1(本来ないが、User Dataが無いときだけ特例で書く) - if(!hasdata){ - memset(bufptr, 0, 8); - bufptr += 8; - bufsize += 8; - - } - - //// XA - //memcpy(bufptr, rawdata + 12 + 4, 8); - - //bufptr += 8; - //bufsize += 8; - } - if (hasdata){ - memcpy(bufptr, rawdata + 12 + 4 + 8, 2048); - bufptr += 2048; - bufsize += 2048; - } - if (hasedcecc){ - //// MODE1 - //memcpy(bufptr, rawdata + 12 + 4 + 8 + 2048, 4); - //memcpy(bufptr + 4, rawdata + 12 + 4 + 8 + 2048 + 12, 276); - - ////// XA - ////memcpy(bufptr, rawdata + 12 + 4 + 8 + 2048, 280); - - //bufptr += 280; - //bufsize += 280; - - memcpy(bufptr, rawdata + 12 + 4 + 8 + 2048, 288); - bufptr += 288; - bufsize += 288; - } - } - - atapi_dataread_end(drv); - - drv->bufsize = bufsize; - drv->cy = bufsize; -} - -static void atapi_cmd_read_cd_msf(IDEDRV drv) { - - UINT32 pos; - UINT32 leng; - - int M, S, F; - if(drv->damsfbcd){ - M = BCD2HEX(drv->buf[3]); - S = BCD2HEX(drv->buf[4]); - F = BCD2HEX(drv->buf[5]); - pos = (((M * 60) + S) * 75) + F; - M = BCD2HEX(drv->buf[6]); - S = BCD2HEX(drv->buf[7]); - F = BCD2HEX(drv->buf[8]); - leng = (((M * 60) + S) * 75) + F; - }else{ - M = drv->buf[3]; - S = drv->buf[4]; - F = drv->buf[5]; - pos = (((M * 60) + S) * 75) + F; - M = drv->buf[6]; - S = drv->buf[7]; - F = drv->buf[8]; - leng = (((M * 60) + S) * 75) + F; - } - if (leng > pos) { - leng -= pos; - } - else { - leng = 0; - } - if (pos >= 150) { - pos -= 150; - } - else { - pos = 0; - } - atapi_cmd_read_cd(drv, pos, leng); -} - -// -- MODE SELECT/SENSE -#define PC_01_SIZE 8 -#define PC_0D_SIZE 8 -#define PC_0E_SIZE 16 -#define PC_2A_SIZE 20 - -// page code changeable value -static const UINT8 chgval_pagecode_01[PC_01_SIZE] = { - 0x00, 0x00, 0x37, 0xff, 0x00, 0x00, 0x00, 0x00, -}; -static const UINT8 chgval_pagecode_0d[PC_0D_SIZE] = { - 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, -}; -static const UINT8 chgval_pagecode_0e[PC_0E_SIZE] = { - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, -}; -static const UINT8 chgval_pagecode_2a[PC_2A_SIZE] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xc2, 0x00, 0x02, 0x00, 0x00, 0x02, 0xc2, - 0x00, 0x00, 0x00, 0x00, -}; - -// page code default value -static const UINT8 defval_pagecode_01[PC_01_SIZE] = { - 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static const UINT8 defval_pagecode_0d[PC_0D_SIZE] = { - 0x0d, 0x06, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x4b, -}; -static const UINT8 defval_pagecode_0e[PC_0E_SIZE] = { - 0x0e, 0x0e, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, - 0x01, 0xff, 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, -}; - -static const UINT8 defval_pagecode_2a[PC_2A_SIZE] = { -//#ifdef YUIDEBUG -// 0x2a, 0x12, 0x00, 0x00, 0x71, 0x65, 0x89, 0x07, -// 0x02, 0xc2, 0x00, 0xff, 0x00, 0x80, 0x02, 0xc2, -// 0x00, 0x00, 0x00, 0x00, -//#else - 0x2a, 0x12, 0x00, 0x00, 0x71, 0x65, 0x29, 0x07, - 0x02, 0xc2, 0x00, 0xff, 0x00, 0x80, 0x02, 0xc2, - 0x00, 0x00, 0x00, 0x00, -//#endif -}; - -#if defined(SUPPORT_NECCDD) -#define PC_0F_SIZE 16 - -// "NEC CD-ROM" unique? (for neccdd.sys) -// It's just a stub, all values are unknown... -static const UINT8 chgval_pagecode_0f[PC_0F_SIZE] = { - 0x0f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static const UINT8 defval_pagecode_0f[PC_0F_SIZE] = { - 0x0f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -#endif - - -// 0x55: MODE SELECT -static void atapi_cmd_mode_select(IDEDRV drv) { - - UINT leng; - - leng = (drv->buf[7] << 8) + drv->buf[8]; - TRACEOUT(("atapi_cmd_mode_select: leng=%u SP=%u", leng, drv->buf[1] & 1)); - - if (drv->buf[1] & 1) { - /* Saved Page is not supported */ - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); - drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; - senderror(drv); - return; - } - -#if 1 - cmddone(drv); /* workaround */ -#else - sendabort(drv); /* XXX */ -#endif - -} - -// 0x5a: MODE SENSE -static void atapi_cmd_mode_sense(IDEDRV drv) { - - const UINT8 *ptr; - UINT leng; - UINT cnt; - UINT8 pctrl, pcode; - - leng = (drv->buf[7] << 8) + drv->buf[8]; - pctrl = ((drv->buf[2] >> 6) & 3) & ~0x2; // 0: current, 1: changeable, 2: default - pcode = drv->buf[2] & 0x3f; - - if (pctrl == 3) { - /* Saved Page is not supported */ - //TRACEOUT(("Saved Page is not supported")); - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); - drv->asc = ATAPI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED; - senderror(drv); - return; - } - - /* Mode Parameter Header */ - ZeroMemory(drv->buf, 8); - if (!(drv->media & IDEIO_MEDIA_LOADED)) { - drv->buf[2] = 0x70; // Door closed, no disc present - } - else if ((drv->media & (IDEIO_MEDIA_COMBINE)) == IDEIO_MEDIA_AUDIO) { - drv->buf[2] = 0x02; // 120mm CD-ROM audio only - } - else if ((drv->media & (IDEIO_MEDIA_COMBINE)) == IDEIO_MEDIA_COMBINE) { - drv->buf[2] = 0x03; // 120mm CD-ROM data & audio combined - } - else { - drv->buf[2] = 0x01; // 120mm CD-ROM data only - } - cnt = 8; - if (cnt > leng) { - goto length_exceeded; - } - - /* Mode Page */ - //TRACEOUT(("pcode = %.2x", pcode)); - switch (pcode) { -#if defined(SUPPORT_NECCDD) - case 0x0f: - { - // some NEC CD-ROM specific support (required for neccdd.sys) - const UINT8 *p2a; - UINT8 *p = drv->buf + cnt; - if (pctrl == 1) { - p2a = chgval_pagecode_2a; - ptr = chgval_pagecode_0f; - } - else { - p2a = defval_pagecode_2a; - ptr = defval_pagecode_0f; - } - CopyMemory(p, ptr, MIN((leng - cnt), PC_0F_SIZE)); - p[4] = (p2a[4] & 1); // byte04 bit0 = Audioplay supported? - p[4] |= ((p2a[6] & 2) << 6); // byte04 bit7 = lock state? - p[4] |= ((p2a[5] & 4) << 2); // byte04 bit4 = R-W supported? - p[5] = ((p2a[7] & 3) << 3); // byte05 bit4,3 = audio manipulation? - // note: When byte04 bit1 is set, neccdd.sys will set bit10 in device status call. - // (bit10 is "reserved" in the Microsoft's reference) - // for drive specific applications? or simply a bug?) - } - cnt += PC_0F_SIZE; - if (cnt > leng) { - goto length_exceeded; - } - drv->damsfbcd = 1; // XXX: NEC CD-ROMコマンドを飛ばしてきたらBCDモードにする・・・(暫定neccdd.sys判定) - break; -#endif - case 0x3f: - /*FALLTHROUGH*/ - - case 0x01: /* Read Error Recovery Parameters Page */ - if (pctrl == 1) { - ptr = chgval_pagecode_01; - } - else { - ptr = defval_pagecode_01; - } - CopyMemory(drv->buf + cnt, ptr, MIN((leng - cnt), PC_01_SIZE)); - cnt += PC_01_SIZE; - if (cnt > leng) { - goto length_exceeded; - } - if (pcode == 0x01) { - break; - } - /*FALLTHROUGH*/ - - case 0x0d: /* CD-ROM Device Parameters Page */ - if (pctrl == 1) { - ptr = chgval_pagecode_0d; - } - else { - ptr = defval_pagecode_0d; - } - CopyMemory(drv->buf + cnt, ptr, MIN((leng - cnt), PC_0D_SIZE)); - cnt += PC_0D_SIZE; - if (cnt > leng) { - goto length_exceeded; - } - if (pcode == 0x0d) { - break; - } - /*FALLTHROUGH*/ - - case 0x0e: /* CD-ROM Audio Control Paramater Page */ - if (pctrl == 1) { - ptr = chgval_pagecode_0e; - } - else { - ptr = defval_pagecode_0e; - } - CopyMemory(drv->buf + cnt, ptr, MIN((leng - cnt), PC_0E_SIZE)); - cnt += PC_0E_SIZE; - if (cnt > leng) { - goto length_exceeded; - } - if (pcode == 0x0e) { - break; - } - //np2cfg.davolume = drv->buf[11]; - /*FALLTHROUGH*/ - - case 0x2a: /* CD-ROM Capabilities & Mechanical Status Page */ - if (pctrl == 1) { - ptr = chgval_pagecode_2a; - } - else { - ptr = defval_pagecode_2a; - } - CopyMemory(drv->buf + cnt, ptr, MIN((leng - cnt), PC_2A_SIZE)); - cnt += PC_2A_SIZE; - if (cnt > leng) { - goto length_exceeded; - } -#if 0 - /*FALLTHROUGH*/ - - case 0x00: -#endif - break; - - default: - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); - drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; - senderror(drv); - return; - } - - drv->buf[0] = (UINT8)((cnt - 2) >> 8); - drv->buf[1] = (UINT8)(cnt - 2); - senddata(drv, cnt, leng); - return; - -length_exceeded: - if (cnt >= 65536) { - ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); - drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; - senderror(drv); - return; - } - - drv->buf[0] = (UINT8)((leng - 2) >> 8); - drv->buf[1] = (UINT8)(leng - 2); - senddata(drv, cnt, leng); -} - - -// ---- Audio - -static void storemsf(UINT8 *ptr, UINT32 pos, int isBCD) { - - UINT f; - UINT m; - - f = pos % 75; - pos = pos / 75; - m = pos % 60; - pos = pos / 60; - ptr[0] = 0; - if(isBCD){ - if (pos > 99) { - ptr[1] = 0xff; - ptr[2] = 0x59; - ptr[3] = 0x74; - return; - } - ptr[1] = (UINT8)HEX2BCD(pos); - ptr[2] = (UINT8)HEX2BCD(m); - ptr[3] = (UINT8)HEX2BCD(f); - }else{ - if (pos > 0xff) { - pos = 0xff; - m = 59; - f = 74; - } - ptr[1] = (UINT8)pos; - ptr[2] = (UINT8)m; - ptr[3] = (UINT8)f; - } -} - -static void storelba(UINT8 *ptr, UINT32 pos) { - - ptr[0] = (UINT8)(pos >> 24); - ptr[1] = (UINT8)(pos >> 16); - ptr[2] = (UINT8)(pos >> 8); - ptr[3] = (UINT8)(pos); -} - -// 0x42: READ SUB CHANNEL -static void atapi_cmd_readsubch(IDEDRV drv) { - - SXSIDEV sxsi; - UINT subq; - UINT cmd; - UINT leng; - CDTRK trk; - UINT tracks; - UINT r; - UINT32 pos; - - sxsi = sxsi_getptr(drv->sxsidrv); - if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) || - (!(sxsi->flag & SXSIFLAG_READY))) { - senderror(drv); - return; - } - trk = sxsicd_gettrk(sxsi, &tracks); - leng = (drv->buf[7] << 8) + drv->buf[8]; - subq = drv->buf[2] & 0x40; - cmd = drv->buf[3]; - - drv->buf[0] = 0; - drv->buf[1] = (UINT8)drv->daflag; - drv->buf[2] = 0; - drv->buf[3] = 0; - if (!subq) { - senddata(drv, 4, leng); - return; - } - switch(cmd) { - case 0x01: // CD-ROM current pos - ZeroMemory(drv->buf + 4, 12); - drv->buf[3] = 0x12; - drv->buf[4] = 0x01; - if (drv->daflag != 0x15) { - pos = drv->dacurpos; - if ((drv->daflag == 0x12) || (drv->daflag == 0x13)) { - pos += (rand() & 7); - } - r = tracks; - while(r) { - r--; - if (trk[r].pos <= pos) { - break; - } - } -#ifdef SUPPORT_KAI_IMAGES - drv->buf[5] = trk[r].adr_ctl; - drv->buf[6] = trk[r].point; -#else - drv->buf[5] = trk[r].type; - drv->buf[6] = trk[r].track; -#endif - drv->buf[7] = 1; - - storemsf(drv->buf + 8, pos + 150, drv->damsfbcd); - storemsf(drv->buf + 12, (UINT32)(pos - trk[r].pos), drv->damsfbcd); - } - senddata(drv, 16, leng); - break; - - default: - senderror(drv); - break; - } -} - -// 0x43: READ TOC -static void atapi_cmd_readtoc(IDEDRV drv) { - - SXSIDEV sxsi; - UINT leng; - UINT format; - CDTRK trk; - UINT tracks; - UINT datasize; - UINT8 *ptr; - UINT i; -#ifdef SUPPORT_KAI_IMAGES - UINT8 time; // 追加(kaiD) -#endif - UINT8 strack; - - sxsi = sxsi_getptr(drv->sxsidrv); - if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) || - (!(sxsi->flag & SXSIFLAG_READY))) { - senderror(drv); - return; - } - trk = sxsicd_gettrk(sxsi, &tracks); - -#ifdef SUPPORT_KAI_IMAGES - -#if 0 // 修正(kaiD) - leng = (drv->buf[7] << 8) + drv->buf[8]; - format = (drv->buf[9] >> 6); - TRACEOUT(("atapi_cmd_readtoc fmt=%d leng=%d", format, leng)); -#else -#if 0 - // こっちが正しいと思うんだけど…ドライバの違い? - time = (drv->buf[1] & 0x02) >> 0x01; - format = (drv->buf[2] & 0x0f); - leng = (drv->buf[6] << 8) + drv->buf[7]; -#else - time = (drv->buf[1] & 0x02) >> 0x01; - // format = (drv->buf[2] & 0x0f); - // if (format == 0) // "When Format in Byte 2 is zero, then Byte 9 is used" (SFF8020) - format = (drv->buf[9] >> 6); - leng = (drv->buf[7] << 8) + drv->buf[8]; -#endif - TRACEOUT(("ATAPI CMD: read TOC : time=%d fmt=%d leng=%d", time, format, leng)); - TRACEOUT(("\t[%02x %02x %02x %02x %02x %02x %02x %02x]", - drv->buf[0x00], drv->buf[0x01], drv->buf[0x02], drv->buf[0x03], drv->buf[0x04], drv->buf[0x05], drv->buf[0x06], drv->buf[0x07])); - TRACEOUT(("\t[%02x %02x %02x %02x %02x %02x %02x %02x]", - drv->buf[0x08], drv->buf[0x09], drv->buf[0x0a], drv->buf[0x0b], drv->buf[0x0c], drv->buf[0x0d], drv->buf[0x0e], drv->buf[0x0f])); -#endif - -#else /* SUPPORT_KAI_IMAGES */ - leng = (drv->buf[7] << 8) + drv->buf[8]; - format = (drv->buf[9] >> 6); - //TRACEOUT(("atapi_cmd_readtoc fmt=%d leng=%d", format, leng)); -#endif /* SUPPORT_KAI_IMAGES */ - strack = drv->buf[6]; - - switch (format) { - case 0: // track info - //datasize = (tracks * 8) + 10; - strack = MIN(MAX(1U, strack), (tracks+1)); // special case: 0 = 1sttrack, 0xaa = leadout - datasize = ((tracks - strack + 1U) * 8U) + 10; - drv->buf[0] = (UINT8)(datasize >> 8); - drv->buf[1] = (UINT8)(datasize >> 0); - drv->buf[2] = 1; - drv->buf[3] = (UINT8)tracks; - ptr = drv->buf + 4; - ////for (i=0; i<=tracks; i++) { - //i = drv->buf[6]; - //if (i > 0) --i; - //for (/* i=0 */; i<=tracks; i++) { - for (i=strack-1; i<=tracks; i++) { - ptr[0] = 0; -#ifdef SUPPORT_KAI_IMAGES - ptr[1] = trk[i].adr_ctl; - ptr[2] = trk[i].point; -#else - ptr[1] = trk[i].type; - ptr[2] = trk[i].track; -#endif - ptr[3] = 0; - //storemsf(ptr + 4, (UINT32)(trk[i].pos + 150), drv->damsfbcd); - if (time) - storemsf(ptr + 4, (UINT32)(trk[i].pos + 150), drv->damsfbcd); - else - storelba(ptr + 4, (UINT32)(trk[i].pos)); - ptr += 8; - } - //senddata(drv, (tracks * 8) + 12, leng); - senddata(drv, 2 + datasize, leng); - drv->media &= ~IDEIO_MEDIA_CHANGED; - break; - - case 1: // multi session - ZeroMemory(drv->buf, 12); - drv->buf[1] = 0x0a; - drv->buf[2] = 0x01; - drv->buf[3] = 0x01; - drv->buf[5] = 0x14; - drv->buf[6] = 0x01; - //drv->buf[10] = 0x02; - if (time) - storemsf(drv->buf + 8, (UINT32)(150), drv->damsfbcd); - else - storelba(drv->buf + 8, (UINT32)(0)); - senddata(drv, 12, leng); - drv->media &= ~IDEIO_MEDIA_CHANGED; - break; - - default: - // time = 1; // 0010b~0101b: MSF(TIME) Field "Ignored by Drive" (SCSI MMC) - senderror(drv); - break; - } -} - -static void atapi_cmd_playaudio_sub(IDEDRV drv, UINT32 pos, UINT32 leng) { - - ideio.daplaying |= 1 << (drv->sxsidrv & 3); - drv->daflag = 0x11; - drv->dacurpos = pos; - drv->dalength = leng; - drv->dabufrem = 0; - cmddone(drv); -} -// 0x45: Play Audio -static void atapi_cmd_playaudio(IDEDRV drv) { - UINT32 pos; - UINT32 leng; - - pos = (drv->buf[2] << 24) | (drv->buf[3] << 16) | (drv->buf[4] << 8) | drv->buf[5]; - leng = (drv->buf[7] << 16) | drv->buf[8]; - atapi_cmd_playaudio_sub(drv, pos, leng); -} - -// 0x47: Play Audio MSF -static void atapi_cmd_playaudiomsf(IDEDRV drv) { - - UINT32 pos; - UINT32 leng; - - int M, S, F; - if(drv->damsfbcd){ - M = BCD2HEX(drv->buf[3]); - S = BCD2HEX(drv->buf[4]); - F = BCD2HEX(drv->buf[5]); - pos = (((M * 60) + S) * 75) + F; - M = BCD2HEX(drv->buf[6]); - S = BCD2HEX(drv->buf[7]); - F = BCD2HEX(drv->buf[8]); - leng = (((M * 60) + S) * 75) + F; - }else{ - M = drv->buf[3]; - S = drv->buf[4]; - F = drv->buf[5]; - pos = (((M * 60) + S) * 75) + F; - M = drv->buf[6]; - S = drv->buf[7]; - F = drv->buf[8]; - leng = (((M * 60) + S) * 75) + F; - } - if (leng > pos) { - leng -= pos; - } - else { - leng = 0; - } - if (pos >= 150) { - pos -= 150; - } - else { - pos = 0; - } - atapi_cmd_playaudio_sub(drv, pos, leng); -} - -// 0x4B: PAUSE RESUME -static void atapi_cmd_pauseresume(IDEDRV drv) { - - if (drv->buf[8] & 1) { - // resume - if (drv->daflag == 0x12) { - ideio.daplaying |= 1 << (drv->sxsidrv & 3); - drv->daflag = 0x11; - } - } - else { - // pause - if (drv->daflag == 0x11) { - ideio.daplaying &= ~(1 << (drv->sxsidrv & 3)); - drv->daflag = 0x12; - } - } - cmddone(drv); -} - -// 0x2B: SEEK -static void atapi_cmd_seek(IDEDRV drv, UINT32 lba) -{ - CDTRK trk; - UINT tracks; - SXSIDEV sxsi; - - stop_daplay(drv); - - sxsi = sxsi_getptr(drv->sxsidrv); - trk = sxsicd_gettrk(sxsi, &tracks); - TRACEOUT(("atapicmd: seek LBA=%d NSEC=%d", lba, trk[tracks-1].pos + trk[tracks-1].sectors)); - if (lba < trk[tracks-1].pos + trk[tracks-1].sectors) { - drv->dacurpos = lba; - } - cmddone(drv); -} - -// 0xBD: MECHANISM STATUS -static void atapi_cmd_mechanismstatus(IDEDRV drv) { - - //SXSIDEV sxsi; - - //sxsi = sxsi_getptr(drv->sxsidrv); - //ZeroMemory(drv->buf, 12); - //drv->buf[0] = 0x00; - //drv->buf[1] = 0x00; - //drv->buf[2] = drv->cy & 0xff; // LBA(MSB) - //drv->buf[3] = (drv->cy >> 8) & 0xff; // LBA - //drv->buf[4] = drv->sn; // LBA(LSB) - //drv->buf[5] = 0x01; - //drv->buf[6] = 0x00; - //drv->buf[7] = 0x04; - //drv->buf[8] = (sxsi->flag & SXSIFLAG_READY) ? 0x80 : 0x00; // XXX: CD挿入状態とか入れてやるべき? - //drv->buf[9] = 0x00; - //drv->buf[10] = 0x00; - //drv->buf[11] = 0x00; - //senddata(drv, 12, 12); - sendabort(drv); -} - -void atapi_initialize(void) { -#if defined(NP2_WIN) - UINT32 dwID = 0; - //if(!pic_cs_initialized){ - // memset(&pic_cs, 0, sizeof(pic_cs)); - // InitializeCriticalSection(&pic_cs); - // pic_cs_initialized = 1; - //} - if(!atapi_thread_initialized){ - atapi_thread_initialized = 1; - atapi_thread_event_complete = CreateEvent(NULL, TRUE, TRUE, NULL); - atapi_thread_event_request = CreateEvent(NULL, FALSE, FALSE, NULL); - atapi_thread = (HANDLE)_beginthreadex(NULL, 0, atapi_dataread_threadfunc, NULL, 0, &dwID); - } -#else - // TODO: 非Windows用コードを書く -#endif -} - -void atapi_deinitialize(void) { -#if defined(NP2_WIN) - if(atapi_thread_initialized){ - atapi_thread_initialized = 0; - SetEvent(atapi_thread_event_request); - if(WaitForSingleObject(atapi_thread, 5000) == WAIT_TIMEOUT){ - TerminateThread(atapi_thread, 0); - } - CloseHandle(atapi_thread); - CloseHandle(atapi_thread_event_complete); - CloseHandle(atapi_thread_event_request); - atapi_thread = NULL; - } -#else - // TODO: 非Windows用コードを書く -#endif -} -#endif /* SUPPORT_IDEIO */ - +#include + +#if 0 +#undef TRACEOUT +static void trace_fmt_ex(const char* fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "¥n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#else +#define TRACEOUT(s) (void)(s) +#endif /* 1 */ + +// これ、scsicmdとどう統合するのよ? + +#if defined(SUPPORT_IDEIO) +#if defined(NP2_WIN) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#define YUIDEBUG + +#define SUPPORT_NECCDD + +#define HEX2BCD(hex) ( (((hex/10)%10)<<4)|((hex)%10) ) +#define BCD2HEX(bcd) ( (((bcd>>4)&0xf)*10)+((bcd)&0xf) ) + +#if defined(NP2_WIN) +static int atapi_thread_initialized = 0; +static HANDLE atapi_thread = NULL; +static IDEDRV atapi_thread_drv = NULL; +static HANDLE atapi_thread_event_request = NULL; +static HANDLE atapi_thread_event_complete = NULL; + // TODO: 非Windows用コードを書く +#endif + +// INQUIRY +static const UINT8 cdrom_inquiry[] = { +#ifdef YUIDEBUG + // うちのドライブの奴 NECCDは Product Level 3.00以上で modesense10のコードがちげー + 0x05, // CD-ROM + 0x80, // bit7: Removable Medium Bit, other: Reserved + 0x00, // version [7-6: ISO, ECMA: 5-3, 2-0: ANSI(00)] + 0x21, // 7-4: ATAPI version, 3-0: Response Data Format + 0x1f, // Additional length + 0x00,0x00,0x00, // Reserved + 'N', 'E', 'C', ' ', ' ', ' ', ' ', ' ', // Vendor ID + 'C', 'D', '-', 'R', 'O', 'M', ' ', 'D', // Product ID + 'R', 'I', 'V', 'E', ':', '9', '8', ' ', // Product ID + '1', '.', '0', ' ' // Product Revision Level +#else + 0x05, // CD-ROM + 0x80, // bit7: Removable Medium Bit, other: Reserved + 0x00, // version [7-6: ISO, ECMA: 5-3, 2-0: ANSI(00)] + 0x21, // 7-4: ATAPI version, 3-0: Response Data Format + 0x1f, // Additional length + 0x00,0x00,0x00, // Reserved + 'N', 'E', 'C', ' ', ' ', ' ', ' ', ' ', // Vendor ID + 'C', 'D', '-', 'R', 'O', 'M', ' ', 'D', // Product ID + 'R', 'I', 'V', 'E', ' ', ' ', ' ', ' ', // Product ID + '1', '.', '0', ' ' // Product Revision Level +#endif +}; + +static void senddata(IDEDRV drv, UINT size, UINT limit) { + + size = MIN(size, limit); + drv->sc = IDEINTR_IO; + drv->cy = size; + drv->status &= ~(IDESTAT_BSY|IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_CHK); + drv->status |= IDESTAT_DRQ|IDESTAT_DSC; // XXX: set Drive Seek Complete bit np21w ver0.86 rev29 + drv->error = 0; + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); + drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; + drv->bufdir = IDEDIR_IN; + drv->buftc = IDETC_TRANSFEREND; + drv->bufpos = 0; + drv->bufsize = size; + + if (!(drv->ctrl & IDECTRL_NIEN)) { + //TRACEOUT(("atapicmd: senddata()")); + ideio.bank[0] = ideio.bank[1] | 0x80; // ???? + pic_setirq(IDE_IRQ); + } +} + +static void cmddone(IDEDRV drv) { + + drv->sc = IDEINTR_IO|IDEINTR_CD; + drv->status &= ~(IDESTAT_BSY|IDESTAT_DRQ|IDESTAT_SERV|IDESTAT_CHK); + drv->status |= IDESTAT_DRDY|IDESTAT_DSC; // XXX: set Drive Seek Complete bit np21w ver0.86 rev13 + drv->error = 0; + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); + drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; + + if (!(drv->ctrl & IDECTRL_NIEN)) { + //TRACEOUT(("atapicmd: cmddone()")); + ideio.bank[0] = ideio.bank[1] | 0x80; // ???? + pic_setirq(IDE_IRQ); + } +} + +static void senderror(IDEDRV drv) { + + //drv->sc = IDEINTR_IO; + drv->sc = IDEINTR_IO | IDEINTR_CD; // set Command or Data bit np21w ver0.86 rev38 + drv->status &= ~(IDESTAT_BSY|IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_DRQ); // clear DRQ bit np21w ver0.86 rev38 + drv->status |= IDESTAT_CHK|IDESTAT_DSC; + + if (!(drv->ctrl & IDECTRL_NIEN)) { + //TRACEOUT(("atapicmd: senderror()")); + ideio.bank[0] = ideio.bank[1] | 0x80; // ???? + pic_setirq(IDE_IRQ); + } +} + +static void sendabort(IDEDRV drv) { + + drv->sk = ATAPI_SK_ABORTED_COMMAND; + drv->error = IDEERR_ABRT; + senderror(drv); +} + +static void stop_daplay(IDEDRV drv) +{ + + /* + "Play operation SHALL stopped" commands (INF-8090) + 0xA1 blank + 0x5B close track/session + 0x04 format unit + 0xA6 load/unload medium + 0x28 read(10) + 0xA8 read(12) + 0x58 repair rzone + 0x2B seek + 0x1B start/stop unit + 0x4E stop play/scan + 0x2F verify(10) + 0x2A write(10) + 0xAA write(12) + 0x2E write and verify(10) + + "Play operation SHALL NOT stopped" commands (INF-8090) + 0x46 get configuration + 0x4A get event/status notification + 0x12 inquiry + 0xBD mechanism status + 0x55 mode select + 0x5A mode sense + 0x1E prevent allow medium removal + 0x5C read buffer capacity + 0x25 read capacity + 0x03 request sense + 0xA7 set read ahead + 0x35 synchronize cache(10) + 0x00 test unit ready + */ + if (ideio.daplaying & (1 << (drv->sxsidrv & 3))) { + /* stop playing audio */ + ideio.daplaying &= ~(1 << (drv->sxsidrv & 3)); + drv->daflag = 0x13; + drv->dacurpos = 0; + drv->dalength = 0; + } +} + +// ----- ATAPI packet command + +static void atapi_cmd_start_stop_unit(IDEDRV drv); +static void atapi_cmd_prevent_allow_medium_removal(IDEDRV drv); +static void atapi_cmd_read_capacity(IDEDRV drv); +static void atapi_cmd_read(IDEDRV drv, UINT32 lba, UINT32 leng); +static void atapi_cmd_read_cd(IDEDRV drv, UINT32 lba, UINT32 leng); +static void atapi_cmd_read_cd_msf(IDEDRV drv); +static void atapi_cmd_mode_select(IDEDRV drv); +static void atapi_cmd_mode_sense(IDEDRV drv); +static void atapi_cmd_readsubch(IDEDRV drv); +static void atapi_cmd_readtoc(IDEDRV drv); +static void atapi_cmd_playaudio(IDEDRV drv); +static void atapi_cmd_playaudiomsf(IDEDRV drv); +static void atapi_cmd_pauseresume(IDEDRV drv); +static void atapi_cmd_seek(IDEDRV drv, UINT32 lba); +static void atapi_cmd_mechanismstatus(IDEDRV drv); + +#define MEDIA_CHANGE_WAIT 6 // Waitを入れないとWinNT系で正しくメディア交換出来ない +static int mediachangeflag = 0; + +extern REG8 cdchange_drv; +void cdchange_timeoutproc(NEVENTITEM item); + +void atapicmd_a0(IDEDRV drv) { + + UINT32 lba, leng; + UINT8 cmd; + + cmd = drv->buf[0]; + switch (cmd) { + case 0x00: // test unit ready + TRACEOUT(("atapicmd: test unit ready")); + if (!(drv->media & IDEIO_MEDIA_LOADED)) { + /* medium not present */ + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NOT_READY); + drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; + if(drv->sxsidrv==cdchange_drv && g_nevent.item[NEVENT_CDWAIT].clock > 0){ + if(mediachangeflag==MEDIA_CHANGE_WAIT){ + nevent_set(NEVENT_CDWAIT, 500, cdchange_timeoutproc, NEVENT_ABSOLUTE); // OS側がCDを催促しているようなので更に急いで交換 + }else if(mediachangeflag==0){ + nevent_setbyms(NEVENT_CDWAIT, 1000, cdchange_timeoutproc, NEVENT_ABSOLUTE); // OS側がCDが無いと認識したようなので急いで交換 + } + } + if(mediachangeflag < MEDIA_CHANGE_WAIT) mediachangeflag++; + //drv->status |= IDESTAT_ERR; + //drv->error = IDEERR_MCNG; + senderror(drv); + break; + } + if (drv->media & IDEIO_MEDIA_CHANGED) { + UINT8 olderror = drv->error; + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NOT_READY); + if(drv->damsfbcd){ + // NECCDD.SYS + //if(mediachangeflag){ + //if(mediachangeflag >= MEDIA_CHANGE_WAIT){ + drv->media &= ~IDEIO_MEDIA_CHANGED; + drv->asc = ATAPI_ASC_NOT_READY_TO_READY_TRANSITION; + //drv->error &= ~IDEERR_MCRQ; + //}else{ + // drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; + // mediachangeflag++; + // //drv->status |= IDESTAT_ERR; + // //drv->error |= IDEERR_MCRQ; + //} + }else{ + // for WinNT,2000 setup + //if(mediachangeflag >= MEDIA_CHANGE_WAIT){ + drv->media &= ~IDEIO_MEDIA_CHANGED; + drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; + //drv->asc = 0x0204; // LOGICAL DRIVE NOT READY - INITIALIZING COMMAND REQUIRED + //}else if(mediachangeflag >= 1){ + // drv->asc = 0x0204; // LOGICAL DRIVE NOT READY - INITIALIZING COMMAND REQUIRED + // mediachangeflag++; +// }else{ +// drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; +////#if defined(CPUCORE_IA32) +//// // Workaround for WinNT +//// if (CPU_STAT_PM && !CPU_STAT_VM86) { +// //mediachangeflag++; +//// } else +////#endif +//// { +// mediachangeflag = MEDIA_CHANGE_WAIT; +// //} +// } + } + senderror(drv); + break; + } + mediachangeflag = 0; + //if(drv->error & IDEERR_MCNG){ + // drv->status &= ~IDESTAT_ERR; + // drv->error &= ~IDEERR_MCNG; + //} + + cmddone(drv); + break; + + case 0x03: // request sense + TRACEOUT(("atapicmd: request sense")); + leng = drv->buf[4]; + ZeroMemory(drv->buf, 18); + drv->buf[0] = 0x70; + drv->buf[2] = drv->sk; + drv->buf[7] = 11; // length + drv->buf[12] = (UINT8)(drv->asc & 0xff); // Additional Sense Code + drv->buf[13] = (UINT8)((drv->asc>>8) & 0xff); // Additional Sense Code Qualifier (Optional) + senddata(drv, 18, leng); + break; + + case 0x12: // inquiry + TRACEOUT(("atapicmd: inquiry")); + leng = drv->buf[4]; + CopyMemory(drv->buf, cdrom_inquiry, sizeof(cdrom_inquiry)); + senddata(drv, sizeof(cdrom_inquiry), leng); + break; + + case 0x1b: // start stop unit + TRACEOUT(("atapicmd: start stop unit")); + atapi_cmd_start_stop_unit(drv); + break; + + case 0x1e: // prevent allow medium removal + TRACEOUT(("atapicmd: prevent allow medium removal")); + atapi_cmd_prevent_allow_medium_removal(drv); + break; + + case 0x25: // read capacity + TRACEOUT(("atapicmd: read capacity")); + atapi_cmd_read_capacity(drv); + break; + + case 0x28: // read(10) + //TRACEOUT(("atapicmd: read(10)")); + lba = (drv->buf[2] << 24) + (drv->buf[3] << 16) + (drv->buf[4] << 8) + drv->buf[5]; + leng = (drv->buf[7] << 8) + drv->buf[8]; + atapi_cmd_read(drv, lba, leng); + break; + + case 0xbe: // read cd + lba = (drv->buf[2] << 24) + (drv->buf[3] << 16) + (drv->buf[4] << 8) + drv->buf[5]; + leng = (drv->buf[6] << 16) + (drv->buf[7] << 8) + drv->buf[8]; + atapi_cmd_read_cd(drv, lba, leng); + break; + + case 0xb9: // read cd msf + atapi_cmd_read_cd_msf(drv); + break; + + case 0x2b: // Seek + lba = (drv->buf[2] << 24) + (drv->buf[3] << 16) + (drv->buf[4] << 8) + drv->buf[5]; + atapi_cmd_seek(drv, lba); + break; + + case 0x55: // mode select + TRACEOUT(("atapicmd: mode select")); + atapi_cmd_mode_select(drv); + break; + + case 0x5a: // mode sense(10) + TRACEOUT(("atapicmd: mode sense(10)")); + atapi_cmd_mode_sense(drv); + break; + + case 0x42: + TRACEOUT(("atapicmd: read sub channel")); + atapi_cmd_readsubch(drv); + break; + + case 0x43: // read TOC + TRACEOUT(("atapicmd: read TOC")); + atapi_cmd_readtoc(drv); + break; + + case 0x45: // Play Audio + TRACEOUT(("atapicmd: Play Audio")); + atapi_cmd_playaudio(drv); + break; + + case 0x46: // get config? + TRACEOUT(("atapicmd: get config")); + leng = drv->buf[7]|(drv->buf[8] << 8); + ZeroMemory(drv->buf, 512); + drv->buf[10] = 3; + drv->buf[6] = 8; + if(leng == 0) leng = 12; + senddata(drv, 512, leng); + break; + + case 0x47: // Play Audio MSF + TRACEOUT(("atapicmd: Play Audio MSF")); + atapi_cmd_playaudiomsf(drv); + break; + + case 0x4b: + TRACEOUT(("atapicmd: pause resume")); + atapi_cmd_pauseresume(drv); + break; + + case 0xbd: // mechanism status + TRACEOUT(("atapicmd: mechanism status")); + atapi_cmd_mechanismstatus(drv); + break; + + default: + TRACEOUT(("atapicmd: unknown command = %.2x", cmd)); + sendabort(drv); + break; + } +} + + +//-- command + +// 0x1b: START/STOP UNIT +#ifdef SUPPORT_PHYSICAL_CDDRV +void atapi_cmd_traycmd_eject_threadfunc(void* vdParam) { +#if defined(NP2_WIN) + HANDLE handle; + DWORD dwRet = 0; + wchar_t wpath[MAX_PATH]; + codecnv_utf8toucs2(wpath, MAX_PATH, np2cfg.idecd[(int)vdParam], -1); + handle = CreateFileW(wpath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if(handle != INVALID_HANDLE_VALUE){ + if(DeviceIoControl(handle, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &dwRet, 0)){ + if(DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &dwRet, 0)){ + DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, &dwRet, 0); + } + } + CloseHandle(handle); + } +#else + // TODO: Windows以外のコードを書く +#endif +} +void atapi_cmd_traycmd_close_threadfunc(void* vdParam) { +#if defined(NP2_WIN) + HANDLE handle; + DWORD dwRet = 0; + wchar_t wpath[MAX_PATH]; + codecnv_utf8toucs2(wpath, MAX_PATH, np2cfg.idecd[(int)vdParam], -1); + handle = CreateFileW(wpath, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + if(handle != INVALID_HANDLE_VALUE){ + DeviceIoControl(handle, IOCTL_STORAGE_LOAD_MEDIA, 0, 0, 0, 0, &dwRet, 0); + CloseHandle(handle); + } +#else + // TODO: Windows以外のコードを書く +#endif +} +#endif +static void atapi_cmd_start_stop_unit(IDEDRV drv) { + + UINT power; + SXSIDEV sxsi; + + sxsi = sxsi_getptr(drv->sxsidrv); + + stop_daplay(drv); + + power = (drv->buf[4] >> 4); + if (power != 0) { + /* power control is not supported */ + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); + drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; + goto send_error; + } + switch(drv->buf[4] & 3){ + case 0: // Stop the Disc + break; + case 1: // Start the Disc and read the TOC + if (!(drv->media & IDEIO_MEDIA_LOADED)) { + atapi_cmd_readtoc(drv); + return; + } + break; + case 2: // Eject the Disc if possible +#ifdef SUPPORT_PHYSICAL_CDDRV + if(np2cfg.allowcdtraycmd && _tcsnicmp(np2cfg.idecd[sxsi->drv], OEMTEXT("\\\\.\\"), 4)==0){ +#if defined(NP2_WIN) + _beginthread(atapi_cmd_traycmd_eject_threadfunc, 0, (void*)sxsi->drv); +#else + // TODO: Windows以外のコードを書く +#endif + }else +#endif + { + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); + drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; + goto send_error; + } + break; + case 3: // Load the Disc (Close Tray) +#ifdef SUPPORT_PHYSICAL_CDDRV + if(np2cfg.allowcdtraycmd && _tcsnicmp(np2cfg.idecd[sxsi->drv], OEMTEXT("\\\\.\\"), 4)==0){ +#if defined(NP2_WIN) + _beginthread(atapi_cmd_traycmd_close_threadfunc, 0, (void*)sxsi->drv); +#else + // TODO: Windows以外のコードを書く +#endif + }else +#endif + { + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); + drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; + goto send_error; + } + break; + } + if (!(drv->media & IDEIO_MEDIA_LOADED)) { + /* medium not present */ + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NOT_READY); + drv->asc = ATAPI_ASC_MEDIUM_NOT_PRESENT; + goto send_error; + } + + /* XXX play/read TOC, stop */ + + cmddone(drv); + + return; + +send_error: + senderror(drv); +} + +// 0x1e: PREVENT/ALLOW MEDIUM REMOVAL +static void atapi_cmd_prevent_allow_medium_removal(IDEDRV drv) { + + /* XXX */ + cmddone(drv); +} + +// 0x25: READ CAPACITY +static void atapi_cmd_read_capacity(IDEDRV drv) { + + /* XXX */ + UINT32 blklen = 2048; // drv->secsize; + UINT8 *b = drv->buf; + SXSIDEV sxsi; + UINT32 totals; + + sxsi = sxsi_getptr(drv->sxsidrv); + if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY) && drv->device != IDETYPE_CDROM)) { + senderror(drv); + return; + } + totals = (UINT32)sxsi->totals; + + b[0] = (UINT8)(totals >> 24); + b[1] = (UINT8)(totals >> 16); + b[2] = (UINT8)(totals >> 8); + b[3] = (UINT8)(totals); + b[4] = (UINT8)(blklen >> 24); + b[5] = (UINT8)(blklen >> 16); + b[6] = (UINT8)(blklen >> 8); + b[7] = (UINT8)(blklen); + + senddata(drv, 8, 8); + + //cmddone(drv); +} + +// 0x28: READ(10) +#if defined(NP2_WIN) +static int atapi_dataread_error = -1; +void atapi_dataread_threadfunc_part(IDEDRV drv) { + + SXSIDEV sxsi; + sxsi = sxsi_getptr(drv->sxsidrv); + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; + + if (sxsi_read(drv->sxsidrv, drv->sector, drv->buf, 2048) != 0) { + atapi_dataread_error = 1; + return; + } + + // EDC/ECC check + if(np2cfg.usecdecc && (sxsi->cdflag_ecc & CD_ECC_BITMASK)==CD_ECC_ERROR){ + atapi_dataread_error = 2; + return; + } + + atapi_dataread_error = 0; +} +void atapi_dataread_asyncwait(int wait) { + if(atapi_dataread_error!=-1 && atapi_thread_drv && (!np2cfg.useasynccd || !atapi_thread || WaitForSingleObject(atapi_thread_event_complete, wait) == WAIT_OBJECT_0)){ + IDEDRV drv = atapi_thread_drv; + SXSIDEV sxsi; + sxsi = sxsi_getptr(drv->sxsidrv); + drv->status &= ~(IDESTAT_DRQ); + + switch(atapi_dataread_error){ + case 1: + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); + drv->asc = 0x21; + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; + senderror(drv); + TRACEOUT(("atapicmd: read error at sector %d", drv->sector)); + break; + case 2: + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_MEDIUM_ERROR); + drv->sk = 0x03; + drv->asc = 0x11; + drv->status |= IDESTAT_ERR; + drv->error |= IDEERR_UNC; + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; + senderror(drv); + TRACEOUT(("atapicmd: EDC/ECC error detected at sector %d", drv->sector)); + break; + case 0: + drv->sector++; + drv->nsectors--; + + drv->sc = IDEINTR_IO; + drv->cy = 2048; + drv->status &= ~(IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_CHK); + drv->status |= IDESTAT_DRQ; + drv->error = 0; + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); + drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; + drv->bufdir = IDEDIR_IN; + drv->buftc = (drv->nsectors)?IDETC_ATAPIREAD:IDETC_TRANSFEREND; + drv->bufpos = 0; + drv->bufsize = 2048; + + if(np2cfg.usecdecc && (sxsi->cdflag_ecc & CD_ECC_BITMASK)==CD_ECC_RECOVERED){ + drv->status |= IDESTAT_CORR; + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_RECOVERED_ERROR); + drv->asc = 0x18; + } + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; + + drv->status &= ~(IDESTAT_BSY); // 念のため直前で解除 + if (!(drv->ctrl & IDECTRL_NIEN)) { + //TRACEOUT(("atapicmd: senddata()")); + ideio.bank[0] = ideio.bank[1] | 0x80; // ???? + pic_setirq(IDE_IRQ); + } + + break; + } + atapi_dataread_error = -1; + } +} +unsigned int __stdcall atapi_dataread_threadfunc(void* vdParam) { + IDEDRV drv = NULL; + + SetEvent(atapi_thread_event_complete); + while(WaitForSingleObject(atapi_thread_event_request, INFINITE) == WAIT_OBJECT_0){ + if(!atapi_thread_initialized) break; + drv = atapi_thread_drv; + atapi_dataread_threadfunc_part(drv); + SetEvent(atapi_thread_event_complete); + } + SetEvent(atapi_thread_event_complete); + _endthreadex(0); + return 0; + +} +void atapi_dataread(IDEDRV drv) { + + if(drv->status & IDESTAT_BSY) { + return; + } + + // エラー処理目茶苦茶〜 + if (drv->nsectors == 0) { + sendabort(drv); + return; + } + + drv->status |= IDESTAT_BSY; + + if(np2cfg.useasynccd){ + if(atapi_thread){ + atapi_dataread_asyncwait(INFINITE); + ResetEvent(atapi_thread_event_complete); + atapi_dataread_error = -1; + atapi_thread_drv = drv; + SetEvent(atapi_thread_event_request); + atapi_dataread_asyncwait(2); + }else{ + atapi_dataread_error = -1; + atapi_thread_drv = drv; + atapi_dataread_threadfunc_part(drv); + atapi_dataread_asyncwait(0); + } + }else{ + if(atapi_thread){ + atapi_dataread_asyncwait(INFINITE); + } + atapi_dataread_error = -1; + atapi_thread_drv = drv; + atapi_dataread_threadfunc_part(drv); + atapi_dataread_asyncwait(0); + } +} +#else +void atapi_dataread(IDEDRV drv) { + + SXSIDEV sxsi; + sxsi = sxsi_getptr(drv->sxsidrv); + + // エラー処理目茶苦茶〜 + if (drv->nsectors == 0) { + sendabort(drv); + return; + } + + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; + + if (sxsi_read(drv->sxsidrv, drv->sector, drv->buf, 2048) != 0) { + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); + drv->asc = 0x21; + senderror(drv); + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; + return; + } + + // EDC/ECC check + if(np2cfg.usecdecc && (sxsi->cdflag_ecc & CD_ECC_BITMASK)==CD_ECC_ERROR){ + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_MEDIUM_ERROR); + drv->sk = 0x03; + drv->asc = 0x11; + drv->status |= IDESTAT_ERR; + drv->error |= IDEERR_UNC; + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; + senderror(drv); + return; + } + + drv->sector++; + drv->nsectors--; + + drv->sc = IDEINTR_IO; + drv->cy = 2048; + drv->status &= ~(IDESTAT_BSY|IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_CHK); + drv->status |= IDESTAT_DRQ; + drv->error = 0; + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); + drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; + drv->bufdir = IDEDIR_IN; + drv->buftc = (drv->nsectors)?IDETC_ATAPIREAD:IDETC_TRANSFEREND; + drv->bufpos = 0; + drv->bufsize = 2048; + + if(np2cfg.usecdecc && (sxsi->cdflag_ecc & CD_ECC_BITMASK)==CD_ECC_RECOVERED){ + drv->status |= IDESTAT_CORR; + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_RECOVERED_ERROR); + drv->asc = 0x18; + } + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; + + if (!(drv->ctrl & IDECTRL_NIEN)) { + //TRACEOUT(("atapicmd: senddata()")); + ideio.bank[0] = ideio.bank[1] | 0x80; // ???? + pic_setirq(IDE_IRQ); + } +} +#endif + +void atapi_dataread_end(IDEDRV drv) { + SXSIDEV sxsi; + sxsi = sxsi_getptr(drv->sxsidrv); + + drv->sector++; + drv->nsectors--; + + drv->sc = IDEINTR_IO; + drv->cy = 2048; + drv->status &= ~(IDESTAT_DMRD|IDESTAT_SERV|IDESTAT_CHK); + drv->status |= IDESTAT_DRQ; + drv->error = 0; + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_NO_SENSE); + drv->asc = ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION; + drv->bufdir = IDEDIR_IN; + drv->buftc = (drv->nsectors)?IDETC_ATAPIREAD:IDETC_TRANSFEREND; + drv->bufpos = 0; + drv->bufsize = 2048; + + if(np2cfg.usecdecc && (sxsi->cdflag_ecc & CD_ECC_BITMASK)==CD_ECC_RECOVERED){ + drv->status |= IDESTAT_CORR; + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_RECOVERED_ERROR); + drv->asc = 0x18; + } + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; + + drv->status &= ~(IDESTAT_BSY); // 念のため直前で解除 + if (!(drv->ctrl & IDECTRL_NIEN)) { + //TRACEOUT(("atapicmd: senddata()")); + ideio.bank[0] = ideio.bank[1] | 0x80; // ???? + pic_setirq(IDE_IRQ); + } +#if defined(NP2_WIN) + atapi_dataread_error = -1; +#endif +} +void atapi_dataread_errorend(IDEDRV drv) { + SXSIDEV sxsi; + sxsi = sxsi_getptr(drv->sxsidrv); + + drv->status &= ~(IDESTAT_DRQ); + + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); + drv->asc = 0x21; + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; + senderror(drv); + TRACEOUT(("atapicmd: read error at sector %d", drv->sector)); +#if defined(NP2_WIN) + atapi_dataread_error = -1; +#endif +} + +static void atapi_cmd_read(IDEDRV drv, UINT32 lba, UINT32 nsec) { + + drv->sector = lba; + drv->nsectors = nsec; + atapi_dataread(drv); +} +static void atapi_cmd_read_cd(IDEDRV drv, UINT32 lba, UINT32 nsec) { + + int i; + SXSIDEV sxsi; + CDTRK trk; + UINT tracks; + UINT8 *bufptr; + UINT bufsize; + + UINT8 rawdata[2352]; + + UINT8 hassync; + UINT8 hashead; + UINT8 hassubhead; + UINT8 hasdata; + UINT8 hasedcecc; + + UINT16 isCDDA = 1; + +#if defined(NP2_WIN) + atapi_thread_drv = drv; +#endif + sxsi = sxsi_getptr(drv->sxsidrv); + + hassync = (drv->buf[9] & 0x80) ? 1 : 0; + hassubhead = (drv->buf[9] & 0x40) ? 1 : 0; + hashead = (drv->buf[9] & 0x20) ? 1 : 0; + hasdata = (drv->buf[9] & 0x10) ? 1 : 0; + hasedcecc = (drv->buf[9] & 0x08) ? 1 : 0; + + drv->sector = lba; + drv->nsectors = nsec; + + // エラー処理目茶苦茶〜 + if (drv->nsectors == 0) { + cmddone(drv); + return; + } + + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_NOERROR; + + trk = sxsicd_gettrk(sxsi, &tracks); + for (i = 0; i < tracks; i++) { + if (trk[i].str_sec <= (UINT32)drv->sector && (UINT32)drv->sector <= trk[i].end_sec) { + isCDDA = (trk[i].adr_ctl == TRACKTYPE_AUDIO); + break; + } + } + + if(isCDDA){ + // Audio + if (sxsicd_readraw(sxsi, drv->sector, drv->buf) != SUCCESS) { + atapi_dataread_errorend(0); + return; + } + bufsize = 2352; + }else{ + // 条件がかなり複雑。 + // ATAPI CD-ROM Specificationの + // Table 99 - Number of Bytes Returned Based on Data Selection Field + // を参照 + + // MODE1決め打ち + if (sxsicd_readraw(sxsi, drv->sector, rawdata) != SUCCESS) { + atapi_dataread_errorend(0); + return; + } + + bufsize = 0; + bufptr = drv->buf; + if (hassync){ + if(hashead){ + // Headerがいるときだけ有効 + memcpy(bufptr, rawdata, 12); + bufptr += 12; + bufsize += 12; + } + } + if (hashead){ + memcpy(bufptr, rawdata + 12, 4); + bufptr += 4; + bufsize += 4; + } + if (hassubhead){ + // MODE1(本来ないが、User Dataが無いときだけ特例で書く) + if(!hasdata){ + memset(bufptr, 0, 8); + bufptr += 8; + bufsize += 8; + + } + + //// XA + //memcpy(bufptr, rawdata + 12 + 4, 8); + + //bufptr += 8; + //bufsize += 8; + } + if (hasdata){ + memcpy(bufptr, rawdata + 12 + 4 + 8, 2048); + bufptr += 2048; + bufsize += 2048; + } + if (hasedcecc){ + //// MODE1 + //memcpy(bufptr, rawdata + 12 + 4 + 8 + 2048, 4); + //memcpy(bufptr + 4, rawdata + 12 + 4 + 8 + 2048 + 12, 276); + + ////// XA + ////memcpy(bufptr, rawdata + 12 + 4 + 8 + 2048, 280); + + //bufptr += 280; + //bufsize += 280; + + memcpy(bufptr, rawdata + 12 + 4 + 8 + 2048, 288); + bufptr += 288; + bufsize += 288; + } + } + + atapi_dataread_end(drv); + + drv->bufsize = bufsize; + drv->cy = bufsize; +} + +static void atapi_cmd_read_cd_msf(IDEDRV drv) { + + UINT32 pos; + UINT32 leng; + + int M, S, F; + if(drv->damsfbcd){ + M = BCD2HEX(drv->buf[3]); + S = BCD2HEX(drv->buf[4]); + F = BCD2HEX(drv->buf[5]); + pos = (((M * 60) + S) * 75) + F; + M = BCD2HEX(drv->buf[6]); + S = BCD2HEX(drv->buf[7]); + F = BCD2HEX(drv->buf[8]); + leng = (((M * 60) + S) * 75) + F; + }else{ + M = drv->buf[3]; + S = drv->buf[4]; + F = drv->buf[5]; + pos = (((M * 60) + S) * 75) + F; + M = drv->buf[6]; + S = drv->buf[7]; + F = drv->buf[8]; + leng = (((M * 60) + S) * 75) + F; + } + if (leng > pos) { + leng -= pos; + } + else { + leng = 0; + } + if (pos >= 150) { + pos -= 150; + } + else { + pos = 0; + } + atapi_cmd_read_cd(drv, pos, leng); +} + +// -- MODE SELECT/SENSE +#define PC_01_SIZE 8 +#define PC_0D_SIZE 8 +#define PC_0E_SIZE 16 +#define PC_2A_SIZE 20 + +// page code changeable value +static const UINT8 chgval_pagecode_01[PC_01_SIZE] = { + 0x00, 0x00, 0x37, 0xff, 0x00, 0x00, 0x00, 0x00, +}; +static const UINT8 chgval_pagecode_0d[PC_0D_SIZE] = { + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, +}; +static const UINT8 chgval_pagecode_0e[PC_0E_SIZE] = { + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, +}; +static const UINT8 chgval_pagecode_2a[PC_2A_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xc2, 0x00, 0x02, 0x00, 0x00, 0x02, 0xc2, + 0x00, 0x00, 0x00, 0x00, +}; + +// page code default value +static const UINT8 defval_pagecode_01[PC_01_SIZE] = { + 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const UINT8 defval_pagecode_0d[PC_0D_SIZE] = { + 0x0d, 0x06, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x4b, +}; +static const UINT8 defval_pagecode_0e[PC_0E_SIZE] = { + 0x0e, 0x0e, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, + 0x01, 0xff, 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, +}; + +static const UINT8 defval_pagecode_2a[PC_2A_SIZE] = { +//#ifdef YUIDEBUG +// 0x2a, 0x12, 0x00, 0x00, 0x71, 0x65, 0x89, 0x07, +// 0x02, 0xc2, 0x00, 0xff, 0x00, 0x80, 0x02, 0xc2, +// 0x00, 0x00, 0x00, 0x00, +//#else + 0x2a, 0x12, 0x00, 0x00, 0x71, 0x65, 0x29, 0x07, + 0x02, 0xc2, 0x00, 0xff, 0x00, 0x80, 0x02, 0xc2, + 0x00, 0x00, 0x00, 0x00, +//#endif +}; + +#if defined(SUPPORT_NECCDD) +#define PC_0F_SIZE 16 + +// "NEC CD-ROM" unique? (for neccdd.sys) +// It's just a stub, all values are unknown... +static const UINT8 chgval_pagecode_0f[PC_0F_SIZE] = { + 0x0f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const UINT8 defval_pagecode_0f[PC_0F_SIZE] = { + 0x0f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +#endif + + +// 0x55: MODE SELECT +static void atapi_cmd_mode_select(IDEDRV drv) { + + UINT leng; + + leng = (drv->buf[7] << 8) + drv->buf[8]; + TRACEOUT(("atapi_cmd_mode_select: leng=%u SP=%u", leng, drv->buf[1] & 1)); + + if (drv->buf[1] & 1) { + /* Saved Page is not supported */ + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); + drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; + senderror(drv); + return; + } + +#if 1 + cmddone(drv); /* workaround */ +#else + sendabort(drv); /* XXX */ +#endif + +} + +// 0x5a: MODE SENSE +static void atapi_cmd_mode_sense(IDEDRV drv) { + + const UINT8 *ptr; + UINT leng; + UINT cnt; + UINT8 pctrl, pcode; + + leng = (drv->buf[7] << 8) + drv->buf[8]; + pctrl = ((drv->buf[2] >> 6) & 3) & ~0x2; // 0: current, 1: changeable, 2: default + pcode = drv->buf[2] & 0x3f; + + if (pctrl == 3) { + /* Saved Page is not supported */ + //TRACEOUT(("Saved Page is not supported")); + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); + drv->asc = ATAPI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED; + senderror(drv); + return; + } + + /* Mode Parameter Header */ + ZeroMemory(drv->buf, 8); + if (!(drv->media & IDEIO_MEDIA_LOADED)) { + drv->buf[2] = 0x70; // Door closed, no disc present + } + else if ((drv->media & (IDEIO_MEDIA_COMBINE)) == IDEIO_MEDIA_AUDIO) { + drv->buf[2] = 0x02; // 120mm CD-ROM audio only + } + else if ((drv->media & (IDEIO_MEDIA_COMBINE)) == IDEIO_MEDIA_COMBINE) { + drv->buf[2] = 0x03; // 120mm CD-ROM data & audio combined + } + else { + drv->buf[2] = 0x01; // 120mm CD-ROM data only + } + cnt = 8; + if (cnt > leng) { + goto length_exceeded; + } + + /* Mode Page */ + //TRACEOUT(("pcode = %.2x", pcode)); + switch (pcode) { +#if defined(SUPPORT_NECCDD) + case 0x0f: + { + // some NEC CD-ROM specific support (required for neccdd.sys) + const UINT8 *p2a; + UINT8 *p = drv->buf + cnt; + if (pctrl == 1) { + p2a = chgval_pagecode_2a; + ptr = chgval_pagecode_0f; + } + else { + p2a = defval_pagecode_2a; + ptr = defval_pagecode_0f; + } + CopyMemory(p, ptr, MIN((leng - cnt), PC_0F_SIZE)); + p[4] = (p2a[4] & 1); // byte04 bit0 = Audioplay supported? + p[4] |= ((p2a[6] & 2) << 6); // byte04 bit7 = lock state? + p[4] |= ((p2a[5] & 4) << 2); // byte04 bit4 = R-W supported? + p[5] = ((p2a[7] & 3) << 3); // byte05 bit4,3 = audio manipulation? + // note: When byte04 bit1 is set, neccdd.sys will set bit10 in device status call. + // (bit10 is "reserved" in the Microsoft's reference) + // for drive specific applications? or simply a bug?) + } + cnt += PC_0F_SIZE; + if (cnt > leng) { + goto length_exceeded; + } + drv->damsfbcd = 1; // XXX: NEC CD-ROMコマンドを飛ばしてきたらBCDモードにする・・・(暫定neccdd.sys判定) + break; +#endif + case 0x3f: + /*FALLTHROUGH*/ + + case 0x01: /* Read Error Recovery Parameters Page */ + if (pctrl == 1) { + ptr = chgval_pagecode_01; + } + else { + ptr = defval_pagecode_01; + } + CopyMemory(drv->buf + cnt, ptr, MIN((leng - cnt), PC_01_SIZE)); + cnt += PC_01_SIZE; + if (cnt > leng) { + goto length_exceeded; + } + if (pcode == 0x01) { + break; + } + /*FALLTHROUGH*/ + + case 0x0d: /* CD-ROM Device Parameters Page */ + if (pctrl == 1) { + ptr = chgval_pagecode_0d; + } + else { + ptr = defval_pagecode_0d; + } + CopyMemory(drv->buf + cnt, ptr, MIN((leng - cnt), PC_0D_SIZE)); + cnt += PC_0D_SIZE; + if (cnt > leng) { + goto length_exceeded; + } + if (pcode == 0x0d) { + break; + } + /*FALLTHROUGH*/ + + case 0x0e: /* CD-ROM Audio Control Paramater Page */ + if (pctrl == 1) { + ptr = chgval_pagecode_0e; + } + else { + ptr = defval_pagecode_0e; + } + CopyMemory(drv->buf + cnt, ptr, MIN((leng - cnt), PC_0E_SIZE)); + cnt += PC_0E_SIZE; + if (cnt > leng) { + goto length_exceeded; + } + if (pcode == 0x0e) { + break; + } + //np2cfg.davolume = drv->buf[11]; + /*FALLTHROUGH*/ + + case 0x2a: /* CD-ROM Capabilities & Mechanical Status Page */ + if (pctrl == 1) { + ptr = chgval_pagecode_2a; + } + else { + ptr = defval_pagecode_2a; + } + CopyMemory(drv->buf + cnt, ptr, MIN((leng - cnt), PC_2A_SIZE)); + cnt += PC_2A_SIZE; + if (cnt > leng) { + goto length_exceeded; + } +#if 0 + /*FALLTHROUGH*/ + + case 0x00: +#endif + break; + + default: + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); + drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; + senderror(drv); + return; + } + + drv->buf[0] = (UINT8)((cnt - 2) >> 8); + drv->buf[1] = (UINT8)(cnt - 2); + senddata(drv, cnt, leng); + return; + +length_exceeded: + if (cnt >= 65536) { + ATAPI_SET_SENSE_KEY(drv, ATAPI_SK_ILLEGAL_REQUEST); + drv->asc = ATAPI_ASC_INVALID_FIELD_IN_CDB; + senderror(drv); + return; + } + + drv->buf[0] = (UINT8)((leng - 2) >> 8); + drv->buf[1] = (UINT8)(leng - 2); + senddata(drv, cnt, leng); +} + + +// ---- Audio + +static void storemsf(UINT8 *ptr, UINT32 pos, int isBCD) { + + UINT f; + UINT m; + + f = pos % 75; + pos = pos / 75; + m = pos % 60; + pos = pos / 60; + ptr[0] = 0; + if(isBCD){ + if (pos > 99) { + ptr[1] = 0xff; + ptr[2] = 0x59; + ptr[3] = 0x74; + return; + } + ptr[1] = (UINT8)HEX2BCD(pos); + ptr[2] = (UINT8)HEX2BCD(m); + ptr[3] = (UINT8)HEX2BCD(f); + }else{ + if (pos > 0xff) { + pos = 0xff; + m = 59; + f = 74; + } + ptr[1] = (UINT8)pos; + ptr[2] = (UINT8)m; + ptr[3] = (UINT8)f; + } +} + +static void storelba(UINT8 *ptr, UINT32 pos) { + + ptr[0] = (UINT8)(pos >> 24); + ptr[1] = (UINT8)(pos >> 16); + ptr[2] = (UINT8)(pos >> 8); + ptr[3] = (UINT8)(pos); +} + +// 0x42: READ SUB CHANNEL +static void atapi_cmd_readsubch(IDEDRV drv) { + + SXSIDEV sxsi; + UINT subq; + UINT cmd; + UINT leng; + CDTRK trk; + UINT tracks; + UINT r; + UINT32 pos; + + sxsi = sxsi_getptr(drv->sxsidrv); + if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) || + (!(sxsi->flag & SXSIFLAG_READY))) { + senderror(drv); + return; + } + trk = sxsicd_gettrk(sxsi, &tracks); + leng = (drv->buf[7] << 8) + drv->buf[8]; + subq = drv->buf[2] & 0x40; + cmd = drv->buf[3]; + + drv->buf[0] = 0; + drv->buf[1] = (UINT8)drv->daflag; + drv->buf[2] = 0; + drv->buf[3] = 0; + if (!subq) { + senddata(drv, 4, leng); + return; + } + switch(cmd) { + case 0x01: // CD-ROM current pos + ZeroMemory(drv->buf + 4, 12); + drv->buf[3] = 0x12; + drv->buf[4] = 0x01; + if (drv->daflag != 0x15) { + pos = drv->dacurpos; + if ((drv->daflag == 0x12) || (drv->daflag == 0x13)) { + pos += (rand() & 7); + } + r = tracks; + while(r) { + r--; + if (trk[r].pos <= pos) { + break; + } + } +#ifdef SUPPORT_KAI_IMAGES + drv->buf[5] = trk[r].adr_ctl; + drv->buf[6] = trk[r].point; +#else + drv->buf[5] = trk[r].type; + drv->buf[6] = trk[r].track; +#endif + drv->buf[7] = 1; + + storemsf(drv->buf + 8, pos + 150, drv->damsfbcd); + storemsf(drv->buf + 12, (UINT32)(pos - trk[r].pos), drv->damsfbcd); + } + senddata(drv, 16, leng); + break; + + default: + senderror(drv); + break; + } +} + +// 0x43: READ TOC +static void atapi_cmd_readtoc(IDEDRV drv) { + + SXSIDEV sxsi; + UINT leng; + UINT format; + CDTRK trk; + UINT tracks; + UINT datasize; + UINT8 *ptr; + UINT i; +#ifdef SUPPORT_KAI_IMAGES + UINT8 time; // 追加(kaiD) +#endif + UINT8 strack; + + sxsi = sxsi_getptr(drv->sxsidrv); + if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) || + (!(sxsi->flag & SXSIFLAG_READY))) { + senderror(drv); + return; + } + trk = sxsicd_gettrk(sxsi, &tracks); + +#ifdef SUPPORT_KAI_IMAGES + +#if 0 // 修正(kaiD) + leng = (drv->buf[7] << 8) + drv->buf[8]; + format = (drv->buf[9] >> 6); + TRACEOUT(("atapi_cmd_readtoc fmt=%d leng=%d", format, leng)); +#else +#if 0 + // こっちが正しいと思うんだけど…ドライバの違い? + time = (drv->buf[1] & 0x02) >> 0x01; + format = (drv->buf[2] & 0x0f); + leng = (drv->buf[6] << 8) + drv->buf[7]; +#else + time = (drv->buf[1] & 0x02) >> 0x01; + // format = (drv->buf[2] & 0x0f); + // if (format == 0) // "When Format in Byte 2 is zero, then Byte 9 is used" (SFF8020) + format = (drv->buf[9] >> 6); + leng = (drv->buf[7] << 8) + drv->buf[8]; +#endif + TRACEOUT(("ATAPI CMD: read TOC : time=%d fmt=%d leng=%d", time, format, leng)); + TRACEOUT(("\t[%02x %02x %02x %02x %02x %02x %02x %02x]", + drv->buf[0x00], drv->buf[0x01], drv->buf[0x02], drv->buf[0x03], drv->buf[0x04], drv->buf[0x05], drv->buf[0x06], drv->buf[0x07])); + TRACEOUT(("\t[%02x %02x %02x %02x %02x %02x %02x %02x]", + drv->buf[0x08], drv->buf[0x09], drv->buf[0x0a], drv->buf[0x0b], drv->buf[0x0c], drv->buf[0x0d], drv->buf[0x0e], drv->buf[0x0f])); +#endif + +#else /* SUPPORT_KAI_IMAGES */ + leng = (drv->buf[7] << 8) + drv->buf[8]; + format = (drv->buf[9] >> 6); + //TRACEOUT(("atapi_cmd_readtoc fmt=%d leng=%d", format, leng)); +#endif /* SUPPORT_KAI_IMAGES */ + strack = drv->buf[6]; + + switch (format) { + case 0: // track info + //datasize = (tracks * 8) + 10; + strack = MIN(MAX(1U, strack), (tracks+1)); // special case: 0 = 1sttrack, 0xaa = leadout + datasize = ((tracks - strack + 1U) * 8U) + 10; + drv->buf[0] = (UINT8)(datasize >> 8); + drv->buf[1] = (UINT8)(datasize >> 0); + drv->buf[2] = 1; + drv->buf[3] = (UINT8)tracks; + ptr = drv->buf + 4; + ////for (i=0; i<=tracks; i++) { + //i = drv->buf[6]; + //if (i > 0) --i; + //for (/* i=0 */; i<=tracks; i++) { + for (i=strack-1; i<=tracks; i++) { + ptr[0] = 0; +#ifdef SUPPORT_KAI_IMAGES + ptr[1] = trk[i].adr_ctl; + ptr[2] = trk[i].point; +#else + ptr[1] = trk[i].type; + ptr[2] = trk[i].track; +#endif + ptr[3] = 0; + //storemsf(ptr + 4, (UINT32)(trk[i].pos + 150), drv->damsfbcd); + if (time) + storemsf(ptr + 4, (UINT32)(trk[i].pos + 150), drv->damsfbcd); + else + storelba(ptr + 4, (UINT32)(trk[i].pos)); + ptr += 8; + } + //senddata(drv, (tracks * 8) + 12, leng); + senddata(drv, 2 + datasize, leng); + drv->media &= ~IDEIO_MEDIA_CHANGED; + break; + + case 1: // multi session + ZeroMemory(drv->buf, 12); + drv->buf[1] = 0x0a; + drv->buf[2] = 0x01; + drv->buf[3] = 0x01; + drv->buf[5] = 0x14; + drv->buf[6] = 0x01; + //drv->buf[10] = 0x02; + if (time) + storemsf(drv->buf + 8, (UINT32)(150), drv->damsfbcd); + else + storelba(drv->buf + 8, (UINT32)(0)); + senddata(drv, 12, leng); + drv->media &= ~IDEIO_MEDIA_CHANGED; + break; + + default: + // time = 1; // 0010b~0101b: MSF(TIME) Field "Ignored by Drive" (SCSI MMC) + senderror(drv); + break; + } +} + +static void atapi_cmd_playaudio_sub(IDEDRV drv, UINT32 pos, UINT32 leng) { + + ideio.daplaying |= 1 << (drv->sxsidrv & 3); + drv->daflag = 0x11; + drv->dacurpos = pos; + drv->dalength = leng; + drv->dabufrem = 0; + cmddone(drv); +} +// 0x45: Play Audio +static void atapi_cmd_playaudio(IDEDRV drv) { + UINT32 pos; + UINT32 leng; + + pos = (drv->buf[2] << 24) | (drv->buf[3] << 16) | (drv->buf[4] << 8) | drv->buf[5]; + leng = (drv->buf[7] << 16) | drv->buf[8]; + atapi_cmd_playaudio_sub(drv, pos, leng); +} + +// 0x47: Play Audio MSF +static void atapi_cmd_playaudiomsf(IDEDRV drv) { + + UINT32 pos; + UINT32 leng; + + int M, S, F; + if(drv->damsfbcd){ + M = BCD2HEX(drv->buf[3]); + S = BCD2HEX(drv->buf[4]); + F = BCD2HEX(drv->buf[5]); + pos = (((M * 60) + S) * 75) + F; + M = BCD2HEX(drv->buf[6]); + S = BCD2HEX(drv->buf[7]); + F = BCD2HEX(drv->buf[8]); + leng = (((M * 60) + S) * 75) + F; + }else{ + M = drv->buf[3]; + S = drv->buf[4]; + F = drv->buf[5]; + pos = (((M * 60) + S) * 75) + F; + M = drv->buf[6]; + S = drv->buf[7]; + F = drv->buf[8]; + leng = (((M * 60) + S) * 75) + F; + } + if (leng > pos) { + leng -= pos; + } + else { + leng = 0; + } + if (pos >= 150) { + pos -= 150; + } + else { + pos = 0; + } + atapi_cmd_playaudio_sub(drv, pos, leng); +} + +// 0x4B: PAUSE RESUME +static void atapi_cmd_pauseresume(IDEDRV drv) { + + if (drv->buf[8] & 1) { + // resume + if (drv->daflag == 0x12) { + ideio.daplaying |= 1 << (drv->sxsidrv & 3); + drv->daflag = 0x11; + } + } + else { + // pause + if (drv->daflag == 0x11) { + ideio.daplaying &= ~(1 << (drv->sxsidrv & 3)); + drv->daflag = 0x12; + } + } + cmddone(drv); +} + +// 0x2B: SEEK +static void atapi_cmd_seek(IDEDRV drv, UINT32 lba) +{ + CDTRK trk; + UINT tracks; + SXSIDEV sxsi; + + stop_daplay(drv); + + sxsi = sxsi_getptr(drv->sxsidrv); + trk = sxsicd_gettrk(sxsi, &tracks); + TRACEOUT(("atapicmd: seek LBA=%d NSEC=%d", lba, trk[tracks-1].pos + trk[tracks-1].sectors)); + if (lba < trk[tracks-1].pos + trk[tracks-1].sectors) { + drv->dacurpos = lba; + } + cmddone(drv); +} + +// 0xBD: MECHANISM STATUS +static void atapi_cmd_mechanismstatus(IDEDRV drv) { + + //SXSIDEV sxsi; + + //sxsi = sxsi_getptr(drv->sxsidrv); + //ZeroMemory(drv->buf, 12); + //drv->buf[0] = 0x00; + //drv->buf[1] = 0x00; + //drv->buf[2] = drv->cy & 0xff; // LBA(MSB) + //drv->buf[3] = (drv->cy >> 8) & 0xff; // LBA + //drv->buf[4] = drv->sn; // LBA(LSB) + //drv->buf[5] = 0x01; + //drv->buf[6] = 0x00; + //drv->buf[7] = 0x04; + //drv->buf[8] = (sxsi->flag & SXSIFLAG_READY) ? 0x80 : 0x00; // XXX: CD挿入状態とか入れてやるべき? + //drv->buf[9] = 0x00; + //drv->buf[10] = 0x00; + //drv->buf[11] = 0x00; + //senddata(drv, 12, 12); + sendabort(drv); +} + +void atapi_initialize(void) { +#if defined(NP2_WIN) + UINT32 dwID = 0; + //if(!pic_cs_initialized){ + // memset(&pic_cs, 0, sizeof(pic_cs)); + // InitializeCriticalSection(&pic_cs); + // pic_cs_initialized = 1; + //} + if(!atapi_thread_initialized){ + atapi_thread_initialized = 1; + atapi_thread_event_complete = CreateEvent(NULL, TRUE, TRUE, NULL); + atapi_thread_event_request = CreateEvent(NULL, FALSE, FALSE, NULL); + atapi_thread = (HANDLE)_beginthreadex(NULL, 0, atapi_dataread_threadfunc, NULL, 0, &dwID); + } +#else + // TODO: 非Windows用コードを書く +#endif +} + +void atapi_deinitialize(void) { +#if defined(NP2_WIN) + if(atapi_thread_initialized){ + atapi_thread_initialized = 0; + SetEvent(atapi_thread_event_request); + if(WaitForSingleObject(atapi_thread, 5000) == WAIT_TIMEOUT){ + TerminateThread(atapi_thread, 0); + } + CloseHandle(atapi_thread); + CloseHandle(atapi_thread_event_complete); + CloseHandle(atapi_thread_event_request); + atapi_thread = NULL; + } +#else + // TODO: 非Windows用コードを書く +#endif +} +#endif /* SUPPORT_IDEIO */ + diff --git a/cbus/atapicmd.h b/cbus/atapicmd.h old mode 100755 new mode 100644 index 41c55f9a..1a694f2e --- a/cbus/atapicmd.h +++ b/cbus/atapicmd.h @@ -1,62 +1,62 @@ - -#if defined(SUPPORT_IDEIO) - -// sense key -enum { - ATAPI_SK_NO_SENSE = 0x00, - ATAPI_SK_RECOVERED_ERROR = 0x01, - ATAPI_SK_NOT_READY = 0x02, - ATAPI_SK_MEDIUM_ERROR = 0x03, - ATAPI_SK_HARDWARE_ERROR = 0x04, - ATAPI_SK_ILLEGAL_REQUEST = 0x05, - ATAPI_SK_UNIT_ATTENTIOn = 0x06, - ATAPI_SK_DATA_PROTECT = 0x07, - ATAPI_SK_ABORTED_COMMAND = 0x0b, - ATAPI_SK_MISCOMPARE = 0x0e, - ATAPI_SK_MAX -}; - -#define ATAPI_SENSE_KEY_SHIFT 4 -#define ATAPI_SENSE_KEY_MASK 0xf0 -#define ATAPI_SET_SENSE_KEY(drv, sensekey) \ -do { \ - (drv)->error &= ~ATAPI_SENSE_KEY_MASK; \ - (drv)->error |= (sensekey) << ATAPI_SENSE_KEY_SHIFT; \ - (drv)->sk = (sensekey); \ -} while (/*CONSTCOND*/ 0) - - -// additional sense code (ASC) & ASC Qualifier (ASCQ) -enum { - ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION = 0x0000, - ATAPI_ASC_PARAMETER_LIST_LENGTH_ERROR = 0x001a, - ATAPI_ASC_INVALID_COMMAND_OPERATION_CODE = 0x0020, - ATAPI_ASC_INVALID_FIELD_IN_CDB = 0x0024, - ATAPI_ASC_NOT_READY_TO_READY_TRANSITION = 0x0028, - ATAPI_ASC_POWER_ON_RESET_OR_BUS_DEVICE_RESET_OCCURRED = 0x0029, - ATAPI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED = 0x0039, - ATAPI_ASC_MEDIUM_NOT_PRESENT = 0x003a, - ATAPI_ASC_MEDIUM_NOT_PRESENT_TRAY_CLOSED = 0x013a, - ATAPI_ASC_MEDIUM_NOT_PRESENT_TRAY_OPEN = 0x023a, - ATAPI_ASC_MAX -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -void atapi_initialize(void); -void atapi_deinitialize(void); - -void atapicmd_a0(IDEDRV drv); - -void atapi_dataread(IDEDRV drv); -void atapi_dataread_asyncwait(int wait); - -#ifdef __cplusplus -} -#endif - -#endif /* SUPPORT_IDEIO */ - + +#if defined(SUPPORT_IDEIO) + +// sense key +enum { + ATAPI_SK_NO_SENSE = 0x00, + ATAPI_SK_RECOVERED_ERROR = 0x01, + ATAPI_SK_NOT_READY = 0x02, + ATAPI_SK_MEDIUM_ERROR = 0x03, + ATAPI_SK_HARDWARE_ERROR = 0x04, + ATAPI_SK_ILLEGAL_REQUEST = 0x05, + ATAPI_SK_UNIT_ATTENTIOn = 0x06, + ATAPI_SK_DATA_PROTECT = 0x07, + ATAPI_SK_ABORTED_COMMAND = 0x0b, + ATAPI_SK_MISCOMPARE = 0x0e, + ATAPI_SK_MAX +}; + +#define ATAPI_SENSE_KEY_SHIFT 4 +#define ATAPI_SENSE_KEY_MASK 0xf0 +#define ATAPI_SET_SENSE_KEY(drv, sensekey) \ +do { \ + (drv)->error &= ~ATAPI_SENSE_KEY_MASK; \ + (drv)->error |= (sensekey) << ATAPI_SENSE_KEY_SHIFT; \ + (drv)->sk = (sensekey); \ +} while (/*CONSTCOND*/ 0) + + +// additional sense code (ASC) & ASC Qualifier (ASCQ) +enum { + ATAPI_ASC_NO_ADDITIONAL_SENSE_INFORMATION = 0x0000, + ATAPI_ASC_PARAMETER_LIST_LENGTH_ERROR = 0x001a, + ATAPI_ASC_INVALID_COMMAND_OPERATION_CODE = 0x0020, + ATAPI_ASC_INVALID_FIELD_IN_CDB = 0x0024, + ATAPI_ASC_NOT_READY_TO_READY_TRANSITION = 0x0028, + ATAPI_ASC_POWER_ON_RESET_OR_BUS_DEVICE_RESET_OCCURRED = 0x0029, + ATAPI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED = 0x0039, + ATAPI_ASC_MEDIUM_NOT_PRESENT = 0x003a, + ATAPI_ASC_MEDIUM_NOT_PRESENT_TRAY_CLOSED = 0x013a, + ATAPI_ASC_MEDIUM_NOT_PRESENT_TRAY_OPEN = 0x023a, + ATAPI_ASC_MAX +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +void atapi_initialize(void); +void atapi_deinitialize(void); + +void atapicmd_a0(IDEDRV drv); + +void atapi_dataread(IDEDRV drv); +void atapi_dataread_asyncwait(int wait); + +#ifdef __cplusplus +} +#endif + +#endif /* SUPPORT_IDEIO */ + diff --git a/cbus/board118.c b/cbus/board118.c old mode 100755 new mode 100644 index b93fbe7e..6e920846 --- a/cbus/board118.c +++ b/cbus/board118.c @@ -1,972 +1,972 @@ -/** - * @file board118.c - * @brief Implementation of PC-9801-118 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int opna_idx = 0; -static int a460_soundid = 0x80; - -/*********** for OPL (MAME) ***********/ - -#define G_OPL3_INDEX 0 - -#ifdef USE_MAME -#ifdef USE_MAME_BSD -#if _MSC_VER < 1900 -#include -#else -#include -#endif -#else -#include -#endif -static int samplerate; - -static void IOOUTCALL sb16_o20d2(UINT port, REG8 dat) { - (void)port; - g_opl3[G_OPL3_INDEX].s.addrl = dat; // Key Display用 - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 0, dat); -} - -static void IOOUTCALL sb16_o21d2(UINT port, REG8 dat) { - (void)port; - opl3_writeRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl, dat); // Key Display用 - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 1, dat); -} -static void IOOUTCALL sb16_o22d2(UINT port, REG8 dat) { - (void)port; - g_opl3[G_OPL3_INDEX].s.addrh = dat; // Key Display用 - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 2, dat); -} - -static void IOOUTCALL sb16_o23d2(UINT port, REG8 dat) { - (void)port; - opl3_writeExtendedRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrh, dat); // Key Display用 - //S98_put(EXTEND2608, opl.addr2, dat); - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 3, dat); -} - -static void IOOUTCALL sb16_o28d2(UINT port, REG8 dat) { - /** - * いわゆるPC/ATで言うところのAdlib互換ポート - * UltimaUnderWorldではこちらを叩く - */ - port = dat; - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 0, dat); -} -static void IOOUTCALL sb16_o29d2(UINT port, REG8 dat) { - port = dat; - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 1, dat); -} - -static REG8 IOINPCALL sb16_i20d2(UINT port) { - - REG8 ret; - ret = YMF262Read(g_mame_opl3[G_OPL3_INDEX], 0); - ////if(g_opl.reg[0x4] == 1) return 0x02; - ////if(g_opl.reg[0x4] == 1){ - // if ((cs4231.reg.pinctrl & IEN) && (cs4231.dmairq != 0xff)) { - // if(cs4231.intflag & INt){ - // } - // } - ////} - return ret; -} - -static REG8 IOINPCALL sb16_i22d2(UINT port) { - (void)port; - return YMF262Read(g_mame_opl3[G_OPL3_INDEX], 1); -} - -static REG8 IOINPCALL sb16_i28d2(UINT port) { - (void)port; - return YMF262Read(g_mame_opl3[G_OPL3_INDEX], 0); -} -#endif - -/*********** for OPNA ***********/ - -static void IOOUTCALL ymf_o188(UINT port, REG8 dat) -{ - g_opna[opna_idx].s.addrl = dat; - g_opna[opna_idx].s.addrh = 0; - g_opna[opna_idx].s.data = dat; - (void)port; -} - -static void IOOUTCALL ymf_o18a(UINT port, REG8 dat) -{ - g_opna[opna_idx].s.data = dat; - if (g_opna[opna_idx].s.addrh != 0) { - return; - } - - if (g_opna[opna_idx].s.addrl == 0x27) { - /* OPL3-LにCSMモードは無い */ - dat &= ~0x80; - g_opna[opna_idx].opngen.opnch[2].extop = dat & 0xc0; - } - - opna_writeRegister(&g_opna[opna_idx], g_opna[opna_idx].s.addrl, dat); - - (void)port; -} - - -static void IOOUTCALL ymf_o18c(UINT port, REG8 dat) -{ - if (g_opna[opna_idx].s.extend) - { - g_opna[opna_idx].s.addrl = dat; - g_opna[opna_idx].s.addrh = 1; - g_opna[opna_idx].s.data = dat; - } - (void)port; -} - -static void IOOUTCALL ymf_o18e(UINT port, REG8 dat) -{ - if (!g_opna[opna_idx].s.extend) - { - return; - } - g_opna[opna_idx].s.data = dat; - - if (g_opna[opna_idx].s.addrh != 1) - { - return; - } - - opna_writeExtendedRegister(&g_opna[opna_idx], g_opna[opna_idx].s.addrl, dat); - - (void)port; -} - -static REG8 IOINPCALL ymf_i188(UINT port) -{ - REG8 ret; - ret = g_opna[opna_idx].s.status; - if((cs4231.reg.pinctrl & IEN) && (cs4231.reg.featurestatus & (PI|TI|CI))) { - ret |= 0x02; - } - return ret; -} - -static REG8 IOINPCALL ymf_i18a(UINT port) -{ - UINT nAddress; - - if (g_opna[opna_idx].s.addrh == 0) - { - nAddress = g_opna[opna_idx].s.addrl; - if (nAddress == 0x0e) - { - return fmboard_getjoy(&g_opna[opna_idx]); - } - else if (nAddress < 0x10) - { - return opna_readRegister(&g_opna[opna_idx], nAddress); - } - else if (nAddress == 0xff) - { - return 1; - } - } - - (void)port; - return g_opna[opna_idx].s.data; -} - -static REG8 IOINPCALL ymf_i18c(UINT port) -{ - if (g_opna[opna_idx].s.extend) - { - return (g_opna[opna_idx].s.status & 3); - } - - (void)port; - return 0xff; -} - -static void extendchannel(REG8 enable) -{ - g_opna[opna_idx].s.extend = enable; - if (enable) - { - opngen_setcfg(&g_opna[opna_idx].opngen, 6, OPN_STEREO | 0x007); - } - else - { - opngen_setcfg(&g_opna[opna_idx].opngen, 3, OPN_MONORAL | 0x007); - rhythm_setreg(&g_opna[opna_idx].rhythm, 0x10, 0xff); - } -} - -static void IOOUTCALL ymf_oa460(UINT port, REG8 dat) -{ - cs4231.extfunc = dat; - extendchannel((REG8)(dat & 1)); - (void)port; -} - -static REG8 IOINPCALL ymf_ia460(UINT port) -{ - return (a460_soundid | (cs4231.extfunc & 1)); - (void)port; -} - -/*********** SRN-F I/O ***********/ - -char srnf; -static void IOOUTCALL srnf_oa460(UINT port, REG8 dat) -{ - srnf = dat; - (void)port; -} - -static REG8 IOINPCALL srnf_ia460(UINT port) -{ - (void)port; - return (srnf); -} - -/*********** WaveStar I/O ***********/ - -REG8 wavestar_4d2 = 0xff; -static void IOOUTCALL wavestar_o4d2(UINT port, REG8 dat) -{ - wavestar_4d2 = dat; - (void)port; -} - -static REG8 IOINPCALL wavestar_i4d2(UINT port) -{ - (void)port; - return (wavestar_4d2); -} - -/*********** ソフトウェアディップスイッチ I/O ***********/ - -static REG8 IOINPCALL wss_i881e(UINT port) -{ - if(g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ - int ret = 0x64; - ret |= (cs4231.dmairq-1) << 3; - if((cs4231.dmairq-1)==0x1 || (cs4231.dmairq-1)==0x2){ - ret |= 0x80; // 奇数パリティ - } - return (ret); - }else{ - return (0xDC); - } -} - -/*********** YMF-701/715 I/O ? ***********/ - -REG8 ymf701; -static void IOOUTCALL wss_o548e(UINT port, REG8 dat) -{ - ymf701 = dat; -} -static REG8 IOINPCALL wss_i548e(UINT port) -{ - return (ymf701); -} -static REG8 IOINPCALL wss_i548f(UINT port) -{ - if(ymf701 == 0) return 0xe8; - else if(ymf701 == 0x1) return 0xfe; - else if(ymf701 == 0x2) return 0x40; - else if(ymf701 == 0x3) return 0x30; - else if(ymf701 == 0x4) return 0xff; - else if(ymf701 == 0x20) return 0x04; - else if(ymf701 == 0x40) return 0x20; - else return 0;// from PC-9821Nr166 -} - -#if defined(SUPPORT_GAMEPORT) -/*********** PC-9801-118 Gameport I/O ***********/ -#define GAMEPORT_JOYCOUNTER_MGN2 (gameport_clkmax/100) -//#define GAMEPORT_JOYCOUNTER_MGN (gameport_clkmax/100) -#define GAMEPORT_JOYCOUNTER_TMPCLK 100000000 -#if defined(SUPPORT_IA32_HAXM) -static LARGE_INTEGER gameport_qpf; -static int gameport_useqpc = 0; -#endif -extern int gameport_tsccounter; -static UINT64 gameport_tsc; -static REG8 gameport_joyflag_base = 0x00; -static REG8 gameport_joyflag = 0x00; -#if defined(SUPPORT_IA32_HAXM) -static UINT64 gameport_clkmax; -static UINT64 gameport_threshold_x = 0; -static UINT64 gameport_threshold_y = 0; -#else -static UINT32 gameport_clkmax; -static UINT32 gameport_threshold_x = 0; -static UINT32 gameport_threshold_y = 0; -#endif -//UINT32 gameport_timeoutcounter = 0; -//UINT32 gameport_timeoutinterval = 0; -// joyflag bit:0 up -// bit:1 down -// bit:2 left -// bit:3 right -// bit:4 trigger1 (rapid) -// bit:5 trigger2 (rapid) -// bit:6 trigger1 -// bit:7 trigger2 -//void gameport_timeoutproc(NEVENTITEM item); -static void IOOUTCALL gameport_o1480(UINT port, REG8 dat) -{ - REG8 joyflag; - joyflag = joymng_getstat(); - if(!joymng_available()){ - return; - } - gameport_joyflag_base = joyflag; - gameport_joyflag = ((joyflag >> 2) & 0x30) | ((joyflag << 2) & 0xc0) | 0x0f; -#if defined(SUPPORT_IA32_HAXM) - { - LARGE_INTEGER li = {0}; - if (QueryPerformanceFrequency(&gameport_qpf)) { - QueryPerformanceCounter(&li); - //li.QuadPart = li.QuadPart; - gameport_tsc = (UINT64)li.QuadPart; - gameport_useqpc = 1; - }else{ - gameport_tsc = CPU_MSR_TSC; - gameport_useqpc = 0; - } - } -#else -#if defined(USE_TSC) - if(CPU_REMCLOCK > 0){ - gameport_tsc = CPU_MSR_TSC - (UINT64)CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple; - }else{ - gameport_tsc = CPU_MSR_TSC; - } - gameport_tsccounter = 0; -#else - gameport_tsc = 0; -#endif -#endif - (void)port; -} -static REG8 IOINPCALL gameport_i1480(UINT port) -{ - REG8 retval = 0xff; -#if defined(NP2_WIN) - UINT32 joyAnalogX; - UINT32 joyAnalogY; -#endif - UINT64 clockdiff; -#if defined(SUPPORT_IA32_HAXM) - LARGE_INTEGER li = {0}; - QueryPerformanceCounter(&li); -#endif - { - REG8 joyflag = joymng_getstat(); - gameport_joyflag = ((joyflag >> 2) & 0x30) | ((joyflag << 2) & 0xc0) | (gameport_joyflag & 0x0f); - } - if(!joymng_available()){ - return 0xff; - } -#if defined(NP2_WIN) - joyAnalogX = joymng_getAnalogX(); - joyAnalogY = joymng_getAnalogY(); -#endif -#if defined(SUPPORT_IA32_HAXM) - if(gameport_useqpc){ - clockdiff = (unsigned long long)((UINT64)li.QuadPart - gameport_tsc); - gameport_clkmax = (UINT64)gameport_qpf.QuadPart / 1300; // とりあえず0.7msで・・・ - }else{ - clockdiff = CPU_MSR_TSC - gameport_tsc; - gameport_clkmax = pccore.realclock / 1430; // とりあえず0.7msで・・・ - } -#else -#if defined(USE_TSC) - if(CPU_REMCLOCK > 0){ - clockdiff = CPU_MSR_TSC - (UINT64)CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple - gameport_tsc; - }else{ - clockdiff = CPU_MSR_TSC - gameport_tsc; - } - gameport_clkmax = pccore.baseclock * pccore.maxmultiple / 1430; // とりあえず0.7msで・・・ -#if !defined(SUPPORT_IA32_HAXM) - if(gameport_tsccounter == 0 || !np2cfg.consttsc){ - gameport_clkmax = gameport_clkmax * pccore.maxmultiple / pccore.multiple; // CPUクロック依存の場合のfix - } -#endif -#else - gameport_clkmax = 32; - clockdiff = gameport_tsc; - gameport_tsc++; -#endif -#endif - if (np2cfg.analogjoy) - { - // アナログ入力タイプ -#if defined(NP2_WIN) - gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2 + (UINT32)((UINT64)(gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2 * 2) * joyAnalogX / 65535); - gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2 + (UINT32)((UINT64)(gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2 * 2) * joyAnalogY / 65535); -#else - gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2; - gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2; -#endif - } - else - { - // ON/OFFタイプ - gameport_threshold_x = gameport_clkmax / 2; - gameport_threshold_y = gameport_clkmax / 2; - if(~gameport_joyflag_base & 0x1){ - gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2; - } - if(~gameport_joyflag_base & 0x2){ - gameport_threshold_y = gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2; - } - if(~gameport_joyflag_base & 0x4){ - gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2; - } - if(~gameport_joyflag_base & 0x8){ - gameport_threshold_x = gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2; - } - } - retval = gameport_joyflag; - if(clockdiff >= (UINT64)gameport_threshold_x){ - gameport_joyflag &= ~0x01; - } - if(clockdiff >= (UINT64)gameport_threshold_y){ - gameport_joyflag &= ~0x02; - } - return retval; -} -#endif - - -/*********** for OPL (NP2) ***********/ - -static void IOOUTCALL ym_o1488(UINT port, REG8 dat) //FM Music Register Address Port -{ - g_opl3[G_OPL3_INDEX].s.addrl = dat; - (void)port; -} -REG8 opl_data; -static void IOOUTCALL ym_o1489(UINT port, REG8 dat) //FM Music Data Port -{ - opl3_writeRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl, dat); - opl_data = dat; - (void)port; -} - - -static void IOOUTCALL ym_o148a(UINT port, REG8 dat) // Advanced FM Music Register Address Port -{ - g_opl3[G_OPL3_INDEX].s.addrh = dat; - (void)port; -} -static void IOOUTCALL ym_o148b(UINT port, REG8 dat) //Advanced FM Music Data Port -{ - opl3_writeExtendedRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrh, dat); - (void)port; -} - -static REG8 IOINPCALL ym_i1488(UINT port) //FM Music Status Port -{ - TRACEOUT(("%x read",port)); -// if (opl_data == 0x80) return 0xe0; - if (opl_data == 0x21) return 0xc0; - return 0; -} - -static REG8 IOINPCALL ym_i1489(UINT port) // ??? -{ - TRACEOUT(("%x read",port)); - return opl3_readRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl); -} -static REG8 IOINPCALL ym_i148a(UINT port) //Advanced FM Music Status Port -{ - TRACEOUT(("%x read",port)); - return opl3_readStatus(&g_opl3[G_OPL3_INDEX]); -} - -static REG8 IOINPCALL ym_i148b(UINT port) // ??? -{ - TRACEOUT(("%x read",port)); - return opl3_readExtendedRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrh); -} - -/*********** PC-9801-118 config I/O ? ***********/ - -REG8 sound118 = 0x05; -static void IOOUTCALL csctrl_o148e(UINT port, REG8 dat) { - TRACEOUT(("write %x %x",port,dat)); - sound118 = dat; -} - -static REG8 IOINPCALL csctrl_i148e(UINT port) { - return(sound118); - TRACEOUT(("%x read",port)); -} -REG8 control118; -static REG8 IOINPCALL csctrl_i148f(UINT port) { - TRACEOUT(("%x read",port)); - (void)port; - //if(sound118 == 0) return(0xf0);//PC-9801-118は3だけどYMFは0xff 2000はこれだけじゃまだダメ - if(sound118 == 0) return(0xf3);//PC-9801-118は3だけどYMFは0xff 2000はこれだけじゃまだダメ - if(sound118 == 0x05){ - if(control118==4)return 4; - if(control118==0x0c) return 4; - if(control118==0)return 0; - } - if(sound118 == 0x04) return (0x00); - if(sound118 == 0x21){ - switch(10/*mpu98.irqnum2*/){//MIDI割り込み 00:IRQ10 01:IRQ6 02:IRQ5 03:IRQ3 - case 10:return 0; - case 6: return 1; - case 5: return 2; - case 3: return 3; - default: return 0; - } - } - if(sound118 == 0xff) return (0x05);//bit0 MIDI割り込みあり bit1:Cb Na7 bit2:Mate-X bit3:A-Mate Ce2 - else - return(0xff); -} - -static void IOOUTCALL csctrl_o148f(UINT port, REG8 dat) { - TRACEOUT(("write %x %x",port,dat)); - - //if (sound118 == 0x21) switch(dat){ - // case 0:mpu98.irqnum2 = 10;break; - // case 1:mpu98.irqnum2 = 6;break; - // case 2:mpu98.irqnum2 = 5;break; - // case 3:mpu98.irqnum2 = 3;break; - // default: break; - //} - control118 = dat; -} - -static REG8 IOINPCALL csctrl_i486(UINT port) { - return(0); -} - -// ---- MAME使用の場合のPCM再生 -#ifdef USE_MAME -static SINT32 oplfm_softvolume_L = 0; -static SINT32 oplfm_softvolume_R = 0; -static SINT32 oplfm_softvolumereg_L = 0xff; -static SINT32 oplfm_softvolumereg_R = 0xff; -#define OPL3_SAMPLE_BUFFER 4096 -static INT16 oplfm_s1ls[OPL3_SAMPLE_BUFFER] = { 0 }; -static INT16 oplfm_s1rs[OPL3_SAMPLE_BUFFER] = { 0 }; -static INT16 oplfm_s2ls[OPL3_SAMPLE_BUFFER] = { 0 }; -static INT16 oplfm_s2rs[OPL3_SAMPLE_BUFFER] = { 0 }; -static void SOUNDCALL opl3gen_getpcm2(void* opl3, SINT32 *pcm, UINT count) { - UINT i; - INT16 *buf[4]; - INT16 s1l,s1r,s2l,s2r; - SINT32 oplfm_volume; - SINT32 *outbuf = pcm; - SINT32 volL, volR; - buf[0] = oplfm_s1ls; - buf[1] = oplfm_s1rs; - buf[2] = oplfm_s2ls; - buf[3] = oplfm_s2rs; - - // NP2グローバルFMボリューム(0~127) - oplfm_volume = np2cfg.vol_fm * np2cfg.vol_master / 100; - - // Canbe/ValueStarミキサー FMボリューム(0~31) bit7:1=mute, bit6-5:reserved, bit4-0:volume(00000b max, 11111b min) - if(oplfm_softvolumereg_L != cs4231.devvolume[0x30]){ - oplfm_softvolumereg_L = cs4231.devvolume[0x30]; - if(oplfm_softvolumereg_L & 0x80){ // FM L Mute - oplfm_softvolume_L = 0; - }else{ - oplfm_softvolume_L = ((~oplfm_softvolumereg_L) & 0x1f); // FM L Volume - } - } - if(oplfm_softvolumereg_R != cs4231.devvolume[0x31]){ - oplfm_softvolumereg_R = cs4231.devvolume[0x31]; - if(oplfm_softvolumereg_R & 0x80){ // FM R Mute - oplfm_softvolume_R = 0; - }else{ - oplfm_softvolume_R = ((~oplfm_softvolumereg_R) & 0x1f); // FM R Volume - } - } - - // PCMサウンドバッファに送る - volL = oplfm_volume * oplfm_softvolume_L; - volR = oplfm_volume * oplfm_softvolume_R; - while (count > 0) { - int cc = MIN(count, OPL3_SAMPLE_BUFFER); - YMF262UpdateOne(opl3, buf, cc); - for (i = 0; i < cc; i++) { - outbuf[0] += (((SINT32)oplfm_s1ls[i] * volL) >> 9); - outbuf[1] += (((SINT32)oplfm_s1rs[i] * volR) >> 9); - outbuf += 2; - } - count -= cc; - } -} -static void SOUNDCALL opl3gen_getpcm2_dummy(void* opl3, SINT32* pcm, UINT count) { - UINT i; - INT16* buf[4]; - INT16 s1l, s1r, s2l, s2r; - buf[0] = oplfm_s1ls; - buf[1] = oplfm_s1rs; - buf[2] = oplfm_s2ls; - buf[3] = oplfm_s2rs; - while (count > 0) { - int cc = MIN(count, OPL3_SAMPLE_BUFFER); - YMF262UpdateOne(opl3, buf, cc); - count -= cc; - } -} -#endif - -static const IOOUT ymf_o[4] = { - ymf_o188, ymf_o18a, ymf_o18c, ymf_o18e}; - -static const IOINP ymf_i[4] = { - ymf_i188, ymf_i18a, ymf_i18c, NULL}; - -/** - * Reset - * @param[in] pConfig A pointer to a configure structure - */ -void board118_reset(const NP2CFG *pConfig) -{ - - // 86音源と共存させる場合、使用するNP2 OPNA番号を変える - if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_WAVESTAR || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ - opna_idx = 1; - }else{ - opna_idx = 0; - } - - // OPNAリセット - opna_reset(&g_opna[opna_idx], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_S98); - if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ - // OPNAタイマーをセットしない - //opna_timer(&g_opna[opna_idx], 0x10, NEVENT_FMTIMERA, NEVENT_FMTIMERB); - }else{ - // OPNAタイマーをセット - UINT irqval = 0x00; - UINT8 irqf = np2cfg.snd118irqf; - if (g_nSoundID == SOUNDID_WAVESTAR) - { - irqf = 0xc; // IRQ12固定 - } - if(g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ - UINT8 irq86table[4] = {0x03, 0x0d, 0x0a, 0x0c}; - UINT8 nIrq86 = (np2cfg.snd86opt & 0x10) | ((np2cfg.snd86opt & 0x4) << 5) | ((np2cfg.snd86opt & 0x8) << 3); - UINT8 irq86 = irq86table[nIrq86 >> 6]; - irqf = np2cfg.snd118irqp; - if(irqf == irq86){ - if(irq86!=3){ - irqf = 0x3; - }else{ - irqf = 0xC; - } - } - } - switch(irqf){ - case 3: - irqval = 0x10|(0 << 6); - break; - case 10: - irqval = 0x10|(2 << 6); - break; - case 12: - irqval = 0x10|(3 << 6); - break; - case 13: - irqval = 0x10|(1 << 6); - break; - } - if(opna_idx == 1){ - opna_timer(&g_opna[opna_idx], irqval, NEVENT_FMTIMER2A, NEVENT_FMTIMER2B); - }else{ - opna_timer(&g_opna[opna_idx], irqval, NEVENT_FMTIMERA, NEVENT_FMTIMERB); - } - - // OPLリセット - opl3_reset(&g_opl3[G_OPL3_INDEX], OPL3_HAS_OPL3L|OPL3_HAS_OPL3); - opngen_setcfg(&g_opna[opna_idx].opngen, 3, OPN_STEREO | 0x038); - } - - // CS4231リセット - cs4231io_reset(); - - // 86+118の場合、被らないように修正 - if(g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ - UINT16 snd86iobase = (pConfig->snd86opt & 0x01) ? 0x000 : 0x100; - if(np2cfg.snd118io == 0x188 + snd86iobase){ - cs4231.port[4] += 0x100; - } - } - - // 86音源+118音源の場合、118側をはじめからFM6音にする - if(g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ - cs4231.extfunc |= 1; - extendchannel(1); - } - - // 色々設定 - if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ - }else{ - if(pConfig->snd118rom && g_nSoundID!=SOUNDID_PC_9801_86_118 && g_nSoundID!=SOUNDID_PC_9801_86_118_SB16){ - soundrom_load(0xcc000, OEMTEXT("118")); - } - fmboard_extreg(extendchannel); -#ifdef SUPPORT_SOUND_SB16 -#ifdef USE_MAME - if (g_mame_opl3[G_OPL3_INDEX]) { - if (samplerate != soundcfg.rate) { - YMF262Shutdown(g_mame_opl3[G_OPL3_INDEX]); - g_mame_opl3[G_OPL3_INDEX] = YMF262Init(14400000, soundcfg.rate); - samplerate = soundcfg.rate; - } else { - YMF262ResetChip(g_mame_opl3[G_OPL3_INDEX], samplerate); - } - } - //ZeroMemory(&g_sb16, sizeof(g_sb16)); - //// ボードデフォルト IO:D2 DMA:3 INT:5 - //g_sb16.base = 0xd2; - //g_sb16.dmach = 0x3; - //g_sb16.dmairq = 0x5; -#endif -#endif - //cs4231.extfunc = 0x01; - //extendchannel((REG8)(cs4231.extfunc & 1)); - } - - // WaveStarの場合、ボリューム初期化 - if(g_nSoundID==SOUNDID_WAVESTAR){ - // FM音量 - cs4231.devvolume[0xff] = 0xf; - opngen_setvol(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - psggen_setvol(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - rhythm_setvol(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); -#if defined(SUPPORT_FMGEN) - if(np2cfg.usefmgen) { - opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - } -#endif - oplgen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); - } - (void)pConfig; -} - -/** - * Bind - */ -void board118_bind(void) -{ - // CS4231バインド(I/Oポート割り当てとか) - cs4231io_bind(); - - // 86音源と共存させる場合、使用するNP2 OPNA番号を変える - if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_WAVESTAR || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ - opna_idx = 1; - }else{ - opna_idx = 0; - } - - if(g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ - a460_soundid = np2cfg.sndwssid;//0x70; - }else if(g_nSoundID==SOUNDID_WAVESTAR){ - a460_soundid = 0x41; - }else{ - a460_soundid = np2cfg.snd118id;//0x80; - } - - if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ - // Mate-X PCMの場合、CS4231だけ - iocore_attachout(cs4231.port[1], ymf_oa460); - iocore_attachinp(cs4231.port[1], ymf_ia460); - iocore_attachinp(0x881e, wss_i881e); - }else if(g_nSoundID==SOUNDID_WAVESTAR){ - // WaveStarの場合 なにもない - }else{ - // 118音源の場合、色々割り当て - - // OPNA割り当て - if(cs4231.port[4]){ - opna_bind(&g_opna[opna_idx]); - cbuscore_attachsndex(cs4231.port[4],ymf_o, ymf_i); - } - -#if defined(SUPPORT_GAMEPORT) - // ゲームポート割り当て 1480h~1487hどこでも良いらしい - if(np2cfg.gameport){ - int i; - for(i=0;i<=7;i++){ - iocore_attachout(0x1480+i, gameport_o1480); - iocore_attachinp(0x1480+i, gameport_i1480); - } - } -#endif - - // OPL割り当て -#ifdef USE_MAME - iocore_attachout(cs4231.port[9], sb16_o20d2); - iocore_attachinp(cs4231.port[9], sb16_i20d2); - iocore_attachout(cs4231.port[9]+1, sb16_o21d2); - iocore_attachout(cs4231.port[9]+2, sb16_o22d2); - iocore_attachinp(cs4231.port[9]+2, sb16_i22d2); - iocore_attachout(cs4231.port[9]+3, sb16_o23d2); - - if (!g_mame_opl3[G_OPL3_INDEX]) { - g_mame_opl3[G_OPL3_INDEX] = YMF262Init(14400000, np2cfg.samplingrate); - samplerate = np2cfg.samplingrate; - } - if (g_opl3[G_OPL3_INDEX].userdata) { - // 外部音源を使用する場合 ダミー登録 - sound_streamregist(g_mame_opl3[G_OPL3_INDEX], (SOUNDCB)opl3gen_getpcm2_dummy); - } - else { - // 外部音源を使用しない場合 PCM登録 - sound_streamregist(g_mame_opl3[G_OPL3_INDEX], (SOUNDCB)opl3gen_getpcm2); - } -#else - iocore_attachout(cs4231.port[9], ym_o1488); - iocore_attachinp(cs4231.port[9], ym_i1488); - iocore_attachout(cs4231.port[9]+1, ym_o1489); - iocore_attachout(cs4231.port[9]+2, ym_o148a); - iocore_attachout(cs4231.port[9]+3, ym_o148b); -#endif - opl3_bind(&g_opl3[G_OPL3_INDEX]); // MAME使用の場合Key Display用 - - // Sound ID I/O port割り当て - iocore_attachout(cs4231.port[1], ymf_oa460); - iocore_attachinp(cs4231.port[1], ymf_ia460); - - // SRN-F寄生 I/O port割り当て - //iocore_attachout(cs4231.port[15],srnf_oa460);//SRN-Fは必要なときだけ使う - //iocore_attachinp(cs4231.port[15],srnf_ia460); - //srnf = 0x81; - - // WaveStar I/O port割り当て - if(g_nSoundID==SOUNDID_WAVESTAR){ - iocore_attachout(0x4d2 ,wavestar_o4d2); - iocore_attachinp(0x4d2 ,wavestar_i4d2); - } - - // PC-9801-118 config I/O port割り当て - iocore_attachout(cs4231.port[14],csctrl_o148e); - iocore_attachinp(cs4231.port[14],csctrl_i148e); - iocore_attachout(cs4231.port[14]+1,csctrl_o148f); - iocore_attachinp(cs4231.port[14]+1,csctrl_i148f); - - // YMF-701 I/O port割り当て - iocore_attachout(cs4231.port[6], wss_o548e);// YMF-701 - iocore_attachinp(cs4231.port[6], wss_i548e);// YMF-701 - iocore_attachinp(cs4231.port[6]+1, wss_i548f);// YMF-701 - - // PC-9801-118 control? I/O port割り当て - iocore_attachinp(cs4231.port[11]+6,csctrl_i486); - iocore_attachinp(0x881e, wss_i881e); - - // MIDI I/O port割り当て mpu98ii.c側で調整 - //iocore_attachout(cs4231.port[10], mpu98ii_o0); - //iocore_attachinp(cs4231.port[10], mpu98ii_i0); - //iocore_attachout(cs4231.port[10]+1, mpu98ii_o2); - //iocore_attachinp(cs4231.port[10]+1, mpu98ii_i2); - //mpu98.irqnum = mpu98.irqnum2; - - } -} -void board118_unbind(void) -{ - cs4231io_unbind(); - - if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ - // Mate-X PCMの場合、CS4231だけ - iocore_detachout(cs4231.port[1]); - iocore_detachinp(cs4231.port[1]); - iocore_detachinp(0x881e); - }else if(g_nSoundID==SOUNDID_WAVESTAR){ - // WaveStarの場合 なにもない - }else{ - // 118音源の場合、色々割り当て - - // OPNA割り当て - if(cs4231.port[4]){ - cbuscore_detachsndex(cs4231.port[4]); - } - -#if defined(SUPPORT_GAMEPORT) - // ゲームポート割り当て 1480h~1487hどこでも良いらしい - if(np2cfg.gameport){ - int i; - for(i=0;i<=7;i++){ - iocore_detachout(0x1480+i); - iocore_detachinp(0x1480+i); - } - } -#endif - - // OPL割り当て - iocore_detachout(cs4231.port[9]); - iocore_detachinp(cs4231.port[9]); - iocore_detachout(cs4231.port[9]+1); - iocore_detachout(cs4231.port[9]+2); - iocore_detachout(cs4231.port[9]+3); - - // Sound ID I/O port割り当て - iocore_detachout(cs4231.port[1]); - iocore_detachinp(cs4231.port[1]); - - // SRN-F寄生 I/O port割り当て - //iocore_detachout(cs4231.port[15]);//SRN-Fは必要なときだけ使う - //iocore_detachinp(cs4231.port[15]); - - // PC-9801-118 config I/O port割り当て - iocore_detachout(cs4231.port[14]); - iocore_detachinp(cs4231.port[14]); - iocore_detachout(cs4231.port[14]+1); - iocore_detachinp(cs4231.port[14]+1); - - // YMF-701 I/O port割り当て - iocore_detachout(cs4231.port[6]);// YMF-701 - iocore_detachinp(cs4231.port[6]);// YMF-701 - iocore_detachinp(cs4231.port[6]+1);// YMF-701 - - // PC-9801-118 control? I/O port割り当て - iocore_detachinp(cs4231.port[11]+6); - iocore_detachinp(0x881e); - - // MIDI I/O port割り当て mpu98ii.c側で調整 - //iocore_detachout(cs4231.port[10]); - //iocore_detachinp(cs4231.port[10]); - //iocore_detachout(cs4231.port[10]+1); - //iocore_detachinp(cs4231.port[10]+1); - - } -} -void board118_finalize(void) -{ -#ifdef USE_MAME - if (g_mame_opl3[G_OPL3_INDEX]) { - YMF262Shutdown(g_mame_opl3[G_OPL3_INDEX]); - g_mame_opl3[G_OPL3_INDEX] = NULL; - } -#endif -} +/** + * @file board118.c + * @brief Implementation of PC-9801-118 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int opna_idx = 0; +static int a460_soundid = 0x80; + +/*********** for OPL (MAME) ***********/ + +#define G_OPL3_INDEX 0 + +#ifdef USE_MAME +#ifdef USE_MAME_BSD +#if _MSC_VER < 1900 +#include +#else +#include +#endif +#else +#include +#endif +static int samplerate; + +static void IOOUTCALL sb16_o20d2(UINT port, REG8 dat) { + (void)port; + g_opl3[G_OPL3_INDEX].s.addrl = dat; // Key Display用 + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 0, dat); +} + +static void IOOUTCALL sb16_o21d2(UINT port, REG8 dat) { + (void)port; + opl3_writeRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl, dat); // Key Display用 + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 1, dat); +} +static void IOOUTCALL sb16_o22d2(UINT port, REG8 dat) { + (void)port; + g_opl3[G_OPL3_INDEX].s.addrh = dat; // Key Display用 + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 2, dat); +} + +static void IOOUTCALL sb16_o23d2(UINT port, REG8 dat) { + (void)port; + opl3_writeExtendedRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrh, dat); // Key Display用 + //S98_put(EXTEND2608, opl.addr2, dat); + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 3, dat); +} + +static void IOOUTCALL sb16_o28d2(UINT port, REG8 dat) { + /** + * いわゆるPC/ATで言うところのAdlib互換ポート + * UltimaUnderWorldではこちらを叩く + */ + port = dat; + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 0, dat); +} +static void IOOUTCALL sb16_o29d2(UINT port, REG8 dat) { + port = dat; + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 1, dat); +} + +static REG8 IOINPCALL sb16_i20d2(UINT port) { + + REG8 ret; + ret = YMF262Read(g_mame_opl3[G_OPL3_INDEX], 0); + ////if(g_opl.reg[0x4] == 1) return 0x02; + ////if(g_opl.reg[0x4] == 1){ + // if ((cs4231.reg.pinctrl & IEN) && (cs4231.dmairq != 0xff)) { + // if(cs4231.intflag & INt){ + // } + // } + ////} + return ret; +} + +static REG8 IOINPCALL sb16_i22d2(UINT port) { + (void)port; + return YMF262Read(g_mame_opl3[G_OPL3_INDEX], 1); +} + +static REG8 IOINPCALL sb16_i28d2(UINT port) { + (void)port; + return YMF262Read(g_mame_opl3[G_OPL3_INDEX], 0); +} +#endif + +/*********** for OPNA ***********/ + +static void IOOUTCALL ymf_o188(UINT port, REG8 dat) +{ + g_opna[opna_idx].s.addrl = dat; + g_opna[opna_idx].s.addrh = 0; + g_opna[opna_idx].s.data = dat; + (void)port; +} + +static void IOOUTCALL ymf_o18a(UINT port, REG8 dat) +{ + g_opna[opna_idx].s.data = dat; + if (g_opna[opna_idx].s.addrh != 0) { + return; + } + + if (g_opna[opna_idx].s.addrl == 0x27) { + /* OPL3-LにCSMモードは無い */ + dat &= ~0x80; + g_opna[opna_idx].opngen.opnch[2].extop = dat & 0xc0; + } + + opna_writeRegister(&g_opna[opna_idx], g_opna[opna_idx].s.addrl, dat); + + (void)port; +} + + +static void IOOUTCALL ymf_o18c(UINT port, REG8 dat) +{ + if (g_opna[opna_idx].s.extend) + { + g_opna[opna_idx].s.addrl = dat; + g_opna[opna_idx].s.addrh = 1; + g_opna[opna_idx].s.data = dat; + } + (void)port; +} + +static void IOOUTCALL ymf_o18e(UINT port, REG8 dat) +{ + if (!g_opna[opna_idx].s.extend) + { + return; + } + g_opna[opna_idx].s.data = dat; + + if (g_opna[opna_idx].s.addrh != 1) + { + return; + } + + opna_writeExtendedRegister(&g_opna[opna_idx], g_opna[opna_idx].s.addrl, dat); + + (void)port; +} + +static REG8 IOINPCALL ymf_i188(UINT port) +{ + REG8 ret; + ret = g_opna[opna_idx].s.status; + if((cs4231.reg.pinctrl & IEN) && (cs4231.reg.featurestatus & (PI|TI|CI))) { + ret |= 0x02; + } + return ret; +} + +static REG8 IOINPCALL ymf_i18a(UINT port) +{ + UINT nAddress; + + if (g_opna[opna_idx].s.addrh == 0) + { + nAddress = g_opna[opna_idx].s.addrl; + if (nAddress == 0x0e) + { + return fmboard_getjoy(&g_opna[opna_idx]); + } + else if (nAddress < 0x10) + { + return opna_readRegister(&g_opna[opna_idx], nAddress); + } + else if (nAddress == 0xff) + { + return 1; + } + } + + (void)port; + return g_opna[opna_idx].s.data; +} + +static REG8 IOINPCALL ymf_i18c(UINT port) +{ + if (g_opna[opna_idx].s.extend) + { + return (g_opna[opna_idx].s.status & 3); + } + + (void)port; + return 0xff; +} + +static void extendchannel(REG8 enable) +{ + g_opna[opna_idx].s.extend = enable; + if (enable) + { + opngen_setcfg(&g_opna[opna_idx].opngen, 6, OPN_STEREO | 0x007); + } + else + { + opngen_setcfg(&g_opna[opna_idx].opngen, 3, OPN_MONORAL | 0x007); + rhythm_setreg(&g_opna[opna_idx].rhythm, 0x10, 0xff); + } +} + +static void IOOUTCALL ymf_oa460(UINT port, REG8 dat) +{ + cs4231.extfunc = dat; + extendchannel((REG8)(dat & 1)); + (void)port; +} + +static REG8 IOINPCALL ymf_ia460(UINT port) +{ + return (a460_soundid | (cs4231.extfunc & 1)); + (void)port; +} + +/*********** SRN-F I/O ***********/ + +char srnf; +static void IOOUTCALL srnf_oa460(UINT port, REG8 dat) +{ + srnf = dat; + (void)port; +} + +static REG8 IOINPCALL srnf_ia460(UINT port) +{ + (void)port; + return (srnf); +} + +/*********** WaveStar I/O ***********/ + +REG8 wavestar_4d2 = 0xff; +static void IOOUTCALL wavestar_o4d2(UINT port, REG8 dat) +{ + wavestar_4d2 = dat; + (void)port; +} + +static REG8 IOINPCALL wavestar_i4d2(UINT port) +{ + (void)port; + return (wavestar_4d2); +} + +/*********** ソフトウェアディップスイッチ I/O ***********/ + +static REG8 IOINPCALL wss_i881e(UINT port) +{ + if(g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ + int ret = 0x64; + ret |= (cs4231.dmairq-1) << 3; + if((cs4231.dmairq-1)==0x1 || (cs4231.dmairq-1)==0x2){ + ret |= 0x80; // 奇数パリティ + } + return (ret); + }else{ + return (0xDC); + } +} + +/*********** YMF-701/715 I/O ? ***********/ + +REG8 ymf701; +static void IOOUTCALL wss_o548e(UINT port, REG8 dat) +{ + ymf701 = dat; +} +static REG8 IOINPCALL wss_i548e(UINT port) +{ + return (ymf701); +} +static REG8 IOINPCALL wss_i548f(UINT port) +{ + if(ymf701 == 0) return 0xe8; + else if(ymf701 == 0x1) return 0xfe; + else if(ymf701 == 0x2) return 0x40; + else if(ymf701 == 0x3) return 0x30; + else if(ymf701 == 0x4) return 0xff; + else if(ymf701 == 0x20) return 0x04; + else if(ymf701 == 0x40) return 0x20; + else return 0;// from PC-9821Nr166 +} + +#if defined(SUPPORT_GAMEPORT) +/*********** PC-9801-118 Gameport I/O ***********/ +#define GAMEPORT_JOYCOUNTER_MGN2 (gameport_clkmax/100) +//#define GAMEPORT_JOYCOUNTER_MGN (gameport_clkmax/100) +#define GAMEPORT_JOYCOUNTER_TMPCLK 100000000 +#if defined(SUPPORT_IA32_HAXM) +static LARGE_INTEGER gameport_qpf; +static int gameport_useqpc = 0; +#endif +extern int gameport_tsccounter; +static UINT64 gameport_tsc; +static REG8 gameport_joyflag_base = 0x00; +static REG8 gameport_joyflag = 0x00; +#if defined(SUPPORT_IA32_HAXM) +static UINT64 gameport_clkmax; +static UINT64 gameport_threshold_x = 0; +static UINT64 gameport_threshold_y = 0; +#else +static UINT32 gameport_clkmax; +static UINT32 gameport_threshold_x = 0; +static UINT32 gameport_threshold_y = 0; +#endif +//UINT32 gameport_timeoutcounter = 0; +//UINT32 gameport_timeoutinterval = 0; +// joyflag bit:0 up +// bit:1 down +// bit:2 left +// bit:3 right +// bit:4 trigger1 (rapid) +// bit:5 trigger2 (rapid) +// bit:6 trigger1 +// bit:7 trigger2 +//void gameport_timeoutproc(NEVENTITEM item); +static void IOOUTCALL gameport_o1480(UINT port, REG8 dat) +{ + REG8 joyflag; + joyflag = joymng_getstat(); + if(!joymng_available()){ + return; + } + gameport_joyflag_base = joyflag; + gameport_joyflag = ((joyflag >> 2) & 0x30) | ((joyflag << 2) & 0xc0) | 0x0f; +#if defined(SUPPORT_IA32_HAXM) + { + LARGE_INTEGER li = {0}; + if (QueryPerformanceFrequency(&gameport_qpf)) { + QueryPerformanceCounter(&li); + //li.QuadPart = li.QuadPart; + gameport_tsc = (UINT64)li.QuadPart; + gameport_useqpc = 1; + }else{ + gameport_tsc = CPU_MSR_TSC; + gameport_useqpc = 0; + } + } +#else +#if defined(USE_TSC) + if(CPU_REMCLOCK > 0){ + gameport_tsc = CPU_MSR_TSC - (UINT64)CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple; + }else{ + gameport_tsc = CPU_MSR_TSC; + } + gameport_tsccounter = 0; +#else + gameport_tsc = 0; +#endif +#endif + (void)port; +} +static REG8 IOINPCALL gameport_i1480(UINT port) +{ + REG8 retval = 0xff; +#if defined(NP2_WIN) + UINT32 joyAnalogX; + UINT32 joyAnalogY; +#endif + UINT64 clockdiff; +#if defined(SUPPORT_IA32_HAXM) + LARGE_INTEGER li = {0}; + QueryPerformanceCounter(&li); +#endif + { + REG8 joyflag = joymng_getstat(); + gameport_joyflag = ((joyflag >> 2) & 0x30) | ((joyflag << 2) & 0xc0) | (gameport_joyflag & 0x0f); + } + if(!joymng_available()){ + return 0xff; + } +#if defined(NP2_WIN) + joyAnalogX = joymng_getAnalogX(); + joyAnalogY = joymng_getAnalogY(); +#endif +#if defined(SUPPORT_IA32_HAXM) + if(gameport_useqpc){ + clockdiff = (unsigned long long)((UINT64)li.QuadPart - gameport_tsc); + gameport_clkmax = (UINT64)gameport_qpf.QuadPart / 1300; // とりあえず0.7msで・・・ + }else{ + clockdiff = CPU_MSR_TSC - gameport_tsc; + gameport_clkmax = pccore.realclock / 1430; // とりあえず0.7msで・・・ + } +#else +#if defined(USE_TSC) + if(CPU_REMCLOCK > 0){ + clockdiff = CPU_MSR_TSC - (UINT64)CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple - gameport_tsc; + }else{ + clockdiff = CPU_MSR_TSC - gameport_tsc; + } + gameport_clkmax = pccore.baseclock * pccore.maxmultiple / 1430; // とりあえず0.7msで・・・ +#if !defined(SUPPORT_IA32_HAXM) + if(gameport_tsccounter == 0 || !np2cfg.consttsc){ + gameport_clkmax = gameport_clkmax * pccore.maxmultiple / pccore.multiple; // CPUクロック依存の場合のfix + } +#endif +#else + gameport_clkmax = 32; + clockdiff = gameport_tsc; + gameport_tsc++; +#endif +#endif + if (np2cfg.analogjoy) + { + // アナログ入力タイプ +#if defined(NP2_WIN) + gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2 + (UINT32)((UINT64)(gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2 * 2) * joyAnalogX / 65535); + gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2 + (UINT32)((UINT64)(gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2 * 2) * joyAnalogY / 65535); +#else + gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2; + gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2; +#endif + } + else + { + // ON/OFFタイプ + gameport_threshold_x = gameport_clkmax / 2; + gameport_threshold_y = gameport_clkmax / 2; + if(~gameport_joyflag_base & 0x1){ + gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2; + } + if(~gameport_joyflag_base & 0x2){ + gameport_threshold_y = gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2; + } + if(~gameport_joyflag_base & 0x4){ + gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2; + } + if(~gameport_joyflag_base & 0x8){ + gameport_threshold_x = gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2; + } + } + retval = gameport_joyflag; + if(clockdiff >= (UINT64)gameport_threshold_x){ + gameport_joyflag &= ~0x01; + } + if(clockdiff >= (UINT64)gameport_threshold_y){ + gameport_joyflag &= ~0x02; + } + return retval; +} +#endif + + +/*********** for OPL (NP2) ***********/ + +static void IOOUTCALL ym_o1488(UINT port, REG8 dat) //FM Music Register Address Port +{ + g_opl3[G_OPL3_INDEX].s.addrl = dat; + (void)port; +} +REG8 opl_data; +static void IOOUTCALL ym_o1489(UINT port, REG8 dat) //FM Music Data Port +{ + opl3_writeRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl, dat); + opl_data = dat; + (void)port; +} + + +static void IOOUTCALL ym_o148a(UINT port, REG8 dat) // Advanced FM Music Register Address Port +{ + g_opl3[G_OPL3_INDEX].s.addrh = dat; + (void)port; +} +static void IOOUTCALL ym_o148b(UINT port, REG8 dat) //Advanced FM Music Data Port +{ + opl3_writeExtendedRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrh, dat); + (void)port; +} + +static REG8 IOINPCALL ym_i1488(UINT port) //FM Music Status Port +{ + TRACEOUT(("%x read",port)); +// if (opl_data == 0x80) return 0xe0; + if (opl_data == 0x21) return 0xc0; + return 0; +} + +static REG8 IOINPCALL ym_i1489(UINT port) // ??? +{ + TRACEOUT(("%x read",port)); + return opl3_readRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl); +} +static REG8 IOINPCALL ym_i148a(UINT port) //Advanced FM Music Status Port +{ + TRACEOUT(("%x read",port)); + return opl3_readStatus(&g_opl3[G_OPL3_INDEX]); +} + +static REG8 IOINPCALL ym_i148b(UINT port) // ??? +{ + TRACEOUT(("%x read",port)); + return opl3_readExtendedRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrh); +} + +/*********** PC-9801-118 config I/O ? ***********/ + +REG8 sound118 = 0x05; +static void IOOUTCALL csctrl_o148e(UINT port, REG8 dat) { + TRACEOUT(("write %x %x",port,dat)); + sound118 = dat; +} + +static REG8 IOINPCALL csctrl_i148e(UINT port) { + return(sound118); + TRACEOUT(("%x read",port)); +} +REG8 control118; +static REG8 IOINPCALL csctrl_i148f(UINT port) { + TRACEOUT(("%x read",port)); + (void)port; + //if(sound118 == 0) return(0xf0);//PC-9801-118は3だけどYMFは0xff 2000はこれだけじゃまだダメ + if(sound118 == 0) return(0xf3);//PC-9801-118は3だけどYMFは0xff 2000はこれだけじゃまだダメ + if(sound118 == 0x05){ + if(control118==4)return 4; + if(control118==0x0c) return 4; + if(control118==0)return 0; + } + if(sound118 == 0x04) return (0x00); + if(sound118 == 0x21){ + switch(10/*mpu98.irqnum2*/){//MIDI割り込み 00:IRQ10 01:IRQ6 02:IRQ5 03:IRQ3 + case 10:return 0; + case 6: return 1; + case 5: return 2; + case 3: return 3; + default: return 0; + } + } + if(sound118 == 0xff) return (0x05);//bit0 MIDI割り込みあり bit1:Cb Na7 bit2:Mate-X bit3:A-Mate Ce2 + else + return(0xff); +} + +static void IOOUTCALL csctrl_o148f(UINT port, REG8 dat) { + TRACEOUT(("write %x %x",port,dat)); + + //if (sound118 == 0x21) switch(dat){ + // case 0:mpu98.irqnum2 = 10;break; + // case 1:mpu98.irqnum2 = 6;break; + // case 2:mpu98.irqnum2 = 5;break; + // case 3:mpu98.irqnum2 = 3;break; + // default: break; + //} + control118 = dat; +} + +static REG8 IOINPCALL csctrl_i486(UINT port) { + return(0); +} + +// ---- MAME使用の場合のPCM再生 +#ifdef USE_MAME +static SINT32 oplfm_softvolume_L = 0; +static SINT32 oplfm_softvolume_R = 0; +static SINT32 oplfm_softvolumereg_L = 0xff; +static SINT32 oplfm_softvolumereg_R = 0xff; +#define OPL3_SAMPLE_BUFFER 4096 +static INT16 oplfm_s1ls[OPL3_SAMPLE_BUFFER] = { 0 }; +static INT16 oplfm_s1rs[OPL3_SAMPLE_BUFFER] = { 0 }; +static INT16 oplfm_s2ls[OPL3_SAMPLE_BUFFER] = { 0 }; +static INT16 oplfm_s2rs[OPL3_SAMPLE_BUFFER] = { 0 }; +static void SOUNDCALL opl3gen_getpcm2(void* opl3, SINT32 *pcm, UINT count) { + UINT i; + INT16 *buf[4]; + INT16 s1l,s1r,s2l,s2r; + SINT32 oplfm_volume; + SINT32 *outbuf = pcm; + SINT32 volL, volR; + buf[0] = oplfm_s1ls; + buf[1] = oplfm_s1rs; + buf[2] = oplfm_s2ls; + buf[3] = oplfm_s2rs; + + // NP2グローバルFMボリューム(0~127) + oplfm_volume = np2cfg.vol_fm * np2cfg.vol_master / 100; + + // Canbe/ValueStarミキサー FMボリューム(0~31) bit7:1=mute, bit6-5:reserved, bit4-0:volume(00000b max, 11111b min) + if(oplfm_softvolumereg_L != cs4231.devvolume[0x30]){ + oplfm_softvolumereg_L = cs4231.devvolume[0x30]; + if(oplfm_softvolumereg_L & 0x80){ // FM L Mute + oplfm_softvolume_L = 0; + }else{ + oplfm_softvolume_L = ((~oplfm_softvolumereg_L) & 0x1f); // FM L Volume + } + } + if(oplfm_softvolumereg_R != cs4231.devvolume[0x31]){ + oplfm_softvolumereg_R = cs4231.devvolume[0x31]; + if(oplfm_softvolumereg_R & 0x80){ // FM R Mute + oplfm_softvolume_R = 0; + }else{ + oplfm_softvolume_R = ((~oplfm_softvolumereg_R) & 0x1f); // FM R Volume + } + } + + // PCMサウンドバッファに送る + volL = oplfm_volume * oplfm_softvolume_L; + volR = oplfm_volume * oplfm_softvolume_R; + while (count > 0) { + int cc = MIN(count, OPL3_SAMPLE_BUFFER); + YMF262UpdateOne(opl3, buf, cc); + for (i = 0; i < cc; i++) { + outbuf[0] += (((SINT32)oplfm_s1ls[i] * volL) >> 9); + outbuf[1] += (((SINT32)oplfm_s1rs[i] * volR) >> 9); + outbuf += 2; + } + count -= cc; + } +} +static void SOUNDCALL opl3gen_getpcm2_dummy(void* opl3, SINT32* pcm, UINT count) { + UINT i; + INT16* buf[4]; + INT16 s1l, s1r, s2l, s2r; + buf[0] = oplfm_s1ls; + buf[1] = oplfm_s1rs; + buf[2] = oplfm_s2ls; + buf[3] = oplfm_s2rs; + while (count > 0) { + int cc = MIN(count, OPL3_SAMPLE_BUFFER); + YMF262UpdateOne(opl3, buf, cc); + count -= cc; + } +} +#endif + +static const IOOUT ymf_o[4] = { + ymf_o188, ymf_o18a, ymf_o18c, ymf_o18e}; + +static const IOINP ymf_i[4] = { + ymf_i188, ymf_i18a, ymf_i18c, NULL}; + +/** + * Reset + * @param[in] pConfig A pointer to a configure structure + */ +void board118_reset(const NP2CFG *pConfig) +{ + + // 86音源と共存させる場合、使用するNP2 OPNA番号を変える + if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_WAVESTAR || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ + opna_idx = 1; + }else{ + opna_idx = 0; + } + + // OPNAリセット + opna_reset(&g_opna[opna_idx], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_S98); + if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ + // OPNAタイマーをセットしない + //opna_timer(&g_opna[opna_idx], 0x10, NEVENT_FMTIMERA, NEVENT_FMTIMERB); + }else{ + // OPNAタイマーをセット + UINT irqval = 0x00; + UINT8 irqf = np2cfg.snd118irqf; + if (g_nSoundID == SOUNDID_WAVESTAR) + { + irqf = 0xc; // IRQ12固定 + } + if(g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ + UINT8 irq86table[4] = {0x03, 0x0d, 0x0a, 0x0c}; + UINT8 nIrq86 = (np2cfg.snd86opt & 0x10) | ((np2cfg.snd86opt & 0x4) << 5) | ((np2cfg.snd86opt & 0x8) << 3); + UINT8 irq86 = irq86table[nIrq86 >> 6]; + irqf = np2cfg.snd118irqp; + if(irqf == irq86){ + if(irq86!=3){ + irqf = 0x3; + }else{ + irqf = 0xC; + } + } + } + switch(irqf){ + case 3: + irqval = 0x10|(0 << 6); + break; + case 10: + irqval = 0x10|(2 << 6); + break; + case 12: + irqval = 0x10|(3 << 6); + break; + case 13: + irqval = 0x10|(1 << 6); + break; + } + if(opna_idx == 1){ + opna_timer(&g_opna[opna_idx], irqval, NEVENT_FMTIMER2A, NEVENT_FMTIMER2B); + }else{ + opna_timer(&g_opna[opna_idx], irqval, NEVENT_FMTIMERA, NEVENT_FMTIMERB); + } + + // OPLリセット + opl3_reset(&g_opl3[G_OPL3_INDEX], OPL3_HAS_OPL3L|OPL3_HAS_OPL3); + opngen_setcfg(&g_opna[opna_idx].opngen, 3, OPN_STEREO | 0x038); + } + + // CS4231リセット + cs4231io_reset(); + + // 86+118の場合、被らないように修正 + if(g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ + UINT16 snd86iobase = (pConfig->snd86opt & 0x01) ? 0x000 : 0x100; + if(np2cfg.snd118io == 0x188 + snd86iobase){ + cs4231.port[4] += 0x100; + } + } + + // 86音源+118音源の場合、118側をはじめからFM6音にする + if(g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ + cs4231.extfunc |= 1; + extendchannel(1); + } + + // 色々設定 + if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ + }else{ + if(pConfig->snd118rom && g_nSoundID!=SOUNDID_PC_9801_86_118 && g_nSoundID!=SOUNDID_PC_9801_86_118_SB16){ + soundrom_load(0xcc000, OEMTEXT("118")); + } + fmboard_extreg(extendchannel); +#ifdef SUPPORT_SOUND_SB16 +#ifdef USE_MAME + if (g_mame_opl3[G_OPL3_INDEX]) { + if (samplerate != soundcfg.rate) { + YMF262Shutdown(g_mame_opl3[G_OPL3_INDEX]); + g_mame_opl3[G_OPL3_INDEX] = YMF262Init(14400000, soundcfg.rate); + samplerate = soundcfg.rate; + } else { + YMF262ResetChip(g_mame_opl3[G_OPL3_INDEX], samplerate); + } + } + //ZeroMemory(&g_sb16, sizeof(g_sb16)); + //// ボードデフォルト IO:D2 DMA:3 INT:5 + //g_sb16.base = 0xd2; + //g_sb16.dmach = 0x3; + //g_sb16.dmairq = 0x5; +#endif +#endif + //cs4231.extfunc = 0x01; + //extendchannel((REG8)(cs4231.extfunc & 1)); + } + + // WaveStarの場合、ボリューム初期化 + if(g_nSoundID==SOUNDID_WAVESTAR){ + // FM音量 + cs4231.devvolume[0xff] = 0xf; + opngen_setvol(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + psggen_setvol(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + rhythm_setvol(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); +#if defined(SUPPORT_FMGEN) + if(np2cfg.usefmgen) { + opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + } +#endif + oplgen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); + } + (void)pConfig; +} + +/** + * Bind + */ +void board118_bind(void) +{ + // CS4231バインド(I/Oポート割り当てとか) + cs4231io_bind(); + + // 86音源と共存させる場合、使用するNP2 OPNA番号を変える + if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_WAVESTAR || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ + opna_idx = 1; + }else{ + opna_idx = 0; + } + + if(g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ + a460_soundid = np2cfg.sndwssid;//0x70; + }else if(g_nSoundID==SOUNDID_WAVESTAR){ + a460_soundid = 0x41; + }else{ + a460_soundid = np2cfg.snd118id;//0x80; + } + + if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ + // Mate-X PCMの場合、CS4231だけ + iocore_attachout(cs4231.port[1], ymf_oa460); + iocore_attachinp(cs4231.port[1], ymf_ia460); + iocore_attachinp(0x881e, wss_i881e); + }else if(g_nSoundID==SOUNDID_WAVESTAR){ + // WaveStarの場合 なにもない + }else{ + // 118音源の場合、色々割り当て + + // OPNA割り当て + if(cs4231.port[4]){ + opna_bind(&g_opna[opna_idx]); + cbuscore_attachsndex(cs4231.port[4],ymf_o, ymf_i); + } + +#if defined(SUPPORT_GAMEPORT) + // ゲームポート割り当て 1480h~1487hどこでも良いらしい + if(np2cfg.gameport){ + int i; + for(i=0;i<=7;i++){ + iocore_attachout(0x1480+i, gameport_o1480); + iocore_attachinp(0x1480+i, gameport_i1480); + } + } +#endif + + // OPL割り当て +#ifdef USE_MAME + iocore_attachout(cs4231.port[9], sb16_o20d2); + iocore_attachinp(cs4231.port[9], sb16_i20d2); + iocore_attachout(cs4231.port[9]+1, sb16_o21d2); + iocore_attachout(cs4231.port[9]+2, sb16_o22d2); + iocore_attachinp(cs4231.port[9]+2, sb16_i22d2); + iocore_attachout(cs4231.port[9]+3, sb16_o23d2); + + if (!g_mame_opl3[G_OPL3_INDEX]) { + g_mame_opl3[G_OPL3_INDEX] = YMF262Init(14400000, np2cfg.samplingrate); + samplerate = np2cfg.samplingrate; + } + if (g_opl3[G_OPL3_INDEX].userdata) { + // 外部音源を使用する場合 ダミー登録 + sound_streamregist(g_mame_opl3[G_OPL3_INDEX], (SOUNDCB)opl3gen_getpcm2_dummy); + } + else { + // 外部音源を使用しない場合 PCM登録 + sound_streamregist(g_mame_opl3[G_OPL3_INDEX], (SOUNDCB)opl3gen_getpcm2); + } +#else + iocore_attachout(cs4231.port[9], ym_o1488); + iocore_attachinp(cs4231.port[9], ym_i1488); + iocore_attachout(cs4231.port[9]+1, ym_o1489); + iocore_attachout(cs4231.port[9]+2, ym_o148a); + iocore_attachout(cs4231.port[9]+3, ym_o148b); +#endif + opl3_bind(&g_opl3[G_OPL3_INDEX]); // MAME使用の場合Key Display用 + + // Sound ID I/O port割り当て + iocore_attachout(cs4231.port[1], ymf_oa460); + iocore_attachinp(cs4231.port[1], ymf_ia460); + + // SRN-F寄生 I/O port割り当て + //iocore_attachout(cs4231.port[15],srnf_oa460);//SRN-Fは必要なときだけ使う + //iocore_attachinp(cs4231.port[15],srnf_ia460); + //srnf = 0x81; + + // WaveStar I/O port割り当て + if(g_nSoundID==SOUNDID_WAVESTAR){ + iocore_attachout(0x4d2 ,wavestar_o4d2); + iocore_attachinp(0x4d2 ,wavestar_i4d2); + } + + // PC-9801-118 config I/O port割り当て + iocore_attachout(cs4231.port[14],csctrl_o148e); + iocore_attachinp(cs4231.port[14],csctrl_i148e); + iocore_attachout(cs4231.port[14]+1,csctrl_o148f); + iocore_attachinp(cs4231.port[14]+1,csctrl_i148f); + + // YMF-701 I/O port割り当て + iocore_attachout(cs4231.port[6], wss_o548e);// YMF-701 + iocore_attachinp(cs4231.port[6], wss_i548e);// YMF-701 + iocore_attachinp(cs4231.port[6]+1, wss_i548f);// YMF-701 + + // PC-9801-118 control? I/O port割り当て + iocore_attachinp(cs4231.port[11]+6,csctrl_i486); + iocore_attachinp(0x881e, wss_i881e); + + // MIDI I/O port割り当て mpu98ii.c側で調整 + //iocore_attachout(cs4231.port[10], mpu98ii_o0); + //iocore_attachinp(cs4231.port[10], mpu98ii_i0); + //iocore_attachout(cs4231.port[10]+1, mpu98ii_o2); + //iocore_attachinp(cs4231.port[10]+1, mpu98ii_i2); + //mpu98.irqnum = mpu98.irqnum2; + + } +} +void board118_unbind(void) +{ + cs4231io_unbind(); + + if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ + // Mate-X PCMの場合、CS4231だけ + iocore_detachout(cs4231.port[1]); + iocore_detachinp(cs4231.port[1]); + iocore_detachinp(0x881e); + }else if(g_nSoundID==SOUNDID_WAVESTAR){ + // WaveStarの場合 なにもない + }else{ + // 118音源の場合、色々割り当て + + // OPNA割り当て + if(cs4231.port[4]){ + cbuscore_detachsndex(cs4231.port[4]); + } + +#if defined(SUPPORT_GAMEPORT) + // ゲームポート割り当て 1480h~1487hどこでも良いらしい + if(np2cfg.gameport){ + int i; + for(i=0;i<=7;i++){ + iocore_detachout(0x1480+i); + iocore_detachinp(0x1480+i); + } + } +#endif + + // OPL割り当て + iocore_detachout(cs4231.port[9]); + iocore_detachinp(cs4231.port[9]); + iocore_detachout(cs4231.port[9]+1); + iocore_detachout(cs4231.port[9]+2); + iocore_detachout(cs4231.port[9]+3); + + // Sound ID I/O port割り当て + iocore_detachout(cs4231.port[1]); + iocore_detachinp(cs4231.port[1]); + + // SRN-F寄生 I/O port割り当て + //iocore_detachout(cs4231.port[15]);//SRN-Fは必要なときだけ使う + //iocore_detachinp(cs4231.port[15]); + + // PC-9801-118 config I/O port割り当て + iocore_detachout(cs4231.port[14]); + iocore_detachinp(cs4231.port[14]); + iocore_detachout(cs4231.port[14]+1); + iocore_detachinp(cs4231.port[14]+1); + + // YMF-701 I/O port割り当て + iocore_detachout(cs4231.port[6]);// YMF-701 + iocore_detachinp(cs4231.port[6]);// YMF-701 + iocore_detachinp(cs4231.port[6]+1);// YMF-701 + + // PC-9801-118 control? I/O port割り当て + iocore_detachinp(cs4231.port[11]+6); + iocore_detachinp(0x881e); + + // MIDI I/O port割り当て mpu98ii.c側で調整 + //iocore_detachout(cs4231.port[10]); + //iocore_detachinp(cs4231.port[10]); + //iocore_detachout(cs4231.port[10]+1); + //iocore_detachinp(cs4231.port[10]+1); + + } +} +void board118_finalize(void) +{ +#ifdef USE_MAME + if (g_mame_opl3[G_OPL3_INDEX]) { + YMF262Shutdown(g_mame_opl3[G_OPL3_INDEX]); + g_mame_opl3[G_OPL3_INDEX] = NULL; + } +#endif +} diff --git a/cbus/board118.h b/cbus/board118.h old mode 100755 new mode 100644 index 9d3a3151..6d8037e1 --- a/cbus/board118.h +++ b/cbus/board118.h @@ -1,22 +1,22 @@ -/** - * @file board118.h - * @brief Interface of PC-9801-118 - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -void board118_reset(const NP2CFG *pConfig); -void board118_bind(void); -void board118_unbind(void); -void board118_finalize(void); - -#ifdef __cplusplus -} -#endif +/** + * @file board118.h + * @brief Interface of PC-9801-118 + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +void board118_reset(const NP2CFG *pConfig); +void board118_bind(void); +void board118_unbind(void); +void board118_finalize(void); + +#ifdef __cplusplus +} +#endif diff --git a/cbus/board14.c b/cbus/board14.c old mode 100755 new mode 100644 index 33a00c76..b2fb4c9a --- a/cbus/board14.c +++ b/cbus/board14.c @@ -1,255 +1,255 @@ -/** - * @file board14.c - * @brief Implementation of PC-9801-14 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* どうも 8253C-2は 4MHz/16らすい? */ -/* とりあえず 1996800/8を入力してみる... (ver0.71) */ - - MUSICGEN g_musicgen; -static _TMS3631 s_tms3631; - -/* ---- 8253C-2 */ - -/** - * Get counter - * @return The counter - */ -UINT board14_pitcount(void) -{ - SINT32 clk; - - clk = nevent_getremain(NEVENT_MUSICGEN); - if (clk >= 0) - { - clk /= pccore.multiple; - clk /= 8; - if (!(pccore.cpumode & CPUMODE_8MHZ)) - { - clk = clk * 13 / 16; - } - return clk; - } - return 0; -} - - -/* ---- intr */ - -static void setmusicgenevent(UINT32 cnt, NEVENTPOSITION absolute) -{ - if (cnt > 4) /* 根拠なし */ - { - cnt *= pccore.multiple; - } - else - { - cnt = pccore.multiple << 16; - } - if (!(pccore.cpumode & CPUMODE_8MHZ)) - { - cnt = cnt * 16 / 13; /* cnt * 2457600 / 1996800 */ - } - cnt *= 8; - nevent_set(NEVENT_MUSICGEN, cnt, musicgenint, absolute); -} - -/** - * Interrupt - * @param[in] item A pointer to an event-item structure - */ -void musicgenint(NEVENTITEM item) -{ - PITCH pitch; - - if (item->flag & NEVENT_SETEVENT) - { - pitch = pit.ch + 3; - if ((pitch->ctrl & 0x0c) == 0x04) - { - /* レートジェネレータ */ - setmusicgenevent(pitch->value, NEVENT_RELATIVE); - } - } - pic_setirq(0x0c); -} - - -/* ---- I/O */ - -static void IOOUTCALL musicgen_o088(UINT port, REG8 dat) -{ - g_musicgen.porta = dat; - (void)port; -} - -static void IOOUTCALL musicgen_o08a(UINT port, REG8 dat) -{ - g_musicgen.portb = dat; - (void)port; -} - -static void IOOUTCALL musicgen_o08c(UINT port, REG8 dat) -{ - if (dat & 0x80) - { - if (!(g_musicgen.portc & 0x80)) - { - g_musicgen.sync = 1; - g_musicgen.ch = 0; - } - else if (g_musicgen.sync) - { - g_musicgen.sync = 0; - sound_sync(); - g_musicgen.key[g_musicgen.ch] = dat; - tms3631_setkey(&s_tms3631, (REG8)g_musicgen.ch, dat); - } - else if ((!(dat & 0x40)) && (g_musicgen.portc & 0x40)) - { - g_musicgen.sync = 1; - g_musicgen.ch = (g_musicgen.ch + 1) & 7; - } - } - g_musicgen.portc = dat; - (void)port; -} - -static void IOOUTCALL musicgen_o188(UINT port, REG8 dat) -{ - sound_sync(); - g_musicgen.mask = dat; - tms3631_setenable(&s_tms3631, dat); - (void)port; -} - -static void IOOUTCALL musicgen_o18c(UINT port, REG8 dat) -{ - PITCH pitch; - - pitch = pit.ch + 3; - if (!pit_setcount(pitch, dat)) - { - setmusicgenevent(pitch->value, NEVENT_ABSOLUTE); - } - (void)port; -} - -static void IOOUTCALL musicgen_o18e(UINT port, REG8 dat) -{ - pit_setflag(pit.ch + 3, dat); - (void)port; -} - -static REG8 IOINPCALL musicgen_i088(UINT port) -{ - (void)port; - return g_musicgen.porta; -} - -static REG8 IOINPCALL musicgen_i08a(UINT port) -{ - (void)port; - return g_musicgen.portb; -} - -static REG8 IOINPCALL musicgen_i08c(UINT port) -{ - (void)port; - return g_musicgen.portc; -} - -static REG8 IOINPCALL musicgen_i08e(UINT port) -{ - - (void)port; - return 0x08; -} - -static REG8 IOINPCALL musicgen_i188(UINT port) -{ - (void)port; - return g_musicgen.mask; -} - -static REG8 IOINPCALL musicgen_i18c(UINT port) -{ - (void)port; - return pit_getstat(pit.ch + 3); -} - -static REG8 IOINPCALL musicgen_i18e(UINT port) -{ - (void)port; - return 0x80; /* INT-5 */ -} - - -/* ---- interface */ - -static const IOOUT musicgen_o0[4] = { - musicgen_o088, musicgen_o08a, musicgen_o08c, NULL}; - -static const IOOUT musicgen_o1[4] = { - musicgen_o188, musicgen_o188, musicgen_o18c, musicgen_o18e}; - -static const IOINP musicgen_i0[4] = { - musicgen_i088, musicgen_i08a, musicgen_i08c, musicgen_i08e}; - -static const IOINP musicgen_i1[4] = { - musicgen_i188, musicgen_i188, musicgen_i18c, musicgen_i18e}; - - -/** - * Reset - * @param[in] pConfig A pointer to a configure structure - * @param[in] bEnable Indicates whether to enable or disable the board - */ -void board14_reset(const NP2CFG *pConfig, BOOL bEnable) -{ - memset(&g_musicgen, 0, sizeof(g_musicgen)); - tms3631_reset(&s_tms3631); - - if (bEnable) - { - soundrom_load(0xcc000, OEMTEXT("14")); - } - (void)pConfig; -} - -/** - * Bind - */ -void board14_bind(void) -{ - sound_streamregist(&s_tms3631, (SOUNDCB)tms3631_getpcm); - cbuscore_attachsndex(0x088, musicgen_o0, musicgen_i0); - cbuscore_attachsndex(0x188, musicgen_o1, musicgen_i1); -} -void board14_unbind(void) -{ - cbuscore_detachsndex(0x088); - cbuscore_detachsndex(0x188); -} - -/** - * Restore - */ -void board14_allkeymake(void) -{ - REG8 i; - - for (i = 0; i < 8; i++) - { - tms3631_setkey(&s_tms3631, i, g_musicgen.key[i]); - } -} +/** + * @file board14.c + * @brief Implementation of PC-9801-14 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* どうも 8253C-2は 4MHz/16らすい? */ +/* とりあえず 1996800/8を入力してみる... (ver0.71) */ + + MUSICGEN g_musicgen; +static _TMS3631 s_tms3631; + +/* ---- 8253C-2 */ + +/** + * Get counter + * @return The counter + */ +UINT board14_pitcount(void) +{ + SINT32 clk; + + clk = nevent_getremain(NEVENT_MUSICGEN); + if (clk >= 0) + { + clk /= pccore.multiple; + clk /= 8; + if (!(pccore.cpumode & CPUMODE_8MHZ)) + { + clk = clk * 13 / 16; + } + return clk; + } + return 0; +} + + +/* ---- intr */ + +static void setmusicgenevent(UINT32 cnt, NEVENTPOSITION absolute) +{ + if (cnt > 4) /* 根拠なし */ + { + cnt *= pccore.multiple; + } + else + { + cnt = pccore.multiple << 16; + } + if (!(pccore.cpumode & CPUMODE_8MHZ)) + { + cnt = cnt * 16 / 13; /* cnt * 2457600 / 1996800 */ + } + cnt *= 8; + nevent_set(NEVENT_MUSICGEN, cnt, musicgenint, absolute); +} + +/** + * Interrupt + * @param[in] item A pointer to an event-item structure + */ +void musicgenint(NEVENTITEM item) +{ + PITCH pitch; + + if (item->flag & NEVENT_SETEVENT) + { + pitch = pit.ch + 3; + if ((pitch->ctrl & 0x0c) == 0x04) + { + /* レートジェネレータ */ + setmusicgenevent(pitch->value, NEVENT_RELATIVE); + } + } + pic_setirq(0x0c); +} + + +/* ---- I/O */ + +static void IOOUTCALL musicgen_o088(UINT port, REG8 dat) +{ + g_musicgen.porta = dat; + (void)port; +} + +static void IOOUTCALL musicgen_o08a(UINT port, REG8 dat) +{ + g_musicgen.portb = dat; + (void)port; +} + +static void IOOUTCALL musicgen_o08c(UINT port, REG8 dat) +{ + if (dat & 0x80) + { + if (!(g_musicgen.portc & 0x80)) + { + g_musicgen.sync = 1; + g_musicgen.ch = 0; + } + else if (g_musicgen.sync) + { + g_musicgen.sync = 0; + sound_sync(); + g_musicgen.key[g_musicgen.ch] = dat; + tms3631_setkey(&s_tms3631, (REG8)g_musicgen.ch, dat); + } + else if ((!(dat & 0x40)) && (g_musicgen.portc & 0x40)) + { + g_musicgen.sync = 1; + g_musicgen.ch = (g_musicgen.ch + 1) & 7; + } + } + g_musicgen.portc = dat; + (void)port; +} + +static void IOOUTCALL musicgen_o188(UINT port, REG8 dat) +{ + sound_sync(); + g_musicgen.mask = dat; + tms3631_setenable(&s_tms3631, dat); + (void)port; +} + +static void IOOUTCALL musicgen_o18c(UINT port, REG8 dat) +{ + PITCH pitch; + + pitch = pit.ch + 3; + if (!pit_setcount(pitch, dat)) + { + setmusicgenevent(pitch->value, NEVENT_ABSOLUTE); + } + (void)port; +} + +static void IOOUTCALL musicgen_o18e(UINT port, REG8 dat) +{ + pit_setflag(pit.ch + 3, dat); + (void)port; +} + +static REG8 IOINPCALL musicgen_i088(UINT port) +{ + (void)port; + return g_musicgen.porta; +} + +static REG8 IOINPCALL musicgen_i08a(UINT port) +{ + (void)port; + return g_musicgen.portb; +} + +static REG8 IOINPCALL musicgen_i08c(UINT port) +{ + (void)port; + return g_musicgen.portc; +} + +static REG8 IOINPCALL musicgen_i08e(UINT port) +{ + + (void)port; + return 0x08; +} + +static REG8 IOINPCALL musicgen_i188(UINT port) +{ + (void)port; + return g_musicgen.mask; +} + +static REG8 IOINPCALL musicgen_i18c(UINT port) +{ + (void)port; + return pit_getstat(pit.ch + 3); +} + +static REG8 IOINPCALL musicgen_i18e(UINT port) +{ + (void)port; + return 0x80; /* INT-5 */ +} + + +/* ---- interface */ + +static const IOOUT musicgen_o0[4] = { + musicgen_o088, musicgen_o08a, musicgen_o08c, NULL}; + +static const IOOUT musicgen_o1[4] = { + musicgen_o188, musicgen_o188, musicgen_o18c, musicgen_o18e}; + +static const IOINP musicgen_i0[4] = { + musicgen_i088, musicgen_i08a, musicgen_i08c, musicgen_i08e}; + +static const IOINP musicgen_i1[4] = { + musicgen_i188, musicgen_i188, musicgen_i18c, musicgen_i18e}; + + +/** + * Reset + * @param[in] pConfig A pointer to a configure structure + * @param[in] bEnable Indicates whether to enable or disable the board + */ +void board14_reset(const NP2CFG *pConfig, BOOL bEnable) +{ + memset(&g_musicgen, 0, sizeof(g_musicgen)); + tms3631_reset(&s_tms3631); + + if (bEnable) + { + soundrom_load(0xcc000, OEMTEXT("14")); + } + (void)pConfig; +} + +/** + * Bind + */ +void board14_bind(void) +{ + sound_streamregist(&s_tms3631, (SOUNDCB)tms3631_getpcm); + cbuscore_attachsndex(0x088, musicgen_o0, musicgen_i0); + cbuscore_attachsndex(0x188, musicgen_o1, musicgen_i1); +} +void board14_unbind(void) +{ + cbuscore_detachsndex(0x088); + cbuscore_detachsndex(0x188); +} + +/** + * Restore + */ +void board14_allkeymake(void) +{ + REG8 i; + + for (i = 0; i < 8; i++) + { + tms3631_setkey(&s_tms3631, i, g_musicgen.key[i]); + } +} diff --git a/cbus/board14.h b/cbus/board14.h old mode 100755 new mode 100644 index 394c765e..e57f6c93 --- a/cbus/board14.h +++ b/cbus/board14.h @@ -1,53 +1,53 @@ -/** - * @file board14.h - * @brief Interface of PC-9801-14 - */ - -#pragma once - -/** - * @breif The sturecture of PC-9801-14 - */ -struct musicgen_t -{ - UINT8 porta; - UINT8 portb; - UINT8 portc; - UINT8 mask; - UINT8 key[8]; - int sync; - int ch; -}; -struct musicgen_old_t // ステートセーブ互換性維持用(変更禁止) -{ - UINT8 porta; - UINT8 portb; - UINT8 portc; - UINT8 mask; - UINT8 key[8]; - int sync; - int ch; -}; - -typedef struct musicgen_t MUSICGEN; -typedef struct musicgen_old_t MUSICGEN_OLD; - -#ifdef __cplusplus -extern "C" -{ -#endif - -extern MUSICGEN g_musicgen; - -void musicgenint(NEVENTITEM item); -UINT board14_pitcount(void); - -void board14_allkeymake(void); - -void board14_reset(const NP2CFG *pConfig, BOOL bEnable); -void board14_bind(void); -void board14_unbind(void); - -#ifdef __cplusplus -} -#endif +/** + * @file board14.h + * @brief Interface of PC-9801-14 + */ + +#pragma once + +/** + * @breif The sturecture of PC-9801-14 + */ +struct musicgen_t +{ + UINT8 porta; + UINT8 portb; + UINT8 portc; + UINT8 mask; + UINT8 key[8]; + int sync; + int ch; +}; +struct musicgen_old_t // ステートセーブ互換性維持用(変更禁止) +{ + UINT8 porta; + UINT8 portb; + UINT8 portc; + UINT8 mask; + UINT8 key[8]; + int sync; + int ch; +}; + +typedef struct musicgen_t MUSICGEN; +typedef struct musicgen_old_t MUSICGEN_OLD; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern MUSICGEN g_musicgen; + +void musicgenint(NEVENTITEM item); +UINT board14_pitcount(void); + +void board14_allkeymake(void); + +void board14_reset(const NP2CFG *pConfig, BOOL bEnable); +void board14_bind(void); +void board14_unbind(void); + +#ifdef __cplusplus +} +#endif diff --git a/cbus/board26k.c b/cbus/board26k.c old mode 100755 new mode 100644 index 5d010b50..27bfddbc --- a/cbus/board26k.c +++ b/cbus/board26k.c @@ -1,87 +1,87 @@ -/** - * @file board26k.c - * @brief Implementation of PC-9801-26K - */ - -#include -#include -#include -#include -#include -#include -#include - -static void IOOUTCALL opn_o188(UINT port, REG8 dat) -{ - g_opna[0].s.addrl = dat; - g_opna[0].s.data = dat; - (void)port; -} - -static void IOOUTCALL opn_o18a(UINT port, REG8 dat) -{ - g_opna[0].s.data = dat; - opna_writeRegister(&g_opna[0], g_opna[0].s.addrl, dat); - - (void)port; -} - -static REG8 IOINPCALL opn_i188(UINT port) -{ - (void)port; - return g_opna[0].s.status; -} - -static REG8 IOINPCALL opn_i18a(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[0].s.addrl; - if (nAddress == 0x0e) - { - return fmboard_getjoy(&g_opna[0]); - } - else if (nAddress < 0x10) - { - return opna_readRegister(&g_opna[0], nAddress); - } - - (void)port; - return g_opna[0].s.data; -} - - -// ---- - -static const IOOUT opn_o[4] = { - opn_o188, opn_o18a, NULL, NULL}; - -static const IOINP opn_i[4] = { - opn_i188, opn_i18a, NULL, NULL}; - -/** - * Reset - * @param[in] pConfig A pointer to a configure structure - */ -void board26k_reset(const NP2CFG *pConfig) -{ - opna_reset(&g_opna[0], OPNA_MODE_2203 | OPNA_HAS_TIMER | OPNA_S98); - opna_timer(&g_opna[0], (pConfig->snd26opt & 0xc0) | 0x10, NEVENT_FMTIMERA, NEVENT_FMTIMERB); - - opngen_setcfg(&g_opna[0].opngen, 3, 0x00); - soundrom_loadex(pConfig->snd26opt & 7, OEMTEXT("26")); - g_opna[0].s.base = (pConfig->snd26opt & 0x10) ? 0x000 : 0x100; -} - -/** - * Bind - */ -void board26k_bind(void) -{ - opna_bind(&g_opna[0]); - cbuscore_attachsndex(0x188 - g_opna[0].s.base, opn_o, opn_i); -} -void board26k_unbind(void) -{ - cbuscore_detachsndex(0x188 - g_opna[0].s.base); -} +/** + * @file board26k.c + * @brief Implementation of PC-9801-26K + */ + +#include +#include +#include +#include +#include +#include +#include + +static void IOOUTCALL opn_o188(UINT port, REG8 dat) +{ + g_opna[0].s.addrl = dat; + g_opna[0].s.data = dat; + (void)port; +} + +static void IOOUTCALL opn_o18a(UINT port, REG8 dat) +{ + g_opna[0].s.data = dat; + opna_writeRegister(&g_opna[0], g_opna[0].s.addrl, dat); + + (void)port; +} + +static REG8 IOINPCALL opn_i188(UINT port) +{ + (void)port; + return g_opna[0].s.status; +} + +static REG8 IOINPCALL opn_i18a(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[0].s.addrl; + if (nAddress == 0x0e) + { + return fmboard_getjoy(&g_opna[0]); + } + else if (nAddress < 0x10) + { + return opna_readRegister(&g_opna[0], nAddress); + } + + (void)port; + return g_opna[0].s.data; +} + + +// ---- + +static const IOOUT opn_o[4] = { + opn_o188, opn_o18a, NULL, NULL}; + +static const IOINP opn_i[4] = { + opn_i188, opn_i18a, NULL, NULL}; + +/** + * Reset + * @param[in] pConfig A pointer to a configure structure + */ +void board26k_reset(const NP2CFG *pConfig) +{ + opna_reset(&g_opna[0], OPNA_MODE_2203 | OPNA_HAS_TIMER | OPNA_S98); + opna_timer(&g_opna[0], (pConfig->snd26opt & 0xc0) | 0x10, NEVENT_FMTIMERA, NEVENT_FMTIMERB); + + opngen_setcfg(&g_opna[0].opngen, 3, 0x00); + soundrom_loadex(pConfig->snd26opt & 7, OEMTEXT("26")); + g_opna[0].s.base = (pConfig->snd26opt & 0x10) ? 0x000 : 0x100; +} + +/** + * Bind + */ +void board26k_bind(void) +{ + opna_bind(&g_opna[0]); + cbuscore_attachsndex(0x188 - g_opna[0].s.base, opn_o, opn_i); +} +void board26k_unbind(void) +{ + cbuscore_detachsndex(0x188 - g_opna[0].s.base); +} diff --git a/cbus/board26k.h b/cbus/board26k.h old mode 100755 new mode 100644 index a24ac65e..cf202d41 --- a/cbus/board26k.h +++ b/cbus/board26k.h @@ -1,21 +1,21 @@ -/** - * @file board26k.h - * @brief Interface of PC-9801-26K - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -void board26k_reset(const NP2CFG *pConfig); -void board26k_bind(void); -void board26k_unbind(void); - -#ifdef __cplusplus -} -#endif +/** + * @file board26k.h + * @brief Interface of PC-9801-26K + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +void board26k_reset(const NP2CFG *pConfig); +void board26k_bind(void); +void board26k_unbind(void); + +#ifdef __cplusplus +} +#endif diff --git a/cbus/board86.c b/cbus/board86.c old mode 100755 new mode 100644 index 9677f5ef..b3cd381f --- a/cbus/board86.c +++ b/cbus/board86.c @@ -1,189 +1,189 @@ -/** - * @file board86.c - * @brief Implementation of PC-9801-86 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static void IOOUTCALL opna_o188(UINT port, REG8 dat) -{ - g_opna[0].s.addrl = dat; - g_opna[0].s.data = dat; - (void)port; -} - -static void IOOUTCALL opna_o18a(UINT port, REG8 dat) -{ - - g_opna[0].s.data = dat; - - opna_writeRegister(&g_opna[0], g_opna[0].s.addrl, dat); - - (void)port; -} - -static void IOOUTCALL opna_o18c(UINT port, REG8 dat) -{ - if (g_opna[0].s.extend) - { - g_opna[0].s.addrh = dat; - g_opna[0].s.data = dat; - } - - (void)port; -} - -static void IOOUTCALL opna_o18e(UINT port, REG8 dat) -{ - if (g_opna[0].s.extend) - { - g_opna[0].s.data = dat; - opna_writeExtendedRegister(&g_opna[0], g_opna[0].s.addrh, dat); - } - - (void)port; -} - -static REG8 IOINPCALL opna_i188(UINT port) -{ - (void)port; - return g_opna[0].s.status; -} - -static REG8 IOINPCALL opna_i18a(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[0].s.addrl; - if (nAddress == 0x0e) - { - return fmboard_getjoy(&g_opna[0]); - } - else if (nAddress < 0x10) - { - return opna_readRegister(&g_opna[0], nAddress); - } - else if (nAddress == 0xff) - { - return 1; - } - - (void)port; - return g_opna[0].s.data; -} - -static REG8 IOINPCALL opna_i18c(UINT port) -{ - if (g_opna[0].s.extend) - { - return opna_readExtendedStatus(&g_opna[0]); - } - - (void)port; - return 0xff; -} - -static REG8 IOINPCALL opna_i18e(UINT port) -{ - UINT nAddress; - - if (g_opna[0].s.extend) - { - nAddress = g_opna[0].s.addrh; - if ((nAddress == 0x08) || (nAddress == 0x0f)) - { - return opna_readExtendedRegister(&g_opna[0], nAddress); - } - return g_opna[0].s.data; - } - - (void)port; - return 0xff; -} - -static void extendchannel(REG8 enable) -{ - g_opna[0].s.extend = enable; - if (enable) - { - opngen_setcfg(&g_opna[0].opngen, 6, OPN_STEREO | 0x07); - } - else - { - opngen_setcfg(&g_opna[0].opngen, 3, OPN_MONORAL | 0x07); - rhythm_setreg(&g_opna[0].rhythm, 0x10, 0xff); - } -} - - -// ---- - -static const IOOUT opna_o[4] = { - opna_o188, opna_o18a, opna_o18c, opna_o18e}; - -static const IOINP opna_i[4] = { - opna_i188, opna_i18a, opna_i18c, opna_i18e}; - - -/** - * Reset - * @param[in] pConfig A pointer to a configure structure - * @param[in] adpcm Enable ADPCM - */ -void board86_reset(const NP2CFG *pConfig, BOOL adpcm) -{ - REG8 cCaps; - UINT nIrq; - - cCaps = OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_S98; - if (adpcm) - { - cCaps |= OPNA_HAS_ADPCM; - } - nIrq = (pConfig->snd86opt & 0x10) | ((pConfig->snd86opt & 0x4) << 5) | ((pConfig->snd86opt & 0x8) << 3); - if(g_nSoundID==SOUNDID_WAVESTAR){ - nIrq |= (0x3 << 6) | 0x10; // IRQ12固定 - } - - opna_reset(&g_opna[0], cCaps); - opna_timer(&g_opna[0], nIrq, NEVENT_FMTIMERA, NEVENT_FMTIMERB); - - opngen_setcfg(&g_opna[0].opngen, 3, OPN_STEREO | 0x38); - if (pConfig->snd86opt & 2) - { - soundrom_load(0xcc000, OEMTEXT("86")); - } - if(g_nSoundID==SOUNDID_WAVESTAR){ - g_opna[0].s.base = 0x000; // 0x188固定 - }else{ - g_opna[0].s.base = (pConfig->snd86opt & 0x01) ? 0x000 : 0x100; - } - fmboard_extreg(extendchannel); - if(g_nSoundID==SOUNDID_WAVESTAR){ - pcm86io_setopt(pConfig->snd86opt | (0x7 << 2)); // IRQ12固定 - }else{ - pcm86io_setopt(pConfig->snd86opt); - } -} - -/** - * Bind - */ -void board86_bind(void) -{ - opna_bind(&g_opna[0]); - pcm86io_bind(); - cbuscore_attachsndex(0x188 + g_opna[0].s.base, opna_o, opna_i); -} -void board86_unbind(void) -{ - pcm86io_unbind(); - cbuscore_detachsndex(0x188 + g_opna[0].s.base); -} +/** + * @file board86.c + * @brief Implementation of PC-9801-86 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static void IOOUTCALL opna_o188(UINT port, REG8 dat) +{ + g_opna[0].s.addrl = dat; + g_opna[0].s.data = dat; + (void)port; +} + +static void IOOUTCALL opna_o18a(UINT port, REG8 dat) +{ + + g_opna[0].s.data = dat; + + opna_writeRegister(&g_opna[0], g_opna[0].s.addrl, dat); + + (void)port; +} + +static void IOOUTCALL opna_o18c(UINT port, REG8 dat) +{ + if (g_opna[0].s.extend) + { + g_opna[0].s.addrh = dat; + g_opna[0].s.data = dat; + } + + (void)port; +} + +static void IOOUTCALL opna_o18e(UINT port, REG8 dat) +{ + if (g_opna[0].s.extend) + { + g_opna[0].s.data = dat; + opna_writeExtendedRegister(&g_opna[0], g_opna[0].s.addrh, dat); + } + + (void)port; +} + +static REG8 IOINPCALL opna_i188(UINT port) +{ + (void)port; + return g_opna[0].s.status; +} + +static REG8 IOINPCALL opna_i18a(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[0].s.addrl; + if (nAddress == 0x0e) + { + return fmboard_getjoy(&g_opna[0]); + } + else if (nAddress < 0x10) + { + return opna_readRegister(&g_opna[0], nAddress); + } + else if (nAddress == 0xff) + { + return 1; + } + + (void)port; + return g_opna[0].s.data; +} + +static REG8 IOINPCALL opna_i18c(UINT port) +{ + if (g_opna[0].s.extend) + { + return opna_readExtendedStatus(&g_opna[0]); + } + + (void)port; + return 0xff; +} + +static REG8 IOINPCALL opna_i18e(UINT port) +{ + UINT nAddress; + + if (g_opna[0].s.extend) + { + nAddress = g_opna[0].s.addrh; + if ((nAddress == 0x08) || (nAddress == 0x0f)) + { + return opna_readExtendedRegister(&g_opna[0], nAddress); + } + return g_opna[0].s.data; + } + + (void)port; + return 0xff; +} + +static void extendchannel(REG8 enable) +{ + g_opna[0].s.extend = enable; + if (enable) + { + opngen_setcfg(&g_opna[0].opngen, 6, OPN_STEREO | 0x07); + } + else + { + opngen_setcfg(&g_opna[0].opngen, 3, OPN_MONORAL | 0x07); + rhythm_setreg(&g_opna[0].rhythm, 0x10, 0xff); + } +} + + +// ---- + +static const IOOUT opna_o[4] = { + opna_o188, opna_o18a, opna_o18c, opna_o18e}; + +static const IOINP opna_i[4] = { + opna_i188, opna_i18a, opna_i18c, opna_i18e}; + + +/** + * Reset + * @param[in] pConfig A pointer to a configure structure + * @param[in] adpcm Enable ADPCM + */ +void board86_reset(const NP2CFG *pConfig, BOOL adpcm) +{ + REG8 cCaps; + UINT nIrq; + + cCaps = OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_S98; + if (adpcm) + { + cCaps |= OPNA_HAS_ADPCM; + } + nIrq = (pConfig->snd86opt & 0x10) | ((pConfig->snd86opt & 0x4) << 5) | ((pConfig->snd86opt & 0x8) << 3); + if(g_nSoundID==SOUNDID_WAVESTAR){ + nIrq |= (0x3 << 6) | 0x10; // IRQ12固定 + } + + opna_reset(&g_opna[0], cCaps); + opna_timer(&g_opna[0], nIrq, NEVENT_FMTIMERA, NEVENT_FMTIMERB); + + opngen_setcfg(&g_opna[0].opngen, 3, OPN_STEREO | 0x38); + if (pConfig->snd86opt & 2) + { + soundrom_load(0xcc000, OEMTEXT("86")); + } + if(g_nSoundID==SOUNDID_WAVESTAR){ + g_opna[0].s.base = 0x000; // 0x188固定 + }else{ + g_opna[0].s.base = (pConfig->snd86opt & 0x01) ? 0x000 : 0x100; + } + fmboard_extreg(extendchannel); + if(g_nSoundID==SOUNDID_WAVESTAR){ + pcm86io_setopt(pConfig->snd86opt | (0x7 << 2)); // IRQ12固定 + }else{ + pcm86io_setopt(pConfig->snd86opt); + } +} + +/** + * Bind + */ +void board86_bind(void) +{ + opna_bind(&g_opna[0]); + pcm86io_bind(); + cbuscore_attachsndex(0x188 + g_opna[0].s.base, opna_o, opna_i); +} +void board86_unbind(void) +{ + pcm86io_unbind(); + cbuscore_detachsndex(0x188 + g_opna[0].s.base); +} diff --git a/cbus/board86.h b/cbus/board86.h old mode 100755 new mode 100644 index ad990289..2b159d33 --- a/cbus/board86.h +++ b/cbus/board86.h @@ -1,21 +1,21 @@ -/** - * @file board86.h - * @brief Interface of PC-9801-86 - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -void board86_reset(const NP2CFG *pConfig, BOOL adpcm); -void board86_bind(void); -void board86_unbind(void); - -#ifdef __cplusplus -} -#endif +/** + * @file board86.h + * @brief Interface of PC-9801-86 + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +void board86_reset(const NP2CFG *pConfig, BOOL adpcm); +void board86_bind(void); +void board86_unbind(void); + +#ifdef __cplusplus +} +#endif diff --git a/cbus/boardlol.c b/cbus/boardlol.c old mode 100755 new mode 100644 index 2cdd883f..ded899e8 --- a/cbus/boardlol.c +++ b/cbus/boardlol.c @@ -90,7 +90,7 @@ static const IOINP opn_i[4] = { opn_i188, opn_i18a, NULL, NULL}; static void psgpanset(OPNA* psg) { - // SSGRŒ + // SSGはR固定 psggen_setpan(psg, 0, 1); psggen_setpan(psg, 1, 1); psggen_setpan(psg, 2, 1); @@ -110,7 +110,7 @@ void boardlol_reset(const NP2CFG *pConfig) { void boardlol_bind(void) { psgpanset(&g_opna[0]); // fmboard_fmrestore(0, 0); - opngen_setreg(&g_opna[0].opngen, 0, 0xb4, 1 << 7); // OPNLŒ + opngen_setreg(&g_opna[0].opngen, 0, 0xb4, 1 << 7); // OPNはL固定 opngen_setreg(&g_opna[0].opngen, 0, 0xb5, 1 << 7); opngen_setreg(&g_opna[0].opngen, 0, 0xb6, 1 << 7); psggen_restore(&g_opna[0]); diff --git a/cbus/boardmo.c b/cbus/boardmo.c old mode 100755 new mode 100644 index 3684bb00..693e261b --- a/cbus/boardmo.c +++ b/cbus/boardmo.c @@ -15,7 +15,7 @@ * SNE Multimedia Orchestra * YM2203C(OPN) + YMF262-M(OPL3) + YMZ263B(MMA) * - * Ή\tg/}jAׂɌMMÃ|[gsB + * 対応ソフト/マニュアルが無い為に現状MMAのポートが不明。 * */ static void *opl3; @@ -158,7 +158,7 @@ static const IOINP opl_i[4] = { opl_i288, opl_i28a, opl_i28c, opl_i28e}; static void psgpanset(OPNA* psg) { - // SSGLŒ + // SSGはL固定 psggen_setpan(psg, 0, 2); psggen_setpan(psg, 1, 2); psggen_setpan(psg, 2, 2); diff --git a/cbus/boardpx.c b/cbus/boardpx.c old mode 100755 new mode 100644 index 72bca482..3b198d67 --- a/cbus/boardpx.c +++ b/cbus/boardpx.c @@ -1,507 +1,507 @@ -/** - * @file boardpx.c - * @brief Implementation of PX - */ - -#include - -#if defined(SUPPORT_PX) - -#include -#include -#include -#include -#include -#include -#include - -static void IOOUTCALL spb_o088(UINT port, REG8 dat) -{ - g_opna[0].s.addrl = dat; -// g_opna[0].s.data = dat; - (void)port; -} - -static void IOOUTCALL spb_o08a(UINT port, REG8 dat) -{ -// g_opna[0].s.data = dat; - opna_writeRegister(&g_opna[0], g_opna[0].s.addrl, dat); - - (void)port; -} - -static void IOOUTCALL spb_o08c(UINT port, REG8 dat) -{ - g_opna[0].s.addrh = dat; -// g_opna[0].s.data = dat; - (void)port; -} - -static void IOOUTCALL spb_o08e(UINT port, REG8 dat) -{ -// g_opna[0].data = dat; - opna_writeExtendedRegister(&g_opna[0], g_opna[0].s.addrh, dat); - - (void)port; -} - -static REG8 IOINPCALL spb_i088(UINT port) -{ - (void)port; - - return opna_readExtendedStatus(&g_opna[0]); -} - -static REG8 IOINPCALL spb_i08a(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[0].s.addrl; - if (nAddress == 0x0e) - { - return fmboard_getjoy(&g_opna[0]); - } - - (void)port; - return opna_readRegister(&g_opna[0], nAddress); -} - -static REG8 IOINPCALL spb_i08e(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[0].s.addrh; - if ((nAddress == 0x08) || (nAddress == 0x0f)) - { - return opna_readExtendedRegister(&g_opna[0], nAddress); - } - - (void)port; - return g_opna[0].s.reg[g_opna[0].s.addrl]; -} - - - -static void IOOUTCALL spb_o188(UINT port, REG8 dat) -{ - g_opna[1].s.addrl = dat; -// g_opna[1].s.data = dat; - - (void)port; -} - -static void IOOUTCALL spb_o18a(UINT port, REG8 dat) -{ -// g_opna[1].s.data = dat; - opna_writeRegister(&g_opna[1], g_opna[1].s.addrl, dat); - - (void)port; -} - -static void IOOUTCALL spb_o18c(UINT port, REG8 dat) -{ - g_opna[1].s.addrh = dat; -// g_opna[1].s.data = dat; - (void)port; -} - -static void IOOUTCALL spb_o18e(UINT port, REG8 dat) -{ -// g_opna[1].s.data = dat; - opna_writeExtendedRegister(&g_opna[1], g_opna[1].s.addrh, dat); - - (void)port; -} - -static REG8 IOINPCALL spb_i188(UINT port) -{ - (void)port; - - return opna_readExtendedStatus(&g_opna[1]); -} - -static REG8 IOINPCALL spb_i18a(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[1].s.addrl; - if (nAddress == 0x0e) - { - return fmboard_getjoy(&g_opna[1]); - } - - (void)port; - return opna_readRegister(&g_opna[1], nAddress); -} - -static REG8 IOINPCALL spb_i18e(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[1].s.addrh; - if ((nAddress == 0x08) || (nAddress == 0x0f)) - { - return opna_readExtendedRegister(&g_opna[1], nAddress); - } - - (void)port; - return g_opna[1].s.reg[g_opna[1].s.addrl]; -} - - - -static void IOOUTCALL p86_o288(UINT port, REG8 dat) -{ - g_opna[4].s.addrl = dat; - g_opna[4].s.data = dat; - (void)port; -} - -static void IOOUTCALL p86_o28a(UINT port, REG8 dat) -{ - g_opna[4].s.data = dat; - opna_writeRegister(&g_opna[4], g_opna[4].s.addrl, dat); - - (void)port; -} - -static void IOOUTCALL p86_o28c(UINT port, REG8 dat) -{ - if (g_opna[4].s.extend) - { - g_opna[4].s.addrh = dat; - g_opna[4].s.data = dat; - } - - (void)port; -} - -static void IOOUTCALL p86_o28e(UINT port, REG8 dat) -{ - if (g_opna[4].s.extend) - { - g_opna[4].s.data = dat; - opna_writeExtendedRegister(&g_opna[4], g_opna[4].s.addrh, dat); - } - - (void)port; -} - -static REG8 IOINPCALL p86_i288(UINT port) -{ - (void)port; - return g_opna[4].s.status; -} - -static REG8 IOINPCALL p86_i28a(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[4].s.addrl; - if (nAddress == 0x0e) - { - return fmboard_getjoy(&g_opna[4]); - } - else if (nAddress < 0x10) - { - return opna_readRegister(&g_opna[4], nAddress); - } - else if (nAddress == 0xff) - { - return 1; - } - - (void)port; - return g_opna[4].s.data; -} - -static REG8 IOINPCALL p86_i28e(UINT port) -{ - UINT nAddress; - - if (g_opna[4].s.extend) - { - nAddress = g_opna[4].s.addrh; - if ((nAddress == 0x08) || (nAddress == 0x0f)) - { - return opna_readExtendedRegister(&g_opna[4], nAddress); - } - return g_opna[4].s.data; - } - - (void)port; - return 0xff; -} - - -// ---- spark board -static void IOOUTCALL spr_o48a(UINT port, REG8 dat) -{ -// g_opna[2].s.data = dat; - opna_writeRegister(&g_opna[2], g_opna[2].s.addrl, dat); - - (void)port; -} - -static void IOOUTCALL spr_o48c(UINT port, REG8 dat) -{ - g_opna[2].s.addrh = dat; -// g_opna[2].s.data = dat; - (void)port; -} - -static void IOOUTCALL spr_o48e(UINT port, REG8 dat) -{ -// g_opn.s.data = dat; - opna_writeExtendedRegister(&g_opna[2], g_opna[2].s.addrh, dat); - - (void)port; -} - -static REG8 IOINPCALL spr_i488(UINT port) -{ - (void)port; - return g_opna[0].s.status; -} - -static REG8 IOINPCALL spr_i48a(UINT port) -{ - (void)port; - return opna_readRegister(&g_opna[2], g_opna[2].s.addrl); -} - -static REG8 IOINPCALL spr_i48c(UINT port) -{ - (void)port; - return (g_opna[0].s.status & 3); -} - -static REG8 IOINPCALL spr_i48e(UINT port) -{ - (void)port; - return opna_read3438ExtRegister(&g_opna[2], g_opna[2].s.addrl); -} - -static void IOOUTCALL spr_o488(UINT port, REG8 dat) -{ - g_opna[2].s.addrl = dat; -// g_opna[2].s.data = dat; - (void)port; -} - - - -static void IOOUTCALL spr_o588(UINT port, REG8 dat) -{ - g_opna[3].s.addrl = dat; -// g_opna[3].s.data = dat; - (void)port; -} - -static void IOOUTCALL spr_o58a(UINT port, REG8 dat) -{ -// g_opna[3].s.data = dat; - opna_writeRegister(&g_opna[3], g_opna[3].s.addrl, dat); - - (void)port; -} - -static void IOOUTCALL spr_o58c(UINT port, REG8 dat) -{ - g_opna[3].s.addrh = dat; -// g_opna[3].s.data = dat; - (void)port; -} - -static void IOOUTCALL spr_o58e(UINT port, REG8 dat) -{ -// g_opna[3].s.data = dat; - opna_writeExtendedRegister(&g_opna[3], g_opna[3].s.addrh, dat); - - (void)port; -} - -static REG8 IOINPCALL spr_i588(UINT port) -{ - (void)port; - return g_opna[1].s.status; -} - -static REG8 IOINPCALL spr_i58a(UINT port) -{ - (void)port; - return opna_readRegister(&g_opna[3], g_opna[3].s.addrl); -} - -static REG8 IOINPCALL spr_i58c(UINT port) -{ - (void)port; - return (g_opna[1].s.status & 3); -} - -static REG8 IOINPCALL spr_i58e(UINT port) -{ - (void)port; - return opna_read3438ExtRegister(&g_opna[3], g_opna[3].s.addrl); -} - - - -// ---- - -static const IOOUT spb_o[4] = { - spb_o188, spb_o18a, spb_o18c, spb_o18e}; - -static const IOINP spb_i[4] = { - spb_i188, spb_i18a, spb_i188, spb_i18e}; - -static const IOOUT spb_o2[4] = { - spb_o088, spb_o08a, spb_o08c, spb_o08e}; - -static const IOINP spb_i2[4] = { - spb_i088, spb_i08a, spb_i088, spb_i08e}; - -static const IOOUT p86_o3[4] = { - p86_o288, p86_o28a, p86_o28c, p86_o28e}; - -static const IOINP p86_i3[4] = { - p86_i288, p86_i28a, p86_i288, p86_i28e}; - -// ---- - -static const IOOUT spr_o[4] = { - spr_o588, spr_o58a, spr_o58c, spr_o58e}; - -static const IOINP spr_i[4] = { - spr_i588, spr_i58a, spr_i58c, spr_i58e}; - -static const IOOUT spr_o2[4] = { - spr_o488, spr_o48a, spr_o48c, spr_o48e}; - -static const IOINP spr_i2[4] = { - spr_i488, spr_i48a, spr_i48c, spr_i48e}; - -/** - * Reset - * @param[in] pConfig A pointer to a configure structure - */ -void boardpx1_reset(const NP2CFG *pConfig) -{ - UINT nIrq1; - UINT nIrq2; - - nIrq1 = (pConfig->spbopt & 0xc0) | 0x10; - nIrq2 = (nIrq1 == 0xd0) ? 0x90 : 0xd0; - - opna_reset(&g_opna[0], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR | OPNA_S98); - opna_timer(&g_opna[0], nIrq1, NEVENT_FMTIMERA, NEVENT_FMTIMERB); - opna_reset(&g_opna[1], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR); - opna_timer(&g_opna[1], nIrq2, NEVENT_FMTIMER2A, NEVENT_FMTIMER2B); - opna_reset(&g_opna[2], OPNA_MODE_3438 | OPNA_HAS_VR); - opna_reset(&g_opna[3], OPNA_MODE_3438 | OPNA_HAS_VR); - - opngen_setcfg(&g_opna[0].opngen, 6, OPN_STEREO | 0x3f); - opngen_setcfg(&g_opna[1].opngen, 6, OPN_STEREO | 0x3f); - opngen_setcfg(&g_opna[2].opngen, 6, OPN_STEREO | 0x3f); - opngen_setcfg(&g_opna[3].opngen, 6, OPN_STEREO | 0x3f); - soundrom_loadex(pConfig->spbopt & 7, OEMTEXT("SPB")); - g_opna[0].s.base = (pConfig->spbopt & 0x10) ? 0x000 : 0x100; -} - -/** - * Bind - */ -void boardpx1_bind(void) -{ - opna_bind(&g_opna[0]); - opna_bind(&g_opna[1]); - opna_bind(&g_opna[2]); - opna_bind(&g_opna[3]); - cbuscore_attachsndex(0x188, spb_o, spb_i); - cbuscore_attachsndex(0x588, spr_o, spr_i); - cbuscore_attachsndex(0x088, spb_o2, spb_i2); - cbuscore_attachsndex(0x488, spr_o2, spr_i2); -} -void boardpx1_unbind(void) -{ - cbuscore_detachsndex(0x188); - cbuscore_detachsndex(0x588); - cbuscore_detachsndex(0x088); - cbuscore_detachsndex(0x488); -} - - -static void extendchannelx2(REG8 enable) { - - g_opna[4].s.extend = enable; - if (enable) - { - opngen_setcfg(&g_opna[4].opngen, 6, OPN_STEREO | 0x07); - } - else - { - opngen_setcfg(&g_opna[4].opngen, 3, OPN_MONORAL | 0x07); - rhythm_setreg(&g_opna[4].rhythm, 0x10, 0xff); - } -} - -/** - * Reset - * @param[in] pConfig A pointer to a configure structure - */ -void boardpx2_reset(const NP2CFG *pConfig) -{ - UINT nIrq1; - UINT nIrq2; - - nIrq1 = (pConfig->spbopt & 0xc0) | 0x10; - nIrq2 = (nIrq1 == 0xd0) ? 0x90 : 0xd0; - - opna_reset(&g_opna[0], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR | OPNA_S98); - opna_timer(&g_opna[0], nIrq1, NEVENT_FMTIMERA, NEVENT_FMTIMERB); - opna_reset(&g_opna[1], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR); - opna_timer(&g_opna[1], nIrq2, NEVENT_FMTIMER2A, NEVENT_FMTIMER2B); - opna_reset(&g_opna[2], OPNA_MODE_3438 | OPNA_HAS_VR); - opna_reset(&g_opna[3], OPNA_MODE_3438 | OPNA_HAS_VR); - opna_reset(&g_opna[4], OPNA_MODE_2608 | OPNA_HAS_ADPCM); - - opngen_setcfg(&g_opna[0].opngen, 6, OPN_STEREO | 0x3f); - opngen_setcfg(&g_opna[1].opngen, 6, OPN_STEREO | 0x3f); - opngen_setcfg(&g_opna[2].opngen, 6, OPN_STEREO | 0x3f); - opngen_setcfg(&g_opna[3].opngen, 6, OPN_STEREO | 0x3f); - opngen_setcfg(&g_opna[4].opngen, 3, OPN_STEREO | 0x38); - soundrom_loadex(pConfig->spbopt & 7, OEMTEXT("SPB")); - g_opna[0].s.base = (pConfig->spbopt & 0x10) ? 0x000 : 0x100; - fmboard_extreg(extendchannelx2); - pcm86io_setopt(0x00); -} - -/** - * Bind - */ -void boardpx2_bind(void) -{ - opna_bind(&g_opna[0]); - opna_bind(&g_opna[1]); - opna_bind(&g_opna[2]); - opna_bind(&g_opna[3]); - opna_bind(&g_opna[4]); - pcm86io_bind(); - cbuscore_attachsndex(0x188, spb_o, spb_i); - cbuscore_attachsndex(0x588, spr_o, spr_i); - cbuscore_attachsndex(0x088, spb_o2, spb_i2); - cbuscore_attachsndex(0x488, spr_o2, spr_i2); - cbuscore_attachsndex(0x288, p86_o3, p86_i3); -} -void boardpx2_unbind(void) -{ - pcm86io_unbind(); - cbuscore_detachsndex(0x188); - cbuscore_detachsndex(0x588); - cbuscore_detachsndex(0x088); - cbuscore_detachsndex(0x488); - cbuscore_detachsndex(0x288); -} - -#endif // defined(SUPPORT_PX) - +/** + * @file boardpx.c + * @brief Implementation of PX + */ + +#include + +#if defined(SUPPORT_PX) + +#include +#include +#include +#include +#include +#include +#include + +static void IOOUTCALL spb_o088(UINT port, REG8 dat) +{ + g_opna[0].s.addrl = dat; +// g_opna[0].s.data = dat; + (void)port; +} + +static void IOOUTCALL spb_o08a(UINT port, REG8 dat) +{ +// g_opna[0].s.data = dat; + opna_writeRegister(&g_opna[0], g_opna[0].s.addrl, dat); + + (void)port; +} + +static void IOOUTCALL spb_o08c(UINT port, REG8 dat) +{ + g_opna[0].s.addrh = dat; +// g_opna[0].s.data = dat; + (void)port; +} + +static void IOOUTCALL spb_o08e(UINT port, REG8 dat) +{ +// g_opna[0].data = dat; + opna_writeExtendedRegister(&g_opna[0], g_opna[0].s.addrh, dat); + + (void)port; +} + +static REG8 IOINPCALL spb_i088(UINT port) +{ + (void)port; + + return opna_readExtendedStatus(&g_opna[0]); +} + +static REG8 IOINPCALL spb_i08a(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[0].s.addrl; + if (nAddress == 0x0e) + { + return fmboard_getjoy(&g_opna[0]); + } + + (void)port; + return opna_readRegister(&g_opna[0], nAddress); +} + +static REG8 IOINPCALL spb_i08e(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[0].s.addrh; + if ((nAddress == 0x08) || (nAddress == 0x0f)) + { + return opna_readExtendedRegister(&g_opna[0], nAddress); + } + + (void)port; + return g_opna[0].s.reg[g_opna[0].s.addrl]; +} + + + +static void IOOUTCALL spb_o188(UINT port, REG8 dat) +{ + g_opna[1].s.addrl = dat; +// g_opna[1].s.data = dat; + + (void)port; +} + +static void IOOUTCALL spb_o18a(UINT port, REG8 dat) +{ +// g_opna[1].s.data = dat; + opna_writeRegister(&g_opna[1], g_opna[1].s.addrl, dat); + + (void)port; +} + +static void IOOUTCALL spb_o18c(UINT port, REG8 dat) +{ + g_opna[1].s.addrh = dat; +// g_opna[1].s.data = dat; + (void)port; +} + +static void IOOUTCALL spb_o18e(UINT port, REG8 dat) +{ +// g_opna[1].s.data = dat; + opna_writeExtendedRegister(&g_opna[1], g_opna[1].s.addrh, dat); + + (void)port; +} + +static REG8 IOINPCALL spb_i188(UINT port) +{ + (void)port; + + return opna_readExtendedStatus(&g_opna[1]); +} + +static REG8 IOINPCALL spb_i18a(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[1].s.addrl; + if (nAddress == 0x0e) + { + return fmboard_getjoy(&g_opna[1]); + } + + (void)port; + return opna_readRegister(&g_opna[1], nAddress); +} + +static REG8 IOINPCALL spb_i18e(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[1].s.addrh; + if ((nAddress == 0x08) || (nAddress == 0x0f)) + { + return opna_readExtendedRegister(&g_opna[1], nAddress); + } + + (void)port; + return g_opna[1].s.reg[g_opna[1].s.addrl]; +} + + + +static void IOOUTCALL p86_o288(UINT port, REG8 dat) +{ + g_opna[4].s.addrl = dat; + g_opna[4].s.data = dat; + (void)port; +} + +static void IOOUTCALL p86_o28a(UINT port, REG8 dat) +{ + g_opna[4].s.data = dat; + opna_writeRegister(&g_opna[4], g_opna[4].s.addrl, dat); + + (void)port; +} + +static void IOOUTCALL p86_o28c(UINT port, REG8 dat) +{ + if (g_opna[4].s.extend) + { + g_opna[4].s.addrh = dat; + g_opna[4].s.data = dat; + } + + (void)port; +} + +static void IOOUTCALL p86_o28e(UINT port, REG8 dat) +{ + if (g_opna[4].s.extend) + { + g_opna[4].s.data = dat; + opna_writeExtendedRegister(&g_opna[4], g_opna[4].s.addrh, dat); + } + + (void)port; +} + +static REG8 IOINPCALL p86_i288(UINT port) +{ + (void)port; + return g_opna[4].s.status; +} + +static REG8 IOINPCALL p86_i28a(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[4].s.addrl; + if (nAddress == 0x0e) + { + return fmboard_getjoy(&g_opna[4]); + } + else if (nAddress < 0x10) + { + return opna_readRegister(&g_opna[4], nAddress); + } + else if (nAddress == 0xff) + { + return 1; + } + + (void)port; + return g_opna[4].s.data; +} + +static REG8 IOINPCALL p86_i28e(UINT port) +{ + UINT nAddress; + + if (g_opna[4].s.extend) + { + nAddress = g_opna[4].s.addrh; + if ((nAddress == 0x08) || (nAddress == 0x0f)) + { + return opna_readExtendedRegister(&g_opna[4], nAddress); + } + return g_opna[4].s.data; + } + + (void)port; + return 0xff; +} + + +// ---- spark board +static void IOOUTCALL spr_o48a(UINT port, REG8 dat) +{ +// g_opna[2].s.data = dat; + opna_writeRegister(&g_opna[2], g_opna[2].s.addrl, dat); + + (void)port; +} + +static void IOOUTCALL spr_o48c(UINT port, REG8 dat) +{ + g_opna[2].s.addrh = dat; +// g_opna[2].s.data = dat; + (void)port; +} + +static void IOOUTCALL spr_o48e(UINT port, REG8 dat) +{ +// g_opn.s.data = dat; + opna_writeExtendedRegister(&g_opna[2], g_opna[2].s.addrh, dat); + + (void)port; +} + +static REG8 IOINPCALL spr_i488(UINT port) +{ + (void)port; + return g_opna[0].s.status; +} + +static REG8 IOINPCALL spr_i48a(UINT port) +{ + (void)port; + return opna_readRegister(&g_opna[2], g_opna[2].s.addrl); +} + +static REG8 IOINPCALL spr_i48c(UINT port) +{ + (void)port; + return (g_opna[0].s.status & 3); +} + +static REG8 IOINPCALL spr_i48e(UINT port) +{ + (void)port; + return opna_read3438ExtRegister(&g_opna[2], g_opna[2].s.addrl); +} + +static void IOOUTCALL spr_o488(UINT port, REG8 dat) +{ + g_opna[2].s.addrl = dat; +// g_opna[2].s.data = dat; + (void)port; +} + + + +static void IOOUTCALL spr_o588(UINT port, REG8 dat) +{ + g_opna[3].s.addrl = dat; +// g_opna[3].s.data = dat; + (void)port; +} + +static void IOOUTCALL spr_o58a(UINT port, REG8 dat) +{ +// g_opna[3].s.data = dat; + opna_writeRegister(&g_opna[3], g_opna[3].s.addrl, dat); + + (void)port; +} + +static void IOOUTCALL spr_o58c(UINT port, REG8 dat) +{ + g_opna[3].s.addrh = dat; +// g_opna[3].s.data = dat; + (void)port; +} + +static void IOOUTCALL spr_o58e(UINT port, REG8 dat) +{ +// g_opna[3].s.data = dat; + opna_writeExtendedRegister(&g_opna[3], g_opna[3].s.addrh, dat); + + (void)port; +} + +static REG8 IOINPCALL spr_i588(UINT port) +{ + (void)port; + return g_opna[1].s.status; +} + +static REG8 IOINPCALL spr_i58a(UINT port) +{ + (void)port; + return opna_readRegister(&g_opna[3], g_opna[3].s.addrl); +} + +static REG8 IOINPCALL spr_i58c(UINT port) +{ + (void)port; + return (g_opna[1].s.status & 3); +} + +static REG8 IOINPCALL spr_i58e(UINT port) +{ + (void)port; + return opna_read3438ExtRegister(&g_opna[3], g_opna[3].s.addrl); +} + + + +// ---- + +static const IOOUT spb_o[4] = { + spb_o188, spb_o18a, spb_o18c, spb_o18e}; + +static const IOINP spb_i[4] = { + spb_i188, spb_i18a, spb_i188, spb_i18e}; + +static const IOOUT spb_o2[4] = { + spb_o088, spb_o08a, spb_o08c, spb_o08e}; + +static const IOINP spb_i2[4] = { + spb_i088, spb_i08a, spb_i088, spb_i08e}; + +static const IOOUT p86_o3[4] = { + p86_o288, p86_o28a, p86_o28c, p86_o28e}; + +static const IOINP p86_i3[4] = { + p86_i288, p86_i28a, p86_i288, p86_i28e}; + +// ---- + +static const IOOUT spr_o[4] = { + spr_o588, spr_o58a, spr_o58c, spr_o58e}; + +static const IOINP spr_i[4] = { + spr_i588, spr_i58a, spr_i58c, spr_i58e}; + +static const IOOUT spr_o2[4] = { + spr_o488, spr_o48a, spr_o48c, spr_o48e}; + +static const IOINP spr_i2[4] = { + spr_i488, spr_i48a, spr_i48c, spr_i48e}; + +/** + * Reset + * @param[in] pConfig A pointer to a configure structure + */ +void boardpx1_reset(const NP2CFG *pConfig) +{ + UINT nIrq1; + UINT nIrq2; + + nIrq1 = (pConfig->spbopt & 0xc0) | 0x10; + nIrq2 = (nIrq1 == 0xd0) ? 0x90 : 0xd0; + + opna_reset(&g_opna[0], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR | OPNA_S98); + opna_timer(&g_opna[0], nIrq1, NEVENT_FMTIMERA, NEVENT_FMTIMERB); + opna_reset(&g_opna[1], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR); + opna_timer(&g_opna[1], nIrq2, NEVENT_FMTIMER2A, NEVENT_FMTIMER2B); + opna_reset(&g_opna[2], OPNA_MODE_3438 | OPNA_HAS_VR); + opna_reset(&g_opna[3], OPNA_MODE_3438 | OPNA_HAS_VR); + + opngen_setcfg(&g_opna[0].opngen, 6, OPN_STEREO | 0x3f); + opngen_setcfg(&g_opna[1].opngen, 6, OPN_STEREO | 0x3f); + opngen_setcfg(&g_opna[2].opngen, 6, OPN_STEREO | 0x3f); + opngen_setcfg(&g_opna[3].opngen, 6, OPN_STEREO | 0x3f); + soundrom_loadex(pConfig->spbopt & 7, OEMTEXT("SPB")); + g_opna[0].s.base = (pConfig->spbopt & 0x10) ? 0x000 : 0x100; +} + +/** + * Bind + */ +void boardpx1_bind(void) +{ + opna_bind(&g_opna[0]); + opna_bind(&g_opna[1]); + opna_bind(&g_opna[2]); + opna_bind(&g_opna[3]); + cbuscore_attachsndex(0x188, spb_o, spb_i); + cbuscore_attachsndex(0x588, spr_o, spr_i); + cbuscore_attachsndex(0x088, spb_o2, spb_i2); + cbuscore_attachsndex(0x488, spr_o2, spr_i2); +} +void boardpx1_unbind(void) +{ + cbuscore_detachsndex(0x188); + cbuscore_detachsndex(0x588); + cbuscore_detachsndex(0x088); + cbuscore_detachsndex(0x488); +} + + +static void extendchannelx2(REG8 enable) { + + g_opna[4].s.extend = enable; + if (enable) + { + opngen_setcfg(&g_opna[4].opngen, 6, OPN_STEREO | 0x07); + } + else + { + opngen_setcfg(&g_opna[4].opngen, 3, OPN_MONORAL | 0x07); + rhythm_setreg(&g_opna[4].rhythm, 0x10, 0xff); + } +} + +/** + * Reset + * @param[in] pConfig A pointer to a configure structure + */ +void boardpx2_reset(const NP2CFG *pConfig) +{ + UINT nIrq1; + UINT nIrq2; + + nIrq1 = (pConfig->spbopt & 0xc0) | 0x10; + nIrq2 = (nIrq1 == 0xd0) ? 0x90 : 0xd0; + + opna_reset(&g_opna[0], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR | OPNA_S98); + opna_timer(&g_opna[0], nIrq1, NEVENT_FMTIMERA, NEVENT_FMTIMERB); + opna_reset(&g_opna[1], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR); + opna_timer(&g_opna[1], nIrq2, NEVENT_FMTIMER2A, NEVENT_FMTIMER2B); + opna_reset(&g_opna[2], OPNA_MODE_3438 | OPNA_HAS_VR); + opna_reset(&g_opna[3], OPNA_MODE_3438 | OPNA_HAS_VR); + opna_reset(&g_opna[4], OPNA_MODE_2608 | OPNA_HAS_ADPCM); + + opngen_setcfg(&g_opna[0].opngen, 6, OPN_STEREO | 0x3f); + opngen_setcfg(&g_opna[1].opngen, 6, OPN_STEREO | 0x3f); + opngen_setcfg(&g_opna[2].opngen, 6, OPN_STEREO | 0x3f); + opngen_setcfg(&g_opna[3].opngen, 6, OPN_STEREO | 0x3f); + opngen_setcfg(&g_opna[4].opngen, 3, OPN_STEREO | 0x38); + soundrom_loadex(pConfig->spbopt & 7, OEMTEXT("SPB")); + g_opna[0].s.base = (pConfig->spbopt & 0x10) ? 0x000 : 0x100; + fmboard_extreg(extendchannelx2); + pcm86io_setopt(0x00); +} + +/** + * Bind + */ +void boardpx2_bind(void) +{ + opna_bind(&g_opna[0]); + opna_bind(&g_opna[1]); + opna_bind(&g_opna[2]); + opna_bind(&g_opna[3]); + opna_bind(&g_opna[4]); + pcm86io_bind(); + cbuscore_attachsndex(0x188, spb_o, spb_i); + cbuscore_attachsndex(0x588, spr_o, spr_i); + cbuscore_attachsndex(0x088, spb_o2, spb_i2); + cbuscore_attachsndex(0x488, spr_o2, spr_i2); + cbuscore_attachsndex(0x288, p86_o3, p86_i3); +} +void boardpx2_unbind(void) +{ + pcm86io_unbind(); + cbuscore_detachsndex(0x188); + cbuscore_detachsndex(0x588); + cbuscore_detachsndex(0x088); + cbuscore_detachsndex(0x488); + cbuscore_detachsndex(0x288); +} + +#endif // defined(SUPPORT_PX) + diff --git a/cbus/boardpx.h b/cbus/boardpx.h old mode 100755 new mode 100644 index 218faabc..689d490a --- a/cbus/boardpx.h +++ b/cbus/boardpx.h @@ -1,29 +1,29 @@ -/** - * @file boardpx.h - * @brief Interface of PX - */ - -#pragma once - -#if defined(SUPPORT_PX) - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -void boardpx1_reset(const NP2CFG *pConfig); -void boardpx1_bind(void); -void boardpx1_unbind(void); - -void boardpx2_reset(const NP2CFG *pConfig); -void boardpx2_bind(void); -void boardpx2_unbind(void); - -#ifdef __cplusplus -} -#endif - -#endif // defined(SUPPORT_PX) +/** + * @file boardpx.h + * @brief Interface of PX + */ + +#pragma once + +#if defined(SUPPORT_PX) + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +void boardpx1_reset(const NP2CFG *pConfig); +void boardpx1_bind(void); +void boardpx1_unbind(void); + +void boardpx2_reset(const NP2CFG *pConfig); +void boardpx2_bind(void); +void boardpx2_unbind(void); + +#ifdef __cplusplus +} +#endif + +#endif // defined(SUPPORT_PX) diff --git a/cbus/boardsb16.c b/cbus/boardsb16.c old mode 100755 new mode 100644 index c7f95028..3ca8bd14 --- a/cbus/boardsb16.c +++ b/cbus/boardsb16.c @@ -1,648 +1,648 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include - -#include - -#if 0 -#undef TRACEOUT -#define USE_TRACEOUT_VS -#ifdef USE_TRACEOUT_VS -static void trace_fmt_ex(const char *fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#else -#define TRACEOUT(s) (void)(s) -#endif -#endif /* 1 */ - -#ifdef SUPPORT_SOUND_SB16 - -/** - * Creative Sound Blaster 16(98) - * YMF262-M(OPL3) + CT1741(PCM) + CT1745(MIXER) + YM2203(OPN - option) - * - * デフォルト仕様 IO:D2 DMA:3 INT:5 - */ - -#define G_OPL3_INDEX 1 - -static const UINT8 sb16base[] = {0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde}; - -static UINT8 seq[] = {0x60, 0x80, 0xff, 0x21}; // XXX: Win2kドライバのチェックを通すためだけの暫定シーケンス -static int forceopl3mode = 0; -static int seqpos = 0; - -#ifdef USE_MAME -#ifdef USE_MAME_BSD -#if _MSC_VER < 1900 -#include -#else -#include -#endif -#else -#include -#endif -static int samplerate; -#endif - -static void IOOUTCALL sb16_o0400(UINT port, REG8 dat) { - port = dat; -} -static void IOOUTCALL sb16_o0500(UINT port, REG8 dat) { - port = dat; -} -static void IOOUTCALL sb16_o0600(UINT port, REG8 dat) { - port = dat; -} -static void IOOUTCALL sb16_o0700(UINT port, REG8 dat) { - port = dat; -} -static void IOOUTCALL sb16_o8000(UINT port, REG8 dat) { - /* MIDI Data Port */ -// TRACEOUT(("SB16-midi commands: %.2x", dat)); - //if(g_sb16.dsp_info.uartmode){ - if(mpu98.enable){ - mpu98.mode = 1; // force set UART mode - mpu98ii_o0(port, dat); - }else if(smpu98.enable){ - smpu98.mode = 1; // force set UART mode - smpu98_o0(port, dat); - } - //} - port = dat; -} -static void IOOUTCALL sb16_o8100(UINT port, REG8 dat) { - /* MIDI Stat Port */ -// TRACEOUT(("SB16-midi status: %.2x", dat)); - //if(g_sb16.dsp_info.uartmode){ - if(mpu98.enable){ - mpu98.mode = 1; // force set UART mode - mpu98ii_o2(port, dat); - }else if(smpu98.enable){ - smpu98.mode = 1; // force set UART mode - smpu98_o2(port, dat); - } - //} - TRACEOUT(("MPU PORT=0x%04x, DATA=0x%02x", port, dat)); - port = dat; -} - -static void IOOUTCALL sb16_o2000(UINT port, REG8 dat) { - (void)port; -#ifdef USE_MAME - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 0, dat); -#endif - g_opl3[G_OPL3_INDEX].s.addrl = dat; // Key Display用 - //TRACEOUT(("OPL3 PORT=0x%04x, DATA=0x%02x", port, dat)); -} - -static void IOOUTCALL sb16_o2100(UINT port, REG8 dat) { - (void)port; -#ifdef USE_MAME - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 1, dat); -#endif - opl3_writeRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl, dat); // Key Display用 - if(g_opl3[G_OPL3_INDEX].s.addrl==2 || g_opl3[G_OPL3_INDEX].s.addrl==4){ - if(seqpos < sizeof(seq) && seq[seqpos]==dat){ - seqpos++; - }else if(seq[0]==dat){ - seqpos = 1; - }else{ - seqpos = 0; - } - } - //TRACEOUT(("OPL3 PORT=0x%04x, DATA=0x%02x", port, dat)); -} -static void IOOUTCALL sb16_o2200(UINT port, REG8 dat) { - (void)port; -#ifdef USE_MAME - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 2, dat); -#endif - g_opl3[G_OPL3_INDEX].s.addrh = dat; // Key Display用 - //TRACEOUT(("OPL3 PORT=0x%04x, DATA=0x%02x", port, dat)); -} - -static void IOOUTCALL sb16_o2300(UINT port, REG8 dat) { - (void)port; -#ifdef USE_MAME - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 3, dat); -#endif - opl3_writeExtendedRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrh, dat); // Key Display用 - //TRACEOUT(("OPL3 PORT=0x%04x, DATA=0x%02x", port, dat)); -} - -static void IOOUTCALL sb16_o2800(UINT port, REG8 dat) { - /** - * いわゆるPC/ATで言うところのAdlib互換ポート - * UltimaUnderWorldではこちらを叩く - */ - port = dat; -#ifdef USE_MAME - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 0, dat); -#endif - g_opl3[G_OPL3_INDEX].s.addrl = dat; // Key Display用 -} -static void IOOUTCALL sb16_o2900(UINT port, REG8 dat) { - port = dat; -#ifdef USE_MAME - YMF262Write(g_mame_opl3[G_OPL3_INDEX], 1, dat); -#endif - opl3_writeRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl, dat); // Key Display用 -} - -static REG8 IOINPCALL sb16_i0400(UINT port) { - return 0xff; -} -static REG8 IOINPCALL sb16_i0500(UINT port) { - return 0; -} -static REG8 IOINPCALL sb16_i0600(UINT port) { - return 0; -} -static REG8 IOINPCALL sb16_i0700(UINT port) { - return 0; -} -static REG8 IOINPCALL sb16_i8000(UINT port) { - /* Midi Port */ - //if(g_sb16.dsp_info.uartmode){ - if(mpu98.enable){ - mpu98.mode = 1; // force set UART mode - return mpu98ii_i0(port); - }else if(smpu98.enable){ - smpu98.mode = 1; // force set UART mode - return smpu98_i0(port); - } - //} - return 0; -} -static REG8 IOINPCALL sb16_i8100(UINT port) { - /* Midi Port */ - //if(g_sb16.dsp_info.uartmode){ - TRACEOUT(("MPU PORT=0x%04x", port)); - if(mpu98.enable){ - mpu98.mode = 1; // force set UART mode - return mpu98ii_i2(port) & ~0x40; // 強制Ready - }else if(smpu98.enable){ - smpu98.mode = 1; // force set UART mode - return smpu98_i2(port) & ~0x40; // 強制Ready - } - //} - return 0x00; -} - - -static REG8 IOINPCALL sb16_i2000(UINT port) { - (void)port; - //TRACEOUT(("OPL3 PORT=0x%04x", port)); -#ifdef USE_MAME - if(!forceopl3mode && seqpos == sizeof(seq)){ - return 0xC0; - }else{ - return YMF262Read(g_mame_opl3[G_OPL3_INDEX], 0); - } -#else - return 0; -#endif -} - -static REG8 IOINPCALL sb16_i2200(UINT port) { - (void)port; - //TRACEOUT(("OPL3 PORT=0x%04x", port)); -#ifdef USE_MAME - return YMF262Read(g_mame_opl3[G_OPL3_INDEX], 1); -#else - return 0; -#endif -} - -static REG8 IOINPCALL sb16_i2800(UINT port) { - (void)port; - //TRACEOUT(("OPL3 PORT=0x%04x", port)); -#ifdef USE_MAME - return YMF262Read(g_mame_opl3[G_OPL3_INDEX], 0); -#else - return 0; -#endif -} - -#if defined(SUPPORT_GAMEPORT) -/*********** Sound Blaster 16 Gameport I/O ***********/ -#define GAMEPORT_JOYCOUNTER_MGN2 (gameport_clkmax/100) -//#define GAMEPORT_JOYCOUNTER_MGN (gameport_clkmax/100) -#define GAMEPORT_JOYCOUNTER_TMPCLK 100000000 -#if defined(SUPPORT_IA32_HAXM) -static LARGE_INTEGER gameport_qpf; -static int gameport_useqpc = 0; -#endif -extern int gameport_tsccounter; -static UINT64 gameport_tsc; -static REG8 gameport_joyflag_base = 0x00; -static REG8 gameport_joyflag = 0x00; -#if defined(SUPPORT_IA32_HAXM) -static UINT64 gameport_clkmax; -static UINT64 gameport_threshold_x = 0; -static UINT64 gameport_threshold_y = 0; -#else -static UINT32 gameport_clkmax; -static UINT32 gameport_threshold_x = 0; -static UINT32 gameport_threshold_y = 0; -#endif -//UINT32 gameport_timeoutcounter = 0; -//UINT32 gameport_timeoutinterval = 0; -// joyflag bit:0 up -// bit:1 down -// bit:2 left -// bit:3 right -// bit:4 trigger1 (rapid) -// bit:5 trigger2 (rapid) -// bit:6 trigger1 -// bit:7 trigger2 -//void gameport_timeoutproc(NEVENTITEM item); -static void IOOUTCALL gameport_o4d2(UINT port, REG8 dat) -{ - REG8 joyflag; - joyflag = joymng_getstat(); - if(!joymng_available()){ - return; - } - gameport_joyflag_base = joyflag; - gameport_joyflag = ((joyflag >> 2) & 0x30) | ((joyflag << 2) & 0xc0) | 0x0f; -#if defined(SUPPORT_IA32_HAXM) - { - LARGE_INTEGER li = {0}; - if (QueryPerformanceFrequency(&gameport_qpf)) { - QueryPerformanceCounter(&li); - //li.QuadPart = li.QuadPart; - gameport_tsc = (UINT64)li.QuadPart; - gameport_useqpc = 1; - }else{ - gameport_tsc = CPU_MSR_TSC; - gameport_useqpc = 0; - } - } -#else -#if defined(USE_TSC) - if(CPU_REMCLOCK > 0){ - gameport_tsc = CPU_MSR_TSC - (UINT64)CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple; - }else{ - gameport_tsc = CPU_MSR_TSC; - } - gameport_tsccounter = 0; -#else - gameport_tsc = 0; -#endif -#endif - (void)port; -} -static REG8 IOINPCALL gameport_i4d2(UINT port) -{ - REG8 retval = 0xff; -#if defined(NP2_WIN) - UINT32 joyAnalogX; - UINT32 joyAnalogY; -#endif - UINT64 clockdiff; -#if defined(SUPPORT_IA32_HAXM) - LARGE_INTEGER li = { 0 }; - QueryPerformanceCounter(&li); -#endif - { - REG8 joyflag = joymng_getstat(); - gameport_joyflag = ((joyflag >> 2) & 0x30) | ((joyflag << 2) & 0xc0) | (gameport_joyflag & 0x0f); - } - if (!joymng_available()) - { - return 0xff; - } -#if defined(NP2_WIN) - joyAnalogX = joymng_getAnalogX(); - joyAnalogY = joymng_getAnalogY(); -#endif -#if defined(SUPPORT_IA32_HAXM) - if(gameport_useqpc){ - clockdiff = (unsigned long long)((UINT64)li.QuadPart - gameport_tsc); - gameport_clkmax = (UINT64)gameport_qpf.QuadPart / 1300; // とりあえず0.7msで・・・ - }else{ - clockdiff = CPU_MSR_TSC - gameport_tsc; - gameport_clkmax = pccore.realclock / 1430; // とりあえず0.7msで・・・ - } -#else -#if defined(USE_TSC) - if(CPU_REMCLOCK > 0){ - clockdiff = CPU_MSR_TSC - (UINT64)CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple - gameport_tsc; - }else{ - clockdiff = CPU_MSR_TSC - gameport_tsc; - } - gameport_clkmax = pccore.baseclock * pccore.maxmultiple / 1430; // とりあえず0.7msで・・・ -#if !defined(SUPPORT_IA32_HAXM) - if(gameport_tsccounter == 0 || !np2cfg.consttsc){ - gameport_clkmax = gameport_clkmax * pccore.maxmultiple / pccore.multiple; // CPUクロック依存の場合のfix - } -#endif -#else - gameport_clkmax = 32; - clockdiff = gameport_tsc; - gameport_tsc++; -#endif -#endif - if (np2cfg.analogjoy) - { - // アナログ入力タイプ -#if defined(NP2_WIN) - gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2 + (UINT32)((UINT64)(gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2 * 2) * joyAnalogX / 65535); - gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2 + (UINT32)((UINT64)(gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2 * 2) * joyAnalogY / 65535); -#else - gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2; - gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2; -#endif - } - else - { - // ON/OFFタイプ - gameport_threshold_x = gameport_clkmax / 2; - gameport_threshold_y = gameport_clkmax / 2; - if(~gameport_joyflag_base & 0x1){ - gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2; - } - if(~gameport_joyflag_base & 0x2){ - gameport_threshold_y = gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2; - } - if(~gameport_joyflag_base & 0x4){ - gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2; - } - if(~gameport_joyflag_base & 0x8){ - gameport_threshold_x = gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2; - } - } - retval = gameport_joyflag; - if(clockdiff >= (UINT64)gameport_threshold_x){ - gameport_joyflag &= ~0x01; - } - if(clockdiff >= (UINT64)gameport_threshold_y){ - gameport_joyflag &= ~0x02; - } - return retval; -} -#endif - -// ---- - -#ifdef USE_MAME -#define OPL3_SAMPLE_BUFFER 4096 -static INT16 oplfm_s1ls[OPL3_SAMPLE_BUFFER] = { 0 }; -static INT16 oplfm_s1rs[OPL3_SAMPLE_BUFFER] = { 0 }; -static INT16 oplfm_s2ls[OPL3_SAMPLE_BUFFER] = { 0 }; -static INT16 oplfm_s2rs[OPL3_SAMPLE_BUFFER] = { 0 }; -static void SOUNDCALL opl3gen_getpcm(void* opl3, SINT32 *pcm, UINT count) { - UINT i; - INT16 *buf[4]; - SINT32 *outbuf = pcm; - SINT32 oplfm_volume; - SINT32 midivolL = g_sb16.mixregexp[MIXER_MIDI_LEFT]; - SINT32 midivolR = g_sb16.mixregexp[MIXER_MIDI_RIGHT]; - SINT32 volL, volR; - oplfm_volume = np2cfg.vol_fm * np2cfg.vol_master / 100; - buf[0] = oplfm_s1ls; - buf[1] = oplfm_s1rs; - buf[2] = oplfm_s2ls; - buf[3] = oplfm_s2rs; - - // PCMサウンドバッファに送る - volL = oplfm_volume * midivolL * 2; - volR = oplfm_volume * midivolR * 2; - while (count > 0) { - int cc = MIN(count, OPL3_SAMPLE_BUFFER); - YMF262UpdateOne(opl3, buf, cc); - for (i = 0; i < cc; i++) { - outbuf[0] += (SINT32)((oplfm_s1ls[i] * volL / 255 * (SINT32)g_sb16.mixregexp[MIXER_MASTER_LEFT] / 255) >> 6); - outbuf[1] += (SINT32)((oplfm_s1rs[i] * volR / 255 * (SINT32)g_sb16.mixregexp[MIXER_MASTER_RIGHT] / 255) >> 6); - outbuf += 2; - } - count -= cc; - } -} - -static void SOUNDCALL opl3gen_getpcm_dummy(void* opl3, SINT32* pcm, UINT count) { - UINT i; - INT16* buf[4]; - INT16 s1l, s1r, s2l, s2r; - buf[0] = oplfm_s1ls; - buf[1] = oplfm_s1rs; - buf[2] = oplfm_s2ls; - buf[3] = oplfm_s2rs; - while (count > 0) { - int cc = MIN(count, OPL3_SAMPLE_BUFFER); - YMF262UpdateOne(opl3, buf, cc); - count -= cc; - } -} -#endif - -void boardsb16_reset(const NP2CFG *pConfig) { - DSP_INFO olddsp; -#ifdef USE_MAME - if (g_mame_opl3[G_OPL3_INDEX]) { - if (samplerate != soundcfg.rate) { - YMF262Shutdown(g_mame_opl3[G_OPL3_INDEX]); - g_mame_opl3[G_OPL3_INDEX] = YMF262Init(14400000, soundcfg.rate); - samplerate = soundcfg.rate; - } else { - YMF262ResetChip(g_mame_opl3[G_OPL3_INDEX], samplerate); - } - } -#endif - olddsp = g_sb16.dsp_info; // dsp_infoだけ初期化しない - ZeroMemory(&g_sb16, sizeof(g_sb16)); - g_sb16.dsp_info = olddsp; - // ボードデフォルト IO:D2 DMA:3 IRQ:5(INT1) - g_sb16.base = np2cfg.sndsb16io; //0xd2; - g_sb16.dmachnum = np2cfg.sndsb16dma; //0x3; - g_sb16.dmairq = np2cfg.sndsb16irq; //0x5; - ct1745io_reset(); - ct1741io_reset(); - - forceopl3mode = 0; - seqpos = 0; -} - -void boardsb16_bind(void) { - opl3_reset(&g_opl3[G_OPL3_INDEX], OPL3_HAS_OPL3L|OPL3_HAS_OPL3); - - ct1745io_bind(); - ct1741io_bind(); - - iocore_attachout(0x2000 + g_sb16.base, sb16_o2000); /* FM Music Register Address Port */ - iocore_attachout(0x2100 + g_sb16.base, sb16_o2100); /* FM Music Data Port */ - iocore_attachout(0x2200 + g_sb16.base, sb16_o2200); /* Advanced FM Music Register Address Port */ - iocore_attachout(0x2300 + g_sb16.base, sb16_o2300); /* Advanced FM Music Data Port */ - iocore_attachout(0x2800 + g_sb16.base, sb16_o2800); /* FM Music Register Port */ - iocore_attachout(0x2900 + g_sb16.base, sb16_o2900); /* FM Music Data Port */ - - iocore_attachinp(0x2000 + g_sb16.base, sb16_i2000); /* FM Music Status Port */ - iocore_attachinp(0x2200 + g_sb16.base, sb16_i2200); /* Advanced FM Music Status Port */ - iocore_attachinp(0x2800 + g_sb16.base, sb16_i2800); /* FM Music Status Port */ - -#if defined(SUPPORT_GAMEPORT) - iocore_attachout(0x0400 + g_sb16.base, gameport_o4d2); /* GAME Port */ - iocore_attachout(0x0500 + g_sb16.base, gameport_o4d2); /* GAME Port */ - iocore_attachout(0x0600 + g_sb16.base, gameport_o4d2); /* GAME Port */ - iocore_attachout(0x0700 + g_sb16.base, gameport_o4d2); /* GAME Port */ - iocore_attachinp(0x0400 + g_sb16.base, gameport_i4d2); /* GAME Port */ - iocore_attachinp(0x0500 + g_sb16.base, gameport_i4d2); /* GAME Port */ - iocore_attachinp(0x0600 + g_sb16.base, gameport_i4d2); /* GAME Port */ - iocore_attachinp(0x0700 + g_sb16.base, gameport_i4d2); /* GAME Port */ -#else - iocore_attachout(0x0400 + g_sb16.base, sb16_o0400); /* GAME Port */ - iocore_attachout(0x0500 + g_sb16.base, sb16_o0400); /* GAME Port */ - iocore_attachout(0x0600 + g_sb16.base, sb16_o0400); /* GAME Port */ - iocore_attachout(0x0700 + g_sb16.base, sb16_o0400); /* GAME Port */ - iocore_attachinp(0x0400 + g_sb16.base, sb16_i0400); /* GAME Port */ - iocore_attachinp(0x0500 + g_sb16.base, sb16_i0400); /* GAME Port */ - iocore_attachinp(0x0600 + g_sb16.base, sb16_i0400); /* GAME Port */ - iocore_attachinp(0x0700 + g_sb16.base, sb16_i0400); /* GAME Port */ -#endif - - iocore_attachout(0x8000 + g_sb16.base, sb16_o8000); /* MIDI Port */ - //iocore_attachout(0x8001 + g_sb16.base, sb16_o8100); /* MIDI Port 暫定 */ - iocore_attachout(0x8100 + g_sb16.base, sb16_o8100); /* MIDI Port */ - iocore_attachinp(0x8000 + g_sb16.base, sb16_i8000); /* MIDI Port */ - //iocore_attachinp(0x8001 + g_sb16.base, sb16_i8100); /* MIDI Port 暫定 */ - iocore_attachinp(0x8100 + g_sb16.base, sb16_i8100); /* MIDI Port */ - - iocore_attachout(0xC800 + g_sb16.base, sb16_o2000); /* FM Music Register Address Port */ - iocore_attachinp(0xC800 + g_sb16.base, sb16_i2000); /* FM Music Status Port */ - iocore_attachout(0xC900 + g_sb16.base, sb16_o2100); /* FM Music Data Port */ - iocore_attachout(0xCA00 + g_sb16.base, sb16_o2200); /* Advanced FM Music Register Address Port */ - iocore_attachinp(0xCA00 + g_sb16.base, sb16_i2200); /* Advanced FM Music Status Port */ - iocore_attachout(0xCB00 + g_sb16.base, sb16_o2300); /* Advanced FM Music Data Port */ - - // PC/AT互換機テスト - if(np2cfg.sndsb16at){ - iocore_attachout(0x388, sb16_o2000); /* FM Music Register Address Port */ - iocore_attachinp(0x388, sb16_i2000); /* FM Music Status Port */ - iocore_attachout(0x389, sb16_o2100); /* FM Music Data Port */ - iocore_attachout(0x38a, sb16_o2200); /* Advanced FM Music Register Address Port */ - iocore_attachinp(0x38a, sb16_i2200); /* Advanced FM Music Status Port */ - iocore_attachout(0x38b, sb16_o2300); /* Advanced FM Music Data Port */ - } - - if (!g_mame_opl3[G_OPL3_INDEX]) { -#ifdef USE_MAME - g_mame_opl3[G_OPL3_INDEX] = YMF262Init(14400000, np2cfg.samplingrate); -#endif - samplerate = np2cfg.samplingrate; - } - -#if defined(SUPPORT_GAMEPORT) - // ゲームポート割り当て 4d2h - if(np2cfg.gameport){ - iocore_attachout(0x0400 + g_sb16.base, gameport_o4d2); - iocore_attachinp(0x0400 + g_sb16.base, gameport_i4d2); - } -#endif - -#ifdef USE_MAME - if (!g_mame_opl3[G_OPL3_INDEX]) { - g_mame_opl3[G_OPL3_INDEX] = YMF262Init(14400000, np2cfg.samplingrate); - samplerate = np2cfg.samplingrate; - } -#endif - opl3_bind(&g_opl3[G_OPL3_INDEX]); // MAME使用の場合Key Display用 -#ifdef USE_MAME - if (g_opl3[G_OPL3_INDEX].userdata) { - // 外部音源を使用する場合 ダミー登録 - sound_streamregist(g_mame_opl3[G_OPL3_INDEX], (SOUNDCB)opl3gen_getpcm_dummy); - } - else { - // 外部音源を使用しない場合 PCM登録 - sound_streamregist(g_mame_opl3[G_OPL3_INDEX], (SOUNDCB)opl3gen_getpcm); - } -#endif -} -void boardsb16_unbind(void) { - ct1745io_unbind(); - ct1741io_unbind(); - - iocore_detachout(0x2000 + g_sb16.base); /* FM Music Register Address Port */ - iocore_detachout(0x2100 + g_sb16.base); /* FM Music Data Port */ - iocore_detachout(0x2200 + g_sb16.base); /* Advanced FM Music Register Address Port */ - iocore_detachout(0x2300 + g_sb16.base); /* Advanced FM Music Data Port */ - iocore_detachout(0x2800 + g_sb16.base); /* FM Music Register Port */ - iocore_detachout(0x2900 + g_sb16.base); /* FM Music Data Port */ - - iocore_detachinp(0x2000 + g_sb16.base); /* FM Music Status Port */ - iocore_detachinp(0x2200 + g_sb16.base); /* Advanced FM Music Status Port */ - iocore_detachinp(0x2800 + g_sb16.base); /* FM Music Status Port */ - - iocore_detachout(0x0400 + g_sb16.base); /* GAME Port */ - iocore_detachout(0x0500 + g_sb16.base); /* GAME Port */ - iocore_detachout(0x0600 + g_sb16.base); /* GAME Port */ - iocore_detachout(0x0700 + g_sb16.base); /* GAME Port */ - iocore_detachinp(0x0400 + g_sb16.base); /* GAME Port */ - iocore_detachinp(0x0500 + g_sb16.base); /* GAME Port */ - iocore_detachinp(0x0600 + g_sb16.base); /* GAME Port */ - iocore_detachinp(0x0700 + g_sb16.base); /* GAME Port */ - - iocore_detachout(0x8000 + g_sb16.base); /* MIDI Port */ - //iocore_detachout(0x8001 + g_sb16.base); /* MIDI Port 暫定 */ - iocore_detachout(0x8100 + g_sb16.base); /* MIDI Port */ - iocore_detachinp(0x8000 + g_sb16.base); /* MIDI Port */ - //iocore_detachinp(0x8001 + g_sb16.base); /* MIDI Port 暫定 */ - iocore_detachinp(0x8100 + g_sb16.base); /* MIDI Port */ - - iocore_detachout(0xC800 + g_sb16.base); /* FM Music Register Address Port */ - iocore_detachinp(0xC800 + g_sb16.base); /* FM Music Status Port */ - iocore_detachout(0xC900 + g_sb16.base); /* FM Music Data Port */ - iocore_detachout(0xCA00 + g_sb16.base); /* Advanced FM Music Register Address Port */ - iocore_detachinp(0xCA00 + g_sb16.base); /* Advanced FM Music Status Port */ - iocore_detachout(0xCB00 + g_sb16.base); /* Advanced FM Music Data Port */ - - // PC/AT互換機テスト - if(np2cfg.sndsb16at){ - iocore_detachout(0x388); /* FM Music Register Address Port */ - iocore_detachinp(0x388); /* FM Music Status Port */ - iocore_detachout(0x389); /* FM Music Data Port */ - iocore_detachout(0x38a); /* Advanced FM Music Register Address Port */ - iocore_detachinp(0x38a); /* Advanced FM Music Status Port */ - iocore_detachout(0x38b); /* Advanced FM Music Data Port */ - } - -#if defined(SUPPORT_GAMEPORT) - // ゲームポート割り当て 4d2h - if(np2cfg.gameport){ - iocore_detachout(0x0400 + g_sb16.base); - iocore_detachinp(0x0400 + g_sb16.base); - } -#endif -} -void boardsb16_finalize(void) -{ -#ifdef USE_MAME - if (g_mame_opl3[G_OPL3_INDEX]) { - YMF262Shutdown(g_mame_opl3[G_OPL3_INDEX]); - g_mame_opl3[G_OPL3_INDEX] = NULL; - } -#endif -} - -#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#include + +#if 0 +#undef TRACEOUT +#define USE_TRACEOUT_VS +#ifdef USE_TRACEOUT_VS +static void trace_fmt_ex(const char *fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "¥n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#else +#define TRACEOUT(s) (void)(s) +#endif +#endif /* 1 */ + +#ifdef SUPPORT_SOUND_SB16 + +/** + * Creative Sound Blaster 16(98) + * YMF262-M(OPL3) + CT1741(PCM) + CT1745(MIXER) + YM2203(OPN - option) + * + * デフォルト仕様 IO:D2 DMA:3 INT:5 + */ + +#define G_OPL3_INDEX 1 + +static const UINT8 sb16base[] = {0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde}; + +static UINT8 seq[] = {0x60, 0x80, 0xff, 0x21}; // XXX: Win2kドライバのチェックを通すためだけの暫定シーケンス +static int forceopl3mode = 0; +static int seqpos = 0; + +#ifdef USE_MAME +#ifdef USE_MAME_BSD +#if _MSC_VER < 1900 +#include +#else +#include +#endif +#else +#include +#endif +static int samplerate; +#endif + +static void IOOUTCALL sb16_o0400(UINT port, REG8 dat) { + port = dat; +} +static void IOOUTCALL sb16_o0500(UINT port, REG8 dat) { + port = dat; +} +static void IOOUTCALL sb16_o0600(UINT port, REG8 dat) { + port = dat; +} +static void IOOUTCALL sb16_o0700(UINT port, REG8 dat) { + port = dat; +} +static void IOOUTCALL sb16_o8000(UINT port, REG8 dat) { + /* MIDI Data Port */ +// TRACEOUT(("SB16-midi commands: %.2x", dat)); + //if(g_sb16.dsp_info.uartmode){ + if(mpu98.enable){ + mpu98.mode = 1; // force set UART mode + mpu98ii_o0(port, dat); + }else if(smpu98.enable){ + smpu98.mode = 1; // force set UART mode + smpu98_o0(port, dat); + } + //} + port = dat; +} +static void IOOUTCALL sb16_o8100(UINT port, REG8 dat) { + /* MIDI Stat Port */ +// TRACEOUT(("SB16-midi status: %.2x", dat)); + //if(g_sb16.dsp_info.uartmode){ + if(mpu98.enable){ + mpu98.mode = 1; // force set UART mode + mpu98ii_o2(port, dat); + }else if(smpu98.enable){ + smpu98.mode = 1; // force set UART mode + smpu98_o2(port, dat); + } + //} + TRACEOUT(("MPU PORT=0x%04x, DATA=0x%02x", port, dat)); + port = dat; +} + +static void IOOUTCALL sb16_o2000(UINT port, REG8 dat) { + (void)port; +#ifdef USE_MAME + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 0, dat); +#endif + g_opl3[G_OPL3_INDEX].s.addrl = dat; // Key Display用 + //TRACEOUT(("OPL3 PORT=0x%04x, DATA=0x%02x", port, dat)); +} + +static void IOOUTCALL sb16_o2100(UINT port, REG8 dat) { + (void)port; +#ifdef USE_MAME + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 1, dat); +#endif + opl3_writeRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl, dat); // Key Display用 + if(g_opl3[G_OPL3_INDEX].s.addrl==2 || g_opl3[G_OPL3_INDEX].s.addrl==4){ + if(seqpos < sizeof(seq) && seq[seqpos]==dat){ + seqpos++; + }else if(seq[0]==dat){ + seqpos = 1; + }else{ + seqpos = 0; + } + } + //TRACEOUT(("OPL3 PORT=0x%04x, DATA=0x%02x", port, dat)); +} +static void IOOUTCALL sb16_o2200(UINT port, REG8 dat) { + (void)port; +#ifdef USE_MAME + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 2, dat); +#endif + g_opl3[G_OPL3_INDEX].s.addrh = dat; // Key Display用 + //TRACEOUT(("OPL3 PORT=0x%04x, DATA=0x%02x", port, dat)); +} + +static void IOOUTCALL sb16_o2300(UINT port, REG8 dat) { + (void)port; +#ifdef USE_MAME + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 3, dat); +#endif + opl3_writeExtendedRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrh, dat); // Key Display用 + //TRACEOUT(("OPL3 PORT=0x%04x, DATA=0x%02x", port, dat)); +} + +static void IOOUTCALL sb16_o2800(UINT port, REG8 dat) { + /** + * いわゆるPC/ATで言うところのAdlib互換ポート + * UltimaUnderWorldではこちらを叩く + */ + port = dat; +#ifdef USE_MAME + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 0, dat); +#endif + g_opl3[G_OPL3_INDEX].s.addrl = dat; // Key Display用 +} +static void IOOUTCALL sb16_o2900(UINT port, REG8 dat) { + port = dat; +#ifdef USE_MAME + YMF262Write(g_mame_opl3[G_OPL3_INDEX], 1, dat); +#endif + opl3_writeRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl, dat); // Key Display用 +} + +static REG8 IOINPCALL sb16_i0400(UINT port) { + return 0xff; +} +static REG8 IOINPCALL sb16_i0500(UINT port) { + return 0; +} +static REG8 IOINPCALL sb16_i0600(UINT port) { + return 0; +} +static REG8 IOINPCALL sb16_i0700(UINT port) { + return 0; +} +static REG8 IOINPCALL sb16_i8000(UINT port) { + /* Midi Port */ + //if(g_sb16.dsp_info.uartmode){ + if(mpu98.enable){ + mpu98.mode = 1; // force set UART mode + return mpu98ii_i0(port); + }else if(smpu98.enable){ + smpu98.mode = 1; // force set UART mode + return smpu98_i0(port); + } + //} + return 0; +} +static REG8 IOINPCALL sb16_i8100(UINT port) { + /* Midi Port */ + //if(g_sb16.dsp_info.uartmode){ + TRACEOUT(("MPU PORT=0x%04x", port)); + if(mpu98.enable){ + mpu98.mode = 1; // force set UART mode + return mpu98ii_i2(port) & ~0x40; // 強制Ready + }else if(smpu98.enable){ + smpu98.mode = 1; // force set UART mode + return smpu98_i2(port) & ~0x40; // 強制Ready + } + //} + return 0x00; +} + + +static REG8 IOINPCALL sb16_i2000(UINT port) { + (void)port; + //TRACEOUT(("OPL3 PORT=0x%04x", port)); +#ifdef USE_MAME + if(!forceopl3mode && seqpos == sizeof(seq)){ + return 0xC0; + }else{ + return YMF262Read(g_mame_opl3[G_OPL3_INDEX], 0); + } +#else + return 0; +#endif +} + +static REG8 IOINPCALL sb16_i2200(UINT port) { + (void)port; + //TRACEOUT(("OPL3 PORT=0x%04x", port)); +#ifdef USE_MAME + return YMF262Read(g_mame_opl3[G_OPL3_INDEX], 1); +#else + return 0; +#endif +} + +static REG8 IOINPCALL sb16_i2800(UINT port) { + (void)port; + //TRACEOUT(("OPL3 PORT=0x%04x", port)); +#ifdef USE_MAME + return YMF262Read(g_mame_opl3[G_OPL3_INDEX], 0); +#else + return 0; +#endif +} + +#if defined(SUPPORT_GAMEPORT) +/*********** Sound Blaster 16 Gameport I/O ***********/ +#define GAMEPORT_JOYCOUNTER_MGN2 (gameport_clkmax/100) +//#define GAMEPORT_JOYCOUNTER_MGN (gameport_clkmax/100) +#define GAMEPORT_JOYCOUNTER_TMPCLK 100000000 +#if defined(SUPPORT_IA32_HAXM) +static LARGE_INTEGER gameport_qpf; +static int gameport_useqpc = 0; +#endif +extern int gameport_tsccounter; +static UINT64 gameport_tsc; +static REG8 gameport_joyflag_base = 0x00; +static REG8 gameport_joyflag = 0x00; +#if defined(SUPPORT_IA32_HAXM) +static UINT64 gameport_clkmax; +static UINT64 gameport_threshold_x = 0; +static UINT64 gameport_threshold_y = 0; +#else +static UINT32 gameport_clkmax; +static UINT32 gameport_threshold_x = 0; +static UINT32 gameport_threshold_y = 0; +#endif +//UINT32 gameport_timeoutcounter = 0; +//UINT32 gameport_timeoutinterval = 0; +// joyflag bit:0 up +// bit:1 down +// bit:2 left +// bit:3 right +// bit:4 trigger1 (rapid) +// bit:5 trigger2 (rapid) +// bit:6 trigger1 +// bit:7 trigger2 +//void gameport_timeoutproc(NEVENTITEM item); +static void IOOUTCALL gameport_o4d2(UINT port, REG8 dat) +{ + REG8 joyflag; + joyflag = joymng_getstat(); + if(!joymng_available()){ + return; + } + gameport_joyflag_base = joyflag; + gameport_joyflag = ((joyflag >> 2) & 0x30) | ((joyflag << 2) & 0xc0) | 0x0f; +#if defined(SUPPORT_IA32_HAXM) + { + LARGE_INTEGER li = {0}; + if (QueryPerformanceFrequency(&gameport_qpf)) { + QueryPerformanceCounter(&li); + //li.QuadPart = li.QuadPart; + gameport_tsc = (UINT64)li.QuadPart; + gameport_useqpc = 1; + }else{ + gameport_tsc = CPU_MSR_TSC; + gameport_useqpc = 0; + } + } +#else +#if defined(USE_TSC) + if(CPU_REMCLOCK > 0){ + gameport_tsc = CPU_MSR_TSC - (UINT64)CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple; + }else{ + gameport_tsc = CPU_MSR_TSC; + } + gameport_tsccounter = 0; +#else + gameport_tsc = 0; +#endif +#endif + (void)port; +} +static REG8 IOINPCALL gameport_i4d2(UINT port) +{ + REG8 retval = 0xff; +#if defined(NP2_WIN) + UINT32 joyAnalogX; + UINT32 joyAnalogY; +#endif + UINT64 clockdiff; +#if defined(SUPPORT_IA32_HAXM) + LARGE_INTEGER li = { 0 }; + QueryPerformanceCounter(&li); +#endif + { + REG8 joyflag = joymng_getstat(); + gameport_joyflag = ((joyflag >> 2) & 0x30) | ((joyflag << 2) & 0xc0) | (gameport_joyflag & 0x0f); + } + if (!joymng_available()) + { + return 0xff; + } +#if defined(NP2_WIN) + joyAnalogX = joymng_getAnalogX(); + joyAnalogY = joymng_getAnalogY(); +#endif +#if defined(SUPPORT_IA32_HAXM) + if(gameport_useqpc){ + clockdiff = (unsigned long long)((UINT64)li.QuadPart - gameport_tsc); + gameport_clkmax = (UINT64)gameport_qpf.QuadPart / 1300; // とりあえず0.7msで・・・ + }else{ + clockdiff = CPU_MSR_TSC - gameport_tsc; + gameport_clkmax = pccore.realclock / 1430; // とりあえず0.7msで・・・ + } +#else +#if defined(USE_TSC) + if(CPU_REMCLOCK > 0){ + clockdiff = CPU_MSR_TSC - (UINT64)CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple - gameport_tsc; + }else{ + clockdiff = CPU_MSR_TSC - gameport_tsc; + } + gameport_clkmax = pccore.baseclock * pccore.maxmultiple / 1430; // とりあえず0.7msで・・・ +#if !defined(SUPPORT_IA32_HAXM) + if(gameport_tsccounter == 0 || !np2cfg.consttsc){ + gameport_clkmax = gameport_clkmax * pccore.maxmultiple / pccore.multiple; // CPUクロック依存の場合のfix + } +#endif +#else + gameport_clkmax = 32; + clockdiff = gameport_tsc; + gameport_tsc++; +#endif +#endif + if (np2cfg.analogjoy) + { + // アナログ入力タイプ +#if defined(NP2_WIN) + gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2 + (UINT32)((UINT64)(gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2 * 2) * joyAnalogX / 65535); + gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2 + (UINT32)((UINT64)(gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2 * 2) * joyAnalogY / 65535); +#else + gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2; + gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2; +#endif + } + else + { + // ON/OFFタイプ + gameport_threshold_x = gameport_clkmax / 2; + gameport_threshold_y = gameport_clkmax / 2; + if(~gameport_joyflag_base & 0x1){ + gameport_threshold_y = GAMEPORT_JOYCOUNTER_MGN2; + } + if(~gameport_joyflag_base & 0x2){ + gameport_threshold_y = gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2; + } + if(~gameport_joyflag_base & 0x4){ + gameport_threshold_x = GAMEPORT_JOYCOUNTER_MGN2; + } + if(~gameport_joyflag_base & 0x8){ + gameport_threshold_x = gameport_clkmax - GAMEPORT_JOYCOUNTER_MGN2; + } + } + retval = gameport_joyflag; + if(clockdiff >= (UINT64)gameport_threshold_x){ + gameport_joyflag &= ~0x01; + } + if(clockdiff >= (UINT64)gameport_threshold_y){ + gameport_joyflag &= ~0x02; + } + return retval; +} +#endif + +// ---- + +#ifdef USE_MAME +#define OPL3_SAMPLE_BUFFER 4096 +static INT16 oplfm_s1ls[OPL3_SAMPLE_BUFFER] = { 0 }; +static INT16 oplfm_s1rs[OPL3_SAMPLE_BUFFER] = { 0 }; +static INT16 oplfm_s2ls[OPL3_SAMPLE_BUFFER] = { 0 }; +static INT16 oplfm_s2rs[OPL3_SAMPLE_BUFFER] = { 0 }; +static void SOUNDCALL opl3gen_getpcm(void* opl3, SINT32 *pcm, UINT count) { + UINT i; + INT16 *buf[4]; + SINT32 *outbuf = pcm; + SINT32 oplfm_volume; + SINT32 midivolL = g_sb16.mixregexp[MIXER_MIDI_LEFT]; + SINT32 midivolR = g_sb16.mixregexp[MIXER_MIDI_RIGHT]; + SINT32 volL, volR; + oplfm_volume = np2cfg.vol_fm * np2cfg.vol_master / 100; + buf[0] = oplfm_s1ls; + buf[1] = oplfm_s1rs; + buf[2] = oplfm_s2ls; + buf[3] = oplfm_s2rs; + + // PCMサウンドバッファに送る + volL = oplfm_volume * midivolL * 2; + volR = oplfm_volume * midivolR * 2; + while (count > 0) { + int cc = MIN(count, OPL3_SAMPLE_BUFFER); + YMF262UpdateOne(opl3, buf, cc); + for (i = 0; i < cc; i++) { + outbuf[0] += (SINT32)((oplfm_s1ls[i] * volL / 255 * (SINT32)g_sb16.mixregexp[MIXER_MASTER_LEFT] / 255) >> 6); + outbuf[1] += (SINT32)((oplfm_s1rs[i] * volR / 255 * (SINT32)g_sb16.mixregexp[MIXER_MASTER_RIGHT] / 255) >> 6); + outbuf += 2; + } + count -= cc; + } +} + +static void SOUNDCALL opl3gen_getpcm_dummy(void* opl3, SINT32* pcm, UINT count) { + UINT i; + INT16* buf[4]; + INT16 s1l, s1r, s2l, s2r; + buf[0] = oplfm_s1ls; + buf[1] = oplfm_s1rs; + buf[2] = oplfm_s2ls; + buf[3] = oplfm_s2rs; + while (count > 0) { + int cc = MIN(count, OPL3_SAMPLE_BUFFER); + YMF262UpdateOne(opl3, buf, cc); + count -= cc; + } +} +#endif + +void boardsb16_reset(const NP2CFG *pConfig) { + DSP_INFO olddsp; +#ifdef USE_MAME + if (g_mame_opl3[G_OPL3_INDEX]) { + if (samplerate != soundcfg.rate) { + YMF262Shutdown(g_mame_opl3[G_OPL3_INDEX]); + g_mame_opl3[G_OPL3_INDEX] = YMF262Init(14400000, soundcfg.rate); + samplerate = soundcfg.rate; + } else { + YMF262ResetChip(g_mame_opl3[G_OPL3_INDEX], samplerate); + } + } +#endif + olddsp = g_sb16.dsp_info; // dsp_infoだけ初期化しない + ZeroMemory(&g_sb16, sizeof(g_sb16)); + g_sb16.dsp_info = olddsp; + // ボードデフォルト IO:D2 DMA:3 IRQ:5(INT1) + g_sb16.base = np2cfg.sndsb16io; //0xd2; + g_sb16.dmachnum = np2cfg.sndsb16dma; //0x3; + g_sb16.dmairq = np2cfg.sndsb16irq; //0x5; + ct1745io_reset(); + ct1741io_reset(); + + forceopl3mode = 0; + seqpos = 0; +} + +void boardsb16_bind(void) { + opl3_reset(&g_opl3[G_OPL3_INDEX], OPL3_HAS_OPL3L|OPL3_HAS_OPL3); + + ct1745io_bind(); + ct1741io_bind(); + + iocore_attachout(0x2000 + g_sb16.base, sb16_o2000); /* FM Music Register Address Port */ + iocore_attachout(0x2100 + g_sb16.base, sb16_o2100); /* FM Music Data Port */ + iocore_attachout(0x2200 + g_sb16.base, sb16_o2200); /* Advanced FM Music Register Address Port */ + iocore_attachout(0x2300 + g_sb16.base, sb16_o2300); /* Advanced FM Music Data Port */ + iocore_attachout(0x2800 + g_sb16.base, sb16_o2800); /* FM Music Register Port */ + iocore_attachout(0x2900 + g_sb16.base, sb16_o2900); /* FM Music Data Port */ + + iocore_attachinp(0x2000 + g_sb16.base, sb16_i2000); /* FM Music Status Port */ + iocore_attachinp(0x2200 + g_sb16.base, sb16_i2200); /* Advanced FM Music Status Port */ + iocore_attachinp(0x2800 + g_sb16.base, sb16_i2800); /* FM Music Status Port */ + +#if defined(SUPPORT_GAMEPORT) + iocore_attachout(0x0400 + g_sb16.base, gameport_o4d2); /* GAME Port */ + iocore_attachout(0x0500 + g_sb16.base, gameport_o4d2); /* GAME Port */ + iocore_attachout(0x0600 + g_sb16.base, gameport_o4d2); /* GAME Port */ + iocore_attachout(0x0700 + g_sb16.base, gameport_o4d2); /* GAME Port */ + iocore_attachinp(0x0400 + g_sb16.base, gameport_i4d2); /* GAME Port */ + iocore_attachinp(0x0500 + g_sb16.base, gameport_i4d2); /* GAME Port */ + iocore_attachinp(0x0600 + g_sb16.base, gameport_i4d2); /* GAME Port */ + iocore_attachinp(0x0700 + g_sb16.base, gameport_i4d2); /* GAME Port */ +#else + iocore_attachout(0x0400 + g_sb16.base, sb16_o0400); /* GAME Port */ + iocore_attachout(0x0500 + g_sb16.base, sb16_o0400); /* GAME Port */ + iocore_attachout(0x0600 + g_sb16.base, sb16_o0400); /* GAME Port */ + iocore_attachout(0x0700 + g_sb16.base, sb16_o0400); /* GAME Port */ + iocore_attachinp(0x0400 + g_sb16.base, sb16_i0400); /* GAME Port */ + iocore_attachinp(0x0500 + g_sb16.base, sb16_i0400); /* GAME Port */ + iocore_attachinp(0x0600 + g_sb16.base, sb16_i0400); /* GAME Port */ + iocore_attachinp(0x0700 + g_sb16.base, sb16_i0400); /* GAME Port */ +#endif + + iocore_attachout(0x8000 + g_sb16.base, sb16_o8000); /* MIDI Port */ + //iocore_attachout(0x8001 + g_sb16.base, sb16_o8100); /* MIDI Port 暫定 */ + iocore_attachout(0x8100 + g_sb16.base, sb16_o8100); /* MIDI Port */ + iocore_attachinp(0x8000 + g_sb16.base, sb16_i8000); /* MIDI Port */ + //iocore_attachinp(0x8001 + g_sb16.base, sb16_i8100); /* MIDI Port 暫定 */ + iocore_attachinp(0x8100 + g_sb16.base, sb16_i8100); /* MIDI Port */ + + iocore_attachout(0xC800 + g_sb16.base, sb16_o2000); /* FM Music Register Address Port */ + iocore_attachinp(0xC800 + g_sb16.base, sb16_i2000); /* FM Music Status Port */ + iocore_attachout(0xC900 + g_sb16.base, sb16_o2100); /* FM Music Data Port */ + iocore_attachout(0xCA00 + g_sb16.base, sb16_o2200); /* Advanced FM Music Register Address Port */ + iocore_attachinp(0xCA00 + g_sb16.base, sb16_i2200); /* Advanced FM Music Status Port */ + iocore_attachout(0xCB00 + g_sb16.base, sb16_o2300); /* Advanced FM Music Data Port */ + + // PC/AT互換機テスト + if(np2cfg.sndsb16at){ + iocore_attachout(0x388, sb16_o2000); /* FM Music Register Address Port */ + iocore_attachinp(0x388, sb16_i2000); /* FM Music Status Port */ + iocore_attachout(0x389, sb16_o2100); /* FM Music Data Port */ + iocore_attachout(0x38a, sb16_o2200); /* Advanced FM Music Register Address Port */ + iocore_attachinp(0x38a, sb16_i2200); /* Advanced FM Music Status Port */ + iocore_attachout(0x38b, sb16_o2300); /* Advanced FM Music Data Port */ + } + + if (!g_mame_opl3[G_OPL3_INDEX]) { +#ifdef USE_MAME + g_mame_opl3[G_OPL3_INDEX] = YMF262Init(14400000, np2cfg.samplingrate); +#endif + samplerate = np2cfg.samplingrate; + } + +#if defined(SUPPORT_GAMEPORT) + // ゲームポート割り当て 4d2h + if(np2cfg.gameport){ + iocore_attachout(0x0400 + g_sb16.base, gameport_o4d2); + iocore_attachinp(0x0400 + g_sb16.base, gameport_i4d2); + } +#endif + +#ifdef USE_MAME + if (!g_mame_opl3[G_OPL3_INDEX]) { + g_mame_opl3[G_OPL3_INDEX] = YMF262Init(14400000, np2cfg.samplingrate); + samplerate = np2cfg.samplingrate; + } +#endif + opl3_bind(&g_opl3[G_OPL3_INDEX]); // MAME使用の場合Key Display用 +#ifdef USE_MAME + if (g_opl3[G_OPL3_INDEX].userdata) { + // 外部音源を使用する場合 ダミー登録 + sound_streamregist(g_mame_opl3[G_OPL3_INDEX], (SOUNDCB)opl3gen_getpcm_dummy); + } + else { + // 外部音源を使用しない場合 PCM登録 + sound_streamregist(g_mame_opl3[G_OPL3_INDEX], (SOUNDCB)opl3gen_getpcm); + } +#endif +} +void boardsb16_unbind(void) { + ct1745io_unbind(); + ct1741io_unbind(); + + iocore_detachout(0x2000 + g_sb16.base); /* FM Music Register Address Port */ + iocore_detachout(0x2100 + g_sb16.base); /* FM Music Data Port */ + iocore_detachout(0x2200 + g_sb16.base); /* Advanced FM Music Register Address Port */ + iocore_detachout(0x2300 + g_sb16.base); /* Advanced FM Music Data Port */ + iocore_detachout(0x2800 + g_sb16.base); /* FM Music Register Port */ + iocore_detachout(0x2900 + g_sb16.base); /* FM Music Data Port */ + + iocore_detachinp(0x2000 + g_sb16.base); /* FM Music Status Port */ + iocore_detachinp(0x2200 + g_sb16.base); /* Advanced FM Music Status Port */ + iocore_detachinp(0x2800 + g_sb16.base); /* FM Music Status Port */ + + iocore_detachout(0x0400 + g_sb16.base); /* GAME Port */ + iocore_detachout(0x0500 + g_sb16.base); /* GAME Port */ + iocore_detachout(0x0600 + g_sb16.base); /* GAME Port */ + iocore_detachout(0x0700 + g_sb16.base); /* GAME Port */ + iocore_detachinp(0x0400 + g_sb16.base); /* GAME Port */ + iocore_detachinp(0x0500 + g_sb16.base); /* GAME Port */ + iocore_detachinp(0x0600 + g_sb16.base); /* GAME Port */ + iocore_detachinp(0x0700 + g_sb16.base); /* GAME Port */ + + iocore_detachout(0x8000 + g_sb16.base); /* MIDI Port */ + //iocore_detachout(0x8001 + g_sb16.base); /* MIDI Port 暫定 */ + iocore_detachout(0x8100 + g_sb16.base); /* MIDI Port */ + iocore_detachinp(0x8000 + g_sb16.base); /* MIDI Port */ + //iocore_detachinp(0x8001 + g_sb16.base); /* MIDI Port 暫定 */ + iocore_detachinp(0x8100 + g_sb16.base); /* MIDI Port */ + + iocore_detachout(0xC800 + g_sb16.base); /* FM Music Register Address Port */ + iocore_detachinp(0xC800 + g_sb16.base); /* FM Music Status Port */ + iocore_detachout(0xC900 + g_sb16.base); /* FM Music Data Port */ + iocore_detachout(0xCA00 + g_sb16.base); /* Advanced FM Music Register Address Port */ + iocore_detachinp(0xCA00 + g_sb16.base); /* Advanced FM Music Status Port */ + iocore_detachout(0xCB00 + g_sb16.base); /* Advanced FM Music Data Port */ + + // PC/AT互換機テスト + if(np2cfg.sndsb16at){ + iocore_detachout(0x388); /* FM Music Register Address Port */ + iocore_detachinp(0x388); /* FM Music Status Port */ + iocore_detachout(0x389); /* FM Music Data Port */ + iocore_detachout(0x38a); /* Advanced FM Music Register Address Port */ + iocore_detachinp(0x38a); /* Advanced FM Music Status Port */ + iocore_detachout(0x38b); /* Advanced FM Music Data Port */ + } + +#if defined(SUPPORT_GAMEPORT) + // ゲームポート割り当て 4d2h + if(np2cfg.gameport){ + iocore_detachout(0x0400 + g_sb16.base); + iocore_detachinp(0x0400 + g_sb16.base); + } +#endif +} +void boardsb16_finalize(void) +{ +#ifdef USE_MAME + if (g_mame_opl3[G_OPL3_INDEX]) { + YMF262Shutdown(g_mame_opl3[G_OPL3_INDEX]); + g_mame_opl3[G_OPL3_INDEX] = NULL; + } +#endif +} + +#endif diff --git a/cbus/boardso.c b/cbus/boardso.c old mode 100755 new mode 100644 index 9e116f19..600f97f3 --- a/cbus/boardso.c +++ b/cbus/boardso.c @@ -1,112 +1,112 @@ -/** - * @file boardso.c - * @brief Implementation of Sound Orchestra - */ - -#include -#include -#include -#include -#include -#include -#include - -#define G_OPL3_INDEX 2 - -static void IOOUTCALL opn_o188(UINT port, REG8 dat) -{ - g_opna[0].s.addrl = dat; - g_opna[0].s.data = dat; - (void)port; -} - -static void IOOUTCALL opn_o18a(UINT port, REG8 dat) -{ - g_opna[0].s.data = dat; - opna_writeRegister(&g_opna[0], g_opna[0].s.addrl, dat); - - (void)port; -} - -static REG8 IOINPCALL opn_i188(UINT port) -{ - (void)port; - return g_opna[0].s.status; -} - -static REG8 IOINPCALL opn_i18a(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[0].s.addrl; - if (nAddress == 0x0e) - { - return fmboard_getjoy(&g_opna[0]); - } - else if (nAddress < 0x10) - { - return opna_readRegister(&g_opna[0], nAddress); - } - - (void)port; - return g_opna[0].s.data; -} - -static void IOOUTCALL opl2_o18c(UINT port, REG8 dat) -{ - g_opl3[G_OPL3_INDEX].s.addrl = dat; -} - -static void IOOUTCALL opl2_o18e(UINT port, REG8 dat) -{ - opl3_writeRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl, dat); -} - -static REG8 IOINPCALL opl2_i18c(UINT port) -{ - return opl3_readStatus(&g_opl3[G_OPL3_INDEX]); -} - -static REG8 IOINPCALL opl2_i18e(UINT port) -{ - return opl3_readRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl); -} - - - -// ---- - -static const IOOUT opn_o[4] = { - opn_o188, opn_o18a, opl2_o18c, opl2_o18e}; - -static const IOINP opn_i[4] = { - opn_i188, opn_i18a, opl2_i18c, opl2_i18e}; - -/** - * Reset - * @param[in] pConfig A pointer to a configure structure - */ -void boardso_reset(const NP2CFG *pConfig, BOOL v) -{ - opna_reset(&g_opna[0], OPNA_MODE_2203 | OPNA_HAS_TIMER | OPNA_S98); - opna_timer(&g_opna[0], (pConfig->snd26opt & 0xc0) | 0x10, NEVENT_FMTIMERA, NEVENT_FMTIMERB); - opl3_reset(&g_opl3[G_OPL3_INDEX], (REG8)((v) ? OPL3_MODE_8950 : OPL3_MODE_3812)); - - opngen_setcfg(&g_opna[0].opngen, 3, 0x00); - soundrom_loadex(pConfig->snd26opt & 7, OEMTEXT("26")); - g_opna[0].s.base = (pConfig->snd26opt & 0x10) ? 0x000 : 0x100; -} - -/** - * Bind - */ -void boardso_bind(void) -{ - opna_bind(&g_opna[0]); - opl3_bind(&g_opl3[G_OPL3_INDEX]); - cbuscore_attachsndex(0x188 - g_opna[0].s.base, opn_o, opn_i); -} -void boardso_unbind(void) -{ - cbuscore_detachsndex(0x188 - g_opna[0].s.base); -} +/** + * @file boardso.c + * @brief Implementation of Sound Orchestra + */ + +#include +#include +#include +#include +#include +#include +#include + +#define G_OPL3_INDEX 2 + +static void IOOUTCALL opn_o188(UINT port, REG8 dat) +{ + g_opna[0].s.addrl = dat; + g_opna[0].s.data = dat; + (void)port; +} + +static void IOOUTCALL opn_o18a(UINT port, REG8 dat) +{ + g_opna[0].s.data = dat; + opna_writeRegister(&g_opna[0], g_opna[0].s.addrl, dat); + + (void)port; +} + +static REG8 IOINPCALL opn_i188(UINT port) +{ + (void)port; + return g_opna[0].s.status; +} + +static REG8 IOINPCALL opn_i18a(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[0].s.addrl; + if (nAddress == 0x0e) + { + return fmboard_getjoy(&g_opna[0]); + } + else if (nAddress < 0x10) + { + return opna_readRegister(&g_opna[0], nAddress); + } + + (void)port; + return g_opna[0].s.data; +} + +static void IOOUTCALL opl2_o18c(UINT port, REG8 dat) +{ + g_opl3[G_OPL3_INDEX].s.addrl = dat; +} + +static void IOOUTCALL opl2_o18e(UINT port, REG8 dat) +{ + opl3_writeRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl, dat); +} + +static REG8 IOINPCALL opl2_i18c(UINT port) +{ + return opl3_readStatus(&g_opl3[G_OPL3_INDEX]); +} + +static REG8 IOINPCALL opl2_i18e(UINT port) +{ + return opl3_readRegister(&g_opl3[G_OPL3_INDEX], g_opl3[G_OPL3_INDEX].s.addrl); +} + + + +// ---- + +static const IOOUT opn_o[4] = { + opn_o188, opn_o18a, opl2_o18c, opl2_o18e}; + +static const IOINP opn_i[4] = { + opn_i188, opn_i18a, opl2_i18c, opl2_i18e}; + +/** + * Reset + * @param[in] pConfig A pointer to a configure structure + */ +void boardso_reset(const NP2CFG *pConfig, BOOL v) +{ + opna_reset(&g_opna[0], OPNA_MODE_2203 | OPNA_HAS_TIMER | OPNA_S98); + opna_timer(&g_opna[0], (pConfig->snd26opt & 0xc0) | 0x10, NEVENT_FMTIMERA, NEVENT_FMTIMERB); + opl3_reset(&g_opl3[G_OPL3_INDEX], (REG8)((v) ? OPL3_MODE_8950 : OPL3_MODE_3812)); + + opngen_setcfg(&g_opna[0].opngen, 3, 0x00); + soundrom_loadex(pConfig->snd26opt & 7, OEMTEXT("26")); + g_opna[0].s.base = (pConfig->snd26opt & 0x10) ? 0x000 : 0x100; +} + +/** + * Bind + */ +void boardso_bind(void) +{ + opna_bind(&g_opna[0]); + opl3_bind(&g_opl3[G_OPL3_INDEX]); + cbuscore_attachsndex(0x188 - g_opna[0].s.base, opn_o, opn_i); +} +void boardso_unbind(void) +{ + cbuscore_detachsndex(0x188 - g_opna[0].s.base); +} diff --git a/cbus/boardso.h b/cbus/boardso.h old mode 100755 new mode 100644 index 1675a702..4984ff3b --- a/cbus/boardso.h +++ b/cbus/boardso.h @@ -1,21 +1,21 @@ -/** - * @file boardso.h - * @brief Interface of Sound Orchestra - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -void boardso_reset(const NP2CFG *pConfig, BOOL v); -void boardso_bind(void); -void boardso_unbind(void); - -#ifdef __cplusplus -} -#endif +/** + * @file boardso.h + * @brief Interface of Sound Orchestra + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +void boardso_reset(const NP2CFG *pConfig, BOOL v); +void boardso_bind(void); +void boardso_unbind(void); + +#ifdef __cplusplus +} +#endif diff --git a/cbus/boardspb.c b/cbus/boardspb.c old mode 100755 new mode 100644 index 7361299b..84819cf1 --- a/cbus/boardspb.c +++ b/cbus/boardspb.c @@ -1,235 +1,235 @@ -/** - * @file boardspb.c - * @brief Implementation of Speak board - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static int opna_idx = 0; - -static void IOOUTCALL spb_o188(UINT port, REG8 dat) -{ - g_opna[opna_idx].s.addrl = dat; -// g_opna[opna_idx].s.data = dat; - - (void)port; -} - -static void IOOUTCALL spb_o18a(UINT port, REG8 dat) -{ -// g_opna[opna_idx].s.data = dat; - opna_writeRegister(&g_opna[opna_idx], g_opna[opna_idx].s.addrl, dat); - - (void)port; -} - -static void IOOUTCALL spb_o18c(UINT port, REG8 dat) -{ - g_opna[opna_idx].s.addrh = dat; -// g_opna[opna_idx].s.data = dat; - (void)port; -} - -static void IOOUTCALL spb_o18e(UINT port, REG8 dat) -{ -// g_opna[opna_idx].s.data = dat; - opna_writeExtendedRegister(&g_opna[opna_idx], g_opna[opna_idx].s.addrh, dat); - - (void)port; -} - -static REG8 IOINPCALL spb_i188(UINT port) -{ - (void)port; - - return opna_readExtendedStatus(&g_opna[opna_idx]); -} - -static REG8 IOINPCALL spb_i18a(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[opna_idx].s.addrl; - if (nAddress == 0x0e) - { - return fmboard_getjoy(&g_opna[opna_idx]); - } - - (void)port; - return opna_readRegister(&g_opna[opna_idx], nAddress); -} - -static REG8 IOINPCALL spb_i18e(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[opna_idx].s.addrh; - if ((nAddress == 0x08) || (nAddress == 0x0f)) - { - return opna_readExtendedRegister(&g_opna[opna_idx], nAddress); - } - - (void)port; - return g_opna[opna_idx].s.reg[g_opna[opna_idx].s.addrl]; -} - - -// ---- spark board - -static void IOOUTCALL spr_o588(UINT port, REG8 dat) -{ - g_opna[1].s.addrl = dat; -// g_opna[1].s.data = dat; - (void)port; -} - -static void IOOUTCALL spr_o58a(UINT port, REG8 dat) -{ -// g_opna[1].s.data = dat; - S98_put(NORMAL2608_2, g_opna[1].s.addrl, dat); - opna_writeRegister(&g_opna[1], g_opna[1].s.addrl, dat); - - (void)port; -} - -static void IOOUTCALL spr_o58c(UINT port, REG8 dat) -{ - g_opna[1].s.addrh = dat; -// g_opna[1].s.data = dat; - (void)port; -} - -static void IOOUTCALL spr_o58e(UINT port, REG8 dat) -{ -// g_opna[1].s.data = dat; - opna_writeExtendedRegister(&g_opna[1], g_opna[1].s.addrh, dat); - - (void)port; -} - -static REG8 IOINPCALL spr_i588(UINT port) -{ - (void)port; - return g_opna[0].s.status; -} - -static REG8 IOINPCALL spr_i58a(UINT port) -{ - (void)port; - return opna_readRegister(&g_opna[1], g_opna[1].s.addrl); -} - -static REG8 IOINPCALL spr_i58c(UINT port) -{ - (void)port; - return (g_opna[0].s.status & 3); -} - -static REG8 IOINPCALL spr_i58e(UINT port) -{ - (void)port; - return opna_read3438ExtRegister(&g_opna[1], g_opna[1].s.addrl); -} - - -// ---- - -static const IOOUT spb_o[4] = -{ - spb_o188, spb_o18a, spb_o18c, spb_o18e -}; - -static const IOINP spb_i[4] = -{ - spb_i188, spb_i18a, spb_i188, spb_i18e -}; - -/** - * Reset - * @param[in] pConfig A pointer to a configure structure - */ -void boardspb_reset(const NP2CFG *pConfig, int opnaidx) -{ - opna_idx = opnaidx; - - opna_reset(&g_opna[opna_idx], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR | OPNA_S98); - if(opna_idx == 1){ - opna_timer(&g_opna[opna_idx], (pConfig->spbopt & 0xc0) | 0x10, NEVENT_FMTIMER2A, NEVENT_FMTIMER2B); - }else{ - opna_timer(&g_opna[opna_idx], (pConfig->spbopt & 0xc0) | 0x10, NEVENT_FMTIMERA, NEVENT_FMTIMERB); - } - - g_opna[opna_idx].s.extend = 1; // はじめからFM6音 - - opngen_setcfg(&g_opna[opna_idx].opngen, 6, OPN_STEREO | 0x3f); - soundrom_loadex(pConfig->spbopt & 7, OEMTEXT("SPB")); - g_opna[opna_idx].s.base = ((pConfig->spbopt & 0x10) ? 0x000 : 0x100); -} - -/** - * Bind - */ -void boardspb_bind(void) -{ - opna_bind(&g_opna[opna_idx]); - cbuscore_attachsndex(0x188 - g_opna[opna_idx].s.base, spb_o, spb_i); -} -void boardspb_unbind(void) -{ - cbuscore_detachsndex(0x188 - g_opna[opna_idx].s.base); -} - - -// ---- - -static const IOOUT spr_o[4] = { - spr_o588, spr_o58a, spr_o58c, spr_o58e}; - -static const IOINP spr_i[4] = { - spr_i588, spr_i58a, spr_i58c, spr_i58e}; - -/** - * Reset - * @param[in] pConfig A pointer to a configure structure - */ -void boardspr_reset(const NP2CFG *pConfig) -{ - opna_idx = 0; - - opna_reset(&g_opna[0], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR | OPNA_S98); - opna_timer(&g_opna[0], (pConfig->spbopt & 0xc0) | 0x10, NEVENT_FMTIMERA, NEVENT_FMTIMERB); - opna_reset(&g_opna[1], OPNA_MODE_3438 | OPNA_HAS_VR); - - g_opna[0].s.extend = 1; // はじめからFM6音 - g_opna[1].s.extend = 1; // はじめからFM6音 - - opngen_setcfg(&g_opna[0].opngen, 6, OPN_STEREO | 0x0f); - opngen_setcfg(&g_opna[1].opngen, 6, OPN_STEREO | 0x0f); - soundrom_loadex(pConfig->spbopt & 7, OEMTEXT("SPB")); - g_opna[0].s.base = (pConfig->spbopt & 0x10) ? 0x000 : 0x100; -} - -/** - * Bind - */ -void boardspr_bind(void) -{ - opna_bind(&g_opna[0]); - opna_bind(&g_opna[1]); - cbuscore_attachsndex(0x188 - g_opna[0].s.base, spb_o, spb_i); - cbuscore_attachsndex(0x588 - g_opna[0].s.base, spr_o, spr_i); -} -void boardspr_unbind(void) -{ - cbuscore_detachsndex(0x188 - g_opna[0].s.base); - cbuscore_detachsndex(0x588 - g_opna[0].s.base); -} - - +/** + * @file boardspb.c + * @brief Implementation of Speak board + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int opna_idx = 0; + +static void IOOUTCALL spb_o188(UINT port, REG8 dat) +{ + g_opna[opna_idx].s.addrl = dat; +// g_opna[opna_idx].s.data = dat; + + (void)port; +} + +static void IOOUTCALL spb_o18a(UINT port, REG8 dat) +{ +// g_opna[opna_idx].s.data = dat; + opna_writeRegister(&g_opna[opna_idx], g_opna[opna_idx].s.addrl, dat); + + (void)port; +} + +static void IOOUTCALL spb_o18c(UINT port, REG8 dat) +{ + g_opna[opna_idx].s.addrh = dat; +// g_opna[opna_idx].s.data = dat; + (void)port; +} + +static void IOOUTCALL spb_o18e(UINT port, REG8 dat) +{ +// g_opna[opna_idx].s.data = dat; + opna_writeExtendedRegister(&g_opna[opna_idx], g_opna[opna_idx].s.addrh, dat); + + (void)port; +} + +static REG8 IOINPCALL spb_i188(UINT port) +{ + (void)port; + + return opna_readExtendedStatus(&g_opna[opna_idx]); +} + +static REG8 IOINPCALL spb_i18a(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[opna_idx].s.addrl; + if (nAddress == 0x0e) + { + return fmboard_getjoy(&g_opna[opna_idx]); + } + + (void)port; + return opna_readRegister(&g_opna[opna_idx], nAddress); +} + +static REG8 IOINPCALL spb_i18e(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[opna_idx].s.addrh; + if ((nAddress == 0x08) || (nAddress == 0x0f)) + { + return opna_readExtendedRegister(&g_opna[opna_idx], nAddress); + } + + (void)port; + return g_opna[opna_idx].s.reg[g_opna[opna_idx].s.addrl]; +} + + +// ---- spark board + +static void IOOUTCALL spr_o588(UINT port, REG8 dat) +{ + g_opna[1].s.addrl = dat; +// g_opna[1].s.data = dat; + (void)port; +} + +static void IOOUTCALL spr_o58a(UINT port, REG8 dat) +{ +// g_opna[1].s.data = dat; + S98_put(NORMAL2608_2, g_opna[1].s.addrl, dat); + opna_writeRegister(&g_opna[1], g_opna[1].s.addrl, dat); + + (void)port; +} + +static void IOOUTCALL spr_o58c(UINT port, REG8 dat) +{ + g_opna[1].s.addrh = dat; +// g_opna[1].s.data = dat; + (void)port; +} + +static void IOOUTCALL spr_o58e(UINT port, REG8 dat) +{ +// g_opna[1].s.data = dat; + opna_writeExtendedRegister(&g_opna[1], g_opna[1].s.addrh, dat); + + (void)port; +} + +static REG8 IOINPCALL spr_i588(UINT port) +{ + (void)port; + return g_opna[0].s.status; +} + +static REG8 IOINPCALL spr_i58a(UINT port) +{ + (void)port; + return opna_readRegister(&g_opna[1], g_opna[1].s.addrl); +} + +static REG8 IOINPCALL spr_i58c(UINT port) +{ + (void)port; + return (g_opna[0].s.status & 3); +} + +static REG8 IOINPCALL spr_i58e(UINT port) +{ + (void)port; + return opna_read3438ExtRegister(&g_opna[1], g_opna[1].s.addrl); +} + + +// ---- + +static const IOOUT spb_o[4] = +{ + spb_o188, spb_o18a, spb_o18c, spb_o18e +}; + +static const IOINP spb_i[4] = +{ + spb_i188, spb_i18a, spb_i188, spb_i18e +}; + +/** + * Reset + * @param[in] pConfig A pointer to a configure structure + */ +void boardspb_reset(const NP2CFG *pConfig, int opnaidx) +{ + opna_idx = opnaidx; + + opna_reset(&g_opna[opna_idx], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR | OPNA_S98); + if(opna_idx == 1){ + opna_timer(&g_opna[opna_idx], (pConfig->spbopt & 0xc0) | 0x10, NEVENT_FMTIMER2A, NEVENT_FMTIMER2B); + }else{ + opna_timer(&g_opna[opna_idx], (pConfig->spbopt & 0xc0) | 0x10, NEVENT_FMTIMERA, NEVENT_FMTIMERB); + } + + g_opna[opna_idx].s.extend = 1; // はじめからFM6音 + + opngen_setcfg(&g_opna[opna_idx].opngen, 6, OPN_STEREO | 0x3f); + soundrom_loadex(pConfig->spbopt & 7, OEMTEXT("SPB")); + g_opna[opna_idx].s.base = ((pConfig->spbopt & 0x10) ? 0x000 : 0x100); +} + +/** + * Bind + */ +void boardspb_bind(void) +{ + opna_bind(&g_opna[opna_idx]); + cbuscore_attachsndex(0x188 - g_opna[opna_idx].s.base, spb_o, spb_i); +} +void boardspb_unbind(void) +{ + cbuscore_detachsndex(0x188 - g_opna[opna_idx].s.base); +} + + +// ---- + +static const IOOUT spr_o[4] = { + spr_o588, spr_o58a, spr_o58c, spr_o58e}; + +static const IOINP spr_i[4] = { + spr_i588, spr_i58a, spr_i58c, spr_i58e}; + +/** + * Reset + * @param[in] pConfig A pointer to a configure structure + */ +void boardspr_reset(const NP2CFG *pConfig) +{ + opna_idx = 0; + + opna_reset(&g_opna[0], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_HAS_ADPCM | OPNA_HAS_VR | OPNA_S98); + opna_timer(&g_opna[0], (pConfig->spbopt & 0xc0) | 0x10, NEVENT_FMTIMERA, NEVENT_FMTIMERB); + opna_reset(&g_opna[1], OPNA_MODE_3438 | OPNA_HAS_VR); + + g_opna[0].s.extend = 1; // はじめからFM6音 + g_opna[1].s.extend = 1; // はじめからFM6音 + + opngen_setcfg(&g_opna[0].opngen, 6, OPN_STEREO | 0x0f); + opngen_setcfg(&g_opna[1].opngen, 6, OPN_STEREO | 0x0f); + soundrom_loadex(pConfig->spbopt & 7, OEMTEXT("SPB")); + g_opna[0].s.base = (pConfig->spbopt & 0x10) ? 0x000 : 0x100; +} + +/** + * Bind + */ +void boardspr_bind(void) +{ + opna_bind(&g_opna[0]); + opna_bind(&g_opna[1]); + cbuscore_attachsndex(0x188 - g_opna[0].s.base, spb_o, spb_i); + cbuscore_attachsndex(0x588 - g_opna[0].s.base, spr_o, spr_i); +} +void boardspr_unbind(void) +{ + cbuscore_detachsndex(0x188 - g_opna[0].s.base); + cbuscore_detachsndex(0x588 - g_opna[0].s.base); +} + + diff --git a/cbus/boardspb.h b/cbus/boardspb.h old mode 100755 new mode 100644 index 9bacfe9a..19961532 --- a/cbus/boardspb.h +++ b/cbus/boardspb.h @@ -1,25 +1,25 @@ -/** - * @file boardspb.h - * @brief Interface of Speak board - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -void boardspb_reset(const NP2CFG *pConfig, int opnaidx); -void boardspb_bind(void); -void boardspb_unbind(void); - -void boardspr_reset(const NP2CFG *pConfig); -void boardspr_bind(void); -void boardspr_unbind(void); - -#ifdef __cplusplus -} -#endif +/** + * @file boardspb.h + * @brief Interface of Speak board + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +void boardspb_reset(const NP2CFG *pConfig, int opnaidx); +void boardspb_bind(void); +void boardspb_unbind(void); + +void boardspr_reset(const NP2CFG *pConfig); +void boardspr_bind(void); +void boardspr_unbind(void); + +#ifdef __cplusplus +} +#endif diff --git a/cbus/boardx2.c b/cbus/boardx2.c old mode 100755 new mode 100644 index c80118e7..7f90ef3f --- a/cbus/boardx2.c +++ b/cbus/boardx2.c @@ -1,230 +1,230 @@ -/** - * @file boardx2.c - * @brief Implementation of PC-9801-86 + 26K - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void IOOUTCALL opn_o088(UINT port, REG8 dat) -{ - g_opna[1].s.addrl = dat; - g_opna[1].s.data = dat; - (void)port; -} - -static void IOOUTCALL opn_o08a(UINT port, REG8 dat) -{ - g_opna[1].s.data = dat; - S98_put(NORMAL2608_2, g_opna[1].s.addrl, dat); - opna_writeRegister(&g_opna[1], g_opna[1].s.addrl, dat); - - (void)port; -} - -static REG8 IOINPCALL opn_i088(UINT port) -{ - (void)port; - return g_opna[1].s.status; -} - -static REG8 IOINPCALL opn_i08a(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[1].s.addrl; - if (nAddress == 0x0e) - { - return fmboard_getjoy(&g_opna[1]); - } - else if (nAddress < 0x10) - { - return opna_readRegister(&g_opna[1], nAddress); - } - - (void)port; - return g_opna[1].s.data; -} - - -// ---- - -static void IOOUTCALL opna_o188(UINT port, REG8 dat) -{ - g_opna[0].s.addrl = dat; - g_opna[0].s.data = dat; - (void)port; -} - -static void IOOUTCALL opna_o18a(UINT port, REG8 dat) -{ - g_opna[0].s.data = dat; - opna_writeRegister(&g_opna[0], g_opna[0].s.addrl, dat); - - (void)port; -} - -static void IOOUTCALL opna_o18c(UINT port, REG8 dat) -{ - if (g_opna[0].s.extend) - { - g_opna[0].s.addrh = dat; - g_opna[0].s.data = dat; - } - - (void)port; -} - -static void IOOUTCALL opna_o18e(UINT port, REG8 dat) -{ - if (g_opna[0].s.extend) - { - g_opna[0].s.data = dat; - opna_writeExtendedRegister(&g_opna[0], g_opna[0].s.addrh, dat); - } - - (void)port; -} - -static REG8 IOINPCALL opna_i188(UINT port) -{ - (void)port; - return g_opna[0].s.status; -} - -static REG8 IOINPCALL opna_i18a(UINT port) -{ - UINT nAddress; - - nAddress = g_opna[0].s.addrl; - if (nAddress == 0x0e) - { - return fmboard_getjoy(&g_opna[0]); - } - else if (nAddress < 0x10) - { - return opna_readRegister(&g_opna[0], nAddress); - } - else if (nAddress == 0xff) - { - return 1; - } - - (void)port; - return g_opna[0].s.data; -} - -static REG8 IOINPCALL opna_i18c(UINT port) -{ - if (g_opna[0].s.extend) - { - return opna_readExtendedStatus(&g_opna[0]); - } - - (void)port; - return 0xff; -} - -static REG8 IOINPCALL opna_i18e(UINT port) -{ - UINT nAddress; - - if (g_opna[0].s.extend) - { - nAddress = g_opna[0].s.addrh; - if ((nAddress == 0x08) || (nAddress == 0x0f)) - { - return opna_readExtendedRegister(&g_opna[0], nAddress); - } - return g_opna[0].s.data; - } - - (void)port; - return 0xff; -} - -static void extendchannel(REG8 enable) -{ - g_opna[0].s.extend = enable; - if (enable) - { - opngen_setcfg(&g_opna[0].opngen, 6, OPN_STEREO | 0x007); - } - else - { - opngen_setcfg(&g_opna[0].opngen, 3, OPN_MONORAL | 0x007); - rhythm_setreg(&g_opna[0].rhythm, 0x10, 0xff); - } -} - - -// ---- - -static const IOOUT opn_o[4] = { - opn_o088, opn_o08a, NULL, NULL}; - -static const IOINP opn_i[4] = { - opn_i088, opn_i08a, NULL, NULL}; - -static const IOOUT opna_o[4] = { - opna_o188, opna_o18a, opna_o18c, opna_o18e}; - -static const IOINP opna_i[4] = { - opna_i188, opna_i18a, opna_i18c, opna_i18e}; - - -/** - * Reset - * @param[in] pConfig A pointer to a configure structure - * @param[in] adpcm Enable ADPCM - */ -void boardx2_reset(const NP2CFG *pConfig) -{ - UINT nIrq1; - UINT nIrq2; - - nIrq1 = (pConfig->snd86opt & 0x10) | ((pConfig->snd86opt & 0x4) << 5) | ((pConfig->snd86opt & 0x8) << 3); - nIrq2 = (pConfig->snd26opt & 0xc0) | 0x10; - if (nIrq1 == nIrq2) - { - nIrq2 = (nIrq2 == 0xd0) ? 0x90 : 0xd0; - } - - opna_reset(&g_opna[0], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_S98); - opna_timer(&g_opna[0], nIrq1, NEVENT_FMTIMERA, NEVENT_FMTIMERB); - opna_reset(&g_opna[1], OPNA_MODE_2203); - opna_timer(&g_opna[1], nIrq2, NEVENT_FMTIMER2A, NEVENT_FMTIMER2B); - - opngen_setcfg(&g_opna[0].opngen, 3, OPN_STEREO | 0x038); - opngen_setcfg(&g_opna[1].opngen, 3, 0); - if (pConfig->snd86opt & 2) - { - soundrom_load(0xcc000, OEMTEXT("86")); - } - fmboard_extreg(extendchannel); - pcm86io_setopt(pConfig->snd86opt); -} - -void boardx2_bind(void) -{ - opna_bind(&g_opna[0]); - opna_bind(&g_opna[1]); - pcm86io_bind(); - cbuscore_attachsndex(0x088, opn_o, opn_i); - cbuscore_attachsndex(0x188, opna_o, opna_i); -} -void boardx2_unbind(void) -{ - pcm86io_unbind(); - cbuscore_detachsndex(0x088); - cbuscore_detachsndex(0x188); -} - - +/** + * @file boardx2.c + * @brief Implementation of PC-9801-86 + 26K + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void IOOUTCALL opn_o088(UINT port, REG8 dat) +{ + g_opna[1].s.addrl = dat; + g_opna[1].s.data = dat; + (void)port; +} + +static void IOOUTCALL opn_o08a(UINT port, REG8 dat) +{ + g_opna[1].s.data = dat; + S98_put(NORMAL2608_2, g_opna[1].s.addrl, dat); + opna_writeRegister(&g_opna[1], g_opna[1].s.addrl, dat); + + (void)port; +} + +static REG8 IOINPCALL opn_i088(UINT port) +{ + (void)port; + return g_opna[1].s.status; +} + +static REG8 IOINPCALL opn_i08a(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[1].s.addrl; + if (nAddress == 0x0e) + { + return fmboard_getjoy(&g_opna[1]); + } + else if (nAddress < 0x10) + { + return opna_readRegister(&g_opna[1], nAddress); + } + + (void)port; + return g_opna[1].s.data; +} + + +// ---- + +static void IOOUTCALL opna_o188(UINT port, REG8 dat) +{ + g_opna[0].s.addrl = dat; + g_opna[0].s.data = dat; + (void)port; +} + +static void IOOUTCALL opna_o18a(UINT port, REG8 dat) +{ + g_opna[0].s.data = dat; + opna_writeRegister(&g_opna[0], g_opna[0].s.addrl, dat); + + (void)port; +} + +static void IOOUTCALL opna_o18c(UINT port, REG8 dat) +{ + if (g_opna[0].s.extend) + { + g_opna[0].s.addrh = dat; + g_opna[0].s.data = dat; + } + + (void)port; +} + +static void IOOUTCALL opna_o18e(UINT port, REG8 dat) +{ + if (g_opna[0].s.extend) + { + g_opna[0].s.data = dat; + opna_writeExtendedRegister(&g_opna[0], g_opna[0].s.addrh, dat); + } + + (void)port; +} + +static REG8 IOINPCALL opna_i188(UINT port) +{ + (void)port; + return g_opna[0].s.status; +} + +static REG8 IOINPCALL opna_i18a(UINT port) +{ + UINT nAddress; + + nAddress = g_opna[0].s.addrl; + if (nAddress == 0x0e) + { + return fmboard_getjoy(&g_opna[0]); + } + else if (nAddress < 0x10) + { + return opna_readRegister(&g_opna[0], nAddress); + } + else if (nAddress == 0xff) + { + return 1; + } + + (void)port; + return g_opna[0].s.data; +} + +static REG8 IOINPCALL opna_i18c(UINT port) +{ + if (g_opna[0].s.extend) + { + return opna_readExtendedStatus(&g_opna[0]); + } + + (void)port; + return 0xff; +} + +static REG8 IOINPCALL opna_i18e(UINT port) +{ + UINT nAddress; + + if (g_opna[0].s.extend) + { + nAddress = g_opna[0].s.addrh; + if ((nAddress == 0x08) || (nAddress == 0x0f)) + { + return opna_readExtendedRegister(&g_opna[0], nAddress); + } + return g_opna[0].s.data; + } + + (void)port; + return 0xff; +} + +static void extendchannel(REG8 enable) +{ + g_opna[0].s.extend = enable; + if (enable) + { + opngen_setcfg(&g_opna[0].opngen, 6, OPN_STEREO | 0x007); + } + else + { + opngen_setcfg(&g_opna[0].opngen, 3, OPN_MONORAL | 0x007); + rhythm_setreg(&g_opna[0].rhythm, 0x10, 0xff); + } +} + + +// ---- + +static const IOOUT opn_o[4] = { + opn_o088, opn_o08a, NULL, NULL}; + +static const IOINP opn_i[4] = { + opn_i088, opn_i08a, NULL, NULL}; + +static const IOOUT opna_o[4] = { + opna_o188, opna_o18a, opna_o18c, opna_o18e}; + +static const IOINP opna_i[4] = { + opna_i188, opna_i18a, opna_i18c, opna_i18e}; + + +/** + * Reset + * @param[in] pConfig A pointer to a configure structure + * @param[in] adpcm Enable ADPCM + */ +void boardx2_reset(const NP2CFG *pConfig) +{ + UINT nIrq1; + UINT nIrq2; + + nIrq1 = (pConfig->snd86opt & 0x10) | ((pConfig->snd86opt & 0x4) << 5) | ((pConfig->snd86opt & 0x8) << 3); + nIrq2 = (pConfig->snd26opt & 0xc0) | 0x10; + if (nIrq1 == nIrq2) + { + nIrq2 = (nIrq2 == 0xd0) ? 0x90 : 0xd0; + } + + opna_reset(&g_opna[0], OPNA_MODE_2608 | OPNA_HAS_TIMER | OPNA_S98); + opna_timer(&g_opna[0], nIrq1, NEVENT_FMTIMERA, NEVENT_FMTIMERB); + opna_reset(&g_opna[1], OPNA_MODE_2203); + opna_timer(&g_opna[1], nIrq2, NEVENT_FMTIMER2A, NEVENT_FMTIMER2B); + + opngen_setcfg(&g_opna[0].opngen, 3, OPN_STEREO | 0x038); + opngen_setcfg(&g_opna[1].opngen, 3, 0); + if (pConfig->snd86opt & 2) + { + soundrom_load(0xcc000, OEMTEXT("86")); + } + fmboard_extreg(extendchannel); + pcm86io_setopt(pConfig->snd86opt); +} + +void boardx2_bind(void) +{ + opna_bind(&g_opna[0]); + opna_bind(&g_opna[1]); + pcm86io_bind(); + cbuscore_attachsndex(0x088, opn_o, opn_i); + cbuscore_attachsndex(0x188, opna_o, opna_i); +} +void boardx2_unbind(void) +{ + pcm86io_unbind(); + cbuscore_detachsndex(0x088); + cbuscore_detachsndex(0x188); +} + + diff --git a/cbus/boardx2.h b/cbus/boardx2.h old mode 100755 new mode 100644 index d9fd53ff..b852f596 --- a/cbus/boardx2.h +++ b/cbus/boardx2.h @@ -1,21 +1,21 @@ -/** - * @file boardx2.h - * @brief Interface of PC-9801-86 + 26K - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -void boardx2_reset(const NP2CFG *pConfig); -void boardx2_bind(void); -void boardx2_unbind(void); - -#ifdef __cplusplus -} -#endif +/** + * @file boardx2.h + * @brief Interface of PC-9801-86 + 26K + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +void boardx2_reset(const NP2CFG *pConfig); +void boardx2_bind(void); +void boardx2_unbind(void); + +#ifdef __cplusplus +} +#endif diff --git a/cbus/cbuscore.c b/cbus/cbuscore.c old mode 100755 new mode 100644 index d702e4de..70c50308 --- a/cbus/cbuscore.c +++ b/cbus/cbuscore.c @@ -1,150 +1,150 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef SUPPORT_SMPU98 -#include -#endif -#include -#ifdef SUPPORT_NET -#include -#endif -#ifdef SUPPORT_LGY98 -#include -#endif -#ifdef SUPPORT_WAB -#include -#endif -#ifdef SUPPORT_CL_GD5430 -#include -#endif -#ifdef SUPPORT_GPIB -#include -#endif - -static const FNIORESET resetfn[] = { -#if defined(SUPPORT_IDEIO) - ideio_reset, -#endif -#if defined(SUPPORT_NET) - np2net_reset, -#endif -#if defined(SUPPORT_LGY98) - lgy98_reset, -#endif -#if defined(SUPPORT_CL_GD5430) - pc98_cirrus_vga_reset, -#endif -#if defined(SUPPORT_WAB) - np2wab_reset, -#endif -#if defined(SUPPORT_SASI) - sasiio_reset, -#endif -#if defined(SUPPORT_SCSI) - scsiio_reset, -#endif -#if defined(SUPPORT_PC9861K) - pc9861k_reset, -#endif -#if defined(SUPPORT_GPIB) - gpibio_reset, -#endif -#if defined(SUPPORT_PEGC) - pegc_reset, -#endif - mpu98ii_reset, -#if defined(SUPPORT_SMPU98) - smpu98_reset, -#endif -#if defined(SUPPORT_BMS) - bmsio_reset, -#endif - }; - -static const FNIOBIND bindfn[] = { -#if defined(SUPPORT_IDEIO) - ideio_bind, -#endif -#if defined(SUPPORT_NET) - np2net_bind, -#endif -#if defined(SUPPORT_LGY98) - lgy98_bind, -#endif -#if defined(SUPPORT_WAB) - np2wab_bind, -#endif -#if defined(SUPPORT_CL_GD5430) - pc98_cirrus_vga_bind, -#endif -#if defined(SUPPORT_SASI) - sasiio_bind, -#endif -#if defined(SUPPORT_SCSI) - scsiio_bind, -#endif -#if defined(SUPPORT_PC9861K) - pc9861k_bind, -#endif -#if defined(SUPPORT_GPIB) - gpibio_bind, -#endif -#if defined(SUPPORT_PEGC) - pegc_bind, -#endif - mpu98ii_bind, -#if defined(SUPPORT_SMPU98) - smpu98_bind, -#endif -#if defined(SUPPORT_BMS) - bmsio_bind, -#endif - }; - - -void cbuscore_reset(const NP2CFG *pConfig) { - - iocore_cbreset(resetfn, NELEMENTS(resetfn), pConfig); -} - -void cbuscore_bind(void) { - - iocore_cbbind(bindfn, NELEMENTS(bindfn)); -} - - -void cbuscore_attachsndex(UINT port, const IOOUT *out, const IOINP *inp) { - - UINT i; - IOOUT outfn; - IOINP inpfn; - - for (i=0; i<4; i++) { - outfn = out[i]; - if (outfn) { - iocore_attachsndout(port, outfn); - } - inpfn = inp[i]; - if (inpfn) { - iocore_attachsndinp(port, inpfn); - } - port += 2; - } -} -void cbuscore_detachsndex(UINT port) { - - UINT i; - - for (i=0; i<4; i++) { - iocore_detachsndout(port); - iocore_detachsndinp(port); - port += 2; - } -} - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SUPPORT_SMPU98 +#include +#endif +#include +#ifdef SUPPORT_NET +#include +#endif +#ifdef SUPPORT_LGY98 +#include +#endif +#ifdef SUPPORT_WAB +#include +#endif +#ifdef SUPPORT_CL_GD5430 +#include +#endif +#ifdef SUPPORT_GPIB +#include +#endif + +static const FNIORESET resetfn[] = { +#if defined(SUPPORT_IDEIO) + ideio_reset, +#endif +#if defined(SUPPORT_NET) + np2net_reset, +#endif +#if defined(SUPPORT_LGY98) + lgy98_reset, +#endif +#if defined(SUPPORT_CL_GD5430) + pc98_cirrus_vga_reset, +#endif +#if defined(SUPPORT_WAB) + np2wab_reset, +#endif +#if defined(SUPPORT_SASI) + sasiio_reset, +#endif +#if defined(SUPPORT_SCSI) + scsiio_reset, +#endif +#if defined(SUPPORT_PC9861K) + pc9861k_reset, +#endif +#if defined(SUPPORT_GPIB) + gpibio_reset, +#endif +#if defined(SUPPORT_PEGC) + pegc_reset, +#endif + mpu98ii_reset, +#if defined(SUPPORT_SMPU98) + smpu98_reset, +#endif +#if defined(SUPPORT_BMS) + bmsio_reset, +#endif + }; + +static const FNIOBIND bindfn[] = { +#if defined(SUPPORT_IDEIO) + ideio_bind, +#endif +#if defined(SUPPORT_NET) + np2net_bind, +#endif +#if defined(SUPPORT_LGY98) + lgy98_bind, +#endif +#if defined(SUPPORT_WAB) + np2wab_bind, +#endif +#if defined(SUPPORT_CL_GD5430) + pc98_cirrus_vga_bind, +#endif +#if defined(SUPPORT_SASI) + sasiio_bind, +#endif +#if defined(SUPPORT_SCSI) + scsiio_bind, +#endif +#if defined(SUPPORT_PC9861K) + pc9861k_bind, +#endif +#if defined(SUPPORT_GPIB) + gpibio_bind, +#endif +#if defined(SUPPORT_PEGC) + pegc_bind, +#endif + mpu98ii_bind, +#if defined(SUPPORT_SMPU98) + smpu98_bind, +#endif +#if defined(SUPPORT_BMS) + bmsio_bind, +#endif + }; + + +void cbuscore_reset(const NP2CFG *pConfig) { + + iocore_cbreset(resetfn, NELEMENTS(resetfn), pConfig); +} + +void cbuscore_bind(void) { + + iocore_cbbind(bindfn, NELEMENTS(bindfn)); +} + + +void cbuscore_attachsndex(UINT port, const IOOUT *out, const IOINP *inp) { + + UINT i; + IOOUT outfn; + IOINP inpfn; + + for (i=0; i<4; i++) { + outfn = out[i]; + if (outfn) { + iocore_attachsndout(port, outfn); + } + inpfn = inp[i]; + if (inpfn) { + iocore_attachsndinp(port, inpfn); + } + port += 2; + } +} +void cbuscore_detachsndex(UINT port) { + + UINT i; + + for (i=0; i<4; i++) { + iocore_detachsndout(port); + iocore_detachsndinp(port); + port += 2; + } +} + diff --git a/cbus/cbuscore.h b/cbus/cbuscore.h old mode 100755 new mode 100644 index 0bd57dbf..9cf84906 --- a/cbus/cbuscore.h +++ b/cbus/cbuscore.h @@ -1,15 +1,15 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void cbuscore_reset(const NP2CFG *pConfig); -void cbuscore_bind(void); - -void cbuscore_attachsndex(UINT port, const IOOUT *out, const IOINP *inp); -void cbuscore_detachsndex(UINT port); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void cbuscore_reset(const NP2CFG *pConfig); +void cbuscore_bind(void); + +void cbuscore_attachsndex(UINT port, const IOOUT *out, const IOINP *inp); +void cbuscore_detachsndex(UINT port); + +#ifdef __cplusplus +} +#endif + diff --git a/cbus/cs4231io.c b/cbus/cs4231io.c old mode 100755 new mode 100644 index 9525a099..fccae5db --- a/cbus/cs4231io.c +++ b/cbus/cs4231io.c @@ -1,526 +1,526 @@ -#include -#include -#include -#include -#include -#include -#include -#include - - -static const UINT8 cs4231dma[] = {0xff,0x00,0x01,0x03,0xff,0x00,0x01,0x03}; -static const UINT8 cs4231irq[] = {0xff,0x03,0x06,0x0a,0x0c,0xff,0xff,0xff}; - - -static void IOOUTCALL csctrl_oc24(UINT port, REG8 dat) { - - cs4231.portctrl = dat; - (void)port; -} - -static void IOOUTCALL csctrl_oc2b(UINT port, REG8 dat) { - - UINT num; - - if ((cs4231.portctrl & 0x60) == 0x60) { - num = cs4231.portctrl & 0xf; - cs4231.port[num] &= 0xff00; - cs4231.port[num] |= dat; - } - (void)port; -} - -static void IOOUTCALL csctrl_oc2d(UINT port, REG8 dat) { - - UINT num; - - if ((cs4231.portctrl & 0x60) == 0x60) { - num = cs4231.portctrl & 0xf; - cs4231.port[num] &= 0x00ff; - cs4231.port[num] |= (dat << 8); - } - (void)port; -} - -static REG8 IOINPCALL csctrl_ic24(UINT port) { - - (void)port; - return((0xe0 | cs4231.portctrl)); -} - -static REG8 IOINPCALL csctrl_ic2b(UINT port) { - - UINT num; - - (void)port; - num = cs4231.portctrl & 0xf; - - return((REG8)(cs4231.port[num] & 0xff)); - -} - -static REG8 IOINPCALL csctrl_ic2d(UINT port) { - - UINT num; - - (void)port; - num = cs4231.portctrl & 0xf; - return((REG8)(cs4231.port[num] >> 8)); -} -REG8 sa3_control; -REG8 sa3_control; -UINT8 sa3data[256]; -static void IOOUTCALL csctrl_o480(UINT port, REG8 dat) { - - sa3_control = dat; - (void)port; - -} -static REG8 IOINPCALL csctrl_i480(UINT port) { - TRACEOUT(("read %x",port)); - return sa3_control; - (void)port; - -} -static void IOOUTCALL csctrl_o481(UINT port, REG8 dat) { - sa3data[sa3_control] = dat; - (void)port; - -} -static REG8 IOINPCALL csctrl_i481(UINT port) { - TRACEOUT(("read %x",port)); - (void)port; - return sa3data[sa3_control]; -} -REG8 f4a_control; -UINT8 f4bdata[256]; -static void IOOUTCALL csctrl_of4a(UINT port, REG8 dat) { - f4a_control = dat; - (void)port; -} - -static REG8 IOINPCALL csctrl_if4a(UINT port) { - TRACEOUT(("read %x",port)); - return f4a_control; - (void)port; -} - -static void IOOUTCALL csctrl_of4b(UINT port, REG8 dat) { - f4bdata[f4a_control] = dat; - (void)port; -} - -static REG8 IOINPCALL csctrl_if4b(UINT port) { - TRACEOUT(("read %x",port)); - (void)port; - return f4bdata[f4a_control]; -} - -static REG8 IOINPCALL csctrl_iac6d(UINT port) { - TRACEOUT(("read %x",port)); - (void)port; - return (0x54); -} - - -static REG8 IOINPCALL csctrl_iac6e(UINT port) { - - (void)port; - return 0; -} - -static REG8 IOINPCALL srnf_i51ee(UINT port) { - TRACEOUT(("read %x",port)); - (void)port; - return (0x02); -} - -static REG8 IOINPCALL srnf_i51ef(UINT port) { - TRACEOUT(("read %x",port)); - (void)port; - return 0xc2; -} - -static REG8 IOINPCALL srnf_i56ef(UINT port) { - TRACEOUT(("read %x",port)); - (void)port; - return (0x9f); -} -static REG8 IOINPCALL srnf_i57ef(UINT port) { - TRACEOUT(("read %x",port)); - (void)port; - return (0xc0); -} - -static REG8 IOINPCALL srnf_i59ef(UINT port) { - TRACEOUT(("read %x",port)); - (void)port; - return 0x3; -} - -static REG8 IOINPCALL srnf_i5bef(UINT port) { - TRACEOUT(("read %x",port)); - (void)port; - return (0x0e); -} - -static REG8 IOINPCALL ifab(UINT port) { - TRACEOUT(("read %x",port)); - (void)port; - return (0); -} - -// ---- - -void cs4231io_reset(void) { - - UINT8 sndirq, snddma; - - cs4231.enable = 1; - -/* [cs4231.adrsの書き方] - bit - 7 未使用 - R/W 6 不明 - R/W 5-3 PCM音源割り込みアドレス - 000b= サウンド機能を使用しない - 001b= INT 0 - 010b= INT 1 - 011b= INT 41 - 100b= INT 5 - R/W 2-0 DMAチャネル設定 - 000b= DMAを使用しない - 001b= DMA #0 - 010b= DMA #1 (PC-9821Npを除く) - 011b= DMA #3 - 100b〜101b= 未定義 - 111b= DMAを使用しない -*/ - if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ - sndirq = np2cfg.sndwssirq; - snddma = np2cfg.sndwssdma; - //cs4231.adrs = 0x0a;////0b00 001 010 INT0 DMA1 - //cs4231.adrs = 0x22;////0b00 100 010 INT5 DMA1 - }else if(g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ - UINT8 irq86table[4] = {0x03, 0x0d, 0x0a, 0x0c}; - UINT8 nIrq86 = (np2cfg.snd86opt & 0x10) | ((np2cfg.snd86opt & 0x4) << 5) | ((np2cfg.snd86opt & 0x8) << 3); - UINT8 irq86 = irq86table[nIrq86 >> 6]; - sndirq = np2cfg.snd118irqp; - snddma = np2cfg.snd118dma; - if(sndirq == irq86){ - if(irq86!=3){ - sndirq = 0x3; - }else{ - sndirq = 0xC; - } - } - }else if(g_nSoundID==SOUNDID_WAVESTAR){ - //UINT8 irq86table[4] = {0x03, 0x0d, 0x0a, 0x0c}; - //UINT8 nIrq86 = (np2cfg.snd86opt & 0x10) | ((np2cfg.snd86opt & 0x4) << 5) | ((np2cfg.snd86opt & 0x8) << 3); - //UINT8 irq86 = irq86table[nIrq86 >> 6]; - sndirq = 12;// IRQ12固定 irq86; - snddma = 3;// DMA#3固定 np2cfg.snd118dma; - }else{ - sndirq = np2cfg.snd118irqp; - snddma = np2cfg.snd118dma; - //cs4231.adrs = 0x23;////0b00 100 011 INT5 DMA3 - } - cs4231.adrs = 0; - switch(sndirq){ - case 3: - cs4231.adrs |= (0x1 << 3); - break; - case 5: - cs4231.adrs |= (0x2 << 3); - break; - case 10: - cs4231.adrs |= (0x3 << 3); - break; - case 12: - cs4231.adrs |= (0x4 << 3); - break; - default: - break; - } - switch(snddma){ - case 0: - cs4231.adrs |= (0x1); - break; - case 1: - cs4231.adrs |= (0x2); - break; - case 3: - cs4231.adrs |= (0x3); - break; - default: - break; - } - cs4231.dmairq = cs4231irq[(cs4231.adrs >> 3) & 7]; // IRQをセット - cs4231.dmach = cs4231dma[cs4231.adrs & 7]; // DMAチャネルをセット - cs4231.port[0] = 0x0f40; //WSS BASE I/O port - if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ - cs4231.port[1] = 0xb460; // Sound ID I/O port (A460hは86音源が使うのでB460hに変更) - }else{ - cs4231.port[1] = 0xa460; // Sound ID I/O port - } - cs4231.port[2] = 0x0f48; // WSS FIFO port - cs4231.port[4] = np2cfg.snd118io;//0x0188; // OPN port - cs4231.port[5] = 0x0f4a; // canbe mixer i/o port? - cs4231.port[6] = 0x548e; // YMF-701/715? - cs4231.port[8] = 0x1480; // Joystick - cs4231.port[9] = 0x1488; // OPL3 - cs4231.port[10] = 0x148c; // MIDI - cs4231.port[11] = 0x0480; //9801-118 control? - cs4231.port[14] = 0x148e; //9801-118 config - cs4231.port[15] = 0xa460; //空いてるのでこっちを利用 - - TRACEOUT(("CS4231 - IRQ = %d", cs4231.dmairq)); - TRACEOUT(("CS4231 - DMA channel = %d", cs4231.dmach)); - cs4231.reg.aux1_l = 0x88;//2 - cs4231.reg.aux1_r = 0x88;//3 - cs4231.reg.aux2_l = 0x88;//4 - cs4231.reg.aux2_r = 0x88;//5 - cs4231.reg.iface = 0x08;//9 - cs4231.reg.mode_id = 0xca;//c from PC-9821Nr166 - cs4231.reg.featurefunc[0]=0x80; //10 from PC-9821Nr166 - cs4231.reg.line_l = 0x88;//12 - cs4231.reg.line_r = 0x88;//13 - cs4231.reg.reserved1=0x80; //16 from PC-9821Nr166 - cs4231.reg.reserved2=0x80; //17 from PC-9821Nr166 - if(g_nSoundID==SOUNDID_PC_9801_118 || g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ - cs4231.reg.chipid =0xa2;//19 from PC-9801-118 CS4231 - }else{ - cs4231.reg.chipid =0x80;//19 from PC-9821Nr166 YMF715 - } - cs4231.reg.monoinput=0xc0;//1a from PC-9821Nr166 - cs4231.reg.reserved3=0x80; //1b from PC-9821Nr166 - cs4231.reg.reserved4=0x80; //1d from PC-9821Nr166 - cs4231.intflag = 0xcc; - - sa3data[7] = 7; - sa3data[8] = 7; - switch (cs4231.dmairq){ - case 0x0c:f4bdata[1] = 0;break; - case 0x0a:f4bdata[1] = 0x02;break; - case 0x03:f4bdata[1] = 0x03;break; - case 0x05:f4bdata[1] = 0x08;break; - } -} - -void cs4231io_bind(void) { - - sound_streamregist(&cs4231, (SOUNDCB)cs4231_getpcm); // CS4231用 オーディオ再生ストリーム - if(g_nSoundID!=SOUNDID_WAVESTAR){ - iocore_attachout(0xc24, csctrl_oc24); - iocore_attachout(0xc2b, csctrl_oc2b); - iocore_attachout(0xc2d, csctrl_oc2d); - iocore_attachinp(0xc24, csctrl_ic24); - iocore_attachinp(0xc2b, csctrl_ic2b); - iocore_attachinp(0xc2d, csctrl_ic2d); - } - if (cs4231.dmach != 0xff) { - dmac_attach(DMADEV_CS4231, cs4231.dmach); // CS4231のDMAチャネルを割り当て - } - if(!(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16)){ - iocore_attachout(0x480, csctrl_o480); - iocore_attachinp(0x480, csctrl_i480); - iocore_attachinp(0x481, csctrl_i481); - iocore_attachinp(0xac6d, csctrl_iac6d); - iocore_attachinp(0xac6e, csctrl_iac6e); - -/* 必要な時だけ有効にすべき -//WSN-F??? - iocore_attachinp(0x51ee, srnf_i51ee);//7番めに読まれる - iocore_attachinp(0x51ef, srnf_i51ef);//1番最初にC2を返す -// iocore_attachinp(0x52ef, srnf_i52ef);//f40等を読み書きしたあとここを読んでエラー - iocore_attachinp(0x56ef, srnf_i56ef);//2番めに読まれて割り込み等の設定? 4番めに2回読まれ直す - iocore_attachinp(0x57ef, srnf_i57ef);//5番めに読まれる - iocore_attachinp(0x59ef, srnf_i59ef);//3番めに読まれて何か調査 3と4でとりあえず通る -// iocore_attachinp(0x5aef, srnf_i5aef);//8番めに読まれて終わり - iocore_attachinp(0x5bef, srnf_i5bef);//6番めに読まれる -*/ - } -} -void cs4231io_unbind(void) { - - iocore_detachout(0xc24); - iocore_detachout(0xc2b); - iocore_detachout(0xc2d); - iocore_detachinp(0xc24); - iocore_detachinp(0xc2b); - iocore_detachinp(0xc2d); - if (cs4231.dmach != 0xff) { - dmac_detach(DMADEV_CS4231); // CS4231のDMAチャネルを割り当て - } - if(!(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WAVESTAR || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16)){ - iocore_detachout(0x480); - iocore_detachinp(0x480); - iocore_detachinp(0x481); - iocore_detachinp(0xac6d); - iocore_detachinp(0xac6e); - -/* 必要な時だけ有効にすべき -//WSN-F??? - iocore_detachinp(0x51ee);//7番めに読まれる - iocore_detachinp(0x51ef);//1番最初にC2を返す -// iocore_detachinp(0x52ef);//f40等を読み書きしたあとここを読んでエラー - iocore_detachinp(0x56ef);//2番めに読まれて割り込み等の設定? 4番めに2回読まれ直す - iocore_detachinp(0x57ef);//5番めに読まれる - iocore_detachinp(0x59ef);//3番めに読まれて何か調査 3と4でとりあえず通る -// iocore_detachinp(0x5aef);//8番めに読まれて終わり - iocore_detachinp(0x5bef);//6番めに読まれる -*/ - } -} - -int acicounter; -// CS4231 I/O WRITE -void IOOUTCALL cs4231io0_w8(UINT port, REG8 value) { - - switch(port - cs4231.port[0]) { - case 0x00: // PCM音源の割り込みアドレス設定 - cs4231.adrs = value &= ~0x40; - cs4231.dmairq = cs4231irq[(value >> 3) & 7]; - cs4231.dmach = cs4231dma[value & 7]; - dmac_detach(DMADEV_CS4231); - if (cs4231.dmach != 0xff) { - if ((cs4231.adrs >> 2) & 1){ - if (cs4231.dmach == 0)dmac_attach(DMADEV_NONE, 1); - else dmac_attach(DMADEV_NONE, 0); - } - dmac_attach(DMADEV_CS4231, cs4231.dmach); // CS4231のDMAチャネルを割り当て - // DMA読み取り位置を戻す - { - DMACH dmach = dmac.dmach + cs4231.dmach; - dmach->adrs.d = dmach->startaddr; - } -#if 0 - if (cs4231.reg.iface & SDC) { - dmac.dmach[cs4231.dmach].ready = 1; - dmac_check(); - } -#endif - } - break; - - case 0x04: // Index Address Register (R0) INIT MCE TRD IA4 IA3 IA2 IA1 IA0 - if ( !(cs4231.index & MCE) && (value & MCE) && (cs4231.reg.iface & (CAL0|CAL1) ) ) acicounter = 1; - if (!(cs4231.index & MCE)) cs4231.intflag |= (PRDY|CRDY); - cs4231.index = value & ~(INIT|TRD); - break; - case 0x05: // Indexed Data Register (R1) ID7 ID6 ID5 ID4 ID3 ID2 ID1 ID0 - cs4231_control(cs4231.index & 0x1f, value); // cs4231c.c内で処理 - break; - - case 0x06: // Status Register (R2, Read Only) CU/L CL/R CRDY SER PU/L PL/R PRDY INT - // PI,CI,TI割り込みビットを全部クリア - if (cs4231.intflag & INt) { - pic_resetirq(cs4231.dmairq); - //nevent_set(NEVENT_CS4231, 0, cs4231_dma, NEVENT_ABSOLUTE); - } - cs4231.intflag &= ~INt; - cs4231.reg.featurestatus &= ~(PI|TI|CI); - break; - - case 0x07: // Capture I/O Data Register (R3, Read Only) CD7 CD6 CD5 CD4 CD3 CD2 CD1 CD0 - cs4231_datasend(value); - break; - } -} -void IOOUTCALL cs4231io0_w8_wavestar(UINT port, REG8 value) { - cs4231io0_w8(((port - 0xA460) >> 1) + cs4231.port[0] + 1, value); -} -// CS4231 I/O READ -REG8 IOINPCALL cs4231io0_r8(UINT port) { - - switch(port - cs4231.port[0]) { - case 0x00: // PCM音源の割り込みアドレス設定 - return(cs4231.adrs); - case 0x03: // Windows Sound System ID (Read Only) - return(0x04); -// return(0x05);//PC-9821Nr - case 0x04: // Index Address Register (R0) INIT MCE TRD IA4 IA3 IA2 IA1 IA0 - return(cs4231.index & ~(INIT|TRD|MCE)); - case 0x05: // Indexed Data Register (R1) ID7 ID6 ID5 ID4 ID3 ID2 ID1 ID0 - { - switch (cs4231.index & 0x1f){ - case 0x0b: // Error Status and Initialization (I11, Read Only) COR PUR ACI DRS ORR1 ORR0 ORL1 ORL0 - if(acicounter){ - TRACEOUT(("acicounter")); - acicounter -= 1; - cs4231.reg.errorstatus |= ACI; - }else{ - cs4231.reg.errorstatus &= ~ACI; - } - break; - case 0x0d: // Loopback Control (I13) LBA5 LBA4 LBA3 LBA2 LBA1 LBA0 res LBE - return 0; - default: - break; - } - return(*(((UINT8 *)(&cs4231.reg)) + (cs4231.index & 0x1f))); - } - case 0x06: // Status Register (R2, Read Only) CU/L CL/R CRDY SER PU/L PL/R PRDY INT - if (cs4231.reg.errorstatus & (1 << 6)) cs4231.intflag |= SER; - return (cs4231.intflag); - case 0x07: // Capture I/O Data Register (R3, Read Only) CD7 CD6 CD5 CD4 CD3 CD2 CD1 CD0 - return (0x80); - } - return(0); -} -REG8 IOINPCALL cs4231io0_r8_wavestar(UINT port) { - return cs4231io0_r8(((port - 0xA460) >> 1) + cs4231.port[0] + 1); -} - -// canbe mixer i/o port? WRITE -void IOOUTCALL cs4231io5_w8(UINT port, REG8 value) { - - switch(port - cs4231.port[5]) { - case 0x00: - cs4231.extindex = value; - break; - - case 0x01: - switch(cs4231.extindex){ - case 0x02: // MODEM L ? - case 0x03: // MODEM R ? - case 0x30: // FM音源 L - case 0x31: // FM音源 R - case 0x32: // CD-DA L - case 0x33: // CD-DA R - case 0x34: // TV L - case 0x35: // TV R - case 0x36: // MODEM mono ? - // bit7:mute, bit6,5:reserved, bit4-0:volume(00000(MAX) - 11111(MIN)) - cs4231.devvolume[cs4231.extindex] = value; - } - break; - } -} -// canbe mixer i/o port? READ -REG8 IOINPCALL cs4231io5_r8(UINT port) { - - switch(port - cs4231.port[5]) { - case 0x00: - return(cs4231.extindex); - - case 0x01: - switch(cs4231.extindex){ - case 1: - return(0); // means opna int5 ??? - case 0x02: // MODEM L ? - case 0x03: // MODEM R ? - case 0x30: // FM音源 L - case 0x31: // FM音源 R - case 0x32: // CD-DA L - case 0x33: // CD-DA R - case 0x34: // TV L - case 0x35: // TV R - case 0x36: // MODEM mono ? - // bit7:mute, bit6,5:reserved, bit4-0:volume(00000(MAX) - 11111(MIN)) - return cs4231.devvolume[cs4231.extindex]; - } - break; - } - return(0xff); -} +#include +#include +#include +#include +#include +#include +#include +#include + + +static const UINT8 cs4231dma[] = {0xff,0x00,0x01,0x03,0xff,0x00,0x01,0x03}; +static const UINT8 cs4231irq[] = {0xff,0x03,0x06,0x0a,0x0c,0xff,0xff,0xff}; + + +static void IOOUTCALL csctrl_oc24(UINT port, REG8 dat) { + + cs4231.portctrl = dat; + (void)port; +} + +static void IOOUTCALL csctrl_oc2b(UINT port, REG8 dat) { + + UINT num; + + if ((cs4231.portctrl & 0x60) == 0x60) { + num = cs4231.portctrl & 0xf; + cs4231.port[num] &= 0xff00; + cs4231.port[num] |= dat; + } + (void)port; +} + +static void IOOUTCALL csctrl_oc2d(UINT port, REG8 dat) { + + UINT num; + + if ((cs4231.portctrl & 0x60) == 0x60) { + num = cs4231.portctrl & 0xf; + cs4231.port[num] &= 0x00ff; + cs4231.port[num] |= (dat << 8); + } + (void)port; +} + +static REG8 IOINPCALL csctrl_ic24(UINT port) { + + (void)port; + return((0xe0 | cs4231.portctrl)); +} + +static REG8 IOINPCALL csctrl_ic2b(UINT port) { + + UINT num; + + (void)port; + num = cs4231.portctrl & 0xf; + + return((REG8)(cs4231.port[num] & 0xff)); + +} + +static REG8 IOINPCALL csctrl_ic2d(UINT port) { + + UINT num; + + (void)port; + num = cs4231.portctrl & 0xf; + return((REG8)(cs4231.port[num] >> 8)); +} +REG8 sa3_control; +REG8 sa3_control; +UINT8 sa3data[256]; +static void IOOUTCALL csctrl_o480(UINT port, REG8 dat) { + + sa3_control = dat; + (void)port; + +} +static REG8 IOINPCALL csctrl_i480(UINT port) { + TRACEOUT(("read %x",port)); + return sa3_control; + (void)port; + +} +static void IOOUTCALL csctrl_o481(UINT port, REG8 dat) { + sa3data[sa3_control] = dat; + (void)port; + +} +static REG8 IOINPCALL csctrl_i481(UINT port) { + TRACEOUT(("read %x",port)); + (void)port; + return sa3data[sa3_control]; +} +REG8 f4a_control; +UINT8 f4bdata[256]; +static void IOOUTCALL csctrl_of4a(UINT port, REG8 dat) { + f4a_control = dat; + (void)port; +} + +static REG8 IOINPCALL csctrl_if4a(UINT port) { + TRACEOUT(("read %x",port)); + return f4a_control; + (void)port; +} + +static void IOOUTCALL csctrl_of4b(UINT port, REG8 dat) { + f4bdata[f4a_control] = dat; + (void)port; +} + +static REG8 IOINPCALL csctrl_if4b(UINT port) { + TRACEOUT(("read %x",port)); + (void)port; + return f4bdata[f4a_control]; +} + +static REG8 IOINPCALL csctrl_iac6d(UINT port) { + TRACEOUT(("read %x",port)); + (void)port; + return (0x54); +} + + +static REG8 IOINPCALL csctrl_iac6e(UINT port) { + + (void)port; + return 0; +} + +static REG8 IOINPCALL srnf_i51ee(UINT port) { + TRACEOUT(("read %x",port)); + (void)port; + return (0x02); +} + +static REG8 IOINPCALL srnf_i51ef(UINT port) { + TRACEOUT(("read %x",port)); + (void)port; + return 0xc2; +} + +static REG8 IOINPCALL srnf_i56ef(UINT port) { + TRACEOUT(("read %x",port)); + (void)port; + return (0x9f); +} +static REG8 IOINPCALL srnf_i57ef(UINT port) { + TRACEOUT(("read %x",port)); + (void)port; + return (0xc0); +} + +static REG8 IOINPCALL srnf_i59ef(UINT port) { + TRACEOUT(("read %x",port)); + (void)port; + return 0x3; +} + +static REG8 IOINPCALL srnf_i5bef(UINT port) { + TRACEOUT(("read %x",port)); + (void)port; + return (0x0e); +} + +static REG8 IOINPCALL ifab(UINT port) { + TRACEOUT(("read %x",port)); + (void)port; + return (0); +} + +// ---- + +void cs4231io_reset(void) { + + UINT8 sndirq, snddma; + + cs4231.enable = 1; + +/* [cs4231.adrsの書き方] + bit + 7 未使用 + R/W 6 不明 + R/W 5-3 PCM音源割り込みアドレス + 000b= サウンド機能を使用しない + 001b= INT 0 + 010b= INT 1 + 011b= INT 41 + 100b= INT 5 + R/W 2-0 DMAチャネル設定 + 000b= DMAを使用しない + 001b= DMA #0 + 010b= DMA #1 (PC-9821Npを除く) + 011b= DMA #3 + 100b〜101b= 未定義 + 111b= DMAを使用しない +*/ + if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ + sndirq = np2cfg.sndwssirq; + snddma = np2cfg.sndwssdma; + //cs4231.adrs = 0x0a;////0b00 001 010 INT0 DMA1 + //cs4231.adrs = 0x22;////0b00 100 010 INT5 DMA1 + }else if(g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ + UINT8 irq86table[4] = {0x03, 0x0d, 0x0a, 0x0c}; + UINT8 nIrq86 = (np2cfg.snd86opt & 0x10) | ((np2cfg.snd86opt & 0x4) << 5) | ((np2cfg.snd86opt & 0x8) << 3); + UINT8 irq86 = irq86table[nIrq86 >> 6]; + sndirq = np2cfg.snd118irqp; + snddma = np2cfg.snd118dma; + if(sndirq == irq86){ + if(irq86!=3){ + sndirq = 0x3; + }else{ + sndirq = 0xC; + } + } + }else if(g_nSoundID==SOUNDID_WAVESTAR){ + //UINT8 irq86table[4] = {0x03, 0x0d, 0x0a, 0x0c}; + //UINT8 nIrq86 = (np2cfg.snd86opt & 0x10) | ((np2cfg.snd86opt & 0x4) << 5) | ((np2cfg.snd86opt & 0x8) << 3); + //UINT8 irq86 = irq86table[nIrq86 >> 6]; + sndirq = 12;// IRQ12固定 irq86; + snddma = 3;// DMA#3固定 np2cfg.snd118dma; + }else{ + sndirq = np2cfg.snd118irqp; + snddma = np2cfg.snd118dma; + //cs4231.adrs = 0x23;////0b00 100 011 INT5 DMA3 + } + cs4231.adrs = 0; + switch(sndirq){ + case 3: + cs4231.adrs |= (0x1 << 3); + break; + case 5: + cs4231.adrs |= (0x2 << 3); + break; + case 10: + cs4231.adrs |= (0x3 << 3); + break; + case 12: + cs4231.adrs |= (0x4 << 3); + break; + default: + break; + } + switch(snddma){ + case 0: + cs4231.adrs |= (0x1); + break; + case 1: + cs4231.adrs |= (0x2); + break; + case 3: + cs4231.adrs |= (0x3); + break; + default: + break; + } + cs4231.dmairq = cs4231irq[(cs4231.adrs >> 3) & 7]; // IRQをセット + cs4231.dmach = cs4231dma[cs4231.adrs & 7]; // DMAチャネルをセット + cs4231.port[0] = 0x0f40; //WSS BASE I/O port + if(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_118_SB16){ + cs4231.port[1] = 0xb460; // Sound ID I/O port (A460hは86音源が使うのでB460hに変更) + }else{ + cs4231.port[1] = 0xa460; // Sound ID I/O port + } + cs4231.port[2] = 0x0f48; // WSS FIFO port + cs4231.port[4] = np2cfg.snd118io;//0x0188; // OPN port + cs4231.port[5] = 0x0f4a; // canbe mixer i/o port? + cs4231.port[6] = 0x548e; // YMF-701/715? + cs4231.port[8] = 0x1480; // Joystick + cs4231.port[9] = 0x1488; // OPL3 + cs4231.port[10] = 0x148c; // MIDI + cs4231.port[11] = 0x0480; //9801-118 control? + cs4231.port[14] = 0x148e; //9801-118 config + cs4231.port[15] = 0xa460; //空いてるのでこっちを利用 + + TRACEOUT(("CS4231 - IRQ = %d", cs4231.dmairq)); + TRACEOUT(("CS4231 - DMA channel = %d", cs4231.dmach)); + cs4231.reg.aux1_l = 0x88;//2 + cs4231.reg.aux1_r = 0x88;//3 + cs4231.reg.aux2_l = 0x88;//4 + cs4231.reg.aux2_r = 0x88;//5 + cs4231.reg.iface = 0x08;//9 + cs4231.reg.mode_id = 0xca;//c from PC-9821Nr166 + cs4231.reg.featurefunc[0]=0x80; //10 from PC-9821Nr166 + cs4231.reg.line_l = 0x88;//12 + cs4231.reg.line_r = 0x88;//13 + cs4231.reg.reserved1=0x80; //16 from PC-9821Nr166 + cs4231.reg.reserved2=0x80; //17 from PC-9821Nr166 + if(g_nSoundID==SOUNDID_PC_9801_118 || g_nSoundID==SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ + cs4231.reg.chipid =0xa2;//19 from PC-9801-118 CS4231 + }else{ + cs4231.reg.chipid =0x80;//19 from PC-9821Nr166 YMF715 + } + cs4231.reg.monoinput=0xc0;//1a from PC-9821Nr166 + cs4231.reg.reserved3=0x80; //1b from PC-9821Nr166 + cs4231.reg.reserved4=0x80; //1d from PC-9821Nr166 + cs4231.intflag = 0xcc; + + sa3data[7] = 7; + sa3data[8] = 7; + switch (cs4231.dmairq){ + case 0x0c:f4bdata[1] = 0;break; + case 0x0a:f4bdata[1] = 0x02;break; + case 0x03:f4bdata[1] = 0x03;break; + case 0x05:f4bdata[1] = 0x08;break; + } +} + +void cs4231io_bind(void) { + + sound_streamregist(&cs4231, (SOUNDCB)cs4231_getpcm); // CS4231用 オーディオ再生ストリーム + if(g_nSoundID!=SOUNDID_WAVESTAR){ + iocore_attachout(0xc24, csctrl_oc24); + iocore_attachout(0xc2b, csctrl_oc2b); + iocore_attachout(0xc2d, csctrl_oc2d); + iocore_attachinp(0xc24, csctrl_ic24); + iocore_attachinp(0xc2b, csctrl_ic2b); + iocore_attachinp(0xc2d, csctrl_ic2d); + } + if (cs4231.dmach != 0xff) { + dmac_attach(DMADEV_CS4231, cs4231.dmach); // CS4231のDMAチャネルを割り当て + } + if(!(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16)){ + iocore_attachout(0x480, csctrl_o480); + iocore_attachinp(0x480, csctrl_i480); + iocore_attachinp(0x481, csctrl_i481); + iocore_attachinp(0xac6d, csctrl_iac6d); + iocore_attachinp(0xac6e, csctrl_iac6e); + +/* 必要な時だけ有効にすべき +//WSN-F??? + iocore_attachinp(0x51ee, srnf_i51ee);//7番めに読まれる + iocore_attachinp(0x51ef, srnf_i51ef);//1番最初にC2を返す +// iocore_attachinp(0x52ef, srnf_i52ef);//f40等を読み書きしたあとここを読んでエラー + iocore_attachinp(0x56ef, srnf_i56ef);//2番めに読まれて割り込み等の設定? 4番めに2回読まれ直す + iocore_attachinp(0x57ef, srnf_i57ef);//5番めに読まれる + iocore_attachinp(0x59ef, srnf_i59ef);//3番めに読まれて何か調査 3と4でとりあえず通る +// iocore_attachinp(0x5aef, srnf_i5aef);//8番めに読まれて終わり + iocore_attachinp(0x5bef, srnf_i5bef);//6番めに読まれる +*/ + } +} +void cs4231io_unbind(void) { + + iocore_detachout(0xc24); + iocore_detachout(0xc2b); + iocore_detachout(0xc2d); + iocore_detachinp(0xc24); + iocore_detachinp(0xc2b); + iocore_detachinp(0xc2d); + if (cs4231.dmach != 0xff) { + dmac_detach(DMADEV_CS4231); // CS4231のDMAチャネルを割り当て + } + if(!(g_nSoundID==SOUNDID_PC_9801_86_WSS || g_nSoundID==SOUNDID_MATE_X_PCM || g_nSoundID==SOUNDID_WAVESTAR || g_nSoundID==SOUNDID_WSS_SB16 || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16)){ + iocore_detachout(0x480); + iocore_detachinp(0x480); + iocore_detachinp(0x481); + iocore_detachinp(0xac6d); + iocore_detachinp(0xac6e); + +/* 必要な時だけ有効にすべき +//WSN-F??? + iocore_detachinp(0x51ee);//7番めに読まれる + iocore_detachinp(0x51ef);//1番最初にC2を返す +// iocore_detachinp(0x52ef);//f40等を読み書きしたあとここを読んでエラー + iocore_detachinp(0x56ef);//2番めに読まれて割り込み等の設定? 4番めに2回読まれ直す + iocore_detachinp(0x57ef);//5番めに読まれる + iocore_detachinp(0x59ef);//3番めに読まれて何か調査 3と4でとりあえず通る +// iocore_detachinp(0x5aef);//8番めに読まれて終わり + iocore_detachinp(0x5bef);//6番めに読まれる +*/ + } +} + +int acicounter; +// CS4231 I/O WRITE +void IOOUTCALL cs4231io0_w8(UINT port, REG8 value) { + + switch(port - cs4231.port[0]) { + case 0x00: // PCM音源の割り込みアドレス設定 + cs4231.adrs = value &= ~0x40; + cs4231.dmairq = cs4231irq[(value >> 3) & 7]; + cs4231.dmach = cs4231dma[value & 7]; + dmac_detach(DMADEV_CS4231); + if (cs4231.dmach != 0xff) { + if ((cs4231.adrs >> 2) & 1){ + if (cs4231.dmach == 0)dmac_attach(DMADEV_NONE, 1); + else dmac_attach(DMADEV_NONE, 0); + } + dmac_attach(DMADEV_CS4231, cs4231.dmach); // CS4231のDMAチャネルを割り当て + // DMA読み取り位置を戻す + { + DMACH dmach = dmac.dmach + cs4231.dmach; + dmach->adrs.d = dmach->startaddr; + } +#if 0 + if (cs4231.reg.iface & SDC) { + dmac.dmach[cs4231.dmach].ready = 1; + dmac_check(); + } +#endif + } + break; + + case 0x04: // Index Address Register (R0) INIT MCE TRD IA4 IA3 IA2 IA1 IA0 + if ( !(cs4231.index & MCE) && (value & MCE) && (cs4231.reg.iface & (CAL0|CAL1) ) ) acicounter = 1; + if (!(cs4231.index & MCE)) cs4231.intflag |= (PRDY|CRDY); + cs4231.index = value & ~(INIT|TRD); + break; + case 0x05: // Indexed Data Register (R1) ID7 ID6 ID5 ID4 ID3 ID2 ID1 ID0 + cs4231_control(cs4231.index & 0x1f, value); // cs4231c.c内で処理 + break; + + case 0x06: // Status Register (R2, Read Only) CU/L CL/R CRDY SER PU/L PL/R PRDY INT + // PI,CI,TI割り込みビットを全部クリア + if (cs4231.intflag & INt) { + pic_resetirq(cs4231.dmairq); + //nevent_set(NEVENT_CS4231, 0, cs4231_dma, NEVENT_ABSOLUTE); + } + cs4231.intflag &= ~INt; + cs4231.reg.featurestatus &= ~(PI|TI|CI); + break; + + case 0x07: // Capture I/O Data Register (R3, Read Only) CD7 CD6 CD5 CD4 CD3 CD2 CD1 CD0 + cs4231_datasend(value); + break; + } +} +void IOOUTCALL cs4231io0_w8_wavestar(UINT port, REG8 value) { + cs4231io0_w8(((port - 0xA460) >> 1) + cs4231.port[0] + 1, value); +} +// CS4231 I/O READ +REG8 IOINPCALL cs4231io0_r8(UINT port) { + + switch(port - cs4231.port[0]) { + case 0x00: // PCM音源の割り込みアドレス設定 + return(cs4231.adrs); + case 0x03: // Windows Sound System ID (Read Only) + return(0x04); +// return(0x05);//PC-9821Nr + case 0x04: // Index Address Register (R0) INIT MCE TRD IA4 IA3 IA2 IA1 IA0 + return(cs4231.index & ~(INIT|TRD|MCE)); + case 0x05: // Indexed Data Register (R1) ID7 ID6 ID5 ID4 ID3 ID2 ID1 ID0 + { + switch (cs4231.index & 0x1f){ + case 0x0b: // Error Status and Initialization (I11, Read Only) COR PUR ACI DRS ORR1 ORR0 ORL1 ORL0 + if(acicounter){ + TRACEOUT(("acicounter")); + acicounter -= 1; + cs4231.reg.errorstatus |= ACI; + }else{ + cs4231.reg.errorstatus &= ~ACI; + } + break; + case 0x0d: // Loopback Control (I13) LBA5 LBA4 LBA3 LBA2 LBA1 LBA0 res LBE + return 0; + default: + break; + } + return(*(((UINT8 *)(&cs4231.reg)) + (cs4231.index & 0x1f))); + } + case 0x06: // Status Register (R2, Read Only) CU/L CL/R CRDY SER PU/L PL/R PRDY INT + if (cs4231.reg.errorstatus & (1 << 6)) cs4231.intflag |= SER; + return (cs4231.intflag); + case 0x07: // Capture I/O Data Register (R3, Read Only) CD7 CD6 CD5 CD4 CD3 CD2 CD1 CD0 + return (0x80); + } + return(0); +} +REG8 IOINPCALL cs4231io0_r8_wavestar(UINT port) { + return cs4231io0_r8(((port - 0xA460) >> 1) + cs4231.port[0] + 1); +} + +// canbe mixer i/o port? WRITE +void IOOUTCALL cs4231io5_w8(UINT port, REG8 value) { + + switch(port - cs4231.port[5]) { + case 0x00: + cs4231.extindex = value; + break; + + case 0x01: + switch(cs4231.extindex){ + case 0x02: // MODEM L ? + case 0x03: // MODEM R ? + case 0x30: // FM音源 L + case 0x31: // FM音源 R + case 0x32: // CD-DA L + case 0x33: // CD-DA R + case 0x34: // TV L + case 0x35: // TV R + case 0x36: // MODEM mono ? + // bit7:mute, bit6,5:reserved, bit4-0:volume(00000(MAX) - 11111(MIN)) + cs4231.devvolume[cs4231.extindex] = value; + } + break; + } +} +// canbe mixer i/o port? READ +REG8 IOINPCALL cs4231io5_r8(UINT port) { + + switch(port - cs4231.port[5]) { + case 0x00: + return(cs4231.extindex); + + case 0x01: + switch(cs4231.extindex){ + case 1: + return(0); // means opna int5 ??? + case 0x02: // MODEM L ? + case 0x03: // MODEM R ? + case 0x30: // FM音源 L + case 0x31: // FM音源 R + case 0x32: // CD-DA L + case 0x33: // CD-DA R + case 0x34: // TV L + case 0x35: // TV R + case 0x36: // MODEM mono ? + // bit7:mute, bit6,5:reserved, bit4-0:volume(00000(MAX) - 11111(MIN)) + return cs4231.devvolume[cs4231.extindex]; + } + break; + } + return(0xff); +} diff --git a/cbus/cs4231io.h b/cbus/cs4231io.h old mode 100755 new mode 100644 index c1289aff..a2f02e56 --- a/cbus/cs4231io.h +++ b/cbus/cs4231io.h @@ -1,62 +1,62 @@ - - -#ifdef __cplusplus -extern "C" { -#endif - -void cs4231io_reset(void); -void cs4231io_bind(void); -void cs4231io_unbind(void); - -void IOOUTCALL cs4231io0_w8(UINT port, REG8 value); -REG8 IOINPCALL cs4231io0_r8(UINT port); -void IOOUTCALL cs4231io0_w8_wavestar(UINT port, REG8 value); -REG8 IOINPCALL cs4231io0_r8_wavestar(UINT port); -void IOOUTCALL cs4231io2_w8(UINT port, REG8 value); -REG8 IOINPCALL cs4231io2_r8(UINT port); -void IOOUTCALL cs4231io5_w8(UINT port, REG8 value); -REG8 IOINPCALL cs4231io5_r8(UINT port); - -#ifdef __cplusplus -} -#endif - -//Index Address Register 0xf44 -#define TRD (1 << 5) //cs4231.index bit5 Transfer Request Disable -#define MCE (1 << 6) //cs4231.index bit6 Mode Change Enable -#define INIT (1 << 7)//cs4231.index bit7 Ititialization - -//Status Register 0xf46 -#define INt (1 << 0) //cs4231.intflag bit0 Interrupt Status -#define PRDY (1 << 1) //cs4231.intflag bit1 Playback Data Ready(PIO data) -#define PLR (1 << 2) //cs4231.intflag bit2 Playback Left/Right Sample -#define PULR (1 << 3) //cs4231.intflag bit3 Playback Upper/Lower Byte -#define SER (1 << 4) //cs4231.intflag bit4 Sample Error -#define CRDY (1 << 5) //cs4231.intflag bit5 Capture Data Ready(PIO) -#define CLR (1 << 6) //cs4231.intflag bit6 Capture Left/Right Sample -#define CUL (1 << 7) //cs4231.intglag bit7 Capture Upper/Lower Byte - -//cs4231.reg.iface(9) -#define PEN (1 << 0) //bit0 Playback Enable set and reset without MCE -#define CEN (1 << 1) //bit1 Capture Enable -#define SDC (1 << 2) //bit2 Single DMA Channel 0 Dual 1 Single 逆と思ってたので修正すべし -#define CAL0 (1 << 3) //bit3 Calibration 0 No Calibration 1 Converter calibration -#define CAL1 (1 << 4) //bit4 2 DAC calibration 3 Full Calibration -#define PPIO (1 << 6) //bit6 Playback PIO Enable 0 DMA 1 PIO -#define CPIO (1 << 7) //bit7 Capture PIO Enable 0 DMA 1 PIO - -//cs4231.reg.errorstatus(10) -#define ACI (1 << 5) //bit5 Auto-calibrate In-Progress - -//cs4231.reg.pinctrl(11) -#define IEN (1 << 1) //bit1 Interrupt Enable reflect cs4231.intflag bit0 -#define DEN (1 << 3) //bit3 Dither Enable only active in 8-bit unsigned mode - -//cs4231.reg.modeid(12) -#define MODE2 (1 << 6) //bit6 - -//cs4231.reg.featurestatus(24) -#define PI (1 << 4) //bit4 Playback Interrupt pending from Playback DMA count registers -#define CI (1 << 5) //bit5 Capture Interrupt pending from record DMA count registers when SDC=1 non-functional -#define TI (1 << 6) //bit6 Timer Interrupt pending from timer count registers -// PI,CI,TI bits are reset by writing a "0" to the particular interrupt bit or by writing any value to the Status register + + +#ifdef __cplusplus +extern "C" { +#endif + +void cs4231io_reset(void); +void cs4231io_bind(void); +void cs4231io_unbind(void); + +void IOOUTCALL cs4231io0_w8(UINT port, REG8 value); +REG8 IOINPCALL cs4231io0_r8(UINT port); +void IOOUTCALL cs4231io0_w8_wavestar(UINT port, REG8 value); +REG8 IOINPCALL cs4231io0_r8_wavestar(UINT port); +void IOOUTCALL cs4231io2_w8(UINT port, REG8 value); +REG8 IOINPCALL cs4231io2_r8(UINT port); +void IOOUTCALL cs4231io5_w8(UINT port, REG8 value); +REG8 IOINPCALL cs4231io5_r8(UINT port); + +#ifdef __cplusplus +} +#endif + +//Index Address Register 0xf44 +#define TRD (1 << 5) //cs4231.index bit5 Transfer Request Disable +#define MCE (1 << 6) //cs4231.index bit6 Mode Change Enable +#define INIT (1 << 7)//cs4231.index bit7 Ititialization + +//Status Register 0xf46 +#define INt (1 << 0) //cs4231.intflag bit0 Interrupt Status +#define PRDY (1 << 1) //cs4231.intflag bit1 Playback Data Ready(PIO data) +#define PLR (1 << 2) //cs4231.intflag bit2 Playback Left/Right Sample +#define PULR (1 << 3) //cs4231.intflag bit3 Playback Upper/Lower Byte +#define SER (1 << 4) //cs4231.intflag bit4 Sample Error +#define CRDY (1 << 5) //cs4231.intflag bit5 Capture Data Ready(PIO) +#define CLR (1 << 6) //cs4231.intflag bit6 Capture Left/Right Sample +#define CUL (1 << 7) //cs4231.intglag bit7 Capture Upper/Lower Byte + +//cs4231.reg.iface(9) +#define PEN (1 << 0) //bit0 Playback Enable set and reset without MCE +#define CEN (1 << 1) //bit1 Capture Enable +#define SDC (1 << 2) //bit2 Single DMA Channel 0 Dual 1 Single 逆と思ってたので修正すべし +#define CAL0 (1 << 3) //bit3 Calibration 0 No Calibration 1 Converter calibration +#define CAL1 (1 << 4) //bit4 2 DAC calibration 3 Full Calibration +#define PPIO (1 << 6) //bit6 Playback PIO Enable 0 DMA 1 PIO +#define CPIO (1 << 7) //bit7 Capture PIO Enable 0 DMA 1 PIO + +//cs4231.reg.errorstatus(10) +#define ACI (1 << 5) //bit5 Auto-calibrate In-Progress + +//cs4231.reg.pinctrl(11) +#define IEN (1 << 1) //bit1 Interrupt Enable reflect cs4231.intflag bit0 +#define DEN (1 << 3) //bit3 Dither Enable only active in 8-bit unsigned mode + +//cs4231.reg.modeid(12) +#define MODE2 (1 << 6) //bit6 + +//cs4231.reg.featurestatus(24) +#define PI (1 << 4) //bit4 Playback Interrupt pending from Playback DMA count registers +#define CI (1 << 5) //bit5 Capture Interrupt pending from record DMA count registers when SDC=1 non-functional +#define TI (1 << 6) //bit6 Timer Interrupt pending from timer count registers +// PI,CI,TI bits are reset by writing a "0" to the particular interrupt bit or by writing any value to the Status register diff --git a/cbus/ct1741io.c b/cbus/ct1741io.c old mode 100755 new mode 100644 index 848cafe0..028591aa --- a/cbus/ct1741io.c +++ b/cbus/ct1741io.c @@ -1,732 +1,732 @@ -/** - * @file ct1741io.c - * @brief Implementation of the Creative SoundBlaster16 CT1741 DSP I/O - */ - -#ifdef SUPPORT_SOUND_SB16 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#undef TRACEOUT -static void trace_fmt_ex(const char* fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#endif /* 1 */ - -#define CT1741_DSP_SAMPLES_DEFAULT 22050 - -// DSPコマンド -typedef enum { - DSP_CMD_NONE = 0, - DSP_CMD_GET_ASP_VERSION = 0x02, - DSP_CMD_SET_ASP_MODE_REG = 0x04, - DSP_CMD_SET_ASP_CODEC = 0x05, - DSP_CMD_WRITE_ASP_REG = 0x0e, - DSP_CMD_READ_ASP_REG = 0x0f, - - DSP_CMD_8BIT_PIO = 0x10, - DSP_CMD_8BIT_DMA_SINGLE = 0x14, - DSP_CMD_2BITADPCM_DMA_SINGLE = 0x16, - DSP_CMD_2BITADPCM_DMA_SINGLE_WITH_REF = 0x17, - DSP_CMD_8BIT_DMA_AUTOINIT = 0x1c, - DSP_CMD_2BITADPCM_DMA_AUTOINIT_WITH_REF = 0x1f, - - DSP_CMD_8BIT_PIO_IN = 0x20, - DSP_CMD_8BIT_DMA_SINGLE_IN = 0x24, - - DSP_CMD_POLLING_MIDI_IN = 0x30, - DSP_CMD_INTERRUPT_MIDI_IN = 0x31, - DSP_CMD_UART_POLLING_MIDI = 0x34, - DSP_CMD_UART_INTERRUPT_MIDI = 0x35, - DSP_CMD_UART_POLLING_MIDI_TIMESTAMP = 0x36, - DSP_CMD_UART_INTERRUPT_MIDI_TIMESTAMP = 0x37, - DSP_CMD_MIDI_OUT = 0x38, - - DSP_CMD_SET_DS_TRANSFER_TIMECONSTANT = 0x40, - DSP_CMD_SET_DS_OUT_SAMPLINGRATE = 0x41, - DSP_CMD_SET_DS_IN_SAMPLINGRATE = 0x42, - DSP_CMD_SET_DSP_BLOCK_SIZE = 0x48, - - DSP_CMD_4BITADPCM_DMA_SINGLE = 0x74, - DSP_CMD_4BITADPCM_DMA_SINGLE_WITH_REF = 0x75, - DSP_CMD_3BITADPCM_DMA_SINGLE = 0x76, - DSP_CMD_3BITADPCM_DMA_SINGLE_WITH_REF = 0x77, - DSP_CMD_4BITADPCM_DMA_AUTOINIT_WITH_REF = 0x7d, - DSP_CMD_3BITADPCM_DMA_AUTOINIT_WITH_REF = 0x7f, - - DSP_CMD_PAUSE_DAC_DURATION = 0x80, - - DSP_CMD_8BIT_HIGHSPEED_DMA_AUTOINIT = 0x90, - DSP_CMD_8BIT_HIGHSPEED_DMA_SINGLE = 0x91, - DSP_CMD_8BIT_HIGHSPEED_DMA_AUTOINIT_IN = 0x98, - DSP_CMD_8BIT_HIGHSPEED_DMA_SINGLE_IN = 0x99, - - DSP_CMD_SET_MONO = 0xa0, - DSP_CMD_SET_STEREO = 0xa8, - - DSP_CMD_PROGRAM_16BIT_DMA_BEGIN = 0xb0, - DSP_CMD_PROGRAM_16BIT_DMA_END = 0xbf, - - DSP_CMD_PROGRAM_8BIT_DMA_BEGIN = 0xc0, - DSP_CMD_PROGRAM_8BIT_DMA_END = 0xcf, - - DSP_CMD_PAUSE_8BIT_DMA = 0xd0, - DSP_CMD_SPEAKER_ON = 0xd1, - DSP_CMD_SPEAKER_OFF = 0xd3, - DSP_CMD_CONTINUE_8BIT_DMA = 0xd4, - DSP_CMD_PAUSE_16BIT_DMA = 0xd5, - DSP_CMD_CONTINUE_16BIT_DMA = 0xd6, - DSP_CMD_GET_SPEAKER_STATUS = 0xd8, - DSP_CMD_EXIT_16BIT_DMA_AUTOINIT = 0xd9, - DSP_CMD_EXIT_8BIT_DMA_AUTOINIT = 0xda, - - DSP_CMD_GET_DSP_ID = 0xe0, - DSP_CMD_GET_DSP_VERSION = 0xe1, - DSP_CMD_DSP_PROTECT = 0xe2, - DSP_CMD_GET_CR = 0xe3, - DSP_CMD_WRITE_TESTREG = 0xe4, - DSP_CMD_READ_TESTREG = 0xe8, - DSP_CMD_GEN_8BIT_IRQ = 0xf2, - DSP_CMD_GEN_16BIT_IRQ = 0xf3, -} DSP_CMD; - -// コマンド長さ(引数の数)テーブル -static UINT8 ct1741dsp_cmdlentbl[256] = { 0 }; - -// コマンド長さ(引数の数)の取得 -static UINT8 ct1741dsp_getcmdlen(UINT8 cmd) { - if (DSP_CMD_PROGRAM_16BIT_DMA_BEGIN <= cmd && cmd <= DSP_CMD_PROGRAM_16BIT_DMA_END) { - return 3; - } - if (DSP_CMD_PROGRAM_8BIT_DMA_BEGIN <= cmd && cmd <= DSP_CMD_PROGRAM_8BIT_DMA_END) { - return 3; - } - switch (cmd) { - case DSP_CMD_GET_ASP_VERSION: - case DSP_CMD_SET_ASP_MODE_REG: - case DSP_CMD_READ_ASP_REG: - case DSP_CMD_8BIT_PIO: - case DSP_CMD_MIDI_OUT: - case DSP_CMD_SET_DS_TRANSFER_TIMECONSTANT: - case DSP_CMD_GET_DSP_ID: - case DSP_CMD_DSP_PROTECT: - case DSP_CMD_WRITE_TESTREG: - return 1; - case DSP_CMD_SET_ASP_CODEC: - case DSP_CMD_WRITE_ASP_REG: - case DSP_CMD_8BIT_DMA_SINGLE: - case DSP_CMD_2BITADPCM_DMA_SINGLE: - case DSP_CMD_2BITADPCM_DMA_SINGLE_WITH_REF: - case DSP_CMD_8BIT_DMA_SINGLE_IN: - case DSP_CMD_SET_DS_OUT_SAMPLINGRATE: - case DSP_CMD_SET_DS_IN_SAMPLINGRATE: - case DSP_CMD_SET_DSP_BLOCK_SIZE: - case DSP_CMD_4BITADPCM_DMA_SINGLE: - case DSP_CMD_4BITADPCM_DMA_SINGLE_WITH_REF: - case DSP_CMD_3BITADPCM_DMA_SINGLE: - case DSP_CMD_3BITADPCM_DMA_SINGLE_WITH_REF: - case DSP_CMD_PAUSE_DAC_DURATION: - return 2; - default: - return 0; - } -} - -// コマンド長さ(引数の数)テーブル作成 -static void ct1741dsp_create_cmdlentbl() { - int i; - for (i = 0; i < NELEMENTS(ct1741dsp_cmdlentbl); i++) { - ct1741dsp_cmdlentbl[i] = ct1741dsp_getcmdlen(i); - } -} - -// CPU→DSPのバッファをクリア -static void ct1741dsp_dspout_clear() -{ - g_sb16.dsp_info.dspout.datalen = 0; -} - -// CPU→DSPへ引数の値をPush -static void ct1741dsp_dspout_push(UINT8 dat) -{ - if (g_sb16.dsp_info.dspout.datalen < CT1741_DSP_BUFSIZE) { - g_sb16.dsp_info.dspout.data[(g_sb16.dsp_info.dspout.rpos + g_sb16.dsp_info.dspout.datalen) % CT1741_DSP_BUFSIZE] = dat; - g_sb16.dsp_info.dspout.datalen++; - } -} - -// DSP→CPUへ返す値をPush -static void ct1741dsp_dspin_push(UINT8 dat) -{ - if (g_sb16.dsp_info.dspin.datalen < CT1741_DSP_BUFSIZE) { - g_sb16.dsp_info.dspin.data[g_sb16.dsp_info.dspin.datalen] = dat; - g_sb16.dsp_info.dspin.datalen++; - } -} - -// DMA転送開始する -static void ct1741dsp_setdma(CT1741_DMAMODE mode, BOOL autoinit, BOOL stereo, BOOL input) -{ - g_sb16.dsp_info.dma.dmach = dmac.dmach + g_sb16.dmachnum; // DMA割り当て - if (g_sb16.dsp_info.mode != CT1741_DSPMODE_NONE) - { - // DMA開始後に設定を変えてくる場合があるので、その時は一旦止めて設定し直し - g_sb16.dsp_info.dma.dmach->ready = 0; - dmac_check(); - } - g_sb16.dsp_info.mode = input ? CT1741_DSPMODE_DMA_IN : CT1741_DSPMODE_DMA; - g_sb16.dsp_info.dma.lastautoinit = g_sb16.dsp_info.dma.autoinit = !!autoinit; - g_sb16.dsp_info.dma.stereo = !!stereo; - g_sb16.dsp_info.dma.mode = mode; - - // DMA開始 - g_sb16.dsp_info.dma.dmach->ready = 1; - dmac_check(); -} - -// DMA転送を再設定する -static void ct1741dsp_updatedma() -{ - ct1741dsp_setdma(g_sb16.dsp_info.dma.mode, g_sb16.dsp_info.dma.autoinit, g_sb16.dsp_info.dma.stereo, g_sb16.dsp_info.mode == CT1741_DSPMODE_DMA_IN); -} - -// DSPコマンドを実行 -static void ct1741dsp_exec_command() -{ - UINT8 cmd = g_sb16.dsp_info.cmd; - TRACEOUT(("CT1741 DSP CMD=0x%02x", cmd)); - if (DSP_CMD_PROGRAM_16BIT_DMA_BEGIN <= cmd && cmd <= DSP_CMD_PROGRAM_16BIT_DMA_END) { - // Prigram 16bit DMA - ct1741_playinfo.bufdatasrem = 0; - g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[2] << 8) | g_sb16.dsp_info.dspin.data[1]) + 1; - ct1741dsp_setdma(CT1741_DMAMODE_16, g_sb16.dsp_info.cmd & 0x4, g_sb16.dsp_info.dspin.data[0] & 0x20, g_sb16.dsp_info.cmd & 0x8); - g_sb16.mixreg[0x82] |= (g_sb16.dsp_info.dmachnum & 0xe0) ? 0x2 : 0x1; // High-DMAが有効な場合はHigh-DMAを使用 - if (g_sb16.dsp_info.cmd & 0x8) { - // 入力の場合、即座に割り込むことにする - ct1741_setpicirq(); - } - } - else if (DSP_CMD_PROGRAM_8BIT_DMA_BEGIN <= cmd && cmd <= DSP_CMD_PROGRAM_8BIT_DMA_END) { - // Prigram 8bit DMA - ct1741_playinfo.bufdatasrem = 0; - g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[2] << 8) | g_sb16.dsp_info.dspin.data[1]) + 1; - ct1741dsp_setdma(CT1741_DMAMODE_8, g_sb16.dsp_info.cmd & 0x4, g_sb16.dsp_info.dspin.data[0] & 0x20, g_sb16.dsp_info.cmd & 0x8); - g_sb16.mixreg[0x82] |= 0x1; - if (g_sb16.dsp_info.cmd & 0x8) { - // 入力の場合、即座に割り込むことにする - ct1741_setpicirq(); - } - } - else { - switch (g_sb16.dsp_info.cmd) { - case DSP_CMD_GET_ASP_VERSION: - break; - case DSP_CMD_SET_ASP_MODE_REG: - ct1741dsp_dspout_clear(); - ct1741dsp_dspout_push(0xff); - break; - case DSP_CMD_SET_ASP_CODEC: - break; - case DSP_CMD_WRITE_ASP_REG: - break; - case DSP_CMD_READ_ASP_REG: - ct1741dsp_dspout_clear(); - ct1741dsp_dspout_push(0); - break; - - case DSP_CMD_8BIT_PIO: - g_sb16.dsp_info.mode = CT1741_DSPMODE_DAC; - ct1741_playinfo.playwaitcounter = 0; - // PIO再生のつもりだがノーチェック -#if defined(SUPPORT_MULTITHREAD) - ct1741cs_enter_criticalsection(); -#endif - if (ct1741_playinfo.pio.bufdatas < CT1741_PIO_BUFSIZE) { - ct1741_playinfo.pio.buffer[ct1741_playinfo.pio.bufwpos] = g_sb16.dsp_info.dspin.data[0]; - ct1741_playinfo.pio.bufwpos++; - if (ct1741_playinfo.pio.bufwpos >= CT1741_PIO_BUFSIZE) ct1741_playinfo.pio.bufwpos -= CT1741_PIO_BUFSIZE; - ct1741_playinfo.pio.bufdatas++; - } -#if defined(SUPPORT_MULTITHREAD) - ct1741cs_leave_criticalsection(); -#endif - if (ct1741_playinfo.pio.bufdatas > CT1741_PIO_BUFSIZE / 2) { - if (ct1741_playinfo.pio.bufdatas > CT1741_PIO_BUFSIZE) - { - g_sb16.dsp_info.wbusy = 1; - } - else - { - g_sb16.dsp_info.wbusy = 0; - } - } - else - { - g_sb16.dsp_info.wbusy = 0; - } - break; - case DSP_CMD_8BIT_DMA_SINGLE: - g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; - ct1741_playinfo.bufdatasrem = 0; - ct1741dsp_setdma(CT1741_DMAMODE_8, FALSE, FALSE, FALSE); - break; - case DSP_CMD_2BITADPCM_DMA_SINGLE: - case DSP_CMD_2BITADPCM_DMA_SINGLE_WITH_REF: - ct1741_playinfo.bufdatasrem = 0; - g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; - ct1741dsp_setdma(CT1741_DMAMODE_2, FALSE, FALSE, FALSE); - break; - case DSP_CMD_8BIT_DMA_AUTOINIT: - ct1741_playinfo.bufdatasrem = 0; - ct1741dsp_setdma(CT1741_DMAMODE_8, TRUE, FALSE, FALSE); - break; - case DSP_CMD_2BITADPCM_DMA_AUTOINIT_WITH_REF: - ct1741_playinfo.bufdatasrem = 0; - g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; - ct1741dsp_setdma(CT1741_DMAMODE_2, TRUE, FALSE, FALSE); - break; - - case DSP_CMD_8BIT_PIO_IN: - // not implemented yet - break; - case DSP_CMD_8BIT_DMA_SINGLE_IN: - ct1741_playinfo.bufdatasrem = 0; - g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; - ct1741dsp_setdma(CT1741_DMAMODE_8, FALSE, FALSE, TRUE); - break; - case DSP_CMD_POLLING_MIDI_IN: - case DSP_CMD_INTERRUPT_MIDI_IN: - case DSP_CMD_UART_POLLING_MIDI: - case DSP_CMD_UART_INTERRUPT_MIDI: - case DSP_CMD_UART_POLLING_MIDI_TIMESTAMP: - case DSP_CMD_UART_INTERRUPT_MIDI_TIMESTAMP: - // not implemented yet - break; - case DSP_CMD_MIDI_OUT: - if (!g_sb16.dsp_info.uartmode) { - if (mpu98.enable) { - mpu98.mode = 1; // force set UART mode - mpu98ii_o0(0x8000 + g_sb16.base, g_sb16.dsp_info.dspin.data[0]); - } - else if (smpu98.enable) { - smpu98.mode = 1; // force set UART mode - smpu98_o0(0x8000 + g_sb16.base, g_sb16.dsp_info.dspin.data[0]); - } - } - break; - - case DSP_CMD_SET_DS_TRANSFER_TIMECONSTANT: - g_sb16.dsp_info.freq = (1000000 / (256 - g_sb16.dsp_info.dspin.data[0])); - if (g_sb16.dsp_info.dma.mode != CT1741_DMAMODE_NONE && g_sb16.dsp_info.dma.autoinit) { - ct1741dsp_updatedma(); - } - break; - case DSP_CMD_SET_DS_OUT_SAMPLINGRATE: - case DSP_CMD_SET_DS_IN_SAMPLINGRATE: - g_sb16.dsp_info.freq = (g_sb16.dsp_info.dspin.data[0] << 8) | g_sb16.dsp_info.dspin.data[1]; - break; - case DSP_CMD_SET_DSP_BLOCK_SIZE: - g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; - break; - - case DSP_CMD_4BITADPCM_DMA_SINGLE: - case DSP_CMD_4BITADPCM_DMA_SINGLE_WITH_REF: - ct1741_playinfo.bufdatasrem = 0; - g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; - ct1741dsp_setdma(CT1741_DMAMODE_4, FALSE, FALSE, FALSE); - break; - case DSP_CMD_3BITADPCM_DMA_SINGLE: - case DSP_CMD_3BITADPCM_DMA_SINGLE_WITH_REF: - ct1741_playinfo.bufdatasrem = 0; - g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; - ct1741dsp_setdma(CT1741_DMAMODE_3, FALSE, FALSE, FALSE); - break; - case DSP_CMD_4BITADPCM_DMA_AUTOINIT_WITH_REF: - ct1741_playinfo.bufdatasrem = 0; - g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; - ct1741dsp_setdma(CT1741_DMAMODE_4, TRUE, FALSE, FALSE); - break; - case DSP_CMD_3BITADPCM_DMA_AUTOINIT_WITH_REF: - ct1741_playinfo.bufdatasrem = 0; - g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; - ct1741dsp_setdma(CT1741_DMAMODE_3, TRUE, FALSE, FALSE); - break; - - case DSP_CMD_PAUSE_DAC_DURATION: - // not implemented yet - break; - - case DSP_CMD_8BIT_HIGHSPEED_DMA_AUTOINIT: - ct1741_playinfo.bufdatasrem = 0; - ct1741dsp_setdma(CT1741_DMAMODE_8, TRUE, FALSE, FALSE); - break; - case DSP_CMD_8BIT_HIGHSPEED_DMA_SINGLE: - ct1741_playinfo.bufdatasrem = 0; - ct1741dsp_setdma(CT1741_DMAMODE_8, FALSE, FALSE, FALSE); - break; - case DSP_CMD_8BIT_HIGHSPEED_DMA_AUTOINIT_IN: - ct1741_playinfo.bufdatasrem = 0; - ct1741dsp_setdma(CT1741_DMAMODE_8, TRUE, FALSE, TRUE); - break; - case DSP_CMD_8BIT_HIGHSPEED_DMA_SINGLE_IN: - ct1741_playinfo.bufdatasrem = 0; - ct1741dsp_setdma(CT1741_DMAMODE_8, FALSE, FALSE, TRUE); - break; - - case DSP_CMD_SET_MONO: - case DSP_CMD_SET_STEREO: - // not supported in DSP V4 - break; - - case DSP_CMD_PAUSE_8BIT_DMA: - case DSP_CMD_PAUSE_16BIT_DMA: - ct1741_playinfo.bufdatasrem = g_sb16.dsp_info.dma.bufdatas; // 停止した瞬間までに送られていた分は再生する - g_sb16.dsp_info.mode = CT1741_DSPMODE_DMA_PAUSE; - g_sb16.dsp_info.dma.mode = CT1741_DMAMODE_NONE; - break; - case DSP_CMD_SPEAKER_ON: - g_sb16.dsp_info.speaker = 0xff; - break; - case DSP_CMD_SPEAKER_OFF: - ct1741_playinfo.bufdatasrem = 0; // バッファ破棄 - g_sb16.dsp_info.speaker = 0x00; - break; - case DSP_CMD_CONTINUE_8BIT_DMA: - case DSP_CMD_CONTINUE_16BIT_DMA: - if (g_sb16.dsp_info.mode == CT1741_DSPMODE_DMA_PAUSE) { - g_sb16.dsp_info.mode = CT1741_DSPMODE_DMA; - ct1741_playinfo.bufdatasrem = 0; - } - break; - case DSP_CMD_GET_SPEAKER_STATUS: - ct1741dsp_dspout_clear(); - ct1741dsp_dspout_push(g_sb16.dsp_info.speaker); - break; - case DSP_CMD_EXIT_16BIT_DMA_AUTOINIT: - case DSP_CMD_EXIT_8BIT_DMA_AUTOINIT: - { - // 停止した瞬間までに送られていた分は再生する -#if defined(SUPPORT_MULTITHREAD) - ct1741cs_enter_criticalsection(); -#endif - if (g_sb16.dsp_info.dma.bufdatas > g_sb16.dsp_info.dma.total || g_sb16.dsp_info.dma.total == 65536) { - // WORKAROUND: バッファを捨てて停止する。この処理をするとWin3.1で後ろが切れる。しないとWin9x DirectSoundで末尾にノイズ(ダブり)が入る - g_sb16.dsp_info.dma.bufdatas = 0; - g_sb16.dsp_info.dma.dmach->ready = 0; - } - g_sb16.dsp_info.dma.autoinit = FALSE; // 本来は次の割り込みタイミングで停止らしい -#if defined(SUPPORT_MULTITHREAD) - ct1741cs_leave_criticalsection(); -#endif - break; - } - - case DSP_CMD_GET_DSP_ID: - ct1741dsp_dspout_clear(); - ct1741dsp_dspout_push(~g_sb16.dsp_info.dspin.data[0]); - break; - case DSP_CMD_GET_DSP_VERSION: - ct1741dsp_dspout_clear(); - ct1741dsp_dspout_push(0x4); - ct1741dsp_dspout_push(0xc); - break; - case DSP_CMD_DSP_PROTECT: - // not implemented yet - break; - case DSP_CMD_GET_CR: - { - UINT32 i; - char crstr[] = "NOT COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; - ct1741dsp_dspout_clear(); - for (i = 4; i < sizeof(crstr); i++) { - ct1741dsp_dspout_push(crstr[i]); - } - } - break; - case DSP_CMD_WRITE_TESTREG: - g_sb16.dsp_info.testreg = g_sb16.dsp_info.dspin.data[0]; - break; - case DSP_CMD_READ_TESTREG: - ct1741dsp_dspout_clear(); - ct1741dsp_dspout_push(g_sb16.dsp_info.testreg);; - break; - case DSP_CMD_GEN_8BIT_IRQ: - ct1741dsp_dspout_clear(); - ct1741dsp_dspout_push(0xaa); - ct1741_setpicirq(); - g_sb16.mixreg[0x82] |= 1; - break; - case DSP_CMD_GEN_16BIT_IRQ: - ct1741dsp_dspout_clear(); - ct1741dsp_dspout_push(0xaa); - ct1741_setpicirq(); - g_sb16.mixreg[0x82] |= 2; - break; - default: - break; - } - } - g_sb16.dsp_info.dspin.datalen = 0; - g_sb16.dsp_info.cmd = DSP_CMD_NONE; - g_sb16.dsp_info.cmdlen = 0; -} - -// DSPをリセット -static void ct1741dsp_reset(BOOL ioreset) -{ - g_sb16.dsp_info.mode = CT1741_DSPMODE_NONE; - g_sb16.dsp_info.freq = CT1741_DSP_SAMPLES_DEFAULT; - g_sb16.dsp_info.cmdlen = 0; - g_sb16.dsp_info.dspin.datalen = 0; - g_sb16.dsp_info.wbusy = 0; - g_sb16.dsp_info.uartmode = 0; - g_sb16.dsp_info.dma.autoinit = FALSE; - g_sb16.dsp_info.dma.lastautoinit = FALSE; - if (ioreset) { - if (g_sb16.dsp_info.dma.dmach) { - g_sb16.dsp_info.dma.dmach->ready = 0; - dmac_check(); - if (g_sb16.dmachnum != 0xff) { - dmac.stat |= (1 << g_sb16.dmachnum); - } - g_sb16.mixreg[0x82] &= ~3; - ct1741_resetpicirq(); - } - } -} - -// ***** DSP I/O Ports ***** - -/* DSP reset */ -static void IOOUTCALL ct1741dsp_write_reset(UINT port, REG8 dat) -{ - TRACEOUT(("CT1741 DSP Write Reset")); - if ((dat & 0x01)) { - /* status reset */ - ct1741dsp_reset(TRUE); - g_sb16.dsp_info.resetout = CT1741_DSPRST_RESET; - } - else { - /* status normal */ - ct1741dsp_dspout_clear(); - ct1741dsp_dspout_push(0xaa); - g_sb16.dsp_info.resetout = CT1741_DSPRST_NORMAL; - } - - if (dat == 0xc6) { - ct1741dsp_dspout_clear(); - ct1741dsp_reset(TRUE); - g_sb16.dsp_info.resetout = CT1741_DSPRST_SPECIAL; - } -} - -/* DSP write Command/Data */ -static void IOOUTCALL ct1741dsp_write_data(UINT port, REG8 dat) -{ - TRACEOUT(("CT1741 DSP command: %.2x", dat)); - if (g_sb16.dsp_info.cmd == DSP_CMD_NONE) { - // コマンド書き込み - g_sb16.dsp_info.dspin.datalen = 0; - g_sb16.dsp_info.cmd = g_sb16.dsp_info.cmd_o = dat; - g_sb16.dsp_info.cmdlen = ct1741dsp_cmdlentbl[dat]; - } - else { - // パラメータ書き込み - ct1741dsp_dspin_push(dat); - } - if (g_sb16.dsp_info.dspin.datalen >= g_sb16.dsp_info.cmdlen) { - // パラメータが規定数に達したら実行 - ct1741dsp_exec_command(); - } -} - -/* DSP reset read */ -static REG8 IOINPCALL ct1741dsp_read_reset(UINT port) -{ - if ((port & 0x0d00) == 0x0d00) - return 0x00; // アドレスが xDxxhの時は0x00を返す - else - return 0xff; // アドレスが上記以外の時は0xffを返す -} - -/* DSP read data */ -static REG8 IOINPCALL ct1741dsp_read_data(UINT port) -{ - static REG8 data = 0; - if (g_sb16.dsp_info.dspout.datalen) { - if (g_sb16.dsp_info.dspout.rpos < sizeof(g_sb16.dsp_info.dspout.data) / sizeof(g_sb16.dsp_info.dspout.data[0])) { - data = g_sb16.dsp_info.dspout.data[g_sb16.dsp_info.dspout.rpos]; - g_sb16.dsp_info.dspout.rpos++; - if (g_sb16.dsp_info.dspout.rpos >= CT1741_DSP_BUFSIZE) - g_sb16.dsp_info.dspout.rpos -= CT1741_DSP_BUFSIZE; - g_sb16.dsp_info.dspout.datalen--; - } - } - return data; -} - -/* DSP read write status */ -static REG8 IOINPCALL ct1741dsp_read_wstatus(UINT port) -{ - switch (g_sb16.dsp_info.resetout) { - case CT1741_DSPRST_NORMAL: - return g_sb16.dsp_info.wbusy ? 0x80 : 0x00; - - case CT1741_DSPRST_RESET: - return 0xff; - - case CT1741_DSPRST_SPECIAL: - return 0; - - default: // ????変な数値とるときがある 意味不明 - return 0; - } - return 0xff; -} - -/* DSP read read status (8 bit) */ -static REG8 IOINPCALL ct1741dsp_read_rstatus(UINT port) -{ - TRACEOUT(("CT1741 DSP read read status")); - // 詳細不明 - if (g_sb16.dsp_info.cmd_o == 0xf2) { - g_sb16.dsp_info.cmd_o = 0; - return 0; - } - // 割り込みを解除。bit0は8-bit用 - if (g_sb16.mixreg[0x82] & 1) { - g_sb16.mixreg[0x82] &= ~1; - ct1741_resetpicirq(); - } - - if (g_sb16.dsp_info.dspout.datalen) - return 0x80; - else - return 0x00; -} - -/* DSP read read status (16 bit) */ -static REG8 IOINPCALL ct1741dsp_read_rstatus16(UINT port) -{ - TRACEOUT(("CT1741 DSP read read status16")); - // 割り込みを解除。bit1は16-bit用 - if (g_sb16.mixreg[0x82] & 2) { - g_sb16.mixreg[0x82] &= ~2; - ct1741_resetpicirq(); - } - - return 0xff; -} - -void ct1741io_reset(void) -{ - ct1741dsp_create_cmdlentbl(); - ct1741dsp_reset(FALSE); - g_sb16.dsp_info.dmairq = ct1741_get_dma_irq(); - g_sb16.dsp_info.dmachnum = ct1741_get_dma_ch() & 0xf; // High DMAはDefaultで無効 - g_sb16.dsp_info.resetout = CT1741_DSPRST_NORMAL; - if (g_sb16.dmachnum == 0 || g_sb16.dmachnum == 3) { - g_sb16.dsp_info.dma.dmach = dmac.dmach + g_sb16.dmachnum; // DMA割り当て - dmac_attach(DMADEV_CT1741, g_sb16.dmachnum); - } - g_sb16.dsp_info.dma.bufsize = CT1741_DMA_BUFSIZE; - g_sb16.dsp_info.dma.rate2 = ct1741_playinfo.playrate; - g_sb16.dsp_info.dma.bufdatas = 0; - ct1741_playinfo.playwaitcounter = 0; - ct1741_playinfo.bufdatasrem = 0; -} - -void ct1741io_bind(void) -{ - sound_streamregist(&g_sb16.dsp_info.dma, (SOUNDCB)ct1741_getpcm); // CT1741用 オーディオ再生ストリーム - - iocore_attachout(0x2600 + g_sb16.base, ct1741dsp_write_reset); /* DSP Reset */ - iocore_attachout(0x2C00 + g_sb16.base, ct1741dsp_write_data); /* DSP Write Command/Data */ - - iocore_attachinp(0x2600 + g_sb16.base, ct1741dsp_read_reset); /* DSP Reset */ - iocore_attachinp(0x2a00 + g_sb16.base, ct1741dsp_read_data); /* DSP Read Data Port */ - iocore_attachinp(0x2c00 + g_sb16.base, ct1741dsp_read_wstatus); /* DSP Write Buffer Status (Bit 7) */ - iocore_attachinp(0x2d00 + g_sb16.base, ct1741dsp_read_reset); /* DSP Reset */ - iocore_attachinp(0x2e00 + g_sb16.base, ct1741dsp_read_rstatus); /* DSP Read Buffer Status (Bit 7) */ - iocore_attachinp(0x2f00 + g_sb16.base, ct1741dsp_read_rstatus16); /* DSP Read Buffer Status (Bit 7) */ - - // Canopus PowerWindow T64S/98 音源部テスト - iocore_attachout(0x6600 + g_sb16.base, ct1741dsp_write_reset); /* DSP Reset */ - iocore_attachout(0x6C00 + g_sb16.base, ct1741dsp_write_data); /* DSP Write Command/Data */ - - iocore_attachinp(0x6600 + g_sb16.base, ct1741dsp_read_reset); /* DSP Reset */ - iocore_attachinp(0x6a00 + g_sb16.base, ct1741dsp_read_data); /* DSP Read Data Port */ - iocore_attachinp(0x6c00 + g_sb16.base, ct1741dsp_read_wstatus); /* DSP Write Buffer Status (Bit 7) */ - iocore_attachinp(0x6d00 + g_sb16.base, ct1741dsp_read_reset); /* DSP Reset */ - iocore_attachinp(0x6e00 + g_sb16.base, ct1741dsp_read_rstatus); /* DSP Read Buffer Status (Bit 7) */ - iocore_attachinp(0x6f00 + g_sb16.base, ct1741dsp_read_rstatus16); /* DSP Read Buffer Status (Bit 7) */ - - // PC/AT互換機テスト - if(np2cfg.sndsb16at){ - iocore_attachout(0x226, ct1741dsp_write_reset); /* DSP Reset */ - iocore_attachout(0x22C, ct1741dsp_write_data); /* DSP Write Command/Data */ - - iocore_attachinp(0x226, ct1741dsp_read_reset); /* DSP Reset */ - iocore_attachinp(0x22a, ct1741dsp_read_data); /* DSP Read Data Port */ - iocore_attachinp(0x22c, ct1741dsp_read_wstatus); /* DSP Write Buffer Status (Bit 7) */ - iocore_attachinp(0x22d, ct1741dsp_read_reset); /* DSP Reset */ - iocore_attachinp(0x22e, ct1741dsp_read_rstatus); /* DSP Read Buffer Status (Bit 7) */ - iocore_attachinp(0x22f, ct1741dsp_read_rstatus16); /* DSP Read Buffer Status (Bit 7) */ - } -} -void ct1741io_unbind(void) -{ - iocore_detachout(0x2600 + g_sb16.base); /* DSP Reset */ - iocore_detachout(0x2C00 + g_sb16.base); /* DSP Write Command/Data */ - - iocore_detachinp(0x2600 + g_sb16.base); /* DSP Reset */ - iocore_detachinp(0x2a00 + g_sb16.base); /* DSP Read Data Port */ - iocore_detachinp(0x2c00 + g_sb16.base); /* DSP Write Buffer Status (Bit 7) */ - iocore_detachinp(0x2e00 + g_sb16.base); /* DSP Read Buffer Status (Bit 7) */ - iocore_detachinp(0x2f00 + g_sb16.base); /* DSP Read Buffer Status (Bit 7) */ - - // Canopus PowerWindow T64S/98 音源部テスト - iocore_detachinp(0x6600 + g_sb16.base); /* DSP Reset */ - iocore_detachinp(0x6C00 + g_sb16.base); /* DSP Write Command/Data */ - - iocore_detachinp(0x6600 + g_sb16.base); /* DSP Reset */ - iocore_detachinp(0x6a00 + g_sb16.base); /* DSP Read Data Port */ - iocore_detachinp(0x6c00 + g_sb16.base); /* DSP Write Buffer Status (Bit 7) */ - iocore_detachinp(0x6d00 + g_sb16.base); /* DSP Reset */ - iocore_detachinp(0x6e00 + g_sb16.base); /* DSP Read Buffer Status (Bit 7) */ - iocore_detachinp(0x6f00 + g_sb16.base); /* DSP Read Buffer Status (Bit 7) */ - - // PC/AT互換機テスト - if(np2cfg.sndsb16at){ - iocore_detachout(0x226); /* DSP Reset */ - iocore_detachout(0x22C); /* DSP Write Command/Data */ - - iocore_detachinp(0x226); /* DSP Reset */ - iocore_detachinp(0x22a); /* DSP Read Data Port */ - iocore_detachinp(0x22c); /* DSP Write Buffer Status (Bit 7) */ - iocore_detachinp(0x22d); /* DSP Reset */ - iocore_detachinp(0x22e); /* DSP Read Buffer Status (Bit 7) */ - iocore_detachinp(0x22f); /* DSP Read Buffer Status (Bit 7) */ - } -} - +/** + * @file ct1741io.c + * @brief Implementation of the Creative SoundBlaster16 CT1741 DSP I/O + */ + +#ifdef SUPPORT_SOUND_SB16 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#undef TRACEOUT +static void trace_fmt_ex(const char* fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "¥n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#endif /* 1 */ + +#define CT1741_DSP_SAMPLES_DEFAULT 22050 + +// DSPコマンド +typedef enum { + DSP_CMD_NONE = 0, + DSP_CMD_GET_ASP_VERSION = 0x02, + DSP_CMD_SET_ASP_MODE_REG = 0x04, + DSP_CMD_SET_ASP_CODEC = 0x05, + DSP_CMD_WRITE_ASP_REG = 0x0e, + DSP_CMD_READ_ASP_REG = 0x0f, + + DSP_CMD_8BIT_PIO = 0x10, + DSP_CMD_8BIT_DMA_SINGLE = 0x14, + DSP_CMD_2BITADPCM_DMA_SINGLE = 0x16, + DSP_CMD_2BITADPCM_DMA_SINGLE_WITH_REF = 0x17, + DSP_CMD_8BIT_DMA_AUTOINIT = 0x1c, + DSP_CMD_2BITADPCM_DMA_AUTOINIT_WITH_REF = 0x1f, + + DSP_CMD_8BIT_PIO_IN = 0x20, + DSP_CMD_8BIT_DMA_SINGLE_IN = 0x24, + + DSP_CMD_POLLING_MIDI_IN = 0x30, + DSP_CMD_INTERRUPT_MIDI_IN = 0x31, + DSP_CMD_UART_POLLING_MIDI = 0x34, + DSP_CMD_UART_INTERRUPT_MIDI = 0x35, + DSP_CMD_UART_POLLING_MIDI_TIMESTAMP = 0x36, + DSP_CMD_UART_INTERRUPT_MIDI_TIMESTAMP = 0x37, + DSP_CMD_MIDI_OUT = 0x38, + + DSP_CMD_SET_DS_TRANSFER_TIMECONSTANT = 0x40, + DSP_CMD_SET_DS_OUT_SAMPLINGRATE = 0x41, + DSP_CMD_SET_DS_IN_SAMPLINGRATE = 0x42, + DSP_CMD_SET_DSP_BLOCK_SIZE = 0x48, + + DSP_CMD_4BITADPCM_DMA_SINGLE = 0x74, + DSP_CMD_4BITADPCM_DMA_SINGLE_WITH_REF = 0x75, + DSP_CMD_3BITADPCM_DMA_SINGLE = 0x76, + DSP_CMD_3BITADPCM_DMA_SINGLE_WITH_REF = 0x77, + DSP_CMD_4BITADPCM_DMA_AUTOINIT_WITH_REF = 0x7d, + DSP_CMD_3BITADPCM_DMA_AUTOINIT_WITH_REF = 0x7f, + + DSP_CMD_PAUSE_DAC_DURATION = 0x80, + + DSP_CMD_8BIT_HIGHSPEED_DMA_AUTOINIT = 0x90, + DSP_CMD_8BIT_HIGHSPEED_DMA_SINGLE = 0x91, + DSP_CMD_8BIT_HIGHSPEED_DMA_AUTOINIT_IN = 0x98, + DSP_CMD_8BIT_HIGHSPEED_DMA_SINGLE_IN = 0x99, + + DSP_CMD_SET_MONO = 0xa0, + DSP_CMD_SET_STEREO = 0xa8, + + DSP_CMD_PROGRAM_16BIT_DMA_BEGIN = 0xb0, + DSP_CMD_PROGRAM_16BIT_DMA_END = 0xbf, + + DSP_CMD_PROGRAM_8BIT_DMA_BEGIN = 0xc0, + DSP_CMD_PROGRAM_8BIT_DMA_END = 0xcf, + + DSP_CMD_PAUSE_8BIT_DMA = 0xd0, + DSP_CMD_SPEAKER_ON = 0xd1, + DSP_CMD_SPEAKER_OFF = 0xd3, + DSP_CMD_CONTINUE_8BIT_DMA = 0xd4, + DSP_CMD_PAUSE_16BIT_DMA = 0xd5, + DSP_CMD_CONTINUE_16BIT_DMA = 0xd6, + DSP_CMD_GET_SPEAKER_STATUS = 0xd8, + DSP_CMD_EXIT_16BIT_DMA_AUTOINIT = 0xd9, + DSP_CMD_EXIT_8BIT_DMA_AUTOINIT = 0xda, + + DSP_CMD_GET_DSP_ID = 0xe0, + DSP_CMD_GET_DSP_VERSION = 0xe1, + DSP_CMD_DSP_PROTECT = 0xe2, + DSP_CMD_GET_CR = 0xe3, + DSP_CMD_WRITE_TESTREG = 0xe4, + DSP_CMD_READ_TESTREG = 0xe8, + DSP_CMD_GEN_8BIT_IRQ = 0xf2, + DSP_CMD_GEN_16BIT_IRQ = 0xf3, +} DSP_CMD; + +// コマンド長さ(引数の数)テーブル +static UINT8 ct1741dsp_cmdlentbl[256] = { 0 }; + +// コマンド長さ(引数の数)の取得 +static UINT8 ct1741dsp_getcmdlen(UINT8 cmd) { + if (DSP_CMD_PROGRAM_16BIT_DMA_BEGIN <= cmd && cmd <= DSP_CMD_PROGRAM_16BIT_DMA_END) { + return 3; + } + if (DSP_CMD_PROGRAM_8BIT_DMA_BEGIN <= cmd && cmd <= DSP_CMD_PROGRAM_8BIT_DMA_END) { + return 3; + } + switch (cmd) { + case DSP_CMD_GET_ASP_VERSION: + case DSP_CMD_SET_ASP_MODE_REG: + case DSP_CMD_READ_ASP_REG: + case DSP_CMD_8BIT_PIO: + case DSP_CMD_MIDI_OUT: + case DSP_CMD_SET_DS_TRANSFER_TIMECONSTANT: + case DSP_CMD_GET_DSP_ID: + case DSP_CMD_DSP_PROTECT: + case DSP_CMD_WRITE_TESTREG: + return 1; + case DSP_CMD_SET_ASP_CODEC: + case DSP_CMD_WRITE_ASP_REG: + case DSP_CMD_8BIT_DMA_SINGLE: + case DSP_CMD_2BITADPCM_DMA_SINGLE: + case DSP_CMD_2BITADPCM_DMA_SINGLE_WITH_REF: + case DSP_CMD_8BIT_DMA_SINGLE_IN: + case DSP_CMD_SET_DS_OUT_SAMPLINGRATE: + case DSP_CMD_SET_DS_IN_SAMPLINGRATE: + case DSP_CMD_SET_DSP_BLOCK_SIZE: + case DSP_CMD_4BITADPCM_DMA_SINGLE: + case DSP_CMD_4BITADPCM_DMA_SINGLE_WITH_REF: + case DSP_CMD_3BITADPCM_DMA_SINGLE: + case DSP_CMD_3BITADPCM_DMA_SINGLE_WITH_REF: + case DSP_CMD_PAUSE_DAC_DURATION: + return 2; + default: + return 0; + } +} + +// コマンド長さ(引数の数)テーブル作成 +static void ct1741dsp_create_cmdlentbl() { + int i; + for (i = 0; i < NELEMENTS(ct1741dsp_cmdlentbl); i++) { + ct1741dsp_cmdlentbl[i] = ct1741dsp_getcmdlen(i); + } +} + +// CPU→DSPのバッファをクリア +static void ct1741dsp_dspout_clear() +{ + g_sb16.dsp_info.dspout.datalen = 0; +} + +// CPU→DSPへ引数の値をPush +static void ct1741dsp_dspout_push(UINT8 dat) +{ + if (g_sb16.dsp_info.dspout.datalen < CT1741_DSP_BUFSIZE) { + g_sb16.dsp_info.dspout.data[(g_sb16.dsp_info.dspout.rpos + g_sb16.dsp_info.dspout.datalen) % CT1741_DSP_BUFSIZE] = dat; + g_sb16.dsp_info.dspout.datalen++; + } +} + +// DSP→CPUへ返す値をPush +static void ct1741dsp_dspin_push(UINT8 dat) +{ + if (g_sb16.dsp_info.dspin.datalen < CT1741_DSP_BUFSIZE) { + g_sb16.dsp_info.dspin.data[g_sb16.dsp_info.dspin.datalen] = dat; + g_sb16.dsp_info.dspin.datalen++; + } +} + +// DMA転送開始する +static void ct1741dsp_setdma(CT1741_DMAMODE mode, BOOL autoinit, BOOL stereo, BOOL input) +{ + g_sb16.dsp_info.dma.dmach = dmac.dmach + g_sb16.dmachnum; // DMA割り当て + if (g_sb16.dsp_info.mode != CT1741_DSPMODE_NONE) + { + // DMA開始後に設定を変えてくる場合があるので、その時は一旦止めて設定し直し + g_sb16.dsp_info.dma.dmach->ready = 0; + dmac_check(); + } + g_sb16.dsp_info.mode = input ? CT1741_DSPMODE_DMA_IN : CT1741_DSPMODE_DMA; + g_sb16.dsp_info.dma.lastautoinit = g_sb16.dsp_info.dma.autoinit = !!autoinit; + g_sb16.dsp_info.dma.stereo = !!stereo; + g_sb16.dsp_info.dma.mode = mode; + + // DMA開始 + g_sb16.dsp_info.dma.dmach->ready = 1; + dmac_check(); +} + +// DMA転送を再設定する +static void ct1741dsp_updatedma() +{ + ct1741dsp_setdma(g_sb16.dsp_info.dma.mode, g_sb16.dsp_info.dma.autoinit, g_sb16.dsp_info.dma.stereo, g_sb16.dsp_info.mode == CT1741_DSPMODE_DMA_IN); +} + +// DSPコマンドを実行 +static void ct1741dsp_exec_command() +{ + UINT8 cmd = g_sb16.dsp_info.cmd; + TRACEOUT(("CT1741 DSP CMD=0x%02x", cmd)); + if (DSP_CMD_PROGRAM_16BIT_DMA_BEGIN <= cmd && cmd <= DSP_CMD_PROGRAM_16BIT_DMA_END) { + // Prigram 16bit DMA + ct1741_playinfo.bufdatasrem = 0; + g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[2] << 8) | g_sb16.dsp_info.dspin.data[1]) + 1; + ct1741dsp_setdma(CT1741_DMAMODE_16, g_sb16.dsp_info.cmd & 0x4, g_sb16.dsp_info.dspin.data[0] & 0x20, g_sb16.dsp_info.cmd & 0x8); + g_sb16.mixreg[0x82] |= (g_sb16.dsp_info.dmachnum & 0xe0) ? 0x2 : 0x1; // High-DMAが有効な場合はHigh-DMAを使用 + if (g_sb16.dsp_info.cmd & 0x8) { + // 入力の場合、即座に割り込むことにする + ct1741_setpicirq(); + } + } + else if (DSP_CMD_PROGRAM_8BIT_DMA_BEGIN <= cmd && cmd <= DSP_CMD_PROGRAM_8BIT_DMA_END) { + // Prigram 8bit DMA + ct1741_playinfo.bufdatasrem = 0; + g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[2] << 8) | g_sb16.dsp_info.dspin.data[1]) + 1; + ct1741dsp_setdma(CT1741_DMAMODE_8, g_sb16.dsp_info.cmd & 0x4, g_sb16.dsp_info.dspin.data[0] & 0x20, g_sb16.dsp_info.cmd & 0x8); + g_sb16.mixreg[0x82] |= 0x1; + if (g_sb16.dsp_info.cmd & 0x8) { + // 入力の場合、即座に割り込むことにする + ct1741_setpicirq(); + } + } + else { + switch (g_sb16.dsp_info.cmd) { + case DSP_CMD_GET_ASP_VERSION: + break; + case DSP_CMD_SET_ASP_MODE_REG: + ct1741dsp_dspout_clear(); + ct1741dsp_dspout_push(0xff); + break; + case DSP_CMD_SET_ASP_CODEC: + break; + case DSP_CMD_WRITE_ASP_REG: + break; + case DSP_CMD_READ_ASP_REG: + ct1741dsp_dspout_clear(); + ct1741dsp_dspout_push(0); + break; + + case DSP_CMD_8BIT_PIO: + g_sb16.dsp_info.mode = CT1741_DSPMODE_DAC; + ct1741_playinfo.playwaitcounter = 0; + // PIO再生のつもりだがノーチェック +#if defined(SUPPORT_MULTITHREAD) + ct1741cs_enter_criticalsection(); +#endif + if (ct1741_playinfo.pio.bufdatas < CT1741_PIO_BUFSIZE) { + ct1741_playinfo.pio.buffer[ct1741_playinfo.pio.bufwpos] = g_sb16.dsp_info.dspin.data[0]; + ct1741_playinfo.pio.bufwpos++; + if (ct1741_playinfo.pio.bufwpos >= CT1741_PIO_BUFSIZE) ct1741_playinfo.pio.bufwpos -= CT1741_PIO_BUFSIZE; + ct1741_playinfo.pio.bufdatas++; + } +#if defined(SUPPORT_MULTITHREAD) + ct1741cs_leave_criticalsection(); +#endif + if (ct1741_playinfo.pio.bufdatas > CT1741_PIO_BUFSIZE / 2) { + if (ct1741_playinfo.pio.bufdatas > CT1741_PIO_BUFSIZE) + { + g_sb16.dsp_info.wbusy = 1; + } + else + { + g_sb16.dsp_info.wbusy = 0; + } + } + else + { + g_sb16.dsp_info.wbusy = 0; + } + break; + case DSP_CMD_8BIT_DMA_SINGLE: + g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; + ct1741_playinfo.bufdatasrem = 0; + ct1741dsp_setdma(CT1741_DMAMODE_8, FALSE, FALSE, FALSE); + break; + case DSP_CMD_2BITADPCM_DMA_SINGLE: + case DSP_CMD_2BITADPCM_DMA_SINGLE_WITH_REF: + ct1741_playinfo.bufdatasrem = 0; + g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; + ct1741dsp_setdma(CT1741_DMAMODE_2, FALSE, FALSE, FALSE); + break; + case DSP_CMD_8BIT_DMA_AUTOINIT: + ct1741_playinfo.bufdatasrem = 0; + ct1741dsp_setdma(CT1741_DMAMODE_8, TRUE, FALSE, FALSE); + break; + case DSP_CMD_2BITADPCM_DMA_AUTOINIT_WITH_REF: + ct1741_playinfo.bufdatasrem = 0; + g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; + ct1741dsp_setdma(CT1741_DMAMODE_2, TRUE, FALSE, FALSE); + break; + + case DSP_CMD_8BIT_PIO_IN: + // not implemented yet + break; + case DSP_CMD_8BIT_DMA_SINGLE_IN: + ct1741_playinfo.bufdatasrem = 0; + g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; + ct1741dsp_setdma(CT1741_DMAMODE_8, FALSE, FALSE, TRUE); + break; + case DSP_CMD_POLLING_MIDI_IN: + case DSP_CMD_INTERRUPT_MIDI_IN: + case DSP_CMD_UART_POLLING_MIDI: + case DSP_CMD_UART_INTERRUPT_MIDI: + case DSP_CMD_UART_POLLING_MIDI_TIMESTAMP: + case DSP_CMD_UART_INTERRUPT_MIDI_TIMESTAMP: + // not implemented yet + break; + case DSP_CMD_MIDI_OUT: + if (!g_sb16.dsp_info.uartmode) { + if (mpu98.enable) { + mpu98.mode = 1; // force set UART mode + mpu98ii_o0(0x8000 + g_sb16.base, g_sb16.dsp_info.dspin.data[0]); + } + else if (smpu98.enable) { + smpu98.mode = 1; // force set UART mode + smpu98_o0(0x8000 + g_sb16.base, g_sb16.dsp_info.dspin.data[0]); + } + } + break; + + case DSP_CMD_SET_DS_TRANSFER_TIMECONSTANT: + g_sb16.dsp_info.freq = (1000000 / (256 - g_sb16.dsp_info.dspin.data[0])); + if (g_sb16.dsp_info.dma.mode != CT1741_DMAMODE_NONE && g_sb16.dsp_info.dma.autoinit) { + ct1741dsp_updatedma(); + } + break; + case DSP_CMD_SET_DS_OUT_SAMPLINGRATE: + case DSP_CMD_SET_DS_IN_SAMPLINGRATE: + g_sb16.dsp_info.freq = (g_sb16.dsp_info.dspin.data[0] << 8) | g_sb16.dsp_info.dspin.data[1]; + break; + case DSP_CMD_SET_DSP_BLOCK_SIZE: + g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; + break; + + case DSP_CMD_4BITADPCM_DMA_SINGLE: + case DSP_CMD_4BITADPCM_DMA_SINGLE_WITH_REF: + ct1741_playinfo.bufdatasrem = 0; + g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; + ct1741dsp_setdma(CT1741_DMAMODE_4, FALSE, FALSE, FALSE); + break; + case DSP_CMD_3BITADPCM_DMA_SINGLE: + case DSP_CMD_3BITADPCM_DMA_SINGLE_WITH_REF: + ct1741_playinfo.bufdatasrem = 0; + g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; + ct1741dsp_setdma(CT1741_DMAMODE_3, FALSE, FALSE, FALSE); + break; + case DSP_CMD_4BITADPCM_DMA_AUTOINIT_WITH_REF: + ct1741_playinfo.bufdatasrem = 0; + g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; + ct1741dsp_setdma(CT1741_DMAMODE_4, TRUE, FALSE, FALSE); + break; + case DSP_CMD_3BITADPCM_DMA_AUTOINIT_WITH_REF: + ct1741_playinfo.bufdatasrem = 0; + g_sb16.dsp_info.dma.total = ((g_sb16.dsp_info.dspin.data[1] << 8) | g_sb16.dsp_info.dspin.data[0]) + 1; + ct1741dsp_setdma(CT1741_DMAMODE_3, TRUE, FALSE, FALSE); + break; + + case DSP_CMD_PAUSE_DAC_DURATION: + // not implemented yet + break; + + case DSP_CMD_8BIT_HIGHSPEED_DMA_AUTOINIT: + ct1741_playinfo.bufdatasrem = 0; + ct1741dsp_setdma(CT1741_DMAMODE_8, TRUE, FALSE, FALSE); + break; + case DSP_CMD_8BIT_HIGHSPEED_DMA_SINGLE: + ct1741_playinfo.bufdatasrem = 0; + ct1741dsp_setdma(CT1741_DMAMODE_8, FALSE, FALSE, FALSE); + break; + case DSP_CMD_8BIT_HIGHSPEED_DMA_AUTOINIT_IN: + ct1741_playinfo.bufdatasrem = 0; + ct1741dsp_setdma(CT1741_DMAMODE_8, TRUE, FALSE, TRUE); + break; + case DSP_CMD_8BIT_HIGHSPEED_DMA_SINGLE_IN: + ct1741_playinfo.bufdatasrem = 0; + ct1741dsp_setdma(CT1741_DMAMODE_8, FALSE, FALSE, TRUE); + break; + + case DSP_CMD_SET_MONO: + case DSP_CMD_SET_STEREO: + // not supported in DSP V4 + break; + + case DSP_CMD_PAUSE_8BIT_DMA: + case DSP_CMD_PAUSE_16BIT_DMA: + ct1741_playinfo.bufdatasrem = g_sb16.dsp_info.dma.bufdatas; // 停止した瞬間までに送られていた分は再生する + g_sb16.dsp_info.mode = CT1741_DSPMODE_DMA_PAUSE; + g_sb16.dsp_info.dma.mode = CT1741_DMAMODE_NONE; + break; + case DSP_CMD_SPEAKER_ON: + g_sb16.dsp_info.speaker = 0xff; + break; + case DSP_CMD_SPEAKER_OFF: + ct1741_playinfo.bufdatasrem = 0; // バッファ破棄 + g_sb16.dsp_info.speaker = 0x00; + break; + case DSP_CMD_CONTINUE_8BIT_DMA: + case DSP_CMD_CONTINUE_16BIT_DMA: + if (g_sb16.dsp_info.mode == CT1741_DSPMODE_DMA_PAUSE) { + g_sb16.dsp_info.mode = CT1741_DSPMODE_DMA; + ct1741_playinfo.bufdatasrem = 0; + } + break; + case DSP_CMD_GET_SPEAKER_STATUS: + ct1741dsp_dspout_clear(); + ct1741dsp_dspout_push(g_sb16.dsp_info.speaker); + break; + case DSP_CMD_EXIT_16BIT_DMA_AUTOINIT: + case DSP_CMD_EXIT_8BIT_DMA_AUTOINIT: + { + // 停止した瞬間までに送られていた分は再生する +#if defined(SUPPORT_MULTITHREAD) + ct1741cs_enter_criticalsection(); +#endif + if (g_sb16.dsp_info.dma.bufdatas > g_sb16.dsp_info.dma.total || g_sb16.dsp_info.dma.total == 65536) { + // WORKAROUND: バッファを捨てて停止する。この処理をするとWin3.1で後ろが切れる。しないとWin9x DirectSoundで末尾にノイズ(ダブり)が入る + g_sb16.dsp_info.dma.bufdatas = 0; + g_sb16.dsp_info.dma.dmach->ready = 0; + } + g_sb16.dsp_info.dma.autoinit = FALSE; // 本来は次の割り込みタイミングで停止らしい +#if defined(SUPPORT_MULTITHREAD) + ct1741cs_leave_criticalsection(); +#endif + break; + } + + case DSP_CMD_GET_DSP_ID: + ct1741dsp_dspout_clear(); + ct1741dsp_dspout_push(~g_sb16.dsp_info.dspin.data[0]); + break; + case DSP_CMD_GET_DSP_VERSION: + ct1741dsp_dspout_clear(); + ct1741dsp_dspout_push(0x4); + ct1741dsp_dspout_push(0xc); + break; + case DSP_CMD_DSP_PROTECT: + // not implemented yet + break; + case DSP_CMD_GET_CR: + { + UINT32 i; + char crstr[] = "NOT COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; + ct1741dsp_dspout_clear(); + for (i = 4; i < sizeof(crstr); i++) { + ct1741dsp_dspout_push(crstr[i]); + } + } + break; + case DSP_CMD_WRITE_TESTREG: + g_sb16.dsp_info.testreg = g_sb16.dsp_info.dspin.data[0]; + break; + case DSP_CMD_READ_TESTREG: + ct1741dsp_dspout_clear(); + ct1741dsp_dspout_push(g_sb16.dsp_info.testreg);; + break; + case DSP_CMD_GEN_8BIT_IRQ: + ct1741dsp_dspout_clear(); + ct1741dsp_dspout_push(0xaa); + ct1741_setpicirq(); + g_sb16.mixreg[0x82] |= 1; + break; + case DSP_CMD_GEN_16BIT_IRQ: + ct1741dsp_dspout_clear(); + ct1741dsp_dspout_push(0xaa); + ct1741_setpicirq(); + g_sb16.mixreg[0x82] |= 2; + break; + default: + break; + } + } + g_sb16.dsp_info.dspin.datalen = 0; + g_sb16.dsp_info.cmd = DSP_CMD_NONE; + g_sb16.dsp_info.cmdlen = 0; +} + +// DSPをリセット +static void ct1741dsp_reset(BOOL ioreset) +{ + g_sb16.dsp_info.mode = CT1741_DSPMODE_NONE; + g_sb16.dsp_info.freq = CT1741_DSP_SAMPLES_DEFAULT; + g_sb16.dsp_info.cmdlen = 0; + g_sb16.dsp_info.dspin.datalen = 0; + g_sb16.dsp_info.wbusy = 0; + g_sb16.dsp_info.uartmode = 0; + g_sb16.dsp_info.dma.autoinit = FALSE; + g_sb16.dsp_info.dma.lastautoinit = FALSE; + if (ioreset) { + if (g_sb16.dsp_info.dma.dmach) { + g_sb16.dsp_info.dma.dmach->ready = 0; + dmac_check(); + if (g_sb16.dmachnum != 0xff) { + dmac.stat |= (1 << g_sb16.dmachnum); + } + g_sb16.mixreg[0x82] &= ~3; + ct1741_resetpicirq(); + } + } +} + +// ***** DSP I/O Ports ***** + +/* DSP reset */ +static void IOOUTCALL ct1741dsp_write_reset(UINT port, REG8 dat) +{ + TRACEOUT(("CT1741 DSP Write Reset")); + if ((dat & 0x01)) { + /* status reset */ + ct1741dsp_reset(TRUE); + g_sb16.dsp_info.resetout = CT1741_DSPRST_RESET; + } + else { + /* status normal */ + ct1741dsp_dspout_clear(); + ct1741dsp_dspout_push(0xaa); + g_sb16.dsp_info.resetout = CT1741_DSPRST_NORMAL; + } + + if (dat == 0xc6) { + ct1741dsp_dspout_clear(); + ct1741dsp_reset(TRUE); + g_sb16.dsp_info.resetout = CT1741_DSPRST_SPECIAL; + } +} + +/* DSP write Command/Data */ +static void IOOUTCALL ct1741dsp_write_data(UINT port, REG8 dat) +{ + TRACEOUT(("CT1741 DSP command: %.2x", dat)); + if (g_sb16.dsp_info.cmd == DSP_CMD_NONE) { + // コマンド書き込み + g_sb16.dsp_info.dspin.datalen = 0; + g_sb16.dsp_info.cmd = g_sb16.dsp_info.cmd_o = dat; + g_sb16.dsp_info.cmdlen = ct1741dsp_cmdlentbl[dat]; + } + else { + // パラメータ書き込み + ct1741dsp_dspin_push(dat); + } + if (g_sb16.dsp_info.dspin.datalen >= g_sb16.dsp_info.cmdlen) { + // パラメータが規定数に達したら実行 + ct1741dsp_exec_command(); + } +} + +/* DSP reset read */ +static REG8 IOINPCALL ct1741dsp_read_reset(UINT port) +{ + if ((port & 0x0d00) == 0x0d00) + return 0x00; // アドレスが xDxxhの時は0x00を返す + else + return 0xff; // アドレスが上記以外の時は0xffを返す +} + +/* DSP read data */ +static REG8 IOINPCALL ct1741dsp_read_data(UINT port) +{ + static REG8 data = 0; + if (g_sb16.dsp_info.dspout.datalen) { + if (g_sb16.dsp_info.dspout.rpos < sizeof(g_sb16.dsp_info.dspout.data) / sizeof(g_sb16.dsp_info.dspout.data[0])) { + data = g_sb16.dsp_info.dspout.data[g_sb16.dsp_info.dspout.rpos]; + g_sb16.dsp_info.dspout.rpos++; + if (g_sb16.dsp_info.dspout.rpos >= CT1741_DSP_BUFSIZE) + g_sb16.dsp_info.dspout.rpos -= CT1741_DSP_BUFSIZE; + g_sb16.dsp_info.dspout.datalen--; + } + } + return data; +} + +/* DSP read write status */ +static REG8 IOINPCALL ct1741dsp_read_wstatus(UINT port) +{ + switch (g_sb16.dsp_info.resetout) { + case CT1741_DSPRST_NORMAL: + return g_sb16.dsp_info.wbusy ? 0x80 : 0x00; + + case CT1741_DSPRST_RESET: + return 0xff; + + case CT1741_DSPRST_SPECIAL: + return 0; + + default: // ????変な数値とるときがある 意味不明 + return 0; + } + return 0xff; +} + +/* DSP read read status (8 bit) */ +static REG8 IOINPCALL ct1741dsp_read_rstatus(UINT port) +{ + TRACEOUT(("CT1741 DSP read read status")); + // 詳細不明 + if (g_sb16.dsp_info.cmd_o == 0xf2) { + g_sb16.dsp_info.cmd_o = 0; + return 0; + } + // 割り込みを解除。bit0は8-bit用 + if (g_sb16.mixreg[0x82] & 1) { + g_sb16.mixreg[0x82] &= ~1; + ct1741_resetpicirq(); + } + + if (g_sb16.dsp_info.dspout.datalen) + return 0x80; + else + return 0x00; +} + +/* DSP read read status (16 bit) */ +static REG8 IOINPCALL ct1741dsp_read_rstatus16(UINT port) +{ + TRACEOUT(("CT1741 DSP read read status16")); + // 割り込みを解除。bit1は16-bit用 + if (g_sb16.mixreg[0x82] & 2) { + g_sb16.mixreg[0x82] &= ~2; + ct1741_resetpicirq(); + } + + return 0xff; +} + +void ct1741io_reset(void) +{ + ct1741dsp_create_cmdlentbl(); + ct1741dsp_reset(FALSE); + g_sb16.dsp_info.dmairq = ct1741_get_dma_irq(); + g_sb16.dsp_info.dmachnum = ct1741_get_dma_ch() & 0xf; // High DMAはDefaultで無効 + g_sb16.dsp_info.resetout = CT1741_DSPRST_NORMAL; + if (g_sb16.dmachnum == 0 || g_sb16.dmachnum == 3) { + g_sb16.dsp_info.dma.dmach = dmac.dmach + g_sb16.dmachnum; // DMA割り当て + dmac_attach(DMADEV_CT1741, g_sb16.dmachnum); + } + g_sb16.dsp_info.dma.bufsize = CT1741_DMA_BUFSIZE; + g_sb16.dsp_info.dma.rate2 = ct1741_playinfo.playrate; + g_sb16.dsp_info.dma.bufdatas = 0; + ct1741_playinfo.playwaitcounter = 0; + ct1741_playinfo.bufdatasrem = 0; +} + +void ct1741io_bind(void) +{ + sound_streamregist(&g_sb16.dsp_info.dma, (SOUNDCB)ct1741_getpcm); // CT1741用 オーディオ再生ストリーム + + iocore_attachout(0x2600 + g_sb16.base, ct1741dsp_write_reset); /* DSP Reset */ + iocore_attachout(0x2C00 + g_sb16.base, ct1741dsp_write_data); /* DSP Write Command/Data */ + + iocore_attachinp(0x2600 + g_sb16.base, ct1741dsp_read_reset); /* DSP Reset */ + iocore_attachinp(0x2a00 + g_sb16.base, ct1741dsp_read_data); /* DSP Read Data Port */ + iocore_attachinp(0x2c00 + g_sb16.base, ct1741dsp_read_wstatus); /* DSP Write Buffer Status (Bit 7) */ + iocore_attachinp(0x2d00 + g_sb16.base, ct1741dsp_read_reset); /* DSP Reset */ + iocore_attachinp(0x2e00 + g_sb16.base, ct1741dsp_read_rstatus); /* DSP Read Buffer Status (Bit 7) */ + iocore_attachinp(0x2f00 + g_sb16.base, ct1741dsp_read_rstatus16); /* DSP Read Buffer Status (Bit 7) */ + + // Canopus PowerWindow T64S/98 音源部テスト + iocore_attachout(0x6600 + g_sb16.base, ct1741dsp_write_reset); /* DSP Reset */ + iocore_attachout(0x6C00 + g_sb16.base, ct1741dsp_write_data); /* DSP Write Command/Data */ + + iocore_attachinp(0x6600 + g_sb16.base, ct1741dsp_read_reset); /* DSP Reset */ + iocore_attachinp(0x6a00 + g_sb16.base, ct1741dsp_read_data); /* DSP Read Data Port */ + iocore_attachinp(0x6c00 + g_sb16.base, ct1741dsp_read_wstatus); /* DSP Write Buffer Status (Bit 7) */ + iocore_attachinp(0x6d00 + g_sb16.base, ct1741dsp_read_reset); /* DSP Reset */ + iocore_attachinp(0x6e00 + g_sb16.base, ct1741dsp_read_rstatus); /* DSP Read Buffer Status (Bit 7) */ + iocore_attachinp(0x6f00 + g_sb16.base, ct1741dsp_read_rstatus16); /* DSP Read Buffer Status (Bit 7) */ + + // PC/AT互換機テスト + if(np2cfg.sndsb16at){ + iocore_attachout(0x226, ct1741dsp_write_reset); /* DSP Reset */ + iocore_attachout(0x22C, ct1741dsp_write_data); /* DSP Write Command/Data */ + + iocore_attachinp(0x226, ct1741dsp_read_reset); /* DSP Reset */ + iocore_attachinp(0x22a, ct1741dsp_read_data); /* DSP Read Data Port */ + iocore_attachinp(0x22c, ct1741dsp_read_wstatus); /* DSP Write Buffer Status (Bit 7) */ + iocore_attachinp(0x22d, ct1741dsp_read_reset); /* DSP Reset */ + iocore_attachinp(0x22e, ct1741dsp_read_rstatus); /* DSP Read Buffer Status (Bit 7) */ + iocore_attachinp(0x22f, ct1741dsp_read_rstatus16); /* DSP Read Buffer Status (Bit 7) */ + } +} +void ct1741io_unbind(void) +{ + iocore_detachout(0x2600 + g_sb16.base); /* DSP Reset */ + iocore_detachout(0x2C00 + g_sb16.base); /* DSP Write Command/Data */ + + iocore_detachinp(0x2600 + g_sb16.base); /* DSP Reset */ + iocore_detachinp(0x2a00 + g_sb16.base); /* DSP Read Data Port */ + iocore_detachinp(0x2c00 + g_sb16.base); /* DSP Write Buffer Status (Bit 7) */ + iocore_detachinp(0x2e00 + g_sb16.base); /* DSP Read Buffer Status (Bit 7) */ + iocore_detachinp(0x2f00 + g_sb16.base); /* DSP Read Buffer Status (Bit 7) */ + + // Canopus PowerWindow T64S/98 音源部テスト + iocore_detachinp(0x6600 + g_sb16.base); /* DSP Reset */ + iocore_detachinp(0x6C00 + g_sb16.base); /* DSP Write Command/Data */ + + iocore_detachinp(0x6600 + g_sb16.base); /* DSP Reset */ + iocore_detachinp(0x6a00 + g_sb16.base); /* DSP Read Data Port */ + iocore_detachinp(0x6c00 + g_sb16.base); /* DSP Write Buffer Status (Bit 7) */ + iocore_detachinp(0x6d00 + g_sb16.base); /* DSP Reset */ + iocore_detachinp(0x6e00 + g_sb16.base); /* DSP Read Buffer Status (Bit 7) */ + iocore_detachinp(0x6f00 + g_sb16.base); /* DSP Read Buffer Status (Bit 7) */ + + // PC/AT互換機テスト + if(np2cfg.sndsb16at){ + iocore_detachout(0x226); /* DSP Reset */ + iocore_detachout(0x22C); /* DSP Write Command/Data */ + + iocore_detachinp(0x226); /* DSP Reset */ + iocore_detachinp(0x22a); /* DSP Read Data Port */ + iocore_detachinp(0x22c); /* DSP Write Buffer Status (Bit 7) */ + iocore_detachinp(0x22d); /* DSP Reset */ + iocore_detachinp(0x22e); /* DSP Read Buffer Status (Bit 7) */ + iocore_detachinp(0x22f); /* DSP Read Buffer Status (Bit 7) */ + } +} + #endif \ No newline at end of file diff --git a/cbus/ct1741io.h b/cbus/ct1741io.h old mode 100755 new mode 100644 index 8634bca9..1c703e01 --- a/cbus/ct1741io.h +++ b/cbus/ct1741io.h @@ -1,22 +1,22 @@ -/** - * @file ct1741io.h - * @brief Interface of the Creative SoundBlaster16 CT1741 DSP I/O - */ - -#pragma once - -#ifdef SUPPORT_SOUND_SB16 - -#ifdef __cplusplus -extern "C" { -#endif - -void ct1741io_reset(); -void ct1741io_bind(void); -void ct1741io_unbind(void); - -#ifdef __cplusplus -} -#endif - +/** + * @file ct1741io.h + * @brief Interface of the Creative SoundBlaster16 CT1741 DSP I/O + */ + +#pragma once + +#ifdef SUPPORT_SOUND_SB16 + +#ifdef __cplusplus +extern "C" { +#endif + +void ct1741io_reset(); +void ct1741io_bind(void); +void ct1741io_unbind(void); + +#ifdef __cplusplus +} +#endif + #endif \ No newline at end of file diff --git a/cbus/ct1745io.c b/cbus/ct1745io.c old mode 100755 new mode 100644 index 823c882e..ef3b78c4 --- a/cbus/ct1745io.c +++ b/cbus/ct1745io.c @@ -1,258 +1,258 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#if 0 -#undef TRACEOUT -#define USE_TRACEOUT_VS -#ifdef USE_TRACEOUT_VS -static void trace_fmt_ex(const char *fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#else -#define TRACEOUT(s) (void)(s) -#endif -#endif /* 1 */ - -#ifdef SUPPORT_SOUND_SB16 - -/** - * Creative SoundBlaster16 mixer CT1745 - */ - -static void ct1745_mixer_reset() { - ZeroMemory(g_sb16.mixreg, sizeof(g_sb16.mixreg)); - - g_sb16.mixregexp[MIXER_MASTER_LEFT] = g_sb16.mixreg[MIXER_MASTER_LEFT] = - g_sb16.mixregexp[MIXER_MASTER_RIGHT] = g_sb16.mixreg[MIXER_MASTER_RIGHT] = - g_sb16.mixregexp[MIXER_VOC_LEFT] = g_sb16.mixreg[MIXER_VOC_LEFT] = - g_sb16.mixregexp[MIXER_VOC_RIGHT] = g_sb16.mixreg[MIXER_VOC_RIGHT] = - g_sb16.mixregexp[MIXER_MIDI_LEFT] = g_sb16.mixreg[MIXER_MIDI_LEFT] = - g_sb16.mixregexp[MIXER_MIDI_RIGHT] = g_sb16.mixreg[MIXER_MIDI_RIGHT] = 0xff; - g_sb16.mixregexp[MIXER_OUT_SW] = g_sb16.mixreg[MIXER_OUT_SW] = 0x1f; - g_sb16.mixregexp[MIXER_IN_SW_LEFT] = g_sb16.mixreg[MIXER_IN_SW_LEFT] = 0x15; - g_sb16.mixregexp[MIXER_IN_SW_RIGHT] = g_sb16.mixreg[MIXER_IN_SW_RIGHT] = 0x0b; - - g_sb16.mixregexp[MIXER_TREBLE_LEFT] = g_sb16.mixreg[MIXER_TREBLE_LEFT] = - g_sb16.mixregexp[MIXER_TREBLE_RIGHT] = g_sb16.mixreg[MIXER_TREBLE_RIGHT] = - g_sb16.mixregexp[MIXER_BASS_LEFT] = g_sb16.mixreg[MIXER_BASS_LEFT] = - g_sb16.mixregexp[MIXER_BASS_RIGHT] = g_sb16.mixreg[MIXER_BASS_RIGHT] = 8; - g_sb16.mixregexp[0x82] = g_sb16.mixreg[0x82] = 2<<5; - -} - -static void IOOUTCALL sb16_o2400(UINT port, REG8 dat) { - (void)port; - g_sb16.mixsel = dat; -} -static void IOOUTCALL sb16_o2500(UINT port, REG8 dat) { -//printf("mixer port write %x %x¥n",dat,g_sb16.mixsel); - if (g_sb16.mixsel >= MIXER_VOL_START && - g_sb16.mixsel <= MIXER_VOL_END) { - g_sb16.mixreg[g_sb16.mixsel] = dat; - g_sb16.mixregexp[g_sb16.mixsel] = (int)(pow(((dat >> 3) & 0x1f) / 32.0, 2) * 255);//(int)(pow(dat / 255.0, 4) * 255); - TRACEOUT(("CT1745 MIXER ID=0x%02x, DATA=0x%02x", g_sb16.mixsel, dat)); - return; - } - - switch (g_sb16.mixsel) { - case MIXER_RESET: // Mixer reset - ct1745_mixer_reset(); - break; - case 0x04: // Voice volume(old) - g_sb16.mixregexp[MIXER_VOC_LEFT] = g_sb16.mixreg[MIXER_VOC_LEFT] = (dat & 0x0f) << 4; - g_sb16.mixregexp[MIXER_VOC_RIGHT] = g_sb16.mixreg[MIXER_VOC_RIGHT] = (dat & 0xf0); - break; - case 0x0a: // Mic volume(old) - g_sb16.mixregexp[MIXER_MIC] = g_sb16.mixreg[MIXER_MIC] = dat & 0x7; - break; - case 0x22: // Master volume(old) - g_sb16.mixregexp[MIXER_MASTER_LEFT] = g_sb16.mixreg[MIXER_MASTER_LEFT] = (dat & 0x0f) << 4; - g_sb16.mixregexp[MIXER_MASTER_RIGHT] = g_sb16.mixreg[MIXER_MASTER_RIGHT] = (dat & 0xf0); - break; - case 0x26: // MIDI volume(old) - g_sb16.mixregexp[MIXER_MIDI_LEFT] = g_sb16.mixreg[MIXER_MIDI_LEFT] = (dat & 0x0f) << 4; - g_sb16.mixregexp[MIXER_MIDI_RIGHT] = g_sb16.mixreg[MIXER_MIDI_RIGHT] = (dat & 0xf0); - break; - case 0x28: // CD volume(old) - g_sb16.mixregexp[MIXER_CD_LEFT] = g_sb16.mixreg[MIXER_CD_LEFT] = (dat & 0x0f) << 4; - g_sb16.mixregexp[MIXER_CD_RIGHT] = g_sb16.mixreg[MIXER_CD_RIGHT] = (dat & 0xf0); - break; - case 0x2e: // Line volume(old) - g_sb16.mixregexp[MIXER_LINE_LEFT] = g_sb16.mixreg[MIXER_LINE_LEFT] = (dat & 0x0f) << 4; - g_sb16.mixregexp[MIXER_LINE_RIGHT] = g_sb16.mixreg[MIXER_LINE_RIGHT] = (dat & 0xff); - - case 0x80: // Write irq num - ct1741_set_dma_irq(dat & ~0xf0); // reservedビットは0扱い - TRACEOUT(("CT1745 MIXER SET IRQ ID=0x%02x", dat)); - break; - case 0x81: // Write dma num - ct1741_set_dma_ch(dat & ~0x14); // reservedビットは0扱い - TRACEOUT(("CT1745 MIXER SET DMA ID=0x%02x", dat)); - break; - case 0x83: - default: - break; - } - -} -static void IOOUTCALL sb16_o2500_AT(UINT port, REG8 dat) { - if(g_sb16.mixsel==0x80){ - switch (dat) { - case 1: // IRQ2 - // 変換不能 - break; - case 2: // IRQ5 - dat = 8; - break; - case 4: // IRQ7 (IRQ2) - // 変換不能 - break; - case 8: // IRQ10 - dat = 2; - break; - } - }else if(g_sb16.mixsel==0x81){ - switch (dat) { - case 1: // DMA0 - dat = 1; - break; - case 2: // DMA1 - // 変換不能 - break; - case 4: // NONE - // 変換不能 - break; - case 8: // DMA3 - dat = 2; - break; - } - } - sb16_o2500(port, dat); -} - -static REG8 IOINPCALL sb16_i2400(UINT port) { - return g_sb16.mixsel; -} -static REG8 IOINPCALL sb16_i2500(UINT port) { -//printf("mixer port read %x %x¥n",g_sb16.mixreg[g_sb16.mixsel],g_sb16.mixsel); - if (g_sb16.mixsel >= MIXER_VOL_START && g_sb16.mixsel <= MIXER_VOL_END) { - return g_sb16.mixreg[g_sb16.mixsel]; - } - - switch (g_sb16.mixsel) { - case 0x04: - return (g_sb16.mixreg[MIXER_VOC_LEFT] + g_sb16.mixreg[MIXER_VOC_RIGHT]) << 1; - case 0x22: - return (g_sb16.mixreg[MIXER_MASTER_LEFT] + g_sb16.mixreg[MIXER_MASTER_RIGHT]) << 1; - case 0x26: - return (g_sb16.mixreg[MIXER_MIDI_LEFT] + g_sb16.mixreg[MIXER_MIDI_RIGHT]) << 1; - case 0x28: // CD volume(old) - return (g_sb16.mixreg[MIXER_CD_LEFT] + g_sb16.mixreg[MIXER_CD_RIGHT]) << 1; - case 0x2e: // Line volume(old) - return (g_sb16.mixreg[MIXER_LINE_LEFT] + g_sb16.mixreg[MIXER_LINE_RIGHT]) << 1; - case 0x0a: // Mic volume(old) - return g_sb16.mixreg[MIXER_MIC]; - case 0x80: // Read irq num - return g_sb16.dsp_info.dmairq | 0xf0; // reservedビットは1扱い - case 0x81: // Read dma num - return g_sb16.dsp_info.dmachnum | 0x14; // reservedビットは1扱い - case 0x82: // Irq pending(98には不要) diagnose用 他よくわからず - // PC/ATでは割り込み発生元が何かを表している  bit 0x04 MPU, bit 0x02 DMA16ACK, bit 0x01 AVAIL - if(g_sb16.mixreg[0x82] == 0x41)return 0x1; - if(g_sb16.mixreg[0x82] == 0x42)return 0x2; - if(g_sb16.mixreg[0x82] == 0x43)return 0x3; - else return 0x40; - default: - break; - } - return 0; -} -static REG8 IOINPCALL sb16_i2500_AT(UINT port) { - REG8 ret = sb16_i2500(port); - if(g_sb16.mixsel==0x80){ - switch (ret) { - case 1: // IRQ3 - // 変換不能 - break; - case 2: // IRQ10 - ret = 8; - break; - case 4: // IRQ12 - // 変換不能 - break; - case 8: // IRQ5 - ret = 2; - break; - } - }else if(g_sb16.mixsel==0x81){ - switch (ret) { - case 1: // DMA0 - ret = 1; - break; - case 2: // DMA3 - ret = 8; - break; - case 4: // NONE - // 変換不能 - break; - case 8: // NONE - // 変換不能 - break; - } - } - return ret; -} - -void ct1745io_reset(void) -{ - ct1745_mixer_reset(); -} - -void ct1745io_bind(void) -{ - iocore_attachout(0x2400 + g_sb16.base, sb16_o2400); /* Mixer Chip Register Address Port */ - iocore_attachout(0x2500 + g_sb16.base, sb16_o2500); /* Mixer Chip Data Port */ - iocore_attachinp(0x2400 + g_sb16.base, sb16_i2400); /* Mixer Chip Register Address Port */ - iocore_attachinp(0x2500 + g_sb16.base, sb16_i2500); /* Mixer Chip Data Port */ - - // PC/AT互換機テスト - if(np2cfg.sndsb16at){ - iocore_attachout(0x224, sb16_o2400); /* Mixer Chip Register Address Port */ - iocore_attachout(0x225, sb16_o2500_AT); /* Mixer Chip Data Port */ - iocore_attachinp(0x224, sb16_i2400); /* Mixer Chip Register Address Port */ - iocore_attachinp(0x225, sb16_i2500_AT); /* Mixer Chip Data Port */ - } -} -void ct1745io_unbind(void) -{ - iocore_detachout(0x2400 + g_sb16.base); /* Mixer Chip Register Address Port */ - iocore_detachout(0x2500 + g_sb16.base); /* Mixer Chip Data Port */ - iocore_detachinp(0x2400 + g_sb16.base); /* Mixer Chip Register Address Port */ - iocore_detachinp(0x2500 + g_sb16.base); /* Mixer Chip Data Port */ - - // PC/AT互換機テスト - if(np2cfg.sndsb16at){ - iocore_detachout(0x224); /* Mixer Chip Register Address Port */ - iocore_detachout(0x225); /* Mixer Chip Data Port */ - iocore_detachinp(0x224); /* Mixer Chip Register Address Port */ - iocore_detachinp(0x225); /* Mixer Chip Data Port */ - } -} - +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if 0 +#undef TRACEOUT +#define USE_TRACEOUT_VS +#ifdef USE_TRACEOUT_VS +static void trace_fmt_ex(const char *fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "¥n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#else +#define TRACEOUT(s) (void)(s) +#endif +#endif /* 1 */ + +#ifdef SUPPORT_SOUND_SB16 + +/** + * Creative SoundBlaster16 mixer CT1745 + */ + +static void ct1745_mixer_reset() { + ZeroMemory(g_sb16.mixreg, sizeof(g_sb16.mixreg)); + + g_sb16.mixregexp[MIXER_MASTER_LEFT] = g_sb16.mixreg[MIXER_MASTER_LEFT] = + g_sb16.mixregexp[MIXER_MASTER_RIGHT] = g_sb16.mixreg[MIXER_MASTER_RIGHT] = + g_sb16.mixregexp[MIXER_VOC_LEFT] = g_sb16.mixreg[MIXER_VOC_LEFT] = + g_sb16.mixregexp[MIXER_VOC_RIGHT] = g_sb16.mixreg[MIXER_VOC_RIGHT] = + g_sb16.mixregexp[MIXER_MIDI_LEFT] = g_sb16.mixreg[MIXER_MIDI_LEFT] = + g_sb16.mixregexp[MIXER_MIDI_RIGHT] = g_sb16.mixreg[MIXER_MIDI_RIGHT] = 0xff; + g_sb16.mixregexp[MIXER_OUT_SW] = g_sb16.mixreg[MIXER_OUT_SW] = 0x1f; + g_sb16.mixregexp[MIXER_IN_SW_LEFT] = g_sb16.mixreg[MIXER_IN_SW_LEFT] = 0x15; + g_sb16.mixregexp[MIXER_IN_SW_RIGHT] = g_sb16.mixreg[MIXER_IN_SW_RIGHT] = 0x0b; + + g_sb16.mixregexp[MIXER_TREBLE_LEFT] = g_sb16.mixreg[MIXER_TREBLE_LEFT] = + g_sb16.mixregexp[MIXER_TREBLE_RIGHT] = g_sb16.mixreg[MIXER_TREBLE_RIGHT] = + g_sb16.mixregexp[MIXER_BASS_LEFT] = g_sb16.mixreg[MIXER_BASS_LEFT] = + g_sb16.mixregexp[MIXER_BASS_RIGHT] = g_sb16.mixreg[MIXER_BASS_RIGHT] = 8; + g_sb16.mixregexp[0x82] = g_sb16.mixreg[0x82] = 2<<5; + +} + +static void IOOUTCALL sb16_o2400(UINT port, REG8 dat) { + (void)port; + g_sb16.mixsel = dat; +} +static void IOOUTCALL sb16_o2500(UINT port, REG8 dat) { +//printf("mixer port write %x %x¥n",dat,g_sb16.mixsel); + if (g_sb16.mixsel >= MIXER_VOL_START && + g_sb16.mixsel <= MIXER_VOL_END) { + g_sb16.mixreg[g_sb16.mixsel] = dat; + g_sb16.mixregexp[g_sb16.mixsel] = (int)(pow(((dat >> 3) & 0x1f) / 32.0, 2) * 255);//(int)(pow(dat / 255.0, 4) * 255); + TRACEOUT(("CT1745 MIXER ID=0x%02x, DATA=0x%02x", g_sb16.mixsel, dat)); + return; + } + + switch (g_sb16.mixsel) { + case MIXER_RESET: // Mixer reset + ct1745_mixer_reset(); + break; + case 0x04: // Voice volume(old) + g_sb16.mixregexp[MIXER_VOC_LEFT] = g_sb16.mixreg[MIXER_VOC_LEFT] = (dat & 0x0f) << 4; + g_sb16.mixregexp[MIXER_VOC_RIGHT] = g_sb16.mixreg[MIXER_VOC_RIGHT] = (dat & 0xf0); + break; + case 0x0a: // Mic volume(old) + g_sb16.mixregexp[MIXER_MIC] = g_sb16.mixreg[MIXER_MIC] = dat & 0x7; + break; + case 0x22: // Master volume(old) + g_sb16.mixregexp[MIXER_MASTER_LEFT] = g_sb16.mixreg[MIXER_MASTER_LEFT] = (dat & 0x0f) << 4; + g_sb16.mixregexp[MIXER_MASTER_RIGHT] = g_sb16.mixreg[MIXER_MASTER_RIGHT] = (dat & 0xf0); + break; + case 0x26: // MIDI volume(old) + g_sb16.mixregexp[MIXER_MIDI_LEFT] = g_sb16.mixreg[MIXER_MIDI_LEFT] = (dat & 0x0f) << 4; + g_sb16.mixregexp[MIXER_MIDI_RIGHT] = g_sb16.mixreg[MIXER_MIDI_RIGHT] = (dat & 0xf0); + break; + case 0x28: // CD volume(old) + g_sb16.mixregexp[MIXER_CD_LEFT] = g_sb16.mixreg[MIXER_CD_LEFT] = (dat & 0x0f) << 4; + g_sb16.mixregexp[MIXER_CD_RIGHT] = g_sb16.mixreg[MIXER_CD_RIGHT] = (dat & 0xf0); + break; + case 0x2e: // Line volume(old) + g_sb16.mixregexp[MIXER_LINE_LEFT] = g_sb16.mixreg[MIXER_LINE_LEFT] = (dat & 0x0f) << 4; + g_sb16.mixregexp[MIXER_LINE_RIGHT] = g_sb16.mixreg[MIXER_LINE_RIGHT] = (dat & 0xff); + + case 0x80: // Write irq num + ct1741_set_dma_irq(dat & ~0xf0); // reservedビットは0扱い + TRACEOUT(("CT1745 MIXER SET IRQ ID=0x%02x", dat)); + break; + case 0x81: // Write dma num + ct1741_set_dma_ch(dat & ~0x14); // reservedビットは0扱い + TRACEOUT(("CT1745 MIXER SET DMA ID=0x%02x", dat)); + break; + case 0x83: + default: + break; + } + +} +static void IOOUTCALL sb16_o2500_AT(UINT port, REG8 dat) { + if(g_sb16.mixsel==0x80){ + switch (dat) { + case 1: // IRQ2 + // 変換不能 + break; + case 2: // IRQ5 + dat = 8; + break; + case 4: // IRQ7 (IRQ2) + // 変換不能 + break; + case 8: // IRQ10 + dat = 2; + break; + } + }else if(g_sb16.mixsel==0x81){ + switch (dat) { + case 1: // DMA0 + dat = 1; + break; + case 2: // DMA1 + // 変換不能 + break; + case 4: // NONE + // 変換不能 + break; + case 8: // DMA3 + dat = 2; + break; + } + } + sb16_o2500(port, dat); +} + +static REG8 IOINPCALL sb16_i2400(UINT port) { + return g_sb16.mixsel; +} +static REG8 IOINPCALL sb16_i2500(UINT port) { +//printf("mixer port read %x %x¥n",g_sb16.mixreg[g_sb16.mixsel],g_sb16.mixsel); + if (g_sb16.mixsel >= MIXER_VOL_START && g_sb16.mixsel <= MIXER_VOL_END) { + return g_sb16.mixreg[g_sb16.mixsel]; + } + + switch (g_sb16.mixsel) { + case 0x04: + return (g_sb16.mixreg[MIXER_VOC_LEFT] + g_sb16.mixreg[MIXER_VOC_RIGHT]) << 1; + case 0x22: + return (g_sb16.mixreg[MIXER_MASTER_LEFT] + g_sb16.mixreg[MIXER_MASTER_RIGHT]) << 1; + case 0x26: + return (g_sb16.mixreg[MIXER_MIDI_LEFT] + g_sb16.mixreg[MIXER_MIDI_RIGHT]) << 1; + case 0x28: // CD volume(old) + return (g_sb16.mixreg[MIXER_CD_LEFT] + g_sb16.mixreg[MIXER_CD_RIGHT]) << 1; + case 0x2e: // Line volume(old) + return (g_sb16.mixreg[MIXER_LINE_LEFT] + g_sb16.mixreg[MIXER_LINE_RIGHT]) << 1; + case 0x0a: // Mic volume(old) + return g_sb16.mixreg[MIXER_MIC]; + case 0x80: // Read irq num + return g_sb16.dsp_info.dmairq | 0xf0; // reservedビットは1扱い + case 0x81: // Read dma num + return g_sb16.dsp_info.dmachnum | 0x14; // reservedビットは1扱い + case 0x82: // Irq pending(98には不要) diagnose用 他よくわからず + // PC/ATでは割り込み発生元が何かを表している  bit 0x04 MPU, bit 0x02 DMA16ACK, bit 0x01 AVAIL + if(g_sb16.mixreg[0x82] == 0x41)return 0x1; + if(g_sb16.mixreg[0x82] == 0x42)return 0x2; + if(g_sb16.mixreg[0x82] == 0x43)return 0x3; + else return 0x40; + default: + break; + } + return 0; +} +static REG8 IOINPCALL sb16_i2500_AT(UINT port) { + REG8 ret = sb16_i2500(port); + if(g_sb16.mixsel==0x80){ + switch (ret) { + case 1: // IRQ3 + // 変換不能 + break; + case 2: // IRQ10 + ret = 8; + break; + case 4: // IRQ12 + // 変換不能 + break; + case 8: // IRQ5 + ret = 2; + break; + } + }else if(g_sb16.mixsel==0x81){ + switch (ret) { + case 1: // DMA0 + ret = 1; + break; + case 2: // DMA3 + ret = 8; + break; + case 4: // NONE + // 変換不能 + break; + case 8: // NONE + // 変換不能 + break; + } + } + return ret; +} + +void ct1745io_reset(void) +{ + ct1745_mixer_reset(); +} + +void ct1745io_bind(void) +{ + iocore_attachout(0x2400 + g_sb16.base, sb16_o2400); /* Mixer Chip Register Address Port */ + iocore_attachout(0x2500 + g_sb16.base, sb16_o2500); /* Mixer Chip Data Port */ + iocore_attachinp(0x2400 + g_sb16.base, sb16_i2400); /* Mixer Chip Register Address Port */ + iocore_attachinp(0x2500 + g_sb16.base, sb16_i2500); /* Mixer Chip Data Port */ + + // PC/AT互換機テスト + if(np2cfg.sndsb16at){ + iocore_attachout(0x224, sb16_o2400); /* Mixer Chip Register Address Port */ + iocore_attachout(0x225, sb16_o2500_AT); /* Mixer Chip Data Port */ + iocore_attachinp(0x224, sb16_i2400); /* Mixer Chip Register Address Port */ + iocore_attachinp(0x225, sb16_i2500_AT); /* Mixer Chip Data Port */ + } +} +void ct1745io_unbind(void) +{ + iocore_detachout(0x2400 + g_sb16.base); /* Mixer Chip Register Address Port */ + iocore_detachout(0x2500 + g_sb16.base); /* Mixer Chip Data Port */ + iocore_detachinp(0x2400 + g_sb16.base); /* Mixer Chip Register Address Port */ + iocore_detachinp(0x2500 + g_sb16.base); /* Mixer Chip Data Port */ + + // PC/AT互換機テスト + if(np2cfg.sndsb16at){ + iocore_detachout(0x224); /* Mixer Chip Register Address Port */ + iocore_detachout(0x225); /* Mixer Chip Data Port */ + iocore_detachinp(0x224); /* Mixer Chip Register Address Port */ + iocore_detachinp(0x225); /* Mixer Chip Data Port */ + } +} + #endif \ No newline at end of file diff --git a/cbus/ct1745io.h b/cbus/ct1745io.h old mode 100755 new mode 100644 index 43504b7a..96fdfe0a --- a/cbus/ct1745io.h +++ b/cbus/ct1745io.h @@ -1,42 +1,42 @@ -#ifdef __cplusplus -extern "C" { -#endif - -enum { - MIXER_RESET = 0x00, - MIXER_VOL_START = 0x30, - MIXER_MASTER_LEFT = 0x30, - MIXER_MASTER_RIGHT, - MIXER_VOC_LEFT, - MIXER_VOC_RIGHT, - MIXER_MIDI_LEFT, - MIXER_MIDI_RIGHT, - MIXER_CD_LEFT, - MIXER_CD_RIGHT, - MIXER_LINE_LEFT, - MIXER_LINE_RIGHT, - MIXER_MIC, - MIXER_PCSPEAKER, - MIXER_OUT_SW, - MIXER_IN_SW_LEFT, - MIXER_IN_SW_RIGHT, - MIXER_IN_GAIN_LEFT, - MIXER_IN_GAIN_RIGHT, - MIXER_OUT_GAIN_LEFT, - MIXER_OUT_GAIN_RIGHT, - MIXER_AGC, - MIXER_TREBLE_LEFT, - MIXER_TREBLE_RIGHT, - MIXER_BASS_LEFT, - MIXER_BASS_RIGHT, - MIXER_VOL_END = 0x47 -}; - -void ct1745io_reset(void); -void ct1745io_bind(void); -void ct1745io_unbind(void); - - -#ifdef __cplusplus -} -#endif +#ifdef __cplusplus +extern "C" { +#endif + +enum { + MIXER_RESET = 0x00, + MIXER_VOL_START = 0x30, + MIXER_MASTER_LEFT = 0x30, + MIXER_MASTER_RIGHT, + MIXER_VOC_LEFT, + MIXER_VOC_RIGHT, + MIXER_MIDI_LEFT, + MIXER_MIDI_RIGHT, + MIXER_CD_LEFT, + MIXER_CD_RIGHT, + MIXER_LINE_LEFT, + MIXER_LINE_RIGHT, + MIXER_MIC, + MIXER_PCSPEAKER, + MIXER_OUT_SW, + MIXER_IN_SW_LEFT, + MIXER_IN_SW_RIGHT, + MIXER_IN_GAIN_LEFT, + MIXER_IN_GAIN_RIGHT, + MIXER_OUT_GAIN_LEFT, + MIXER_OUT_GAIN_RIGHT, + MIXER_AGC, + MIXER_TREBLE_LEFT, + MIXER_TREBLE_RIGHT, + MIXER_BASS_LEFT, + MIXER_BASS_RIGHT, + MIXER_VOL_END = 0x47 +}; + +void ct1745io_reset(void); +void ct1745io_bind(void); +void ct1745io_unbind(void); + + +#ifdef __cplusplus +} +#endif diff --git a/cbus/gpibio.c b/cbus/gpibio.c old mode 100755 new mode 100644 index c875b38b..3a6f1b57 --- a/cbus/gpibio.c +++ b/cbus/gpibio.c @@ -1,409 +1,409 @@ -/** - * @file gpib.c - * @brief Implementation of PC-9801-06/19/29/29K/29N GP-IB(IEEE-488.1) Interface (uPD7210) - */ - -// 注意:まだ何も実装してないので使えません(GP-IBボードもそれで動く機器も持ってないし・・・) - -#include - -#include -#include -#include -#include -#include -#include -#include - -#if defined(SUPPORT_GPIB) - -#if defined(SUPPORT_GPIB_CONTEC) -#include "Gpibac.h" -#endif - - - _GPIB gpib; - -UINT8 irq2idx(UINT8 irq){ - switch(irq){ - case 3: - return 0x0; - case 10: - return 0x1; - case 12: - return 0x2; - case 13: - return 0x3; - } - return 0x0; -} -UINT8 idx2irq(UINT8 idx){ - switch(idx){ - case 0x0: - return 3; - case 0x1: - return 10; - case 0x2: - return 12; - case 0x3: - return 13; - } - return 3; -} - -UINT32 getGPIBinfoAddr(){ - return (LOADINTELWORD((mem+0x5c2))<<4)+(LOADINTELWORD((mem+0x5c4))); -} - -// ---- - -// Byte Out -static void IOOUTCALL gpib_o1(UINT port, REG8 dat) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ - (void)port; -} -// Data In -static REG8 IOOUTCALL gpib_i1(UINT port) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ -#if defined(SUPPORT_GPIB_CONTEC) - DWORD reg; - GpBoardsts(0x00, ®); - return (REG8)reg; -#else - return 0xff; -#endif -} - -// Interrupt Mask 1 -static void IOOUTCALL gpib_o3(UINT port, REG8 dat) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ - (void)port; -} -// Interrupt Status 1 -static REG8 IOOUTCALL gpib_i3(UINT port) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ -#if defined(SUPPORT_GPIB_CONTEC) - DWORD reg; - GpBoardsts(0x01, ®); - return (REG8)reg; -#else - return 0xff; -#endif -} - -// Interrupt Mask 2 -static void IOOUTCALL gpib_o5(UINT port, REG8 dat) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ - (void)port; -} -// Interrupt Status 2 -static REG8 IOOUTCALL gpib_i5(UINT port) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ -#if defined(SUPPORT_GPIB_CONTEC) - DWORD reg; - GpBoardsts(0x02, ®); - return (REG8)reg; -#else - return 0xff; -#endif -} - -// Serial Poll Mode -static void IOOUTCALL gpib_o7(UINT port, REG8 dat) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ - (void)port; -} -// Serial Poll Status -static REG8 IOOUTCALL gpib_i7(UINT port) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ -#if defined(SUPPORT_GPIB_CONTEC) - DWORD reg; - GpBoardsts(0x03, ®); - return (REG8)reg; -#else - return 0xff; -#endif -} - -// Address Mode -static void IOOUTCALL gpib_o9(UINT port, REG8 dat) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ - (void)port; -} -// Address Status -static REG8 IOOUTCALL gpib_i9(UINT port) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ -#if defined(SUPPORT_GPIB_CONTEC) - DWORD reg; - GpBoardsts(0x04, ®); - return (REG8)reg; -#else - return 0xff; -#endif -} - -// Auxiliary Mode -static void IOOUTCALL gpib_ob(UINT port, REG8 dat) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ - static int cmd = 0; - if(dat==0x11 && cmd==0){ - cmd = 1; - }else if(dat==0x10 && cmd==1){ - UINT32 addr = getGPIBinfoAddr(); - mem[addr+2] = 0x3f; - mem[addr+3] = 0x7f; - cmd = 0; - }else{ - cmd = 0; - } - (void)port; -} -// Command Pass Through -static REG8 IOOUTCALL gpib_ib(UINT port) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ -#if defined(SUPPORT_GPIB_CONTEC) - DWORD reg; - GpBoardsts(0x05, ®); - return (REG8)reg; -#else - return 0xff; -#endif -} - -// Address 0/1 -static void IOOUTCALL gpib_od(UINT port, REG8 dat) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ - (void)port; -} -// Address 0 -static REG8 IOOUTCALL gpib_id(UINT port) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ -#if defined(SUPPORT_GPIB_CONTEC) - DWORD reg; - GpBoardsts(0x06, ®); - return (REG8)reg; -#else - return 0xff; -#endif -} - -// End of String -static void IOOUTCALL gpib_of(UINT port, REG8 dat) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ - (void)port; -} -// Address 1 -static REG8 IOOUTCALL gpib_if(UINT port) { - // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ -#if defined(SUPPORT_GPIB_CONTEC) - DWORD reg; - GpBoardsts(0x07, ®); - return (REG8)reg; -#else - return 0xff; -#endif -} - -// Read Switch -static REG8 IOOUTCALL gpib_i99(UINT port) { - // TODO: Windows対応の uPD7210互換 GP-IBボードから設定を取る -#if defined(SUPPORT_GPIB_CONTEC) - DWORD reg; - GpBoardsts(0x8, ®); - gpib.gpibaddr = (UINT8)reg; - GpBoardsts(0xa, ®); - gpib.mode = (reg==0 ? GPIB_MODE_MASTER : GPIB_MODE_SLAVE); -#endif - return (irq2idx(gpib.irq) << 6)|(gpib.mode << 5)|(gpib.gpibaddr); -} -// Read IFC -static REG8 IOOUTCALL gpib_i9b(UINT port) { - // TODO: Windows対応の uPD7210互換 GP-IBボードからIFCフラグを取ってくる -#if defined(SUPPORT_GPIB_CONTEC) - DWORD reg; - GpBoardsts(0x17, ®); - gpib.ifcflag = (UINT8)reg; -#endif - return (gpib.ifcflag ? 0x00: 0x80)|(gpib_i99(0x99) & ~0x80); -} - -// 拡張 -static void IOOUTCALL gpib_o0(UINT port, REG8 dat) { - (void)port; -} -static REG8 IOOUTCALL gpib_i0(UINT port) { - return 0xff; -} - -static void IOOUTCALL gpib_o2(UINT port, REG8 dat) { - (void)port; -} -static REG8 IOOUTCALL gpib_i2(UINT port) { - return 0xff; -} - -static void IOOUTCALL gpib_o4(UINT port, REG8 dat) { - (void)port; -} -static REG8 IOOUTCALL gpib_i4(UINT port) { - return 0xff; -} - -static void IOOUTCALL gpib_o6(UINT port, REG8 dat) { - (void)port; -} -static REG8 IOOUTCALL gpib_i6(UINT port) { - return 0xff; -} - -static void IOOUTCALL gpib_o8(UINT port, REG8 dat) { - (void)port; -} -static REG8 IOOUTCALL gpib_i8(UINT port) { - return 0xff; -} - -static void IOOUTCALL gpib_oa(UINT port, REG8 dat) { - (void)port; -} -static REG8 IOOUTCALL gpib_ia(UINT port) { - return 0xff; -} - -static void IOOUTCALL gpib_oc(UINT port, REG8 dat) { - (void)port; -} -static REG8 IOOUTCALL gpib_ic(UINT port) { - return 0xff; -} - -static void IOOUTCALL gpib_oe(UINT port, REG8 dat) { - (void)port; -} -static REG8 IOOUTCALL gpib_ie(UINT port) { - return 0xff; -} - - -static const IOOUT gpib_o[] = { - gpib_o0, gpib_o1, gpib_o2, gpib_o3, gpib_o4, gpib_o5, gpib_o6, gpib_o7, gpib_o8, gpib_o9, gpib_oa, gpib_ob, gpib_oc, gpib_od, gpib_oe, gpib_of}; - -static const IOINP gpib_i[] = { - gpib_i0, gpib_i1, gpib_i2, gpib_i3, gpib_i4, gpib_i5, gpib_i6, gpib_i7, gpib_i8, gpib_i9, gpib_ia, gpib_ib, gpib_ic, gpib_id, gpib_ie, gpib_if}; - -// NP2起動時の処理 -void gpibio_initialize(void) -{ -#if defined(SUPPORT_GPIB_CONTEC) - GpExit(); - GpIni(); - GpTimeout(10000); -#endif -} -// NP2終了時の処理 -void gpibio_shutdown(void) -{ -#if defined(SUPPORT_GPIB_CONTEC) - DWORD master; - DWORD cmd[32]; - if(GpBoardsts(0x0a, &master) == 80) return; - if(master == 0){ - cmd[0] = 2; - cmd[1] = 0x3f; - cmd[2] = 0x5f; - GpComand(cmd); - } - GpResetren(); - GpExit(); -#endif -} - -void gpibio_reset(const NP2CFG *pConfig) { - - OEMCHAR path[MAX_PATH]; - FILEH fh; - OEMCHAR tmpbiosname[16]; - - _tcscpy(tmpbiosname, OEMTEXT("gpib.rom")); - getbiospath(path, tmpbiosname, NELEMENTS(path)); - fh = file_open_rb(path); - - // GP-IB BIOS 拡張ROM(D4000h - D5FFFh) 有効? - if((np2cfg.memsw[3] & 0x20) == 0){ - gpib.enable = 0; - return; - } - gpib.enable = 1; - gpib.irq = np2cfg.gpibirq; - gpib.mode = np2cfg.gpibmode; - gpib.gpibaddr = np2cfg.gpibaddr; - gpib.exiobase = np2cfg.gpibexio; - - if (fh != FILEH_INVALID) { - // GP-IB BIOS - if (file_read(fh, mem + 0x0d4000, 0x2000) == 0x2000) { - CPU_RAM_D000 &= ~(0x3 << 4); - TRACEOUT(("load gpib.rom")); - }else{ - //CopyMemory(mem + 0x0d4000, gpibbios, sizeof(gpibbios)); - //TRACEOUT(("use simulate gpib.rom")); - gpib.enable = 0; - return; - } - file_close(fh); - }else{ - //CopyMemory(mem + 0x0d4000, gpibbios, sizeof(gpibbios)); - //TRACEOUT(("use simulate gpib.rom")); - gpib.enable = 0; - return; - } - - (void)pConfig; -} - -void gpibio_bind(void) { - - int i; - - // GP-IB 有効? - if(!gpib.enable){ - return; - } - - // 標準I/Oポート設定 - for(i=0;i<16;i++){ - if(gpib_o[i]){ - iocore_attachout(0xC0 + i, gpib_o[i]); - } - if(gpib_i[i]){ - iocore_attachinp(0xC0 + i, gpib_i[i]); - } - } - iocore_attachinp(0x99, gpib_i99); - iocore_attachinp(0x9b, gpib_i9b); - - // カスタムI/Oポートベースアドレス - if(gpib.exiobase != 0){ - for(i=0;i<16;i++){ - if(gpib_o[i]){ - iocore_attachout(gpib.exiobase + i, gpib_o[i]); - } - if(gpib_i[i]){ - iocore_attachinp(gpib.exiobase + i, gpib_i[i]); - } - } - } - - //// AZI-4301P - //for(i=0;i<16;i++){ - // if(gpib_o[i]){ - // iocore_attachout(0xD0 + i, gpib_o[i]); - // } - // if(gpib_i[i]){ - // iocore_attachinp(0xD0 + i, gpib_i[i]); - // } - //} - -} -#endif - +/** + * @file gpib.c + * @brief Implementation of PC-9801-06/19/29/29K/29N GP-IB(IEEE-488.1) Interface (uPD7210) + */ + +// 注意:まだ何も実装してないので使えません(GP-IBボードもそれで動く機器も持ってないし・・・) + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if defined(SUPPORT_GPIB) + +#if defined(SUPPORT_GPIB_CONTEC) +#include "Gpibac.h" +#endif + + + _GPIB gpib; + +UINT8 irq2idx(UINT8 irq){ + switch(irq){ + case 3: + return 0x0; + case 10: + return 0x1; + case 12: + return 0x2; + case 13: + return 0x3; + } + return 0x0; +} +UINT8 idx2irq(UINT8 idx){ + switch(idx){ + case 0x0: + return 3; + case 0x1: + return 10; + case 0x2: + return 12; + case 0x3: + return 13; + } + return 3; +} + +UINT32 getGPIBinfoAddr(){ + return (LOADINTELWORD((mem+0x5c2))<<4)+(LOADINTELWORD((mem+0x5c4))); +} + +// ---- + +// Byte Out +static void IOOUTCALL gpib_o1(UINT port, REG8 dat) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ + (void)port; +} +// Data In +static REG8 IOOUTCALL gpib_i1(UINT port) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ +#if defined(SUPPORT_GPIB_CONTEC) + DWORD reg; + GpBoardsts(0x00, ®); + return (REG8)reg; +#else + return 0xff; +#endif +} + +// Interrupt Mask 1 +static void IOOUTCALL gpib_o3(UINT port, REG8 dat) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ + (void)port; +} +// Interrupt Status 1 +static REG8 IOOUTCALL gpib_i3(UINT port) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ +#if defined(SUPPORT_GPIB_CONTEC) + DWORD reg; + GpBoardsts(0x01, ®); + return (REG8)reg; +#else + return 0xff; +#endif +} + +// Interrupt Mask 2 +static void IOOUTCALL gpib_o5(UINT port, REG8 dat) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ + (void)port; +} +// Interrupt Status 2 +static REG8 IOOUTCALL gpib_i5(UINT port) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ +#if defined(SUPPORT_GPIB_CONTEC) + DWORD reg; + GpBoardsts(0x02, ®); + return (REG8)reg; +#else + return 0xff; +#endif +} + +// Serial Poll Mode +static void IOOUTCALL gpib_o7(UINT port, REG8 dat) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ + (void)port; +} +// Serial Poll Status +static REG8 IOOUTCALL gpib_i7(UINT port) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ +#if defined(SUPPORT_GPIB_CONTEC) + DWORD reg; + GpBoardsts(0x03, ®); + return (REG8)reg; +#else + return 0xff; +#endif +} + +// Address Mode +static void IOOUTCALL gpib_o9(UINT port, REG8 dat) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ + (void)port; +} +// Address Status +static REG8 IOOUTCALL gpib_i9(UINT port) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ +#if defined(SUPPORT_GPIB_CONTEC) + DWORD reg; + GpBoardsts(0x04, ®); + return (REG8)reg; +#else + return 0xff; +#endif +} + +// Auxiliary Mode +static void IOOUTCALL gpib_ob(UINT port, REG8 dat) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ + static int cmd = 0; + if(dat==0x11 && cmd==0){ + cmd = 1; + }else if(dat==0x10 && cmd==1){ + UINT32 addr = getGPIBinfoAddr(); + mem[addr+2] = 0x3f; + mem[addr+3] = 0x7f; + cmd = 0; + }else{ + cmd = 0; + } + (void)port; +} +// Command Pass Through +static REG8 IOOUTCALL gpib_ib(UINT port) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ +#if defined(SUPPORT_GPIB_CONTEC) + DWORD reg; + GpBoardsts(0x05, ®); + return (REG8)reg; +#else + return 0xff; +#endif +} + +// Address 0/1 +static void IOOUTCALL gpib_od(UINT port, REG8 dat) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ + (void)port; +} +// Address 0 +static REG8 IOOUTCALL gpib_id(UINT port) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ +#if defined(SUPPORT_GPIB_CONTEC) + DWORD reg; + GpBoardsts(0x06, ®); + return (REG8)reg; +#else + return 0xff; +#endif +} + +// End of String +static void IOOUTCALL gpib_of(UINT port, REG8 dat) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ + (void)port; +} +// Address 1 +static REG8 IOOUTCALL gpib_if(UINT port) { + // TODO: Windows対応の uPD7210互換 GP-IBボードに丸投げ +#if defined(SUPPORT_GPIB_CONTEC) + DWORD reg; + GpBoardsts(0x07, ®); + return (REG8)reg; +#else + return 0xff; +#endif +} + +// Read Switch +static REG8 IOOUTCALL gpib_i99(UINT port) { + // TODO: Windows対応の uPD7210互換 GP-IBボードから設定を取る +#if defined(SUPPORT_GPIB_CONTEC) + DWORD reg; + GpBoardsts(0x8, ®); + gpib.gpibaddr = (UINT8)reg; + GpBoardsts(0xa, ®); + gpib.mode = (reg==0 ? GPIB_MODE_MASTER : GPIB_MODE_SLAVE); +#endif + return (irq2idx(gpib.irq) << 6)|(gpib.mode << 5)|(gpib.gpibaddr); +} +// Read IFC +static REG8 IOOUTCALL gpib_i9b(UINT port) { + // TODO: Windows対応の uPD7210互換 GP-IBボードからIFCフラグを取ってくる +#if defined(SUPPORT_GPIB_CONTEC) + DWORD reg; + GpBoardsts(0x17, ®); + gpib.ifcflag = (UINT8)reg; +#endif + return (gpib.ifcflag ? 0x00: 0x80)|(gpib_i99(0x99) & ~0x80); +} + +// 拡張 +static void IOOUTCALL gpib_o0(UINT port, REG8 dat) { + (void)port; +} +static REG8 IOOUTCALL gpib_i0(UINT port) { + return 0xff; +} + +static void IOOUTCALL gpib_o2(UINT port, REG8 dat) { + (void)port; +} +static REG8 IOOUTCALL gpib_i2(UINT port) { + return 0xff; +} + +static void IOOUTCALL gpib_o4(UINT port, REG8 dat) { + (void)port; +} +static REG8 IOOUTCALL gpib_i4(UINT port) { + return 0xff; +} + +static void IOOUTCALL gpib_o6(UINT port, REG8 dat) { + (void)port; +} +static REG8 IOOUTCALL gpib_i6(UINT port) { + return 0xff; +} + +static void IOOUTCALL gpib_o8(UINT port, REG8 dat) { + (void)port; +} +static REG8 IOOUTCALL gpib_i8(UINT port) { + return 0xff; +} + +static void IOOUTCALL gpib_oa(UINT port, REG8 dat) { + (void)port; +} +static REG8 IOOUTCALL gpib_ia(UINT port) { + return 0xff; +} + +static void IOOUTCALL gpib_oc(UINT port, REG8 dat) { + (void)port; +} +static REG8 IOOUTCALL gpib_ic(UINT port) { + return 0xff; +} + +static void IOOUTCALL gpib_oe(UINT port, REG8 dat) { + (void)port; +} +static REG8 IOOUTCALL gpib_ie(UINT port) { + return 0xff; +} + + +static const IOOUT gpib_o[] = { + gpib_o0, gpib_o1, gpib_o2, gpib_o3, gpib_o4, gpib_o5, gpib_o6, gpib_o7, gpib_o8, gpib_o9, gpib_oa, gpib_ob, gpib_oc, gpib_od, gpib_oe, gpib_of}; + +static const IOINP gpib_i[] = { + gpib_i0, gpib_i1, gpib_i2, gpib_i3, gpib_i4, gpib_i5, gpib_i6, gpib_i7, gpib_i8, gpib_i9, gpib_ia, gpib_ib, gpib_ic, gpib_id, gpib_ie, gpib_if}; + +// NP2起動時の処理 +void gpibio_initialize(void) +{ +#if defined(SUPPORT_GPIB_CONTEC) + GpExit(); + GpIni(); + GpTimeout(10000); +#endif +} +// NP2終了時の処理 +void gpibio_shutdown(void) +{ +#if defined(SUPPORT_GPIB_CONTEC) + DWORD master; + DWORD cmd[32]; + if(GpBoardsts(0x0a, &master) == 80) return; + if(master == 0){ + cmd[0] = 2; + cmd[1] = 0x3f; + cmd[2] = 0x5f; + GpComand(cmd); + } + GpResetren(); + GpExit(); +#endif +} + +void gpibio_reset(const NP2CFG *pConfig) { + + OEMCHAR path[MAX_PATH]; + FILEH fh; + OEMCHAR tmpbiosname[16]; + + _tcscpy(tmpbiosname, OEMTEXT("gpib.rom")); + getbiospath(path, tmpbiosname, NELEMENTS(path)); + fh = file_open_rb(path); + + // GP-IB BIOS 拡張ROM(D4000h - D5FFFh) 有効? + if((np2cfg.memsw[3] & 0x20) == 0){ + gpib.enable = 0; + return; + } + gpib.enable = 1; + gpib.irq = np2cfg.gpibirq; + gpib.mode = np2cfg.gpibmode; + gpib.gpibaddr = np2cfg.gpibaddr; + gpib.exiobase = np2cfg.gpibexio; + + if (fh != FILEH_INVALID) { + // GP-IB BIOS + if (file_read(fh, mem + 0x0d4000, 0x2000) == 0x2000) { + CPU_RAM_D000 &= ~(0x3 << 4); + TRACEOUT(("load gpib.rom")); + }else{ + //CopyMemory(mem + 0x0d4000, gpibbios, sizeof(gpibbios)); + //TRACEOUT(("use simulate gpib.rom")); + gpib.enable = 0; + return; + } + file_close(fh); + }else{ + //CopyMemory(mem + 0x0d4000, gpibbios, sizeof(gpibbios)); + //TRACEOUT(("use simulate gpib.rom")); + gpib.enable = 0; + return; + } + + (void)pConfig; +} + +void gpibio_bind(void) { + + int i; + + // GP-IB 有効? + if(!gpib.enable){ + return; + } + + // 標準I/Oポート設定 + for(i=0;i<16;i++){ + if(gpib_o[i]){ + iocore_attachout(0xC0 + i, gpib_o[i]); + } + if(gpib_i[i]){ + iocore_attachinp(0xC0 + i, gpib_i[i]); + } + } + iocore_attachinp(0x99, gpib_i99); + iocore_attachinp(0x9b, gpib_i9b); + + // カスタムI/Oポートベースアドレス + if(gpib.exiobase != 0){ + for(i=0;i<16;i++){ + if(gpib_o[i]){ + iocore_attachout(gpib.exiobase + i, gpib_o[i]); + } + if(gpib_i[i]){ + iocore_attachinp(gpib.exiobase + i, gpib_i[i]); + } + } + } + + //// AZI-4301P + //for(i=0;i<16;i++){ + // if(gpib_o[i]){ + // iocore_attachout(0xD0 + i, gpib_o[i]); + // } + // if(gpib_i[i]){ + // iocore_attachinp(0xD0 + i, gpib_i[i]); + // } + //} + +} +#endif + diff --git a/cbus/gpibio.h b/cbus/gpibio.h old mode 100755 new mode 100644 index 471caca3..cfd21e32 --- a/cbus/gpibio.h +++ b/cbus/gpibio.h @@ -1,38 +1,38 @@ - -#if defined(SUPPORT_GPIB) - -enum { - GPIB_MODE_MASTER = 1, - GPIB_MODE_SLAVE = 0, -}; - -typedef struct { - UINT8 enable; - UINT8 irq; // 割り込み - UINT8 mode; // マスタ=1, スレーブ=0 - UINT8 gpibaddr; // GP-IBアドレス(0x0〜0x1F) - UINT8 ifcflag; // IFC# 1=アクティブ, 0=非アクティブ - - UINT16 exiobase; -} _GPIB, *GPIB; - -#ifdef __cplusplus -extern "C" { -#endif - -extern _GPIB gpib; - -void gpibint(NEVENTITEM item); - -void gpibio_initialize(void); -void gpibio_shutdown(void); - -void gpibio_reset(const NP2CFG *pConfig); -void gpibio_bind(void); - -#ifdef __cplusplus -} -#endif - -#endif - + +#if defined(SUPPORT_GPIB) + +enum { + GPIB_MODE_MASTER = 1, + GPIB_MODE_SLAVE = 0, +}; + +typedef struct { + UINT8 enable; + UINT8 irq; // 割り込み + UINT8 mode; // マスタ=1, スレーブ=0 + UINT8 gpibaddr; // GP-IBアドレス(0x0〜0x1F) + UINT8 ifcflag; // IFC# 1=アクティブ, 0=非アクティブ + + UINT16 exiobase; +} _GPIB, *GPIB; + +#ifdef __cplusplus +extern "C" { +#endif + +extern _GPIB gpib; + +void gpibint(NEVENTITEM item); + +void gpibio_initialize(void); +void gpibio_shutdown(void); + +void gpibio_reset(const NP2CFG *pConfig); +void gpibio_bind(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/cbus/ideio.c b/cbus/ideio.c old mode 100755 new mode 100644 index f3780179..5c81e916 --- a/cbus/ideio.c +++ b/cbus/ideio.c @@ -1,2102 +1,2102 @@ -#include - -#if 1 -#undef TRACEOUT -#define TRACEOUT(s) (void)(s) -//static void trace_fmt_ex(const char *fmt, ...) -//{ -// char stmp[2048]; -// va_list ap; -// va_start(ap, fmt); -// vsprintf(stmp, fmt, ap); -// strcat(stmp, "¥n"); -// va_end(ap); -// OutputDebugStringA(stmp); -//} -//#define TRACEOUT(s) trace_fmt_ex s -#endif /* 1 */ - -// winでidentifyまでは取得に行くんだけどな…ってAnex86も同じか - -#if defined(SUPPORT_IDEIO) - -#include -#include -#include -#include -#include -#include -#include -#include -#include "idebios.res" -#include -#include -#include - - IDEIO ideio; - -static IDEDEV getidedev(void) { - - UINT bank; - - bank = ideio.bank[1] & 0x7f; - if (bank < 2) { - return(ideio.dev + bank); - } - else { - return(NULL); - } -} - -static IDEDRV getidedrv(void) { - - IDEDEV dev; - IDEDRV drv; - - dev = getidedev(); - if (dev) { - drv = dev->drv + dev->drivesel; - if (drv->device != IDETYPE_NONE) { - return(drv); - } - } - return(NULL); -} - -static const char serial[] = "824919341192 "; -static const char firm[] = "A5U.1200"; -static const char model[] = "QUANTUM FIREBALL CR "; -static const char model48[] = "NYANTUM YARNBALL CR "; - -static const char cdrom_serial[] = "1.0 "; -static const char cdrom_firm[] = " "; -static const char cdrom_model[] = "NEC CD-ROM DRIVE:98 "; - -static BRESULT setidentify(IDEDRV drv) { - - SXSIDEV sxsi; - UINT16 tmp[256]; - UINT8 *p; - UINT i; - FILELEN size; - - sxsi = sxsi_getptr(drv->sxsidrv); - if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY) && drv->device != IDETYPE_CDROM)) { - return(FAILURE); - } - - ZeroMemory(tmp, sizeof(tmp)); - // とりあえず使ってる部分だけ - if (drv->device == IDETYPE_HDD) { - tmp[0] = 0x0040; // non removable device - tmp[1] = sxsi->cylinders; - tmp[3] = sxsi->surfaces; - tmp[4] = sxsi->sectors * 512; - tmp[6] = sxsi->sectors; - for (i=0; i<10; i++) { - tmp[10+i] = (serial[i*2] << 8) + serial[i*2+1]; - } - tmp[10+2] = '0'+drv->sxsidrv; // シリアル番号はユニークにしておかないと駄目っぽい - tmp[22] = 4; - for (i=0; i<4; i++) { - tmp[23+i] = (firm[i*2] << 8) + firm[i*2+1]; - } - for (i=0; i<20; i++) { - tmp[27+i] = (model[i*2] << 8) + model[i*2+1]; - } -#if IDEIO_MULTIPLE_MAX > 0 - tmp[47] = 0x8000 | IDEIO_MULTIPLE_MAX; // multiple -#endif - tmp[49] = 0x0200; // support LBA - tmp[51] = 0x0278; - tmp[53] = 0x0003; - size = (FILELEN)sxsi->cylinders * sxsi->surfaces * sxsi->sectors; - tmp[54] = (UINT16)(size / drv->surfaces / drv->sectors);//sxsi->cylinders; - tmp[55] = drv->surfaces;//sxsi->surfaces; - tmp[56] = drv->sectors;//sxsi->sectors; - size = (FILELEN)tmp[54] * tmp[55] * tmp[56]; - tmp[57] = (UINT16)size; - tmp[58] = (UINT16)(size >> 16); -#if IDEIO_MULTIPLE_MAX > 0 - tmp[59] = 0x0100 | drv->mulmode; // current multiple mode -#endif - tmp[60] = (UINT16)size; - tmp[61] = (UINT16)(size >> 16); - tmp[63] = 0x0000; // no support multiword DMA - tmp[64] = 0x0003; // device supports PIO mode 3, 4 - - tmp[81] = 0; - tmp[82] = 0x4200; // support NOP, DEVICE RESET and Write Cache - -#if defined(SUPPORT_IDEIO_48BIT) - if(sxsi->totals > 65535*16*255){ - // 48-bit LBA - FILELEN tmpCyl = (UINT32)(sxsi->totals / 255 / 255); - tmp[80] = 0x007e; // support ATA-1 to 6 - tmp[81] = 0; - tmp[82] = 0x0200; // support DEVICE RESET - tmp[83] = 0x4400; // 48-bit Address feature set supported - tmp[86] = 0x4400; // 48-bit Address feature set supported - tmp[100] = (UINT16)(sxsi->totals); // Maximum user LBA for 48-bit Address feature set 1 - tmp[101] = (UINT16)(sxsi->totals >> 16); // Maximum user LBA for 48-bit Address feature set 2 - tmp[102] = (UINT16)(sxsi->totals >> 32); // Maximum user LBA for 48-bit Address feature set 3 - tmp[103] = (UINT16)(sxsi->totals >> 48); // Maximum user LBA for 48-bit Address feature set 4 - if(tmp[102] || tmp[103] || (tmp[101] & 0xf000)){ - tmp[60] = (UINT16)0xffff; - tmp[61] = (UINT16)0xfff; - }else{ - tmp[60] = tmp[100]; - tmp[61] = tmp[101]; - } - tmp[54] = (UINT16)(tmpCyl < 0xffff ? tmpCyl : 0xffff); - tmp[55] = 255; - tmp[56] = 255; - size = (FILELEN)tmp[54] * tmp[55] * tmp[56]; - tmp[57] = (UINT16)size; - tmp[58] = (UINT16)(size >> 16); - for (i=0; i<20; i++) { - tmp[27+i] = (model48[i*2] << 8) + model48[i*2+1]; - } - } -#endif - { - tmp[80] = 0x003e; // support ATA-1 to 5 - } - } - else if (drv->device == IDETYPE_CDROM) { - tmp[0] = 0x8580; // ATAPI,CD-ROM,removable,12bytes PACKET - for (i=0; i<10; i++) { - tmp[10+i] = (cdrom_serial[i*2] << 8) + cdrom_serial[i*2+1]; - } - tmp[10+2] = '0'+drv->sxsidrv; // シリアル番号はユニークにしておかないと駄目っぽい - for (i=0; i<4; i++) { - tmp[23+i] = (cdrom_firm[i*2] << 8) + cdrom_firm[i*2+1]; - } - for (i=0; i<20; i++) { - tmp[27+i] = (cdrom_model[i*2] << 8) + cdrom_model[i*2+1]; - } - tmp[49] = 0x0200; // support LBA - tmp[51] = 0x0278; - tmp[53] = 0x0003; - tmp[63] = 0x0000; // no support multiword DMA - tmp[64] = 0x0003; // device supports PIO mode 3, 4 - tmp[80] = 0x003e; // support ATA-1 to 5 - tmp[82] = 0x0214; // support PACKET/DEVICE RESET - tmp[126] = 0x0000; // ATAPI byte count - } - if (drv->sxsidrv & 0x1){ - // slave - tmp[93] = 0x4b00; - }else{ - // master - tmp[93] = 0x407b; - } - - p = drv->buf; - for (i=0; i<256; i++) { - p[0] = (UINT8)tmp[i]; - p[1] = (UINT8)(tmp[i] >> 8); - p += 2; - } - drv->bufdir = IDEDIR_IN; - drv->buftc = IDETC_TRANSFEREND; - drv->bufpos = 0; - drv->bufsize = 512; - return(SUCCESS); -} - -static void setintr(IDEDRV drv) { - - if (!(drv->ctrl & IDECTRL_NIEN)) { - TRACEOUT(("ideio: setintr()")); - ideio.bank[0] = ideio.bank[1] | 0x80; // ???? - pic_setirq(IDE_IRQ); - if (ideio.bios != IDETC_BIOS) { - mem[MEMB_DISK_INTH] |= 0x01; // エミュレーションIDE BIOSなら代理で立てる - } - } -} - -// 割り込み後にBSYを解除し、DRQをセットする(コマンド継続中など) -void ideioint(NEVENTITEM item) { - - IDEDRV drv; - IDEDEV dev; - - //ドライブがあるか - dev = getidedev(); - if (dev == NULL) { - return; - } - - drv = getidedrv(); - if (drv == NULL) { - return; - } - - //BUSY解除 - if(dev->drv[0].status != 0xFF){ - dev->drv[0].status |= IDESTAT_DRQ; - dev->drv[0].status &= ~IDESTAT_BSY; - } - if(dev->drv[1].status != 0xFF){ - dev->drv[1].status |= IDESTAT_DRQ; - dev->drv[1].status &= ~IDESTAT_BSY; - } - - //割り込み実行//(割り込みはドライブ毎には指定できない仕様) - if(!(dev->drv[0].ctrl & IDECTRL_NIEN) || !(dev->drv[1].ctrl & IDECTRL_NIEN)){ - TRACEOUT(("ideio: run setdintr()")); - pic_setirq(IDE_IRQ); - if (ideio.bios != IDETC_BIOS) { - mem[MEMB_DISK_INTH] |= 0x01; // エミュレーションIDE BIOSなら代理で立てる - } - } - (void)item; -} -// 割り込み後にBSYを解除し、DRQも解除する(コマンド終了時など) -void ideioint2(NEVENTITEM item) { - - IDEDRV drv; - IDEDEV dev; - - //ドライブがあるか - dev = getidedev(); - if (dev == NULL) { - return; - } - - drv = getidedrv(); - if (drv == NULL) { - return; - } - - //BUSY解除 - if(dev->drv[0].status != 0xFF){ - dev->drv[0].status &= ~IDESTAT_DRQ; - dev->drv[0].status &= ~IDESTAT_BSY; - } - if(dev->drv[1].status != 0xFF){ - dev->drv[1].status &= ~IDESTAT_DRQ; - dev->drv[1].status &= ~IDESTAT_BSY; - } - - //割り込み実行//(割り込みはドライブ毎には指定できない仕様) - if(!(dev->drv[0].ctrl & IDECTRL_NIEN) || !(dev->drv[1].ctrl & IDECTRL_NIEN)){ - TRACEOUT(("ideio: run setdintr()")); - pic_setirq(IDE_IRQ); - if (ideio.bios != IDETC_BIOS) { - mem[MEMB_DISK_INTH] |= 0x01; // エミュレーションIDE BIOSなら代理で立てる - } - } - (void)item; -} - -// 遅延付き割り込み -static void setdintr(IDEDRV drv, UINT8 errno, UINT8 status, UINT32 delay) { - - if (!(drv->ctrl & IDECTRL_NIEN)) { - //drv->status |= IDESTAT_BSY; - ideio.bank[0] = ideio.bank[1] | 0x80; // ???? - TRACEOUT(("ideio: reg setdintr()")); - - //// 指定した時間遅延(マイクロ秒) - //nevent_set(NEVENT_SASIIO, (pccore.realclock / 1000 / 1000) * delay, ideioint, NEVENT_ABSOLUTE); - - // 指定した時間遅延(クロック数) - if (delay == 0) - { - ideioint(&g_nevent.item[NEVENT_SASIIO]); - } - else - { - nevent_set(NEVENT_SASIIO, delay, ideioint, NEVENT_ABSOLUTE); - } - } -} -static void setdintr2(IDEDRV drv, UINT8 errno, UINT8 status, UINT32 delay) { - - if (!(drv->ctrl & IDECTRL_NIEN)) { - //drv->status |= IDESTAT_BSY; - ideio.bank[0] = ideio.bank[1] | 0x80; // ???? - TRACEOUT(("ideio: reg setdintr()")); - - //// 指定した時間遅延(マイクロ秒) - //nevent_set(NEVENT_SASIIO, (pccore.realclock / 1000 / 1000) * delay, ideioint, NEVENT_ABSOLUTE); - - // 指定した時間遅延(クロック数) - if (delay == 0) - { - ideioint2(&g_nevent.item[NEVENT_SASIIO]); - } - else - { - nevent_set(NEVENT_SASIIO, delay, ideioint2, NEVENT_ABSOLUTE); - } - } -} - - -static void cmdabort(IDEDRV drv) { - - TRACEOUT(("ideio: cmdabort()")); - drv->status = IDESTAT_DRDY | IDESTAT_ERR; - drv->error = IDEERR_ABRT; -#if defined(SUPPORT_IDEIO_48BIT) - drv->lba48mode = 0; -#endif - setintr(drv); -} - -static void drvreset(IDEDRV drv) { - - if (drv->device == IDETYPE_CDROM) { - drv->hd = 0x10; - drv->sc = 0x01; - drv->sn = 0x01; - drv->cy = 0xeb14; - drv->status = 0; - } - else { - drv->hd = 0x00; - drv->sc = 0x01; - drv->sn = 0x01; - drv->cy = 0x0000; -#if defined(SUPPORT_IDEIO_48BIT) - drv->lba48[1] = drv->lba48[2] = drv->lba48[3] = drv->lba48[4] = drv->lba48[5] = 0; - drv->lba48[0] = 1; - drv->lba48sc = 0x0001; -#endif - //drv->status = IDESTAT_DRDY; - drv->status = IDESTAT_DRDY | IDESTAT_DSC; - } -} - -static void panic(const char *str, ...) { - - char buf[2048]; - va_list ap; - - va_start(ap, str); - vsnprintf(buf, sizeof(buf), str, ap); - va_end(ap); - - msgbox("ide_panic", buf); - exit(1); -} - - -// ---- - -static void incsec(IDEDRV drv) { - - if (!(drv->dr & IDEDEV_LBA)) { - drv->sn++; - if (drv->sn <= drv->sectors && drv->sn!=0) { - return; - } - drv->sn = 1; - drv->hd++; - if (drv->hd < drv->surfaces) { - return; - } - drv->hd = 0; - drv->cy++; - } - else { -#if defined(SUPPORT_IDEIO_48BIT) - // 48-bit Address feature set - { - int i; - for(i=0;i<6;i++){ - drv->lba48[i]++; - if (drv->lba48[i]) { - break; - } - } - } -#endif - drv->sn++; - if (drv->sn) { - return; - } - drv->cy++; - if (drv->cy) { - return; - } - drv->hd++; - } -} - -void ideio_setcursec(FILEPOS pos) { - IDEDRV drv; -#if defined(SUPPORT_IDEIO_48BIT) - int shift = 0; - int i; -#endif - drv = getidedrv(); - if (drv) { - if (!(drv->dr & IDEDEV_LBA)) { - drv->sn = (pos % drv->sectors) + 1; - pos /= drv->sectors; - drv->hd = (pos % drv->surfaces); - pos /= drv->surfaces; - drv->cy = pos & 0xffff; - } - else { - drv->sn = (pos & 0xff); - drv->cy = ((pos >> 8) & 0xffff); - drv->hd = ((pos >> 24) & 0xff); - -#if defined(SUPPORT_IDEIO_48BIT) - // 48-bit Address feature set - for(i=0;i<6;i++){ - drv->lba48[i] = (pos >> shift) & 0xff; - shift += 8; - } -#endif - } - } -} -static FILEPOS getcursec(const IDEDRV drv) { - - FILEPOS ret; - -#if defined(SUPPORT_IDEIO_48BIT) - if(drv->lba48mode){ - int i; - ret = 0; - for(i=0;i<6;i++){ - ret <<= 8; - ret |= drv->lba48[5-i]; - } - }else -#endif - { - if (!(drv->dr & IDEDEV_LBA)) { - ret = drv->cy; - ret *= drv->surfaces; - ret += drv->hd; - ret *= drv->sectors; - ret += (drv->sn - 1); - } - else { - ret = drv->sn; - ret |= (drv->cy << 8); - ret |= (drv->hd << 24); - } - } - return(ret); -} - -static void readsec(IDEDRV drv) { - - FILEPOS sec; - - if (drv->device != IDETYPE_HDD) { - goto read_err; - } - sec = getcursec(drv); - //TRACEOUT(("readsec->drv %d sec %x cnt %d thr %d", - // drv->sxsidrv, sec, drv->mulcnt, drv->multhr)); - if (sxsi_read(drv->sxsidrv, sec, drv->buf, 512)) { - TRACEOUT(("read error!")); - goto read_err; - } - drv->bufdir = IDEDIR_IN; - drv->buftc = IDETC_TRANSFEREND; - drv->bufpos = 0; - drv->bufsize = 512; - // READはI/Oポートで読み取るデータが準備できたら割り込み - if (1) { - drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; - drv->error = 0; - if(drv->mulcnt == 0){ // READ MULTIPLEではブロック単位で割り込み - if(ideio.rwait > 0){ - drv->status |= IDESTAT_BSY; - drv->status &= ~IDESTAT_DRQ; - setdintr(drv, 0, 0, ideio.rwait); - }else{ - setintr(drv); - } - //setintr(drv); - } - } - drv->mulcnt++; - if(drv->mulcnt >= drv->multhr){ - drv->mulcnt = 0; - } - return; - -read_err: - cmdabort(drv); -} - -static void writeinit(IDEDRV drv) { - if (drv->device == IDETYPE_NONE) { - goto write_err; - } - - drv->bufdir = IDEDIR_OUT; - drv->buftc = IDETC_TRANSFEREND; - drv->bufpos = 0; - drv->bufsize = 512; - - if (1) { - drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; - drv->error = 0; - } - return; - -write_err: - cmdabort(drv); -} - -static void writesec(IDEDRV drv) { - - if (drv->device == IDETYPE_NONE) { - goto write_err; - } - - drv->bufdir = IDEDIR_OUT; - drv->buftc = IDETC_TRANSFEREND; - drv->bufpos = 0; - drv->bufsize = 512; - - // WRITEはデータ書き込みが完了したら割り込み - drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; - drv->error = 0; - drv->mulcnt++; - if(drv->mulcnt >= drv->multhr){ - drv->mulcnt = 0; - } - if(drv->mulcnt == 0){ // WRITE MULTIPLEの時はブロック書き込み完了時に割り込み -> 最後の割り込みはideio_w16()内に存在 - if(ideio.wwait > 0){ - drv->status |= IDESTAT_BSY; - drv->status &= ~IDESTAT_DRQ; - setdintr(drv, 0, 0, ideio.wwait); - }else{ - setintr(drv); - } - } - return; - -write_err: - cmdabort(drv); -} - - -// ---- - -static void IOOUTCALL ideio_o430(UINT port, REG8 dat) { - - TRACEOUT(("ideio setbank%d %.2x [%.4x:%.8x]", - (port >> 1) & 1, dat, CPU_CS, CPU_EIP)); -#if defined(NP2_WIN) - atapi_dataread_asyncwait(INFINITE); -#endif - - if (!(dat & 0x80)) { - //char buf[100] = {0}; - if ((port >> 1) & 1) { - // 432h - ideio.bank[(port >> 1) & 1] = dat & 0x71; - } - else { - // 430h - ideio.bank[(port >> 1) & 1] = dat & 0x71; - } - //sprintf(buf, "0x%x¥n", dat); - //OutputDebugStringA(buf); - } - - // XXX: WORKAROUND for WinNT4.0 正常な接続フラグに書き戻す - if(mem[0x05bb]){ - mem[0x05ba] = mem[0x05bb]; - mem[0x05bb] = 0; - } -} - -static REG8 IOINPCALL ideio_i430(UINT port) { - - UINT bank; - REG8 ret; - - bank = (port >> 1) & 1; - ret = ideio.bank[bank]; - if ((port >> 1) & 1) { - // 432h - } - else { - // 430h - int compmode = (sxsi_getdevtype(0)!=SXSIDEV_CDROM && sxsi_getdevtype(1)!=SXSIDEV_CDROM && sxsi_getdevtype(2)==SXSIDEV_CDROM && sxsi_getdevtype(3)!=SXSIDEV_CDROM); // 旧機種互換モード? - IDEDEV dev; - dev = getidedev(); - // - if(dev){ - ret = (compmode ? 0 : 1); - // - // Win2000はbit6が1の時スレーブデバイスを見に行く - // - if (dev->drv[1].device != IDETYPE_NONE) { - ret |= 0x40; - } - } - } - ideio.bank[bank] = ret & (~0x80); - TRACEOUT(("ideio getbank%d %.2x [%.4x:%.8x]", - (port >> 1) & 1, ret, CPU_CS, CPU_EIP)); - return(ret & 0x7f); -} - - - -// ---- - -static void IOOUTCALL ideio_o433(UINT port, REG8 dat) { - -} - -static REG8 IOINPCALL ideio_i433(UINT port) { - - UINT bank; - REG8 ret; - - bank = (port >> 1) & 1; - ret = (ideio.bank[bank] & 0x1) ? 0x2 : 0x0; - - if(ret == 0x2 && ideio.dev[1].drv[0].device==IDETYPE_NONE && ideio.dev[1].drv[1].device==IDETYPE_NONE){ - ret = 0; - } - //OutputDebugStringA("IN 433h¥n"); - return(ret); -} - -static void IOOUTCALL ideio_o435(UINT port, REG8 dat) { - -} - -static REG8 IOINPCALL ideio_i435(UINT port) { - - return(0x00); -} - - - -// ---- - -static void IOOUTCALL ideio_o642(UINT port, REG8 dat) { - - IDEDRV drv; - - drv = getidedrv(); - if (drv) { - drv->wp = dat; - TRACEOUT(("ideio set WP %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); - } - (void)port; -} - -static void IOOUTCALL ideio_o644(UINT port, REG8 dat) { - - IDEDRV drv; - - (void)port; - drv = getidedrv(); - if (drv) { - drv->sc = dat; -#if defined(SUPPORT_IDEIO_48BIT) - drv->lba48sc <<= 8; - drv->lba48sc |= dat; -#endif - TRACEOUT(("ideio set SC %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); - } - (void)port; -} - -static void IOOUTCALL ideio_o646(UINT port, REG8 dat) { - - IDEDRV drv; - - drv = getidedrv(); - if (drv) { - drv->sn = dat; -#if defined(SUPPORT_IDEIO_48BIT) - drv->lba48[3] = drv->lba48[0]; - drv->lba48[0] = dat; -#endif - TRACEOUT(("ideio set SN %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); - } - (void)port; -} - -static void IOOUTCALL ideio_o648(UINT port, REG8 dat) { - - IDEDRV drv; - - drv = getidedrv(); - if (drv) { - drv->cy &= 0xff00; - drv->cy |= dat; -#if defined(SUPPORT_IDEIO_48BIT) - drv->lba48[4] = drv->lba48[1]; - drv->lba48[1] = dat; -#endif - TRACEOUT(("ideio set CYL %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); - } - (void)port; -} - -static void IOOUTCALL ideio_o64a(UINT port, REG8 dat) { - - IDEDRV drv; - - drv = getidedrv(); - if (drv) { - drv->cy &= 0x00ff; - drv->cy |= dat << 8; -#if defined(SUPPORT_IDEIO_48BIT) - drv->lba48[5] = drv->lba48[2]; - drv->lba48[2] = dat; -#endif - TRACEOUT(("ideio set CYH %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); - } - (void)port; -} - -static void IOOUTCALL ideio_o64c(UINT port, REG8 dat) { - - IDEDEV dev; - UINT drvnum; - -#if defined(NP2_WIN) - atapi_dataread_asyncwait(INFINITE); -#endif - - dev = getidedev(); - if (dev == NULL) { - return; - } -#if defined(TRACE) - if ((dat & 0xf0) != 0xa0) { - TRACEOUT(("ideio set SDH illegal param? (%.2x)", dat)); - } -#endif - drvnum = (dat >> 4) & 1; - if(dev->drivesel != drvnum){ - //dev->drv[drvnum].status = dev->drv[drvnum].status & ~(IDESTAT_DRQ|IDESTAT_BSY); - //drvreset(&(dev->drv[drvnum])); - //dev->drv[drvnum].status = IDESTAT_DRDY | IDESTAT_DSC; - //dev->drv[drvnum].error = IDEERR_AMNF; - //if(!drvnum) dev->drv[drvnum].error |= IDEERR_BBK; - } - dev->drv[drvnum].dr = dat & 0xf0; -//#if defined(SUPPORT_IDEIO_48BIT) -// { -// SXSIDEV sxsi = sxsi_getptr(dev->drv[drvnum].sxsidrv); -// if(sxsi->totals > 65535*16*255){ -// dev->drv[drvnum].dr |= IDEDEV_LBA; -// } -// } -//#endif - dev->drv[drvnum].hd = dat & 0x0f; - dev->drivesel = drvnum; - TRACEOUT(("ideio set DRHD %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); - - (void)port; -} - -static void IOOUTCALL ideio_o64e(UINT port, REG8 dat) { - - IDEDRV drv, d; - IDEDEV dev; - int i; - -#if defined(NP2_WIN) - atapi_dataread_asyncwait(INFINITE); -#endif - - // execute device diagnostic - if (dat == 0x90) { - TRACEOUT(("ideio set cmd %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); - TRACEOUT(("ideio: execute device diagnostic")); - dev = getidedev(); - if (dev) { - for (i = 0; i < 2; i++) { - d = dev->drv + i; - drvreset(d); - d->error = 0x01; - if (dev->drv[i].device == IDETYPE_NONE) { - d->error = 0x00; - } - if (i == 0) { - if (dev->drv[1].device == IDETYPE_NONE) { - d->error |= 0x80; - } - } - } - } - return; - } - - drv = getidedrv(); - if (drv == NULL) { - return; - } - drv->cmd = dat; - TRACEOUT(("ideio set cmd %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); - switch(dat) { - case 0x00: // NOP - break; - case 0x08: // device reset - TRACEOUT(("ideio: device reset")); - drvreset(drv); - drv->error = 0x01; - dev = getidedev(); - if (dev) { - if (dev->drv[dev->drivesel].device == IDETYPE_NONE) { - drv->error = 0x00; - } - if (dev->drivesel == 0) { - if (dev->drv[1].device == IDETYPE_NONE) { - drv->error |= 0x80; - } - } - } - setintr(drv); - break; - - case 0x10: case 0x11: case 0x12: case 0x13: // recalibrate - case 0x14: case 0x15: case 0x16: case 0x17: - case 0x18: case 0x19: case 0x1a: case 0x1b: - case 0x1c: case 0x1d: case 0x1e: case 0x1f: - TRACEOUT(("ideio: recalibrate")); - if (drv->device == IDETYPE_HDD) { - //drv->hd = 0x00; - //drv->sc = 0x00; - drv->cy = 0x0000; -#if defined(SUPPORT_IDEIO_48BIT) - drv->lba48[0] = drv->lba48[1] = drv->lba48[2] = drv->lba48[3] = drv->lba48[4] = drv->lba48[5] = 0; -#endif - //if (!(drv->dr & IDEDEV_LBA)) { - // drv->sn = 0x01; - //} - //else { - // drv->sn = 0x00; - //} - drv->status = IDESTAT_DRDY | IDESTAT_DSC; - drv->error = 0; - setintr(drv); - } - else { - cmdabort(drv); - } - break; - - case 0x20: // read (with retry) - case 0x21: // read - TRACEOUT(("ideio: read sector")); - if (drv->device == IDETYPE_HDD) { - drv->mulcnt = 0; - drv->multhr = 1; - readsec(drv); - } - else { - cmdabort(drv); - } - break; - - case 0x30: // write (with retry) - case 0x31: // write - TRACEOUT(("ideio: write sector")); - if (drv->device == IDETYPE_HDD) { - drv->mulcnt = 0; - drv->multhr = 1; - writeinit(drv); - } - else { - cmdabort(drv); - } - break; - case 0x40: // read verify(w) - case 0x41: // read verify(w/o) - drv->status = drv->status & ~IDESTAT_BSY; - setintr(drv); - break; - case 0x91: // INITIALIZE DEVICE PARAMETERS - TRACEOUT(("ideio: INITIALIZE DEVICE PARAMETERS dh=%x sec=%x", - drv->dr | drv->hd, drv->sc)); - if (drv->device == IDETYPE_HDD) { - drv->surfaces = drv->hd + 1; - drv->sectors = drv->sc; - drv->status &= ~(IDESTAT_BSY | IDESTAT_DRQ | IDESTAT_ERR | 0x20); - drv->status |= IDESTAT_DRDY; - setintr(drv); - } - else { - cmdabort(drv); - } - break; - - case 0xa0: // send packet - TRACEOUT(("ideio: packet")); - if (drv->device == IDETYPE_CDROM) { - drv->sc &= ~(IDEINTR_REL | IDEINTR_IO); - drv->sc |= IDEINTR_CD; - drv->status &= ~(IDESTAT_BSY | IDESTAT_DMRD | IDESTAT_SERV | IDESTAT_CHK); - drv->status |= IDESTAT_DRDY | IDESTAT_DRQ | IDESTAT_DSC; - drv->error = 0; - drv->bufpos = 0; - drv->bufsize = 12; - drv->bufdir = IDEDIR_OUT; - drv->buftc = IDETC_TRANSFEREND; - break; - } - cmdabort(drv); - break; - - case 0xa1: // identify packet device - TRACEOUT(("ideio: identify packet device")); - if (drv->device == IDETYPE_CDROM && setidentify(drv) == SUCCESS) { - drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; - drv->error = 0; - setintr(drv); - } - else { - cmdabort(drv); - } - break; - - case 0xb0: // SMART - cmdabort(drv); - break; - - case 0xc4: // read multiple - TRACEOUT(("ideio: read multiple")); -#if IDEIO_MULTIPLE_MAX > 0 - if (drv->device == IDETYPE_HDD) { - drv->mulcnt = 0; - drv->multhr = drv->mulmode; - readsec(drv); - break; - } -#endif - cmdabort(drv); - break; - - case 0xc5: // write multiple - TRACEOUT(("ideio: write multiple")); -#if IDEIO_MULTIPLE_MAX > 0 - if (drv->device == IDETYPE_HDD) { - drv->mulcnt = 0; - drv->multhr = drv->mulmode; - writeinit(drv); - break; - } -#endif - cmdabort(drv); - break; - - case 0xc6: // set multiple mode - TRACEOUT(("ideio: set multiple mode")); - if (drv->device == IDETYPE_HDD) { - switch(drv->sc) { -#if IDEIO_MULTIPLE_MAX > 0 - case 2: case 4: case 8: case 16: case 32: case 64: case 128: - if (drv->sc <= IDEIO_MULTIPLE_MAX) { - drv->mulmode = drv->sc; - setintr(drv); - break; - } - /*FALLTHROUGH*/ -#endif - default: - cmdabort(drv); - break; - } - } - else { - cmdabort(drv); - } - break; - - case 0xe0: // STANDBY IMMEDIATE - TRACEOUT(("ideio: STANDBY IMMEDIATE dr = %.2x", drv->dr)); - if(!(drv->status & IDESTAT_BSY)){ - setintr(drv); - } - //cmdabort(drv); - break; - - case 0xe1: // idle immediate - TRACEOUT(("ideio: idle immediate dr = %.2x", drv->dr)); - //必ず成功するはず - if(drv->status & IDESTAT_DRDY){ - drv->status = IDESTAT_DRDY | IDESTAT_DSC; - drv->error = 0; - setintr(drv); - }else{ - cmdabort(drv); - } - break; - - case 0xe5: // Check power mode - drv->sc = 0xff; - drv->status = drv->status & ~IDESTAT_BSY; - setintr(drv); - break; - - case 0xe7: // flush cache - TRACEOUT(("ideio: flush cache")); - if(!(drv->status & IDESTAT_BSY)){ - drv->status = IDESTAT_DRDY|IDESTAT_BSY; - setdintr2(drv, 0, 0, 20000); - } - drv->error = 0; - break; - - case 0xec: // identify device - TRACEOUT(("ideio: identify device")); - if (drv->device == IDETYPE_HDD && setidentify(drv) == SUCCESS) { - drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; - drv->error = 0; - setintr(drv); - } - else if (drv->device == IDETYPE_CDROM) { - drvreset(drv); - cmdabort(drv); - } - else{ - cmdabort(drv); - } - break; - - case 0xef: // set features - TRACEOUT(("ideio: set features reg = %.2x", drv->wp)); - if(drv->device == IDETYPE_CDROM){ - switch(drv->wp) { - //case 0x95: // Enable Media Status Notification - // ideio_mediastatusnotification[drv->sxsidrv] = 1; - // drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; - // drv->error = 0; - // break; - //case 0x31: // Disable Media Status Notification - // ideio_mediastatusnotification[drv->sxsidrv] = 0; - // drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; - // drv->error = 0; - // break; - default: - cmdabort(drv); - } - }else{ - switch(drv->wp) { - case 0x02: // Enable write cache - case 0x82: // Disable write cache - // nothing to do - drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; - drv->error = 0; - if(!(drv->status & IDESTAT_BSY)){ - setintr(drv); - } - break; - case 0x03: // Set transfer mode based on value in Sector Count register - drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; - drv->error = 0; - if(!(drv->status & IDESTAT_BSY)){ - setintr(drv); - } - break; - default: - cmdabort(drv); - } - } - break; - - case 0xda: // GET MEDIA STATUS - TRACEOUT(("ideio: GET MEDIA STATUS dev=%d", drv->device)); - //if (ideio_mediastatusnotification[drv->sxsidrv]) { - // SXSIDEV sxsi; - // drv->status = IDESTAT_DRDY | IDESTAT_ERR; - // drv->error = 0; - // sxsi = sxsi_getptr(drv->sxsidrv); - // if ((sxsi == NULL) || !(sxsi->flag & SXSIFLAG_READY)) { - // drv->error |= 0x02; // No media - // }else if(ideio_mediachangeflag[drv->sxsidrv]){ - // drv->error |= IDEERR_MCNG; - // ideio_mediachangeflag[drv->sxsidrv] = 0; - // } - // setintr(drv); - //} - //else { - cmdabort(drv); - //} - break; - - case 0xde: // media lock - TRACEOUT(("ideio: media lock dev=%d", drv->device)); - if (drv->device == IDETYPE_HDD) { - cmdabort(drv); - } - else { - drv->status |= IDESTAT_DRDY; - drv->status &= ~(IDESTAT_BSY|IDESTAT_DWF|IDESTAT_DRQ|IDESTAT_ERR); - setintr(drv); - } - break; - - case 0xdf: // media unlock - TRACEOUT(("ideio: media unlock dev=%d", drv->device)); - if (drv->device == IDETYPE_HDD) { - cmdabort(drv); - } - else { - drv->status |= IDESTAT_DRDY; - drv->status &= ~(IDESTAT_BSY|IDESTAT_DWF|IDESTAT_DRQ|IDESTAT_ERR); - setintr(drv); - } - break; - - case 0xf8: // READ NATIVE MAX ADDRESS - TRACEOUT(("ideio: READ NATIVE MAX ADDRESS reg = %.2x", drv->wp)); - { - SXSIDEV sxsi; - sxsi = sxsi_getptr(drv->sxsidrv); - drv->sn = sxsi->totals & 0xff; - drv->cy = (sxsi->totals >> 8) & 0xffff; - drv->hd = (drv->hd & 0xf0) | ((sxsi->totals >> 24) & 0xf); - - if(!(drv->status & IDESTAT_BSY)){ - setintr(drv); - } - } - -#if defined(SUPPORT_IDEIO_48BIT) - case 0x24: // read EXT - TRACEOUT(("ideio: read sector EXT")); - if (drv->device == IDETYPE_HDD) { - drv->mulcnt = 0; - drv->multhr = 1; - drv->lba48mode = 1; - readsec(drv); - } - else { - cmdabort(drv); - } - break; - - case 0x34: // write EXT - TRACEOUT(("ideio: write sector EXT")); - if (drv->device == IDETYPE_HDD) { - drv->mulcnt = 0; - drv->multhr = 1; - drv->lba48mode = 1; - writeinit(drv); - } - else { - cmdabort(drv); - } - break; - case 0x42: // read EXT verify(w) - TRACEOUT(("ideio: read verify EXT")); - drv->status = drv->status & ~IDESTAT_BSY; - setintr(drv); - break; - - case 0x29: // read multiple EXT - TRACEOUT(("ideio: read multiple EXT")); -#if IDEIO_MULTIPLE_MAX > 0 - if (drv->device == IDETYPE_HDD) { - drv->mulcnt = 0; - drv->multhr = drv->mulmode; - drv->lba48mode = 1; - readsec(drv); - break; - } -#endif - cmdabort(drv); - break; - - case 0x39: // write multiple EXT - TRACEOUT(("ideio: write multiple EXT")); -#if IDEIO_MULTIPLE_MAX > 0 - if (drv->device == IDETYPE_HDD) { - drv->mulcnt = 0; - drv->multhr = drv->mulmode; - drv->lba48mode = 1; - writesec(drv); - break; - } -#endif - cmdabort(drv); - break; - - case 0xea: // flush cache EXT - TRACEOUT(("ideio: flush cache EXT")); - if(!(drv->status & IDESTAT_BSY)){ - drv->status = IDESTAT_DRDY|IDESTAT_BSY; - setdintr2(drv, 0, 0, 20000); - } - drv->error = 0; - break; - - case 0x27: // READ NATIVE MAX ADDRESS EXT - TRACEOUT(("ideio: READ NATIVE MAX ADDRESS EXT reg = %.2x", drv->wp)); - { - SXSIDEV sxsi; - sxsi = sxsi_getptr(drv->sxsidrv); - if(drv->ctrl & 0x80){ // HOB bit - drv->sn = (sxsi->totals >> 24) & 0xff; - drv->cy = (sxsi->totals >> 32) & 0xffff; - }else{ - drv->sn = sxsi->totals & 0xff; - drv->cy = (sxsi->totals >> 8) & 0xffff; - } - if(!(drv->status & IDESTAT_BSY)){ - setintr(drv); - } - } - //cmdabort(drv); - break; - -#endif - - default: - panic("ideio: unknown command %.2x", dat); - break; - } - (void)port; -} - -static void IOOUTCALL ideio_o74c(UINT port, REG8 dat) { - - IDEDEV dev; - REG8 modify; - - dev = getidedev(); - if (dev == NULL) { - return; - } - modify = dev->drv[0].ctrl ^ dat; - dev->drv[0].ctrl = dat; - dev->drv[1].ctrl = dat; - if (modify & IDECTRL_SRST) { - if (dat & IDECTRL_SRST) { - dev->drv[0].status = 0; - dev->drv[0].error = 0; - dev->drv[1].status = 0; - dev->drv[1].error = 0; - } - else { - drvreset(&dev->drv[0]); - if (dev->drv[0].device == IDETYPE_HDD) { - dev->drv[0].status = IDESTAT_DRDY | IDESTAT_DSC; - dev->drv[0].error = IDEERR_AMNF; - } - if (dev->drv[0].device == IDETYPE_CDROM) { - dev->drv[0].status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_ERR; - dev->drv[0].error = IDEERR_AMNF; - } - drvreset(&dev->drv[1]); - if (dev->drv[1].device == IDETYPE_HDD) { - dev->drv[1].status = IDESTAT_DRDY | IDESTAT_DSC; - dev->drv[1].error = IDEERR_AMNF; - } - if (dev->drv[1].device == IDETYPE_CDROM) { - dev->drv[1].status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_ERR; - dev->drv[1].error = IDEERR_AMNF; - } - } - } - TRACEOUT(("ideio interrupt %sable", (dat & IDECTRL_NIEN) ? "dis" : "en")); - TRACEOUT(("ideio devctrl %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); - (void)port; -} - -static void IOOUTCALL ideio_o74e(UINT port, REG8 dat) { - - TRACEOUT(("ideio %.4x,%.2x [%.4x:%.8x]", port, dat, CPU_CS, CPU_EIP)); - (void)port; - (void)dat; -} - - -// ---- - -static REG8 IOINPCALL ideio_i642(UINT port) { - - IDEDRV drv; - - (void)port; - - drv = getidedrv(); - if (drv) { - drv->status &= ~IDESTAT_ERR; - TRACEOUT(("ideio get error %.2x [%.4x:%.8x]", - drv->error, CPU_CS, CPU_EIP)); - return(drv->error); - } - else { - return(0xff); - } -} - -static REG8 IOINPCALL ideio_i644(UINT port) { - - IDEDRV drv; - - (void)port; - - drv = getidedrv(); - if (drv) { - UINT8 ret = drv->sc; - TRACEOUT(("ideio get SC %.2x [%.4x:%.8x]", drv->sc, CPU_CS, CPU_EIP)); - //if (drv->device == IDETYPE_CDROM && drv->cmd == 0xa0) { - // drv->sc = 7; // ???? - //} - return(ret); - } - else { - return(0xff); - } -} - -static REG8 IOINPCALL ideio_i646(UINT port) { - - IDEDRV drv; - - (void)port; - - drv = getidedrv(); - if (drv) { - TRACEOUT(("ideio get SN %.2x [%.4x:%.8x]", drv->sn, CPU_CS, CPU_EIP)); - return(drv->sn); - } - else { - return(0xff); - } -} - -static REG8 IOINPCALL ideio_i648(UINT port) { - - IDEDRV drv; - - (void)port; - - drv = getidedrv(); - if (drv) { - TRACEOUT(("ideio get CYL %.4x [%.4x:%.8x]", drv->cy, CPU_CS, CPU_EIP)); - return((UINT8)drv->cy); - } - else { - return(0xff); - } -} - -static REG8 IOINPCALL ideio_i64a(UINT port) { - - IDEDRV drv; - - (void)port; - - drv = getidedrv(); - if (drv) { - TRACEOUT(("ideio get CYH %.4x [%.4x:%.8x]", drv->cy, CPU_CS, CPU_EIP)); - return((REG8)(drv->cy >> 8)); - } - else { - return(0xff); - } -} - -static REG8 IOINPCALL ideio_i64c(UINT port) { - - IDEDRV drv; - REG8 ret; - - (void)port; - - drv = getidedrv(); - if (drv) { - ret = drv->dr | drv->hd; - TRACEOUT(("ideio get DRHD %.2x [%.4x:%.8x]", ret, CPU_CS, CPU_EIP)); - return(ret); - } - else { - return(0xff); - } -} - -static REG8 IOINPCALL ideio_i64e(UINT port) { - - IDEDRV drv; - - (void)port; - - drv = getidedrv(); - if (drv) { - TRACEOUT(("ideio status %.2x [%.4x:%.8x]", - drv->status, CPU_CS, CPU_EIP)); - if (!(drv->ctrl & IDECTRL_NIEN)) { - TRACEOUT(("ideio: resetirq")); - pic_resetirq(IDE_IRQ); - if (ideio.bios != IDETC_BIOS) { - mem[MEMB_DISK_INTH] &= ~0x01; // エミュレーションIDE BIOSなら代理で下ろす - } - } - return(drv->status); - } - else { - return(0xff); - } -} - -static REG8 IOINPCALL ideio_i74c(UINT port) { - - IDEDRV drv; - - (void)port; - - drv = getidedrv(); - if (drv) { - TRACEOUT(("ideio alt status %.2x [%.4x:%.8x]", - drv->status, CPU_CS, CPU_EIP)); - return(drv->status); - } - else { - return(0xff); - } -} - -static REG8 IOINPCALL ideio_i74e(UINT port) { - - IDEDEV dev; - IDEDRV drv; - REG8 ret; - - dev = getidedev(); - drv = getidedrv(); - ret = 0xc0; - ret |= (~(drv->hd) & 0x0f) << 2; - if (dev->drivesel == 0) { - ret |= 2; /* master */ - } else { - ret |= 1; /* slave */ - } - return ret; -} - -static REG8 IOINPCALL ideio_i1e8e(UINT port) { - if((CPU_RAM_D000 & 0x1c00) == 0x1c00){ - return(0x81); - } - return(0x80); -} - -static void IOOUTCALL ideio_o1e8e(UINT port, REG8 dat) { - switch(dat){ - case 0x00: - case 0x80: - TRACEOUT(("remove RAM on 0xDA000-DBFFF but ignore")); - //CPU_RAM_D000 |= 0x0000; - break; - case 0x81: - TRACEOUT(("connect RAM on 0xDA000-DBFFF")); - CPU_RAM_D000 |= 0x1c00; - break; - default: - break; - } -} - - -// ---- data - -void IOOUTCALL ideio_w16(UINT port, REG16 value) { - - IDEDEV dev; - IDEDRV drv; - UINT8 *p; - FILEPOS sec; - - dev = getidedev(); - drv = getidedrv(); - if ((drv != NULL) && - (drv->status & IDESTAT_DRQ) && (drv->bufdir == IDEDIR_OUT)) { - p = drv->buf + drv->bufpos; - p[0] = (UINT8)value; - p[1] = (UINT8)(value >> 8); - //TRACEOUT(("ide-data send %.4x (%.4x) [%.4x:%.8x]", - // value, drv->bufpos, CPU_CS, CPU_EIP)); - drv->bufpos += 2; - if (drv->bufpos >= drv->bufsize) { - drv->status &= ~IDESTAT_DRQ; - switch(drv->cmd) { - case 0x30: - case 0x31: - case 0x34: - case 0xc5: - case 0x39: - drv->status |= IDESTAT_BSY; - sec = getcursec(drv); - //TRACEOUT(("writesec->drv %d sec %x cnt %d thr %d", - // drv->sxsidrv, sec, drv->mulcnt, drv->multhr)); - if (sxsi_write(drv->sxsidrv, sec, drv->buf, drv->bufsize)) { - TRACEOUT(("write error!")); - cmdabort(drv); - break; - } - incsec(drv); -#if defined(SUPPORT_IDEIO_48BIT) - if(drv->lba48mode){ - drv->lba48sc--; - drv->sc = (UINT8)drv->lba48sc; - if (drv->lba48sc) { - writesec(drv); - }else{ - // セクタ書き込み完了 - if(ideio.wwait > 0){ - setdintr2(drv, 0, 0, ideio.wwait); - }else{ - setintr(drv); - drv->status &= ~(IDESTAT_BSY); - } - drv->sc = 0; - drv->lba48mode = 0; - } - }else -#endif - { - drv->sc--; - if (drv->sc) { - writesec(drv); - }else{ - // セクタ書き込み完了 - if(ideio.wwait > 0){ - setdintr2(drv, 0, 0, ideio.wwait); - }else{ - setintr(drv); - drv->status &= ~(IDESTAT_BSY); - } - } - } - break; - - case 0xa0: - TRACEOUT(("ideio: execute atapi packet command")); - atapicmd_a0(drv); - break; - } - } - } - (void)port; -} - -REG16 IOINPCALL ideio_r16(UINT port) { - - IDEDRV drv; - REG16 ret; - UINT8 *p; - - (void)port; - - drv = getidedrv(); - if (drv == NULL) { - return(0xff); - } - ret = 0; - if ((drv->status & IDESTAT_DRQ) && (drv->bufdir == IDEDIR_IN)) { - p = drv->buf + drv->bufpos; - ret = p[0] + (p[1] << 8); - //TRACEOUT(("ide-data recv %.4x (%.4x) [%.4x:%.8x]", - // ret, drv->bufpos, CPU_CS, CPU_EIP)); - drv->bufpos += 2; - if (drv->bufpos >= drv->bufsize) { - drv->status &= ~IDESTAT_DRQ; - switch(drv->cmd) { - case 0x20: - case 0x21: - case 0x24: - case 0xc4: - case 0x29: - incsec(drv); -#if defined(SUPPORT_IDEIO_48BIT) - if(drv->lba48mode){ - drv->lba48sc--; - drv->sc = (UINT8)drv->lba48sc; - if (drv->lba48sc) { - readsec(drv); - }else{ - // 読み取り終わり - drv->lba48mode = 0; - } - }else -#endif - { - drv->sc--; - if (drv->sc) { - readsec(drv); - }else{ - // 読み取り終わり - } - } - break; - - case 0xa0: - if (drv->status & IDESTAT_BSY) { - break; - } - if (drv->buftc == IDETC_ATAPIREAD) { - atapi_dataread(drv); - break; - } - drv->sc = IDEINTR_IO | IDEINTR_CD; - drv->status &= ~(IDESTAT_BSY | IDESTAT_SERV | IDESTAT_CHK | IDESTAT_DRQ); // clear DRQ bit np21w ver0.86 rev38 - drv->status |= IDESTAT_DRDY | IDESTAT_DSC; - drv->error = 0; - setintr(drv); - break; - } - } - } - return(ret); -} - - -// ---- - -#if 1 -static SINT32 cdda_softvolume_L = 0; -static SINT32 cdda_softvolume_R = 0; -static SINT32 cdda_softvolumereg_L = 0xff; -static SINT32 cdda_softvolumereg_R = 0xff; -static BRESULT SOUNDCALL playdevaudio(IDEDRV drv, SINT32 *pcm, UINT count) { - - SXSIDEV sxsi; - UINT r; -const UINT8 *ptr; - SINT sampl; - SINT sampr; - SINT32 buf_l; - SINT32 buf_r; - SINT32 buf_count; - SINT32 samplen_n; - SINT32 samplen_d; -static SINT32 sampcount2_n = 0; - SINT32 sampcount2_d; - UINT mute = 0; - - samplen_n = soundcfg.rate; - samplen_d = 44100; - //if(samplen_n > samplen_d){ - // // XXX: サンプリングレートが大きい場合のオーバーフロー対策・・・ - // samplen_n /= 100; - // samplen_d /= 100; - //} - //if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_MATE_X_PCM || g_nSoundID == SOUNDID_PC_9801_86_WSS || g_nSoundID == SOUNDID_WAVESTAR || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ - // if(cdda_softvolumereg_L != cs4231.devvolume[0x32]){ - // cdda_softvolumereg_L = cs4231.devvolume[0x32]; - // if(cdda_softvolumereg_L & 0x80){ // CD L Mute - // cdda_softvolume_L = 0; - // }else{ - // cdda_softvolume_L = ((~cdda_softvolumereg_L) & 0x1f); // CD L Volume - // } - // } - // if(cdda_softvolumereg_R != cs4231.devvolume[0x33]){ - // cdda_softvolumereg_R = cs4231.devvolume[0x33]; - // if(cdda_softvolumereg_R & 0x80){ // CD R Mute - // cdda_softvolume_R = 0; - // }else{ - // cdda_softvolume_R = ((~cdda_softvolumereg_R) & 0x1f); // CD R Volume - // } - // } - //}else{ - cdda_softvolume_L = 0x1f; - cdda_softvolume_R = 0x1f; - cdda_softvolumereg_L = 0; - cdda_softvolumereg_R = 0; - //} - - sxsi = sxsi_getptr(drv->sxsidrv); - if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) || - (!(sxsi->flag & SXSIFLAG_READY))) { - drv->daflag = 0x14; - return(FAILURE); - } - while(count) { - r = MIN(count, drv->dabufrem * samplen_n / samplen_d); - if (r) { - count -= r; - ptr = drv->dabuf + 2352 - (drv->dabufrem * 4); - drv->dabufrem -= r * samplen_d / samplen_n; - if(samplen_n < samplen_d){ - //sampcount2_n = 0; - sampcount2_d = samplen_d; - buf_l = buf_r = buf_count = 0; - do { - sampl = ((SINT8)ptr[1] << 8) + ptr[0]; - sampr = ((SINT8)ptr[3] << 8) + ptr[2]; - ptr += 4; - sampcount2_n += samplen_n; - buf_l += (SINT)((int)(sampl)*((int)np2cfg.davolume * np2cfg.vol_master / 100)*cdda_softvolume_L/255/31); - buf_r += (SINT)((int)(sampr)*((int)np2cfg.davolume * np2cfg.vol_master / 100)*cdda_softvolume_R/255/31); - buf_count++; - if(sampcount2_n > sampcount2_d){ - pcm[0] += buf_l / buf_count; - pcm[1] += buf_r / buf_count; - //pcm[0] += (SINT)((int)(sampl)*((int)np2cfg.davolume * np2cfg.vol_master / 100)/255); - //pcm[1] += (SINT)((int)(sampr)*((int)np2cfg.davolume * np2cfg.vol_master / 100)/255); - pcm += 2 * (sampcount2_n / sampcount2_d); - --r; - sampcount2_n = sampcount2_n % sampcount2_d; - buf_l = buf_r = buf_count = 0; - } - } while(r > 0); - }else{ - sampcount2_n = samplen_n; - sampcount2_d = samplen_d; - do { - sampl = ((SINT8)ptr[1] << 8) + ptr[0]; - sampr = ((SINT8)ptr[3] << 8) + ptr[2]; - pcm[0] += (SINT)((int)(sampl)*((int)np2cfg.davolume * np2cfg.vol_master / 100)*cdda_softvolume_L/255/31); - pcm[1] += (SINT)((int)(sampr)*((int)np2cfg.davolume * np2cfg.vol_master / 100)*cdda_softvolume_L/255/31); - sampcount2_n -= sampcount2_d; - if(sampcount2_n <= 0){ - sampcount2_n += samplen_n; - ptr += 4; - } - pcm += 2; - } while(--r); - } - } - if (count == 0) { - break; - } - if (drv->dalength == 0) { - drv->daflag = 0x13; - return(FAILURE); - } - if(np2cfg.cddtskip){ - CDTRK trk; - UINT tracks; - trk = sxsicd_gettrk(sxsi, &tracks); - r = tracks; - while(r) { - r--; - if (trk[r].pos <= drv->dacurpos) { - break; - } - } - if(trk[r].adr_ctl!=TRACKTYPE_AUDIO){ - if(drv->dacurpos != 0){ - // オーディオトラックでない場合は強制的に次に飛ばす - if(r==tracks-1){ - drv->dacurpos = trk[0].pos; - }else{ - drv->dacurpos = trk[r+1].pos; - } - } - mute = 1; - } - } - if(mute){ - memset(drv->dabuf, 0, sizeof(drv->dabuf)); - }else{ - if (sxsicd_readraw(sxsi, drv->dacurpos, drv->dabuf) != SUCCESS) { - drv->daflag = 0x14; - return(FAILURE); - } - } - drv->dalength--; - drv->dacurpos++; - drv->dabufrem = sizeof(drv->dabuf) / 4; - } - return(SUCCESS); -} - -static void SOUNDCALL playaudio(void *hdl, SINT32 *pcm, UINT count) { - - UINT bit; - IDEDRV drv; - - bit = ideio.daplaying; - if (!bit) { - return; - } - if (bit & 4) { - drv = ideio.dev[1].drv + 0; - if (playdevaudio(drv, pcm, count) != SUCCESS) { - bit = bit & (~4); - } - } - ideio.daplaying = bit; -} -#endif - -// ---- - -static void devinit(IDEDRV drv, REG8 sxsidrv) { - - SXSIDEV sxsi; - - ZeroMemory(drv, sizeof(_IDEDRV)); - drv->sxsidrv = sxsidrv; - //drv->dr = 0xa0; - sxsi = sxsi_getptr(sxsidrv); - if ((sxsi != NULL) && (np2cfg.idetype[sxsidrv] == SXSIDEV_HDD) && - (sxsi->devtype == SXSIDEV_HDD) && (sxsi->flag & SXSIFLAG_READY)) { - drv->status = IDESTAT_DRDY | IDESTAT_DSC; - drv->error = IDEERR_AMNF; - drv->device = IDETYPE_HDD; - drv->surfaces = sxsi->surfaces; - drv->sectors = sxsi->sectors; - drv->mulmode = IDEIO_MULTIPLE_MAX; - } - else if ((sxsi != NULL) && (np2cfg.idetype[sxsidrv] == SXSIDEV_CDROM) && - (sxsi->devtype == SXSIDEV_CDROM)) { - drv->device = IDETYPE_CDROM; - drvreset(drv); - drv->error = 0; - drv->media = IDEIO_MEDIA_EJECTABLE; - if (sxsi->flag & SXSIFLAG_READY) { - drv->media |= (IDEIO_MEDIA_CHANGED|IDEIO_MEDIA_LOADED); - } - drv->daflag = 0x15; - drv->damsfbcd = 0; - } - else { - drv->status = IDESTAT_ERR; - drv->error = IDEERR_TR0; - drv->device = IDETYPE_NONE; - } -//#if defined(SUPPORT_IDEIO_48BIT) -// if(sxsi->totals > 65535*16*255){ -// drv->dr |= IDEDEV_LBA; -// } -//#endif - //memset(ideio_mediastatusnotification, 0, sizeof(ideio_mediastatusnotification)); - //memset(ideio_mediachangeflag, 0, sizeof(ideio_mediachangeflag)); -} - -void ideio_initialize(void) { - atapi_initialize(); -} - -void ideio_deinitialize(void) { - atapi_deinitialize(); -} - -void ideio_basereset() { - REG8 i; - IDEDRV drv; - - for (i=0; i<4; i++) { - drv = ideio.dev[i >> 1].drv + (i & 1); - devinit(drv, i); - } - - if (pccore.hddif & PCHDD_IDE) { - int compmode = (sxsi_getdevtype(0)!=SXSIDEV_CDROM && sxsi_getdevtype(1)!=SXSIDEV_CDROM && sxsi_getdevtype(2)==SXSIDEV_CDROM && sxsi_getdevtype(3)!=SXSIDEV_CDROM); // 旧機種互換モード? - - // WORKAROUND for WinNT4.0 - if(compmode){ - mem[0x05ba] = (sxsi_getdevtype(3)==SXSIDEV_HDD ? 0x8 : 0x0)|(sxsi_getdevtype(2)==SXSIDEV_HDD ? 0x4 : 0x0)| - (sxsi_getdevtype(1)==SXSIDEV_HDD ? 0x2 : 0x0)|(sxsi_getdevtype(0)==SXSIDEV_HDD ? 0x1 : 0x0); - }else{ - mem[0x05ba] = (sxsi_getdevtype(3)!=SXSIDEV_NC ? 0x8 : 0x0)|(sxsi_getdevtype(2)!=SXSIDEV_NC ? 0x4 : 0x0)| - (sxsi_getdevtype(1)!=SXSIDEV_NC ? 0x2 : 0x0)|(sxsi_getdevtype(0)!=SXSIDEV_NC ? 0x1 : 0x0); - } - } -} -void ideio_reset(const NP2CFG *pConfig) { - REG8 i; - - OEMCHAR path[MAX_PATH]; - FILEH fh; - OEMCHAR tmpbiosname[16]; - UINT8 useidebios; - UINT32 biosaddr; - - ZeroMemory(&ideio, sizeof(ideio)); - - ideio_basereset(); - - ideio.rwait = np2cfg.iderwait; - ideio.wwait = np2cfg.idewwait; - ideio.bios = IDETC_NOBIOS; - - if(pccore.hddif & PCHDD_IDE){ - if(pConfig->idebaddr){ - biosaddr = (UINT32)pConfig->idebaddr << 12; - useidebios = np2cfg.idebios && np2cfg.usebios; - if(useidebios && np2cfg.autoidebios){ - SXSIDEV sxsi; - for (i=0; i<4; i++) { - sxsi = sxsi_getptr(i); - if ((sxsi != NULL) && (np2cfg.idetype[i] == SXSIDEV_HDD) && - (sxsi->devtype == SXSIDEV_HDD) && (sxsi->flag & SXSIFLAG_READY)) { - if(sxsi->surfaces != 8 || sxsi->sectors != 17){ - TRACEOUT(("Incompatible CHS parameter detected. IDE BIOS automatically disabled.")); - useidebios = 0; - } - } - } - } - if(useidebios){ - _tcscpy(tmpbiosname, OEMTEXT("ide.rom")); - getbiospath(path, tmpbiosname, NELEMENTS(path)); - fh = file_open_rb(path); - if (fh == FILEH_INVALID) { - _tcscpy(tmpbiosname, OEMTEXT("d8000.rom")); - getbiospath(path, tmpbiosname, NELEMENTS(path)); - fh = file_open_rb(path); - } - if (fh == FILEH_INVALID) { - _tcscpy(tmpbiosname, OEMTEXT("bank3.bin")); - getbiospath(path, tmpbiosname, NELEMENTS(path)); - fh = file_open_rb(path); - } - if (fh == FILEH_INVALID) { - _tcscpy(tmpbiosname, OEMTEXT("bios9821.rom")); - getbiospath(path, tmpbiosname, NELEMENTS(path)); - fh = file_open_rb(path); - } - }else{ - fh = FILEH_INVALID; - } - if (fh != FILEH_INVALID) { - // IDE BIOS - if (file_read(fh, mem + biosaddr, 0x2000) == 0x2000) { - ideio.bios = IDETC_BIOS; - TRACEOUT(("load ide.rom")); - _tcscpy(ideio.biosname, tmpbiosname); - CPU_RAM_D000 &= ~(0x3 << 8); - }else{ - //CopyMemory(mem + biosaddr, idebios, sizeof(idebios)); - TRACEOUT(("use simulate ide.rom")); - } - file_close(fh); - }else{ - //CopyMemory(mem + biosaddr, idebios, sizeof(idebios)); - TRACEOUT(("use simulate ide.rom")); - } - } - } - - (void)pConfig; -} - -void ideio_bindCDDA(void) { - if (pccore.hddif & PCHDD_IDE) { - sound_streamregist(NULL, (SOUNDCB)playaudio); - } -} - -void ideio_bind(void) { - - if (pccore.hddif & PCHDD_IDE) { - ideio_bindCDDA(); - - iocore_attachout(0x0430, ideio_o430); - iocore_attachout(0x0432, ideio_o430); - iocore_attachinp(0x0430, ideio_i430); - iocore_attachinp(0x0432, ideio_i430); - - iocore_attachout(0x0642, ideio_o642); - iocore_attachout(0x0644, ideio_o644); - iocore_attachout(0x0646, ideio_o646); - iocore_attachout(0x0648, ideio_o648); - iocore_attachout(0x064a, ideio_o64a); - iocore_attachout(0x064c, ideio_o64c); - iocore_attachout(0x064e, ideio_o64e); - iocore_attachinp(0x0642, ideio_i642); - iocore_attachinp(0x0644, ideio_i644); - iocore_attachinp(0x0646, ideio_i646); - iocore_attachinp(0x0648, ideio_i648); - iocore_attachinp(0x064a, ideio_i64a); - iocore_attachinp(0x064c, ideio_i64c); - iocore_attachinp(0x064e, ideio_i64e); - - iocore_attachout(0x074c, ideio_o74c); - iocore_attachout(0x074e, ideio_o74e); - iocore_attachinp(0x074c, ideio_i74c); - iocore_attachinp(0x074e, ideio_i74e); - - iocore_attachout(0x1e8e, ideio_o1e8e); // 一部IDE BIOSはこれがないと起動時にフリーズしたりシリンダ数が0になる - iocore_attachinp(0x1e8e, ideio_i1e8e); // 一部IDE BIOSはこれがないと起動時にフリーズしたりシリンダ数が0になる - - iocore_attachout(0x0433, ideio_o433); - iocore_attachinp(0x0433, ideio_i433); - iocore_attachout(0x0435, ideio_o435); - iocore_attachinp(0x0435, ideio_i435); - } -} - -void ideio_notify(REG8 sxsidrv, UINT action) { - - SXSIDEV sxsi; - IDEDRV drv; - REG8 i; - - sxsi = sxsi_getptr(sxsidrv); - if ((sxsi == NULL) - || (!(sxsi->flag & SXSIFLAG_READY)) - || (sxsi->devtype != SXSIDEV_CDROM)) { - return; - } - - for (i=0; i<4; i++) { - drv = ideio.dev[i >> 1].drv + (i & 1); - if ((drv != NULL) && (drv->sxsidrv == sxsidrv)) { - goto do_notify; - } - } - return; - -do_notify: - switch(action) { - case 1: - drv->media |= (IDEIO_MEDIA_CHANGED|IDEIO_MEDIA_LOADED); - if (sxsi->mediatype & SXSIMEDIA_DATA) - drv->media |= IDEIO_MEDIA_DATA; - if (sxsi->mediatype & SXSIMEDIA_AUDIO) - drv->media |= IDEIO_MEDIA_AUDIO; - break; - - case 0: - drv->media &= ~(IDEIO_MEDIA_LOADED|IDEIO_MEDIA_COMBINE); - break; - } -} - -void ideio_mediachange(REG8 sxsidrv) { - - //SXSIDEV sxsi; - //IDEDRV drv; - //REG8 i; - // - //sxsi = sxsi_getptr(sxsidrv); - //if ((sxsi == NULL) - // || (!(sxsi->flag & SXSIFLAG_READY)) - // || (sxsi->devtype != SXSIDEV_CDROM)) { - // return; - //} - - //for (i=0; i<4; i++) { - // drv = ideio.dev[i >> 1].drv + (i & 1); - // if ((drv != NULL) && (drv->sxsidrv == sxsidrv)) { - // break; - // } - //} - //if(i==4) return; - // - //drv->status |= IDESTAT_ERR; - //drv->error |= IDEERR_MCNG; - //setintr(drv); - //drv->error &= ~IDEERR_MCNG; // 一旦フラグクリア - //drv->media |= IDEIO_MEDIA_CHANGED; - //setintr(drv); - //ideio_mediachangeflag[sxsidrv] = 1; -} - -#endif /* SUPPORT_IDEIO */ - +#include + +#if 1 +#undef TRACEOUT +#define TRACEOUT(s) (void)(s) +//static void trace_fmt_ex(const char *fmt, ...) +//{ +// char stmp[2048]; +// va_list ap; +// va_start(ap, fmt); +// vsprintf(stmp, fmt, ap); +// strcat(stmp, "¥n"); +// va_end(ap); +// OutputDebugStringA(stmp); +//} +//#define TRACEOUT(s) trace_fmt_ex s +#endif /* 1 */ + +// winでidentifyまでは取得に行くんだけどな…ってAnex86も同じか + +#if defined(SUPPORT_IDEIO) + +#include +#include +#include +#include +#include +#include +#include +#include +#include "idebios.res" +#include +#include +#include + + IDEIO ideio; + +static IDEDEV getidedev(void) { + + UINT bank; + + bank = ideio.bank[1] & 0x7f; + if (bank < 2) { + return(ideio.dev + bank); + } + else { + return(NULL); + } +} + +static IDEDRV getidedrv(void) { + + IDEDEV dev; + IDEDRV drv; + + dev = getidedev(); + if (dev) { + drv = dev->drv + dev->drivesel; + if (drv->device != IDETYPE_NONE) { + return(drv); + } + } + return(NULL); +} + +static const char serial[] = "824919341192 "; +static const char firm[] = "A5U.1200"; +static const char model[] = "QUANTUM FIREBALL CR "; +static const char model48[] = "NYANTUM YARNBALL CR "; + +static const char cdrom_serial[] = "1.0 "; +static const char cdrom_firm[] = " "; +static const char cdrom_model[] = "NEC CD-ROM DRIVE:98 "; + +static BRESULT setidentify(IDEDRV drv) { + + SXSIDEV sxsi; + UINT16 tmp[256]; + UINT8 *p; + UINT i; + FILELEN size; + + sxsi = sxsi_getptr(drv->sxsidrv); + if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY) && drv->device != IDETYPE_CDROM)) { + return(FAILURE); + } + + ZeroMemory(tmp, sizeof(tmp)); + // とりあえず使ってる部分だけ + if (drv->device == IDETYPE_HDD) { + tmp[0] = 0x0040; // non removable device + tmp[1] = sxsi->cylinders; + tmp[3] = sxsi->surfaces; + tmp[4] = sxsi->sectors * 512; + tmp[6] = sxsi->sectors; + for (i=0; i<10; i++) { + tmp[10+i] = (serial[i*2] << 8) + serial[i*2+1]; + } + tmp[10+2] = '0'+drv->sxsidrv; // シリアル番号はユニークにしておかないと駄目っぽい + tmp[22] = 4; + for (i=0; i<4; i++) { + tmp[23+i] = (firm[i*2] << 8) + firm[i*2+1]; + } + for (i=0; i<20; i++) { + tmp[27+i] = (model[i*2] << 8) + model[i*2+1]; + } +#if IDEIO_MULTIPLE_MAX > 0 + tmp[47] = 0x8000 | IDEIO_MULTIPLE_MAX; // multiple +#endif + tmp[49] = 0x0200; // support LBA + tmp[51] = 0x0278; + tmp[53] = 0x0003; + size = (FILELEN)sxsi->cylinders * sxsi->surfaces * sxsi->sectors; + tmp[54] = (UINT16)(size / drv->surfaces / drv->sectors);//sxsi->cylinders; + tmp[55] = drv->surfaces;//sxsi->surfaces; + tmp[56] = drv->sectors;//sxsi->sectors; + size = (FILELEN)tmp[54] * tmp[55] * tmp[56]; + tmp[57] = (UINT16)size; + tmp[58] = (UINT16)(size >> 16); +#if IDEIO_MULTIPLE_MAX > 0 + tmp[59] = 0x0100 | drv->mulmode; // current multiple mode +#endif + tmp[60] = (UINT16)size; + tmp[61] = (UINT16)(size >> 16); + tmp[63] = 0x0000; // no support multiword DMA + tmp[64] = 0x0003; // device supports PIO mode 3, 4 + + tmp[81] = 0; + tmp[82] = 0x4200; // support NOP, DEVICE RESET and Write Cache + +#if defined(SUPPORT_IDEIO_48BIT) + if(sxsi->totals > 65535*16*255){ + // 48-bit LBA + FILELEN tmpCyl = (UINT32)(sxsi->totals / 255 / 255); + tmp[80] = 0x007e; // support ATA-1 to 6 + tmp[81] = 0; + tmp[82] = 0x0200; // support DEVICE RESET + tmp[83] = 0x4400; // 48-bit Address feature set supported + tmp[86] = 0x4400; // 48-bit Address feature set supported + tmp[100] = (UINT16)(sxsi->totals); // Maximum user LBA for 48-bit Address feature set 1 + tmp[101] = (UINT16)(sxsi->totals >> 16); // Maximum user LBA for 48-bit Address feature set 2 + tmp[102] = (UINT16)(sxsi->totals >> 32); // Maximum user LBA for 48-bit Address feature set 3 + tmp[103] = (UINT16)(sxsi->totals >> 48); // Maximum user LBA for 48-bit Address feature set 4 + if(tmp[102] || tmp[103] || (tmp[101] & 0xf000)){ + tmp[60] = (UINT16)0xffff; + tmp[61] = (UINT16)0xfff; + }else{ + tmp[60] = tmp[100]; + tmp[61] = tmp[101]; + } + tmp[54] = (UINT16)(tmpCyl < 0xffff ? tmpCyl : 0xffff); + tmp[55] = 255; + tmp[56] = 255; + size = (FILELEN)tmp[54] * tmp[55] * tmp[56]; + tmp[57] = (UINT16)size; + tmp[58] = (UINT16)(size >> 16); + for (i=0; i<20; i++) { + tmp[27+i] = (model48[i*2] << 8) + model48[i*2+1]; + } + } +#endif + { + tmp[80] = 0x003e; // support ATA-1 to 5 + } + } + else if (drv->device == IDETYPE_CDROM) { + tmp[0] = 0x8580; // ATAPI,CD-ROM,removable,12bytes PACKET + for (i=0; i<10; i++) { + tmp[10+i] = (cdrom_serial[i*2] << 8) + cdrom_serial[i*2+1]; + } + tmp[10+2] = '0'+drv->sxsidrv; // シリアル番号はユニークにしておかないと駄目っぽい + for (i=0; i<4; i++) { + tmp[23+i] = (cdrom_firm[i*2] << 8) + cdrom_firm[i*2+1]; + } + for (i=0; i<20; i++) { + tmp[27+i] = (cdrom_model[i*2] << 8) + cdrom_model[i*2+1]; + } + tmp[49] = 0x0200; // support LBA + tmp[51] = 0x0278; + tmp[53] = 0x0003; + tmp[63] = 0x0000; // no support multiword DMA + tmp[64] = 0x0003; // device supports PIO mode 3, 4 + tmp[80] = 0x003e; // support ATA-1 to 5 + tmp[82] = 0x0214; // support PACKET/DEVICE RESET + tmp[126] = 0x0000; // ATAPI byte count + } + if (drv->sxsidrv & 0x1){ + // slave + tmp[93] = 0x4b00; + }else{ + // master + tmp[93] = 0x407b; + } + + p = drv->buf; + for (i=0; i<256; i++) { + p[0] = (UINT8)tmp[i]; + p[1] = (UINT8)(tmp[i] >> 8); + p += 2; + } + drv->bufdir = IDEDIR_IN; + drv->buftc = IDETC_TRANSFEREND; + drv->bufpos = 0; + drv->bufsize = 512; + return(SUCCESS); +} + +static void setintr(IDEDRV drv) { + + if (!(drv->ctrl & IDECTRL_NIEN)) { + TRACEOUT(("ideio: setintr()")); + ideio.bank[0] = ideio.bank[1] | 0x80; // ???? + pic_setirq(IDE_IRQ); + if (ideio.bios != IDETC_BIOS) { + mem[MEMB_DISK_INTH] |= 0x01; // エミュレーションIDE BIOSなら代理で立てる + } + } +} + +// 割り込み後にBSYを解除し、DRQをセットする(コマンド継続中など) +void ideioint(NEVENTITEM item) { + + IDEDRV drv; + IDEDEV dev; + + //ドライブがあるか + dev = getidedev(); + if (dev == NULL) { + return; + } + + drv = getidedrv(); + if (drv == NULL) { + return; + } + + //BUSY解除 + if(dev->drv[0].status != 0xFF){ + dev->drv[0].status |= IDESTAT_DRQ; + dev->drv[0].status &= ~IDESTAT_BSY; + } + if(dev->drv[1].status != 0xFF){ + dev->drv[1].status |= IDESTAT_DRQ; + dev->drv[1].status &= ~IDESTAT_BSY; + } + + //割り込み実行//(割り込みはドライブ毎には指定できない仕様) + if(!(dev->drv[0].ctrl & IDECTRL_NIEN) || !(dev->drv[1].ctrl & IDECTRL_NIEN)){ + TRACEOUT(("ideio: run setdintr()")); + pic_setirq(IDE_IRQ); + if (ideio.bios != IDETC_BIOS) { + mem[MEMB_DISK_INTH] |= 0x01; // エミュレーションIDE BIOSなら代理で立てる + } + } + (void)item; +} +// 割り込み後にBSYを解除し、DRQも解除する(コマンド終了時など) +void ideioint2(NEVENTITEM item) { + + IDEDRV drv; + IDEDEV dev; + + //ドライブがあるか + dev = getidedev(); + if (dev == NULL) { + return; + } + + drv = getidedrv(); + if (drv == NULL) { + return; + } + + //BUSY解除 + if(dev->drv[0].status != 0xFF){ + dev->drv[0].status &= ~IDESTAT_DRQ; + dev->drv[0].status &= ~IDESTAT_BSY; + } + if(dev->drv[1].status != 0xFF){ + dev->drv[1].status &= ~IDESTAT_DRQ; + dev->drv[1].status &= ~IDESTAT_BSY; + } + + //割り込み実行//(割り込みはドライブ毎には指定できない仕様) + if(!(dev->drv[0].ctrl & IDECTRL_NIEN) || !(dev->drv[1].ctrl & IDECTRL_NIEN)){ + TRACEOUT(("ideio: run setdintr()")); + pic_setirq(IDE_IRQ); + if (ideio.bios != IDETC_BIOS) { + mem[MEMB_DISK_INTH] |= 0x01; // エミュレーションIDE BIOSなら代理で立てる + } + } + (void)item; +} + +// 遅延付き割り込み +static void setdintr(IDEDRV drv, UINT8 errno, UINT8 status, UINT32 delay) { + + if (!(drv->ctrl & IDECTRL_NIEN)) { + //drv->status |= IDESTAT_BSY; + ideio.bank[0] = ideio.bank[1] | 0x80; // ???? + TRACEOUT(("ideio: reg setdintr()")); + + //// 指定した時間遅延(マイクロ秒) + //nevent_set(NEVENT_SASIIO, (pccore.realclock / 1000 / 1000) * delay, ideioint, NEVENT_ABSOLUTE); + + // 指定した時間遅延(クロック数) + if (delay == 0) + { + ideioint(&g_nevent.item[NEVENT_SASIIO]); + } + else + { + nevent_set(NEVENT_SASIIO, delay, ideioint, NEVENT_ABSOLUTE); + } + } +} +static void setdintr2(IDEDRV drv, UINT8 errno, UINT8 status, UINT32 delay) { + + if (!(drv->ctrl & IDECTRL_NIEN)) { + //drv->status |= IDESTAT_BSY; + ideio.bank[0] = ideio.bank[1] | 0x80; // ???? + TRACEOUT(("ideio: reg setdintr()")); + + //// 指定した時間遅延(マイクロ秒) + //nevent_set(NEVENT_SASIIO, (pccore.realclock / 1000 / 1000) * delay, ideioint, NEVENT_ABSOLUTE); + + // 指定した時間遅延(クロック数) + if (delay == 0) + { + ideioint2(&g_nevent.item[NEVENT_SASIIO]); + } + else + { + nevent_set(NEVENT_SASIIO, delay, ideioint2, NEVENT_ABSOLUTE); + } + } +} + + +static void cmdabort(IDEDRV drv) { + + TRACEOUT(("ideio: cmdabort()")); + drv->status = IDESTAT_DRDY | IDESTAT_ERR; + drv->error = IDEERR_ABRT; +#if defined(SUPPORT_IDEIO_48BIT) + drv->lba48mode = 0; +#endif + setintr(drv); +} + +static void drvreset(IDEDRV drv) { + + if (drv->device == IDETYPE_CDROM) { + drv->hd = 0x10; + drv->sc = 0x01; + drv->sn = 0x01; + drv->cy = 0xeb14; + drv->status = 0; + } + else { + drv->hd = 0x00; + drv->sc = 0x01; + drv->sn = 0x01; + drv->cy = 0x0000; +#if defined(SUPPORT_IDEIO_48BIT) + drv->lba48[1] = drv->lba48[2] = drv->lba48[3] = drv->lba48[4] = drv->lba48[5] = 0; + drv->lba48[0] = 1; + drv->lba48sc = 0x0001; +#endif + //drv->status = IDESTAT_DRDY; + drv->status = IDESTAT_DRDY | IDESTAT_DSC; + } +} + +static void panic(const char *str, ...) { + + char buf[2048]; + va_list ap; + + va_start(ap, str); + vsnprintf(buf, sizeof(buf), str, ap); + va_end(ap); + + msgbox("ide_panic", buf); + exit(1); +} + + +// ---- + +static void incsec(IDEDRV drv) { + + if (!(drv->dr & IDEDEV_LBA)) { + drv->sn++; + if (drv->sn <= drv->sectors && drv->sn!=0) { + return; + } + drv->sn = 1; + drv->hd++; + if (drv->hd < drv->surfaces) { + return; + } + drv->hd = 0; + drv->cy++; + } + else { +#if defined(SUPPORT_IDEIO_48BIT) + // 48-bit Address feature set + { + int i; + for(i=0;i<6;i++){ + drv->lba48[i]++; + if (drv->lba48[i]) { + break; + } + } + } +#endif + drv->sn++; + if (drv->sn) { + return; + } + drv->cy++; + if (drv->cy) { + return; + } + drv->hd++; + } +} + +void ideio_setcursec(FILEPOS pos) { + IDEDRV drv; +#if defined(SUPPORT_IDEIO_48BIT) + int shift = 0; + int i; +#endif + drv = getidedrv(); + if (drv) { + if (!(drv->dr & IDEDEV_LBA)) { + drv->sn = (pos % drv->sectors) + 1; + pos /= drv->sectors; + drv->hd = (pos % drv->surfaces); + pos /= drv->surfaces; + drv->cy = pos & 0xffff; + } + else { + drv->sn = (pos & 0xff); + drv->cy = ((pos >> 8) & 0xffff); + drv->hd = ((pos >> 24) & 0xff); + +#if defined(SUPPORT_IDEIO_48BIT) + // 48-bit Address feature set + for(i=0;i<6;i++){ + drv->lba48[i] = (pos >> shift) & 0xff; + shift += 8; + } +#endif + } + } +} +static FILEPOS getcursec(const IDEDRV drv) { + + FILEPOS ret; + +#if defined(SUPPORT_IDEIO_48BIT) + if(drv->lba48mode){ + int i; + ret = 0; + for(i=0;i<6;i++){ + ret <<= 8; + ret |= drv->lba48[5-i]; + } + }else +#endif + { + if (!(drv->dr & IDEDEV_LBA)) { + ret = drv->cy; + ret *= drv->surfaces; + ret += drv->hd; + ret *= drv->sectors; + ret += (drv->sn - 1); + } + else { + ret = drv->sn; + ret |= (drv->cy << 8); + ret |= (drv->hd << 24); + } + } + return(ret); +} + +static void readsec(IDEDRV drv) { + + FILEPOS sec; + + if (drv->device != IDETYPE_HDD) { + goto read_err; + } + sec = getcursec(drv); + //TRACEOUT(("readsec->drv %d sec %x cnt %d thr %d", + // drv->sxsidrv, sec, drv->mulcnt, drv->multhr)); + if (sxsi_read(drv->sxsidrv, sec, drv->buf, 512)) { + TRACEOUT(("read error!")); + goto read_err; + } + drv->bufdir = IDEDIR_IN; + drv->buftc = IDETC_TRANSFEREND; + drv->bufpos = 0; + drv->bufsize = 512; + // READはI/Oポートで読み取るデータが準備できたら割り込み + if (1) { + drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; + drv->error = 0; + if(drv->mulcnt == 0){ // READ MULTIPLEではブロック単位で割り込み + if(ideio.rwait > 0){ + drv->status |= IDESTAT_BSY; + drv->status &= ~IDESTAT_DRQ; + setdintr(drv, 0, 0, ideio.rwait); + }else{ + setintr(drv); + } + //setintr(drv); + } + } + drv->mulcnt++; + if(drv->mulcnt >= drv->multhr){ + drv->mulcnt = 0; + } + return; + +read_err: + cmdabort(drv); +} + +static void writeinit(IDEDRV drv) { + if (drv->device == IDETYPE_NONE) { + goto write_err; + } + + drv->bufdir = IDEDIR_OUT; + drv->buftc = IDETC_TRANSFEREND; + drv->bufpos = 0; + drv->bufsize = 512; + + if (1) { + drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; + drv->error = 0; + } + return; + +write_err: + cmdabort(drv); +} + +static void writesec(IDEDRV drv) { + + if (drv->device == IDETYPE_NONE) { + goto write_err; + } + + drv->bufdir = IDEDIR_OUT; + drv->buftc = IDETC_TRANSFEREND; + drv->bufpos = 0; + drv->bufsize = 512; + + // WRITEはデータ書き込みが完了したら割り込み + drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; + drv->error = 0; + drv->mulcnt++; + if(drv->mulcnt >= drv->multhr){ + drv->mulcnt = 0; + } + if(drv->mulcnt == 0){ // WRITE MULTIPLEの時はブロック書き込み完了時に割り込み -> 最後の割り込みはideio_w16()内に存在 + if(ideio.wwait > 0){ + drv->status |= IDESTAT_BSY; + drv->status &= ~IDESTAT_DRQ; + setdintr(drv, 0, 0, ideio.wwait); + }else{ + setintr(drv); + } + } + return; + +write_err: + cmdabort(drv); +} + + +// ---- + +static void IOOUTCALL ideio_o430(UINT port, REG8 dat) { + + TRACEOUT(("ideio setbank%d %.2x [%.4x:%.8x]", + (port >> 1) & 1, dat, CPU_CS, CPU_EIP)); +#if defined(NP2_WIN) + atapi_dataread_asyncwait(INFINITE); +#endif + + if (!(dat & 0x80)) { + //char buf[100] = {0}; + if ((port >> 1) & 1) { + // 432h + ideio.bank[(port >> 1) & 1] = dat & 0x71; + } + else { + // 430h + ideio.bank[(port >> 1) & 1] = dat & 0x71; + } + //sprintf(buf, "0x%x¥n", dat); + //OutputDebugStringA(buf); + } + + // XXX: WORKAROUND for WinNT4.0 正常な接続フラグに書き戻す + if(mem[0x05bb]){ + mem[0x05ba] = mem[0x05bb]; + mem[0x05bb] = 0; + } +} + +static REG8 IOINPCALL ideio_i430(UINT port) { + + UINT bank; + REG8 ret; + + bank = (port >> 1) & 1; + ret = ideio.bank[bank]; + if ((port >> 1) & 1) { + // 432h + } + else { + // 430h + int compmode = (sxsi_getdevtype(0)!=SXSIDEV_CDROM && sxsi_getdevtype(1)!=SXSIDEV_CDROM && sxsi_getdevtype(2)==SXSIDEV_CDROM && sxsi_getdevtype(3)!=SXSIDEV_CDROM); // 旧機種互換モード? + IDEDEV dev; + dev = getidedev(); + // + if(dev){ + ret = (compmode ? 0 : 1); + // + // Win2000はbit6が1の時スレーブデバイスを見に行く + // + if (dev->drv[1].device != IDETYPE_NONE) { + ret |= 0x40; + } + } + } + ideio.bank[bank] = ret & (~0x80); + TRACEOUT(("ideio getbank%d %.2x [%.4x:%.8x]", + (port >> 1) & 1, ret, CPU_CS, CPU_EIP)); + return(ret & 0x7f); +} + + + +// ---- + +static void IOOUTCALL ideio_o433(UINT port, REG8 dat) { + +} + +static REG8 IOINPCALL ideio_i433(UINT port) { + + UINT bank; + REG8 ret; + + bank = (port >> 1) & 1; + ret = (ideio.bank[bank] & 0x1) ? 0x2 : 0x0; + + if(ret == 0x2 && ideio.dev[1].drv[0].device==IDETYPE_NONE && ideio.dev[1].drv[1].device==IDETYPE_NONE){ + ret = 0; + } + //OutputDebugStringA("IN 433h¥n"); + return(ret); +} + +static void IOOUTCALL ideio_o435(UINT port, REG8 dat) { + +} + +static REG8 IOINPCALL ideio_i435(UINT port) { + + return(0x00); +} + + + +// ---- + +static void IOOUTCALL ideio_o642(UINT port, REG8 dat) { + + IDEDRV drv; + + drv = getidedrv(); + if (drv) { + drv->wp = dat; + TRACEOUT(("ideio set WP %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); + } + (void)port; +} + +static void IOOUTCALL ideio_o644(UINT port, REG8 dat) { + + IDEDRV drv; + + (void)port; + drv = getidedrv(); + if (drv) { + drv->sc = dat; +#if defined(SUPPORT_IDEIO_48BIT) + drv->lba48sc <<= 8; + drv->lba48sc |= dat; +#endif + TRACEOUT(("ideio set SC %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); + } + (void)port; +} + +static void IOOUTCALL ideio_o646(UINT port, REG8 dat) { + + IDEDRV drv; + + drv = getidedrv(); + if (drv) { + drv->sn = dat; +#if defined(SUPPORT_IDEIO_48BIT) + drv->lba48[3] = drv->lba48[0]; + drv->lba48[0] = dat; +#endif + TRACEOUT(("ideio set SN %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); + } + (void)port; +} + +static void IOOUTCALL ideio_o648(UINT port, REG8 dat) { + + IDEDRV drv; + + drv = getidedrv(); + if (drv) { + drv->cy &= 0xff00; + drv->cy |= dat; +#if defined(SUPPORT_IDEIO_48BIT) + drv->lba48[4] = drv->lba48[1]; + drv->lba48[1] = dat; +#endif + TRACEOUT(("ideio set CYL %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); + } + (void)port; +} + +static void IOOUTCALL ideio_o64a(UINT port, REG8 dat) { + + IDEDRV drv; + + drv = getidedrv(); + if (drv) { + drv->cy &= 0x00ff; + drv->cy |= dat << 8; +#if defined(SUPPORT_IDEIO_48BIT) + drv->lba48[5] = drv->lba48[2]; + drv->lba48[2] = dat; +#endif + TRACEOUT(("ideio set CYH %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); + } + (void)port; +} + +static void IOOUTCALL ideio_o64c(UINT port, REG8 dat) { + + IDEDEV dev; + UINT drvnum; + +#if defined(NP2_WIN) + atapi_dataread_asyncwait(INFINITE); +#endif + + dev = getidedev(); + if (dev == NULL) { + return; + } +#if defined(TRACE) + if ((dat & 0xf0) != 0xa0) { + TRACEOUT(("ideio set SDH illegal param? (%.2x)", dat)); + } +#endif + drvnum = (dat >> 4) & 1; + if(dev->drivesel != drvnum){ + //dev->drv[drvnum].status = dev->drv[drvnum].status & ~(IDESTAT_DRQ|IDESTAT_BSY); + //drvreset(&(dev->drv[drvnum])); + //dev->drv[drvnum].status = IDESTAT_DRDY | IDESTAT_DSC; + //dev->drv[drvnum].error = IDEERR_AMNF; + //if(!drvnum) dev->drv[drvnum].error |= IDEERR_BBK; + } + dev->drv[drvnum].dr = dat & 0xf0; +//#if defined(SUPPORT_IDEIO_48BIT) +// { +// SXSIDEV sxsi = sxsi_getptr(dev->drv[drvnum].sxsidrv); +// if(sxsi->totals > 65535*16*255){ +// dev->drv[drvnum].dr |= IDEDEV_LBA; +// } +// } +//#endif + dev->drv[drvnum].hd = dat & 0x0f; + dev->drivesel = drvnum; + TRACEOUT(("ideio set DRHD %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); + + (void)port; +} + +static void IOOUTCALL ideio_o64e(UINT port, REG8 dat) { + + IDEDRV drv, d; + IDEDEV dev; + int i; + +#if defined(NP2_WIN) + atapi_dataread_asyncwait(INFINITE); +#endif + + // execute device diagnostic + if (dat == 0x90) { + TRACEOUT(("ideio set cmd %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); + TRACEOUT(("ideio: execute device diagnostic")); + dev = getidedev(); + if (dev) { + for (i = 0; i < 2; i++) { + d = dev->drv + i; + drvreset(d); + d->error = 0x01; + if (dev->drv[i].device == IDETYPE_NONE) { + d->error = 0x00; + } + if (i == 0) { + if (dev->drv[1].device == IDETYPE_NONE) { + d->error |= 0x80; + } + } + } + } + return; + } + + drv = getidedrv(); + if (drv == NULL) { + return; + } + drv->cmd = dat; + TRACEOUT(("ideio set cmd %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); + switch(dat) { + case 0x00: // NOP + break; + case 0x08: // device reset + TRACEOUT(("ideio: device reset")); + drvreset(drv); + drv->error = 0x01; + dev = getidedev(); + if (dev) { + if (dev->drv[dev->drivesel].device == IDETYPE_NONE) { + drv->error = 0x00; + } + if (dev->drivesel == 0) { + if (dev->drv[1].device == IDETYPE_NONE) { + drv->error |= 0x80; + } + } + } + setintr(drv); + break; + + case 0x10: case 0x11: case 0x12: case 0x13: // recalibrate + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + TRACEOUT(("ideio: recalibrate")); + if (drv->device == IDETYPE_HDD) { + //drv->hd = 0x00; + //drv->sc = 0x00; + drv->cy = 0x0000; +#if defined(SUPPORT_IDEIO_48BIT) + drv->lba48[0] = drv->lba48[1] = drv->lba48[2] = drv->lba48[3] = drv->lba48[4] = drv->lba48[5] = 0; +#endif + //if (!(drv->dr & IDEDEV_LBA)) { + // drv->sn = 0x01; + //} + //else { + // drv->sn = 0x00; + //} + drv->status = IDESTAT_DRDY | IDESTAT_DSC; + drv->error = 0; + setintr(drv); + } + else { + cmdabort(drv); + } + break; + + case 0x20: // read (with retry) + case 0x21: // read + TRACEOUT(("ideio: read sector")); + if (drv->device == IDETYPE_HDD) { + drv->mulcnt = 0; + drv->multhr = 1; + readsec(drv); + } + else { + cmdabort(drv); + } + break; + + case 0x30: // write (with retry) + case 0x31: // write + TRACEOUT(("ideio: write sector")); + if (drv->device == IDETYPE_HDD) { + drv->mulcnt = 0; + drv->multhr = 1; + writeinit(drv); + } + else { + cmdabort(drv); + } + break; + case 0x40: // read verify(w) + case 0x41: // read verify(w/o) + drv->status = drv->status & ~IDESTAT_BSY; + setintr(drv); + break; + case 0x91: // INITIALIZE DEVICE PARAMETERS + TRACEOUT(("ideio: INITIALIZE DEVICE PARAMETERS dh=%x sec=%x", + drv->dr | drv->hd, drv->sc)); + if (drv->device == IDETYPE_HDD) { + drv->surfaces = drv->hd + 1; + drv->sectors = drv->sc; + drv->status &= ~(IDESTAT_BSY | IDESTAT_DRQ | IDESTAT_ERR | 0x20); + drv->status |= IDESTAT_DRDY; + setintr(drv); + } + else { + cmdabort(drv); + } + break; + + case 0xa0: // send packet + TRACEOUT(("ideio: packet")); + if (drv->device == IDETYPE_CDROM) { + drv->sc &= ~(IDEINTR_REL | IDEINTR_IO); + drv->sc |= IDEINTR_CD; + drv->status &= ~(IDESTAT_BSY | IDESTAT_DMRD | IDESTAT_SERV | IDESTAT_CHK); + drv->status |= IDESTAT_DRDY | IDESTAT_DRQ | IDESTAT_DSC; + drv->error = 0; + drv->bufpos = 0; + drv->bufsize = 12; + drv->bufdir = IDEDIR_OUT; + drv->buftc = IDETC_TRANSFEREND; + break; + } + cmdabort(drv); + break; + + case 0xa1: // identify packet device + TRACEOUT(("ideio: identify packet device")); + if (drv->device == IDETYPE_CDROM && setidentify(drv) == SUCCESS) { + drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; + drv->error = 0; + setintr(drv); + } + else { + cmdabort(drv); + } + break; + + case 0xb0: // SMART + cmdabort(drv); + break; + + case 0xc4: // read multiple + TRACEOUT(("ideio: read multiple")); +#if IDEIO_MULTIPLE_MAX > 0 + if (drv->device == IDETYPE_HDD) { + drv->mulcnt = 0; + drv->multhr = drv->mulmode; + readsec(drv); + break; + } +#endif + cmdabort(drv); + break; + + case 0xc5: // write multiple + TRACEOUT(("ideio: write multiple")); +#if IDEIO_MULTIPLE_MAX > 0 + if (drv->device == IDETYPE_HDD) { + drv->mulcnt = 0; + drv->multhr = drv->mulmode; + writeinit(drv); + break; + } +#endif + cmdabort(drv); + break; + + case 0xc6: // set multiple mode + TRACEOUT(("ideio: set multiple mode")); + if (drv->device == IDETYPE_HDD) { + switch(drv->sc) { +#if IDEIO_MULTIPLE_MAX > 0 + case 2: case 4: case 8: case 16: case 32: case 64: case 128: + if (drv->sc <= IDEIO_MULTIPLE_MAX) { + drv->mulmode = drv->sc; + setintr(drv); + break; + } + /*FALLTHROUGH*/ +#endif + default: + cmdabort(drv); + break; + } + } + else { + cmdabort(drv); + } + break; + + case 0xe0: // STANDBY IMMEDIATE + TRACEOUT(("ideio: STANDBY IMMEDIATE dr = %.2x", drv->dr)); + if(!(drv->status & IDESTAT_BSY)){ + setintr(drv); + } + //cmdabort(drv); + break; + + case 0xe1: // idle immediate + TRACEOUT(("ideio: idle immediate dr = %.2x", drv->dr)); + //必ず成功するはず + if(drv->status & IDESTAT_DRDY){ + drv->status = IDESTAT_DRDY | IDESTAT_DSC; + drv->error = 0; + setintr(drv); + }else{ + cmdabort(drv); + } + break; + + case 0xe5: // Check power mode + drv->sc = 0xff; + drv->status = drv->status & ~IDESTAT_BSY; + setintr(drv); + break; + + case 0xe7: // flush cache + TRACEOUT(("ideio: flush cache")); + if(!(drv->status & IDESTAT_BSY)){ + drv->status = IDESTAT_DRDY|IDESTAT_BSY; + setdintr2(drv, 0, 0, 20000); + } + drv->error = 0; + break; + + case 0xec: // identify device + TRACEOUT(("ideio: identify device")); + if (drv->device == IDETYPE_HDD && setidentify(drv) == SUCCESS) { + drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; + drv->error = 0; + setintr(drv); + } + else if (drv->device == IDETYPE_CDROM) { + drvreset(drv); + cmdabort(drv); + } + else{ + cmdabort(drv); + } + break; + + case 0xef: // set features + TRACEOUT(("ideio: set features reg = %.2x", drv->wp)); + if(drv->device == IDETYPE_CDROM){ + switch(drv->wp) { + //case 0x95: // Enable Media Status Notification + // ideio_mediastatusnotification[drv->sxsidrv] = 1; + // drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; + // drv->error = 0; + // break; + //case 0x31: // Disable Media Status Notification + // ideio_mediastatusnotification[drv->sxsidrv] = 0; + // drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; + // drv->error = 0; + // break; + default: + cmdabort(drv); + } + }else{ + switch(drv->wp) { + case 0x02: // Enable write cache + case 0x82: // Disable write cache + // nothing to do + drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; + drv->error = 0; + if(!(drv->status & IDESTAT_BSY)){ + setintr(drv); + } + break; + case 0x03: // Set transfer mode based on value in Sector Count register + drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ; + drv->error = 0; + if(!(drv->status & IDESTAT_BSY)){ + setintr(drv); + } + break; + default: + cmdabort(drv); + } + } + break; + + case 0xda: // GET MEDIA STATUS + TRACEOUT(("ideio: GET MEDIA STATUS dev=%d", drv->device)); + //if (ideio_mediastatusnotification[drv->sxsidrv]) { + // SXSIDEV sxsi; + // drv->status = IDESTAT_DRDY | IDESTAT_ERR; + // drv->error = 0; + // sxsi = sxsi_getptr(drv->sxsidrv); + // if ((sxsi == NULL) || !(sxsi->flag & SXSIFLAG_READY)) { + // drv->error |= 0x02; // No media + // }else if(ideio_mediachangeflag[drv->sxsidrv]){ + // drv->error |= IDEERR_MCNG; + // ideio_mediachangeflag[drv->sxsidrv] = 0; + // } + // setintr(drv); + //} + //else { + cmdabort(drv); + //} + break; + + case 0xde: // media lock + TRACEOUT(("ideio: media lock dev=%d", drv->device)); + if (drv->device == IDETYPE_HDD) { + cmdabort(drv); + } + else { + drv->status |= IDESTAT_DRDY; + drv->status &= ~(IDESTAT_BSY|IDESTAT_DWF|IDESTAT_DRQ|IDESTAT_ERR); + setintr(drv); + } + break; + + case 0xdf: // media unlock + TRACEOUT(("ideio: media unlock dev=%d", drv->device)); + if (drv->device == IDETYPE_HDD) { + cmdabort(drv); + } + else { + drv->status |= IDESTAT_DRDY; + drv->status &= ~(IDESTAT_BSY|IDESTAT_DWF|IDESTAT_DRQ|IDESTAT_ERR); + setintr(drv); + } + break; + + case 0xf8: // READ NATIVE MAX ADDRESS + TRACEOUT(("ideio: READ NATIVE MAX ADDRESS reg = %.2x", drv->wp)); + { + SXSIDEV sxsi; + sxsi = sxsi_getptr(drv->sxsidrv); + drv->sn = sxsi->totals & 0xff; + drv->cy = (sxsi->totals >> 8) & 0xffff; + drv->hd = (drv->hd & 0xf0) | ((sxsi->totals >> 24) & 0xf); + + if(!(drv->status & IDESTAT_BSY)){ + setintr(drv); + } + } + +#if defined(SUPPORT_IDEIO_48BIT) + case 0x24: // read EXT + TRACEOUT(("ideio: read sector EXT")); + if (drv->device == IDETYPE_HDD) { + drv->mulcnt = 0; + drv->multhr = 1; + drv->lba48mode = 1; + readsec(drv); + } + else { + cmdabort(drv); + } + break; + + case 0x34: // write EXT + TRACEOUT(("ideio: write sector EXT")); + if (drv->device == IDETYPE_HDD) { + drv->mulcnt = 0; + drv->multhr = 1; + drv->lba48mode = 1; + writeinit(drv); + } + else { + cmdabort(drv); + } + break; + case 0x42: // read EXT verify(w) + TRACEOUT(("ideio: read verify EXT")); + drv->status = drv->status & ~IDESTAT_BSY; + setintr(drv); + break; + + case 0x29: // read multiple EXT + TRACEOUT(("ideio: read multiple EXT")); +#if IDEIO_MULTIPLE_MAX > 0 + if (drv->device == IDETYPE_HDD) { + drv->mulcnt = 0; + drv->multhr = drv->mulmode; + drv->lba48mode = 1; + readsec(drv); + break; + } +#endif + cmdabort(drv); + break; + + case 0x39: // write multiple EXT + TRACEOUT(("ideio: write multiple EXT")); +#if IDEIO_MULTIPLE_MAX > 0 + if (drv->device == IDETYPE_HDD) { + drv->mulcnt = 0; + drv->multhr = drv->mulmode; + drv->lba48mode = 1; + writesec(drv); + break; + } +#endif + cmdabort(drv); + break; + + case 0xea: // flush cache EXT + TRACEOUT(("ideio: flush cache EXT")); + if(!(drv->status & IDESTAT_BSY)){ + drv->status = IDESTAT_DRDY|IDESTAT_BSY; + setdintr2(drv, 0, 0, 20000); + } + drv->error = 0; + break; + + case 0x27: // READ NATIVE MAX ADDRESS EXT + TRACEOUT(("ideio: READ NATIVE MAX ADDRESS EXT reg = %.2x", drv->wp)); + { + SXSIDEV sxsi; + sxsi = sxsi_getptr(drv->sxsidrv); + if(drv->ctrl & 0x80){ // HOB bit + drv->sn = (sxsi->totals >> 24) & 0xff; + drv->cy = (sxsi->totals >> 32) & 0xffff; + }else{ + drv->sn = sxsi->totals & 0xff; + drv->cy = (sxsi->totals >> 8) & 0xffff; + } + if(!(drv->status & IDESTAT_BSY)){ + setintr(drv); + } + } + //cmdabort(drv); + break; + +#endif + + default: + panic("ideio: unknown command %.2x", dat); + break; + } + (void)port; +} + +static void IOOUTCALL ideio_o74c(UINT port, REG8 dat) { + + IDEDEV dev; + REG8 modify; + + dev = getidedev(); + if (dev == NULL) { + return; + } + modify = dev->drv[0].ctrl ^ dat; + dev->drv[0].ctrl = dat; + dev->drv[1].ctrl = dat; + if (modify & IDECTRL_SRST) { + if (dat & IDECTRL_SRST) { + dev->drv[0].status = 0; + dev->drv[0].error = 0; + dev->drv[1].status = 0; + dev->drv[1].error = 0; + } + else { + drvreset(&dev->drv[0]); + if (dev->drv[0].device == IDETYPE_HDD) { + dev->drv[0].status = IDESTAT_DRDY | IDESTAT_DSC; + dev->drv[0].error = IDEERR_AMNF; + } + if (dev->drv[0].device == IDETYPE_CDROM) { + dev->drv[0].status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_ERR; + dev->drv[0].error = IDEERR_AMNF; + } + drvreset(&dev->drv[1]); + if (dev->drv[1].device == IDETYPE_HDD) { + dev->drv[1].status = IDESTAT_DRDY | IDESTAT_DSC; + dev->drv[1].error = IDEERR_AMNF; + } + if (dev->drv[1].device == IDETYPE_CDROM) { + dev->drv[1].status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_ERR; + dev->drv[1].error = IDEERR_AMNF; + } + } + } + TRACEOUT(("ideio interrupt %sable", (dat & IDECTRL_NIEN) ? "dis" : "en")); + TRACEOUT(("ideio devctrl %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP)); + (void)port; +} + +static void IOOUTCALL ideio_o74e(UINT port, REG8 dat) { + + TRACEOUT(("ideio %.4x,%.2x [%.4x:%.8x]", port, dat, CPU_CS, CPU_EIP)); + (void)port; + (void)dat; +} + + +// ---- + +static REG8 IOINPCALL ideio_i642(UINT port) { + + IDEDRV drv; + + (void)port; + + drv = getidedrv(); + if (drv) { + drv->status &= ~IDESTAT_ERR; + TRACEOUT(("ideio get error %.2x [%.4x:%.8x]", + drv->error, CPU_CS, CPU_EIP)); + return(drv->error); + } + else { + return(0xff); + } +} + +static REG8 IOINPCALL ideio_i644(UINT port) { + + IDEDRV drv; + + (void)port; + + drv = getidedrv(); + if (drv) { + UINT8 ret = drv->sc; + TRACEOUT(("ideio get SC %.2x [%.4x:%.8x]", drv->sc, CPU_CS, CPU_EIP)); + //if (drv->device == IDETYPE_CDROM && drv->cmd == 0xa0) { + // drv->sc = 7; // ???? + //} + return(ret); + } + else { + return(0xff); + } +} + +static REG8 IOINPCALL ideio_i646(UINT port) { + + IDEDRV drv; + + (void)port; + + drv = getidedrv(); + if (drv) { + TRACEOUT(("ideio get SN %.2x [%.4x:%.8x]", drv->sn, CPU_CS, CPU_EIP)); + return(drv->sn); + } + else { + return(0xff); + } +} + +static REG8 IOINPCALL ideio_i648(UINT port) { + + IDEDRV drv; + + (void)port; + + drv = getidedrv(); + if (drv) { + TRACEOUT(("ideio get CYL %.4x [%.4x:%.8x]", drv->cy, CPU_CS, CPU_EIP)); + return((UINT8)drv->cy); + } + else { + return(0xff); + } +} + +static REG8 IOINPCALL ideio_i64a(UINT port) { + + IDEDRV drv; + + (void)port; + + drv = getidedrv(); + if (drv) { + TRACEOUT(("ideio get CYH %.4x [%.4x:%.8x]", drv->cy, CPU_CS, CPU_EIP)); + return((REG8)(drv->cy >> 8)); + } + else { + return(0xff); + } +} + +static REG8 IOINPCALL ideio_i64c(UINT port) { + + IDEDRV drv; + REG8 ret; + + (void)port; + + drv = getidedrv(); + if (drv) { + ret = drv->dr | drv->hd; + TRACEOUT(("ideio get DRHD %.2x [%.4x:%.8x]", ret, CPU_CS, CPU_EIP)); + return(ret); + } + else { + return(0xff); + } +} + +static REG8 IOINPCALL ideio_i64e(UINT port) { + + IDEDRV drv; + + (void)port; + + drv = getidedrv(); + if (drv) { + TRACEOUT(("ideio status %.2x [%.4x:%.8x]", + drv->status, CPU_CS, CPU_EIP)); + if (!(drv->ctrl & IDECTRL_NIEN)) { + TRACEOUT(("ideio: resetirq")); + pic_resetirq(IDE_IRQ); + if (ideio.bios != IDETC_BIOS) { + mem[MEMB_DISK_INTH] &= ~0x01; // エミュレーションIDE BIOSなら代理で下ろす + } + } + return(drv->status); + } + else { + return(0xff); + } +} + +static REG8 IOINPCALL ideio_i74c(UINT port) { + + IDEDRV drv; + + (void)port; + + drv = getidedrv(); + if (drv) { + TRACEOUT(("ideio alt status %.2x [%.4x:%.8x]", + drv->status, CPU_CS, CPU_EIP)); + return(drv->status); + } + else { + return(0xff); + } +} + +static REG8 IOINPCALL ideio_i74e(UINT port) { + + IDEDEV dev; + IDEDRV drv; + REG8 ret; + + dev = getidedev(); + drv = getidedrv(); + ret = 0xc0; + ret |= (~(drv->hd) & 0x0f) << 2; + if (dev->drivesel == 0) { + ret |= 2; /* master */ + } else { + ret |= 1; /* slave */ + } + return ret; +} + +static REG8 IOINPCALL ideio_i1e8e(UINT port) { + if((CPU_RAM_D000 & 0x1c00) == 0x1c00){ + return(0x81); + } + return(0x80); +} + +static void IOOUTCALL ideio_o1e8e(UINT port, REG8 dat) { + switch(dat){ + case 0x00: + case 0x80: + TRACEOUT(("remove RAM on 0xDA000-DBFFF but ignore")); + //CPU_RAM_D000 |= 0x0000; + break; + case 0x81: + TRACEOUT(("connect RAM on 0xDA000-DBFFF")); + CPU_RAM_D000 |= 0x1c00; + break; + default: + break; + } +} + + +// ---- data + +void IOOUTCALL ideio_w16(UINT port, REG16 value) { + + IDEDEV dev; + IDEDRV drv; + UINT8 *p; + FILEPOS sec; + + dev = getidedev(); + drv = getidedrv(); + if ((drv != NULL) && + (drv->status & IDESTAT_DRQ) && (drv->bufdir == IDEDIR_OUT)) { + p = drv->buf + drv->bufpos; + p[0] = (UINT8)value; + p[1] = (UINT8)(value >> 8); + //TRACEOUT(("ide-data send %.4x (%.4x) [%.4x:%.8x]", + // value, drv->bufpos, CPU_CS, CPU_EIP)); + drv->bufpos += 2; + if (drv->bufpos >= drv->bufsize) { + drv->status &= ~IDESTAT_DRQ; + switch(drv->cmd) { + case 0x30: + case 0x31: + case 0x34: + case 0xc5: + case 0x39: + drv->status |= IDESTAT_BSY; + sec = getcursec(drv); + //TRACEOUT(("writesec->drv %d sec %x cnt %d thr %d", + // drv->sxsidrv, sec, drv->mulcnt, drv->multhr)); + if (sxsi_write(drv->sxsidrv, sec, drv->buf, drv->bufsize)) { + TRACEOUT(("write error!")); + cmdabort(drv); + break; + } + incsec(drv); +#if defined(SUPPORT_IDEIO_48BIT) + if(drv->lba48mode){ + drv->lba48sc--; + drv->sc = (UINT8)drv->lba48sc; + if (drv->lba48sc) { + writesec(drv); + }else{ + // セクタ書き込み完了 + if(ideio.wwait > 0){ + setdintr2(drv, 0, 0, ideio.wwait); + }else{ + setintr(drv); + drv->status &= ~(IDESTAT_BSY); + } + drv->sc = 0; + drv->lba48mode = 0; + } + }else +#endif + { + drv->sc--; + if (drv->sc) { + writesec(drv); + }else{ + // セクタ書き込み完了 + if(ideio.wwait > 0){ + setdintr2(drv, 0, 0, ideio.wwait); + }else{ + setintr(drv); + drv->status &= ~(IDESTAT_BSY); + } + } + } + break; + + case 0xa0: + TRACEOUT(("ideio: execute atapi packet command")); + atapicmd_a0(drv); + break; + } + } + } + (void)port; +} + +REG16 IOINPCALL ideio_r16(UINT port) { + + IDEDRV drv; + REG16 ret; + UINT8 *p; + + (void)port; + + drv = getidedrv(); + if (drv == NULL) { + return(0xff); + } + ret = 0; + if ((drv->status & IDESTAT_DRQ) && (drv->bufdir == IDEDIR_IN)) { + p = drv->buf + drv->bufpos; + ret = p[0] + (p[1] << 8); + //TRACEOUT(("ide-data recv %.4x (%.4x) [%.4x:%.8x]", + // ret, drv->bufpos, CPU_CS, CPU_EIP)); + drv->bufpos += 2; + if (drv->bufpos >= drv->bufsize) { + drv->status &= ~IDESTAT_DRQ; + switch(drv->cmd) { + case 0x20: + case 0x21: + case 0x24: + case 0xc4: + case 0x29: + incsec(drv); +#if defined(SUPPORT_IDEIO_48BIT) + if(drv->lba48mode){ + drv->lba48sc--; + drv->sc = (UINT8)drv->lba48sc; + if (drv->lba48sc) { + readsec(drv); + }else{ + // 読み取り終わり + drv->lba48mode = 0; + } + }else +#endif + { + drv->sc--; + if (drv->sc) { + readsec(drv); + }else{ + // 読み取り終わり + } + } + break; + + case 0xa0: + if (drv->status & IDESTAT_BSY) { + break; + } + if (drv->buftc == IDETC_ATAPIREAD) { + atapi_dataread(drv); + break; + } + drv->sc = IDEINTR_IO | IDEINTR_CD; + drv->status &= ~(IDESTAT_BSY | IDESTAT_SERV | IDESTAT_CHK | IDESTAT_DRQ); // clear DRQ bit np21w ver0.86 rev38 + drv->status |= IDESTAT_DRDY | IDESTAT_DSC; + drv->error = 0; + setintr(drv); + break; + } + } + } + return(ret); +} + + +// ---- + +#if 1 +static SINT32 cdda_softvolume_L = 0; +static SINT32 cdda_softvolume_R = 0; +static SINT32 cdda_softvolumereg_L = 0xff; +static SINT32 cdda_softvolumereg_R = 0xff; +static BRESULT SOUNDCALL playdevaudio(IDEDRV drv, SINT32 *pcm, UINT count) { + + SXSIDEV sxsi; + UINT r; +const UINT8 *ptr; + SINT sampl; + SINT sampr; + SINT32 buf_l; + SINT32 buf_r; + SINT32 buf_count; + SINT32 samplen_n; + SINT32 samplen_d; +static SINT32 sampcount2_n = 0; + SINT32 sampcount2_d; + UINT mute = 0; + + samplen_n = soundcfg.rate; + samplen_d = 44100; + //if(samplen_n > samplen_d){ + // // XXX: サンプリングレートが大きい場合のオーバーフロー対策・・・ + // samplen_n /= 100; + // samplen_d /= 100; + //} + //if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_MATE_X_PCM || g_nSoundID == SOUNDID_PC_9801_86_WSS || g_nSoundID == SOUNDID_WAVESTAR || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ + // if(cdda_softvolumereg_L != cs4231.devvolume[0x32]){ + // cdda_softvolumereg_L = cs4231.devvolume[0x32]; + // if(cdda_softvolumereg_L & 0x80){ // CD L Mute + // cdda_softvolume_L = 0; + // }else{ + // cdda_softvolume_L = ((~cdda_softvolumereg_L) & 0x1f); // CD L Volume + // } + // } + // if(cdda_softvolumereg_R != cs4231.devvolume[0x33]){ + // cdda_softvolumereg_R = cs4231.devvolume[0x33]; + // if(cdda_softvolumereg_R & 0x80){ // CD R Mute + // cdda_softvolume_R = 0; + // }else{ + // cdda_softvolume_R = ((~cdda_softvolumereg_R) & 0x1f); // CD R Volume + // } + // } + //}else{ + cdda_softvolume_L = 0x1f; + cdda_softvolume_R = 0x1f; + cdda_softvolumereg_L = 0; + cdda_softvolumereg_R = 0; + //} + + sxsi = sxsi_getptr(drv->sxsidrv); + if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) || + (!(sxsi->flag & SXSIFLAG_READY))) { + drv->daflag = 0x14; + return(FAILURE); + } + while(count) { + r = MIN(count, drv->dabufrem * samplen_n / samplen_d); + if (r) { + count -= r; + ptr = drv->dabuf + 2352 - (drv->dabufrem * 4); + drv->dabufrem -= r * samplen_d / samplen_n; + if(samplen_n < samplen_d){ + //sampcount2_n = 0; + sampcount2_d = samplen_d; + buf_l = buf_r = buf_count = 0; + do { + sampl = ((SINT8)ptr[1] << 8) + ptr[0]; + sampr = ((SINT8)ptr[3] << 8) + ptr[2]; + ptr += 4; + sampcount2_n += samplen_n; + buf_l += (SINT)((int)(sampl)*((int)np2cfg.davolume * np2cfg.vol_master / 100)*cdda_softvolume_L/255/31); + buf_r += (SINT)((int)(sampr)*((int)np2cfg.davolume * np2cfg.vol_master / 100)*cdda_softvolume_R/255/31); + buf_count++; + if(sampcount2_n > sampcount2_d){ + pcm[0] += buf_l / buf_count; + pcm[1] += buf_r / buf_count; + //pcm[0] += (SINT)((int)(sampl)*((int)np2cfg.davolume * np2cfg.vol_master / 100)/255); + //pcm[1] += (SINT)((int)(sampr)*((int)np2cfg.davolume * np2cfg.vol_master / 100)/255); + pcm += 2 * (sampcount2_n / sampcount2_d); + --r; + sampcount2_n = sampcount2_n % sampcount2_d; + buf_l = buf_r = buf_count = 0; + } + } while(r > 0); + }else{ + sampcount2_n = samplen_n; + sampcount2_d = samplen_d; + do { + sampl = ((SINT8)ptr[1] << 8) + ptr[0]; + sampr = ((SINT8)ptr[3] << 8) + ptr[2]; + pcm[0] += (SINT)((int)(sampl)*((int)np2cfg.davolume * np2cfg.vol_master / 100)*cdda_softvolume_L/255/31); + pcm[1] += (SINT)((int)(sampr)*((int)np2cfg.davolume * np2cfg.vol_master / 100)*cdda_softvolume_L/255/31); + sampcount2_n -= sampcount2_d; + if(sampcount2_n <= 0){ + sampcount2_n += samplen_n; + ptr += 4; + } + pcm += 2; + } while(--r); + } + } + if (count == 0) { + break; + } + if (drv->dalength == 0) { + drv->daflag = 0x13; + return(FAILURE); + } + if(np2cfg.cddtskip){ + CDTRK trk; + UINT tracks; + trk = sxsicd_gettrk(sxsi, &tracks); + r = tracks; + while(r) { + r--; + if (trk[r].pos <= drv->dacurpos) { + break; + } + } + if(trk[r].adr_ctl!=TRACKTYPE_AUDIO){ + if(drv->dacurpos != 0){ + // オーディオトラックでない場合は強制的に次に飛ばす + if(r==tracks-1){ + drv->dacurpos = trk[0].pos; + }else{ + drv->dacurpos = trk[r+1].pos; + } + } + mute = 1; + } + } + if(mute){ + memset(drv->dabuf, 0, sizeof(drv->dabuf)); + }else{ + if (sxsicd_readraw(sxsi, drv->dacurpos, drv->dabuf) != SUCCESS) { + drv->daflag = 0x14; + return(FAILURE); + } + } + drv->dalength--; + drv->dacurpos++; + drv->dabufrem = sizeof(drv->dabuf) / 4; + } + return(SUCCESS); +} + +static void SOUNDCALL playaudio(void *hdl, SINT32 *pcm, UINT count) { + + UINT bit; + IDEDRV drv; + + bit = ideio.daplaying; + if (!bit) { + return; + } + if (bit & 4) { + drv = ideio.dev[1].drv + 0; + if (playdevaudio(drv, pcm, count) != SUCCESS) { + bit = bit & (~4); + } + } + ideio.daplaying = bit; +} +#endif + +// ---- + +static void devinit(IDEDRV drv, REG8 sxsidrv) { + + SXSIDEV sxsi; + + ZeroMemory(drv, sizeof(_IDEDRV)); + drv->sxsidrv = sxsidrv; + //drv->dr = 0xa0; + sxsi = sxsi_getptr(sxsidrv); + if ((sxsi != NULL) && (np2cfg.idetype[sxsidrv] == SXSIDEV_HDD) && + (sxsi->devtype == SXSIDEV_HDD) && (sxsi->flag & SXSIFLAG_READY)) { + drv->status = IDESTAT_DRDY | IDESTAT_DSC; + drv->error = IDEERR_AMNF; + drv->device = IDETYPE_HDD; + drv->surfaces = sxsi->surfaces; + drv->sectors = sxsi->sectors; + drv->mulmode = IDEIO_MULTIPLE_MAX; + } + else if ((sxsi != NULL) && (np2cfg.idetype[sxsidrv] == SXSIDEV_CDROM) && + (sxsi->devtype == SXSIDEV_CDROM)) { + drv->device = IDETYPE_CDROM; + drvreset(drv); + drv->error = 0; + drv->media = IDEIO_MEDIA_EJECTABLE; + if (sxsi->flag & SXSIFLAG_READY) { + drv->media |= (IDEIO_MEDIA_CHANGED|IDEIO_MEDIA_LOADED); + } + drv->daflag = 0x15; + drv->damsfbcd = 0; + } + else { + drv->status = IDESTAT_ERR; + drv->error = IDEERR_TR0; + drv->device = IDETYPE_NONE; + } +//#if defined(SUPPORT_IDEIO_48BIT) +// if(sxsi->totals > 65535*16*255){ +// drv->dr |= IDEDEV_LBA; +// } +//#endif + //memset(ideio_mediastatusnotification, 0, sizeof(ideio_mediastatusnotification)); + //memset(ideio_mediachangeflag, 0, sizeof(ideio_mediachangeflag)); +} + +void ideio_initialize(void) { + atapi_initialize(); +} + +void ideio_deinitialize(void) { + atapi_deinitialize(); +} + +void ideio_basereset() { + REG8 i; + IDEDRV drv; + + for (i=0; i<4; i++) { + drv = ideio.dev[i >> 1].drv + (i & 1); + devinit(drv, i); + } + + if (pccore.hddif & PCHDD_IDE) { + int compmode = (sxsi_getdevtype(0)!=SXSIDEV_CDROM && sxsi_getdevtype(1)!=SXSIDEV_CDROM && sxsi_getdevtype(2)==SXSIDEV_CDROM && sxsi_getdevtype(3)!=SXSIDEV_CDROM); // 旧機種互換モード? + + // WORKAROUND for WinNT4.0 + if(compmode){ + mem[0x05ba] = (sxsi_getdevtype(3)==SXSIDEV_HDD ? 0x8 : 0x0)|(sxsi_getdevtype(2)==SXSIDEV_HDD ? 0x4 : 0x0)| + (sxsi_getdevtype(1)==SXSIDEV_HDD ? 0x2 : 0x0)|(sxsi_getdevtype(0)==SXSIDEV_HDD ? 0x1 : 0x0); + }else{ + mem[0x05ba] = (sxsi_getdevtype(3)!=SXSIDEV_NC ? 0x8 : 0x0)|(sxsi_getdevtype(2)!=SXSIDEV_NC ? 0x4 : 0x0)| + (sxsi_getdevtype(1)!=SXSIDEV_NC ? 0x2 : 0x0)|(sxsi_getdevtype(0)!=SXSIDEV_NC ? 0x1 : 0x0); + } + } +} +void ideio_reset(const NP2CFG *pConfig) { + REG8 i; + + OEMCHAR path[MAX_PATH]; + FILEH fh; + OEMCHAR tmpbiosname[16]; + UINT8 useidebios; + UINT32 biosaddr; + + ZeroMemory(&ideio, sizeof(ideio)); + + ideio_basereset(); + + ideio.rwait = np2cfg.iderwait; + ideio.wwait = np2cfg.idewwait; + ideio.bios = IDETC_NOBIOS; + + if(pccore.hddif & PCHDD_IDE){ + if(pConfig->idebaddr){ + biosaddr = (UINT32)pConfig->idebaddr << 12; + useidebios = np2cfg.idebios && np2cfg.usebios; + if(useidebios && np2cfg.autoidebios){ + SXSIDEV sxsi; + for (i=0; i<4; i++) { + sxsi = sxsi_getptr(i); + if ((sxsi != NULL) && (np2cfg.idetype[i] == SXSIDEV_HDD) && + (sxsi->devtype == SXSIDEV_HDD) && (sxsi->flag & SXSIFLAG_READY)) { + if(sxsi->surfaces != 8 || sxsi->sectors != 17){ + TRACEOUT(("Incompatible CHS parameter detected. IDE BIOS automatically disabled.")); + useidebios = 0; + } + } + } + } + if(useidebios){ + _tcscpy(tmpbiosname, OEMTEXT("ide.rom")); + getbiospath(path, tmpbiosname, NELEMENTS(path)); + fh = file_open_rb(path); + if (fh == FILEH_INVALID) { + _tcscpy(tmpbiosname, OEMTEXT("d8000.rom")); + getbiospath(path, tmpbiosname, NELEMENTS(path)); + fh = file_open_rb(path); + } + if (fh == FILEH_INVALID) { + _tcscpy(tmpbiosname, OEMTEXT("bank3.bin")); + getbiospath(path, tmpbiosname, NELEMENTS(path)); + fh = file_open_rb(path); + } + if (fh == FILEH_INVALID) { + _tcscpy(tmpbiosname, OEMTEXT("bios9821.rom")); + getbiospath(path, tmpbiosname, NELEMENTS(path)); + fh = file_open_rb(path); + } + }else{ + fh = FILEH_INVALID; + } + if (fh != FILEH_INVALID) { + // IDE BIOS + if (file_read(fh, mem + biosaddr, 0x2000) == 0x2000) { + ideio.bios = IDETC_BIOS; + TRACEOUT(("load ide.rom")); + _tcscpy(ideio.biosname, tmpbiosname); + CPU_RAM_D000 &= ~(0x3 << 8); + }else{ + //CopyMemory(mem + biosaddr, idebios, sizeof(idebios)); + TRACEOUT(("use simulate ide.rom")); + } + file_close(fh); + }else{ + //CopyMemory(mem + biosaddr, idebios, sizeof(idebios)); + TRACEOUT(("use simulate ide.rom")); + } + } + } + + (void)pConfig; +} + +void ideio_bindCDDA(void) { + if (pccore.hddif & PCHDD_IDE) { + sound_streamregist(NULL, (SOUNDCB)playaudio); + } +} + +void ideio_bind(void) { + + if (pccore.hddif & PCHDD_IDE) { + ideio_bindCDDA(); + + iocore_attachout(0x0430, ideio_o430); + iocore_attachout(0x0432, ideio_o430); + iocore_attachinp(0x0430, ideio_i430); + iocore_attachinp(0x0432, ideio_i430); + + iocore_attachout(0x0642, ideio_o642); + iocore_attachout(0x0644, ideio_o644); + iocore_attachout(0x0646, ideio_o646); + iocore_attachout(0x0648, ideio_o648); + iocore_attachout(0x064a, ideio_o64a); + iocore_attachout(0x064c, ideio_o64c); + iocore_attachout(0x064e, ideio_o64e); + iocore_attachinp(0x0642, ideio_i642); + iocore_attachinp(0x0644, ideio_i644); + iocore_attachinp(0x0646, ideio_i646); + iocore_attachinp(0x0648, ideio_i648); + iocore_attachinp(0x064a, ideio_i64a); + iocore_attachinp(0x064c, ideio_i64c); + iocore_attachinp(0x064e, ideio_i64e); + + iocore_attachout(0x074c, ideio_o74c); + iocore_attachout(0x074e, ideio_o74e); + iocore_attachinp(0x074c, ideio_i74c); + iocore_attachinp(0x074e, ideio_i74e); + + iocore_attachout(0x1e8e, ideio_o1e8e); // 一部IDE BIOSはこれがないと起動時にフリーズしたりシリンダ数が0になる + iocore_attachinp(0x1e8e, ideio_i1e8e); // 一部IDE BIOSはこれがないと起動時にフリーズしたりシリンダ数が0になる + + iocore_attachout(0x0433, ideio_o433); + iocore_attachinp(0x0433, ideio_i433); + iocore_attachout(0x0435, ideio_o435); + iocore_attachinp(0x0435, ideio_i435); + } +} + +void ideio_notify(REG8 sxsidrv, UINT action) { + + SXSIDEV sxsi; + IDEDRV drv; + REG8 i; + + sxsi = sxsi_getptr(sxsidrv); + if ((sxsi == NULL) + || (!(sxsi->flag & SXSIFLAG_READY)) + || (sxsi->devtype != SXSIDEV_CDROM)) { + return; + } + + for (i=0; i<4; i++) { + drv = ideio.dev[i >> 1].drv + (i & 1); + if ((drv != NULL) && (drv->sxsidrv == sxsidrv)) { + goto do_notify; + } + } + return; + +do_notify: + switch(action) { + case 1: + drv->media |= (IDEIO_MEDIA_CHANGED|IDEIO_MEDIA_LOADED); + if (sxsi->mediatype & SXSIMEDIA_DATA) + drv->media |= IDEIO_MEDIA_DATA; + if (sxsi->mediatype & SXSIMEDIA_AUDIO) + drv->media |= IDEIO_MEDIA_AUDIO; + break; + + case 0: + drv->media &= ~(IDEIO_MEDIA_LOADED|IDEIO_MEDIA_COMBINE); + break; + } +} + +void ideio_mediachange(REG8 sxsidrv) { + + //SXSIDEV sxsi; + //IDEDRV drv; + //REG8 i; + // + //sxsi = sxsi_getptr(sxsidrv); + //if ((sxsi == NULL) + // || (!(sxsi->flag & SXSIFLAG_READY)) + // || (sxsi->devtype != SXSIDEV_CDROM)) { + // return; + //} + + //for (i=0; i<4; i++) { + // drv = ideio.dev[i >> 1].drv + (i & 1); + // if ((drv != NULL) && (drv->sxsidrv == sxsidrv)) { + // break; + // } + //} + //if(i==4) return; + // + //drv->status |= IDESTAT_ERR; + //drv->error |= IDEERR_MCNG; + //setintr(drv); + //drv->error &= ~IDEERR_MCNG; // 一旦フラグクリア + //drv->media |= IDEIO_MEDIA_CHANGED; + //setintr(drv); + //ideio_mediachangeflag[sxsidrv] = 1; +} + +#endif /* SUPPORT_IDEIO */ + diff --git a/cbus/ideio.h b/cbus/ideio.h old mode 100755 new mode 100644 index 59b2a88b..995a9db6 --- a/cbus/ideio.h +++ b/cbus/ideio.h @@ -1,211 +1,211 @@ - -#define IDEIO_MULTIPLE_MAX 128 -#define IDEIO_BUFSIZE_MAX 4096 - -#define IDEIO_MEDIA_EJECTABLE (1 << 7) -#define IDEIO_MEDIA_PREVENT (1 << 6) -#define IDEIO_MEDIA_PERSIST (1 << 5) -// (1 << 4) -#define IDEIO_MEDIA_AUDIO (1 << 3) -#define IDEIO_MEDIA_DATA (1 << 2) -#define IDEIO_MEDIA_CHANGED (1 << 1) -#define IDEIO_MEDIA_LOADED (1 << 0) - -#define IDEIO_MEDIA_COMBINE (IDEIO_MEDIA_DATA|IDEIO_MEDIA_AUDIO) - -typedef struct { - UINT8 sxsidrv; - - UINT8 wp; - UINT8 dr; - UINT8 hd; - UINT8 sc; - UINT8 sn; - UINT16 cy; - - UINT8 cmd; - UINT8 status; - UINT8 error; - UINT8 ctrl; - - UINT8 device; - UINT8 surfaces; - UINT8 sectors; - UINT8 bufdir; - UINT8 buftc; - - // for ATA multiple mode - UINT8 mulcnt; - UINT8 multhr; - UINT8 mulmode; - - // for ATAPI - UINT8 media; - UINT8 sk; // sense key - UINT16 asc; // additional sense code (LSB) & qualifer (MSB) - - UINT32 sector; // アクセスセクタ (LBA) - UINT32 nsectors; // 総セクタ数 - UINT16 secsize; // セクタサイズ - UINT16 dmy; - - // buffer management - UINT bufpos; - UINT bufsize; - UINT8 buf[IDEIO_BUFSIZE_MAX]; - - // audio - UINT daflag; - UINT32 dacurpos; - UINT32 dalength; - UINT dabufrem; - UINT8 dabuf[2352]; - UINT8 davolume; - UINT8 damsfbcd; - -#if defined(SUPPORT_IDEIO_48BIT) - // 48-bit Address feature set - UINT8 lba48mode; // READ/WRITE with 48-bit LBA - UINT8 lba48[8]; // LBA (48-bit) - UINT16 lba48sc; // Sector Count (16-bit) -#endif -} _IDEDRV, *IDEDRV; - -typedef struct { - _IDEDRV drv[2]; - UINT drivesel; -} _IDEDEV, *IDEDEV; - -typedef struct { - UINT8 bank[2]; - UINT8 daplaying; - UINT8 padding; - UINT8 bios; - OEMCHAR biosname[16]; - UINT32 rwait; - UINT32 wwait; - UINT32 mwait; - _IDEDEV dev[2]; -} IDEIO; - -enum { - IDE_IRQ = 0x09, - - IDETYPE_NONE = 0, - IDETYPE_HDD = 1, - IDETYPE_CDROM = 2, - - IDEDIR_NONE = 0, - IDEDIR_OUT = 1, - IDEDIR_IN = 2, - - IDETC_TRANSFEREND = 0, - IDETC_ATAPIREAD = 1, - - IDETC_NOBIOS = 0, - IDETC_BIOS = 1 -}; - -// error -// bit7: Bad Block detected -// bit6: Data ECC error -// bit4: ID Not Found -// bit2: Aborted command -// bit1: Track0 Error -// bit0: Address Mark Not Found - -enum { - IDEERR_BBK = 0x80, - IDEERR_UNC = 0x40, - IDEERR_MCNG = 0x20, - IDEERR_IDNF = 0x10, - IDEERR_MCRQ = 0x08, - IDEERR_ABRT = 0x04, - IDEERR_TR0 = 0x02, - IDEERR_AMNF = 0x01 -}; - -// interrupt reason (sector count) -// bit7-3: tag -// bit2: bus release -// bit1: input/output -// bit0: command/data -// -enum { - IDEINTR_REL = 0x04, - IDEINTR_IO = 0x02, // 0: host->device, 1: device->host - IDEINTR_CD = 0x01 // 0: data, 1: command -}; - -// status -// bit7: Busy -// bit6: Drive Ready -// bit5: Drive Write Fault -// bit4: Drive Seek Complete -// bit3: Data Request -// bit2: Corrected data -// bit1: Index -// bit0: Error - -enum { - IDESTAT_BSY = 0x80, - IDESTAT_DRDY = 0x40, - IDESTAT_DWF = 0x20, - IDESTAT_DSC = 0x10, - IDESTAT_DRQ = 0x08, - IDESTAT_CORR = 0x04, - IDESTAT_INDX = 0x02, - IDESTAT_ERR = 0x01, - - // for ATAPI PACKET - IDESTAT_DMRD = 0x20, // DMA Ready - IDESTAT_SERV = 0x10, // Service - IDESTAT_CHK = 0x01 -}; - -// device/head -// bit6: LBA (for read/write sector(s)/multiple) -// bit4: master/slave device select - -enum { - IDEDEV_LBA = 0x40, - IDEDEV_DEV = 0x10 -}; - -// control -// bit2: Software Reset -// bit1: ~Interrupt Enable - -enum { - IDECTRL_SRST = 0x04, - IDECTRL_NIEN = 0x02 -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern IDEIO ideio; - -void IOOUTCALL ideio_w16(UINT port, REG16 value); -REG16 IOINPCALL ideio_r16(UINT port); -void IOOUTCALL ideio_w32(UINT port, UINT32 value); -UINT32 IOINPCALL ideio_r32(UINT port); - -void ideio_initialize(void); -void ideio_deinitialize(void); -void ideio_basereset(); -void ideio_reset(const NP2CFG *pConfig); -void ideio_bindCDDA(void); -void ideio_bind(void); -void ideio_notify(REG8 sxsidrv, UINT action); -void ideioint(NEVENTITEM item); -void ideio_mediachange(REG8 sxsidrv); - -void ideio_setcursec(FILEPOS pos); - -#ifdef __cplusplus -} -#endif - + +#define IDEIO_MULTIPLE_MAX 128 +#define IDEIO_BUFSIZE_MAX 4096 + +#define IDEIO_MEDIA_EJECTABLE (1 << 7) +#define IDEIO_MEDIA_PREVENT (1 << 6) +#define IDEIO_MEDIA_PERSIST (1 << 5) +// (1 << 4) +#define IDEIO_MEDIA_AUDIO (1 << 3) +#define IDEIO_MEDIA_DATA (1 << 2) +#define IDEIO_MEDIA_CHANGED (1 << 1) +#define IDEIO_MEDIA_LOADED (1 << 0) + +#define IDEIO_MEDIA_COMBINE (IDEIO_MEDIA_DATA|IDEIO_MEDIA_AUDIO) + +typedef struct { + UINT8 sxsidrv; + + UINT8 wp; + UINT8 dr; + UINT8 hd; + UINT8 sc; + UINT8 sn; + UINT16 cy; + + UINT8 cmd; + UINT8 status; + UINT8 error; + UINT8 ctrl; + + UINT8 device; + UINT8 surfaces; + UINT8 sectors; + UINT8 bufdir; + UINT8 buftc; + + // for ATA multiple mode + UINT8 mulcnt; + UINT8 multhr; + UINT8 mulmode; + + // for ATAPI + UINT8 media; + UINT8 sk; // sense key + UINT16 asc; // additional sense code (LSB) & qualifer (MSB) + + UINT32 sector; // アクセスセクタ (LBA) + UINT32 nsectors; // 総セクタ数 + UINT16 secsize; // セクタサイズ + UINT16 dmy; + + // buffer management + UINT bufpos; + UINT bufsize; + UINT8 buf[IDEIO_BUFSIZE_MAX]; + + // audio + UINT daflag; + UINT32 dacurpos; + UINT32 dalength; + UINT dabufrem; + UINT8 dabuf[2352]; + UINT8 davolume; + UINT8 damsfbcd; + +#if defined(SUPPORT_IDEIO_48BIT) + // 48-bit Address feature set + UINT8 lba48mode; // READ/WRITE with 48-bit LBA + UINT8 lba48[8]; // LBA (48-bit) + UINT16 lba48sc; // Sector Count (16-bit) +#endif +} _IDEDRV, *IDEDRV; + +typedef struct { + _IDEDRV drv[2]; + UINT drivesel; +} _IDEDEV, *IDEDEV; + +typedef struct { + UINT8 bank[2]; + UINT8 daplaying; + UINT8 padding; + UINT8 bios; + OEMCHAR biosname[16]; + UINT32 rwait; + UINT32 wwait; + UINT32 mwait; + _IDEDEV dev[2]; +} IDEIO; + +enum { + IDE_IRQ = 0x09, + + IDETYPE_NONE = 0, + IDETYPE_HDD = 1, + IDETYPE_CDROM = 2, + + IDEDIR_NONE = 0, + IDEDIR_OUT = 1, + IDEDIR_IN = 2, + + IDETC_TRANSFEREND = 0, + IDETC_ATAPIREAD = 1, + + IDETC_NOBIOS = 0, + IDETC_BIOS = 1 +}; + +// error +// bit7: Bad Block detected +// bit6: Data ECC error +// bit4: ID Not Found +// bit2: Aborted command +// bit1: Track0 Error +// bit0: Address Mark Not Found + +enum { + IDEERR_BBK = 0x80, + IDEERR_UNC = 0x40, + IDEERR_MCNG = 0x20, + IDEERR_IDNF = 0x10, + IDEERR_MCRQ = 0x08, + IDEERR_ABRT = 0x04, + IDEERR_TR0 = 0x02, + IDEERR_AMNF = 0x01 +}; + +// interrupt reason (sector count) +// bit7-3: tag +// bit2: bus release +// bit1: input/output +// bit0: command/data +// +enum { + IDEINTR_REL = 0x04, + IDEINTR_IO = 0x02, // 0: host->device, 1: device->host + IDEINTR_CD = 0x01 // 0: data, 1: command +}; + +// status +// bit7: Busy +// bit6: Drive Ready +// bit5: Drive Write Fault +// bit4: Drive Seek Complete +// bit3: Data Request +// bit2: Corrected data +// bit1: Index +// bit0: Error + +enum { + IDESTAT_BSY = 0x80, + IDESTAT_DRDY = 0x40, + IDESTAT_DWF = 0x20, + IDESTAT_DSC = 0x10, + IDESTAT_DRQ = 0x08, + IDESTAT_CORR = 0x04, + IDESTAT_INDX = 0x02, + IDESTAT_ERR = 0x01, + + // for ATAPI PACKET + IDESTAT_DMRD = 0x20, // DMA Ready + IDESTAT_SERV = 0x10, // Service + IDESTAT_CHK = 0x01 +}; + +// device/head +// bit6: LBA (for read/write sector(s)/multiple) +// bit4: master/slave device select + +enum { + IDEDEV_LBA = 0x40, + IDEDEV_DEV = 0x10 +}; + +// control +// bit2: Software Reset +// bit1: ~Interrupt Enable + +enum { + IDECTRL_SRST = 0x04, + IDECTRL_NIEN = 0x02 +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern IDEIO ideio; + +void IOOUTCALL ideio_w16(UINT port, REG16 value); +REG16 IOINPCALL ideio_r16(UINT port); +void IOOUTCALL ideio_w32(UINT port, UINT32 value); +UINT32 IOINPCALL ideio_r32(UINT port); + +void ideio_initialize(void); +void ideio_deinitialize(void); +void ideio_basereset(); +void ideio_reset(const NP2CFG *pConfig); +void ideio_bindCDDA(void); +void ideio_bind(void); +void ideio_notify(REG8 sxsidrv, UINT action); +void ideioint(NEVENTITEM item); +void ideio_mediachange(REG8 sxsidrv); + +void ideio_setcursec(FILEPOS pos); + +#ifdef __cplusplus +} +#endif + diff --git a/cbus/mpu98ii.c b/cbus/mpu98ii.c old mode 100755 new mode 100644 index 956bb36b..b1c1f3f8 --- a/cbus/mpu98ii.c +++ b/cbus/mpu98ii.c @@ -1,1241 +1,1241 @@ - -// emulation MPU-401 CPU Version 1.3 ('84/07/07) - -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#undef TRACEOUT -#define USE_TRACEOUT_VS -#ifdef USE_TRACEOUT_VS -static void trace_fmt_ex(const char *fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "\n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#else -#define TRACEOUT(s) (void)(s) -#endif -#endif /* 1 */ - -enum { - MIDI_STOP = 0xfc, - - MIDIIN_AVAIL = 0x80, - MIDIOUT_BUSY = 0x40, - - MPUMSG_TRACKDATAREQ = 0xf0, - MPUMSG_OVERFLOW = 0xf8, - MPUMSG_REQCOND = 0xf9, - MPUMSG_DATAEND = 0xfc, - MPUMSG_HCLK = 0xfd, - MPUMSG_ACK = 0xfe, - MPUMSG_SYS = 0xff, - - MIDITIMEOUTCLOCK = 3000, - MIDITIMEOUTCLOCK2 = 300 -}; - -enum { - MIDIE_STEP = 0x01, - MIDIE_EVENT = 0x02, - MIDIE_DATA = 0x04 -}; - -enum { - MPUCMDP_IDLE = 0x00, - MPUCMDP_STEP = 0x01, - MPUCMDP_CMD = 0x02, - MPUCMDP_REQ = 0x04, - MPUCMDP_FOLLOWBYTE = 0x08, - MPUCMDP_SHORT = 0x10, - MPUCMDP_LONG = 0x20, - MPUCMDP_INIT = 0x80 -}; - -enum { - MPUSYNCMODE_INT = 0x00, - MPUSYNCMODE_FSK = 0x01, - MPUSYNCMODE_MIDI = 0x02, - - MPUMETROMODE_ACC = 0x00, - MPUMETROMODE_OFF = 0x01, - MPUMETROMODE_ON = 0x02, - - MPUFLAG1_PLAY = 0x01, - MPUFLAG1_BENDERTOHOST = 0x08, - MPUFLAG1_THRU = 0x10, - MPUFLAG1_DATAINSTOP = 0x20, - MPUFLAG1_SENDME = 0x40, - MPUFLAG1_CONDUCTOR = 0x80, - - MPUFLAG2_RTAFF = 0x01, - MPUFLAG2_FSKRESO = 0x02, - MPUFLAG2_CLKTOHOST = 0x04, - MPUFLAG2_EXECLUTOHOST = 0x08, - MPUFLAG2_REFA = 0x10, - MPUFLAG2_REFB = 0x20, - MPUFLAG2_REFC = 0x40, - MPUFLAG2_REFD = 0x80 -}; - - - _MPU98II mpu98; - COMMNG cm_mpu98; - - -static const UINT8 mpuirqnum[4] = {3, 5, 6, 12}; - -static const UINT8 shortmsgleng[0x10] = { - 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 2, 2, 3, 1}; - -static const UINT8 hclk_step1[4][4] = {{0, 0, 0, 0}, {1, 0, 0, 0}, - {1, 0, 1, 0}, {1, 1, 1, 0}}; - -// XXX: 根拠なし とりあえず大きめの値にしておく -#define MPU98_WRITEBUFFER 2048 -static int mpu98_writecounter = 0; - - -static void makeintclock(void) { - - UINT32 l; - UINT curtempo; - - l = mpu98.tempo * 2 * mpu98.reltempo / 0x40; - if (l < 5 * 2) { - l = 5 * 2; - } - curtempo = l >> 1; - if (curtempo > 250) { - curtempo = 250; - } - mpu98.curtempo = curtempo; - if (!(mpu98.flag2 & MPUFLAG2_FSKRESO)) { - l *= mpu98.inttimebase; // *12 - } - mpu98.stepclock = (pccore.realclock * 5 / l); // /12 -} - -static void sethclk(REG8 data) { - - REG8 quarter; - int i; - - quarter = data >> 2; - if (!quarter) { - quarter = 64; - } - for (i=0; i<4; i++) { - mpu98.hclk_step[i] = quarter + hclk_step1[data & 3][i]; - } - mpu98.hclk_rem = 0; -} - -static void setdefaultcondition(void) { - - mpu98.recvevent = 0; - mpu98.remainstep = 0; - mpu98.intphase = 0; - mpu98.intreq = 0; - - ZeroMemory(&mpu98.cmd, sizeof(mpu98.cmd)); - ZeroMemory(mpu98.tr, sizeof(mpu98.tr)); - ZeroMemory(&mpu98.cond, sizeof(mpu98.cond)); - - mpu98.syncmode = MPUSYNCMODE_INT; - mpu98.metromode = MPUMETROMODE_OFF; - mpu98.flag1 = MPUFLAG1_THRU | MPUFLAG1_SENDME; - mpu98.flag2 = MPUFLAG2_RTAFF; - - mpu98.inttimebase = 120 / 24; - mpu98.tempo = 100; - mpu98.reltempo = 0x40; - makeintclock(); - mpu98.midipermetero = 12; - mpu98.meteropermeas = 8; - sethclk(240); - mpu98.acttr = 0x00; - mpu98.sendplaycnt = 0; - mpu98.accch = 0xffff; -} - -static void setrecvdata(REG8 data) { - - MPURECV *r; - - r = &mpu98.r; - if (r->cnt < MPU98_RECVBUFS) { - r->buf[(r->pos + r->cnt) & (MPU98_RECVBUFS - 1)] = data; - r->cnt++; - } -} - -static void sendmpushortmsg(const UINT8 *dat, UINT count) { - - UINT i; - COMMNG cm; - -#if 0 - if (!(mpu98.flag1 & MPUFLAG1_BENDERTOHOST)) { - switch(dat[0] >> 4) { - case 0x0a: - case 0x0d: - case 0x0e: - return; - - case 0x0b: - if (dat[1] < 0x40) { - return; - } - break; - } - } -#endif - cm = cm_mpu98; - for (i=0; iwrite(cm, dat[i]); - } -} - -static void sendmpulongmsg(const UINT8 *dat, UINT count) { - - UINT i; - COMMNG cm; - - cm = cm_mpu98; - for (i=0; iwrite(cm, dat[i]); - } -} - -static void sendmpureset(void) { - - UINT i; - UINT8 sMessage[3]; - - for (i=0; i<0x10; i++) { - sMessage[0] = (UINT8)(0xb0 + i); - sMessage[1] = 0x7b; - sMessage[2] = 0x00; - sendmpushortmsg(sMessage, 3); - } -} - -static void mpu98ii_int(void) { - - TRACEOUT(("int!")); - pic_setirq(mpu98.irqnum); - //// Sound Blaster 16 - //if(g_nSoundID == SOUNDID_SB16 || g_nSoundID == SOUNDID_PC_9801_86_SB16 || g_nSoundID == SOUNDID_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ - // pic_setirq(g_sb16.dmairq); - //} - //// PC-9801-118 - //if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ - // pic_setirq(10); - //} - //// WaveStar - //if(g_nSoundID == SOUNDID_WAVESTAR){ - // pic_setirq(10); - //} -} - -static void tr_step(void) { - - int i; - REG8 bit; - - if (mpu98.flag1 & MPUFLAG1_CONDUCTOR) { - if (mpu98.cond.step) { - mpu98.cond.step--; - } - } - for (i=0, bit=1; i<8; bit<<=1, i++) { - if (mpu98.acttr & bit) { - if (mpu98.tr[i].step) { - mpu98.tr[i].step--; - } - } - } -} - -static BOOL tr_nextsearch(void) { - - int i; - REG8 bit; - -tr_nextsearch_more: - if (mpu98.intphase == 1) { - if (mpu98.flag1 & MPUFLAG1_CONDUCTOR) { - if (!mpu98.cond.step) { - mpu98.intreq = MPUMSG_REQCOND; - mpu98.cond.phase |= MPUCMDP_STEP | MPUCMDP_CMD; - mpu98ii_int(); - return(TRUE); - } - } - mpu98.intphase = 2; - } - if (mpu98.intphase) { - bit = 1 << (mpu98.intphase - 2); - do { - if (mpu98.acttr & bit) { - MPUTR *tr; - tr = mpu98.tr + (mpu98.intphase - 2); - if (!tr->step) { - if ((tr->datas) && (tr->remain == 0)) { - if (cm_mpu98 == NULL) { - cm_mpu98 = commng_create(COMCREATE_MPU98II, FALSE); - } - if (tr->data[0] == MIDI_STOP) { - tr->datas = 0; - cm_mpu98->write(cm_mpu98, MIDI_STOP); - setrecvdata(MIDI_STOP); - mpu98ii_int(); - return(TRUE); - } - for (i=0; idatas; i++) { - cm_mpu98->write(cm_mpu98, tr->data[i]); - } - tr->datas = 0; - } - mpu98.intreq = 0xf0 + (mpu98.intphase - 2); - mpu98.recvevent |= MIDIE_STEP; - mpu98ii_int(); - return(TRUE); - } - } - bit <<= 1; - mpu98.intphase++; - } while(mpu98.intphase < 10); - mpu98.intphase = 0; - } - mpu98.remainstep--; - if (mpu98.remainstep) { - tr_step(); - mpu98.intphase = 1; - goto tr_nextsearch_more; - } - return(FALSE); -} - -void midiint(NEVENTITEM item) { - - nevent_set(NEVENT_MIDIINT, mpu98.stepclock, midiint, NEVENT_RELATIVE); - - if (mpu98.flag2 & MPUFLAG2_CLKTOHOST) { - if (!mpu98.hclk_rem) { - mpu98.hclk_rem = mpu98.hclk_step[mpu98.hclk_cnt & 3]; - mpu98.hclk_cnt++; - } - mpu98.hclk_rem--; - if (!mpu98.hclk_rem) { - setrecvdata(MPUMSG_HCLK); - mpu98ii_int(); - } - } - if (mpu98.flag1 & MPUFLAG1_PLAY) { - if (!mpu98.remainstep++) { - tr_step(); - mpu98.intphase = 1; - tr_nextsearch(); - } - } - (void)item; -} - -void midiwaitout(NEVENTITEM item) { - - // TRACE_("midi ready", 0); - if (mpu98_writecounter > 0) { - mpu98_writecounter--; - } - if (mpu98_writecounter < MPU98_WRITEBUFFER) { - // カウンタがバッファサイズより小さいならBUSY解除 - mpu98.status &= ~MIDIOUT_BUSY; - } - if (mpu98_writecounter > 0) { - // カウンタが0になるまで再登録 - nevent_set(NEVENT_MIDIWAIT, mpu98.xferclock, midiwaitout, NEVENT_RELATIVE); - } - (void)item; -} - -static void midiwait(SINT32 waitclock) { - - // 転送が多すぎてバッファを溢れるようならBUSYに変える - mpu98_writecounter += waitclock / mpu98.xferclock; - if (mpu98_writecounter > MPU98_WRITEBUFFER) { - mpu98.status |= MIDIOUT_BUSY; - } - if (!nevent_iswork(NEVENT_MIDIWAIT)) { - nevent_set(NEVENT_MIDIWAIT, mpu98.xferclock, midiwaitout, NEVENT_ABSOLUTE); - } -} - -static void midicmdwait(SINT32 waitclock) { - - // 一定時間強制BUSY - mpu98_writecounter++; - mpu98.status |= MIDIOUT_BUSY; - if (!nevent_iswork(NEVENT_MIDIWAIT)) { - nevent_set(NEVENT_MIDIWAIT, mpu98.xferclock, midiwaitout, NEVENT_ABSOLUTE); - } -} - -// ---- - -typedef REG8 (*MPUCMDFN)(REG8 cmd); - -static REG8 mpucmd_xx(REG8 cmd) { - -// TRACEOUT(("unknown MPU commands: %.2x", cmd)); - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_md(REG8 cmd) { // 00-2F: Mode - - TRACEOUT(("mpucmd_md %.2x", cmd)); -#if 0 - switch((cmd >> 0) & 3) { - case 1: // MIDI Stop - case 2: // MIDI Start - case 3: // MIDI Cont - break; - } -#endif - switch((cmd >> 2) & 3) { - case 1: // Stop Play - mpu98.flag1 &= ~MPUFLAG1_PLAY; - mpu98.recvevent = 0; - mpu98.intphase = 0; - mpu98.intreq = 0; - ZeroMemory(mpu98.tr, sizeof(mpu98.tr)); - ZeroMemory(&mpu98.cond, sizeof(mpu98.cond)); - if (!(mpu98.flag2 & MPUFLAG2_CLKTOHOST)) { - nevent_reset(NEVENT_MIDIINT); - } - break; - - case 2: // Start Play - mpu98.flag1 |= MPUFLAG1_PLAY; - mpu98.remainstep = 0; - if (!nevent_iswork(NEVENT_MIDIINT)) { - nevent_set(NEVENT_MIDIINT, mpu98.stepclock, - midiint, NEVENT_ABSOLUTE); - } - break; - } -#if 0 - switch((cmd >> 4) & 3) { - case 1: // Stop Rec - case 2: // Rec - break; - } -#endif - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_3f(REG8 cmd) { // 3F: UART - - mpu98.mode = 1; - sendmpureset(); - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_sr(REG8 cmd) { // 40-7F: Set ch of Ref table - - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_sm(REG8 cmd) { // 80-82: Clock Sync/Mode - - mpu98.syncmode = cmd - 0x80; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_mm(REG8 cmd) { // 83-85: Metronome - - mpu98.metromode = cmd - 0x83; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_8x(REG8 cmd) { // 86-8F: Flag1 - - REG8 bit; - - bit = 1 << ((cmd >> 1) & 7); - if (cmd & 1) { - mpu98.flag1 |= bit; - } - else { - mpu98.flag1 &= ~bit; - } -#if 0 - switch(cmd & 0x0f) { - case 0x06: // 86: Bender to Host / off - case 0x07: // 87: Bender to Host / on - case 0x08: // 88: THRU / off - case 0x09: // 89: THRU / on - case 0x0a: // 8A: Data in Stop / off - case 0x0b: // 8B: Data in Stop / on - case 0x0c: // 8C: Send Me / off - case 0x0d: // 8D: Send Me / on - case 0x0e: // 8E: Conductor / off - case 0x0f: // 8F: Conductor / on - break; - } -#endif - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_9x(REG8 cmd) { // 90-9F: Flag2 - - REG8 bit; - - bit = 1 << ((cmd >> 1) & 7); - if (cmd & 1) { - mpu98.flag2 |= bit; - } - else { - mpu98.flag2 &= ~bit; - } - switch(cmd & 0x0f) { -#if 0 - case 0x00: // 90: RT Aff / off - case 0x01: // 91: RT Aff / on - case 0x02: // 92: FSK Reso / INT - case 0x03: // 93: FSK Reso / 24 - break; -#endif - - case 0x04: // 94: CLK to Host / off - if (!(mpu98.flag1 & MPUFLAG1_PLAY)) { - nevent_reset(NEVENT_MIDIINT); - } - break; - - case 0x05: // 95: CLK to Host / on - if (!nevent_iswork(NEVENT_MIDIINT)) { - nevent_set(NEVENT_MIDIINT, mpu98.stepclock, - midiint, NEVENT_ABSOLUTE); - } - break; - -#if 0 - case 0x06: // 96: Exclu to Host / off - case 0x07: // 97: Exclu to Host / on - case 0x08: // 98: Ref A / off - case 0x09: // 99: Ref A / on - case 0x0a: // 9A: Ref B / off - case 0x0b: // 9B: Ref B / on - case 0x0c: // 9C: Ref C / off - case 0x0d: // 9D: Ref C / on - case 0x0e: // 9E: Ref D / off - case 0x0f: // 9F: Ref D / on - break; -#endif - } - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_rq(REG8 cmd) { // A0-AF: Req - - (void)cmd; - return(MPUCMDP_REQ); -} - -static REG8 mpucmd_b1(REG8 cmd) { // B1: Clear Rel - - mpu98.reltempo = 0x40; - makeintclock(); - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_b8(REG8 cmd) { // B8: Clear PC - - int i; - - for (i=0; i<8; i++) { - mpu98.tr[i].step = 0; - } - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_tb(REG8 cmd) { // C2-C8: .INT Time Base - - mpu98.inttimebase = cmd & 0x0f; - makeintclock(); - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_ws(REG8 cmd) { // D0-D7: Want to Send Data - - (void)cmd; - return(MPUCMDP_SHORT | MPUCMDP_INIT); -} - -static REG8 mpucmd_df(REG8 cmd) { // DF: WSD System - - (void)cmd; - return(MPUCMDP_LONG | MPUCMDP_INIT); -} - -static REG8 mpucmd_fo(REG8 cmd) { // E0-EF: Following Byte - - (void)cmd; - return(MPUCMDP_FOLLOWBYTE); -} - -static REG8 mpucmd_ff(REG8 cmd) { // FF: Reset - - sendmpureset(); - nevent_reset(NEVENT_MIDIINT); - setdefaultcondition(); - (void)cmd; - return(MPUCMDP_IDLE); -} - -static const MPUCMDFN mpucmds[0x100] = { - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 00 - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 10 - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 20 - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, // 30 - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_3f, - - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 40 - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 50 - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 60 - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 70 - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - - mpucmd_sm, mpucmd_sm, mpucmd_sm, mpucmd_mm, // 80 - mpucmd_mm, mpucmd_mm, mpucmd_8x, mpucmd_8x, - mpucmd_8x, mpucmd_8x, mpucmd_8x, mpucmd_8x, - mpucmd_8x, mpucmd_8x, mpucmd_8x, mpucmd_8x, - - mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, // 90 - mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, - mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, - mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, - - mpucmd_rq, mpucmd_rq, mpucmd_rq, mpucmd_rq, // a0 - mpucmd_rq, mpucmd_rq, mpucmd_rq, mpucmd_rq, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_rq, - mpucmd_rq, mpucmd_rq, mpucmd_xx, mpucmd_rq, - - mpucmd_xx, mpucmd_b1, mpucmd_xx, mpucmd_xx, // b0 - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_b8, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - - mpucmd_xx, mpucmd_xx, mpucmd_tb, mpucmd_tb, // c0 - mpucmd_tb, mpucmd_tb, mpucmd_tb, mpucmd_tb, - mpucmd_tb, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - - mpucmd_ws, mpucmd_ws, mpucmd_ws, mpucmd_ws, // d0 - mpucmd_ws, mpucmd_ws, mpucmd_ws, mpucmd_ws, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_df, - - mpucmd_fo, mpucmd_fo, mpucmd_fo, mpucmd_xx, // e0 - mpucmd_fo, mpucmd_xx, mpucmd_fo, mpucmd_fo, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_fo, mpucmd_fo, mpucmd_fo, mpucmd_fo, - - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, // f0 - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_ff}; - - -static void reqmpucmdgroupd(REG8 cmd) { - - switch(cmd) { - case 0xa0: // A0: Req Play Cnt Tr1 - case 0xa1: // A1: Req Play Cnt Tr2 - case 0xa2: // A2: Req Play Cnt Tr3 - case 0xa3: // A3: Req Play Cnt Tr4 - case 0xa4: // A4: Req Play Cnt Tr5 - case 0xa5: // A5: Req Play Cnt Tr6 - case 0xa6: // A6: Req Play Cnt Tr7 - case 0xa7: // A7: Req Play Cnt Tr8 - setrecvdata(mpu98.tr[cmd - 0xa0].step); - break; - - case 0xab: // AB: Read & Clear RC - setrecvdata(0); - break; - - case 0xac: // AC: Req Major Version - setrecvdata(1); - break; - - case 0xad: // AD: Req Minor Version - setrecvdata(0); - break; - - case 0xaf: // AF: Req Tempo - setrecvdata(mpu98.curtempo); - break; - } -} - -static void setmpucmdgroupe(REG8 cmd, REG8 data) { - - switch(cmd) { - case 0xe0: // Set Tempo - mpu98.tempo = data; - mpu98.reltempo = 0x40; - makeintclock(); - break; - - case 0xe1: // Rel Tempo - mpu98.reltempo = data; - makeintclock(); - break; - - case 0xe2: // Graduation - break; - - case 0xe4: // MIDI/Metro - mpu98.midipermetero = data; - break; - - case 0xe6: // Metro/Meas - mpu98.meteropermeas = data; - break; - - case 0xe7: // INTx4/H.CLK - sethclk(data); - break; - - case 0xec: // Act Tr - mpu98.acttr = data; - break; - - case 0xed: // Send Play CNT - mpu98.sendplaycnt = data; - break; - - case 0xee: // Acc CH 1-8 - mpu98.accch = (mpu98.accch & 0xff00) | data; - break; - - case 0xef: // Acc CH 9-16 - mpu98.accch = (mpu98.accch & 0x00ff) | (data << 8); - break; - } -} - -static BOOL sendmpumsg(MPUCMDS *cmd, REG8 data) { - - if (cmd->phase & MPUCMDP_SHORT) { - if (cmd->phase & MPUCMDP_INIT) { - cmd->phase &= ~MPUCMDP_INIT; - if (!(data & 0x80)) { - cmd->data[0] = cmd->rstat; - cmd->datapos = 1; - cmd->datacnt = shortmsgleng[cmd->rstat >> 4]; - } - else { - if ((data & 0xf0) != 0xf0) { - cmd->rstat = data; - } - cmd->datapos = 0; - cmd->datacnt = shortmsgleng[data >> 4]; - } - } - cmd->data[cmd->datapos] = data; - cmd->datapos++; - if (cmd->datapos >= cmd->datacnt) { - sendmpushortmsg(cmd->data, cmd->datacnt); - cmd->phase &= ~MPUCMDP_SHORT; - } - return(TRUE); - } - else if (cmd->phase & MPUCMDP_LONG) { - if (cmd->phase & MPUCMDP_INIT) { - cmd->phase &= ~MPUCMDP_INIT; - cmd->datapos = 0; - cmd->datacnt = sizeof(cmd->data); - } - if (cmd->datapos < cmd->datacnt) { - cmd->data[cmd->datapos] = data; - cmd->datapos++; - } - switch(cmd->data[0]) { - case 0xf0: - if (data == 0xf7) { - cmd->phase &= ~MPUCMDP_LONG; - sendmpulongmsg(cmd->data, cmd->datapos); - } - break; - - case 0xf2: - case 0xf3: - if (cmd->datapos >= 3) { - cmd->phase &= ~MPUCMDP_LONG; - } - break; - - case 0xf6: - default: - cmd->phase &= ~MPUCMDP_LONG; - break; - } - return(TRUE); - } - return(FALSE); -} - -static BRESULT sendmpucmd(MPUCMDS *cmd, REG8 data) { - - if (cmd->phase & MPUCMDP_FOLLOWBYTE) { - cmd->phase &= ~MPUCMDP_FOLLOWBYTE; - setmpucmdgroupe(cmd->cmd, data); - return(SUCCESS); - } - else if (cmd->phase & (MPUCMDP_SHORT | MPUCMDP_LONG)) { - sendmpumsg(cmd, data); - return(SUCCESS); - } - else { - cmd->phase = 0; - return(FAILURE); - } -} - -static BRESULT sendmpucond(MPUCMDS *cmd, REG8 data) { - - if (cmd->phase & (MPUCMDP_SHORT | MPUCMDP_LONG)) { -// if (mpu98.intreq == 0xf9) { -// mpu98.intreq = 0; -// } - sendmpumsg(cmd, data); - return(SUCCESS); - } - else if (cmd->phase & MPUCMDP_STEP) { - if (data < 0xf0) { - cmd->step = data; - cmd->phase &= ~MPUCMDP_STEP; - } - else { - cmd->step = 0xf0; - cmd->phase &= ~(MPUCMDP_STEP | MPUCMDP_CMD); - } - return(SUCCESS); - } - else if (cmd->phase & MPUCMDP_CMD) { - cmd->phase &= ~MPUCMDP_CMD; - cmd->cmd = data; - if (data < 0xf0) { - REG8 phase; - phase = (*mpucmds[data])(data); - if (phase & MPUCMDP_REQ) { - phase &= ~MPUCMDP_REQ; - reqmpucmdgroupd(data); - } - cmd->phase = phase; - if (phase & MPUCMDP_FOLLOWBYTE) { - return(SUCCESS); - } - } - else { - cmd->phase = 0; - if (data == MIDI_STOP) { - cm_mpu98->write(cm_mpu98, MIDI_STOP); - setrecvdata(MIDI_STOP); - mpu98ii_int(); - } - } - } - else if (cmd->phase & MPUCMDP_FOLLOWBYTE) { - cmd->phase &= ~MPUCMDP_FOLLOWBYTE; - setmpucmdgroupe(cmd->cmd, data); - } - else { - cmd->phase = 0; - return(FAILURE); - } - - tr_nextsearch(); - return(SUCCESS); -} - -static void sendmpudata(REG8 data) { - - if (mpu98.cmd.phase) { - sendmpucmd(&mpu98.cmd, data); - return; - } - - if (mpu98.recvevent & MIDIE_STEP) { - MPUTR *tr; - mpu98.recvevent ^= MIDIE_STEP; - tr = mpu98.tr + (mpu98.intphase - 2); - tr->datas = 0; - if (data < 0xf0) { - mpu98.recvevent ^= MIDIE_EVENT; - tr->step = data; - } - else { - tr->step = 0xf0; - tr->remain = 0; - tr->datas = 0; - tr_nextsearch(); - } - return; - } - if (mpu98.recvevent & MIDIE_EVENT) { - MPUTR *tr; - mpu98.recvevent ^= MIDIE_EVENT; - mpu98.recvevent |= MIDIE_DATA; - tr = mpu98.tr + (mpu98.intphase - 2); - switch(data & 0xf0) { - case 0xc0: - case 0xd0: - tr->remain = 2; - tr->rstat = data; - break; - - case 0x80: - case 0x90: - case 0xa0: - case 0xb0: - case 0xe0: - tr->remain = 3; - tr->rstat = data; - break; - - case 0xf0: - tr->remain = 1; - break; - - default: - tr->data[0] = tr->rstat; - tr->datas = 1; - tr->remain = 2; - if ((tr->rstat & 0xe0) == 0xc0) { - tr->remain--; - } - break; - } - } - if (mpu98.recvevent & MIDIE_DATA) { - MPUTR *tr; - tr = mpu98.tr + (mpu98.intphase - 2); - if (tr->remain) { - tr->data[tr->datas] = data; - tr->datas++; - tr->remain--; - } - if (!tr->remain) { - mpu98.recvevent ^= MIDIE_DATA; - tr_nextsearch(); - } - return; - } - -#if 1 - if (mpu98.cond.phase) -#else - if (mpu98.cond.phase & (MPUCMDP_CMD | MPUCMDP_FOLLOWBYTE)) -#endif - { - sendmpucond(&mpu98.cond, data); - return; - } -} - -void IOOUTCALL mpu98ii_o0(UINT port, REG8 dat) { - - UINT sent; - -TRACEOUT(("mpu98ii out %.4x %.2x", port, dat)); - if (cm_mpu98 == NULL) { - cm_mpu98 = commng_create(COMCREATE_MPU98II, FALSE); - } - if (cm_mpu98->connect != COMCONNECT_OFF) { - if (mpu98.mode) { - sent = cm_mpu98->write(cm_mpu98, (UINT8)dat); - } - else { -// TRACEOUT(("send data->%.2x", dat)); - sendmpudata(dat); - sent = 1; - } - if (sent) { - midiwait(mpu98.xferclock * sent); - } - } - (void)port; -} - -void IOOUTCALL mpu98ii_o2(UINT port, REG8 dat) { - -TRACEOUT(("mpu98ii out %.4x %.2x", port, dat)); - if (cm_mpu98 == NULL) { - cm_mpu98 = commng_create(COMCREATE_MPU98II, FALSE); - } - if (cm_mpu98->connect != COMCONNECT_OFF) { - if (!mpu98.mode) { - REG8 phase; -// TRACEOUT(("send cmd->%.2x", dat)); - mpu98.cmd.cmd = dat; - phase = (*mpucmds[dat])(dat); - setrecvdata(MPUMSG_ACK); - mpu98ii_int(); - if (phase & MPUCMDP_REQ) { - phase &= ~MPUCMDP_REQ; - reqmpucmdgroupd(dat); - } - mpu98.cmd.phase = phase; - } - else { - if (dat == 0xff) { - mpu98.mode = 0; - setrecvdata(MPUMSG_ACK); - } - } - midicmdwait(pccore.realclock / 10000); - } - (void)port; -} - -REG8 IOINPCALL mpu98ii_i0(UINT port) { - - if (cm_mpu98 == NULL) { - cm_mpu98 = commng_create(COMCREATE_MPU98II, FALSE); - } - if (cm_mpu98->connect != COMCONNECT_OFF) { - if (mpu98.r.cnt) { - mpu98.r.cnt--; -#if 0 - if (mpu98.r.cnt) { - mpu98ii_int(); - } - else { - pic_resetirq(mpu98.irqnum); - } -#endif - mpu98.data = mpu98.r.buf[mpu98.r.pos]; - mpu98.r.pos = (mpu98.r.pos + 1) & (MPU98_RECVBUFS - 1); - } - else if (mpu98.intreq) { - mpu98.data = mpu98.intreq; - mpu98.intreq = 0; - } - if ((mpu98.r.cnt) || (mpu98.intreq)) { - mpu98ii_int(); - } - else { - pic_resetirq(mpu98.irqnum); - } - -// TRACEOUT(("recv data->%.2x", mpu98.data)); -TRACEOUT(("mpu98ii inp %.4x %.2x", port, mpu98.data)); - return(mpu98.data); - } - else if ((port & 0xff00) == 0x8000) { - return(mpu98.data); - } - (void)port; - return(0xff); -} - -REG8 IOINPCALL mpu98ii_i2(UINT port) { - - REG8 ret; - - if (cm_mpu98 == NULL) { - cm_mpu98 = commng_create(COMCREATE_MPU98II, FALSE); - } - if (cm_mpu98->connect != COMCONNECT_OFF || port == (cs4231.port[10] + 1) || (port & 0xff00) == 0x8100) { - ret = mpu98.status; - if ((mpu98.r.cnt == 0) && (mpu98.intreq == 0)) { - ret |= MIDIIN_AVAIL; - } - // TRACEOUT(("mpu98ii inp %.4x %.2x", port, ret)); - TRACEOUT(("mpu98ii inp %.4x %.2x", port, mpu98.data)); - if ((port & 0xff00) == 0x8100) - { - // SB16のMPU互換ポートではMIDIIN_AVAILとMIDIOUT_BUSY以外のビットが常に1らしい - return(ret | ~(MIDIIN_AVAIL | MIDIOUT_BUSY)); - } - else - { - return(ret); - } - } - (void)port; - return(0xff); -} - - -// ---- I/F - -void mpu98ii_construct(void) { - - cm_mpu98 = NULL; -} - -void mpu98ii_destruct(void) { - - commng_destroy(cm_mpu98); - cm_mpu98 = NULL; -} - -void mpu98ii_reset(const NP2CFG *pConfig) { - - commng_destroy(cm_mpu98); - cm_mpu98 = NULL; - - ZeroMemory(&mpu98, sizeof(mpu98)); - mpu98.enable = (pConfig->mpuenable ? 1 : 0); - mpu98.data = MPUMSG_ACK; - mpu98.port = 0xc0d0 | ((pConfig->mpuopt & 0xf0) << 6); - mpu98.irqnum = mpuirqnum[pConfig->mpuopt & 3]; - setdefaultcondition(); -// pic_registext(mpu98.irqnum); - - if (cm_mpu98 == NULL) { - cm_mpu98 = commng_create(COMCREATE_MPU98II, TRUE); - } - - (void)pConfig; -} - -void mpu98ii_bind(void) { - - UINT port; - - if(mpu98.enable){ - mpu98ii_changeclock(); - - port = mpu98.port; - iocore_attachout(port, mpu98ii_o0); - iocore_attachinp(port, mpu98ii_i0); - //iocore_attachout(port+1, mpu98ii_o2); - //iocore_attachinp(port+1, mpu98ii_i2); - //iocore_attachout(port+0x100, mpu98ii_o2); - //iocore_attachinp(port+0x100, mpu98ii_i2); - port |= 2; - iocore_attachout(port, mpu98ii_o2); - iocore_attachinp(port, mpu98ii_i2); - - // PC/AT MPU-401 - if(np2cfg.mpu_at){ - iocore_attachout(0x330, mpu98ii_o0); - iocore_attachinp(0x330, mpu98ii_i0); - iocore_attachout(0x331, mpu98ii_o2); - iocore_attachinp(0x331, mpu98ii_i2); - } - // PC-9801-118 - if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ - iocore_attachout(cs4231.port[10], mpu98ii_o0); - iocore_attachinp(cs4231.port[10], mpu98ii_i0); - iocore_attachout(cs4231.port[10]+1, mpu98ii_o2); - iocore_attachinp(cs4231.port[10]+1, mpu98ii_i2); - } - } -} - -//#define MIDIIN_DEBUG - -void mpu98ii_callback(void) { - - UINT8 data; -#ifdef MIDIIN_DEBUG - static UINT8 testseq[] = {0x90, 0x3C, 0x7F}; - static int testseqpos = 0; - static DWORD time = 0; -#endif - - if (cm_mpu98) { - while((mpu98.r.cnt < MPU98_RECVBUFS) && - (cm_mpu98->read(cm_mpu98, &data) -#ifdef MIDIIN_DEBUG - || (np2cfg.asynccpu) -#endif - )) { - if (!mpu98.r.cnt) { - mpu98ii_int(); - } -#ifdef MIDIIN_DEBUG - data = testseq[testseqpos]; -#endif - setrecvdata(data); -#ifdef MIDIIN_DEBUG - if(testseqpos == sizeof(testseq) - 1){ - time = GetTickCount(); - testseq[1] = rand() & 0x7f; - } - testseqpos = (testseqpos + 1) % sizeof(testseq); -#endif - } - } -} - -void mpu98ii_midipanic(void) { - - if (cm_mpu98) { - cm_mpu98->msg(cm_mpu98, COMMSG_MIDIRESET, 0); - } -} - -void mpu98ii_changeclock(void) { - - if(mpu98.enable){ - mpu98.xferclock = pccore.realclock / (31250 / 8); - makeintclock(); - } -} - - + +// emulation MPU-401 CPU Version 1.3 ('84/07/07) + +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#undef TRACEOUT +#define USE_TRACEOUT_VS +#ifdef USE_TRACEOUT_VS +static void trace_fmt_ex(const char *fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "\n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#else +#define TRACEOUT(s) (void)(s) +#endif +#endif /* 1 */ + +enum { + MIDI_STOP = 0xfc, + + MIDIIN_AVAIL = 0x80, + MIDIOUT_BUSY = 0x40, + + MPUMSG_TRACKDATAREQ = 0xf0, + MPUMSG_OVERFLOW = 0xf8, + MPUMSG_REQCOND = 0xf9, + MPUMSG_DATAEND = 0xfc, + MPUMSG_HCLK = 0xfd, + MPUMSG_ACK = 0xfe, + MPUMSG_SYS = 0xff, + + MIDITIMEOUTCLOCK = 3000, + MIDITIMEOUTCLOCK2 = 300 +}; + +enum { + MIDIE_STEP = 0x01, + MIDIE_EVENT = 0x02, + MIDIE_DATA = 0x04 +}; + +enum { + MPUCMDP_IDLE = 0x00, + MPUCMDP_STEP = 0x01, + MPUCMDP_CMD = 0x02, + MPUCMDP_REQ = 0x04, + MPUCMDP_FOLLOWBYTE = 0x08, + MPUCMDP_SHORT = 0x10, + MPUCMDP_LONG = 0x20, + MPUCMDP_INIT = 0x80 +}; + +enum { + MPUSYNCMODE_INT = 0x00, + MPUSYNCMODE_FSK = 0x01, + MPUSYNCMODE_MIDI = 0x02, + + MPUMETROMODE_ACC = 0x00, + MPUMETROMODE_OFF = 0x01, + MPUMETROMODE_ON = 0x02, + + MPUFLAG1_PLAY = 0x01, + MPUFLAG1_BENDERTOHOST = 0x08, + MPUFLAG1_THRU = 0x10, + MPUFLAG1_DATAINSTOP = 0x20, + MPUFLAG1_SENDME = 0x40, + MPUFLAG1_CONDUCTOR = 0x80, + + MPUFLAG2_RTAFF = 0x01, + MPUFLAG2_FSKRESO = 0x02, + MPUFLAG2_CLKTOHOST = 0x04, + MPUFLAG2_EXECLUTOHOST = 0x08, + MPUFLAG2_REFA = 0x10, + MPUFLAG2_REFB = 0x20, + MPUFLAG2_REFC = 0x40, + MPUFLAG2_REFD = 0x80 +}; + + + _MPU98II mpu98; + COMMNG cm_mpu98; + + +static const UINT8 mpuirqnum[4] = {3, 5, 6, 12}; + +static const UINT8 shortmsgleng[0x10] = { + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 2, 2, 3, 1}; + +static const UINT8 hclk_step1[4][4] = {{0, 0, 0, 0}, {1, 0, 0, 0}, + {1, 0, 1, 0}, {1, 1, 1, 0}}; + +// XXX: 根拠なし とりあえず大きめの値にしておく +#define MPU98_WRITEBUFFER 2048 +static int mpu98_writecounter = 0; + + +static void makeintclock(void) { + + UINT32 l; + UINT curtempo; + + l = mpu98.tempo * 2 * mpu98.reltempo / 0x40; + if (l < 5 * 2) { + l = 5 * 2; + } + curtempo = l >> 1; + if (curtempo > 250) { + curtempo = 250; + } + mpu98.curtempo = curtempo; + if (!(mpu98.flag2 & MPUFLAG2_FSKRESO)) { + l *= mpu98.inttimebase; // *12 + } + mpu98.stepclock = (pccore.realclock * 5 / l); // /12 +} + +static void sethclk(REG8 data) { + + REG8 quarter; + int i; + + quarter = data >> 2; + if (!quarter) { + quarter = 64; + } + for (i=0; i<4; i++) { + mpu98.hclk_step[i] = quarter + hclk_step1[data & 3][i]; + } + mpu98.hclk_rem = 0; +} + +static void setdefaultcondition(void) { + + mpu98.recvevent = 0; + mpu98.remainstep = 0; + mpu98.intphase = 0; + mpu98.intreq = 0; + + ZeroMemory(&mpu98.cmd, sizeof(mpu98.cmd)); + ZeroMemory(mpu98.tr, sizeof(mpu98.tr)); + ZeroMemory(&mpu98.cond, sizeof(mpu98.cond)); + + mpu98.syncmode = MPUSYNCMODE_INT; + mpu98.metromode = MPUMETROMODE_OFF; + mpu98.flag1 = MPUFLAG1_THRU | MPUFLAG1_SENDME; + mpu98.flag2 = MPUFLAG2_RTAFF; + + mpu98.inttimebase = 120 / 24; + mpu98.tempo = 100; + mpu98.reltempo = 0x40; + makeintclock(); + mpu98.midipermetero = 12; + mpu98.meteropermeas = 8; + sethclk(240); + mpu98.acttr = 0x00; + mpu98.sendplaycnt = 0; + mpu98.accch = 0xffff; +} + +static void setrecvdata(REG8 data) { + + MPURECV *r; + + r = &mpu98.r; + if (r->cnt < MPU98_RECVBUFS) { + r->buf[(r->pos + r->cnt) & (MPU98_RECVBUFS - 1)] = data; + r->cnt++; + } +} + +static void sendmpushortmsg(const UINT8 *dat, UINT count) { + + UINT i; + COMMNG cm; + +#if 0 + if (!(mpu98.flag1 & MPUFLAG1_BENDERTOHOST)) { + switch(dat[0] >> 4) { + case 0x0a: + case 0x0d: + case 0x0e: + return; + + case 0x0b: + if (dat[1] < 0x40) { + return; + } + break; + } + } +#endif + cm = cm_mpu98; + for (i=0; iwrite(cm, dat[i]); + } +} + +static void sendmpulongmsg(const UINT8 *dat, UINT count) { + + UINT i; + COMMNG cm; + + cm = cm_mpu98; + for (i=0; iwrite(cm, dat[i]); + } +} + +static void sendmpureset(void) { + + UINT i; + UINT8 sMessage[3]; + + for (i=0; i<0x10; i++) { + sMessage[0] = (UINT8)(0xb0 + i); + sMessage[1] = 0x7b; + sMessage[2] = 0x00; + sendmpushortmsg(sMessage, 3); + } +} + +static void mpu98ii_int(void) { + + TRACEOUT(("int!")); + pic_setirq(mpu98.irqnum); + //// Sound Blaster 16 + //if(g_nSoundID == SOUNDID_SB16 || g_nSoundID == SOUNDID_PC_9801_86_SB16 || g_nSoundID == SOUNDID_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ + // pic_setirq(g_sb16.dmairq); + //} + //// PC-9801-118 + //if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ + // pic_setirq(10); + //} + //// WaveStar + //if(g_nSoundID == SOUNDID_WAVESTAR){ + // pic_setirq(10); + //} +} + +static void tr_step(void) { + + int i; + REG8 bit; + + if (mpu98.flag1 & MPUFLAG1_CONDUCTOR) { + if (mpu98.cond.step) { + mpu98.cond.step--; + } + } + for (i=0, bit=1; i<8; bit<<=1, i++) { + if (mpu98.acttr & bit) { + if (mpu98.tr[i].step) { + mpu98.tr[i].step--; + } + } + } +} + +static BOOL tr_nextsearch(void) { + + int i; + REG8 bit; + +tr_nextsearch_more: + if (mpu98.intphase == 1) { + if (mpu98.flag1 & MPUFLAG1_CONDUCTOR) { + if (!mpu98.cond.step) { + mpu98.intreq = MPUMSG_REQCOND; + mpu98.cond.phase |= MPUCMDP_STEP | MPUCMDP_CMD; + mpu98ii_int(); + return(TRUE); + } + } + mpu98.intphase = 2; + } + if (mpu98.intphase) { + bit = 1 << (mpu98.intphase - 2); + do { + if (mpu98.acttr & bit) { + MPUTR *tr; + tr = mpu98.tr + (mpu98.intphase - 2); + if (!tr->step) { + if ((tr->datas) && (tr->remain == 0)) { + if (cm_mpu98 == NULL) { + cm_mpu98 = commng_create(COMCREATE_MPU98II, FALSE); + } + if (tr->data[0] == MIDI_STOP) { + tr->datas = 0; + cm_mpu98->write(cm_mpu98, MIDI_STOP); + setrecvdata(MIDI_STOP); + mpu98ii_int(); + return(TRUE); + } + for (i=0; idatas; i++) { + cm_mpu98->write(cm_mpu98, tr->data[i]); + } + tr->datas = 0; + } + mpu98.intreq = 0xf0 + (mpu98.intphase - 2); + mpu98.recvevent |= MIDIE_STEP; + mpu98ii_int(); + return(TRUE); + } + } + bit <<= 1; + mpu98.intphase++; + } while(mpu98.intphase < 10); + mpu98.intphase = 0; + } + mpu98.remainstep--; + if (mpu98.remainstep) { + tr_step(); + mpu98.intphase = 1; + goto tr_nextsearch_more; + } + return(FALSE); +} + +void midiint(NEVENTITEM item) { + + nevent_set(NEVENT_MIDIINT, mpu98.stepclock, midiint, NEVENT_RELATIVE); + + if (mpu98.flag2 & MPUFLAG2_CLKTOHOST) { + if (!mpu98.hclk_rem) { + mpu98.hclk_rem = mpu98.hclk_step[mpu98.hclk_cnt & 3]; + mpu98.hclk_cnt++; + } + mpu98.hclk_rem--; + if (!mpu98.hclk_rem) { + setrecvdata(MPUMSG_HCLK); + mpu98ii_int(); + } + } + if (mpu98.flag1 & MPUFLAG1_PLAY) { + if (!mpu98.remainstep++) { + tr_step(); + mpu98.intphase = 1; + tr_nextsearch(); + } + } + (void)item; +} + +void midiwaitout(NEVENTITEM item) { + + // TRACE_("midi ready", 0); + if (mpu98_writecounter > 0) { + mpu98_writecounter--; + } + if (mpu98_writecounter < MPU98_WRITEBUFFER) { + // カウンタがバッファサイズより小さいならBUSY解除 + mpu98.status &= ~MIDIOUT_BUSY; + } + if (mpu98_writecounter > 0) { + // カウンタが0になるまで再登録 + nevent_set(NEVENT_MIDIWAIT, mpu98.xferclock, midiwaitout, NEVENT_RELATIVE); + } + (void)item; +} + +static void midiwait(SINT32 waitclock) { + + // 転送が多すぎてバッファを溢れるようならBUSYに変える + mpu98_writecounter += waitclock / mpu98.xferclock; + if (mpu98_writecounter > MPU98_WRITEBUFFER) { + mpu98.status |= MIDIOUT_BUSY; + } + if (!nevent_iswork(NEVENT_MIDIWAIT)) { + nevent_set(NEVENT_MIDIWAIT, mpu98.xferclock, midiwaitout, NEVENT_ABSOLUTE); + } +} + +static void midicmdwait(SINT32 waitclock) { + + // 一定時間強制BUSY + mpu98_writecounter++; + mpu98.status |= MIDIOUT_BUSY; + if (!nevent_iswork(NEVENT_MIDIWAIT)) { + nevent_set(NEVENT_MIDIWAIT, mpu98.xferclock, midiwaitout, NEVENT_ABSOLUTE); + } +} + +// ---- + +typedef REG8 (*MPUCMDFN)(REG8 cmd); + +static REG8 mpucmd_xx(REG8 cmd) { + +// TRACEOUT(("unknown MPU commands: %.2x", cmd)); + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_md(REG8 cmd) { // 00-2F: Mode + + TRACEOUT(("mpucmd_md %.2x", cmd)); +#if 0 + switch((cmd >> 0) & 3) { + case 1: // MIDI Stop + case 2: // MIDI Start + case 3: // MIDI Cont + break; + } +#endif + switch((cmd >> 2) & 3) { + case 1: // Stop Play + mpu98.flag1 &= ~MPUFLAG1_PLAY; + mpu98.recvevent = 0; + mpu98.intphase = 0; + mpu98.intreq = 0; + ZeroMemory(mpu98.tr, sizeof(mpu98.tr)); + ZeroMemory(&mpu98.cond, sizeof(mpu98.cond)); + if (!(mpu98.flag2 & MPUFLAG2_CLKTOHOST)) { + nevent_reset(NEVENT_MIDIINT); + } + break; + + case 2: // Start Play + mpu98.flag1 |= MPUFLAG1_PLAY; + mpu98.remainstep = 0; + if (!nevent_iswork(NEVENT_MIDIINT)) { + nevent_set(NEVENT_MIDIINT, mpu98.stepclock, + midiint, NEVENT_ABSOLUTE); + } + break; + } +#if 0 + switch((cmd >> 4) & 3) { + case 1: // Stop Rec + case 2: // Rec + break; + } +#endif + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_3f(REG8 cmd) { // 3F: UART + + mpu98.mode = 1; + sendmpureset(); + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_sr(REG8 cmd) { // 40-7F: Set ch of Ref table + + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_sm(REG8 cmd) { // 80-82: Clock Sync/Mode + + mpu98.syncmode = cmd - 0x80; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_mm(REG8 cmd) { // 83-85: Metronome + + mpu98.metromode = cmd - 0x83; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_8x(REG8 cmd) { // 86-8F: Flag1 + + REG8 bit; + + bit = 1 << ((cmd >> 1) & 7); + if (cmd & 1) { + mpu98.flag1 |= bit; + } + else { + mpu98.flag1 &= ~bit; + } +#if 0 + switch(cmd & 0x0f) { + case 0x06: // 86: Bender to Host / off + case 0x07: // 87: Bender to Host / on + case 0x08: // 88: THRU / off + case 0x09: // 89: THRU / on + case 0x0a: // 8A: Data in Stop / off + case 0x0b: // 8B: Data in Stop / on + case 0x0c: // 8C: Send Me / off + case 0x0d: // 8D: Send Me / on + case 0x0e: // 8E: Conductor / off + case 0x0f: // 8F: Conductor / on + break; + } +#endif + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_9x(REG8 cmd) { // 90-9F: Flag2 + + REG8 bit; + + bit = 1 << ((cmd >> 1) & 7); + if (cmd & 1) { + mpu98.flag2 |= bit; + } + else { + mpu98.flag2 &= ~bit; + } + switch(cmd & 0x0f) { +#if 0 + case 0x00: // 90: RT Aff / off + case 0x01: // 91: RT Aff / on + case 0x02: // 92: FSK Reso / INT + case 0x03: // 93: FSK Reso / 24 + break; +#endif + + case 0x04: // 94: CLK to Host / off + if (!(mpu98.flag1 & MPUFLAG1_PLAY)) { + nevent_reset(NEVENT_MIDIINT); + } + break; + + case 0x05: // 95: CLK to Host / on + if (!nevent_iswork(NEVENT_MIDIINT)) { + nevent_set(NEVENT_MIDIINT, mpu98.stepclock, + midiint, NEVENT_ABSOLUTE); + } + break; + +#if 0 + case 0x06: // 96: Exclu to Host / off + case 0x07: // 97: Exclu to Host / on + case 0x08: // 98: Ref A / off + case 0x09: // 99: Ref A / on + case 0x0a: // 9A: Ref B / off + case 0x0b: // 9B: Ref B / on + case 0x0c: // 9C: Ref C / off + case 0x0d: // 9D: Ref C / on + case 0x0e: // 9E: Ref D / off + case 0x0f: // 9F: Ref D / on + break; +#endif + } + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_rq(REG8 cmd) { // A0-AF: Req + + (void)cmd; + return(MPUCMDP_REQ); +} + +static REG8 mpucmd_b1(REG8 cmd) { // B1: Clear Rel + + mpu98.reltempo = 0x40; + makeintclock(); + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_b8(REG8 cmd) { // B8: Clear PC + + int i; + + for (i=0; i<8; i++) { + mpu98.tr[i].step = 0; + } + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_tb(REG8 cmd) { // C2-C8: .INT Time Base + + mpu98.inttimebase = cmd & 0x0f; + makeintclock(); + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_ws(REG8 cmd) { // D0-D7: Want to Send Data + + (void)cmd; + return(MPUCMDP_SHORT | MPUCMDP_INIT); +} + +static REG8 mpucmd_df(REG8 cmd) { // DF: WSD System + + (void)cmd; + return(MPUCMDP_LONG | MPUCMDP_INIT); +} + +static REG8 mpucmd_fo(REG8 cmd) { // E0-EF: Following Byte + + (void)cmd; + return(MPUCMDP_FOLLOWBYTE); +} + +static REG8 mpucmd_ff(REG8 cmd) { // FF: Reset + + sendmpureset(); + nevent_reset(NEVENT_MIDIINT); + setdefaultcondition(); + (void)cmd; + return(MPUCMDP_IDLE); +} + +static const MPUCMDFN mpucmds[0x100] = { + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 00 + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 10 + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 20 + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, // 30 + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_3f, + + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 40 + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 50 + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 60 + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 70 + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + + mpucmd_sm, mpucmd_sm, mpucmd_sm, mpucmd_mm, // 80 + mpucmd_mm, mpucmd_mm, mpucmd_8x, mpucmd_8x, + mpucmd_8x, mpucmd_8x, mpucmd_8x, mpucmd_8x, + mpucmd_8x, mpucmd_8x, mpucmd_8x, mpucmd_8x, + + mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, // 90 + mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, + mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, + mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, + + mpucmd_rq, mpucmd_rq, mpucmd_rq, mpucmd_rq, // a0 + mpucmd_rq, mpucmd_rq, mpucmd_rq, mpucmd_rq, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_rq, + mpucmd_rq, mpucmd_rq, mpucmd_xx, mpucmd_rq, + + mpucmd_xx, mpucmd_b1, mpucmd_xx, mpucmd_xx, // b0 + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_b8, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + + mpucmd_xx, mpucmd_xx, mpucmd_tb, mpucmd_tb, // c0 + mpucmd_tb, mpucmd_tb, mpucmd_tb, mpucmd_tb, + mpucmd_tb, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + + mpucmd_ws, mpucmd_ws, mpucmd_ws, mpucmd_ws, // d0 + mpucmd_ws, mpucmd_ws, mpucmd_ws, mpucmd_ws, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_df, + + mpucmd_fo, mpucmd_fo, mpucmd_fo, mpucmd_xx, // e0 + mpucmd_fo, mpucmd_xx, mpucmd_fo, mpucmd_fo, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_fo, mpucmd_fo, mpucmd_fo, mpucmd_fo, + + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, // f0 + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_ff}; + + +static void reqmpucmdgroupd(REG8 cmd) { + + switch(cmd) { + case 0xa0: // A0: Req Play Cnt Tr1 + case 0xa1: // A1: Req Play Cnt Tr2 + case 0xa2: // A2: Req Play Cnt Tr3 + case 0xa3: // A3: Req Play Cnt Tr4 + case 0xa4: // A4: Req Play Cnt Tr5 + case 0xa5: // A5: Req Play Cnt Tr6 + case 0xa6: // A6: Req Play Cnt Tr7 + case 0xa7: // A7: Req Play Cnt Tr8 + setrecvdata(mpu98.tr[cmd - 0xa0].step); + break; + + case 0xab: // AB: Read & Clear RC + setrecvdata(0); + break; + + case 0xac: // AC: Req Major Version + setrecvdata(1); + break; + + case 0xad: // AD: Req Minor Version + setrecvdata(0); + break; + + case 0xaf: // AF: Req Tempo + setrecvdata(mpu98.curtempo); + break; + } +} + +static void setmpucmdgroupe(REG8 cmd, REG8 data) { + + switch(cmd) { + case 0xe0: // Set Tempo + mpu98.tempo = data; + mpu98.reltempo = 0x40; + makeintclock(); + break; + + case 0xe1: // Rel Tempo + mpu98.reltempo = data; + makeintclock(); + break; + + case 0xe2: // Graduation + break; + + case 0xe4: // MIDI/Metro + mpu98.midipermetero = data; + break; + + case 0xe6: // Metro/Meas + mpu98.meteropermeas = data; + break; + + case 0xe7: // INTx4/H.CLK + sethclk(data); + break; + + case 0xec: // Act Tr + mpu98.acttr = data; + break; + + case 0xed: // Send Play CNT + mpu98.sendplaycnt = data; + break; + + case 0xee: // Acc CH 1-8 + mpu98.accch = (mpu98.accch & 0xff00) | data; + break; + + case 0xef: // Acc CH 9-16 + mpu98.accch = (mpu98.accch & 0x00ff) | (data << 8); + break; + } +} + +static BOOL sendmpumsg(MPUCMDS *cmd, REG8 data) { + + if (cmd->phase & MPUCMDP_SHORT) { + if (cmd->phase & MPUCMDP_INIT) { + cmd->phase &= ~MPUCMDP_INIT; + if (!(data & 0x80)) { + cmd->data[0] = cmd->rstat; + cmd->datapos = 1; + cmd->datacnt = shortmsgleng[cmd->rstat >> 4]; + } + else { + if ((data & 0xf0) != 0xf0) { + cmd->rstat = data; + } + cmd->datapos = 0; + cmd->datacnt = shortmsgleng[data >> 4]; + } + } + cmd->data[cmd->datapos] = data; + cmd->datapos++; + if (cmd->datapos >= cmd->datacnt) { + sendmpushortmsg(cmd->data, cmd->datacnt); + cmd->phase &= ~MPUCMDP_SHORT; + } + return(TRUE); + } + else if (cmd->phase & MPUCMDP_LONG) { + if (cmd->phase & MPUCMDP_INIT) { + cmd->phase &= ~MPUCMDP_INIT; + cmd->datapos = 0; + cmd->datacnt = sizeof(cmd->data); + } + if (cmd->datapos < cmd->datacnt) { + cmd->data[cmd->datapos] = data; + cmd->datapos++; + } + switch(cmd->data[0]) { + case 0xf0: + if (data == 0xf7) { + cmd->phase &= ~MPUCMDP_LONG; + sendmpulongmsg(cmd->data, cmd->datapos); + } + break; + + case 0xf2: + case 0xf3: + if (cmd->datapos >= 3) { + cmd->phase &= ~MPUCMDP_LONG; + } + break; + + case 0xf6: + default: + cmd->phase &= ~MPUCMDP_LONG; + break; + } + return(TRUE); + } + return(FALSE); +} + +static BRESULT sendmpucmd(MPUCMDS *cmd, REG8 data) { + + if (cmd->phase & MPUCMDP_FOLLOWBYTE) { + cmd->phase &= ~MPUCMDP_FOLLOWBYTE; + setmpucmdgroupe(cmd->cmd, data); + return(SUCCESS); + } + else if (cmd->phase & (MPUCMDP_SHORT | MPUCMDP_LONG)) { + sendmpumsg(cmd, data); + return(SUCCESS); + } + else { + cmd->phase = 0; + return(FAILURE); + } +} + +static BRESULT sendmpucond(MPUCMDS *cmd, REG8 data) { + + if (cmd->phase & (MPUCMDP_SHORT | MPUCMDP_LONG)) { +// if (mpu98.intreq == 0xf9) { +// mpu98.intreq = 0; +// } + sendmpumsg(cmd, data); + return(SUCCESS); + } + else if (cmd->phase & MPUCMDP_STEP) { + if (data < 0xf0) { + cmd->step = data; + cmd->phase &= ~MPUCMDP_STEP; + } + else { + cmd->step = 0xf0; + cmd->phase &= ~(MPUCMDP_STEP | MPUCMDP_CMD); + } + return(SUCCESS); + } + else if (cmd->phase & MPUCMDP_CMD) { + cmd->phase &= ~MPUCMDP_CMD; + cmd->cmd = data; + if (data < 0xf0) { + REG8 phase; + phase = (*mpucmds[data])(data); + if (phase & MPUCMDP_REQ) { + phase &= ~MPUCMDP_REQ; + reqmpucmdgroupd(data); + } + cmd->phase = phase; + if (phase & MPUCMDP_FOLLOWBYTE) { + return(SUCCESS); + } + } + else { + cmd->phase = 0; + if (data == MIDI_STOP) { + cm_mpu98->write(cm_mpu98, MIDI_STOP); + setrecvdata(MIDI_STOP); + mpu98ii_int(); + } + } + } + else if (cmd->phase & MPUCMDP_FOLLOWBYTE) { + cmd->phase &= ~MPUCMDP_FOLLOWBYTE; + setmpucmdgroupe(cmd->cmd, data); + } + else { + cmd->phase = 0; + return(FAILURE); + } + + tr_nextsearch(); + return(SUCCESS); +} + +static void sendmpudata(REG8 data) { + + if (mpu98.cmd.phase) { + sendmpucmd(&mpu98.cmd, data); + return; + } + + if (mpu98.recvevent & MIDIE_STEP) { + MPUTR *tr; + mpu98.recvevent ^= MIDIE_STEP; + tr = mpu98.tr + (mpu98.intphase - 2); + tr->datas = 0; + if (data < 0xf0) { + mpu98.recvevent ^= MIDIE_EVENT; + tr->step = data; + } + else { + tr->step = 0xf0; + tr->remain = 0; + tr->datas = 0; + tr_nextsearch(); + } + return; + } + if (mpu98.recvevent & MIDIE_EVENT) { + MPUTR *tr; + mpu98.recvevent ^= MIDIE_EVENT; + mpu98.recvevent |= MIDIE_DATA; + tr = mpu98.tr + (mpu98.intphase - 2); + switch(data & 0xf0) { + case 0xc0: + case 0xd0: + tr->remain = 2; + tr->rstat = data; + break; + + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: + case 0xe0: + tr->remain = 3; + tr->rstat = data; + break; + + case 0xf0: + tr->remain = 1; + break; + + default: + tr->data[0] = tr->rstat; + tr->datas = 1; + tr->remain = 2; + if ((tr->rstat & 0xe0) == 0xc0) { + tr->remain--; + } + break; + } + } + if (mpu98.recvevent & MIDIE_DATA) { + MPUTR *tr; + tr = mpu98.tr + (mpu98.intphase - 2); + if (tr->remain) { + tr->data[tr->datas] = data; + tr->datas++; + tr->remain--; + } + if (!tr->remain) { + mpu98.recvevent ^= MIDIE_DATA; + tr_nextsearch(); + } + return; + } + +#if 1 + if (mpu98.cond.phase) +#else + if (mpu98.cond.phase & (MPUCMDP_CMD | MPUCMDP_FOLLOWBYTE)) +#endif + { + sendmpucond(&mpu98.cond, data); + return; + } +} + +void IOOUTCALL mpu98ii_o0(UINT port, REG8 dat) { + + UINT sent; + +TRACEOUT(("mpu98ii out %.4x %.2x", port, dat)); + if (cm_mpu98 == NULL) { + cm_mpu98 = commng_create(COMCREATE_MPU98II, FALSE); + } + if (cm_mpu98->connect != COMCONNECT_OFF) { + if (mpu98.mode) { + sent = cm_mpu98->write(cm_mpu98, (UINT8)dat); + } + else { +// TRACEOUT(("send data->%.2x", dat)); + sendmpudata(dat); + sent = 1; + } + if (sent) { + midiwait(mpu98.xferclock * sent); + } + } + (void)port; +} + +void IOOUTCALL mpu98ii_o2(UINT port, REG8 dat) { + +TRACEOUT(("mpu98ii out %.4x %.2x", port, dat)); + if (cm_mpu98 == NULL) { + cm_mpu98 = commng_create(COMCREATE_MPU98II, FALSE); + } + if (cm_mpu98->connect != COMCONNECT_OFF) { + if (!mpu98.mode) { + REG8 phase; +// TRACEOUT(("send cmd->%.2x", dat)); + mpu98.cmd.cmd = dat; + phase = (*mpucmds[dat])(dat); + setrecvdata(MPUMSG_ACK); + mpu98ii_int(); + if (phase & MPUCMDP_REQ) { + phase &= ~MPUCMDP_REQ; + reqmpucmdgroupd(dat); + } + mpu98.cmd.phase = phase; + } + else { + if (dat == 0xff) { + mpu98.mode = 0; + setrecvdata(MPUMSG_ACK); + } + } + midicmdwait(pccore.realclock / 10000); + } + (void)port; +} + +REG8 IOINPCALL mpu98ii_i0(UINT port) { + + if (cm_mpu98 == NULL) { + cm_mpu98 = commng_create(COMCREATE_MPU98II, FALSE); + } + if (cm_mpu98->connect != COMCONNECT_OFF) { + if (mpu98.r.cnt) { + mpu98.r.cnt--; +#if 0 + if (mpu98.r.cnt) { + mpu98ii_int(); + } + else { + pic_resetirq(mpu98.irqnum); + } +#endif + mpu98.data = mpu98.r.buf[mpu98.r.pos]; + mpu98.r.pos = (mpu98.r.pos + 1) & (MPU98_RECVBUFS - 1); + } + else if (mpu98.intreq) { + mpu98.data = mpu98.intreq; + mpu98.intreq = 0; + } + if ((mpu98.r.cnt) || (mpu98.intreq)) { + mpu98ii_int(); + } + else { + pic_resetirq(mpu98.irqnum); + } + +// TRACEOUT(("recv data->%.2x", mpu98.data)); +TRACEOUT(("mpu98ii inp %.4x %.2x", port, mpu98.data)); + return(mpu98.data); + } + else if ((port & 0xff00) == 0x8000) { + return(mpu98.data); + } + (void)port; + return(0xff); +} + +REG8 IOINPCALL mpu98ii_i2(UINT port) { + + REG8 ret; + + if (cm_mpu98 == NULL) { + cm_mpu98 = commng_create(COMCREATE_MPU98II, FALSE); + } + if (cm_mpu98->connect != COMCONNECT_OFF || port == (cs4231.port[10] + 1) || (port & 0xff00) == 0x8100) { + ret = mpu98.status; + if ((mpu98.r.cnt == 0) && (mpu98.intreq == 0)) { + ret |= MIDIIN_AVAIL; + } + // TRACEOUT(("mpu98ii inp %.4x %.2x", port, ret)); + TRACEOUT(("mpu98ii inp %.4x %.2x", port, mpu98.data)); + if ((port & 0xff00) == 0x8100) + { + // SB16のMPU互換ポートではMIDIIN_AVAILとMIDIOUT_BUSY以外のビットが常に1らしい + return(ret | ~(MIDIIN_AVAIL | MIDIOUT_BUSY)); + } + else + { + return(ret); + } + } + (void)port; + return(0xff); +} + + +// ---- I/F + +void mpu98ii_construct(void) { + + cm_mpu98 = NULL; +} + +void mpu98ii_destruct(void) { + + commng_destroy(cm_mpu98); + cm_mpu98 = NULL; +} + +void mpu98ii_reset(const NP2CFG *pConfig) { + + commng_destroy(cm_mpu98); + cm_mpu98 = NULL; + + ZeroMemory(&mpu98, sizeof(mpu98)); + mpu98.enable = (pConfig->mpuenable ? 1 : 0); + mpu98.data = MPUMSG_ACK; + mpu98.port = 0xc0d0 | ((pConfig->mpuopt & 0xf0) << 6); + mpu98.irqnum = mpuirqnum[pConfig->mpuopt & 3]; + setdefaultcondition(); +// pic_registext(mpu98.irqnum); + + if (cm_mpu98 == NULL) { + cm_mpu98 = commng_create(COMCREATE_MPU98II, TRUE); + } + + (void)pConfig; +} + +void mpu98ii_bind(void) { + + UINT port; + + if(mpu98.enable){ + mpu98ii_changeclock(); + + port = mpu98.port; + iocore_attachout(port, mpu98ii_o0); + iocore_attachinp(port, mpu98ii_i0); + //iocore_attachout(port+1, mpu98ii_o2); + //iocore_attachinp(port+1, mpu98ii_i2); + //iocore_attachout(port+0x100, mpu98ii_o2); + //iocore_attachinp(port+0x100, mpu98ii_i2); + port |= 2; + iocore_attachout(port, mpu98ii_o2); + iocore_attachinp(port, mpu98ii_i2); + + // PC/AT MPU-401 + if(np2cfg.mpu_at){ + iocore_attachout(0x330, mpu98ii_o0); + iocore_attachinp(0x330, mpu98ii_i0); + iocore_attachout(0x331, mpu98ii_o2); + iocore_attachinp(0x331, mpu98ii_i2); + } + // PC-9801-118 + if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ + iocore_attachout(cs4231.port[10], mpu98ii_o0); + iocore_attachinp(cs4231.port[10], mpu98ii_i0); + iocore_attachout(cs4231.port[10]+1, mpu98ii_o2); + iocore_attachinp(cs4231.port[10]+1, mpu98ii_i2); + } + } +} + +//#define MIDIIN_DEBUG + +void mpu98ii_callback(void) { + + UINT8 data; +#ifdef MIDIIN_DEBUG + static UINT8 testseq[] = {0x90, 0x3C, 0x7F}; + static int testseqpos = 0; + static DWORD time = 0; +#endif + + if (cm_mpu98) { + while((mpu98.r.cnt < MPU98_RECVBUFS) && + (cm_mpu98->read(cm_mpu98, &data) +#ifdef MIDIIN_DEBUG + || (np2cfg.asynccpu) +#endif + )) { + if (!mpu98.r.cnt) { + mpu98ii_int(); + } +#ifdef MIDIIN_DEBUG + data = testseq[testseqpos]; +#endif + setrecvdata(data); +#ifdef MIDIIN_DEBUG + if(testseqpos == sizeof(testseq) - 1){ + time = GetTickCount(); + testseq[1] = rand() & 0x7f; + } + testseqpos = (testseqpos + 1) % sizeof(testseq); +#endif + } + } +} + +void mpu98ii_midipanic(void) { + + if (cm_mpu98) { + cm_mpu98->msg(cm_mpu98, COMMSG_MIDIRESET, 0); + } +} + +void mpu98ii_changeclock(void) { + + if(mpu98.enable){ + mpu98.xferclock = pccore.realclock / (31250 / 8); + makeintclock(); + } +} + + diff --git a/cbus/mpu98ii.h b/cbus/mpu98ii.h old mode 100755 new mode 100644 index 4ab8a591..f2860007 --- a/cbus/mpu98ii.h +++ b/cbus/mpu98ii.h @@ -1,111 +1,111 @@ - -// ねこ専用ヘッダ - -enum { - MPU98_EXCVBUFS = 512, - MPU98_RECVBUFS = (1 << 7) -}; - -#define MPUTRDATAS 4 - -typedef struct { - UINT8 phase; - UINT8 step; - UINT8 cmd; - UINT8 rstat; - UINT datapos; - UINT datacnt; - UINT8 data[MPU98_EXCVBUFS]; -} MPUCMDS; - -typedef struct { - UINT8 step; - UINT8 datas; - UINT8 remain; - UINT8 rstat; - UINT8 recv; - UINT8 padding[2]; - UINT8 data[MPUTRDATAS]; -} MPUTR; - -typedef struct { - int cnt; - int pos; - UINT8 buf[MPU98_RECVBUFS]; -} MPURECV; - -typedef struct { - UINT8 enable; - - UINT16 port; - UINT8 irqnum; - UINT8 data; - - UINT32 xferclock; - SINT32 stepclock; - - UINT8 intphase; - UINT8 intreq; - UINT8 hclk_rem; - UINT8 hclk_cnt; - UINT8 hclk_step[4]; - - UINT8 acttr; - UINT8 status; - UINT8 mode; - UINT8 flag1; - UINT8 flag2; - - UINT8 tempo; - UINT8 reltempo; - UINT8 curtempo; - UINT8 inttimebase; - - UINT8 recvevent; - UINT8 remainstep; - UINT8 syncmode; - UINT8 metromode; - - UINT8 midipermetero; - UINT8 meteropermeas; - UINT8 sendplaycnt; - - UINT accch; - - MPURECV r; - - MPUCMDS cmd; - MPUTR tr[8]; - MPUCMDS cond; -} _MPU98II, *MPU98II; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern _MPU98II mpu98; - -void midiint(NEVENTITEM item); -void midiwaitout(NEVENTITEM item); - -void mpu98ii_construct(void); -void mpu98ii_destruct(void); - -void mpu98ii_reset(const NP2CFG *pConfig); -void mpu98ii_bind(void); - -void mpu98ii_callback(void); -void mpu98ii_midipanic(void); - -void mpu98ii_changeclock(void); - -void IOOUTCALL mpu98ii_o0(UINT port, REG8 dat); -void IOOUTCALL mpu98ii_o2(UINT port, REG8 dat); -REG8 IOINPCALL mpu98ii_i0(UINT port); -REG8 IOINPCALL mpu98ii_i2(UINT port); - -#ifdef __cplusplus -} -#endif - + +// ねこ専用ヘッダ + +enum { + MPU98_EXCVBUFS = 512, + MPU98_RECVBUFS = (1 << 7) +}; + +#define MPUTRDATAS 4 + +typedef struct { + UINT8 phase; + UINT8 step; + UINT8 cmd; + UINT8 rstat; + UINT datapos; + UINT datacnt; + UINT8 data[MPU98_EXCVBUFS]; +} MPUCMDS; + +typedef struct { + UINT8 step; + UINT8 datas; + UINT8 remain; + UINT8 rstat; + UINT8 recv; + UINT8 padding[2]; + UINT8 data[MPUTRDATAS]; +} MPUTR; + +typedef struct { + int cnt; + int pos; + UINT8 buf[MPU98_RECVBUFS]; +} MPURECV; + +typedef struct { + UINT8 enable; + + UINT16 port; + UINT8 irqnum; + UINT8 data; + + UINT32 xferclock; + SINT32 stepclock; + + UINT8 intphase; + UINT8 intreq; + UINT8 hclk_rem; + UINT8 hclk_cnt; + UINT8 hclk_step[4]; + + UINT8 acttr; + UINT8 status; + UINT8 mode; + UINT8 flag1; + UINT8 flag2; + + UINT8 tempo; + UINT8 reltempo; + UINT8 curtempo; + UINT8 inttimebase; + + UINT8 recvevent; + UINT8 remainstep; + UINT8 syncmode; + UINT8 metromode; + + UINT8 midipermetero; + UINT8 meteropermeas; + UINT8 sendplaycnt; + + UINT accch; + + MPURECV r; + + MPUCMDS cmd; + MPUTR tr[8]; + MPUCMDS cond; +} _MPU98II, *MPU98II; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _MPU98II mpu98; + +void midiint(NEVENTITEM item); +void midiwaitout(NEVENTITEM item); + +void mpu98ii_construct(void); +void mpu98ii_destruct(void); + +void mpu98ii_reset(const NP2CFG *pConfig); +void mpu98ii_bind(void); + +void mpu98ii_callback(void); +void mpu98ii_midipanic(void); + +void mpu98ii_changeclock(void); + +void IOOUTCALL mpu98ii_o0(UINT port, REG8 dat); +void IOOUTCALL mpu98ii_o2(UINT port, REG8 dat); +REG8 IOINPCALL mpu98ii_i0(UINT port); +REG8 IOINPCALL mpu98ii_i2(UINT port); + +#ifdef __cplusplus +} +#endif + diff --git a/cbus/pc9861k.c b/cbus/pc9861k.c old mode 100755 new mode 100644 index 1c5c76fe..878ba70d --- a/cbus/pc9861k.c +++ b/cbus/pc9861k.c @@ -1,350 +1,350 @@ -#include - -#if defined(SUPPORT_PC9861K) - -#include -#include -#include -#include -#include - - - _PC9861K pc9861k; - COMMNG cm_pc9861ch1; - COMMNG cm_pc9861ch2; - - -const UINT32 pc9861k_speed[11] = {75, 150, 300, 600, 1200, 2400, 4800, - 9600, 19200, 38400, 76800}; - -static const UINT8 ch1_irq[4] = {IRQ_INT0, IRQ_INT1, IRQ_INT2, IRQ_INT3}; -static const UINT8 ch2_irq[4] = {IRQ_INT0, IRQ_INT41, IRQ_INT5, IRQ_INT6}; -static const _PC9861CH pc9861def = - {0x05, 0xff, 7, 1, - 0, 0, 2400, NEVENT_MAXCLOCK, 0, 0, 0}; - - -// ---- - -static void pc9861k_callback(COMMNG cm, PC9861CH m) { - - BOOL interrupt; - - interrupt = FALSE; - if ((cm != NULL) && (cm->read(cm, &m->data))) { - m->result |= 2; - if (m->signal & 1) { - interrupt = TRUE; - } - } - else { - m->result &= ~2; - } - if (m->signal & 4) { - if (m->send) { - m->send = 0; - interrupt = TRUE; - } - } - if (interrupt) { - pic_setirq(m->irq); - } -} - -void pc9861ch1cb(NEVENTITEM item) { - - if (item->flag & NEVENT_SETEVENT) { - nevent_set(NEVENT_PC9861CH1, pc9861k.ch1.clk, pc9861ch1cb, - NEVENT_RELATIVE); - } - pc9861k_callback(cm_pc9861ch1, &pc9861k.ch1); -} - -void pc9861ch2cb(NEVENTITEM item) { - - if (item->flag & NEVENT_SETEVENT) { - nevent_set(NEVENT_PC9861CH2, pc9861k.ch2.clk, pc9861ch2cb, - NEVENT_RELATIVE); - } - pc9861k_callback(cm_pc9861ch2, &pc9861k.ch2); -} - -static UINT32 pc9861k_getspeed(REG8 dip) { - - UINT speed; - - speed = (((~dip) >> 2) & 0x0f) + 1; - if (dip & 0x02) { - if (speed > 4) { - speed -= 4; - } - else { - speed = 0; - } - } - if (speed > (NELEMENTS(pc9861k_speed) - 1)) { - speed = NELEMENTS(pc9861k_speed) - 1; - } - return(pc9861k_speed[speed]); -} - -static void pc9861_makeclk(PC9861CH m, UINT32 mul2) { - - m->clk = pccore.realclock * mul2 / ((m->speed) * 2); -} - -static void pc9861ch1_open(void) { - - cm_pc9861ch1 = commng_create(COMCREATE_PC9861K1, FALSE); - - pc9861k.ch1.dip = np2cfg.pc9861sw[0]; - pc9861k.ch1.speed = pc9861k_getspeed(pc9861k.ch1.dip); - pc9861k.ch1.vect = ((np2cfg.pc9861sw[1] >> 1) & 1) | - ((np2cfg.pc9861sw[1] << 1) & 2); - pc9861k.ch1.irq = ch1_irq[pc9861k.ch1.vect]; - pc9861_makeclk(&pc9861k.ch1, 10*2); - nevent_set(NEVENT_PC9861CH1, pc9861k.ch1.clk, - pc9861ch1cb, NEVENT_ABSOLUTE); -} - -static void pc9861ch2_open(void) { - - cm_pc9861ch2 = commng_create(COMCREATE_PC9861K2, FALSE); - - pc9861k.ch2.dip = np2cfg.pc9861sw[2]; - pc9861k.ch2.speed = pc9861k_getspeed(pc9861k.ch2.dip); - pc9861k.ch2.vect = ((np2cfg.pc9861sw[1] >> 3) & 1) | - ((np2cfg.pc9861sw[1] >> 1) & 2); - pc9861k.ch2.irq = ch1_irq[pc9861k.ch2.vect]; - pc9861_makeclk(&pc9861k.ch2, 10*2); - nevent_set(NEVENT_PC9861CH2, pc9861k.ch2.clk, - pc9861ch2cb, NEVENT_ABSOLUTE); -} - - -// ------------------------------------------------------------------------- - -static void IOOUTCALL pc9861data_w8(COMMNG cm, PC9861CH m, - UINT port, REG8 value) { - - UINT32 mul2; - - switch(port & 0x3) { - case 0x01: - cm->write(cm, (UINT8)value); - if (m->signal & 4) { - m->send = 0; - pic_setirq(m->irq); - } - else { - m->send = 1; - } - break; - - case 0x03: - if (!(value & 0xfd)) { - m->dummyinst += 1; - } - else { - if ((m->dummyinst >= 3) && (value == 0x40)) { - m->pos = 0; - } - m->dummyinst = 0; - } - switch(m->pos) { - case 0x00: // reset - m->pos += 1; - break; - - case 0x01: // mode - if (!(value & 0x03)) { - mul2 = 10 * 2; - } - else { - mul2 = ((value >> 1) & 6) + 10; - if (value & 0x10) { - mul2 += 2; - } - switch(value & 0xc0) { - case 0x80: - mul2 += 3; - break; - case 0xc0: - mul2 += 4; - break; - default: - mul2 += 2; - break; - } - } - pc9861_makeclk(m, mul2); - m->pos += 1; - break; - - case 0x02: // cmd - m->pos += 1; - break; - } - break; - } -} - -static REG8 IOINPCALL pc9861data_r8(COMMNG cm, PC9861CH m, UINT port) { - - switch(port & 0x3) { - case 0x01: - return(m->data); - - case 0x03: - if (!(cm->getstat(cm) & 0x20)) { - return((m->result) | 0x80); - } - return(m->result); - } - return(0xff); -} - - -static void IOOUTCALL pc9861k_ob0(UINT port, REG8 dat) { - - if (cm_pc9861ch1 == NULL) { - pc9861ch1_open(); - } - pc9861k.ch1.signal = dat; - (void)port; -} - -static void IOOUTCALL pc9861k_ob2(UINT port, REG8 dat) { - - if (cm_pc9861ch2 == NULL) { - pc9861ch2_open(); - } - pc9861k.ch2.signal = dat; - (void)port; -} - -static REG8 IOINPCALL pc9861k_ib0(UINT port) { - - if (cm_pc9861ch1 == NULL) { - pc9861ch1_open(); - } - if (cm_pc9861ch1 == NULL) { - return 0; - } - return(cm_pc9861ch1->getstat(cm_pc9861ch1) | pc9861k.ch1.vect); -} - -static REG8 IOINPCALL pc9861k_ib2(UINT port) { - - if (cm_pc9861ch2 == NULL) { - pc9861ch2_open(); - } - if (cm_pc9861ch1 == NULL) { - return 0; - } - return(cm_pc9861ch2->getstat(cm_pc9861ch2) | pc9861k.ch2.vect); -} - - -static void IOOUTCALL pc9861k_ob1(UINT port, REG8 dat) { - - if (cm_pc9861ch1 == NULL) { - pc9861ch1_open(); - } - pc9861data_w8(cm_pc9861ch1, &pc9861k.ch1, port, dat); -} - -static REG8 IOINPCALL pc9861k_ib1(UINT port) { - - if (cm_pc9861ch2 == NULL) { - pc9861ch1_open(); - } - return(pc9861data_r8(cm_pc9861ch1, &pc9861k.ch1, port)); -} - - -static void IOOUTCALL pc9861k_ob9(UINT port, REG8 dat) { - - if (cm_pc9861ch2 == NULL) { - pc9861ch2_open(); - } - pc9861data_w8(cm_pc9861ch2, &pc9861k.ch2, port, dat); -} - -static REG8 IOINPCALL pc9861k_ib9(UINT port) { - - if (cm_pc9861ch2 == NULL) { - pc9861ch2_open(); - } - return(pc9861data_r8(cm_pc9861ch2, &pc9861k.ch2, port)); -} - - -// ---- I/F - -void pc9861k_initialize(void) { - - cm_pc9861ch1 = NULL; - cm_pc9861ch2 = NULL; -} - -void pc9861k_deinitialize(void) { - - commng_destroy(cm_pc9861ch1); - cm_pc9861ch1 = NULL; - commng_destroy(cm_pc9861ch2); - cm_pc9861ch2 = NULL; -} - -void pc9861k_reset(const NP2CFG *pConfig) { - - commng_destroy(cm_pc9861ch1); - cm_pc9861ch1 = NULL; - commng_destroy(cm_pc9861ch2); - cm_pc9861ch2 = NULL; - - pc9861k.ch1 = pc9861def; - pc9861k.ch2 = pc9861def; - pc9861k.en = pConfig->pc9861enable & 1; - - if(cm_pc9861ch1 == NULL){ - cm_pc9861ch1 = commng_create(COMCREATE_PC9861K1, TRUE); - } - if(cm_pc9861ch2 == NULL){ - cm_pc9861ch2 = commng_create(COMCREATE_PC9861K2, TRUE); - } -} - -void pc9861k_bind(void) { - - pc9861k_deinitialize(); - if (pc9861k.en) { - iocore_attachout(0xb0, pc9861k_ob0); - iocore_attachout(0xb2, pc9861k_ob2); - iocore_attachinp(0xb0, pc9861k_ib0); - iocore_attachinp(0xb2, pc9861k_ib2); - - iocore_attachout(0xb1, pc9861k_ob1); - iocore_attachout(0xb3, pc9861k_ob1); - iocore_attachinp(0xb1, pc9861k_ib1); - iocore_attachinp(0xb3, pc9861k_ib1); - - iocore_attachout(0xb9, pc9861k_ob9); - iocore_attachout(0xbb, pc9861k_ob9); - iocore_attachinp(0xb9, pc9861k_ib9); - iocore_attachinp(0xbb, pc9861k_ib9); - } -} - -void pc9861k_midipanic(void) { - - if (cm_pc9861ch1) { - cm_pc9861ch1->msg(cm_pc9861ch1, COMMSG_MIDIRESET, 0); - } - if (cm_pc9861ch2) { - cm_pc9861ch2->msg(cm_pc9861ch1, COMMSG_MIDIRESET, 0); - } -} - -#endif - +#include + +#if defined(SUPPORT_PC9861K) + +#include +#include +#include +#include +#include + + + _PC9861K pc9861k; + COMMNG cm_pc9861ch1; + COMMNG cm_pc9861ch2; + + +const UINT32 pc9861k_speed[11] = {75, 150, 300, 600, 1200, 2400, 4800, + 9600, 19200, 38400, 76800}; + +static const UINT8 ch1_irq[4] = {IRQ_INT0, IRQ_INT1, IRQ_INT2, IRQ_INT3}; +static const UINT8 ch2_irq[4] = {IRQ_INT0, IRQ_INT41, IRQ_INT5, IRQ_INT6}; +static const _PC9861CH pc9861def = + {0x05, 0xff, 7, 1, + 0, 0, 2400, NEVENT_MAXCLOCK, 0, 0, 0}; + + +// ---- + +static void pc9861k_callback(COMMNG cm, PC9861CH m) { + + BOOL interrupt; + + interrupt = FALSE; + if ((cm != NULL) && (cm->read(cm, &m->data))) { + m->result |= 2; + if (m->signal & 1) { + interrupt = TRUE; + } + } + else { + m->result &= ~2; + } + if (m->signal & 4) { + if (m->send) { + m->send = 0; + interrupt = TRUE; + } + } + if (interrupt) { + pic_setirq(m->irq); + } +} + +void pc9861ch1cb(NEVENTITEM item) { + + if (item->flag & NEVENT_SETEVENT) { + nevent_set(NEVENT_PC9861CH1, pc9861k.ch1.clk, pc9861ch1cb, + NEVENT_RELATIVE); + } + pc9861k_callback(cm_pc9861ch1, &pc9861k.ch1); +} + +void pc9861ch2cb(NEVENTITEM item) { + + if (item->flag & NEVENT_SETEVENT) { + nevent_set(NEVENT_PC9861CH2, pc9861k.ch2.clk, pc9861ch2cb, + NEVENT_RELATIVE); + } + pc9861k_callback(cm_pc9861ch2, &pc9861k.ch2); +} + +static UINT32 pc9861k_getspeed(REG8 dip) { + + UINT speed; + + speed = (((~dip) >> 2) & 0x0f) + 1; + if (dip & 0x02) { + if (speed > 4) { + speed -= 4; + } + else { + speed = 0; + } + } + if (speed > (NELEMENTS(pc9861k_speed) - 1)) { + speed = NELEMENTS(pc9861k_speed) - 1; + } + return(pc9861k_speed[speed]); +} + +static void pc9861_makeclk(PC9861CH m, UINT32 mul2) { + + m->clk = pccore.realclock * mul2 / ((m->speed) * 2); +} + +static void pc9861ch1_open(void) { + + cm_pc9861ch1 = commng_create(COMCREATE_PC9861K1, FALSE); + + pc9861k.ch1.dip = np2cfg.pc9861sw[0]; + pc9861k.ch1.speed = pc9861k_getspeed(pc9861k.ch1.dip); + pc9861k.ch1.vect = ((np2cfg.pc9861sw[1] >> 1) & 1) | + ((np2cfg.pc9861sw[1] << 1) & 2); + pc9861k.ch1.irq = ch1_irq[pc9861k.ch1.vect]; + pc9861_makeclk(&pc9861k.ch1, 10*2); + nevent_set(NEVENT_PC9861CH1, pc9861k.ch1.clk, + pc9861ch1cb, NEVENT_ABSOLUTE); +} + +static void pc9861ch2_open(void) { + + cm_pc9861ch2 = commng_create(COMCREATE_PC9861K2, FALSE); + + pc9861k.ch2.dip = np2cfg.pc9861sw[2]; + pc9861k.ch2.speed = pc9861k_getspeed(pc9861k.ch2.dip); + pc9861k.ch2.vect = ((np2cfg.pc9861sw[1] >> 3) & 1) | + ((np2cfg.pc9861sw[1] >> 1) & 2); + pc9861k.ch2.irq = ch1_irq[pc9861k.ch2.vect]; + pc9861_makeclk(&pc9861k.ch2, 10*2); + nevent_set(NEVENT_PC9861CH2, pc9861k.ch2.clk, + pc9861ch2cb, NEVENT_ABSOLUTE); +} + + +// ------------------------------------------------------------------------- + +static void IOOUTCALL pc9861data_w8(COMMNG cm, PC9861CH m, + UINT port, REG8 value) { + + UINT32 mul2; + + switch(port & 0x3) { + case 0x01: + cm->write(cm, (UINT8)value); + if (m->signal & 4) { + m->send = 0; + pic_setirq(m->irq); + } + else { + m->send = 1; + } + break; + + case 0x03: + if (!(value & 0xfd)) { + m->dummyinst += 1; + } + else { + if ((m->dummyinst >= 3) && (value == 0x40)) { + m->pos = 0; + } + m->dummyinst = 0; + } + switch(m->pos) { + case 0x00: // reset + m->pos += 1; + break; + + case 0x01: // mode + if (!(value & 0x03)) { + mul2 = 10 * 2; + } + else { + mul2 = ((value >> 1) & 6) + 10; + if (value & 0x10) { + mul2 += 2; + } + switch(value & 0xc0) { + case 0x80: + mul2 += 3; + break; + case 0xc0: + mul2 += 4; + break; + default: + mul2 += 2; + break; + } + } + pc9861_makeclk(m, mul2); + m->pos += 1; + break; + + case 0x02: // cmd + m->pos += 1; + break; + } + break; + } +} + +static REG8 IOINPCALL pc9861data_r8(COMMNG cm, PC9861CH m, UINT port) { + + switch(port & 0x3) { + case 0x01: + return(m->data); + + case 0x03: + if (!(cm->getstat(cm) & 0x20)) { + return((m->result) | 0x80); + } + return(m->result); + } + return(0xff); +} + + +static void IOOUTCALL pc9861k_ob0(UINT port, REG8 dat) { + + if (cm_pc9861ch1 == NULL) { + pc9861ch1_open(); + } + pc9861k.ch1.signal = dat; + (void)port; +} + +static void IOOUTCALL pc9861k_ob2(UINT port, REG8 dat) { + + if (cm_pc9861ch2 == NULL) { + pc9861ch2_open(); + } + pc9861k.ch2.signal = dat; + (void)port; +} + +static REG8 IOINPCALL pc9861k_ib0(UINT port) { + + if (cm_pc9861ch1 == NULL) { + pc9861ch1_open(); + } + if (cm_pc9861ch1 == NULL) { + return 0; + } + return(cm_pc9861ch1->getstat(cm_pc9861ch1) | pc9861k.ch1.vect); +} + +static REG8 IOINPCALL pc9861k_ib2(UINT port) { + + if (cm_pc9861ch2 == NULL) { + pc9861ch2_open(); + } + if (cm_pc9861ch1 == NULL) { + return 0; + } + return(cm_pc9861ch2->getstat(cm_pc9861ch2) | pc9861k.ch2.vect); +} + + +static void IOOUTCALL pc9861k_ob1(UINT port, REG8 dat) { + + if (cm_pc9861ch1 == NULL) { + pc9861ch1_open(); + } + pc9861data_w8(cm_pc9861ch1, &pc9861k.ch1, port, dat); +} + +static REG8 IOINPCALL pc9861k_ib1(UINT port) { + + if (cm_pc9861ch2 == NULL) { + pc9861ch1_open(); + } + return(pc9861data_r8(cm_pc9861ch1, &pc9861k.ch1, port)); +} + + +static void IOOUTCALL pc9861k_ob9(UINT port, REG8 dat) { + + if (cm_pc9861ch2 == NULL) { + pc9861ch2_open(); + } + pc9861data_w8(cm_pc9861ch2, &pc9861k.ch2, port, dat); +} + +static REG8 IOINPCALL pc9861k_ib9(UINT port) { + + if (cm_pc9861ch2 == NULL) { + pc9861ch2_open(); + } + return(pc9861data_r8(cm_pc9861ch2, &pc9861k.ch2, port)); +} + + +// ---- I/F + +void pc9861k_initialize(void) { + + cm_pc9861ch1 = NULL; + cm_pc9861ch2 = NULL; +} + +void pc9861k_deinitialize(void) { + + commng_destroy(cm_pc9861ch1); + cm_pc9861ch1 = NULL; + commng_destroy(cm_pc9861ch2); + cm_pc9861ch2 = NULL; +} + +void pc9861k_reset(const NP2CFG *pConfig) { + + commng_destroy(cm_pc9861ch1); + cm_pc9861ch1 = NULL; + commng_destroy(cm_pc9861ch2); + cm_pc9861ch2 = NULL; + + pc9861k.ch1 = pc9861def; + pc9861k.ch2 = pc9861def; + pc9861k.en = pConfig->pc9861enable & 1; + + if(cm_pc9861ch1 == NULL){ + cm_pc9861ch1 = commng_create(COMCREATE_PC9861K1, TRUE); + } + if(cm_pc9861ch2 == NULL){ + cm_pc9861ch2 = commng_create(COMCREATE_PC9861K2, TRUE); + } +} + +void pc9861k_bind(void) { + + pc9861k_deinitialize(); + if (pc9861k.en) { + iocore_attachout(0xb0, pc9861k_ob0); + iocore_attachout(0xb2, pc9861k_ob2); + iocore_attachinp(0xb0, pc9861k_ib0); + iocore_attachinp(0xb2, pc9861k_ib2); + + iocore_attachout(0xb1, pc9861k_ob1); + iocore_attachout(0xb3, pc9861k_ob1); + iocore_attachinp(0xb1, pc9861k_ib1); + iocore_attachinp(0xb3, pc9861k_ib1); + + iocore_attachout(0xb9, pc9861k_ob9); + iocore_attachout(0xbb, pc9861k_ob9); + iocore_attachinp(0xb9, pc9861k_ib9); + iocore_attachinp(0xbb, pc9861k_ib9); + } +} + +void pc9861k_midipanic(void) { + + if (cm_pc9861ch1) { + cm_pc9861ch1->msg(cm_pc9861ch1, COMMSG_MIDIRESET, 0); + } + if (cm_pc9861ch2) { + cm_pc9861ch2->msg(cm_pc9861ch1, COMMSG_MIDIRESET, 0); + } +} + +#endif + diff --git a/cbus/pc9861k.h b/cbus/pc9861k.h old mode 100755 new mode 100644 index 9b3ef4a2..38f65856 --- a/cbus/pc9861k.h +++ b/cbus/pc9861k.h @@ -1,56 +1,56 @@ - -#if !defined(SUPPORT_PC9861K) - -#define pc9861k_initialize() -#define pc9861k_deinitialize() -#define pc9861k_midipanic() - -#else - -typedef struct { - UINT8 result; - UINT8 data; - UINT8 signal; - UINT8 send; - - UINT pos; - UINT dummyinst; - UINT32 speed; - SINT32 clk; - - UINT8 dip; - UINT8 vect; - UINT8 irq; -} _PC9861CH, *PC9861CH; - -typedef struct { - _PC9861CH ch1; - _PC9861CH ch2; - BOOL en; -} _PC9861K, *PC9861K; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern const UINT32 pc9861k_speed[11]; -extern _PC9861K pc9861k; - -void pc9861ch1cb(NEVENTITEM item); -void pc9861ch2cb(NEVENTITEM item); - -void pc9861k_initialize(void); -void pc9861k_deinitialize(void); - -void pc9861k_reset(const NP2CFG *pConfig); -void pc9861k_bind(void); - -void pc9861k_midipanic(void); - -#ifdef __cplusplus -} -#endif - -#endif - + +#if !defined(SUPPORT_PC9861K) + +#define pc9861k_initialize() +#define pc9861k_deinitialize() +#define pc9861k_midipanic() + +#else + +typedef struct { + UINT8 result; + UINT8 data; + UINT8 signal; + UINT8 send; + + UINT pos; + UINT dummyinst; + UINT32 speed; + SINT32 clk; + + UINT8 dip; + UINT8 vect; + UINT8 irq; +} _PC9861CH, *PC9861CH; + +typedef struct { + _PC9861CH ch1; + _PC9861CH ch2; + BOOL en; +} _PC9861K, *PC9861K; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern const UINT32 pc9861k_speed[11]; +extern _PC9861K pc9861k; + +void pc9861ch1cb(NEVENTITEM item); +void pc9861ch2cb(NEVENTITEM item); + +void pc9861k_initialize(void); +void pc9861k_deinitialize(void); + +void pc9861k_reset(const NP2CFG *pConfig); +void pc9861k_bind(void); + +void pc9861k_midipanic(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/cbus/pcm86io.c b/cbus/pcm86io.c old mode 100755 new mode 100644 index 3a41c8c3..a801274c --- a/cbus/pcm86io.c +++ b/cbus/pcm86io.c @@ -1,517 +1,517 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#undef TRACEOUT -#define TRACEOUT(s) (void)(s) -static void trace_fmt_ex(const char* fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#endif /* 1 */ - - -extern PCM86CFG pcm86cfg; - -extern UINT64 datawriteirqwait; - -static const UINT8 pcm86bits[] = {1, 1, 1, 2, 0, 0, 0, 1}; -static const SINT32 pcm86rescue[] = {PCM86_RESCUE * 32, PCM86_RESCUE * 24, - PCM86_RESCUE * 16, PCM86_RESCUE * 12, - PCM86_RESCUE * 8, PCM86_RESCUE * 6, - PCM86_RESCUE * 4, PCM86_RESCUE * 3}; - -static const UINT8 s_irqtable[8] = {0xff, 0xff, 0xff, 0xff, 0x03, 0x0a, 0x0d, 0x0c}; - -// for Q-Vision Wave Star (XXX: この辺のポートを操作中にResumeやStateSaveを使うとやばい) -static void pcm86_updateWaveStarPorts(); -REG8 wavestar_a462_seq[] = {0xa6, 0xd3, 0x69, 0xb4, 0x5a}; -REG8 wavestar_a462_seq_index = 0; -REG8 wavestar_a464_value = 0xff; - -static void IOOUTCALL pcm86_oa460(UINT port, REG8 val) -{ -// TRACEOUT(("86pcm out %.4x %.2x", port, val)); - g_pcm86.soundflags = (g_pcm86.soundflags & 0xfe) | (val & 1); - fmboard_extenable((REG8)(val & 1)); - (void)port; -} - -static void IOOUTCALL pcm86_oa466(UINT port, REG8 val) { - -// TRACEOUT(("86pcm out %.4x %.2x", port, val)); - if ((val & 0xe0) == 0xa0) { - sound_sync(); - g_pcm86.vol5 = (~val) & 15; - g_pcm86.volume = pcm86cfg.vol * g_pcm86.vol5; - } - // WaveStar FM音量? - if((g_nSoundID == SOUNDID_WAVESTAR && (val & 0xe0) == 0x00)){ - UINT i; - cs4231.devvolume[0xff] = (~val) & 15; - opngen_setvol(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - psggen_setvol(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - rhythm_setvol(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); -#if defined(SUPPORT_FMGEN) - if(np2cfg.usefmgen) { - opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - } -#endif - for (i = 0; i < NELEMENTS(g_opna); i++) - { - rhythm_update(&g_opna[i].rhythm); - } - } - - (void)port; -} - -static void IOOUTCALL pcm86_oa468(UINT port, REG8 val) { - - REG8 xchgbit; - UINT64 curclk = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - -// TRACEOUT(("86pcm out %.4x %.2x", port, val)); - sound_sync(); - xchgbit = g_pcm86.fifo ^ val; - // バッファリセット判定 - if (xchgbit & 8) - { - if (val & 8) - { -#if defined(SUPPORT_MULTITHREAD) - pcm86cs_enter_criticalsection(); -#endif - // バッファリセット - g_pcm86.wrtpos = 0; - g_pcm86.readpos = 0; - g_pcm86.realbuf = 0; - g_pcm86.virbuf = 0; - g_pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - g_pcm86.lastclock <<= 6; - g_pcm86.lastclockforwait = curclk; -#if defined(SUPPORT_MULTITHREAD) - pcm86cs_leave_criticalsection(); -#endif - } - } - // 割り込み消去 - if ((!(val & 0x10))) - { - g_pcm86.irqflag = 0; - if (g_pcm86.virbuf == 0) { - // WORKAROUND: 割り込みクリア時にバッファが空の状態だったら、長めの割り込み待ちを入れる - g_pcm86.lastclockforwait = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - } - } - // 割り込み条件を満たしていれば強制的に割り込む ポリスノーツ用 - if (g_pcm86.virbuf <= g_pcm86.fifosize) - { - g_pcm86.irqflag = 1; - //g_pcm86.reqirq = 1; - } - // サンプリングレート変更 - if (xchgbit & 7) { - g_pcm86.rescue = pcm86rescue[val & 7] << g_pcm86.stepbit; - pcm86_setpcmrate(val); - } - g_pcm86.fifo = val; - if ((xchgbit & 0x80) && (val & 0x80)) { - g_pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - g_pcm86.lastclock <<= 6; - } - if (g_pcm86.reqirq) - { - pcm86_setnextintr(); - } - (void)port; -} - -static void IOOUTCALL pcm86_oa46a(UINT port, REG8 val) { - -// TRACEOUT(("86pcm out %.4x %.2x", port, val)); - sound_sync(); - if (g_pcm86.fifo & 0x20) { -#if 1 - if (val != 0xff) { - g_pcm86.fifosize = (UINT16)((val + 1) << 7); - } - else { - g_pcm86.fifosize = 0x7ffc; - } -#else - if (!val) { - val++; - } - g_pcm86.fifosize = (WORD)(val) << 7; -#endif - } - else { - if ((val & 0xf) == 0xf) - { - return; // WORKAROUND: WinNT 3.5向け 異常設定値を弾く - } - g_pcm86.dactrl = val; - g_pcm86.stepbit = pcm86bits[(val >> 4) & 7]; - g_pcm86.stepmask = (1 << g_pcm86.stepbit) - 1; - g_pcm86.rescue = pcm86rescue[g_pcm86.fifo & 7] << g_pcm86.stepbit; - } - if (g_pcm86.reqirq) - { - pcm86_setnextintr(); - } - (void)port; -} - -static void IOOUTCALL pcm86_oa46c(UINT port, REG8 val) { - - UINT64 addClock = 0; - -// TRACEOUT(("86pcm out %.4x %.2x", port, val)); -#if defined(SUPPORT_MULTITHREAD) - pcm86cs_enter_criticalsection(); -#endif -#if 1 - if (g_pcm86.virbuf < PCM86_LOGICALBUF) { - g_pcm86.virbuf++; - } - g_pcm86.buffer[g_pcm86.wrtpos] = val; - g_pcm86.wrtpos = (g_pcm86.wrtpos + 1) & PCM86_BUFMSK; - g_pcm86.realbuf++; - // バッファオーバーフローの監視 - if (g_pcm86.realbuf >= PCM86_REALBUFSIZE) { -#if 1 - g_pcm86.realbuf -= 4; - g_pcm86.readpos = (g_pcm86.readpos + 4) & PCM86_BUFMSK; -#else - g_pcm86.realbuf &= 3; // align4決めウチ - g_pcm86.realbuf += PCM86_REALBUFSIZE - 4; -#endif - } -// g_pcm86.write = 1; - g_pcm86.reqirq = 1; - - // WORKAROUND: ウェイト時間はfifosizeに比例するものとする 根拠なし 元のdatawriteirqwaitは8192の場合の実験値 - if (g_pcm86.fifosize < 8192) { - addClock = datawriteirqwait - datawriteirqwait * g_pcm86.fifosize / 8192; - } - // WORKAROUND: バッファがFIFO割り込みサイズの2倍以上満たされているか、フル状態か、FIFO割り込みサイズが小さいなら割り込みウェイトはかけないことにする 根拠なし - // 上の「ウェイト時間はfifosizeに比例する」だけあればOK?? - if (g_pcm86.virbuf > g_pcm86.fifosize * 2 || g_pcm86.virbuf >= PCM86_LOGICALBUF) { - addClock = datawriteirqwait; - } - g_pcm86.lastclockforwait = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK + addClock; -#else - if (g_pcm86.virbuf < PCM86_LOGICALBUF) { - g_pcm86.virbuf++; - g_pcm86.buffer[g_pcm86.wrtpos] = val; - g_pcm86.wrtpos = (g_pcm86.wrtpos + 1) & PCM86_BUFMSK; - g_pcm86.realbuf++; - // バッファオーバーフローの監視 - if (g_pcm86.realbuf >= PCM86_REALBUFSIZE) { - g_pcm86.realbuf &= 3; // align4決めウチ - g_pcm86.realbuf += PCM86_REALBUFSIZE - 4; - } -// g_pcm86.write = 1; - g_pcm86.reqirq = 1; - } -#endif -#if defined(SUPPORT_MULTITHREAD) - pcm86cs_leave_criticalsection(); -#endif - (void)port; -} - -static REG8 IOINPCALL pcm86_ia460(UINT port) -{ - (void)port; - return g_pcm86.soundflags; -} - -static REG8 IOINPCALL pcm86_ia466(UINT port) { - - UINT64 cur; - UINT64 past; - UINT64 pastCycle; - UINT64 cnt; - UINT64 stepclock; - REG8 ret; - int smpsize[0x8] = { 0, 2, 2, 4, 0, 1, 1, 2 }; - - stepclock = g_pcm86.stepclock; - - pastCycle = (UINT64)UINT_MAX << 6; - cur = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - cur <<= 6; - past = (cur + pastCycle - g_pcm86.lastclock) % pastCycle; - if (past > pastCycle / 2) - { - // 負の値になってしまっているとき - if (past < pastCycle - stepclock * 4) - { - // かなり小さいならリセットをかける - past = 1; - g_pcm86.lastclock = cur - 1; - } - else - { - // 小さいなら様子見で0扱いとする - past = 0; - } - } - if (past >= g_pcm86.stepclock) - { - cnt = past / stepclock; - g_pcm86.lastclock = (g_pcm86.lastclock + cnt * stepclock) % pastCycle; - past -= cnt * stepclock; - if (g_pcm86.fifo & 0x80) - { - RECALC_NOWCLKWAIT(cnt); - } - } - ret = ((past << 1) >= stepclock) ? 1 : 0; - if (g_pcm86.virbuf >= PCM86_LOGICALBUF) { // バッファフル - ret |= 0x80; - } - else if (g_pcm86.virbuf <= g_pcm86.stepmask) { // バッファ0 stepmask以下のときも実質空 - ret |= 0x40; // ちと変… - } - (void)port; -// TRACEOUT(("86pcm in %.4x %.2x", port, ret)); - return(ret); -} - -static REG8 IOINPCALL pcm86_ia468(UINT port) { - - REG8 ret; - - ret = g_pcm86.fifo & (~0x10); -#if 1 - if (pcm86gen_intrq(0)) { - ret |= 0x10; - } -#elif 1 // むしろこう? - if (g_pcm86.fifo & 0x20) { - sound_sync(); - if (g_pcm86.virbuf <= g_pcm86.fifosize) { - if (g_pcm86.write) { - g_pcm86.write = 0; - } - else { - ret |= 0x10; - } - } - } -#else - if ((g_pcm86.write) && (g_pcm86.fifo & 0x20)) { -// g_pcm86.write = 0; - sound_sync(); - if (g_pcm86.virbuf <= g_pcm86.fifosize) { - g_pcm86.write = 0; - ret |= 0x10; - } - } -#endif - (void)port; -// TRACEOUT(("86pcm in %.4x %.2x", port, ret)); - return(ret); -} - -static REG8 IOINPCALL pcm86_ia46a(UINT port) { - - (void)port; -// TRACEOUT(("86pcm in %.4x %.2x", port, g_pcm86.dactrl)); - return(g_pcm86.dactrl); -} - -static REG8 IOINPCALL pcm86_inpdummy(UINT port) { - - (void)port; - return(0); -} - -// for Q-Vision Wave Star -static void IOOUTCALL pcm86_oa462(UINT port, REG8 val) -{ - if(wavestar_a462_seq_index < sizeof(wavestar_a462_seq) && val == wavestar_a462_seq[wavestar_a462_seq_index]){ - wavestar_a462_seq_index++; - if(wavestar_a462_seq_index == sizeof(wavestar_a462_seq)){ - wavestar_a464_value = 0x0b; - } - }else if(val == wavestar_a462_seq[0]){ - wavestar_a462_seq_index = 1; - }else{ - wavestar_a462_seq_index = 0; - } - (void)port; -} -static REG8 IOINPCALL pcm86_ia462(UINT port) { - - (void)port; - - return(0xff); -} -static void IOOUTCALL pcm86_oa464(UINT port, REG8 val) -{ - if(wavestar_a462_seq_index == sizeof(wavestar_a462_seq)){ - if(val == 0x04){ - cs4231.devvolume[0xfe] = 1; // XXX: 暫定でフラグ用に借りる(本来は変数を追加すべき) - wavestar_a464_value = 0x0c; - }else{ - cs4231.devvolume[0xfe] = 0; // XXX: 暫定でフラグ用に借りる(本来は変数を追加すべき) - wavestar_a464_value = 0x08; - } - pcm86_updateWaveStarPorts(); - } - if(val == 0x09) wavestar_a464_value = 0xff; - (void)port; -} -static REG8 IOINPCALL pcm86_ia464(UINT port) { - - REG8 ret; - (void)port; - if(wavestar_a462_seq_index != sizeof(wavestar_a462_seq)){ - wavestar_a464_value = 0xff; - } - ret = wavestar_a464_value; - if(wavestar_a464_value==0x00){ - wavestar_a464_value = 0xff; - }else{ - wavestar_a464_value = 0x00; - } - return(ret); -} -static void pcm86_updateWaveStarPorts(){ - if(cs4231.devvolume[0xfe]){ - // I/OポートをWSSに変更 - iocore_detachout(0xa460); - //iocore_attachout(0xa464, cs4231io0_w8_wavestar); - iocore_attachout(0xa466, cs4231io0_w8_wavestar); - iocore_attachout(0xa468, cs4231io0_w8_wavestar); - iocore_attachout(0xa46a, cs4231io0_w8_wavestar); - iocore_attachout(0xa46c, cs4231io0_w8_wavestar); - iocore_detachinp(0xa460); - iocore_attachinp(0xa464, cs4231io0_r8_wavestar); - iocore_attachinp(0xa466, cs4231io0_r8_wavestar); - iocore_attachinp(0xa468, cs4231io0_r8_wavestar); - iocore_attachinp(0xa46a, cs4231io0_r8_wavestar); - iocore_attachinp(0xa46c, cs4231io0_r8_wavestar); - - // OPNA割り込み無効 - g_pcm86.irq = 0xff; - g_opna[0].s.irq = 0xff; - }else{ - // I/Oポートを86互換に変更 - iocore_attachout(0xa460, pcm86_oa460); - iocore_attachout(0xa462, pcm86_oa462); - iocore_attachout(0xa464, pcm86_oa464); - iocore_attachout(0xa466, pcm86_oa466); - iocore_attachout(0xa468, pcm86_oa468); - iocore_attachout(0xa46a, pcm86_oa46a); - iocore_attachout(0xa46c, pcm86_oa46c); - iocore_attachinp(0xa460, pcm86_ia460); - iocore_attachinp(0xa462, pcm86_ia462); - iocore_attachinp(0xa464, pcm86_ia464); - iocore_attachinp(0xa466, pcm86_ia466); - iocore_attachinp(0xa468, pcm86_ia468); - iocore_attachinp(0xa46a, pcm86_ia46a); - iocore_attachinp(0xa46c, pcm86_inpdummy); - iocore_attachinp(0xa46e, pcm86_inpdummy); - - // OPNA割り込み有効 - g_pcm86.irq = cs4231.devvolume[0xfd]; - g_opna[0].s.irq = cs4231.devvolume[0xfc]; - } -} - - -// ---- - -/** - * Reset - * @param[in] cDipSw Dip switch - */ -void pcm86io_setopt(REG8 cDipSw) -{ - g_pcm86.soundflags = ((~cDipSw) >> 1) & 0x70; - g_pcm86.irq = s_irqtable[(cDipSw >> 2) & 7]; - - if(g_nSoundID==SOUNDID_WAVESTAR){ - g_pcm86.soundflags = 0x41; - fmboard_extenable(1); - cs4231.devvolume[0xfd] = g_pcm86.irq; - cs4231.devvolume[0xfc] = g_opna[0].s.irq; - } -} - -void pcm86io_bind(void) { - - sound_streamregist(&g_pcm86, (SOUNDCB)pcm86gen_getpcm); - - iocore_attachout(0xa460, pcm86_oa460); - if(g_nSoundID == SOUNDID_WAVESTAR){ - iocore_attachout(0xa462, pcm86_oa462); - iocore_attachout(0xa464, pcm86_oa464); - wavestar_a462_seq_index = 0; - wavestar_a464_value = 0xff; - } - iocore_attachout(0xa466, pcm86_oa466); - iocore_attachout(0xa468, pcm86_oa468); - iocore_attachout(0xa46a, pcm86_oa46a); - iocore_attachout(0xa46c, pcm86_oa46c); - - iocore_attachinp(0xa460, pcm86_ia460); - if(g_nSoundID == SOUNDID_WAVESTAR){ - iocore_attachinp(0xa462, pcm86_ia462); - iocore_attachinp(0xa464, pcm86_ia464); - }else{ - iocore_attachinp(0xa462, pcm86_inpdummy); - iocore_attachinp(0xa464, pcm86_inpdummy); - } - iocore_attachinp(0xa466, pcm86_ia466); - iocore_attachinp(0xa468, pcm86_ia468); - iocore_attachinp(0xa46a, pcm86_ia46a); - iocore_attachinp(0xa46c, pcm86_inpdummy); - iocore_attachinp(0xa46e, pcm86_inpdummy); - - if(g_nSoundID == SOUNDID_WAVESTAR){ - pcm86_updateWaveStarPorts(); - } -} -void pcm86io_unbind(void) { - - iocore_detachout(0xa460); - if(g_nSoundID == SOUNDID_WAVESTAR){ - iocore_detachout(0xa462); - iocore_detachout(0xa464); - } - iocore_detachout(0xa466); - iocore_detachout(0xa468); - iocore_detachout(0xa46a); - iocore_detachout(0xa46c); - - iocore_detachinp(0xa460); - iocore_detachinp(0xa462); - iocore_detachinp(0xa464); - iocore_detachinp(0xa466); - iocore_detachinp(0xa468); - iocore_detachinp(0xa46a); - iocore_detachinp(0xa46c); - iocore_detachinp(0xa46e); -} - +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#undef TRACEOUT +#define TRACEOUT(s) (void)(s) +static void trace_fmt_ex(const char* fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "¥n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#endif /* 1 */ + + +extern PCM86CFG pcm86cfg; + +extern UINT64 datawriteirqwait; + +static const UINT8 pcm86bits[] = {1, 1, 1, 2, 0, 0, 0, 1}; +static const SINT32 pcm86rescue[] = {PCM86_RESCUE * 32, PCM86_RESCUE * 24, + PCM86_RESCUE * 16, PCM86_RESCUE * 12, + PCM86_RESCUE * 8, PCM86_RESCUE * 6, + PCM86_RESCUE * 4, PCM86_RESCUE * 3}; + +static const UINT8 s_irqtable[8] = {0xff, 0xff, 0xff, 0xff, 0x03, 0x0a, 0x0d, 0x0c}; + +// for Q-Vision Wave Star (XXX: この辺のポートを操作中にResumeやStateSaveを使うとやばい) +static void pcm86_updateWaveStarPorts(); +REG8 wavestar_a462_seq[] = {0xa6, 0xd3, 0x69, 0xb4, 0x5a}; +REG8 wavestar_a462_seq_index = 0; +REG8 wavestar_a464_value = 0xff; + +static void IOOUTCALL pcm86_oa460(UINT port, REG8 val) +{ +// TRACEOUT(("86pcm out %.4x %.2x", port, val)); + g_pcm86.soundflags = (g_pcm86.soundflags & 0xfe) | (val & 1); + fmboard_extenable((REG8)(val & 1)); + (void)port; +} + +static void IOOUTCALL pcm86_oa466(UINT port, REG8 val) { + +// TRACEOUT(("86pcm out %.4x %.2x", port, val)); + if ((val & 0xe0) == 0xa0) { + sound_sync(); + g_pcm86.vol5 = (~val) & 15; + g_pcm86.volume = pcm86cfg.vol * g_pcm86.vol5; + } + // WaveStar FM音量? + if((g_nSoundID == SOUNDID_WAVESTAR && (val & 0xe0) == 0x00)){ + UINT i; + cs4231.devvolume[0xff] = (~val) & 15; + opngen_setvol(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + psggen_setvol(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + rhythm_setvol(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); +#if defined(SUPPORT_FMGEN) + if(np2cfg.usefmgen) { + opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + } +#endif + for (i = 0; i < NELEMENTS(g_opna); i++) + { + rhythm_update(&g_opna[i].rhythm); + } + } + + (void)port; +} + +static void IOOUTCALL pcm86_oa468(UINT port, REG8 val) { + + REG8 xchgbit; + UINT64 curclk = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + +// TRACEOUT(("86pcm out %.4x %.2x", port, val)); + sound_sync(); + xchgbit = g_pcm86.fifo ^ val; + // バッファリセット判定 + if (xchgbit & 8) + { + if (val & 8) + { +#if defined(SUPPORT_MULTITHREAD) + pcm86cs_enter_criticalsection(); +#endif + // バッファリセット + g_pcm86.wrtpos = 0; + g_pcm86.readpos = 0; + g_pcm86.realbuf = 0; + g_pcm86.virbuf = 0; + g_pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + g_pcm86.lastclock <<= 6; + g_pcm86.lastclockforwait = curclk; +#if defined(SUPPORT_MULTITHREAD) + pcm86cs_leave_criticalsection(); +#endif + } + } + // 割り込み消去 + if ((!(val & 0x10))) + { + g_pcm86.irqflag = 0; + if (g_pcm86.virbuf == 0) { + // WORKAROUND: 割り込みクリア時にバッファが空の状態だったら、長めの割り込み待ちを入れる + g_pcm86.lastclockforwait = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + } + } + // 割り込み条件を満たしていれば強制的に割り込む ポリスノーツ用 + if (g_pcm86.virbuf <= g_pcm86.fifosize) + { + g_pcm86.irqflag = 1; + //g_pcm86.reqirq = 1; + } + // サンプリングレート変更 + if (xchgbit & 7) { + g_pcm86.rescue = pcm86rescue[val & 7] << g_pcm86.stepbit; + pcm86_setpcmrate(val); + } + g_pcm86.fifo = val; + if ((xchgbit & 0x80) && (val & 0x80)) { + g_pcm86.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + g_pcm86.lastclock <<= 6; + } + if (g_pcm86.reqirq) + { + pcm86_setnextintr(); + } + (void)port; +} + +static void IOOUTCALL pcm86_oa46a(UINT port, REG8 val) { + +// TRACEOUT(("86pcm out %.4x %.2x", port, val)); + sound_sync(); + if (g_pcm86.fifo & 0x20) { +#if 1 + if (val != 0xff) { + g_pcm86.fifosize = (UINT16)((val + 1) << 7); + } + else { + g_pcm86.fifosize = 0x7ffc; + } +#else + if (!val) { + val++; + } + g_pcm86.fifosize = (WORD)(val) << 7; +#endif + } + else { + if ((val & 0xf) == 0xf) + { + return; // WORKAROUND: WinNT 3.5向け 異常設定値を弾く + } + g_pcm86.dactrl = val; + g_pcm86.stepbit = pcm86bits[(val >> 4) & 7]; + g_pcm86.stepmask = (1 << g_pcm86.stepbit) - 1; + g_pcm86.rescue = pcm86rescue[g_pcm86.fifo & 7] << g_pcm86.stepbit; + } + if (g_pcm86.reqirq) + { + pcm86_setnextintr(); + } + (void)port; +} + +static void IOOUTCALL pcm86_oa46c(UINT port, REG8 val) { + + UINT64 addClock = 0; + +// TRACEOUT(("86pcm out %.4x %.2x", port, val)); +#if defined(SUPPORT_MULTITHREAD) + pcm86cs_enter_criticalsection(); +#endif +#if 1 + if (g_pcm86.virbuf < PCM86_LOGICALBUF) { + g_pcm86.virbuf++; + } + g_pcm86.buffer[g_pcm86.wrtpos] = val; + g_pcm86.wrtpos = (g_pcm86.wrtpos + 1) & PCM86_BUFMSK; + g_pcm86.realbuf++; + // バッファオーバーフローの監視 + if (g_pcm86.realbuf >= PCM86_REALBUFSIZE) { +#if 1 + g_pcm86.realbuf -= 4; + g_pcm86.readpos = (g_pcm86.readpos + 4) & PCM86_BUFMSK; +#else + g_pcm86.realbuf &= 3; // align4決めウチ + g_pcm86.realbuf += PCM86_REALBUFSIZE - 4; +#endif + } +// g_pcm86.write = 1; + g_pcm86.reqirq = 1; + + // WORKAROUND: ウェイト時間はfifosizeに比例するものとする 根拠なし 元のdatawriteirqwaitは8192の場合の実験値 + if (g_pcm86.fifosize < 8192) { + addClock = datawriteirqwait - datawriteirqwait * g_pcm86.fifosize / 8192; + } + // WORKAROUND: バッファがFIFO割り込みサイズの2倍以上満たされているか、フル状態か、FIFO割り込みサイズが小さいなら割り込みウェイトはかけないことにする 根拠なし + // 上の「ウェイト時間はfifosizeに比例する」だけあればOK?? + if (g_pcm86.virbuf > g_pcm86.fifosize * 2 || g_pcm86.virbuf >= PCM86_LOGICALBUF) { + addClock = datawriteirqwait; + } + g_pcm86.lastclockforwait = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK + addClock; +#else + if (g_pcm86.virbuf < PCM86_LOGICALBUF) { + g_pcm86.virbuf++; + g_pcm86.buffer[g_pcm86.wrtpos] = val; + g_pcm86.wrtpos = (g_pcm86.wrtpos + 1) & PCM86_BUFMSK; + g_pcm86.realbuf++; + // バッファオーバーフローの監視 + if (g_pcm86.realbuf >= PCM86_REALBUFSIZE) { + g_pcm86.realbuf &= 3; // align4決めウチ + g_pcm86.realbuf += PCM86_REALBUFSIZE - 4; + } +// g_pcm86.write = 1; + g_pcm86.reqirq = 1; + } +#endif +#if defined(SUPPORT_MULTITHREAD) + pcm86cs_leave_criticalsection(); +#endif + (void)port; +} + +static REG8 IOINPCALL pcm86_ia460(UINT port) +{ + (void)port; + return g_pcm86.soundflags; +} + +static REG8 IOINPCALL pcm86_ia466(UINT port) { + + UINT64 cur; + UINT64 past; + UINT64 pastCycle; + UINT64 cnt; + UINT64 stepclock; + REG8 ret; + int smpsize[0x8] = { 0, 2, 2, 4, 0, 1, 1, 2 }; + + stepclock = g_pcm86.stepclock; + + pastCycle = (UINT64)UINT_MAX << 6; + cur = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + cur <<= 6; + past = (cur + pastCycle - g_pcm86.lastclock) % pastCycle; + if (past > pastCycle / 2) + { + // 負の値になってしまっているとき + if (past < pastCycle - stepclock * 4) + { + // かなり小さいならリセットをかける + past = 1; + g_pcm86.lastclock = cur - 1; + } + else + { + // 小さいなら様子見で0扱いとする + past = 0; + } + } + if (past >= g_pcm86.stepclock) + { + cnt = past / stepclock; + g_pcm86.lastclock = (g_pcm86.lastclock + cnt * stepclock) % pastCycle; + past -= cnt * stepclock; + if (g_pcm86.fifo & 0x80) + { + RECALC_NOWCLKWAIT(cnt); + } + } + ret = ((past << 1) >= stepclock) ? 1 : 0; + if (g_pcm86.virbuf >= PCM86_LOGICALBUF) { // バッファフル + ret |= 0x80; + } + else if (g_pcm86.virbuf <= g_pcm86.stepmask) { // バッファ0 stepmask以下のときも実質空 + ret |= 0x40; // ちと変… + } + (void)port; +// TRACEOUT(("86pcm in %.4x %.2x", port, ret)); + return(ret); +} + +static REG8 IOINPCALL pcm86_ia468(UINT port) { + + REG8 ret; + + ret = g_pcm86.fifo & (~0x10); +#if 1 + if (pcm86gen_intrq(0)) { + ret |= 0x10; + } +#elif 1 // むしろこう? + if (g_pcm86.fifo & 0x20) { + sound_sync(); + if (g_pcm86.virbuf <= g_pcm86.fifosize) { + if (g_pcm86.write) { + g_pcm86.write = 0; + } + else { + ret |= 0x10; + } + } + } +#else + if ((g_pcm86.write) && (g_pcm86.fifo & 0x20)) { +// g_pcm86.write = 0; + sound_sync(); + if (g_pcm86.virbuf <= g_pcm86.fifosize) { + g_pcm86.write = 0; + ret |= 0x10; + } + } +#endif + (void)port; +// TRACEOUT(("86pcm in %.4x %.2x", port, ret)); + return(ret); +} + +static REG8 IOINPCALL pcm86_ia46a(UINT port) { + + (void)port; +// TRACEOUT(("86pcm in %.4x %.2x", port, g_pcm86.dactrl)); + return(g_pcm86.dactrl); +} + +static REG8 IOINPCALL pcm86_inpdummy(UINT port) { + + (void)port; + return(0); +} + +// for Q-Vision Wave Star +static void IOOUTCALL pcm86_oa462(UINT port, REG8 val) +{ + if(wavestar_a462_seq_index < sizeof(wavestar_a462_seq) && val == wavestar_a462_seq[wavestar_a462_seq_index]){ + wavestar_a462_seq_index++; + if(wavestar_a462_seq_index == sizeof(wavestar_a462_seq)){ + wavestar_a464_value = 0x0b; + } + }else if(val == wavestar_a462_seq[0]){ + wavestar_a462_seq_index = 1; + }else{ + wavestar_a462_seq_index = 0; + } + (void)port; +} +static REG8 IOINPCALL pcm86_ia462(UINT port) { + + (void)port; + + return(0xff); +} +static void IOOUTCALL pcm86_oa464(UINT port, REG8 val) +{ + if(wavestar_a462_seq_index == sizeof(wavestar_a462_seq)){ + if(val == 0x04){ + cs4231.devvolume[0xfe] = 1; // XXX: 暫定でフラグ用に借りる(本来は変数を追加すべき) + wavestar_a464_value = 0x0c; + }else{ + cs4231.devvolume[0xfe] = 0; // XXX: 暫定でフラグ用に借りる(本来は変数を追加すべき) + wavestar_a464_value = 0x08; + } + pcm86_updateWaveStarPorts(); + } + if(val == 0x09) wavestar_a464_value = 0xff; + (void)port; +} +static REG8 IOINPCALL pcm86_ia464(UINT port) { + + REG8 ret; + (void)port; + if(wavestar_a462_seq_index != sizeof(wavestar_a462_seq)){ + wavestar_a464_value = 0xff; + } + ret = wavestar_a464_value; + if(wavestar_a464_value==0x00){ + wavestar_a464_value = 0xff; + }else{ + wavestar_a464_value = 0x00; + } + return(ret); +} +static void pcm86_updateWaveStarPorts(){ + if(cs4231.devvolume[0xfe]){ + // I/OポートをWSSに変更 + iocore_detachout(0xa460); + //iocore_attachout(0xa464, cs4231io0_w8_wavestar); + iocore_attachout(0xa466, cs4231io0_w8_wavestar); + iocore_attachout(0xa468, cs4231io0_w8_wavestar); + iocore_attachout(0xa46a, cs4231io0_w8_wavestar); + iocore_attachout(0xa46c, cs4231io0_w8_wavestar); + iocore_detachinp(0xa460); + iocore_attachinp(0xa464, cs4231io0_r8_wavestar); + iocore_attachinp(0xa466, cs4231io0_r8_wavestar); + iocore_attachinp(0xa468, cs4231io0_r8_wavestar); + iocore_attachinp(0xa46a, cs4231io0_r8_wavestar); + iocore_attachinp(0xa46c, cs4231io0_r8_wavestar); + + // OPNA割り込み無効 + g_pcm86.irq = 0xff; + g_opna[0].s.irq = 0xff; + }else{ + // I/Oポートを86互換に変更 + iocore_attachout(0xa460, pcm86_oa460); + iocore_attachout(0xa462, pcm86_oa462); + iocore_attachout(0xa464, pcm86_oa464); + iocore_attachout(0xa466, pcm86_oa466); + iocore_attachout(0xa468, pcm86_oa468); + iocore_attachout(0xa46a, pcm86_oa46a); + iocore_attachout(0xa46c, pcm86_oa46c); + iocore_attachinp(0xa460, pcm86_ia460); + iocore_attachinp(0xa462, pcm86_ia462); + iocore_attachinp(0xa464, pcm86_ia464); + iocore_attachinp(0xa466, pcm86_ia466); + iocore_attachinp(0xa468, pcm86_ia468); + iocore_attachinp(0xa46a, pcm86_ia46a); + iocore_attachinp(0xa46c, pcm86_inpdummy); + iocore_attachinp(0xa46e, pcm86_inpdummy); + + // OPNA割り込み有効 + g_pcm86.irq = cs4231.devvolume[0xfd]; + g_opna[0].s.irq = cs4231.devvolume[0xfc]; + } +} + + +// ---- + +/** + * Reset + * @param[in] cDipSw Dip switch + */ +void pcm86io_setopt(REG8 cDipSw) +{ + g_pcm86.soundflags = ((~cDipSw) >> 1) & 0x70; + g_pcm86.irq = s_irqtable[(cDipSw >> 2) & 7]; + + if(g_nSoundID==SOUNDID_WAVESTAR){ + g_pcm86.soundflags = 0x41; + fmboard_extenable(1); + cs4231.devvolume[0xfd] = g_pcm86.irq; + cs4231.devvolume[0xfc] = g_opna[0].s.irq; + } +} + +void pcm86io_bind(void) { + + sound_streamregist(&g_pcm86, (SOUNDCB)pcm86gen_getpcm); + + iocore_attachout(0xa460, pcm86_oa460); + if(g_nSoundID == SOUNDID_WAVESTAR){ + iocore_attachout(0xa462, pcm86_oa462); + iocore_attachout(0xa464, pcm86_oa464); + wavestar_a462_seq_index = 0; + wavestar_a464_value = 0xff; + } + iocore_attachout(0xa466, pcm86_oa466); + iocore_attachout(0xa468, pcm86_oa468); + iocore_attachout(0xa46a, pcm86_oa46a); + iocore_attachout(0xa46c, pcm86_oa46c); + + iocore_attachinp(0xa460, pcm86_ia460); + if(g_nSoundID == SOUNDID_WAVESTAR){ + iocore_attachinp(0xa462, pcm86_ia462); + iocore_attachinp(0xa464, pcm86_ia464); + }else{ + iocore_attachinp(0xa462, pcm86_inpdummy); + iocore_attachinp(0xa464, pcm86_inpdummy); + } + iocore_attachinp(0xa466, pcm86_ia466); + iocore_attachinp(0xa468, pcm86_ia468); + iocore_attachinp(0xa46a, pcm86_ia46a); + iocore_attachinp(0xa46c, pcm86_inpdummy); + iocore_attachinp(0xa46e, pcm86_inpdummy); + + if(g_nSoundID == SOUNDID_WAVESTAR){ + pcm86_updateWaveStarPorts(); + } +} +void pcm86io_unbind(void) { + + iocore_detachout(0xa460); + if(g_nSoundID == SOUNDID_WAVESTAR){ + iocore_detachout(0xa462); + iocore_detachout(0xa464); + } + iocore_detachout(0xa466); + iocore_detachout(0xa468); + iocore_detachout(0xa46a); + iocore_detachout(0xa46c); + + iocore_detachinp(0xa460); + iocore_detachinp(0xa462); + iocore_detachinp(0xa464); + iocore_detachinp(0xa466); + iocore_detachinp(0xa468); + iocore_detachinp(0xa46a); + iocore_detachinp(0xa46c); + iocore_detachinp(0xa46e); +} + diff --git a/cbus/pcm86io.h b/cbus/pcm86io.h old mode 100755 new mode 100644 index b192ce96..672c5c7f --- a/cbus/pcm86io.h +++ b/cbus/pcm86io.h @@ -1,14 +1,14 @@ - - -#ifdef __cplusplus -extern "C" { -#endif - -void pcm86io_setopt(REG8 cDipSw); -void pcm86io_bind(void); -void pcm86io_unbind(void); - -#ifdef __cplusplus -} -#endif - + + +#ifdef __cplusplus +extern "C" { +#endif + +void pcm86io_setopt(REG8 cDipSw); +void pcm86io_bind(void); +void pcm86io_unbind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/cbus/sasiio.c b/cbus/sasiio.c old mode 100755 new mode 100644 index 64107a18..0e352861 --- a/cbus/sasiio.c +++ b/cbus/sasiio.c @@ -1,483 +1,483 @@ -#include - -#if defined(SUPPORT_SASI) - -#include -#include -#include -#include -#include -#include -#include "sasibios.res" - - -enum { - SASI_IRQ = 0x09, - SASI_DMACH = 0x00, - - SASIPHASE_FREE = 0, - SASIPHASE_CMD = 1, - SASIPHASE_C2 = 2, - SASIPHASE_SENSE = 3, - SASIPHASE_READ = 4, - SASIPHASE_WRITE = 5, - SASIPHASE_STAT = 6, - SASIPHASE_MSG = 7, - - SASIOCR_INTE = 0x01, - SASIOCR_DMAE = 0x02, - SASIOCR_RST = 0x08, - SASIOCR_SEL = 0x20, - SASIOCR_NRDSW = 0x40, - SASIOCR_CHEN = 0x80, - - SASIISR_INT = 0x01, - SASIISR_IXO = 0x04, - SASIISR_CXD = 0x08, - SASIISR_MSG = 0x10, - SASIISR_BSY = 0x20, - SASIISR_ACK = 0x40, - SASIISR_REQ = 0x80 -}; - -extern int sxsi_unittbl[]; - - _SASIIO sasiio; - - -static BRESULT sasiseek(void) { - - SXSIDEV sxsi; - - sasiio.datpos = 0; - sasiio.datsize = 0; - sxsi = sxsi_getptr(sasiio.unit); - if ((sxsi == NULL) || (sxsi->size != 256) || - (sxsi_read(sasiio.unit, sasiio.sector, sasiio.dat, sxsi->size))) { - return(FAILURE); - } - TRACEOUT(("sasi read - drv:%d sec:%x", sasiio.unit, sasiio.sector)); - sasiio.datsize = sxsi->size; - return(SUCCESS); -} - -static BRESULT sasiflash(void) { - - SXSIDEV sxsi; - - sasiio.datpos = 0; - sasiio.datsize = 0; - sxsi = sxsi_getptr(sasiio.unit); - if ((sxsi == NULL) || (sxsi->size != 256) || - (sxsi_write(sasiio.unit, sasiio.sector, sasiio.dat, sxsi->size))) { - return(FAILURE); - } - TRACEOUT(("sasi write - drv:%d sec:%x", sasiio.unit, sasiio.sector)); - return(SUCCESS); -} - -static void sasidmac(void) { - - REG8 en; - - if ((sasiio.ocr & SASIOCR_DMAE) && - ((sasiio.phase == SASIPHASE_READ) - || (sasiio.phase == SASIPHASE_WRITE))) { - en = TRUE; - } - else { - en = FALSE; - } - dmac.dmach[SASI_DMACH].ready = en; - dmac_check(); -} - -void sasiioint(NEVENTITEM item) { - - sasiio.phase = SASIPHASE_STAT; - sasiio.isrint = SASIISR_INT; - if (sasiio.ocr & SASIOCR_INTE) { - TRACEOUT(("sasi set irq")); - pic_setirq(SASI_IRQ); - } - sasidmac(); - (void)item; -} - -static void sasisetstat(REG8 errorcode) { - - sasiio.error = errorcode; - nevent_set(NEVENT_SASIIO, 4000, sasiioint, NEVENT_ABSOLUTE); -} - -static void checkcmd(void) { - - UINT8 unit; - - unit = sxsi_unittbl[(sasiio.cmd[1] >> 5) & 1]; - sasiio.unit = unit; - switch(sasiio.cmd[0]) { - case 0x00: // Test Drive Ready - TRACEOUT(("Test Drive Ready")); - if (sxsi_getptr(unit)) { - sasiio.stat = 0x00; - sasisetstat(0x00); - } - else { - sasiio.stat = 0x02; - sasisetstat(0x7f); - } - break; - - case 0x01: // Recalibrate - TRACEOUT(("Recalibrate")); - if (sxsi_getptr(unit)) { - sasiio.sector = 0; - sasiio.stat = 0x00; - sasisetstat(0x00); - } - else { - sasiio.stat = 0x02; - sasisetstat(0x7f); - } - break; - - case 0x03: // Request Sense Status - TRACEOUT(("Request Sense Status")); - sasiio.phase = SASIPHASE_SENSE; - sasiio.senspos = 0; - sasiio.sens[0] = sasiio.error; - sasiio.sens[1] = (UINT8)((sasiio.unit << 5) + - ((sasiio.sector >> 16) & 0x1f)); - sasiio.sens[2] = (UINT8)(sasiio.sector >> 8); - sasiio.sens[3] = (UINT8)sasiio.sector; - sasiio.error = 0x00; - sasiio.stat = 0x00; - break; - - case 0x04: // Format Drive - TRACEOUT(("Format Drive")); - sasiio.sector = 0; - sasiio.stat = 0; - sasisetstat(0x0f); - break; - - case 0x06: // Format Track - TRACEOUT(("Format Track")); - sasiio.sector = (sasiio.cmd[1] & 0x1f) << 16; - sasiio.sector += (sasiio.cmd[2] << 8); - sasiio.sector += sasiio.cmd[3]; - sasiio.blocks = sasiio.cmd[4]; - sasiio.stat = 0; - if (!sxsi_format(unit, sasiio.sector)) { - sasisetstat(0x00); - } - else { - sasisetstat(0x0f); - } - break; - - case 0x08: // Read Data - TRACEOUT(("Read Data")); - sasiio.sector = (sasiio.cmd[1] & 0x1f) << 16; - sasiio.sector += (sasiio.cmd[2] << 8); - sasiio.sector += sasiio.cmd[3]; - sasiio.blocks = sasiio.cmd[4]; - sasiio.stat = 0; - if ((sasiio.blocks != 0) && (sasiseek() == SUCCESS)) { - sasiio.phase = SASIPHASE_READ; - sasidmac(); - } - else { - sasisetstat(0x0f); - } - break; - - case 0x0a: // Write Data - TRACEOUT(("Write Data")); - sasiio.sector = (sasiio.cmd[1] & 0x1f) << 16; - sasiio.sector += (sasiio.cmd[2] << 8); - sasiio.sector += sasiio.cmd[3]; - sasiio.blocks = sasiio.cmd[4]; - sasiio.stat = 0; - if ((sasiio.blocks != 0) && (sasiseek() == SUCCESS)) { - sasiio.phase = SASIPHASE_WRITE; - sasidmac(); - } - else { - sasisetstat(0x0f); - } - break; - - case 0x0b: - sasiio.sector = (sasiio.cmd[1] & 0x1f) << 16; - sasiio.sector += (sasiio.cmd[2] << 8); - sasiio.sector += sasiio.cmd[3]; - sasiio.blocks = sasiio.cmd[4]; - sasiio.stat = 0x00; - sasisetstat(0x00); - break; - - case 0xc2: - sasiio.phase = SASIPHASE_C2; - sasiio.c2pos = 0; - sasiio.stat = 0x00; - break; - - default: - TRACEOUT(("!!! unknown command %.2x", sasiio.cmd[0])); - sasisetstat(0x00); - break; - } -} - -REG8 DMACCALL sasi_dmafunc(REG8 func) { - - switch(func) { - case DMAEXT_START: - TRACEOUT(("sasi dma transfer!! %.5x:%.4x", - dmac.dmach[0].adrs.d, - dmac.dmach[0].leng.w)); - return(1); - - case DMAEXT_BREAK: - break; - } - return(0); -} - -REG8 DMACCALL sasi_dataread(void) { - - REG8 ret; - - if (sasiio.phase == SASIPHASE_READ) { - ret = sasiio.dat[sasiio.datpos]; - sasiio.datpos++; - if (sasiio.datpos >= sasiio.datsize) { - sasiio.blocks--; - if (sasiio.blocks == 0) { - sasisetstat(0x00); - } - else { - sasiio.sector++; - if (sasiseek() != SUCCESS) { - sasisetstat(0x0f); - } - } - } - } - else { - ret = 0; - } - return(ret); -} - -void DMACCALL sasi_datawrite(REG8 data) { - - if (sasiio.phase == SASIPHASE_WRITE) { - sasiio.dat[sasiio.datpos] = data; - sasiio.datpos++; - if (sasiio.datpos >= sasiio.datsize) { - if (sasiflash() != SUCCESS) { - sasisetstat(0x0f); - } - else { - sasiio.blocks--; - if (sasiio.blocks == 0) { - sasisetstat(0x00); - } - else { - sasiio.sector++; - if (sasiseek() != SUCCESS) { - sasisetstat(0x0f); - } - } - } - } - } -} - - -// ---- - -static void IOOUTCALL sasiio_o80(UINT port, REG8 dat) { - - switch(sasiio.phase) { - case SASIPHASE_FREE: - if (dat == 1) { -// TRACEOUT(("select controller - 1")); - sasiio.phase = SASIPHASE_CMD; - sasiio.cmdpos = 0; - } - break; - - case SASIPHASE_CMD: -// TRACEOUT(("sasi cmd = %.2x", dat)); - sasiio.cmd[sasiio.cmdpos] = (UINT8)dat; - sasiio.cmdpos++; - if (sasiio.cmdpos >= 6) { - checkcmd(); - } - break; - - case SASIPHASE_C2: - sasiio.c2pos++; - if (sasiio.c2pos >= 10) { - sasisetstat(0x00); - } - break; - - case SASIPHASE_WRITE: - sasi_datawrite(dat); - break; - } - (void)port; -} - -static void IOOUTCALL sasiio_o82(UINT port, REG8 dat) { - - UINT8 oldocr; - - oldocr = sasiio.ocr; - sasiio.ocr = (UINT8)dat; - - if ((oldocr & SASIOCR_RST) && (!(dat & SASIOCR_RST))) { - sasiio.phase = SASIPHASE_FREE; - TRACEOUT(("SASI reset")); - } - sasidmac(); - (void)port; -} - -static REG8 IOINPCALL sasiio_i80(UINT port) { - - REG8 ret; - - ret = 0; - switch(sasiio.phase) { - case SASIPHASE_READ: - ret = sasi_dataread(); - break; - - case SASIPHASE_STAT: - if (!sasiio.error) { - ret = sasiio.stat; - } - else { - ret = 0x02; - } - sasiio.phase = SASIPHASE_MSG; - TRACEOUT(("sasi status: %.2x", ret)); - break; - - case SASIPHASE_MSG: - sasiio.phase = SASIPHASE_FREE; - TRACEOUT(("sasi message")); - break; - - case SASIPHASE_SENSE: - ret = sasiio.sens[sasiio.senspos]; - sasiio.senspos++; - if (sasiio.senspos >= 4) { - sasisetstat(0x00); - } - break; - } - (void)port; - return(ret); -} - -static REG8 IOINPCALL sasiio_i82(UINT port) { - - REG8 ret; - SXSIDEV sxsi; - - if (sasiio.ocr & SASIOCR_NRDSW) { - ret = sasiio.isrint; - sasiio.isrint = 0; - if (sasiio.phase != SASIPHASE_FREE) { - ret += SASIISR_BSY; - ret += SASIISR_REQ; - switch(sasiio.phase) { - case SASIPHASE_CMD: - ret += SASIISR_CXD; - break; - - case SASIPHASE_SENSE: - case SASIPHASE_READ: - ret += SASIISR_IXO; - break; - - case SASIPHASE_STAT: - ret += SASIISR_CXD + SASIISR_IXO; - break; - - case SASIPHASE_MSG: - ret += SASIISR_MSG + SASIISR_CXD + SASIISR_IXO; - break; - } - } - } - else { - ret = 0; - sxsi = sxsi_getptr(sxsi_unittbl[0x00]); // SASI-1 - if (sxsi) { - ret |= (sxsi->mediatype & 7) << 3; - } - else { - ret |= (7 << 3); - } - sxsi = sxsi_getptr(sxsi_unittbl[0x01]); // SASI-2 - if (sxsi) { - ret |= (sxsi->mediatype & 7); - } - else { - ret |= 7; - } - } - (void)port; - return(ret); -} - - -// ---- - -void sasiio_reset(const NP2CFG *pConfig) { - - FILEH fh; - UINT r; - - ZeroMemory(&sasiio, sizeof(sasiio)); - if (pccore.hddif & PCHDD_SASI) { - dmac_attach(DMADEV_SASI, SASI_DMACH); - - CPU_RAM_D000 &= ~(1 << 0); - fh = file_open_rb_c(OEMTEXT("sasi.rom")); - r = 0; - if (fh != FILEH_INVALID) { - r = file_read(fh, mem + 0xd0000, 0x1000); - file_close(fh); - } - if (r == 0x1000) { - TRACEOUT(("load sasi.rom")); - } - else { - CopyMemory(mem + 0xd0000, sasibios, sizeof(sasibios)); - TRACEOUT(("use simulate sasi.rom")); - } - } - - (void)pConfig; -} - -void sasiio_bind(void) { - - if (pccore.hddif & PCHDD_SASI) { - iocore_attachout(0x0080, sasiio_o80); - iocore_attachout(0x0082, sasiio_o82); - iocore_attachinp(0x0080, sasiio_i80); - iocore_attachinp(0x0082, sasiio_i82); - } -} -#endif - +#include + +#if defined(SUPPORT_SASI) + +#include +#include +#include +#include +#include +#include +#include "sasibios.res" + + +enum { + SASI_IRQ = 0x09, + SASI_DMACH = 0x00, + + SASIPHASE_FREE = 0, + SASIPHASE_CMD = 1, + SASIPHASE_C2 = 2, + SASIPHASE_SENSE = 3, + SASIPHASE_READ = 4, + SASIPHASE_WRITE = 5, + SASIPHASE_STAT = 6, + SASIPHASE_MSG = 7, + + SASIOCR_INTE = 0x01, + SASIOCR_DMAE = 0x02, + SASIOCR_RST = 0x08, + SASIOCR_SEL = 0x20, + SASIOCR_NRDSW = 0x40, + SASIOCR_CHEN = 0x80, + + SASIISR_INT = 0x01, + SASIISR_IXO = 0x04, + SASIISR_CXD = 0x08, + SASIISR_MSG = 0x10, + SASIISR_BSY = 0x20, + SASIISR_ACK = 0x40, + SASIISR_REQ = 0x80 +}; + +extern int sxsi_unittbl[]; + + _SASIIO sasiio; + + +static BRESULT sasiseek(void) { + + SXSIDEV sxsi; + + sasiio.datpos = 0; + sasiio.datsize = 0; + sxsi = sxsi_getptr(sasiio.unit); + if ((sxsi == NULL) || (sxsi->size != 256) || + (sxsi_read(sasiio.unit, sasiio.sector, sasiio.dat, sxsi->size))) { + return(FAILURE); + } + TRACEOUT(("sasi read - drv:%d sec:%x", sasiio.unit, sasiio.sector)); + sasiio.datsize = sxsi->size; + return(SUCCESS); +} + +static BRESULT sasiflash(void) { + + SXSIDEV sxsi; + + sasiio.datpos = 0; + sasiio.datsize = 0; + sxsi = sxsi_getptr(sasiio.unit); + if ((sxsi == NULL) || (sxsi->size != 256) || + (sxsi_write(sasiio.unit, sasiio.sector, sasiio.dat, sxsi->size))) { + return(FAILURE); + } + TRACEOUT(("sasi write - drv:%d sec:%x", sasiio.unit, sasiio.sector)); + return(SUCCESS); +} + +static void sasidmac(void) { + + REG8 en; + + if ((sasiio.ocr & SASIOCR_DMAE) && + ((sasiio.phase == SASIPHASE_READ) + || (sasiio.phase == SASIPHASE_WRITE))) { + en = TRUE; + } + else { + en = FALSE; + } + dmac.dmach[SASI_DMACH].ready = en; + dmac_check(); +} + +void sasiioint(NEVENTITEM item) { + + sasiio.phase = SASIPHASE_STAT; + sasiio.isrint = SASIISR_INT; + if (sasiio.ocr & SASIOCR_INTE) { + TRACEOUT(("sasi set irq")); + pic_setirq(SASI_IRQ); + } + sasidmac(); + (void)item; +} + +static void sasisetstat(REG8 errorcode) { + + sasiio.error = errorcode; + nevent_set(NEVENT_SASIIO, 4000, sasiioint, NEVENT_ABSOLUTE); +} + +static void checkcmd(void) { + + UINT8 unit; + + unit = sxsi_unittbl[(sasiio.cmd[1] >> 5) & 1]; + sasiio.unit = unit; + switch(sasiio.cmd[0]) { + case 0x00: // Test Drive Ready + TRACEOUT(("Test Drive Ready")); + if (sxsi_getptr(unit)) { + sasiio.stat = 0x00; + sasisetstat(0x00); + } + else { + sasiio.stat = 0x02; + sasisetstat(0x7f); + } + break; + + case 0x01: // Recalibrate + TRACEOUT(("Recalibrate")); + if (sxsi_getptr(unit)) { + sasiio.sector = 0; + sasiio.stat = 0x00; + sasisetstat(0x00); + } + else { + sasiio.stat = 0x02; + sasisetstat(0x7f); + } + break; + + case 0x03: // Request Sense Status + TRACEOUT(("Request Sense Status")); + sasiio.phase = SASIPHASE_SENSE; + sasiio.senspos = 0; + sasiio.sens[0] = sasiio.error; + sasiio.sens[1] = (UINT8)((sasiio.unit << 5) + + ((sasiio.sector >> 16) & 0x1f)); + sasiio.sens[2] = (UINT8)(sasiio.sector >> 8); + sasiio.sens[3] = (UINT8)sasiio.sector; + sasiio.error = 0x00; + sasiio.stat = 0x00; + break; + + case 0x04: // Format Drive + TRACEOUT(("Format Drive")); + sasiio.sector = 0; + sasiio.stat = 0; + sasisetstat(0x0f); + break; + + case 0x06: // Format Track + TRACEOUT(("Format Track")); + sasiio.sector = (sasiio.cmd[1] & 0x1f) << 16; + sasiio.sector += (sasiio.cmd[2] << 8); + sasiio.sector += sasiio.cmd[3]; + sasiio.blocks = sasiio.cmd[4]; + sasiio.stat = 0; + if (!sxsi_format(unit, sasiio.sector)) { + sasisetstat(0x00); + } + else { + sasisetstat(0x0f); + } + break; + + case 0x08: // Read Data + TRACEOUT(("Read Data")); + sasiio.sector = (sasiio.cmd[1] & 0x1f) << 16; + sasiio.sector += (sasiio.cmd[2] << 8); + sasiio.sector += sasiio.cmd[3]; + sasiio.blocks = sasiio.cmd[4]; + sasiio.stat = 0; + if ((sasiio.blocks != 0) && (sasiseek() == SUCCESS)) { + sasiio.phase = SASIPHASE_READ; + sasidmac(); + } + else { + sasisetstat(0x0f); + } + break; + + case 0x0a: // Write Data + TRACEOUT(("Write Data")); + sasiio.sector = (sasiio.cmd[1] & 0x1f) << 16; + sasiio.sector += (sasiio.cmd[2] << 8); + sasiio.sector += sasiio.cmd[3]; + sasiio.blocks = sasiio.cmd[4]; + sasiio.stat = 0; + if ((sasiio.blocks != 0) && (sasiseek() == SUCCESS)) { + sasiio.phase = SASIPHASE_WRITE; + sasidmac(); + } + else { + sasisetstat(0x0f); + } + break; + + case 0x0b: + sasiio.sector = (sasiio.cmd[1] & 0x1f) << 16; + sasiio.sector += (sasiio.cmd[2] << 8); + sasiio.sector += sasiio.cmd[3]; + sasiio.blocks = sasiio.cmd[4]; + sasiio.stat = 0x00; + sasisetstat(0x00); + break; + + case 0xc2: + sasiio.phase = SASIPHASE_C2; + sasiio.c2pos = 0; + sasiio.stat = 0x00; + break; + + default: + TRACEOUT(("!!! unknown command %.2x", sasiio.cmd[0])); + sasisetstat(0x00); + break; + } +} + +REG8 DMACCALL sasi_dmafunc(REG8 func) { + + switch(func) { + case DMAEXT_START: + TRACEOUT(("sasi dma transfer!! %.5x:%.4x", + dmac.dmach[0].adrs.d, + dmac.dmach[0].leng.w)); + return(1); + + case DMAEXT_BREAK: + break; + } + return(0); +} + +REG8 DMACCALL sasi_dataread(void) { + + REG8 ret; + + if (sasiio.phase == SASIPHASE_READ) { + ret = sasiio.dat[sasiio.datpos]; + sasiio.datpos++; + if (sasiio.datpos >= sasiio.datsize) { + sasiio.blocks--; + if (sasiio.blocks == 0) { + sasisetstat(0x00); + } + else { + sasiio.sector++; + if (sasiseek() != SUCCESS) { + sasisetstat(0x0f); + } + } + } + } + else { + ret = 0; + } + return(ret); +} + +void DMACCALL sasi_datawrite(REG8 data) { + + if (sasiio.phase == SASIPHASE_WRITE) { + sasiio.dat[sasiio.datpos] = data; + sasiio.datpos++; + if (sasiio.datpos >= sasiio.datsize) { + if (sasiflash() != SUCCESS) { + sasisetstat(0x0f); + } + else { + sasiio.blocks--; + if (sasiio.blocks == 0) { + sasisetstat(0x00); + } + else { + sasiio.sector++; + if (sasiseek() != SUCCESS) { + sasisetstat(0x0f); + } + } + } + } + } +} + + +// ---- + +static void IOOUTCALL sasiio_o80(UINT port, REG8 dat) { + + switch(sasiio.phase) { + case SASIPHASE_FREE: + if (dat == 1) { +// TRACEOUT(("select controller - 1")); + sasiio.phase = SASIPHASE_CMD; + sasiio.cmdpos = 0; + } + break; + + case SASIPHASE_CMD: +// TRACEOUT(("sasi cmd = %.2x", dat)); + sasiio.cmd[sasiio.cmdpos] = (UINT8)dat; + sasiio.cmdpos++; + if (sasiio.cmdpos >= 6) { + checkcmd(); + } + break; + + case SASIPHASE_C2: + sasiio.c2pos++; + if (sasiio.c2pos >= 10) { + sasisetstat(0x00); + } + break; + + case SASIPHASE_WRITE: + sasi_datawrite(dat); + break; + } + (void)port; +} + +static void IOOUTCALL sasiio_o82(UINT port, REG8 dat) { + + UINT8 oldocr; + + oldocr = sasiio.ocr; + sasiio.ocr = (UINT8)dat; + + if ((oldocr & SASIOCR_RST) && (!(dat & SASIOCR_RST))) { + sasiio.phase = SASIPHASE_FREE; + TRACEOUT(("SASI reset")); + } + sasidmac(); + (void)port; +} + +static REG8 IOINPCALL sasiio_i80(UINT port) { + + REG8 ret; + + ret = 0; + switch(sasiio.phase) { + case SASIPHASE_READ: + ret = sasi_dataread(); + break; + + case SASIPHASE_STAT: + if (!sasiio.error) { + ret = sasiio.stat; + } + else { + ret = 0x02; + } + sasiio.phase = SASIPHASE_MSG; + TRACEOUT(("sasi status: %.2x", ret)); + break; + + case SASIPHASE_MSG: + sasiio.phase = SASIPHASE_FREE; + TRACEOUT(("sasi message")); + break; + + case SASIPHASE_SENSE: + ret = sasiio.sens[sasiio.senspos]; + sasiio.senspos++; + if (sasiio.senspos >= 4) { + sasisetstat(0x00); + } + break; + } + (void)port; + return(ret); +} + +static REG8 IOINPCALL sasiio_i82(UINT port) { + + REG8 ret; + SXSIDEV sxsi; + + if (sasiio.ocr & SASIOCR_NRDSW) { + ret = sasiio.isrint; + sasiio.isrint = 0; + if (sasiio.phase != SASIPHASE_FREE) { + ret += SASIISR_BSY; + ret += SASIISR_REQ; + switch(sasiio.phase) { + case SASIPHASE_CMD: + ret += SASIISR_CXD; + break; + + case SASIPHASE_SENSE: + case SASIPHASE_READ: + ret += SASIISR_IXO; + break; + + case SASIPHASE_STAT: + ret += SASIISR_CXD + SASIISR_IXO; + break; + + case SASIPHASE_MSG: + ret += SASIISR_MSG + SASIISR_CXD + SASIISR_IXO; + break; + } + } + } + else { + ret = 0; + sxsi = sxsi_getptr(sxsi_unittbl[0x00]); // SASI-1 + if (sxsi) { + ret |= (sxsi->mediatype & 7) << 3; + } + else { + ret |= (7 << 3); + } + sxsi = sxsi_getptr(sxsi_unittbl[0x01]); // SASI-2 + if (sxsi) { + ret |= (sxsi->mediatype & 7); + } + else { + ret |= 7; + } + } + (void)port; + return(ret); +} + + +// ---- + +void sasiio_reset(const NP2CFG *pConfig) { + + FILEH fh; + UINT r; + + ZeroMemory(&sasiio, sizeof(sasiio)); + if (pccore.hddif & PCHDD_SASI) { + dmac_attach(DMADEV_SASI, SASI_DMACH); + + CPU_RAM_D000 &= ~(1 << 0); + fh = file_open_rb_c(OEMTEXT("sasi.rom")); + r = 0; + if (fh != FILEH_INVALID) { + r = file_read(fh, mem + 0xd0000, 0x1000); + file_close(fh); + } + if (r == 0x1000) { + TRACEOUT(("load sasi.rom")); + } + else { + CopyMemory(mem + 0xd0000, sasibios, sizeof(sasibios)); + TRACEOUT(("use simulate sasi.rom")); + } + } + + (void)pConfig; +} + +void sasiio_bind(void) { + + if (pccore.hddif & PCHDD_SASI) { + iocore_attachout(0x0080, sasiio_o80); + iocore_attachout(0x0082, sasiio_o82); + iocore_attachinp(0x0080, sasiio_i80); + iocore_attachinp(0x0082, sasiio_i82); + } +} +#endif + diff --git a/cbus/sasiio.h b/cbus/sasiio.h old mode 100755 new mode 100644 index 48e1a1ea..ea6f6574 --- a/cbus/sasiio.h +++ b/cbus/sasiio.h @@ -1,43 +1,43 @@ - -#if defined(SUPPORT_SASI) - -typedef struct { - UINT8 phase; - UINT8 ocr; - UINT8 stat; - UINT8 error; - UINT8 unit; - UINT8 isrint; - UINT8 cmd[6]; - UINT cmdpos; - UINT8 sens[4]; - UINT senspos; - UINT c2pos; - UINT32 sector; - UINT blocks; - UINT datpos; - UINT datsize; - UINT8 dat[256]; -} _SASIIO, *SASIIO; - -#ifdef __cplusplus -extern "C" { -#endif - -extern _SASIIO sasiio; - -void sasiioint(NEVENTITEM item); - -REG8 DMACCALL sasi_dmafunc(REG8 func); -REG8 DMACCALL sasi_dataread(void); -void DMACCALL sasi_datawrite(REG8 data); - -void sasiio_reset(const NP2CFG *pConfig); -void sasiio_bind(void); - -#ifdef __cplusplus -} -#endif - -#endif - + +#if defined(SUPPORT_SASI) + +typedef struct { + UINT8 phase; + UINT8 ocr; + UINT8 stat; + UINT8 error; + UINT8 unit; + UINT8 isrint; + UINT8 cmd[6]; + UINT cmdpos; + UINT8 sens[4]; + UINT senspos; + UINT c2pos; + UINT32 sector; + UINT blocks; + UINT datpos; + UINT datsize; + UINT8 dat[256]; +} _SASIIO, *SASIIO; + +#ifdef __cplusplus +extern "C" { +#endif + +extern _SASIIO sasiio; + +void sasiioint(NEVENTITEM item); + +REG8 DMACCALL sasi_dmafunc(REG8 func); +REG8 DMACCALL sasi_dataread(void); +void DMACCALL sasi_datawrite(REG8 data); + +void sasiio_reset(const NP2CFG *pConfig); +void sasiio_bind(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/cbus/scsicmd.c b/cbus/scsicmd.c old mode 100755 new mode 100644 index fabc76c8..e2c5c5e3 --- a/cbus/scsicmd.c +++ b/cbus/scsicmd.c @@ -1,279 +1,279 @@ -#include - -#if defined(SUPPORT_SCSI) - -#include -#include -#include -#include -#include -#include -#include "scsiio.tbl" -#include -#include - -#if defined(_WIN32) && defined(TRACE) -extern void iptrace_out(void); -#define SCSICMD_ERR MessageBox(NULL, _T("SCSI error"), _T("?"), MB_OK); \ - exit(1); -#else -#define SCSICMD_ERR -#endif - - -static const UINT8 hdd_inquiry[0x20] = { - 0x00,0x00,0x02,0x02,0x1c,0x00,0x00,0x18, - 'N', 'E', 'C', 0x20,0x20,0x20,0x20,0x20, - 'N', 'P', '2', '-', 'H', 'D', 'D', 0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}; - - -static UINT scsicmd_datain(SXSIDEV sxsi, UINT8 *cdb) { - - UINT length; - - switch(cdb[0]) { - case 0x12: // Inquiry - TRACEOUT(("Inquiry")); - // Logical unit number = cdb[1] >> 5; - // EVPD = cdb[1] & 1; - // Page code = cdb[2]; - length = cdb[4]; - if (length) { - CopyMemory(scsiio.data, hdd_inquiry, MIN(length, 0x20)); - } - break; - - default: - length = 0; - } - (void)sxsi; - return(length); -} - - - - - - -// ---- - -REG8 scsicmd_negate(REG8 id) { - - scsiio.phase = 0; - (void)id; - return(0x85); // disconnect -} - -REG8 scsicmd_select(REG8 id) { - - SXSIDEV sxsi; - - TRACEOUT(("scsicmd_select")); - if (scsiio.reg[SCSICTR_TARGETLUN] & 7) { - TRACEOUT(("LUN = %d", scsiio.reg[SCSICTR_TARGETLUN] & 7)); - return(0x42); - } - sxsi = sxsi_getptr((REG8)(0x20 + id)); - if ((sxsi) && (sxsi->flag & SXSIFLAG_READY)) { - scsiio.phase = SCSIPH_COMMAND; - return(0x8a); // Transfer Command要求 - } - return(0x42); // Timeout -} - -REG8 scsicmd_transfer(REG8 id, UINT8 *cdb) { - - SXSIDEV sxsi; - UINT leng; - - if (scsiio.reg[SCSICTR_TARGETLUN] & 7) { - return(0x42); - } - - sxsi = sxsi_getptr((REG8)(0x20 + id)); - if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY))) { - return(0x42); - } - - TRACEOUT(("sel ope code = %.2x", cdb[0])); - switch(cdb[0]) { - case 0x00: // Test Unit Ready - return(0x16); // Succeed - - case 0x12: // Inquiry - leng = scsicmd_datain(sxsi, cdb); -#if 0 - if (leng > scsiio.transfer) { - return(0x2b); // Abort - } - else if (leng < scsiio.transfer) { - return(0x20); // Pause - } -#endif - return(0x16); // Succeed - } - - SCSICMD_ERR - return(0xff); -} - -static REG8 scsicmd_cmd(REG8 id) { - - SXSIDEV sxsi; - - TRACEOUT(("scsicmd_cmd = %.2x", scsiio.cmd[0])); - if (scsiio.reg[SCSICTR_TARGETLUN] & 7) { - return(0x42); - } - sxsi = sxsi_getptr((REG8)(0x20 + id)); - if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY))) { - return(0x42); - } - switch(scsiio.cmd[0]) { - case 0x00: - return(0x8b); // Transfer Status要求 - - case 0x12: // inquiry - scsicmd_datain(sxsi, scsiio.cmd); - scsiio.phase = SCSIPH_DATAIN; - return(0x89); // Transfer Data要求 - } - - SCSICMD_ERR - return(0xff); -} - -BRESULT scsicmd_send(void) { - - switch(scsiio.phase) { - case SCSIPH_COMMAND: - scsiio.cmdpos = 0; - return(SUCCESS); - } - return(FAILURE); -} - - -// ---- BIOS から - -static const UINT8 stat2ret[16] = { - 0x40, 0x00, 0x10, 0x00, - 0x20, 0x00, 0x10, 0x00, - 0x30, 0x00, 0x10, 0x00, - 0x20, 0x00, 0x10, 0x00}; - -static REG8 bios1bc_seltrans(REG8 id) { - - UINT8 cdb[16]; - REG8 ret; - - MEMR_READS(CPU_DS, CPU_DX, cdb, 16); - scsiio.reg[SCSICTR_TARGETLUN] = cdb[0]; - if ((cdb[1] & 0x0c) == 0x08) { // OUT - MEMR_READS(CPU_ES, CPU_BX, scsiio.data, CPU_CX); - } - ret = scsicmd_transfer(id, cdb + 4); - if ((cdb[1] & 0x0c) == 0x04) { // IN - MEMR_WRITES(CPU_ES, CPU_BX, scsiio.data, CPU_CX); - } - return(ret); -} - -void scsicmd_bios(void) { - - UINT8 flag; - UINT8 ret; - REG8 stat; - UINT cmd; - REG8 dstid; - - TRACEOUT(("BIOS 1B-C* CPU_AH %.2x", CPU_AH)); - - if (CPU_AH & 0x80) { // エラーぽ - return; - } - - flag = MEMR_READ8(CPU_SS, CPU_SP+4) & 0xbe; - ret = mem[0x0483]; - cmd = CPU_AH & 0x1f; - dstid = CPU_AL & 7; - if (ret & 0x80) { - mem[0x0483] &= 0x7f; - } - else if (cmd < 0x18) { - switch(cmd) { - case 0x00: // reset - stat = 0x00; - break; - - case 0x03: // Negate ACK - stat = scsicmd_negate(dstid); - break; - - case 0x07: // Select Without AMN - stat = scsicmd_select(dstid); - break; - - case 0x09: // Select Without AMN and Transfer - stat = bios1bc_seltrans(dstid); - break; - - default: - TRACEOUT(("cmd = %.2x", CPU_AH)); - SCSICMD_ERR - stat = 0x42; - break; - } - ret = stat2ret[stat >> 4] + (stat & 0x0f); - TRACEOUT(("BIOS 1B-C* CPU_AH %.2x ret = %.2x", CPU_AH, ret)); - mem[0x0483] = ret; - } - else { - if ((ret ^ cmd) & 0x0f) { - ret = cmd | 0x80; - } - else { - switch(cmd) { - case 0x19: // Data In - MEMR_WRITES(CPU_ES, CPU_BX, scsiio.data, CPU_CX); - scsiio.phase = SCSIPH_STATUS; - stat = 0x8b; - break; - - case 0x1a: // Transfer command - MEMR_READS(CPU_ES, CPU_BX, scsiio.cmd, 12); - stat = scsicmd_cmd(dstid); - break; - - case 0x1b: // Status In - scsiio.phase = SCSIPH_MSGIN; - stat = 0x8f; - break; - - case 0x1f: // Message In - scsiio.phase = 0; - stat = 0x80; - break; - - default: - TRACEOUT(("cmd = %.2x", CPU_AH)); - SCSICMD_ERR - stat = 0x42; - break; - } - ret = stat2ret[stat >> 4] + (stat & 0x0f); - } - TRACEOUT(("BIOS 1B-C* CPU_AH %.2x ret = %.2x", CPU_AH, ret)); - mem[0x0483] = ret; - } - flag |= ret & Z_FLAG; - if (ret & 0x80) { - flag |= C_FLAG; - ret &= 0x7f; - } - CPU_AH = ret; - MEMR_WRITE8(CPU_SS, CPU_SP + 4, flag); -} -#endif - +#include + +#if defined(SUPPORT_SCSI) + +#include +#include +#include +#include +#include +#include +#include "scsiio.tbl" +#include +#include + +#if defined(_WIN32) && defined(TRACE) +extern void iptrace_out(void); +#define SCSICMD_ERR MessageBox(NULL, _T("SCSI error"), _T("?"), MB_OK); \ + exit(1); +#else +#define SCSICMD_ERR +#endif + + +static const UINT8 hdd_inquiry[0x20] = { + 0x00,0x00,0x02,0x02,0x1c,0x00,0x00,0x18, + 'N', 'E', 'C', 0x20,0x20,0x20,0x20,0x20, + 'N', 'P', '2', '-', 'H', 'D', 'D', 0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}; + + +static UINT scsicmd_datain(SXSIDEV sxsi, UINT8 *cdb) { + + UINT length; + + switch(cdb[0]) { + case 0x12: // Inquiry + TRACEOUT(("Inquiry")); + // Logical unit number = cdb[1] >> 5; + // EVPD = cdb[1] & 1; + // Page code = cdb[2]; + length = cdb[4]; + if (length) { + CopyMemory(scsiio.data, hdd_inquiry, MIN(length, 0x20)); + } + break; + + default: + length = 0; + } + (void)sxsi; + return(length); +} + + + + + + +// ---- + +REG8 scsicmd_negate(REG8 id) { + + scsiio.phase = 0; + (void)id; + return(0x85); // disconnect +} + +REG8 scsicmd_select(REG8 id) { + + SXSIDEV sxsi; + + TRACEOUT(("scsicmd_select")); + if (scsiio.reg[SCSICTR_TARGETLUN] & 7) { + TRACEOUT(("LUN = %d", scsiio.reg[SCSICTR_TARGETLUN] & 7)); + return(0x42); + } + sxsi = sxsi_getptr((REG8)(0x20 + id)); + if ((sxsi) && (sxsi->flag & SXSIFLAG_READY)) { + scsiio.phase = SCSIPH_COMMAND; + return(0x8a); // Transfer Command要求 + } + return(0x42); // Timeout +} + +REG8 scsicmd_transfer(REG8 id, UINT8 *cdb) { + + SXSIDEV sxsi; + UINT leng; + + if (scsiio.reg[SCSICTR_TARGETLUN] & 7) { + return(0x42); + } + + sxsi = sxsi_getptr((REG8)(0x20 + id)); + if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY))) { + return(0x42); + } + + TRACEOUT(("sel ope code = %.2x", cdb[0])); + switch(cdb[0]) { + case 0x00: // Test Unit Ready + return(0x16); // Succeed + + case 0x12: // Inquiry + leng = scsicmd_datain(sxsi, cdb); +#if 0 + if (leng > scsiio.transfer) { + return(0x2b); // Abort + } + else if (leng < scsiio.transfer) { + return(0x20); // Pause + } +#endif + return(0x16); // Succeed + } + + SCSICMD_ERR + return(0xff); +} + +static REG8 scsicmd_cmd(REG8 id) { + + SXSIDEV sxsi; + + TRACEOUT(("scsicmd_cmd = %.2x", scsiio.cmd[0])); + if (scsiio.reg[SCSICTR_TARGETLUN] & 7) { + return(0x42); + } + sxsi = sxsi_getptr((REG8)(0x20 + id)); + if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY))) { + return(0x42); + } + switch(scsiio.cmd[0]) { + case 0x00: + return(0x8b); // Transfer Status要求 + + case 0x12: // inquiry + scsicmd_datain(sxsi, scsiio.cmd); + scsiio.phase = SCSIPH_DATAIN; + return(0x89); // Transfer Data要求 + } + + SCSICMD_ERR + return(0xff); +} + +BRESULT scsicmd_send(void) { + + switch(scsiio.phase) { + case SCSIPH_COMMAND: + scsiio.cmdpos = 0; + return(SUCCESS); + } + return(FAILURE); +} + + +// ---- BIOS から + +static const UINT8 stat2ret[16] = { + 0x40, 0x00, 0x10, 0x00, + 0x20, 0x00, 0x10, 0x00, + 0x30, 0x00, 0x10, 0x00, + 0x20, 0x00, 0x10, 0x00}; + +static REG8 bios1bc_seltrans(REG8 id) { + + UINT8 cdb[16]; + REG8 ret; + + MEMR_READS(CPU_DS, CPU_DX, cdb, 16); + scsiio.reg[SCSICTR_TARGETLUN] = cdb[0]; + if ((cdb[1] & 0x0c) == 0x08) { // OUT + MEMR_READS(CPU_ES, CPU_BX, scsiio.data, CPU_CX); + } + ret = scsicmd_transfer(id, cdb + 4); + if ((cdb[1] & 0x0c) == 0x04) { // IN + MEMR_WRITES(CPU_ES, CPU_BX, scsiio.data, CPU_CX); + } + return(ret); +} + +void scsicmd_bios(void) { + + UINT8 flag; + UINT8 ret; + REG8 stat; + UINT cmd; + REG8 dstid; + + TRACEOUT(("BIOS 1B-C* CPU_AH %.2x", CPU_AH)); + + if (CPU_AH & 0x80) { // エラーぽ + return; + } + + flag = MEMR_READ8(CPU_SS, CPU_SP+4) & 0xbe; + ret = mem[0x0483]; + cmd = CPU_AH & 0x1f; + dstid = CPU_AL & 7; + if (ret & 0x80) { + mem[0x0483] &= 0x7f; + } + else if (cmd < 0x18) { + switch(cmd) { + case 0x00: // reset + stat = 0x00; + break; + + case 0x03: // Negate ACK + stat = scsicmd_negate(dstid); + break; + + case 0x07: // Select Without AMN + stat = scsicmd_select(dstid); + break; + + case 0x09: // Select Without AMN and Transfer + stat = bios1bc_seltrans(dstid); + break; + + default: + TRACEOUT(("cmd = %.2x", CPU_AH)); + SCSICMD_ERR + stat = 0x42; + break; + } + ret = stat2ret[stat >> 4] + (stat & 0x0f); + TRACEOUT(("BIOS 1B-C* CPU_AH %.2x ret = %.2x", CPU_AH, ret)); + mem[0x0483] = ret; + } + else { + if ((ret ^ cmd) & 0x0f) { + ret = cmd | 0x80; + } + else { + switch(cmd) { + case 0x19: // Data In + MEMR_WRITES(CPU_ES, CPU_BX, scsiio.data, CPU_CX); + scsiio.phase = SCSIPH_STATUS; + stat = 0x8b; + break; + + case 0x1a: // Transfer command + MEMR_READS(CPU_ES, CPU_BX, scsiio.cmd, 12); + stat = scsicmd_cmd(dstid); + break; + + case 0x1b: // Status In + scsiio.phase = SCSIPH_MSGIN; + stat = 0x8f; + break; + + case 0x1f: // Message In + scsiio.phase = 0; + stat = 0x80; + break; + + default: + TRACEOUT(("cmd = %.2x", CPU_AH)); + SCSICMD_ERR + stat = 0x42; + break; + } + ret = stat2ret[stat >> 4] + (stat & 0x0f); + } + TRACEOUT(("BIOS 1B-C* CPU_AH %.2x ret = %.2x", CPU_AH, ret)); + mem[0x0483] = ret; + } + flag |= ret & Z_FLAG; + if (ret & 0x80) { + flag |= C_FLAG; + ret &= 0x7f; + } + CPU_AH = ret; + MEMR_WRITE8(CPU_SS, CPU_SP + 4, flag); +} +#endif + diff --git a/cbus/scsicmd.h b/cbus/scsicmd.h old mode 100755 new mode 100644 index 22b56da2..7a622696 --- a/cbus/scsicmd.h +++ b/cbus/scsicmd.h @@ -1,20 +1,20 @@ - -#if defined(SUPPORT_SCSI) - -#ifdef __cplusplus -extern "C" { -#endif - -REG8 scsicmd_negate(REG8 id); -REG8 scsicmd_select(REG8 id); -REG8 scsicmd_transfer(REG8 id, UINT8 *cdb); -BRESULT scsicmd_send(void); - -void scsicmd_bios(void); - -#ifdef __cplusplus -} -#endif - -#endif - + +#if defined(SUPPORT_SCSI) + +#ifdef __cplusplus +extern "C" { +#endif + +REG8 scsicmd_negate(REG8 id); +REG8 scsicmd_select(REG8 id); +REG8 scsicmd_transfer(REG8 id, UINT8 *cdb); +BRESULT scsicmd_send(void); + +void scsicmd_bios(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/cbus/scsiio.c b/cbus/scsiio.c old mode 100755 new mode 100644 index d3902dbe..5d5e4366 --- a/cbus/scsiio.c +++ b/cbus/scsiio.c @@ -1,773 +1,773 @@ -#include - -#if defined(SUPPORT_SCSI) - -#include -#include -#include -#include -#include -#include -#include "scsiio.tbl" -#include -#include "scsibios.res" -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif -#include - - - _SCSIIO scsiio; - -static const UINT8 scsiirq[] = {0x03, 0x05, 0x06, 0x09, 0x0c, 0x0d, 3, 3}; - - -void scsiioint(NEVENTITEM item) { - - TRACEOUT(("scsiioint")); - if (scsiio.membank & 4) { - pic_setirq(scsiirq[(scsiio.resent >> 3) & 7]); - TRACEOUT(("scsi intr")); - } - scsiio.auxstatus = 0x80; - (void)item; -} - -static void scsiintr(REG8 status) { - - scsiio.scsistatus = status; - nevent_set(NEVENT_SCSIIO, 4000, scsiioint, NEVENT_ABSOLUTE); -} - -static void scsicmd(REG8 cmd) { - - REG8 ret; - UINT8 id; - - id = scsiio.reg[SCSICTR_DSTID] & 7; - switch(cmd) { - case SCSICMD_RESET: - scsiintr(SCSISTAT_RESET); - break; - - case SCSICMD_NEGATE: - ret = scsicmd_negate(id); - scsiintr(ret); - break; - - case SCSICMD_SEL: - ret = scsicmd_select(id); - if (ret & 0x80) { - scsiintr(0x11); - // で retはどーやって割り込みさせるの? - } - else { - scsiintr(ret); - } - break; - - case SCSICMD_SEL_TR: - ret = scsicmd_transfer(id, scsiio.reg + SCSICTR_CDB); - if (ret != 0xff) { - scsiintr(ret); - } - break; - } -} - - - -// ---- - -static void IOOUTCALL scsiio_occ0(UINT port, REG8 dat) { - - scsiio.port = dat; - (void)port; -} - -static void IOOUTCALL scsiio_occ2(UINT port, REG8 dat) { - - UINT8 bit; - - if (scsiio.port < 0x40) { - TRACEOUT(("scsi ctrl write %s %.2x", scsictr[scsiio.port], dat)); - } - if (scsiio.port <= 0x19) { - scsiio.reg[scsiio.port] = dat; - if (scsiio.port == SCSICTR_CMD) { - scsicmd(dat); - } - scsiio.port++; - } - else { - switch(scsiio.port) { - case SCSICTR_MEMBANK: - scsiio.membank = dat; - if (!(dat & 0x40)) { - CopyMemory(mem + 0xd2000, scsiio.bios[0], 0x2000); - } - else { - CopyMemory(mem + 0xd2000, scsiio.bios[1], 0x2000); - } - break; - - case 0x3f: - bit = 1 << (dat & 7); - if (dat & 8) { - scsiio.datmap |= bit; - } - else { - if (scsiio.datmap & bit) { - scsiio.datmap &= ~bit; - if (bit == (1 << 1)) { - scsiio.wrdatpos = 0; - } - else if (bit == (1 << 5)) { - scsiio.rddatpos = 0; - } - } - } - break; - } - } - (void)port; -} - -static void IOOUTCALL scsiio_occ4(UINT port, REG8 dat) { - - TRACEOUT(("scsiio_occ4 %.2x", dat)); - (void)port; - (void)dat; -} - -static void IOOUTCALL scsiio_occ6(UINT port, REG8 dat) { - - scsiio.data[scsiio.wrdatpos & 0x7fff] = dat; - scsiio.wrdatpos++; - (void)port; -} - -static REG8 IOINPCALL scsiio_icc0(UINT port) { - - REG8 ret; - - ret = scsiio.auxstatus; - scsiio.auxstatus = 0; - (void)port; - return(ret); -} - -static REG8 IOINPCALL scsiio_icc2(UINT port) { - - REG8 ret; - - switch(scsiio.port) { - case SCSICTR_STATUS: - scsiio.port++; - return(scsiio.scsistatus); - - case SCSICTR_MEMBANK: - return(scsiio.membank); - - case SCSICTR_MEMWND: - return(scsiio.memwnd); - - case SCSICTR_RESENT: - return(scsiio.resent); - - case 0x36: - return(0); // 2枚刺しとか… - } - if (scsiio.port <= 0x19) { - ret = scsiio.reg[scsiio.port]; - TRACEOUT(("scsi ctrl read %s %.2x [%.4x:%.4x]", - scsictr[scsiio.port], ret, CPU_CS, CPU_IP)); - scsiio.port++; - return(ret); - } - (void)port; - return(0xff); -} - -static REG8 IOINPCALL scsiio_icc4(UINT port) { - - TRACEOUT(("scsiio_icc4")); - (void)port; - return(0x00); -} - -static REG8 IOINPCALL scsiio_icc6(UINT port) { - - REG8 ret; - - ret = scsiio.data[scsiio.rddatpos & 0x7fff]; - scsiio.rddatpos++; - (void)port; - return(ret); -} - -#if defined(SUPPORT_NP2SCSI) - -_NP2STOR np2stor; - -#if 0 -#undef TRACEOUT2 -static void trace_fmt_ex(const char* fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT2(s) trace_fmt_ex s -#else -#define TRACEOUT2(s) -#endif /* 1 */ - -static void np2stor_memread(UINT32 vaddr, void* buffer, UINT32 size) -{ - UINT32 readaddr = vaddr; - UINT32 readsize = size; - UINT8* readptr = (UINT8*)buffer; - while (readsize >= 4) - { - *((UINT32*)readptr) = cpu_kmemoryread_d(readaddr); - readsize -= 4; - readptr += 4; - readaddr += 4; - } - while (readsize > 0) - { - *readptr = cpu_kmemoryread(readaddr); - readsize--; - readptr++; - readaddr++; - } -} -static void np2stor_memwrite(UINT32 vaddr, void* buffer, UINT32 size) -{ - UINT32 writeaddr = vaddr; - UINT32 writesize = size; - UINT8* writeptr = (UINT8*)buffer; - while (writesize >= 4) - { - cpu_kmemorywrite_d(writeaddr, *((UINT32*)writeptr)); - writesize -= 4; - writeptr += 4; - writeaddr += 4; - } - while (writesize > 0) - { - cpu_kmemorywrite(writeaddr, *writeptr); - writesize--; - writeptr++; - writeaddr++; - } -} - -// StartIoの処理 -static void np2stor_startIo() -{ - NP2STOR_INVOKEINFO invokeInfo; - - if (np2stor.maddr == 0) return; - -#if defined(SUPPORT_IA32_HAXM) - // HAXMレジスタを読み取り - i386haxfunc_vcpu_getREGs(&np2haxstat.state); - i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); - np2haxstat.update_regs = np2haxstat.update_fpu = 0; - // HAXMレジスタ→猫レジスタにコピー - ia32hax_copyregHAXtoNP2(); -#endif - - // ドライバから渡されたメモリアドレスからデータを直接読み取り - invokeInfo.version = cpu_kmemoryread_d(np2stor.maddr); - if (invokeInfo.version == 1) - { - invokeInfo.cmd = cpu_kmemoryread_d(np2stor.maddr + 4); - if (invokeInfo.cmd == NP2STOR_INVOKECMD_DEFAULT || invokeInfo.cmd == NP2STOR_INVOKECMD_NOBUSY) - { - UINT8 drv = 0; - SXSIDEV sxsi = NULL; - NP2_SCSI_REQUEST_BLOCK srb = { 0 }; - invokeInfo.srbAddr = cpu_kmemoryread_d(np2stor.maddr + 8); - np2stor_memread(invokeInfo.srbAddr, &srb, sizeof(srb)); - if (srb.PathId == 0 && 0 <= srb.TargetId && srb.TargetId < 4 && srb.Lun == 0) - { - drv = SXSIDRV_SCSI + srb.TargetId; - sxsi = sxsi_getptr(drv); - } - if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY))) - { - srb.SrbStatus = NP2_SRB_STATUS_NO_DEVICE; - return; - } - - switch (srb.Function) - { - case NP2_SRB_FUNCTION_EXECUTE_SCSI: - switch (srb.Cdb[0]) - { - case NP2_SCSIOP_TEST_UNIT_READY: - srb.ScsiStatus = NP2_SCSISTAT_GOOD; - srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; - srb.DataTransferLength = 0; - break; - - case NP2_SCSIOP_INQUIRY: - { - UINT32 dataLength = sizeof(NP2_INQUIRYDATA); - NP2_INQUIRYDATA inquiryData = { 0 }; - if (srb.DataTransferLength < dataLength) dataLength = srb.DataTransferLength; - //np2stor_memread(srb.DataBuffer, &inquiryData, dataLength); // NT4では初期値は0にしておかないとだめ なので現在のメモリのデータは読まない - inquiryData.DeviceType = 0x00; // DIRECT_ACCESS_DEVICE - inquiryData.RemovableMedia = FALSE; - inquiryData.Versions = 0x04; - inquiryData.ResponseDataFormat = 0x02; - inquiryData.AdditionalLength = 0x1f; - RtlCopyMemory(inquiryData.VendorId, "NP2 ", 8); - RtlCopyMemory(inquiryData.ProductId, "FASTSTORAGE ", 16); - RtlCopyMemory(inquiryData.ProductRevisionLevel, "1.00", 4); - //inquiryData->ProductId[8] = '0' + Srb->PathId; - //inquiryData->ProductId[10] = '0' + Srb->TargetId; - //inquiryData->ProductId[12] = '0' + Srb->Lun; - srb.ScsiStatus = NP2_SCSISTAT_GOOD; - srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; - srb.DataTransferLength = dataLength; - np2stor_memwrite(srb.DataBuffer, &inquiryData, dataLength); - - break; - } - - case NP2_SCSIOP_READ_CAPACITY: - { - UINT32 dataLength = sizeof(NP2_READ_CAPACITY_DATA); - NP2_READ_CAPACITY_DATA cap = { 0 }; - UINT32 lastSector; - if (srb.DataTransferLength < dataLength) - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - break; - } - np2stor_memread(srb.DataBuffer, &cap, dataLength); - lastSector = sxsi->totals - 1; - cap.LogicalBlockAddress = (((lastSector) & 0xff) << 24) | (((lastSector >> 8) & 0xff) << 16) | (((lastSector >> 16) & 0xff) << 8) | ((lastSector >> 24) & 0xff); - cap.BytesPerBlock = (((NP2STOR_SECTOR_SIZE) & 0xff) << 24) | (((NP2STOR_SECTOR_SIZE >> 8) & 0xff) << 16) | (((NP2STOR_SECTOR_SIZE >> 16) & 0xff) << 8) | ((NP2STOR_SECTOR_SIZE >> 24) & 0xff); - - np2stor_memwrite(srb.DataBuffer, &cap, dataLength); - - srb.ScsiStatus = NP2_SCSISTAT_GOOD; - srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; - srb.DataTransferLength = dataLength; - break; - } - - case NP2_SCSIOP_READ: - case NP2_SCSIOP_WRITE: - { - UINT64 offset = (((UINT64)srb.Cdb[2] << 24) | ((UINT64)srb.Cdb[3] << 16) | ((UINT64)srb.Cdb[4] << 8) | (UINT64)srb.Cdb[5]); - UINT64 lengthInBytes = (((UINT64)srb.Cdb[7] << 8) | (UINT64)srb.Cdb[8]) * NP2STOR_SECTOR_SIZE; - UINT8* lpBuffer; - - if (offset * NP2STOR_SECTOR_SIZE + lengthInBytes > sxsi->totals * NP2STOR_SECTOR_SIZE) - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - break; - } - - lpBuffer = (UINT8*)malloc(lengthInBytes); - if (!lpBuffer) - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - break; - } - if (srb.Cdb[0] == NP2_SCSIOP_READ) - { - if (sxsi_read(drv, offset, lpBuffer, lengthInBytes)) - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - break; - } - np2stor_memwrite(srb.DataBuffer, lpBuffer, lengthInBytes); - } - else - { - if (invokeInfo.cmd != NP2STOR_INVOKECMD_NOBUSY) - { - // WORKAROUND: Win2KがEDBx.LOGを大量生成してしまうので、20MB書き込む毎にBUSYを返す - np2stor.busyflag += lengthInBytes; - if (np2stor.busyflag > 1024 * 1024 * 20) - { - np2stor.busyflag = 0; - srb.SrbStatus = NP2_SRB_STATUS_BUSY; - break; - } - } - np2stor_memread(srb.DataBuffer, lpBuffer, lengthInBytes); - if (sxsi_write(drv, offset, lpBuffer, lengthInBytes)) - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - break; - } - } - - free(lpBuffer); - - srb.ScsiStatus = NP2_SCSISTAT_GOOD; - srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; - srb.DataTransferLength = lengthInBytes; - break; - } - - case NP2_SCSIOP_READ6: - case NP2_SCSIOP_WRITE6: - { - UINT64 offset = (((UINT64)srb.Cdb[1] & 0x1F) << 16) | ((UINT64)srb.Cdb[2] << 8) | ((UINT64)srb.Cdb[3]); - UINT64 lengthInBytes = srb.Cdb[4] * NP2STOR_SECTOR_SIZE; - UINT8* lpBuffer; - if (lengthInBytes == 0) - { - lengthInBytes = 256 * NP2STOR_SECTOR_SIZE; - } - - if (offset * NP2STOR_SECTOR_SIZE + lengthInBytes > sxsi->totals * NP2STOR_SECTOR_SIZE) - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - break; - } - - lpBuffer = (UINT8*)malloc(lengthInBytes); - if (!lpBuffer) - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - break; - } - if (srb.Cdb[0] == NP2_SCSIOP_READ6) - { - if (sxsi_read(drv, offset, lpBuffer, lengthInBytes)) - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - break; - } - np2stor_memwrite(srb.DataBuffer, lpBuffer, lengthInBytes); - } - else - { - np2stor_memread(srb.DataBuffer, lpBuffer, lengthInBytes); - if (sxsi_write(drv, offset, lpBuffer, lengthInBytes)) - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - break; - } - } - - free(lpBuffer); - - srb.ScsiStatus = NP2_SCSISTAT_GOOD; - srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; - srb.DataTransferLength = lengthInBytes; - break; - } - - case NP2_SCSIOP_SEEK: - srb.ScsiStatus = NP2_SCSISTAT_GOOD; - srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; - srb.DataTransferLength = 0; - break; - - case NP2_SCSIOP_VERIFY: - { - UINT64 lba = ((UINT64)srb.Cdb[2] << 24) | ((UINT64)srb.Cdb[3] << 16) | ((UINT64)srb.Cdb[4] << 8) | ((UINT64)srb.Cdb[5]); - UINT64 length = ((UINT64)srb.Cdb[7] << 8) | (UINT64)srb.Cdb[8]; - - if ((lba + length) > sxsi->totals) - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - } - srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; - srb.DataTransferLength = 0; - break; - } - - case NP2_SCSIOP_MODE_SENSE: - { - // PC-98版WIn2000のDISK.SYSでは以下の条件を満たしたときだけMODE SENSEのCHSの結果を使用 - // ・MODE SENSEで全ページ要求したとき、Page1→Page3→Page4の順に返す - // ・PageLength(ページ全体のサイズ - 2)が以下の通り - //   Page1 = 6, Page2 = 22, Page3 = 18 - // ・MODE SENSEでPage3とPage4がとれない場合はIDEのBIOSでディスクCHS探しに行く - // ・それでも見つからない場合はH:Sを255:63にされる - if ((srb.Cdb[2] & 0x3f) == NP2_MODE_SENSE_RETURN_ALL) - { - UINT8 buffer[sizeof(NP2_MODE_PARAMETER_HEADER) + sizeof(NP2_MODE_PARAMETER_BLOCK) + sizeof(NP2_MODE_READ_RECOVERY_PAGE) + sizeof(NP2_MODE_FORMAT_PAGE) + sizeof(NP2_MODE_RIGID_GEOMETRY_PAGE)] = { 0 }; - UINT32 bufferLength = sizeof(buffer); - UINT8 dbd = srb.Cdb[1] & 0x08; // DBD - UINT8 allocationLength = srb.Cdb[4]; // CDB byte 4 = Allocation length - UINT8 pageCode = srb.Cdb[2] & 0x3F; // bit6=PCF (Page Control), bit0-5 = Page Code - NP2_MODE_PARAMETER_HEADER* header = NULL; - NP2_MODE_PARAMETER_BLOCK* blockdesc = NULL; - NP2_MODE_READ_RECOVERY_PAGE* recpage = NULL; - NP2_MODE_FORMAT_PAGE* fmtpage = NULL; - NP2_MODE_RIGID_GEOMETRY_PAGE* geopage = NULL; - - header = (NP2_MODE_PARAMETER_HEADER*)(buffer); - header->ModeDataLength = bufferLength - 1; - header->MediumType = 0; - header->DeviceSpecificParameter = 0; - - if (dbd) - { - header->BlockDescriptorLength = 0; - recpage = (NP2_MODE_READ_RECOVERY_PAGE*)((UINT8*)header + sizeof(NP2_MODE_PARAMETER_HEADER)); - fmtpage = (NP2_MODE_FORMAT_PAGE*)((UINT8*)recpage + sizeof(NP2_MODE_READ_RECOVERY_PAGE)); - geopage = (NP2_MODE_RIGID_GEOMETRY_PAGE*)((UINT8*)fmtpage + sizeof(NP2_MODE_FORMAT_PAGE)); - bufferLength -= sizeof(NP2_MODE_PARAMETER_BLOCK); - } - else - { - header->BlockDescriptorLength = sizeof(NP2_MODE_PARAMETER_BLOCK); - blockdesc = (NP2_MODE_PARAMETER_BLOCK*)((UINT8*)header + sizeof(NP2_MODE_PARAMETER_HEADER)); - recpage = (NP2_MODE_READ_RECOVERY_PAGE*)((UINT8*)blockdesc + sizeof(NP2_MODE_PARAMETER_BLOCK)); - fmtpage = (NP2_MODE_FORMAT_PAGE*)((UINT8*)recpage + sizeof(NP2_MODE_READ_RECOVERY_PAGE)); - geopage = (NP2_MODE_RIGID_GEOMETRY_PAGE*)((UINT8*)fmtpage + sizeof(NP2_MODE_FORMAT_PAGE)); - - blockdesc->DensityCode = 0x00; // Density Code - blockdesc->NumberOfBlocks[0] = (sxsi->sectors >> 16) & 0xff; // Number of Blocks - blockdesc->NumberOfBlocks[1] = (sxsi->sectors >> 8) & 0xff; // Number of Blocks - blockdesc->NumberOfBlocks[2] = (sxsi->sectors) & 0xff; // Number of Blocks - blockdesc->Reserved = 0x00; // Reserved - blockdesc->BlockLength[0] = (sxsi->size >> 8) & 0xff; // Block Length - blockdesc->BlockLength[1] = (sxsi->size >> 8) & 0xff; // Block Length - blockdesc->BlockLength[2] = (sxsi->size) & 0xff; // Block Length - } - - recpage->PageCode = 0x01; - recpage->PageLength = sizeof(NP2_MODE_READ_RECOVERY_PAGE) - 2; - - fmtpage->PageCode = 0x03; - fmtpage->PageLength = sizeof(NP2_MODE_FORMAT_PAGE) - 2; - fmtpage->SectorsPerTrack[0] = (sxsi->sectors >> 8) & 0xff; - fmtpage->SectorsPerTrack[1] = (sxsi->sectors) & 0xff; - fmtpage->BytesPerPhysicalSector[0] = (sxsi->size >> 8) & 0xff; - fmtpage->BytesPerPhysicalSector[1] = (sxsi->size) & 0xff; - fmtpage->Interleave[1] = 1; - - geopage->PageCode = 0x04; - geopage->PageLength = sizeof(NP2_MODE_RIGID_GEOMETRY_PAGE) - 2; - geopage->NumberOfCylinders[0] = (sxsi->cylinders >> 16) & 0xff; - geopage->NumberOfCylinders[1] = (sxsi->cylinders >> 8) & 0xff; - geopage->NumberOfCylinders[2] = (sxsi->cylinders) & 0xff; - geopage->NumberOfHeads = sxsi->surfaces; - - if (allocationLength < bufferLength) - { - // 格納先長さ足りないので削る - bufferLength -= sizeof(NP2_MODE_RIGID_GEOMETRY_PAGE); - } - if (allocationLength < bufferLength) - { - // 格納先長さ足りないので削る - bufferLength -= sizeof(NP2_MODE_FORMAT_PAGE); - } - if (allocationLength < bufferLength) - { - // 格納先長さ足りないので削る - bufferLength -= sizeof(NP2_MODE_READ_RECOVERY_PAGE); - } - if (allocationLength < bufferLength) - { - // もう削れないのでエラー - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - } - else - { - // 返せる分を返す - np2stor_memwrite(srb.DataBuffer, &buffer, bufferLength); - - srb.ScsiStatus = NP2_SCSISTAT_GOOD; - srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; - srb.DataTransferLength = bufferLength; - } - } - else - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - } - break; - } - - case NP2_SCSIOP_MEDIUM_REMOVAL: - { - srb.ScsiStatus = NP2_SCSISTAT_GOOD; - srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; - srb.DataTransferLength = 0; - break; - } - - default: - TRACEOUT2(("Unknown Function=0x%02x, SCSIOP=0x%02x", srb.Function, srb.Cdb[0])); - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - break; - } - break; - - case NP2_SRB_FUNCTION_IO_CONTROL: - { - //NP2_SRB_IO_CONTROL ioctrl; - //if (srb.DataBuffer == NULL && cpu_kmemoryread_d(srb.DataBuffer) < sizeof(ioctrl)) - //{ - // srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - // break; - //} - //np2stor_memread(srb.DataBuffer, &ioctrl, sizeof(ioctrl)); - //if (ioctrl.ControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) - //{ - // if (ioctrl.Length >= sizeof(DISK_GEOMETRY)) - // { - // NP2_DISK_GEOMETRY geo = { 0 }; - // np2stor_memwrite(srb.DataBuffer + sizeof(ioctrl), &geo, sizeof(geo)); - // geo.Cylinders = sxsi->cylinders; - // geo.MediaType = 12; // Fixed hard disk media - // geo.TracksPerCylinder = sxsi->surfaces; - // geo.SectorsPerTrack = sxsi->sectors; - // geo.BytesPerSector = sxsi->size; - - // ioctrl.ReturnCode = 0; - // np2stor_memwrite(srb.DataBuffer, &ioctrl, sizeof(ioctrl)); - // srb.ScsiStatus = NP2_SCSISTAT_GOOD; - // srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; - // srb.DataTransferLength = sizeof(NP2_SRB_IO_CONTROL) + sizeof(NP2_DISK_GEOMETRY); - // } - // else - // { - // srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - // } - //} - //else - { - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - } - - break; - } - - default: - srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; - break; - } - - np2stor_memwrite(invokeInfo.srbAddr, &srb, sizeof(srb)); - } - } -} - -static void IOOUTCALL np2stor_o7ea(UINT port, REG8 dat) -{ - np2stor.maddr = (dat << 24) | (np2stor.maddr >> 8); - (void)port; -} - -static void IOOUTCALL np2stor_o7eb(UINT port, REG8 dat) -{ - // データ格納先の仮想メモリアドレスをI/Oポート7EAhへ書き込み、 - // 7EBhに0x98→0x01の順で書き込むと猫本体が処理を実行する。 - if (dat == NP2STOR_CMD_ACTIVATE) - { - np2stor.ioenable = 1; - } - else if (dat == NP2STOR_CMD_STARTIO && np2stor.ioenable) - { - np2stor_startIo(); - } - else - { - np2stor.ioenable = 0; - } - (void)port; -} - -static REG8 IOINPCALL np2stor_i7ea(UINT port) -{ - return(98); -} - -static REG8 IOINPCALL np2stor_i7eb(UINT port) -{ - return(21); -} - -#endif - - -// ---- - -void scsiio_reset(const NP2CFG *pConfig) { - - FILEH fh; - UINT r; - - ZeroMemory(&scsiio, sizeof(scsiio)); - if (pccore.hddif & PCHDD_SCSI) { - scsiio.memwnd = (0xd200 & 0x0e00) >> 9; - scsiio.resent = (3 << 3) + (7 << 0); - - CPU_RAM_D000 |= (3 << 2); // ramにする - fh = file_open_rb_c(OEMTEXT("scsi.rom")); - r = 0; - if (fh != FILEH_INVALID) { - r = file_read(fh, scsiio.bios, 0x4000); - file_close(fh); - } - if (r != 0) { // if (r == 0x4000) { - TRACEOUT(("load scsi.rom")); - } - else { - ZeroMemory(mem + 0xd2000, 0x4000); - CopyMemory(scsiio.bios, scsibios, sizeof(scsibios)); - TRACEOUT(("use simulate scsi.rom")); - } - CopyMemory(mem + 0xd2000, scsiio.bios[0], 0x2000); - } - -#if defined(SUPPORT_NP2SCSI) - ZeroMemory(&np2stor, sizeof(np2stor)); - if (np2cfg.usenp2stor) - { - np2stor.enable = 1; - } -#endif - - (void)pConfig; -} - -void scsiio_bind(void) { - - if (pccore.hddif & PCHDD_SCSI) { - iocore_attachout(0x0cc0, scsiio_occ0); - iocore_attachout(0x0cc2, scsiio_occ2); - iocore_attachout(0x0cc4, scsiio_occ4); - iocore_attachout(0x0cc6, scsiio_occ6); - iocore_attachinp(0x0cc0, scsiio_icc0); - iocore_attachinp(0x0cc2, scsiio_icc2); - iocore_attachinp(0x0cc4, scsiio_icc4); - iocore_attachinp(0x0cc6, scsiio_icc6); - -#if defined(SUPPORT_NP2SCSI) - if (np2stor.enable) - { - iocore_attachout(0x07ea, np2stor_o7ea); - iocore_attachout(0x07eb, np2stor_o7eb); - iocore_attachinp(0x07ea, np2stor_i7ea); - iocore_attachinp(0x07eb, np2stor_i7eb); - } -#endif - } -} - -#endif - +#include + +#if defined(SUPPORT_SCSI) + +#include +#include +#include +#include +#include +#include +#include "scsiio.tbl" +#include +#include "scsibios.res" +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif +#include + + + _SCSIIO scsiio; + +static const UINT8 scsiirq[] = {0x03, 0x05, 0x06, 0x09, 0x0c, 0x0d, 3, 3}; + + +void scsiioint(NEVENTITEM item) { + + TRACEOUT(("scsiioint")); + if (scsiio.membank & 4) { + pic_setirq(scsiirq[(scsiio.resent >> 3) & 7]); + TRACEOUT(("scsi intr")); + } + scsiio.auxstatus = 0x80; + (void)item; +} + +static void scsiintr(REG8 status) { + + scsiio.scsistatus = status; + nevent_set(NEVENT_SCSIIO, 4000, scsiioint, NEVENT_ABSOLUTE); +} + +static void scsicmd(REG8 cmd) { + + REG8 ret; + UINT8 id; + + id = scsiio.reg[SCSICTR_DSTID] & 7; + switch(cmd) { + case SCSICMD_RESET: + scsiintr(SCSISTAT_RESET); + break; + + case SCSICMD_NEGATE: + ret = scsicmd_negate(id); + scsiintr(ret); + break; + + case SCSICMD_SEL: + ret = scsicmd_select(id); + if (ret & 0x80) { + scsiintr(0x11); + // で retはどーやって割り込みさせるの? + } + else { + scsiintr(ret); + } + break; + + case SCSICMD_SEL_TR: + ret = scsicmd_transfer(id, scsiio.reg + SCSICTR_CDB); + if (ret != 0xff) { + scsiintr(ret); + } + break; + } +} + + + +// ---- + +static void IOOUTCALL scsiio_occ0(UINT port, REG8 dat) { + + scsiio.port = dat; + (void)port; +} + +static void IOOUTCALL scsiio_occ2(UINT port, REG8 dat) { + + UINT8 bit; + + if (scsiio.port < 0x40) { + TRACEOUT(("scsi ctrl write %s %.2x", scsictr[scsiio.port], dat)); + } + if (scsiio.port <= 0x19) { + scsiio.reg[scsiio.port] = dat; + if (scsiio.port == SCSICTR_CMD) { + scsicmd(dat); + } + scsiio.port++; + } + else { + switch(scsiio.port) { + case SCSICTR_MEMBANK: + scsiio.membank = dat; + if (!(dat & 0x40)) { + CopyMemory(mem + 0xd2000, scsiio.bios[0], 0x2000); + } + else { + CopyMemory(mem + 0xd2000, scsiio.bios[1], 0x2000); + } + break; + + case 0x3f: + bit = 1 << (dat & 7); + if (dat & 8) { + scsiio.datmap |= bit; + } + else { + if (scsiio.datmap & bit) { + scsiio.datmap &= ~bit; + if (bit == (1 << 1)) { + scsiio.wrdatpos = 0; + } + else if (bit == (1 << 5)) { + scsiio.rddatpos = 0; + } + } + } + break; + } + } + (void)port; +} + +static void IOOUTCALL scsiio_occ4(UINT port, REG8 dat) { + + TRACEOUT(("scsiio_occ4 %.2x", dat)); + (void)port; + (void)dat; +} + +static void IOOUTCALL scsiio_occ6(UINT port, REG8 dat) { + + scsiio.data[scsiio.wrdatpos & 0x7fff] = dat; + scsiio.wrdatpos++; + (void)port; +} + +static REG8 IOINPCALL scsiio_icc0(UINT port) { + + REG8 ret; + + ret = scsiio.auxstatus; + scsiio.auxstatus = 0; + (void)port; + return(ret); +} + +static REG8 IOINPCALL scsiio_icc2(UINT port) { + + REG8 ret; + + switch(scsiio.port) { + case SCSICTR_STATUS: + scsiio.port++; + return(scsiio.scsistatus); + + case SCSICTR_MEMBANK: + return(scsiio.membank); + + case SCSICTR_MEMWND: + return(scsiio.memwnd); + + case SCSICTR_RESENT: + return(scsiio.resent); + + case 0x36: + return(0); // 2枚刺しとか… + } + if (scsiio.port <= 0x19) { + ret = scsiio.reg[scsiio.port]; + TRACEOUT(("scsi ctrl read %s %.2x [%.4x:%.4x]", + scsictr[scsiio.port], ret, CPU_CS, CPU_IP)); + scsiio.port++; + return(ret); + } + (void)port; + return(0xff); +} + +static REG8 IOINPCALL scsiio_icc4(UINT port) { + + TRACEOUT(("scsiio_icc4")); + (void)port; + return(0x00); +} + +static REG8 IOINPCALL scsiio_icc6(UINT port) { + + REG8 ret; + + ret = scsiio.data[scsiio.rddatpos & 0x7fff]; + scsiio.rddatpos++; + (void)port; + return(ret); +} + +#if defined(SUPPORT_NP2SCSI) + +_NP2STOR np2stor; + +#if 0 +#undef TRACEOUT2 +static void trace_fmt_ex(const char* fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "¥n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT2(s) trace_fmt_ex s +#else +#define TRACEOUT2(s) +#endif /* 1 */ + +static void np2stor_memread(UINT32 vaddr, void* buffer, UINT32 size) +{ + UINT32 readaddr = vaddr; + UINT32 readsize = size; + UINT8* readptr = (UINT8*)buffer; + while (readsize >= 4) + { + *((UINT32*)readptr) = cpu_kmemoryread_d(readaddr); + readsize -= 4; + readptr += 4; + readaddr += 4; + } + while (readsize > 0) + { + *readptr = cpu_kmemoryread(readaddr); + readsize--; + readptr++; + readaddr++; + } +} +static void np2stor_memwrite(UINT32 vaddr, void* buffer, UINT32 size) +{ + UINT32 writeaddr = vaddr; + UINT32 writesize = size; + UINT8* writeptr = (UINT8*)buffer; + while (writesize >= 4) + { + cpu_kmemorywrite_d(writeaddr, *((UINT32*)writeptr)); + writesize -= 4; + writeptr += 4; + writeaddr += 4; + } + while (writesize > 0) + { + cpu_kmemorywrite(writeaddr, *writeptr); + writesize--; + writeptr++; + writeaddr++; + } +} + +// StartIoの処理 +static void np2stor_startIo() +{ + NP2STOR_INVOKEINFO invokeInfo; + + if (np2stor.maddr == 0) return; + +#if defined(SUPPORT_IA32_HAXM) + // HAXMレジスタを読み取り + i386haxfunc_vcpu_getREGs(&np2haxstat.state); + i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); + np2haxstat.update_regs = np2haxstat.update_fpu = 0; + // HAXMレジスタ→猫レジスタにコピー + ia32hax_copyregHAXtoNP2(); +#endif + + // ドライバから渡されたメモリアドレスからデータを直接読み取り + invokeInfo.version = cpu_kmemoryread_d(np2stor.maddr); + if (invokeInfo.version == 1) + { + invokeInfo.cmd = cpu_kmemoryread_d(np2stor.maddr + 4); + if (invokeInfo.cmd == NP2STOR_INVOKECMD_DEFAULT || invokeInfo.cmd == NP2STOR_INVOKECMD_NOBUSY) + { + UINT8 drv = 0; + SXSIDEV sxsi = NULL; + NP2_SCSI_REQUEST_BLOCK srb = { 0 }; + invokeInfo.srbAddr = cpu_kmemoryread_d(np2stor.maddr + 8); + np2stor_memread(invokeInfo.srbAddr, &srb, sizeof(srb)); + if (srb.PathId == 0 && 0 <= srb.TargetId && srb.TargetId < 4 && srb.Lun == 0) + { + drv = SXSIDRV_SCSI + srb.TargetId; + sxsi = sxsi_getptr(drv); + } + if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY))) + { + srb.SrbStatus = NP2_SRB_STATUS_NO_DEVICE; + return; + } + + switch (srb.Function) + { + case NP2_SRB_FUNCTION_EXECUTE_SCSI: + switch (srb.Cdb[0]) + { + case NP2_SCSIOP_TEST_UNIT_READY: + srb.ScsiStatus = NP2_SCSISTAT_GOOD; + srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; + srb.DataTransferLength = 0; + break; + + case NP2_SCSIOP_INQUIRY: + { + UINT32 dataLength = sizeof(NP2_INQUIRYDATA); + NP2_INQUIRYDATA inquiryData = { 0 }; + if (srb.DataTransferLength < dataLength) dataLength = srb.DataTransferLength; + //np2stor_memread(srb.DataBuffer, &inquiryData, dataLength); // NT4では初期値は0にしておかないとだめ なので現在のメモリのデータは読まない + inquiryData.DeviceType = 0x00; // DIRECT_ACCESS_DEVICE + inquiryData.RemovableMedia = FALSE; + inquiryData.Versions = 0x04; + inquiryData.ResponseDataFormat = 0x02; + inquiryData.AdditionalLength = 0x1f; + RtlCopyMemory(inquiryData.VendorId, "NP2 ", 8); + RtlCopyMemory(inquiryData.ProductId, "FASTSTORAGE ", 16); + RtlCopyMemory(inquiryData.ProductRevisionLevel, "1.00", 4); + //inquiryData->ProductId[8] = '0' + Srb->PathId; + //inquiryData->ProductId[10] = '0' + Srb->TargetId; + //inquiryData->ProductId[12] = '0' + Srb->Lun; + srb.ScsiStatus = NP2_SCSISTAT_GOOD; + srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; + srb.DataTransferLength = dataLength; + np2stor_memwrite(srb.DataBuffer, &inquiryData, dataLength); + + break; + } + + case NP2_SCSIOP_READ_CAPACITY: + { + UINT32 dataLength = sizeof(NP2_READ_CAPACITY_DATA); + NP2_READ_CAPACITY_DATA cap = { 0 }; + UINT32 lastSector; + if (srb.DataTransferLength < dataLength) + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + break; + } + np2stor_memread(srb.DataBuffer, &cap, dataLength); + lastSector = sxsi->totals - 1; + cap.LogicalBlockAddress = (((lastSector) & 0xff) << 24) | (((lastSector >> 8) & 0xff) << 16) | (((lastSector >> 16) & 0xff) << 8) | ((lastSector >> 24) & 0xff); + cap.BytesPerBlock = (((NP2STOR_SECTOR_SIZE) & 0xff) << 24) | (((NP2STOR_SECTOR_SIZE >> 8) & 0xff) << 16) | (((NP2STOR_SECTOR_SIZE >> 16) & 0xff) << 8) | ((NP2STOR_SECTOR_SIZE >> 24) & 0xff); + + np2stor_memwrite(srb.DataBuffer, &cap, dataLength); + + srb.ScsiStatus = NP2_SCSISTAT_GOOD; + srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; + srb.DataTransferLength = dataLength; + break; + } + + case NP2_SCSIOP_READ: + case NP2_SCSIOP_WRITE: + { + UINT64 offset = (((UINT64)srb.Cdb[2] << 24) | ((UINT64)srb.Cdb[3] << 16) | ((UINT64)srb.Cdb[4] << 8) | (UINT64)srb.Cdb[5]); + UINT64 lengthInBytes = (((UINT64)srb.Cdb[7] << 8) | (UINT64)srb.Cdb[8]) * NP2STOR_SECTOR_SIZE; + UINT8* lpBuffer; + + if (offset * NP2STOR_SECTOR_SIZE + lengthInBytes > sxsi->totals * NP2STOR_SECTOR_SIZE) + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + break; + } + + lpBuffer = (UINT8*)malloc(lengthInBytes); + if (!lpBuffer) + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + break; + } + if (srb.Cdb[0] == NP2_SCSIOP_READ) + { + if (sxsi_read(drv, offset, lpBuffer, lengthInBytes)) + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + break; + } + np2stor_memwrite(srb.DataBuffer, lpBuffer, lengthInBytes); + } + else + { + if (invokeInfo.cmd != NP2STOR_INVOKECMD_NOBUSY) + { + // WORKAROUND: Win2KがEDBx.LOGを大量生成してしまうので、20MB書き込む毎にBUSYを返す + np2stor.busyflag += lengthInBytes; + if (np2stor.busyflag > 1024 * 1024 * 20) + { + np2stor.busyflag = 0; + srb.SrbStatus = NP2_SRB_STATUS_BUSY; + break; + } + } + np2stor_memread(srb.DataBuffer, lpBuffer, lengthInBytes); + if (sxsi_write(drv, offset, lpBuffer, lengthInBytes)) + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + break; + } + } + + free(lpBuffer); + + srb.ScsiStatus = NP2_SCSISTAT_GOOD; + srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; + srb.DataTransferLength = lengthInBytes; + break; + } + + case NP2_SCSIOP_READ6: + case NP2_SCSIOP_WRITE6: + { + UINT64 offset = (((UINT64)srb.Cdb[1] & 0x1F) << 16) | ((UINT64)srb.Cdb[2] << 8) | ((UINT64)srb.Cdb[3]); + UINT64 lengthInBytes = srb.Cdb[4] * NP2STOR_SECTOR_SIZE; + UINT8* lpBuffer; + if (lengthInBytes == 0) + { + lengthInBytes = 256 * NP2STOR_SECTOR_SIZE; + } + + if (offset * NP2STOR_SECTOR_SIZE + lengthInBytes > sxsi->totals * NP2STOR_SECTOR_SIZE) + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + break; + } + + lpBuffer = (UINT8*)malloc(lengthInBytes); + if (!lpBuffer) + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + break; + } + if (srb.Cdb[0] == NP2_SCSIOP_READ6) + { + if (sxsi_read(drv, offset, lpBuffer, lengthInBytes)) + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + break; + } + np2stor_memwrite(srb.DataBuffer, lpBuffer, lengthInBytes); + } + else + { + np2stor_memread(srb.DataBuffer, lpBuffer, lengthInBytes); + if (sxsi_write(drv, offset, lpBuffer, lengthInBytes)) + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + break; + } + } + + free(lpBuffer); + + srb.ScsiStatus = NP2_SCSISTAT_GOOD; + srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; + srb.DataTransferLength = lengthInBytes; + break; + } + + case NP2_SCSIOP_SEEK: + srb.ScsiStatus = NP2_SCSISTAT_GOOD; + srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; + srb.DataTransferLength = 0; + break; + + case NP2_SCSIOP_VERIFY: + { + UINT64 lba = ((UINT64)srb.Cdb[2] << 24) | ((UINT64)srb.Cdb[3] << 16) | ((UINT64)srb.Cdb[4] << 8) | ((UINT64)srb.Cdb[5]); + UINT64 length = ((UINT64)srb.Cdb[7] << 8) | (UINT64)srb.Cdb[8]; + + if ((lba + length) > sxsi->totals) + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + } + srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; + srb.DataTransferLength = 0; + break; + } + + case NP2_SCSIOP_MODE_SENSE: + { + // PC-98版WIn2000のDISK.SYSでは以下の条件を満たしたときだけMODE SENSEのCHSの結果を使用 + // ・MODE SENSEで全ページ要求したとき、Page1→Page3→Page4の順に返す + // ・PageLength(ページ全体のサイズ - 2)が以下の通り + //   Page1 = 6, Page2 = 22, Page3 = 18 + // ・MODE SENSEでPage3とPage4がとれない場合はIDEのBIOSでディスクCHS探しに行く + // ・それでも見つからない場合はH:Sを255:63にされる + if ((srb.Cdb[2] & 0x3f) == NP2_MODE_SENSE_RETURN_ALL) + { + UINT8 buffer[sizeof(NP2_MODE_PARAMETER_HEADER) + sizeof(NP2_MODE_PARAMETER_BLOCK) + sizeof(NP2_MODE_READ_RECOVERY_PAGE) + sizeof(NP2_MODE_FORMAT_PAGE) + sizeof(NP2_MODE_RIGID_GEOMETRY_PAGE)] = { 0 }; + UINT32 bufferLength = sizeof(buffer); + UINT8 dbd = srb.Cdb[1] & 0x08; // DBD + UINT8 allocationLength = srb.Cdb[4]; // CDB byte 4 = Allocation length + UINT8 pageCode = srb.Cdb[2] & 0x3F; // bit6=PCF (Page Control), bit0-5 = Page Code + NP2_MODE_PARAMETER_HEADER* header = NULL; + NP2_MODE_PARAMETER_BLOCK* blockdesc = NULL; + NP2_MODE_READ_RECOVERY_PAGE* recpage = NULL; + NP2_MODE_FORMAT_PAGE* fmtpage = NULL; + NP2_MODE_RIGID_GEOMETRY_PAGE* geopage = NULL; + + header = (NP2_MODE_PARAMETER_HEADER*)(buffer); + header->ModeDataLength = bufferLength - 1; + header->MediumType = 0; + header->DeviceSpecificParameter = 0; + + if (dbd) + { + header->BlockDescriptorLength = 0; + recpage = (NP2_MODE_READ_RECOVERY_PAGE*)((UINT8*)header + sizeof(NP2_MODE_PARAMETER_HEADER)); + fmtpage = (NP2_MODE_FORMAT_PAGE*)((UINT8*)recpage + sizeof(NP2_MODE_READ_RECOVERY_PAGE)); + geopage = (NP2_MODE_RIGID_GEOMETRY_PAGE*)((UINT8*)fmtpage + sizeof(NP2_MODE_FORMAT_PAGE)); + bufferLength -= sizeof(NP2_MODE_PARAMETER_BLOCK); + } + else + { + header->BlockDescriptorLength = sizeof(NP2_MODE_PARAMETER_BLOCK); + blockdesc = (NP2_MODE_PARAMETER_BLOCK*)((UINT8*)header + sizeof(NP2_MODE_PARAMETER_HEADER)); + recpage = (NP2_MODE_READ_RECOVERY_PAGE*)((UINT8*)blockdesc + sizeof(NP2_MODE_PARAMETER_BLOCK)); + fmtpage = (NP2_MODE_FORMAT_PAGE*)((UINT8*)recpage + sizeof(NP2_MODE_READ_RECOVERY_PAGE)); + geopage = (NP2_MODE_RIGID_GEOMETRY_PAGE*)((UINT8*)fmtpage + sizeof(NP2_MODE_FORMAT_PAGE)); + + blockdesc->DensityCode = 0x00; // Density Code + blockdesc->NumberOfBlocks[0] = (sxsi->sectors >> 16) & 0xff; // Number of Blocks + blockdesc->NumberOfBlocks[1] = (sxsi->sectors >> 8) & 0xff; // Number of Blocks + blockdesc->NumberOfBlocks[2] = (sxsi->sectors) & 0xff; // Number of Blocks + blockdesc->Reserved = 0x00; // Reserved + blockdesc->BlockLength[0] = (sxsi->size >> 8) & 0xff; // Block Length + blockdesc->BlockLength[1] = (sxsi->size >> 8) & 0xff; // Block Length + blockdesc->BlockLength[2] = (sxsi->size) & 0xff; // Block Length + } + + recpage->PageCode = 0x01; + recpage->PageLength = sizeof(NP2_MODE_READ_RECOVERY_PAGE) - 2; + + fmtpage->PageCode = 0x03; + fmtpage->PageLength = sizeof(NP2_MODE_FORMAT_PAGE) - 2; + fmtpage->SectorsPerTrack[0] = (sxsi->sectors >> 8) & 0xff; + fmtpage->SectorsPerTrack[1] = (sxsi->sectors) & 0xff; + fmtpage->BytesPerPhysicalSector[0] = (sxsi->size >> 8) & 0xff; + fmtpage->BytesPerPhysicalSector[1] = (sxsi->size) & 0xff; + fmtpage->Interleave[1] = 1; + + geopage->PageCode = 0x04; + geopage->PageLength = sizeof(NP2_MODE_RIGID_GEOMETRY_PAGE) - 2; + geopage->NumberOfCylinders[0] = (sxsi->cylinders >> 16) & 0xff; + geopage->NumberOfCylinders[1] = (sxsi->cylinders >> 8) & 0xff; + geopage->NumberOfCylinders[2] = (sxsi->cylinders) & 0xff; + geopage->NumberOfHeads = sxsi->surfaces; + + if (allocationLength < bufferLength) + { + // 格納先長さ足りないので削る + bufferLength -= sizeof(NP2_MODE_RIGID_GEOMETRY_PAGE); + } + if (allocationLength < bufferLength) + { + // 格納先長さ足りないので削る + bufferLength -= sizeof(NP2_MODE_FORMAT_PAGE); + } + if (allocationLength < bufferLength) + { + // 格納先長さ足りないので削る + bufferLength -= sizeof(NP2_MODE_READ_RECOVERY_PAGE); + } + if (allocationLength < bufferLength) + { + // もう削れないのでエラー + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + } + else + { + // 返せる分を返す + np2stor_memwrite(srb.DataBuffer, &buffer, bufferLength); + + srb.ScsiStatus = NP2_SCSISTAT_GOOD; + srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; + srb.DataTransferLength = bufferLength; + } + } + else + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + } + break; + } + + case NP2_SCSIOP_MEDIUM_REMOVAL: + { + srb.ScsiStatus = NP2_SCSISTAT_GOOD; + srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; + srb.DataTransferLength = 0; + break; + } + + default: + TRACEOUT2(("Unknown Function=0x%02x, SCSIOP=0x%02x", srb.Function, srb.Cdb[0])); + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + break; + } + break; + + case NP2_SRB_FUNCTION_IO_CONTROL: + { + //NP2_SRB_IO_CONTROL ioctrl; + //if (srb.DataBuffer == NULL && cpu_kmemoryread_d(srb.DataBuffer) < sizeof(ioctrl)) + //{ + // srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + // break; + //} + //np2stor_memread(srb.DataBuffer, &ioctrl, sizeof(ioctrl)); + //if (ioctrl.ControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) + //{ + // if (ioctrl.Length >= sizeof(DISK_GEOMETRY)) + // { + // NP2_DISK_GEOMETRY geo = { 0 }; + // np2stor_memwrite(srb.DataBuffer + sizeof(ioctrl), &geo, sizeof(geo)); + // geo.Cylinders = sxsi->cylinders; + // geo.MediaType = 12; // Fixed hard disk media + // geo.TracksPerCylinder = sxsi->surfaces; + // geo.SectorsPerTrack = sxsi->sectors; + // geo.BytesPerSector = sxsi->size; + + // ioctrl.ReturnCode = 0; + // np2stor_memwrite(srb.DataBuffer, &ioctrl, sizeof(ioctrl)); + // srb.ScsiStatus = NP2_SCSISTAT_GOOD; + // srb.SrbStatus = NP2_SRB_STATUS_SUCCESS; + // srb.DataTransferLength = sizeof(NP2_SRB_IO_CONTROL) + sizeof(NP2_DISK_GEOMETRY); + // } + // else + // { + // srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + // } + //} + //else + { + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + } + + break; + } + + default: + srb.SrbStatus = NP2_SRB_STATUS_INVALID_REQUEST; + break; + } + + np2stor_memwrite(invokeInfo.srbAddr, &srb, sizeof(srb)); + } + } +} + +static void IOOUTCALL np2stor_o7ea(UINT port, REG8 dat) +{ + np2stor.maddr = (dat << 24) | (np2stor.maddr >> 8); + (void)port; +} + +static void IOOUTCALL np2stor_o7eb(UINT port, REG8 dat) +{ + // データ格納先の仮想メモリアドレスをI/Oポート7EAhへ書き込み、 + // 7EBhに0x98→0x01の順で書き込むと猫本体が処理を実行する。 + if (dat == NP2STOR_CMD_ACTIVATE) + { + np2stor.ioenable = 1; + } + else if (dat == NP2STOR_CMD_STARTIO && np2stor.ioenable) + { + np2stor_startIo(); + } + else + { + np2stor.ioenable = 0; + } + (void)port; +} + +static REG8 IOINPCALL np2stor_i7ea(UINT port) +{ + return(98); +} + +static REG8 IOINPCALL np2stor_i7eb(UINT port) +{ + return(21); +} + +#endif + + +// ---- + +void scsiio_reset(const NP2CFG *pConfig) { + + FILEH fh; + UINT r; + + ZeroMemory(&scsiio, sizeof(scsiio)); + if (pccore.hddif & PCHDD_SCSI) { + scsiio.memwnd = (0xd200 & 0x0e00) >> 9; + scsiio.resent = (3 << 3) + (7 << 0); + + CPU_RAM_D000 |= (3 << 2); // ramにする + fh = file_open_rb_c(OEMTEXT("scsi.rom")); + r = 0; + if (fh != FILEH_INVALID) { + r = file_read(fh, scsiio.bios, 0x4000); + file_close(fh); + } + if (r != 0) { // if (r == 0x4000) { + TRACEOUT(("load scsi.rom")); + } + else { + ZeroMemory(mem + 0xd2000, 0x4000); + CopyMemory(scsiio.bios, scsibios, sizeof(scsibios)); + TRACEOUT(("use simulate scsi.rom")); + } + CopyMemory(mem + 0xd2000, scsiio.bios[0], 0x2000); + } + +#if defined(SUPPORT_NP2SCSI) + ZeroMemory(&np2stor, sizeof(np2stor)); + if (np2cfg.usenp2stor) + { + np2stor.enable = 1; + } +#endif + + (void)pConfig; +} + +void scsiio_bind(void) { + + if (pccore.hddif & PCHDD_SCSI) { + iocore_attachout(0x0cc0, scsiio_occ0); + iocore_attachout(0x0cc2, scsiio_occ2); + iocore_attachout(0x0cc4, scsiio_occ4); + iocore_attachout(0x0cc6, scsiio_occ6); + iocore_attachinp(0x0cc0, scsiio_icc0); + iocore_attachinp(0x0cc2, scsiio_icc2); + iocore_attachinp(0x0cc4, scsiio_icc4); + iocore_attachinp(0x0cc6, scsiio_icc6); + +#if defined(SUPPORT_NP2SCSI) + if (np2stor.enable) + { + iocore_attachout(0x07ea, np2stor_o7ea); + iocore_attachout(0x07eb, np2stor_o7eb); + iocore_attachinp(0x07ea, np2stor_i7ea); + iocore_attachinp(0x07eb, np2stor_i7eb); + } +#endif + } +} + +#endif + diff --git a/cbus/scsiio.h b/cbus/scsiio.h old mode 100755 new mode 100644 index bf0f411a..77b12429 --- a/cbus/scsiio.h +++ b/cbus/scsiio.h @@ -1,415 +1,415 @@ - -#if defined(SUPPORT_SCSI) - -typedef struct { - UINT port; - UINT phase; - UINT8 reg[0x30]; - UINT8 auxstatus; - UINT8 scsistatus; - UINT8 membank; - UINT8 memwnd; - UINT8 resent; - UINT8 datmap; - UINT cmdpos; - UINT wrdatpos; - UINT rddatpos; - UINT8 cmd[12]; - UINT8 data[0x10000]; - UINT8 bios[2][0x2000]; -} _SCSIIO, *SCSIIO; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern _SCSIIO scsiio; - -void scsiioint(NEVENTITEM item); - -void scsiio_reset(const NP2CFG *pConfig); -void scsiio_bind(void); - -#ifdef __cplusplus -} -#endif - -#if defined(SUPPORT_NP2SCSI) - -typedef struct -{ - UINT32 enable; - UINT32 ioenable; - UINT32 maddr; - UINT32 busyflag; - UINT32 reserved; -} _NP2STOR, *NP2STOR; - -extern _NP2STOR np2stor; - -#define NP2STOR_CMD_ACTIVATE 0x98 -#define NP2STOR_CMD_STARTIO 0x01 - -#define NP2STOR_INVOKECMD_DEFAULT 0x00 -#define NP2STOR_INVOKECMD_NOBUSY 0x01 - -#define NP2STOR_SECTOR_SIZE 512 - -#define NP2_SRB_FUNCTION_EXECUTE_SCSI 0x00 -#define NP2_SRB_FUNCTION_CLAIM_DEVICE 0x01 -#define NP2_SRB_FUNCTION_IO_CONTROL 0x02 -#define NP2_SRB_FUNCTION_RECEIVE_EVENT 0x03 -#define NP2_SRB_FUNCTION_RELEASE_QUEUE 0x04 -#define NP2_SRB_FUNCTION_ATTACH_DEVICE 0x05 -#define NP2_SRB_FUNCTION_RELEASE_DEVICE 0x06 -#define NP2_SRB_FUNCTION_SHUTDOWN 0x07 -#define NP2_SRB_FUNCTION_FLUSH 0x08 -#define NP2_SRB_FUNCTION_ABORT_COMMAND 0x10 -#define NP2_SRB_FUNCTION_RELEASE_RECOVERY 0x11 -#define NP2_SRB_FUNCTION_RESET_BUS 0x12 -#define NP2_SRB_FUNCTION_RESET_DEVICE 0x13 -#define NP2_SRB_FUNCTION_TERMINATE_IO 0x14 -#define NP2_SRB_FUNCTION_FLUSH_QUEUE 0x15 -#define NP2_SRB_FUNCTION_REMOVE_DEVICE 0x16 -#define NP2_SRB_FUNCTION_WMI 0x17 -#define NP2_SRB_FUNCTION_LOCK_QUEUE 0x18 -#define NP2_SRB_FUNCTION_UNLOCK_QUEUE 0x19 - -#define NP2_SRB_STATUS_PENDING 0x00 -#define NP2_SRB_STATUS_SUCCESS 0x01 -#define NP2_SRB_STATUS_ABORTED 0x02 -#define NP2_SRB_STATUS_ABORT_FAILED 0x03 -#define NP2_SRB_STATUS_ERROR 0x04 -#define NP2_SRB_STATUS_BUSY 0x05 -#define NP2_SRB_STATUS_INVALID_REQUEST 0x06 -#define NP2_SRB_STATUS_INVALID_PATH_ID 0x07 -#define NP2_SRB_STATUS_NO_DEVICE 0x08 -#define NP2_SRB_STATUS_TIMEOUT 0x09 -#define NP2_SRB_STATUS_SELECTION_TIMEOUT 0x0A -#define NP2_SRB_STATUS_COMMAND_TIMEOUT 0x0B -#define NP2_SRB_STATUS_MESSAGE_REJECTED 0x0D -#define NP2_SRB_STATUS_BUS_RESET 0x0E -#define NP2_SRB_STATUS_PARITY_ERROR 0x0F -#define NP2_SRB_STATUS_REQUEST_SENSE_FAILED 0x10 -#define NP2_SRB_STATUS_NO_HBA 0x11 -#define NP2_SRB_STATUS_DATA_OVERRUN 0x12 -#define NP2_SRB_STATUS_UNEXPECTED_BUS_FREE 0x13 -#define NP2_SRB_STATUS_PHASE_SEQUENCE_FAILURE 0x14 -#define NP2_SRB_STATUS_BAD_SRB_BLOCK_LENGTH 0x15 -#define NP2_SRB_STATUS_REQUEST_FLUSHED 0x16 -#define NP2_SRB_STATUS_INVALID_LUN 0x20 -#define NP2_SRB_STATUS_INVALID_TARGET_ID 0x21 -#define NP2_SRB_STATUS_BAD_FUNCTION 0x22 -#define NP2_SRB_STATUS_ERROR_RECOVERY 0x23 -#define NP2_SRB_STATUS_NOT_POWERED 0x24 - -#define NP2_SCSIOP_TEST_UNIT_READY 0x00 -#define NP2_SCSIOP_REZERO_UNIT 0x01 -#define NP2_SCSIOP_REWIND 0x01 -#define NP2_SCSIOP_REQUEST_BLOCK_ADDR 0x02 -#define NP2_SCSIOP_REQUEST_SENSE 0x03 -#define NP2_SCSIOP_FORMAT_UNIT 0x04 -#define NP2_SCSIOP_READ_BLOCK_LIMITS 0x05 -#define NP2_SCSIOP_REASSIGN_BLOCKS 0x07 -#define NP2_SCSIOP_READ6 0x08 -#define NP2_SCSIOP_RECEIVE 0x08 -#define NP2_SCSIOP_WRITE6 0x0A -#define NP2_SCSIOP_PRINT 0x0A -#define NP2_SCSIOP_SEND 0x0A -#define NP2_SCSIOP_SEEK6 0x0B -#define NP2_SCSIOP_TRACK_SELECT 0x0B -#define NP2_SCSIOP_SLEW_PRINT 0x0B -#define NP2_SCSIOP_SEEK_BLOCK 0x0C -#define NP2_SCSIOP_PARTITION 0x0D -#define NP2_SCSIOP_READ_REVERSE 0x0F -#define NP2_SCSIOP_WRITE_FILEMARKS 0x10 -#define NP2_SCSIOP_FLUSH_BUFFER 0x10 -#define NP2_SCSIOP_SPACE 0x11 -#define NP2_SCSIOP_INQUIRY 0x12 -#define NP2_SCSIOP_VERIFY6 0x13 -#define NP2_SCSIOP_RECOVER_BUF_DATA 0x14 -#define NP2_SCSIOP_MODE_SELECT 0x15 -#define NP2_SCSIOP_RESERVE_UNIT 0x16 -#define NP2_SCSIOP_RELEASE_UNIT 0x17 -#define NP2_SCSIOP_COPY 0x18 -#define NP2_SCSIOP_ERASE 0x19 -#define NP2_SCSIOP_MODE_SENSE 0x1A -#define NP2_SCSIOP_START_STOP_UNIT 0x1B -#define NP2_SCSIOP_STOP_PRINT 0x1B -#define NP2_SCSIOP_LOAD_UNLOAD 0x1B -#define NP2_SCSIOP_RECEIVE_DIAGNOSTIC 0x1C -#define NP2_SCSIOP_SEND_DIAGNOSTIC 0x1D -#define NP2_SCSIOP_MEDIUM_REMOVAL 0x1E -#define NP2_SCSIOP_READ_FORMAT_CAPACITY 0x23 -#define NP2_SCSIOP_READ_CAPACITY 0x25 -#define NP2_SCSIOP_READ 0x28 -#define NP2_SCSIOP_WRITE 0x2A -#define NP2_SCSIOP_WRITE_CD 0x2A -#define NP2_SCSIOP_SEEK 0x2B -#define NP2_SCSIOP_LOCATE 0x2B -#define NP2_SCSIOP_ERASE10 0x2C -#define NP2_SCSIOP_WRITE_VERIFY 0x2E -#define NP2_SCSIOP_VERIFY 0x2F -#define NP2_SCSIOP_SEARCH_DATA_HIGH 0x30 -#define NP2_SCSIOP_SEARCH_DATA_EQUAL 0x31 -#define NP2_SCSIOP_SEARCH_DATA_LOW 0x32 -#define NP2_SCSIOP_SET_LIMITS 0x33 -#define NP2_SCSIOP_READ_POSITION 0x34 -#define NP2_SCSIOP_SYNCHRONIZE_CACHE 0x35 -#define NP2_SCSIOP_COMPARE 0x39 -#define NP2_SCSIOP_COPY_COMPARE 0x3A -#define NP2_SCSIOP_COPY_VERIFY 0x3A -#define NP2_SCSIOP_WRITE_DATA_BUFF 0x3B -#define NP2_SCSIOP_READ_DATA_BUFF 0x3C -#define NP2_SCSIOP_CHANGE_DEFINITION 0x40 -#define NP2_SCSIOP_PLAY_AUDIO10 0x41 -#define NP2_SCSIOP_READ_SUB_CHANNEL 0x42 -#define NP2_SCSIOP_READ_TOC 0x43 -#define NP2_SCSIOP_READ_HEADER 0x44 -#define NP2_SCSIOP_PLAY_AUDIO 0x45 -#define NP2_SCSIOP_GET_CONFIGURATION 0x46 -#define NP2_SCSIOP_PLAY_AUDIO_MSF 0x47 -#define NP2_SCSIOP_PLAY_TRACK_INDEX 0x48 -#define NP2_SCSIOP_PLAY_TRACK_RELATIVE 0x49 -#define NP2_SCSIOP_GET_EVENT_STATUS 0x4A -#define NP2_SCSIOP_PAUSE_RESUME 0x4B -#define NP2_SCSIOP_LOG_SELECT 0x4C -#define NP2_SCSIOP_LOG_SENSE 0x4D -#define NP2_SCSIOP_STOP_PLAY_SCAN 0x4E -#define NP2_SCSIOP_READ_DISC_INFO 0x51 -#define NP2_SCSIOP_READ_TRACK_INFO 0x52 -#define NP2_SCSIOP_RESERVE_TRACK 0x53 -#define NP2_SCSIOP_SEND_OPC_INFO 0x54 -#define NP2_SCSIOP_MODE_SELECT10 0x55 -#define NP2_SCSIOP_REPAIR_TRACK 0x58 -#define NP2_SCSIOP_READ_MASTER_CUE 0x59 -#define NP2_SCSIOP_MODE_SENSE10 0x5A -#define NP2_SCSIOP_CLOSE_TRACK_SESSION 0x5B -#define NP2_SCSIOP_READ_BUFFER_CAPACITY 0x5C -#define NP2_SCSIOP_SEND_CUE_SHEET 0x5D -#define NP2_SCSIOP_READ16 0x88 -#define NP2_SCSIOP_WRITE16 0x8A -#define NP2_SCSIOP_VERIFY16 0x8F -#define NP2_SCSIOP_SERVICE_ACTION16 0x9E -#define NP2_SCSIOP_SA_READ_CAPACITY16 0x10 -#define NP2_SCSIOP_REPORT_LUNS 0xA0 -#define NP2_SCSIOP_BLANK 0xA1 -#define NP2_SCSIOP_SEND_KEY 0xA3 -#define NP2_SCSIOP_REPORT_KEY 0xA4 -#define NP2_SCSIOP_PLAY_AUDIO12 0xA5 -#define NP2_SCSIOP_LOAD_UNLOAD_SLOT 0xA6 -#define NP2_SCSIOP_SET_READ_AHEAD 0xA7 -#define NP2_SCSIOP_READ12 0xA8 -#define NP2_SCSIOP_WRITE12 0xAA -#define NP2_SCSIOP_VERIFY12 0xAF -#define NP2_SCSIOP_SEEK12 0xAB -#define NP2_SCSIOP_GET_PERFORMANCE 0xAC -#define NP2_SCSIOP_READ_DVD_STRUCTURE 0xAD -#define NP2_SCSIOP_WRITE_VERIFY12 0xAE -#define NP2_SCSIOP_VERIFY12 0xAF -#define NP2_SCSIOP_SET_STREAMING 0xB6 -#define NP2_SCSIOP_READ_CD_MSF 0xB9 -#define NP2_SCSIOP_SET_CD_SPEED 0xBB -#define NP2_SCSIOP_MECHANISM_STATUS 0xBD -#define NP2_SCSIOP_READ_CD 0xBE -#define NP2_SCSIOP_SEND_DVD_STRUCTURE 0xBF -#define NP2_SCSIOP_DOORLOCK 0xDE -#define NP2_SCSIOP_DOORUNLOCK 0xDF - -#define NP2_SCSISTAT_GOOD 0x00 -#define NP2_SCSISTAT_CHECK_CONDITION 0x02 -#define NP2_SCSISTAT_CONDITION_MET 0x04 -#define NP2_SCSISTAT_BUSY 0x08 -#define NP2_SCSISTAT_INTERMEDIATE 0x10 -#define NP2_SCSISTAT_INTERMEDIATE_COND_MET 0x14 -#define NP2_SCSISTAT_RESERVATION_CONFLICT 0x18 -#define NP2_SCSISTAT_COMMAND_TERMINATED 0x22 -#define NP2_SCSISTAT_QUEUE_FULL 0x28 - -#define NP2_MODE_SENSE_RETURN_ALL 0x3f - -#define NP2_MODE_PAGE_ERROR_RECOVERY 0x01 -#define NP2_MODE_PAGE_DISCONNECT 0x02 -#define NP2_MODE_PAGE_FORMAT_DEVICE 0x03 -#define NP2_MODE_PAGE_RIGID_GEOMETRY 0x04 - -#pragma pack(push, 4) -typedef struct _NP2_INQUIRYDATA -{ - UINT8 DeviceType : 5; - UINT8 DeviceTypeQualifier : 3; - UINT8 DeviceTypeModifier : 7; - UINT8 RemovableMedia : 1; - UINT8 Versions; - UINT8 ResponseDataFormat : 4; - UINT8 HiSupport : 1; - UINT8 NormACA : 1; - UINT8 ReservedBit : 1; - UINT8 AERC : 1; - UINT8 AdditionalLength; - UINT8 Reserved[2]; - UINT8 SoftReset : 1; - UINT8 CommandQueue : 1; - UINT8 Reserved2 : 1; - UINT8 LinkedCommands : 1; - UINT8 Synchronous : 1; - UINT8 Wide16Bit : 1; - UINT8 Wide32Bit : 1; - UINT8 RelativeAddressing : 1; - UINT8 VendorId[8]; - UINT8 ProductId[16]; - UINT8 ProductRevisionLevel[4]; - UINT8 VendorSpecific[20]; - UINT8 Reserved3[40]; -} NP2_INQUIRYDATA; -typedef struct _NP2_READ_CAPACITY_DATA -{ - UINT32 LogicalBlockAddress; - UINT32 BytesPerBlock; -} NP2_READ_CAPACITY_DATA; - -typedef struct -{ - UINT32 version; // \83o\81[\83W\83\87\83\93 \8D\A1\82̂Ƃ\B1\82\EB1\82̂\DD - UINT32 cmd; // \83R\83}\83\93\83h NP2STOR_INVOKECMD_xxx - UINT32 srbAddr; // SCSI_REQUEST_BLOCK\82ւ̉\BC\91z\83\81\83\82\83\8A\83A\83h\83\8C\83X -} NP2STOR_INVOKEINFO; - -typedef struct _NP2_SCSI_REQUEST_BLOCK -{ - UINT16 Length; - UINT8 Function; - UINT8 SrbStatus; - UINT8 ScsiStatus; - UINT8 PathId; - UINT8 TargetId; - UINT8 Lun; - UINT8 QueueTag; - UINT8 QueueAction; - UINT8 CdbLength; - UINT8 SenseInfoBufferLength; - UINT32 SrbFlags; - UINT32 DataTransferLength; - UINT32 TimeOutValue; - UINT32 DataBuffer; - UINT32 SenseInfoBuffer; - UINT32 NextSrb; // offset 20 - UINT32 OriginalRequest; - UINT32 SrbExtension; - union - { - UINT32 InternalStatus; - UINT32 QueueSortKey; - }; - UINT8 Cdb[16]; -} NP2_SCSI_REQUEST_BLOCK; - -typedef struct _NP2_SRB_IO_CONTROL -{ - UINT32 HeaderLength; - UINT8 Signature[8]; - UINT32 Timeout; - UINT32 ControlCode; - UINT32 ReturnCode; - UINT32 Length; -} NP2_SRB_IO_CONTROL; - -typedef struct _NP2_DISK_GEOMETRY -{ - UINT64 Cylinders; - UINT32 MediaType; - UINT32 TracksPerCylinder; - UINT32 SectorsPerTrack; - UINT32 BytesPerSector; -} NP2_DISK_GEOMETRY; -#pragma pack(pop) - -#pragma pack(push, 1) -typedef struct _NP2_MODE_PARAMETER_HEADER -{ - UINT8 ModeDataLength; - UINT8 MediumType; - UINT8 DeviceSpecificParameter; - UINT8 BlockDescriptorLength; -} NP2_MODE_PARAMETER_HEADER; - -typedef struct _NP2_MODE_PARAMETER_BLOCK -{ - UINT8 DensityCode; - UINT8 NumberOfBlocks[3]; - UINT8 Reserved; - UINT8 BlockLength[3]; -} NP2_MODE_PARAMETER_BLOCK; - -typedef struct _NP2_MODE_DUMMY_PAGE -{ - UINT8 PageCode : 6; - UINT8 Reserved : 1; - UINT8 PageSavable : 1; - UINT8 PageLength; -} NP2_MODE_DUMMY_PAGE; - -typedef struct _NP2_MODE_READ_RECOVERY_PAGE -{ - UINT8 PageCode : 6; // 0x01 - UINT8 Reserved1 : 1; - UINT8 PSBit : 1; - UINT8 PageLength; // sizeof(NP2_MODE_READ_RECOVERY_PAGE) - 2 = 6 - UINT8 DCRBit : 1; - UINT8 DTEBit : 1; - UINT8 PERBit : 1; - UINT8 Reserved2 : 1; - UINT8 RCBit : 1; - UINT8 TBBit : 1; - UINT8 Reserved3 : 2; - UINT8 ReadRetryCount; - UINT8 Reserved4[4]; -} NP2_MODE_READ_RECOVERY_PAGE; - -typedef struct _NP2_MODE_FORMAT_PAGE -{ - UINT8 PageCode : 6; // 0x03 - UINT8 Reserved : 1; - UINT8 PageSavable : 1; - UINT8 PageLength; // sizeof(NP2_MODE_FORMAT_PAGE) - 2 = 22 - UINT8 TracksPerZone[2]; - UINT8 AlternateSectorsPerZone[2]; - UINT8 AlternateTracksPerZone[2]; - UINT8 AlternateTracksPerLogicalUnit[2]; - UINT8 SectorsPerTrack[2]; - UINT8 BytesPerPhysicalSector[2]; - UINT8 Interleave[2]; - UINT8 TrackSkewFactor[2]; - UINT8 CylinderSkewFactor[2]; - UINT8 Reserved2 : 4; - UINT8 SurfaceFirst : 1; - UINT8 RemovableMedia : 1; - UINT8 HardSectorFormating : 1; - UINT8 SoftSectorFormating : 1; - UINT8 Reserved3[3]; -} NP2_MODE_FORMAT_PAGE; - -typedef struct _NP2_MODE_RIGID_GEOMETRY_PAGE -{ - UINT8 PageCode : 6; // 0x04 - UINT8 Reserved : 1; - UINT8 PageSavable : 1; - UINT8 PageLength; // sizeof(NP2_MODE_READ_RECOVERY_PAGE) - 2 = 18 <-- NEC\82\CD22\82ł͂Ȃ\AD18 - UINT8 NumberOfCylinders[3]; - UINT8 NumberOfHeads; - UINT8 StartWritePrecom[3]; - UINT8 StartReducedCurrent[3]; - UINT8 DriveStepRate[2]; - UINT8 LandZoneCyclinder[3]; - UINT8 RotationalPositionLock : 2; - UINT8 Reserved2 : 6; - UINT8 RotationOffset; - UINT8 Reserved3; -} NP2_MODE_RIGID_GEOMETRY_PAGE; -#pragma pack(pop) - -#endif - -#endif - + +#if defined(SUPPORT_SCSI) + +typedef struct { + UINT port; + UINT phase; + UINT8 reg[0x30]; + UINT8 auxstatus; + UINT8 scsistatus; + UINT8 membank; + UINT8 memwnd; + UINT8 resent; + UINT8 datmap; + UINT cmdpos; + UINT wrdatpos; + UINT rddatpos; + UINT8 cmd[12]; + UINT8 data[0x10000]; + UINT8 bios[2][0x2000]; +} _SCSIIO, *SCSIIO; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _SCSIIO scsiio; + +void scsiioint(NEVENTITEM item); + +void scsiio_reset(const NP2CFG *pConfig); +void scsiio_bind(void); + +#ifdef __cplusplus +} +#endif + +#if defined(SUPPORT_NP2SCSI) + +typedef struct +{ + UINT32 enable; + UINT32 ioenable; + UINT32 maddr; + UINT32 busyflag; + UINT32 reserved; +} _NP2STOR, *NP2STOR; + +extern _NP2STOR np2stor; + +#define NP2STOR_CMD_ACTIVATE 0x98 +#define NP2STOR_CMD_STARTIO 0x01 + +#define NP2STOR_INVOKECMD_DEFAULT 0x00 +#define NP2STOR_INVOKECMD_NOBUSY 0x01 + +#define NP2STOR_SECTOR_SIZE 512 + +#define NP2_SRB_FUNCTION_EXECUTE_SCSI 0x00 +#define NP2_SRB_FUNCTION_CLAIM_DEVICE 0x01 +#define NP2_SRB_FUNCTION_IO_CONTROL 0x02 +#define NP2_SRB_FUNCTION_RECEIVE_EVENT 0x03 +#define NP2_SRB_FUNCTION_RELEASE_QUEUE 0x04 +#define NP2_SRB_FUNCTION_ATTACH_DEVICE 0x05 +#define NP2_SRB_FUNCTION_RELEASE_DEVICE 0x06 +#define NP2_SRB_FUNCTION_SHUTDOWN 0x07 +#define NP2_SRB_FUNCTION_FLUSH 0x08 +#define NP2_SRB_FUNCTION_ABORT_COMMAND 0x10 +#define NP2_SRB_FUNCTION_RELEASE_RECOVERY 0x11 +#define NP2_SRB_FUNCTION_RESET_BUS 0x12 +#define NP2_SRB_FUNCTION_RESET_DEVICE 0x13 +#define NP2_SRB_FUNCTION_TERMINATE_IO 0x14 +#define NP2_SRB_FUNCTION_FLUSH_QUEUE 0x15 +#define NP2_SRB_FUNCTION_REMOVE_DEVICE 0x16 +#define NP2_SRB_FUNCTION_WMI 0x17 +#define NP2_SRB_FUNCTION_LOCK_QUEUE 0x18 +#define NP2_SRB_FUNCTION_UNLOCK_QUEUE 0x19 + +#define NP2_SRB_STATUS_PENDING 0x00 +#define NP2_SRB_STATUS_SUCCESS 0x01 +#define NP2_SRB_STATUS_ABORTED 0x02 +#define NP2_SRB_STATUS_ABORT_FAILED 0x03 +#define NP2_SRB_STATUS_ERROR 0x04 +#define NP2_SRB_STATUS_BUSY 0x05 +#define NP2_SRB_STATUS_INVALID_REQUEST 0x06 +#define NP2_SRB_STATUS_INVALID_PATH_ID 0x07 +#define NP2_SRB_STATUS_NO_DEVICE 0x08 +#define NP2_SRB_STATUS_TIMEOUT 0x09 +#define NP2_SRB_STATUS_SELECTION_TIMEOUT 0x0A +#define NP2_SRB_STATUS_COMMAND_TIMEOUT 0x0B +#define NP2_SRB_STATUS_MESSAGE_REJECTED 0x0D +#define NP2_SRB_STATUS_BUS_RESET 0x0E +#define NP2_SRB_STATUS_PARITY_ERROR 0x0F +#define NP2_SRB_STATUS_REQUEST_SENSE_FAILED 0x10 +#define NP2_SRB_STATUS_NO_HBA 0x11 +#define NP2_SRB_STATUS_DATA_OVERRUN 0x12 +#define NP2_SRB_STATUS_UNEXPECTED_BUS_FREE 0x13 +#define NP2_SRB_STATUS_PHASE_SEQUENCE_FAILURE 0x14 +#define NP2_SRB_STATUS_BAD_SRB_BLOCK_LENGTH 0x15 +#define NP2_SRB_STATUS_REQUEST_FLUSHED 0x16 +#define NP2_SRB_STATUS_INVALID_LUN 0x20 +#define NP2_SRB_STATUS_INVALID_TARGET_ID 0x21 +#define NP2_SRB_STATUS_BAD_FUNCTION 0x22 +#define NP2_SRB_STATUS_ERROR_RECOVERY 0x23 +#define NP2_SRB_STATUS_NOT_POWERED 0x24 + +#define NP2_SCSIOP_TEST_UNIT_READY 0x00 +#define NP2_SCSIOP_REZERO_UNIT 0x01 +#define NP2_SCSIOP_REWIND 0x01 +#define NP2_SCSIOP_REQUEST_BLOCK_ADDR 0x02 +#define NP2_SCSIOP_REQUEST_SENSE 0x03 +#define NP2_SCSIOP_FORMAT_UNIT 0x04 +#define NP2_SCSIOP_READ_BLOCK_LIMITS 0x05 +#define NP2_SCSIOP_REASSIGN_BLOCKS 0x07 +#define NP2_SCSIOP_READ6 0x08 +#define NP2_SCSIOP_RECEIVE 0x08 +#define NP2_SCSIOP_WRITE6 0x0A +#define NP2_SCSIOP_PRINT 0x0A +#define NP2_SCSIOP_SEND 0x0A +#define NP2_SCSIOP_SEEK6 0x0B +#define NP2_SCSIOP_TRACK_SELECT 0x0B +#define NP2_SCSIOP_SLEW_PRINT 0x0B +#define NP2_SCSIOP_SEEK_BLOCK 0x0C +#define NP2_SCSIOP_PARTITION 0x0D +#define NP2_SCSIOP_READ_REVERSE 0x0F +#define NP2_SCSIOP_WRITE_FILEMARKS 0x10 +#define NP2_SCSIOP_FLUSH_BUFFER 0x10 +#define NP2_SCSIOP_SPACE 0x11 +#define NP2_SCSIOP_INQUIRY 0x12 +#define NP2_SCSIOP_VERIFY6 0x13 +#define NP2_SCSIOP_RECOVER_BUF_DATA 0x14 +#define NP2_SCSIOP_MODE_SELECT 0x15 +#define NP2_SCSIOP_RESERVE_UNIT 0x16 +#define NP2_SCSIOP_RELEASE_UNIT 0x17 +#define NP2_SCSIOP_COPY 0x18 +#define NP2_SCSIOP_ERASE 0x19 +#define NP2_SCSIOP_MODE_SENSE 0x1A +#define NP2_SCSIOP_START_STOP_UNIT 0x1B +#define NP2_SCSIOP_STOP_PRINT 0x1B +#define NP2_SCSIOP_LOAD_UNLOAD 0x1B +#define NP2_SCSIOP_RECEIVE_DIAGNOSTIC 0x1C +#define NP2_SCSIOP_SEND_DIAGNOSTIC 0x1D +#define NP2_SCSIOP_MEDIUM_REMOVAL 0x1E +#define NP2_SCSIOP_READ_FORMAT_CAPACITY 0x23 +#define NP2_SCSIOP_READ_CAPACITY 0x25 +#define NP2_SCSIOP_READ 0x28 +#define NP2_SCSIOP_WRITE 0x2A +#define NP2_SCSIOP_WRITE_CD 0x2A +#define NP2_SCSIOP_SEEK 0x2B +#define NP2_SCSIOP_LOCATE 0x2B +#define NP2_SCSIOP_ERASE10 0x2C +#define NP2_SCSIOP_WRITE_VERIFY 0x2E +#define NP2_SCSIOP_VERIFY 0x2F +#define NP2_SCSIOP_SEARCH_DATA_HIGH 0x30 +#define NP2_SCSIOP_SEARCH_DATA_EQUAL 0x31 +#define NP2_SCSIOP_SEARCH_DATA_LOW 0x32 +#define NP2_SCSIOP_SET_LIMITS 0x33 +#define NP2_SCSIOP_READ_POSITION 0x34 +#define NP2_SCSIOP_SYNCHRONIZE_CACHE 0x35 +#define NP2_SCSIOP_COMPARE 0x39 +#define NP2_SCSIOP_COPY_COMPARE 0x3A +#define NP2_SCSIOP_COPY_VERIFY 0x3A +#define NP2_SCSIOP_WRITE_DATA_BUFF 0x3B +#define NP2_SCSIOP_READ_DATA_BUFF 0x3C +#define NP2_SCSIOP_CHANGE_DEFINITION 0x40 +#define NP2_SCSIOP_PLAY_AUDIO10 0x41 +#define NP2_SCSIOP_READ_SUB_CHANNEL 0x42 +#define NP2_SCSIOP_READ_TOC 0x43 +#define NP2_SCSIOP_READ_HEADER 0x44 +#define NP2_SCSIOP_PLAY_AUDIO 0x45 +#define NP2_SCSIOP_GET_CONFIGURATION 0x46 +#define NP2_SCSIOP_PLAY_AUDIO_MSF 0x47 +#define NP2_SCSIOP_PLAY_TRACK_INDEX 0x48 +#define NP2_SCSIOP_PLAY_TRACK_RELATIVE 0x49 +#define NP2_SCSIOP_GET_EVENT_STATUS 0x4A +#define NP2_SCSIOP_PAUSE_RESUME 0x4B +#define NP2_SCSIOP_LOG_SELECT 0x4C +#define NP2_SCSIOP_LOG_SENSE 0x4D +#define NP2_SCSIOP_STOP_PLAY_SCAN 0x4E +#define NP2_SCSIOP_READ_DISC_INFO 0x51 +#define NP2_SCSIOP_READ_TRACK_INFO 0x52 +#define NP2_SCSIOP_RESERVE_TRACK 0x53 +#define NP2_SCSIOP_SEND_OPC_INFO 0x54 +#define NP2_SCSIOP_MODE_SELECT10 0x55 +#define NP2_SCSIOP_REPAIR_TRACK 0x58 +#define NP2_SCSIOP_READ_MASTER_CUE 0x59 +#define NP2_SCSIOP_MODE_SENSE10 0x5A +#define NP2_SCSIOP_CLOSE_TRACK_SESSION 0x5B +#define NP2_SCSIOP_READ_BUFFER_CAPACITY 0x5C +#define NP2_SCSIOP_SEND_CUE_SHEET 0x5D +#define NP2_SCSIOP_READ16 0x88 +#define NP2_SCSIOP_WRITE16 0x8A +#define NP2_SCSIOP_VERIFY16 0x8F +#define NP2_SCSIOP_SERVICE_ACTION16 0x9E +#define NP2_SCSIOP_SA_READ_CAPACITY16 0x10 +#define NP2_SCSIOP_REPORT_LUNS 0xA0 +#define NP2_SCSIOP_BLANK 0xA1 +#define NP2_SCSIOP_SEND_KEY 0xA3 +#define NP2_SCSIOP_REPORT_KEY 0xA4 +#define NP2_SCSIOP_PLAY_AUDIO12 0xA5 +#define NP2_SCSIOP_LOAD_UNLOAD_SLOT 0xA6 +#define NP2_SCSIOP_SET_READ_AHEAD 0xA7 +#define NP2_SCSIOP_READ12 0xA8 +#define NP2_SCSIOP_WRITE12 0xAA +#define NP2_SCSIOP_VERIFY12 0xAF +#define NP2_SCSIOP_SEEK12 0xAB +#define NP2_SCSIOP_GET_PERFORMANCE 0xAC +#define NP2_SCSIOP_READ_DVD_STRUCTURE 0xAD +#define NP2_SCSIOP_WRITE_VERIFY12 0xAE +#define NP2_SCSIOP_VERIFY12 0xAF +#define NP2_SCSIOP_SET_STREAMING 0xB6 +#define NP2_SCSIOP_READ_CD_MSF 0xB9 +#define NP2_SCSIOP_SET_CD_SPEED 0xBB +#define NP2_SCSIOP_MECHANISM_STATUS 0xBD +#define NP2_SCSIOP_READ_CD 0xBE +#define NP2_SCSIOP_SEND_DVD_STRUCTURE 0xBF +#define NP2_SCSIOP_DOORLOCK 0xDE +#define NP2_SCSIOP_DOORUNLOCK 0xDF + +#define NP2_SCSISTAT_GOOD 0x00 +#define NP2_SCSISTAT_CHECK_CONDITION 0x02 +#define NP2_SCSISTAT_CONDITION_MET 0x04 +#define NP2_SCSISTAT_BUSY 0x08 +#define NP2_SCSISTAT_INTERMEDIATE 0x10 +#define NP2_SCSISTAT_INTERMEDIATE_COND_MET 0x14 +#define NP2_SCSISTAT_RESERVATION_CONFLICT 0x18 +#define NP2_SCSISTAT_COMMAND_TERMINATED 0x22 +#define NP2_SCSISTAT_QUEUE_FULL 0x28 + +#define NP2_MODE_SENSE_RETURN_ALL 0x3f + +#define NP2_MODE_PAGE_ERROR_RECOVERY 0x01 +#define NP2_MODE_PAGE_DISCONNECT 0x02 +#define NP2_MODE_PAGE_FORMAT_DEVICE 0x03 +#define NP2_MODE_PAGE_RIGID_GEOMETRY 0x04 + +#pragma pack(push, 4) +typedef struct _NP2_INQUIRYDATA +{ + UINT8 DeviceType : 5; + UINT8 DeviceTypeQualifier : 3; + UINT8 DeviceTypeModifier : 7; + UINT8 RemovableMedia : 1; + UINT8 Versions; + UINT8 ResponseDataFormat : 4; + UINT8 HiSupport : 1; + UINT8 NormACA : 1; + UINT8 ReservedBit : 1; + UINT8 AERC : 1; + UINT8 AdditionalLength; + UINT8 Reserved[2]; + UINT8 SoftReset : 1; + UINT8 CommandQueue : 1; + UINT8 Reserved2 : 1; + UINT8 LinkedCommands : 1; + UINT8 Synchronous : 1; + UINT8 Wide16Bit : 1; + UINT8 Wide32Bit : 1; + UINT8 RelativeAddressing : 1; + UINT8 VendorId[8]; + UINT8 ProductId[16]; + UINT8 ProductRevisionLevel[4]; + UINT8 VendorSpecific[20]; + UINT8 Reserved3[40]; +} NP2_INQUIRYDATA; +typedef struct _NP2_READ_CAPACITY_DATA +{ + UINT32 LogicalBlockAddress; + UINT32 BytesPerBlock; +} NP2_READ_CAPACITY_DATA; + +typedef struct +{ + UINT32 version; // \83o\81[\83W\83\87\83\93 \8D\A1\82̂Ƃ\B1\82\EB1\82̂\DD + UINT32 cmd; // \83R\83}\83\93\83h NP2STOR_INVOKECMD_xxx + UINT32 srbAddr; // SCSI_REQUEST_BLOCK\82ւ̉\BC\91z\83\81\83\82\83\8A\83A\83h\83\8C\83X +} NP2STOR_INVOKEINFO; + +typedef struct _NP2_SCSI_REQUEST_BLOCK +{ + UINT16 Length; + UINT8 Function; + UINT8 SrbStatus; + UINT8 ScsiStatus; + UINT8 PathId; + UINT8 TargetId; + UINT8 Lun; + UINT8 QueueTag; + UINT8 QueueAction; + UINT8 CdbLength; + UINT8 SenseInfoBufferLength; + UINT32 SrbFlags; + UINT32 DataTransferLength; + UINT32 TimeOutValue; + UINT32 DataBuffer; + UINT32 SenseInfoBuffer; + UINT32 NextSrb; // offset 20 + UINT32 OriginalRequest; + UINT32 SrbExtension; + union + { + UINT32 InternalStatus; + UINT32 QueueSortKey; + }; + UINT8 Cdb[16]; +} NP2_SCSI_REQUEST_BLOCK; + +typedef struct _NP2_SRB_IO_CONTROL +{ + UINT32 HeaderLength; + UINT8 Signature[8]; + UINT32 Timeout; + UINT32 ControlCode; + UINT32 ReturnCode; + UINT32 Length; +} NP2_SRB_IO_CONTROL; + +typedef struct _NP2_DISK_GEOMETRY +{ + UINT64 Cylinders; + UINT32 MediaType; + UINT32 TracksPerCylinder; + UINT32 SectorsPerTrack; + UINT32 BytesPerSector; +} NP2_DISK_GEOMETRY; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct _NP2_MODE_PARAMETER_HEADER +{ + UINT8 ModeDataLength; + UINT8 MediumType; + UINT8 DeviceSpecificParameter; + UINT8 BlockDescriptorLength; +} NP2_MODE_PARAMETER_HEADER; + +typedef struct _NP2_MODE_PARAMETER_BLOCK +{ + UINT8 DensityCode; + UINT8 NumberOfBlocks[3]; + UINT8 Reserved; + UINT8 BlockLength[3]; +} NP2_MODE_PARAMETER_BLOCK; + +typedef struct _NP2_MODE_DUMMY_PAGE +{ + UINT8 PageCode : 6; + UINT8 Reserved : 1; + UINT8 PageSavable : 1; + UINT8 PageLength; +} NP2_MODE_DUMMY_PAGE; + +typedef struct _NP2_MODE_READ_RECOVERY_PAGE +{ + UINT8 PageCode : 6; // 0x01 + UINT8 Reserved1 : 1; + UINT8 PSBit : 1; + UINT8 PageLength; // sizeof(NP2_MODE_READ_RECOVERY_PAGE) - 2 = 6 + UINT8 DCRBit : 1; + UINT8 DTEBit : 1; + UINT8 PERBit : 1; + UINT8 Reserved2 : 1; + UINT8 RCBit : 1; + UINT8 TBBit : 1; + UINT8 Reserved3 : 2; + UINT8 ReadRetryCount; + UINT8 Reserved4[4]; +} NP2_MODE_READ_RECOVERY_PAGE; + +typedef struct _NP2_MODE_FORMAT_PAGE +{ + UINT8 PageCode : 6; // 0x03 + UINT8 Reserved : 1; + UINT8 PageSavable : 1; + UINT8 PageLength; // sizeof(NP2_MODE_FORMAT_PAGE) - 2 = 22 + UINT8 TracksPerZone[2]; + UINT8 AlternateSectorsPerZone[2]; + UINT8 AlternateTracksPerZone[2]; + UINT8 AlternateTracksPerLogicalUnit[2]; + UINT8 SectorsPerTrack[2]; + UINT8 BytesPerPhysicalSector[2]; + UINT8 Interleave[2]; + UINT8 TrackSkewFactor[2]; + UINT8 CylinderSkewFactor[2]; + UINT8 Reserved2 : 4; + UINT8 SurfaceFirst : 1; + UINT8 RemovableMedia : 1; + UINT8 HardSectorFormating : 1; + UINT8 SoftSectorFormating : 1; + UINT8 Reserved3[3]; +} NP2_MODE_FORMAT_PAGE; + +typedef struct _NP2_MODE_RIGID_GEOMETRY_PAGE +{ + UINT8 PageCode : 6; // 0x04 + UINT8 Reserved : 1; + UINT8 PageSavable : 1; + UINT8 PageLength; // sizeof(NP2_MODE_READ_RECOVERY_PAGE) - 2 = 18 <-- NEC\82\CD22\82ł͂Ȃ\AD18 + UINT8 NumberOfCylinders[3]; + UINT8 NumberOfHeads; + UINT8 StartWritePrecom[3]; + UINT8 StartReducedCurrent[3]; + UINT8 DriveStepRate[2]; + UINT8 LandZoneCyclinder[3]; + UINT8 RotationalPositionLock : 2; + UINT8 Reserved2 : 6; + UINT8 RotationOffset; + UINT8 Reserved3; +} NP2_MODE_RIGID_GEOMETRY_PAGE; +#pragma pack(pop) + +#endif + +#endif + diff --git a/cbus/smpu98.c b/cbus/smpu98.c index 6a3529b2..afe42cb9 100644 --- a/cbus/smpu98.c +++ b/cbus/smpu98.c @@ -1,1715 +1,1715 @@ - -// emulation Super MPU - -// �Q�l���� -// �ESuper MPU Developer's Kit for Windows �v���O���}�[�Y�E�K�C�h -// �Ehttps://gist.github.com/o-p-a/8b26f12c36073a3f1f6829d3ed974dd1#file-smpumsg-txt-L93 - -#include - -#if defined(SUPPORT_SMPU98) - -#include -#include -#include -#include -#include -#include -#include - -enum { - MIDI_STOP = 0xfc, - - MIDIIN_AVAIL = 0x80, - MIDIOUT_BUSY = 0x40, - - MPUMSG_TRACKDATAREQ = 0xf0, - MPUMSG_OVERFLOW = 0xf8, - MPUMSG_REQCOND = 0xf9, - MPUMSG_DATAEND = 0xfc, - MPUMSG_HCLK = 0xfd, - MPUMSG_ACK = 0xfe, - MPUMSG_SYS = 0xff, - - MIDITIMEOUTCLOCK = 3000, - MIDITIMEOUTCLOCK2 = 300 -}; - -enum { - MIDIE_STEP = 0x01, - MIDIE_EVENT = 0x02, - MIDIE_DATA = 0x04 -}; - -enum { - MPUCMDP_IDLE = 0x00, - MPUCMDP_STEP = 0x01, - MPUCMDP_CMD = 0x02, - MPUCMDP_REQ = 0x04, - MPUCMDP_FOLLOWBYTE = 0x08, - MPUCMDP_SHORT = 0x10, - MPUCMDP_LONG = 0x20, - MPUCMDP_INIT = 0x80 -}; - -enum { - MPUSYNCMODE_INT = 0x00, - MPUSYNCMODE_FSK = 0x01, - MPUSYNCMODE_MIDI = 0x02, - - MPUMETROMODE_ACC = 0x00, - MPUMETROMODE_OFF = 0x01, - MPUMETROMODE_ON = 0x02, - - MPUFLAG1_PLAY = 0x01, - MPUFLAG1_BENDERTOHOST = 0x08, - MPUFLAG1_THRU = 0x10, - MPUFLAG1_DATAINSTOP = 0x20, - MPUFLAG1_SENDME = 0x40, - MPUFLAG1_CONDUCTOR = 0x80, - - MPUFLAG2_RTAFF = 0x01, - MPUFLAG2_FSKRESO = 0x02, - MPUFLAG2_CLKTOHOST = 0x04, - MPUFLAG2_EXECLUTOHOST = 0x08, - MPUFLAG2_REFA = 0x10, - MPUFLAG2_REFB = 0x20, - MPUFLAG2_REFC = 0x40, - MPUFLAG2_REFD = 0x80 -}; - -enum { - SMPUMODE_401 = 0, - SMPUMODE_UART = 1, - SMPUMODE_NATIVE = 2, -}; - -// [Native Mode] status �̃r�b�g -enum { - SMPU_STATUS_ISR = 0x0001, // Imm data set ready - SMPU_STATUS_SSR = 0x0002, // Seq data set ready - SMPU_STATUS_MSR = 0x0004, // Mon data set ready - SMPU_STATUS_IRR = 0x0008, // Imm data read ready - SMPU_STATUS_SRR = 0x0010, // Seq data read ready - SMPU_STATUS_RSS = 0x0020, // Request sequence set - SMPU_STATUS_RIR = 0x0040, // Request IMM receive - SMPU_STATUS_RSR = 0x0080, // Request SEQ receive - SMPU_STATUS_RMR = 0x0100, // Request MON receive - SMPU_STATUS_IM0 = 0x0200, // Int mask monitor 0001 - SMPU_STATUS_IM1 = 0x0400, // Int mask monitor 0002 - SMPU_STATUS_IM2 = 0x0800, // Int mask monitor 0004 - SMPU_STATUS_IM3 = 0x1000, // Int mask monitor 0008 - SMPU_STATUS_IM4 = 0x2000, // Int mask monitor 0010 -}; - -// [Native Mode] Int mask �̃r�b�g 0�ŋ֎~ 1�ŋ��� -enum { - SMPU_INTMASK_RSS = 0x0001, // RSS ���荞�� - SMPU_INTMASK_RIR = 0x0002, // RIR ���荞�� - SMPU_INTMASK_RSR = 0x0004, // RSR ���荞�� - SMPU_INTMASK_RMR = 0x0008, // RMR ���荞�� - SMPU_INTMASK_401 = 0x0010, // 401 ���荞�� - - SMPU_INTMASK_ALL = 0x001f, -}; - -#define SMPU_PORTS 2 - - _SMPU98 smpu98; - COMMNG cm_smpu98[SMPU_PORTS]; // [0]=A, [1]=B - - -static const UINT8 mpuirqnum[4] = {3, 5, 6, 12}; - -static const UINT8 shortmsgleng[0x10] = { - 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 2, 2, 3, 1}; - -static const UINT8 hclk_step1[4][4] = {{0, 0, 0, 0}, {1, 0, 0, 0}, - {1, 0, 1, 0}, {1, 1, 1, 0}}; - -// XXX: 根拠なし とりあえず大きめの値にしておく -#define SMPU98_WRITEBUFFER 2048 -static int smpu98_writecounter = 0; - -static void makeintclock(void) { - - UINT32 l; - UINT curtempo; - - l = smpu98.tempo * 2 * smpu98.reltempo / 0x40; - if (l < 5 * 2) { - l = 5 * 2; - } - curtempo = l >> 1; - if (curtempo > 250) { - curtempo = 250; - } - smpu98.curtempo = curtempo; - if (!(smpu98.flag2 & MPUFLAG2_FSKRESO)) { - l *= smpu98.inttimebase; // *12 - } - smpu98.stepclock = (pccore.realclock * 5 / l); // /12 -} - -static void sethclk(REG8 data) { - - REG8 quarter; - int i; - - quarter = data >> 2; - if (!quarter) { - quarter = 64; - } - for (i=0; i<4; i++) { - smpu98.hclk_step[i] = quarter + hclk_step1[data & 3][i]; - } - smpu98.hclk_rem = 0; -} - -static void setdefaultcondition(void) { - - smpu98.recvevent = 0; - smpu98.remainstep = 0; - smpu98.intphase = 0; - smpu98.intreq = 0; - - ZeroMemory(&smpu98.cmd, sizeof(smpu98.cmd)); - ZeroMemory(smpu98.tr, sizeof(smpu98.tr)); - ZeroMemory(&smpu98.cond, sizeof(smpu98.cond)); - - smpu98.syncmode = MPUSYNCMODE_INT; - smpu98.metromode = MPUMETROMODE_OFF; - smpu98.flag1 = MPUFLAG1_THRU | MPUFLAG1_SENDME; - smpu98.flag2 = MPUFLAG2_RTAFF; - - smpu98.inttimebase = 120 / 24; - smpu98.tempo = 100; - smpu98.reltempo = 0x40; - makeintclock(); - smpu98.midipermetero = 12; - smpu98.meteropermeas = 8; - sethclk(240); - smpu98.acttr = 0x00; - smpu98.sendplaycnt = 0; - smpu98.accch = 0xffff; - - // for S-MPU - smpu98.native_status = SMPU_STATUS_ISR|SMPU_STATUS_SSR|SMPU_STATUS_MSR; - smpu98.native_intmask = SMPU_INTMASK_ALL; - smpu98.mode = SMPUMODE_NATIVE; -} - -static void setrecvdata(REG8 data) { - - MPURECV *r; - - r = &smpu98.r; - if (r->cnt < MPU98_RECVBUFS) { - r->buf[(r->pos + r->cnt) & (MPU98_RECVBUFS - 1)] = data; - r->cnt++; - } -} - -// ------- for S-MPU Native Mode -static void smpu98_writeimm_r(UINT16 dat) { - if(smpu98.native_immbuf_r_len < SMPU_IMMBUF_R_LEN){ - // IMM READ�o�b�t�@�ɏ������ݏ��� - smpu98.native_immbuf_r[smpu98.native_immbuf_r_len] = dat; - smpu98.native_immbuf_r_len++; - if(smpu98.native_immbuf_r_len >= SMPU_IMMBUF_R_LEN){ - //smpu98.native_status |= SMPU_STATUS_IRR; // XXX: ����ŗǂ��̂�������Ȃ� - } - if(smpu98.native_status & SMPU_STATUS_ISR){ - smpu98.native_status &= ~SMPU_STATUS_ISR; - smpu98.native_status |= SMPU_STATUS_RIR; - } - } -} - -static void sendmpushortmsg(const UINT8 *dat, UINT count) { - - UINT i; - -#if 0 - if (!(smpu98.flag1 & MPUFLAG1_BENDERTOHOST)) { - switch(dat[0] >> 4) { - case 0x0a: - case 0x0d: - case 0x0e: - return; - - case 0x0b: - if (dat[1] < 0x40) { - return; - } - break; - } - } -#endif - if (smpu98.mode == SMPUMODE_NATIVE) { - for (i=0; iwrite(cm_smpu98[smpu98.native_portnum], dat[i]); - } - }else{ - for (i=0; iwrite(cm_smpu98[0], dat[i]); - } - if(smpu98.portBready && !smpu98.muteB) { - for (i=0; iwrite(cm_smpu98[1], dat[i]); - } - } - } -} - -static void sendmpulongmsg(const UINT8 *dat, UINT count) { - - UINT i; - - if (smpu98.mode == SMPUMODE_NATIVE) { - for (i=0; iwrite(cm_smpu98[smpu98.native_portnum], dat[i]); - } - }else{ - for (i=0; iwrite(cm_smpu98[0], dat[i]); - } - if(smpu98.portBready && !smpu98.muteB) { - for (i=0; iwrite(cm_smpu98[1], dat[i]); - } - } - } -} - -static void sendmpureset(void) { - - UINT i; - UINT8 sMessage[3]; - - if (smpu98.mode == SMPUMODE_NATIVE) { - UINT8 oldlinenum = smpu98.native_portnum; - for (i=0; i<0x10; i++) { - sMessage[0] = (UINT8)(0xb0 + i); - sMessage[1] = 0x7b; - sMessage[2] = 0x00; - smpu98.native_portnum = 0; - sendmpushortmsg(sMessage, 3); - smpu98.native_portnum = 1; - sendmpushortmsg(sMessage, 3); - } - smpu98.native_portnum = oldlinenum; - }else{ - for (i=0; i<0x10; i++) { - sMessage[0] = (UINT8)(0xb0 + i); - sMessage[1] = 0x7b; - sMessage[2] = 0x00; - sendmpushortmsg(sMessage, 3); - } - } -} - -static void smpu98_int(void) { - - TRACEOUT(("int!")); - pic_setirq(smpu98.irqnum); - - //if(!mpu98.enable){ - // // Sound Blaster 16 - // if(g_nSoundID == SOUNDID_SB16 || g_nSoundID == SOUNDID_PC_9801_86_SB16 || g_nSoundID == SOUNDID_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ - // pic_setirq(g_sb16.dmairq); - // } - // // PC-9801-118 - // if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ - // pic_setirq(10); - // } - // // WaveStar - // if(g_nSoundID == SOUNDID_WAVESTAR){ - // pic_setirq(10); - // } - //} -} - -static void tr_step(void) { - - int i; - REG8 bit; - - if (smpu98.flag1 & MPUFLAG1_CONDUCTOR) { - if (smpu98.cond.step) { - smpu98.cond.step--; - } - } - for (i=0, bit=1; i<8; bit<<=1, i++) { - if (smpu98.acttr & bit) { - if (smpu98.tr[i].step) { - smpu98.tr[i].step--; - } - } - } -} - -static BOOL tr_nextsearch(void) { - - int i; - REG8 bit; - -tr_nextsearch_more: - if (smpu98.intphase == 1) { - if (smpu98.flag1 & MPUFLAG1_CONDUCTOR) { - if (!smpu98.cond.step) { - smpu98.intreq = MPUMSG_REQCOND; - smpu98.cond.phase |= MPUCMDP_STEP | MPUCMDP_CMD; - smpu98_int(); - return(TRUE); - } - } - smpu98.intphase = 2; - } - if (smpu98.intphase) { - bit = 1 << (smpu98.intphase - 2); - do { - if (smpu98.acttr & bit) { - MPUTR *tr; - tr = smpu98.tr + (smpu98.intphase - 2); - if (!tr->step) { - if ((tr->datas) && (tr->remain == 0)) { - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (tr->data[0] == MIDI_STOP) { - tr->datas = 0; - cm_smpu98[0]->write(cm_smpu98[0], MIDI_STOP); - if(smpu98.portBready && !smpu98.muteB) cm_smpu98[1]->write(cm_smpu98[1], MIDI_STOP); - setrecvdata(MIDI_STOP); - smpu98_int(); - return(TRUE); - } - for (i=0; idatas; i++) { - cm_smpu98[0]->write(cm_smpu98[0], tr->data[i]); - if(smpu98.portBready && !smpu98.muteB) cm_smpu98[1]->write(cm_smpu98[1], tr->data[i]); - } - tr->datas = 0; - } - smpu98.intreq = 0xf0 + (smpu98.intphase - 2); - smpu98.recvevent |= MIDIE_STEP; - smpu98_int(); - return(TRUE); - } - } - bit <<= 1; - smpu98.intphase++; - } while(smpu98.intphase < 10); - smpu98.intphase = 0; - } - smpu98.remainstep--; - if (smpu98.remainstep) { - tr_step(); - smpu98.intphase = 1; - goto tr_nextsearch_more; - } - return(FALSE); -} - -void smpu98_midiint(NEVENTITEM item) { - - nevent_set(NEVENT_MIDIINT, smpu98.stepclock, smpu98_midiint, NEVENT_RELATIVE); - - if (smpu98.flag2 & MPUFLAG2_CLKTOHOST) { - if (!smpu98.hclk_rem) { - smpu98.hclk_rem = smpu98.hclk_step[smpu98.hclk_cnt & 3]; - smpu98.hclk_cnt++; - } - smpu98.hclk_rem--; - if (!smpu98.hclk_rem) { - setrecvdata(MPUMSG_HCLK); - smpu98_int(); - } - } - if (smpu98.flag1 & MPUFLAG1_PLAY) { - if (!smpu98.remainstep++) { - tr_step(); - smpu98.intphase = 1; - tr_nextsearch(); - } - } - (void)item; -} - -void smpu98_midiwaitout(NEVENTITEM item) { - -// TRACE_("midi ready", 0); - if (smpu98_writecounter > 0) { - smpu98_writecounter--; - } - if (smpu98_writecounter < SMPU98_WRITEBUFFER) { - // カウンタがバッファサイズより小さいならBUSY解除 - smpu98.status &= ~MIDIOUT_BUSY; - } - if (smpu98_writecounter > 0) { - // カウンタが0になるまで再登録 - nevent_set(NEVENT_MIDIWAIT, smpu98.xferclock, smpu98_midiwaitout, NEVENT_RELATIVE); - } - (void)item; -} - -static void midiwait(SINT32 waitclock) { - - // 転送が多すぎてバッファを溢れるようならBUSYに変える - smpu98_writecounter += waitclock / smpu98.xferclock; - if (smpu98_writecounter > SMPU98_WRITEBUFFER) { - smpu98.status |= MIDIOUT_BUSY; - } - if (!nevent_iswork(NEVENT_MIDIWAIT)) { - nevent_set(NEVENT_MIDIWAIT, smpu98.xferclock, smpu98_midiwaitout, NEVENT_ABSOLUTE); - } -} - -static void midicmdwait(SINT32 waitclock) { - - // 一定時間強制BUSY - smpu98_writecounter++; - smpu98.status |= MIDIOUT_BUSY; - if (!nevent_iswork(NEVENT_MIDIWAIT)) { - nevent_set(NEVENT_MIDIWAIT, smpu98.xferclock, smpu98_midiwaitout, NEVENT_ABSOLUTE); - } -} - - -// ---- - -typedef REG8 (*MPUCMDFN)(REG8 cmd); - -static REG8 mpucmd_xx(REG8 cmd) { - -// TRACEOUT(("unknown MPU commands: %.2x", cmd)); - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_md(REG8 cmd) { // 00-2F: Mode - - TRACEOUT(("mpucmd_md %.2x", cmd)); -#if 0 - switch((cmd >> 0) & 3) { - case 1: // MIDI Stop - case 2: // MIDI Start - case 3: // MIDI Cont - break; - } -#endif - switch((cmd >> 2) & 3) { - case 1: // Stop Play - smpu98.flag1 &= ~MPUFLAG1_PLAY; - smpu98.recvevent = 0; - smpu98.intphase = 0; - smpu98.intreq = 0; - ZeroMemory(smpu98.tr, sizeof(smpu98.tr)); - ZeroMemory(&smpu98.cond, sizeof(smpu98.cond)); - if (!(smpu98.flag2 & MPUFLAG2_CLKTOHOST)) { - nevent_reset(NEVENT_MIDIINT); - } - break; - - case 2: // Start Play - smpu98.flag1 |= MPUFLAG1_PLAY; - smpu98.remainstep = 0; - if (!nevent_iswork(NEVENT_MIDIINT)) { - nevent_set(NEVENT_MIDIINT, smpu98.stepclock, - smpu98_midiint, NEVENT_ABSOLUTE); - } - break; - } -#if 0 - switch((cmd >> 4) & 3) { - case 1: // Stop Rec - case 2: // Rec - break; - } -#endif - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_3f(REG8 cmd) { // 3F: UART - - smpu98.mode = SMPUMODE_UART; - sendmpureset(); - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_sr(REG8 cmd) { // 40-7F: Set ch of Ref table - - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_sm(REG8 cmd) { // 80-82: Clock Sync/Mode - - smpu98.syncmode = cmd - 0x80; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_mm(REG8 cmd) { // 83-85: Metronome - - smpu98.metromode = cmd - 0x83; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_8x(REG8 cmd) { // 86-8F: Flag1 - - REG8 bit; - - bit = 1 << ((cmd >> 1) & 7); - if (cmd & 1) { - smpu98.flag1 |= bit; - } - else { - smpu98.flag1 &= ~bit; - } -#if 0 - switch(cmd & 0x0f) { - case 0x06: // 86: Bender to Host / off - case 0x07: // 87: Bender to Host / on - case 0x08: // 88: THRU / off - case 0x09: // 89: THRU / on - case 0x0a: // 8A: Data in Stop / off - case 0x0b: // 8B: Data in Stop / on - case 0x0c: // 8C: Send Me / off - case 0x0d: // 8D: Send Me / on - case 0x0e: // 8E: Conductor / off - case 0x0f: // 8F: Conductor / on - break; - } -#endif - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_9x(REG8 cmd) { // 90-9F: Flag2 - - REG8 bit; - - bit = 1 << ((cmd >> 1) & 7); - if (cmd & 1) { - smpu98.flag2 |= bit; - } - else { - smpu98.flag2 &= ~bit; - } - switch(cmd & 0x0f) { -#if 0 - case 0x00: // 90: RT Aff / off - case 0x01: // 91: RT Aff / on - case 0x02: // 92: FSK Reso / INT - case 0x03: // 93: FSK Reso / 24 - break; -#endif - - case 0x04: // 94: CLK to Host / off - if (!(smpu98.flag1 & MPUFLAG1_PLAY)) { - nevent_reset(NEVENT_MIDIINT); - } - break; - - case 0x05: // 95: CLK to Host / on - if (!nevent_iswork(NEVENT_MIDIINT)) { - nevent_set(NEVENT_MIDIINT, smpu98.stepclock, - smpu98_midiint, NEVENT_ABSOLUTE); - } - break; - -#if 0 - case 0x06: // 96: Exclu to Host / off - case 0x07: // 97: Exclu to Host / on - case 0x08: // 98: Ref A / off - case 0x09: // 99: Ref A / on - case 0x0a: // 9A: Ref B / off - case 0x0b: // 9B: Ref B / on - case 0x0c: // 9C: Ref C / off - case 0x0d: // 9D: Ref C / on - case 0x0e: // 9E: Ref D / off - case 0x0f: // 9F: Ref D / on - break; -#endif - } - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_rq(REG8 cmd) { // A0-AF: Req - - (void)cmd; - return(MPUCMDP_REQ); -} - -static REG8 mpucmd_b1(REG8 cmd) { // B1: Clear Rel - - smpu98.reltempo = 0x40; - makeintclock(); - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_b8(REG8 cmd) { // B8: Clear PC - - int i; - - for (i=0; i<8; i++) { - smpu98.tr[i].step = 0; - } - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_tb(REG8 cmd) { // C2-C8: .INT Time Base - - smpu98.inttimebase = cmd & 0x0f; - makeintclock(); - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_ws(REG8 cmd) { // D0-D7: Want to Send Data - - (void)cmd; - return(MPUCMDP_SHORT | MPUCMDP_INIT); -} - -static REG8 mpucmd_df(REG8 cmd) { // DF: WSD System - - (void)cmd; - return(MPUCMDP_LONG | MPUCMDP_INIT); -} - -static REG8 mpucmd_fo(REG8 cmd) { // E0-EF: Following Byte - - (void)cmd; - return(MPUCMDP_FOLLOWBYTE); -} - -static REG8 mpucmd_fe(REG8 cmd) { // FE: Switch to Native Mode - - smpu98.mode = SMPUMODE_NATIVE; - sendmpureset(); - (void)cmd; - return(MPUCMDP_IDLE); -} - -static REG8 mpucmd_ff(REG8 cmd) { // FF: Reset - - sendmpureset(); - nevent_reset(NEVENT_MIDIINT); - setdefaultcondition(); - smpu98.mode = SMPUMODE_401; - (void)cmd; - return(MPUCMDP_IDLE); -} - -static const MPUCMDFN mpucmds[0x100] = { - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 00 - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 10 - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 20 - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, // 30 - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_3f, - - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 40 - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 50 - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 60 - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 70 - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, - - mpucmd_sm, mpucmd_sm, mpucmd_sm, mpucmd_mm, // 80 - mpucmd_mm, mpucmd_mm, mpucmd_8x, mpucmd_8x, - mpucmd_8x, mpucmd_8x, mpucmd_8x, mpucmd_8x, - mpucmd_8x, mpucmd_8x, mpucmd_8x, mpucmd_8x, - - mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, // 90 - mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, - mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, - mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, - - mpucmd_rq, mpucmd_rq, mpucmd_rq, mpucmd_rq, // a0 - mpucmd_rq, mpucmd_rq, mpucmd_rq, mpucmd_rq, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_rq, - mpucmd_rq, mpucmd_rq, mpucmd_xx, mpucmd_rq, - - mpucmd_xx, mpucmd_b1, mpucmd_xx, mpucmd_xx, // b0 - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_b8, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - - mpucmd_xx, mpucmd_xx, mpucmd_tb, mpucmd_tb, // c0 - mpucmd_tb, mpucmd_tb, mpucmd_tb, mpucmd_tb, - mpucmd_tb, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - - mpucmd_ws, mpucmd_ws, mpucmd_ws, mpucmd_ws, // d0 - mpucmd_ws, mpucmd_ws, mpucmd_ws, mpucmd_ws, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_df, - - mpucmd_fo, mpucmd_fo, mpucmd_fo, mpucmd_xx, // e0 - mpucmd_fo, mpucmd_xx, mpucmd_fo, mpucmd_fo, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_fo, mpucmd_fo, mpucmd_fo, mpucmd_fo, - - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, // f0 - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, - mpucmd_xx, mpucmd_xx, mpucmd_fe, mpucmd_ff}; - - -static void reqmpucmdgroupd(REG8 cmd) { - - switch(cmd) { - case 0xa0: // A0: Req Play Cnt Tr1 - case 0xa1: // A1: Req Play Cnt Tr2 - case 0xa2: // A2: Req Play Cnt Tr3 - case 0xa3: // A3: Req Play Cnt Tr4 - case 0xa4: // A4: Req Play Cnt Tr5 - case 0xa5: // A5: Req Play Cnt Tr6 - case 0xa6: // A6: Req Play Cnt Tr7 - case 0xa7: // A7: Req Play Cnt Tr8 - setrecvdata(smpu98.tr[cmd - 0xa0].step); - break; - - case 0xab: // AB: Read & Clear RC - setrecvdata(0); - break; - - case 0xac: // AC: Req Major Version - setrecvdata(0x20); - break; - - case 0xad: // AD: Req Minor Version - setrecvdata(0); - break; - - case 0xaf: // AF: Req Tempo - setrecvdata(smpu98.curtempo); - break; - } -} - -static void setmpucmdgroupe(REG8 cmd, REG8 data) { - - switch(cmd) { - case 0xe0: // Set Tempo - smpu98.tempo = data; - smpu98.reltempo = 0x40; - makeintclock(); - break; - - case 0xe1: // Rel Tempo - smpu98.reltempo = data; - makeintclock(); - break; - - case 0xe2: // Graduation - break; - - case 0xe4: // MIDI/Metro - smpu98.midipermetero = data; - break; - - case 0xe6: // Metro/Meas - smpu98.meteropermeas = data; - break; - - case 0xe7: // INTx4/H.CLK - sethclk(data); - break; - - case 0xec: // Act Tr - smpu98.acttr = data; - break; - - case 0xed: // Send Play CNT - smpu98.sendplaycnt = data; - break; - - case 0xee: // Acc CH 1-8 - smpu98.accch = (smpu98.accch & 0xff00) | data; - break; - - case 0xef: // Acc CH 9-16 - smpu98.accch = (smpu98.accch & 0x00ff) | (data << 8); - break; - } -} - -static BOOL sendmpumsg(MPUCMDS *cmd, REG8 data) { - - if (cmd->phase & MPUCMDP_SHORT) { - if (cmd->phase & MPUCMDP_INIT) { - cmd->phase &= ~MPUCMDP_INIT; - if (!(data & 0x80)) { - cmd->data[0] = cmd->rstat; - cmd->datapos = 1; - cmd->datacnt = shortmsgleng[cmd->rstat >> 4]; - } - else { - if ((data & 0xf0) != 0xf0) { - cmd->rstat = data; - } - cmd->datapos = 0; - cmd->datacnt = shortmsgleng[data >> 4]; - } - } - cmd->data[cmd->datapos] = data; - cmd->datapos++; - if (cmd->datapos >= cmd->datacnt) { - sendmpushortmsg(cmd->data, cmd->datacnt); - cmd->phase &= ~MPUCMDP_SHORT; - } - return(TRUE); - } - else if (cmd->phase & MPUCMDP_LONG) { - if (cmd->phase & MPUCMDP_INIT) { - cmd->phase &= ~MPUCMDP_INIT; - cmd->datapos = 0; - cmd->datacnt = sizeof(cmd->data); - } - if (cmd->datapos < cmd->datacnt) { - cmd->data[cmd->datapos] = data; - cmd->datapos++; - } - switch(cmd->data[0]) { - case 0xf0: - if (data == 0xf7) { - cmd->phase &= ~MPUCMDP_LONG; - sendmpulongmsg(cmd->data, cmd->datapos); - } - break; - - case 0xf2: - case 0xf3: - if (cmd->datapos >= 3) { - cmd->phase &= ~MPUCMDP_LONG; - } - break; - - case 0xf6: - default: - cmd->phase &= ~MPUCMDP_LONG; - break; - } - return(TRUE); - } - return(FALSE); -} - -static BRESULT sendmpucmd(MPUCMDS *cmd, REG8 data) { - - if (cmd->phase & MPUCMDP_FOLLOWBYTE) { - cmd->phase &= ~MPUCMDP_FOLLOWBYTE; - setmpucmdgroupe(cmd->cmd, data); - return(SUCCESS); - } - else if (cmd->phase & (MPUCMDP_SHORT | MPUCMDP_LONG)) { - sendmpumsg(cmd, data); - return(SUCCESS); - } - else { - cmd->phase = 0; - return(FAILURE); - } -} - -static BRESULT sendmpucond(MPUCMDS *cmd, REG8 data) { - - if (cmd->phase & (MPUCMDP_SHORT | MPUCMDP_LONG)) { -// if (smpu98.intreq == 0xf9) { -// smpu98.intreq = 0; -// } - sendmpumsg(cmd, data); - return(SUCCESS); - } - else if (cmd->phase & MPUCMDP_STEP) { - if (data < 0xf0) { - cmd->step = data; - cmd->phase &= ~MPUCMDP_STEP; - } - else { - cmd->step = 0xf0; - cmd->phase &= ~(MPUCMDP_STEP | MPUCMDP_CMD); - } - return(SUCCESS); - } - else if (cmd->phase & MPUCMDP_CMD) { - cmd->phase &= ~MPUCMDP_CMD; - cmd->cmd = data; - if (data < 0xf0) { - REG8 phase; - phase = (*mpucmds[data])(data); - if (phase & MPUCMDP_REQ) { - phase &= ~MPUCMDP_REQ; - reqmpucmdgroupd(data); - } - cmd->phase = phase; - if (phase & MPUCMDP_FOLLOWBYTE) { - return(SUCCESS); - } - } - else { - cmd->phase = 0; - if (data == MIDI_STOP) { - cm_smpu98[0]->write(cm_smpu98[0], MIDI_STOP); - if(smpu98.portBready && !smpu98.muteB) cm_smpu98[1]->write(cm_smpu98[1], MIDI_STOP); - setrecvdata(MIDI_STOP); - smpu98_int(); - } - } - } - else if (cmd->phase & MPUCMDP_FOLLOWBYTE) { - cmd->phase &= ~MPUCMDP_FOLLOWBYTE; - setmpucmdgroupe(cmd->cmd, data); - } - else { - cmd->phase = 0; - return(FAILURE); - } - - tr_nextsearch(); - return(SUCCESS); -} - -static void sendmpudata(REG8 data) { - - if (smpu98.cmd.phase) { - sendmpucmd(&smpu98.cmd, data); - return; - } - - if (smpu98.recvevent & MIDIE_STEP) { - MPUTR *tr; - smpu98.recvevent ^= MIDIE_STEP; - tr = smpu98.tr + (smpu98.intphase - 2); - tr->datas = 0; - if (data < 0xf0) { - smpu98.recvevent ^= MIDIE_EVENT; - tr->step = data; - } - else { - tr->step = 0xf0; - tr->remain = 0; - tr->datas = 0; - tr_nextsearch(); - } - return; - } - if (smpu98.recvevent & MIDIE_EVENT) { - MPUTR *tr; - smpu98.recvevent ^= MIDIE_EVENT; - smpu98.recvevent |= MIDIE_DATA; - tr = smpu98.tr + (smpu98.intphase - 2); - switch(data & 0xf0) { - case 0xc0: - case 0xd0: - tr->remain = 2; - tr->rstat = data; - break; - - case 0x80: - case 0x90: - case 0xa0: - case 0xb0: - case 0xe0: - tr->remain = 3; - tr->rstat = data; - break; - - case 0xf0: - tr->remain = 1; - break; - - default: - tr->data[0] = tr->rstat; - tr->datas = 1; - tr->remain = 2; - if ((tr->rstat & 0xe0) == 0xc0) { - tr->remain--; - } - break; - } - } - if (smpu98.recvevent & MIDIE_DATA) { - MPUTR *tr; - tr = smpu98.tr + (smpu98.intphase - 2); - if (tr->remain) { - tr->data[tr->datas] = data; - tr->datas++; - tr->remain--; - } - if (!tr->remain) { - smpu98.recvevent ^= MIDIE_DATA; - tr_nextsearch(); - } - return; - } - -#if 1 - if (smpu98.cond.phase) -#else - if (smpu98.cond.phase & (MPUCMDP_CMD | MPUCMDP_FOLLOWBYTE)) -#endif - { - sendmpucond(&smpu98.cond, data); - return; - } -} - -// [401 Mode] Data -void IOOUTCALL smpu98_o0(UINT port, REG8 dat) { - - UINT sent; - -TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (cm_smpu98[0]->connect != COMCONNECT_OFF) { - if (smpu98.mode == SMPUMODE_UART) { - sent = cm_smpu98[0]->write(cm_smpu98[0], (UINT8)dat); - if(smpu98.portBready && !smpu98.muteB) cm_smpu98[1]->write(cm_smpu98[1], (UINT8)dat); - } - else if(smpu98.mode == SMPUMODE_NATIVE){ - sent = 0; - } - else { -// TRACEOUT(("send data->%.2x", dat)); - sendmpudata(dat); - sent = 1; - } - if (sent) { - midiwait(smpu98.xferclock * sent); - } - } - (void)port; -} - -// [401 Mode] Command -void IOOUTCALL smpu98_o2(UINT port, REG8 dat) { - -TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (cm_smpu98[0]->connect != COMCONNECT_OFF) { - if (smpu98.mode != SMPUMODE_UART) { - REG8 phase; -// TRACEOUT(("send cmd->%.2x", dat)); - smpu98.cmd.cmd = dat; - phase = (*mpucmds[dat])(dat); - setrecvdata(MPUMSG_ACK); - smpu98_int(); - if (phase & MPUCMDP_REQ) { - phase &= ~MPUCMDP_REQ; - reqmpucmdgroupd(dat); - } - smpu98.cmd.phase = phase; - } - else { - if (dat == 0xff) { - smpu98.mode = SMPUMODE_401; - setrecvdata(MPUMSG_ACK); - } - } - midicmdwait(pccore.realclock / 10000); - } - (void)port; -} - -// [401 Mode] Data -REG8 IOINPCALL smpu98_i0(UINT port) { - - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (cm_smpu98[0]->connect != COMCONNECT_OFF) { - if (smpu98.r.cnt) { - smpu98.r.cnt--; -#if 0 - if (smpu98.r.cnt) { - smpu98_int(); - } - else { - pic_resetirq(smpu98.irqnum); - } -#endif - smpu98.data = smpu98.r.buf[smpu98.r.pos]; - smpu98.r.pos = (smpu98.r.pos + 1) & (MPU98_RECVBUFS - 1); - } - else if (smpu98.intreq) { - smpu98.data = smpu98.intreq; - smpu98.intreq = 0; - } - if ((smpu98.r.cnt) || (smpu98.intreq)) { - smpu98_int(); - } - else { - pic_resetirq(smpu98.irqnum); - } - -// TRACEOUT(("recv data->%.2x", smpu98.data)); -TRACEOUT(("smpu98 inp %.4x %.2x", port, smpu98.data)); - return(smpu98.data); - } - (void)port; - return(0xff); -} - -// [401 Mode] Status -REG8 IOINPCALL smpu98_i2(UINT port) { - - REG8 ret; - - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if ((cm_smpu98[0]->connect != COMCONNECT_OFF) || g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16) { - - ret = smpu98.status; - if ((smpu98.r.cnt == 0) && (smpu98.intreq == 0)) { - ret |= MIDIIN_AVAIL; - } -// TRACEOUT(("smpu98 inp %.4x %.2x", port, ret)); - return(ret); - } - (void)port; - return(0xff); -} - -// ------- for S-MPU Native Mode - -// [Native Mode] Immediate Message/Function -void IOOUTCALL smpu98_o4(UINT port, UINT16 dat) { - -TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { - if((smpu98.native_status & SMPU_STATUS_IRR) == 0){ - if(smpu98.native_immbuf_w_len < SMPU_IMMBUF_W_LEN){ - // IMM�������ݏ��� - smpu98.native_immbuf_w[smpu98.native_immbuf_w_len] = dat; - smpu98.native_immbuf_w_len++; - if(smpu98.native_immbuf_w_len >= SMPU_IMMBUF_W_LEN){ - //smpu98.native_status |= SMPU_STATUS_IRR; // XXX: ����ŗǂ��̂�������Ȃ� - } - } - } - } - (void)port; -} - -// [Native Mode] Sequence Message/Function -void IOOUTCALL smpu98_o6(UINT port, UINT16 dat) { - -TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { - if((smpu98.native_status & SMPU_STATUS_SRR) == 0){ - if(smpu98.native_seqbuf_w_len < SMPU_SEQBUF_W_LEN){ - // SEQ�������ݏ��� - smpu98.native_seqbuf_w[smpu98.native_seqbuf_w_len] = dat; - smpu98.native_seqbuf_w_len++; - if(smpu98.native_seqbuf_w_len >= SMPU_SEQBUF_W_LEN){ - //smpu98.native_status |= SMPU_STATUS_SRR; // XXX: ����ŗǂ��̂�������Ȃ� - } - } - } - } - (void)port; -} - -// [Native Mode] Interrupt to Super MPU -void IOOUTCALL smpu98_o8(UINT port, UINT16 dat) { - - UINT16 sent = 0; - -TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { - UINT8 *buf = smpu98.native_tmpbuf; - switch(dat){ - case 1: - // IMM���� - while(smpu98.native_immbuf_w_pos < smpu98.native_immbuf_w_len){ - UINT16 w1 = smpu98.native_immbuf_w[smpu98.native_immbuf_w_pos]; - UINT8 msg = ((w1 >> 8) & 0xff); - if(msg & 0x80){ - smpu98.native_lastmsg = msg; - if(msg==0xf7){ - // F7(End of Exclusive)�������� - sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 >> 8) & 0xff); - smpu98.native_lastmsg = smpu98.native_runningmsg; - }else if(msg==0xef){ - // Continue Exclusive - smpu98.native_linenum = (w1 & 0xff); - smpu98.native_portnum = (smpu98.native_linenum > 0xf ? 1 : 0); - smpu98.native_lastmsg = 0xf0; - }else if(0xf0 <= msg && msg <= 0xff){ - // ���C���i���o�[������đ��� - smpu98.native_linenum = (w1 & 0xff); - smpu98.native_portnum = (smpu98.native_linenum > 0xf ? 1 : 0); - sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 >> 8) & 0xff); - }else if(msg & 0x0f){ - // �Ƃ肠�������� - if(smpu98.native_lastmsg==0xf0){ - // �^�C���X�^���v�Ƃ����Ԃɋ��߂�炵���BContinue Exclusive�������Ă�����Exclusive���M�ĊJ - } - }else{ - // ch�����đ��� - smpu98.native_linenum = (w1 & 0xff); - smpu98.native_portnum = (smpu98.native_linenum > 0xf ? 1 : 0); - sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 >> 8) & 0xf0 | (smpu98.native_linenum & 0xf)); - smpu98.native_runningmsg = msg; - } - }else{ - msg = smpu98.native_lastmsg; // ���߂̃��b�Z�[�W�̑��� - if(!(msg==0xf7) && !(0xf0 <= msg && msg <= 0xff || msg==0xef) && (msg & 0x0f)){ - // �Ƃ肠�������� - }else{ - switch(msg){ - case 0xc0: - case 0xd0: - // 1byte�ڂ������� - sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 >> 8) & 0xff); - break; - default: - // ���̂܂ܑ��� - sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 >> 8) & 0xff); - sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 ) & 0xff); - if((w1 & 0xff) == 0xf7){ - smpu98.native_lastmsg = smpu98.native_runningmsg; - } - } - } - } - smpu98.native_immbuf_w_pos++; - } - smpu98.native_immbuf_w_pos = smpu98.native_immbuf_w_len = 0; - break; - case 2: - // TODO: SEQ���� - smpu98.native_seqbuf_w_pos = smpu98.native_seqbuf_w_len = 0; - break; - } - if (sent) { - //midiwait(smpu98.xferclock * sent); - } - } - (void)port; -} - -// [Native Mode] Interrupt Mask -void IOOUTCALL smpu98_oa(UINT port, UINT16 dat) { - -TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { - smpu98.native_intmask = dat; - } - (void)port; -} - -// [Native Mode] Immediate Message/Function -UINT16 IOINPCALL smpu98_i4(UINT port) { - - UINT16 ret = 0xffff; - - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { - if((smpu98.native_status & SMPU_STATUS_ISR) == 0){ - ret = smpu98.native_immbuf_r[smpu98.native_immbuf_r_pos]; - smpu98.native_immbuf_r_pos++; - if(smpu98.native_immbuf_r_pos >= smpu98.native_immbuf_r_len){ - smpu98.native_status |= SMPU_STATUS_ISR; - smpu98.native_immbuf_r_pos = smpu98.native_immbuf_r_len = 0; - //smpu98.native_status &= ~SMPU_STATUS_IRR; // XXX: ����ŗǂ��̂�������Ȃ� - } - smpu98.native_status &= ~SMPU_STATUS_RIR; - } -// TRACEOUT(("smpu98 inp %.4x %.2x", port, ret)); - return(ret); - } - (void)port; - return(0xffff); -} - -// [Native Mode] Sequence Message/Function -UINT16 IOINPCALL smpu98_i6(UINT port) { - - UINT16 ret = 0xffff; - - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { - if((smpu98.native_status & SMPU_STATUS_SSR) == 0){ - ret = smpu98.native_seqbuf_r[smpu98.native_seqbuf_r_pos]; - smpu98.native_seqbuf_r_pos++; - if(smpu98.native_seqbuf_r_pos >= smpu98.native_seqbuf_r_len){ - smpu98.native_status |= SMPU_STATUS_SSR; - smpu98.native_seqbuf_r_pos = smpu98.native_seqbuf_r_len = 0; - //smpu98.native_status &= ~SMPU_STATUS_SRR; // XXX: ����ŗǂ��̂�������Ȃ� - } - smpu98.native_status &= ~SMPU_STATUS_RSR; - } -// TRACEOUT(("smpu98 inp %.4x %.2x", port, ret)); - return(ret); - } - (void)port; - return(0xffff); -} - -// [Native Mode] Monitor -UINT16 IOINPCALL smpu98_i8(UINT port) { - - UINT16 ret = 0xffff; - - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { - if((smpu98.native_status & SMPU_STATUS_MSR) == 0){ - ret = smpu98.native_monbuf[smpu98.native_monbuf_pos]; - smpu98.native_monbuf_pos++; - if(smpu98.native_monbuf_pos >= smpu98.native_monbuf_len){ - smpu98.native_status |= SMPU_STATUS_MSR; - smpu98.native_monbuf_pos = smpu98.native_monbuf_len = 0; - } - smpu98.native_status &= ~SMPU_STATUS_RMR; - } - -// TRACEOUT(("smpu98 inp %.4x %.2x", port, ret)); - return(ret); - } - (void)port; - return(0xffff); -} - -// [Native Mode] Status -UINT16 IOINPCALL smpu98_ia(UINT port) { - - UINT16 ret; - - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { - ret = smpu98.native_status & ~(SMPU_INTMASK_ALL << 9) | (smpu98.native_intmask << 9); - //if ((smpu98.r.cnt == 0) && (smpu98.intreq == 0)) { - // ret |= MIDIIN_AVAIL; - //} -// TRACEOUT(("smpu98 inp %.4x %.2x", port, ret)); - return(ret); - } - (void)port; - return(0xffff); -} - -// 16-bit I/O func -void (IOOUTCALL *smpu98_io16outfunc[])(UINT port, UINT16 dat) = { - NULL, NULL, NULL, NULL, - smpu98_o4, NULL, smpu98_o6, NULL, - smpu98_o8, NULL, smpu98_oa, NULL, - NULL, NULL, NULL, NULL, -}; -UINT16 (IOINPCALL *smpu98_io16inpfunc[])(UINT port) = { - NULL, NULL, NULL, NULL, - smpu98_i4, NULL, smpu98_i6, NULL, - smpu98_i8, NULL, smpu98_ia, NULL, - NULL, NULL, NULL, NULL, -}; - -// ---- I/F - -void smpu98_construct(void) { - - cm_smpu98[0] = NULL; - cm_smpu98[1] = NULL; - smpu98.portBready = 0; -} - -void smpu98_destruct(void) { - - commng_destroy(cm_smpu98[0]); - commng_destroy(cm_smpu98[1]); - cm_smpu98[0] = NULL; - cm_smpu98[1] = NULL; - smpu98.portBready = 0; -} - -void smpu98_reset(const NP2CFG *pConfig) { - - commng_destroy(cm_smpu98[0]); - commng_destroy(cm_smpu98[1]); - cm_smpu98[0] = NULL; - cm_smpu98[1] = NULL; - - ZeroMemory(&smpu98, sizeof(smpu98)); - smpu98.portBready = 0; - smpu98.enable = (pConfig->smpuenable ? 1 : 0); - smpu98.muteB = (pConfig->smpumuteB ? 1 : 0); - smpu98.data = MPUMSG_ACK; - smpu98.port = 0xc0d0 | ((pConfig->smpuopt & 0xf0) << 6); - smpu98.irqnum = mpuirqnum[pConfig->smpuopt & 3]; - setdefaultcondition(); -// pic_registext(smpu98.irqnum); - - if (cm_smpu98[0] == NULL) { - cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, TRUE); - } - if (cm_smpu98[1] == NULL) { - cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, TRUE); - if(cm_smpu98[1]){ - smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); - } - } - - (void)pConfig; -} - -void smpu98_bind(void) { - - UINT port; - - if(smpu98.enable){ - smpu98_changeclock(); - - port = smpu98.port; - iocore_attachout(port, smpu98_o0); - iocore_attachinp(port, smpu98_i0); - port += 2; - iocore_attachout(port, smpu98_o2); - iocore_attachinp(port, smpu98_i2); - - // for S-MPU Native Mode (16-bit I/O�|�[�g�Ȃ̂�iocore.c�ŏ���) - //port += 2; - //iocore_attachout(port, smpu98_o4); - //iocore_attachinp(port, smpu98_i4); - //port += 2; - //iocore_attachout(port, smpu98_o6); - //iocore_attachinp(port, smpu98_i6); - //port += 2; - //iocore_attachout(port, smpu98_o8); - //iocore_attachinp(port, smpu98_i8); - //port += 2; - //iocore_attachout(port, smpu98_oa); - //iocore_attachinp(port, smpu98_ia); - - if(!mpu98.enable){ - // PC/AT MPU-401 - if(np2cfg.mpu_at){ - iocore_attachout(0x330, smpu98_o0); - iocore_attachinp(0x330, smpu98_i0); - iocore_attachout(0x331, smpu98_o2); - iocore_attachinp(0x331, smpu98_i2); - } - // PC-9801-118 - if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ - iocore_attachout(cs4231.port[10], smpu98_o0); - iocore_attachinp(cs4231.port[10], smpu98_i0); - iocore_attachout(cs4231.port[10]+1, smpu98_o2); - iocore_attachinp(cs4231.port[10]+1, smpu98_i2); - } - } - }else if(!mpu98.enable){ - // MPU-PC98II��S-MPU�������̎� - - // PC-9801-118 - if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ - iocore_attachout(cs4231.port[10], smpu98_o0); - iocore_attachinp(cs4231.port[10], smpu98_i0); - iocore_attachout(cs4231.port[10]+1, smpu98_o2); - iocore_attachinp(cs4231.port[10]+1, smpu98_i2); - // NULL�ō���Ă��� - cm_smpu98[0] = commng_create(COMCREATE_NULL, FALSE); - cm_smpu98[1] = commng_create(COMCREATE_NULL, FALSE); - } - } -} - -static void smpu98_callback_port(UINT8 dat, UINT8 port) { - if(smpu98.native_immread_phase[port] == 0){ - // 1byte�� - if(dat & 0x80){ - smpu98.native_immread_lastmsg[port] = dat; - smpu98.native_immread_portbuf[port] = ((UINT16)dat) << 8; - if(dat==0xf7){ - // F7(End of Exclusive) - smpu98_writeimm_r(smpu98.native_immread_portbuf[port]); - }else if(0xf0 <= dat && dat <= 0xff){ - // ���C���i���o�[������ - smpu98.native_immread_portbuf[port] |= (port==0 ? 0x00 : 0x10); - smpu98_writeimm_r(smpu98.native_immread_portbuf[port]); - }else{ - // ch�����C���i���o�[�ɕϊ� - smpu98.native_immread_portbuf[port] &= 0xf000; // ch������ - smpu98.native_immread_portbuf[port] |= (port==0 ? 0x00 : 0x10) | (dat & 0x0f); // ch�����C���i���o�[�ϊ� - smpu98_writeimm_r(smpu98.native_immread_portbuf[port]); - } - }else{ - UINT8 oldmsg = smpu98.native_immread_lastmsg[port]; // ���߂̃��b�Z�[�W�̑��� - smpu98.native_immread_portbuf[port] = ((UINT16)dat) << 8; - switch(oldmsg){ - case 0xc0: - case 0xd0: - // 1byte�����i2byte�ڂ�0�Łj - smpu98_writeimm_r(smpu98.native_immread_portbuf[port]); - break; - default: - // 2byte�ڂ�҂� - smpu98.native_immread_phase[port] = 1; - } - } - }else{ - // 2byte�� - smpu98.native_immread_portbuf[port] |= ((UINT16)dat); - smpu98_writeimm_r(smpu98.native_immread_portbuf[port]); - smpu98.native_immread_phase[port] = 0; - } -} - -void smpu98_callback(void) { - - UINT8 data; - - if (smpu98.mode == SMPUMODE_NATIVE) { - if (cm_smpu98[0]) { - while((SMPU_IMMBUF_R_LEN < smpu98.native_immbuf_r_len) && (cm_smpu98[0]->read(cm_smpu98[0], &data))) { - smpu98_callback_port(data, 0); - // XXX: 401�ɂ������Ă��� - if (!smpu98.r.cnt) { - smpu98_int(); - } - setrecvdata(data); - } - } - if (cm_smpu98[1]) { - while((SMPU_IMMBUF_R_LEN < smpu98.native_immbuf_r_len) && (cm_smpu98[1]->read(cm_smpu98[1], &data))) { - smpu98_callback_port(data, 0); - } - } - }else{ - if (cm_smpu98[0]) { - while((smpu98.r.cnt < MPU98_RECVBUFS) && - (cm_smpu98[0]->read(cm_smpu98[0], &data))) { - if (!smpu98.r.cnt) { - smpu98_int(); - } - setrecvdata(data); - } - } - } -} - -void smpu98_midipanic(void) { - - if (cm_smpu98[0]) { - cm_smpu98[0]->msg(cm_smpu98[0], COMMSG_MIDIRESET, 0); - } - if (cm_smpu98[1] && smpu98.portBready) { - cm_smpu98[1]->msg(cm_smpu98[1], COMMSG_MIDIRESET, 0); - } -} - -void smpu98_changeclock(void) { - - smpu98.xferclock = pccore.realclock / (31250 / 8); - - makeintclock(); -} - -#endif - + +// emulation Super MPU + +// �Q�l���� +// �ESuper MPU Developer's Kit for Windows �v���O���}�[�Y�E�K�C�h +// �Ehttps://gist.github.com/o-p-a/8b26f12c36073a3f1f6829d3ed974dd1#file-smpumsg-txt-L93 + +#include + +#if defined(SUPPORT_SMPU98) + +#include +#include +#include +#include +#include +#include +#include + +enum { + MIDI_STOP = 0xfc, + + MIDIIN_AVAIL = 0x80, + MIDIOUT_BUSY = 0x40, + + MPUMSG_TRACKDATAREQ = 0xf0, + MPUMSG_OVERFLOW = 0xf8, + MPUMSG_REQCOND = 0xf9, + MPUMSG_DATAEND = 0xfc, + MPUMSG_HCLK = 0xfd, + MPUMSG_ACK = 0xfe, + MPUMSG_SYS = 0xff, + + MIDITIMEOUTCLOCK = 3000, + MIDITIMEOUTCLOCK2 = 300 +}; + +enum { + MIDIE_STEP = 0x01, + MIDIE_EVENT = 0x02, + MIDIE_DATA = 0x04 +}; + +enum { + MPUCMDP_IDLE = 0x00, + MPUCMDP_STEP = 0x01, + MPUCMDP_CMD = 0x02, + MPUCMDP_REQ = 0x04, + MPUCMDP_FOLLOWBYTE = 0x08, + MPUCMDP_SHORT = 0x10, + MPUCMDP_LONG = 0x20, + MPUCMDP_INIT = 0x80 +}; + +enum { + MPUSYNCMODE_INT = 0x00, + MPUSYNCMODE_FSK = 0x01, + MPUSYNCMODE_MIDI = 0x02, + + MPUMETROMODE_ACC = 0x00, + MPUMETROMODE_OFF = 0x01, + MPUMETROMODE_ON = 0x02, + + MPUFLAG1_PLAY = 0x01, + MPUFLAG1_BENDERTOHOST = 0x08, + MPUFLAG1_THRU = 0x10, + MPUFLAG1_DATAINSTOP = 0x20, + MPUFLAG1_SENDME = 0x40, + MPUFLAG1_CONDUCTOR = 0x80, + + MPUFLAG2_RTAFF = 0x01, + MPUFLAG2_FSKRESO = 0x02, + MPUFLAG2_CLKTOHOST = 0x04, + MPUFLAG2_EXECLUTOHOST = 0x08, + MPUFLAG2_REFA = 0x10, + MPUFLAG2_REFB = 0x20, + MPUFLAG2_REFC = 0x40, + MPUFLAG2_REFD = 0x80 +}; + +enum { + SMPUMODE_401 = 0, + SMPUMODE_UART = 1, + SMPUMODE_NATIVE = 2, +}; + +// [Native Mode] status �̃r�b�g +enum { + SMPU_STATUS_ISR = 0x0001, // Imm data set ready + SMPU_STATUS_SSR = 0x0002, // Seq data set ready + SMPU_STATUS_MSR = 0x0004, // Mon data set ready + SMPU_STATUS_IRR = 0x0008, // Imm data read ready + SMPU_STATUS_SRR = 0x0010, // Seq data read ready + SMPU_STATUS_RSS = 0x0020, // Request sequence set + SMPU_STATUS_RIR = 0x0040, // Request IMM receive + SMPU_STATUS_RSR = 0x0080, // Request SEQ receive + SMPU_STATUS_RMR = 0x0100, // Request MON receive + SMPU_STATUS_IM0 = 0x0200, // Int mask monitor 0001 + SMPU_STATUS_IM1 = 0x0400, // Int mask monitor 0002 + SMPU_STATUS_IM2 = 0x0800, // Int mask monitor 0004 + SMPU_STATUS_IM3 = 0x1000, // Int mask monitor 0008 + SMPU_STATUS_IM4 = 0x2000, // Int mask monitor 0010 +}; + +// [Native Mode] Int mask �̃r�b�g 0�ŋ֎~ 1�ŋ��� +enum { + SMPU_INTMASK_RSS = 0x0001, // RSS ���荞�� + SMPU_INTMASK_RIR = 0x0002, // RIR ���荞�� + SMPU_INTMASK_RSR = 0x0004, // RSR ���荞�� + SMPU_INTMASK_RMR = 0x0008, // RMR ���荞�� + SMPU_INTMASK_401 = 0x0010, // 401 ���荞�� + + SMPU_INTMASK_ALL = 0x001f, +}; + +#define SMPU_PORTS 2 + + _SMPU98 smpu98; + COMMNG cm_smpu98[SMPU_PORTS]; // [0]=A, [1]=B + + +static const UINT8 mpuirqnum[4] = {3, 5, 6, 12}; + +static const UINT8 shortmsgleng[0x10] = { + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 2, 2, 3, 1}; + +static const UINT8 hclk_step1[4][4] = {{0, 0, 0, 0}, {1, 0, 0, 0}, + {1, 0, 1, 0}, {1, 1, 1, 0}}; + +// XXX: 根拠なし とりあえず大きめの値にしておく +#define SMPU98_WRITEBUFFER 2048 +static int smpu98_writecounter = 0; + +static void makeintclock(void) { + + UINT32 l; + UINT curtempo; + + l = smpu98.tempo * 2 * smpu98.reltempo / 0x40; + if (l < 5 * 2) { + l = 5 * 2; + } + curtempo = l >> 1; + if (curtempo > 250) { + curtempo = 250; + } + smpu98.curtempo = curtempo; + if (!(smpu98.flag2 & MPUFLAG2_FSKRESO)) { + l *= smpu98.inttimebase; // *12 + } + smpu98.stepclock = (pccore.realclock * 5 / l); // /12 +} + +static void sethclk(REG8 data) { + + REG8 quarter; + int i; + + quarter = data >> 2; + if (!quarter) { + quarter = 64; + } + for (i=0; i<4; i++) { + smpu98.hclk_step[i] = quarter + hclk_step1[data & 3][i]; + } + smpu98.hclk_rem = 0; +} + +static void setdefaultcondition(void) { + + smpu98.recvevent = 0; + smpu98.remainstep = 0; + smpu98.intphase = 0; + smpu98.intreq = 0; + + ZeroMemory(&smpu98.cmd, sizeof(smpu98.cmd)); + ZeroMemory(smpu98.tr, sizeof(smpu98.tr)); + ZeroMemory(&smpu98.cond, sizeof(smpu98.cond)); + + smpu98.syncmode = MPUSYNCMODE_INT; + smpu98.metromode = MPUMETROMODE_OFF; + smpu98.flag1 = MPUFLAG1_THRU | MPUFLAG1_SENDME; + smpu98.flag2 = MPUFLAG2_RTAFF; + + smpu98.inttimebase = 120 / 24; + smpu98.tempo = 100; + smpu98.reltempo = 0x40; + makeintclock(); + smpu98.midipermetero = 12; + smpu98.meteropermeas = 8; + sethclk(240); + smpu98.acttr = 0x00; + smpu98.sendplaycnt = 0; + smpu98.accch = 0xffff; + + // for S-MPU + smpu98.native_status = SMPU_STATUS_ISR|SMPU_STATUS_SSR|SMPU_STATUS_MSR; + smpu98.native_intmask = SMPU_INTMASK_ALL; + smpu98.mode = SMPUMODE_NATIVE; +} + +static void setrecvdata(REG8 data) { + + MPURECV *r; + + r = &smpu98.r; + if (r->cnt < MPU98_RECVBUFS) { + r->buf[(r->pos + r->cnt) & (MPU98_RECVBUFS - 1)] = data; + r->cnt++; + } +} + +// ------- for S-MPU Native Mode +static void smpu98_writeimm_r(UINT16 dat) { + if(smpu98.native_immbuf_r_len < SMPU_IMMBUF_R_LEN){ + // IMM READ�o�b�t�@�ɏ������ݏ��� + smpu98.native_immbuf_r[smpu98.native_immbuf_r_len] = dat; + smpu98.native_immbuf_r_len++; + if(smpu98.native_immbuf_r_len >= SMPU_IMMBUF_R_LEN){ + //smpu98.native_status |= SMPU_STATUS_IRR; // XXX: ����ŗǂ��̂�������Ȃ� + } + if(smpu98.native_status & SMPU_STATUS_ISR){ + smpu98.native_status &= ~SMPU_STATUS_ISR; + smpu98.native_status |= SMPU_STATUS_RIR; + } + } +} + +static void sendmpushortmsg(const UINT8 *dat, UINT count) { + + UINT i; + +#if 0 + if (!(smpu98.flag1 & MPUFLAG1_BENDERTOHOST)) { + switch(dat[0] >> 4) { + case 0x0a: + case 0x0d: + case 0x0e: + return; + + case 0x0b: + if (dat[1] < 0x40) { + return; + } + break; + } + } +#endif + if (smpu98.mode == SMPUMODE_NATIVE) { + for (i=0; iwrite(cm_smpu98[smpu98.native_portnum], dat[i]); + } + }else{ + for (i=0; iwrite(cm_smpu98[0], dat[i]); + } + if(smpu98.portBready && !smpu98.muteB) { + for (i=0; iwrite(cm_smpu98[1], dat[i]); + } + } + } +} + +static void sendmpulongmsg(const UINT8 *dat, UINT count) { + + UINT i; + + if (smpu98.mode == SMPUMODE_NATIVE) { + for (i=0; iwrite(cm_smpu98[smpu98.native_portnum], dat[i]); + } + }else{ + for (i=0; iwrite(cm_smpu98[0], dat[i]); + } + if(smpu98.portBready && !smpu98.muteB) { + for (i=0; iwrite(cm_smpu98[1], dat[i]); + } + } + } +} + +static void sendmpureset(void) { + + UINT i; + UINT8 sMessage[3]; + + if (smpu98.mode == SMPUMODE_NATIVE) { + UINT8 oldlinenum = smpu98.native_portnum; + for (i=0; i<0x10; i++) { + sMessage[0] = (UINT8)(0xb0 + i); + sMessage[1] = 0x7b; + sMessage[2] = 0x00; + smpu98.native_portnum = 0; + sendmpushortmsg(sMessage, 3); + smpu98.native_portnum = 1; + sendmpushortmsg(sMessage, 3); + } + smpu98.native_portnum = oldlinenum; + }else{ + for (i=0; i<0x10; i++) { + sMessage[0] = (UINT8)(0xb0 + i); + sMessage[1] = 0x7b; + sMessage[2] = 0x00; + sendmpushortmsg(sMessage, 3); + } + } +} + +static void smpu98_int(void) { + + TRACEOUT(("int!")); + pic_setirq(smpu98.irqnum); + + //if(!mpu98.enable){ + // // Sound Blaster 16 + // if(g_nSoundID == SOUNDID_SB16 || g_nSoundID == SOUNDID_PC_9801_86_SB16 || g_nSoundID == SOUNDID_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ + // pic_setirq(g_sb16.dmairq); + // } + // // PC-9801-118 + // if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ + // pic_setirq(10); + // } + // // WaveStar + // if(g_nSoundID == SOUNDID_WAVESTAR){ + // pic_setirq(10); + // } + //} +} + +static void tr_step(void) { + + int i; + REG8 bit; + + if (smpu98.flag1 & MPUFLAG1_CONDUCTOR) { + if (smpu98.cond.step) { + smpu98.cond.step--; + } + } + for (i=0, bit=1; i<8; bit<<=1, i++) { + if (smpu98.acttr & bit) { + if (smpu98.tr[i].step) { + smpu98.tr[i].step--; + } + } + } +} + +static BOOL tr_nextsearch(void) { + + int i; + REG8 bit; + +tr_nextsearch_more: + if (smpu98.intphase == 1) { + if (smpu98.flag1 & MPUFLAG1_CONDUCTOR) { + if (!smpu98.cond.step) { + smpu98.intreq = MPUMSG_REQCOND; + smpu98.cond.phase |= MPUCMDP_STEP | MPUCMDP_CMD; + smpu98_int(); + return(TRUE); + } + } + smpu98.intphase = 2; + } + if (smpu98.intphase) { + bit = 1 << (smpu98.intphase - 2); + do { + if (smpu98.acttr & bit) { + MPUTR *tr; + tr = smpu98.tr + (smpu98.intphase - 2); + if (!tr->step) { + if ((tr->datas) && (tr->remain == 0)) { + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (tr->data[0] == MIDI_STOP) { + tr->datas = 0; + cm_smpu98[0]->write(cm_smpu98[0], MIDI_STOP); + if(smpu98.portBready && !smpu98.muteB) cm_smpu98[1]->write(cm_smpu98[1], MIDI_STOP); + setrecvdata(MIDI_STOP); + smpu98_int(); + return(TRUE); + } + for (i=0; idatas; i++) { + cm_smpu98[0]->write(cm_smpu98[0], tr->data[i]); + if(smpu98.portBready && !smpu98.muteB) cm_smpu98[1]->write(cm_smpu98[1], tr->data[i]); + } + tr->datas = 0; + } + smpu98.intreq = 0xf0 + (smpu98.intphase - 2); + smpu98.recvevent |= MIDIE_STEP; + smpu98_int(); + return(TRUE); + } + } + bit <<= 1; + smpu98.intphase++; + } while(smpu98.intphase < 10); + smpu98.intphase = 0; + } + smpu98.remainstep--; + if (smpu98.remainstep) { + tr_step(); + smpu98.intphase = 1; + goto tr_nextsearch_more; + } + return(FALSE); +} + +void smpu98_midiint(NEVENTITEM item) { + + nevent_set(NEVENT_MIDIINT, smpu98.stepclock, smpu98_midiint, NEVENT_RELATIVE); + + if (smpu98.flag2 & MPUFLAG2_CLKTOHOST) { + if (!smpu98.hclk_rem) { + smpu98.hclk_rem = smpu98.hclk_step[smpu98.hclk_cnt & 3]; + smpu98.hclk_cnt++; + } + smpu98.hclk_rem--; + if (!smpu98.hclk_rem) { + setrecvdata(MPUMSG_HCLK); + smpu98_int(); + } + } + if (smpu98.flag1 & MPUFLAG1_PLAY) { + if (!smpu98.remainstep++) { + tr_step(); + smpu98.intphase = 1; + tr_nextsearch(); + } + } + (void)item; +} + +void smpu98_midiwaitout(NEVENTITEM item) { + +// TRACE_("midi ready", 0); + if (smpu98_writecounter > 0) { + smpu98_writecounter--; + } + if (smpu98_writecounter < SMPU98_WRITEBUFFER) { + // カウンタがバッファサイズより小さいならBUSY解除 + smpu98.status &= ~MIDIOUT_BUSY; + } + if (smpu98_writecounter > 0) { + // カウンタが0になるまで再登録 + nevent_set(NEVENT_MIDIWAIT, smpu98.xferclock, smpu98_midiwaitout, NEVENT_RELATIVE); + } + (void)item; +} + +static void midiwait(SINT32 waitclock) { + + // 転送が多すぎてバッファを溢れるようならBUSYに変える + smpu98_writecounter += waitclock / smpu98.xferclock; + if (smpu98_writecounter > SMPU98_WRITEBUFFER) { + smpu98.status |= MIDIOUT_BUSY; + } + if (!nevent_iswork(NEVENT_MIDIWAIT)) { + nevent_set(NEVENT_MIDIWAIT, smpu98.xferclock, smpu98_midiwaitout, NEVENT_ABSOLUTE); + } +} + +static void midicmdwait(SINT32 waitclock) { + + // 一定時間強制BUSY + smpu98_writecounter++; + smpu98.status |= MIDIOUT_BUSY; + if (!nevent_iswork(NEVENT_MIDIWAIT)) { + nevent_set(NEVENT_MIDIWAIT, smpu98.xferclock, smpu98_midiwaitout, NEVENT_ABSOLUTE); + } +} + + +// ---- + +typedef REG8 (*MPUCMDFN)(REG8 cmd); + +static REG8 mpucmd_xx(REG8 cmd) { + +// TRACEOUT(("unknown MPU commands: %.2x", cmd)); + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_md(REG8 cmd) { // 00-2F: Mode + + TRACEOUT(("mpucmd_md %.2x", cmd)); +#if 0 + switch((cmd >> 0) & 3) { + case 1: // MIDI Stop + case 2: // MIDI Start + case 3: // MIDI Cont + break; + } +#endif + switch((cmd >> 2) & 3) { + case 1: // Stop Play + smpu98.flag1 &= ~MPUFLAG1_PLAY; + smpu98.recvevent = 0; + smpu98.intphase = 0; + smpu98.intreq = 0; + ZeroMemory(smpu98.tr, sizeof(smpu98.tr)); + ZeroMemory(&smpu98.cond, sizeof(smpu98.cond)); + if (!(smpu98.flag2 & MPUFLAG2_CLKTOHOST)) { + nevent_reset(NEVENT_MIDIINT); + } + break; + + case 2: // Start Play + smpu98.flag1 |= MPUFLAG1_PLAY; + smpu98.remainstep = 0; + if (!nevent_iswork(NEVENT_MIDIINT)) { + nevent_set(NEVENT_MIDIINT, smpu98.stepclock, + smpu98_midiint, NEVENT_ABSOLUTE); + } + break; + } +#if 0 + switch((cmd >> 4) & 3) { + case 1: // Stop Rec + case 2: // Rec + break; + } +#endif + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_3f(REG8 cmd) { // 3F: UART + + smpu98.mode = SMPUMODE_UART; + sendmpureset(); + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_sr(REG8 cmd) { // 40-7F: Set ch of Ref table + + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_sm(REG8 cmd) { // 80-82: Clock Sync/Mode + + smpu98.syncmode = cmd - 0x80; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_mm(REG8 cmd) { // 83-85: Metronome + + smpu98.metromode = cmd - 0x83; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_8x(REG8 cmd) { // 86-8F: Flag1 + + REG8 bit; + + bit = 1 << ((cmd >> 1) & 7); + if (cmd & 1) { + smpu98.flag1 |= bit; + } + else { + smpu98.flag1 &= ~bit; + } +#if 0 + switch(cmd & 0x0f) { + case 0x06: // 86: Bender to Host / off + case 0x07: // 87: Bender to Host / on + case 0x08: // 88: THRU / off + case 0x09: // 89: THRU / on + case 0x0a: // 8A: Data in Stop / off + case 0x0b: // 8B: Data in Stop / on + case 0x0c: // 8C: Send Me / off + case 0x0d: // 8D: Send Me / on + case 0x0e: // 8E: Conductor / off + case 0x0f: // 8F: Conductor / on + break; + } +#endif + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_9x(REG8 cmd) { // 90-9F: Flag2 + + REG8 bit; + + bit = 1 << ((cmd >> 1) & 7); + if (cmd & 1) { + smpu98.flag2 |= bit; + } + else { + smpu98.flag2 &= ~bit; + } + switch(cmd & 0x0f) { +#if 0 + case 0x00: // 90: RT Aff / off + case 0x01: // 91: RT Aff / on + case 0x02: // 92: FSK Reso / INT + case 0x03: // 93: FSK Reso / 24 + break; +#endif + + case 0x04: // 94: CLK to Host / off + if (!(smpu98.flag1 & MPUFLAG1_PLAY)) { + nevent_reset(NEVENT_MIDIINT); + } + break; + + case 0x05: // 95: CLK to Host / on + if (!nevent_iswork(NEVENT_MIDIINT)) { + nevent_set(NEVENT_MIDIINT, smpu98.stepclock, + smpu98_midiint, NEVENT_ABSOLUTE); + } + break; + +#if 0 + case 0x06: // 96: Exclu to Host / off + case 0x07: // 97: Exclu to Host / on + case 0x08: // 98: Ref A / off + case 0x09: // 99: Ref A / on + case 0x0a: // 9A: Ref B / off + case 0x0b: // 9B: Ref B / on + case 0x0c: // 9C: Ref C / off + case 0x0d: // 9D: Ref C / on + case 0x0e: // 9E: Ref D / off + case 0x0f: // 9F: Ref D / on + break; +#endif + } + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_rq(REG8 cmd) { // A0-AF: Req + + (void)cmd; + return(MPUCMDP_REQ); +} + +static REG8 mpucmd_b1(REG8 cmd) { // B1: Clear Rel + + smpu98.reltempo = 0x40; + makeintclock(); + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_b8(REG8 cmd) { // B8: Clear PC + + int i; + + for (i=0; i<8; i++) { + smpu98.tr[i].step = 0; + } + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_tb(REG8 cmd) { // C2-C8: .INT Time Base + + smpu98.inttimebase = cmd & 0x0f; + makeintclock(); + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_ws(REG8 cmd) { // D0-D7: Want to Send Data + + (void)cmd; + return(MPUCMDP_SHORT | MPUCMDP_INIT); +} + +static REG8 mpucmd_df(REG8 cmd) { // DF: WSD System + + (void)cmd; + return(MPUCMDP_LONG | MPUCMDP_INIT); +} + +static REG8 mpucmd_fo(REG8 cmd) { // E0-EF: Following Byte + + (void)cmd; + return(MPUCMDP_FOLLOWBYTE); +} + +static REG8 mpucmd_fe(REG8 cmd) { // FE: Switch to Native Mode + + smpu98.mode = SMPUMODE_NATIVE; + sendmpureset(); + (void)cmd; + return(MPUCMDP_IDLE); +} + +static REG8 mpucmd_ff(REG8 cmd) { // FF: Reset + + sendmpureset(); + nevent_reset(NEVENT_MIDIINT); + setdefaultcondition(); + smpu98.mode = SMPUMODE_401; + (void)cmd; + return(MPUCMDP_IDLE); +} + +static const MPUCMDFN mpucmds[0x100] = { + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 00 + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 10 + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, // 20 + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_md, mpucmd_md, mpucmd_md, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, // 30 + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_3f, + + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 40 + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 50 + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 60 + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, // 70 + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + mpucmd_sr, mpucmd_sr, mpucmd_sr, mpucmd_sr, + + mpucmd_sm, mpucmd_sm, mpucmd_sm, mpucmd_mm, // 80 + mpucmd_mm, mpucmd_mm, mpucmd_8x, mpucmd_8x, + mpucmd_8x, mpucmd_8x, mpucmd_8x, mpucmd_8x, + mpucmd_8x, mpucmd_8x, mpucmd_8x, mpucmd_8x, + + mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, // 90 + mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, + mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, + mpucmd_9x, mpucmd_9x, mpucmd_9x, mpucmd_9x, + + mpucmd_rq, mpucmd_rq, mpucmd_rq, mpucmd_rq, // a0 + mpucmd_rq, mpucmd_rq, mpucmd_rq, mpucmd_rq, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_rq, + mpucmd_rq, mpucmd_rq, mpucmd_xx, mpucmd_rq, + + mpucmd_xx, mpucmd_b1, mpucmd_xx, mpucmd_xx, // b0 + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_b8, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + + mpucmd_xx, mpucmd_xx, mpucmd_tb, mpucmd_tb, // c0 + mpucmd_tb, mpucmd_tb, mpucmd_tb, mpucmd_tb, + mpucmd_tb, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + + mpucmd_ws, mpucmd_ws, mpucmd_ws, mpucmd_ws, // d0 + mpucmd_ws, mpucmd_ws, mpucmd_ws, mpucmd_ws, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_df, + + mpucmd_fo, mpucmd_fo, mpucmd_fo, mpucmd_xx, // e0 + mpucmd_fo, mpucmd_xx, mpucmd_fo, mpucmd_fo, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_fo, mpucmd_fo, mpucmd_fo, mpucmd_fo, + + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, // f0 + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_xx, mpucmd_xx, + mpucmd_xx, mpucmd_xx, mpucmd_fe, mpucmd_ff}; + + +static void reqmpucmdgroupd(REG8 cmd) { + + switch(cmd) { + case 0xa0: // A0: Req Play Cnt Tr1 + case 0xa1: // A1: Req Play Cnt Tr2 + case 0xa2: // A2: Req Play Cnt Tr3 + case 0xa3: // A3: Req Play Cnt Tr4 + case 0xa4: // A4: Req Play Cnt Tr5 + case 0xa5: // A5: Req Play Cnt Tr6 + case 0xa6: // A6: Req Play Cnt Tr7 + case 0xa7: // A7: Req Play Cnt Tr8 + setrecvdata(smpu98.tr[cmd - 0xa0].step); + break; + + case 0xab: // AB: Read & Clear RC + setrecvdata(0); + break; + + case 0xac: // AC: Req Major Version + setrecvdata(0x20); + break; + + case 0xad: // AD: Req Minor Version + setrecvdata(0); + break; + + case 0xaf: // AF: Req Tempo + setrecvdata(smpu98.curtempo); + break; + } +} + +static void setmpucmdgroupe(REG8 cmd, REG8 data) { + + switch(cmd) { + case 0xe0: // Set Tempo + smpu98.tempo = data; + smpu98.reltempo = 0x40; + makeintclock(); + break; + + case 0xe1: // Rel Tempo + smpu98.reltempo = data; + makeintclock(); + break; + + case 0xe2: // Graduation + break; + + case 0xe4: // MIDI/Metro + smpu98.midipermetero = data; + break; + + case 0xe6: // Metro/Meas + smpu98.meteropermeas = data; + break; + + case 0xe7: // INTx4/H.CLK + sethclk(data); + break; + + case 0xec: // Act Tr + smpu98.acttr = data; + break; + + case 0xed: // Send Play CNT + smpu98.sendplaycnt = data; + break; + + case 0xee: // Acc CH 1-8 + smpu98.accch = (smpu98.accch & 0xff00) | data; + break; + + case 0xef: // Acc CH 9-16 + smpu98.accch = (smpu98.accch & 0x00ff) | (data << 8); + break; + } +} + +static BOOL sendmpumsg(MPUCMDS *cmd, REG8 data) { + + if (cmd->phase & MPUCMDP_SHORT) { + if (cmd->phase & MPUCMDP_INIT) { + cmd->phase &= ~MPUCMDP_INIT; + if (!(data & 0x80)) { + cmd->data[0] = cmd->rstat; + cmd->datapos = 1; + cmd->datacnt = shortmsgleng[cmd->rstat >> 4]; + } + else { + if ((data & 0xf0) != 0xf0) { + cmd->rstat = data; + } + cmd->datapos = 0; + cmd->datacnt = shortmsgleng[data >> 4]; + } + } + cmd->data[cmd->datapos] = data; + cmd->datapos++; + if (cmd->datapos >= cmd->datacnt) { + sendmpushortmsg(cmd->data, cmd->datacnt); + cmd->phase &= ~MPUCMDP_SHORT; + } + return(TRUE); + } + else if (cmd->phase & MPUCMDP_LONG) { + if (cmd->phase & MPUCMDP_INIT) { + cmd->phase &= ~MPUCMDP_INIT; + cmd->datapos = 0; + cmd->datacnt = sizeof(cmd->data); + } + if (cmd->datapos < cmd->datacnt) { + cmd->data[cmd->datapos] = data; + cmd->datapos++; + } + switch(cmd->data[0]) { + case 0xf0: + if (data == 0xf7) { + cmd->phase &= ~MPUCMDP_LONG; + sendmpulongmsg(cmd->data, cmd->datapos); + } + break; + + case 0xf2: + case 0xf3: + if (cmd->datapos >= 3) { + cmd->phase &= ~MPUCMDP_LONG; + } + break; + + case 0xf6: + default: + cmd->phase &= ~MPUCMDP_LONG; + break; + } + return(TRUE); + } + return(FALSE); +} + +static BRESULT sendmpucmd(MPUCMDS *cmd, REG8 data) { + + if (cmd->phase & MPUCMDP_FOLLOWBYTE) { + cmd->phase &= ~MPUCMDP_FOLLOWBYTE; + setmpucmdgroupe(cmd->cmd, data); + return(SUCCESS); + } + else if (cmd->phase & (MPUCMDP_SHORT | MPUCMDP_LONG)) { + sendmpumsg(cmd, data); + return(SUCCESS); + } + else { + cmd->phase = 0; + return(FAILURE); + } +} + +static BRESULT sendmpucond(MPUCMDS *cmd, REG8 data) { + + if (cmd->phase & (MPUCMDP_SHORT | MPUCMDP_LONG)) { +// if (smpu98.intreq == 0xf9) { +// smpu98.intreq = 0; +// } + sendmpumsg(cmd, data); + return(SUCCESS); + } + else if (cmd->phase & MPUCMDP_STEP) { + if (data < 0xf0) { + cmd->step = data; + cmd->phase &= ~MPUCMDP_STEP; + } + else { + cmd->step = 0xf0; + cmd->phase &= ~(MPUCMDP_STEP | MPUCMDP_CMD); + } + return(SUCCESS); + } + else if (cmd->phase & MPUCMDP_CMD) { + cmd->phase &= ~MPUCMDP_CMD; + cmd->cmd = data; + if (data < 0xf0) { + REG8 phase; + phase = (*mpucmds[data])(data); + if (phase & MPUCMDP_REQ) { + phase &= ~MPUCMDP_REQ; + reqmpucmdgroupd(data); + } + cmd->phase = phase; + if (phase & MPUCMDP_FOLLOWBYTE) { + return(SUCCESS); + } + } + else { + cmd->phase = 0; + if (data == MIDI_STOP) { + cm_smpu98[0]->write(cm_smpu98[0], MIDI_STOP); + if(smpu98.portBready && !smpu98.muteB) cm_smpu98[1]->write(cm_smpu98[1], MIDI_STOP); + setrecvdata(MIDI_STOP); + smpu98_int(); + } + } + } + else if (cmd->phase & MPUCMDP_FOLLOWBYTE) { + cmd->phase &= ~MPUCMDP_FOLLOWBYTE; + setmpucmdgroupe(cmd->cmd, data); + } + else { + cmd->phase = 0; + return(FAILURE); + } + + tr_nextsearch(); + return(SUCCESS); +} + +static void sendmpudata(REG8 data) { + + if (smpu98.cmd.phase) { + sendmpucmd(&smpu98.cmd, data); + return; + } + + if (smpu98.recvevent & MIDIE_STEP) { + MPUTR *tr; + smpu98.recvevent ^= MIDIE_STEP; + tr = smpu98.tr + (smpu98.intphase - 2); + tr->datas = 0; + if (data < 0xf0) { + smpu98.recvevent ^= MIDIE_EVENT; + tr->step = data; + } + else { + tr->step = 0xf0; + tr->remain = 0; + tr->datas = 0; + tr_nextsearch(); + } + return; + } + if (smpu98.recvevent & MIDIE_EVENT) { + MPUTR *tr; + smpu98.recvevent ^= MIDIE_EVENT; + smpu98.recvevent |= MIDIE_DATA; + tr = smpu98.tr + (smpu98.intphase - 2); + switch(data & 0xf0) { + case 0xc0: + case 0xd0: + tr->remain = 2; + tr->rstat = data; + break; + + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: + case 0xe0: + tr->remain = 3; + tr->rstat = data; + break; + + case 0xf0: + tr->remain = 1; + break; + + default: + tr->data[0] = tr->rstat; + tr->datas = 1; + tr->remain = 2; + if ((tr->rstat & 0xe0) == 0xc0) { + tr->remain--; + } + break; + } + } + if (smpu98.recvevent & MIDIE_DATA) { + MPUTR *tr; + tr = smpu98.tr + (smpu98.intphase - 2); + if (tr->remain) { + tr->data[tr->datas] = data; + tr->datas++; + tr->remain--; + } + if (!tr->remain) { + smpu98.recvevent ^= MIDIE_DATA; + tr_nextsearch(); + } + return; + } + +#if 1 + if (smpu98.cond.phase) +#else + if (smpu98.cond.phase & (MPUCMDP_CMD | MPUCMDP_FOLLOWBYTE)) +#endif + { + sendmpucond(&smpu98.cond, data); + return; + } +} + +// [401 Mode] Data +void IOOUTCALL smpu98_o0(UINT port, REG8 dat) { + + UINT sent; + +TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (cm_smpu98[0]->connect != COMCONNECT_OFF) { + if (smpu98.mode == SMPUMODE_UART) { + sent = cm_smpu98[0]->write(cm_smpu98[0], (UINT8)dat); + if(smpu98.portBready && !smpu98.muteB) cm_smpu98[1]->write(cm_smpu98[1], (UINT8)dat); + } + else if(smpu98.mode == SMPUMODE_NATIVE){ + sent = 0; + } + else { +// TRACEOUT(("send data->%.2x", dat)); + sendmpudata(dat); + sent = 1; + } + if (sent) { + midiwait(smpu98.xferclock * sent); + } + } + (void)port; +} + +// [401 Mode] Command +void IOOUTCALL smpu98_o2(UINT port, REG8 dat) { + +TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (cm_smpu98[0]->connect != COMCONNECT_OFF) { + if (smpu98.mode != SMPUMODE_UART) { + REG8 phase; +// TRACEOUT(("send cmd->%.2x", dat)); + smpu98.cmd.cmd = dat; + phase = (*mpucmds[dat])(dat); + setrecvdata(MPUMSG_ACK); + smpu98_int(); + if (phase & MPUCMDP_REQ) { + phase &= ~MPUCMDP_REQ; + reqmpucmdgroupd(dat); + } + smpu98.cmd.phase = phase; + } + else { + if (dat == 0xff) { + smpu98.mode = SMPUMODE_401; + setrecvdata(MPUMSG_ACK); + } + } + midicmdwait(pccore.realclock / 10000); + } + (void)port; +} + +// [401 Mode] Data +REG8 IOINPCALL smpu98_i0(UINT port) { + + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (cm_smpu98[0]->connect != COMCONNECT_OFF) { + if (smpu98.r.cnt) { + smpu98.r.cnt--; +#if 0 + if (smpu98.r.cnt) { + smpu98_int(); + } + else { + pic_resetirq(smpu98.irqnum); + } +#endif + smpu98.data = smpu98.r.buf[smpu98.r.pos]; + smpu98.r.pos = (smpu98.r.pos + 1) & (MPU98_RECVBUFS - 1); + } + else if (smpu98.intreq) { + smpu98.data = smpu98.intreq; + smpu98.intreq = 0; + } + if ((smpu98.r.cnt) || (smpu98.intreq)) { + smpu98_int(); + } + else { + pic_resetirq(smpu98.irqnum); + } + +// TRACEOUT(("recv data->%.2x", smpu98.data)); +TRACEOUT(("smpu98 inp %.4x %.2x", port, smpu98.data)); + return(smpu98.data); + } + (void)port; + return(0xff); +} + +// [401 Mode] Status +REG8 IOINPCALL smpu98_i2(UINT port) { + + REG8 ret; + + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if ((cm_smpu98[0]->connect != COMCONNECT_OFF) || g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16) { + + ret = smpu98.status; + if ((smpu98.r.cnt == 0) && (smpu98.intreq == 0)) { + ret |= MIDIIN_AVAIL; + } +// TRACEOUT(("smpu98 inp %.4x %.2x", port, ret)); + return(ret); + } + (void)port; + return(0xff); +} + +// ------- for S-MPU Native Mode + +// [Native Mode] Immediate Message/Function +void IOOUTCALL smpu98_o4(UINT port, UINT16 dat) { + +TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { + if((smpu98.native_status & SMPU_STATUS_IRR) == 0){ + if(smpu98.native_immbuf_w_len < SMPU_IMMBUF_W_LEN){ + // IMM�������ݏ��� + smpu98.native_immbuf_w[smpu98.native_immbuf_w_len] = dat; + smpu98.native_immbuf_w_len++; + if(smpu98.native_immbuf_w_len >= SMPU_IMMBUF_W_LEN){ + //smpu98.native_status |= SMPU_STATUS_IRR; // XXX: ����ŗǂ��̂�������Ȃ� + } + } + } + } + (void)port; +} + +// [Native Mode] Sequence Message/Function +void IOOUTCALL smpu98_o6(UINT port, UINT16 dat) { + +TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { + if((smpu98.native_status & SMPU_STATUS_SRR) == 0){ + if(smpu98.native_seqbuf_w_len < SMPU_SEQBUF_W_LEN){ + // SEQ�������ݏ��� + smpu98.native_seqbuf_w[smpu98.native_seqbuf_w_len] = dat; + smpu98.native_seqbuf_w_len++; + if(smpu98.native_seqbuf_w_len >= SMPU_SEQBUF_W_LEN){ + //smpu98.native_status |= SMPU_STATUS_SRR; // XXX: ����ŗǂ��̂�������Ȃ� + } + } + } + } + (void)port; +} + +// [Native Mode] Interrupt to Super MPU +void IOOUTCALL smpu98_o8(UINT port, UINT16 dat) { + + UINT16 sent = 0; + +TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { + UINT8 *buf = smpu98.native_tmpbuf; + switch(dat){ + case 1: + // IMM���� + while(smpu98.native_immbuf_w_pos < smpu98.native_immbuf_w_len){ + UINT16 w1 = smpu98.native_immbuf_w[smpu98.native_immbuf_w_pos]; + UINT8 msg = ((w1 >> 8) & 0xff); + if(msg & 0x80){ + smpu98.native_lastmsg = msg; + if(msg==0xf7){ + // F7(End of Exclusive)�������� + sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 >> 8) & 0xff); + smpu98.native_lastmsg = smpu98.native_runningmsg; + }else if(msg==0xef){ + // Continue Exclusive + smpu98.native_linenum = (w1 & 0xff); + smpu98.native_portnum = (smpu98.native_linenum > 0xf ? 1 : 0); + smpu98.native_lastmsg = 0xf0; + }else if(0xf0 <= msg && msg <= 0xff){ + // ���C���i���o�[������đ��� + smpu98.native_linenum = (w1 & 0xff); + smpu98.native_portnum = (smpu98.native_linenum > 0xf ? 1 : 0); + sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 >> 8) & 0xff); + }else if(msg & 0x0f){ + // �Ƃ肠�������� + if(smpu98.native_lastmsg==0xf0){ + // �^�C���X�^���v�Ƃ����Ԃɋ��߂�炵���BContinue Exclusive�������Ă�����Exclusive���M�ĊJ + } + }else{ + // ch�����đ��� + smpu98.native_linenum = (w1 & 0xff); + smpu98.native_portnum = (smpu98.native_linenum > 0xf ? 1 : 0); + sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 >> 8) & 0xf0 | (smpu98.native_linenum & 0xf)); + smpu98.native_runningmsg = msg; + } + }else{ + msg = smpu98.native_lastmsg; // ���߂̃��b�Z�[�W�̑��� + if(!(msg==0xf7) && !(0xf0 <= msg && msg <= 0xff || msg==0xef) && (msg & 0x0f)){ + // �Ƃ肠�������� + }else{ + switch(msg){ + case 0xc0: + case 0xd0: + // 1byte�ڂ������� + sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 >> 8) & 0xff); + break; + default: + // ���̂܂ܑ��� + sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 >> 8) & 0xff); + sent += cm_smpu98[smpu98.native_portnum]->write(cm_smpu98[smpu98.native_portnum], (w1 ) & 0xff); + if((w1 & 0xff) == 0xf7){ + smpu98.native_lastmsg = smpu98.native_runningmsg; + } + } + } + } + smpu98.native_immbuf_w_pos++; + } + smpu98.native_immbuf_w_pos = smpu98.native_immbuf_w_len = 0; + break; + case 2: + // TODO: SEQ���� + smpu98.native_seqbuf_w_pos = smpu98.native_seqbuf_w_len = 0; + break; + } + if (sent) { + //midiwait(smpu98.xferclock * sent); + } + } + (void)port; +} + +// [Native Mode] Interrupt Mask +void IOOUTCALL smpu98_oa(UINT port, UINT16 dat) { + +TRACEOUT(("smpu98 out %.4x %.2x", port, dat)); + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { + smpu98.native_intmask = dat; + } + (void)port; +} + +// [Native Mode] Immediate Message/Function +UINT16 IOINPCALL smpu98_i4(UINT port) { + + UINT16 ret = 0xffff; + + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { + if((smpu98.native_status & SMPU_STATUS_ISR) == 0){ + ret = smpu98.native_immbuf_r[smpu98.native_immbuf_r_pos]; + smpu98.native_immbuf_r_pos++; + if(smpu98.native_immbuf_r_pos >= smpu98.native_immbuf_r_len){ + smpu98.native_status |= SMPU_STATUS_ISR; + smpu98.native_immbuf_r_pos = smpu98.native_immbuf_r_len = 0; + //smpu98.native_status &= ~SMPU_STATUS_IRR; // XXX: ����ŗǂ��̂�������Ȃ� + } + smpu98.native_status &= ~SMPU_STATUS_RIR; + } +// TRACEOUT(("smpu98 inp %.4x %.2x", port, ret)); + return(ret); + } + (void)port; + return(0xffff); +} + +// [Native Mode] Sequence Message/Function +UINT16 IOINPCALL smpu98_i6(UINT port) { + + UINT16 ret = 0xffff; + + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { + if((smpu98.native_status & SMPU_STATUS_SSR) == 0){ + ret = smpu98.native_seqbuf_r[smpu98.native_seqbuf_r_pos]; + smpu98.native_seqbuf_r_pos++; + if(smpu98.native_seqbuf_r_pos >= smpu98.native_seqbuf_r_len){ + smpu98.native_status |= SMPU_STATUS_SSR; + smpu98.native_seqbuf_r_pos = smpu98.native_seqbuf_r_len = 0; + //smpu98.native_status &= ~SMPU_STATUS_SRR; // XXX: ����ŗǂ��̂�������Ȃ� + } + smpu98.native_status &= ~SMPU_STATUS_RSR; + } +// TRACEOUT(("smpu98 inp %.4x %.2x", port, ret)); + return(ret); + } + (void)port; + return(0xffff); +} + +// [Native Mode] Monitor +UINT16 IOINPCALL smpu98_i8(UINT port) { + + UINT16 ret = 0xffff; + + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { + if((smpu98.native_status & SMPU_STATUS_MSR) == 0){ + ret = smpu98.native_monbuf[smpu98.native_monbuf_pos]; + smpu98.native_monbuf_pos++; + if(smpu98.native_monbuf_pos >= smpu98.native_monbuf_len){ + smpu98.native_status |= SMPU_STATUS_MSR; + smpu98.native_monbuf_pos = smpu98.native_monbuf_len = 0; + } + smpu98.native_status &= ~SMPU_STATUS_RMR; + } + +// TRACEOUT(("smpu98 inp %.4x %.2x", port, ret)); + return(ret); + } + (void)port; + return(0xffff); +} + +// [Native Mode] Status +UINT16 IOINPCALL smpu98_ia(UINT port) { + + UINT16 ret; + + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, FALSE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, FALSE); + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + if (cm_smpu98[0]->connect != COMCONNECT_OFF && cm_smpu98[1]->connect != COMCONNECT_OFF) { + ret = smpu98.native_status & ~(SMPU_INTMASK_ALL << 9) | (smpu98.native_intmask << 9); + //if ((smpu98.r.cnt == 0) && (smpu98.intreq == 0)) { + // ret |= MIDIIN_AVAIL; + //} +// TRACEOUT(("smpu98 inp %.4x %.2x", port, ret)); + return(ret); + } + (void)port; + return(0xffff); +} + +// 16-bit I/O func +void (IOOUTCALL *smpu98_io16outfunc[])(UINT port, UINT16 dat) = { + NULL, NULL, NULL, NULL, + smpu98_o4, NULL, smpu98_o6, NULL, + smpu98_o8, NULL, smpu98_oa, NULL, + NULL, NULL, NULL, NULL, +}; +UINT16 (IOINPCALL *smpu98_io16inpfunc[])(UINT port) = { + NULL, NULL, NULL, NULL, + smpu98_i4, NULL, smpu98_i6, NULL, + smpu98_i8, NULL, smpu98_ia, NULL, + NULL, NULL, NULL, NULL, +}; + +// ---- I/F + +void smpu98_construct(void) { + + cm_smpu98[0] = NULL; + cm_smpu98[1] = NULL; + smpu98.portBready = 0; +} + +void smpu98_destruct(void) { + + commng_destroy(cm_smpu98[0]); + commng_destroy(cm_smpu98[1]); + cm_smpu98[0] = NULL; + cm_smpu98[1] = NULL; + smpu98.portBready = 0; +} + +void smpu98_reset(const NP2CFG *pConfig) { + + commng_destroy(cm_smpu98[0]); + commng_destroy(cm_smpu98[1]); + cm_smpu98[0] = NULL; + cm_smpu98[1] = NULL; + + ZeroMemory(&smpu98, sizeof(smpu98)); + smpu98.portBready = 0; + smpu98.enable = (pConfig->smpuenable ? 1 : 0); + smpu98.muteB = (pConfig->smpumuteB ? 1 : 0); + smpu98.data = MPUMSG_ACK; + smpu98.port = 0xc0d0 | ((pConfig->smpuopt & 0xf0) << 6); + smpu98.irqnum = mpuirqnum[pConfig->smpuopt & 3]; + setdefaultcondition(); +// pic_registext(smpu98.irqnum); + + if (cm_smpu98[0] == NULL) { + cm_smpu98[0] = commng_create(COMCREATE_SMPU98_A, TRUE); + } + if (cm_smpu98[1] == NULL) { + cm_smpu98[1] = commng_create(COMCREATE_SMPU98_B, TRUE); + if(cm_smpu98[1]){ + smpu98.portBready = (cm_smpu98[1]->connect != COMCONNECT_OFF); + } + } + + (void)pConfig; +} + +void smpu98_bind(void) { + + UINT port; + + if(smpu98.enable){ + smpu98_changeclock(); + + port = smpu98.port; + iocore_attachout(port, smpu98_o0); + iocore_attachinp(port, smpu98_i0); + port += 2; + iocore_attachout(port, smpu98_o2); + iocore_attachinp(port, smpu98_i2); + + // for S-MPU Native Mode (16-bit I/O�|�[�g�Ȃ̂�iocore.c�ŏ���) + //port += 2; + //iocore_attachout(port, smpu98_o4); + //iocore_attachinp(port, smpu98_i4); + //port += 2; + //iocore_attachout(port, smpu98_o6); + //iocore_attachinp(port, smpu98_i6); + //port += 2; + //iocore_attachout(port, smpu98_o8); + //iocore_attachinp(port, smpu98_i8); + //port += 2; + //iocore_attachout(port, smpu98_oa); + //iocore_attachinp(port, smpu98_ia); + + if(!mpu98.enable){ + // PC/AT MPU-401 + if(np2cfg.mpu_at){ + iocore_attachout(0x330, smpu98_o0); + iocore_attachinp(0x330, smpu98_i0); + iocore_attachout(0x331, smpu98_o2); + iocore_attachinp(0x331, smpu98_i2); + } + // PC-9801-118 + if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ + iocore_attachout(cs4231.port[10], smpu98_o0); + iocore_attachinp(cs4231.port[10], smpu98_i0); + iocore_attachout(cs4231.port[10]+1, smpu98_o2); + iocore_attachinp(cs4231.port[10]+1, smpu98_i2); + } + } + }else if(!mpu98.enable){ + // MPU-PC98II��S-MPU�������̎� + + // PC-9801-118 + if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ + iocore_attachout(cs4231.port[10], smpu98_o0); + iocore_attachinp(cs4231.port[10], smpu98_i0); + iocore_attachout(cs4231.port[10]+1, smpu98_o2); + iocore_attachinp(cs4231.port[10]+1, smpu98_i2); + // NULL�ō���Ă��� + cm_smpu98[0] = commng_create(COMCREATE_NULL, FALSE); + cm_smpu98[1] = commng_create(COMCREATE_NULL, FALSE); + } + } +} + +static void smpu98_callback_port(UINT8 dat, UINT8 port) { + if(smpu98.native_immread_phase[port] == 0){ + // 1byte�� + if(dat & 0x80){ + smpu98.native_immread_lastmsg[port] = dat; + smpu98.native_immread_portbuf[port] = ((UINT16)dat) << 8; + if(dat==0xf7){ + // F7(End of Exclusive) + smpu98_writeimm_r(smpu98.native_immread_portbuf[port]); + }else if(0xf0 <= dat && dat <= 0xff){ + // ���C���i���o�[������ + smpu98.native_immread_portbuf[port] |= (port==0 ? 0x00 : 0x10); + smpu98_writeimm_r(smpu98.native_immread_portbuf[port]); + }else{ + // ch�����C���i���o�[�ɕϊ� + smpu98.native_immread_portbuf[port] &= 0xf000; // ch������ + smpu98.native_immread_portbuf[port] |= (port==0 ? 0x00 : 0x10) | (dat & 0x0f); // ch�����C���i���o�[�ϊ� + smpu98_writeimm_r(smpu98.native_immread_portbuf[port]); + } + }else{ + UINT8 oldmsg = smpu98.native_immread_lastmsg[port]; // ���߂̃��b�Z�[�W�̑��� + smpu98.native_immread_portbuf[port] = ((UINT16)dat) << 8; + switch(oldmsg){ + case 0xc0: + case 0xd0: + // 1byte�����i2byte�ڂ�0�Łj + smpu98_writeimm_r(smpu98.native_immread_portbuf[port]); + break; + default: + // 2byte�ڂ�҂� + smpu98.native_immread_phase[port] = 1; + } + } + }else{ + // 2byte�� + smpu98.native_immread_portbuf[port] |= ((UINT16)dat); + smpu98_writeimm_r(smpu98.native_immread_portbuf[port]); + smpu98.native_immread_phase[port] = 0; + } +} + +void smpu98_callback(void) { + + UINT8 data; + + if (smpu98.mode == SMPUMODE_NATIVE) { + if (cm_smpu98[0]) { + while((SMPU_IMMBUF_R_LEN < smpu98.native_immbuf_r_len) && (cm_smpu98[0]->read(cm_smpu98[0], &data))) { + smpu98_callback_port(data, 0); + // XXX: 401�ɂ������Ă��� + if (!smpu98.r.cnt) { + smpu98_int(); + } + setrecvdata(data); + } + } + if (cm_smpu98[1]) { + while((SMPU_IMMBUF_R_LEN < smpu98.native_immbuf_r_len) && (cm_smpu98[1]->read(cm_smpu98[1], &data))) { + smpu98_callback_port(data, 0); + } + } + }else{ + if (cm_smpu98[0]) { + while((smpu98.r.cnt < MPU98_RECVBUFS) && + (cm_smpu98[0]->read(cm_smpu98[0], &data))) { + if (!smpu98.r.cnt) { + smpu98_int(); + } + setrecvdata(data); + } + } + } +} + +void smpu98_midipanic(void) { + + if (cm_smpu98[0]) { + cm_smpu98[0]->msg(cm_smpu98[0], COMMSG_MIDIRESET, 0); + } + if (cm_smpu98[1] && smpu98.portBready) { + cm_smpu98[1]->msg(cm_smpu98[1], COMMSG_MIDIRESET, 0); + } +} + +void smpu98_changeclock(void) { + + smpu98.xferclock = pccore.realclock / (31250 / 8); + + makeintclock(); +} + +#endif + diff --git a/cbus/smpu98.h b/cbus/smpu98.h index d3286f1f..e95c9e53 100644 --- a/cbus/smpu98.h +++ b/cbus/smpu98.h @@ -1,128 +1,128 @@ - -// ˂pwb_ - -#define SMPU_IMMBUF_W_LEN 32 -#define SMPU_IMMBUF_R_LEN 16 -#define SMPU_SEQBUF_W_LEN 32 -#define SMPU_SEQBUF_R_LEN 32 -#define SMPU_MONBUF_LEN 16 - -typedef struct { - UINT8 enable; - UINT8 portBready; // |[gB̎gpłĂ1 - UINT8 muteB; // MPU-PC98II݊[h̎A|[gBɏo͂Ȃ - - UINT16 port; - UINT8 irqnum; - UINT8 data; - - UINT32 xferclock; - SINT32 stepclock; - - UINT8 intphase; - UINT8 intreq; - UINT8 hclk_rem; - UINT8 hclk_cnt; - UINT8 hclk_step[4]; - - UINT8 acttr; - UINT8 status; - UINT8 mode; - UINT8 flag1; - UINT8 flag2; - - UINT8 tempo; - UINT8 reltempo; - UINT8 curtempo; - UINT8 inttimebase; - - UINT8 recvevent; - UINT8 remainstep; - UINT8 syncmode; - UINT8 metromode; - - UINT8 midipermetero; - UINT8 meteropermeas; - UINT8 sendplaycnt; - - UINT accch; - - MPURECV r; - - MPUCMDS cmd; - MPUTR tr[8]; - MPUCMDS cond; - - // for S-MPU Native Mode - UINT16 native_status; - UINT16 native_intmask; - - UINT16 native_immbuf_w[SMPU_IMMBUF_W_LEN]; - int native_immbuf_w_pos; - int native_immbuf_w_len; - UINT16 native_immbuf_r[SMPU_IMMBUF_R_LEN]; - int native_immbuf_r_pos; - int native_immbuf_r_len; - UINT16 native_seqbuf_w[SMPU_SEQBUF_W_LEN]; - int native_seqbuf_w_pos; - int native_seqbuf_w_len; - UINT16 native_seqbuf_r[SMPU_SEQBUF_R_LEN]; - int native_seqbuf_r_pos; - int native_seqbuf_r_len; - UINT16 native_monbuf[SMPU_MONBUF_LEN]; - int native_monbuf_pos; - int native_monbuf_len; - - UINT8 native_lastmsg; - UINT8 native_runningmsg; - UINT8 native_linenum; - UINT8 native_portnum; - UINT8 native_tmpbuf[1024]; - - UINT8 native_immread_lastmsg[2]; - UINT16 native_immread_portbuf[2]; - UINT16 native_immread_phase[2]; -} _SMPU98, *SMPU98; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern _SMPU98 smpu98; - -void smpu98_midiint(NEVENTITEM item); -void smpu98_midiwaitout(NEVENTITEM item); - -void smpu98_construct(void); -void smpu98_destruct(void); - -void smpu98_reset(const NP2CFG *pConfig); -void smpu98_bind(void); - -void smpu98_callback(void); -void smpu98_midipanic(void); - -void smpu98_changeclock(void); - -void IOOUTCALL smpu98_o0(UINT port, REG8 dat); -void IOOUTCALL smpu98_o2(UINT port, REG8 dat); -REG8 IOINPCALL smpu98_i0(UINT port); -REG8 IOINPCALL smpu98_i2(UINT port); - -void IOOUTCALL smpu98_o4(UINT port, UINT16 dat); -void IOOUTCALL smpu98_o6(UINT port, UINT16 dat); -void IOOUTCALL smpu98_o8(UINT port, UINT16 dat); -void IOOUTCALL smpu98_oa(UINT port, UINT16 dat); -UINT16 IOINPCALL smpu98_i4(UINT port); -UINT16 IOINPCALL smpu98_i6(UINT port); -UINT16 IOINPCALL smpu98_i8(UINT port); -UINT16 IOINPCALL smpu98_ia(UINT port); - -extern void (IOOUTCALL *smpu98_io16outfunc[])(UINT port, UINT16 dat); -extern UINT16 (IOINPCALL *smpu98_io16inpfunc[])(UINT port); - -#ifdef __cplusplus -} -#endif - + +// ねこ専用ヘッダ + +#define SMPU_IMMBUF_W_LEN 32 +#define SMPU_IMMBUF_R_LEN 16 +#define SMPU_SEQBUF_W_LEN 32 +#define SMPU_SEQBUF_R_LEN 32 +#define SMPU_MONBUF_LEN 16 + +typedef struct { + UINT8 enable; + UINT8 portBready; // ポートBの使用準備ができていれば1 + UINT8 muteB; // MPU-PC98II互換モードの時、ポートBに出力しない + + UINT16 port; + UINT8 irqnum; + UINT8 data; + + UINT32 xferclock; + SINT32 stepclock; + + UINT8 intphase; + UINT8 intreq; + UINT8 hclk_rem; + UINT8 hclk_cnt; + UINT8 hclk_step[4]; + + UINT8 acttr; + UINT8 status; + UINT8 mode; + UINT8 flag1; + UINT8 flag2; + + UINT8 tempo; + UINT8 reltempo; + UINT8 curtempo; + UINT8 inttimebase; + + UINT8 recvevent; + UINT8 remainstep; + UINT8 syncmode; + UINT8 metromode; + + UINT8 midipermetero; + UINT8 meteropermeas; + UINT8 sendplaycnt; + + UINT accch; + + MPURECV r; + + MPUCMDS cmd; + MPUTR tr[8]; + MPUCMDS cond; + + // for S-MPU Native Mode + UINT16 native_status; + UINT16 native_intmask; + + UINT16 native_immbuf_w[SMPU_IMMBUF_W_LEN]; + int native_immbuf_w_pos; + int native_immbuf_w_len; + UINT16 native_immbuf_r[SMPU_IMMBUF_R_LEN]; + int native_immbuf_r_pos; + int native_immbuf_r_len; + UINT16 native_seqbuf_w[SMPU_SEQBUF_W_LEN]; + int native_seqbuf_w_pos; + int native_seqbuf_w_len; + UINT16 native_seqbuf_r[SMPU_SEQBUF_R_LEN]; + int native_seqbuf_r_pos; + int native_seqbuf_r_len; + UINT16 native_monbuf[SMPU_MONBUF_LEN]; + int native_monbuf_pos; + int native_monbuf_len; + + UINT8 native_lastmsg; + UINT8 native_runningmsg; + UINT8 native_linenum; + UINT8 native_portnum; + UINT8 native_tmpbuf[1024]; + + UINT8 native_immread_lastmsg[2]; + UINT16 native_immread_portbuf[2]; + UINT16 native_immread_phase[2]; +} _SMPU98, *SMPU98; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _SMPU98 smpu98; + +void smpu98_midiint(NEVENTITEM item); +void smpu98_midiwaitout(NEVENTITEM item); + +void smpu98_construct(void); +void smpu98_destruct(void); + +void smpu98_reset(const NP2CFG *pConfig); +void smpu98_bind(void); + +void smpu98_callback(void); +void smpu98_midipanic(void); + +void smpu98_changeclock(void); + +void IOOUTCALL smpu98_o0(UINT port, REG8 dat); +void IOOUTCALL smpu98_o2(UINT port, REG8 dat); +REG8 IOINPCALL smpu98_i0(UINT port); +REG8 IOINPCALL smpu98_i2(UINT port); + +void IOOUTCALL smpu98_o4(UINT port, UINT16 dat); +void IOOUTCALL smpu98_o6(UINT port, UINT16 dat); +void IOOUTCALL smpu98_o8(UINT port, UINT16 dat); +void IOOUTCALL smpu98_oa(UINT port, UINT16 dat); +UINT16 IOINPCALL smpu98_i4(UINT port); +UINT16 IOINPCALL smpu98_i6(UINT port); +UINT16 IOINPCALL smpu98_i8(UINT port); +UINT16 IOINPCALL smpu98_ia(UINT port); + +extern void (IOOUTCALL *smpu98_io16outfunc[])(UINT port, UINT16 dat); +extern UINT16 (IOINPCALL *smpu98_io16inpfunc[])(UINT port); + +#ifdef __cplusplus +} +#endif + diff --git a/codecnv/codecnv.h b/codecnv/codecnv.h old mode 100755 new mode 100644 index e3792134..50a8edf6 --- a/codecnv/codecnv.h +++ b/codecnv/codecnv.h @@ -1,75 +1,75 @@ -/** - * @file codecnv.h - * @brief Interface of converting buffer - */ - -#if !defined(NP2_CODECNV_H__) -#define NP2_CODECNV_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -UINT codecnv_jistoucs2_1(UINT* puType, UINT16 *lpOutput, const char *lpInput, const UINT uType); -UINT codecnv_jistoucs2(UINT* puType, UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput, const UINT uType); - -UINT codecnv_sjistoeuc(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); -UINT codecnv_sjistoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); -UINT codecnv_sjistoutf8(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); - -UINT codecnv_euctosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); -UINT codecnv_euctoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); - -UINT codecnv_utf8toucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); -UINT codecnv_utf8tosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); - -UINT codecnv_ucs2len(const UINT16 *lpString); -UINT codecnv_ucs2tosjis(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput); -UINT codecnv_ucs2toutf8(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput); -UINT codecnv_utf8toucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); - -UINT codecnv_utf8toucs4_1(UINT32 *lpOutput, const char *lpInput, UINT cchInput); -UINT codecnv_utf8toucs4(UINT32 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); -UINT codecnv_ucs4toutf8(char *lpOutput, UINT cchOutput, const UINT32 *lpInput, UINT cchInput); - -UINT codecnv_ucs4len(const UINT32 *lpString); -UINT codecnv_ucs4toucs2_1(UINT16 *lpOutput, UINT cchOutput, const UINT32 *lpInput); -UINT codecnv_ucs2toucs4(UINT32 *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput); -UINT codecnv_ucs4toucs2(UINT16 *lpOutput, UINT cchOutput, const UINT32 *lpInput, UINT cchInput); - -#ifdef __cplusplus -} -#endif - -#endif // !defined(NP2_CODECNV_H__) - - - - -// codecnv仕様 -// -// (dst != NULL) 時はテストのみ行なう。この場合dcnt=無限と扱う。 -// -// scnt == -1 の場合、String Modeとなる。 -// ・NULLまで変換する -// ・dcntが足りなくても dstは必ずNULL Terminateとなる。 -// -// 戻り値: 書き込みバッファ数が返る。(NULL Terminateも含む) -// -// codecnv_AtoB(NULL, 0, "ABC\0DEF", -1) == 4 -// codecnv_AtoB(buf, 5, "ABC\0DEF", -1) == 4 / Copy(buf, "ABC\0", 4) -// codecnv_AtoB(buf, 3, "ABC\0DEF", -1) == 3 / Copy(buf, "AB\0", 3) -// -// -// scnt != -1 の場合、Binary Modeとなる。 -// ・scnt分変換を行なう -// -// 戻り値: 書き込みバッファ数が返る。 -// -// codecnv_AtoB(NULL, 0, "ABC\0DEF", 7) == 7 -// codecnv_AtoB(NULL, 0, "ABC\0DEF", 4) == 4 -// codecnv_AtoB(buf, 7, "ABC\0DEF", 5) == 5 / Copy(buf, "ABC\0D", 5) -// codecnv_AtoB(buf, 3, "ABC\0DEF", 6) == 3 / Copy(buf, "ABC", 3) -// codecnv_AtoB(buf, 3, "ABC\0DEF", 0) == 0 / Copy(buf, "", 0) - +/** + * @file codecnv.h + * @brief Interface of converting buffer + */ + +#if !defined(NP2_CODECNV_H__) +#define NP2_CODECNV_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +UINT codecnv_jistoucs2_1(UINT* puType, UINT16 *lpOutput, const char *lpInput, const UINT uType); +UINT codecnv_jistoucs2(UINT* puType, UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput, const UINT uType); + +UINT codecnv_sjistoeuc(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); +UINT codecnv_sjistoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); +UINT codecnv_sjistoutf8(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); + +UINT codecnv_euctosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); +UINT codecnv_euctoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); + +UINT codecnv_utf8toucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); +UINT codecnv_utf8tosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); + +UINT codecnv_ucs2len(const UINT16 *lpString); +UINT codecnv_ucs2tosjis(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput); +UINT codecnv_ucs2toutf8(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput); +UINT codecnv_utf8toucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); + +UINT codecnv_utf8toucs4_1(UINT32 *lpOutput, const char *lpInput, UINT cchInput); +UINT codecnv_utf8toucs4(UINT32 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); +UINT codecnv_ucs4toutf8(char *lpOutput, UINT cchOutput, const UINT32 *lpInput, UINT cchInput); + +UINT codecnv_ucs4len(const UINT32 *lpString); +UINT codecnv_ucs4toucs2_1(UINT16 *lpOutput, UINT cchOutput, const UINT32 *lpInput); +UINT codecnv_ucs2toucs4(UINT32 *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput); +UINT codecnv_ucs4toucs2(UINT16 *lpOutput, UINT cchOutput, const UINT32 *lpInput, UINT cchInput); + +#ifdef __cplusplus +} +#endif + +#endif // !defined(NP2_CODECNV_H__) + + + + +// codecnv仕様 +// +// (dst != NULL) 時はテストのみ行なう。この場合dcnt=無限と扱う。 +// +// scnt == -1 の場合、String Modeとなる。 +// ・NULLまで変換する +// ・dcntが足りなくても dstは必ずNULL Terminateとなる。 +// +// 戻り値: 書き込みバッファ数が返る。(NULL Terminateも含む) +// +// codecnv_AtoB(NULL, 0, "ABC\0DEF", -1) == 4 +// codecnv_AtoB(buf, 5, "ABC\0DEF", -1) == 4 / Copy(buf, "ABC\0", 4) +// codecnv_AtoB(buf, 3, "ABC\0DEF", -1) == 3 / Copy(buf, "AB\0", 3) +// +// +// scnt != -1 の場合、Binary Modeとなる。 +// ・scnt分変換を行なう +// +// 戻り値: 書き込みバッファ数が返る。 +// +// codecnv_AtoB(NULL, 0, "ABC\0DEF", 7) == 7 +// codecnv_AtoB(NULL, 0, "ABC\0DEF", 4) == 4 +// codecnv_AtoB(buf, 7, "ABC\0DEF", 5) == 5 / Copy(buf, "ABC\0D", 5) +// codecnv_AtoB(buf, 3, "ABC\0DEF", 6) == 3 / Copy(buf, "ABC", 3) +// codecnv_AtoB(buf, 3, "ABC\0DEF", 0) == 0 / Copy(buf, "", 0) + diff --git a/codecnv/eucsjis.c b/codecnv/eucsjis.c old mode 100755 new mode 100644 index 095e9af2..8c5485e0 --- a/codecnv/eucsjis.c +++ b/codecnv/eucsjis.c @@ -1,132 +1,132 @@ -/** - * @file eucsjis.c - * @brief Implementation of converting EUC to S-JIS - */ - -#ifdef CODECNV_TEST -#include "compiler_base.h" -#else -#include -#endif -#include - -static UINT euctosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); - -/** - * Maps a EUC string to a S-JIS string - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -UINT codecnv_euctosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) -{ - UINT nLength; - - if (lpInput == NULL) - { - return 0; - } - - if (cchOutput == 0) - { - lpOutput = NULL; - cchOutput = (UINT)-1; - } - - if (cchInput != (UINT)-1) - { - // Binary mode - return euctosjis(lpOutput, cchOutput, lpInput, cchInput); - } - else - { - // String mode - nLength = euctosjis(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); - if (lpOutput) - { - lpOutput[nLength] = '\0'; - } - return nLength + 1; - } -} - -/** - * Maps a EUC string to a S-JIS string (inner) - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -static UINT euctosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) -{ - UINT nRemain; - char h; - UINT l; - - nRemain = cchOutput; - while ((cchInput > 0) && (nRemain > 0)) - { - cchInput--; - h = *lpInput++; - if ((h & 0x80) == 0) - { - nRemain--; - if (lpOutput) - { - *lpOutput++ = h; - } - } - else if (h == (char)0x8e) - { - if (cchInput == 0) - { - break; - } - cchInput--; - h = *lpInput++; - - nRemain--; - if (lpOutput) - { - *lpOutput++ = h; - } - - } - else - { - if (cchInput == 0) - { - break; - } - cchInput--; - l = *lpInput++; - if (l == 0) - { - continue; - } - - if (nRemain < 2) - { - break; - } - nRemain -= 2; - if (lpOutput) - { - h &= 0x7f; - l &= 0x7f; - l += ((h & 1) - 1) & 0x5e; - if (l >= 0x60) - { - l++; - } - *lpOutput++ = (char)(((h + 0x121) >> 1) ^ 0x20); - *lpOutput++ = (char)(l + 0x1f); - } - } - } - - return (UINT)(cchOutput - nRemain); -} +/** + * @file eucsjis.c + * @brief Implementation of converting EUC to S-JIS + */ + +#ifdef CODECNV_TEST +#include "compiler_base.h" +#else +#include +#endif +#include + +static UINT euctosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); + +/** + * Maps a EUC string to a S-JIS string + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +UINT codecnv_euctosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) +{ + UINT nLength; + + if (lpInput == NULL) + { + return 0; + } + + if (cchOutput == 0) + { + lpOutput = NULL; + cchOutput = (UINT)-1; + } + + if (cchInput != (UINT)-1) + { + // Binary mode + return euctosjis(lpOutput, cchOutput, lpInput, cchInput); + } + else + { + // String mode + nLength = euctosjis(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); + if (lpOutput) + { + lpOutput[nLength] = '\0'; + } + return nLength + 1; + } +} + +/** + * Maps a EUC string to a S-JIS string (inner) + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +static UINT euctosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) +{ + UINT nRemain; + char h; + UINT l; + + nRemain = cchOutput; + while ((cchInput > 0) && (nRemain > 0)) + { + cchInput--; + h = *lpInput++; + if ((h & 0x80) == 0) + { + nRemain--; + if (lpOutput) + { + *lpOutput++ = h; + } + } + else if (h == (char)0x8e) + { + if (cchInput == 0) + { + break; + } + cchInput--; + h = *lpInput++; + + nRemain--; + if (lpOutput) + { + *lpOutput++ = h; + } + + } + else + { + if (cchInput == 0) + { + break; + } + cchInput--; + l = *lpInput++; + if (l == 0) + { + continue; + } + + if (nRemain < 2) + { + break; + } + nRemain -= 2; + if (lpOutput) + { + h &= 0x7f; + l &= 0x7f; + l += ((h & 1) - 1) & 0x5e; + if (l >= 0x60) + { + l++; + } + *lpOutput++ = (char)(((h + 0x121) >> 1) ^ 0x20); + *lpOutput++ = (char)(l + 0x1f); + } + } + } + + return (UINT)(cchOutput - nRemain); +} diff --git a/codecnv/eucucs2.c b/codecnv/eucucs2.c old mode 100755 new mode 100644 index 9e3d111a..f1fcf6e3 --- a/codecnv/eucucs2.c +++ b/codecnv/eucucs2.c @@ -1,77 +1,77 @@ -/** - * @file eucucs2.c - * @brief Implementation of converting EUC to UTF-16 - */ - -#ifdef CODECNV_TEST -#include "compiler_base.h" -#else -#include -#endif -#include - -static UINT euctoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); - -/** - * Maps a EUC string to a UTF-16 string - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -UINT codecnv_euctoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) -{ - UINT nLength; - - if (lpInput == NULL) - { - return 0; - } - - if (cchOutput == 0) - { - lpOutput = NULL; - cchOutput = (UINT)-1; - } - - if (cchInput != (UINT)-1) - { - // Binary mode - return euctoucs2(lpOutput, cchOutput, lpInput, cchInput); - } - else - { - // String mode - nLength = euctoucs2(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); - if (lpOutput) - { - lpOutput[nLength] = '\0'; - } - return nLength + 1; - } -} - -/** - * Maps a EUC string to a UTF-16 string (inner) - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -static UINT euctoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) -{ - UINT nLength; - char* pWork; - - nLength = codecnv_euctosjis(NULL, 0, lpInput, cchInput); - if (nLength) - { - pWork = (char*)malloc(nLength * sizeof(char)); - nLength = codecnv_euctosjis(pWork, nLength, lpInput, cchInput); - nLength = codecnv_sjistoucs2(lpOutput, cchOutput, pWork, nLength); - free(pWork); - } - return nLength; -} +/** + * @file eucucs2.c + * @brief Implementation of converting EUC to UTF-16 + */ + +#ifdef CODECNV_TEST +#include "compiler_base.h" +#else +#include +#endif +#include + +static UINT euctoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); + +/** + * Maps a EUC string to a UTF-16 string + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +UINT codecnv_euctoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) +{ + UINT nLength; + + if (lpInput == NULL) + { + return 0; + } + + if (cchOutput == 0) + { + lpOutput = NULL; + cchOutput = (UINT)-1; + } + + if (cchInput != (UINT)-1) + { + // Binary mode + return euctoucs2(lpOutput, cchOutput, lpInput, cchInput); + } + else + { + // String mode + nLength = euctoucs2(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); + if (lpOutput) + { + lpOutput[nLength] = '\0'; + } + return nLength + 1; + } +} + +/** + * Maps a EUC string to a UTF-16 string (inner) + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +static UINT euctoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) +{ + UINT nLength; + char* pWork; + + nLength = codecnv_euctosjis(NULL, 0, lpInput, cchInput); + if (nLength) + { + pWork = (char*)malloc(nLength * sizeof(char)); + nLength = codecnv_euctosjis(pWork, nLength, lpInput, cchInput); + nLength = codecnv_sjistoucs2(lpOutput, cchOutput, pWork, nLength); + free(pWork); + } + return nLength; +} diff --git a/codecnv/sjiseuc.c b/codecnv/sjiseuc.c old mode 100755 new mode 100644 index 30a68331..fe024b36 --- a/codecnv/sjiseuc.c +++ b/codecnv/sjiseuc.c @@ -1,128 +1,128 @@ -/** - * @file sjiseuc.c - * @brief Implementation of converting S-JIS to EUC - */ - -#ifdef CODECNV_TEST -#include "compiler_base.h" -#else -#include -#endif -#include - -static UINT sjistoeuc(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); - -/** - * Maps a S-JIS string to a EUC string - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -UINT codecnv_sjistoeuc(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) -{ - UINT nLength; - - if (lpInput == NULL) - { - return 0; - } - - if (cchOutput == 0) - { - lpOutput = NULL; - cchOutput = (UINT)-1; - } - - if (cchInput != (UINT)-1) - { - // Binary mode - return sjistoeuc(lpOutput, cchOutput, lpInput, cchInput); - } - else - { - // String mode - nLength = sjistoeuc(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); - if (lpOutput) - { - lpOutput[nLength] = '\0'; - } - return nLength + 1; - } -} - -/** - * Maps a S-JIS string to a EUC string (inner) - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -static UINT sjistoeuc(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) -{ - UINT nRemain; - char c; - UINT c2; - - nRemain = cchOutput; - while ((cchInput > 0) && (nRemain > 0)) - { - cchInput--; - c = *lpInput++; - if ((c & 0x80) == 0) - { - nRemain--; - if (lpOutput) - { - *lpOutput++ = c; - } - } - else if ((((c ^ 0x20) - 0xa1) & 0xff) < 0x2f) - { - if (cchInput == 0) - { - break; - } - cchInput--; - c2 = (UINT8)*lpInput++; - if (c2 == '\0') - { - continue; - } - - if (nRemain < 2) - { - break; - } - nRemain -= 2; - if (lpOutput) - { - c2 += 0x62 - ((c2 & 0x80) >> 7); - if (c2 < 256) - { - c2 = (c2 - 0xa2) & 0x1ff; - } - c2 += 0x9fa1; - *lpOutput++ = (char)(((c & 0x3f) << 1) + (c2 >> 8)); - *lpOutput++ = (char)c2; - } - } - else if (((c - 0xa0) & 0xff) < 0x40) - { - if (nRemain < 2) - { - break; - } - nRemain -= 2; - if (lpOutput) - { - *lpOutput++ = (char)0x8e; - *lpOutput++ = c; - } - } - } - - return (UINT)(cchOutput - nRemain); -} +/** + * @file sjiseuc.c + * @brief Implementation of converting S-JIS to EUC + */ + +#ifdef CODECNV_TEST +#include "compiler_base.h" +#else +#include +#endif +#include + +static UINT sjistoeuc(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); + +/** + * Maps a S-JIS string to a EUC string + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +UINT codecnv_sjistoeuc(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) +{ + UINT nLength; + + if (lpInput == NULL) + { + return 0; + } + + if (cchOutput == 0) + { + lpOutput = NULL; + cchOutput = (UINT)-1; + } + + if (cchInput != (UINT)-1) + { + // Binary mode + return sjistoeuc(lpOutput, cchOutput, lpInput, cchInput); + } + else + { + // String mode + nLength = sjistoeuc(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); + if (lpOutput) + { + lpOutput[nLength] = '\0'; + } + return nLength + 1; + } +} + +/** + * Maps a S-JIS string to a EUC string (inner) + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +static UINT sjistoeuc(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) +{ + UINT nRemain; + char c; + UINT c2; + + nRemain = cchOutput; + while ((cchInput > 0) && (nRemain > 0)) + { + cchInput--; + c = *lpInput++; + if ((c & 0x80) == 0) + { + nRemain--; + if (lpOutput) + { + *lpOutput++ = c; + } + } + else if ((((c ^ 0x20) - 0xa1) & 0xff) < 0x2f) + { + if (cchInput == 0) + { + break; + } + cchInput--; + c2 = (UINT8)*lpInput++; + if (c2 == '\0') + { + continue; + } + + if (nRemain < 2) + { + break; + } + nRemain -= 2; + if (lpOutput) + { + c2 += 0x62 - ((c2 & 0x80) >> 7); + if (c2 < 256) + { + c2 = (c2 - 0xa2) & 0x1ff; + } + c2 += 0x9fa1; + *lpOutput++ = (char)(((c & 0x3f) << 1) + (c2 >> 8)); + *lpOutput++ = (char)c2; + } + } + else if (((c - 0xa0) & 0xff) < 0x40) + { + if (nRemain < 2) + { + break; + } + nRemain -= 2; + if (lpOutput) + { + *lpOutput++ = (char)0x8e; + *lpOutput++ = c; + } + } + } + + return (UINT)(cchOutput - nRemain); +} diff --git a/codecnv/sjisucs2.c b/codecnv/sjisucs2.c old mode 100755 new mode 100644 index 4409c2d0..842b36dc --- a/codecnv/sjisucs2.c +++ b/codecnv/sjisucs2.c @@ -1,1370 +1,1370 @@ -/** - * @file sjisucs2.c - * @brief Implementation of converting S-JIS to UCS2 - */ - -#ifdef CODECNV_TEST -#include "compiler_base.h" -#else -#include -#endif -#include - -//! undefined code -#define UDCODE 0x30fb - -//! 2nd table -static const UINT16 s_level2[] = -{ - UDCODE,0x3000,0x3001,0x3002,0xff0c,0xff0e,0x30fb,0xff1a,0xff1b, - 0xff1f,0xff01,0x309b,0x309c,0x00b4,0xff40,0x00a8,0xff3e,0xffe3, - 0xff3f,0x30fd,0x30fe,0x309d,0x309e,0x3003,0x4edd,0x3005,0x3006, - 0x3007,0x30fc,0x2015,0x2010,0xff0f,0xff3c,0xff5e,0x2225,0xff5c, - 0x2026,0x2025,0x2018,0x2019,0x201c,0x201d,0xff08,0xff09,0x3014, - 0x3015,0xff3b,0xff3d,0xff5b,0xff5d,0x3008,0x3009,0x300a,0x300b, - 0x300c,0x300d,0x300e,0x300f,0x3010,0x3011,0xff0b,0xff0d,0x00b1, - 0x00d7,UDCODE,0x00f7,0xff1d,0x2260,0xff1c,0xff1e,0x2266,0x2267, - 0x221e,0x2234,0x2642,0x2640,0x00b0,0x2032,0x2033,0x2103,0xffe5, - 0xff04,0xffe0,0xffe1,0xff05,0xff03,0xff06,0xff0a,0xff20,0x00a7, - 0x2606,0x2605,0x25cb,0x25cf,0x25ce,0x25c7,0x25c6,0x25a1,0x25a0, - 0x25b3,0x25b2,0x25bd,0x25bc,0x203b,0x3012,0x2192,0x2190,0x2191, - 0x2193,0x3013,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x2208,0x220b,0x2286,0x2287,0x2282, - 0x2283,0x222a,0x2229,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x2227,0x2228,0xffe2,0x21d2,0x21d4,0x2200,0x2203, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x2220,0x22a5,0x2312,0x2202,0x2207,0x2261,0x2252, - 0x226a,0x226b,0x221a,0x223d,0x221d,0x2235,0x222b,0x222c,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x212b,0x2030,0x266f, - 0x266d,0x266a,0x2020,0x2021,0x00b6,UDCODE,UDCODE,UDCODE,UDCODE, - 0x25ef,0xff10,0xff11,0xff12,0xff13,0xff14,0xff15,0xff16,0xff17, - 0xff18,0xff19,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xff21,0xff22,0xff23,0xff24,0xff25,0xff26,0xff27,0xff28,0xff29, - 0xff2a,0xff2b,0xff2c,0xff2d,0xff2e,0xff2f,0xff30,0xff31,0xff32, - 0xff33,0xff34,0xff35,0xff36,0xff37,0xff38,0xff39,0xff3a,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xff41,0xff42,0xff43, - 0xff44,0xff45,0xff46,0xff47,0xff48,0xff49,0xff4a,0xff4b,0xff4c, - 0xff4d,0xff4e,0xff4f,0xff50,0xff51,0xff52,0xff53,0xff54,0xff55, - 0xff56,0xff57,0xff58,0xff59,0xff5a,UDCODE,UDCODE,UDCODE,UDCODE, - 0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,0x3049, - 0x304a,0x304b,0x304c,0x304d,0x304e,0x304f,0x3050,0x3051,0x3052, - 0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,0x3059,0x305a,0x305b, - 0x305c,0x305d,0x305e,0x305f,0x3060,0x3061,0x3062,0x3063,0x3064, - 0x3065,0x3066,0x3067,0x3068,0x3069,0x306a,0x306b,0x306c,0x306d, - 0x306e,0x306f,0x3070,0x3071,0x3072,0x3073,0x3074,0x3075,0x3076, - 0x3077,0x3078,0x3079,0x307a,0x307b,0x307c,0x307d,0x307e,0x307f, - 0x3080,0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087,0x3088, - 0x3089,0x308a,0x308b,0x308c,0x308d,0x308e,0x308f,0x3090,0x3091, - 0x3092,0x3093,0x30a1,0x30a2,0x30a3,0x30a4,0x30a5,0x30a6,0x30a7, - 0x30a8,0x30a9,0x30aa,0x30ab,0x30ac,0x30ad,0x30ae,0x30af,0x30b0, - 0x30b1,0x30b2,0x30b3,0x30b4,0x30b5,0x30b6,0x30b7,0x30b8,0x30b9, - 0x30ba,0x30bb,0x30bc,0x30bd,0x30be,0x30bf,0x30c0,0x30c1,0x30c2, - 0x30c3,0x30c4,0x30c5,0x30c6,0x30c7,0x30c8,0x30c9,0x30ca,0x30cb, - 0x30cc,0x30cd,0x30ce,0x30cf,0x30d0,0x30d1,0x30d2,0x30d3,0x30d4, - 0x30d5,0x30d6,0x30d7,0x30d8,0x30d9,0x30da,0x30db,0x30dc,0x30dd, - 0x30de,0x30df,UDCODE,0x30e0,0x30e1,0x30e2,0x30e3,0x30e4,0x30e5, - 0x30e6,0x30e7,0x30e8,0x30e9,0x30ea,0x30eb,0x30ec,0x30ed,0x30ee, - 0x30ef,0x30f0,0x30f1,0x30f2,0x30f3,0x30f4,0x30f5,0x30f6,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x0391,0x0392, - 0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,0x0399,0x039a,0x039b, - 0x039c,0x039d,0x039e,0x039f,0x03a0,0x03a1,0x03a3,0x03a4,0x03a5, - 0x03a6,0x03a7,0x03a8,0x03a9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6, - 0x03b7,0x03b8,0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf, - 0x03c0,0x03c1,0x03c3,0x03c4,0x03c5,0x03c6,0x03c7,0x03c8,0x03c9, - 0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,0x0416,0x0417, - 0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f,0x0420, - 0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429, - 0x042a,0x042b,0x042c,0x042d,0x042e,0x042f,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x0430,0x0431,0x0432,0x0433,0x0434,0x0435, - 0x0451,0x0436,0x0437,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d, - UDCODE,0x043e,0x043f,0x0440,0x0441,0x0442,0x0443,0x0444,0x0445, - 0x0446,0x0447,0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e, - 0x044f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x2500,0x2502,0x250c,0x2510, - 0x2518,0x2514,0x251c,0x252c,0x2524,0x2534,0x253c,0x2501,0x2503, - 0x250f,0x2513,0x251b,0x2517,0x2523,0x2533,0x252b,0x253b,0x254b, - 0x2520,0x252f,0x2528,0x2537,0x253f,0x251d,0x2530,0x2525,0x2538, - 0x2542,0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467, - 0x2468,0x2469,0x246a,0x246b,0x246c,0x246d,0x246e,0x246f,0x2470, - 0x2471,0x2472,0x2473,0x2160,0x2161,0x2162,0x2163,0x2164,0x2165, - 0x2166,0x2167,0x2168,0x2169,UDCODE,0x3349,0x3314,0x3322,0x334d, - 0x3318,0x3327,0x3303,0x3336,0x3351,0x3357,0x330d,0x3326,0x3323, - 0x332b,0x334a,0x333b,0x339c,0x339d,0x339e,0x338e,0x338f,0x33c4, - 0x33a1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x337b,UDCODE,0x301d,0x301f,0x2116,0x33cd,0x2121,0x32a4,0x32a5, - 0x32a6,0x32a7,0x32a8,0x3231,0x3232,0x3239,0x337e,0x337d,0x337c, - 0x2252,0x2261,0x222b,0x222e,0x2211,0x221a,0x22a5,0x2220,0x221f, - 0x22bf,0x2235,0x2229,0x222a,0x4e9c,0x5516,0x5a03,0x963f,0x54c0, - 0x611b,0x6328,0x59f6,0x9022,0x8475,0x831c,0x7a50,0x60aa,0x63e1, - 0x6e25,0x65ed,0x8466,0x82a6,0x9bf5,0x6893,0x5727,0x65a1,0x6271, - 0x5b9b,0x59d0,0x867b,0x98f4,0x7d62,0x7dbe,0x9b8e,0x6216,0x7c9f, - 0x88b7,0x5b89,0x5eb5,0x6309,0x6697,0x6848,0x95c7,0x978d,0x674f, - 0x4ee5,0x4f0a,0x4f4d,0x4f9d,0x5049,0x56f2,0x5937,0x59d4,0x5a01, - 0x5c09,0x60df,0x610f,0x6170,0x6613,0x6905,0x70ba,0x754f,0x7570, - 0x79fb,0x7dad,0x7def,0x80c3,0x840e,0x8863,0x8b02,0x9055,0x907a, - 0x533b,0x4e95,0x4ea5,0x57df,0x80b2,0x90c1,0x78ef,0x4e00,0x58f1, - 0x6ea2,0x9038,0x7a32,0x8328,0x828b,0x9c2f,0x5141,0x5370,0x54bd, - 0x54e1,0x56e0,0x59fb,0x5f15,0x98f2,0x6deb,0x80e4,0x852d,0x9662, - 0x9670,0x96a0,0x97fb,0x540b,0x53f3,0x5b87,0x70cf,0x7fbd,0x8fc2, - 0x96e8,0x536f,0x9d5c,0x7aba,0x4e11,0x7893,0x81fc,0x6e26,0x5618, - 0x5504,0x6b1d,0x851a,0x9c3b,0x59e5,0x53a9,0x6d66,0x74dc,0x958f, - 0x5642,0x4e91,0x904b,0x96f2,0x834f,0x990c,0x53e1,0x55b6,0x5b30, - 0x5f71,0x6620,0x66f3,0x6804,0x6c38,0x6cf3,0x6d29,0x745b,0x76c8, - 0x7a4e,0x9834,0x82f1,0x885b,0x8a60,0x92ed,0x6db2,0x75ab,0x76ca, - 0x99c5,0x60a6,0x8b01,0x8d8a,0x95b2,0x698e,0x53ad,0x5186,UDCODE, - 0x5712,0x5830,0x5944,0x5bb4,0x5ef6,0x6028,0x63a9,0x63f4,0x6cbf, - 0x6f14,0x708e,0x7114,0x7159,0x71d5,0x733f,0x7e01,0x8276,0x82d1, - 0x8597,0x9060,0x925b,0x9d1b,0x5869,0x65bc,0x6c5a,0x7525,0x51f9, - 0x592e,0x5965,0x5f80,0x5fdc,0x62bc,0x65fa,0x6a2a,0x6b27,0x6bb4, - 0x738b,0x7fc1,0x8956,0x9d2c,0x9d0e,0x9ec4,0x5ca1,0x6c96,0x837b, - 0x5104,0x5c4b,0x61b6,0x81c6,0x6876,0x7261,0x4e59,0x4ffa,0x5378, - 0x6069,0x6e29,0x7a4f,0x97f3,0x4e0b,0x5316,0x4eee,0x4f55,0x4f3d, - 0x4fa1,0x4f73,0x52a0,0x53ef,0x5609,0x590f,0x5ac1,0x5bb6,0x5be1, - 0x79d1,0x6687,0x679c,0x67b6,0x6b4c,0x6cb3,0x706b,0x73c2,0x798d, - 0x79be,0x7a3c,0x7b87,0x82b1,0x82db,0x8304,0x8377,0x83ef,0x83d3, - 0x8766,0x8ab2,0x5629,0x8ca8,0x8fe6,0x904e,0x971e,0x868a,0x4fc4, - 0x5ce8,0x6211,0x7259,0x753b,0x81e5,0x82bd,0x86fe,0x8cc0,0x96c5, - 0x9913,0x99d5,0x4ecb,0x4f1a,0x89e3,0x56de,0x584a,0x58ca,0x5efb, - 0x5feb,0x602a,0x6094,0x6062,0x61d0,0x6212,0x62d0,0x6539,0x9b41, - 0x6666,0x68b0,0x6d77,0x7070,0x754c,0x7686,0x7d75,0x82a5,0x87f9, - 0x958b,0x968e,0x8c9d,0x51f1,0x52be,0x5916,0x54b3,0x5bb3,0x5d16, - 0x6168,0x6982,0x6daf,0x788d,0x84cb,0x8857,0x8a72,0x93a7,0x9ab8, - 0x6d6c,0x99a8,0x86d9,0x57a3,0x67ff,0x86ce,0x920e,0x5283,0x5687, - 0x5404,0x5ed3,0x62e1,0x64b9,0x683c,0x6838,0x6bbb,0x7372,0x78ba, - 0x7a6b,0x899a,0x89d2,0x8d6b,0x8f03,0x90ed,0x95a3,0x9694,0x9769, - 0x5b66,0x5cb3,0x697d,0x984d,0x984e,0x639b,0x7b20,0x6a2b,UDCODE, - 0x6a7f,0x68b6,0x9c0d,0x6f5f,0x5272,0x559d,0x6070,0x62ec,0x6d3b, - 0x6e07,0x6ed1,0x845b,0x8910,0x8f44,0x4e14,0x9c39,0x53f6,0x691b, - 0x6a3a,0x9784,0x682a,0x515c,0x7ac3,0x84b2,0x91dc,0x938c,0x565b, - 0x9d28,0x6822,0x8305,0x8431,0x7ca5,0x5208,0x82c5,0x74e6,0x4e7e, - 0x4f83,0x51a0,0x5bd2,0x520a,0x52d8,0x52e7,0x5dfb,0x559a,0x582a, - 0x59e6,0x5b8c,0x5b98,0x5bdb,0x5e72,0x5e79,0x60a3,0x611f,0x6163, - 0x61be,0x63db,0x6562,0x67d1,0x6853,0x68fa,0x6b3e,0x6b53,0x6c57, - 0x6f22,0x6f97,0x6f45,0x74b0,0x7518,0x76e3,0x770b,0x7aff,0x7ba1, - 0x7c21,0x7de9,0x7f36,0x7ff0,0x809d,0x8266,0x839e,0x89b3,0x8acc, - 0x8cab,0x9084,0x9451,0x9593,0x9591,0x95a2,0x9665,0x97d3,0x9928, - 0x8218,0x4e38,0x542b,0x5cb8,0x5dcc,0x73a9,0x764c,0x773c,0x5ca9, - 0x7feb,0x8d0b,0x96c1,0x9811,0x9854,0x9858,0x4f01,0x4f0e,0x5371, - 0x559c,0x5668,0x57fa,0x5947,0x5b09,0x5bc4,0x5c90,0x5e0c,0x5e7e, - 0x5fcc,0x63ee,0x673a,0x65d7,0x65e2,0x671f,0x68cb,0x68c4,0x6a5f, - 0x5e30,0x6bc5,0x6c17,0x6c7d,0x757f,0x7948,0x5b63,0x7a00,0x7d00, - 0x5fbd,0x898f,0x8a18,0x8cb4,0x8d77,0x8ecc,0x8f1d,0x98e2,0x9a0e, - 0x9b3c,0x4e80,0x507d,0x5100,0x5993,0x5b9c,0x622f,0x6280,0x64ec, - 0x6b3a,0x72a0,0x7591,0x7947,0x7fa9,0x87fb,0x8abc,0x8b70,0x63ac, - 0x83ca,0x97a0,0x5409,0x5403,0x55ab,0x6854,0x6a58,0x8a70,0x7827, - 0x6775,0x9ecd,0x5374,0x5ba2,0x811a,0x8650,0x9006,0x4e18,0x4e45, - 0x4ec7,0x4f11,0x53ca,0x5438,0x5bae,0x5f13,0x6025,0x6551,UDCODE, - 0x673d,0x6c42,0x6c72,0x6ce3,0x7078,0x7403,0x7a76,0x7aae,0x7b08, - 0x7d1a,0x7cfe,0x7d66,0x65e7,0x725b,0x53bb,0x5c45,0x5de8,0x62d2, - 0x62e0,0x6319,0x6e20,0x865a,0x8a31,0x8ddd,0x92f8,0x6f01,0x79a6, - 0x9b5a,0x4ea8,0x4eab,0x4eac,0x4f9b,0x4fa0,0x50d1,0x5147,0x7af6, - 0x5171,0x51f6,0x5354,0x5321,0x537f,0x53eb,0x55ac,0x5883,0x5ce1, - 0x5f37,0x5f4a,0x602f,0x6050,0x606d,0x631f,0x6559,0x6a4b,0x6cc1, - 0x72c2,0x72ed,0x77ef,0x80f8,0x8105,0x8208,0x854e,0x90f7,0x93e1, - 0x97ff,0x9957,0x9a5a,0x4ef0,0x51dd,0x5c2d,0x6681,0x696d,0x5c40, - 0x66f2,0x6975,0x7389,0x6850,0x7c81,0x50c5,0x52e4,0x5747,0x5dfe, - 0x9326,0x65a4,0x6b23,0x6b3d,0x7434,0x7981,0x79bd,0x7b4b,0x7dca, - 0x82b9,0x83cc,0x887f,0x895f,0x8b39,0x8fd1,0x91d1,0x541f,0x9280, - 0x4e5d,0x5036,0x53e5,0x533a,0x72d7,0x7396,0x77e9,0x82e6,0x8eaf, - 0x99c6,0x99c8,0x99d2,0x5177,0x611a,0x865e,0x55b0,0x7a7a,0x5076, - 0x5bd3,0x9047,0x9685,0x4e32,0x6adb,0x91e7,0x5c51,0x5c48,0x6398, - 0x7a9f,0x6c93,0x9774,0x8f61,0x7aaa,0x718a,0x9688,0x7c82,0x6817, - 0x7e70,0x6851,0x936c,0x52f2,0x541b,0x85ab,0x8a13,0x7fa4,0x8ecd, - 0x90e1,0x5366,0x8888,0x7941,0x4fc2,0x50be,0x5211,0x5144,0x5553, - 0x572d,0x73ea,0x578b,0x5951,0x5f62,0x5f84,0x6075,0x6176,0x6167, - 0x61a9,0x63b2,0x643a,0x656c,0x666f,0x6842,0x6e13,0x7566,0x7a3d, - 0x7cfb,0x7d4c,0x7d99,0x7e4b,0x7f6b,0x830e,0x834a,0x86cd,0x8a08, - 0x8a63,0x8b66,0x8efd,0x981a,0x9d8f,0x82b8,0x8fce,0x9be8,UDCODE, - 0x5287,0x621f,0x6483,0x6fc0,0x9699,0x6841,0x5091,0x6b20,0x6c7a, - 0x6f54,0x7a74,0x7d50,0x8840,0x8a23,0x6708,0x4ef6,0x5039,0x5026, - 0x5065,0x517c,0x5238,0x5263,0x55a7,0x570f,0x5805,0x5acc,0x5efa, - 0x61b2,0x61f8,0x62f3,0x6372,0x691c,0x6a29,0x727d,0x72ac,0x732e, - 0x7814,0x786f,0x7d79,0x770c,0x80a9,0x898b,0x8b19,0x8ce2,0x8ed2, - 0x9063,0x9375,0x967a,0x9855,0x9a13,0x9e78,0x5143,0x539f,0x53b3, - 0x5e7b,0x5f26,0x6e1b,0x6e90,0x7384,0x73fe,0x7d43,0x8237,0x8a00, - 0x8afa,0x9650,0x4e4e,0x500b,0x53e4,0x547c,0x56fa,0x59d1,0x5b64, - 0x5df1,0x5eab,0x5f27,0x6238,0x6545,0x67af,0x6e56,0x72d0,0x7cca, - 0x88b4,0x80a1,0x80e1,0x83f0,0x864e,0x8a87,0x8de8,0x9237,0x96c7, - 0x9867,0x9f13,0x4e94,0x4e92,0x4f0d,0x5348,0x5449,0x543e,0x5a2f, - 0x5f8c,0x5fa1,0x609f,0x68a7,0x6a8e,0x745a,0x7881,0x8a9e,0x8aa4, - 0x8b77,0x9190,0x4e5e,0x9bc9,0x4ea4,0x4f7c,0x4faf,0x5019,0x5016, - 0x5149,0x516c,0x529f,0x52b9,0x52fe,0x539a,0x53e3,0x5411,0x540e, - 0x5589,0x5751,0x57a2,0x597d,0x5b54,0x5b5d,0x5b8f,0x5de5,0x5de7, - 0x5df7,0x5e78,0x5e83,0x5e9a,0x5eb7,0x5f18,0x6052,0x614c,0x6297, - 0x62d8,0x63a7,0x653b,0x6602,0x6643,0x66f4,0x676d,0x6821,0x6897, - 0x69cb,0x6c5f,0x6d2a,0x6d69,0x6e2f,0x6e9d,0x7532,0x7687,0x786c, - 0x7a3f,0x7ce0,0x7d05,0x7d18,0x7d5e,0x7db1,0x8015,0x8003,0x80af, - 0x80b1,0x8154,0x818f,0x822a,0x8352,0x884c,0x8861,0x8b1b,0x8ca2, - 0x8cfc,0x90ca,0x9175,0x9271,0x783f,0x92fc,0x95a4,0x964d,UDCODE, - 0x9805,0x9999,0x9ad8,0x9d3b,0x525b,0x52ab,0x53f7,0x5408,0x58d5, - 0x62f7,0x6fe0,0x8c6a,0x8f5f,0x9eb9,0x514b,0x523b,0x544a,0x56fd, - 0x7a40,0x9177,0x9d60,0x9ed2,0x7344,0x6f09,0x8170,0x7511,0x5ffd, - 0x60da,0x9aa8,0x72db,0x8fbc,0x6b64,0x9803,0x4eca,0x56f0,0x5764, - 0x58be,0x5a5a,0x6068,0x61c7,0x660f,0x6606,0x6839,0x68b1,0x6df7, - 0x75d5,0x7d3a,0x826e,0x9b42,0x4e9b,0x4f50,0x53c9,0x5506,0x5d6f, - 0x5de6,0x5dee,0x67fb,0x6c99,0x7473,0x7802,0x8a50,0x9396,0x88df, - 0x5750,0x5ea7,0x632b,0x50b5,0x50ac,0x518d,0x6700,0x54c9,0x585e, - 0x59bb,0x5bb0,0x5f69,0x624d,0x63a1,0x683d,0x6b73,0x6e08,0x707d, - 0x91c7,0x7280,0x7815,0x7826,0x796d,0x658e,0x7d30,0x83dc,0x88c1, - 0x8f09,0x969b,0x5264,0x5728,0x6750,0x7f6a,0x8ca1,0x51b4,0x5742, - 0x962a,0x583a,0x698a,0x80b4,0x54b2,0x5d0e,0x57fc,0x7895,0x9dfa, - 0x4f5c,0x524a,0x548b,0x643e,0x6628,0x6714,0x67f5,0x7a84,0x7b56, - 0x7d22,0x932f,0x685c,0x9bad,0x7b39,0x5319,0x518a,0x5237,0x5bdf, - 0x62f6,0x64ae,0x64e6,0x672d,0x6bba,0x85a9,0x96d1,0x7690,0x9bd6, - 0x634c,0x9306,0x9bab,0x76bf,0x6652,0x4e09,0x5098,0x53c2,0x5c71, - 0x60e8,0x6492,0x6563,0x685f,0x71e6,0x73ca,0x7523,0x7b97,0x7e82, - 0x8695,0x8b83,0x8cdb,0x9178,0x9910,0x65ac,0x66ab,0x6b8b,0x4ed5, - 0x4ed4,0x4f3a,0x4f7f,0x523a,0x53f8,0x53f2,0x55e3,0x56db,0x58eb, - 0x59cb,0x59c9,0x59ff,0x5b50,0x5c4d,0x5e02,0x5e2b,0x5fd7,0x601d, - 0x6307,0x652f,0x5b5c,0x65af,0x65bd,0x65e8,0x679d,0x6b62,UDCODE, - 0x6b7b,0x6c0f,0x7345,0x7949,0x79c1,0x7cf8,0x7d19,0x7d2b,0x80a2, - 0x8102,0x81f3,0x8996,0x8a5e,0x8a69,0x8a66,0x8a8c,0x8aee,0x8cc7, - 0x8cdc,0x96cc,0x98fc,0x6b6f,0x4e8b,0x4f3c,0x4f8d,0x5150,0x5b57, - 0x5bfa,0x6148,0x6301,0x6642,0x6b21,0x6ecb,0x6cbb,0x723e,0x74bd, - 0x75d4,0x78c1,0x793a,0x800c,0x8033,0x81ea,0x8494,0x8f9e,0x6c50, - 0x9e7f,0x5f0f,0x8b58,0x9d2b,0x7afa,0x8ef8,0x5b8d,0x96eb,0x4e03, - 0x53f1,0x57f7,0x5931,0x5ac9,0x5ba4,0x6089,0x6e7f,0x6f06,0x75be, - 0x8cea,0x5b9f,0x8500,0x7be0,0x5072,0x67f4,0x829d,0x5c61,0x854a, - 0x7e1e,0x820e,0x5199,0x5c04,0x6368,0x8d66,0x659c,0x716e,0x793e, - 0x7d17,0x8005,0x8b1d,0x8eca,0x906e,0x86c7,0x90aa,0x501f,0x52fa, - 0x5c3a,0x6753,0x707c,0x7235,0x914c,0x91c8,0x932b,0x82e5,0x5bc2, - 0x5f31,0x60f9,0x4e3b,0x53d6,0x5b88,0x624b,0x6731,0x6b8a,0x72e9, - 0x73e0,0x7a2e,0x816b,0x8da3,0x9152,0x9996,0x5112,0x53d7,0x546a, - 0x5bff,0x6388,0x6a39,0x7dac,0x9700,0x56da,0x53ce,0x5468,0x5b97, - 0x5c31,0x5dde,0x4fee,0x6101,0x62fe,0x6d32,0x79c0,0x79cb,0x7d42, - 0x7e4d,0x7fd2,0x81ed,0x821f,0x8490,0x8846,0x8972,0x8b90,0x8e74, - 0x8f2f,0x9031,0x914b,0x916c,0x96c6,0x919c,0x4ec0,0x4f4f,0x5145, - 0x5341,0x5f93,0x620e,0x67d4,0x6c41,0x6e0b,0x7363,0x7e26,0x91cd, - 0x9283,0x53d4,0x5919,0x5bbf,0x6dd1,0x795d,0x7e2e,0x7c9b,0x587e, - 0x719f,0x51fa,0x8853,0x8ff0,0x4fca,0x5cfb,0x6625,0x77ac,0x7ae3, - 0x821c,0x99ff,0x51c6,0x5faa,0x65ec,0x696f,0x6b89,0x6df3,UDCODE, - 0x6e96,0x6f64,0x76fe,0x7d14,0x5de1,0x9075,0x9187,0x9806,0x51e6, - 0x521d,0x6240,0x6691,0x66d9,0x6e1a,0x5eb6,0x7dd2,0x7f72,0x66f8, - 0x85af,0x85f7,0x8af8,0x52a9,0x53d9,0x5973,0x5e8f,0x5f90,0x6055, - 0x92e4,0x9664,0x50b7,0x511f,0x52dd,0x5320,0x5347,0x53ec,0x54e8, - 0x5546,0x5531,0x5617,0x5968,0x59be,0x5a3c,0x5bb5,0x5c06,0x5c0f, - 0x5c11,0x5c1a,0x5e84,0x5e8a,0x5ee0,0x5f70,0x627f,0x6284,0x62db, - 0x638c,0x6377,0x6607,0x660c,0x662d,0x6676,0x677e,0x68a2,0x6a1f, - 0x6a35,0x6cbc,0x6d88,0x6e09,0x6e58,0x713c,0x7126,0x7167,0x75c7, - 0x7701,0x785d,0x7901,0x7965,0x79f0,0x7ae0,0x7b11,0x7ca7,0x7d39, - 0x8096,0x83d6,0x848b,0x8549,0x885d,0x88f3,0x8a1f,0x8a3c,0x8a54, - 0x8a73,0x8c61,0x8cde,0x91a4,0x9266,0x937e,0x9418,0x969c,0x9798, - 0x4e0a,0x4e08,0x4e1e,0x4e57,0x5197,0x5270,0x57ce,0x5834,0x58cc, - 0x5b22,0x5e38,0x60c5,0x64fe,0x6761,0x6756,0x6d44,0x72b6,0x7573, - 0x7a63,0x84b8,0x8b72,0x91b8,0x9320,0x5631,0x57f4,0x98fe,0x62ed, - 0x690d,0x6b96,0x71ed,0x7e54,0x8077,0x8272,0x89e6,0x98df,0x8755, - 0x8fb1,0x5c3b,0x4f38,0x4fe1,0x4fb5,0x5507,0x5a20,0x5bdd,0x5be9, - 0x5fc3,0x614e,0x632f,0x65b0,0x664b,0x68ee,0x699b,0x6d78,0x6df1, - 0x7533,0x75b9,0x771f,0x795e,0x79e6,0x7d33,0x81e3,0x82af,0x85aa, - 0x89aa,0x8a3a,0x8eab,0x8f9b,0x9032,0x91dd,0x9707,0x4eba,0x4ec1, - 0x5203,0x5875,0x58ec,0x5c0b,0x751a,0x5c3d,0x814e,0x8a0a,0x8fc5, - 0x9663,0x976d,0x7b25,0x8acf,0x9808,0x9162,0x56f3,0x53a8,UDCODE, - 0x9017,0x5439,0x5782,0x5e25,0x63a8,0x6c34,0x708a,0x7761,0x7c8b, - 0x7fe0,0x8870,0x9042,0x9154,0x9310,0x9318,0x968f,0x745e,0x9ac4, - 0x5d07,0x5d69,0x6570,0x67a2,0x8da8,0x96db,0x636e,0x6749,0x6919, - 0x83c5,0x9817,0x96c0,0x88fe,0x6f84,0x647a,0x5bf8,0x4e16,0x702c, - 0x755d,0x662f,0x51c4,0x5236,0x52e2,0x59d3,0x5f81,0x6027,0x6210, - 0x653f,0x6574,0x661f,0x6674,0x68f2,0x6816,0x6b63,0x6e05,0x7272, - 0x751f,0x76db,0x7cbe,0x8056,0x58f0,0x88fd,0x897f,0x8aa0,0x8a93, - 0x8acb,0x901d,0x9192,0x9752,0x9759,0x6589,0x7a0e,0x8106,0x96bb, - 0x5e2d,0x60dc,0x621a,0x65a5,0x6614,0x6790,0x77f3,0x7a4d,0x7c4d, - 0x7e3e,0x810a,0x8cac,0x8d64,0x8de1,0x8e5f,0x78a9,0x5207,0x62d9, - 0x63a5,0x6442,0x6298,0x8a2d,0x7a83,0x7bc0,0x8aac,0x96ea,0x7d76, - 0x820c,0x8749,0x4ed9,0x5148,0x5343,0x5360,0x5ba3,0x5c02,0x5c16, - 0x5ddd,0x6226,0x6247,0x64b0,0x6813,0x6834,0x6cc9,0x6d45,0x6d17, - 0x67d3,0x6f5c,0x714e,0x717d,0x65cb,0x7a7f,0x7bad,0x7dda,0x7e4a, - 0x7fa8,0x817a,0x821b,0x8239,0x85a6,0x8a6e,0x8cce,0x8df5,0x9078, - 0x9077,0x92ad,0x9291,0x9583,0x9bae,0x524d,0x5584,0x6f38,0x7136, - 0x5168,0x7985,0x7e55,0x81b3,0x7cce,0x564c,0x5851,0x5ca8,0x63aa, - 0x66fe,0x66fd,0x695a,0x72d9,0x758f,0x758e,0x790e,0x7956,0x79df, - 0x7c97,0x7d20,0x7d44,0x8607,0x8a34,0x963b,0x9061,0x9f20,0x50e7, - 0x5275,0x53cc,0x53e2,0x5009,0x55aa,0x58ee,0x594f,0x723d,0x5b8b, - 0x5c64,0x531d,0x60e3,0x60f3,0x635c,0x6383,0x633f,0x63bb,UDCODE, - 0x64cd,0x65e9,0x66f9,0x5de3,0x69cd,0x69fd,0x6f15,0x71e5,0x4e89, - 0x75e9,0x76f8,0x7a93,0x7cdf,0x7dcf,0x7d9c,0x8061,0x8349,0x8358, - 0x846c,0x84bc,0x85fb,0x88c5,0x8d70,0x9001,0x906d,0x9397,0x971c, - 0x9a12,0x50cf,0x5897,0x618e,0x81d3,0x8535,0x8d08,0x9020,0x4fc3, - 0x5074,0x5247,0x5373,0x606f,0x6349,0x675f,0x6e2c,0x8db3,0x901f, - 0x4fd7,0x5c5e,0x8cca,0x65cf,0x7d9a,0x5352,0x8896,0x5176,0x63c3, - 0x5b58,0x5b6b,0x5c0a,0x640d,0x6751,0x905c,0x4ed6,0x591a,0x592a, - 0x6c70,0x8a51,0x553e,0x5815,0x59a5,0x60f0,0x6253,0x67c1,0x8235, - 0x6955,0x9640,0x99c4,0x9a28,0x4f53,0x5806,0x5bfe,0x8010,0x5cb1, - 0x5e2f,0x5f85,0x6020,0x614b,0x6234,0x66ff,0x6cf0,0x6ede,0x80ce, - 0x817f,0x82d4,0x888b,0x8cb8,0x9000,0x902e,0x968a,0x9edb,0x9bdb, - 0x4ee3,0x53f0,0x5927,0x7b2c,0x918d,0x984c,0x9df9,0x6edd,0x7027, - 0x5353,0x5544,0x5b85,0x6258,0x629e,0x62d3,0x6ca2,0x6fef,0x7422, - 0x8a17,0x9438,0x6fc1,0x8afe,0x8338,0x51e7,0x86f8,0x53ea,0x53e9, - 0x4f46,0x9054,0x8fb0,0x596a,0x8131,0x5dfd,0x7aea,0x8fbf,0x68da, - 0x8c37,0x72f8,0x9c48,0x6a3d,0x8ab0,0x4e39,0x5358,0x5606,0x5766, - 0x62c5,0x63a2,0x65e6,0x6b4e,0x6de1,0x6e5b,0x70ad,0x77ed,0x7aef, - 0x7baa,0x7dbb,0x803d,0x80c6,0x86cb,0x8a95,0x935b,0x56e3,0x58c7, - 0x5f3e,0x65ad,0x6696,0x6a80,0x6bb5,0x7537,0x8ac7,0x5024,0x77e5, - 0x5730,0x5f1b,0x6065,0x667a,0x6c60,0x75f4,0x7a1a,0x7f6e,0x81f4, - 0x8718,0x9045,0x99b3,0x7bc9,0x755c,0x7af9,0x7b51,0x84c4,UDCODE, - 0x9010,0x79e9,0x7a92,0x8336,0x5ae1,0x7740,0x4e2d,0x4ef2,0x5b99, - 0x5fe0,0x62bd,0x663c,0x67f1,0x6ce8,0x866b,0x8877,0x8a3b,0x914e, - 0x92f3,0x99d0,0x6a17,0x7026,0x732a,0x82e7,0x8457,0x8caf,0x4e01, - 0x5146,0x51cb,0x558b,0x5bf5,0x5e16,0x5e33,0x5e81,0x5f14,0x5f35, - 0x5f6b,0x5fb4,0x61f2,0x6311,0x66a2,0x671d,0x6f6e,0x7252,0x753a, - 0x773a,0x8074,0x8139,0x8178,0x8776,0x8abf,0x8adc,0x8d85,0x8df3, - 0x929a,0x9577,0x9802,0x9ce5,0x52c5,0x6357,0x76f4,0x6715,0x6c88, - 0x73cd,0x8cc3,0x93ae,0x9673,0x6d25,0x589c,0x690e,0x69cc,0x8ffd, - 0x939a,0x75db,0x901a,0x585a,0x6802,0x63b4,0x69fb,0x4f43,0x6f2c, - 0x67d8,0x8fbb,0x8526,0x7db4,0x9354,0x693f,0x6f70,0x576a,0x58f7, - 0x5b2c,0x7d2c,0x722a,0x540a,0x91e3,0x9db4,0x4ead,0x4f4e,0x505c, - 0x5075,0x5243,0x8c9e,0x5448,0x5824,0x5b9a,0x5e1d,0x5e95,0x5ead, - 0x5ef7,0x5f1f,0x608c,0x62b5,0x633a,0x63d0,0x68af,0x6c40,0x7887, - 0x798e,0x7a0b,0x7de0,0x8247,0x8a02,0x8ae6,0x8e44,0x9013,0x90b8, - 0x912d,0x91d8,0x9f0e,0x6ce5,0x6458,0x64e2,0x6575,0x6ef4,0x7684, - 0x7b1b,0x9069,0x93d1,0x6eba,0x54f2,0x5fb9,0x64a4,0x8f4d,0x8fed, - 0x9244,0x5178,0x586b,0x5929,0x5c55,0x5e97,0x6dfb,0x7e8f,0x751c, - 0x8cbc,0x8ee2,0x985b,0x70b9,0x4f1d,0x6bbf,0x6fb1,0x7530,0x96fb, - 0x514e,0x5410,0x5835,0x5857,0x59ac,0x5c60,0x5f92,0x6597,0x675c, - 0x6e21,0x767b,0x83df,0x8ced,0x9014,0x90fd,0x934d,0x7825,0x783a, - 0x52aa,0x5ea6,0x571f,0x5974,0x6012,0x5012,0x515a,0x51ac,UDCODE, - 0x51cd,0x5200,0x5510,0x5854,0x5858,0x5957,0x5b95,0x5cf6,0x5d8b, - 0x60bc,0x6295,0x642d,0x6771,0x6843,0x68bc,0x68df,0x76d7,0x6dd8, - 0x6e6f,0x6d9b,0x706f,0x71c8,0x5f53,0x75d8,0x7977,0x7b49,0x7b54, - 0x7b52,0x7cd6,0x7d71,0x5230,0x8463,0x8569,0x85e4,0x8a0e,0x8b04, - 0x8c46,0x8e0f,0x9003,0x900f,0x9419,0x9676,0x982d,0x9a30,0x95d8, - 0x50cd,0x52d5,0x540c,0x5802,0x5c0e,0x61a7,0x649e,0x6d1e,0x77b3, - 0x7ae5,0x80f4,0x8404,0x9053,0x9285,0x5ce0,0x9d07,0x533f,0x5f97, - 0x5fb3,0x6d9c,0x7279,0x7763,0x79bf,0x7be4,0x6bd2,0x72ec,0x8aad, - 0x6803,0x6a61,0x51f8,0x7a81,0x6934,0x5c4a,0x9cf6,0x82eb,0x5bc5, - 0x9149,0x701e,0x5678,0x5c6f,0x60c7,0x6566,0x6c8c,0x8c5a,0x9041, - 0x9813,0x5451,0x66c7,0x920d,0x5948,0x90a3,0x5185,0x4e4d,0x51ea, - 0x8599,0x8b0e,0x7058,0x637a,0x934b,0x6962,0x99b4,0x7e04,0x7577, - 0x5357,0x6960,0x8edf,0x96e3,0x6c5d,0x4e8c,0x5c3c,0x5f10,0x8fe9, - 0x5302,0x8cd1,0x8089,0x8679,0x5eff,0x65e5,0x4e73,0x5165,0x5982, - 0x5c3f,0x97ee,0x4efb,0x598a,0x5fcd,0x8a8d,0x6fe1,0x79b0,0x7962, - 0x5be7,0x8471,0x732b,0x71b1,0x5e74,0x5ff5,0x637b,0x649a,0x71c3, - 0x7c98,0x4e43,0x5efc,0x4e4b,0x57dc,0x56a2,0x60a9,0x6fc3,0x7d0d, - 0x80fd,0x8133,0x81bf,0x8fb2,0x8997,0x86a4,0x5df4,0x628a,0x64ad, - 0x8987,0x6777,0x6ce2,0x6d3e,0x7436,0x7834,0x5a46,0x7f75,0x82ad, - 0x99ac,0x4ff3,0x5ec3,0x62dd,0x6392,0x6557,0x676f,0x76c3,0x724c, - 0x80cc,0x80ba,0x8f29,0x914d,0x500d,0x57f9,0x5a92,0x6885,UDCODE, - 0x6973,0x7164,0x72fd,0x8cb7,0x58f2,0x8ce0,0x966a,0x9019,0x877f, - 0x79e4,0x77e7,0x8429,0x4f2f,0x5265,0x535a,0x62cd,0x67cf,0x6cca, - 0x767d,0x7b94,0x7c95,0x8236,0x8584,0x8feb,0x66dd,0x6f20,0x7206, - 0x7e1b,0x83ab,0x99c1,0x9ea6,0x51fd,0x7bb1,0x7872,0x7bb8,0x8087, - 0x7b48,0x6ae8,0x5e61,0x808c,0x7551,0x7560,0x516b,0x9262,0x6e8c, - 0x767a,0x9197,0x9aea,0x4f10,0x7f70,0x629c,0x7b4f,0x95a5,0x9ce9, - 0x567a,0x5859,0x86e4,0x96bc,0x4f34,0x5224,0x534a,0x53cd,0x53db, - 0x5e06,0x642c,0x6591,0x677f,0x6c3e,0x6c4e,0x7248,0x72af,0x73ed, - 0x7554,0x7e41,0x822c,0x85e9,0x8ca9,0x7bc4,0x91c6,0x7169,0x9812, - 0x98ef,0x633d,0x6669,0x756a,0x76e4,0x78d0,0x8543,0x86ee,0x532a, - 0x5351,0x5426,0x5983,0x5e87,0x5f7c,0x60b2,0x6249,0x6279,0x62ab, - 0x6590,0x6bd4,0x6ccc,0x75b2,0x76ae,0x7891,0x79d8,0x7dcb,0x7f77, - 0x80a5,0x88ab,0x8ab9,0x8cbb,0x907f,0x975e,0x98db,0x6a0b,0x7c38, - 0x5099,0x5c3e,0x5fae,0x6787,0x6bd8,0x7435,0x7709,0x7f8e,0x9f3b, - 0x67ca,0x7a17,0x5339,0x758b,0x9aed,0x5f66,0x819d,0x83f1,0x8098, - 0x5f3c,0x5fc5,0x7562,0x7b46,0x903c,0x6867,0x59eb,0x5a9b,0x7d10, - 0x767e,0x8b2c,0x4ff5,0x5f6a,0x6a19,0x6c37,0x6f02,0x74e2,0x7968, - 0x8868,0x8a55,0x8c79,0x5edf,0x63cf,0x75c5,0x79d2,0x82d7,0x9328, - 0x92f2,0x849c,0x86ed,0x9c2d,0x54c1,0x5f6c,0x658c,0x6d5c,0x7015, - 0x8ca7,0x8cd3,0x983b,0x654f,0x74f6,0x4e0d,0x4ed8,0x57e0,0x592b, - 0x5a66,0x5bcc,0x51a8,0x5e03,0x5e9c,0x6016,0x6276,0x6577,UDCODE, - 0x65a7,0x666e,0x6d6e,0x7236,0x7b26,0x8150,0x819a,0x8299,0x8b5c, - 0x8ca0,0x8ce6,0x8d74,0x961c,0x9644,0x4fae,0x64ab,0x6b66,0x821e, - 0x8461,0x856a,0x90e8,0x5c01,0x6953,0x98a8,0x847a,0x8557,0x4f0f, - 0x526f,0x5fa9,0x5e45,0x670d,0x798f,0x8179,0x8907,0x8986,0x6df5, - 0x5f17,0x6255,0x6cb8,0x4ecf,0x7269,0x9b92,0x5206,0x543b,0x5674, - 0x58b3,0x61a4,0x626e,0x711a,0x596e,0x7c89,0x7cde,0x7d1b,0x96f0, - 0x6587,0x805e,0x4e19,0x4f75,0x5175,0x5840,0x5e63,0x5e73,0x5f0a, - 0x67c4,0x4e26,0x853d,0x9589,0x965b,0x7c73,0x9801,0x50fb,0x58c1, - 0x7656,0x78a7,0x5225,0x77a5,0x8511,0x7b86,0x504f,0x5909,0x7247, - 0x7bc7,0x7de8,0x8fba,0x8fd4,0x904d,0x4fbf,0x52c9,0x5a29,0x5f01, - 0x97ad,0x4fdd,0x8217,0x92ea,0x5703,0x6355,0x6b69,0x752b,0x88dc, - 0x8f14,0x7a42,0x52df,0x5893,0x6155,0x620a,0x66ae,0x6bcd,0x7c3f, - 0x83e9,0x5023,0x4ff8,0x5305,0x5446,0x5831,0x5949,0x5b9d,0x5cf0, - 0x5cef,0x5d29,0x5e96,0x62b1,0x6367,0x653e,0x65b9,0x670b,0x6cd5, - 0x6ce1,0x70f9,0x7832,0x7e2b,0x80de,0x82b3,0x840c,0x84ec,0x8702, - 0x8912,0x8a2a,0x8c4a,0x90a6,0x92d2,0x98fd,0x9cf3,0x9d6c,0x4e4f, - 0x4ea1,0x508d,0x5256,0x574a,0x59a8,0x5e3d,0x5fd8,0x5fd9,0x623f, - 0x66b4,0x671b,0x67d0,0x68d2,0x5192,0x7d21,0x80aa,0x81a8,0x8b00, - 0x8c8c,0x8cbf,0x927e,0x9632,0x5420,0x982c,0x5317,0x50d5,0x535c, - 0x58a8,0x64b2,0x6734,0x7267,0x7766,0x7a46,0x91e6,0x52c3,0x6ca1, - 0x6b86,0x5800,0x5e4c,0x5954,0x672c,0x7ffb,0x51e1,0x76c6,UDCODE, - 0x6469,0x78e8,0x9b54,0x9ebb,0x57cb,0x59b9,0x6627,0x679a,0x6bce, - 0x54e9,0x69d9,0x5e55,0x819c,0x6795,0x9baa,0x67fe,0x9c52,0x685d, - 0x4ea6,0x4fe3,0x53c8,0x62b9,0x672b,0x6cab,0x8fc4,0x4fad,0x7e6d, - 0x9ebf,0x4e07,0x6162,0x6e80,0x6f2b,0x8513,0x5473,0x672a,0x9b45, - 0x5df3,0x7b95,0x5cac,0x5bc6,0x871c,0x6e4a,0x84d1,0x7a14,0x8108, - 0x5999,0x7c8d,0x6c11,0x7720,0x52d9,0x5922,0x7121,0x725f,0x77db, - 0x9727,0x9d61,0x690b,0x5a7f,0x5a18,0x51a5,0x540d,0x547d,0x660e, - 0x76df,0x8ff7,0x9298,0x9cf4,0x59ea,0x725d,0x6ec5,0x514d,0x68c9, - 0x7dbf,0x7dec,0x9762,0x9eba,0x6478,0x6a21,0x8302,0x5984,0x5b5f, - 0x6bdb,0x731b,0x76f2,0x7db2,0x8017,0x8499,0x5132,0x6728,0x9ed9, - 0x76ee,0x6762,0x52ff,0x9905,0x5c24,0x623b,0x7c7e,0x8cb0,0x554f, - 0x60b6,0x7d0b,0x9580,0x5301,0x4e5f,0x51b6,0x591c,0x723a,0x8036, - 0x91ce,0x5f25,0x77e2,0x5384,0x5f79,0x7d04,0x85ac,0x8a33,0x8e8d, - 0x9756,0x67f3,0x85ae,0x9453,0x6109,0x6108,0x6cb9,0x7652,0x8aed, - 0x8f38,0x552f,0x4f51,0x512a,0x52c7,0x53cb,0x5ba5,0x5e7d,0x60a0, - 0x6182,0x63d6,0x6709,0x67da,0x6e67,0x6d8c,0x7336,0x7337,0x7531, - 0x7950,0x88d5,0x8a98,0x904a,0x9091,0x90f5,0x96c4,0x878d,0x5915, - 0x4e88,0x4f59,0x4e0e,0x8a89,0x8f3f,0x9810,0x50ad,0x5e7c,0x5996, - 0x5bb9,0x5eb8,0x63da,0x63fa,0x64c1,0x66dc,0x694a,0x69d8,0x6d0b, - 0x6eb6,0x7194,0x7528,0x7aaf,0x7f8a,0x8000,0x8449,0x84c9,0x8981, - 0x8b21,0x8e0a,0x9065,0x967d,0x990a,0x617e,0x6291,0x6b32,UDCODE, - 0x6c83,0x6d74,0x7fcc,0x7ffc,0x6dc0,0x7f85,0x87ba,0x88f8,0x6765, - 0x83b1,0x983c,0x96f7,0x6d1b,0x7d61,0x843d,0x916a,0x4e71,0x5375, - 0x5d50,0x6b04,0x6feb,0x85cd,0x862d,0x89a7,0x5229,0x540f,0x5c65, - 0x674e,0x68a8,0x7406,0x7483,0x75e2,0x88cf,0x88e1,0x91cc,0x96e2, - 0x9678,0x5f8b,0x7387,0x7acb,0x844e,0x63a0,0x7565,0x5289,0x6d41, - 0x6e9c,0x7409,0x7559,0x786b,0x7c92,0x9686,0x7adc,0x9f8d,0x4fb6, - 0x616e,0x65c5,0x865c,0x4e86,0x4eae,0x50da,0x4e21,0x51cc,0x5bee, - 0x6599,0x6881,0x6dbc,0x731f,0x7642,0x77ad,0x7a1c,0x7ce7,0x826f, - 0x8ad2,0x907c,0x91cf,0x9675,0x9818,0x529b,0x7dd1,0x502b,0x5398, - 0x6797,0x6dcb,0x71d0,0x7433,0x81e8,0x8f2a,0x96a3,0x9c57,0x9e9f, - 0x7460,0x5841,0x6d99,0x7d2f,0x985e,0x4ee4,0x4f36,0x4f8b,0x51b7, - 0x52b1,0x5dba,0x601c,0x73b2,0x793c,0x82d3,0x9234,0x96b7,0x96f6, - 0x970a,0x9e97,0x9f62,0x66a6,0x6b74,0x5217,0x52a3,0x70c8,0x88c2, - 0x5ec9,0x604b,0x6190,0x6f23,0x7149,0x7c3e,0x7df4,0x806f,0x84ee, - 0x9023,0x932c,0x5442,0x9b6f,0x6ad3,0x7089,0x8cc2,0x8def,0x9732, - 0x52b4,0x5a41,0x5eca,0x5f04,0x6717,0x697c,0x6994,0x6d6a,0x6f0f, - 0x7262,0x72fc,0x7bed,0x8001,0x807e,0x874b,0x90ce,0x516d,0x9e93, - 0x7984,0x808b,0x9332,0x8ad6,0x502d,0x548c,0x8a71,0x6b6a,0x8cc4, - 0x8107,0x60d1,0x67a0,0x9df2,0x4e99,0x4e98,0x9c10,0x8a6b,0x85c1, - 0x8568,0x6900,0x6e7e,0x7897,0x8155,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x5f0c,0x4e10,0x4e15,0x4e2a,0x4e31, - 0x4e36,0x4e3c,0x4e3f,0x4e42,0x4e56,0x4e58,0x4e82,0x4e85,0x8c6b, - 0x4e8a,0x8212,0x5f0d,0x4e8e,0x4e9e,0x4e9f,0x4ea0,0x4ea2,0x4eb0, - 0x4eb3,0x4eb6,0x4ece,0x4ecd,0x4ec4,0x4ec6,0x4ec2,0x4ed7,0x4ede, - 0x4eed,0x4edf,0x4ef7,0x4f09,0x4f5a,0x4f30,0x4f5b,0x4f5d,0x4f57, - 0x4f47,0x4f76,0x4f88,0x4f8f,0x4f98,0x4f7b,0x4f69,0x4f70,0x4f91, - 0x4f6f,0x4f86,0x4f96,0x5118,0x4fd4,0x4fdf,0x4fce,0x4fd8,0x4fdb, - 0x4fd1,0x4fda,0x4fd0,0x4fe4,0x4fe5,0x501a,0x5028,0x5014,0x502a, - 0x5025,0x5005,0x4f1c,0x4ff6,0x5021,0x5029,0x502c,0x4ffe,0x4fef, - 0x5011,0x5006,0x5043,0x5047,0x6703,0x5055,0x5050,0x5048,0x505a, - 0x5056,0x506c,0x5078,0x5080,0x509a,0x5085,0x50b4,0x50b2,0x50c9, - 0x50ca,0x50b3,0x50c2,0x50d6,0x50de,0x50e5,0x50ed,0x50e3,0x50ee, - 0x50f9,0x50f5,0x5109,0x5101,0x5102,0x5116,0x5115,0x5114,0x511a, - 0x5121,0x513a,0x5137,0x513c,0x513b,0x513f,0x5140,0x5152,0x514c, - 0x5154,0x5162,0x7af8,0x5169,0x516a,0x516e,0x5180,0x5182,0x56d8, - 0x518c,0x5189,0x518f,0x5191,0x5193,0x5195,0x5196,0x51a4,0x51a6, - 0x51a2,0x51a9,0x51aa,0x51ab,0x51b3,0x51b1,0x51b2,0x51b0,0x51b5, - 0x51bd,0x51c5,0x51c9,0x51db,0x51e0,0x8655,0x51e9,0x51ed,UDCODE, - 0x51f0,0x51f5,0x51fe,0x5204,0x520b,0x5214,0x520e,0x5227,0x522a, - 0x522e,0x5233,0x5239,0x524f,0x5244,0x524b,0x524c,0x525e,0x5254, - 0x526a,0x5274,0x5269,0x5273,0x527f,0x527d,0x528d,0x5294,0x5292, - 0x5271,0x5288,0x5291,0x8fa8,0x8fa7,0x52ac,0x52ad,0x52bc,0x52b5, - 0x52c1,0x52cd,0x52d7,0x52de,0x52e3,0x52e6,0x98ed,0x52e0,0x52f3, - 0x52f5,0x52f8,0x52f9,0x5306,0x5308,0x7538,0x530d,0x5310,0x530f, - 0x5315,0x531a,0x5323,0x532f,0x5331,0x5333,0x5338,0x5340,0x5346, - 0x5345,0x4e17,0x5349,0x534d,0x51d6,0x535e,0x5369,0x536e,0x5918, - 0x537b,0x5377,0x5382,0x5396,0x53a0,0x53a6,0x53a5,0x53ae,0x53b0, - 0x53b6,0x53c3,0x7c12,0x96d9,0x53df,0x66fc,0x71ee,0x53ee,0x53e8, - 0x53ed,0x53fa,0x5401,0x543d,0x5440,0x542c,0x542d,0x543c,0x542e, - 0x5436,0x5429,0x541d,0x544e,0x548f,0x5475,0x548e,0x545f,0x5471, - 0x5477,0x5470,0x5492,0x547b,0x5480,0x5476,0x5484,0x5490,0x5486, - 0x54c7,0x54a2,0x54b8,0x54a5,0x54ac,0x54c4,0x54c8,0x54a8,0x54ab, - 0x54c2,0x54a4,0x54be,0x54bc,0x54d8,0x54e5,0x54e6,0x550f,0x5514, - 0x54fd,0x54ee,0x54ed,0x54fa,0x54e2,0x5539,0x5540,0x5563,0x554c, - 0x552e,0x555c,0x5545,0x5556,0x5557,0x5538,0x5533,0x555d,0x5599, - 0x5580,0x54af,0x558a,0x559f,0x557b,0x557e,0x5598,0x559e,0x55ae, - 0x557c,0x5583,0x55a9,0x5587,0x55a8,0x55da,0x55c5,0x55df,0x55c4, - 0x55dc,0x55e4,0x55d4,0x5614,0x55f7,0x5616,0x55fe,0x55fd,0x561b, - 0x55f9,0x564e,0x5650,0x71df,0x5634,0x5636,0x5632,0x5638,UDCODE, - 0x566b,0x5664,0x562f,0x566c,0x566a,0x5686,0x5680,0x568a,0x56a0, - 0x5694,0x568f,0x56a5,0x56ae,0x56b6,0x56b4,0x56c2,0x56bc,0x56c1, - 0x56c3,0x56c0,0x56c8,0x56ce,0x56d1,0x56d3,0x56d7,0x56ee,0x56f9, - 0x5700,0x56ff,0x5704,0x5709,0x5708,0x570b,0x570d,0x5713,0x5718, - 0x5716,0x55c7,0x571c,0x5726,0x5737,0x5738,0x574e,0x573b,0x5740, - 0x574f,0x5769,0x57c0,0x5788,0x5761,0x577f,0x5789,0x5793,0x57a0, - 0x57b3,0x57a4,0x57aa,0x57b0,0x57c3,0x57c6,0x57d4,0x57d2,0x57d3, - 0x580a,0x57d6,0x57e3,0x580b,0x5819,0x581d,0x5872,0x5821,0x5862, - 0x584b,0x5870,0x6bc0,0x5852,0x583d,0x5879,0x5885,0x58b9,0x589f, - 0x58ab,0x58ba,0x58de,0x58bb,0x58b8,0x58ae,0x58c5,0x58d3,0x58d1, - 0x58d7,0x58d9,0x58d8,0x58e5,0x58dc,0x58e4,0x58df,0x58ef,0x58fa, - 0x58f9,0x58fb,0x58fc,0x58fd,0x5902,0x590a,0x5910,0x591b,0x68a6, - 0x5925,0x592c,0x592d,0x5932,0x5938,0x593e,0x7ad2,0x5955,0x5950, - 0x594e,0x595a,0x5958,0x5962,0x5960,0x5967,0x596c,0x5969,0x5978, - 0x5981,0x599d,0x4f5e,0x4fab,0x59a3,0x59b2,0x59c6,0x59e8,0x59dc, - 0x598d,0x59d9,0x59da,0x5a25,0x5a1f,0x5a11,0x5a1c,0x5a09,0x5a1a, - 0x5a40,0x5a6c,0x5a49,0x5a35,0x5a36,0x5a62,0x5a6a,0x5a9a,0x5abc, - 0x5abe,0x5acb,0x5ac2,0x5abd,0x5ae3,0x5ad7,0x5ae6,0x5ae9,0x5ad6, - 0x5afa,0x5afb,0x5b0c,0x5b0b,0x5b16,0x5b32,0x5ad0,0x5b2a,0x5b36, - 0x5b3e,0x5b43,0x5b45,0x5b40,0x5b51,0x5b55,0x5b5a,0x5b5b,0x5b65, - 0x5b69,0x5b70,0x5b73,0x5b75,0x5b78,0x6588,0x5b7a,0x5b80,UDCODE, - 0x5b83,0x5ba6,0x5bb8,0x5bc3,0x5bc7,0x5bc9,0x5bd4,0x5bd0,0x5be4, - 0x5be6,0x5be2,0x5bde,0x5be5,0x5beb,0x5bf0,0x5bf6,0x5bf3,0x5c05, - 0x5c07,0x5c08,0x5c0d,0x5c13,0x5c20,0x5c22,0x5c28,0x5c38,0x5c39, - 0x5c41,0x5c46,0x5c4e,0x5c53,0x5c50,0x5c4f,0x5b71,0x5c6c,0x5c6e, - 0x4e62,0x5c76,0x5c79,0x5c8c,0x5c91,0x5c94,0x599b,0x5cab,0x5cbb, - 0x5cb6,0x5cbc,0x5cb7,0x5cc5,0x5cbe,0x5cc7,0x5cd9,0x5ce9,0x5cfd, - 0x5cfa,0x5ced,0x5d8c,0x5cea,0x5d0b,0x5d15,0x5d17,0x5d5c,0x5d1f, - 0x5d1b,0x5d11,0x5d14,0x5d22,0x5d1a,0x5d19,0x5d18,0x5d4c,0x5d52, - 0x5d4e,0x5d4b,0x5d6c,0x5d73,0x5d76,0x5d87,0x5d84,0x5d82,0x5da2, - 0x5d9d,0x5dac,0x5dae,0x5dbd,0x5d90,0x5db7,0x5dbc,0x5dc9,0x5dcd, - 0x5dd3,0x5dd2,0x5dd6,0x5ddb,0x5deb,0x5df2,0x5df5,0x5e0b,0x5e1a, - 0x5e19,0x5e11,0x5e1b,0x5e36,0x5e37,0x5e44,0x5e43,0x5e40,0x5e4e, - 0x5e57,0x5e54,0x5e5f,0x5e62,0x5e64,0x5e47,0x5e75,0x5e76,0x5e7a, - 0x9ebc,0x5e7f,0x5ea0,0x5ec1,0x5ec2,0x5ec8,0x5ed0,0x5ecf,0x5ed6, - 0x5ee3,0x5edd,0x5eda,0x5edb,0x5ee2,0x5ee1,0x5ee8,0x5ee9,0x5eec, - 0x5ef1,0x5ef3,0x5ef0,0x5ef4,0x5ef8,0x5efe,0x5f03,0x5f09,0x5f5d, - 0x5f5c,0x5f0b,0x5f11,0x5f16,0x5f29,0x5f2d,0x5f38,0x5f41,0x5f48, - 0x5f4c,0x5f4e,0x5f2f,0x5f51,0x5f56,0x5f57,0x5f59,0x5f61,0x5f6d, - 0x5f73,0x5f77,0x5f83,0x5f82,0x5f7f,0x5f8a,0x5f88,0x5f91,0x5f87, - 0x5f9e,0x5f99,0x5f98,0x5fa0,0x5fa8,0x5fad,0x5fbc,0x5fd6,0x5ffb, - 0x5fe4,0x5ff8,0x5ff1,0x5fdd,0x60b3,0x5fff,0x6021,0x6060,UDCODE, - 0x6019,0x6010,0x6029,0x600e,0x6031,0x601b,0x6015,0x602b,0x6026, - 0x600f,0x603a,0x605a,0x6041,0x606a,0x6077,0x605f,0x604a,0x6046, - 0x604d,0x6063,0x6043,0x6064,0x6042,0x606c,0x606b,0x6059,0x6081, - 0x608d,0x60e7,0x6083,0x609a,0x6084,0x609b,0x6096,0x6097,0x6092, - 0x60a7,0x608b,0x60e1,0x60b8,0x60e0,0x60d3,0x60b4,0x5ff0,0x60bd, - 0x60c6,0x60b5,0x60d8,0x614d,0x6115,0x6106,0x60f6,0x60f7,0x6100, - 0x60f4,0x60fa,0x6103,0x6121,0x60fb,0x60f1,0x610d,0x610e,0x6147, - 0x613e,0x6128,0x6127,0x614a,0x613f,0x613c,0x612c,0x6134,0x613d, - 0x6142,0x6144,0x6173,0x6177,0x6158,0x6159,0x615a,0x616b,0x6174, - 0x616f,0x6165,0x6171,0x615f,0x615d,0x6153,0x6175,0x6199,0x6196, - 0x6187,0x61ac,0x6194,0x619a,0x618a,0x6191,0x61ab,0x61ae,0x61cc, - 0x61ca,0x61c9,0x61f7,0x61c8,0x61c3,0x61c6,0x61ba,0x61cb,0x7f79, - 0x61cd,0x61e6,0x61e3,0x61f6,0x61fa,0x61f4,0x61ff,0x61fd,0x61fc, - 0x61fe,0x6200,0x6208,0x6209,0x620d,0x620c,0x6214,0x621b,0x621e, - 0x6221,0x622a,0x622e,0x6230,0x6232,0x6233,0x6241,0x624e,0x625e, - 0x6263,0x625b,0x6260,0x6268,0x627c,0x6282,0x6289,0x627e,0x6292, - 0x6293,0x6296,0x62d4,0x6283,0x6294,0x62d7,0x62d1,0x62bb,0x62cf, - 0x62ff,0x62c6,0x64d4,0x62c8,0x62dc,0x62cc,0x62ca,0x62c2,0x62c7, - 0x629b,0x62c9,0x630c,0x62ee,0x62f1,0x6327,0x6302,0x6308,0x62ef, - 0x62f5,0x6350,0x633e,0x634d,0x641c,0x634f,0x6396,0x638e,0x6380, - 0x63ab,0x6376,0x63a3,0x638f,0x6389,0x639f,0x63b5,0x636b,UDCODE, - 0x6369,0x63be,0x63e9,0x63c0,0x63c6,0x63e3,0x63c9,0x63d2,0x63f6, - 0x63c4,0x6416,0x6434,0x6406,0x6413,0x6426,0x6436,0x651d,0x6417, - 0x6428,0x640f,0x6467,0x646f,0x6476,0x644e,0x652a,0x6495,0x6493, - 0x64a5,0x64a9,0x6488,0x64bc,0x64da,0x64d2,0x64c5,0x64c7,0x64bb, - 0x64d8,0x64c2,0x64f1,0x64e7,0x8209,0x64e0,0x64e1,0x62ac,0x64e3, - 0x64ef,0x652c,0x64f6,0x64f4,0x64f2,0x64fa,0x6500,0x64fd,0x6518, - 0x651c,0x6505,0x6524,0x6523,0x652b,0x6534,0x6535,0x6537,0x6536, - 0x6538,0x754b,0x6548,0x6556,0x6555,0x654d,0x6558,0x655e,0x655d, - 0x6572,0x6578,0x6582,0x6583,0x8b8a,0x659b,0x659f,0x65ab,0x65b7, - 0x65c3,0x65c6,0x65c1,0x65c4,0x65cc,0x65d2,0x65db,0x65d9,0x65e0, - 0x65e1,0x65f1,0x6772,0x660a,0x6603,0x65fb,0x6773,0x6635,0x6636, - 0x6634,0x661c,0x664f,0x6644,0x6649,0x6641,0x665e,0x665d,0x6664, - 0x6667,0x6668,0x665f,0x6662,0x6670,0x6683,0x6688,0x668e,0x6689, - 0x6684,0x6698,0x669d,0x66c1,0x66b9,0x66c9,0x66be,0x66bc,0x66c4, - 0x66b8,0x66d6,0x66da,0x66e0,0x663f,0x66e6,0x66e9,0x66f0,0x66f5, - 0x66f7,0x670f,0x6716,0x671e,0x6726,0x6727,0x9738,0x672e,0x673f, - 0x6736,0x6741,0x6738,0x6737,0x6746,0x675e,0x6760,0x6759,0x6763, - 0x6764,0x6789,0x6770,0x67a9,0x677c,0x676a,0x678c,0x678b,0x67a6, - 0x67a1,0x6785,0x67b7,0x67ef,0x67b4,0x67ec,0x67b3,0x67e9,0x67b8, - 0x67e4,0x67de,0x67dd,0x67e2,0x67ee,0x67b9,0x67ce,0x67c6,0x67e7, - 0x6a9c,0x681e,0x6846,0x6829,0x6840,0x684d,0x6832,0x684e,UDCODE, - 0x68b3,0x682b,0x6859,0x6863,0x6877,0x687f,0x689f,0x688f,0x68ad, - 0x6894,0x689d,0x689b,0x6883,0x6aae,0x68b9,0x6874,0x68b5,0x68a0, - 0x68ba,0x690f,0x688d,0x687e,0x6901,0x68ca,0x6908,0x68d8,0x6922, - 0x6926,0x68e1,0x690c,0x68cd,0x68d4,0x68e7,0x68d5,0x6936,0x6912, - 0x6904,0x68d7,0x68e3,0x6925,0x68f9,0x68e0,0x68ef,0x6928,0x692a, - 0x691a,0x6923,0x6921,0x68c6,0x6979,0x6977,0x695c,0x6978,0x696b, - 0x6954,0x697e,0x696e,0x6939,0x6974,0x693d,0x6959,0x6930,0x6961, - 0x695e,0x695d,0x6981,0x696a,0x69b2,0x69ae,0x69d0,0x69bf,0x69c1, - 0x69d3,0x69be,0x69ce,0x5be8,0x69ca,0x69dd,0x69bb,0x69c3,0x69a7, - 0x6a2e,0x6991,0x69a0,0x699c,0x6995,0x69b4,0x69de,0x69e8,0x6a02, - 0x6a1b,0x69ff,0x6b0a,0x69f9,0x69f2,0x69e7,0x6a05,0x69b1,0x6a1e, - 0x69ed,0x6a14,0x69eb,0x6a0a,0x6a12,0x6ac1,0x6a23,0x6a13,0x6a44, - 0x6a0c,0x6a72,0x6a36,0x6a78,0x6a47,0x6a62,0x6a59,0x6a66,0x6a48, - 0x6a38,0x6a22,0x6a90,0x6a8d,0x6aa0,0x6a84,0x6aa2,0x6aa3,0x6a97, - 0x8617,0x6abb,0x6ac3,0x6ac2,0x6ab8,0x6ab3,0x6aac,0x6ade,0x6ad1, - 0x6adf,0x6aaa,0x6ada,0x6aea,0x6afb,0x6b05,0x8616,0x6afa,0x6b12, - 0x6b16,0x9b31,0x6b1f,0x6b38,0x6b37,0x76dc,0x6b39,0x98ee,0x6b47, - 0x6b43,0x6b49,0x6b50,0x6b59,0x6b54,0x6b5b,0x6b5f,0x6b61,0x6b78, - 0x6b79,0x6b7f,0x6b80,0x6b84,0x6b83,0x6b8d,0x6b98,0x6b95,0x6b9e, - 0x6ba4,0x6baa,0x6bab,0x6baf,0x6bb2,0x6bb1,0x6bb3,0x6bb7,0x6bbc, - 0x6bc6,0x6bcb,0x6bd3,0x6bdf,0x6bec,0x6beb,0x6bf3,0x6bef,UDCODE, - 0x9ebe,0x6c08,0x6c13,0x6c14,0x6c1b,0x6c24,0x6c23,0x6c5e,0x6c55, - 0x6c62,0x6c6a,0x6c82,0x6c8d,0x6c9a,0x6c81,0x6c9b,0x6c7e,0x6c68, - 0x6c73,0x6c92,0x6c90,0x6cc4,0x6cf1,0x6cd3,0x6cbd,0x6cd7,0x6cc5, - 0x6cdd,0x6cae,0x6cb1,0x6cbe,0x6cba,0x6cdb,0x6cef,0x6cd9,0x6cea, - 0x6d1f,0x884d,0x6d36,0x6d2b,0x6d3d,0x6d38,0x6d19,0x6d35,0x6d33, - 0x6d12,0x6d0c,0x6d63,0x6d93,0x6d64,0x6d5a,0x6d79,0x6d59,0x6d8e, - 0x6d95,0x6fe4,0x6d85,0x6df9,0x6e15,0x6e0a,0x6db5,0x6dc7,0x6de6, - 0x6db8,0x6dc6,0x6dec,0x6dde,0x6dcc,0x6de8,0x6dd2,0x6dc5,0x6dfa, - 0x6dd9,0x6de4,0x6dd5,0x6dea,0x6dee,0x6e2d,0x6e6e,0x6e2e,0x6e19, - 0x6e72,0x6e5f,0x6e3e,0x6e23,0x6e6b,0x6e2b,0x6e76,0x6e4d,0x6e1f, - 0x6e43,0x6e3a,0x6e4e,0x6e24,0x6eff,0x6e1d,0x6e38,0x6e82,0x6eaa, - 0x6e98,0x6ec9,0x6eb7,0x6ed3,0x6ebd,0x6eaf,0x6ec4,0x6eb2,0x6ed4, - 0x6ed5,0x6e8f,0x6ea5,0x6ec2,0x6e9f,0x6f41,0x6f11,0x704c,0x6eec, - 0x6ef8,0x6efe,0x6f3f,0x6ef2,0x6f31,0x6eef,0x6f32,0x6ecc,0x6f3e, - 0x6f13,0x6ef7,0x6f86,0x6f7a,0x6f78,0x6f81,0x6f80,0x6f6f,0x6f5b, - 0x6ff3,0x6f6d,0x6f82,0x6f7c,0x6f58,0x6f8e,0x6f91,0x6fc2,0x6f66, - 0x6fb3,0x6fa3,0x6fa1,0x6fa4,0x6fb9,0x6fc6,0x6faa,0x6fdf,0x6fd5, - 0x6fec,0x6fd4,0x6fd8,0x6ff1,0x6fee,0x6fdb,0x7009,0x700b,0x6ffa, - 0x7011,0x7001,0x700f,0x6ffe,0x701b,0x701a,0x6f74,0x701d,0x7018, - 0x701f,0x7030,0x703e,0x7032,0x7051,0x7063,0x7099,0x7092,0x70af, - 0x70f1,0x70ac,0x70b8,0x70b3,0x70ae,0x70df,0x70cb,0x70dd,UDCODE, - 0x70d9,0x7109,0x70fd,0x711c,0x7119,0x7165,0x7155,0x7188,0x7166, - 0x7162,0x714c,0x7156,0x716c,0x718f,0x71fb,0x7184,0x7195,0x71a8, - 0x71ac,0x71d7,0x71b9,0x71be,0x71d2,0x71c9,0x71d4,0x71ce,0x71e0, - 0x71ec,0x71e7,0x71f5,0x71fc,0x71f9,0x71ff,0x720d,0x7210,0x721b, - 0x7228,0x722d,0x722c,0x7230,0x7232,0x723b,0x723c,0x723f,0x7240, - 0x7246,0x724b,0x7258,0x7274,0x727e,0x7282,0x7281,0x7287,0x7292, - 0x7296,0x72a2,0x72a7,0x72b9,0x72b2,0x72c3,0x72c6,0x72c4,0x72ce, - 0x72d2,0x72e2,0x72e0,0x72e1,0x72f9,0x72f7,0x500f,0x7317,0x730a, - 0x731c,0x7316,0x731d,0x7334,0x732f,0x7329,0x7325,0x733e,0x734e, - 0x734f,0x9ed8,0x7357,0x736a,0x7368,0x7370,0x7378,0x7375,0x737b, - 0x737a,0x73c8,0x73b3,0x73ce,0x73bb,0x73c0,0x73e5,0x73ee,0x73de, - 0x74a2,0x7405,0x746f,0x7425,0x73f8,0x7432,0x743a,0x7455,0x743f, - 0x745f,0x7459,0x7441,0x745c,0x7469,0x7470,0x7463,0x746a,0x7476, - 0x747e,0x748b,0x749e,0x74a7,0x74ca,0x74cf,0x74d4,0x73f1,0x74e0, - 0x74e3,0x74e7,0x74e9,0x74ee,0x74f2,0x74f0,0x74f1,0x74f8,0x74f7, - 0x7504,0x7503,0x7505,0x750c,0x750e,0x750d,0x7515,0x7513,0x751e, - 0x7526,0x752c,0x753c,0x7544,0x754d,0x754a,0x7549,0x755b,0x7546, - 0x755a,0x7569,0x7564,0x7567,0x756b,0x756d,0x7578,0x7576,0x7586, - 0x7587,0x7574,0x758a,0x7589,0x7582,0x7594,0x759a,0x759d,0x75a5, - 0x75a3,0x75c2,0x75b3,0x75c3,0x75b5,0x75bd,0x75b8,0x75bc,0x75b1, - 0x75cd,0x75ca,0x75d2,0x75d9,0x75e3,0x75de,0x75fe,0x75ff,UDCODE, - 0x75fc,0x7601,0x75f0,0x75fa,0x75f2,0x75f3,0x760b,0x760d,0x7609, - 0x761f,0x7627,0x7620,0x7621,0x7622,0x7624,0x7634,0x7630,0x763b, - 0x7647,0x7648,0x7646,0x765c,0x7658,0x7661,0x7662,0x7668,0x7669, - 0x766a,0x7667,0x766c,0x7670,0x7672,0x7676,0x7678,0x767c,0x7680, - 0x7683,0x7688,0x768b,0x768e,0x7696,0x7693,0x7699,0x769a,0x76b0, - 0x76b4,0x76b8,0x76b9,0x76ba,0x76c2,0x76cd,0x76d6,0x76d2,0x76de, - 0x76e1,0x76e5,0x76e7,0x76ea,0x862f,0x76fb,0x7708,0x7707,0x7704, - 0x7729,0x7724,0x771e,0x7725,0x7726,0x771b,0x7737,0x7738,0x7747, - 0x775a,0x7768,0x776b,0x775b,0x7765,0x777f,0x777e,0x7779,0x778e, - 0x778b,0x7791,0x77a0,0x779e,0x77b0,0x77b6,0x77b9,0x77bf,0x77bc, - 0x77bd,0x77bb,0x77c7,0x77cd,0x77d7,0x77da,0x77dc,0x77e3,0x77ee, - 0x77fc,0x780c,0x7812,0x7926,0x7820,0x792a,0x7845,0x788e,0x7874, - 0x7886,0x787c,0x789a,0x788c,0x78a3,0x78b5,0x78aa,0x78af,0x78d1, - 0x78c6,0x78cb,0x78d4,0x78be,0x78bc,0x78c5,0x78ca,0x78ec,0x78e7, - 0x78da,0x78fd,0x78f4,0x7907,0x7912,0x7911,0x7919,0x792c,0x792b, - 0x7940,0x7960,0x7957,0x795f,0x795a,0x7955,0x7953,0x797a,0x797f, - 0x798a,0x799d,0x79a7,0x9f4b,0x79aa,0x79ae,0x79b3,0x79b9,0x79ba, - 0x79c9,0x79d5,0x79e7,0x79ec,0x79e1,0x79e3,0x7a08,0x7a0d,0x7a18, - 0x7a19,0x7a20,0x7a1f,0x7980,0x7a31,0x7a3b,0x7a3e,0x7a37,0x7a43, - 0x7a57,0x7a49,0x7a61,0x7a62,0x7a69,0x9f9d,0x7a70,0x7a79,0x7a7d, - 0x7a88,0x7a97,0x7a95,0x7a98,0x7a96,0x7aa9,0x7ac8,0x7ab0,UDCODE, - 0x7ab6,0x7ac5,0x7ac4,0x7abf,0x9083,0x7ac7,0x7aca,0x7acd,0x7acf, - 0x7ad5,0x7ad3,0x7ad9,0x7ada,0x7add,0x7ae1,0x7ae2,0x7ae6,0x7aed, - 0x7af0,0x7b02,0x7b0f,0x7b0a,0x7b06,0x7b33,0x7b18,0x7b19,0x7b1e, - 0x7b35,0x7b28,0x7b36,0x7b50,0x7b7a,0x7b04,0x7b4d,0x7b0b,0x7b4c, - 0x7b45,0x7b75,0x7b65,0x7b74,0x7b67,0x7b70,0x7b71,0x7b6c,0x7b6e, - 0x7b9d,0x7b98,0x7b9f,0x7b8d,0x7b9c,0x7b9a,0x7b8b,0x7b92,0x7b8f, - 0x7b5d,0x7b99,0x7bcb,0x7bc1,0x7bcc,0x7bcf,0x7bb4,0x7bc6,0x7bdd, - 0x7be9,0x7c11,0x7c14,0x7be6,0x7be5,0x7c60,0x7c00,0x7c07,0x7c13, - 0x7bf3,0x7bf7,0x7c17,0x7c0d,0x7bf6,0x7c23,0x7c27,0x7c2a,0x7c1f, - 0x7c37,0x7c2b,0x7c3d,0x7c4c,0x7c43,0x7c54,0x7c4f,0x7c40,0x7c50, - 0x7c58,0x7c5f,0x7c64,0x7c56,0x7c65,0x7c6c,0x7c75,0x7c83,0x7c90, - 0x7ca4,0x7cad,0x7ca2,0x7cab,0x7ca1,0x7ca8,0x7cb3,0x7cb2,0x7cb1, - 0x7cae,0x7cb9,0x7cbd,0x7cc0,0x7cc5,0x7cc2,0x7cd8,0x7cd2,0x7cdc, - 0x7ce2,0x9b3b,0x7cef,0x7cf2,0x7cf4,0x7cf6,0x7cfa,0x7d06,0x7d02, - 0x7d1c,0x7d15,0x7d0a,0x7d45,0x7d4b,0x7d2e,0x7d32,0x7d3f,0x7d35, - 0x7d46,0x7d73,0x7d56,0x7d4e,0x7d72,0x7d68,0x7d6e,0x7d4f,0x7d63, - 0x7d93,0x7d89,0x7d5b,0x7d8f,0x7d7d,0x7d9b,0x7dba,0x7dae,0x7da3, - 0x7db5,0x7dc7,0x7dbd,0x7dab,0x7e3d,0x7da2,0x7daf,0x7ddc,0x7db8, - 0x7d9f,0x7db0,0x7dd8,0x7ddd,0x7de4,0x7dde,0x7dfb,0x7df2,0x7de1, - 0x7e05,0x7e0a,0x7e23,0x7e21,0x7e12,0x7e31,0x7e1f,0x7e09,0x7e0b, - 0x7e22,0x7e46,0x7e66,0x7e3b,0x7e35,0x7e39,0x7e43,0x7e37,UDCODE, - 0x7e32,0x7e3a,0x7e67,0x7e5d,0x7e56,0x7e5e,0x7e59,0x7e5a,0x7e79, - 0x7e6a,0x7e69,0x7e7c,0x7e7b,0x7e83,0x7dd5,0x7e7d,0x8fae,0x7e7f, - 0x7e88,0x7e89,0x7e8c,0x7e92,0x7e90,0x7e93,0x7e94,0x7e96,0x7e8e, - 0x7e9b,0x7e9c,0x7f38,0x7f3a,0x7f45,0x7f4c,0x7f4d,0x7f4e,0x7f50, - 0x7f51,0x7f55,0x7f54,0x7f58,0x7f5f,0x7f60,0x7f68,0x7f69,0x7f67, - 0x7f78,0x7f82,0x7f86,0x7f83,0x7f88,0x7f87,0x7f8c,0x7f94,0x7f9e, - 0x7f9d,0x7f9a,0x7fa3,0x7faf,0x7fb2,0x7fb9,0x7fae,0x7fb6,0x7fb8, - 0x8b71,0x7fc5,0x7fc6,0x7fca,0x7fd5,0x7fd4,0x7fe1,0x7fe6,0x7fe9, - 0x7ff3,0x7ff9,0x98dc,0x8006,0x8004,0x800b,0x8012,0x8018,0x8019, - 0x801c,0x8021,0x8028,0x803f,0x803b,0x804a,0x8046,0x8052,0x8058, - 0x805a,0x805f,0x8062,0x8068,0x8073,0x8072,0x8070,0x8076,0x8079, - 0x807d,0x807f,0x8084,0x8086,0x8085,0x809b,0x8093,0x809a,0x80ad, - 0x5190,0x80ac,0x80db,0x80e5,0x80d9,0x80dd,0x80c4,0x80da,0x80d6, - 0x8109,0x80ef,0x80f1,0x811b,0x8129,0x8123,0x812f,0x814b,0x968b, - 0x8146,0x813e,0x8153,0x8151,0x80fc,0x8171,0x816e,0x8165,0x8166, - 0x8174,0x8183,0x8188,0x818a,0x8180,0x8182,0x81a0,0x8195,0x81a4, - 0x81a3,0x815f,0x8193,0x81a9,0x81b0,0x81b5,0x81be,0x81b8,0x81bd, - 0x81c0,0x81c2,0x81ba,0x81c9,0x81cd,0x81d1,0x81d9,0x81d8,0x81c8, - 0x81da,0x81df,0x81e0,0x81e7,0x81fa,0x81fb,0x81fe,0x8201,0x8202, - 0x8205,0x8207,0x820a,0x820d,0x8210,0x8216,0x8229,0x822b,0x8238, - 0x8233,0x8240,0x8259,0x8258,0x825d,0x825a,0x825f,0x8264,UDCODE, - 0x8262,0x8268,0x826a,0x826b,0x822e,0x8271,0x8277,0x8278,0x827e, - 0x828d,0x8292,0x82ab,0x829f,0x82bb,0x82ac,0x82e1,0x82e3,0x82df, - 0x82d2,0x82f4,0x82f3,0x82fa,0x8393,0x8303,0x82fb,0x82f9,0x82de, - 0x8306,0x82dc,0x8309,0x82d9,0x8335,0x8334,0x8316,0x8332,0x8331, - 0x8340,0x8339,0x8350,0x8345,0x832f,0x832b,0x8317,0x8318,0x8385, - 0x839a,0x83aa,0x839f,0x83a2,0x8396,0x8323,0x838e,0x8387,0x838a, - 0x837c,0x83b5,0x8373,0x8375,0x83a0,0x8389,0x83a8,0x83f4,0x8413, - 0x83eb,0x83ce,0x83fd,0x8403,0x83d8,0x840b,0x83c1,0x83f7,0x8407, - 0x83e0,0x83f2,0x840d,0x8422,0x8420,0x83bd,0x8438,0x8506,0x83fb, - 0x846d,0x842a,0x843c,0x855a,0x8484,0x8477,0x846b,0x84ad,0x846e, - 0x8482,0x8469,0x8446,0x842c,0x846f,0x8479,0x8435,0x84ca,0x8462, - 0x84b9,0x84bf,0x849f,0x84d9,0x84cd,0x84bb,0x84da,0x84d0,0x84c1, - 0x84c6,0x84d6,0x84a1,0x8521,0x84ff,0x84f4,0x8517,0x8518,0x852c, - 0x851f,0x8515,0x8514,0x84fc,0x8540,0x8563,0x8558,0x8548,0x8541, - 0x8602,0x854b,0x8555,0x8580,0x85a4,0x8588,0x8591,0x858a,0x85a8, - 0x856d,0x8594,0x859b,0x85ea,0x8587,0x859c,0x8577,0x857e,0x8590, - 0x85c9,0x85ba,0x85cf,0x85b9,0x85d0,0x85d5,0x85dd,0x85e5,0x85dc, - 0x85f9,0x860a,0x8613,0x860b,0x85fe,0x85fa,0x8606,0x8622,0x861a, - 0x8630,0x863f,0x864d,0x4e55,0x8654,0x865f,0x8667,0x8671,0x8693, - 0x86a3,0x86a9,0x86aa,0x868b,0x868c,0x86b6,0x86af,0x86c4,0x86c6, - 0x86b0,0x86c9,0x8823,0x86ab,0x86d4,0x86de,0x86e9,0x86ec,UDCODE, - 0x86df,0x86db,0x86ef,0x8712,0x8706,0x8708,0x8700,0x8703,0x86fb, - 0x8711,0x8709,0x870d,0x86f9,0x870a,0x8734,0x873f,0x8737,0x873b, - 0x8725,0x8729,0x871a,0x8760,0x875f,0x8778,0x874c,0x874e,0x8774, - 0x8757,0x8768,0x876e,0x8759,0x8753,0x8763,0x876a,0x8805,0x87a2, - 0x879f,0x8782,0x87af,0x87cb,0x87bd,0x87c0,0x87d0,0x96d6,0x87ab, - 0x87c4,0x87b3,0x87c7,0x87c6,0x87bb,0x87ef,0x87f2,0x87e0,0x880f, - 0x880d,0x87fe,0x87f6,0x87f7,0x880e,0x87d2,0x8811,0x8816,0x8815, - 0x8822,0x8821,0x8831,0x8836,0x8839,0x8827,0x883b,0x8844,0x8842, - 0x8852,0x8859,0x885e,0x8862,0x886b,0x8881,0x887e,0x889e,0x8875, - 0x887d,0x88b5,0x8872,0x8882,0x8897,0x8892,0x88ae,0x8899,0x88a2, - 0x888d,0x88a4,0x88b0,0x88bf,0x88b1,0x88c3,0x88c4,0x88d4,0x88d8, - 0x88d9,0x88dd,0x88f9,0x8902,0x88fc,0x88f4,0x88e8,0x88f2,0x8904, - 0x890c,0x890a,0x8913,0x8943,0x891e,0x8925,0x892a,0x892b,0x8941, - 0x8944,0x893b,0x8936,0x8938,0x894c,0x891d,0x8960,0x895e,0x8966, - 0x8964,0x896d,0x896a,0x896f,0x8974,0x8977,0x897e,0x8983,0x8988, - 0x898a,0x8993,0x8998,0x89a1,0x89a9,0x89a6,0x89ac,0x89af,0x89b2, - 0x89ba,0x89bd,0x89bf,0x89c0,0x89da,0x89dc,0x89dd,0x89e7,0x89f4, - 0x89f8,0x8a03,0x8a16,0x8a10,0x8a0c,0x8a1b,0x8a1d,0x8a25,0x8a36, - 0x8a41,0x8a5b,0x8a52,0x8a46,0x8a48,0x8a7c,0x8a6d,0x8a6c,0x8a62, - 0x8a85,0x8a82,0x8a84,0x8aa8,0x8aa1,0x8a91,0x8aa5,0x8aa6,0x8a9a, - 0x8aa3,0x8ac4,0x8acd,0x8ac2,0x8ada,0x8aeb,0x8af3,0x8ae7,UDCODE, - 0x8ae4,0x8af1,0x8b14,0x8ae0,0x8ae2,0x8af7,0x8ade,0x8adb,0x8b0c, - 0x8b07,0x8b1a,0x8ae1,0x8b16,0x8b10,0x8b17,0x8b20,0x8b33,0x97ab, - 0x8b26,0x8b2b,0x8b3e,0x8b28,0x8b41,0x8b4c,0x8b4f,0x8b4e,0x8b49, - 0x8b56,0x8b5b,0x8b5a,0x8b6b,0x8b5f,0x8b6c,0x8b6f,0x8b74,0x8b7d, - 0x8b80,0x8b8c,0x8b8e,0x8b92,0x8b93,0x8b96,0x8b99,0x8b9a,0x8c3a, - 0x8c41,0x8c3f,0x8c48,0x8c4c,0x8c4e,0x8c50,0x8c55,0x8c62,0x8c6c, - 0x8c78,0x8c7a,0x8c82,0x8c89,0x8c85,0x8c8a,0x8c8d,0x8c8e,0x8c94, - 0x8c7c,0x8c98,0x621d,0x8cad,0x8caa,0x8cbd,0x8cb2,0x8cb3,0x8cae, - 0x8cb6,0x8cc8,0x8cc1,0x8ce4,0x8ce3,0x8cda,0x8cfd,0x8cfa,0x8cfb, - 0x8d04,0x8d05,0x8d0a,0x8d07,0x8d0f,0x8d0d,0x8d10,0x9f4e,0x8d13, - 0x8ccd,0x8d14,0x8d16,0x8d67,0x8d6d,0x8d71,0x8d73,0x8d81,0x8d99, - 0x8dc2,0x8dbe,0x8dba,0x8dcf,0x8dda,0x8dd6,0x8dcc,0x8ddb,0x8dcb, - 0x8dea,0x8deb,0x8ddf,0x8de3,0x8dfc,0x8e08,0x8e09,0x8dff,0x8e1d, - 0x8e1e,0x8e10,0x8e1f,0x8e42,0x8e35,0x8e30,0x8e34,0x8e4a,0x8e47, - 0x8e49,0x8e4c,0x8e50,0x8e48,0x8e59,0x8e64,0x8e60,0x8e2a,0x8e63, - 0x8e55,0x8e76,0x8e72,0x8e7c,0x8e81,0x8e87,0x8e85,0x8e84,0x8e8b, - 0x8e8a,0x8e93,0x8e91,0x8e94,0x8e99,0x8eaa,0x8ea1,0x8eac,0x8eb0, - 0x8ec6,0x8eb1,0x8ebe,0x8ec5,0x8ec8,0x8ecb,0x8edb,0x8ee3,0x8efc, - 0x8efb,0x8eeb,0x8efe,0x8f0a,0x8f05,0x8f15,0x8f12,0x8f19,0x8f13, - 0x8f1c,0x8f1f,0x8f1b,0x8f0c,0x8f26,0x8f33,0x8f3b,0x8f39,0x8f45, - 0x8f42,0x8f3e,0x8f4c,0x8f49,0x8f46,0x8f4e,0x8f57,0x8f5c,UDCODE, - 0x8f62,0x8f63,0x8f64,0x8f9c,0x8f9f,0x8fa3,0x8fad,0x8faf,0x8fb7, - 0x8fda,0x8fe5,0x8fe2,0x8fea,0x8fef,0x9087,0x8ff4,0x9005,0x8ff9, - 0x8ffa,0x9011,0x9015,0x9021,0x900d,0x901e,0x9016,0x900b,0x9027, - 0x9036,0x9035,0x9039,0x8ff8,0x904f,0x9050,0x9051,0x9052,0x900e, - 0x9049,0x903e,0x9056,0x9058,0x905e,0x9068,0x906f,0x9076,0x96a8, - 0x9072,0x9082,0x907d,0x9081,0x9080,0x908a,0x9089,0x908f,0x90a8, - 0x90af,0x90b1,0x90b5,0x90e2,0x90e4,0x6248,0x90db,0x9102,0x9112, - 0x9119,0x9132,0x9130,0x914a,0x9156,0x9158,0x9163,0x9165,0x9169, - 0x9173,0x9172,0x918b,0x9189,0x9182,0x91a2,0x91ab,0x91af,0x91aa, - 0x91b5,0x91b4,0x91ba,0x91c0,0x91c1,0x91c9,0x91cb,0x91d0,0x91d6, - 0x91df,0x91e1,0x91db,0x91fc,0x91f5,0x91f6,0x921e,0x91ff,0x9214, - 0x922c,0x9215,0x9211,0x925e,0x9257,0x9245,0x9249,0x9264,0x9248, - 0x9295,0x923f,0x924b,0x9250,0x929c,0x9296,0x9293,0x929b,0x925a, - 0x92cf,0x92b9,0x92b7,0x92e9,0x930f,0x92fa,0x9344,0x932e,0x9319, - 0x9322,0x931a,0x9323,0x933a,0x9335,0x933b,0x935c,0x9360,0x937c, - 0x936e,0x9356,0x93b0,0x93ac,0x93ad,0x9394,0x93b9,0x93d6,0x93d7, - 0x93e8,0x93e5,0x93d8,0x93c3,0x93dd,0x93d0,0x93c8,0x93e4,0x941a, - 0x9414,0x9413,0x9403,0x9407,0x9410,0x9436,0x942b,0x9435,0x9421, - 0x943a,0x9441,0x9452,0x9444,0x945b,0x9460,0x9462,0x945e,0x946a, - 0x9229,0x9470,0x9475,0x9477,0x947d,0x945a,0x947c,0x947e,0x9481, - 0x947f,0x9582,0x9587,0x958a,0x9594,0x9596,0x9598,0x9599,UDCODE, - 0x95a0,0x95a8,0x95a7,0x95ad,0x95bc,0x95bb,0x95b9,0x95be,0x95ca, - 0x6ff6,0x95c3,0x95cd,0x95cc,0x95d5,0x95d4,0x95d6,0x95dc,0x95e1, - 0x95e5,0x95e2,0x9621,0x9628,0x962e,0x962f,0x9642,0x964c,0x964f, - 0x964b,0x9677,0x965c,0x965e,0x965d,0x965f,0x9666,0x9672,0x966c, - 0x968d,0x9698,0x9695,0x9697,0x96aa,0x96a7,0x96b1,0x96b2,0x96b0, - 0x96b4,0x96b6,0x96b8,0x96b9,0x96ce,0x96cb,0x96c9,0x96cd,0x894d, - 0x96dc,0x970d,0x96d5,0x96f9,0x9704,0x9706,0x9708,0x9713,0x970e, - 0x9711,0x970f,0x9716,0x9719,0x9724,0x972a,0x9730,0x9739,0x973d, - 0x973e,0x9744,0x9746,0x9748,0x9742,0x9749,0x975c,0x9760,0x9764, - 0x9766,0x9768,0x52d2,0x976b,0x9771,0x9779,0x9785,0x977c,0x9781, - 0x977a,0x9786,0x978b,0x978f,0x9790,0x979c,0x97a8,0x97a6,0x97a3, - 0x97b3,0x97b4,0x97c3,0x97c6,0x97c8,0x97cb,0x97dc,0x97ed,0x9f4f, - 0x97f2,0x7adf,0x97f6,0x97f5,0x980f,0x980c,0x9838,0x9824,0x9821, - 0x9837,0x983d,0x9846,0x984f,0x984b,0x986b,0x986f,0x9870,0x9871, - 0x9874,0x9873,0x98aa,0x98af,0x98b1,0x98b6,0x98c4,0x98c3,0x98c6, - 0x98e9,0x98eb,0x9903,0x9909,0x9912,0x9914,0x9918,0x9921,0x991d, - 0x991e,0x9924,0x9920,0x992c,0x992e,0x993d,0x993e,0x9942,0x9949, - 0x9945,0x9950,0x994b,0x9951,0x9952,0x994c,0x9955,0x9997,0x9998, - 0x99a5,0x99ad,0x99ae,0x99bc,0x99df,0x99db,0x99dd,0x99d8,0x99d1, - 0x99ed,0x99ee,0x99f1,0x99f2,0x99fb,0x99f8,0x9a01,0x9a0f,0x9a05, - 0x99e2,0x9a19,0x9a2b,0x9a37,0x9a45,0x9a42,0x9a40,0x9a43,UDCODE, - 0x9a3e,0x9a55,0x9a4d,0x9a5b,0x9a57,0x9a5f,0x9a62,0x9a65,0x9a64, - 0x9a69,0x9a6b,0x9a6a,0x9aad,0x9ab0,0x9abc,0x9ac0,0x9acf,0x9ad1, - 0x9ad3,0x9ad4,0x9ade,0x9adf,0x9ae2,0x9ae3,0x9ae6,0x9aef,0x9aeb, - 0x9aee,0x9af4,0x9af1,0x9af7,0x9afb,0x9b06,0x9b18,0x9b1a,0x9b1f, - 0x9b22,0x9b23,0x9b25,0x9b27,0x9b28,0x9b29,0x9b2a,0x9b2e,0x9b2f, - 0x9b32,0x9b44,0x9b43,0x9b4f,0x9b4d,0x9b4e,0x9b51,0x9b58,0x9b74, - 0x9b93,0x9b83,0x9b91,0x9b96,0x9b97,0x9b9f,0x9ba0,0x9ba8,0x9bb4, - 0x9bc0,0x9bca,0x9bb9,0x9bc6,0x9bcf,0x9bd1,0x9bd2,0x9be3,0x9be2, - 0x9be4,0x9bd4,0x9be1,0x9c3a,0x9bf2,0x9bf1,0x9bf0,0x9c15,0x9c14, - 0x9c09,0x9c13,0x9c0c,0x9c06,0x9c08,0x9c12,0x9c0a,0x9c04,0x9c2e, - 0x9c1b,0x9c25,0x9c24,0x9c21,0x9c30,0x9c47,0x9c32,0x9c46,0x9c3e, - 0x9c5a,0x9c60,0x9c67,0x9c76,0x9c78,0x9ce7,0x9cec,0x9cf0,0x9d09, - 0x9d08,0x9ceb,0x9d03,0x9d06,0x9d2a,0x9d26,0x9daf,0x9d23,0x9d1f, - 0x9d44,0x9d15,0x9d12,0x9d41,0x9d3f,0x9d3e,0x9d46,0x9d48,0x9d5d, - 0x9d5e,0x9d64,0x9d51,0x9d50,0x9d59,0x9d72,0x9d89,0x9d87,0x9dab, - 0x9d6f,0x9d7a,0x9d9a,0x9da4,0x9da9,0x9db2,0x9dc4,0x9dc1,0x9dbb, - 0x9db8,0x9dba,0x9dc6,0x9dcf,0x9dc2,0x9dd9,0x9dd3,0x9df8,0x9de6, - 0x9ded,0x9def,0x9dfd,0x9e1a,0x9e1b,0x9e1e,0x9e75,0x9e79,0x9e7d, - 0x9e81,0x9e88,0x9e8b,0x9e8c,0x9e92,0x9e95,0x9e91,0x9e9d,0x9ea5, - 0x9ea9,0x9eb8,0x9eaa,0x9ead,0x9761,0x9ecc,0x9ece,0x9ecf,0x9ed0, - 0x9ed4,0x9edc,0x9ede,0x9edd,0x9ee0,0x9ee5,0x9ee8,0x9eef,UDCODE, - 0x9ef4,0x9ef6,0x9ef7,0x9ef9,0x9efb,0x9efc,0x9efd,0x9f07,0x9f08, - 0x76b7,0x9f15,0x9f21,0x9f2c,0x9f3e,0x9f4a,0x9f52,0x9f54,0x9f63, - 0x9f5f,0x9f60,0x9f61,0x9f66,0x9f67,0x9f6c,0x9f6a,0x9f77,0x9f72, - 0x9f76,0x9f95,0x9f9c,0x9fa0,0x582f,0x69c7,0x9059,0x7464,0x51dc, - 0x7199,0x7e8a,0x891c,0x9348,0x9288,0x84dc,0x4fc9,0x70bb,0x6631, - 0x68c8,0x92f9,0x66fb,0x5f45,0x4e28,0x4ee1,0x4efc,0x4f00,0x4f03, - 0x4f39,0x4f56,0x4f92,0x4f8a,0x4f9a,0x4f94,0x4fcd,0x5040,0x5022, - 0x4fff,0x501e,0x5046,0x5070,0x5042,0x5094,0x50f4,0x50d8,0x514a, - 0x5164,0x519d,0x51be,0x51ec,0x5215,0x529c,0x52a6,0x52c0,0x52db, - 0x5300,0x5307,0x5324,0x5372,0x5393,0x53b2,0x53dd,0xfa0e,0x549c, - 0x548a,0x54a9,0x54ff,0x5586,0x5759,0x5765,0x57ac,0x57c8,0x57c7, - 0xfa0f,UDCODE,0xfa10,0x589e,0x58b2,0x590b,0x5953,0x595b,0x595d, - 0x5963,0x59a4,0x59ba,0x5b56,0x5bc0,0x752f,0x5bd8,0x5bec,0x5c1e, - 0x5ca6,0x5cba,0x5cf5,0x5d27,0x5d53,0xfa11,0x5d42,0x5d6d,0x5db8, - 0x5db9,0x5dd0,0x5f21,0x5f34,0x5f67,0x5fb7,0x5fde,0x605d,0x6085, - 0x608a,0x60de,0x60d5,0x6120,0x60f2,0x6111,0x6137,0x6130,0x6198, - 0x6213,0x62a6,0x63f5,0x6460,0x649d,0x64ce,0x654e,0x6600,0x6615, - 0x663b,0x6609,0x662e,0x661e,0x6624,0x6665,0x6657,0x6659,0xfa12, - 0x6673,0x6699,0x66a0,0x66b2,0x66bf,0x66fa,0x670e,0xf929,0x6766, - 0x67bb,0x6852,0x67c0,0x6801,0x6844,0x68cf,0xfa13,0x6968,0xfa14, - 0x6998,0x69e2,0x6a30,0x6a6b,0x6a46,0x6a73,0x6a7e,0x6ae2,0x6ae4, - 0x6bd6,0x6c3f,0x6c5c,0x6c86,0x6c6f,0x6cda,0x6d04,0x6d87,0x6d6f, - 0x6d96,0x6dac,0x6dcf,0x6df8,0x6df2,0x6dfc,0x6e39,0x6e5c,0x6e27, - 0x6e3c,0x6ebf,0x6f88,0x6fb5,0x6ff5,0x7005,0x7007,0x7028,0x7085, - 0x70ab,0x710f,0x7104,0x715c,0x7146,0x7147,0xfa15,0x71c1,0x71fe, - 0x72b1,0x72be,0x7324,0xfa16,0x7377,0x73bd,0x73c9,0x73d6,0x73e3, - 0x73d2,0x7407,0x73f5,0x7426,0x742a,0x7429,0x742e,0x7462,0x7489, - 0x749f,0x7501,0x756f,0x7682,0x769c,0x769e,0x769b,0x76a6,0xfa17, - 0x7746,0x52af,0x7821,0x784e,0x7864,0x787a,0x7930,0xfa18,0xfa19, - 0xfa1a,0x7994,0xfa1b,0x799b,0x7ad1,0x7ae7,0xfa1c,0x7aeb,0x7b9e, - 0xfa1d,0x7d48,0x7d5c,0x7db7,0x7da0,0x7dd6,0x7e52,0x7f47,0x7fa1, - 0xfa1e,0x8301,0x8362,0x837f,0x83c7,0x83f6,0x8448,0x84b4,0x8553, - 0x8559,UDCODE,0x856b,0xfa1f,0x85b0,0xfa20,0xfa21,0x8807,0x88f5, - 0x8a12,0x8a37,0x8a79,0x8aa7,0x8abe,0x8adf,0xfa22,0x8af6,0x8b53, - 0x8b7f,0x8cf0,0x8cf4,0x8d12,0x8d76,0xfa23,0x8ecf,0xfa24,0xfa25, - 0x9067,0x90de,0xfa26,0x9115,0x9127,0x91da,0x91d7,0x91de,0x91ed, - 0x91ee,0x91e4,0x91e5,0x9206,0x9210,0x920a,0x923a,0x9240,0x923c, - 0x924e,0x9259,0x9251,0x9239,0x9267,0x92a7,0x9277,0x9278,0x92e7, - 0x92d7,0x92d9,0x92d0,0xfa27,0x92d5,0x92e0,0x92d3,0x9325,0x9321, - 0x92fb,0xfa28,0x931e,0x92ff,0x931d,0x9302,0x9370,0x9357,0x93a4, - 0x93c6,0x93de,0x93f8,0x9431,0x9445,0x9448,0x9592,0xf9dc,0xfa29, - 0x969d,0x96af,0x9733,0x973b,0x9743,0x974d,0x974f,0x9751,0x9755, - 0x9857,0x9865,0xfa2a,0xfa2b,0x9927,0xfa2c,0x999e,0x9a4e,0x9ad9, - 0x9adc,0x9b75,0x9b72,0x9b8f,0x9bb1,0x9bbb,0x9c00,0x9d70,0x9d6b, - 0xfa2d,0x9e19,0x9ed1,UDCODE,UDCODE,0x2170,0x2171,0x2172,0x2173, - 0x2174,0x2175,0x2176,0x2177,0x2178,0x2179,0xffe2,0xffe4,0xff07, - 0xff02,0xe000,0xe001,0xe002,0xe003,0xe004,0xe005,0xe006,0xe007, - 0xe008,0xe009,0xe00a,0xe00b,0xe00c,0xe00d,0xe00e,0xe00f,0xe010, - 0xe011,0xe012,0xe013,0xe014,0xe015,0xe016,0xe017,0xe018,0xe019, - 0xe01a,0xe01b,0xe01c,0xe01d,0xe01e,0xe01f,0xe020,0xe021,0xe022, - 0xe023,0xe024,0xe025,0xe026,0xe027,0xe028,0xe029,0xe02a,0xe02b, - 0xe02c,0xe02d,0xe02e,0xe02f,0xe030,0xe031,0xe032,0xe033,0xe034, - 0xe035,0xe036,0xe037,0xe038,0xe039,0xe03a,0xe03b,0xe03c,0xe03d, - 0xe03e,UDCODE,0xe03f,0xe040,0xe041,0xe042,0xe043,0xe044,0xe045, - 0xe046,0xe047,0xe048,0xe049,0xe04a,0xe04b,0xe04c,0xe04d,0xe04e, - 0xe04f,0xe050,0xe051,0xe052,0xe053,0xe054,0xe055,0xe056,0xe057, - 0xe058,0xe059,0xe05a,0xe05b,0xe05c,0xe05d,0xe05e,0xe05f,0xe060, - 0xe061,0xe062,0xe063,0xe064,0xe065,0xe066,0xe067,0xe068,0xe069, - 0xe06a,0xe06b,0xe06c,0xe06d,0xe06e,0xe06f,0xe070,0xe071,0xe072, - 0xe073,0xe074,0xe075,0xe076,0xe077,0xe078,0xe079,0xe07a,0xe07b, - 0xe07c,0xe07d,0xe07e,0xe07f,0xe080,0xe081,0xe082,0xe083,0xe084, - 0xe085,0xe086,0xe087,0xe088,0xe089,0xe08a,0xe08b,0xe08c,0xe08d, - 0xe08e,0xe08f,0xe090,0xe091,0xe092,0xe093,0xe094,0xe095,0xe096, - 0xe097,0xe098,0xe099,0xe09a,0xe09b,0xe09c,0xe09d,0xe09e,0xe09f, - 0xe0a0,0xe0a1,0xe0a2,0xe0a3,0xe0a4,0xe0a5,0xe0a6,0xe0a7,0xe0a8, - 0xe0a9,0xe0aa,0xe0ab,0xe0ac,0xe0ad,0xe0ae,0xe0af,0xe0b0,0xe0b1, - 0xe0b2,0xe0b3,0xe0b4,0xe0b5,0xe0b6,0xe0b7,0xe0b8,0xe0b9,0xe0ba, - 0xe0bb,0xe0bc,0xe0bd,0xe0be,0xe0bf,0xe0c0,0xe0c1,0xe0c2,0xe0c3, - 0xe0c4,0xe0c5,0xe0c6,0xe0c7,0xe0c8,0xe0c9,0xe0ca,0xe0cb,0xe0cc, - 0xe0cd,0xe0ce,0xe0cf,0xe0d0,0xe0d1,0xe0d2,0xe0d3,0xe0d4,0xe0d5, - 0xe0d6,0xe0d7,0xe0d8,0xe0d9,0xe0da,0xe0db,0xe0dc,0xe0dd,0xe0de, - 0xe0df,0xe0e0,0xe0e1,0xe0e2,0xe0e3,0xe0e4,0xe0e5,0xe0e6,0xe0e7, - 0xe0e8,0xe0e9,0xe0ea,0xe0eb,0xe0ec,0xe0ed,0xe0ee,0xe0ef,0xe0f0, - 0xe0f1,0xe0f2,0xe0f3,0xe0f4,0xe0f5,0xe0f6,0xe0f7,0xe0f8,0xe0f9, - 0xe0fa,UDCODE,0xe0fb,0xe0fc,0xe0fd,0xe0fe,0xe0ff,0xe100,0xe101, - 0xe102,0xe103,0xe104,0xe105,0xe106,0xe107,0xe108,0xe109,0xe10a, - 0xe10b,0xe10c,0xe10d,0xe10e,0xe10f,0xe110,0xe111,0xe112,0xe113, - 0xe114,0xe115,0xe116,0xe117,0xe118,0xe119,0xe11a,0xe11b,0xe11c, - 0xe11d,0xe11e,0xe11f,0xe120,0xe121,0xe122,0xe123,0xe124,0xe125, - 0xe126,0xe127,0xe128,0xe129,0xe12a,0xe12b,0xe12c,0xe12d,0xe12e, - 0xe12f,0xe130,0xe131,0xe132,0xe133,0xe134,0xe135,0xe136,0xe137, - 0xe138,0xe139,0xe13a,0xe13b,0xe13c,0xe13d,0xe13e,0xe13f,0xe140, - 0xe141,0xe142,0xe143,0xe144,0xe145,0xe146,0xe147,0xe148,0xe149, - 0xe14a,0xe14b,0xe14c,0xe14d,0xe14e,0xe14f,0xe150,0xe151,0xe152, - 0xe153,0xe154,0xe155,0xe156,0xe157,0xe158,0xe159,0xe15a,0xe15b, - 0xe15c,0xe15d,0xe15e,0xe15f,0xe160,0xe161,0xe162,0xe163,0xe164, - 0xe165,0xe166,0xe167,0xe168,0xe169,0xe16a,0xe16b,0xe16c,0xe16d, - 0xe16e,0xe16f,0xe170,0xe171,0xe172,0xe173,0xe174,0xe175,0xe176, - 0xe177,0xe178,0xe179,0xe17a,0xe17b,0xe17c,0xe17d,0xe17e,0xe17f, - 0xe180,0xe181,0xe182,0xe183,0xe184,0xe185,0xe186,0xe187,0xe188, - 0xe189,0xe18a,0xe18b,0xe18c,0xe18d,0xe18e,0xe18f,0xe190,0xe191, - 0xe192,0xe193,0xe194,0xe195,0xe196,0xe197,0xe198,0xe199,0xe19a, - 0xe19b,0xe19c,0xe19d,0xe19e,0xe19f,0xe1a0,0xe1a1,0xe1a2,0xe1a3, - 0xe1a4,0xe1a5,0xe1a6,0xe1a7,0xe1a8,0xe1a9,0xe1aa,0xe1ab,0xe1ac, - 0xe1ad,0xe1ae,0xe1af,0xe1b0,0xe1b1,0xe1b2,0xe1b3,0xe1b4,0xe1b5, - 0xe1b6,UDCODE,0xe1b7,0xe1b8,0xe1b9,0xe1ba,0xe1bb,0xe1bc,0xe1bd, - 0xe1be,0xe1bf,0xe1c0,0xe1c1,0xe1c2,0xe1c3,0xe1c4,0xe1c5,0xe1c6, - 0xe1c7,0xe1c8,0xe1c9,0xe1ca,0xe1cb,0xe1cc,0xe1cd,0xe1ce,0xe1cf, - 0xe1d0,0xe1d1,0xe1d2,0xe1d3,0xe1d4,0xe1d5,0xe1d6,0xe1d7,0xe1d8, - 0xe1d9,0xe1da,0xe1db,0xe1dc,0xe1dd,0xe1de,0xe1df,0xe1e0,0xe1e1, - 0xe1e2,0xe1e3,0xe1e4,0xe1e5,0xe1e6,0xe1e7,0xe1e8,0xe1e9,0xe1ea, - 0xe1eb,0xe1ec,0xe1ed,0xe1ee,0xe1ef,0xe1f0,0xe1f1,0xe1f2,0xe1f3, - 0xe1f4,0xe1f5,0xe1f6,0xe1f7,0xe1f8,0xe1f9,0xe1fa,0xe1fb,0xe1fc, - 0xe1fd,0xe1fe,0xe1ff,0xe200,0xe201,0xe202,0xe203,0xe204,0xe205, - 0xe206,0xe207,0xe208,0xe209,0xe20a,0xe20b,0xe20c,0xe20d,0xe20e, - 0xe20f,0xe210,0xe211,0xe212,0xe213,0xe214,0xe215,0xe216,0xe217, - 0xe218,0xe219,0xe21a,0xe21b,0xe21c,0xe21d,0xe21e,0xe21f,0xe220, - 0xe221,0xe222,0xe223,0xe224,0xe225,0xe226,0xe227,0xe228,0xe229, - 0xe22a,0xe22b,0xe22c,0xe22d,0xe22e,0xe22f,0xe230,0xe231,0xe232, - 0xe233,0xe234,0xe235,0xe236,0xe237,0xe238,0xe239,0xe23a,0xe23b, - 0xe23c,0xe23d,0xe23e,0xe23f,0xe240,0xe241,0xe242,0xe243,0xe244, - 0xe245,0xe246,0xe247,0xe248,0xe249,0xe24a,0xe24b,0xe24c,0xe24d, - 0xe24e,0xe24f,0xe250,0xe251,0xe252,0xe253,0xe254,0xe255,0xe256, - 0xe257,0xe258,0xe259,0xe25a,0xe25b,0xe25c,0xe25d,0xe25e,0xe25f, - 0xe260,0xe261,0xe262,0xe263,0xe264,0xe265,0xe266,0xe267,0xe268, - 0xe269,0xe26a,0xe26b,0xe26c,0xe26d,0xe26e,0xe26f,0xe270,0xe271, - 0xe272,UDCODE,0xe273,0xe274,0xe275,0xe276,0xe277,0xe278,0xe279, - 0xe27a,0xe27b,0xe27c,0xe27d,0xe27e,0xe27f,0xe280,0xe281,0xe282, - 0xe283,0xe284,0xe285,0xe286,0xe287,0xe288,0xe289,0xe28a,0xe28b, - 0xe28c,0xe28d,0xe28e,0xe28f,0xe290,0xe291,0xe292,0xe293,0xe294, - 0xe295,0xe296,0xe297,0xe298,0xe299,0xe29a,0xe29b,0xe29c,0xe29d, - 0xe29e,0xe29f,0xe2a0,0xe2a1,0xe2a2,0xe2a3,0xe2a4,0xe2a5,0xe2a6, - 0xe2a7,0xe2a8,0xe2a9,0xe2aa,0xe2ab,0xe2ac,0xe2ad,0xe2ae,0xe2af, - 0xe2b0,0xe2b1,0xe2b2,0xe2b3,0xe2b4,0xe2b5,0xe2b6,0xe2b7,0xe2b8, - 0xe2b9,0xe2ba,0xe2bb,0xe2bc,0xe2bd,0xe2be,0xe2bf,0xe2c0,0xe2c1, - 0xe2c2,0xe2c3,0xe2c4,0xe2c5,0xe2c6,0xe2c7,0xe2c8,0xe2c9,0xe2ca, - 0xe2cb,0xe2cc,0xe2cd,0xe2ce,0xe2cf,0xe2d0,0xe2d1,0xe2d2,0xe2d3, - 0xe2d4,0xe2d5,0xe2d6,0xe2d7,0xe2d8,0xe2d9,0xe2da,0xe2db,0xe2dc, - 0xe2dd,0xe2de,0xe2df,0xe2e0,0xe2e1,0xe2e2,0xe2e3,0xe2e4,0xe2e5, - 0xe2e6,0xe2e7,0xe2e8,0xe2e9,0xe2ea,0xe2eb,0xe2ec,0xe2ed,0xe2ee, - 0xe2ef,0xe2f0,0xe2f1,0xe2f2,0xe2f3,0xe2f4,0xe2f5,0xe2f6,0xe2f7, - 0xe2f8,0xe2f9,0xe2fa,0xe2fb,0xe2fc,0xe2fd,0xe2fe,0xe2ff,0xe300, - 0xe301,0xe302,0xe303,0xe304,0xe305,0xe306,0xe307,0xe308,0xe309, - 0xe30a,0xe30b,0xe30c,0xe30d,0xe30e,0xe30f,0xe310,0xe311,0xe312, - 0xe313,0xe314,0xe315,0xe316,0xe317,0xe318,0xe319,0xe31a,0xe31b, - 0xe31c,0xe31d,0xe31e,0xe31f,0xe320,0xe321,0xe322,0xe323,0xe324, - 0xe325,0xe326,0xe327,0xe328,0xe329,0xe32a,0xe32b,0xe32c,0xe32d, - 0xe32e,UDCODE,0xe32f,0xe330,0xe331,0xe332,0xe333,0xe334,0xe335, - 0xe336,0xe337,0xe338,0xe339,0xe33a,0xe33b,0xe33c,0xe33d,0xe33e, - 0xe33f,0xe340,0xe341,0xe342,0xe343,0xe344,0xe345,0xe346,0xe347, - 0xe348,0xe349,0xe34a,0xe34b,0xe34c,0xe34d,0xe34e,0xe34f,0xe350, - 0xe351,0xe352,0xe353,0xe354,0xe355,0xe356,0xe357,0xe358,0xe359, - 0xe35a,0xe35b,0xe35c,0xe35d,0xe35e,0xe35f,0xe360,0xe361,0xe362, - 0xe363,0xe364,0xe365,0xe366,0xe367,0xe368,0xe369,0xe36a,0xe36b, - 0xe36c,0xe36d,0xe36e,0xe36f,0xe370,0xe371,0xe372,0xe373,0xe374, - 0xe375,0xe376,0xe377,0xe378,0xe379,0xe37a,0xe37b,0xe37c,0xe37d, - 0xe37e,0xe37f,0xe380,0xe381,0xe382,0xe383,0xe384,0xe385,0xe386, - 0xe387,0xe388,0xe389,0xe38a,0xe38b,0xe38c,0xe38d,0xe38e,0xe38f, - 0xe390,0xe391,0xe392,0xe393,0xe394,0xe395,0xe396,0xe397,0xe398, - 0xe399,0xe39a,0xe39b,0xe39c,0xe39d,0xe39e,0xe39f,0xe3a0,0xe3a1, - 0xe3a2,0xe3a3,0xe3a4,0xe3a5,0xe3a6,0xe3a7,0xe3a8,0xe3a9,0xe3aa, - 0xe3ab,0xe3ac,0xe3ad,0xe3ae,0xe3af,0xe3b0,0xe3b1,0xe3b2,0xe3b3, - 0xe3b4,0xe3b5,0xe3b6,0xe3b7,0xe3b8,0xe3b9,0xe3ba,0xe3bb,0xe3bc, - 0xe3bd,0xe3be,0xe3bf,0xe3c0,0xe3c1,0xe3c2,0xe3c3,0xe3c4,0xe3c5, - 0xe3c6,0xe3c7,0xe3c8,0xe3c9,0xe3ca,0xe3cb,0xe3cc,0xe3cd,0xe3ce, - 0xe3cf,0xe3d0,0xe3d1,0xe3d2,0xe3d3,0xe3d4,0xe3d5,0xe3d6,0xe3d7, - 0xe3d8,0xe3d9,0xe3da,0xe3db,0xe3dc,0xe3dd,0xe3de,0xe3df,0xe3e0, - 0xe3e1,0xe3e2,0xe3e3,0xe3e4,0xe3e5,0xe3e6,0xe3e7,0xe3e8,0xe3e9, - 0xe3ea,UDCODE,0xe3eb,0xe3ec,0xe3ed,0xe3ee,0xe3ef,0xe3f0,0xe3f1, - 0xe3f2,0xe3f3,0xe3f4,0xe3f5,0xe3f6,0xe3f7,0xe3f8,0xe3f9,0xe3fa, - 0xe3fb,0xe3fc,0xe3fd,0xe3fe,0xe3ff,0xe400,0xe401,0xe402,0xe403, - 0xe404,0xe405,0xe406,0xe407,0xe408,0xe409,0xe40a,0xe40b,0xe40c, - 0xe40d,0xe40e,0xe40f,0xe410,0xe411,0xe412,0xe413,0xe414,0xe415, - 0xe416,0xe417,0xe418,0xe419,0xe41a,0xe41b,0xe41c,0xe41d,0xe41e, - 0xe41f,0xe420,0xe421,0xe422,0xe423,0xe424,0xe425,0xe426,0xe427, - 0xe428,0xe429,0xe42a,0xe42b,0xe42c,0xe42d,0xe42e,0xe42f,0xe430, - 0xe431,0xe432,0xe433,0xe434,0xe435,0xe436,0xe437,0xe438,0xe439, - 0xe43a,0xe43b,0xe43c,0xe43d,0xe43e,0xe43f,0xe440,0xe441,0xe442, - 0xe443,0xe444,0xe445,0xe446,0xe447,0xe448,0xe449,0xe44a,0xe44b, - 0xe44c,0xe44d,0xe44e,0xe44f,0xe450,0xe451,0xe452,0xe453,0xe454, - 0xe455,0xe456,0xe457,0xe458,0xe459,0xe45a,0xe45b,0xe45c,0xe45d, - 0xe45e,0xe45f,0xe460,0xe461,0xe462,0xe463,0xe464,0xe465,0xe466, - 0xe467,0xe468,0xe469,0xe46a,0xe46b,0xe46c,0xe46d,0xe46e,0xe46f, - 0xe470,0xe471,0xe472,0xe473,0xe474,0xe475,0xe476,0xe477,0xe478, - 0xe479,0xe47a,0xe47b,0xe47c,0xe47d,0xe47e,0xe47f,0xe480,0xe481, - 0xe482,0xe483,0xe484,0xe485,0xe486,0xe487,0xe488,0xe489,0xe48a, - 0xe48b,0xe48c,0xe48d,0xe48e,0xe48f,0xe490,0xe491,0xe492,0xe493, - 0xe494,0xe495,0xe496,0xe497,0xe498,0xe499,0xe49a,0xe49b,0xe49c, - 0xe49d,0xe49e,0xe49f,0xe4a0,0xe4a1,0xe4a2,0xe4a3,0xe4a4,0xe4a5, - 0xe4a6,UDCODE,0xe4a7,0xe4a8,0xe4a9,0xe4aa,0xe4ab,0xe4ac,0xe4ad, - 0xe4ae,0xe4af,0xe4b0,0xe4b1,0xe4b2,0xe4b3,0xe4b4,0xe4b5,0xe4b6, - 0xe4b7,0xe4b8,0xe4b9,0xe4ba,0xe4bb,0xe4bc,0xe4bd,0xe4be,0xe4bf, - 0xe4c0,0xe4c1,0xe4c2,0xe4c3,0xe4c4,0xe4c5,0xe4c6,0xe4c7,0xe4c8, - 0xe4c9,0xe4ca,0xe4cb,0xe4cc,0xe4cd,0xe4ce,0xe4cf,0xe4d0,0xe4d1, - 0xe4d2,0xe4d3,0xe4d4,0xe4d5,0xe4d6,0xe4d7,0xe4d8,0xe4d9,0xe4da, - 0xe4db,0xe4dc,0xe4dd,0xe4de,0xe4df,0xe4e0,0xe4e1,0xe4e2,0xe4e3, - 0xe4e4,0xe4e5,0xe4e6,0xe4e7,0xe4e8,0xe4e9,0xe4ea,0xe4eb,0xe4ec, - 0xe4ed,0xe4ee,0xe4ef,0xe4f0,0xe4f1,0xe4f2,0xe4f3,0xe4f4,0xe4f5, - 0xe4f6,0xe4f7,0xe4f8,0xe4f9,0xe4fa,0xe4fb,0xe4fc,0xe4fd,0xe4fe, - 0xe4ff,0xe500,0xe501,0xe502,0xe503,0xe504,0xe505,0xe506,0xe507, - 0xe508,0xe509,0xe50a,0xe50b,0xe50c,0xe50d,0xe50e,0xe50f,0xe510, - 0xe511,0xe512,0xe513,0xe514,0xe515,0xe516,0xe517,0xe518,0xe519, - 0xe51a,0xe51b,0xe51c,0xe51d,0xe51e,0xe51f,0xe520,0xe521,0xe522, - 0xe523,0xe524,0xe525,0xe526,0xe527,0xe528,0xe529,0xe52a,0xe52b, - 0xe52c,0xe52d,0xe52e,0xe52f,0xe530,0xe531,0xe532,0xe533,0xe534, - 0xe535,0xe536,0xe537,0xe538,0xe539,0xe53a,0xe53b,0xe53c,0xe53d, - 0xe53e,0xe53f,0xe540,0xe541,0xe542,0xe543,0xe544,0xe545,0xe546, - 0xe547,0xe548,0xe549,0xe54a,0xe54b,0xe54c,0xe54d,0xe54e,0xe54f, - 0xe550,0xe551,0xe552,0xe553,0xe554,0xe555,0xe556,0xe557,0xe558, - 0xe559,0xe55a,0xe55b,0xe55c,0xe55d,0xe55e,0xe55f,0xe560,0xe561, - 0xe562,UDCODE,0xe563,0xe564,0xe565,0xe566,0xe567,0xe568,0xe569, - 0xe56a,0xe56b,0xe56c,0xe56d,0xe56e,0xe56f,0xe570,0xe571,0xe572, - 0xe573,0xe574,0xe575,0xe576,0xe577,0xe578,0xe579,0xe57a,0xe57b, - 0xe57c,0xe57d,0xe57e,0xe57f,0xe580,0xe581,0xe582,0xe583,0xe584, - 0xe585,0xe586,0xe587,0xe588,0xe589,0xe58a,0xe58b,0xe58c,0xe58d, - 0xe58e,0xe58f,0xe590,0xe591,0xe592,0xe593,0xe594,0xe595,0xe596, - 0xe597,0xe598,0xe599,0xe59a,0xe59b,0xe59c,0xe59d,0xe59e,0xe59f, - 0xe5a0,0xe5a1,0xe5a2,0xe5a3,0xe5a4,0xe5a5,0xe5a6,0xe5a7,0xe5a8, - 0xe5a9,0xe5aa,0xe5ab,0xe5ac,0xe5ad,0xe5ae,0xe5af,0xe5b0,0xe5b1, - 0xe5b2,0xe5b3,0xe5b4,0xe5b5,0xe5b6,0xe5b7,0xe5b8,0xe5b9,0xe5ba, - 0xe5bb,0xe5bc,0xe5bd,0xe5be,0xe5bf,0xe5c0,0xe5c1,0xe5c2,0xe5c3, - 0xe5c4,0xe5c5,0xe5c6,0xe5c7,0xe5c8,0xe5c9,0xe5ca,0xe5cb,0xe5cc, - 0xe5cd,0xe5ce,0xe5cf,0xe5d0,0xe5d1,0xe5d2,0xe5d3,0xe5d4,0xe5d5, - 0xe5d6,0xe5d7,0xe5d8,0xe5d9,0xe5da,0xe5db,0xe5dc,0xe5dd,0xe5de, - 0xe5df,0xe5e0,0xe5e1,0xe5e2,0xe5e3,0xe5e4,0xe5e5,0xe5e6,0xe5e7, - 0xe5e8,0xe5e9,0xe5ea,0xe5eb,0xe5ec,0xe5ed,0xe5ee,0xe5ef,0xe5f0, - 0xe5f1,0xe5f2,0xe5f3,0xe5f4,0xe5f5,0xe5f6,0xe5f7,0xe5f8,0xe5f9, - 0xe5fa,0xe5fb,0xe5fc,0xe5fd,0xe5fe,0xe5ff,0xe600,0xe601,0xe602, - 0xe603,0xe604,0xe605,0xe606,0xe607,0xe608,0xe609,0xe60a,0xe60b, - 0xe60c,0xe60d,0xe60e,0xe60f,0xe610,0xe611,0xe612,0xe613,0xe614, - 0xe615,0xe616,0xe617,0xe618,0xe619,0xe61a,0xe61b,0xe61c,0xe61d, - 0xe61e,UDCODE,0xe61f,0xe620,0xe621,0xe622,0xe623,0xe624,0xe625, - 0xe626,0xe627,0xe628,0xe629,0xe62a,0xe62b,0xe62c,0xe62d,0xe62e, - 0xe62f,0xe630,0xe631,0xe632,0xe633,0xe634,0xe635,0xe636,0xe637, - 0xe638,0xe639,0xe63a,0xe63b,0xe63c,0xe63d,0xe63e,0xe63f,0xe640, - 0xe641,0xe642,0xe643,0xe644,0xe645,0xe646,0xe647,0xe648,0xe649, - 0xe64a,0xe64b,0xe64c,0xe64d,0xe64e,0xe64f,0xe650,0xe651,0xe652, - 0xe653,0xe654,0xe655,0xe656,0xe657,0xe658,0xe659,0xe65a,0xe65b, - 0xe65c,0xe65d,0xe65e,0xe65f,0xe660,0xe661,0xe662,0xe663,0xe664, - 0xe665,0xe666,0xe667,0xe668,0xe669,0xe66a,0xe66b,0xe66c,0xe66d, - 0xe66e,0xe66f,0xe670,0xe671,0xe672,0xe673,0xe674,0xe675,0xe676, - 0xe677,0xe678,0xe679,0xe67a,0xe67b,0xe67c,0xe67d,0xe67e,0xe67f, - 0xe680,0xe681,0xe682,0xe683,0xe684,0xe685,0xe686,0xe687,0xe688, - 0xe689,0xe68a,0xe68b,0xe68c,0xe68d,0xe68e,0xe68f,0xe690,0xe691, - 0xe692,0xe693,0xe694,0xe695,0xe696,0xe697,0xe698,0xe699,0xe69a, - 0xe69b,0xe69c,0xe69d,0xe69e,0xe69f,0xe6a0,0xe6a1,0xe6a2,0xe6a3, - 0xe6a4,0xe6a5,0xe6a6,0xe6a7,0xe6a8,0xe6a9,0xe6aa,0xe6ab,0xe6ac, - 0xe6ad,0xe6ae,0xe6af,0xe6b0,0xe6b1,0xe6b2,0xe6b3,0xe6b4,0xe6b5, - 0xe6b6,0xe6b7,0xe6b8,0xe6b9,0xe6ba,0xe6bb,0xe6bc,0xe6bd,0xe6be, - 0xe6bf,0xe6c0,0xe6c1,0xe6c2,0xe6c3,0xe6c4,0xe6c5,0xe6c6,0xe6c7, - 0xe6c8,0xe6c9,0xe6ca,0xe6cb,0xe6cc,0xe6cd,0xe6ce,0xe6cf,0xe6d0, - 0xe6d1,0xe6d2,0xe6d3,0xe6d4,0xe6d5,0xe6d6,0xe6d7,0xe6d8,0xe6d9, - 0xe6da,UDCODE,0xe6db,0xe6dc,0xe6dd,0xe6de,0xe6df,0xe6e0,0xe6e1, - 0xe6e2,0xe6e3,0xe6e4,0xe6e5,0xe6e6,0xe6e7,0xe6e8,0xe6e9,0xe6ea, - 0xe6eb,0xe6ec,0xe6ed,0xe6ee,0xe6ef,0xe6f0,0xe6f1,0xe6f2,0xe6f3, - 0xe6f4,0xe6f5,0xe6f6,0xe6f7,0xe6f8,0xe6f9,0xe6fa,0xe6fb,0xe6fc, - 0xe6fd,0xe6fe,0xe6ff,0xe700,0xe701,0xe702,0xe703,0xe704,0xe705, - 0xe706,0xe707,0xe708,0xe709,0xe70a,0xe70b,0xe70c,0xe70d,0xe70e, - 0xe70f,0xe710,0xe711,0xe712,0xe713,0xe714,0xe715,0xe716,0xe717, - 0xe718,0xe719,0xe71a,0xe71b,0xe71c,0xe71d,0xe71e,0xe71f,0xe720, - 0xe721,0xe722,0xe723,0xe724,0xe725,0xe726,0xe727,0xe728,0xe729, - 0xe72a,0xe72b,0xe72c,0xe72d,0xe72e,0xe72f,0xe730,0xe731,0xe732, - 0xe733,0xe734,0xe735,0xe736,0xe737,0xe738,0xe739,0xe73a,0xe73b, - 0xe73c,0xe73d,0xe73e,0xe73f,0xe740,0xe741,0xe742,0xe743,0xe744, - 0xe745,0xe746,0xe747,0xe748,0xe749,0xe74a,0xe74b,0xe74c,0xe74d, - 0xe74e,0xe74f,0xe750,0xe751,0xe752,0xe753,0xe754,0xe755,0xe756, - 0xe757,0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177, - 0x2178,0x2179,0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166, - 0x2167,0x2168,0x2169,0xffe2,0xffe4,0xff07,0xff02,0x3231,0x2116, - 0x2121,0x2235,0x7e8a,0x891c,0x9348,0x9288,0x84dc,0x4fc9,0x70bb, - 0x6631,0x68c8,0x92f9,0x66fb,0x5f45,0x4e28,0x4ee1,0x4efc,0x4f00, - 0x4f03,0x4f39,0x4f56,0x4f92,0x4f8a,0x4f9a,0x4f94,0x4fcd,0x5040, - 0x5022,0x4fff,0x501e,0x5046,0x5070,0x5042,0x5094,0x50f4,0x50d8, - 0x514a,UDCODE,0x5164,0x519d,0x51be,0x51ec,0x5215,0x529c,0x52a6, - 0x52c0,0x52db,0x5300,0x5307,0x5324,0x5372,0x5393,0x53b2,0x53dd, - 0xfa0e,0x549c,0x548a,0x54a9,0x54ff,0x5586,0x5759,0x5765,0x57ac, - 0x57c8,0x57c7,0xfa0f,0xfa10,0x589e,0x58b2,0x590b,0x5953,0x595b, - 0x595d,0x5963,0x59a4,0x59ba,0x5b56,0x5bc0,0x752f,0x5bd8,0x5bec, - 0x5c1e,0x5ca6,0x5cba,0x5cf5,0x5d27,0x5d53,0xfa11,0x5d42,0x5d6d, - 0x5db8,0x5db9,0x5dd0,0x5f21,0x5f34,0x5f67,0x5fb7,0x5fde,0x605d, - 0x6085,0x608a,0x60de,0x60d5,0x6120,0x60f2,0x6111,0x6137,0x6130, - 0x6198,0x6213,0x62a6,0x63f5,0x6460,0x649d,0x64ce,0x654e,0x6600, - 0x6615,0x663b,0x6609,0x662e,0x661e,0x6624,0x6665,0x6657,0x6659, - 0xfa12,0x6673,0x6699,0x66a0,0x66b2,0x66bf,0x66fa,0x670e,0xf929, - 0x6766,0x67bb,0x6852,0x67c0,0x6801,0x6844,0x68cf,0xfa13,0x6968, - 0xfa14,0x6998,0x69e2,0x6a30,0x6a6b,0x6a46,0x6a73,0x6a7e,0x6ae2, - 0x6ae4,0x6bd6,0x6c3f,0x6c5c,0x6c86,0x6c6f,0x6cda,0x6d04,0x6d87, - 0x6d6f,0x6d96,0x6dac,0x6dcf,0x6df8,0x6df2,0x6dfc,0x6e39,0x6e5c, - 0x6e27,0x6e3c,0x6ebf,0x6f88,0x6fb5,0x6ff5,0x7005,0x7007,0x7028, - 0x7085,0x70ab,0x710f,0x7104,0x715c,0x7146,0x7147,0xfa15,0x71c1, - 0x71fe,0x72b1,0x72be,0x7324,0xfa16,0x7377,0x73bd,0x73c9,0x73d6, - 0x73e3,0x73d2,0x7407,0x73f5,0x7426,0x742a,0x7429,0x742e,0x7462, - 0x7489,0x749f,0x7501,0x756f,0x7682,0x769c,0x769e,0x769b,0x76a6, - 0xfa17,0x7746,0x52af,0x7821,0x784e,0x7864,0x787a,0x7930,0xfa18, - 0xfa19,UDCODE,0xfa1a,0x7994,0xfa1b,0x799b,0x7ad1,0x7ae7,0xfa1c, - 0x7aeb,0x7b9e,0xfa1d,0x7d48,0x7d5c,0x7db7,0x7da0,0x7dd6,0x7e52, - 0x7f47,0x7fa1,0xfa1e,0x8301,0x8362,0x837f,0x83c7,0x83f6,0x8448, - 0x84b4,0x8553,0x8559,0x856b,0xfa1f,0x85b0,0xfa20,0xfa21,0x8807, - 0x88f5,0x8a12,0x8a37,0x8a79,0x8aa7,0x8abe,0x8adf,0xfa22,0x8af6, - 0x8b53,0x8b7f,0x8cf0,0x8cf4,0x8d12,0x8d76,0xfa23,0x8ecf,0xfa24, - 0xfa25,0x9067,0x90de,0xfa26,0x9115,0x9127,0x91da,0x91d7,0x91de, - 0x91ed,0x91ee,0x91e4,0x91e5,0x9206,0x9210,0x920a,0x923a,0x9240, - 0x923c,0x924e,0x9259,0x9251,0x9239,0x9267,0x92a7,0x9277,0x9278, - 0x92e7,0x92d7,0x92d9,0x92d0,0xfa27,0x92d5,0x92e0,0x92d3,0x9325, - 0x9321,0x92fb,0xfa28,0x931e,0x92ff,0x931d,0x9302,0x9370,0x9357, - 0x93a4,0x93c6,0x93de,0x93f8,0x9431,0x9445,0x9448,0x9592,0xf9dc, - 0xfa29,0x969d,0x96af,0x9733,0x973b,0x9743,0x974d,0x974f,0x9751, - 0x9755,0x9857,0x9865,0xfa2a,0xfa2b,0x9927,0xfa2c,0x999e,0x9a4e, - 0x9ad9,0x9adc,0x9b75,0x9b72,0x9b8f,0x9bb1,0x9bbb,0x9c00,0x9d70, - 0x9d6b,0xfa2d,0x9e19,0x9ed1 -}; - -//! 1st table -static const UINT32 s_level1[] = -{ - 0x00000000,0x00000001,0x00000002,0x00000003,0x00000004,0x00000005, - 0x00000006,0x00000007,0x00000008,0x00000009,0x0000000a,0x0000000b, - 0x0000000c,0x0000000d,0x0000000e,0x0000000f,0x00000010,0x00000011, - 0x00000012,0x00000013,0x00000014,0x00000015,0x00000016,0x00000017, - 0x00000018,0x00000019,0x0000001a,0x0000001b,0x0000001c,0x0000001d, - 0x0000001e,0x0000001f,0x00000020,0x00000021,0x00000022,0x00000023, - 0x00000024,0x00000025,0x00000026,0x00000027,0x00000028,0x00000029, - 0x0000002a,0x0000002b,0x0000002c,0x0000002d,0x0000002e,0x0000002f, - 0x00000030,0x00000031,0x00000032,0x00000033,0x00000034,0x00000035, - 0x00000036,0x00000037,0x00000038,0x00000039,0x0000003a,0x0000003b, - 0x0000003c,0x0000003d,0x0000003e,0x0000003f,0x00000040,0x00000041, - 0x00000042,0x00000043,0x00000044,0x00000045,0x00000046,0x00000047, - 0x00000048,0x00000049,0x0000004a,0x0000004b,0x0000004c,0x0000004d, - 0x0000004e,0x0000004f,0x00000050,0x00000051,0x00000052,0x00000053, - 0x00000054,0x00000055,0x00000056,0x00000057,0x00000058,0x00000059, - 0x0000005a,0x0000005b,0x0000005c,0x0000005d,0x0000005e,0x0000005f, - 0x00000060,0x00000061,0x00000062,0x00000063,0x00000064,0x00000065, - 0x00000066,0x00000067,0x00000068,0x00000069,0x0000006a,0x0000006b, - 0x0000006c,0x0000006d,0x0000006e,0x0000006f,0x00000070,0x00000071, - 0x00000072,0x00000073,0x00000074,0x00000075,0x00000076,0x00000077, - 0x00000078,0x00000079,0x0000007a,0x0000007b,0x0000007c,0x0000007d, - 0x0000007e,0x0000007f,0x00000080,0x0001bd40,0x00bea34f,0x01619740, - 0x01f87f40,0x02770000,0x02770000,0x02775d40,0x02d45e9f,0x0332bd40, - 0x03efbd40,0x04acbd40,0x0569bd40,0x0626bd40,0x06e3bd40,0x07a0bd40, - 0x085dbd40,0x091abd40,0x09d7bd40,0x0a94bd40,0x0b51bd40,0x0c0ebd40, - 0x0ccbbd40,0x0d88bd40,0x0e45bd40,0x0f02bd40,0x0fbfbd40,0x107cbd40, - 0x1139bd40,0x11f6bd40,0x12b3bd40,0x1370bd40,0x0000f8f0,0x0000ff61, - 0x0000ff62,0x0000ff63,0x0000ff64,0x0000ff65,0x0000ff66,0x0000ff67, - 0x0000ff68,0x0000ff69,0x0000ff6a,0x0000ff6b,0x0000ff6c,0x0000ff6d, - 0x0000ff6e,0x0000ff6f,0x0000ff70,0x0000ff71,0x0000ff72,0x0000ff73, - 0x0000ff74,0x0000ff75,0x0000ff76,0x0000ff77,0x0000ff78,0x0000ff79, - 0x0000ff7a,0x0000ff7b,0x0000ff7c,0x0000ff7d,0x0000ff7e,0x0000ff7f, - 0x0000ff80,0x0000ff81,0x0000ff82,0x0000ff83,0x0000ff84,0x0000ff85, - 0x0000ff86,0x0000ff87,0x0000ff88,0x0000ff89,0x0000ff8a,0x0000ff8b, - 0x0000ff8c,0x0000ff8d,0x0000ff8e,0x0000ff8f,0x0000ff90,0x0000ff91, - 0x0000ff92,0x0000ff93,0x0000ff94,0x0000ff95,0x0000ff96,0x0000ff97, - 0x0000ff98,0x0000ff99,0x0000ff9a,0x0000ff9b,0x0000ff9c,0x0000ff9d, - 0x0000ff9e,0x0000ff9f,0x142dbd40,0x14eabd40,0x15a7bd40,0x1664bd40, - 0x1721bd40,0x17debd40,0x189bbd40,0x1958bd40,0x1a15bd40,0x1ad2bd40, - 0x1b8f6540,0x1bf40000,0x1bf40000,0x1bf4bd40,0x1cb1bd40,0x1d6e0000, - 0x1d6ebd40,0x1e2bbd40,0x1ee8bd40,0x1fa5bd40,0x2062bd40,0x211fbd40, - 0x21dcbd40,0x2299bd40,0x2356bd40,0x2413bd40,0x24d0bd40,0x258dbd40, - 0x264a0c40,0x0000f8f1,0x0000f8f2,0x0000f8f3 -}; - -static UINT sjis2ucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); -static UINT sjis2utf8(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); - -/** - * Maps a S-JIS string to a UTF-16 string - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -UINT codecnv_sjistoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) -{ - UINT nLength; - - if (lpInput == NULL) - { - return 0; - } - - if (cchOutput == 0) - { - lpOutput = NULL; - cchOutput = (UINT)-1; - } - - if (cchInput != (UINT)-1) - { - // Binary mode - return sjis2ucs2(lpOutput, cchOutput, lpInput, cchInput); - } - else - { - // String mode - nLength = sjis2ucs2(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); - if (lpOutput) - { - lpOutput[nLength] = '\0'; - } - return nLength + 1; - } -} - -/** - * Maps a S-JIS string to a UTF-16 string (inner) - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -static UINT sjis2ucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) -{ - UINT nRemain; - UINT c; - UINT r; - UINT32 idx; - - nRemain = cchOutput; - while ((cchInput > 0) && (nRemain > 0)) - { - c = (*lpInput++) & 0xff; - cchInput--; - - r = s_level1[c]; - if (r & 0xffff0000) - { - if (cchInput == 0) - { - break; - } - cchInput--; - c = ((*lpInput++) - r) & 0xff; - if (c < ((r >> 8) & 0xff)) - { - idx = ((r >> 16) & 0xffff) + c; - r = idx < NELEMENTS(s_level2) ? s_level2[idx] : UDCODE; - } - else - { - r = UDCODE; - } - } - nRemain--; - if (lpOutput) - { - *lpOutput++ = (UINT16)r; - } - } - return (UINT)(cchOutput - nRemain); -} - -/** - * Maps a S-JIS string to a UTF-8 string - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -UINT codecnv_sjistoutf8(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) -{ - UINT nLength; - - if (lpInput == NULL) - { - return 0; - } - - if (cchOutput == 0) - { - lpOutput = NULL; - cchOutput = (UINT)-1; - } - - if (cchInput != (UINT)-1) - { - // Binary mode - return sjis2utf8(lpOutput, cchOutput, lpInput, cchInput); - } - else - { - // String mode - nLength = sjis2utf8(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); - if (lpOutput) - { - lpOutput[nLength] = '\0'; - } - return nLength + 1; - } -} - -/** - * Maps a S-JIS string to a UTF-8 string (inner) - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -static UINT sjis2utf8(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) -{ - UINT nRemain; - UINT c; - UINT r; - UINT32 idx; - - nRemain = cchOutput; - while ((cchInput > 0) && (nRemain > 0)) - { - c = (*lpInput++) & 0xff; - cchInput--; - - r = s_level1[c]; - if (r & 0xffff0000) - { - if (cchInput == 0) - { - break; - } - cchInput--; - c = ((*lpInput++) - r) & 0xff; - if (c < ((r >> 8) & 0xff)) - { - idx = ((r >> 16) & 0xffff) + c; - r = idx < NELEMENTS(s_level2) ? s_level2[idx] : UDCODE; - } - else - { - r = UDCODE; - } - } - - if (r < 0x80) - { - nRemain--; - if (lpOutput) - { - *lpOutput++ = (char)r; - } - } - else if (r < 0x800) - { - if (nRemain < 2) - { - break; - } - nRemain -= 2; - if (lpOutput) - { - *lpOutput++ = (char)(0xc0 + ((r >> 6) & 0x1f)); - *lpOutput++ = (char)(0x80 + ((r >> 0) & 0x3f)); - } - } - else - { - if (nRemain < 3) - { - break; - } - nRemain -= 3; - if (lpOutput) - { - *lpOutput++ = (char)(0xe0 + ((r >> 12) & 0x0f)); - *lpOutput++ = (char)(0x80 + ((r >> 6) & 0x3f)); - *lpOutput++ = (char)(0x80 + ((r >> 0) & 0x3f)); - } - } - } - return (UINT)(cchOutput - nRemain); -} +/** + * @file sjisucs2.c + * @brief Implementation of converting S-JIS to UCS2 + */ + +#ifdef CODECNV_TEST +#include "compiler_base.h" +#else +#include +#endif +#include + +//! undefined code +#define UDCODE 0x30fb + +//! 2nd table +static const UINT16 s_level2[] = +{ + UDCODE,0x3000,0x3001,0x3002,0xff0c,0xff0e,0x30fb,0xff1a,0xff1b, + 0xff1f,0xff01,0x309b,0x309c,0x00b4,0xff40,0x00a8,0xff3e,0xffe3, + 0xff3f,0x30fd,0x30fe,0x309d,0x309e,0x3003,0x4edd,0x3005,0x3006, + 0x3007,0x30fc,0x2015,0x2010,0xff0f,0xff3c,0xff5e,0x2225,0xff5c, + 0x2026,0x2025,0x2018,0x2019,0x201c,0x201d,0xff08,0xff09,0x3014, + 0x3015,0xff3b,0xff3d,0xff5b,0xff5d,0x3008,0x3009,0x300a,0x300b, + 0x300c,0x300d,0x300e,0x300f,0x3010,0x3011,0xff0b,0xff0d,0x00b1, + 0x00d7,UDCODE,0x00f7,0xff1d,0x2260,0xff1c,0xff1e,0x2266,0x2267, + 0x221e,0x2234,0x2642,0x2640,0x00b0,0x2032,0x2033,0x2103,0xffe5, + 0xff04,0xffe0,0xffe1,0xff05,0xff03,0xff06,0xff0a,0xff20,0x00a7, + 0x2606,0x2605,0x25cb,0x25cf,0x25ce,0x25c7,0x25c6,0x25a1,0x25a0, + 0x25b3,0x25b2,0x25bd,0x25bc,0x203b,0x3012,0x2192,0x2190,0x2191, + 0x2193,0x3013,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x2208,0x220b,0x2286,0x2287,0x2282, + 0x2283,0x222a,0x2229,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x2227,0x2228,0xffe2,0x21d2,0x21d4,0x2200,0x2203, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x2220,0x22a5,0x2312,0x2202,0x2207,0x2261,0x2252, + 0x226a,0x226b,0x221a,0x223d,0x221d,0x2235,0x222b,0x222c,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x212b,0x2030,0x266f, + 0x266d,0x266a,0x2020,0x2021,0x00b6,UDCODE,UDCODE,UDCODE,UDCODE, + 0x25ef,0xff10,0xff11,0xff12,0xff13,0xff14,0xff15,0xff16,0xff17, + 0xff18,0xff19,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xff21,0xff22,0xff23,0xff24,0xff25,0xff26,0xff27,0xff28,0xff29, + 0xff2a,0xff2b,0xff2c,0xff2d,0xff2e,0xff2f,0xff30,0xff31,0xff32, + 0xff33,0xff34,0xff35,0xff36,0xff37,0xff38,0xff39,0xff3a,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xff41,0xff42,0xff43, + 0xff44,0xff45,0xff46,0xff47,0xff48,0xff49,0xff4a,0xff4b,0xff4c, + 0xff4d,0xff4e,0xff4f,0xff50,0xff51,0xff52,0xff53,0xff54,0xff55, + 0xff56,0xff57,0xff58,0xff59,0xff5a,UDCODE,UDCODE,UDCODE,UDCODE, + 0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,0x3049, + 0x304a,0x304b,0x304c,0x304d,0x304e,0x304f,0x3050,0x3051,0x3052, + 0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,0x3059,0x305a,0x305b, + 0x305c,0x305d,0x305e,0x305f,0x3060,0x3061,0x3062,0x3063,0x3064, + 0x3065,0x3066,0x3067,0x3068,0x3069,0x306a,0x306b,0x306c,0x306d, + 0x306e,0x306f,0x3070,0x3071,0x3072,0x3073,0x3074,0x3075,0x3076, + 0x3077,0x3078,0x3079,0x307a,0x307b,0x307c,0x307d,0x307e,0x307f, + 0x3080,0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087,0x3088, + 0x3089,0x308a,0x308b,0x308c,0x308d,0x308e,0x308f,0x3090,0x3091, + 0x3092,0x3093,0x30a1,0x30a2,0x30a3,0x30a4,0x30a5,0x30a6,0x30a7, + 0x30a8,0x30a9,0x30aa,0x30ab,0x30ac,0x30ad,0x30ae,0x30af,0x30b0, + 0x30b1,0x30b2,0x30b3,0x30b4,0x30b5,0x30b6,0x30b7,0x30b8,0x30b9, + 0x30ba,0x30bb,0x30bc,0x30bd,0x30be,0x30bf,0x30c0,0x30c1,0x30c2, + 0x30c3,0x30c4,0x30c5,0x30c6,0x30c7,0x30c8,0x30c9,0x30ca,0x30cb, + 0x30cc,0x30cd,0x30ce,0x30cf,0x30d0,0x30d1,0x30d2,0x30d3,0x30d4, + 0x30d5,0x30d6,0x30d7,0x30d8,0x30d9,0x30da,0x30db,0x30dc,0x30dd, + 0x30de,0x30df,UDCODE,0x30e0,0x30e1,0x30e2,0x30e3,0x30e4,0x30e5, + 0x30e6,0x30e7,0x30e8,0x30e9,0x30ea,0x30eb,0x30ec,0x30ed,0x30ee, + 0x30ef,0x30f0,0x30f1,0x30f2,0x30f3,0x30f4,0x30f5,0x30f6,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x0391,0x0392, + 0x0393,0x0394,0x0395,0x0396,0x0397,0x0398,0x0399,0x039a,0x039b, + 0x039c,0x039d,0x039e,0x039f,0x03a0,0x03a1,0x03a3,0x03a4,0x03a5, + 0x03a6,0x03a7,0x03a8,0x03a9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x03b1,0x03b2,0x03b3,0x03b4,0x03b5,0x03b6, + 0x03b7,0x03b8,0x03b9,0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf, + 0x03c0,0x03c1,0x03c3,0x03c4,0x03c5,0x03c6,0x03c7,0x03c8,0x03c9, + 0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0401,0x0416,0x0417, + 0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f,0x0420, + 0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429, + 0x042a,0x042b,0x042c,0x042d,0x042e,0x042f,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x0430,0x0431,0x0432,0x0433,0x0434,0x0435, + 0x0451,0x0436,0x0437,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d, + UDCODE,0x043e,0x043f,0x0440,0x0441,0x0442,0x0443,0x0444,0x0445, + 0x0446,0x0447,0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e, + 0x044f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x2500,0x2502,0x250c,0x2510, + 0x2518,0x2514,0x251c,0x252c,0x2524,0x2534,0x253c,0x2501,0x2503, + 0x250f,0x2513,0x251b,0x2517,0x2523,0x2533,0x252b,0x253b,0x254b, + 0x2520,0x252f,0x2528,0x2537,0x253f,0x251d,0x2530,0x2525,0x2538, + 0x2542,0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467, + 0x2468,0x2469,0x246a,0x246b,0x246c,0x246d,0x246e,0x246f,0x2470, + 0x2471,0x2472,0x2473,0x2160,0x2161,0x2162,0x2163,0x2164,0x2165, + 0x2166,0x2167,0x2168,0x2169,UDCODE,0x3349,0x3314,0x3322,0x334d, + 0x3318,0x3327,0x3303,0x3336,0x3351,0x3357,0x330d,0x3326,0x3323, + 0x332b,0x334a,0x333b,0x339c,0x339d,0x339e,0x338e,0x338f,0x33c4, + 0x33a1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x337b,UDCODE,0x301d,0x301f,0x2116,0x33cd,0x2121,0x32a4,0x32a5, + 0x32a6,0x32a7,0x32a8,0x3231,0x3232,0x3239,0x337e,0x337d,0x337c, + 0x2252,0x2261,0x222b,0x222e,0x2211,0x221a,0x22a5,0x2220,0x221f, + 0x22bf,0x2235,0x2229,0x222a,0x4e9c,0x5516,0x5a03,0x963f,0x54c0, + 0x611b,0x6328,0x59f6,0x9022,0x8475,0x831c,0x7a50,0x60aa,0x63e1, + 0x6e25,0x65ed,0x8466,0x82a6,0x9bf5,0x6893,0x5727,0x65a1,0x6271, + 0x5b9b,0x59d0,0x867b,0x98f4,0x7d62,0x7dbe,0x9b8e,0x6216,0x7c9f, + 0x88b7,0x5b89,0x5eb5,0x6309,0x6697,0x6848,0x95c7,0x978d,0x674f, + 0x4ee5,0x4f0a,0x4f4d,0x4f9d,0x5049,0x56f2,0x5937,0x59d4,0x5a01, + 0x5c09,0x60df,0x610f,0x6170,0x6613,0x6905,0x70ba,0x754f,0x7570, + 0x79fb,0x7dad,0x7def,0x80c3,0x840e,0x8863,0x8b02,0x9055,0x907a, + 0x533b,0x4e95,0x4ea5,0x57df,0x80b2,0x90c1,0x78ef,0x4e00,0x58f1, + 0x6ea2,0x9038,0x7a32,0x8328,0x828b,0x9c2f,0x5141,0x5370,0x54bd, + 0x54e1,0x56e0,0x59fb,0x5f15,0x98f2,0x6deb,0x80e4,0x852d,0x9662, + 0x9670,0x96a0,0x97fb,0x540b,0x53f3,0x5b87,0x70cf,0x7fbd,0x8fc2, + 0x96e8,0x536f,0x9d5c,0x7aba,0x4e11,0x7893,0x81fc,0x6e26,0x5618, + 0x5504,0x6b1d,0x851a,0x9c3b,0x59e5,0x53a9,0x6d66,0x74dc,0x958f, + 0x5642,0x4e91,0x904b,0x96f2,0x834f,0x990c,0x53e1,0x55b6,0x5b30, + 0x5f71,0x6620,0x66f3,0x6804,0x6c38,0x6cf3,0x6d29,0x745b,0x76c8, + 0x7a4e,0x9834,0x82f1,0x885b,0x8a60,0x92ed,0x6db2,0x75ab,0x76ca, + 0x99c5,0x60a6,0x8b01,0x8d8a,0x95b2,0x698e,0x53ad,0x5186,UDCODE, + 0x5712,0x5830,0x5944,0x5bb4,0x5ef6,0x6028,0x63a9,0x63f4,0x6cbf, + 0x6f14,0x708e,0x7114,0x7159,0x71d5,0x733f,0x7e01,0x8276,0x82d1, + 0x8597,0x9060,0x925b,0x9d1b,0x5869,0x65bc,0x6c5a,0x7525,0x51f9, + 0x592e,0x5965,0x5f80,0x5fdc,0x62bc,0x65fa,0x6a2a,0x6b27,0x6bb4, + 0x738b,0x7fc1,0x8956,0x9d2c,0x9d0e,0x9ec4,0x5ca1,0x6c96,0x837b, + 0x5104,0x5c4b,0x61b6,0x81c6,0x6876,0x7261,0x4e59,0x4ffa,0x5378, + 0x6069,0x6e29,0x7a4f,0x97f3,0x4e0b,0x5316,0x4eee,0x4f55,0x4f3d, + 0x4fa1,0x4f73,0x52a0,0x53ef,0x5609,0x590f,0x5ac1,0x5bb6,0x5be1, + 0x79d1,0x6687,0x679c,0x67b6,0x6b4c,0x6cb3,0x706b,0x73c2,0x798d, + 0x79be,0x7a3c,0x7b87,0x82b1,0x82db,0x8304,0x8377,0x83ef,0x83d3, + 0x8766,0x8ab2,0x5629,0x8ca8,0x8fe6,0x904e,0x971e,0x868a,0x4fc4, + 0x5ce8,0x6211,0x7259,0x753b,0x81e5,0x82bd,0x86fe,0x8cc0,0x96c5, + 0x9913,0x99d5,0x4ecb,0x4f1a,0x89e3,0x56de,0x584a,0x58ca,0x5efb, + 0x5feb,0x602a,0x6094,0x6062,0x61d0,0x6212,0x62d0,0x6539,0x9b41, + 0x6666,0x68b0,0x6d77,0x7070,0x754c,0x7686,0x7d75,0x82a5,0x87f9, + 0x958b,0x968e,0x8c9d,0x51f1,0x52be,0x5916,0x54b3,0x5bb3,0x5d16, + 0x6168,0x6982,0x6daf,0x788d,0x84cb,0x8857,0x8a72,0x93a7,0x9ab8, + 0x6d6c,0x99a8,0x86d9,0x57a3,0x67ff,0x86ce,0x920e,0x5283,0x5687, + 0x5404,0x5ed3,0x62e1,0x64b9,0x683c,0x6838,0x6bbb,0x7372,0x78ba, + 0x7a6b,0x899a,0x89d2,0x8d6b,0x8f03,0x90ed,0x95a3,0x9694,0x9769, + 0x5b66,0x5cb3,0x697d,0x984d,0x984e,0x639b,0x7b20,0x6a2b,UDCODE, + 0x6a7f,0x68b6,0x9c0d,0x6f5f,0x5272,0x559d,0x6070,0x62ec,0x6d3b, + 0x6e07,0x6ed1,0x845b,0x8910,0x8f44,0x4e14,0x9c39,0x53f6,0x691b, + 0x6a3a,0x9784,0x682a,0x515c,0x7ac3,0x84b2,0x91dc,0x938c,0x565b, + 0x9d28,0x6822,0x8305,0x8431,0x7ca5,0x5208,0x82c5,0x74e6,0x4e7e, + 0x4f83,0x51a0,0x5bd2,0x520a,0x52d8,0x52e7,0x5dfb,0x559a,0x582a, + 0x59e6,0x5b8c,0x5b98,0x5bdb,0x5e72,0x5e79,0x60a3,0x611f,0x6163, + 0x61be,0x63db,0x6562,0x67d1,0x6853,0x68fa,0x6b3e,0x6b53,0x6c57, + 0x6f22,0x6f97,0x6f45,0x74b0,0x7518,0x76e3,0x770b,0x7aff,0x7ba1, + 0x7c21,0x7de9,0x7f36,0x7ff0,0x809d,0x8266,0x839e,0x89b3,0x8acc, + 0x8cab,0x9084,0x9451,0x9593,0x9591,0x95a2,0x9665,0x97d3,0x9928, + 0x8218,0x4e38,0x542b,0x5cb8,0x5dcc,0x73a9,0x764c,0x773c,0x5ca9, + 0x7feb,0x8d0b,0x96c1,0x9811,0x9854,0x9858,0x4f01,0x4f0e,0x5371, + 0x559c,0x5668,0x57fa,0x5947,0x5b09,0x5bc4,0x5c90,0x5e0c,0x5e7e, + 0x5fcc,0x63ee,0x673a,0x65d7,0x65e2,0x671f,0x68cb,0x68c4,0x6a5f, + 0x5e30,0x6bc5,0x6c17,0x6c7d,0x757f,0x7948,0x5b63,0x7a00,0x7d00, + 0x5fbd,0x898f,0x8a18,0x8cb4,0x8d77,0x8ecc,0x8f1d,0x98e2,0x9a0e, + 0x9b3c,0x4e80,0x507d,0x5100,0x5993,0x5b9c,0x622f,0x6280,0x64ec, + 0x6b3a,0x72a0,0x7591,0x7947,0x7fa9,0x87fb,0x8abc,0x8b70,0x63ac, + 0x83ca,0x97a0,0x5409,0x5403,0x55ab,0x6854,0x6a58,0x8a70,0x7827, + 0x6775,0x9ecd,0x5374,0x5ba2,0x811a,0x8650,0x9006,0x4e18,0x4e45, + 0x4ec7,0x4f11,0x53ca,0x5438,0x5bae,0x5f13,0x6025,0x6551,UDCODE, + 0x673d,0x6c42,0x6c72,0x6ce3,0x7078,0x7403,0x7a76,0x7aae,0x7b08, + 0x7d1a,0x7cfe,0x7d66,0x65e7,0x725b,0x53bb,0x5c45,0x5de8,0x62d2, + 0x62e0,0x6319,0x6e20,0x865a,0x8a31,0x8ddd,0x92f8,0x6f01,0x79a6, + 0x9b5a,0x4ea8,0x4eab,0x4eac,0x4f9b,0x4fa0,0x50d1,0x5147,0x7af6, + 0x5171,0x51f6,0x5354,0x5321,0x537f,0x53eb,0x55ac,0x5883,0x5ce1, + 0x5f37,0x5f4a,0x602f,0x6050,0x606d,0x631f,0x6559,0x6a4b,0x6cc1, + 0x72c2,0x72ed,0x77ef,0x80f8,0x8105,0x8208,0x854e,0x90f7,0x93e1, + 0x97ff,0x9957,0x9a5a,0x4ef0,0x51dd,0x5c2d,0x6681,0x696d,0x5c40, + 0x66f2,0x6975,0x7389,0x6850,0x7c81,0x50c5,0x52e4,0x5747,0x5dfe, + 0x9326,0x65a4,0x6b23,0x6b3d,0x7434,0x7981,0x79bd,0x7b4b,0x7dca, + 0x82b9,0x83cc,0x887f,0x895f,0x8b39,0x8fd1,0x91d1,0x541f,0x9280, + 0x4e5d,0x5036,0x53e5,0x533a,0x72d7,0x7396,0x77e9,0x82e6,0x8eaf, + 0x99c6,0x99c8,0x99d2,0x5177,0x611a,0x865e,0x55b0,0x7a7a,0x5076, + 0x5bd3,0x9047,0x9685,0x4e32,0x6adb,0x91e7,0x5c51,0x5c48,0x6398, + 0x7a9f,0x6c93,0x9774,0x8f61,0x7aaa,0x718a,0x9688,0x7c82,0x6817, + 0x7e70,0x6851,0x936c,0x52f2,0x541b,0x85ab,0x8a13,0x7fa4,0x8ecd, + 0x90e1,0x5366,0x8888,0x7941,0x4fc2,0x50be,0x5211,0x5144,0x5553, + 0x572d,0x73ea,0x578b,0x5951,0x5f62,0x5f84,0x6075,0x6176,0x6167, + 0x61a9,0x63b2,0x643a,0x656c,0x666f,0x6842,0x6e13,0x7566,0x7a3d, + 0x7cfb,0x7d4c,0x7d99,0x7e4b,0x7f6b,0x830e,0x834a,0x86cd,0x8a08, + 0x8a63,0x8b66,0x8efd,0x981a,0x9d8f,0x82b8,0x8fce,0x9be8,UDCODE, + 0x5287,0x621f,0x6483,0x6fc0,0x9699,0x6841,0x5091,0x6b20,0x6c7a, + 0x6f54,0x7a74,0x7d50,0x8840,0x8a23,0x6708,0x4ef6,0x5039,0x5026, + 0x5065,0x517c,0x5238,0x5263,0x55a7,0x570f,0x5805,0x5acc,0x5efa, + 0x61b2,0x61f8,0x62f3,0x6372,0x691c,0x6a29,0x727d,0x72ac,0x732e, + 0x7814,0x786f,0x7d79,0x770c,0x80a9,0x898b,0x8b19,0x8ce2,0x8ed2, + 0x9063,0x9375,0x967a,0x9855,0x9a13,0x9e78,0x5143,0x539f,0x53b3, + 0x5e7b,0x5f26,0x6e1b,0x6e90,0x7384,0x73fe,0x7d43,0x8237,0x8a00, + 0x8afa,0x9650,0x4e4e,0x500b,0x53e4,0x547c,0x56fa,0x59d1,0x5b64, + 0x5df1,0x5eab,0x5f27,0x6238,0x6545,0x67af,0x6e56,0x72d0,0x7cca, + 0x88b4,0x80a1,0x80e1,0x83f0,0x864e,0x8a87,0x8de8,0x9237,0x96c7, + 0x9867,0x9f13,0x4e94,0x4e92,0x4f0d,0x5348,0x5449,0x543e,0x5a2f, + 0x5f8c,0x5fa1,0x609f,0x68a7,0x6a8e,0x745a,0x7881,0x8a9e,0x8aa4, + 0x8b77,0x9190,0x4e5e,0x9bc9,0x4ea4,0x4f7c,0x4faf,0x5019,0x5016, + 0x5149,0x516c,0x529f,0x52b9,0x52fe,0x539a,0x53e3,0x5411,0x540e, + 0x5589,0x5751,0x57a2,0x597d,0x5b54,0x5b5d,0x5b8f,0x5de5,0x5de7, + 0x5df7,0x5e78,0x5e83,0x5e9a,0x5eb7,0x5f18,0x6052,0x614c,0x6297, + 0x62d8,0x63a7,0x653b,0x6602,0x6643,0x66f4,0x676d,0x6821,0x6897, + 0x69cb,0x6c5f,0x6d2a,0x6d69,0x6e2f,0x6e9d,0x7532,0x7687,0x786c, + 0x7a3f,0x7ce0,0x7d05,0x7d18,0x7d5e,0x7db1,0x8015,0x8003,0x80af, + 0x80b1,0x8154,0x818f,0x822a,0x8352,0x884c,0x8861,0x8b1b,0x8ca2, + 0x8cfc,0x90ca,0x9175,0x9271,0x783f,0x92fc,0x95a4,0x964d,UDCODE, + 0x9805,0x9999,0x9ad8,0x9d3b,0x525b,0x52ab,0x53f7,0x5408,0x58d5, + 0x62f7,0x6fe0,0x8c6a,0x8f5f,0x9eb9,0x514b,0x523b,0x544a,0x56fd, + 0x7a40,0x9177,0x9d60,0x9ed2,0x7344,0x6f09,0x8170,0x7511,0x5ffd, + 0x60da,0x9aa8,0x72db,0x8fbc,0x6b64,0x9803,0x4eca,0x56f0,0x5764, + 0x58be,0x5a5a,0x6068,0x61c7,0x660f,0x6606,0x6839,0x68b1,0x6df7, + 0x75d5,0x7d3a,0x826e,0x9b42,0x4e9b,0x4f50,0x53c9,0x5506,0x5d6f, + 0x5de6,0x5dee,0x67fb,0x6c99,0x7473,0x7802,0x8a50,0x9396,0x88df, + 0x5750,0x5ea7,0x632b,0x50b5,0x50ac,0x518d,0x6700,0x54c9,0x585e, + 0x59bb,0x5bb0,0x5f69,0x624d,0x63a1,0x683d,0x6b73,0x6e08,0x707d, + 0x91c7,0x7280,0x7815,0x7826,0x796d,0x658e,0x7d30,0x83dc,0x88c1, + 0x8f09,0x969b,0x5264,0x5728,0x6750,0x7f6a,0x8ca1,0x51b4,0x5742, + 0x962a,0x583a,0x698a,0x80b4,0x54b2,0x5d0e,0x57fc,0x7895,0x9dfa, + 0x4f5c,0x524a,0x548b,0x643e,0x6628,0x6714,0x67f5,0x7a84,0x7b56, + 0x7d22,0x932f,0x685c,0x9bad,0x7b39,0x5319,0x518a,0x5237,0x5bdf, + 0x62f6,0x64ae,0x64e6,0x672d,0x6bba,0x85a9,0x96d1,0x7690,0x9bd6, + 0x634c,0x9306,0x9bab,0x76bf,0x6652,0x4e09,0x5098,0x53c2,0x5c71, + 0x60e8,0x6492,0x6563,0x685f,0x71e6,0x73ca,0x7523,0x7b97,0x7e82, + 0x8695,0x8b83,0x8cdb,0x9178,0x9910,0x65ac,0x66ab,0x6b8b,0x4ed5, + 0x4ed4,0x4f3a,0x4f7f,0x523a,0x53f8,0x53f2,0x55e3,0x56db,0x58eb, + 0x59cb,0x59c9,0x59ff,0x5b50,0x5c4d,0x5e02,0x5e2b,0x5fd7,0x601d, + 0x6307,0x652f,0x5b5c,0x65af,0x65bd,0x65e8,0x679d,0x6b62,UDCODE, + 0x6b7b,0x6c0f,0x7345,0x7949,0x79c1,0x7cf8,0x7d19,0x7d2b,0x80a2, + 0x8102,0x81f3,0x8996,0x8a5e,0x8a69,0x8a66,0x8a8c,0x8aee,0x8cc7, + 0x8cdc,0x96cc,0x98fc,0x6b6f,0x4e8b,0x4f3c,0x4f8d,0x5150,0x5b57, + 0x5bfa,0x6148,0x6301,0x6642,0x6b21,0x6ecb,0x6cbb,0x723e,0x74bd, + 0x75d4,0x78c1,0x793a,0x800c,0x8033,0x81ea,0x8494,0x8f9e,0x6c50, + 0x9e7f,0x5f0f,0x8b58,0x9d2b,0x7afa,0x8ef8,0x5b8d,0x96eb,0x4e03, + 0x53f1,0x57f7,0x5931,0x5ac9,0x5ba4,0x6089,0x6e7f,0x6f06,0x75be, + 0x8cea,0x5b9f,0x8500,0x7be0,0x5072,0x67f4,0x829d,0x5c61,0x854a, + 0x7e1e,0x820e,0x5199,0x5c04,0x6368,0x8d66,0x659c,0x716e,0x793e, + 0x7d17,0x8005,0x8b1d,0x8eca,0x906e,0x86c7,0x90aa,0x501f,0x52fa, + 0x5c3a,0x6753,0x707c,0x7235,0x914c,0x91c8,0x932b,0x82e5,0x5bc2, + 0x5f31,0x60f9,0x4e3b,0x53d6,0x5b88,0x624b,0x6731,0x6b8a,0x72e9, + 0x73e0,0x7a2e,0x816b,0x8da3,0x9152,0x9996,0x5112,0x53d7,0x546a, + 0x5bff,0x6388,0x6a39,0x7dac,0x9700,0x56da,0x53ce,0x5468,0x5b97, + 0x5c31,0x5dde,0x4fee,0x6101,0x62fe,0x6d32,0x79c0,0x79cb,0x7d42, + 0x7e4d,0x7fd2,0x81ed,0x821f,0x8490,0x8846,0x8972,0x8b90,0x8e74, + 0x8f2f,0x9031,0x914b,0x916c,0x96c6,0x919c,0x4ec0,0x4f4f,0x5145, + 0x5341,0x5f93,0x620e,0x67d4,0x6c41,0x6e0b,0x7363,0x7e26,0x91cd, + 0x9283,0x53d4,0x5919,0x5bbf,0x6dd1,0x795d,0x7e2e,0x7c9b,0x587e, + 0x719f,0x51fa,0x8853,0x8ff0,0x4fca,0x5cfb,0x6625,0x77ac,0x7ae3, + 0x821c,0x99ff,0x51c6,0x5faa,0x65ec,0x696f,0x6b89,0x6df3,UDCODE, + 0x6e96,0x6f64,0x76fe,0x7d14,0x5de1,0x9075,0x9187,0x9806,0x51e6, + 0x521d,0x6240,0x6691,0x66d9,0x6e1a,0x5eb6,0x7dd2,0x7f72,0x66f8, + 0x85af,0x85f7,0x8af8,0x52a9,0x53d9,0x5973,0x5e8f,0x5f90,0x6055, + 0x92e4,0x9664,0x50b7,0x511f,0x52dd,0x5320,0x5347,0x53ec,0x54e8, + 0x5546,0x5531,0x5617,0x5968,0x59be,0x5a3c,0x5bb5,0x5c06,0x5c0f, + 0x5c11,0x5c1a,0x5e84,0x5e8a,0x5ee0,0x5f70,0x627f,0x6284,0x62db, + 0x638c,0x6377,0x6607,0x660c,0x662d,0x6676,0x677e,0x68a2,0x6a1f, + 0x6a35,0x6cbc,0x6d88,0x6e09,0x6e58,0x713c,0x7126,0x7167,0x75c7, + 0x7701,0x785d,0x7901,0x7965,0x79f0,0x7ae0,0x7b11,0x7ca7,0x7d39, + 0x8096,0x83d6,0x848b,0x8549,0x885d,0x88f3,0x8a1f,0x8a3c,0x8a54, + 0x8a73,0x8c61,0x8cde,0x91a4,0x9266,0x937e,0x9418,0x969c,0x9798, + 0x4e0a,0x4e08,0x4e1e,0x4e57,0x5197,0x5270,0x57ce,0x5834,0x58cc, + 0x5b22,0x5e38,0x60c5,0x64fe,0x6761,0x6756,0x6d44,0x72b6,0x7573, + 0x7a63,0x84b8,0x8b72,0x91b8,0x9320,0x5631,0x57f4,0x98fe,0x62ed, + 0x690d,0x6b96,0x71ed,0x7e54,0x8077,0x8272,0x89e6,0x98df,0x8755, + 0x8fb1,0x5c3b,0x4f38,0x4fe1,0x4fb5,0x5507,0x5a20,0x5bdd,0x5be9, + 0x5fc3,0x614e,0x632f,0x65b0,0x664b,0x68ee,0x699b,0x6d78,0x6df1, + 0x7533,0x75b9,0x771f,0x795e,0x79e6,0x7d33,0x81e3,0x82af,0x85aa, + 0x89aa,0x8a3a,0x8eab,0x8f9b,0x9032,0x91dd,0x9707,0x4eba,0x4ec1, + 0x5203,0x5875,0x58ec,0x5c0b,0x751a,0x5c3d,0x814e,0x8a0a,0x8fc5, + 0x9663,0x976d,0x7b25,0x8acf,0x9808,0x9162,0x56f3,0x53a8,UDCODE, + 0x9017,0x5439,0x5782,0x5e25,0x63a8,0x6c34,0x708a,0x7761,0x7c8b, + 0x7fe0,0x8870,0x9042,0x9154,0x9310,0x9318,0x968f,0x745e,0x9ac4, + 0x5d07,0x5d69,0x6570,0x67a2,0x8da8,0x96db,0x636e,0x6749,0x6919, + 0x83c5,0x9817,0x96c0,0x88fe,0x6f84,0x647a,0x5bf8,0x4e16,0x702c, + 0x755d,0x662f,0x51c4,0x5236,0x52e2,0x59d3,0x5f81,0x6027,0x6210, + 0x653f,0x6574,0x661f,0x6674,0x68f2,0x6816,0x6b63,0x6e05,0x7272, + 0x751f,0x76db,0x7cbe,0x8056,0x58f0,0x88fd,0x897f,0x8aa0,0x8a93, + 0x8acb,0x901d,0x9192,0x9752,0x9759,0x6589,0x7a0e,0x8106,0x96bb, + 0x5e2d,0x60dc,0x621a,0x65a5,0x6614,0x6790,0x77f3,0x7a4d,0x7c4d, + 0x7e3e,0x810a,0x8cac,0x8d64,0x8de1,0x8e5f,0x78a9,0x5207,0x62d9, + 0x63a5,0x6442,0x6298,0x8a2d,0x7a83,0x7bc0,0x8aac,0x96ea,0x7d76, + 0x820c,0x8749,0x4ed9,0x5148,0x5343,0x5360,0x5ba3,0x5c02,0x5c16, + 0x5ddd,0x6226,0x6247,0x64b0,0x6813,0x6834,0x6cc9,0x6d45,0x6d17, + 0x67d3,0x6f5c,0x714e,0x717d,0x65cb,0x7a7f,0x7bad,0x7dda,0x7e4a, + 0x7fa8,0x817a,0x821b,0x8239,0x85a6,0x8a6e,0x8cce,0x8df5,0x9078, + 0x9077,0x92ad,0x9291,0x9583,0x9bae,0x524d,0x5584,0x6f38,0x7136, + 0x5168,0x7985,0x7e55,0x81b3,0x7cce,0x564c,0x5851,0x5ca8,0x63aa, + 0x66fe,0x66fd,0x695a,0x72d9,0x758f,0x758e,0x790e,0x7956,0x79df, + 0x7c97,0x7d20,0x7d44,0x8607,0x8a34,0x963b,0x9061,0x9f20,0x50e7, + 0x5275,0x53cc,0x53e2,0x5009,0x55aa,0x58ee,0x594f,0x723d,0x5b8b, + 0x5c64,0x531d,0x60e3,0x60f3,0x635c,0x6383,0x633f,0x63bb,UDCODE, + 0x64cd,0x65e9,0x66f9,0x5de3,0x69cd,0x69fd,0x6f15,0x71e5,0x4e89, + 0x75e9,0x76f8,0x7a93,0x7cdf,0x7dcf,0x7d9c,0x8061,0x8349,0x8358, + 0x846c,0x84bc,0x85fb,0x88c5,0x8d70,0x9001,0x906d,0x9397,0x971c, + 0x9a12,0x50cf,0x5897,0x618e,0x81d3,0x8535,0x8d08,0x9020,0x4fc3, + 0x5074,0x5247,0x5373,0x606f,0x6349,0x675f,0x6e2c,0x8db3,0x901f, + 0x4fd7,0x5c5e,0x8cca,0x65cf,0x7d9a,0x5352,0x8896,0x5176,0x63c3, + 0x5b58,0x5b6b,0x5c0a,0x640d,0x6751,0x905c,0x4ed6,0x591a,0x592a, + 0x6c70,0x8a51,0x553e,0x5815,0x59a5,0x60f0,0x6253,0x67c1,0x8235, + 0x6955,0x9640,0x99c4,0x9a28,0x4f53,0x5806,0x5bfe,0x8010,0x5cb1, + 0x5e2f,0x5f85,0x6020,0x614b,0x6234,0x66ff,0x6cf0,0x6ede,0x80ce, + 0x817f,0x82d4,0x888b,0x8cb8,0x9000,0x902e,0x968a,0x9edb,0x9bdb, + 0x4ee3,0x53f0,0x5927,0x7b2c,0x918d,0x984c,0x9df9,0x6edd,0x7027, + 0x5353,0x5544,0x5b85,0x6258,0x629e,0x62d3,0x6ca2,0x6fef,0x7422, + 0x8a17,0x9438,0x6fc1,0x8afe,0x8338,0x51e7,0x86f8,0x53ea,0x53e9, + 0x4f46,0x9054,0x8fb0,0x596a,0x8131,0x5dfd,0x7aea,0x8fbf,0x68da, + 0x8c37,0x72f8,0x9c48,0x6a3d,0x8ab0,0x4e39,0x5358,0x5606,0x5766, + 0x62c5,0x63a2,0x65e6,0x6b4e,0x6de1,0x6e5b,0x70ad,0x77ed,0x7aef, + 0x7baa,0x7dbb,0x803d,0x80c6,0x86cb,0x8a95,0x935b,0x56e3,0x58c7, + 0x5f3e,0x65ad,0x6696,0x6a80,0x6bb5,0x7537,0x8ac7,0x5024,0x77e5, + 0x5730,0x5f1b,0x6065,0x667a,0x6c60,0x75f4,0x7a1a,0x7f6e,0x81f4, + 0x8718,0x9045,0x99b3,0x7bc9,0x755c,0x7af9,0x7b51,0x84c4,UDCODE, + 0x9010,0x79e9,0x7a92,0x8336,0x5ae1,0x7740,0x4e2d,0x4ef2,0x5b99, + 0x5fe0,0x62bd,0x663c,0x67f1,0x6ce8,0x866b,0x8877,0x8a3b,0x914e, + 0x92f3,0x99d0,0x6a17,0x7026,0x732a,0x82e7,0x8457,0x8caf,0x4e01, + 0x5146,0x51cb,0x558b,0x5bf5,0x5e16,0x5e33,0x5e81,0x5f14,0x5f35, + 0x5f6b,0x5fb4,0x61f2,0x6311,0x66a2,0x671d,0x6f6e,0x7252,0x753a, + 0x773a,0x8074,0x8139,0x8178,0x8776,0x8abf,0x8adc,0x8d85,0x8df3, + 0x929a,0x9577,0x9802,0x9ce5,0x52c5,0x6357,0x76f4,0x6715,0x6c88, + 0x73cd,0x8cc3,0x93ae,0x9673,0x6d25,0x589c,0x690e,0x69cc,0x8ffd, + 0x939a,0x75db,0x901a,0x585a,0x6802,0x63b4,0x69fb,0x4f43,0x6f2c, + 0x67d8,0x8fbb,0x8526,0x7db4,0x9354,0x693f,0x6f70,0x576a,0x58f7, + 0x5b2c,0x7d2c,0x722a,0x540a,0x91e3,0x9db4,0x4ead,0x4f4e,0x505c, + 0x5075,0x5243,0x8c9e,0x5448,0x5824,0x5b9a,0x5e1d,0x5e95,0x5ead, + 0x5ef7,0x5f1f,0x608c,0x62b5,0x633a,0x63d0,0x68af,0x6c40,0x7887, + 0x798e,0x7a0b,0x7de0,0x8247,0x8a02,0x8ae6,0x8e44,0x9013,0x90b8, + 0x912d,0x91d8,0x9f0e,0x6ce5,0x6458,0x64e2,0x6575,0x6ef4,0x7684, + 0x7b1b,0x9069,0x93d1,0x6eba,0x54f2,0x5fb9,0x64a4,0x8f4d,0x8fed, + 0x9244,0x5178,0x586b,0x5929,0x5c55,0x5e97,0x6dfb,0x7e8f,0x751c, + 0x8cbc,0x8ee2,0x985b,0x70b9,0x4f1d,0x6bbf,0x6fb1,0x7530,0x96fb, + 0x514e,0x5410,0x5835,0x5857,0x59ac,0x5c60,0x5f92,0x6597,0x675c, + 0x6e21,0x767b,0x83df,0x8ced,0x9014,0x90fd,0x934d,0x7825,0x783a, + 0x52aa,0x5ea6,0x571f,0x5974,0x6012,0x5012,0x515a,0x51ac,UDCODE, + 0x51cd,0x5200,0x5510,0x5854,0x5858,0x5957,0x5b95,0x5cf6,0x5d8b, + 0x60bc,0x6295,0x642d,0x6771,0x6843,0x68bc,0x68df,0x76d7,0x6dd8, + 0x6e6f,0x6d9b,0x706f,0x71c8,0x5f53,0x75d8,0x7977,0x7b49,0x7b54, + 0x7b52,0x7cd6,0x7d71,0x5230,0x8463,0x8569,0x85e4,0x8a0e,0x8b04, + 0x8c46,0x8e0f,0x9003,0x900f,0x9419,0x9676,0x982d,0x9a30,0x95d8, + 0x50cd,0x52d5,0x540c,0x5802,0x5c0e,0x61a7,0x649e,0x6d1e,0x77b3, + 0x7ae5,0x80f4,0x8404,0x9053,0x9285,0x5ce0,0x9d07,0x533f,0x5f97, + 0x5fb3,0x6d9c,0x7279,0x7763,0x79bf,0x7be4,0x6bd2,0x72ec,0x8aad, + 0x6803,0x6a61,0x51f8,0x7a81,0x6934,0x5c4a,0x9cf6,0x82eb,0x5bc5, + 0x9149,0x701e,0x5678,0x5c6f,0x60c7,0x6566,0x6c8c,0x8c5a,0x9041, + 0x9813,0x5451,0x66c7,0x920d,0x5948,0x90a3,0x5185,0x4e4d,0x51ea, + 0x8599,0x8b0e,0x7058,0x637a,0x934b,0x6962,0x99b4,0x7e04,0x7577, + 0x5357,0x6960,0x8edf,0x96e3,0x6c5d,0x4e8c,0x5c3c,0x5f10,0x8fe9, + 0x5302,0x8cd1,0x8089,0x8679,0x5eff,0x65e5,0x4e73,0x5165,0x5982, + 0x5c3f,0x97ee,0x4efb,0x598a,0x5fcd,0x8a8d,0x6fe1,0x79b0,0x7962, + 0x5be7,0x8471,0x732b,0x71b1,0x5e74,0x5ff5,0x637b,0x649a,0x71c3, + 0x7c98,0x4e43,0x5efc,0x4e4b,0x57dc,0x56a2,0x60a9,0x6fc3,0x7d0d, + 0x80fd,0x8133,0x81bf,0x8fb2,0x8997,0x86a4,0x5df4,0x628a,0x64ad, + 0x8987,0x6777,0x6ce2,0x6d3e,0x7436,0x7834,0x5a46,0x7f75,0x82ad, + 0x99ac,0x4ff3,0x5ec3,0x62dd,0x6392,0x6557,0x676f,0x76c3,0x724c, + 0x80cc,0x80ba,0x8f29,0x914d,0x500d,0x57f9,0x5a92,0x6885,UDCODE, + 0x6973,0x7164,0x72fd,0x8cb7,0x58f2,0x8ce0,0x966a,0x9019,0x877f, + 0x79e4,0x77e7,0x8429,0x4f2f,0x5265,0x535a,0x62cd,0x67cf,0x6cca, + 0x767d,0x7b94,0x7c95,0x8236,0x8584,0x8feb,0x66dd,0x6f20,0x7206, + 0x7e1b,0x83ab,0x99c1,0x9ea6,0x51fd,0x7bb1,0x7872,0x7bb8,0x8087, + 0x7b48,0x6ae8,0x5e61,0x808c,0x7551,0x7560,0x516b,0x9262,0x6e8c, + 0x767a,0x9197,0x9aea,0x4f10,0x7f70,0x629c,0x7b4f,0x95a5,0x9ce9, + 0x567a,0x5859,0x86e4,0x96bc,0x4f34,0x5224,0x534a,0x53cd,0x53db, + 0x5e06,0x642c,0x6591,0x677f,0x6c3e,0x6c4e,0x7248,0x72af,0x73ed, + 0x7554,0x7e41,0x822c,0x85e9,0x8ca9,0x7bc4,0x91c6,0x7169,0x9812, + 0x98ef,0x633d,0x6669,0x756a,0x76e4,0x78d0,0x8543,0x86ee,0x532a, + 0x5351,0x5426,0x5983,0x5e87,0x5f7c,0x60b2,0x6249,0x6279,0x62ab, + 0x6590,0x6bd4,0x6ccc,0x75b2,0x76ae,0x7891,0x79d8,0x7dcb,0x7f77, + 0x80a5,0x88ab,0x8ab9,0x8cbb,0x907f,0x975e,0x98db,0x6a0b,0x7c38, + 0x5099,0x5c3e,0x5fae,0x6787,0x6bd8,0x7435,0x7709,0x7f8e,0x9f3b, + 0x67ca,0x7a17,0x5339,0x758b,0x9aed,0x5f66,0x819d,0x83f1,0x8098, + 0x5f3c,0x5fc5,0x7562,0x7b46,0x903c,0x6867,0x59eb,0x5a9b,0x7d10, + 0x767e,0x8b2c,0x4ff5,0x5f6a,0x6a19,0x6c37,0x6f02,0x74e2,0x7968, + 0x8868,0x8a55,0x8c79,0x5edf,0x63cf,0x75c5,0x79d2,0x82d7,0x9328, + 0x92f2,0x849c,0x86ed,0x9c2d,0x54c1,0x5f6c,0x658c,0x6d5c,0x7015, + 0x8ca7,0x8cd3,0x983b,0x654f,0x74f6,0x4e0d,0x4ed8,0x57e0,0x592b, + 0x5a66,0x5bcc,0x51a8,0x5e03,0x5e9c,0x6016,0x6276,0x6577,UDCODE, + 0x65a7,0x666e,0x6d6e,0x7236,0x7b26,0x8150,0x819a,0x8299,0x8b5c, + 0x8ca0,0x8ce6,0x8d74,0x961c,0x9644,0x4fae,0x64ab,0x6b66,0x821e, + 0x8461,0x856a,0x90e8,0x5c01,0x6953,0x98a8,0x847a,0x8557,0x4f0f, + 0x526f,0x5fa9,0x5e45,0x670d,0x798f,0x8179,0x8907,0x8986,0x6df5, + 0x5f17,0x6255,0x6cb8,0x4ecf,0x7269,0x9b92,0x5206,0x543b,0x5674, + 0x58b3,0x61a4,0x626e,0x711a,0x596e,0x7c89,0x7cde,0x7d1b,0x96f0, + 0x6587,0x805e,0x4e19,0x4f75,0x5175,0x5840,0x5e63,0x5e73,0x5f0a, + 0x67c4,0x4e26,0x853d,0x9589,0x965b,0x7c73,0x9801,0x50fb,0x58c1, + 0x7656,0x78a7,0x5225,0x77a5,0x8511,0x7b86,0x504f,0x5909,0x7247, + 0x7bc7,0x7de8,0x8fba,0x8fd4,0x904d,0x4fbf,0x52c9,0x5a29,0x5f01, + 0x97ad,0x4fdd,0x8217,0x92ea,0x5703,0x6355,0x6b69,0x752b,0x88dc, + 0x8f14,0x7a42,0x52df,0x5893,0x6155,0x620a,0x66ae,0x6bcd,0x7c3f, + 0x83e9,0x5023,0x4ff8,0x5305,0x5446,0x5831,0x5949,0x5b9d,0x5cf0, + 0x5cef,0x5d29,0x5e96,0x62b1,0x6367,0x653e,0x65b9,0x670b,0x6cd5, + 0x6ce1,0x70f9,0x7832,0x7e2b,0x80de,0x82b3,0x840c,0x84ec,0x8702, + 0x8912,0x8a2a,0x8c4a,0x90a6,0x92d2,0x98fd,0x9cf3,0x9d6c,0x4e4f, + 0x4ea1,0x508d,0x5256,0x574a,0x59a8,0x5e3d,0x5fd8,0x5fd9,0x623f, + 0x66b4,0x671b,0x67d0,0x68d2,0x5192,0x7d21,0x80aa,0x81a8,0x8b00, + 0x8c8c,0x8cbf,0x927e,0x9632,0x5420,0x982c,0x5317,0x50d5,0x535c, + 0x58a8,0x64b2,0x6734,0x7267,0x7766,0x7a46,0x91e6,0x52c3,0x6ca1, + 0x6b86,0x5800,0x5e4c,0x5954,0x672c,0x7ffb,0x51e1,0x76c6,UDCODE, + 0x6469,0x78e8,0x9b54,0x9ebb,0x57cb,0x59b9,0x6627,0x679a,0x6bce, + 0x54e9,0x69d9,0x5e55,0x819c,0x6795,0x9baa,0x67fe,0x9c52,0x685d, + 0x4ea6,0x4fe3,0x53c8,0x62b9,0x672b,0x6cab,0x8fc4,0x4fad,0x7e6d, + 0x9ebf,0x4e07,0x6162,0x6e80,0x6f2b,0x8513,0x5473,0x672a,0x9b45, + 0x5df3,0x7b95,0x5cac,0x5bc6,0x871c,0x6e4a,0x84d1,0x7a14,0x8108, + 0x5999,0x7c8d,0x6c11,0x7720,0x52d9,0x5922,0x7121,0x725f,0x77db, + 0x9727,0x9d61,0x690b,0x5a7f,0x5a18,0x51a5,0x540d,0x547d,0x660e, + 0x76df,0x8ff7,0x9298,0x9cf4,0x59ea,0x725d,0x6ec5,0x514d,0x68c9, + 0x7dbf,0x7dec,0x9762,0x9eba,0x6478,0x6a21,0x8302,0x5984,0x5b5f, + 0x6bdb,0x731b,0x76f2,0x7db2,0x8017,0x8499,0x5132,0x6728,0x9ed9, + 0x76ee,0x6762,0x52ff,0x9905,0x5c24,0x623b,0x7c7e,0x8cb0,0x554f, + 0x60b6,0x7d0b,0x9580,0x5301,0x4e5f,0x51b6,0x591c,0x723a,0x8036, + 0x91ce,0x5f25,0x77e2,0x5384,0x5f79,0x7d04,0x85ac,0x8a33,0x8e8d, + 0x9756,0x67f3,0x85ae,0x9453,0x6109,0x6108,0x6cb9,0x7652,0x8aed, + 0x8f38,0x552f,0x4f51,0x512a,0x52c7,0x53cb,0x5ba5,0x5e7d,0x60a0, + 0x6182,0x63d6,0x6709,0x67da,0x6e67,0x6d8c,0x7336,0x7337,0x7531, + 0x7950,0x88d5,0x8a98,0x904a,0x9091,0x90f5,0x96c4,0x878d,0x5915, + 0x4e88,0x4f59,0x4e0e,0x8a89,0x8f3f,0x9810,0x50ad,0x5e7c,0x5996, + 0x5bb9,0x5eb8,0x63da,0x63fa,0x64c1,0x66dc,0x694a,0x69d8,0x6d0b, + 0x6eb6,0x7194,0x7528,0x7aaf,0x7f8a,0x8000,0x8449,0x84c9,0x8981, + 0x8b21,0x8e0a,0x9065,0x967d,0x990a,0x617e,0x6291,0x6b32,UDCODE, + 0x6c83,0x6d74,0x7fcc,0x7ffc,0x6dc0,0x7f85,0x87ba,0x88f8,0x6765, + 0x83b1,0x983c,0x96f7,0x6d1b,0x7d61,0x843d,0x916a,0x4e71,0x5375, + 0x5d50,0x6b04,0x6feb,0x85cd,0x862d,0x89a7,0x5229,0x540f,0x5c65, + 0x674e,0x68a8,0x7406,0x7483,0x75e2,0x88cf,0x88e1,0x91cc,0x96e2, + 0x9678,0x5f8b,0x7387,0x7acb,0x844e,0x63a0,0x7565,0x5289,0x6d41, + 0x6e9c,0x7409,0x7559,0x786b,0x7c92,0x9686,0x7adc,0x9f8d,0x4fb6, + 0x616e,0x65c5,0x865c,0x4e86,0x4eae,0x50da,0x4e21,0x51cc,0x5bee, + 0x6599,0x6881,0x6dbc,0x731f,0x7642,0x77ad,0x7a1c,0x7ce7,0x826f, + 0x8ad2,0x907c,0x91cf,0x9675,0x9818,0x529b,0x7dd1,0x502b,0x5398, + 0x6797,0x6dcb,0x71d0,0x7433,0x81e8,0x8f2a,0x96a3,0x9c57,0x9e9f, + 0x7460,0x5841,0x6d99,0x7d2f,0x985e,0x4ee4,0x4f36,0x4f8b,0x51b7, + 0x52b1,0x5dba,0x601c,0x73b2,0x793c,0x82d3,0x9234,0x96b7,0x96f6, + 0x970a,0x9e97,0x9f62,0x66a6,0x6b74,0x5217,0x52a3,0x70c8,0x88c2, + 0x5ec9,0x604b,0x6190,0x6f23,0x7149,0x7c3e,0x7df4,0x806f,0x84ee, + 0x9023,0x932c,0x5442,0x9b6f,0x6ad3,0x7089,0x8cc2,0x8def,0x9732, + 0x52b4,0x5a41,0x5eca,0x5f04,0x6717,0x697c,0x6994,0x6d6a,0x6f0f, + 0x7262,0x72fc,0x7bed,0x8001,0x807e,0x874b,0x90ce,0x516d,0x9e93, + 0x7984,0x808b,0x9332,0x8ad6,0x502d,0x548c,0x8a71,0x6b6a,0x8cc4, + 0x8107,0x60d1,0x67a0,0x9df2,0x4e99,0x4e98,0x9c10,0x8a6b,0x85c1, + 0x8568,0x6900,0x6e7e,0x7897,0x8155,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x5f0c,0x4e10,0x4e15,0x4e2a,0x4e31, + 0x4e36,0x4e3c,0x4e3f,0x4e42,0x4e56,0x4e58,0x4e82,0x4e85,0x8c6b, + 0x4e8a,0x8212,0x5f0d,0x4e8e,0x4e9e,0x4e9f,0x4ea0,0x4ea2,0x4eb0, + 0x4eb3,0x4eb6,0x4ece,0x4ecd,0x4ec4,0x4ec6,0x4ec2,0x4ed7,0x4ede, + 0x4eed,0x4edf,0x4ef7,0x4f09,0x4f5a,0x4f30,0x4f5b,0x4f5d,0x4f57, + 0x4f47,0x4f76,0x4f88,0x4f8f,0x4f98,0x4f7b,0x4f69,0x4f70,0x4f91, + 0x4f6f,0x4f86,0x4f96,0x5118,0x4fd4,0x4fdf,0x4fce,0x4fd8,0x4fdb, + 0x4fd1,0x4fda,0x4fd0,0x4fe4,0x4fe5,0x501a,0x5028,0x5014,0x502a, + 0x5025,0x5005,0x4f1c,0x4ff6,0x5021,0x5029,0x502c,0x4ffe,0x4fef, + 0x5011,0x5006,0x5043,0x5047,0x6703,0x5055,0x5050,0x5048,0x505a, + 0x5056,0x506c,0x5078,0x5080,0x509a,0x5085,0x50b4,0x50b2,0x50c9, + 0x50ca,0x50b3,0x50c2,0x50d6,0x50de,0x50e5,0x50ed,0x50e3,0x50ee, + 0x50f9,0x50f5,0x5109,0x5101,0x5102,0x5116,0x5115,0x5114,0x511a, + 0x5121,0x513a,0x5137,0x513c,0x513b,0x513f,0x5140,0x5152,0x514c, + 0x5154,0x5162,0x7af8,0x5169,0x516a,0x516e,0x5180,0x5182,0x56d8, + 0x518c,0x5189,0x518f,0x5191,0x5193,0x5195,0x5196,0x51a4,0x51a6, + 0x51a2,0x51a9,0x51aa,0x51ab,0x51b3,0x51b1,0x51b2,0x51b0,0x51b5, + 0x51bd,0x51c5,0x51c9,0x51db,0x51e0,0x8655,0x51e9,0x51ed,UDCODE, + 0x51f0,0x51f5,0x51fe,0x5204,0x520b,0x5214,0x520e,0x5227,0x522a, + 0x522e,0x5233,0x5239,0x524f,0x5244,0x524b,0x524c,0x525e,0x5254, + 0x526a,0x5274,0x5269,0x5273,0x527f,0x527d,0x528d,0x5294,0x5292, + 0x5271,0x5288,0x5291,0x8fa8,0x8fa7,0x52ac,0x52ad,0x52bc,0x52b5, + 0x52c1,0x52cd,0x52d7,0x52de,0x52e3,0x52e6,0x98ed,0x52e0,0x52f3, + 0x52f5,0x52f8,0x52f9,0x5306,0x5308,0x7538,0x530d,0x5310,0x530f, + 0x5315,0x531a,0x5323,0x532f,0x5331,0x5333,0x5338,0x5340,0x5346, + 0x5345,0x4e17,0x5349,0x534d,0x51d6,0x535e,0x5369,0x536e,0x5918, + 0x537b,0x5377,0x5382,0x5396,0x53a0,0x53a6,0x53a5,0x53ae,0x53b0, + 0x53b6,0x53c3,0x7c12,0x96d9,0x53df,0x66fc,0x71ee,0x53ee,0x53e8, + 0x53ed,0x53fa,0x5401,0x543d,0x5440,0x542c,0x542d,0x543c,0x542e, + 0x5436,0x5429,0x541d,0x544e,0x548f,0x5475,0x548e,0x545f,0x5471, + 0x5477,0x5470,0x5492,0x547b,0x5480,0x5476,0x5484,0x5490,0x5486, + 0x54c7,0x54a2,0x54b8,0x54a5,0x54ac,0x54c4,0x54c8,0x54a8,0x54ab, + 0x54c2,0x54a4,0x54be,0x54bc,0x54d8,0x54e5,0x54e6,0x550f,0x5514, + 0x54fd,0x54ee,0x54ed,0x54fa,0x54e2,0x5539,0x5540,0x5563,0x554c, + 0x552e,0x555c,0x5545,0x5556,0x5557,0x5538,0x5533,0x555d,0x5599, + 0x5580,0x54af,0x558a,0x559f,0x557b,0x557e,0x5598,0x559e,0x55ae, + 0x557c,0x5583,0x55a9,0x5587,0x55a8,0x55da,0x55c5,0x55df,0x55c4, + 0x55dc,0x55e4,0x55d4,0x5614,0x55f7,0x5616,0x55fe,0x55fd,0x561b, + 0x55f9,0x564e,0x5650,0x71df,0x5634,0x5636,0x5632,0x5638,UDCODE, + 0x566b,0x5664,0x562f,0x566c,0x566a,0x5686,0x5680,0x568a,0x56a0, + 0x5694,0x568f,0x56a5,0x56ae,0x56b6,0x56b4,0x56c2,0x56bc,0x56c1, + 0x56c3,0x56c0,0x56c8,0x56ce,0x56d1,0x56d3,0x56d7,0x56ee,0x56f9, + 0x5700,0x56ff,0x5704,0x5709,0x5708,0x570b,0x570d,0x5713,0x5718, + 0x5716,0x55c7,0x571c,0x5726,0x5737,0x5738,0x574e,0x573b,0x5740, + 0x574f,0x5769,0x57c0,0x5788,0x5761,0x577f,0x5789,0x5793,0x57a0, + 0x57b3,0x57a4,0x57aa,0x57b0,0x57c3,0x57c6,0x57d4,0x57d2,0x57d3, + 0x580a,0x57d6,0x57e3,0x580b,0x5819,0x581d,0x5872,0x5821,0x5862, + 0x584b,0x5870,0x6bc0,0x5852,0x583d,0x5879,0x5885,0x58b9,0x589f, + 0x58ab,0x58ba,0x58de,0x58bb,0x58b8,0x58ae,0x58c5,0x58d3,0x58d1, + 0x58d7,0x58d9,0x58d8,0x58e5,0x58dc,0x58e4,0x58df,0x58ef,0x58fa, + 0x58f9,0x58fb,0x58fc,0x58fd,0x5902,0x590a,0x5910,0x591b,0x68a6, + 0x5925,0x592c,0x592d,0x5932,0x5938,0x593e,0x7ad2,0x5955,0x5950, + 0x594e,0x595a,0x5958,0x5962,0x5960,0x5967,0x596c,0x5969,0x5978, + 0x5981,0x599d,0x4f5e,0x4fab,0x59a3,0x59b2,0x59c6,0x59e8,0x59dc, + 0x598d,0x59d9,0x59da,0x5a25,0x5a1f,0x5a11,0x5a1c,0x5a09,0x5a1a, + 0x5a40,0x5a6c,0x5a49,0x5a35,0x5a36,0x5a62,0x5a6a,0x5a9a,0x5abc, + 0x5abe,0x5acb,0x5ac2,0x5abd,0x5ae3,0x5ad7,0x5ae6,0x5ae9,0x5ad6, + 0x5afa,0x5afb,0x5b0c,0x5b0b,0x5b16,0x5b32,0x5ad0,0x5b2a,0x5b36, + 0x5b3e,0x5b43,0x5b45,0x5b40,0x5b51,0x5b55,0x5b5a,0x5b5b,0x5b65, + 0x5b69,0x5b70,0x5b73,0x5b75,0x5b78,0x6588,0x5b7a,0x5b80,UDCODE, + 0x5b83,0x5ba6,0x5bb8,0x5bc3,0x5bc7,0x5bc9,0x5bd4,0x5bd0,0x5be4, + 0x5be6,0x5be2,0x5bde,0x5be5,0x5beb,0x5bf0,0x5bf6,0x5bf3,0x5c05, + 0x5c07,0x5c08,0x5c0d,0x5c13,0x5c20,0x5c22,0x5c28,0x5c38,0x5c39, + 0x5c41,0x5c46,0x5c4e,0x5c53,0x5c50,0x5c4f,0x5b71,0x5c6c,0x5c6e, + 0x4e62,0x5c76,0x5c79,0x5c8c,0x5c91,0x5c94,0x599b,0x5cab,0x5cbb, + 0x5cb6,0x5cbc,0x5cb7,0x5cc5,0x5cbe,0x5cc7,0x5cd9,0x5ce9,0x5cfd, + 0x5cfa,0x5ced,0x5d8c,0x5cea,0x5d0b,0x5d15,0x5d17,0x5d5c,0x5d1f, + 0x5d1b,0x5d11,0x5d14,0x5d22,0x5d1a,0x5d19,0x5d18,0x5d4c,0x5d52, + 0x5d4e,0x5d4b,0x5d6c,0x5d73,0x5d76,0x5d87,0x5d84,0x5d82,0x5da2, + 0x5d9d,0x5dac,0x5dae,0x5dbd,0x5d90,0x5db7,0x5dbc,0x5dc9,0x5dcd, + 0x5dd3,0x5dd2,0x5dd6,0x5ddb,0x5deb,0x5df2,0x5df5,0x5e0b,0x5e1a, + 0x5e19,0x5e11,0x5e1b,0x5e36,0x5e37,0x5e44,0x5e43,0x5e40,0x5e4e, + 0x5e57,0x5e54,0x5e5f,0x5e62,0x5e64,0x5e47,0x5e75,0x5e76,0x5e7a, + 0x9ebc,0x5e7f,0x5ea0,0x5ec1,0x5ec2,0x5ec8,0x5ed0,0x5ecf,0x5ed6, + 0x5ee3,0x5edd,0x5eda,0x5edb,0x5ee2,0x5ee1,0x5ee8,0x5ee9,0x5eec, + 0x5ef1,0x5ef3,0x5ef0,0x5ef4,0x5ef8,0x5efe,0x5f03,0x5f09,0x5f5d, + 0x5f5c,0x5f0b,0x5f11,0x5f16,0x5f29,0x5f2d,0x5f38,0x5f41,0x5f48, + 0x5f4c,0x5f4e,0x5f2f,0x5f51,0x5f56,0x5f57,0x5f59,0x5f61,0x5f6d, + 0x5f73,0x5f77,0x5f83,0x5f82,0x5f7f,0x5f8a,0x5f88,0x5f91,0x5f87, + 0x5f9e,0x5f99,0x5f98,0x5fa0,0x5fa8,0x5fad,0x5fbc,0x5fd6,0x5ffb, + 0x5fe4,0x5ff8,0x5ff1,0x5fdd,0x60b3,0x5fff,0x6021,0x6060,UDCODE, + 0x6019,0x6010,0x6029,0x600e,0x6031,0x601b,0x6015,0x602b,0x6026, + 0x600f,0x603a,0x605a,0x6041,0x606a,0x6077,0x605f,0x604a,0x6046, + 0x604d,0x6063,0x6043,0x6064,0x6042,0x606c,0x606b,0x6059,0x6081, + 0x608d,0x60e7,0x6083,0x609a,0x6084,0x609b,0x6096,0x6097,0x6092, + 0x60a7,0x608b,0x60e1,0x60b8,0x60e0,0x60d3,0x60b4,0x5ff0,0x60bd, + 0x60c6,0x60b5,0x60d8,0x614d,0x6115,0x6106,0x60f6,0x60f7,0x6100, + 0x60f4,0x60fa,0x6103,0x6121,0x60fb,0x60f1,0x610d,0x610e,0x6147, + 0x613e,0x6128,0x6127,0x614a,0x613f,0x613c,0x612c,0x6134,0x613d, + 0x6142,0x6144,0x6173,0x6177,0x6158,0x6159,0x615a,0x616b,0x6174, + 0x616f,0x6165,0x6171,0x615f,0x615d,0x6153,0x6175,0x6199,0x6196, + 0x6187,0x61ac,0x6194,0x619a,0x618a,0x6191,0x61ab,0x61ae,0x61cc, + 0x61ca,0x61c9,0x61f7,0x61c8,0x61c3,0x61c6,0x61ba,0x61cb,0x7f79, + 0x61cd,0x61e6,0x61e3,0x61f6,0x61fa,0x61f4,0x61ff,0x61fd,0x61fc, + 0x61fe,0x6200,0x6208,0x6209,0x620d,0x620c,0x6214,0x621b,0x621e, + 0x6221,0x622a,0x622e,0x6230,0x6232,0x6233,0x6241,0x624e,0x625e, + 0x6263,0x625b,0x6260,0x6268,0x627c,0x6282,0x6289,0x627e,0x6292, + 0x6293,0x6296,0x62d4,0x6283,0x6294,0x62d7,0x62d1,0x62bb,0x62cf, + 0x62ff,0x62c6,0x64d4,0x62c8,0x62dc,0x62cc,0x62ca,0x62c2,0x62c7, + 0x629b,0x62c9,0x630c,0x62ee,0x62f1,0x6327,0x6302,0x6308,0x62ef, + 0x62f5,0x6350,0x633e,0x634d,0x641c,0x634f,0x6396,0x638e,0x6380, + 0x63ab,0x6376,0x63a3,0x638f,0x6389,0x639f,0x63b5,0x636b,UDCODE, + 0x6369,0x63be,0x63e9,0x63c0,0x63c6,0x63e3,0x63c9,0x63d2,0x63f6, + 0x63c4,0x6416,0x6434,0x6406,0x6413,0x6426,0x6436,0x651d,0x6417, + 0x6428,0x640f,0x6467,0x646f,0x6476,0x644e,0x652a,0x6495,0x6493, + 0x64a5,0x64a9,0x6488,0x64bc,0x64da,0x64d2,0x64c5,0x64c7,0x64bb, + 0x64d8,0x64c2,0x64f1,0x64e7,0x8209,0x64e0,0x64e1,0x62ac,0x64e3, + 0x64ef,0x652c,0x64f6,0x64f4,0x64f2,0x64fa,0x6500,0x64fd,0x6518, + 0x651c,0x6505,0x6524,0x6523,0x652b,0x6534,0x6535,0x6537,0x6536, + 0x6538,0x754b,0x6548,0x6556,0x6555,0x654d,0x6558,0x655e,0x655d, + 0x6572,0x6578,0x6582,0x6583,0x8b8a,0x659b,0x659f,0x65ab,0x65b7, + 0x65c3,0x65c6,0x65c1,0x65c4,0x65cc,0x65d2,0x65db,0x65d9,0x65e0, + 0x65e1,0x65f1,0x6772,0x660a,0x6603,0x65fb,0x6773,0x6635,0x6636, + 0x6634,0x661c,0x664f,0x6644,0x6649,0x6641,0x665e,0x665d,0x6664, + 0x6667,0x6668,0x665f,0x6662,0x6670,0x6683,0x6688,0x668e,0x6689, + 0x6684,0x6698,0x669d,0x66c1,0x66b9,0x66c9,0x66be,0x66bc,0x66c4, + 0x66b8,0x66d6,0x66da,0x66e0,0x663f,0x66e6,0x66e9,0x66f0,0x66f5, + 0x66f7,0x670f,0x6716,0x671e,0x6726,0x6727,0x9738,0x672e,0x673f, + 0x6736,0x6741,0x6738,0x6737,0x6746,0x675e,0x6760,0x6759,0x6763, + 0x6764,0x6789,0x6770,0x67a9,0x677c,0x676a,0x678c,0x678b,0x67a6, + 0x67a1,0x6785,0x67b7,0x67ef,0x67b4,0x67ec,0x67b3,0x67e9,0x67b8, + 0x67e4,0x67de,0x67dd,0x67e2,0x67ee,0x67b9,0x67ce,0x67c6,0x67e7, + 0x6a9c,0x681e,0x6846,0x6829,0x6840,0x684d,0x6832,0x684e,UDCODE, + 0x68b3,0x682b,0x6859,0x6863,0x6877,0x687f,0x689f,0x688f,0x68ad, + 0x6894,0x689d,0x689b,0x6883,0x6aae,0x68b9,0x6874,0x68b5,0x68a0, + 0x68ba,0x690f,0x688d,0x687e,0x6901,0x68ca,0x6908,0x68d8,0x6922, + 0x6926,0x68e1,0x690c,0x68cd,0x68d4,0x68e7,0x68d5,0x6936,0x6912, + 0x6904,0x68d7,0x68e3,0x6925,0x68f9,0x68e0,0x68ef,0x6928,0x692a, + 0x691a,0x6923,0x6921,0x68c6,0x6979,0x6977,0x695c,0x6978,0x696b, + 0x6954,0x697e,0x696e,0x6939,0x6974,0x693d,0x6959,0x6930,0x6961, + 0x695e,0x695d,0x6981,0x696a,0x69b2,0x69ae,0x69d0,0x69bf,0x69c1, + 0x69d3,0x69be,0x69ce,0x5be8,0x69ca,0x69dd,0x69bb,0x69c3,0x69a7, + 0x6a2e,0x6991,0x69a0,0x699c,0x6995,0x69b4,0x69de,0x69e8,0x6a02, + 0x6a1b,0x69ff,0x6b0a,0x69f9,0x69f2,0x69e7,0x6a05,0x69b1,0x6a1e, + 0x69ed,0x6a14,0x69eb,0x6a0a,0x6a12,0x6ac1,0x6a23,0x6a13,0x6a44, + 0x6a0c,0x6a72,0x6a36,0x6a78,0x6a47,0x6a62,0x6a59,0x6a66,0x6a48, + 0x6a38,0x6a22,0x6a90,0x6a8d,0x6aa0,0x6a84,0x6aa2,0x6aa3,0x6a97, + 0x8617,0x6abb,0x6ac3,0x6ac2,0x6ab8,0x6ab3,0x6aac,0x6ade,0x6ad1, + 0x6adf,0x6aaa,0x6ada,0x6aea,0x6afb,0x6b05,0x8616,0x6afa,0x6b12, + 0x6b16,0x9b31,0x6b1f,0x6b38,0x6b37,0x76dc,0x6b39,0x98ee,0x6b47, + 0x6b43,0x6b49,0x6b50,0x6b59,0x6b54,0x6b5b,0x6b5f,0x6b61,0x6b78, + 0x6b79,0x6b7f,0x6b80,0x6b84,0x6b83,0x6b8d,0x6b98,0x6b95,0x6b9e, + 0x6ba4,0x6baa,0x6bab,0x6baf,0x6bb2,0x6bb1,0x6bb3,0x6bb7,0x6bbc, + 0x6bc6,0x6bcb,0x6bd3,0x6bdf,0x6bec,0x6beb,0x6bf3,0x6bef,UDCODE, + 0x9ebe,0x6c08,0x6c13,0x6c14,0x6c1b,0x6c24,0x6c23,0x6c5e,0x6c55, + 0x6c62,0x6c6a,0x6c82,0x6c8d,0x6c9a,0x6c81,0x6c9b,0x6c7e,0x6c68, + 0x6c73,0x6c92,0x6c90,0x6cc4,0x6cf1,0x6cd3,0x6cbd,0x6cd7,0x6cc5, + 0x6cdd,0x6cae,0x6cb1,0x6cbe,0x6cba,0x6cdb,0x6cef,0x6cd9,0x6cea, + 0x6d1f,0x884d,0x6d36,0x6d2b,0x6d3d,0x6d38,0x6d19,0x6d35,0x6d33, + 0x6d12,0x6d0c,0x6d63,0x6d93,0x6d64,0x6d5a,0x6d79,0x6d59,0x6d8e, + 0x6d95,0x6fe4,0x6d85,0x6df9,0x6e15,0x6e0a,0x6db5,0x6dc7,0x6de6, + 0x6db8,0x6dc6,0x6dec,0x6dde,0x6dcc,0x6de8,0x6dd2,0x6dc5,0x6dfa, + 0x6dd9,0x6de4,0x6dd5,0x6dea,0x6dee,0x6e2d,0x6e6e,0x6e2e,0x6e19, + 0x6e72,0x6e5f,0x6e3e,0x6e23,0x6e6b,0x6e2b,0x6e76,0x6e4d,0x6e1f, + 0x6e43,0x6e3a,0x6e4e,0x6e24,0x6eff,0x6e1d,0x6e38,0x6e82,0x6eaa, + 0x6e98,0x6ec9,0x6eb7,0x6ed3,0x6ebd,0x6eaf,0x6ec4,0x6eb2,0x6ed4, + 0x6ed5,0x6e8f,0x6ea5,0x6ec2,0x6e9f,0x6f41,0x6f11,0x704c,0x6eec, + 0x6ef8,0x6efe,0x6f3f,0x6ef2,0x6f31,0x6eef,0x6f32,0x6ecc,0x6f3e, + 0x6f13,0x6ef7,0x6f86,0x6f7a,0x6f78,0x6f81,0x6f80,0x6f6f,0x6f5b, + 0x6ff3,0x6f6d,0x6f82,0x6f7c,0x6f58,0x6f8e,0x6f91,0x6fc2,0x6f66, + 0x6fb3,0x6fa3,0x6fa1,0x6fa4,0x6fb9,0x6fc6,0x6faa,0x6fdf,0x6fd5, + 0x6fec,0x6fd4,0x6fd8,0x6ff1,0x6fee,0x6fdb,0x7009,0x700b,0x6ffa, + 0x7011,0x7001,0x700f,0x6ffe,0x701b,0x701a,0x6f74,0x701d,0x7018, + 0x701f,0x7030,0x703e,0x7032,0x7051,0x7063,0x7099,0x7092,0x70af, + 0x70f1,0x70ac,0x70b8,0x70b3,0x70ae,0x70df,0x70cb,0x70dd,UDCODE, + 0x70d9,0x7109,0x70fd,0x711c,0x7119,0x7165,0x7155,0x7188,0x7166, + 0x7162,0x714c,0x7156,0x716c,0x718f,0x71fb,0x7184,0x7195,0x71a8, + 0x71ac,0x71d7,0x71b9,0x71be,0x71d2,0x71c9,0x71d4,0x71ce,0x71e0, + 0x71ec,0x71e7,0x71f5,0x71fc,0x71f9,0x71ff,0x720d,0x7210,0x721b, + 0x7228,0x722d,0x722c,0x7230,0x7232,0x723b,0x723c,0x723f,0x7240, + 0x7246,0x724b,0x7258,0x7274,0x727e,0x7282,0x7281,0x7287,0x7292, + 0x7296,0x72a2,0x72a7,0x72b9,0x72b2,0x72c3,0x72c6,0x72c4,0x72ce, + 0x72d2,0x72e2,0x72e0,0x72e1,0x72f9,0x72f7,0x500f,0x7317,0x730a, + 0x731c,0x7316,0x731d,0x7334,0x732f,0x7329,0x7325,0x733e,0x734e, + 0x734f,0x9ed8,0x7357,0x736a,0x7368,0x7370,0x7378,0x7375,0x737b, + 0x737a,0x73c8,0x73b3,0x73ce,0x73bb,0x73c0,0x73e5,0x73ee,0x73de, + 0x74a2,0x7405,0x746f,0x7425,0x73f8,0x7432,0x743a,0x7455,0x743f, + 0x745f,0x7459,0x7441,0x745c,0x7469,0x7470,0x7463,0x746a,0x7476, + 0x747e,0x748b,0x749e,0x74a7,0x74ca,0x74cf,0x74d4,0x73f1,0x74e0, + 0x74e3,0x74e7,0x74e9,0x74ee,0x74f2,0x74f0,0x74f1,0x74f8,0x74f7, + 0x7504,0x7503,0x7505,0x750c,0x750e,0x750d,0x7515,0x7513,0x751e, + 0x7526,0x752c,0x753c,0x7544,0x754d,0x754a,0x7549,0x755b,0x7546, + 0x755a,0x7569,0x7564,0x7567,0x756b,0x756d,0x7578,0x7576,0x7586, + 0x7587,0x7574,0x758a,0x7589,0x7582,0x7594,0x759a,0x759d,0x75a5, + 0x75a3,0x75c2,0x75b3,0x75c3,0x75b5,0x75bd,0x75b8,0x75bc,0x75b1, + 0x75cd,0x75ca,0x75d2,0x75d9,0x75e3,0x75de,0x75fe,0x75ff,UDCODE, + 0x75fc,0x7601,0x75f0,0x75fa,0x75f2,0x75f3,0x760b,0x760d,0x7609, + 0x761f,0x7627,0x7620,0x7621,0x7622,0x7624,0x7634,0x7630,0x763b, + 0x7647,0x7648,0x7646,0x765c,0x7658,0x7661,0x7662,0x7668,0x7669, + 0x766a,0x7667,0x766c,0x7670,0x7672,0x7676,0x7678,0x767c,0x7680, + 0x7683,0x7688,0x768b,0x768e,0x7696,0x7693,0x7699,0x769a,0x76b0, + 0x76b4,0x76b8,0x76b9,0x76ba,0x76c2,0x76cd,0x76d6,0x76d2,0x76de, + 0x76e1,0x76e5,0x76e7,0x76ea,0x862f,0x76fb,0x7708,0x7707,0x7704, + 0x7729,0x7724,0x771e,0x7725,0x7726,0x771b,0x7737,0x7738,0x7747, + 0x775a,0x7768,0x776b,0x775b,0x7765,0x777f,0x777e,0x7779,0x778e, + 0x778b,0x7791,0x77a0,0x779e,0x77b0,0x77b6,0x77b9,0x77bf,0x77bc, + 0x77bd,0x77bb,0x77c7,0x77cd,0x77d7,0x77da,0x77dc,0x77e3,0x77ee, + 0x77fc,0x780c,0x7812,0x7926,0x7820,0x792a,0x7845,0x788e,0x7874, + 0x7886,0x787c,0x789a,0x788c,0x78a3,0x78b5,0x78aa,0x78af,0x78d1, + 0x78c6,0x78cb,0x78d4,0x78be,0x78bc,0x78c5,0x78ca,0x78ec,0x78e7, + 0x78da,0x78fd,0x78f4,0x7907,0x7912,0x7911,0x7919,0x792c,0x792b, + 0x7940,0x7960,0x7957,0x795f,0x795a,0x7955,0x7953,0x797a,0x797f, + 0x798a,0x799d,0x79a7,0x9f4b,0x79aa,0x79ae,0x79b3,0x79b9,0x79ba, + 0x79c9,0x79d5,0x79e7,0x79ec,0x79e1,0x79e3,0x7a08,0x7a0d,0x7a18, + 0x7a19,0x7a20,0x7a1f,0x7980,0x7a31,0x7a3b,0x7a3e,0x7a37,0x7a43, + 0x7a57,0x7a49,0x7a61,0x7a62,0x7a69,0x9f9d,0x7a70,0x7a79,0x7a7d, + 0x7a88,0x7a97,0x7a95,0x7a98,0x7a96,0x7aa9,0x7ac8,0x7ab0,UDCODE, + 0x7ab6,0x7ac5,0x7ac4,0x7abf,0x9083,0x7ac7,0x7aca,0x7acd,0x7acf, + 0x7ad5,0x7ad3,0x7ad9,0x7ada,0x7add,0x7ae1,0x7ae2,0x7ae6,0x7aed, + 0x7af0,0x7b02,0x7b0f,0x7b0a,0x7b06,0x7b33,0x7b18,0x7b19,0x7b1e, + 0x7b35,0x7b28,0x7b36,0x7b50,0x7b7a,0x7b04,0x7b4d,0x7b0b,0x7b4c, + 0x7b45,0x7b75,0x7b65,0x7b74,0x7b67,0x7b70,0x7b71,0x7b6c,0x7b6e, + 0x7b9d,0x7b98,0x7b9f,0x7b8d,0x7b9c,0x7b9a,0x7b8b,0x7b92,0x7b8f, + 0x7b5d,0x7b99,0x7bcb,0x7bc1,0x7bcc,0x7bcf,0x7bb4,0x7bc6,0x7bdd, + 0x7be9,0x7c11,0x7c14,0x7be6,0x7be5,0x7c60,0x7c00,0x7c07,0x7c13, + 0x7bf3,0x7bf7,0x7c17,0x7c0d,0x7bf6,0x7c23,0x7c27,0x7c2a,0x7c1f, + 0x7c37,0x7c2b,0x7c3d,0x7c4c,0x7c43,0x7c54,0x7c4f,0x7c40,0x7c50, + 0x7c58,0x7c5f,0x7c64,0x7c56,0x7c65,0x7c6c,0x7c75,0x7c83,0x7c90, + 0x7ca4,0x7cad,0x7ca2,0x7cab,0x7ca1,0x7ca8,0x7cb3,0x7cb2,0x7cb1, + 0x7cae,0x7cb9,0x7cbd,0x7cc0,0x7cc5,0x7cc2,0x7cd8,0x7cd2,0x7cdc, + 0x7ce2,0x9b3b,0x7cef,0x7cf2,0x7cf4,0x7cf6,0x7cfa,0x7d06,0x7d02, + 0x7d1c,0x7d15,0x7d0a,0x7d45,0x7d4b,0x7d2e,0x7d32,0x7d3f,0x7d35, + 0x7d46,0x7d73,0x7d56,0x7d4e,0x7d72,0x7d68,0x7d6e,0x7d4f,0x7d63, + 0x7d93,0x7d89,0x7d5b,0x7d8f,0x7d7d,0x7d9b,0x7dba,0x7dae,0x7da3, + 0x7db5,0x7dc7,0x7dbd,0x7dab,0x7e3d,0x7da2,0x7daf,0x7ddc,0x7db8, + 0x7d9f,0x7db0,0x7dd8,0x7ddd,0x7de4,0x7dde,0x7dfb,0x7df2,0x7de1, + 0x7e05,0x7e0a,0x7e23,0x7e21,0x7e12,0x7e31,0x7e1f,0x7e09,0x7e0b, + 0x7e22,0x7e46,0x7e66,0x7e3b,0x7e35,0x7e39,0x7e43,0x7e37,UDCODE, + 0x7e32,0x7e3a,0x7e67,0x7e5d,0x7e56,0x7e5e,0x7e59,0x7e5a,0x7e79, + 0x7e6a,0x7e69,0x7e7c,0x7e7b,0x7e83,0x7dd5,0x7e7d,0x8fae,0x7e7f, + 0x7e88,0x7e89,0x7e8c,0x7e92,0x7e90,0x7e93,0x7e94,0x7e96,0x7e8e, + 0x7e9b,0x7e9c,0x7f38,0x7f3a,0x7f45,0x7f4c,0x7f4d,0x7f4e,0x7f50, + 0x7f51,0x7f55,0x7f54,0x7f58,0x7f5f,0x7f60,0x7f68,0x7f69,0x7f67, + 0x7f78,0x7f82,0x7f86,0x7f83,0x7f88,0x7f87,0x7f8c,0x7f94,0x7f9e, + 0x7f9d,0x7f9a,0x7fa3,0x7faf,0x7fb2,0x7fb9,0x7fae,0x7fb6,0x7fb8, + 0x8b71,0x7fc5,0x7fc6,0x7fca,0x7fd5,0x7fd4,0x7fe1,0x7fe6,0x7fe9, + 0x7ff3,0x7ff9,0x98dc,0x8006,0x8004,0x800b,0x8012,0x8018,0x8019, + 0x801c,0x8021,0x8028,0x803f,0x803b,0x804a,0x8046,0x8052,0x8058, + 0x805a,0x805f,0x8062,0x8068,0x8073,0x8072,0x8070,0x8076,0x8079, + 0x807d,0x807f,0x8084,0x8086,0x8085,0x809b,0x8093,0x809a,0x80ad, + 0x5190,0x80ac,0x80db,0x80e5,0x80d9,0x80dd,0x80c4,0x80da,0x80d6, + 0x8109,0x80ef,0x80f1,0x811b,0x8129,0x8123,0x812f,0x814b,0x968b, + 0x8146,0x813e,0x8153,0x8151,0x80fc,0x8171,0x816e,0x8165,0x8166, + 0x8174,0x8183,0x8188,0x818a,0x8180,0x8182,0x81a0,0x8195,0x81a4, + 0x81a3,0x815f,0x8193,0x81a9,0x81b0,0x81b5,0x81be,0x81b8,0x81bd, + 0x81c0,0x81c2,0x81ba,0x81c9,0x81cd,0x81d1,0x81d9,0x81d8,0x81c8, + 0x81da,0x81df,0x81e0,0x81e7,0x81fa,0x81fb,0x81fe,0x8201,0x8202, + 0x8205,0x8207,0x820a,0x820d,0x8210,0x8216,0x8229,0x822b,0x8238, + 0x8233,0x8240,0x8259,0x8258,0x825d,0x825a,0x825f,0x8264,UDCODE, + 0x8262,0x8268,0x826a,0x826b,0x822e,0x8271,0x8277,0x8278,0x827e, + 0x828d,0x8292,0x82ab,0x829f,0x82bb,0x82ac,0x82e1,0x82e3,0x82df, + 0x82d2,0x82f4,0x82f3,0x82fa,0x8393,0x8303,0x82fb,0x82f9,0x82de, + 0x8306,0x82dc,0x8309,0x82d9,0x8335,0x8334,0x8316,0x8332,0x8331, + 0x8340,0x8339,0x8350,0x8345,0x832f,0x832b,0x8317,0x8318,0x8385, + 0x839a,0x83aa,0x839f,0x83a2,0x8396,0x8323,0x838e,0x8387,0x838a, + 0x837c,0x83b5,0x8373,0x8375,0x83a0,0x8389,0x83a8,0x83f4,0x8413, + 0x83eb,0x83ce,0x83fd,0x8403,0x83d8,0x840b,0x83c1,0x83f7,0x8407, + 0x83e0,0x83f2,0x840d,0x8422,0x8420,0x83bd,0x8438,0x8506,0x83fb, + 0x846d,0x842a,0x843c,0x855a,0x8484,0x8477,0x846b,0x84ad,0x846e, + 0x8482,0x8469,0x8446,0x842c,0x846f,0x8479,0x8435,0x84ca,0x8462, + 0x84b9,0x84bf,0x849f,0x84d9,0x84cd,0x84bb,0x84da,0x84d0,0x84c1, + 0x84c6,0x84d6,0x84a1,0x8521,0x84ff,0x84f4,0x8517,0x8518,0x852c, + 0x851f,0x8515,0x8514,0x84fc,0x8540,0x8563,0x8558,0x8548,0x8541, + 0x8602,0x854b,0x8555,0x8580,0x85a4,0x8588,0x8591,0x858a,0x85a8, + 0x856d,0x8594,0x859b,0x85ea,0x8587,0x859c,0x8577,0x857e,0x8590, + 0x85c9,0x85ba,0x85cf,0x85b9,0x85d0,0x85d5,0x85dd,0x85e5,0x85dc, + 0x85f9,0x860a,0x8613,0x860b,0x85fe,0x85fa,0x8606,0x8622,0x861a, + 0x8630,0x863f,0x864d,0x4e55,0x8654,0x865f,0x8667,0x8671,0x8693, + 0x86a3,0x86a9,0x86aa,0x868b,0x868c,0x86b6,0x86af,0x86c4,0x86c6, + 0x86b0,0x86c9,0x8823,0x86ab,0x86d4,0x86de,0x86e9,0x86ec,UDCODE, + 0x86df,0x86db,0x86ef,0x8712,0x8706,0x8708,0x8700,0x8703,0x86fb, + 0x8711,0x8709,0x870d,0x86f9,0x870a,0x8734,0x873f,0x8737,0x873b, + 0x8725,0x8729,0x871a,0x8760,0x875f,0x8778,0x874c,0x874e,0x8774, + 0x8757,0x8768,0x876e,0x8759,0x8753,0x8763,0x876a,0x8805,0x87a2, + 0x879f,0x8782,0x87af,0x87cb,0x87bd,0x87c0,0x87d0,0x96d6,0x87ab, + 0x87c4,0x87b3,0x87c7,0x87c6,0x87bb,0x87ef,0x87f2,0x87e0,0x880f, + 0x880d,0x87fe,0x87f6,0x87f7,0x880e,0x87d2,0x8811,0x8816,0x8815, + 0x8822,0x8821,0x8831,0x8836,0x8839,0x8827,0x883b,0x8844,0x8842, + 0x8852,0x8859,0x885e,0x8862,0x886b,0x8881,0x887e,0x889e,0x8875, + 0x887d,0x88b5,0x8872,0x8882,0x8897,0x8892,0x88ae,0x8899,0x88a2, + 0x888d,0x88a4,0x88b0,0x88bf,0x88b1,0x88c3,0x88c4,0x88d4,0x88d8, + 0x88d9,0x88dd,0x88f9,0x8902,0x88fc,0x88f4,0x88e8,0x88f2,0x8904, + 0x890c,0x890a,0x8913,0x8943,0x891e,0x8925,0x892a,0x892b,0x8941, + 0x8944,0x893b,0x8936,0x8938,0x894c,0x891d,0x8960,0x895e,0x8966, + 0x8964,0x896d,0x896a,0x896f,0x8974,0x8977,0x897e,0x8983,0x8988, + 0x898a,0x8993,0x8998,0x89a1,0x89a9,0x89a6,0x89ac,0x89af,0x89b2, + 0x89ba,0x89bd,0x89bf,0x89c0,0x89da,0x89dc,0x89dd,0x89e7,0x89f4, + 0x89f8,0x8a03,0x8a16,0x8a10,0x8a0c,0x8a1b,0x8a1d,0x8a25,0x8a36, + 0x8a41,0x8a5b,0x8a52,0x8a46,0x8a48,0x8a7c,0x8a6d,0x8a6c,0x8a62, + 0x8a85,0x8a82,0x8a84,0x8aa8,0x8aa1,0x8a91,0x8aa5,0x8aa6,0x8a9a, + 0x8aa3,0x8ac4,0x8acd,0x8ac2,0x8ada,0x8aeb,0x8af3,0x8ae7,UDCODE, + 0x8ae4,0x8af1,0x8b14,0x8ae0,0x8ae2,0x8af7,0x8ade,0x8adb,0x8b0c, + 0x8b07,0x8b1a,0x8ae1,0x8b16,0x8b10,0x8b17,0x8b20,0x8b33,0x97ab, + 0x8b26,0x8b2b,0x8b3e,0x8b28,0x8b41,0x8b4c,0x8b4f,0x8b4e,0x8b49, + 0x8b56,0x8b5b,0x8b5a,0x8b6b,0x8b5f,0x8b6c,0x8b6f,0x8b74,0x8b7d, + 0x8b80,0x8b8c,0x8b8e,0x8b92,0x8b93,0x8b96,0x8b99,0x8b9a,0x8c3a, + 0x8c41,0x8c3f,0x8c48,0x8c4c,0x8c4e,0x8c50,0x8c55,0x8c62,0x8c6c, + 0x8c78,0x8c7a,0x8c82,0x8c89,0x8c85,0x8c8a,0x8c8d,0x8c8e,0x8c94, + 0x8c7c,0x8c98,0x621d,0x8cad,0x8caa,0x8cbd,0x8cb2,0x8cb3,0x8cae, + 0x8cb6,0x8cc8,0x8cc1,0x8ce4,0x8ce3,0x8cda,0x8cfd,0x8cfa,0x8cfb, + 0x8d04,0x8d05,0x8d0a,0x8d07,0x8d0f,0x8d0d,0x8d10,0x9f4e,0x8d13, + 0x8ccd,0x8d14,0x8d16,0x8d67,0x8d6d,0x8d71,0x8d73,0x8d81,0x8d99, + 0x8dc2,0x8dbe,0x8dba,0x8dcf,0x8dda,0x8dd6,0x8dcc,0x8ddb,0x8dcb, + 0x8dea,0x8deb,0x8ddf,0x8de3,0x8dfc,0x8e08,0x8e09,0x8dff,0x8e1d, + 0x8e1e,0x8e10,0x8e1f,0x8e42,0x8e35,0x8e30,0x8e34,0x8e4a,0x8e47, + 0x8e49,0x8e4c,0x8e50,0x8e48,0x8e59,0x8e64,0x8e60,0x8e2a,0x8e63, + 0x8e55,0x8e76,0x8e72,0x8e7c,0x8e81,0x8e87,0x8e85,0x8e84,0x8e8b, + 0x8e8a,0x8e93,0x8e91,0x8e94,0x8e99,0x8eaa,0x8ea1,0x8eac,0x8eb0, + 0x8ec6,0x8eb1,0x8ebe,0x8ec5,0x8ec8,0x8ecb,0x8edb,0x8ee3,0x8efc, + 0x8efb,0x8eeb,0x8efe,0x8f0a,0x8f05,0x8f15,0x8f12,0x8f19,0x8f13, + 0x8f1c,0x8f1f,0x8f1b,0x8f0c,0x8f26,0x8f33,0x8f3b,0x8f39,0x8f45, + 0x8f42,0x8f3e,0x8f4c,0x8f49,0x8f46,0x8f4e,0x8f57,0x8f5c,UDCODE, + 0x8f62,0x8f63,0x8f64,0x8f9c,0x8f9f,0x8fa3,0x8fad,0x8faf,0x8fb7, + 0x8fda,0x8fe5,0x8fe2,0x8fea,0x8fef,0x9087,0x8ff4,0x9005,0x8ff9, + 0x8ffa,0x9011,0x9015,0x9021,0x900d,0x901e,0x9016,0x900b,0x9027, + 0x9036,0x9035,0x9039,0x8ff8,0x904f,0x9050,0x9051,0x9052,0x900e, + 0x9049,0x903e,0x9056,0x9058,0x905e,0x9068,0x906f,0x9076,0x96a8, + 0x9072,0x9082,0x907d,0x9081,0x9080,0x908a,0x9089,0x908f,0x90a8, + 0x90af,0x90b1,0x90b5,0x90e2,0x90e4,0x6248,0x90db,0x9102,0x9112, + 0x9119,0x9132,0x9130,0x914a,0x9156,0x9158,0x9163,0x9165,0x9169, + 0x9173,0x9172,0x918b,0x9189,0x9182,0x91a2,0x91ab,0x91af,0x91aa, + 0x91b5,0x91b4,0x91ba,0x91c0,0x91c1,0x91c9,0x91cb,0x91d0,0x91d6, + 0x91df,0x91e1,0x91db,0x91fc,0x91f5,0x91f6,0x921e,0x91ff,0x9214, + 0x922c,0x9215,0x9211,0x925e,0x9257,0x9245,0x9249,0x9264,0x9248, + 0x9295,0x923f,0x924b,0x9250,0x929c,0x9296,0x9293,0x929b,0x925a, + 0x92cf,0x92b9,0x92b7,0x92e9,0x930f,0x92fa,0x9344,0x932e,0x9319, + 0x9322,0x931a,0x9323,0x933a,0x9335,0x933b,0x935c,0x9360,0x937c, + 0x936e,0x9356,0x93b0,0x93ac,0x93ad,0x9394,0x93b9,0x93d6,0x93d7, + 0x93e8,0x93e5,0x93d8,0x93c3,0x93dd,0x93d0,0x93c8,0x93e4,0x941a, + 0x9414,0x9413,0x9403,0x9407,0x9410,0x9436,0x942b,0x9435,0x9421, + 0x943a,0x9441,0x9452,0x9444,0x945b,0x9460,0x9462,0x945e,0x946a, + 0x9229,0x9470,0x9475,0x9477,0x947d,0x945a,0x947c,0x947e,0x9481, + 0x947f,0x9582,0x9587,0x958a,0x9594,0x9596,0x9598,0x9599,UDCODE, + 0x95a0,0x95a8,0x95a7,0x95ad,0x95bc,0x95bb,0x95b9,0x95be,0x95ca, + 0x6ff6,0x95c3,0x95cd,0x95cc,0x95d5,0x95d4,0x95d6,0x95dc,0x95e1, + 0x95e5,0x95e2,0x9621,0x9628,0x962e,0x962f,0x9642,0x964c,0x964f, + 0x964b,0x9677,0x965c,0x965e,0x965d,0x965f,0x9666,0x9672,0x966c, + 0x968d,0x9698,0x9695,0x9697,0x96aa,0x96a7,0x96b1,0x96b2,0x96b0, + 0x96b4,0x96b6,0x96b8,0x96b9,0x96ce,0x96cb,0x96c9,0x96cd,0x894d, + 0x96dc,0x970d,0x96d5,0x96f9,0x9704,0x9706,0x9708,0x9713,0x970e, + 0x9711,0x970f,0x9716,0x9719,0x9724,0x972a,0x9730,0x9739,0x973d, + 0x973e,0x9744,0x9746,0x9748,0x9742,0x9749,0x975c,0x9760,0x9764, + 0x9766,0x9768,0x52d2,0x976b,0x9771,0x9779,0x9785,0x977c,0x9781, + 0x977a,0x9786,0x978b,0x978f,0x9790,0x979c,0x97a8,0x97a6,0x97a3, + 0x97b3,0x97b4,0x97c3,0x97c6,0x97c8,0x97cb,0x97dc,0x97ed,0x9f4f, + 0x97f2,0x7adf,0x97f6,0x97f5,0x980f,0x980c,0x9838,0x9824,0x9821, + 0x9837,0x983d,0x9846,0x984f,0x984b,0x986b,0x986f,0x9870,0x9871, + 0x9874,0x9873,0x98aa,0x98af,0x98b1,0x98b6,0x98c4,0x98c3,0x98c6, + 0x98e9,0x98eb,0x9903,0x9909,0x9912,0x9914,0x9918,0x9921,0x991d, + 0x991e,0x9924,0x9920,0x992c,0x992e,0x993d,0x993e,0x9942,0x9949, + 0x9945,0x9950,0x994b,0x9951,0x9952,0x994c,0x9955,0x9997,0x9998, + 0x99a5,0x99ad,0x99ae,0x99bc,0x99df,0x99db,0x99dd,0x99d8,0x99d1, + 0x99ed,0x99ee,0x99f1,0x99f2,0x99fb,0x99f8,0x9a01,0x9a0f,0x9a05, + 0x99e2,0x9a19,0x9a2b,0x9a37,0x9a45,0x9a42,0x9a40,0x9a43,UDCODE, + 0x9a3e,0x9a55,0x9a4d,0x9a5b,0x9a57,0x9a5f,0x9a62,0x9a65,0x9a64, + 0x9a69,0x9a6b,0x9a6a,0x9aad,0x9ab0,0x9abc,0x9ac0,0x9acf,0x9ad1, + 0x9ad3,0x9ad4,0x9ade,0x9adf,0x9ae2,0x9ae3,0x9ae6,0x9aef,0x9aeb, + 0x9aee,0x9af4,0x9af1,0x9af7,0x9afb,0x9b06,0x9b18,0x9b1a,0x9b1f, + 0x9b22,0x9b23,0x9b25,0x9b27,0x9b28,0x9b29,0x9b2a,0x9b2e,0x9b2f, + 0x9b32,0x9b44,0x9b43,0x9b4f,0x9b4d,0x9b4e,0x9b51,0x9b58,0x9b74, + 0x9b93,0x9b83,0x9b91,0x9b96,0x9b97,0x9b9f,0x9ba0,0x9ba8,0x9bb4, + 0x9bc0,0x9bca,0x9bb9,0x9bc6,0x9bcf,0x9bd1,0x9bd2,0x9be3,0x9be2, + 0x9be4,0x9bd4,0x9be1,0x9c3a,0x9bf2,0x9bf1,0x9bf0,0x9c15,0x9c14, + 0x9c09,0x9c13,0x9c0c,0x9c06,0x9c08,0x9c12,0x9c0a,0x9c04,0x9c2e, + 0x9c1b,0x9c25,0x9c24,0x9c21,0x9c30,0x9c47,0x9c32,0x9c46,0x9c3e, + 0x9c5a,0x9c60,0x9c67,0x9c76,0x9c78,0x9ce7,0x9cec,0x9cf0,0x9d09, + 0x9d08,0x9ceb,0x9d03,0x9d06,0x9d2a,0x9d26,0x9daf,0x9d23,0x9d1f, + 0x9d44,0x9d15,0x9d12,0x9d41,0x9d3f,0x9d3e,0x9d46,0x9d48,0x9d5d, + 0x9d5e,0x9d64,0x9d51,0x9d50,0x9d59,0x9d72,0x9d89,0x9d87,0x9dab, + 0x9d6f,0x9d7a,0x9d9a,0x9da4,0x9da9,0x9db2,0x9dc4,0x9dc1,0x9dbb, + 0x9db8,0x9dba,0x9dc6,0x9dcf,0x9dc2,0x9dd9,0x9dd3,0x9df8,0x9de6, + 0x9ded,0x9def,0x9dfd,0x9e1a,0x9e1b,0x9e1e,0x9e75,0x9e79,0x9e7d, + 0x9e81,0x9e88,0x9e8b,0x9e8c,0x9e92,0x9e95,0x9e91,0x9e9d,0x9ea5, + 0x9ea9,0x9eb8,0x9eaa,0x9ead,0x9761,0x9ecc,0x9ece,0x9ecf,0x9ed0, + 0x9ed4,0x9edc,0x9ede,0x9edd,0x9ee0,0x9ee5,0x9ee8,0x9eef,UDCODE, + 0x9ef4,0x9ef6,0x9ef7,0x9ef9,0x9efb,0x9efc,0x9efd,0x9f07,0x9f08, + 0x76b7,0x9f15,0x9f21,0x9f2c,0x9f3e,0x9f4a,0x9f52,0x9f54,0x9f63, + 0x9f5f,0x9f60,0x9f61,0x9f66,0x9f67,0x9f6c,0x9f6a,0x9f77,0x9f72, + 0x9f76,0x9f95,0x9f9c,0x9fa0,0x582f,0x69c7,0x9059,0x7464,0x51dc, + 0x7199,0x7e8a,0x891c,0x9348,0x9288,0x84dc,0x4fc9,0x70bb,0x6631, + 0x68c8,0x92f9,0x66fb,0x5f45,0x4e28,0x4ee1,0x4efc,0x4f00,0x4f03, + 0x4f39,0x4f56,0x4f92,0x4f8a,0x4f9a,0x4f94,0x4fcd,0x5040,0x5022, + 0x4fff,0x501e,0x5046,0x5070,0x5042,0x5094,0x50f4,0x50d8,0x514a, + 0x5164,0x519d,0x51be,0x51ec,0x5215,0x529c,0x52a6,0x52c0,0x52db, + 0x5300,0x5307,0x5324,0x5372,0x5393,0x53b2,0x53dd,0xfa0e,0x549c, + 0x548a,0x54a9,0x54ff,0x5586,0x5759,0x5765,0x57ac,0x57c8,0x57c7, + 0xfa0f,UDCODE,0xfa10,0x589e,0x58b2,0x590b,0x5953,0x595b,0x595d, + 0x5963,0x59a4,0x59ba,0x5b56,0x5bc0,0x752f,0x5bd8,0x5bec,0x5c1e, + 0x5ca6,0x5cba,0x5cf5,0x5d27,0x5d53,0xfa11,0x5d42,0x5d6d,0x5db8, + 0x5db9,0x5dd0,0x5f21,0x5f34,0x5f67,0x5fb7,0x5fde,0x605d,0x6085, + 0x608a,0x60de,0x60d5,0x6120,0x60f2,0x6111,0x6137,0x6130,0x6198, + 0x6213,0x62a6,0x63f5,0x6460,0x649d,0x64ce,0x654e,0x6600,0x6615, + 0x663b,0x6609,0x662e,0x661e,0x6624,0x6665,0x6657,0x6659,0xfa12, + 0x6673,0x6699,0x66a0,0x66b2,0x66bf,0x66fa,0x670e,0xf929,0x6766, + 0x67bb,0x6852,0x67c0,0x6801,0x6844,0x68cf,0xfa13,0x6968,0xfa14, + 0x6998,0x69e2,0x6a30,0x6a6b,0x6a46,0x6a73,0x6a7e,0x6ae2,0x6ae4, + 0x6bd6,0x6c3f,0x6c5c,0x6c86,0x6c6f,0x6cda,0x6d04,0x6d87,0x6d6f, + 0x6d96,0x6dac,0x6dcf,0x6df8,0x6df2,0x6dfc,0x6e39,0x6e5c,0x6e27, + 0x6e3c,0x6ebf,0x6f88,0x6fb5,0x6ff5,0x7005,0x7007,0x7028,0x7085, + 0x70ab,0x710f,0x7104,0x715c,0x7146,0x7147,0xfa15,0x71c1,0x71fe, + 0x72b1,0x72be,0x7324,0xfa16,0x7377,0x73bd,0x73c9,0x73d6,0x73e3, + 0x73d2,0x7407,0x73f5,0x7426,0x742a,0x7429,0x742e,0x7462,0x7489, + 0x749f,0x7501,0x756f,0x7682,0x769c,0x769e,0x769b,0x76a6,0xfa17, + 0x7746,0x52af,0x7821,0x784e,0x7864,0x787a,0x7930,0xfa18,0xfa19, + 0xfa1a,0x7994,0xfa1b,0x799b,0x7ad1,0x7ae7,0xfa1c,0x7aeb,0x7b9e, + 0xfa1d,0x7d48,0x7d5c,0x7db7,0x7da0,0x7dd6,0x7e52,0x7f47,0x7fa1, + 0xfa1e,0x8301,0x8362,0x837f,0x83c7,0x83f6,0x8448,0x84b4,0x8553, + 0x8559,UDCODE,0x856b,0xfa1f,0x85b0,0xfa20,0xfa21,0x8807,0x88f5, + 0x8a12,0x8a37,0x8a79,0x8aa7,0x8abe,0x8adf,0xfa22,0x8af6,0x8b53, + 0x8b7f,0x8cf0,0x8cf4,0x8d12,0x8d76,0xfa23,0x8ecf,0xfa24,0xfa25, + 0x9067,0x90de,0xfa26,0x9115,0x9127,0x91da,0x91d7,0x91de,0x91ed, + 0x91ee,0x91e4,0x91e5,0x9206,0x9210,0x920a,0x923a,0x9240,0x923c, + 0x924e,0x9259,0x9251,0x9239,0x9267,0x92a7,0x9277,0x9278,0x92e7, + 0x92d7,0x92d9,0x92d0,0xfa27,0x92d5,0x92e0,0x92d3,0x9325,0x9321, + 0x92fb,0xfa28,0x931e,0x92ff,0x931d,0x9302,0x9370,0x9357,0x93a4, + 0x93c6,0x93de,0x93f8,0x9431,0x9445,0x9448,0x9592,0xf9dc,0xfa29, + 0x969d,0x96af,0x9733,0x973b,0x9743,0x974d,0x974f,0x9751,0x9755, + 0x9857,0x9865,0xfa2a,0xfa2b,0x9927,0xfa2c,0x999e,0x9a4e,0x9ad9, + 0x9adc,0x9b75,0x9b72,0x9b8f,0x9bb1,0x9bbb,0x9c00,0x9d70,0x9d6b, + 0xfa2d,0x9e19,0x9ed1,UDCODE,UDCODE,0x2170,0x2171,0x2172,0x2173, + 0x2174,0x2175,0x2176,0x2177,0x2178,0x2179,0xffe2,0xffe4,0xff07, + 0xff02,0xe000,0xe001,0xe002,0xe003,0xe004,0xe005,0xe006,0xe007, + 0xe008,0xe009,0xe00a,0xe00b,0xe00c,0xe00d,0xe00e,0xe00f,0xe010, + 0xe011,0xe012,0xe013,0xe014,0xe015,0xe016,0xe017,0xe018,0xe019, + 0xe01a,0xe01b,0xe01c,0xe01d,0xe01e,0xe01f,0xe020,0xe021,0xe022, + 0xe023,0xe024,0xe025,0xe026,0xe027,0xe028,0xe029,0xe02a,0xe02b, + 0xe02c,0xe02d,0xe02e,0xe02f,0xe030,0xe031,0xe032,0xe033,0xe034, + 0xe035,0xe036,0xe037,0xe038,0xe039,0xe03a,0xe03b,0xe03c,0xe03d, + 0xe03e,UDCODE,0xe03f,0xe040,0xe041,0xe042,0xe043,0xe044,0xe045, + 0xe046,0xe047,0xe048,0xe049,0xe04a,0xe04b,0xe04c,0xe04d,0xe04e, + 0xe04f,0xe050,0xe051,0xe052,0xe053,0xe054,0xe055,0xe056,0xe057, + 0xe058,0xe059,0xe05a,0xe05b,0xe05c,0xe05d,0xe05e,0xe05f,0xe060, + 0xe061,0xe062,0xe063,0xe064,0xe065,0xe066,0xe067,0xe068,0xe069, + 0xe06a,0xe06b,0xe06c,0xe06d,0xe06e,0xe06f,0xe070,0xe071,0xe072, + 0xe073,0xe074,0xe075,0xe076,0xe077,0xe078,0xe079,0xe07a,0xe07b, + 0xe07c,0xe07d,0xe07e,0xe07f,0xe080,0xe081,0xe082,0xe083,0xe084, + 0xe085,0xe086,0xe087,0xe088,0xe089,0xe08a,0xe08b,0xe08c,0xe08d, + 0xe08e,0xe08f,0xe090,0xe091,0xe092,0xe093,0xe094,0xe095,0xe096, + 0xe097,0xe098,0xe099,0xe09a,0xe09b,0xe09c,0xe09d,0xe09e,0xe09f, + 0xe0a0,0xe0a1,0xe0a2,0xe0a3,0xe0a4,0xe0a5,0xe0a6,0xe0a7,0xe0a8, + 0xe0a9,0xe0aa,0xe0ab,0xe0ac,0xe0ad,0xe0ae,0xe0af,0xe0b0,0xe0b1, + 0xe0b2,0xe0b3,0xe0b4,0xe0b5,0xe0b6,0xe0b7,0xe0b8,0xe0b9,0xe0ba, + 0xe0bb,0xe0bc,0xe0bd,0xe0be,0xe0bf,0xe0c0,0xe0c1,0xe0c2,0xe0c3, + 0xe0c4,0xe0c5,0xe0c6,0xe0c7,0xe0c8,0xe0c9,0xe0ca,0xe0cb,0xe0cc, + 0xe0cd,0xe0ce,0xe0cf,0xe0d0,0xe0d1,0xe0d2,0xe0d3,0xe0d4,0xe0d5, + 0xe0d6,0xe0d7,0xe0d8,0xe0d9,0xe0da,0xe0db,0xe0dc,0xe0dd,0xe0de, + 0xe0df,0xe0e0,0xe0e1,0xe0e2,0xe0e3,0xe0e4,0xe0e5,0xe0e6,0xe0e7, + 0xe0e8,0xe0e9,0xe0ea,0xe0eb,0xe0ec,0xe0ed,0xe0ee,0xe0ef,0xe0f0, + 0xe0f1,0xe0f2,0xe0f3,0xe0f4,0xe0f5,0xe0f6,0xe0f7,0xe0f8,0xe0f9, + 0xe0fa,UDCODE,0xe0fb,0xe0fc,0xe0fd,0xe0fe,0xe0ff,0xe100,0xe101, + 0xe102,0xe103,0xe104,0xe105,0xe106,0xe107,0xe108,0xe109,0xe10a, + 0xe10b,0xe10c,0xe10d,0xe10e,0xe10f,0xe110,0xe111,0xe112,0xe113, + 0xe114,0xe115,0xe116,0xe117,0xe118,0xe119,0xe11a,0xe11b,0xe11c, + 0xe11d,0xe11e,0xe11f,0xe120,0xe121,0xe122,0xe123,0xe124,0xe125, + 0xe126,0xe127,0xe128,0xe129,0xe12a,0xe12b,0xe12c,0xe12d,0xe12e, + 0xe12f,0xe130,0xe131,0xe132,0xe133,0xe134,0xe135,0xe136,0xe137, + 0xe138,0xe139,0xe13a,0xe13b,0xe13c,0xe13d,0xe13e,0xe13f,0xe140, + 0xe141,0xe142,0xe143,0xe144,0xe145,0xe146,0xe147,0xe148,0xe149, + 0xe14a,0xe14b,0xe14c,0xe14d,0xe14e,0xe14f,0xe150,0xe151,0xe152, + 0xe153,0xe154,0xe155,0xe156,0xe157,0xe158,0xe159,0xe15a,0xe15b, + 0xe15c,0xe15d,0xe15e,0xe15f,0xe160,0xe161,0xe162,0xe163,0xe164, + 0xe165,0xe166,0xe167,0xe168,0xe169,0xe16a,0xe16b,0xe16c,0xe16d, + 0xe16e,0xe16f,0xe170,0xe171,0xe172,0xe173,0xe174,0xe175,0xe176, + 0xe177,0xe178,0xe179,0xe17a,0xe17b,0xe17c,0xe17d,0xe17e,0xe17f, + 0xe180,0xe181,0xe182,0xe183,0xe184,0xe185,0xe186,0xe187,0xe188, + 0xe189,0xe18a,0xe18b,0xe18c,0xe18d,0xe18e,0xe18f,0xe190,0xe191, + 0xe192,0xe193,0xe194,0xe195,0xe196,0xe197,0xe198,0xe199,0xe19a, + 0xe19b,0xe19c,0xe19d,0xe19e,0xe19f,0xe1a0,0xe1a1,0xe1a2,0xe1a3, + 0xe1a4,0xe1a5,0xe1a6,0xe1a7,0xe1a8,0xe1a9,0xe1aa,0xe1ab,0xe1ac, + 0xe1ad,0xe1ae,0xe1af,0xe1b0,0xe1b1,0xe1b2,0xe1b3,0xe1b4,0xe1b5, + 0xe1b6,UDCODE,0xe1b7,0xe1b8,0xe1b9,0xe1ba,0xe1bb,0xe1bc,0xe1bd, + 0xe1be,0xe1bf,0xe1c0,0xe1c1,0xe1c2,0xe1c3,0xe1c4,0xe1c5,0xe1c6, + 0xe1c7,0xe1c8,0xe1c9,0xe1ca,0xe1cb,0xe1cc,0xe1cd,0xe1ce,0xe1cf, + 0xe1d0,0xe1d1,0xe1d2,0xe1d3,0xe1d4,0xe1d5,0xe1d6,0xe1d7,0xe1d8, + 0xe1d9,0xe1da,0xe1db,0xe1dc,0xe1dd,0xe1de,0xe1df,0xe1e0,0xe1e1, + 0xe1e2,0xe1e3,0xe1e4,0xe1e5,0xe1e6,0xe1e7,0xe1e8,0xe1e9,0xe1ea, + 0xe1eb,0xe1ec,0xe1ed,0xe1ee,0xe1ef,0xe1f0,0xe1f1,0xe1f2,0xe1f3, + 0xe1f4,0xe1f5,0xe1f6,0xe1f7,0xe1f8,0xe1f9,0xe1fa,0xe1fb,0xe1fc, + 0xe1fd,0xe1fe,0xe1ff,0xe200,0xe201,0xe202,0xe203,0xe204,0xe205, + 0xe206,0xe207,0xe208,0xe209,0xe20a,0xe20b,0xe20c,0xe20d,0xe20e, + 0xe20f,0xe210,0xe211,0xe212,0xe213,0xe214,0xe215,0xe216,0xe217, + 0xe218,0xe219,0xe21a,0xe21b,0xe21c,0xe21d,0xe21e,0xe21f,0xe220, + 0xe221,0xe222,0xe223,0xe224,0xe225,0xe226,0xe227,0xe228,0xe229, + 0xe22a,0xe22b,0xe22c,0xe22d,0xe22e,0xe22f,0xe230,0xe231,0xe232, + 0xe233,0xe234,0xe235,0xe236,0xe237,0xe238,0xe239,0xe23a,0xe23b, + 0xe23c,0xe23d,0xe23e,0xe23f,0xe240,0xe241,0xe242,0xe243,0xe244, + 0xe245,0xe246,0xe247,0xe248,0xe249,0xe24a,0xe24b,0xe24c,0xe24d, + 0xe24e,0xe24f,0xe250,0xe251,0xe252,0xe253,0xe254,0xe255,0xe256, + 0xe257,0xe258,0xe259,0xe25a,0xe25b,0xe25c,0xe25d,0xe25e,0xe25f, + 0xe260,0xe261,0xe262,0xe263,0xe264,0xe265,0xe266,0xe267,0xe268, + 0xe269,0xe26a,0xe26b,0xe26c,0xe26d,0xe26e,0xe26f,0xe270,0xe271, + 0xe272,UDCODE,0xe273,0xe274,0xe275,0xe276,0xe277,0xe278,0xe279, + 0xe27a,0xe27b,0xe27c,0xe27d,0xe27e,0xe27f,0xe280,0xe281,0xe282, + 0xe283,0xe284,0xe285,0xe286,0xe287,0xe288,0xe289,0xe28a,0xe28b, + 0xe28c,0xe28d,0xe28e,0xe28f,0xe290,0xe291,0xe292,0xe293,0xe294, + 0xe295,0xe296,0xe297,0xe298,0xe299,0xe29a,0xe29b,0xe29c,0xe29d, + 0xe29e,0xe29f,0xe2a0,0xe2a1,0xe2a2,0xe2a3,0xe2a4,0xe2a5,0xe2a6, + 0xe2a7,0xe2a8,0xe2a9,0xe2aa,0xe2ab,0xe2ac,0xe2ad,0xe2ae,0xe2af, + 0xe2b0,0xe2b1,0xe2b2,0xe2b3,0xe2b4,0xe2b5,0xe2b6,0xe2b7,0xe2b8, + 0xe2b9,0xe2ba,0xe2bb,0xe2bc,0xe2bd,0xe2be,0xe2bf,0xe2c0,0xe2c1, + 0xe2c2,0xe2c3,0xe2c4,0xe2c5,0xe2c6,0xe2c7,0xe2c8,0xe2c9,0xe2ca, + 0xe2cb,0xe2cc,0xe2cd,0xe2ce,0xe2cf,0xe2d0,0xe2d1,0xe2d2,0xe2d3, + 0xe2d4,0xe2d5,0xe2d6,0xe2d7,0xe2d8,0xe2d9,0xe2da,0xe2db,0xe2dc, + 0xe2dd,0xe2de,0xe2df,0xe2e0,0xe2e1,0xe2e2,0xe2e3,0xe2e4,0xe2e5, + 0xe2e6,0xe2e7,0xe2e8,0xe2e9,0xe2ea,0xe2eb,0xe2ec,0xe2ed,0xe2ee, + 0xe2ef,0xe2f0,0xe2f1,0xe2f2,0xe2f3,0xe2f4,0xe2f5,0xe2f6,0xe2f7, + 0xe2f8,0xe2f9,0xe2fa,0xe2fb,0xe2fc,0xe2fd,0xe2fe,0xe2ff,0xe300, + 0xe301,0xe302,0xe303,0xe304,0xe305,0xe306,0xe307,0xe308,0xe309, + 0xe30a,0xe30b,0xe30c,0xe30d,0xe30e,0xe30f,0xe310,0xe311,0xe312, + 0xe313,0xe314,0xe315,0xe316,0xe317,0xe318,0xe319,0xe31a,0xe31b, + 0xe31c,0xe31d,0xe31e,0xe31f,0xe320,0xe321,0xe322,0xe323,0xe324, + 0xe325,0xe326,0xe327,0xe328,0xe329,0xe32a,0xe32b,0xe32c,0xe32d, + 0xe32e,UDCODE,0xe32f,0xe330,0xe331,0xe332,0xe333,0xe334,0xe335, + 0xe336,0xe337,0xe338,0xe339,0xe33a,0xe33b,0xe33c,0xe33d,0xe33e, + 0xe33f,0xe340,0xe341,0xe342,0xe343,0xe344,0xe345,0xe346,0xe347, + 0xe348,0xe349,0xe34a,0xe34b,0xe34c,0xe34d,0xe34e,0xe34f,0xe350, + 0xe351,0xe352,0xe353,0xe354,0xe355,0xe356,0xe357,0xe358,0xe359, + 0xe35a,0xe35b,0xe35c,0xe35d,0xe35e,0xe35f,0xe360,0xe361,0xe362, + 0xe363,0xe364,0xe365,0xe366,0xe367,0xe368,0xe369,0xe36a,0xe36b, + 0xe36c,0xe36d,0xe36e,0xe36f,0xe370,0xe371,0xe372,0xe373,0xe374, + 0xe375,0xe376,0xe377,0xe378,0xe379,0xe37a,0xe37b,0xe37c,0xe37d, + 0xe37e,0xe37f,0xe380,0xe381,0xe382,0xe383,0xe384,0xe385,0xe386, + 0xe387,0xe388,0xe389,0xe38a,0xe38b,0xe38c,0xe38d,0xe38e,0xe38f, + 0xe390,0xe391,0xe392,0xe393,0xe394,0xe395,0xe396,0xe397,0xe398, + 0xe399,0xe39a,0xe39b,0xe39c,0xe39d,0xe39e,0xe39f,0xe3a0,0xe3a1, + 0xe3a2,0xe3a3,0xe3a4,0xe3a5,0xe3a6,0xe3a7,0xe3a8,0xe3a9,0xe3aa, + 0xe3ab,0xe3ac,0xe3ad,0xe3ae,0xe3af,0xe3b0,0xe3b1,0xe3b2,0xe3b3, + 0xe3b4,0xe3b5,0xe3b6,0xe3b7,0xe3b8,0xe3b9,0xe3ba,0xe3bb,0xe3bc, + 0xe3bd,0xe3be,0xe3bf,0xe3c0,0xe3c1,0xe3c2,0xe3c3,0xe3c4,0xe3c5, + 0xe3c6,0xe3c7,0xe3c8,0xe3c9,0xe3ca,0xe3cb,0xe3cc,0xe3cd,0xe3ce, + 0xe3cf,0xe3d0,0xe3d1,0xe3d2,0xe3d3,0xe3d4,0xe3d5,0xe3d6,0xe3d7, + 0xe3d8,0xe3d9,0xe3da,0xe3db,0xe3dc,0xe3dd,0xe3de,0xe3df,0xe3e0, + 0xe3e1,0xe3e2,0xe3e3,0xe3e4,0xe3e5,0xe3e6,0xe3e7,0xe3e8,0xe3e9, + 0xe3ea,UDCODE,0xe3eb,0xe3ec,0xe3ed,0xe3ee,0xe3ef,0xe3f0,0xe3f1, + 0xe3f2,0xe3f3,0xe3f4,0xe3f5,0xe3f6,0xe3f7,0xe3f8,0xe3f9,0xe3fa, + 0xe3fb,0xe3fc,0xe3fd,0xe3fe,0xe3ff,0xe400,0xe401,0xe402,0xe403, + 0xe404,0xe405,0xe406,0xe407,0xe408,0xe409,0xe40a,0xe40b,0xe40c, + 0xe40d,0xe40e,0xe40f,0xe410,0xe411,0xe412,0xe413,0xe414,0xe415, + 0xe416,0xe417,0xe418,0xe419,0xe41a,0xe41b,0xe41c,0xe41d,0xe41e, + 0xe41f,0xe420,0xe421,0xe422,0xe423,0xe424,0xe425,0xe426,0xe427, + 0xe428,0xe429,0xe42a,0xe42b,0xe42c,0xe42d,0xe42e,0xe42f,0xe430, + 0xe431,0xe432,0xe433,0xe434,0xe435,0xe436,0xe437,0xe438,0xe439, + 0xe43a,0xe43b,0xe43c,0xe43d,0xe43e,0xe43f,0xe440,0xe441,0xe442, + 0xe443,0xe444,0xe445,0xe446,0xe447,0xe448,0xe449,0xe44a,0xe44b, + 0xe44c,0xe44d,0xe44e,0xe44f,0xe450,0xe451,0xe452,0xe453,0xe454, + 0xe455,0xe456,0xe457,0xe458,0xe459,0xe45a,0xe45b,0xe45c,0xe45d, + 0xe45e,0xe45f,0xe460,0xe461,0xe462,0xe463,0xe464,0xe465,0xe466, + 0xe467,0xe468,0xe469,0xe46a,0xe46b,0xe46c,0xe46d,0xe46e,0xe46f, + 0xe470,0xe471,0xe472,0xe473,0xe474,0xe475,0xe476,0xe477,0xe478, + 0xe479,0xe47a,0xe47b,0xe47c,0xe47d,0xe47e,0xe47f,0xe480,0xe481, + 0xe482,0xe483,0xe484,0xe485,0xe486,0xe487,0xe488,0xe489,0xe48a, + 0xe48b,0xe48c,0xe48d,0xe48e,0xe48f,0xe490,0xe491,0xe492,0xe493, + 0xe494,0xe495,0xe496,0xe497,0xe498,0xe499,0xe49a,0xe49b,0xe49c, + 0xe49d,0xe49e,0xe49f,0xe4a0,0xe4a1,0xe4a2,0xe4a3,0xe4a4,0xe4a5, + 0xe4a6,UDCODE,0xe4a7,0xe4a8,0xe4a9,0xe4aa,0xe4ab,0xe4ac,0xe4ad, + 0xe4ae,0xe4af,0xe4b0,0xe4b1,0xe4b2,0xe4b3,0xe4b4,0xe4b5,0xe4b6, + 0xe4b7,0xe4b8,0xe4b9,0xe4ba,0xe4bb,0xe4bc,0xe4bd,0xe4be,0xe4bf, + 0xe4c0,0xe4c1,0xe4c2,0xe4c3,0xe4c4,0xe4c5,0xe4c6,0xe4c7,0xe4c8, + 0xe4c9,0xe4ca,0xe4cb,0xe4cc,0xe4cd,0xe4ce,0xe4cf,0xe4d0,0xe4d1, + 0xe4d2,0xe4d3,0xe4d4,0xe4d5,0xe4d6,0xe4d7,0xe4d8,0xe4d9,0xe4da, + 0xe4db,0xe4dc,0xe4dd,0xe4de,0xe4df,0xe4e0,0xe4e1,0xe4e2,0xe4e3, + 0xe4e4,0xe4e5,0xe4e6,0xe4e7,0xe4e8,0xe4e9,0xe4ea,0xe4eb,0xe4ec, + 0xe4ed,0xe4ee,0xe4ef,0xe4f0,0xe4f1,0xe4f2,0xe4f3,0xe4f4,0xe4f5, + 0xe4f6,0xe4f7,0xe4f8,0xe4f9,0xe4fa,0xe4fb,0xe4fc,0xe4fd,0xe4fe, + 0xe4ff,0xe500,0xe501,0xe502,0xe503,0xe504,0xe505,0xe506,0xe507, + 0xe508,0xe509,0xe50a,0xe50b,0xe50c,0xe50d,0xe50e,0xe50f,0xe510, + 0xe511,0xe512,0xe513,0xe514,0xe515,0xe516,0xe517,0xe518,0xe519, + 0xe51a,0xe51b,0xe51c,0xe51d,0xe51e,0xe51f,0xe520,0xe521,0xe522, + 0xe523,0xe524,0xe525,0xe526,0xe527,0xe528,0xe529,0xe52a,0xe52b, + 0xe52c,0xe52d,0xe52e,0xe52f,0xe530,0xe531,0xe532,0xe533,0xe534, + 0xe535,0xe536,0xe537,0xe538,0xe539,0xe53a,0xe53b,0xe53c,0xe53d, + 0xe53e,0xe53f,0xe540,0xe541,0xe542,0xe543,0xe544,0xe545,0xe546, + 0xe547,0xe548,0xe549,0xe54a,0xe54b,0xe54c,0xe54d,0xe54e,0xe54f, + 0xe550,0xe551,0xe552,0xe553,0xe554,0xe555,0xe556,0xe557,0xe558, + 0xe559,0xe55a,0xe55b,0xe55c,0xe55d,0xe55e,0xe55f,0xe560,0xe561, + 0xe562,UDCODE,0xe563,0xe564,0xe565,0xe566,0xe567,0xe568,0xe569, + 0xe56a,0xe56b,0xe56c,0xe56d,0xe56e,0xe56f,0xe570,0xe571,0xe572, + 0xe573,0xe574,0xe575,0xe576,0xe577,0xe578,0xe579,0xe57a,0xe57b, + 0xe57c,0xe57d,0xe57e,0xe57f,0xe580,0xe581,0xe582,0xe583,0xe584, + 0xe585,0xe586,0xe587,0xe588,0xe589,0xe58a,0xe58b,0xe58c,0xe58d, + 0xe58e,0xe58f,0xe590,0xe591,0xe592,0xe593,0xe594,0xe595,0xe596, + 0xe597,0xe598,0xe599,0xe59a,0xe59b,0xe59c,0xe59d,0xe59e,0xe59f, + 0xe5a0,0xe5a1,0xe5a2,0xe5a3,0xe5a4,0xe5a5,0xe5a6,0xe5a7,0xe5a8, + 0xe5a9,0xe5aa,0xe5ab,0xe5ac,0xe5ad,0xe5ae,0xe5af,0xe5b0,0xe5b1, + 0xe5b2,0xe5b3,0xe5b4,0xe5b5,0xe5b6,0xe5b7,0xe5b8,0xe5b9,0xe5ba, + 0xe5bb,0xe5bc,0xe5bd,0xe5be,0xe5bf,0xe5c0,0xe5c1,0xe5c2,0xe5c3, + 0xe5c4,0xe5c5,0xe5c6,0xe5c7,0xe5c8,0xe5c9,0xe5ca,0xe5cb,0xe5cc, + 0xe5cd,0xe5ce,0xe5cf,0xe5d0,0xe5d1,0xe5d2,0xe5d3,0xe5d4,0xe5d5, + 0xe5d6,0xe5d7,0xe5d8,0xe5d9,0xe5da,0xe5db,0xe5dc,0xe5dd,0xe5de, + 0xe5df,0xe5e0,0xe5e1,0xe5e2,0xe5e3,0xe5e4,0xe5e5,0xe5e6,0xe5e7, + 0xe5e8,0xe5e9,0xe5ea,0xe5eb,0xe5ec,0xe5ed,0xe5ee,0xe5ef,0xe5f0, + 0xe5f1,0xe5f2,0xe5f3,0xe5f4,0xe5f5,0xe5f6,0xe5f7,0xe5f8,0xe5f9, + 0xe5fa,0xe5fb,0xe5fc,0xe5fd,0xe5fe,0xe5ff,0xe600,0xe601,0xe602, + 0xe603,0xe604,0xe605,0xe606,0xe607,0xe608,0xe609,0xe60a,0xe60b, + 0xe60c,0xe60d,0xe60e,0xe60f,0xe610,0xe611,0xe612,0xe613,0xe614, + 0xe615,0xe616,0xe617,0xe618,0xe619,0xe61a,0xe61b,0xe61c,0xe61d, + 0xe61e,UDCODE,0xe61f,0xe620,0xe621,0xe622,0xe623,0xe624,0xe625, + 0xe626,0xe627,0xe628,0xe629,0xe62a,0xe62b,0xe62c,0xe62d,0xe62e, + 0xe62f,0xe630,0xe631,0xe632,0xe633,0xe634,0xe635,0xe636,0xe637, + 0xe638,0xe639,0xe63a,0xe63b,0xe63c,0xe63d,0xe63e,0xe63f,0xe640, + 0xe641,0xe642,0xe643,0xe644,0xe645,0xe646,0xe647,0xe648,0xe649, + 0xe64a,0xe64b,0xe64c,0xe64d,0xe64e,0xe64f,0xe650,0xe651,0xe652, + 0xe653,0xe654,0xe655,0xe656,0xe657,0xe658,0xe659,0xe65a,0xe65b, + 0xe65c,0xe65d,0xe65e,0xe65f,0xe660,0xe661,0xe662,0xe663,0xe664, + 0xe665,0xe666,0xe667,0xe668,0xe669,0xe66a,0xe66b,0xe66c,0xe66d, + 0xe66e,0xe66f,0xe670,0xe671,0xe672,0xe673,0xe674,0xe675,0xe676, + 0xe677,0xe678,0xe679,0xe67a,0xe67b,0xe67c,0xe67d,0xe67e,0xe67f, + 0xe680,0xe681,0xe682,0xe683,0xe684,0xe685,0xe686,0xe687,0xe688, + 0xe689,0xe68a,0xe68b,0xe68c,0xe68d,0xe68e,0xe68f,0xe690,0xe691, + 0xe692,0xe693,0xe694,0xe695,0xe696,0xe697,0xe698,0xe699,0xe69a, + 0xe69b,0xe69c,0xe69d,0xe69e,0xe69f,0xe6a0,0xe6a1,0xe6a2,0xe6a3, + 0xe6a4,0xe6a5,0xe6a6,0xe6a7,0xe6a8,0xe6a9,0xe6aa,0xe6ab,0xe6ac, + 0xe6ad,0xe6ae,0xe6af,0xe6b0,0xe6b1,0xe6b2,0xe6b3,0xe6b4,0xe6b5, + 0xe6b6,0xe6b7,0xe6b8,0xe6b9,0xe6ba,0xe6bb,0xe6bc,0xe6bd,0xe6be, + 0xe6bf,0xe6c0,0xe6c1,0xe6c2,0xe6c3,0xe6c4,0xe6c5,0xe6c6,0xe6c7, + 0xe6c8,0xe6c9,0xe6ca,0xe6cb,0xe6cc,0xe6cd,0xe6ce,0xe6cf,0xe6d0, + 0xe6d1,0xe6d2,0xe6d3,0xe6d4,0xe6d5,0xe6d6,0xe6d7,0xe6d8,0xe6d9, + 0xe6da,UDCODE,0xe6db,0xe6dc,0xe6dd,0xe6de,0xe6df,0xe6e0,0xe6e1, + 0xe6e2,0xe6e3,0xe6e4,0xe6e5,0xe6e6,0xe6e7,0xe6e8,0xe6e9,0xe6ea, + 0xe6eb,0xe6ec,0xe6ed,0xe6ee,0xe6ef,0xe6f0,0xe6f1,0xe6f2,0xe6f3, + 0xe6f4,0xe6f5,0xe6f6,0xe6f7,0xe6f8,0xe6f9,0xe6fa,0xe6fb,0xe6fc, + 0xe6fd,0xe6fe,0xe6ff,0xe700,0xe701,0xe702,0xe703,0xe704,0xe705, + 0xe706,0xe707,0xe708,0xe709,0xe70a,0xe70b,0xe70c,0xe70d,0xe70e, + 0xe70f,0xe710,0xe711,0xe712,0xe713,0xe714,0xe715,0xe716,0xe717, + 0xe718,0xe719,0xe71a,0xe71b,0xe71c,0xe71d,0xe71e,0xe71f,0xe720, + 0xe721,0xe722,0xe723,0xe724,0xe725,0xe726,0xe727,0xe728,0xe729, + 0xe72a,0xe72b,0xe72c,0xe72d,0xe72e,0xe72f,0xe730,0xe731,0xe732, + 0xe733,0xe734,0xe735,0xe736,0xe737,0xe738,0xe739,0xe73a,0xe73b, + 0xe73c,0xe73d,0xe73e,0xe73f,0xe740,0xe741,0xe742,0xe743,0xe744, + 0xe745,0xe746,0xe747,0xe748,0xe749,0xe74a,0xe74b,0xe74c,0xe74d, + 0xe74e,0xe74f,0xe750,0xe751,0xe752,0xe753,0xe754,0xe755,0xe756, + 0xe757,0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177, + 0x2178,0x2179,0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166, + 0x2167,0x2168,0x2169,0xffe2,0xffe4,0xff07,0xff02,0x3231,0x2116, + 0x2121,0x2235,0x7e8a,0x891c,0x9348,0x9288,0x84dc,0x4fc9,0x70bb, + 0x6631,0x68c8,0x92f9,0x66fb,0x5f45,0x4e28,0x4ee1,0x4efc,0x4f00, + 0x4f03,0x4f39,0x4f56,0x4f92,0x4f8a,0x4f9a,0x4f94,0x4fcd,0x5040, + 0x5022,0x4fff,0x501e,0x5046,0x5070,0x5042,0x5094,0x50f4,0x50d8, + 0x514a,UDCODE,0x5164,0x519d,0x51be,0x51ec,0x5215,0x529c,0x52a6, + 0x52c0,0x52db,0x5300,0x5307,0x5324,0x5372,0x5393,0x53b2,0x53dd, + 0xfa0e,0x549c,0x548a,0x54a9,0x54ff,0x5586,0x5759,0x5765,0x57ac, + 0x57c8,0x57c7,0xfa0f,0xfa10,0x589e,0x58b2,0x590b,0x5953,0x595b, + 0x595d,0x5963,0x59a4,0x59ba,0x5b56,0x5bc0,0x752f,0x5bd8,0x5bec, + 0x5c1e,0x5ca6,0x5cba,0x5cf5,0x5d27,0x5d53,0xfa11,0x5d42,0x5d6d, + 0x5db8,0x5db9,0x5dd0,0x5f21,0x5f34,0x5f67,0x5fb7,0x5fde,0x605d, + 0x6085,0x608a,0x60de,0x60d5,0x6120,0x60f2,0x6111,0x6137,0x6130, + 0x6198,0x6213,0x62a6,0x63f5,0x6460,0x649d,0x64ce,0x654e,0x6600, + 0x6615,0x663b,0x6609,0x662e,0x661e,0x6624,0x6665,0x6657,0x6659, + 0xfa12,0x6673,0x6699,0x66a0,0x66b2,0x66bf,0x66fa,0x670e,0xf929, + 0x6766,0x67bb,0x6852,0x67c0,0x6801,0x6844,0x68cf,0xfa13,0x6968, + 0xfa14,0x6998,0x69e2,0x6a30,0x6a6b,0x6a46,0x6a73,0x6a7e,0x6ae2, + 0x6ae4,0x6bd6,0x6c3f,0x6c5c,0x6c86,0x6c6f,0x6cda,0x6d04,0x6d87, + 0x6d6f,0x6d96,0x6dac,0x6dcf,0x6df8,0x6df2,0x6dfc,0x6e39,0x6e5c, + 0x6e27,0x6e3c,0x6ebf,0x6f88,0x6fb5,0x6ff5,0x7005,0x7007,0x7028, + 0x7085,0x70ab,0x710f,0x7104,0x715c,0x7146,0x7147,0xfa15,0x71c1, + 0x71fe,0x72b1,0x72be,0x7324,0xfa16,0x7377,0x73bd,0x73c9,0x73d6, + 0x73e3,0x73d2,0x7407,0x73f5,0x7426,0x742a,0x7429,0x742e,0x7462, + 0x7489,0x749f,0x7501,0x756f,0x7682,0x769c,0x769e,0x769b,0x76a6, + 0xfa17,0x7746,0x52af,0x7821,0x784e,0x7864,0x787a,0x7930,0xfa18, + 0xfa19,UDCODE,0xfa1a,0x7994,0xfa1b,0x799b,0x7ad1,0x7ae7,0xfa1c, + 0x7aeb,0x7b9e,0xfa1d,0x7d48,0x7d5c,0x7db7,0x7da0,0x7dd6,0x7e52, + 0x7f47,0x7fa1,0xfa1e,0x8301,0x8362,0x837f,0x83c7,0x83f6,0x8448, + 0x84b4,0x8553,0x8559,0x856b,0xfa1f,0x85b0,0xfa20,0xfa21,0x8807, + 0x88f5,0x8a12,0x8a37,0x8a79,0x8aa7,0x8abe,0x8adf,0xfa22,0x8af6, + 0x8b53,0x8b7f,0x8cf0,0x8cf4,0x8d12,0x8d76,0xfa23,0x8ecf,0xfa24, + 0xfa25,0x9067,0x90de,0xfa26,0x9115,0x9127,0x91da,0x91d7,0x91de, + 0x91ed,0x91ee,0x91e4,0x91e5,0x9206,0x9210,0x920a,0x923a,0x9240, + 0x923c,0x924e,0x9259,0x9251,0x9239,0x9267,0x92a7,0x9277,0x9278, + 0x92e7,0x92d7,0x92d9,0x92d0,0xfa27,0x92d5,0x92e0,0x92d3,0x9325, + 0x9321,0x92fb,0xfa28,0x931e,0x92ff,0x931d,0x9302,0x9370,0x9357, + 0x93a4,0x93c6,0x93de,0x93f8,0x9431,0x9445,0x9448,0x9592,0xf9dc, + 0xfa29,0x969d,0x96af,0x9733,0x973b,0x9743,0x974d,0x974f,0x9751, + 0x9755,0x9857,0x9865,0xfa2a,0xfa2b,0x9927,0xfa2c,0x999e,0x9a4e, + 0x9ad9,0x9adc,0x9b75,0x9b72,0x9b8f,0x9bb1,0x9bbb,0x9c00,0x9d70, + 0x9d6b,0xfa2d,0x9e19,0x9ed1 +}; + +//! 1st table +static const UINT32 s_level1[] = +{ + 0x00000000,0x00000001,0x00000002,0x00000003,0x00000004,0x00000005, + 0x00000006,0x00000007,0x00000008,0x00000009,0x0000000a,0x0000000b, + 0x0000000c,0x0000000d,0x0000000e,0x0000000f,0x00000010,0x00000011, + 0x00000012,0x00000013,0x00000014,0x00000015,0x00000016,0x00000017, + 0x00000018,0x00000019,0x0000001a,0x0000001b,0x0000001c,0x0000001d, + 0x0000001e,0x0000001f,0x00000020,0x00000021,0x00000022,0x00000023, + 0x00000024,0x00000025,0x00000026,0x00000027,0x00000028,0x00000029, + 0x0000002a,0x0000002b,0x0000002c,0x0000002d,0x0000002e,0x0000002f, + 0x00000030,0x00000031,0x00000032,0x00000033,0x00000034,0x00000035, + 0x00000036,0x00000037,0x00000038,0x00000039,0x0000003a,0x0000003b, + 0x0000003c,0x0000003d,0x0000003e,0x0000003f,0x00000040,0x00000041, + 0x00000042,0x00000043,0x00000044,0x00000045,0x00000046,0x00000047, + 0x00000048,0x00000049,0x0000004a,0x0000004b,0x0000004c,0x0000004d, + 0x0000004e,0x0000004f,0x00000050,0x00000051,0x00000052,0x00000053, + 0x00000054,0x00000055,0x00000056,0x00000057,0x00000058,0x00000059, + 0x0000005a,0x0000005b,0x0000005c,0x0000005d,0x0000005e,0x0000005f, + 0x00000060,0x00000061,0x00000062,0x00000063,0x00000064,0x00000065, + 0x00000066,0x00000067,0x00000068,0x00000069,0x0000006a,0x0000006b, + 0x0000006c,0x0000006d,0x0000006e,0x0000006f,0x00000070,0x00000071, + 0x00000072,0x00000073,0x00000074,0x00000075,0x00000076,0x00000077, + 0x00000078,0x00000079,0x0000007a,0x0000007b,0x0000007c,0x0000007d, + 0x0000007e,0x0000007f,0x00000080,0x0001bd40,0x00bea34f,0x01619740, + 0x01f87f40,0x02770000,0x02770000,0x02775d40,0x02d45e9f,0x0332bd40, + 0x03efbd40,0x04acbd40,0x0569bd40,0x0626bd40,0x06e3bd40,0x07a0bd40, + 0x085dbd40,0x091abd40,0x09d7bd40,0x0a94bd40,0x0b51bd40,0x0c0ebd40, + 0x0ccbbd40,0x0d88bd40,0x0e45bd40,0x0f02bd40,0x0fbfbd40,0x107cbd40, + 0x1139bd40,0x11f6bd40,0x12b3bd40,0x1370bd40,0x0000f8f0,0x0000ff61, + 0x0000ff62,0x0000ff63,0x0000ff64,0x0000ff65,0x0000ff66,0x0000ff67, + 0x0000ff68,0x0000ff69,0x0000ff6a,0x0000ff6b,0x0000ff6c,0x0000ff6d, + 0x0000ff6e,0x0000ff6f,0x0000ff70,0x0000ff71,0x0000ff72,0x0000ff73, + 0x0000ff74,0x0000ff75,0x0000ff76,0x0000ff77,0x0000ff78,0x0000ff79, + 0x0000ff7a,0x0000ff7b,0x0000ff7c,0x0000ff7d,0x0000ff7e,0x0000ff7f, + 0x0000ff80,0x0000ff81,0x0000ff82,0x0000ff83,0x0000ff84,0x0000ff85, + 0x0000ff86,0x0000ff87,0x0000ff88,0x0000ff89,0x0000ff8a,0x0000ff8b, + 0x0000ff8c,0x0000ff8d,0x0000ff8e,0x0000ff8f,0x0000ff90,0x0000ff91, + 0x0000ff92,0x0000ff93,0x0000ff94,0x0000ff95,0x0000ff96,0x0000ff97, + 0x0000ff98,0x0000ff99,0x0000ff9a,0x0000ff9b,0x0000ff9c,0x0000ff9d, + 0x0000ff9e,0x0000ff9f,0x142dbd40,0x14eabd40,0x15a7bd40,0x1664bd40, + 0x1721bd40,0x17debd40,0x189bbd40,0x1958bd40,0x1a15bd40,0x1ad2bd40, + 0x1b8f6540,0x1bf40000,0x1bf40000,0x1bf4bd40,0x1cb1bd40,0x1d6e0000, + 0x1d6ebd40,0x1e2bbd40,0x1ee8bd40,0x1fa5bd40,0x2062bd40,0x211fbd40, + 0x21dcbd40,0x2299bd40,0x2356bd40,0x2413bd40,0x24d0bd40,0x258dbd40, + 0x264a0c40,0x0000f8f1,0x0000f8f2,0x0000f8f3 +}; + +static UINT sjis2ucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); +static UINT sjis2utf8(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); + +/** + * Maps a S-JIS string to a UTF-16 string + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +UINT codecnv_sjistoucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) +{ + UINT nLength; + + if (lpInput == NULL) + { + return 0; + } + + if (cchOutput == 0) + { + lpOutput = NULL; + cchOutput = (UINT)-1; + } + + if (cchInput != (UINT)-1) + { + // Binary mode + return sjis2ucs2(lpOutput, cchOutput, lpInput, cchInput); + } + else + { + // String mode + nLength = sjis2ucs2(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); + if (lpOutput) + { + lpOutput[nLength] = '\0'; + } + return nLength + 1; + } +} + +/** + * Maps a S-JIS string to a UTF-16 string (inner) + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +static UINT sjis2ucs2(UINT16 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) +{ + UINT nRemain; + UINT c; + UINT r; + UINT32 idx; + + nRemain = cchOutput; + while ((cchInput > 0) && (nRemain > 0)) + { + c = (*lpInput++) & 0xff; + cchInput--; + + r = s_level1[c]; + if (r & 0xffff0000) + { + if (cchInput == 0) + { + break; + } + cchInput--; + c = ((*lpInput++) - r) & 0xff; + if (c < ((r >> 8) & 0xff)) + { + idx = ((r >> 16) & 0xffff) + c; + r = idx < NELEMENTS(s_level2) ? s_level2[idx] : UDCODE; + } + else + { + r = UDCODE; + } + } + nRemain--; + if (lpOutput) + { + *lpOutput++ = (UINT16)r; + } + } + return (UINT)(cchOutput - nRemain); +} + +/** + * Maps a S-JIS string to a UTF-8 string + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +UINT codecnv_sjistoutf8(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) +{ + UINT nLength; + + if (lpInput == NULL) + { + return 0; + } + + if (cchOutput == 0) + { + lpOutput = NULL; + cchOutput = (UINT)-1; + } + + if (cchInput != (UINT)-1) + { + // Binary mode + return sjis2utf8(lpOutput, cchOutput, lpInput, cchInput); + } + else + { + // String mode + nLength = sjis2utf8(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); + if (lpOutput) + { + lpOutput[nLength] = '\0'; + } + return nLength + 1; + } +} + +/** + * Maps a S-JIS string to a UTF-8 string (inner) + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +static UINT sjis2utf8(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) +{ + UINT nRemain; + UINT c; + UINT r; + UINT32 idx; + + nRemain = cchOutput; + while ((cchInput > 0) && (nRemain > 0)) + { + c = (*lpInput++) & 0xff; + cchInput--; + + r = s_level1[c]; + if (r & 0xffff0000) + { + if (cchInput == 0) + { + break; + } + cchInput--; + c = ((*lpInput++) - r) & 0xff; + if (c < ((r >> 8) & 0xff)) + { + idx = ((r >> 16) & 0xffff) + c; + r = idx < NELEMENTS(s_level2) ? s_level2[idx] : UDCODE; + } + else + { + r = UDCODE; + } + } + + if (r < 0x80) + { + nRemain--; + if (lpOutput) + { + *lpOutput++ = (char)r; + } + } + else if (r < 0x800) + { + if (nRemain < 2) + { + break; + } + nRemain -= 2; + if (lpOutput) + { + *lpOutput++ = (char)(0xc0 + ((r >> 6) & 0x1f)); + *lpOutput++ = (char)(0x80 + ((r >> 0) & 0x3f)); + } + } + else + { + if (nRemain < 3) + { + break; + } + nRemain -= 3; + if (lpOutput) + { + *lpOutput++ = (char)(0xe0 + ((r >> 12) & 0x0f)); + *lpOutput++ = (char)(0x80 + ((r >> 6) & 0x3f)); + *lpOutput++ = (char)(0x80 + ((r >> 0) & 0x3f)); + } + } + } + return (UINT)(cchOutput - nRemain); +} diff --git a/codecnv/tcswap16.c b/codecnv/tcswap16.c old mode 100755 new mode 100644 index bda62aea..dcaf25bd --- a/codecnv/tcswap16.c +++ b/codecnv/tcswap16.c @@ -1,19 +1,19 @@ -#include -#include "textcnv.h" - - -void textcnv_swapendian16(void *buf, UINT leng) { - - UINT8 *p; - UINT8 tmp; - - p = (UINT8 *)buf; - while(leng) { - tmp = p[0]; - p[0] = p[1]; - p[1] = tmp; - p += 2; - leng--; - } -} - +#include +#include "textcnv.h" + + +void textcnv_swapendian16(void *buf, UINT leng) { + + UINT8 *p; + UINT8 tmp; + + p = (UINT8 *)buf; + while(leng) { + tmp = p[0]; + p[0] = p[1]; + p[1] = tmp; + p += 2; + leng--; + } +} + diff --git a/codecnv/tcswap32.c b/codecnv/tcswap32.c old mode 100755 new mode 100644 index 8a34dc81..56530b30 --- a/codecnv/tcswap32.c +++ b/codecnv/tcswap32.c @@ -1,23 +1,23 @@ -#include -#include "textcnv.h" - - -void textcnv_swapendian32(void *buf, UINT leng) { - - UINT8 *p; - UINT8 tmp0; - UINT8 tmp1; - - p = (UINT8 *)buf; - while(leng) { - tmp0 = p[0]; - tmp1 = p[1]; - p[0] = p[3]; - p[1] = p[2]; - p[2] = tmp1; - p[3] = tmp0; - p += 4; - leng--; - } -} - +#include +#include "textcnv.h" + + +void textcnv_swapendian32(void *buf, UINT leng) { + + UINT8 *p; + UINT8 tmp0; + UINT8 tmp1; + + p = (UINT8 *)buf; + while(leng) { + tmp0 = p[0]; + tmp1 = p[1]; + p[0] = p[3]; + p[1] = p[2]; + p[2] = tmp1; + p[3] = tmp0; + p += 4; + leng--; + } +} + diff --git a/codecnv/textcnv.c b/codecnv/textcnv.c old mode 100755 new mode 100644 index 0a84a135..b41b814f --- a/codecnv/textcnv.c +++ b/codecnv/textcnv.c @@ -1,93 +1,93 @@ -#include -#include -#include "textcnv.h" - - -UINT textcnv_getinfo(TCINF *inf, const UINT8 *hdr, UINT hdrsize) { - - UINT textcode; - TCINF info; - - textcode = TEXTCNV_DEFAULT; - ZeroMemory(&info, sizeof(info)); - if ((hdrsize >= 3) && - (hdr[0] == 0xef) && (hdr[1] == 0xbb) && (hdr[2] == 0xbf)) { - // UTF-8 - textcode = TEXTCNV_UTF8; - info.width = 1; - info.hdrsize = 3; - } - else if ((hdrsize >= 2) && (hdr[0] == 0xff) && (hdr[1] == 0xfe)) { - // UCSLE - textcode = TEXTCNV_UCS2; -#if defined(BYTESEX_BIG) - info.xendian = 1; -#endif - info.width = 2; - info.hdrsize = 2; - } - else if ((hdrsize >= 2) && (hdr[0] == 0xfe) && (hdr[1] == 0xff)) { - // UCS2BE - // UCSLE - textcode = TEXTCNV_UCS2; -#if defined(BYTESEX_LITTLE) - info.xendian = 1; -#endif - info.width = 2; - info.hdrsize = 2; - } - else { - info.width = 1; - } - -#if defined(OSLANG_SJIS) - switch(textcode) { - case TEXTCNV_DEFAULT: - case TEXTCNV_SJIS: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - break; - } -#elif defined(OSLANG_EUC) - switch(textcode) { - case TEXTCNV_DEFAULT: - case TEXTCNV_EUC: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - break; - } -#elif defined(OSLANG_UTF8) - switch(textcode) { - case TEXTCNV_UTF8: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - break; - - case TEXTCNV_UCS2: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - info.tooem = (TCTOOEM)codecnv_ucs2toutf8; - info.fromoem = (TCFROMOEM)codecnv_utf8toucs2; - break; - } -#elif defined(OSLANG_UCS2) - switch(textcode) { - case TEXTCNV_UTF8: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - info.tooem = (TCTOOEM)codecnv_utf8toucs2; - info.fromoem = (TCFROMOEM)codecnv_ucs2toutf8; - break; - - case TEXTCNV_UCS2: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - break; - } -#else // defined(OSLANG_*) - switch(textcode) { - case TEXTCNV_DEFAULT: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - break; - } -#endif // defined(OSLANG_*) - if (inf) { - *inf = info; - } - return(info.caps); -} - +#include +#include +#include "textcnv.h" + + +UINT textcnv_getinfo(TCINF *inf, const UINT8 *hdr, UINT hdrsize) { + + UINT textcode; + TCINF info; + + textcode = TEXTCNV_DEFAULT; + ZeroMemory(&info, sizeof(info)); + if ((hdrsize >= 3) && + (hdr[0] == 0xef) && (hdr[1] == 0xbb) && (hdr[2] == 0xbf)) { + // UTF-8 + textcode = TEXTCNV_UTF8; + info.width = 1; + info.hdrsize = 3; + } + else if ((hdrsize >= 2) && (hdr[0] == 0xff) && (hdr[1] == 0xfe)) { + // UCSLE + textcode = TEXTCNV_UCS2; +#if defined(BYTESEX_BIG) + info.xendian = 1; +#endif + info.width = 2; + info.hdrsize = 2; + } + else if ((hdrsize >= 2) && (hdr[0] == 0xfe) && (hdr[1] == 0xff)) { + // UCS2BE + // UCSLE + textcode = TEXTCNV_UCS2; +#if defined(BYTESEX_LITTLE) + info.xendian = 1; +#endif + info.width = 2; + info.hdrsize = 2; + } + else { + info.width = 1; + } + +#if defined(OSLANG_SJIS) + switch(textcode) { + case TEXTCNV_DEFAULT: + case TEXTCNV_SJIS: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + break; + } +#elif defined(OSLANG_EUC) + switch(textcode) { + case TEXTCNV_DEFAULT: + case TEXTCNV_EUC: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + break; + } +#elif defined(OSLANG_UTF8) + switch(textcode) { + case TEXTCNV_UTF8: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + break; + + case TEXTCNV_UCS2: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + info.tooem = (TCTOOEM)codecnv_ucs2toutf8; + info.fromoem = (TCFROMOEM)codecnv_utf8toucs2; + break; + } +#elif defined(OSLANG_UCS2) + switch(textcode) { + case TEXTCNV_UTF8: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + info.tooem = (TCTOOEM)codecnv_utf8toucs2; + info.fromoem = (TCFROMOEM)codecnv_ucs2toutf8; + break; + + case TEXTCNV_UCS2: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + break; + } +#else // defined(OSLANG_*) + switch(textcode) { + case TEXTCNV_DEFAULT: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + break; + } +#endif // defined(OSLANG_*) + if (inf) { + *inf = info; + } + return(info.caps); +} + diff --git a/codecnv/textcnv.h b/codecnv/textcnv.h old mode 100755 new mode 100644 index 77bf5471..ec81352b --- a/codecnv/textcnv.h +++ b/codecnv/textcnv.h @@ -1,41 +1,41 @@ - -// テキストファイルの変換ルール - -enum { - TEXTCNV_DEFAULT = 0, - TEXTCNV_SJIS = 1, - TEXTCNV_EUC = 2, - TEXTCNV_UTF8 = 3, - TEXTCNV_UCS2 = 4 -}; - -enum { - TEXTCNV_READ = 0x01, - TEXTCNV_WRITE = 0x02 -}; - -typedef UINT (*TCTOOEM)(OEMCHAR *dst, UINT dcnt, const void *src, UINT scnt); -typedef UINT (*TCFROMOEM)(void *dst, UINT dcnt, const OEMCHAR *src, UINT scnt); - -typedef struct { - UINT8 caps; - UINT8 xendian; - UINT8 width; - UINT8 hdrsize; - TCTOOEM tooem; - TCFROMOEM fromoem; -} TCINF; - - -#ifdef __cplusplus -extern "C" { -#endif - -UINT textcnv_getinfo(TCINF *inf, const UINT8 *hdr, UINT hdrsize); -void textcnv_swapendian16(void *buf, UINT leng); -void textcnv_swapendian32(void *buf, UINT leng); - -#ifdef __cplusplus -} -#endif - + +// テキストファイルの変換ルール + +enum { + TEXTCNV_DEFAULT = 0, + TEXTCNV_SJIS = 1, + TEXTCNV_EUC = 2, + TEXTCNV_UTF8 = 3, + TEXTCNV_UCS2 = 4 +}; + +enum { + TEXTCNV_READ = 0x01, + TEXTCNV_WRITE = 0x02 +}; + +typedef UINT (*TCTOOEM)(OEMCHAR *dst, UINT dcnt, const void *src, UINT scnt); +typedef UINT (*TCFROMOEM)(void *dst, UINT dcnt, const OEMCHAR *src, UINT scnt); + +typedef struct { + UINT8 caps; + UINT8 xendian; + UINT8 width; + UINT8 hdrsize; + TCTOOEM tooem; + TCFROMOEM fromoem; +} TCINF; + + +#ifdef __cplusplus +extern "C" { +#endif + +UINT textcnv_getinfo(TCINF *inf, const UINT8 *hdr, UINT hdrsize); +void textcnv_swapendian16(void *buf, UINT leng); +void textcnv_swapendian32(void *buf, UINT leng); + +#ifdef __cplusplus +} +#endif + diff --git a/codecnv/ucs2sjis.c b/codecnv/ucs2sjis.c old mode 100755 new mode 100644 index 8404fc14..ba79cec8 --- a/codecnv/ucs2sjis.c +++ b/codecnv/ucs2sjis.c @@ -1,2970 +1,2970 @@ -/** - * @file ucs2sjis.c - * @brief Implementation of converting UCS2 to S-JIS - */ - -#ifdef CODECNV_TEST -#include "compiler_base.h" -#else -#include -#endif -#include - -//! undefined code -#define UDCODE 0x003f - -//! 1st table -static const UINT32 s_level1[256] = -{ - 0x00010000,0x00000000,0x00000000,0x02003991,0x02725101,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x03142c10,0x036cd203,0x0510c000,0x06900112, - 0x06921460,0x06baf000,0x089a6b05,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x0970ff00,0x00000000,0x0b6e7831,0x0c5ecb03,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x0df4fd00,0x0fef0000,0x11eef705,0x13dcff00,0x15db0000,0x17dafb00, - 0x19d0ff01,0x1bcefb04,0x1dc4fa06,0x1fb8fd00,0x21b2fe00,0x23aefe02, - 0x25aafb01,0x27a0f709,0x298efd01,0x2b88f807,0x2d78fe02,0x2f74ff01, - 0x3172ee0e,0x334f0000,0x354f0000,0x374efa01,0x3942f906,0x3b34fc00, - 0x3d2d0000,0x3f2d0000,0x412cfa01,0x43210000,0x4520fa02,0x4714f004, - 0x48f4ec08,0x4accf904,0x4cbefb05,0x4eb4fe01,0x50b0fd01,0x52aafc04, - 0x54a2f806,0x5692f50a,0x587cf603,0x5a68ff01,0x5c66fe01,0x5e62fc01, - 0x605afc02,0x6252fb01,0x64490000,0x6648f602,0x6834ff00,0x6a32fc00, - 0x6c2a9c01,0x6d62c736,0x6ef0fe00,0x70ecfd02,0x72e6fb01,0x74dcfd01, - 0x76d6fd03,0x78d0ff00,0x7acefd02,0x7cc8ff00,0x7ec6fa05,0x80baf702, - 0x82a8ff00,0x84a69b00,0x85dcc737,0x876afc04,0x8962f708,0x8b50fb03, - 0x8d46fe00,0x8f42fe02,0x913efa06,0x9332f702,0x95207f03,0x961e6f77, - 0x96fce01c,0x98bd0000,0x9abcfe01,0x9cb8fd03,0x9eb2fb01,0xa0a8f006, - 0xa288f700,0xa476fb03,0xa66ce519,0xa8369a07,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0xa96b0000,0xab6b0000,0xad6b0000,0xaf6b0000, - 0xb16b0000,0xb36b0000,0xb56b0000,0xb76a5800,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000000,0x00000000,0xb81a04f0,0xb822b429,0xb98a200e,0x00000000, - 0x00000000,0x00000000,0x00000000,0xb9cae501 -}; - -//! 2nd table -static const UINT32 s_level2[] = -{ - 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008, - 0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,0x0010,0x0011, - 0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a, - 0x001b,0x001c,0x001d,0x001e,0x001f,0x0020,0x0021,0x0022,0x0023, - 0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c, - 0x002d,0x002e,0x002f,0x0030,0x0031,0x0032,0x0033,0x0034,0x0035, - 0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e, - 0x003f,0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, - 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,0x0050, - 0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059, - 0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,0x0060,0x0061,0x0062, - 0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b, - 0x006c,0x006d,0x006e,0x006f,0x0070,0x0071,0x0072,0x0073,0x0074, - 0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d, - 0x007e,0x007f,0x0080,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x0021, - 0x8191,0x8192,UDCODE,0x005c,0x007c,0x8198,0x814e,0x0063,0x0061, - 0x81e1,0x81ca,0x002d,0x0052,0x8150,0x818b,0x817d,0x0032,0x0033, - 0x814c,0x83ca,0x81f7,0x8145,0x8143,0x0031,0x006f,0x81e2,UDCODE, - UDCODE,UDCODE,UDCODE,0x0041,0x0041,0x0041,0x0041,0x0041,0x0041, - 0x0041,0x0043,0x0045,0x0045,0x0045,0x0045,0x0049,0x0049,0x0049, - 0x0049,0x0044,0x004e,0x004f,0x004f,0x004f,0x004f,0x004f,0x817e, - 0x004f,0x0055,0x0055,0x0055,0x0055,0x0059,0x0054,0x0073,0x0061, - 0x0061,0x0061,0x0061,0x0061,0x0061,0x0061,0x0063,0x0065,0x0065, - 0x0065,0x0065,0x0069,0x0069,0x0069,0x0069,0x0064,0x006e,0x006f, - 0x006f,0x006f,0x006f,0x006f,0x8180,0x006f,0x0075,0x0075,0x0075, - 0x0075,0x0079,0x0074,0x0079,0x839f,0x83a0,0x83a1,0x83a2,0x83a3, - 0x83a4,0x83a5,0x83a6,0x83a7,0x83a8,0x83a9,0x83aa,0x83ab,0x83ac, - 0x83ad,0x83ae,0x83af,UDCODE,0x83b0,0x83b1,0x83b2,0x83b3,0x83b4, - 0x83b5,0x83b6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x83bf,0x83c0,0x83c1,0x83c2,0x83c3,0x83c4,0x83c5,0x83c6,0x83c7, - 0x83c8,0x83c9,0x83ca,0x83cb,0x83cc,0x83cd,0x83ce,0x83cf,UDCODE, - 0x83d0,0x83d1,0x83d2,0x83d3,0x83d4,0x83d5,0x83d6,0x8446,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8440,0x8441,0x8442,0x8443,0x8444, - 0x8445,0x8447,0x8448,0x8449,0x844a,0x844b,0x844c,0x844d,0x844e, - 0x844f,0x8450,0x8451,0x8452,0x8453,0x8454,0x8455,0x8456,0x8457, - 0x8458,0x8459,0x845a,0x845b,0x845c,0x845d,0x845e,0x845f,0x8460, - 0x8470,0x8471,0x8472,0x8473,0x8474,0x8475,0x8477,0x8478,0x8479, - 0x847a,0x847b,0x847c,0x847d,0x847e,0x8480,0x8481,0x8482,0x8483, - 0x8484,0x8485,0x8486,0x8487,0x8488,0x8489,0x848a,0x848b,0x848c, - 0x848d,0x848e,0x848f,0x8490,0x8491,UDCODE,0x8476,0x815d,UDCODE, - UDCODE,UDCODE,UDCODE,0x815c,UDCODE,UDCODE,0x8165,0x8166,UDCODE, - UDCODE,0x8167,0x8168,UDCODE,UDCODE,0x81f5,0x81f6,UDCODE,UDCODE, - UDCODE,0x8164,0x8163,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x81f1,UDCODE,0x818c,0x818d,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81a6,0x818e,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8782,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8784,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x81f0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8754,0x8755,0x8756,0x8757,0x8758,0x8759,0x875a,0x875b,0x875c, - 0x875d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfa40,0xfa41, - 0xfa42,0xfa43,0xfa44,0xfa45,0xfa46,0xfa47,0xfa48,0xfa49,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x81a9,0x81aa,0x81a8,0x81ab,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81cb,UDCODE,0x81cc, - 0x81cd,UDCODE,0x81dd,0x81ce,UDCODE,UDCODE,UDCODE,0x81de,0x81b8, - UDCODE,UDCODE,0x81b9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8794, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81e3, - UDCODE,UDCODE,0x81e5,0x8187,0x8798,0x81da,UDCODE,UDCODE,UDCODE, - UDCODE,0x8161,UDCODE,0x81c8,0x81c9,0x81bf,0x81be,0x81e7,0x81e8, - UDCODE,0x8793,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8188,0x81e6, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81e4,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x81e0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8182,0x81df,UDCODE, - UDCODE,UDCODE,UDCODE,0x8185,0x8186,UDCODE,UDCODE,0x81e1,0x81e2, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x81bc,0x81bd,UDCODE,UDCODE,0x81ba, - 0x81bb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x81db,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8799,0x81dc,0x8740,0x8741,0x8742,0x8743,0x8744, - 0x8745,0x8746,0x8747,0x8748,0x8749,0x874a,0x874b,0x874c,0x874d, - 0x874e,0x874f,0x8750,0x8751,0x8752,0x8753,0x849f,0x84aa,0x84a0, - 0x84ab,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x84a1,UDCODE,UDCODE,0x84ac,0x84a2,UDCODE,UDCODE,0x84ad,0x84a4, - UDCODE,UDCODE,0x84af,0x84a3,UDCODE,UDCODE,0x84ae,0x84a5,0x84ba, - UDCODE,UDCODE,0x84b5,UDCODE,UDCODE,0x84b0,0x84a7,0x84bc,UDCODE, - UDCODE,0x84b7,UDCODE,UDCODE,0x84b2,0x84a6,UDCODE,UDCODE,0x84b6, - 0x84bb,UDCODE,UDCODE,0x84b1,0x84a8,UDCODE,UDCODE,0x84b8,0x84bd, - UDCODE,UDCODE,0x84b3,0x84a9,UDCODE,UDCODE,0x84b9,UDCODE,UDCODE, - 0x84be,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x84b4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x81a1,0x81a0,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x81a3,0x81a2,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81a5,0x81a4,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x819f,0x819e,UDCODE, - UDCODE,UDCODE,0x819b,UDCODE,UDCODE,0x819d,0x819c,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x81fc,0x819a,0x8199,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x818a, - UDCODE,0x8189,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81f4,UDCODE,UDCODE,0x81f3, - UDCODE,0x81f2,0x8140,0x8141,0x8142,0x8156,UDCODE,0x8158,0x8159, - 0x815a,0x8171,0x8172,0x8173,0x8174,0x8175,0x8176,0x8177,0x8178, - 0x8179,0x817a,0x81a7,0x81ac,0x816b,0x816c,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8780,UDCODE,0x8781,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x829f,0x82a0,0x82a1,0x82a2,0x82a3, - 0x82a4,0x82a5,0x82a6,0x82a7,0x82a8,0x82a9,0x82aa,0x82ab,0x82ac, - 0x82ad,0x82ae,0x82af,0x82b0,0x82b1,0x82b2,0x82b3,0x82b4,0x82b5, - 0x82b6,0x82b7,0x82b8,0x82b9,0x82ba,0x82bb,0x82bc,0x82bd,0x82be, - 0x82bf,0x82c0,0x82c1,0x82c2,0x82c3,0x82c4,0x82c5,0x82c6,0x82c7, - 0x82c8,0x82c9,0x82ca,0x82cb,0x82cc,0x82cd,0x82ce,0x82cf,0x82d0, - 0x82d1,0x82d2,0x82d3,0x82d4,0x82d5,0x82d6,0x82d7,0x82d8,0x82d9, - 0x82da,0x82db,0x82dc,0x82dd,0x82de,0x82df,0x82e0,0x82e1,0x82e2, - 0x82e3,0x82e4,0x82e5,0x82e6,0x82e7,0x82e8,0x82e9,0x82ea,0x82eb, - 0x82ec,0x82ed,0x82ee,0x82ef,0x82f0,0x82f1,0x8394,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x814a,0x814b,0x8154,0x8155,UDCODE, - UDCODE,0x8340,0x8341,0x8342,0x8343,0x8344,0x8345,0x8346,0x8347, - 0x8348,0x8349,0x834a,0x834b,0x834c,0x834d,0x834e,0x834f,0x8350, - 0x8351,0x8352,0x8353,0x8354,0x8355,0x8356,0x8357,0x8358,0x8359, - 0x835a,0x835b,0x835c,0x835d,0x835e,0x835f,0x8360,0x8361,0x8362, - 0x8363,0x8364,0x8365,0x8366,0x8367,0x8368,0x8369,0x836a,0x836b, - 0x836c,0x836d,0x836e,0x836f,0x8370,0x8371,0x8372,0x8373,0x8374, - 0x8375,0x8376,0x8377,0x8378,0x8379,0x837a,0x837b,0x837c,0x837d, - 0x837e,0x8380,0x8381,0x8382,0x8383,0x8384,0x8385,0x8386,0x8387, - 0x8388,0x8389,0x838a,0x838b,0x838c,0x838d,0x838e,0x838f,0x8390, - 0x8391,0x8392,0x8393,0x8394,0x8395,0x8396,UDCODE,UDCODE,UDCODE, - UDCODE,0x8145,0x815b,0x8152,0x8153,0x878a,0x878b,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x878c,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8785,0x8786,0x8787,0x8788,0x8789,0x8765, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8769,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8760,UDCODE, - UDCODE,UDCODE,0x8763,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8761,0x876b,UDCODE,UDCODE,0x876a,0x8764, - UDCODE,UDCODE,UDCODE,0x876c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8766,UDCODE,UDCODE,UDCODE, - UDCODE,0x876e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x875f,0x876d,UDCODE, - UDCODE,0x8762,UDCODE,UDCODE,UDCODE,0x8767,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8768,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x877e,0x878f,0x878e,0x878d,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8772,0x8773,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x876f, - 0x8770,0x8771,UDCODE,UDCODE,0x8775,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8774,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8783,0x88ea,0x929a,UDCODE,0x8eb5,UDCODE, - UDCODE,UDCODE,0x969c,0x8fe4,0x8e4f,0x8fe3,0x89ba,UDCODE,0x9573, - 0x975e,UDCODE,0x98a0,0x894e,UDCODE,UDCODE,0x8a8e,0x98a1,0x90a2, - 0x99c0,0x8b75,0x95b8,UDCODE,UDCODE,UDCODE,UDCODE,0x8fe5,UDCODE, - UDCODE,0x97bc,UDCODE,UDCODE,UDCODE,UDCODE,0x95c0,UDCODE,0xfa68, - UDCODE,0x98a2,UDCODE,UDCODE,0x9286,UDCODE,UDCODE,UDCODE,0x98a3, - 0x8bf8,UDCODE,UDCODE,UDCODE,0x98a4,UDCODE,0x8adb,0x924f,UDCODE, - 0x8ee5,0x98a5,UDCODE,UDCODE,0x98a6,UDCODE,UDCODE,0x98a7,0x9454, - UDCODE,0x8b76,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9456,UDCODE, - 0x93e1,0x8cc1,0x9652,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe568, - 0x98a8,0x8fe6,0x98a9,0x89b3,UDCODE,UDCODE,UDCODE,0x8be3,0x8cee, - 0x96e7,UDCODE,UDCODE,0x9ba4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9790,UDCODE,0x93fb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8aa3,UDCODE,0x8b54,UDCODE,0x98aa, - UDCODE,UDCODE,0x98ab,0x97b9,UDCODE,0x975c,0x9188,0x98ad,0x8e96, - 0x93f1,UDCODE,0x98b0,UDCODE,UDCODE,0x895d,0x8cdd,UDCODE,0x8cdc, - 0x88e4,UDCODE,UDCODE,0x986a,0x9869,UDCODE,0x8db1,0x889f,UDCODE, - 0x98b1,0x98b2,0x98b3,0x9653,0x98b4,UDCODE,0x8cf0,0x88e5,0x9692, - UDCODE,0x8b9c,UDCODE,UDCODE,0x8b9d,0x8b9e,0x92e0,0x97ba,UDCODE, - 0x98b5,UDCODE,UDCODE,0x98b6,UDCODE,UDCODE,0x98b7,UDCODE,UDCODE, - UDCODE,0x906c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f59,0x906d, - 0x98bc,UDCODE,0x98ba,UDCODE,0x98bb,0x8b77,UDCODE,UDCODE,0x8da1, - 0x89ee,UDCODE,0x98b9,0x98b8,0x95a7,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8e65,0x8e64,0x91bc,0x98bd,0x9574,0x90e5,UDCODE,UDCODE,UDCODE, - 0x8157,0x98be,0x98c0,UDCODE,0xfa69,UDCODE,0x91e3,0x97df,0x88c8, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x98bf,0x89bc, - UDCODE,0x8bc2,UDCODE,0x9287,UDCODE,UDCODE,UDCODE,0x8c8f,0x98c1, - UDCODE,UDCODE,UDCODE,0x9443,0xfa6a,0xfa6b,0x8ae9,UDCODE,0xfa6c, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x98c2,0x88c9,UDCODE,UDCODE, - 0x8cde,0x8aea,0x959a,0x94b0,0x8b78,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x89ef,UDCODE,0x98e5,0x9360,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x948c,0x98c4, - UDCODE,UDCODE,UDCODE,0x94ba,UDCODE,0x97e0,UDCODE,0x904c,0xfa6d, - 0x8e66,UDCODE,0x8e97,0x89be,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x92cf,UDCODE,UDCODE,0x9241,0x98c8,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x88ca,0x92e1,0x8f5a,0x8db2,0x9743,UDCODE,0x91cc,UDCODE, - 0x89bd,0xfa6e,0x98c7,UDCODE,0x975d,0x98c3,0x98c5,0x8dec,0x98c6, - 0x9b43,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x98ce,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x98d1, - 0x98cf,UDCODE,UDCODE,0x89c0,UDCODE,0x95b9,0x98c9,UDCODE,UDCODE, - UDCODE,UDCODE,0x98cd,0x8cf1,UDCODE,UDCODE,0x8e67,UDCODE,UDCODE, - UDCODE,0x8aa4,UDCODE,UDCODE,0x98d2,UDCODE,0x98ca,UDCODE,0xfa70, - 0x97e1,UDCODE,0x8e98,UDCODE,0x98cb,UDCODE,0x98d0,0xfa6f,UDCODE, - 0xfa72,UDCODE,0x98d3,UDCODE,0x98cc,UDCODE,0xfa71,0x8b9f,UDCODE, - 0x88cb,UDCODE,UDCODE,0x8ba0,0x89bf,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9b44,UDCODE,0x9699,0x958e, - 0x8cf2,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x904e,0x97b5,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95d6,UDCODE, - UDCODE,0x8c57,0x91a3,0x89e2,UDCODE,UDCODE,UDCODE,UDCODE,0xfa61, - 0x8f72,UDCODE,UDCODE,0xfa73,0x98d7,UDCODE,0x98dc,0x98da,UDCODE, - UDCODE,0x98d5,UDCODE,UDCODE,0x91ad,0x98d8,UDCODE,0x98db,0x98d9, - UDCODE,0x95db,UDCODE,0x98d6,UDCODE,0x904d,UDCODE,0x9693,0x98dd, - 0x98de,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8f43,0x98eb,UDCODE,UDCODE,UDCODE,0x946f,UDCODE,0x9555,0x98e6, - UDCODE,0x95ee,UDCODE,0x89b4,UDCODE,UDCODE,UDCODE,0x98ea,0xfa76, - 0x98e4,0x98ed,UDCODE,UDCODE,0x9171,UDCODE,0x8cc2,UDCODE,0x947b, - UDCODE,0xe0c5,UDCODE,0x98ec,0x937c,UDCODE,0x98e1,UDCODE,0x8cf4, - UDCODE,UDCODE,0x8cf3,0x98df,UDCODE,UDCODE,UDCODE,0xfa77,0x8ed8, - UDCODE,0x98e7,0xfa75,0x95ed,0x926c,0x98e3,0x8c91,UDCODE,0x98e0, - 0x98e8,0x98e2,0x97cf,0x98e9,0x9860,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8be4,UDCODE,UDCODE,0x8c90,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfa74,UDCODE,0xfa7a,0x98ee, - UDCODE,UDCODE,0xfa78,0x98ef,0x98f3,0x88cc,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x95ce,0x98f2,UDCODE,UDCODE,UDCODE,UDCODE,0x98f1, - 0x98f5,UDCODE,UDCODE,UDCODE,0x98f4,UDCODE,0x92e2,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c92,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x98f6,UDCODE,UDCODE,UDCODE,0xfa79, - UDCODE,0x8ec3,UDCODE,0x91a4,0x92e3,0x8bf4,UDCODE,0x98f7,UDCODE, - UDCODE,UDCODE,UDCODE,0x8b55,UDCODE,UDCODE,0x98f8,UDCODE,UDCODE, - UDCODE,UDCODE,0x98fa,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9654,UDCODE,UDCODE,UDCODE,0x8c86,UDCODE,UDCODE,0xfa7b, - UDCODE,UDCODE,UDCODE,0x8e50,0x94f5,0x98f9,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8dc3,0x9762,UDCODE,UDCODE, - UDCODE,UDCODE,0x98fc,0x9942,0x98fb,0x8dc2,UDCODE,0x8f9d,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c58,UDCODE,UDCODE,UDCODE, - 0x9943,UDCODE,UDCODE,0x8bcd,UDCODE,UDCODE,UDCODE,0x9940,0x9941, - UDCODE,UDCODE,0x93ad,UDCODE,0x919c,UDCODE,0x8ba1,UDCODE,UDCODE, - UDCODE,0x966c,0x9944,UDCODE,0xfa7d,UDCODE,0x97bb,UDCODE,UDCODE, - UDCODE,0x9945,UDCODE,UDCODE,UDCODE,UDCODE,0x9948,UDCODE,0x9946, - UDCODE,0x916d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9947,0x9949, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfa7c,0x994b,UDCODE,UDCODE, - UDCODE,0x994a,UDCODE,0x95c6,0x8b56,0x994d,0x994e,UDCODE,0x89ad, - UDCODE,UDCODE,UDCODE,UDCODE,0x994c,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8ef2,UDCODE,0x9951,0x9950,0x994f, - UDCODE,0x98d4,UDCODE,0x9952,UDCODE,UDCODE,UDCODE,UDCODE,0x8f9e, - UDCODE,0x9953,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9744,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x96d7,UDCODE,UDCODE,UDCODE,UDCODE,0x9955,UDCODE,UDCODE,0x9954, - 0x9957,0x9956,UDCODE,UDCODE,0x9958,0x9959,0x88f2,UDCODE,0x8cb3, - 0x8c5a,0x8f5b,0x929b,0x8ba2,0x90e6,0x8cf5,0xfa7e,0x8d8e,0x995b, - 0x96c6,0x9365,UDCODE,0x8e99,UDCODE,0x995a,UDCODE,0x995c,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x937d,UDCODE,0x8a95,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x995d,UDCODE,0xfa80,0x93fc,UDCODE,UDCODE, - 0x9153,0x995f,0x9960,0x94aa,0x8cf6,0x985a,0x9961,UDCODE,UDCODE, - 0x8ba4,UDCODE,UDCODE,UDCODE,0x95ba,0x91b4,0x8bef,0x9354,UDCODE, - UDCODE,UDCODE,0x8c93,UDCODE,UDCODE,UDCODE,0x9962,UDCODE,0x9963, - UDCODE,UDCODE,0x93e0,0x897e,UDCODE,UDCODE,0x9966,0x8dfb,UDCODE, - 0x9965,0x8dc4,UDCODE,0x9967,0xe3ec,0x9968,0x9660,0x9969,UDCODE, - 0x996a,0x996b,0x8fe7,UDCODE,0x8eca,UDCODE,UDCODE,UDCODE,0xfa81, - UDCODE,UDCODE,0x8aa5,UDCODE,0x996e,UDCODE,0x996c,0x96bb,0x996d, - UDCODE,0x9579,0x996f,0x9970,0x9971,0x937e,UDCODE,UDCODE,UDCODE, - 0x9975,0x9973,0x9974,0x9972,0x8de1,0x9976,0x96e8,0x97e2,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9977,0xfa82,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x90a6,0x9978,0x8f79,UDCODE,UDCODE,0x9979,UDCODE, - 0x929c,0x97bd,0x9380,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x99c3,UDCODE,UDCODE,UDCODE,UDCODE,0x997a,0xeaa3, - 0x8bc3,UDCODE,UDCODE,0x997b,0x967d,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8f88,0x91fa,UDCODE,0x997d,0x93e2,UDCODE,0xfa83,0x997e,UDCODE, - UDCODE,0x9980,0x8a4d,UDCODE,UDCODE,UDCODE,0x9981,0x8ba5,UDCODE, - 0x93ca,0x899a,0x8f6f,UDCODE,UDCODE,0x949f,0x9982,0x9381,UDCODE, - UDCODE,0x906e,0x9983,UDCODE,0x95aa,0x90d8,0x8aa0,UDCODE,0x8aa7, - 0x9984,UDCODE,UDCODE,0x9986,UDCODE,UDCODE,0x8c59,UDCODE,UDCODE, - 0x9985,0xfa84,UDCODE,0x97f1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8f89,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x94bb,0x95ca, - UDCODE,0x9987,UDCODE,0x9798,0x9988,UDCODE,UDCODE,UDCODE,0x9989, - UDCODE,0x939e,UDCODE,UDCODE,0x998a,UDCODE,UDCODE,0x90a7,0x8dfc, - 0x8c94,0x998b,0x8e68,0x8d8f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x92e4,0x998d,UDCODE,UDCODE,0x91a5,UDCODE,UDCODE, - 0x8ded,0x998e,0x998f,0x914f,UDCODE,0x998c,UDCODE,UDCODE,UDCODE, - UDCODE,0x9991,UDCODE,0x9655,UDCODE,UDCODE,UDCODE,UDCODE,0x8d84, - UDCODE,UDCODE,0x9990,UDCODE,UDCODE,UDCODE,UDCODE,0x8c95,0x8ddc, - 0x948d,UDCODE,UDCODE,UDCODE,0x9994,0x9992,UDCODE,UDCODE,UDCODE, - UDCODE,0x959b,0x8fe8,0x999b,0x8a84,0x9995,0x9993,0x916e,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9997,UDCODE,0x9996, - UDCODE,UDCODE,UDCODE,0x8a63,UDCODE,UDCODE,UDCODE,0x8c80,0x999c, - 0x97ab,UDCODE,UDCODE,UDCODE,0x9998,UDCODE,UDCODE,UDCODE,0x999d, - 0x999a,UDCODE,0x9999,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x97cd,0xfa85,UDCODE,UDCODE,0x8cf7,0x89c1,UDCODE,UDCODE,0x97f2, - UDCODE,UDCODE,0xfa86,UDCODE,UDCODE,0x8f95,0x9377,0x8d85,0x99a0, - 0x99a1,UDCODE,0xfb77,UDCODE,0x97e3,UDCODE,UDCODE,0x984a,0x99a3, - UDCODE,UDCODE,UDCODE,0x8cf8,UDCODE,UDCODE,0x99a2,UDCODE,0x8a4e, - UDCODE,0xfa87,0x99a4,UDCODE,0x9675,UDCODE,0x92ba,UDCODE,0x9745, - UDCODE,0x95d7,UDCODE,UDCODE,UDCODE,0x99a5,UDCODE,UDCODE,UDCODE, - UDCODE,0xe8d3,UDCODE,UDCODE,0x93ae,UDCODE,0x99a6,0x8aa8,0x96b1, - UDCODE,0xfa88,UDCODE,0x8f9f,0x99a7,0x95e5,0x99ab,UDCODE,0x90a8, - 0x99a8,0x8bce,UDCODE,0x99a9,0x8aa9,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c4d,0x99ac,UDCODE, - 0x99ad,UDCODE,UDCODE,0x99ae,0x99af,0x8ed9,UDCODE,UDCODE,UDCODE, - 0x8cf9,0x96dc,0xfa89,0x96e6,0x93f5,UDCODE,UDCODE,0x95ef,0x99b0, - 0xfa8a,0x99b1,UDCODE,UDCODE,UDCODE,UDCODE,0x99b3,UDCODE,0x99b5, - 0x99b4,UDCODE,UDCODE,UDCODE,UDCODE,0x99b6,0x89bb,0x966b,UDCODE, - 0x8dfa,0x99b7,UDCODE,UDCODE,0x9178,UDCODE,UDCODE,0x8fa0,0x8ba7, - UDCODE,0x99b8,0xfa8b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x94d9, - UDCODE,UDCODE,UDCODE,UDCODE,0x99b9,UDCODE,0x99ba,UDCODE,0x99bb, - UDCODE,UDCODE,UDCODE,UDCODE,0x99bc,0x9543,0x8be6,0x88e3,UDCODE, - UDCODE,UDCODE,0x93bd,0x99bd,0x8f5c,UDCODE,0x90e7,UDCODE,0x99bf, - 0x99be,0x8fa1,0x8cdf,0x99c1,0x94bc,UDCODE,UDCODE,0x99c2,UDCODE, - UDCODE,UDCODE,0x94da,0x91b2,0x91ec,0x8ba6,UDCODE,UDCODE,0x93ec, - 0x9250,UDCODE,0x948e,UDCODE,0x966d,UDCODE,0x99c4,UDCODE,0x90e8, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c54,UDCODE,UDCODE,0x99c5, - UDCODE,UDCODE,UDCODE,UDCODE,0x99c6,0x894b,0x88f3,0x8aeb,0xfa8c, - 0x91a6,0x8b70,0x9791,UDCODE,0x99c9,0x89b5,UDCODE,UDCODE,0x99c8, - UDCODE,UDCODE,UDCODE,0x8ba8,UDCODE,UDCODE,0x99ca,UDCODE,0x96ef, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfa8d,UDCODE,UDCODE,0x99cb, - UDCODE,0x97d0,UDCODE,0x8cfa,UDCODE,UDCODE,UDCODE,UDCODE,0x8cb4, - 0x99cc,UDCODE,UDCODE,UDCODE,UDCODE,0x99ce,0x99cd,UDCODE,0x907e, - 0x8958,UDCODE,UDCODE,UDCODE,0x897d,0x99cf,UDCODE,0x99d0,UDCODE, - 0xfa8e,0x8cb5,UDCODE,UDCODE,0x99d1,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8b8e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8e51,0x99d2, - UDCODE,UDCODE,UDCODE,UDCODE,0x9694,0x8db3,0x8b79,0x9746,0x916f, - 0x94bd,0x8efb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f66,UDCODE, - 0x8ee6,0x8ef3,UDCODE,0x8f96,UDCODE,0x94be,UDCODE,0xfa8f,UDCODE, - 0x99d5,UDCODE,0x8962,0x9170,0x8cfb,0x8cc3,0x8be5,UDCODE,UDCODE, - 0x99d9,0x9240,0x91fc,0x8ba9,0x8fa2,0x99da,0x99d8,0x89c2,0x91e4, - 0x8eb6,0x8e6a,0x8945,UDCODE,UDCODE,0x8a90,0x8d86,0x8e69,UDCODE, - 0x99db,0x99dc,UDCODE,0x8b68,0x8a65,UDCODE,UDCODE,UDCODE,0x8d87, - 0x8b67,0x92dd,0x8944,0x93af,0x96bc,0x8d40,0x9799,0x9366,0x8cfc, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8c4e,UDCODE,0x99e5,UDCODE,0x8be1,0x9669,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x94db,UDCODE,UDCODE,0x99e4,UDCODE,0x8adc,0x99df, - 0x99e0,0x99e2,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x99e3,UDCODE,0x8b7a,0x9081,UDCODE,0x95ab,0x99e1,0x99dd,0x8ce1, - UDCODE,0x99de,UDCODE,0x9843,UDCODE,UDCODE,UDCODE,0x95f0,UDCODE, - 0x92e6,0x8ce0,0x8d90,UDCODE,UDCODE,UDCODE,0x99e6,UDCODE,UDCODE, - 0x93db,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x99ea,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8efc,UDCODE,0x8ef4,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x99ed,0x99eb,UDCODE,0x96a1,UDCODE, - 0x99e8,0x99f1,0x99ec,UDCODE,UDCODE,UDCODE,0x99ef,0x8cc4,0x96bd, - UDCODE,UDCODE,0x99f0,UDCODE,UDCODE,UDCODE,0x99f2,UDCODE,0x99f4, - UDCODE,UDCODE,UDCODE,0xfa92,0x8dee,0x9861,UDCODE,0x99e9,0x99e7, - 0x99f3,UDCODE,0x99ee,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xfa91,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x99f6,UDCODE,0x9a42,0x99f8,UDCODE,UDCODE,0x99fc,0xfa93,UDCODE, - 0x9a40,0x99f9,UDCODE,UDCODE,0x9a5d,UDCODE,UDCODE,0x8de7,0x8a50, - UDCODE,UDCODE,UDCODE,UDCODE,0x99f7,UDCODE,UDCODE,UDCODE,0x9a44, - 0x88f4,0x9a43,UDCODE,0x88a3,0x9569,0x9a41,UDCODE,0x99fa,UDCODE, - UDCODE,0x99f5,0x99fb,0x8dc6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9a45,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x88f5,0x9a4e,UDCODE,UDCODE,0x9a46,0x9a47,UDCODE,0x8fa3,0x9689, - UDCODE,UDCODE,UDCODE,0x9a4c,0x9a4b,UDCODE,UDCODE,UDCODE,0x934e, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a4d,UDCODE, - UDCODE,0x9a4a,UDCODE,0xfa94,0x8953,UDCODE,0x8db4,0x904f,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a48,0x9382,UDCODE, - UDCODE,UDCODE,0x9a49,UDCODE,0x88a0,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9a53,0x9742,UDCODE,0x8fa5,UDCODE,0x9a59,UDCODE,UDCODE, - UDCODE,UDCODE,0x9a58,0x9a4f,UDCODE,UDCODE,UDCODE,UDCODE,0x91c1, - UDCODE,0x9a50,UDCODE,UDCODE,UDCODE,0x91ed,0x9a55,0x8fa4,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9a52,UDCODE,UDCODE,0x96e2,UDCODE, - UDCODE,UDCODE,0x8c5b,UDCODE,UDCODE,0x9a56,0x9a57,UDCODE,UDCODE, - UDCODE,UDCODE,0x9a54,0x9a5a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9a51,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a60,0x9a65,UDCODE, - 0x9a61,UDCODE,0x9a5c,UDCODE,UDCODE,0x9a66,0x9150,UDCODE,0xfa95, - 0x9a68,UDCODE,0x8d41,0x9a5e,0x929d,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a62, - 0x9a5b,0x8aab,UDCODE,0x8aec,0x8a85,0x9a63,0x9a5f,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c96,0x9a69,0x9a67,0x9172, - 0x8b69,0x8baa,UDCODE,0x9a64,UDCODE,0x8bf2,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8963,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a6d,0x9a6b, - UDCODE,0x9aa5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a70,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9a6a,UDCODE,0x9a6e,UDCODE,UDCODE,0x9a6c,UDCODE, - UDCODE,UDCODE,0x8e6b,0x9a6f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9a72,UDCODE,0x9a77,UDCODE,UDCODE, - UDCODE,0x9a75,0x9a74,0x9251,UDCODE,UDCODE,0x89c3,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a71, - UDCODE,0x9a73,0x8fa6,0x8952,UDCODE,UDCODE,0x9a76,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x89dc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a82, - UDCODE,0x8ffa,0x9a7d,UDCODE,0x9a7b,UDCODE,0x9a7c,UDCODE,0x9a7e, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x895c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9158,UDCODE,0x9a78,UDCODE,0x9a79,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8a9a,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a81,UDCODE, - UDCODE,UDCODE,0x8aed,UDCODE,0x9a84,0x9a80,0x9a83,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95ac,UDCODE,UDCODE,UDCODE, - 0x93d3,UDCODE,0x94b6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a86, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a85,0x8a64,UDCODE,UDCODE, - 0x9a87,UDCODE,UDCODE,UDCODE,UDCODE,0x9a8a,UDCODE,UDCODE,UDCODE, - UDCODE,0x9a89,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9a88,UDCODE,0x9458,UDCODE,UDCODE, - 0x9a8b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9a8c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a8e,UDCODE,0x9a8d, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a90,UDCODE,UDCODE,UDCODE, - 0x9a93,0x9a91,0x9a8f,0x9a92,UDCODE,UDCODE,UDCODE,UDCODE,0x9a94, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a95,UDCODE,UDCODE,0x9a96, - UDCODE,0x9a97,UDCODE,UDCODE,UDCODE,0x9a98,0x9964,UDCODE,0x8efa, - 0x8e6c,UDCODE,UDCODE,0x89f1,UDCODE,0x88f6,UDCODE,UDCODE,0x9263, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9a99,UDCODE,0x8da2,UDCODE,0x88cd,0x907d,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9a9a,0x8cc5,UDCODE,UDCODE,0x8d91,UDCODE, - 0x9a9c,0x9a9b,UDCODE,UDCODE,0x95de,0x9a9d,UDCODE,UDCODE,UDCODE, - 0x9a9f,0x9a9e,UDCODE,0x9aa0,UDCODE,0x9aa1,UDCODE,0x8c97,UDCODE, - UDCODE,0x8980,0x9aa2,UDCODE,UDCODE,0x9aa4,UDCODE,0x9aa3,UDCODE, - UDCODE,UDCODE,0x9aa6,UDCODE,UDCODE,0x9379,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9aa7,0x88b3,0x8ddd,UDCODE,UDCODE,UDCODE, - UDCODE,0x8c5c,UDCODE,UDCODE,0x926e,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9aa8,0x9aa9,UDCODE,UDCODE,0x9aab,UDCODE,UDCODE, - UDCODE,UDCODE,0x9aac,UDCODE,0x8de2,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8bcf,UDCODE,UDCODE,0x9656,UDCODE,UDCODE,UDCODE,0x9aaa,0x9aad, - 0x8dbf,0x8d42,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xfa96,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ab1, - UDCODE,UDCODE,0x8da3,0xfa97,0x9252,UDCODE,UDCODE,0x9aae,0x92d8, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9ab2,UDCODE,UDCODE,0x9082,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9ab0,0x9ab3,UDCODE,0x8c5e,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9ab4,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ab5, - UDCODE,0x8d43,0x8a5f,0x9ab7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9ab8,UDCODE,0xfa98,UDCODE,UDCODE,UDCODE,0x9ab9,UDCODE,UDCODE, - 0x9ab6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9aaf,UDCODE,UDCODE,0x9aba,UDCODE, - UDCODE,0x9abb,0xfa9a,0xfa99,UDCODE,UDCODE,0x9684,UDCODE,UDCODE, - 0x8fe9,UDCODE,UDCODE,UDCODE,0x9abd,0x9abe,0x9abc,UDCODE,0x9ac0, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9457,UDCODE,UDCODE,0x88e6, - 0x9575,UDCODE,UDCODE,0x9ac1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8ffb,UDCODE,UDCODE,0x8eb7,UDCODE,0x947c,0x8aee, - UDCODE,0x8de9,0x9678,UDCODE,0x93b0,UDCODE,UDCODE,0x8c98,0x91cd, - UDCODE,UDCODE,UDCODE,0x9abf,0x9ac2,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x91c2,UDCODE,UDCODE,UDCODE, - 0x9ac3,UDCODE,UDCODE,UDCODE,0x9ac4,UDCODE,UDCODE,UDCODE,0x9ac6, - UDCODE,UDCODE,0x92e7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8aac, - UDCODE,UDCODE,UDCODE,UDCODE,0xea9f,0x8981,0x95f1,UDCODE,UDCODE, - 0x8fea,0x9367,UDCODE,UDCODE,UDCODE,UDCODE,0x8de4,UDCODE,UDCODE, - 0x9acc,UDCODE,UDCODE,0x95bb,0x97db,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x89f2,0x9ac8,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9159,0x9acb,UDCODE,0x9383,UDCODE,UDCODE,0x9368, - 0x9384,0x94b7,0x92cb,UDCODE,UDCODE,UDCODE,0x8dc7,UDCODE,UDCODE, - UDCODE,0x9ac7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8996, - UDCODE,0x9355,UDCODE,UDCODE,UDCODE,UDCODE,0x9ac9,UDCODE,0x9ac5, - UDCODE,UDCODE,0x906f,UDCODE,UDCODE,UDCODE,0x9acd,UDCODE,UDCODE, - UDCODE,UDCODE,0x8f6d,UDCODE,UDCODE,UDCODE,UDCODE,0x8bab,UDCODE, - 0x9ace,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95e6,UDCODE,UDCODE,UDCODE, - 0x919d,UDCODE,UDCODE,UDCODE,UDCODE,0x92c4,UDCODE,0xfa9d,0x9ad0, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x966e, - UDCODE,UDCODE,0x9ad1,UDCODE,UDCODE,0x9ad6,UDCODE,UDCODE,UDCODE, - 0xfa9e,0x95ad,UDCODE,UDCODE,UDCODE,UDCODE,0x9ad5,0x9acf,0x9ad2, - 0x9ad4,UDCODE,UDCODE,0x8da4,UDCODE,UDCODE,0x95c7,UDCODE,UDCODE, - UDCODE,0x9ad7,UDCODE,0x9264,UDCODE,UDCODE,0x89f3,UDCODE,0x8feb, - UDCODE,UDCODE,UDCODE,UDCODE,0x9ad9,UDCODE,0x9ad8,UDCODE,0x8d88, - UDCODE,0x9ada,0x9adc,0x9adb,UDCODE,UDCODE,0x9ade,UDCODE,0x9ad3, - 0x9ae0,UDCODE,UDCODE,UDCODE,UDCODE,0x9adf,0x9add,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8e6d,0x9070,UDCODE,0x9173,0x9ae1,0x90ba, - 0x88eb,0x9484,UDCODE,UDCODE,UDCODE,UDCODE,0x92d9,UDCODE,0x9ae3, - 0x9ae2,0x9ae4,0x9ae5,0x9ae6,0x9ae7,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x95cf,0x9ae8,0xfa9f,UDCODE,UDCODE,UDCODE,0x89c4, - 0x9ae9,UDCODE,UDCODE,UDCODE,UDCODE,0x975b,0x8a4f,UDCODE,0x99c7, - 0x8f67,0x91bd,0x9aea,0x96e9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x96b2,UDCODE,UDCODE,0x9aec,UDCODE,0x91e5,UDCODE,0x9356,0x91be, - 0x9576,0x9aed,0x9aee,0x899b,UDCODE,UDCODE,0x8eb8,0x9aef,UDCODE, - UDCODE,UDCODE,UDCODE,0x88ce,0x9af0,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9af1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8982,UDCODE, - UDCODE,0x8aef,0x93de,0x95f2,UDCODE,UDCODE,UDCODE,UDCODE,0x9af5, - 0x9174,0x9af4,0x8c5f,UDCODE,0xfaa0,0x967a,0x9af3,UDCODE,0x9385, - 0x9af7,UDCODE,0x9af6,0xfaa1,UDCODE,0xfaa2,UDCODE,UDCODE,0x9af9, - UDCODE,0x9af8,0xfaa3,UDCODE,0x899c,UDCODE,0x9afa,0x8fa7,0x9afc, - 0x9244,UDCODE,0x9afb,UDCODE,0x95b1,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8f97,0x937a,UDCODE,UDCODE,UDCODE,0x9b40,UDCODE,UDCODE,UDCODE, - UDCODE,0x8d44,UDCODE,UDCODE,UDCODE,0x9b41,0x9440,0x94dc,0x96cf, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9444,UDCODE,UDCODE,0x9b4a, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b57,UDCODE,UDCODE,0x9764, - UDCODE,UDCODE,0x96ad,UDCODE,0x9baa,UDCODE,0x9b42,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9b45,0xfaa4,0x91c3,UDCODE,UDCODE,0x9657, - UDCODE,UDCODE,UDCODE,0x9369,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9b46,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9685,0xfaa5, - 0x8dc8,UDCODE,UDCODE,0x8fa8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9b47,UDCODE,UDCODE,0x8e6f,UDCODE,0x8e6e,UDCODE, - UDCODE,UDCODE,UDCODE,0x88b7,0x8cc6,UDCODE,0x90a9,0x88cf,UDCODE, - UDCODE,UDCODE,UDCODE,0x9b4b,0x9b4c,UDCODE,0x9b49,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8957,0x8aad,UDCODE, - 0x9b48,UDCODE,0x96c3,0x9550,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x88a6,UDCODE,UDCODE,UDCODE, - UDCODE,0x88f7,UDCODE,UDCODE,UDCODE,0x8e70,0x88d0,UDCODE,0x88a1, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9b51,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9b4f,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x96ba,UDCODE,0x9b52,UDCODE,0x9b50,UDCODE,UDCODE, - 0x9b4e,0x9050,UDCODE,UDCODE,UDCODE,UDCODE,0x9b4d,UDCODE,UDCODE, - UDCODE,0x95d8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ce2,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9b56,0x9b57,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8fa9,UDCODE,UDCODE,UDCODE,0x9b53,0x984b,UDCODE, - UDCODE,UDCODE,UDCODE,0x946b,UDCODE,UDCODE,0x9b55,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8da5,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9b58,UDCODE,UDCODE,UDCODE,0x9577, - UDCODE,UDCODE,UDCODE,0x9b59,UDCODE,0x9b54,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x96b9,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x947d,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9b5a,0x9551,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9b5b,0x9b5f,0x9b5c,UDCODE,UDCODE, - 0x89c5,0x9b5e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8eb9, - UDCODE,0x9b5d,0x8c99,UDCODE,UDCODE,UDCODE,0x9b6b,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9b64,0x9b61,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9284,UDCODE,0x9b60,UDCODE, - UDCODE,0x9b62,UDCODE,UDCODE,0x9b63,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9b65,0x9b66,0x8af0,UDCODE,0x9b68,0x9b67, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9b69,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8fec,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9b6c,UDCODE,0x92da,UDCODE,UDCODE,UDCODE,0x8964, - UDCODE,0x9b6a,UDCODE,UDCODE,UDCODE,0x9b6d,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9b6e,UDCODE,0x9b71,UDCODE,UDCODE, - 0x9b6f,UDCODE,0x9b70,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8e71,0x9b72,UDCODE,UDCODE,0x8d45, - 0x9b73,0xfaa6,0x8e9a,0x91b6,UDCODE,0x9b74,0x9b75,0x8e79,0x8d46, - UDCODE,0x96d0,UDCODE,UDCODE,UDCODE,0x8b47,0x8cc7,0x9b76,0x8a77, - UDCODE,UDCODE,0x9b77,UDCODE,0x91b7,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9b78,0x9ba1,UDCODE,0x9b79,UDCODE,0x9b7a,UDCODE,UDCODE,0x9b7b, - UDCODE,0x9b7d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9b7e,UDCODE, - UDCODE,0x9b80,UDCODE,0x91ee,UDCODE,0x8946,0x8ee7,0x88c0,UDCODE, - 0x9176,0x8aae,0x8eb3,UDCODE,0x8d47,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9386,UDCODE,0x8f40,0x8aaf,0x9288,0x92e8,0x88b6,0x8b58, - 0x95f3,UDCODE,0x8ec0,UDCODE,UDCODE,0x8b71,0x90e9,0x8eba,0x9747, - 0x9b81,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b7b, - UDCODE,0x8dc9,UDCODE,UDCODE,0x8a51,0x8983,0x8faa,0x89c6,UDCODE, - 0x9b82,0x9765,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f68,0xfaa7, - UDCODE,0x8ee2,0x9b83,0x8af1,0x93d0,0x96a7,0x9b84,UDCODE,0x9b85, - UDCODE,UDCODE,0x9578,UDCODE,UDCODE,UDCODE,0x9b87,UDCODE,0x8aa6, - 0x8bf5,0x9b86,UDCODE,UDCODE,UDCODE,0xfaa9,UDCODE,UDCODE,0x8ab0, - UDCODE,0x9051,0x9b8b,0x8e40,UDCODE,0x89c7,0x9b8a,UDCODE,0x9b88, - 0x9b8c,0x9b89,0x944a,0x9ecb,0x9052,UDCODE,0x9b8d,0xfaaa,UDCODE, - 0x97be,UDCODE,0x9b8e,UDCODE,UDCODE,0x9b90,UDCODE,0x929e,0x9b8f, - UDCODE,0x90a1,UDCODE,0x8e9b,UDCODE,UDCODE,UDCODE,0x91ce,0x8ef5, - 0x9595,0x90ea,UDCODE,0x8ecb,0x9b91,0x8fab,0x9b92,0x9b93,0x88d1, - 0x91b8,0x9071,UDCODE,0x9b94,0x93b1,0x8fac,UDCODE,0x8fad,UDCODE, - 0x9b95,UDCODE,UDCODE,0x90eb,UDCODE,UDCODE,UDCODE,0x8fae,UDCODE, - UDCODE,UDCODE,0xfaab,UDCODE,0x9b96,UDCODE,0x9b97,UDCODE,0x96de, - UDCODE,UDCODE,UDCODE,0x9b98,UDCODE,UDCODE,UDCODE,UDCODE,0x8bc4, - UDCODE,UDCODE,UDCODE,0x8f41,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9b99,0x9b9a,0x8eda,0x904b,0x93f2,0x9073,0x94f6,0x9441, - 0x8bc7,0x9b9b,UDCODE,UDCODE,UDCODE,0x8b8f,0x9b9c,UDCODE,0x8bfc, - UDCODE,0x93cd,0x89ae,UDCODE,0x8e72,0x9b9d,0x9ba0,0x9b9f,0x8bfb, - UDCODE,0x9b9e,UDCODE,0x9357,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x91ae,UDCODE,0x936a,0x8ec6,UDCODE,UDCODE, - 0x9177,0x979a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ba2, - UDCODE,0x9ba3,0x93d4,UDCODE,0x8e52,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9ba5,UDCODE,UDCODE,0x9ba6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9ba7,UDCODE,UDCODE,UDCODE,0x8af2, - 0x9ba8,UDCODE,UDCODE,0x9ba9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89aa,UDCODE, - UDCODE,UDCODE,UDCODE,0xfaac,UDCODE,0x915a,0x8ae2,UDCODE,0x9bab, - 0x96a6,UDCODE,UDCODE,UDCODE,UDCODE,0x91d0,UDCODE,0x8a78,UDCODE, - UDCODE,0x9bad,0x9baf,0x8add,UDCODE,0xfaad,0x9bac,0x9bae,UDCODE, - 0x9bb1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bb0,UDCODE, - 0x9bb2,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9bb3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x93bb,0x8bac, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89e3,0x9bb4,0x9bb9, - UDCODE,UDCODE,0x9bb7,UDCODE,0x95f5,0x95f4,UDCODE,UDCODE,UDCODE, - UDCODE,0xfaae,0x9387,UDCODE,UDCODE,UDCODE,0x9bb6,0x8f73,UDCODE, - 0x9bb5,0x9092,UDCODE,UDCODE,UDCODE,0x9bba,UDCODE,UDCODE,0x8de8, - UDCODE,UDCODE,0x9bc0,UDCODE,UDCODE,0x9bc1,0x9bbb,0x8a52,0x9bbc, - 0x9bc5,0x9bc4,0x9bc3,0x9bbf,UDCODE,UDCODE,UDCODE,0x9bbe,UDCODE, - UDCODE,0x9bc2,UDCODE,UDCODE,UDCODE,UDCODE,0xfaaf,UDCODE,0x95f6, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfab2,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bc9,0x9bc6,UDCODE, - 0x9bc8,UDCODE,0x9792,UDCODE,0x9bc7,0xfab0,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bbd,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9093,UDCODE,UDCODE,0x9bca,0xfab3,UDCODE,0x8db5,UDCODE,UDCODE, - UDCODE,0x9bcb,UDCODE,UDCODE,0x9bcc,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bcf,UDCODE, - 0x9bce,UDCODE,UDCODE,0x9bcd,UDCODE,UDCODE,UDCODE,0x9388,0x9bb8, - UDCODE,UDCODE,UDCODE,0x9bd5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bd1,UDCODE, - UDCODE,UDCODE,UDCODE,0x9bd0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9bd2,UDCODE,0x9bd3,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bd6,0xfab4,0xfab5, - 0x97e4,UDCODE,0x9bd7,0x9bd4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bd8,UDCODE,UDCODE, - 0x8ade,0x9bd9,UDCODE,UDCODE,0xfab6,UDCODE,0x9bdb,0x9bda,UDCODE, - UDCODE,0x9bdc,UDCODE,UDCODE,UDCODE,UDCODE,0x9bdd,UDCODE,0x90ec, - 0x8f42,UDCODE,UDCODE,0x8f84,UDCODE,0x9183,UDCODE,0x8d48,0x8db6, - 0x8d49,0x8b90,UDCODE,UDCODE,0x9bde,UDCODE,UDCODE,0x8db7,UDCODE, - UDCODE,0x8cc8,0x9bdf,0x96a4,0x9462,0x9be0,UDCODE,0x8d4a,UDCODE, - UDCODE,UDCODE,0x8aaa,UDCODE,0x9246,0x8bd0,0x8e73,0x957a,UDCODE, - UDCODE,0x94bf,UDCODE,UDCODE,UDCODE,UDCODE,0x9be1,0x8af3,UDCODE, - UDCODE,UDCODE,UDCODE,0x9be4,UDCODE,UDCODE,UDCODE,UDCODE,0x929f, - UDCODE,UDCODE,0x9be3,0x9be2,0x9be5,UDCODE,0x92e9,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9083,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8e74,UDCODE,0x90c8,UDCODE,0x91d1,0x8b41,UDCODE, - UDCODE,0x92a0,UDCODE,UDCODE,0x9be6,0x9be7,0x8fed,UDCODE,UDCODE, - UDCODE,UDCODE,0x9658,UDCODE,UDCODE,0x9bea,UDCODE,UDCODE,0x9be9, - 0x9be8,0x959d,UDCODE,0x9bf1,UDCODE,UDCODE,UDCODE,UDCODE,0x9679, - UDCODE,0x9beb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bed,0x968b, - UDCODE,0x9bec,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9bee,UDCODE,0x94a6,0x9bef,0x95bc,0x9bf0,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x8ab1,0x95bd,0x944e,0x9bf2,0x9bf3,UDCODE,0x8d4b,0x8ab2, - 0x9bf4,0x8cb6,0x9763,0x9748,0x8af4,0x9bf6,UDCODE,0x92a1,UDCODE, - 0x8d4c,0x8faf,UDCODE,UDCODE,0x94dd,UDCODE,UDCODE,0x8fb0,UDCODE, - UDCODE,UDCODE,UDCODE,0x8f98,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x92ea,0x95f7,0x9358,UDCODE,UDCODE,0x8d4d,UDCODE,0x957b,UDCODE, - UDCODE,UDCODE,0x9bf7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9378, - 0x8dc0,UDCODE,UDCODE,UDCODE,0x8cc9,UDCODE,0x92eb,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x88c1,0x8f8e,0x8d4e,0x9766, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bf8, - 0x9bf9,0x9470,UDCODE,UDCODE,UDCODE,UDCODE,0x9bfa,0x97f5,0x984c, - UDCODE,UDCODE,UDCODE,UDCODE,0x9bfc,0x9bfb,UDCODE,UDCODE,0x8a66, - UDCODE,UDCODE,0x9c40,UDCODE,UDCODE,UDCODE,0x9c43,0x9c44,UDCODE, - 0x9c42,UDCODE,0x955f,0x8fb1,0x9c46,0x9c45,0x9c41,UDCODE,UDCODE, - UDCODE,UDCODE,0x9c47,0x9c48,UDCODE,UDCODE,0x9c49,UDCODE,UDCODE, - UDCODE,0x9c4c,0x9c4a,UDCODE,0x9c4b,0x9c4d,UDCODE,0x8984,0x92ec, - 0x9c4e,UDCODE,0x8c9a,0x89f4,0x9455,UDCODE,0x9c4f,0x93f9,0x95d9, - UDCODE,0x9c50,0x984d,UDCODE,UDCODE,UDCODE,UDCODE,0x9c51,0x95be, - 0x9c54,0x989f,0x98af,UDCODE,0x8eae,0x93f3,0x9c55,UDCODE,0x8b7c, - 0x92a2,0x88f8,0x9c56,0x95a4,0x8d4f,UDCODE,UDCODE,0x926f,UDCODE, - UDCODE,UDCODE,0x92ed,UDCODE,0xfab7,UDCODE,UDCODE,UDCODE,0x96ed, - 0x8cb7,0x8cca,UDCODE,0x9c57,UDCODE,UDCODE,UDCODE,0x9c58,UDCODE, - 0x9c5e,UDCODE,0x8ee3,UDCODE,UDCODE,0xfab8,0x92a3,UDCODE,0x8bad, - 0x9c59,UDCODE,UDCODE,UDCODE,0x954a,UDCODE,0x9265,UDCODE,UDCODE, - 0x9c5a,UDCODE,UDCODE,UDCODE,0xfa67,UDCODE,UDCODE,0x9c5b,UDCODE, - 0x8bae,UDCODE,0x9c5c,UDCODE,0x9c5d,UDCODE,UDCODE,0x9c5f,UDCODE, - 0x9396,UDCODE,UDCODE,0x9c60,0x9c61,UDCODE,0x9c62,UDCODE,UDCODE, - 0x9c53,0x9c52,UDCODE,UDCODE,UDCODE,0x9c63,0x8c60,UDCODE,UDCODE, - UDCODE,0x9546,0xfab9,UDCODE,0x8dca,0x9556,0x92a4,0x956a,0x9c64, - UDCODE,UDCODE,0x8fb2,0x8965,UDCODE,0x9c65,UDCODE,UDCODE,UDCODE, - 0x9c66,UDCODE,0x96f0,UDCODE,UDCODE,0x94de,UDCODE,UDCODE,0x9c69, - 0x899d,0x90aa,0x9c68,0x9c67,0x8c61,0x91d2,UDCODE,0x9c6d,0x9c6b, - UDCODE,0x9c6a,0x97a5,0x8ce3,UDCODE,UDCODE,UDCODE,0x8f99,0x9c6c, - 0x936b,0x8f5d,UDCODE,UDCODE,UDCODE,0x93be,0x9c70,0x9c6f,UDCODE, - UDCODE,UDCODE,UDCODE,0x9c6e,UDCODE,0x9c71,0x8ce4,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9c72,0x959c,0x8f7a,UDCODE,UDCODE, - 0x9c73,0x94f7,UDCODE,UDCODE,UDCODE,UDCODE,0x93bf,0x92a5,UDCODE, - UDCODE,0xfaba,UDCODE,0x934f,UDCODE,UDCODE,0x9c74,0x8b4a,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9053,UDCODE,0x954b,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8af5,0x9445,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9c75,0x8e75,0x9659,0x965a, - UDCODE,UDCODE,0x899e,0x9c7a,0xfabb,UDCODE,0x9289,UDCODE,UDCODE, - UDCODE,0x9c77,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89f5, - UDCODE,UDCODE,UDCODE,UDCODE,0x9cab,0x9c79,UDCODE,UDCODE,UDCODE, - 0x944f,UDCODE,UDCODE,0x9c78,UDCODE,UDCODE,0x9c76,UDCODE,0x8d9a, - UDCODE,0x9c7c,0x9c83,0x9c89,0x9c81,UDCODE,0x937b,UDCODE,UDCODE, - 0x9c86,0x957c,UDCODE,UDCODE,0x9c80,UDCODE,0x9c85,0x97e5,0x8e76, - UDCODE,UDCODE,0x91d3,0x9c7d,UDCODE,UDCODE,UDCODE,0x8b7d,0x9c88, - 0x90ab,0x8985,0x9c82,0x89f6,0x9c87,UDCODE,UDCODE,UDCODE,0x8baf, - UDCODE,0x9c84,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9c8a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9c8c, - 0x9c96,0x9c94,UDCODE,UDCODE,0x9c91,UDCODE,UDCODE,UDCODE,0x9c90, - 0x97f6,UDCODE,0x9c92,UDCODE,UDCODE,0x8bb0,UDCODE,0x8d50,UDCODE, - UDCODE,0x8f9a,UDCODE,UDCODE,UDCODE,0x9c99,0x9c8b,UDCODE,UDCODE, - 0xfabc,UDCODE,0x9c8f,0x9c7e,UDCODE,0x89f8,0x9c93,0x9c95,0x9270, - UDCODE,UDCODE,0x8da6,0x89b6,0x9c8d,0x9c98,0x9c97,0x8bb1,UDCODE, - 0x91a7,0x8a86,UDCODE,UDCODE,UDCODE,UDCODE,0x8c62,UDCODE,0x9c8e, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9c9a,UDCODE,0x9c9d,0x9c9f,0xfabd,UDCODE,UDCODE,UDCODE,0x8ebb, - 0xfabe,0x9ca5,0x92ee,0x9c9b,UDCODE,UDCODE,UDCODE,UDCODE,0x9ca3, - UDCODE,0x89f7,UDCODE,0x9ca1,0x9ca2,UDCODE,UDCODE,0x9c9e,0x9ca0, - UDCODE,UDCODE,UDCODE,0x8ce5,0x9749,UDCODE,UDCODE,0x8ab3,UDCODE, - UDCODE,0x8978,0x9ca4,UDCODE,0x9459,0x88ab,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x94df,0x9c7b,0x9caa,0x9cae,0x96e3, - UDCODE,0x9ca7,UDCODE,UDCODE,UDCODE,0x9389,0x9cac,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8fee,0x9cad,0x93d5,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9866, - UDCODE,0x9ca9,UDCODE,0xfac0,UDCODE,UDCODE,0x9caf,UDCODE,0x8d9b, - UDCODE,0x90c9,UDCODE,0xfabf,0x88d2,0x9ca8,0x9ca6,UDCODE,0x9179, - UDCODE,UDCODE,UDCODE,0x9c9c,0x8e53,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x91c4,0x9cbb,0xfac2,0x917a,0x9cb6,UDCODE, - 0x9cb3,0x9cb4,UDCODE,0x8ee4,0x9cb7,0x9cba,0x9cb5,0x8f44,UDCODE, - 0x9cb8,UDCODE,UDCODE,0x9cb2,UDCODE,0x96fa,0x96f9,UDCODE,UDCODE, - UDCODE,0x9cbc,0x9cbd,0x88d3,UDCODE,0xfac3,UDCODE,UDCODE,UDCODE, - 0x9cb1,UDCODE,UDCODE,UDCODE,UDCODE,0x8bf0,0x88a4,UDCODE,UDCODE, - UDCODE,0x8ab4,0xfac1,0x9cb9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9cc1,0x9cc0,UDCODE,UDCODE,UDCODE,0x9cc5,UDCODE,UDCODE,UDCODE, - 0xfac5,UDCODE,UDCODE,UDCODE,0x9cc6,UDCODE,UDCODE,0xfac4,UDCODE, - UDCODE,UDCODE,UDCODE,0x9cc4,0x9cc7,0x9cbf,0x9cc3,UDCODE,UDCODE, - 0x9cc8,UDCODE,0x9cc9,UDCODE,UDCODE,0x9cbe,0x8e9c,UDCODE,0x9cc2, - 0x91d4,0x8d51,0x9cb0,0x9054,UDCODE,UDCODE,UDCODE,UDCODE,0x9cd6, - UDCODE,0x95e7,UDCODE,UDCODE,0x9ccc,0x9ccd,0x9cce,UDCODE,UDCODE, - 0x9cd5,UDCODE,0x9cd4,UDCODE,UDCODE,0x969d,0x8ab5,UDCODE,0x9cd2, - UDCODE,0x8c64,0x8a53,UDCODE,UDCODE,0x9ccf,UDCODE,UDCODE,0x97b6, - 0x9cd1,0x88d4,0x9cd3,UDCODE,0x9cca,0x9cd0,0x9cd7,0x8c63,0x9ccb, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x977c,UDCODE,UDCODE, - UDCODE,0x974a,UDCODE,UDCODE,UDCODE,UDCODE,0x9cda,UDCODE,UDCODE, - 0x9cde,UDCODE,UDCODE,UDCODE,0x919e,UDCODE,0x97f7,0x9cdf,UDCODE, - UDCODE,0x9cdc,UDCODE,0x9cd9,UDCODE,0xfac6,0x9cd8,0x9cdd,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95ae, - UDCODE,UDCODE,0x93b2,UDCODE,0x8c65,UDCODE,0x9ce0,0x9cdb,UDCODE, - 0x9ce1,UDCODE,UDCODE,UDCODE,0x8c9b,UDCODE,UDCODE,UDCODE,0x89af, - UDCODE,UDCODE,UDCODE,0x9ce9,UDCODE,UDCODE,UDCODE,0x8ab6,UDCODE, - UDCODE,UDCODE,UDCODE,0x9ce7,UDCODE,UDCODE,0x9ce8,0x8da7,0x9ce6, - 0x9ce4,0x9ce3,0x9cea,0x9ce2,0x9cec,UDCODE,UDCODE,0x89f9,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9cee, - UDCODE,UDCODE,0x9ced,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x92a6,UDCODE,0x9cf1,UDCODE, - 0x9cef,0x9ce5,0x8c9c,UDCODE,0x9cf0,UDCODE,0x9cf4,0x9cf3,0x9cf5, - 0x9cf2,0x9cf6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9cf7,0x9cf8,0x95e8,UDCODE,0x9cfa,0x9cf9,0x8f5e,UDCODE,0x90ac, - 0x89e4,0x89fa,0xfac7,0x9cfb,UDCODE,0x88bd,UDCODE,UDCODE,UDCODE, - 0x90ca,0x9cfc,UDCODE,0xe6c1,0x9d40,0x8c81,UDCODE,0x9d41,UDCODE, - UDCODE,UDCODE,UDCODE,0x90ed,UDCODE,UDCODE,UDCODE,0x9d42,UDCODE, - UDCODE,UDCODE,0x9d43,0x8b59,0x9d44,UDCODE,0x9d45,0x9d46,0x91d5, - UDCODE,UDCODE,UDCODE,0x8ccb,UDCODE,UDCODE,0x96df,UDCODE,UDCODE, - UDCODE,0x965b,0x8f8a,0x9d47,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x90ee,0xe7bb,0x94e0,UDCODE,0x8ee8,UDCODE,0x8dcb,0x9d48,UDCODE, - UDCODE,UDCODE,UDCODE,0x91c5,UDCODE,0x95a5,UDCODE,UDCODE,0x91ef, - UDCODE,UDCODE,0x9d4b,UDCODE,UDCODE,0x9d49,UDCODE,0x9d4c,UDCODE, - UDCODE,0x9d4a,UDCODE,UDCODE,UDCODE,UDCODE,0x9d4d,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x95af,UDCODE,UDCODE,0x88b5,UDCODE,UDCODE, - UDCODE,UDCODE,0x957d,UDCODE,UDCODE,0x94e1,UDCODE,UDCODE,0x9d4e, - UDCODE,0x9d51,0x8fb3,0x8b5a,UDCODE,0x9d4f,0x9d56,0x8fb4,UDCODE, - UDCODE,UDCODE,UDCODE,0x9d50,0x9463,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x977d,0x9d52,0x9d53,0x9d57,0x938a,0x9d54,0x8d52, - 0x90dc,UDCODE,UDCODE,0x9d65,0x94b2,UDCODE,0x91f0,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfac8,UDCODE,UDCODE,UDCODE, - UDCODE,0x94e2,0x9dab,UDCODE,UDCODE,UDCODE,UDCODE,0x95f8,UDCODE, - UDCODE,UDCODE,0x92ef,UDCODE,UDCODE,UDCODE,0x9695,UDCODE,0x9d5a, - 0x899f,0x928a,UDCODE,UDCODE,UDCODE,UDCODE,0x9d63,UDCODE,UDCODE, - 0x9253,0x9d5d,0x9d64,0x9d5f,0x9d66,0x9d62,UDCODE,0x9d61,0x948f, - UDCODE,0x9d5b,0x89fb,0x9d59,0x8b91,0x91f1,0x9d55,UDCODE,UDCODE, - 0x9d58,0x8d53,0x90d9,UDCODE,0x8fb5,0x9d60,0x9471,UDCODE,UDCODE, - 0x8b92,0x8a67,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8a87,0x9040,0x9d68,0x9d6d,UDCODE,0x9d69, - UDCODE,0x8c9d,UDCODE,0x9d6e,0x8e41,0x8d89,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8f45,0x9d5c,0x8e9d,0x9d6b,UDCODE,UDCODE, - UDCODE,UDCODE,0x8e77,0x9d6c,0x88c2,UDCODE,UDCODE,0x9d67,UDCODE, - UDCODE,UDCODE,UDCODE,0x92a7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8b93,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8bb2, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9d6a,0x88a5, - UDCODE,UDCODE,0x8dc1,UDCODE,UDCODE,UDCODE,0x9055,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x92f0, - UDCODE,UDCODE,0x94d2,0x9d70,0x917d,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x91a8,UDCODE,UDCODE,0x8e4a, - 0x9d71,UDCODE,0x9d73,0x9d6f,UDCODE,UDCODE,UDCODE,UDCODE,0x95df, - UDCODE,0x92bb,UDCODE,UDCODE,UDCODE,UDCODE,0x917b,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95f9, - 0x8ecc,0x9d80,UDCODE,0x9d7e,UDCODE,UDCODE,0x9098,UDCODE,UDCODE, - UDCODE,0x8c9e,UDCODE,UDCODE,UDCODE,0x9d78,0x8fb7,UDCODE,UDCODE, - 0x93e6,0x9450,UDCODE,UDCODE,UDCODE,UDCODE,0x9d76,UDCODE,UDCODE, - 0x917c,UDCODE,UDCODE,UDCODE,UDCODE,0x8ef6,0x9d7b,UDCODE,UDCODE, - 0x8fb6,UDCODE,0x9d75,0x9d7a,UDCODE,UDCODE,0x9472,UDCODE,UDCODE, - UDCODE,0x9d74,UDCODE,0x8c40,UDCODE,UDCODE,0x8a7c,UDCODE,UDCODE, - UDCODE,0x9d7c,0x97a9,0x8dcc,0x9254,0x9d79,UDCODE,0x90da,UDCODE, - 0x8d54,0x9084,0x8986,0x915b,0x9d77,0x8b64,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8c66,UDCODE,0x92cd,0x9d7d,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x917e,UDCODE,UDCODE,0x9d81,UDCODE,0x9d83,UDCODE, - UDCODE,0x91b5,0x9d89,UDCODE,0x9d84,UDCODE,UDCODE,0x9d86,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9560,0x92f1,UDCODE,0x9d87,UDCODE, - UDCODE,UDCODE,0x974b,UDCODE,UDCODE,UDCODE,0x9767,0x8ab7,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x88ac,UDCODE,0x9d85,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9d82,UDCODE,UDCODE,UDCODE,UDCODE,0x8af6, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8987,0xfac9,0x9d88,UDCODE, - UDCODE,UDCODE,0x9768,0x9d8c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x91b9,UDCODE,0x9d93,UDCODE,UDCODE,UDCODE,0x9d8d,UDCODE, - UDCODE,0x9d8a,0x9d91,UDCODE,UDCODE,UDCODE,UDCODE,0x9d72,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9d8e, - UDCODE,0x9d92,UDCODE,UDCODE,UDCODE,0x94c0,0x938b,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9d8b,UDCODE,0x9d8f,UDCODE,UDCODE, - UDCODE,0x8c67,UDCODE,UDCODE,UDCODE,0x8def,UDCODE,UDCODE,UDCODE, - 0x90db,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9d97,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9345,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xfaca,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9d94,UDCODE,0x9680,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9d95,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9d96,UDCODE, - 0x96cc,UDCODE,0x90a0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8c82,UDCODE,UDCODE,UDCODE,UDCODE,0x9d9d,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8e54, - 0x9d9a,UDCODE,0x9d99,UDCODE,UDCODE,UDCODE,UDCODE,0x9451,UDCODE, - UDCODE,0xfacb,0x93b3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9350, - 0x9d9b,UDCODE,UDCODE,UDCODE,0x9d9c,UDCODE,0x958f,UDCODE,0x9464, - 0x8e42,UDCODE,0x90ef,UDCODE,0x966f,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8a68,UDCODE,0x9da3,0x9d9e,UDCODE,UDCODE,UDCODE, - UDCODE,0x9769,0x9da5,UDCODE,UDCODE,0x9da1,UDCODE,0x9da2,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9180,0xfacc,UDCODE,UDCODE,UDCODE, - 0x9da0,UDCODE,0x9d5e,UDCODE,UDCODE,UDCODE,0x9da4,UDCODE,0x9d9f, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9da9,0x9daa,0x9346,0x9dac, - UDCODE,UDCODE,0x8e43,0x9da7,UDCODE,UDCODE,UDCODE,UDCODE,0x8b5b, - UDCODE,UDCODE,0x9dad,UDCODE,0x9da6,0x9db1,UDCODE,0x9db0,UDCODE, - 0x9daf,UDCODE,UDCODE,UDCODE,0x9db2,UDCODE,UDCODE,0x9db4,0x8fef, - 0x9db3,UDCODE,UDCODE,UDCODE,UDCODE,0x9db7,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9db5,UDCODE,UDCODE, - UDCODE,0x9db6,0x9d90,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9db9, - 0x9db8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9d98,0x9dba,0x9dae, - UDCODE,UDCODE,0x8e78,UDCODE,UDCODE,UDCODE,UDCODE,0x9dbb,0x9dbc, - 0x9dbe,0x9dbd,0x9dbf,0x89fc,UDCODE,0x8d55,UDCODE,UDCODE,0x95fa, - 0x90ad,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ccc,UDCODE,UDCODE, - 0x9dc1,UDCODE,UDCODE,UDCODE,UDCODE,0x9dc4,0xfacd,0x9571,UDCODE, - 0x8b7e,UDCODE,UDCODE,UDCODE,0x9dc3,0x9dc2,0x9473,0x9dc5,0x8bb3, - UDCODE,UDCODE,UDCODE,0x9dc7,0x9dc6,UDCODE,UDCODE,UDCODE,0x8ab8, - 0x8e55,UDCODE,UDCODE,0x93d6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8c68,UDCODE,UDCODE,UDCODE,0x9094,UDCODE,0x9dc8,UDCODE,0x90ae, - 0x9347,UDCODE,0x957e,0x9dc9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9dca,0x9dcb,UDCODE,UDCODE,UDCODE, - 0x95b6,0x9b7c,0x90c4,UDCODE,UDCODE,0x956b,UDCODE,0x8dd6,UDCODE, - 0x94e3,0x94c1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x936c,UDCODE, - 0x97bf,UDCODE,0x9dcd,0x8ece,UDCODE,UDCODE,0x9dce,UDCODE,0x88b4, - UDCODE,UDCODE,0x8bd2,0x90cb,UDCODE,0x9580,UDCODE,UDCODE,UDCODE, - 0x9dcf,0x8e61,0x9266,UDCODE,0x8e7a,0x9056,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9dd0,UDCODE,0x95fb,UDCODE,UDCODE,0x8997, - 0x8e7b,UDCODE,UDCODE,UDCODE,0x9dd3,UDCODE,0x9dd1,0x9dd4,0x97b7, - 0x9dd2,UDCODE,UDCODE,UDCODE,UDCODE,0x90f9,0x9dd5,UDCODE,UDCODE, - 0x91b0,UDCODE,UDCODE,0x9dd6,UDCODE,UDCODE,UDCODE,UDCODE,0x8af8, - UDCODE,0x9dd8,UDCODE,0x9dd7,UDCODE,UDCODE,UDCODE,UDCODE,0x9dd9, - 0x9dda,0x8af9,UDCODE,UDCODE,0x93fa,0x9255,0x8b8c,0x8e7c,0x9181, - UDCODE,UDCODE,0x8f7b,0x88ae,UDCODE,UDCODE,UDCODE,0x9ddb,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89a0,0x9ddf, - 0xface,UDCODE,0x8d56,0x9dde,UDCODE,UDCODE,0x8da9,0x8fb8,UDCODE, - 0xfad1,0x9ddd,UDCODE,0x8fb9,UDCODE,0x96be,0x8da8,UDCODE,UDCODE, - UDCODE,0x88d5,0x90cc,0xfacf,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9de4,UDCODE,0xfad3,0x90af,0x8966,UDCODE,UDCODE,UDCODE, - 0xfad4,0x8f74,UDCODE,0x9686,0x8df0,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8fba,0xfad2,0x90a5,UDCODE,0xfa63,UDCODE,UDCODE,0x9de3,0x9de1, - 0x9de2,UDCODE,UDCODE,UDCODE,UDCODE,0xfad0,0x928b,UDCODE,UDCODE, - 0x9e45,UDCODE,0x9de8,0x8e9e,0x8d57,0x9de6,UDCODE,UDCODE,UDCODE, - UDCODE,0x9de7,UDCODE,0x9057,UDCODE,UDCODE,UDCODE,0x9de5,UDCODE, - UDCODE,0x8e4e,UDCODE,UDCODE,UDCODE,UDCODE,0xfad6,UDCODE,0xfad7, - UDCODE,UDCODE,UDCODE,0x9dea,0x9de9,0x9dee,UDCODE,UDCODE,0x9def, - UDCODE,0x9deb,0xfad5,0x8a41,0x9dec,0x9ded,0x94d3,UDCODE,UDCODE, - UDCODE,UDCODE,0x9581,0x8c69,0x9df0,UDCODE,UDCODE,0xfad9,0x90b0, - UDCODE,0x8fbb,UDCODE,UDCODE,UDCODE,0x9271,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8bc5,UDCODE,0x9df1,0x9df5,UDCODE,UDCODE, - 0x89c9,0x9df2,0x9df4,UDCODE,UDCODE,UDCODE,UDCODE,0x9df3,UDCODE, - UDCODE,0x8f8b,UDCODE,UDCODE,UDCODE,UDCODE,0x9267,0x88c3,0x9df6, - 0xfada,UDCODE,UDCODE,UDCODE,0x9df7,UDCODE,UDCODE,0xfadb,UDCODE, - 0x92a8,UDCODE,UDCODE,UDCODE,0x97ef,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8e62,UDCODE,UDCODE,0x95e9,UDCODE,UDCODE,UDCODE,0xfadc,UDCODE, - 0x965c,UDCODE,UDCODE,UDCODE,0x9e41,0x9df9,UDCODE,UDCODE,0x9dfc, - UDCODE,0x9dfb,0xfadd,UDCODE,0x9df8,UDCODE,UDCODE,0x9e40,UDCODE, - UDCODE,0x93dc,UDCODE,0x9dfa,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e42,UDCODE, - UDCODE,0x8f8c,0x9e43,UDCODE,0x976a,0x9498,UDCODE,UDCODE,0x9e44, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e46,UDCODE,UDCODE,0x9e47, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e48,UDCODE,0x8bc8, - 0x8967,0x8d58,0x9e49,UDCODE,0x9e4a,0x8f91,0x9182,0xfade,0xfa66, - 0x99d6,0x915d,0x915c,0x91d6,0x8dc5,UDCODE,UDCODE,0x98f0,UDCODE, - UDCODE,UDCODE,UDCODE,0x8c8e,0x974c,UDCODE,0x95fc,UDCODE,0x959e, - 0xfadf,0x9e4b,UDCODE,UDCODE,UDCODE,UDCODE,0x8df1,0x92bd,0x9e4c, - 0x984e,UDCODE,UDCODE,UDCODE,0x965d,UDCODE,0x92a9,0x9e4d,0x8afa, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e4e,0x9e4f,0x96d8, - UDCODE,0x96a2,0x9696,0x967b,0x8e44,0x9e51,UDCODE,UDCODE,0x8ee9, - UDCODE,UDCODE,0x9670,UDCODE,0x9e53,0x9e56,0x9e55,UDCODE,0x8af7, - UDCODE,UDCODE,0x8b80,UDCODE,0x9e52,UDCODE,0x9e54,UDCODE,UDCODE, - UDCODE,UDCODE,0x9e57,UDCODE,UDCODE,0x9099,UDCODE,UDCODE,UDCODE, - UDCODE,0x979b,0x88c7,0x8dde,0x91ba,UDCODE,0x8edb,UDCODE,UDCODE, - 0x8ff1,UDCODE,UDCODE,0x9e5a,UDCODE,UDCODE,0x936d,UDCODE,0x9e58, - 0x91a9,0x9e59,0x8ff0,0x96db,0x9e5b,0x9e5c,0x9788,0xfae1,UDCODE, - UDCODE,UDCODE,0x9e61,UDCODE,UDCODE,0x8d59,UDCODE,0x9474,0x9e5e, - 0x938c,0x9ddc,0x9de0,UDCODE,0x8b6e,UDCODE,0x9466,UDCODE,UDCODE, - UDCODE,UDCODE,0x9e60,UDCODE,0x8fbc,0x94c2,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9e66,UDCODE,0x94f8,UDCODE,0x9e5d,UDCODE,0x9e63, - 0x9e62,UDCODE,UDCODE,UDCODE,0x90cd,UDCODE,UDCODE,UDCODE,UDCODE, - 0x968d,UDCODE,0x97d1,UDCODE,UDCODE,0x9687,UDCODE,0x89ca,0x8e7d, - UDCODE,UDCODE,0x9867,0x9e65,0x9095,UDCODE,UDCODE,UDCODE,0x9e64, - UDCODE,UDCODE,0x9e5f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ccd, - UDCODE,UDCODE,UDCODE,0x9e6b,0x9e69,UDCODE,0x89cb,0x9e67,0x9e6d, - 0x9e73,UDCODE,0xfae2,UDCODE,UDCODE,UDCODE,UDCODE,0xfae4,0x91c6, - UDCODE,UDCODE,0x95bf,UDCODE,0x9e75,UDCODE,UDCODE,UDCODE,0x9541, - UDCODE,UDCODE,UDCODE,0x9e74,0x9490,0x965e,0x8ab9,UDCODE,0x90f5, - 0x8f5f,UDCODE,UDCODE,UDCODE,0x92d1,UDCODE,0x974d,UDCODE,UDCODE, - 0x9e70,0x9e6f,UDCODE,UDCODE,UDCODE,0x9e71,UDCODE,0x9e6e,UDCODE, - UDCODE,0x9e76,UDCODE,0x9e6c,UDCODE,UDCODE,0x9e6a,UDCODE,0x9e72, - 0x9e68,UDCODE,0x928c,UDCODE,0x96f6,0x8ec4,0x8df2,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8db8,UDCODE,UDCODE,0x968f,0x8a60,0xfae5, - 0x92cc,0x93c8,0x8968,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90f0, - UDCODE,UDCODE,0x90b2,0x8c49,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9e78,UDCODE,UDCODE,0x8d5a,0x8a9c,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9e7a,0x8a94,0x9e81,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9e7d,UDCODE,0x90f1,UDCODE,UDCODE,UDCODE, - 0x8a6a,0x8daa,UDCODE,UDCODE,0x8a69,0x8dcd,UDCODE,UDCODE,0x9e7b, - 0x8c85,0x8c6a,0x938d,0xfae6,UDCODE,0x9e79,UDCODE,0x88c4,UDCODE, - UDCODE,UDCODE,UDCODE,0x9e7c,0x9e7e,UDCODE,0x8bcb,0x8c4b,0xfae3, - 0x8aba,0x8b6a,UDCODE,UDCODE,UDCODE,UDCODE,0x9e82,UDCODE,UDCODE, - 0x8df7,0x9691,UDCODE,0x8e56,UDCODE,UDCODE,UDCODE,0x9e83,UDCODE, - UDCODE,UDCODE,0x954f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e8f,UDCODE,0x89b1, - 0x9e84,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e95,0x9e85, - UDCODE,0x97c0,UDCODE,0x9e8c,UDCODE,0x947e,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9e94,UDCODE,0x9e87,UDCODE,UDCODE, - UDCODE,0x88b2,0x9e89,UDCODE,UDCODE,0x8d5b,UDCODE,UDCODE,UDCODE, - 0x9e8b,UDCODE,0x9e8a,UDCODE,0x9e86,0x9e91,UDCODE,0x8fbd,UDCODE, - UDCODE,UDCODE,0x9aeb,0x8ce6,0x979c,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9e88,UDCODE,0x92f2,0x8a42,0x8dab,UDCODE,0x9e80,UDCODE,0x9e90, - 0x8a81,UDCODE,UDCODE,0x9e8e,0x9e92,UDCODE,0x938e,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8afc,UDCODE,0x9eb0,UDCODE, - 0xfa64,0x96c7,0x9e97,0x8afb,UDCODE,0x9e9e,UDCODE,0xfae7,UDCODE, - UDCODE,0x965f,UDCODE,0x9e9f,0x9ea1,UDCODE,0x9ea5,0x9e99,UDCODE, - 0x9249,UDCODE,UDCODE,UDCODE,UDCODE,0x938f,0x9ea9,0x9e9c,UDCODE, - 0x9ea6,UDCODE,UDCODE,UDCODE,0x9ea0,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9058,0x9eaa,UDCODE,UDCODE,0x90b1,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9ea8,0x8abb,0x986f,0x9e96,UDCODE, - UDCODE,0x9ea4,0x88d6,UDCODE,UDCODE,0x9e98,UDCODE,UDCODE,0x96b8, - 0x9e9d,0x9041,0x92c5,0x9e93,UDCODE,UDCODE,0x9ea3,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x909a,0x9ead,0x8a91,0x8c9f,UDCODE, - UDCODE,UDCODE,UDCODE,0x9eaf,0x9e9a,0x9eae,UDCODE,0x9ea7,0x9e9b, - UDCODE,0x9eab,UDCODE,0x9eac,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9ebd,UDCODE,UDCODE,UDCODE,0x93cc,UDCODE,0x9ea2,UDCODE,UDCODE, - 0x9eb9,UDCODE,UDCODE,UDCODE,0x9ebb,UDCODE,0x92d6,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x976b, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9596, - 0x9eb6,0x91c8,UDCODE,UDCODE,UDCODE,0x9ebc,0x915e,UDCODE,0x9eb3, - 0x9ec0,0x9ebf,UDCODE,0x93ed,0x9ebe,0x93e8,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xfae9,UDCODE,0x9ec2,0x9eb5,UDCODE,0x8bc6,0x9eb8, - 0x8f7c,UDCODE,UDCODE,UDCODE,0x9480,0x9eba,0x8bc9,UDCODE,0x9eb2, - 0x9eb4,0x9eb1,UDCODE,UDCODE,0x984f,0x8a79,0x9eb7,UDCODE,UDCODE, - 0x9ec1,0x8a54,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8de5,UDCODE,UDCODE,UDCODE,0x897c,UDCODE,UDCODE,0x9ed2,UDCODE, - UDCODE,0x9850,0x9ed5,UDCODE,UDCODE,0xfaeb,UDCODE,UDCODE,0x9059, - 0x9ed4,UDCODE,UDCODE,UDCODE,0x9ed3,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9ed0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9ec4,UDCODE,UDCODE,0x9ee1,0x9ec3,UDCODE,0x9ed6,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9ece,UDCODE,UDCODE,0x9ec9,0x9ec6, - UDCODE,0x9ec7,UDCODE,0x9ecf,UDCODE,UDCODE,UDCODE,0xeaa0,UDCODE, - UDCODE,0x9ecc,0x8d5c,0x92c6,0x9184,0x9eca,UDCODE,0x9ec5,UDCODE, - UDCODE,0x9ec8,UDCODE,UDCODE,UDCODE,UDCODE,0x976c,0x968a,UDCODE, - UDCODE,UDCODE,0x9ecd,0x9ed7,UDCODE,UDCODE,UDCODE,0xfaec,UDCODE, - UDCODE,UDCODE,UDCODE,0x9edf,0x9ed8,UDCODE,UDCODE,0x9ee5,UDCODE, - 0x9ee3,UDCODE,UDCODE,UDCODE,UDCODE,0x9ede,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9edd,UDCODE,0x92ce,UDCODE,0x9185,UDCODE, - 0x9edb,0x9ed9,UDCODE,UDCODE,0x9ee0,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9ee6,0x94f3,0x9eec,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ee7, - 0x9eea,0x9ee4,UDCODE,UDCODE,0x9294,UDCODE,0x9557,UDCODE,0x9eda, - UDCODE,UDCODE,0x9ee2,0x8fbe,UDCODE,0x96cd,0x9ef6,0x9ee9,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8ca0,0x89a1,0x8a7e,UDCODE,UDCODE, - 0x9ed1,UDCODE,0xfaed,UDCODE,UDCODE,UDCODE,UDCODE,0x8fbf,0x9eee, - UDCODE,0x9ef5,0x8ef7,0x8a92,UDCODE,UDCODE,0x924d,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9eeb,UDCODE,0xfaef,0x9ef0,0x9ef4, - UDCODE,UDCODE,0x8bb4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b6b,0x9ef2,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8b40,UDCODE,0x93c9,0x9ef1,UDCODE, - UDCODE,UDCODE,0x9ef3,UDCODE,UDCODE,UDCODE,UDCODE,0xfaee,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9eed,0xfaf0,UDCODE,UDCODE, - UDCODE,UDCODE,0x9eef,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfaf1, - 0x8a80,0x9268,UDCODE,UDCODE,UDCODE,0x9efa,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ef8,0x8ce7,UDCODE,0x9ef7, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f40,UDCODE,UDCODE, - UDCODE,UDCODE,0x9e77,UDCODE,UDCODE,UDCODE,0x9ef9,UDCODE,0x9efb, - 0x9efc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f4b,UDCODE, - 0x9f47,UDCODE,0x9e8d,UDCODE,UDCODE,UDCODE,UDCODE,0x9f46,UDCODE, - UDCODE,UDCODE,UDCODE,0x9f45,UDCODE,UDCODE,0x9f42,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9ee8,0x9f44,0x9f43,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9f49,UDCODE,0x9845,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9f4c,0x8bf9,UDCODE,UDCODE,0x9f48,0x9f4a,UDCODE,UDCODE, - 0xfaf2,UDCODE,0xfaf3,UDCODE,UDCODE,UDCODE,0x94a5,UDCODE,0x9f4d, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f51,0x9f4e,0x9793, - 0x9f4f,UDCODE,UDCODE,UDCODE,UDCODE,0x9edc,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9f52,UDCODE,UDCODE,UDCODE,0x9f53, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8954,UDCODE,0x9f55, - 0x8c87,0x8e9f,UDCODE,0x8bd3,UDCODE,UDCODE,UDCODE,0x89a2,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x977e,UDCODE,UDCODE,UDCODE,UDCODE,0x9f57,0x9f56,0x9f59,0x8b5c, - UDCODE,UDCODE,0x8bd4,0x8abc,UDCODE,UDCODE,UDCODE,UDCODE,0x9f5c, - UDCODE,UDCODE,UDCODE,0x9f5b,UDCODE,0x9f5d,UDCODE,UDCODE,0x89cc, - UDCODE,0x9256,UDCODE,0x9f5e,UDCODE,UDCODE,0x8abd,0x9f60,UDCODE, - UDCODE,UDCODE,UDCODE,0x9f5f,UDCODE,0x9f61,UDCODE,UDCODE,UDCODE, - 0x9f62,UDCODE,0x9f63,0x8e7e,0x90b3,0x8d9f,UDCODE,0x9590,UDCODE, - UDCODE,0x95e0,0x9863,UDCODE,UDCODE,UDCODE,UDCODE,0x8e95,UDCODE, - UDCODE,UDCODE,0x8dce,0x97f0,UDCODE,UDCODE,UDCODE,0x9f64,0x9f65, - UDCODE,0x8e80,UDCODE,UDCODE,UDCODE,0x9f66,0x9f67,UDCODE,UDCODE, - 0x9f69,0x9f68,UDCODE,0x9677,UDCODE,UDCODE,0x8f7d,0x8eea,0x8e63, - UDCODE,0x9f6a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9f6c,0x9042,UDCODE,0x9f6b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9f6d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f6e,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9f6f,0x9f70,UDCODE,UDCODE,UDCODE,0x9f71, - UDCODE,0x9f73,0x9f72,0x9f74,0x89a3,0x9269,UDCODE,0x9f75,UDCODE, - UDCODE,0x8e45,0x8a6b,0x9f76,UDCODE,UDCODE,0x9361,0x9aca,UDCODE, - UDCODE,UDCODE,UDCODE,0x8b42,0x9f77,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9f78,UDCODE,0x95ea,0x9688,UDCODE,UDCODE,UDCODE,0x93c5,0x9f79, - 0x94e4,UDCODE,0xfaf4,UDCODE,0x94f9,UDCODE,UDCODE,0x96d1,UDCODE, - UDCODE,UDCODE,0x9f7a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f7c,0x9f7b,UDCODE,UDCODE, - 0x9f7e,UDCODE,UDCODE,UDCODE,0x9f7d,0x9f81,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8e81,UDCODE,0x96af,UDCODE,0x9f82,0x9f83, - UDCODE,UDCODE,0x8b43,UDCODE,UDCODE,UDCODE,0x9f84,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f86,0x9f85,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9085,UDCODE,UDCODE,0x9558,0x8969, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x94c3,0xfaf5,0x92f3,0x8f60, - 0x8b81,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x94c4,UDCODE,0x8eac,UDCODE,UDCODE,UDCODE, - UDCODE,0x9f88,UDCODE,0x8abe,UDCODE,UDCODE,0x8998,UDCODE,0xfaf6, - 0x93f0,0x9f87,0x8d5d,0x9272,UDCODE,0x9f89,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9f91,UDCODE,0x9f8a,UDCODE,UDCODE,UDCODE,UDCODE, - 0xfaf8,0x91bf,UDCODE,0x8b82,0x9f92,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8c88,UDCODE,UDCODE,0x8b44,0x9f90,UDCODE,UDCODE, - 0x9f8e,0x9f8b,0x9780,UDCODE,UDCODE,0xfaf7,UDCODE,0x92be,UDCODE, - UDCODE,UDCODE,0x93d7,0x9f8c,UDCODE,UDCODE,0x9f94,UDCODE,0x9f93, - 0x8c42,UDCODE,UDCODE,0x89ab,UDCODE,UDCODE,0x8db9,0x9f8d,0x9f8f, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9676,0x91f2,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9697,UDCODE,UDCODE, - 0x9f9c,UDCODE,UDCODE,0x9f9d,UDCODE,0x89cd,UDCODE,UDCODE,UDCODE, - UDCODE,0x95a6,0x96fb,0x9f9f,0x8ea1,0x8fc0,0x9f98,0x9f9e,0x8988, - UDCODE,0x8bb5,UDCODE,UDCODE,0x9f95,0x9f9a,UDCODE,UDCODE,UDCODE, - 0x90f2,0x9491,UDCODE,0x94e5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9f97,UDCODE,0x9640,UDCODE,0x9f99,UDCODE,0x9fa2,0xfaf9, - 0x9fa0,UDCODE,0x9f9b,UDCODE,UDCODE,UDCODE,0x9641,0x9467,0x8b83, - UDCODE,0x9344,UDCODE,UDCODE,0x928d,UDCODE,0x9fa3,UDCODE,UDCODE, - UDCODE,UDCODE,0x9fa1,0x91d7,0x9f96,UDCODE,0x896a,0xfafa,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x976d,0x9fae,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9fad,UDCODE,UDCODE,UDCODE,UDCODE,0x90f4, - UDCODE,0x9faa,UDCODE,0x978c,UDCODE,UDCODE,0x93b4,0x9fa4,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x92c3,UDCODE,UDCODE,UDCODE,0x896b, - 0x8d5e,0x9fa7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f46, - 0x9fac,UDCODE,0x9fab,0x9fa6,UDCODE,0x9fa9,UDCODE,UDCODE,0x8a88, - UDCODE,0x9fa8,0x9468,UDCODE,UDCODE,0x97ac,UDCODE,UDCODE,0x8ff2, - 0x90f3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9fb4,0x9fb2,UDCODE,0x956c,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9faf,0x9fb1,UDCODE,0x8959,UDCODE,UDCODE, - 0x8d5f,0x9851,UDCODE,0x8a5c,UDCODE,0x9582,0xfafc,UDCODE,UDCODE, - UDCODE,UDCODE,0x9781,UDCODE,UDCODE,0x8a43,0x905a,0x9fb3,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9fb8,UDCODE,0xfafb,0x8fc1,UDCODE,UDCODE,UDCODE,0x974f, - UDCODE,0x9fb5,UDCODE,UDCODE,UDCODE,UDCODE,0x9fb0,UDCODE,0x9fb6, - 0xfb40,UDCODE,UDCODE,0x97dc,UDCODE,0x9393,0x93c0,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xfb41,UDCODE,UDCODE,0x8a55,UDCODE, - UDCODE,0x8974,UDCODE,UDCODE,0x9fbc,UDCODE,UDCODE,0x9fbf,UDCODE, - UDCODE,UDCODE,0x97c1,UDCODE,UDCODE,UDCODE,0x9784,UDCODE,UDCODE, - UDCODE,UDCODE,0x9fc6,0x9fc0,0x9fbd,UDCODE,UDCODE,UDCODE,0x97d2, - 0x9fc3,UDCODE,UDCODE,0xfb42,UDCODE,0x8f69,0x9fc5,UDCODE,UDCODE, - 0x9fca,UDCODE,UDCODE,0x9391,0x9fc8,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9fc2,UDCODE,UDCODE,0x9257,UDCODE,UDCODE,0x9fc9,UDCODE,0x9fbe, - UDCODE,0x9fc4,UDCODE,0x9fcb,0x88fa,0x9fc1,UDCODE,0x9fcc,UDCODE, - UDCODE,0x905b,0xfb44,0x8f7e,UDCODE,0x95a3,UDCODE,0x8dac,0xfb43, - 0x9fb9,0x9fc7,0x9359,0xfb45,0x90b4,UDCODE,0x8a89,0x8dcf,0x8fc2, - 0x9fbb,0x8f61,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8c6b,UDCODE,0x9fba,UDCODE,UDCODE,UDCODE,0x9fd0,0x8f8d,0x8cb8, - UDCODE,0x9fdf,UDCODE,0x9fd9,0x8b94,0x936e,UDCODE,0x9fd4,0x9fdd, - 0x88ad,0x8951,0xfb48,UDCODE,0x89b7,UDCODE,0x9fd6,0x91aa,0x9fcd, - 0x9fcf,0x8d60,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9fe0,0xfb46,0x9fdb,UDCODE,0xfb49,UDCODE,0x9fd3,UDCODE, - UDCODE,UDCODE,UDCODE,0x9fda,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x96a9,UDCODE,UDCODE,0x9fd8,0x9fdc,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8cce,UDCODE,0x8fc3,UDCODE,UDCODE, - 0x9258,0xfb47,UDCODE,UDCODE,0x9fd2,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x974e,UDCODE,UDCODE,UDCODE,0x9fd5,UDCODE, - UDCODE,0x9fce,0x9392,UDCODE,UDCODE,0x9fd1,UDCODE,UDCODE,UDCODE, - 0x9fd7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9870, - 0x8ebc,0x969e,UDCODE,0x9fe1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x94ac,UDCODE,UDCODE,0x9fed,0x8cb9, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f80,UDCODE,0x9fe3,UDCODE, - UDCODE,UDCODE,0x97ad,0x8d61,UDCODE,0x9ff0,UDCODE,UDCODE,0x88ec, - UDCODE,UDCODE,0x9fee,UDCODE,UDCODE,UDCODE,UDCODE,0x9fe2,UDCODE, - UDCODE,UDCODE,UDCODE,0x9fe8,UDCODE,UDCODE,0x9fea,UDCODE,UDCODE, - UDCODE,0x976e,0x9fe5,UDCODE,UDCODE,0x934d,UDCODE,UDCODE,0x9fe7, - UDCODE,0xfb4a,UDCODE,UDCODE,0x9fef,UDCODE,0x9fe9,0x96c5,UDCODE, - UDCODE,UDCODE,0x9fe4,UDCODE,0x8ea0,0x9ffc,UDCODE,UDCODE,UDCODE, - UDCODE,0x8a8a,UDCODE,0x9fe6,0x9feb,0x9fec,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x91ea,0x91d8,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9ff4,UDCODE,UDCODE,0x9ffa,UDCODE,UDCODE,0x9ff8,UDCODE, - 0x9348,UDCODE,UDCODE,0xe042,0x9ff5,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9ff6,0x9fde,0x8b99,0x9559,UDCODE,UDCODE,UDCODE,0x8ebd, - UDCODE,UDCODE,0x8d97,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9852, - UDCODE,0x9ff2,UDCODE,0xe041,0x8989,0x9186,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9499,UDCODE, - 0x8abf,0x97f8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x969f,0x92d0,UDCODE,UDCODE,UDCODE,UDCODE,0x9ff9,0x9ffb,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9151,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe040,0x9ff7,UDCODE,0x9ff1,UDCODE,UDCODE,UDCODE,0x8ac1, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c89,UDCODE,UDCODE,UDCODE, - 0xe04e,UDCODE,UDCODE,0xe049,0x90f6,UDCODE,UDCODE,0x8a83,UDCODE, - UDCODE,UDCODE,UDCODE,0x8f81,UDCODE,0xe052,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe04b,0x92aa,0xe048,0x92d7,UDCODE,UDCODE, - UDCODE,0xe06b,UDCODE,UDCODE,UDCODE,0xe045,UDCODE,0xe044,UDCODE, - 0xe04d,UDCODE,UDCODE,UDCODE,0xe047,0xe046,0xe04c,UDCODE,0x909f, - UDCODE,0xe043,UDCODE,0xfb4b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe04f,UDCODE,UDCODE,0xe050,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8ac0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe055,UDCODE,0xe054,0xe056,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe059,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9362, - UDCODE,0xe053,UDCODE,0xfb4c,UDCODE,UDCODE,UDCODE,0xe057,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c83,0x91f7,0xe051,0x945a, - UDCODE,UDCODE,0xe058,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe05d,0xe05b, - UDCODE,UDCODE,0xe05e,UDCODE,UDCODE,0xe061,UDCODE,UDCODE,UDCODE, - 0xe05a,0x8d8a,0x9447,UDCODE,UDCODE,0x9fb7,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9794,0xe05c,UDCODE,0xe060,0x91f3,UDCODE, - 0xe05f,UDCODE,0xe04a,UDCODE,0xfb4d,0xe889,UDCODE,UDCODE,UDCODE, - 0xe064,UDCODE,UDCODE,UDCODE,0xe068,0xe066,UDCODE,UDCODE,UDCODE, - 0xfb4e,UDCODE,0xfb4f,UDCODE,0xe062,UDCODE,0xe063,UDCODE,UDCODE, - UDCODE,0xe067,UDCODE,0xe065,UDCODE,UDCODE,UDCODE,0x956d,UDCODE, - UDCODE,0xe06d,UDCODE,0xe06a,0xe069,UDCODE,0xe06c,0x93d2,0xe06e, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9295,0x91eb,0xfb50, - UDCODE,UDCODE,UDCODE,0x90a3,UDCODE,UDCODE,UDCODE,0xe06f,UDCODE, - 0xe071,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe070,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ff3, - UDCODE,UDCODE,UDCODE,UDCODE,0xe072,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x93e5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe073,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x89ce,UDCODE,UDCODE,UDCODE,0x9394,0x8a44, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b84,UDCODE, - UDCODE,UDCODE,0x8edc,0x8dd0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xfb51,UDCODE,UDCODE,UDCODE,0x9846,0x9086,UDCODE, - UDCODE,UDCODE,0x898a,UDCODE,UDCODE,UDCODE,0xe075,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe074,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xfb52,0xe078,0x9259,0xe07b,0xe076, - UDCODE,UDCODE,UDCODE,0xe07a,UDCODE,UDCODE,UDCODE,UDCODE,0xe079, - 0x935f,0x88d7,0xfa62,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x97f3,UDCODE,UDCODE, - 0xe07d,UDCODE,UDCODE,UDCODE,0x8947,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe080,UDCODE,UDCODE,UDCODE, - 0xe07e,UDCODE,0xe07c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe077,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9642,UDCODE,UDCODE,UDCODE,0xe082,0xfb54,UDCODE,UDCODE, - UDCODE,UDCODE,0xe081,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfb53, - UDCODE,UDCODE,UDCODE,UDCODE,0x898b,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe084,0x95b0,UDCODE,0xe083,UDCODE,UDCODE,UDCODE,UDCODE,0x96b3, - UDCODE,UDCODE,UDCODE,UDCODE,0x8fc5,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9152,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8fc4, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xfb56,0xfb57,UDCODE,0x97f9,UDCODE,UDCODE,0xe08a,UDCODE,0x90f7, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe086,0xe08b,UDCODE, - UDCODE,0x898c,UDCODE,UDCODE,0xfb55,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe089,UDCODE,0x9481,0xe085,0xe088,0x8fc6,UDCODE,0x94cf, - UDCODE,UDCODE,0xe08c,UDCODE,0x8ecf,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x90f8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe08f, - UDCODE,UDCODE,UDCODE,0xe087,UDCODE,0x8c46,UDCODE,UDCODE,UDCODE, - UDCODE,0xe08d,UDCODE,UDCODE,UDCODE,UDCODE,0x976f,0xe090,UDCODE, - UDCODE,UDCODE,0xeaa4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f6e, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe091, - UDCODE,UDCODE,UDCODE,0xe092,UDCODE,UDCODE,UDCODE,UDCODE,0x944d, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe094,UDCODE, - UDCODE,UDCODE,UDCODE,0xe095,UDCODE,UDCODE,0xfb59,UDCODE,0x9452, - UDCODE,UDCODE,UDCODE,UDCODE,0x9395,0xe097,UDCODE,UDCODE,UDCODE, - UDCODE,0xe099,UDCODE,0x97d3,UDCODE,0xe096,UDCODE,0xe098,0x898d, - UDCODE,0xe093,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9a7a,0xe09a,UDCODE,UDCODE,UDCODE,UDCODE,0x9187,0x8e57,0xe09c, - UDCODE,UDCODE,UDCODE,UDCODE,0xe09b,0x9043,0x99d7,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe09d,UDCODE,UDCODE,UDCODE,0xe09f, - UDCODE,0xe08e,0xe09e,UDCODE,0xfb5a,0xe0a0,0x949a,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe0a1,UDCODE,UDCODE,0xe0a2,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe0a3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe0a4,UDCODE,0x92dc,UDCODE,0xe0a6, - 0xe0a5,UDCODE,UDCODE,0xe0a7,UDCODE,0xe0a8,UDCODE,UDCODE,0x8edd, - 0x9583,UDCODE,UDCODE,UDCODE,0x96ea,0xe0a9,0xe0aa,0x9175,0x8ea2, - 0xe0ab,0xe0ac,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0ad,0x95d0, - 0x94c5,UDCODE,UDCODE,0xe0ae,0x9476,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x92ab,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0af,0x89e5, - UDCODE,0x8b8d,UDCODE,0x96c4,UDCODE,0x96b4,UDCODE,0x89b2,0x9853, - UDCODE,UDCODE,UDCODE,UDCODE,0x9671,UDCODE,0x95a8,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90b5,UDCODE,0xe0b0, - UDCODE,UDCODE,UDCODE,UDCODE,0x93c1,UDCODE,UDCODE,UDCODE,0x8ca1, - 0xe0b1,UDCODE,0x8dd2,0xe0b3,0xe0b2,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe0b4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe0b5,UDCODE,UDCODE,UDCODE,0xe0b6,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b5d,UDCODE, - 0xe0b7,UDCODE,UDCODE,UDCODE,UDCODE,0xe0b8,UDCODE,UDCODE,UDCODE, - UDCODE,0x8ca2,UDCODE,UDCODE,0x94c6,UDCODE,0xfb5b,0xe0ba,UDCODE, - UDCODE,UDCODE,0x8ff3,UDCODE,UDCODE,0xe0b9,UDCODE,UDCODE,UDCODE, - UDCODE,0xfb5c,UDCODE,UDCODE,UDCODE,0x8bb6,0xe0bb,0xe0bd,UDCODE, - 0xe0bc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0be, - UDCODE,0x8ccf,UDCODE,0xe0bf,UDCODE,UDCODE,UDCODE,UDCODE,0x8be7, - UDCODE,0x915f,UDCODE,0x8d9d,UDCODE,UDCODE,UDCODE,UDCODE,0xe0c1, - 0xe0c2,0xe0c0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8eeb, - UDCODE,UDCODE,0x93c6,0x8bb7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe0c4,0x924b,0xe0c3,UDCODE,UDCODE, - 0x9854,0x9482,0xe0c7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0c9,0xe0c6,UDCODE,UDCODE, - UDCODE,0x96d2,0xe0c8,0xe0ca,UDCODE,0x97c2,UDCODE,UDCODE,UDCODE, - UDCODE,0xfb5d,0xe0ce,UDCODE,UDCODE,UDCODE,0xe0cd,0x9296,0x944c, - UDCODE,UDCODE,0x8ca3,0xe0cc,UDCODE,UDCODE,UDCODE,UDCODE,0xe0cb, - UDCODE,0x9750,0x9751,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe0cf,0x898e,UDCODE,UDCODE,UDCODE,UDCODE,0x8d96,0x8e82,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0d0,0xe0d1, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0d3,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x8f62,UDCODE,UDCODE,UDCODE,UDCODE,0xe0d5,UDCODE,0xe0d4, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0d6,UDCODE,0x8a6c,UDCODE, - UDCODE,0xe0d8,UDCODE,0xfb5f,0xe0d7,UDCODE,0xe0da,0xe0d9,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8cba,UDCODE, - UDCODE,0x97a6,UDCODE,0x8bca,UDCODE,0x89a4,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8be8,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8adf, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x97e6, - 0xe0dc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0de, - UDCODE,0xfb60,UDCODE,UDCODE,0xe0df,UDCODE,0x89cf,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe0db,0xfb61,0x8e58,UDCODE,UDCODE,0x92bf, - 0xe0dd,UDCODE,UDCODE,UDCODE,0xfb64,UDCODE,UDCODE,UDCODE,0xfb62, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0e2,UDCODE, - 0x8eec,UDCODE,UDCODE,0xfb63,UDCODE,0xe0e0,UDCODE,UDCODE,UDCODE, - UDCODE,0x8c5d,UDCODE,UDCODE,0x94c7,0xe0e1,UDCODE,UDCODE,0xe0fc, - UDCODE,UDCODE,UDCODE,0xfb66,UDCODE,UDCODE,0xe0e7,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8cbb,0x8b85,UDCODE,0xe0e4,0x979d,0xfb65, - UDCODE,0x97ae,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x91f4, - UDCODE,UDCODE,0xe0e6,0xfb67,UDCODE,UDCODE,0xfb69,0xfb68,UDCODE, - UDCODE,UDCODE,0xfb6a,UDCODE,UDCODE,UDCODE,0xe0e8,0x97d4,0x8bd5, - 0x94fa,0x9469,UDCODE,UDCODE,UDCODE,0xe0e9,UDCODE,UDCODE,UDCODE, - UDCODE,0xe0eb,UDCODE,0xe0ee,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0ea,UDCODE,UDCODE,UDCODE, - 0xe0ed,0x8ce8,0x896c,0xe0ef,UDCODE,0x9090,0xe0ec,0x97da,UDCODE, - 0xfb6b,0xe0f2,0xeaa2,UDCODE,UDCODE,UDCODE,UDCODE,0xe0f0,0xe0f3, - UDCODE,UDCODE,UDCODE,UDCODE,0xe0e5,0xe0f1,UDCODE,UDCODE,0x8dba, - UDCODE,UDCODE,0xe0f4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe0f5,UDCODE,UDCODE,UDCODE,UDCODE,0x979e,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xfb6c,UDCODE,0xe0f6,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0f7,0xfb6d,UDCODE, - UDCODE,0xe0e3,UDCODE,UDCODE,UDCODE,UDCODE,0xe0f8,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ac2,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x8ea3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0f9,UDCODE,UDCODE,UDCODE, - UDCODE,0xe0fa,UDCODE,UDCODE,UDCODE,UDCODE,0xe0fb,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x895a,UDCODE,UDCODE,UDCODE, - 0xe140,UDCODE,0x955a,0xe141,UDCODE,UDCODE,0x8aa2,0xe142,UDCODE, - 0xe143,UDCODE,UDCODE,UDCODE,UDCODE,0xe144,UDCODE,0xe146,0xe147, - 0xe145,UDCODE,UDCODE,UDCODE,0x9572,0xe149,0xe148,0xfb6e,UDCODE, - 0xe14b,0xe14a,0xe14c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe14d,0xe14f,0xe14e,UDCODE,UDCODE,0x8d99,UDCODE,0xe151,UDCODE, - 0xe150,UDCODE,UDCODE,0x8ac3,UDCODE,0x9072,UDCODE,0x935b,UDCODE, - 0xe152,0x90b6,UDCODE,UDCODE,UDCODE,0x8e59,UDCODE,0x8999,0xe153, - UDCODE,0x9770,UDCODE,UDCODE,0x95e1,0xe154,UDCODE,UDCODE,0xfaa8, - 0x9363,0x9752,0x8d62,0x905c,UDCODE,UDCODE,UDCODE,0x926a,0x99b2, - UDCODE,0x92ac,0x89e6,0xe155,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe156,UDCODE,0xe15b,UDCODE,UDCODE,0xe159,0xe158, - 0x9dc0,0x8a45,0xe157,UDCODE,0x88d8,UDCODE,0x94a8,UDCODE,UDCODE, - 0x94c8,UDCODE,UDCODE,UDCODE,UDCODE,0x97af,0xe15c,0xe15a,0x927b, - 0x90a4,UDCODE,UDCODE,0x94a9,UDCODE,0x954c,UDCODE,0xe15e,0x97aa, - 0x8c6c,0xe15f,UDCODE,0xe15d,0x94d4,0xe160,UDCODE,0xe161,UDCODE, - 0xfb6f,0x88d9,UDCODE,UDCODE,0x8ff4,0xe166,UDCODE,0xe163,0x93eb, - 0xe162,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b45,UDCODE, - UDCODE,0xe169,UDCODE,UDCODE,UDCODE,0xe164,0xe165,UDCODE,0xe168, - 0xe167,0x9544,UDCODE,UDCODE,0x9161,0x9160,UDCODE,0x8b5e,UDCODE, - UDCODE,0xe16a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe16b,UDCODE, - UDCODE,0xe16c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe16e,UDCODE, - 0xe16d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8975,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe176,0x94e6,0xe170,UDCODE,0xe172,UDCODE, - UDCODE,0xe174,0x905d,UDCODE,UDCODE,0xe175,0xe173,0x8ebe,UDCODE, - UDCODE,UDCODE,0xe16f,0xe171,UDCODE,0x9561,UDCODE,0x8fc7,UDCODE, - UDCODE,0xe178,UDCODE,UDCODE,0xe177,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe179,UDCODE,0x8ea4,0x8dad,UDCODE,UDCODE,0x9397,0xe17a,UDCODE, - 0x92c9,UDCODE,UDCODE,0xe17c,UDCODE,UDCODE,UDCODE,0x979f,0xe17b, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9189,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe182,UDCODE,0xe184,0xe185,0x9273,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe183,UDCODE,0xe180,UDCODE,0xe17d, - 0xe17e,0xe181,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe188,UDCODE,0xe186,UDCODE,0xe187,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe189,0xe18b,0xe18c,0xe18d,UDCODE, - 0xe18e,UDCODE,UDCODE,0xe18a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe190,UDCODE,UDCODE,UDCODE,0xe18f,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe191,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x97c3,UDCODE,UDCODE,UDCODE,0xe194,0xe192, - 0xe193,UDCODE,UDCODE,UDCODE,0x8ae0,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x96fc,UDCODE,UDCODE,UDCODE,0x95c8,UDCODE,0xe196,UDCODE, - UDCODE,UDCODE,0xe195,UDCODE,UDCODE,UDCODE,UDCODE,0xe197,0xe198, - UDCODE,UDCODE,UDCODE,UDCODE,0xe19c,0xe199,0xe19a,0xe19b,UDCODE, - 0xe19d,UDCODE,UDCODE,UDCODE,0xe19e,UDCODE,0xe19f,UDCODE,UDCODE, - UDCODE,0xe1a0,UDCODE,0xe1a1,UDCODE,0x94ad,0x936f,0xe1a2,0x9492, - 0x9553,UDCODE,0xe1a3,UDCODE,0xfb70,0xe1a4,0x9349,UDCODE,0x8a46, - 0x8d63,0xe1a5,UDCODE,UDCODE,0xe1a6,UDCODE,UDCODE,0xe1a7,UDCODE, - 0x8e48,UDCODE,UDCODE,0xe1a9,UDCODE,UDCODE,0xe1a8,UDCODE,UDCODE, - 0xe1aa,0xe1ab,0xfb73,0xfb71,UDCODE,0xfb72,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xfb74,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x94e7,UDCODE,0xe1ac,UDCODE,UDCODE,UDCODE, - 0xe1ad,UDCODE,UDCODE,0xea89,0xe1ae,0xe1af,0xe1b0,UDCODE,UDCODE, - UDCODE,UDCODE,0x8e4d,UDCODE,UDCODE,0xe1b1,0x9475,UDCODE,UDCODE, - 0x967e,UDCODE,0x896d,UDCODE,0x8976,UDCODE,UDCODE,0xe1b2,UDCODE, - UDCODE,UDCODE,UDCODE,0xe1b4,UDCODE,UDCODE,UDCODE,0xe1b3,0x9390, - UDCODE,UDCODE,UDCODE,0x90b7,0x9f58,UDCODE,0xe1b5,0x96bf,UDCODE, - 0xe1b6,UDCODE,0x8ac4,0x94d5,0xe1b7,UDCODE,0xe1b8,UDCODE,UDCODE, - 0xe1b9,UDCODE,UDCODE,UDCODE,0x96da,UDCODE,UDCODE,UDCODE,0x96d3, - UDCODE,0x92bc,UDCODE,UDCODE,UDCODE,0x918a,UDCODE,UDCODE,0xe1bb, - UDCODE,UDCODE,0x8f82,0x8fc8,UDCODE,UDCODE,0xe1be,UDCODE,UDCODE, - 0xe1bd,0xe1bc,0x94fb,UDCODE,0x8ac5,0x8ca7,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe1c4,UDCODE,UDCODE,0xe1c1,0x905e,0x96b0,UDCODE, - UDCODE,UDCODE,0xe1c0,0xe1c2,0xe1c3,UDCODE,UDCODE,0xe1bf,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe1c5,0xe1c6,UDCODE,0x92ad,UDCODE,0x8ae1, - UDCODE,UDCODE,UDCODE,0x9285,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xfb76,0xe1c7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe1c8,0xe1cb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9087,UDCODE,0x93c2,UDCODE,0xe1cc,0x9672,UDCODE,0xe1c9,UDCODE, - UDCODE,0xe1ca,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe1cf,UDCODE,UDCODE, - UDCODE,UDCODE,0xe1ce,0xe1cd,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe1d1,UDCODE,UDCODE, - 0xe1d0,UDCODE,UDCODE,0xe1d2,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe1d4,UDCODE, - 0xe1d3,UDCODE,UDCODE,UDCODE,UDCODE,0x95cb,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8f75,0x97c4,UDCODE,UDCODE,0xe1d5,UDCODE, - UDCODE,0x93b5,UDCODE,UDCODE,0xe1d6,UDCODE,UDCODE,0xe1d7,UDCODE, - 0xe1db,0xe1d9,0xe1da,UDCODE,0xe1d8,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe1dc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe1dd,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe1de,UDCODE,UDCODE,0xe1df,0x96b5,0xe1e0,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x96ee,0xe1e1,UDCODE,0x926d,UDCODE,0x948a, - UDCODE,0x8be9,UDCODE,UDCODE,UDCODE,0x925a,0xe1e2,0x8bb8,UDCODE, - UDCODE,UDCODE,0x90ce,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe1e3,0x8dbb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe1e4,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe1e5,UDCODE,0x8ca4,0x8dd3,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe1e7,0xfb78,UDCODE, - UDCODE,UDCODE,0x9375,0x8dd4,0x8b6d,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9643,UDCODE,0x946a, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9376,UDCODE,UDCODE,UDCODE, - UDCODE,0x8d7b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe1e9,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfb79,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8fc9,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xfb7a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x97b0,0x8d64,UDCODE,UDCODE,0x8ca5,UDCODE,UDCODE,0x94a1,UDCODE, - 0xe1eb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfb7b,UDCODE,0xe1ed, - UDCODE,UDCODE,UDCODE,UDCODE,0x8ce9,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe1ec,0x92f4,UDCODE,UDCODE,UDCODE,UDCODE,0xe1ef,0x8a56,0xe1ea, - UDCODE,UDCODE,0x94e8,UDCODE,0x894f,UDCODE,0x8dea,UDCODE,0x9871, - UDCODE,UDCODE,0xe1ee,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe1f0,UDCODE,UDCODE,UDCODE,0x95c9,UDCODE,0x90d7, - 0xe1f2,UDCODE,UDCODE,UDCODE,UDCODE,0xe1f3,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe1f1,UDCODE,UDCODE,UDCODE,UDCODE,0x8a6d,UDCODE, - 0xe1f9,UDCODE,0xe1f8,UDCODE,UDCODE,0x8ea5,UDCODE,UDCODE,UDCODE, - 0xe1fa,0xe1f5,UDCODE,UDCODE,UDCODE,0xe1fb,0xe1f6,UDCODE,UDCODE, - UDCODE,UDCODE,0x94d6,0xe1f4,UDCODE,UDCODE,0xe1f7,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe241,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe240,0x9681, - UDCODE,UDCODE,UDCODE,0xe1fc,UDCODE,UDCODE,0x88e9,UDCODE,UDCODE, - UDCODE,UDCODE,0xe243,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe242,0x8fca,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe244,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9162,UDCODE, - UDCODE,0xe246,0xe245,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe247,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe1e6,UDCODE,UDCODE,UDCODE,0xe1e8, - 0xe249,0xe248,UDCODE,UDCODE,UDCODE,0xfb7c,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ea6,UDCODE,0x97e7, - UDCODE,0x8ed0,UDCODE,0xe24a,0x8c56,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x8b5f,0x8b46,0x8e83,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9753,UDCODE,UDCODE,0xe250,UDCODE,0xe24f,0x9163,0xe24c, - UDCODE,UDCODE,0xe24e,UDCODE,UDCODE,0x8f6a,0x905f,0xe24d,0xe24b, - UDCODE,0x9449,UDCODE,UDCODE,0x8fcb,UDCODE,UDCODE,0x955b,UDCODE, - UDCODE,UDCODE,UDCODE,0x8dd5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9398,UDCODE,UDCODE,0xe251,UDCODE, - UDCODE,UDCODE,UDCODE,0xe252,0xe268,0x8bd6,UDCODE,UDCODE,0x985c, - 0x9154,UDCODE,UDCODE,UDCODE,UDCODE,0xe253,UDCODE,UDCODE,0x89d0, - 0x92f5,0x959f,UDCODE,UDCODE,UDCODE,UDCODE,0xfb81,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xfb83,UDCODE,0xe254,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b9a,0xe255,UDCODE, - UDCODE,0xe257,UDCODE,UDCODE,UDCODE,0xe258,UDCODE,0x9448,UDCODE, - UDCODE,0xe259,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe25a,0xe25b, - UDCODE,UDCODE,0x8bd7,0x89d1,0x93c3,0x8f47,0x8e84,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe25c,UDCODE,0x8f48,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x89c8,0x9562,UDCODE,UDCODE,0xe25d, - UDCODE,UDCODE,0x94e9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9164,UDCODE,0xe260,UDCODE,0xe261,0x9489,UDCODE,0x9060,0xe25e, - UDCODE,0x9281,UDCODE,UDCODE,0xe25f,UDCODE,UDCODE,UDCODE,0x8fcc, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x88da,0x8b48,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe262,UDCODE,UDCODE,0x92f6,UDCODE,0xe263,0x90c5,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x96ab,UDCODE,UDCODE,0x9542,0xe264, - 0xe265,0x9274,UDCODE,0x97c5,UDCODE,UDCODE,0xe267,0xe266,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8eed,UDCODE,UDCODE,0xe269,0x88ee,UDCODE, - UDCODE,UDCODE,UDCODE,0xe26c,UDCODE,UDCODE,UDCODE,0xe26a,0x89d2, - 0x8c6d,0xe26b,0x8d65,0x8d92,UDCODE,0x95e4,0xe26d,UDCODE,UDCODE, - 0x9673,UDCODE,UDCODE,0xe26f,UDCODE,UDCODE,UDCODE,0x90cf,0x896e, - 0x89b8,0x88aa,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe26e, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe270,0xe271,0x8ff5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe272, - UDCODE,0x8a6e,UDCODE,UDCODE,UDCODE,UDCODE,0xe274,UDCODE,UDCODE, - UDCODE,0x8c8a,UDCODE,0x8b86,UDCODE,UDCODE,0xe275,0x8bf3,UDCODE, - UDCODE,0xe276,UDCODE,0x90fa,UDCODE,0x93cb,UDCODE,0x90de,0x8df3, - UDCODE,UDCODE,UDCODE,0xe277,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9282,0x918b,UDCODE,0xe279,0xe27b, - 0xe278,0xe27a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c41, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe27c,0x8c45,UDCODE,UDCODE,UDCODE,0x8b87,0x9771,0xe27e,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe280,UDCODE,UDCODE,UDCODE,0x894d, - UDCODE,UDCODE,UDCODE,UDCODE,0xe283,UDCODE,UDCODE,UDCODE,0x8a96, - 0xe282,0xe281,UDCODE,0xe285,0xe27d,UDCODE,0xe286,0x97a7,UDCODE, - 0xe287,UDCODE,0xe288,UDCODE,0xfb84,0x9af2,0xe28a,UDCODE,0xe289, - UDCODE,UDCODE,UDCODE,0xe28b,0xe28c,UDCODE,0x97b3,0xe28d,UDCODE, - 0xe8ed,0x8fcd,0xe28e,0xe28f,0x8f76,UDCODE,0x93b6,0xe290,0xfb85, - UDCODE,UDCODE,0x9247,0xfb87,UDCODE,0xe291,UDCODE,0x925b,0xe292, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ba3,UDCODE,0x995e,0x927c, - 0x8eb1,UDCODE,UDCODE,UDCODE,UDCODE,0x8ac6,0xe293,UDCODE,0xe2a0, - UDCODE,0xe296,UDCODE,0x8b88,UDCODE,0xe295,0xe2a2,UDCODE,UDCODE, - UDCODE,0xe294,UDCODE,0x8fce,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe298,0xe299,UDCODE,0x934a,UDCODE,UDCODE,0xe29a,UDCODE, - 0x8a7d,UDCODE,UDCODE,UDCODE,UDCODE,0x9079,0x9584,UDCODE,0xe29c, - UDCODE,UDCODE,UDCODE,0x91e6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe297,UDCODE,0xe29b,0xe29d,UDCODE,UDCODE,0x8df9,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe2a4,0x954d,UDCODE,0x94a4,0x9399,UDCODE,0x8bd8,0xe2a3, - 0xe2a1,UDCODE,0x94b3,0xe29e,0x927d,0x939b,UDCODE,0x939a,UDCODE, - 0x8df4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2b6,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2a6,UDCODE,0xe2a8, - UDCODE,UDCODE,UDCODE,UDCODE,0xe2ab,UDCODE,0xe2ac,UDCODE,0xe2a9, - 0xe2aa,UDCODE,UDCODE,0xe2a7,0xe2a5,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe29f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x95cd,0x89d3,UDCODE,UDCODE,UDCODE,0xe2b3, - UDCODE,0xe2b0,UDCODE,0xe2b5,UDCODE,UDCODE,0xe2b4,UDCODE,0x9493, - 0x96a5,UDCODE,0x8e5a,0xe2ae,0xe2b7,0xe2b2,UDCODE,0xe2b1,0xe2ad, - 0xfb88,0xe2af,UDCODE,0x8ac7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x925c,UDCODE,UDCODE,0x90fb,UDCODE,UDCODE, - UDCODE,0x94a0,UDCODE,UDCODE,0xe2bc,UDCODE,UDCODE,UDCODE,0x94a2, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90df,0xe2b9, - UDCODE,UDCODE,0x94cd,UDCODE,0xe2bd,0x95d1,UDCODE,0x927a,UDCODE, - 0xe2b8,0xe2ba,UDCODE,UDCODE,0xe2bb,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe2be,UDCODE,UDCODE,0x8ec2,UDCODE,UDCODE,UDCODE,0x93c4,0xe2c3, - 0xe2c2,UDCODE,UDCODE,0xe2bf,UDCODE,UDCODE,UDCODE,0x9855,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe2c8,UDCODE,UDCODE,0xe2cc,0xe2c9, - 0xe2c5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2c6,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe2cb,UDCODE,UDCODE,UDCODE,0xe2c0, - 0x99d3,0xe2c7,0xe2c1,UDCODE,UDCODE,0xe2ca,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe2d0,UDCODE,0x8ac8,UDCODE,0xe2cd, - UDCODE,UDCODE,UDCODE,0xe2ce,UDCODE,UDCODE,0xe2cf,0xe2d2,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe2d1,0x94f4,UDCODE,UDCODE,UDCODE,UDCODE,0xe2d3,0x97fa, - 0x95eb,0xe2d8,UDCODE,UDCODE,0xe2d5,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe2d4,0x90d0,UDCODE,0xe2d7,0xe2d9, - UDCODE,UDCODE,UDCODE,0xe2d6,UDCODE,0xe2dd,UDCODE,0xe2da,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2db,0xe2c4,UDCODE,UDCODE, - UDCODE,0xe2dc,0xe2de,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe2df,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95c4,UDCODE, - 0xe2e0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x96e0,UDCODE,UDCODE,0x8bcc,0x8c48,0xe2e1,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x95b2,UDCODE,0x9088,UDCODE,0x96ae,UDCODE,UDCODE, - 0xe2e2,UDCODE,0x97b1,UDCODE,UDCODE,0x9494,UDCODE,0x9165,0x9453, - UDCODE,UDCODE,0x8f6c,UDCODE,UDCODE,UDCODE,0x88be,UDCODE,0xe2e7, - 0xe2e5,UDCODE,0xe2e3,0x8a9f,UDCODE,0x8fcf,0xe2e8,UDCODE,UDCODE, - 0xe2e6,UDCODE,0xe2e4,0xe2ec,UDCODE,UDCODE,0xe2eb,0xe2ea,0xe2e9, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2ed,UDCODE,UDCODE,UDCODE, - 0xe2ee,0x90b8,UDCODE,0xe2ef,UDCODE,0xe2f1,UDCODE,UDCODE,0xe2f0, - UDCODE,UDCODE,UDCODE,UDCODE,0x8cd0,UDCODE,UDCODE,UDCODE,0x9157, - UDCODE,UDCODE,UDCODE,0xe2f3,UDCODE,UDCODE,UDCODE,0x939c,UDCODE, - 0xe2f2,UDCODE,UDCODE,UDCODE,0xe2f4,UDCODE,0x95b3,0x918c,0x8d66, - UDCODE,0xe2f5,UDCODE,UDCODE,UDCODE,UDCODE,0x97c6,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2f7,UDCODE,UDCODE,0xe2f8, - UDCODE,0xe2f9,UDCODE,0xe2fa,UDCODE,0x8e85,UDCODE,0xe2fb,0x8c6e, - UDCODE,UDCODE,0x8b8a,0x8b49,UDCODE,0xe340,UDCODE,0x96f1,0x8d67, - 0xe2fc,UDCODE,UDCODE,UDCODE,0xe343,0x96e4,UDCODE,0x945b,UDCODE, - UDCODE,0x9552,UDCODE,UDCODE,UDCODE,0x8f83,0xe342,UDCODE,0x8ed1, - 0x8d68,0x8e86,0x8b89,0x95b4,0xe341,UDCODE,UDCODE,UDCODE,0x9166, - 0x9661,0x8df5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x8e87,0x92db,UDCODE,0xe346,0x97dd,0x8dd7,UDCODE,0xe347, - 0x9061,UDCODE,0xe349,UDCODE,UDCODE,UDCODE,0x8fd0,0x8dae,UDCODE, - UDCODE,UDCODE,UDCODE,0xe348,UDCODE,UDCODE,0x8f49,0x8cbc,0x9167, - 0xe344,0xe34a,UDCODE,0xfb8a,UDCODE,UDCODE,0xe345,0x8c6f,UDCODE, - 0xe34d,0xe351,0x8c8b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe34c, - UDCODE,UDCODE,UDCODE,UDCODE,0xe355,0xfb8b,UDCODE,0x8d69,UDCODE, - UDCODE,0x978d,0x88ba,0xe352,UDCODE,UDCODE,0x8b8b,UDCODE,0xe34f, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe350,UDCODE,UDCODE,0x939d, - 0xe34e,0xe34b,UDCODE,0x8a47,0x90e2,UDCODE,UDCODE,0x8ca6,UDCODE, - UDCODE,UDCODE,0xe357,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe354,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe356,UDCODE,UDCODE,UDCODE,0xe353,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8c70,0x91b1,0xe358,0x918e,UDCODE,UDCODE, - 0xe365,0xfb8d,UDCODE,0xe361,0xe35b,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe35f,0x8ef8,0x88db,0xe35a,0xe362,0xe366, - 0x8d6a,0x96d4,UDCODE,0x92d4,0xe35c,UDCODE,0xfb8c,0xe364,UDCODE, - 0xe359,0x925d,UDCODE,0xe35e,0x88bb,0x96c8,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe35d,UDCODE,UDCODE,0x8bd9,0x94ea, - UDCODE,UDCODE,UDCODE,0x918d,UDCODE,0x97ce,0x8f8f,UDCODE,UDCODE, - 0xe38e,0xfb8e,UDCODE,0xe367,UDCODE,0x90fc,UDCODE,0xe363,0xe368, - 0xe36a,UDCODE,0x92f7,0xe36d,UDCODE,UDCODE,0xe369,UDCODE,UDCODE, - UDCODE,0x95d2,0x8ac9,UDCODE,UDCODE,0x96c9,UDCODE,UDCODE,0x88dc, - UDCODE,UDCODE,0xe36c,UDCODE,0x97fb,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe36b,0x898f,UDCODE,UDCODE,0x93ea,0xe36e,UDCODE, - UDCODE,UDCODE,0xe375,0xe36f,0xe376,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe372,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x949b,UDCODE,UDCODE,0x8ec8,0xe374,UDCODE,0xe371, - 0xe377,0xe370,UDCODE,UDCODE,0x8f63,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9644,UDCODE,UDCODE,0x8f6b,UDCODE,UDCODE,0xe373,0xe380,UDCODE, - UDCODE,0xe37b,UDCODE,0xe37e,UDCODE,0xe37c,0xe381,0xe37a,UDCODE, - 0xe360,0x90d1,UDCODE,UDCODE,0x94c9,UDCODE,0xe37d,UDCODE,UDCODE, - 0xe378,UDCODE,UDCODE,UDCODE,0x9140,0x8c71,UDCODE,0x8f4a,UDCODE, - UDCODE,UDCODE,UDCODE,0xfb8f,UDCODE,0x9044,0x9155,0xe384,UDCODE, - UDCODE,0xe386,0xe387,UDCODE,UDCODE,0xe383,0xe385,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe379,0xe382,UDCODE,0xe38a, - 0xe389,UDCODE,UDCODE,0x969a,UDCODE,UDCODE,0x8c4a,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe388,UDCODE,0xe38c, - 0xe38b,0xe38f,UDCODE,0xe391,UDCODE,UDCODE,0x8e5b,0xe38d,UDCODE, - UDCODE,UDCODE,UDCODE,0xe392,0xe393,0xfa5c,UDCODE,0xe394,UDCODE, - 0xe39a,0x935a,0xe396,UDCODE,0xe395,0xe397,0xe398,UDCODE,0xe399, - UDCODE,UDCODE,UDCODE,UDCODE,0xe39b,0xe39c,0x8aca,UDCODE,0xe39d, - UDCODE,0xe39e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe39f,UDCODE,0xfb90,UDCODE,UDCODE,UDCODE, - UDCODE,0xe3a0,0xe3a1,0xe3a2,UDCODE,0xe3a3,0xe3a4,UDCODE,UDCODE, - 0xe3a6,0xe3a5,UDCODE,UDCODE,0xe3a7,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe3a8,0xe3a9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe3ac,0xe3aa,0xe3ab,0x8ddf,0x8c72,UDCODE,UDCODE,0x9275, - UDCODE,0x94b1,UDCODE,0x8f90,UDCODE,UDCODE,0x946c,UDCODE,0x94eb, - 0xe3ad,0x9ceb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe3ae,0xe3b0,UDCODE,0x9785,0xe3af,0xe3b2,0xe3b1,UDCODE, - 0x9772,UDCODE,0xe3b3,UDCODE,0x94fc,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe3b4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe3b7,UDCODE, - UDCODE,0xe3b6,0xe3b5,UDCODE,UDCODE,0xfb91,UDCODE,0xe3b8,0x8c51, - UDCODE,UDCODE,UDCODE,0x9141,0x8b60,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe3bc,0xe3b9,UDCODE,UDCODE,0xe3ba,UDCODE,UDCODE,UDCODE,0xe3bd, - UDCODE,0xe3be,0xe3bb,UDCODE,UDCODE,UDCODE,0x8948,UDCODE,UDCODE, - UDCODE,0x89a5,UDCODE,UDCODE,UDCODE,0xe3c0,0xe3c1,UDCODE,UDCODE, - UDCODE,0xe3c2,UDCODE,0x9782,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8f4b,UDCODE,0xe3c4,0xe3c3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9089,0xe3c5,UDCODE,UDCODE, - UDCODE,UDCODE,0xe3c6,UDCODE,UDCODE,0xe3c7,UDCODE,0x8ae3,UDCODE, - UDCODE,UDCODE,UDCODE,0x8acb,UDCODE,UDCODE,0xe3c8,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe3c9,UDCODE,0x967c,0x9783,0x9773,0x9856, - UDCODE,0x8d6c,0xe3cc,0x8ed2,0xe3cb,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe3cd,0x8ea7,UDCODE,UDCODE,UDCODE,0x91cf,UDCODE,0xe3ce,UDCODE, - UDCODE,0x8d6b,UDCODE,0x96d5,0xe3cf,0xe3d0,UDCODE,UDCODE,0xe3d1, - UDCODE,UDCODE,UDCODE,UDCODE,0xe3d2,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe3d3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8ea8,UDCODE,UDCODE,0x96eb,UDCODE, - UDCODE,UDCODE,UDCODE,0xe3d5,UDCODE,0x925e,UDCODE,0xe3d4,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe3d7,UDCODE,UDCODE,UDCODE, - 0xe3d6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe3d8, - UDCODE,UDCODE,UDCODE,0x90b9,UDCODE,0xe3d9,UDCODE,0xe3da,UDCODE, - UDCODE,UDCODE,0x95b7,0xe3db,UDCODE,0x918f,0xe3dc,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe3dd,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x97fc,0xe3e0,UDCODE,0xe3df,0xe3de,0x92ae,UDCODE,0xe3e1, - 0x9045,UDCODE,0xe3e2,UDCODE,UDCODE,UDCODE,0xe3e3,0x9857,0xe3e4, - UDCODE,UDCODE,UDCODE,UDCODE,0xe3e5,0xe3e7,0xe3e6,0x94a3,UDCODE, - 0x93f7,UDCODE,0x985d,0x94a7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe3e9,UDCODE,UDCODE,0x8fd1,UDCODE,0x9549,UDCODE,0xe3ea, - 0xe3e8,UDCODE,0x8acc,UDCODE,UDCODE,UDCODE,0x8cd2,0x8e88,UDCODE, - UDCODE,0x94ec,UDCODE,UDCODE,UDCODE,0x8ca8,0x9662,UDCODE,0xe3ed, - 0xe3eb,UDCODE,0x8d6d,UDCODE,0x8d6e,0x88e7,UDCODE,0x8de6,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9478,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x88dd,0xe3f2,UDCODE,0x925f,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9477,UDCODE,0x91d9,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe3f4,UDCODE,UDCODE,0xe3f0, - 0xe3f3,0xe3ee,UDCODE,0xe3f1,0x9645,UDCODE,UDCODE,0x8cd3,UDCODE, - UDCODE,0x88fb,0xe3ef,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe3f6,UDCODE,0xe3f7,UDCODE,UDCODE,0x93b7, - UDCODE,UDCODE,UDCODE,0x8bb9,UDCODE,UDCODE,UDCODE,0xe445,0x945c, - 0x8e89,UDCODE,UDCODE,0x8bba,0x90c6,0x9865,0x96ac,0xe3f5,0x90d2, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b72,0xe3f8,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe3fa,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe3f9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe3fb,UDCODE,0x9245,UDCODE,0x945d,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x92af,UDCODE,UDCODE,UDCODE,UDCODE,0xe442,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe441,UDCODE,UDCODE,UDCODE, - UDCODE,0xe3fc,UDCODE,UDCODE,0x9074,UDCODE,0x9585,0xe444,UDCODE, - 0xe443,0x8d6f,0x9872,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe454,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe448,0xe449,UDCODE,UDCODE,UDCODE,UDCODE,0x8eee,UDCODE,UDCODE, - 0xe447,UDCODE,0x8d98,0xe446,UDCODE,UDCODE,0xe44a,UDCODE,UDCODE, - UDCODE,0x92b0,0x95a0,0x9142,UDCODE,UDCODE,UDCODE,UDCODE,0x91da, - 0xe44e,UDCODE,0xe44f,0xe44b,UDCODE,UDCODE,UDCODE,UDCODE,0xe44c, - UDCODE,0xe44d,UDCODE,UDCODE,UDCODE,UDCODE,0x8d70,UDCODE,UDCODE, - UDCODE,0xe455,UDCODE,0xe451,UDCODE,UDCODE,UDCODE,UDCODE,0x9586, - UDCODE,0x968c,0x9547,UDCODE,UDCODE,0xe450,UDCODE,UDCODE,0xe453, - 0xe452,UDCODE,UDCODE,UDCODE,0x9663,0xe456,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe457,UDCODE,UDCODE,0x9156,UDCODE,0xe458, - UDCODE,UDCODE,0xe45a,UDCODE,0xe45e,UDCODE,UDCODE,0xe45b,0xe459, - 0x945e,0xe45c,UDCODE,0xe45d,UDCODE,UDCODE,UDCODE,0x89b0,UDCODE, - 0xe464,0xe45f,UDCODE,UDCODE,UDCODE,0xe460,UDCODE,UDCODE,UDCODE, - 0xe461,UDCODE,0x919f,UDCODE,UDCODE,UDCODE,UDCODE,0xe463,0xe462, - 0xe465,UDCODE,UDCODE,UDCODE,UDCODE,0xe466,0xe467,UDCODE,UDCODE, - 0x9062,UDCODE,0x89e7,UDCODE,0xe468,0x97d5,UDCODE,0x8ea9,UDCODE, - UDCODE,0x8f4c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8e8a,0x9276, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe469,0xe46a,0x8950,UDCODE, - 0xe46b,0xe46c,0xe46d,UDCODE,UDCODE,0xe46e,UDCODE,0xe46f,0x8bbb, - 0x9da8,0xe470,UDCODE,0x90e3,0xe471,0x8ec9,UDCODE,0xe472,UDCODE, - 0x98ae,UDCODE,UDCODE,UDCODE,0xe473,0x95dc,0x8ada,UDCODE,UDCODE, - 0x9143,0x8f77,UDCODE,0x9591,0x8f4d,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe474,0x8d71,0xe475,0x94ca, - UDCODE,0xe484,UDCODE,UDCODE,UDCODE,UDCODE,0xe477,UDCODE,0x91c7, - 0x9495,0x8cbd,0xe476,0x9144,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe478,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x92f8, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe47a,0xe479, - 0xe47c,UDCODE,UDCODE,0xe47b,UDCODE,0xe47d,UDCODE,UDCODE,0xe480, - UDCODE,0xe47e,UDCODE,0x8acd,UDCODE,0xe481,UDCODE,0xe482,0xe483, - UDCODE,UDCODE,0x8daf,0x97c7,UDCODE,0xe485,0x9046,UDCODE,UDCODE, - UDCODE,0x8990,0xe486,0xe487,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe488,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x88f0,UDCODE,0xe489,UDCODE,UDCODE, - UDCODE,UDCODE,0xe48a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9587,UDCODE,UDCODE,UDCODE,0x8ec5,UDCODE,0xe48c,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8a48,0x88b0,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe48b,0xe48e,0x946d,UDCODE,0x9063,UDCODE,0x89d4,UDCODE,0x9646, - UDCODE,UDCODE,UDCODE,UDCODE,0x8c7c,0x8bda,UDCODE,0xe48d,UDCODE, - 0x89e8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8aa1, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8991,0xe492,0x97e8,0x91db,UDCODE,UDCODE,0x9563, - UDCODE,0xe49e,UDCODE,0x89d5,0xe49c,UDCODE,0xe49a,0xe491,UDCODE, - 0xe48f,UDCODE,0xe490,UDCODE,0x8ee1,0x8bea,0x9297,UDCODE,UDCODE, - UDCODE,0x93cf,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8970,UDCODE, - 0xe494,0xe493,UDCODE,UDCODE,UDCODE,UDCODE,0xe499,0xe495,0xe498, - 0xfb93,0x96ce,0xe497,0x89d6,0x8a9d,0xe49b,UDCODE,UDCODE,0xe49d, - UDCODE,UDCODE,UDCODE,UDCODE,0x8c73,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe4a1,0xe4aa,0xe4ab,UDCODE,UDCODE,UDCODE, - 0x88a9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4b2,UDCODE, - UDCODE,UDCODE,UDCODE,0x88ef,UDCODE,UDCODE,0xe4a9,UDCODE,UDCODE, - UDCODE,0xe4a8,UDCODE,0xe4a3,0xe4a2,UDCODE,0xe4a0,0xe49f,0x9283, - UDCODE,0x91f9,0xe4a5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe4a4,UDCODE,UDCODE,UDCODE,UDCODE,0xe4a7,UDCODE,UDCODE,UDCODE, - 0x9190,0x8c74,UDCODE,UDCODE,UDCODE,UDCODE,0x8960,0xe4a6,UDCODE, - 0x8d72,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9191,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfb94,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4b8,UDCODE,0xe4b9, - UDCODE,0x89d7,UDCODE,UDCODE,UDCODE,0x89ac,0xe4b6,UDCODE,UDCODE, - 0xfb95,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4ac,UDCODE,0xe4b4, - UDCODE,0xe4bb,0xe4b5,UDCODE,UDCODE,UDCODE,0xe4b3,UDCODE,UDCODE, - UDCODE,UDCODE,0xe496,UDCODE,UDCODE,0xe4b1,UDCODE,UDCODE,UDCODE, - 0xe4ad,UDCODE,UDCODE,UDCODE,0x8ace,0xe4af,0xe4ba,UDCODE,0xe4b0, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4bc,UDCODE,0xe4ae,0x949c, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9789,UDCODE,UDCODE,UDCODE, - 0xe4b7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4cd, - UDCODE,UDCODE,UDCODE,0xe4c5,UDCODE,UDCODE,UDCODE,0x909b,UDCODE, - 0xfb96,UDCODE,UDCODE,0x8b65,UDCODE,0x8bdb,UDCODE,0xe4c0,UDCODE, - UDCODE,UDCODE,UDCODE,0x89d9,UDCODE,UDCODE,0x8fd2,UDCODE,0xe4c3, - UDCODE,UDCODE,UDCODE,0x8dd8,UDCODE,UDCODE,0x9370,0xe4c8,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95ec,UDCODE, - 0xe4bf,UDCODE,UDCODE,UDCODE,0x89d8,0x8cd4,0x9548,0xe4c9,UDCODE, - 0xe4bd,UDCODE,0xfb97,0xe4c6,UDCODE,UDCODE,UDCODE,0xe4d0,UDCODE, - 0xe4c1,0xe4c2,0x93b8,UDCODE,UDCODE,0xe4c7,UDCODE,UDCODE,UDCODE, - 0xe4c4,0x9647,0xe4ca,0x88de,UDCODE,UDCODE,UDCODE,UDCODE,0xe4be, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe4cc,UDCODE,0xe4cb,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x948b,0xe4d2,UDCODE,0xe4dd,UDCODE,UDCODE, - UDCODE,UDCODE,0x8a9e,UDCODE,UDCODE,UDCODE,0xe4e0,UDCODE,UDCODE, - 0xe4ce,UDCODE,UDCODE,UDCODE,0xe4d3,0x978e,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4dc,UDCODE,0xfb98,0x9774, - UDCODE,UDCODE,UDCODE,UDCODE,0x97a8,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9298,UDCODE,UDCODE,UDCODE,0x8a8b, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9592,0xe4e2,0x939f,UDCODE, - UDCODE,0x88af,UDCODE,UDCODE,0xe4db,UDCODE,0xe4d7,0x9192,0xe4d1, - 0xe4d9,0xe4de,UDCODE,0x944b,UDCODE,UDCODE,UDCODE,0x88a8,UDCODE, - 0xe4d6,UDCODE,0xe4df,0x9598,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe4da,UDCODE,0xe4d5,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8fd3,UDCODE,UDCODE,UDCODE,UDCODE,0x8f4e,UDCODE, - UDCODE,UDCODE,0x8eaa,UDCODE,UDCODE,UDCODE,UDCODE,0x96d6,UDCODE, - UDCODE,0x9566,UDCODE,UDCODE,0xe4e5,UDCODE,0xe4ee,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe4d8,UDCODE,UDCODE,UDCODE,UDCODE,0x8a97,UDCODE,0xfb99,UDCODE, - UDCODE,UDCODE,0x8ff6,0xe4e3,UDCODE,0xe4e8,0x9193,UDCODE,UDCODE, - 0xe4e4,UDCODE,0xe4eb,UDCODE,UDCODE,0x927e,UDCODE,0xe4ec,UDCODE, - UDCODE,0x9775,0xe4e1,0x8a57,UDCODE,0xe4e7,UDCODE,UDCODE,0xe4ea, - 0x96aa,UDCODE,UDCODE,UDCODE,UDCODE,0xe4ed,UDCODE,UDCODE,0xe4e6, - 0xe4e9,UDCODE,0xfa60,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9648,UDCODE,0x9840,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4f1, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4f8,UDCODE, - UDCODE,0xe4f0,0x8ec1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4cf, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x95cc,UDCODE,0x96a0,0xe4f7,0xe4f6,UDCODE,0xe4f2,0xe4f3, - UDCODE,0x8955,UDCODE,UDCODE,UDCODE,UDCODE,0xe4f5,UDCODE,0xe4ef, - UDCODE,UDCODE,UDCODE,UDCODE,0x92d3,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe4f4,0x88fc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x91a0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x95c1,UDCODE,UDCODE,0xe4f9,0xe540,UDCODE,0x94d7,UDCODE,UDCODE, - UDCODE,UDCODE,0xe4fc,0x8fd4,0x8ec7,0xe542,UDCODE,UDCODE,0x8bbc, - UDCODE,UDCODE,UDCODE,UDCODE,0xfb9a,UDCODE,0xe543,UDCODE,0x9599, - 0xe4fb,0xfb9b,0xe4d4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe4fa,UDCODE,UDCODE,UDCODE,UDCODE,0x986e,0x93a0, - 0x9593,0xfb9c,UDCODE,0xe54a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe550,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe551,UDCODE,0xe544,UDCODE,UDCODE,UDCODE,0x9496, - UDCODE,UDCODE,0xe54e,0xe546,UDCODE,0xe548,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe552,0xe547,UDCODE,UDCODE,0xe54b,UDCODE,UDCODE, - 0x8992,UDCODE,0x93e3,UDCODE,0xe54c,0xe54f,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe545,UDCODE,0x9145,UDCODE,0xe549, - 0x8e46,0x9064,0x8c4f,0x96f2,UDCODE,0x96f7,0x8f92,0xfb9e,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe556,0xe554, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x986d,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe553,UDCODE,UDCODE,UDCODE, - 0x9795,UDCODE,0xe555,0xe557,UDCODE,UDCODE,UDCODE,UDCODE,0xe558, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe55b,0xe559,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x93a1,0xe55a,UDCODE,UDCODE, - UDCODE,0x94cb,0xe54d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f93,UDCODE,0xe55c, - 0xe561,0x9194,UDCODE,UDCODE,0xe560,0xe541,UDCODE,UDCODE,UDCODE, - 0xe562,0x9168,UDCODE,UDCODE,0xe55d,0xe55f,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe55e,UDCODE,UDCODE,0x9f50,0x9f41, - UDCODE,UDCODE,0xe564,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe563,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9796,UDCODE,0xe1ba,0xe565,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe566,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe567, - 0x8cd5,UDCODE,0x8b73,UDCODE,UDCODE,UDCODE,0xe569,0x997c,UDCODE, - UDCODE,UDCODE,UDCODE,0x8b95,UDCODE,0x97b8,UDCODE,0x8bf1,0xe56a, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe56b,UDCODE, - UDCODE,UDCODE,0x928e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe56c, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x93f8,UDCODE, - 0x88b8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89e1,0xe571,0xe572, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe56d,UDCODE,0x8e5c, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe56e,0x9461,UDCODE,UDCODE,UDCODE, - UDCODE,0xe56f,0xe570,0xe57a,UDCODE,UDCODE,UDCODE,0xe574,0xe577, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe573,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe575,UDCODE,0xe576,0x8ed6,UDCODE,0xe578,UDCODE,0x9260, - UDCODE,0x8c75,0x8a61,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe57b, - UDCODE,UDCODE,UDCODE,UDCODE,0x8a5e,UDCODE,0xe581,UDCODE,UDCODE, - 0xe57c,0xe580,UDCODE,UDCODE,UDCODE,UDCODE,0x94b8,UDCODE,UDCODE, - UDCODE,UDCODE,0xe57d,UDCODE,UDCODE,0xe57e,0x9567,0x94d8,0xe582, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x91fb, - 0xe58c,UDCODE,0xe588,UDCODE,UDCODE,0x89e9,0xe586,UDCODE,0x9649, - 0xe587,UDCODE,UDCODE,0xe584,UDCODE,0xe585,0xe58a,0xe58d,UDCODE, - UDCODE,0xe58b,UDCODE,UDCODE,UDCODE,0xe589,0xe583,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9277,UDCODE,0xe594,UDCODE,0x96a8,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe592,UDCODE, - UDCODE,UDCODE,0xe593,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe58e,UDCODE,UDCODE,0xe590,UDCODE, - UDCODE,UDCODE,0xe591,UDCODE,UDCODE,UDCODE,0xe58f,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90e4,UDCODE, - 0x9858,0xe598,UDCODE,0xe599,UDCODE,UDCODE,UDCODE,UDCODE,0xe59f, - UDCODE,0x9049,UDCODE,0xe59b,UDCODE,0xe59e,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe596,0xe595,UDCODE,UDCODE,0xe5a0,UDCODE,UDCODE, - 0x89da,UDCODE,0xe59c,UDCODE,0xe5a1,UDCODE,UDCODE,UDCODE,0xe59d, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe59a,UDCODE,0x92b1,UDCODE, - 0xe597,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9488,UDCODE, - UDCODE,0xe5a5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x975a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe5a4,UDCODE,UDCODE,0xe5a3,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5ac,UDCODE,UDCODE, - UDCODE,0xe5a6,UDCODE,UDCODE,UDCODE,0xe5ae,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9786,0xe5b1,UDCODE,0xe5a8,UDCODE,UDCODE, - 0xe5a9,UDCODE,UDCODE,UDCODE,0xe5ad,UDCODE,0xe5b0,0xe5af,UDCODE, - UDCODE,UDCODE,0xe5a7,UDCODE,UDCODE,UDCODE,UDCODE,0xe5aa,UDCODE, - 0xe5bb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5b4,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe5b2,UDCODE,UDCODE,0xe5b3,UDCODE,UDCODE,UDCODE, - 0xe5b8,0xe5b9,UDCODE,0x8a49,UDCODE,0x8b61,UDCODE,UDCODE,0xe5b7, - 0xe5a2,UDCODE,0xfba1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5b6, - 0xe5ba,0xe5b5,UDCODE,0xe5bc,UDCODE,UDCODE,UDCODE,0xe5be,0xe5bd, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe5c0,0xe5bf,0xe579,UDCODE,UDCODE,UDCODE,0xe5c4,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5c1, - UDCODE,UDCODE,UDCODE,UDCODE,0xe5c2,UDCODE,UDCODE,0xe5c3,UDCODE, - 0xe5c5,UDCODE,UDCODE,UDCODE,UDCODE,0x8c8c,UDCODE,0xe5c7,UDCODE, - 0xe5c6,UDCODE,0x8f4f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8d73, - 0x9fa5,UDCODE,UDCODE,UDCODE,UDCODE,0xe5c8,0x8f70,UDCODE,UDCODE, - UDCODE,0x8a58,UDCODE,0xe5c9,UDCODE,0x8971,UDCODE,0x8fd5,0xe5ca, - UDCODE,UDCODE,0x8d74,0xe5cb,0x88df,UDCODE,UDCODE,UDCODE,UDCODE, - 0x955c,UDCODE,UDCODE,0xe5cc,UDCODE,UDCODE,UDCODE,UDCODE,0x908a, - UDCODE,0xe5d3,UDCODE,UDCODE,0xe5d0,UDCODE,0x928f,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe5d1,0xe5ce,0x8bdc,UDCODE,0xe5cd,0xe5d4, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c55,UDCODE,UDCODE,0x91dc, - UDCODE,0xe5da,UDCODE,UDCODE,UDCODE,UDCODE,0xe5d6,UDCODE,UDCODE, - UDCODE,0x91b3,0xe5d5,UDCODE,0xe5d8,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe5cf,UDCODE,UDCODE,UDCODE,0xe5d9,UDCODE,0xe5db,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x94ed,UDCODE,UDCODE,0xe5d7,UDCODE, - 0xe5dc,0xe5de,UDCODE,UDCODE,0x8cd1,0xe5d2,UDCODE,0x88bf,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5dd,UDCODE,0x8dd9, - 0x97f4,0xe5df,0xe5e0,0x9195,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x97a0,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe5e1,0x9754,UDCODE,UDCODE,0xe5e2,0xe5e3,UDCODE,UDCODE,0x95e2, - 0xe5e4,UDCODE,0x8dbe,UDCODE,0x97a1,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe5e9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe5ea,0x8fd6,0xe5e8,0xfba2,UDCODE,UDCODE, - 0x9787,0xe5e5,UDCODE,UDCODE,0xe5e7,0x90bb,0x909e,0xe5e6,UDCODE, - 0xe5eb,UDCODE,UDCODE,0x95a1,UDCODE,UDCODE,0xe5ed,UDCODE,0xe5ec, - UDCODE,UDCODE,UDCODE,0x8a8c,UDCODE,0x964a,0xe5ee,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfa5d,0xe5fa,0xe5f0, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5f1,UDCODE,UDCODE, - UDCODE,UDCODE,0xe5f2,0xe5f3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5f7,UDCODE,0xe5f8,UDCODE, - UDCODE,0xe5f6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5f4,UDCODE, - 0xe5ef,0xe5f5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe5f9,0xe8b5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x89a6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe5fc,0x8bdd,0xe5fb,UDCODE,UDCODE,UDCODE,0xe641,UDCODE,0xe640, - UDCODE,UDCODE,UDCODE,0xe643,UDCODE,UDCODE,0xe642,UDCODE,0xe644, - UDCODE,UDCODE,0x8f50,UDCODE,0xe645,UDCODE,UDCODE,0xe646,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe647,0x90bc,UDCODE,0x9776, - UDCODE,0xe648,UDCODE,UDCODE,0x95a2,0x9465,0xe649,UDCODE,0xe64a, - 0x8ca9,UDCODE,UDCODE,UDCODE,0x8b4b,UDCODE,UDCODE,UDCODE,0xe64b, - UDCODE,UDCODE,0x8e8b,0x9460,0xe64c,UDCODE,0x8a6f,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe64d,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe64f,0x9797,UDCODE,0xe64e,0x9065,UDCODE,0xe650,UDCODE,UDCODE, - 0xe651,UDCODE,UDCODE,0xe652,0x8acf,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe653,UDCODE,UDCODE,0xe654,UDCODE,0xe655,0xe656, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8a70, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe657,UDCODE, - 0xe658,0xe659,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89f0,UDCODE, - UDCODE,0x9047,0xe65a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe65b,UDCODE,UDCODE, - UDCODE,0xe65c,0x8cbe,UDCODE,0x92f9,0xe65d,UDCODE,UDCODE,UDCODE, - UDCODE,0x8c76,UDCODE,0x9075,UDCODE,0xe660,UDCODE,0x93a2,UDCODE, - 0xe65f,UDCODE,0xfba3,0x8c50,UDCODE,UDCODE,0xe65e,0x91f5,0x8b4c, - UDCODE,UDCODE,0xe661,UDCODE,0xe662,UDCODE,0x8fd7,UDCODE,UDCODE, - UDCODE,0x8c8d,UDCODE,0xe663,UDCODE,UDCODE,UDCODE,UDCODE,0x964b, - UDCODE,UDCODE,0x90dd,UDCODE,UDCODE,UDCODE,0x8b96,UDCODE,0x96f3, - 0x9169,UDCODE,0xe664,0xfba4,UDCODE,UDCODE,0x9066,0x9290,0x8fd8, - UDCODE,UDCODE,UDCODE,UDCODE,0xe665,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe668,UDCODE,0xe669,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x8dbc,0x91c0,0xe667,UDCODE,0x8fd9,0x955d,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe666,UDCODE,UDCODE,0x8e8c,UDCODE,0x8972, - UDCODE,0xe66d,0x8c77,UDCODE,UDCODE,0x8e8e,UDCODE,UDCODE,0x8e8d, - UDCODE,0x986c,0xe66c,0xe66b,0x9146,UDCODE,0x8b6c,0x9862,0x8a59, - 0x8fda,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfba5,UDCODE,UDCODE, - 0xe66a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe66f,UDCODE,0xe670, - 0xe66e,UDCODE,0x8cd6,UDCODE,0x975f,UDCODE,UDCODE,0x8e8f,0x9446, - UDCODE,UDCODE,UDCODE,0xe673,UDCODE,0x90be,UDCODE,0x9261,UDCODE, - UDCODE,0x9755,UDCODE,0xe676,UDCODE,UDCODE,UDCODE,0x8cea,UDCODE, - 0x90bd,0xe672,UDCODE,0xe677,0x8ceb,0xe674,0xe675,0xfba6,0xe671, - UDCODE,UDCODE,UDCODE,0x90e0,0x93c7,UDCODE,UDCODE,0x924e,UDCODE, - 0x89db,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x94ee,UDCODE, - UDCODE,0x8b62,UDCODE,0xfba7,0x92b2,UDCODE,UDCODE,0xe67a,UDCODE, - 0xe678,UDCODE,UDCODE,0x926b,UDCODE,UDCODE,UDCODE,0x90bf,0x8ad0, - 0xe679,UDCODE,0x907a,UDCODE,UDCODE,0x97c8,UDCODE,UDCODE,UDCODE, - 0x985f,UDCODE,UDCODE,UDCODE,0xe67b,0xe687,0x92b3,UDCODE,0xe686, - 0xfba8,0xe683,0xe68b,0xe684,UDCODE,0xe680,UDCODE,0x92fa,0xe67e, - UDCODE,UDCODE,UDCODE,0xe67c,UDCODE,0x9740,0x8e90,UDCODE,UDCODE, - 0xe681,UDCODE,0xe67d,UDCODE,UDCODE,0xfbaa,0xe685,0x8f94,UDCODE, - 0x8cbf,UDCODE,UDCODE,UDCODE,0x91f8,0x9664,0x8979,0x88e0,UDCODE, - 0x93a3,UDCODE,UDCODE,0xe689,UDCODE,UDCODE,UDCODE,UDCODE,0xe688, - UDCODE,0x93e4,UDCODE,0xe68d,UDCODE,UDCODE,UDCODE,0xe682,UDCODE, - 0xe68c,0xe68e,UDCODE,0x8caa,0xe68a,0x8d75,UDCODE,0x8ed3,UDCODE, - UDCODE,0xe68f,0x9777,UDCODE,UDCODE,UDCODE,UDCODE,0xe692,UDCODE, - 0xe695,UDCODE,UDCODE,0xe693,0x9554,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe690,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8bde, - UDCODE,UDCODE,UDCODE,UDCODE,0xe694,UDCODE,UDCODE,0xe696,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe69a,UDCODE,UDCODE, - 0xe697,UDCODE,0xe699,0xe698,UDCODE,UDCODE,UDCODE,0xfbab,UDCODE, - UDCODE,0xe69b,UDCODE,0x8eaf,UDCODE,0xe69d,0xe69c,0x9588,UDCODE, - UDCODE,0xe69f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c78, - UDCODE,UDCODE,UDCODE,UDCODE,0xe69e,0xe6a0,UDCODE,UDCODE,0xe6a1, - 0x8b63,0xe3bf,0x8ff7,UDCODE,0xe6a2,UDCODE,UDCODE,0x8cec,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe6a3,UDCODE,0xfbac,0xe6a4,UDCODE, - UDCODE,0x8e5d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9dcc, - UDCODE,0xe6a5,UDCODE,0xe6a6,UDCODE,0x8f51,UDCODE,0xe6a7,0xe6a8, - UDCODE,UDCODE,0xe6a9,UDCODE,UDCODE,0xe6aa,0xe6ab,0x924a,UDCODE, - UDCODE,0xe6ac,UDCODE,UDCODE,UDCODE,UDCODE,0xe6ae,UDCODE,0xe6ad, - UDCODE,UDCODE,UDCODE,UDCODE,0x93a4,UDCODE,0xe6af,UDCODE,0x964c, - UDCODE,0xe6b0,UDCODE,0xe6b1,UDCODE,0xe6b2,UDCODE,UDCODE,UDCODE, - UDCODE,0xe6b3,UDCODE,UDCODE,UDCODE,UDCODE,0x93d8,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8fdb,0xe6b4,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8d8b,0x98ac,0xe6b5,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe6b6,0x955e,0xe6b7,UDCODE,0xe6bf,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe6b8,UDCODE,UDCODE,0xe6ba,UDCODE,UDCODE,UDCODE,0xe6b9, - 0xe6bb,UDCODE,0x9665,0xe6bc,0xe6bd,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe6be,UDCODE,UDCODE,UDCODE,0xe6c0,UDCODE,UDCODE,UDCODE, - UDCODE,0x8a4c,0x92e5,UDCODE,0x9589,0x8de0,0x8d76,UDCODE,UDCODE, - UDCODE,UDCODE,0x956e,0x89dd,0x94cc,0xe6c3,0x8ad1,0x90d3,0xe6c2, - 0xe6c7,0x9299,0x96e1,UDCODE,0xe6c5,0xe6c6,0x8b4d,UDCODE,0xe6c8, - 0x9483,0x91dd,UDCODE,UDCODE,0x94ef,0x935c,0xe6c4,UDCODE,0x9666, - 0x89ea,0xe6ca,0x9847,0x92c0,0x9864,UDCODE,UDCODE,0x8e91,0xe6c9, - UDCODE,0x91af,UDCODE,UDCODE,0xe6da,0x9147,UDCODE,UDCODE,0x93f6, - UDCODE,0x956f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe6cd, - 0x8e5e,0x8e92,UDCODE,0x8fdc,UDCODE,0x9485,UDCODE,0x8cab,0xe6cc, - 0xe6cb,UDCODE,0x958a,UDCODE,UDCODE,UDCODE,0x8ebf,UDCODE,UDCODE, - 0x9371,UDCODE,UDCODE,0xfbad,UDCODE,UDCODE,UDCODE,0xfbae,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe6cf,0xe6d0,0x8d77,0xe6ce,0xe6d1, - 0xe6d2,UDCODE,0xe6d4,0x91a1,UDCODE,0xe6d3,0x8ae4,UDCODE,0xe6d6, - UDCODE,0xe6d5,0xe6d7,UDCODE,0xfbaf,0xe6d9,0xe6db,UDCODE,0xe6dc, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90d4,UDCODE,0x8ecd,0xe6dd, - UDCODE,UDCODE,UDCODE,0x8a71,UDCODE,0xe6de,UDCODE,UDCODE,0x9196, - 0xe6df,UDCODE,0xe6e0,0x958b,UDCODE,0xfbb0,0x8b4e,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe6e1,UDCODE, - UDCODE,UDCODE,0x92b4,UDCODE,UDCODE,UDCODE,UDCODE,0x897a,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe6e2,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8eef,UDCODE,UDCODE,UDCODE, - UDCODE,0x9096,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x91ab,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe6e5,UDCODE,UDCODE,UDCODE,0xe6e4,UDCODE,UDCODE,UDCODE, - 0xe6e3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe6eb,0xe6e9,UDCODE,UDCODE,0xe6e6,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe6e8,UDCODE,UDCODE,UDCODE,0xe6e7,0xe6ea,UDCODE, - 0x8b97,UDCODE,0xe6ee,UDCODE,0x90d5,UDCODE,0xe6ef,UDCODE,UDCODE, - UDCODE,UDCODE,0x8cd7,UDCODE,0xe6ec,0xe6ed,UDCODE,UDCODE,UDCODE, - 0x9848,UDCODE,UDCODE,UDCODE,0x92b5,UDCODE,0x9148,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe6f0,UDCODE,UDCODE,0xe6f3,0xe6f1, - 0xe6f2,0x9778,UDCODE,UDCODE,UDCODE,UDCODE,0x93a5,0xe6f6,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe6f4,0xe6f5,0xe6f7,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe748,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe6fa,UDCODE,UDCODE,UDCODE,0xe6fb,0xe6f9, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe6f8,UDCODE,0x92fb,UDCODE,UDCODE,0xe740, - 0xe744,0xe741,0xe6fc,UDCODE,0xe742,UDCODE,UDCODE,UDCODE,0xe743, - UDCODE,UDCODE,UDCODE,UDCODE,0xe74a,UDCODE,UDCODE,UDCODE,0xe745, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90d6,0xe747,UDCODE,UDCODE, - 0xe749,0xe746,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe74c,UDCODE,0x8f52, - UDCODE,0xe74b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe74d,UDCODE, - UDCODE,UDCODE,UDCODE,0xe74e,UDCODE,UDCODE,0xe751,0xe750,UDCODE, - 0xe74f,UDCODE,UDCODE,0xe753,0xe752,UDCODE,0x96f4,UDCODE,UDCODE, - UDCODE,0xe755,UDCODE,0xe754,0xe756,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe757,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe759, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe758, - 0x9067,0xe75a,UDCODE,UDCODE,0x8beb,0xe75b,0xe75d,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe75e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe75f, - 0xe75c,UDCODE,0xe760,UDCODE,0x8ed4,0xe761,0x8b4f,0x8c52,UDCODE, - 0xfbb2,UDCODE,UDCODE,0x8cac,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe762,UDCODE,UDCODE,UDCODE,0x93ee,UDCODE, - UDCODE,0x935d,0xe763,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe766,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8eb2,UDCODE,UDCODE,0xe765, - 0xe764,0x8c79,0xe767,0x8a72,UDCODE,0xe769,UDCODE,UDCODE,UDCODE, - 0x8dda,0xe768,UDCODE,0xe771,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe76b,0xe76d,0x95e3,0xe76a,UDCODE,UDCODE,UDCODE,0xe76c,UDCODE, - 0xe770,0xe76e,0x8b50,UDCODE,0xe76f,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe772,UDCODE,UDCODE,0x9479,0x97d6,UDCODE,UDCODE, - UDCODE,UDCODE,0x8f53,UDCODE,UDCODE,UDCODE,0xe773,UDCODE,UDCODE, - UDCODE,UDCODE,0x9741,0xe775,UDCODE,0xe774,UDCODE,UDCODE,0xe778, - 0x9760,UDCODE,UDCODE,0xe777,UDCODE,0x8a8d,0xe776,0xe77b,UDCODE, - UDCODE,0xe77a,UDCODE,UDCODE,0xe779,0x9351,0xe77c,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe77d,UDCODE,UDCODE, - UDCODE,UDCODE,0xe77e,UDCODE,UDCODE,0x8d8c,UDCODE,0x8c44,0xe780, - 0xe781,0xe782,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9068,0xe783,UDCODE,0x8eab,0xe784,UDCODE,UDCODE, - UDCODE,0xe785,UDCODE,UDCODE,UDCODE,0x999f,0x999e,UDCODE,UDCODE, - UDCODE,UDCODE,0xe786,0xe390,0xe787,0x9243,0x904a,0x945f,UDCODE, - UDCODE,UDCODE,UDCODE,0xe788,UDCODE,UDCODE,0x95d3,0x92d2,0x8d9e, - UDCODE,UDCODE,0x9248,UDCODE,UDCODE,0x8949,UDCODE,0x9698,0x9076, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c7d, - UDCODE,UDCODE,0x8bdf,UDCODE,UDCODE,0x95d4,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe789,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe78b,UDCODE,UDCODE,0xe78a,0x89de,UDCODE,UDCODE,0x93f4, - 0xe78c,0x9497,UDCODE,0x9352,UDCODE,0xe78d,0x8f71,UDCODE,UDCODE, - UDCODE,0xe78f,UDCODE,UDCODE,0x96c0,0xe79e,0xe791,0xe792,UDCODE, - UDCODE,0x92c7,0x91de,0x9197,UDCODE,0x93a6,UDCODE,0xe790,0x8b74, - UDCODE,UDCODE,UDCODE,UDCODE,0xe799,UDCODE,0xe796,0xe7a3,0x93a7, - 0x9280,0xe793,UDCODE,0x92fc,0x9372,0xe794,0xe798,0x9080,UDCODE, - 0x9487,0x92ca,UDCODE,UDCODE,0x90c0,0xe797,0x91ac,0x91a2,0xe795, - 0x88a7,0x9841,UDCODE,UDCODE,UDCODE,0xe79a,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x91df,UDCODE,UDCODE,0x8f54,0x9069,UDCODE, - UDCODE,0xe79c,0xe79b,UDCODE,0x88ed,0xe79d,UDCODE,UDCODE,0x954e, - UDCODE,0xe7a5,UDCODE,UDCODE,0x93d9,0x908b,UDCODE,UDCODE,0x9278, - UDCODE,0x8bf6,UDCODE,0xe7a4,0x9756,0x895e,UDCODE,0x95d5,0x89df, - 0xe79f,0xe7a0,0xe7a1,0xe7a2,0x93b9,0x9242,0x88e1,0xe7a6,UDCODE, - 0xe7a7,0xeaa1,UDCODE,UDCODE,0x91bb,UDCODE,0xe7a8,UDCODE,0x8993, - 0x916b,UDCODE,0x8cad,UDCODE,0x9779,UDCODE,0xfbb5,0xe7a9,0x934b, - UDCODE,UDCODE,UDCODE,0x9198,0x8ed5,0xe7aa,UDCODE,UDCODE,0xe7ad, - UDCODE,UDCODE,0x8f85,0xe7ab,0x914a,0x9149,UDCODE,0x88e2,UDCODE, - 0x97c9,0xe7af,UDCODE,0x94f0,0xe7b1,0xe7b0,0xe7ae,0xe284,0x8ad2, - UDCODE,UDCODE,0xe78e,UDCODE,0xe7b3,0xe7b2,UDCODE,UDCODE,UDCODE, - UDCODE,0xe7b4,UDCODE,0x9757,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x93df,UDCODE,UDCODE,0x964d,UDCODE,0xe7b5, - UDCODE,0x8ed7,UDCODE,UDCODE,UDCODE,UDCODE,0xe7b6,UDCODE,0xe7b7, - UDCODE,UDCODE,UDCODE,0xe7b8,UDCODE,UDCODE,0x9340,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x88e8,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8d78,UDCODE,UDCODE, - UDCODE,0x9859,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7bc,UDCODE,UDCODE,0xfbb6, - UDCODE,UDCODE,0x8c53,0xe7b9,UDCODE,0xe7ba,UDCODE,UDCODE,UDCODE, - 0x9594,UDCODE,UDCODE,UDCODE,UDCODE,0x8a73,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x9758,UDCODE,0x8bbd,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x9373,0xe7bd,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe7be,UDCODE,UDCODE,0xfbb8,UDCODE,UDCODE,UDCODE, - 0xe7bf,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbb9,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9341,UDCODE,UDCODE,0xe7c1,UDCODE,0xe7c0,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x93d1,0xe7c2,0x8f55,0x8ede,0x947a,0x9291, - UDCODE,UDCODE,UDCODE,0x8ef0,UDCODE,0x908c,UDCODE,0xe7c3,UDCODE, - 0xe7c4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x907c,0xe7c5,UDCODE,0xe7c6,UDCODE,UDCODE,UDCODE,0xe7c7, - 0x978f,UDCODE,0x8f56,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7c9, - 0xe7c8,UDCODE,0x8d79,UDCODE,0x8d93,0x8e5f,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7cc,UDCODE,UDCODE, - UDCODE,UDCODE,0x8f86,UDCODE,0xe7cb,UDCODE,0xe7ca,UDCODE,0x91e7, - UDCODE,UDCODE,0x8ced,UDCODE,0x90c1,UDCODE,UDCODE,UDCODE,UDCODE, - 0x94ae,UDCODE,UDCODE,UDCODE,UDCODE,0x8f58,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe7cd,UDCODE,0x8fdd,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe7d0,0xe7ce,UDCODE,UDCODE,UDCODE,0xe7cf,UDCODE,UDCODE, - UDCODE,UDCODE,0xe7d2,0xe7d1,UDCODE,UDCODE,0x8ff8,UDCODE,0xe7d3, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7d4,0xe7d5,UDCODE,UDCODE, - UDCODE,UDCODE,0x94ce,0x8dd1,0x8edf,0xe7d6,UDCODE,0xe7d7,0x97a2, - 0x8f64,0x96ec,0x97ca,0xe7d8,0x8be0,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe7d9,0xfbbb,0x9342,UDCODE,0xfbba,0xe7dc,0x8a98,0x906a,0xfbbc, - 0xe7da,UDCODE,0xe7db,UDCODE,0x92de,0xfbbf,0xfbc0,0x9674,0x8bfa, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbbd,0xfbbe,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe7de,0xe7df,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe7dd,UDCODE,UDCODE,0xe7e1,0xfbc1,UDCODE,UDCODE, - UDCODE,0xfbc3,UDCODE,UDCODE,0x93dd,0x8a62,UDCODE,0xfbc2,0xe7e5, - UDCODE,UDCODE,0xe7e2,0xe7e4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe7e0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe86e,UDCODE,UDCODE,0xe7e3, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x97e9,UDCODE, - UDCODE,0x8cd8,UDCODE,0xfbca,0xfbc4,UDCODE,0xfbc6,UDCODE,UDCODE, - 0xe7ed,0xfbc5,UDCODE,UDCODE,UDCODE,0x9353,0xe7e8,UDCODE,UDCODE, - 0xe7eb,0xe7e9,UDCODE,0xe7ee,UDCODE,UDCODE,0xfbc7,UDCODE,0xe7ef, - 0xfbc9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7e7,UDCODE,0xfbc8, - 0xe7f4,0x8994,UDCODE,UDCODE,0xe7e6,UDCODE,UDCODE,UDCODE,0x94ab, - UDCODE,0xe7ea,UDCODE,0x8fde,0xfbcb,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8d7a,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xfbcd,0xfbce,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x9667,UDCODE,0x8be2,UDCODE,UDCODE,0x8f65,UDCODE,0x93ba,UDCODE, - UDCODE,0xfa5f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x914c,UDCODE,0xe7f2,UDCODE,0xe7ec,0xe7f1,UDCODE,0x96c1, - UDCODE,0x92b6,0xe7f3,0xe7f0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbcc,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x914b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe7f7,UDCODE,0xe7f6,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe7f5,0xfbd2,UDCODE,0x964e,0xfbd6,UDCODE,0xfbd4,UDCODE,0xfbd0, - UDCODE,0xfbd1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbd5, - UDCODE,UDCODE,UDCODE,0x8f9b,UDCODE,UDCODE,0xfbcf,UDCODE,0xe7f8, - 0x95dd,UDCODE,UDCODE,0x8973,UDCODE,UDCODE,UDCODE,UDCODE,0x9565, - 0x9292,UDCODE,UDCODE,UDCODE,UDCODE,0x8b98,0xfa65,0xe7fa,0xfbd9, - 0x8d7c,UDCODE,UDCODE,0xfbdc,0xfbde,UDCODE,UDCODE,UDCODE,0x8e4b, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7f9, - 0x908d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x908e, - 0xe840,0xe842,UDCODE,UDCODE,0xfbdd,0xfbdb,UDCODE,0x8ff9,0xfbd8, - 0xe841,0xe843,UDCODE,0xfbd7,0x8bd1,UDCODE,0x9564,UDCODE,UDCODE, - 0x8ee0,0x9842,UDCODE,0xe7fc,0x8df6,UDCODE,UDCODE,0x985e,UDCODE, - UDCODE,0xe845,UDCODE,UDCODE,UDCODE,UDCODE,0xe844,0xe846,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7fb,UDCODE, - UDCODE,UDCODE,0xfa5e,UDCODE,UDCODE,0x93e7,UDCODE,0x9374,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x92d5,UDCODE,0xe84b,0xfbe0, - UDCODE,UDCODE,UDCODE,0x9262,0xe847,UDCODE,UDCODE,UDCODE,0xe848, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8c4c,UDCODE,0xe84a,UDCODE,0xfbdf,UDCODE,UDCODE, - UDCODE,UDCODE,0x8cae,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe849,UDCODE,0x8fdf,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8a99,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe84f,UDCODE,0x8dbd, - 0x9199,UDCODE,UDCODE,0x92c8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xfbe1,UDCODE,UDCODE,0x8a5a,UDCODE, - UDCODE,UDCODE,UDCODE,0xe84d,0xe84e,0x92c1,UDCODE,0xe84c,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe850,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe856, - UDCODE,UDCODE,0xfbe2,UDCODE,0xe859,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe858,0x934c,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe851,0xe852,0xe855,UDCODE,UDCODE,UDCODE,UDCODE,0xe857,0xfbe3, - UDCODE,UDCODE,0x8bbe,UDCODE,UDCODE,0xe85a,0xe854,UDCODE,UDCODE, - 0xe853,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbe4,0xe85e, - UDCODE,UDCODE,UDCODE,0xe85f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe860,UDCODE,UDCODE,0xe85d,0xe85c,UDCODE, - UDCODE,UDCODE,0x8fe0,0x93a8,0xe85b,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe864,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe862,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xfbe5,UDCODE,UDCODE,UDCODE,0xe863,0xe861,UDCODE,0x91f6,UDCODE, - 0xe865,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe866,UDCODE, - UDCODE,0xe868,0xfbe6,UDCODE,UDCODE,0xfbe7,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ad3,0xe867,0x96f8,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe873,0xe869,UDCODE,UDCODE, - 0xe86c,UDCODE,0xe86a,UDCODE,0xe86b,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe86d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe86f,UDCODE,UDCODE,UDCODE,UDCODE,0xe870,UDCODE,0xe871,UDCODE, - UDCODE,UDCODE,UDCODE,0xe874,0xe872,0xe875,0xe877,UDCODE,0xe876, - 0x92b7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x96e5,UDCODE,0xe878,0x914d,UDCODE,UDCODE,UDCODE,0xe879,UDCODE, - 0x95c2,0xe87a,0x8a4a,UDCODE,UDCODE,UDCODE,0x895b,UDCODE,0x8ad5, - 0xfbe8,0x8ad4,0xe87b,UDCODE,0xe87c,UDCODE,0xe87d,0xe87e,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe880,UDCODE,0x8ad6,0x8a74, - 0x8d7d,0x94b4,UDCODE,0xe882,0xe881,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe883,UDCODE,UDCODE,UDCODE,UDCODE,0x897b,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe886,UDCODE,0xe885,0xe884,UDCODE,0xe887, - UDCODE,UDCODE,UDCODE,UDCODE,0xe88a,UDCODE,UDCODE,UDCODE,0x88c5, - UDCODE,UDCODE,0xe888,UDCODE,0xe88c,0xe88b,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe88e,0xe88d,0xe88f,UDCODE,0x93ac,UDCODE, - UDCODE,UDCODE,0xe890,UDCODE,UDCODE,UDCODE,UDCODE,0xe891,0xe893, - UDCODE,UDCODE,0xe892,0x958c,UDCODE,UDCODE,UDCODE,UDCODE,0xe894, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe895,UDCODE,0x8de3, - UDCODE,UDCODE,UDCODE,0xe896,0xe897,UDCODE,UDCODE,0x9668,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x916a,UDCODE, - UDCODE,UDCODE,0x88a2,0x91c9,UDCODE,0xe898,UDCODE,0x958d,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe89b,0xe899,0x8d7e,UDCODE, - 0xe89a,0x8cc0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x95c3,0xe89d,0xe89f,0xe89e,0xe8a0,UDCODE, - UDCODE,0x8940,0x9077,0x8f9c,0x8ad7,0xe8a1,UDCODE,UDCODE,UDCODE, - 0x9486,UDCODE,0xe8a3,UDCODE,UDCODE,UDCODE,0x8941,UDCODE,0xe8a2, - 0x92c2,UDCODE,0x97cb,0x93a9,0xe89c,0x97a4,UDCODE,0x8caf,UDCODE, - UDCODE,0x977a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x8bf7,0x97b2,UDCODE,0x8c47,UDCODE,0x91e0,0xe440,UDCODE,0xe8a4, - 0x8a4b,0x908f,UDCODE,UDCODE,UDCODE,UDCODE,0x8a75,0xe8a6,UDCODE, - 0xe8a7,0xe8a5,0x8c84,UDCODE,0x8ddb,0x8fe1,0xfbeb,UDCODE,UDCODE, - 0x8942,UDCODE,UDCODE,0x97d7,UDCODE,UDCODE,UDCODE,0xe8a9,0xe7ac, - UDCODE,0xe8a8,UDCODE,UDCODE,UDCODE,UDCODE,0xfbec,0xe8ac,0xe8aa, - 0xe8ab,UDCODE,0xe8ad,UDCODE,0xe8ae,0x97ea,0xe8af,0xe8b0,UDCODE, - 0x90c7,0x94b9,UDCODE,UDCODE,UDCODE,0x909d,0x8ae5,UDCODE,UDCODE, - 0x9759,0x89eb,0x8f57,0x8cd9,UDCODE,0xe8b3,UDCODE,0xe8b2,0x8e93, - 0xe8b4,0xe8b1,UDCODE,UDCODE,0x8e47,UDCODE,UDCODE,UDCODE,0xe8b8, - 0xe5ab,UDCODE,UDCODE,0x99d4,UDCODE,0x9097,0xe8b6,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x97a3,0x93ef,UDCODE,UDCODE,UDCODE,UDCODE, - 0x894a,UDCODE,0x90e1,0x8eb4,UDCODE,UDCODE,UDCODE,UDCODE,0x95b5, - UDCODE,0x895f,UDCODE,UDCODE,UDCODE,0x97eb,0x978b,UDCODE,0xe8b9, - UDCODE,0x9364,0x8ef9,UDCODE,UDCODE,UDCODE,0xe8ba,UDCODE,0xe8bb, - 0x906b,0xe8bc,UDCODE,0x97ec,UDCODE,UDCODE,0xe8b7,0xe8be,0xe8c0, - UDCODE,0xe8bf,UDCODE,0xe8bd,UDCODE,UDCODE,0xe8c1,UDCODE,UDCODE, - 0xe8c2,UDCODE,UDCODE,0x919a,UDCODE,0x89e0,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe8c3,UDCODE,UDCODE,0x96b6,UDCODE,UDCODE,0xe8c4, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe8c5,UDCODE,0x9849,0xfbed, - UDCODE,UDCODE,UDCODE,UDCODE,0x9e50,0xe8c6,UDCODE,0xfbee,UDCODE, - 0xe8c7,0xe8c8,UDCODE,UDCODE,UDCODE,0xe8cc,0xfbef,0xe8c9,UDCODE, - 0xe8ca,UDCODE,0xe8cb,0xe8cd,UDCODE,UDCODE,UDCODE,0xfbf0,UDCODE, - 0xfbf1,UDCODE,0xfbf2,0x90c2,UDCODE,UDCODE,0xfbf3,0x96f5,UDCODE, - UDCODE,0x90c3,UDCODE,UDCODE,0xe8ce,UDCODE,0x94f1,UDCODE,0xe8cf, - 0xea72,0x96ca,UDCODE,0xe8d0,UDCODE,0xe8d1,UDCODE,0xe8d2,0x8a76, - UDCODE,0xe8d4,UDCODE,0x9078,UDCODE,UDCODE,UDCODE,0xe8d5,UDCODE, - UDCODE,0x8c43,UDCODE,UDCODE,UDCODE,UDCODE,0xe8d6,0xe8da,UDCODE, - 0xe8d8,UDCODE,UDCODE,UDCODE,UDCODE,0xe8d9,UDCODE,UDCODE,0x8a93, - 0xe8d7,0xe8db,UDCODE,UDCODE,UDCODE,UDCODE,0xe8dc,UDCODE,0x88c6, - UDCODE,0xe8dd,0xe8de,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x8fe2,UDCODE,UDCODE,UDCODE,0xe8df,UDCODE,UDCODE,UDCODE, - 0x8b66,UDCODE,UDCODE,0xe8e2,UDCODE,UDCODE,0xe8e1,UDCODE,0xe8e0, - UDCODE,UDCODE,0xe691,UDCODE,0x95da,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe8e3,0xe8e4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe8e5, - UDCODE,UDCODE,0xe8e6,UDCODE,0xe8e7,UDCODE,UDCODE,0xe8e8,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ad8,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe8e9,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe8ea,0x9442,UDCODE,UDCODE, - UDCODE,0xe8ec,0x89b9,UDCODE,0xe8ef,0xe8ee,UDCODE,UDCODE,UDCODE, - UDCODE,0x8943,UDCODE,UDCODE,UDCODE,0x8bbf,0x95c5,0x92b8,0x8da0, - UDCODE,0x8d80,0x8f87,UDCODE,0x907b,UDCODE,UDCODE,UDCODE,0xe8f1, - UDCODE,UDCODE,0xe8f0,0x9761,0x8ae6,0x94d0,0x93da,UDCODE,UDCODE, - UDCODE,0x909c,0x97cc,UDCODE,0x8c7a,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe8f4,UDCODE,UDCODE,0xe8f3,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x966a,0x93aa,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x896f,UDCODE,UDCODE,0xe8f5,0xe8f2,UDCODE, - UDCODE,0x9570,0x978a,0xe8f6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe8f7,UDCODE,UDCODE,UDCODE,UDCODE,0xe8f9, - 0x91e8,0x8a7a,0x8a7b,0xe8f8,UDCODE,UDCODE,UDCODE,UDCODE,0x8ae7, - 0x8cb0,UDCODE,0xfbf4,0x8ae8,UDCODE,UDCODE,0x935e,UDCODE,UDCODE, - 0x97de,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbf5,UDCODE, - 0x8cda,UDCODE,UDCODE,UDCODE,0xe8fa,UDCODE,UDCODE,UDCODE,0xe8fb, - 0xe8fc,0xe940,UDCODE,0xe942,0xe941,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x9597,UDCODE,0xe943,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe944,UDCODE,0xe945,UDCODE,UDCODE,UDCODE,UDCODE,0xe946,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe948,0xe947,UDCODE,0xe949,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x94f2, - 0xe3ca,UDCODE,UDCODE,0x9048,UDCODE,UDCODE,0x8b51,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe94a,UDCODE,0xe94b,UDCODE,0x99aa, - 0x9f5a,0x94d1,UDCODE,UDCODE,0x88f9,UDCODE,0x88b9,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8e94,0x964f,0x8ffc,0xe94c, - UDCODE,0x96dd,UDCODE,UDCODE,UDCODE,0xe94d,0x977b,UDCODE,0x8961, - UDCODE,UDCODE,UDCODE,0x8e60,UDCODE,0xe94e,0x89ec,0xe94f,UDCODE, - UDCODE,UDCODE,0xe950,UDCODE,UDCODE,UDCODE,UDCODE,0xe952,0xe953, - UDCODE,0xe955,0xe951,UDCODE,UDCODE,0xe954,UDCODE,UDCODE,0xfbf8, - 0x8ad9,UDCODE,UDCODE,UDCODE,0xe956,UDCODE,0xe957,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe958,0xe959,UDCODE,UDCODE,UDCODE,0xe95a, - UDCODE,UDCODE,0xe95c,UDCODE,UDCODE,UDCODE,0xe95b,UDCODE,0xe95e, - 0xe961,UDCODE,UDCODE,UDCODE,0xe95d,0xe95f,0xe960,UDCODE,UDCODE, - 0xe962,UDCODE,0x8bc0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8ef1,0xe963,0xe964,0x8d81,UDCODE,UDCODE,UDCODE, - UDCODE,0xfbfa,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe965, - UDCODE,UDCODE,0x8a5d,UDCODE,UDCODE,UDCODE,0x946e,0xe966,0xe967, - UDCODE,UDCODE,UDCODE,UDCODE,0x9279,0x93e9,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe968,UDCODE,UDCODE,UDCODE,UDCODE, - 0x949d,UDCODE,UDCODE,0x91ca,0x8977,0x8bec,UDCODE,0x8bed,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9293,0xe96d,0x8bee, - UDCODE,UDCODE,0x89ed,UDCODE,UDCODE,0xe96c,UDCODE,UDCODE,0xe96a, - UDCODE,0xe96b,UDCODE,0xe969,UDCODE,UDCODE,0xe977,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe96e, - 0xe96f,UDCODE,UDCODE,0xe970,0xe971,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xe973,UDCODE,UDCODE,0xe972,UDCODE,UDCODE,UDCODE,0x8f78, - 0xe974,UDCODE,UDCODE,UDCODE,0xe976,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0x8b52,0xe975,UDCODE,UDCODE,0x919b, - 0x8cb1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe978,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x91cb,UDCODE,UDCODE,0xe979,UDCODE,UDCODE, - UDCODE,UDCODE,0x93ab,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe97a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe980,UDCODE, - 0xe97d,UDCODE,0xe97c,0xe97e,UDCODE,0xe97b,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xe982,0xfbfb,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe981,UDCODE,0xe984,UDCODE,UDCODE,0x8bc1, - 0xe983,UDCODE,UDCODE,UDCODE,0xe985,UDCODE,UDCODE,0xe986,UDCODE, - 0xe988,0xe987,UDCODE,UDCODE,UDCODE,0xe989,0xe98b,0xe98a,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8d9c,UDCODE,UDCODE,UDCODE, - UDCODE,0xe98c,UDCODE,UDCODE,0xe98d,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0x8a5b,UDCODE,UDCODE,UDCODE,0xe98e,UDCODE, - UDCODE,UDCODE,0xe98f,UDCODE,UDCODE,UDCODE,0x9091,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe990, - UDCODE,0xe991,UDCODE,0xe992,0xe993,UDCODE,UDCODE,UDCODE,0x8d82, - 0xfbfc,UDCODE,UDCODE,0xfc40,UDCODE,0xe994,0xe995,UDCODE,UDCODE, - 0xe996,0xe997,UDCODE,UDCODE,0xe998,UDCODE,UDCODE,UDCODE,0x94af, - 0xe99a,UDCODE,0x9545,0xe99b,0xe999,UDCODE,0xe99d,UDCODE,UDCODE, - 0xe99c,UDCODE,UDCODE,0xe99e,UDCODE,UDCODE,UDCODE,0xe99f,0xe9a0, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9a1, - UDCODE,0xe9a2,UDCODE,UDCODE,UDCODE,UDCODE,0xe9a3,UDCODE,UDCODE, - 0xe9a4,0xe9a5,UDCODE,0xe9a6,UDCODE,0xe9a7,0xe9a8,0xe9a9,0xe9aa, - UDCODE,UDCODE,UDCODE,0xe9ab,0xe9ac,UDCODE,0x9f54,0xe9ad,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2f6,0x8b53, - UDCODE,UDCODE,UDCODE,UDCODE,0x8a40,0x8db0,0xe9af,0xe9ae,0x96a3, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9b1,0xe9b2, - 0xe9b0,UDCODE,0xe9b3,UDCODE,UDCODE,0x9682,UDCODE,UDCODE,UDCODE, - 0xe9b4,UDCODE,0x8b9b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9844,UDCODE,UDCODE,0xfc42, - UDCODE,0xe9b5,0xfc41,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9b7,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x88bc,0xfc43,UDCODE,0xe9b8,0x95a9,0xe9b6,UDCODE,UDCODE,0xe9b9, - 0xe9ba,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9bb, - 0xe9bc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9bd, - UDCODE,0x968e,0x8e4c,UDCODE,0x8df8,0x914e,UDCODE,UDCODE,0xfc44, - UDCODE,UDCODE,0xe9be,UDCODE,UDCODE,UDCODE,UDCODE,0xe9c1,UDCODE, - 0xfc45,UDCODE,UDCODE,UDCODE,UDCODE,0xe9bf,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe9c2,UDCODE,UDCODE,0x8cef,0xe9c0,UDCODE,UDCODE, - UDCODE,UDCODE,0xe9c3,UDCODE,0xe9c4,0xe9c5,UDCODE,0xe9c9,UDCODE, - 0x8e49,UDCODE,UDCODE,UDCODE,UDCODE,0x91e2,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe9ca,0xe9c7,0xe9c6,0xe9c8,UDCODE,UDCODE,UDCODE, - 0x8c7e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9ce, - 0xe9cd,0xe9cc,UDCODE,UDCODE,0x88b1,0xfc46,UDCODE,UDCODE,UDCODE, - 0xe9d8,UDCODE,0xe9d4,UDCODE,0xe9d5,0xe9d1,0xe9d7,UDCODE,0xe9d3, - 0x8a82,UDCODE,UDCODE,0x986b,UDCODE,0xe9d6,0xe9d2,0xe9d0,0xe9cf, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9da,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe9dd,UDCODE,UDCODE,0xe9dc,0xe9db,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9568,0xe9d9,0x88f1,0xe9de, - UDCODE,0xe9e0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8a8f, - 0xe9cb,0x8956,UDCODE,UDCODE,0xe9e2,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,0xe9e1,0xe9df,0x924c,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9690,UDCODE,UDCODE, - UDCODE,UDCODE,0x97d8,UDCODE,UDCODE,0xe9e3,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xe9e4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xe9e5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9e6,UDCODE,0xe9e7, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0x92b9,UDCODE,0xe9e8,UDCODE,0x94b5,UDCODE,0xe9ed,0xe9e9,UDCODE, - UDCODE,UDCODE,0xe9ea,UDCODE,UDCODE,0x9650,0x96c2,UDCODE,0x93ce, - 0xe9ee,UDCODE,UDCODE,0xe9ef,0x93bc,0xe9ec,0xe9eb,UDCODE,UDCODE, - UDCODE,UDCODE,0x89a8,UDCODE,UDCODE,UDCODE,0xe9f7,UDCODE,UDCODE, - 0xe9f6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8995,UDCODE,UDCODE, - UDCODE,0xe9f4,UDCODE,UDCODE,UDCODE,0xe9f3,UDCODE,UDCODE,0xe9f1, - UDCODE,0x8a9b,UDCODE,0xe9f0,0x8eb0,0x89a7,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x8d83,UDCODE,UDCODE,0xe9fa,0xe9f9,UDCODE,0xe9f8, - UDCODE,UDCODE,0xe9f5,UDCODE,0xe9fb,UDCODE,0xe9fc,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea44,0xea43,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea45,UDCODE,UDCODE,0x894c, - 0xea40,0xea41,UDCODE,0x8d94,0x96b7,UDCODE,UDCODE,0xea42,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfc48,0x9651,UDCODE,UDCODE, - 0xea4a,0xfc47,UDCODE,0xea46,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xea4b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea48,UDCODE,0xea47, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c7b,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea4c,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea4d, - UDCODE,UDCODE,UDCODE,UDCODE,0xea4e,UDCODE,0xea49,UDCODE,UDCODE, - UDCODE,0xe9f2,UDCODE,UDCODE,0xea4f,UDCODE,0x92df,UDCODE,UDCODE, - UDCODE,0xea53,UDCODE,0xea54,0xea52,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xea51,0xea57,UDCODE,0xea50,UDCODE,0xea55,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea56,UDCODE,UDCODE, - UDCODE,0xea59,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea58,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xea5b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - 0xea5c,UDCODE,0xea5d,UDCODE,UDCODE,0x9868,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xea5a,0x91e9,0x8deb,UDCODE,UDCODE,0xea5e,0xfc4a, - 0xea5f,0xea60,UDCODE,UDCODE,0xea61,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xea62,UDCODE,UDCODE,0x8cb2,0xea63,UDCODE,UDCODE,UDCODE, - 0xea64,UDCODE,0x8ead,UDCODE,0xea65,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xea66,UDCODE,UDCODE,0xea67,0xea68,UDCODE,UDCODE, - UDCODE,UDCODE,0xea6b,0xea69,0x985b,UDCODE,0xea6a,UDCODE,0x97ed, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea6c,UDCODE,0x97d9,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xea6d,0x949e,UDCODE,UDCODE,0xea6e, - 0xea70,UDCODE,UDCODE,0xea71,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea6f,0x8d8d,0x96cb,0x9683, - 0x9bf5,UDCODE,0x9f80,0x969b,UDCODE,UDCODE,UDCODE,UDCODE,0x89a9, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea73,0x8b6f, - 0xea74,0xea75,0xea76,0xfc4b,0x8d95,UDCODE,0xea77,UDCODE,UDCODE, - UDCODE,0xe0d2,0x96d9,UDCODE,0x91e1,0xea78,0xea7a,0xea79,UDCODE, - 0xea7b,UDCODE,UDCODE,UDCODE,UDCODE,0xea7c,UDCODE,UDCODE,0xea7d, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea7e,UDCODE,UDCODE, - UDCODE,UDCODE,0xea80,UDCODE,0xea81,0xea82,UDCODE,0xea83,UDCODE, - 0xea84,0xea85,0xea86,0xea87,0xea88,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9343,UDCODE,UDCODE,UDCODE,UDCODE,0x8cdb,UDCODE,0xea8a, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x916c,0xea8b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,0xea8c,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x9540,UDCODE,UDCODE,0xea8d,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea8e,0xe256, - UDCODE,UDCODE,0xe6d8,0xe8eb,UDCODE,UDCODE,0xea8f,UDCODE,0xea90, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xea92,0xea93,0xea94,0x97ee,0xea91,UDCODE,UDCODE,0xea95, - 0xea96,UDCODE,UDCODE,0xea98,UDCODE,0xea97,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0xea9a,UDCODE,UDCODE,UDCODE,0xea9b,0xea99,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,0x97b4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0xea9c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea9d, - 0xe273,UDCODE,UDCODE,0xea9e,0xf040,0xf041,0xf042,0xf043,0xf044, - 0xf045,0xf046,0xf047,0xf048,0xf049,0xf04a,0xf04b,0xf04c,0xf04d, - 0xf04e,0xf04f,0xf050,0xf051,0xf052,0xf053,0xf054,0xf055,0xf056, - 0xf057,0xf058,0xf059,0xf05a,0xf05b,0xf05c,0xf05d,0xf05e,0xf05f, - 0xf060,0xf061,0xf062,0xf063,0xf064,0xf065,0xf066,0xf067,0xf068, - 0xf069,0xf06a,0xf06b,0xf06c,0xf06d,0xf06e,0xf06f,0xf070,0xf071, - 0xf072,0xf073,0xf074,0xf075,0xf076,0xf077,0xf078,0xf079,0xf07a, - 0xf07b,0xf07c,0xf07d,0xf07e,0xf080,0xf081,0xf082,0xf083,0xf084, - 0xf085,0xf086,0xf087,0xf088,0xf089,0xf08a,0xf08b,0xf08c,0xf08d, - 0xf08e,0xf08f,0xf090,0xf091,0xf092,0xf093,0xf094,0xf095,0xf096, - 0xf097,0xf098,0xf099,0xf09a,0xf09b,0xf09c,0xf09d,0xf09e,0xf09f, - 0xf0a0,0xf0a1,0xf0a2,0xf0a3,0xf0a4,0xf0a5,0xf0a6,0xf0a7,0xf0a8, - 0xf0a9,0xf0aa,0xf0ab,0xf0ac,0xf0ad,0xf0ae,0xf0af,0xf0b0,0xf0b1, - 0xf0b2,0xf0b3,0xf0b4,0xf0b5,0xf0b6,0xf0b7,0xf0b8,0xf0b9,0xf0ba, - 0xf0bb,0xf0bc,0xf0bd,0xf0be,0xf0bf,0xf0c0,0xf0c1,0xf0c2,0xf0c3, - 0xf0c4,0xf0c5,0xf0c6,0xf0c7,0xf0c8,0xf0c9,0xf0ca,0xf0cb,0xf0cc, - 0xf0cd,0xf0ce,0xf0cf,0xf0d0,0xf0d1,0xf0d2,0xf0d3,0xf0d4,0xf0d5, - 0xf0d6,0xf0d7,0xf0d8,0xf0d9,0xf0da,0xf0db,0xf0dc,0xf0dd,0xf0de, - 0xf0df,0xf0e0,0xf0e1,0xf0e2,0xf0e3,0xf0e4,0xf0e5,0xf0e6,0xf0e7, - 0xf0e8,0xf0e9,0xf0ea,0xf0eb,0xf0ec,0xf0ed,0xf0ee,0xf0ef,0xf0f0, - 0xf0f1,0xf0f2,0xf0f3,0xf0f4,0xf0f5,0xf0f6,0xf0f7,0xf0f8,0xf0f9, - 0xf0fa,0xf0fb,0xf0fc,0xf140,0xf141,0xf142,0xf143,0xf144,0xf145, - 0xf146,0xf147,0xf148,0xf149,0xf14a,0xf14b,0xf14c,0xf14d,0xf14e, - 0xf14f,0xf150,0xf151,0xf152,0xf153,0xf154,0xf155,0xf156,0xf157, - 0xf158,0xf159,0xf15a,0xf15b,0xf15c,0xf15d,0xf15e,0xf15f,0xf160, - 0xf161,0xf162,0xf163,0xf164,0xf165,0xf166,0xf167,0xf168,0xf169, - 0xf16a,0xf16b,0xf16c,0xf16d,0xf16e,0xf16f,0xf170,0xf171,0xf172, - 0xf173,0xf174,0xf175,0xf176,0xf177,0xf178,0xf179,0xf17a,0xf17b, - 0xf17c,0xf17d,0xf17e,0xf180,0xf181,0xf182,0xf183,0xf184,0xf185, - 0xf186,0xf187,0xf188,0xf189,0xf18a,0xf18b,0xf18c,0xf18d,0xf18e, - 0xf18f,0xf190,0xf191,0xf192,0xf193,0xf194,0xf195,0xf196,0xf197, - 0xf198,0xf199,0xf19a,0xf19b,0xf19c,0xf19d,0xf19e,0xf19f,0xf1a0, - 0xf1a1,0xf1a2,0xf1a3,0xf1a4,0xf1a5,0xf1a6,0xf1a7,0xf1a8,0xf1a9, - 0xf1aa,0xf1ab,0xf1ac,0xf1ad,0xf1ae,0xf1af,0xf1b0,0xf1b1,0xf1b2, - 0xf1b3,0xf1b4,0xf1b5,0xf1b6,0xf1b7,0xf1b8,0xf1b9,0xf1ba,0xf1bb, - 0xf1bc,0xf1bd,0xf1be,0xf1bf,0xf1c0,0xf1c1,0xf1c2,0xf1c3,0xf1c4, - 0xf1c5,0xf1c6,0xf1c7,0xf1c8,0xf1c9,0xf1ca,0xf1cb,0xf1cc,0xf1cd, - 0xf1ce,0xf1cf,0xf1d0,0xf1d1,0xf1d2,0xf1d3,0xf1d4,0xf1d5,0xf1d6, - 0xf1d7,0xf1d8,0xf1d9,0xf1da,0xf1db,0xf1dc,0xf1dd,0xf1de,0xf1df, - 0xf1e0,0xf1e1,0xf1e2,0xf1e3,0xf1e4,0xf1e5,0xf1e6,0xf1e7,0xf1e8, - 0xf1e9,0xf1ea,0xf1eb,0xf1ec,0xf1ed,0xf1ee,0xf1ef,0xf1f0,0xf1f1, - 0xf1f2,0xf1f3,0xf1f4,0xf1f5,0xf1f6,0xf1f7,0xf1f8,0xf1f9,0xf1fa, - 0xf1fb,0xf1fc,0xf240,0xf241,0xf242,0xf243,0xf244,0xf245,0xf246, - 0xf247,0xf248,0xf249,0xf24a,0xf24b,0xf24c,0xf24d,0xf24e,0xf24f, - 0xf250,0xf251,0xf252,0xf253,0xf254,0xf255,0xf256,0xf257,0xf258, - 0xf259,0xf25a,0xf25b,0xf25c,0xf25d,0xf25e,0xf25f,0xf260,0xf261, - 0xf262,0xf263,0xf264,0xf265,0xf266,0xf267,0xf268,0xf269,0xf26a, - 0xf26b,0xf26c,0xf26d,0xf26e,0xf26f,0xf270,0xf271,0xf272,0xf273, - 0xf274,0xf275,0xf276,0xf277,0xf278,0xf279,0xf27a,0xf27b,0xf27c, - 0xf27d,0xf27e,0xf280,0xf281,0xf282,0xf283,0xf284,0xf285,0xf286, - 0xf287,0xf288,0xf289,0xf28a,0xf28b,0xf28c,0xf28d,0xf28e,0xf28f, - 0xf290,0xf291,0xf292,0xf293,0xf294,0xf295,0xf296,0xf297,0xf298, - 0xf299,0xf29a,0xf29b,0xf29c,0xf29d,0xf29e,0xf29f,0xf2a0,0xf2a1, - 0xf2a2,0xf2a3,0xf2a4,0xf2a5,0xf2a6,0xf2a7,0xf2a8,0xf2a9,0xf2aa, - 0xf2ab,0xf2ac,0xf2ad,0xf2ae,0xf2af,0xf2b0,0xf2b1,0xf2b2,0xf2b3, - 0xf2b4,0xf2b5,0xf2b6,0xf2b7,0xf2b8,0xf2b9,0xf2ba,0xf2bb,0xf2bc, - 0xf2bd,0xf2be,0xf2bf,0xf2c0,0xf2c1,0xf2c2,0xf2c3,0xf2c4,0xf2c5, - 0xf2c6,0xf2c7,0xf2c8,0xf2c9,0xf2ca,0xf2cb,0xf2cc,0xf2cd,0xf2ce, - 0xf2cf,0xf2d0,0xf2d1,0xf2d2,0xf2d3,0xf2d4,0xf2d5,0xf2d6,0xf2d7, - 0xf2d8,0xf2d9,0xf2da,0xf2db,0xf2dc,0xf2dd,0xf2de,0xf2df,0xf2e0, - 0xf2e1,0xf2e2,0xf2e3,0xf2e4,0xf2e5,0xf2e6,0xf2e7,0xf2e8,0xf2e9, - 0xf2ea,0xf2eb,0xf2ec,0xf2ed,0xf2ee,0xf2ef,0xf2f0,0xf2f1,0xf2f2, - 0xf2f3,0xf2f4,0xf2f5,0xf2f6,0xf2f7,0xf2f8,0xf2f9,0xf2fa,0xf2fb, - 0xf2fc,0xf340,0xf341,0xf342,0xf343,0xf344,0xf345,0xf346,0xf347, - 0xf348,0xf349,0xf34a,0xf34b,0xf34c,0xf34d,0xf34e,0xf34f,0xf350, - 0xf351,0xf352,0xf353,0xf354,0xf355,0xf356,0xf357,0xf358,0xf359, - 0xf35a,0xf35b,0xf35c,0xf35d,0xf35e,0xf35f,0xf360,0xf361,0xf362, - 0xf363,0xf364,0xf365,0xf366,0xf367,0xf368,0xf369,0xf36a,0xf36b, - 0xf36c,0xf36d,0xf36e,0xf36f,0xf370,0xf371,0xf372,0xf373,0xf374, - 0xf375,0xf376,0xf377,0xf378,0xf379,0xf37a,0xf37b,0xf37c,0xf37d, - 0xf37e,0xf380,0xf381,0xf382,0xf383,0xf384,0xf385,0xf386,0xf387, - 0xf388,0xf389,0xf38a,0xf38b,0xf38c,0xf38d,0xf38e,0xf38f,0xf390, - 0xf391,0xf392,0xf393,0xf394,0xf395,0xf396,0xf397,0xf398,0xf399, - 0xf39a,0xf39b,0xf39c,0xf39d,0xf39e,0xf39f,0xf3a0,0xf3a1,0xf3a2, - 0xf3a3,0xf3a4,0xf3a5,0xf3a6,0xf3a7,0xf3a8,0xf3a9,0xf3aa,0xf3ab, - 0xf3ac,0xf3ad,0xf3ae,0xf3af,0xf3b0,0xf3b1,0xf3b2,0xf3b3,0xf3b4, - 0xf3b5,0xf3b6,0xf3b7,0xf3b8,0xf3b9,0xf3ba,0xf3bb,0xf3bc,0xf3bd, - 0xf3be,0xf3bf,0xf3c0,0xf3c1,0xf3c2,0xf3c3,0xf3c4,0xf3c5,0xf3c6, - 0xf3c7,0xf3c8,0xf3c9,0xf3ca,0xf3cb,0xf3cc,0xf3cd,0xf3ce,0xf3cf, - 0xf3d0,0xf3d1,0xf3d2,0xf3d3,0xf3d4,0xf3d5,0xf3d6,0xf3d7,0xf3d8, - 0xf3d9,0xf3da,0xf3db,0xf3dc,0xf3dd,0xf3de,0xf3df,0xf3e0,0xf3e1, - 0xf3e2,0xf3e3,0xf3e4,0xf3e5,0xf3e6,0xf3e7,0xf3e8,0xf3e9,0xf3ea, - 0xf3eb,0xf3ec,0xf3ed,0xf3ee,0xf3ef,0xf3f0,0xf3f1,0xf3f2,0xf3f3, - 0xf3f4,0xf3f5,0xf3f6,0xf3f7,0xf3f8,0xf3f9,0xf3fa,0xf3fb,0xf3fc, - 0xf440,0xf441,0xf442,0xf443,0xf444,0xf445,0xf446,0xf447,0xf448, - 0xf449,0xf44a,0xf44b,0xf44c,0xf44d,0xf44e,0xf44f,0xf450,0xf451, - 0xf452,0xf453,0xf454,0xf455,0xf456,0xf457,0xf458,0xf459,0xf45a, - 0xf45b,0xf45c,0xf45d,0xf45e,0xf45f,0xf460,0xf461,0xf462,0xf463, - 0xf464,0xf465,0xf466,0xf467,0xf468,0xf469,0xf46a,0xf46b,0xf46c, - 0xf46d,0xf46e,0xf46f,0xf470,0xf471,0xf472,0xf473,0xf474,0xf475, - 0xf476,0xf477,0xf478,0xf479,0xf47a,0xf47b,0xf47c,0xf47d,0xf47e, - 0xf480,0xf481,0xf482,0xf483,0xf484,0xf485,0xf486,0xf487,0xf488, - 0xf489,0xf48a,0xf48b,0xf48c,0xf48d,0xf48e,0xf48f,0xf490,0xf491, - 0xf492,0xf493,0xf494,0xf495,0xf496,0xf497,0xf498,0xf499,0xf49a, - 0xf49b,0xf49c,0xf49d,0xf49e,0xf49f,0xf4a0,0xf4a1,0xf4a2,0xf4a3, - 0xf4a4,0xf4a5,0xf4a6,0xf4a7,0xf4a8,0xf4a9,0xf4aa,0xf4ab,0xf4ac, - 0xf4ad,0xf4ae,0xf4af,0xf4b0,0xf4b1,0xf4b2,0xf4b3,0xf4b4,0xf4b5, - 0xf4b6,0xf4b7,0xf4b8,0xf4b9,0xf4ba,0xf4bb,0xf4bc,0xf4bd,0xf4be, - 0xf4bf,0xf4c0,0xf4c1,0xf4c2,0xf4c3,0xf4c4,0xf4c5,0xf4c6,0xf4c7, - 0xf4c8,0xf4c9,0xf4ca,0xf4cb,0xf4cc,0xf4cd,0xf4ce,0xf4cf,0xf4d0, - 0xf4d1,0xf4d2,0xf4d3,0xf4d4,0xf4d5,0xf4d6,0xf4d7,0xf4d8,0xf4d9, - 0xf4da,0xf4db,0xf4dc,0xf4dd,0xf4de,0xf4df,0xf4e0,0xf4e1,0xf4e2, - 0xf4e3,0xf4e4,0xf4e5,0xf4e6,0xf4e7,0xf4e8,0xf4e9,0xf4ea,0xf4eb, - 0xf4ec,0xf4ed,0xf4ee,0xf4ef,0xf4f0,0xf4f1,0xf4f2,0xf4f3,0xf4f4, - 0xf4f5,0xf4f6,0xf4f7,0xf4f8,0xf4f9,0xf4fa,0xf4fb,0xf4fc,0xf540, - 0xf541,0xf542,0xf543,0xf544,0xf545,0xf546,0xf547,0xf548,0xf549, - 0xf54a,0xf54b,0xf54c,0xf54d,0xf54e,0xf54f,0xf550,0xf551,0xf552, - 0xf553,0xf554,0xf555,0xf556,0xf557,0xf558,0xf559,0xf55a,0xf55b, - 0xf55c,0xf55d,0xf55e,0xf55f,0xf560,0xf561,0xf562,0xf563,0xf564, - 0xf565,0xf566,0xf567,0xf568,0xf569,0xf56a,0xf56b,0xf56c,0xf56d, - 0xf56e,0xf56f,0xf570,0xf571,0xf572,0xf573,0xf574,0xf575,0xf576, - 0xf577,0xf578,0xf579,0xf57a,0xf57b,0xf57c,0xf57d,0xf57e,0xf580, - 0xf581,0xf582,0xf583,0xf584,0xf585,0xf586,0xf587,0xf588,0xf589, - 0xf58a,0xf58b,0xf58c,0xf58d,0xf58e,0xf58f,0xf590,0xf591,0xf592, - 0xf593,0xf594,0xf595,0xf596,0xf597,0xf598,0xf599,0xf59a,0xf59b, - 0xf59c,0xf59d,0xf59e,0xf59f,0xf5a0,0xf5a1,0xf5a2,0xf5a3,0xf5a4, - 0xf5a5,0xf5a6,0xf5a7,0xf5a8,0xf5a9,0xf5aa,0xf5ab,0xf5ac,0xf5ad, - 0xf5ae,0xf5af,0xf5b0,0xf5b1,0xf5b2,0xf5b3,0xf5b4,0xf5b5,0xf5b6, - 0xf5b7,0xf5b8,0xf5b9,0xf5ba,0xf5bb,0xf5bc,0xf5bd,0xf5be,0xf5bf, - 0xf5c0,0xf5c1,0xf5c2,0xf5c3,0xf5c4,0xf5c5,0xf5c6,0xf5c7,0xf5c8, - 0xf5c9,0xf5ca,0xf5cb,0xf5cc,0xf5cd,0xf5ce,0xf5cf,0xf5d0,0xf5d1, - 0xf5d2,0xf5d3,0xf5d4,0xf5d5,0xf5d6,0xf5d7,0xf5d8,0xf5d9,0xf5da, - 0xf5db,0xf5dc,0xf5dd,0xf5de,0xf5df,0xf5e0,0xf5e1,0xf5e2,0xf5e3, - 0xf5e4,0xf5e5,0xf5e6,0xf5e7,0xf5e8,0xf5e9,0xf5ea,0xf5eb,0xf5ec, - 0xf5ed,0xf5ee,0xf5ef,0xf5f0,0xf5f1,0xf5f2,0xf5f3,0xf5f4,0xf5f5, - 0xf5f6,0xf5f7,0xf5f8,0xf5f9,0xf5fa,0xf5fb,0xf5fc,0xf640,0xf641, - 0xf642,0xf643,0xf644,0xf645,0xf646,0xf647,0xf648,0xf649,0xf64a, - 0xf64b,0xf64c,0xf64d,0xf64e,0xf64f,0xf650,0xf651,0xf652,0xf653, - 0xf654,0xf655,0xf656,0xf657,0xf658,0xf659,0xf65a,0xf65b,0xf65c, - 0xf65d,0xf65e,0xf65f,0xf660,0xf661,0xf662,0xf663,0xf664,0xf665, - 0xf666,0xf667,0xf668,0xf669,0xf66a,0xf66b,0xf66c,0xf66d,0xf66e, - 0xf66f,0xf670,0xf671,0xf672,0xf673,0xf674,0xf675,0xf676,0xf677, - 0xf678,0xf679,0xf67a,0xf67b,0xf67c,0xf67d,0xf67e,0xf680,0xf681, - 0xf682,0xf683,0xf684,0xf685,0xf686,0xf687,0xf688,0xf689,0xf68a, - 0xf68b,0xf68c,0xf68d,0xf68e,0xf68f,0xf690,0xf691,0xf692,0xf693, - 0xf694,0xf695,0xf696,0xf697,0xf698,0xf699,0xf69a,0xf69b,0xf69c, - 0xf69d,0xf69e,0xf69f,0xf6a0,0xf6a1,0xf6a2,0xf6a3,0xf6a4,0xf6a5, - 0xf6a6,0xf6a7,0xf6a8,0xf6a9,0xf6aa,0xf6ab,0xf6ac,0xf6ad,0xf6ae, - 0xf6af,0xf6b0,0xf6b1,0xf6b2,0xf6b3,0xf6b4,0xf6b5,0xf6b6,0xf6b7, - 0xf6b8,0xf6b9,0xf6ba,0xf6bb,0xf6bc,0xf6bd,0xf6be,0xf6bf,0xf6c0, - 0xf6c1,0xf6c2,0xf6c3,0xf6c4,0xf6c5,0xf6c6,0xf6c7,0xf6c8,0xf6c9, - 0xf6ca,0xf6cb,0xf6cc,0xf6cd,0xf6ce,0xf6cf,0xf6d0,0xf6d1,0xf6d2, - 0xf6d3,0xf6d4,0xf6d5,0xf6d6,0xf6d7,0xf6d8,0xf6d9,0xf6da,0xf6db, - 0xf6dc,0xf6dd,0xf6de,0xf6df,0xf6e0,0xf6e1,0xf6e2,0xf6e3,0xf6e4, - 0xf6e5,0xf6e6,0xf6e7,0xf6e8,0xf6e9,0xf6ea,0xf6eb,0xf6ec,0xf6ed, - 0xf6ee,0xf6ef,0xf6f0,0xf6f1,0xf6f2,0xf6f3,0xf6f4,0xf6f5,0xf6f6, - 0xf6f7,0xf6f8,0xf6f9,0xf6fa,0xf6fb,0xf6fc,0xf740,0xf741,0xf742, - 0xf743,0xf744,0xf745,0xf746,0xf747,0xf748,0xf749,0xf74a,0xf74b, - 0xf74c,0xf74d,0xf74e,0xf74f,0xf750,0xf751,0xf752,0xf753,0xf754, - 0xf755,0xf756,0xf757,0xf758,0xf759,0xf75a,0xf75b,0xf75c,0xf75d, - 0xf75e,0xf75f,0xf760,0xf761,0xf762,0xf763,0xf764,0xf765,0xf766, - 0xf767,0xf768,0xf769,0xf76a,0xf76b,0xf76c,0xf76d,0xf76e,0xf76f, - 0xf770,0xf771,0xf772,0xf773,0xf774,0xf775,0xf776,0xf777,0xf778, - 0xf779,0xf77a,0xf77b,0xf77c,0xf77d,0xf77e,0xf780,0xf781,0xf782, - 0xf783,0xf784,0xf785,0xf786,0xf787,0xf788,0xf789,0xf78a,0xf78b, - 0xf78c,0xf78d,0xf78e,0xf78f,0xf790,0xf791,0xf792,0xf793,0xf794, - 0xf795,0xf796,0xf797,0xf798,0xf799,0xf79a,0xf79b,0xf79c,0xf79d, - 0xf79e,0xf79f,0xf7a0,0xf7a1,0xf7a2,0xf7a3,0xf7a4,0xf7a5,0xf7a6, - 0xf7a7,0xf7a8,0xf7a9,0xf7aa,0xf7ab,0xf7ac,0xf7ad,0xf7ae,0xf7af, - 0xf7b0,0xf7b1,0xf7b2,0xf7b3,0xf7b4,0xf7b5,0xf7b6,0xf7b7,0xf7b8, - 0xf7b9,0xf7ba,0xf7bb,0xf7bc,0xf7bd,0xf7be,0xf7bf,0xf7c0,0xf7c1, - 0xf7c2,0xf7c3,0xf7c4,0xf7c5,0xf7c6,0xf7c7,0xf7c8,0xf7c9,0xf7ca, - 0xf7cb,0xf7cc,0xf7cd,0xf7ce,0xf7cf,0xf7d0,0xf7d1,0xf7d2,0xf7d3, - 0xf7d4,0xf7d5,0xf7d6,0xf7d7,0xf7d8,0xf7d9,0xf7da,0xf7db,0xf7dc, - 0xf7dd,0xf7de,0xf7df,0xf7e0,0xf7e1,0xf7e2,0xf7e3,0xf7e4,0xf7e5, - 0xf7e6,0xf7e7,0xf7e8,0xf7e9,0xf7ea,0xf7eb,0xf7ec,0xf7ed,0xf7ee, - 0xf7ef,0xf7f0,0xf7f1,0xf7f2,0xf7f3,0xf7f4,0xf7f5,0xf7f6,0xf7f7, - 0xf7f8,0xf7f9,0xf7fa,0xf7fb,0xf7fc,0xf840,0xf841,0xf842,0xf843, - 0xf844,0xf845,0xf846,0xf847,0xf848,0xf849,0xf84a,0xf84b,0xf84c, - 0xf84d,0xf84e,0xf84f,0xf850,0xf851,0xf852,0xf853,0xf854,0xf855, - 0xf856,0xf857,0xf858,0xf859,0xf85a,0xf85b,0xf85c,0xf85d,0xf85e, - 0xf85f,0xf860,0xf861,0xf862,0xf863,0xf864,0xf865,0xf866,0xf867, - 0xf868,0xf869,0xf86a,0xf86b,0xf86c,0xf86d,0xf86e,0xf86f,0xf870, - 0xf871,0xf872,0xf873,0xf874,0xf875,0xf876,0xf877,0xf878,0xf879, - 0xf87a,0xf87b,0xf87c,0xf87d,0xf87e,0xf880,0xf881,0xf882,0xf883, - 0xf884,0xf885,0xf886,0xf887,0xf888,0xf889,0xf88a,0xf88b,0xf88c, - 0xf88d,0xf88e,0xf88f,0xf890,0xf891,0xf892,0xf893,0xf894,0xf895, - 0xf896,0xf897,0xf898,0xf899,0xf89a,0xf89b,0xf89c,0xf89d,0xf89e, - 0xf89f,0xf8a0,0xf8a1,0xf8a2,0xf8a3,0xf8a4,0xf8a5,0xf8a6,0xf8a7, - 0xf8a8,0xf8a9,0xf8aa,0xf8ab,0xf8ac,0xf8ad,0xf8ae,0xf8af,0xf8b0, - 0xf8b1,0xf8b2,0xf8b3,0xf8b4,0xf8b5,0xf8b6,0xf8b7,0xf8b8,0xf8b9, - 0xf8ba,0xf8bb,0xf8bc,0xf8bd,0xf8be,0xf8bf,0xf8c0,0xf8c1,0xf8c2, - 0xf8c3,0xf8c4,0xf8c5,0xf8c6,0xf8c7,0xf8c8,0xf8c9,0xf8ca,0xf8cb, - 0xf8cc,0xf8cd,0xf8ce,0xf8cf,0xf8d0,0xf8d1,0xf8d2,0xf8d3,0xf8d4, - 0xf8d5,0xf8d6,0xf8d7,0xf8d8,0xf8d9,0xf8da,0xf8db,0xf8dc,0xf8dd, - 0xf8de,0xf8df,0xf8e0,0xf8e1,0xf8e2,0xf8e3,0xf8e4,0xf8e5,0xf8e6, - 0xf8e7,0xf8e8,0xf8e9,0xf8ea,0xf8eb,0xf8ec,0xf8ed,0xf8ee,0xf8ef, - 0xf8f0,0xf8f1,0xf8f2,0xf8f3,0xf8f4,0xf8f5,0xf8f6,0xf8f7,0xf8f8, - 0xf8f9,0xf8fa,0xf8fb,0xf8fc,0xf940,0xf941,0xf942,0xf943,0xf944, - 0xf945,0xf946,0xf947,0xf948,0xf949,0xf94a,0xf94b,0xf94c,0xf94d, - 0xf94e,0xf94f,0xf950,0xf951,0xf952,0xf953,0xf954,0xf955,0xf956, - 0xf957,0xf958,0xf959,0xf95a,0xf95b,0xf95c,0xf95d,0xf95e,0xf95f, - 0xf960,0xf961,0xf962,0xf963,0xf964,0xf965,0xf966,0xf967,0xf968, - 0xf969,0xf96a,0xf96b,0xf96c,0xf96d,0xf96e,0xf96f,0xf970,0xf971, - 0xf972,0xf973,0xf974,0xf975,0xf976,0xf977,0xf978,0xf979,0xf97a, - 0xf97b,0xf97c,0xf97d,0xf97e,0xf980,0xf981,0xf982,0xf983,0xf984, - 0xf985,0xf986,0xf987,0xf988,0xf989,0xf98a,0xf98b,0xf98c,0xf98d, - 0xf98e,0xf98f,0xf990,0xf991,0xf992,0xf993,0xf994,0xf995,0xf996, - 0xf997,0xf998,0xf999,0xf99a,0xf99b,0xf99c,0xf99d,0xf99e,0xf99f, - 0xf9a0,0xf9a1,0xf9a2,0xf9a3,0xf9a4,0xf9a5,0xf9a6,0xf9a7,0xf9a8, - 0xf9a9,0xf9aa,0xf9ab,0xf9ac,0xf9ad,0xf9ae,0xf9af,0xf9b0,0xf9b1, - 0xf9b2,0xf9b3,0xf9b4,0xf9b5,0xf9b6,0xf9b7,0xf9b8,0xf9b9,0xf9ba, - 0xf9bb,0xf9bc,0xf9bd,0xf9be,0xf9bf,0xf9c0,0xf9c1,0xf9c2,0xf9c3, - 0xf9c4,0xf9c5,0xf9c6,0xf9c7,0xf9c8,0xf9c9,0xf9ca,0xf9cb,0xf9cc, - 0xf9cd,0xf9ce,0xf9cf,0xf9d0,0xf9d1,0xf9d2,0xf9d3,0xf9d4,0xf9d5, - 0xf9d6,0xf9d7,0xf9d8,0xf9d9,0xf9da,0xf9db,0xf9dc,0xf9dd,0xf9de, - 0xf9df,0xf9e0,0xf9e1,0xf9e2,0xf9e3,0xf9e4,0xf9e5,0xf9e6,0xf9e7, - 0xf9e8,0xf9e9,0xf9ea,0xf9eb,0xf9ec,0xf9ed,0xf9ee,0xf9ef,0xf9f0, - 0xf9f1,0xf9f2,0xf9f3,0xf9f4,0xf9f5,0xf9f6,0xf9f7,0xf9f8,0xf9f9, - 0xf9fa,0xf9fb,0xf9fc,0x00a0,0x00fd,0x00fe,0x00ff,0xfae0,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbe9,0xfa90,0xfa9b, - 0xfa9c,0xfab1,0xfad8,0xfae8,0xfaea,0xfb58,0xfb5e,0xfb75,0xfb7d, - 0xfb7e,0xfb80,0xfb82,0xfb86,0xfb89,0xfb92,0xfb9d,0xfb9f,0xfba0, - 0xfba9,0xfbb1,0xfbb3,0xfbb4,0xfbb7,0xfbd3,0xfbda,0xfbea,0xfbf6, - 0xfbf7,0xfbf9,0xfc49,0x8149,0xfa57,0x8194,0x8190,0x8193,0x8195, - 0xfa56,0x8169,0x816a,0x8196,0x817b,0x8143,0x817c,0x8144,0x815e, - 0x824f,0x8250,0x8251,0x8252,0x8253,0x8254,0x8255,0x8256,0x8257, - 0x8258,0x8146,0x8147,0x8183,0x8181,0x8184,0x8148,0x8197,0x8260, - 0x8261,0x8262,0x8263,0x8264,0x8265,0x8266,0x8267,0x8268,0x8269, - 0x826a,0x826b,0x826c,0x826d,0x826e,0x826f,0x8270,0x8271,0x8272, - 0x8273,0x8274,0x8275,0x8276,0x8277,0x8278,0x8279,0x816d,0x815f, - 0x816e,0x814f,0x8151,0x814d,0x8281,0x8282,0x8283,0x8284,0x8285, - 0x8286,0x8287,0x8288,0x8289,0x828a,0x828b,0x828c,0x828d,0x828e, - 0x828f,0x8290,0x8291,0x8292,0x8293,0x8294,0x8295,0x8296,0x8297, - 0x8298,0x8299,0x829a,0x816f,0x8162,0x8170,0x8160,UDCODE,UDCODE, - 0x00a1,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,0x00a8,0x00a9, - 0x00aa,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,0x00b0,0x00b1,0x00b2, - 0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,0x00b8,0x00b9,0x00ba,0x00bb, - 0x00bc,0x00bd,0x00be,0x00bf,0x00c0,0x00c1,0x00c2,0x00c3,0x00c4, - 0x00c5,0x00c6,0x00c7,0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd, - 0x00ce,0x00cf,0x00d0,0x00d1,0x00d2,0x00d3,0x00d4,0x00d5,0x00d6, - 0x00d7,0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x00dd,0x00de,0x00df, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, - UDCODE,0x8191,0x8192,0x81ca,0x8150,0xfa55,0x818f -}; - -static UINT ucs2len(const UINT16 *lpString); -static UINT ucs2tosjis(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cbInput); -static UINT utf8tosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cbInput); - -/** - * Maps a UTF-16 string to a S-SJIS string - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cbInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -UINT codecnv_ucs2tosjis(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cbInput) -{ - UINT nLength; - - if (lpInput == NULL) - { - return 0; - } - - if (cchOutput == 0) - { - lpOutput = NULL; - cchOutput = (UINT)-1; - } - - if (cbInput != (UINT)-1) - { - // Binary mode - return ucs2tosjis(lpOutput, cchOutput, lpInput, cbInput); - } - else - { - // String mode - nLength = ucs2tosjis(lpOutput, cchOutput - 1, lpInput, ucs2len(lpInput)); - if (lpOutput) - { - lpOutput[nLength] = '\0'; - } - return nLength + 1; - } -} - -/** - * Get the length of a string - * @param[in] lpString Null-terminated string - * @return the number of characters in lpString - */ -static UINT ucs2len(const UINT16 *lpString) -{ - const UINT16 *p = lpString; - while (*p != 0) - { - p++; - } - return (UINT)(p - lpString); -} - -/** - * Maps a UTF-16 string to a S-JIS string (inner) - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cbInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -static UINT ucs2tosjis(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cbInput) -{ - UINT nRemain; - UINT c; - UINT r; - - nRemain = cchOutput; - while ((cbInput > 0) && (nRemain > 0)) - { - c = *lpInput++; - cbInput--; - - r = s_level1[c >> 8]; - c = (c - r) & 0xff; - if (c < ((r >> 8) & 0x1ff)) - { - c = s_level2[(r >> 17) + c]; - } - else - { - c = UDCODE; - } - - if (c < 0x100) - { - nRemain--; - if (lpOutput) - { - *lpOutput++ = (char)c; - } - } - else - { - if (nRemain < 2) - { - break; - } - nRemain -= 2; - if (lpOutput) - { - *lpOutput++ = (char)(c >> 8); - *lpOutput++ = (char)(c >> 0); - } - } - } - return (UINT)(cchOutput - nRemain); -} - -/** - * Maps a UTF-8 string to a S-SJIS string - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cbInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -UINT codecnv_utf8tosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cbInput) -{ - UINT nLength; - - if (lpInput == NULL) - { - return 0; - } - - if (cchOutput == 0) - { - lpOutput = NULL; - cchOutput = (UINT)-1; - } - - if (cbInput != (UINT)-1) - { - // Binary mode - return utf8tosjis(lpOutput, cchOutput, lpInput, cbInput); - } - else - { - // String mode - nLength = utf8tosjis(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); - if (lpOutput) - { - lpOutput[nLength] = '\0'; - } - return nLength + 1; - } -} - -/** - * Maps a UTF-8 string to a S-JIS string (inner) - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cbInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -static UINT utf8tosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cbInput) -{ - UINT nRemain; - UINT c; - int nBits; - UINT r; - - nRemain = cchOutput; - while ((cbInput > 0) && (nRemain > 0)) - { - c = *lpInput++; - cbInput--; - - if (c & 0x80) - { - nBits = 0; - while ((nBits < 6) && (c & (0x80 >> nBits))) - { - nBits++; - } - - c &= (0x7f >> nBits); - nBits--; - - while ((nBits > 0) && (cbInput > 0) && (((*lpInput) & 0xc0) == 0x80)) - { - c = (c << 6) | ((*lpInput++) & 0x3f); - cbInput--; - nBits--; - } - - r = 0; - if (c < 0x10000) - { - r = s_level1[c >> 8]; - } - c = (c - r) & 0xff; - if (c < ((r >> 8) & 0x1ff)) - { - c = s_level2[(r >> 17) + c]; - } - else - { - c = UDCODE; - } - } - - if (c < 0x100) - { - nRemain--; - if (lpOutput) - { - *lpOutput++ = (char)c; - } - } - else - { - if (nRemain < 2) - { - break; - } - nRemain -= 2; - if (lpOutput) - { - *lpOutput++ = (char)(c >> 8); - *lpOutput++ = (char)(c >> 0); - } - } - } - return (UINT)(cchOutput - nRemain); -} +/** + * @file ucs2sjis.c + * @brief Implementation of converting UCS2 to S-JIS + */ + +#ifdef CODECNV_TEST +#include "compiler_base.h" +#else +#include +#endif +#include + +//! undefined code +#define UDCODE 0x003f + +//! 1st table +static const UINT32 s_level1[256] = +{ + 0x00010000,0x00000000,0x00000000,0x02003991,0x02725101,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x03142c10,0x036cd203,0x0510c000,0x06900112, + 0x06921460,0x06baf000,0x089a6b05,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x0970ff00,0x00000000,0x0b6e7831,0x0c5ecb03,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x0df4fd00,0x0fef0000,0x11eef705,0x13dcff00,0x15db0000,0x17dafb00, + 0x19d0ff01,0x1bcefb04,0x1dc4fa06,0x1fb8fd00,0x21b2fe00,0x23aefe02, + 0x25aafb01,0x27a0f709,0x298efd01,0x2b88f807,0x2d78fe02,0x2f74ff01, + 0x3172ee0e,0x334f0000,0x354f0000,0x374efa01,0x3942f906,0x3b34fc00, + 0x3d2d0000,0x3f2d0000,0x412cfa01,0x43210000,0x4520fa02,0x4714f004, + 0x48f4ec08,0x4accf904,0x4cbefb05,0x4eb4fe01,0x50b0fd01,0x52aafc04, + 0x54a2f806,0x5692f50a,0x587cf603,0x5a68ff01,0x5c66fe01,0x5e62fc01, + 0x605afc02,0x6252fb01,0x64490000,0x6648f602,0x6834ff00,0x6a32fc00, + 0x6c2a9c01,0x6d62c736,0x6ef0fe00,0x70ecfd02,0x72e6fb01,0x74dcfd01, + 0x76d6fd03,0x78d0ff00,0x7acefd02,0x7cc8ff00,0x7ec6fa05,0x80baf702, + 0x82a8ff00,0x84a69b00,0x85dcc737,0x876afc04,0x8962f708,0x8b50fb03, + 0x8d46fe00,0x8f42fe02,0x913efa06,0x9332f702,0x95207f03,0x961e6f77, + 0x96fce01c,0x98bd0000,0x9abcfe01,0x9cb8fd03,0x9eb2fb01,0xa0a8f006, + 0xa288f700,0xa476fb03,0xa66ce519,0xa8369a07,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0xa96b0000,0xab6b0000,0xad6b0000,0xaf6b0000, + 0xb16b0000,0xb36b0000,0xb56b0000,0xb76a5800,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000,0xb81a04f0,0xb822b429,0xb98a200e,0x00000000, + 0x00000000,0x00000000,0x00000000,0xb9cae501 +}; + +//! 2nd table +static const UINT32 s_level2[] = +{ + 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008, + 0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,0x0010,0x0011, + 0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001a, + 0x001b,0x001c,0x001d,0x001e,0x001f,0x0020,0x0021,0x0022,0x0023, + 0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002a,0x002b,0x002c, + 0x002d,0x002e,0x002f,0x0030,0x0031,0x0032,0x0033,0x0034,0x0035, + 0x0036,0x0037,0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e, + 0x003f,0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, + 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,0x0050, + 0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059, + 0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,0x0060,0x0061,0x0062, + 0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006a,0x006b, + 0x006c,0x006d,0x006e,0x006f,0x0070,0x0071,0x0072,0x0073,0x0074, + 0x0075,0x0076,0x0077,0x0078,0x0079,0x007a,0x007b,0x007c,0x007d, + 0x007e,0x007f,0x0080,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x0021, + 0x8191,0x8192,UDCODE,0x005c,0x007c,0x8198,0x814e,0x0063,0x0061, + 0x81e1,0x81ca,0x002d,0x0052,0x8150,0x818b,0x817d,0x0032,0x0033, + 0x814c,0x83ca,0x81f7,0x8145,0x8143,0x0031,0x006f,0x81e2,UDCODE, + UDCODE,UDCODE,UDCODE,0x0041,0x0041,0x0041,0x0041,0x0041,0x0041, + 0x0041,0x0043,0x0045,0x0045,0x0045,0x0045,0x0049,0x0049,0x0049, + 0x0049,0x0044,0x004e,0x004f,0x004f,0x004f,0x004f,0x004f,0x817e, + 0x004f,0x0055,0x0055,0x0055,0x0055,0x0059,0x0054,0x0073,0x0061, + 0x0061,0x0061,0x0061,0x0061,0x0061,0x0061,0x0063,0x0065,0x0065, + 0x0065,0x0065,0x0069,0x0069,0x0069,0x0069,0x0064,0x006e,0x006f, + 0x006f,0x006f,0x006f,0x006f,0x8180,0x006f,0x0075,0x0075,0x0075, + 0x0075,0x0079,0x0074,0x0079,0x839f,0x83a0,0x83a1,0x83a2,0x83a3, + 0x83a4,0x83a5,0x83a6,0x83a7,0x83a8,0x83a9,0x83aa,0x83ab,0x83ac, + 0x83ad,0x83ae,0x83af,UDCODE,0x83b0,0x83b1,0x83b2,0x83b3,0x83b4, + 0x83b5,0x83b6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x83bf,0x83c0,0x83c1,0x83c2,0x83c3,0x83c4,0x83c5,0x83c6,0x83c7, + 0x83c8,0x83c9,0x83ca,0x83cb,0x83cc,0x83cd,0x83ce,0x83cf,UDCODE, + 0x83d0,0x83d1,0x83d2,0x83d3,0x83d4,0x83d5,0x83d6,0x8446,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8440,0x8441,0x8442,0x8443,0x8444, + 0x8445,0x8447,0x8448,0x8449,0x844a,0x844b,0x844c,0x844d,0x844e, + 0x844f,0x8450,0x8451,0x8452,0x8453,0x8454,0x8455,0x8456,0x8457, + 0x8458,0x8459,0x845a,0x845b,0x845c,0x845d,0x845e,0x845f,0x8460, + 0x8470,0x8471,0x8472,0x8473,0x8474,0x8475,0x8477,0x8478,0x8479, + 0x847a,0x847b,0x847c,0x847d,0x847e,0x8480,0x8481,0x8482,0x8483, + 0x8484,0x8485,0x8486,0x8487,0x8488,0x8489,0x848a,0x848b,0x848c, + 0x848d,0x848e,0x848f,0x8490,0x8491,UDCODE,0x8476,0x815d,UDCODE, + UDCODE,UDCODE,UDCODE,0x815c,UDCODE,UDCODE,0x8165,0x8166,UDCODE, + UDCODE,0x8167,0x8168,UDCODE,UDCODE,0x81f5,0x81f6,UDCODE,UDCODE, + UDCODE,0x8164,0x8163,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x81f1,UDCODE,0x818c,0x818d,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81a6,0x818e,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8782,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8784,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x81f0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8754,0x8755,0x8756,0x8757,0x8758,0x8759,0x875a,0x875b,0x875c, + 0x875d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfa40,0xfa41, + 0xfa42,0xfa43,0xfa44,0xfa45,0xfa46,0xfa47,0xfa48,0xfa49,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x81a9,0x81aa,0x81a8,0x81ab,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81cb,UDCODE,0x81cc, + 0x81cd,UDCODE,0x81dd,0x81ce,UDCODE,UDCODE,UDCODE,0x81de,0x81b8, + UDCODE,UDCODE,0x81b9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8794, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81e3, + UDCODE,UDCODE,0x81e5,0x8187,0x8798,0x81da,UDCODE,UDCODE,UDCODE, + UDCODE,0x8161,UDCODE,0x81c8,0x81c9,0x81bf,0x81be,0x81e7,0x81e8, + UDCODE,0x8793,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8188,0x81e6, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81e4,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x81e0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8182,0x81df,UDCODE, + UDCODE,UDCODE,UDCODE,0x8185,0x8186,UDCODE,UDCODE,0x81e1,0x81e2, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x81bc,0x81bd,UDCODE,UDCODE,0x81ba, + 0x81bb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x81db,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8799,0x81dc,0x8740,0x8741,0x8742,0x8743,0x8744, + 0x8745,0x8746,0x8747,0x8748,0x8749,0x874a,0x874b,0x874c,0x874d, + 0x874e,0x874f,0x8750,0x8751,0x8752,0x8753,0x849f,0x84aa,0x84a0, + 0x84ab,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x84a1,UDCODE,UDCODE,0x84ac,0x84a2,UDCODE,UDCODE,0x84ad,0x84a4, + UDCODE,UDCODE,0x84af,0x84a3,UDCODE,UDCODE,0x84ae,0x84a5,0x84ba, + UDCODE,UDCODE,0x84b5,UDCODE,UDCODE,0x84b0,0x84a7,0x84bc,UDCODE, + UDCODE,0x84b7,UDCODE,UDCODE,0x84b2,0x84a6,UDCODE,UDCODE,0x84b6, + 0x84bb,UDCODE,UDCODE,0x84b1,0x84a8,UDCODE,UDCODE,0x84b8,0x84bd, + UDCODE,UDCODE,0x84b3,0x84a9,UDCODE,UDCODE,0x84b9,UDCODE,UDCODE, + 0x84be,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x84b4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x81a1,0x81a0,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x81a3,0x81a2,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81a5,0x81a4,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x819f,0x819e,UDCODE, + UDCODE,UDCODE,0x819b,UDCODE,UDCODE,0x819d,0x819c,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x81fc,0x819a,0x8199,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x818a, + UDCODE,0x8189,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x81f4,UDCODE,UDCODE,0x81f3, + UDCODE,0x81f2,0x8140,0x8141,0x8142,0x8156,UDCODE,0x8158,0x8159, + 0x815a,0x8171,0x8172,0x8173,0x8174,0x8175,0x8176,0x8177,0x8178, + 0x8179,0x817a,0x81a7,0x81ac,0x816b,0x816c,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8780,UDCODE,0x8781,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x829f,0x82a0,0x82a1,0x82a2,0x82a3, + 0x82a4,0x82a5,0x82a6,0x82a7,0x82a8,0x82a9,0x82aa,0x82ab,0x82ac, + 0x82ad,0x82ae,0x82af,0x82b0,0x82b1,0x82b2,0x82b3,0x82b4,0x82b5, + 0x82b6,0x82b7,0x82b8,0x82b9,0x82ba,0x82bb,0x82bc,0x82bd,0x82be, + 0x82bf,0x82c0,0x82c1,0x82c2,0x82c3,0x82c4,0x82c5,0x82c6,0x82c7, + 0x82c8,0x82c9,0x82ca,0x82cb,0x82cc,0x82cd,0x82ce,0x82cf,0x82d0, + 0x82d1,0x82d2,0x82d3,0x82d4,0x82d5,0x82d6,0x82d7,0x82d8,0x82d9, + 0x82da,0x82db,0x82dc,0x82dd,0x82de,0x82df,0x82e0,0x82e1,0x82e2, + 0x82e3,0x82e4,0x82e5,0x82e6,0x82e7,0x82e8,0x82e9,0x82ea,0x82eb, + 0x82ec,0x82ed,0x82ee,0x82ef,0x82f0,0x82f1,0x8394,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x814a,0x814b,0x8154,0x8155,UDCODE, + UDCODE,0x8340,0x8341,0x8342,0x8343,0x8344,0x8345,0x8346,0x8347, + 0x8348,0x8349,0x834a,0x834b,0x834c,0x834d,0x834e,0x834f,0x8350, + 0x8351,0x8352,0x8353,0x8354,0x8355,0x8356,0x8357,0x8358,0x8359, + 0x835a,0x835b,0x835c,0x835d,0x835e,0x835f,0x8360,0x8361,0x8362, + 0x8363,0x8364,0x8365,0x8366,0x8367,0x8368,0x8369,0x836a,0x836b, + 0x836c,0x836d,0x836e,0x836f,0x8370,0x8371,0x8372,0x8373,0x8374, + 0x8375,0x8376,0x8377,0x8378,0x8379,0x837a,0x837b,0x837c,0x837d, + 0x837e,0x8380,0x8381,0x8382,0x8383,0x8384,0x8385,0x8386,0x8387, + 0x8388,0x8389,0x838a,0x838b,0x838c,0x838d,0x838e,0x838f,0x8390, + 0x8391,0x8392,0x8393,0x8394,0x8395,0x8396,UDCODE,UDCODE,UDCODE, + UDCODE,0x8145,0x815b,0x8152,0x8153,0x878a,0x878b,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x878c,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8785,0x8786,0x8787,0x8788,0x8789,0x8765, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8769,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8760,UDCODE, + UDCODE,UDCODE,0x8763,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8761,0x876b,UDCODE,UDCODE,0x876a,0x8764, + UDCODE,UDCODE,UDCODE,0x876c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8766,UDCODE,UDCODE,UDCODE, + UDCODE,0x876e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x875f,0x876d,UDCODE, + UDCODE,0x8762,UDCODE,UDCODE,UDCODE,0x8767,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8768,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x877e,0x878f,0x878e,0x878d,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8772,0x8773,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x876f, + 0x8770,0x8771,UDCODE,UDCODE,0x8775,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8774,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8783,0x88ea,0x929a,UDCODE,0x8eb5,UDCODE, + UDCODE,UDCODE,0x969c,0x8fe4,0x8e4f,0x8fe3,0x89ba,UDCODE,0x9573, + 0x975e,UDCODE,0x98a0,0x894e,UDCODE,UDCODE,0x8a8e,0x98a1,0x90a2, + 0x99c0,0x8b75,0x95b8,UDCODE,UDCODE,UDCODE,UDCODE,0x8fe5,UDCODE, + UDCODE,0x97bc,UDCODE,UDCODE,UDCODE,UDCODE,0x95c0,UDCODE,0xfa68, + UDCODE,0x98a2,UDCODE,UDCODE,0x9286,UDCODE,UDCODE,UDCODE,0x98a3, + 0x8bf8,UDCODE,UDCODE,UDCODE,0x98a4,UDCODE,0x8adb,0x924f,UDCODE, + 0x8ee5,0x98a5,UDCODE,UDCODE,0x98a6,UDCODE,UDCODE,0x98a7,0x9454, + UDCODE,0x8b76,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9456,UDCODE, + 0x93e1,0x8cc1,0x9652,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe568, + 0x98a8,0x8fe6,0x98a9,0x89b3,UDCODE,UDCODE,UDCODE,0x8be3,0x8cee, + 0x96e7,UDCODE,UDCODE,0x9ba4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9790,UDCODE,0x93fb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8aa3,UDCODE,0x8b54,UDCODE,0x98aa, + UDCODE,UDCODE,0x98ab,0x97b9,UDCODE,0x975c,0x9188,0x98ad,0x8e96, + 0x93f1,UDCODE,0x98b0,UDCODE,UDCODE,0x895d,0x8cdd,UDCODE,0x8cdc, + 0x88e4,UDCODE,UDCODE,0x986a,0x9869,UDCODE,0x8db1,0x889f,UDCODE, + 0x98b1,0x98b2,0x98b3,0x9653,0x98b4,UDCODE,0x8cf0,0x88e5,0x9692, + UDCODE,0x8b9c,UDCODE,UDCODE,0x8b9d,0x8b9e,0x92e0,0x97ba,UDCODE, + 0x98b5,UDCODE,UDCODE,0x98b6,UDCODE,UDCODE,0x98b7,UDCODE,UDCODE, + UDCODE,0x906c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f59,0x906d, + 0x98bc,UDCODE,0x98ba,UDCODE,0x98bb,0x8b77,UDCODE,UDCODE,0x8da1, + 0x89ee,UDCODE,0x98b9,0x98b8,0x95a7,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8e65,0x8e64,0x91bc,0x98bd,0x9574,0x90e5,UDCODE,UDCODE,UDCODE, + 0x8157,0x98be,0x98c0,UDCODE,0xfa69,UDCODE,0x91e3,0x97df,0x88c8, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x98bf,0x89bc, + UDCODE,0x8bc2,UDCODE,0x9287,UDCODE,UDCODE,UDCODE,0x8c8f,0x98c1, + UDCODE,UDCODE,UDCODE,0x9443,0xfa6a,0xfa6b,0x8ae9,UDCODE,0xfa6c, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x98c2,0x88c9,UDCODE,UDCODE, + 0x8cde,0x8aea,0x959a,0x94b0,0x8b78,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x89ef,UDCODE,0x98e5,0x9360,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x948c,0x98c4, + UDCODE,UDCODE,UDCODE,0x94ba,UDCODE,0x97e0,UDCODE,0x904c,0xfa6d, + 0x8e66,UDCODE,0x8e97,0x89be,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x92cf,UDCODE,UDCODE,0x9241,0x98c8,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x88ca,0x92e1,0x8f5a,0x8db2,0x9743,UDCODE,0x91cc,UDCODE, + 0x89bd,0xfa6e,0x98c7,UDCODE,0x975d,0x98c3,0x98c5,0x8dec,0x98c6, + 0x9b43,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x98ce,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x98d1, + 0x98cf,UDCODE,UDCODE,0x89c0,UDCODE,0x95b9,0x98c9,UDCODE,UDCODE, + UDCODE,UDCODE,0x98cd,0x8cf1,UDCODE,UDCODE,0x8e67,UDCODE,UDCODE, + UDCODE,0x8aa4,UDCODE,UDCODE,0x98d2,UDCODE,0x98ca,UDCODE,0xfa70, + 0x97e1,UDCODE,0x8e98,UDCODE,0x98cb,UDCODE,0x98d0,0xfa6f,UDCODE, + 0xfa72,UDCODE,0x98d3,UDCODE,0x98cc,UDCODE,0xfa71,0x8b9f,UDCODE, + 0x88cb,UDCODE,UDCODE,0x8ba0,0x89bf,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9b44,UDCODE,0x9699,0x958e, + 0x8cf2,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x904e,0x97b5,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95d6,UDCODE, + UDCODE,0x8c57,0x91a3,0x89e2,UDCODE,UDCODE,UDCODE,UDCODE,0xfa61, + 0x8f72,UDCODE,UDCODE,0xfa73,0x98d7,UDCODE,0x98dc,0x98da,UDCODE, + UDCODE,0x98d5,UDCODE,UDCODE,0x91ad,0x98d8,UDCODE,0x98db,0x98d9, + UDCODE,0x95db,UDCODE,0x98d6,UDCODE,0x904d,UDCODE,0x9693,0x98dd, + 0x98de,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8f43,0x98eb,UDCODE,UDCODE,UDCODE,0x946f,UDCODE,0x9555,0x98e6, + UDCODE,0x95ee,UDCODE,0x89b4,UDCODE,UDCODE,UDCODE,0x98ea,0xfa76, + 0x98e4,0x98ed,UDCODE,UDCODE,0x9171,UDCODE,0x8cc2,UDCODE,0x947b, + UDCODE,0xe0c5,UDCODE,0x98ec,0x937c,UDCODE,0x98e1,UDCODE,0x8cf4, + UDCODE,UDCODE,0x8cf3,0x98df,UDCODE,UDCODE,UDCODE,0xfa77,0x8ed8, + UDCODE,0x98e7,0xfa75,0x95ed,0x926c,0x98e3,0x8c91,UDCODE,0x98e0, + 0x98e8,0x98e2,0x97cf,0x98e9,0x9860,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8be4,UDCODE,UDCODE,0x8c90,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfa74,UDCODE,0xfa7a,0x98ee, + UDCODE,UDCODE,0xfa78,0x98ef,0x98f3,0x88cc,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x95ce,0x98f2,UDCODE,UDCODE,UDCODE,UDCODE,0x98f1, + 0x98f5,UDCODE,UDCODE,UDCODE,0x98f4,UDCODE,0x92e2,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c92,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x98f6,UDCODE,UDCODE,UDCODE,0xfa79, + UDCODE,0x8ec3,UDCODE,0x91a4,0x92e3,0x8bf4,UDCODE,0x98f7,UDCODE, + UDCODE,UDCODE,UDCODE,0x8b55,UDCODE,UDCODE,0x98f8,UDCODE,UDCODE, + UDCODE,UDCODE,0x98fa,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9654,UDCODE,UDCODE,UDCODE,0x8c86,UDCODE,UDCODE,0xfa7b, + UDCODE,UDCODE,UDCODE,0x8e50,0x94f5,0x98f9,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8dc3,0x9762,UDCODE,UDCODE, + UDCODE,UDCODE,0x98fc,0x9942,0x98fb,0x8dc2,UDCODE,0x8f9d,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c58,UDCODE,UDCODE,UDCODE, + 0x9943,UDCODE,UDCODE,0x8bcd,UDCODE,UDCODE,UDCODE,0x9940,0x9941, + UDCODE,UDCODE,0x93ad,UDCODE,0x919c,UDCODE,0x8ba1,UDCODE,UDCODE, + UDCODE,0x966c,0x9944,UDCODE,0xfa7d,UDCODE,0x97bb,UDCODE,UDCODE, + UDCODE,0x9945,UDCODE,UDCODE,UDCODE,UDCODE,0x9948,UDCODE,0x9946, + UDCODE,0x916d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9947,0x9949, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfa7c,0x994b,UDCODE,UDCODE, + UDCODE,0x994a,UDCODE,0x95c6,0x8b56,0x994d,0x994e,UDCODE,0x89ad, + UDCODE,UDCODE,UDCODE,UDCODE,0x994c,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8ef2,UDCODE,0x9951,0x9950,0x994f, + UDCODE,0x98d4,UDCODE,0x9952,UDCODE,UDCODE,UDCODE,UDCODE,0x8f9e, + UDCODE,0x9953,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9744,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x96d7,UDCODE,UDCODE,UDCODE,UDCODE,0x9955,UDCODE,UDCODE,0x9954, + 0x9957,0x9956,UDCODE,UDCODE,0x9958,0x9959,0x88f2,UDCODE,0x8cb3, + 0x8c5a,0x8f5b,0x929b,0x8ba2,0x90e6,0x8cf5,0xfa7e,0x8d8e,0x995b, + 0x96c6,0x9365,UDCODE,0x8e99,UDCODE,0x995a,UDCODE,0x995c,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x937d,UDCODE,0x8a95,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x995d,UDCODE,0xfa80,0x93fc,UDCODE,UDCODE, + 0x9153,0x995f,0x9960,0x94aa,0x8cf6,0x985a,0x9961,UDCODE,UDCODE, + 0x8ba4,UDCODE,UDCODE,UDCODE,0x95ba,0x91b4,0x8bef,0x9354,UDCODE, + UDCODE,UDCODE,0x8c93,UDCODE,UDCODE,UDCODE,0x9962,UDCODE,0x9963, + UDCODE,UDCODE,0x93e0,0x897e,UDCODE,UDCODE,0x9966,0x8dfb,UDCODE, + 0x9965,0x8dc4,UDCODE,0x9967,0xe3ec,0x9968,0x9660,0x9969,UDCODE, + 0x996a,0x996b,0x8fe7,UDCODE,0x8eca,UDCODE,UDCODE,UDCODE,0xfa81, + UDCODE,UDCODE,0x8aa5,UDCODE,0x996e,UDCODE,0x996c,0x96bb,0x996d, + UDCODE,0x9579,0x996f,0x9970,0x9971,0x937e,UDCODE,UDCODE,UDCODE, + 0x9975,0x9973,0x9974,0x9972,0x8de1,0x9976,0x96e8,0x97e2,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9977,0xfa82,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x90a6,0x9978,0x8f79,UDCODE,UDCODE,0x9979,UDCODE, + 0x929c,0x97bd,0x9380,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x99c3,UDCODE,UDCODE,UDCODE,UDCODE,0x997a,0xeaa3, + 0x8bc3,UDCODE,UDCODE,0x997b,0x967d,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8f88,0x91fa,UDCODE,0x997d,0x93e2,UDCODE,0xfa83,0x997e,UDCODE, + UDCODE,0x9980,0x8a4d,UDCODE,UDCODE,UDCODE,0x9981,0x8ba5,UDCODE, + 0x93ca,0x899a,0x8f6f,UDCODE,UDCODE,0x949f,0x9982,0x9381,UDCODE, + UDCODE,0x906e,0x9983,UDCODE,0x95aa,0x90d8,0x8aa0,UDCODE,0x8aa7, + 0x9984,UDCODE,UDCODE,0x9986,UDCODE,UDCODE,0x8c59,UDCODE,UDCODE, + 0x9985,0xfa84,UDCODE,0x97f1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8f89,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x94bb,0x95ca, + UDCODE,0x9987,UDCODE,0x9798,0x9988,UDCODE,UDCODE,UDCODE,0x9989, + UDCODE,0x939e,UDCODE,UDCODE,0x998a,UDCODE,UDCODE,0x90a7,0x8dfc, + 0x8c94,0x998b,0x8e68,0x8d8f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x92e4,0x998d,UDCODE,UDCODE,0x91a5,UDCODE,UDCODE, + 0x8ded,0x998e,0x998f,0x914f,UDCODE,0x998c,UDCODE,UDCODE,UDCODE, + UDCODE,0x9991,UDCODE,0x9655,UDCODE,UDCODE,UDCODE,UDCODE,0x8d84, + UDCODE,UDCODE,0x9990,UDCODE,UDCODE,UDCODE,UDCODE,0x8c95,0x8ddc, + 0x948d,UDCODE,UDCODE,UDCODE,0x9994,0x9992,UDCODE,UDCODE,UDCODE, + UDCODE,0x959b,0x8fe8,0x999b,0x8a84,0x9995,0x9993,0x916e,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9997,UDCODE,0x9996, + UDCODE,UDCODE,UDCODE,0x8a63,UDCODE,UDCODE,UDCODE,0x8c80,0x999c, + 0x97ab,UDCODE,UDCODE,UDCODE,0x9998,UDCODE,UDCODE,UDCODE,0x999d, + 0x999a,UDCODE,0x9999,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x97cd,0xfa85,UDCODE,UDCODE,0x8cf7,0x89c1,UDCODE,UDCODE,0x97f2, + UDCODE,UDCODE,0xfa86,UDCODE,UDCODE,0x8f95,0x9377,0x8d85,0x99a0, + 0x99a1,UDCODE,0xfb77,UDCODE,0x97e3,UDCODE,UDCODE,0x984a,0x99a3, + UDCODE,UDCODE,UDCODE,0x8cf8,UDCODE,UDCODE,0x99a2,UDCODE,0x8a4e, + UDCODE,0xfa87,0x99a4,UDCODE,0x9675,UDCODE,0x92ba,UDCODE,0x9745, + UDCODE,0x95d7,UDCODE,UDCODE,UDCODE,0x99a5,UDCODE,UDCODE,UDCODE, + UDCODE,0xe8d3,UDCODE,UDCODE,0x93ae,UDCODE,0x99a6,0x8aa8,0x96b1, + UDCODE,0xfa88,UDCODE,0x8f9f,0x99a7,0x95e5,0x99ab,UDCODE,0x90a8, + 0x99a8,0x8bce,UDCODE,0x99a9,0x8aa9,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c4d,0x99ac,UDCODE, + 0x99ad,UDCODE,UDCODE,0x99ae,0x99af,0x8ed9,UDCODE,UDCODE,UDCODE, + 0x8cf9,0x96dc,0xfa89,0x96e6,0x93f5,UDCODE,UDCODE,0x95ef,0x99b0, + 0xfa8a,0x99b1,UDCODE,UDCODE,UDCODE,UDCODE,0x99b3,UDCODE,0x99b5, + 0x99b4,UDCODE,UDCODE,UDCODE,UDCODE,0x99b6,0x89bb,0x966b,UDCODE, + 0x8dfa,0x99b7,UDCODE,UDCODE,0x9178,UDCODE,UDCODE,0x8fa0,0x8ba7, + UDCODE,0x99b8,0xfa8b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x94d9, + UDCODE,UDCODE,UDCODE,UDCODE,0x99b9,UDCODE,0x99ba,UDCODE,0x99bb, + UDCODE,UDCODE,UDCODE,UDCODE,0x99bc,0x9543,0x8be6,0x88e3,UDCODE, + UDCODE,UDCODE,0x93bd,0x99bd,0x8f5c,UDCODE,0x90e7,UDCODE,0x99bf, + 0x99be,0x8fa1,0x8cdf,0x99c1,0x94bc,UDCODE,UDCODE,0x99c2,UDCODE, + UDCODE,UDCODE,0x94da,0x91b2,0x91ec,0x8ba6,UDCODE,UDCODE,0x93ec, + 0x9250,UDCODE,0x948e,UDCODE,0x966d,UDCODE,0x99c4,UDCODE,0x90e8, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c54,UDCODE,UDCODE,0x99c5, + UDCODE,UDCODE,UDCODE,UDCODE,0x99c6,0x894b,0x88f3,0x8aeb,0xfa8c, + 0x91a6,0x8b70,0x9791,UDCODE,0x99c9,0x89b5,UDCODE,UDCODE,0x99c8, + UDCODE,UDCODE,UDCODE,0x8ba8,UDCODE,UDCODE,0x99ca,UDCODE,0x96ef, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfa8d,UDCODE,UDCODE,0x99cb, + UDCODE,0x97d0,UDCODE,0x8cfa,UDCODE,UDCODE,UDCODE,UDCODE,0x8cb4, + 0x99cc,UDCODE,UDCODE,UDCODE,UDCODE,0x99ce,0x99cd,UDCODE,0x907e, + 0x8958,UDCODE,UDCODE,UDCODE,0x897d,0x99cf,UDCODE,0x99d0,UDCODE, + 0xfa8e,0x8cb5,UDCODE,UDCODE,0x99d1,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8b8e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8e51,0x99d2, + UDCODE,UDCODE,UDCODE,UDCODE,0x9694,0x8db3,0x8b79,0x9746,0x916f, + 0x94bd,0x8efb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f66,UDCODE, + 0x8ee6,0x8ef3,UDCODE,0x8f96,UDCODE,0x94be,UDCODE,0xfa8f,UDCODE, + 0x99d5,UDCODE,0x8962,0x9170,0x8cfb,0x8cc3,0x8be5,UDCODE,UDCODE, + 0x99d9,0x9240,0x91fc,0x8ba9,0x8fa2,0x99da,0x99d8,0x89c2,0x91e4, + 0x8eb6,0x8e6a,0x8945,UDCODE,UDCODE,0x8a90,0x8d86,0x8e69,UDCODE, + 0x99db,0x99dc,UDCODE,0x8b68,0x8a65,UDCODE,UDCODE,UDCODE,0x8d87, + 0x8b67,0x92dd,0x8944,0x93af,0x96bc,0x8d40,0x9799,0x9366,0x8cfc, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8c4e,UDCODE,0x99e5,UDCODE,0x8be1,0x9669,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x94db,UDCODE,UDCODE,0x99e4,UDCODE,0x8adc,0x99df, + 0x99e0,0x99e2,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x99e3,UDCODE,0x8b7a,0x9081,UDCODE,0x95ab,0x99e1,0x99dd,0x8ce1, + UDCODE,0x99de,UDCODE,0x9843,UDCODE,UDCODE,UDCODE,0x95f0,UDCODE, + 0x92e6,0x8ce0,0x8d90,UDCODE,UDCODE,UDCODE,0x99e6,UDCODE,UDCODE, + 0x93db,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x99ea,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8efc,UDCODE,0x8ef4,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x99ed,0x99eb,UDCODE,0x96a1,UDCODE, + 0x99e8,0x99f1,0x99ec,UDCODE,UDCODE,UDCODE,0x99ef,0x8cc4,0x96bd, + UDCODE,UDCODE,0x99f0,UDCODE,UDCODE,UDCODE,0x99f2,UDCODE,0x99f4, + UDCODE,UDCODE,UDCODE,0xfa92,0x8dee,0x9861,UDCODE,0x99e9,0x99e7, + 0x99f3,UDCODE,0x99ee,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xfa91,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x99f6,UDCODE,0x9a42,0x99f8,UDCODE,UDCODE,0x99fc,0xfa93,UDCODE, + 0x9a40,0x99f9,UDCODE,UDCODE,0x9a5d,UDCODE,UDCODE,0x8de7,0x8a50, + UDCODE,UDCODE,UDCODE,UDCODE,0x99f7,UDCODE,UDCODE,UDCODE,0x9a44, + 0x88f4,0x9a43,UDCODE,0x88a3,0x9569,0x9a41,UDCODE,0x99fa,UDCODE, + UDCODE,0x99f5,0x99fb,0x8dc6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9a45,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x88f5,0x9a4e,UDCODE,UDCODE,0x9a46,0x9a47,UDCODE,0x8fa3,0x9689, + UDCODE,UDCODE,UDCODE,0x9a4c,0x9a4b,UDCODE,UDCODE,UDCODE,0x934e, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a4d,UDCODE, + UDCODE,0x9a4a,UDCODE,0xfa94,0x8953,UDCODE,0x8db4,0x904f,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a48,0x9382,UDCODE, + UDCODE,UDCODE,0x9a49,UDCODE,0x88a0,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9a53,0x9742,UDCODE,0x8fa5,UDCODE,0x9a59,UDCODE,UDCODE, + UDCODE,UDCODE,0x9a58,0x9a4f,UDCODE,UDCODE,UDCODE,UDCODE,0x91c1, + UDCODE,0x9a50,UDCODE,UDCODE,UDCODE,0x91ed,0x9a55,0x8fa4,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9a52,UDCODE,UDCODE,0x96e2,UDCODE, + UDCODE,UDCODE,0x8c5b,UDCODE,UDCODE,0x9a56,0x9a57,UDCODE,UDCODE, + UDCODE,UDCODE,0x9a54,0x9a5a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9a51,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a60,0x9a65,UDCODE, + 0x9a61,UDCODE,0x9a5c,UDCODE,UDCODE,0x9a66,0x9150,UDCODE,0xfa95, + 0x9a68,UDCODE,0x8d41,0x9a5e,0x929d,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a62, + 0x9a5b,0x8aab,UDCODE,0x8aec,0x8a85,0x9a63,0x9a5f,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c96,0x9a69,0x9a67,0x9172, + 0x8b69,0x8baa,UDCODE,0x9a64,UDCODE,0x8bf2,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8963,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a6d,0x9a6b, + UDCODE,0x9aa5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a70,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9a6a,UDCODE,0x9a6e,UDCODE,UDCODE,0x9a6c,UDCODE, + UDCODE,UDCODE,0x8e6b,0x9a6f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9a72,UDCODE,0x9a77,UDCODE,UDCODE, + UDCODE,0x9a75,0x9a74,0x9251,UDCODE,UDCODE,0x89c3,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a71, + UDCODE,0x9a73,0x8fa6,0x8952,UDCODE,UDCODE,0x9a76,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x89dc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a82, + UDCODE,0x8ffa,0x9a7d,UDCODE,0x9a7b,UDCODE,0x9a7c,UDCODE,0x9a7e, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x895c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9158,UDCODE,0x9a78,UDCODE,0x9a79,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8a9a,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a81,UDCODE, + UDCODE,UDCODE,0x8aed,UDCODE,0x9a84,0x9a80,0x9a83,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95ac,UDCODE,UDCODE,UDCODE, + 0x93d3,UDCODE,0x94b6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a86, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a85,0x8a64,UDCODE,UDCODE, + 0x9a87,UDCODE,UDCODE,UDCODE,UDCODE,0x9a8a,UDCODE,UDCODE,UDCODE, + UDCODE,0x9a89,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9a88,UDCODE,0x9458,UDCODE,UDCODE, + 0x9a8b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9a8c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a8e,UDCODE,0x9a8d, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a90,UDCODE,UDCODE,UDCODE, + 0x9a93,0x9a91,0x9a8f,0x9a92,UDCODE,UDCODE,UDCODE,UDCODE,0x9a94, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9a95,UDCODE,UDCODE,0x9a96, + UDCODE,0x9a97,UDCODE,UDCODE,UDCODE,0x9a98,0x9964,UDCODE,0x8efa, + 0x8e6c,UDCODE,UDCODE,0x89f1,UDCODE,0x88f6,UDCODE,UDCODE,0x9263, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9a99,UDCODE,0x8da2,UDCODE,0x88cd,0x907d,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9a9a,0x8cc5,UDCODE,UDCODE,0x8d91,UDCODE, + 0x9a9c,0x9a9b,UDCODE,UDCODE,0x95de,0x9a9d,UDCODE,UDCODE,UDCODE, + 0x9a9f,0x9a9e,UDCODE,0x9aa0,UDCODE,0x9aa1,UDCODE,0x8c97,UDCODE, + UDCODE,0x8980,0x9aa2,UDCODE,UDCODE,0x9aa4,UDCODE,0x9aa3,UDCODE, + UDCODE,UDCODE,0x9aa6,UDCODE,UDCODE,0x9379,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9aa7,0x88b3,0x8ddd,UDCODE,UDCODE,UDCODE, + UDCODE,0x8c5c,UDCODE,UDCODE,0x926e,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9aa8,0x9aa9,UDCODE,UDCODE,0x9aab,UDCODE,UDCODE, + UDCODE,UDCODE,0x9aac,UDCODE,0x8de2,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8bcf,UDCODE,UDCODE,0x9656,UDCODE,UDCODE,UDCODE,0x9aaa,0x9aad, + 0x8dbf,0x8d42,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xfa96,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ab1, + UDCODE,UDCODE,0x8da3,0xfa97,0x9252,UDCODE,UDCODE,0x9aae,0x92d8, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9ab2,UDCODE,UDCODE,0x9082,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9ab0,0x9ab3,UDCODE,0x8c5e,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9ab4,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ab5, + UDCODE,0x8d43,0x8a5f,0x9ab7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9ab8,UDCODE,0xfa98,UDCODE,UDCODE,UDCODE,0x9ab9,UDCODE,UDCODE, + 0x9ab6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9aaf,UDCODE,UDCODE,0x9aba,UDCODE, + UDCODE,0x9abb,0xfa9a,0xfa99,UDCODE,UDCODE,0x9684,UDCODE,UDCODE, + 0x8fe9,UDCODE,UDCODE,UDCODE,0x9abd,0x9abe,0x9abc,UDCODE,0x9ac0, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9457,UDCODE,UDCODE,0x88e6, + 0x9575,UDCODE,UDCODE,0x9ac1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8ffb,UDCODE,UDCODE,0x8eb7,UDCODE,0x947c,0x8aee, + UDCODE,0x8de9,0x9678,UDCODE,0x93b0,UDCODE,UDCODE,0x8c98,0x91cd, + UDCODE,UDCODE,UDCODE,0x9abf,0x9ac2,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x91c2,UDCODE,UDCODE,UDCODE, + 0x9ac3,UDCODE,UDCODE,UDCODE,0x9ac4,UDCODE,UDCODE,UDCODE,0x9ac6, + UDCODE,UDCODE,0x92e7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8aac, + UDCODE,UDCODE,UDCODE,UDCODE,0xea9f,0x8981,0x95f1,UDCODE,UDCODE, + 0x8fea,0x9367,UDCODE,UDCODE,UDCODE,UDCODE,0x8de4,UDCODE,UDCODE, + 0x9acc,UDCODE,UDCODE,0x95bb,0x97db,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x89f2,0x9ac8,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9159,0x9acb,UDCODE,0x9383,UDCODE,UDCODE,0x9368, + 0x9384,0x94b7,0x92cb,UDCODE,UDCODE,UDCODE,0x8dc7,UDCODE,UDCODE, + UDCODE,0x9ac7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8996, + UDCODE,0x9355,UDCODE,UDCODE,UDCODE,UDCODE,0x9ac9,UDCODE,0x9ac5, + UDCODE,UDCODE,0x906f,UDCODE,UDCODE,UDCODE,0x9acd,UDCODE,UDCODE, + UDCODE,UDCODE,0x8f6d,UDCODE,UDCODE,UDCODE,UDCODE,0x8bab,UDCODE, + 0x9ace,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95e6,UDCODE,UDCODE,UDCODE, + 0x919d,UDCODE,UDCODE,UDCODE,UDCODE,0x92c4,UDCODE,0xfa9d,0x9ad0, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x966e, + UDCODE,UDCODE,0x9ad1,UDCODE,UDCODE,0x9ad6,UDCODE,UDCODE,UDCODE, + 0xfa9e,0x95ad,UDCODE,UDCODE,UDCODE,UDCODE,0x9ad5,0x9acf,0x9ad2, + 0x9ad4,UDCODE,UDCODE,0x8da4,UDCODE,UDCODE,0x95c7,UDCODE,UDCODE, + UDCODE,0x9ad7,UDCODE,0x9264,UDCODE,UDCODE,0x89f3,UDCODE,0x8feb, + UDCODE,UDCODE,UDCODE,UDCODE,0x9ad9,UDCODE,0x9ad8,UDCODE,0x8d88, + UDCODE,0x9ada,0x9adc,0x9adb,UDCODE,UDCODE,0x9ade,UDCODE,0x9ad3, + 0x9ae0,UDCODE,UDCODE,UDCODE,UDCODE,0x9adf,0x9add,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8e6d,0x9070,UDCODE,0x9173,0x9ae1,0x90ba, + 0x88eb,0x9484,UDCODE,UDCODE,UDCODE,UDCODE,0x92d9,UDCODE,0x9ae3, + 0x9ae2,0x9ae4,0x9ae5,0x9ae6,0x9ae7,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x95cf,0x9ae8,0xfa9f,UDCODE,UDCODE,UDCODE,0x89c4, + 0x9ae9,UDCODE,UDCODE,UDCODE,UDCODE,0x975b,0x8a4f,UDCODE,0x99c7, + 0x8f67,0x91bd,0x9aea,0x96e9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x96b2,UDCODE,UDCODE,0x9aec,UDCODE,0x91e5,UDCODE,0x9356,0x91be, + 0x9576,0x9aed,0x9aee,0x899b,UDCODE,UDCODE,0x8eb8,0x9aef,UDCODE, + UDCODE,UDCODE,UDCODE,0x88ce,0x9af0,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9af1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8982,UDCODE, + UDCODE,0x8aef,0x93de,0x95f2,UDCODE,UDCODE,UDCODE,UDCODE,0x9af5, + 0x9174,0x9af4,0x8c5f,UDCODE,0xfaa0,0x967a,0x9af3,UDCODE,0x9385, + 0x9af7,UDCODE,0x9af6,0xfaa1,UDCODE,0xfaa2,UDCODE,UDCODE,0x9af9, + UDCODE,0x9af8,0xfaa3,UDCODE,0x899c,UDCODE,0x9afa,0x8fa7,0x9afc, + 0x9244,UDCODE,0x9afb,UDCODE,0x95b1,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8f97,0x937a,UDCODE,UDCODE,UDCODE,0x9b40,UDCODE,UDCODE,UDCODE, + UDCODE,0x8d44,UDCODE,UDCODE,UDCODE,0x9b41,0x9440,0x94dc,0x96cf, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9444,UDCODE,UDCODE,0x9b4a, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b57,UDCODE,UDCODE,0x9764, + UDCODE,UDCODE,0x96ad,UDCODE,0x9baa,UDCODE,0x9b42,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9b45,0xfaa4,0x91c3,UDCODE,UDCODE,0x9657, + UDCODE,UDCODE,UDCODE,0x9369,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9b46,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9685,0xfaa5, + 0x8dc8,UDCODE,UDCODE,0x8fa8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9b47,UDCODE,UDCODE,0x8e6f,UDCODE,0x8e6e,UDCODE, + UDCODE,UDCODE,UDCODE,0x88b7,0x8cc6,UDCODE,0x90a9,0x88cf,UDCODE, + UDCODE,UDCODE,UDCODE,0x9b4b,0x9b4c,UDCODE,0x9b49,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8957,0x8aad,UDCODE, + 0x9b48,UDCODE,0x96c3,0x9550,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x88a6,UDCODE,UDCODE,UDCODE, + UDCODE,0x88f7,UDCODE,UDCODE,UDCODE,0x8e70,0x88d0,UDCODE,0x88a1, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9b51,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9b4f,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x96ba,UDCODE,0x9b52,UDCODE,0x9b50,UDCODE,UDCODE, + 0x9b4e,0x9050,UDCODE,UDCODE,UDCODE,UDCODE,0x9b4d,UDCODE,UDCODE, + UDCODE,0x95d8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ce2,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9b56,0x9b57,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8fa9,UDCODE,UDCODE,UDCODE,0x9b53,0x984b,UDCODE, + UDCODE,UDCODE,UDCODE,0x946b,UDCODE,UDCODE,0x9b55,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8da5,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9b58,UDCODE,UDCODE,UDCODE,0x9577, + UDCODE,UDCODE,UDCODE,0x9b59,UDCODE,0x9b54,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x96b9,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x947d,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9b5a,0x9551,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9b5b,0x9b5f,0x9b5c,UDCODE,UDCODE, + 0x89c5,0x9b5e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8eb9, + UDCODE,0x9b5d,0x8c99,UDCODE,UDCODE,UDCODE,0x9b6b,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9b64,0x9b61,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9284,UDCODE,0x9b60,UDCODE, + UDCODE,0x9b62,UDCODE,UDCODE,0x9b63,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9b65,0x9b66,0x8af0,UDCODE,0x9b68,0x9b67, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9b69,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8fec,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9b6c,UDCODE,0x92da,UDCODE,UDCODE,UDCODE,0x8964, + UDCODE,0x9b6a,UDCODE,UDCODE,UDCODE,0x9b6d,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9b6e,UDCODE,0x9b71,UDCODE,UDCODE, + 0x9b6f,UDCODE,0x9b70,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8e71,0x9b72,UDCODE,UDCODE,0x8d45, + 0x9b73,0xfaa6,0x8e9a,0x91b6,UDCODE,0x9b74,0x9b75,0x8e79,0x8d46, + UDCODE,0x96d0,UDCODE,UDCODE,UDCODE,0x8b47,0x8cc7,0x9b76,0x8a77, + UDCODE,UDCODE,0x9b77,UDCODE,0x91b7,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9b78,0x9ba1,UDCODE,0x9b79,UDCODE,0x9b7a,UDCODE,UDCODE,0x9b7b, + UDCODE,0x9b7d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9b7e,UDCODE, + UDCODE,0x9b80,UDCODE,0x91ee,UDCODE,0x8946,0x8ee7,0x88c0,UDCODE, + 0x9176,0x8aae,0x8eb3,UDCODE,0x8d47,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9386,UDCODE,0x8f40,0x8aaf,0x9288,0x92e8,0x88b6,0x8b58, + 0x95f3,UDCODE,0x8ec0,UDCODE,UDCODE,0x8b71,0x90e9,0x8eba,0x9747, + 0x9b81,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b7b, + UDCODE,0x8dc9,UDCODE,UDCODE,0x8a51,0x8983,0x8faa,0x89c6,UDCODE, + 0x9b82,0x9765,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f68,0xfaa7, + UDCODE,0x8ee2,0x9b83,0x8af1,0x93d0,0x96a7,0x9b84,UDCODE,0x9b85, + UDCODE,UDCODE,0x9578,UDCODE,UDCODE,UDCODE,0x9b87,UDCODE,0x8aa6, + 0x8bf5,0x9b86,UDCODE,UDCODE,UDCODE,0xfaa9,UDCODE,UDCODE,0x8ab0, + UDCODE,0x9051,0x9b8b,0x8e40,UDCODE,0x89c7,0x9b8a,UDCODE,0x9b88, + 0x9b8c,0x9b89,0x944a,0x9ecb,0x9052,UDCODE,0x9b8d,0xfaaa,UDCODE, + 0x97be,UDCODE,0x9b8e,UDCODE,UDCODE,0x9b90,UDCODE,0x929e,0x9b8f, + UDCODE,0x90a1,UDCODE,0x8e9b,UDCODE,UDCODE,UDCODE,0x91ce,0x8ef5, + 0x9595,0x90ea,UDCODE,0x8ecb,0x9b91,0x8fab,0x9b92,0x9b93,0x88d1, + 0x91b8,0x9071,UDCODE,0x9b94,0x93b1,0x8fac,UDCODE,0x8fad,UDCODE, + 0x9b95,UDCODE,UDCODE,0x90eb,UDCODE,UDCODE,UDCODE,0x8fae,UDCODE, + UDCODE,UDCODE,0xfaab,UDCODE,0x9b96,UDCODE,0x9b97,UDCODE,0x96de, + UDCODE,UDCODE,UDCODE,0x9b98,UDCODE,UDCODE,UDCODE,UDCODE,0x8bc4, + UDCODE,UDCODE,UDCODE,0x8f41,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9b99,0x9b9a,0x8eda,0x904b,0x93f2,0x9073,0x94f6,0x9441, + 0x8bc7,0x9b9b,UDCODE,UDCODE,UDCODE,0x8b8f,0x9b9c,UDCODE,0x8bfc, + UDCODE,0x93cd,0x89ae,UDCODE,0x8e72,0x9b9d,0x9ba0,0x9b9f,0x8bfb, + UDCODE,0x9b9e,UDCODE,0x9357,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x91ae,UDCODE,0x936a,0x8ec6,UDCODE,UDCODE, + 0x9177,0x979a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ba2, + UDCODE,0x9ba3,0x93d4,UDCODE,0x8e52,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9ba5,UDCODE,UDCODE,0x9ba6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9ba7,UDCODE,UDCODE,UDCODE,0x8af2, + 0x9ba8,UDCODE,UDCODE,0x9ba9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89aa,UDCODE, + UDCODE,UDCODE,UDCODE,0xfaac,UDCODE,0x915a,0x8ae2,UDCODE,0x9bab, + 0x96a6,UDCODE,UDCODE,UDCODE,UDCODE,0x91d0,UDCODE,0x8a78,UDCODE, + UDCODE,0x9bad,0x9baf,0x8add,UDCODE,0xfaad,0x9bac,0x9bae,UDCODE, + 0x9bb1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bb0,UDCODE, + 0x9bb2,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9bb3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x93bb,0x8bac, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89e3,0x9bb4,0x9bb9, + UDCODE,UDCODE,0x9bb7,UDCODE,0x95f5,0x95f4,UDCODE,UDCODE,UDCODE, + UDCODE,0xfaae,0x9387,UDCODE,UDCODE,UDCODE,0x9bb6,0x8f73,UDCODE, + 0x9bb5,0x9092,UDCODE,UDCODE,UDCODE,0x9bba,UDCODE,UDCODE,0x8de8, + UDCODE,UDCODE,0x9bc0,UDCODE,UDCODE,0x9bc1,0x9bbb,0x8a52,0x9bbc, + 0x9bc5,0x9bc4,0x9bc3,0x9bbf,UDCODE,UDCODE,UDCODE,0x9bbe,UDCODE, + UDCODE,0x9bc2,UDCODE,UDCODE,UDCODE,UDCODE,0xfaaf,UDCODE,0x95f6, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfab2,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bc9,0x9bc6,UDCODE, + 0x9bc8,UDCODE,0x9792,UDCODE,0x9bc7,0xfab0,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bbd,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9093,UDCODE,UDCODE,0x9bca,0xfab3,UDCODE,0x8db5,UDCODE,UDCODE, + UDCODE,0x9bcb,UDCODE,UDCODE,0x9bcc,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bcf,UDCODE, + 0x9bce,UDCODE,UDCODE,0x9bcd,UDCODE,UDCODE,UDCODE,0x9388,0x9bb8, + UDCODE,UDCODE,UDCODE,0x9bd5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bd1,UDCODE, + UDCODE,UDCODE,UDCODE,0x9bd0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9bd2,UDCODE,0x9bd3,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bd6,0xfab4,0xfab5, + 0x97e4,UDCODE,0x9bd7,0x9bd4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bd8,UDCODE,UDCODE, + 0x8ade,0x9bd9,UDCODE,UDCODE,0xfab6,UDCODE,0x9bdb,0x9bda,UDCODE, + UDCODE,0x9bdc,UDCODE,UDCODE,UDCODE,UDCODE,0x9bdd,UDCODE,0x90ec, + 0x8f42,UDCODE,UDCODE,0x8f84,UDCODE,0x9183,UDCODE,0x8d48,0x8db6, + 0x8d49,0x8b90,UDCODE,UDCODE,0x9bde,UDCODE,UDCODE,0x8db7,UDCODE, + UDCODE,0x8cc8,0x9bdf,0x96a4,0x9462,0x9be0,UDCODE,0x8d4a,UDCODE, + UDCODE,UDCODE,0x8aaa,UDCODE,0x9246,0x8bd0,0x8e73,0x957a,UDCODE, + UDCODE,0x94bf,UDCODE,UDCODE,UDCODE,UDCODE,0x9be1,0x8af3,UDCODE, + UDCODE,UDCODE,UDCODE,0x9be4,UDCODE,UDCODE,UDCODE,UDCODE,0x929f, + UDCODE,UDCODE,0x9be3,0x9be2,0x9be5,UDCODE,0x92e9,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9083,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8e74,UDCODE,0x90c8,UDCODE,0x91d1,0x8b41,UDCODE, + UDCODE,0x92a0,UDCODE,UDCODE,0x9be6,0x9be7,0x8fed,UDCODE,UDCODE, + UDCODE,UDCODE,0x9658,UDCODE,UDCODE,0x9bea,UDCODE,UDCODE,0x9be9, + 0x9be8,0x959d,UDCODE,0x9bf1,UDCODE,UDCODE,UDCODE,UDCODE,0x9679, + UDCODE,0x9beb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bed,0x968b, + UDCODE,0x9bec,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9bee,UDCODE,0x94a6,0x9bef,0x95bc,0x9bf0,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x8ab1,0x95bd,0x944e,0x9bf2,0x9bf3,UDCODE,0x8d4b,0x8ab2, + 0x9bf4,0x8cb6,0x9763,0x9748,0x8af4,0x9bf6,UDCODE,0x92a1,UDCODE, + 0x8d4c,0x8faf,UDCODE,UDCODE,0x94dd,UDCODE,UDCODE,0x8fb0,UDCODE, + UDCODE,UDCODE,UDCODE,0x8f98,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x92ea,0x95f7,0x9358,UDCODE,UDCODE,0x8d4d,UDCODE,0x957b,UDCODE, + UDCODE,UDCODE,0x9bf7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9378, + 0x8dc0,UDCODE,UDCODE,UDCODE,0x8cc9,UDCODE,0x92eb,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x88c1,0x8f8e,0x8d4e,0x9766, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9bf8, + 0x9bf9,0x9470,UDCODE,UDCODE,UDCODE,UDCODE,0x9bfa,0x97f5,0x984c, + UDCODE,UDCODE,UDCODE,UDCODE,0x9bfc,0x9bfb,UDCODE,UDCODE,0x8a66, + UDCODE,UDCODE,0x9c40,UDCODE,UDCODE,UDCODE,0x9c43,0x9c44,UDCODE, + 0x9c42,UDCODE,0x955f,0x8fb1,0x9c46,0x9c45,0x9c41,UDCODE,UDCODE, + UDCODE,UDCODE,0x9c47,0x9c48,UDCODE,UDCODE,0x9c49,UDCODE,UDCODE, + UDCODE,0x9c4c,0x9c4a,UDCODE,0x9c4b,0x9c4d,UDCODE,0x8984,0x92ec, + 0x9c4e,UDCODE,0x8c9a,0x89f4,0x9455,UDCODE,0x9c4f,0x93f9,0x95d9, + UDCODE,0x9c50,0x984d,UDCODE,UDCODE,UDCODE,UDCODE,0x9c51,0x95be, + 0x9c54,0x989f,0x98af,UDCODE,0x8eae,0x93f3,0x9c55,UDCODE,0x8b7c, + 0x92a2,0x88f8,0x9c56,0x95a4,0x8d4f,UDCODE,UDCODE,0x926f,UDCODE, + UDCODE,UDCODE,0x92ed,UDCODE,0xfab7,UDCODE,UDCODE,UDCODE,0x96ed, + 0x8cb7,0x8cca,UDCODE,0x9c57,UDCODE,UDCODE,UDCODE,0x9c58,UDCODE, + 0x9c5e,UDCODE,0x8ee3,UDCODE,UDCODE,0xfab8,0x92a3,UDCODE,0x8bad, + 0x9c59,UDCODE,UDCODE,UDCODE,0x954a,UDCODE,0x9265,UDCODE,UDCODE, + 0x9c5a,UDCODE,UDCODE,UDCODE,0xfa67,UDCODE,UDCODE,0x9c5b,UDCODE, + 0x8bae,UDCODE,0x9c5c,UDCODE,0x9c5d,UDCODE,UDCODE,0x9c5f,UDCODE, + 0x9396,UDCODE,UDCODE,0x9c60,0x9c61,UDCODE,0x9c62,UDCODE,UDCODE, + 0x9c53,0x9c52,UDCODE,UDCODE,UDCODE,0x9c63,0x8c60,UDCODE,UDCODE, + UDCODE,0x9546,0xfab9,UDCODE,0x8dca,0x9556,0x92a4,0x956a,0x9c64, + UDCODE,UDCODE,0x8fb2,0x8965,UDCODE,0x9c65,UDCODE,UDCODE,UDCODE, + 0x9c66,UDCODE,0x96f0,UDCODE,UDCODE,0x94de,UDCODE,UDCODE,0x9c69, + 0x899d,0x90aa,0x9c68,0x9c67,0x8c61,0x91d2,UDCODE,0x9c6d,0x9c6b, + UDCODE,0x9c6a,0x97a5,0x8ce3,UDCODE,UDCODE,UDCODE,0x8f99,0x9c6c, + 0x936b,0x8f5d,UDCODE,UDCODE,UDCODE,0x93be,0x9c70,0x9c6f,UDCODE, + UDCODE,UDCODE,UDCODE,0x9c6e,UDCODE,0x9c71,0x8ce4,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9c72,0x959c,0x8f7a,UDCODE,UDCODE, + 0x9c73,0x94f7,UDCODE,UDCODE,UDCODE,UDCODE,0x93bf,0x92a5,UDCODE, + UDCODE,0xfaba,UDCODE,0x934f,UDCODE,UDCODE,0x9c74,0x8b4a,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9053,UDCODE,0x954b,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8af5,0x9445,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9c75,0x8e75,0x9659,0x965a, + UDCODE,UDCODE,0x899e,0x9c7a,0xfabb,UDCODE,0x9289,UDCODE,UDCODE, + UDCODE,0x9c77,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89f5, + UDCODE,UDCODE,UDCODE,UDCODE,0x9cab,0x9c79,UDCODE,UDCODE,UDCODE, + 0x944f,UDCODE,UDCODE,0x9c78,UDCODE,UDCODE,0x9c76,UDCODE,0x8d9a, + UDCODE,0x9c7c,0x9c83,0x9c89,0x9c81,UDCODE,0x937b,UDCODE,UDCODE, + 0x9c86,0x957c,UDCODE,UDCODE,0x9c80,UDCODE,0x9c85,0x97e5,0x8e76, + UDCODE,UDCODE,0x91d3,0x9c7d,UDCODE,UDCODE,UDCODE,0x8b7d,0x9c88, + 0x90ab,0x8985,0x9c82,0x89f6,0x9c87,UDCODE,UDCODE,UDCODE,0x8baf, + UDCODE,0x9c84,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9c8a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9c8c, + 0x9c96,0x9c94,UDCODE,UDCODE,0x9c91,UDCODE,UDCODE,UDCODE,0x9c90, + 0x97f6,UDCODE,0x9c92,UDCODE,UDCODE,0x8bb0,UDCODE,0x8d50,UDCODE, + UDCODE,0x8f9a,UDCODE,UDCODE,UDCODE,0x9c99,0x9c8b,UDCODE,UDCODE, + 0xfabc,UDCODE,0x9c8f,0x9c7e,UDCODE,0x89f8,0x9c93,0x9c95,0x9270, + UDCODE,UDCODE,0x8da6,0x89b6,0x9c8d,0x9c98,0x9c97,0x8bb1,UDCODE, + 0x91a7,0x8a86,UDCODE,UDCODE,UDCODE,UDCODE,0x8c62,UDCODE,0x9c8e, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9c9a,UDCODE,0x9c9d,0x9c9f,0xfabd,UDCODE,UDCODE,UDCODE,0x8ebb, + 0xfabe,0x9ca5,0x92ee,0x9c9b,UDCODE,UDCODE,UDCODE,UDCODE,0x9ca3, + UDCODE,0x89f7,UDCODE,0x9ca1,0x9ca2,UDCODE,UDCODE,0x9c9e,0x9ca0, + UDCODE,UDCODE,UDCODE,0x8ce5,0x9749,UDCODE,UDCODE,0x8ab3,UDCODE, + UDCODE,0x8978,0x9ca4,UDCODE,0x9459,0x88ab,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x94df,0x9c7b,0x9caa,0x9cae,0x96e3, + UDCODE,0x9ca7,UDCODE,UDCODE,UDCODE,0x9389,0x9cac,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8fee,0x9cad,0x93d5,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9866, + UDCODE,0x9ca9,UDCODE,0xfac0,UDCODE,UDCODE,0x9caf,UDCODE,0x8d9b, + UDCODE,0x90c9,UDCODE,0xfabf,0x88d2,0x9ca8,0x9ca6,UDCODE,0x9179, + UDCODE,UDCODE,UDCODE,0x9c9c,0x8e53,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x91c4,0x9cbb,0xfac2,0x917a,0x9cb6,UDCODE, + 0x9cb3,0x9cb4,UDCODE,0x8ee4,0x9cb7,0x9cba,0x9cb5,0x8f44,UDCODE, + 0x9cb8,UDCODE,UDCODE,0x9cb2,UDCODE,0x96fa,0x96f9,UDCODE,UDCODE, + UDCODE,0x9cbc,0x9cbd,0x88d3,UDCODE,0xfac3,UDCODE,UDCODE,UDCODE, + 0x9cb1,UDCODE,UDCODE,UDCODE,UDCODE,0x8bf0,0x88a4,UDCODE,UDCODE, + UDCODE,0x8ab4,0xfac1,0x9cb9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9cc1,0x9cc0,UDCODE,UDCODE,UDCODE,0x9cc5,UDCODE,UDCODE,UDCODE, + 0xfac5,UDCODE,UDCODE,UDCODE,0x9cc6,UDCODE,UDCODE,0xfac4,UDCODE, + UDCODE,UDCODE,UDCODE,0x9cc4,0x9cc7,0x9cbf,0x9cc3,UDCODE,UDCODE, + 0x9cc8,UDCODE,0x9cc9,UDCODE,UDCODE,0x9cbe,0x8e9c,UDCODE,0x9cc2, + 0x91d4,0x8d51,0x9cb0,0x9054,UDCODE,UDCODE,UDCODE,UDCODE,0x9cd6, + UDCODE,0x95e7,UDCODE,UDCODE,0x9ccc,0x9ccd,0x9cce,UDCODE,UDCODE, + 0x9cd5,UDCODE,0x9cd4,UDCODE,UDCODE,0x969d,0x8ab5,UDCODE,0x9cd2, + UDCODE,0x8c64,0x8a53,UDCODE,UDCODE,0x9ccf,UDCODE,UDCODE,0x97b6, + 0x9cd1,0x88d4,0x9cd3,UDCODE,0x9cca,0x9cd0,0x9cd7,0x8c63,0x9ccb, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x977c,UDCODE,UDCODE, + UDCODE,0x974a,UDCODE,UDCODE,UDCODE,UDCODE,0x9cda,UDCODE,UDCODE, + 0x9cde,UDCODE,UDCODE,UDCODE,0x919e,UDCODE,0x97f7,0x9cdf,UDCODE, + UDCODE,0x9cdc,UDCODE,0x9cd9,UDCODE,0xfac6,0x9cd8,0x9cdd,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95ae, + UDCODE,UDCODE,0x93b2,UDCODE,0x8c65,UDCODE,0x9ce0,0x9cdb,UDCODE, + 0x9ce1,UDCODE,UDCODE,UDCODE,0x8c9b,UDCODE,UDCODE,UDCODE,0x89af, + UDCODE,UDCODE,UDCODE,0x9ce9,UDCODE,UDCODE,UDCODE,0x8ab6,UDCODE, + UDCODE,UDCODE,UDCODE,0x9ce7,UDCODE,UDCODE,0x9ce8,0x8da7,0x9ce6, + 0x9ce4,0x9ce3,0x9cea,0x9ce2,0x9cec,UDCODE,UDCODE,0x89f9,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9cee, + UDCODE,UDCODE,0x9ced,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x92a6,UDCODE,0x9cf1,UDCODE, + 0x9cef,0x9ce5,0x8c9c,UDCODE,0x9cf0,UDCODE,0x9cf4,0x9cf3,0x9cf5, + 0x9cf2,0x9cf6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9cf7,0x9cf8,0x95e8,UDCODE,0x9cfa,0x9cf9,0x8f5e,UDCODE,0x90ac, + 0x89e4,0x89fa,0xfac7,0x9cfb,UDCODE,0x88bd,UDCODE,UDCODE,UDCODE, + 0x90ca,0x9cfc,UDCODE,0xe6c1,0x9d40,0x8c81,UDCODE,0x9d41,UDCODE, + UDCODE,UDCODE,UDCODE,0x90ed,UDCODE,UDCODE,UDCODE,0x9d42,UDCODE, + UDCODE,UDCODE,0x9d43,0x8b59,0x9d44,UDCODE,0x9d45,0x9d46,0x91d5, + UDCODE,UDCODE,UDCODE,0x8ccb,UDCODE,UDCODE,0x96df,UDCODE,UDCODE, + UDCODE,0x965b,0x8f8a,0x9d47,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x90ee,0xe7bb,0x94e0,UDCODE,0x8ee8,UDCODE,0x8dcb,0x9d48,UDCODE, + UDCODE,UDCODE,UDCODE,0x91c5,UDCODE,0x95a5,UDCODE,UDCODE,0x91ef, + UDCODE,UDCODE,0x9d4b,UDCODE,UDCODE,0x9d49,UDCODE,0x9d4c,UDCODE, + UDCODE,0x9d4a,UDCODE,UDCODE,UDCODE,UDCODE,0x9d4d,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x95af,UDCODE,UDCODE,0x88b5,UDCODE,UDCODE, + UDCODE,UDCODE,0x957d,UDCODE,UDCODE,0x94e1,UDCODE,UDCODE,0x9d4e, + UDCODE,0x9d51,0x8fb3,0x8b5a,UDCODE,0x9d4f,0x9d56,0x8fb4,UDCODE, + UDCODE,UDCODE,UDCODE,0x9d50,0x9463,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x977d,0x9d52,0x9d53,0x9d57,0x938a,0x9d54,0x8d52, + 0x90dc,UDCODE,UDCODE,0x9d65,0x94b2,UDCODE,0x91f0,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfac8,UDCODE,UDCODE,UDCODE, + UDCODE,0x94e2,0x9dab,UDCODE,UDCODE,UDCODE,UDCODE,0x95f8,UDCODE, + UDCODE,UDCODE,0x92ef,UDCODE,UDCODE,UDCODE,0x9695,UDCODE,0x9d5a, + 0x899f,0x928a,UDCODE,UDCODE,UDCODE,UDCODE,0x9d63,UDCODE,UDCODE, + 0x9253,0x9d5d,0x9d64,0x9d5f,0x9d66,0x9d62,UDCODE,0x9d61,0x948f, + UDCODE,0x9d5b,0x89fb,0x9d59,0x8b91,0x91f1,0x9d55,UDCODE,UDCODE, + 0x9d58,0x8d53,0x90d9,UDCODE,0x8fb5,0x9d60,0x9471,UDCODE,UDCODE, + 0x8b92,0x8a67,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8a87,0x9040,0x9d68,0x9d6d,UDCODE,0x9d69, + UDCODE,0x8c9d,UDCODE,0x9d6e,0x8e41,0x8d89,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8f45,0x9d5c,0x8e9d,0x9d6b,UDCODE,UDCODE, + UDCODE,UDCODE,0x8e77,0x9d6c,0x88c2,UDCODE,UDCODE,0x9d67,UDCODE, + UDCODE,UDCODE,UDCODE,0x92a7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8b93,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8bb2, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9d6a,0x88a5, + UDCODE,UDCODE,0x8dc1,UDCODE,UDCODE,UDCODE,0x9055,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x92f0, + UDCODE,UDCODE,0x94d2,0x9d70,0x917d,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x91a8,UDCODE,UDCODE,0x8e4a, + 0x9d71,UDCODE,0x9d73,0x9d6f,UDCODE,UDCODE,UDCODE,UDCODE,0x95df, + UDCODE,0x92bb,UDCODE,UDCODE,UDCODE,UDCODE,0x917b,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95f9, + 0x8ecc,0x9d80,UDCODE,0x9d7e,UDCODE,UDCODE,0x9098,UDCODE,UDCODE, + UDCODE,0x8c9e,UDCODE,UDCODE,UDCODE,0x9d78,0x8fb7,UDCODE,UDCODE, + 0x93e6,0x9450,UDCODE,UDCODE,UDCODE,UDCODE,0x9d76,UDCODE,UDCODE, + 0x917c,UDCODE,UDCODE,UDCODE,UDCODE,0x8ef6,0x9d7b,UDCODE,UDCODE, + 0x8fb6,UDCODE,0x9d75,0x9d7a,UDCODE,UDCODE,0x9472,UDCODE,UDCODE, + UDCODE,0x9d74,UDCODE,0x8c40,UDCODE,UDCODE,0x8a7c,UDCODE,UDCODE, + UDCODE,0x9d7c,0x97a9,0x8dcc,0x9254,0x9d79,UDCODE,0x90da,UDCODE, + 0x8d54,0x9084,0x8986,0x915b,0x9d77,0x8b64,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8c66,UDCODE,0x92cd,0x9d7d,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x917e,UDCODE,UDCODE,0x9d81,UDCODE,0x9d83,UDCODE, + UDCODE,0x91b5,0x9d89,UDCODE,0x9d84,UDCODE,UDCODE,0x9d86,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9560,0x92f1,UDCODE,0x9d87,UDCODE, + UDCODE,UDCODE,0x974b,UDCODE,UDCODE,UDCODE,0x9767,0x8ab7,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x88ac,UDCODE,0x9d85,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9d82,UDCODE,UDCODE,UDCODE,UDCODE,0x8af6, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8987,0xfac9,0x9d88,UDCODE, + UDCODE,UDCODE,0x9768,0x9d8c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x91b9,UDCODE,0x9d93,UDCODE,UDCODE,UDCODE,0x9d8d,UDCODE, + UDCODE,0x9d8a,0x9d91,UDCODE,UDCODE,UDCODE,UDCODE,0x9d72,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9d8e, + UDCODE,0x9d92,UDCODE,UDCODE,UDCODE,0x94c0,0x938b,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9d8b,UDCODE,0x9d8f,UDCODE,UDCODE, + UDCODE,0x8c67,UDCODE,UDCODE,UDCODE,0x8def,UDCODE,UDCODE,UDCODE, + 0x90db,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9d97,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9345,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xfaca,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9d94,UDCODE,0x9680,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9d95,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9d96,UDCODE, + 0x96cc,UDCODE,0x90a0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8c82,UDCODE,UDCODE,UDCODE,UDCODE,0x9d9d,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8e54, + 0x9d9a,UDCODE,0x9d99,UDCODE,UDCODE,UDCODE,UDCODE,0x9451,UDCODE, + UDCODE,0xfacb,0x93b3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9350, + 0x9d9b,UDCODE,UDCODE,UDCODE,0x9d9c,UDCODE,0x958f,UDCODE,0x9464, + 0x8e42,UDCODE,0x90ef,UDCODE,0x966f,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8a68,UDCODE,0x9da3,0x9d9e,UDCODE,UDCODE,UDCODE, + UDCODE,0x9769,0x9da5,UDCODE,UDCODE,0x9da1,UDCODE,0x9da2,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9180,0xfacc,UDCODE,UDCODE,UDCODE, + 0x9da0,UDCODE,0x9d5e,UDCODE,UDCODE,UDCODE,0x9da4,UDCODE,0x9d9f, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9da9,0x9daa,0x9346,0x9dac, + UDCODE,UDCODE,0x8e43,0x9da7,UDCODE,UDCODE,UDCODE,UDCODE,0x8b5b, + UDCODE,UDCODE,0x9dad,UDCODE,0x9da6,0x9db1,UDCODE,0x9db0,UDCODE, + 0x9daf,UDCODE,UDCODE,UDCODE,0x9db2,UDCODE,UDCODE,0x9db4,0x8fef, + 0x9db3,UDCODE,UDCODE,UDCODE,UDCODE,0x9db7,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9db5,UDCODE,UDCODE, + UDCODE,0x9db6,0x9d90,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9db9, + 0x9db8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9d98,0x9dba,0x9dae, + UDCODE,UDCODE,0x8e78,UDCODE,UDCODE,UDCODE,UDCODE,0x9dbb,0x9dbc, + 0x9dbe,0x9dbd,0x9dbf,0x89fc,UDCODE,0x8d55,UDCODE,UDCODE,0x95fa, + 0x90ad,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ccc,UDCODE,UDCODE, + 0x9dc1,UDCODE,UDCODE,UDCODE,UDCODE,0x9dc4,0xfacd,0x9571,UDCODE, + 0x8b7e,UDCODE,UDCODE,UDCODE,0x9dc3,0x9dc2,0x9473,0x9dc5,0x8bb3, + UDCODE,UDCODE,UDCODE,0x9dc7,0x9dc6,UDCODE,UDCODE,UDCODE,0x8ab8, + 0x8e55,UDCODE,UDCODE,0x93d6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8c68,UDCODE,UDCODE,UDCODE,0x9094,UDCODE,0x9dc8,UDCODE,0x90ae, + 0x9347,UDCODE,0x957e,0x9dc9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9dca,0x9dcb,UDCODE,UDCODE,UDCODE, + 0x95b6,0x9b7c,0x90c4,UDCODE,UDCODE,0x956b,UDCODE,0x8dd6,UDCODE, + 0x94e3,0x94c1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x936c,UDCODE, + 0x97bf,UDCODE,0x9dcd,0x8ece,UDCODE,UDCODE,0x9dce,UDCODE,0x88b4, + UDCODE,UDCODE,0x8bd2,0x90cb,UDCODE,0x9580,UDCODE,UDCODE,UDCODE, + 0x9dcf,0x8e61,0x9266,UDCODE,0x8e7a,0x9056,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9dd0,UDCODE,0x95fb,UDCODE,UDCODE,0x8997, + 0x8e7b,UDCODE,UDCODE,UDCODE,0x9dd3,UDCODE,0x9dd1,0x9dd4,0x97b7, + 0x9dd2,UDCODE,UDCODE,UDCODE,UDCODE,0x90f9,0x9dd5,UDCODE,UDCODE, + 0x91b0,UDCODE,UDCODE,0x9dd6,UDCODE,UDCODE,UDCODE,UDCODE,0x8af8, + UDCODE,0x9dd8,UDCODE,0x9dd7,UDCODE,UDCODE,UDCODE,UDCODE,0x9dd9, + 0x9dda,0x8af9,UDCODE,UDCODE,0x93fa,0x9255,0x8b8c,0x8e7c,0x9181, + UDCODE,UDCODE,0x8f7b,0x88ae,UDCODE,UDCODE,UDCODE,0x9ddb,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89a0,0x9ddf, + 0xface,UDCODE,0x8d56,0x9dde,UDCODE,UDCODE,0x8da9,0x8fb8,UDCODE, + 0xfad1,0x9ddd,UDCODE,0x8fb9,UDCODE,0x96be,0x8da8,UDCODE,UDCODE, + UDCODE,0x88d5,0x90cc,0xfacf,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9de4,UDCODE,0xfad3,0x90af,0x8966,UDCODE,UDCODE,UDCODE, + 0xfad4,0x8f74,UDCODE,0x9686,0x8df0,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8fba,0xfad2,0x90a5,UDCODE,0xfa63,UDCODE,UDCODE,0x9de3,0x9de1, + 0x9de2,UDCODE,UDCODE,UDCODE,UDCODE,0xfad0,0x928b,UDCODE,UDCODE, + 0x9e45,UDCODE,0x9de8,0x8e9e,0x8d57,0x9de6,UDCODE,UDCODE,UDCODE, + UDCODE,0x9de7,UDCODE,0x9057,UDCODE,UDCODE,UDCODE,0x9de5,UDCODE, + UDCODE,0x8e4e,UDCODE,UDCODE,UDCODE,UDCODE,0xfad6,UDCODE,0xfad7, + UDCODE,UDCODE,UDCODE,0x9dea,0x9de9,0x9dee,UDCODE,UDCODE,0x9def, + UDCODE,0x9deb,0xfad5,0x8a41,0x9dec,0x9ded,0x94d3,UDCODE,UDCODE, + UDCODE,UDCODE,0x9581,0x8c69,0x9df0,UDCODE,UDCODE,0xfad9,0x90b0, + UDCODE,0x8fbb,UDCODE,UDCODE,UDCODE,0x9271,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8bc5,UDCODE,0x9df1,0x9df5,UDCODE,UDCODE, + 0x89c9,0x9df2,0x9df4,UDCODE,UDCODE,UDCODE,UDCODE,0x9df3,UDCODE, + UDCODE,0x8f8b,UDCODE,UDCODE,UDCODE,UDCODE,0x9267,0x88c3,0x9df6, + 0xfada,UDCODE,UDCODE,UDCODE,0x9df7,UDCODE,UDCODE,0xfadb,UDCODE, + 0x92a8,UDCODE,UDCODE,UDCODE,0x97ef,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8e62,UDCODE,UDCODE,0x95e9,UDCODE,UDCODE,UDCODE,0xfadc,UDCODE, + 0x965c,UDCODE,UDCODE,UDCODE,0x9e41,0x9df9,UDCODE,UDCODE,0x9dfc, + UDCODE,0x9dfb,0xfadd,UDCODE,0x9df8,UDCODE,UDCODE,0x9e40,UDCODE, + UDCODE,0x93dc,UDCODE,0x9dfa,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e42,UDCODE, + UDCODE,0x8f8c,0x9e43,UDCODE,0x976a,0x9498,UDCODE,UDCODE,0x9e44, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e46,UDCODE,UDCODE,0x9e47, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e48,UDCODE,0x8bc8, + 0x8967,0x8d58,0x9e49,UDCODE,0x9e4a,0x8f91,0x9182,0xfade,0xfa66, + 0x99d6,0x915d,0x915c,0x91d6,0x8dc5,UDCODE,UDCODE,0x98f0,UDCODE, + UDCODE,UDCODE,UDCODE,0x8c8e,0x974c,UDCODE,0x95fc,UDCODE,0x959e, + 0xfadf,0x9e4b,UDCODE,UDCODE,UDCODE,UDCODE,0x8df1,0x92bd,0x9e4c, + 0x984e,UDCODE,UDCODE,UDCODE,0x965d,UDCODE,0x92a9,0x9e4d,0x8afa, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e4e,0x9e4f,0x96d8, + UDCODE,0x96a2,0x9696,0x967b,0x8e44,0x9e51,UDCODE,UDCODE,0x8ee9, + UDCODE,UDCODE,0x9670,UDCODE,0x9e53,0x9e56,0x9e55,UDCODE,0x8af7, + UDCODE,UDCODE,0x8b80,UDCODE,0x9e52,UDCODE,0x9e54,UDCODE,UDCODE, + UDCODE,UDCODE,0x9e57,UDCODE,UDCODE,0x9099,UDCODE,UDCODE,UDCODE, + UDCODE,0x979b,0x88c7,0x8dde,0x91ba,UDCODE,0x8edb,UDCODE,UDCODE, + 0x8ff1,UDCODE,UDCODE,0x9e5a,UDCODE,UDCODE,0x936d,UDCODE,0x9e58, + 0x91a9,0x9e59,0x8ff0,0x96db,0x9e5b,0x9e5c,0x9788,0xfae1,UDCODE, + UDCODE,UDCODE,0x9e61,UDCODE,UDCODE,0x8d59,UDCODE,0x9474,0x9e5e, + 0x938c,0x9ddc,0x9de0,UDCODE,0x8b6e,UDCODE,0x9466,UDCODE,UDCODE, + UDCODE,UDCODE,0x9e60,UDCODE,0x8fbc,0x94c2,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9e66,UDCODE,0x94f8,UDCODE,0x9e5d,UDCODE,0x9e63, + 0x9e62,UDCODE,UDCODE,UDCODE,0x90cd,UDCODE,UDCODE,UDCODE,UDCODE, + 0x968d,UDCODE,0x97d1,UDCODE,UDCODE,0x9687,UDCODE,0x89ca,0x8e7d, + UDCODE,UDCODE,0x9867,0x9e65,0x9095,UDCODE,UDCODE,UDCODE,0x9e64, + UDCODE,UDCODE,0x9e5f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ccd, + UDCODE,UDCODE,UDCODE,0x9e6b,0x9e69,UDCODE,0x89cb,0x9e67,0x9e6d, + 0x9e73,UDCODE,0xfae2,UDCODE,UDCODE,UDCODE,UDCODE,0xfae4,0x91c6, + UDCODE,UDCODE,0x95bf,UDCODE,0x9e75,UDCODE,UDCODE,UDCODE,0x9541, + UDCODE,UDCODE,UDCODE,0x9e74,0x9490,0x965e,0x8ab9,UDCODE,0x90f5, + 0x8f5f,UDCODE,UDCODE,UDCODE,0x92d1,UDCODE,0x974d,UDCODE,UDCODE, + 0x9e70,0x9e6f,UDCODE,UDCODE,UDCODE,0x9e71,UDCODE,0x9e6e,UDCODE, + UDCODE,0x9e76,UDCODE,0x9e6c,UDCODE,UDCODE,0x9e6a,UDCODE,0x9e72, + 0x9e68,UDCODE,0x928c,UDCODE,0x96f6,0x8ec4,0x8df2,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8db8,UDCODE,UDCODE,0x968f,0x8a60,0xfae5, + 0x92cc,0x93c8,0x8968,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90f0, + UDCODE,UDCODE,0x90b2,0x8c49,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9e78,UDCODE,UDCODE,0x8d5a,0x8a9c,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9e7a,0x8a94,0x9e81,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9e7d,UDCODE,0x90f1,UDCODE,UDCODE,UDCODE, + 0x8a6a,0x8daa,UDCODE,UDCODE,0x8a69,0x8dcd,UDCODE,UDCODE,0x9e7b, + 0x8c85,0x8c6a,0x938d,0xfae6,UDCODE,0x9e79,UDCODE,0x88c4,UDCODE, + UDCODE,UDCODE,UDCODE,0x9e7c,0x9e7e,UDCODE,0x8bcb,0x8c4b,0xfae3, + 0x8aba,0x8b6a,UDCODE,UDCODE,UDCODE,UDCODE,0x9e82,UDCODE,UDCODE, + 0x8df7,0x9691,UDCODE,0x8e56,UDCODE,UDCODE,UDCODE,0x9e83,UDCODE, + UDCODE,UDCODE,0x954f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e8f,UDCODE,0x89b1, + 0x9e84,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9e95,0x9e85, + UDCODE,0x97c0,UDCODE,0x9e8c,UDCODE,0x947e,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9e94,UDCODE,0x9e87,UDCODE,UDCODE, + UDCODE,0x88b2,0x9e89,UDCODE,UDCODE,0x8d5b,UDCODE,UDCODE,UDCODE, + 0x9e8b,UDCODE,0x9e8a,UDCODE,0x9e86,0x9e91,UDCODE,0x8fbd,UDCODE, + UDCODE,UDCODE,0x9aeb,0x8ce6,0x979c,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9e88,UDCODE,0x92f2,0x8a42,0x8dab,UDCODE,0x9e80,UDCODE,0x9e90, + 0x8a81,UDCODE,UDCODE,0x9e8e,0x9e92,UDCODE,0x938e,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8afc,UDCODE,0x9eb0,UDCODE, + 0xfa64,0x96c7,0x9e97,0x8afb,UDCODE,0x9e9e,UDCODE,0xfae7,UDCODE, + UDCODE,0x965f,UDCODE,0x9e9f,0x9ea1,UDCODE,0x9ea5,0x9e99,UDCODE, + 0x9249,UDCODE,UDCODE,UDCODE,UDCODE,0x938f,0x9ea9,0x9e9c,UDCODE, + 0x9ea6,UDCODE,UDCODE,UDCODE,0x9ea0,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9058,0x9eaa,UDCODE,UDCODE,0x90b1,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9ea8,0x8abb,0x986f,0x9e96,UDCODE, + UDCODE,0x9ea4,0x88d6,UDCODE,UDCODE,0x9e98,UDCODE,UDCODE,0x96b8, + 0x9e9d,0x9041,0x92c5,0x9e93,UDCODE,UDCODE,0x9ea3,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x909a,0x9ead,0x8a91,0x8c9f,UDCODE, + UDCODE,UDCODE,UDCODE,0x9eaf,0x9e9a,0x9eae,UDCODE,0x9ea7,0x9e9b, + UDCODE,0x9eab,UDCODE,0x9eac,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9ebd,UDCODE,UDCODE,UDCODE,0x93cc,UDCODE,0x9ea2,UDCODE,UDCODE, + 0x9eb9,UDCODE,UDCODE,UDCODE,0x9ebb,UDCODE,0x92d6,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x976b, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9596, + 0x9eb6,0x91c8,UDCODE,UDCODE,UDCODE,0x9ebc,0x915e,UDCODE,0x9eb3, + 0x9ec0,0x9ebf,UDCODE,0x93ed,0x9ebe,0x93e8,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xfae9,UDCODE,0x9ec2,0x9eb5,UDCODE,0x8bc6,0x9eb8, + 0x8f7c,UDCODE,UDCODE,UDCODE,0x9480,0x9eba,0x8bc9,UDCODE,0x9eb2, + 0x9eb4,0x9eb1,UDCODE,UDCODE,0x984f,0x8a79,0x9eb7,UDCODE,UDCODE, + 0x9ec1,0x8a54,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8de5,UDCODE,UDCODE,UDCODE,0x897c,UDCODE,UDCODE,0x9ed2,UDCODE, + UDCODE,0x9850,0x9ed5,UDCODE,UDCODE,0xfaeb,UDCODE,UDCODE,0x9059, + 0x9ed4,UDCODE,UDCODE,UDCODE,0x9ed3,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9ed0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9ec4,UDCODE,UDCODE,0x9ee1,0x9ec3,UDCODE,0x9ed6,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9ece,UDCODE,UDCODE,0x9ec9,0x9ec6, + UDCODE,0x9ec7,UDCODE,0x9ecf,UDCODE,UDCODE,UDCODE,0xeaa0,UDCODE, + UDCODE,0x9ecc,0x8d5c,0x92c6,0x9184,0x9eca,UDCODE,0x9ec5,UDCODE, + UDCODE,0x9ec8,UDCODE,UDCODE,UDCODE,UDCODE,0x976c,0x968a,UDCODE, + UDCODE,UDCODE,0x9ecd,0x9ed7,UDCODE,UDCODE,UDCODE,0xfaec,UDCODE, + UDCODE,UDCODE,UDCODE,0x9edf,0x9ed8,UDCODE,UDCODE,0x9ee5,UDCODE, + 0x9ee3,UDCODE,UDCODE,UDCODE,UDCODE,0x9ede,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9edd,UDCODE,0x92ce,UDCODE,0x9185,UDCODE, + 0x9edb,0x9ed9,UDCODE,UDCODE,0x9ee0,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9ee6,0x94f3,0x9eec,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ee7, + 0x9eea,0x9ee4,UDCODE,UDCODE,0x9294,UDCODE,0x9557,UDCODE,0x9eda, + UDCODE,UDCODE,0x9ee2,0x8fbe,UDCODE,0x96cd,0x9ef6,0x9ee9,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8ca0,0x89a1,0x8a7e,UDCODE,UDCODE, + 0x9ed1,UDCODE,0xfaed,UDCODE,UDCODE,UDCODE,UDCODE,0x8fbf,0x9eee, + UDCODE,0x9ef5,0x8ef7,0x8a92,UDCODE,UDCODE,0x924d,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9eeb,UDCODE,0xfaef,0x9ef0,0x9ef4, + UDCODE,UDCODE,0x8bb4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b6b,0x9ef2,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8b40,UDCODE,0x93c9,0x9ef1,UDCODE, + UDCODE,UDCODE,0x9ef3,UDCODE,UDCODE,UDCODE,UDCODE,0xfaee,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9eed,0xfaf0,UDCODE,UDCODE, + UDCODE,UDCODE,0x9eef,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfaf1, + 0x8a80,0x9268,UDCODE,UDCODE,UDCODE,0x9efa,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ef8,0x8ce7,UDCODE,0x9ef7, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f40,UDCODE,UDCODE, + UDCODE,UDCODE,0x9e77,UDCODE,UDCODE,UDCODE,0x9ef9,UDCODE,0x9efb, + 0x9efc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f4b,UDCODE, + 0x9f47,UDCODE,0x9e8d,UDCODE,UDCODE,UDCODE,UDCODE,0x9f46,UDCODE, + UDCODE,UDCODE,UDCODE,0x9f45,UDCODE,UDCODE,0x9f42,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9ee8,0x9f44,0x9f43,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9f49,UDCODE,0x9845,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9f4c,0x8bf9,UDCODE,UDCODE,0x9f48,0x9f4a,UDCODE,UDCODE, + 0xfaf2,UDCODE,0xfaf3,UDCODE,UDCODE,UDCODE,0x94a5,UDCODE,0x9f4d, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f51,0x9f4e,0x9793, + 0x9f4f,UDCODE,UDCODE,UDCODE,UDCODE,0x9edc,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9f52,UDCODE,UDCODE,UDCODE,0x9f53, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8954,UDCODE,0x9f55, + 0x8c87,0x8e9f,UDCODE,0x8bd3,UDCODE,UDCODE,UDCODE,0x89a2,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x977e,UDCODE,UDCODE,UDCODE,UDCODE,0x9f57,0x9f56,0x9f59,0x8b5c, + UDCODE,UDCODE,0x8bd4,0x8abc,UDCODE,UDCODE,UDCODE,UDCODE,0x9f5c, + UDCODE,UDCODE,UDCODE,0x9f5b,UDCODE,0x9f5d,UDCODE,UDCODE,0x89cc, + UDCODE,0x9256,UDCODE,0x9f5e,UDCODE,UDCODE,0x8abd,0x9f60,UDCODE, + UDCODE,UDCODE,UDCODE,0x9f5f,UDCODE,0x9f61,UDCODE,UDCODE,UDCODE, + 0x9f62,UDCODE,0x9f63,0x8e7e,0x90b3,0x8d9f,UDCODE,0x9590,UDCODE, + UDCODE,0x95e0,0x9863,UDCODE,UDCODE,UDCODE,UDCODE,0x8e95,UDCODE, + UDCODE,UDCODE,0x8dce,0x97f0,UDCODE,UDCODE,UDCODE,0x9f64,0x9f65, + UDCODE,0x8e80,UDCODE,UDCODE,UDCODE,0x9f66,0x9f67,UDCODE,UDCODE, + 0x9f69,0x9f68,UDCODE,0x9677,UDCODE,UDCODE,0x8f7d,0x8eea,0x8e63, + UDCODE,0x9f6a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9f6c,0x9042,UDCODE,0x9f6b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9f6d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f6e,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9f6f,0x9f70,UDCODE,UDCODE,UDCODE,0x9f71, + UDCODE,0x9f73,0x9f72,0x9f74,0x89a3,0x9269,UDCODE,0x9f75,UDCODE, + UDCODE,0x8e45,0x8a6b,0x9f76,UDCODE,UDCODE,0x9361,0x9aca,UDCODE, + UDCODE,UDCODE,UDCODE,0x8b42,0x9f77,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9f78,UDCODE,0x95ea,0x9688,UDCODE,UDCODE,UDCODE,0x93c5,0x9f79, + 0x94e4,UDCODE,0xfaf4,UDCODE,0x94f9,UDCODE,UDCODE,0x96d1,UDCODE, + UDCODE,UDCODE,0x9f7a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f7c,0x9f7b,UDCODE,UDCODE, + 0x9f7e,UDCODE,UDCODE,UDCODE,0x9f7d,0x9f81,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8e81,UDCODE,0x96af,UDCODE,0x9f82,0x9f83, + UDCODE,UDCODE,0x8b43,UDCODE,UDCODE,UDCODE,0x9f84,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9f86,0x9f85,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9085,UDCODE,UDCODE,0x9558,0x8969, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x94c3,0xfaf5,0x92f3,0x8f60, + 0x8b81,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x94c4,UDCODE,0x8eac,UDCODE,UDCODE,UDCODE, + UDCODE,0x9f88,UDCODE,0x8abe,UDCODE,UDCODE,0x8998,UDCODE,0xfaf6, + 0x93f0,0x9f87,0x8d5d,0x9272,UDCODE,0x9f89,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9f91,UDCODE,0x9f8a,UDCODE,UDCODE,UDCODE,UDCODE, + 0xfaf8,0x91bf,UDCODE,0x8b82,0x9f92,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8c88,UDCODE,UDCODE,0x8b44,0x9f90,UDCODE,UDCODE, + 0x9f8e,0x9f8b,0x9780,UDCODE,UDCODE,0xfaf7,UDCODE,0x92be,UDCODE, + UDCODE,UDCODE,0x93d7,0x9f8c,UDCODE,UDCODE,0x9f94,UDCODE,0x9f93, + 0x8c42,UDCODE,UDCODE,0x89ab,UDCODE,UDCODE,0x8db9,0x9f8d,0x9f8f, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9676,0x91f2,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9697,UDCODE,UDCODE, + 0x9f9c,UDCODE,UDCODE,0x9f9d,UDCODE,0x89cd,UDCODE,UDCODE,UDCODE, + UDCODE,0x95a6,0x96fb,0x9f9f,0x8ea1,0x8fc0,0x9f98,0x9f9e,0x8988, + UDCODE,0x8bb5,UDCODE,UDCODE,0x9f95,0x9f9a,UDCODE,UDCODE,UDCODE, + 0x90f2,0x9491,UDCODE,0x94e5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9f97,UDCODE,0x9640,UDCODE,0x9f99,UDCODE,0x9fa2,0xfaf9, + 0x9fa0,UDCODE,0x9f9b,UDCODE,UDCODE,UDCODE,0x9641,0x9467,0x8b83, + UDCODE,0x9344,UDCODE,UDCODE,0x928d,UDCODE,0x9fa3,UDCODE,UDCODE, + UDCODE,UDCODE,0x9fa1,0x91d7,0x9f96,UDCODE,0x896a,0xfafa,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x976d,0x9fae,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9fad,UDCODE,UDCODE,UDCODE,UDCODE,0x90f4, + UDCODE,0x9faa,UDCODE,0x978c,UDCODE,UDCODE,0x93b4,0x9fa4,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x92c3,UDCODE,UDCODE,UDCODE,0x896b, + 0x8d5e,0x9fa7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f46, + 0x9fac,UDCODE,0x9fab,0x9fa6,UDCODE,0x9fa9,UDCODE,UDCODE,0x8a88, + UDCODE,0x9fa8,0x9468,UDCODE,UDCODE,0x97ac,UDCODE,UDCODE,0x8ff2, + 0x90f3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9fb4,0x9fb2,UDCODE,0x956c,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9faf,0x9fb1,UDCODE,0x8959,UDCODE,UDCODE, + 0x8d5f,0x9851,UDCODE,0x8a5c,UDCODE,0x9582,0xfafc,UDCODE,UDCODE, + UDCODE,UDCODE,0x9781,UDCODE,UDCODE,0x8a43,0x905a,0x9fb3,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9fb8,UDCODE,0xfafb,0x8fc1,UDCODE,UDCODE,UDCODE,0x974f, + UDCODE,0x9fb5,UDCODE,UDCODE,UDCODE,UDCODE,0x9fb0,UDCODE,0x9fb6, + 0xfb40,UDCODE,UDCODE,0x97dc,UDCODE,0x9393,0x93c0,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xfb41,UDCODE,UDCODE,0x8a55,UDCODE, + UDCODE,0x8974,UDCODE,UDCODE,0x9fbc,UDCODE,UDCODE,0x9fbf,UDCODE, + UDCODE,UDCODE,0x97c1,UDCODE,UDCODE,UDCODE,0x9784,UDCODE,UDCODE, + UDCODE,UDCODE,0x9fc6,0x9fc0,0x9fbd,UDCODE,UDCODE,UDCODE,0x97d2, + 0x9fc3,UDCODE,UDCODE,0xfb42,UDCODE,0x8f69,0x9fc5,UDCODE,UDCODE, + 0x9fca,UDCODE,UDCODE,0x9391,0x9fc8,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9fc2,UDCODE,UDCODE,0x9257,UDCODE,UDCODE,0x9fc9,UDCODE,0x9fbe, + UDCODE,0x9fc4,UDCODE,0x9fcb,0x88fa,0x9fc1,UDCODE,0x9fcc,UDCODE, + UDCODE,0x905b,0xfb44,0x8f7e,UDCODE,0x95a3,UDCODE,0x8dac,0xfb43, + 0x9fb9,0x9fc7,0x9359,0xfb45,0x90b4,UDCODE,0x8a89,0x8dcf,0x8fc2, + 0x9fbb,0x8f61,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8c6b,UDCODE,0x9fba,UDCODE,UDCODE,UDCODE,0x9fd0,0x8f8d,0x8cb8, + UDCODE,0x9fdf,UDCODE,0x9fd9,0x8b94,0x936e,UDCODE,0x9fd4,0x9fdd, + 0x88ad,0x8951,0xfb48,UDCODE,0x89b7,UDCODE,0x9fd6,0x91aa,0x9fcd, + 0x9fcf,0x8d60,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9fe0,0xfb46,0x9fdb,UDCODE,0xfb49,UDCODE,0x9fd3,UDCODE, + UDCODE,UDCODE,UDCODE,0x9fda,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x96a9,UDCODE,UDCODE,0x9fd8,0x9fdc,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8cce,UDCODE,0x8fc3,UDCODE,UDCODE, + 0x9258,0xfb47,UDCODE,UDCODE,0x9fd2,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x974e,UDCODE,UDCODE,UDCODE,0x9fd5,UDCODE, + UDCODE,0x9fce,0x9392,UDCODE,UDCODE,0x9fd1,UDCODE,UDCODE,UDCODE, + 0x9fd7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9870, + 0x8ebc,0x969e,UDCODE,0x9fe1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x94ac,UDCODE,UDCODE,0x9fed,0x8cb9, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f80,UDCODE,0x9fe3,UDCODE, + UDCODE,UDCODE,0x97ad,0x8d61,UDCODE,0x9ff0,UDCODE,UDCODE,0x88ec, + UDCODE,UDCODE,0x9fee,UDCODE,UDCODE,UDCODE,UDCODE,0x9fe2,UDCODE, + UDCODE,UDCODE,UDCODE,0x9fe8,UDCODE,UDCODE,0x9fea,UDCODE,UDCODE, + UDCODE,0x976e,0x9fe5,UDCODE,UDCODE,0x934d,UDCODE,UDCODE,0x9fe7, + UDCODE,0xfb4a,UDCODE,UDCODE,0x9fef,UDCODE,0x9fe9,0x96c5,UDCODE, + UDCODE,UDCODE,0x9fe4,UDCODE,0x8ea0,0x9ffc,UDCODE,UDCODE,UDCODE, + UDCODE,0x8a8a,UDCODE,0x9fe6,0x9feb,0x9fec,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x91ea,0x91d8,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9ff4,UDCODE,UDCODE,0x9ffa,UDCODE,UDCODE,0x9ff8,UDCODE, + 0x9348,UDCODE,UDCODE,0xe042,0x9ff5,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9ff6,0x9fde,0x8b99,0x9559,UDCODE,UDCODE,UDCODE,0x8ebd, + UDCODE,UDCODE,0x8d97,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9852, + UDCODE,0x9ff2,UDCODE,0xe041,0x8989,0x9186,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9499,UDCODE, + 0x8abf,0x97f8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x969f,0x92d0,UDCODE,UDCODE,UDCODE,UDCODE,0x9ff9,0x9ffb,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9151,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe040,0x9ff7,UDCODE,0x9ff1,UDCODE,UDCODE,UDCODE,0x8ac1, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c89,UDCODE,UDCODE,UDCODE, + 0xe04e,UDCODE,UDCODE,0xe049,0x90f6,UDCODE,UDCODE,0x8a83,UDCODE, + UDCODE,UDCODE,UDCODE,0x8f81,UDCODE,0xe052,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe04b,0x92aa,0xe048,0x92d7,UDCODE,UDCODE, + UDCODE,0xe06b,UDCODE,UDCODE,UDCODE,0xe045,UDCODE,0xe044,UDCODE, + 0xe04d,UDCODE,UDCODE,UDCODE,0xe047,0xe046,0xe04c,UDCODE,0x909f, + UDCODE,0xe043,UDCODE,0xfb4b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe04f,UDCODE,UDCODE,0xe050,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8ac0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe055,UDCODE,0xe054,0xe056,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe059,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9362, + UDCODE,0xe053,UDCODE,0xfb4c,UDCODE,UDCODE,UDCODE,0xe057,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c83,0x91f7,0xe051,0x945a, + UDCODE,UDCODE,0xe058,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe05d,0xe05b, + UDCODE,UDCODE,0xe05e,UDCODE,UDCODE,0xe061,UDCODE,UDCODE,UDCODE, + 0xe05a,0x8d8a,0x9447,UDCODE,UDCODE,0x9fb7,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9794,0xe05c,UDCODE,0xe060,0x91f3,UDCODE, + 0xe05f,UDCODE,0xe04a,UDCODE,0xfb4d,0xe889,UDCODE,UDCODE,UDCODE, + 0xe064,UDCODE,UDCODE,UDCODE,0xe068,0xe066,UDCODE,UDCODE,UDCODE, + 0xfb4e,UDCODE,0xfb4f,UDCODE,0xe062,UDCODE,0xe063,UDCODE,UDCODE, + UDCODE,0xe067,UDCODE,0xe065,UDCODE,UDCODE,UDCODE,0x956d,UDCODE, + UDCODE,0xe06d,UDCODE,0xe06a,0xe069,UDCODE,0xe06c,0x93d2,0xe06e, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9295,0x91eb,0xfb50, + UDCODE,UDCODE,UDCODE,0x90a3,UDCODE,UDCODE,UDCODE,0xe06f,UDCODE, + 0xe071,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe070,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9ff3, + UDCODE,UDCODE,UDCODE,UDCODE,0xe072,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x93e5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe073,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x89ce,UDCODE,UDCODE,UDCODE,0x9394,0x8a44, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b84,UDCODE, + UDCODE,UDCODE,0x8edc,0x8dd0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xfb51,UDCODE,UDCODE,UDCODE,0x9846,0x9086,UDCODE, + UDCODE,UDCODE,0x898a,UDCODE,UDCODE,UDCODE,0xe075,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe074,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xfb52,0xe078,0x9259,0xe07b,0xe076, + UDCODE,UDCODE,UDCODE,0xe07a,UDCODE,UDCODE,UDCODE,UDCODE,0xe079, + 0x935f,0x88d7,0xfa62,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x97f3,UDCODE,UDCODE, + 0xe07d,UDCODE,UDCODE,UDCODE,0x8947,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe080,UDCODE,UDCODE,UDCODE, + 0xe07e,UDCODE,0xe07c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe077,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9642,UDCODE,UDCODE,UDCODE,0xe082,0xfb54,UDCODE,UDCODE, + UDCODE,UDCODE,0xe081,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfb53, + UDCODE,UDCODE,UDCODE,UDCODE,0x898b,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe084,0x95b0,UDCODE,0xe083,UDCODE,UDCODE,UDCODE,UDCODE,0x96b3, + UDCODE,UDCODE,UDCODE,UDCODE,0x8fc5,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9152,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8fc4, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xfb56,0xfb57,UDCODE,0x97f9,UDCODE,UDCODE,0xe08a,UDCODE,0x90f7, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe086,0xe08b,UDCODE, + UDCODE,0x898c,UDCODE,UDCODE,0xfb55,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe089,UDCODE,0x9481,0xe085,0xe088,0x8fc6,UDCODE,0x94cf, + UDCODE,UDCODE,0xe08c,UDCODE,0x8ecf,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x90f8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe08f, + UDCODE,UDCODE,UDCODE,0xe087,UDCODE,0x8c46,UDCODE,UDCODE,UDCODE, + UDCODE,0xe08d,UDCODE,UDCODE,UDCODE,UDCODE,0x976f,0xe090,UDCODE, + UDCODE,UDCODE,0xeaa4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f6e, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe091, + UDCODE,UDCODE,UDCODE,0xe092,UDCODE,UDCODE,UDCODE,UDCODE,0x944d, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe094,UDCODE, + UDCODE,UDCODE,UDCODE,0xe095,UDCODE,UDCODE,0xfb59,UDCODE,0x9452, + UDCODE,UDCODE,UDCODE,UDCODE,0x9395,0xe097,UDCODE,UDCODE,UDCODE, + UDCODE,0xe099,UDCODE,0x97d3,UDCODE,0xe096,UDCODE,0xe098,0x898d, + UDCODE,0xe093,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9a7a,0xe09a,UDCODE,UDCODE,UDCODE,UDCODE,0x9187,0x8e57,0xe09c, + UDCODE,UDCODE,UDCODE,UDCODE,0xe09b,0x9043,0x99d7,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe09d,UDCODE,UDCODE,UDCODE,0xe09f, + UDCODE,0xe08e,0xe09e,UDCODE,0xfb5a,0xe0a0,0x949a,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe0a1,UDCODE,UDCODE,0xe0a2,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe0a3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe0a4,UDCODE,0x92dc,UDCODE,0xe0a6, + 0xe0a5,UDCODE,UDCODE,0xe0a7,UDCODE,0xe0a8,UDCODE,UDCODE,0x8edd, + 0x9583,UDCODE,UDCODE,UDCODE,0x96ea,0xe0a9,0xe0aa,0x9175,0x8ea2, + 0xe0ab,0xe0ac,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0ad,0x95d0, + 0x94c5,UDCODE,UDCODE,0xe0ae,0x9476,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x92ab,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0af,0x89e5, + UDCODE,0x8b8d,UDCODE,0x96c4,UDCODE,0x96b4,UDCODE,0x89b2,0x9853, + UDCODE,UDCODE,UDCODE,UDCODE,0x9671,UDCODE,0x95a8,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90b5,UDCODE,0xe0b0, + UDCODE,UDCODE,UDCODE,UDCODE,0x93c1,UDCODE,UDCODE,UDCODE,0x8ca1, + 0xe0b1,UDCODE,0x8dd2,0xe0b3,0xe0b2,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe0b4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe0b5,UDCODE,UDCODE,UDCODE,0xe0b6,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b5d,UDCODE, + 0xe0b7,UDCODE,UDCODE,UDCODE,UDCODE,0xe0b8,UDCODE,UDCODE,UDCODE, + UDCODE,0x8ca2,UDCODE,UDCODE,0x94c6,UDCODE,0xfb5b,0xe0ba,UDCODE, + UDCODE,UDCODE,0x8ff3,UDCODE,UDCODE,0xe0b9,UDCODE,UDCODE,UDCODE, + UDCODE,0xfb5c,UDCODE,UDCODE,UDCODE,0x8bb6,0xe0bb,0xe0bd,UDCODE, + 0xe0bc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0be, + UDCODE,0x8ccf,UDCODE,0xe0bf,UDCODE,UDCODE,UDCODE,UDCODE,0x8be7, + UDCODE,0x915f,UDCODE,0x8d9d,UDCODE,UDCODE,UDCODE,UDCODE,0xe0c1, + 0xe0c2,0xe0c0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8eeb, + UDCODE,UDCODE,0x93c6,0x8bb7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe0c4,0x924b,0xe0c3,UDCODE,UDCODE, + 0x9854,0x9482,0xe0c7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0c9,0xe0c6,UDCODE,UDCODE, + UDCODE,0x96d2,0xe0c8,0xe0ca,UDCODE,0x97c2,UDCODE,UDCODE,UDCODE, + UDCODE,0xfb5d,0xe0ce,UDCODE,UDCODE,UDCODE,0xe0cd,0x9296,0x944c, + UDCODE,UDCODE,0x8ca3,0xe0cc,UDCODE,UDCODE,UDCODE,UDCODE,0xe0cb, + UDCODE,0x9750,0x9751,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe0cf,0x898e,UDCODE,UDCODE,UDCODE,UDCODE,0x8d96,0x8e82,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0d0,0xe0d1, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0d3,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x8f62,UDCODE,UDCODE,UDCODE,UDCODE,0xe0d5,UDCODE,0xe0d4, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0d6,UDCODE,0x8a6c,UDCODE, + UDCODE,0xe0d8,UDCODE,0xfb5f,0xe0d7,UDCODE,0xe0da,0xe0d9,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8cba,UDCODE, + UDCODE,0x97a6,UDCODE,0x8bca,UDCODE,0x89a4,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8be8,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8adf, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x97e6, + 0xe0dc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0de, + UDCODE,0xfb60,UDCODE,UDCODE,0xe0df,UDCODE,0x89cf,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe0db,0xfb61,0x8e58,UDCODE,UDCODE,0x92bf, + 0xe0dd,UDCODE,UDCODE,UDCODE,0xfb64,UDCODE,UDCODE,UDCODE,0xfb62, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0e2,UDCODE, + 0x8eec,UDCODE,UDCODE,0xfb63,UDCODE,0xe0e0,UDCODE,UDCODE,UDCODE, + UDCODE,0x8c5d,UDCODE,UDCODE,0x94c7,0xe0e1,UDCODE,UDCODE,0xe0fc, + UDCODE,UDCODE,UDCODE,0xfb66,UDCODE,UDCODE,0xe0e7,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8cbb,0x8b85,UDCODE,0xe0e4,0x979d,0xfb65, + UDCODE,0x97ae,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x91f4, + UDCODE,UDCODE,0xe0e6,0xfb67,UDCODE,UDCODE,0xfb69,0xfb68,UDCODE, + UDCODE,UDCODE,0xfb6a,UDCODE,UDCODE,UDCODE,0xe0e8,0x97d4,0x8bd5, + 0x94fa,0x9469,UDCODE,UDCODE,UDCODE,0xe0e9,UDCODE,UDCODE,UDCODE, + UDCODE,0xe0eb,UDCODE,0xe0ee,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0ea,UDCODE,UDCODE,UDCODE, + 0xe0ed,0x8ce8,0x896c,0xe0ef,UDCODE,0x9090,0xe0ec,0x97da,UDCODE, + 0xfb6b,0xe0f2,0xeaa2,UDCODE,UDCODE,UDCODE,UDCODE,0xe0f0,0xe0f3, + UDCODE,UDCODE,UDCODE,UDCODE,0xe0e5,0xe0f1,UDCODE,UDCODE,0x8dba, + UDCODE,UDCODE,0xe0f4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe0f5,UDCODE,UDCODE,UDCODE,UDCODE,0x979e,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xfb6c,UDCODE,0xe0f6,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0f7,0xfb6d,UDCODE, + UDCODE,0xe0e3,UDCODE,UDCODE,UDCODE,UDCODE,0xe0f8,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ac2,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x8ea3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe0f9,UDCODE,UDCODE,UDCODE, + UDCODE,0xe0fa,UDCODE,UDCODE,UDCODE,UDCODE,0xe0fb,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x895a,UDCODE,UDCODE,UDCODE, + 0xe140,UDCODE,0x955a,0xe141,UDCODE,UDCODE,0x8aa2,0xe142,UDCODE, + 0xe143,UDCODE,UDCODE,UDCODE,UDCODE,0xe144,UDCODE,0xe146,0xe147, + 0xe145,UDCODE,UDCODE,UDCODE,0x9572,0xe149,0xe148,0xfb6e,UDCODE, + 0xe14b,0xe14a,0xe14c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe14d,0xe14f,0xe14e,UDCODE,UDCODE,0x8d99,UDCODE,0xe151,UDCODE, + 0xe150,UDCODE,UDCODE,0x8ac3,UDCODE,0x9072,UDCODE,0x935b,UDCODE, + 0xe152,0x90b6,UDCODE,UDCODE,UDCODE,0x8e59,UDCODE,0x8999,0xe153, + UDCODE,0x9770,UDCODE,UDCODE,0x95e1,0xe154,UDCODE,UDCODE,0xfaa8, + 0x9363,0x9752,0x8d62,0x905c,UDCODE,UDCODE,UDCODE,0x926a,0x99b2, + UDCODE,0x92ac,0x89e6,0xe155,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe156,UDCODE,0xe15b,UDCODE,UDCODE,0xe159,0xe158, + 0x9dc0,0x8a45,0xe157,UDCODE,0x88d8,UDCODE,0x94a8,UDCODE,UDCODE, + 0x94c8,UDCODE,UDCODE,UDCODE,UDCODE,0x97af,0xe15c,0xe15a,0x927b, + 0x90a4,UDCODE,UDCODE,0x94a9,UDCODE,0x954c,UDCODE,0xe15e,0x97aa, + 0x8c6c,0xe15f,UDCODE,0xe15d,0x94d4,0xe160,UDCODE,0xe161,UDCODE, + 0xfb6f,0x88d9,UDCODE,UDCODE,0x8ff4,0xe166,UDCODE,0xe163,0x93eb, + 0xe162,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b45,UDCODE, + UDCODE,0xe169,UDCODE,UDCODE,UDCODE,0xe164,0xe165,UDCODE,0xe168, + 0xe167,0x9544,UDCODE,UDCODE,0x9161,0x9160,UDCODE,0x8b5e,UDCODE, + UDCODE,0xe16a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe16b,UDCODE, + UDCODE,0xe16c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe16e,UDCODE, + 0xe16d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8975,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe176,0x94e6,0xe170,UDCODE,0xe172,UDCODE, + UDCODE,0xe174,0x905d,UDCODE,UDCODE,0xe175,0xe173,0x8ebe,UDCODE, + UDCODE,UDCODE,0xe16f,0xe171,UDCODE,0x9561,UDCODE,0x8fc7,UDCODE, + UDCODE,0xe178,UDCODE,UDCODE,0xe177,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe179,UDCODE,0x8ea4,0x8dad,UDCODE,UDCODE,0x9397,0xe17a,UDCODE, + 0x92c9,UDCODE,UDCODE,0xe17c,UDCODE,UDCODE,UDCODE,0x979f,0xe17b, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9189,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe182,UDCODE,0xe184,0xe185,0x9273,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe183,UDCODE,0xe180,UDCODE,0xe17d, + 0xe17e,0xe181,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe188,UDCODE,0xe186,UDCODE,0xe187,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe189,0xe18b,0xe18c,0xe18d,UDCODE, + 0xe18e,UDCODE,UDCODE,0xe18a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe190,UDCODE,UDCODE,UDCODE,0xe18f,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe191,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x97c3,UDCODE,UDCODE,UDCODE,0xe194,0xe192, + 0xe193,UDCODE,UDCODE,UDCODE,0x8ae0,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x96fc,UDCODE,UDCODE,UDCODE,0x95c8,UDCODE,0xe196,UDCODE, + UDCODE,UDCODE,0xe195,UDCODE,UDCODE,UDCODE,UDCODE,0xe197,0xe198, + UDCODE,UDCODE,UDCODE,UDCODE,0xe19c,0xe199,0xe19a,0xe19b,UDCODE, + 0xe19d,UDCODE,UDCODE,UDCODE,0xe19e,UDCODE,0xe19f,UDCODE,UDCODE, + UDCODE,0xe1a0,UDCODE,0xe1a1,UDCODE,0x94ad,0x936f,0xe1a2,0x9492, + 0x9553,UDCODE,0xe1a3,UDCODE,0xfb70,0xe1a4,0x9349,UDCODE,0x8a46, + 0x8d63,0xe1a5,UDCODE,UDCODE,0xe1a6,UDCODE,UDCODE,0xe1a7,UDCODE, + 0x8e48,UDCODE,UDCODE,0xe1a9,UDCODE,UDCODE,0xe1a8,UDCODE,UDCODE, + 0xe1aa,0xe1ab,0xfb73,0xfb71,UDCODE,0xfb72,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xfb74,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x94e7,UDCODE,0xe1ac,UDCODE,UDCODE,UDCODE, + 0xe1ad,UDCODE,UDCODE,0xea89,0xe1ae,0xe1af,0xe1b0,UDCODE,UDCODE, + UDCODE,UDCODE,0x8e4d,UDCODE,UDCODE,0xe1b1,0x9475,UDCODE,UDCODE, + 0x967e,UDCODE,0x896d,UDCODE,0x8976,UDCODE,UDCODE,0xe1b2,UDCODE, + UDCODE,UDCODE,UDCODE,0xe1b4,UDCODE,UDCODE,UDCODE,0xe1b3,0x9390, + UDCODE,UDCODE,UDCODE,0x90b7,0x9f58,UDCODE,0xe1b5,0x96bf,UDCODE, + 0xe1b6,UDCODE,0x8ac4,0x94d5,0xe1b7,UDCODE,0xe1b8,UDCODE,UDCODE, + 0xe1b9,UDCODE,UDCODE,UDCODE,0x96da,UDCODE,UDCODE,UDCODE,0x96d3, + UDCODE,0x92bc,UDCODE,UDCODE,UDCODE,0x918a,UDCODE,UDCODE,0xe1bb, + UDCODE,UDCODE,0x8f82,0x8fc8,UDCODE,UDCODE,0xe1be,UDCODE,UDCODE, + 0xe1bd,0xe1bc,0x94fb,UDCODE,0x8ac5,0x8ca7,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe1c4,UDCODE,UDCODE,0xe1c1,0x905e,0x96b0,UDCODE, + UDCODE,UDCODE,0xe1c0,0xe1c2,0xe1c3,UDCODE,UDCODE,0xe1bf,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe1c5,0xe1c6,UDCODE,0x92ad,UDCODE,0x8ae1, + UDCODE,UDCODE,UDCODE,0x9285,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xfb76,0xe1c7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe1c8,0xe1cb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9087,UDCODE,0x93c2,UDCODE,0xe1cc,0x9672,UDCODE,0xe1c9,UDCODE, + UDCODE,0xe1ca,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe1cf,UDCODE,UDCODE, + UDCODE,UDCODE,0xe1ce,0xe1cd,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe1d1,UDCODE,UDCODE, + 0xe1d0,UDCODE,UDCODE,0xe1d2,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe1d4,UDCODE, + 0xe1d3,UDCODE,UDCODE,UDCODE,UDCODE,0x95cb,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8f75,0x97c4,UDCODE,UDCODE,0xe1d5,UDCODE, + UDCODE,0x93b5,UDCODE,UDCODE,0xe1d6,UDCODE,UDCODE,0xe1d7,UDCODE, + 0xe1db,0xe1d9,0xe1da,UDCODE,0xe1d8,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe1dc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe1dd,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe1de,UDCODE,UDCODE,0xe1df,0x96b5,0xe1e0,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x96ee,0xe1e1,UDCODE,0x926d,UDCODE,0x948a, + UDCODE,0x8be9,UDCODE,UDCODE,UDCODE,0x925a,0xe1e2,0x8bb8,UDCODE, + UDCODE,UDCODE,0x90ce,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe1e3,0x8dbb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe1e4,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe1e5,UDCODE,0x8ca4,0x8dd3,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe1e7,0xfb78,UDCODE, + UDCODE,UDCODE,0x9375,0x8dd4,0x8b6d,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9643,UDCODE,0x946a, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9376,UDCODE,UDCODE,UDCODE, + UDCODE,0x8d7b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe1e9,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfb79,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8fc9,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xfb7a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x97b0,0x8d64,UDCODE,UDCODE,0x8ca5,UDCODE,UDCODE,0x94a1,UDCODE, + 0xe1eb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfb7b,UDCODE,0xe1ed, + UDCODE,UDCODE,UDCODE,UDCODE,0x8ce9,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe1ec,0x92f4,UDCODE,UDCODE,UDCODE,UDCODE,0xe1ef,0x8a56,0xe1ea, + UDCODE,UDCODE,0x94e8,UDCODE,0x894f,UDCODE,0x8dea,UDCODE,0x9871, + UDCODE,UDCODE,0xe1ee,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe1f0,UDCODE,UDCODE,UDCODE,0x95c9,UDCODE,0x90d7, + 0xe1f2,UDCODE,UDCODE,UDCODE,UDCODE,0xe1f3,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe1f1,UDCODE,UDCODE,UDCODE,UDCODE,0x8a6d,UDCODE, + 0xe1f9,UDCODE,0xe1f8,UDCODE,UDCODE,0x8ea5,UDCODE,UDCODE,UDCODE, + 0xe1fa,0xe1f5,UDCODE,UDCODE,UDCODE,0xe1fb,0xe1f6,UDCODE,UDCODE, + UDCODE,UDCODE,0x94d6,0xe1f4,UDCODE,UDCODE,0xe1f7,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe241,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe240,0x9681, + UDCODE,UDCODE,UDCODE,0xe1fc,UDCODE,UDCODE,0x88e9,UDCODE,UDCODE, + UDCODE,UDCODE,0xe243,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe242,0x8fca,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe244,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9162,UDCODE, + UDCODE,0xe246,0xe245,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe247,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe1e6,UDCODE,UDCODE,UDCODE,0xe1e8, + 0xe249,0xe248,UDCODE,UDCODE,UDCODE,0xfb7c,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ea6,UDCODE,0x97e7, + UDCODE,0x8ed0,UDCODE,0xe24a,0x8c56,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x8b5f,0x8b46,0x8e83,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9753,UDCODE,UDCODE,0xe250,UDCODE,0xe24f,0x9163,0xe24c, + UDCODE,UDCODE,0xe24e,UDCODE,UDCODE,0x8f6a,0x905f,0xe24d,0xe24b, + UDCODE,0x9449,UDCODE,UDCODE,0x8fcb,UDCODE,UDCODE,0x955b,UDCODE, + UDCODE,UDCODE,UDCODE,0x8dd5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9398,UDCODE,UDCODE,0xe251,UDCODE, + UDCODE,UDCODE,UDCODE,0xe252,0xe268,0x8bd6,UDCODE,UDCODE,0x985c, + 0x9154,UDCODE,UDCODE,UDCODE,UDCODE,0xe253,UDCODE,UDCODE,0x89d0, + 0x92f5,0x959f,UDCODE,UDCODE,UDCODE,UDCODE,0xfb81,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xfb83,UDCODE,0xe254,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b9a,0xe255,UDCODE, + UDCODE,0xe257,UDCODE,UDCODE,UDCODE,0xe258,UDCODE,0x9448,UDCODE, + UDCODE,0xe259,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe25a,0xe25b, + UDCODE,UDCODE,0x8bd7,0x89d1,0x93c3,0x8f47,0x8e84,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe25c,UDCODE,0x8f48,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x89c8,0x9562,UDCODE,UDCODE,0xe25d, + UDCODE,UDCODE,0x94e9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9164,UDCODE,0xe260,UDCODE,0xe261,0x9489,UDCODE,0x9060,0xe25e, + UDCODE,0x9281,UDCODE,UDCODE,0xe25f,UDCODE,UDCODE,UDCODE,0x8fcc, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x88da,0x8b48,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe262,UDCODE,UDCODE,0x92f6,UDCODE,0xe263,0x90c5,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x96ab,UDCODE,UDCODE,0x9542,0xe264, + 0xe265,0x9274,UDCODE,0x97c5,UDCODE,UDCODE,0xe267,0xe266,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8eed,UDCODE,UDCODE,0xe269,0x88ee,UDCODE, + UDCODE,UDCODE,UDCODE,0xe26c,UDCODE,UDCODE,UDCODE,0xe26a,0x89d2, + 0x8c6d,0xe26b,0x8d65,0x8d92,UDCODE,0x95e4,0xe26d,UDCODE,UDCODE, + 0x9673,UDCODE,UDCODE,0xe26f,UDCODE,UDCODE,UDCODE,0x90cf,0x896e, + 0x89b8,0x88aa,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe26e, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe270,0xe271,0x8ff5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe272, + UDCODE,0x8a6e,UDCODE,UDCODE,UDCODE,UDCODE,0xe274,UDCODE,UDCODE, + UDCODE,0x8c8a,UDCODE,0x8b86,UDCODE,UDCODE,0xe275,0x8bf3,UDCODE, + UDCODE,0xe276,UDCODE,0x90fa,UDCODE,0x93cb,UDCODE,0x90de,0x8df3, + UDCODE,UDCODE,UDCODE,0xe277,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9282,0x918b,UDCODE,0xe279,0xe27b, + 0xe278,0xe27a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c41, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe27c,0x8c45,UDCODE,UDCODE,UDCODE,0x8b87,0x9771,0xe27e,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe280,UDCODE,UDCODE,UDCODE,0x894d, + UDCODE,UDCODE,UDCODE,UDCODE,0xe283,UDCODE,UDCODE,UDCODE,0x8a96, + 0xe282,0xe281,UDCODE,0xe285,0xe27d,UDCODE,0xe286,0x97a7,UDCODE, + 0xe287,UDCODE,0xe288,UDCODE,0xfb84,0x9af2,0xe28a,UDCODE,0xe289, + UDCODE,UDCODE,UDCODE,0xe28b,0xe28c,UDCODE,0x97b3,0xe28d,UDCODE, + 0xe8ed,0x8fcd,0xe28e,0xe28f,0x8f76,UDCODE,0x93b6,0xe290,0xfb85, + UDCODE,UDCODE,0x9247,0xfb87,UDCODE,0xe291,UDCODE,0x925b,0xe292, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ba3,UDCODE,0x995e,0x927c, + 0x8eb1,UDCODE,UDCODE,UDCODE,UDCODE,0x8ac6,0xe293,UDCODE,0xe2a0, + UDCODE,0xe296,UDCODE,0x8b88,UDCODE,0xe295,0xe2a2,UDCODE,UDCODE, + UDCODE,0xe294,UDCODE,0x8fce,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe298,0xe299,UDCODE,0x934a,UDCODE,UDCODE,0xe29a,UDCODE, + 0x8a7d,UDCODE,UDCODE,UDCODE,UDCODE,0x9079,0x9584,UDCODE,0xe29c, + UDCODE,UDCODE,UDCODE,0x91e6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe297,UDCODE,0xe29b,0xe29d,UDCODE,UDCODE,0x8df9,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe2a4,0x954d,UDCODE,0x94a4,0x9399,UDCODE,0x8bd8,0xe2a3, + 0xe2a1,UDCODE,0x94b3,0xe29e,0x927d,0x939b,UDCODE,0x939a,UDCODE, + 0x8df4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2b6,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2a6,UDCODE,0xe2a8, + UDCODE,UDCODE,UDCODE,UDCODE,0xe2ab,UDCODE,0xe2ac,UDCODE,0xe2a9, + 0xe2aa,UDCODE,UDCODE,0xe2a7,0xe2a5,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe29f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x95cd,0x89d3,UDCODE,UDCODE,UDCODE,0xe2b3, + UDCODE,0xe2b0,UDCODE,0xe2b5,UDCODE,UDCODE,0xe2b4,UDCODE,0x9493, + 0x96a5,UDCODE,0x8e5a,0xe2ae,0xe2b7,0xe2b2,UDCODE,0xe2b1,0xe2ad, + 0xfb88,0xe2af,UDCODE,0x8ac7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x925c,UDCODE,UDCODE,0x90fb,UDCODE,UDCODE, + UDCODE,0x94a0,UDCODE,UDCODE,0xe2bc,UDCODE,UDCODE,UDCODE,0x94a2, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90df,0xe2b9, + UDCODE,UDCODE,0x94cd,UDCODE,0xe2bd,0x95d1,UDCODE,0x927a,UDCODE, + 0xe2b8,0xe2ba,UDCODE,UDCODE,0xe2bb,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe2be,UDCODE,UDCODE,0x8ec2,UDCODE,UDCODE,UDCODE,0x93c4,0xe2c3, + 0xe2c2,UDCODE,UDCODE,0xe2bf,UDCODE,UDCODE,UDCODE,0x9855,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe2c8,UDCODE,UDCODE,0xe2cc,0xe2c9, + 0xe2c5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2c6,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe2cb,UDCODE,UDCODE,UDCODE,0xe2c0, + 0x99d3,0xe2c7,0xe2c1,UDCODE,UDCODE,0xe2ca,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe2d0,UDCODE,0x8ac8,UDCODE,0xe2cd, + UDCODE,UDCODE,UDCODE,0xe2ce,UDCODE,UDCODE,0xe2cf,0xe2d2,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe2d1,0x94f4,UDCODE,UDCODE,UDCODE,UDCODE,0xe2d3,0x97fa, + 0x95eb,0xe2d8,UDCODE,UDCODE,0xe2d5,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe2d4,0x90d0,UDCODE,0xe2d7,0xe2d9, + UDCODE,UDCODE,UDCODE,0xe2d6,UDCODE,0xe2dd,UDCODE,0xe2da,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2db,0xe2c4,UDCODE,UDCODE, + UDCODE,0xe2dc,0xe2de,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe2df,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95c4,UDCODE, + 0xe2e0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x96e0,UDCODE,UDCODE,0x8bcc,0x8c48,0xe2e1,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x95b2,UDCODE,0x9088,UDCODE,0x96ae,UDCODE,UDCODE, + 0xe2e2,UDCODE,0x97b1,UDCODE,UDCODE,0x9494,UDCODE,0x9165,0x9453, + UDCODE,UDCODE,0x8f6c,UDCODE,UDCODE,UDCODE,0x88be,UDCODE,0xe2e7, + 0xe2e5,UDCODE,0xe2e3,0x8a9f,UDCODE,0x8fcf,0xe2e8,UDCODE,UDCODE, + 0xe2e6,UDCODE,0xe2e4,0xe2ec,UDCODE,UDCODE,0xe2eb,0xe2ea,0xe2e9, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2ed,UDCODE,UDCODE,UDCODE, + 0xe2ee,0x90b8,UDCODE,0xe2ef,UDCODE,0xe2f1,UDCODE,UDCODE,0xe2f0, + UDCODE,UDCODE,UDCODE,UDCODE,0x8cd0,UDCODE,UDCODE,UDCODE,0x9157, + UDCODE,UDCODE,UDCODE,0xe2f3,UDCODE,UDCODE,UDCODE,0x939c,UDCODE, + 0xe2f2,UDCODE,UDCODE,UDCODE,0xe2f4,UDCODE,0x95b3,0x918c,0x8d66, + UDCODE,0xe2f5,UDCODE,UDCODE,UDCODE,UDCODE,0x97c6,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2f7,UDCODE,UDCODE,0xe2f8, + UDCODE,0xe2f9,UDCODE,0xe2fa,UDCODE,0x8e85,UDCODE,0xe2fb,0x8c6e, + UDCODE,UDCODE,0x8b8a,0x8b49,UDCODE,0xe340,UDCODE,0x96f1,0x8d67, + 0xe2fc,UDCODE,UDCODE,UDCODE,0xe343,0x96e4,UDCODE,0x945b,UDCODE, + UDCODE,0x9552,UDCODE,UDCODE,UDCODE,0x8f83,0xe342,UDCODE,0x8ed1, + 0x8d68,0x8e86,0x8b89,0x95b4,0xe341,UDCODE,UDCODE,UDCODE,0x9166, + 0x9661,0x8df5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x8e87,0x92db,UDCODE,0xe346,0x97dd,0x8dd7,UDCODE,0xe347, + 0x9061,UDCODE,0xe349,UDCODE,UDCODE,UDCODE,0x8fd0,0x8dae,UDCODE, + UDCODE,UDCODE,UDCODE,0xe348,UDCODE,UDCODE,0x8f49,0x8cbc,0x9167, + 0xe344,0xe34a,UDCODE,0xfb8a,UDCODE,UDCODE,0xe345,0x8c6f,UDCODE, + 0xe34d,0xe351,0x8c8b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe34c, + UDCODE,UDCODE,UDCODE,UDCODE,0xe355,0xfb8b,UDCODE,0x8d69,UDCODE, + UDCODE,0x978d,0x88ba,0xe352,UDCODE,UDCODE,0x8b8b,UDCODE,0xe34f, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe350,UDCODE,UDCODE,0x939d, + 0xe34e,0xe34b,UDCODE,0x8a47,0x90e2,UDCODE,UDCODE,0x8ca6,UDCODE, + UDCODE,UDCODE,0xe357,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe354,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe356,UDCODE,UDCODE,UDCODE,0xe353,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8c70,0x91b1,0xe358,0x918e,UDCODE,UDCODE, + 0xe365,0xfb8d,UDCODE,0xe361,0xe35b,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe35f,0x8ef8,0x88db,0xe35a,0xe362,0xe366, + 0x8d6a,0x96d4,UDCODE,0x92d4,0xe35c,UDCODE,0xfb8c,0xe364,UDCODE, + 0xe359,0x925d,UDCODE,0xe35e,0x88bb,0x96c8,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe35d,UDCODE,UDCODE,0x8bd9,0x94ea, + UDCODE,UDCODE,UDCODE,0x918d,UDCODE,0x97ce,0x8f8f,UDCODE,UDCODE, + 0xe38e,0xfb8e,UDCODE,0xe367,UDCODE,0x90fc,UDCODE,0xe363,0xe368, + 0xe36a,UDCODE,0x92f7,0xe36d,UDCODE,UDCODE,0xe369,UDCODE,UDCODE, + UDCODE,0x95d2,0x8ac9,UDCODE,UDCODE,0x96c9,UDCODE,UDCODE,0x88dc, + UDCODE,UDCODE,0xe36c,UDCODE,0x97fb,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe36b,0x898f,UDCODE,UDCODE,0x93ea,0xe36e,UDCODE, + UDCODE,UDCODE,0xe375,0xe36f,0xe376,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe372,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x949b,UDCODE,UDCODE,0x8ec8,0xe374,UDCODE,0xe371, + 0xe377,0xe370,UDCODE,UDCODE,0x8f63,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9644,UDCODE,UDCODE,0x8f6b,UDCODE,UDCODE,0xe373,0xe380,UDCODE, + UDCODE,0xe37b,UDCODE,0xe37e,UDCODE,0xe37c,0xe381,0xe37a,UDCODE, + 0xe360,0x90d1,UDCODE,UDCODE,0x94c9,UDCODE,0xe37d,UDCODE,UDCODE, + 0xe378,UDCODE,UDCODE,UDCODE,0x9140,0x8c71,UDCODE,0x8f4a,UDCODE, + UDCODE,UDCODE,UDCODE,0xfb8f,UDCODE,0x9044,0x9155,0xe384,UDCODE, + UDCODE,0xe386,0xe387,UDCODE,UDCODE,0xe383,0xe385,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe379,0xe382,UDCODE,0xe38a, + 0xe389,UDCODE,UDCODE,0x969a,UDCODE,UDCODE,0x8c4a,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe388,UDCODE,0xe38c, + 0xe38b,0xe38f,UDCODE,0xe391,UDCODE,UDCODE,0x8e5b,0xe38d,UDCODE, + UDCODE,UDCODE,UDCODE,0xe392,0xe393,0xfa5c,UDCODE,0xe394,UDCODE, + 0xe39a,0x935a,0xe396,UDCODE,0xe395,0xe397,0xe398,UDCODE,0xe399, + UDCODE,UDCODE,UDCODE,UDCODE,0xe39b,0xe39c,0x8aca,UDCODE,0xe39d, + UDCODE,0xe39e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe39f,UDCODE,0xfb90,UDCODE,UDCODE,UDCODE, + UDCODE,0xe3a0,0xe3a1,0xe3a2,UDCODE,0xe3a3,0xe3a4,UDCODE,UDCODE, + 0xe3a6,0xe3a5,UDCODE,UDCODE,0xe3a7,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe3a8,0xe3a9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe3ac,0xe3aa,0xe3ab,0x8ddf,0x8c72,UDCODE,UDCODE,0x9275, + UDCODE,0x94b1,UDCODE,0x8f90,UDCODE,UDCODE,0x946c,UDCODE,0x94eb, + 0xe3ad,0x9ceb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe3ae,0xe3b0,UDCODE,0x9785,0xe3af,0xe3b2,0xe3b1,UDCODE, + 0x9772,UDCODE,0xe3b3,UDCODE,0x94fc,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe3b4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe3b7,UDCODE, + UDCODE,0xe3b6,0xe3b5,UDCODE,UDCODE,0xfb91,UDCODE,0xe3b8,0x8c51, + UDCODE,UDCODE,UDCODE,0x9141,0x8b60,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe3bc,0xe3b9,UDCODE,UDCODE,0xe3ba,UDCODE,UDCODE,UDCODE,0xe3bd, + UDCODE,0xe3be,0xe3bb,UDCODE,UDCODE,UDCODE,0x8948,UDCODE,UDCODE, + UDCODE,0x89a5,UDCODE,UDCODE,UDCODE,0xe3c0,0xe3c1,UDCODE,UDCODE, + UDCODE,0xe3c2,UDCODE,0x9782,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8f4b,UDCODE,0xe3c4,0xe3c3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9089,0xe3c5,UDCODE,UDCODE, + UDCODE,UDCODE,0xe3c6,UDCODE,UDCODE,0xe3c7,UDCODE,0x8ae3,UDCODE, + UDCODE,UDCODE,UDCODE,0x8acb,UDCODE,UDCODE,0xe3c8,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe3c9,UDCODE,0x967c,0x9783,0x9773,0x9856, + UDCODE,0x8d6c,0xe3cc,0x8ed2,0xe3cb,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe3cd,0x8ea7,UDCODE,UDCODE,UDCODE,0x91cf,UDCODE,0xe3ce,UDCODE, + UDCODE,0x8d6b,UDCODE,0x96d5,0xe3cf,0xe3d0,UDCODE,UDCODE,0xe3d1, + UDCODE,UDCODE,UDCODE,UDCODE,0xe3d2,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe3d3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8ea8,UDCODE,UDCODE,0x96eb,UDCODE, + UDCODE,UDCODE,UDCODE,0xe3d5,UDCODE,0x925e,UDCODE,0xe3d4,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe3d7,UDCODE,UDCODE,UDCODE, + 0xe3d6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe3d8, + UDCODE,UDCODE,UDCODE,0x90b9,UDCODE,0xe3d9,UDCODE,0xe3da,UDCODE, + UDCODE,UDCODE,0x95b7,0xe3db,UDCODE,0x918f,0xe3dc,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe3dd,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x97fc,0xe3e0,UDCODE,0xe3df,0xe3de,0x92ae,UDCODE,0xe3e1, + 0x9045,UDCODE,0xe3e2,UDCODE,UDCODE,UDCODE,0xe3e3,0x9857,0xe3e4, + UDCODE,UDCODE,UDCODE,UDCODE,0xe3e5,0xe3e7,0xe3e6,0x94a3,UDCODE, + 0x93f7,UDCODE,0x985d,0x94a7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe3e9,UDCODE,UDCODE,0x8fd1,UDCODE,0x9549,UDCODE,0xe3ea, + 0xe3e8,UDCODE,0x8acc,UDCODE,UDCODE,UDCODE,0x8cd2,0x8e88,UDCODE, + UDCODE,0x94ec,UDCODE,UDCODE,UDCODE,0x8ca8,0x9662,UDCODE,0xe3ed, + 0xe3eb,UDCODE,0x8d6d,UDCODE,0x8d6e,0x88e7,UDCODE,0x8de6,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9478,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x88dd,0xe3f2,UDCODE,0x925f,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9477,UDCODE,0x91d9,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe3f4,UDCODE,UDCODE,0xe3f0, + 0xe3f3,0xe3ee,UDCODE,0xe3f1,0x9645,UDCODE,UDCODE,0x8cd3,UDCODE, + UDCODE,0x88fb,0xe3ef,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe3f6,UDCODE,0xe3f7,UDCODE,UDCODE,0x93b7, + UDCODE,UDCODE,UDCODE,0x8bb9,UDCODE,UDCODE,UDCODE,0xe445,0x945c, + 0x8e89,UDCODE,UDCODE,0x8bba,0x90c6,0x9865,0x96ac,0xe3f5,0x90d2, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8b72,0xe3f8,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe3fa,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe3f9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe3fb,UDCODE,0x9245,UDCODE,0x945d,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x92af,UDCODE,UDCODE,UDCODE,UDCODE,0xe442,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe441,UDCODE,UDCODE,UDCODE, + UDCODE,0xe3fc,UDCODE,UDCODE,0x9074,UDCODE,0x9585,0xe444,UDCODE, + 0xe443,0x8d6f,0x9872,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe454,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe448,0xe449,UDCODE,UDCODE,UDCODE,UDCODE,0x8eee,UDCODE,UDCODE, + 0xe447,UDCODE,0x8d98,0xe446,UDCODE,UDCODE,0xe44a,UDCODE,UDCODE, + UDCODE,0x92b0,0x95a0,0x9142,UDCODE,UDCODE,UDCODE,UDCODE,0x91da, + 0xe44e,UDCODE,0xe44f,0xe44b,UDCODE,UDCODE,UDCODE,UDCODE,0xe44c, + UDCODE,0xe44d,UDCODE,UDCODE,UDCODE,UDCODE,0x8d70,UDCODE,UDCODE, + UDCODE,0xe455,UDCODE,0xe451,UDCODE,UDCODE,UDCODE,UDCODE,0x9586, + UDCODE,0x968c,0x9547,UDCODE,UDCODE,0xe450,UDCODE,UDCODE,0xe453, + 0xe452,UDCODE,UDCODE,UDCODE,0x9663,0xe456,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe457,UDCODE,UDCODE,0x9156,UDCODE,0xe458, + UDCODE,UDCODE,0xe45a,UDCODE,0xe45e,UDCODE,UDCODE,0xe45b,0xe459, + 0x945e,0xe45c,UDCODE,0xe45d,UDCODE,UDCODE,UDCODE,0x89b0,UDCODE, + 0xe464,0xe45f,UDCODE,UDCODE,UDCODE,0xe460,UDCODE,UDCODE,UDCODE, + 0xe461,UDCODE,0x919f,UDCODE,UDCODE,UDCODE,UDCODE,0xe463,0xe462, + 0xe465,UDCODE,UDCODE,UDCODE,UDCODE,0xe466,0xe467,UDCODE,UDCODE, + 0x9062,UDCODE,0x89e7,UDCODE,0xe468,0x97d5,UDCODE,0x8ea9,UDCODE, + UDCODE,0x8f4c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8e8a,0x9276, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe469,0xe46a,0x8950,UDCODE, + 0xe46b,0xe46c,0xe46d,UDCODE,UDCODE,0xe46e,UDCODE,0xe46f,0x8bbb, + 0x9da8,0xe470,UDCODE,0x90e3,0xe471,0x8ec9,UDCODE,0xe472,UDCODE, + 0x98ae,UDCODE,UDCODE,UDCODE,0xe473,0x95dc,0x8ada,UDCODE,UDCODE, + 0x9143,0x8f77,UDCODE,0x9591,0x8f4d,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe474,0x8d71,0xe475,0x94ca, + UDCODE,0xe484,UDCODE,UDCODE,UDCODE,UDCODE,0xe477,UDCODE,0x91c7, + 0x9495,0x8cbd,0xe476,0x9144,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe478,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x92f8, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe47a,0xe479, + 0xe47c,UDCODE,UDCODE,0xe47b,UDCODE,0xe47d,UDCODE,UDCODE,0xe480, + UDCODE,0xe47e,UDCODE,0x8acd,UDCODE,0xe481,UDCODE,0xe482,0xe483, + UDCODE,UDCODE,0x8daf,0x97c7,UDCODE,0xe485,0x9046,UDCODE,UDCODE, + UDCODE,0x8990,0xe486,0xe487,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe488,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x88f0,UDCODE,0xe489,UDCODE,UDCODE, + UDCODE,UDCODE,0xe48a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9587,UDCODE,UDCODE,UDCODE,0x8ec5,UDCODE,0xe48c,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8a48,0x88b0,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe48b,0xe48e,0x946d,UDCODE,0x9063,UDCODE,0x89d4,UDCODE,0x9646, + UDCODE,UDCODE,UDCODE,UDCODE,0x8c7c,0x8bda,UDCODE,0xe48d,UDCODE, + 0x89e8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8aa1, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8991,0xe492,0x97e8,0x91db,UDCODE,UDCODE,0x9563, + UDCODE,0xe49e,UDCODE,0x89d5,0xe49c,UDCODE,0xe49a,0xe491,UDCODE, + 0xe48f,UDCODE,0xe490,UDCODE,0x8ee1,0x8bea,0x9297,UDCODE,UDCODE, + UDCODE,0x93cf,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8970,UDCODE, + 0xe494,0xe493,UDCODE,UDCODE,UDCODE,UDCODE,0xe499,0xe495,0xe498, + 0xfb93,0x96ce,0xe497,0x89d6,0x8a9d,0xe49b,UDCODE,UDCODE,0xe49d, + UDCODE,UDCODE,UDCODE,UDCODE,0x8c73,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe4a1,0xe4aa,0xe4ab,UDCODE,UDCODE,UDCODE, + 0x88a9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4b2,UDCODE, + UDCODE,UDCODE,UDCODE,0x88ef,UDCODE,UDCODE,0xe4a9,UDCODE,UDCODE, + UDCODE,0xe4a8,UDCODE,0xe4a3,0xe4a2,UDCODE,0xe4a0,0xe49f,0x9283, + UDCODE,0x91f9,0xe4a5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe4a4,UDCODE,UDCODE,UDCODE,UDCODE,0xe4a7,UDCODE,UDCODE,UDCODE, + 0x9190,0x8c74,UDCODE,UDCODE,UDCODE,UDCODE,0x8960,0xe4a6,UDCODE, + 0x8d72,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9191,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfb94,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4b8,UDCODE,0xe4b9, + UDCODE,0x89d7,UDCODE,UDCODE,UDCODE,0x89ac,0xe4b6,UDCODE,UDCODE, + 0xfb95,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4ac,UDCODE,0xe4b4, + UDCODE,0xe4bb,0xe4b5,UDCODE,UDCODE,UDCODE,0xe4b3,UDCODE,UDCODE, + UDCODE,UDCODE,0xe496,UDCODE,UDCODE,0xe4b1,UDCODE,UDCODE,UDCODE, + 0xe4ad,UDCODE,UDCODE,UDCODE,0x8ace,0xe4af,0xe4ba,UDCODE,0xe4b0, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4bc,UDCODE,0xe4ae,0x949c, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9789,UDCODE,UDCODE,UDCODE, + 0xe4b7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4cd, + UDCODE,UDCODE,UDCODE,0xe4c5,UDCODE,UDCODE,UDCODE,0x909b,UDCODE, + 0xfb96,UDCODE,UDCODE,0x8b65,UDCODE,0x8bdb,UDCODE,0xe4c0,UDCODE, + UDCODE,UDCODE,UDCODE,0x89d9,UDCODE,UDCODE,0x8fd2,UDCODE,0xe4c3, + UDCODE,UDCODE,UDCODE,0x8dd8,UDCODE,UDCODE,0x9370,0xe4c8,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x95ec,UDCODE, + 0xe4bf,UDCODE,UDCODE,UDCODE,0x89d8,0x8cd4,0x9548,0xe4c9,UDCODE, + 0xe4bd,UDCODE,0xfb97,0xe4c6,UDCODE,UDCODE,UDCODE,0xe4d0,UDCODE, + 0xe4c1,0xe4c2,0x93b8,UDCODE,UDCODE,0xe4c7,UDCODE,UDCODE,UDCODE, + 0xe4c4,0x9647,0xe4ca,0x88de,UDCODE,UDCODE,UDCODE,UDCODE,0xe4be, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe4cc,UDCODE,0xe4cb,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x948b,0xe4d2,UDCODE,0xe4dd,UDCODE,UDCODE, + UDCODE,UDCODE,0x8a9e,UDCODE,UDCODE,UDCODE,0xe4e0,UDCODE,UDCODE, + 0xe4ce,UDCODE,UDCODE,UDCODE,0xe4d3,0x978e,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4dc,UDCODE,0xfb98,0x9774, + UDCODE,UDCODE,UDCODE,UDCODE,0x97a8,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9298,UDCODE,UDCODE,UDCODE,0x8a8b, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9592,0xe4e2,0x939f,UDCODE, + UDCODE,0x88af,UDCODE,UDCODE,0xe4db,UDCODE,0xe4d7,0x9192,0xe4d1, + 0xe4d9,0xe4de,UDCODE,0x944b,UDCODE,UDCODE,UDCODE,0x88a8,UDCODE, + 0xe4d6,UDCODE,0xe4df,0x9598,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe4da,UDCODE,0xe4d5,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8fd3,UDCODE,UDCODE,UDCODE,UDCODE,0x8f4e,UDCODE, + UDCODE,UDCODE,0x8eaa,UDCODE,UDCODE,UDCODE,UDCODE,0x96d6,UDCODE, + UDCODE,0x9566,UDCODE,UDCODE,0xe4e5,UDCODE,0xe4ee,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe4d8,UDCODE,UDCODE,UDCODE,UDCODE,0x8a97,UDCODE,0xfb99,UDCODE, + UDCODE,UDCODE,0x8ff6,0xe4e3,UDCODE,0xe4e8,0x9193,UDCODE,UDCODE, + 0xe4e4,UDCODE,0xe4eb,UDCODE,UDCODE,0x927e,UDCODE,0xe4ec,UDCODE, + UDCODE,0x9775,0xe4e1,0x8a57,UDCODE,0xe4e7,UDCODE,UDCODE,0xe4ea, + 0x96aa,UDCODE,UDCODE,UDCODE,UDCODE,0xe4ed,UDCODE,UDCODE,0xe4e6, + 0xe4e9,UDCODE,0xfa60,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9648,UDCODE,0x9840,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4f1, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4f8,UDCODE, + UDCODE,0xe4f0,0x8ec1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe4cf, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x95cc,UDCODE,0x96a0,0xe4f7,0xe4f6,UDCODE,0xe4f2,0xe4f3, + UDCODE,0x8955,UDCODE,UDCODE,UDCODE,UDCODE,0xe4f5,UDCODE,0xe4ef, + UDCODE,UDCODE,UDCODE,UDCODE,0x92d3,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe4f4,0x88fc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x91a0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x95c1,UDCODE,UDCODE,0xe4f9,0xe540,UDCODE,0x94d7,UDCODE,UDCODE, + UDCODE,UDCODE,0xe4fc,0x8fd4,0x8ec7,0xe542,UDCODE,UDCODE,0x8bbc, + UDCODE,UDCODE,UDCODE,UDCODE,0xfb9a,UDCODE,0xe543,UDCODE,0x9599, + 0xe4fb,0xfb9b,0xe4d4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe4fa,UDCODE,UDCODE,UDCODE,UDCODE,0x986e,0x93a0, + 0x9593,0xfb9c,UDCODE,0xe54a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe550,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe551,UDCODE,0xe544,UDCODE,UDCODE,UDCODE,0x9496, + UDCODE,UDCODE,0xe54e,0xe546,UDCODE,0xe548,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe552,0xe547,UDCODE,UDCODE,0xe54b,UDCODE,UDCODE, + 0x8992,UDCODE,0x93e3,UDCODE,0xe54c,0xe54f,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe545,UDCODE,0x9145,UDCODE,0xe549, + 0x8e46,0x9064,0x8c4f,0x96f2,UDCODE,0x96f7,0x8f92,0xfb9e,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe556,0xe554, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x986d,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe553,UDCODE,UDCODE,UDCODE, + 0x9795,UDCODE,0xe555,0xe557,UDCODE,UDCODE,UDCODE,UDCODE,0xe558, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe55b,0xe559,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x93a1,0xe55a,UDCODE,UDCODE, + UDCODE,0x94cb,0xe54d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8f93,UDCODE,0xe55c, + 0xe561,0x9194,UDCODE,UDCODE,0xe560,0xe541,UDCODE,UDCODE,UDCODE, + 0xe562,0x9168,UDCODE,UDCODE,0xe55d,0xe55f,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe55e,UDCODE,UDCODE,0x9f50,0x9f41, + UDCODE,UDCODE,0xe564,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe563,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9796,UDCODE,0xe1ba,0xe565,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe566,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe567, + 0x8cd5,UDCODE,0x8b73,UDCODE,UDCODE,UDCODE,0xe569,0x997c,UDCODE, + UDCODE,UDCODE,UDCODE,0x8b95,UDCODE,0x97b8,UDCODE,0x8bf1,0xe56a, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe56b,UDCODE, + UDCODE,UDCODE,0x928e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe56c, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x93f8,UDCODE, + 0x88b8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89e1,0xe571,0xe572, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe56d,UDCODE,0x8e5c, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe56e,0x9461,UDCODE,UDCODE,UDCODE, + UDCODE,0xe56f,0xe570,0xe57a,UDCODE,UDCODE,UDCODE,0xe574,0xe577, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe573,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe575,UDCODE,0xe576,0x8ed6,UDCODE,0xe578,UDCODE,0x9260, + UDCODE,0x8c75,0x8a61,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe57b, + UDCODE,UDCODE,UDCODE,UDCODE,0x8a5e,UDCODE,0xe581,UDCODE,UDCODE, + 0xe57c,0xe580,UDCODE,UDCODE,UDCODE,UDCODE,0x94b8,UDCODE,UDCODE, + UDCODE,UDCODE,0xe57d,UDCODE,UDCODE,0xe57e,0x9567,0x94d8,0xe582, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x91fb, + 0xe58c,UDCODE,0xe588,UDCODE,UDCODE,0x89e9,0xe586,UDCODE,0x9649, + 0xe587,UDCODE,UDCODE,0xe584,UDCODE,0xe585,0xe58a,0xe58d,UDCODE, + UDCODE,0xe58b,UDCODE,UDCODE,UDCODE,0xe589,0xe583,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9277,UDCODE,0xe594,UDCODE,0x96a8,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe592,UDCODE, + UDCODE,UDCODE,0xe593,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe58e,UDCODE,UDCODE,0xe590,UDCODE, + UDCODE,UDCODE,0xe591,UDCODE,UDCODE,UDCODE,0xe58f,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90e4,UDCODE, + 0x9858,0xe598,UDCODE,0xe599,UDCODE,UDCODE,UDCODE,UDCODE,0xe59f, + UDCODE,0x9049,UDCODE,0xe59b,UDCODE,0xe59e,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe596,0xe595,UDCODE,UDCODE,0xe5a0,UDCODE,UDCODE, + 0x89da,UDCODE,0xe59c,UDCODE,0xe5a1,UDCODE,UDCODE,UDCODE,0xe59d, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe59a,UDCODE,0x92b1,UDCODE, + 0xe597,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9488,UDCODE, + UDCODE,0xe5a5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x975a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe5a4,UDCODE,UDCODE,0xe5a3,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5ac,UDCODE,UDCODE, + UDCODE,0xe5a6,UDCODE,UDCODE,UDCODE,0xe5ae,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9786,0xe5b1,UDCODE,0xe5a8,UDCODE,UDCODE, + 0xe5a9,UDCODE,UDCODE,UDCODE,0xe5ad,UDCODE,0xe5b0,0xe5af,UDCODE, + UDCODE,UDCODE,0xe5a7,UDCODE,UDCODE,UDCODE,UDCODE,0xe5aa,UDCODE, + 0xe5bb,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5b4,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe5b2,UDCODE,UDCODE,0xe5b3,UDCODE,UDCODE,UDCODE, + 0xe5b8,0xe5b9,UDCODE,0x8a49,UDCODE,0x8b61,UDCODE,UDCODE,0xe5b7, + 0xe5a2,UDCODE,0xfba1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5b6, + 0xe5ba,0xe5b5,UDCODE,0xe5bc,UDCODE,UDCODE,UDCODE,0xe5be,0xe5bd, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe5c0,0xe5bf,0xe579,UDCODE,UDCODE,UDCODE,0xe5c4,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5c1, + UDCODE,UDCODE,UDCODE,UDCODE,0xe5c2,UDCODE,UDCODE,0xe5c3,UDCODE, + 0xe5c5,UDCODE,UDCODE,UDCODE,UDCODE,0x8c8c,UDCODE,0xe5c7,UDCODE, + 0xe5c6,UDCODE,0x8f4f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8d73, + 0x9fa5,UDCODE,UDCODE,UDCODE,UDCODE,0xe5c8,0x8f70,UDCODE,UDCODE, + UDCODE,0x8a58,UDCODE,0xe5c9,UDCODE,0x8971,UDCODE,0x8fd5,0xe5ca, + UDCODE,UDCODE,0x8d74,0xe5cb,0x88df,UDCODE,UDCODE,UDCODE,UDCODE, + 0x955c,UDCODE,UDCODE,0xe5cc,UDCODE,UDCODE,UDCODE,UDCODE,0x908a, + UDCODE,0xe5d3,UDCODE,UDCODE,0xe5d0,UDCODE,0x928f,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe5d1,0xe5ce,0x8bdc,UDCODE,0xe5cd,0xe5d4, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c55,UDCODE,UDCODE,0x91dc, + UDCODE,0xe5da,UDCODE,UDCODE,UDCODE,UDCODE,0xe5d6,UDCODE,UDCODE, + UDCODE,0x91b3,0xe5d5,UDCODE,0xe5d8,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe5cf,UDCODE,UDCODE,UDCODE,0xe5d9,UDCODE,0xe5db,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x94ed,UDCODE,UDCODE,0xe5d7,UDCODE, + 0xe5dc,0xe5de,UDCODE,UDCODE,0x8cd1,0xe5d2,UDCODE,0x88bf,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5dd,UDCODE,0x8dd9, + 0x97f4,0xe5df,0xe5e0,0x9195,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x97a0,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe5e1,0x9754,UDCODE,UDCODE,0xe5e2,0xe5e3,UDCODE,UDCODE,0x95e2, + 0xe5e4,UDCODE,0x8dbe,UDCODE,0x97a1,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe5e9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe5ea,0x8fd6,0xe5e8,0xfba2,UDCODE,UDCODE, + 0x9787,0xe5e5,UDCODE,UDCODE,0xe5e7,0x90bb,0x909e,0xe5e6,UDCODE, + 0xe5eb,UDCODE,UDCODE,0x95a1,UDCODE,UDCODE,0xe5ed,UDCODE,0xe5ec, + UDCODE,UDCODE,UDCODE,0x8a8c,UDCODE,0x964a,0xe5ee,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfa5d,0xe5fa,0xe5f0, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5f1,UDCODE,UDCODE, + UDCODE,UDCODE,0xe5f2,0xe5f3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5f7,UDCODE,0xe5f8,UDCODE, + UDCODE,0xe5f6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe5f4,UDCODE, + 0xe5ef,0xe5f5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe5f9,0xe8b5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x89a6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe5fc,0x8bdd,0xe5fb,UDCODE,UDCODE,UDCODE,0xe641,UDCODE,0xe640, + UDCODE,UDCODE,UDCODE,0xe643,UDCODE,UDCODE,0xe642,UDCODE,0xe644, + UDCODE,UDCODE,0x8f50,UDCODE,0xe645,UDCODE,UDCODE,0xe646,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe647,0x90bc,UDCODE,0x9776, + UDCODE,0xe648,UDCODE,UDCODE,0x95a2,0x9465,0xe649,UDCODE,0xe64a, + 0x8ca9,UDCODE,UDCODE,UDCODE,0x8b4b,UDCODE,UDCODE,UDCODE,0xe64b, + UDCODE,UDCODE,0x8e8b,0x9460,0xe64c,UDCODE,0x8a6f,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe64d,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe64f,0x9797,UDCODE,0xe64e,0x9065,UDCODE,0xe650,UDCODE,UDCODE, + 0xe651,UDCODE,UDCODE,0xe652,0x8acf,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe653,UDCODE,UDCODE,0xe654,UDCODE,0xe655,0xe656, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8a70, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe657,UDCODE, + 0xe658,0xe659,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x89f0,UDCODE, + UDCODE,0x9047,0xe65a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe65b,UDCODE,UDCODE, + UDCODE,0xe65c,0x8cbe,UDCODE,0x92f9,0xe65d,UDCODE,UDCODE,UDCODE, + UDCODE,0x8c76,UDCODE,0x9075,UDCODE,0xe660,UDCODE,0x93a2,UDCODE, + 0xe65f,UDCODE,0xfba3,0x8c50,UDCODE,UDCODE,0xe65e,0x91f5,0x8b4c, + UDCODE,UDCODE,0xe661,UDCODE,0xe662,UDCODE,0x8fd7,UDCODE,UDCODE, + UDCODE,0x8c8d,UDCODE,0xe663,UDCODE,UDCODE,UDCODE,UDCODE,0x964b, + UDCODE,UDCODE,0x90dd,UDCODE,UDCODE,UDCODE,0x8b96,UDCODE,0x96f3, + 0x9169,UDCODE,0xe664,0xfba4,UDCODE,UDCODE,0x9066,0x9290,0x8fd8, + UDCODE,UDCODE,UDCODE,UDCODE,0xe665,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe668,UDCODE,0xe669,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x8dbc,0x91c0,0xe667,UDCODE,0x8fd9,0x955d,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe666,UDCODE,UDCODE,0x8e8c,UDCODE,0x8972, + UDCODE,0xe66d,0x8c77,UDCODE,UDCODE,0x8e8e,UDCODE,UDCODE,0x8e8d, + UDCODE,0x986c,0xe66c,0xe66b,0x9146,UDCODE,0x8b6c,0x9862,0x8a59, + 0x8fda,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfba5,UDCODE,UDCODE, + 0xe66a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe66f,UDCODE,0xe670, + 0xe66e,UDCODE,0x8cd6,UDCODE,0x975f,UDCODE,UDCODE,0x8e8f,0x9446, + UDCODE,UDCODE,UDCODE,0xe673,UDCODE,0x90be,UDCODE,0x9261,UDCODE, + UDCODE,0x9755,UDCODE,0xe676,UDCODE,UDCODE,UDCODE,0x8cea,UDCODE, + 0x90bd,0xe672,UDCODE,0xe677,0x8ceb,0xe674,0xe675,0xfba6,0xe671, + UDCODE,UDCODE,UDCODE,0x90e0,0x93c7,UDCODE,UDCODE,0x924e,UDCODE, + 0x89db,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x94ee,UDCODE, + UDCODE,0x8b62,UDCODE,0xfba7,0x92b2,UDCODE,UDCODE,0xe67a,UDCODE, + 0xe678,UDCODE,UDCODE,0x926b,UDCODE,UDCODE,UDCODE,0x90bf,0x8ad0, + 0xe679,UDCODE,0x907a,UDCODE,UDCODE,0x97c8,UDCODE,UDCODE,UDCODE, + 0x985f,UDCODE,UDCODE,UDCODE,0xe67b,0xe687,0x92b3,UDCODE,0xe686, + 0xfba8,0xe683,0xe68b,0xe684,UDCODE,0xe680,UDCODE,0x92fa,0xe67e, + UDCODE,UDCODE,UDCODE,0xe67c,UDCODE,0x9740,0x8e90,UDCODE,UDCODE, + 0xe681,UDCODE,0xe67d,UDCODE,UDCODE,0xfbaa,0xe685,0x8f94,UDCODE, + 0x8cbf,UDCODE,UDCODE,UDCODE,0x91f8,0x9664,0x8979,0x88e0,UDCODE, + 0x93a3,UDCODE,UDCODE,0xe689,UDCODE,UDCODE,UDCODE,UDCODE,0xe688, + UDCODE,0x93e4,UDCODE,0xe68d,UDCODE,UDCODE,UDCODE,0xe682,UDCODE, + 0xe68c,0xe68e,UDCODE,0x8caa,0xe68a,0x8d75,UDCODE,0x8ed3,UDCODE, + UDCODE,0xe68f,0x9777,UDCODE,UDCODE,UDCODE,UDCODE,0xe692,UDCODE, + 0xe695,UDCODE,UDCODE,0xe693,0x9554,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe690,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8bde, + UDCODE,UDCODE,UDCODE,UDCODE,0xe694,UDCODE,UDCODE,0xe696,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe69a,UDCODE,UDCODE, + 0xe697,UDCODE,0xe699,0xe698,UDCODE,UDCODE,UDCODE,0xfbab,UDCODE, + UDCODE,0xe69b,UDCODE,0x8eaf,UDCODE,0xe69d,0xe69c,0x9588,UDCODE, + UDCODE,0xe69f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c78, + UDCODE,UDCODE,UDCODE,UDCODE,0xe69e,0xe6a0,UDCODE,UDCODE,0xe6a1, + 0x8b63,0xe3bf,0x8ff7,UDCODE,0xe6a2,UDCODE,UDCODE,0x8cec,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe6a3,UDCODE,0xfbac,0xe6a4,UDCODE, + UDCODE,0x8e5d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9dcc, + UDCODE,0xe6a5,UDCODE,0xe6a6,UDCODE,0x8f51,UDCODE,0xe6a7,0xe6a8, + UDCODE,UDCODE,0xe6a9,UDCODE,UDCODE,0xe6aa,0xe6ab,0x924a,UDCODE, + UDCODE,0xe6ac,UDCODE,UDCODE,UDCODE,UDCODE,0xe6ae,UDCODE,0xe6ad, + UDCODE,UDCODE,UDCODE,UDCODE,0x93a4,UDCODE,0xe6af,UDCODE,0x964c, + UDCODE,0xe6b0,UDCODE,0xe6b1,UDCODE,0xe6b2,UDCODE,UDCODE,UDCODE, + UDCODE,0xe6b3,UDCODE,UDCODE,UDCODE,UDCODE,0x93d8,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8fdb,0xe6b4,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8d8b,0x98ac,0xe6b5,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe6b6,0x955e,0xe6b7,UDCODE,0xe6bf,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe6b8,UDCODE,UDCODE,0xe6ba,UDCODE,UDCODE,UDCODE,0xe6b9, + 0xe6bb,UDCODE,0x9665,0xe6bc,0xe6bd,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe6be,UDCODE,UDCODE,UDCODE,0xe6c0,UDCODE,UDCODE,UDCODE, + UDCODE,0x8a4c,0x92e5,UDCODE,0x9589,0x8de0,0x8d76,UDCODE,UDCODE, + UDCODE,UDCODE,0x956e,0x89dd,0x94cc,0xe6c3,0x8ad1,0x90d3,0xe6c2, + 0xe6c7,0x9299,0x96e1,UDCODE,0xe6c5,0xe6c6,0x8b4d,UDCODE,0xe6c8, + 0x9483,0x91dd,UDCODE,UDCODE,0x94ef,0x935c,0xe6c4,UDCODE,0x9666, + 0x89ea,0xe6ca,0x9847,0x92c0,0x9864,UDCODE,UDCODE,0x8e91,0xe6c9, + UDCODE,0x91af,UDCODE,UDCODE,0xe6da,0x9147,UDCODE,UDCODE,0x93f6, + UDCODE,0x956f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe6cd, + 0x8e5e,0x8e92,UDCODE,0x8fdc,UDCODE,0x9485,UDCODE,0x8cab,0xe6cc, + 0xe6cb,UDCODE,0x958a,UDCODE,UDCODE,UDCODE,0x8ebf,UDCODE,UDCODE, + 0x9371,UDCODE,UDCODE,0xfbad,UDCODE,UDCODE,UDCODE,0xfbae,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe6cf,0xe6d0,0x8d77,0xe6ce,0xe6d1, + 0xe6d2,UDCODE,0xe6d4,0x91a1,UDCODE,0xe6d3,0x8ae4,UDCODE,0xe6d6, + UDCODE,0xe6d5,0xe6d7,UDCODE,0xfbaf,0xe6d9,0xe6db,UDCODE,0xe6dc, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90d4,UDCODE,0x8ecd,0xe6dd, + UDCODE,UDCODE,UDCODE,0x8a71,UDCODE,0xe6de,UDCODE,UDCODE,0x9196, + 0xe6df,UDCODE,0xe6e0,0x958b,UDCODE,0xfbb0,0x8b4e,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe6e1,UDCODE, + UDCODE,UDCODE,0x92b4,UDCODE,UDCODE,UDCODE,UDCODE,0x897a,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe6e2,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8eef,UDCODE,UDCODE,UDCODE, + UDCODE,0x9096,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x91ab,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe6e5,UDCODE,UDCODE,UDCODE,0xe6e4,UDCODE,UDCODE,UDCODE, + 0xe6e3,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe6eb,0xe6e9,UDCODE,UDCODE,0xe6e6,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe6e8,UDCODE,UDCODE,UDCODE,0xe6e7,0xe6ea,UDCODE, + 0x8b97,UDCODE,0xe6ee,UDCODE,0x90d5,UDCODE,0xe6ef,UDCODE,UDCODE, + UDCODE,UDCODE,0x8cd7,UDCODE,0xe6ec,0xe6ed,UDCODE,UDCODE,UDCODE, + 0x9848,UDCODE,UDCODE,UDCODE,0x92b5,UDCODE,0x9148,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe6f0,UDCODE,UDCODE,0xe6f3,0xe6f1, + 0xe6f2,0x9778,UDCODE,UDCODE,UDCODE,UDCODE,0x93a5,0xe6f6,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe6f4,0xe6f5,0xe6f7,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe748,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe6fa,UDCODE,UDCODE,UDCODE,0xe6fb,0xe6f9, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe6f8,UDCODE,0x92fb,UDCODE,UDCODE,0xe740, + 0xe744,0xe741,0xe6fc,UDCODE,0xe742,UDCODE,UDCODE,UDCODE,0xe743, + UDCODE,UDCODE,UDCODE,UDCODE,0xe74a,UDCODE,UDCODE,UDCODE,0xe745, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x90d6,0xe747,UDCODE,UDCODE, + 0xe749,0xe746,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe74c,UDCODE,0x8f52, + UDCODE,0xe74b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe74d,UDCODE, + UDCODE,UDCODE,UDCODE,0xe74e,UDCODE,UDCODE,0xe751,0xe750,UDCODE, + 0xe74f,UDCODE,UDCODE,0xe753,0xe752,UDCODE,0x96f4,UDCODE,UDCODE, + UDCODE,0xe755,UDCODE,0xe754,0xe756,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe757,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe759, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe758, + 0x9067,0xe75a,UDCODE,UDCODE,0x8beb,0xe75b,0xe75d,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe75e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe75f, + 0xe75c,UDCODE,0xe760,UDCODE,0x8ed4,0xe761,0x8b4f,0x8c52,UDCODE, + 0xfbb2,UDCODE,UDCODE,0x8cac,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe762,UDCODE,UDCODE,UDCODE,0x93ee,UDCODE, + UDCODE,0x935d,0xe763,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe766,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8eb2,UDCODE,UDCODE,0xe765, + 0xe764,0x8c79,0xe767,0x8a72,UDCODE,0xe769,UDCODE,UDCODE,UDCODE, + 0x8dda,0xe768,UDCODE,0xe771,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe76b,0xe76d,0x95e3,0xe76a,UDCODE,UDCODE,UDCODE,0xe76c,UDCODE, + 0xe770,0xe76e,0x8b50,UDCODE,0xe76f,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe772,UDCODE,UDCODE,0x9479,0x97d6,UDCODE,UDCODE, + UDCODE,UDCODE,0x8f53,UDCODE,UDCODE,UDCODE,0xe773,UDCODE,UDCODE, + UDCODE,UDCODE,0x9741,0xe775,UDCODE,0xe774,UDCODE,UDCODE,0xe778, + 0x9760,UDCODE,UDCODE,0xe777,UDCODE,0x8a8d,0xe776,0xe77b,UDCODE, + UDCODE,0xe77a,UDCODE,UDCODE,0xe779,0x9351,0xe77c,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe77d,UDCODE,UDCODE, + UDCODE,UDCODE,0xe77e,UDCODE,UDCODE,0x8d8c,UDCODE,0x8c44,0xe780, + 0xe781,0xe782,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9068,0xe783,UDCODE,0x8eab,0xe784,UDCODE,UDCODE, + UDCODE,0xe785,UDCODE,UDCODE,UDCODE,0x999f,0x999e,UDCODE,UDCODE, + UDCODE,UDCODE,0xe786,0xe390,0xe787,0x9243,0x904a,0x945f,UDCODE, + UDCODE,UDCODE,UDCODE,0xe788,UDCODE,UDCODE,0x95d3,0x92d2,0x8d9e, + UDCODE,UDCODE,0x9248,UDCODE,UDCODE,0x8949,UDCODE,0x9698,0x9076, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c7d, + UDCODE,UDCODE,0x8bdf,UDCODE,UDCODE,0x95d4,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe789,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe78b,UDCODE,UDCODE,0xe78a,0x89de,UDCODE,UDCODE,0x93f4, + 0xe78c,0x9497,UDCODE,0x9352,UDCODE,0xe78d,0x8f71,UDCODE,UDCODE, + UDCODE,0xe78f,UDCODE,UDCODE,0x96c0,0xe79e,0xe791,0xe792,UDCODE, + UDCODE,0x92c7,0x91de,0x9197,UDCODE,0x93a6,UDCODE,0xe790,0x8b74, + UDCODE,UDCODE,UDCODE,UDCODE,0xe799,UDCODE,0xe796,0xe7a3,0x93a7, + 0x9280,0xe793,UDCODE,0x92fc,0x9372,0xe794,0xe798,0x9080,UDCODE, + 0x9487,0x92ca,UDCODE,UDCODE,0x90c0,0xe797,0x91ac,0x91a2,0xe795, + 0x88a7,0x9841,UDCODE,UDCODE,UDCODE,0xe79a,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x91df,UDCODE,UDCODE,0x8f54,0x9069,UDCODE, + UDCODE,0xe79c,0xe79b,UDCODE,0x88ed,0xe79d,UDCODE,UDCODE,0x954e, + UDCODE,0xe7a5,UDCODE,UDCODE,0x93d9,0x908b,UDCODE,UDCODE,0x9278, + UDCODE,0x8bf6,UDCODE,0xe7a4,0x9756,0x895e,UDCODE,0x95d5,0x89df, + 0xe79f,0xe7a0,0xe7a1,0xe7a2,0x93b9,0x9242,0x88e1,0xe7a6,UDCODE, + 0xe7a7,0xeaa1,UDCODE,UDCODE,0x91bb,UDCODE,0xe7a8,UDCODE,0x8993, + 0x916b,UDCODE,0x8cad,UDCODE,0x9779,UDCODE,0xfbb5,0xe7a9,0x934b, + UDCODE,UDCODE,UDCODE,0x9198,0x8ed5,0xe7aa,UDCODE,UDCODE,0xe7ad, + UDCODE,UDCODE,0x8f85,0xe7ab,0x914a,0x9149,UDCODE,0x88e2,UDCODE, + 0x97c9,0xe7af,UDCODE,0x94f0,0xe7b1,0xe7b0,0xe7ae,0xe284,0x8ad2, + UDCODE,UDCODE,0xe78e,UDCODE,0xe7b3,0xe7b2,UDCODE,UDCODE,UDCODE, + UDCODE,0xe7b4,UDCODE,0x9757,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x93df,UDCODE,UDCODE,0x964d,UDCODE,0xe7b5, + UDCODE,0x8ed7,UDCODE,UDCODE,UDCODE,UDCODE,0xe7b6,UDCODE,0xe7b7, + UDCODE,UDCODE,UDCODE,0xe7b8,UDCODE,UDCODE,0x9340,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x88e8,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8d78,UDCODE,UDCODE, + UDCODE,0x9859,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7bc,UDCODE,UDCODE,0xfbb6, + UDCODE,UDCODE,0x8c53,0xe7b9,UDCODE,0xe7ba,UDCODE,UDCODE,UDCODE, + 0x9594,UDCODE,UDCODE,UDCODE,UDCODE,0x8a73,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x9758,UDCODE,0x8bbd,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x9373,0xe7bd,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe7be,UDCODE,UDCODE,0xfbb8,UDCODE,UDCODE,UDCODE, + 0xe7bf,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbb9,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9341,UDCODE,UDCODE,0xe7c1,UDCODE,0xe7c0,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x93d1,0xe7c2,0x8f55,0x8ede,0x947a,0x9291, + UDCODE,UDCODE,UDCODE,0x8ef0,UDCODE,0x908c,UDCODE,0xe7c3,UDCODE, + 0xe7c4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x907c,0xe7c5,UDCODE,0xe7c6,UDCODE,UDCODE,UDCODE,0xe7c7, + 0x978f,UDCODE,0x8f56,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7c9, + 0xe7c8,UDCODE,0x8d79,UDCODE,0x8d93,0x8e5f,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7cc,UDCODE,UDCODE, + UDCODE,UDCODE,0x8f86,UDCODE,0xe7cb,UDCODE,0xe7ca,UDCODE,0x91e7, + UDCODE,UDCODE,0x8ced,UDCODE,0x90c1,UDCODE,UDCODE,UDCODE,UDCODE, + 0x94ae,UDCODE,UDCODE,UDCODE,UDCODE,0x8f58,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe7cd,UDCODE,0x8fdd,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe7d0,0xe7ce,UDCODE,UDCODE,UDCODE,0xe7cf,UDCODE,UDCODE, + UDCODE,UDCODE,0xe7d2,0xe7d1,UDCODE,UDCODE,0x8ff8,UDCODE,0xe7d3, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7d4,0xe7d5,UDCODE,UDCODE, + UDCODE,UDCODE,0x94ce,0x8dd1,0x8edf,0xe7d6,UDCODE,0xe7d7,0x97a2, + 0x8f64,0x96ec,0x97ca,0xe7d8,0x8be0,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe7d9,0xfbbb,0x9342,UDCODE,0xfbba,0xe7dc,0x8a98,0x906a,0xfbbc, + 0xe7da,UDCODE,0xe7db,UDCODE,0x92de,0xfbbf,0xfbc0,0x9674,0x8bfa, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbbd,0xfbbe,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe7de,0xe7df,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe7dd,UDCODE,UDCODE,0xe7e1,0xfbc1,UDCODE,UDCODE, + UDCODE,0xfbc3,UDCODE,UDCODE,0x93dd,0x8a62,UDCODE,0xfbc2,0xe7e5, + UDCODE,UDCODE,0xe7e2,0xe7e4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe7e0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe86e,UDCODE,UDCODE,0xe7e3, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x97e9,UDCODE, + UDCODE,0x8cd8,UDCODE,0xfbca,0xfbc4,UDCODE,0xfbc6,UDCODE,UDCODE, + 0xe7ed,0xfbc5,UDCODE,UDCODE,UDCODE,0x9353,0xe7e8,UDCODE,UDCODE, + 0xe7eb,0xe7e9,UDCODE,0xe7ee,UDCODE,UDCODE,0xfbc7,UDCODE,0xe7ef, + 0xfbc9,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7e7,UDCODE,0xfbc8, + 0xe7f4,0x8994,UDCODE,UDCODE,0xe7e6,UDCODE,UDCODE,UDCODE,0x94ab, + UDCODE,0xe7ea,UDCODE,0x8fde,0xfbcb,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8d7a,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xfbcd,0xfbce,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x9667,UDCODE,0x8be2,UDCODE,UDCODE,0x8f65,UDCODE,0x93ba,UDCODE, + UDCODE,0xfa5f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x914c,UDCODE,0xe7f2,UDCODE,0xe7ec,0xe7f1,UDCODE,0x96c1, + UDCODE,0x92b6,0xe7f3,0xe7f0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbcc,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x914b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe7f7,UDCODE,0xe7f6,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe7f5,0xfbd2,UDCODE,0x964e,0xfbd6,UDCODE,0xfbd4,UDCODE,0xfbd0, + UDCODE,0xfbd1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbd5, + UDCODE,UDCODE,UDCODE,0x8f9b,UDCODE,UDCODE,0xfbcf,UDCODE,0xe7f8, + 0x95dd,UDCODE,UDCODE,0x8973,UDCODE,UDCODE,UDCODE,UDCODE,0x9565, + 0x9292,UDCODE,UDCODE,UDCODE,UDCODE,0x8b98,0xfa65,0xe7fa,0xfbd9, + 0x8d7c,UDCODE,UDCODE,0xfbdc,0xfbde,UDCODE,UDCODE,UDCODE,0x8e4b, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7f9, + 0x908d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x908e, + 0xe840,0xe842,UDCODE,UDCODE,0xfbdd,0xfbdb,UDCODE,0x8ff9,0xfbd8, + 0xe841,0xe843,UDCODE,0xfbd7,0x8bd1,UDCODE,0x9564,UDCODE,UDCODE, + 0x8ee0,0x9842,UDCODE,0xe7fc,0x8df6,UDCODE,UDCODE,0x985e,UDCODE, + UDCODE,0xe845,UDCODE,UDCODE,UDCODE,UDCODE,0xe844,0xe846,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe7fb,UDCODE, + UDCODE,UDCODE,0xfa5e,UDCODE,UDCODE,0x93e7,UDCODE,0x9374,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x92d5,UDCODE,0xe84b,0xfbe0, + UDCODE,UDCODE,UDCODE,0x9262,0xe847,UDCODE,UDCODE,UDCODE,0xe848, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8c4c,UDCODE,0xe84a,UDCODE,0xfbdf,UDCODE,UDCODE, + UDCODE,UDCODE,0x8cae,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe849,UDCODE,0x8fdf,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8a99,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe84f,UDCODE,0x8dbd, + 0x9199,UDCODE,UDCODE,0x92c8,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xfbe1,UDCODE,UDCODE,0x8a5a,UDCODE, + UDCODE,UDCODE,UDCODE,0xe84d,0xe84e,0x92c1,UDCODE,0xe84c,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe850,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe856, + UDCODE,UDCODE,0xfbe2,UDCODE,0xe859,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe858,0x934c,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe851,0xe852,0xe855,UDCODE,UDCODE,UDCODE,UDCODE,0xe857,0xfbe3, + UDCODE,UDCODE,0x8bbe,UDCODE,UDCODE,0xe85a,0xe854,UDCODE,UDCODE, + 0xe853,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbe4,0xe85e, + UDCODE,UDCODE,UDCODE,0xe85f,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe860,UDCODE,UDCODE,0xe85d,0xe85c,UDCODE, + UDCODE,UDCODE,0x8fe0,0x93a8,0xe85b,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe864,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe862,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xfbe5,UDCODE,UDCODE,UDCODE,0xe863,0xe861,UDCODE,0x91f6,UDCODE, + 0xe865,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe866,UDCODE, + UDCODE,0xe868,0xfbe6,UDCODE,UDCODE,0xfbe7,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ad3,0xe867,0x96f8,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe873,0xe869,UDCODE,UDCODE, + 0xe86c,UDCODE,0xe86a,UDCODE,0xe86b,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe86d,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe86f,UDCODE,UDCODE,UDCODE,UDCODE,0xe870,UDCODE,0xe871,UDCODE, + UDCODE,UDCODE,UDCODE,0xe874,0xe872,0xe875,0xe877,UDCODE,0xe876, + 0x92b7,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x96e5,UDCODE,0xe878,0x914d,UDCODE,UDCODE,UDCODE,0xe879,UDCODE, + 0x95c2,0xe87a,0x8a4a,UDCODE,UDCODE,UDCODE,0x895b,UDCODE,0x8ad5, + 0xfbe8,0x8ad4,0xe87b,UDCODE,0xe87c,UDCODE,0xe87d,0xe87e,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe880,UDCODE,0x8ad6,0x8a74, + 0x8d7d,0x94b4,UDCODE,0xe882,0xe881,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe883,UDCODE,UDCODE,UDCODE,UDCODE,0x897b,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe886,UDCODE,0xe885,0xe884,UDCODE,0xe887, + UDCODE,UDCODE,UDCODE,UDCODE,0xe88a,UDCODE,UDCODE,UDCODE,0x88c5, + UDCODE,UDCODE,0xe888,UDCODE,0xe88c,0xe88b,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe88e,0xe88d,0xe88f,UDCODE,0x93ac,UDCODE, + UDCODE,UDCODE,0xe890,UDCODE,UDCODE,UDCODE,UDCODE,0xe891,0xe893, + UDCODE,UDCODE,0xe892,0x958c,UDCODE,UDCODE,UDCODE,UDCODE,0xe894, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe895,UDCODE,0x8de3, + UDCODE,UDCODE,UDCODE,0xe896,0xe897,UDCODE,UDCODE,0x9668,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x916a,UDCODE, + UDCODE,UDCODE,0x88a2,0x91c9,UDCODE,0xe898,UDCODE,0x958d,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe89b,0xe899,0x8d7e,UDCODE, + 0xe89a,0x8cc0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x95c3,0xe89d,0xe89f,0xe89e,0xe8a0,UDCODE, + UDCODE,0x8940,0x9077,0x8f9c,0x8ad7,0xe8a1,UDCODE,UDCODE,UDCODE, + 0x9486,UDCODE,0xe8a3,UDCODE,UDCODE,UDCODE,0x8941,UDCODE,0xe8a2, + 0x92c2,UDCODE,0x97cb,0x93a9,0xe89c,0x97a4,UDCODE,0x8caf,UDCODE, + UDCODE,0x977a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x8bf7,0x97b2,UDCODE,0x8c47,UDCODE,0x91e0,0xe440,UDCODE,0xe8a4, + 0x8a4b,0x908f,UDCODE,UDCODE,UDCODE,UDCODE,0x8a75,0xe8a6,UDCODE, + 0xe8a7,0xe8a5,0x8c84,UDCODE,0x8ddb,0x8fe1,0xfbeb,UDCODE,UDCODE, + 0x8942,UDCODE,UDCODE,0x97d7,UDCODE,UDCODE,UDCODE,0xe8a9,0xe7ac, + UDCODE,0xe8a8,UDCODE,UDCODE,UDCODE,UDCODE,0xfbec,0xe8ac,0xe8aa, + 0xe8ab,UDCODE,0xe8ad,UDCODE,0xe8ae,0x97ea,0xe8af,0xe8b0,UDCODE, + 0x90c7,0x94b9,UDCODE,UDCODE,UDCODE,0x909d,0x8ae5,UDCODE,UDCODE, + 0x9759,0x89eb,0x8f57,0x8cd9,UDCODE,0xe8b3,UDCODE,0xe8b2,0x8e93, + 0xe8b4,0xe8b1,UDCODE,UDCODE,0x8e47,UDCODE,UDCODE,UDCODE,0xe8b8, + 0xe5ab,UDCODE,UDCODE,0x99d4,UDCODE,0x9097,0xe8b6,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x97a3,0x93ef,UDCODE,UDCODE,UDCODE,UDCODE, + 0x894a,UDCODE,0x90e1,0x8eb4,UDCODE,UDCODE,UDCODE,UDCODE,0x95b5, + UDCODE,0x895f,UDCODE,UDCODE,UDCODE,0x97eb,0x978b,UDCODE,0xe8b9, + UDCODE,0x9364,0x8ef9,UDCODE,UDCODE,UDCODE,0xe8ba,UDCODE,0xe8bb, + 0x906b,0xe8bc,UDCODE,0x97ec,UDCODE,UDCODE,0xe8b7,0xe8be,0xe8c0, + UDCODE,0xe8bf,UDCODE,0xe8bd,UDCODE,UDCODE,0xe8c1,UDCODE,UDCODE, + 0xe8c2,UDCODE,UDCODE,0x919a,UDCODE,0x89e0,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe8c3,UDCODE,UDCODE,0x96b6,UDCODE,UDCODE,0xe8c4, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe8c5,UDCODE,0x9849,0xfbed, + UDCODE,UDCODE,UDCODE,UDCODE,0x9e50,0xe8c6,UDCODE,0xfbee,UDCODE, + 0xe8c7,0xe8c8,UDCODE,UDCODE,UDCODE,0xe8cc,0xfbef,0xe8c9,UDCODE, + 0xe8ca,UDCODE,0xe8cb,0xe8cd,UDCODE,UDCODE,UDCODE,0xfbf0,UDCODE, + 0xfbf1,UDCODE,0xfbf2,0x90c2,UDCODE,UDCODE,0xfbf3,0x96f5,UDCODE, + UDCODE,0x90c3,UDCODE,UDCODE,0xe8ce,UDCODE,0x94f1,UDCODE,0xe8cf, + 0xea72,0x96ca,UDCODE,0xe8d0,UDCODE,0xe8d1,UDCODE,0xe8d2,0x8a76, + UDCODE,0xe8d4,UDCODE,0x9078,UDCODE,UDCODE,UDCODE,0xe8d5,UDCODE, + UDCODE,0x8c43,UDCODE,UDCODE,UDCODE,UDCODE,0xe8d6,0xe8da,UDCODE, + 0xe8d8,UDCODE,UDCODE,UDCODE,UDCODE,0xe8d9,UDCODE,UDCODE,0x8a93, + 0xe8d7,0xe8db,UDCODE,UDCODE,UDCODE,UDCODE,0xe8dc,UDCODE,0x88c6, + UDCODE,0xe8dd,0xe8de,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x8fe2,UDCODE,UDCODE,UDCODE,0xe8df,UDCODE,UDCODE,UDCODE, + 0x8b66,UDCODE,UDCODE,0xe8e2,UDCODE,UDCODE,0xe8e1,UDCODE,0xe8e0, + UDCODE,UDCODE,0xe691,UDCODE,0x95da,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe8e3,0xe8e4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe8e5, + UDCODE,UDCODE,0xe8e6,UDCODE,0xe8e7,UDCODE,UDCODE,0xe8e8,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8ad8,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe8e9,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe8ea,0x9442,UDCODE,UDCODE, + UDCODE,0xe8ec,0x89b9,UDCODE,0xe8ef,0xe8ee,UDCODE,UDCODE,UDCODE, + UDCODE,0x8943,UDCODE,UDCODE,UDCODE,0x8bbf,0x95c5,0x92b8,0x8da0, + UDCODE,0x8d80,0x8f87,UDCODE,0x907b,UDCODE,UDCODE,UDCODE,0xe8f1, + UDCODE,UDCODE,0xe8f0,0x9761,0x8ae6,0x94d0,0x93da,UDCODE,UDCODE, + UDCODE,0x909c,0x97cc,UDCODE,0x8c7a,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe8f4,UDCODE,UDCODE,0xe8f3,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x966a,0x93aa,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x896f,UDCODE,UDCODE,0xe8f5,0xe8f2,UDCODE, + UDCODE,0x9570,0x978a,0xe8f6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe8f7,UDCODE,UDCODE,UDCODE,UDCODE,0xe8f9, + 0x91e8,0x8a7a,0x8a7b,0xe8f8,UDCODE,UDCODE,UDCODE,UDCODE,0x8ae7, + 0x8cb0,UDCODE,0xfbf4,0x8ae8,UDCODE,UDCODE,0x935e,UDCODE,UDCODE, + 0x97de,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbf5,UDCODE, + 0x8cda,UDCODE,UDCODE,UDCODE,0xe8fa,UDCODE,UDCODE,UDCODE,0xe8fb, + 0xe8fc,0xe940,UDCODE,0xe942,0xe941,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x9597,UDCODE,0xe943,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe944,UDCODE,0xe945,UDCODE,UDCODE,UDCODE,UDCODE,0xe946,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe948,0xe947,UDCODE,0xe949,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x94f2, + 0xe3ca,UDCODE,UDCODE,0x9048,UDCODE,UDCODE,0x8b51,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe94a,UDCODE,0xe94b,UDCODE,0x99aa, + 0x9f5a,0x94d1,UDCODE,UDCODE,0x88f9,UDCODE,0x88b9,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8e94,0x964f,0x8ffc,0xe94c, + UDCODE,0x96dd,UDCODE,UDCODE,UDCODE,0xe94d,0x977b,UDCODE,0x8961, + UDCODE,UDCODE,UDCODE,0x8e60,UDCODE,0xe94e,0x89ec,0xe94f,UDCODE, + UDCODE,UDCODE,0xe950,UDCODE,UDCODE,UDCODE,UDCODE,0xe952,0xe953, + UDCODE,0xe955,0xe951,UDCODE,UDCODE,0xe954,UDCODE,UDCODE,0xfbf8, + 0x8ad9,UDCODE,UDCODE,UDCODE,0xe956,UDCODE,0xe957,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe958,0xe959,UDCODE,UDCODE,UDCODE,0xe95a, + UDCODE,UDCODE,0xe95c,UDCODE,UDCODE,UDCODE,0xe95b,UDCODE,0xe95e, + 0xe961,UDCODE,UDCODE,UDCODE,0xe95d,0xe95f,0xe960,UDCODE,UDCODE, + 0xe962,UDCODE,0x8bc0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8ef1,0xe963,0xe964,0x8d81,UDCODE,UDCODE,UDCODE, + UDCODE,0xfbfa,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe965, + UDCODE,UDCODE,0x8a5d,UDCODE,UDCODE,UDCODE,0x946e,0xe966,0xe967, + UDCODE,UDCODE,UDCODE,UDCODE,0x9279,0x93e9,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe968,UDCODE,UDCODE,UDCODE,UDCODE, + 0x949d,UDCODE,UDCODE,0x91ca,0x8977,0x8bec,UDCODE,0x8bed,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9293,0xe96d,0x8bee, + UDCODE,UDCODE,0x89ed,UDCODE,UDCODE,0xe96c,UDCODE,UDCODE,0xe96a, + UDCODE,0xe96b,UDCODE,0xe969,UDCODE,UDCODE,0xe977,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe96e, + 0xe96f,UDCODE,UDCODE,0xe970,0xe971,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xe973,UDCODE,UDCODE,0xe972,UDCODE,UDCODE,UDCODE,0x8f78, + 0xe974,UDCODE,UDCODE,UDCODE,0xe976,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0x8b52,0xe975,UDCODE,UDCODE,0x919b, + 0x8cb1,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe978,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x91cb,UDCODE,UDCODE,0xe979,UDCODE,UDCODE, + UDCODE,UDCODE,0x93ab,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe97a,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe980,UDCODE, + 0xe97d,UDCODE,0xe97c,0xe97e,UDCODE,0xe97b,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xe982,0xfbfb,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe981,UDCODE,0xe984,UDCODE,UDCODE,0x8bc1, + 0xe983,UDCODE,UDCODE,UDCODE,0xe985,UDCODE,UDCODE,0xe986,UDCODE, + 0xe988,0xe987,UDCODE,UDCODE,UDCODE,0xe989,0xe98b,0xe98a,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8d9c,UDCODE,UDCODE,UDCODE, + UDCODE,0xe98c,UDCODE,UDCODE,0xe98d,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0x8a5b,UDCODE,UDCODE,UDCODE,0xe98e,UDCODE, + UDCODE,UDCODE,0xe98f,UDCODE,UDCODE,UDCODE,0x9091,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe990, + UDCODE,0xe991,UDCODE,0xe992,0xe993,UDCODE,UDCODE,UDCODE,0x8d82, + 0xfbfc,UDCODE,UDCODE,0xfc40,UDCODE,0xe994,0xe995,UDCODE,UDCODE, + 0xe996,0xe997,UDCODE,UDCODE,0xe998,UDCODE,UDCODE,UDCODE,0x94af, + 0xe99a,UDCODE,0x9545,0xe99b,0xe999,UDCODE,0xe99d,UDCODE,UDCODE, + 0xe99c,UDCODE,UDCODE,0xe99e,UDCODE,UDCODE,UDCODE,0xe99f,0xe9a0, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9a1, + UDCODE,0xe9a2,UDCODE,UDCODE,UDCODE,UDCODE,0xe9a3,UDCODE,UDCODE, + 0xe9a4,0xe9a5,UDCODE,0xe9a6,UDCODE,0xe9a7,0xe9a8,0xe9a9,0xe9aa, + UDCODE,UDCODE,UDCODE,0xe9ab,0xe9ac,UDCODE,0x9f54,0xe9ad,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe2f6,0x8b53, + UDCODE,UDCODE,UDCODE,UDCODE,0x8a40,0x8db0,0xe9af,0xe9ae,0x96a3, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9b1,0xe9b2, + 0xe9b0,UDCODE,0xe9b3,UDCODE,UDCODE,0x9682,UDCODE,UDCODE,UDCODE, + 0xe9b4,UDCODE,0x8b9b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9844,UDCODE,UDCODE,0xfc42, + UDCODE,0xe9b5,0xfc41,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9b7,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x88bc,0xfc43,UDCODE,0xe9b8,0x95a9,0xe9b6,UDCODE,UDCODE,0xe9b9, + 0xe9ba,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9bb, + 0xe9bc,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9bd, + UDCODE,0x968e,0x8e4c,UDCODE,0x8df8,0x914e,UDCODE,UDCODE,0xfc44, + UDCODE,UDCODE,0xe9be,UDCODE,UDCODE,UDCODE,UDCODE,0xe9c1,UDCODE, + 0xfc45,UDCODE,UDCODE,UDCODE,UDCODE,0xe9bf,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe9c2,UDCODE,UDCODE,0x8cef,0xe9c0,UDCODE,UDCODE, + UDCODE,UDCODE,0xe9c3,UDCODE,0xe9c4,0xe9c5,UDCODE,0xe9c9,UDCODE, + 0x8e49,UDCODE,UDCODE,UDCODE,UDCODE,0x91e2,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe9ca,0xe9c7,0xe9c6,0xe9c8,UDCODE,UDCODE,UDCODE, + 0x8c7e,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9ce, + 0xe9cd,0xe9cc,UDCODE,UDCODE,0x88b1,0xfc46,UDCODE,UDCODE,UDCODE, + 0xe9d8,UDCODE,0xe9d4,UDCODE,0xe9d5,0xe9d1,0xe9d7,UDCODE,0xe9d3, + 0x8a82,UDCODE,UDCODE,0x986b,UDCODE,0xe9d6,0xe9d2,0xe9d0,0xe9cf, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9da,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe9dd,UDCODE,UDCODE,0xe9dc,0xe9db,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9568,0xe9d9,0x88f1,0xe9de, + UDCODE,0xe9e0,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8a8f, + 0xe9cb,0x8956,UDCODE,UDCODE,0xe9e2,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,0xe9e1,0xe9df,0x924c,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x9690,UDCODE,UDCODE, + UDCODE,UDCODE,0x97d8,UDCODE,UDCODE,0xe9e3,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xe9e4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xe9e5,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xe9e6,UDCODE,0xe9e7, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0x92b9,UDCODE,0xe9e8,UDCODE,0x94b5,UDCODE,0xe9ed,0xe9e9,UDCODE, + UDCODE,UDCODE,0xe9ea,UDCODE,UDCODE,0x9650,0x96c2,UDCODE,0x93ce, + 0xe9ee,UDCODE,UDCODE,0xe9ef,0x93bc,0xe9ec,0xe9eb,UDCODE,UDCODE, + UDCODE,UDCODE,0x89a8,UDCODE,UDCODE,UDCODE,0xe9f7,UDCODE,UDCODE, + 0xe9f6,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8995,UDCODE,UDCODE, + UDCODE,0xe9f4,UDCODE,UDCODE,UDCODE,0xe9f3,UDCODE,UDCODE,0xe9f1, + UDCODE,0x8a9b,UDCODE,0xe9f0,0x8eb0,0x89a7,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x8d83,UDCODE,UDCODE,0xe9fa,0xe9f9,UDCODE,0xe9f8, + UDCODE,UDCODE,0xe9f5,UDCODE,0xe9fb,UDCODE,0xe9fc,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea44,0xea43,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea45,UDCODE,UDCODE,0x894c, + 0xea40,0xea41,UDCODE,0x8d94,0x96b7,UDCODE,UDCODE,0xea42,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfc48,0x9651,UDCODE,UDCODE, + 0xea4a,0xfc47,UDCODE,0xea46,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xea4b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea48,UDCODE,0xea47, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0x8c7b,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea4c,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea4d, + UDCODE,UDCODE,UDCODE,UDCODE,0xea4e,UDCODE,0xea49,UDCODE,UDCODE, + UDCODE,0xe9f2,UDCODE,UDCODE,0xea4f,UDCODE,0x92df,UDCODE,UDCODE, + UDCODE,0xea53,UDCODE,0xea54,0xea52,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xea51,0xea57,UDCODE,0xea50,UDCODE,0xea55,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea56,UDCODE,UDCODE, + UDCODE,0xea59,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea58,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xea5b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + 0xea5c,UDCODE,0xea5d,UDCODE,UDCODE,0x9868,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xea5a,0x91e9,0x8deb,UDCODE,UDCODE,0xea5e,0xfc4a, + 0xea5f,0xea60,UDCODE,UDCODE,0xea61,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xea62,UDCODE,UDCODE,0x8cb2,0xea63,UDCODE,UDCODE,UDCODE, + 0xea64,UDCODE,0x8ead,UDCODE,0xea65,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xea66,UDCODE,UDCODE,0xea67,0xea68,UDCODE,UDCODE, + UDCODE,UDCODE,0xea6b,0xea69,0x985b,UDCODE,0xea6a,UDCODE,0x97ed, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea6c,UDCODE,0x97d9,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xea6d,0x949e,UDCODE,UDCODE,0xea6e, + 0xea70,UDCODE,UDCODE,0xea71,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea6f,0x8d8d,0x96cb,0x9683, + 0x9bf5,UDCODE,0x9f80,0x969b,UDCODE,UDCODE,UDCODE,UDCODE,0x89a9, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea73,0x8b6f, + 0xea74,0xea75,0xea76,0xfc4b,0x8d95,UDCODE,0xea77,UDCODE,UDCODE, + UDCODE,0xe0d2,0x96d9,UDCODE,0x91e1,0xea78,0xea7a,0xea79,UDCODE, + 0xea7b,UDCODE,UDCODE,UDCODE,UDCODE,0xea7c,UDCODE,UDCODE,0xea7d, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea7e,UDCODE,UDCODE, + UDCODE,UDCODE,0xea80,UDCODE,0xea81,0xea82,UDCODE,0xea83,UDCODE, + 0xea84,0xea85,0xea86,0xea87,0xea88,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9343,UDCODE,UDCODE,UDCODE,UDCODE,0x8cdb,UDCODE,0xea8a, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x916c,0xea8b,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,0xea8c,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x9540,UDCODE,UDCODE,0xea8d,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea8e,0xe256, + UDCODE,UDCODE,0xe6d8,0xe8eb,UDCODE,UDCODE,0xea8f,UDCODE,0xea90, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xea92,0xea93,0xea94,0x97ee,0xea91,UDCODE,UDCODE,0xea95, + 0xea96,UDCODE,UDCODE,0xea98,UDCODE,0xea97,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0xea9a,UDCODE,UDCODE,UDCODE,0xea9b,0xea99,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,0x97b4,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0xea9c,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xea9d, + 0xe273,UDCODE,UDCODE,0xea9e,0xf040,0xf041,0xf042,0xf043,0xf044, + 0xf045,0xf046,0xf047,0xf048,0xf049,0xf04a,0xf04b,0xf04c,0xf04d, + 0xf04e,0xf04f,0xf050,0xf051,0xf052,0xf053,0xf054,0xf055,0xf056, + 0xf057,0xf058,0xf059,0xf05a,0xf05b,0xf05c,0xf05d,0xf05e,0xf05f, + 0xf060,0xf061,0xf062,0xf063,0xf064,0xf065,0xf066,0xf067,0xf068, + 0xf069,0xf06a,0xf06b,0xf06c,0xf06d,0xf06e,0xf06f,0xf070,0xf071, + 0xf072,0xf073,0xf074,0xf075,0xf076,0xf077,0xf078,0xf079,0xf07a, + 0xf07b,0xf07c,0xf07d,0xf07e,0xf080,0xf081,0xf082,0xf083,0xf084, + 0xf085,0xf086,0xf087,0xf088,0xf089,0xf08a,0xf08b,0xf08c,0xf08d, + 0xf08e,0xf08f,0xf090,0xf091,0xf092,0xf093,0xf094,0xf095,0xf096, + 0xf097,0xf098,0xf099,0xf09a,0xf09b,0xf09c,0xf09d,0xf09e,0xf09f, + 0xf0a0,0xf0a1,0xf0a2,0xf0a3,0xf0a4,0xf0a5,0xf0a6,0xf0a7,0xf0a8, + 0xf0a9,0xf0aa,0xf0ab,0xf0ac,0xf0ad,0xf0ae,0xf0af,0xf0b0,0xf0b1, + 0xf0b2,0xf0b3,0xf0b4,0xf0b5,0xf0b6,0xf0b7,0xf0b8,0xf0b9,0xf0ba, + 0xf0bb,0xf0bc,0xf0bd,0xf0be,0xf0bf,0xf0c0,0xf0c1,0xf0c2,0xf0c3, + 0xf0c4,0xf0c5,0xf0c6,0xf0c7,0xf0c8,0xf0c9,0xf0ca,0xf0cb,0xf0cc, + 0xf0cd,0xf0ce,0xf0cf,0xf0d0,0xf0d1,0xf0d2,0xf0d3,0xf0d4,0xf0d5, + 0xf0d6,0xf0d7,0xf0d8,0xf0d9,0xf0da,0xf0db,0xf0dc,0xf0dd,0xf0de, + 0xf0df,0xf0e0,0xf0e1,0xf0e2,0xf0e3,0xf0e4,0xf0e5,0xf0e6,0xf0e7, + 0xf0e8,0xf0e9,0xf0ea,0xf0eb,0xf0ec,0xf0ed,0xf0ee,0xf0ef,0xf0f0, + 0xf0f1,0xf0f2,0xf0f3,0xf0f4,0xf0f5,0xf0f6,0xf0f7,0xf0f8,0xf0f9, + 0xf0fa,0xf0fb,0xf0fc,0xf140,0xf141,0xf142,0xf143,0xf144,0xf145, + 0xf146,0xf147,0xf148,0xf149,0xf14a,0xf14b,0xf14c,0xf14d,0xf14e, + 0xf14f,0xf150,0xf151,0xf152,0xf153,0xf154,0xf155,0xf156,0xf157, + 0xf158,0xf159,0xf15a,0xf15b,0xf15c,0xf15d,0xf15e,0xf15f,0xf160, + 0xf161,0xf162,0xf163,0xf164,0xf165,0xf166,0xf167,0xf168,0xf169, + 0xf16a,0xf16b,0xf16c,0xf16d,0xf16e,0xf16f,0xf170,0xf171,0xf172, + 0xf173,0xf174,0xf175,0xf176,0xf177,0xf178,0xf179,0xf17a,0xf17b, + 0xf17c,0xf17d,0xf17e,0xf180,0xf181,0xf182,0xf183,0xf184,0xf185, + 0xf186,0xf187,0xf188,0xf189,0xf18a,0xf18b,0xf18c,0xf18d,0xf18e, + 0xf18f,0xf190,0xf191,0xf192,0xf193,0xf194,0xf195,0xf196,0xf197, + 0xf198,0xf199,0xf19a,0xf19b,0xf19c,0xf19d,0xf19e,0xf19f,0xf1a0, + 0xf1a1,0xf1a2,0xf1a3,0xf1a4,0xf1a5,0xf1a6,0xf1a7,0xf1a8,0xf1a9, + 0xf1aa,0xf1ab,0xf1ac,0xf1ad,0xf1ae,0xf1af,0xf1b0,0xf1b1,0xf1b2, + 0xf1b3,0xf1b4,0xf1b5,0xf1b6,0xf1b7,0xf1b8,0xf1b9,0xf1ba,0xf1bb, + 0xf1bc,0xf1bd,0xf1be,0xf1bf,0xf1c0,0xf1c1,0xf1c2,0xf1c3,0xf1c4, + 0xf1c5,0xf1c6,0xf1c7,0xf1c8,0xf1c9,0xf1ca,0xf1cb,0xf1cc,0xf1cd, + 0xf1ce,0xf1cf,0xf1d0,0xf1d1,0xf1d2,0xf1d3,0xf1d4,0xf1d5,0xf1d6, + 0xf1d7,0xf1d8,0xf1d9,0xf1da,0xf1db,0xf1dc,0xf1dd,0xf1de,0xf1df, + 0xf1e0,0xf1e1,0xf1e2,0xf1e3,0xf1e4,0xf1e5,0xf1e6,0xf1e7,0xf1e8, + 0xf1e9,0xf1ea,0xf1eb,0xf1ec,0xf1ed,0xf1ee,0xf1ef,0xf1f0,0xf1f1, + 0xf1f2,0xf1f3,0xf1f4,0xf1f5,0xf1f6,0xf1f7,0xf1f8,0xf1f9,0xf1fa, + 0xf1fb,0xf1fc,0xf240,0xf241,0xf242,0xf243,0xf244,0xf245,0xf246, + 0xf247,0xf248,0xf249,0xf24a,0xf24b,0xf24c,0xf24d,0xf24e,0xf24f, + 0xf250,0xf251,0xf252,0xf253,0xf254,0xf255,0xf256,0xf257,0xf258, + 0xf259,0xf25a,0xf25b,0xf25c,0xf25d,0xf25e,0xf25f,0xf260,0xf261, + 0xf262,0xf263,0xf264,0xf265,0xf266,0xf267,0xf268,0xf269,0xf26a, + 0xf26b,0xf26c,0xf26d,0xf26e,0xf26f,0xf270,0xf271,0xf272,0xf273, + 0xf274,0xf275,0xf276,0xf277,0xf278,0xf279,0xf27a,0xf27b,0xf27c, + 0xf27d,0xf27e,0xf280,0xf281,0xf282,0xf283,0xf284,0xf285,0xf286, + 0xf287,0xf288,0xf289,0xf28a,0xf28b,0xf28c,0xf28d,0xf28e,0xf28f, + 0xf290,0xf291,0xf292,0xf293,0xf294,0xf295,0xf296,0xf297,0xf298, + 0xf299,0xf29a,0xf29b,0xf29c,0xf29d,0xf29e,0xf29f,0xf2a0,0xf2a1, + 0xf2a2,0xf2a3,0xf2a4,0xf2a5,0xf2a6,0xf2a7,0xf2a8,0xf2a9,0xf2aa, + 0xf2ab,0xf2ac,0xf2ad,0xf2ae,0xf2af,0xf2b0,0xf2b1,0xf2b2,0xf2b3, + 0xf2b4,0xf2b5,0xf2b6,0xf2b7,0xf2b8,0xf2b9,0xf2ba,0xf2bb,0xf2bc, + 0xf2bd,0xf2be,0xf2bf,0xf2c0,0xf2c1,0xf2c2,0xf2c3,0xf2c4,0xf2c5, + 0xf2c6,0xf2c7,0xf2c8,0xf2c9,0xf2ca,0xf2cb,0xf2cc,0xf2cd,0xf2ce, + 0xf2cf,0xf2d0,0xf2d1,0xf2d2,0xf2d3,0xf2d4,0xf2d5,0xf2d6,0xf2d7, + 0xf2d8,0xf2d9,0xf2da,0xf2db,0xf2dc,0xf2dd,0xf2de,0xf2df,0xf2e0, + 0xf2e1,0xf2e2,0xf2e3,0xf2e4,0xf2e5,0xf2e6,0xf2e7,0xf2e8,0xf2e9, + 0xf2ea,0xf2eb,0xf2ec,0xf2ed,0xf2ee,0xf2ef,0xf2f0,0xf2f1,0xf2f2, + 0xf2f3,0xf2f4,0xf2f5,0xf2f6,0xf2f7,0xf2f8,0xf2f9,0xf2fa,0xf2fb, + 0xf2fc,0xf340,0xf341,0xf342,0xf343,0xf344,0xf345,0xf346,0xf347, + 0xf348,0xf349,0xf34a,0xf34b,0xf34c,0xf34d,0xf34e,0xf34f,0xf350, + 0xf351,0xf352,0xf353,0xf354,0xf355,0xf356,0xf357,0xf358,0xf359, + 0xf35a,0xf35b,0xf35c,0xf35d,0xf35e,0xf35f,0xf360,0xf361,0xf362, + 0xf363,0xf364,0xf365,0xf366,0xf367,0xf368,0xf369,0xf36a,0xf36b, + 0xf36c,0xf36d,0xf36e,0xf36f,0xf370,0xf371,0xf372,0xf373,0xf374, + 0xf375,0xf376,0xf377,0xf378,0xf379,0xf37a,0xf37b,0xf37c,0xf37d, + 0xf37e,0xf380,0xf381,0xf382,0xf383,0xf384,0xf385,0xf386,0xf387, + 0xf388,0xf389,0xf38a,0xf38b,0xf38c,0xf38d,0xf38e,0xf38f,0xf390, + 0xf391,0xf392,0xf393,0xf394,0xf395,0xf396,0xf397,0xf398,0xf399, + 0xf39a,0xf39b,0xf39c,0xf39d,0xf39e,0xf39f,0xf3a0,0xf3a1,0xf3a2, + 0xf3a3,0xf3a4,0xf3a5,0xf3a6,0xf3a7,0xf3a8,0xf3a9,0xf3aa,0xf3ab, + 0xf3ac,0xf3ad,0xf3ae,0xf3af,0xf3b0,0xf3b1,0xf3b2,0xf3b3,0xf3b4, + 0xf3b5,0xf3b6,0xf3b7,0xf3b8,0xf3b9,0xf3ba,0xf3bb,0xf3bc,0xf3bd, + 0xf3be,0xf3bf,0xf3c0,0xf3c1,0xf3c2,0xf3c3,0xf3c4,0xf3c5,0xf3c6, + 0xf3c7,0xf3c8,0xf3c9,0xf3ca,0xf3cb,0xf3cc,0xf3cd,0xf3ce,0xf3cf, + 0xf3d0,0xf3d1,0xf3d2,0xf3d3,0xf3d4,0xf3d5,0xf3d6,0xf3d7,0xf3d8, + 0xf3d9,0xf3da,0xf3db,0xf3dc,0xf3dd,0xf3de,0xf3df,0xf3e0,0xf3e1, + 0xf3e2,0xf3e3,0xf3e4,0xf3e5,0xf3e6,0xf3e7,0xf3e8,0xf3e9,0xf3ea, + 0xf3eb,0xf3ec,0xf3ed,0xf3ee,0xf3ef,0xf3f0,0xf3f1,0xf3f2,0xf3f3, + 0xf3f4,0xf3f5,0xf3f6,0xf3f7,0xf3f8,0xf3f9,0xf3fa,0xf3fb,0xf3fc, + 0xf440,0xf441,0xf442,0xf443,0xf444,0xf445,0xf446,0xf447,0xf448, + 0xf449,0xf44a,0xf44b,0xf44c,0xf44d,0xf44e,0xf44f,0xf450,0xf451, + 0xf452,0xf453,0xf454,0xf455,0xf456,0xf457,0xf458,0xf459,0xf45a, + 0xf45b,0xf45c,0xf45d,0xf45e,0xf45f,0xf460,0xf461,0xf462,0xf463, + 0xf464,0xf465,0xf466,0xf467,0xf468,0xf469,0xf46a,0xf46b,0xf46c, + 0xf46d,0xf46e,0xf46f,0xf470,0xf471,0xf472,0xf473,0xf474,0xf475, + 0xf476,0xf477,0xf478,0xf479,0xf47a,0xf47b,0xf47c,0xf47d,0xf47e, + 0xf480,0xf481,0xf482,0xf483,0xf484,0xf485,0xf486,0xf487,0xf488, + 0xf489,0xf48a,0xf48b,0xf48c,0xf48d,0xf48e,0xf48f,0xf490,0xf491, + 0xf492,0xf493,0xf494,0xf495,0xf496,0xf497,0xf498,0xf499,0xf49a, + 0xf49b,0xf49c,0xf49d,0xf49e,0xf49f,0xf4a0,0xf4a1,0xf4a2,0xf4a3, + 0xf4a4,0xf4a5,0xf4a6,0xf4a7,0xf4a8,0xf4a9,0xf4aa,0xf4ab,0xf4ac, + 0xf4ad,0xf4ae,0xf4af,0xf4b0,0xf4b1,0xf4b2,0xf4b3,0xf4b4,0xf4b5, + 0xf4b6,0xf4b7,0xf4b8,0xf4b9,0xf4ba,0xf4bb,0xf4bc,0xf4bd,0xf4be, + 0xf4bf,0xf4c0,0xf4c1,0xf4c2,0xf4c3,0xf4c4,0xf4c5,0xf4c6,0xf4c7, + 0xf4c8,0xf4c9,0xf4ca,0xf4cb,0xf4cc,0xf4cd,0xf4ce,0xf4cf,0xf4d0, + 0xf4d1,0xf4d2,0xf4d3,0xf4d4,0xf4d5,0xf4d6,0xf4d7,0xf4d8,0xf4d9, + 0xf4da,0xf4db,0xf4dc,0xf4dd,0xf4de,0xf4df,0xf4e0,0xf4e1,0xf4e2, + 0xf4e3,0xf4e4,0xf4e5,0xf4e6,0xf4e7,0xf4e8,0xf4e9,0xf4ea,0xf4eb, + 0xf4ec,0xf4ed,0xf4ee,0xf4ef,0xf4f0,0xf4f1,0xf4f2,0xf4f3,0xf4f4, + 0xf4f5,0xf4f6,0xf4f7,0xf4f8,0xf4f9,0xf4fa,0xf4fb,0xf4fc,0xf540, + 0xf541,0xf542,0xf543,0xf544,0xf545,0xf546,0xf547,0xf548,0xf549, + 0xf54a,0xf54b,0xf54c,0xf54d,0xf54e,0xf54f,0xf550,0xf551,0xf552, + 0xf553,0xf554,0xf555,0xf556,0xf557,0xf558,0xf559,0xf55a,0xf55b, + 0xf55c,0xf55d,0xf55e,0xf55f,0xf560,0xf561,0xf562,0xf563,0xf564, + 0xf565,0xf566,0xf567,0xf568,0xf569,0xf56a,0xf56b,0xf56c,0xf56d, + 0xf56e,0xf56f,0xf570,0xf571,0xf572,0xf573,0xf574,0xf575,0xf576, + 0xf577,0xf578,0xf579,0xf57a,0xf57b,0xf57c,0xf57d,0xf57e,0xf580, + 0xf581,0xf582,0xf583,0xf584,0xf585,0xf586,0xf587,0xf588,0xf589, + 0xf58a,0xf58b,0xf58c,0xf58d,0xf58e,0xf58f,0xf590,0xf591,0xf592, + 0xf593,0xf594,0xf595,0xf596,0xf597,0xf598,0xf599,0xf59a,0xf59b, + 0xf59c,0xf59d,0xf59e,0xf59f,0xf5a0,0xf5a1,0xf5a2,0xf5a3,0xf5a4, + 0xf5a5,0xf5a6,0xf5a7,0xf5a8,0xf5a9,0xf5aa,0xf5ab,0xf5ac,0xf5ad, + 0xf5ae,0xf5af,0xf5b0,0xf5b1,0xf5b2,0xf5b3,0xf5b4,0xf5b5,0xf5b6, + 0xf5b7,0xf5b8,0xf5b9,0xf5ba,0xf5bb,0xf5bc,0xf5bd,0xf5be,0xf5bf, + 0xf5c0,0xf5c1,0xf5c2,0xf5c3,0xf5c4,0xf5c5,0xf5c6,0xf5c7,0xf5c8, + 0xf5c9,0xf5ca,0xf5cb,0xf5cc,0xf5cd,0xf5ce,0xf5cf,0xf5d0,0xf5d1, + 0xf5d2,0xf5d3,0xf5d4,0xf5d5,0xf5d6,0xf5d7,0xf5d8,0xf5d9,0xf5da, + 0xf5db,0xf5dc,0xf5dd,0xf5de,0xf5df,0xf5e0,0xf5e1,0xf5e2,0xf5e3, + 0xf5e4,0xf5e5,0xf5e6,0xf5e7,0xf5e8,0xf5e9,0xf5ea,0xf5eb,0xf5ec, + 0xf5ed,0xf5ee,0xf5ef,0xf5f0,0xf5f1,0xf5f2,0xf5f3,0xf5f4,0xf5f5, + 0xf5f6,0xf5f7,0xf5f8,0xf5f9,0xf5fa,0xf5fb,0xf5fc,0xf640,0xf641, + 0xf642,0xf643,0xf644,0xf645,0xf646,0xf647,0xf648,0xf649,0xf64a, + 0xf64b,0xf64c,0xf64d,0xf64e,0xf64f,0xf650,0xf651,0xf652,0xf653, + 0xf654,0xf655,0xf656,0xf657,0xf658,0xf659,0xf65a,0xf65b,0xf65c, + 0xf65d,0xf65e,0xf65f,0xf660,0xf661,0xf662,0xf663,0xf664,0xf665, + 0xf666,0xf667,0xf668,0xf669,0xf66a,0xf66b,0xf66c,0xf66d,0xf66e, + 0xf66f,0xf670,0xf671,0xf672,0xf673,0xf674,0xf675,0xf676,0xf677, + 0xf678,0xf679,0xf67a,0xf67b,0xf67c,0xf67d,0xf67e,0xf680,0xf681, + 0xf682,0xf683,0xf684,0xf685,0xf686,0xf687,0xf688,0xf689,0xf68a, + 0xf68b,0xf68c,0xf68d,0xf68e,0xf68f,0xf690,0xf691,0xf692,0xf693, + 0xf694,0xf695,0xf696,0xf697,0xf698,0xf699,0xf69a,0xf69b,0xf69c, + 0xf69d,0xf69e,0xf69f,0xf6a0,0xf6a1,0xf6a2,0xf6a3,0xf6a4,0xf6a5, + 0xf6a6,0xf6a7,0xf6a8,0xf6a9,0xf6aa,0xf6ab,0xf6ac,0xf6ad,0xf6ae, + 0xf6af,0xf6b0,0xf6b1,0xf6b2,0xf6b3,0xf6b4,0xf6b5,0xf6b6,0xf6b7, + 0xf6b8,0xf6b9,0xf6ba,0xf6bb,0xf6bc,0xf6bd,0xf6be,0xf6bf,0xf6c0, + 0xf6c1,0xf6c2,0xf6c3,0xf6c4,0xf6c5,0xf6c6,0xf6c7,0xf6c8,0xf6c9, + 0xf6ca,0xf6cb,0xf6cc,0xf6cd,0xf6ce,0xf6cf,0xf6d0,0xf6d1,0xf6d2, + 0xf6d3,0xf6d4,0xf6d5,0xf6d6,0xf6d7,0xf6d8,0xf6d9,0xf6da,0xf6db, + 0xf6dc,0xf6dd,0xf6de,0xf6df,0xf6e0,0xf6e1,0xf6e2,0xf6e3,0xf6e4, + 0xf6e5,0xf6e6,0xf6e7,0xf6e8,0xf6e9,0xf6ea,0xf6eb,0xf6ec,0xf6ed, + 0xf6ee,0xf6ef,0xf6f0,0xf6f1,0xf6f2,0xf6f3,0xf6f4,0xf6f5,0xf6f6, + 0xf6f7,0xf6f8,0xf6f9,0xf6fa,0xf6fb,0xf6fc,0xf740,0xf741,0xf742, + 0xf743,0xf744,0xf745,0xf746,0xf747,0xf748,0xf749,0xf74a,0xf74b, + 0xf74c,0xf74d,0xf74e,0xf74f,0xf750,0xf751,0xf752,0xf753,0xf754, + 0xf755,0xf756,0xf757,0xf758,0xf759,0xf75a,0xf75b,0xf75c,0xf75d, + 0xf75e,0xf75f,0xf760,0xf761,0xf762,0xf763,0xf764,0xf765,0xf766, + 0xf767,0xf768,0xf769,0xf76a,0xf76b,0xf76c,0xf76d,0xf76e,0xf76f, + 0xf770,0xf771,0xf772,0xf773,0xf774,0xf775,0xf776,0xf777,0xf778, + 0xf779,0xf77a,0xf77b,0xf77c,0xf77d,0xf77e,0xf780,0xf781,0xf782, + 0xf783,0xf784,0xf785,0xf786,0xf787,0xf788,0xf789,0xf78a,0xf78b, + 0xf78c,0xf78d,0xf78e,0xf78f,0xf790,0xf791,0xf792,0xf793,0xf794, + 0xf795,0xf796,0xf797,0xf798,0xf799,0xf79a,0xf79b,0xf79c,0xf79d, + 0xf79e,0xf79f,0xf7a0,0xf7a1,0xf7a2,0xf7a3,0xf7a4,0xf7a5,0xf7a6, + 0xf7a7,0xf7a8,0xf7a9,0xf7aa,0xf7ab,0xf7ac,0xf7ad,0xf7ae,0xf7af, + 0xf7b0,0xf7b1,0xf7b2,0xf7b3,0xf7b4,0xf7b5,0xf7b6,0xf7b7,0xf7b8, + 0xf7b9,0xf7ba,0xf7bb,0xf7bc,0xf7bd,0xf7be,0xf7bf,0xf7c0,0xf7c1, + 0xf7c2,0xf7c3,0xf7c4,0xf7c5,0xf7c6,0xf7c7,0xf7c8,0xf7c9,0xf7ca, + 0xf7cb,0xf7cc,0xf7cd,0xf7ce,0xf7cf,0xf7d0,0xf7d1,0xf7d2,0xf7d3, + 0xf7d4,0xf7d5,0xf7d6,0xf7d7,0xf7d8,0xf7d9,0xf7da,0xf7db,0xf7dc, + 0xf7dd,0xf7de,0xf7df,0xf7e0,0xf7e1,0xf7e2,0xf7e3,0xf7e4,0xf7e5, + 0xf7e6,0xf7e7,0xf7e8,0xf7e9,0xf7ea,0xf7eb,0xf7ec,0xf7ed,0xf7ee, + 0xf7ef,0xf7f0,0xf7f1,0xf7f2,0xf7f3,0xf7f4,0xf7f5,0xf7f6,0xf7f7, + 0xf7f8,0xf7f9,0xf7fa,0xf7fb,0xf7fc,0xf840,0xf841,0xf842,0xf843, + 0xf844,0xf845,0xf846,0xf847,0xf848,0xf849,0xf84a,0xf84b,0xf84c, + 0xf84d,0xf84e,0xf84f,0xf850,0xf851,0xf852,0xf853,0xf854,0xf855, + 0xf856,0xf857,0xf858,0xf859,0xf85a,0xf85b,0xf85c,0xf85d,0xf85e, + 0xf85f,0xf860,0xf861,0xf862,0xf863,0xf864,0xf865,0xf866,0xf867, + 0xf868,0xf869,0xf86a,0xf86b,0xf86c,0xf86d,0xf86e,0xf86f,0xf870, + 0xf871,0xf872,0xf873,0xf874,0xf875,0xf876,0xf877,0xf878,0xf879, + 0xf87a,0xf87b,0xf87c,0xf87d,0xf87e,0xf880,0xf881,0xf882,0xf883, + 0xf884,0xf885,0xf886,0xf887,0xf888,0xf889,0xf88a,0xf88b,0xf88c, + 0xf88d,0xf88e,0xf88f,0xf890,0xf891,0xf892,0xf893,0xf894,0xf895, + 0xf896,0xf897,0xf898,0xf899,0xf89a,0xf89b,0xf89c,0xf89d,0xf89e, + 0xf89f,0xf8a0,0xf8a1,0xf8a2,0xf8a3,0xf8a4,0xf8a5,0xf8a6,0xf8a7, + 0xf8a8,0xf8a9,0xf8aa,0xf8ab,0xf8ac,0xf8ad,0xf8ae,0xf8af,0xf8b0, + 0xf8b1,0xf8b2,0xf8b3,0xf8b4,0xf8b5,0xf8b6,0xf8b7,0xf8b8,0xf8b9, + 0xf8ba,0xf8bb,0xf8bc,0xf8bd,0xf8be,0xf8bf,0xf8c0,0xf8c1,0xf8c2, + 0xf8c3,0xf8c4,0xf8c5,0xf8c6,0xf8c7,0xf8c8,0xf8c9,0xf8ca,0xf8cb, + 0xf8cc,0xf8cd,0xf8ce,0xf8cf,0xf8d0,0xf8d1,0xf8d2,0xf8d3,0xf8d4, + 0xf8d5,0xf8d6,0xf8d7,0xf8d8,0xf8d9,0xf8da,0xf8db,0xf8dc,0xf8dd, + 0xf8de,0xf8df,0xf8e0,0xf8e1,0xf8e2,0xf8e3,0xf8e4,0xf8e5,0xf8e6, + 0xf8e7,0xf8e8,0xf8e9,0xf8ea,0xf8eb,0xf8ec,0xf8ed,0xf8ee,0xf8ef, + 0xf8f0,0xf8f1,0xf8f2,0xf8f3,0xf8f4,0xf8f5,0xf8f6,0xf8f7,0xf8f8, + 0xf8f9,0xf8fa,0xf8fb,0xf8fc,0xf940,0xf941,0xf942,0xf943,0xf944, + 0xf945,0xf946,0xf947,0xf948,0xf949,0xf94a,0xf94b,0xf94c,0xf94d, + 0xf94e,0xf94f,0xf950,0xf951,0xf952,0xf953,0xf954,0xf955,0xf956, + 0xf957,0xf958,0xf959,0xf95a,0xf95b,0xf95c,0xf95d,0xf95e,0xf95f, + 0xf960,0xf961,0xf962,0xf963,0xf964,0xf965,0xf966,0xf967,0xf968, + 0xf969,0xf96a,0xf96b,0xf96c,0xf96d,0xf96e,0xf96f,0xf970,0xf971, + 0xf972,0xf973,0xf974,0xf975,0xf976,0xf977,0xf978,0xf979,0xf97a, + 0xf97b,0xf97c,0xf97d,0xf97e,0xf980,0xf981,0xf982,0xf983,0xf984, + 0xf985,0xf986,0xf987,0xf988,0xf989,0xf98a,0xf98b,0xf98c,0xf98d, + 0xf98e,0xf98f,0xf990,0xf991,0xf992,0xf993,0xf994,0xf995,0xf996, + 0xf997,0xf998,0xf999,0xf99a,0xf99b,0xf99c,0xf99d,0xf99e,0xf99f, + 0xf9a0,0xf9a1,0xf9a2,0xf9a3,0xf9a4,0xf9a5,0xf9a6,0xf9a7,0xf9a8, + 0xf9a9,0xf9aa,0xf9ab,0xf9ac,0xf9ad,0xf9ae,0xf9af,0xf9b0,0xf9b1, + 0xf9b2,0xf9b3,0xf9b4,0xf9b5,0xf9b6,0xf9b7,0xf9b8,0xf9b9,0xf9ba, + 0xf9bb,0xf9bc,0xf9bd,0xf9be,0xf9bf,0xf9c0,0xf9c1,0xf9c2,0xf9c3, + 0xf9c4,0xf9c5,0xf9c6,0xf9c7,0xf9c8,0xf9c9,0xf9ca,0xf9cb,0xf9cc, + 0xf9cd,0xf9ce,0xf9cf,0xf9d0,0xf9d1,0xf9d2,0xf9d3,0xf9d4,0xf9d5, + 0xf9d6,0xf9d7,0xf9d8,0xf9d9,0xf9da,0xf9db,0xf9dc,0xf9dd,0xf9de, + 0xf9df,0xf9e0,0xf9e1,0xf9e2,0xf9e3,0xf9e4,0xf9e5,0xf9e6,0xf9e7, + 0xf9e8,0xf9e9,0xf9ea,0xf9eb,0xf9ec,0xf9ed,0xf9ee,0xf9ef,0xf9f0, + 0xf9f1,0xf9f2,0xf9f3,0xf9f4,0xf9f5,0xf9f6,0xf9f7,0xf9f8,0xf9f9, + 0xf9fa,0xf9fb,0xf9fc,0x00a0,0x00fd,0x00fe,0x00ff,0xfae0,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,0xfbe9,0xfa90,0xfa9b, + 0xfa9c,0xfab1,0xfad8,0xfae8,0xfaea,0xfb58,0xfb5e,0xfb75,0xfb7d, + 0xfb7e,0xfb80,0xfb82,0xfb86,0xfb89,0xfb92,0xfb9d,0xfb9f,0xfba0, + 0xfba9,0xfbb1,0xfbb3,0xfbb4,0xfbb7,0xfbd3,0xfbda,0xfbea,0xfbf6, + 0xfbf7,0xfbf9,0xfc49,0x8149,0xfa57,0x8194,0x8190,0x8193,0x8195, + 0xfa56,0x8169,0x816a,0x8196,0x817b,0x8143,0x817c,0x8144,0x815e, + 0x824f,0x8250,0x8251,0x8252,0x8253,0x8254,0x8255,0x8256,0x8257, + 0x8258,0x8146,0x8147,0x8183,0x8181,0x8184,0x8148,0x8197,0x8260, + 0x8261,0x8262,0x8263,0x8264,0x8265,0x8266,0x8267,0x8268,0x8269, + 0x826a,0x826b,0x826c,0x826d,0x826e,0x826f,0x8270,0x8271,0x8272, + 0x8273,0x8274,0x8275,0x8276,0x8277,0x8278,0x8279,0x816d,0x815f, + 0x816e,0x814f,0x8151,0x814d,0x8281,0x8282,0x8283,0x8284,0x8285, + 0x8286,0x8287,0x8288,0x8289,0x828a,0x828b,0x828c,0x828d,0x828e, + 0x828f,0x8290,0x8291,0x8292,0x8293,0x8294,0x8295,0x8296,0x8297, + 0x8298,0x8299,0x829a,0x816f,0x8162,0x8170,0x8160,UDCODE,UDCODE, + 0x00a1,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,0x00a8,0x00a9, + 0x00aa,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,0x00b0,0x00b1,0x00b2, + 0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,0x00b8,0x00b9,0x00ba,0x00bb, + 0x00bc,0x00bd,0x00be,0x00bf,0x00c0,0x00c1,0x00c2,0x00c3,0x00c4, + 0x00c5,0x00c6,0x00c7,0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd, + 0x00ce,0x00cf,0x00d0,0x00d1,0x00d2,0x00d3,0x00d4,0x00d5,0x00d6, + 0x00d7,0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x00dd,0x00de,0x00df, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE,UDCODE, + UDCODE,0x8191,0x8192,0x81ca,0x8150,0xfa55,0x818f +}; + +static UINT ucs2len(const UINT16 *lpString); +static UINT ucs2tosjis(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cbInput); +static UINT utf8tosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cbInput); + +/** + * Maps a UTF-16 string to a S-SJIS string + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cbInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +UINT codecnv_ucs2tosjis(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cbInput) +{ + UINT nLength; + + if (lpInput == NULL) + { + return 0; + } + + if (cchOutput == 0) + { + lpOutput = NULL; + cchOutput = (UINT)-1; + } + + if (cbInput != (UINT)-1) + { + // Binary mode + return ucs2tosjis(lpOutput, cchOutput, lpInput, cbInput); + } + else + { + // String mode + nLength = ucs2tosjis(lpOutput, cchOutput - 1, lpInput, ucs2len(lpInput)); + if (lpOutput) + { + lpOutput[nLength] = '\0'; + } + return nLength + 1; + } +} + +/** + * Get the length of a string + * @param[in] lpString Null-terminated string + * @return the number of characters in lpString + */ +static UINT ucs2len(const UINT16 *lpString) +{ + const UINT16 *p = lpString; + while (*p != 0) + { + p++; + } + return (UINT)(p - lpString); +} + +/** + * Maps a UTF-16 string to a S-JIS string (inner) + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cbInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +static UINT ucs2tosjis(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cbInput) +{ + UINT nRemain; + UINT c; + UINT r; + + nRemain = cchOutput; + while ((cbInput > 0) && (nRemain > 0)) + { + c = *lpInput++; + cbInput--; + + r = s_level1[c >> 8]; + c = (c - r) & 0xff; + if (c < ((r >> 8) & 0x1ff)) + { + c = s_level2[(r >> 17) + c]; + } + else + { + c = UDCODE; + } + + if (c < 0x100) + { + nRemain--; + if (lpOutput) + { + *lpOutput++ = (char)c; + } + } + else + { + if (nRemain < 2) + { + break; + } + nRemain -= 2; + if (lpOutput) + { + *lpOutput++ = (char)(c >> 8); + *lpOutput++ = (char)(c >> 0); + } + } + } + return (UINT)(cchOutput - nRemain); +} + +/** + * Maps a UTF-8 string to a S-SJIS string + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cbInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +UINT codecnv_utf8tosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cbInput) +{ + UINT nLength; + + if (lpInput == NULL) + { + return 0; + } + + if (cchOutput == 0) + { + lpOutput = NULL; + cchOutput = (UINT)-1; + } + + if (cbInput != (UINT)-1) + { + // Binary mode + return utf8tosjis(lpOutput, cchOutput, lpInput, cbInput); + } + else + { + // String mode + nLength = utf8tosjis(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); + if (lpOutput) + { + lpOutput[nLength] = '\0'; + } + return nLength + 1; + } +} + +/** + * Maps a UTF-8 string to a S-JIS string (inner) + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cbInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +static UINT utf8tosjis(char *lpOutput, UINT cchOutput, const char *lpInput, UINT cbInput) +{ + UINT nRemain; + UINT c; + int nBits; + UINT r; + + nRemain = cchOutput; + while ((cbInput > 0) && (nRemain > 0)) + { + c = *lpInput++; + cbInput--; + + if (c & 0x80) + { + nBits = 0; + while ((nBits < 6) && (c & (0x80 >> nBits))) + { + nBits++; + } + + c &= (0x7f >> nBits); + nBits--; + + while ((nBits > 0) && (cbInput > 0) && (((*lpInput) & 0xc0) == 0x80)) + { + c = (c << 6) | ((*lpInput++) & 0x3f); + cbInput--; + nBits--; + } + + r = 0; + if (c < 0x10000) + { + r = s_level1[c >> 8]; + } + c = (c - r) & 0xff; + if (c < ((r >> 8) & 0x1ff)) + { + c = s_level2[(r >> 17) + c]; + } + else + { + c = UDCODE; + } + } + + if (c < 0x100) + { + nRemain--; + if (lpOutput) + { + *lpOutput++ = (char)c; + } + } + else + { + if (nRemain < 2) + { + break; + } + nRemain -= 2; + if (lpOutput) + { + *lpOutput++ = (char)(c >> 8); + *lpOutput++ = (char)(c >> 0); + } + } + } + return (UINT)(cchOutput - nRemain); +} diff --git a/codecnv/ucs2ucs4.c b/codecnv/ucs2ucs4.c old mode 100755 new mode 100644 index a56f0c13..a15d74bb --- a/codecnv/ucs2ucs4.c +++ b/codecnv/ucs2ucs4.c @@ -1,115 +1,115 @@ -/** - * @file ucs2ucs4.c - * @brief Implementation of converting UTF-16 to UTF-32 - */ - -#ifdef CODECNV_TEST -#include "compiler_base.h" -#else -#include -#endif -#include - -static BOOL isucs2highsurrogate(const UINT16 c); -static BOOL isucs2lowsurrogate(const UINT16 c); -static UINT ucs2toucs4(UINT32 *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput); - -/** - * Maps a UTF-16 string to a UTF-8 string - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -UINT codecnv_ucs2toucs4(UINT32 *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput) { - UINT n = 0; - UINT nLength; - - if(lpOutput != NULL && lpInput != NULL) { - if(cchOutput == 0) { - lpOutput = NULL; - cchOutput = (UINT)-1; - } - - if(cchInput != (UINT)-1) { - // Binary mode - n = ucs2toucs4(lpOutput, cchOutput, lpInput, cchInput); - } else { - // String mode - nLength = ucs2toucs4(lpOutput, cchOutput - 1, lpInput, codecnv_ucs2len(lpInput)); - lpOutput[nLength] = '\0'; - n = nLength + 1; - } - } - - return n; -} - -static BOOL isucs2highsurrogate(const UINT16 c) { - return 0xD800 <= c && c < 0xDC00; -} - -static BOOL isucs2lowsurrogate(const UINT16 c) { - return 0xDC00 <= c && c < 0xE000; -} - -/** - * Maps a UTF-16 char to a UTF-32 character - * @param[out] lpOutput Pointer to a buffer that receives the converted character - * @param[in] lpInput Pointer to the character to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters read to the buffer indicated by lpInput - */ -UINT codecnv_ucs2toucs4_1(UINT32 *lpOutput, const UINT16 *lpInput, UINT cchInput) { - int n = 0; - - if(isucs2highsurrogate(lpInput[0])) { - if(isucs2lowsurrogate(lpInput[1]) && cchInput >= 2) { - lpOutput[0] = 0x10000; - lpOutput[0] += ((UINT32)lpInput[0] - 0xD800) * 0x400; - lpOutput[0] += (UINT32)lpInput[1] - 0xDC00 ; - n = 2; - } else if(lpInput[1] == 0 && cchInput >= 1) { - lpOutput[0] = lpInput[0]; - n = 1; - } - } else if(isucs2lowsurrogate(lpInput[0])) { - if(lpInput[1] == 0 && cchInput >= 1) { - lpOutput[0] = lpInput[0]; - n = 1; - } - } else { - if(cchInput >= 1) { - lpOutput[0] = lpInput[0]; - n = 1; - } - } - - return n; -} - -/** - * Maps a UTF-16 string to a UTF-32 string (inner) - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -static UINT ucs2toucs4(UINT32 *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput) -{ - UINT nRemain; - int n = 1; - - nRemain = cchOutput; - while ((cchInput > 0) && (nRemain > 0) && (n > 0)) { - n = codecnv_ucs2toucs4_1(lpOutput, lpInput, nRemain); - cchInput -= n; - lpInput += n; - lpOutput++; - nRemain--; - } - - return (UINT)(cchOutput - nRemain); -} +/** + * @file ucs2ucs4.c + * @brief Implementation of converting UTF-16 to UTF-32 + */ + +#ifdef CODECNV_TEST +#include "compiler_base.h" +#else +#include +#endif +#include + +static BOOL isucs2highsurrogate(const UINT16 c); +static BOOL isucs2lowsurrogate(const UINT16 c); +static UINT ucs2toucs4(UINT32 *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput); + +/** + * Maps a UTF-16 string to a UTF-8 string + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +UINT codecnv_ucs2toucs4(UINT32 *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput) { + UINT n = 0; + UINT nLength; + + if(lpOutput != NULL && lpInput != NULL) { + if(cchOutput == 0) { + lpOutput = NULL; + cchOutput = (UINT)-1; + } + + if(cchInput != (UINT)-1) { + // Binary mode + n = ucs2toucs4(lpOutput, cchOutput, lpInput, cchInput); + } else { + // String mode + nLength = ucs2toucs4(lpOutput, cchOutput - 1, lpInput, codecnv_ucs2len(lpInput)); + lpOutput[nLength] = '\0'; + n = nLength + 1; + } + } + + return n; +} + +static BOOL isucs2highsurrogate(const UINT16 c) { + return 0xD800 <= c && c < 0xDC00; +} + +static BOOL isucs2lowsurrogate(const UINT16 c) { + return 0xDC00 <= c && c < 0xE000; +} + +/** + * Maps a UTF-16 char to a UTF-32 character + * @param[out] lpOutput Pointer to a buffer that receives the converted character + * @param[in] lpInput Pointer to the character to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters read to the buffer indicated by lpInput + */ +UINT codecnv_ucs2toucs4_1(UINT32 *lpOutput, const UINT16 *lpInput, UINT cchInput) { + int n = 0; + + if(isucs2highsurrogate(lpInput[0])) { + if(isucs2lowsurrogate(lpInput[1]) && cchInput >= 2) { + lpOutput[0] = 0x10000; + lpOutput[0] += ((UINT32)lpInput[0] - 0xD800) * 0x400; + lpOutput[0] += (UINT32)lpInput[1] - 0xDC00 ; + n = 2; + } else if(lpInput[1] == 0 && cchInput >= 1) { + lpOutput[0] = lpInput[0]; + n = 1; + } + } else if(isucs2lowsurrogate(lpInput[0])) { + if(lpInput[1] == 0 && cchInput >= 1) { + lpOutput[0] = lpInput[0]; + n = 1; + } + } else { + if(cchInput >= 1) { + lpOutput[0] = lpInput[0]; + n = 1; + } + } + + return n; +} + +/** + * Maps a UTF-16 string to a UTF-32 string (inner) + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +static UINT ucs2toucs4(UINT32 *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput) +{ + UINT nRemain; + int n = 1; + + nRemain = cchOutput; + while ((cchInput > 0) && (nRemain > 0) && (n > 0)) { + n = codecnv_ucs2toucs4_1(lpOutput, lpInput, nRemain); + cchInput -= n; + lpInput += n; + lpOutput++; + nRemain--; + } + + return (UINT)(cchOutput - nRemain); +} diff --git a/codecnv/ucs2utf8.c b/codecnv/ucs2utf8.c old mode 100755 new mode 100644 index 5041c3eb..1c247547 --- a/codecnv/ucs2utf8.c +++ b/codecnv/ucs2utf8.c @@ -1,89 +1,89 @@ -/** - * @file ucs2utf8.c - * @brief Implementation of converting UCS2 to UTF-8 - */ - -#ifdef CODECNV_TEST -#include "compiler_base.h" -#else -#include -#endif -#include - -static UINT ucs2toutf8(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput); - -/** - * Maps a UTF-16 string to a UTF-8 string - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -UINT codecnv_ucs2toutf8(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput) { - UINT n = 0; - UINT nLength; - - if(lpOutput != NULL && lpInput != NULL) { - if(cchOutput == 0) { - lpOutput = NULL; - cchOutput = (UINT)-1; - } - - if(cchInput != (UINT)-1) { - // Binary mode - n = ucs2toutf8(lpOutput, cchOutput, lpInput, cchInput); - } else { - // String mode - nLength = ucs2toutf8(lpOutput, cchOutput - 1, lpInput, codecnv_ucs2len(lpInput)); - lpOutput[nLength] = '\0'; - n = nLength + 1; - } - } - - return n; -} - -/** - * Get the length of a string - * @param[in] lpString Null-terminated string - * @return the number of characters in lpString - */ -UINT codecnv_ucs2len(const UINT16 *lpString) { - const UINT16 *p = lpString; - - while (*p != 0) { - p++; - } - - return (UINT)(p - lpString); -} - -/** - * Maps a UTF-16 string to a UTF-8 string (inner) - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -static UINT ucs2toutf8(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput) { - UINT n, m; - UINT nRemain; - UINT32 c[2]; - - n = m = 1; - nRemain = cchOutput; - while ((cchInput > 0) && (nRemain > 0) && (m > 0) && (n > 0)) { - n = codecnv_ucs2toucs4(c, 1, lpInput, 2); - if(n) { - m = codecnv_ucs4toutf8(lpOutput, nRemain, c, 1); - lpInput += n; - cchInput -= n; - lpOutput += m; - nRemain -= m; - } - } - - return (UINT)(cchOutput - nRemain); -} +/** + * @file ucs2utf8.c + * @brief Implementation of converting UCS2 to UTF-8 + */ + +#ifdef CODECNV_TEST +#include "compiler_base.h" +#else +#include +#endif +#include + +static UINT ucs2toutf8(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput); + +/** + * Maps a UTF-16 string to a UTF-8 string + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +UINT codecnv_ucs2toutf8(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput) { + UINT n = 0; + UINT nLength; + + if(lpOutput != NULL && lpInput != NULL) { + if(cchOutput == 0) { + lpOutput = NULL; + cchOutput = (UINT)-1; + } + + if(cchInput != (UINT)-1) { + // Binary mode + n = ucs2toutf8(lpOutput, cchOutput, lpInput, cchInput); + } else { + // String mode + nLength = ucs2toutf8(lpOutput, cchOutput - 1, lpInput, codecnv_ucs2len(lpInput)); + lpOutput[nLength] = '\0'; + n = nLength + 1; + } + } + + return n; +} + +/** + * Get the length of a string + * @param[in] lpString Null-terminated string + * @return the number of characters in lpString + */ +UINT codecnv_ucs2len(const UINT16 *lpString) { + const UINT16 *p = lpString; + + while (*p != 0) { + p++; + } + + return (UINT)(p - lpString); +} + +/** + * Maps a UTF-16 string to a UTF-8 string (inner) + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +static UINT ucs2toutf8(char *lpOutput, UINT cchOutput, const UINT16 *lpInput, UINT cchInput) { + UINT n, m; + UINT nRemain; + UINT32 c[2]; + + n = m = 1; + nRemain = cchOutput; + while ((cchInput > 0) && (nRemain > 0) && (m > 0) && (n > 0)) { + n = codecnv_ucs2toucs4(c, 1, lpInput, 2); + if(n) { + m = codecnv_ucs4toutf8(lpOutput, nRemain, c, 1); + lpInput += n; + cchInput -= n; + lpOutput += m; + nRemain -= m; + } + } + + return (UINT)(cchOutput - nRemain); +} diff --git a/codecnv/utf8ucs4.c b/codecnv/utf8ucs4.c old mode 100755 new mode 100644 index fb4c5fb1..eef9d214 --- a/codecnv/utf8ucs4.c +++ b/codecnv/utf8ucs4.c @@ -1,121 +1,121 @@ -/** - * @file utf8ucs4.c - * @brief Implementation of converting UTF-8 to UCS4 - */ - -#ifdef CODECNV_TEST -#include "compiler_base.h" -#else -#include -#endif -#include - -static UINT utf8toucs4(UINT32 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); - -/** - * Maps a UTF-8 string to a UTF-32 string - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -UINT codecnv_utf8toucs4(UINT32 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) { - UINT n = 0; - UINT nLength; - - if(lpOutput != NULL && lpInput != NULL) { - if(cchOutput == 0) { - cchOutput = (UINT)-1; - } - - if(cchInput != (UINT)-1) { - // Binary mode - n = utf8toucs4(lpOutput, cchOutput, lpInput, cchInput); - } else { - // String mode - nLength = utf8toucs4(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); - lpOutput[nLength] = '\0'; - n = nLength + 1; - } - } - - return n; -} - -/** - * Maps a UTF-8 char to a UTF-32 character - * @param[out] lpOutput Pointer to a buffer that receives the converted character - * @param[in] lpInput Pointer to the character to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters read to the buffer indicated by lpInput - */ -UINT codecnv_utf8toucs4_1(UINT32 *lpOutput, const char *lpInput, UINT cchInput) { - UINT c; - UINT n; - - c = (UINT8)lpInput[0]; - if(c < 0x80) { - n = 1; - } else if(0xC2 <= c && c < 0xE0) { - n = 2; - } else if(0xE0 <= c && c < 0xF0) { - n = 3; - } else if(0xF0 <= c && c < 0xF8) { - n = 4; - } else { - n = 0; - } - - if(cchInput < n) { - n = 0; - } - - switch(n) { - case 1: - lpOutput[0] = (UINT8)lpInput[0]; - break; - case 2: - lpOutput[0] = ((UINT8)lpInput[0] & 0x1F) << 6; - lpOutput[0] |= (UINT8)lpInput[1] & 0x3F; - break; - case 3: - lpOutput[0] = ((UINT8)lpInput[0] & 0x0F) << 12; - lpOutput[0] |= ((UINT8)lpInput[1] & 0x3F) << 6; - lpOutput[0] |= (UINT8)lpInput[2] & 0x3F; - break; - case 4: - lpOutput[0] = ((UINT8)lpInput[0] & 0x07) << 18; - lpOutput[0] |= ((UINT8)lpInput[1] & 0x3F) << 12; - lpOutput[0] |= ((UINT8)lpInput[2] & 0x3F) << 6; - lpOutput[0] |= (UINT8)lpInput[3] & 0x3F; - break; - } - - return n; -} - -/** - * Maps a UTF-8 string to a UTF-32 string (inner) - * @param[out] lpOutput Pointer to a buffer that receives the converted string - * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput - * @param[in] lpInput Pointer to the character string to convert - * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput - * @return The number of characters written to the buffer indicated by lpOutput - */ -static UINT utf8toucs4(UINT32 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) -{ - UINT nRemain; - UINT n = 1; - - nRemain = cchOutput; - while ((cchInput > 0) && (nRemain > 0) && (n > 0)) { - n = codecnv_utf8toucs4_1(lpOutput, lpInput, nRemain); - cchInput -= n; - lpInput += n; - lpOutput++; - nRemain--; - } - - return (UINT)(cchOutput - nRemain); -} +/** + * @file utf8ucs4.c + * @brief Implementation of converting UTF-8 to UCS4 + */ + +#ifdef CODECNV_TEST +#include "compiler_base.h" +#else +#include +#endif +#include + +static UINT utf8toucs4(UINT32 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput); + +/** + * Maps a UTF-8 string to a UTF-32 string + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +UINT codecnv_utf8toucs4(UINT32 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) { + UINT n = 0; + UINT nLength; + + if(lpOutput != NULL && lpInput != NULL) { + if(cchOutput == 0) { + cchOutput = (UINT)-1; + } + + if(cchInput != (UINT)-1) { + // Binary mode + n = utf8toucs4(lpOutput, cchOutput, lpInput, cchInput); + } else { + // String mode + nLength = utf8toucs4(lpOutput, cchOutput - 1, lpInput, (UINT)strlen(lpInput)); + lpOutput[nLength] = '\0'; + n = nLength + 1; + } + } + + return n; +} + +/** + * Maps a UTF-8 char to a UTF-32 character + * @param[out] lpOutput Pointer to a buffer that receives the converted character + * @param[in] lpInput Pointer to the character to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters read to the buffer indicated by lpInput + */ +UINT codecnv_utf8toucs4_1(UINT32 *lpOutput, const char *lpInput, UINT cchInput) { + UINT c; + UINT n; + + c = (UINT8)lpInput[0]; + if(c < 0x80) { + n = 1; + } else if(0xC2 <= c && c < 0xE0) { + n = 2; + } else if(0xE0 <= c && c < 0xF0) { + n = 3; + } else if(0xF0 <= c && c < 0xF8) { + n = 4; + } else { + n = 0; + } + + if(cchInput < n) { + n = 0; + } + + switch(n) { + case 1: + lpOutput[0] = (UINT8)lpInput[0]; + break; + case 2: + lpOutput[0] = ((UINT8)lpInput[0] & 0x1F) << 6; + lpOutput[0] |= (UINT8)lpInput[1] & 0x3F; + break; + case 3: + lpOutput[0] = ((UINT8)lpInput[0] & 0x0F) << 12; + lpOutput[0] |= ((UINT8)lpInput[1] & 0x3F) << 6; + lpOutput[0] |= (UINT8)lpInput[2] & 0x3F; + break; + case 4: + lpOutput[0] = ((UINT8)lpInput[0] & 0x07) << 18; + lpOutput[0] |= ((UINT8)lpInput[1] & 0x3F) << 12; + lpOutput[0] |= ((UINT8)lpInput[2] & 0x3F) << 6; + lpOutput[0] |= (UINT8)lpInput[3] & 0x3F; + break; + } + + return n; +} + +/** + * Maps a UTF-8 string to a UTF-32 string (inner) + * @param[out] lpOutput Pointer to a buffer that receives the converted string + * @param[in] cchOutput Size, in characters, of the buffer indicated by lpOutput + * @param[in] lpInput Pointer to the character string to convert + * @param[in] cchInput Size, in characters, of the buffer indicated by lpInput + * @return The number of characters written to the buffer indicated by lpOutput + */ +static UINT utf8toucs4(UINT32 *lpOutput, UINT cchOutput, const char *lpInput, UINT cchInput) +{ + UINT nRemain; + UINT n = 1; + + nRemain = cchOutput; + while ((cchInput > 0) && (nRemain > 0) && (n > 0)) { + n = codecnv_utf8toucs4_1(lpOutput, lpInput, nRemain); + cchInput -= n; + lpInput += n; + lpOutput++; + nRemain--; + } + + return (UINT)(cchOutput - nRemain); +} diff --git a/common.h b/common.h old mode 100755 new mode 100644 index fb7ef8aa..1f5e3416 --- a/common.h +++ b/common.h @@ -1,216 +1,216 @@ -#ifndef NP2_COMMON_H -#define NP2_COMMON_H - -enum { - SUCCESS = 0, - FAILURE = 1 -}; - -#ifndef BRESULT -#define BRESULT UINT -#endif - -#ifndef INTPTR -#define INTPTR intptr_t -#endif -#ifndef UINTPTR -#define UINTPTR uintptr_t -#endif - -#ifndef LOADINTELDWORD -#define LOADINTELDWORD(a) (((UINT32)(((UINT8*)(a))[0])) | \ - ((UINT32)(((UINT8*)(a))[1]) << 8) | \ - ((UINT32)(((UINT8*)(a))[2]) << 16) | \ - ((UINT32)(((UINT8*)(a))[3]) << 24)) -#endif - -#ifndef LOADINTELWORD -#define LOADINTELWORD(a) (((UINT16)((UINT8*)(a))[0]) | ((UINT16)(((UINT8*)(a))[1]) << 8)) -#endif - -#ifndef STOREINTELDWORD -#define STOREINTELDWORD(a, b) *(((UINT8*)(a))+0) = (UINT8)((b)); \ - *(((UINT8*)(a))+1) = (UINT8)((b)>>8); \ - *(((UINT8*)(a))+2) = (UINT8)((b)>>16); \ - *(((UINT8*)(a))+3) = (UINT8)((b)>>24) -#endif - -#ifndef STOREINTELWORD -#define STOREINTELWORD(a, b) *(((UINT8*)(a))+0) = (UINT8)((b)); \ - *(((UINT8*)(a))+1) = (UINT8)((b)>>8) -#endif - -/* Big Ending */ - -#ifndef LOADMOTOROLAQWORD -#define LOADMOTOROLAQWORD(a) (((UINT64)((UINT8*)(a))[7]) | \ - ((UINT64)(((UINT8*)(a))[6]) << 8) | \ - ((UINT64)(((UINT8*)(a))[5]) << 16) | \ - ((UINT64)(((UINT8*)(a))[4]) << 24) | \ - ((UINT64)(((UINT8*)(a))[3]) << 32) | \ - ((UINT64)(((UINT8*)(a))[2]) << 40) | \ - ((UINT64)(((UINT8*)(a))[1]) << 48) | \ - ((UINT64)(((UINT8*)(a))[0]) << 56)) -#endif - -#ifndef LOADMOTOROLADWORD -#define LOADMOTOROLADWORD(a) (((UINT32)((UINT8*)(a))[3]) | \ - ((UINT32)(((UINT8*)(a))[2]) << 8) | \ - ((UINT32)(((UINT8*)(a))[1]) << 16) | \ - ((UINT32)(((UINT8*)(a))[0]) << 24)) -#endif - -#ifndef LOADMOTOROLAWORD -#define LOADMOTOROLAWORD(a) (((UINT16)((UINT8*)(a))[1]) | ((UINT16)(((UINT8*)(a))[0]) << 8)) -#endif - -#ifndef STOREMOTOROLAQWORD -#define STOREMOTOROLAQWORD(a, b) *(((UINT8*)(a))+7) = (UINT8)((b)); \ - *(((UINT8*)(a))+6) = (UINT8)((b)>>8); \ - *(((UINT8*)(a))+5) = (UINT8)((b)>>16); \ - *(((UINT8*)(a))+4) = (UINT8)((b)>>24); \ - *(((UINT8*)(a))+3) = (UINT8)((b)>>32); \ - *(((UINT8*)(a))+2) = (UINT8)((b)>>40); \ - *(((UINT8*)(a))+1) = (UINT8)((b)>>48); \ - *(((UINT8*)(a))+0) = (UINT8)((b)>>56) -#endif - -#ifndef STOREMOTOROLADWORD -#define STOREMOTOROLADWORD(a, b) *(((UINT8*)(a))+3) = (UINT8)((b)); \ - *(((UINT8*)(a))+2) = (UINT8)((b)>>8); \ - *(((UINT8*)(a))+1) = (UINT8)((b)>>16); \ - *(((UINT8*)(a))+0) = (UINT8)((b)>>24) -#endif - -#ifndef STOREMOTOROLAWORD -#define STOREMOTOROLAWORD(a, b) *(((UINT8*)(a))+1) = (UINT8)((b)); \ - *(((UINT8*)(a))+0) = (UINT8)((b)>>8) -#endif - -/* *** */ - -#ifndef NELEMENTS -#define NELEMENTS(a) ((int)(sizeof(a) / sizeof(a[0]))) -#endif - - -// ---- Optimize Macros - -#ifndef REG8 -#define REG8 UINT8 -#endif -#ifndef REG16 -#define REG16 UINT16 -#endif - -#if defined(USE_CPU_PLATFORMINT) -// プラットフォームネイティブの整数型を使用 -typedef UINT32 PF_UINT8; -typedef UINT32 PF_UINT16; -typedef UINT32 PF_UINT32; -#else -typedef UINT8 PF_UINT8; -typedef UINT16 PF_UINT16; -typedef UINT32 PF_UINT32; -#endif - -#ifndef LOW8 -#define LOW8(a) ((UINT8)(a)) -#endif -#ifndef LOW10 -#define LOW10(a) ((a) & 0x03ff) -#endif -#ifndef LOW11 -#define LOW11(a) ((a) & 0x07ff) -#endif -#ifndef LOW12 -#define LOW12(a) ((a) & 0x0fff) -#endif -#ifndef LOW14 -#define LOW14(a) ((a) & 0x3fff) -#endif -#ifndef LOW15 -#define LOW15(a) ((a) & 0x7fff) -#endif -#ifndef LOW16 -#define LOW16(a) ((UINT16)(a)) -#endif -#ifndef HIGH16 -#define HIGH16(a) (((UINT32)(a)) >> 16) -#endif - - -#ifndef OEMCHAR -#define OEMCHAR char -#endif -#ifndef OEMTEXT -#define OEMTEXT(string) string -#endif - - -#if !defined(RGB16) -#define RGB16 UINT16 -#endif - -#if !defined(RGB32) -#if defined(BYTESEX_LITTLE) -typedef union { - UINT32 d; - struct { - UINT8 b; - UINT8 g; - UINT8 r; - UINT8 e; - } p; -} RGB32; -#define RGB32D(r, g, b) (((r) << 16) + ((g) << 8) + ((b) << 0)) -#elif defined(BYTESEX_BIG) -typedef union { - UINT32 d; - struct { - UINT8 e; - UINT8 r; - UINT8 g; - UINT8 b; - } p; -} RGB32; -#define RGB32D(r, g, b) (((r) << 16) + ((g) << 8) + ((b) << 0)) -#endif -#endif - - -#define FTYPEID(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) - -enum { - FTYPE_NONE = 0, - FTYPE_SMIL = FTYPEID('S','M','I','L'), - FTYPE_TEXT = FTYPEID('T','E','X','T'), - FTYPE_BMP = FTYPEID('B','M','P',' '), - FTYPE_GIF = FTYPEID('G','I','F',' '), - FTYPE_WAVE = FTYPEID('W','A','V','E'), - FTYPE_OGG = FTYPEID('O','G','G',' '), - FTYPE_MP3 = FTYPEID('M','P','3',' '), - FTYPE_D88 = FTYPEID('.','D','8','8'), - FTYPE_FDI = FTYPEID('.','F','D','I'), - FTYPE_BETA = FTYPEID('B','E','T','A'), - FTYPE_THD = FTYPEID('.','T','H','D'), - FTYPE_NHD = FTYPEID('.','N','H','D'), - FTYPE_HDI = FTYPEID('.','H','D','I'), - FTYPE_HDD = FTYPEID('.','H','D','D'), - FTYPE_S98 = FTYPEID('.','S','9','8'), - FTYPE_MIMPI = FTYPEID('M','I','M','P') -}; - - -#if !defined(INLINE) -#if defined(DEBUG) -#define INLINE -#else -#define INLINE inline -#endif -#endif -#if !defined(FASTCALL) -#define FASTCALL -#endif - -#endif /* NP2_COMMON_H */ +#ifndef NP2_COMMON_H +#define NP2_COMMON_H + +enum { + SUCCESS = 0, + FAILURE = 1 +}; + +#ifndef BRESULT +#define BRESULT UINT +#endif + +#ifndef INTPTR +#define INTPTR intptr_t +#endif +#ifndef UINTPTR +#define UINTPTR uintptr_t +#endif + +#ifndef LOADINTELDWORD +#define LOADINTELDWORD(a) (((UINT32)(((UINT8*)(a))[0])) | \ + ((UINT32)(((UINT8*)(a))[1]) << 8) | \ + ((UINT32)(((UINT8*)(a))[2]) << 16) | \ + ((UINT32)(((UINT8*)(a))[3]) << 24)) +#endif + +#ifndef LOADINTELWORD +#define LOADINTELWORD(a) (((UINT16)((UINT8*)(a))[0]) | ((UINT16)(((UINT8*)(a))[1]) << 8)) +#endif + +#ifndef STOREINTELDWORD +#define STOREINTELDWORD(a, b) *(((UINT8*)(a))+0) = (UINT8)((b)); \ + *(((UINT8*)(a))+1) = (UINT8)((b)>>8); \ + *(((UINT8*)(a))+2) = (UINT8)((b)>>16); \ + *(((UINT8*)(a))+3) = (UINT8)((b)>>24) +#endif + +#ifndef STOREINTELWORD +#define STOREINTELWORD(a, b) *(((UINT8*)(a))+0) = (UINT8)((b)); \ + *(((UINT8*)(a))+1) = (UINT8)((b)>>8) +#endif + +/* Big Ending */ + +#ifndef LOADMOTOROLAQWORD +#define LOADMOTOROLAQWORD(a) (((UINT64)((UINT8*)(a))[7]) | \ + ((UINT64)(((UINT8*)(a))[6]) << 8) | \ + ((UINT64)(((UINT8*)(a))[5]) << 16) | \ + ((UINT64)(((UINT8*)(a))[4]) << 24) | \ + ((UINT64)(((UINT8*)(a))[3]) << 32) | \ + ((UINT64)(((UINT8*)(a))[2]) << 40) | \ + ((UINT64)(((UINT8*)(a))[1]) << 48) | \ + ((UINT64)(((UINT8*)(a))[0]) << 56)) +#endif + +#ifndef LOADMOTOROLADWORD +#define LOADMOTOROLADWORD(a) (((UINT32)((UINT8*)(a))[3]) | \ + ((UINT32)(((UINT8*)(a))[2]) << 8) | \ + ((UINT32)(((UINT8*)(a))[1]) << 16) | \ + ((UINT32)(((UINT8*)(a))[0]) << 24)) +#endif + +#ifndef LOADMOTOROLAWORD +#define LOADMOTOROLAWORD(a) (((UINT16)((UINT8*)(a))[1]) | ((UINT16)(((UINT8*)(a))[0]) << 8)) +#endif + +#ifndef STOREMOTOROLAQWORD +#define STOREMOTOROLAQWORD(a, b) *(((UINT8*)(a))+7) = (UINT8)((b)); \ + *(((UINT8*)(a))+6) = (UINT8)((b)>>8); \ + *(((UINT8*)(a))+5) = (UINT8)((b)>>16); \ + *(((UINT8*)(a))+4) = (UINT8)((b)>>24); \ + *(((UINT8*)(a))+3) = (UINT8)((b)>>32); \ + *(((UINT8*)(a))+2) = (UINT8)((b)>>40); \ + *(((UINT8*)(a))+1) = (UINT8)((b)>>48); \ + *(((UINT8*)(a))+0) = (UINT8)((b)>>56) +#endif + +#ifndef STOREMOTOROLADWORD +#define STOREMOTOROLADWORD(a, b) *(((UINT8*)(a))+3) = (UINT8)((b)); \ + *(((UINT8*)(a))+2) = (UINT8)((b)>>8); \ + *(((UINT8*)(a))+1) = (UINT8)((b)>>16); \ + *(((UINT8*)(a))+0) = (UINT8)((b)>>24) +#endif + +#ifndef STOREMOTOROLAWORD +#define STOREMOTOROLAWORD(a, b) *(((UINT8*)(a))+1) = (UINT8)((b)); \ + *(((UINT8*)(a))+0) = (UINT8)((b)>>8) +#endif + +/* *** */ + +#ifndef NELEMENTS +#define NELEMENTS(a) ((int)(sizeof(a) / sizeof(a[0]))) +#endif + + +// ---- Optimize Macros + +#ifndef REG8 +#define REG8 UINT8 +#endif +#ifndef REG16 +#define REG16 UINT16 +#endif + +#if defined(USE_CPU_PLATFORMINT) +// プラットフォームネイティブの整数型を使用 +typedef UINT32 PF_UINT8; +typedef UINT32 PF_UINT16; +typedef UINT32 PF_UINT32; +#else +typedef UINT8 PF_UINT8; +typedef UINT16 PF_UINT16; +typedef UINT32 PF_UINT32; +#endif + +#ifndef LOW8 +#define LOW8(a) ((UINT8)(a)) +#endif +#ifndef LOW10 +#define LOW10(a) ((a) & 0x03ff) +#endif +#ifndef LOW11 +#define LOW11(a) ((a) & 0x07ff) +#endif +#ifndef LOW12 +#define LOW12(a) ((a) & 0x0fff) +#endif +#ifndef LOW14 +#define LOW14(a) ((a) & 0x3fff) +#endif +#ifndef LOW15 +#define LOW15(a) ((a) & 0x7fff) +#endif +#ifndef LOW16 +#define LOW16(a) ((UINT16)(a)) +#endif +#ifndef HIGH16 +#define HIGH16(a) (((UINT32)(a)) >> 16) +#endif + + +#ifndef OEMCHAR +#define OEMCHAR char +#endif +#ifndef OEMTEXT +#define OEMTEXT(string) string +#endif + + +#if !defined(RGB16) +#define RGB16 UINT16 +#endif + +#if !defined(RGB32) +#if defined(BYTESEX_LITTLE) +typedef union { + UINT32 d; + struct { + UINT8 b; + UINT8 g; + UINT8 r; + UINT8 e; + } p; +} RGB32; +#define RGB32D(r, g, b) (((r) << 16) + ((g) << 8) + ((b) << 0)) +#elif defined(BYTESEX_BIG) +typedef union { + UINT32 d; + struct { + UINT8 e; + UINT8 r; + UINT8 g; + UINT8 b; + } p; +} RGB32; +#define RGB32D(r, g, b) (((r) << 16) + ((g) << 8) + ((b) << 0)) +#endif +#endif + + +#define FTYPEID(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) + +enum { + FTYPE_NONE = 0, + FTYPE_SMIL = FTYPEID('S','M','I','L'), + FTYPE_TEXT = FTYPEID('T','E','X','T'), + FTYPE_BMP = FTYPEID('B','M','P',' '), + FTYPE_GIF = FTYPEID('G','I','F',' '), + FTYPE_WAVE = FTYPEID('W','A','V','E'), + FTYPE_OGG = FTYPEID('O','G','G',' '), + FTYPE_MP3 = FTYPEID('M','P','3',' '), + FTYPE_D88 = FTYPEID('.','D','8','8'), + FTYPE_FDI = FTYPEID('.','F','D','I'), + FTYPE_BETA = FTYPEID('B','E','T','A'), + FTYPE_THD = FTYPEID('.','T','H','D'), + FTYPE_NHD = FTYPEID('.','N','H','D'), + FTYPE_HDI = FTYPEID('.','H','D','I'), + FTYPE_HDD = FTYPEID('.','H','D','D'), + FTYPE_S98 = FTYPEID('.','S','9','8'), + FTYPE_MIMPI = FTYPEID('M','I','M','P') +}; + + +#if !defined(INLINE) +#if defined(DEBUG) +#define INLINE +#else +#define INLINE inline +#endif +#endif +#if !defined(FASTCALL) +#define FASTCALL +#endif + +#endif /* NP2_COMMON_H */ diff --git a/common/_memory.c b/common/_memory.c old mode 100755 new mode 100644 index 080c98b8..cb081287 --- a/common/_memory.c +++ b/common/_memory.c @@ -1,227 +1,227 @@ -#include - - -#define MEMTBLMAX 256 -#define HDLTBLMAX 256 - - -#if defined(MEMTRACE) - -#include -#include - -#if defined(MACOS) -#define CRLITERAL "\r" -#elif defined(X11) -#define CRLITERAL "\n" -#else -#define CRLITERAL "\r\n" -#endif -static const char s_cr[] = CRLITERAL; - -typedef struct { - void *hdl; - UINT size; - char name[24]; -} _MEMTBL; - -typedef struct { - void *hdl; - char name[28]; -} _HDLTBL; - -static _MEMTBL memtbl[MEMTBLMAX]; -static _HDLTBL hdltbl[HDLTBLMAX]; - -static const char str_memhdr[] = \ - "Handle Size Name" CRLITERAL \ - "--------------------------------------------" CRLITERAL; - -static const char str_hdlhdr[] = \ - "Handle Name" CRLITERAL \ - "-------------------------------------" CRLITERAL; - -static const char str_memused[] = "memused: %d" CRLITERAL; - -void _meminit(void) { - - ZeroMemory(memtbl, sizeof(memtbl)); - ZeroMemory(hdltbl, sizeof(hdltbl)); -} - -void *_memalloc(int size, const char *name) { - - void *ret; - int i; - - ret = malloc(size); - if (ret) { - for (i=0; i>3] |= (UINT8)(0x80 >> (i & 7)); - memuses++; - } - } - for (i=0; i>3] |= (UINT8)(0x80 >> (i & 7)); - hdluses++; - } - } - fh = file_create_c(filename); - if (fh != FILEH_INVALID) { - sprintf(work, "memused: %d\r\n"); - file_write(fh, work, strlen(work)); - if (memuses) { - file_write(fh, str_memhdr, strlen(str_memhdr)); - for (i=0; i>3] << (i & 7)) & 0x80) { - sprintf(work, "%08lx %10u %s\r\n", - (long)memtbl[i].hdl, memtbl[i].size, memtbl[i].name); - file_write(fh, work, strlen(work)); - } - } - file_write(fh, s_cr, strlen(s_cr)); - } - sprintf(work, "hdlused: %d\r\n", hdluses); - file_write(fh, work, strlen(work)); - if (hdluses) { - file_write(fh, str_hdlhdr, strlen(str_hdlhdr)); - for (i=0; i>3] << (i & 7)) & 0x80) { - sprintf(work, "%08lx %s\r\n", - (long)hdltbl[i].hdl, hdltbl[i].name); - file_write(fh, work, strlen(work)); - } - } - file_write(fh, s_cr, strlen(s_cr)); - } - file_close(fh); - } -} - -#elif defined(MEMCHECK) - -typedef struct { - void *hdl; - UINT size; -} _MEMTBL; - - BOOL chgmemory; - UINT usedmemory; - -static _MEMTBL memtbl[MEMTBLMAX]; - -void _meminit(void) { - - usedmemory = 0; - chgmemory = FALSE; - ZeroMemory(memtbl, sizeof(memtbl)); -} - -void *_memalloc(int size) { - - void *ret; - int i; - - ret = malloc(size); - if (ret) { - for (i=0; i + + +#define MEMTBLMAX 256 +#define HDLTBLMAX 256 + + +#if defined(MEMTRACE) + +#include +#include + +#if defined(MACOS) +#define CRLITERAL "\r" +#elif defined(X11) +#define CRLITERAL "\n" +#else +#define CRLITERAL "\r\n" +#endif +static const char s_cr[] = CRLITERAL; + +typedef struct { + void *hdl; + UINT size; + char name[24]; +} _MEMTBL; + +typedef struct { + void *hdl; + char name[28]; +} _HDLTBL; + +static _MEMTBL memtbl[MEMTBLMAX]; +static _HDLTBL hdltbl[HDLTBLMAX]; + +static const char str_memhdr[] = \ + "Handle Size Name" CRLITERAL \ + "--------------------------------------------" CRLITERAL; + +static const char str_hdlhdr[] = \ + "Handle Name" CRLITERAL \ + "-------------------------------------" CRLITERAL; + +static const char str_memused[] = "memused: %d" CRLITERAL; + +void _meminit(void) { + + ZeroMemory(memtbl, sizeof(memtbl)); + ZeroMemory(hdltbl, sizeof(hdltbl)); +} + +void *_memalloc(int size, const char *name) { + + void *ret; + int i; + + ret = malloc(size); + if (ret) { + for (i=0; i>3] |= (UINT8)(0x80 >> (i & 7)); + memuses++; + } + } + for (i=0; i>3] |= (UINT8)(0x80 >> (i & 7)); + hdluses++; + } + } + fh = file_create_c(filename); + if (fh != FILEH_INVALID) { + sprintf(work, "memused: %d\r\n"); + file_write(fh, work, strlen(work)); + if (memuses) { + file_write(fh, str_memhdr, strlen(str_memhdr)); + for (i=0; i>3] << (i & 7)) & 0x80) { + sprintf(work, "%08lx %10u %s\r\n", + (long)memtbl[i].hdl, memtbl[i].size, memtbl[i].name); + file_write(fh, work, strlen(work)); + } + } + file_write(fh, s_cr, strlen(s_cr)); + } + sprintf(work, "hdlused: %d\r\n", hdluses); + file_write(fh, work, strlen(work)); + if (hdluses) { + file_write(fh, str_hdlhdr, strlen(str_hdlhdr)); + for (i=0; i>3] << (i & 7)) & 0x80) { + sprintf(work, "%08lx %s\r\n", + (long)hdltbl[i].hdl, hdltbl[i].name); + file_write(fh, work, strlen(work)); + } + } + file_write(fh, s_cr, strlen(s_cr)); + } + file_close(fh); + } +} + +#elif defined(MEMCHECK) + +typedef struct { + void *hdl; + UINT size; +} _MEMTBL; + + BOOL chgmemory; + UINT usedmemory; + +static _MEMTBL memtbl[MEMTBLMAX]; + +void _meminit(void) { + + usedmemory = 0; + chgmemory = FALSE; + ZeroMemory(memtbl, sizeof(memtbl)); +} + +void *_memalloc(int size) { + + void *ret; + int i; + + ret = malloc(size); + if (ret) { + for (i=0; i -#include - - -UINT bmpdata_getalign(const BMPINFO *bi) { - - UINT ret; - int width; - int bit; - - width = LOADINTELDWORD(bi->biWidth); - bit = LOADINTELWORD(bi->biBitCount); - ret = ((width * bit) + 7) / 8; - ret = (ret + 3) & (~3); - return(ret); -} - -UINT bmpdata_getdatasize(const BMPINFO *bi) { - - int height; - - height = (SINT32)LOADINTELDWORD(bi->biHeight); - if (height < 0) { - height = 0 - height; - } - return(height * bmpdata_getalign(bi)); -} - -UINT bmpdata_sethead(BMPFILE *bf, const BMPINFO *bi) { - - UINT ret; - UINT bit; - UINT pal; - - ret = 0; - if (bi == NULL) { - goto bdsh_exit; - } - ret = sizeof(BMPFILE) + sizeof(BMPINFO); - bit = LOADINTELWORD(bi->biBitCount); - if (bit < 8) { - pal = LOADINTELDWORD(bi->biClrUsed); - pal = MIN(pal, (UINT)(1 << bit)); - ret += pal * 4; - } - if (bf) { - ZeroMemory(bf, sizeof(BMPFILE)); - bf->bfType[0] = 'B'; - bf->bfType[1] = 'M'; - STOREINTELDWORD(bf->bfOffBits, ret); - } - ret += bmpdata_getdatasize(bi); - -bdsh_exit: - return(ret); -} - -UINT bmpdata_setinfo(BMPINFO *bi, const BMPDATA *inf) { - - UINT ret; - UINT tmp; - - ret = 0; - if ((bi == NULL) || (inf == NULL)) { - goto bdsi_exit; - } - ZeroMemory(bi, sizeof(BMPINFO)); - STOREINTELDWORD(bi->biSize, sizeof(BMPINFO)); - STOREINTELDWORD(bi->biWidth, inf->width); - STOREINTELDWORD(bi->biHeight, inf->height); - STOREINTELWORD(bi->biPlanes, 1); - STOREINTELWORD(bi->biBitCount, inf->bpp); -// STOREINTELDWORD(bi->biCompression, BI_RGB); - ret = bmpdata_getdatasize(bi); - STOREINTELDWORD(bi->biSizeImage, ret); -// STOREINTELDWORD(bi->biXPelsPerMeter, 0); -// STOREINTELDWORD(bi->biYPelsPerMeter, 0); - if (inf->bpp <= 8) { - tmp = 1 << inf->bpp; - STOREINTELDWORD(bi->biClrUsed, tmp); - STOREINTELDWORD(bi->biClrImportant, tmp); - } - -bdsi_exit: - return(ret); -} - -BRESULT bmpdata_getinfo(const BMPINFO *bi, BMPDATA *inf) { - - UINT tmp; - int width; - int height; - - if ((bi == NULL) || (inf == NULL)) { - goto bdgi_err; - } - - tmp = LOADINTELDWORD(bi->biSize); - if (tmp != sizeof(BMPINFO)) { - goto bdgi_err; - } - tmp = LOADINTELWORD(bi->biPlanes); - if (tmp != 1) { - goto bdgi_err; - } - tmp = LOADINTELDWORD(bi->biCompression); - if (tmp != 0) { - goto bdgi_err; - } - width = (SINT32)LOADINTELDWORD(bi->biWidth); - height = (SINT32)LOADINTELDWORD(bi->biHeight); - if ((width <= 0) || (height == 0)) { - goto bdgi_err; - } - inf->width = width; - inf->height = height; - inf->bpp = LOADINTELWORD(bi->biBitCount); - return(SUCCESS); - -bdgi_err: - return(FAILURE); -} - -UINT8 *bmpdata_lzx(int level, int dstsize, const UINT8 *dat) { - - UINT8 *ret; - UINT8 *ptr; - UINT8 ctrl; - UINT8 bit; - UINT mask; - UINT tmp; - int pos; - int leng; - - ret = NULL; - if (dat == NULL) { - return(NULL); - } - ret = (UINT8 *)_MALLOC(dstsize, "res"); - if (ret == NULL) { - goto lxz_err; - } - ptr = ret; - - ctrl = 0; - bit = 0; - mask = (1 << level) - 1; - while(dstsize > 0) { - if (!bit) { - ctrl = *dat++; - bit = 0x80; - } - if (ctrl & bit) { - tmp = *dat++; - tmp <<= 8; - tmp |= *dat++; - pos = -1 - (tmp >> level); - leng = (tmp & mask) + 1; - leng = MIN(leng, dstsize); - dstsize -= leng; - while(leng--) { - *ptr = *(ptr + pos); - ptr++; - } - } - else { - *ptr++ = *dat++; - dstsize--; - } - bit >>= 1; - } - -lxz_err: - return(ret); -} - -UINT8 *bmpdata_solvedata(const UINT8 *dat) { - - int dstsize; - - if (dat == NULL) { - return(NULL); - } - dstsize = dat[0] + (dat[1] << 8) + (dat[2] << 16); - return(bmpdata_lzx(dat[3], dstsize, dat + 4)); -} - +#include +#include + + +UINT bmpdata_getalign(const BMPINFO *bi) { + + UINT ret; + int width; + int bit; + + width = LOADINTELDWORD(bi->biWidth); + bit = LOADINTELWORD(bi->biBitCount); + ret = ((width * bit) + 7) / 8; + ret = (ret + 3) & (~3); + return(ret); +} + +UINT bmpdata_getdatasize(const BMPINFO *bi) { + + int height; + + height = (SINT32)LOADINTELDWORD(bi->biHeight); + if (height < 0) { + height = 0 - height; + } + return(height * bmpdata_getalign(bi)); +} + +UINT bmpdata_sethead(BMPFILE *bf, const BMPINFO *bi) { + + UINT ret; + UINT bit; + UINT pal; + + ret = 0; + if (bi == NULL) { + goto bdsh_exit; + } + ret = sizeof(BMPFILE) + sizeof(BMPINFO); + bit = LOADINTELWORD(bi->biBitCount); + if (bit < 8) { + pal = LOADINTELDWORD(bi->biClrUsed); + pal = MIN(pal, (UINT)(1 << bit)); + ret += pal * 4; + } + if (bf) { + ZeroMemory(bf, sizeof(BMPFILE)); + bf->bfType[0] = 'B'; + bf->bfType[1] = 'M'; + STOREINTELDWORD(bf->bfOffBits, ret); + } + ret += bmpdata_getdatasize(bi); + +bdsh_exit: + return(ret); +} + +UINT bmpdata_setinfo(BMPINFO *bi, const BMPDATA *inf) { + + UINT ret; + UINT tmp; + + ret = 0; + if ((bi == NULL) || (inf == NULL)) { + goto bdsi_exit; + } + ZeroMemory(bi, sizeof(BMPINFO)); + STOREINTELDWORD(bi->biSize, sizeof(BMPINFO)); + STOREINTELDWORD(bi->biWidth, inf->width); + STOREINTELDWORD(bi->biHeight, inf->height); + STOREINTELWORD(bi->biPlanes, 1); + STOREINTELWORD(bi->biBitCount, inf->bpp); +// STOREINTELDWORD(bi->biCompression, BI_RGB); + ret = bmpdata_getdatasize(bi); + STOREINTELDWORD(bi->biSizeImage, ret); +// STOREINTELDWORD(bi->biXPelsPerMeter, 0); +// STOREINTELDWORD(bi->biYPelsPerMeter, 0); + if (inf->bpp <= 8) { + tmp = 1 << inf->bpp; + STOREINTELDWORD(bi->biClrUsed, tmp); + STOREINTELDWORD(bi->biClrImportant, tmp); + } + +bdsi_exit: + return(ret); +} + +BRESULT bmpdata_getinfo(const BMPINFO *bi, BMPDATA *inf) { + + UINT tmp; + int width; + int height; + + if ((bi == NULL) || (inf == NULL)) { + goto bdgi_err; + } + + tmp = LOADINTELDWORD(bi->biSize); + if (tmp != sizeof(BMPINFO)) { + goto bdgi_err; + } + tmp = LOADINTELWORD(bi->biPlanes); + if (tmp != 1) { + goto bdgi_err; + } + tmp = LOADINTELDWORD(bi->biCompression); + if (tmp != 0) { + goto bdgi_err; + } + width = (SINT32)LOADINTELDWORD(bi->biWidth); + height = (SINT32)LOADINTELDWORD(bi->biHeight); + if ((width <= 0) || (height == 0)) { + goto bdgi_err; + } + inf->width = width; + inf->height = height; + inf->bpp = LOADINTELWORD(bi->biBitCount); + return(SUCCESS); + +bdgi_err: + return(FAILURE); +} + +UINT8 *bmpdata_lzx(int level, int dstsize, const UINT8 *dat) { + + UINT8 *ret; + UINT8 *ptr; + UINT8 ctrl; + UINT8 bit; + UINT mask; + UINT tmp; + int pos; + int leng; + + ret = NULL; + if (dat == NULL) { + return(NULL); + } + ret = (UINT8 *)_MALLOC(dstsize, "res"); + if (ret == NULL) { + goto lxz_err; + } + ptr = ret; + + ctrl = 0; + bit = 0; + mask = (1 << level) - 1; + while(dstsize > 0) { + if (!bit) { + ctrl = *dat++; + bit = 0x80; + } + if (ctrl & bit) { + tmp = *dat++; + tmp <<= 8; + tmp |= *dat++; + pos = -1 - (tmp >> level); + leng = (tmp & mask) + 1; + leng = MIN(leng, dstsize); + dstsize -= leng; + while(leng--) { + *ptr = *(ptr + pos); + ptr++; + } + } + else { + *ptr++ = *dat++; + dstsize--; + } + bit >>= 1; + } + +lxz_err: + return(ret); +} + +UINT8 *bmpdata_solvedata(const UINT8 *dat) { + + int dstsize; + + if (dat == NULL) { + return(NULL); + } + dstsize = dat[0] + (dat[1] << 8) + (dat[2] << 16); + return(bmpdata_lzx(dat[3], dstsize, dat + 4)); +} + diff --git a/common/bmpdata.h b/common/bmpdata.h old mode 100755 new mode 100644 index 6fb48af4..9f12787c --- a/common/bmpdata.h +++ b/common/bmpdata.h @@ -1,75 +1,75 @@ -#ifndef BMPDATA_H -#define BMPDATA_H - -#if defined(__GNUC__) -typedef struct { - UINT8 bfType[2]; - UINT8 bfSize[4]; - UINT8 bfReserved1[2]; - UINT8 bfReserved2[2]; - UINT8 bfOffBits[4]; -} __attribute__ ((packed)) BMPFILE; -typedef struct { - UINT8 biSize[4]; - UINT8 biWidth[4]; - UINT8 biHeight[4]; - UINT8 biPlanes[2]; - UINT8 biBitCount[2]; - UINT8 biCompression[4]; - UINT8 biSizeImage[4]; - UINT8 biXPelsPerMeter[4]; - UINT8 biYPelsPerMeter[4]; - UINT8 biClrUsed[4]; - UINT8 biClrImportant[4]; -} __attribute__ ((packed)) BMPINFO; -#else -#pragma pack(push, 1) -typedef struct { - UINT8 bfType[2]; - UINT8 bfSize[4]; - UINT8 bfReserved1[2]; - UINT8 bfReserved2[2]; - UINT8 bfOffBits[4]; -} BMPFILE; -typedef struct { - UINT8 biSize[4]; - UINT8 biWidth[4]; - UINT8 biHeight[4]; - UINT8 biPlanes[2]; - UINT8 biBitCount[2]; - UINT8 biCompression[4]; - UINT8 biSizeImage[4]; - UINT8 biXPelsPerMeter[4]; - UINT8 biYPelsPerMeter[4]; - UINT8 biClrUsed[4]; - UINT8 biClrImportant[4]; -} BMPINFO; -#pragma pack(pop) -#endif - -typedef struct { - int width; - int height; - int bpp; -} BMPDATA; - - -#ifdef __cplusplus -extern "C" { -#endif - -UINT bmpdata_getalign(const BMPINFO *bi); -UINT bmpdata_getdatasize(const BMPINFO *bi); - -UINT bmpdata_sethead(BMPFILE *bf, const BMPINFO *bi); -UINT bmpdata_setinfo(BMPINFO *bi, const BMPDATA *inf); -BRESULT bmpdata_getinfo(const BMPINFO *bi, BMPDATA *inf); - -UINT8 *bmpdata_lzx(int level, int dstsize, const UINT8 *dat); -UINT8 *bmpdata_solvedata(const UINT8 *dat); - -#ifdef __cplusplus -} -#endif - -#endif /* BMPDATA_H */ +#ifndef BMPDATA_H +#define BMPDATA_H + +#if defined(__GNUC__) +typedef struct { + UINT8 bfType[2]; + UINT8 bfSize[4]; + UINT8 bfReserved1[2]; + UINT8 bfReserved2[2]; + UINT8 bfOffBits[4]; +} __attribute__ ((packed)) BMPFILE; +typedef struct { + UINT8 biSize[4]; + UINT8 biWidth[4]; + UINT8 biHeight[4]; + UINT8 biPlanes[2]; + UINT8 biBitCount[2]; + UINT8 biCompression[4]; + UINT8 biSizeImage[4]; + UINT8 biXPelsPerMeter[4]; + UINT8 biYPelsPerMeter[4]; + UINT8 biClrUsed[4]; + UINT8 biClrImportant[4]; +} __attribute__ ((packed)) BMPINFO; +#else +#pragma pack(push, 1) +typedef struct { + UINT8 bfType[2]; + UINT8 bfSize[4]; + UINT8 bfReserved1[2]; + UINT8 bfReserved2[2]; + UINT8 bfOffBits[4]; +} BMPFILE; +typedef struct { + UINT8 biSize[4]; + UINT8 biWidth[4]; + UINT8 biHeight[4]; + UINT8 biPlanes[2]; + UINT8 biBitCount[2]; + UINT8 biCompression[4]; + UINT8 biSizeImage[4]; + UINT8 biXPelsPerMeter[4]; + UINT8 biYPelsPerMeter[4]; + UINT8 biClrUsed[4]; + UINT8 biClrImportant[4]; +} BMPINFO; +#pragma pack(pop) +#endif + +typedef struct { + int width; + int height; + int bpp; +} BMPDATA; + + +#ifdef __cplusplus +extern "C" { +#endif + +UINT bmpdata_getalign(const BMPINFO *bi); +UINT bmpdata_getdatasize(const BMPINFO *bi); + +UINT bmpdata_sethead(BMPFILE *bf, const BMPINFO *bi); +UINT bmpdata_setinfo(BMPINFO *bi, const BMPDATA *inf); +BRESULT bmpdata_getinfo(const BMPINFO *bi, BMPDATA *inf); + +UINT8 *bmpdata_lzx(int level, int dstsize, const UINT8 *dat); +UINT8 *bmpdata_solvedata(const UINT8 *dat); + +#ifdef __cplusplus +} +#endif + +#endif /* BMPDATA_H */ diff --git a/common/lstarray.c b/common/lstarray.c old mode 100755 new mode 100644 index f596a1c5..06aa1601 --- a/common/lstarray.c +++ b/common/lstarray.c @@ -1,151 +1,151 @@ -#include - - -LISTARRAY listarray_new(size_t listsize, UINT maxitems) { - - LISTARRAY laRet = NULL; - UINT dwSize; - - listsize = (listsize + 3) & (~3); - dwSize = sizeof(_LISTARRAY); - dwSize += (UINT)(listsize * maxitems); - -#ifdef TRACE - { - char work[256]; - SPRINTF(work, "listarray %dx%d", listsize, maxitems); - laRet = (LISTARRAY)_MALLOC(dwSize, work); - } -#else - laRet = (LISTARRAY)_MALLOC(dwSize, "listarray"); -#endif - if (laRet) { - ZeroMemory(laRet, dwSize); - laRet->maxitems = maxitems; - laRet->listsize = listsize; - } - return(laRet); -} - -void listarray_clr(LISTARRAY laHandle) { - - while(laHandle) { - laHandle->items = 0; - laHandle = laHandle->laNext; - } -} - -void listarray_destroy(LISTARRAY laHandle) { - - LISTARRAY laNext; - - while(laHandle) { - laNext = laHandle->laNext; - _MFREE(laHandle); - laHandle = laNext; - } -} - -UINT listarray_getitems(LISTARRAY laHandle) { - - UINT dwRet; - - dwRet = 0; - while(laHandle) { - dwRet += laHandle->items; - laHandle = laHandle->laNext; - } - return(dwRet); -} - -void *listarray_append(LISTARRAY laHandle, const void *vpItem) { - - LISTARRAY laNext; - UINT8 *p; - - if (laHandle == NULL) { - goto laapp_err; - } - - while(laHandle->items >= laHandle->maxitems) { - laNext = laHandle->laNext; - if (laNext == NULL) { - laNext = listarray_new(laHandle->listsize, laHandle->maxitems); - if (laNext == NULL) { - goto laapp_err; - } - laHandle->laNext = laNext; - } - laHandle = laNext; - } - p = (UINT8 *)(laHandle + 1); - p += laHandle->items * laHandle->listsize; - if (vpItem) { - CopyMemory(p, vpItem, laHandle->listsize); - } - else { - ZeroMemory(p, laHandle->listsize); - } - laHandle->items++; - return(p); - -laapp_err: - return(NULL); -} - -void *listarray_getitem(LISTARRAY laHandle, UINT num) { - - while(laHandle) { - if (num < laHandle->items) { - return((UINT8 *)(laHandle + 1) + (laHandle->listsize * num)); - } - num -= laHandle->items; - laHandle = laHandle->laNext; - } - return(NULL); -} - -UINT listarray_getpos(LISTARRAY laHandle, void *vpItem) { - - UINT pos; - UINT i; - - pos = 0; - while(laHandle) { - UINT8 *p = (UINT8 *)(laHandle + 1); - for (i=0; iitems; i++) { - if (p == vpItem) { - return(pos + i); - } - p += laHandle->listsize; - } - pos += laHandle->items; - laHandle = laHandle->laNext; - } - return((UINT)-1); -} - -void *listarray_enum(LISTARRAY laHandle, - BOOL (*cbProc)(void *vpItem, void *vpArg), void *vpArg) { - - UINT i; - - if (cbProc == NULL) { - goto laenum_end; - } - - while(laHandle) { - UINT8 *p = (UINT8 *)(laHandle + 1); - for (i=0; iitems; i++) { - if (cbProc((void *)p, vpArg)) { - return((void *)p); - } - p += laHandle->listsize; - } - laHandle = laHandle->laNext; - } - -laenum_end: - return(NULL); -} - +#include + + +LISTARRAY listarray_new(size_t listsize, UINT maxitems) { + + LISTARRAY laRet = NULL; + UINT dwSize; + + listsize = (listsize + 3) & (~3); + dwSize = sizeof(_LISTARRAY); + dwSize += (UINT)(listsize * maxitems); + +#ifdef TRACE + { + char work[256]; + SPRINTF(work, "listarray %dx%d", listsize, maxitems); + laRet = (LISTARRAY)_MALLOC(dwSize, work); + } +#else + laRet = (LISTARRAY)_MALLOC(dwSize, "listarray"); +#endif + if (laRet) { + ZeroMemory(laRet, dwSize); + laRet->maxitems = maxitems; + laRet->listsize = listsize; + } + return(laRet); +} + +void listarray_clr(LISTARRAY laHandle) { + + while(laHandle) { + laHandle->items = 0; + laHandle = laHandle->laNext; + } +} + +void listarray_destroy(LISTARRAY laHandle) { + + LISTARRAY laNext; + + while(laHandle) { + laNext = laHandle->laNext; + _MFREE(laHandle); + laHandle = laNext; + } +} + +UINT listarray_getitems(LISTARRAY laHandle) { + + UINT dwRet; + + dwRet = 0; + while(laHandle) { + dwRet += laHandle->items; + laHandle = laHandle->laNext; + } + return(dwRet); +} + +void *listarray_append(LISTARRAY laHandle, const void *vpItem) { + + LISTARRAY laNext; + UINT8 *p; + + if (laHandle == NULL) { + goto laapp_err; + } + + while(laHandle->items >= laHandle->maxitems) { + laNext = laHandle->laNext; + if (laNext == NULL) { + laNext = listarray_new(laHandle->listsize, laHandle->maxitems); + if (laNext == NULL) { + goto laapp_err; + } + laHandle->laNext = laNext; + } + laHandle = laNext; + } + p = (UINT8 *)(laHandle + 1); + p += laHandle->items * laHandle->listsize; + if (vpItem) { + CopyMemory(p, vpItem, laHandle->listsize); + } + else { + ZeroMemory(p, laHandle->listsize); + } + laHandle->items++; + return(p); + +laapp_err: + return(NULL); +} + +void *listarray_getitem(LISTARRAY laHandle, UINT num) { + + while(laHandle) { + if (num < laHandle->items) { + return((UINT8 *)(laHandle + 1) + (laHandle->listsize * num)); + } + num -= laHandle->items; + laHandle = laHandle->laNext; + } + return(NULL); +} + +UINT listarray_getpos(LISTARRAY laHandle, void *vpItem) { + + UINT pos; + UINT i; + + pos = 0; + while(laHandle) { + UINT8 *p = (UINT8 *)(laHandle + 1); + for (i=0; iitems; i++) { + if (p == vpItem) { + return(pos + i); + } + p += laHandle->listsize; + } + pos += laHandle->items; + laHandle = laHandle->laNext; + } + return((UINT)-1); +} + +void *listarray_enum(LISTARRAY laHandle, + BOOL (*cbProc)(void *vpItem, void *vpArg), void *vpArg) { + + UINT i; + + if (cbProc == NULL) { + goto laenum_end; + } + + while(laHandle) { + UINT8 *p = (UINT8 *)(laHandle + 1); + for (i=0; iitems; i++) { + if (cbProc((void *)p, vpArg)) { + return((void *)p); + } + p += laHandle->listsize; + } + laHandle = laHandle->laNext; + } + +laenum_end: + return(NULL); +} + diff --git a/common/lstarray.h b/common/lstarray.h old mode 100755 new mode 100644 index df27448a..44e16c4c --- a/common/lstarray.h +++ b/common/lstarray.h @@ -1,31 +1,31 @@ -#ifndef NP2_LSTARRAY_H -#define NP2_LSTARRAY_H - -typedef struct _la { - UINT maxitems; - size_t listsize; - UINT items; -struct _la *laNext; -} _LISTARRAY, *LISTARRAY; - - -#ifdef __cplusplus -extern "C" { -#endif - -LISTARRAY listarray_new(size_t listsize, UINT maxitems); -void listarray_clr(LISTARRAY laHandle); -void listarray_destroy(LISTARRAY laHandle); - -UINT listarray_getitems(LISTARRAY laHandle); -void *listarray_append(LISTARRAY laHandle, const void *vpItem); -void *listarray_getitem(LISTARRAY laHandle, UINT num); -UINT listarray_getpos(LISTARRAY laHandle, void *vpItem); -void *listarray_enum(LISTARRAY laHandle, - BOOL (*cbProc)(void *vpItem, void *vpArg), void *vpArg); - -#ifdef __cplusplus -} -#endif - -#endif /* NP2_LSTARRAY_H */ +#ifndef NP2_LSTARRAY_H +#define NP2_LSTARRAY_H + +typedef struct _la { + UINT maxitems; + size_t listsize; + UINT items; +struct _la *laNext; +} _LISTARRAY, *LISTARRAY; + + +#ifdef __cplusplus +extern "C" { +#endif + +LISTARRAY listarray_new(size_t listsize, UINT maxitems); +void listarray_clr(LISTARRAY laHandle); +void listarray_destroy(LISTARRAY laHandle); + +UINT listarray_getitems(LISTARRAY laHandle); +void *listarray_append(LISTARRAY laHandle, const void *vpItem); +void *listarray_getitem(LISTARRAY laHandle, UINT num); +UINT listarray_getpos(LISTARRAY laHandle, void *vpItem); +void *listarray_enum(LISTARRAY laHandle, + BOOL (*cbProc)(void *vpItem, void *vpArg), void *vpArg); + +#ifdef __cplusplus +} +#endif + +#endif /* NP2_LSTARRAY_H */ diff --git a/common/milstr.c b/common/milstr.c old mode 100755 new mode 100644 index 1e04e5e6..8fef4934 --- a/common/milstr.c +++ b/common/milstr.c @@ -1,1009 +1,1009 @@ -#include - -// ---- ANK / UCS2 / UCS4 - -#if defined(SUPPORT_ANK) -int STRCALL milank_charsize(const char *str) { - - return((str[0] != '\0')?1:0); -} - -int STRCALL milank_cmp(const char *str, const char *cmp) { - - int s; - int c; - - do { - s = *str++; - if ((s >= 'a') && (s <= 'z')) { - s -= 0x20; - } - c = *cmp++; - if ((c >= 'a') && (c <= 'z')) { - c -= 0x20; - } - if (s != c) { - return((s > c)?1:-1); - } - } while(s); - return(0); -} - -int STRCALL milank_ncmp(const char *str, const char *cmp, unsigned int maxlen) { - - int s; - int c; - - do { - s = *str++; - if ((s >= 'a') && (s <= 'z')) { - s -= 0x20; - } - c = *cmp++; - if ((c >= 'a') && (c <= 'z')) { - c -= 0x20; - } - if (s != c) { - return((s > c)?1:-1); - } - if(maxlen) { - maxlen--; - } - } while(s && maxlen); - return(0); -} - -int STRCALL milank_memcmp(const char *str, const char *cmp) { - - int s; - int c; - - do { - c = *cmp++; - if (c == 0) { - return(0); - } - if ((c >= 'a') && (c <= 'z')) { - c -= 0x20; - } - s = *str++; - if ((s >= 'a') && (s <= 'z')) { - s -= 0x20; - } - } while(s == c); - return((s > c)?1:-1); -} - -int STRCALL milank_memncmp(const char *str, const char *cmp, unsigned int maxlen) { - - int s; - int c; - - do { - c = *cmp++; - if (c == 0) { - return(0); - } - if ((c >= 'a') && (c <= 'z')) { - c -= 0x20; - } - s = *str++; - if ((s >= 'a') && (s <= 'z')) { - s -= 0x20; - } - if(maxlen) { - maxlen--; - } - } while(s == c && maxlen); - return((s > c)?1:-1); -} - -void STRCALL milank_ncpy(char *dst, const char *src, unsigned int maxlen) { - - int i; - - if (maxlen > 0) { - maxlen--; - for (i=0; i 0) { - maxlen--; - for (i=0; i c)?1:-1); -} - -int STRCALL milsjis_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen) { - - int s; - int c; - - do { - s = (UINT8)*str++; - if ((((s ^ 0x20) - 0xa1) & 0xff) < 0x3c) { - c = (UINT8)*cmp++; - if (s != c) { - goto mscp_err; - } - if(maxlen) { - maxlen--; - } - s = (UINT8)*str++; - c = (UINT8)*cmp++; - } - else { - if (((s - 'a') & 0xff) < 26) { - s -= 0x20; - } - c = (UINT8)*cmp++; - if (((c - 'a') & 0xff) < 26) { - c -= 0x20; - } - } - if (s != c) { - goto mscp_err; - } - if(maxlen) { - maxlen--; - } - } while(s && maxlen); - return(0); - -mscp_err: - return((s > c)?1:-1); -} - -int STRCALL milsjis_memcmp(const char *str, const char *cmp) { - - int s; - int c; - - do { - c = (UINT8)*cmp++; - if ((((c ^ 0x20) - 0xa1) & 0xff) < 0x3c) { - s = (UINT8)*str++; - if (c != s) { - break; - } - c = (UINT8)*cmp++; - s = (UINT8)*str++; - } - else if (c) { - if (((c - 'a') & 0xff) < 26) { - c &= ~0x20; - } - s = (UINT8)*str++; - if (((s - 'a') & 0xff) < 26) { - s &= ~0x20; - } - } - else { - return(0); - } - } while(s == c); - return((s > c)?1:-1); -} - -int STRCALL milsjis_memncmp(const char *str, const char *cmp, unsigned int maxlen) { - - int s; - int c; - - do { - c = (UINT8)*cmp++; - if ((((c ^ 0x20) - 0xa1) & 0xff) < 0x3c) { - s = (UINT8)*str++; - if (c != s) { - break; - } - if(maxlen) { - maxlen--; - } - c = (UINT8)*cmp++; - s = (UINT8)*str++; - } - else if (c) { - if (((c - 'a') & 0xff) < 26) { - c &= ~0x20; - } - s = (UINT8)*str++; - if (((s - 'a') & 0xff) < 26) { - s &= ~0x20; - } - } - else { - return(0); - } - if(maxlen) { - maxlen--; - } - } while(s == c && maxlen); - return((s > c)?1:-1); -} - -int STRCALL milsjis_kanji1st(const char *str, unsigned int pos) { - - int ret; - - ret = 0; - while((pos >= 0) && - ((((str[pos--] ^ 0x20) - 0xa1) & 0xff) < 0x3c)) { - ret ^= 1; - } - return(ret); -} - -int STRCALL milsjis_kanji2nd(const char *str, unsigned int pos) { - - int ret; - - ret = 0; - while((pos > 0) && ((((str[--pos] ^ 0x20) - 0xa1) & 0xff) < 0x3c)) { - ret ^= 1; - } - return(ret); -} - -void STRCALL milsjis_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen) { - - int i; - - if (maxlen > 0) { - maxlen--; - for (i=0; i 0) { - maxlen--; - for (i=0; i 0) && (j > 0)) { - if (milsjis_kanji1st(dst, i-1)) { - i--; - } - } - dst[i] = '\0'; - } -} - -OEMCHAR * STRCALL milsjis_chr(const OEMCHAR *str, OEMCHAR c) { - - int s; - - if (str) { - do { - s = *str; - if (s == c) { - return((OEMCHAR *)str); - } - if ((((s ^ 0x20) - 0xa1) & 0xff) < 0x3c) { - str++; - s = *str; - } - str++; - } while(s); - } - return(NULL); -} -#endif - - -// ---- EUC - -#if defined(SUPPORT_EUC) // あれ 半角カナ忘れてるぞ? -int STRCALL mileuc_charsize(const char *str) { - - int pos; - - pos = (str[0] & 0x80)?1:0; - return((str[pos] != '\0')?(pos+1):0); -} - -int STRCALL mileuc_cmp(const OEMCHAR *str, const OEMCHAR *cmp) { - - int s; - int c; - - do { - s = (UINT8)*str++; - if (s & 0x80) { - c = (UINT8)*cmp++; - if (s != c) { - goto mscp_err; - } - s = (UINT8)*str++; - c = (UINT8)*cmp++; - } - else { - if (((s - 'a') & 0xff) < 26) { - s -= 0x20; - } - c = (UINT8)*cmp++; - if (((c - 'a') & 0xff) < 26) { - c -= 0x20; - } - } - if (s != c) { - goto mscp_err; - } - } while(s); - return(0); - -mscp_err: - return((s > c)?1:-1); -} - -int STRCALL mileuc_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen) { - - int s; - int c; - - do { - s = (UINT8)*str++; - if (s & 0x80) { - c = (UINT8)*cmp++; - if (s != c) { - goto mscp_err; - } - if(maxlen) { - maxlen--; - } - s = (UINT8)*str++; - c = (UINT8)*cmp++; - } - else { - if (((s - 'a') & 0xff) < 26) { - s -= 0x20; - } - c = (UINT8)*cmp++; - if (((c - 'a') & 0xff) < 26) { - c -= 0x20; - } - } - if (s != c) { - goto mscp_err; - } - if(maxlen) { - maxlen--; - } - } while(s && maxlen); - return(0); - -mscp_err: - return((s > c)?1:-1); -} - -int STRCALL mileuc_memcmp(const char *str, const char *cmp) { - - int s; - int c; - - do { - c = (UINT8)*cmp++; - if (c & 0x80) { - s = (UINT8)*str++; - if (c != s) { - break; - } - c = (UINT8)*cmp++; - s = (UINT8)*str++; - } - else if (c) { - if (((c - 'a') & 0xff) < 26) { - c -= 0x20; - } - s = (UINT8)*str++; - if (((s - 'a') & 0xff) < 26) { - s -= 0x20; - } - } - else { - return(0); - } - } while(s == c); - return((s > c)?1:-1); -} - -int STRCALL mileuc_memncmp(const char *str, const char *cmp, unsigned int maxlen) { - - int s; - int c; - - do { - c = (UINT8)*cmp++; - if (c & 0x80) { - s = (UINT8)*str++; - if (c != s) { - break; - } - if(maxlen) { - maxlen--; - } - c = (UINT8)*cmp++; - s = (UINT8)*str++; - } - else if (c) { - if (((c - 'a') & 0xff) < 26) { - c -= 0x20; - } - s = (UINT8)*str++; - if (((s - 'a') & 0xff) < 26) { - s -= 0x20; - } - } - else { - return(0); - } - if(maxlen) { - maxlen--; - } - } while(s == c && maxlen); - return((s > c)?1:-1); -} - -int STRCALL mileuc_kanji1st(const char *str, unsigned int pos) { - - int ret; - - ret = 0; - while((pos >= 0) && (str[pos--] & 0x80)) { - ret ^= 1; - } - return(ret); -} - -int STRCALL mileuc_kanji2nd(const char *str, unsigned int pos) { - - int ret; - - ret = 0; - while((pos > 0) && (str[--pos] & 0x80)) { - ret ^= 1; - } - return(ret); -} - -void STRCALL mileuc_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen) { - - int i; - - if (maxlen > 0) { - maxlen--; - for (i=0; i 0) { - maxlen--; - for (i=0; i 0) && (j > 0)) { - if (mileuc_kanji1st(dst, i-1)) { - i--; - } - } - dst[i] = '\0'; - } -} - -char * STRCALL mileuc_chr(const OEMCHAR *str, OEMCHAR c) { - - int s; - - if (str) { - do { - s = *str; - if (s == c) { - return((char *)str); - } - if (s & 0x80) { - str++; - s = *str; - } - str++; - } while(s); - } - return(NULL); -} -#endif - - -// ---- UTF8 - -#if defined(SUPPORT_UTF8) -int STRCALL milutf8_charsize(const char *str) { - - if (str[0] == '\0') { - return(0); - } - else if (!(str[0] & 0x80)) { - return(1); - } - else if ((str[0] & 0xe0) == 0xc0) { - if ((str[1] & 0xc0) == 0x80) { - return(2); - } - } - else if ((str[0] & 0xf0) == 0xe0) { - if (((str[1] & 0xc0) == 0x80) || - ((str[2] & 0xc0) == 0x80)) { - return(3); - } - } - return(0); -} - -int STRCALL milutf8_cmp(const OEMCHAR *str, const OEMCHAR *cmp) { - - int s; - int c; - - do { - s = (UINT8)*str++; - if (((s - 'a') & 0xff) < 26) { - s -= 0x20; - } - c = (UINT8)*cmp++; - if (((c - 'a') & 0xff) < 26) { - c -= 0x20; - } - if (s != c) { - return((s > c)?1:-1); - } - } while(s); - return(0); -} - -int STRCALL milutf8_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen) { - - int s; - int c; - - do { - s = (UINT8)*str++; - if (((s - 'a') & 0xff) < 26) { - s -= 0x20; - } - c = (UINT8)*cmp++; - if (((c - 'a') & 0xff) < 26) { - c -= 0x20; - } - if (s != c) { - return((s > c)?1:-1); - } - if(maxlen) { - maxlen--; - } - } while(s && maxlen); - return(0); -} - -int STRCALL milutf8_memcmp(const char *str, const char *cmp) { - - int s; - int c; - - do { - c = (UINT8)*cmp++; - if (c == 0) { - return(0); - } - if (((c - 'a') & 0xff) < 26) { - c -= 0x20; - } - s = (UINT8)*str++; - if (((s - 'a') & 0xff) < 26) { - s -= 0x20; - } - } while(s == c); - return((s > c)?1:-1); -} - -int STRCALL milutf8_memncmp(const char *str, const char *cmp, unsigned int maxlen) { - - int s; - int c; - - do { - c = (UINT8)*cmp++; - if (c == 0) { - return(0); - } - if (((c - 'a') & 0xff) < 26) { - c -= 0x20; - } - s = (UINT8)*str++; - if (((s - 'a') & 0xff) < 26) { - s -= 0x20; - } - if(maxlen) { - maxlen--; - } - } while(s == c && maxlen); - return((s > c)?1:-1); -} - -int STRCALL milutf8_kanji1st(const char *str, unsigned int pos) { - - return(((str[pos] & 0xc0) >= 0xc0)?1:0); -} - -int STRCALL milutf8_kanji2nd(const char *str, unsigned int pos) { - - return(((str[pos] & 0xc0) == 0x80)?1:0); -} - -void STRCALL milutf8_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen) { - - int i; - - if (maxlen > 0) { - maxlen--; - for (i=0; i 0) { - maxlen--; - for (i=0; i c)?1:-1); -} - -OEMCHAR * STRCALL milstr_nextword(const OEMCHAR *str) { - - if (str) { - while((*str > '\0') && (*str <= ' ')) { - str++; - } - } - return((OEMCHAR *)str); -} - -int STRCALL milstr_getarg(OEMCHAR *str, OEMCHAR *arg[], int maxarg) { - - int ret = 0; - OEMCHAR *p; - BOOL quot; - - while(maxarg--) { - quot = FALSE; - while((*str > '\0') && (*str <= ' ')) { - str++; - } - if (*str == '\0') { - break; - } - arg[ret++] = str; - p = str; - while(*str) { - if (*str == '\"') { - quot = !quot; - } - else if ((quot) || (*str < '\0') || (*str > ' ')) { - *p++ = *str; - } - else { - str++; - break; - } - str++; - } - *p = '\0'; - } - return(ret); -} - -long STRCALL milstr_solveHEX(const OEMCHAR *str) { - - long ret; - int i; - OEMCHAR c; - - ret = 0; - for (i=0; i<8; i++) { - c = *str++; - if ((c >= '0') && (c <= '9')) { - c -= '0'; - } - else if ((c >= 'A') && (c <= 'F')) { - c -= '7'; - } - else if ((c >= 'a') && (c <= 'f')) { - c -= 'W'; - } - else { - break; - } - ret <<= 4; - ret += (long)c; - } - return(ret); -} - -long STRCALL milstr_solveINT(const OEMCHAR *str) { - - unsigned long ret; - BOOL minus; - int c; - - ret = 0; - minus = FALSE; - c = *str; - if (c == '+') { - str++; - } - else if (c == '-') { - str++; - minus = TRUE; - } - while(1) { - c = *str++; - c -= '0'; - if ((c >= 0) && (c < 10)) { - ret *= 10; - ret += c; - } - else { - break; - } - } - if (!minus) { - return((long)ret); - } - else { - return((long)(0 - ret)); - } -} - -long long STRCALL milstr_solveINT64(const OEMCHAR *str) { - - unsigned long long ret; - BOOL minus; - int c; - - ret = 0; - minus = FALSE; - c = *str; - if (c == '+') { - str++; - } - else if (c == '-') { - str++; - minus = TRUE; - } - while(1) { - c = *str++; - c -= '0'; - if ((c >= 0) && (c < 10)) { - ret *= 10; - ret += c; - } - else { - break; - } - } - if (!minus) { - return((long long)ret); - } - else { - return((long long)(0 - ret)); - } -} - -OEMCHAR * STRCALL milstr_list(const OEMCHAR *lststr, UINT pos) { - - if (lststr) { - while(pos) { - pos--; - while(*lststr++ != '\0') { - } - } - } - return((OEMCHAR *)lststr); -} - +#include + +// ---- ANK / UCS2 / UCS4 + +#if defined(SUPPORT_ANK) +int STRCALL milank_charsize(const char *str) { + + return((str[0] != '\0')?1:0); +} + +int STRCALL milank_cmp(const char *str, const char *cmp) { + + int s; + int c; + + do { + s = *str++; + if ((s >= 'a') && (s <= 'z')) { + s -= 0x20; + } + c = *cmp++; + if ((c >= 'a') && (c <= 'z')) { + c -= 0x20; + } + if (s != c) { + return((s > c)?1:-1); + } + } while(s); + return(0); +} + +int STRCALL milank_ncmp(const char *str, const char *cmp, unsigned int maxlen) { + + int s; + int c; + + do { + s = *str++; + if ((s >= 'a') && (s <= 'z')) { + s -= 0x20; + } + c = *cmp++; + if ((c >= 'a') && (c <= 'z')) { + c -= 0x20; + } + if (s != c) { + return((s > c)?1:-1); + } + if(maxlen) { + maxlen--; + } + } while(s && maxlen); + return(0); +} + +int STRCALL milank_memcmp(const char *str, const char *cmp) { + + int s; + int c; + + do { + c = *cmp++; + if (c == 0) { + return(0); + } + if ((c >= 'a') && (c <= 'z')) { + c -= 0x20; + } + s = *str++; + if ((s >= 'a') && (s <= 'z')) { + s -= 0x20; + } + } while(s == c); + return((s > c)?1:-1); +} + +int STRCALL milank_memncmp(const char *str, const char *cmp, unsigned int maxlen) { + + int s; + int c; + + do { + c = *cmp++; + if (c == 0) { + return(0); + } + if ((c >= 'a') && (c <= 'z')) { + c -= 0x20; + } + s = *str++; + if ((s >= 'a') && (s <= 'z')) { + s -= 0x20; + } + if(maxlen) { + maxlen--; + } + } while(s == c && maxlen); + return((s > c)?1:-1); +} + +void STRCALL milank_ncpy(char *dst, const char *src, unsigned int maxlen) { + + int i; + + if (maxlen > 0) { + maxlen--; + for (i=0; i 0) { + maxlen--; + for (i=0; i c)?1:-1); +} + +int STRCALL milsjis_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen) { + + int s; + int c; + + do { + s = (UINT8)*str++; + if ((((s ^ 0x20) - 0xa1) & 0xff) < 0x3c) { + c = (UINT8)*cmp++; + if (s != c) { + goto mscp_err; + } + if(maxlen) { + maxlen--; + } + s = (UINT8)*str++; + c = (UINT8)*cmp++; + } + else { + if (((s - 'a') & 0xff) < 26) { + s -= 0x20; + } + c = (UINT8)*cmp++; + if (((c - 'a') & 0xff) < 26) { + c -= 0x20; + } + } + if (s != c) { + goto mscp_err; + } + if(maxlen) { + maxlen--; + } + } while(s && maxlen); + return(0); + +mscp_err: + return((s > c)?1:-1); +} + +int STRCALL milsjis_memcmp(const char *str, const char *cmp) { + + int s; + int c; + + do { + c = (UINT8)*cmp++; + if ((((c ^ 0x20) - 0xa1) & 0xff) < 0x3c) { + s = (UINT8)*str++; + if (c != s) { + break; + } + c = (UINT8)*cmp++; + s = (UINT8)*str++; + } + else if (c) { + if (((c - 'a') & 0xff) < 26) { + c &= ~0x20; + } + s = (UINT8)*str++; + if (((s - 'a') & 0xff) < 26) { + s &= ~0x20; + } + } + else { + return(0); + } + } while(s == c); + return((s > c)?1:-1); +} + +int STRCALL milsjis_memncmp(const char *str, const char *cmp, unsigned int maxlen) { + + int s; + int c; + + do { + c = (UINT8)*cmp++; + if ((((c ^ 0x20) - 0xa1) & 0xff) < 0x3c) { + s = (UINT8)*str++; + if (c != s) { + break; + } + if(maxlen) { + maxlen--; + } + c = (UINT8)*cmp++; + s = (UINT8)*str++; + } + else if (c) { + if (((c - 'a') & 0xff) < 26) { + c &= ~0x20; + } + s = (UINT8)*str++; + if (((s - 'a') & 0xff) < 26) { + s &= ~0x20; + } + } + else { + return(0); + } + if(maxlen) { + maxlen--; + } + } while(s == c && maxlen); + return((s > c)?1:-1); +} + +int STRCALL milsjis_kanji1st(const char *str, unsigned int pos) { + + int ret; + + ret = 0; + while((pos >= 0) && + ((((str[pos--] ^ 0x20) - 0xa1) & 0xff) < 0x3c)) { + ret ^= 1; + } + return(ret); +} + +int STRCALL milsjis_kanji2nd(const char *str, unsigned int pos) { + + int ret; + + ret = 0; + while((pos > 0) && ((((str[--pos] ^ 0x20) - 0xa1) & 0xff) < 0x3c)) { + ret ^= 1; + } + return(ret); +} + +void STRCALL milsjis_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen) { + + int i; + + if (maxlen > 0) { + maxlen--; + for (i=0; i 0) { + maxlen--; + for (i=0; i 0) && (j > 0)) { + if (milsjis_kanji1st(dst, i-1)) { + i--; + } + } + dst[i] = '\0'; + } +} + +OEMCHAR * STRCALL milsjis_chr(const OEMCHAR *str, OEMCHAR c) { + + int s; + + if (str) { + do { + s = *str; + if (s == c) { + return((OEMCHAR *)str); + } + if ((((s ^ 0x20) - 0xa1) & 0xff) < 0x3c) { + str++; + s = *str; + } + str++; + } while(s); + } + return(NULL); +} +#endif + + +// ---- EUC + +#if defined(SUPPORT_EUC) // あれ 半角カナ忘れてるぞ? +int STRCALL mileuc_charsize(const char *str) { + + int pos; + + pos = (str[0] & 0x80)?1:0; + return((str[pos] != '\0')?(pos+1):0); +} + +int STRCALL mileuc_cmp(const OEMCHAR *str, const OEMCHAR *cmp) { + + int s; + int c; + + do { + s = (UINT8)*str++; + if (s & 0x80) { + c = (UINT8)*cmp++; + if (s != c) { + goto mscp_err; + } + s = (UINT8)*str++; + c = (UINT8)*cmp++; + } + else { + if (((s - 'a') & 0xff) < 26) { + s -= 0x20; + } + c = (UINT8)*cmp++; + if (((c - 'a') & 0xff) < 26) { + c -= 0x20; + } + } + if (s != c) { + goto mscp_err; + } + } while(s); + return(0); + +mscp_err: + return((s > c)?1:-1); +} + +int STRCALL mileuc_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen) { + + int s; + int c; + + do { + s = (UINT8)*str++; + if (s & 0x80) { + c = (UINT8)*cmp++; + if (s != c) { + goto mscp_err; + } + if(maxlen) { + maxlen--; + } + s = (UINT8)*str++; + c = (UINT8)*cmp++; + } + else { + if (((s - 'a') & 0xff) < 26) { + s -= 0x20; + } + c = (UINT8)*cmp++; + if (((c - 'a') & 0xff) < 26) { + c -= 0x20; + } + } + if (s != c) { + goto mscp_err; + } + if(maxlen) { + maxlen--; + } + } while(s && maxlen); + return(0); + +mscp_err: + return((s > c)?1:-1); +} + +int STRCALL mileuc_memcmp(const char *str, const char *cmp) { + + int s; + int c; + + do { + c = (UINT8)*cmp++; + if (c & 0x80) { + s = (UINT8)*str++; + if (c != s) { + break; + } + c = (UINT8)*cmp++; + s = (UINT8)*str++; + } + else if (c) { + if (((c - 'a') & 0xff) < 26) { + c -= 0x20; + } + s = (UINT8)*str++; + if (((s - 'a') & 0xff) < 26) { + s -= 0x20; + } + } + else { + return(0); + } + } while(s == c); + return((s > c)?1:-1); +} + +int STRCALL mileuc_memncmp(const char *str, const char *cmp, unsigned int maxlen) { + + int s; + int c; + + do { + c = (UINT8)*cmp++; + if (c & 0x80) { + s = (UINT8)*str++; + if (c != s) { + break; + } + if(maxlen) { + maxlen--; + } + c = (UINT8)*cmp++; + s = (UINT8)*str++; + } + else if (c) { + if (((c - 'a') & 0xff) < 26) { + c -= 0x20; + } + s = (UINT8)*str++; + if (((s - 'a') & 0xff) < 26) { + s -= 0x20; + } + } + else { + return(0); + } + if(maxlen) { + maxlen--; + } + } while(s == c && maxlen); + return((s > c)?1:-1); +} + +int STRCALL mileuc_kanji1st(const char *str, unsigned int pos) { + + int ret; + + ret = 0; + while((pos >= 0) && (str[pos--] & 0x80)) { + ret ^= 1; + } + return(ret); +} + +int STRCALL mileuc_kanji2nd(const char *str, unsigned int pos) { + + int ret; + + ret = 0; + while((pos > 0) && (str[--pos] & 0x80)) { + ret ^= 1; + } + return(ret); +} + +void STRCALL mileuc_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen) { + + int i; + + if (maxlen > 0) { + maxlen--; + for (i=0; i 0) { + maxlen--; + for (i=0; i 0) && (j > 0)) { + if (mileuc_kanji1st(dst, i-1)) { + i--; + } + } + dst[i] = '\0'; + } +} + +char * STRCALL mileuc_chr(const OEMCHAR *str, OEMCHAR c) { + + int s; + + if (str) { + do { + s = *str; + if (s == c) { + return((char *)str); + } + if (s & 0x80) { + str++; + s = *str; + } + str++; + } while(s); + } + return(NULL); +} +#endif + + +// ---- UTF8 + +#if defined(SUPPORT_UTF8) +int STRCALL milutf8_charsize(const char *str) { + + if (str[0] == '\0') { + return(0); + } + else if (!(str[0] & 0x80)) { + return(1); + } + else if ((str[0] & 0xe0) == 0xc0) { + if ((str[1] & 0xc0) == 0x80) { + return(2); + } + } + else if ((str[0] & 0xf0) == 0xe0) { + if (((str[1] & 0xc0) == 0x80) || + ((str[2] & 0xc0) == 0x80)) { + return(3); + } + } + return(0); +} + +int STRCALL milutf8_cmp(const OEMCHAR *str, const OEMCHAR *cmp) { + + int s; + int c; + + do { + s = (UINT8)*str++; + if (((s - 'a') & 0xff) < 26) { + s -= 0x20; + } + c = (UINT8)*cmp++; + if (((c - 'a') & 0xff) < 26) { + c -= 0x20; + } + if (s != c) { + return((s > c)?1:-1); + } + } while(s); + return(0); +} + +int STRCALL milutf8_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen) { + + int s; + int c; + + do { + s = (UINT8)*str++; + if (((s - 'a') & 0xff) < 26) { + s -= 0x20; + } + c = (UINT8)*cmp++; + if (((c - 'a') & 0xff) < 26) { + c -= 0x20; + } + if (s != c) { + return((s > c)?1:-1); + } + if(maxlen) { + maxlen--; + } + } while(s && maxlen); + return(0); +} + +int STRCALL milutf8_memcmp(const char *str, const char *cmp) { + + int s; + int c; + + do { + c = (UINT8)*cmp++; + if (c == 0) { + return(0); + } + if (((c - 'a') & 0xff) < 26) { + c -= 0x20; + } + s = (UINT8)*str++; + if (((s - 'a') & 0xff) < 26) { + s -= 0x20; + } + } while(s == c); + return((s > c)?1:-1); +} + +int STRCALL milutf8_memncmp(const char *str, const char *cmp, unsigned int maxlen) { + + int s; + int c; + + do { + c = (UINT8)*cmp++; + if (c == 0) { + return(0); + } + if (((c - 'a') & 0xff) < 26) { + c -= 0x20; + } + s = (UINT8)*str++; + if (((s - 'a') & 0xff) < 26) { + s -= 0x20; + } + if(maxlen) { + maxlen--; + } + } while(s == c && maxlen); + return((s > c)?1:-1); +} + +int STRCALL milutf8_kanji1st(const char *str, unsigned int pos) { + + return(((str[pos] & 0xc0) >= 0xc0)?1:0); +} + +int STRCALL milutf8_kanji2nd(const char *str, unsigned int pos) { + + return(((str[pos] & 0xc0) == 0x80)?1:0); +} + +void STRCALL milutf8_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen) { + + int i; + + if (maxlen > 0) { + maxlen--; + for (i=0; i 0) { + maxlen--; + for (i=0; i c)?1:-1); +} + +OEMCHAR * STRCALL milstr_nextword(const OEMCHAR *str) { + + if (str) { + while((*str > '\0') && (*str <= ' ')) { + str++; + } + } + return((OEMCHAR *)str); +} + +int STRCALL milstr_getarg(OEMCHAR *str, OEMCHAR *arg[], int maxarg) { + + int ret = 0; + OEMCHAR *p; + BOOL quot; + + while(maxarg--) { + quot = FALSE; + while((*str > '\0') && (*str <= ' ')) { + str++; + } + if (*str == '\0') { + break; + } + arg[ret++] = str; + p = str; + while(*str) { + if (*str == '\"') { + quot = !quot; + } + else if ((quot) || (*str < '\0') || (*str > ' ')) { + *p++ = *str; + } + else { + str++; + break; + } + str++; + } + *p = '\0'; + } + return(ret); +} + +long STRCALL milstr_solveHEX(const OEMCHAR *str) { + + long ret; + int i; + OEMCHAR c; + + ret = 0; + for (i=0; i<8; i++) { + c = *str++; + if ((c >= '0') && (c <= '9')) { + c -= '0'; + } + else if ((c >= 'A') && (c <= 'F')) { + c -= '7'; + } + else if ((c >= 'a') && (c <= 'f')) { + c -= 'W'; + } + else { + break; + } + ret <<= 4; + ret += (long)c; + } + return(ret); +} + +long STRCALL milstr_solveINT(const OEMCHAR *str) { + + unsigned long ret; + BOOL minus; + int c; + + ret = 0; + minus = FALSE; + c = *str; + if (c == '+') { + str++; + } + else if (c == '-') { + str++; + minus = TRUE; + } + while(1) { + c = *str++; + c -= '0'; + if ((c >= 0) && (c < 10)) { + ret *= 10; + ret += c; + } + else { + break; + } + } + if (!minus) { + return((long)ret); + } + else { + return((long)(0 - ret)); + } +} + +long long STRCALL milstr_solveINT64(const OEMCHAR *str) { + + unsigned long long ret; + BOOL minus; + int c; + + ret = 0; + minus = FALSE; + c = *str; + if (c == '+') { + str++; + } + else if (c == '-') { + str++; + minus = TRUE; + } + while(1) { + c = *str++; + c -= '0'; + if ((c >= 0) && (c < 10)) { + ret *= 10; + ret += c; + } + else { + break; + } + } + if (!minus) { + return((long long)ret); + } + else { + return((long long)(0 - ret)); + } +} + +OEMCHAR * STRCALL milstr_list(const OEMCHAR *lststr, UINT pos) { + + if (lststr) { + while(pos) { + pos--; + while(*lststr++ != '\0') { + } + } + } + return((OEMCHAR *)lststr); +} + diff --git a/common/milstr.h b/common/milstr.h old mode 100755 new mode 100644 index 3c94d38b..7027316b --- a/common/milstr.h +++ b/common/milstr.h @@ -1,159 +1,159 @@ -#ifndef _MILSTR_H_ -#define _MILSTR_H_ - -#ifndef STRCALL -#define STRCALL -#endif - -#ifdef MILSTR_TEST -#include "compiler_base.h" -#else -#include "compiler.h" -#endif - -// Must use milstr macros only. - -#ifdef __cplusplus -extern "C" { -#endif - -// 1文字分のサイズを取得 -int STRCALL milank_charsize(const OEMCHAR *str); -int STRCALL milsjis_charsize(const char *str); -int STRCALL mileuc_charsize(const char *str); -int STRCALL milutf8_charsize(const char *str); - -// 大文字小文字を同一視して比較 -// ret 0:一致 -int STRCALL milank_cmp(const char *str, const char *cmp); -int STRCALL milsjis_cmp(const OEMCHAR *str, const OEMCHAR *cmp); -int STRCALL mileuc_cmp(const OEMCHAR *str, const OEMCHAR *cmp); -int STRCALL milutf8_cmp(const OEMCHAR *str, const OEMCHAR *cmp); - -// 大文字小文字を同一視してmaxlen分比較 -// ret 0:一致 -int STRCALL milank_ncmp(const char *str, const char *cmp, unsigned int maxlen); -int STRCALL milsjis_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen); -int STRCALL mileuc_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen); -int STRCALL milutf8_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen); - -// 大文字小文字を 同一視してcmpのヌルまで比較 -// ret 0:一致 -int STRCALL milank_memcmp(const char *str, const char *cmp); -int STRCALL milsjis_memcmp(const char *str, const char *cmp); -int STRCALL mileuc_memcmp(const char *str, const char *cmp); -int STRCALL milutf8_memcmp(const char *str, const char *cmp); - -// 大文字小文字を 同一視してmaxlen分またはcmpのヌルまで比較 -// ret 0:一致 -int STRCALL milank_memncmp(const char *str, const char *cmp, unsigned int maxlen); -int STRCALL milsjis_memncmp(const char *str, const char *cmp, unsigned int maxlen); -int STRCALL mileuc_memncmp(const char *str, const char *cmp, unsigned int maxlen); -int STRCALL milutf8_memncmp(const char *str, const char *cmp, unsigned int maxlen); - -// str[pos]が漢字1バイト目かどうか… -int STRCALL milsjis_kanji1st(const char *str, unsigned int pos); -int STRCALL mileuc_kanji1st(const char *str, unsigned int pos); -int STRCALL milutf8_kanji1st(const char *str, unsigned int pos); - -// str[pos]が漢字2バイト目かどうか… -int STRCALL milsjis_kanji2nd(const char *str, unsigned int pos); -int STRCALL mileuc_kanji2nd(const char *str, unsigned int pos); -int STRCALL milutf8_kanji2nd(const char *str, unsigned int pos); - -// maxlen分だけ文字列をコピー -void STRCALL milank_ncpy(char *dst, const char *src, unsigned int maxlen); -void STRCALL milsjis_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); -void STRCALL mileuc_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); -void STRCALL milutf8_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); - -// maxlen分だけ文字列をキャット -void STRCALL milank_ncat(char *dst, const char *src, unsigned int maxlen); -void STRCALL milsjis_ncat(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); -void STRCALL mileuc_ncat(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); -void STRCALL milutf8_ncat(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); - -// 文字を検索 -OEMCHAR * STRCALL milank_chr(const char *str, char c); -char * STRCALL milsjis_chr(const OEMCHAR *str, OEMCHAR c); -char * STRCALL mileuc_chr(const OEMCHAR *str, OEMCHAR c); -char * STRCALL milutf8_chr(const OEMCHAR *str, OEMCHAR c); - - -// 0~9, A~Z のみを大文字小文字を同一視して比較 -// ret 0:一致 -int STRCALL milstr_extendcmp(const OEMCHAR *str, const OEMCHAR *cmp); - -// 次の語を取得 -OEMCHAR * STRCALL milstr_nextword(const OEMCHAR *str); - -// 文字列からARGの取得 -int STRCALL milstr_getarg(OEMCHAR *str, OEMCHAR *arg[], int maxarg); - -// HEX2INT -long STRCALL milstr_solveHEX(const OEMCHAR *str); - -// STR2INT -long STRCALL milstr_solveINT(const OEMCHAR *str); - -// STR2INT64 -long long STRCALL milstr_solveINT64(const OEMCHAR* str); - -// STRLIST -OEMCHAR * STRCALL milstr_list(const OEMCHAR *lststr, UINT pos); - -#ifdef __cplusplus -} -#endif - - -// ---- macros - -#if defined(OSLANG_SJIS) -#define milstr_charsize(s) milsjis_charsize(s) -#define milstr_cmp(s, c) milsjis_cmp(s, c) -#define milstr_ncmp(s, c, n) milsjis_ncmp(s, c, n) -#define milstr_memcmp(s, c) milsjis_memcmp(s, c) -#define milstr_memncmp(s, c, n) milsjis_memncmp(s, c, n) -#define milstr_kanji1st(s, p) milsjis_kanji1st(s, p) -#define milstr_kanji2nd(s, p) milsjis_kanji2nd(s, p) -#define milstr_ncpy(d, s, l) milsjis_ncpy(d, s, l) -#define milstr_ncat(d, s, l) milsjis_ncat(d, s, l) -#define milstr_chr(s, c) milsjis_chr(s, c) -#elif defined(OSLANG_EUC) -#define milstr_charsize(s) mileuc_charsize(s) -#define milstr_cmp(s, c) mileuc_cmp(s, c) -#define milstr_ncmp(s, c, n) mileuc_ncmp(s, c, n) -#define milstr_memcmp(s, c) mileuc_memcmp(s, c) -#define milstr_memncmp(s, c, n) mileuc_memncmp(s, c, n) -#define milstr_kanji1st(s, p) mileuc_kanji1st(s, p) -#define milstr_kanji2nd(s, p) mileuc_kanji2nd(s, p) -#define milstr_ncpy(d, s, l) mileuc_ncpy(d, s, l) -#define milstr_ncat(d, s, l) mileuc_ncat(d, s, l) -#define milstr_chr(s, c) mileuc_chr(s, c) -#elif defined(OSLANG_UTF8) -#define milstr_charsize(s) milutf8_charsize(s) -#define milstr_cmp(s, c) milutf8_cmp(s, c) -#define milstr_ncmp(s, c, n) milutf8_ncmp(s, c, n) -#define milstr_memcmp(s, c) milutf8_memcmp(s, c) -#define milstr_memncmp(s, c, n) milutf8_memncmp(s, c, n) -#define milstr_kanji1st(s, p) milutf8_kanji1st(s, p) -#define milstr_kanji2nd(s, p) milutf8_kanji2nd(s, p) -#define milstr_ncpy(d, s, l) milutf8_ncpy(d, s, l) -#define milstr_ncat(d, s, l) milutf8_ncat(d, s, l) -#define milstr_chr(s, c) milutf8_chr(s, c) -#else -#define milstr_charsize(s) milank_charsize(s) -#define milstr_cmp(s, c) milank_cmp(s, c) -#define milstr_ncmp(s, c, n) milank_ncmp(s, c, n) -#define milstr_memcmp(s, c) milank_memcmp(s, c) -#define milstr_memncmp(s, c, n) milank_memncmp(s, c, n) -#define milstr_kanji1st(s, p) (0) -#define milstr_kanji2nd(s, p) (0) -#define milstr_ncpy(d, s, l) milank_ncpy(d, s, l) -#define milstr_ncat(d, s, l) milank_ncat(d, s, l) -#define milstr_chr(s, c) milank_chr(s, c) -#endif - -#endif // _MILSTR_H_ - +#ifndef _MILSTR_H_ +#define _MILSTR_H_ + +#ifndef STRCALL +#define STRCALL +#endif + +#ifdef MILSTR_TEST +#include "compiler_base.h" +#else +#include "compiler.h" +#endif + +// Must use milstr macros only. + +#ifdef __cplusplus +extern "C" { +#endif + +// 1文字分のサイズを取得 +int STRCALL milank_charsize(const OEMCHAR *str); +int STRCALL milsjis_charsize(const char *str); +int STRCALL mileuc_charsize(const char *str); +int STRCALL milutf8_charsize(const char *str); + +// 大文字小文字を同一視して比較 +// ret 0:一致 +int STRCALL milank_cmp(const char *str, const char *cmp); +int STRCALL milsjis_cmp(const OEMCHAR *str, const OEMCHAR *cmp); +int STRCALL mileuc_cmp(const OEMCHAR *str, const OEMCHAR *cmp); +int STRCALL milutf8_cmp(const OEMCHAR *str, const OEMCHAR *cmp); + +// 大文字小文字を同一視してmaxlen分比較 +// ret 0:一致 +int STRCALL milank_ncmp(const char *str, const char *cmp, unsigned int maxlen); +int STRCALL milsjis_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen); +int STRCALL mileuc_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen); +int STRCALL milutf8_ncmp(const OEMCHAR *str, const OEMCHAR *cmp, unsigned int maxlen); + +// 大文字小文字を 同一視してcmpのヌルまで比較 +// ret 0:一致 +int STRCALL milank_memcmp(const char *str, const char *cmp); +int STRCALL milsjis_memcmp(const char *str, const char *cmp); +int STRCALL mileuc_memcmp(const char *str, const char *cmp); +int STRCALL milutf8_memcmp(const char *str, const char *cmp); + +// 大文字小文字を 同一視してmaxlen分またはcmpのヌルまで比較 +// ret 0:一致 +int STRCALL milank_memncmp(const char *str, const char *cmp, unsigned int maxlen); +int STRCALL milsjis_memncmp(const char *str, const char *cmp, unsigned int maxlen); +int STRCALL mileuc_memncmp(const char *str, const char *cmp, unsigned int maxlen); +int STRCALL milutf8_memncmp(const char *str, const char *cmp, unsigned int maxlen); + +// str[pos]が漢字1バイト目かどうか… +int STRCALL milsjis_kanji1st(const char *str, unsigned int pos); +int STRCALL mileuc_kanji1st(const char *str, unsigned int pos); +int STRCALL milutf8_kanji1st(const char *str, unsigned int pos); + +// str[pos]が漢字2バイト目かどうか… +int STRCALL milsjis_kanji2nd(const char *str, unsigned int pos); +int STRCALL mileuc_kanji2nd(const char *str, unsigned int pos); +int STRCALL milutf8_kanji2nd(const char *str, unsigned int pos); + +// maxlen分だけ文字列をコピー +void STRCALL milank_ncpy(char *dst, const char *src, unsigned int maxlen); +void STRCALL milsjis_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); +void STRCALL mileuc_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); +void STRCALL milutf8_ncpy(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); + +// maxlen分だけ文字列をキャット +void STRCALL milank_ncat(char *dst, const char *src, unsigned int maxlen); +void STRCALL milsjis_ncat(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); +void STRCALL mileuc_ncat(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); +void STRCALL milutf8_ncat(OEMCHAR *dst, const OEMCHAR *src, unsigned int maxlen); + +// 文字を検索 +OEMCHAR * STRCALL milank_chr(const char *str, char c); +char * STRCALL milsjis_chr(const OEMCHAR *str, OEMCHAR c); +char * STRCALL mileuc_chr(const OEMCHAR *str, OEMCHAR c); +char * STRCALL milutf8_chr(const OEMCHAR *str, OEMCHAR c); + + +// 0~9, A~Z のみを大文字小文字を同一視して比較 +// ret 0:一致 +int STRCALL milstr_extendcmp(const OEMCHAR *str, const OEMCHAR *cmp); + +// 次の語を取得 +OEMCHAR * STRCALL milstr_nextword(const OEMCHAR *str); + +// 文字列からARGの取得 +int STRCALL milstr_getarg(OEMCHAR *str, OEMCHAR *arg[], int maxarg); + +// HEX2INT +long STRCALL milstr_solveHEX(const OEMCHAR *str); + +// STR2INT +long STRCALL milstr_solveINT(const OEMCHAR *str); + +// STR2INT64 +long long STRCALL milstr_solveINT64(const OEMCHAR* str); + +// STRLIST +OEMCHAR * STRCALL milstr_list(const OEMCHAR *lststr, UINT pos); + +#ifdef __cplusplus +} +#endif + + +// ---- macros + +#if defined(OSLANG_SJIS) +#define milstr_charsize(s) milsjis_charsize(s) +#define milstr_cmp(s, c) milsjis_cmp(s, c) +#define milstr_ncmp(s, c, n) milsjis_ncmp(s, c, n) +#define milstr_memcmp(s, c) milsjis_memcmp(s, c) +#define milstr_memncmp(s, c, n) milsjis_memncmp(s, c, n) +#define milstr_kanji1st(s, p) milsjis_kanji1st(s, p) +#define milstr_kanji2nd(s, p) milsjis_kanji2nd(s, p) +#define milstr_ncpy(d, s, l) milsjis_ncpy(d, s, l) +#define milstr_ncat(d, s, l) milsjis_ncat(d, s, l) +#define milstr_chr(s, c) milsjis_chr(s, c) +#elif defined(OSLANG_EUC) +#define milstr_charsize(s) mileuc_charsize(s) +#define milstr_cmp(s, c) mileuc_cmp(s, c) +#define milstr_ncmp(s, c, n) mileuc_ncmp(s, c, n) +#define milstr_memcmp(s, c) mileuc_memcmp(s, c) +#define milstr_memncmp(s, c, n) mileuc_memncmp(s, c, n) +#define milstr_kanji1st(s, p) mileuc_kanji1st(s, p) +#define milstr_kanji2nd(s, p) mileuc_kanji2nd(s, p) +#define milstr_ncpy(d, s, l) mileuc_ncpy(d, s, l) +#define milstr_ncat(d, s, l) mileuc_ncat(d, s, l) +#define milstr_chr(s, c) mileuc_chr(s, c) +#elif defined(OSLANG_UTF8) +#define milstr_charsize(s) milutf8_charsize(s) +#define milstr_cmp(s, c) milutf8_cmp(s, c) +#define milstr_ncmp(s, c, n) milutf8_ncmp(s, c, n) +#define milstr_memcmp(s, c) milutf8_memcmp(s, c) +#define milstr_memncmp(s, c, n) milutf8_memncmp(s, c, n) +#define milstr_kanji1st(s, p) milutf8_kanji1st(s, p) +#define milstr_kanji2nd(s, p) milutf8_kanji2nd(s, p) +#define milstr_ncpy(d, s, l) milutf8_ncpy(d, s, l) +#define milstr_ncat(d, s, l) milutf8_ncat(d, s, l) +#define milstr_chr(s, c) milutf8_chr(s, c) +#else +#define milstr_charsize(s) milank_charsize(s) +#define milstr_cmp(s, c) milank_cmp(s, c) +#define milstr_ncmp(s, c, n) milank_ncmp(s, c, n) +#define milstr_memcmp(s, c) milank_memcmp(s, c) +#define milstr_memncmp(s, c, n) milank_memncmp(s, c, n) +#define milstr_kanji1st(s, p) (0) +#define milstr_kanji2nd(s, p) (0) +#define milstr_ncpy(d, s, l) milank_ncpy(d, s, l) +#define milstr_ncat(d, s, l) milank_ncat(d, s, l) +#define milstr_chr(s, c) milank_chr(s, c) +#endif + +#endif // _MILSTR_H_ + diff --git a/common/mimpidef.c b/common/mimpidef.c old mode 100755 new mode 100644 index 1b65f63a..b62c1163 --- a/common/mimpidef.c +++ b/common/mimpidef.c @@ -1,136 +1,136 @@ -#include -#include -#include -#include - - -static const OEMCHAR str_la[] = OEMTEXT("LA"); -static const OEMCHAR str_pcm[] = OEMTEXT("PCM"); -static const OEMCHAR str_gs[] = OEMTEXT("GS"); -static const OEMCHAR str_rhythm[] = OEMTEXT("RHYTHM"); - - -static OEMCHAR *cutdelimit(const OEMCHAR *buf) { - - while((buf[0] > 0) && (buf[0] <= ' ')) { - buf++; - } - return((OEMCHAR *)buf); -} - -static BRESULT getvalue(OEMCHAR **buf, int *value) { - - OEMCHAR *p; - int val; - BRESULT ret; - OEMCHAR c; - - p = cutdelimit(*buf); - val = 0; - ret = FAILURE; - while(1) { - c = *p; - if ((c < '0') || (c > '9')) { - break; - } - p++; - val *= 10; - val += c - '0'; - ret = SUCCESS; - } - if (ret == SUCCESS) { - *buf = p; - *value = val; - } - return(ret); -} - -static void analyze(MIMPIDEF *def, OEMCHAR *buf) { - - int num; - int mod; - int bank; - int tone; - - buf = cutdelimit(buf); - if (buf[0] == '@') { - buf++; - if ((getvalue(&buf, &num) != SUCCESS) || (num < 1) || (num > 16)) { - return; - } - num--; - buf = cutdelimit(buf); - if (!milstr_memcmp(buf, str_la)) { - def->ch[num] = MIMPI_LA; - } - else if (!milstr_memcmp(buf, str_pcm)) { - def->ch[num] = MIMPI_PCM; - } - else if (!milstr_memcmp(buf, str_gs)) { - def->ch[num] = MIMPI_GS; - } - else if (!milstr_memcmp(buf, str_rhythm)) { - def->ch[num] = MIMPI_RHYTHM; - } - } - else { - if ((getvalue(&buf, &mod) != SUCCESS) || - (mod < 0) || (mod >= MIMPI_RHYTHM)) { - return; - } - if ((getvalue(&buf, &num) != SUCCESS) || (num < 1) || (num > 128)) { - return; - } - if ((getvalue(&buf, &tone) != SUCCESS) || - (tone < 1) || (tone > 128)) { - return; - } - num--; - tone--; - if (buf[0] == ':') { - buf++; - bank = tone; - if ((getvalue(&buf, &tone) != SUCCESS) || - (tone < 1) || (tone > 128)) { - return; - } - tone--; - def->bank[mod][num] = (UINT8)bank; - } - def->map[mod][num] = (UINT8)tone; - } -} - -BRESULT mimpidef_load(MIMPIDEF *def, const OEMCHAR *filename) { - - UINT8 b; - TEXTFILEH fh; - OEMCHAR buf[256]; - - if (def == NULL) { - goto mdld_err; - } - ZeroMemory(def->ch, sizeof(def->ch)); - def->ch[9] = MIMPI_RHYTHM; - for (b=0; b<128; b++) { - def->map[0][b] = b; - def->map[1][b] = b; - def->map[2][b] = b; - } - if ((filename == NULL) || (!filename[0])) { - goto mdld_err; - } - fh = textfile_open(filename, 512); - if (fh == NULL) { - goto mdld_err; - } - while(textfile_read(fh, buf, NELEMENTS(buf)) == SUCCESS) { - analyze(def, buf); - } - textfile_close(fh); - return(SUCCESS); - -mdld_err: - return(FAILURE); -} - +#include +#include +#include +#include + + +static const OEMCHAR str_la[] = OEMTEXT("LA"); +static const OEMCHAR str_pcm[] = OEMTEXT("PCM"); +static const OEMCHAR str_gs[] = OEMTEXT("GS"); +static const OEMCHAR str_rhythm[] = OEMTEXT("RHYTHM"); + + +static OEMCHAR *cutdelimit(const OEMCHAR *buf) { + + while((buf[0] > 0) && (buf[0] <= ' ')) { + buf++; + } + return((OEMCHAR *)buf); +} + +static BRESULT getvalue(OEMCHAR **buf, int *value) { + + OEMCHAR *p; + int val; + BRESULT ret; + OEMCHAR c; + + p = cutdelimit(*buf); + val = 0; + ret = FAILURE; + while(1) { + c = *p; + if ((c < '0') || (c > '9')) { + break; + } + p++; + val *= 10; + val += c - '0'; + ret = SUCCESS; + } + if (ret == SUCCESS) { + *buf = p; + *value = val; + } + return(ret); +} + +static void analyze(MIMPIDEF *def, OEMCHAR *buf) { + + int num; + int mod; + int bank; + int tone; + + buf = cutdelimit(buf); + if (buf[0] == '@') { + buf++; + if ((getvalue(&buf, &num) != SUCCESS) || (num < 1) || (num > 16)) { + return; + } + num--; + buf = cutdelimit(buf); + if (!milstr_memcmp(buf, str_la)) { + def->ch[num] = MIMPI_LA; + } + else if (!milstr_memcmp(buf, str_pcm)) { + def->ch[num] = MIMPI_PCM; + } + else if (!milstr_memcmp(buf, str_gs)) { + def->ch[num] = MIMPI_GS; + } + else if (!milstr_memcmp(buf, str_rhythm)) { + def->ch[num] = MIMPI_RHYTHM; + } + } + else { + if ((getvalue(&buf, &mod) != SUCCESS) || + (mod < 0) || (mod >= MIMPI_RHYTHM)) { + return; + } + if ((getvalue(&buf, &num) != SUCCESS) || (num < 1) || (num > 128)) { + return; + } + if ((getvalue(&buf, &tone) != SUCCESS) || + (tone < 1) || (tone > 128)) { + return; + } + num--; + tone--; + if (buf[0] == ':') { + buf++; + bank = tone; + if ((getvalue(&buf, &tone) != SUCCESS) || + (tone < 1) || (tone > 128)) { + return; + } + tone--; + def->bank[mod][num] = (UINT8)bank; + } + def->map[mod][num] = (UINT8)tone; + } +} + +BRESULT mimpidef_load(MIMPIDEF *def, const OEMCHAR *filename) { + + UINT8 b; + TEXTFILEH fh; + OEMCHAR buf[256]; + + if (def == NULL) { + goto mdld_err; + } + ZeroMemory(def->ch, sizeof(def->ch)); + def->ch[9] = MIMPI_RHYTHM; + for (b=0; b<128; b++) { + def->map[0][b] = b; + def->map[1][b] = b; + def->map[2][b] = b; + } + if ((filename == NULL) || (!filename[0])) { + goto mdld_err; + } + fh = textfile_open(filename, 512); + if (fh == NULL) { + goto mdld_err; + } + while(textfile_read(fh, buf, NELEMENTS(buf)) == SUCCESS) { + analyze(def, buf); + } + textfile_close(fh); + return(SUCCESS); + +mdld_err: + return(FAILURE); +} + diff --git a/common/mimpidef.h b/common/mimpidef.h old mode 100755 new mode 100644 index f5ea4890..fa5c396e --- a/common/mimpidef.h +++ b/common/mimpidef.h @@ -1,25 +1,25 @@ - -enum { - MIMPI_LA = 0, - MIMPI_PCM, - MIMPI_GS, - MIMPI_RHYTHM -}; - -typedef struct { - UINT8 ch[16]; - UINT8 map[3][128]; - UINT8 bank[3][128]; -} MIMPIDEF; - - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT mimpidef_load(MIMPIDEF *def, const OEMCHAR *filename); - -#ifdef __cplusplus -} -#endif - + +enum { + MIMPI_LA = 0, + MIMPI_PCM, + MIMPI_GS, + MIMPI_RHYTHM +}; + +typedef struct { + UINT8 ch[16]; + UINT8 map[3][128]; + UINT8 bank[3][128]; +} MIMPIDEF; + + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT mimpidef_load(MIMPIDEF *def, const OEMCHAR *filename); + +#ifdef __cplusplus +} +#endif + diff --git a/common/parts.c b/common/parts.c old mode 100755 new mode 100644 index b8234ca8..d60917f9 --- a/common/parts.c +++ b/common/parts.c @@ -1,105 +1,105 @@ -#include -#include - - -static SINT32 randseed = 1; - - -void PARTSCALL rand_setseed(SINT32 seed) { - - randseed = seed; -} - -SINT32 PARTSCALL rand_get(void) { - - randseed = (randseed * 0x343fd) + 0x269ec3; - return(randseed >> 16); -} - -UINT8 PARTSCALL AdjustAfterMultiply(UINT8 value) { - - return((UINT8)(((value / 10) << 4) + (value % 10))); -} - -UINT8 PARTSCALL AdjustBeforeDivision(UINT8 value) { - - return((UINT8)(((value >> 4) * 10) + (value & 0xf))); -} - -UINT PARTSCALL sjis2jis(UINT sjis) { - - UINT ret; - - ret = sjis & 0xff; - ret -= (ret >> 7); - ret += 0x62; - if (ret < 256) { - ret = (ret - 0xa2) & 0x1ff; - } - ret += 0x1f21; - ret += (sjis & 0x3f00) << 1; - return(ret); -} - -UINT PARTSCALL jis2sjis(UINT jis) { - - UINT high; - UINT low; - - low = jis & 0x7f; - high = (jis >> 8) & 0x7f; - low += ((high & 1) - 1) & 0x5e; - if (low >= 0x60) { - low++; - } - high += 0x121; - low += 0x1f; - high >>= 1; - high ^= 0x20; - return((high << 8) | low); -} - -void PARTSCALL satuation_s16(SINT16 *dst, const SINT32 *src, UINT size) { - - SINT32 data; - - size >>= 1; - while(size--) { - data = *src++; - if (data > 32767) { - data = 32767; - } - else if (data < -32768) { - data = -32768; - } - *dst++ = (SINT16)data; - } -} - -void PARTSCALL satuation_s16x(SINT16 *dst, const SINT32 *src, UINT size) { - - SINT32 data; - - size >>= 2; - while(size--) { - data = src[0]; - if (data > 32767) { - data = 32767; - } - else if (data < -32768) { - data = -32768; - } - dst[1] = (SINT16)data; - data = src[1]; - if (data > 32767) { - data = 32767; - } - else if (data < -32768) { - data = -32768; - } - dst[0] = (SINT16)data; - src += 2; - dst += 2; - } -} - +#include +#include + + +static SINT32 randseed = 1; + + +void PARTSCALL rand_setseed(SINT32 seed) { + + randseed = seed; +} + +SINT32 PARTSCALL rand_get(void) { + + randseed = (randseed * 0x343fd) + 0x269ec3; + return(randseed >> 16); +} + +UINT8 PARTSCALL AdjustAfterMultiply(UINT8 value) { + + return((UINT8)(((value / 10) << 4) + (value % 10))); +} + +UINT8 PARTSCALL AdjustBeforeDivision(UINT8 value) { + + return((UINT8)(((value >> 4) * 10) + (value & 0xf))); +} + +UINT PARTSCALL sjis2jis(UINT sjis) { + + UINT ret; + + ret = sjis & 0xff; + ret -= (ret >> 7); + ret += 0x62; + if (ret < 256) { + ret = (ret - 0xa2) & 0x1ff; + } + ret += 0x1f21; + ret += (sjis & 0x3f00) << 1; + return(ret); +} + +UINT PARTSCALL jis2sjis(UINT jis) { + + UINT high; + UINT low; + + low = jis & 0x7f; + high = (jis >> 8) & 0x7f; + low += ((high & 1) - 1) & 0x5e; + if (low >= 0x60) { + low++; + } + high += 0x121; + low += 0x1f; + high >>= 1; + high ^= 0x20; + return((high << 8) | low); +} + +void PARTSCALL satuation_s16(SINT16 *dst, const SINT32 *src, UINT size) { + + SINT32 data; + + size >>= 1; + while(size--) { + data = *src++; + if (data > 32767) { + data = 32767; + } + else if (data < -32768) { + data = -32768; + } + *dst++ = (SINT16)data; + } +} + +void PARTSCALL satuation_s16x(SINT16 *dst, const SINT32 *src, UINT size) { + + SINT32 data; + + size >>= 2; + while(size--) { + data = src[0]; + if (data > 32767) { + data = 32767; + } + else if (data < -32768) { + data = -32768; + } + dst[1] = (SINT16)data; + data = src[1]; + if (data > 32767) { + data = 32767; + } + else if (data < -32768) { + data = -32768; + } + dst[0] = (SINT16)data; + src += 2; + dst += 2; + } +} + diff --git a/common/parts.h b/common/parts.h old mode 100755 new mode 100644 index 2ac38162..6ee8fcc0 --- a/common/parts.h +++ b/common/parts.h @@ -1,18 +1,18 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void PARTSCALL rand_setseed(SINT32 seed); -SINT32 PARTSCALL rand_get(void); -UINT8 PARTSCALL AdjustAfterMultiply(UINT8 value); -UINT8 PARTSCALL AdjustBeforeDivision(UINT8 value); -UINT PARTSCALL sjis2jis(UINT sjis); -UINT PARTSCALL jis2sjis(UINT jis); -void PARTSCALL satuation_s16(SINT16 *dst, const SINT32 *src, UINT size); -void PARTSCALL satuation_s16x(SINT16 *dst, const SINT32 *src, UINT size); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void PARTSCALL rand_setseed(SINT32 seed); +SINT32 PARTSCALL rand_get(void); +UINT8 PARTSCALL AdjustAfterMultiply(UINT8 value); +UINT8 PARTSCALL AdjustBeforeDivision(UINT8 value); +UINT PARTSCALL sjis2jis(UINT sjis); +UINT PARTSCALL jis2sjis(UINT jis); +void PARTSCALL satuation_s16(SINT16 *dst, const SINT32 *src, UINT size); +void PARTSCALL satuation_s16x(SINT16 *dst, const SINT32 *src, UINT size); + +#ifdef __cplusplus +} +#endif + diff --git a/common/profile.c b/common/profile.c old mode 100755 new mode 100644 index f24bbd63..ef45442c --- a/common/profile.c +++ b/common/profile.c @@ -1,1190 +1,1190 @@ -/** - * @file profile.c - * @brief Implementation of the profiler - */ - -#include -#include -#include -#include -#include -#if defined(SUPPORT_TEXTCNV) -#include "codecnv/textcnv.h" -#endif - -/** - * End of line style - */ -static const OEMCHAR s_eol[] = -{ -#if defined(OSLINEBREAK_CR) || defined(OSLINEBREAK_CRLF) - '\r', -#endif -#if defined(OSLINEBREAK_LF) || defined(OSLINEBREAK_CRLF) - '\n', -#endif -}; - -/** - * Trims space - * @param[in] lpString The pointer to a string - * @param[in, out] pcchString The size, in characters - * @return The start of the string - */ -static OEMCHAR* TrimSpace(const OEMCHAR *lpString, UINT *pcchString) -{ - UINT cchString; - - cchString = *pcchString; - while ((cchString > 0) && (lpString[0] == ' ')) - { - lpString++; - cchString--; - } - while ((cchString > 0) && (lpString[cchString - 1] == ' ')) - { - cchString--; - } - *pcchString = cchString; - return (OEMCHAR *)lpString; -} - -/** - * Parses line - * @param[in] lpString The pointer to a string - * @param[in,out] lpcchString The pointer to a length - * @param[out] lppData The pointer to data - * @param[out] lpcchData The pointer to data-length - * @return The start of the string - */ -static OEMCHAR *ParseLine(const OEMCHAR *lpString, UINT *lpcchString, OEMCHAR **lppData, UINT *lpcchData) -{ - UINT cchString; - UINT nIndex; - const OEMCHAR *lpData = NULL; - UINT cchData = 0; - - cchString = *lpcchString; - lpString = TrimSpace(lpString, &cchString); - - if ((cchString >= 2) && (lpString[0] == '[') && (lpString[cchString - 1] == ']')) - { - lpString++; - cchString -= 2; - } - else - { - for (nIndex = 0; nIndex < cchString; nIndex++) - { - if (lpString[nIndex] == '=') - { - break; - } - } - if (nIndex >= cchString) - { - return NULL; - } - lpData = lpString + (nIndex + 1); - cchData = cchString - (nIndex + 1); - cchString = nIndex; - } - - lpString = TrimSpace(lpString, &cchString); - lpData = TrimSpace(lpData, &cchData); - if ((cchData >= 2) && (lpData[0] == '\"') && (lpData[cchData - 1] == '\"')) - { - lpData++; - cchData -= 2; - lpData = TrimSpace(lpData, &cchData); - } - - *lpcchString = cchString; - if (lppData) - { - *lppData = (OEMCHAR*)lpData; - } - if (lpcchData) - { - *lpcchData = cchData; - } - return (OEMCHAR*)lpString; -} - -/** - * Retrieves a string from the specified section in an initialization file - * @param[in] lpFileName The name of the initialization file - * @param[in] lpParam An application-defined value to be passed to the callback function. - * @param[in] lpFunc A pointer to an application-defined callback function - * @retval SUCCESS If the function succeeds - * @retval FAILIURE If the function fails - */ -BRESULT profile_enum(const OEMCHAR *lpFileName, void *lpParam, PROFILEENUMPROC lpFunc) -{ - TEXTFILEH fh; - BRESULT r; - OEMCHAR szAppName[256]; - OEMCHAR szBuffer[512]; - UINT cchBuffer; - OEMCHAR *lpKeyName; - OEMCHAR *lpString; - UINT cchString; - - if (lpFunc == NULL) - { - return SUCCESS; - } - fh = textfile_open(lpFileName, 0x800); - if (fh == NULL) - { - return SUCCESS; - } - - r = SUCCESS; - szAppName[0] = '\0'; - while (textfile_read(fh, szBuffer, NELEMENTS(szBuffer)) == SUCCESS) - { - cchBuffer = (UINT)OEMSTRLEN(szBuffer); - lpKeyName = ParseLine(szBuffer, &cchBuffer, &lpString, &cchString); - if (lpKeyName) - { - lpKeyName[cchBuffer] = '\0'; - if (lpString == NULL) - { - milstr_ncpy(szAppName, lpKeyName, NELEMENTS(szAppName)); - } - else - { - lpString[cchString] = '\0'; - r = (*lpFunc)(lpParam, szAppName, lpKeyName, lpString); - if (r != SUCCESS) - { - break; - } - } - } - } - textfile_close(fh); - return r; -} - - -/* profiler */ - -/** - * @brief the structure of profiler's handle - */ -struct tagProfileHandle -{ - OEMCHAR *lpBuffer; /*!< The pointer of buffer */ - UINT cchBuffer; /*!< The size of buffer */ - UINT nSize; /*!< The available */ - UINT8 szHeader[4]; /*!< The bom */ - UINT cbHeader; /*!< The size of bom */ - UINT nFlags; /*!< The flag */ - OEMCHAR szPath[MAX_PATH]; /*!< The file path */ -}; -typedef struct tagProfileHandle _PFILEH; /*!< defines handle */ - -/** - * @brief The result of search - */ -struct tagProfilePos -{ - UINT cchAppName; /*!< The charactors of app */ - UINT cchKeyName; /*!< The charactors of key */ - UINT nPos; /*!< The position */ - UINT nSize; /*!< The size of key */ - UINT apphit; /*!< The returned flag */ - const OEMCHAR *lpString; /*!< The pointer of the string */ - UINT cchString; /*!< The charactors of the string */ -}; -typedef struct tagProfilePos PFPOS; /*!< defines the structure of position */ - -/*! default buffer size */ -#define PFBUFSIZE (1 << 8) - -/** - * Search - * @param[in] hdl The handle - * @param[out] pfp The pointer of returned - * @param[in] lpAppName The name of app - * @param[in] lpKeyName The name of key - * @retval SUCCESS If succeeded - * @retval FAILURE If failed - */ -static BRESULT SearchKey(PFILEH hdl, PFPOS *pfp, const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName) -{ - PFPOS ret; - const OEMCHAR *lpProfile; - UINT cchProfile; - UINT nIndex; - UINT nSize; - UINT cchLeft; - const OEMCHAR *lpLeft; - OEMCHAR *lpRight; - UINT cchRight; - - if ((hdl == NULL) || (lpAppName == NULL) || (lpKeyName == NULL)) - { - return FAILURE; - } - memset(&ret, 0, sizeof(ret)); - ret.cchAppName = (UINT)OEMSTRLEN(lpAppName); - ret.cchKeyName = (UINT)OEMSTRLEN(lpKeyName); - if ((ret.cchAppName == 0) || (ret.cchKeyName == 0)) - { - return FAILURE; - } - - lpProfile = hdl->lpBuffer; - cchProfile = hdl->nSize; - while (cchProfile > 0) - { - nIndex = 0; - while ((nIndex < cchProfile) && (lpProfile[nIndex] != '\r') && (lpProfile[nIndex] != '\n')) - { - nIndex++; - } - lpLeft = lpProfile; - cchLeft = nIndex; - - nSize = nIndex; - if ((nSize < cchProfile) && (lpProfile[nSize] == '\r')) - { - nSize++; - } - if ((nSize < cchProfile) && (lpProfile[nSize] == '\n')) - { - nSize++; - } - - lpLeft = ParseLine(lpLeft, &cchLeft, &lpRight, &cchRight); - if (lpLeft) - { - if (lpRight == NULL) - { - if (ret.apphit) - { - break; - } - if ((cchLeft == ret.cchAppName) && (!milstr_memcmp(lpLeft, lpAppName))) - { - ret.apphit = 1; - } - } - else if ((ret.apphit) && (cchLeft == ret.cchKeyName) && (!milstr_memcmp(lpLeft, lpKeyName))) - { - ret.nPos = (UINT)(lpProfile - hdl->lpBuffer); - ret.nSize = nSize; - - ret.lpString = lpRight; - ret.cchString = cchRight; - break; - } - } - - lpProfile += nSize; - cchProfile -= nSize; - - if (nIndex) - { - ret.nPos = (UINT)(lpProfile - hdl->lpBuffer); - ret.nSize = 0; - } - } - if (pfp) - { - *pfp = ret; - } - return SUCCESS; -} - -/** - * Replace - * @param[in] hdl The handle - * @param[in] nPos The position - * @param[in] size1 The current size - * @param[in] size2 The new size - * @retval SUCCESS If succeeded - * @retval FAILURE If failed - */ -static BRESULT replace(PFILEH hdl, UINT nPos, UINT size1, UINT size2) -{ - UINT cnt; - UINT size; - UINT newsize; - OEMCHAR *p; - OEMCHAR *q; - - size1 += nPos; - size2 += nPos; - if (size1 > hdl->nSize) - { - return FAILURE; - } - cnt = hdl->nSize - size1; - if (size1 < size2) - { - size = hdl->nSize + size2 - size1; - if (size > hdl->cchBuffer) - { - newsize = (size & (~(PFBUFSIZE - 1))) + PFBUFSIZE; - p = (OEMCHAR *)_MALLOC(newsize * sizeof(OEMCHAR), "profile"); - if (p == NULL) - { - return FAILURE; - } - if (hdl->lpBuffer) - { - CopyMemory(p, hdl->lpBuffer, hdl->cchBuffer * sizeof(OEMCHAR)); - _MFREE(hdl->lpBuffer); - } - hdl->lpBuffer = p; - hdl->cchBuffer = newsize; - } - hdl->nSize = size; - if (cnt) - { - p = hdl->lpBuffer + size1; - q = hdl->lpBuffer + size2; - do - { - --cnt; - q[cnt] = p[cnt]; - } while (cnt); - } - } - else if (size1 > size2) - { - hdl->nSize -= (size1 - size2); - if (cnt) - { - p = hdl->lpBuffer + size1; - q = hdl->lpBuffer + size2; - do - { - *q++ = *p++; - } while(--cnt); - } - } - hdl->nFlags |= PFILEH_MODIFY; - return SUCCESS; -} - -/** - * Regist file - * @param[in] fh The handle of file - * @return The handle - */ -static PFILEH registfile(FILEH fh) -{ - UINT nReadSize; -#if defined(SUPPORT_TEXTCNV) - TCINF inf; -#endif - UINT cbHeader; - UINT nWidth; - UINT8 szHeader[4]; - UINT nFileSize; - UINT nNewSize; - void *lpBuffer1; -#if defined(SUPPORT_TEXTCNV) - void *lpBuffer2; -#endif - PFILEH ret; - - nReadSize = file_read(fh, szHeader, sizeof(szHeader)); -#if defined(SUPPORT_TEXTCNV) - if (textcnv_getinfo(&inf, szHeader, nReadSize) == 0) - { - goto rf_err1; - } - if (!(inf.caps & TEXTCNV_READ)) - { - goto rf_err1; - } - if ((inf.width != 1) && (inf.width != 2)) - { - goto rf_err1; - } - cbHeader = inf.hdrsize; - nWidth = inf.width; -#else - cbHeader = 0; - nWidth = 1; - if ((nReadSize >= 3) && (szHeader[0] == 0xef) && (szHeader[1] == 0xbb) && (szHeader[2] == 0xbf)) - { - // UTF-8 - cbHeader = 3; - } - else if ((nReadSize >= 2) && (szHeader[0] == 0xff) && (szHeader[1] == 0xfe)) - { - // UCSLE - cbHeader = 2; - nWidth = 2; -#if defined(BYTESEX_BIG) - goto rf_err1; -#endif - } - else if ((nReadSize >= 2) && (szHeader[0] == 0xfe) && (szHeader[1] == 0xff)) - { - // UCS2BE - cbHeader = 2; - nWidth = 2; -#if defined(BYTESEX_LITTLE) - goto rf_err1; -#endif - } - if (nWidth != sizeof(OEMCHAR)) - { - goto rf_err1; - } -#endif - - nFileSize = (UINT)file_getsize(fh); - if (nFileSize < cbHeader) - { - goto rf_err1; - } - if (file_seek(fh, (long)cbHeader, FSEEK_SET) != (long)cbHeader) - { - goto rf_err1; - } - nFileSize = (nFileSize - cbHeader) / nWidth; - nNewSize = (nFileSize & (~(PFBUFSIZE - 1))) + PFBUFSIZE; - lpBuffer1 = _MALLOC(nNewSize * nWidth, "profile"); - if (lpBuffer1 == NULL) - { - goto rf_err1; - } - nReadSize = file_read(fh, lpBuffer1, nNewSize * nWidth) / nWidth; -#if defined(SUPPORT_TEXTCNV) - if (inf.xendian) - { - textcnv_swapendian16(lpBuffer1, nReadSize); - } - if (inf.tooem) - { - nFileSize = (inf.tooem)(NULL, 0, lpBuffer1, nReadSize); - nNewSize = (nFileSize & (~(PFBUFSIZE - 1))) + PFBUFSIZE; - lpBuffer2 = _MALLOC(nNewSize * sizeof(OEMCHAR), "profile tmp"); - if (lpBuffer2 == NULL) - { - goto rf_err2; - } - (inf.tooem)((OEMCHAR *)lpBuffer2, nFileSize, lpBuffer1, nReadSize); - _MFREE(lpBuffer1); - lpBuffer1 = lpBuffer2; - nReadSize = nFileSize; - } -#endif // defined(SUPPORT_TEXTCNV) - - ret = (PFILEH)_MALLOC(sizeof(_PFILEH), "profile"); - if (ret == NULL) - { - goto rf_err2; - } - ZeroMemory(ret, sizeof(_PFILEH)); - ret->lpBuffer = (OEMCHAR *)lpBuffer1; - ret->cchBuffer = nNewSize; - ret->nSize = nReadSize; - if (cbHeader) - { - CopyMemory(ret->szHeader, szHeader, cbHeader); - } - ret->cbHeader = cbHeader; - return ret; - -rf_err2: - _MFREE(lpBuffer1); - -rf_err1: - return NULL; -} - -/** - * New file - * @return The handle - */ -static PFILEH registnew(void) -{ - PFILEH ret; - const UINT8 *lpHeader; - UINT cbHeader; - - ret = (PFILEH)_MALLOC(sizeof(*ret), "profile"); - if (ret != NULL) - { - memset(ret, 0, sizeof(*ret)); - -#if defined(OSLANG_UTF8) - lpHeader = str_utf8; - cbHeader = sizeof(str_utf8); -#elif defined(OSLANG_UCS2) - lpHeader = (UINT8 *)str_ucs2; - cbHeader = sizeof(str_ucs2); -#else - lpHeader = NULL; - cbHeader = 0; -#endif - if (cbHeader) - { - memcpy(ret->szHeader, lpHeader, cbHeader); - } - ret->cbHeader = cbHeader; - } - return ret; -} - -/** - * Opens profiler - * @param[in] lpFileName The name of the initialization file - * @param[in] nFlags The flag of opening - * @return The handle - */ -PFILEH profile_open(const OEMCHAR *lpFileName, UINT nFlags) -{ - PFILEH ret; - FILEH fh; - - ret = NULL; - if (lpFileName != NULL) - { - fh = file_open_rb(lpFileName); - if (fh != FILEH_INVALID) - { - ret = registfile(fh); - file_close(fh); - } - else if (nFlags & PFILEH_READONLY) - { - } - else - { - ret = registnew(); - } - } - if (ret) - { - ret->nFlags = nFlags; - file_cpyname(ret->szPath, lpFileName, NELEMENTS(ret->szPath)); - } - return ret; -} - -/** - * Close - * @param[in] hdl The handle of profiler - */ -void profile_close(PFILEH hdl) -{ - void *lpBuffer1; - UINT cchBuffer1; -#if defined(SUPPORT_TEXTCNV) - TCINF inf; - void *lpBuffer2; - UINT cchBuffer2; -#endif - UINT cbHeader; - UINT nWidth; - FILEH fh; - - if (hdl == NULL) - { - return; - } - lpBuffer1 = hdl->lpBuffer; - cchBuffer1 = hdl->nSize; - if (hdl->nFlags & PFILEH_MODIFY) - { -#if defined(SUPPORT_TEXTCNV) - if (textcnv_getinfo(&inf, hdl->szHeader, hdl->cbHeader) == 0) - { - goto wf_err1; - } - if (!(inf.caps & TEXTCNV_WRITE)) - { - goto wf_err1; - } - if ((inf.width != 1) && (inf.width != 2)) - { - goto wf_err1; - } - if (inf.fromoem) - { - cchBuffer2 = (inf.fromoem)(NULL, 0, (const OEMCHAR *)lpBuffer1, cchBuffer1); - lpBuffer2 = _MALLOC(cchBuffer2 * inf.width, "profile tmp"); - if (lpBuffer2 == NULL) - { - goto wf_err1; - } - (inf.fromoem)(lpBuffer2, cchBuffer2, (const OEMCHAR *)lpBuffer1, cchBuffer1); - _MFREE(lpBuffer1); - lpBuffer1 = lpBuffer2; - cchBuffer1 = cchBuffer2; - } - if (inf.xendian) - { - textcnv_swapendian16(lpBuffer1, cchBuffer1); - } - cbHeader = inf.hdrsize; - nWidth = inf.width; -#else // defined(SUPPORT_TEXTCNV) - cbHeader = hdl->cbHeader; - nWidth = sizeof(OEMCHAR); -#endif // defined(SUPPORT_TEXTCNV) - fh = file_create(hdl->szPath); - if (fh == FILEH_INVALID) - { - goto wf_err1; - } - if (cbHeader) - { - file_write(fh, hdl->szHeader, cbHeader); - } - file_write(fh, lpBuffer1, cchBuffer1 * nWidth); - file_close(fh); - } - -wf_err1: - if (lpBuffer1) - { - _MFREE(lpBuffer1); - } - _MFREE(hdl); -} - -/** - * Retrieves the names of all sections in an initialization file. - * @param[out] lpBuffer A pointer to a buffer that receives the section names - * @param[in] cchBuffer The size of the buffer pointed to by the lpBuffer parameter, in characters. - * @param[in] hdl The handle of profiler - * @return The return value specifies the number of characters copied to the specified buffer - */ -UINT profile_getsectionnames(OEMCHAR *lpBuffer, UINT cchBuffer, PFILEH hdl) -{ - UINT cchWritten = 0; - const OEMCHAR* lpProfile; - UINT cchProfile; - UINT nIndex; - OEMCHAR *lpKeyName; - UINT cchKeyName; - OEMCHAR *lpData; - UINT cchRemain; - - if ((hdl == NULL) || (cchBuffer <= 1)) - { - return 0; - } - lpProfile = hdl->lpBuffer; - cchProfile = hdl->nSize; - - cchBuffer--; - - while (cchProfile > 0) - { - nIndex = 0; - while ((nIndex < cchProfile) && (lpProfile[nIndex] != '\r') && (lpProfile[nIndex] != '\n')) - { - nIndex++; - } - - cchKeyName = nIndex; - lpKeyName = ParseLine(lpProfile, &cchKeyName, &lpData, NULL); - if ((lpKeyName != NULL) && (lpData == NULL)) - { - if (lpBuffer) - { - cchRemain = cchBuffer - cchWritten; - if (cchRemain >= (cchKeyName + 1)) - { - memcpy(lpBuffer + cchWritten, lpKeyName, cchKeyName * sizeof(*lpBuffer)); - cchWritten += cchKeyName; - lpBuffer[cchWritten] = '\0'; - cchWritten++; - } - } - } - - lpProfile += nIndex; - cchProfile -= nIndex; - - if ((cchProfile >= 2) && (lpProfile[0] == '\r') && (lpProfile[1] == '\n')) - { - lpProfile++; - cchProfile--; - } - if (cchProfile > 0) - { - lpProfile++; - cchProfile--; - } - } - - if (lpBuffer) - { - lpBuffer[cchWritten] = '\0'; - } - return cchWritten; -} - -/** - * Retrieves a string from the specified section in an initialization file - * @param[in] lpAppName The name of the section containing the key name - * @param[in] lpKeyName The name of the key whose associated string is to be retrieved - * @param[in] lpDefault A default string - * @param[out] lpReturnedString A pointer to the buffer that receives the retrieved string - * @param[in] nSize The size of the buffer pointed to by the lpReturnedString parameter, in characters - * @param[in] hdl The handle of profiler - * @retval SUCCESS If the function succeeds - * @retval FAILIURE If the function fails - */ -BRESULT profile_read(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, const OEMCHAR *lpDefault, OEMCHAR *lpReturnedString, UINT nSize, PFILEH hdl) -{ - PFPOS pfp; - - if ((SearchKey(hdl, &pfp, lpAppName, lpKeyName) != SUCCESS) || (pfp.lpString == NULL)) - { - if (lpDefault == NULL) - { - lpDefault = str_null; - } - milstr_ncpy(lpReturnedString, lpDefault, nSize); - return FAILURE; - } - else - { - nSize = MIN(nSize, pfp.cchString + 1); - milstr_ncpy(lpReturnedString, pfp.lpString, nSize); - return SUCCESS; - } -} - -/** - * Retrieves a string from the specified section in an initialization file - * @param[in] lpAppName The name of the section containing the key name - * @param[in] lpKeyName The name of the key whose associated string is to be retrieved - * @param[in] nDefault A default value - * @param[in] hdl The handle of profiler - * @return The value - */ -int profile_readint(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, int nDefault, PFILEH hdl) -{ - PFPOS pfp; - UINT nSize; - OEMCHAR szBuffer[32]; - - if ((SearchKey(hdl, &pfp, lpAppName, lpKeyName) != SUCCESS) || (pfp.lpString == NULL)) - { - return nDefault; - } - else - { - nSize = MIN(NELEMENTS(szBuffer), pfp.cchString + 1); - milstr_ncpy(szBuffer, pfp.lpString, nSize); - return (int)milstr_solveINT(szBuffer); - } -} - -/** - * Copies a string into the specified section of an initialization file. - * @param[in] lpAppName The name of the section to which the string will be copied - * @param[in] lpKeyName The name of the key to be associated with a string - * @param[in] lpString A null-terminated string to be written to the file - * @param[in] hdl The handle of profiler - * @retval SUCCESS If the function succeeds - * @retval FAILIURE If the function fails - */ -BRESULT profile_write(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, const OEMCHAR *lpString, PFILEH hdl) -{ - PFPOS pfp; - UINT cchWrite; - UINT cchString; - OEMCHAR *lpBuffer; - - if ((hdl == NULL) || (hdl->nFlags & PFILEH_READONLY) || (lpString == NULL) || (SearchKey(hdl, &pfp, lpAppName, lpKeyName) != SUCCESS)) - { - return FAILURE; - } - - if (pfp.nPos != 0) - { - lpBuffer = hdl->lpBuffer + pfp.nPos; - if ((lpBuffer[-1] != '\r') && (lpBuffer[-1] != '\n')) - { - if (replace(hdl, pfp.nPos, 0, NELEMENTS(s_eol)) != SUCCESS) - { - return FAILURE; - } - memcpy(lpBuffer, s_eol, sizeof(s_eol)); - pfp.nPos += NELEMENTS(s_eol); - } - } - - if (!pfp.apphit) - { - cchWrite = pfp.cchAppName + 2 + NELEMENTS(s_eol); - if (replace(hdl, pfp.nPos, 0, cchWrite) != SUCCESS) - { - return FAILURE; - } - lpBuffer = hdl->lpBuffer + pfp.nPos; - *lpBuffer++ = '['; - memcpy(lpBuffer, lpAppName, pfp.cchAppName * sizeof(OEMCHAR)); - lpBuffer += pfp.cchAppName; - *lpBuffer++ = ']'; - memcpy(lpBuffer, s_eol, sizeof(s_eol)); - pfp.nPos += cchWrite; - } - - cchString = (UINT)OEMSTRLEN(lpString); - cchWrite = pfp.cchKeyName + 1 + cchString + NELEMENTS(s_eol); - if (replace(hdl, pfp.nPos, pfp.nSize, cchWrite) != SUCCESS) - { - return FAILURE; - } - lpBuffer = hdl->lpBuffer + pfp.nPos; - memcpy(lpBuffer, lpKeyName, pfp.cchKeyName * sizeof(OEMCHAR)); - lpBuffer += pfp.cchKeyName; - *lpBuffer++ = '='; - memcpy(lpBuffer, lpString, cchString * sizeof(OEMCHAR)); - lpBuffer += cchString; - memcpy(lpBuffer, s_eol, sizeof(s_eol)); - - return SUCCESS; -} - -/** - * Copies a string into the specified section of an initialization file. - * @param[in] lpAppName The name of the section to which the string will be copied - * @param[in] lpKeyName The name of the key to be associated with a string - * @param[in] nValue The value - * @param[in] hdl The handle of profiler - * @retval SUCCESS If the function succeeds - * @retval FAILIURE If the function fails - */ -BRESULT profile_writeint(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, int nValue, PFILEH hdl) -{ - OEMCHAR szBuffer[64]; - - OEMSNPRINTF(szBuffer, sizeof(szBuffer), OEMTEXT("%d"), nValue); - return profile_write(lpAppName, lpKeyName, szBuffer, hdl); - -} - - - -// ---- - -/** - * Set bit - * @param[in,out] ptr The pointer of the bit buffer - * @param[in] nPos The posiiont - * @param[in] set On/Off - */ -static void bitmapset(UINT8 *ptr, UINT nPos, BOOL set) -{ - UINT8 bit; - - ptr += (nPos >> 3); - bit = 1 << (nPos & 7); - if (set) - { - *ptr |= bit; - } - else - { - *ptr &= ~bit; - } -} - -/** - * Get bit - * @param[in] ptr The pointer of the bit buffer - * @param[in] nPos The posiiont - * @return The bit - */ -static BOOL bitmapget(const UINT8 *ptr, UINT nPos) -{ - return ((ptr[nPos >> 3] >> (nPos & 7)) & 1); -} - -/** - * Unserialize - * @param[out] lpBin The pointer of the bit buffer - * @param[in] cbBin The count of the bit - * @param[in] lpString The string - */ -static void binset(UINT8 *lpBin, UINT cbBin, const OEMCHAR *lpString) -{ - UINT i; - UINT8 val; - BOOL set; - OEMCHAR c; - - for (i = 0; i < cbBin; i++) - { - val = 0; - set = FALSE; - while (*lpString == ' ') - { - lpString++; - } - while (1) - { - c = *lpString; - if ((c == '\0') || (c == ' ')) - { - break; - } - else if ((c >= '0') && (c <= '9')) - { - val <<= 4; - val += c - '0'; - set = TRUE; - } - else - { - c |= 0x20; - if ((c >= 'a') && (c <= 'f')) - { - val <<= 4; - val += c - 'a' + 10; - set = TRUE; - } - } - lpString++; - } - if (set == FALSE) - { - break; - } - lpBin[i] = val; - } -} - -/** - * Serialize - * @param[out] lpString The pointer of the string - * @param[in] cchString The charactors of the string - * @param[in] lpBin The pointer of the bit buffer - * @param[in] cbBin The count of the bit - */ -static void binget(OEMCHAR *lpString, int cchString, const UINT8 *lpBin, UINT cbBin) -{ - UINT i; - OEMCHAR tmp[16]; - - if (cbBin) - { - OEMSNPRINTF(tmp, sizeof(tmp), OEMTEXT("%.2x"), lpBin[0]); - milstr_ncpy(lpString, tmp, cchString); - } - for (i = 1; i < cbBin; i++) - { - OEMSNPRINTF(tmp, sizeof(tmp), OEMTEXT(" %.2x"), lpBin[i]); - milstr_ncat(lpString, tmp, cchString); - } -} - -/** - * Read - * @param[in] lpPath The path - * @param[in] lpApp The name of app - * @param[in] lpTable The pointer of tables - * @param[in] nCount The count of tables - * @param[in] cb The callback - */ -void profile_iniread(const OEMCHAR *lpPath, const OEMCHAR *lpApp, const PFTBL *lpTable, UINT nCount, PFREAD cb) -{ - PFILEH pfh; - const PFTBL *p; - const PFTBL *pterm; - OEMCHAR work[512]; - - pfh = profile_open(lpPath, 0); - if (pfh == NULL) - { - return; - } - p = lpTable; - pterm = lpTable + nCount; - while (p < pterm) - { - if (profile_read(lpApp, p->item, NULL, work, NELEMENTS(work), pfh) == SUCCESS) - { - switch(p->itemtype & PFTYPE_MASK) - { - case PFTYPE_STR: - milstr_ncpy((OEMCHAR *)p->value, work, p->arg); - break; - - case PFTYPE_BOOL: - *((UINT8 *)p->value) = (!milstr_cmp(work, str_true)) ? 1 : 0; - break; - - case PFTYPE_BITMAP: - bitmapset((UINT8 *)p->value, p->arg, (!milstr_cmp(work, str_true)) ? TRUE : FALSE); - break; - - case PFTYPE_BIN: - binset((UINT8 *)p->value, p->arg, work); - break; - - case PFTYPE_SINT8: - case PFTYPE_UINT8: - *(UINT8 *)p->value = (UINT32)milstr_solveINT(work); - break; - - case PFTYPE_SINT16: - case PFTYPE_UINT16: - *(UINT16 *)p->value = (UINT32)milstr_solveINT(work); - break; - - case PFTYPE_SINT32: - case PFTYPE_UINT32: - *(UINT32 *)p->value = (UINT32)milstr_solveINT(work); - break; - - case PFTYPE_SINT64: - case PFTYPE_UINT64: - *(UINT64*)p->value = (UINT64)milstr_solveINT64(work); - break; - - case PFTYPE_HEX8: - *(UINT8 *)p->value = (UINT8)milstr_solveHEX(work); - break; - - case PFTYPE_HEX16: - *(UINT16 *)p->value = (UINT16)milstr_solveHEX(work); - break; - - case PFTYPE_HEX32: - *(UINT32 *)p->value = (UINT32)milstr_solveHEX(work); - break; - - default: - if (cb != NULL) - { - (*cb)(p, work); - } - break; - } - } - p++; - } - profile_close(pfh); -} - -/** - * Write - * @param[in] lpPath The path - * @param[in] lpApp The name of app - * @param[in] lpTable The pointer of tables - * @param[in] nCount The count of tables - * @param[in] cb The callback - */ -void profile_iniwrite(const OEMCHAR *lpPath, const OEMCHAR *lpApp, const PFTBL *lpTable, UINT nCount, PFWRITE cb) -{ - PFILEH pfh; - const PFTBL *p; - const PFTBL *pterm; - const OEMCHAR *set; - OEMCHAR work[512]; - - pfh = profile_open(lpPath, 0); - if (pfh == NULL) - { - return; - } - p = lpTable; - pterm = lpTable + nCount; - while (p < pterm) - { - if (!(p->itemtype & PFFLAG_RO)) - { - work[0] = '\0'; - set = work; - switch (p->itemtype & PFTYPE_MASK) - { - case PFTYPE_STR: - set = (OEMCHAR *)p->value; - break; - - case PFTYPE_BOOL: - set = (*((UINT8 *)p->value)) ? str_true : str_false; - break; - - case PFTYPE_BITMAP: - set = (bitmapget((UINT8 *)p->value, p->arg)) ? str_true : str_false; - break; - - case PFTYPE_BIN: - binget(work, NELEMENTS(work), (UINT8 *)p->value, p->arg); - break; - - case PFTYPE_SINT8: - OEMSNPRINTF(work, sizeof(work), str_d, *((SINT8 *)p->value)); - break; - - case PFTYPE_SINT16: - OEMSNPRINTF(work, sizeof(work), str_d, *((SINT16 *)p->value)); - break; - - case PFTYPE_SINT32: - OEMSNPRINTF(work, sizeof(work), str_d, *((SINT32 *)p->value)); - break; - - case PFTYPE_SINT64: - OEMSPRINTF(work, str_lld, *((SINT64*)p->value)); - break; - - case PFTYPE_UINT8: - OEMSNPRINTF(work, sizeof(work), str_u, *((UINT8 *)p->value)); - break; - - case PFTYPE_UINT16: - OEMSNPRINTF(work, sizeof(work), str_u, *((UINT16 *)p->value)); - break; - - case PFTYPE_UINT32: - OEMSNPRINTF(work, sizeof(work), str_u, *((UINT32 *)p->value)); - break; - - case PFTYPE_UINT64: - OEMSPRINTF(work, str_llu, *((UINT64*)p->value)); - break; - - case PFTYPE_HEX8: - OEMSNPRINTF(work, sizeof(work), str_x, *((UINT8 *)p->value)); - break; - - case PFTYPE_HEX16: - OEMSNPRINTF(work, sizeof(work), str_x, *((UINT16 *)p->value)); - break; - - case PFTYPE_HEX32: - OEMSNPRINTF(work, sizeof(work), str_x, *((UINT32 *)p->value)); - break; - - default: - if (cb != NULL) - { - set = (*cb)(p, work, NELEMENTS(work)); - } - else - { - set = NULL; - } - break; - } - if (set) - { - profile_write(lpApp, p->item, set, pfh); - } - } - p++; - } - profile_close(pfh); -} +/** + * @file profile.c + * @brief Implementation of the profiler + */ + +#include +#include +#include +#include +#include +#if defined(SUPPORT_TEXTCNV) +#include "codecnv/textcnv.h" +#endif + +/** + * End of line style + */ +static const OEMCHAR s_eol[] = +{ +#if defined(OSLINEBREAK_CR) || defined(OSLINEBREAK_CRLF) + '\r', +#endif +#if defined(OSLINEBREAK_LF) || defined(OSLINEBREAK_CRLF) + '\n', +#endif +}; + +/** + * Trims space + * @param[in] lpString The pointer to a string + * @param[in, out] pcchString The size, in characters + * @return The start of the string + */ +static OEMCHAR* TrimSpace(const OEMCHAR *lpString, UINT *pcchString) +{ + UINT cchString; + + cchString = *pcchString; + while ((cchString > 0) && (lpString[0] == ' ')) + { + lpString++; + cchString--; + } + while ((cchString > 0) && (lpString[cchString - 1] == ' ')) + { + cchString--; + } + *pcchString = cchString; + return (OEMCHAR *)lpString; +} + +/** + * Parses line + * @param[in] lpString The pointer to a string + * @param[in,out] lpcchString The pointer to a length + * @param[out] lppData The pointer to data + * @param[out] lpcchData The pointer to data-length + * @return The start of the string + */ +static OEMCHAR *ParseLine(const OEMCHAR *lpString, UINT *lpcchString, OEMCHAR **lppData, UINT *lpcchData) +{ + UINT cchString; + UINT nIndex; + const OEMCHAR *lpData = NULL; + UINT cchData = 0; + + cchString = *lpcchString; + lpString = TrimSpace(lpString, &cchString); + + if ((cchString >= 2) && (lpString[0] == '[') && (lpString[cchString - 1] == ']')) + { + lpString++; + cchString -= 2; + } + else + { + for (nIndex = 0; nIndex < cchString; nIndex++) + { + if (lpString[nIndex] == '=') + { + break; + } + } + if (nIndex >= cchString) + { + return NULL; + } + lpData = lpString + (nIndex + 1); + cchData = cchString - (nIndex + 1); + cchString = nIndex; + } + + lpString = TrimSpace(lpString, &cchString); + lpData = TrimSpace(lpData, &cchData); + if ((cchData >= 2) && (lpData[0] == '\"') && (lpData[cchData - 1] == '\"')) + { + lpData++; + cchData -= 2; + lpData = TrimSpace(lpData, &cchData); + } + + *lpcchString = cchString; + if (lppData) + { + *lppData = (OEMCHAR*)lpData; + } + if (lpcchData) + { + *lpcchData = cchData; + } + return (OEMCHAR*)lpString; +} + +/** + * Retrieves a string from the specified section in an initialization file + * @param[in] lpFileName The name of the initialization file + * @param[in] lpParam An application-defined value to be passed to the callback function. + * @param[in] lpFunc A pointer to an application-defined callback function + * @retval SUCCESS If the function succeeds + * @retval FAILIURE If the function fails + */ +BRESULT profile_enum(const OEMCHAR *lpFileName, void *lpParam, PROFILEENUMPROC lpFunc) +{ + TEXTFILEH fh; + BRESULT r; + OEMCHAR szAppName[256]; + OEMCHAR szBuffer[512]; + UINT cchBuffer; + OEMCHAR *lpKeyName; + OEMCHAR *lpString; + UINT cchString; + + if (lpFunc == NULL) + { + return SUCCESS; + } + fh = textfile_open(lpFileName, 0x800); + if (fh == NULL) + { + return SUCCESS; + } + + r = SUCCESS; + szAppName[0] = '\0'; + while (textfile_read(fh, szBuffer, NELEMENTS(szBuffer)) == SUCCESS) + { + cchBuffer = (UINT)OEMSTRLEN(szBuffer); + lpKeyName = ParseLine(szBuffer, &cchBuffer, &lpString, &cchString); + if (lpKeyName) + { + lpKeyName[cchBuffer] = '\0'; + if (lpString == NULL) + { + milstr_ncpy(szAppName, lpKeyName, NELEMENTS(szAppName)); + } + else + { + lpString[cchString] = '\0'; + r = (*lpFunc)(lpParam, szAppName, lpKeyName, lpString); + if (r != SUCCESS) + { + break; + } + } + } + } + textfile_close(fh); + return r; +} + + +/* profiler */ + +/** + * @brief the structure of profiler's handle + */ +struct tagProfileHandle +{ + OEMCHAR *lpBuffer; /*!< The pointer of buffer */ + UINT cchBuffer; /*!< The size of buffer */ + UINT nSize; /*!< The available */ + UINT8 szHeader[4]; /*!< The bom */ + UINT cbHeader; /*!< The size of bom */ + UINT nFlags; /*!< The flag */ + OEMCHAR szPath[MAX_PATH]; /*!< The file path */ +}; +typedef struct tagProfileHandle _PFILEH; /*!< defines handle */ + +/** + * @brief The result of search + */ +struct tagProfilePos +{ + UINT cchAppName; /*!< The charactors of app */ + UINT cchKeyName; /*!< The charactors of key */ + UINT nPos; /*!< The position */ + UINT nSize; /*!< The size of key */ + UINT apphit; /*!< The returned flag */ + const OEMCHAR *lpString; /*!< The pointer of the string */ + UINT cchString; /*!< The charactors of the string */ +}; +typedef struct tagProfilePos PFPOS; /*!< defines the structure of position */ + +/*! default buffer size */ +#define PFBUFSIZE (1 << 8) + +/** + * Search + * @param[in] hdl The handle + * @param[out] pfp The pointer of returned + * @param[in] lpAppName The name of app + * @param[in] lpKeyName The name of key + * @retval SUCCESS If succeeded + * @retval FAILURE If failed + */ +static BRESULT SearchKey(PFILEH hdl, PFPOS *pfp, const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName) +{ + PFPOS ret; + const OEMCHAR *lpProfile; + UINT cchProfile; + UINT nIndex; + UINT nSize; + UINT cchLeft; + const OEMCHAR *lpLeft; + OEMCHAR *lpRight; + UINT cchRight; + + if ((hdl == NULL) || (lpAppName == NULL) || (lpKeyName == NULL)) + { + return FAILURE; + } + memset(&ret, 0, sizeof(ret)); + ret.cchAppName = (UINT)OEMSTRLEN(lpAppName); + ret.cchKeyName = (UINT)OEMSTRLEN(lpKeyName); + if ((ret.cchAppName == 0) || (ret.cchKeyName == 0)) + { + return FAILURE; + } + + lpProfile = hdl->lpBuffer; + cchProfile = hdl->nSize; + while (cchProfile > 0) + { + nIndex = 0; + while ((nIndex < cchProfile) && (lpProfile[nIndex] != '\r') && (lpProfile[nIndex] != '\n')) + { + nIndex++; + } + lpLeft = lpProfile; + cchLeft = nIndex; + + nSize = nIndex; + if ((nSize < cchProfile) && (lpProfile[nSize] == '\r')) + { + nSize++; + } + if ((nSize < cchProfile) && (lpProfile[nSize] == '\n')) + { + nSize++; + } + + lpLeft = ParseLine(lpLeft, &cchLeft, &lpRight, &cchRight); + if (lpLeft) + { + if (lpRight == NULL) + { + if (ret.apphit) + { + break; + } + if ((cchLeft == ret.cchAppName) && (!milstr_memcmp(lpLeft, lpAppName))) + { + ret.apphit = 1; + } + } + else if ((ret.apphit) && (cchLeft == ret.cchKeyName) && (!milstr_memcmp(lpLeft, lpKeyName))) + { + ret.nPos = (UINT)(lpProfile - hdl->lpBuffer); + ret.nSize = nSize; + + ret.lpString = lpRight; + ret.cchString = cchRight; + break; + } + } + + lpProfile += nSize; + cchProfile -= nSize; + + if (nIndex) + { + ret.nPos = (UINT)(lpProfile - hdl->lpBuffer); + ret.nSize = 0; + } + } + if (pfp) + { + *pfp = ret; + } + return SUCCESS; +} + +/** + * Replace + * @param[in] hdl The handle + * @param[in] nPos The position + * @param[in] size1 The current size + * @param[in] size2 The new size + * @retval SUCCESS If succeeded + * @retval FAILURE If failed + */ +static BRESULT replace(PFILEH hdl, UINT nPos, UINT size1, UINT size2) +{ + UINT cnt; + UINT size; + UINT newsize; + OEMCHAR *p; + OEMCHAR *q; + + size1 += nPos; + size2 += nPos; + if (size1 > hdl->nSize) + { + return FAILURE; + } + cnt = hdl->nSize - size1; + if (size1 < size2) + { + size = hdl->nSize + size2 - size1; + if (size > hdl->cchBuffer) + { + newsize = (size & (~(PFBUFSIZE - 1))) + PFBUFSIZE; + p = (OEMCHAR *)_MALLOC(newsize * sizeof(OEMCHAR), "profile"); + if (p == NULL) + { + return FAILURE; + } + if (hdl->lpBuffer) + { + CopyMemory(p, hdl->lpBuffer, hdl->cchBuffer * sizeof(OEMCHAR)); + _MFREE(hdl->lpBuffer); + } + hdl->lpBuffer = p; + hdl->cchBuffer = newsize; + } + hdl->nSize = size; + if (cnt) + { + p = hdl->lpBuffer + size1; + q = hdl->lpBuffer + size2; + do + { + --cnt; + q[cnt] = p[cnt]; + } while (cnt); + } + } + else if (size1 > size2) + { + hdl->nSize -= (size1 - size2); + if (cnt) + { + p = hdl->lpBuffer + size1; + q = hdl->lpBuffer + size2; + do + { + *q++ = *p++; + } while(--cnt); + } + } + hdl->nFlags |= PFILEH_MODIFY; + return SUCCESS; +} + +/** + * Regist file + * @param[in] fh The handle of file + * @return The handle + */ +static PFILEH registfile(FILEH fh) +{ + UINT nReadSize; +#if defined(SUPPORT_TEXTCNV) + TCINF inf; +#endif + UINT cbHeader; + UINT nWidth; + UINT8 szHeader[4]; + UINT nFileSize; + UINT nNewSize; + void *lpBuffer1; +#if defined(SUPPORT_TEXTCNV) + void *lpBuffer2; +#endif + PFILEH ret; + + nReadSize = file_read(fh, szHeader, sizeof(szHeader)); +#if defined(SUPPORT_TEXTCNV) + if (textcnv_getinfo(&inf, szHeader, nReadSize) == 0) + { + goto rf_err1; + } + if (!(inf.caps & TEXTCNV_READ)) + { + goto rf_err1; + } + if ((inf.width != 1) && (inf.width != 2)) + { + goto rf_err1; + } + cbHeader = inf.hdrsize; + nWidth = inf.width; +#else + cbHeader = 0; + nWidth = 1; + if ((nReadSize >= 3) && (szHeader[0] == 0xef) && (szHeader[1] == 0xbb) && (szHeader[2] == 0xbf)) + { + // UTF-8 + cbHeader = 3; + } + else if ((nReadSize >= 2) && (szHeader[0] == 0xff) && (szHeader[1] == 0xfe)) + { + // UCSLE + cbHeader = 2; + nWidth = 2; +#if defined(BYTESEX_BIG) + goto rf_err1; +#endif + } + else if ((nReadSize >= 2) && (szHeader[0] == 0xfe) && (szHeader[1] == 0xff)) + { + // UCS2BE + cbHeader = 2; + nWidth = 2; +#if defined(BYTESEX_LITTLE) + goto rf_err1; +#endif + } + if (nWidth != sizeof(OEMCHAR)) + { + goto rf_err1; + } +#endif + + nFileSize = (UINT)file_getsize(fh); + if (nFileSize < cbHeader) + { + goto rf_err1; + } + if (file_seek(fh, (long)cbHeader, FSEEK_SET) != (long)cbHeader) + { + goto rf_err1; + } + nFileSize = (nFileSize - cbHeader) / nWidth; + nNewSize = (nFileSize & (~(PFBUFSIZE - 1))) + PFBUFSIZE; + lpBuffer1 = _MALLOC(nNewSize * nWidth, "profile"); + if (lpBuffer1 == NULL) + { + goto rf_err1; + } + nReadSize = file_read(fh, lpBuffer1, nNewSize * nWidth) / nWidth; +#if defined(SUPPORT_TEXTCNV) + if (inf.xendian) + { + textcnv_swapendian16(lpBuffer1, nReadSize); + } + if (inf.tooem) + { + nFileSize = (inf.tooem)(NULL, 0, lpBuffer1, nReadSize); + nNewSize = (nFileSize & (~(PFBUFSIZE - 1))) + PFBUFSIZE; + lpBuffer2 = _MALLOC(nNewSize * sizeof(OEMCHAR), "profile tmp"); + if (lpBuffer2 == NULL) + { + goto rf_err2; + } + (inf.tooem)((OEMCHAR *)lpBuffer2, nFileSize, lpBuffer1, nReadSize); + _MFREE(lpBuffer1); + lpBuffer1 = lpBuffer2; + nReadSize = nFileSize; + } +#endif // defined(SUPPORT_TEXTCNV) + + ret = (PFILEH)_MALLOC(sizeof(_PFILEH), "profile"); + if (ret == NULL) + { + goto rf_err2; + } + ZeroMemory(ret, sizeof(_PFILEH)); + ret->lpBuffer = (OEMCHAR *)lpBuffer1; + ret->cchBuffer = nNewSize; + ret->nSize = nReadSize; + if (cbHeader) + { + CopyMemory(ret->szHeader, szHeader, cbHeader); + } + ret->cbHeader = cbHeader; + return ret; + +rf_err2: + _MFREE(lpBuffer1); + +rf_err1: + return NULL; +} + +/** + * New file + * @return The handle + */ +static PFILEH registnew(void) +{ + PFILEH ret; + const UINT8 *lpHeader; + UINT cbHeader; + + ret = (PFILEH)_MALLOC(sizeof(*ret), "profile"); + if (ret != NULL) + { + memset(ret, 0, sizeof(*ret)); + +#if defined(OSLANG_UTF8) + lpHeader = str_utf8; + cbHeader = sizeof(str_utf8); +#elif defined(OSLANG_UCS2) + lpHeader = (UINT8 *)str_ucs2; + cbHeader = sizeof(str_ucs2); +#else + lpHeader = NULL; + cbHeader = 0; +#endif + if (cbHeader) + { + memcpy(ret->szHeader, lpHeader, cbHeader); + } + ret->cbHeader = cbHeader; + } + return ret; +} + +/** + * Opens profiler + * @param[in] lpFileName The name of the initialization file + * @param[in] nFlags The flag of opening + * @return The handle + */ +PFILEH profile_open(const OEMCHAR *lpFileName, UINT nFlags) +{ + PFILEH ret; + FILEH fh; + + ret = NULL; + if (lpFileName != NULL) + { + fh = file_open_rb(lpFileName); + if (fh != FILEH_INVALID) + { + ret = registfile(fh); + file_close(fh); + } + else if (nFlags & PFILEH_READONLY) + { + } + else + { + ret = registnew(); + } + } + if (ret) + { + ret->nFlags = nFlags; + file_cpyname(ret->szPath, lpFileName, NELEMENTS(ret->szPath)); + } + return ret; +} + +/** + * Close + * @param[in] hdl The handle of profiler + */ +void profile_close(PFILEH hdl) +{ + void *lpBuffer1; + UINT cchBuffer1; +#if defined(SUPPORT_TEXTCNV) + TCINF inf; + void *lpBuffer2; + UINT cchBuffer2; +#endif + UINT cbHeader; + UINT nWidth; + FILEH fh; + + if (hdl == NULL) + { + return; + } + lpBuffer1 = hdl->lpBuffer; + cchBuffer1 = hdl->nSize; + if (hdl->nFlags & PFILEH_MODIFY) + { +#if defined(SUPPORT_TEXTCNV) + if (textcnv_getinfo(&inf, hdl->szHeader, hdl->cbHeader) == 0) + { + goto wf_err1; + } + if (!(inf.caps & TEXTCNV_WRITE)) + { + goto wf_err1; + } + if ((inf.width != 1) && (inf.width != 2)) + { + goto wf_err1; + } + if (inf.fromoem) + { + cchBuffer2 = (inf.fromoem)(NULL, 0, (const OEMCHAR *)lpBuffer1, cchBuffer1); + lpBuffer2 = _MALLOC(cchBuffer2 * inf.width, "profile tmp"); + if (lpBuffer2 == NULL) + { + goto wf_err1; + } + (inf.fromoem)(lpBuffer2, cchBuffer2, (const OEMCHAR *)lpBuffer1, cchBuffer1); + _MFREE(lpBuffer1); + lpBuffer1 = lpBuffer2; + cchBuffer1 = cchBuffer2; + } + if (inf.xendian) + { + textcnv_swapendian16(lpBuffer1, cchBuffer1); + } + cbHeader = inf.hdrsize; + nWidth = inf.width; +#else // defined(SUPPORT_TEXTCNV) + cbHeader = hdl->cbHeader; + nWidth = sizeof(OEMCHAR); +#endif // defined(SUPPORT_TEXTCNV) + fh = file_create(hdl->szPath); + if (fh == FILEH_INVALID) + { + goto wf_err1; + } + if (cbHeader) + { + file_write(fh, hdl->szHeader, cbHeader); + } + file_write(fh, lpBuffer1, cchBuffer1 * nWidth); + file_close(fh); + } + +wf_err1: + if (lpBuffer1) + { + _MFREE(lpBuffer1); + } + _MFREE(hdl); +} + +/** + * Retrieves the names of all sections in an initialization file. + * @param[out] lpBuffer A pointer to a buffer that receives the section names + * @param[in] cchBuffer The size of the buffer pointed to by the lpBuffer parameter, in characters. + * @param[in] hdl The handle of profiler + * @return The return value specifies the number of characters copied to the specified buffer + */ +UINT profile_getsectionnames(OEMCHAR *lpBuffer, UINT cchBuffer, PFILEH hdl) +{ + UINT cchWritten = 0; + const OEMCHAR* lpProfile; + UINT cchProfile; + UINT nIndex; + OEMCHAR *lpKeyName; + UINT cchKeyName; + OEMCHAR *lpData; + UINT cchRemain; + + if ((hdl == NULL) || (cchBuffer <= 1)) + { + return 0; + } + lpProfile = hdl->lpBuffer; + cchProfile = hdl->nSize; + + cchBuffer--; + + while (cchProfile > 0) + { + nIndex = 0; + while ((nIndex < cchProfile) && (lpProfile[nIndex] != '\r') && (lpProfile[nIndex] != '\n')) + { + nIndex++; + } + + cchKeyName = nIndex; + lpKeyName = ParseLine(lpProfile, &cchKeyName, &lpData, NULL); + if ((lpKeyName != NULL) && (lpData == NULL)) + { + if (lpBuffer) + { + cchRemain = cchBuffer - cchWritten; + if (cchRemain >= (cchKeyName + 1)) + { + memcpy(lpBuffer + cchWritten, lpKeyName, cchKeyName * sizeof(*lpBuffer)); + cchWritten += cchKeyName; + lpBuffer[cchWritten] = '\0'; + cchWritten++; + } + } + } + + lpProfile += nIndex; + cchProfile -= nIndex; + + if ((cchProfile >= 2) && (lpProfile[0] == '\r') && (lpProfile[1] == '\n')) + { + lpProfile++; + cchProfile--; + } + if (cchProfile > 0) + { + lpProfile++; + cchProfile--; + } + } + + if (lpBuffer) + { + lpBuffer[cchWritten] = '\0'; + } + return cchWritten; +} + +/** + * Retrieves a string from the specified section in an initialization file + * @param[in] lpAppName The name of the section containing the key name + * @param[in] lpKeyName The name of the key whose associated string is to be retrieved + * @param[in] lpDefault A default string + * @param[out] lpReturnedString A pointer to the buffer that receives the retrieved string + * @param[in] nSize The size of the buffer pointed to by the lpReturnedString parameter, in characters + * @param[in] hdl The handle of profiler + * @retval SUCCESS If the function succeeds + * @retval FAILIURE If the function fails + */ +BRESULT profile_read(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, const OEMCHAR *lpDefault, OEMCHAR *lpReturnedString, UINT nSize, PFILEH hdl) +{ + PFPOS pfp; + + if ((SearchKey(hdl, &pfp, lpAppName, lpKeyName) != SUCCESS) || (pfp.lpString == NULL)) + { + if (lpDefault == NULL) + { + lpDefault = str_null; + } + milstr_ncpy(lpReturnedString, lpDefault, nSize); + return FAILURE; + } + else + { + nSize = MIN(nSize, pfp.cchString + 1); + milstr_ncpy(lpReturnedString, pfp.lpString, nSize); + return SUCCESS; + } +} + +/** + * Retrieves a string from the specified section in an initialization file + * @param[in] lpAppName The name of the section containing the key name + * @param[in] lpKeyName The name of the key whose associated string is to be retrieved + * @param[in] nDefault A default value + * @param[in] hdl The handle of profiler + * @return The value + */ +int profile_readint(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, int nDefault, PFILEH hdl) +{ + PFPOS pfp; + UINT nSize; + OEMCHAR szBuffer[32]; + + if ((SearchKey(hdl, &pfp, lpAppName, lpKeyName) != SUCCESS) || (pfp.lpString == NULL)) + { + return nDefault; + } + else + { + nSize = MIN(NELEMENTS(szBuffer), pfp.cchString + 1); + milstr_ncpy(szBuffer, pfp.lpString, nSize); + return (int)milstr_solveINT(szBuffer); + } +} + +/** + * Copies a string into the specified section of an initialization file. + * @param[in] lpAppName The name of the section to which the string will be copied + * @param[in] lpKeyName The name of the key to be associated with a string + * @param[in] lpString A null-terminated string to be written to the file + * @param[in] hdl The handle of profiler + * @retval SUCCESS If the function succeeds + * @retval FAILIURE If the function fails + */ +BRESULT profile_write(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, const OEMCHAR *lpString, PFILEH hdl) +{ + PFPOS pfp; + UINT cchWrite; + UINT cchString; + OEMCHAR *lpBuffer; + + if ((hdl == NULL) || (hdl->nFlags & PFILEH_READONLY) || (lpString == NULL) || (SearchKey(hdl, &pfp, lpAppName, lpKeyName) != SUCCESS)) + { + return FAILURE; + } + + if (pfp.nPos != 0) + { + lpBuffer = hdl->lpBuffer + pfp.nPos; + if ((lpBuffer[-1] != '\r') && (lpBuffer[-1] != '\n')) + { + if (replace(hdl, pfp.nPos, 0, NELEMENTS(s_eol)) != SUCCESS) + { + return FAILURE; + } + memcpy(lpBuffer, s_eol, sizeof(s_eol)); + pfp.nPos += NELEMENTS(s_eol); + } + } + + if (!pfp.apphit) + { + cchWrite = pfp.cchAppName + 2 + NELEMENTS(s_eol); + if (replace(hdl, pfp.nPos, 0, cchWrite) != SUCCESS) + { + return FAILURE; + } + lpBuffer = hdl->lpBuffer + pfp.nPos; + *lpBuffer++ = '['; + memcpy(lpBuffer, lpAppName, pfp.cchAppName * sizeof(OEMCHAR)); + lpBuffer += pfp.cchAppName; + *lpBuffer++ = ']'; + memcpy(lpBuffer, s_eol, sizeof(s_eol)); + pfp.nPos += cchWrite; + } + + cchString = (UINT)OEMSTRLEN(lpString); + cchWrite = pfp.cchKeyName + 1 + cchString + NELEMENTS(s_eol); + if (replace(hdl, pfp.nPos, pfp.nSize, cchWrite) != SUCCESS) + { + return FAILURE; + } + lpBuffer = hdl->lpBuffer + pfp.nPos; + memcpy(lpBuffer, lpKeyName, pfp.cchKeyName * sizeof(OEMCHAR)); + lpBuffer += pfp.cchKeyName; + *lpBuffer++ = '='; + memcpy(lpBuffer, lpString, cchString * sizeof(OEMCHAR)); + lpBuffer += cchString; + memcpy(lpBuffer, s_eol, sizeof(s_eol)); + + return SUCCESS; +} + +/** + * Copies a string into the specified section of an initialization file. + * @param[in] lpAppName The name of the section to which the string will be copied + * @param[in] lpKeyName The name of the key to be associated with a string + * @param[in] nValue The value + * @param[in] hdl The handle of profiler + * @retval SUCCESS If the function succeeds + * @retval FAILIURE If the function fails + */ +BRESULT profile_writeint(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, int nValue, PFILEH hdl) +{ + OEMCHAR szBuffer[64]; + + OEMSNPRINTF(szBuffer, sizeof(szBuffer), OEMTEXT("%d"), nValue); + return profile_write(lpAppName, lpKeyName, szBuffer, hdl); + +} + + + +// ---- + +/** + * Set bit + * @param[in,out] ptr The pointer of the bit buffer + * @param[in] nPos The posiiont + * @param[in] set On/Off + */ +static void bitmapset(UINT8 *ptr, UINT nPos, BOOL set) +{ + UINT8 bit; + + ptr += (nPos >> 3); + bit = 1 << (nPos & 7); + if (set) + { + *ptr |= bit; + } + else + { + *ptr &= ~bit; + } +} + +/** + * Get bit + * @param[in] ptr The pointer of the bit buffer + * @param[in] nPos The posiiont + * @return The bit + */ +static BOOL bitmapget(const UINT8 *ptr, UINT nPos) +{ + return ((ptr[nPos >> 3] >> (nPos & 7)) & 1); +} + +/** + * Unserialize + * @param[out] lpBin The pointer of the bit buffer + * @param[in] cbBin The count of the bit + * @param[in] lpString The string + */ +static void binset(UINT8 *lpBin, UINT cbBin, const OEMCHAR *lpString) +{ + UINT i; + UINT8 val; + BOOL set; + OEMCHAR c; + + for (i = 0; i < cbBin; i++) + { + val = 0; + set = FALSE; + while (*lpString == ' ') + { + lpString++; + } + while (1) + { + c = *lpString; + if ((c == '\0') || (c == ' ')) + { + break; + } + else if ((c >= '0') && (c <= '9')) + { + val <<= 4; + val += c - '0'; + set = TRUE; + } + else + { + c |= 0x20; + if ((c >= 'a') && (c <= 'f')) + { + val <<= 4; + val += c - 'a' + 10; + set = TRUE; + } + } + lpString++; + } + if (set == FALSE) + { + break; + } + lpBin[i] = val; + } +} + +/** + * Serialize + * @param[out] lpString The pointer of the string + * @param[in] cchString The charactors of the string + * @param[in] lpBin The pointer of the bit buffer + * @param[in] cbBin The count of the bit + */ +static void binget(OEMCHAR *lpString, int cchString, const UINT8 *lpBin, UINT cbBin) +{ + UINT i; + OEMCHAR tmp[16]; + + if (cbBin) + { + OEMSNPRINTF(tmp, sizeof(tmp), OEMTEXT("%.2x"), lpBin[0]); + milstr_ncpy(lpString, tmp, cchString); + } + for (i = 1; i < cbBin; i++) + { + OEMSNPRINTF(tmp, sizeof(tmp), OEMTEXT(" %.2x"), lpBin[i]); + milstr_ncat(lpString, tmp, cchString); + } +} + +/** + * Read + * @param[in] lpPath The path + * @param[in] lpApp The name of app + * @param[in] lpTable The pointer of tables + * @param[in] nCount The count of tables + * @param[in] cb The callback + */ +void profile_iniread(const OEMCHAR *lpPath, const OEMCHAR *lpApp, const PFTBL *lpTable, UINT nCount, PFREAD cb) +{ + PFILEH pfh; + const PFTBL *p; + const PFTBL *pterm; + OEMCHAR work[512]; + + pfh = profile_open(lpPath, 0); + if (pfh == NULL) + { + return; + } + p = lpTable; + pterm = lpTable + nCount; + while (p < pterm) + { + if (profile_read(lpApp, p->item, NULL, work, NELEMENTS(work), pfh) == SUCCESS) + { + switch(p->itemtype & PFTYPE_MASK) + { + case PFTYPE_STR: + milstr_ncpy((OEMCHAR *)p->value, work, p->arg); + break; + + case PFTYPE_BOOL: + *((UINT8 *)p->value) = (!milstr_cmp(work, str_true)) ? 1 : 0; + break; + + case PFTYPE_BITMAP: + bitmapset((UINT8 *)p->value, p->arg, (!milstr_cmp(work, str_true)) ? TRUE : FALSE); + break; + + case PFTYPE_BIN: + binset((UINT8 *)p->value, p->arg, work); + break; + + case PFTYPE_SINT8: + case PFTYPE_UINT8: + *(UINT8 *)p->value = (UINT32)milstr_solveINT(work); + break; + + case PFTYPE_SINT16: + case PFTYPE_UINT16: + *(UINT16 *)p->value = (UINT32)milstr_solveINT(work); + break; + + case PFTYPE_SINT32: + case PFTYPE_UINT32: + *(UINT32 *)p->value = (UINT32)milstr_solveINT(work); + break; + + case PFTYPE_SINT64: + case PFTYPE_UINT64: + *(UINT64*)p->value = (UINT64)milstr_solveINT64(work); + break; + + case PFTYPE_HEX8: + *(UINT8 *)p->value = (UINT8)milstr_solveHEX(work); + break; + + case PFTYPE_HEX16: + *(UINT16 *)p->value = (UINT16)milstr_solveHEX(work); + break; + + case PFTYPE_HEX32: + *(UINT32 *)p->value = (UINT32)milstr_solveHEX(work); + break; + + default: + if (cb != NULL) + { + (*cb)(p, work); + } + break; + } + } + p++; + } + profile_close(pfh); +} + +/** + * Write + * @param[in] lpPath The path + * @param[in] lpApp The name of app + * @param[in] lpTable The pointer of tables + * @param[in] nCount The count of tables + * @param[in] cb The callback + */ +void profile_iniwrite(const OEMCHAR *lpPath, const OEMCHAR *lpApp, const PFTBL *lpTable, UINT nCount, PFWRITE cb) +{ + PFILEH pfh; + const PFTBL *p; + const PFTBL *pterm; + const OEMCHAR *set; + OEMCHAR work[512]; + + pfh = profile_open(lpPath, 0); + if (pfh == NULL) + { + return; + } + p = lpTable; + pterm = lpTable + nCount; + while (p < pterm) + { + if (!(p->itemtype & PFFLAG_RO)) + { + work[0] = '\0'; + set = work; + switch (p->itemtype & PFTYPE_MASK) + { + case PFTYPE_STR: + set = (OEMCHAR *)p->value; + break; + + case PFTYPE_BOOL: + set = (*((UINT8 *)p->value)) ? str_true : str_false; + break; + + case PFTYPE_BITMAP: + set = (bitmapget((UINT8 *)p->value, p->arg)) ? str_true : str_false; + break; + + case PFTYPE_BIN: + binget(work, NELEMENTS(work), (UINT8 *)p->value, p->arg); + break; + + case PFTYPE_SINT8: + OEMSNPRINTF(work, sizeof(work), str_d, *((SINT8 *)p->value)); + break; + + case PFTYPE_SINT16: + OEMSNPRINTF(work, sizeof(work), str_d, *((SINT16 *)p->value)); + break; + + case PFTYPE_SINT32: + OEMSNPRINTF(work, sizeof(work), str_d, *((SINT32 *)p->value)); + break; + + case PFTYPE_SINT64: + OEMSPRINTF(work, str_lld, *((SINT64*)p->value)); + break; + + case PFTYPE_UINT8: + OEMSNPRINTF(work, sizeof(work), str_u, *((UINT8 *)p->value)); + break; + + case PFTYPE_UINT16: + OEMSNPRINTF(work, sizeof(work), str_u, *((UINT16 *)p->value)); + break; + + case PFTYPE_UINT32: + OEMSNPRINTF(work, sizeof(work), str_u, *((UINT32 *)p->value)); + break; + + case PFTYPE_UINT64: + OEMSPRINTF(work, str_llu, *((UINT64*)p->value)); + break; + + case PFTYPE_HEX8: + OEMSNPRINTF(work, sizeof(work), str_x, *((UINT8 *)p->value)); + break; + + case PFTYPE_HEX16: + OEMSNPRINTF(work, sizeof(work), str_x, *((UINT16 *)p->value)); + break; + + case PFTYPE_HEX32: + OEMSNPRINTF(work, sizeof(work), str_x, *((UINT32 *)p->value)); + break; + + default: + if (cb != NULL) + { + set = (*cb)(p, work, NELEMENTS(work)); + } + else + { + set = NULL; + } + break; + } + if (set) + { + profile_write(lpApp, p->item, set, pfh); + } + } + p++; + } + profile_close(pfh); +} diff --git a/common/profile.h b/common/profile.h old mode 100755 new mode 100644 index 95892f15..914b5e9f --- a/common/profile.h +++ b/common/profile.h @@ -1,103 +1,103 @@ -/** - * @file profile.h - * @brief Interface of the profiler - */ - -#if !defined(NP2_PROFILE_H__) -#define NP2_PROFILE_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * An application-defined callback function used with the profile_enum - */ -typedef BRESULT (*PROFILEENUMPROC)(void *lpParam, const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, const OEMCHAR *lpString); - -BRESULT profile_enum(const OEMCHAR *lpFileName, void *lpParam, PROFILEENUMPROC lpFunc); - - -/* profiler */ - -/** - * The mode - */ -enum -{ - PFILEH_READONLY = 0x0001, /*!< Readonly */ - PFILEH_MODIFY = 0x0002 /*!< Modified */ -}; - -struct tagProfileHandle; -typedef struct tagProfileHandle* PFILEH; /*!< defines handle */ - -PFILEH profile_open(const OEMCHAR *lpFileName, UINT nFlags); -void profile_close(PFILEH hdl); -UINT profile_getsectionnames(OEMCHAR *lpBuffer, UINT cchBuffer, PFILEH hdl); -BRESULT profile_read(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, const OEMCHAR *lpDefault, OEMCHAR *lpReturnedString, UINT nSize, PFILEH hdl); -int profile_readint(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, int nDefault, PFILEH hdl); -BRESULT profile_write(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, const OEMCHAR *lpString, PFILEH hdl); -BRESULT profile_writeint(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, int nValue, PFILEH hdl); - -/** - * The type of items - */ -enum -{ - PFTYPE_STR = 0, - PFTYPE_BOOL, - PFTYPE_BITMAP, - PFTYPE_BIN, - PFTYPE_SINT8, - PFTYPE_SINT16, - PFTYPE_SINT32, - PFTYPE_SINT64, - PFTYPE_UINT8, - PFTYPE_UINT16, - PFTYPE_UINT32, - PFTYPE_UINT64, - PFTYPE_HEX8, - PFTYPE_HEX16, - PFTYPE_HEX32, - PFTYPE_USER, - PFTYPE_MASK = 0xff, - - PFFLAG_RO = 0x0100, - PFFLAG_MAX = 0x0200, - PFFLAG_AND = 0x0400 -}; - -/** - * @brief The item of profile - */ -struct tagProfileItem -{ - OEMCHAR item[32]; /*!< The name of the item */ - UINT itemtype; /*!< The type of the item */ - void *value; /*!< The pointer of values */ - UINT32 arg; /*!< The arg */ -}; -typedef struct tagProfileItem PFTBL; /*!< defines handle */ - -#define PFSTR(k, f, a) {OEMTEXT(k), f, a, NELEMENTS(a)} /*!< macro:string */ -#define PFVAL(k, f, a) {OEMTEXT(k), f, a, 0} /*!< macro:value */ -#define PFMAX(k, f, a, v) {OEMTEXT(k), f | PFFLAG_MAX, a, v} /*!< macro:max */ -#define PFAND(k, f, a, v) {OEMTEXT(k), f | PFFLAG_AND, a, v} /*!< macro:and */ -#define PFEXT(k, f, a, v) {OEMTEXT(k), f, a, v} /*!< macro */ - -/** Read callback */ -typedef void (*PFREAD)(const PFTBL *lpItem, const OEMCHAR *lpString); -/** Write callback */ -typedef OEMCHAR *(*PFWRITE)(const PFTBL *lpItem, OEMCHAR *lpString, UINT cchString); - -void profile_iniread(const OEMCHAR *lpPath, const OEMCHAR *lpApp, const PFTBL *lpTable, UINT nCount, PFREAD cb); -void profile_iniwrite(const OEMCHAR *lpPath, const OEMCHAR *lpApp, const PFTBL *lpTable, UINT nCount, PFWRITE cb); - -#ifdef __cplusplus -} -#endif - -#endif // defined(NP2_PROFILE_H__) - +/** + * @file profile.h + * @brief Interface of the profiler + */ + +#if !defined(NP2_PROFILE_H__) +#define NP2_PROFILE_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * An application-defined callback function used with the profile_enum + */ +typedef BRESULT (*PROFILEENUMPROC)(void *lpParam, const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, const OEMCHAR *lpString); + +BRESULT profile_enum(const OEMCHAR *lpFileName, void *lpParam, PROFILEENUMPROC lpFunc); + + +/* profiler */ + +/** + * The mode + */ +enum +{ + PFILEH_READONLY = 0x0001, /*!< Readonly */ + PFILEH_MODIFY = 0x0002 /*!< Modified */ +}; + +struct tagProfileHandle; +typedef struct tagProfileHandle* PFILEH; /*!< defines handle */ + +PFILEH profile_open(const OEMCHAR *lpFileName, UINT nFlags); +void profile_close(PFILEH hdl); +UINT profile_getsectionnames(OEMCHAR *lpBuffer, UINT cchBuffer, PFILEH hdl); +BRESULT profile_read(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, const OEMCHAR *lpDefault, OEMCHAR *lpReturnedString, UINT nSize, PFILEH hdl); +int profile_readint(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, int nDefault, PFILEH hdl); +BRESULT profile_write(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, const OEMCHAR *lpString, PFILEH hdl); +BRESULT profile_writeint(const OEMCHAR *lpAppName, const OEMCHAR *lpKeyName, int nValue, PFILEH hdl); + +/** + * The type of items + */ +enum +{ + PFTYPE_STR = 0, + PFTYPE_BOOL, + PFTYPE_BITMAP, + PFTYPE_BIN, + PFTYPE_SINT8, + PFTYPE_SINT16, + PFTYPE_SINT32, + PFTYPE_SINT64, + PFTYPE_UINT8, + PFTYPE_UINT16, + PFTYPE_UINT32, + PFTYPE_UINT64, + PFTYPE_HEX8, + PFTYPE_HEX16, + PFTYPE_HEX32, + PFTYPE_USER, + PFTYPE_MASK = 0xff, + + PFFLAG_RO = 0x0100, + PFFLAG_MAX = 0x0200, + PFFLAG_AND = 0x0400 +}; + +/** + * @brief The item of profile + */ +struct tagProfileItem +{ + OEMCHAR item[32]; /*!< The name of the item */ + UINT itemtype; /*!< The type of the item */ + void *value; /*!< The pointer of values */ + UINT32 arg; /*!< The arg */ +}; +typedef struct tagProfileItem PFTBL; /*!< defines handle */ + +#define PFSTR(k, f, a) {OEMTEXT(k), f, a, NELEMENTS(a)} /*!< macro:string */ +#define PFVAL(k, f, a) {OEMTEXT(k), f, a, 0} /*!< macro:value */ +#define PFMAX(k, f, a, v) {OEMTEXT(k), f | PFFLAG_MAX, a, v} /*!< macro:max */ +#define PFAND(k, f, a, v) {OEMTEXT(k), f | PFFLAG_AND, a, v} /*!< macro:and */ +#define PFEXT(k, f, a, v) {OEMTEXT(k), f, a, v} /*!< macro */ + +/** Read callback */ +typedef void (*PFREAD)(const PFTBL *lpItem, const OEMCHAR *lpString); +/** Write callback */ +typedef OEMCHAR *(*PFWRITE)(const PFTBL *lpItem, OEMCHAR *lpString, UINT cchString); + +void profile_iniread(const OEMCHAR *lpPath, const OEMCHAR *lpApp, const PFTBL *lpTable, UINT nCount, PFREAD cb); +void profile_iniwrite(const OEMCHAR *lpPath, const OEMCHAR *lpApp, const PFTBL *lpTable, UINT nCount, PFWRITE cb); + +#ifdef __cplusplus +} +#endif + +#endif // defined(NP2_PROFILE_H__) + diff --git a/common/rect.c b/common/rect.c old mode 100755 new mode 100644 index 7dc7eaa1..cb86e2a2 --- a/common/rect.c +++ b/common/rect.c @@ -1,155 +1,155 @@ -#include - - -BOOL rect_in(const RECT_T *rect, int x, int y) { - - if ((rect) && - (rect->left <= x) && (rect->right > x) && - (rect->top <= y) && (rect->bottom > y)) { - return(TRUE); - } - return(FALSE); -} - -int rect_num(const RECT_T *rect, int cnt, int x, int y) { - - int i; - - if (rect) { - for (i=0; ileft <= x) && (x < rect->right) && - (rect->top <= y) && (y < rect->bottom)) { - return(i); - } - } - } - return(-1); -} - -BOOL rect_isoverlap(const RECT_T *r1, const RECT_T *r2) { - - if ((r1->left >= r2->right) || - (r1->right <= r2->left) || - (r1->top >= r2->bottom) || - (r1->bottom <= r2->top)) { - return(FALSE); - } - return(TRUE); -} - -void rect_enumout(const RECT_T *tag, const RECT_T *base, - void *arg, void (*outcb)(void *arg, const RECT_T *rect)) { - - RECT_T rect; - - if ((tag != NULL) && (base != NULL) && (outcb != NULL)) { - // base.top -> tag.top - rect.top = base->top; - rect.bottom = MIN(tag->top, base->bottom); - if (rect.top < rect.bottom) { - rect.left = base->left; - rect.right = base->right; - outcb(arg, &rect); - rect.top = rect.bottom; - } - - // -> tag.bottom - rect.bottom = MIN(tag->bottom, base->bottom); - if (rect.top < rect.bottom) { - rect.left = base->left; - rect.right = MIN(tag->left, base->right); - if (rect.left < rect.right) { - outcb(arg, &rect); - } - rect.left = MAX(tag->right, base->left); - rect.right = base->right; - if (rect.left < rect.right) { - outcb(arg, &rect); - } - rect.top = rect.bottom; - } - - // -> base.bottom - rect.bottom = base->bottom; - if (rect.top < rect.bottom) { - rect.left = base->left; - rect.right = base->right; - outcb(arg, &rect); - } - } -} - -void rect_add(RECT_T *dst, const RECT_T *src) { - - if (dst->left > src->left) { - dst->left = src->left; - } - if (dst->top > src->top) { - dst->top = src->top; - } - if (dst->right < src->right) { - dst->right = src->right; - } - if (dst->bottom < src->bottom) { - dst->bottom = src->bottom; - } -} - -void unionrect_rst(UNIRECT *unirct) { - - if (unirct) { - unirct->type = 0; - } -} - -void unionrect_add(UNIRECT *unirct, const RECT_T *rct) { - - int type; - RECT_T *r; - - if (unirct == NULL) { - goto ura_end; - } - type = unirct->type; - if (type < 0) { - goto ura_end; - } - if (rct == NULL) { - type = -1; - } - else { - r = &unirct->r; - if (type++ == 0) { - unirct->r = *rct; - } - else { - if (r->left > rct->left) { - r->left = rct->left; - } - if (r->top > rct->top) { - r->top = rct->top; - } - if (r->right < rct->right) { - r->right = rct->right; - } - if (r->bottom < rct->bottom) { - r->bottom = rct->bottom; - } - } - } - unirct->type = type; - -ura_end: - return; -} - -const RECT_T *unionrect_get(const UNIRECT *unirct) { - - if ((unirct) && (unirct->type > 0)) { - return(&unirct->r); - } - else { - return(NULL); - } -} - +#include + + +BOOL rect_in(const RECT_T *rect, int x, int y) { + + if ((rect) && + (rect->left <= x) && (rect->right > x) && + (rect->top <= y) && (rect->bottom > y)) { + return(TRUE); + } + return(FALSE); +} + +int rect_num(const RECT_T *rect, int cnt, int x, int y) { + + int i; + + if (rect) { + for (i=0; ileft <= x) && (x < rect->right) && + (rect->top <= y) && (y < rect->bottom)) { + return(i); + } + } + } + return(-1); +} + +BOOL rect_isoverlap(const RECT_T *r1, const RECT_T *r2) { + + if ((r1->left >= r2->right) || + (r1->right <= r2->left) || + (r1->top >= r2->bottom) || + (r1->bottom <= r2->top)) { + return(FALSE); + } + return(TRUE); +} + +void rect_enumout(const RECT_T *tag, const RECT_T *base, + void *arg, void (*outcb)(void *arg, const RECT_T *rect)) { + + RECT_T rect; + + if ((tag != NULL) && (base != NULL) && (outcb != NULL)) { + // base.top -> tag.top + rect.top = base->top; + rect.bottom = MIN(tag->top, base->bottom); + if (rect.top < rect.bottom) { + rect.left = base->left; + rect.right = base->right; + outcb(arg, &rect); + rect.top = rect.bottom; + } + + // -> tag.bottom + rect.bottom = MIN(tag->bottom, base->bottom); + if (rect.top < rect.bottom) { + rect.left = base->left; + rect.right = MIN(tag->left, base->right); + if (rect.left < rect.right) { + outcb(arg, &rect); + } + rect.left = MAX(tag->right, base->left); + rect.right = base->right; + if (rect.left < rect.right) { + outcb(arg, &rect); + } + rect.top = rect.bottom; + } + + // -> base.bottom + rect.bottom = base->bottom; + if (rect.top < rect.bottom) { + rect.left = base->left; + rect.right = base->right; + outcb(arg, &rect); + } + } +} + +void rect_add(RECT_T *dst, const RECT_T *src) { + + if (dst->left > src->left) { + dst->left = src->left; + } + if (dst->top > src->top) { + dst->top = src->top; + } + if (dst->right < src->right) { + dst->right = src->right; + } + if (dst->bottom < src->bottom) { + dst->bottom = src->bottom; + } +} + +void unionrect_rst(UNIRECT *unirct) { + + if (unirct) { + unirct->type = 0; + } +} + +void unionrect_add(UNIRECT *unirct, const RECT_T *rct) { + + int type; + RECT_T *r; + + if (unirct == NULL) { + goto ura_end; + } + type = unirct->type; + if (type < 0) { + goto ura_end; + } + if (rct == NULL) { + type = -1; + } + else { + r = &unirct->r; + if (type++ == 0) { + unirct->r = *rct; + } + else { + if (r->left > rct->left) { + r->left = rct->left; + } + if (r->top > rct->top) { + r->top = rct->top; + } + if (r->right < rct->right) { + r->right = rct->right; + } + if (r->bottom < rct->bottom) { + r->bottom = rct->bottom; + } + } + } + unirct->type = type; + +ura_end: + return; +} + +const RECT_T *unionrect_get(const UNIRECT *unirct) { + + if ((unirct) && (unirct->type > 0)) { + return(&unirct->r); + } + else { + return(NULL); + } +} + diff --git a/common/rect.h b/common/rect.h old mode 100755 new mode 100644 index 8289048f..fffd32f0 --- a/common/rect.h +++ b/common/rect.h @@ -1,54 +1,54 @@ -#ifndef NP2_RECT_H -#define NP2_RECT_H - -typedef struct { - int x; - int y; -} POINT_T; - -typedef struct { - int left; - int top; - int right; - int bottom; -} RECT_T; - -typedef struct { - int left; - int top; - int width; - int height; -} SCRN_T; - -typedef union { - POINT_T p; - RECT_T r; - SCRN_T s; -} RECT_U; - -typedef struct { - int type; - RECT_T r; -} UNIRECT; - - -#ifdef __cplusplus -extern "C" { -#endif - -BOOL rect_in(const RECT_T *rect, int x, int y); -int rect_num(const RECT_T *rect, int cnt, int x, int y); -BOOL rect_isoverlap(const RECT_T *r1, const RECT_T *r2); -void rect_enumout(const RECT_T *tag, const RECT_T *base, - void *arg, void (*outcb)(void *arg, const RECT_T *rect)); -void rect_add(RECT_T *dst, const RECT_T *src); - -void unionrect_rst(UNIRECT *unirct); -void unionrect_add(UNIRECT *unirct, const RECT_T *rct); -const RECT_T *unionrect_get(const UNIRECT *unirct); - -#ifdef __cplusplus -} -#endif - -#endif /* NP2_RECT_H */ +#ifndef NP2_RECT_H +#define NP2_RECT_H + +typedef struct { + int x; + int y; +} POINT_T; + +typedef struct { + int left; + int top; + int right; + int bottom; +} RECT_T; + +typedef struct { + int left; + int top; + int width; + int height; +} SCRN_T; + +typedef union { + POINT_T p; + RECT_T r; + SCRN_T s; +} RECT_U; + +typedef struct { + int type; + RECT_T r; +} UNIRECT; + + +#ifdef __cplusplus +extern "C" { +#endif + +BOOL rect_in(const RECT_T *rect, int x, int y); +int rect_num(const RECT_T *rect, int cnt, int x, int y); +BOOL rect_isoverlap(const RECT_T *r1, const RECT_T *r2); +void rect_enumout(const RECT_T *tag, const RECT_T *base, + void *arg, void (*outcb)(void *arg, const RECT_T *rect)); +void rect_add(RECT_T *dst, const RECT_T *src); + +void unionrect_rst(UNIRECT *unirct); +void unionrect_add(UNIRECT *unirct, const RECT_T *rct); +const RECT_T *unionrect_get(const UNIRECT *unirct); + +#ifdef __cplusplus +} +#endif + +#endif /* NP2_RECT_H */ diff --git a/common/resize.c b/common/resize.c old mode 100755 new mode 100644 index 87aa1f3a..a6199727 --- a/common/resize.c +++ b/common/resize.c @@ -1,619 +1,619 @@ -#include -#include - - -enum { - RESIZE_HDIF = 0x01, - RESIZE_VDIF = 0x02 -}; - -enum { - MXBITS = 8, - MYBITS = 8, - MULTIX = (1 << MXBITS), - MULTIY = (1 << MYBITS), - MXMASK = (MULTIX - 1), - MYMASK = (MULTIY - 1) -}; - -enum { - B16BIT = 5, - G16BIT = 6, - R16BIT = 5, - B16SFT = 0, - G16SFT = 5, - R16SFT = 11 -}; - -#define GET16B(c) (((c) >> B16SFT) & ((1 << B16BIT) - 1)) -#define GET16G(c) (((c) >> G16SFT) & ((1 << G16BIT) - 1)) -#define GET16R(c) (((c) >> R16SFT) & ((1 << R16BIT) - 1)) - -typedef struct { - RSZFN func; - int width; - int height; - - int orgx; - int orgy; - UINT *h; - UINT *buf; - UINT bufsize; -} _RSZEX, *RSZEX; - - - -// ---- convert sub - -typedef void (*FNCNV)(RSZHDL hdl, UINT8 *dst, const UINT8 *src); - -#if defined(RESIZE_FASTCOPY) || defined(RESIZE_BILINEAR) -static void cc16by24(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { - - UINT width; - UINT col; - - width = hdl->width; - do { - col = (src[0] >> (8 - B16BIT)) << B16SFT; - col += (src[1] >> (8 - G16BIT)) << G16SFT; - col += (src[2] >> (8 - R16BIT)) << R16SFT; - *(UINT16 *)dst = (UINT16)col; - src += 3; - dst += 2; - } while(--width); -} - -static void cc16by32(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { - - UINT width; - UINT col; - - width = hdl->width; - do { - col = (src[0] >> (8 - B16BIT)) << B16SFT; - col += (src[1] >> (8 - G16BIT)) << G16SFT; - col += (src[2] >> (8 - R16BIT)) << R16SFT; - *(UINT16 *)dst = (UINT16)col; - src += 4; - dst += 2; - } while(--width); -} - -static void cc24by16(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { - - UINT width; - UINT col; - UINT tmp; - - width = hdl->width; - do { - col = *(UINT16 *)src; - tmp = (col >> B16SFT) & ((1 << B16BIT) - 1); - dst[0] = (UINT8)((tmp << (8 - B16BIT)) + (tmp >> (B16BIT * 2 - 8))); - tmp = (col >> G16SFT) & ((1 << G16BIT) - 1); - dst[1] = (UINT8)((tmp << (8 - G16BIT)) + (tmp >> (G16BIT * 2 - 8))); - tmp = (col >> R16SFT) & ((1 << R16BIT) - 1); - dst[2] = (UINT8)((tmp << (8 - R16BIT)) + (tmp >> (R16BIT * 2 - 8))); - src += 2; - dst += 3; - } while(--width); -} - -static void cc32by16(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { - - UINT width; - UINT col; - UINT tmp; - - width = hdl->width; - do { - col = *(UINT16 *)src; - tmp = (col >> B16SFT) & ((1 << B16BIT) - 1); - dst[0] = (UINT8)((tmp << (8 - B16BIT)) + (tmp >> (B16BIT * 2 - 8))); - tmp = (col >> G16SFT) & ((1 << G16BIT) - 1); - dst[1] = (UINT8)((tmp << (8 - G16BIT)) + (tmp >> (G16BIT * 2 - 8))); - tmp = (col >> R16SFT) & ((1 << R16BIT) - 1); - dst[2] = (UINT8)((tmp << (8 - R16BIT)) + (tmp >> (R16BIT * 2 - 8))); - src += 2; - dst += 4; - } while(--width); -} - -static void cc32by24(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { - - UINT width; - - width = hdl->width; - do { - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - src += 3; - dst += 4; - } while(--width); -} -#endif - -#if defined(RESIZE_FASTCOPY) -static void cc8(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { - - CopyMemory(dst, src, hdl->width); -} - -static void cc16(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { - - CopyMemory(dst, src, hdl->width * 2); -} - -static void cc24(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { - - CopyMemory(dst, src, hdl->width * 3); -} - -static void cc32(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { - - CopyMemory(dst, src, hdl->width * 4); -} - -static const FNCNV cnvcpy[RSZFNMAX] = {cc8, cc16, cc24, cc32, cc16by24, cc16by32, cc24by16, cc32by16, cc32by24}; -#endif - - - -// ---- - -#if defined(RESIZE_FASTCOPY) -static void fastcopyfunc(RSZHDL hdl, UINT type, UINT8 *dst, int dalign, - const UINT8 *src, int salign) { - - UINT height; - FNCNV cnv; - - if (type >= RSZFNMAX) { - return; - } - height = hdl->height; - cnv = cnvcpy[type]; - do { - cnv(hdl, dst, src); - src += salign; - dst += dalign; - } while(--height); -} - -static RSZHDL fastcopy(int width, int height) { - - RSZHDL ret; - - ret = (RSZHDL)_MALLOC(sizeof(_RSZHDL), "fastcopy"); - if (ret) { - ret->func = fastcopyfunc; - ret->width = width; - ret->height = height; - } - return(ret); -} -#endif - - -// ---- area average - -#if defined(RESIZE_AREAAVG) -static void aamix8(RSZEX hdl, const UINT8 *src, int volume) { - - UINT *buf; - UINT posx; - int i; - UINT curx; - int vol; - - buf = hdl->buf; - posx = 0; - for (i=0; iorgx; i++) { - curx = hdl->h[i]; - while((curx ^ posx) >> MXBITS) { - vol = (int)(MULTIX - (posx & MXMASK)) * volume; - buf[0] += src[0] * vol; - buf += 1; - posx &= ~MXMASK; - posx += MULTIX; - } - curx -= posx; - if (curx) { - posx += curx; - vol = (int)curx * volume; - buf[0] += src[0] * vol; - } - src++; - } -} - -static void aamix16(RSZEX hdl, const UINT8 *src, int volume) { - - UINT *buf; - UINT posx; - int i; - UINT col; - int r, g, b; - UINT curx; - int vol; - - buf = hdl->buf; - posx = 0; - for (i=0; iorgx; i++) { - col = *(UINT16 *)src; - src += 2; - b = (col >> B16SFT) & ((1 << B16BIT) - 1); - g = (col >> G16SFT) & ((1 << G16BIT) - 1); - r = (col >> R16SFT) & ((1 << R16BIT) - 1); - curx = hdl->h[i]; - while((curx ^ posx) >> MXBITS) { - vol = (int)(MULTIX - (posx & MXMASK)) * volume; - buf[0] += b * vol; - buf[1] += g * vol; - buf[2] += r * vol; - buf += 3; - posx &= ~MXMASK; - posx += MULTIX; - } - curx -= posx; - if (curx) { - posx += curx; - vol = (int)curx * volume; - buf[0] += b * vol; - buf[1] += g * vol; - buf[2] += r * vol; - } - } -} - -static void aamix24(RSZEX hdl, const UINT8 *src, int volume) { - - UINT *buf; - UINT posx; - int i; - UINT curx; - int vol; - - buf = hdl->buf; - posx = 0; - for (i=0; iorgx; i++) { - curx = hdl->h[i]; - while((curx ^ posx) >> MXBITS) { - vol = (int)(MULTIX - (posx & MXMASK)) * volume; - buf[0] += (int)src[0] * vol; - buf[1] += (int)src[1] * vol; - buf[2] += (int)src[2] * vol; - buf += 3; - posx &= ~MXMASK; - posx += MULTIX; - } - curx -= posx; - if (curx) { - posx += curx; - vol = (int)curx * volume; - buf[0] += (int)src[0] * vol; - buf[1] += (int)src[1] * vol; - buf[2] += (int)src[2] * vol; - } - src += 3; - } -} - -static void aamix32(RSZEX hdl, const UINT8 *src, int volume) { - - UINT *buf; - UINT posx; - int i; - UINT curx; - int vol; - - buf = hdl->buf; - posx = 0; - for (i=0; iorgx; i++) { - curx = hdl->h[i]; - while((curx ^ posx) >> MXBITS) { - vol = (int)(MULTIX - (posx & MXMASK)) * volume; - buf[0] += (int)src[0] * vol; - buf[1] += (int)src[1] * vol; - buf[2] += (int)src[2] * vol; - buf += 4; - posx &= ~MXMASK; - posx += MULTIX; - } - curx -= posx; - if (curx) { - posx += curx; - vol = (int)curx * volume; - buf[0] += (int)src[0] * vol; - buf[1] += (int)src[1] * vol; - buf[2] += (int)src[2] * vol; - } - src += 4; - } -} - -static void aaout8(RSZEX hdl, UINT8 *dst) { - -const UINT *buf; - int rem; - - buf = hdl->buf; - rem = hdl->width; - do { - *dst++ = (UINT8)((*buf++) >> (MXBITS + MYBITS)); - } while(--rem); -} - -static void aaout16(RSZEX hdl, UINT8 *dst) { - -const UINT *buf; - int rem; - UINT tmp; - UINT col; - - buf = hdl->buf; - rem = hdl->width; - do { - tmp = buf[0] + (buf[0] >> (8 - B16BIT)); - col = (tmp >> (MXBITS + MYBITS - B16SFT)) & - (((1 << B16BIT) - 1) << B16SFT); - tmp = buf[1] + (buf[1] >> (8 - G16BIT)); - col += (tmp >> (MXBITS + MYBITS - G16SFT)) & - (((1 << G16BIT) - 1) << G16SFT); - tmp = buf[2] + (buf[2] >> (8 - R16BIT)); - col += (tmp >> (MXBITS + MYBITS - R16SFT)) & - (((1 << R16BIT) - 1) << R16SFT); - *(UINT16 *)dst = (UINT16)col; - dst += 2; - buf += 3; - } while(--rem); -} - -static void aaout24(RSZEX hdl, UINT8 *dst) { - -const UINT *buf; - int rem; - - buf = hdl->buf; - rem = hdl->width * 3; - do { - *dst++ = (UINT8)((*buf++) >> (MXBITS + MYBITS)); - } while(--rem); -} - -static void aaout32(RSZEX hdl, UINT8 *dst) { - -const UINT *buf; - int rem; - - buf = hdl->buf; - rem = hdl->width * 4; - do { - *dst++ = (UINT8)((*buf++) >> (MXBITS + MYBITS)); - } while(--rem); -} - -static void aaout16by24(RSZEX hdl, UINT8 *dst) { - -const UINT *buf; - int rem; - UINT col; - - buf = hdl->buf; - rem = hdl->width; - do { - col = (buf[0] >> (MXBITS + MYBITS + 8 - B16BIT - B16SFT)) & - (((1 << B16BIT) - 1) << B16SFT); - col += (buf[1] >> (MXBITS + MYBITS + 8 - G16BIT - G16SFT)) & - (((1 << G16BIT) - 1) << G16SFT); - col += (buf[2] >> (MXBITS + MYBITS + 8 - R16BIT - R16SFT)) & - (((1 << R16BIT) - 1) << R16SFT); - *(UINT16 *)dst = (UINT16)col; - dst += 2; - buf += 3; - } while(--rem); -} - -static void aaout16by32(RSZEX hdl, UINT8 *dst) { - -const UINT *buf; - int rem; - UINT col; - - buf = hdl->buf; - rem = hdl->width; - do { - col = (buf[0] >> (MXBITS + MYBITS + 8 - B16BIT - B16SFT)) & - (((1 << B16BIT) - 1) << B16SFT); - col += (buf[1] >> (MXBITS + MYBITS + 8 - G16BIT - G16SFT)) & - (((1 << G16BIT) - 1) << G16SFT); - col += (buf[2] >> (MXBITS + MYBITS + 8 - R16BIT - R16SFT)) & - (((1 << R16BIT) - 1) << R16SFT); - *(UINT16 *)dst = (UINT16)col; - dst += 2; - buf += 4; - } while(--rem); -} - -static void aaout24by16(RSZEX hdl, UINT8 *dst) { - -const UINT *buf; - int rem; - - buf = hdl->buf; - rem = hdl->width; - do { - dst[0] = (UINT8)(buf[0] >> (MXBITS + MYBITS - 8 + B16BIT)); - dst[1] = (UINT8)(buf[1] >> (MXBITS + MYBITS - 8 + G16BIT)); - dst[2] = (UINT8)(buf[2] >> (MXBITS + MYBITS - 8 + R16BIT)); - dst += 3; - buf += 3; - } while(--rem); -} - -static void aaout32by16(RSZEX hdl, UINT8 *dst) { - -const UINT *buf; - int rem; - - buf = hdl->buf; - rem = hdl->width; - do { - dst[0] = (UINT8)(buf[0] >> (MXBITS + MYBITS - 8 + B16BIT)); - dst[1] = (UINT8)(buf[1] >> (MXBITS + MYBITS - 8 + G16BIT)); - dst[2] = (UINT8)(buf[2] >> (MXBITS + MYBITS - 8 + R16BIT)); - dst += 4; - buf += 3; - } while(--rem); -} - -static void aaout32by24(RSZEX hdl, UINT8 *dst) { - -const UINT *buf; - int rem; - - buf = hdl->buf; - rem = hdl->width; - do { - dst[0] = buf[0] >> (UINT8)((MXBITS + MYBITS)); - dst[1] = buf[1] >> (UINT8)((MXBITS + MYBITS)); - dst[2] = buf[2] >> (UINT8)((MXBITS + MYBITS)); - dst += 4; - buf += 3; - } while(--rem); -} - -typedef void (*AAMIX)(RSZEX hdl, const UINT8 *src, int volume); -typedef void (*AAOUT)(RSZEX hdl, UINT8 *dst); - -static const AAMIX fnaamix[RSZFNMAX] = {aamix8, aamix16, aamix24, aamix32, - aamix24, aamix32, aamix16, aamix16, aamix24}; -static const AAOUT fnaaout[RSZFNMAX] = {aaout8, aaout16, aaout24, aaout32, - aaout16by24, aaout16by32, aaout24by16, aaout32by16, aaout32by24}; - -static void areaavefunc(RSZEX hdl, UINT type, UINT8 *dst, int dalign, - const UINT8 *src, int salign) { - - AAMIX aamix; - AAOUT aaout; - UINT posy; - UINT i; - UINT cury; - - if (type >= RSZFNMAX) { - return; - } - aamix = fnaamix[type]; - aaout = fnaaout[type]; - ZeroMemory(hdl->buf, hdl->bufsize); - posy = 0; - for (i=0; i<(UINT)hdl->orgy; i++) { - cury = (((i + 1) << MYBITS) * (UINT)hdl->height) / (UINT)hdl->orgy; - while((cury ^ posy) >> MYBITS) { - aamix(hdl, src, MULTIY - (posy & MYMASK)); - aaout(hdl, dst); - dst += dalign; - ZeroMemory(hdl->buf, hdl->bufsize); - posy &= ~MYMASK; - posy += MULTIY; - } - cury -= posy; - if (cury) { - posy += cury; - aamix(hdl, src, cury); - } - src += salign; - } -} - -static RSZHDL areaave(int width, int height, int orgx, int orgy) { - - UINT dstcnt; - UINT tbls; - RSZEX rszex; - UINT *ptr; - UINT i; - - dstcnt = width * 3; - tbls = orgx + orgy + dstcnt; - rszex = (RSZEX)_MALLOC(sizeof(_RSZEX) + (tbls * sizeof(UINT)), "RSZEX"); - if (rszex) { - rszex->func = (RSZFN)areaavefunc; - rszex->width = width; - rszex->height = height; - rszex->orgx = orgx; - rszex->orgy = orgy; - ptr = (UINT *)(rszex + 1); - rszex->h = ptr; - i = 0; - do { - i++; - *ptr++ = ((i << MXBITS) * (UINT)width) / (UINT)orgx; - } while(i < (UINT)orgx); - rszex->buf = ptr; - rszex->bufsize = dstcnt * sizeof(UINT); - } - return((RSZHDL)rszex); -} -#endif - - -// ---- - -UINT resize_gettype(int dbpp, int sbpp) { - - UINT ret; - - if (dbpp == 8) { - ret = RSZFN_8BPP; - } - else if (dbpp == 16) { - ret = (sbpp == 24)?RSZFN_16BY24:RSZFN_16BPP; - } - else if (dbpp == 24) { - ret = (sbpp == 16)?RSZFN_24BY16:RSZFN_24BPP; - } - else if (dbpp == 32) { - ret = (sbpp == 16)?RSZFN_32BY16:((sbpp == 24)?RSZFN_32BY24:RSZFN_32BPP); - } - else { - ret = RSZFNMAX; - } - if ((dbpp != sbpp) && (ret < RSZFN_16BY24)) { - ret = RSZFNMAX; - } - return(ret); -} - -RSZHDL resize(int xdst, int ydst, int xsrc, int ysrc) { - - UINT flag; - - flag = 0; - if ((xsrc <= 0) || (xdst <= 0)) { - goto rsz_err; - } - if (xsrc != xdst) { - flag += RESIZE_HDIF; - } - if ((ysrc <= 0) || (ydst <= 0)) { - goto rsz_err; - } - if (ysrc != ydst) { - flag += RESIZE_VDIF; - } -#if defined(RESIZE_FASTCOPY) - if (flag == 0) { - return(fastcopy(xdst, ydst)); - } -#endif -#if defined(RESIZE_AREAAVG) - return(areaave(xdst, ydst, xsrc, ysrc)); -#endif - -rsz_err: - return(NULL); -} - +#include +#include + + +enum { + RESIZE_HDIF = 0x01, + RESIZE_VDIF = 0x02 +}; + +enum { + MXBITS = 8, + MYBITS = 8, + MULTIX = (1 << MXBITS), + MULTIY = (1 << MYBITS), + MXMASK = (MULTIX - 1), + MYMASK = (MULTIY - 1) +}; + +enum { + B16BIT = 5, + G16BIT = 6, + R16BIT = 5, + B16SFT = 0, + G16SFT = 5, + R16SFT = 11 +}; + +#define GET16B(c) (((c) >> B16SFT) & ((1 << B16BIT) - 1)) +#define GET16G(c) (((c) >> G16SFT) & ((1 << G16BIT) - 1)) +#define GET16R(c) (((c) >> R16SFT) & ((1 << R16BIT) - 1)) + +typedef struct { + RSZFN func; + int width; + int height; + + int orgx; + int orgy; + UINT *h; + UINT *buf; + UINT bufsize; +} _RSZEX, *RSZEX; + + + +// ---- convert sub + +typedef void (*FNCNV)(RSZHDL hdl, UINT8 *dst, const UINT8 *src); + +#if defined(RESIZE_FASTCOPY) || defined(RESIZE_BILINEAR) +static void cc16by24(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { + + UINT width; + UINT col; + + width = hdl->width; + do { + col = (src[0] >> (8 - B16BIT)) << B16SFT; + col += (src[1] >> (8 - G16BIT)) << G16SFT; + col += (src[2] >> (8 - R16BIT)) << R16SFT; + *(UINT16 *)dst = (UINT16)col; + src += 3; + dst += 2; + } while(--width); +} + +static void cc16by32(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { + + UINT width; + UINT col; + + width = hdl->width; + do { + col = (src[0] >> (8 - B16BIT)) << B16SFT; + col += (src[1] >> (8 - G16BIT)) << G16SFT; + col += (src[2] >> (8 - R16BIT)) << R16SFT; + *(UINT16 *)dst = (UINT16)col; + src += 4; + dst += 2; + } while(--width); +} + +static void cc24by16(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { + + UINT width; + UINT col; + UINT tmp; + + width = hdl->width; + do { + col = *(UINT16 *)src; + tmp = (col >> B16SFT) & ((1 << B16BIT) - 1); + dst[0] = (UINT8)((tmp << (8 - B16BIT)) + (tmp >> (B16BIT * 2 - 8))); + tmp = (col >> G16SFT) & ((1 << G16BIT) - 1); + dst[1] = (UINT8)((tmp << (8 - G16BIT)) + (tmp >> (G16BIT * 2 - 8))); + tmp = (col >> R16SFT) & ((1 << R16BIT) - 1); + dst[2] = (UINT8)((tmp << (8 - R16BIT)) + (tmp >> (R16BIT * 2 - 8))); + src += 2; + dst += 3; + } while(--width); +} + +static void cc32by16(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { + + UINT width; + UINT col; + UINT tmp; + + width = hdl->width; + do { + col = *(UINT16 *)src; + tmp = (col >> B16SFT) & ((1 << B16BIT) - 1); + dst[0] = (UINT8)((tmp << (8 - B16BIT)) + (tmp >> (B16BIT * 2 - 8))); + tmp = (col >> G16SFT) & ((1 << G16BIT) - 1); + dst[1] = (UINT8)((tmp << (8 - G16BIT)) + (tmp >> (G16BIT * 2 - 8))); + tmp = (col >> R16SFT) & ((1 << R16BIT) - 1); + dst[2] = (UINT8)((tmp << (8 - R16BIT)) + (tmp >> (R16BIT * 2 - 8))); + src += 2; + dst += 4; + } while(--width); +} + +static void cc32by24(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { + + UINT width; + + width = hdl->width; + do { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + src += 3; + dst += 4; + } while(--width); +} +#endif + +#if defined(RESIZE_FASTCOPY) +static void cc8(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { + + CopyMemory(dst, src, hdl->width); +} + +static void cc16(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { + + CopyMemory(dst, src, hdl->width * 2); +} + +static void cc24(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { + + CopyMemory(dst, src, hdl->width * 3); +} + +static void cc32(RSZHDL hdl, UINT8 *dst, const UINT8 *src) { + + CopyMemory(dst, src, hdl->width * 4); +} + +static const FNCNV cnvcpy[RSZFNMAX] = {cc8, cc16, cc24, cc32, cc16by24, cc16by32, cc24by16, cc32by16, cc32by24}; +#endif + + + +// ---- + +#if defined(RESIZE_FASTCOPY) +static void fastcopyfunc(RSZHDL hdl, UINT type, UINT8 *dst, int dalign, + const UINT8 *src, int salign) { + + UINT height; + FNCNV cnv; + + if (type >= RSZFNMAX) { + return; + } + height = hdl->height; + cnv = cnvcpy[type]; + do { + cnv(hdl, dst, src); + src += salign; + dst += dalign; + } while(--height); +} + +static RSZHDL fastcopy(int width, int height) { + + RSZHDL ret; + + ret = (RSZHDL)_MALLOC(sizeof(_RSZHDL), "fastcopy"); + if (ret) { + ret->func = fastcopyfunc; + ret->width = width; + ret->height = height; + } + return(ret); +} +#endif + + +// ---- area average + +#if defined(RESIZE_AREAAVG) +static void aamix8(RSZEX hdl, const UINT8 *src, int volume) { + + UINT *buf; + UINT posx; + int i; + UINT curx; + int vol; + + buf = hdl->buf; + posx = 0; + for (i=0; iorgx; i++) { + curx = hdl->h[i]; + while((curx ^ posx) >> MXBITS) { + vol = (int)(MULTIX - (posx & MXMASK)) * volume; + buf[0] += src[0] * vol; + buf += 1; + posx &= ~MXMASK; + posx += MULTIX; + } + curx -= posx; + if (curx) { + posx += curx; + vol = (int)curx * volume; + buf[0] += src[0] * vol; + } + src++; + } +} + +static void aamix16(RSZEX hdl, const UINT8 *src, int volume) { + + UINT *buf; + UINT posx; + int i; + UINT col; + int r, g, b; + UINT curx; + int vol; + + buf = hdl->buf; + posx = 0; + for (i=0; iorgx; i++) { + col = *(UINT16 *)src; + src += 2; + b = (col >> B16SFT) & ((1 << B16BIT) - 1); + g = (col >> G16SFT) & ((1 << G16BIT) - 1); + r = (col >> R16SFT) & ((1 << R16BIT) - 1); + curx = hdl->h[i]; + while((curx ^ posx) >> MXBITS) { + vol = (int)(MULTIX - (posx & MXMASK)) * volume; + buf[0] += b * vol; + buf[1] += g * vol; + buf[2] += r * vol; + buf += 3; + posx &= ~MXMASK; + posx += MULTIX; + } + curx -= posx; + if (curx) { + posx += curx; + vol = (int)curx * volume; + buf[0] += b * vol; + buf[1] += g * vol; + buf[2] += r * vol; + } + } +} + +static void aamix24(RSZEX hdl, const UINT8 *src, int volume) { + + UINT *buf; + UINT posx; + int i; + UINT curx; + int vol; + + buf = hdl->buf; + posx = 0; + for (i=0; iorgx; i++) { + curx = hdl->h[i]; + while((curx ^ posx) >> MXBITS) { + vol = (int)(MULTIX - (posx & MXMASK)) * volume; + buf[0] += (int)src[0] * vol; + buf[1] += (int)src[1] * vol; + buf[2] += (int)src[2] * vol; + buf += 3; + posx &= ~MXMASK; + posx += MULTIX; + } + curx -= posx; + if (curx) { + posx += curx; + vol = (int)curx * volume; + buf[0] += (int)src[0] * vol; + buf[1] += (int)src[1] * vol; + buf[2] += (int)src[2] * vol; + } + src += 3; + } +} + +static void aamix32(RSZEX hdl, const UINT8 *src, int volume) { + + UINT *buf; + UINT posx; + int i; + UINT curx; + int vol; + + buf = hdl->buf; + posx = 0; + for (i=0; iorgx; i++) { + curx = hdl->h[i]; + while((curx ^ posx) >> MXBITS) { + vol = (int)(MULTIX - (posx & MXMASK)) * volume; + buf[0] += (int)src[0] * vol; + buf[1] += (int)src[1] * vol; + buf[2] += (int)src[2] * vol; + buf += 4; + posx &= ~MXMASK; + posx += MULTIX; + } + curx -= posx; + if (curx) { + posx += curx; + vol = (int)curx * volume; + buf[0] += (int)src[0] * vol; + buf[1] += (int)src[1] * vol; + buf[2] += (int)src[2] * vol; + } + src += 4; + } +} + +static void aaout8(RSZEX hdl, UINT8 *dst) { + +const UINT *buf; + int rem; + + buf = hdl->buf; + rem = hdl->width; + do { + *dst++ = (UINT8)((*buf++) >> (MXBITS + MYBITS)); + } while(--rem); +} + +static void aaout16(RSZEX hdl, UINT8 *dst) { + +const UINT *buf; + int rem; + UINT tmp; + UINT col; + + buf = hdl->buf; + rem = hdl->width; + do { + tmp = buf[0] + (buf[0] >> (8 - B16BIT)); + col = (tmp >> (MXBITS + MYBITS - B16SFT)) & + (((1 << B16BIT) - 1) << B16SFT); + tmp = buf[1] + (buf[1] >> (8 - G16BIT)); + col += (tmp >> (MXBITS + MYBITS - G16SFT)) & + (((1 << G16BIT) - 1) << G16SFT); + tmp = buf[2] + (buf[2] >> (8 - R16BIT)); + col += (tmp >> (MXBITS + MYBITS - R16SFT)) & + (((1 << R16BIT) - 1) << R16SFT); + *(UINT16 *)dst = (UINT16)col; + dst += 2; + buf += 3; + } while(--rem); +} + +static void aaout24(RSZEX hdl, UINT8 *dst) { + +const UINT *buf; + int rem; + + buf = hdl->buf; + rem = hdl->width * 3; + do { + *dst++ = (UINT8)((*buf++) >> (MXBITS + MYBITS)); + } while(--rem); +} + +static void aaout32(RSZEX hdl, UINT8 *dst) { + +const UINT *buf; + int rem; + + buf = hdl->buf; + rem = hdl->width * 4; + do { + *dst++ = (UINT8)((*buf++) >> (MXBITS + MYBITS)); + } while(--rem); +} + +static void aaout16by24(RSZEX hdl, UINT8 *dst) { + +const UINT *buf; + int rem; + UINT col; + + buf = hdl->buf; + rem = hdl->width; + do { + col = (buf[0] >> (MXBITS + MYBITS + 8 - B16BIT - B16SFT)) & + (((1 << B16BIT) - 1) << B16SFT); + col += (buf[1] >> (MXBITS + MYBITS + 8 - G16BIT - G16SFT)) & + (((1 << G16BIT) - 1) << G16SFT); + col += (buf[2] >> (MXBITS + MYBITS + 8 - R16BIT - R16SFT)) & + (((1 << R16BIT) - 1) << R16SFT); + *(UINT16 *)dst = (UINT16)col; + dst += 2; + buf += 3; + } while(--rem); +} + +static void aaout16by32(RSZEX hdl, UINT8 *dst) { + +const UINT *buf; + int rem; + UINT col; + + buf = hdl->buf; + rem = hdl->width; + do { + col = (buf[0] >> (MXBITS + MYBITS + 8 - B16BIT - B16SFT)) & + (((1 << B16BIT) - 1) << B16SFT); + col += (buf[1] >> (MXBITS + MYBITS + 8 - G16BIT - G16SFT)) & + (((1 << G16BIT) - 1) << G16SFT); + col += (buf[2] >> (MXBITS + MYBITS + 8 - R16BIT - R16SFT)) & + (((1 << R16BIT) - 1) << R16SFT); + *(UINT16 *)dst = (UINT16)col; + dst += 2; + buf += 4; + } while(--rem); +} + +static void aaout24by16(RSZEX hdl, UINT8 *dst) { + +const UINT *buf; + int rem; + + buf = hdl->buf; + rem = hdl->width; + do { + dst[0] = (UINT8)(buf[0] >> (MXBITS + MYBITS - 8 + B16BIT)); + dst[1] = (UINT8)(buf[1] >> (MXBITS + MYBITS - 8 + G16BIT)); + dst[2] = (UINT8)(buf[2] >> (MXBITS + MYBITS - 8 + R16BIT)); + dst += 3; + buf += 3; + } while(--rem); +} + +static void aaout32by16(RSZEX hdl, UINT8 *dst) { + +const UINT *buf; + int rem; + + buf = hdl->buf; + rem = hdl->width; + do { + dst[0] = (UINT8)(buf[0] >> (MXBITS + MYBITS - 8 + B16BIT)); + dst[1] = (UINT8)(buf[1] >> (MXBITS + MYBITS - 8 + G16BIT)); + dst[2] = (UINT8)(buf[2] >> (MXBITS + MYBITS - 8 + R16BIT)); + dst += 4; + buf += 3; + } while(--rem); +} + +static void aaout32by24(RSZEX hdl, UINT8 *dst) { + +const UINT *buf; + int rem; + + buf = hdl->buf; + rem = hdl->width; + do { + dst[0] = buf[0] >> (UINT8)((MXBITS + MYBITS)); + dst[1] = buf[1] >> (UINT8)((MXBITS + MYBITS)); + dst[2] = buf[2] >> (UINT8)((MXBITS + MYBITS)); + dst += 4; + buf += 3; + } while(--rem); +} + +typedef void (*AAMIX)(RSZEX hdl, const UINT8 *src, int volume); +typedef void (*AAOUT)(RSZEX hdl, UINT8 *dst); + +static const AAMIX fnaamix[RSZFNMAX] = {aamix8, aamix16, aamix24, aamix32, + aamix24, aamix32, aamix16, aamix16, aamix24}; +static const AAOUT fnaaout[RSZFNMAX] = {aaout8, aaout16, aaout24, aaout32, + aaout16by24, aaout16by32, aaout24by16, aaout32by16, aaout32by24}; + +static void areaavefunc(RSZEX hdl, UINT type, UINT8 *dst, int dalign, + const UINT8 *src, int salign) { + + AAMIX aamix; + AAOUT aaout; + UINT posy; + UINT i; + UINT cury; + + if (type >= RSZFNMAX) { + return; + } + aamix = fnaamix[type]; + aaout = fnaaout[type]; + ZeroMemory(hdl->buf, hdl->bufsize); + posy = 0; + for (i=0; i<(UINT)hdl->orgy; i++) { + cury = (((i + 1) << MYBITS) * (UINT)hdl->height) / (UINT)hdl->orgy; + while((cury ^ posy) >> MYBITS) { + aamix(hdl, src, MULTIY - (posy & MYMASK)); + aaout(hdl, dst); + dst += dalign; + ZeroMemory(hdl->buf, hdl->bufsize); + posy &= ~MYMASK; + posy += MULTIY; + } + cury -= posy; + if (cury) { + posy += cury; + aamix(hdl, src, cury); + } + src += salign; + } +} + +static RSZHDL areaave(int width, int height, int orgx, int orgy) { + + UINT dstcnt; + UINT tbls; + RSZEX rszex; + UINT *ptr; + UINT i; + + dstcnt = width * 3; + tbls = orgx + orgy + dstcnt; + rszex = (RSZEX)_MALLOC(sizeof(_RSZEX) + (tbls * sizeof(UINT)), "RSZEX"); + if (rszex) { + rszex->func = (RSZFN)areaavefunc; + rszex->width = width; + rszex->height = height; + rszex->orgx = orgx; + rszex->orgy = orgy; + ptr = (UINT *)(rszex + 1); + rszex->h = ptr; + i = 0; + do { + i++; + *ptr++ = ((i << MXBITS) * (UINT)width) / (UINT)orgx; + } while(i < (UINT)orgx); + rszex->buf = ptr; + rszex->bufsize = dstcnt * sizeof(UINT); + } + return((RSZHDL)rszex); +} +#endif + + +// ---- + +UINT resize_gettype(int dbpp, int sbpp) { + + UINT ret; + + if (dbpp == 8) { + ret = RSZFN_8BPP; + } + else if (dbpp == 16) { + ret = (sbpp == 24)?RSZFN_16BY24:RSZFN_16BPP; + } + else if (dbpp == 24) { + ret = (sbpp == 16)?RSZFN_24BY16:RSZFN_24BPP; + } + else if (dbpp == 32) { + ret = (sbpp == 16)?RSZFN_32BY16:((sbpp == 24)?RSZFN_32BY24:RSZFN_32BPP); + } + else { + ret = RSZFNMAX; + } + if ((dbpp != sbpp) && (ret < RSZFN_16BY24)) { + ret = RSZFNMAX; + } + return(ret); +} + +RSZHDL resize(int xdst, int ydst, int xsrc, int ysrc) { + + UINT flag; + + flag = 0; + if ((xsrc <= 0) || (xdst <= 0)) { + goto rsz_err; + } + if (xsrc != xdst) { + flag += RESIZE_HDIF; + } + if ((ysrc <= 0) || (ydst <= 0)) { + goto rsz_err; + } + if (ysrc != ydst) { + flag += RESIZE_VDIF; + } +#if defined(RESIZE_FASTCOPY) + if (flag == 0) { + return(fastcopy(xdst, ydst)); + } +#endif +#if defined(RESIZE_AREAAVG) + return(areaave(xdst, ydst, xsrc, ysrc)); +#endif + +rsz_err: + return(NULL); +} + diff --git a/common/resize.h b/common/resize.h old mode 100755 new mode 100644 index f8f8c892..a9cf66fc --- a/common/resize.h +++ b/common/resize.h @@ -1,42 +1,42 @@ - -#define RESIZE_AREAAVG -#define RESIZE_FASTCOPY - -enum { - RSZFN_8BPP = 0, - RSZFN_16BPP, - RSZFN_24BPP, - RSZFN_32BPP, - RSZFN_16BY24, - RSZFN_16BY32, - RSZFN_24BY16, - RSZFN_32BY16, - RSZFN_32BY24, - RSZFNMAX -}; - -struct _rszhdl; -typedef struct _rszhdl _RSZHDL; -typedef struct _rszhdl *RSZHDL; - -typedef void (*RSZFN)(RSZHDL hdl, UINT type, UINT8 *dst, int dalign, - const UINT8 *src, int salign); - -struct _rszhdl { - RSZFN func; - int width; - int height; -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -UINT resize_gettype(int dbpp, int sbpp); -RSZHDL resize(int xdst, int ydst, int xsrc, int ysrc); - -#ifdef __cplusplus -} -#endif - + +#define RESIZE_AREAAVG +#define RESIZE_FASTCOPY + +enum { + RSZFN_8BPP = 0, + RSZFN_16BPP, + RSZFN_24BPP, + RSZFN_32BPP, + RSZFN_16BY24, + RSZFN_16BY32, + RSZFN_24BY16, + RSZFN_32BY16, + RSZFN_32BY24, + RSZFNMAX +}; + +struct _rszhdl; +typedef struct _rszhdl _RSZHDL; +typedef struct _rszhdl *RSZHDL; + +typedef void (*RSZFN)(RSZHDL hdl, UINT type, UINT8 *dst, int dalign, + const UINT8 *src, int salign); + +struct _rszhdl { + RSZFN func; + int width; + int height; +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +UINT resize_gettype(int dbpp, int sbpp); +RSZHDL resize(int xdst, int ydst, int xsrc, int ysrc); + +#ifdef __cplusplus +} +#endif + diff --git a/common/strres.c b/common/strres.c old mode 100755 new mode 100644 index ef87a551..a2451c5d --- a/common/strres.c +++ b/common/strres.c @@ -1,70 +1,70 @@ -#include -#include - - -const UINT8 str_utf8[3] = {0xef, 0xbb, 0xbf}; -const UINT16 str_ucs2[1] = {0xfeff}; - - -const OEMCHAR str_null[] = OEMTEXT(""); -const OEMCHAR str_space[] = OEMTEXT(" "); -const OEMCHAR str_dot[] = OEMTEXT("."); - -const OEMCHAR str_cr[] = OEMTEXT("\r"); -const OEMCHAR str_crlf[] = OEMTEXT("\r\n"); - -const OEMCHAR str_ini[] = OEMTEXT("ini"); -const OEMCHAR str_cfg[] = OEMTEXT("cfg"); -const OEMCHAR str_sav[] = OEMTEXT("sav"); -const OEMCHAR str_bmp[] = OEMTEXT("bmp"); -const OEMCHAR str_bmp_b[] = OEMTEXT("BMP"); -const OEMCHAR str_d88[] = OEMTEXT("d88"); -const OEMCHAR str_d98[] = OEMTEXT("d98"); -const OEMCHAR str_88d[] = OEMTEXT("88d"); -const OEMCHAR str_98d[] = OEMTEXT("98d"); -const OEMCHAR str_thd[] = OEMTEXT("thd"); -const OEMCHAR str_hdi[] = OEMTEXT("hdi"); -const OEMCHAR str_fdi[] = OEMTEXT("fdi"); -const OEMCHAR str_hdd[] = OEMTEXT("hdd"); -const OEMCHAR str_nhd[] = OEMTEXT("nhd"); -const OEMCHAR str_vhd[] = OEMTEXT("vhd"); -const OEMCHAR str_slh[] = OEMTEXT("slh"); -const OEMCHAR str_hdn[] = OEMTEXT("hdn"); -const OEMCHAR str_hds[] = OEMTEXT("hds"); -const OEMCHAR str_hdm[] = OEMTEXT("hdm"); -const OEMCHAR str_hd4[] = OEMTEXT("hd4"); - -const OEMCHAR str_d[] = OEMTEXT("%d"); -const OEMCHAR str_u[] = OEMTEXT("%u"); -#if defined(_MSC_VER) -const OEMCHAR str_lld[] = OEMTEXT("%I64d"); -const OEMCHAR str_llu[] = OEMTEXT("%I64u"); -#else -const OEMCHAR str_lld[] = OEMTEXT("%lld"); -const OEMCHAR str_llu[] = OEMTEXT("%llu"); -#endif -const OEMCHAR str_x[] = OEMTEXT("%x"); -const OEMCHAR str_2d[] = OEMTEXT("%.2d"); -const OEMCHAR str_2x[] = OEMTEXT("%.2x"); -const OEMCHAR str_4x[] = OEMTEXT("%.4x"); -const OEMCHAR str_4X[] = OEMTEXT("%.4X"); - -const OEMCHAR str_false[] = OEMTEXT("false"); -const OEMCHAR str_true[] = OEMTEXT("true"); - -const OEMCHAR str_posx[] = OEMTEXT("posx"); -const OEMCHAR str_posy[] = OEMTEXT("posy"); -const OEMCHAR str_width[] = OEMTEXT("width"); -const OEMCHAR str_height[] = OEMTEXT("height"); - -const OEMCHAR str_np2[] = OEMTEXT("Neko Project II kai"); -const OEMCHAR str_resume[] = OEMTEXT("Resume"); - -const OEMCHAR str_VM[] = OEMTEXT("VM"); -const OEMCHAR str_VX[] = OEMTEXT("VX"); -const OEMCHAR str_EPSON[] = OEMTEXT("EPSON"); - -const OEMCHAR str_biosrom[] = OEMTEXT("bios.rom"); -const OEMCHAR str_sasirom[] = OEMTEXT("sasi.rom"); -const OEMCHAR str_scsirom[] = OEMTEXT("scsi.rom"); - +#include +#include + + +const UINT8 str_utf8[3] = {0xef, 0xbb, 0xbf}; +const UINT16 str_ucs2[1] = {0xfeff}; + + +const OEMCHAR str_null[] = OEMTEXT(""); +const OEMCHAR str_space[] = OEMTEXT(" "); +const OEMCHAR str_dot[] = OEMTEXT("."); + +const OEMCHAR str_cr[] = OEMTEXT("\r"); +const OEMCHAR str_crlf[] = OEMTEXT("\r\n"); + +const OEMCHAR str_ini[] = OEMTEXT("ini"); +const OEMCHAR str_cfg[] = OEMTEXT("cfg"); +const OEMCHAR str_sav[] = OEMTEXT("sav"); +const OEMCHAR str_bmp[] = OEMTEXT("bmp"); +const OEMCHAR str_bmp_b[] = OEMTEXT("BMP"); +const OEMCHAR str_d88[] = OEMTEXT("d88"); +const OEMCHAR str_d98[] = OEMTEXT("d98"); +const OEMCHAR str_88d[] = OEMTEXT("88d"); +const OEMCHAR str_98d[] = OEMTEXT("98d"); +const OEMCHAR str_thd[] = OEMTEXT("thd"); +const OEMCHAR str_hdi[] = OEMTEXT("hdi"); +const OEMCHAR str_fdi[] = OEMTEXT("fdi"); +const OEMCHAR str_hdd[] = OEMTEXT("hdd"); +const OEMCHAR str_nhd[] = OEMTEXT("nhd"); +const OEMCHAR str_vhd[] = OEMTEXT("vhd"); +const OEMCHAR str_slh[] = OEMTEXT("slh"); +const OEMCHAR str_hdn[] = OEMTEXT("hdn"); +const OEMCHAR str_hds[] = OEMTEXT("hds"); +const OEMCHAR str_hdm[] = OEMTEXT("hdm"); +const OEMCHAR str_hd4[] = OEMTEXT("hd4"); + +const OEMCHAR str_d[] = OEMTEXT("%d"); +const OEMCHAR str_u[] = OEMTEXT("%u"); +#if defined(_MSC_VER) +const OEMCHAR str_lld[] = OEMTEXT("%I64d"); +const OEMCHAR str_llu[] = OEMTEXT("%I64u"); +#else +const OEMCHAR str_lld[] = OEMTEXT("%lld"); +const OEMCHAR str_llu[] = OEMTEXT("%llu"); +#endif +const OEMCHAR str_x[] = OEMTEXT("%x"); +const OEMCHAR str_2d[] = OEMTEXT("%.2d"); +const OEMCHAR str_2x[] = OEMTEXT("%.2x"); +const OEMCHAR str_4x[] = OEMTEXT("%.4x"); +const OEMCHAR str_4X[] = OEMTEXT("%.4X"); + +const OEMCHAR str_false[] = OEMTEXT("false"); +const OEMCHAR str_true[] = OEMTEXT("true"); + +const OEMCHAR str_posx[] = OEMTEXT("posx"); +const OEMCHAR str_posy[] = OEMTEXT("posy"); +const OEMCHAR str_width[] = OEMTEXT("width"); +const OEMCHAR str_height[] = OEMTEXT("height"); + +const OEMCHAR str_np2[] = OEMTEXT("Neko Project II kai"); +const OEMCHAR str_resume[] = OEMTEXT("Resume"); + +const OEMCHAR str_VM[] = OEMTEXT("VM"); +const OEMCHAR str_VX[] = OEMTEXT("VX"); +const OEMCHAR str_EPSON[] = OEMTEXT("EPSON"); + +const OEMCHAR str_biosrom[] = OEMTEXT("bios.rom"); +const OEMCHAR str_sasirom[] = OEMTEXT("sasi.rom"); +const OEMCHAR str_scsirom[] = OEMTEXT("scsi.rom"); + diff --git a/common/strres.h b/common/strres.h old mode 100755 new mode 100644 index adc3602d..a095fff2 --- a/common/strres.h +++ b/common/strres.h @@ -1,78 +1,78 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -extern const UINT8 str_utf8[3]; -extern const UINT16 str_ucs2[1]; - -extern const OEMCHAR str_null[]; -extern const OEMCHAR str_space[]; -extern const OEMCHAR str_dot[]; - -extern const OEMCHAR str_cr[]; -extern const OEMCHAR str_crlf[]; -#define str_lf (str_crlf + 1) - -#if defined(OSLINEBREAK_CR) -#define str_oscr str_cr -#elif defined(OSLINEBREAK_CRLF) -#define str_oscr str_crlf -#else -#define str_oscr str_lf -#endif - -extern const OEMCHAR str_ini[]; -extern const OEMCHAR str_cfg[]; -extern const OEMCHAR str_sav[]; -extern const OEMCHAR str_bmp[]; -extern const OEMCHAR str_bmp_b[]; -extern const OEMCHAR str_d88[]; -extern const OEMCHAR str_d98[]; -extern const OEMCHAR str_88d[]; -extern const OEMCHAR str_98d[]; -extern const OEMCHAR str_thd[]; -extern const OEMCHAR str_hdi[]; -extern const OEMCHAR str_fdi[]; -extern const OEMCHAR str_hdd[]; -extern const OEMCHAR str_nhd[]; -extern const OEMCHAR str_vhd[]; -extern const OEMCHAR str_slh[]; -extern const OEMCHAR str_hdn[]; -extern const OEMCHAR str_hds[]; -extern const OEMCHAR str_hdm[]; -extern const OEMCHAR str_hd4[]; - -extern const OEMCHAR str_d[]; -extern const OEMCHAR str_u[]; -extern const OEMCHAR str_lld[]; -extern const OEMCHAR str_llu[]; -extern const OEMCHAR str_x[]; -extern const OEMCHAR str_2d[]; -extern const OEMCHAR str_2x[]; -extern const OEMCHAR str_4x[]; -extern const OEMCHAR str_4X[]; - -extern const OEMCHAR str_false[]; -extern const OEMCHAR str_true[]; - -extern const OEMCHAR str_posx[]; -extern const OEMCHAR str_posy[]; -extern const OEMCHAR str_width[]; -extern const OEMCHAR str_height[]; - -extern const OEMCHAR str_np2[]; -extern const OEMCHAR str_resume[]; - -extern const OEMCHAR str_VM[]; -extern const OEMCHAR str_VX[]; -extern const OEMCHAR str_EPSON[]; - -extern const OEMCHAR str_biosrom[]; -extern const OEMCHAR str_sasirom[]; -extern const OEMCHAR str_scsirom[]; - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +extern const UINT8 str_utf8[3]; +extern const UINT16 str_ucs2[1]; + +extern const OEMCHAR str_null[]; +extern const OEMCHAR str_space[]; +extern const OEMCHAR str_dot[]; + +extern const OEMCHAR str_cr[]; +extern const OEMCHAR str_crlf[]; +#define str_lf (str_crlf + 1) + +#if defined(OSLINEBREAK_CR) +#define str_oscr str_cr +#elif defined(OSLINEBREAK_CRLF) +#define str_oscr str_crlf +#else +#define str_oscr str_lf +#endif + +extern const OEMCHAR str_ini[]; +extern const OEMCHAR str_cfg[]; +extern const OEMCHAR str_sav[]; +extern const OEMCHAR str_bmp[]; +extern const OEMCHAR str_bmp_b[]; +extern const OEMCHAR str_d88[]; +extern const OEMCHAR str_d98[]; +extern const OEMCHAR str_88d[]; +extern const OEMCHAR str_98d[]; +extern const OEMCHAR str_thd[]; +extern const OEMCHAR str_hdi[]; +extern const OEMCHAR str_fdi[]; +extern const OEMCHAR str_hdd[]; +extern const OEMCHAR str_nhd[]; +extern const OEMCHAR str_vhd[]; +extern const OEMCHAR str_slh[]; +extern const OEMCHAR str_hdn[]; +extern const OEMCHAR str_hds[]; +extern const OEMCHAR str_hdm[]; +extern const OEMCHAR str_hd4[]; + +extern const OEMCHAR str_d[]; +extern const OEMCHAR str_u[]; +extern const OEMCHAR str_lld[]; +extern const OEMCHAR str_llu[]; +extern const OEMCHAR str_x[]; +extern const OEMCHAR str_2d[]; +extern const OEMCHAR str_2x[]; +extern const OEMCHAR str_4x[]; +extern const OEMCHAR str_4X[]; + +extern const OEMCHAR str_false[]; +extern const OEMCHAR str_true[]; + +extern const OEMCHAR str_posx[]; +extern const OEMCHAR str_posy[]; +extern const OEMCHAR str_width[]; +extern const OEMCHAR str_height[]; + +extern const OEMCHAR str_np2[]; +extern const OEMCHAR str_resume[]; + +extern const OEMCHAR str_VM[]; +extern const OEMCHAR str_VX[]; +extern const OEMCHAR str_EPSON[]; + +extern const OEMCHAR str_biosrom[]; +extern const OEMCHAR str_sasirom[]; +extern const OEMCHAR str_scsirom[]; + +#ifdef __cplusplus +} +#endif + diff --git a/common/textfile.c b/common/textfile.c old mode 100755 new mode 100644 index f759267e..76301056 --- a/common/textfile.c +++ b/common/textfile.c @@ -1,589 +1,589 @@ -#include -#include -#include -#if defined(SUPPORT_TEXTCNV) -#include "codecnv/textcnv.h" -#endif -#include - - -// ---- arc support? - -#define _FILEH FILEH -#define _FILEH_INVALID FILEH_INVALID -#define _FSEEK_SET FSEEK_SET -#define _file_open_rb file_open_rb -#define _file_create file_create -#define _file_read file_read -#define _file_write file_write -#define _file_seek file_seek -#define _file_close file_close - -enum { - TFMODE_READ = 0x01, - TFMODE_WRITE = 0x02 -}; - -struct _textfile; -typedef struct _textfile _TEXTFILE; -typedef struct _textfile *TEXTFILE; - -typedef BRESULT (*READFN)(TEXTFILE tf, void *buffer, UINT size); - -struct _textfile { - UINT8 mode; - UINT8 width; -#if defined(SUPPORT_TEXTCNV) - UINT8 access; - UINT8 xendian; -#endif - _FILEH fh; - UINT64 fpos; - UINT8 *buf; - UINT bufsize; - UINT bufpos; - UINT bufrem; - READFN readfn; -#if defined(SUPPORT_TEXTCNV) - UINT8 *cnvbuf; - UINT cnvbufsize; - TCTOOEM tooem; - TCFROMOEM fromoem; -#endif -}; - - -// ---- ReadA - -static UINT readbufferA(TEXTFILE tf) { - - UINT rsize; - - if (tf->bufrem == 0) { - rsize = _file_read(tf->fh, tf->buf, tf->bufsize); - rsize = rsize / sizeof(char); - tf->fpos += rsize * sizeof(char); - tf->bufpos = 0; - tf->bufrem = rsize; - } - return(tf->bufrem); -} - -static BRESULT readlineA(TEXTFILE tf, void *buffer, UINT size) { - - char *dst; - BOOL crlf; - BRESULT ret; - char c; -const char *src; - UINT pos; - - if (size == 0) { - dst = NULL; - size = 0; - } - else { - dst = (char *)buffer; - size--; - } - - crlf = FALSE; - ret = FAILURE; - c = 0; - do { - if (readbufferA(tf) == 0) { - break; - } - ret = SUCCESS; - src = (char *)tf->buf; - src += tf->bufpos; - pos = 0; - while(posbufrem) { - c = src[pos]; - pos++; - if ((c == 0x0d) || (c == 0x0a)) { - crlf = TRUE; - break; - } - if (size) { - size--; - *dst++ = c; - } - } - tf->bufpos += pos; - tf->bufrem -= pos; - } while(!crlf); - if ((crlf) && (c == 0x0d)) { - if (readbufferA(tf) != 0) { - src = (char *)tf->buf; - src += tf->bufpos; - if (*src == 0x0a) { - tf->bufpos++; - tf->bufrem--; - } - } - } - if (dst) { - *dst = '\0'; - } - return(ret); -} - - -// ---- ReadW - -static UINT readbufferW(TEXTFILE tf) { - - UINT rsize; - UINT8 *buf; - - if (tf->bufrem == 0) { - buf = tf->buf; - rsize = _file_read(tf->fh, buf, tf->bufsize); - rsize = rsize / sizeof(UINT16); - tf->fpos += rsize * sizeof(UINT16); - tf->bufpos = 0; - tf->bufrem = rsize; -#if defined(SUPPORT_TEXTCNV) - if (tf->xendian) { - textcnv_swapendian16(buf, rsize); - } -#endif // defined(SUPPORT_TEXTCNV) - } - return(tf->bufrem); -} - -static BRESULT readlineW(TEXTFILE tf, void *buffer, UINT size) { - - UINT16 *dst; - BOOL crlf; - BRESULT ret; - UINT16 c; -const UINT16 *src; - UINT pos; - - if (size == 0) { - dst = NULL; - size = 0; - } - else { - dst = (UINT16 *)buffer; - size--; - } - crlf = FALSE; - ret = FAILURE; - c = 0; - do { - if (readbufferW(tf) == 0) { - break; - } - ret = SUCCESS; - src = (UINT16 *)tf->buf; - src += tf->bufpos; - pos = 0; - while(posbufrem) { - c = src[pos]; - pos++; - if ((c == 0x0d) || (c == 0x0a)) { - crlf = TRUE; - break; - } - if (size) { - size--; - *dst++ = c; - } - } - tf->bufpos += pos; - tf->bufrem -= pos; - } while(!crlf); - if ((crlf) && (c == 0x0d)) { - if (readbufferW(tf) != 0) { - src = (UINT16 *)tf->buf; - src += tf->bufpos; - if (*src == 0x0a) { - tf->bufpos++; - tf->bufrem--; - } - } - } - if (dst) { - *dst = '\0'; - } - return(ret); -} - - -// ---- read with convert - -#if defined(SUPPORT_TEXTCNV) -static BRESULT readlineAtoOEM(TEXTFILE tf, void *buffer, UINT size) { - - BRESULT ret; - - ret = readlineA(tf, tf->cnvbuf, tf->cnvbufsize); - if (ret == SUCCESS) { - (tf->tooem)((OEMCHAR *)buffer, size, tf->cnvbuf, (UINT)-1); - } - return(ret); -} - -static BRESULT readlineWtoOEM(TEXTFILE tf, void *buffer, UINT size) { - - BRESULT ret; - - ret = readlineW(tf, tf->cnvbuf, tf->cnvbufsize / 2); - if (ret == SUCCESS) { - (tf->tooem)((OEMCHAR *)buffer, size, tf->cnvbuf, (UINT)-1); - } - return(ret); -} -#endif // defined(SUPPORT_TEXTCNV) - - -// ---- write - -static BRESULT flushwritebuffer(TEXTFILE tf) { - - UINT size; - UINT wsize; - - if (tf->bufpos) { - size = tf->bufpos * tf->width; - wsize = _file_write(tf->fh, tf->buf, size); - tf->fpos += wsize; - if (wsize != size) { - return(FAILURE); - } - } - return(SUCCESS); -} - -static BRESULT writebufferA(TEXTFILE tf, const void *buffer, UINT size) { - - BRESULT ret; -const UINT8 *p; - UINT wsize; - - ret = SUCCESS; - p = (UINT8 *)buffer; - while(size) { - wsize = MIN(size, tf->bufrem); - if (wsize) { - CopyMemory(tf->buf + tf->bufpos, p, wsize); - p += wsize; - size -= wsize; - tf->bufpos += wsize; - tf->bufrem -= wsize; - } - if (tf->bufrem == 0) { - ret = flushwritebuffer(tf); - tf->bufpos = 0; - tf->bufrem = tf->bufsize / sizeof(char); - } - } - return(ret); -} - -static BRESULT writebufferW(TEXTFILE tf, const void *buffer, UINT size) { - - BRESULT ret; -const UINT8 *p; - UINT8 *q; - UINT wsize; - - ret = SUCCESS; - p = (UINT8 *)buffer; - while(size) { - wsize = MIN(size, tf->bufrem); - if (wsize) { - q = tf->buf + (tf->bufpos * sizeof(UINT16)); - CopyMemory(q, p, wsize * sizeof(UINT16)); -#if defined(SUPPORT_TEXTCNV) - if (tf->xendian) { - textcnv_swapendian16(q, wsize); - } -#endif // defined(SUPPORT_TEXTCNV) - p += wsize * sizeof(UINT16); - size -= wsize; - tf->bufpos += wsize; - tf->bufrem -= wsize; - } - if (tf->bufrem == 0) { - ret = flushwritebuffer(tf); - tf->bufpos = 0; - tf->bufrem = tf->bufsize / sizeof(UINT16); - } - } - return(ret); -} - - -// ---- - -static TEXTFILEH registfile(_FILEH fh, UINT buffersize, - const UINT8 *hdr, UINT hdrsize) { - - UINT cnvbufsize; -#if defined(SUPPORT_TEXTCNV) - TCINF inf; -#endif - long fpos; - UINT8 width; - READFN readfn; - TEXTFILE ret; - - buffersize = buffersize & (~3); - if (buffersize < 256) { - buffersize = 256; - } - cnvbufsize = 0; -#if defined(SUPPORT_TEXTCNV) - if (textcnv_getinfo(&inf, hdr, hdrsize) == 0) { - return(NULL); - } - fpos = inf.hdrsize; - width = inf.width; - if (inf.width == 1) { - readfn = (inf.tooem != NULL)?readlineAtoOEM:readlineA; - } - else if (inf.width == 2) { - buffersize = buffersize * 2; - readfn = (inf.tooem != NULL)?readlineWtoOEM:readlineW; - } - else { - return(NULL); - } - if ((inf.tooem != NULL) || (inf.fromoem != NULL)) { - cnvbufsize = buffersize; - } -#else // defined(SUPPORT_TEXTCNV) - fpos = 0; - width = 1; - if ((hdrsize >= 3) && - (hdr[0] == 0xef) && (hdr[1] == 0xbb) && (hdr[2] == 0xbf)) { - // UTF-8 - fpos = 3; - } - else if ((hdrsize >= 2) && (hdr[0] == 0xff) && (hdr[1] == 0xfe)) { - // UCSLE - fpos = 2; - width = 2; -#if defined(BYTESEX_BIG) - return(NULL); -#endif // defined(BYTESEX_BIG) - } - else if ((hdrsize >= 2) && (hdr[0] == 0xfe) && (hdr[1] == 0xff)) { - // UCS2BE - fpos = 2; - width = 2; -#if defined(BYTESEX_LITTLE) - return(NULL); -#endif // defined(BYTESEX_LITTLE) - } - if (width != sizeof(OEMCHAR)) { - return(NULL); - } - buffersize = buffersize * sizeof(OEMCHAR); - readfn = (width == 2)?readlineW:readlineA; -#endif // defined(SUPPORT_TEXTCNV) - - ret = (TEXTFILE)_MALLOC(sizeof(_TEXTFILE) + buffersize + cnvbufsize, - "TEXTFILE"); - if (ret == NULL) { - return(NULL); - } - ZeroMemory(ret, sizeof(_TEXTFILE)); -// ret->mode = 0; - ret->width = width; - ret->fh = fh; - ret->fpos = fpos; - ret->buf = (UINT8 *)(ret + 1); - ret->bufsize = buffersize; - ret->readfn = readfn; -#if defined(SUPPORT_TEXTCNV) - ret->access = inf.caps; - ret->xendian = inf.xendian; - ret->cnvbuf = ret->buf + buffersize; - ret->cnvbufsize = cnvbufsize; - ret->tooem = inf.tooem; - ret->fromoem = inf.fromoem; -#endif // defined(SUPPORT_TEXTCNV) - return((TEXTFILEH)ret); -} - -static BRESULT flushfile(TEXTFILE tf) { - - BRESULT ret; - UINT64 fpos; - UINT size; - UINT wsize; - - ret = SUCCESS; - if (tf->mode & TFMODE_READ) { - fpos = tf->fpos - (tf->bufrem * tf->width); - tf->fpos = _file_seek(tf->fh, fpos, _FSEEK_SET); - if (tf->fpos != fpos) { - ret = FAILURE; - } - } - else if (tf->mode & TFMODE_WRITE) { - if (tf->bufpos) { - size = tf->bufpos * tf->width; - wsize = _file_write(tf->fh, tf->buf, size); - if (wsize != size) { - ret = FAILURE; - } - tf->fpos += wsize; - } - } - else { - fpos = _file_seek(tf->fh, tf->fpos, _FSEEK_SET); - if (tf->fpos != fpos) { - ret = FAILURE; - } - tf->fpos = fpos; - } - tf->mode = 0; - tf->bufpos = 0; - tf->bufrem = 0; - return(ret); -} - - -// ---- - -TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize) { - - _FILEH fh; - UINT8 hdr[4]; - UINT hdrsize; - TEXTFILEH ret; - - fh = _file_open_rb(filename); - if (fh == _FILEH_INVALID) { - goto tfo_err; - } - hdrsize = _file_read(fh, hdr, sizeof(hdr)); - ret = registfile(fh, buffersize, hdr, hdrsize); - if (ret) { - return(ret); - } - _file_close(fh); - -tfo_err: - return(NULL); -} - -TEXTFILEH textfile_create(const OEMCHAR *filename, UINT buffersize) { - - _FILEH fh; -const UINT8 *hdr; - UINT hdrsize; - TEXTFILEH ret; - - fh = _file_create(filename); - if (fh == _FILEH_INVALID) { - goto tfc_err1; - } -#if defined(OSLANG_UTF8) - hdr = str_utf8; - hdrsize = sizeof(str_utf8); -#elif defined(OSLANG_UCS2) - hdr = (UINT8 *)str_ucs2; - hdrsize = sizeof(str_ucs2); -#else - hdr = NULL; - hdrsize = 0; -#endif - if ((hdrsize) && (_file_write(fh, hdr, hdrsize) != hdrsize)) { - goto tfc_err2; - } - ret = registfile(fh, buffersize, hdr, hdrsize); - if (ret) { - return(ret); - } - -tfc_err2: - _file_close(fh); - -tfc_err1: - return(NULL); -} - -BRESULT textfile_read(TEXTFILEH tfh, OEMCHAR *buffer, UINT size) { - - TEXTFILE tf; - - tf = (TEXTFILE)tfh; - if (tf == NULL) { - return(FAILURE); - } -#if defined(SUPPORT_TEXTCNV) - if (!(tf->access & TEXTCNV_READ)) { - return(FAILURE); - } -#endif // defined(SUPPORT_TEXTCNV) - if (!(tf->mode & TFMODE_READ)) { - flushfile(tf); - tf->mode = TFMODE_READ; - } - return((tf->readfn)(tf, buffer, size)); -} - -BRESULT textfile_write(TEXTFILEH tfh, const OEMCHAR *buffer) { - - TEXTFILE tf; -const void *buf; - UINT leng; - - tf = (TEXTFILE)tfh; - if (tf == NULL) { - return(FAILURE); - } -#if defined(SUPPORT_TEXTCNV) - if (!(tf->access & TEXTCNV_WRITE)) { - return(FAILURE); - } -#endif // defined(SUPPORT_TEXTCNV) - if (!(tf->mode & TFMODE_WRITE)) { - flushfile(tf); - tf->mode = TFMODE_WRITE; - } - leng = (UINT)OEMSTRLEN(buffer); -#if defined(SUPPORT_TEXTCNV) - if (tf->fromoem != NULL) { - leng = (tf->fromoem)(tf->cnvbuf, tf->cnvbufsize / tf->width, - buffer, leng); - buf = tf->cnvbuf; - } - else { - buf = buffer; - } -#else // defined(SUPPORT_TEXTCNV) - buf = buffer; -#endif // defined(SUPPORT_TEXTCNV) - if (tf->width == 1) { - return(writebufferA(tf, buf, leng)); - } - else if (tf->width == 2) { - return(writebufferW(tf, buf, leng)); - } - else { - return(FAILURE); - } -} - -void textfile_close(TEXTFILEH tfh) { - - TEXTFILE tf; - - tf = (TEXTFILE)tfh; - if (tf) { - if (tf->mode & TFMODE_WRITE) { - flushfile(tf); - } - _file_close(tf->fh); - _MFREE(tf); - } -} - +#include +#include +#include +#if defined(SUPPORT_TEXTCNV) +#include "codecnv/textcnv.h" +#endif +#include + + +// ---- arc support? + +#define _FILEH FILEH +#define _FILEH_INVALID FILEH_INVALID +#define _FSEEK_SET FSEEK_SET +#define _file_open_rb file_open_rb +#define _file_create file_create +#define _file_read file_read +#define _file_write file_write +#define _file_seek file_seek +#define _file_close file_close + +enum { + TFMODE_READ = 0x01, + TFMODE_WRITE = 0x02 +}; + +struct _textfile; +typedef struct _textfile _TEXTFILE; +typedef struct _textfile *TEXTFILE; + +typedef BRESULT (*READFN)(TEXTFILE tf, void *buffer, UINT size); + +struct _textfile { + UINT8 mode; + UINT8 width; +#if defined(SUPPORT_TEXTCNV) + UINT8 access; + UINT8 xendian; +#endif + _FILEH fh; + UINT64 fpos; + UINT8 *buf; + UINT bufsize; + UINT bufpos; + UINT bufrem; + READFN readfn; +#if defined(SUPPORT_TEXTCNV) + UINT8 *cnvbuf; + UINT cnvbufsize; + TCTOOEM tooem; + TCFROMOEM fromoem; +#endif +}; + + +// ---- ReadA + +static UINT readbufferA(TEXTFILE tf) { + + UINT rsize; + + if (tf->bufrem == 0) { + rsize = _file_read(tf->fh, tf->buf, tf->bufsize); + rsize = rsize / sizeof(char); + tf->fpos += rsize * sizeof(char); + tf->bufpos = 0; + tf->bufrem = rsize; + } + return(tf->bufrem); +} + +static BRESULT readlineA(TEXTFILE tf, void *buffer, UINT size) { + + char *dst; + BOOL crlf; + BRESULT ret; + char c; +const char *src; + UINT pos; + + if (size == 0) { + dst = NULL; + size = 0; + } + else { + dst = (char *)buffer; + size--; + } + + crlf = FALSE; + ret = FAILURE; + c = 0; + do { + if (readbufferA(tf) == 0) { + break; + } + ret = SUCCESS; + src = (char *)tf->buf; + src += tf->bufpos; + pos = 0; + while(posbufrem) { + c = src[pos]; + pos++; + if ((c == 0x0d) || (c == 0x0a)) { + crlf = TRUE; + break; + } + if (size) { + size--; + *dst++ = c; + } + } + tf->bufpos += pos; + tf->bufrem -= pos; + } while(!crlf); + if ((crlf) && (c == 0x0d)) { + if (readbufferA(tf) != 0) { + src = (char *)tf->buf; + src += tf->bufpos; + if (*src == 0x0a) { + tf->bufpos++; + tf->bufrem--; + } + } + } + if (dst) { + *dst = '\0'; + } + return(ret); +} + + +// ---- ReadW + +static UINT readbufferW(TEXTFILE tf) { + + UINT rsize; + UINT8 *buf; + + if (tf->bufrem == 0) { + buf = tf->buf; + rsize = _file_read(tf->fh, buf, tf->bufsize); + rsize = rsize / sizeof(UINT16); + tf->fpos += rsize * sizeof(UINT16); + tf->bufpos = 0; + tf->bufrem = rsize; +#if defined(SUPPORT_TEXTCNV) + if (tf->xendian) { + textcnv_swapendian16(buf, rsize); + } +#endif // defined(SUPPORT_TEXTCNV) + } + return(tf->bufrem); +} + +static BRESULT readlineW(TEXTFILE tf, void *buffer, UINT size) { + + UINT16 *dst; + BOOL crlf; + BRESULT ret; + UINT16 c; +const UINT16 *src; + UINT pos; + + if (size == 0) { + dst = NULL; + size = 0; + } + else { + dst = (UINT16 *)buffer; + size--; + } + crlf = FALSE; + ret = FAILURE; + c = 0; + do { + if (readbufferW(tf) == 0) { + break; + } + ret = SUCCESS; + src = (UINT16 *)tf->buf; + src += tf->bufpos; + pos = 0; + while(posbufrem) { + c = src[pos]; + pos++; + if ((c == 0x0d) || (c == 0x0a)) { + crlf = TRUE; + break; + } + if (size) { + size--; + *dst++ = c; + } + } + tf->bufpos += pos; + tf->bufrem -= pos; + } while(!crlf); + if ((crlf) && (c == 0x0d)) { + if (readbufferW(tf) != 0) { + src = (UINT16 *)tf->buf; + src += tf->bufpos; + if (*src == 0x0a) { + tf->bufpos++; + tf->bufrem--; + } + } + } + if (dst) { + *dst = '\0'; + } + return(ret); +} + + +// ---- read with convert + +#if defined(SUPPORT_TEXTCNV) +static BRESULT readlineAtoOEM(TEXTFILE tf, void *buffer, UINT size) { + + BRESULT ret; + + ret = readlineA(tf, tf->cnvbuf, tf->cnvbufsize); + if (ret == SUCCESS) { + (tf->tooem)((OEMCHAR *)buffer, size, tf->cnvbuf, (UINT)-1); + } + return(ret); +} + +static BRESULT readlineWtoOEM(TEXTFILE tf, void *buffer, UINT size) { + + BRESULT ret; + + ret = readlineW(tf, tf->cnvbuf, tf->cnvbufsize / 2); + if (ret == SUCCESS) { + (tf->tooem)((OEMCHAR *)buffer, size, tf->cnvbuf, (UINT)-1); + } + return(ret); +} +#endif // defined(SUPPORT_TEXTCNV) + + +// ---- write + +static BRESULT flushwritebuffer(TEXTFILE tf) { + + UINT size; + UINT wsize; + + if (tf->bufpos) { + size = tf->bufpos * tf->width; + wsize = _file_write(tf->fh, tf->buf, size); + tf->fpos += wsize; + if (wsize != size) { + return(FAILURE); + } + } + return(SUCCESS); +} + +static BRESULT writebufferA(TEXTFILE tf, const void *buffer, UINT size) { + + BRESULT ret; +const UINT8 *p; + UINT wsize; + + ret = SUCCESS; + p = (UINT8 *)buffer; + while(size) { + wsize = MIN(size, tf->bufrem); + if (wsize) { + CopyMemory(tf->buf + tf->bufpos, p, wsize); + p += wsize; + size -= wsize; + tf->bufpos += wsize; + tf->bufrem -= wsize; + } + if (tf->bufrem == 0) { + ret = flushwritebuffer(tf); + tf->bufpos = 0; + tf->bufrem = tf->bufsize / sizeof(char); + } + } + return(ret); +} + +static BRESULT writebufferW(TEXTFILE tf, const void *buffer, UINT size) { + + BRESULT ret; +const UINT8 *p; + UINT8 *q; + UINT wsize; + + ret = SUCCESS; + p = (UINT8 *)buffer; + while(size) { + wsize = MIN(size, tf->bufrem); + if (wsize) { + q = tf->buf + (tf->bufpos * sizeof(UINT16)); + CopyMemory(q, p, wsize * sizeof(UINT16)); +#if defined(SUPPORT_TEXTCNV) + if (tf->xendian) { + textcnv_swapendian16(q, wsize); + } +#endif // defined(SUPPORT_TEXTCNV) + p += wsize * sizeof(UINT16); + size -= wsize; + tf->bufpos += wsize; + tf->bufrem -= wsize; + } + if (tf->bufrem == 0) { + ret = flushwritebuffer(tf); + tf->bufpos = 0; + tf->bufrem = tf->bufsize / sizeof(UINT16); + } + } + return(ret); +} + + +// ---- + +static TEXTFILEH registfile(_FILEH fh, UINT buffersize, + const UINT8 *hdr, UINT hdrsize) { + + UINT cnvbufsize; +#if defined(SUPPORT_TEXTCNV) + TCINF inf; +#endif + long fpos; + UINT8 width; + READFN readfn; + TEXTFILE ret; + + buffersize = buffersize & (~3); + if (buffersize < 256) { + buffersize = 256; + } + cnvbufsize = 0; +#if defined(SUPPORT_TEXTCNV) + if (textcnv_getinfo(&inf, hdr, hdrsize) == 0) { + return(NULL); + } + fpos = inf.hdrsize; + width = inf.width; + if (inf.width == 1) { + readfn = (inf.tooem != NULL)?readlineAtoOEM:readlineA; + } + else if (inf.width == 2) { + buffersize = buffersize * 2; + readfn = (inf.tooem != NULL)?readlineWtoOEM:readlineW; + } + else { + return(NULL); + } + if ((inf.tooem != NULL) || (inf.fromoem != NULL)) { + cnvbufsize = buffersize; + } +#else // defined(SUPPORT_TEXTCNV) + fpos = 0; + width = 1; + if ((hdrsize >= 3) && + (hdr[0] == 0xef) && (hdr[1] == 0xbb) && (hdr[2] == 0xbf)) { + // UTF-8 + fpos = 3; + } + else if ((hdrsize >= 2) && (hdr[0] == 0xff) && (hdr[1] == 0xfe)) { + // UCSLE + fpos = 2; + width = 2; +#if defined(BYTESEX_BIG) + return(NULL); +#endif // defined(BYTESEX_BIG) + } + else if ((hdrsize >= 2) && (hdr[0] == 0xfe) && (hdr[1] == 0xff)) { + // UCS2BE + fpos = 2; + width = 2; +#if defined(BYTESEX_LITTLE) + return(NULL); +#endif // defined(BYTESEX_LITTLE) + } + if (width != sizeof(OEMCHAR)) { + return(NULL); + } + buffersize = buffersize * sizeof(OEMCHAR); + readfn = (width == 2)?readlineW:readlineA; +#endif // defined(SUPPORT_TEXTCNV) + + ret = (TEXTFILE)_MALLOC(sizeof(_TEXTFILE) + buffersize + cnvbufsize, + "TEXTFILE"); + if (ret == NULL) { + return(NULL); + } + ZeroMemory(ret, sizeof(_TEXTFILE)); +// ret->mode = 0; + ret->width = width; + ret->fh = fh; + ret->fpos = fpos; + ret->buf = (UINT8 *)(ret + 1); + ret->bufsize = buffersize; + ret->readfn = readfn; +#if defined(SUPPORT_TEXTCNV) + ret->access = inf.caps; + ret->xendian = inf.xendian; + ret->cnvbuf = ret->buf + buffersize; + ret->cnvbufsize = cnvbufsize; + ret->tooem = inf.tooem; + ret->fromoem = inf.fromoem; +#endif // defined(SUPPORT_TEXTCNV) + return((TEXTFILEH)ret); +} + +static BRESULT flushfile(TEXTFILE tf) { + + BRESULT ret; + UINT64 fpos; + UINT size; + UINT wsize; + + ret = SUCCESS; + if (tf->mode & TFMODE_READ) { + fpos = tf->fpos - (tf->bufrem * tf->width); + tf->fpos = _file_seek(tf->fh, fpos, _FSEEK_SET); + if (tf->fpos != fpos) { + ret = FAILURE; + } + } + else if (tf->mode & TFMODE_WRITE) { + if (tf->bufpos) { + size = tf->bufpos * tf->width; + wsize = _file_write(tf->fh, tf->buf, size); + if (wsize != size) { + ret = FAILURE; + } + tf->fpos += wsize; + } + } + else { + fpos = _file_seek(tf->fh, tf->fpos, _FSEEK_SET); + if (tf->fpos != fpos) { + ret = FAILURE; + } + tf->fpos = fpos; + } + tf->mode = 0; + tf->bufpos = 0; + tf->bufrem = 0; + return(ret); +} + + +// ---- + +TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize) { + + _FILEH fh; + UINT8 hdr[4]; + UINT hdrsize; + TEXTFILEH ret; + + fh = _file_open_rb(filename); + if (fh == _FILEH_INVALID) { + goto tfo_err; + } + hdrsize = _file_read(fh, hdr, sizeof(hdr)); + ret = registfile(fh, buffersize, hdr, hdrsize); + if (ret) { + return(ret); + } + _file_close(fh); + +tfo_err: + return(NULL); +} + +TEXTFILEH textfile_create(const OEMCHAR *filename, UINT buffersize) { + + _FILEH fh; +const UINT8 *hdr; + UINT hdrsize; + TEXTFILEH ret; + + fh = _file_create(filename); + if (fh == _FILEH_INVALID) { + goto tfc_err1; + } +#if defined(OSLANG_UTF8) + hdr = str_utf8; + hdrsize = sizeof(str_utf8); +#elif defined(OSLANG_UCS2) + hdr = (UINT8 *)str_ucs2; + hdrsize = sizeof(str_ucs2); +#else + hdr = NULL; + hdrsize = 0; +#endif + if ((hdrsize) && (_file_write(fh, hdr, hdrsize) != hdrsize)) { + goto tfc_err2; + } + ret = registfile(fh, buffersize, hdr, hdrsize); + if (ret) { + return(ret); + } + +tfc_err2: + _file_close(fh); + +tfc_err1: + return(NULL); +} + +BRESULT textfile_read(TEXTFILEH tfh, OEMCHAR *buffer, UINT size) { + + TEXTFILE tf; + + tf = (TEXTFILE)tfh; + if (tf == NULL) { + return(FAILURE); + } +#if defined(SUPPORT_TEXTCNV) + if (!(tf->access & TEXTCNV_READ)) { + return(FAILURE); + } +#endif // defined(SUPPORT_TEXTCNV) + if (!(tf->mode & TFMODE_READ)) { + flushfile(tf); + tf->mode = TFMODE_READ; + } + return((tf->readfn)(tf, buffer, size)); +} + +BRESULT textfile_write(TEXTFILEH tfh, const OEMCHAR *buffer) { + + TEXTFILE tf; +const void *buf; + UINT leng; + + tf = (TEXTFILE)tfh; + if (tf == NULL) { + return(FAILURE); + } +#if defined(SUPPORT_TEXTCNV) + if (!(tf->access & TEXTCNV_WRITE)) { + return(FAILURE); + } +#endif // defined(SUPPORT_TEXTCNV) + if (!(tf->mode & TFMODE_WRITE)) { + flushfile(tf); + tf->mode = TFMODE_WRITE; + } + leng = (UINT)OEMSTRLEN(buffer); +#if defined(SUPPORT_TEXTCNV) + if (tf->fromoem != NULL) { + leng = (tf->fromoem)(tf->cnvbuf, tf->cnvbufsize / tf->width, + buffer, leng); + buf = tf->cnvbuf; + } + else { + buf = buffer; + } +#else // defined(SUPPORT_TEXTCNV) + buf = buffer; +#endif // defined(SUPPORT_TEXTCNV) + if (tf->width == 1) { + return(writebufferA(tf, buf, leng)); + } + else if (tf->width == 2) { + return(writebufferW(tf, buf, leng)); + } + else { + return(FAILURE); + } +} + +void textfile_close(TEXTFILEH tfh) { + + TEXTFILE tf; + + tf = (TEXTFILE)tfh; + if (tf) { + if (tf->mode & TFMODE_WRITE) { + flushfile(tf); + } + _file_close(tf->fh); + _MFREE(tf); + } +} + diff --git a/common/textfile.h b/common/textfile.h old mode 100755 new mode 100644 index acdbb49d..7967ad5f --- a/common/textfile.h +++ b/common/textfile.h @@ -1,17 +1,17 @@ - -typedef void *TEXTFILEH; - -#ifdef __cplusplus -extern "C" { -#endif - -TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize); -TEXTFILEH textfile_create(const OEMCHAR *filename, UINT buffersize); -BRESULT textfile_read(TEXTFILEH fh, OEMCHAR *buffer, UINT size); -BRESULT textfile_write(TEXTFILEH fh, const OEMCHAR *buffer); -void textfile_close(TEXTFILEH fh); - -#ifdef __cplusplus -} -#endif - + +typedef void *TEXTFILEH; + +#ifdef __cplusplus +extern "C" { +#endif + +TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize); +TEXTFILEH textfile_create(const OEMCHAR *filename, UINT buffersize); +BRESULT textfile_read(TEXTFILEH fh, OEMCHAR *buffer, UINT size); +BRESULT textfile_write(TEXTFILEH fh, const OEMCHAR *buffer); +void textfile_close(TEXTFILEH fh); + +#ifdef __cplusplus +} +#endif + diff --git a/common/wavefile.c b/common/wavefile.c old mode 100755 new mode 100644 index ade5ccfe..27a2079a --- a/common/wavefile.c +++ b/common/wavefile.c @@ -1,256 +1,256 @@ -/** - * @file wavefile.c - * @brief Implementation of wave file - */ - -#include -#include -#include - -#if !defined(WAVE_FORMAT_PCM) -#define WAVE_FORMAT_PCM 1 /*!< PCM */ -#endif /* !defined(WAVE_FORMAT_PCM) */ - -#if defined(BYTESEX_BIG) -#define MAKEID(a, b, c, d) (UINT32)((d) | ((c) << 8) | ((b) << 16) | ((a) << 24)) /*!< FOURCCs */ -#else -#define MAKEID(a, b, c, d) (UINT32)((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) /*!< FOURCCs */ -#endif - -#pragma pack(push, 1) - -/** - * @brief RIFF chunk - */ -struct TagRiffChunk -{ - UINT32 riff; /*!< 'RIFF' */ - UINT8 fileSize[4]; /*!< fileSize */ - UINT32 fileType; /*!< fileType */ -}; - -/** - * @brief chunk - */ -struct tagChunk -{ - UINT32 id; /*!< chunkID */ - UINT8 size[4]; /*!< chunkSize */ -}; - -/** - * @brief WAVEFORMAT structure - */ -struct TagWaveFormat -{ - UINT8 formatTag[2]; /*!< Format type */ - UINT8 channels[2]; /*!< Number of channels */ - UINT8 samplePerSec[4]; /*!< Sample rate */ - UINT8 avgBytesPerSec[4]; /*!< Required average data transfer rate */ - UINT8 blockAlign[2]; /*!< Block alignment */ - UINT8 bitsPerSample[2]; /*!< Bits per sample */ -}; - -#pragma pack(pop) - -/** - * @brief The informations of wave - */ -struct TagWaveFile -{ - FILEH fh; /*!< The handle of file */ - UINT nRate; /*!< The sampling rate */ - UINT nBits; /*!< The bits of the sample */ - UINT nChannels; /*!< The number of the channel */ - - UINT nDataSize; /*!< The size of the file */ - UINT8* lpCurrent; /*!< The current */ - UINT nRemain; /*!< The remain of the buffer */ - UINT8 buffer[4096]; /*!< The buffer */ -}; - -/** - * Write the header - * @param[in] hWave The handle of wave - * @retval SUCCESS If succeeded - * @retval FAILURE If failed - */ -static BRESULT WriteHeader(WAVEFILEH hWave) -{ - struct TagRiffChunk riff; - struct tagChunk chunk; - struct TagWaveFormat format; - UINT nFileSize; - UINT nBlockAlign; - UINT nAvgBytesPerSec; - - nFileSize = hWave->nDataSize; - nFileSize += 4 + sizeof(chunk) + sizeof(format) + sizeof(chunk); - - riff.riff = MAKEID('R', 'I', 'F', 'F'); - STOREINTELDWORD(riff.fileSize, nFileSize); - riff.fileType = MAKEID('W', 'A', 'V', 'E'); - if (file_write(hWave->fh, &riff, sizeof(riff)) != sizeof(riff)) - { - return FAILURE; - } - - chunk.id = MAKEID('f', 'm', 't', ' '); - STOREINTELDWORD(chunk.size, sizeof(format)); - if (file_write(hWave->fh, &chunk, sizeof(chunk)) != sizeof(chunk)) - { - return FAILURE; - } - - nBlockAlign = hWave->nChannels * (hWave->nBits / 8); - nAvgBytesPerSec = nBlockAlign * hWave->nRate; - STOREINTELWORD(format.formatTag, WAVE_FORMAT_PCM); - STOREINTELWORD(format.channels, hWave->nChannels); - STOREINTELDWORD(format.samplePerSec, hWave->nRate); - STOREINTELDWORD(format.avgBytesPerSec, nAvgBytesPerSec); - STOREINTELWORD(format.blockAlign, nBlockAlign); - STOREINTELWORD(format.bitsPerSample, hWave->nBits); - if (file_write(hWave->fh, &format, sizeof(format)) != sizeof(format)) - { - return FAILURE; - } - - chunk.id = MAKEID('d', 'a', 't', 'a'); - STOREINTELDWORD(chunk.size, hWave->nDataSize); - if (file_write(hWave->fh, &chunk, sizeof(chunk)) != sizeof(chunk)) - { - return FAILURE; - } - return SUCCESS; -} - -/** - * Flash - * @param[in] hWave The handle of wave - */ -static void FlashBuffer(WAVEFILEH hWave) -{ - UINT nSize; - - nSize = (UINT)(hWave->lpCurrent - hWave->buffer); - if (nSize) - { - hWave->nDataSize += file_write(hWave->fh, hWave->buffer, nSize); - } - hWave->lpCurrent = hWave->buffer; - hWave->nRemain = sizeof(hWave->buffer); -} - -/** - * Creates - * @param[in] lpFilename The filename - * @param[in] nRate The sampling rate - * @param[in] nBits The bits of the sample - * @param[in] nChannels The number of the channels - * @return The handle of wave - */ -WAVEFILEH wavefile_create(const OEMCHAR *lpFilename, UINT nRate, UINT nBits, UINT nChannels) -{ - FILEH fh = FILEH_INVALID; - WAVEFILEH hWave = NULL; - - do - { - if (lpFilename == NULL) - { - break; - } - if (nRate == 0) - { - break; - } - if ((nBits != 8) && (nBits != 16)) - { - break; - } - if ((nChannels != 1) && (nChannels != 2)) - { - break; - } - - fh = file_create(lpFilename); - if (fh == FILEH_INVALID) - { - break; - } - - hWave = (WAVEFILEH)_MALLOC(sizeof(*hWave), "WAVEFILEH"); - if (hWave == NULL) - { - break; - } - - memset(hWave, 0, sizeof(*hWave)); - hWave->fh = fh; - hWave->nRate = nRate; - hWave->nBits = nBits; - hWave->nChannels = nChannels; - if (WriteHeader(hWave) != SUCCESS) - { - break; - } - hWave->lpCurrent = hWave->buffer; - hWave->nRemain = sizeof(hWave->buffer); - return hWave; - } while (FALSE /*CONSTCOND*/); - - if (hWave) - { - _MFREE(hWave); - } - if (fh != FILEH_INVALID) - { - file_close(fh); - } - return NULL; -} - -/** - * Write - * @param[in] hWave The handle of wave - * @param[in] lpBuffer The buffer - * @param[in] cbBuffer The size of the buffer - * @return The written size - */ -UINT wavefile_write(WAVEFILEH hWave, const void *lpBuffer, UINT cbBuffer) -{ - if (hWave == NULL) - { - return 0; - } - while (cbBuffer) - { - UINT nSize = MIN(hWave->nRemain, cbBuffer); - memcpy(hWave->lpCurrent, lpBuffer, nSize); - lpBuffer = ((UINT8 *)lpBuffer) + nSize; - cbBuffer -= nSize; - hWave->lpCurrent += nSize; - hWave->nRemain -= nSize; - if (hWave->nRemain == 0) - { - FlashBuffer(hWave); - } - } - return 0; -} - -/** - * Close - * @param[in] hWave The handle of wave - */ -void wavefile_close(WAVEFILEH hWave) -{ - if (hWave) - { - FlashBuffer(hWave); - file_seek(hWave->fh, 0, FSEEK_SET); - WriteHeader(hWave); - file_close(hWave->fh); - _MFREE(hWave); - } -} +/** + * @file wavefile.c + * @brief Implementation of wave file + */ + +#include +#include +#include + +#if !defined(WAVE_FORMAT_PCM) +#define WAVE_FORMAT_PCM 1 /*!< PCM */ +#endif /* !defined(WAVE_FORMAT_PCM) */ + +#if defined(BYTESEX_BIG) +#define MAKEID(a, b, c, d) (UINT32)((d) | ((c) << 8) | ((b) << 16) | ((a) << 24)) /*!< FOURCCs */ +#else +#define MAKEID(a, b, c, d) (UINT32)((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) /*!< FOURCCs */ +#endif + +#pragma pack(push, 1) + +/** + * @brief RIFF chunk + */ +struct TagRiffChunk +{ + UINT32 riff; /*!< 'RIFF' */ + UINT8 fileSize[4]; /*!< fileSize */ + UINT32 fileType; /*!< fileType */ +}; + +/** + * @brief chunk + */ +struct tagChunk +{ + UINT32 id; /*!< chunkID */ + UINT8 size[4]; /*!< chunkSize */ +}; + +/** + * @brief WAVEFORMAT structure + */ +struct TagWaveFormat +{ + UINT8 formatTag[2]; /*!< Format type */ + UINT8 channels[2]; /*!< Number of channels */ + UINT8 samplePerSec[4]; /*!< Sample rate */ + UINT8 avgBytesPerSec[4]; /*!< Required average data transfer rate */ + UINT8 blockAlign[2]; /*!< Block alignment */ + UINT8 bitsPerSample[2]; /*!< Bits per sample */ +}; + +#pragma pack(pop) + +/** + * @brief The informations of wave + */ +struct TagWaveFile +{ + FILEH fh; /*!< The handle of file */ + UINT nRate; /*!< The sampling rate */ + UINT nBits; /*!< The bits of the sample */ + UINT nChannels; /*!< The number of the channel */ + + UINT nDataSize; /*!< The size of the file */ + UINT8* lpCurrent; /*!< The current */ + UINT nRemain; /*!< The remain of the buffer */ + UINT8 buffer[4096]; /*!< The buffer */ +}; + +/** + * Write the header + * @param[in] hWave The handle of wave + * @retval SUCCESS If succeeded + * @retval FAILURE If failed + */ +static BRESULT WriteHeader(WAVEFILEH hWave) +{ + struct TagRiffChunk riff; + struct tagChunk chunk; + struct TagWaveFormat format; + UINT nFileSize; + UINT nBlockAlign; + UINT nAvgBytesPerSec; + + nFileSize = hWave->nDataSize; + nFileSize += 4 + sizeof(chunk) + sizeof(format) + sizeof(chunk); + + riff.riff = MAKEID('R', 'I', 'F', 'F'); + STOREINTELDWORD(riff.fileSize, nFileSize); + riff.fileType = MAKEID('W', 'A', 'V', 'E'); + if (file_write(hWave->fh, &riff, sizeof(riff)) != sizeof(riff)) + { + return FAILURE; + } + + chunk.id = MAKEID('f', 'm', 't', ' '); + STOREINTELDWORD(chunk.size, sizeof(format)); + if (file_write(hWave->fh, &chunk, sizeof(chunk)) != sizeof(chunk)) + { + return FAILURE; + } + + nBlockAlign = hWave->nChannels * (hWave->nBits / 8); + nAvgBytesPerSec = nBlockAlign * hWave->nRate; + STOREINTELWORD(format.formatTag, WAVE_FORMAT_PCM); + STOREINTELWORD(format.channels, hWave->nChannels); + STOREINTELDWORD(format.samplePerSec, hWave->nRate); + STOREINTELDWORD(format.avgBytesPerSec, nAvgBytesPerSec); + STOREINTELWORD(format.blockAlign, nBlockAlign); + STOREINTELWORD(format.bitsPerSample, hWave->nBits); + if (file_write(hWave->fh, &format, sizeof(format)) != sizeof(format)) + { + return FAILURE; + } + + chunk.id = MAKEID('d', 'a', 't', 'a'); + STOREINTELDWORD(chunk.size, hWave->nDataSize); + if (file_write(hWave->fh, &chunk, sizeof(chunk)) != sizeof(chunk)) + { + return FAILURE; + } + return SUCCESS; +} + +/** + * Flash + * @param[in] hWave The handle of wave + */ +static void FlashBuffer(WAVEFILEH hWave) +{ + UINT nSize; + + nSize = (UINT)(hWave->lpCurrent - hWave->buffer); + if (nSize) + { + hWave->nDataSize += file_write(hWave->fh, hWave->buffer, nSize); + } + hWave->lpCurrent = hWave->buffer; + hWave->nRemain = sizeof(hWave->buffer); +} + +/** + * Creates + * @param[in] lpFilename The filename + * @param[in] nRate The sampling rate + * @param[in] nBits The bits of the sample + * @param[in] nChannels The number of the channels + * @return The handle of wave + */ +WAVEFILEH wavefile_create(const OEMCHAR *lpFilename, UINT nRate, UINT nBits, UINT nChannels) +{ + FILEH fh = FILEH_INVALID; + WAVEFILEH hWave = NULL; + + do + { + if (lpFilename == NULL) + { + break; + } + if (nRate == 0) + { + break; + } + if ((nBits != 8) && (nBits != 16)) + { + break; + } + if ((nChannels != 1) && (nChannels != 2)) + { + break; + } + + fh = file_create(lpFilename); + if (fh == FILEH_INVALID) + { + break; + } + + hWave = (WAVEFILEH)_MALLOC(sizeof(*hWave), "WAVEFILEH"); + if (hWave == NULL) + { + break; + } + + memset(hWave, 0, sizeof(*hWave)); + hWave->fh = fh; + hWave->nRate = nRate; + hWave->nBits = nBits; + hWave->nChannels = nChannels; + if (WriteHeader(hWave) != SUCCESS) + { + break; + } + hWave->lpCurrent = hWave->buffer; + hWave->nRemain = sizeof(hWave->buffer); + return hWave; + } while (FALSE /*CONSTCOND*/); + + if (hWave) + { + _MFREE(hWave); + } + if (fh != FILEH_INVALID) + { + file_close(fh); + } + return NULL; +} + +/** + * Write + * @param[in] hWave The handle of wave + * @param[in] lpBuffer The buffer + * @param[in] cbBuffer The size of the buffer + * @return The written size + */ +UINT wavefile_write(WAVEFILEH hWave, const void *lpBuffer, UINT cbBuffer) +{ + if (hWave == NULL) + { + return 0; + } + while (cbBuffer) + { + UINT nSize = MIN(hWave->nRemain, cbBuffer); + memcpy(hWave->lpCurrent, lpBuffer, nSize); + lpBuffer = ((UINT8 *)lpBuffer) + nSize; + cbBuffer -= nSize; + hWave->lpCurrent += nSize; + hWave->nRemain -= nSize; + if (hWave->nRemain == 0) + { + FlashBuffer(hWave); + } + } + return 0; +} + +/** + * Close + * @param[in] hWave The handle of wave + */ +void wavefile_close(WAVEFILEH hWave) +{ + if (hWave) + { + FlashBuffer(hWave); + file_seek(hWave->fh, 0, FSEEK_SET); + WriteHeader(hWave); + file_close(hWave->fh); + _MFREE(hWave); + } +} diff --git a/common/wavefile.h b/common/wavefile.h old mode 100755 new mode 100644 index 1c1b4787..bd115cc4 --- a/common/wavefile.h +++ b/common/wavefile.h @@ -1,21 +1,21 @@ -/** - * @file wavefile.h - * @brief Interface of wave file - */ - -#pragma once - -typedef struct TagWaveFile *WAVEFILEH; /*!< Defines handle */ - -#ifdef __cplusplus -extern "C" -{ -#endif - -WAVEFILEH wavefile_create(const OEMCHAR *lpFilename, UINT nRate, UINT nBits, UINT nChannels); -UINT wavefile_write(WAVEFILEH hWave, const void *lpBuffer, UINT cbBuffer); -void wavefile_close(WAVEFILEH hWave); - -#ifdef __cplusplus -} -#endif +/** + * @file wavefile.h + * @brief Interface of wave file + */ + +#pragma once + +typedef struct TagWaveFile *WAVEFILEH; /*!< Defines handle */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +WAVEFILEH wavefile_create(const OEMCHAR *lpFilename, UINT nRate, UINT nBits, UINT nChannels); +UINT wavefile_write(WAVEFILEH hWave, const void *lpBuffer, UINT cbBuffer); +void wavefile_close(WAVEFILEH hWave); + +#ifdef __cplusplus +} +#endif diff --git a/compiler_base.h b/compiler_base.h index 4506f8fc..421a64c2 100644 --- a/compiler_base.h +++ b/compiler_base.h @@ -1,441 +1,441 @@ -/* === compiler base header === (c) 2020 AZO */ - -// for VC2013, ICC12, GCC4, Clang3 - -#ifndef _COMPILER_BASE_H_ -#define _COMPILER_BASE_H_ - -// secure -#if defined(__MINGW32__) || defined(__MINGW64__) -#define MINGW_HAS_SECURE_API 1 -#endif - -// Windows -#if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__) -#if !defined(_WINDOWS) -#define _WINDOWS 1 -#endif -#endif - -// standard include -#if defined(_WINDOWS) -#include -#include -// not define _UNICODE, UNICODE now -#include -#include -#endif - -#if defined(NP2_WIN) -#elif defined(USE_SDL) -#if USE_SDL >= 3 -#include -#elif USE_SDL == 2 -#include -#elif USE_SDL == 1 -#include -#else -#error USE_SDL must be 3, 2, 1 -#endif -#elif defined(__LIBRETRO__) -#include -#else -#error NP2 must be define target -#endif - -#if defined(__cplusplus) -#include -#include // include cwchar -#include -#include -#include -#include -#include -#include -#else -#include -#include // include wchar.h -#include -#include -#include -#include -#include -#include -#endif - -// C/C++ standard -#if defined(__cplusplus) -#include -#if defined(__APPLE__) -#include -#if !defined(CPP11) -#define CPP11 -#endif -#elif defined(_MSC_VER) -#include -#if !defined(CPP11) -#define CPP11 -#endif -#else -#if __cplusplus >= 201103L -#include -#if !defined(CPP11) -#define CPP11 -#endif -#endif -#if defined(__GXX_EXPERIMENTAL_CXX0X__) -#if !defined(CPP0X) -#define CPP0X -#endif -#endif -#endif -#if !defined(_MSC_VER) -#if !defined(SUPPORT_SNPRINTF) -#define SUPPORT_SNPRINTF -#endif -#endif -#else -#if defined(_MSC_VER) -#if _MSC_VER >= 1800 -#include -#include -#if !defined(C99) -#define C99 -#endif -// _MSC_VER<1900(older VC2015) not support snprintf() -#elif _MSC_VER >= 1900 -#if !defined(SUPPORT_SNPRINTF) -#define SUPPORT_SNPRINTF -#endif -#endif -#elif defined(__STDC_VERSION__) -#if __STDC_VERSION__ >= 199901L -#include -#if !defined(C99) -#define C99 -#endif -#if !defined(SUPPORT_SNPRINTF) -#define SUPPORT_SNPRINTF -#endif -#endif -#if __STDC_VERSION__ >= 201112L -#if !defined(C11) -#define C11 -#endif -#if !defined(SUPPORT_STRNLENS) -//#define SUPPORT_STRNLENS -#endif -#endif -#endif -#endif - -// XOPEN_SOURCE -#if __STDC_VERSION__ >= 199901L -#define _XOPEN_SOURCE 600 -#else -#define _XOPEN_SOURCE 500 -#endif - -// size fixed integer -#if !defined(__cplusplus) && !defined(C99) -typedef char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef long int32_t; -typedef unsigned long uint32_t; -typedef long long int64_t; // literal: nnnLL format: %PRId64 -typedef unsigned long long uint64_t; // literal: nnnULL format: %PRIu64 -typedef int64_t intptr_t; -typedef uint64_t uintptr_t; -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; -#endif - -typedef int INT; -typedef INT SINT; -typedef unsigned int UINT; -typedef int8_t INT8; -typedef INT8 SINT8; -typedef uint8_t UINT8; -typedef int16_t INT16; -typedef INT16 SINT16; -typedef uint16_t UINT16; -typedef int32_t INT32; -typedef INT32 SINT32; -typedef uint32_t UINT32; -typedef int64_t INT64; -typedef INT64 SINT64; -typedef uint64_t UINT64; - -// variable size -typedef size_t SIZET; // format: %zu -typedef intptr_t INTPTR; // format: %PRIdPTR -typedef uintptr_t UINTPTR; // format: %PRIuPTR -typedef intptr_t INT_PTR; // format: %PRIdPTR -typedef uintptr_t UINT_PTR; // format: %PRIuPTR -typedef intmax_t INTMAX; // format: %PRIdMAX -typedef uintmax_t UINTMAX; // format: %PRIuMAX - -// bool -#if !defined(_WINDOWS) -#include -typedef bool BOOL; -#if !defined(TRUE) -#define TRUE (1==1) -#endif -#if !defined(FALSE) -#define FALSE (1==0) -#endif -#endif - -// inline -#if !defined(DEBUG) || !defined(_DEBUG) -#if !defined(INLINE) -#if defined(_MSC_VER) -#pragma warning(disable: 4244) -#pragma warning(disable: 4245) -#define INLINE __inline -#elif defined(__BORLANDC__) -#define INLINE __inline -#elif defined(__GNUC__) -#define INLINE __inline__ __attribute__((always_inline)) -#else -#define INLINE -#endif -#endif -#else -#undef INLINE -#define INLINE -#endif - -// pi -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif -#ifndef M_PI -#define M_PIl 3.1415926535897932384626433832795029L -#endif - -// --> milstr OEMCHAR -#if defined(_WINDOWS) -#define OEMNEWLINE "\r\n" -#define OEMPATHDIV "\\" -#define OEMPATHDIVC '\\' -#else -#define OEMNEWLINE "\n" -#define OEMPATHDIV "/" -#define OEMPATHDIVC '/' -#endif -#define OEMSLASH "/" -#define OEMSLASHC '/' - -#if defined(SUPPORT_STRNLENS) -#define OEMSTRNLENS strnlen_s -#define OEMSTRNLEN strnlen_s -#elif defined(C99) || defined(CPP11) -#define OEMSTRNLENS strnlen -#define OEMSTRNLEN strnlen -#else -#define OEMSTRNLENS(s, z) strlen(s) -#define OEMSTRNLEN(s, z) strlen(s) -#endif -#define OEMSTRLEN strlen -#define STRNLENS OEMSTRNLENS -#define STRNLEN OEMSTRNLEN -#define STRLEN OEMSTRLEN - -#if defined(SUPPORT_SNPRINTF) -#define OEMSNPRINTF snprintf -#else -#if defined(C99) || defined(CPP11) -#define OEMSNPRINTF(s, z, f, ...) sprintf(s, f, __VA_ARGS__) -#else -#define OEMSNPRINTF(s, z, f, d) sprintf(s, f, d) -#endif -#endif -#define OEMSPRINTF sprintf -#define SNPRINTF OEMSNPRINTF -#define SPRINTF OEMSPRINTF - -#define OEMSTRCPY(s1, s2) OEMSPRINTF(s1, OEMTEXT("%s"), s2) -#define OEMPRINTFSTR(s) printf(OEMTEXT("%s"), s) - -// future depracted maybe -#define OEMCHAR char -#define OEMTEXT(string) string - -#define STRCALL -// <-- milstr OEMCHAR - -// --> Windowsnize -// calling convention -#undef CDECL -#undef STDCALL -#undef CLRCALL -#undef FASTCALL -#undef VECTORCALL -#if defined(__cpluscplus) -#undef THISCALL -#endif - -#if defined(_MSC_VER) && defined(_M_IX86) && !defined(LR_VS2017) -#define CDECL __cdecl -#define STDCALL __stdcall -#define FASTCALL __fastcall -#define SAFECALL __safecall -#define CLRCALL __clrcall -#define VECTORCALL __vectorcall -#if defined(__cpluscplus) -#define THISCALL __thiscall -#endif -#elif defined(__GNUC__) && defined(__i386__) && !defined(__ANDROID__) && !defined(EMSCRIPTEN) -#define CDECL __attribute__ ((cdecl)) -#define STDCALL __attribute__ ((stdcall)) -#define FASTCALL __attribute__ ((fastcall)) -#define CLRCALL -#define VECTORCALL __attribute__ ((interrupt)) -#if defined(__cpluscplus) -#define THISCALL __attribute__ ((thiscall)) -#endif -#else -#define CDECL -#define STDCALL -#define FASTCALL -#define SAFECALL -#define CLRCALL -#define VECTORCALL -#if defined(__cpluscplus) -#define THISCALL -#endif -#endif - -#if !defined(NP2_WIN) -#define WINAPI - -#if !defined(_WINDOWS) -typedef uint8_t BYTE; -typedef uint16_t WORD; -typedef uint32_t DWORD; -typedef bool BRESULT; -typedef wchar_t TCHAR; - -typedef union { - struct { - UINT32 LowPart; - SINT32 HighPart; - } u; - SINT64 QuadPart; -} LARGE_INTEGER; -#endif - -#define _T(string) string -#define _tcscpy OEMSTRCPY -#define _tcsicmp milstr_cmp -#define _tcsnicmp strncasecmp - -#ifndef ZeroMemory -#define ZeroMemory(d, z) memset((d), 0, (z)) -#endif -#ifndef CopyMemory -#define CopyMemory(d, s, z) memcpy((d), (s), (z)) -#endif -#ifndef FillMemory -#define FillMemory(d, z, c) memset((d), (c), (z)) -#endif - -#if defined(__WINRT__) && defined(_M_IX86) -#define CreateFileW(f, a, s, sec, p, flg, t) CreateFile2(f, a, s, p, NULL) -#endif -#endif -// <-- Windowsnize - -typedef uint8_t REG8; -typedef uint16_t REG16; - -#define UNUSED(v) (void)(v) - -#define CPUCALL FASTCALL -#define MEMCALL FASTCALL -#define DMACCALL FASTCALL -#define IOOUTCALL FASTCALL -#define IOINPCALL FASTCALL -#define SOUNDCALL FASTCALL -#define VRAMCALL FASTCALL -#define SCRNCALL FASTCALL -#define VERMOUTHCL FASTCALL -#define PARTSCALL FASTCALL - -#define GETRAND() rand() - -#ifndef MSB_FIRST -#define BYTESEX_LITTLE -#else -#define BYTESEX_BIG -#endif - -#define sigjmp_buf jmp_buf -#ifndef sigsetjmp -#define sigsetjmp(env, mask) setjmp(env) -#endif -#ifndef siglongjmp -#define siglongjmp(env, val) longjmp(env, val) -#endif - -#define COPY64(pd, ps) *(UINT64*)(pd) = *(UINT64*)(ps); - -// MAXPATH -#ifndef MAX_PATH -#define MAX_PATH 4096 -#endif - -// min max 2 params -#ifndef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef NELEMENTS -#define NELEMENTS(a) (sizeof(a) / sizeof(a[0])) -#endif - -// MEMORYSIZE -#if defined(SUPPORT_LARGE_MEMORY) -#define MEMORY_MAXSIZE 4000 -#else -#define MEMORY_MAXSIZE 230 -#endif - -// FILELEN -#if defined(SUPPORT_LARGE_HDD) -typedef int64_t FILEPOS; -typedef int64_t FILELEN; -#define NHD_MAXSIZE 8000 -#define NHD_MAXSIZE2 ((uint32_t)0xffffffff/1024/2) -#define NHD_MAXSIZE28 130558 -#else -typedef int32_t FILEPOS; -typedef int32_t FILELEN; -#define NHD_MAXSIZE 2000 -#define NHD_MAXSIZE2 2000 -#endif - -// MEMOPTIMIZE -#undef MEMOPTIMIZE -#if defined(arm) || defined (__arm__) -#define MEMOPTIMIZE 2 -#define LOW12(a) ((((UINT32)(a)) << 20) >> 20) -#define LOW14(a) ((((UINT32)(a)) << 18) >> 18) -#define LOW15(a) ((((UINT32)(a)) << 17) >> 17) -#define LOW16(a) ((UINT16)(a)) -#define HIGH16(a) (((UINT32)(a)) >> 16) -#endif - -#include "common.h" -#include "common/_memory.h" -#include "common/rect.h" -#include "common/lstarray.h" - -#endif // _COMPILER_BASE_H_ +/* === compiler base header === (c) 2020 AZO */ + +// for VC2013, ICC12, GCC4, Clang3 + +#ifndef _COMPILER_BASE_H_ +#define _COMPILER_BASE_H_ + +// secure +#if defined(__MINGW32__) || defined(__MINGW64__) +#define MINGW_HAS_SECURE_API 1 +#endif + +// Windows +#if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__) || defined(__MINGW64__) || defined(__CYGWIN__) +#if !defined(_WINDOWS) +#define _WINDOWS 1 +#endif +#endif + +// standard include +#if defined(_WINDOWS) +#include +#include +// not define _UNICODE, UNICODE now +#include +#include +#endif + +#if defined(NP2_WIN) +#elif defined(USE_SDL) +#if USE_SDL >= 3 +#include +#elif USE_SDL == 2 +#include +#elif USE_SDL == 1 +#include +#else +#error USE_SDL must be 3, 2, 1 +#endif +#elif defined(__LIBRETRO__) +#include +#else +#error NP2 must be define target +#endif + +#if defined(__cplusplus) +#include +#include // include cwchar +#include +#include +#include +#include +#include +#include +#else +#include +#include // include wchar.h +#include +#include +#include +#include +#include +#include +#endif + +// C/C++ standard +#if defined(__cplusplus) +#include +#if defined(__APPLE__) +#include +#if !defined(CPP11) +#define CPP11 +#endif +#elif defined(_MSC_VER) +#include +#if !defined(CPP11) +#define CPP11 +#endif +#else +#if __cplusplus >= 201103L +#include +#if !defined(CPP11) +#define CPP11 +#endif +#endif +#if defined(__GXX_EXPERIMENTAL_CXX0X__) +#if !defined(CPP0X) +#define CPP0X +#endif +#endif +#endif +#if !defined(_MSC_VER) +#if !defined(SUPPORT_SNPRINTF) +#define SUPPORT_SNPRINTF +#endif +#endif +#else +#if defined(_MSC_VER) +#if _MSC_VER >= 1800 +#include +#include +#if !defined(C99) +#define C99 +#endif +// _MSC_VER<1900(older VC2015) not support snprintf() +#elif _MSC_VER >= 1900 +#if !defined(SUPPORT_SNPRINTF) +#define SUPPORT_SNPRINTF +#endif +#endif +#elif defined(__STDC_VERSION__) +#if __STDC_VERSION__ >= 199901L +#include +#if !defined(C99) +#define C99 +#endif +#if !defined(SUPPORT_SNPRINTF) +#define SUPPORT_SNPRINTF +#endif +#endif +#if __STDC_VERSION__ >= 201112L +#if !defined(C11) +#define C11 +#endif +#if !defined(SUPPORT_STRNLENS) +//#define SUPPORT_STRNLENS +#endif +#endif +#endif +#endif + +// XOPEN_SOURCE +#if __STDC_VERSION__ >= 199901L +#define _XOPEN_SOURCE 600 +#else +#define _XOPEN_SOURCE 500 +#endif + +// size fixed integer +#if !defined(__cplusplus) && !defined(C99) +typedef char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef long int32_t; +typedef unsigned long uint32_t; +typedef long long int64_t; // literal: nnnLL format: %PRId64 +typedef unsigned long long uint64_t; // literal: nnnULL format: %PRIu64 +typedef int64_t intptr_t; +typedef uint64_t uintptr_t; +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; +#endif + +typedef int INT; +typedef INT SINT; +typedef unsigned int UINT; +typedef int8_t INT8; +typedef INT8 SINT8; +typedef uint8_t UINT8; +typedef int16_t INT16; +typedef INT16 SINT16; +typedef uint16_t UINT16; +typedef int32_t INT32; +typedef INT32 SINT32; +typedef uint32_t UINT32; +typedef int64_t INT64; +typedef INT64 SINT64; +typedef uint64_t UINT64; + +// variable size +typedef size_t SIZET; // format: %zu +typedef intptr_t INTPTR; // format: %PRIdPTR +typedef uintptr_t UINTPTR; // format: %PRIuPTR +typedef intptr_t INT_PTR; // format: %PRIdPTR +typedef uintptr_t UINT_PTR; // format: %PRIuPTR +typedef intmax_t INTMAX; // format: %PRIdMAX +typedef uintmax_t UINTMAX; // format: %PRIuMAX + +// bool +#if !defined(_WINDOWS) +#include +typedef bool BOOL; +#if !defined(TRUE) +#define TRUE (1==1) +#endif +#if !defined(FALSE) +#define FALSE (1==0) +#endif +#endif + +// inline +#if !defined(DEBUG) || !defined(_DEBUG) +#if !defined(INLINE) +#if defined(_MSC_VER) +#pragma warning(disable: 4244) +#pragma warning(disable: 4245) +#define INLINE __inline +#elif defined(__BORLANDC__) +#define INLINE __inline +#elif defined(__GNUC__) +#define INLINE __inline__ __attribute__((always_inline)) +#else +#define INLINE +#endif +#endif +#else +#undef INLINE +#define INLINE +#endif + +// pi +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_PI +#define M_PIl 3.1415926535897932384626433832795029L +#endif + +// --> milstr OEMCHAR +#if defined(_WINDOWS) +#define OEMNEWLINE "\r\n" +#define OEMPATHDIV "\\" +#define OEMPATHDIVC '\\' +#else +#define OEMNEWLINE "\n" +#define OEMPATHDIV "/" +#define OEMPATHDIVC '/' +#endif +#define OEMSLASH "/" +#define OEMSLASHC '/' + +#if defined(SUPPORT_STRNLENS) +#define OEMSTRNLENS strnlen_s +#define OEMSTRNLEN strnlen_s +#elif defined(C99) || defined(CPP11) +#define OEMSTRNLENS strnlen +#define OEMSTRNLEN strnlen +#else +#define OEMSTRNLENS(s, z) strlen(s) +#define OEMSTRNLEN(s, z) strlen(s) +#endif +#define OEMSTRLEN strlen +#define STRNLENS OEMSTRNLENS +#define STRNLEN OEMSTRNLEN +#define STRLEN OEMSTRLEN + +#if defined(SUPPORT_SNPRINTF) +#define OEMSNPRINTF snprintf +#else +#if defined(C99) || defined(CPP11) +#define OEMSNPRINTF(s, z, f, ...) sprintf(s, f, __VA_ARGS__) +#else +#define OEMSNPRINTF(s, z, f, d) sprintf(s, f, d) +#endif +#endif +#define OEMSPRINTF sprintf +#define SNPRINTF OEMSNPRINTF +#define SPRINTF OEMSPRINTF + +#define OEMSTRCPY(s1, s2) OEMSPRINTF(s1, OEMTEXT("%s"), s2) +#define OEMPRINTFSTR(s) printf(OEMTEXT("%s"), s) + +// future depracted maybe +#define OEMCHAR char +#define OEMTEXT(string) string + +#define STRCALL +// <-- milstr OEMCHAR + +// --> Windowsnize +// calling convention +#undef CDECL +#undef STDCALL +#undef CLRCALL +#undef FASTCALL +#undef VECTORCALL +#if defined(__cpluscplus) +#undef THISCALL +#endif + +#if defined(_MSC_VER) && defined(_M_IX86) && !defined(LR_VS2017) +#define CDECL __cdecl +#define STDCALL __stdcall +#define FASTCALL __fastcall +#define SAFECALL __safecall +#define CLRCALL __clrcall +#define VECTORCALL __vectorcall +#if defined(__cpluscplus) +#define THISCALL __thiscall +#endif +#elif defined(__GNUC__) && defined(__i386__) && !defined(__ANDROID__) && !defined(EMSCRIPTEN) +#define CDECL __attribute__ ((cdecl)) +#define STDCALL __attribute__ ((stdcall)) +#define FASTCALL __attribute__ ((fastcall)) +#define CLRCALL +#define VECTORCALL __attribute__ ((interrupt)) +#if defined(__cpluscplus) +#define THISCALL __attribute__ ((thiscall)) +#endif +#else +#define CDECL +#define STDCALL +#define FASTCALL +#define SAFECALL +#define CLRCALL +#define VECTORCALL +#if defined(__cpluscplus) +#define THISCALL +#endif +#endif + +#if !defined(NP2_WIN) +#define WINAPI + +#if !defined(_WINDOWS) +typedef uint8_t BYTE; +typedef uint16_t WORD; +typedef uint32_t DWORD; +typedef bool BRESULT; +typedef wchar_t TCHAR; + +typedef union { + struct { + UINT32 LowPart; + SINT32 HighPart; + } u; + SINT64 QuadPart; +} LARGE_INTEGER; +#endif + +#define _T(string) string +#define _tcscpy OEMSTRCPY +#define _tcsicmp milstr_cmp +#define _tcsnicmp strncasecmp + +#ifndef ZeroMemory +#define ZeroMemory(d, z) memset((d), 0, (z)) +#endif +#ifndef CopyMemory +#define CopyMemory(d, s, z) memcpy((d), (s), (z)) +#endif +#ifndef FillMemory +#define FillMemory(d, z, c) memset((d), (c), (z)) +#endif + +#if defined(__WINRT__) && defined(_M_IX86) +#define CreateFileW(f, a, s, sec, p, flg, t) CreateFile2(f, a, s, p, NULL) +#endif +#endif +// <-- Windowsnize + +typedef uint8_t REG8; +typedef uint16_t REG16; + +#define UNUSED(v) (void)(v) + +#define CPUCALL FASTCALL +#define MEMCALL FASTCALL +#define DMACCALL FASTCALL +#define IOOUTCALL FASTCALL +#define IOINPCALL FASTCALL +#define SOUNDCALL FASTCALL +#define VRAMCALL FASTCALL +#define SCRNCALL FASTCALL +#define VERMOUTHCL FASTCALL +#define PARTSCALL FASTCALL + +#define GETRAND() rand() + +#ifndef MSB_FIRST +#define BYTESEX_LITTLE +#else +#define BYTESEX_BIG +#endif + +#define sigjmp_buf jmp_buf +#ifndef sigsetjmp +#define sigsetjmp(env, mask) setjmp(env) +#endif +#ifndef siglongjmp +#define siglongjmp(env, val) longjmp(env, val) +#endif + +#define COPY64(pd, ps) *(UINT64*)(pd) = *(UINT64*)(ps); + +// MAXPATH +#ifndef MAX_PATH +#define MAX_PATH 4096 +#endif + +// min max 2 params +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef NELEMENTS +#define NELEMENTS(a) (sizeof(a) / sizeof(a[0])) +#endif + +// MEMORYSIZE +#if defined(SUPPORT_LARGE_MEMORY) +#define MEMORY_MAXSIZE 4000 +#else +#define MEMORY_MAXSIZE 230 +#endif + +// FILELEN +#if defined(SUPPORT_LARGE_HDD) +typedef int64_t FILEPOS; +typedef int64_t FILELEN; +#define NHD_MAXSIZE 8000 +#define NHD_MAXSIZE2 ((uint32_t)0xffffffff/1024/2) +#define NHD_MAXSIZE28 130558 +#else +typedef int32_t FILEPOS; +typedef int32_t FILELEN; +#define NHD_MAXSIZE 2000 +#define NHD_MAXSIZE2 2000 +#endif + +// MEMOPTIMIZE +#undef MEMOPTIMIZE +#if defined(arm) || defined (__arm__) +#define MEMOPTIMIZE 2 +#define LOW12(a) ((((UINT32)(a)) << 20) >> 20) +#define LOW14(a) ((((UINT32)(a)) << 18) >> 18) +#define LOW15(a) ((((UINT32)(a)) << 17) >> 17) +#define LOW16(a) ((UINT16)(a)) +#define HIGH16(a) (((UINT32)(a)) >> 16) +#endif + +#include "common.h" +#include "common/_memory.h" +#include "common/rect.h" +#include "common/lstarray.h" + +#endif // _COMPILER_BASE_H_ diff --git a/debugsub.c b/debugsub.c old mode 100755 new mode 100644 index 48821b3b..94ee9698 --- a/debugsub.c +++ b/debugsub.c @@ -1,183 +1,183 @@ -#include -#include -#include -#include -#include -#include -#include -#include - - -#if defined(MACOS) -#define CRLITERAL "\r" -#define CRCONST str_cr -#elif defined(X11) -#define CRLITERAL "\n" -#define CRCONST str_lf -#else -#define CRLITERAL "\r\n" -#define CRCONST str_crlf -#endif - - -static const OEMCHAR s_nv[] = OEMTEXT("NV"); -static const OEMCHAR s_ov[] = OEMTEXT("OV"); -static const OEMCHAR s_dn[] = OEMTEXT("DN"); -static const OEMCHAR s_up[] = OEMTEXT("UP"); -static const OEMCHAR s_di[] = OEMTEXT("DI"); -static const OEMCHAR s_ei[] = OEMTEXT("EI"); -static const OEMCHAR s_pl[] = OEMTEXT("PL"); -static const OEMCHAR s_ng[] = OEMTEXT("NG"); -static const OEMCHAR s_nz[] = OEMTEXT("NZ"); -static const OEMCHAR s_zr[] = OEMTEXT("ZR"); -static const OEMCHAR s_na[] = OEMTEXT("NA"); -static const OEMCHAR s_ac[] = OEMTEXT("AC"); -static const OEMCHAR s_po[] = OEMTEXT("PO"); -static const OEMCHAR s_pe[] = OEMTEXT("PE"); -static const OEMCHAR s_nc[] = OEMTEXT("NC"); -static const OEMCHAR s_cy[] = OEMTEXT("CY"); - -static const OEMCHAR *flagstr[16][2] = { - {NULL, NULL}, // 0x8000 - {NULL, NULL}, // 0x4000 - {NULL, NULL}, // 0x2000 - {NULL, NULL}, // 0x1000 - {s_nv, s_ov}, // 0x0800 - {s_dn, s_up}, // 0x0400 - {s_di, s_ei}, // 0x0200 - {NULL, NULL}, // 0x0100 - {s_pl, s_ng}, // 0x0080 - {s_nz, s_zr}, // 0x0040 - {NULL, NULL}, // 0x0020 - {s_na, s_ac}, // 0x0010 - {NULL, NULL}, // 0x0008 - {s_po, s_pe}, // 0x0004 - {NULL, NULL}, // 0x0002 - {s_nc, s_cy}}; // 0x0001 - -static const OEMCHAR file_i286reg[] = OEMTEXT("i286reg.%.3u"); -static const OEMCHAR file_i286cs[] = OEMTEXT("i286_cs.%.3u"); -static const OEMCHAR file_i286ds[] = OEMTEXT("i286_ds.%.3u"); -static const OEMCHAR file_i286es[] = OEMTEXT("i286_es.%.3u"); -static const OEMCHAR file_i286ss[] = OEMTEXT("i286_ss.%.3u"); -static const OEMCHAR file_memorybin[] = OEMTEXT("memory.bin"); - -static const OEMCHAR str_register[] = \ - OEMTEXT("AX=%.4x BX=%.4x CX=%.4x DX=%.4x ") \ - OEMTEXT("SP=%.4x BP=%.4x SI=%.4x DI=%.4x") \ - OEMTEXT(CRLITERAL) \ - OEMTEXT("DS=%.4x ES=%.4x SS=%.4x CS=%.4x ") \ - OEMTEXT("IP=%.4x "); -static const OEMCHAR str_picstat[] = \ - OEMTEXT(CRLITERAL) \ - OEMTEXT("PIC0=%.2x:%.2x:%.2x") \ - OEMTEXT(CRLITERAL) \ - OEMTEXT("PIC1=%.2x:%.2x:%.2x") \ - OEMTEXT(CRLITERAL) \ - OEMTEXT("8255PORTC = %.2x / system-port = %.2x"); - - -const OEMCHAR *debugsub_flags(UINT16 flag) { - -static OEMCHAR work[128]; - int i; - UINT16 bit; - - work[0] = 0; - for (i=0, bit=0x8000; bit; i++, bit>>=1) { - if (flagstr[i][0]) { - if (flag & bit) { - milstr_ncat(work, flagstr[i][1], NELEMENTS(work)); - } - else { - milstr_ncat(work, flagstr[i][0], NELEMENTS(work)); - } - if (bit != 1) { - milstr_ncat(work, str_space, NELEMENTS(work)); - } - } - } - return(work); -} - -const OEMCHAR *debugsub_regs(void) { - -static OEMCHAR work[512]; - - OEMSNPRINTF(work, sizeof(work), str_register, CPU_AX, CPU_BX, CPU_CX, CPU_DX, - CPU_SP, CPU_BP, CPU_SI, CPU_DI, - CPU_DS, CPU_ES, CPU_SS, CPU_CS, CPU_IP); - milstr_ncat(work, debugsub_flags(CPU_FLAG), NELEMENTS(work)); - milstr_ncat(work, CRCONST, NELEMENTS(work)); - return(work); -} - -static void writeseg(const OEMCHAR *fname, UINT32 addr, UINT limit) { - - FILEH fh; - UINT size; - UINT8 buf[0x400]; // Stack 0x1000 -> 0x400 - - fh = file_create_c(fname); - if (fh == FILEH_INVALID) { - return; - } - limit = MIN(limit, 0xffff); - limit++; - while(limit) { - size = MIN(limit, sizeof(buf)); - MEML_READS(addr, buf, size); - file_write(fh, buf, size); - addr += size; - limit -= size; - } - file_close(fh); -} - -void debugsub_status(void) { - -static int filenum = 0; - TEXTFILEH tfh; - OEMCHAR work[512]; -const OEMCHAR *p; - - OEMSNPRINTF(work, sizeof(work), file_i286reg, filenum); - tfh = textfile_create(file_getcd(work), 0); - if (tfh != NULL) { - p = debugsub_regs(); - textfile_write(tfh, p); - OEMSNPRINTF(work, sizeof(work), str_picstat, - pic.pi[0].imr, pic.pi[0].irr, pic.pi[0].isr, - pic.pi[1].imr, pic.pi[1].irr, pic.pi[1].isr, - mouseif.upd8255.portc, sysport.c); - textfile_write(tfh, work); - textfile_close(tfh); - } - - OEMSNPRINTF(work, sizeof(work), file_i286cs, filenum); - writeseg(work, CS_BASE, 0xffff); - OEMSNPRINTF(work, sizeof(work), file_i286ds, filenum); - writeseg(work, DS_BASE, 0xffff); - OEMSNPRINTF(work, sizeof(work), file_i286es, filenum); - writeseg(work, ES_BASE, 0xffff); - OEMSNPRINTF(work, sizeof(work), file_i286ss, filenum); - writeseg(work, SS_BASE, 0xffff); - filenum++; -} - -void debugsub_memorydump(void) { - - FILEH fh; - int i; - - fh = file_create_c(file_memorybin); - if (fh != FILEH_INVALID) { - for (i=0; i<34; i++) -// for (i=0; i<64; i++) - { - file_write(fh, mem + i*0x8000, 0x8000); - } - file_close(fh); - } -} - +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined(MACOS) +#define CRLITERAL "\r" +#define CRCONST str_cr +#elif defined(X11) +#define CRLITERAL "\n" +#define CRCONST str_lf +#else +#define CRLITERAL "\r\n" +#define CRCONST str_crlf +#endif + + +static const OEMCHAR s_nv[] = OEMTEXT("NV"); +static const OEMCHAR s_ov[] = OEMTEXT("OV"); +static const OEMCHAR s_dn[] = OEMTEXT("DN"); +static const OEMCHAR s_up[] = OEMTEXT("UP"); +static const OEMCHAR s_di[] = OEMTEXT("DI"); +static const OEMCHAR s_ei[] = OEMTEXT("EI"); +static const OEMCHAR s_pl[] = OEMTEXT("PL"); +static const OEMCHAR s_ng[] = OEMTEXT("NG"); +static const OEMCHAR s_nz[] = OEMTEXT("NZ"); +static const OEMCHAR s_zr[] = OEMTEXT("ZR"); +static const OEMCHAR s_na[] = OEMTEXT("NA"); +static const OEMCHAR s_ac[] = OEMTEXT("AC"); +static const OEMCHAR s_po[] = OEMTEXT("PO"); +static const OEMCHAR s_pe[] = OEMTEXT("PE"); +static const OEMCHAR s_nc[] = OEMTEXT("NC"); +static const OEMCHAR s_cy[] = OEMTEXT("CY"); + +static const OEMCHAR *flagstr[16][2] = { + {NULL, NULL}, // 0x8000 + {NULL, NULL}, // 0x4000 + {NULL, NULL}, // 0x2000 + {NULL, NULL}, // 0x1000 + {s_nv, s_ov}, // 0x0800 + {s_dn, s_up}, // 0x0400 + {s_di, s_ei}, // 0x0200 + {NULL, NULL}, // 0x0100 + {s_pl, s_ng}, // 0x0080 + {s_nz, s_zr}, // 0x0040 + {NULL, NULL}, // 0x0020 + {s_na, s_ac}, // 0x0010 + {NULL, NULL}, // 0x0008 + {s_po, s_pe}, // 0x0004 + {NULL, NULL}, // 0x0002 + {s_nc, s_cy}}; // 0x0001 + +static const OEMCHAR file_i286reg[] = OEMTEXT("i286reg.%.3u"); +static const OEMCHAR file_i286cs[] = OEMTEXT("i286_cs.%.3u"); +static const OEMCHAR file_i286ds[] = OEMTEXT("i286_ds.%.3u"); +static const OEMCHAR file_i286es[] = OEMTEXT("i286_es.%.3u"); +static const OEMCHAR file_i286ss[] = OEMTEXT("i286_ss.%.3u"); +static const OEMCHAR file_memorybin[] = OEMTEXT("memory.bin"); + +static const OEMCHAR str_register[] = \ + OEMTEXT("AX=%.4x BX=%.4x CX=%.4x DX=%.4x ") \ + OEMTEXT("SP=%.4x BP=%.4x SI=%.4x DI=%.4x") \ + OEMTEXT(CRLITERAL) \ + OEMTEXT("DS=%.4x ES=%.4x SS=%.4x CS=%.4x ") \ + OEMTEXT("IP=%.4x "); +static const OEMCHAR str_picstat[] = \ + OEMTEXT(CRLITERAL) \ + OEMTEXT("PIC0=%.2x:%.2x:%.2x") \ + OEMTEXT(CRLITERAL) \ + OEMTEXT("PIC1=%.2x:%.2x:%.2x") \ + OEMTEXT(CRLITERAL) \ + OEMTEXT("8255PORTC = %.2x / system-port = %.2x"); + + +const OEMCHAR *debugsub_flags(UINT16 flag) { + +static OEMCHAR work[128]; + int i; + UINT16 bit; + + work[0] = 0; + for (i=0, bit=0x8000; bit; i++, bit>>=1) { + if (flagstr[i][0]) { + if (flag & bit) { + milstr_ncat(work, flagstr[i][1], NELEMENTS(work)); + } + else { + milstr_ncat(work, flagstr[i][0], NELEMENTS(work)); + } + if (bit != 1) { + milstr_ncat(work, str_space, NELEMENTS(work)); + } + } + } + return(work); +} + +const OEMCHAR *debugsub_regs(void) { + +static OEMCHAR work[512]; + + OEMSNPRINTF(work, sizeof(work), str_register, CPU_AX, CPU_BX, CPU_CX, CPU_DX, + CPU_SP, CPU_BP, CPU_SI, CPU_DI, + CPU_DS, CPU_ES, CPU_SS, CPU_CS, CPU_IP); + milstr_ncat(work, debugsub_flags(CPU_FLAG), NELEMENTS(work)); + milstr_ncat(work, CRCONST, NELEMENTS(work)); + return(work); +} + +static void writeseg(const OEMCHAR *fname, UINT32 addr, UINT limit) { + + FILEH fh; + UINT size; + UINT8 buf[0x400]; // Stack 0x1000 -> 0x400 + + fh = file_create_c(fname); + if (fh == FILEH_INVALID) { + return; + } + limit = MIN(limit, 0xffff); + limit++; + while(limit) { + size = MIN(limit, sizeof(buf)); + MEML_READS(addr, buf, size); + file_write(fh, buf, size); + addr += size; + limit -= size; + } + file_close(fh); +} + +void debugsub_status(void) { + +static int filenum = 0; + TEXTFILEH tfh; + OEMCHAR work[512]; +const OEMCHAR *p; + + OEMSNPRINTF(work, sizeof(work), file_i286reg, filenum); + tfh = textfile_create(file_getcd(work), 0); + if (tfh != NULL) { + p = debugsub_regs(); + textfile_write(tfh, p); + OEMSNPRINTF(work, sizeof(work), str_picstat, + pic.pi[0].imr, pic.pi[0].irr, pic.pi[0].isr, + pic.pi[1].imr, pic.pi[1].irr, pic.pi[1].isr, + mouseif.upd8255.portc, sysport.c); + textfile_write(tfh, work); + textfile_close(tfh); + } + + OEMSNPRINTF(work, sizeof(work), file_i286cs, filenum); + writeseg(work, CS_BASE, 0xffff); + OEMSNPRINTF(work, sizeof(work), file_i286ds, filenum); + writeseg(work, DS_BASE, 0xffff); + OEMSNPRINTF(work, sizeof(work), file_i286es, filenum); + writeseg(work, ES_BASE, 0xffff); + OEMSNPRINTF(work, sizeof(work), file_i286ss, filenum); + writeseg(work, SS_BASE, 0xffff); + filenum++; +} + +void debugsub_memorydump(void) { + + FILEH fh; + int i; + + fh = file_create_c(file_memorybin); + if (fh != FILEH_INVALID) { + for (i=0; i<34; i++) +// for (i=0; i<64; i++) + { + file_write(fh, mem + i*0x8000, 0x8000); + } + file_close(fh); + } +} + diff --git a/debugsub.h b/debugsub.h old mode 100755 new mode 100644 index 2f2a6b64..4e4efc0b --- a/debugsub.h +++ b/debugsub.h @@ -1,15 +1,15 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -const OEMCHAR *debugsub_flags(UINT16 flag); -const OEMCHAR *debugsub_regs(void); -void debugsub_status(void); -void debugsub_memorydump(void); -void debugsub_memorydumpall(void); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +const OEMCHAR *debugsub_flags(UINT16 flag); +const OEMCHAR *debugsub_regs(void); +void debugsub_status(void); +void debugsub_memorydump(void); +void debugsub_memorydumpall(void); + +#ifdef __cplusplus +} +#endif + diff --git a/debugsub386.c b/debugsub386.c old mode 100755 new mode 100644 index d7de724c..68378de9 --- a/debugsub386.c +++ b/debugsub386.c @@ -1,245 +1,245 @@ -#include -#include -#include -#include -#include -#include -#include - -void debugwriteseg(const OEMCHAR *fname, const descriptor_t *sd, - UINT32 addr, UINT32 size); -void debugpageptr(UINT32 addr); - - -#if defined(MACOS) -#define CRLITERAL "\r" -#define CRCONST str_cr -#elif defined(X11) -#define CRLITERAL "\n" -#define CRCONST str_lf -#else -#define CRLITERAL "\r\n" -#define CRCONST str_crlf -#endif - - -static const OEMCHAR s_nv[] = OEMTEXT("NV"); -static const OEMCHAR s_ov[] = OEMTEXT("OV"); -static const OEMCHAR s_dn[] = OEMTEXT("DN"); -static const OEMCHAR s_up[] = OEMTEXT("UP"); -static const OEMCHAR s_di[] = OEMTEXT("DI"); -static const OEMCHAR s_ei[] = OEMTEXT("EI"); -static const OEMCHAR s_pl[] = OEMTEXT("PL"); -static const OEMCHAR s_ng[] = OEMTEXT("NG"); -static const OEMCHAR s_nz[] = OEMTEXT("NZ"); -static const OEMCHAR s_zr[] = OEMTEXT("ZR"); -static const OEMCHAR s_na[] = OEMTEXT("NA"); -static const OEMCHAR s_ac[] = OEMTEXT("AC"); -static const OEMCHAR s_po[] = OEMTEXT("PO"); -static const OEMCHAR s_pe[] = OEMTEXT("PE"); -static const OEMCHAR s_nc[] = OEMTEXT("NC"); -static const OEMCHAR s_cy[] = OEMTEXT("CY"); - -static const OEMCHAR *flagstr[16][2] = { - {NULL, NULL}, // 0x8000 - {NULL, NULL}, // 0x4000 - {NULL, NULL}, // 0x2000 - {NULL, NULL}, // 0x1000 - {s_nv, s_ov}, // 0x0800 - {s_dn, s_up}, // 0x0400 - {s_di, s_ei}, // 0x0200 - {NULL, NULL}, // 0x0100 - {s_pl, s_ng}, // 0x0080 - {s_nz, s_zr}, // 0x0040 - {NULL, NULL}, // 0x0020 - {s_na, s_ac}, // 0x0010 - {NULL, NULL}, // 0x0008 - {s_po, s_pe}, // 0x0004 - {NULL, NULL}, // 0x0002 - {s_nc, s_cy}}; // 0x0001 - -static const OEMCHAR file_i386reg[] = OEMTEXT("i386reg.%.3u"); -static const OEMCHAR file_i386cs[] = OEMTEXT("i386_cs.%.3u"); -static const OEMCHAR file_i386ds[] = OEMTEXT("i386_ds.%.3u"); -static const OEMCHAR file_i386es[] = OEMTEXT("i386_es.%.3u"); -static const OEMCHAR file_i386ss[] = OEMTEXT("i386_ss.%.3u"); -static const OEMCHAR file_memorybin[] = OEMTEXT("memory.bin"); - -static const OEMCHAR str_register[] = \ - OEMTEXT("EAX=%.8x EBX=%.8x ECX=%.8x EDX=%.8x") \ - OEMTEXT(CRLITERAL) \ - OEMTEXT("ESP=%.8x EBP=%.8x ESI=%.8x EDI=%.8x") \ - OEMTEXT(CRLITERAL) \ - OEMTEXT("DS=%.4x ES=%.4x SS=%.4x CS=%.4x ") \ - OEMTEXT("EIP=%.8x ") \ - OEMTEXT(CRLITERAL); -static const OEMCHAR str_picstat[] = \ - OEMTEXT("PIC0=%.2x:%.2x:%.2x") \ - OEMTEXT(CRLITERAL) \ - OEMTEXT("PIC1=%.2x:%.2x:%.2x") \ - OEMTEXT(CRLITERAL) \ - OEMTEXT("8255PORTC = %.2x / system-port = %.2x") \ - OEMTEXT(CRLITERAL); - - -const OEMCHAR *debugsub_flags(UINT16 flag) { - -static OEMCHAR work[128]; - int i; - UINT16 bit; - - work[0] = 0; - for (i=0, bit=0x8000; bit; i++, bit>>=1) { - if (flagstr[i][0]) { - if (flag & bit) { - milstr_ncat(work, flagstr[i][1], NELEMENTS(work)); - } - else { - milstr_ncat(work, flagstr[i][0], NELEMENTS(work)); - } - if (bit != 1) { - milstr_ncat(work, str_space, NELEMENTS(work)); - } - } - } - return(work); -} - -const OEMCHAR *debugsub_regs(void) { - -static OEMCHAR work[256]; - - OEMSPRINTF(work, str_register, CPU_EAX, CPU_EBX, CPU_ECX, CPU_EDX, - CPU_ESP, CPU_EBP, CPU_ESI, CPU_EDI, - CPU_DS, CPU_ES, CPU_SS, CPU_CS, CPU_EIP); - milstr_ncat(work, debugsub_flags(CPU_FLAG), NELEMENTS(work)); - milstr_ncat(work, CRCONST, NELEMENTS(work)); - return(work); -} - -void debugwriteseg(const OEMCHAR *fname, const descriptor_t *sd, - UINT32 addr, UINT32 size) { - - FILEH fh; - UINT8 buf[0x1000]; - UINT32 limit; - - limit = sd->u.seg.limit; - if (limit <= addr) { - return; - } - size = MIN(limit - addr, size - 1) + 1; - fh = file_create_c(fname); - if (fh == FILEH_INVALID) { - return; - } - addr += sd->u.seg.segbase; - while(size) { - limit = MIN(size, sizeof(buf)); - MEML_READS(addr, buf, limit); - file_write(fh, buf, limit); - addr += limit; - size -= limit; - } - file_close(fh); -} - -void debugsub_status(void) { - -static int filenum = 0; - FILEH fh; - OEMCHAR work[512]; -const OEMCHAR *p; - - OEMSPRINTF(work, file_i386reg, filenum); - fh = file_create_c(work); - if (fh != FILEH_INVALID) { - p = debugsub_regs(); - file_write(fh, p, OEMSTRLEN(p) * sizeof(OEMCHAR)); - OEMSPRINTF(work, str_picstat, - pic.pi[0].imr, pic.pi[0].irr, pic.pi[0].isr, - pic.pi[1].imr, pic.pi[1].irr, pic.pi[1].isr, - mouseif.upd8255.portc, sysport.c); - file_write(fh, work, OEMSTRLEN(work) * sizeof(OEMCHAR)); - - OEMSPRINTF(work, OEMTEXT("CS = %.8x:%.8x") OEMTEXT(CRLITERAL), - CPU_STAT_SREGBASE(CPU_CS_INDEX), - CPU_STAT_SREGLIMIT(CPU_CS_INDEX)); - file_write(fh, work, OEMSTRLEN(work) * sizeof(OEMCHAR)); - - file_close(fh); - } - - OEMSPRINTF(work, file_i386cs, filenum); - debugwriteseg(work, &CPU_STAT_SREG(CPU_CS_INDEX), CPU_EIP & 0xffff0000, 0x10000); - OEMSPRINTF(work, file_i386ds, filenum); - debugwriteseg(work, &CPU_STAT_SREG(CPU_DS_INDEX), 0, 0x10000); - OEMSPRINTF(work, file_i386es, filenum); - debugwriteseg(work, &CPU_STAT_SREG(CPU_ES_INDEX), 0, 0x10000); - OEMSPRINTF(work, file_i386ss, filenum); - debugwriteseg(work, &CPU_STAT_SREG(CPU_SS_INDEX), CPU_ESP & 0xffff0000, 0x10000); - filenum++; -} - -void debugsub_memorydump(void) { - - FILEH fh; - int i; - - fh = file_create_c(file_memorybin); - if (fh != FILEH_INVALID) { - for (i=0; i<34; i++) { - file_write(fh, mem + i*0x8000, 0x8000); - } - file_close(fh); - } -} - -void debugsub_memorydumpall(void) { - - FILEH fh; - - fh = file_create_c(file_memorybin); - if (fh != FILEH_INVALID) { - file_write(fh, mem, 0x110000); - if (CPU_EXTMEMSIZE > 0x10000) { - file_write(fh, CPU_EXTMEM + 0x10000, CPU_EXTMEMSIZE - 0x10000); - } - file_close(fh); - } -} - - -#if 0 // 俺用デバグ - -void debugpageptr(UINT32 addr) { - - FILEH fh; - char buf[256]; - UINT32 pde; - UINT32 pte; - UINT i; - UINT32 a; - - fh = file_create("page.txt"); - SPRINTF(buf, "CR3=%.8x\r\n", CPU_CR3); - file_write(fh, buf, strlen(buf)); - for (i=0; i<1024; i++) { - a = CPU_STAT_PDE_BASE + (i * 4); - pde = cpu_memoryread_d(a); - SPRINTF(buf, "%.8x=>%.8x [%.8x]\r\n", (i << 22), pde, a); - file_write(fh, buf, strlen(buf)); - } - addr >>= 22; - pde = cpu_memoryread_d(CPU_STAT_PDE_BASE + (addr * 4)); - for (i=0; i<1024; i++) { - a = (pde & CPU_PDE_BASEADDR_MASK) + (i * 4); - pte = cpu_memoryread_d(a); - SPRINTF(buf, "%.8x=>%.8x [%.8x]\r\n", (addr << 22) + (i << 12), pte, a); - file_write(fh, buf, strlen(buf)); - } - file_close(fh); -} - -#endif - +#include +#include +#include +#include +#include +#include +#include + +void debugwriteseg(const OEMCHAR *fname, const descriptor_t *sd, + UINT32 addr, UINT32 size); +void debugpageptr(UINT32 addr); + + +#if defined(MACOS) +#define CRLITERAL "\r" +#define CRCONST str_cr +#elif defined(X11) +#define CRLITERAL "\n" +#define CRCONST str_lf +#else +#define CRLITERAL "\r\n" +#define CRCONST str_crlf +#endif + + +static const OEMCHAR s_nv[] = OEMTEXT("NV"); +static const OEMCHAR s_ov[] = OEMTEXT("OV"); +static const OEMCHAR s_dn[] = OEMTEXT("DN"); +static const OEMCHAR s_up[] = OEMTEXT("UP"); +static const OEMCHAR s_di[] = OEMTEXT("DI"); +static const OEMCHAR s_ei[] = OEMTEXT("EI"); +static const OEMCHAR s_pl[] = OEMTEXT("PL"); +static const OEMCHAR s_ng[] = OEMTEXT("NG"); +static const OEMCHAR s_nz[] = OEMTEXT("NZ"); +static const OEMCHAR s_zr[] = OEMTEXT("ZR"); +static const OEMCHAR s_na[] = OEMTEXT("NA"); +static const OEMCHAR s_ac[] = OEMTEXT("AC"); +static const OEMCHAR s_po[] = OEMTEXT("PO"); +static const OEMCHAR s_pe[] = OEMTEXT("PE"); +static const OEMCHAR s_nc[] = OEMTEXT("NC"); +static const OEMCHAR s_cy[] = OEMTEXT("CY"); + +static const OEMCHAR *flagstr[16][2] = { + {NULL, NULL}, // 0x8000 + {NULL, NULL}, // 0x4000 + {NULL, NULL}, // 0x2000 + {NULL, NULL}, // 0x1000 + {s_nv, s_ov}, // 0x0800 + {s_dn, s_up}, // 0x0400 + {s_di, s_ei}, // 0x0200 + {NULL, NULL}, // 0x0100 + {s_pl, s_ng}, // 0x0080 + {s_nz, s_zr}, // 0x0040 + {NULL, NULL}, // 0x0020 + {s_na, s_ac}, // 0x0010 + {NULL, NULL}, // 0x0008 + {s_po, s_pe}, // 0x0004 + {NULL, NULL}, // 0x0002 + {s_nc, s_cy}}; // 0x0001 + +static const OEMCHAR file_i386reg[] = OEMTEXT("i386reg.%.3u"); +static const OEMCHAR file_i386cs[] = OEMTEXT("i386_cs.%.3u"); +static const OEMCHAR file_i386ds[] = OEMTEXT("i386_ds.%.3u"); +static const OEMCHAR file_i386es[] = OEMTEXT("i386_es.%.3u"); +static const OEMCHAR file_i386ss[] = OEMTEXT("i386_ss.%.3u"); +static const OEMCHAR file_memorybin[] = OEMTEXT("memory.bin"); + +static const OEMCHAR str_register[] = \ + OEMTEXT("EAX=%.8x EBX=%.8x ECX=%.8x EDX=%.8x") \ + OEMTEXT(CRLITERAL) \ + OEMTEXT("ESP=%.8x EBP=%.8x ESI=%.8x EDI=%.8x") \ + OEMTEXT(CRLITERAL) \ + OEMTEXT("DS=%.4x ES=%.4x SS=%.4x CS=%.4x ") \ + OEMTEXT("EIP=%.8x ") \ + OEMTEXT(CRLITERAL); +static const OEMCHAR str_picstat[] = \ + OEMTEXT("PIC0=%.2x:%.2x:%.2x") \ + OEMTEXT(CRLITERAL) \ + OEMTEXT("PIC1=%.2x:%.2x:%.2x") \ + OEMTEXT(CRLITERAL) \ + OEMTEXT("8255PORTC = %.2x / system-port = %.2x") \ + OEMTEXT(CRLITERAL); + + +const OEMCHAR *debugsub_flags(UINT16 flag) { + +static OEMCHAR work[128]; + int i; + UINT16 bit; + + work[0] = 0; + for (i=0, bit=0x8000; bit; i++, bit>>=1) { + if (flagstr[i][0]) { + if (flag & bit) { + milstr_ncat(work, flagstr[i][1], NELEMENTS(work)); + } + else { + milstr_ncat(work, flagstr[i][0], NELEMENTS(work)); + } + if (bit != 1) { + milstr_ncat(work, str_space, NELEMENTS(work)); + } + } + } + return(work); +} + +const OEMCHAR *debugsub_regs(void) { + +static OEMCHAR work[256]; + + OEMSPRINTF(work, str_register, CPU_EAX, CPU_EBX, CPU_ECX, CPU_EDX, + CPU_ESP, CPU_EBP, CPU_ESI, CPU_EDI, + CPU_DS, CPU_ES, CPU_SS, CPU_CS, CPU_EIP); + milstr_ncat(work, debugsub_flags(CPU_FLAG), NELEMENTS(work)); + milstr_ncat(work, CRCONST, NELEMENTS(work)); + return(work); +} + +void debugwriteseg(const OEMCHAR *fname, const descriptor_t *sd, + UINT32 addr, UINT32 size) { + + FILEH fh; + UINT8 buf[0x1000]; + UINT32 limit; + + limit = sd->u.seg.limit; + if (limit <= addr) { + return; + } + size = MIN(limit - addr, size - 1) + 1; + fh = file_create_c(fname); + if (fh == FILEH_INVALID) { + return; + } + addr += sd->u.seg.segbase; + while(size) { + limit = MIN(size, sizeof(buf)); + MEML_READS(addr, buf, limit); + file_write(fh, buf, limit); + addr += limit; + size -= limit; + } + file_close(fh); +} + +void debugsub_status(void) { + +static int filenum = 0; + FILEH fh; + OEMCHAR work[512]; +const OEMCHAR *p; + + OEMSPRINTF(work, file_i386reg, filenum); + fh = file_create_c(work); + if (fh != FILEH_INVALID) { + p = debugsub_regs(); + file_write(fh, p, OEMSTRLEN(p) * sizeof(OEMCHAR)); + OEMSPRINTF(work, str_picstat, + pic.pi[0].imr, pic.pi[0].irr, pic.pi[0].isr, + pic.pi[1].imr, pic.pi[1].irr, pic.pi[1].isr, + mouseif.upd8255.portc, sysport.c); + file_write(fh, work, OEMSTRLEN(work) * sizeof(OEMCHAR)); + + OEMSPRINTF(work, OEMTEXT("CS = %.8x:%.8x") OEMTEXT(CRLITERAL), + CPU_STAT_SREGBASE(CPU_CS_INDEX), + CPU_STAT_SREGLIMIT(CPU_CS_INDEX)); + file_write(fh, work, OEMSTRLEN(work) * sizeof(OEMCHAR)); + + file_close(fh); + } + + OEMSPRINTF(work, file_i386cs, filenum); + debugwriteseg(work, &CPU_STAT_SREG(CPU_CS_INDEX), CPU_EIP & 0xffff0000, 0x10000); + OEMSPRINTF(work, file_i386ds, filenum); + debugwriteseg(work, &CPU_STAT_SREG(CPU_DS_INDEX), 0, 0x10000); + OEMSPRINTF(work, file_i386es, filenum); + debugwriteseg(work, &CPU_STAT_SREG(CPU_ES_INDEX), 0, 0x10000); + OEMSPRINTF(work, file_i386ss, filenum); + debugwriteseg(work, &CPU_STAT_SREG(CPU_SS_INDEX), CPU_ESP & 0xffff0000, 0x10000); + filenum++; +} + +void debugsub_memorydump(void) { + + FILEH fh; + int i; + + fh = file_create_c(file_memorybin); + if (fh != FILEH_INVALID) { + for (i=0; i<34; i++) { + file_write(fh, mem + i*0x8000, 0x8000); + } + file_close(fh); + } +} + +void debugsub_memorydumpall(void) { + + FILEH fh; + + fh = file_create_c(file_memorybin); + if (fh != FILEH_INVALID) { + file_write(fh, mem, 0x110000); + if (CPU_EXTMEMSIZE > 0x10000) { + file_write(fh, CPU_EXTMEM + 0x10000, CPU_EXTMEMSIZE - 0x10000); + } + file_close(fh); + } +} + + +#if 0 // 俺用デバグ + +void debugpageptr(UINT32 addr) { + + FILEH fh; + char buf[256]; + UINT32 pde; + UINT32 pte; + UINT i; + UINT32 a; + + fh = file_create("page.txt"); + SPRINTF(buf, "CR3=%.8x\r\n", CPU_CR3); + file_write(fh, buf, strlen(buf)); + for (i=0; i<1024; i++) { + a = CPU_STAT_PDE_BASE + (i * 4); + pde = cpu_memoryread_d(a); + SPRINTF(buf, "%.8x=>%.8x [%.8x]\r\n", (i << 22), pde, a); + file_write(fh, buf, strlen(buf)); + } + addr >>= 22; + pde = cpu_memoryread_d(CPU_STAT_PDE_BASE + (addr * 4)); + for (i=0; i<1024; i++) { + a = (pde & CPU_PDE_BASEADDR_MASK) + (i * 4); + pte = cpu_memoryread_d(a); + SPRINTF(buf, "%.8x=>%.8x [%.8x]\r\n", (addr << 22) + (i << 12), pte, a); + file_write(fh, buf, strlen(buf)); + } + file_close(fh); +} + +#endif + diff --git a/diskimage/cd/cdd_ccd.c b/diskimage/cd/cdd_ccd.c old mode 100755 new mode 100644 index d698dcf8..9b9ad55c --- a/diskimage/cd/cdd_ccd.c +++ b/diskimage/cd/cdd_ccd.c @@ -1,172 +1,172 @@ -#include -#include -#include -#include -#include - -#ifdef SUPPORT_KAI_IMAGES - -#include "diskimage/cddfile.h" -#include "diskimage/cd/cdd_cue.h" - -static const OEMCHAR str_img[] = OEMTEXT(".img"); - -static const OEMCHAR str__mode1[] = OEMTEXT("MODE=1"); -static const OEMCHAR str__mode0[] = OEMTEXT("MODE=0"); - -#if 0 -"Entry" -"Point" -"ADR" -"Control" -"AMin" -"ASec" -"AFrame" -"ALBA" -"Zero" -"PMin" -"PSec" -"PFrame" -"PLBA" -#endif - -// CCD(&CDM)読み込み -BRESULT openccd(SXSIDEV sxsi, const OEMCHAR *fname) { - - _CDTRK trk[99]; - OEMCHAR path[MAX_PATH]; - UINT index; - UINT16 curssize; - UINT8 curtrk; - UINT curtype; - UINT32 curpos0; - TEXTFILEH tfh; - OEMCHAR buf[512]; - OEMCHAR *argv[8]; - int argc; - - ZeroMemory(trk, sizeof(trk)); - path[0] = '\0'; - index = 0; - curssize = 2352; // セクタサイズは2352byte固定…でいいのかな? - curtrk = 1; - curtype = 0x14; - curpos0 = 0; - - // イメージファイルの実体は"*.img"固定…でいいのかな? - file_cpyname(path, fname, NELEMENTS(path)); - file_cutext(path); - file_catname(path, str_img, NELEMENTS(path)); - - tfh = textfile_open(fname, 0x800); - if (tfh == NULL) { - goto openccd_err2; - } - while (textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) { - if (!milstr_cmp(buf, str__mode1)) { - curtype = 0x14; - } - else if (!milstr_cmp(buf, str__mode0)) { - curtype = 0x10; - } - argc = milstr_getarg(buf, argv, NELEMENTS(argv)); - if ((argc >= 2) && (!milstr_cmp(argv[0] + 1, str_track))) { - curtrk = (UINT8)milstr_solveINT(argv[1]); - } - else if ((argc >= 2) && (!milstr_cmp(argv[0], str_index))) { - if (index < NELEMENTS(trk)) { - // "INDEX 0"、セクタを記録 - if ((UINT8)milstr_solveINT(argv[1]) == 0) { - curpos0 = (UINT32)milstr_solveINT(argv[1] + 2); - continue; - } - trk[index].adr_ctl = curtype; - trk[index].point = curtrk; - trk[index].pos = (UINT32)milstr_solveINT(argv[1] + 2); - trk[index].pos0 = curpos0; - - trk[index].sector_size = curssize; - - index++; - - curpos0 = 0; - } - } - } - - if (index == 0) { - goto openccd_err1; - } - - sxsi->read = sec2352_read_with_ecc; //sec2352_read; - sxsi->totals = -1; - - textfile_close(tfh); - - return(setsxsidev(sxsi, path, trk, index)); - -openccd_err1: - textfile_close(tfh); - -openccd_err2: - return(FAILURE); -} - -// 参照部分の記述内容がCloneCD(*.ccd)と同じため、とりあえず封印 -#if 0 -static BRESULT opencdm(SXSIDEV sxsi, const OEMCHAR *fname) { - - _CDTRK trk[99]; - OEMCHAR path[MAX_PATH]; - UINT index; - UINT8 curtrk; - UINT curtype; - TEXTFILEH tfh; - OEMCHAR buf[512]; - OEMCHAR *argv[8]; - int argc; - - ZeroMemory(trk, sizeof(trk)); - path[0] = '\0'; - index = -1; -// index = 0; - curtrk = 1; - curtype = 0x14; - - file_cpyname(path, fname, NELEMENTS(path)); - file_cutext(path); - file_catname(path, str_img, NELEMENTS(path)); - - tfh = textfile_open(fname, 0x800); - if (tfh == NULL) { - return(FAILURE); - } - while(textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) { - if (!milstr_cmp(buf, str__mode1)) { - curtype = 0x14; - } - else if (!milstr_cmp(buf, str__mode0)) { - curtype = 0x10; - } - argc = milstr_getarg(buf, argv, NELEMENTS(argv)); - if ((argc >= 2) && (!milstr_cmp(argv[0] + 1, str_track))) { - index++; - //curtrk++; - curtrk = (UINT8)milstr_solveINT(argv[1]); - } - else if ((argc >= 2) && (!milstr_cmp(argv[0], str_index))) { - if (index < NELEMENTS(trk)) { - trk[index].type = curtype; - trk[index].track = curtrk; - trk[index].pos = (UINT32)milstr_solveINT(argv[1] + 2); -// index++; - } - } - } - textfile_close(tfh); - - return(setsxsidev(sxsi, path, trk, index)); -} -#endif - -#endif +#include +#include +#include +#include +#include + +#ifdef SUPPORT_KAI_IMAGES + +#include "diskimage/cddfile.h" +#include "diskimage/cd/cdd_cue.h" + +static const OEMCHAR str_img[] = OEMTEXT(".img"); + +static const OEMCHAR str__mode1[] = OEMTEXT("MODE=1"); +static const OEMCHAR str__mode0[] = OEMTEXT("MODE=0"); + +#if 0 +"Entry" +"Point" +"ADR" +"Control" +"AMin" +"ASec" +"AFrame" +"ALBA" +"Zero" +"PMin" +"PSec" +"PFrame" +"PLBA" +#endif + +// CCD(&CDM)読み込み +BRESULT openccd(SXSIDEV sxsi, const OEMCHAR *fname) { + + _CDTRK trk[99]; + OEMCHAR path[MAX_PATH]; + UINT index; + UINT16 curssize; + UINT8 curtrk; + UINT curtype; + UINT32 curpos0; + TEXTFILEH tfh; + OEMCHAR buf[512]; + OEMCHAR *argv[8]; + int argc; + + ZeroMemory(trk, sizeof(trk)); + path[0] = '\0'; + index = 0; + curssize = 2352; // セクタサイズは2352byte固定…でいいのかな? + curtrk = 1; + curtype = 0x14; + curpos0 = 0; + + // イメージファイルの実体は"*.img"固定…でいいのかな? + file_cpyname(path, fname, NELEMENTS(path)); + file_cutext(path); + file_catname(path, str_img, NELEMENTS(path)); + + tfh = textfile_open(fname, 0x800); + if (tfh == NULL) { + goto openccd_err2; + } + while (textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) { + if (!milstr_cmp(buf, str__mode1)) { + curtype = 0x14; + } + else if (!milstr_cmp(buf, str__mode0)) { + curtype = 0x10; + } + argc = milstr_getarg(buf, argv, NELEMENTS(argv)); + if ((argc >= 2) && (!milstr_cmp(argv[0] + 1, str_track))) { + curtrk = (UINT8)milstr_solveINT(argv[1]); + } + else if ((argc >= 2) && (!milstr_cmp(argv[0], str_index))) { + if (index < NELEMENTS(trk)) { + // "INDEX 0"、セクタを記録 + if ((UINT8)milstr_solveINT(argv[1]) == 0) { + curpos0 = (UINT32)milstr_solveINT(argv[1] + 2); + continue; + } + trk[index].adr_ctl = curtype; + trk[index].point = curtrk; + trk[index].pos = (UINT32)milstr_solveINT(argv[1] + 2); + trk[index].pos0 = curpos0; + + trk[index].sector_size = curssize; + + index++; + + curpos0 = 0; + } + } + } + + if (index == 0) { + goto openccd_err1; + } + + sxsi->read = sec2352_read_with_ecc; //sec2352_read; + sxsi->totals = -1; + + textfile_close(tfh); + + return(setsxsidev(sxsi, path, trk, index)); + +openccd_err1: + textfile_close(tfh); + +openccd_err2: + return(FAILURE); +} + +// 参照部分の記述内容がCloneCD(*.ccd)と同じため、とりあえず封印 +#if 0 +static BRESULT opencdm(SXSIDEV sxsi, const OEMCHAR *fname) { + + _CDTRK trk[99]; + OEMCHAR path[MAX_PATH]; + UINT index; + UINT8 curtrk; + UINT curtype; + TEXTFILEH tfh; + OEMCHAR buf[512]; + OEMCHAR *argv[8]; + int argc; + + ZeroMemory(trk, sizeof(trk)); + path[0] = '\0'; + index = -1; +// index = 0; + curtrk = 1; + curtype = 0x14; + + file_cpyname(path, fname, NELEMENTS(path)); + file_cutext(path); + file_catname(path, str_img, NELEMENTS(path)); + + tfh = textfile_open(fname, 0x800); + if (tfh == NULL) { + return(FAILURE); + } + while(textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) { + if (!milstr_cmp(buf, str__mode1)) { + curtype = 0x14; + } + else if (!milstr_cmp(buf, str__mode0)) { + curtype = 0x10; + } + argc = milstr_getarg(buf, argv, NELEMENTS(argv)); + if ((argc >= 2) && (!milstr_cmp(argv[0] + 1, str_track))) { + index++; + //curtrk++; + curtrk = (UINT8)milstr_solveINT(argv[1]); + } + else if ((argc >= 2) && (!milstr_cmp(argv[0], str_index))) { + if (index < NELEMENTS(trk)) { + trk[index].type = curtype; + trk[index].track = curtrk; + trk[index].pos = (UINT32)milstr_solveINT(argv[1] + 2); +// index++; + } + } + } + textfile_close(tfh); + + return(setsxsidev(sxsi, path, trk, index)); +} +#endif + +#endif diff --git a/diskimage/cd/cdd_ccd.h b/diskimage/cd/cdd_ccd.h old mode 100755 new mode 100644 index 3bb8c510..258c8c16 --- a/diskimage/cd/cdd_ccd.h +++ b/diskimage/cd/cdd_ccd.h @@ -1,13 +1,13 @@ -#ifdef __cplusplus -extern "C" { -#endif - -extern const OEMCHAR str_ccd[]; -extern const OEMCHAR str_cdm[]; - -BRESULT openccd(SXSIDEV sxsi, const OEMCHAR *fname); -//BRESULT opencdm(SXSIDEV sxsi, const OEMCHAR *fname); - -#ifdef __cplusplus -} -#endif +#ifdef __cplusplus +extern "C" { +#endif + +extern const OEMCHAR str_ccd[]; +extern const OEMCHAR str_cdm[]; + +BRESULT openccd(SXSIDEV sxsi, const OEMCHAR *fname); +//BRESULT opencdm(SXSIDEV sxsi, const OEMCHAR *fname); + +#ifdef __cplusplus +} +#endif diff --git a/diskimage/cd/cdd_cue.c b/diskimage/cd/cdd_cue.c old mode 100755 new mode 100644 index b4cddd00..b3ee3e5c --- a/diskimage/cd/cdd_cue.c +++ b/diskimage/cd/cdd_cue.c @@ -1,185 +1,185 @@ -#include -#include -#include -#include - -#ifdef SUPPORT_KAI_IMAGES - -#include "diskimage/cddfile.h" - -//const OEMCHAR str_cue[] = OEMTEXT("cue"); // CUEシート - -// CDD_CCD.Cで共有するための暫定処置 -const OEMCHAR str_track[] = OEMTEXT("TRACK"); -const OEMCHAR str_index[] = OEMTEXT("INDEX"); -// - -static const OEMCHAR str_file[] = OEMTEXT("FILE"); -static const OEMCHAR str_binary[] = OEMTEXT("BINARY"); -static const OEMCHAR str_wave[] = OEMTEXT("WAVE"); -//static const OEMCHAR str_track[] = OEMTEXT("TRACK"); -static const OEMCHAR str_pregap[] = OEMTEXT("PREGAP"); -//static const OEMCHAR str_index[] = OEMTEXT("INDEX"); -static const OEMCHAR str_mode1[] = OEMTEXT("MODE1"); -static const OEMCHAR str_mode2[] = OEMTEXT("MODE2"); // 暫定対応 -static const OEMCHAR str_audio[] = OEMTEXT("AUDIO"); - -//static BRESULT getint2(const OEMCHAR *str, UINT *val) { -// -// if ((str[0] < '0') || (str[0] > '9') || -// (str[1] < '0') || (str[1] > '9')) { -// return(FAILURE); -// } -// if (val) { -// *val = ((str[0] - '0') * 10) + (str[1] - '0'); -// } -// return(SUCCESS); -//} - -static UINT32 getpos(const OEMCHAR *str) { - - UINT m = 0; - UINT s = 0; - UINT f = 0; - - int idx = 0; // 文字位置 - UINT sdata[3] = {0}; // 数値バッファ - UINT sdatapos = 0; // 数値バッファの格納位置 - int numdig = 0; // 通知の桁数 - - while(str[idx]){ // NULL文字まで続ける - if('0' <= str[idx] && str[idx] <= '9'){ // 0から9の数字ならバッファに入れる - sdata[sdatapos] *= 10; // 桁上げ - sdata[sdatapos] += (str[idx] - '0'); - numdig++; // 桁数カウント - }else if(str[idx] == ':' && numdig >= 1){ // 「:」なら区切り文字(ただし、数字が一桁も無い場合は不正扱い) - if(sdatapos == 2){ - break; // 3個目のデータならループを抜ける(配列を3つ分しか確保していない&そもそも4つ以上があり得ないので) - } - sdatapos++; // 格納位置変更 - numdig = 0; // 桁数カウントリセット - }else{ - return(0); // 不正な文字 - } - idx++; - } - sdatapos++; // データ数にするために1を足す - if(sdatapos!=3){ - return(0); // データ数が変(3個ではない) - } - m = sdata[0]; - s = sdata[1]; - f = sdata[2]; - return((((m * 60) + s) * 75) + f); -} - -// CUEシート読み込み -BRESULT opencue(SXSIDEV sxsi, const OEMCHAR *fname) { - - _CDTRK trk[99]; - OEMCHAR path[MAX_PATH]; - UINT index; - UINT8 curtrk; - UINT curtype; - TEXTFILEH tfh; - OEMCHAR buf_mode[10]; - OEMCHAR buf[512]; - OEMCHAR *argv[8]; - int argc; -// -------- - UINT16 curssize = 0; - UINT32 curpos0; - UINT32 curpregap; - - ZeroMemory(trk, sizeof(trk)); - path[0] = '\0'; - index = 0; - curtrk = 1; - curtype = 0x14; -// -------- - curpos0 = 0; - curpregap = 0; -// -------- - - tfh = textfile_open(fname, 0x800); - if (tfh == NULL) { - goto opencue_err2; - } - while (textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) { - argc = milstr_getarg(buf, argv, NELEMENTS(argv)); - if ((argc >= 3) && (!milstr_cmp(argv[0], str_file))) { // FILE - if (!milstr_cmp(argv[argc-1], str_binary) && path[0] == '\0') { // BINARY - file_cpyname(path, fname, NELEMENTS(path)); - file_cutname(path); - file_catname(path, argv[1], NELEMENTS(path)); - } - } - else if ((argc >= 3) && (!milstr_cmp(argv[0], str_track))) { // TRACK - curtrk = (UINT8)milstr_solveINT(argv[1]); - milstr_ncpy(buf_mode, argv[2], NELEMENTS(str_mode1)); - if (!milstr_cmp(buf_mode, str_mode1)) { // MODE1/???? - curtype = 0x14; - curssize = (UINT16)milstr_solveINT(argv[2] + 6); - } - else if (!milstr_cmp(buf_mode, str_mode2)) { // MODE2/???? - curtype = 0x14; - curssize = (UINT16)milstr_solveINT(argv[2] + 6); - } - else if (!milstr_cmp(argv[2], str_audio)) { // AUDIO - curtype = 0x10; - curssize = 2352; - } - } - else if ((argc >= 2) && (!milstr_cmp(argv[0], str_pregap))) { // PREGAP - curpregap = getpos(argv[1]); - } - else if ((argc >= 3) && (!milstr_cmp(argv[0], str_index))) { // INDEX ?? - if (index < NELEMENTS(trk)) { - if ((UINT8)milstr_solveINT(argv[1]) == 0) { // INDEX 00 - curpos0 = getpos(argv[2]); - continue; - } - if ((UINT8)milstr_solveINT(argv[1]) != 1) { // INDEX 01以外 - continue; - } - - trk[index].adr_ctl = curtype; - trk[index].point = curtrk; - trk[index].pos = getpos(argv[2]); - trk[index].pos0 = (curpos0 == 0) ? trk[index].pos : curpos0; - - trk[index].sector_size = curssize; - - trk[index].pregap_sectors = curpregap + (trk[index].pos - trk[index].pos0); - - trk[index].img_pregap_sec = (trk[index].pos0 == 0) ? trk[index].pos : trk[index].pos0; - trk[index].img_start_sec = trk[index].pos; - -// trk[index].pregap_sector = trk[index].start_sector - trk[index].pregap_sectors; - - index++; - curpregap = 0; - curpos0 = 0; - } - } - } - - if (index == 0) { - goto opencue_err1; - } - - set_secread(sxsi, trk, index); - sxsi->totals = -1; - - textfile_close(tfh); - - return(setsxsidev(sxsi, path, trk, index)); - -opencue_err1: - textfile_close(tfh); - -opencue_err2: - return(FAILURE); -} - -#endif +#include +#include +#include +#include + +#ifdef SUPPORT_KAI_IMAGES + +#include "diskimage/cddfile.h" + +//const OEMCHAR str_cue[] = OEMTEXT("cue"); // CUEシート + +// CDD_CCD.Cで共有するための暫定処置 +const OEMCHAR str_track[] = OEMTEXT("TRACK"); +const OEMCHAR str_index[] = OEMTEXT("INDEX"); +// + +static const OEMCHAR str_file[] = OEMTEXT("FILE"); +static const OEMCHAR str_binary[] = OEMTEXT("BINARY"); +static const OEMCHAR str_wave[] = OEMTEXT("WAVE"); +//static const OEMCHAR str_track[] = OEMTEXT("TRACK"); +static const OEMCHAR str_pregap[] = OEMTEXT("PREGAP"); +//static const OEMCHAR str_index[] = OEMTEXT("INDEX"); +static const OEMCHAR str_mode1[] = OEMTEXT("MODE1"); +static const OEMCHAR str_mode2[] = OEMTEXT("MODE2"); // 暫定対応 +static const OEMCHAR str_audio[] = OEMTEXT("AUDIO"); + +//static BRESULT getint2(const OEMCHAR *str, UINT *val) { +// +// if ((str[0] < '0') || (str[0] > '9') || +// (str[1] < '0') || (str[1] > '9')) { +// return(FAILURE); +// } +// if (val) { +// *val = ((str[0] - '0') * 10) + (str[1] - '0'); +// } +// return(SUCCESS); +//} + +static UINT32 getpos(const OEMCHAR *str) { + + UINT m = 0; + UINT s = 0; + UINT f = 0; + + int idx = 0; // 文字位置 + UINT sdata[3] = {0}; // 数値バッファ + UINT sdatapos = 0; // 数値バッファの格納位置 + int numdig = 0; // 通知の桁数 + + while(str[idx]){ // NULL文字まで続ける + if('0' <= str[idx] && str[idx] <= '9'){ // 0から9の数字ならバッファに入れる + sdata[sdatapos] *= 10; // 桁上げ + sdata[sdatapos] += (str[idx] - '0'); + numdig++; // 桁数カウント + }else if(str[idx] == ':' && numdig >= 1){ // 「:」なら区切り文字(ただし、数字が一桁も無い場合は不正扱い) + if(sdatapos == 2){ + break; // 3個目のデータならループを抜ける(配列を3つ分しか確保していない&そもそも4つ以上があり得ないので) + } + sdatapos++; // 格納位置変更 + numdig = 0; // 桁数カウントリセット + }else{ + return(0); // 不正な文字 + } + idx++; + } + sdatapos++; // データ数にするために1を足す + if(sdatapos!=3){ + return(0); // データ数が変(3個ではない) + } + m = sdata[0]; + s = sdata[1]; + f = sdata[2]; + return((((m * 60) + s) * 75) + f); +} + +// CUEシート読み込み +BRESULT opencue(SXSIDEV sxsi, const OEMCHAR *fname) { + + _CDTRK trk[99]; + OEMCHAR path[MAX_PATH]; + UINT index; + UINT8 curtrk; + UINT curtype; + TEXTFILEH tfh; + OEMCHAR buf_mode[10]; + OEMCHAR buf[512]; + OEMCHAR *argv[8]; + int argc; +// -------- + UINT16 curssize = 0; + UINT32 curpos0; + UINT32 curpregap; + + ZeroMemory(trk, sizeof(trk)); + path[0] = '\0'; + index = 0; + curtrk = 1; + curtype = 0x14; +// -------- + curpos0 = 0; + curpregap = 0; +// -------- + + tfh = textfile_open(fname, 0x800); + if (tfh == NULL) { + goto opencue_err2; + } + while (textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) { + argc = milstr_getarg(buf, argv, NELEMENTS(argv)); + if ((argc >= 3) && (!milstr_cmp(argv[0], str_file))) { // FILE + if (!milstr_cmp(argv[argc-1], str_binary) && path[0] == '\0') { // BINARY + file_cpyname(path, fname, NELEMENTS(path)); + file_cutname(path); + file_catname(path, argv[1], NELEMENTS(path)); + } + } + else if ((argc >= 3) && (!milstr_cmp(argv[0], str_track))) { // TRACK + curtrk = (UINT8)milstr_solveINT(argv[1]); + milstr_ncpy(buf_mode, argv[2], NELEMENTS(str_mode1)); + if (!milstr_cmp(buf_mode, str_mode1)) { // MODE1/???? + curtype = 0x14; + curssize = (UINT16)milstr_solveINT(argv[2] + 6); + } + else if (!milstr_cmp(buf_mode, str_mode2)) { // MODE2/???? + curtype = 0x14; + curssize = (UINT16)milstr_solveINT(argv[2] + 6); + } + else if (!milstr_cmp(argv[2], str_audio)) { // AUDIO + curtype = 0x10; + curssize = 2352; + } + } + else if ((argc >= 2) && (!milstr_cmp(argv[0], str_pregap))) { // PREGAP + curpregap = getpos(argv[1]); + } + else if ((argc >= 3) && (!milstr_cmp(argv[0], str_index))) { // INDEX ?? + if (index < NELEMENTS(trk)) { + if ((UINT8)milstr_solveINT(argv[1]) == 0) { // INDEX 00 + curpos0 = getpos(argv[2]); + continue; + } + if ((UINT8)milstr_solveINT(argv[1]) != 1) { // INDEX 01以外 + continue; + } + + trk[index].adr_ctl = curtype; + trk[index].point = curtrk; + trk[index].pos = getpos(argv[2]); + trk[index].pos0 = (curpos0 == 0) ? trk[index].pos : curpos0; + + trk[index].sector_size = curssize; + + trk[index].pregap_sectors = curpregap + (trk[index].pos - trk[index].pos0); + + trk[index].img_pregap_sec = (trk[index].pos0 == 0) ? trk[index].pos : trk[index].pos0; + trk[index].img_start_sec = trk[index].pos; + +// trk[index].pregap_sector = trk[index].start_sector - trk[index].pregap_sectors; + + index++; + curpregap = 0; + curpos0 = 0; + } + } + } + + if (index == 0) { + goto opencue_err1; + } + + set_secread(sxsi, trk, index); + sxsi->totals = -1; + + textfile_close(tfh); + + return(setsxsidev(sxsi, path, trk, index)); + +opencue_err1: + textfile_close(tfh); + +opencue_err2: + return(FAILURE); +} + +#endif diff --git a/diskimage/cd/cdd_cue.h b/diskimage/cd/cdd_cue.h old mode 100755 new mode 100644 index 05394edf..9eb9f106 --- a/diskimage/cd/cdd_cue.h +++ b/diskimage/cd/cdd_cue.h @@ -1,13 +1,13 @@ -#ifdef __cplusplus -extern "C" { -#endif - -extern const OEMCHAR str_cue[]; -extern const OEMCHAR str_track[]; -extern const OEMCHAR str_index[]; - -BRESULT opencue(SXSIDEV sxsi, const OEMCHAR *fname); - -#ifdef __cplusplus -} -#endif +#ifdef __cplusplus +extern "C" { +#endif + +extern const OEMCHAR str_cue[]; +extern const OEMCHAR str_track[]; +extern const OEMCHAR str_index[]; + +BRESULT opencue(SXSIDEV sxsi, const OEMCHAR *fname); + +#ifdef __cplusplus +} +#endif diff --git a/diskimage/cd/cdd_iso.c b/diskimage/cd/cdd_iso.c old mode 100755 new mode 100644 index be5ad7a7..9d24a413 --- a/diskimage/cd/cdd_iso.c +++ b/diskimage/cd/cdd_iso.c @@ -1,80 +1,80 @@ -#include -#include -#include - -#ifdef SUPPORT_KAI_IMAGES - -#include "diskimage/cddfile.h" - -// 指定ファイルをISOイメージとみなして開く -BRESULT openiso(SXSIDEV sxsi, const OEMCHAR *path) { - - _CDTRK trk[99]; - UINT trks; - FILEH fh; - UINT16 sector_size; - long totals; - - ZeroMemory(trk, sizeof(trk)); - trks = 0; - - fh = file_open_rb(path); - if (fh == FILEH_INVALID) { - goto openiso_err1; - } - - // ファイルサイズが2048byte、2352byte、2448byteのどれかで割り切れるかチェック - sxsi->read = sec2048_read; - sector_size = 2048; - totals = issec2048(fh); - if (totals < 0) { - sxsi->read = sec2352_read_with_ecc; - sector_size = 2352; - totals = issec2352(fh); - } - if (totals < 0) { - sxsi->read = sec2448_read; - sector_size = 2448; - totals = issec2448(fh); - } - if (totals < 0) { - goto openiso_err2; - } - - trk[0].adr_ctl = TRACKTYPE_DATA; - trk[0].point = 1; - trk[0].pos = 0; - trk[0].pos0 = 0; - - trk[0].sector_size = sector_size; - - trk[0].pregap_sector = 0; - trk[0].start_sector = 0; - trk[0].end_sector = totals; - - trk[0].img_pregap_sec = 0; - trk[0].img_start_sec = 0; - trk[0].img_end_sec = totals; - - trk[0].pregap_offset = 0; - trk[0].start_offset = 0; - trk[0].end_offset = totals * sector_size; - - trk[0].pregap_sectors = 0; - trk[0].track_sectors = totals; - trks = 1; - - sxsi->totals = totals; - - file_close(fh); - - return(setsxsidev(sxsi, path, trk, trks)); - -openiso_err2: - file_close(fh); - -openiso_err1: - return(FAILURE); -} - -#endif +#include +#include +#include + +#ifdef SUPPORT_KAI_IMAGES + +#include "diskimage/cddfile.h" + +// 指定ファイルをISOイメージとみなして開く +BRESULT openiso(SXSIDEV sxsi, const OEMCHAR *path) { + + _CDTRK trk[99]; + UINT trks; + FILEH fh; + UINT16 sector_size; + long totals; + + ZeroMemory(trk, sizeof(trk)); + trks = 0; + + fh = file_open_rb(path); + if (fh == FILEH_INVALID) { + goto openiso_err1; + } + + // ファイルサイズが2048byte、2352byte、2448byteのどれかで割り切れるかチェック + sxsi->read = sec2048_read; + sector_size = 2048; + totals = issec2048(fh); + if (totals < 0) { + sxsi->read = sec2352_read_with_ecc; + sector_size = 2352; + totals = issec2352(fh); + } + if (totals < 0) { + sxsi->read = sec2448_read; + sector_size = 2448; + totals = issec2448(fh); + } + if (totals < 0) { + goto openiso_err2; + } + + trk[0].adr_ctl = TRACKTYPE_DATA; + trk[0].point = 1; + trk[0].pos = 0; + trk[0].pos0 = 0; + + trk[0].sector_size = sector_size; + + trk[0].pregap_sector = 0; + trk[0].start_sector = 0; + trk[0].end_sector = totals; + + trk[0].img_pregap_sec = 0; + trk[0].img_start_sec = 0; + trk[0].img_end_sec = totals; + + trk[0].pregap_offset = 0; + trk[0].start_offset = 0; + trk[0].end_offset = totals * sector_size; + + trk[0].pregap_sectors = 0; + trk[0].track_sectors = totals; + trks = 1; + + sxsi->totals = totals; + + file_close(fh); + + return(setsxsidev(sxsi, path, trk, trks)); + +openiso_err2: + file_close(fh); + +openiso_err1: + return(FAILURE); +} + +#endif diff --git a/diskimage/cd/cdd_iso.h b/diskimage/cd/cdd_iso.h old mode 100755 new mode 100644 index 16f22f8b..a946132c --- a/diskimage/cd/cdd_iso.h +++ b/diskimage/cd/cdd_iso.h @@ -1,9 +1,9 @@ -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT openiso(SXSIDEV sxsi, const OEMCHAR *path); - -#ifdef __cplusplus -} -#endif +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT openiso(SXSIDEV sxsi, const OEMCHAR *path); + +#ifdef __cplusplus +} +#endif diff --git a/diskimage/cd/cdd_mds.c b/diskimage/cd/cdd_mds.c old mode 100755 new mode 100644 index 5be79a65..2d24adb2 --- a/diskimage/cd/cdd_mds.c +++ b/diskimage/cd/cdd_mds.c @@ -1,284 +1,284 @@ -#include -#include -#include - -#ifdef SUPPORT_KAI_IMAGES - -#include "diskimage/cddfile.h" - -#define LOADINTELQWORD(a) (*((UINT64 *)(a))) - -static const OEMCHAR str_mdf[] = OEMTEXT(".mdf"); - -static const UINT8 mds_sig[16] = - {'M','E','D','I','A',' ','D','E','S','C','R','I','P','T','O','R'}; - -#define MDS_MEDIUM_CD 0x00 // CD-ROM -#define MDS_MEDIUM_CD_R 0x01 // CD-R -#define MDS_MEDIUM_CD_RW 0x02 // CD-RW -#define MDS_MEDIUM_DVD 0x10 // DVD-ROM -#define MDS_MEDIUM_DVD_MINUS_R 0x12 // DVD-R - -#define MDS_TRACKMODE_UNKNOWN 0x00 -#define MDS_TRACKMODE_AUDIO 0xA9 // sector size = 2352 -#define MDS_TRACKMODE_MODE1 0xAA // sector size = 2048 -#define MDS_TRACKMODE_MODE2 0xAB // sector size = 2336 -#define MDS_TRACKMODE_MODE2_FORM1 0xAC // sector size = 2048 -#define MDS_TRACKMODE_MODE2_FORM2 0xAD // sector size = 2324 (+4) - -#define MDS_SUBCHAN_NONE 0x00 // no subchannel -#define MDS_SUBCHAN_PW_INTERLEAVED 0x08 // 96-byte PW subchannel, interleaved - -#define MDS_POINT_TRACK_FIRST 0xA0 // info about first track -#define MDS_POINT_TRACK_LAST 0xA1 // info about last track -#define MDS_POINT_TRACK_LEADOUT 0xA2 // info about lead-out - -#if defined(__GNUC__) -typedef struct { - UINT8 signature[16]; /* 0x0000 "MEDIA DESCRIPTOR" */ - UINT8 version[2]; /* 0x0010 Version ? */ - UINT16 medium_type; /* 0x0012 Medium type */ - UINT16 num_sessions; /* 0x0014 Number of sessions */ - UINT16 __dummy1__[2]; /* 0x0016 Wish I knew... */ - UINT16 bca_len; /* 0x001A Length of BCA data (DVD-ROM) */ - UINT32 __dummy2__[2]; /* 0x001C */ - UINT32 bca_data_offset; /* 0x0026 Offset to BCA data (DVD-ROM) */ - UINT32 __dummy3__[6]; /* 0x002A Probably more offsets */ - UINT32 disc_structures_offset; /* 0x0042 Offset to disc structures */ - UINT32 __dummy4__[3]; /* 0x0046 Probably more offsets */ - UINT32 sessions_blocks_offset; /* 0x0052 Offset to session blocks */ - UINT32 dpm_blocks_offset; /* 0x0056 offset to DPM data blocks */ -} __attribute__ ((packed)) MDS_Header; /* length: 88 bytes */ - -typedef struct { - INT32 session_start; /* Session's start address */ - INT32 session_end; /* Session's end address */ - UINT16 session_number; /* (Unknown) */ - UINT8 num_all_blocks; /* Number of all data blocks. */ - UINT8 num_nontrack_blocks; /* Number of lead-in data blocks */ - UINT16 first_track; /* Total number of sessions in image? */ - UINT16 last_track; /* Number of regular track data blocks. */ - UINT32 __dummy2__; /* (unknown) */ - UINT32 tracks_blocks_offset; /* Offset of lead-in+regular track data blocks. */ -} __attribute__ ((packed)) MDS_SessionBlock; /* length: 24 bytes */ - -typedef struct { - UINT8 mode; /* Track mode */ - UINT8 subchannel; /* Subchannel mode */ - UINT8 adr_ctl; /* Adr/Ctl */ - UINT8 __dummy2__; /* Track flags? */ - UINT8 point; /* Track number. (>0x99 is lead-in track) */ - - UINT32 __dummy3__; - UINT8 min; /* Min */ - UINT8 sec; /* Sec */ - UINT8 frame; /* Frame */ - UINT32 extra_offset; /* Start offset of this track's extra block. */ - UINT16 sector_size; /* Sector size. */ - - UINT8 __dummy4__[18]; - UINT32 start_sector; /* Track start sector (PLBA). */ - UINT64 start_offset; /* Track start offset. */ - UINT8 session; /* Session or index? */ - UINT8 __dummy5__[3]; - UINT32 footer_offset; /* Start offset of footer. */ - UINT8 __dummy6__[24]; -} __attribute__ ((packed)) MDS_TrackBlock; /* length: 80 bytes */ - -typedef struct { - UINT32 pregap; /* Number of sectors in pregap. */ - UINT32 length; /* Number of sectors in track. */ -} __attribute__ ((packed)) MDS_TrackExtraBlock; /* length: 8 bytes */ - -typedef struct { - UINT32 filename_offset; /* Start offset of image filename. */ - UINT32 widechar_filename; /* Seems to be set to 1 if widechar filename is used */ - UINT32 __dummy1__; - UINT32 __dummy2__; -} __attribute__ ((packed)) MDS_Footer; /* length: 16 bytes */ -#else -#pragma pack(push, 1) -typedef struct { - UINT8 signature[16]; /* 0x0000 "MEDIA DESCRIPTOR" */ - UINT8 version[2]; /* 0x0010 Version ? */ - UINT16 medium_type; /* 0x0012 Medium type */ - UINT16 num_sessions; /* 0x0014 Number of sessions */ - UINT16 __dummy1__[2]; /* 0x0016 Wish I knew... */ - UINT16 bca_len; /* 0x001A Length of BCA data (DVD-ROM) */ - UINT32 __dummy2__[2]; /* 0x001C */ - UINT32 bca_data_offset; /* 0x0026 Offset to BCA data (DVD-ROM) */ - UINT32 __dummy3__[6]; /* 0x002A Probably more offsets */ - UINT32 disc_structures_offset; /* 0x0042 Offset to disc structures */ - UINT32 __dummy4__[3]; /* 0x0046 Probably more offsets */ - UINT32 sessions_blocks_offset; /* 0x0052 Offset to session blocks */ - UINT32 dpm_blocks_offset; /* 0x0056 offset to DPM data blocks */ -} MDS_Header; /* length: 88 bytes */ - -typedef struct { - INT32 session_start; /* Session's start address */ - INT32 session_end; /* Session's end address */ - UINT16 session_number; /* (Unknown) */ - UINT8 num_all_blocks; /* Number of all data blocks. */ - UINT8 num_nontrack_blocks; /* Number of lead-in data blocks */ - UINT16 first_track; /* Total number of sessions in image? */ - UINT16 last_track; /* Number of regular track data blocks. */ - UINT32 __dummy2__; /* (unknown) */ - UINT32 tracks_blocks_offset; /* Offset of lead-in+regular track data blocks. */ -} MDS_SessionBlock; /* length: 24 bytes */ - -typedef struct { - UINT8 mode; /* Track mode */ - UINT8 subchannel; /* Subchannel mode */ - UINT8 adr_ctl; /* Adr/Ctl */ - UINT8 __dummy2__; /* Track flags? */ - UINT8 point; /* Track number. (>0x99 is lead-in track) */ - - UINT32 __dummy3__; - UINT8 min; /* Min */ - UINT8 sec; /* Sec */ - UINT8 frame; /* Frame */ - UINT32 extra_offset; /* Start offset of this track's extra block. */ - UINT16 sector_size; /* Sector size. */ - - UINT8 __dummy4__[18]; - UINT32 start_sector; /* Track start sector (PLBA). */ - UINT64 start_offset; /* Track start offset. */ - UINT8 session; /* Session or index? */ - UINT8 __dummy5__[3]; - UINT32 footer_offset; /* Start offset of footer. */ - UINT8 __dummy6__[24]; -} MDS_TrackBlock; /* length: 80 bytes */ - -typedef struct { - UINT32 pregap; /* Number of sectors in pregap. */ - UINT32 length; /* Number of sectors in track. */ -} MDS_TrackExtraBlock; /* length: 8 bytes */ - -typedef struct { - UINT32 filename_offset; /* Start offset of image filename. */ - UINT32 widechar_filename; /* Seems to be set to 1 if widechar filename is used */ - UINT32 __dummy1__; - UINT32 __dummy2__; -} MDS_Footer; /* length: 16 bytes */ -#pragma pack(pop) -#endif - -// MDS読み込み -BRESULT openmds(SXSIDEV sxsi, const OEMCHAR *fname) { - - _CDTRK trk[99]; - OEMCHAR path[MAX_PATH]; - UINT index; - FILEH fh; - MDS_Header MDS_H; - MDS_SessionBlock MDS_SB; - MDS_TrackBlock MDS_TB; - MDS_TrackExtraBlock MDS_TEB; -// MDS_Footer MDS_F; - long fpos; - UINT i; - UINT32 ex_offset[99]; - UINT32 total_pregap; - - ZeroMemory(trk, sizeof(trk)); - path[0] = '\0'; - index = 0; - - // イメージファイルの実体は手抜きで単一"*.mdf"固定 - file_cpyname(path, fname, NELEMENTS(path)); - file_cutext(path); - file_catname(path, str_mdf, NELEMENTS(path)); - - fh = file_open_rb(fname); - if (fh == FILEH_INVALID) { - goto openmds_err2; - } - - // Header読み込み - if (file_read(fh, &MDS_H, sizeof(MDS_H)) != sizeof(MDS_H)) { - goto openmds_err1; - } - if (memcmp(MDS_H.signature, mds_sig, 16)) { - goto openmds_err1; - } - - // SessionBlockへシーク後、SessionBlock読み込み - fpos = LOADINTELDWORD(&MDS_H.sessions_blocks_offset); - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - goto openmds_err1; - } - if (file_read(fh, &MDS_SB, sizeof(MDS_SB)) != sizeof(MDS_SB)) { - goto openmds_err1; - } - - // そのすぐ後にTrackBlockが続いている前提で必要数分TrackBlock読み込み - // ※MDS_SB.tracks_blocks_offsetに期待した値が入ってない… - for (i = 0; i < MDS_SB.num_all_blocks; i++) { - if (file_read(fh, &MDS_TB, sizeof(MDS_TB)) != sizeof(MDS_TB)) { - goto openmds_err1; - } - - // MDS_TRACKMODE_AUDIO - // MDS_TRACKMODE_MODE1 - // のみ、認識対象 - if (MDS_TB.mode == MDS_TRACKMODE_AUDIO || MDS_TB.mode == MDS_TRACKMODE_MODE1) { - trk[index].adr_ctl = MDS_TB.adr_ctl; - trk[index].point = MDS_TB.point; - trk[index].pos = ((MDS_TB.min * 60) + MDS_TB.sec) * 75 + MDS_TB.frame; - trk[index].pos0 = 0; - - trk[index].sector_size = LOADINTELWORD(&MDS_TB.sector_size); - - trk[index].start_sector = LOADINTELDWORD(&MDS_TB.start_sector); - trk[index].start_offset = LOADINTELQWORD(&MDS_TB.start_offset); - - ex_offset[index] = LOADINTELDWORD(&MDS_TB.extra_offset); - - index++; - } - } - - // TrackExtraBlockを読み込んでPREGAP分の補正 - total_pregap = 0; - for (i = 0; i < index; i++) { - if (ex_offset[i] != 0) { - fpos = ex_offset[i]; - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - goto openmds_err1; - } - if (file_read(fh, &MDS_TEB, sizeof(MDS_TEB)) != sizeof(MDS_TEB)) { - goto openmds_err1; - } - total_pregap += LOADINTELDWORD(&MDS_TEB.pregap); - trk[i].pos -= total_pregap; - - trk[i].pregap_sectors = LOADINTELDWORD(&MDS_TEB.pregap); - trk[i].track_sectors = LOADINTELDWORD(&MDS_TEB.length); - - trk[i].pregap_sector = trk[i].start_sector - trk[i].pregap_sectors; - trk[i].end_sector = trk[i].start_sector + trk[i].track_sectors - 1; - - trk[i].pregap_offset = trk[i].start_offset; - trk[i].end_offset = trk[i].start_offset + (trk[i].track_sectors * trk[i].sector_size); - } - } - - if (index == 0) { - goto openmds_err1; - } - - set_secread(sxsi, trk, index); - sxsi->totals = -1; - - file_close(fh); - - return(setsxsidev(sxsi, path, trk, index)); - -openmds_err1: - file_close(fh); - -openmds_err2: - return(FAILURE); -} - +#include +#include +#include + +#ifdef SUPPORT_KAI_IMAGES + +#include "diskimage/cddfile.h" + +#define LOADINTELQWORD(a) (*((UINT64 *)(a))) + +static const OEMCHAR str_mdf[] = OEMTEXT(".mdf"); + +static const UINT8 mds_sig[16] = + {'M','E','D','I','A',' ','D','E','S','C','R','I','P','T','O','R'}; + +#define MDS_MEDIUM_CD 0x00 // CD-ROM +#define MDS_MEDIUM_CD_R 0x01 // CD-R +#define MDS_MEDIUM_CD_RW 0x02 // CD-RW +#define MDS_MEDIUM_DVD 0x10 // DVD-ROM +#define MDS_MEDIUM_DVD_MINUS_R 0x12 // DVD-R + +#define MDS_TRACKMODE_UNKNOWN 0x00 +#define MDS_TRACKMODE_AUDIO 0xA9 // sector size = 2352 +#define MDS_TRACKMODE_MODE1 0xAA // sector size = 2048 +#define MDS_TRACKMODE_MODE2 0xAB // sector size = 2336 +#define MDS_TRACKMODE_MODE2_FORM1 0xAC // sector size = 2048 +#define MDS_TRACKMODE_MODE2_FORM2 0xAD // sector size = 2324 (+4) + +#define MDS_SUBCHAN_NONE 0x00 // no subchannel +#define MDS_SUBCHAN_PW_INTERLEAVED 0x08 // 96-byte PW subchannel, interleaved + +#define MDS_POINT_TRACK_FIRST 0xA0 // info about first track +#define MDS_POINT_TRACK_LAST 0xA1 // info about last track +#define MDS_POINT_TRACK_LEADOUT 0xA2 // info about lead-out + +#if defined(__GNUC__) +typedef struct { + UINT8 signature[16]; /* 0x0000 "MEDIA DESCRIPTOR" */ + UINT8 version[2]; /* 0x0010 Version ? */ + UINT16 medium_type; /* 0x0012 Medium type */ + UINT16 num_sessions; /* 0x0014 Number of sessions */ + UINT16 __dummy1__[2]; /* 0x0016 Wish I knew... */ + UINT16 bca_len; /* 0x001A Length of BCA data (DVD-ROM) */ + UINT32 __dummy2__[2]; /* 0x001C */ + UINT32 bca_data_offset; /* 0x0026 Offset to BCA data (DVD-ROM) */ + UINT32 __dummy3__[6]; /* 0x002A Probably more offsets */ + UINT32 disc_structures_offset; /* 0x0042 Offset to disc structures */ + UINT32 __dummy4__[3]; /* 0x0046 Probably more offsets */ + UINT32 sessions_blocks_offset; /* 0x0052 Offset to session blocks */ + UINT32 dpm_blocks_offset; /* 0x0056 offset to DPM data blocks */ +} __attribute__ ((packed)) MDS_Header; /* length: 88 bytes */ + +typedef struct { + INT32 session_start; /* Session's start address */ + INT32 session_end; /* Session's end address */ + UINT16 session_number; /* (Unknown) */ + UINT8 num_all_blocks; /* Number of all data blocks. */ + UINT8 num_nontrack_blocks; /* Number of lead-in data blocks */ + UINT16 first_track; /* Total number of sessions in image? */ + UINT16 last_track; /* Number of regular track data blocks. */ + UINT32 __dummy2__; /* (unknown) */ + UINT32 tracks_blocks_offset; /* Offset of lead-in+regular track data blocks. */ +} __attribute__ ((packed)) MDS_SessionBlock; /* length: 24 bytes */ + +typedef struct { + UINT8 mode; /* Track mode */ + UINT8 subchannel; /* Subchannel mode */ + UINT8 adr_ctl; /* Adr/Ctl */ + UINT8 __dummy2__; /* Track flags? */ + UINT8 point; /* Track number. (>0x99 is lead-in track) */ + + UINT32 __dummy3__; + UINT8 min; /* Min */ + UINT8 sec; /* Sec */ + UINT8 frame; /* Frame */ + UINT32 extra_offset; /* Start offset of this track's extra block. */ + UINT16 sector_size; /* Sector size. */ + + UINT8 __dummy4__[18]; + UINT32 start_sector; /* Track start sector (PLBA). */ + UINT64 start_offset; /* Track start offset. */ + UINT8 session; /* Session or index? */ + UINT8 __dummy5__[3]; + UINT32 footer_offset; /* Start offset of footer. */ + UINT8 __dummy6__[24]; +} __attribute__ ((packed)) MDS_TrackBlock; /* length: 80 bytes */ + +typedef struct { + UINT32 pregap; /* Number of sectors in pregap. */ + UINT32 length; /* Number of sectors in track. */ +} __attribute__ ((packed)) MDS_TrackExtraBlock; /* length: 8 bytes */ + +typedef struct { + UINT32 filename_offset; /* Start offset of image filename. */ + UINT32 widechar_filename; /* Seems to be set to 1 if widechar filename is used */ + UINT32 __dummy1__; + UINT32 __dummy2__; +} __attribute__ ((packed)) MDS_Footer; /* length: 16 bytes */ +#else +#pragma pack(push, 1) +typedef struct { + UINT8 signature[16]; /* 0x0000 "MEDIA DESCRIPTOR" */ + UINT8 version[2]; /* 0x0010 Version ? */ + UINT16 medium_type; /* 0x0012 Medium type */ + UINT16 num_sessions; /* 0x0014 Number of sessions */ + UINT16 __dummy1__[2]; /* 0x0016 Wish I knew... */ + UINT16 bca_len; /* 0x001A Length of BCA data (DVD-ROM) */ + UINT32 __dummy2__[2]; /* 0x001C */ + UINT32 bca_data_offset; /* 0x0026 Offset to BCA data (DVD-ROM) */ + UINT32 __dummy3__[6]; /* 0x002A Probably more offsets */ + UINT32 disc_structures_offset; /* 0x0042 Offset to disc structures */ + UINT32 __dummy4__[3]; /* 0x0046 Probably more offsets */ + UINT32 sessions_blocks_offset; /* 0x0052 Offset to session blocks */ + UINT32 dpm_blocks_offset; /* 0x0056 offset to DPM data blocks */ +} MDS_Header; /* length: 88 bytes */ + +typedef struct { + INT32 session_start; /* Session's start address */ + INT32 session_end; /* Session's end address */ + UINT16 session_number; /* (Unknown) */ + UINT8 num_all_blocks; /* Number of all data blocks. */ + UINT8 num_nontrack_blocks; /* Number of lead-in data blocks */ + UINT16 first_track; /* Total number of sessions in image? */ + UINT16 last_track; /* Number of regular track data blocks. */ + UINT32 __dummy2__; /* (unknown) */ + UINT32 tracks_blocks_offset; /* Offset of lead-in+regular track data blocks. */ +} MDS_SessionBlock; /* length: 24 bytes */ + +typedef struct { + UINT8 mode; /* Track mode */ + UINT8 subchannel; /* Subchannel mode */ + UINT8 adr_ctl; /* Adr/Ctl */ + UINT8 __dummy2__; /* Track flags? */ + UINT8 point; /* Track number. (>0x99 is lead-in track) */ + + UINT32 __dummy3__; + UINT8 min; /* Min */ + UINT8 sec; /* Sec */ + UINT8 frame; /* Frame */ + UINT32 extra_offset; /* Start offset of this track's extra block. */ + UINT16 sector_size; /* Sector size. */ + + UINT8 __dummy4__[18]; + UINT32 start_sector; /* Track start sector (PLBA). */ + UINT64 start_offset; /* Track start offset. */ + UINT8 session; /* Session or index? */ + UINT8 __dummy5__[3]; + UINT32 footer_offset; /* Start offset of footer. */ + UINT8 __dummy6__[24]; +} MDS_TrackBlock; /* length: 80 bytes */ + +typedef struct { + UINT32 pregap; /* Number of sectors in pregap. */ + UINT32 length; /* Number of sectors in track. */ +} MDS_TrackExtraBlock; /* length: 8 bytes */ + +typedef struct { + UINT32 filename_offset; /* Start offset of image filename. */ + UINT32 widechar_filename; /* Seems to be set to 1 if widechar filename is used */ + UINT32 __dummy1__; + UINT32 __dummy2__; +} MDS_Footer; /* length: 16 bytes */ +#pragma pack(pop) +#endif + +// MDS読み込み +BRESULT openmds(SXSIDEV sxsi, const OEMCHAR *fname) { + + _CDTRK trk[99]; + OEMCHAR path[MAX_PATH]; + UINT index; + FILEH fh; + MDS_Header MDS_H; + MDS_SessionBlock MDS_SB; + MDS_TrackBlock MDS_TB; + MDS_TrackExtraBlock MDS_TEB; +// MDS_Footer MDS_F; + long fpos; + UINT i; + UINT32 ex_offset[99]; + UINT32 total_pregap; + + ZeroMemory(trk, sizeof(trk)); + path[0] = '\0'; + index = 0; + + // イメージファイルの実体は手抜きで単一"*.mdf"固定 + file_cpyname(path, fname, NELEMENTS(path)); + file_cutext(path); + file_catname(path, str_mdf, NELEMENTS(path)); + + fh = file_open_rb(fname); + if (fh == FILEH_INVALID) { + goto openmds_err2; + } + + // Header読み込み + if (file_read(fh, &MDS_H, sizeof(MDS_H)) != sizeof(MDS_H)) { + goto openmds_err1; + } + if (memcmp(MDS_H.signature, mds_sig, 16)) { + goto openmds_err1; + } + + // SessionBlockへシーク後、SessionBlock読み込み + fpos = LOADINTELDWORD(&MDS_H.sessions_blocks_offset); + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + goto openmds_err1; + } + if (file_read(fh, &MDS_SB, sizeof(MDS_SB)) != sizeof(MDS_SB)) { + goto openmds_err1; + } + + // そのすぐ後にTrackBlockが続いている前提で必要数分TrackBlock読み込み + // ※MDS_SB.tracks_blocks_offsetに期待した値が入ってない… + for (i = 0; i < MDS_SB.num_all_blocks; i++) { + if (file_read(fh, &MDS_TB, sizeof(MDS_TB)) != sizeof(MDS_TB)) { + goto openmds_err1; + } + + // MDS_TRACKMODE_AUDIO + // MDS_TRACKMODE_MODE1 + // のみ、認識対象 + if (MDS_TB.mode == MDS_TRACKMODE_AUDIO || MDS_TB.mode == MDS_TRACKMODE_MODE1) { + trk[index].adr_ctl = MDS_TB.adr_ctl; + trk[index].point = MDS_TB.point; + trk[index].pos = ((MDS_TB.min * 60) + MDS_TB.sec) * 75 + MDS_TB.frame; + trk[index].pos0 = 0; + + trk[index].sector_size = LOADINTELWORD(&MDS_TB.sector_size); + + trk[index].start_sector = LOADINTELDWORD(&MDS_TB.start_sector); + trk[index].start_offset = LOADINTELQWORD(&MDS_TB.start_offset); + + ex_offset[index] = LOADINTELDWORD(&MDS_TB.extra_offset); + + index++; + } + } + + // TrackExtraBlockを読み込んでPREGAP分の補正 + total_pregap = 0; + for (i = 0; i < index; i++) { + if (ex_offset[i] != 0) { + fpos = ex_offset[i]; + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + goto openmds_err1; + } + if (file_read(fh, &MDS_TEB, sizeof(MDS_TEB)) != sizeof(MDS_TEB)) { + goto openmds_err1; + } + total_pregap += LOADINTELDWORD(&MDS_TEB.pregap); + trk[i].pos -= total_pregap; + + trk[i].pregap_sectors = LOADINTELDWORD(&MDS_TEB.pregap); + trk[i].track_sectors = LOADINTELDWORD(&MDS_TEB.length); + + trk[i].pregap_sector = trk[i].start_sector - trk[i].pregap_sectors; + trk[i].end_sector = trk[i].start_sector + trk[i].track_sectors - 1; + + trk[i].pregap_offset = trk[i].start_offset; + trk[i].end_offset = trk[i].start_offset + (trk[i].track_sectors * trk[i].sector_size); + } + } + + if (index == 0) { + goto openmds_err1; + } + + set_secread(sxsi, trk, index); + sxsi->totals = -1; + + file_close(fh); + + return(setsxsidev(sxsi, path, trk, index)); + +openmds_err1: + file_close(fh); + +openmds_err2: + return(FAILURE); +} + #endif \ No newline at end of file diff --git a/diskimage/cd/cdd_mds.h b/diskimage/cd/cdd_mds.h old mode 100755 new mode 100644 index e4124236..ef590063 --- a/diskimage/cd/cdd_mds.h +++ b/diskimage/cd/cdd_mds.h @@ -1,11 +1,11 @@ -#ifdef __cplusplus -extern "C" { -#endif - -extern const OEMCHAR str_mds[]; - -BRESULT openmds(SXSIDEV sxsi, const OEMCHAR *fname); - -#ifdef __cplusplus -} -#endif +#ifdef __cplusplus +extern "C" { +#endif + +extern const OEMCHAR str_mds[]; + +BRESULT openmds(SXSIDEV sxsi, const OEMCHAR *fname); + +#ifdef __cplusplus +} +#endif diff --git a/diskimage/cd/cdd_nrg.c b/diskimage/cd/cdd_nrg.c old mode 100755 new mode 100644 index ad65dc4d..a69b722a --- a/diskimage/cd/cdd_nrg.c +++ b/diskimage/cd/cdd_nrg.c @@ -1,349 +1,349 @@ -#include -#include -#include -#include - -#ifdef SUPPORT_KAI_IMAGES - -#include "diskimage/cddfile.h" -#include "diskimage/win9x/img_dosio.h" - -static const UINT8 nrg_sig_new[4] = {'N','E','R','5'}; -static const UINT8 nrg_sig_old[4] = {'N','E','R','O'}; - -// 手抜きで拙いBE->LE変換マクロ -#define UINT8_FROM_BE(val) \ - ( val << 4 ) | \ - ( val >> 4 ) -#define UINT16_FROM_BE(val) \ - ( val << 8 ) | \ - ( val >> 8 & 0x00ff ) -#define UINT32_FROM_BE(val) \ - ( val << 24 ) | \ - ( val << 8 & 0x00ff0000 ) | \ - ( val >> 8 & 0x0000ff00 ) | \ - ( val >> 24 & 0x000000ff ) -#define UINT64_FROM_BE(val) \ - ( val << 56) | \ - ( val << 40 & 0x00ff000000000000 ) | \ - ( val << 24 & 0x0000ff0000000000 ) | \ - ( val << 8 & 0x000000ff00000000 ) | \ - ( val >> 8 & 0x00000000ff000000 ) | \ - ( val >> 24 & 0x0000000000ff0000 ) | \ - ( val >> 40 & 0x000000000000ff00 ) | \ - ( val >> 56 & 0x00000000000000ff ) - -#if defined(__GNUC__) -typedef struct { - UINT8 adr_ctl; - UINT8 track; - UINT8 index; - UINT8 __dummy1__; - UINT32 start_sector; -} __attribute__ ((packed)) NRG_CUE_Block; - -typedef struct { - UINT32 __dummy1__; - char mcn[13]; - UINT8 __dummy2__; - UINT8 _session_type; /* ? */ - UINT8 _num_sessions; /* ? */ - UINT8 first_track; - UINT8 last_track; -} __attribute__ ((packed)) NRG_DAO_Header; /* length: 22 bytes */ - -// バージョンによって構造体内のメンバのサイズがちげえ -typedef struct { - char isrc[12]; - UINT16 sector_size; - UINT8 mode_code; - UINT8 __dummy1__; - UINT16 __dummy2__; - /* The following fields are 32-bit in old format and 64-bit in new format */ - UINT64 pregap_offset; /* Pregap offset in file */ - UINT64 start_offset; /* Track start offset in file */ - UINT64 end_offset; /* Track end offset */ -} __attribute__ ((packed)) NRG_DAO_Block64; - -typedef struct { - char isrc[12]; - UINT16 sector_size; - UINT8 mode_code; - UINT8 __dummy1__; - UINT16 __dummy2__; - /* The following fields are 32-bit in old format and 64-bit in new format */ - UINT32 pregap_offset; /* Pregap offset in file */ - UINT32 start_offset; /* Track start offset in file */ - UINT32 end_offset; /* Track end offset */ -} __attribute__ ((packed)) NRG_DAO_Block32; - -typedef struct { - char *block_id; - INT32 subblock_offset; - INT32 subblock_length; -} __attribute__ ((packed)) NRG_BlockIDs; -#else -#pragma pack(push, 1) -typedef struct { - UINT8 adr_ctl; - UINT8 track; - UINT8 index; - UINT8 __dummy1__; - UINT32 start_sector; -} NRG_CUE_Block; - -typedef struct { - UINT32 __dummy1__; - char mcn[13]; - UINT8 __dummy2__; - UINT8 _session_type; /* ? */ - UINT8 _num_sessions; /* ? */ - UINT8 first_track; - UINT8 last_track; -} NRG_DAO_Header; /* length: 22 bytes */ - -// バージョンによって構造体内のメンバのサイズがちげえ -typedef struct { - char isrc[12]; - UINT16 sector_size; - UINT8 mode_code; - UINT8 __dummy1__; - UINT16 __dummy2__; - /* The following fields are 32-bit in old format and 64-bit in new format */ - UINT64 pregap_offset; /* Pregap offset in file */ - UINT64 start_offset; /* Track start offset in file */ - UINT64 end_offset; /* Track end offset */ -} NRG_DAO_Block64; - -typedef struct { - char isrc[12]; - UINT16 sector_size; - UINT8 mode_code; - UINT8 __dummy1__; - UINT16 __dummy2__; - /* The following fields are 32-bit in old format and 64-bit in new format */ - UINT32 pregap_offset; /* Pregap offset in file */ - UINT32 start_offset; /* Track start offset in file */ - UINT32 end_offset; /* Track end offset */ -} NRG_DAO_Block32; - -typedef struct { - char *block_id; - INT32 subblock_offset; - INT32 subblock_length; -} NRG_BlockIDs; -#pragma pack(pop) -#endif - -static NRG_BlockIDs NRGBlockID[] = { - { "CUEX", 0, 8 }, - { "CUES", 0, 8 }, - { "ETN2", 0, 32 }, - { "ETNF", 0, 20 }, - { "DAOX", 22, 42 }, - { "DAOI", 22, 30 }, - { "CDTX", 0, 0 }, - { "SINF", 0, 0 }, - { "MTYP", 0, 0 }, - { "END!", 0, 0 }, - { NULL, 0, 0 } -}; - - -// NRG読み込み -// ※手抜き実装なのでCUExブロックとDAOxブロックの間(?)にETNxブロックが -//  存在しているイメージは読み込み失敗する -BRESULT opennrg(SXSIDEV sxsi, const OEMCHAR *fname) { - - _CDTRK trk[99]; - UINT index; - FILEH fh; - FILELEN filesize; - UINT64 trailer_offset; - UINT64 data_length; - UINT8 sig[4]; - UINT8 nrg_ver; - UINT i; - long total_sec; -#ifdef TOCLOGOUT - OEMCHAR logpath[MAX_PATH]; - OEMCHAR logbuf[2048]; - TEXTFILEH tfh; -#endif - - ZeroMemory(trk, sizeof(trk)); - index = 0; - nrg_ver = 0; - - fh = file_open_rb(fname); - if (fh == FILEH_INVALID) { - goto opennrg_err2; - } - - filesize = file_getsize(fh); - file_seek(fh, -12, FSEEK_END); // 末尾から12byte位置へ - - if (file_read(fh, sig, sizeof(sig)) != sizeof(sig)) { - goto opennrg_err1; - } - - if (!memcmp(sig, nrg_sig_new, sizeof(sig))) { - /* New format, 64-bit offset */ - UINT64 tmp_offset = 0; - - if (file_read(fh, &tmp_offset, sizeof(UINT64)) != sizeof(UINT64)) { - goto opennrg_err1; - } - - trailer_offset = UINT64_FROM_BE(tmp_offset); - data_length = (filesize - 12) - trailer_offset; - } - else { - /* Try old format, with 32-bit offset */ - file_seek(fh, -8, FSEEK_END); // 末尾から8byte位置へ - if (file_read(fh, sig, sizeof(sig)) != sizeof(sig)) { - goto opennrg_err1; - } - - if (!memcmp(sig, nrg_sig_old, sizeof(sig))) { - UINT32 tmp_offset = 0; - - if (file_read(fh, &tmp_offset, sizeof(UINT32)) != sizeof(UINT32)) { - goto opennrg_err1; - } - - trailer_offset = UINT32_FROM_BE(tmp_offset); - data_length = (filesize - 8) - trailer_offset; - nrg_ver = 1; - } - else { - /* Unknown signature, can't handle the file */ - goto opennrg_err1; - } - } - - file_seek(fh, (FILEPOS)trailer_offset, FSEEK_SET); - - if (file_read(fh, sig, sizeof(sig)) != sizeof(sig)) { - goto opennrg_err1; - } - // CUEX、CUESブロック読み込み - if (!memcmp(sig, NRGBlockID[0].block_id, sizeof(sig)) || - !memcmp(sig, NRGBlockID[1].block_id, sizeof(sig))) { - - UINT32 tmp_size; - UINT32 blk_size; - - if (file_read(fh, &tmp_size, sizeof(UINT32)) != sizeof(UINT32)) { - goto opennrg_err1; - } - blk_size = UINT32_FROM_BE(tmp_size); - - for (i = 0; i < blk_size/sizeof(NRG_CUE_Block); i++) { - NRG_CUE_Block NRG_CB; - - if (file_read(fh, &NRG_CB, sizeof(NRG_CUE_Block)) != sizeof(NRG_CUE_Block)) { - goto opennrg_err1; - } - - if (NRG_CB.index == 0x00 && NRG_CB.track >= 0x02) { - // モノによってトラック番号偽っているCD-ROMがあるっぽい? -// trk[NRG_CB.track].pos0 = UINT32_FROM_BE(NRG_CB.start_sector); - trk[index].pos0 = UINT32_FROM_BE(NRG_CB.start_sector); - } - if (NRG_CB.index == 0x01 && NRG_CB.track != 0xAA) { - trk[index].adr_ctl = UINT8_FROM_BE(NRG_CB.adr_ctl); - // モノによってトラック番号偽っているCD-ROMがあるっぽい? -// trk[index].point = NRG_CB.track; - trk[index].point = index+1; - trk[index].pos = UINT32_FROM_BE(NRG_CB.start_sector); - index++; - } - } - } - else { - // 最初がCUExブロック以外なら未対応 - goto opennrg_err1; - } - - if (file_read(fh, sig, sizeof(sig)) != sizeof(sig)) { - goto opennrg_err1; - } - // DAOX、DAOIブロック読み込み - if (!memcmp(sig, NRGBlockID[4].block_id, sizeof(sig)) || - !memcmp(sig, NRGBlockID[5].block_id, sizeof(sig))) { - - UINT32 tmp_size; - UINT32 blk_size; - NRG_DAO_Header NRG_DH; - - if (file_read(fh, &tmp_size, sizeof(UINT32)) != sizeof(UINT32)) { - goto opennrg_err1; - } - blk_size = UINT32_FROM_BE(tmp_size); - - if (file_read(fh, &NRG_DH, sizeof(NRG_DAO_Header)) != sizeof(NRG_DAO_Header)) { - goto opennrg_err1; - } - - blk_size -= sizeof(NRG_DAO_Header); - if (nrg_ver == 0) { - for (i = 0; i < blk_size/sizeof(NRG_DAO_Block64); i++) { - NRG_DAO_Block64 NRG_DB; - - if (file_read(fh, &NRG_DB, sizeof(NRG_DAO_Block64)) != sizeof(NRG_DAO_Block64)) { - goto opennrg_err1; - } - - trk[i].sector_size = UINT16_FROM_BE(NRG_DB.sector_size); - trk[i].pregap_offset = UINT64_FROM_BE(NRG_DB.pregap_offset); - trk[i].start_offset = UINT64_FROM_BE(NRG_DB.start_offset); - trk[i].end_offset = UINT64_FROM_BE(NRG_DB.end_offset); - } - } - else { - for (i = 0; i < blk_size/sizeof(NRG_DAO_Block32); i++) { - NRG_DAO_Block32 NRG_DB; - - if (file_read(fh, &NRG_DB, sizeof(NRG_DAO_Block32)) != sizeof(NRG_DAO_Block32)) { - goto opennrg_err1; - } - - trk[i].sector_size = UINT16_FROM_BE(NRG_DB.sector_size); - trk[i].pregap_offset = UINT32_FROM_BE(NRG_DB.pregap_offset); - trk[i].start_offset = UINT32_FROM_BE(NRG_DB.start_offset); - trk[i].end_offset = UINT32_FROM_BE(NRG_DB.end_offset); - } - } - } - else { - // 2番目ががDAOxブロック以外なら未対応 - goto opennrg_err1; - } - - if (index == 0) { - goto opennrg_err1; - } - - set_secread(sxsi, trk, index); - - total_sec = set_trkinfo(fh, trk, index, (FILELEN)trailer_offset); - if (total_sec < 0) { - goto opennrg_err1; - } - - // リードアウト?ポストギャップ?分150セクタ引く - sxsi->totals = total_sec - 150; - - file_close(fh); - - return(setsxsidev(sxsi, fname, trk, index)); - -opennrg_err1: - file_close(fh); - -opennrg_err2: - return(FAILURE); -} - -#endif +#include +#include +#include +#include + +#ifdef SUPPORT_KAI_IMAGES + +#include "diskimage/cddfile.h" +#include "diskimage/win9x/img_dosio.h" + +static const UINT8 nrg_sig_new[4] = {'N','E','R','5'}; +static const UINT8 nrg_sig_old[4] = {'N','E','R','O'}; + +// 手抜きで拙いBE->LE変換マクロ +#define UINT8_FROM_BE(val) \ + ( val << 4 ) | \ + ( val >> 4 ) +#define UINT16_FROM_BE(val) \ + ( val << 8 ) | \ + ( val >> 8 & 0x00ff ) +#define UINT32_FROM_BE(val) \ + ( val << 24 ) | \ + ( val << 8 & 0x00ff0000 ) | \ + ( val >> 8 & 0x0000ff00 ) | \ + ( val >> 24 & 0x000000ff ) +#define UINT64_FROM_BE(val) \ + ( val << 56) | \ + ( val << 40 & 0x00ff000000000000 ) | \ + ( val << 24 & 0x0000ff0000000000 ) | \ + ( val << 8 & 0x000000ff00000000 ) | \ + ( val >> 8 & 0x00000000ff000000 ) | \ + ( val >> 24 & 0x0000000000ff0000 ) | \ + ( val >> 40 & 0x000000000000ff00 ) | \ + ( val >> 56 & 0x00000000000000ff ) + +#if defined(__GNUC__) +typedef struct { + UINT8 adr_ctl; + UINT8 track; + UINT8 index; + UINT8 __dummy1__; + UINT32 start_sector; +} __attribute__ ((packed)) NRG_CUE_Block; + +typedef struct { + UINT32 __dummy1__; + char mcn[13]; + UINT8 __dummy2__; + UINT8 _session_type; /* ? */ + UINT8 _num_sessions; /* ? */ + UINT8 first_track; + UINT8 last_track; +} __attribute__ ((packed)) NRG_DAO_Header; /* length: 22 bytes */ + +// バージョンによって構造体内のメンバのサイズがちげえ +typedef struct { + char isrc[12]; + UINT16 sector_size; + UINT8 mode_code; + UINT8 __dummy1__; + UINT16 __dummy2__; + /* The following fields are 32-bit in old format and 64-bit in new format */ + UINT64 pregap_offset; /* Pregap offset in file */ + UINT64 start_offset; /* Track start offset in file */ + UINT64 end_offset; /* Track end offset */ +} __attribute__ ((packed)) NRG_DAO_Block64; + +typedef struct { + char isrc[12]; + UINT16 sector_size; + UINT8 mode_code; + UINT8 __dummy1__; + UINT16 __dummy2__; + /* The following fields are 32-bit in old format and 64-bit in new format */ + UINT32 pregap_offset; /* Pregap offset in file */ + UINT32 start_offset; /* Track start offset in file */ + UINT32 end_offset; /* Track end offset */ +} __attribute__ ((packed)) NRG_DAO_Block32; + +typedef struct { + char *block_id; + INT32 subblock_offset; + INT32 subblock_length; +} __attribute__ ((packed)) NRG_BlockIDs; +#else +#pragma pack(push, 1) +typedef struct { + UINT8 adr_ctl; + UINT8 track; + UINT8 index; + UINT8 __dummy1__; + UINT32 start_sector; +} NRG_CUE_Block; + +typedef struct { + UINT32 __dummy1__; + char mcn[13]; + UINT8 __dummy2__; + UINT8 _session_type; /* ? */ + UINT8 _num_sessions; /* ? */ + UINT8 first_track; + UINT8 last_track; +} NRG_DAO_Header; /* length: 22 bytes */ + +// バージョンによって構造体内のメンバのサイズがちげえ +typedef struct { + char isrc[12]; + UINT16 sector_size; + UINT8 mode_code; + UINT8 __dummy1__; + UINT16 __dummy2__; + /* The following fields are 32-bit in old format and 64-bit in new format */ + UINT64 pregap_offset; /* Pregap offset in file */ + UINT64 start_offset; /* Track start offset in file */ + UINT64 end_offset; /* Track end offset */ +} NRG_DAO_Block64; + +typedef struct { + char isrc[12]; + UINT16 sector_size; + UINT8 mode_code; + UINT8 __dummy1__; + UINT16 __dummy2__; + /* The following fields are 32-bit in old format and 64-bit in new format */ + UINT32 pregap_offset; /* Pregap offset in file */ + UINT32 start_offset; /* Track start offset in file */ + UINT32 end_offset; /* Track end offset */ +} NRG_DAO_Block32; + +typedef struct { + char *block_id; + INT32 subblock_offset; + INT32 subblock_length; +} NRG_BlockIDs; +#pragma pack(pop) +#endif + +static NRG_BlockIDs NRGBlockID[] = { + { "CUEX", 0, 8 }, + { "CUES", 0, 8 }, + { "ETN2", 0, 32 }, + { "ETNF", 0, 20 }, + { "DAOX", 22, 42 }, + { "DAOI", 22, 30 }, + { "CDTX", 0, 0 }, + { "SINF", 0, 0 }, + { "MTYP", 0, 0 }, + { "END!", 0, 0 }, + { NULL, 0, 0 } +}; + + +// NRG読み込み +// ※手抜き実装なのでCUExブロックとDAOxブロックの間(?)にETNxブロックが +//  存在しているイメージは読み込み失敗する +BRESULT opennrg(SXSIDEV sxsi, const OEMCHAR *fname) { + + _CDTRK trk[99]; + UINT index; + FILEH fh; + FILELEN filesize; + UINT64 trailer_offset; + UINT64 data_length; + UINT8 sig[4]; + UINT8 nrg_ver; + UINT i; + long total_sec; +#ifdef TOCLOGOUT + OEMCHAR logpath[MAX_PATH]; + OEMCHAR logbuf[2048]; + TEXTFILEH tfh; +#endif + + ZeroMemory(trk, sizeof(trk)); + index = 0; + nrg_ver = 0; + + fh = file_open_rb(fname); + if (fh == FILEH_INVALID) { + goto opennrg_err2; + } + + filesize = file_getsize(fh); + file_seek(fh, -12, FSEEK_END); // 末尾から12byte位置へ + + if (file_read(fh, sig, sizeof(sig)) != sizeof(sig)) { + goto opennrg_err1; + } + + if (!memcmp(sig, nrg_sig_new, sizeof(sig))) { + /* New format, 64-bit offset */ + UINT64 tmp_offset = 0; + + if (file_read(fh, &tmp_offset, sizeof(UINT64)) != sizeof(UINT64)) { + goto opennrg_err1; + } + + trailer_offset = UINT64_FROM_BE(tmp_offset); + data_length = (filesize - 12) - trailer_offset; + } + else { + /* Try old format, with 32-bit offset */ + file_seek(fh, -8, FSEEK_END); // 末尾から8byte位置へ + if (file_read(fh, sig, sizeof(sig)) != sizeof(sig)) { + goto opennrg_err1; + } + + if (!memcmp(sig, nrg_sig_old, sizeof(sig))) { + UINT32 tmp_offset = 0; + + if (file_read(fh, &tmp_offset, sizeof(UINT32)) != sizeof(UINT32)) { + goto opennrg_err1; + } + + trailer_offset = UINT32_FROM_BE(tmp_offset); + data_length = (filesize - 8) - trailer_offset; + nrg_ver = 1; + } + else { + /* Unknown signature, can't handle the file */ + goto opennrg_err1; + } + } + + file_seek(fh, (FILEPOS)trailer_offset, FSEEK_SET); + + if (file_read(fh, sig, sizeof(sig)) != sizeof(sig)) { + goto opennrg_err1; + } + // CUEX、CUESブロック読み込み + if (!memcmp(sig, NRGBlockID[0].block_id, sizeof(sig)) || + !memcmp(sig, NRGBlockID[1].block_id, sizeof(sig))) { + + UINT32 tmp_size; + UINT32 blk_size; + + if (file_read(fh, &tmp_size, sizeof(UINT32)) != sizeof(UINT32)) { + goto opennrg_err1; + } + blk_size = UINT32_FROM_BE(tmp_size); + + for (i = 0; i < blk_size/sizeof(NRG_CUE_Block); i++) { + NRG_CUE_Block NRG_CB; + + if (file_read(fh, &NRG_CB, sizeof(NRG_CUE_Block)) != sizeof(NRG_CUE_Block)) { + goto opennrg_err1; + } + + if (NRG_CB.index == 0x00 && NRG_CB.track >= 0x02) { + // モノによってトラック番号偽っているCD-ROMがあるっぽい? +// trk[NRG_CB.track].pos0 = UINT32_FROM_BE(NRG_CB.start_sector); + trk[index].pos0 = UINT32_FROM_BE(NRG_CB.start_sector); + } + if (NRG_CB.index == 0x01 && NRG_CB.track != 0xAA) { + trk[index].adr_ctl = UINT8_FROM_BE(NRG_CB.adr_ctl); + // モノによってトラック番号偽っているCD-ROMがあるっぽい? +// trk[index].point = NRG_CB.track; + trk[index].point = index+1; + trk[index].pos = UINT32_FROM_BE(NRG_CB.start_sector); + index++; + } + } + } + else { + // 最初がCUExブロック以外なら未対応 + goto opennrg_err1; + } + + if (file_read(fh, sig, sizeof(sig)) != sizeof(sig)) { + goto opennrg_err1; + } + // DAOX、DAOIブロック読み込み + if (!memcmp(sig, NRGBlockID[4].block_id, sizeof(sig)) || + !memcmp(sig, NRGBlockID[5].block_id, sizeof(sig))) { + + UINT32 tmp_size; + UINT32 blk_size; + NRG_DAO_Header NRG_DH; + + if (file_read(fh, &tmp_size, sizeof(UINT32)) != sizeof(UINT32)) { + goto opennrg_err1; + } + blk_size = UINT32_FROM_BE(tmp_size); + + if (file_read(fh, &NRG_DH, sizeof(NRG_DAO_Header)) != sizeof(NRG_DAO_Header)) { + goto opennrg_err1; + } + + blk_size -= sizeof(NRG_DAO_Header); + if (nrg_ver == 0) { + for (i = 0; i < blk_size/sizeof(NRG_DAO_Block64); i++) { + NRG_DAO_Block64 NRG_DB; + + if (file_read(fh, &NRG_DB, sizeof(NRG_DAO_Block64)) != sizeof(NRG_DAO_Block64)) { + goto opennrg_err1; + } + + trk[i].sector_size = UINT16_FROM_BE(NRG_DB.sector_size); + trk[i].pregap_offset = UINT64_FROM_BE(NRG_DB.pregap_offset); + trk[i].start_offset = UINT64_FROM_BE(NRG_DB.start_offset); + trk[i].end_offset = UINT64_FROM_BE(NRG_DB.end_offset); + } + } + else { + for (i = 0; i < blk_size/sizeof(NRG_DAO_Block32); i++) { + NRG_DAO_Block32 NRG_DB; + + if (file_read(fh, &NRG_DB, sizeof(NRG_DAO_Block32)) != sizeof(NRG_DAO_Block32)) { + goto opennrg_err1; + } + + trk[i].sector_size = UINT16_FROM_BE(NRG_DB.sector_size); + trk[i].pregap_offset = UINT32_FROM_BE(NRG_DB.pregap_offset); + trk[i].start_offset = UINT32_FROM_BE(NRG_DB.start_offset); + trk[i].end_offset = UINT32_FROM_BE(NRG_DB.end_offset); + } + } + } + else { + // 2番目ががDAOxブロック以外なら未対応 + goto opennrg_err1; + } + + if (index == 0) { + goto opennrg_err1; + } + + set_secread(sxsi, trk, index); + + total_sec = set_trkinfo(fh, trk, index, (FILELEN)trailer_offset); + if (total_sec < 0) { + goto opennrg_err1; + } + + // リードアウト?ポストギャップ?分150セクタ引く + sxsi->totals = total_sec - 150; + + file_close(fh); + + return(setsxsidev(sxsi, fname, trk, index)); + +opennrg_err1: + file_close(fh); + +opennrg_err2: + return(FAILURE); +} + +#endif diff --git a/diskimage/cd/cdd_nrg.h b/diskimage/cd/cdd_nrg.h old mode 100755 new mode 100644 index 8dd9c964..e735e6af --- a/diskimage/cd/cdd_nrg.h +++ b/diskimage/cd/cdd_nrg.h @@ -1,11 +1,11 @@ -#ifdef __cplusplus -extern "C" { -#endif - -extern const OEMCHAR str_nrg[]; - -BRESULT opennrg(SXSIDEV sxsi, const OEMCHAR *fname); - -#ifdef __cplusplus -} -#endif +#ifdef __cplusplus +extern "C" { +#endif + +extern const OEMCHAR str_nrg[]; + +BRESULT opennrg(SXSIDEV sxsi, const OEMCHAR *fname); + +#ifdef __cplusplus +} +#endif diff --git a/diskimage/cd/cdd_real.c b/diskimage/cd/cdd_real.c old mode 100755 new mode 100644 index 8393f8c2..6aaa14ea --- a/diskimage/cd/cdd_real.c +++ b/diskimage/cd/cdd_real.c @@ -1,622 +1,622 @@ -#include -#include -#include -#include - -#ifdef SUPPORT_PHYSICAL_CDDRV - -#include - -#pragma warning (push) -#pragma warning (disable: 4091) -#include -#pragma warning (pop) - -#include "diskimage/cddfile.h" -#include "diskimage/cd/cdd_real.h" - -UINT64 msf2lba(UINT64 msf){ - UINT64 m,s,f; - m = (msf >> 16) & 0xffffffffffff; - s = (msf >> 8) & 0xff; - f = (msf >> 0) & 0xff; - return (((m * 60) + s) * 75) + f; -} - -struct sptdinfo -{ - SCSI_PASS_THROUGH info; - char sense_buffer[20]; - UCHAR ucDataBuf[16384]; -}; - -struct sptdreadcapacityinfo -{ - SCSI_PASS_THROUGH info; - char sense_buffer[20]; - UCHAR ucDataBuf[8]; -}; - - -// ---- -// イメージファイル内全トラックセクタ長2048byte用 -REG8 sec2048_read_SPTI(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { - - CDINFO cdinfo; - FILEH fh; - //UINT rsize; - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(0x40); - } - - cdinfo = (CDINFO)sxsi->hdl; - fh = cdinfo->fh; - - size /= 2048; - - if (1 || size != 2048) { - DWORD sptisize = 0; - struct sptdinfo* psptd = (struct sptdinfo*)malloc(sizeof(struct sptdinfo)); - if (!psptd) { - return(0x60); - } - memset(psptd, 0, sizeof(struct sptdinfo)); - //UCHAR ucDataBuf[2048*8]; - - // READ command - psptd->info.Cdb[0] = 0x28;//0xBE;//0x3C;//0xBE; - // Don't care about sector type. - //psptd->info.Cdb[1] = 0; - //psptd->info.Cdb[2] = (pos >> 24) & 0xFF; - //psptd->info.Cdb[3] = (pos >> 16) & 0xFF; - //psptd->info.Cdb[4] = (pos >> 8) & 0xFF; - //psptd->info.Cdb[5] = pos & 0xFF; - //psptd->info.Cdb[6] = (size >> 16) & 0xFF; - //psptd->info.Cdb[7] = (size >> 8) & 0xFF; - //psptd->info.Cdb[8] = size & 0xFF; - //// Sync + all headers + user data + EDC/ECC. Excludes C2 + subchannel - psptd->info.Cdb[1] = 2; // Data mode - psptd->info.Cdb[2] = (pos >> 24) & 0xFF; - psptd->info.Cdb[3] = (pos >> 16) & 0xFF; - psptd->info.Cdb[4] = (pos >> 8) & 0xFF; - psptd->info.Cdb[5] = pos & 0xFF; - psptd->info.Cdb[6] = (size >> 16) & 0xFF; - psptd->info.Cdb[7] = (size >> 8) & 0xFF; - psptd->info.Cdb[8] = size & 0xFF; - psptd->info.Cdb[9] = 0xF8; - psptd->info.Cdb[10] = 0; - psptd->info.Cdb[11] = 0; - - psptd->info.CdbLength = 12; - psptd->info.Length = sizeof(SCSI_PASS_THROUGH); - psptd->info.DataIn = SCSI_IOCTL_DATA_IN; - psptd->info.DataTransferLength = 2048 * size; - psptd->info.DataBufferOffset = offsetof(struct sptdinfo, ucDataBuf); - //psptd->info.DataBuffer = ucDataBuf; - psptd->info.SenseInfoLength = sizeof(psptd->sense_buffer); - psptd->info.SenseInfoOffset = offsetof(struct sptdinfo, sense_buffer); - psptd->info.TimeOutValue = 5; - - if (psptd->info.DataTransferLength > sizeof(psptd->ucDataBuf)) return 0xd0; - - if (DeviceIoControl(fh, IOCTL_SCSI_PASS_THROUGH, psptd, offsetof(struct sptdinfo, sense_buffer) + sizeof(psptd->sense_buffer), psptd, offsetof(struct sptdinfo, ucDataBuf) + 2048 * size, &sptisize, FALSE)) - { - if (psptd->info.DataTransferLength != 0) { - memcpy(buf, psptd->ucDataBuf, psptd->info.DataTransferLength); - free(psptd); - return(0x00); - } - } - free(psptd); - } - - return(0xd0); -} - -// イメージファイルの実体を開き、各種情報構築 -BRESULT setsxsidev_SPTI(SXSIDEV sxsi, const OEMCHAR *path, const _CDTRK *trk, UINT trks) { - - FILEH fh; - long totals; - CDINFO cdinfo; - UINT mediatype; - UINT i; -#ifdef TOCLOGOUT - OEMCHAR logpath[MAX_PATH]; - OEMCHAR logbuf[2048]; - TEXTFILEH tfh; -#endif - - // trk、trksは有効な値が設定済みなのが前提 - if ((trk == NULL) || (trks == 0)) { - goto sxsiope_err1; - } - - fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (fh == FILEH_INVALID) { - goto sxsiope_err1; - } - - cdinfo = (CDINFO)_MALLOC(sizeof(_CDINFO), path); - if (cdinfo == NULL) { - goto sxsiope_err2; - } - ZeroMemory(cdinfo, sizeof(_CDINFO)); - cdinfo->fh = fh; - trks = min(trks, NELEMENTS(cdinfo->trk) - 1); - CopyMemory(cdinfo->trk, trk, trks * sizeof(_CDTRK)); - -#ifdef TOCLOGOUT - file_cpyname(logpath, path, NELEMENTS(logpath)); - file_cutext(logpath); - file_catname(logpath, str_logB, NELEMENTS(logpath)); - - tfh = textfile_create(logpath, 0x800); - if (tfh == NULL) { - return(FAILURE); - } - - TOCLOG(OEMTEXT("STR _CDTRK LOG\r\n"), 0); - for (i = 0; i < trks; i++) { - TOCLOG(OEMTEXT("trk[%02d]\r\n"), i); - TOCLOG(OEMTEXT(" adr_ctl = 0x%02X\r\n"), cdinfo->trk[i].adr_ctl); - TOCLOG(OEMTEXT(" point = %02d\r\n"), cdinfo->trk[i].point); - TOCLOG(OEMTEXT(" [pos0][pos][ ] = [%18I32d]"), cdinfo->trk[i].pos0); - TOCLOG(OEMTEXT("[%18I32d][ ]\r\n"), cdinfo->trk[i].pos); - TOCLOG(OEMTEXT(" sec[ ][str][end] = [ ][%18I32d]"), cdinfo->trk[i].str_sec); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sec); - TOCLOG(OEMTEXT(" sectors = %I32d\r\n"), cdinfo->trk[i].sectors); - TOCLOG(OEMTEXT(" sector_size = %d\r\n"), cdinfo->trk[i].sector_size); - TOCLOG(OEMTEXT(" sector [pregap][start][end] = [%18I32d]"), cdinfo->trk[i].pregap_sector); - TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].start_sector); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sector); - TOCLOG(OEMTEXT(" img_sec[pregap][start][end] = [%18I32d]"), cdinfo->trk[i].img_pregap_sec); - TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].img_start_sec); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].img_end_sec); - TOCLOG(OEMTEXT(" offset [pregap][start][end] = [0x%016I64X]"), cdinfo->trk[i].pregap_offset); - TOCLOG(OEMTEXT("[0x%016I64X]"), cdinfo->trk[i].start_offset); - TOCLOG(OEMTEXT("[0x%016I64X]\r\n"), cdinfo->trk[i].end_offset); - TOCLOG(OEMTEXT(" pregap_sectors = %I32d\r\n"), cdinfo->trk[i].pregap_sectors); - TOCLOG(OEMTEXT(" track_sectors = %I32d\r\n"), cdinfo->trk[i].track_sectors); - } - TOCLOG(OEMTEXT("END _CDTRK LOG\r\n"), 0); - - textfile_close(tfh); -#endif - -#if 1 - if (sxsi->totals == -1) { - totals = set_trkinfo(fh, cdinfo->trk, trks, 0); - if (totals < 0) { - goto sxsiope_err3; - } - sxsi->totals = totals; - } -#else - totals = issec(fh, cdinfo->trk, trks); // とりあえず - sxsi->read = sec2048_read; - totals = issec2048(cdinfo->fh); - if (totals < 0) { - sxsi->read = sec2352_read; - totals = issec2352(cdinfo->fh); - } - if (totals < 0) { - sxsi->read = sec2448_read; - totals = issec2448(cdinfo->fh); - } - if (totals < 0) { - sxsi->read = sec_read; - totals = issec(cdinfo->fh, cdinfo->trk, trks); - } - if (totals < 0) { - goto sxsiope_err3; - } -#endif - - mediatype = 0; - for (i = 0; i < trks; i++) { - if (cdinfo->trk[i].adr_ctl == TRACKTYPE_DATA) { - mediatype |= SXSIMEDIA_DATA; - } - else if (cdinfo->trk[i].adr_ctl == TRACKTYPE_AUDIO) { - mediatype |= SXSIMEDIA_AUDIO; - } - } - - // リードアウトトラックを生成 - cdinfo->trk[trks].adr_ctl = 0x10; - cdinfo->trk[trks].point = 0xaa; -// cdinfo->trk[trks].pos = totals; - cdinfo->trk[trks].pos = (UINT32)sxsi->totals; - - cdinfo->trks = trks; - file_cpyname(cdinfo->path, path, NELEMENTS(cdinfo->path)); - - sxsi->reopen = cd_reopen; - sxsi->close = cd_close; - sxsi->destroy = cd_destroy; - sxsi->hdl = (INTPTR)cdinfo; -// sxsi->totals = totals; - sxsi->cylinders = 0; - sxsi->size = 2352; - sxsi->sectors = 1; - sxsi->surfaces = 1; - sxsi->headersize = 0; - sxsi->mediatype = mediatype; - -#ifdef TOCLOGOUT - file_cpyname(logpath, path, NELEMENTS(logpath)); - file_cutext(logpath); - file_catname(logpath, str_logA, NELEMENTS(logpath)); - - tfh = textfile_create(logpath, 0x800); - if (tfh == NULL) { - return(FAILURE); - } - - TOCLOG(OEMTEXT("STR _CDTRK LOG\r\n"), 0); - for (i = 0; i < trks; i++) { - TOCLOG(OEMTEXT("trk[%02d]\r\n"), i); - TOCLOG(OEMTEXT(" adr_ctl = 0x%02X\r\n"), cdinfo->trk[i].adr_ctl); - TOCLOG(OEMTEXT(" point = %02d\r\n"), cdinfo->trk[i].point); - TOCLOG(OEMTEXT(" [pos0][pos][ ] = [%18I32d]"), cdinfo->trk[i].pos0); - TOCLOG(OEMTEXT("[%18I32d][ ]\r\n"), cdinfo->trk[i].pos); - TOCLOG(OEMTEXT(" sec[ ][str][end] = [ ][%18I32d]"), cdinfo->trk[i].str_sec); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sec); - TOCLOG(OEMTEXT(" sectors = %I32d\r\n"), cdinfo->trk[i].sectors); - TOCLOG(OEMTEXT(" sector_size = %d\r\n"), cdinfo->trk[i].sector_size); - TOCLOG(OEMTEXT(" sector [pregap][start][end] = [%18I32d]"), cdinfo->trk[i].pregap_sector); - TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].start_sector); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sector); - TOCLOG(OEMTEXT(" img_sec[pregap][start][end] = [%18I32d]"), cdinfo->trk[i].img_pregap_sec); - TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].img_start_sec); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].img_end_sec); - TOCLOG(OEMTEXT(" offset [pregap][start][end] = [0x%016I64X]"), cdinfo->trk[i].pregap_offset); - TOCLOG(OEMTEXT("[0x%016I64X]"), cdinfo->trk[i].start_offset); - TOCLOG(OEMTEXT("[0x%016I64X]\r\n"), cdinfo->trk[i].end_offset); - TOCLOG(OEMTEXT(" pregap_sectors = %I32d\r\n"), cdinfo->trk[i].pregap_sectors); - TOCLOG(OEMTEXT(" track_sectors = %I32d\r\n"), cdinfo->trk[i].track_sectors); - } - TOCLOG(OEMTEXT("END _CDTRK LOG\r\n"), 0); - - textfile_close(tfh); -#endif - - return(SUCCESS); - -sxsiope_err3: - _MFREE(cdinfo); - -sxsiope_err2: - file_close(fh); - -sxsiope_err1: - return(FAILURE); -} - -// ---- -// セクタ長取得用(でもREAD CAPACITYコマンドに返事してくれない場合があるような・・・) -UINT32 readcapacity_SPTI(FILEH fh) { - - //CDINFO cdinfo; - UINT rsize; - - { - DWORD sptisize=0; - struct sptdreadcapacityinfo sptd = {0}; - // READ_CAPACITY command - sptd.info.Cdb[0] = 0x25; - sptd.info.Cdb[9] = 0xF8; - - sptd.info.CdbLength = 10; - sptd.info.Length = sizeof(SCSI_PASS_THROUGH); - sptd.info.DataIn = SCSI_IOCTL_DATA_IN; - sptd.info.DataTransferLength = 8; - sptd.info.DataBufferOffset = offsetof(struct sptdreadcapacityinfo, ucDataBuf); - //sptd.info.DataBuffer = ucDataBuf; - sptd.info.SenseInfoLength = sizeof(sptd.sense_buffer); - sptd.info.SenseInfoOffset = offsetof(struct sptdreadcapacityinfo, sense_buffer); - sptd.info.TimeOutValue = 5; - - //memset(buf, 0, 2048 * size); - //memset(ucDataBuf, 0, 16384); - //SetLastError(0); - if (DeviceIoControl(fh, IOCTL_SCSI_PASS_THROUGH, &sptd, offsetof(struct sptdreadcapacityinfo, sense_buffer)+sizeof(sptd.sense_buffer), &sptd, offsetof(struct sptdreadcapacityinfo, ucDataBuf)+8, &sptisize, FALSE)) - { - if (sptd.info.DataTransferLength != 0){ - int secsize = LOADMOTOROLADWORD(sptd.ucDataBuf+4); - return(secsize); - } - } - } - - - //if (file_seek(fh, pos, FSEEK_SET) != pos) { - // return(0xd0); - //} - - //while(size) { - // rsize = min(size, 2048); - // CPU_REMCLOCK -= rsize; - // if (file_read(fh, buf, rsize) != rsize) { - // return(0xd0); - // } - // buf += rsize; - // size -= rsize; - //} - // - rsize = GetLastError(); - return 0; -} - -// 実ドライブを開く -BRESULT openrealcdd(SXSIDEV sxsi, const OEMCHAR *path) { - - _CDTRK trk[99]; - UINT trks; - FILEH fh; - UINT16 sector_size; - FILELEN totals; - DISK_GEOMETRY dgCDROM; - CDROM_TOC tocCDROM; - DWORD dwNotUsed; - UINT i; - - ZeroMemory(trk, sizeof(trk)); - trks = 0; - - //fh = file_open_rb(path); - fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - //fh = file_open(path); - if (fh == FILEH_INVALID) { - goto openiso_err1; - } - - // セクタサイズが2048byte、2352byte、2448byteのどれかをチェック - DeviceIoControl(fh, IOCTL_CDROM_GET_DRIVE_GEOMETRY, - NULL, 0, &dgCDROM, sizeof(DISK_GEOMETRY), - &dwNotUsed, NULL); - - if(dgCDROM.MediaType != 11){ // Removable Media Check - goto openiso_err2; - } - - sector_size = (UINT16)dgCDROM.BytesPerSector; - totals = (FILELEN)dgCDROM.SectorsPerTrack*dgCDROM.TracksPerCylinder*dgCDROM.Cylinders.QuadPart; - switch(sector_size){ - case 2048: - if(readcapacity_SPTI(fh) == 2048){ - sxsi->read = sec2048_read_SPTI; - }else{ - sxsi->read = sec2048_read; - } - break; - case 2352: - sxsi->read = sec2352_read; - break; - case 2448: - sxsi->read = sec2448_read; - break; - default: - goto openiso_err2; - } - - // トラック情報を拾う - DeviceIoControl(fh, IOCTL_CDROM_READ_TOC, - NULL, 0, &tocCDROM, sizeof(tocCDROM), - &dwNotUsed, NULL); - - trks = tocCDROM.LastTrack - tocCDROM.FirstTrack + 1; - if (trks <= 0) goto openiso_err2; - for(i=0;itotals = trk[trks-1].end_sector; - - file_close(fh); - - return(setsxsidev_SPTI(sxsi, path, trk, trks)); - -openiso_err2: - file_close(fh); - -openiso_err1: - return(FAILURE); -} - -#endif - -// _CDTRK trk[99]; -// UINT trks; -// FILEH fh; -// UINT16 sector_size; -// FILELEN totals; -// DISK_GEOMETRY dgCDROM; -// CDROM_TOC_FULL_TOC_DATA tocCDROMtmp; -// CDROM_TOC_FULL_TOC_DATA *lptocCDROM; -// DWORD dwNotUsed; -// int i; -// WORD lentmp; -// CDROM_READ_TOC_EX TOCEx={0}; -// -// TOCEx.Format=CDROM_READ_TOC_EX_FORMAT_FULL_TOC; -// TOCEx.Msf=1; -// -// ZeroMemory(trk, sizeof(trk)); -// trks = 0; -// -// //fh = CreateFile(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); -// fh = file_open_rb(path); -// if (fh == FILEH_INVALID) { -// goto openiso_err1; -// } -// -// // セクタサイズが2048byte、2352byte、2448byteのどれかをチェック -// DeviceIoControl(fh, IOCTL_CDROM_GET_DRIVE_GEOMETRY, -// NULL, 0, &dgCDROM, sizeof(DISK_GEOMETRY), -// &dwNotUsed, NULL); -// -// if(dgCDROM.MediaType != 11){ // Removable Media Check -// goto openiso_err2; -// } -// sector_size = dgCDROM.BytesPerSector; -// totals = dgCDROM.SectorsPerTrack*dgCDROM.TracksPerCylinder*dgCDROM.Cylinders.QuadPart; -// switch(sector_size){ -// case 2048: -// sxsi->read = sec2048_read; -// break; -// case 2352: -// sxsi->read = sec2352_read; -// break; -// case 2448: -// sxsi->read = sec2448_read; -// break; -// default: -// goto openiso_err2; -// } -// -// // トラック情報を拾う -// DeviceIoControl(fh, IOCTL_CDROM_READ_TOC_EX, -// &TOCEx, sizeof(TOCEx), &tocCDROMtmp, sizeof(tocCDROMtmp), -// &dwNotUsed, NULL); -// trks = (LOADMOTOROLAWORD(tocCDROMtmp.Length) - sizeof(UCHAR)*2) / sizeof(CDROM_TOC_FULL_TOC_DATA_BLOCK); -// lentmp = sizeof(CDROM_TOC_FULL_TOC_DATA) + trks * sizeof(CDROM_TOC_FULL_TOC_DATA_BLOCK); -// lptocCDROM = (CDROM_TOC_FULL_TOC_DATA*)calloc(lentmp, 1); -// -// DeviceIoControl(fh, IOCTL_CDROM_READ_TOC_EX, -// &TOCEx, sizeof(TOCEx), lptocCDROM, lentmp, -// &dwNotUsed, NULL); -// -// //trks = tocCDROM.LastTrack - tocCDROM.FirstTrack + 1; -// for(i=0;iDescriptors[i].Control & 0xC) == 0x4){ -// trk[i].adr_ctl = TRACKTYPE_DATA; -// }else{ -// trk[i].adr_ctl = TRACKTYPE_AUDIO; -// } -// trk[i].point = lptocCDROM->Descriptors[i].SessionNumber; -// trk[i].pos = (msf2lba(LOADMOTOROLADWORD(lptocCDROM->Descriptors[i].Msf)) - 150); -// trk[i].pos0 = trk[i].pos; -// -// trk[i].sector_size = sector_size; -// -// trk[i].pregap_sector = trk[i].pos; -// //trk[i].start_sector = trk[i].pos; -// if(i==trks-1){ -// trk[i].end_sector = totals; -// }else{ -// trk[i].end_sector = (msf2lba(LOADMOTOROLADWORD(lptocCDROM->Descriptors[i].Msf)) - 150 - 1); -// } -// -// trk[i].img_pregap_sec = trk[i].pregap_sector; -// trk[i].img_start_sec = trk[i].start_sector; -// trk[i].img_end_sec = trk[i].end_sector; -// -// trk[i].pregap_sectors = 0; -// trk[i].track_sectors = trk[i].end_sector - trk[i].start_sector + 1; -// -// trk[i].str_sec = trk[i].start_sector; -// trk[i].end_sec = trk[i].end_sector; -// trk[i].sectors = trk[i].track_sectors; -// -// trk[i].pregap_offset = trk[i].start_sector * trk[i].sector_size; -// trk[i].start_offset = trk[i].start_sector * trk[i].sector_size; -// trk[i].end_offset = trk[i].end_sector * trk[i].sector_size; -// } -// -// //trk[0].adr_ctl = TRACKTYPE_DATA; -// //trk[0].point = 1; -// //trk[0].pos = 0; -// //trk[0].pos0 = 0; -// -// //trk[0].sector_size = sector_size; -// -// //trk[0].pregap_sector = 0; -// //trk[0].start_sector = 0; -// //trk[0].end_sector = totals; -// -// //trk[0].img_pregap_sec = 0; -// //trk[0].img_start_sec = 0; -// //trk[0].img_end_sec = totals; -// -// //trk[0].pregap_offset = 0; -// //trk[0].start_offset = 0; -// //trk[0].end_offset = totals * sector_size; -// -// //trk[0].pregap_sectors = 0; -// //trk[0].track_sectors = totals; -// //trks = 1; -// -// sxsi->totals = trk[trks-1].end_sector; -// -// file_close(fh); -// -// free(lptocCDROM); -// -// return(setsxsidev(sxsi, path, trk, trks)); -// -//openiso_err2: -// file_close(fh); -// -//openiso_err1: -// return(FAILURE); +#include +#include +#include +#include + +#ifdef SUPPORT_PHYSICAL_CDDRV + +#include + +#pragma warning (push) +#pragma warning (disable: 4091) +#include +#pragma warning (pop) + +#include "diskimage/cddfile.h" +#include "diskimage/cd/cdd_real.h" + +UINT64 msf2lba(UINT64 msf){ + UINT64 m,s,f; + m = (msf >> 16) & 0xffffffffffff; + s = (msf >> 8) & 0xff; + f = (msf >> 0) & 0xff; + return (((m * 60) + s) * 75) + f; +} + +struct sptdinfo +{ + SCSI_PASS_THROUGH info; + char sense_buffer[20]; + UCHAR ucDataBuf[16384]; +}; + +struct sptdreadcapacityinfo +{ + SCSI_PASS_THROUGH info; + char sense_buffer[20]; + UCHAR ucDataBuf[8]; +}; + + +// ---- +// イメージファイル内全トラックセクタ長2048byte用 +REG8 sec2048_read_SPTI(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { + + CDINFO cdinfo; + FILEH fh; + //UINT rsize; + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(0x40); + } + + cdinfo = (CDINFO)sxsi->hdl; + fh = cdinfo->fh; + + size /= 2048; + + if (1 || size != 2048) { + DWORD sptisize = 0; + struct sptdinfo* psptd = (struct sptdinfo*)malloc(sizeof(struct sptdinfo)); + if (!psptd) { + return(0x60); + } + memset(psptd, 0, sizeof(struct sptdinfo)); + //UCHAR ucDataBuf[2048*8]; + + // READ command + psptd->info.Cdb[0] = 0x28;//0xBE;//0x3C;//0xBE; + // Don't care about sector type. + //psptd->info.Cdb[1] = 0; + //psptd->info.Cdb[2] = (pos >> 24) & 0xFF; + //psptd->info.Cdb[3] = (pos >> 16) & 0xFF; + //psptd->info.Cdb[4] = (pos >> 8) & 0xFF; + //psptd->info.Cdb[5] = pos & 0xFF; + //psptd->info.Cdb[6] = (size >> 16) & 0xFF; + //psptd->info.Cdb[7] = (size >> 8) & 0xFF; + //psptd->info.Cdb[8] = size & 0xFF; + //// Sync + all headers + user data + EDC/ECC. Excludes C2 + subchannel + psptd->info.Cdb[1] = 2; // Data mode + psptd->info.Cdb[2] = (pos >> 24) & 0xFF; + psptd->info.Cdb[3] = (pos >> 16) & 0xFF; + psptd->info.Cdb[4] = (pos >> 8) & 0xFF; + psptd->info.Cdb[5] = pos & 0xFF; + psptd->info.Cdb[6] = (size >> 16) & 0xFF; + psptd->info.Cdb[7] = (size >> 8) & 0xFF; + psptd->info.Cdb[8] = size & 0xFF; + psptd->info.Cdb[9] = 0xF8; + psptd->info.Cdb[10] = 0; + psptd->info.Cdb[11] = 0; + + psptd->info.CdbLength = 12; + psptd->info.Length = sizeof(SCSI_PASS_THROUGH); + psptd->info.DataIn = SCSI_IOCTL_DATA_IN; + psptd->info.DataTransferLength = 2048 * size; + psptd->info.DataBufferOffset = offsetof(struct sptdinfo, ucDataBuf); + //psptd->info.DataBuffer = ucDataBuf; + psptd->info.SenseInfoLength = sizeof(psptd->sense_buffer); + psptd->info.SenseInfoOffset = offsetof(struct sptdinfo, sense_buffer); + psptd->info.TimeOutValue = 5; + + if (psptd->info.DataTransferLength > sizeof(psptd->ucDataBuf)) return 0xd0; + + if (DeviceIoControl(fh, IOCTL_SCSI_PASS_THROUGH, psptd, offsetof(struct sptdinfo, sense_buffer) + sizeof(psptd->sense_buffer), psptd, offsetof(struct sptdinfo, ucDataBuf) + 2048 * size, &sptisize, FALSE)) + { + if (psptd->info.DataTransferLength != 0) { + memcpy(buf, psptd->ucDataBuf, psptd->info.DataTransferLength); + free(psptd); + return(0x00); + } + } + free(psptd); + } + + return(0xd0); +} + +// イメージファイルの実体を開き、各種情報構築 +BRESULT setsxsidev_SPTI(SXSIDEV sxsi, const OEMCHAR *path, const _CDTRK *trk, UINT trks) { + + FILEH fh; + long totals; + CDINFO cdinfo; + UINT mediatype; + UINT i; +#ifdef TOCLOGOUT + OEMCHAR logpath[MAX_PATH]; + OEMCHAR logbuf[2048]; + TEXTFILEH tfh; +#endif + + // trk、trksは有効な値が設定済みなのが前提 + if ((trk == NULL) || (trks == 0)) { + goto sxsiope_err1; + } + + fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (fh == FILEH_INVALID) { + goto sxsiope_err1; + } + + cdinfo = (CDINFO)_MALLOC(sizeof(_CDINFO), path); + if (cdinfo == NULL) { + goto sxsiope_err2; + } + ZeroMemory(cdinfo, sizeof(_CDINFO)); + cdinfo->fh = fh; + trks = min(trks, NELEMENTS(cdinfo->trk) - 1); + CopyMemory(cdinfo->trk, trk, trks * sizeof(_CDTRK)); + +#ifdef TOCLOGOUT + file_cpyname(logpath, path, NELEMENTS(logpath)); + file_cutext(logpath); + file_catname(logpath, str_logB, NELEMENTS(logpath)); + + tfh = textfile_create(logpath, 0x800); + if (tfh == NULL) { + return(FAILURE); + } + + TOCLOG(OEMTEXT("STR _CDTRK LOG\r\n"), 0); + for (i = 0; i < trks; i++) { + TOCLOG(OEMTEXT("trk[%02d]\r\n"), i); + TOCLOG(OEMTEXT(" adr_ctl = 0x%02X\r\n"), cdinfo->trk[i].adr_ctl); + TOCLOG(OEMTEXT(" point = %02d\r\n"), cdinfo->trk[i].point); + TOCLOG(OEMTEXT(" [pos0][pos][ ] = [%18I32d]"), cdinfo->trk[i].pos0); + TOCLOG(OEMTEXT("[%18I32d][ ]\r\n"), cdinfo->trk[i].pos); + TOCLOG(OEMTEXT(" sec[ ][str][end] = [ ][%18I32d]"), cdinfo->trk[i].str_sec); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sec); + TOCLOG(OEMTEXT(" sectors = %I32d\r\n"), cdinfo->trk[i].sectors); + TOCLOG(OEMTEXT(" sector_size = %d\r\n"), cdinfo->trk[i].sector_size); + TOCLOG(OEMTEXT(" sector [pregap][start][end] = [%18I32d]"), cdinfo->trk[i].pregap_sector); + TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].start_sector); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sector); + TOCLOG(OEMTEXT(" img_sec[pregap][start][end] = [%18I32d]"), cdinfo->trk[i].img_pregap_sec); + TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].img_start_sec); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].img_end_sec); + TOCLOG(OEMTEXT(" offset [pregap][start][end] = [0x%016I64X]"), cdinfo->trk[i].pregap_offset); + TOCLOG(OEMTEXT("[0x%016I64X]"), cdinfo->trk[i].start_offset); + TOCLOG(OEMTEXT("[0x%016I64X]\r\n"), cdinfo->trk[i].end_offset); + TOCLOG(OEMTEXT(" pregap_sectors = %I32d\r\n"), cdinfo->trk[i].pregap_sectors); + TOCLOG(OEMTEXT(" track_sectors = %I32d\r\n"), cdinfo->trk[i].track_sectors); + } + TOCLOG(OEMTEXT("END _CDTRK LOG\r\n"), 0); + + textfile_close(tfh); +#endif + +#if 1 + if (sxsi->totals == -1) { + totals = set_trkinfo(fh, cdinfo->trk, trks, 0); + if (totals < 0) { + goto sxsiope_err3; + } + sxsi->totals = totals; + } +#else + totals = issec(fh, cdinfo->trk, trks); // とりあえず + sxsi->read = sec2048_read; + totals = issec2048(cdinfo->fh); + if (totals < 0) { + sxsi->read = sec2352_read; + totals = issec2352(cdinfo->fh); + } + if (totals < 0) { + sxsi->read = sec2448_read; + totals = issec2448(cdinfo->fh); + } + if (totals < 0) { + sxsi->read = sec_read; + totals = issec(cdinfo->fh, cdinfo->trk, trks); + } + if (totals < 0) { + goto sxsiope_err3; + } +#endif + + mediatype = 0; + for (i = 0; i < trks; i++) { + if (cdinfo->trk[i].adr_ctl == TRACKTYPE_DATA) { + mediatype |= SXSIMEDIA_DATA; + } + else if (cdinfo->trk[i].adr_ctl == TRACKTYPE_AUDIO) { + mediatype |= SXSIMEDIA_AUDIO; + } + } + + // リードアウトトラックを生成 + cdinfo->trk[trks].adr_ctl = 0x10; + cdinfo->trk[trks].point = 0xaa; +// cdinfo->trk[trks].pos = totals; + cdinfo->trk[trks].pos = (UINT32)sxsi->totals; + + cdinfo->trks = trks; + file_cpyname(cdinfo->path, path, NELEMENTS(cdinfo->path)); + + sxsi->reopen = cd_reopen; + sxsi->close = cd_close; + sxsi->destroy = cd_destroy; + sxsi->hdl = (INTPTR)cdinfo; +// sxsi->totals = totals; + sxsi->cylinders = 0; + sxsi->size = 2352; + sxsi->sectors = 1; + sxsi->surfaces = 1; + sxsi->headersize = 0; + sxsi->mediatype = mediatype; + +#ifdef TOCLOGOUT + file_cpyname(logpath, path, NELEMENTS(logpath)); + file_cutext(logpath); + file_catname(logpath, str_logA, NELEMENTS(logpath)); + + tfh = textfile_create(logpath, 0x800); + if (tfh == NULL) { + return(FAILURE); + } + + TOCLOG(OEMTEXT("STR _CDTRK LOG\r\n"), 0); + for (i = 0; i < trks; i++) { + TOCLOG(OEMTEXT("trk[%02d]\r\n"), i); + TOCLOG(OEMTEXT(" adr_ctl = 0x%02X\r\n"), cdinfo->trk[i].adr_ctl); + TOCLOG(OEMTEXT(" point = %02d\r\n"), cdinfo->trk[i].point); + TOCLOG(OEMTEXT(" [pos0][pos][ ] = [%18I32d]"), cdinfo->trk[i].pos0); + TOCLOG(OEMTEXT("[%18I32d][ ]\r\n"), cdinfo->trk[i].pos); + TOCLOG(OEMTEXT(" sec[ ][str][end] = [ ][%18I32d]"), cdinfo->trk[i].str_sec); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sec); + TOCLOG(OEMTEXT(" sectors = %I32d\r\n"), cdinfo->trk[i].sectors); + TOCLOG(OEMTEXT(" sector_size = %d\r\n"), cdinfo->trk[i].sector_size); + TOCLOG(OEMTEXT(" sector [pregap][start][end] = [%18I32d]"), cdinfo->trk[i].pregap_sector); + TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].start_sector); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sector); + TOCLOG(OEMTEXT(" img_sec[pregap][start][end] = [%18I32d]"), cdinfo->trk[i].img_pregap_sec); + TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].img_start_sec); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].img_end_sec); + TOCLOG(OEMTEXT(" offset [pregap][start][end] = [0x%016I64X]"), cdinfo->trk[i].pregap_offset); + TOCLOG(OEMTEXT("[0x%016I64X]"), cdinfo->trk[i].start_offset); + TOCLOG(OEMTEXT("[0x%016I64X]\r\n"), cdinfo->trk[i].end_offset); + TOCLOG(OEMTEXT(" pregap_sectors = %I32d\r\n"), cdinfo->trk[i].pregap_sectors); + TOCLOG(OEMTEXT(" track_sectors = %I32d\r\n"), cdinfo->trk[i].track_sectors); + } + TOCLOG(OEMTEXT("END _CDTRK LOG\r\n"), 0); + + textfile_close(tfh); +#endif + + return(SUCCESS); + +sxsiope_err3: + _MFREE(cdinfo); + +sxsiope_err2: + file_close(fh); + +sxsiope_err1: + return(FAILURE); +} + +// ---- +// セクタ長取得用(でもREAD CAPACITYコマンドに返事してくれない場合があるような・・・) +UINT32 readcapacity_SPTI(FILEH fh) { + + //CDINFO cdinfo; + UINT rsize; + + { + DWORD sptisize=0; + struct sptdreadcapacityinfo sptd = {0}; + // READ_CAPACITY command + sptd.info.Cdb[0] = 0x25; + sptd.info.Cdb[9] = 0xF8; + + sptd.info.CdbLength = 10; + sptd.info.Length = sizeof(SCSI_PASS_THROUGH); + sptd.info.DataIn = SCSI_IOCTL_DATA_IN; + sptd.info.DataTransferLength = 8; + sptd.info.DataBufferOffset = offsetof(struct sptdreadcapacityinfo, ucDataBuf); + //sptd.info.DataBuffer = ucDataBuf; + sptd.info.SenseInfoLength = sizeof(sptd.sense_buffer); + sptd.info.SenseInfoOffset = offsetof(struct sptdreadcapacityinfo, sense_buffer); + sptd.info.TimeOutValue = 5; + + //memset(buf, 0, 2048 * size); + //memset(ucDataBuf, 0, 16384); + //SetLastError(0); + if (DeviceIoControl(fh, IOCTL_SCSI_PASS_THROUGH, &sptd, offsetof(struct sptdreadcapacityinfo, sense_buffer)+sizeof(sptd.sense_buffer), &sptd, offsetof(struct sptdreadcapacityinfo, ucDataBuf)+8, &sptisize, FALSE)) + { + if (sptd.info.DataTransferLength != 0){ + int secsize = LOADMOTOROLADWORD(sptd.ucDataBuf+4); + return(secsize); + } + } + } + + + //if (file_seek(fh, pos, FSEEK_SET) != pos) { + // return(0xd0); + //} + + //while(size) { + // rsize = min(size, 2048); + // CPU_REMCLOCK -= rsize; + // if (file_read(fh, buf, rsize) != rsize) { + // return(0xd0); + // } + // buf += rsize; + // size -= rsize; + //} + // + rsize = GetLastError(); + return 0; +} + +// 実ドライブを開く +BRESULT openrealcdd(SXSIDEV sxsi, const OEMCHAR *path) { + + _CDTRK trk[99]; + UINT trks; + FILEH fh; + UINT16 sector_size; + FILELEN totals; + DISK_GEOMETRY dgCDROM; + CDROM_TOC tocCDROM; + DWORD dwNotUsed; + UINT i; + + ZeroMemory(trk, sizeof(trk)); + trks = 0; + + //fh = file_open_rb(path); + fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + //fh = file_open(path); + if (fh == FILEH_INVALID) { + goto openiso_err1; + } + + // セクタサイズが2048byte、2352byte、2448byteのどれかをチェック + DeviceIoControl(fh, IOCTL_CDROM_GET_DRIVE_GEOMETRY, + NULL, 0, &dgCDROM, sizeof(DISK_GEOMETRY), + &dwNotUsed, NULL); + + if(dgCDROM.MediaType != 11){ // Removable Media Check + goto openiso_err2; + } + + sector_size = (UINT16)dgCDROM.BytesPerSector; + totals = (FILELEN)dgCDROM.SectorsPerTrack*dgCDROM.TracksPerCylinder*dgCDROM.Cylinders.QuadPart; + switch(sector_size){ + case 2048: + if(readcapacity_SPTI(fh) == 2048){ + sxsi->read = sec2048_read_SPTI; + }else{ + sxsi->read = sec2048_read; + } + break; + case 2352: + sxsi->read = sec2352_read; + break; + case 2448: + sxsi->read = sec2448_read; + break; + default: + goto openiso_err2; + } + + // トラック情報を拾う + DeviceIoControl(fh, IOCTL_CDROM_READ_TOC, + NULL, 0, &tocCDROM, sizeof(tocCDROM), + &dwNotUsed, NULL); + + trks = tocCDROM.LastTrack - tocCDROM.FirstTrack + 1; + if (trks <= 0) goto openiso_err2; + for(i=0;itotals = trk[trks-1].end_sector; + + file_close(fh); + + return(setsxsidev_SPTI(sxsi, path, trk, trks)); + +openiso_err2: + file_close(fh); + +openiso_err1: + return(FAILURE); +} + +#endif + +// _CDTRK trk[99]; +// UINT trks; +// FILEH fh; +// UINT16 sector_size; +// FILELEN totals; +// DISK_GEOMETRY dgCDROM; +// CDROM_TOC_FULL_TOC_DATA tocCDROMtmp; +// CDROM_TOC_FULL_TOC_DATA *lptocCDROM; +// DWORD dwNotUsed; +// int i; +// WORD lentmp; +// CDROM_READ_TOC_EX TOCEx={0}; +// +// TOCEx.Format=CDROM_READ_TOC_EX_FORMAT_FULL_TOC; +// TOCEx.Msf=1; +// +// ZeroMemory(trk, sizeof(trk)); +// trks = 0; +// +// //fh = CreateFile(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); +// fh = file_open_rb(path); +// if (fh == FILEH_INVALID) { +// goto openiso_err1; +// } +// +// // セクタサイズが2048byte、2352byte、2448byteのどれかをチェック +// DeviceIoControl(fh, IOCTL_CDROM_GET_DRIVE_GEOMETRY, +// NULL, 0, &dgCDROM, sizeof(DISK_GEOMETRY), +// &dwNotUsed, NULL); +// +// if(dgCDROM.MediaType != 11){ // Removable Media Check +// goto openiso_err2; +// } +// sector_size = dgCDROM.BytesPerSector; +// totals = dgCDROM.SectorsPerTrack*dgCDROM.TracksPerCylinder*dgCDROM.Cylinders.QuadPart; +// switch(sector_size){ +// case 2048: +// sxsi->read = sec2048_read; +// break; +// case 2352: +// sxsi->read = sec2352_read; +// break; +// case 2448: +// sxsi->read = sec2448_read; +// break; +// default: +// goto openiso_err2; +// } +// +// // トラック情報を拾う +// DeviceIoControl(fh, IOCTL_CDROM_READ_TOC_EX, +// &TOCEx, sizeof(TOCEx), &tocCDROMtmp, sizeof(tocCDROMtmp), +// &dwNotUsed, NULL); +// trks = (LOADMOTOROLAWORD(tocCDROMtmp.Length) - sizeof(UCHAR)*2) / sizeof(CDROM_TOC_FULL_TOC_DATA_BLOCK); +// lentmp = sizeof(CDROM_TOC_FULL_TOC_DATA) + trks * sizeof(CDROM_TOC_FULL_TOC_DATA_BLOCK); +// lptocCDROM = (CDROM_TOC_FULL_TOC_DATA*)calloc(lentmp, 1); +// +// DeviceIoControl(fh, IOCTL_CDROM_READ_TOC_EX, +// &TOCEx, sizeof(TOCEx), lptocCDROM, lentmp, +// &dwNotUsed, NULL); +// +// //trks = tocCDROM.LastTrack - tocCDROM.FirstTrack + 1; +// for(i=0;iDescriptors[i].Control & 0xC) == 0x4){ +// trk[i].adr_ctl = TRACKTYPE_DATA; +// }else{ +// trk[i].adr_ctl = TRACKTYPE_AUDIO; +// } +// trk[i].point = lptocCDROM->Descriptors[i].SessionNumber; +// trk[i].pos = (msf2lba(LOADMOTOROLADWORD(lptocCDROM->Descriptors[i].Msf)) - 150); +// trk[i].pos0 = trk[i].pos; +// +// trk[i].sector_size = sector_size; +// +// trk[i].pregap_sector = trk[i].pos; +// //trk[i].start_sector = trk[i].pos; +// if(i==trks-1){ +// trk[i].end_sector = totals; +// }else{ +// trk[i].end_sector = (msf2lba(LOADMOTOROLADWORD(lptocCDROM->Descriptors[i].Msf)) - 150 - 1); +// } +// +// trk[i].img_pregap_sec = trk[i].pregap_sector; +// trk[i].img_start_sec = trk[i].start_sector; +// trk[i].img_end_sec = trk[i].end_sector; +// +// trk[i].pregap_sectors = 0; +// trk[i].track_sectors = trk[i].end_sector - trk[i].start_sector + 1; +// +// trk[i].str_sec = trk[i].start_sector; +// trk[i].end_sec = trk[i].end_sector; +// trk[i].sectors = trk[i].track_sectors; +// +// trk[i].pregap_offset = trk[i].start_sector * trk[i].sector_size; +// trk[i].start_offset = trk[i].start_sector * trk[i].sector_size; +// trk[i].end_offset = trk[i].end_sector * trk[i].sector_size; +// } +// +// //trk[0].adr_ctl = TRACKTYPE_DATA; +// //trk[0].point = 1; +// //trk[0].pos = 0; +// //trk[0].pos0 = 0; +// +// //trk[0].sector_size = sector_size; +// +// //trk[0].pregap_sector = 0; +// //trk[0].start_sector = 0; +// //trk[0].end_sector = totals; +// +// //trk[0].img_pregap_sec = 0; +// //trk[0].img_start_sec = 0; +// //trk[0].img_end_sec = totals; +// +// //trk[0].pregap_offset = 0; +// //trk[0].start_offset = 0; +// //trk[0].end_offset = totals * sector_size; +// +// //trk[0].pregap_sectors = 0; +// //trk[0].track_sectors = totals; +// //trks = 1; +// +// sxsi->totals = trk[trks-1].end_sector; +// +// file_close(fh); +// +// free(lptocCDROM); +// +// return(setsxsidev(sxsi, path, trk, trks)); +// +//openiso_err2: +// file_close(fh); +// +//openiso_err1: +// return(FAILURE); diff --git a/diskimage/cd/cdd_real.h b/diskimage/cd/cdd_real.h index a5349efe..595eafce 100644 --- a/diskimage/cd/cdd_real.h +++ b/diskimage/cd/cdd_real.h @@ -1,51 +1,51 @@ -#ifdef SUPPORT_PHYSICAL_CDDRV - -#ifdef __cplusplus -extern "C" { -#endif - -#if 0 -#include -#else - // DDK用意が面倒なので代替 -#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(FILE_DEVICE_CD_ROM, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_READ_TOC CTL_CODE(FILE_DEVICE_CD_ROM, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_RAW_READ CTL_CODE(FILE_DEVICE_CD_ROM, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) - -typedef struct _TRACK_DATA { - UCHAR Reserved; - UCHAR Control : 4; - UCHAR Adr : 4; - UCHAR TrackNumber; - UCHAR Reserved1; - UCHAR Address[4]; -} TRACK_DATA, * PTRACK_DATA; - -typedef struct _CDROM_TOC { - UCHAR Length[2]; - UCHAR FirstTrack; - UCHAR LastTrack; - TRACK_DATA TrackData[100]; -} CDROM_TOC, * PCDROM_TOC; - -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; - -#endif - -BRESULT openrealcdd(SXSIDEV sxsi, const OEMCHAR *fname); - -#ifdef __cplusplus -} -#endif - +#ifdef SUPPORT_PHYSICAL_CDDRV + +#ifdef __cplusplus +extern "C" { +#endif + +#if 0 +#include +#else + // DDK用意が面倒なので代替 +#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(FILE_DEVICE_CD_ROM, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_READ_TOC CTL_CODE(FILE_DEVICE_CD_ROM, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_RAW_READ CTL_CODE(FILE_DEVICE_CD_ROM, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) + +typedef struct _TRACK_DATA { + UCHAR Reserved; + UCHAR Control : 4; + UCHAR Adr : 4; + UCHAR TrackNumber; + UCHAR Reserved1; + UCHAR Address[4]; +} TRACK_DATA, * PTRACK_DATA; + +typedef struct _CDROM_TOC { + UCHAR Length[2]; + UCHAR FirstTrack; + UCHAR LastTrack; + TRACK_DATA TrackData[100]; +} CDROM_TOC, * PCDROM_TOC; + +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; + +#endif + +BRESULT openrealcdd(SXSIDEV sxsi, const OEMCHAR *fname); + +#ifdef __cplusplus +} +#endif + #endif \ No newline at end of file diff --git a/diskimage/cddfile.c b/diskimage/cddfile.c old mode 100755 new mode 100644 index 32710dd0..86875c01 --- a/diskimage/cddfile.c +++ b/diskimage/cddfile.c @@ -1,810 +1,810 @@ -#include -#include -#include -#include -#include -#include "cddfile.h" - -#ifdef SUPPORT_KAI_IMAGES - -#include "diskimage/img_strres.h" -#include "diskimage/win9x/img_dosio.h" -#include "diskimage/cd/cdd_iso.h" - -// ISO9660のボリューム記述子によるチェックを有効にする場合はコメントを外す -// ※有効にした場合、CD-ROM以外がマウントできなくなる -//#define CHECK_ISO9660 - -#ifdef CHECK_ISO9660 -static const UINT8 cd001[7] = {0x01,'C','D','0','0','1',0x01}; -#endif - -#define CD_EDC_POLYNOMIAL 0xD8018001 // Reverse 0x8001801B - -UINT32 crcTable[256]; - -void makeCRCTable( void) -{ - UINT32 i, j; - for( i=0; i<256; i++){ - UINT32 crc = i; - for( j=0; j<8; j++){ - crc = ( crc >> 1) ^ ( ( crc & 0x1) ? CD_EDC_POLYNOMIAL : 0); - } - crcTable[i] = crc; - } -} - -// 追加(kaiA) -BOOL isCDImage(const OEMCHAR *fname) { - -const OEMCHAR *ext; - - ext = file_getext(fname); - if ((!file_cmpname(ext, str_cue)) || - (!file_cmpname(ext, str_ccd)) || - (!file_cmpname(ext, str_cdm)) || - (!file_cmpname(ext, str_mds)) || - (!file_cmpname(ext, str_nrg)) || - (!file_cmpname(ext, str_iso))) { - return TRUE; - } - return FALSE; -} -// - -long issec2048(FILEH fh) { - -#ifdef CHECK_ISO9660 - FILEPOS fpos; - UINT8 buf[2048]; - UINT secsize; -#endif - FILELEN fsize; - -#ifdef CHECK_ISO9660 - fpos = 16 * 2048; - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - goto sec2048_err; - } - if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { - goto sec2048_err; - } - if (memcmp(buf, cd001, 7) != 0) { - goto sec2048_err; - } - secsize = LOADINTELWORD(buf + 128); - if (secsize != 2048) { - goto sec2048_err; - } -#endif - fsize = file_getsize(fh); - if ((fsize % 2048) != 0) { - goto sec2048_err; - } - return((long)(fsize / 2048)); - -sec2048_err: - return(-1); -} - -long issec2352(FILEH fh) { - -#ifdef CHECK_ISO9660 - FILEPOS fpos; - UINT8 buf[2048]; - UINT secsize; -#endif - FILELEN fsize; - -#ifdef CHECK_ISO9660 - fpos = (16 * 2352) + 16; - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - goto sec2352_err; - } - if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { - goto sec2352_err; - } - if (memcmp(buf, cd001, 7) != 0) { - goto sec2352_err; - } - secsize = LOADINTELWORD(buf + 128); - if (secsize != 2048) { - goto sec2352_err; - } -#endif - fsize = file_getsize(fh); - if ((fsize % 2352) != 0) { - goto sec2352_err; - } - return((long)(fsize / 2352)); - -sec2352_err: - return(-1); -} - -long issec2448(FILEH fh) { - -#ifdef CHECK_ISO9660 - FILEPOS fpos; - UINT8 buf[2048]; - UINT secsize; -#endif - FILELEN fsize; - -#ifdef CHECK_ISO9660 - fpos = (16 * 2448) + 16; - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - goto sec2448_err; - } - if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { - goto sec2448_err; - } - if (memcmp(buf, cd001, 7) != 0) { - goto sec2448_err; - } - secsize = LOADINTELWORD(buf + 128); - if (secsize != 2048) { - goto sec2448_err; - } -#endif - fsize = file_getsize(fh); - if ((fsize % 2448) != 0) { - goto sec2448_err; - } - return((long)(fsize / 2448)); - -sec2448_err: - return(-1); -} - -long issec(FILEH fh, _CDTRK *trk, UINT trks) { - -#ifdef CHECK_ISO9660 - FILEPOS fpos; - UINT8 buf[2048]; - UINT secsize; -#endif - UINT i; - FILELEN fsize; - long total; - - total = 0; - -#ifdef CHECK_ISO9660 - fpos = 16 * trk[0].sector_size; - if (trk[0].sector_size != 2048) { - fpos += 16; - } - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - goto sec_err; - } - if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { - goto sec_err; - } - if (memcmp(buf, cd001, 7) != 0) { - goto sec_err; - } - secsize = LOADINTELWORD(buf + 128); - if (secsize != 2048) { - goto sec_err; - } -#endif - - if (trks == 1) { - trk[0].sector_size = 2048; - trk[0].str_sec = 0; - total = issec2048(fh); - if (total < 0) { - trk[0].sector_size = 2352; - total = issec2352(fh); - } - if (total < 0) { - trk[0].sector_size = 2448; - total = issec2448(fh); - } - if (total < 0) { - return(-1); - } - else { - trk[0].end_sec = total - 1; - trk[0].sectors = total; - return(total); - } - } - - fsize = file_getsize(fh); - if (trk[0].pos0 == 0) { - trk[0].str_sec = trk[0].pos; - } - else { - trk[0].str_sec = trk[0].pos0; - } - for (i = 1; i < trks; i++) { - if (trk[i].pos0 == 0) { - trk[i].str_sec = trk[i].pos; - } - else { - trk[i].str_sec = trk[i].pos0; - } - trk[i-1].end_sec = trk[i].str_sec - 1; - trk[i-1].sectors = trk[i-1].end_sec - trk[i-1].str_sec + 1; - total += trk[i-1].sectors; - fsize -= trk[i-1].sectors * trk[i-1].sector_size; - } - if (fsize % trk[trks-1].sector_size != 0) { - return(-1); - } - if (trk[trks-1].pos0 == 0) { - trk[trks-1].str_sec = trk[trks-1].pos; - } - else { - trk[trks-1].str_sec = trk[trks-1].pos0; - } - trk[trks-1].end_sec = (UINT32)(trk[trks-1].str_sec + (fsize / trk[trks-1].sector_size)); - trk[trks-1].sectors = trk[trks-1].end_sec - trk[trks-1].str_sec + 1; - total += trk[trks-1].sectors; - - return(total); - -#ifdef CHECK_ISO9660 -sec_err: - return(-1); -#endif -} - -// ※CDTRK構造体内の -// UINT32 str_sec; -// UINT32 end_sec; -// UINT32 sectors; -// 等のメンバの設定 -long set_trkinfo(FILEH fh, _CDTRK *trk, UINT trks, FILELEN imagesize) { - - UINT i; - FILELEN fsize; - long total; - - total = 0; - - if (trks == 1) { - trk[0].sector_size = 2048; - trk[0].str_sec = 0; - total = issec2048(fh); - if (total < 0) { - trk[0].sector_size = 2352; - total = issec2352(fh); - } - if (total < 0) { - trk[0].sector_size = 2448; - total = issec2448(fh); - } - if (total < 0) { - return(-1); - } - else { - trk[0].end_sec = total - 1; - trk[0].sectors = total; - return(total); - } - } - - if (imagesize == 0) { - fsize = file_getsize(fh); - } - else { - fsize = imagesize; - } - if (trk[0].pos0 == 0) { - trk[0].str_sec = trk[0].pos; - } - else { - trk[0].str_sec = trk[0].pos0; - } - for (i = 1; i < trks; i++) { - if (trk[i].pos0 == 0) { - trk[i].str_sec = trk[i].pos; - } - else { - trk[i].str_sec = trk[i].pos0; - } - trk[i-1].end_sec = trk[i].str_sec - 1; - trk[i-1].sectors = trk[i-1].end_sec - trk[i-1].str_sec + 1; - total += trk[i-1].sectors; - fsize -= trk[i-1].sectors * trk[i-1].sector_size; - } - if (fsize % trk[trks-1].sector_size != 0) { - return(-1); - } - if (trk[trks-1].pos0 == 0) { - trk[trks-1].str_sec = trk[trks-1].pos; - } - else { - trk[trks-1].str_sec = trk[trks-1].pos0; - } - trk[trks-1].end_sec = (UINT32)(trk[trks-1].str_sec + (fsize / trk[trks-1].sector_size)); - trk[trks-1].sectors = trk[trks-1].end_sec - trk[trks-1].str_sec + 1; - total += trk[trks-1].sectors; - - return(total); -} - - -// ---- -// イメージファイル内全トラックセクタ長2048byte用 -REG8 sec2048_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { - - CDINFO cdinfo; - FILEH fh; - UINT rsize; - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(0x40); - } - - cdinfo = (CDINFO)sxsi->hdl; - fh = cdinfo->fh; - - pos = (FILEPOS)(pos * 2048 + cdinfo->trk[0].start_offset); - if (file_seek(fh, pos, FSEEK_SET) != pos) { - return(0xd0); - } - - while(size) { - rsize = MIN(size, 2048); - CPU_REMCLOCK -= rsize; - if (file_read(fh, buf, rsize) != rsize) { - return(0xd0); - } - buf += rsize; - size -= rsize; - } - return(0x00); -} - - -// イメージファイル内全トラックセクタ長2352byte用 -REG8 sec2352_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { - - CDINFO cdinfo; - FILEH fh; - FILEPOS fpos; - UINT rsize; - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(0x40); - } - - cdinfo = (CDINFO)sxsi->hdl; - fh = cdinfo->fh; - - while(size) { - fpos = (FILEPOS)((pos * 2352) + 16 + cdinfo->trk[0].start_offset); - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - return(0xd0); - } - rsize = MIN(size, 2048); - CPU_REMCLOCK -= rsize; - if (file_read(fh, buf, rsize) != rsize) { - return(0xd0); - } - buf += rsize; - size -= rsize; - pos++; - } - return(0x00); -} - -UINT32 calcCRC(UINT8 *buf, int len) -{ - int i; - UINT32 crc = 0x00000000; - for( i=0; i> 8) ^ crcTable[(crc^buf[i]) & 0xff]; - } - return crc; -} - -// イメージファイル内全トラックセクタ長2352byte用(ECCチェック有効) -REG8 sec2352_read_with_ecc(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { - - CDINFO cdinfo; - FILEH fh; - FILEPOS fpos; - UINT rsize; - UINT8 bufedc[4]; - UINT8 bufecc[276]; - UINT8 bufdata[2352]; - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(0x40); - } - - cdinfo = (CDINFO)sxsi->hdl; - fh = cdinfo->fh; - - while(size) { - fpos = (FILEPOS)((pos * 2352) + cdinfo->trk[0].start_offset); - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - return(0xd0); - } - rsize = 2352; - CPU_REMCLOCK -= rsize; - if (file_read(fh, bufdata, rsize) != rsize) { - return(0xd0); - } - memcpy(buf, bufdata+16, MIN(size, 2048)); - memcpy(bufedc, bufdata+16+2048, 4); - memcpy(bufecc, bufdata+16+2048+4+8, 276); - - // Check EDC - if(calcCRC(bufdata, 2064) != LOADINTELDWORD(bufedc)){ - // EDC Error - // TODO: Check ECC - //sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_RECOVERED; // ECC recovered - sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_ERROR; // ECC error - //return(0xd0); - } - - rsize = MIN(size, 2048); - buf += rsize; - size -= rsize; - pos++; - } - return(0x00); -} - - -// イメージファイル内全トラックセクタ長2448(2352+96)用 -REG8 sec2448_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { - - CDINFO cdinfo; - FILEH fh; - FILEPOS fpos; - UINT rsize; - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(0x40); - } - - cdinfo = (CDINFO)sxsi->hdl; - fh = cdinfo->fh; - while(size) { - fpos = (FILEPOS)((pos * 2448) + 16 + cdinfo->trk[0].start_offset); - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - return(0xd0); - } - rsize = MIN(size, 2048); - CPU_REMCLOCK -= rsize; - if (file_read(fh, buf, rsize) != rsize) { - return(0xd0); - } - buf += rsize; - size -= rsize; - pos++; - } - return(0x00); -} - - -// イメージファイル内セクタ長混在用 -// 非RAW(2048byte)+Audio(2352byte)等 -REG8 sec_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { - - CDINFO cdinfo; - FILEH fh; - FILEPOS fpos; - UINT rsize; - UINT i; - UINT32 secs; - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(0x40); - } - - cdinfo = (CDINFO)sxsi->hdl; - fh = cdinfo->fh; - - while (size) { - fpos = 0; - secs = 0; - for (i = 0; i < cdinfo->trks; i++) { - if (cdinfo->trk[i].str_sec <= (UINT32)pos && (UINT32)pos <= cdinfo->trk[i].end_sec) { - fpos += (pos - secs) * cdinfo->trk[i].sector_size; - if (cdinfo->trk[i].sector_size != 2048) { - fpos += 16; - } - break; - } - fpos += cdinfo->trk[i].sectors * cdinfo->trk[i].sector_size; - secs += cdinfo->trk[i].sectors; - } - fpos += (FILEPOS)cdinfo->trk[0].start_offset; - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - return(0xd0); - } - rsize = MIN(size, 2048); - CPU_REMCLOCK -= rsize; - if (file_read(fh, buf, rsize) != rsize) { - return(0xd0); - } - buf += rsize; - size -= rsize; - pos++; - } - return(0x00); -} - -// ---- -BRESULT cd_reopen(SXSIDEV sxsi) { - - CDINFO cdinfo; - FILEH fh; - - cdinfo = (CDINFO)sxsi->hdl; - fh = file_open_rb(cdinfo->path); - if (fh != FILEH_INVALID) { - cdinfo->fh = fh; - return(SUCCESS); - } - else { - return(FAILURE); - } -} - -void cd_close(SXSIDEV sxsi) { - - CDINFO cdinfo; - - cdinfo = (CDINFO)sxsi->hdl; - file_close(cdinfo->fh); -} - -void cd_destroy(SXSIDEV sxsi) { - - if(sxsi->hdl){ - _MFREE((CDINFO)sxsi->hdl); - sxsi->hdl = (INTPTR)NULL; - } -} -// ---- - -void set_secread(SXSIDEV sxsi, const _CDTRK *trk, UINT trks) { - - UINT i; - UINT16 secsize; - - secsize = trk[0].sector_size; - for (i = 1; i < trks; i++) { - if (secsize != trk[i].sector_size) { - secsize = 0; - break; - } - } - if (secsize != 0) { - switch (secsize) { - case 2048: - sxsi->read = sec2048_read; - break; - case 2352: - sxsi->read = sec2352_read_with_ecc; // sec2352_read; - break; - case 2448: - sxsi->read = sec2448_read; - break; - } - } - else { - sxsi->read = sec_read; - } -} - -// -//#define TOCLOGOUT -#ifdef TOCLOGOUT -#define TOCLOG(fmt, val) \ - _stprintf(logbuf, fmt, val); \ - textfile_write(tfh, logbuf); -static const OEMCHAR str_logB[] = OEMTEXT("._CDTRK.Before.log"); -static const OEMCHAR str_logA[] = OEMTEXT("._CDTRK.After.log"); -#endif -// - -// イメージファイルの実体を開き、各種情報構築 -BRESULT setsxsidev(SXSIDEV sxsi, const OEMCHAR *path, const _CDTRK *trk, UINT trks) { - - FILEH fh; - long totals; - CDINFO cdinfo; - UINT mediatype; - UINT i; -#ifdef TOCLOGOUT - OEMCHAR logpath[MAX_PATH]; - OEMCHAR logbuf[2048]; - TEXTFILEH tfh; -#endif - - makeCRCTable(); - - // trk、trksは有効な値が設定済みなのが前提 - if ((trk == NULL) || (trks == 0)) { - goto sxsiope_err1; - } - - fh = file_open_rb(path); - if (fh == FILEH_INVALID) { - goto sxsiope_err1; - } - - cdinfo = (CDINFO)_MALLOC(sizeof(_CDINFO), path); - if (cdinfo == NULL) { - goto sxsiope_err2; - } - ZeroMemory(cdinfo, sizeof(_CDINFO)); - cdinfo->fh = fh; - trks = MIN(trks, NELEMENTS(cdinfo->trk) - 1); - CopyMemory(cdinfo->trk, trk, trks * sizeof(_CDTRK)); - -#ifdef TOCLOGOUT - file_cpyname(logpath, path, NELEMENTS(logpath)); - file_cutext(logpath); - file_catname(logpath, str_logB, NELEMENTS(logpath)); - - tfh = textfile_create(logpath, 0x800); - if (tfh == NULL) { - return(FAILURE); - } - - TOCLOG(OEMTEXT("STR _CDTRK LOG\r\n"), 0); - for (i = 0; i < trks; i++) { - TOCLOG(OEMTEXT("trk[%02d]\r\n"), i); - TOCLOG(OEMTEXT(" adr_ctl = 0x%02X\r\n"), cdinfo->trk[i].adr_ctl); - TOCLOG(OEMTEXT(" point = %02d\r\n"), cdinfo->trk[i].point); - TOCLOG(OEMTEXT(" [pos0][pos][ ] = [%18I32d]"), cdinfo->trk[i].pos0); - TOCLOG(OEMTEXT("[%18I32d][ ]\r\n"), cdinfo->trk[i].pos); - TOCLOG(OEMTEXT(" sec[ ][str][end] = [ ][%18I32d]"), cdinfo->trk[i].str_sec); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sec); - TOCLOG(OEMTEXT(" sectors = %I32d\r\n"), cdinfo->trk[i].sectors); - TOCLOG(OEMTEXT(" sector_size = %d\r\n"), cdinfo->trk[i].sector_size); - TOCLOG(OEMTEXT(" sector [pregap][start][end] = [%18I32d]"), cdinfo->trk[i].pregap_sector); - TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].start_sector); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sector); - TOCLOG(OEMTEXT(" img_sec[pregap][start][end] = [%18I32d]"), cdinfo->trk[i].img_pregap_sec); - TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].img_start_sec); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].img_end_sec); - TOCLOG(OEMTEXT(" offset [pregap][start][end] = [0x%016I64X]"), cdinfo->trk[i].pregap_offset); - TOCLOG(OEMTEXT("[0x%016I64X]"), cdinfo->trk[i].start_offset); - TOCLOG(OEMTEXT("[0x%016I64X]\r\n"), cdinfo->trk[i].end_offset); - TOCLOG(OEMTEXT(" pregap_sectors = %I32d\r\n"), cdinfo->trk[i].pregap_sectors); - TOCLOG(OEMTEXT(" track_sectors = %I32d\r\n"), cdinfo->trk[i].track_sectors); - } - TOCLOG(OEMTEXT("END _CDTRK LOG\r\n"), 0); - - textfile_close(tfh); -#endif - -#if 1 - if (sxsi->totals == -1) { - totals = set_trkinfo(fh, cdinfo->trk, trks, 0); - if (totals < 0) { - goto sxsiope_err3; - } - sxsi->totals = totals; - } -#else - totals = issec(fh, cdinfo->trk, trks); // とりあえず - sxsi->read = sec2048_read; - totals = issec2048(cdinfo->fh); - if (totals < 0) { - sxsi->read = sec2352_read; - totals = issec2352(cdinfo->fh); - } - if (totals < 0) { - sxsi->read = sec2448_read; - totals = issec2448(cdinfo->fh); - } - if (totals < 0) { - sxsi->read = sec_read; - totals = issec(cdinfo->fh, cdinfo->trk, trks); - } - if (totals < 0) { - goto sxsiope_err3; - } -#endif - - mediatype = 0; - for (i = 0; i < trks; i++) { - if (cdinfo->trk[i].adr_ctl == TRACKTYPE_DATA) { - mediatype |= SXSIMEDIA_DATA; - } - else if (cdinfo->trk[i].adr_ctl == TRACKTYPE_AUDIO) { - mediatype |= SXSIMEDIA_AUDIO; - } - } - - // リードアウトトラックを生成 - cdinfo->trk[trks].adr_ctl = 0x10; - cdinfo->trk[trks].point = 0xaa; -// cdinfo->trk[trks].pos = totals; - cdinfo->trk[trks].pos = (UINT32)sxsi->totals; - - cdinfo->trks = trks; - file_cpyname(cdinfo->path, path, NELEMENTS(cdinfo->path)); - - sxsi->reopen = cd_reopen; - sxsi->close = cd_close; - sxsi->destroy = cd_destroy; - sxsi->hdl = (INTPTR)cdinfo; -// sxsi->totals = totals; - sxsi->cylinders = (sxsi->totals + 17 * 8 - 1) / (17 * 8); - sxsi->size = 2048; - sxsi->sectors = 8; - sxsi->surfaces = 17; - sxsi->headersize = 0; - sxsi->mediatype = mediatype; - -#ifdef TOCLOGOUT - file_cpyname(logpath, path, NELEMENTS(logpath)); - file_cutext(logpath); - file_catname(logpath, str_logA, NELEMENTS(logpath)); - - tfh = textfile_create(logpath, 0x800); - if (tfh == NULL) { - return(FAILURE); - } - - TOCLOG(OEMTEXT("STR _CDTRK LOG\r\n"), 0); - for (i = 0; i < trks; i++) { - TOCLOG(OEMTEXT("trk[%02d]\r\n"), i); - TOCLOG(OEMTEXT(" adr_ctl = 0x%02X\r\n"), cdinfo->trk[i].adr_ctl); - TOCLOG(OEMTEXT(" point = %02d\r\n"), cdinfo->trk[i].point); - TOCLOG(OEMTEXT(" [pos0][pos][ ] = [%18I32d]"), cdinfo->trk[i].pos0); - TOCLOG(OEMTEXT("[%18I32d][ ]\r\n"), cdinfo->trk[i].pos); - TOCLOG(OEMTEXT(" sec[ ][str][end] = [ ][%18I32d]"), cdinfo->trk[i].str_sec); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sec); - TOCLOG(OEMTEXT(" sectors = %I32d\r\n"), cdinfo->trk[i].sectors); - TOCLOG(OEMTEXT(" sector_size = %d\r\n"), cdinfo->trk[i].sector_size); - TOCLOG(OEMTEXT(" sector [pregap][start][end] = [%18I32d]"), cdinfo->trk[i].pregap_sector); - TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].start_sector); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sector); - TOCLOG(OEMTEXT(" img_sec[pregap][start][end] = [%18I32d]"), cdinfo->trk[i].img_pregap_sec); - TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].img_start_sec); - TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].img_end_sec); - TOCLOG(OEMTEXT(" offset [pregap][start][end] = [0x%016I64X]"), cdinfo->trk[i].pregap_offset); - TOCLOG(OEMTEXT("[0x%016I64X]"), cdinfo->trk[i].start_offset); - TOCLOG(OEMTEXT("[0x%016I64X]\r\n"), cdinfo->trk[i].end_offset); - TOCLOG(OEMTEXT(" pregap_sectors = %I32d\r\n"), cdinfo->trk[i].pregap_sectors); - TOCLOG(OEMTEXT(" track_sectors = %I32d\r\n"), cdinfo->trk[i].track_sectors); - } - TOCLOG(OEMTEXT("END _CDTRK LOG\r\n"), 0); - - textfile_close(tfh); -#endif - - return(SUCCESS); - -sxsiope_err3: - _MFREE(cdinfo); - -sxsiope_err2: - file_close(fh); - -sxsiope_err1: - return(FAILURE); -} - -#endif +#include +#include +#include +#include +#include +#include "cddfile.h" + +#ifdef SUPPORT_KAI_IMAGES + +#include "diskimage/img_strres.h" +#include "diskimage/win9x/img_dosio.h" +#include "diskimage/cd/cdd_iso.h" + +// ISO9660のボリューム記述子によるチェックを有効にする場合はコメントを外す +// ※有効にした場合、CD-ROM以外がマウントできなくなる +//#define CHECK_ISO9660 + +#ifdef CHECK_ISO9660 +static const UINT8 cd001[7] = {0x01,'C','D','0','0','1',0x01}; +#endif + +#define CD_EDC_POLYNOMIAL 0xD8018001 // Reverse 0x8001801B + +UINT32 crcTable[256]; + +void makeCRCTable( void) +{ + UINT32 i, j; + for( i=0; i<256; i++){ + UINT32 crc = i; + for( j=0; j<8; j++){ + crc = ( crc >> 1) ^ ( ( crc & 0x1) ? CD_EDC_POLYNOMIAL : 0); + } + crcTable[i] = crc; + } +} + +// 追加(kaiA) +BOOL isCDImage(const OEMCHAR *fname) { + +const OEMCHAR *ext; + + ext = file_getext(fname); + if ((!file_cmpname(ext, str_cue)) || + (!file_cmpname(ext, str_ccd)) || + (!file_cmpname(ext, str_cdm)) || + (!file_cmpname(ext, str_mds)) || + (!file_cmpname(ext, str_nrg)) || + (!file_cmpname(ext, str_iso))) { + return TRUE; + } + return FALSE; +} +// + +long issec2048(FILEH fh) { + +#ifdef CHECK_ISO9660 + FILEPOS fpos; + UINT8 buf[2048]; + UINT secsize; +#endif + FILELEN fsize; + +#ifdef CHECK_ISO9660 + fpos = 16 * 2048; + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + goto sec2048_err; + } + if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { + goto sec2048_err; + } + if (memcmp(buf, cd001, 7) != 0) { + goto sec2048_err; + } + secsize = LOADINTELWORD(buf + 128); + if (secsize != 2048) { + goto sec2048_err; + } +#endif + fsize = file_getsize(fh); + if ((fsize % 2048) != 0) { + goto sec2048_err; + } + return((long)(fsize / 2048)); + +sec2048_err: + return(-1); +} + +long issec2352(FILEH fh) { + +#ifdef CHECK_ISO9660 + FILEPOS fpos; + UINT8 buf[2048]; + UINT secsize; +#endif + FILELEN fsize; + +#ifdef CHECK_ISO9660 + fpos = (16 * 2352) + 16; + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + goto sec2352_err; + } + if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { + goto sec2352_err; + } + if (memcmp(buf, cd001, 7) != 0) { + goto sec2352_err; + } + secsize = LOADINTELWORD(buf + 128); + if (secsize != 2048) { + goto sec2352_err; + } +#endif + fsize = file_getsize(fh); + if ((fsize % 2352) != 0) { + goto sec2352_err; + } + return((long)(fsize / 2352)); + +sec2352_err: + return(-1); +} + +long issec2448(FILEH fh) { + +#ifdef CHECK_ISO9660 + FILEPOS fpos; + UINT8 buf[2048]; + UINT secsize; +#endif + FILELEN fsize; + +#ifdef CHECK_ISO9660 + fpos = (16 * 2448) + 16; + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + goto sec2448_err; + } + if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { + goto sec2448_err; + } + if (memcmp(buf, cd001, 7) != 0) { + goto sec2448_err; + } + secsize = LOADINTELWORD(buf + 128); + if (secsize != 2048) { + goto sec2448_err; + } +#endif + fsize = file_getsize(fh); + if ((fsize % 2448) != 0) { + goto sec2448_err; + } + return((long)(fsize / 2448)); + +sec2448_err: + return(-1); +} + +long issec(FILEH fh, _CDTRK *trk, UINT trks) { + +#ifdef CHECK_ISO9660 + FILEPOS fpos; + UINT8 buf[2048]; + UINT secsize; +#endif + UINT i; + FILELEN fsize; + long total; + + total = 0; + +#ifdef CHECK_ISO9660 + fpos = 16 * trk[0].sector_size; + if (trk[0].sector_size != 2048) { + fpos += 16; + } + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + goto sec_err; + } + if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { + goto sec_err; + } + if (memcmp(buf, cd001, 7) != 0) { + goto sec_err; + } + secsize = LOADINTELWORD(buf + 128); + if (secsize != 2048) { + goto sec_err; + } +#endif + + if (trks == 1) { + trk[0].sector_size = 2048; + trk[0].str_sec = 0; + total = issec2048(fh); + if (total < 0) { + trk[0].sector_size = 2352; + total = issec2352(fh); + } + if (total < 0) { + trk[0].sector_size = 2448; + total = issec2448(fh); + } + if (total < 0) { + return(-1); + } + else { + trk[0].end_sec = total - 1; + trk[0].sectors = total; + return(total); + } + } + + fsize = file_getsize(fh); + if (trk[0].pos0 == 0) { + trk[0].str_sec = trk[0].pos; + } + else { + trk[0].str_sec = trk[0].pos0; + } + for (i = 1; i < trks; i++) { + if (trk[i].pos0 == 0) { + trk[i].str_sec = trk[i].pos; + } + else { + trk[i].str_sec = trk[i].pos0; + } + trk[i-1].end_sec = trk[i].str_sec - 1; + trk[i-1].sectors = trk[i-1].end_sec - trk[i-1].str_sec + 1; + total += trk[i-1].sectors; + fsize -= trk[i-1].sectors * trk[i-1].sector_size; + } + if (fsize % trk[trks-1].sector_size != 0) { + return(-1); + } + if (trk[trks-1].pos0 == 0) { + trk[trks-1].str_sec = trk[trks-1].pos; + } + else { + trk[trks-1].str_sec = trk[trks-1].pos0; + } + trk[trks-1].end_sec = (UINT32)(trk[trks-1].str_sec + (fsize / trk[trks-1].sector_size)); + trk[trks-1].sectors = trk[trks-1].end_sec - trk[trks-1].str_sec + 1; + total += trk[trks-1].sectors; + + return(total); + +#ifdef CHECK_ISO9660 +sec_err: + return(-1); +#endif +} + +// ※CDTRK構造体内の +// UINT32 str_sec; +// UINT32 end_sec; +// UINT32 sectors; +// 等のメンバの設定 +long set_trkinfo(FILEH fh, _CDTRK *trk, UINT trks, FILELEN imagesize) { + + UINT i; + FILELEN fsize; + long total; + + total = 0; + + if (trks == 1) { + trk[0].sector_size = 2048; + trk[0].str_sec = 0; + total = issec2048(fh); + if (total < 0) { + trk[0].sector_size = 2352; + total = issec2352(fh); + } + if (total < 0) { + trk[0].sector_size = 2448; + total = issec2448(fh); + } + if (total < 0) { + return(-1); + } + else { + trk[0].end_sec = total - 1; + trk[0].sectors = total; + return(total); + } + } + + if (imagesize == 0) { + fsize = file_getsize(fh); + } + else { + fsize = imagesize; + } + if (trk[0].pos0 == 0) { + trk[0].str_sec = trk[0].pos; + } + else { + trk[0].str_sec = trk[0].pos0; + } + for (i = 1; i < trks; i++) { + if (trk[i].pos0 == 0) { + trk[i].str_sec = trk[i].pos; + } + else { + trk[i].str_sec = trk[i].pos0; + } + trk[i-1].end_sec = trk[i].str_sec - 1; + trk[i-1].sectors = trk[i-1].end_sec - trk[i-1].str_sec + 1; + total += trk[i-1].sectors; + fsize -= trk[i-1].sectors * trk[i-1].sector_size; + } + if (fsize % trk[trks-1].sector_size != 0) { + return(-1); + } + if (trk[trks-1].pos0 == 0) { + trk[trks-1].str_sec = trk[trks-1].pos; + } + else { + trk[trks-1].str_sec = trk[trks-1].pos0; + } + trk[trks-1].end_sec = (UINT32)(trk[trks-1].str_sec + (fsize / trk[trks-1].sector_size)); + trk[trks-1].sectors = trk[trks-1].end_sec - trk[trks-1].str_sec + 1; + total += trk[trks-1].sectors; + + return(total); +} + + +// ---- +// イメージファイル内全トラックセクタ長2048byte用 +REG8 sec2048_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { + + CDINFO cdinfo; + FILEH fh; + UINT rsize; + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(0x40); + } + + cdinfo = (CDINFO)sxsi->hdl; + fh = cdinfo->fh; + + pos = (FILEPOS)(pos * 2048 + cdinfo->trk[0].start_offset); + if (file_seek(fh, pos, FSEEK_SET) != pos) { + return(0xd0); + } + + while(size) { + rsize = MIN(size, 2048); + CPU_REMCLOCK -= rsize; + if (file_read(fh, buf, rsize) != rsize) { + return(0xd0); + } + buf += rsize; + size -= rsize; + } + return(0x00); +} + + +// イメージファイル内全トラックセクタ長2352byte用 +REG8 sec2352_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { + + CDINFO cdinfo; + FILEH fh; + FILEPOS fpos; + UINT rsize; + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(0x40); + } + + cdinfo = (CDINFO)sxsi->hdl; + fh = cdinfo->fh; + + while(size) { + fpos = (FILEPOS)((pos * 2352) + 16 + cdinfo->trk[0].start_offset); + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + return(0xd0); + } + rsize = MIN(size, 2048); + CPU_REMCLOCK -= rsize; + if (file_read(fh, buf, rsize) != rsize) { + return(0xd0); + } + buf += rsize; + size -= rsize; + pos++; + } + return(0x00); +} + +UINT32 calcCRC(UINT8 *buf, int len) +{ + int i; + UINT32 crc = 0x00000000; + for( i=0; i> 8) ^ crcTable[(crc^buf[i]) & 0xff]; + } + return crc; +} + +// イメージファイル内全トラックセクタ長2352byte用(ECCチェック有効) +REG8 sec2352_read_with_ecc(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { + + CDINFO cdinfo; + FILEH fh; + FILEPOS fpos; + UINT rsize; + UINT8 bufedc[4]; + UINT8 bufecc[276]; + UINT8 bufdata[2352]; + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(0x40); + } + + cdinfo = (CDINFO)sxsi->hdl; + fh = cdinfo->fh; + + while(size) { + fpos = (FILEPOS)((pos * 2352) + cdinfo->trk[0].start_offset); + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + return(0xd0); + } + rsize = 2352; + CPU_REMCLOCK -= rsize; + if (file_read(fh, bufdata, rsize) != rsize) { + return(0xd0); + } + memcpy(buf, bufdata+16, MIN(size, 2048)); + memcpy(bufedc, bufdata+16+2048, 4); + memcpy(bufecc, bufdata+16+2048+4+8, 276); + + // Check EDC + if(calcCRC(bufdata, 2064) != LOADINTELDWORD(bufedc)){ + // EDC Error + // TODO: Check ECC + //sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_RECOVERED; // ECC recovered + sxsi->cdflag_ecc = (sxsi->cdflag_ecc & ~CD_ECC_BITMASK) | CD_ECC_ERROR; // ECC error + //return(0xd0); + } + + rsize = MIN(size, 2048); + buf += rsize; + size -= rsize; + pos++; + } + return(0x00); +} + + +// イメージファイル内全トラックセクタ長2448(2352+96)用 +REG8 sec2448_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { + + CDINFO cdinfo; + FILEH fh; + FILEPOS fpos; + UINT rsize; + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(0x40); + } + + cdinfo = (CDINFO)sxsi->hdl; + fh = cdinfo->fh; + while(size) { + fpos = (FILEPOS)((pos * 2448) + 16 + cdinfo->trk[0].start_offset); + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + return(0xd0); + } + rsize = MIN(size, 2048); + CPU_REMCLOCK -= rsize; + if (file_read(fh, buf, rsize) != rsize) { + return(0xd0); + } + buf += rsize; + size -= rsize; + pos++; + } + return(0x00); +} + + +// イメージファイル内セクタ長混在用 +// 非RAW(2048byte)+Audio(2352byte)等 +REG8 sec_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { + + CDINFO cdinfo; + FILEH fh; + FILEPOS fpos; + UINT rsize; + UINT i; + UINT32 secs; + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(0x40); + } + + cdinfo = (CDINFO)sxsi->hdl; + fh = cdinfo->fh; + + while (size) { + fpos = 0; + secs = 0; + for (i = 0; i < cdinfo->trks; i++) { + if (cdinfo->trk[i].str_sec <= (UINT32)pos && (UINT32)pos <= cdinfo->trk[i].end_sec) { + fpos += (pos - secs) * cdinfo->trk[i].sector_size; + if (cdinfo->trk[i].sector_size != 2048) { + fpos += 16; + } + break; + } + fpos += cdinfo->trk[i].sectors * cdinfo->trk[i].sector_size; + secs += cdinfo->trk[i].sectors; + } + fpos += (FILEPOS)cdinfo->trk[0].start_offset; + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + return(0xd0); + } + rsize = MIN(size, 2048); + CPU_REMCLOCK -= rsize; + if (file_read(fh, buf, rsize) != rsize) { + return(0xd0); + } + buf += rsize; + size -= rsize; + pos++; + } + return(0x00); +} + +// ---- +BRESULT cd_reopen(SXSIDEV sxsi) { + + CDINFO cdinfo; + FILEH fh; + + cdinfo = (CDINFO)sxsi->hdl; + fh = file_open_rb(cdinfo->path); + if (fh != FILEH_INVALID) { + cdinfo->fh = fh; + return(SUCCESS); + } + else { + return(FAILURE); + } +} + +void cd_close(SXSIDEV sxsi) { + + CDINFO cdinfo; + + cdinfo = (CDINFO)sxsi->hdl; + file_close(cdinfo->fh); +} + +void cd_destroy(SXSIDEV sxsi) { + + if(sxsi->hdl){ + _MFREE((CDINFO)sxsi->hdl); + sxsi->hdl = (INTPTR)NULL; + } +} +// ---- + +void set_secread(SXSIDEV sxsi, const _CDTRK *trk, UINT trks) { + + UINT i; + UINT16 secsize; + + secsize = trk[0].sector_size; + for (i = 1; i < trks; i++) { + if (secsize != trk[i].sector_size) { + secsize = 0; + break; + } + } + if (secsize != 0) { + switch (secsize) { + case 2048: + sxsi->read = sec2048_read; + break; + case 2352: + sxsi->read = sec2352_read_with_ecc; // sec2352_read; + break; + case 2448: + sxsi->read = sec2448_read; + break; + } + } + else { + sxsi->read = sec_read; + } +} + +// +//#define TOCLOGOUT +#ifdef TOCLOGOUT +#define TOCLOG(fmt, val) \ + _stprintf(logbuf, fmt, val); \ + textfile_write(tfh, logbuf); +static const OEMCHAR str_logB[] = OEMTEXT("._CDTRK.Before.log"); +static const OEMCHAR str_logA[] = OEMTEXT("._CDTRK.After.log"); +#endif +// + +// イメージファイルの実体を開き、各種情報構築 +BRESULT setsxsidev(SXSIDEV sxsi, const OEMCHAR *path, const _CDTRK *trk, UINT trks) { + + FILEH fh; + long totals; + CDINFO cdinfo; + UINT mediatype; + UINT i; +#ifdef TOCLOGOUT + OEMCHAR logpath[MAX_PATH]; + OEMCHAR logbuf[2048]; + TEXTFILEH tfh; +#endif + + makeCRCTable(); + + // trk、trksは有効な値が設定済みなのが前提 + if ((trk == NULL) || (trks == 0)) { + goto sxsiope_err1; + } + + fh = file_open_rb(path); + if (fh == FILEH_INVALID) { + goto sxsiope_err1; + } + + cdinfo = (CDINFO)_MALLOC(sizeof(_CDINFO), path); + if (cdinfo == NULL) { + goto sxsiope_err2; + } + ZeroMemory(cdinfo, sizeof(_CDINFO)); + cdinfo->fh = fh; + trks = MIN(trks, NELEMENTS(cdinfo->trk) - 1); + CopyMemory(cdinfo->trk, trk, trks * sizeof(_CDTRK)); + +#ifdef TOCLOGOUT + file_cpyname(logpath, path, NELEMENTS(logpath)); + file_cutext(logpath); + file_catname(logpath, str_logB, NELEMENTS(logpath)); + + tfh = textfile_create(logpath, 0x800); + if (tfh == NULL) { + return(FAILURE); + } + + TOCLOG(OEMTEXT("STR _CDTRK LOG\r\n"), 0); + for (i = 0; i < trks; i++) { + TOCLOG(OEMTEXT("trk[%02d]\r\n"), i); + TOCLOG(OEMTEXT(" adr_ctl = 0x%02X\r\n"), cdinfo->trk[i].adr_ctl); + TOCLOG(OEMTEXT(" point = %02d\r\n"), cdinfo->trk[i].point); + TOCLOG(OEMTEXT(" [pos0][pos][ ] = [%18I32d]"), cdinfo->trk[i].pos0); + TOCLOG(OEMTEXT("[%18I32d][ ]\r\n"), cdinfo->trk[i].pos); + TOCLOG(OEMTEXT(" sec[ ][str][end] = [ ][%18I32d]"), cdinfo->trk[i].str_sec); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sec); + TOCLOG(OEMTEXT(" sectors = %I32d\r\n"), cdinfo->trk[i].sectors); + TOCLOG(OEMTEXT(" sector_size = %d\r\n"), cdinfo->trk[i].sector_size); + TOCLOG(OEMTEXT(" sector [pregap][start][end] = [%18I32d]"), cdinfo->trk[i].pregap_sector); + TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].start_sector); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sector); + TOCLOG(OEMTEXT(" img_sec[pregap][start][end] = [%18I32d]"), cdinfo->trk[i].img_pregap_sec); + TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].img_start_sec); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].img_end_sec); + TOCLOG(OEMTEXT(" offset [pregap][start][end] = [0x%016I64X]"), cdinfo->trk[i].pregap_offset); + TOCLOG(OEMTEXT("[0x%016I64X]"), cdinfo->trk[i].start_offset); + TOCLOG(OEMTEXT("[0x%016I64X]\r\n"), cdinfo->trk[i].end_offset); + TOCLOG(OEMTEXT(" pregap_sectors = %I32d\r\n"), cdinfo->trk[i].pregap_sectors); + TOCLOG(OEMTEXT(" track_sectors = %I32d\r\n"), cdinfo->trk[i].track_sectors); + } + TOCLOG(OEMTEXT("END _CDTRK LOG\r\n"), 0); + + textfile_close(tfh); +#endif + +#if 1 + if (sxsi->totals == -1) { + totals = set_trkinfo(fh, cdinfo->trk, trks, 0); + if (totals < 0) { + goto sxsiope_err3; + } + sxsi->totals = totals; + } +#else + totals = issec(fh, cdinfo->trk, trks); // とりあえず + sxsi->read = sec2048_read; + totals = issec2048(cdinfo->fh); + if (totals < 0) { + sxsi->read = sec2352_read; + totals = issec2352(cdinfo->fh); + } + if (totals < 0) { + sxsi->read = sec2448_read; + totals = issec2448(cdinfo->fh); + } + if (totals < 0) { + sxsi->read = sec_read; + totals = issec(cdinfo->fh, cdinfo->trk, trks); + } + if (totals < 0) { + goto sxsiope_err3; + } +#endif + + mediatype = 0; + for (i = 0; i < trks; i++) { + if (cdinfo->trk[i].adr_ctl == TRACKTYPE_DATA) { + mediatype |= SXSIMEDIA_DATA; + } + else if (cdinfo->trk[i].adr_ctl == TRACKTYPE_AUDIO) { + mediatype |= SXSIMEDIA_AUDIO; + } + } + + // リードアウトトラックを生成 + cdinfo->trk[trks].adr_ctl = 0x10; + cdinfo->trk[trks].point = 0xaa; +// cdinfo->trk[trks].pos = totals; + cdinfo->trk[trks].pos = (UINT32)sxsi->totals; + + cdinfo->trks = trks; + file_cpyname(cdinfo->path, path, NELEMENTS(cdinfo->path)); + + sxsi->reopen = cd_reopen; + sxsi->close = cd_close; + sxsi->destroy = cd_destroy; + sxsi->hdl = (INTPTR)cdinfo; +// sxsi->totals = totals; + sxsi->cylinders = (sxsi->totals + 17 * 8 - 1) / (17 * 8); + sxsi->size = 2048; + sxsi->sectors = 8; + sxsi->surfaces = 17; + sxsi->headersize = 0; + sxsi->mediatype = mediatype; + +#ifdef TOCLOGOUT + file_cpyname(logpath, path, NELEMENTS(logpath)); + file_cutext(logpath); + file_catname(logpath, str_logA, NELEMENTS(logpath)); + + tfh = textfile_create(logpath, 0x800); + if (tfh == NULL) { + return(FAILURE); + } + + TOCLOG(OEMTEXT("STR _CDTRK LOG\r\n"), 0); + for (i = 0; i < trks; i++) { + TOCLOG(OEMTEXT("trk[%02d]\r\n"), i); + TOCLOG(OEMTEXT(" adr_ctl = 0x%02X\r\n"), cdinfo->trk[i].adr_ctl); + TOCLOG(OEMTEXT(" point = %02d\r\n"), cdinfo->trk[i].point); + TOCLOG(OEMTEXT(" [pos0][pos][ ] = [%18I32d]"), cdinfo->trk[i].pos0); + TOCLOG(OEMTEXT("[%18I32d][ ]\r\n"), cdinfo->trk[i].pos); + TOCLOG(OEMTEXT(" sec[ ][str][end] = [ ][%18I32d]"), cdinfo->trk[i].str_sec); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sec); + TOCLOG(OEMTEXT(" sectors = %I32d\r\n"), cdinfo->trk[i].sectors); + TOCLOG(OEMTEXT(" sector_size = %d\r\n"), cdinfo->trk[i].sector_size); + TOCLOG(OEMTEXT(" sector [pregap][start][end] = [%18I32d]"), cdinfo->trk[i].pregap_sector); + TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].start_sector); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].end_sector); + TOCLOG(OEMTEXT(" img_sec[pregap][start][end] = [%18I32d]"), cdinfo->trk[i].img_pregap_sec); + TOCLOG(OEMTEXT("[%18I32d]"), cdinfo->trk[i].img_start_sec); + TOCLOG(OEMTEXT("[%18I32d]\r\n"), cdinfo->trk[i].img_end_sec); + TOCLOG(OEMTEXT(" offset [pregap][start][end] = [0x%016I64X]"), cdinfo->trk[i].pregap_offset); + TOCLOG(OEMTEXT("[0x%016I64X]"), cdinfo->trk[i].start_offset); + TOCLOG(OEMTEXT("[0x%016I64X]\r\n"), cdinfo->trk[i].end_offset); + TOCLOG(OEMTEXT(" pregap_sectors = %I32d\r\n"), cdinfo->trk[i].pregap_sectors); + TOCLOG(OEMTEXT(" track_sectors = %I32d\r\n"), cdinfo->trk[i].track_sectors); + } + TOCLOG(OEMTEXT("END _CDTRK LOG\r\n"), 0); + + textfile_close(tfh); +#endif + + return(SUCCESS); + +sxsiope_err3: + _MFREE(cdinfo); + +sxsiope_err2: + file_close(fh); + +sxsiope_err1: + return(FAILURE); +} + +#endif diff --git a/diskimage/cddfile.h b/diskimage/cddfile.h old mode 100755 new mode 100644 index 22865a60..ff5ae26a --- a/diskimage/cddfile.h +++ b/diskimage/cddfile.h @@ -1,43 +1,43 @@ -#ifdef __cplusplus -extern "C" { -#endif - -extern const OEMCHAR str_cue[]; -extern const OEMCHAR str_ccd[]; -extern const OEMCHAR str_cdm[]; -extern const OEMCHAR str_mds[]; -extern const OEMCHAR str_nrg[]; -extern const OEMCHAR str_iso[]; - -typedef struct { - FILEH fh; - UINT trks; - _CDTRK trk[100]; - OEMCHAR path[MAX_PATH]; -} _CDINFO, *CDINFO; - -BOOL isCDImage(const OEMCHAR *fname); // 追加(kaiA) -long issec2048(FILEH fh); -long issec2352(FILEH fh); -long issec2448(FILEH fh); -long issec(FILEH fh, _CDTRK *trk, UINT trks); - -long set_trkinfo(FILEH fh, _CDTRK *trk, UINT trks, FILELEN imagesize); - -REG8 sec2048_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); -REG8 sec2352_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); -REG8 sec2352_read_with_ecc(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); -REG8 sec2448_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); -REG8 sec_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); - -BRESULT cd_reopen(SXSIDEV sxsi); -void cd_close(SXSIDEV sxsi); -void cd_destroy(SXSIDEV sxsi); - -void set_secread(SXSIDEV sxsi, const _CDTRK *trk, UINT trks); - -BRESULT setsxsidev(SXSIDEV sxsi, const OEMCHAR *path, const _CDTRK *trk, UINT trks); - -#ifdef __cplusplus -} -#endif +#ifdef __cplusplus +extern "C" { +#endif + +extern const OEMCHAR str_cue[]; +extern const OEMCHAR str_ccd[]; +extern const OEMCHAR str_cdm[]; +extern const OEMCHAR str_mds[]; +extern const OEMCHAR str_nrg[]; +extern const OEMCHAR str_iso[]; + +typedef struct { + FILEH fh; + UINT trks; + _CDTRK trk[100]; + OEMCHAR path[MAX_PATH]; +} _CDINFO, *CDINFO; + +BOOL isCDImage(const OEMCHAR *fname); // 追加(kaiA) +long issec2048(FILEH fh); +long issec2352(FILEH fh); +long issec2448(FILEH fh); +long issec(FILEH fh, _CDTRK *trk, UINT trks); + +long set_trkinfo(FILEH fh, _CDTRK *trk, UINT trks, FILELEN imagesize); + +REG8 sec2048_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); +REG8 sec2352_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); +REG8 sec2352_read_with_ecc(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); +REG8 sec2448_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); +REG8 sec_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); + +BRESULT cd_reopen(SXSIDEV sxsi); +void cd_close(SXSIDEV sxsi); +void cd_destroy(SXSIDEV sxsi); + +void set_secread(SXSIDEV sxsi, const _CDTRK *trk, UINT trks); + +BRESULT setsxsidev(SXSIDEV sxsi, const OEMCHAR *path, const _CDTRK *trk, UINT trks); + +#ifdef __cplusplus +} +#endif diff --git a/diskimage/fd/fdd_bkdsk.c b/diskimage/fd/fdd_bkdsk.c old mode 100755 new mode 100644 index 1fef92f3..127eb65c --- a/diskimage/fd/fdd_bkdsk.c +++ b/diskimage/fd/fdd_bkdsk.c @@ -1,95 +1,95 @@ -// BKDSK用…なんだけど実質HDB専用 - -#include -#include -#include -#include - -#ifdef SUPPORT_KAI_IMAGES - -#include -#include "diskimage/fd/fdd_xdf.h" -#include "diskimage/fd/fdd_dcp.h" -#include "diskimage/fd/fdd_bkdsk.h" - -static const _XDFINFO supportbkdsk[] = { - {0, 154, 26, 1, DISKTYPE_2HD, 0}, // BKDSK(HDB) BASIC 2HD -}; - -BRESULT fdd_set_bkdsk(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { - -const _XDFINFO *xdf; - short attr; - FILEH fh; - UINT32 fdsize; - UINT size; - UINT tracksize; - UINT32 trackptr; - UINT i; - - attr = file_attr(fname); - if (attr & 0x18) { - return(FAILURE); - } - if(!ro) { - if(attr & FILEATTR_READONLY) { - ro = 1; - } - } - if(ro) { - fh = file_open_rb(fname); - } else { - fh = file_open(fname); - } - if (fh == FILEH_INVALID) { - return(FAILURE); - } - fdsize = (UINT32)file_getsize(fh); - file_close(fh); - - // イメージファイルサイズチェック -// {0, 154, 26, 1, DISKTYPE_2HD, 0}, // BKDSK(HDB) BASIC 2HD - xdf = supportbkdsk; - size = xdf->tracks; - size *= xdf->sectors; - size -= (xdf->sectors / 2); - size <<= (7 + xdf->n); - - size += xdf->headersize; - if (size != fdsize) { - return(FAILURE); - } - - fdd->type = DISKTYPE_BETA; - fdd->protect = ((attr & 0x01) || (ro)) ? TRUE : FALSE; - fdd->inf.xdf = *xdf; - - // ディスクアクセス時用に各トラックのオフセットを算出 - tracksize = fdd->inf.xdf.sectors * (128 << fdd->inf.xdf.n); - // track 0用 - fdd->inf.bkdsk.ptr[0] = 0; - trackptr = tracksize / 2; - // - for(i = 1; i < fdd->inf.xdf.tracks; i++) { - fdd->inf.bkdsk.ptr[i] = trackptr; - trackptr += tracksize; - } - - // 処理関数群を登録 - // ※read、writeはdcp系、それ以外は構造体の小細工でxdf系と共用 - fdd_fn->eject = fdd_eject_xxx; - fdd_fn->diskaccess = fdd_diskaccess_common; - fdd_fn->seek = fdd_seek_common; - fdd_fn->seeksector = fdd_seeksector_common; - fdd_fn->read = fdd_read_dcp; - fdd_fn->write = fdd_write_dcp; - fdd_fn->readid = fdd_readid_common; - fdd_fn->writeid = fdd_dummy_xxx; - fdd_fn->formatinit = fdd_dummy_xxx; - fdd_fn->formating = fdd_formating_xxx; - fdd_fn->isformating = fdd_isformating_xxx; - - return(SUCCESS); -} - -#endif +// BKDSK用…なんだけど実質HDB専用 + +#include +#include +#include +#include + +#ifdef SUPPORT_KAI_IMAGES + +#include +#include "diskimage/fd/fdd_xdf.h" +#include "diskimage/fd/fdd_dcp.h" +#include "diskimage/fd/fdd_bkdsk.h" + +static const _XDFINFO supportbkdsk[] = { + {0, 154, 26, 1, DISKTYPE_2HD, 0}, // BKDSK(HDB) BASIC 2HD +}; + +BRESULT fdd_set_bkdsk(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { + +const _XDFINFO *xdf; + short attr; + FILEH fh; + UINT32 fdsize; + UINT size; + UINT tracksize; + UINT32 trackptr; + UINT i; + + attr = file_attr(fname); + if (attr & 0x18) { + return(FAILURE); + } + if(!ro) { + if(attr & FILEATTR_READONLY) { + ro = 1; + } + } + if(ro) { + fh = file_open_rb(fname); + } else { + fh = file_open(fname); + } + if (fh == FILEH_INVALID) { + return(FAILURE); + } + fdsize = (UINT32)file_getsize(fh); + file_close(fh); + + // イメージファイルサイズチェック +// {0, 154, 26, 1, DISKTYPE_2HD, 0}, // BKDSK(HDB) BASIC 2HD + xdf = supportbkdsk; + size = xdf->tracks; + size *= xdf->sectors; + size -= (xdf->sectors / 2); + size <<= (7 + xdf->n); + + size += xdf->headersize; + if (size != fdsize) { + return(FAILURE); + } + + fdd->type = DISKTYPE_BETA; + fdd->protect = ((attr & 0x01) || (ro)) ? TRUE : FALSE; + fdd->inf.xdf = *xdf; + + // ディスクアクセス時用に各トラックのオフセットを算出 + tracksize = fdd->inf.xdf.sectors * (128 << fdd->inf.xdf.n); + // track 0用 + fdd->inf.bkdsk.ptr[0] = 0; + trackptr = tracksize / 2; + // + for(i = 1; i < fdd->inf.xdf.tracks; i++) { + fdd->inf.bkdsk.ptr[i] = trackptr; + trackptr += tracksize; + } + + // 処理関数群を登録 + // ※read、writeはdcp系、それ以外は構造体の小細工でxdf系と共用 + fdd_fn->eject = fdd_eject_xxx; + fdd_fn->diskaccess = fdd_diskaccess_common; + fdd_fn->seek = fdd_seek_common; + fdd_fn->seeksector = fdd_seeksector_common; + fdd_fn->read = fdd_read_dcp; + fdd_fn->write = fdd_write_dcp; + fdd_fn->readid = fdd_readid_common; + fdd_fn->writeid = fdd_dummy_xxx; + fdd_fn->formatinit = fdd_dummy_xxx; + fdd_fn->formating = fdd_formating_xxx; + fdd_fn->isformating = fdd_isformating_xxx; + + return(SUCCESS); +} + +#endif diff --git a/diskimage/fd/fdd_bkdsk.h b/diskimage/fd/fdd_bkdsk.h old mode 100755 new mode 100644 index 0c92d612..8596936f --- a/diskimage/fd/fdd_bkdsk.h +++ b/diskimage/fd/fdd_bkdsk.h @@ -1,11 +1,11 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT fdd_set_bkdsk(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT fdd_set_bkdsk(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); + +#ifdef __cplusplus +} +#endif + diff --git a/diskimage/fd/fdd_d88.c b/diskimage/fd/fdd_d88.c old mode 100755 new mode 100644 index ef58a2e9..48102d4d --- a/diskimage/fd/fdd_d88.c +++ b/diskimage/fd/fdd_d88.c @@ -1,1416 +1,1416 @@ -#include -#include -#include -#include - -#include -#include "diskimage/fd/fdd_d88.h" - -#define D88BUFSIZE 0x6000 -#define D88TRACKMAX 10600 - - -#ifdef SUPPORT_KAI_IMAGES - -static UINT32 nexttrackptr(FDDFILE fdd, UINT32 fptr, UINT32 last) { - - int t; - UINT32 cur; - - for (t=0; t<164; t++) { - cur = fdd->inf.d88.ptr[t]; - if ((cur > fptr) && (cur < last)) { - last = cur; - } - } - return(last); -} - - -// ---- - -typedef struct { - FDDFILE fdd; - UINT track; - UINT type; - long fptr; - UINT size; - BOOL write; - UINT8 buf[D88BUFSIZE]; -} _D88TRK, *D88TRK; - -static _D88TRK d88trk; - - -static BRESULT d88trk_flushdata(D88TRK trk) { - - FDDFILE fdd; - FILEH fh; - - fdd = trk->fdd; - trk->fdd = NULL; - if ((fdd == NULL) || (trk->size == 0) || (!trk->write)) { - goto dtfd_exit; - } - if (fdd->protect) { - goto dtfd_exit; - } - fh = file_open(fdd->fname); - if (fh == FILEH_INVALID) { - goto dtfd_err1; - } - if ((file_seek(fh, trk->fptr, FSEEK_SET) != trk->fptr) || - (file_write(fh, trk->buf, trk->size) != trk->size)) { - goto dtfd_err2; - } - file_close(fh); - trk->write = FALSE; - -dtfd_exit: - return(SUCCESS); - -dtfd_err2: - file_close(fh); - -dtfd_err1: - return(FAILURE); -} - -static BRESULT d88trk_read(D88TRK trk, FDDFILE fdd, UINT track, UINT type) { - - UINT8 rpm; - FILEH fh; - UINT32 fptr; - UINT32 size; - - d88trk_flushdata(trk); - if (track >= 164) { - goto dtrd_err1; - } - - rpm = fdc.rpm[fdc.us]; - switch(fdd->inf.d88.fdtype_major) { - case DISKTYPE_2D: - TRACEOUT(("DISKTYPE_2D")); - if ((rpm) || (type != DISKTYPE_2DD) || (track & 2)) { - goto dtrd_err1; - } - track = ((track >> 1) & 0xfe) | (track & 1); - break; - - case DISKTYPE_2DD: - if ((rpm) || (type != DISKTYPE_2DD)) { - goto dtrd_err1; - } - break; - - case DISKTYPE_2HD: - if (CTRL_FDMEDIA != DISKTYPE_2HD) { - goto dtrd_err1; - } - if ((fdd->inf.d88.fdtype_minor == 0) && (rpm)) { - goto dtrd_err1; - } - break; - - default: - goto dtrd_err1; - } - - fptr = fdd->inf.d88.ptr[track]; - if (fptr == 0) { - goto dtrd_err1; - } - size = nexttrackptr(fdd, fptr, fdd->inf.d88.fd_size) - fptr; - if (size > D88BUFSIZE) { - size = D88BUFSIZE; - } - fh = file_open_rb(fdd->fname); - if (fh == FILEH_INVALID) { - goto dtrd_err1; - } - if ((file_seek(fh, (long)fptr, FSEEK_SET) != (long)fptr) || - (file_read(fh, trk->buf, size) != size)) { - goto dtrd_err2; - } - file_close(fh); - - trk->fdd = fdd; - trk->track = track; - trk->type = type; - trk->fptr = fptr; - trk->size = size; - trk->write = FALSE; - return(SUCCESS); - -dtrd_err2: - file_close(fh); - -dtrd_err1: - return(FAILURE); -} - - -static BRESULT rpmcheck(D88SEC sec) { - - FDDFILE fdd = fddfile + fdc.us; - UINT8 rpm; - - rpm = fdc.rpm[fdc.us]; - switch(fdd->inf.d88.fdtype_major) { - case DISKTYPE_2D: - case DISKTYPE_2DD: - if (rpm) { - return(FAILURE); - } - break; - - case DISKTYPE_2HD: - if (fdd->inf.d88.fdtype_minor == 0) { - if (rpm) { - return(FAILURE); - } - } - else { - if (sec->rpm_flg != rpm) { - return(FAILURE); - } - } - break; - - default: - return(FAILURE); - } - return(SUCCESS); -} - - -// ---- - -static void drvflush(FDDFILE fdd) { - - D88TRK trk; - - trk = &d88trk; - if (trk->fdd == fdd && !fdd->protect) { - d88trk_flushdata(trk); - trk->fdd = NULL; - } -} - -static BRESULT trkseek(FDDFILE fdd, UINT track) { - - D88TRK trk; - BRESULT r; - - trk = &d88trk; - if ((trk->fdd == fdd) && (trk->track == track) && - (trk->type == CTRL_FDMEDIA)) { - r = SUCCESS; - } - else { - r = d88trk_read(trk, fdd, track, CTRL_FDMEDIA); - } - return(r); -} - - -static D88SEC searchsector_d88(BOOL check) { // ver0.29 - - UINT8 *p; - UINT sec; - UINT pos = 0; - UINT nsize; - UINT sectors; - UINT secsize; - - if (fdc.N < 8) { - nsize = 128 << fdc.N; - } - else { - nsize = 128 << 8; - } - - p = d88trk.buf; - for (sec=0; sec<40; ) { - if ((pos + nsize + sizeof(_D88SEC)) > D88BUFSIZE) { - break; - } - - if ((((D88SEC)p)->c == fdc.C) && - (((D88SEC)p)->h == fdc.H) && - (((D88SEC)p)->r == fdc.R) && - (((D88SEC)p)->n == fdc.N) && - (!rpmcheck((D88SEC)p))) { - - // ver0.29 - if (check) { - if ((fdc.mf != 0xff) && - !((fdc.mf ^ (((D88SEC)p)->mfm_flg)) & 0x40)) { - break; - } - } - return((D88SEC)p); - } - sectors = LOADINTELWORD(((D88SEC)p)->sectors); - if (++sec >= sectors) { - break; - } - - secsize = LOADINTELWORD(((D88SEC)p)->size); - secsize += sizeof(_D88SEC); - pos += secsize; - p += secsize; - } - return(NULL); -} - - -// ---- - -//BRESULT fddd88_set(FDDFILE fdd, const OEMCHAR *fname, int ro) { -BRESULT fdd_set_d88(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { - - short attr; - FILEH fh; - UINT rsize; - int i; - -// fddd88_eject(fdd); // 削除(kai9) - attr = file_attr(fname); - if (attr & 0x18) { - goto fdst_err; - } - if(attr & FILEATTR_READONLY) { - ro = 1; - } - if(!ro) { - if(attr & FILEATTR_READONLY) { - ro = 1; - } - } - if(ro) { - fh = file_open_rb(fname); - } else { - fh = file_open(fname); - } - if (fh == FILEH_INVALID) { - goto fdst_err; - } - rsize = file_read(fh, &fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); - file_close(fh); - if (rsize != sizeof(fdd->inf.d88.head)) { - goto fdst_err; - } - fdd->type = DISKTYPE_D88; - fdd->protect = ((attr & 1) || (fdd->inf.d88.head.protect & 0x10) || - (ro))?TRUE:FALSE; - fdd->inf.d88.fdtype_major = fdd->inf.d88.head.fd_type >> 4; - fdd->inf.d88.fdtype_minor = fdd->inf.d88.head.fd_type & 0x0f; - fdd->inf.d88.fd_size = LOADINTELDWORD(fdd->inf.d88.head.fd_size); - for (i=0; i<164; i++) { - fdd->inf.d88.ptr[i] = LOADINTELDWORD(fdd->inf.d88.head.trackp[i]); - } - // 処理関数群を登録(kai9) - fdd_fn->eject = fdd_eject_d88; - fdd_fn->diskaccess = fdd_diskaccess_d88; - fdd_fn->seek = fdd_seek_d88; - fdd_fn->seeksector = fdd_seeksector_d88; - fdd_fn->read = fdd_read_d88; - fdd_fn->write = fdd_write_d88; - fdd_fn->readid = fdd_readid_d88; - fdd_fn->writeid = fdd_dummy_xxx; - fdd_fn->formatinit = fdd_formatinit_d88; - fdd_fn->formating = fdd_formating_d88; - fdd_fn->isformating = fdd_isformating_d88; - // - return(SUCCESS); - -fdst_err: - return(FAILURE); -} - -//BRESULT fddd88_eject(FDDFILE fdd) { -BRESULT fdd_eject_d88(FDDFILE fdd) { - - drvflush(fdd); -// 共通関数部へ移動(kai9) -// fdd->fname[0] = '\0'; -// fdd->type = DISKTYPE_NOTREADY; -// ZeroMemory(&fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); - return(SUCCESS); -} - - -//BRESULT fdd_diskaccess_d88(void) { // ver0.31 -BRESULT fdd_diskaccess_d88(FDDFILE fdd) { - -// FDDFILE fdd = fddfile + fdc.us; - UINT8 rpm; - - rpm = fdc.rpm[fdc.us]; - switch(fdd->inf.d88.fdtype_major) { - case DISKTYPE_2D: - case DISKTYPE_2DD: - if ((rpm) || (CTRL_FDMEDIA != DISKTYPE_2DD)) { - return(FAILURE); - } - break; - - case DISKTYPE_2HD: - if (CTRL_FDMEDIA != DISKTYPE_2HD) { - return(FAILURE); - } - if ((fdd->inf.d88.fdtype_minor == 0) && (rpm)) { - return(FAILURE); - } - break; - - default: - return(FAILURE); - - } - return(SUCCESS); -} - -//BRESULT fdd_seek_d88(void) { -BRESULT fdd_seek_d88(FDDFILE fdd) { - -// FDDFILE fdd = fddfile + fdc.us; -TRACEOUT(("D88 seek trkseek[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); - return(trkseek(fdd, (fdc.ncn << 1) + fdc.hd)); -} - -//BRESULT fdd_seeksector_d88(void) { -BRESULT fdd_seeksector_d88(FDDFILE fdd) { - -// FDDFILE fdd = fddfile + fdc.us; - -TRACEOUT(("D88 seeksector trkseek[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); - if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { -TRACEOUT(("D88 seeksector FAILURE trkseek[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); - return(FAILURE); - } - if (!searchsector_d88(FALSE)) { -TRACEOUT(("D88 seeksector FAILURE searchsector[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); - return(FAILURE); - } - return(SUCCESS); -} - -//BRESULT fdd_read_d88(void) { -BRESULT fdd_read_d88(FDDFILE fdd) { - -// FDDFILE fdd = fddfile + fdc.us; - D88SEC p; - UINT size; - UINT secsize; - -TRACEOUT(("D88 read trkseek[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); - fddlasterror = 0x00; - if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { -TRACEOUT(("D88 read FAILURE trkseek[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); - fddlasterror = 0xe0; - return(FAILURE); - } - p = searchsector_d88(TRUE); - if (!p) { -TRACEOUT(("D88 read FAILURE searchsector_d88[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); - fddlasterror = 0xc0; - return(FAILURE); - } - if (fdc.N < 8) { - size = 128 << fdc.N; - } - else { - size = 128 << 8; - } - fdc.bufcnt = size; - ZeroMemory(fdc.buf, size); - secsize = LOADINTELWORD(p->size); - if (size > secsize) { - size = secsize; - } - if (size) { - CopyMemory(fdc.buf, p+1, size); - } - fddlasterror = p->stat; -TRACEOUT(("D88 read FDC Result Status[%02x]", p->stat)); -TRACEOUT(("D88 read C:%02x,H:%02x,R:%02x,N:%02x", fdc.C, fdc.H, fdc.R, fdc.N)); -TRACEOUT(("D88 read dump")); -TRACEOUT(("\t%02x %02x %02x %02x %02x %02x %02x %02x", - fdc.buf[0x00], fdc.buf[0x01], fdc.buf[0x02], fdc.buf[0x03], fdc.buf[0x04], fdc.buf[0x05], fdc.buf[0x06], fdc.buf[0x07])); - return(SUCCESS); -} - -//BRESULT fdd_write_d88(void) { -BRESULT fdd_write_d88(FDDFILE fdd) { - -// FDDFILE fdd = fddfile + fdc.us; - D88SEC p; - UINT size; - UINT secsize; - - if (fdd->protect) { - return(FAILURE); - } - - fddlasterror = 0x00; - if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { - fddlasterror = 0xe0; - return(FAILURE); - } - p = searchsector_d88(FALSE); - if (!p) { - fddlasterror = 0xc0; - return(FAILURE); - } - if (fdc.N < 8) { - size = 128 << fdc.N; - } - else { - size = 128 << 8; - } - secsize = LOADINTELWORD(p->size); - if (size > secsize) { - size = secsize; - } - if (size) { - CopyMemory(p+1, fdc.buf, size); - d88trk.write = TRUE; - } - fddlasterror = 0x00; - return(SUCCESS); -} - -//BRESULT fdd_readid_d88(void) { -BRESULT fdd_readid_d88(FDDFILE fdd) { - -// FDDFILE fdd = fddfile + fdc.us; - UINT8 *p; - UINT sec; - UINT pos = 0; - UINT sectors; - UINT secsize; - - fddlasterror = 0x00; - if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { - fddlasterror = 0xe0; - return(FAILURE); - } - p = d88trk.buf; - for (sec=0; sec<40; ) { - if (pos > (D88BUFSIZE - sizeof(_D88SEC))) { - break; - } - sectors = LOADINTELWORD(((D88SEC)p)->sectors); - if ((sec == fdc.crcn) && (!rpmcheck((D88SEC)p))) { // ver0.31 - /* 170101 ST modified to work on Windows 9x/2000 form ... */ - if (++fdc.crcn >= sectors) { - fdc.crcn = 0; - /* np21w rev36 removed */ - //if(fdc.mt) { - // fdc.hd ^= 1; - // if (fdc.hd == 0) { - // fdc.treg[fdc.us]++; - // } - //} - //else { - // fdc.treg[fdc.us]++; - //} - } - fdc.C = fdc.treg[fdc.us]; - fdc.H = fdc.hd; - fdc.R = ((D88SEC)p)->r; - fdc.N = ((D88SEC)p)->n; - //fdc.crcn++; - //if (fdc.crcn >= sectors) { - // fdc.crcn = 0; - //} - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - if ((fdc.mf == 0xff) || - ((fdc.mf ^ (((D88SEC)p)->mfm_flg)) & 0x40)) { - fddlasterror = 0x00; - return(SUCCESS); - } - } - if (++sec >= sectors) { - break; - } - secsize = LOADINTELWORD(((D88SEC)p)->size); - secsize += sizeof(_D88SEC); - pos += secsize; - p += secsize; - } - fdc.crcn = 0x00; - fddlasterror = 0xe0; // ver0.31 - return(FAILURE); -} - - -// -------------------------------------------------------------------------- - -// えーと…こんなところにあって大丈夫? -static BOOL formating = FALSE; -static UINT8 formatsec = 0; -static UINT8 formatwrt = 0; -static UINT formatpos = 0; - -static int fileappend(FILEH hdl, FDDFILE fdd, - UINT32 ptr, long last, long apsize) { - - long length; - UINT size; - UINT rsize; - int t; - UINT8 tmp[0x400]; // Stack 0x1000->0x400 - UINT32 cur; - - if (fdd->protect) { - return(0); - } - - if ((length = last - ptr) <= 0) { // 書き換える必要なし - return(0); - } - while(length) { - if (length >= (long)(sizeof(tmp))) { - size = sizeof(tmp); - } - else { - size = length; - } - length -= size; - file_seek(hdl, (FILEPOS)ptr + length, 0); - rsize = file_read(hdl, tmp, size); - file_seek(hdl, (FILEPOS)ptr + length + apsize, 0); - file_write(hdl, tmp, rsize); - } - - for (t=0; t<164; t++) { - cur = fdd->inf.d88.ptr[t]; - if ((cur != 0) && (cur >= ptr)) { - cur += apsize; - fdd->inf.d88.ptr[t] = cur; - STOREINTELDWORD(fdd->inf.d88.head.trackp[t], cur); - } - } - return(0); -} - - -static void endoftrack(UINT fmtsize, UINT8 sectors) { - - FDDFILE fdd = fddfile + fdc.us; - - D88SEC d88sec; - FILEH hdl; - int i; - UINT trk; - long fpointer; - long endpointer; - long lastpointer; - long trksize; - int ptr; - long apsize; - - if (fdd->protect) { - return; - } - - trk = (fdc.treg[fdc.us] << 1) + fdc.hd; - - ptr = 0; - for (i=0; i<(int)sectors; i++) { - d88sec = (D88SEC)(d88trk.buf + ptr); - STOREINTELWORD(d88sec->sectors, sectors); - ptr += LOADINTELWORD(d88sec->size); - ptr += sizeof(_D88SEC); - } - - hdl = file_open(fddfile[fdc.us].fname); - if (hdl == FILEH_INVALID) { - return; - } - lastpointer = (long)file_getsize(hdl); /* lastpointer = file_seek(hdl, 0, FSEEK_END); */ - fpointer = fdd->inf.d88.ptr[trk]; - if (fpointer == 0) { - for (i=trk; i>=0; i--) { // 新規トラック - fpointer = fdd->inf.d88.ptr[i]; - if (fpointer) { - break; - } - } - if (fpointer) { // ヒットした - fpointer = nexttrackptr(fdd, fpointer, lastpointer); - } - else { - fpointer = sizeof(_D88HEAD); - } - endpointer = fpointer; - } - else { // トラックデータは既にある - endpointer = nexttrackptr(fdd, fpointer, lastpointer); - } - trksize = endpointer - fpointer; - if ((apsize = (long)fmtsize - trksize) > 0) { - // 書き込むデータのほーが大きい - fileappend(hdl, fdd, endpointer, lastpointer, apsize); - fdd->inf.d88.fd_size += apsize; - STOREINTELDWORD(fdd->inf.d88.head.fd_size, fdd->inf.d88.fd_size); - } - if (trk >= D88_TRACKMAX) { - file_close(hdl); - return; - } - fdd->inf.d88.ptr[trk] = fpointer; - STOREINTELDWORD(fdd->inf.d88.head.trackp[trk], fpointer); - file_seek(hdl, fpointer, 0); - file_write(hdl, d88trk.buf, fmtsize); - file_seek(hdl, 0, FSEEK_SET); - file_write(hdl, &fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); - file_close(hdl); -// TRACEOUT(("fmt %d %d", fpointer, fmtsize)); -} - - -//BRESULT fdd_formatinit_d88(void) { -BRESULT fdd_formatinit_d88(FDDFILE fdd) { - - if (fdc.treg[fdc.us] < 82) { - formating = TRUE; - formatsec = 0; - formatpos = 0; - formatwrt = 0; - drvflush(fddfile + fdc.us); - return(SUCCESS); - } - return(FAILURE); -} - - // todo アンフォーマットとか ディスク1周した時の切り捨てとか… -//BRESULT fdd_formating_d88(const UINT8 *ID) { -BRESULT fdd_formating_d88(FDDFILE fdd, const UINT8 *ID) { - -// FDDFILE fdd = fddfile + fdc.us; - - UINT size; - D88SEC d88sec; - - if (!formating) { - return(FAILURE); - } - if (fdc.N < 8) { - size = 128 << fdc.N; - } - else { - size = 128 << 8; - } - if ((formatpos + sizeof(_D88SEC) + size) < D88TRACKMAX) { - d88sec = (D88SEC)(d88trk.buf + formatpos); - ZeroMemory(d88sec, sizeof(_D88SEC)); - d88sec->c = ID[0]; - d88sec->h = ID[1]; - d88sec->r = ID[2]; - d88sec->n = ID[3]; - STOREINTELWORD(d88sec->size, size); - if ((fdd->inf.d88.fdtype_major == DISKTYPE_2HD) && - (fdd->inf.d88.fdtype_minor != 0)) { - d88sec->rpm_flg = fdc.rpm[fdc.us]; - } - FillMemory(d88sec + 1, size, fdc.d); - formatpos += sizeof(_D88SEC); - formatpos += size; - formatwrt++; - } - formatsec++; -// TRACE_("format sec", formatsec); -// TRACE_("format wrt", formatwrt); -// TRACE_("format max", fdc.sc); -// TRACE_("format pos", formatpos); - if (formatsec >= fdc.sc) { - endoftrack(formatpos, formatwrt); - formating = FALSE; - } - return(SUCCESS); -} - -//BOOL fdd_isformating_d88(void) { -BOOL fdd_isformating_d88(FDDFILE fdd) { - - return(formating); -} -#else - -static UINT nexttrackptr(FDDFILE fdd, UINT fptr, UINT last) { - - int t; - UINT cur; - - for (t=0; t<164; t++) { - cur = fdd->inf.d88.ptr[t]; - if ((cur > fptr) && (cur < last)) { - last = cur; - } - } - return(last); -} - - -// ---- - -typedef struct { - FDDFILE fdd; - UINT track; - UINT type; - long fptr; - UINT size; - BOOL write; - UINT8 buf[D88BUFSIZE]; -} _D88TRK, *D88TRK; - -static _D88TRK d88trk; - - -static BRESULT d88trk_flushdata(D88TRK trk) { - - FDDFILE fdd; - FILEH fh; - - fdd = trk->fdd; - trk->fdd = NULL; - if ((fdd == NULL) || (trk->size == 0) || (!trk->write)) { - goto dtfd_exit; - } - if (fdd->protect) { - goto dtfd_exit; - } - fh = file_open(fdd->fname); - if (fh == FILEH_INVALID) { - goto dtfd_err1; - } - if ((file_seek(fh, trk->fptr, FSEEK_SET) != trk->fptr) || - (file_write(fh, trk->buf, trk->size) != trk->size)) { - goto dtfd_err2; - } - file_close(fh); - trk->write = FALSE; - -dtfd_exit: - return(SUCCESS); - -dtfd_err2: - file_close(fh); - -dtfd_err1: - return(FAILURE); -} - -static BRESULT d88trk_read(D88TRK trk, FDDFILE fdd, UINT track, UINT type) { - - UINT8 rpm; - FILEH fh; - UINT fptr; - UINT size; - - d88trk_flushdata(trk); - if (track >= 164) { - goto dtrd_err1; - } - - rpm = fdc.rpm[fdc.us]; - switch(fdd->inf.d88.fdtype_major) { - case DISKTYPE_2D: - TRACEOUT(("DISKTYPE_2D")); - if ((rpm) || (type != DISKTYPE_2DD) || (track & 2)) { - goto dtrd_err1; - } - track = ((track >> 1) & 0xfe) | (track & 1); - break; - - case DISKTYPE_2DD: - if ((rpm) || (type != DISKTYPE_2DD)) { - goto dtrd_err1; - } - break; - - case DISKTYPE_2HD: - if (CTRL_FDMEDIA != DISKTYPE_2HD) { - goto dtrd_err1; - } - if ((fdd->inf.d88.fdtype_minor == 0) && (rpm)) { - goto dtrd_err1; - } - break; - - default: - goto dtrd_err1; - } - - fptr = fdd->inf.d88.ptr[track]; - if (fptr == 0) { - goto dtrd_err1; - } - size = nexttrackptr(fdd, fptr, fdd->inf.d88.fd_size) - fptr; - if (size > D88BUFSIZE) { - size = D88BUFSIZE; - } - fh = file_open_rb(fdd->fname); - if (fh == FILEH_INVALID) { - goto dtrd_err1; - } - if ((file_seek(fh, (long)fptr, FSEEK_SET) != (long)fptr) || - (file_read(fh, trk->buf, size) != size)) { - goto dtrd_err2; - } - file_close(fh); - - trk->fdd = fdd; - trk->track = track; - trk->type = type; - trk->fptr = fptr; - trk->size = size; - trk->write = FALSE; - return(SUCCESS); - -dtrd_err2: - file_close(fh); - -dtrd_err1: - return(FAILURE); -} - - -static BRESULT rpmcheck(D88SEC sec) { - - FDDFILE fdd = fddfile + fdc.us; - UINT8 rpm; - - rpm = fdc.rpm[fdc.us]; - switch(fdd->inf.d88.fdtype_major) { - case DISKTYPE_2D: - case DISKTYPE_2DD: - if (rpm) { - return(FAILURE); - } - break; - - case DISKTYPE_2HD: - if (fdd->inf.d88.fdtype_minor == 0) { - if (rpm) { - return(FAILURE); - } - } - else { - if (sec->rpm_flg != rpm) { - return(FAILURE); - } - } - break; - - default: - return(FAILURE); - } - return(SUCCESS); -} - - -// ---- - -static void drvflush(FDDFILE fdd) { - - D88TRK trk; - - trk = &d88trk; - if (trk->fdd == fdd) { - d88trk_flushdata(trk); - trk->fdd = NULL; - } -} - -static BRESULT trkseek(FDDFILE fdd, UINT track) { - - D88TRK trk; - BRESULT r; - - trk = &d88trk; - if ((trk->fdd == fdd) && (trk->track == track) && - (trk->type == CTRL_FDMEDIA)) { - r = SUCCESS; - } - else { - r = d88trk_read(trk, fdd, track, CTRL_FDMEDIA); - } - return(r); -} - - -static D88SEC searchsector_d88(BOOL check) { // ver0.29 - - UINT8 *p; - UINT sec; - UINT pos = 0; - UINT nsize; - UINT sectors; - UINT secsize; - - if (fdc.N < 8) { - nsize = 128 << fdc.N; - } - else { - nsize = 128 << 8; - } - - p = d88trk.buf; - for (sec=0; sec<40; ) { - if ((pos + nsize + sizeof(_D88SEC)) > D88BUFSIZE) { - break; - } - - if ((((D88SEC)p)->c == fdc.C) && - (((D88SEC)p)->h == fdc.H) && - (((D88SEC)p)->r == fdc.R) && - (((D88SEC)p)->n == fdc.N) && - (!rpmcheck((D88SEC)p))) { - - // ver0.29 - if (check) { - if ((fdc.mf != 0xff) && - !((fdc.mf ^ (((D88SEC)p)->mfm_flg)) & 0x40)) { - break; - } - } - return((D88SEC)p); - } - sectors = LOADINTELWORD(((D88SEC)p)->sectors); - if (++sec >= sectors) { - break; - } - - secsize = LOADINTELWORD(((D88SEC)p)->size); - secsize += sizeof(_D88SEC); - pos += secsize; - p += secsize; - } - return(NULL); -} - - -// ---- - -BRESULT fddd88_set(FDDFILE fdd, const OEMCHAR *fname, int ro) { - - short attr; - FILEH fh; - UINT rsize; - int i; - - fddd88_eject(fdd); - attr = file_attr(fname); - if (attr & 0x18) { - goto fdst_err; - } - if(attr & FILEATTR_READONLY) { - ro = 1; - } - if(!ro) { - if(attr & FILEATTR_READONLY) { - ro = 1; - } - } - if(ro) { - fh = file_open_rb(fname); - } else { - fh = file_open(fname); - } - if (fh == FILEH_INVALID) { - goto fdst_err; - } - rsize = file_read(fh, &fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); - file_close(fh); - if (rsize != sizeof(fdd->inf.d88.head)) { - goto fdst_err; - } - fdd->type = DISKTYPE_D88; - fdd->protect = ((attr & 1) || (fdd->inf.d88.head.protect & 0x10) || - (ro))?TRUE:FALSE; - fdd->inf.d88.fdtype_major = fdd->inf.d88.head.fd_type >> 4; - fdd->inf.d88.fdtype_minor = fdd->inf.d88.head.fd_type & 0x0f; - fdd->inf.d88.fd_size = LOADINTELDWORD(fdd->inf.d88.head.fd_size); - for (i=0; i<164; i++) { - fdd->inf.d88.ptr[i] = LOADINTELDWORD(fdd->inf.d88.head.trackp[i]); - } - return(SUCCESS); - -fdst_err: - return(FAILURE); -} - -BRESULT fddd88_eject(FDDFILE fdd) { - - drvflush(fdd); - fdd->fname[0] = '\0'; - fdd->type = DISKTYPE_NOTREADY; - ZeroMemory(&fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); - return(SUCCESS); -} - - -BRESULT fdd_diskaccess_d88(void) { // ver0.31 - - FDDFILE fdd = fddfile + fdc.us; - UINT8 rpm; - - rpm = fdc.rpm[fdc.us]; - switch(fdd->inf.d88.fdtype_major) { - case DISKTYPE_2D: - case DISKTYPE_2DD: - if ((rpm) || (CTRL_FDMEDIA != DISKTYPE_2DD)) { - return(FAILURE); - } - break; - - case DISKTYPE_2HD: - if (CTRL_FDMEDIA != DISKTYPE_2HD) { - return(FAILURE); - } - if ((fdd->inf.d88.fdtype_minor == 0) && (rpm)) { - return(FAILURE); - } - break; - - default: - return(FAILURE); - - } - return(SUCCESS); -} - -BRESULT fdd_seek_d88(void) { - - FDDFILE fdd = fddfile + fdc.us; - - return(trkseek(fdd, (fdc.ncn << 1) + fdc.hd)); -} - -BRESULT fdd_seeksector_d88(void) { - - FDDFILE fdd = fddfile + fdc.us; - - if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { - return(FAILURE); - } - if (!searchsector_d88(FALSE)) { - return(FAILURE); - } - return(SUCCESS); -} - -BRESULT fdd_read_d88(void) { - - FDDFILE fdd = fddfile + fdc.us; - D88SEC p; - UINT size; - UINT secsize; - - fddlasterror = 0x00; - if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { - fddlasterror = 0xe0; - return(FAILURE); - } - p = searchsector_d88(TRUE); - if (!p) { - fddlasterror = 0xc0; - return(FAILURE); - } - if (fdc.N < 8) { - size = 128 << fdc.N; - } - else { - size = 128 << 8; - } - fdc.bufcnt = size; - ZeroMemory(fdc.buf, size); - secsize = LOADINTELWORD(p->size); - if (size > secsize) { - size = secsize; - } - if (size) { - CopyMemory(fdc.buf, p+1, size); - } - fddlasterror = p->stat; - return(SUCCESS); -} - -BRESULT fdd_write_d88(void) { - - FDDFILE fdd = fddfile + fdc.us; - D88SEC p; - UINT size; - UINT secsize; - - fddlasterror = 0x00; - if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { - fddlasterror = 0xe0; - return(FAILURE); - } - p = searchsector_d88(FALSE); - if (!p) { - fddlasterror = 0xc0; - return(FAILURE); - } - if (fdc.N < 8) { - size = 128 << fdc.N; - } - else { - size = 128 << 8; - } - secsize = LOADINTELWORD(p->size); - if (size > secsize) { - size = secsize; - } - if (size) { - CopyMemory(p+1, fdc.buf, size); - d88trk.write = TRUE; - } - fddlasterror = 0x00; - return(SUCCESS); -} - -BRESULT fdd_readid_d88(void) { - - FDDFILE fdd = fddfile + fdc.us; - UINT8 *p; - UINT sec; - UINT pos = 0; - UINT sectors; - UINT secsize; - - fddlasterror = 0x00; - if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { - fddlasterror = 0xe0; - return(FAILURE); - } - p = d88trk.buf; - for (sec=0; sec<40; ) { - if (pos > (D88BUFSIZE - sizeof(_D88SEC))) { - break; - } - sectors = LOADINTELWORD(((D88SEC)p)->sectors); - if ((sec == fdc.crcn) && (!rpmcheck((D88SEC)p))) { // ver0.31 - fdc.C = ((D88SEC)p)->c; - fdc.H = ((D88SEC)p)->h; - fdc.R = ((D88SEC)p)->r; - fdc.N = ((D88SEC)p)->n; - fdc.crcn++; - if (fdc.crcn >= sectors) { - fdc.crcn = 0; - } - if ((fdc.mf == 0xff) || - ((fdc.mf ^ (((D88SEC)p)->mfm_flg)) & 0x40)) { - fddlasterror = 0x00; - return(SUCCESS); - } - } - if (++sec >= sectors) { - break; - } - secsize = LOADINTELWORD(((D88SEC)p)->size); - secsize += sizeof(_D88SEC); - pos += secsize; - p += secsize; - } - fdc.crcn = 0x00; - fddlasterror = 0xe0; // ver0.31 - return(FAILURE); -} - - -// -------------------------------------------------------------------------- - -// えーと…こんなところにあって大丈夫? -static BOOL formating = FALSE; -static UINT8 formatsec = 0; -static UINT8 formatwrt = 0; -static UINT formatpos = 0; - -static int fileappend(FILEH hdl, FDDFILE fdd, UINT ptr, UINT last, int apsize) { - - int length; - UINT size; - UINT rsize; - int t; - UINT8 tmp[0x400]; // Stack 0x1000->0x400 - UINT cur; - - if (fdd->protect) { - return(0); - } - - if ((length = last - ptr) <= 0) { // 書き換える必要なし - return(0); - } - while(length) { - if (length >= sizeof(tmp)) { - size = sizeof(tmp); - } - else { - size = length; - } - length -= size; - file_seek(hdl, ptr + length, 0); - rsize = file_read(hdl, tmp, size); - file_seek(hdl, ptr + length + apsize, 0); - file_write(hdl, tmp, rsize); - } - - for (t=0; t<164; t++) { - cur = fdd->inf.d88.ptr[t]; - if ((cur != 0) && (cur >= ptr)) { - cur += apsize; - fdd->inf.d88.ptr[t] = cur; - STOREINTELDWORD(fdd->inf.d88.head.trackp[t], cur); - } - } - return(0); -} - - -static void endoftrack(UINT fmtsize, UINT8 sectors) { - - FDDFILE fdd = fddfile + fdc.us; - - D88SEC d88sec; - FILEH hdl; - int i; - UINT trk; - UINT fpointer; - UINT endpointer; - UINT lastpointer; - UINT trksize; - int ptr; - int apsize; - - if (fdd->protect) { - return; - } - - trk = (fdc.treg[fdc.us] << 1) + fdc.hd; - - ptr = 0; - for (i=0; i<(int)sectors; i++) { - d88sec = (D88SEC)(d88trk.buf + ptr); - STOREINTELWORD(d88sec->sectors, sectors); - ptr += LOADINTELWORD(d88sec->size); - ptr += sizeof(_D88SEC); - } - - hdl = file_open(fddfile[fdc.us].fname); - if (hdl == FILEH_INVALID) { - return; - } - lastpointer = file_getsize(hdl); - fpointer = fdd->inf.d88.ptr[trk]; - if (fpointer == 0) { - for (i=trk; i>=0; i--) { // 新規トラック - fpointer = fdd->inf.d88.ptr[i]; - if (fpointer) { - break; - } - } - if (fpointer) { // ヒットした - fpointer = nexttrackptr(fdd, fpointer, lastpointer); - } - else { - fpointer = sizeof(_D88HEAD); - } - endpointer = fpointer; - } - else { // トラックデータは既にある - endpointer = nexttrackptr(fdd, fpointer, lastpointer); - } - trksize = endpointer - fpointer; - if ((apsize = fmtsize - trksize) > 0) { - // 書き込むデータのほーが大きい - fileappend(hdl, fdd, endpointer, lastpointer, apsize); - fdd->inf.d88.fd_size += apsize; - STOREINTELDWORD(fdd->inf.d88.head.fd_size, fdd->inf.d88.fd_size); - } - fdd->inf.d88.ptr[trk] = fpointer; - STOREINTELDWORD(fdd->inf.d88.head.trackp[trk], fpointer); - file_seek(hdl, (long)fpointer, 0); - file_write(hdl, d88trk.buf, fmtsize); - file_seek(hdl, 0, FSEEK_SET); - file_write(hdl, &fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); - file_close(hdl); -// TRACEOUT(("fmt %d %d", fpointer, fmtsize)); -} - - -BRESULT fdd_formatinit_d88(void) { - - if (fdc.treg[fdc.us] < 82) { - formating = TRUE; - formatsec = 0; - formatpos = 0; - formatwrt = 0; - drvflush(fddfile + fdc.us); - return(SUCCESS); - } - return(FAILURE); -} - - // todo アンフォーマットとか ディスク1周した時の切り捨てとか… -BRESULT fdd_formating_d88(const UINT8 *ID) { - - FDDFILE fdd = fddfile + fdc.us; - - UINT size; - D88SEC d88sec; - - if (!formating) { - return(FAILURE); - } - if (fdc.N < 8) { - size = 128 << fdc.N; - } - else { - size = 128 << 8; - } - if ((formatpos + sizeof(_D88SEC) + size) < D88TRACKMAX) { - d88sec = (D88SEC)(d88trk.buf + formatpos); - ZeroMemory(d88sec, sizeof(_D88SEC)); - d88sec->c = ID[0]; - d88sec->h = ID[1]; - d88sec->r = ID[2]; - d88sec->n = ID[3]; - STOREINTELWORD(d88sec->size, size); - if ((fdd->inf.d88.fdtype_major == DISKTYPE_2HD) && - (fdd->inf.d88.fdtype_minor != 0)) { - d88sec->rpm_flg = fdc.rpm[fdc.us]; - } - FillMemory(d88sec + 1, size, fdc.d); - formatpos += sizeof(_D88SEC); - formatpos += size; - formatwrt++; - } - formatsec++; -// TRACE_("format sec", formatsec); -// TRACE_("format wrt", formatwrt); -// TRACE_("format max", fdc.sc); -// TRACE_("format pos", formatpos); - if (formatsec >= fdc.sc) { - endoftrack(formatpos, formatwrt); - formating = FALSE; - } - return(SUCCESS); -} - -BOOL fdd_isformating_d88(void) { - - return(formating); -} - - - -#endif +#include +#include +#include +#include + +#include +#include "diskimage/fd/fdd_d88.h" + +#define D88BUFSIZE 0x6000 +#define D88TRACKMAX 10600 + + +#ifdef SUPPORT_KAI_IMAGES + +static UINT32 nexttrackptr(FDDFILE fdd, UINT32 fptr, UINT32 last) { + + int t; + UINT32 cur; + + for (t=0; t<164; t++) { + cur = fdd->inf.d88.ptr[t]; + if ((cur > fptr) && (cur < last)) { + last = cur; + } + } + return(last); +} + + +// ---- + +typedef struct { + FDDFILE fdd; + UINT track; + UINT type; + long fptr; + UINT size; + BOOL write; + UINT8 buf[D88BUFSIZE]; +} _D88TRK, *D88TRK; + +static _D88TRK d88trk; + + +static BRESULT d88trk_flushdata(D88TRK trk) { + + FDDFILE fdd; + FILEH fh; + + fdd = trk->fdd; + trk->fdd = NULL; + if ((fdd == NULL) || (trk->size == 0) || (!trk->write)) { + goto dtfd_exit; + } + if (fdd->protect) { + goto dtfd_exit; + } + fh = file_open(fdd->fname); + if (fh == FILEH_INVALID) { + goto dtfd_err1; + } + if ((file_seek(fh, trk->fptr, FSEEK_SET) != trk->fptr) || + (file_write(fh, trk->buf, trk->size) != trk->size)) { + goto dtfd_err2; + } + file_close(fh); + trk->write = FALSE; + +dtfd_exit: + return(SUCCESS); + +dtfd_err2: + file_close(fh); + +dtfd_err1: + return(FAILURE); +} + +static BRESULT d88trk_read(D88TRK trk, FDDFILE fdd, UINT track, UINT type) { + + UINT8 rpm; + FILEH fh; + UINT32 fptr; + UINT32 size; + + d88trk_flushdata(trk); + if (track >= 164) { + goto dtrd_err1; + } + + rpm = fdc.rpm[fdc.us]; + switch(fdd->inf.d88.fdtype_major) { + case DISKTYPE_2D: + TRACEOUT(("DISKTYPE_2D")); + if ((rpm) || (type != DISKTYPE_2DD) || (track & 2)) { + goto dtrd_err1; + } + track = ((track >> 1) & 0xfe) | (track & 1); + break; + + case DISKTYPE_2DD: + if ((rpm) || (type != DISKTYPE_2DD)) { + goto dtrd_err1; + } + break; + + case DISKTYPE_2HD: + if (CTRL_FDMEDIA != DISKTYPE_2HD) { + goto dtrd_err1; + } + if ((fdd->inf.d88.fdtype_minor == 0) && (rpm)) { + goto dtrd_err1; + } + break; + + default: + goto dtrd_err1; + } + + fptr = fdd->inf.d88.ptr[track]; + if (fptr == 0) { + goto dtrd_err1; + } + size = nexttrackptr(fdd, fptr, fdd->inf.d88.fd_size) - fptr; + if (size > D88BUFSIZE) { + size = D88BUFSIZE; + } + fh = file_open_rb(fdd->fname); + if (fh == FILEH_INVALID) { + goto dtrd_err1; + } + if ((file_seek(fh, (long)fptr, FSEEK_SET) != (long)fptr) || + (file_read(fh, trk->buf, size) != size)) { + goto dtrd_err2; + } + file_close(fh); + + trk->fdd = fdd; + trk->track = track; + trk->type = type; + trk->fptr = fptr; + trk->size = size; + trk->write = FALSE; + return(SUCCESS); + +dtrd_err2: + file_close(fh); + +dtrd_err1: + return(FAILURE); +} + + +static BRESULT rpmcheck(D88SEC sec) { + + FDDFILE fdd = fddfile + fdc.us; + UINT8 rpm; + + rpm = fdc.rpm[fdc.us]; + switch(fdd->inf.d88.fdtype_major) { + case DISKTYPE_2D: + case DISKTYPE_2DD: + if (rpm) { + return(FAILURE); + } + break; + + case DISKTYPE_2HD: + if (fdd->inf.d88.fdtype_minor == 0) { + if (rpm) { + return(FAILURE); + } + } + else { + if (sec->rpm_flg != rpm) { + return(FAILURE); + } + } + break; + + default: + return(FAILURE); + } + return(SUCCESS); +} + + +// ---- + +static void drvflush(FDDFILE fdd) { + + D88TRK trk; + + trk = &d88trk; + if (trk->fdd == fdd && !fdd->protect) { + d88trk_flushdata(trk); + trk->fdd = NULL; + } +} + +static BRESULT trkseek(FDDFILE fdd, UINT track) { + + D88TRK trk; + BRESULT r; + + trk = &d88trk; + if ((trk->fdd == fdd) && (trk->track == track) && + (trk->type == CTRL_FDMEDIA)) { + r = SUCCESS; + } + else { + r = d88trk_read(trk, fdd, track, CTRL_FDMEDIA); + } + return(r); +} + + +static D88SEC searchsector_d88(BOOL check) { // ver0.29 + + UINT8 *p; + UINT sec; + UINT pos = 0; + UINT nsize; + UINT sectors; + UINT secsize; + + if (fdc.N < 8) { + nsize = 128 << fdc.N; + } + else { + nsize = 128 << 8; + } + + p = d88trk.buf; + for (sec=0; sec<40; ) { + if ((pos + nsize + sizeof(_D88SEC)) > D88BUFSIZE) { + break; + } + + if ((((D88SEC)p)->c == fdc.C) && + (((D88SEC)p)->h == fdc.H) && + (((D88SEC)p)->r == fdc.R) && + (((D88SEC)p)->n == fdc.N) && + (!rpmcheck((D88SEC)p))) { + + // ver0.29 + if (check) { + if ((fdc.mf != 0xff) && + !((fdc.mf ^ (((D88SEC)p)->mfm_flg)) & 0x40)) { + break; + } + } + return((D88SEC)p); + } + sectors = LOADINTELWORD(((D88SEC)p)->sectors); + if (++sec >= sectors) { + break; + } + + secsize = LOADINTELWORD(((D88SEC)p)->size); + secsize += sizeof(_D88SEC); + pos += secsize; + p += secsize; + } + return(NULL); +} + + +// ---- + +//BRESULT fddd88_set(FDDFILE fdd, const OEMCHAR *fname, int ro) { +BRESULT fdd_set_d88(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { + + short attr; + FILEH fh; + UINT rsize; + int i; + +// fddd88_eject(fdd); // 削除(kai9) + attr = file_attr(fname); + if (attr & 0x18) { + goto fdst_err; + } + if(attr & FILEATTR_READONLY) { + ro = 1; + } + if(!ro) { + if(attr & FILEATTR_READONLY) { + ro = 1; + } + } + if(ro) { + fh = file_open_rb(fname); + } else { + fh = file_open(fname); + } + if (fh == FILEH_INVALID) { + goto fdst_err; + } + rsize = file_read(fh, &fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); + file_close(fh); + if (rsize != sizeof(fdd->inf.d88.head)) { + goto fdst_err; + } + fdd->type = DISKTYPE_D88; + fdd->protect = ((attr & 1) || (fdd->inf.d88.head.protect & 0x10) || + (ro))?TRUE:FALSE; + fdd->inf.d88.fdtype_major = fdd->inf.d88.head.fd_type >> 4; + fdd->inf.d88.fdtype_minor = fdd->inf.d88.head.fd_type & 0x0f; + fdd->inf.d88.fd_size = LOADINTELDWORD(fdd->inf.d88.head.fd_size); + for (i=0; i<164; i++) { + fdd->inf.d88.ptr[i] = LOADINTELDWORD(fdd->inf.d88.head.trackp[i]); + } + // 処理関数群を登録(kai9) + fdd_fn->eject = fdd_eject_d88; + fdd_fn->diskaccess = fdd_diskaccess_d88; + fdd_fn->seek = fdd_seek_d88; + fdd_fn->seeksector = fdd_seeksector_d88; + fdd_fn->read = fdd_read_d88; + fdd_fn->write = fdd_write_d88; + fdd_fn->readid = fdd_readid_d88; + fdd_fn->writeid = fdd_dummy_xxx; + fdd_fn->formatinit = fdd_formatinit_d88; + fdd_fn->formating = fdd_formating_d88; + fdd_fn->isformating = fdd_isformating_d88; + // + return(SUCCESS); + +fdst_err: + return(FAILURE); +} + +//BRESULT fddd88_eject(FDDFILE fdd) { +BRESULT fdd_eject_d88(FDDFILE fdd) { + + drvflush(fdd); +// 共通関数部へ移動(kai9) +// fdd->fname[0] = '\0'; +// fdd->type = DISKTYPE_NOTREADY; +// ZeroMemory(&fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); + return(SUCCESS); +} + + +//BRESULT fdd_diskaccess_d88(void) { // ver0.31 +BRESULT fdd_diskaccess_d88(FDDFILE fdd) { + +// FDDFILE fdd = fddfile + fdc.us; + UINT8 rpm; + + rpm = fdc.rpm[fdc.us]; + switch(fdd->inf.d88.fdtype_major) { + case DISKTYPE_2D: + case DISKTYPE_2DD: + if ((rpm) || (CTRL_FDMEDIA != DISKTYPE_2DD)) { + return(FAILURE); + } + break; + + case DISKTYPE_2HD: + if (CTRL_FDMEDIA != DISKTYPE_2HD) { + return(FAILURE); + } + if ((fdd->inf.d88.fdtype_minor == 0) && (rpm)) { + return(FAILURE); + } + break; + + default: + return(FAILURE); + + } + return(SUCCESS); +} + +//BRESULT fdd_seek_d88(void) { +BRESULT fdd_seek_d88(FDDFILE fdd) { + +// FDDFILE fdd = fddfile + fdc.us; +TRACEOUT(("D88 seek trkseek[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); + return(trkseek(fdd, (fdc.ncn << 1) + fdc.hd)); +} + +//BRESULT fdd_seeksector_d88(void) { +BRESULT fdd_seeksector_d88(FDDFILE fdd) { + +// FDDFILE fdd = fddfile + fdc.us; + +TRACEOUT(("D88 seeksector trkseek[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); + if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { +TRACEOUT(("D88 seeksector FAILURE trkseek[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); + return(FAILURE); + } + if (!searchsector_d88(FALSE)) { +TRACEOUT(("D88 seeksector FAILURE searchsector[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); + return(FAILURE); + } + return(SUCCESS); +} + +//BRESULT fdd_read_d88(void) { +BRESULT fdd_read_d88(FDDFILE fdd) { + +// FDDFILE fdd = fddfile + fdc.us; + D88SEC p; + UINT size; + UINT secsize; + +TRACEOUT(("D88 read trkseek[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); + fddlasterror = 0x00; + if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { +TRACEOUT(("D88 read FAILURE trkseek[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); + fddlasterror = 0xe0; + return(FAILURE); + } + p = searchsector_d88(TRUE); + if (!p) { +TRACEOUT(("D88 read FAILURE searchsector_d88[%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); + fddlasterror = 0xc0; + return(FAILURE); + } + if (fdc.N < 8) { + size = 128 << fdc.N; + } + else { + size = 128 << 8; + } + fdc.bufcnt = size; + ZeroMemory(fdc.buf, size); + secsize = LOADINTELWORD(p->size); + if (size > secsize) { + size = secsize; + } + if (size) { + CopyMemory(fdc.buf, p+1, size); + } + fddlasterror = p->stat; +TRACEOUT(("D88 read FDC Result Status[%02x]", p->stat)); +TRACEOUT(("D88 read C:%02x,H:%02x,R:%02x,N:%02x", fdc.C, fdc.H, fdc.R, fdc.N)); +TRACEOUT(("D88 read dump")); +TRACEOUT(("\t%02x %02x %02x %02x %02x %02x %02x %02x", + fdc.buf[0x00], fdc.buf[0x01], fdc.buf[0x02], fdc.buf[0x03], fdc.buf[0x04], fdc.buf[0x05], fdc.buf[0x06], fdc.buf[0x07])); + return(SUCCESS); +} + +//BRESULT fdd_write_d88(void) { +BRESULT fdd_write_d88(FDDFILE fdd) { + +// FDDFILE fdd = fddfile + fdc.us; + D88SEC p; + UINT size; + UINT secsize; + + if (fdd->protect) { + return(FAILURE); + } + + fddlasterror = 0x00; + if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { + fddlasterror = 0xe0; + return(FAILURE); + } + p = searchsector_d88(FALSE); + if (!p) { + fddlasterror = 0xc0; + return(FAILURE); + } + if (fdc.N < 8) { + size = 128 << fdc.N; + } + else { + size = 128 << 8; + } + secsize = LOADINTELWORD(p->size); + if (size > secsize) { + size = secsize; + } + if (size) { + CopyMemory(p+1, fdc.buf, size); + d88trk.write = TRUE; + } + fddlasterror = 0x00; + return(SUCCESS); +} + +//BRESULT fdd_readid_d88(void) { +BRESULT fdd_readid_d88(FDDFILE fdd) { + +// FDDFILE fdd = fddfile + fdc.us; + UINT8 *p; + UINT sec; + UINT pos = 0; + UINT sectors; + UINT secsize; + + fddlasterror = 0x00; + if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { + fddlasterror = 0xe0; + return(FAILURE); + } + p = d88trk.buf; + for (sec=0; sec<40; ) { + if (pos > (D88BUFSIZE - sizeof(_D88SEC))) { + break; + } + sectors = LOADINTELWORD(((D88SEC)p)->sectors); + if ((sec == fdc.crcn) && (!rpmcheck((D88SEC)p))) { // ver0.31 + /* 170101 ST modified to work on Windows 9x/2000 form ... */ + if (++fdc.crcn >= sectors) { + fdc.crcn = 0; + /* np21w rev36 removed */ + //if(fdc.mt) { + // fdc.hd ^= 1; + // if (fdc.hd == 0) { + // fdc.treg[fdc.us]++; + // } + //} + //else { + // fdc.treg[fdc.us]++; + //} + } + fdc.C = fdc.treg[fdc.us]; + fdc.H = fdc.hd; + fdc.R = ((D88SEC)p)->r; + fdc.N = ((D88SEC)p)->n; + //fdc.crcn++; + //if (fdc.crcn >= sectors) { + // fdc.crcn = 0; + //} + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + if ((fdc.mf == 0xff) || + ((fdc.mf ^ (((D88SEC)p)->mfm_flg)) & 0x40)) { + fddlasterror = 0x00; + return(SUCCESS); + } + } + if (++sec >= sectors) { + break; + } + secsize = LOADINTELWORD(((D88SEC)p)->size); + secsize += sizeof(_D88SEC); + pos += secsize; + p += secsize; + } + fdc.crcn = 0x00; + fddlasterror = 0xe0; // ver0.31 + return(FAILURE); +} + + +// -------------------------------------------------------------------------- + +// えーと…こんなところにあって大丈夫? +static BOOL formating = FALSE; +static UINT8 formatsec = 0; +static UINT8 formatwrt = 0; +static UINT formatpos = 0; + +static int fileappend(FILEH hdl, FDDFILE fdd, + UINT32 ptr, long last, long apsize) { + + long length; + UINT size; + UINT rsize; + int t; + UINT8 tmp[0x400]; // Stack 0x1000->0x400 + UINT32 cur; + + if (fdd->protect) { + return(0); + } + + if ((length = last - ptr) <= 0) { // 書き換える必要なし + return(0); + } + while(length) { + if (length >= (long)(sizeof(tmp))) { + size = sizeof(tmp); + } + else { + size = length; + } + length -= size; + file_seek(hdl, (FILEPOS)ptr + length, 0); + rsize = file_read(hdl, tmp, size); + file_seek(hdl, (FILEPOS)ptr + length + apsize, 0); + file_write(hdl, tmp, rsize); + } + + for (t=0; t<164; t++) { + cur = fdd->inf.d88.ptr[t]; + if ((cur != 0) && (cur >= ptr)) { + cur += apsize; + fdd->inf.d88.ptr[t] = cur; + STOREINTELDWORD(fdd->inf.d88.head.trackp[t], cur); + } + } + return(0); +} + + +static void endoftrack(UINT fmtsize, UINT8 sectors) { + + FDDFILE fdd = fddfile + fdc.us; + + D88SEC d88sec; + FILEH hdl; + int i; + UINT trk; + long fpointer; + long endpointer; + long lastpointer; + long trksize; + int ptr; + long apsize; + + if (fdd->protect) { + return; + } + + trk = (fdc.treg[fdc.us] << 1) + fdc.hd; + + ptr = 0; + for (i=0; i<(int)sectors; i++) { + d88sec = (D88SEC)(d88trk.buf + ptr); + STOREINTELWORD(d88sec->sectors, sectors); + ptr += LOADINTELWORD(d88sec->size); + ptr += sizeof(_D88SEC); + } + + hdl = file_open(fddfile[fdc.us].fname); + if (hdl == FILEH_INVALID) { + return; + } + lastpointer = (long)file_getsize(hdl); /* lastpointer = file_seek(hdl, 0, FSEEK_END); */ + fpointer = fdd->inf.d88.ptr[trk]; + if (fpointer == 0) { + for (i=trk; i>=0; i--) { // 新規トラック + fpointer = fdd->inf.d88.ptr[i]; + if (fpointer) { + break; + } + } + if (fpointer) { // ヒットした + fpointer = nexttrackptr(fdd, fpointer, lastpointer); + } + else { + fpointer = sizeof(_D88HEAD); + } + endpointer = fpointer; + } + else { // トラックデータは既にある + endpointer = nexttrackptr(fdd, fpointer, lastpointer); + } + trksize = endpointer - fpointer; + if ((apsize = (long)fmtsize - trksize) > 0) { + // 書き込むデータのほーが大きい + fileappend(hdl, fdd, endpointer, lastpointer, apsize); + fdd->inf.d88.fd_size += apsize; + STOREINTELDWORD(fdd->inf.d88.head.fd_size, fdd->inf.d88.fd_size); + } + if (trk >= D88_TRACKMAX) { + file_close(hdl); + return; + } + fdd->inf.d88.ptr[trk] = fpointer; + STOREINTELDWORD(fdd->inf.d88.head.trackp[trk], fpointer); + file_seek(hdl, fpointer, 0); + file_write(hdl, d88trk.buf, fmtsize); + file_seek(hdl, 0, FSEEK_SET); + file_write(hdl, &fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); + file_close(hdl); +// TRACEOUT(("fmt %d %d", fpointer, fmtsize)); +} + + +//BRESULT fdd_formatinit_d88(void) { +BRESULT fdd_formatinit_d88(FDDFILE fdd) { + + if (fdc.treg[fdc.us] < 82) { + formating = TRUE; + formatsec = 0; + formatpos = 0; + formatwrt = 0; + drvflush(fddfile + fdc.us); + return(SUCCESS); + } + return(FAILURE); +} + + // todo アンフォーマットとか ディスク1周した時の切り捨てとか… +//BRESULT fdd_formating_d88(const UINT8 *ID) { +BRESULT fdd_formating_d88(FDDFILE fdd, const UINT8 *ID) { + +// FDDFILE fdd = fddfile + fdc.us; + + UINT size; + D88SEC d88sec; + + if (!formating) { + return(FAILURE); + } + if (fdc.N < 8) { + size = 128 << fdc.N; + } + else { + size = 128 << 8; + } + if ((formatpos + sizeof(_D88SEC) + size) < D88TRACKMAX) { + d88sec = (D88SEC)(d88trk.buf + formatpos); + ZeroMemory(d88sec, sizeof(_D88SEC)); + d88sec->c = ID[0]; + d88sec->h = ID[1]; + d88sec->r = ID[2]; + d88sec->n = ID[3]; + STOREINTELWORD(d88sec->size, size); + if ((fdd->inf.d88.fdtype_major == DISKTYPE_2HD) && + (fdd->inf.d88.fdtype_minor != 0)) { + d88sec->rpm_flg = fdc.rpm[fdc.us]; + } + FillMemory(d88sec + 1, size, fdc.d); + formatpos += sizeof(_D88SEC); + formatpos += size; + formatwrt++; + } + formatsec++; +// TRACE_("format sec", formatsec); +// TRACE_("format wrt", formatwrt); +// TRACE_("format max", fdc.sc); +// TRACE_("format pos", formatpos); + if (formatsec >= fdc.sc) { + endoftrack(formatpos, formatwrt); + formating = FALSE; + } + return(SUCCESS); +} + +//BOOL fdd_isformating_d88(void) { +BOOL fdd_isformating_d88(FDDFILE fdd) { + + return(formating); +} +#else + +static UINT nexttrackptr(FDDFILE fdd, UINT fptr, UINT last) { + + int t; + UINT cur; + + for (t=0; t<164; t++) { + cur = fdd->inf.d88.ptr[t]; + if ((cur > fptr) && (cur < last)) { + last = cur; + } + } + return(last); +} + + +// ---- + +typedef struct { + FDDFILE fdd; + UINT track; + UINT type; + long fptr; + UINT size; + BOOL write; + UINT8 buf[D88BUFSIZE]; +} _D88TRK, *D88TRK; + +static _D88TRK d88trk; + + +static BRESULT d88trk_flushdata(D88TRK trk) { + + FDDFILE fdd; + FILEH fh; + + fdd = trk->fdd; + trk->fdd = NULL; + if ((fdd == NULL) || (trk->size == 0) || (!trk->write)) { + goto dtfd_exit; + } + if (fdd->protect) { + goto dtfd_exit; + } + fh = file_open(fdd->fname); + if (fh == FILEH_INVALID) { + goto dtfd_err1; + } + if ((file_seek(fh, trk->fptr, FSEEK_SET) != trk->fptr) || + (file_write(fh, trk->buf, trk->size) != trk->size)) { + goto dtfd_err2; + } + file_close(fh); + trk->write = FALSE; + +dtfd_exit: + return(SUCCESS); + +dtfd_err2: + file_close(fh); + +dtfd_err1: + return(FAILURE); +} + +static BRESULT d88trk_read(D88TRK trk, FDDFILE fdd, UINT track, UINT type) { + + UINT8 rpm; + FILEH fh; + UINT fptr; + UINT size; + + d88trk_flushdata(trk); + if (track >= 164) { + goto dtrd_err1; + } + + rpm = fdc.rpm[fdc.us]; + switch(fdd->inf.d88.fdtype_major) { + case DISKTYPE_2D: + TRACEOUT(("DISKTYPE_2D")); + if ((rpm) || (type != DISKTYPE_2DD) || (track & 2)) { + goto dtrd_err1; + } + track = ((track >> 1) & 0xfe) | (track & 1); + break; + + case DISKTYPE_2DD: + if ((rpm) || (type != DISKTYPE_2DD)) { + goto dtrd_err1; + } + break; + + case DISKTYPE_2HD: + if (CTRL_FDMEDIA != DISKTYPE_2HD) { + goto dtrd_err1; + } + if ((fdd->inf.d88.fdtype_minor == 0) && (rpm)) { + goto dtrd_err1; + } + break; + + default: + goto dtrd_err1; + } + + fptr = fdd->inf.d88.ptr[track]; + if (fptr == 0) { + goto dtrd_err1; + } + size = nexttrackptr(fdd, fptr, fdd->inf.d88.fd_size) - fptr; + if (size > D88BUFSIZE) { + size = D88BUFSIZE; + } + fh = file_open_rb(fdd->fname); + if (fh == FILEH_INVALID) { + goto dtrd_err1; + } + if ((file_seek(fh, (long)fptr, FSEEK_SET) != (long)fptr) || + (file_read(fh, trk->buf, size) != size)) { + goto dtrd_err2; + } + file_close(fh); + + trk->fdd = fdd; + trk->track = track; + trk->type = type; + trk->fptr = fptr; + trk->size = size; + trk->write = FALSE; + return(SUCCESS); + +dtrd_err2: + file_close(fh); + +dtrd_err1: + return(FAILURE); +} + + +static BRESULT rpmcheck(D88SEC sec) { + + FDDFILE fdd = fddfile + fdc.us; + UINT8 rpm; + + rpm = fdc.rpm[fdc.us]; + switch(fdd->inf.d88.fdtype_major) { + case DISKTYPE_2D: + case DISKTYPE_2DD: + if (rpm) { + return(FAILURE); + } + break; + + case DISKTYPE_2HD: + if (fdd->inf.d88.fdtype_minor == 0) { + if (rpm) { + return(FAILURE); + } + } + else { + if (sec->rpm_flg != rpm) { + return(FAILURE); + } + } + break; + + default: + return(FAILURE); + } + return(SUCCESS); +} + + +// ---- + +static void drvflush(FDDFILE fdd) { + + D88TRK trk; + + trk = &d88trk; + if (trk->fdd == fdd) { + d88trk_flushdata(trk); + trk->fdd = NULL; + } +} + +static BRESULT trkseek(FDDFILE fdd, UINT track) { + + D88TRK trk; + BRESULT r; + + trk = &d88trk; + if ((trk->fdd == fdd) && (trk->track == track) && + (trk->type == CTRL_FDMEDIA)) { + r = SUCCESS; + } + else { + r = d88trk_read(trk, fdd, track, CTRL_FDMEDIA); + } + return(r); +} + + +static D88SEC searchsector_d88(BOOL check) { // ver0.29 + + UINT8 *p; + UINT sec; + UINT pos = 0; + UINT nsize; + UINT sectors; + UINT secsize; + + if (fdc.N < 8) { + nsize = 128 << fdc.N; + } + else { + nsize = 128 << 8; + } + + p = d88trk.buf; + for (sec=0; sec<40; ) { + if ((pos + nsize + sizeof(_D88SEC)) > D88BUFSIZE) { + break; + } + + if ((((D88SEC)p)->c == fdc.C) && + (((D88SEC)p)->h == fdc.H) && + (((D88SEC)p)->r == fdc.R) && + (((D88SEC)p)->n == fdc.N) && + (!rpmcheck((D88SEC)p))) { + + // ver0.29 + if (check) { + if ((fdc.mf != 0xff) && + !((fdc.mf ^ (((D88SEC)p)->mfm_flg)) & 0x40)) { + break; + } + } + return((D88SEC)p); + } + sectors = LOADINTELWORD(((D88SEC)p)->sectors); + if (++sec >= sectors) { + break; + } + + secsize = LOADINTELWORD(((D88SEC)p)->size); + secsize += sizeof(_D88SEC); + pos += secsize; + p += secsize; + } + return(NULL); +} + + +// ---- + +BRESULT fddd88_set(FDDFILE fdd, const OEMCHAR *fname, int ro) { + + short attr; + FILEH fh; + UINT rsize; + int i; + + fddd88_eject(fdd); + attr = file_attr(fname); + if (attr & 0x18) { + goto fdst_err; + } + if(attr & FILEATTR_READONLY) { + ro = 1; + } + if(!ro) { + if(attr & FILEATTR_READONLY) { + ro = 1; + } + } + if(ro) { + fh = file_open_rb(fname); + } else { + fh = file_open(fname); + } + if (fh == FILEH_INVALID) { + goto fdst_err; + } + rsize = file_read(fh, &fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); + file_close(fh); + if (rsize != sizeof(fdd->inf.d88.head)) { + goto fdst_err; + } + fdd->type = DISKTYPE_D88; + fdd->protect = ((attr & 1) || (fdd->inf.d88.head.protect & 0x10) || + (ro))?TRUE:FALSE; + fdd->inf.d88.fdtype_major = fdd->inf.d88.head.fd_type >> 4; + fdd->inf.d88.fdtype_minor = fdd->inf.d88.head.fd_type & 0x0f; + fdd->inf.d88.fd_size = LOADINTELDWORD(fdd->inf.d88.head.fd_size); + for (i=0; i<164; i++) { + fdd->inf.d88.ptr[i] = LOADINTELDWORD(fdd->inf.d88.head.trackp[i]); + } + return(SUCCESS); + +fdst_err: + return(FAILURE); +} + +BRESULT fddd88_eject(FDDFILE fdd) { + + drvflush(fdd); + fdd->fname[0] = '\0'; + fdd->type = DISKTYPE_NOTREADY; + ZeroMemory(&fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); + return(SUCCESS); +} + + +BRESULT fdd_diskaccess_d88(void) { // ver0.31 + + FDDFILE fdd = fddfile + fdc.us; + UINT8 rpm; + + rpm = fdc.rpm[fdc.us]; + switch(fdd->inf.d88.fdtype_major) { + case DISKTYPE_2D: + case DISKTYPE_2DD: + if ((rpm) || (CTRL_FDMEDIA != DISKTYPE_2DD)) { + return(FAILURE); + } + break; + + case DISKTYPE_2HD: + if (CTRL_FDMEDIA != DISKTYPE_2HD) { + return(FAILURE); + } + if ((fdd->inf.d88.fdtype_minor == 0) && (rpm)) { + return(FAILURE); + } + break; + + default: + return(FAILURE); + + } + return(SUCCESS); +} + +BRESULT fdd_seek_d88(void) { + + FDDFILE fdd = fddfile + fdc.us; + + return(trkseek(fdd, (fdc.ncn << 1) + fdc.hd)); +} + +BRESULT fdd_seeksector_d88(void) { + + FDDFILE fdd = fddfile + fdc.us; + + if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { + return(FAILURE); + } + if (!searchsector_d88(FALSE)) { + return(FAILURE); + } + return(SUCCESS); +} + +BRESULT fdd_read_d88(void) { + + FDDFILE fdd = fddfile + fdc.us; + D88SEC p; + UINT size; + UINT secsize; + + fddlasterror = 0x00; + if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { + fddlasterror = 0xe0; + return(FAILURE); + } + p = searchsector_d88(TRUE); + if (!p) { + fddlasterror = 0xc0; + return(FAILURE); + } + if (fdc.N < 8) { + size = 128 << fdc.N; + } + else { + size = 128 << 8; + } + fdc.bufcnt = size; + ZeroMemory(fdc.buf, size); + secsize = LOADINTELWORD(p->size); + if (size > secsize) { + size = secsize; + } + if (size) { + CopyMemory(fdc.buf, p+1, size); + } + fddlasterror = p->stat; + return(SUCCESS); +} + +BRESULT fdd_write_d88(void) { + + FDDFILE fdd = fddfile + fdc.us; + D88SEC p; + UINT size; + UINT secsize; + + fddlasterror = 0x00; + if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { + fddlasterror = 0xe0; + return(FAILURE); + } + p = searchsector_d88(FALSE); + if (!p) { + fddlasterror = 0xc0; + return(FAILURE); + } + if (fdc.N < 8) { + size = 128 << fdc.N; + } + else { + size = 128 << 8; + } + secsize = LOADINTELWORD(p->size); + if (size > secsize) { + size = secsize; + } + if (size) { + CopyMemory(p+1, fdc.buf, size); + d88trk.write = TRUE; + } + fddlasterror = 0x00; + return(SUCCESS); +} + +BRESULT fdd_readid_d88(void) { + + FDDFILE fdd = fddfile + fdc.us; + UINT8 *p; + UINT sec; + UINT pos = 0; + UINT sectors; + UINT secsize; + + fddlasterror = 0x00; + if (trkseek(fdd, (fdc.treg[fdc.us] << 1) + fdc.hd)) { + fddlasterror = 0xe0; + return(FAILURE); + } + p = d88trk.buf; + for (sec=0; sec<40; ) { + if (pos > (D88BUFSIZE - sizeof(_D88SEC))) { + break; + } + sectors = LOADINTELWORD(((D88SEC)p)->sectors); + if ((sec == fdc.crcn) && (!rpmcheck((D88SEC)p))) { // ver0.31 + fdc.C = ((D88SEC)p)->c; + fdc.H = ((D88SEC)p)->h; + fdc.R = ((D88SEC)p)->r; + fdc.N = ((D88SEC)p)->n; + fdc.crcn++; + if (fdc.crcn >= sectors) { + fdc.crcn = 0; + } + if ((fdc.mf == 0xff) || + ((fdc.mf ^ (((D88SEC)p)->mfm_flg)) & 0x40)) { + fddlasterror = 0x00; + return(SUCCESS); + } + } + if (++sec >= sectors) { + break; + } + secsize = LOADINTELWORD(((D88SEC)p)->size); + secsize += sizeof(_D88SEC); + pos += secsize; + p += secsize; + } + fdc.crcn = 0x00; + fddlasterror = 0xe0; // ver0.31 + return(FAILURE); +} + + +// -------------------------------------------------------------------------- + +// えーと…こんなところにあって大丈夫? +static BOOL formating = FALSE; +static UINT8 formatsec = 0; +static UINT8 formatwrt = 0; +static UINT formatpos = 0; + +static int fileappend(FILEH hdl, FDDFILE fdd, UINT ptr, UINT last, int apsize) { + + int length; + UINT size; + UINT rsize; + int t; + UINT8 tmp[0x400]; // Stack 0x1000->0x400 + UINT cur; + + if (fdd->protect) { + return(0); + } + + if ((length = last - ptr) <= 0) { // 書き換える必要なし + return(0); + } + while(length) { + if (length >= sizeof(tmp)) { + size = sizeof(tmp); + } + else { + size = length; + } + length -= size; + file_seek(hdl, ptr + length, 0); + rsize = file_read(hdl, tmp, size); + file_seek(hdl, ptr + length + apsize, 0); + file_write(hdl, tmp, rsize); + } + + for (t=0; t<164; t++) { + cur = fdd->inf.d88.ptr[t]; + if ((cur != 0) && (cur >= ptr)) { + cur += apsize; + fdd->inf.d88.ptr[t] = cur; + STOREINTELDWORD(fdd->inf.d88.head.trackp[t], cur); + } + } + return(0); +} + + +static void endoftrack(UINT fmtsize, UINT8 sectors) { + + FDDFILE fdd = fddfile + fdc.us; + + D88SEC d88sec; + FILEH hdl; + int i; + UINT trk; + UINT fpointer; + UINT endpointer; + UINT lastpointer; + UINT trksize; + int ptr; + int apsize; + + if (fdd->protect) { + return; + } + + trk = (fdc.treg[fdc.us] << 1) + fdc.hd; + + ptr = 0; + for (i=0; i<(int)sectors; i++) { + d88sec = (D88SEC)(d88trk.buf + ptr); + STOREINTELWORD(d88sec->sectors, sectors); + ptr += LOADINTELWORD(d88sec->size); + ptr += sizeof(_D88SEC); + } + + hdl = file_open(fddfile[fdc.us].fname); + if (hdl == FILEH_INVALID) { + return; + } + lastpointer = file_getsize(hdl); + fpointer = fdd->inf.d88.ptr[trk]; + if (fpointer == 0) { + for (i=trk; i>=0; i--) { // 新規トラック + fpointer = fdd->inf.d88.ptr[i]; + if (fpointer) { + break; + } + } + if (fpointer) { // ヒットした + fpointer = nexttrackptr(fdd, fpointer, lastpointer); + } + else { + fpointer = sizeof(_D88HEAD); + } + endpointer = fpointer; + } + else { // トラックデータは既にある + endpointer = nexttrackptr(fdd, fpointer, lastpointer); + } + trksize = endpointer - fpointer; + if ((apsize = fmtsize - trksize) > 0) { + // 書き込むデータのほーが大きい + fileappend(hdl, fdd, endpointer, lastpointer, apsize); + fdd->inf.d88.fd_size += apsize; + STOREINTELDWORD(fdd->inf.d88.head.fd_size, fdd->inf.d88.fd_size); + } + fdd->inf.d88.ptr[trk] = fpointer; + STOREINTELDWORD(fdd->inf.d88.head.trackp[trk], fpointer); + file_seek(hdl, (long)fpointer, 0); + file_write(hdl, d88trk.buf, fmtsize); + file_seek(hdl, 0, FSEEK_SET); + file_write(hdl, &fdd->inf.d88.head, sizeof(fdd->inf.d88.head)); + file_close(hdl); +// TRACEOUT(("fmt %d %d", fpointer, fmtsize)); +} + + +BRESULT fdd_formatinit_d88(void) { + + if (fdc.treg[fdc.us] < 82) { + formating = TRUE; + formatsec = 0; + formatpos = 0; + formatwrt = 0; + drvflush(fddfile + fdc.us); + return(SUCCESS); + } + return(FAILURE); +} + + // todo アンフォーマットとか ディスク1周した時の切り捨てとか… +BRESULT fdd_formating_d88(const UINT8 *ID) { + + FDDFILE fdd = fddfile + fdc.us; + + UINT size; + D88SEC d88sec; + + if (!formating) { + return(FAILURE); + } + if (fdc.N < 8) { + size = 128 << fdc.N; + } + else { + size = 128 << 8; + } + if ((formatpos + sizeof(_D88SEC) + size) < D88TRACKMAX) { + d88sec = (D88SEC)(d88trk.buf + formatpos); + ZeroMemory(d88sec, sizeof(_D88SEC)); + d88sec->c = ID[0]; + d88sec->h = ID[1]; + d88sec->r = ID[2]; + d88sec->n = ID[3]; + STOREINTELWORD(d88sec->size, size); + if ((fdd->inf.d88.fdtype_major == DISKTYPE_2HD) && + (fdd->inf.d88.fdtype_minor != 0)) { + d88sec->rpm_flg = fdc.rpm[fdc.us]; + } + FillMemory(d88sec + 1, size, fdc.d); + formatpos += sizeof(_D88SEC); + formatpos += size; + formatwrt++; + } + formatsec++; +// TRACE_("format sec", formatsec); +// TRACE_("format wrt", formatwrt); +// TRACE_("format max", fdc.sc); +// TRACE_("format pos", formatpos); + if (formatsec >= fdc.sc) { + endoftrack(formatpos, formatwrt); + formating = FALSE; + } + return(SUCCESS); +} + +BOOL fdd_isformating_d88(void) { + + return(formating); +} + + + +#endif diff --git a/diskimage/fd/fdd_d88.h b/diskimage/fd/fdd_d88.h old mode 100755 new mode 100644 index a3310d57..a098568b --- a/diskimage/fd/fdd_d88.h +++ b/diskimage/fd/fdd_d88.h @@ -1,70 +1,70 @@ -#ifdef SUPPORT_KAI_IMAGES - -#ifdef __cplusplus -extern "C" { -#endif - -#if 1 // 関数名変更&引数追加(k9) -BRESULT fdd_set_d88(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); -BRESULT fdd_eject_d88(FDDFILE fdd); - -BRESULT fdd_diskaccess_d88(FDDFILE fdd); -BRESULT fdd_seek_d88(FDDFILE fdd); -BRESULT fdd_seeksector_d88(FDDFILE fdd); -BRESULT fdd_read_d88(FDDFILE fdd); -BRESULT fdd_write_d88(FDDFILE fdd); -BRESULT fdd_diagread_d88(FDDFILE fdd); -BRESULT fdd_readid_d88(FDDFILE fdd); -BRESULT fdd_writeid_d88(FDDFILE fdd); // 未実装 - -BRESULT fdd_formatinit_d88(FDDFILE fdd); -BRESULT fdd_formating_d88(FDDFILE fdd, const UINT8 *ID); -BOOL fdd_isformating_d88(FDDFILE fdd); -#else -BRESULT fddd88_set(FDDFILE fdd, const OEMCHAR *fname, int ro); -BRESULT fddd88_eject(FDDFILE fdd); - -BRESULT fdd_diskaccess_d88(void); -BRESULT fdd_seek_d88(void); -BRESULT fdd_seeksector_d88(void); -BRESULT fdd_read_d88(void); -BRESULT fdd_write_d88(void); -BRESULT fdd_diagread_d88(void); -BRESULT fdd_readid_d88(void); -BRESULT fdd_writeid_d88(void); - -BRESULT fdd_formatinit_d88(void); -BRESULT fdd_formating_d88(const UINT8 *ID); -BOOL fdd_isformating_d88(void); -#endif - -#ifdef __cplusplus -} -#endif - -#else -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT fddd88_set(FDDFILE fdd, const OEMCHAR *fname, int ro); -BRESULT fddd88_eject(FDDFILE fdd); - -BRESULT fdd_diskaccess_d88(void); -BRESULT fdd_seek_d88(void); -BRESULT fdd_seeksector_d88(void); -BRESULT fdd_read_d88(void); -BRESULT fdd_write_d88(void); -BRESULT fdd_diagread_d88(void); -BRESULT fdd_readid_d88(void); -BRESULT fdd_writeid_d88(void); - -BRESULT fdd_formatinit_d88(void); -BRESULT fdd_formating_d88(const UINT8 *ID); -BOOL fdd_isformating_d88(void); - -#ifdef __cplusplus -} -#endif - -#endif +#ifdef SUPPORT_KAI_IMAGES + +#ifdef __cplusplus +extern "C" { +#endif + +#if 1 // 関数名変更&引数追加(k9) +BRESULT fdd_set_d88(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); +BRESULT fdd_eject_d88(FDDFILE fdd); + +BRESULT fdd_diskaccess_d88(FDDFILE fdd); +BRESULT fdd_seek_d88(FDDFILE fdd); +BRESULT fdd_seeksector_d88(FDDFILE fdd); +BRESULT fdd_read_d88(FDDFILE fdd); +BRESULT fdd_write_d88(FDDFILE fdd); +BRESULT fdd_diagread_d88(FDDFILE fdd); +BRESULT fdd_readid_d88(FDDFILE fdd); +BRESULT fdd_writeid_d88(FDDFILE fdd); // 未実装 + +BRESULT fdd_formatinit_d88(FDDFILE fdd); +BRESULT fdd_formating_d88(FDDFILE fdd, const UINT8 *ID); +BOOL fdd_isformating_d88(FDDFILE fdd); +#else +BRESULT fddd88_set(FDDFILE fdd, const OEMCHAR *fname, int ro); +BRESULT fddd88_eject(FDDFILE fdd); + +BRESULT fdd_diskaccess_d88(void); +BRESULT fdd_seek_d88(void); +BRESULT fdd_seeksector_d88(void); +BRESULT fdd_read_d88(void); +BRESULT fdd_write_d88(void); +BRESULT fdd_diagread_d88(void); +BRESULT fdd_readid_d88(void); +BRESULT fdd_writeid_d88(void); + +BRESULT fdd_formatinit_d88(void); +BRESULT fdd_formating_d88(const UINT8 *ID); +BOOL fdd_isformating_d88(void); +#endif + +#ifdef __cplusplus +} +#endif + +#else +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT fddd88_set(FDDFILE fdd, const OEMCHAR *fname, int ro); +BRESULT fddd88_eject(FDDFILE fdd); + +BRESULT fdd_diskaccess_d88(void); +BRESULT fdd_seek_d88(void); +BRESULT fdd_seeksector_d88(void); +BRESULT fdd_read_d88(void); +BRESULT fdd_write_d88(void); +BRESULT fdd_diagread_d88(void); +BRESULT fdd_readid_d88(void); +BRESULT fdd_writeid_d88(void); + +BRESULT fdd_formatinit_d88(void); +BRESULT fdd_formating_d88(const UINT8 *ID); +BOOL fdd_isformating_d88(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/diskimage/fd/fdd_dcp.c b/diskimage/fd/fdd_dcp.c old mode 100755 new mode 100644 index 50fb742c..c8178c92 --- a/diskimage/fd/fdd_dcp.c +++ b/diskimage/fd/fdd_dcp.c @@ -1,459 +1,459 @@ -#include -#include -#include -#include - -#ifdef SUPPORT_KAI_IMAGES - -#include -#include "diskimage/fd/fdd_xdf.h" -#include "diskimage/fd/fdd_dcp.h" - -typedef struct { - UINT8 mediatype; - _XDFINFO xdf; -} __DCPINFO; - -// 全トラック格納イメージチェック用 -static const __DCPINFO supportdcp[] = { - {0x01, {162, 154, 8, 3, DISKTYPE_2HD, 0}}, // 01h 2HD- 8セクタ(1.25MB) - {0x02, {162, 160, 15, 2, DISKTYPE_2HD, 0}}, // 02h 2HD-15セクタ(1.21MB) - {0x03, {162, 160, 18, 2, DISKTYPE_2HD, 1}}, // 03h 2HQ-18セクタ(1.44MB) - {0x04, {162, 160, 8, 2, DISKTYPE_2DD, 0}}, // 04h 2DD- 8セクタ( 640KB) - {0x05, {162, 160, 9, 2, DISKTYPE_2DD, 0}}, // 05h 2DD- 9セクタ( 720KB) - {0x08, {162, 154, 9, 3, DISKTYPE_2HD, 0}}, // 08h 2HD- 9セクタ(1.44MB) - {0x11, {162, 154, 26, 1, DISKTYPE_2HD, 0}}, // 11h BASIC-2HD - {0x19, {162, 160, 16, 1, DISKTYPE_2DD, 0}}, // 19h BASIC-2DD - {0x21, {162, 154, 26, 1, DISKTYPE_2HD, 0}}, // 21h 2HD-26セクタ -}; - -BRESULT fdd_set_dcp(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { - -const __DCPINFO *dcp; - short attr; - FILEH fh; - UINT32 fdsize; - UINT size; - UINT rsize; - UINT tracksize; - UINT32 trackptr; - UINT i; - - attr = file_attr(fname); - if (attr & 0x18) { - return(FAILURE); - } - if(!ro) { - if(attr & FILEATTR_READONLY) { - ro = 1; - } - } - if(ro) { - fh = file_open_rb(fname); - } else { - fh = file_open(fname); - } - if (fh == FILEH_INVALID) { - return(FAILURE); - } - fdsize = (UINT32)file_getsize(fh); - rsize = file_read(fh, &fdd->inf.dcp.head, DCP_HEADERSIZE); // DCPヘッダ読込 - file_close(fh); - if (rsize != DCP_HEADERSIZE) { - return(FAILURE); - } - - // 全トラック格納イメージチェック - dcp = supportdcp; - while(dcp < (supportdcp + NELEMENTS(supportdcp))) { - if (fdd->inf.dcp.head.mediatype == dcp->mediatype) { - if (fdd->inf.dcp.head.alltrackflg == 0x01) { - // 全トラック格納フラグが0x01の場合、ファイルサイズチェック - size = dcp->xdf.tracks; - size *= dcp->xdf.sectors; - size <<= (7 + dcp->xdf.n); - size += dcp->xdf.headersize; - if (size != fdsize) { - return(FAILURE); - } - } - fdd->type = DISKTYPE_DCP; - fdd->protect = ((attr & 0x01) || (ro)) ? TRUE : FALSE; - fdd->inf.xdf = dcp->xdf; - - // ディスクアクセス時用に各トラックのオフセットを算出 - tracksize = fdd->inf.xdf.sectors * (128 << fdd->inf.xdf.n); -// trackptr = 0; - trackptr = DCP_HEADERSIZE; - for(i = 0; i < fdd->inf.xdf.tracks; i++) { - if (fdd->inf.dcp.head.trackmap[i] == 0x01 || fdd->inf.dcp.head.alltrackflg == 0x01) { - // トラックデータが存在する(trackmap[i] = 0x01) - // or 全トラック格納フラグが0x01 - fdd->inf.dcp.ptr[i] = trackptr; - if (i == 0 && fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS) { - trackptr += tracksize / 2; // BASIC-2HD、track 0用小細工 - } - else { - trackptr += tracksize; - } - } - else { - // イメージファイル上に存在しないトラック - fdd->inf.dcp.ptr[i] = 0; - } - } - - // 処理関数群を登録 - // ※read、write以外は構造体の小細工でxdf系と共用 - fdd_fn->eject = fdd_eject_xxx; - fdd_fn->diskaccess = fdd_diskaccess_common; - fdd_fn->seek = fdd_seek_common; - fdd_fn->seeksector = fdd_seeksector_common; - fdd_fn->read = fdd_read_dcp; - fdd_fn->write = fdd_write_dcp; - fdd_fn->readid = fdd_readid_common; - fdd_fn->writeid = fdd_dummy_xxx; - fdd_fn->formatinit = fdd_dummy_xxx; - fdd_fn->formating = fdd_formating_xxx; - fdd_fn->isformating = fdd_isformating_xxx; - - return(SUCCESS); - } - dcp++; - } - - return(FAILURE); -} - -BRESULT fdd_read_dcp(FDDFILE fdd) { - - FILEH hdl; - UINT track; - UINT secsize; - long seekp; - - fddlasterror = 0x00; - if (fdd_seeksector_common(fdd)) { - return(FAILURE); - } - if (fdc.N != fdd->inf.xdf.n) { - fddlasterror = 0xc0; - return(FAILURE); - } - /* 170101 ST modified to work on Windows 9x/2000 form ... */ - if (fdc.eot > fdd->inf.xdf.sectors) { - fddlasterror = 0xc0; - return(FAILURE); - } - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - - track = (fdc.treg[fdc.us] << 1) + fdc.hd; - secsize = 128 << fdd->inf.xdf.n; - if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && track == 0) { - // BASIC-2HD、track 0用小細工 - secsize /= 2; - } - if ((fdd->type == DISKTYPE_BETA) || - (fdd->type == DISKTYPE_DCP && fdd->inf.dcp.head.trackmap[track] == 0x01) || - (fdd->type == DISKTYPE_DCP && fdd->inf.dcp.head.alltrackflg == 0x01)) { - - seekp = fdc.R - 1; - seekp <<= (7 + fdd->inf.xdf.n); - if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && track == 0) { - // BASIC-2HD、track 0用小細工 - seekp /= 2; - } - seekp += fdd->inf.dcp.ptr[track]; -// seekp += fdd->inf.xdf.headersize; - - hdl = file_open_rb(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xe0; - return(FAILURE); - } - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_read(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xe0; - return(FAILURE); - } - file_close(hdl); - } - else { - // ファイル上にデータの存在しないセクタは0xE5で埋めて返す - // ※DCUだと違う? - FillMemory(fdc.buf, secsize, 0xe5); - } -#if 0 - if (fdd->inf.dcp.head.trackmap[track] != 0x01) { -// if (fdd->inf.dcp.ptr[track] == 0) { - // ファイル上にデータの存在しないセクタは0xE5で埋めて返す - // ※DCUだと違う? - FillMemory(fdc.buf, secsize, 0xe5); - } - else { - seekp = fdc.R - 1; - seekp <<= (7 + fdd->inf.xdf.n); - if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && track == 0) { - // BASIC-2HD、track 0用小細工 - seekp /= 2; - } - seekp += fdd->inf.dcp.ptr[track]; - seekp += fdd->inf.xdf.headersize; - - hdl = file_open_rb(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xe0; - return(FAILURE); - } - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_read(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xe0; - return(FAILURE); - } - file_close(hdl); - } -#endif - fdc.bufcnt = secsize; - fddlasterror = 0x00; - return(SUCCESS); -} - -BRESULT makenewtrack_dcp(FDDFILE fdd) { - -#if 1 - FILEH hdl; -// UINT curtrack; - UINT newtrack; - - UINT32 tracksize; - UINT32 length; - UINT size; - UINT rsize; -// int t; - UINT8 tmp[0x0400]; -// UINT32 cur; - - int i; - UINT32 ptr; - UINT32 fdsize; - - if (fdd->protect) { - fddlasterror = 0x70; - return(FAILURE); - } - - hdl = file_open(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xc0; - return(FAILURE); - } - - fdsize = (UINT32)file_getsize(hdl); - - newtrack = (fdc.treg[fdc.us] << 1) + fdc.hd; - tracksize = fdd->inf.xdf.sectors * (128 << fdd->inf.xdf.n); - if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && newtrack == 0) { - tracksize /= 2; - } - // ずらし始めるオフセット取得 - ptr = 0; - for (i = newtrack; i < DCP_TRACKMAX; i++) { - if (fdd->inf.dcp.ptr[i] != 0) { - ptr = fdd->inf.dcp.ptr[i]; - break; - } - } - if (ptr != 0) { -// ptr += fdd->inf.xdf.headersize; - length = fdsize - ptr; - - while(length) { - if (length >= (long)(sizeof(tmp))) { - size = sizeof(tmp); - } - else { - size = length; - } - length -= size; - file_seek(hdl, (FILEPOS)ptr + length, 0); - rsize = file_read(hdl, tmp, size); - file_seek(hdl, (FILEPOS)ptr + length + tracksize, 0); - file_write(hdl, tmp, rsize); - } - - // 各トラックのオフセット再計算 - fdd->inf.dcp.ptr[newtrack] = ptr; - ptr += tracksize; - for (i = newtrack+1; i < DCP_TRACKMAX; i++) { - if (fdd->inf.dcp.ptr[i] != 0) { - fdd->inf.dcp.ptr[i] = ptr; - ptr += tracksize; - } - } - } - else { - if (newtrack >= DCP_TRACKMAX) { - file_close(hdl); - return(FAILURE); - } - fdd->inf.dcp.ptr[newtrack] = fdsize; - } - - file_close(hdl); - - return(SUCCESS); -#else - return(FAILURE); -#endif -} - -BRESULT refreshheader_dcp(FDDFILE fdd) { - - FILEH hdl; - - if (fdd->protect) { - hdl = file_open_rb(fdd->fname); - } else { - hdl = file_open(fdd->fname); - } - if (hdl == FILEH_INVALID) { - fddlasterror = 0xc0; - return(FAILURE); - } - file_seek(hdl, 0, 0); - file_write(hdl, &fdd->inf.dcp.head, DCP_HEADERSIZE); - file_close(hdl); - - return(SUCCESS); -} - - -BRESULT fdd_write_dcp(FDDFILE fdd) { - - FILEH hdl; - UINT track; - UINT secsize; - long seekp; - - fddlasterror = 0x00; - if (fdd_seeksector_common(fdd)) { - fddlasterror = 0xe0; - return(FAILURE); - } - if (fdd->protect) { - fddlasterror = 0x70; - return(FAILURE); - } - if (fdc.N != fdd->inf.xdf.n) { - fddlasterror = 0xc0; - return(FAILURE); - } - /* 170101 ST modified to work on Windows 9x/2000 form ... */ - if (fdc.eot > fdd->inf.xdf.sectors) { - fddlasterror = 0xc0; - return(FAILURE); - } - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - - track = (fdc.treg[fdc.us] << 1) + fdc.hd; - - if ((fdd->type == DISKTYPE_BETA) || - (fdd->type == DISKTYPE_DCP && fdd->inf.dcp.head.trackmap[track] == 0x01) || - (fdd->type == DISKTYPE_DCP && fdd->inf.dcp.head.alltrackflg == 0x01)) { - - secsize = 128 << fdd->inf.xdf.n; - seekp = fdc.R - 1; - seekp <<= (7 + fdd->inf.xdf.n); - if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && track == 0) { - // BASIC-2HD、track 0用小細工 - secsize /= 2; - seekp /= 2; - } - seekp += fdd->inf.dcp.ptr[track]; -// seekp += fdd->inf.xdf.headersize; - - hdl = file_open(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xc0; - return(FAILURE); - } - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_write(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xc0; - return(FAILURE); - } - file_close(hdl); - } - else { - // 新規トラック挿入後、再帰呼び出し - BRESULT r; - r = makenewtrack_dcp(fdd); - if (r != SUCCESS) { - return r; - } - fdd->inf.dcp.head.trackmap[track] = 0x01; - r = refreshheader_dcp(fdd); - if (r != SUCCESS) { - return r; - } - return(fdd_write_dcp(fdd)); - } -#if 0 - if (fdd->inf.dcp.head.trackmap[track] != 0x01) { -// if (fdd->inf.dcp.ptr[track] == 0) { - // データの存在しないトラックはエラーにしとく -// fddlasterror = 0xc0; -// return(FAILURE); - // 新規トラック挿入&ヘッダ部更新後、 - // 再帰呼び出し - BRESULT r; - r = makenewtrack_dcp(fdd); - if (r != SUCCESS) { - return r; - } - // r = refreshheader_dcp(fdd); - // if (r != SUCCESS) { - // return r; - // } - return(fdd_write_dcp(fdd)); - } - - secsize = 128 << fdd->inf.xdf.n; - seekp = fdc.R - 1; - seekp <<= (7 + fdd->inf.xdf.n); - if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && track == 0) { - // BASIC-2HD、track 0用小細工 - secsize /= 2; - seekp /= 2; - } - seekp += fdd->inf.dcp.ptr[track]; - seekp += fdd->inf.xdf.headersize; - - hdl = file_open(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xc0; - return(FAILURE); - } - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_write(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xc0; - return(FAILURE); - } - file_close(hdl); -#endif - fdc.bufcnt = secsize; - fddlasterror = 0x00; - if (fdd->type == DISKTYPE_DCP ) { - if (fdd->inf.dcp.head.trackmap[track] != 0x01) { - fdd->inf.dcp.head.trackmap[track] = 0x01; - refreshheader_dcp(fdd); - } - } - return(SUCCESS); -} - -#endif +#include +#include +#include +#include + +#ifdef SUPPORT_KAI_IMAGES + +#include +#include "diskimage/fd/fdd_xdf.h" +#include "diskimage/fd/fdd_dcp.h" + +typedef struct { + UINT8 mediatype; + _XDFINFO xdf; +} __DCPINFO; + +// 全トラック格納イメージチェック用 +static const __DCPINFO supportdcp[] = { + {0x01, {162, 154, 8, 3, DISKTYPE_2HD, 0}}, // 01h 2HD- 8セクタ(1.25MB) + {0x02, {162, 160, 15, 2, DISKTYPE_2HD, 0}}, // 02h 2HD-15セクタ(1.21MB) + {0x03, {162, 160, 18, 2, DISKTYPE_2HD, 1}}, // 03h 2HQ-18セクタ(1.44MB) + {0x04, {162, 160, 8, 2, DISKTYPE_2DD, 0}}, // 04h 2DD- 8セクタ( 640KB) + {0x05, {162, 160, 9, 2, DISKTYPE_2DD, 0}}, // 05h 2DD- 9セクタ( 720KB) + {0x08, {162, 154, 9, 3, DISKTYPE_2HD, 0}}, // 08h 2HD- 9セクタ(1.44MB) + {0x11, {162, 154, 26, 1, DISKTYPE_2HD, 0}}, // 11h BASIC-2HD + {0x19, {162, 160, 16, 1, DISKTYPE_2DD, 0}}, // 19h BASIC-2DD + {0x21, {162, 154, 26, 1, DISKTYPE_2HD, 0}}, // 21h 2HD-26セクタ +}; + +BRESULT fdd_set_dcp(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { + +const __DCPINFO *dcp; + short attr; + FILEH fh; + UINT32 fdsize; + UINT size; + UINT rsize; + UINT tracksize; + UINT32 trackptr; + UINT i; + + attr = file_attr(fname); + if (attr & 0x18) { + return(FAILURE); + } + if(!ro) { + if(attr & FILEATTR_READONLY) { + ro = 1; + } + } + if(ro) { + fh = file_open_rb(fname); + } else { + fh = file_open(fname); + } + if (fh == FILEH_INVALID) { + return(FAILURE); + } + fdsize = (UINT32)file_getsize(fh); + rsize = file_read(fh, &fdd->inf.dcp.head, DCP_HEADERSIZE); // DCPヘッダ読込 + file_close(fh); + if (rsize != DCP_HEADERSIZE) { + return(FAILURE); + } + + // 全トラック格納イメージチェック + dcp = supportdcp; + while(dcp < (supportdcp + NELEMENTS(supportdcp))) { + if (fdd->inf.dcp.head.mediatype == dcp->mediatype) { + if (fdd->inf.dcp.head.alltrackflg == 0x01) { + // 全トラック格納フラグが0x01の場合、ファイルサイズチェック + size = dcp->xdf.tracks; + size *= dcp->xdf.sectors; + size <<= (7 + dcp->xdf.n); + size += dcp->xdf.headersize; + if (size != fdsize) { + return(FAILURE); + } + } + fdd->type = DISKTYPE_DCP; + fdd->protect = ((attr & 0x01) || (ro)) ? TRUE : FALSE; + fdd->inf.xdf = dcp->xdf; + + // ディスクアクセス時用に各トラックのオフセットを算出 + tracksize = fdd->inf.xdf.sectors * (128 << fdd->inf.xdf.n); +// trackptr = 0; + trackptr = DCP_HEADERSIZE; + for(i = 0; i < fdd->inf.xdf.tracks; i++) { + if (fdd->inf.dcp.head.trackmap[i] == 0x01 || fdd->inf.dcp.head.alltrackflg == 0x01) { + // トラックデータが存在する(trackmap[i] = 0x01) + // or 全トラック格納フラグが0x01 + fdd->inf.dcp.ptr[i] = trackptr; + if (i == 0 && fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS) { + trackptr += tracksize / 2; // BASIC-2HD、track 0用小細工 + } + else { + trackptr += tracksize; + } + } + else { + // イメージファイル上に存在しないトラック + fdd->inf.dcp.ptr[i] = 0; + } + } + + // 処理関数群を登録 + // ※read、write以外は構造体の小細工でxdf系と共用 + fdd_fn->eject = fdd_eject_xxx; + fdd_fn->diskaccess = fdd_diskaccess_common; + fdd_fn->seek = fdd_seek_common; + fdd_fn->seeksector = fdd_seeksector_common; + fdd_fn->read = fdd_read_dcp; + fdd_fn->write = fdd_write_dcp; + fdd_fn->readid = fdd_readid_common; + fdd_fn->writeid = fdd_dummy_xxx; + fdd_fn->formatinit = fdd_dummy_xxx; + fdd_fn->formating = fdd_formating_xxx; + fdd_fn->isformating = fdd_isformating_xxx; + + return(SUCCESS); + } + dcp++; + } + + return(FAILURE); +} + +BRESULT fdd_read_dcp(FDDFILE fdd) { + + FILEH hdl; + UINT track; + UINT secsize; + long seekp; + + fddlasterror = 0x00; + if (fdd_seeksector_common(fdd)) { + return(FAILURE); + } + if (fdc.N != fdd->inf.xdf.n) { + fddlasterror = 0xc0; + return(FAILURE); + } + /* 170101 ST modified to work on Windows 9x/2000 form ... */ + if (fdc.eot > fdd->inf.xdf.sectors) { + fddlasterror = 0xc0; + return(FAILURE); + } + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + + track = (fdc.treg[fdc.us] << 1) + fdc.hd; + secsize = 128 << fdd->inf.xdf.n; + if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && track == 0) { + // BASIC-2HD、track 0用小細工 + secsize /= 2; + } + if ((fdd->type == DISKTYPE_BETA) || + (fdd->type == DISKTYPE_DCP && fdd->inf.dcp.head.trackmap[track] == 0x01) || + (fdd->type == DISKTYPE_DCP && fdd->inf.dcp.head.alltrackflg == 0x01)) { + + seekp = fdc.R - 1; + seekp <<= (7 + fdd->inf.xdf.n); + if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && track == 0) { + // BASIC-2HD、track 0用小細工 + seekp /= 2; + } + seekp += fdd->inf.dcp.ptr[track]; +// seekp += fdd->inf.xdf.headersize; + + hdl = file_open_rb(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xe0; + return(FAILURE); + } + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_read(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xe0; + return(FAILURE); + } + file_close(hdl); + } + else { + // ファイル上にデータの存在しないセクタは0xE5で埋めて返す + // ※DCUだと違う? + FillMemory(fdc.buf, secsize, 0xe5); + } +#if 0 + if (fdd->inf.dcp.head.trackmap[track] != 0x01) { +// if (fdd->inf.dcp.ptr[track] == 0) { + // ファイル上にデータの存在しないセクタは0xE5で埋めて返す + // ※DCUだと違う? + FillMemory(fdc.buf, secsize, 0xe5); + } + else { + seekp = fdc.R - 1; + seekp <<= (7 + fdd->inf.xdf.n); + if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && track == 0) { + // BASIC-2HD、track 0用小細工 + seekp /= 2; + } + seekp += fdd->inf.dcp.ptr[track]; + seekp += fdd->inf.xdf.headersize; + + hdl = file_open_rb(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xe0; + return(FAILURE); + } + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_read(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xe0; + return(FAILURE); + } + file_close(hdl); + } +#endif + fdc.bufcnt = secsize; + fddlasterror = 0x00; + return(SUCCESS); +} + +BRESULT makenewtrack_dcp(FDDFILE fdd) { + +#if 1 + FILEH hdl; +// UINT curtrack; + UINT newtrack; + + UINT32 tracksize; + UINT32 length; + UINT size; + UINT rsize; +// int t; + UINT8 tmp[0x0400]; +// UINT32 cur; + + int i; + UINT32 ptr; + UINT32 fdsize; + + if (fdd->protect) { + fddlasterror = 0x70; + return(FAILURE); + } + + hdl = file_open(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xc0; + return(FAILURE); + } + + fdsize = (UINT32)file_getsize(hdl); + + newtrack = (fdc.treg[fdc.us] << 1) + fdc.hd; + tracksize = fdd->inf.xdf.sectors * (128 << fdd->inf.xdf.n); + if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && newtrack == 0) { + tracksize /= 2; + } + // ずらし始めるオフセット取得 + ptr = 0; + for (i = newtrack; i < DCP_TRACKMAX; i++) { + if (fdd->inf.dcp.ptr[i] != 0) { + ptr = fdd->inf.dcp.ptr[i]; + break; + } + } + if (ptr != 0) { +// ptr += fdd->inf.xdf.headersize; + length = fdsize - ptr; + + while(length) { + if (length >= (long)(sizeof(tmp))) { + size = sizeof(tmp); + } + else { + size = length; + } + length -= size; + file_seek(hdl, (FILEPOS)ptr + length, 0); + rsize = file_read(hdl, tmp, size); + file_seek(hdl, (FILEPOS)ptr + length + tracksize, 0); + file_write(hdl, tmp, rsize); + } + + // 各トラックのオフセット再計算 + fdd->inf.dcp.ptr[newtrack] = ptr; + ptr += tracksize; + for (i = newtrack+1; i < DCP_TRACKMAX; i++) { + if (fdd->inf.dcp.ptr[i] != 0) { + fdd->inf.dcp.ptr[i] = ptr; + ptr += tracksize; + } + } + } + else { + if (newtrack >= DCP_TRACKMAX) { + file_close(hdl); + return(FAILURE); + } + fdd->inf.dcp.ptr[newtrack] = fdsize; + } + + file_close(hdl); + + return(SUCCESS); +#else + return(FAILURE); +#endif +} + +BRESULT refreshheader_dcp(FDDFILE fdd) { + + FILEH hdl; + + if (fdd->protect) { + hdl = file_open_rb(fdd->fname); + } else { + hdl = file_open(fdd->fname); + } + if (hdl == FILEH_INVALID) { + fddlasterror = 0xc0; + return(FAILURE); + } + file_seek(hdl, 0, 0); + file_write(hdl, &fdd->inf.dcp.head, DCP_HEADERSIZE); + file_close(hdl); + + return(SUCCESS); +} + + +BRESULT fdd_write_dcp(FDDFILE fdd) { + + FILEH hdl; + UINT track; + UINT secsize; + long seekp; + + fddlasterror = 0x00; + if (fdd_seeksector_common(fdd)) { + fddlasterror = 0xe0; + return(FAILURE); + } + if (fdd->protect) { + fddlasterror = 0x70; + return(FAILURE); + } + if (fdc.N != fdd->inf.xdf.n) { + fddlasterror = 0xc0; + return(FAILURE); + } + /* 170101 ST modified to work on Windows 9x/2000 form ... */ + if (fdc.eot > fdd->inf.xdf.sectors) { + fddlasterror = 0xc0; + return(FAILURE); + } + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + + track = (fdc.treg[fdc.us] << 1) + fdc.hd; + + if ((fdd->type == DISKTYPE_BETA) || + (fdd->type == DISKTYPE_DCP && fdd->inf.dcp.head.trackmap[track] == 0x01) || + (fdd->type == DISKTYPE_DCP && fdd->inf.dcp.head.alltrackflg == 0x01)) { + + secsize = 128 << fdd->inf.xdf.n; + seekp = fdc.R - 1; + seekp <<= (7 + fdd->inf.xdf.n); + if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && track == 0) { + // BASIC-2HD、track 0用小細工 + secsize /= 2; + seekp /= 2; + } + seekp += fdd->inf.dcp.ptr[track]; +// seekp += fdd->inf.xdf.headersize; + + hdl = file_open(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xc0; + return(FAILURE); + } + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_write(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xc0; + return(FAILURE); + } + file_close(hdl); + } + else { + // 新規トラック挿入後、再帰呼び出し + BRESULT r; + r = makenewtrack_dcp(fdd); + if (r != SUCCESS) { + return r; + } + fdd->inf.dcp.head.trackmap[track] = 0x01; + r = refreshheader_dcp(fdd); + if (r != SUCCESS) { + return r; + } + return(fdd_write_dcp(fdd)); + } +#if 0 + if (fdd->inf.dcp.head.trackmap[track] != 0x01) { +// if (fdd->inf.dcp.ptr[track] == 0) { + // データの存在しないトラックはエラーにしとく +// fddlasterror = 0xc0; +// return(FAILURE); + // 新規トラック挿入&ヘッダ部更新後、 + // 再帰呼び出し + BRESULT r; + r = makenewtrack_dcp(fdd); + if (r != SUCCESS) { + return r; + } + // r = refreshheader_dcp(fdd); + // if (r != SUCCESS) { + // return r; + // } + return(fdd_write_dcp(fdd)); + } + + secsize = 128 << fdd->inf.xdf.n; + seekp = fdc.R - 1; + seekp <<= (7 + fdd->inf.xdf.n); + if (fdd->inf.dcp.head.mediatype == DCP_DISK_2HD_BAS && track == 0) { + // BASIC-2HD、track 0用小細工 + secsize /= 2; + seekp /= 2; + } + seekp += fdd->inf.dcp.ptr[track]; + seekp += fdd->inf.xdf.headersize; + + hdl = file_open(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xc0; + return(FAILURE); + } + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_write(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xc0; + return(FAILURE); + } + file_close(hdl); +#endif + fdc.bufcnt = secsize; + fddlasterror = 0x00; + if (fdd->type == DISKTYPE_DCP ) { + if (fdd->inf.dcp.head.trackmap[track] != 0x01) { + fdd->inf.dcp.head.trackmap[track] = 0x01; + refreshheader_dcp(fdd); + } + } + return(SUCCESS); +} + +#endif diff --git a/diskimage/fd/fdd_dcp.h b/diskimage/fd/fdd_dcp.h old mode 100755 new mode 100644 index d9761c17..e6ab0919 --- a/diskimage/fd/fdd_dcp.h +++ b/diskimage/fd/fdd_dcp.h @@ -1,14 +1,14 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT fdd_set_dcp(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); - -BRESULT fdd_read_dcp(FDDFILE fdd); -BRESULT fdd_write_dcp(FDDFILE fdd); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT fdd_set_dcp(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); + +BRESULT fdd_read_dcp(FDDFILE fdd); +BRESULT fdd_write_dcp(FDDFILE fdd); + +#ifdef __cplusplus +} +#endif + diff --git a/diskimage/fd/fdd_head_d88.h b/diskimage/fd/fdd_head_d88.h old mode 100755 new mode 100644 index a5d4416a..7f8895b8 --- a/diskimage/fd/fdd_head_d88.h +++ b/diskimage/fd/fdd_head_d88.h @@ -1,66 +1,66 @@ -#ifndef _FDD_HEAD_D88_H_ -#define _FDD_HEAD_D88_H_ - -enum { - D88_TRACKMAX = 164, - D88_HEADERSIZE = 0x20 + (D88_TRACKMAX * 4) -}; - - -#if defined(__GNUC__) -// D88ヘッダ (size: 2b0h bytes) -typedef struct { - UINT8 fd_name[17]; // Disk Name - UINT8 reserved1[9]; // Reserved - UINT8 protect; // Write Protect bit:4 - UINT8 fd_type; // Disk Format - UINT8 fd_size[4]; // Disk Size - UINT8 trackp[D88_TRACKMAX][4]; -} __attribute__ ((packed)) _D88HEAD, *D88HEAD; - -// D88セクタ (size: 16bytes) -typedef struct { - UINT8 c; - UINT8 h; - UINT8 r; - UINT8 n; - UINT8 sectors[2]; // Sector Count - UINT8 mfm_flg; // sides - UINT8 del_flg; // DELETED DATA - UINT8 stat; // STATUS (FDC ret) - UINT8 seektime; // Seek Time - UINT8 reserved[3]; // Reserved - UINT8 rpm_flg; // rpm 0:1.2 1:1.44 - UINT8 size[2]; // Sector Size -} __attribute__ ((packed)) _D88SEC, *D88SEC; -#else -#pragma pack(push, 1) -// D88ヘッダ (size: 2b0h bytes) -typedef struct { - UINT8 fd_name[17]; // Disk Name - UINT8 reserved1[9]; // Reserved - UINT8 protect; // Write Protect bit:4 - UINT8 fd_type; // Disk Format - UINT8 fd_size[4]; // Disk Size - UINT8 trackp[D88_TRACKMAX][4]; -} _D88HEAD, *D88HEAD; - -// D88セクタ (size: 16bytes) -typedef struct { - UINT8 c; - UINT8 h; - UINT8 r; - UINT8 n; - UINT8 sectors[2]; // Sector Count - UINT8 mfm_flg; // sides - UINT8 del_flg; // DELETED DATA - UINT8 stat; // STATUS (FDC ret) - UINT8 seektime; // Seek Time - UINT8 reserved[3]; // Reserved - UINT8 rpm_flg; // rpm 0:1.2 1:1.44 - UINT8 size[2]; // Sector Size -} _D88SEC, *D88SEC; -#pragma pack(pop) -#endif - -#endif // _FDD_HEAD_D88_H_ +#ifndef _FDD_HEAD_D88_H_ +#define _FDD_HEAD_D88_H_ + +enum { + D88_TRACKMAX = 164, + D88_HEADERSIZE = 0x20 + (D88_TRACKMAX * 4) +}; + + +#if defined(__GNUC__) +// D88ヘッダ (size: 2b0h bytes) +typedef struct { + UINT8 fd_name[17]; // Disk Name + UINT8 reserved1[9]; // Reserved + UINT8 protect; // Write Protect bit:4 + UINT8 fd_type; // Disk Format + UINT8 fd_size[4]; // Disk Size + UINT8 trackp[D88_TRACKMAX][4]; +} __attribute__ ((packed)) _D88HEAD, *D88HEAD; + +// D88セクタ (size: 16bytes) +typedef struct { + UINT8 c; + UINT8 h; + UINT8 r; + UINT8 n; + UINT8 sectors[2]; // Sector Count + UINT8 mfm_flg; // sides + UINT8 del_flg; // DELETED DATA + UINT8 stat; // STATUS (FDC ret) + UINT8 seektime; // Seek Time + UINT8 reserved[3]; // Reserved + UINT8 rpm_flg; // rpm 0:1.2 1:1.44 + UINT8 size[2]; // Sector Size +} __attribute__ ((packed)) _D88SEC, *D88SEC; +#else +#pragma pack(push, 1) +// D88ヘッダ (size: 2b0h bytes) +typedef struct { + UINT8 fd_name[17]; // Disk Name + UINT8 reserved1[9]; // Reserved + UINT8 protect; // Write Protect bit:4 + UINT8 fd_type; // Disk Format + UINT8 fd_size[4]; // Disk Size + UINT8 trackp[D88_TRACKMAX][4]; +} _D88HEAD, *D88HEAD; + +// D88セクタ (size: 16bytes) +typedef struct { + UINT8 c; + UINT8 h; + UINT8 r; + UINT8 n; + UINT8 sectors[2]; // Sector Count + UINT8 mfm_flg; // sides + UINT8 del_flg; // DELETED DATA + UINT8 stat; // STATUS (FDC ret) + UINT8 seektime; // Seek Time + UINT8 reserved[3]; // Reserved + UINT8 rpm_flg; // rpm 0:1.2 1:1.44 + UINT8 size[2]; // Sector Size +} _D88SEC, *D88SEC; +#pragma pack(pop) +#endif + +#endif // _FDD_HEAD_D88_H_ diff --git a/diskimage/fd/fdd_head_dcp.h b/diskimage/fd/fdd_head_dcp.h old mode 100755 new mode 100644 index 2edb8dfc..401328e7 --- a/diskimage/fd/fdd_head_dcp.h +++ b/diskimage/fd/fdd_head_dcp.h @@ -1,37 +1,37 @@ -#ifndef _FDD_HEAD_DCP_H_ -#define _FDD_HEAD_DCP_H_ - -enum { - DCP_TRACKMAX = 160, - DCP_HEADERSIZE = 0x01 + DCP_TRACKMAX + 0x01, - - DCP_DISK_2HD_08 = 0x01, // 2HD- 8セクタ(1.25MB) - DCP_DISK_2HD_15 = 0x02, // 2HD-15セクタ(1.21MB) - DCP_DISK_2HQ_18 = 0x03, // 2HQ-18セクタ(1.44MB) - DCP_DISK_2DD_08 = 0x04, // 2DD- 8セクタ( 640KB) - DCP_DISK_2DD_09 = 0x05, // 2DD- 9セクタ( 720KB) - DCP_DISK_2HD_09 = 0x08, // 2HD- 9セクタ(1.44MB) - DCP_DISK_2HD_BAS = 0x11, // 2HD-BASIC - DCP_DISK_2DD_BAS = 0x19, // 2DD-BASIC - DCP_DISK_2HD_26 = 0x21 // 2HD-26セクタ -}; - -#if defined(__GNUC__) -// DCPヘッダ (size: a2h bytes) -typedef struct { - UINT8 mediatype; - UINT8 trackmap[DCP_TRACKMAX]; - UINT8 alltrackflg; -} __attribute__ ((packed)) _DCPHEAD, *DCPHEAD; -#else -#pragma pack(push, 1) -// DCPヘッダ (size: a2h bytes) -typedef struct { - UINT8 mediatype; - UINT8 trackmap[DCP_TRACKMAX]; - UINT8 alltrackflg; -} _DCPHEAD, *DCPHEAD; -#pragma pack(pop) -#endif - -#endif // _FDD_HEAD_DCP_H_ +#ifndef _FDD_HEAD_DCP_H_ +#define _FDD_HEAD_DCP_H_ + +enum { + DCP_TRACKMAX = 160, + DCP_HEADERSIZE = 0x01 + DCP_TRACKMAX + 0x01, + + DCP_DISK_2HD_08 = 0x01, // 2HD- 8セクタ(1.25MB) + DCP_DISK_2HD_15 = 0x02, // 2HD-15セクタ(1.21MB) + DCP_DISK_2HQ_18 = 0x03, // 2HQ-18セクタ(1.44MB) + DCP_DISK_2DD_08 = 0x04, // 2DD- 8セクタ( 640KB) + DCP_DISK_2DD_09 = 0x05, // 2DD- 9セクタ( 720KB) + DCP_DISK_2HD_09 = 0x08, // 2HD- 9セクタ(1.44MB) + DCP_DISK_2HD_BAS = 0x11, // 2HD-BASIC + DCP_DISK_2DD_BAS = 0x19, // 2DD-BASIC + DCP_DISK_2HD_26 = 0x21 // 2HD-26セクタ +}; + +#if defined(__GNUC__) +// DCPヘッダ (size: a2h bytes) +typedef struct { + UINT8 mediatype; + UINT8 trackmap[DCP_TRACKMAX]; + UINT8 alltrackflg; +} __attribute__ ((packed)) _DCPHEAD, *DCPHEAD; +#else +#pragma pack(push, 1) +// DCPヘッダ (size: a2h bytes) +typedef struct { + UINT8 mediatype; + UINT8 trackmap[DCP_TRACKMAX]; + UINT8 alltrackflg; +} _DCPHEAD, *DCPHEAD; +#pragma pack(pop) +#endif + +#endif // _FDD_HEAD_DCP_H_ diff --git a/diskimage/fd/fdd_head_nfd.h b/diskimage/fd/fdd_head_nfd.h old mode 100755 new mode 100644 index 16da2ca7..1c80a690 --- a/diskimage/fd/fdd_head_nfd.h +++ b/diskimage/fd/fdd_head_nfd.h @@ -1,188 +1,188 @@ -#ifndef _FDD_HEAD_NFD_H_ -#define _FDD_HEAD_NFD_H_ - -enum { - NFD_TRKMAX = 163, - NFD_TRKMAX1 = 164, - NFD_SECMAX = 26, - NFD_HEADERSIZE = 288 + (16 * NFD_TRKMAX * NFD_SECMAX) + 0x10, - NFD_HEADERSIZE1 = 288 + (16 * NFD_TRKMAX * NFD_SECMAX) + 0x10, -}; - -#if defined(__GNUC__) -// セクタID -typedef struct { - BYTE C; // C(0xFFの時セクタ無し) - BYTE H; // H - BYTE R; // R - BYTE N; // N - BYTE flMFM; // 0:FM / 1:MFM - BYTE flDDAM; // 0:DAM / 1:DDAM - BYTE byStatus; // READ DATA(FDDBIOS)の結果 - BYTE byST0; // READ DATA(FDDBIOS)の結果 ST0 - BYTE byST1; // READ DATA(FDDBIOS)の結果 ST1 - BYTE byST2; // READ DATA(FDDBIOS)の結果 ST2 - BYTE byPDA; // FDDBIOSで使用するアドレス - char Reserve1[5]; // 予約 -} __attribute__ ((packed)) NFD_SECT_ID, *LP_NFD_SECT_ID; - -// nfdヘッダ(r0) -typedef struct { - char szFileID[15]; // 識別ID "T98FDDIMAGE.R0" - char Reserve1[1]; // 予約 - char szComment[0x100]; // イメージコメント(ASCIIz) - DWORD dwHeadSize; // ヘッダ部のサイズ - BYTE flProtect; // 0以外 : ライトプロテクト - BYTE byHead; // ヘッド数 - char Reserve2[10]; // 予約 - NFD_SECT_ID si[NFD_TRKMAX][NFD_SECMAX]; // セクタID - char Reserve3[0x10]; // 予約 -} __attribute__ ((packed)) NFD_FILE_HEAD, *LP_NFD_FILE_HEAD; - -// nfdヘッダ(r1) -typedef struct { -// char szFileID[sizeof(NFD_FILE_ID1)]; // 識別ID "T98FDDIMAGE.R1" -// char Reserv1[0x10-sizeof(NFD_FILE_ID1)]; // 予備 - char szFileID[15]; // 識別ID "T98FDDIMAGE.R1" - char Reserv1[1]; // 予備 - char szComment[0x100]; // コメント - DWORD dwHeadSize; // ヘッダのサイズ - BYTE flProtect; // ライトプロテクト0以外 - BYTE byHead; // ヘッド数 1-2 - char Reserv2[0x10-4-1-1]; // 予備 - DWORD dwTrackHead[NFD_TRKMAX1]; // トラックID位置 - DWORD dwAddInfo; // 追加情報ヘッダのアドレス - char Reserv3[0x10-4]; // 予備 -} __attribute__ ((packed)) NFD_FILE_HEAD1, *LP_NFD_FILE_HEAD1; - -// トラックID -typedef struct { - WORD wSector; // セクタID数 - WORD wDiag; // 特 殊ID数 - char Reserv1[0x10-4]; // 予備 -} __attribute__ ((packed)) NFD_TRACK_ID1, *LP_NFD_TRACK_ID1; - -// セクタ情報ヘッダ -typedef struct { - BYTE C; // C - BYTE H; // H - BYTE R; // R - BYTE N; // N - BYTE flMFM; // MFM(1)/FM(0) - BYTE flDDAM; // DDAM(1)/DAM(0) - BYTE byStatus; // READ DATA RESULT - BYTE bySTS0; // ST0 - BYTE bySTS1; // ST1 - BYTE bySTS2; // ST2 - BYTE byRetry; // RetryDataなし(0)あり(1-) - BYTE byPDA; // PDA - char Reserv1[0x10-12]; // 予備 -} __attribute__ ((packed)) NFD_SECT_ID1, *LP_NFD_SECT_ID1; - -// 特殊読み込み情報ヘッダ -typedef struct { - BYTE Cmd; // Command - BYTE C; // C - BYTE H; // H - BYTE R; // R - BYTE N; // N - BYTE byStatus; // READ DATA RESULT - BYTE bySTS0; // ST0 - BYTE bySTS1; // ST1 - BYTE bySTS2; // ST2 - BYTE byRetry; // RetryDataなし(0)あり(1-) - DWORD dwDataLen; // 転送を行うデータサイズ - BYTE byPDA; // PDA - char Reserv1[0x10-15]; // 予備 -} __attribute__ ((packed)) NFD_DIAG_ID1, *LP_NFD_DIAG_ID1; -#else -#pragma pack(push, 1) -// セクタID -typedef struct { - BYTE C; // C(0xFFの時セクタ無し) - BYTE H; // H - BYTE R; // R - BYTE N; // N - BYTE flMFM; // 0:FM / 1:MFM - BYTE flDDAM; // 0:DAM / 1:DDAM - BYTE byStatus; // READ DATA(FDDBIOS)の結果 - BYTE byST0; // READ DATA(FDDBIOS)の結果 ST0 - BYTE byST1; // READ DATA(FDDBIOS)の結果 ST1 - BYTE byST2; // READ DATA(FDDBIOS)の結果 ST2 - BYTE byPDA; // FDDBIOSで使用するアドレス - char Reserve1[5]; // 予約 -} NFD_SECT_ID, *LP_NFD_SECT_ID; - -// nfdヘッダ(r0) -typedef struct { - char szFileID[15]; // 識別ID "T98FDDIMAGE.R0" - char Reserve1[1]; // 予約 - char szComment[0x100]; // イメージコメント(ASCIIz) - DWORD dwHeadSize; // ヘッダ部のサイズ - BYTE flProtect; // 0以外 : ライトプロテクト - BYTE byHead; // ヘッド数 - char Reserve2[10]; // 予約 - NFD_SECT_ID si[NFD_TRKMAX][NFD_SECMAX]; // セクタID - char Reserve3[0x10]; // 予約 -} NFD_FILE_HEAD, *LP_NFD_FILE_HEAD; - -// nfdヘッダ(r1) -typedef struct { -// char szFileID[sizeof(NFD_FILE_ID1)]; // 識別ID "T98FDDIMAGE.R1" -// char Reserv1[0x10-sizeof(NFD_FILE_ID1)]; // 予備 - char szFileID[15]; // 識別ID "T98FDDIMAGE.R1" - char Reserv1[1]; // 予備 - char szComment[0x100]; // コメント - DWORD dwHeadSize; // ヘッダのサイズ - BYTE flProtect; // ライトプロテクト0以外 - BYTE byHead; // ヘッド数 1-2 - char Reserv2[0x10-4-1-1]; // 予備 - DWORD dwTrackHead[NFD_TRKMAX1]; // トラックID位置 - DWORD dwAddInfo; // 追加情報ヘッダのアドレス - char Reserv3[0x10-4]; // 予備 -} NFD_FILE_HEAD1, *LP_NFD_FILE_HEAD1; - -// トラックID -typedef struct { - WORD wSector; // セクタID数 - WORD wDiag; // 特 殊ID数 - char Reserv1[0x10-4]; // 予備 -} NFD_TRACK_ID1, *LP_NFD_TRACK_ID1; - -// セクタ情報ヘッダ -typedef struct { - BYTE C; // C - BYTE H; // H - BYTE R; // R - BYTE N; // N - BYTE flMFM; // MFM(1)/FM(0) - BYTE flDDAM; // DDAM(1)/DAM(0) - BYTE byStatus; // READ DATA RESULT - BYTE bySTS0; // ST0 - BYTE bySTS1; // ST1 - BYTE bySTS2; // ST2 - BYTE byRetry; // RetryDataなし(0)あり(1-) - BYTE byPDA; // PDA - char Reserv1[0x10-12]; // 予備 -} NFD_SECT_ID1, *LP_NFD_SECT_ID1; - -// 特殊読み込み情報ヘッダ -typedef struct { - BYTE Cmd; // Command - BYTE C; // C - BYTE H; // H - BYTE R; // R - BYTE N; // N - BYTE byStatus; // READ DATA RESULT - BYTE bySTS0; // ST0 - BYTE bySTS1; // ST1 - BYTE bySTS2; // ST2 - BYTE byRetry; // RetryDataなし(0)あり(1-) - DWORD dwDataLen; // 転送を行うデータサイズ - BYTE byPDA; // PDA - char Reserv1[0x10-15]; // 予備 -} NFD_DIAG_ID1, *LP_NFD_DIAG_ID1; -#pragma pack(pop) -#endif - -#endif // _FDD_HEAD_NFD_H_ +#ifndef _FDD_HEAD_NFD_H_ +#define _FDD_HEAD_NFD_H_ + +enum { + NFD_TRKMAX = 163, + NFD_TRKMAX1 = 164, + NFD_SECMAX = 26, + NFD_HEADERSIZE = 288 + (16 * NFD_TRKMAX * NFD_SECMAX) + 0x10, + NFD_HEADERSIZE1 = 288 + (16 * NFD_TRKMAX * NFD_SECMAX) + 0x10, +}; + +#if defined(__GNUC__) +// セクタID +typedef struct { + BYTE C; // C(0xFFの時セクタ無し) + BYTE H; // H + BYTE R; // R + BYTE N; // N + BYTE flMFM; // 0:FM / 1:MFM + BYTE flDDAM; // 0:DAM / 1:DDAM + BYTE byStatus; // READ DATA(FDDBIOS)の結果 + BYTE byST0; // READ DATA(FDDBIOS)の結果 ST0 + BYTE byST1; // READ DATA(FDDBIOS)の結果 ST1 + BYTE byST2; // READ DATA(FDDBIOS)の結果 ST2 + BYTE byPDA; // FDDBIOSで使用するアドレス + char Reserve1[5]; // 予約 +} __attribute__ ((packed)) NFD_SECT_ID, *LP_NFD_SECT_ID; + +// nfdヘッダ(r0) +typedef struct { + char szFileID[15]; // 識別ID "T98FDDIMAGE.R0" + char Reserve1[1]; // 予約 + char szComment[0x100]; // イメージコメント(ASCIIz) + DWORD dwHeadSize; // ヘッダ部のサイズ + BYTE flProtect; // 0以外 : ライトプロテクト + BYTE byHead; // ヘッド数 + char Reserve2[10]; // 予約 + NFD_SECT_ID si[NFD_TRKMAX][NFD_SECMAX]; // セクタID + char Reserve3[0x10]; // 予約 +} __attribute__ ((packed)) NFD_FILE_HEAD, *LP_NFD_FILE_HEAD; + +// nfdヘッダ(r1) +typedef struct { +// char szFileID[sizeof(NFD_FILE_ID1)]; // 識別ID "T98FDDIMAGE.R1" +// char Reserv1[0x10-sizeof(NFD_FILE_ID1)]; // 予備 + char szFileID[15]; // 識別ID "T98FDDIMAGE.R1" + char Reserv1[1]; // 予備 + char szComment[0x100]; // コメント + DWORD dwHeadSize; // ヘッダのサイズ + BYTE flProtect; // ライトプロテクト0以外 + BYTE byHead; // ヘッド数 1-2 + char Reserv2[0x10-4-1-1]; // 予備 + DWORD dwTrackHead[NFD_TRKMAX1]; // トラックID位置 + DWORD dwAddInfo; // 追加情報ヘッダのアドレス + char Reserv3[0x10-4]; // 予備 +} __attribute__ ((packed)) NFD_FILE_HEAD1, *LP_NFD_FILE_HEAD1; + +// トラックID +typedef struct { + WORD wSector; // セクタID数 + WORD wDiag; // 特 殊ID数 + char Reserv1[0x10-4]; // 予備 +} __attribute__ ((packed)) NFD_TRACK_ID1, *LP_NFD_TRACK_ID1; + +// セクタ情報ヘッダ +typedef struct { + BYTE C; // C + BYTE H; // H + BYTE R; // R + BYTE N; // N + BYTE flMFM; // MFM(1)/FM(0) + BYTE flDDAM; // DDAM(1)/DAM(0) + BYTE byStatus; // READ DATA RESULT + BYTE bySTS0; // ST0 + BYTE bySTS1; // ST1 + BYTE bySTS2; // ST2 + BYTE byRetry; // RetryDataなし(0)あり(1-) + BYTE byPDA; // PDA + char Reserv1[0x10-12]; // 予備 +} __attribute__ ((packed)) NFD_SECT_ID1, *LP_NFD_SECT_ID1; + +// 特殊読み込み情報ヘッダ +typedef struct { + BYTE Cmd; // Command + BYTE C; // C + BYTE H; // H + BYTE R; // R + BYTE N; // N + BYTE byStatus; // READ DATA RESULT + BYTE bySTS0; // ST0 + BYTE bySTS1; // ST1 + BYTE bySTS2; // ST2 + BYTE byRetry; // RetryDataなし(0)あり(1-) + DWORD dwDataLen; // 転送を行うデータサイズ + BYTE byPDA; // PDA + char Reserv1[0x10-15]; // 予備 +} __attribute__ ((packed)) NFD_DIAG_ID1, *LP_NFD_DIAG_ID1; +#else +#pragma pack(push, 1) +// セクタID +typedef struct { + BYTE C; // C(0xFFの時セクタ無し) + BYTE H; // H + BYTE R; // R + BYTE N; // N + BYTE flMFM; // 0:FM / 1:MFM + BYTE flDDAM; // 0:DAM / 1:DDAM + BYTE byStatus; // READ DATA(FDDBIOS)の結果 + BYTE byST0; // READ DATA(FDDBIOS)の結果 ST0 + BYTE byST1; // READ DATA(FDDBIOS)の結果 ST1 + BYTE byST2; // READ DATA(FDDBIOS)の結果 ST2 + BYTE byPDA; // FDDBIOSで使用するアドレス + char Reserve1[5]; // 予約 +} NFD_SECT_ID, *LP_NFD_SECT_ID; + +// nfdヘッダ(r0) +typedef struct { + char szFileID[15]; // 識別ID "T98FDDIMAGE.R0" + char Reserve1[1]; // 予約 + char szComment[0x100]; // イメージコメント(ASCIIz) + DWORD dwHeadSize; // ヘッダ部のサイズ + BYTE flProtect; // 0以外 : ライトプロテクト + BYTE byHead; // ヘッド数 + char Reserve2[10]; // 予約 + NFD_SECT_ID si[NFD_TRKMAX][NFD_SECMAX]; // セクタID + char Reserve3[0x10]; // 予約 +} NFD_FILE_HEAD, *LP_NFD_FILE_HEAD; + +// nfdヘッダ(r1) +typedef struct { +// char szFileID[sizeof(NFD_FILE_ID1)]; // 識別ID "T98FDDIMAGE.R1" +// char Reserv1[0x10-sizeof(NFD_FILE_ID1)]; // 予備 + char szFileID[15]; // 識別ID "T98FDDIMAGE.R1" + char Reserv1[1]; // 予備 + char szComment[0x100]; // コメント + DWORD dwHeadSize; // ヘッダのサイズ + BYTE flProtect; // ライトプロテクト0以外 + BYTE byHead; // ヘッド数 1-2 + char Reserv2[0x10-4-1-1]; // 予備 + DWORD dwTrackHead[NFD_TRKMAX1]; // トラックID位置 + DWORD dwAddInfo; // 追加情報ヘッダのアドレス + char Reserv3[0x10-4]; // 予備 +} NFD_FILE_HEAD1, *LP_NFD_FILE_HEAD1; + +// トラックID +typedef struct { + WORD wSector; // セクタID数 + WORD wDiag; // 特 殊ID数 + char Reserv1[0x10-4]; // 予備 +} NFD_TRACK_ID1, *LP_NFD_TRACK_ID1; + +// セクタ情報ヘッダ +typedef struct { + BYTE C; // C + BYTE H; // H + BYTE R; // R + BYTE N; // N + BYTE flMFM; // MFM(1)/FM(0) + BYTE flDDAM; // DDAM(1)/DAM(0) + BYTE byStatus; // READ DATA RESULT + BYTE bySTS0; // ST0 + BYTE bySTS1; // ST1 + BYTE bySTS2; // ST2 + BYTE byRetry; // RetryDataなし(0)あり(1-) + BYTE byPDA; // PDA + char Reserv1[0x10-12]; // 予備 +} NFD_SECT_ID1, *LP_NFD_SECT_ID1; + +// 特殊読み込み情報ヘッダ +typedef struct { + BYTE Cmd; // Command + BYTE C; // C + BYTE H; // H + BYTE R; // R + BYTE N; // N + BYTE byStatus; // READ DATA RESULT + BYTE bySTS0; // ST0 + BYTE bySTS1; // ST1 + BYTE bySTS2; // ST2 + BYTE byRetry; // RetryDataなし(0)あり(1-) + DWORD dwDataLen; // 転送を行うデータサイズ + BYTE byPDA; // PDA + char Reserv1[0x10-15]; // 予備 +} NFD_DIAG_ID1, *LP_NFD_DIAG_ID1; +#pragma pack(pop) +#endif + +#endif // _FDD_HEAD_NFD_H_ diff --git a/diskimage/fd/fdd_head_vfdd.h b/diskimage/fd/fdd_head_vfdd.h old mode 100755 new mode 100644 index 2e73eea5..f1266acb --- a/diskimage/fd/fdd_head_vfdd.h +++ b/diskimage/fd/fdd_head_vfdd.h @@ -1,94 +1,94 @@ -#ifndef _FDD_HEAD_VFDD_H_ -#define _FDD_HEAD_VFDD_H_ - -enum { - VFDD_TRKMAX = 160, - VFDD_SECMAX = 26, - VFDD_HEADERSIZE = 220 + (12 * VFDD_TRKMAX * VFDD_SECMAX) + 32, -}; - -#if defined(__GNUC__) -// 仮想FDDヘッダー部 -typedef struct { - SINT8 verID[8]; // バージョンを表すID - SINT8 memo[128]; // ディスクメモ - SINT16 write_protect; // 書き込み禁止 - SINT16 spdrv; // 特殊読み込みドライブ - SINT8 dmy[80]; // 予約領域 -} __attribute__ ((packed)) _VFDD_HEAD, *VFDD_HEAD; - -// 仮想FDDのIDデータ -typedef struct { - UINT8 C; // C シリンダ番号 - UINT8 H; // H サーフェース番号 - UINT8 R; // R セクタ番号 - UINT8 N; // N セクタ長 - UINT8 D; // D データパターン - UINT8 DDAM; // DDAM デリーテッドデータフラグ - UINT8 flMF; // MF 倍密度フラグ - UINT8 flHD; // 2HDフラグ - SINT32 dataPoint; // データへのファイルポインタ -} __attribute__ ((packed)) _VFDD_ID, *VFDD_ID; - -/* 特殊読み込み時のデータ */ -typedef struct { - SINT16 trk; // 現在のトラック位置 - UINT16 iax; // 入力レジスタの値 - UINT16 ibx; - UINT16 icx; - UINT16 idx; - UINT16 oax; // 出力レジスタの値 - UINT16 obx; - UINT16 ocx; - UINT16 odx; - UINT16 ofl; - SINT32 dataPoint; // データへのファイルポインタ - SINT32 nextPoint; // 次のデータへのファイルポインタ - SINT16 count; // 特殊読み込みカウンタ - SINT16 neg_count; // カウント無視フラグ -} __attribute__ ((packed)) _VFDD_SP, *VFDD_SP; -#else -#pragma pack(push, 1) -// 仮想FDDヘッダー部 -typedef struct { - SINT8 verID[8]; // バージョンを表すID - SINT8 memo[128]; // ディスクメモ - SINT16 write_protect; // 書き込み禁止 - SINT16 spdrv; // 特殊読み込みドライブ - SINT8 dmy[80]; // 予約領域 -} _VFDD_HEAD, *VFDD_HEAD; - -// 仮想FDDのIDデータ -typedef struct { - UINT8 C; // C シリンダ番号 - UINT8 H; // H サーフェース番号 - UINT8 R; // R セクタ番号 - UINT8 N; // N セクタ長 - UINT8 D; // D データパターン - UINT8 DDAM; // DDAM デリーテッドデータフラグ - UINT8 flMF; // MF 倍密度フラグ - UINT8 flHD; // 2HDフラグ - SINT32 dataPoint; // データへのファイルポインタ -} _VFDD_ID, *VFDD_ID; - -/* 特殊読み込み時のデータ */ -typedef struct { - SINT16 trk; // 現在のトラック位置 - UINT16 iax; // 入力レジスタの値 - UINT16 ibx; - UINT16 icx; - UINT16 idx; - UINT16 oax; // 出力レジスタの値 - UINT16 obx; - UINT16 ocx; - UINT16 odx; - UINT16 ofl; - SINT32 dataPoint; // データへのファイルポインタ - SINT32 nextPoint; // 次のデータへのファイルポインタ - SINT16 count; // 特殊読み込みカウンタ - SINT16 neg_count; // カウント無視フラグ -} _VFDD_SP, *VFDD_SP; -#pragma pack(pop) -#endif - -#endif // _FDD_HEAD_VFDD_H_ +#ifndef _FDD_HEAD_VFDD_H_ +#define _FDD_HEAD_VFDD_H_ + +enum { + VFDD_TRKMAX = 160, + VFDD_SECMAX = 26, + VFDD_HEADERSIZE = 220 + (12 * VFDD_TRKMAX * VFDD_SECMAX) + 32, +}; + +#if defined(__GNUC__) +// 仮想FDDヘッダー部 +typedef struct { + SINT8 verID[8]; // バージョンを表すID + SINT8 memo[128]; // ディスクメモ + SINT16 write_protect; // 書き込み禁止 + SINT16 spdrv; // 特殊読み込みドライブ + SINT8 dmy[80]; // 予約領域 +} __attribute__ ((packed)) _VFDD_HEAD, *VFDD_HEAD; + +// 仮想FDDのIDデータ +typedef struct { + UINT8 C; // C シリンダ番号 + UINT8 H; // H サーフェース番号 + UINT8 R; // R セクタ番号 + UINT8 N; // N セクタ長 + UINT8 D; // D データパターン + UINT8 DDAM; // DDAM デリーテッドデータフラグ + UINT8 flMF; // MF 倍密度フラグ + UINT8 flHD; // 2HDフラグ + SINT32 dataPoint; // データへのファイルポインタ +} __attribute__ ((packed)) _VFDD_ID, *VFDD_ID; + +/* 特殊読み込み時のデータ */ +typedef struct { + SINT16 trk; // 現在のトラック位置 + UINT16 iax; // 入力レジスタの値 + UINT16 ibx; + UINT16 icx; + UINT16 idx; + UINT16 oax; // 出力レジスタの値 + UINT16 obx; + UINT16 ocx; + UINT16 odx; + UINT16 ofl; + SINT32 dataPoint; // データへのファイルポインタ + SINT32 nextPoint; // 次のデータへのファイルポインタ + SINT16 count; // 特殊読み込みカウンタ + SINT16 neg_count; // カウント無視フラグ +} __attribute__ ((packed)) _VFDD_SP, *VFDD_SP; +#else +#pragma pack(push, 1) +// 仮想FDDヘッダー部 +typedef struct { + SINT8 verID[8]; // バージョンを表すID + SINT8 memo[128]; // ディスクメモ + SINT16 write_protect; // 書き込み禁止 + SINT16 spdrv; // 特殊読み込みドライブ + SINT8 dmy[80]; // 予約領域 +} _VFDD_HEAD, *VFDD_HEAD; + +// 仮想FDDのIDデータ +typedef struct { + UINT8 C; // C シリンダ番号 + UINT8 H; // H サーフェース番号 + UINT8 R; // R セクタ番号 + UINT8 N; // N セクタ長 + UINT8 D; // D データパターン + UINT8 DDAM; // DDAM デリーテッドデータフラグ + UINT8 flMF; // MF 倍密度フラグ + UINT8 flHD; // 2HDフラグ + SINT32 dataPoint; // データへのファイルポインタ +} _VFDD_ID, *VFDD_ID; + +/* 特殊読み込み時のデータ */ +typedef struct { + SINT16 trk; // 現在のトラック位置 + UINT16 iax; // 入力レジスタの値 + UINT16 ibx; + UINT16 icx; + UINT16 idx; + UINT16 oax; // 出力レジスタの値 + UINT16 obx; + UINT16 ocx; + UINT16 odx; + UINT16 ofl; + SINT32 dataPoint; // データへのファイルポインタ + SINT32 nextPoint; // 次のデータへのファイルポインタ + SINT16 count; // 特殊読み込みカウンタ + SINT16 neg_count; // カウント無視フラグ +} _VFDD_SP, *VFDD_SP; +#pragma pack(pop) +#endif + +#endif // _FDD_HEAD_VFDD_H_ diff --git a/diskimage/fd/fdd_nfd.c b/diskimage/fd/fdd_nfd.c old mode 100755 new mode 100644 index 1b9994fb..0a41778b --- a/diskimage/fd/fdd_nfd.c +++ b/diskimage/fd/fdd_nfd.c @@ -1,971 +1,971 @@ -#include -#include -#include -#include - -#ifdef SUPPORT_KAI_IMAGES - -#include -#include "diskimage/fd/fdd_nfd.h" - -static const UINT8 nfd_FileID_r0[15] = - {'T','9','8','F','D','D','I','M','A','G','E','.','R','0',0x00}; -static const UINT8 nfd_FileID_r1[15] = - {'T','9','8','F','D','D','I','M','A','G','E','.','R','1',0x00}; - -BRESULT fdd_set_nfd(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { - - short attr; - FILEH fh; - UINT rsize; - UINT32 ptr; - UINT i; - UINT j; - - attr = file_attr(fname); - if (attr & 0x18) { - return(FAILURE); - } - if(!ro) { - if(attr & FILEATTR_READONLY) { - ro = 1; - } - } - if(ro) { - fh = file_open_rb(fname); - } else { - fh = file_open(fname); - } - if (fh == FILEH_INVALID) { - return(FAILURE); - } - rsize = file_read(fh, &fdd->inf.nfd.head, NFD_HEADERSIZE); // nfdヘッダ読込(とりあえずr0で) - file_close(fh); - if (rsize != NFD_HEADERSIZE) { - return(FAILURE); - } - - // 識別IDチェック - if (memcmp(fdd->inf.nfd.head.r0.szFileID, nfd_FileID_r0, 15) == 0) { - // NFD r0形式 - const NFD_SECT_ID *sec_nfd; - - fdd->type = DISKTYPE_NFD; - fdd->protect = ((attr & 0x01) || (ro)) ? TRUE : FALSE; - if (fdd->inf.nfd.head.r0.flProtect) { - fdd->protect = TRUE; - } - - /* 170101 ST modified to work on Windows 9x/2000 from ... */ - // 最大値入れて平気? - // fdd->inf.xdf.tracks = NFD_TRKMAX; - // fdd->inf.xdf.sectors = NFD_SECMAX; - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - - // 期待した値が入ってないことが…orz - ptr = LOADINTELDWORD(&fdd->inf.nfd.head.r0.dwHeadSize); -// ptr = NFD_HEADERSIZE; -//TRACEOUT(("NFD(r0) TopSec Offset[%08x]", ptr)); - // 先頭格納セクタを見て決め打ち - // …2DD/2HD混在フォーマットでまずい気がする - sec_nfd = &fdd->inf.nfd.head.r0.si[0][0]; -//TRACEOUT(("NFD(r0) TopSec PDA[%02x]", sec_nfd->byPDA)); - switch (sec_nfd->byPDA) { - case 0x10: // 640K - fdd->inf.xdf.disktype = DISKTYPE_2DD; - fdd->inf.xdf.rpm = 0; - break; - case 0x30: // 1.44M - fdd->inf.xdf.disktype = DISKTYPE_2HD; - fdd->inf.xdf.rpm = 1; - break; - case 0x90: // 1.2M - fdd->inf.xdf.disktype = DISKTYPE_2HD; - fdd->inf.xdf.rpm = 0; - break; - default: - return(FAILURE); - break; - } - /* 170101 ST modified to work on Windows 9x/2000 from ... */ - fdd->inf.xdf.tracks = 0; - fdd->inf.xdf.sectors = 0; - ZeroMemory(fdd->inf.nfd.ptr, sizeof(fdd->inf.nfd.ptr)); - fdd->inf.xdf.headersize = ptr; - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - // ディスクアクセス時用に各セクタのオフセットを算出し格納 - for (i = 0; i < NFD_TRKMAX; i++) { - for (j = 0; j < NFD_SECMAX; j++) { -TRACEOUT(("NFD(r0) C[%02x]:H[%02x]:R[%02x]:N[%02x]", - sec_nfd->C, sec_nfd->H, sec_nfd->R, sec_nfd->N)); - if (sec_nfd->C != 0xff) { -TRACEOUT(("\tSetOffset Trk[%03d]Sec[%02x] = Offset[%08x]", i, j, ptr)); - fdd->inf.nfd.ptr[i][j] = ptr; - ptr += 128 << sec_nfd->N; - /* 170101 ST modified to work on Windows 9x/2000 from ... */ - fdd->inf.xdf.tracks = i; - if (fdd->inf.xdf.sectors < j) { - fdd->inf.xdf.sectors = j; - } - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - } - sec_nfd++; - } - } - /* 170101 ST modified to work on Windows 9x/2000 from ... */ - fdd->inf.xdf.tracks++; - fdd->inf.xdf.sectors++; - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - - // 処理関数群を登録 - fdd_fn->eject = fdd_eject_xxx; - fdd_fn->diskaccess = fdd_diskaccess_common; - fdd_fn->seek = fdd_seek_common; - fdd_fn->seeksector = fdd_seeksector_nfd; // 変更(kaiE) - fdd_fn->read = fdd_read_nfd; - fdd_fn->write = fdd_write_nfd; - fdd_fn->readid = fdd_readid_nfd; - fdd_fn->writeid = fdd_dummy_xxx; - fdd_fn->formatinit = fdd_formatinit_nfd; /* 170107 to support format command */ - fdd_fn->formating = fdd_formating_xxx; - fdd_fn->isformating = fdd_isformating_xxx; - fdd_fn->fdcresult = TRUE; - } - else if (memcmp(fdd->inf.nfd.head.r1.szFileID, nfd_FileID_r1, 15) == 0) { - // NFD r1形式 - NFD_TRACK_ID1 trk_id; - NFD_SECT_ID1 sec_id; - NFD_DIAG_ID1 dia_id; - UINT32 trksize; - -TRACEOUT(("This is NFD(r1) IMAGE!")); - // ヘッダ再読込 - if(fdd->protect) { - fh = file_open_rb(fname); - } else { - fh = file_open(fname); - } - if (fh == FILEH_INVALID) { - return(FAILURE); - } - rsize = file_read(fh, &fdd->inf.nfd.head, sizeof(NFD_FILE_HEAD1)); - - fdd->type = DISKTYPE_NFD; - fdd->protect = ((attr & 0x01) || (ro)) ? TRUE : FALSE; - if (fdd->inf.nfd.head.r1.flProtect) { - fdd->protect = TRUE; - } - - /* 170101 ST modified to work on Windows 9x/2000 from ... */ - // 最大値入れて平気? - //fdd->inf.xdf.tracks = NFD_TRKMAX; - //fdd->inf.xdf.sectors = NFD_SECMAX; - /* 170101 modified to work on Windows 9x/2000 ... to */ - - ptr = LOADINTELDWORD(&fdd->inf.nfd.head.r1.dwHeadSize); - /* 170107 modified to work on Windows 9x/2000 from ... */ - fdd->inf.xdf.tracks = 0; - fdd->inf.xdf.sectors = 0; - ZeroMemory(fdd->inf.nfd.ptr, sizeof(fdd->inf.nfd.ptr)); - fdd->inf.xdf.headersize = ptr; - /* 170107 modified to work on Windows 9x/2000 ... to */ - for (i = 0; i < NFD_TRKMAX1; i++) { - // トラック情報ヘッダ読込 - /* 170107 modified to work on Windows 9x/2000 from ... */ - if (LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[i])) == 0) { - continue; - } - /* 170107 modified to work on Windows 9x/2000 ... to */ - if ((file_seek(fh, LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[i])), FSEEK_SET) != LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[i]))) || - (file_read(fh, &trk_id, sizeof(NFD_TRACK_ID1)) != sizeof(NFD_TRACK_ID1))) { - file_close(fh); - return(FAILURE); - } - trksize = 0; - // セクタ情報ヘッダ読込 - for (j = 0; j < LOADINTELWORD(&(trk_id.wSector)); j++) { - file_read(fh, &sec_id, sizeof(NFD_SECT_ID1)); -// if (sec_id.R < NFD_SECMAX) { - fdd->inf.nfd.ptr[i][sec_id.R - 1] = ptr; -// fdd->inf.nfd.ptr[i][j] = ptr; -// } - ptr += 128 << sec_id.N; - trksize += 128 << sec_id.N; - if (sec_id.byRetry > 0) { - ptr += (128 << sec_id.N) * sec_id.byRetry; - trksize += (128 << sec_id.N) * sec_id.byRetry; - } - if (i == 0 && j == 0) { - // 先頭格納セクタを見て決め打ち - // …2DD/2HD混在フォーマットでまずい気がする -TRACEOUT(("NFD(r1) TopSec PDA[%02x]", sec_id.byPDA)); - switch (sec_id.byPDA) { - case 0x10: // 640K - fdd->inf.xdf.disktype = DISKTYPE_2DD; - fdd->inf.xdf.rpm = 0; - break; - case 0x30: // 1.44M - fdd->inf.xdf.disktype = DISKTYPE_2HD; - fdd->inf.xdf.rpm = 1; - break; - case 0x00: // 1.2M…? - case 0x90: // 1.2M - fdd->inf.xdf.disktype = DISKTYPE_2HD; - fdd->inf.xdf.rpm = 0; - break; - default: - file_close(fh); - return(FAILURE); - break; - } - } - } - fdd->inf.nfd.trksize[i] = trksize; - // 特殊読み込み情報ヘッダ読込 - for (j = 0; j < LOADINTELWORD(&(trk_id.wDiag)); j++) { - file_read(fh, &dia_id, sizeof(NFD_DIAG_ID1)); - ptr += LOADINTELDWORD(&dia_id.dwDataLen); - if (dia_id.byRetry > 0) { - ptr += LOADINTELDWORD(&dia_id.dwDataLen) * dia_id.byRetry; - } - } - /* 170107 modified to work on Windows 9x/2000 from ... */ - if(fdd->inf.xdf.tracks == 0) { - fdd->inf.xdf.sectors = (UINT8)trk_id.wSector; - } - fdd->inf.xdf.tracks++; - /* 170107 modified to work on Windows 9x/2000 ... to */ - } - - file_close(fh); - - // 処理関数群を登録 - fdd_fn->eject = fdd_eject_xxx; - fdd_fn->diskaccess = fdd_diskaccess_common; - fdd_fn->seek = fdd_seek_common; - fdd_fn->seeksector = fdd_seeksector_nfd1; - fdd_fn->read = fdd_read_nfd1; - fdd_fn->write = fdd_write_nfd1; - fdd_fn->readid = fdd_readid_nfd1; - fdd_fn->writeid = fdd_dummy_xxx; - fdd_fn->formatinit = fdd_dummy_xxx; - fdd_fn->formating = fdd_formating_xxx; - fdd_fn->isformating = fdd_isformating_xxx; - fdd_fn->fdcresult = TRUE; -TRACEOUT(("Build ImageAccess Info OK ... maybe")); - } - else { - return(FAILURE); - } - - return(SUCCESS); -} - -// 追加(kaiE) -BRESULT fdd_seeksector_nfd(FDDFILE fdd) { - - UINT trk; - BYTE MaxR; - UINT i; - - TRACEOUT(("NFD(r0) seeksector [%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); - - if ((CTRL_FDMEDIA != fdd->inf.xdf.disktype) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (fdc.treg[fdc.us] >= (fdd->inf.xdf.tracks >> 1))) { - TRACEOUT(("fdd_seek_nfd FAILURE CTRL_FDMEDIA[%02x], DISKTYPE[%02x]", CTRL_FDMEDIA, fdd->inf.xdf.disktype)); - TRACEOUT(("fdd_seek_nfd FAILURE fdc.rpm[%02x], fdd->rpm[%02x]", fdc.rpm[fdc.us], fdd->inf.xdf.rpm)); - TRACEOUT(("fdd_seek_nfd FAILURE fdc.treg[%02x], fdd->trk[%02x]", fdc.treg[fdc.us], (fdd->inf.xdf.tracks >> 1))); - fddlasterror = 0xe0; - return(FAILURE); - } - if (!fdc.R) { - TRACEOUT(("fdd_seek_nfd FAILURE fdc.R[%02x]", fdc.R)); - fddlasterror = 0xc0; - return(FAILURE); - } - - trk = (fdc.treg[fdc.us] << 1) + fdc.hd; - MaxR = 0; - for (i = 0; i < NFD_SECMAX; i++) { -// TRACEOUT(("fdd_seek_nfd1 read sector_id[C:%02x,H:%02x,R:%02x,N:%02x]", sec_id.C, sec_id.H, sec_id.R, sec_id.N)); - if (fdd->inf.nfd.head.r0.si[trk][i].R > MaxR) { - MaxR = fdd->inf.nfd.head.r0.si[trk][i].R; - } - } - - if (fdc.R > MaxR) { - TRACEOUT(("fdd_seek_nfd FAILURE fdc.R[%02x],MaxR[%02x]", fdc.R, MaxR)); - fddlasterror = 0xc0; - return(FAILURE); - } - if ((fdc.mf != 0xff) && (fdc.mf != 0x40)) { - TRACEOUT(("fdd_seek_nfd FAILURE fdc.mf[%02x]", fdc.mf)); - fddlasterror = 0xc0; - return(FAILURE); - } - return(SUCCESS); -} -// - -BRESULT fdd_read_nfd(FDDFILE fdd) { - - FILEH hdl; - UINT trk; - UINT sec; - UINT secR; - UINT secsize; - long seekp; - UINT i; - - fddlasterror = 0x00; -// 変更(kaiE) -// if (fdd_seeksector_common(fdd)) { - if (fdd_seeksector_nfd(fdd)) { - TRACEOUT(("NFD(r0) read FAILURE seeksector")); - return(FAILURE); - } - trk = (fdc.treg[fdc.us] << 1) + fdc.hd; - /* 170107 modified to work on Windows 9x/2000 form ... */ - if (fdc.eot && !fdd->inf.nfd.ptr[trk][fdc.eot - 1]) { - fddlasterror = 0xc0; - return(FAILURE); - } - /* 170107 modified to work on Windows 9x/2000 ... to */ - sec = fdc.R - 1; - secR = 0xff; - for (i = 0; i < NFD_SECMAX; i++) { -#if 0 - TRACEOUT(("NFD(r0) read NOR trk[%03d]: C[%02x]:H[%02x]:R[%02x]:N[%02x]:MF[%02x]", - trk, - fdd->inf.nfd.head.r0.si[trk][i].C, - fdd->inf.nfd.head.r0.si[trk][i].H, - fdd->inf.nfd.head.r0.si[trk][i].R, - fdd->inf.nfd.head.r0.si[trk][i].N, - fdd->inf.nfd.head.r0.si[trk][i].flMFM)); -#endif - if (fdd->inf.nfd.head.r0.si[trk][i].R == fdc.R) { - secR = i; -// break; - } - } - if (secR == 0xff) { - TRACEOUT(("NFD(r0) read FAILURE R[%02x] not found", fdc.R)); - fddlasterror = 0xc0; // 抜けてた…追加(kaiE) - return(FAILURE); - } - if (fdc.N != fdd->inf.nfd.head.r0.si[trk][secR].N) { - TRACEOUT(("NFD(r0) read FAILURE N not match FDC[%02x],DSK[%02x]", fdc.N, fdd->inf.nfd.head.r0.si[trk][secR].N)); - fddlasterror = 0xc0; - return(FAILURE); - } - - if (fdd->type == DISKTYPE_NFD) { - secsize = 128 << fdd->inf.nfd.head.r0.si[trk][secR].N; - seekp = fdd->inf.nfd.ptr[trk][secR]; - - hdl = file_open_rb(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xe0; - return(FAILURE); - } - TRACEOUT(("NFD(r0) read seek to ... [%08x]", seekp)); - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_read(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xe0; - return(FAILURE); - } - file_close(hdl); - } - - fdc.bufcnt = secsize; -// 変更(kaiD) -// fddlasterror = 0x00; - // イメージ内情報のREAD DATA(FDDBIOS)の結果を反映 - fdc.stat[fdc.us] = fdd->inf.nfd.head.r0.si[trk][secR].byST0 + (fdd->inf.nfd.head.r0.si[trk][secR].byST1 *256) + (fdd->inf.nfd.head.r0.si[trk][secR].byST2 * 256 * 256); - fddlasterror = fdd->inf.nfd.head.r0.si[trk][secR].byStatus; - TRACEOUT(("NFD(r0) read FDC Result Status[%02x],STS0[%02x],STS1[%02x],STS2[%02x]", - fdd->inf.nfd.head.r0.si[trk][secR].byStatus, - fdd->inf.nfd.head.r0.si[trk][secR].byST0, - fdd->inf.nfd.head.r0.si[trk][secR].byST1, - fdd->inf.nfd.head.r0.si[trk][secR].byST2)); - TRACEOUT(("NFD(r0) read C:%02x,H:%02x,R:%02x,N:%02x", fdc.C, fdc.H, fdc.R, fdc.N)); - TRACEOUT(("NFD(r0) read dump")); - TRACEOUT(("\t%02x %02x %02x %02x %02x %02x %02x %02x", - fdc.buf[0x00], fdc.buf[0x01], fdc.buf[0x02], fdc.buf[0x03], fdc.buf[0x04], fdc.buf[0x05], fdc.buf[0x06], fdc.buf[0x07])); -// - return(SUCCESS); -} - -BRESULT fdd_write_nfd(FDDFILE fdd) { - - FILEH hdl; - UINT trk; - UINT sec; - UINT secR; - UINT secsize; - long seekp; - UINT i; - - fddlasterror = 0x00; -// 変更(kaiE) -// if (fdd_seeksector_common(fdd)) { - if (fdd_seeksector_nfd(fdd)) { - fddlasterror = 0xe0; - return(FAILURE); - } - if (fdd->protect) { - fddlasterror = 0x70; - return(FAILURE); - } - trk = (fdc.treg[fdc.us] << 1) + fdc.hd; - /* 170107 modified to work on Windows 9x/2000 form ... */ - if (fdc.eot && !fdd->inf.nfd.ptr[trk][fdc.eot - 1]) { - fddlasterror = 0xc0; - return(FAILURE); - } - /* 170107 modified to work on Windows 9x/2000 ... to */ - sec = fdc.R - 1; - secR = 0xff; - for (i = 0; i < NFD_SECMAX; i++) { - if (fdd->inf.nfd.head.r0.si[trk][i].R == fdc.R) { - secR = i; - break; - } - } - if (secR == 0xff) { - return(FAILURE); - } - if (fdc.N != fdd->inf.nfd.head.r0.si[trk][secR].N) { - fddlasterror = 0xc0; - return(FAILURE); - } - - if (fdd->type == DISKTYPE_NFD) { - secsize = 128 << fdd->inf.nfd.head.r0.si[trk][secR].N; - seekp = fdd->inf.nfd.ptr[trk][secR]; - - hdl = file_open(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xc0; - return(FAILURE); - } - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_write(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xc0; - return(FAILURE); - } - file_close(hdl); - } - else { - fddlasterror = 0xc0; - return(FAILURE); - } - - fdc.bufcnt = secsize; - fddlasterror = 0x00; - - return(SUCCESS); -} - -BRESULT fdd_readid_nfd(FDDFILE fdd) { - - UINT trk; - UINT sec; - UINT i; - - /* 170101 ST modified to work on Windows 9x/2000 form ... */ - if (fdc.crcn >= fdd->inf.xdf.sectors) { - fdc.crcn = 0; - if(fdc.mt) { - fdc.hd ^= 1; - if (fdc.hd == 0) { - fdc.treg[fdc.us]++; - } - } - else { - fdc.treg[fdc.us]++; - } - } - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - fddlasterror = 0x00; - if ((!fdc.mf) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (CTRL_FDMEDIA != fdd->inf.xdf.disktype)) { - //(fdc.crcn >= fdd->inf.xdf.sectors)) { - fddlasterror = 0xe0; - return(FAILURE); - } - fdc.C = fdc.treg[fdc.us]; - fdc.H = fdc.hd; - fdc.R = ++fdc.crcn; - trk = (fdc.C << 1) + fdc.H; - sec = 0xff; - for (i = 0; i < NFD_SECMAX; i++) { - if (fdd->inf.nfd.head.r0.si[trk][i].R == fdc.R) { - sec = i; - break; - } - } - if (sec == 0xff) { - fddlasterror = 0xe0; - return(FAILURE); - } - fdc.N = fdd->inf.nfd.head.r0.si[trk][sec].N; - return(SUCCESS); -} - -/* 170107 to supprt format command form ... */ -/* ヘッダの更新頻度が多いのが気になります */ -BRESULT fdd_formatinit_nfd(FDDFILE fdd) { - FILEH hdl; - UINT32 fddtype; - UINT32 cylinders; - UINT32 offset; - UINT trk; - UINT secsize; - UINT size; - UINT i; - - if (fdd->protect) { - fddlasterror = 0x70; - return(FAILURE); - } - - hdl = file_open(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xc0; - return(FAILURE); - } - - secsize = 128 << fdc.N; - size = secsize * fdc.sc; - trk = (fdc.treg[fdc.us] << 1) + fdc.hd; - memset(fdc.buf, fdc.d, size); - - fddtype = 0x90; - if (fdc.N == 2) { - if (fdc.sc < 10) { - fddtype = 0x10; - } - else if (fdc.sc > 16) { - fddtype = 0x30; - } - } - - if (trk == 0) { - ZeroMemory(fdd->inf.nfd.head.r0.si, sizeof(fdd->inf.nfd.head.r0.si)); - offset = fdd->inf.xdf.headersize; - } else { - offset = fdd->inf.nfd.tptr[trk]; - } - fdd->inf.nfd.tptr[trk + 1] = offset + size; - - for (i = 0; i < fdc.sc; i++) { - fdd->inf.nfd.head.r0.si[trk][i].C = fdc.treg[fdc.us]; - fdd->inf.nfd.head.r0.si[trk][i].H = fdc.hd; - fdd->inf.nfd.head.r0.si[trk][i].R = i + 1; - fdd->inf.nfd.head.r0.si[trk][i].N = fdc.N; - fdd->inf.nfd.head.r0.si[trk][i].flMFM = 1; - fdd->inf.nfd.head.r0.si[trk][i].flDDAM = 0; - fdd->inf.nfd.head.r0.si[trk][i].byStatus = 0; - fdd->inf.nfd.head.r0.si[trk][i].byST0 = fdc.hd << 2; - fdd->inf.nfd.head.r0.si[trk][i].byST1 = 0; - fdd->inf.nfd.head.r0.si[trk][i].byST2 = 0; - fdd->inf.nfd.head.r0.si[trk][i].byPDA = fddtype; - fdd->inf.nfd.ptr[trk][i] = offset; - offset += secsize; - } - if (trk == 0) { - for (; i < NFD_TRKMAX * NFD_SECMAX; i++) { - fdd->inf.nfd.head.r0.si[trk][i].C = 0xff; - fdd->inf.nfd.head.r0.si[trk][i].H = 0xff; - fdd->inf.nfd.head.r0.si[trk][i].R = 0xff; - fdd->inf.nfd.head.r0.si[trk][i].N = 0xff; - fdd->inf.nfd.head.r0.si[trk][i].flMFM = 0xff; - fdd->inf.nfd.head.r0.si[trk][i].flDDAM = 0xff; - fdd->inf.nfd.head.r0.si[trk][i].byStatus = 0xe0; - fdd->inf.nfd.head.r0.si[trk][i].byST0 = 0x40 | (fdc.hd << 2); - fdd->inf.nfd.head.r0.si[trk][i].byST1 = 1; - fdd->inf.nfd.head.r0.si[trk][i].byST2 = 0; - fdd->inf.nfd.head.r0.si[trk][i].byPDA = 0; - } - } - - if ((file_seek(hdl, 0, FSEEK_SET) != 0) || - (file_write(hdl, &fdd->inf.nfd.head, NFD_HEADERSIZE) != NFD_HEADERSIZE)) { - file_close(hdl); - fddlasterror = 0xc0; - return(FAILURE); - } - - offset = fdd->inf.nfd.ptr[trk][0]; - if ((file_seek(hdl, offset, FSEEK_SET) != offset) || - (file_write(hdl, fdc.buf, size) != size)) { - file_close(hdl); - fddlasterror = 0xc0; - return(FAILURE); - } - - if (trk == 0) { - fdd->inf.xdf.disktype = DISKTYPE_2HD; - cylinders = 77; - switch(fdc.N) { - case 1: // BASIC (sector size = 256) - break; - case 2: // 1.44M/1.21M/2DD - if (fdc.sc < 10) { - fdd->inf.xdf.disktype = DISKTYPE_2DD; - } - cylinders = 80; - break; - default: // 1.25M - break; - } - - fdd->inf.xdf.tracks = (UINT8)(cylinders * 2); - fdd->inf.xdf.sectors = fdc.sc; - fdd->inf.xdf.n = fdc.N; - fdd->inf.xdf.rpm = fdc.rpm[fdc.us]; - - // trim media image - offset = fdd->inf.xdf.tracks * size + fdd->inf.xdf.headersize; - file_seek(hdl, offset, FSEEK_SET); - file_write(hdl, fdc.buf, 0); - } - - file_close(hdl); - fddlasterror = 0x00; - return(SUCCESS); -} -/* 170107 to supprt format command ... to */ - -// 追加(kaiD) -BRESULT fdd_seeksector_nfd1(FDDFILE fdd) { - - FILEH hdl; - UINT trk; - BYTE MaxR; - UINT i; - NFD_TRACK_ID1 trk_id; - NFD_SECT_ID1 sec_id; - - if ((CTRL_FDMEDIA != fdd->inf.xdf.disktype) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (fdc.treg[fdc.us] >= (fdd->inf.xdf.tracks >> 1))) { - TRACEOUT(("fdd_seek_nfd1 FAILURE CTRL_FDMEDIA[%02x], DISKTYPE[%02x]", CTRL_FDMEDIA, fdd->inf.xdf.disktype)); - TRACEOUT(("fdd_seek_nfd1 FAILURE fdc.rpm[%02x], fdd->rpm[%02x]", fdc.rpm[fdc.us], fdd->inf.xdf.rpm)); - TRACEOUT(("fdd_seek_nfd1 FAILURE fdc.treg[%02x], fdd->trk[%02x]", fdc.treg[fdc.us], (fdd->inf.xdf.tracks >> 1))); - fddlasterror = 0xe0; - return(FAILURE); - } - if (!fdc.R) { - TRACEOUT(("fdd_seek_nfd1 FAILURE fdc.R[%02x]", fdc.R)); - fddlasterror = 0xc0; - return(FAILURE); - } - - hdl = file_open_rb(fdd->fname); - if (hdl == FILEH_INVALID) { - TRACEOUT(("fdd_seek_nfd1 FAILURE ... 1")); - fddlasterror = 0xe0; - return(FAILURE); - } - trk = (fdc.treg[fdc.us] << 1) + fdc.hd; - file_seek(hdl, LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[trk])), FSEEK_SET); - file_read(hdl, &trk_id, sizeof(NFD_TRACK_ID1)); -// TRACEOUT(("fdd_seek_nfd1 read track_id[%03d:%08x]", trk, fdd->inf.nfd.head.r1.dwTrackHead[trk])); - MaxR = 0; - for (i = 0; i < LOADINTELWORD(&(trk_id.wSector)); i++) { - file_read(hdl, &sec_id, sizeof(NFD_SECT_ID1)); -// TRACEOUT(("fdd_seek_nfd1 read sector_id[C:%02x,H:%02x,R:%02x,N:%02x]", sec_id.C, sec_id.H, sec_id.R, sec_id.N)); - if (sec_id.R > MaxR) { - MaxR = sec_id.R; - } - } - file_close(hdl); - - if (fdc.R > MaxR) { - TRACEOUT(("fdd_seek_nfd1 FAILURE fdc.R[%02x],MaxR[%02x]", fdc.R, MaxR)); - fddlasterror = 0xc0; - return(FAILURE); - } - if ((fdc.mf != 0xff) && (fdc.mf != 0x40)) { - TRACEOUT(("fdd_seek_nfd1 FAILURE fdc.mf[%02x]", fdc.mf)); - fddlasterror = 0xc0; - return(FAILURE); - } - return(SUCCESS); -} - -// RetryData有の対応…いいのか?これで -static UINT8 rcnt = 0; - -BRESULT fdd_read_nfd1(FDDFILE fdd) { - - FILEH hdl; - UINT trk; - UINT sec; - UINT secR; - UINT secsize; - long seekp; - long ex_offset; - long ex_offset2; - UINT i; - UINT8 MaxRetry; - NFD_TRACK_ID1 trk_id; - NFD_SECT_ID1 sec_id; - NFD_SECT_ID1 sec_idx; - NFD_DIAG_ID1 dia_id; - - // RetryData有の対応…いいのか?これで - rcnt++; - - fddlasterror = 0x00; - if (fdd_seeksector_nfd1(fdd)) { - TRACEOUT(("NFD(r1) read failure ... seeksector")); - return(FAILURE); - } - trk = (fdc.treg[fdc.us] << 1) + fdc.hd; - /* 170107 modified to work on Windows 9x/2000 form ... */ - if (fdc.eot && !fdd->inf.nfd.ptr[trk][fdc.eot - 1]) { - fddlasterror = 0xc0; - return(FAILURE); - } - /* 170107 modified to work on Windows 9x/2000 ... to */ - sec = fdc.R - 1; - secR = 0xff; - ex_offset = 0; - ex_offset2 = 0; - MaxRetry = 0; - hdl = file_open_rb(fdd->fname); - if (hdl == FILEH_INVALID) { - TRACEOUT(("NFD(r1) read failure ... FILE OPEN")); - fddlasterror = 0xe0; - return(FAILURE); - } - file_seek(hdl, LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[trk])), FSEEK_SET); - file_read(hdl, &trk_id, sizeof(NFD_TRACK_ID1)); - for (i = 0; i < LOADINTELWORD(&(trk_id.wSector)); i++) { - file_read(hdl, &sec_idx, sizeof(NFD_SECT_ID1)); - TRACEOUT(("NFD(r1) read NOR trk[%03d]: C[%02x]:H[%02x]:R[%02x]:N[%02x]:MFM[%02x]:DDAM[%02x]:Retry[%02x]:PDA[%02x]", - trk, sec_idx.C, sec_idx.H, sec_idx.R, sec_idx.N, sec_idx.flMFM, sec_idx.flDDAM, sec_idx.byRetry, sec_idx.byPDA)); - if (sec_idx.R == fdc.R) { - secR = i; - memcpy(&sec_id, &sec_idx, sizeof(NFD_SECT_ID1)); - MaxRetry = sec_idx.byRetry; -// break; - } -// ex_offset += 128 << sec_id.N; - } - if (secR == 0xff) { - TRACEOUT(("NFD(r1) read failure ... R[%0x2] not found", fdc.R)); - file_close(hdl); - return(FAILURE); - } - - if (fdc.N != sec_id.N) { - BOOL flg; - TRACEOUT(("NFD(r1) read failure ... N not match : fdc.n:[%02x],sec_id.N:[%02x]", fdc.N, sec_id.N)); -#if 1 - flg = FALSE; - for (i = 0; i < LOADINTELWORD(&(trk_id.wDiag)); i++) { - file_read(hdl, &dia_id, sizeof(NFD_DIAG_ID1)); - TRACEOUT(("NFD(r1) read DIA trk[%03d]:Cmd[%02x]:C[%02x]:H[%02x]:R[%02x]:N[%02x]:Len[%08x]:Retry[%02x]", - trk, dia_id.Cmd, dia_id.C, dia_id.H, dia_id.R, dia_id.N, dia_id.dwDataLen, dia_id.byRetry)); - if (fdc.N == dia_id.N) { - TRACEOUT(("\tfound diag data")); - flg = TRUE; - break; - } - ex_offset2 += LOADINTELDWORD(&(dia_id.dwDataLen)); - } -#endif - if (flg == FALSE) { - fddlasterror = 0xc0; - file_close(hdl); - return(FAILURE); - } - } - - if (fdd->type == DISKTYPE_NFD) { - if (fdc.N == sec_id.N) { - secsize = 128 << sec_id.N; - seekp = fdd->inf.nfd.ptr[trk][sec]; - // RetryData有の対応…いいのか?これで - seekp += secsize * (MaxRetry ? (rcnt % MaxRetry) : 0); - } - else { - secsize = LOADINTELDWORD(&(dia_id.dwDataLen)); - seekp = fdd->inf.nfd.ptr[trk][sec] + fdd->inf.nfd.trksize[trk] + ex_offset2; - } - - TRACEOUT(("NFD(r1) read seek to ... [%08x]", seekp)); - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_read(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xe0; - TRACEOUT(("NFD(r1) read failure ... FILE SEEK or READ")); - return(FAILURE); - } - } - else { - fddlasterror = 0xc0; - file_close(hdl); - return(FAILURE); - } - file_close(hdl); - - // イメージ内情報のREAD DATA RESULTを反映 - fdc.stat[fdc.us] = sec_id.bySTS0 | (sec_id.bySTS1 << 8) | (sec_id.bySTS2 << 16); - fddlasterror = sec_id.byStatus; - fdc.bufcnt = secsize; - TRACEOUT(("NFD(r1) read FDC Result Status[%02x],STS0[%02x],STS1[%02x],STS2[%02x]", - sec_id.byStatus, sec_id.bySTS0, sec_id.bySTS1, sec_id.bySTS2)); - TRACEOUT(("NFD(r1) read C:%02x,H:%02x,R:%02x,N:%02x", fdc.C, fdc.H, fdc.R, fdc.N)); - TRACEOUT(("NFD(r1) read dump")); - TRACEOUT(("\t%02x %02x %02x %02x %02x %02x %02x %02x", - fdc.buf[0x00], fdc.buf[0x01], fdc.buf[0x02], fdc.buf[0x03], fdc.buf[0x04], fdc.buf[0x05], fdc.buf[0x06], fdc.buf[0x07])); - return(SUCCESS); -} - -BRESULT fdd_write_nfd1(FDDFILE fdd) { - - FILEH hdl; - UINT trk; - UINT sec; - UINT secR; - UINT secsize; - long seekp; - UINT i; - NFD_TRACK_ID1 trk_id; - NFD_SECT_ID1 sec_id; - - fddlasterror = 0x00; - if (fdd_seeksector_nfd1(fdd)) { - fddlasterror = 0xe0; - return(FAILURE); - } - if (fdd->protect) { - fddlasterror = 0x70; - return(FAILURE); - } - trk = (fdc.treg[fdc.us] << 1) + fdc.hd; - /* 170107 modified to work on Windows 9x/2000 form ... */ - if (fdc.eot && !fdd->inf.nfd.ptr[trk][fdc.eot - 1]) { - fddlasterror = 0xc0; - return(FAILURE); - } - /* 170107 modified to work on Windows 9x/2000 ... to */ - sec = fdc.R - 1; - secR = 0xff; - hdl = file_open(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xe0; - return(FAILURE); - } - file_seek(hdl, LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[trk])), FSEEK_SET); - file_read(hdl, &trk_id, sizeof(NFD_TRACK_ID1)); - for (i = 0; i < LOADINTELWORD(&(trk_id.wSector)); i++) { - file_read(hdl, &sec_id, sizeof(NFD_SECT_ID1)); - if (sec_id.R == fdc.R) { - secR = i; - break; - } - } - if (secR == 0xff) { - file_close(hdl); - return(FAILURE); - } - if (fdc.N != sec_id.N) { - fddlasterror = 0xc0; - file_close(hdl); - return(FAILURE); - } - - if (fdd->type == DISKTYPE_NFD) { - secsize = 128 << sec_id.N; - seekp = fdd->inf.nfd.ptr[trk][sec]; - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_write(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xc0; - return(FAILURE); - } - } - else { - fddlasterror = 0xc0; - file_close(hdl); - return(FAILURE); - } - - file_close(hdl); - fdc.bufcnt = secsize; - fddlasterror = 0x00; - - return(SUCCESS); -} - -BRESULT fdd_readid_nfd1(FDDFILE fdd) { - - FILEH hdl; - UINT trk; - UINT sec; - UINT i; - NFD_TRACK_ID1 trk_id; - NFD_SECT_ID1 sec_id; - - /* 170107 modified to work on Windows 9x/2000 form ... */ - if (fdc.crcn >= fdd->inf.xdf.sectors) { - fdc.crcn = 0; - if(fdc.mt) { - fdc.hd ^= 1; - if (fdc.hd == 0) { - fdc.treg[fdc.us]++; - } - } - else { - fdc.treg[fdc.us]++; - } - } - /* 170107 modified to work on Windows 9x/2000 ... to */ - fddlasterror = 0x00; - if ((!fdc.mf) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (CTRL_FDMEDIA != fdd->inf.xdf.disktype)) { - //(fdc.crcn >= fdd->inf.xdf.sectors)) { - fddlasterror = 0xe0; - return(FAILURE); - } - fdc.C = fdc.treg[fdc.us]; - fdc.H = fdc.hd; - fdc.R = ++fdc.crcn; - trk = (fdc.C << 1) + fdc.H; - sec = 0xff; - hdl = file_open_rb(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xe0; - return(FAILURE); - } - file_seek(hdl, LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[trk])), FSEEK_SET); - file_read(hdl, &trk_id, sizeof(NFD_TRACK_ID1)); - for (i = 0; i < LOADINTELWORD(&(trk_id.wSector)); i++) { - file_read(hdl, &sec_id, sizeof(NFD_SECT_ID1)); - if (sec_id.R == fdc.R) { - sec = i; - break; - } - } - file_close(hdl); - if (sec == 0xff) { - fddlasterror = 0xe0; - return(FAILURE); - } - fdc.N = sec_id.N; - return(SUCCESS); -} -// - -#endif +#include +#include +#include +#include + +#ifdef SUPPORT_KAI_IMAGES + +#include +#include "diskimage/fd/fdd_nfd.h" + +static const UINT8 nfd_FileID_r0[15] = + {'T','9','8','F','D','D','I','M','A','G','E','.','R','0',0x00}; +static const UINT8 nfd_FileID_r1[15] = + {'T','9','8','F','D','D','I','M','A','G','E','.','R','1',0x00}; + +BRESULT fdd_set_nfd(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { + + short attr; + FILEH fh; + UINT rsize; + UINT32 ptr; + UINT i; + UINT j; + + attr = file_attr(fname); + if (attr & 0x18) { + return(FAILURE); + } + if(!ro) { + if(attr & FILEATTR_READONLY) { + ro = 1; + } + } + if(ro) { + fh = file_open_rb(fname); + } else { + fh = file_open(fname); + } + if (fh == FILEH_INVALID) { + return(FAILURE); + } + rsize = file_read(fh, &fdd->inf.nfd.head, NFD_HEADERSIZE); // nfdヘッダ読込(とりあえずr0で) + file_close(fh); + if (rsize != NFD_HEADERSIZE) { + return(FAILURE); + } + + // 識別IDチェック + if (memcmp(fdd->inf.nfd.head.r0.szFileID, nfd_FileID_r0, 15) == 0) { + // NFD r0形式 + const NFD_SECT_ID *sec_nfd; + + fdd->type = DISKTYPE_NFD; + fdd->protect = ((attr & 0x01) || (ro)) ? TRUE : FALSE; + if (fdd->inf.nfd.head.r0.flProtect) { + fdd->protect = TRUE; + } + + /* 170101 ST modified to work on Windows 9x/2000 from ... */ + // 最大値入れて平気? + // fdd->inf.xdf.tracks = NFD_TRKMAX; + // fdd->inf.xdf.sectors = NFD_SECMAX; + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + + // 期待した値が入ってないことが…orz + ptr = LOADINTELDWORD(&fdd->inf.nfd.head.r0.dwHeadSize); +// ptr = NFD_HEADERSIZE; +//TRACEOUT(("NFD(r0) TopSec Offset[%08x]", ptr)); + // 先頭格納セクタを見て決め打ち + // …2DD/2HD混在フォーマットでまずい気がする + sec_nfd = &fdd->inf.nfd.head.r0.si[0][0]; +//TRACEOUT(("NFD(r0) TopSec PDA[%02x]", sec_nfd->byPDA)); + switch (sec_nfd->byPDA) { + case 0x10: // 640K + fdd->inf.xdf.disktype = DISKTYPE_2DD; + fdd->inf.xdf.rpm = 0; + break; + case 0x30: // 1.44M + fdd->inf.xdf.disktype = DISKTYPE_2HD; + fdd->inf.xdf.rpm = 1; + break; + case 0x90: // 1.2M + fdd->inf.xdf.disktype = DISKTYPE_2HD; + fdd->inf.xdf.rpm = 0; + break; + default: + return(FAILURE); + break; + } + /* 170101 ST modified to work on Windows 9x/2000 from ... */ + fdd->inf.xdf.tracks = 0; + fdd->inf.xdf.sectors = 0; + ZeroMemory(fdd->inf.nfd.ptr, sizeof(fdd->inf.nfd.ptr)); + fdd->inf.xdf.headersize = ptr; + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + // ディスクアクセス時用に各セクタのオフセットを算出し格納 + for (i = 0; i < NFD_TRKMAX; i++) { + for (j = 0; j < NFD_SECMAX; j++) { +TRACEOUT(("NFD(r0) C[%02x]:H[%02x]:R[%02x]:N[%02x]", + sec_nfd->C, sec_nfd->H, sec_nfd->R, sec_nfd->N)); + if (sec_nfd->C != 0xff) { +TRACEOUT(("\tSetOffset Trk[%03d]Sec[%02x] = Offset[%08x]", i, j, ptr)); + fdd->inf.nfd.ptr[i][j] = ptr; + ptr += 128 << sec_nfd->N; + /* 170101 ST modified to work on Windows 9x/2000 from ... */ + fdd->inf.xdf.tracks = i; + if (fdd->inf.xdf.sectors < j) { + fdd->inf.xdf.sectors = j; + } + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + } + sec_nfd++; + } + } + /* 170101 ST modified to work on Windows 9x/2000 from ... */ + fdd->inf.xdf.tracks++; + fdd->inf.xdf.sectors++; + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + + // 処理関数群を登録 + fdd_fn->eject = fdd_eject_xxx; + fdd_fn->diskaccess = fdd_diskaccess_common; + fdd_fn->seek = fdd_seek_common; + fdd_fn->seeksector = fdd_seeksector_nfd; // 変更(kaiE) + fdd_fn->read = fdd_read_nfd; + fdd_fn->write = fdd_write_nfd; + fdd_fn->readid = fdd_readid_nfd; + fdd_fn->writeid = fdd_dummy_xxx; + fdd_fn->formatinit = fdd_formatinit_nfd; /* 170107 to support format command */ + fdd_fn->formating = fdd_formating_xxx; + fdd_fn->isformating = fdd_isformating_xxx; + fdd_fn->fdcresult = TRUE; + } + else if (memcmp(fdd->inf.nfd.head.r1.szFileID, nfd_FileID_r1, 15) == 0) { + // NFD r1形式 + NFD_TRACK_ID1 trk_id; + NFD_SECT_ID1 sec_id; + NFD_DIAG_ID1 dia_id; + UINT32 trksize; + +TRACEOUT(("This is NFD(r1) IMAGE!")); + // ヘッダ再読込 + if(fdd->protect) { + fh = file_open_rb(fname); + } else { + fh = file_open(fname); + } + if (fh == FILEH_INVALID) { + return(FAILURE); + } + rsize = file_read(fh, &fdd->inf.nfd.head, sizeof(NFD_FILE_HEAD1)); + + fdd->type = DISKTYPE_NFD; + fdd->protect = ((attr & 0x01) || (ro)) ? TRUE : FALSE; + if (fdd->inf.nfd.head.r1.flProtect) { + fdd->protect = TRUE; + } + + /* 170101 ST modified to work on Windows 9x/2000 from ... */ + // 最大値入れて平気? + //fdd->inf.xdf.tracks = NFD_TRKMAX; + //fdd->inf.xdf.sectors = NFD_SECMAX; + /* 170101 modified to work on Windows 9x/2000 ... to */ + + ptr = LOADINTELDWORD(&fdd->inf.nfd.head.r1.dwHeadSize); + /* 170107 modified to work on Windows 9x/2000 from ... */ + fdd->inf.xdf.tracks = 0; + fdd->inf.xdf.sectors = 0; + ZeroMemory(fdd->inf.nfd.ptr, sizeof(fdd->inf.nfd.ptr)); + fdd->inf.xdf.headersize = ptr; + /* 170107 modified to work on Windows 9x/2000 ... to */ + for (i = 0; i < NFD_TRKMAX1; i++) { + // トラック情報ヘッダ読込 + /* 170107 modified to work on Windows 9x/2000 from ... */ + if (LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[i])) == 0) { + continue; + } + /* 170107 modified to work on Windows 9x/2000 ... to */ + if ((file_seek(fh, LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[i])), FSEEK_SET) != LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[i]))) || + (file_read(fh, &trk_id, sizeof(NFD_TRACK_ID1)) != sizeof(NFD_TRACK_ID1))) { + file_close(fh); + return(FAILURE); + } + trksize = 0; + // セクタ情報ヘッダ読込 + for (j = 0; j < LOADINTELWORD(&(trk_id.wSector)); j++) { + file_read(fh, &sec_id, sizeof(NFD_SECT_ID1)); +// if (sec_id.R < NFD_SECMAX) { + fdd->inf.nfd.ptr[i][sec_id.R - 1] = ptr; +// fdd->inf.nfd.ptr[i][j] = ptr; +// } + ptr += 128 << sec_id.N; + trksize += 128 << sec_id.N; + if (sec_id.byRetry > 0) { + ptr += (128 << sec_id.N) * sec_id.byRetry; + trksize += (128 << sec_id.N) * sec_id.byRetry; + } + if (i == 0 && j == 0) { + // 先頭格納セクタを見て決め打ち + // …2DD/2HD混在フォーマットでまずい気がする +TRACEOUT(("NFD(r1) TopSec PDA[%02x]", sec_id.byPDA)); + switch (sec_id.byPDA) { + case 0x10: // 640K + fdd->inf.xdf.disktype = DISKTYPE_2DD; + fdd->inf.xdf.rpm = 0; + break; + case 0x30: // 1.44M + fdd->inf.xdf.disktype = DISKTYPE_2HD; + fdd->inf.xdf.rpm = 1; + break; + case 0x00: // 1.2M…? + case 0x90: // 1.2M + fdd->inf.xdf.disktype = DISKTYPE_2HD; + fdd->inf.xdf.rpm = 0; + break; + default: + file_close(fh); + return(FAILURE); + break; + } + } + } + fdd->inf.nfd.trksize[i] = trksize; + // 特殊読み込み情報ヘッダ読込 + for (j = 0; j < LOADINTELWORD(&(trk_id.wDiag)); j++) { + file_read(fh, &dia_id, sizeof(NFD_DIAG_ID1)); + ptr += LOADINTELDWORD(&dia_id.dwDataLen); + if (dia_id.byRetry > 0) { + ptr += LOADINTELDWORD(&dia_id.dwDataLen) * dia_id.byRetry; + } + } + /* 170107 modified to work on Windows 9x/2000 from ... */ + if(fdd->inf.xdf.tracks == 0) { + fdd->inf.xdf.sectors = (UINT8)trk_id.wSector; + } + fdd->inf.xdf.tracks++; + /* 170107 modified to work on Windows 9x/2000 ... to */ + } + + file_close(fh); + + // 処理関数群を登録 + fdd_fn->eject = fdd_eject_xxx; + fdd_fn->diskaccess = fdd_diskaccess_common; + fdd_fn->seek = fdd_seek_common; + fdd_fn->seeksector = fdd_seeksector_nfd1; + fdd_fn->read = fdd_read_nfd1; + fdd_fn->write = fdd_write_nfd1; + fdd_fn->readid = fdd_readid_nfd1; + fdd_fn->writeid = fdd_dummy_xxx; + fdd_fn->formatinit = fdd_dummy_xxx; + fdd_fn->formating = fdd_formating_xxx; + fdd_fn->isformating = fdd_isformating_xxx; + fdd_fn->fdcresult = TRUE; +TRACEOUT(("Build ImageAccess Info OK ... maybe")); + } + else { + return(FAILURE); + } + + return(SUCCESS); +} + +// 追加(kaiE) +BRESULT fdd_seeksector_nfd(FDDFILE fdd) { + + UINT trk; + BYTE MaxR; + UINT i; + + TRACEOUT(("NFD(r0) seeksector [%03d]", (fdc.treg[fdc.us] << 1) + fdc.hd)); + + if ((CTRL_FDMEDIA != fdd->inf.xdf.disktype) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (fdc.treg[fdc.us] >= (fdd->inf.xdf.tracks >> 1))) { + TRACEOUT(("fdd_seek_nfd FAILURE CTRL_FDMEDIA[%02x], DISKTYPE[%02x]", CTRL_FDMEDIA, fdd->inf.xdf.disktype)); + TRACEOUT(("fdd_seek_nfd FAILURE fdc.rpm[%02x], fdd->rpm[%02x]", fdc.rpm[fdc.us], fdd->inf.xdf.rpm)); + TRACEOUT(("fdd_seek_nfd FAILURE fdc.treg[%02x], fdd->trk[%02x]", fdc.treg[fdc.us], (fdd->inf.xdf.tracks >> 1))); + fddlasterror = 0xe0; + return(FAILURE); + } + if (!fdc.R) { + TRACEOUT(("fdd_seek_nfd FAILURE fdc.R[%02x]", fdc.R)); + fddlasterror = 0xc0; + return(FAILURE); + } + + trk = (fdc.treg[fdc.us] << 1) + fdc.hd; + MaxR = 0; + for (i = 0; i < NFD_SECMAX; i++) { +// TRACEOUT(("fdd_seek_nfd1 read sector_id[C:%02x,H:%02x,R:%02x,N:%02x]", sec_id.C, sec_id.H, sec_id.R, sec_id.N)); + if (fdd->inf.nfd.head.r0.si[trk][i].R > MaxR) { + MaxR = fdd->inf.nfd.head.r0.si[trk][i].R; + } + } + + if (fdc.R > MaxR) { + TRACEOUT(("fdd_seek_nfd FAILURE fdc.R[%02x],MaxR[%02x]", fdc.R, MaxR)); + fddlasterror = 0xc0; + return(FAILURE); + } + if ((fdc.mf != 0xff) && (fdc.mf != 0x40)) { + TRACEOUT(("fdd_seek_nfd FAILURE fdc.mf[%02x]", fdc.mf)); + fddlasterror = 0xc0; + return(FAILURE); + } + return(SUCCESS); +} +// + +BRESULT fdd_read_nfd(FDDFILE fdd) { + + FILEH hdl; + UINT trk; + UINT sec; + UINT secR; + UINT secsize; + long seekp; + UINT i; + + fddlasterror = 0x00; +// 変更(kaiE) +// if (fdd_seeksector_common(fdd)) { + if (fdd_seeksector_nfd(fdd)) { + TRACEOUT(("NFD(r0) read FAILURE seeksector")); + return(FAILURE); + } + trk = (fdc.treg[fdc.us] << 1) + fdc.hd; + /* 170107 modified to work on Windows 9x/2000 form ... */ + if (fdc.eot && !fdd->inf.nfd.ptr[trk][fdc.eot - 1]) { + fddlasterror = 0xc0; + return(FAILURE); + } + /* 170107 modified to work on Windows 9x/2000 ... to */ + sec = fdc.R - 1; + secR = 0xff; + for (i = 0; i < NFD_SECMAX; i++) { +#if 0 + TRACEOUT(("NFD(r0) read NOR trk[%03d]: C[%02x]:H[%02x]:R[%02x]:N[%02x]:MF[%02x]", + trk, + fdd->inf.nfd.head.r0.si[trk][i].C, + fdd->inf.nfd.head.r0.si[trk][i].H, + fdd->inf.nfd.head.r0.si[trk][i].R, + fdd->inf.nfd.head.r0.si[trk][i].N, + fdd->inf.nfd.head.r0.si[trk][i].flMFM)); +#endif + if (fdd->inf.nfd.head.r0.si[trk][i].R == fdc.R) { + secR = i; +// break; + } + } + if (secR == 0xff) { + TRACEOUT(("NFD(r0) read FAILURE R[%02x] not found", fdc.R)); + fddlasterror = 0xc0; // 抜けてた…追加(kaiE) + return(FAILURE); + } + if (fdc.N != fdd->inf.nfd.head.r0.si[trk][secR].N) { + TRACEOUT(("NFD(r0) read FAILURE N not match FDC[%02x],DSK[%02x]", fdc.N, fdd->inf.nfd.head.r0.si[trk][secR].N)); + fddlasterror = 0xc0; + return(FAILURE); + } + + if (fdd->type == DISKTYPE_NFD) { + secsize = 128 << fdd->inf.nfd.head.r0.si[trk][secR].N; + seekp = fdd->inf.nfd.ptr[trk][secR]; + + hdl = file_open_rb(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xe0; + return(FAILURE); + } + TRACEOUT(("NFD(r0) read seek to ... [%08x]", seekp)); + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_read(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xe0; + return(FAILURE); + } + file_close(hdl); + } + + fdc.bufcnt = secsize; +// 変更(kaiD) +// fddlasterror = 0x00; + // イメージ内情報のREAD DATA(FDDBIOS)の結果を反映 + fdc.stat[fdc.us] = fdd->inf.nfd.head.r0.si[trk][secR].byST0 + (fdd->inf.nfd.head.r0.si[trk][secR].byST1 *256) + (fdd->inf.nfd.head.r0.si[trk][secR].byST2 * 256 * 256); + fddlasterror = fdd->inf.nfd.head.r0.si[trk][secR].byStatus; + TRACEOUT(("NFD(r0) read FDC Result Status[%02x],STS0[%02x],STS1[%02x],STS2[%02x]", + fdd->inf.nfd.head.r0.si[trk][secR].byStatus, + fdd->inf.nfd.head.r0.si[trk][secR].byST0, + fdd->inf.nfd.head.r0.si[trk][secR].byST1, + fdd->inf.nfd.head.r0.si[trk][secR].byST2)); + TRACEOUT(("NFD(r0) read C:%02x,H:%02x,R:%02x,N:%02x", fdc.C, fdc.H, fdc.R, fdc.N)); + TRACEOUT(("NFD(r0) read dump")); + TRACEOUT(("\t%02x %02x %02x %02x %02x %02x %02x %02x", + fdc.buf[0x00], fdc.buf[0x01], fdc.buf[0x02], fdc.buf[0x03], fdc.buf[0x04], fdc.buf[0x05], fdc.buf[0x06], fdc.buf[0x07])); +// + return(SUCCESS); +} + +BRESULT fdd_write_nfd(FDDFILE fdd) { + + FILEH hdl; + UINT trk; + UINT sec; + UINT secR; + UINT secsize; + long seekp; + UINT i; + + fddlasterror = 0x00; +// 変更(kaiE) +// if (fdd_seeksector_common(fdd)) { + if (fdd_seeksector_nfd(fdd)) { + fddlasterror = 0xe0; + return(FAILURE); + } + if (fdd->protect) { + fddlasterror = 0x70; + return(FAILURE); + } + trk = (fdc.treg[fdc.us] << 1) + fdc.hd; + /* 170107 modified to work on Windows 9x/2000 form ... */ + if (fdc.eot && !fdd->inf.nfd.ptr[trk][fdc.eot - 1]) { + fddlasterror = 0xc0; + return(FAILURE); + } + /* 170107 modified to work on Windows 9x/2000 ... to */ + sec = fdc.R - 1; + secR = 0xff; + for (i = 0; i < NFD_SECMAX; i++) { + if (fdd->inf.nfd.head.r0.si[trk][i].R == fdc.R) { + secR = i; + break; + } + } + if (secR == 0xff) { + return(FAILURE); + } + if (fdc.N != fdd->inf.nfd.head.r0.si[trk][secR].N) { + fddlasterror = 0xc0; + return(FAILURE); + } + + if (fdd->type == DISKTYPE_NFD) { + secsize = 128 << fdd->inf.nfd.head.r0.si[trk][secR].N; + seekp = fdd->inf.nfd.ptr[trk][secR]; + + hdl = file_open(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xc0; + return(FAILURE); + } + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_write(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xc0; + return(FAILURE); + } + file_close(hdl); + } + else { + fddlasterror = 0xc0; + return(FAILURE); + } + + fdc.bufcnt = secsize; + fddlasterror = 0x00; + + return(SUCCESS); +} + +BRESULT fdd_readid_nfd(FDDFILE fdd) { + + UINT trk; + UINT sec; + UINT i; + + /* 170101 ST modified to work on Windows 9x/2000 form ... */ + if (fdc.crcn >= fdd->inf.xdf.sectors) { + fdc.crcn = 0; + if(fdc.mt) { + fdc.hd ^= 1; + if (fdc.hd == 0) { + fdc.treg[fdc.us]++; + } + } + else { + fdc.treg[fdc.us]++; + } + } + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + fddlasterror = 0x00; + if ((!fdc.mf) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (CTRL_FDMEDIA != fdd->inf.xdf.disktype)) { + //(fdc.crcn >= fdd->inf.xdf.sectors)) { + fddlasterror = 0xe0; + return(FAILURE); + } + fdc.C = fdc.treg[fdc.us]; + fdc.H = fdc.hd; + fdc.R = ++fdc.crcn; + trk = (fdc.C << 1) + fdc.H; + sec = 0xff; + for (i = 0; i < NFD_SECMAX; i++) { + if (fdd->inf.nfd.head.r0.si[trk][i].R == fdc.R) { + sec = i; + break; + } + } + if (sec == 0xff) { + fddlasterror = 0xe0; + return(FAILURE); + } + fdc.N = fdd->inf.nfd.head.r0.si[trk][sec].N; + return(SUCCESS); +} + +/* 170107 to supprt format command form ... */ +/* ヘッダの更新頻度が多いのが気になります */ +BRESULT fdd_formatinit_nfd(FDDFILE fdd) { + FILEH hdl; + UINT32 fddtype; + UINT32 cylinders; + UINT32 offset; + UINT trk; + UINT secsize; + UINT size; + UINT i; + + if (fdd->protect) { + fddlasterror = 0x70; + return(FAILURE); + } + + hdl = file_open(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xc0; + return(FAILURE); + } + + secsize = 128 << fdc.N; + size = secsize * fdc.sc; + trk = (fdc.treg[fdc.us] << 1) + fdc.hd; + memset(fdc.buf, fdc.d, size); + + fddtype = 0x90; + if (fdc.N == 2) { + if (fdc.sc < 10) { + fddtype = 0x10; + } + else if (fdc.sc > 16) { + fddtype = 0x30; + } + } + + if (trk == 0) { + ZeroMemory(fdd->inf.nfd.head.r0.si, sizeof(fdd->inf.nfd.head.r0.si)); + offset = fdd->inf.xdf.headersize; + } else { + offset = fdd->inf.nfd.tptr[trk]; + } + fdd->inf.nfd.tptr[trk + 1] = offset + size; + + for (i = 0; i < fdc.sc; i++) { + fdd->inf.nfd.head.r0.si[trk][i].C = fdc.treg[fdc.us]; + fdd->inf.nfd.head.r0.si[trk][i].H = fdc.hd; + fdd->inf.nfd.head.r0.si[trk][i].R = i + 1; + fdd->inf.nfd.head.r0.si[trk][i].N = fdc.N; + fdd->inf.nfd.head.r0.si[trk][i].flMFM = 1; + fdd->inf.nfd.head.r0.si[trk][i].flDDAM = 0; + fdd->inf.nfd.head.r0.si[trk][i].byStatus = 0; + fdd->inf.nfd.head.r0.si[trk][i].byST0 = fdc.hd << 2; + fdd->inf.nfd.head.r0.si[trk][i].byST1 = 0; + fdd->inf.nfd.head.r0.si[trk][i].byST2 = 0; + fdd->inf.nfd.head.r0.si[trk][i].byPDA = fddtype; + fdd->inf.nfd.ptr[trk][i] = offset; + offset += secsize; + } + if (trk == 0) { + for (; i < NFD_TRKMAX * NFD_SECMAX; i++) { + fdd->inf.nfd.head.r0.si[trk][i].C = 0xff; + fdd->inf.nfd.head.r0.si[trk][i].H = 0xff; + fdd->inf.nfd.head.r0.si[trk][i].R = 0xff; + fdd->inf.nfd.head.r0.si[trk][i].N = 0xff; + fdd->inf.nfd.head.r0.si[trk][i].flMFM = 0xff; + fdd->inf.nfd.head.r0.si[trk][i].flDDAM = 0xff; + fdd->inf.nfd.head.r0.si[trk][i].byStatus = 0xe0; + fdd->inf.nfd.head.r0.si[trk][i].byST0 = 0x40 | (fdc.hd << 2); + fdd->inf.nfd.head.r0.si[trk][i].byST1 = 1; + fdd->inf.nfd.head.r0.si[trk][i].byST2 = 0; + fdd->inf.nfd.head.r0.si[trk][i].byPDA = 0; + } + } + + if ((file_seek(hdl, 0, FSEEK_SET) != 0) || + (file_write(hdl, &fdd->inf.nfd.head, NFD_HEADERSIZE) != NFD_HEADERSIZE)) { + file_close(hdl); + fddlasterror = 0xc0; + return(FAILURE); + } + + offset = fdd->inf.nfd.ptr[trk][0]; + if ((file_seek(hdl, offset, FSEEK_SET) != offset) || + (file_write(hdl, fdc.buf, size) != size)) { + file_close(hdl); + fddlasterror = 0xc0; + return(FAILURE); + } + + if (trk == 0) { + fdd->inf.xdf.disktype = DISKTYPE_2HD; + cylinders = 77; + switch(fdc.N) { + case 1: // BASIC (sector size = 256) + break; + case 2: // 1.44M/1.21M/2DD + if (fdc.sc < 10) { + fdd->inf.xdf.disktype = DISKTYPE_2DD; + } + cylinders = 80; + break; + default: // 1.25M + break; + } + + fdd->inf.xdf.tracks = (UINT8)(cylinders * 2); + fdd->inf.xdf.sectors = fdc.sc; + fdd->inf.xdf.n = fdc.N; + fdd->inf.xdf.rpm = fdc.rpm[fdc.us]; + + // trim media image + offset = fdd->inf.xdf.tracks * size + fdd->inf.xdf.headersize; + file_seek(hdl, offset, FSEEK_SET); + file_write(hdl, fdc.buf, 0); + } + + file_close(hdl); + fddlasterror = 0x00; + return(SUCCESS); +} +/* 170107 to supprt format command ... to */ + +// 追加(kaiD) +BRESULT fdd_seeksector_nfd1(FDDFILE fdd) { + + FILEH hdl; + UINT trk; + BYTE MaxR; + UINT i; + NFD_TRACK_ID1 trk_id; + NFD_SECT_ID1 sec_id; + + if ((CTRL_FDMEDIA != fdd->inf.xdf.disktype) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (fdc.treg[fdc.us] >= (fdd->inf.xdf.tracks >> 1))) { + TRACEOUT(("fdd_seek_nfd1 FAILURE CTRL_FDMEDIA[%02x], DISKTYPE[%02x]", CTRL_FDMEDIA, fdd->inf.xdf.disktype)); + TRACEOUT(("fdd_seek_nfd1 FAILURE fdc.rpm[%02x], fdd->rpm[%02x]", fdc.rpm[fdc.us], fdd->inf.xdf.rpm)); + TRACEOUT(("fdd_seek_nfd1 FAILURE fdc.treg[%02x], fdd->trk[%02x]", fdc.treg[fdc.us], (fdd->inf.xdf.tracks >> 1))); + fddlasterror = 0xe0; + return(FAILURE); + } + if (!fdc.R) { + TRACEOUT(("fdd_seek_nfd1 FAILURE fdc.R[%02x]", fdc.R)); + fddlasterror = 0xc0; + return(FAILURE); + } + + hdl = file_open_rb(fdd->fname); + if (hdl == FILEH_INVALID) { + TRACEOUT(("fdd_seek_nfd1 FAILURE ... 1")); + fddlasterror = 0xe0; + return(FAILURE); + } + trk = (fdc.treg[fdc.us] << 1) + fdc.hd; + file_seek(hdl, LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[trk])), FSEEK_SET); + file_read(hdl, &trk_id, sizeof(NFD_TRACK_ID1)); +// TRACEOUT(("fdd_seek_nfd1 read track_id[%03d:%08x]", trk, fdd->inf.nfd.head.r1.dwTrackHead[trk])); + MaxR = 0; + for (i = 0; i < LOADINTELWORD(&(trk_id.wSector)); i++) { + file_read(hdl, &sec_id, sizeof(NFD_SECT_ID1)); +// TRACEOUT(("fdd_seek_nfd1 read sector_id[C:%02x,H:%02x,R:%02x,N:%02x]", sec_id.C, sec_id.H, sec_id.R, sec_id.N)); + if (sec_id.R > MaxR) { + MaxR = sec_id.R; + } + } + file_close(hdl); + + if (fdc.R > MaxR) { + TRACEOUT(("fdd_seek_nfd1 FAILURE fdc.R[%02x],MaxR[%02x]", fdc.R, MaxR)); + fddlasterror = 0xc0; + return(FAILURE); + } + if ((fdc.mf != 0xff) && (fdc.mf != 0x40)) { + TRACEOUT(("fdd_seek_nfd1 FAILURE fdc.mf[%02x]", fdc.mf)); + fddlasterror = 0xc0; + return(FAILURE); + } + return(SUCCESS); +} + +// RetryData有の対応…いいのか?これで +static UINT8 rcnt = 0; + +BRESULT fdd_read_nfd1(FDDFILE fdd) { + + FILEH hdl; + UINT trk; + UINT sec; + UINT secR; + UINT secsize; + long seekp; + long ex_offset; + long ex_offset2; + UINT i; + UINT8 MaxRetry; + NFD_TRACK_ID1 trk_id; + NFD_SECT_ID1 sec_id; + NFD_SECT_ID1 sec_idx; + NFD_DIAG_ID1 dia_id; + + // RetryData有の対応…いいのか?これで + rcnt++; + + fddlasterror = 0x00; + if (fdd_seeksector_nfd1(fdd)) { + TRACEOUT(("NFD(r1) read failure ... seeksector")); + return(FAILURE); + } + trk = (fdc.treg[fdc.us] << 1) + fdc.hd; + /* 170107 modified to work on Windows 9x/2000 form ... */ + if (fdc.eot && !fdd->inf.nfd.ptr[trk][fdc.eot - 1]) { + fddlasterror = 0xc0; + return(FAILURE); + } + /* 170107 modified to work on Windows 9x/2000 ... to */ + sec = fdc.R - 1; + secR = 0xff; + ex_offset = 0; + ex_offset2 = 0; + MaxRetry = 0; + hdl = file_open_rb(fdd->fname); + if (hdl == FILEH_INVALID) { + TRACEOUT(("NFD(r1) read failure ... FILE OPEN")); + fddlasterror = 0xe0; + return(FAILURE); + } + file_seek(hdl, LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[trk])), FSEEK_SET); + file_read(hdl, &trk_id, sizeof(NFD_TRACK_ID1)); + for (i = 0; i < LOADINTELWORD(&(trk_id.wSector)); i++) { + file_read(hdl, &sec_idx, sizeof(NFD_SECT_ID1)); + TRACEOUT(("NFD(r1) read NOR trk[%03d]: C[%02x]:H[%02x]:R[%02x]:N[%02x]:MFM[%02x]:DDAM[%02x]:Retry[%02x]:PDA[%02x]", + trk, sec_idx.C, sec_idx.H, sec_idx.R, sec_idx.N, sec_idx.flMFM, sec_idx.flDDAM, sec_idx.byRetry, sec_idx.byPDA)); + if (sec_idx.R == fdc.R) { + secR = i; + memcpy(&sec_id, &sec_idx, sizeof(NFD_SECT_ID1)); + MaxRetry = sec_idx.byRetry; +// break; + } +// ex_offset += 128 << sec_id.N; + } + if (secR == 0xff) { + TRACEOUT(("NFD(r1) read failure ... R[%0x2] not found", fdc.R)); + file_close(hdl); + return(FAILURE); + } + + if (fdc.N != sec_id.N) { + BOOL flg; + TRACEOUT(("NFD(r1) read failure ... N not match : fdc.n:[%02x],sec_id.N:[%02x]", fdc.N, sec_id.N)); +#if 1 + flg = FALSE; + for (i = 0; i < LOADINTELWORD(&(trk_id.wDiag)); i++) { + file_read(hdl, &dia_id, sizeof(NFD_DIAG_ID1)); + TRACEOUT(("NFD(r1) read DIA trk[%03d]:Cmd[%02x]:C[%02x]:H[%02x]:R[%02x]:N[%02x]:Len[%08x]:Retry[%02x]", + trk, dia_id.Cmd, dia_id.C, dia_id.H, dia_id.R, dia_id.N, dia_id.dwDataLen, dia_id.byRetry)); + if (fdc.N == dia_id.N) { + TRACEOUT(("\tfound diag data")); + flg = TRUE; + break; + } + ex_offset2 += LOADINTELDWORD(&(dia_id.dwDataLen)); + } +#endif + if (flg == FALSE) { + fddlasterror = 0xc0; + file_close(hdl); + return(FAILURE); + } + } + + if (fdd->type == DISKTYPE_NFD) { + if (fdc.N == sec_id.N) { + secsize = 128 << sec_id.N; + seekp = fdd->inf.nfd.ptr[trk][sec]; + // RetryData有の対応…いいのか?これで + seekp += secsize * (MaxRetry ? (rcnt % MaxRetry) : 0); + } + else { + secsize = LOADINTELDWORD(&(dia_id.dwDataLen)); + seekp = fdd->inf.nfd.ptr[trk][sec] + fdd->inf.nfd.trksize[trk] + ex_offset2; + } + + TRACEOUT(("NFD(r1) read seek to ... [%08x]", seekp)); + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_read(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xe0; + TRACEOUT(("NFD(r1) read failure ... FILE SEEK or READ")); + return(FAILURE); + } + } + else { + fddlasterror = 0xc0; + file_close(hdl); + return(FAILURE); + } + file_close(hdl); + + // イメージ内情報のREAD DATA RESULTを反映 + fdc.stat[fdc.us] = sec_id.bySTS0 | (sec_id.bySTS1 << 8) | (sec_id.bySTS2 << 16); + fddlasterror = sec_id.byStatus; + fdc.bufcnt = secsize; + TRACEOUT(("NFD(r1) read FDC Result Status[%02x],STS0[%02x],STS1[%02x],STS2[%02x]", + sec_id.byStatus, sec_id.bySTS0, sec_id.bySTS1, sec_id.bySTS2)); + TRACEOUT(("NFD(r1) read C:%02x,H:%02x,R:%02x,N:%02x", fdc.C, fdc.H, fdc.R, fdc.N)); + TRACEOUT(("NFD(r1) read dump")); + TRACEOUT(("\t%02x %02x %02x %02x %02x %02x %02x %02x", + fdc.buf[0x00], fdc.buf[0x01], fdc.buf[0x02], fdc.buf[0x03], fdc.buf[0x04], fdc.buf[0x05], fdc.buf[0x06], fdc.buf[0x07])); + return(SUCCESS); +} + +BRESULT fdd_write_nfd1(FDDFILE fdd) { + + FILEH hdl; + UINT trk; + UINT sec; + UINT secR; + UINT secsize; + long seekp; + UINT i; + NFD_TRACK_ID1 trk_id; + NFD_SECT_ID1 sec_id; + + fddlasterror = 0x00; + if (fdd_seeksector_nfd1(fdd)) { + fddlasterror = 0xe0; + return(FAILURE); + } + if (fdd->protect) { + fddlasterror = 0x70; + return(FAILURE); + } + trk = (fdc.treg[fdc.us] << 1) + fdc.hd; + /* 170107 modified to work on Windows 9x/2000 form ... */ + if (fdc.eot && !fdd->inf.nfd.ptr[trk][fdc.eot - 1]) { + fddlasterror = 0xc0; + return(FAILURE); + } + /* 170107 modified to work on Windows 9x/2000 ... to */ + sec = fdc.R - 1; + secR = 0xff; + hdl = file_open(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xe0; + return(FAILURE); + } + file_seek(hdl, LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[trk])), FSEEK_SET); + file_read(hdl, &trk_id, sizeof(NFD_TRACK_ID1)); + for (i = 0; i < LOADINTELWORD(&(trk_id.wSector)); i++) { + file_read(hdl, &sec_id, sizeof(NFD_SECT_ID1)); + if (sec_id.R == fdc.R) { + secR = i; + break; + } + } + if (secR == 0xff) { + file_close(hdl); + return(FAILURE); + } + if (fdc.N != sec_id.N) { + fddlasterror = 0xc0; + file_close(hdl); + return(FAILURE); + } + + if (fdd->type == DISKTYPE_NFD) { + secsize = 128 << sec_id.N; + seekp = fdd->inf.nfd.ptr[trk][sec]; + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_write(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xc0; + return(FAILURE); + } + } + else { + fddlasterror = 0xc0; + file_close(hdl); + return(FAILURE); + } + + file_close(hdl); + fdc.bufcnt = secsize; + fddlasterror = 0x00; + + return(SUCCESS); +} + +BRESULT fdd_readid_nfd1(FDDFILE fdd) { + + FILEH hdl; + UINT trk; + UINT sec; + UINT i; + NFD_TRACK_ID1 trk_id; + NFD_SECT_ID1 sec_id; + + /* 170107 modified to work on Windows 9x/2000 form ... */ + if (fdc.crcn >= fdd->inf.xdf.sectors) { + fdc.crcn = 0; + if(fdc.mt) { + fdc.hd ^= 1; + if (fdc.hd == 0) { + fdc.treg[fdc.us]++; + } + } + else { + fdc.treg[fdc.us]++; + } + } + /* 170107 modified to work on Windows 9x/2000 ... to */ + fddlasterror = 0x00; + if ((!fdc.mf) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (CTRL_FDMEDIA != fdd->inf.xdf.disktype)) { + //(fdc.crcn >= fdd->inf.xdf.sectors)) { + fddlasterror = 0xe0; + return(FAILURE); + } + fdc.C = fdc.treg[fdc.us]; + fdc.H = fdc.hd; + fdc.R = ++fdc.crcn; + trk = (fdc.C << 1) + fdc.H; + sec = 0xff; + hdl = file_open_rb(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xe0; + return(FAILURE); + } + file_seek(hdl, LOADINTELDWORD(&(fdd->inf.nfd.head.r1.dwTrackHead[trk])), FSEEK_SET); + file_read(hdl, &trk_id, sizeof(NFD_TRACK_ID1)); + for (i = 0; i < LOADINTELWORD(&(trk_id.wSector)); i++) { + file_read(hdl, &sec_id, sizeof(NFD_SECT_ID1)); + if (sec_id.R == fdc.R) { + sec = i; + break; + } + } + file_close(hdl); + if (sec == 0xff) { + fddlasterror = 0xe0; + return(FAILURE); + } + fdc.N = sec_id.N; + return(SUCCESS); +} +// + +#endif diff --git a/diskimage/fd/fdd_nfd.h b/diskimage/fd/fdd_nfd.h old mode 100755 new mode 100644 index 330f2737..696139c4 --- a/diskimage/fd/fdd_nfd.h +++ b/diskimage/fd/fdd_nfd.h @@ -1,22 +1,22 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT fdd_set_nfd(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); - -BRESULT fdd_seeksector_nfd(FDDFILE fdd); // 追加(kaiE) -BRESULT fdd_read_nfd(FDDFILE fdd); -BRESULT fdd_write_nfd(FDDFILE fdd); -BRESULT fdd_readid_nfd(FDDFILE fdd); -BRESULT fdd_formatinit_nfd(FDDFILE fdd); /* 170107 to support format command */ - -BRESULT fdd_seeksector_nfd1(FDDFILE fdd); // 追加(kaiD) -BRESULT fdd_read_nfd1(FDDFILE fdd); // 追加(kaiD) -BRESULT fdd_write_nfd1(FDDFILE fdd); // 追加(kaiD) -BRESULT fdd_readid_nfd1(FDDFILE fdd); // 追加(kaiD) - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT fdd_set_nfd(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); + +BRESULT fdd_seeksector_nfd(FDDFILE fdd); // 追加(kaiE) +BRESULT fdd_read_nfd(FDDFILE fdd); +BRESULT fdd_write_nfd(FDDFILE fdd); +BRESULT fdd_readid_nfd(FDDFILE fdd); +BRESULT fdd_formatinit_nfd(FDDFILE fdd); /* 170107 to support format command */ + +BRESULT fdd_seeksector_nfd1(FDDFILE fdd); // 追加(kaiD) +BRESULT fdd_read_nfd1(FDDFILE fdd); // 追加(kaiD) +BRESULT fdd_write_nfd1(FDDFILE fdd); // 追加(kaiD) +BRESULT fdd_readid_nfd1(FDDFILE fdd); // 追加(kaiD) + +#ifdef __cplusplus +} +#endif + diff --git a/diskimage/fd/fdd_vfdd.c b/diskimage/fd/fdd_vfdd.c old mode 100755 new mode 100644 index 3e0f848b..6c320b1a --- a/diskimage/fd/fdd_vfdd.c +++ b/diskimage/fd/fdd_vfdd.c @@ -1,276 +1,276 @@ -#include -#include -#include -#include - -#ifdef SUPPORT_KAI_IMAGES - -#include -#include "diskimage/fd/fdd_vfdd.h" - -static const UINT8 vfdd_verID_100[8] = - {'V','F','D','1','.','0','0', 0x00}; -static const UINT8 vfdd_verID_101[8] = - {'V','F','D','1','.','0','1', 0x00}; // 1.01もとりあえず対象に(kaiF) - -BRESULT fdd_set_vfdd(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { - -const _VFDD_ID *sec_vfdd; - short attr; - FILEH fh; - UINT rsize; - UINT i; - - attr = file_attr(fname); - if (attr & 0x18) { - return(FAILURE); - } - if(!ro) { - if(attr & FILEATTR_READONLY) { - ro = 1; - } - } - if(ro) { - fh = file_open_rb(fname); - } else { - fh = file_open(fname); - } - if (fh == FILEH_INVALID) { - return(FAILURE); - } - rsize = file_read(fh, &fdd->inf.vfdd.head, VFDD_HEADERSIZE); // VFDDヘッダ読込 - file_close(fh); - if (rsize != VFDD_HEADERSIZE) { - return(FAILURE); - } - - // バージョンIDチェック - if (memcmp(fdd->inf.vfdd.head.verID, vfdd_verID_100, 8)) { - if (memcmp(fdd->inf.vfdd.head.verID, vfdd_verID_101, 8)) { // 1.01もとりあえず対象に(kaiF) - return(FAILURE); - } - } - - fdd->type = DISKTYPE_VFDD; - fdd->protect = ((attr & 0x01) || (ro)) ? TRUE : FALSE; - if (LOADINTELWORD(&fdd->inf.vfdd.head.write_protect)) { - fdd->protect = TRUE; - } - - // 最大値入れて平気? - fdd->inf.xdf.tracks = VFDD_TRKMAX; - fdd->inf.xdf.sectors = VFDD_SECMAX; - - sec_vfdd = &fdd->inf.vfdd.id[0][0]; - // ディスクアクセス時用に各セクタのオフセットを算出 - for (i = 0; i < VFDD_TRKMAX * VFDD_SECMAX; i++) { - if (sec_vfdd->C != 0xff) { - fdd->inf.vfdd.ptr[(sec_vfdd->C << 1) + sec_vfdd->H][sec_vfdd->R - 1] = LOADINTELDWORD(&sec_vfdd->dataPoint); - } - sec_vfdd++; - } - - // 先頭格納セクタを見て決め打ち - // …2DD/2HD混在フォーマットでまずい気がする - sec_vfdd = &fdd->inf.vfdd.id[0][0]; - if (sec_vfdd->flHD) { - /* 1.2M */ - fdd->inf.xdf.disktype = DISKTYPE_2HD; - fdd->inf.xdf.rpm = 0; - sec_vfdd = &fdd->inf.vfdd.id[0][17]; - if (sec_vfdd->flMF == 0x01 && sec_vfdd->flHD == 0x01) { - /* 1.44M(暫定) */ - fdd->inf.xdf.rpm = 1; - } - } - else { - // 640K - fdd->inf.xdf.disktype = DISKTYPE_2DD; - fdd->inf.xdf.rpm = 0; - } - - // 処理関数群を登録 - fdd_fn->eject = fdd_eject_xxx; - fdd_fn->diskaccess = fdd_diskaccess_common; - fdd_fn->seek = fdd_seek_common; - fdd_fn->seeksector = fdd_seeksector_common; - fdd_fn->read = fdd_read_vfdd; - fdd_fn->write = fdd_write_vfdd; - fdd_fn->readid = fdd_readid_vfdd; - fdd_fn->writeid = fdd_dummy_xxx; - fdd_fn->formatinit = fdd_dummy_xxx; - fdd_fn->formating = fdd_formating_xxx; - fdd_fn->isformating = fdd_isformating_xxx; - - return(SUCCESS); -} - -BRESULT fdd_read_vfdd(FDDFILE fdd) { - - FILEH hdl; - UINT trk; - UINT sec; - UINT secR; - UINT secsize; - long seekp; - UINT i; - - fddlasterror = 0x00; - if (fdd_seeksector_common(fdd)) { - return(FAILURE); - } - trk = (fdc.treg[fdc.us] << 1) + fdc.hd; - sec = fdc.R - 1; - secR = 0xff; - for (i = 0; i < VFDD_SECMAX; i++) { - if (fdd->inf.vfdd.id[trk][i].R == fdc.R) { - secR = i; - break; - } - } - if (secR == 0xff) { - return(FAILURE); - } - if (fdc.N != fdd->inf.vfdd.id[trk][secR].N) { - fddlasterror = 0xc0; - return(FAILURE); - } - - if (fdd->type == DISKTYPE_VFDD) { - secsize = 128 << fdd->inf.vfdd.id[trk][secR].N; -// seekp = (long)fdd->inf.vfdd.ptr[trk][sec]; - if (fdd->inf.vfdd.ptr[trk][sec] == 0xffffffff || fdd->inf.vfdd.ptr[trk][sec] == 0x00000000) { - FillMemory(fdc.buf, secsize, fdd->inf.vfdd.id[trk][secR].D); - } - else { - seekp = fdd->inf.vfdd.ptr[trk][sec]; - hdl = file_open_rb(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xe0; - return(FAILURE); - } - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_read(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xe0; - return(FAILURE); - } - file_close(hdl); - } - } - else { - fddlasterror = 0xc0; - return(FAILURE); - } - - fdc.bufcnt = secsize; - fddlasterror = 0x00; - return(SUCCESS); -} - -BRESULT fdd_write_vfdd(FDDFILE fdd) { - - FILEH hdl; - UINT trk; - UINT sec; - UINT secR; - UINT secsize; - long seekp; - UINT i; - - fddlasterror = 0x00; - if (fdd_seeksector_common(fdd)) { - fddlasterror = 0xe0; - return(FAILURE); - } - if (fdd->protect) { - fddlasterror = 0x70; - return(FAILURE); - } - trk = (fdc.treg[fdc.us] << 1) + fdc.hd; - sec = fdc.R - 1; - secR = 0xff; - for (i = 0; i < VFDD_SECMAX; i++) { - if (fdd->inf.vfdd.id[trk][i].R == fdc.R) { - secR = i; - break; - } - } - if (secR == 0xff) { - return(FAILURE); - } - if (fdc.N != fdd->inf.vfdd.id[trk][secR].N) { - fddlasterror = 0xc0; - return(FAILURE); - } - - if (fdd->type == DISKTYPE_VFDD) { - hdl = file_open(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xc0; - return(FAILURE); - } - secsize = 128 << fdd->inf.vfdd.id[trk][secR].N; - seekp = fdd->inf.vfdd.ptr[trk][sec]; - if (seekp == -1 || seekp == 0) { - UINT32 fdsize; - - fdsize = (UINT32)file_getsize(hdl); - STOREINTELDWORD(&fdd->inf.vfdd.id[trk][secR].dataPoint, fdsize); - fdd->inf.vfdd.ptr[trk][sec] = fdsize; - file_seek(hdl, 0, 0); - file_write(hdl, &fdd->inf.vfdd.head, VFDD_HEADERSIZE); - seekp = fdsize; - } - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_write(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xc0; - return(FAILURE); - } - file_close(hdl); - } - else { - fddlasterror = 0xc0; - return(FAILURE); - } - - fdc.bufcnt = secsize; - fddlasterror = 0x00; - - return(SUCCESS); -} - -BRESULT fdd_readid_vfdd(FDDFILE fdd) { - - UINT trk; - UINT sec; - UINT i; - - fddlasterror = 0x00; - if ((!fdc.mf) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (fdc.crcn >= fdd->inf.xdf.sectors)) { - fddlasterror = 0xe0; - return(FAILURE); - } - fdc.C = fdc.treg[fdc.us]; - fdc.H = fdc.hd; - fdc.R = ++fdc.crcn; - trk = (fdc.C << 1) + fdc.H; - sec = 0xff; - for (i = 0; i < VFDD_SECMAX; i++) { - if (fdd->inf.vfdd.id[trk][i].R == fdc.R) { - sec = i; - break; - } - } - if (sec == 0xff) { - fddlasterror = 0xe0; - return(FAILURE); - } - fdc.N = fdd->inf.vfdd.id[trk][sec].N; - return(SUCCESS); -} - -#endif +#include +#include +#include +#include + +#ifdef SUPPORT_KAI_IMAGES + +#include +#include "diskimage/fd/fdd_vfdd.h" + +static const UINT8 vfdd_verID_100[8] = + {'V','F','D','1','.','0','0', 0x00}; +static const UINT8 vfdd_verID_101[8] = + {'V','F','D','1','.','0','1', 0x00}; // 1.01もとりあえず対象に(kaiF) + +BRESULT fdd_set_vfdd(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { + +const _VFDD_ID *sec_vfdd; + short attr; + FILEH fh; + UINT rsize; + UINT i; + + attr = file_attr(fname); + if (attr & 0x18) { + return(FAILURE); + } + if(!ro) { + if(attr & FILEATTR_READONLY) { + ro = 1; + } + } + if(ro) { + fh = file_open_rb(fname); + } else { + fh = file_open(fname); + } + if (fh == FILEH_INVALID) { + return(FAILURE); + } + rsize = file_read(fh, &fdd->inf.vfdd.head, VFDD_HEADERSIZE); // VFDDヘッダ読込 + file_close(fh); + if (rsize != VFDD_HEADERSIZE) { + return(FAILURE); + } + + // バージョンIDチェック + if (memcmp(fdd->inf.vfdd.head.verID, vfdd_verID_100, 8)) { + if (memcmp(fdd->inf.vfdd.head.verID, vfdd_verID_101, 8)) { // 1.01もとりあえず対象に(kaiF) + return(FAILURE); + } + } + + fdd->type = DISKTYPE_VFDD; + fdd->protect = ((attr & 0x01) || (ro)) ? TRUE : FALSE; + if (LOADINTELWORD(&fdd->inf.vfdd.head.write_protect)) { + fdd->protect = TRUE; + } + + // 最大値入れて平気? + fdd->inf.xdf.tracks = VFDD_TRKMAX; + fdd->inf.xdf.sectors = VFDD_SECMAX; + + sec_vfdd = &fdd->inf.vfdd.id[0][0]; + // ディスクアクセス時用に各セクタのオフセットを算出 + for (i = 0; i < VFDD_TRKMAX * VFDD_SECMAX; i++) { + if (sec_vfdd->C != 0xff) { + fdd->inf.vfdd.ptr[(sec_vfdd->C << 1) + sec_vfdd->H][sec_vfdd->R - 1] = LOADINTELDWORD(&sec_vfdd->dataPoint); + } + sec_vfdd++; + } + + // 先頭格納セクタを見て決め打ち + // …2DD/2HD混在フォーマットでまずい気がする + sec_vfdd = &fdd->inf.vfdd.id[0][0]; + if (sec_vfdd->flHD) { + /* 1.2M */ + fdd->inf.xdf.disktype = DISKTYPE_2HD; + fdd->inf.xdf.rpm = 0; + sec_vfdd = &fdd->inf.vfdd.id[0][17]; + if (sec_vfdd->flMF == 0x01 && sec_vfdd->flHD == 0x01) { + /* 1.44M(暫定) */ + fdd->inf.xdf.rpm = 1; + } + } + else { + // 640K + fdd->inf.xdf.disktype = DISKTYPE_2DD; + fdd->inf.xdf.rpm = 0; + } + + // 処理関数群を登録 + fdd_fn->eject = fdd_eject_xxx; + fdd_fn->diskaccess = fdd_diskaccess_common; + fdd_fn->seek = fdd_seek_common; + fdd_fn->seeksector = fdd_seeksector_common; + fdd_fn->read = fdd_read_vfdd; + fdd_fn->write = fdd_write_vfdd; + fdd_fn->readid = fdd_readid_vfdd; + fdd_fn->writeid = fdd_dummy_xxx; + fdd_fn->formatinit = fdd_dummy_xxx; + fdd_fn->formating = fdd_formating_xxx; + fdd_fn->isformating = fdd_isformating_xxx; + + return(SUCCESS); +} + +BRESULT fdd_read_vfdd(FDDFILE fdd) { + + FILEH hdl; + UINT trk; + UINT sec; + UINT secR; + UINT secsize; + long seekp; + UINT i; + + fddlasterror = 0x00; + if (fdd_seeksector_common(fdd)) { + return(FAILURE); + } + trk = (fdc.treg[fdc.us] << 1) + fdc.hd; + sec = fdc.R - 1; + secR = 0xff; + for (i = 0; i < VFDD_SECMAX; i++) { + if (fdd->inf.vfdd.id[trk][i].R == fdc.R) { + secR = i; + break; + } + } + if (secR == 0xff) { + return(FAILURE); + } + if (fdc.N != fdd->inf.vfdd.id[trk][secR].N) { + fddlasterror = 0xc0; + return(FAILURE); + } + + if (fdd->type == DISKTYPE_VFDD) { + secsize = 128 << fdd->inf.vfdd.id[trk][secR].N; +// seekp = (long)fdd->inf.vfdd.ptr[trk][sec]; + if (fdd->inf.vfdd.ptr[trk][sec] == 0xffffffff || fdd->inf.vfdd.ptr[trk][sec] == 0x00000000) { + FillMemory(fdc.buf, secsize, fdd->inf.vfdd.id[trk][secR].D); + } + else { + seekp = fdd->inf.vfdd.ptr[trk][sec]; + hdl = file_open_rb(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xe0; + return(FAILURE); + } + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_read(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xe0; + return(FAILURE); + } + file_close(hdl); + } + } + else { + fddlasterror = 0xc0; + return(FAILURE); + } + + fdc.bufcnt = secsize; + fddlasterror = 0x00; + return(SUCCESS); +} + +BRESULT fdd_write_vfdd(FDDFILE fdd) { + + FILEH hdl; + UINT trk; + UINT sec; + UINT secR; + UINT secsize; + long seekp; + UINT i; + + fddlasterror = 0x00; + if (fdd_seeksector_common(fdd)) { + fddlasterror = 0xe0; + return(FAILURE); + } + if (fdd->protect) { + fddlasterror = 0x70; + return(FAILURE); + } + trk = (fdc.treg[fdc.us] << 1) + fdc.hd; + sec = fdc.R - 1; + secR = 0xff; + for (i = 0; i < VFDD_SECMAX; i++) { + if (fdd->inf.vfdd.id[trk][i].R == fdc.R) { + secR = i; + break; + } + } + if (secR == 0xff) { + return(FAILURE); + } + if (fdc.N != fdd->inf.vfdd.id[trk][secR].N) { + fddlasterror = 0xc0; + return(FAILURE); + } + + if (fdd->type == DISKTYPE_VFDD) { + hdl = file_open(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xc0; + return(FAILURE); + } + secsize = 128 << fdd->inf.vfdd.id[trk][secR].N; + seekp = fdd->inf.vfdd.ptr[trk][sec]; + if (seekp == -1 || seekp == 0) { + UINT32 fdsize; + + fdsize = (UINT32)file_getsize(hdl); + STOREINTELDWORD(&fdd->inf.vfdd.id[trk][secR].dataPoint, fdsize); + fdd->inf.vfdd.ptr[trk][sec] = fdsize; + file_seek(hdl, 0, 0); + file_write(hdl, &fdd->inf.vfdd.head, VFDD_HEADERSIZE); + seekp = fdsize; + } + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_write(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xc0; + return(FAILURE); + } + file_close(hdl); + } + else { + fddlasterror = 0xc0; + return(FAILURE); + } + + fdc.bufcnt = secsize; + fddlasterror = 0x00; + + return(SUCCESS); +} + +BRESULT fdd_readid_vfdd(FDDFILE fdd) { + + UINT trk; + UINT sec; + UINT i; + + fddlasterror = 0x00; + if ((!fdc.mf) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (fdc.crcn >= fdd->inf.xdf.sectors)) { + fddlasterror = 0xe0; + return(FAILURE); + } + fdc.C = fdc.treg[fdc.us]; + fdc.H = fdc.hd; + fdc.R = ++fdc.crcn; + trk = (fdc.C << 1) + fdc.H; + sec = 0xff; + for (i = 0; i < VFDD_SECMAX; i++) { + if (fdd->inf.vfdd.id[trk][i].R == fdc.R) { + sec = i; + break; + } + } + if (sec == 0xff) { + fddlasterror = 0xe0; + return(FAILURE); + } + fdc.N = fdd->inf.vfdd.id[trk][sec].N; + return(SUCCESS); +} + +#endif diff --git a/diskimage/fd/fdd_vfdd.h b/diskimage/fd/fdd_vfdd.h old mode 100755 new mode 100644 index 6d885e54..216e075f --- a/diskimage/fd/fdd_vfdd.h +++ b/diskimage/fd/fdd_vfdd.h @@ -1,15 +1,15 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT fdd_set_vfdd(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); - -BRESULT fdd_read_vfdd(FDDFILE fdd); -BRESULT fdd_write_vfdd(FDDFILE fdd); -BRESULT fdd_readid_vfdd(FDDFILE fdd); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT fdd_set_vfdd(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); + +BRESULT fdd_read_vfdd(FDDFILE fdd); +BRESULT fdd_write_vfdd(FDDFILE fdd); +BRESULT fdd_readid_vfdd(FDDFILE fdd); + +#ifdef __cplusplus +} +#endif + diff --git a/diskimage/fd/fdd_xdf.c b/diskimage/fd/fdd_xdf.c old mode 100755 new mode 100644 index 4a58c73b..cd94a9d6 --- a/diskimage/fd/fdd_xdf.c +++ b/diskimage/fd/fdd_xdf.c @@ -1,847 +1,847 @@ -#include -#include -#include -#include - -#include -#include "diskimage/fd/fdd_xdf.h" - -#ifdef SUPPORT_KAI_IMAGES - -// BKDSK(DD6)、BKDSK(DDB)判定用 -//static const OEMCHAR str_dd6[] = OEMTEXT("dd6"); // 未使用なのでコメント(kai9) -static const OEMCHAR str_ddb[] = OEMTEXT("ddb"); -// - -static const _XDFINFO supportxdf[] = { -#if 0 - // 256 - {0, 154, 26, 1, DISKTYPE_2HD, 0}, - // 512 - {0, 154, 15, 2, DISKTYPE_2HD, 0}, -#endif -#if 1 - // 512 - {0, 160, 15, 2, DISKTYPE_2HD, 0}, // BKDSK(HD5) MS-DOS 1.21M(2HC) -#endif - // 1024 - {0, 154, 8, 3, DISKTYPE_2HD, 0}, // XDF他2HD、BIN、FLP等 - // BKDSK(HDM) MS-DOS 1.25M(2HD) - // 1.44MB - {0, 160, 18, 2, DISKTYPE_2HD, 1}, // BKDSK(HD4) MS-DOS 1.44M(2HD) - {0, 160, 21, 2, DISKTYPE_2HD, 1}, // BKDSK MS 2HD-DMF - - // 追加でいくつかのBKDSK形式に対応 - {0, 154, 26, 1, DISKTYPE_2HD, 0}, // BKDSK(H01) 2HD:256byte*26sec (0-154)track - {0, 154, 9, 3, DISKTYPE_2HD, 0}, // BKDSK(HD9) MS-DOS 2HD(9sec) - {0, 160, 8, 2, DISKTYPE_2DD, 0}, // BKDSK(DD6) MS-DOS 640K(2DD) - {0, 160, 9, 2, DISKTYPE_2DD, 0}, // BKDSK(DD9) MS-DOS 720K(2DD) - // track 0とそれ以外でセクタサイズが違うため未対応 -// {0, 154, 26, 1, DISKTYPE_2HD, 0}, // BKDSK(HDB) BASIC 2HD - // - {0, 160, 16, 1, DISKTYPE_2DD, 0}, // BKDSK(DDB) BASIC 2DD - // - // ヘッダサイズを指定し、判定時に考慮するようにすれば - // DIPやDCP/DCU(全トラック格納イメージ)とかもいける - {256, 154, 8, 3, DISKTYPE_2HD, 0}, // DIP 2HD-8セクタ(1.25MB) - // FIM 2HD-8セクタ(1.25MB) - {256, 154, 26, 1, DISKTYPE_2HD, 0}, // FIM 2HD-26セクタ -#if 0 // fdd_dcp.cへ移動(kai9) - {162, 154, 8, 3, DISKTYPE_2HD, 0}, // DCP/DCU 01h 2HD- 8セクタ(1.25MB) - {162, 160, 15, 2, DISKTYPE_2HD, 0}, // DCP/DCU 02h 2HD-15セクタ(1.21MB) - {162, 160, 18, 2, DISKTYPE_2HD, 1}, // DCP/DCU 03h 2HQ-18セクタ(1.44MB) - {162, 160, 8, 2, DISKTYPE_2DD, 0}, // DCP/DCU 04h 2DD- 8セクタ( 640KB) - {162, 160, 9, 2, DISKTYPE_2DD, 0}, // DCP/DCU 05h 2DD- 9セクタ( 720KB) - {162, 154, 9, 3, DISKTYPE_2HD, 0}, // DCP/DCU 08h 2HD- 9セクタ(1.44MB) -// {162, 154, 26, 1, DISKTYPE_2HD, 0}, // DCP/DCU 11h BASIC-2HD - {162, 160, 16, 1, DISKTYPE_2DD, 0}, // DCP/DCU 19h BASIC-2DD - {162, 154, 26, 1, DISKTYPE_2HD, 0}, // DCP/DCU 21h 2HD-26セクタ -#endif - // -}; - -// FDIヘッダ -typedef struct { - UINT8 dummy[4]; - UINT8 fddtype[4]; - UINT8 headersize[4]; - UINT8 fddsize[4]; - UINT8 sectorsize[4]; - UINT8 sectors[4]; - UINT8 surfaces[4]; - UINT8 cylinders[4]; -} FDIHDR; - -//BRESULT fddxdf_set(FDDFILE fdd, const OEMCHAR *fname, int ro) { -BRESULT fdd_set_xdf(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { - -const _XDFINFO *xdf; - short attr; - FILEH fh; - UINT32 fdsize; - UINT size; -const OEMCHAR *p; // BKDSK(DD6) or BKDSK(DDB)判定用 - - attr = file_attr(fname); - if (attr & 0x18) { - return(FAILURE); - } - if(!ro) { - if(attr & FILEATTR_READONLY) { - ro = 1; - } - } - if(ro) { - fh = file_open_rb(fname); - } else { - fh = file_open(fname); - } - if (fh == FILEH_INVALID) { - return(FAILURE); - } - fdsize = (UINT32)file_getsize(fh); - file_close(fh); - - p = file_getext(fname); // BKDSK(DD6) or BKDSK(DDB)判定用 - - xdf = supportxdf; - while(xdf < (supportxdf + NELEMENTS(supportxdf))) { - size = xdf->tracks; - size *= xdf->sectors; - size <<= (7 + xdf->n); - // ヘッダサイズを考慮するように - size += xdf->headersize; - // - if (size == fdsize) { - // BKDSK(DD6)とBKDSK(DDB)が同一サイズのため、拡張子で判定 - if (!milstr_cmp(p, str_ddb) && xdf->sectors == 8) { - xdf++; - continue; - } - // - fdd->type = DISKTYPE_BETA; - fdd->protect = ((attr & 1) || (ro))?TRUE:FALSE; - fdd->inf.xdf = *xdf; - // 処理関数群を登録(kai9) - fdd_fn->eject = fdd_eject_xxx; -// fdd_fn->diskaccess = fdd_diskaccess_xdf; -// fdd_fn->seek = fdd_seek_xdf; -// fdd_fn->seeksector = fdd_seeksector_xdf; - fdd_fn->diskaccess = fdd_diskaccess_common; - fdd_fn->seek = fdd_seek_common; - fdd_fn->seeksector = fdd_seeksector_common; - fdd_fn->read = fdd_read_xdf; - fdd_fn->write = fdd_write_xdf; -// fdd_fn->readid = fdd_readid_xdf; - fdd_fn->readid = fdd_readid_common; - fdd_fn->writeid = fdd_dummy_xxx; - fdd_fn->formatinit = fdd_formatinit_xdf; /* 170107 to support format command */ - fdd_fn->formating = fdd_formating_xxx; - fdd_fn->isformating = fdd_isformating_xxx; - // - return(SUCCESS); - } - xdf++; - } - return(FAILURE); -} - -// こっそり対応したりして -//BRESULT fddxdf_setfdi(FDDFILE fdd, const OEMCHAR *fname, int ro) { -BRESULT fdd_set_fdi(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { - - short attr; - FILEH fh; - UINT32 fdsize; - UINT r; - FDIHDR fdi; - UINT32 fddtype; - UINT32 headersize; - UINT32 size; - UINT32 sectors; - UINT32 surfaces; - UINT32 cylinders; - UINT8 n; - UINT8 disktype; - UINT8 rpm; - - attr = file_attr(fname); - if (attr & 0x18) { - return(FAILURE); - } - fdsize = 0; - r = 0; - if(!ro) { - if(attr & FILEATTR_READONLY) { - ro = 1; - } - } - if(ro) { - fh = file_open_rb(fname); - } else { - fh = file_open(fname); - } - if (fh != FILEH_INVALID) { - fdsize = (UINT32)file_getsize(fh); - r = file_read(fh, &fdi, sizeof(fdi)); - file_close(fh); - } - if (r != sizeof(fdi)) { - return(FAILURE); - } - fddtype = LOADINTELDWORD(fdi.fddtype); - headersize = LOADINTELDWORD(fdi.headersize); - size = LOADINTELDWORD(fdi.sectorsize); - sectors = LOADINTELDWORD(fdi.sectors); - surfaces = LOADINTELDWORD(fdi.surfaces); - cylinders = LOADINTELDWORD(fdi.cylinders); - if (((size & (size - 1)) != 0) || (!(size & 0x7f80)) || - (sectors == 0) || (sectors >= 256) || - (surfaces != 2) || - (cylinders == 0) || (cylinders >= 128)) { - return(FAILURE); - } - if (fdsize != (headersize + (size * sectors * surfaces * cylinders))) { - return(FAILURE); - } - size >>= 8; - n = 0; - while(size) { - size >>= 1; - n++; - } - disktype = DISKTYPE_2HD; - rpm = 0; - switch(fddtype & 0xf0) { - case 0x10: // 1MB/640KB - 2DD - case 0x70: // 640KB - 2DD - case 0xf0: - disktype = DISKTYPE_2DD; - break; - - case 0x30: // 1.44MB - 2HD - case 0xb0: - rpm = 1; - break; - - case 0x50: // 320KB - 2D - case 0xd0: // - disktype = DISKTYPE_2D; - break; - - case 0x90: // 2HD - break; - - default: - return(FAILURE); - } - fdd->type = DISKTYPE_BETA; - fdd->protect = ((attr & 1) || (ro))?TRUE:FALSE; - fdd->inf.xdf.headersize = headersize; - fdd->inf.xdf.tracks = (UINT8)(cylinders * 2); - fdd->inf.xdf.sectors = (UINT8)sectors; - fdd->inf.xdf.n = n; - fdd->inf.xdf.disktype = disktype; - fdd->inf.xdf.rpm = rpm; - // 処理関数群を登録(kai9) - fdd_fn->eject = fdd_eject_xxx; - fdd_fn->diskaccess = fdd_diskaccess_common; - fdd_fn->seek = fdd_seek_common; - fdd_fn->seeksector = fdd_seeksector_common; - fdd_fn->read = fdd_read_xdf; - fdd_fn->write = fdd_write_xdf; - fdd_fn->readid = fdd_readid_common; - fdd_fn->writeid = fdd_dummy_xxx; - fdd_fn->formatinit = fdd_formatinit_xdf; /* 170107 modified to work on Windows 9x/2000 */ - fdd_fn->formating = fdd_formating_xxx; - fdd_fn->isformating = fdd_isformating_xxx; - // - return(SUCCESS); -} - -#if 0 // 共通関数化したので廃止(fddfile.cへ)(kai9) -//BRESULT fddxdf_eject(FDDFILE fdd) { -BRESULT fdd_eject_xdf(FDDFILE fdd) { - -// fdd->fname[0] = '\0'; -// fdd->type = DISKTYPE_NOTREADY; - return(SUCCESS); -} - -//BRESULT fddxdf_diskaccess(FDDFILE fdd) { -BRESULT fdd_diskaccess_xdf(FDDFILE fdd) { - - if ((fdd->type != DISKTYPE_BETA) || - (CTRL_FDMEDIA != fdd->inf.xdf.disktype)) { - return(FAILURE); - } - return(SUCCESS); -} - -//BRESULT fddxdf_seek(FDDFILE fdd) { -BRESULT fdd_seek_xdf(FDDFILE fdd) { - - if ((fdd->type != DISKTYPE_BETA) || - (CTRL_FDMEDIA != fdd->inf.xdf.disktype) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (fdc.ncn >= (fdd->inf.xdf.tracks >> 1))) { - return(FAILURE); - } - return(SUCCESS); -} - -//BRESULT fddxdf_seeksector(FDDFILE fdd) { -BRESULT fdd_seeksector_xdf(FDDFILE fdd) { - - if ((fdd->type != DISKTYPE_BETA) || - (CTRL_FDMEDIA != fdd->inf.xdf.disktype) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (fdc.treg[fdc.us] >= (fdd->inf.xdf.tracks >> 1))) { - fddlasterror = 0xe0; - return(FAILURE); - } - if ((!fdc.R) || (fdc.R > fdd->inf.xdf.sectors)) { - fddlasterror = 0xc0; - return(FAILURE); - } - if ((fdc.mf != 0xff) && (fdc.mf != 0x40)) { - fddlasterror = 0xc0; - return(FAILURE); - } - return(SUCCESS); -} -#endif - -//BRESULT fddxdf_read(FDDFILE fdd) { -BRESULT fdd_read_xdf(FDDFILE fdd) { - - FILEH hdl; - long seekp; - UINT secsize; - - fddlasterror = 0x00; -// if (fddxdf_seeksector(fdd)) { - if (fdd_seeksector_common(fdd)) { - return(FAILURE); - } - if (fdc.N != fdd->inf.xdf.n) { - fddlasterror = 0xc0; - return(FAILURE); - } -// /* 170101 ST modified to work on Windows 9x/2000 form ... */ -// if (fdc.eot < fdd->inf.xdf.sectors) { -// fddlasterror = 0xc0; -// return(FAILURE); -// } -// /* 170101 ST modified to work on Windows 9x/2000 ... to */ - - seekp = (fdc.treg[fdc.us] << 1) + fdc.hd; - seekp *= fdd->inf.xdf.sectors; - seekp += fdc.R - 1; - seekp <<= (7 + fdd->inf.xdf.n); - seekp += fdd->inf.xdf.headersize; - secsize = 128 << fdd->inf.xdf.n; - - hdl = file_open_rb(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xe0; - return(FAILURE); - } - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_read(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xe0; - return(FAILURE); - } - file_close(hdl); - fdc.bufcnt = secsize; - fddlasterror = 0x00; - return(SUCCESS); -} - -//BRESULT fddxdf_write(FDDFILE fdd) { -BRESULT fdd_write_xdf(FDDFILE fdd) { - - FILEH hdl; - long seekp; - UINT secsize; - - fddlasterror = 0x00; -// if (fddxdf_seeksector(fdd)) { - if (fdd_seeksector_common(fdd)) { - fddlasterror = 0xe0; - return(FAILURE); - } - if (fdd->protect) { - fddlasterror = 0x70; - return(FAILURE); - } - if (fdc.N != fdd->inf.xdf.n) { - fddlasterror = 0xc0; - return(FAILURE); - } - /* 170101 ST modified to work on Windows 9x/2000 form ... */ - if (fdc.eot > fdd->inf.xdf.sectors) { - fddlasterror = 0xc0; - return(FAILURE); - } - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - - seekp = (fdc.treg[fdc.us] << 1) + fdc.hd; - seekp *= fdd->inf.xdf.sectors; - seekp += fdc.R - 1; - seekp <<= (7 + fdd->inf.xdf.n); - seekp += fdd->inf.xdf.headersize; - secsize = 128 << fdd->inf.xdf.n; - - hdl = file_open(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xc0; - return(FAILURE); - } - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_write(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xc0; - return(FAILURE); - } - file_close(hdl); - fdc.bufcnt = secsize; - fddlasterror = 0x00; - return(SUCCESS); -} - -/* 170107 modified to work on Windows 9x/2000 form ... */ -/* 実装補足 先頭からのオフセット値は単純にトラック数x1トラック当たりのセクタ数xセクタサイズ - で行っているため、トラックごとに異なるセクタ構造を持つフォーマットには対応できません - 元々ファイルのデータ構造的にサポートできません */ -BRESULT fdd_formatinit_xdf(FDDFILE fdd) { - FILEH hdl; - FDIHDR fdi; - UINT32 fddtype; - UINT32 cylinders; - long seekp; - UINT size; - - if (fdd->protect) { - fddlasterror = 0x70; - return(FAILURE); - } - - hdl = file_open(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xc0; - return(FAILURE); - } - - size = (128 << fdc.N) * fdc.sc; - seekp = (fdc.treg[fdc.us] << 1) + fdc.hd; - seekp *= size; - seekp += fdd->inf.xdf.headersize; - memset(fdc.buf, fdc.d, size); - - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_write(hdl, fdc.buf, size) != size)) { - file_close(hdl); - fddlasterror = 0xc0; - return(FAILURE); - } - - if (seekp == fdd->inf.xdf.headersize) { - - fdd->inf.xdf.disktype = DISKTYPE_2HD; - cylinders = 77; - switch(fdc.N) { - case 1: // BASIC (sector size = 256) - fddtype = 0x10; - break; - case 2: // 1.44M/1.21M/2DD - fddtype = 0x30; - if (fdc.sc < 10) { - fddtype = 0x70; - fdd->inf.xdf.disktype = DISKTYPE_2DD; - } - else if (fdc.sc < 18) { - fddtype = 0x90; - } - cylinders = 80; - break; - default: // 1.25M - fddtype = 0x90; - break; - } - - fdd->inf.xdf.tracks = (UINT8)(cylinders * 2); - fdd->inf.xdf.sectors = fdc.sc; - fdd->inf.xdf.n = fdc.N; - fdd->inf.xdf.rpm = fdc.rpm[fdc.us]; - - if(fdd->inf.xdf.headersize) { /* for FDI */ - if ((file_seek(hdl, 0, FSEEK_SET) == 0) && - (file_read(hdl, &fdi, sizeof(fdi)) == sizeof(fdi))) { - if (fdd->inf.xdf.headersize == LOADINTELDWORD(fdi.headersize)) { - STOREINTELDWORD(fdi.fddtype, fddtype); - STOREINTELDWORD(fdi.fddsize, size * cylinders * 2); - STOREINTELDWORD(fdi.sectorsize, 128 << fdc.N); - STOREINTELDWORD(fdi.sectors, fdc.sc); - STOREINTELDWORD(fdi.surfaces, 2); - STOREINTELDWORD(fdi.cylinders, cylinders); - file_seek(hdl, 0, FSEEK_SET); - file_write(hdl, &fdi, sizeof(fdi)); - } - } - } - // trim media image - seekp = fdd->inf.xdf.tracks * size + fdd->inf.xdf.headersize; - file_seek(hdl, seekp, FSEEK_SET); - file_write(hdl, fdc.buf, 0); - } - - file_close(hdl); - fddlasterror = 0x00; - return(SUCCESS); -} -/* 170107 modified to work on Windows 9x/2000 ... to */ - -#if 0 // 共通関数化したので廃止(fddfile.cへ)(kai9) -//BRESULT fddxdf_readid(FDDFILE fdd) { -BRESULT fdd_readid_xdf(FDDFILE fdd) { - - fddlasterror = 0x00; - if ((!fdc.mf) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (fdc.crcn >= fdd->inf.xdf.sectors)) { - fddlasterror = 0xe0; - return(FAILURE); - } - fdc.C = fdc.treg[fdc.us]; - fdc.H = fdc.hd; - fdc.R = ++fdc.crcn; - fdc.N = fdd->inf.xdf.n; - return(SUCCESS); -} -#endif - -#else - - -static const _XDFINFO supportxdf[] = { -#if 0 - // 256 - {0, 154, 26, 1, DISKTYPE_2HD, 0}, - // 512 - {0, 154, 15, 2, DISKTYPE_2HD, 0}, -#endif -#if 1 - // 512 - {0, 160, 15, 2, DISKTYPE_2HD, 0}, -#endif - // 1024 - {0, 154, 8, 3, DISKTYPE_2HD, 0}, - // 1.44MB - {0, 160, 18, 2, DISKTYPE_2HD, 1}, -}; - -typedef struct { - UINT8 dummy[4]; - UINT8 fddtype[4]; - UINT8 headersize[4]; - UINT8 fddsize[4]; - UINT8 sectorsize[4]; - UINT8 sectors[4]; - UINT8 surfaces[4]; - UINT8 cylinders[4]; -} FDIHDR; - - -BRESULT fddxdf_set(FDDFILE fdd, const OEMCHAR *fname, int ro) { - -const _XDFINFO *xdf; - short attr; - FILEH fh; - UINT32 fdsize; - UINT size; - - attr = file_attr(fname); - if (attr & 0x18) { - return(FAILURE); - } - if(!ro) { - if(attr & FILEATTR_READONLY) { - ro = 1; - } - } - if(ro) { - fh = file_open_rb(fname); - } else { - fh = file_open(fname); - } - if (fh == FILEH_INVALID) { - return(FAILURE); - } - fdsize = file_getsize(fh); - file_close(fh); - - xdf = supportxdf; - while(xdf < (supportxdf + NELEMENTS(supportxdf))) { - size = xdf->tracks; - size *= xdf->sectors; - size <<= (7 + xdf->n); - if (size == fdsize) { - fdd->type = DISKTYPE_BETA; - fdd->protect = ((attr & 1) || (ro))?TRUE:FALSE; - fdd->inf.xdf = *xdf; - return(SUCCESS); - } - xdf++; - } - return(FAILURE); -} - -// こっそり対応したりして -BRESULT fddxdf_setfdi(FDDFILE fdd, const OEMCHAR *fname, int ro) { - - short attr; - FILEH fh; - UINT32 fdsize; - UINT r; - FDIHDR fdi; - UINT32 fddtype; - UINT32 headersize; - UINT32 size; - UINT32 sectors; - UINT32 surfaces; - UINT32 cylinders; - UINT8 n; - UINT8 disktype; - UINT8 rpm; - - attr = file_attr(fname); - if (attr & 0x18) { - return(FAILURE); - } - fdsize = 0; - r = 0; - if(!ro) { - if(attr & FILEATTR_READONLY) { - ro = 1; - } - } - if(ro) { - fh = file_open_rb(fname); - } else { - fh = file_open(fname); - } - if (fh != FILEH_INVALID) { - fdsize = file_getsize(fh); - r = file_read(fh, &fdi, sizeof(fdi)); - file_close(fh); - } - if (r != sizeof(fdi)) { - return(FAILURE); - } - fddtype = LOADINTELDWORD(fdi.fddtype); - headersize = LOADINTELDWORD(fdi.headersize); - size = LOADINTELDWORD(fdi.sectorsize); - sectors = LOADINTELDWORD(fdi.sectors); - surfaces = LOADINTELDWORD(fdi.surfaces); - cylinders = LOADINTELDWORD(fdi.cylinders); - if (((size & (size - 1)) != 0) || (!(size & 0x7f80)) || - (sectors == 0) || (sectors >= 256) || - (surfaces != 2) || - (cylinders == 0) || (cylinders >= 128)) { - return(FAILURE); - } - if (fdsize != (headersize + (size * sectors * surfaces * cylinders))) { - return(FAILURE); - } - size >>= 8; - n = 0; - while(size) { - size >>= 1; - n++; - } - disktype = DISKTYPE_2HD; - rpm = 0; - switch(fddtype & 0xf0) { - case 0x10: // 1MB/640KB - 2DD - case 0x70: // 640KB - 2DD - case 0xf0: - disktype = DISKTYPE_2DD; - break; - - case 0x30: // 1.44MB - 2HD - case 0xb0: - rpm = 1; - break; - - case 0x50: // 320KB - 2D - case 0xd0: // - disktype = DISKTYPE_2D; - break; - - case 0x90: // 2HD - break; - - default: - return(FAILURE); - } - fdd->type = DISKTYPE_BETA; - fdd->protect = ((attr & 1) || (ro))?TRUE:FALSE; - fdd->inf.xdf.headersize = headersize; - fdd->inf.xdf.tracks = (UINT8)(cylinders * 2); - fdd->inf.xdf.sectors = (UINT8)sectors; - fdd->inf.xdf.n = n; - fdd->inf.xdf.disktype = disktype; - fdd->inf.xdf.rpm = rpm; - return(SUCCESS); -} - -BRESULT fddxdf_eject(FDDFILE fdd) { - - fdd->fname[0] = '\0'; - fdd->type = DISKTYPE_NOTREADY; - return(SUCCESS); -} - - -BRESULT fddxdf_diskaccess(FDDFILE fdd) { - - if ((fdd->type != DISKTYPE_BETA) || - (CTRL_FDMEDIA != fdd->inf.xdf.disktype)) { - return(FAILURE); - } - return(SUCCESS); -} - -BRESULT fddxdf_seek(FDDFILE fdd) { - - if ((fdd->type != DISKTYPE_BETA) || - (CTRL_FDMEDIA != fdd->inf.xdf.disktype) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (fdc.ncn >= (fdd->inf.xdf.tracks >> 1))) { - return(FAILURE); - } - return(SUCCESS); -} - -BRESULT fddxdf_seeksector(FDDFILE fdd) { - - if ((fdd->type != DISKTYPE_BETA) || - (CTRL_FDMEDIA != fdd->inf.xdf.disktype) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (fdc.treg[fdc.us] >= (fdd->inf.xdf.tracks >> 1))) { - fddlasterror = 0xe0; - return(FAILURE); - } - if ((!fdc.R) || (fdc.R > fdd->inf.xdf.sectors)) { - fddlasterror = 0xc0; - return(FAILURE); - } - if ((fdc.mf != 0xff) && (fdc.mf != 0x40)) { - fddlasterror = 0xc0; - return(FAILURE); - } - return(SUCCESS); -} - -BRESULT fddxdf_read(FDDFILE fdd) { - - FILEH hdl; - long seekp; - UINT secsize; - - fddlasterror = 0x00; - if (fddxdf_seeksector(fdd)) { - return(FAILURE); - } - if (fdc.N != fdd->inf.xdf.n) { - fddlasterror = 0xc0; - return(FAILURE); - } - - seekp = (fdc.treg[fdc.us] << 1) + fdc.hd; - seekp *= fdd->inf.xdf.sectors; - seekp += fdc.R - 1; - seekp <<= (7 + fdd->inf.xdf.n); - seekp += fdd->inf.xdf.headersize; - secsize = 128 << fdd->inf.xdf.n; - - hdl = file_open_rb(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xe0; - return(FAILURE); - } - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_read(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xe0; - return(FAILURE); - } - file_close(hdl); - fdc.bufcnt = secsize; - fddlasterror = 0x00; - return(SUCCESS); -} - -BRESULT fddxdf_write(FDDFILE fdd) { - - FILEH hdl; - long seekp; - UINT secsize; - - fddlasterror = 0x00; - if (fddxdf_seeksector(fdd)) { - fddlasterror = 0xe0; - return(FAILURE); - } - if (fdd->protect) { - fddlasterror = 0x70; - return(FAILURE); - } - if (fdc.N != fdd->inf.xdf.n) { - fddlasterror = 0xc0; - return(FAILURE); - } - - seekp = (fdc.treg[fdc.us] << 1) + fdc.hd; - seekp *= fdd->inf.xdf.sectors; - seekp += fdc.R - 1; - seekp <<= (7 + fdd->inf.xdf.n); - seekp += fdd->inf.xdf.headersize; - secsize = 128 << fdd->inf.xdf.n; - - hdl = file_open(fdd->fname); - if (hdl == FILEH_INVALID) { - fddlasterror = 0xc0; - return(FAILURE); - } - if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || - (file_write(hdl, fdc.buf, secsize) != secsize)) { - file_close(hdl); - fddlasterror = 0xc0; - return(FAILURE); - } - file_close(hdl); - fdc.bufcnt = secsize; - fddlasterror = 0x00; - return(SUCCESS); -} - -BRESULT fddxdf_readid(FDDFILE fdd) { - - fddlasterror = 0x00; - if ((!fdc.mf) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (fdc.crcn >= fdd->inf.xdf.sectors)) { - fddlasterror = 0xe0; - return(FAILURE); - } - fdc.C = fdc.treg[fdc.us]; - fdc.H = fdc.hd; - fdc.R = ++fdc.crcn; - fdc.N = fdd->inf.xdf.n; - return(SUCCESS); -} - -#endif +#include +#include +#include +#include + +#include +#include "diskimage/fd/fdd_xdf.h" + +#ifdef SUPPORT_KAI_IMAGES + +// BKDSK(DD6)、BKDSK(DDB)判定用 +//static const OEMCHAR str_dd6[] = OEMTEXT("dd6"); // 未使用なのでコメント(kai9) +static const OEMCHAR str_ddb[] = OEMTEXT("ddb"); +// + +static const _XDFINFO supportxdf[] = { +#if 0 + // 256 + {0, 154, 26, 1, DISKTYPE_2HD, 0}, + // 512 + {0, 154, 15, 2, DISKTYPE_2HD, 0}, +#endif +#if 1 + // 512 + {0, 160, 15, 2, DISKTYPE_2HD, 0}, // BKDSK(HD5) MS-DOS 1.21M(2HC) +#endif + // 1024 + {0, 154, 8, 3, DISKTYPE_2HD, 0}, // XDF他2HD、BIN、FLP等 + // BKDSK(HDM) MS-DOS 1.25M(2HD) + // 1.44MB + {0, 160, 18, 2, DISKTYPE_2HD, 1}, // BKDSK(HD4) MS-DOS 1.44M(2HD) + {0, 160, 21, 2, DISKTYPE_2HD, 1}, // BKDSK MS 2HD-DMF + + // 追加でいくつかのBKDSK形式に対応 + {0, 154, 26, 1, DISKTYPE_2HD, 0}, // BKDSK(H01) 2HD:256byte*26sec (0-154)track + {0, 154, 9, 3, DISKTYPE_2HD, 0}, // BKDSK(HD9) MS-DOS 2HD(9sec) + {0, 160, 8, 2, DISKTYPE_2DD, 0}, // BKDSK(DD6) MS-DOS 640K(2DD) + {0, 160, 9, 2, DISKTYPE_2DD, 0}, // BKDSK(DD9) MS-DOS 720K(2DD) + // track 0とそれ以外でセクタサイズが違うため未対応 +// {0, 154, 26, 1, DISKTYPE_2HD, 0}, // BKDSK(HDB) BASIC 2HD + // + {0, 160, 16, 1, DISKTYPE_2DD, 0}, // BKDSK(DDB) BASIC 2DD + // + // ヘッダサイズを指定し、判定時に考慮するようにすれば + // DIPやDCP/DCU(全トラック格納イメージ)とかもいける + {256, 154, 8, 3, DISKTYPE_2HD, 0}, // DIP 2HD-8セクタ(1.25MB) + // FIM 2HD-8セクタ(1.25MB) + {256, 154, 26, 1, DISKTYPE_2HD, 0}, // FIM 2HD-26セクタ +#if 0 // fdd_dcp.cへ移動(kai9) + {162, 154, 8, 3, DISKTYPE_2HD, 0}, // DCP/DCU 01h 2HD- 8セクタ(1.25MB) + {162, 160, 15, 2, DISKTYPE_2HD, 0}, // DCP/DCU 02h 2HD-15セクタ(1.21MB) + {162, 160, 18, 2, DISKTYPE_2HD, 1}, // DCP/DCU 03h 2HQ-18セクタ(1.44MB) + {162, 160, 8, 2, DISKTYPE_2DD, 0}, // DCP/DCU 04h 2DD- 8セクタ( 640KB) + {162, 160, 9, 2, DISKTYPE_2DD, 0}, // DCP/DCU 05h 2DD- 9セクタ( 720KB) + {162, 154, 9, 3, DISKTYPE_2HD, 0}, // DCP/DCU 08h 2HD- 9セクタ(1.44MB) +// {162, 154, 26, 1, DISKTYPE_2HD, 0}, // DCP/DCU 11h BASIC-2HD + {162, 160, 16, 1, DISKTYPE_2DD, 0}, // DCP/DCU 19h BASIC-2DD + {162, 154, 26, 1, DISKTYPE_2HD, 0}, // DCP/DCU 21h 2HD-26セクタ +#endif + // +}; + +// FDIヘッダ +typedef struct { + UINT8 dummy[4]; + UINT8 fddtype[4]; + UINT8 headersize[4]; + UINT8 fddsize[4]; + UINT8 sectorsize[4]; + UINT8 sectors[4]; + UINT8 surfaces[4]; + UINT8 cylinders[4]; +} FDIHDR; + +//BRESULT fddxdf_set(FDDFILE fdd, const OEMCHAR *fname, int ro) { +BRESULT fdd_set_xdf(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { + +const _XDFINFO *xdf; + short attr; + FILEH fh; + UINT32 fdsize; + UINT size; +const OEMCHAR *p; // BKDSK(DD6) or BKDSK(DDB)判定用 + + attr = file_attr(fname); + if (attr & 0x18) { + return(FAILURE); + } + if(!ro) { + if(attr & FILEATTR_READONLY) { + ro = 1; + } + } + if(ro) { + fh = file_open_rb(fname); + } else { + fh = file_open(fname); + } + if (fh == FILEH_INVALID) { + return(FAILURE); + } + fdsize = (UINT32)file_getsize(fh); + file_close(fh); + + p = file_getext(fname); // BKDSK(DD6) or BKDSK(DDB)判定用 + + xdf = supportxdf; + while(xdf < (supportxdf + NELEMENTS(supportxdf))) { + size = xdf->tracks; + size *= xdf->sectors; + size <<= (7 + xdf->n); + // ヘッダサイズを考慮するように + size += xdf->headersize; + // + if (size == fdsize) { + // BKDSK(DD6)とBKDSK(DDB)が同一サイズのため、拡張子で判定 + if (!milstr_cmp(p, str_ddb) && xdf->sectors == 8) { + xdf++; + continue; + } + // + fdd->type = DISKTYPE_BETA; + fdd->protect = ((attr & 1) || (ro))?TRUE:FALSE; + fdd->inf.xdf = *xdf; + // 処理関数群を登録(kai9) + fdd_fn->eject = fdd_eject_xxx; +// fdd_fn->diskaccess = fdd_diskaccess_xdf; +// fdd_fn->seek = fdd_seek_xdf; +// fdd_fn->seeksector = fdd_seeksector_xdf; + fdd_fn->diskaccess = fdd_diskaccess_common; + fdd_fn->seek = fdd_seek_common; + fdd_fn->seeksector = fdd_seeksector_common; + fdd_fn->read = fdd_read_xdf; + fdd_fn->write = fdd_write_xdf; +// fdd_fn->readid = fdd_readid_xdf; + fdd_fn->readid = fdd_readid_common; + fdd_fn->writeid = fdd_dummy_xxx; + fdd_fn->formatinit = fdd_formatinit_xdf; /* 170107 to support format command */ + fdd_fn->formating = fdd_formating_xxx; + fdd_fn->isformating = fdd_isformating_xxx; + // + return(SUCCESS); + } + xdf++; + } + return(FAILURE); +} + +// こっそり対応したりして +//BRESULT fddxdf_setfdi(FDDFILE fdd, const OEMCHAR *fname, int ro) { +BRESULT fdd_set_fdi(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro) { + + short attr; + FILEH fh; + UINT32 fdsize; + UINT r; + FDIHDR fdi; + UINT32 fddtype; + UINT32 headersize; + UINT32 size; + UINT32 sectors; + UINT32 surfaces; + UINT32 cylinders; + UINT8 n; + UINT8 disktype; + UINT8 rpm; + + attr = file_attr(fname); + if (attr & 0x18) { + return(FAILURE); + } + fdsize = 0; + r = 0; + if(!ro) { + if(attr & FILEATTR_READONLY) { + ro = 1; + } + } + if(ro) { + fh = file_open_rb(fname); + } else { + fh = file_open(fname); + } + if (fh != FILEH_INVALID) { + fdsize = (UINT32)file_getsize(fh); + r = file_read(fh, &fdi, sizeof(fdi)); + file_close(fh); + } + if (r != sizeof(fdi)) { + return(FAILURE); + } + fddtype = LOADINTELDWORD(fdi.fddtype); + headersize = LOADINTELDWORD(fdi.headersize); + size = LOADINTELDWORD(fdi.sectorsize); + sectors = LOADINTELDWORD(fdi.sectors); + surfaces = LOADINTELDWORD(fdi.surfaces); + cylinders = LOADINTELDWORD(fdi.cylinders); + if (((size & (size - 1)) != 0) || (!(size & 0x7f80)) || + (sectors == 0) || (sectors >= 256) || + (surfaces != 2) || + (cylinders == 0) || (cylinders >= 128)) { + return(FAILURE); + } + if (fdsize != (headersize + (size * sectors * surfaces * cylinders))) { + return(FAILURE); + } + size >>= 8; + n = 0; + while(size) { + size >>= 1; + n++; + } + disktype = DISKTYPE_2HD; + rpm = 0; + switch(fddtype & 0xf0) { + case 0x10: // 1MB/640KB - 2DD + case 0x70: // 640KB - 2DD + case 0xf0: + disktype = DISKTYPE_2DD; + break; + + case 0x30: // 1.44MB - 2HD + case 0xb0: + rpm = 1; + break; + + case 0x50: // 320KB - 2D + case 0xd0: // + disktype = DISKTYPE_2D; + break; + + case 0x90: // 2HD + break; + + default: + return(FAILURE); + } + fdd->type = DISKTYPE_BETA; + fdd->protect = ((attr & 1) || (ro))?TRUE:FALSE; + fdd->inf.xdf.headersize = headersize; + fdd->inf.xdf.tracks = (UINT8)(cylinders * 2); + fdd->inf.xdf.sectors = (UINT8)sectors; + fdd->inf.xdf.n = n; + fdd->inf.xdf.disktype = disktype; + fdd->inf.xdf.rpm = rpm; + // 処理関数群を登録(kai9) + fdd_fn->eject = fdd_eject_xxx; + fdd_fn->diskaccess = fdd_diskaccess_common; + fdd_fn->seek = fdd_seek_common; + fdd_fn->seeksector = fdd_seeksector_common; + fdd_fn->read = fdd_read_xdf; + fdd_fn->write = fdd_write_xdf; + fdd_fn->readid = fdd_readid_common; + fdd_fn->writeid = fdd_dummy_xxx; + fdd_fn->formatinit = fdd_formatinit_xdf; /* 170107 modified to work on Windows 9x/2000 */ + fdd_fn->formating = fdd_formating_xxx; + fdd_fn->isformating = fdd_isformating_xxx; + // + return(SUCCESS); +} + +#if 0 // 共通関数化したので廃止(fddfile.cへ)(kai9) +//BRESULT fddxdf_eject(FDDFILE fdd) { +BRESULT fdd_eject_xdf(FDDFILE fdd) { + +// fdd->fname[0] = '\0'; +// fdd->type = DISKTYPE_NOTREADY; + return(SUCCESS); +} + +//BRESULT fddxdf_diskaccess(FDDFILE fdd) { +BRESULT fdd_diskaccess_xdf(FDDFILE fdd) { + + if ((fdd->type != DISKTYPE_BETA) || + (CTRL_FDMEDIA != fdd->inf.xdf.disktype)) { + return(FAILURE); + } + return(SUCCESS); +} + +//BRESULT fddxdf_seek(FDDFILE fdd) { +BRESULT fdd_seek_xdf(FDDFILE fdd) { + + if ((fdd->type != DISKTYPE_BETA) || + (CTRL_FDMEDIA != fdd->inf.xdf.disktype) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (fdc.ncn >= (fdd->inf.xdf.tracks >> 1))) { + return(FAILURE); + } + return(SUCCESS); +} + +//BRESULT fddxdf_seeksector(FDDFILE fdd) { +BRESULT fdd_seeksector_xdf(FDDFILE fdd) { + + if ((fdd->type != DISKTYPE_BETA) || + (CTRL_FDMEDIA != fdd->inf.xdf.disktype) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (fdc.treg[fdc.us] >= (fdd->inf.xdf.tracks >> 1))) { + fddlasterror = 0xe0; + return(FAILURE); + } + if ((!fdc.R) || (fdc.R > fdd->inf.xdf.sectors)) { + fddlasterror = 0xc0; + return(FAILURE); + } + if ((fdc.mf != 0xff) && (fdc.mf != 0x40)) { + fddlasterror = 0xc0; + return(FAILURE); + } + return(SUCCESS); +} +#endif + +//BRESULT fddxdf_read(FDDFILE fdd) { +BRESULT fdd_read_xdf(FDDFILE fdd) { + + FILEH hdl; + long seekp; + UINT secsize; + + fddlasterror = 0x00; +// if (fddxdf_seeksector(fdd)) { + if (fdd_seeksector_common(fdd)) { + return(FAILURE); + } + if (fdc.N != fdd->inf.xdf.n) { + fddlasterror = 0xc0; + return(FAILURE); + } +// /* 170101 ST modified to work on Windows 9x/2000 form ... */ +// if (fdc.eot < fdd->inf.xdf.sectors) { +// fddlasterror = 0xc0; +// return(FAILURE); +// } +// /* 170101 ST modified to work on Windows 9x/2000 ... to */ + + seekp = (fdc.treg[fdc.us] << 1) + fdc.hd; + seekp *= fdd->inf.xdf.sectors; + seekp += fdc.R - 1; + seekp <<= (7 + fdd->inf.xdf.n); + seekp += fdd->inf.xdf.headersize; + secsize = 128 << fdd->inf.xdf.n; + + hdl = file_open_rb(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xe0; + return(FAILURE); + } + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_read(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xe0; + return(FAILURE); + } + file_close(hdl); + fdc.bufcnt = secsize; + fddlasterror = 0x00; + return(SUCCESS); +} + +//BRESULT fddxdf_write(FDDFILE fdd) { +BRESULT fdd_write_xdf(FDDFILE fdd) { + + FILEH hdl; + long seekp; + UINT secsize; + + fddlasterror = 0x00; +// if (fddxdf_seeksector(fdd)) { + if (fdd_seeksector_common(fdd)) { + fddlasterror = 0xe0; + return(FAILURE); + } + if (fdd->protect) { + fddlasterror = 0x70; + return(FAILURE); + } + if (fdc.N != fdd->inf.xdf.n) { + fddlasterror = 0xc0; + return(FAILURE); + } + /* 170101 ST modified to work on Windows 9x/2000 form ... */ + if (fdc.eot > fdd->inf.xdf.sectors) { + fddlasterror = 0xc0; + return(FAILURE); + } + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + + seekp = (fdc.treg[fdc.us] << 1) + fdc.hd; + seekp *= fdd->inf.xdf.sectors; + seekp += fdc.R - 1; + seekp <<= (7 + fdd->inf.xdf.n); + seekp += fdd->inf.xdf.headersize; + secsize = 128 << fdd->inf.xdf.n; + + hdl = file_open(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xc0; + return(FAILURE); + } + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_write(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xc0; + return(FAILURE); + } + file_close(hdl); + fdc.bufcnt = secsize; + fddlasterror = 0x00; + return(SUCCESS); +} + +/* 170107 modified to work on Windows 9x/2000 form ... */ +/* 実装補足 先頭からのオフセット値は単純にトラック数x1トラック当たりのセクタ数xセクタサイズ + で行っているため、トラックごとに異なるセクタ構造を持つフォーマットには対応できません + 元々ファイルのデータ構造的にサポートできません */ +BRESULT fdd_formatinit_xdf(FDDFILE fdd) { + FILEH hdl; + FDIHDR fdi; + UINT32 fddtype; + UINT32 cylinders; + long seekp; + UINT size; + + if (fdd->protect) { + fddlasterror = 0x70; + return(FAILURE); + } + + hdl = file_open(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xc0; + return(FAILURE); + } + + size = (128 << fdc.N) * fdc.sc; + seekp = (fdc.treg[fdc.us] << 1) + fdc.hd; + seekp *= size; + seekp += fdd->inf.xdf.headersize; + memset(fdc.buf, fdc.d, size); + + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_write(hdl, fdc.buf, size) != size)) { + file_close(hdl); + fddlasterror = 0xc0; + return(FAILURE); + } + + if (seekp == fdd->inf.xdf.headersize) { + + fdd->inf.xdf.disktype = DISKTYPE_2HD; + cylinders = 77; + switch(fdc.N) { + case 1: // BASIC (sector size = 256) + fddtype = 0x10; + break; + case 2: // 1.44M/1.21M/2DD + fddtype = 0x30; + if (fdc.sc < 10) { + fddtype = 0x70; + fdd->inf.xdf.disktype = DISKTYPE_2DD; + } + else if (fdc.sc < 18) { + fddtype = 0x90; + } + cylinders = 80; + break; + default: // 1.25M + fddtype = 0x90; + break; + } + + fdd->inf.xdf.tracks = (UINT8)(cylinders * 2); + fdd->inf.xdf.sectors = fdc.sc; + fdd->inf.xdf.n = fdc.N; + fdd->inf.xdf.rpm = fdc.rpm[fdc.us]; + + if(fdd->inf.xdf.headersize) { /* for FDI */ + if ((file_seek(hdl, 0, FSEEK_SET) == 0) && + (file_read(hdl, &fdi, sizeof(fdi)) == sizeof(fdi))) { + if (fdd->inf.xdf.headersize == LOADINTELDWORD(fdi.headersize)) { + STOREINTELDWORD(fdi.fddtype, fddtype); + STOREINTELDWORD(fdi.fddsize, size * cylinders * 2); + STOREINTELDWORD(fdi.sectorsize, 128 << fdc.N); + STOREINTELDWORD(fdi.sectors, fdc.sc); + STOREINTELDWORD(fdi.surfaces, 2); + STOREINTELDWORD(fdi.cylinders, cylinders); + file_seek(hdl, 0, FSEEK_SET); + file_write(hdl, &fdi, sizeof(fdi)); + } + } + } + // trim media image + seekp = fdd->inf.xdf.tracks * size + fdd->inf.xdf.headersize; + file_seek(hdl, seekp, FSEEK_SET); + file_write(hdl, fdc.buf, 0); + } + + file_close(hdl); + fddlasterror = 0x00; + return(SUCCESS); +} +/* 170107 modified to work on Windows 9x/2000 ... to */ + +#if 0 // 共通関数化したので廃止(fddfile.cへ)(kai9) +//BRESULT fddxdf_readid(FDDFILE fdd) { +BRESULT fdd_readid_xdf(FDDFILE fdd) { + + fddlasterror = 0x00; + if ((!fdc.mf) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (fdc.crcn >= fdd->inf.xdf.sectors)) { + fddlasterror = 0xe0; + return(FAILURE); + } + fdc.C = fdc.treg[fdc.us]; + fdc.H = fdc.hd; + fdc.R = ++fdc.crcn; + fdc.N = fdd->inf.xdf.n; + return(SUCCESS); +} +#endif + +#else + + +static const _XDFINFO supportxdf[] = { +#if 0 + // 256 + {0, 154, 26, 1, DISKTYPE_2HD, 0}, + // 512 + {0, 154, 15, 2, DISKTYPE_2HD, 0}, +#endif +#if 1 + // 512 + {0, 160, 15, 2, DISKTYPE_2HD, 0}, +#endif + // 1024 + {0, 154, 8, 3, DISKTYPE_2HD, 0}, + // 1.44MB + {0, 160, 18, 2, DISKTYPE_2HD, 1}, +}; + +typedef struct { + UINT8 dummy[4]; + UINT8 fddtype[4]; + UINT8 headersize[4]; + UINT8 fddsize[4]; + UINT8 sectorsize[4]; + UINT8 sectors[4]; + UINT8 surfaces[4]; + UINT8 cylinders[4]; +} FDIHDR; + + +BRESULT fddxdf_set(FDDFILE fdd, const OEMCHAR *fname, int ro) { + +const _XDFINFO *xdf; + short attr; + FILEH fh; + UINT32 fdsize; + UINT size; + + attr = file_attr(fname); + if (attr & 0x18) { + return(FAILURE); + } + if(!ro) { + if(attr & FILEATTR_READONLY) { + ro = 1; + } + } + if(ro) { + fh = file_open_rb(fname); + } else { + fh = file_open(fname); + } + if (fh == FILEH_INVALID) { + return(FAILURE); + } + fdsize = file_getsize(fh); + file_close(fh); + + xdf = supportxdf; + while(xdf < (supportxdf + NELEMENTS(supportxdf))) { + size = xdf->tracks; + size *= xdf->sectors; + size <<= (7 + xdf->n); + if (size == fdsize) { + fdd->type = DISKTYPE_BETA; + fdd->protect = ((attr & 1) || (ro))?TRUE:FALSE; + fdd->inf.xdf = *xdf; + return(SUCCESS); + } + xdf++; + } + return(FAILURE); +} + +// こっそり対応したりして +BRESULT fddxdf_setfdi(FDDFILE fdd, const OEMCHAR *fname, int ro) { + + short attr; + FILEH fh; + UINT32 fdsize; + UINT r; + FDIHDR fdi; + UINT32 fddtype; + UINT32 headersize; + UINT32 size; + UINT32 sectors; + UINT32 surfaces; + UINT32 cylinders; + UINT8 n; + UINT8 disktype; + UINT8 rpm; + + attr = file_attr(fname); + if (attr & 0x18) { + return(FAILURE); + } + fdsize = 0; + r = 0; + if(!ro) { + if(attr & FILEATTR_READONLY) { + ro = 1; + } + } + if(ro) { + fh = file_open_rb(fname); + } else { + fh = file_open(fname); + } + if (fh != FILEH_INVALID) { + fdsize = file_getsize(fh); + r = file_read(fh, &fdi, sizeof(fdi)); + file_close(fh); + } + if (r != sizeof(fdi)) { + return(FAILURE); + } + fddtype = LOADINTELDWORD(fdi.fddtype); + headersize = LOADINTELDWORD(fdi.headersize); + size = LOADINTELDWORD(fdi.sectorsize); + sectors = LOADINTELDWORD(fdi.sectors); + surfaces = LOADINTELDWORD(fdi.surfaces); + cylinders = LOADINTELDWORD(fdi.cylinders); + if (((size & (size - 1)) != 0) || (!(size & 0x7f80)) || + (sectors == 0) || (sectors >= 256) || + (surfaces != 2) || + (cylinders == 0) || (cylinders >= 128)) { + return(FAILURE); + } + if (fdsize != (headersize + (size * sectors * surfaces * cylinders))) { + return(FAILURE); + } + size >>= 8; + n = 0; + while(size) { + size >>= 1; + n++; + } + disktype = DISKTYPE_2HD; + rpm = 0; + switch(fddtype & 0xf0) { + case 0x10: // 1MB/640KB - 2DD + case 0x70: // 640KB - 2DD + case 0xf0: + disktype = DISKTYPE_2DD; + break; + + case 0x30: // 1.44MB - 2HD + case 0xb0: + rpm = 1; + break; + + case 0x50: // 320KB - 2D + case 0xd0: // + disktype = DISKTYPE_2D; + break; + + case 0x90: // 2HD + break; + + default: + return(FAILURE); + } + fdd->type = DISKTYPE_BETA; + fdd->protect = ((attr & 1) || (ro))?TRUE:FALSE; + fdd->inf.xdf.headersize = headersize; + fdd->inf.xdf.tracks = (UINT8)(cylinders * 2); + fdd->inf.xdf.sectors = (UINT8)sectors; + fdd->inf.xdf.n = n; + fdd->inf.xdf.disktype = disktype; + fdd->inf.xdf.rpm = rpm; + return(SUCCESS); +} + +BRESULT fddxdf_eject(FDDFILE fdd) { + + fdd->fname[0] = '\0'; + fdd->type = DISKTYPE_NOTREADY; + return(SUCCESS); +} + + +BRESULT fddxdf_diskaccess(FDDFILE fdd) { + + if ((fdd->type != DISKTYPE_BETA) || + (CTRL_FDMEDIA != fdd->inf.xdf.disktype)) { + return(FAILURE); + } + return(SUCCESS); +} + +BRESULT fddxdf_seek(FDDFILE fdd) { + + if ((fdd->type != DISKTYPE_BETA) || + (CTRL_FDMEDIA != fdd->inf.xdf.disktype) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (fdc.ncn >= (fdd->inf.xdf.tracks >> 1))) { + return(FAILURE); + } + return(SUCCESS); +} + +BRESULT fddxdf_seeksector(FDDFILE fdd) { + + if ((fdd->type != DISKTYPE_BETA) || + (CTRL_FDMEDIA != fdd->inf.xdf.disktype) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (fdc.treg[fdc.us] >= (fdd->inf.xdf.tracks >> 1))) { + fddlasterror = 0xe0; + return(FAILURE); + } + if ((!fdc.R) || (fdc.R > fdd->inf.xdf.sectors)) { + fddlasterror = 0xc0; + return(FAILURE); + } + if ((fdc.mf != 0xff) && (fdc.mf != 0x40)) { + fddlasterror = 0xc0; + return(FAILURE); + } + return(SUCCESS); +} + +BRESULT fddxdf_read(FDDFILE fdd) { + + FILEH hdl; + long seekp; + UINT secsize; + + fddlasterror = 0x00; + if (fddxdf_seeksector(fdd)) { + return(FAILURE); + } + if (fdc.N != fdd->inf.xdf.n) { + fddlasterror = 0xc0; + return(FAILURE); + } + + seekp = (fdc.treg[fdc.us] << 1) + fdc.hd; + seekp *= fdd->inf.xdf.sectors; + seekp += fdc.R - 1; + seekp <<= (7 + fdd->inf.xdf.n); + seekp += fdd->inf.xdf.headersize; + secsize = 128 << fdd->inf.xdf.n; + + hdl = file_open_rb(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xe0; + return(FAILURE); + } + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_read(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xe0; + return(FAILURE); + } + file_close(hdl); + fdc.bufcnt = secsize; + fddlasterror = 0x00; + return(SUCCESS); +} + +BRESULT fddxdf_write(FDDFILE fdd) { + + FILEH hdl; + long seekp; + UINT secsize; + + fddlasterror = 0x00; + if (fddxdf_seeksector(fdd)) { + fddlasterror = 0xe0; + return(FAILURE); + } + if (fdd->protect) { + fddlasterror = 0x70; + return(FAILURE); + } + if (fdc.N != fdd->inf.xdf.n) { + fddlasterror = 0xc0; + return(FAILURE); + } + + seekp = (fdc.treg[fdc.us] << 1) + fdc.hd; + seekp *= fdd->inf.xdf.sectors; + seekp += fdc.R - 1; + seekp <<= (7 + fdd->inf.xdf.n); + seekp += fdd->inf.xdf.headersize; + secsize = 128 << fdd->inf.xdf.n; + + hdl = file_open(fdd->fname); + if (hdl == FILEH_INVALID) { + fddlasterror = 0xc0; + return(FAILURE); + } + if ((file_seek(hdl, seekp, FSEEK_SET) != seekp) || + (file_write(hdl, fdc.buf, secsize) != secsize)) { + file_close(hdl); + fddlasterror = 0xc0; + return(FAILURE); + } + file_close(hdl); + fdc.bufcnt = secsize; + fddlasterror = 0x00; + return(SUCCESS); +} + +BRESULT fddxdf_readid(FDDFILE fdd) { + + fddlasterror = 0x00; + if ((!fdc.mf) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (fdc.crcn >= fdd->inf.xdf.sectors)) { + fddlasterror = 0xe0; + return(FAILURE); + } + fdc.C = fdc.treg[fdc.us]; + fdc.H = fdc.hd; + fdc.R = ++fdc.crcn; + fdc.N = fdd->inf.xdf.n; + return(SUCCESS); +} + +#endif diff --git a/diskimage/fd/fdd_xdf.h b/diskimage/fd/fdd_xdf.h old mode 100755 new mode 100644 index 4b51fcc8..a6a96e84 --- a/diskimage/fd/fdd_xdf.h +++ b/diskimage/fd/fdd_xdf.h @@ -1,57 +1,57 @@ - -#ifdef SUPPORT_KAI_IMAGES - -#ifdef __cplusplus -extern "C" { -#endif - -#if 1 // 関数名変更&引数追加(k9) -BRESULT fdd_set_xdf(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); -BRESULT fdd_set_fdi(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); - -//BRESULT fdd_diskaccess_xdf(FDDFILE fdd); -//BRESULT fdd_seek_xdf(FDDFILE fdd); -//BRESULT fdd_seeksector_xdf(FDDFILE fdd); -BRESULT fdd_read_xdf(FDDFILE fdd); -BRESULT fdd_write_xdf(FDDFILE fdd); -//BRESULT fdd_readid_xdf(FDDFILE fdd); -BRESULT fdd_formatinit_xdf(FDDFILE fdd); /* 170107 to support format command */ -#else -BRESULT fddxdf_set(FDDFILE fdd, const OEMCHAR *fname, int ro); -BRESULT fddxdf_setfdi(FDDFILE fdd, const OEMCHAR *fname, int ro); -BRESULT fddxdf_eject(FDDFILE fdd); - -BRESULT fddxdf_diskaccess(FDDFILE fdd); -BRESULT fddxdf_seek(FDDFILE fdd); -BRESULT fddxdf_seeksector(FDDFILE fdd); -BRESULT fddxdf_read(FDDFILE fdd); -BRESULT fddxdf_write(FDDFILE fdd); -BRESULT fddxdf_readid(FDDFILE fdd); - -#ifdef __cplusplus -} -#endif -#endif - -#else -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT fddxdf_set(FDDFILE fdd, const OEMCHAR *fname, int ro); -BRESULT fddxdf_setfdi(FDDFILE fdd, const OEMCHAR *fname, int ro); -BRESULT fddxdf_eject(FDDFILE fdd); - -BRESULT fddxdf_diskaccess(FDDFILE fdd); -BRESULT fddxdf_seek(FDDFILE fdd); -BRESULT fddxdf_seeksector(FDDFILE fdd); -BRESULT fddxdf_read(FDDFILE fdd); -BRESULT fddxdf_write(FDDFILE fdd); -BRESULT fddxdf_readid(FDDFILE fdd); - -#ifdef __cplusplus -} -#endif -#endif - - + +#ifdef SUPPORT_KAI_IMAGES + +#ifdef __cplusplus +extern "C" { +#endif + +#if 1 // 関数名変更&引数追加(k9) +BRESULT fdd_set_xdf(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); +BRESULT fdd_set_fdi(FDDFILE fdd, FDDFUNC fdd_fn, const OEMCHAR *fname, int ro); + +//BRESULT fdd_diskaccess_xdf(FDDFILE fdd); +//BRESULT fdd_seek_xdf(FDDFILE fdd); +//BRESULT fdd_seeksector_xdf(FDDFILE fdd); +BRESULT fdd_read_xdf(FDDFILE fdd); +BRESULT fdd_write_xdf(FDDFILE fdd); +//BRESULT fdd_readid_xdf(FDDFILE fdd); +BRESULT fdd_formatinit_xdf(FDDFILE fdd); /* 170107 to support format command */ +#else +BRESULT fddxdf_set(FDDFILE fdd, const OEMCHAR *fname, int ro); +BRESULT fddxdf_setfdi(FDDFILE fdd, const OEMCHAR *fname, int ro); +BRESULT fddxdf_eject(FDDFILE fdd); + +BRESULT fddxdf_diskaccess(FDDFILE fdd); +BRESULT fddxdf_seek(FDDFILE fdd); +BRESULT fddxdf_seeksector(FDDFILE fdd); +BRESULT fddxdf_read(FDDFILE fdd); +BRESULT fddxdf_write(FDDFILE fdd); +BRESULT fddxdf_readid(FDDFILE fdd); + +#ifdef __cplusplus +} +#endif +#endif + +#else +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT fddxdf_set(FDDFILE fdd, const OEMCHAR *fname, int ro); +BRESULT fddxdf_setfdi(FDDFILE fdd, const OEMCHAR *fname, int ro); +BRESULT fddxdf_eject(FDDFILE fdd); + +BRESULT fddxdf_diskaccess(FDDFILE fdd); +BRESULT fddxdf_seek(FDDFILE fdd); +BRESULT fddxdf_seeksector(FDDFILE fdd); +BRESULT fddxdf_read(FDDFILE fdd); +BRESULT fddxdf_write(FDDFILE fdd); +BRESULT fddxdf_readid(FDDFILE fdd); + +#ifdef __cplusplus +} +#endif +#endif + + diff --git a/diskimage/fddfile.c b/diskimage/fddfile.c old mode 100755 new mode 100644 index bc720af5..e894a763 --- a/diskimage/fddfile.c +++ b/diskimage/fddfile.c @@ -1,835 +1,835 @@ -#include -#include -#include -#include -#include -#include -#include - -#ifdef SUPPORT_KAI_IMAGES - -#include "diskimage/img_common.h" // 追加(Kai1) -#include "diskimage/img_strres.h" // 追加(Kai1) -#include "diskimage/fd/fdd_xdf.h" // 追加(Kai1) -#include "diskimage/fd/fdd_d88.h" // 追加(Kai1) -#include "diskimage/fd/fdd_dcp.h" // 追加(Kai1) -#include "diskimage/fd/fdd_bkdsk.h" // 追加(Kai1) -#include "diskimage/fd/fdd_nfd.h" // 追加(Kai1) -#include "diskimage/fd/fdd_vfdd.h" // 追加(Kai1) - - - _FDDFILE fddfile[MAX_FDDFILE]; - _FDDFUNC fddfunc[MAX_FDDFILE]; // 追加(Kai1) - UINT8 fddlasterror; - -// 追加(kai9) -void fddfunc_init(FDDFUNC fdd_fn) { - - fdd_fn->eject = fdd_eject_xxx; - fdd_fn->diskaccess = fdd_dummy_xxx; - fdd_fn->seek = fdd_dummy_xxx; - fdd_fn->seeksector = fdd_dummy_xxx; - fdd_fn->read = fdd_dummy_xxx; - fdd_fn->write = fdd_dummy_xxx; - fdd_fn->readid = fdd_dummy_xxx; - fdd_fn->writeid = fdd_dummy_xxx; - fdd_fn->formatinit = fdd_dummy_xxx; - fdd_fn->formating = fdd_formating_xxx; - fdd_fn->isformating = fdd_isformating_xxx; - fdd_fn->fdcresult = FALSE; // 追加(Kai1) -} -// - -// ---- - -void fddfile_initialize(void) { - - UINT i; - - // とりあえずダミーで埋めておく(Kai1) - for (i = 0; i < MAX_FDDFILE; i++) { - fddfunc_init(&fddfunc[i]); - } - // - ZeroMemory(fddfile, sizeof(fddfile)); -} - -void fddfile_reset2dmode(void) { // ver0.29 -#if 0 - int i; - - for (i=0; i<4; i++) { - fddfile[i].mode2d = 0; - } -#endif -} - -OEMCHAR *fdd_diskname(REG8 drv) { - - if (drv >= MAX_FDDFILE) { - return(NULL); - } - return(fddfile[drv].fname); -} - -OEMCHAR *fdd_getfileex(REG8 drv, UINT *ftype, int *ro) { - - FDDFILE fdd; - - if (drv >= MAX_FDDFILE) { - return((OEMCHAR *)str_null); - } - fdd = fddfile + drv; - if (ftype) { - *ftype = fdd->ftype; - } - if (ro) { - *ro = fdd->ro; - } - return(fdd->fname); -} - -BOOL fdd_diskready(REG8 drv) { - - if ((drv >= MAX_FDDFILE) || (!fddfile[drv].fname[0])) { - return(FALSE); - } - return(TRUE); -} - -BOOL fdd_diskprotect(REG8 drv) { - - if ((drv >= MAX_FDDFILE) || (!fddfile[drv].protect)) { - return(FALSE); - } - return(TRUE); -} - - -// -------------------------------------------------------------------------- - -BRESULT fdd_set(REG8 drv, const OEMCHAR *fname, UINT ftype, int ro) { - - FDDFILE fdd; - FDDFUNC fdd_fn; // 追加(Kai1) - UINT fddtype; -const OEMCHAR *p; - BRESULT r; - - if (drv >= MAX_FDDFILE) { - return(FAILURE); - } - fddtype = ftype; - if (fddtype == FTYPE_NONE) { - p = file_getext(fname); - if ((!milstr_cmp(p, str_d88)) || (!milstr_cmp(p, str_88d)) || - (!milstr_cmp(p, str_d98)) || (!milstr_cmp(p, str_98d))) { - fddtype = FTYPE_D88; - } - else if (!milstr_cmp(p, str_fdi)) { - fddtype = FTYPE_FDI; - } -// 厳密な対応のためにFTYPE_BETAより分離(Kai1) - else if ((!milstr_cmp(p, str_dcp)) || (!milstr_cmp(p, str_dcu))) { - fddtype = FTYPE_DCP; - } -// -// 追加(Kai1) - else if (!milstr_cmp(p, str_nfd)) { - fddtype = FTYPE_NFD; - } - else if (!milstr_cmp(p, str_vfdd)) { - fddtype = FTYPE_VFDD; - } -// - else { - fddtype = FTYPE_BETA; - } - } - fdd = fddfile + drv; - fdd_fn = fddfunc + drv; // 追加(Kai1) - fdd_fn->eject(fdd); // 念のためイジェクト(Kai1) - switch(fddtype) { - case FTYPE_FDI: - r = fdd_set_fdi(fdd, fdd_fn, fname, ro); - if (r == SUCCESS) { - break; - } - /* FALLTHROUGH */ - - case FTYPE_BETA: - r = fdd_set_xdf(fdd, fdd_fn, fname, ro); - // 追加(Kai1) - if (r != SUCCESS) { - // BKDSK(HDB) BASIC 2HDかな?かな? - r = fdd_set_bkdsk(fdd, fdd_fn, fname, ro); - break; - } - // - break; - - case FTYPE_D88: - r = fdd_set_d88(fdd, fdd_fn, fname, ro); - break; -// 厳密な対応(Kai1) - case FTYPE_DCP: - r = fdd_set_dcp(fdd, fdd_fn, fname, ro); - break; -// -// 追加(Kai1) - case FTYPE_NFD: - r = fdd_set_nfd(fdd, fdd_fn, fname, ro); - break; - case FTYPE_VFDD: - r = fdd_set_vfdd(fdd, fdd_fn, fname, ro); - break; -// - default: - r = fdd_set_xdf(fdd, fdd_fn, fname, ro); - // 追加(Kai1) - if (r != SUCCESS) { - // BKDSK(HDB) BASIC 2HDかな?かな? - r = fdd_set_bkdsk(fdd, fdd_fn, fname, ro); - break; - } - // - break; - //r = FAILURE; - } - if (r == SUCCESS) { - file_cpyname(fdd->fname, fname, NELEMENTS(fdd->fname)); - file_cpyname(np2cfg.fddfile[drv], fname, NELEMENTS(np2cfg.fddfile[drv])); - fdd->ftype = ftype; - fdd->ro = ro; - } - return(FAILURE); -} - -BRESULT fdd_eject(REG8 drv) { - - BRESULT ret; // 追加(Kai1) - FDDFILE fdd; - FDDFUNC fdd_fn; // 追加(Kai1) - - if (drv >= MAX_FDDFILE) { - return(FAILURE); - } - fdd = fddfile + drv; - fdd_fn = fddfunc + drv; // 追加(Kai1) -#if 1 // 変更(Kai1) - ret = fdd_fn->eject(fdd); - - ZeroMemory(fdd, sizeof(_FDDFILE)); - - fdd->fname[0] = '\0'; - fdd->type = DISKTYPE_NOTREADY; - - fddfunc_init(fdd_fn); - - return ret; -#else - switch(fdd->type) { - case DISKTYPE_BETA: -// return(fddxdf_eject(fdd)); - return(fdd_eject_xdf(fdd)); - - case DISKTYPE_D88: -// return(fddd88_eject(fdd)); - return(fdd_eject_d88(fdd)); - } - return(FAILURE); -#endif -} - -// ---- -// 未実装、未対応用ダミー関数群(Kai1) -BRESULT fdd_dummy_xxx(FDDFILE fdd) { - - (void)fdd; - return(FAILURE); -} - -BRESULT fdd_eject_xxx(FDDFILE fdd) { - - (void)fdd; - return(SUCCESS); -} - -BRESULT fdd_formating_xxx(FDDFILE fdd, const UINT8 *ID) { - - (void)fdd; - (void)ID; - return(FAILURE); -} - -BOOL fdd_isformating_xxx(FDDFILE fdd) { - - (void)fdd; - /* 170107 to support format command form ... */ - //return(FAILURE); - return FALSE; - /* 170107 to support format command ... to */ -} -// ---- -// ベタ系イメージ用共通処理関数群(Kai1) -BRESULT fdd_diskaccess_common(FDDFILE fdd) { - - if (CTRL_FDMEDIA != fdd->inf.xdf.disktype) { - return(FAILURE); - } - return(SUCCESS); -} - -BRESULT fdd_seek_common(FDDFILE fdd) { - - if ((CTRL_FDMEDIA != fdd->inf.xdf.disktype) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - //!(fdc.chgreg & fdd->inf.xdf.disktype) || // np21w ver0.86 rev20 - (fdc.ncn >= (fdd->inf.xdf.tracks >> 1))) { - return(FAILURE); - } - return(SUCCESS); -} - -BRESULT fdd_seeksector_common(FDDFILE fdd) { - - if ((CTRL_FDMEDIA != fdd->inf.xdf.disktype) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - //!(fdc.chgreg & fdd->inf.xdf.disktype) || // np21w ver0.86 rev20 - (fdc.treg[fdc.us] >= (fdd->inf.xdf.tracks >> 1))) { -TRACEOUT(("fdd_seek_common FAILURE CTRL_FDMEDIA[%02x], DISKTYPE[%02x]", CTRL_FDMEDIA, fdd->inf.xdf.disktype)); -TRACEOUT(("fdd_seek_common FAILURE fdc.rpm[%02x], fdd->rpm[%02x]", fdc.rpm[fdc.us], fdd->inf.xdf.rpm)); -TRACEOUT(("fdd_seek_common FAILURE fdc.treg[%02x], fdd->trk[%02x]", fdc.treg[fdc.us], (fdd->inf.xdf.tracks >> 1))); - fddlasterror = 0xe0; - return(FAILURE); - } - if ((!fdc.R) || (fdc.R > fdd->inf.xdf.sectors)) { -TRACEOUT(("fdd_seek_common FAILURE fdc.R[%02x], Secters[%02x]", fdc.R, fdd->inf.xdf.sectors)); - fddlasterror = 0xc0; - return(FAILURE); - } - if ((fdc.mf != 0xff) && (fdc.mf != 0x40)) { -TRACEOUT(("fdd_seek_common FAILURE fdc.mf[%02x]", fdc.mf)); - fddlasterror = 0xc0; - return(FAILURE); - } - return(SUCCESS); -} - -BRESULT fdd_readid_common(FDDFILE fdd) { - - fddlasterror = 0x00; - /* 170101 ST modified to work on Windows 9x/2000 form ... */ - if (fdc.crcn >= fdd->inf.xdf.sectors) { - fdc.crcn = 0; - if(fdc.mt) { - fdc.hd ^= 1; - if (fdc.hd == 0) { - fdc.treg[fdc.us]++; - } - } - else { - fdc.treg[fdc.us]++; - } - } - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - if ((!fdc.mf) || - (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || - (CTRL_FDMEDIA != fdd->inf.xdf.disktype)) { - //!(fdc.chgreg & fdd->inf.xdf.disktype) || // np21w ver0.86 rev20 - //(fdc.crcn >= fdd->inf.xdf.sectors)) { - fddlasterror = 0xe0; - return(FAILURE); - } - fdc.C = fdc.treg[fdc.us]; - fdc.H = fdc.hd; - fdc.R = ++fdc.crcn; - fdc.N = fdd->inf.xdf.n; - return(SUCCESS); -} -// ---- - -BRESULT fdd_diskaccess(void) { - - FDDFILE fdd; - FDDFUNC fdd_fn; // 追加(Kai1) - - fdd = fddfile + fdc.us; - fdd_fn = fddfunc + fdc.us; // 追加(Kai1) -#if 1 // 変更(Kai1) - return(fdd_fn->diskaccess(fdd)); -#else - switch(fdd->type) { - case DISKTYPE_BETA: -// return(fddxdf_diskaccess(fdd)); - return(fdd_diskaccess_xdf(fdd)); - - case DISKTYPE_D88: -// return(fdd_diskaccess_d88()); - return(fdd_diskaccess_d88(fdd)); - } - return(FAILURE); -#endif -} - -BRESULT fdd_seek(void) { - - BRESULT ret; - FDDFILE fdd; - FDDFUNC fdd_fn; // 追加(Kai1) - - ret = FAILURE; - fdd = fddfile + fdc.us; - fdd_fn = fddfunc + fdc.us; // 追加(Kai1) -#if 1 // 変更(Kai1) - ret = fdd_fn->seek(fdd); -#else - switch(fdd->type) { - case DISKTYPE_BETA: -// ret = fddxdf_seek(fdd); - ret = fdd_seek_xdf(fdd); - break; - - case DISKTYPE_D88: -// ret = fdd_seek_d88(); - ret = fdd_seek_d88(fdd); - break; - } -#endif - fdc.treg[fdc.us] = fdc.ncn; - return(ret); -} - -BRESULT fdd_seeksector(void) { - - FDDFILE fdd; - FDDFUNC fdd_fn; // 追加(Kai1) - - fdd = fddfile + fdc.us; - fdd_fn = fddfunc + fdc.us; // 追加(Kai1) -#if 1 // 変更(Kai1) - return(fdd_fn->seeksector(fdd)); -#else - switch(fdd->type) { - case DISKTYPE_BETA: -// return(fddxdf_seeksector(fdd)); - return(fdd_seeksector_xdf(fdd)); - - case DISKTYPE_D88: -// return(fdd_seeksector_d88()); - return(fdd_seeksector_d88(fdd)); - } - return(FAILURE); -#endif -} - - -BRESULT fdd_read(void) { - - FDDFILE fdd; - FDDFUNC fdd_fn; // 追加(Kai1) - - sysmng_fddaccess(fdc.us); - fdd = fddfile + fdc.us; - fdd_fn = fddfunc + fdc.us; // 追加(Kai1) -#if 1 // 変更(Kai1) - return(fdd_fn->read(fdd)); -#else - switch(fdd->type) { - case DISKTYPE_BETA: -// return(fddxdf_read(fdd)); - return(fdd_read_xdf(fdd)); - - case DISKTYPE_D88: -// return(fdd_read_d88()); - return(fdd_read_d88(fdd)); - } - return(FAILURE); -#endif -} - -BRESULT fdd_write(void) { - - FDDFILE fdd; - FDDFUNC fdd_fn; // 追加(Kai1) - - sysmng_fddaccess(fdc.us); - fdd = fddfile + fdc.us; - fdd_fn = fddfunc + fdc.us; // 追加(Kai1) -#if 1 // 変更(Kai1) - return(fdd_fn->write(fdd)); -#else - switch(fdd->type) { - case DISKTYPE_BETA: -// return(fddxdf_write(fdd)); - return(fdd_write_xdf(fdd)); - - case DISKTYPE_D88: -// return(fdd_write_d88()); - return(fdd_write_d88(fdd)); - } - return(FAILURE); -#endif -} - -BRESULT fdd_readid(void) { - - FDDFILE fdd; - FDDFUNC fdd_fn; // 追加(Kai1) - - sysmng_fddaccess(fdc.us); - fdd = fddfile + fdc.us; - fdd_fn = fddfunc + fdc.us; // 追加(Kai1) -#if 1 // 変更(Kai1) - return(fdd_fn->readid(fdd)); -#else - switch(fdd->type) { - case DISKTYPE_BETA: -// return(fddxdf_readid(fdd)); - return(fdd_readid_xdf(fdd)); - - case DISKTYPE_D88: -// return(fdd_readid_d88()); - return(fdd_readid_d88(fdd)); - } - return(FAILURE); -#endif -} - -BRESULT fdd_formatinit(void) { - - FDDFILE fdd; // 追加(Kai1) - FDDFUNC fdd_fn; // 追加(Kai1) - - fdd = fddfile + fdc.us; // 追加(Kai1) - fdd_fn = fddfunc + fdc.us; // 追加(Kai1) -#if 1 // 変更(Kai1) - return(fdd_fn->formatinit(fdd)); -#else - if (fddfile[fdc.us].type == DISKTYPE_D88) { -// return(fdd_formatinit_d88()); - return(fdd_formatinit_d88(fdd)); - } - return(FAILURE); -#endif -} - -BRESULT fdd_formating(const UINT8 *ID) { - - FDDFILE fdd; // 追加(Kai1) - FDDFUNC fdd_fn; // 追加(Kai1) - - sysmng_fddaccess(fdc.us); - fdd = fddfile + fdc.us; // 追加(Kai1) - fdd_fn = fddfunc + fdc.us; // 追加(Kai1) -#if 1 // 変更(Kai1) - return(fdd_fn->formating(fdd, ID)); -#else - if (fddfile[fdc.us].type == DISKTYPE_D88) { -// return(fdd_formating_d88(ID)); - return(fdd_formating_d88(fdd, ID)); - } - return(FAILURE); -#endif -} - -BOOL fdd_isformating(void) { - - FDDFILE fdd; // 追加(Kai1) - FDDFUNC fdd_fn; // 追加(Kai1) - - fdd = fddfile + fdc.us; // 追加(Kai1) - fdd_fn = fddfunc + fdc.us; // 追加(Kai1) -#if 1 // 変更(Kai1) - /* 170107 to support format command form ... */ - //return(fdd_fn->formatinit(fdd)); - return(fdd_fn->isformating(fdd)); - /* 170107 to support format command ... to */ -#else - if (fddfile[fdc.us].type == DISKTYPE_D88) { -// return(fdd_isformating_d88()); - return(fdd_isformating_d88(fdd)); - } - return(FALSE); -#endif -} - -// 追加(Kai1) -BOOL fdd_fdcresult(void) { - - FDDFUNC fdd_fn; - - fdd_fn = fddfunc + fdc.us; - - return(fdd_fn->fdcresult); -} -// - -#else -#include "diskimage/fd/fdd_xdf.h" -#include "diskimage/fd/fdd_d88.h" - - - _FDDFILE fddfile[MAX_FDDFILE]; - UINT8 fddlasterror; - - -// ---- - -void fddfile_initialize(void) { - - ZeroMemory(fddfile, sizeof(fddfile)); -} - -void fddfile_reset2dmode(void) { // ver0.29 -#if 0 - int i; - - for (i=0; i<4; i++) { - fddfile[i].mode2d = 0; - } -#endif -} - -OEMCHAR *fdd_diskname(REG8 drv) { - - if (drv >= MAX_FDDFILE) { - return(NULL); - } - return(fddfile[drv].fname); -} - -OEMCHAR *fdd_getfileex(REG8 drv, UINT *ftype, int *ro) { - - FDDFILE fdd; - - if (drv >= MAX_FDDFILE) { - return((OEMCHAR *)str_null); - } - fdd = fddfile + drv; - if (ftype) { - *ftype = fdd->ftype; - } - if (ro) { - *ro = fdd->ro; - } - return(fdd->fname); -} - -BOOL fdd_diskready(REG8 drv) { - - if ((drv >= MAX_FDDFILE) || (!fddfile[drv].fname[0])) { - return(FALSE); - } - return(TRUE); -} - -BOOL fdd_diskprotect(REG8 drv) { - - if ((drv >= MAX_FDDFILE) || (!fddfile[drv].protect)) { - return(FALSE); - } - return(TRUE); -} - - -// -------------------------------------------------------------------------- - -BRESULT fdd_set(REG8 drv, const OEMCHAR *fname, UINT ftype, int ro) { - - FDDFILE fdd; - UINT fddtype; -const OEMCHAR *p; - BRESULT r; - - if (drv >= MAX_FDDFILE) { - return(FAILURE); - } - fddtype = ftype; - if (fddtype == FTYPE_NONE) { - p = file_getext(fname); - if ((!milstr_cmp(p, str_d88)) || (!milstr_cmp(p, str_88d)) || - (!milstr_cmp(p, str_d98)) || (!milstr_cmp(p, str_98d))) { - fddtype = FTYPE_D88; - } - else if (!milstr_cmp(p, str_fdi)) { - fddtype = FTYPE_FDI; - } - else { - fddtype = FTYPE_BETA; - } - } - fdd = fddfile + drv; - switch(fddtype) { - case FTYPE_FDI: - r = fddxdf_setfdi(fdd, fname, ro); - if (r == SUCCESS) { - break; - } - /* FALLTHROUGH */ - - case FTYPE_BETA: - r = fddxdf_set(fdd, fname, ro); - break; - - case FTYPE_D88: - r = fddd88_set(fdd, fname, ro); - break; - - default: - r = FAILURE; - } - if (r == SUCCESS) { - file_cpyname(fdd->fname, fname, NELEMENTS(fdd->fname)); - fdd->ftype = ftype; - fdd->ro = ro; - } - return(FAILURE); -} - -BRESULT fdd_eject(REG8 drv) { - - FDDFILE fdd; - - if (drv >= MAX_FDDFILE) { - return(FAILURE); - } - fdd = fddfile + drv; - switch(fdd->type) { - case DISKTYPE_BETA: - return(fddxdf_eject(fdd)); - - case DISKTYPE_D88: - return(fddd88_eject(fdd)); - } - return(FAILURE); -} - - -// ---- - -BRESULT fdd_diskaccess(void) { - - FDDFILE fdd; - - fdd = fddfile + fdc.us; - switch(fdd->type) { - case DISKTYPE_BETA: - return(fddxdf_diskaccess(fdd)); - - case DISKTYPE_D88: - return(fdd_diskaccess_d88()); - } - return(FAILURE); -} - -BRESULT fdd_seek(void) { - - BRESULT ret; - FDDFILE fdd; - - ret = FAILURE; - fdd = fddfile + fdc.us; - switch(fdd->type) { - case DISKTYPE_BETA: - ret = fddxdf_seek(fdd); - break; - - case DISKTYPE_D88: - ret = fdd_seek_d88(); - break; - } - fdc.treg[fdc.us] = fdc.ncn; - return(ret); -} - -BRESULT fdd_seeksector(void) { - - FDDFILE fdd; - - fdd = fddfile + fdc.us; - switch(fdd->type) { - case DISKTYPE_BETA: - return(fddxdf_seeksector(fdd)); - - case DISKTYPE_D88: - return(fdd_seeksector_d88()); - } - return(FAILURE); -} - - -BRESULT fdd_read(void) { - - FDDFILE fdd; - - sysmng_fddaccess(fdc.us); - fdd = fddfile + fdc.us; - switch(fdd->type) { - case DISKTYPE_BETA: - return(fddxdf_read(fdd)); - - case DISKTYPE_D88: - return(fdd_read_d88()); - } - return(FAILURE); -} - -BRESULT fdd_write(void) { - - FDDFILE fdd; - - sysmng_fddaccess(fdc.us); - fdd = fddfile + fdc.us; - switch(fdd->type) { - case DISKTYPE_BETA: - return(fddxdf_write(fdd)); - - case DISKTYPE_D88: - return(fdd_write_d88()); - } - return(FAILURE); -} - -BRESULT fdd_readid(void) { - - FDDFILE fdd; - - sysmng_fddaccess(fdc.us); - fdd = fddfile + fdc.us; - switch(fdd->type) { - case DISKTYPE_BETA: - return(fddxdf_readid(fdd)); - - case DISKTYPE_D88: - return(fdd_readid_d88()); - } - return(FAILURE); -} - -BRESULT fdd_formatinit(void) { - - if (fddfile[fdc.us].type == DISKTYPE_D88) { - return(fdd_formatinit_d88()); - } - return(FAILURE); -} - -BRESULT fdd_formating(const UINT8 *ID) { - - sysmng_fddaccess(fdc.us); - if (fddfile[fdc.us].type == DISKTYPE_D88) { - return(fdd_formating_d88(ID)); - } - return(FAILURE); -} - -BOOL fdd_isformating(void) { - - if (fddfile[fdc.us].type == DISKTYPE_D88) { - return(fdd_isformating_d88()); - } - return(FALSE); -} - +#include +#include +#include +#include +#include +#include +#include + +#ifdef SUPPORT_KAI_IMAGES + +#include "diskimage/img_common.h" // 追加(Kai1) +#include "diskimage/img_strres.h" // 追加(Kai1) +#include "diskimage/fd/fdd_xdf.h" // 追加(Kai1) +#include "diskimage/fd/fdd_d88.h" // 追加(Kai1) +#include "diskimage/fd/fdd_dcp.h" // 追加(Kai1) +#include "diskimage/fd/fdd_bkdsk.h" // 追加(Kai1) +#include "diskimage/fd/fdd_nfd.h" // 追加(Kai1) +#include "diskimage/fd/fdd_vfdd.h" // 追加(Kai1) + + + _FDDFILE fddfile[MAX_FDDFILE]; + _FDDFUNC fddfunc[MAX_FDDFILE]; // 追加(Kai1) + UINT8 fddlasterror; + +// 追加(kai9) +void fddfunc_init(FDDFUNC fdd_fn) { + + fdd_fn->eject = fdd_eject_xxx; + fdd_fn->diskaccess = fdd_dummy_xxx; + fdd_fn->seek = fdd_dummy_xxx; + fdd_fn->seeksector = fdd_dummy_xxx; + fdd_fn->read = fdd_dummy_xxx; + fdd_fn->write = fdd_dummy_xxx; + fdd_fn->readid = fdd_dummy_xxx; + fdd_fn->writeid = fdd_dummy_xxx; + fdd_fn->formatinit = fdd_dummy_xxx; + fdd_fn->formating = fdd_formating_xxx; + fdd_fn->isformating = fdd_isformating_xxx; + fdd_fn->fdcresult = FALSE; // 追加(Kai1) +} +// + +// ---- + +void fddfile_initialize(void) { + + UINT i; + + // とりあえずダミーで埋めておく(Kai1) + for (i = 0; i < MAX_FDDFILE; i++) { + fddfunc_init(&fddfunc[i]); + } + // + ZeroMemory(fddfile, sizeof(fddfile)); +} + +void fddfile_reset2dmode(void) { // ver0.29 +#if 0 + int i; + + for (i=0; i<4; i++) { + fddfile[i].mode2d = 0; + } +#endif +} + +OEMCHAR *fdd_diskname(REG8 drv) { + + if (drv >= MAX_FDDFILE) { + return(NULL); + } + return(fddfile[drv].fname); +} + +OEMCHAR *fdd_getfileex(REG8 drv, UINT *ftype, int *ro) { + + FDDFILE fdd; + + if (drv >= MAX_FDDFILE) { + return((OEMCHAR *)str_null); + } + fdd = fddfile + drv; + if (ftype) { + *ftype = fdd->ftype; + } + if (ro) { + *ro = fdd->ro; + } + return(fdd->fname); +} + +BOOL fdd_diskready(REG8 drv) { + + if ((drv >= MAX_FDDFILE) || (!fddfile[drv].fname[0])) { + return(FALSE); + } + return(TRUE); +} + +BOOL fdd_diskprotect(REG8 drv) { + + if ((drv >= MAX_FDDFILE) || (!fddfile[drv].protect)) { + return(FALSE); + } + return(TRUE); +} + + +// -------------------------------------------------------------------------- + +BRESULT fdd_set(REG8 drv, const OEMCHAR *fname, UINT ftype, int ro) { + + FDDFILE fdd; + FDDFUNC fdd_fn; // 追加(Kai1) + UINT fddtype; +const OEMCHAR *p; + BRESULT r; + + if (drv >= MAX_FDDFILE) { + return(FAILURE); + } + fddtype = ftype; + if (fddtype == FTYPE_NONE) { + p = file_getext(fname); + if ((!milstr_cmp(p, str_d88)) || (!milstr_cmp(p, str_88d)) || + (!milstr_cmp(p, str_d98)) || (!milstr_cmp(p, str_98d))) { + fddtype = FTYPE_D88; + } + else if (!milstr_cmp(p, str_fdi)) { + fddtype = FTYPE_FDI; + } +// 厳密な対応のためにFTYPE_BETAより分離(Kai1) + else if ((!milstr_cmp(p, str_dcp)) || (!milstr_cmp(p, str_dcu))) { + fddtype = FTYPE_DCP; + } +// +// 追加(Kai1) + else if (!milstr_cmp(p, str_nfd)) { + fddtype = FTYPE_NFD; + } + else if (!milstr_cmp(p, str_vfdd)) { + fddtype = FTYPE_VFDD; + } +// + else { + fddtype = FTYPE_BETA; + } + } + fdd = fddfile + drv; + fdd_fn = fddfunc + drv; // 追加(Kai1) + fdd_fn->eject(fdd); // 念のためイジェクト(Kai1) + switch(fddtype) { + case FTYPE_FDI: + r = fdd_set_fdi(fdd, fdd_fn, fname, ro); + if (r == SUCCESS) { + break; + } + /* FALLTHROUGH */ + + case FTYPE_BETA: + r = fdd_set_xdf(fdd, fdd_fn, fname, ro); + // 追加(Kai1) + if (r != SUCCESS) { + // BKDSK(HDB) BASIC 2HDかな?かな? + r = fdd_set_bkdsk(fdd, fdd_fn, fname, ro); + break; + } + // + break; + + case FTYPE_D88: + r = fdd_set_d88(fdd, fdd_fn, fname, ro); + break; +// 厳密な対応(Kai1) + case FTYPE_DCP: + r = fdd_set_dcp(fdd, fdd_fn, fname, ro); + break; +// +// 追加(Kai1) + case FTYPE_NFD: + r = fdd_set_nfd(fdd, fdd_fn, fname, ro); + break; + case FTYPE_VFDD: + r = fdd_set_vfdd(fdd, fdd_fn, fname, ro); + break; +// + default: + r = fdd_set_xdf(fdd, fdd_fn, fname, ro); + // 追加(Kai1) + if (r != SUCCESS) { + // BKDSK(HDB) BASIC 2HDかな?かな? + r = fdd_set_bkdsk(fdd, fdd_fn, fname, ro); + break; + } + // + break; + //r = FAILURE; + } + if (r == SUCCESS) { + file_cpyname(fdd->fname, fname, NELEMENTS(fdd->fname)); + file_cpyname(np2cfg.fddfile[drv], fname, NELEMENTS(np2cfg.fddfile[drv])); + fdd->ftype = ftype; + fdd->ro = ro; + } + return(FAILURE); +} + +BRESULT fdd_eject(REG8 drv) { + + BRESULT ret; // 追加(Kai1) + FDDFILE fdd; + FDDFUNC fdd_fn; // 追加(Kai1) + + if (drv >= MAX_FDDFILE) { + return(FAILURE); + } + fdd = fddfile + drv; + fdd_fn = fddfunc + drv; // 追加(Kai1) +#if 1 // 変更(Kai1) + ret = fdd_fn->eject(fdd); + + ZeroMemory(fdd, sizeof(_FDDFILE)); + + fdd->fname[0] = '\0'; + fdd->type = DISKTYPE_NOTREADY; + + fddfunc_init(fdd_fn); + + return ret; +#else + switch(fdd->type) { + case DISKTYPE_BETA: +// return(fddxdf_eject(fdd)); + return(fdd_eject_xdf(fdd)); + + case DISKTYPE_D88: +// return(fddd88_eject(fdd)); + return(fdd_eject_d88(fdd)); + } + return(FAILURE); +#endif +} + +// ---- +// 未実装、未対応用ダミー関数群(Kai1) +BRESULT fdd_dummy_xxx(FDDFILE fdd) { + + (void)fdd; + return(FAILURE); +} + +BRESULT fdd_eject_xxx(FDDFILE fdd) { + + (void)fdd; + return(SUCCESS); +} + +BRESULT fdd_formating_xxx(FDDFILE fdd, const UINT8 *ID) { + + (void)fdd; + (void)ID; + return(FAILURE); +} + +BOOL fdd_isformating_xxx(FDDFILE fdd) { + + (void)fdd; + /* 170107 to support format command form ... */ + //return(FAILURE); + return FALSE; + /* 170107 to support format command ... to */ +} +// ---- +// ベタ系イメージ用共通処理関数群(Kai1) +BRESULT fdd_diskaccess_common(FDDFILE fdd) { + + if (CTRL_FDMEDIA != fdd->inf.xdf.disktype) { + return(FAILURE); + } + return(SUCCESS); +} + +BRESULT fdd_seek_common(FDDFILE fdd) { + + if ((CTRL_FDMEDIA != fdd->inf.xdf.disktype) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + //!(fdc.chgreg & fdd->inf.xdf.disktype) || // np21w ver0.86 rev20 + (fdc.ncn >= (fdd->inf.xdf.tracks >> 1))) { + return(FAILURE); + } + return(SUCCESS); +} + +BRESULT fdd_seeksector_common(FDDFILE fdd) { + + if ((CTRL_FDMEDIA != fdd->inf.xdf.disktype) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + //!(fdc.chgreg & fdd->inf.xdf.disktype) || // np21w ver0.86 rev20 + (fdc.treg[fdc.us] >= (fdd->inf.xdf.tracks >> 1))) { +TRACEOUT(("fdd_seek_common FAILURE CTRL_FDMEDIA[%02x], DISKTYPE[%02x]", CTRL_FDMEDIA, fdd->inf.xdf.disktype)); +TRACEOUT(("fdd_seek_common FAILURE fdc.rpm[%02x], fdd->rpm[%02x]", fdc.rpm[fdc.us], fdd->inf.xdf.rpm)); +TRACEOUT(("fdd_seek_common FAILURE fdc.treg[%02x], fdd->trk[%02x]", fdc.treg[fdc.us], (fdd->inf.xdf.tracks >> 1))); + fddlasterror = 0xe0; + return(FAILURE); + } + if ((!fdc.R) || (fdc.R > fdd->inf.xdf.sectors)) { +TRACEOUT(("fdd_seek_common FAILURE fdc.R[%02x], Secters[%02x]", fdc.R, fdd->inf.xdf.sectors)); + fddlasterror = 0xc0; + return(FAILURE); + } + if ((fdc.mf != 0xff) && (fdc.mf != 0x40)) { +TRACEOUT(("fdd_seek_common FAILURE fdc.mf[%02x]", fdc.mf)); + fddlasterror = 0xc0; + return(FAILURE); + } + return(SUCCESS); +} + +BRESULT fdd_readid_common(FDDFILE fdd) { + + fddlasterror = 0x00; + /* 170101 ST modified to work on Windows 9x/2000 form ... */ + if (fdc.crcn >= fdd->inf.xdf.sectors) { + fdc.crcn = 0; + if(fdc.mt) { + fdc.hd ^= 1; + if (fdc.hd == 0) { + fdc.treg[fdc.us]++; + } + } + else { + fdc.treg[fdc.us]++; + } + } + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + if ((!fdc.mf) || + (fdc.rpm[fdc.us] != fdd->inf.xdf.rpm) || + (CTRL_FDMEDIA != fdd->inf.xdf.disktype)) { + //!(fdc.chgreg & fdd->inf.xdf.disktype) || // np21w ver0.86 rev20 + //(fdc.crcn >= fdd->inf.xdf.sectors)) { + fddlasterror = 0xe0; + return(FAILURE); + } + fdc.C = fdc.treg[fdc.us]; + fdc.H = fdc.hd; + fdc.R = ++fdc.crcn; + fdc.N = fdd->inf.xdf.n; + return(SUCCESS); +} +// ---- + +BRESULT fdd_diskaccess(void) { + + FDDFILE fdd; + FDDFUNC fdd_fn; // 追加(Kai1) + + fdd = fddfile + fdc.us; + fdd_fn = fddfunc + fdc.us; // 追加(Kai1) +#if 1 // 変更(Kai1) + return(fdd_fn->diskaccess(fdd)); +#else + switch(fdd->type) { + case DISKTYPE_BETA: +// return(fddxdf_diskaccess(fdd)); + return(fdd_diskaccess_xdf(fdd)); + + case DISKTYPE_D88: +// return(fdd_diskaccess_d88()); + return(fdd_diskaccess_d88(fdd)); + } + return(FAILURE); +#endif +} + +BRESULT fdd_seek(void) { + + BRESULT ret; + FDDFILE fdd; + FDDFUNC fdd_fn; // 追加(Kai1) + + ret = FAILURE; + fdd = fddfile + fdc.us; + fdd_fn = fddfunc + fdc.us; // 追加(Kai1) +#if 1 // 変更(Kai1) + ret = fdd_fn->seek(fdd); +#else + switch(fdd->type) { + case DISKTYPE_BETA: +// ret = fddxdf_seek(fdd); + ret = fdd_seek_xdf(fdd); + break; + + case DISKTYPE_D88: +// ret = fdd_seek_d88(); + ret = fdd_seek_d88(fdd); + break; + } +#endif + fdc.treg[fdc.us] = fdc.ncn; + return(ret); +} + +BRESULT fdd_seeksector(void) { + + FDDFILE fdd; + FDDFUNC fdd_fn; // 追加(Kai1) + + fdd = fddfile + fdc.us; + fdd_fn = fddfunc + fdc.us; // 追加(Kai1) +#if 1 // 変更(Kai1) + return(fdd_fn->seeksector(fdd)); +#else + switch(fdd->type) { + case DISKTYPE_BETA: +// return(fddxdf_seeksector(fdd)); + return(fdd_seeksector_xdf(fdd)); + + case DISKTYPE_D88: +// return(fdd_seeksector_d88()); + return(fdd_seeksector_d88(fdd)); + } + return(FAILURE); +#endif +} + + +BRESULT fdd_read(void) { + + FDDFILE fdd; + FDDFUNC fdd_fn; // 追加(Kai1) + + sysmng_fddaccess(fdc.us); + fdd = fddfile + fdc.us; + fdd_fn = fddfunc + fdc.us; // 追加(Kai1) +#if 1 // 変更(Kai1) + return(fdd_fn->read(fdd)); +#else + switch(fdd->type) { + case DISKTYPE_BETA: +// return(fddxdf_read(fdd)); + return(fdd_read_xdf(fdd)); + + case DISKTYPE_D88: +// return(fdd_read_d88()); + return(fdd_read_d88(fdd)); + } + return(FAILURE); +#endif +} + +BRESULT fdd_write(void) { + + FDDFILE fdd; + FDDFUNC fdd_fn; // 追加(Kai1) + + sysmng_fddaccess(fdc.us); + fdd = fddfile + fdc.us; + fdd_fn = fddfunc + fdc.us; // 追加(Kai1) +#if 1 // 変更(Kai1) + return(fdd_fn->write(fdd)); +#else + switch(fdd->type) { + case DISKTYPE_BETA: +// return(fddxdf_write(fdd)); + return(fdd_write_xdf(fdd)); + + case DISKTYPE_D88: +// return(fdd_write_d88()); + return(fdd_write_d88(fdd)); + } + return(FAILURE); +#endif +} + +BRESULT fdd_readid(void) { + + FDDFILE fdd; + FDDFUNC fdd_fn; // 追加(Kai1) + + sysmng_fddaccess(fdc.us); + fdd = fddfile + fdc.us; + fdd_fn = fddfunc + fdc.us; // 追加(Kai1) +#if 1 // 変更(Kai1) + return(fdd_fn->readid(fdd)); +#else + switch(fdd->type) { + case DISKTYPE_BETA: +// return(fddxdf_readid(fdd)); + return(fdd_readid_xdf(fdd)); + + case DISKTYPE_D88: +// return(fdd_readid_d88()); + return(fdd_readid_d88(fdd)); + } + return(FAILURE); +#endif +} + +BRESULT fdd_formatinit(void) { + + FDDFILE fdd; // 追加(Kai1) + FDDFUNC fdd_fn; // 追加(Kai1) + + fdd = fddfile + fdc.us; // 追加(Kai1) + fdd_fn = fddfunc + fdc.us; // 追加(Kai1) +#if 1 // 変更(Kai1) + return(fdd_fn->formatinit(fdd)); +#else + if (fddfile[fdc.us].type == DISKTYPE_D88) { +// return(fdd_formatinit_d88()); + return(fdd_formatinit_d88(fdd)); + } + return(FAILURE); +#endif +} + +BRESULT fdd_formating(const UINT8 *ID) { + + FDDFILE fdd; // 追加(Kai1) + FDDFUNC fdd_fn; // 追加(Kai1) + + sysmng_fddaccess(fdc.us); + fdd = fddfile + fdc.us; // 追加(Kai1) + fdd_fn = fddfunc + fdc.us; // 追加(Kai1) +#if 1 // 変更(Kai1) + return(fdd_fn->formating(fdd, ID)); +#else + if (fddfile[fdc.us].type == DISKTYPE_D88) { +// return(fdd_formating_d88(ID)); + return(fdd_formating_d88(fdd, ID)); + } + return(FAILURE); +#endif +} + +BOOL fdd_isformating(void) { + + FDDFILE fdd; // 追加(Kai1) + FDDFUNC fdd_fn; // 追加(Kai1) + + fdd = fddfile + fdc.us; // 追加(Kai1) + fdd_fn = fddfunc + fdc.us; // 追加(Kai1) +#if 1 // 変更(Kai1) + /* 170107 to support format command form ... */ + //return(fdd_fn->formatinit(fdd)); + return(fdd_fn->isformating(fdd)); + /* 170107 to support format command ... to */ +#else + if (fddfile[fdc.us].type == DISKTYPE_D88) { +// return(fdd_isformating_d88()); + return(fdd_isformating_d88(fdd)); + } + return(FALSE); +#endif +} + +// 追加(Kai1) +BOOL fdd_fdcresult(void) { + + FDDFUNC fdd_fn; + + fdd_fn = fddfunc + fdc.us; + + return(fdd_fn->fdcresult); +} +// + +#else +#include "diskimage/fd/fdd_xdf.h" +#include "diskimage/fd/fdd_d88.h" + + + _FDDFILE fddfile[MAX_FDDFILE]; + UINT8 fddlasterror; + + +// ---- + +void fddfile_initialize(void) { + + ZeroMemory(fddfile, sizeof(fddfile)); +} + +void fddfile_reset2dmode(void) { // ver0.29 +#if 0 + int i; + + for (i=0; i<4; i++) { + fddfile[i].mode2d = 0; + } +#endif +} + +OEMCHAR *fdd_diskname(REG8 drv) { + + if (drv >= MAX_FDDFILE) { + return(NULL); + } + return(fddfile[drv].fname); +} + +OEMCHAR *fdd_getfileex(REG8 drv, UINT *ftype, int *ro) { + + FDDFILE fdd; + + if (drv >= MAX_FDDFILE) { + return((OEMCHAR *)str_null); + } + fdd = fddfile + drv; + if (ftype) { + *ftype = fdd->ftype; + } + if (ro) { + *ro = fdd->ro; + } + return(fdd->fname); +} + +BOOL fdd_diskready(REG8 drv) { + + if ((drv >= MAX_FDDFILE) || (!fddfile[drv].fname[0])) { + return(FALSE); + } + return(TRUE); +} + +BOOL fdd_diskprotect(REG8 drv) { + + if ((drv >= MAX_FDDFILE) || (!fddfile[drv].protect)) { + return(FALSE); + } + return(TRUE); +} + + +// -------------------------------------------------------------------------- + +BRESULT fdd_set(REG8 drv, const OEMCHAR *fname, UINT ftype, int ro) { + + FDDFILE fdd; + UINT fddtype; +const OEMCHAR *p; + BRESULT r; + + if (drv >= MAX_FDDFILE) { + return(FAILURE); + } + fddtype = ftype; + if (fddtype == FTYPE_NONE) { + p = file_getext(fname); + if ((!milstr_cmp(p, str_d88)) || (!milstr_cmp(p, str_88d)) || + (!milstr_cmp(p, str_d98)) || (!milstr_cmp(p, str_98d))) { + fddtype = FTYPE_D88; + } + else if (!milstr_cmp(p, str_fdi)) { + fddtype = FTYPE_FDI; + } + else { + fddtype = FTYPE_BETA; + } + } + fdd = fddfile + drv; + switch(fddtype) { + case FTYPE_FDI: + r = fddxdf_setfdi(fdd, fname, ro); + if (r == SUCCESS) { + break; + } + /* FALLTHROUGH */ + + case FTYPE_BETA: + r = fddxdf_set(fdd, fname, ro); + break; + + case FTYPE_D88: + r = fddd88_set(fdd, fname, ro); + break; + + default: + r = FAILURE; + } + if (r == SUCCESS) { + file_cpyname(fdd->fname, fname, NELEMENTS(fdd->fname)); + fdd->ftype = ftype; + fdd->ro = ro; + } + return(FAILURE); +} + +BRESULT fdd_eject(REG8 drv) { + + FDDFILE fdd; + + if (drv >= MAX_FDDFILE) { + return(FAILURE); + } + fdd = fddfile + drv; + switch(fdd->type) { + case DISKTYPE_BETA: + return(fddxdf_eject(fdd)); + + case DISKTYPE_D88: + return(fddd88_eject(fdd)); + } + return(FAILURE); +} + + +// ---- + +BRESULT fdd_diskaccess(void) { + + FDDFILE fdd; + + fdd = fddfile + fdc.us; + switch(fdd->type) { + case DISKTYPE_BETA: + return(fddxdf_diskaccess(fdd)); + + case DISKTYPE_D88: + return(fdd_diskaccess_d88()); + } + return(FAILURE); +} + +BRESULT fdd_seek(void) { + + BRESULT ret; + FDDFILE fdd; + + ret = FAILURE; + fdd = fddfile + fdc.us; + switch(fdd->type) { + case DISKTYPE_BETA: + ret = fddxdf_seek(fdd); + break; + + case DISKTYPE_D88: + ret = fdd_seek_d88(); + break; + } + fdc.treg[fdc.us] = fdc.ncn; + return(ret); +} + +BRESULT fdd_seeksector(void) { + + FDDFILE fdd; + + fdd = fddfile + fdc.us; + switch(fdd->type) { + case DISKTYPE_BETA: + return(fddxdf_seeksector(fdd)); + + case DISKTYPE_D88: + return(fdd_seeksector_d88()); + } + return(FAILURE); +} + + +BRESULT fdd_read(void) { + + FDDFILE fdd; + + sysmng_fddaccess(fdc.us); + fdd = fddfile + fdc.us; + switch(fdd->type) { + case DISKTYPE_BETA: + return(fddxdf_read(fdd)); + + case DISKTYPE_D88: + return(fdd_read_d88()); + } + return(FAILURE); +} + +BRESULT fdd_write(void) { + + FDDFILE fdd; + + sysmng_fddaccess(fdc.us); + fdd = fddfile + fdc.us; + switch(fdd->type) { + case DISKTYPE_BETA: + return(fddxdf_write(fdd)); + + case DISKTYPE_D88: + return(fdd_write_d88()); + } + return(FAILURE); +} + +BRESULT fdd_readid(void) { + + FDDFILE fdd; + + sysmng_fddaccess(fdc.us); + fdd = fddfile + fdc.us; + switch(fdd->type) { + case DISKTYPE_BETA: + return(fddxdf_readid(fdd)); + + case DISKTYPE_D88: + return(fdd_readid_d88()); + } + return(FAILURE); +} + +BRESULT fdd_formatinit(void) { + + if (fddfile[fdc.us].type == DISKTYPE_D88) { + return(fdd_formatinit_d88()); + } + return(FAILURE); +} + +BRESULT fdd_formating(const UINT8 *ID) { + + sysmng_fddaccess(fdc.us); + if (fddfile[fdc.us].type == DISKTYPE_D88) { + return(fdd_formating_d88(ID)); + } + return(FAILURE); +} + +BOOL fdd_isformating(void) { + + if (fddfile[fdc.us].type == DISKTYPE_D88) { + return(fdd_isformating_d88()); + } + return(FALSE); +} + #endif \ No newline at end of file diff --git a/diskimage/fddfile.h b/diskimage/fddfile.h old mode 100755 new mode 100644 index 947cdc86..d7653322 --- a/diskimage/fddfile.h +++ b/diskimage/fddfile.h @@ -1,287 +1,287 @@ -#ifndef _FDDFILE_H_ -#define _FDDFILE_H_ - - -#ifdef SUPPORT_KAI_IMAGES - -#define MAX_FDDFILE 4 // ver0.31 - -#include "diskimage/fd/fdd_head_d88.h" -#include "diskimage/fd/fdd_head_dcp.h" // 追加(Kai1) -#include "diskimage/fd/fdd_head_nfd.h" // 追加(Kai1) -#include "diskimage/fd/fdd_head_vfdd.h" // 追加(Kai1) - -enum { - FDDFILE_MF = 0x80, - FDDFILE_FM = 0x20, - - FDDFILE_AM = 0x08, - FDDFILE_DDAM = 0x02, - - FDDFILE_NONE = 0x00, - FDDCHECK_FM = (FDDFILE_MF | FDDFILE_FM), - FDDCHECK_MFM = FDDFILE_MF, - FDDCHECK_DAM = FDDFILE_AM, - FDDCHECK_DDAM = (FDDFILE_AM | FDDFILE_DDAM), - - FDDWRITE_FM = 0x40, - FDDWRITE_DDAM = 0x04 -}; - -enum { - DISKTYPE_NOTREADY = 0, - DISKTYPE_BETA, - DISKTYPE_D88, - DISKTYPE_DCP, // 追加(Kai1) - DISKTYPE_MAHALITO, // 未実装 - DISKTYPE_NFD, // 追加(Kai1) - DISKTYPE_VFDD // 追加(Kai1) -}; - -enum { - DISKTYPE_2D = 0, - DISKTYPE_2DD, - DISKTYPE_2HD -}; - -typedef struct { - UINT32 headersize; - UINT8 tracks; - UINT8 sectors; - UINT8 n; - UINT8 disktype; - UINT8 rpm; -} _XDFINFO, *XDFINFO; - -typedef struct { - UINT fdtype_major; - UINT fdtype_minor; - UINT32 fd_size; - UINT32 ptr[D88_TRACKMAX]; - _D88HEAD head; -} _D88INFO, *D88INFO; - -// 追加(Kai1) -typedef struct { - _XDFINFO xdf; - UINT32 ptr[DCP_TRACKMAX]; - _DCPHEAD head; -} _DCPINFO, *DCPINFO, _BKDSKINFO, *BKDSKINFO; - -typedef struct { - _XDFINFO xdf; - UINT32 ptr[NFD_TRKMAX1][0xff]; - UINT32 tptr[NFD_TRKMAX1]; - UINT32 trksize[NFD_TRKMAX1]; - union { - NFD_FILE_HEAD r0; - NFD_FILE_HEAD1 r1; - } head; -} _NFDINFO, *NFDINFO; - -typedef struct { - _XDFINFO xdf; - SINT32 ptr[VFDD_TRKMAX][VFDD_SECMAX]; - _VFDD_HEAD head; - _VFDD_ID id[VFDD_TRKMAX][VFDD_SECMAX]; - _VFDD_SP sp_dmy; -} _VFDDINFO, *VFDDINFO; -// - -union fdinfo { - _XDFINFO xdf; - _D88INFO d88; - _DCPINFO dcp; // 追加(Kai1) - _BKDSKINFO bkdsk; // 追加(Kai1) - _NFDINFO nfd; // 追加(Kai1) - _VFDDINFO vfdd; // 追加(Kai1) -}; - -typedef struct { - OEMCHAR fname[MAX_PATH]; - UINT ftype; - int ro; - UINT8 type; - UINT8 num; - UINT8 protect; - union fdinfo inf; - UINT8 hash_sha1[20]; -} _FDDFILE, *FDDFILE; - -// 各種処理関数格納構造体(Kai1) -typedef struct { - BRESULT (*eject)(FDDFILE fdd); - - BRESULT (*diskaccess)(FDDFILE fdd); - BRESULT (*seek)(FDDFILE fdd); - BRESULT (*seeksector)(FDDFILE fdd); - BRESULT (*readdiag)(FDDFILE fdd); - BRESULT (*read)(FDDFILE fdd); - BRESULT (*write)(FDDFILE fdd); - BRESULT (*readid)(FDDFILE fdd); - BRESULT (*writeid)(FDDFILE fdd); - - BRESULT (*formatinit)(FDDFILE fdd); - BRESULT (*formating)(FDDFILE fdd, const UINT8 *ID); - BOOL (*isformating)(FDDFILE fdd); - BOOL fdcresult; -} _FDDFUNC, *FDDFUNC; -// - -#ifdef __cplusplus -extern "C" { -#endif - -extern _FDDFILE fddfile[MAX_FDDFILE]; -extern UINT8 fddlasterror; - -// 起動時に一回だけ初期化 -void fddfile_initialize(void); - -void fddfile_reset2dmode(void); - -OEMCHAR *fdd_diskname(REG8 drv); -OEMCHAR *fdd_getfileex(REG8 drv, UINT *ftype, int *ro); -BOOL fdd_diskready(REG8 drv); -BOOL fdd_diskprotect(REG8 drv); - -BRESULT fdd_set(REG8 drv, const OEMCHAR *fname, UINT ftype, int ro); -BRESULT fdd_eject(REG8 drv); - -// 未実装、未対応用ダミー関数群(Kai1) -BRESULT fdd_dummy_xxx(FDDFILE fdd); -BRESULT fdd_eject_xxx(FDDFILE fdd); -BRESULT fdd_formating_xxx(FDDFILE fdd, const UINT8 *ID); -BOOL fdd_isformating_xxx(FDDFILE fdd); -// -// ベタ系イメージ用共通処理関数群(Kai1) -BRESULT fdd_diskaccess_common(FDDFILE fdd); -BRESULT fdd_seek_common(FDDFILE fdd); -BRESULT fdd_seeksector_common(FDDFILE fdd); -BRESULT fdd_readid_common(FDDFILE fdd); -// - -BRESULT fdd_diskaccess(void); -BRESULT fdd_seek(void); -BRESULT fdd_seeksector(void); -BRESULT fdd_read(void); -BRESULT fdd_write(void); -BRESULT fdd_diagread(void); -BRESULT fdd_readid(void); -BRESULT fdd_writeid(void); - -BRESULT fdd_formatinit(void); -BRESULT fdd_formating(const UINT8 *ID); -BOOL fdd_isformating(void); - -BOOL fdd_fdcresult(void); // 追加(Kai1) - -#ifdef __cplusplus -} -#endif - -#else -#define MAX_FDDFILE 4 // ver0.31 - -#include "fdd/d88head.h" - -enum { - FDDFILE_MF = 0x80, - FDDFILE_FM = 0x20, - - FDDFILE_AM = 0x08, - FDDFILE_DDAM = 0x02, - - FDDFILE_NONE = 0x00, - FDDCHECK_FM = (FDDFILE_MF | FDDFILE_FM), - FDDCHECK_MFM = FDDFILE_MF, - FDDCHECK_DAM = FDDFILE_AM, - FDDCHECK_DDAM = (FDDFILE_AM | FDDFILE_DDAM), - - FDDWRITE_FM = 0x40, - FDDWRITE_DDAM = 0x04 -}; - -enum { - DISKTYPE_NOTREADY = 0, - DISKTYPE_BETA, - DISKTYPE_D88 -}; - -enum { - DISKTYPE_2D = 0, - DISKTYPE_2DD, - DISKTYPE_2HD -}; - -typedef struct { - UINT32 headersize; - UINT8 tracks; - UINT8 sectors; - UINT8 n; - UINT8 disktype; - UINT8 rpm; -} _XDFINFO, *XDFINFO; - -typedef struct { - UINT fdtype_major; - UINT fdtype_minor; - UINT32 fd_size; - UINT32 ptr[164]; - _D88HEAD head; -} _D88INFO, *D88INFO; - -typedef struct { - OEMCHAR fname[MAX_PATH]; - UINT ftype; - int ro; - UINT8 type; - UINT8 num; - UINT8 protect; - union { - _XDFINFO xdf; - _D88INFO d88; - } inf; -} _FDDFILE, *FDDFILE; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern _FDDFILE fddfile[MAX_FDDFILE]; -extern UINT8 fddlasterror; - -// 起動時に一回だけ初期化 -void fddfile_initialize(void); - -void fddfile_reset2dmode(void); - -OEMCHAR *fdd_diskname(REG8 drv); -OEMCHAR *fdd_getfileex(REG8 drv, UINT *ftype, int *ro); -BOOL fdd_diskready(REG8 drv); -BOOL fdd_diskprotect(REG8 drv); - -BRESULT fdd_set(REG8 drv, const OEMCHAR *fname, UINT ftype, int ro); -BRESULT fdd_eject(REG8 drv); - -BRESULT fdd_diskaccess(void); -BRESULT fdd_seek(void); -BRESULT fdd_seeksector(void); -BRESULT fdd_read(void); -BRESULT fdd_write(void); -BRESULT fdd_diagread(void); -BRESULT fdd_readid(void); -BRESULT fdd_writeid(void); - -BRESULT fdd_formatinit(void); -BRESULT fdd_formating(const UINT8 *ID); -BOOL fdd_isformating(void); - -#ifdef __cplusplus -} -#endif - -#endif - -#endif // _FDDFILE_H_ +#ifndef _FDDFILE_H_ +#define _FDDFILE_H_ + + +#ifdef SUPPORT_KAI_IMAGES + +#define MAX_FDDFILE 4 // ver0.31 + +#include "diskimage/fd/fdd_head_d88.h" +#include "diskimage/fd/fdd_head_dcp.h" // 追加(Kai1) +#include "diskimage/fd/fdd_head_nfd.h" // 追加(Kai1) +#include "diskimage/fd/fdd_head_vfdd.h" // 追加(Kai1) + +enum { + FDDFILE_MF = 0x80, + FDDFILE_FM = 0x20, + + FDDFILE_AM = 0x08, + FDDFILE_DDAM = 0x02, + + FDDFILE_NONE = 0x00, + FDDCHECK_FM = (FDDFILE_MF | FDDFILE_FM), + FDDCHECK_MFM = FDDFILE_MF, + FDDCHECK_DAM = FDDFILE_AM, + FDDCHECK_DDAM = (FDDFILE_AM | FDDFILE_DDAM), + + FDDWRITE_FM = 0x40, + FDDWRITE_DDAM = 0x04 +}; + +enum { + DISKTYPE_NOTREADY = 0, + DISKTYPE_BETA, + DISKTYPE_D88, + DISKTYPE_DCP, // 追加(Kai1) + DISKTYPE_MAHALITO, // 未実装 + DISKTYPE_NFD, // 追加(Kai1) + DISKTYPE_VFDD // 追加(Kai1) +}; + +enum { + DISKTYPE_2D = 0, + DISKTYPE_2DD, + DISKTYPE_2HD +}; + +typedef struct { + UINT32 headersize; + UINT8 tracks; + UINT8 sectors; + UINT8 n; + UINT8 disktype; + UINT8 rpm; +} _XDFINFO, *XDFINFO; + +typedef struct { + UINT fdtype_major; + UINT fdtype_minor; + UINT32 fd_size; + UINT32 ptr[D88_TRACKMAX]; + _D88HEAD head; +} _D88INFO, *D88INFO; + +// 追加(Kai1) +typedef struct { + _XDFINFO xdf; + UINT32 ptr[DCP_TRACKMAX]; + _DCPHEAD head; +} _DCPINFO, *DCPINFO, _BKDSKINFO, *BKDSKINFO; + +typedef struct { + _XDFINFO xdf; + UINT32 ptr[NFD_TRKMAX1][0xff]; + UINT32 tptr[NFD_TRKMAX1]; + UINT32 trksize[NFD_TRKMAX1]; + union { + NFD_FILE_HEAD r0; + NFD_FILE_HEAD1 r1; + } head; +} _NFDINFO, *NFDINFO; + +typedef struct { + _XDFINFO xdf; + SINT32 ptr[VFDD_TRKMAX][VFDD_SECMAX]; + _VFDD_HEAD head; + _VFDD_ID id[VFDD_TRKMAX][VFDD_SECMAX]; + _VFDD_SP sp_dmy; +} _VFDDINFO, *VFDDINFO; +// + +union fdinfo { + _XDFINFO xdf; + _D88INFO d88; + _DCPINFO dcp; // 追加(Kai1) + _BKDSKINFO bkdsk; // 追加(Kai1) + _NFDINFO nfd; // 追加(Kai1) + _VFDDINFO vfdd; // 追加(Kai1) +}; + +typedef struct { + OEMCHAR fname[MAX_PATH]; + UINT ftype; + int ro; + UINT8 type; + UINT8 num; + UINT8 protect; + union fdinfo inf; + UINT8 hash_sha1[20]; +} _FDDFILE, *FDDFILE; + +// 各種処理関数格納構造体(Kai1) +typedef struct { + BRESULT (*eject)(FDDFILE fdd); + + BRESULT (*diskaccess)(FDDFILE fdd); + BRESULT (*seek)(FDDFILE fdd); + BRESULT (*seeksector)(FDDFILE fdd); + BRESULT (*readdiag)(FDDFILE fdd); + BRESULT (*read)(FDDFILE fdd); + BRESULT (*write)(FDDFILE fdd); + BRESULT (*readid)(FDDFILE fdd); + BRESULT (*writeid)(FDDFILE fdd); + + BRESULT (*formatinit)(FDDFILE fdd); + BRESULT (*formating)(FDDFILE fdd, const UINT8 *ID); + BOOL (*isformating)(FDDFILE fdd); + BOOL fdcresult; +} _FDDFUNC, *FDDFUNC; +// + +#ifdef __cplusplus +extern "C" { +#endif + +extern _FDDFILE fddfile[MAX_FDDFILE]; +extern UINT8 fddlasterror; + +// 起動時に一回だけ初期化 +void fddfile_initialize(void); + +void fddfile_reset2dmode(void); + +OEMCHAR *fdd_diskname(REG8 drv); +OEMCHAR *fdd_getfileex(REG8 drv, UINT *ftype, int *ro); +BOOL fdd_diskready(REG8 drv); +BOOL fdd_diskprotect(REG8 drv); + +BRESULT fdd_set(REG8 drv, const OEMCHAR *fname, UINT ftype, int ro); +BRESULT fdd_eject(REG8 drv); + +// 未実装、未対応用ダミー関数群(Kai1) +BRESULT fdd_dummy_xxx(FDDFILE fdd); +BRESULT fdd_eject_xxx(FDDFILE fdd); +BRESULT fdd_formating_xxx(FDDFILE fdd, const UINT8 *ID); +BOOL fdd_isformating_xxx(FDDFILE fdd); +// +// ベタ系イメージ用共通処理関数群(Kai1) +BRESULT fdd_diskaccess_common(FDDFILE fdd); +BRESULT fdd_seek_common(FDDFILE fdd); +BRESULT fdd_seeksector_common(FDDFILE fdd); +BRESULT fdd_readid_common(FDDFILE fdd); +// + +BRESULT fdd_diskaccess(void); +BRESULT fdd_seek(void); +BRESULT fdd_seeksector(void); +BRESULT fdd_read(void); +BRESULT fdd_write(void); +BRESULT fdd_diagread(void); +BRESULT fdd_readid(void); +BRESULT fdd_writeid(void); + +BRESULT fdd_formatinit(void); +BRESULT fdd_formating(const UINT8 *ID); +BOOL fdd_isformating(void); + +BOOL fdd_fdcresult(void); // 追加(Kai1) + +#ifdef __cplusplus +} +#endif + +#else +#define MAX_FDDFILE 4 // ver0.31 + +#include "fdd/d88head.h" + +enum { + FDDFILE_MF = 0x80, + FDDFILE_FM = 0x20, + + FDDFILE_AM = 0x08, + FDDFILE_DDAM = 0x02, + + FDDFILE_NONE = 0x00, + FDDCHECK_FM = (FDDFILE_MF | FDDFILE_FM), + FDDCHECK_MFM = FDDFILE_MF, + FDDCHECK_DAM = FDDFILE_AM, + FDDCHECK_DDAM = (FDDFILE_AM | FDDFILE_DDAM), + + FDDWRITE_FM = 0x40, + FDDWRITE_DDAM = 0x04 +}; + +enum { + DISKTYPE_NOTREADY = 0, + DISKTYPE_BETA, + DISKTYPE_D88 +}; + +enum { + DISKTYPE_2D = 0, + DISKTYPE_2DD, + DISKTYPE_2HD +}; + +typedef struct { + UINT32 headersize; + UINT8 tracks; + UINT8 sectors; + UINT8 n; + UINT8 disktype; + UINT8 rpm; +} _XDFINFO, *XDFINFO; + +typedef struct { + UINT fdtype_major; + UINT fdtype_minor; + UINT32 fd_size; + UINT32 ptr[164]; + _D88HEAD head; +} _D88INFO, *D88INFO; + +typedef struct { + OEMCHAR fname[MAX_PATH]; + UINT ftype; + int ro; + UINT8 type; + UINT8 num; + UINT8 protect; + union { + _XDFINFO xdf; + _D88INFO d88; + } inf; +} _FDDFILE, *FDDFILE; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _FDDFILE fddfile[MAX_FDDFILE]; +extern UINT8 fddlasterror; + +// 起動時に一回だけ初期化 +void fddfile_initialize(void); + +void fddfile_reset2dmode(void); + +OEMCHAR *fdd_diskname(REG8 drv); +OEMCHAR *fdd_getfileex(REG8 drv, UINT *ftype, int *ro); +BOOL fdd_diskready(REG8 drv); +BOOL fdd_diskprotect(REG8 drv); + +BRESULT fdd_set(REG8 drv, const OEMCHAR *fname, UINT ftype, int ro); +BRESULT fdd_eject(REG8 drv); + +BRESULT fdd_diskaccess(void); +BRESULT fdd_seek(void); +BRESULT fdd_seeksector(void); +BRESULT fdd_read(void); +BRESULT fdd_write(void); +BRESULT fdd_diagread(void); +BRESULT fdd_readid(void); +BRESULT fdd_writeid(void); + +BRESULT fdd_formatinit(void); +BRESULT fdd_formating(const UINT8 *ID); +BOOL fdd_isformating(void); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif // _FDDFILE_H_ diff --git a/diskimage/img_common.h b/diskimage/img_common.h old mode 100755 new mode 100644 index 5aa2fca7..1138a2aa --- a/diskimage/img_common.h +++ b/diskimage/img_common.h @@ -1,5 +1,5 @@ -enum { - FTYPE_DCP = FTYPEID('.','D','C','P'), - FTYPE_NFD = FTYPEID('.','N','F','D'), - FTYPE_VFDD = FTYPEID('.','F','D','D') -}; +enum { + FTYPE_DCP = FTYPEID('.','D','C','P'), + FTYPE_NFD = FTYPEID('.','N','F','D'), + FTYPE_VFDD = FTYPEID('.','F','D','D') +}; diff --git a/diskimage/img_strres.c b/diskimage/img_strres.c old mode 100755 new mode 100644 index 17f50a81..742e2af1 --- a/diskimage/img_strres.c +++ b/diskimage/img_strres.c @@ -1,18 +1,18 @@ -#include -#include "diskimage/img_strres.h" - -#ifdef SUPPORT_KAI_IMAGES - -const OEMCHAR str_dcp[] = OEMTEXT("dcp"); -const OEMCHAR str_dcu[] = OEMTEXT("dcu"); -const OEMCHAR str_nfd[] = OEMTEXT("nfd"); -const OEMCHAR str_vfdd[] = OEMTEXT("fdd"); - -const OEMCHAR str_cue[] = OEMTEXT("cue"); // CUEシート -const OEMCHAR str_ccd[] = OEMTEXT("ccd"); // CloneCDに対応してみる -const OEMCHAR str_cdm[] = OEMTEXT("cdm"); // CD Manipulatorに対応してみる -const OEMCHAR str_mds[] = OEMTEXT("mds"); // Media Descriptor(Alcohol 52%等)に対応してみる -const OEMCHAR str_nrg[] = OEMTEXT("nrg"); // Neroに対応してみる -const OEMCHAR str_iso[] = OEMTEXT("iso"); - -#endif +#include +#include "diskimage/img_strres.h" + +#ifdef SUPPORT_KAI_IMAGES + +const OEMCHAR str_dcp[] = OEMTEXT("dcp"); +const OEMCHAR str_dcu[] = OEMTEXT("dcu"); +const OEMCHAR str_nfd[] = OEMTEXT("nfd"); +const OEMCHAR str_vfdd[] = OEMTEXT("fdd"); + +const OEMCHAR str_cue[] = OEMTEXT("cue"); // CUEシート +const OEMCHAR str_ccd[] = OEMTEXT("ccd"); // CloneCDに対応してみる +const OEMCHAR str_cdm[] = OEMTEXT("cdm"); // CD Manipulatorに対応してみる +const OEMCHAR str_mds[] = OEMTEXT("mds"); // Media Descriptor(Alcohol 52%等)に対応してみる +const OEMCHAR str_nrg[] = OEMTEXT("nrg"); // Neroに対応してみる +const OEMCHAR str_iso[] = OEMTEXT("iso"); + +#endif diff --git a/diskimage/img_strres.h b/diskimage/img_strres.h old mode 100755 new mode 100644 index 7ad0a33f..046c9092 --- a/diskimage/img_strres.h +++ b/diskimage/img_strres.h @@ -1,19 +1,19 @@ -#ifdef __cplusplus -extern "C" { -#endif - -extern const OEMCHAR str_dcp[]; -extern const OEMCHAR str_dcu[]; -extern const OEMCHAR str_nfd[]; -extern const OEMCHAR str_vfdd[]; - -extern const OEMCHAR str_cue[]; -extern const OEMCHAR str_ccd[]; -extern const OEMCHAR str_cdm[]; -extern const OEMCHAR str_mds[]; -extern const OEMCHAR str_nrg[]; -extern const OEMCHAR str_iso[]; - -#ifdef __cplusplus -} -#endif +#ifdef __cplusplus +extern "C" { +#endif + +extern const OEMCHAR str_dcp[]; +extern const OEMCHAR str_dcu[]; +extern const OEMCHAR str_nfd[]; +extern const OEMCHAR str_vfdd[]; + +extern const OEMCHAR str_cue[]; +extern const OEMCHAR str_ccd[]; +extern const OEMCHAR str_cdm[]; +extern const OEMCHAR str_mds[]; +extern const OEMCHAR str_nrg[]; +extern const OEMCHAR str_iso[]; + +#ifdef __cplusplus +} +#endif diff --git a/diskimage/win9x/img_dosio.c b/diskimage/win9x/img_dosio.c old mode 100755 new mode 100644 index 913f425f..558bb2ac --- a/diskimage/win9x/img_dosio.c +++ b/diskimage/win9x/img_dosio.c @@ -1,28 +1,28 @@ -#include -#include "img_dosio.h" - -INT64 DOSIOCALL file_seeki64(FILEH handle, INT64 pointer, int method) { - - LARGE_INTEGER li; - - li.QuadPart = pointer; - - li.LowPart = SetFilePointer(handle, li.LowPart, &li.HighPart, method); - - if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) { - li.QuadPart = -1; - } - - return(li.QuadPart); -} - -INT64 DOSIOCALL file_getsizei64(FILEH handle) { - - LARGE_INTEGER li; - - if (GetFileSizeEx(handle, &li) == 0) { - li.QuadPart = -1; - } - - return(li.QuadPart); -} +#include +#include "img_dosio.h" + +INT64 DOSIOCALL file_seeki64(FILEH handle, INT64 pointer, int method) { + + LARGE_INTEGER li; + + li.QuadPart = pointer; + + li.LowPart = SetFilePointer(handle, li.LowPart, &li.HighPart, method); + + if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) { + li.QuadPart = -1; + } + + return(li.QuadPart); +} + +INT64 DOSIOCALL file_getsizei64(FILEH handle) { + + LARGE_INTEGER li; + + if (GetFileSizeEx(handle, &li) == 0) { + li.QuadPart = -1; + } + + return(li.QuadPart); +} diff --git a/diskimage/win9x/img_dosio.h b/diskimage/win9x/img_dosio.h old mode 100755 new mode 100644 index 8deef9dd..c8811d95 --- a/diskimage/win9x/img_dosio.h +++ b/diskimage/win9x/img_dosio.h @@ -1,18 +1,18 @@ -//#define DOSIOCALL __stdcall -// -//#define FILEH HANDLE -//#define FILEH_INVALID (INVALID_HANDLE_VALUE) -// -//#define FLISTH HANDLE -//#define FLISTH_INVALID (INVALID_HANDLE_VALUE) -// -//#ifdef __cplusplus -//extern "C" { -//#endif -// -//INT64 DOSIOCALL file_seeki64(FILEH handle, INT64 pointer, int method); -//INT64 DOSIOCALL file_getsizei64(FILEH handle); -// -//#ifdef __cplusplus -//} -//#endif +//#define DOSIOCALL __stdcall +// +//#define FILEH HANDLE +//#define FILEH_INVALID (INVALID_HANDLE_VALUE) +// +//#define FLISTH HANDLE +//#define FLISTH_INVALID (INVALID_HANDLE_VALUE) +// +//#ifdef __cplusplus +//extern "C" { +//#endif +// +//INT64 DOSIOCALL file_seeki64(FILEH handle, INT64 pointer, int method); +//INT64 DOSIOCALL file_getsizei64(FILEH handle); +// +//#ifdef __cplusplus +//} +//#endif diff --git a/embed/menu/dlgabout.c b/embed/menu/dlgabout.c old mode 100755 new mode 100644 index 4fe9c72c..32d01c84 --- a/embed/menu/dlgabout.c +++ b/embed/menu/dlgabout.c @@ -1,79 +1,79 @@ -#include -#include -#include -#include -#include -#include -#include -#include "sysmenu.res" -#include - - -enum { - DID_ICON = DID_USER, - DID_VER, - DID_VER2 -}; - -#if defined(NP2_SIZE_QVGA) -static const MENUPRM res_about[] = { - {DLGTYPE_ICON, DID_ICON, 0, - (void *)MICON_NP2, 7, 7, 24, 24}, - {DLGTYPE_LTEXT, DID_VER, 0, - NULL, 40, 7, 128, 11}, - {DLGTYPE_LTEXT, DID_VER2, 0, - NULL, 40, 14, 128, 11}, - {DLGTYPE_BUTTON, DID_OK, MENU_TABSTOP, - mstr_ok, 176, 8, 48, 15}}; -#else -static const MENUPRM res_about[] = { - {DLGTYPE_ICON, DID_ICON, 0, - (void *)MICON_NP2, 14, 12, 32, 32}, - {DLGTYPE_LTEXT, DID_VER, 0, - NULL, 64, 12, 180, 13}, - {DLGTYPE_LTEXT, DID_VER2, 0, - NULL, 64, 24, 180, 13}, - {DLGTYPE_BUTTON, DID_OK, MENU_TABSTOP, - mstr_ok, 258, 12, 70, 21}}; -#endif - - -// ---- - -static void dlginit(void) { - - OEMCHAR work[128]; - OEMCHAR work2[128]; - - menudlg_appends(res_about, NELEMENTS(res_about)); - milstr_ncpy(work, str_np2, NELEMENTS(work)); - milstr_ncat(work, str_space, NELEMENTS(work)); - milstr_ncat(work, NP2KAI_GIT_TAG, NELEMENTS(work)); - milstr_ncpy(work2, NP2KAI_GIT_HASH, NELEMENTS(work2)); - menudlg_settext(DID_VER, work); - menudlg_settext(DID_VER2, work2); -} - -int dlgabout_cmd(int msg, MENUID id, long param) { - - switch(msg) { - case DLGMSG_CREATE: - dlginit(); - break; - - case DLGMSG_COMMAND: - switch(id) { - case DID_OK: - menubase_close(); - break; - } - break; - - case DLGMSG_CLOSE: - menubase_close(); - break; - } - (void)param; - return(0); -} - +#include +#include +#include +#include +#include +#include +#include +#include "sysmenu.res" +#include + + +enum { + DID_ICON = DID_USER, + DID_VER, + DID_VER2 +}; + +#if defined(NP2_SIZE_QVGA) +static const MENUPRM res_about[] = { + {DLGTYPE_ICON, DID_ICON, 0, + (void *)MICON_NP2, 7, 7, 24, 24}, + {DLGTYPE_LTEXT, DID_VER, 0, + NULL, 40, 7, 128, 11}, + {DLGTYPE_LTEXT, DID_VER2, 0, + NULL, 40, 14, 128, 11}, + {DLGTYPE_BUTTON, DID_OK, MENU_TABSTOP, + mstr_ok, 176, 8, 48, 15}}; +#else +static const MENUPRM res_about[] = { + {DLGTYPE_ICON, DID_ICON, 0, + (void *)MICON_NP2, 14, 12, 32, 32}, + {DLGTYPE_LTEXT, DID_VER, 0, + NULL, 64, 12, 180, 13}, + {DLGTYPE_LTEXT, DID_VER2, 0, + NULL, 64, 24, 180, 13}, + {DLGTYPE_BUTTON, DID_OK, MENU_TABSTOP, + mstr_ok, 258, 12, 70, 21}}; +#endif + + +// ---- + +static void dlginit(void) { + + OEMCHAR work[128]; + OEMCHAR work2[128]; + + menudlg_appends(res_about, NELEMENTS(res_about)); + milstr_ncpy(work, str_np2, NELEMENTS(work)); + milstr_ncat(work, str_space, NELEMENTS(work)); + milstr_ncat(work, NP2KAI_GIT_TAG, NELEMENTS(work)); + milstr_ncpy(work2, NP2KAI_GIT_HASH, NELEMENTS(work2)); + menudlg_settext(DID_VER, work); + menudlg_settext(DID_VER2, work2); +} + +int dlgabout_cmd(int msg, MENUID id, long param) { + + switch(msg) { + case DLGMSG_CREATE: + dlginit(); + break; + + case DLGMSG_COMMAND: + switch(id) { + case DID_OK: + menubase_close(); + break; + } + break; + + case DLGMSG_CLOSE: + menubase_close(); + break; + } + (void)param; + return(0); +} + diff --git a/embed/menu/dlgabout.h b/embed/menu/dlgabout.h old mode 100755 new mode 100644 index 4e733282..e86ad3e6 --- a/embed/menu/dlgabout.h +++ b/embed/menu/dlgabout.h @@ -1,24 +1,24 @@ - -#if defined(NP2_SIZE_QVGA) -enum { - DLGABOUT_WIDTH = 232, - DLGABOUT_HEIGHT = 40 -}; -#else -enum { - DLGABOUT_WIDTH = 342, - DLGABOUT_HEIGHT = 58 -}; -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -int dlgabout_cmd(int msg, MENUID id, long param); - -#ifdef __cplusplus -} -#endif - + +#if defined(NP2_SIZE_QVGA) +enum { + DLGABOUT_WIDTH = 232, + DLGABOUT_HEIGHT = 40 +}; +#else +enum { + DLGABOUT_WIDTH = 342, + DLGABOUT_HEIGHT = 58 +}; +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +int dlgabout_cmd(int msg, MENUID id, long param); + +#ifdef __cplusplus +} +#endif + diff --git a/embed/menu/dlgcfg.h b/embed/menu/dlgcfg.h old mode 100755 new mode 100644 index 2164f4ba..72f80d5b --- a/embed/menu/dlgcfg.h +++ b/embed/menu/dlgcfg.h @@ -1,24 +1,24 @@ - -#if defined(NP2_SIZE_QVGA) -enum { - DLGCFG_WIDTH = 254, - DLGCFG_HEIGHT = 180 -}; -#else -enum { - DLGCFG_WIDTH = 303, - DLGCFG_HEIGHT = 214 -}; -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -int dlgcfg_cmd(int msg, MENUID id, long param); - -#ifdef __cplusplus -} -#endif - + +#if defined(NP2_SIZE_QVGA) +enum { + DLGCFG_WIDTH = 254, + DLGCFG_HEIGHT = 180 +}; +#else +enum { + DLGCFG_WIDTH = 303, + DLGCFG_HEIGHT = 214 +}; +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +int dlgcfg_cmd(int msg, MENUID id, long param); + +#ifdef __cplusplus +} +#endif + diff --git a/embed/menu/dlgscr.c b/embed/menu/dlgscr.c old mode 100755 new mode 100644 index b7d0e497..d5427ddf --- a/embed/menu/dlgscr.c +++ b/embed/menu/dlgscr.c @@ -1,426 +1,426 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sysmenu.res" -#include - - -enum { - DID_TAB = DID_USER, - DID_LCD, - DID_LCDX, - DID_SKIPLINE, - DID_SKIPLIGHT, - DID_LIGHTSTR, - DID_GDC7220, - DID_GDC72020, - DID_GRCGNON, - DID_GRCG, - DID_GRCG2, - DID_EGC, - DID_PC980124, - DID_TRAMWAIT, - DID_TRAMSTR, - DID_VRAMWAIT, - DID_VRAMSTR, - DID_GRCGWAIT, - DID_GRCGSTR, - DID_REALPAL, - DID_REALPALSTR -}; - -static const OEMCHAR str_video[] = OEMTEXT("Video"); -static const OEMCHAR str_lcd[] = OEMTEXT("Liquid Crystal Display"); -static const OEMCHAR str_lcdx[] = OEMTEXT("Reverse"); -static const OEMCHAR str_skipline[] = OEMTEXT("Use skipline revisions"); -static const OEMCHAR str_skiplght[] = OEMTEXT("Ratio"); - -static const OEMCHAR str_chip[] = OEMTEXT("Chip"); -static const OEMCHAR str_gdc[] = OEMTEXT("GDC"); -static const OEMCHAR str_gdc0[] = OEMTEXT("uPD7220"); -static const OEMCHAR str_gdc1[] = OEMTEXT("uPD72020"); -static const OEMCHAR str_grcg[] = OEMTEXT("Graphic Charger"); -static const OEMCHAR str_grcg0[] = OEMTEXT("None"); -static const OEMCHAR str_grcg1[] = OEMTEXT("GRCG"); -static const OEMCHAR str_grcg2[] = OEMTEXT("GRCG+"); -static const OEMCHAR str_grcg3[] = OEMTEXT("EGC"); -static const OEMCHAR str_pc980124[] = OEMTEXT("Enable 16color (PC-9801-24)"); - -static const OEMCHAR str_timing[] = OEMTEXT("Timing"); -static const OEMCHAR str_tram[] = OEMTEXT("T-RAM"); -static const OEMCHAR str_vram[] = OEMTEXT("V-RAM"); -static const OEMCHAR str_clock[] = OEMTEXT("clock"); -static const OEMCHAR str_realpal[] = OEMTEXT("RealPalettes Adjust"); - - -#if defined(NP2_SIZE_QVGA) -static const MENUPRM res_scr0[] = { - {DLGTYPE_TABLIST, DID_TAB, 0, - NULL, 5, 3, 270, 144}, - {DLGTYPE_BUTTON, DID_OK, MENU_TABSTOP, - mstr_ok, 152, 150, 58, 15}, - {DLGTYPE_BUTTON, DID_CANCEL, MENU_TABSTOP, - mstr_cancel, 214, 150, 58, 15}}; - -static const MENUPRM res_scr1[] = { - {DLGTYPE_CHECK, DID_LCD, MENU_TABSTOP, - str_lcd, 18, 28, 240, 11}, - {DLGTYPE_CHECK, DID_LCDX, MENU_TABSTOP, - str_lcdx, 32, 43, 226, 11}, - {DLGTYPE_CHECK, DID_SKIPLINE, MENU_GRAY | MENU_TABSTOP, - str_skipline, 18, 62, 240, 11}, - {DLGTYPE_LTEXT, DID_STATIC, MENU_GRAY, - str_skiplght, 32, 77, 32, 11}, - {DLGTYPE_SLIDER, DID_SKIPLIGHT, MENU_GRAY | - MSS_BOTH | MENU_TABSTOP, - (void *)SLIDERPOS(0, 255), 66, 77, 112, 11}, - {DLGTYPE_RTEXT, DID_LIGHTSTR, MENU_GRAY, - NULL, 186, 77, 20, 11}}; - -static const MENUPRM res_scr2[] = { - {DLGTYPE_FRAME, DID_STATIC, 0, - str_gdc, 18, 26, 153, 32}, - {DLGTYPE_RADIO, DID_GDC7220, MENU_TABSTOP, - str_gdc0, 32, 40, 64, 11}, - {DLGTYPE_RADIO, DID_GDC72020, 0, - str_gdc1, 96, 40, 64, 11}, - {DLGTYPE_FRAME, DID_STATIC, 0, - str_grcg, 18, 64, 196, 32}, - {DLGTYPE_RADIO, DID_GRCGNON, MENU_TABSTOP, - str_grcg0, 32, 78, 44, 11}, - {DLGTYPE_RADIO, DID_GRCG, 0, - str_grcg1, 76, 78, 44, 11}, - {DLGTYPE_RADIO, DID_GRCG2, 0, - str_grcg2, 120, 78, 48, 11}, - {DLGTYPE_RADIO, DID_EGC, 0, - str_grcg3, 168, 78, 40, 11}, - {DLGTYPE_CHECK, DID_PC980124, MENU_TABSTOP, - str_pc980124, 28, 104, 224, 11}}; - -static const MENUPRM res_scr3[] = { - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_tram, 18, 28, 42, 11}, - {DLGTYPE_SLIDER, DID_TRAMWAIT, MSS_BOTH | MENU_TABSTOP, - (void *)SLIDERPOS(0, 48), 60, 28, 96, 11}, - {DLGTYPE_RTEXT, DID_TRAMSTR, 0, - NULL, 168, 28, 22, 11}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_clock, 192, 28, 32, 11}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_vram, 18, 46, 42, 11}, - {DLGTYPE_SLIDER, DID_VRAMWAIT, MSS_BOTH | MENU_TABSTOP, - (void *)SLIDERPOS(0, 48), 60, 46, 96, 11}, - {DLGTYPE_RTEXT, DID_VRAMSTR, 0, - NULL, 168, 46, 22, 11}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_clock, 192, 46, 32, 11}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_grcg1, 18, 64, 42, 11}, - {DLGTYPE_SLIDER, DID_GRCGWAIT, MSS_BOTH | MENU_TABSTOP, - (void *)SLIDERPOS(0, 48), 60, 64, 96, 11}, - {DLGTYPE_RTEXT, DID_GRCGSTR, 0, - NULL, 168, 64, 22, 11}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_clock, 192, 64, 32, 11}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_realpal, 18, 84, 192, 11}, - {DLGTYPE_SLIDER, DID_REALPAL, MSS_BOTH | MENU_TABSTOP, - (void *)SLIDERPOS(0, 64), 60, 98, 96, 11}, - {DLGTYPE_RTEXT, DID_REALPALSTR, 0, - NULL, 168, 98, 22, 11}}; -#else -static const MENUPRM res_scr0[] = { - {DLGTYPE_TABLIST, DID_TAB, 0, - NULL, 7, 6, 379, 196}, - {DLGTYPE_BUTTON, DID_OK, MENU_TABSTOP, - mstr_ok, 204, 208, 88, 21}, - {DLGTYPE_BUTTON, DID_CANCEL, MENU_TABSTOP, - mstr_cancel, 299, 208, 88, 21}}; - -static const MENUPRM res_scr1[] = { - {DLGTYPE_CHECK, DID_LCD, MENU_TABSTOP, - str_lcd, 25, 40, 358, 13}, - {DLGTYPE_CHECK, DID_LCDX, MENU_TABSTOP, - str_lcdx, 46, 64, 337, 13}, - {DLGTYPE_CHECK, DID_SKIPLINE, MENU_TABSTOP, - str_skipline, 25, 88, 358, 13}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_skiplght, 46, 109, 40, 13}, - {DLGTYPE_SLIDER, DID_SKIPLIGHT, MSS_BOTH | MENU_TABSTOP, - (void *)SLIDERPOS(0, 255), 92, 110, 160, 11}, - {DLGTYPE_RTEXT, DID_LIGHTSTR, 0, - NULL, 264, 109, 26, 13}}; - -static const MENUPRM res_scr2[] = { - {DLGTYPE_FRAME, DID_STATIC, 0, - str_gdc, 25, 39, 214, 42}, - {DLGTYPE_RADIO, DID_GDC7220, MENU_TABSTOP, - str_gdc0, 47, 58, 90, 13}, - {DLGTYPE_RADIO, DID_GDC72020, 0, - str_gdc1, 138, 58, 90, 13}, - {DLGTYPE_FRAME, DID_STATIC, 0, - str_grcg, 25, 90, 273, 42}, - {DLGTYPE_RADIO, DID_GRCGNON, MENU_TABSTOP, - str_grcg0, 47, 109, 60, 13}, - {DLGTYPE_RADIO, DID_GRCG, 0, - str_grcg1, 107, 109, 60, 13}, - {DLGTYPE_RADIO, DID_GRCG2, 0, - str_grcg2, 167, 109, 69, 13}, - {DLGTYPE_RADIO, DID_EGC, 0, - str_grcg3, 236, 109, 60, 13}, - {DLGTYPE_CHECK, DID_PC980124, MENU_TABSTOP, - str_pc980124, 39, 148, 224, 13}}; - -static const MENUPRM res_scr3[] = { - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_tram, 24, 41, 60, 13}, - {DLGTYPE_SLIDER, DID_TRAMWAIT, MSS_BOTH | MENU_TABSTOP, - (void *)SLIDERPOS(0, 48), 86, 42, 130, 11}, - {DLGTYPE_RTEXT, DID_TRAMSTR, 0, - NULL, 234, 41, 28, 13}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_clock, 268, 41, 48, 13}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_vram, 24, 65, 60, 13}, - {DLGTYPE_SLIDER, DID_VRAMWAIT, MSS_BOTH | MENU_TABSTOP, - (void *)SLIDERPOS(0, 48), 86, 66, 130, 11}, - {DLGTYPE_RTEXT, DID_VRAMSTR, 0, - NULL, 234, 65, 28, 13}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_clock, 268, 65, 48, 13}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_grcg1, 24, 89, 60, 13}, - {DLGTYPE_SLIDER, DID_GRCGWAIT, MSS_BOTH | MENU_TABSTOP, - (void *)SLIDERPOS(0, 48), 86, 90, 130, 11}, - {DLGTYPE_RTEXT, DID_GRCGSTR, 0, - NULL, 234, 89, 28, 13}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_clock, 268, 89, 48, 13}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_realpal, 24, 116, 224, 13}, - {DLGTYPE_SLIDER, DID_REALPAL, MSS_BOTH | MENU_TABSTOP, - (void *)SLIDERPOS(0, 64), 86, 137, 130, 11}, - {DLGTYPE_RTEXT, DID_REALPALSTR, 0, - NULL, 234, 136, 28, 13}}; -#endif - -typedef struct { -const OEMCHAR *tab; -const MENUPRM *prm; - UINT count; -} TABLISTS; - -static const MENUID gdcchip[4] = {DID_GRCGNON, DID_GRCG, DID_GRCG2, DID_EGC}; - -static const TABLISTS tablist[] = { - {str_video, res_scr1, NELEMENTS(res_scr1)}, - {str_chip, res_scr2, NELEMENTS(res_scr2)}, - {str_timing,res_scr3, NELEMENTS(res_scr3)}, -}; - -static void setpage(UINT page) { - - UINT i; - - for (i=0; itab); - menudlg_appends(tl->prm, tl->count); - } - - menudlg_setval(DID_LCD, np2cfg.LCD_MODE & 1); - menudlg_setenable(DID_LCDX, np2cfg.LCD_MODE & 1); - menudlg_setval(DID_LCDX, np2cfg.LCD_MODE & 2); - menudlg_setval(DID_SKIPLINE, np2cfg.skipline); - menudlg_setval(DID_SKIPLIGHT, np2cfg.skiplight); - setintstr(DID_LIGHTSTR, np2cfg.skiplight); - - if (!np2cfg.uPD72020) { - menudlg_setval(DID_GDC7220, TRUE); - } - else { - menudlg_setval(DID_GDC72020, TRUE); - } - menudlg_setval(gdcchip[np2cfg.grcg & 3], TRUE); - menudlg_setval(DID_PC980124, np2cfg.color16); - - menudlg_setval(DID_TRAMWAIT, np2cfg.wait[0]); - setintstr(DID_TRAMSTR, np2cfg.wait[0]); - menudlg_setval(DID_VRAMWAIT, np2cfg.wait[2]); - setintstr(DID_VRAMSTR, np2cfg.wait[2]); - menudlg_setval(DID_GRCGWAIT, np2cfg.wait[4]); - setintstr(DID_GRCGSTR, np2cfg.wait[4]); - menudlg_setval(DID_REALPAL, np2cfg.realpal); - setintstr(DID_REALPALSTR, np2cfg.realpal - 32); - - menudlg_setval(DID_TAB, 0); - setpage(0); -} - -static void dlgupdate(void) { - - UINT update; - BOOL renewal; - UINT val; - UINT8 value[6]; - - update = 0; - renewal = FALSE; - val = menudlg_getval(DID_SKIPLINE); - if (np2cfg.skipline != (UINT8)val) { - np2cfg.skipline = (UINT8)val; - renewal = TRUE; - } - val = menudlg_getval(DID_SKIPLIGHT); - if (val > 255) { - val = 255; - } - if (np2cfg.skiplight != (UINT16)val) { - np2cfg.skiplight = (UINT16)val; - renewal = TRUE; - } - if (renewal) { - pal_makeskiptable(); - } - val = menudlg_getval(DID_LCD) + (menudlg_getval(DID_LCDX) << 1); - if (np2cfg.LCD_MODE != (UINT8)val) { - np2cfg.LCD_MODE = (UINT8)val; - pal_makelcdpal(); - renewal = TRUE; - } - if (renewal) { - scrndraw_redraw(); - update |= SYS_UPDATECFG; - } - - val = menudlg_getval(DID_GDC72020); - if (np2cfg.uPD72020 != (UINT8)val) { - np2cfg.uPD72020 = (UINT8)val; - update |= SYS_UPDATECFG; - gdc_restorekacmode(); - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - } - for (val=0; (val<3) && (!menudlg_getval(gdcchip[val])); val++) { } - if (np2cfg.grcg != (UINT8)val) { - np2cfg.grcg = (UINT8)val; - update |= SYS_UPDATECFG; - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - } - val = menudlg_getval(DID_PC980124); - if (np2cfg.color16 != (UINT8)val) { - np2cfg.color16 = (UINT8)val; - update |= SYS_UPDATECFG; - } - - ZeroMemory(value, sizeof(value)); - value[0] = (UINT8)menudlg_getval(DID_TRAMWAIT); - if (value[0]) { - value[1] = 1; - } - value[2] = (UINT8)menudlg_getval(DID_VRAMWAIT); - if (value[2]) { - value[3] = 1; - } - value[4] = (UINT8)menudlg_getval(DID_GRCGWAIT); - if (value[4]) { - value[5] = 1; - } - for (val=0; val<6; val++) { - if (np2cfg.wait[val] != value[val]) { - np2cfg.wait[val] = value[val]; - update |= SYS_UPDATECFG; - } - } - val = menudlg_getval(DID_REALPAL); - if (np2cfg.realpal != (UINT8)val) { - np2cfg.realpal = (UINT8)val; - update |= SYS_UPDATECFG; - } - sysmng_update(update); -} - -int dlgscr_cmd(int msg, MENUID id, long param) { - - switch(msg) { - case DLGMSG_CREATE: - dlginit(); - break; - - case DLGMSG_COMMAND: - switch(id) { - case DID_OK: - dlgupdate(); - menubase_close(); - break; - - case DID_CANCEL: - menubase_close(); - break; - - case DID_TAB: - setpage(menudlg_getval(DID_TAB)); - break; - - case DID_LCD: - menudlg_setenable(DID_LCDX, menudlg_getval(DID_LCD)); - break; - - case DID_SKIPLIGHT: - setintstr(DID_LIGHTSTR, menudlg_getval(DID_SKIPLIGHT)); - break; - - case DID_TRAMWAIT: - setintstr(DID_TRAMSTR, menudlg_getval(DID_TRAMWAIT)); - break; - - case DID_VRAMWAIT: - setintstr(DID_VRAMSTR, menudlg_getval(DID_VRAMWAIT)); - break; - - case DID_GRCGWAIT: - setintstr(DID_GRCGSTR, menudlg_getval(DID_GRCGWAIT)); - break; - - case DID_REALPAL: - setintstr(DID_REALPALSTR, - menudlg_getval(DID_REALPAL) - 32); - break; - } - break; - - case DLGMSG_CLOSE: - menubase_close(); - break; - } - (void)param; - return(0); -} - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sysmenu.res" +#include + + +enum { + DID_TAB = DID_USER, + DID_LCD, + DID_LCDX, + DID_SKIPLINE, + DID_SKIPLIGHT, + DID_LIGHTSTR, + DID_GDC7220, + DID_GDC72020, + DID_GRCGNON, + DID_GRCG, + DID_GRCG2, + DID_EGC, + DID_PC980124, + DID_TRAMWAIT, + DID_TRAMSTR, + DID_VRAMWAIT, + DID_VRAMSTR, + DID_GRCGWAIT, + DID_GRCGSTR, + DID_REALPAL, + DID_REALPALSTR +}; + +static const OEMCHAR str_video[] = OEMTEXT("Video"); +static const OEMCHAR str_lcd[] = OEMTEXT("Liquid Crystal Display"); +static const OEMCHAR str_lcdx[] = OEMTEXT("Reverse"); +static const OEMCHAR str_skipline[] = OEMTEXT("Use skipline revisions"); +static const OEMCHAR str_skiplght[] = OEMTEXT("Ratio"); + +static const OEMCHAR str_chip[] = OEMTEXT("Chip"); +static const OEMCHAR str_gdc[] = OEMTEXT("GDC"); +static const OEMCHAR str_gdc0[] = OEMTEXT("uPD7220"); +static const OEMCHAR str_gdc1[] = OEMTEXT("uPD72020"); +static const OEMCHAR str_grcg[] = OEMTEXT("Graphic Charger"); +static const OEMCHAR str_grcg0[] = OEMTEXT("None"); +static const OEMCHAR str_grcg1[] = OEMTEXT("GRCG"); +static const OEMCHAR str_grcg2[] = OEMTEXT("GRCG+"); +static const OEMCHAR str_grcg3[] = OEMTEXT("EGC"); +static const OEMCHAR str_pc980124[] = OEMTEXT("Enable 16color (PC-9801-24)"); + +static const OEMCHAR str_timing[] = OEMTEXT("Timing"); +static const OEMCHAR str_tram[] = OEMTEXT("T-RAM"); +static const OEMCHAR str_vram[] = OEMTEXT("V-RAM"); +static const OEMCHAR str_clock[] = OEMTEXT("clock"); +static const OEMCHAR str_realpal[] = OEMTEXT("RealPalettes Adjust"); + + +#if defined(NP2_SIZE_QVGA) +static const MENUPRM res_scr0[] = { + {DLGTYPE_TABLIST, DID_TAB, 0, + NULL, 5, 3, 270, 144}, + {DLGTYPE_BUTTON, DID_OK, MENU_TABSTOP, + mstr_ok, 152, 150, 58, 15}, + {DLGTYPE_BUTTON, DID_CANCEL, MENU_TABSTOP, + mstr_cancel, 214, 150, 58, 15}}; + +static const MENUPRM res_scr1[] = { + {DLGTYPE_CHECK, DID_LCD, MENU_TABSTOP, + str_lcd, 18, 28, 240, 11}, + {DLGTYPE_CHECK, DID_LCDX, MENU_TABSTOP, + str_lcdx, 32, 43, 226, 11}, + {DLGTYPE_CHECK, DID_SKIPLINE, MENU_GRAY | MENU_TABSTOP, + str_skipline, 18, 62, 240, 11}, + {DLGTYPE_LTEXT, DID_STATIC, MENU_GRAY, + str_skiplght, 32, 77, 32, 11}, + {DLGTYPE_SLIDER, DID_SKIPLIGHT, MENU_GRAY | + MSS_BOTH | MENU_TABSTOP, + (void *)SLIDERPOS(0, 255), 66, 77, 112, 11}, + {DLGTYPE_RTEXT, DID_LIGHTSTR, MENU_GRAY, + NULL, 186, 77, 20, 11}}; + +static const MENUPRM res_scr2[] = { + {DLGTYPE_FRAME, DID_STATIC, 0, + str_gdc, 18, 26, 153, 32}, + {DLGTYPE_RADIO, DID_GDC7220, MENU_TABSTOP, + str_gdc0, 32, 40, 64, 11}, + {DLGTYPE_RADIO, DID_GDC72020, 0, + str_gdc1, 96, 40, 64, 11}, + {DLGTYPE_FRAME, DID_STATIC, 0, + str_grcg, 18, 64, 196, 32}, + {DLGTYPE_RADIO, DID_GRCGNON, MENU_TABSTOP, + str_grcg0, 32, 78, 44, 11}, + {DLGTYPE_RADIO, DID_GRCG, 0, + str_grcg1, 76, 78, 44, 11}, + {DLGTYPE_RADIO, DID_GRCG2, 0, + str_grcg2, 120, 78, 48, 11}, + {DLGTYPE_RADIO, DID_EGC, 0, + str_grcg3, 168, 78, 40, 11}, + {DLGTYPE_CHECK, DID_PC980124, MENU_TABSTOP, + str_pc980124, 28, 104, 224, 11}}; + +static const MENUPRM res_scr3[] = { + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_tram, 18, 28, 42, 11}, + {DLGTYPE_SLIDER, DID_TRAMWAIT, MSS_BOTH | MENU_TABSTOP, + (void *)SLIDERPOS(0, 48), 60, 28, 96, 11}, + {DLGTYPE_RTEXT, DID_TRAMSTR, 0, + NULL, 168, 28, 22, 11}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_clock, 192, 28, 32, 11}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_vram, 18, 46, 42, 11}, + {DLGTYPE_SLIDER, DID_VRAMWAIT, MSS_BOTH | MENU_TABSTOP, + (void *)SLIDERPOS(0, 48), 60, 46, 96, 11}, + {DLGTYPE_RTEXT, DID_VRAMSTR, 0, + NULL, 168, 46, 22, 11}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_clock, 192, 46, 32, 11}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_grcg1, 18, 64, 42, 11}, + {DLGTYPE_SLIDER, DID_GRCGWAIT, MSS_BOTH | MENU_TABSTOP, + (void *)SLIDERPOS(0, 48), 60, 64, 96, 11}, + {DLGTYPE_RTEXT, DID_GRCGSTR, 0, + NULL, 168, 64, 22, 11}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_clock, 192, 64, 32, 11}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_realpal, 18, 84, 192, 11}, + {DLGTYPE_SLIDER, DID_REALPAL, MSS_BOTH | MENU_TABSTOP, + (void *)SLIDERPOS(0, 64), 60, 98, 96, 11}, + {DLGTYPE_RTEXT, DID_REALPALSTR, 0, + NULL, 168, 98, 22, 11}}; +#else +static const MENUPRM res_scr0[] = { + {DLGTYPE_TABLIST, DID_TAB, 0, + NULL, 7, 6, 379, 196}, + {DLGTYPE_BUTTON, DID_OK, MENU_TABSTOP, + mstr_ok, 204, 208, 88, 21}, + {DLGTYPE_BUTTON, DID_CANCEL, MENU_TABSTOP, + mstr_cancel, 299, 208, 88, 21}}; + +static const MENUPRM res_scr1[] = { + {DLGTYPE_CHECK, DID_LCD, MENU_TABSTOP, + str_lcd, 25, 40, 358, 13}, + {DLGTYPE_CHECK, DID_LCDX, MENU_TABSTOP, + str_lcdx, 46, 64, 337, 13}, + {DLGTYPE_CHECK, DID_SKIPLINE, MENU_TABSTOP, + str_skipline, 25, 88, 358, 13}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_skiplght, 46, 109, 40, 13}, + {DLGTYPE_SLIDER, DID_SKIPLIGHT, MSS_BOTH | MENU_TABSTOP, + (void *)SLIDERPOS(0, 255), 92, 110, 160, 11}, + {DLGTYPE_RTEXT, DID_LIGHTSTR, 0, + NULL, 264, 109, 26, 13}}; + +static const MENUPRM res_scr2[] = { + {DLGTYPE_FRAME, DID_STATIC, 0, + str_gdc, 25, 39, 214, 42}, + {DLGTYPE_RADIO, DID_GDC7220, MENU_TABSTOP, + str_gdc0, 47, 58, 90, 13}, + {DLGTYPE_RADIO, DID_GDC72020, 0, + str_gdc1, 138, 58, 90, 13}, + {DLGTYPE_FRAME, DID_STATIC, 0, + str_grcg, 25, 90, 273, 42}, + {DLGTYPE_RADIO, DID_GRCGNON, MENU_TABSTOP, + str_grcg0, 47, 109, 60, 13}, + {DLGTYPE_RADIO, DID_GRCG, 0, + str_grcg1, 107, 109, 60, 13}, + {DLGTYPE_RADIO, DID_GRCG2, 0, + str_grcg2, 167, 109, 69, 13}, + {DLGTYPE_RADIO, DID_EGC, 0, + str_grcg3, 236, 109, 60, 13}, + {DLGTYPE_CHECK, DID_PC980124, MENU_TABSTOP, + str_pc980124, 39, 148, 224, 13}}; + +static const MENUPRM res_scr3[] = { + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_tram, 24, 41, 60, 13}, + {DLGTYPE_SLIDER, DID_TRAMWAIT, MSS_BOTH | MENU_TABSTOP, + (void *)SLIDERPOS(0, 48), 86, 42, 130, 11}, + {DLGTYPE_RTEXT, DID_TRAMSTR, 0, + NULL, 234, 41, 28, 13}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_clock, 268, 41, 48, 13}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_vram, 24, 65, 60, 13}, + {DLGTYPE_SLIDER, DID_VRAMWAIT, MSS_BOTH | MENU_TABSTOP, + (void *)SLIDERPOS(0, 48), 86, 66, 130, 11}, + {DLGTYPE_RTEXT, DID_VRAMSTR, 0, + NULL, 234, 65, 28, 13}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_clock, 268, 65, 48, 13}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_grcg1, 24, 89, 60, 13}, + {DLGTYPE_SLIDER, DID_GRCGWAIT, MSS_BOTH | MENU_TABSTOP, + (void *)SLIDERPOS(0, 48), 86, 90, 130, 11}, + {DLGTYPE_RTEXT, DID_GRCGSTR, 0, + NULL, 234, 89, 28, 13}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_clock, 268, 89, 48, 13}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_realpal, 24, 116, 224, 13}, + {DLGTYPE_SLIDER, DID_REALPAL, MSS_BOTH | MENU_TABSTOP, + (void *)SLIDERPOS(0, 64), 86, 137, 130, 11}, + {DLGTYPE_RTEXT, DID_REALPALSTR, 0, + NULL, 234, 136, 28, 13}}; +#endif + +typedef struct { +const OEMCHAR *tab; +const MENUPRM *prm; + UINT count; +} TABLISTS; + +static const MENUID gdcchip[4] = {DID_GRCGNON, DID_GRCG, DID_GRCG2, DID_EGC}; + +static const TABLISTS tablist[] = { + {str_video, res_scr1, NELEMENTS(res_scr1)}, + {str_chip, res_scr2, NELEMENTS(res_scr2)}, + {str_timing,res_scr3, NELEMENTS(res_scr3)}, +}; + +static void setpage(UINT page) { + + UINT i; + + for (i=0; itab); + menudlg_appends(tl->prm, tl->count); + } + + menudlg_setval(DID_LCD, np2cfg.LCD_MODE & 1); + menudlg_setenable(DID_LCDX, np2cfg.LCD_MODE & 1); + menudlg_setval(DID_LCDX, np2cfg.LCD_MODE & 2); + menudlg_setval(DID_SKIPLINE, np2cfg.skipline); + menudlg_setval(DID_SKIPLIGHT, np2cfg.skiplight); + setintstr(DID_LIGHTSTR, np2cfg.skiplight); + + if (!np2cfg.uPD72020) { + menudlg_setval(DID_GDC7220, TRUE); + } + else { + menudlg_setval(DID_GDC72020, TRUE); + } + menudlg_setval(gdcchip[np2cfg.grcg & 3], TRUE); + menudlg_setval(DID_PC980124, np2cfg.color16); + + menudlg_setval(DID_TRAMWAIT, np2cfg.wait[0]); + setintstr(DID_TRAMSTR, np2cfg.wait[0]); + menudlg_setval(DID_VRAMWAIT, np2cfg.wait[2]); + setintstr(DID_VRAMSTR, np2cfg.wait[2]); + menudlg_setval(DID_GRCGWAIT, np2cfg.wait[4]); + setintstr(DID_GRCGSTR, np2cfg.wait[4]); + menudlg_setval(DID_REALPAL, np2cfg.realpal); + setintstr(DID_REALPALSTR, np2cfg.realpal - 32); + + menudlg_setval(DID_TAB, 0); + setpage(0); +} + +static void dlgupdate(void) { + + UINT update; + BOOL renewal; + UINT val; + UINT8 value[6]; + + update = 0; + renewal = FALSE; + val = menudlg_getval(DID_SKIPLINE); + if (np2cfg.skipline != (UINT8)val) { + np2cfg.skipline = (UINT8)val; + renewal = TRUE; + } + val = menudlg_getval(DID_SKIPLIGHT); + if (val > 255) { + val = 255; + } + if (np2cfg.skiplight != (UINT16)val) { + np2cfg.skiplight = (UINT16)val; + renewal = TRUE; + } + if (renewal) { + pal_makeskiptable(); + } + val = menudlg_getval(DID_LCD) + (menudlg_getval(DID_LCDX) << 1); + if (np2cfg.LCD_MODE != (UINT8)val) { + np2cfg.LCD_MODE = (UINT8)val; + pal_makelcdpal(); + renewal = TRUE; + } + if (renewal) { + scrndraw_redraw(); + update |= SYS_UPDATECFG; + } + + val = menudlg_getval(DID_GDC72020); + if (np2cfg.uPD72020 != (UINT8)val) { + np2cfg.uPD72020 = (UINT8)val; + update |= SYS_UPDATECFG; + gdc_restorekacmode(); + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + } + for (val=0; (val<3) && (!menudlg_getval(gdcchip[val])); val++) { } + if (np2cfg.grcg != (UINT8)val) { + np2cfg.grcg = (UINT8)val; + update |= SYS_UPDATECFG; + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + } + val = menudlg_getval(DID_PC980124); + if (np2cfg.color16 != (UINT8)val) { + np2cfg.color16 = (UINT8)val; + update |= SYS_UPDATECFG; + } + + ZeroMemory(value, sizeof(value)); + value[0] = (UINT8)menudlg_getval(DID_TRAMWAIT); + if (value[0]) { + value[1] = 1; + } + value[2] = (UINT8)menudlg_getval(DID_VRAMWAIT); + if (value[2]) { + value[3] = 1; + } + value[4] = (UINT8)menudlg_getval(DID_GRCGWAIT); + if (value[4]) { + value[5] = 1; + } + for (val=0; val<6; val++) { + if (np2cfg.wait[val] != value[val]) { + np2cfg.wait[val] = value[val]; + update |= SYS_UPDATECFG; + } + } + val = menudlg_getval(DID_REALPAL); + if (np2cfg.realpal != (UINT8)val) { + np2cfg.realpal = (UINT8)val; + update |= SYS_UPDATECFG; + } + sysmng_update(update); +} + +int dlgscr_cmd(int msg, MENUID id, long param) { + + switch(msg) { + case DLGMSG_CREATE: + dlginit(); + break; + + case DLGMSG_COMMAND: + switch(id) { + case DID_OK: + dlgupdate(); + menubase_close(); + break; + + case DID_CANCEL: + menubase_close(); + break; + + case DID_TAB: + setpage(menudlg_getval(DID_TAB)); + break; + + case DID_LCD: + menudlg_setenable(DID_LCDX, menudlg_getval(DID_LCD)); + break; + + case DID_SKIPLIGHT: + setintstr(DID_LIGHTSTR, menudlg_getval(DID_SKIPLIGHT)); + break; + + case DID_TRAMWAIT: + setintstr(DID_TRAMSTR, menudlg_getval(DID_TRAMWAIT)); + break; + + case DID_VRAMWAIT: + setintstr(DID_VRAMSTR, menudlg_getval(DID_VRAMWAIT)); + break; + + case DID_GRCGWAIT: + setintstr(DID_GRCGSTR, menudlg_getval(DID_GRCGWAIT)); + break; + + case DID_REALPAL: + setintstr(DID_REALPALSTR, + menudlg_getval(DID_REALPAL) - 32); + break; + } + break; + + case DLGMSG_CLOSE: + menubase_close(); + break; + } + (void)param; + return(0); +} + diff --git a/embed/menu/dlgscr.h b/embed/menu/dlgscr.h old mode 100755 new mode 100644 index f97138ac..55c97af5 --- a/embed/menu/dlgscr.h +++ b/embed/menu/dlgscr.h @@ -1,23 +1,23 @@ - -#if defined(NP2_SIZE_QVGA) -enum { - DLGSCR_WIDTH = 280, - DLGSCR_HEIGHT = 166 -}; -#else -enum { - DLGSCR_WIDTH = 393, - DLGSCR_HEIGHT = 235 -}; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -int dlgscr_cmd(int msg, MENUID id, long param); - -#ifdef __cplusplus -} -#endif - + +#if defined(NP2_SIZE_QVGA) +enum { + DLGSCR_WIDTH = 280, + DLGSCR_HEIGHT = 166 +}; +#else +enum { + DLGSCR_WIDTH = 393, + DLGSCR_HEIGHT = 235 +}; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +int dlgscr_cmd(int msg, MENUID id, long param); + +#ifdef __cplusplus +} +#endif + diff --git a/embed/menu/dlgwab.c b/embed/menu/dlgwab.c old mode 100755 new mode 100644 index 96591f9f..6fe2298d --- a/embed/menu/dlgwab.c +++ b/embed/menu/dlgwab.c @@ -1,447 +1,447 @@ -#include - -#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sysmenu.res" -#include -#include -#include - -enum { - DID_TAB = DID_USER, - DID_WAB_ASW, - DID_WAB_MT, - DID_CLGD_EN, - DID_CLGD_TYPE, - DID_CLGD_TYPESTR, - DID_CLGD_FC -}; - -static const OEMCHAR str_wab[] = OEMTEXT("General"); -static const OEMCHAR str_wab_asw[] = OEMTEXT("Use Analog Switch IC (No relay sound)"); -static const OEMCHAR str_wab_mt[] = OEMTEXT("Multi Thread Mode"); - -static const OEMCHAR str_clgd[] = OEMTEXT("CL-GD54xx"); -static const OEMCHAR str_clgd_en[] = OEMTEXT("Enabled (restart)"); -static const OEMCHAR str_clgd_type[] = OEMTEXT("Type"); -static const OEMCHAR str_clgd_fc[] = OEMTEXT("Use Fake Hardware Cursor"); - -static const OEMCHAR *str_cl_gd54xx_type[] = { - OEMTEXT("PC-9821Bp,Bs,Be,Bf built-in"), - OEMTEXT("PC-9821Xe built-in"), - OEMTEXT("PC-9821Cb built-in"), - OEMTEXT("PC-9821Cf built-in"), - OEMTEXT("PC-9821Xe10,Xa7e,Xb10 built-in"), - OEMTEXT("PC-9821Cb2 built-in"), - OEMTEXT("PC-9821Cx2 built-in"), -#ifdef SUPPORT_PCI - OEMTEXT("PC-9821 PCI CL-GD5446 built-in"), -#endif - OEMTEXT("MELCO WAB-S"), - OEMTEXT("MELCO WSN-A2F"), - OEMTEXT("MELCO WSN-A4F"), - OEMTEXT("I-O DATA GA-98NBI/C"), - OEMTEXT("I-O DATA GA-98NBII"), - OEMTEXT("I-O DATA GA-98NBIV"), - OEMTEXT("PC-9801-96(PC-9801B3-E02)"), -#ifdef SUPPORT_PCI - OEMTEXT("Auto Select(Xe10, GA-98NBI/C), PCI"), - OEMTEXT("Auto Select(Xe10, GA-98NBII), PCI"), - OEMTEXT("Auto Select(Xe10, GA-98NBIV), PCI"), - OEMTEXT("Auto Select(Xe10, WAB-S), PCI"), - OEMTEXT("Auto Select(Xe10, WSN-A2F), PCI"), - OEMTEXT("Auto Select(Xe10, WSN-A4F), PCI"), -#endif - OEMTEXT("Auto Select(Xe10, WAB-S)"), - OEMTEXT("Auto Select(Xe10, WSN-A2F)"), - OEMTEXT("Auto Select(Xe10, WSN-A4F)"), -}; - -static const MENUPRM res_wab0[] = { - {DLGTYPE_TABLIST, DID_TAB, 0, - NULL, 7, 6, 379, 196}, - {DLGTYPE_BUTTON, DID_OK, MENU_TABSTOP, - mstr_ok, 204, 208, 88, 21}, - {DLGTYPE_BUTTON, DID_CANCEL, MENU_TABSTOP, - mstr_cancel, 299, 208, 88, 21}}; - -static const MENUPRM res_wab1[] = { - {DLGTYPE_CHECK, DID_WAB_ASW, MENU_TABSTOP, - str_wab_asw, 25, 40, 358, 13}, - {DLGTYPE_CHECK, DID_WAB_MT, MENU_TABSTOP, - str_wab_mt, 25, 64, 358, 13}}; - -static const MENUPRM res_wab2[] = { - {DLGTYPE_CHECK, DID_CLGD_EN, MENU_TABSTOP, - str_clgd_en, 25, 40, 358, 13}, - {DLGTYPE_LTEXT, DID_STATIC, 0, - str_clgd_type, 25, 64, 358, 13}, - {DLGTYPE_SLIDER, DID_CLGD_TYPE, MSS_BOTH | MENU_TABSTOP, - (void *)SLIDERPOS(0, 14), 86, 66, 130, 11}, - {DLGTYPE_RTEXT, DID_CLGD_TYPESTR, 0, - NULL, 86, 88, 250, 13}, - {DLGTYPE_CHECK, DID_CLGD_FC, MENU_TABSTOP, - str_clgd_fc, 25, 112, 358, 13}}; - -typedef struct { - const OEMCHAR *tab; - const MENUPRM *prm; - UINT count; -} TABLISTS; - -static const TABLISTS tablist[] = { - {str_wab, res_wab1, NELEMENTS(res_wab1)}, - {str_clgd, res_wab2, NELEMENTS(res_wab2)}, -}; - -static void setpage(UINT page) { - - UINT i; - - for (i=0; itab); - menudlg_appends(tl->prm, tl->count); - } - - menudlg_setval(DID_WAB_ASW, np2cfg.wabasw & 1); - menudlg_setval(DID_WAB_MT, np2wabcfg.multithread & 1); -menudlg_setenable(DID_WAB_MT, 0); - - menudlg_setval(DID_CLGD_EN, np2cfg.usegd5430 & 1); - menudlg_setval(DID_CLGD_TYPE, type); - menudlg_settext(DID_CLGD_TYPESTR, str_cl_gd54xx_type[type]); - menudlg_setval(DID_CLGD_FC, np2cfg.gd5430fakecur & 1); - - menudlg_setval(DID_TAB, 0); - setpage(0); -} - -static void dlgupdate(void) { - - UINT update; - BOOL renewal; - UINT val; - UINT type; - - update = 0; - renewal = FALSE; - val = menudlg_getval(DID_WAB_ASW); - if (np2cfg.wabasw != (UINT8)val) { - np2cfg.wabasw = (UINT8)val; - renewal = TRUE; - } - val = menudlg_getval(DID_WAB_MT); - if (np2wabcfg.multithread != (UINT8)val) { - np2wabcfg.multithread = (UINT8)val; - renewal = TRUE; - } - val = menudlg_getval(DID_CLGD_EN); - if (np2cfg.usegd5430 != (UINT8)val) { - np2cfg.usegd5430 = (UINT8)val; - renewal = TRUE; - } - val = menudlg_getval(DID_CLGD_TYPE); - if (val > 14) { - val = 14; - } - switch(val) { - case 0: - type = CIRRUS_98ID_Be; - break; - case 1: - type = CIRRUS_98ID_Xe; - break; - case 2: - type = CIRRUS_98ID_Cb; - break; - case 3: - type = CIRRUS_98ID_Cf; - break; - case 4: - type = CIRRUS_98ID_Xe10; - break; - case 5: - type = CIRRUS_98ID_Cb2; - break; - case 6: - type = CIRRUS_98ID_Cx2; - break; -#ifdef SUPPORT_PCI - case 7: - type = CIRRUS_98ID_PCI; - break; - case 8: - type = CIRRUS_98ID_WAB; - break; - case 9: - type = CIRRUS_98ID_WSN_A2F; - break; - case 10: - type = CIRRUS_98ID_WSN; - break; - case 11: - type = CIRRUS_98ID_GA98NBIC; - break; - case 12: - type = CIRRUS_98ID_GA98NBII; - break; - case 13: - type = CIRRUS_98ID_GA98NBIV; - break; - case 14: - type = CIRRUS_98ID_96; - break; - case 15: - type = CIRRUS_98ID_AUTO_XE_G1_PCI; - break; - case 16: - type = CIRRUS_98ID_AUTO_XE_G2_PCI; - break; - case 17: - type = CIRRUS_98ID_AUTO_XE_G4_PCI; - break; - case 18: - type = CIRRUS_98ID_AUTO_XE_WA_PCI; - break; - case 19: - type = CIRRUS_98ID_AUTO_XE_WS_PCI; - break; - case 20: - type = CIRRUS_98ID_AUTO_XE_W4_PCI; - break; - case 21: - type = CIRRUS_98ID_AUTO_XE10_WABS; - break; - case 22: - type = CIRRUS_98ID_AUTO_XE10_WSN2; - break; - case 23: - type = CIRRUS_98ID_AUTO_XE10_WSN4; - break; -#else - case 7: - type = CIRRUS_98ID_WAB; - break; - case 8: - type = CIRRUS_98ID_WSN_A2F; - break; - case 9: - type = CIRRUS_98ID_WSN; - break; - case 10: - type = CIRRUS_98ID_GA98NBIC; - break; - case 11: - type = CIRRUS_98ID_GA98NBII; - break; - case 12: - type = CIRRUS_98ID_GA98NBIV; - break; - case 13: - type = CIRRUS_98ID_96; - break; - case 14: - type = CIRRUS_98ID_AUTO_XE10_WABS; - break; - case 15: - type = CIRRUS_98ID_AUTO_XE10_WSN2; - break; - case 16: - type = CIRRUS_98ID_AUTO_XE10_WSN4; - break; -#endif - } - if (np2cfg.gd5430type != (UINT16)type) { - np2cfg.gd5430type = (UINT16)type; - renewal = TRUE; - } - val = menudlg_getval(DID_CLGD_FC); - if (np2cfg.gd5430fakecur != (UINT8)val) { - np2cfg.gd5430fakecur = (UINT8)val; - renewal = TRUE; - } - if (renewal) { - scrndraw_redraw(); - update |= SYS_UPDATECFG; - } - - sysmng_update(update); -} - -int dlgwab_cmd(int msg, MENUID id, long param) { - - switch(msg) { - case DLGMSG_CREATE: - dlginit(); - break; - - case DLGMSG_COMMAND: - switch(id) { - case DID_OK: - dlgupdate(); - menubase_close(); - break; - - case DID_CANCEL: - menubase_close(); - break; - - case DID_TAB: - setpage(menudlg_getval(DID_TAB)); - break; - - case DID_CLGD_TYPE: - menudlg_settext(DID_CLGD_TYPESTR, str_cl_gd54xx_type[menudlg_getval(DID_CLGD_TYPE)]); - break; - } - break; - - case DLGMSG_CLOSE: - menubase_close(); - break; - } - (void)param; - return(0); -} - -#endif +#include + +#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sysmenu.res" +#include +#include +#include + +enum { + DID_TAB = DID_USER, + DID_WAB_ASW, + DID_WAB_MT, + DID_CLGD_EN, + DID_CLGD_TYPE, + DID_CLGD_TYPESTR, + DID_CLGD_FC +}; + +static const OEMCHAR str_wab[] = OEMTEXT("General"); +static const OEMCHAR str_wab_asw[] = OEMTEXT("Use Analog Switch IC (No relay sound)"); +static const OEMCHAR str_wab_mt[] = OEMTEXT("Multi Thread Mode"); + +static const OEMCHAR str_clgd[] = OEMTEXT("CL-GD54xx"); +static const OEMCHAR str_clgd_en[] = OEMTEXT("Enabled (restart)"); +static const OEMCHAR str_clgd_type[] = OEMTEXT("Type"); +static const OEMCHAR str_clgd_fc[] = OEMTEXT("Use Fake Hardware Cursor"); + +static const OEMCHAR *str_cl_gd54xx_type[] = { + OEMTEXT("PC-9821Bp,Bs,Be,Bf built-in"), + OEMTEXT("PC-9821Xe built-in"), + OEMTEXT("PC-9821Cb built-in"), + OEMTEXT("PC-9821Cf built-in"), + OEMTEXT("PC-9821Xe10,Xa7e,Xb10 built-in"), + OEMTEXT("PC-9821Cb2 built-in"), + OEMTEXT("PC-9821Cx2 built-in"), +#ifdef SUPPORT_PCI + OEMTEXT("PC-9821 PCI CL-GD5446 built-in"), +#endif + OEMTEXT("MELCO WAB-S"), + OEMTEXT("MELCO WSN-A2F"), + OEMTEXT("MELCO WSN-A4F"), + OEMTEXT("I-O DATA GA-98NBI/C"), + OEMTEXT("I-O DATA GA-98NBII"), + OEMTEXT("I-O DATA GA-98NBIV"), + OEMTEXT("PC-9801-96(PC-9801B3-E02)"), +#ifdef SUPPORT_PCI + OEMTEXT("Auto Select(Xe10, GA-98NBI/C), PCI"), + OEMTEXT("Auto Select(Xe10, GA-98NBII), PCI"), + OEMTEXT("Auto Select(Xe10, GA-98NBIV), PCI"), + OEMTEXT("Auto Select(Xe10, WAB-S), PCI"), + OEMTEXT("Auto Select(Xe10, WSN-A2F), PCI"), + OEMTEXT("Auto Select(Xe10, WSN-A4F), PCI"), +#endif + OEMTEXT("Auto Select(Xe10, WAB-S)"), + OEMTEXT("Auto Select(Xe10, WSN-A2F)"), + OEMTEXT("Auto Select(Xe10, WSN-A4F)"), +}; + +static const MENUPRM res_wab0[] = { + {DLGTYPE_TABLIST, DID_TAB, 0, + NULL, 7, 6, 379, 196}, + {DLGTYPE_BUTTON, DID_OK, MENU_TABSTOP, + mstr_ok, 204, 208, 88, 21}, + {DLGTYPE_BUTTON, DID_CANCEL, MENU_TABSTOP, + mstr_cancel, 299, 208, 88, 21}}; + +static const MENUPRM res_wab1[] = { + {DLGTYPE_CHECK, DID_WAB_ASW, MENU_TABSTOP, + str_wab_asw, 25, 40, 358, 13}, + {DLGTYPE_CHECK, DID_WAB_MT, MENU_TABSTOP, + str_wab_mt, 25, 64, 358, 13}}; + +static const MENUPRM res_wab2[] = { + {DLGTYPE_CHECK, DID_CLGD_EN, MENU_TABSTOP, + str_clgd_en, 25, 40, 358, 13}, + {DLGTYPE_LTEXT, DID_STATIC, 0, + str_clgd_type, 25, 64, 358, 13}, + {DLGTYPE_SLIDER, DID_CLGD_TYPE, MSS_BOTH | MENU_TABSTOP, + (void *)SLIDERPOS(0, 14), 86, 66, 130, 11}, + {DLGTYPE_RTEXT, DID_CLGD_TYPESTR, 0, + NULL, 86, 88, 250, 13}, + {DLGTYPE_CHECK, DID_CLGD_FC, MENU_TABSTOP, + str_clgd_fc, 25, 112, 358, 13}}; + +typedef struct { + const OEMCHAR *tab; + const MENUPRM *prm; + UINT count; +} TABLISTS; + +static const TABLISTS tablist[] = { + {str_wab, res_wab1, NELEMENTS(res_wab1)}, + {str_clgd, res_wab2, NELEMENTS(res_wab2)}, +}; + +static void setpage(UINT page) { + + UINT i; + + for (i=0; itab); + menudlg_appends(tl->prm, tl->count); + } + + menudlg_setval(DID_WAB_ASW, np2cfg.wabasw & 1); + menudlg_setval(DID_WAB_MT, np2wabcfg.multithread & 1); +menudlg_setenable(DID_WAB_MT, 0); + + menudlg_setval(DID_CLGD_EN, np2cfg.usegd5430 & 1); + menudlg_setval(DID_CLGD_TYPE, type); + menudlg_settext(DID_CLGD_TYPESTR, str_cl_gd54xx_type[type]); + menudlg_setval(DID_CLGD_FC, np2cfg.gd5430fakecur & 1); + + menudlg_setval(DID_TAB, 0); + setpage(0); +} + +static void dlgupdate(void) { + + UINT update; + BOOL renewal; + UINT val; + UINT type; + + update = 0; + renewal = FALSE; + val = menudlg_getval(DID_WAB_ASW); + if (np2cfg.wabasw != (UINT8)val) { + np2cfg.wabasw = (UINT8)val; + renewal = TRUE; + } + val = menudlg_getval(DID_WAB_MT); + if (np2wabcfg.multithread != (UINT8)val) { + np2wabcfg.multithread = (UINT8)val; + renewal = TRUE; + } + val = menudlg_getval(DID_CLGD_EN); + if (np2cfg.usegd5430 != (UINT8)val) { + np2cfg.usegd5430 = (UINT8)val; + renewal = TRUE; + } + val = menudlg_getval(DID_CLGD_TYPE); + if (val > 14) { + val = 14; + } + switch(val) { + case 0: + type = CIRRUS_98ID_Be; + break; + case 1: + type = CIRRUS_98ID_Xe; + break; + case 2: + type = CIRRUS_98ID_Cb; + break; + case 3: + type = CIRRUS_98ID_Cf; + break; + case 4: + type = CIRRUS_98ID_Xe10; + break; + case 5: + type = CIRRUS_98ID_Cb2; + break; + case 6: + type = CIRRUS_98ID_Cx2; + break; +#ifdef SUPPORT_PCI + case 7: + type = CIRRUS_98ID_PCI; + break; + case 8: + type = CIRRUS_98ID_WAB; + break; + case 9: + type = CIRRUS_98ID_WSN_A2F; + break; + case 10: + type = CIRRUS_98ID_WSN; + break; + case 11: + type = CIRRUS_98ID_GA98NBIC; + break; + case 12: + type = CIRRUS_98ID_GA98NBII; + break; + case 13: + type = CIRRUS_98ID_GA98NBIV; + break; + case 14: + type = CIRRUS_98ID_96; + break; + case 15: + type = CIRRUS_98ID_AUTO_XE_G1_PCI; + break; + case 16: + type = CIRRUS_98ID_AUTO_XE_G2_PCI; + break; + case 17: + type = CIRRUS_98ID_AUTO_XE_G4_PCI; + break; + case 18: + type = CIRRUS_98ID_AUTO_XE_WA_PCI; + break; + case 19: + type = CIRRUS_98ID_AUTO_XE_WS_PCI; + break; + case 20: + type = CIRRUS_98ID_AUTO_XE_W4_PCI; + break; + case 21: + type = CIRRUS_98ID_AUTO_XE10_WABS; + break; + case 22: + type = CIRRUS_98ID_AUTO_XE10_WSN2; + break; + case 23: + type = CIRRUS_98ID_AUTO_XE10_WSN4; + break; +#else + case 7: + type = CIRRUS_98ID_WAB; + break; + case 8: + type = CIRRUS_98ID_WSN_A2F; + break; + case 9: + type = CIRRUS_98ID_WSN; + break; + case 10: + type = CIRRUS_98ID_GA98NBIC; + break; + case 11: + type = CIRRUS_98ID_GA98NBII; + break; + case 12: + type = CIRRUS_98ID_GA98NBIV; + break; + case 13: + type = CIRRUS_98ID_96; + break; + case 14: + type = CIRRUS_98ID_AUTO_XE10_WABS; + break; + case 15: + type = CIRRUS_98ID_AUTO_XE10_WSN2; + break; + case 16: + type = CIRRUS_98ID_AUTO_XE10_WSN4; + break; +#endif + } + if (np2cfg.gd5430type != (UINT16)type) { + np2cfg.gd5430type = (UINT16)type; + renewal = TRUE; + } + val = menudlg_getval(DID_CLGD_FC); + if (np2cfg.gd5430fakecur != (UINT8)val) { + np2cfg.gd5430fakecur = (UINT8)val; + renewal = TRUE; + } + if (renewal) { + scrndraw_redraw(); + update |= SYS_UPDATECFG; + } + + sysmng_update(update); +} + +int dlgwab_cmd(int msg, MENUID id, long param) { + + switch(msg) { + case DLGMSG_CREATE: + dlginit(); + break; + + case DLGMSG_COMMAND: + switch(id) { + case DID_OK: + dlgupdate(); + menubase_close(); + break; + + case DID_CANCEL: + menubase_close(); + break; + + case DID_TAB: + setpage(menudlg_getval(DID_TAB)); + break; + + case DID_CLGD_TYPE: + menudlg_settext(DID_CLGD_TYPESTR, str_cl_gd54xx_type[menudlg_getval(DID_CLGD_TYPE)]); + break; + } + break; + + case DLGMSG_CLOSE: + menubase_close(); + break; + } + (void)param; + return(0); +} + +#endif diff --git a/embed/menu/dlgwab.h b/embed/menu/dlgwab.h old mode 100755 new mode 100644 index 9ae62f93..5c69b75f --- a/embed/menu/dlgwab.h +++ b/embed/menu/dlgwab.h @@ -1,20 +1,20 @@ - -#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) - -enum { - DLGWAB_WIDTH = 393, - DLGWAB_HEIGHT = 235 -}; - -#ifdef __cplusplus -extern "C" { -#endif - -int dlgwab_cmd(int msg, MENUID id, long param); - -#ifdef __cplusplus -} -#endif - -#endif - + +#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) + +enum { + DLGWAB_WIDTH = 393, + DLGWAB_HEIGHT = 235 +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int dlgwab_cmd(int msg, MENUID id, long param); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/embed/menu/filesel.h b/embed/menu/filesel.h old mode 100755 new mode 100644 index 297f8d6b..2443bc87 --- a/embed/menu/filesel.h +++ b/embed/menu/filesel.h @@ -1,12 +1,12 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void filesel_fdd(REG8 drv); -void filesel_hdd(REG8 drv); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void filesel_fdd(REG8 drv); +void filesel_hdd(REG8 drv); + +#ifdef __cplusplus +} +#endif + diff --git a/embed/menu/menustr.c b/embed/menu/menustr.c old mode 100755 new mode 100644 index 986daf85..429673d3 --- a/embed/menu/menustr.c +++ b/embed/menu/menustr.c @@ -1,46 +1,46 @@ -#include -#include -#include -#include - - -const OEMCHAR mstr_cfg[] = OEMTEXT("Configure"); -const OEMCHAR mstr_scropt[] = OEMTEXT("Screen Option"); -const OEMCHAR mstr_wabopt[] = OEMTEXT("WAB Option"); -const OEMCHAR mstr_about[] = OEMTEXT("About"); - - - -// ---- - -static const UINT8 np2icondat[210] = { // 32x32 - 0x06,0x6f,0x00,0x00,0x3f,0x00,0x2d,0xff,0x00,0x0a,0x0d,0x7f,0x09, - 0x9c,0x0c,0xa3,0xf8,0x0b,0xf8,0x0f,0x94,0x16,0x5a,0x0f,0x94,0x23, - 0xdd,0xc0,0xc0,0xc0,0xc7,0x28,0x5a,0x17,0x0e,0x80,0x80,0x80,0x0b, - 0xc2,0x17,0xe9,0x0b,0x05,0xff,0x18,0xa3,0x17,0x11,0x0d,0x45,0x18, - 0xa6,0x17,0xe6,0x00,0x02,0x85,0x66,0x17,0x2c,0xff,0x14,0x08,0x47, - 0x23,0x68,0xd1,0x17,0x23,0x18,0x8e,0x47,0x1d,0x9c,0x9d,0x03,0x9a, - 0xff,0x00,0x08,0x4a,0x02,0xcb,0x2c,0x17,0xef,0xe3,0x2f,0x17,0xec, - 0x47,0x20,0x17,0xda,0xff,0x70,0x4b,0x03,0x91,0x17,0xff,0x00,0x25, - 0x5f,0x23,0x1c,0x5a,0x03,0x88,0xbb,0x48,0xff,0x13,0x75,0x6e,0xe0, - 0x47,0x3b,0xdd,0xe0,0x17,0x08,0x13,0x7b,0x61,0x6f,0x2f,0x3f,0xff, - 0xdd,0x19,0x31,0x7f,0x8c,0xe2,0x8d,0xb8,0x18,0xa3,0x30,0x3f,0xa4, - 0xd0,0xba,0xbe,0xff,0xf4,0x6c,0x20,0x11,0x1d,0xf2,0x8d,0xa6,0x92, - 0x35,0x77,0xe3,0x2f,0xc8,0x17,0x02,0xff,0x2f,0xef,0xbf,0x23,0x5e, - 0x7f,0x17,0xe2,0xf5,0xc5,0x00,0x05,0x12,0xa0,0x2f,0xfe,0xff,0x35, - 0x1a,0x0e,0xd4,0x02,0x0e,0x05,0xdd,0x4c,0x60,0x17,0xd7,0x14,0xd7, - 0x0c,0x94,0xfc,0x5d,0xa9,0x53,0xc5,0x4d,0xd7,0x5e,0x48,0x7a,0x3f, - 0x00,0x3a}; - -static const UINT8 np2iconmask[95] = { // 32x32 - 0x06,0x5f,0x00,0x00,0x03,0xff,0x00,0x02,0x02,0x04,0x00,0x08,0x04, - 0x4c,0x03,0x03,0xff,0x04,0x0b,0x03,0xce,0x03,0x87,0x04,0x46,0x03, - 0x8e,0x04,0x0c,0x00,0x0e,0x07,0xff,0xff,0x20,0x11,0x07,0x93,0x07, - 0xff,0x07,0xe0,0x08,0x16,0x53,0x4d,0x07,0xff,0x1f,0xb0,0xff,0x10, - 0x1f,0x7b,0x8f,0x17,0xb0,0x10,0x8c,0x17,0x6f,0x9c,0x90,0x06,0x9a, - 0x08,0x50,0xff,0x03,0x05,0x07,0xdb,0x11,0x12,0x17,0x8c,0x1f,0xdf, - 0x07,0xe3,0x06,0x4a,0x50,0x9b,0xf8,0x4f,0x99,0x08,0x20,0x9f,0xff, - 0x2f,0x51,0xef,0x10}; - -const MENURES np2icon = {32, 32, np2icondat, np2iconmask}; - +#include +#include +#include +#include + + +const OEMCHAR mstr_cfg[] = OEMTEXT("Configure"); +const OEMCHAR mstr_scropt[] = OEMTEXT("Screen Option"); +const OEMCHAR mstr_wabopt[] = OEMTEXT("WAB Option"); +const OEMCHAR mstr_about[] = OEMTEXT("About"); + + + +// ---- + +static const UINT8 np2icondat[210] = { // 32x32 + 0x06,0x6f,0x00,0x00,0x3f,0x00,0x2d,0xff,0x00,0x0a,0x0d,0x7f,0x09, + 0x9c,0x0c,0xa3,0xf8,0x0b,0xf8,0x0f,0x94,0x16,0x5a,0x0f,0x94,0x23, + 0xdd,0xc0,0xc0,0xc0,0xc7,0x28,0x5a,0x17,0x0e,0x80,0x80,0x80,0x0b, + 0xc2,0x17,0xe9,0x0b,0x05,0xff,0x18,0xa3,0x17,0x11,0x0d,0x45,0x18, + 0xa6,0x17,0xe6,0x00,0x02,0x85,0x66,0x17,0x2c,0xff,0x14,0x08,0x47, + 0x23,0x68,0xd1,0x17,0x23,0x18,0x8e,0x47,0x1d,0x9c,0x9d,0x03,0x9a, + 0xff,0x00,0x08,0x4a,0x02,0xcb,0x2c,0x17,0xef,0xe3,0x2f,0x17,0xec, + 0x47,0x20,0x17,0xda,0xff,0x70,0x4b,0x03,0x91,0x17,0xff,0x00,0x25, + 0x5f,0x23,0x1c,0x5a,0x03,0x88,0xbb,0x48,0xff,0x13,0x75,0x6e,0xe0, + 0x47,0x3b,0xdd,0xe0,0x17,0x08,0x13,0x7b,0x61,0x6f,0x2f,0x3f,0xff, + 0xdd,0x19,0x31,0x7f,0x8c,0xe2,0x8d,0xb8,0x18,0xa3,0x30,0x3f,0xa4, + 0xd0,0xba,0xbe,0xff,0xf4,0x6c,0x20,0x11,0x1d,0xf2,0x8d,0xa6,0x92, + 0x35,0x77,0xe3,0x2f,0xc8,0x17,0x02,0xff,0x2f,0xef,0xbf,0x23,0x5e, + 0x7f,0x17,0xe2,0xf5,0xc5,0x00,0x05,0x12,0xa0,0x2f,0xfe,0xff,0x35, + 0x1a,0x0e,0xd4,0x02,0x0e,0x05,0xdd,0x4c,0x60,0x17,0xd7,0x14,0xd7, + 0x0c,0x94,0xfc,0x5d,0xa9,0x53,0xc5,0x4d,0xd7,0x5e,0x48,0x7a,0x3f, + 0x00,0x3a}; + +static const UINT8 np2iconmask[95] = { // 32x32 + 0x06,0x5f,0x00,0x00,0x03,0xff,0x00,0x02,0x02,0x04,0x00,0x08,0x04, + 0x4c,0x03,0x03,0xff,0x04,0x0b,0x03,0xce,0x03,0x87,0x04,0x46,0x03, + 0x8e,0x04,0x0c,0x00,0x0e,0x07,0xff,0xff,0x20,0x11,0x07,0x93,0x07, + 0xff,0x07,0xe0,0x08,0x16,0x53,0x4d,0x07,0xff,0x1f,0xb0,0xff,0x10, + 0x1f,0x7b,0x8f,0x17,0xb0,0x10,0x8c,0x17,0x6f,0x9c,0x90,0x06,0x9a, + 0x08,0x50,0xff,0x03,0x05,0x07,0xdb,0x11,0x12,0x17,0x8c,0x1f,0xdf, + 0x07,0xe3,0x06,0x4a,0x50,0x9b,0xf8,0x4f,0x99,0x08,0x20,0x9f,0xff, + 0x2f,0x51,0xef,0x10}; + +const MENURES np2icon = {32, 32, np2icondat, np2iconmask}; + diff --git a/embed/menu/menustr.h b/embed/menu/menustr.h old mode 100755 new mode 100644 index 006ae868..f0551979 --- a/embed/menu/menustr.h +++ b/embed/menu/menustr.h @@ -1,16 +1,16 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -extern const OEMCHAR mstr_cfg[]; -extern const OEMCHAR mstr_scropt[]; -extern const OEMCHAR mstr_wabopt[]; -extern const OEMCHAR mstr_about[]; - -extern const MENURES np2icon; - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +extern const OEMCHAR mstr_cfg[]; +extern const OEMCHAR mstr_scropt[]; +extern const OEMCHAR mstr_wabopt[]; +extern const OEMCHAR mstr_about[]; + +extern const MENURES np2icon; + +#ifdef __cplusplus +} +#endif + diff --git a/embed/menubase/menubase.h b/embed/menubase/menubase.h old mode 100755 new mode 100644 index 27509c1d..a0fd198c --- a/embed/menubase/menubase.h +++ b/embed/menubase/menubase.h @@ -1,82 +1,82 @@ - -typedef unsigned short MENUID; -typedef unsigned short MENUFLG; - -#include "menuvram.h" -#include "menuicon.h" -#include "menusys.h" -#include "menudlg.h" -#include "menumbox.h" -#include "menures.h" - - -enum { - MENU_DISABLE = 0x0001, - MENU_GRAY = 0x0002, - MENU_CHECKED = 0x0004, - MENU_SEPARATOR = 0x0008, - MENU_REDRAW = 0x1000, - MENU_NOSEND = 0x2000, - MENU_TABSTOP = 0x4000, - MENU_DELETED = 0x8000, - MENU_STYLE = 0x0ff0 -}; - -enum { - DID_STATIC = 0, - DID_OK, - DID_CANCEL, - DID_ABORT, - DID_RETRY, - DID_IGNORE, - DID_YES, - DID_NO, - DID_APPLY, - DID_USER -}; - -enum { - SID_CAPTION = 0x7ffd, - SID_MINIMIZE = 0x7ffe, - SID_CLOSE = 0x7fff -}; - -typedef struct { - int num; - void *font; - void *font2; - int del; - UNIRECT rect; - int width; - int height; - UINT bpp; -} MENUBASE; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern VRAMHDL menuvram; -extern MENUBASE menubase; - -BRESULT menubase_create(void); -void menubase_destroy(void); - -BRESULT menubase_open(int num); -void menubase_close(void); -BRESULT menubase_moving(int x, int y, int btn); -BRESULT menubase_key(UINT key); - -void menubase_setrect(VRAMHDL vram, const RECT_T *rect); -void menubase_clrrect(VRAMHDL vram); -void menubase_draw(void (*draw)(VRAMHDL dst, const RECT_T *rect, void *arg), - void *arg); - -void menubase_proc(void); -void menubase_modalproc(void); - -#ifdef __cplusplus -} -#endif - + +typedef unsigned short MENUID; +typedef unsigned short MENUFLG; + +#include "menuvram.h" +#include "menuicon.h" +#include "menusys.h" +#include "menudlg.h" +#include "menumbox.h" +#include "menures.h" + + +enum { + MENU_DISABLE = 0x0001, + MENU_GRAY = 0x0002, + MENU_CHECKED = 0x0004, + MENU_SEPARATOR = 0x0008, + MENU_REDRAW = 0x1000, + MENU_NOSEND = 0x2000, + MENU_TABSTOP = 0x4000, + MENU_DELETED = 0x8000, + MENU_STYLE = 0x0ff0 +}; + +enum { + DID_STATIC = 0, + DID_OK, + DID_CANCEL, + DID_ABORT, + DID_RETRY, + DID_IGNORE, + DID_YES, + DID_NO, + DID_APPLY, + DID_USER +}; + +enum { + SID_CAPTION = 0x7ffd, + SID_MINIMIZE = 0x7ffe, + SID_CLOSE = 0x7fff +}; + +typedef struct { + int num; + void *font; + void *font2; + int del; + UNIRECT rect; + int width; + int height; + UINT bpp; +} MENUBASE; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern VRAMHDL menuvram; +extern MENUBASE menubase; + +BRESULT menubase_create(void); +void menubase_destroy(void); + +BRESULT menubase_open(int num); +void menubase_close(void); +BRESULT menubase_moving(int x, int y, int btn); +BRESULT menubase_key(UINT key); + +void menubase_setrect(VRAMHDL vram, const RECT_T *rect); +void menubase_clrrect(VRAMHDL vram); +void menubase_draw(void (*draw)(VRAMHDL dst, const RECT_T *rect, void *arg), + void *arg); + +void menubase_proc(void); +void menubase_modalproc(void); + +#ifdef __cplusplus +} +#endif + diff --git a/embed/menubase/menudeco.inc b/embed/menubase/menudeco.inc old mode 100755 new mode 100644 index 38ce727b..06e3a214 --- a/embed/menubase/menudeco.inc +++ b/embed/menubase/menudeco.inc @@ -1,184 +1,184 @@ - -// めにゅーでこれーしょん。 -// VGA用。 - -#ifndef NP2_SIZE_QVGA - -enum { - MENU_FBORDER = 2, - MENU_BORDER = 1, - MENU_FONTSIZE = 12, - MENU_PXCAPTION = 2, - MENU_PYCAPTION = 1, - MENU_LINE = 1, - MENU_DSTEXT = 1 -}; - -enum { - MENUSYS_BCAPTION = 1, - - MENUSYS_SZICON = 16, - MENUSYS_CYCAPTION = 18, - MENUSYS_CXCLOSE = 16, - MENUSYS_CYCLOSE = 14, - - MENUSYS_CYSYS = 18, - MENUSYS_SXSYS = 7, - MENUSYS_LXSYS = 7, - MENUSYS_SYSYS = 2, - - MENUSYS_CYITEM = 16, - MENUSYS_SXITEM = 3, - MENUSYS_SYITEM = 1, - MENUSYS_CXCHECK = 10, - MENUSYS_CXNEXT = 16, - - MENUSYS_CYSEP = 9, - MENUSYS_SXSEP = 1, - MENUSYS_LXSEP = 1, - MENUSYS_SYSEP = 3 -}; - -enum { - MENUDLG_CYCAPTION = 18, - MENUDLG_BORDER = 1, - - MENUDLG_CXCLOSE = 16, - MENUDLG_CYCLOSE = 14, - MENUDLG_PXCAPTION = 2, - - MENUDLG_CXRADIO = 12, - MENUDLG_CYRADIO = 12, - MENUDLG_SXRADIO = 17, - - MENUDLG_CXCHECK = 13, - MENUDLG_CYCHECK = 13, - MENUDLG_SXCHECK = 18, - - MENUDLG_SXFRAME = 7, - MENUDLG_SYFRAME = 6, - MENUDLG_PXFRAME = 2, - -// MENUDLG_SXSLD = 5, -// MENUDLG_SYSLD = 7, - - MENUDLG_SYTAB = 2, - MENUDLG_TXTAB = 4, - MENUDLG_TYTAB = 3, - MENUDLG_EYTAB = 2, - - MENUDLG_CXVSCR = 16, - MENUDLG_CYVSCR = 16 -}; - -enum { - MENUMBOX_WIDTH = 512, - MENUMBOX_MAXLINE = 8, - MENUMBOX_MAXTEXT = 128, - MENUMBOX_SX = 12, - MENUMBOX_SY = 11, - MENUMBOX_SZICON = 32, - MENUMBOX_CXICON = 50, - MENUMBOX_CYICON = 32, - MENUMBOX_PXTEXT = 6, - MENUMBOX_LXTEXT = 5, - - MENUMBOX_CXBTN = 88, - MENUMBOX_CYBTN = 21, - MENUMBOX_SXBTN = 13, - MENUMBOX_PXBTN = 7, - MENUMBOX_SYBTN = 14, - MENUMBOX_LYBTN = 10 -}; - -#else - -enum { - MENU_FBORDER = 2, - MENU_BORDER = 1, - MENU_FONTSIZE = 10, - MENU_PXCAPTION = 2, - MENU_PYCAPTION = 1, - MENU_LINE = 1, - MENU_DSTEXT = 1 -}; - -enum { - MENUSYS_BCAPTION = 1, - - MENUSYS_SZICON = 12, - MENUSYS_CYCAPTION = 14, - MENUSYS_CXCLOSE = 12, - MENUSYS_CYCLOSE = 12, - - MENUSYS_CYSYS = 12, - MENUSYS_SXSYS = 4, - MENUSYS_LXSYS = 4, - MENUSYS_SYSYS = 0, - - MENUSYS_CYITEM = 12, - MENUSYS_SXITEM = 3, - MENUSYS_SYITEM = 1, - MENUSYS_CXCHECK = 8, - MENUSYS_CXNEXT = 8, - - MENUSYS_CYSEP = 6, - MENUSYS_SXSEP = 1, - MENUSYS_LXSEP = 1, - MENUSYS_SYSEP = 2 -}; - -enum { - MENUDLG_CYCAPTION = 14, - MENUDLG_BORDER = 1, - - MENUDLG_CXCLOSE = 12, - MENUDLG_CYCLOSE = 12, - MENUDLG_PXCAPTION = 2, - - MENUDLG_CXRADIO = 10, - MENUDLG_CYRADIO = 10, - MENUDLG_SXRADIO = 12, - - MENUDLG_CXCHECK = 10, - MENUDLG_CYCHECK = 10, - MENUDLG_SXCHECK = 12, - - MENUDLG_SXFRAME = 6, - MENUDLG_SYFRAME = 5, - MENUDLG_PXFRAME = 2, - -// MENUDLG_SXSLD = 3, -// MENUDLG_SYSLD = 5, - - MENUDLG_SYTAB = 1, - MENUDLG_TXTAB = 3, - MENUDLG_TYTAB = 2, - MENUDLG_EYTAB = 1, - - MENUDLG_CXVSCR = 10, - MENUDLG_CYVSCR = 10 -}; - -enum { - MENUMBOX_WIDTH = 288, - MENUMBOX_MAXLINE = 8, - MENUMBOX_MAXTEXT = 64, - MENUMBOX_SX = 3, - MENUMBOX_SY = 3, - MENUMBOX_SZICON = 16, - MENUMBOX_CXICON = 24, - MENUMBOX_CYICON = 16, - MENUMBOX_PXTEXT = 1, - MENUMBOX_LXTEXT = 4, - - MENUMBOX_CXBTN = 48, - MENUMBOX_CYBTN = 12, - MENUMBOX_SXBTN = 4, - MENUMBOX_PXBTN = 4, - MENUMBOX_SYBTN = 8, - MENUMBOX_LYBTN = 4 -}; - -#endif - + +// めにゅーでこれーしょん。 +// VGA用。 + +#ifndef NP2_SIZE_QVGA + +enum { + MENU_FBORDER = 2, + MENU_BORDER = 1, + MENU_FONTSIZE = 12, + MENU_PXCAPTION = 2, + MENU_PYCAPTION = 1, + MENU_LINE = 1, + MENU_DSTEXT = 1 +}; + +enum { + MENUSYS_BCAPTION = 1, + + MENUSYS_SZICON = 16, + MENUSYS_CYCAPTION = 18, + MENUSYS_CXCLOSE = 16, + MENUSYS_CYCLOSE = 14, + + MENUSYS_CYSYS = 18, + MENUSYS_SXSYS = 7, + MENUSYS_LXSYS = 7, + MENUSYS_SYSYS = 2, + + MENUSYS_CYITEM = 16, + MENUSYS_SXITEM = 3, + MENUSYS_SYITEM = 1, + MENUSYS_CXCHECK = 10, + MENUSYS_CXNEXT = 16, + + MENUSYS_CYSEP = 9, + MENUSYS_SXSEP = 1, + MENUSYS_LXSEP = 1, + MENUSYS_SYSEP = 3 +}; + +enum { + MENUDLG_CYCAPTION = 18, + MENUDLG_BORDER = 1, + + MENUDLG_CXCLOSE = 16, + MENUDLG_CYCLOSE = 14, + MENUDLG_PXCAPTION = 2, + + MENUDLG_CXRADIO = 12, + MENUDLG_CYRADIO = 12, + MENUDLG_SXRADIO = 17, + + MENUDLG_CXCHECK = 13, + MENUDLG_CYCHECK = 13, + MENUDLG_SXCHECK = 18, + + MENUDLG_SXFRAME = 7, + MENUDLG_SYFRAME = 6, + MENUDLG_PXFRAME = 2, + +// MENUDLG_SXSLD = 5, +// MENUDLG_SYSLD = 7, + + MENUDLG_SYTAB = 2, + MENUDLG_TXTAB = 4, + MENUDLG_TYTAB = 3, + MENUDLG_EYTAB = 2, + + MENUDLG_CXVSCR = 16, + MENUDLG_CYVSCR = 16 +}; + +enum { + MENUMBOX_WIDTH = 512, + MENUMBOX_MAXLINE = 8, + MENUMBOX_MAXTEXT = 128, + MENUMBOX_SX = 12, + MENUMBOX_SY = 11, + MENUMBOX_SZICON = 32, + MENUMBOX_CXICON = 50, + MENUMBOX_CYICON = 32, + MENUMBOX_PXTEXT = 6, + MENUMBOX_LXTEXT = 5, + + MENUMBOX_CXBTN = 88, + MENUMBOX_CYBTN = 21, + MENUMBOX_SXBTN = 13, + MENUMBOX_PXBTN = 7, + MENUMBOX_SYBTN = 14, + MENUMBOX_LYBTN = 10 +}; + +#else + +enum { + MENU_FBORDER = 2, + MENU_BORDER = 1, + MENU_FONTSIZE = 10, + MENU_PXCAPTION = 2, + MENU_PYCAPTION = 1, + MENU_LINE = 1, + MENU_DSTEXT = 1 +}; + +enum { + MENUSYS_BCAPTION = 1, + + MENUSYS_SZICON = 12, + MENUSYS_CYCAPTION = 14, + MENUSYS_CXCLOSE = 12, + MENUSYS_CYCLOSE = 12, + + MENUSYS_CYSYS = 12, + MENUSYS_SXSYS = 4, + MENUSYS_LXSYS = 4, + MENUSYS_SYSYS = 0, + + MENUSYS_CYITEM = 12, + MENUSYS_SXITEM = 3, + MENUSYS_SYITEM = 1, + MENUSYS_CXCHECK = 8, + MENUSYS_CXNEXT = 8, + + MENUSYS_CYSEP = 6, + MENUSYS_SXSEP = 1, + MENUSYS_LXSEP = 1, + MENUSYS_SYSEP = 2 +}; + +enum { + MENUDLG_CYCAPTION = 14, + MENUDLG_BORDER = 1, + + MENUDLG_CXCLOSE = 12, + MENUDLG_CYCLOSE = 12, + MENUDLG_PXCAPTION = 2, + + MENUDLG_CXRADIO = 10, + MENUDLG_CYRADIO = 10, + MENUDLG_SXRADIO = 12, + + MENUDLG_CXCHECK = 10, + MENUDLG_CYCHECK = 10, + MENUDLG_SXCHECK = 12, + + MENUDLG_SXFRAME = 6, + MENUDLG_SYFRAME = 5, + MENUDLG_PXFRAME = 2, + +// MENUDLG_SXSLD = 3, +// MENUDLG_SYSLD = 5, + + MENUDLG_SYTAB = 1, + MENUDLG_TXTAB = 3, + MENUDLG_TYTAB = 2, + MENUDLG_EYTAB = 1, + + MENUDLG_CXVSCR = 10, + MENUDLG_CYVSCR = 10 +}; + +enum { + MENUMBOX_WIDTH = 288, + MENUMBOX_MAXLINE = 8, + MENUMBOX_MAXTEXT = 64, + MENUMBOX_SX = 3, + MENUMBOX_SY = 3, + MENUMBOX_SZICON = 16, + MENUMBOX_CXICON = 24, + MENUMBOX_CYICON = 16, + MENUMBOX_PXTEXT = 1, + MENUMBOX_LXTEXT = 4, + + MENUMBOX_CXBTN = 48, + MENUMBOX_CYBTN = 12, + MENUMBOX_SXBTN = 4, + MENUMBOX_PXBTN = 4, + MENUMBOX_SYBTN = 8, + MENUMBOX_LYBTN = 4 +}; + +#endif + diff --git a/embed/menubase/menudlg.c b/embed/menubase/menudlg.c old mode 100755 new mode 100644 index 859c7781..0546a866 --- a/embed/menubase/menudlg.c +++ b/embed/menubase/menudlg.c @@ -1,2423 +1,2423 @@ -#include -#include -#include -#include -#include -#include "menudeco.inc" -#include - - -typedef struct _dprm { -struct _dprm *next; - UINT16 width; - UINT16 num; - VRAMHDL icon; - OEMCHAR str[96]; -} _DLGPRM, *DLGPRM; - -#define PRMNEXT_EMPTY ((DLGPRM)-1) - -typedef struct { - POINT_T pt; - void *font; -} DLGTEXT; - -typedef struct { - void *font; - int fontsize; -} DLGTAB; - -typedef struct { - void *font; - SINT16 fontsize; - SINT16 scrollbar; - SINT16 dispmax; - SINT16 basepos; -} DLGLIST; - -typedef struct { - SINT16 minval; - SINT16 maxval; - int pos; - UINT8 type; - UINT8 moving; - UINT8 sldh; - UINT8 sldv; -} DLGSLD; - -typedef struct { - VRAMHDL vram; -} DLGVRAM; - -typedef struct _ditem { - int type; - MENUID id; - MENUFLG flag; - MENUID page; - MENUID group; - RECT_T rect; - DLGPRM prm; - int prmcnt; - int val; - VRAMHDL vram; - union { - DLGTEXT dt; - DLGTAB dtl; - DLGLIST dl; - DLGSLD ds; - DLGVRAM dv; - } c; -} _DLGHDL, *DLGHDL; - -typedef struct { - VRAMHDL vram; - LISTARRAY dlg; - LISTARRAY res; - int locked; - int closing; - int sx; - int sy; - void *font; - MENUID page; - MENUID group; - int (*proc)(int msg, MENUID id, long param); - - int dragflg; - int btn; - int lastx; - int lasty; - MENUID lastid; -} _MENUDLG, *MENUDLG; - - -static _MENUDLG menudlg; - -static void drawctrls(MENUDLG dlg, DLGHDL hdl); - - -// ---- - -static BOOL seaprmempty(void *vpItem, void *vpArg) { - - if (((DLGPRM)vpItem)->next == PRMNEXT_EMPTY) { - menuicon_unlock(((DLGPRM)vpItem)->icon); - ((DLGPRM)vpItem)->icon = NULL; - return(TRUE); - } - (void)vpArg; - return(FALSE); -} - -static DLGPRM resappend(MENUDLG dlg, const OEMCHAR *str) { - - DLGPRM prm; - - prm = (DLGPRM)listarray_enum(dlg->res, seaprmempty, NULL); - if (prm == NULL) { - prm = (DLGPRM)listarray_append(dlg->res, NULL); - } - if (prm) { - prm->next = NULL; - prm->width = 0; - prm->num = 0; - prm->icon = NULL; - prm->str[0] = '\0'; - if (str) { - milstr_ncpy(prm->str, str, NELEMENTS(prm->str)); - } - } - return(prm); -} - -static void resattachicon(MENUDLG dlg, DLGPRM prm, UINT16 icon, - int width, int height) { - - if (prm) { - menuicon_unlock(prm->icon); - prm->num = icon; - prm->icon = menuicon_lock(icon, width, height, dlg->vram->bpp); - } -} - -static DLGPRM ressea(DLGHDL hdl, int pos) { - - DLGPRM prm; - - if (pos >= 0) { - prm = hdl->prm; - while(prm) { - if (!pos) { - return(prm); - } - pos--; - prm = prm->next; - } - } - return(NULL); -} - -static BOOL dsbyid(void *vpItem, void *vpArg) { - - if (((DLGHDL)vpItem)->id == (MENUID)(unsigned long)vpArg) { - return(TRUE); - } - return(FALSE); -} - -static DLGHDL dlghdlsea(MENUDLG dlg, MENUID id) { - - return((DLGHDL)listarray_enum(dlg->dlg, dsbyid, (void *)(long)id)); -} - -static BRESULT gettextsz(DLGHDL hdl, POINT_T *sz) { - - DLGPRM prm; - - prm = hdl->prm; - if (prm == NULL) { - goto gts_err; - } - *sz = hdl->c.dt.pt; - if (prm->icon) { - if (sz->x) { -#if defined(NP2_SIZE_QVGA) - sz->x += 1; -#else - sz->x += 2; -#endif - } - sz->x += sz->y; - } - return(SUCCESS); - -gts_err: - return(FAILURE); -} - -static void getleft(POINT_T *pt, const RECT_T *rect, const POINT_T *sz) { - - pt->x = rect->left; - pt->y = rect->top; - (void)sz; -} - -static void getcenter(POINT_T *pt, const RECT_T *rect, const POINT_T *sz) { - - pt->x = rect->left; - pt->x += (rect->right - rect->left - sz->x) >> 1; - pt->y = rect->top; -} - -static void getright(POINT_T *pt, const RECT_T *rect, const POINT_T *sz) { - - pt->x = rect->right - sz->x - MENU_DSTEXT; - pt->y = rect->top; -} - -static void getmid(POINT_T *pt, const RECT_T *rect, const POINT_T *sz) { - - pt->x = rect->left; - pt->x += (rect->right - rect->left - sz->x) >> 1; - pt->y = rect->top; - pt->y += (rect->bottom - rect->top - sz->y) >> 1; -} - - -static BRESULT _cre_settext(MENUDLG dlg, DLGHDL hdl, const void *arg) { - -const OEMCHAR *str; - - str = (OEMCHAR *)arg; - if (str == NULL) { - str = str_null; - } - hdl->prm = resappend(dlg, str); - hdl->c.dt.font = dlg->font; - fontmng_getsize(dlg->font, str, &hdl->c.dt.pt); - return(SUCCESS); -} - -static void dlg_text(MENUDLG dlg, DLGHDL hdl, - const POINT_T *pt, const RECT_T *rect) { - - VRAMHDL icon; -const OEMCHAR *string; - int color; - POINT_T fp; - POINT_T p; - - if (hdl->prm == NULL) { - return; - } - fp = *pt; - icon = hdl->prm->icon; - if (icon) { - if (icon->alpha) { - vramcpy_cpyex(dlg->vram, &fp, icon, NULL); - } - else { - vramcpy_cpy(dlg->vram, &fp, icon, NULL); - } - fp.x += icon->width; -#if defined(NP2_SIZE_QVGA) - fp.x += 1; -#else - fp.x += 2; -#endif - } - string = hdl->prm->str; - if (string) { - if (!(hdl->flag & MENU_GRAY)) { - color = MVC_TEXT; - } - else { - p.x = fp.x + MENU_DSTEXT; - p.y = fp.y + MENU_DSTEXT; - vrammix_text(dlg->vram, hdl->c.dt.font, string, - menucolor[MVC_GRAYTEXT2], &p, rect); - color = MVC_GRAYTEXT1; - } - vrammix_text(dlg->vram, hdl->c.dt.font, string, - menucolor[color], &fp, rect); - } -} - - -// ---- base - -static BRESULT dlgbase_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { - - RECT_T rct; - - rct.right = hdl->rect.right - hdl->rect.left - - ((MENU_FBORDER + MENU_BORDER) * 2); - hdl->vram = vram_create(rct.right, MENUDLG_CYCAPTION, FALSE, menubase.bpp); - if (hdl->vram == NULL) { - goto dbcre_err; - } - hdl->vram->posx = (MENU_FBORDER + MENU_BORDER); - hdl->vram->posy = (MENU_FBORDER + MENU_BORDER); - rct.left = 0; - rct.top = 0; - rct.bottom = MENUDLG_CYCAPTION; - menuvram_caption(hdl->vram, &rct, MICON_NULL, (OEMCHAR *)arg); - return(SUCCESS); - -dbcre_err: - (void)dlg; - return(FAILURE); -} - - -static void dlgbase_paint(MENUDLG dlg, DLGHDL hdl) { - - OEMCHAR *title; - - title = NULL; - if (hdl->prm) { - title = hdl->prm->str; - } - menuvram_base(dlg->vram); - vrammix_cpy(dlg->vram, NULL, hdl->vram, NULL); - menubase_setrect(dlg->vram, NULL); -} - - -static void dlgbase_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { - - RECT_T rct; - - vram_getrect(hdl->vram, &rct); - dlg->dragflg = rect_in(&rct, x, y); - dlg->lastx = x; - dlg->lasty = y; -} - - -static void dlgbase_move(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus) { - - if (dlg->dragflg) { - x -= dlg->lastx; - y -= dlg->lasty; - if ((x) || (y)) { - menubase_clrrect(dlg->vram); - dlg->vram->posx += x; - dlg->vram->posy += y; - menubase_setrect(dlg->vram, NULL); - } - } - (void)hdl; - (void)focus; -} - - -// ---- close - -static void dlgclose_paint(MENUDLG dlg, DLGHDL hdl) { - - menuvram_closebtn(dlg->vram, &hdl->rect, hdl->val); -} - - -static void dlgclose_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { - - hdl->val = 1; - drawctrls(dlg, hdl); - (void)x; - (void)y; -} - - -static void dlgclose_move(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus) { - - if (hdl->val != focus) { - hdl->val = focus; - drawctrls(dlg, hdl); - } - (void)x; - (void)y; -} - - -static void dlgclose_rel(MENUDLG dlg, DLGHDL hdl, int focus) { - - if (focus) { - dlg->proc(DLGMSG_CLOSE, 0, 0); - } - (void)hdl; -} - - -// ---- button - -static void dlgbtn_paint(MENUDLG dlg, DLGHDL hdl) { - - POINT_T sz; - POINT_T pt; - UINT c; - - vram_filldat(dlg->vram, &hdl->rect, menucolor[MVC_BTNFACE]); - if (!hdl->val) { - c = MVC4(MVC_HILIGHT, MVC_DARK, MVC_LIGHT, MVC_SHADOW); - } - else { - c = MVC4(MVC_DARK, MVC_DARK, MVC_SHADOW, MVC_SHADOW); - } - menuvram_box2(dlg->vram, &hdl->rect, c); - - if (gettextsz(hdl, &sz) == SUCCESS) { - getmid(&pt, &hdl->rect, &sz); - if (hdl->val) { - pt.x += MENU_DSTEXT; - pt.y += MENU_DSTEXT; - } - dlg_text(dlg, hdl, &pt, &hdl->rect); - } -} - - -static void dlgbtn_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { - - hdl->val = 1; - drawctrls(dlg, hdl); - (void)x; - (void)y; -} - -static void dlgbtn_move(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus) { - - if (hdl->val != focus) { - hdl->val = focus; - drawctrls(dlg, hdl); - } - (void)x; - (void)y; -} - -static void dlgbtn_rel(MENUDLG dlg, DLGHDL hdl, int focus) { - - if (hdl->val != 0) { - hdl->val = 0; - drawctrls(dlg, hdl); - } - if (focus) { - dlg->proc(DLGMSG_COMMAND, hdl->id, 0); - } -} - - -// ---- list - -static void *dlglist_setfont(DLGHDL hdl, void *font) { - // 後でスクロールバーの調整をすべし - void *ret; - POINT_T pt; - - ret = hdl->c.dl.font; - hdl->c.dl.font = font; - fontmng_getsize(font, mstr_fontcheck, &pt); - if ((pt.y <= 0) || (pt.y >= 65536)) { - pt.y = 16; - } - hdl->c.dl.fontsize = (SINT16)pt.y; - hdl->c.dl.dispmax = (SINT16)(hdl->vram->height / pt.y); - return(ret); -} - -static void dlglist_reset(MENUDLG dlg, DLGHDL hdl) { - - DLGPRM dp; - DLGPRM next; - - vram_filldat(hdl->vram, NULL, 0xffffff); - dp = hdl->prm; - while(dp) { - next = dp->next; - dp->next = PRMNEXT_EMPTY; - dp = next; - } - hdl->prm = NULL; - hdl->prmcnt = 0; - hdl->val = -1; - hdl->c.dl.scrollbar = 0; - hdl->c.dl.basepos = 0; -} - -static BRESULT dlglist_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { - - int width; - int height; - - width = hdl->rect.right - hdl->rect.left - (MENU_LINE * 4); - height = hdl->rect.bottom - hdl->rect.top - (MENU_LINE * 4); - hdl->vram = vram_create(width, height, FALSE, menubase.bpp); - if (hdl->vram == NULL) { - goto dlcre_err; - } - hdl->vram->posx = hdl->rect.left + (MENU_LINE * 2); - hdl->vram->posy = hdl->rect.top + (MENU_LINE * 2); - dlglist_setfont(hdl, dlg->font); - dlglist_reset(dlg, hdl); - return(SUCCESS); - -dlcre_err: - (void)dlg; - (void)arg; - return(FAILURE); -} - -static void dlglist_paint(MENUDLG dlg, DLGHDL hdl) { - - menuvram_box2(dlg->vram, &hdl->rect, - MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_DARK, MVC_LIGHT)); - vrammix_cpy(dlg->vram, NULL, hdl->vram, NULL); -} - -static void dlglist_drawitem(DLGHDL hdl, DLGPRM prm, int focus, - POINT_T *pt, RECT_T *rct) { - - VRAMHDL icon; - POINT_T fp; - - vram_filldat(hdl->vram, rct, menucolor[focus?MVC_CURBACK:MVC_HILIGHT]); - fp.x = pt->x; - fp.y = pt->y; - icon = prm->icon; - if (icon) { - if (icon->alpha) { - vramcpy_cpyex(hdl->vram, &fp, icon, NULL); - } - else { - vramcpy_cpy(hdl->vram, &fp, icon, NULL); - } - fp.x += icon->width; -#if defined(NP2_SIZE_QVGA) - fp.x += 1; -#else - fp.x += 2; -#endif - } - vrammix_text(hdl->vram, hdl->c.dl.font, prm->str, - menucolor[focus?MVC_CURTEXT:MVC_TEXT], &fp, rct); -} - -static BOOL dlglist_drawsub(DLGHDL hdl, int pos, int focus) { - - DLGPRM prm; - POINT_T pt; - RECT_T rct; - - prm = ressea(hdl, pos); - if (prm == NULL) { - return(FALSE); - } - pos -= hdl->c.dl.basepos; - if (pos < 0) { - return(FALSE); - } - pt.x = 0; - pt.y = pos * hdl->c.dl.fontsize; - if (pt.y >= hdl->vram->height) { - return(FALSE); - } - rct.left = 0; - rct.top = pt.y; - rct.right = hdl->vram->width; - if (hdl->prmcnt > hdl->c.dl.dispmax) { - rct.right -= MENUDLG_CXVSCR; - } - rct.bottom = rct.top + hdl->c.dl.fontsize; - dlglist_drawitem(hdl, prm, focus, &pt, &rct); - return(TRUE); -} - -static void dlglist_setbtn(DLGHDL hdl, int flg) { - - RECT_T rct; - POINT_T pt; - UINT mvc4; -const MENURES2 *res; - - res = menures_scrbtn; - rct.right = hdl->vram->width; - rct.left = rct.right - MENUDLG_CXVSCR; - if (!(flg & 2)) { - rct.top = 0; - } - else { - rct.top = hdl->vram->height - MENUDLG_CYVSCR; - if (rct.top < MENUDLG_CYVSCR) { - rct.top = MENUDLG_CYVSCR; - } - res++; - } - rct.bottom = rct.top + MENUDLG_CYVSCR; - - vram_filldat(hdl->vram, &rct, menucolor[MVC_BTNFACE]); - if (flg & 1) { - mvc4 = MVC4(MVC_SHADOW, MVC_SHADOW, MVC_LIGHT, MVC_LIGHT); - } - else { - mvc4 = MVC4(MVC_LIGHT, MVC_DARK, MVC_HILIGHT, MVC_SHADOW); - } - menuvram_box2(hdl->vram, &rct, mvc4); - pt.x = rct.left + (MENU_LINE * 2); - pt.y = rct.top + (MENU_LINE * 2); - if (flg & 1) { - pt.x += MENU_DSTEXT; - pt.y += MENU_DSTEXT; - } - menuvram_res3put(hdl->vram, res, &pt, MVC_TEXT); -} - -static void dlglist_drawall(DLGHDL hdl) { - - DLGPRM prm; - POINT_T pt; - RECT_T rct; - int pos; - - rct.left = 0; - rct.top = 0 - (hdl->c.dl.basepos * hdl->c.dl.fontsize); - rct.right = hdl->vram->width; - if (hdl->prmcnt > hdl->c.dl.dispmax) { - rct.right -= MENUDLG_CXVSCR; - } - - prm = hdl->prm; - pos = 0; - while(prm) { - if (rct.top >= hdl->vram->height) { - break; - } - if (rct.top >= 0) { - rct.bottom = rct.top + hdl->c.dl.fontsize; - pt.x = 0; - pt.y = rct.top; - dlglist_drawitem(hdl, prm, (pos == hdl->val), &pt, &rct); - } - prm = prm->next; - pos++; - rct.top += hdl->c.dl.fontsize; - } - rct.bottom = hdl->vram->height; - vram_filldat(hdl->vram, &rct, menucolor[MVC_HILIGHT]); -} - -static int dlglist_barpos(DLGHDL hdl) { - - int ret; - - ret = hdl->vram->height - (MENUDLG_CYVSCR * 2); - ret -= hdl->c.dl.scrollbar; - ret *= hdl->c.dl.basepos; - ret /= (hdl->prmcnt - hdl->c.dl.dispmax); - return(ret); -} - -static void dlglist_drawbar(DLGHDL hdl) { - - RECT_T rct; - - rct.right = hdl->vram->width; - rct.left = rct.right - MENUDLG_CXVSCR; - rct.top = MENUDLG_CYVSCR; - rct.bottom = hdl->vram->height - MENUDLG_CYVSCR; - vram_filldat(hdl->vram, &rct, menucolor[MVC_SCROLLBAR]); - - rct.top += dlglist_barpos(hdl); - rct.bottom = rct.top + hdl->c.dl.scrollbar; - vram_filldat(hdl->vram, &rct, menucolor[MVC_BTNFACE]); - menuvram_box2(hdl->vram, &rct, - MVC4(MVC_LIGHT, MVC_DARK, MVC_HILIGHT, MVC_SHADOW)); -} - -static BOOL dlglist_append(MENUDLG dlg, DLGHDL hdl, const OEMCHAR* arg) { - - BOOL r; - DLGPRM *sto; - int barsize; - - r = FALSE; - sto = &hdl->prm; - while(*sto) { - sto = &((*sto)->next); - } - *sto = resappend(dlg, arg); - if (*sto) { - r = dlglist_drawsub(hdl, hdl->prmcnt, FALSE); - hdl->prmcnt++; - if (hdl->prmcnt > hdl->c.dl.dispmax) { - barsize = hdl->vram->height - (MENUDLG_CYVSCR * 2); - if (barsize >= 8) { - barsize *= hdl->c.dl.dispmax; - barsize /= hdl->prmcnt; - barsize = MAX(barsize, 6); - if (!hdl->c.dl.scrollbar) { - dlglist_drawall(hdl); - dlglist_setbtn(hdl, 0); - dlglist_setbtn(hdl, 2); - } - hdl->c.dl.scrollbar = barsize; - dlglist_drawbar(hdl); - } - } - } - return(r); -} - -static BOOL dlglist_setex(MENUDLG dlg, DLGHDL hdl, const ITEMEXPRM *arg) { - - DLGPRM dp; - UINT cnt; - - if ((arg == NULL) || (arg->pos >= hdl->prmcnt)) { - return(FALSE); - } - cnt = arg->pos; - dp = hdl->prm; - while((cnt) && (dp)) { - cnt--; - dp = dp->next; - } - if (dp == NULL) { - return(FALSE); - } - resattachicon(dlg, dp, arg->icon, hdl->c.dl.fontsize, - hdl->c.dl.fontsize); - milstr_ncpy(dp->str, arg->str, NELEMENTS(dp->str)); - return(dlglist_drawsub(hdl, arg->pos, (arg->pos == hdl->val))); -} - -static int dlglist_getpos(DLGHDL hdl, int y) { - - int val; - - val = (y / hdl->c.dl.fontsize) + hdl->c.dl.basepos; - if ((unsigned int)val < (unsigned int)hdl->prmcnt) { - return(val); - } - else { - return(-1); - } -} - -enum { - DLCUR_OUT = -1, - DLCUR_INLIST = 0, - DLCUR_UP = 1, - DLCUR_INBAR = 2, - DLCUR_DOWN = 3, - DLCUR_PGUP = 4, - DLCUR_PGDN = 5, - DLCUR_INCUR = 6 -}; - -static int dlglist_getpc(DLGHDL hdl, int x, int y) { - - if ((unsigned int)x >= (unsigned int)hdl->vram->width) { - goto dlgp_out; - } - if ((unsigned int)y >= (unsigned int)hdl->vram->height) { - goto dlgp_out; - } - - if ((hdl->prmcnt < hdl->c.dl.dispmax) || - (x < (hdl->vram->width - MENUDLG_CXVSCR))) { - return(DLCUR_INLIST); - } - else if (y < MENUDLG_CYVSCR) { - return(DLCUR_UP); - } - else if (y >= (hdl->vram->height - MENUDLG_CYVSCR)) { - return(DLCUR_DOWN); - } - y -= MENUDLG_CYVSCR; - y -= dlglist_barpos(hdl); - if (y < 0) { - return(DLCUR_PGUP); - } - else if (y < (int)hdl->c.dl.scrollbar) { - return(DLCUR_INBAR); - } - else { - return(DLCUR_PGDN); - } - -dlgp_out: - return(DLCUR_OUT); -} - -static void dlglist_setval(MENUDLG dlg, DLGHDL hdl, int val) { - - BOOL r; - - if ((unsigned int)val >= (unsigned int)hdl->prmcnt) { - val = -1; - } - if (val != hdl->val) { - r = dlglist_drawsub(hdl, hdl->val, FALSE); - r |= dlglist_drawsub(hdl, val, TRUE); - hdl->val = val; - if (r) { - drawctrls(dlg, hdl); - } - } -} - -static void dlglist_setbasepos(MENUDLG dlg, DLGHDL hdl, int pos) { - - int displimit; - - if (pos < 0) { - pos = 0; - } - else { - displimit = hdl->prmcnt - hdl->c.dl.dispmax; - if (displimit < 0) { - displimit = 0; - } - if (pos > displimit) { - pos = displimit; - } - } - if (hdl->c.dl.basepos != pos) { - hdl->c.dl.basepos = pos; - dlglist_drawall(hdl); - dlglist_drawbar(hdl); - } - (void)dlg; -} - -static void dlglist_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { - - int flg; - int val; - - x -= (MENU_LINE * 2); - y -= (MENU_LINE * 2); - flg = dlglist_getpc(hdl, x, y); - dlg->dragflg = flg; - switch(flg) { - case DLCUR_INLIST: - val = dlglist_getpos(hdl, y); - if ((val == hdl->val) && (val != -1)) { - dlg->dragflg = DLCUR_INCUR; - } - dlglist_setval(dlg, hdl, val); - dlg->proc(DLGMSG_COMMAND, hdl->id, 0); - break; - - case 1: - case 3: - dlglist_setbtn(hdl, flg); - dlglist_setbasepos(dlg, hdl, hdl->c.dl.basepos + flg - 2); - drawctrls(dlg, hdl); - break; - - case DLCUR_INBAR: - y -= MENUDLG_CYVSCR; - y -= dlglist_barpos(hdl); - if ((unsigned int)y < (unsigned int)hdl->c.dl.scrollbar) { - dlg->lasty = y; - } - else { - dlg->lasty = -1; - } - break; - - case DLCUR_PGUP: - dlglist_setbasepos(dlg, hdl, hdl->c.dl.basepos - - hdl->c.dl.dispmax); - drawctrls(dlg, hdl); - break; - - case DLCUR_PGDN: - dlglist_setbasepos(dlg, hdl, hdl->c.dl.basepos - + hdl->c.dl.dispmax); - drawctrls(dlg, hdl); - break; - } -} - -static void dlglist_move(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus) { - - int flg; - int val; - int height; - - x -= (MENU_LINE * 2); - y -= (MENU_LINE * 2); - flg = dlglist_getpc(hdl, x, y); - switch(dlg->dragflg) { - case DLCUR_INLIST: - case DLCUR_INCUR: - if (flg == DLCUR_INLIST) { - val = dlglist_getpos(hdl, y); - if (val != hdl->val) { - dlg->dragflg = DLCUR_INLIST; - dlglist_setval(dlg, hdl, val); - dlg->proc(DLGMSG_COMMAND, hdl->id, 0); - } - } - break; - - case 1: - case 3: - dlglist_setbtn(hdl, dlg->dragflg - ((dlg->dragflg == flg)?0:1)); - drawctrls(dlg, hdl); - break; - - case DLCUR_INBAR: - if (dlg->lasty >= 0) { - y -= MENUDLG_CYVSCR; - y -= dlg->lasty; - height = hdl->vram->height - (MENUDLG_CYVSCR * 2); - height -= hdl->c.dl.scrollbar; - if (y < 0) { - y = 0; - } - else if (y > height) { - y = height; - } - y *= (hdl->prmcnt - hdl->c.dl.dispmax); - y /= height; - dlglist_setbasepos(dlg, hdl, y); - drawctrls(dlg, hdl); - } - break; - } - (void)focus; -} - -static void dlglist_rel(MENUDLG dlg, DLGHDL hdl, int focus) { - - switch(dlg->dragflg) { - case 1: - case 3: - dlglist_setbtn(hdl, dlg->dragflg - 1); - drawctrls(dlg, hdl); - break; - - case DLCUR_INCUR: - dlg->proc(DLGMSG_COMMAND, hdl->id, 1); - break; - } - (void)focus; -} - - -// ---- slider - -static void dlgslider_setflag(DLGHDL hdl) { - - int size; - UINT type; - - if (!(hdl->flag & MSS_VERT)) { - size = hdl->rect.bottom - hdl->rect.top; - } - else { - size = hdl->rect.right - hdl->rect.left; - } - if (size < 13) { - type = 0 + (9 << 8) + (5 << 16); - } - else if (size < 21) { - type = 1 + (13 << 8) + (7 << 16); - } - else { - type = 2 + (21 << 8) + (11 << 16); - } - hdl->c.ds.type = (UINT8)type; - if (!(hdl->flag & MSS_VERT)) { - hdl->c.ds.sldh = (UINT8)(type >> 16); - hdl->c.ds.sldv = (UINT8)(type >> 8); - } - else { - hdl->c.ds.sldh = (UINT8)(type >> 8); - hdl->c.ds.sldv = (UINT8)(type >> 16); - } -} - -static int dlgslider_setpos(DLGHDL hdl, int val) { - - int range; - int width; - int dir; - - range = hdl->c.ds.maxval - hdl->c.ds.minval; - if (range) { - dir = (range > 0)?1:-1; - val -= hdl->c.ds.minval; - val *= dir; - range *= dir; - if (val < 0) { - val = 0; - } - else if (val >= range) { - val = range; - } - hdl->val = hdl->c.ds.minval + (val * dir); - if (!(hdl->flag & MSS_VERT)) { - width = hdl->rect.right - hdl->rect.left; - width -= hdl->c.ds.sldh; - } - else { - width = hdl->rect.bottom - hdl->rect.top; - width -= hdl->c.ds.sldv; - } - if ((width > 0) || (range)) { - val *= width; - val /= range; - } - else { - val = 0; - } - } - else { - val = 0; - } - return(val); -} - -static BRESULT dlgslider_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { - - hdl->c.ds.minval = (SINT16)(long)arg; - hdl->c.ds.maxval = (SINT16)((long)arg >> 16); - hdl->c.ds.moving = 0; - dlgslider_setflag(hdl); - hdl->c.ds.pos = dlgslider_setpos(hdl, 0); - (void)dlg; - return(SUCCESS); -} - -static void dlgslider_paint(MENUDLG dlg, DLGHDL hdl) { - - UINT flag; - int ptr; - RECT_U rct; - POINT_T pt; - MENURES2 src; - - flag = hdl->flag; - switch(flag & MSS_POSMASK) { - case MSS_BOTH: - ptr = 1; - break; - case MSS_TOP: - ptr = 2; - break; - default: - ptr = 0; - break; - } - vram_filldat(dlg->vram, &hdl->rect, menucolor[MVC_STATIC]); - if (!(hdl->flag & MSS_VERT)) { - rct.r.left = hdl->rect.left; - rct.r.right = hdl->rect.right; - rct.r.top = hdl->rect.top + ptr + - (hdl->c.ds.sldv / 2) - (MENU_LINE * 2); - rct.r.bottom = rct.r.top + (MENU_LINE * 4); - menuvram_box2(dlg->vram, &rct.r, - MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_DARK, MVC_LIGHT)); - pt.x = hdl->rect.left + hdl->c.ds.pos; - pt.y = hdl->rect.top; - } - else { - rct.r.left = hdl->rect.left + ptr + - (hdl->c.ds.sldh / 2) - (MENU_LINE * 2); - rct.r.right = rct.r.left + (MENU_LINE * 4); - rct.r.top = hdl->rect.top; - rct.r.bottom = hdl->rect.bottom; - menuvram_box2(dlg->vram, &rct.r, - MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_DARK, MVC_LIGHT)); - pt.x = hdl->rect.left; - pt.y = hdl->rect.top + hdl->c.ds.pos; - ptr += 3; - } - ptr *= 2; - if ((hdl->flag & MENU_GRAY) || (hdl->c.ds.moving)) { - ptr++; - } - src.width = hdl->c.ds.sldh; - src.height = hdl->c.ds.sldv; - src.pat = menures_slddat + menures_sldpos[hdl->c.ds.type][ptr]; - menuvram_res2put(dlg->vram, &src, &pt); -} - -static void dlgslider_setval(MENUDLG dlg, DLGHDL hdl, int val) { - - int pos; - - pos = dlgslider_setpos(hdl, val); - if (hdl->c.ds.pos != pos) { - hdl->c.ds.pos = pos; - drawctrls(dlg, hdl); - } -} - -static void dlgslider_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { - - int width; - int range; - int dir; - - if (!(hdl->flag & MSS_VERT)) { - width = hdl->c.ds.sldh; - } - else { - width = hdl->c.ds.sldv; - x = y; - } - x -= hdl->c.ds.pos; - if ((x >= -1) && (x <= width)) { - dlg->dragflg = x; - hdl->c.ds.moving = 1; - drawctrls(dlg, hdl); - } - else { - dlg->dragflg = -1; - dir = (x > 0)?1:0; - range = hdl->c.ds.maxval - hdl->c.ds.minval; - if (range < 0) { - range = 0 - range; - dir ^= 1; - } - if (range < 16) { - range = 16; - } - range >>= 4; - if (!dir) { - range = 0 - range; - } - dlgslider_setval(dlg, hdl, hdl->val + range); - dlg->proc(DLGMSG_COMMAND, hdl->id, 0); - } -} - -static void dlgslider_move(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus) { - - int range; - int width; - int dir; - - if (hdl->c.ds.moving) { - range = hdl->c.ds.maxval - hdl->c.ds.minval; - if (range) { - dir = (range > 0)?1:-1; - range *= dir; - if (!(hdl->flag & MSS_VERT)) { - width = hdl->rect.right - hdl->rect.left; - width -= hdl->c.ds.sldh; - } - else { - width = hdl->rect.bottom - hdl->rect.top; - width -= hdl->c.ds.sldv; - x = y; - } - x -= dlg->dragflg; - if ((x < 0) || (width <= 0)) { - x = 0; - } - else if (x >= width) { - x = range; - } - else { - x *= range; - x += (width >> 1); - x /= width; - } - x = hdl->c.ds.minval + (x * dir); - dlgslider_setval(dlg, hdl, x); - dlg->proc(DLGMSG_COMMAND, hdl->id, 0); - } - } - (void)focus; -} - - -static void dlgslider_rel(MENUDLG dlg, DLGHDL hdl, int focus) { - - if (hdl->c.ds.moving) { - hdl->c.ds.moving = 0; - drawctrls(dlg, hdl); - } - (void)focus; -} - - -// ---- tablist - -static void *dlgtablist_setfont(DLGHDL hdl, void *font) { - - void *ret; - POINT_T pt; - DLGPRM prm; - - ret = hdl->c.dtl.font; - hdl->c.dtl.font = font; - fontmng_getsize(font, mstr_fontcheck, &pt); - if ((pt.y <= 0) || (pt.y >= 65536)) { - pt.y = 16; - } - hdl->c.dtl.fontsize = pt.y; - prm = hdl->prm; - while(prm) { - fontmng_getsize(hdl->c.dtl.font, prm->str, &pt); - prm->width = pt.x; - prm = prm->next; - } - return(ret); -} - -static BRESULT dlgtablist_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { - - RECT_T rct; - - rct.right = hdl->rect.right - hdl->rect.left; - hdl->val = -1; - dlgtablist_setfont(hdl, dlg->font); - (void)arg; - return(SUCCESS); -} - -static void dlgtablist_paint(MENUDLG dlg, DLGHDL hdl) { - - VRAMHDL dst; - DLGPRM prm; - POINT_T pt; - RECT_T rct; - int posx; - int lx; - int cnt; - int tabey; - int tabdy; - - dst = dlg->vram; - rct = hdl->rect; - vram_filldat(dst, &rct, menucolor[MVC_STATIC]); - tabey = rct.top + hdl->c.dtl.fontsize + - MENUDLG_SYTAB + MENUDLG_TYTAB + MENUDLG_EYTAB; - rct.top = tabey; - menuvram_box2(dst, &rct, - MVC4(MVC_HILIGHT, MVC_DARK, MVC_LIGHT, MVC_SHADOW)); - - posx = hdl->rect.left + (MENU_LINE * 2); - prm = hdl->prm; - cnt = hdl->val; - while(prm) { - if (cnt) { - pt.x = posx; - pt.y = hdl->rect.top + MENUDLG_SYTAB; - menuvram_liney(dst, pt.x, pt.y + (MENU_LINE * 2), - tabey, MVC_HILIGHT); - pt.x += MENU_LINE; - menuvram_liney(dst, pt.x, pt.y + MENU_LINE, - pt.y + (MENU_LINE * 2), MVC_HILIGHT); - menuvram_liney(dst, pt.x, pt.y + (MENU_LINE * 2), - tabey, MVC_LIGHT); - pt.x += MENU_LINE; - lx = pt.x + prm->width + (MENUDLG_TXTAB * 2); - menuvram_linex(dst, pt.x, pt.y, lx, MVC_HILIGHT); - menuvram_linex(dst, pt.x, pt.y + MENU_LINE, lx, MVC_LIGHT); - - menuvram_liney(dst, lx, pt.y + MENU_LINE, - pt.y + (MENU_LINE * 2), MVC_DARK); - menuvram_liney(dst, lx, pt.y + (MENU_LINE * 2), - tabey, MVC_SHADOW); - lx++; - menuvram_liney(dst, lx, pt.y + (MENU_LINE * 2), - tabey, MVC_DARK); - pt.x += MENUDLG_TXTAB; - pt.y += MENUDLG_TYTAB; - vrammix_text(dst, hdl->c.dtl.font, prm->str, - menucolor[MVC_TEXT], &pt, NULL); - } - cnt--; - posx += prm->width + (MENU_LINE * 4) + (MENUDLG_TXTAB) * 2; - prm = prm->next; - } - - posx = hdl->rect.left; - prm = hdl->prm; - cnt = hdl->val; - while(prm) { - if (!cnt) { - pt.x = posx; - pt.y = hdl->rect.top; - if (posx == hdl->rect.left) { - tabdy = tabey + 2; - } - else { - tabdy = tabey + 1; - menuvram_linex(dst, pt.x, tabdy, - pt.x + (MENU_LINE * 2), MVC_STATIC); - } - menuvram_liney(dst, pt.x, pt.y + (MENU_LINE * 2), - tabdy, MVC_HILIGHT); - pt.x += MENU_LINE; - menuvram_liney(dst, pt.x, pt.y + MENU_LINE, - pt.y + (MENU_LINE * 2), MVC_HILIGHT); - menuvram_liney(dst, pt.x, pt.y + (MENU_LINE * 2), - tabdy, MVC_LIGHT); - pt.x += MENU_LINE; - lx = pt.x + prm->width + (MENU_LINE * 4) + (MENUDLG_TXTAB * 2); - menuvram_linex(dst, pt.x, pt.y, lx, MVC_HILIGHT); - menuvram_linex(dst, pt.x, pt.y + MENU_LINE, lx, MVC_LIGHT); - menuvram_linex(dst, pt.x, tabey, lx, MVC_STATIC); - menuvram_linex(dst, pt.x, tabey + MENU_LINE, lx, MVC_STATIC); - tabdy = tabey + 1; - menuvram_liney(dst, lx, pt.y + MENU_LINE, - pt.y + (MENU_LINE * 2), MVC_DARK); - menuvram_liney(dst, lx, pt.y + (MENU_LINE * 2), - tabdy, MVC_SHADOW); - lx++; - menuvram_liney(dst, lx, pt.y + (MENU_LINE * 2), - tabdy, MVC_DARK); - pt.x += MENUDLG_TXTAB + (MENU_LINE * 2); - pt.y += MENUDLG_TYTAB; - vrammix_text(dst, hdl->c.dtl.font, prm->str, - menucolor[MVC_TEXT], &pt, NULL); - break; - } - cnt--; - posx += prm->width + (MENU_LINE * 4) + (MENUDLG_TXTAB * 2); - prm = prm->next; - } -} - -static void dlgtablist_setval(MENUDLG dlg, DLGHDL hdl, int val) { - - if (hdl->val != val) { - hdl->val = val; - drawctrls(dlg, hdl); - } -} - -static void dlgtablist_append(MENUDLG dlg, DLGHDL hdl, const OEMCHAR *arg) { - - DLGPRM res; - DLGPRM *sto; - POINT_T pt; - - sto = &hdl->prm; - while(*sto) { - sto = &((*sto)->next); - } - res = resappend(dlg, arg); - if (res) { - *sto = res; - fontmng_getsize(hdl->c.dtl.font, (OEMCHAR *)arg, &pt); - res->width = pt.x; - hdl->prmcnt++; - } -} - -static void dlgtablist_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { - - DLGPRM prm; - int pos; - - if (y < (hdl->c.dtl.fontsize + - MENUDLG_SYTAB + MENUDLG_TYTAB + MENUDLG_EYTAB)) { - pos = 0; - prm = hdl->prm; - while(prm) { - x -= (MENU_LINE * 4); - if (x < 0) { - break; - } - x -= prm->width + (MENUDLG_TXTAB * 2); - if (x < 0) { - dlgtablist_setval(dlg, hdl, pos); - dlg->proc(DLGMSG_COMMAND, hdl->id, 0); - break; - } - pos++; - prm = prm->next; - } - } -} - - -// ---- edit - -static void dlgedit_paint(MENUDLG dlg, DLGHDL hdl) { - - RECT_T rct; - POINT_T pt; -const OEMCHAR *string; - - rct = hdl->rect; - menuvram_box2(dlg->vram, &rct, - MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_DARK, MVC_LIGHT)); - rct.left += (MENU_LINE * 2); - rct.top += (MENU_LINE * 2); - rct.right -= (MENU_LINE * 2); - rct.bottom -= (MENU_LINE * 2); - vram_filldat(dlg->vram, &rct, menucolor[ - (hdl->flag & MENU_GRAY)?MVC_STATIC:MVC_HILIGHT]); - if (hdl->prm == NULL) { - goto dged_exit; - } - string = hdl->prm->str; - if (string == NULL) { - goto dged_exit; - } - pt.x = rct.left + MENU_LINE; - pt.y = rct.top + MENU_LINE; - vrammix_text(dlg->vram, hdl->c.dt.font, string, - menucolor[MVC_TEXT], &pt, &rct); - -dged_exit: - return; -} - - -// ---- frame - -static void dlgframe_paint(MENUDLG dlg, DLGHDL hdl) { - - RECT_T rct; - POINT_T pt; - - rct.left = hdl->rect.left; - rct.top = hdl->rect.top + MENUDLG_SYFRAME; - rct.right = hdl->rect.right; - rct.bottom = hdl->rect.bottom; - menuvram_box2(dlg->vram, &rct, - MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_HILIGHT, MVC_SHADOW)); - rct.left += MENUDLG_SXFRAME; - rct.top = hdl->rect.top; - rct.right = rct.left + (MENUDLG_PXFRAME * 2) + hdl->c.dt.pt.x; - rct.bottom = rct.top + hdl->c.dt.pt.y + MENU_DSTEXT; - vram_filldat(dlg->vram, &rct, menucolor[MVC_STATIC]); - if (hdl->prm) { - pt.x = rct.left + MENUDLG_PXFRAME; - pt.y = rct.top; - dlg_text(dlg, hdl, &pt, &rct); - } -} - - -// ---- radio - -typedef struct { - MENUDLG dlg; - MENUID group; -} MDCB1; - -static void dlgradio_paint(MENUDLG dlg, DLGHDL hdl) { - - POINT_T pt; -const MENURES2 *src; - int pat; - - vram_filldat(dlg->vram, &hdl->rect, menucolor[MVC_STATIC]); - pt.x = hdl->rect.left; - pt.y = hdl->rect.top; - src = menures_radio; - pat = (hdl->flag & MENU_GRAY)?1:0; - menuvram_res2put(dlg->vram, src + pat, &pt); - if (hdl->val) { - menuvram_res3put(dlg->vram, src + 2, &pt, - (hdl->flag & MENU_GRAY)?MVC_GRAYTEXT1:MVC_TEXT); - } - pt.x += MENUDLG_SXRADIO; - dlg_text(dlg, hdl, &pt, &hdl->rect); -} - -static BOOL drsv_cb(void *vpItem, void *vpArg) { - - DLGHDL item; - - item = (DLGHDL)vpItem; - if ((item->type == DLGTYPE_RADIO) && (item->val) && - (item->group == ((MDCB1 *)vpArg)->group)) { - item->val = 0; - drawctrls(((MDCB1 *)vpArg)->dlg, item); - } - return(FALSE); -} - -static void dlgradio_setval(MENUDLG dlg, DLGHDL hdl, int val) { - - MDCB1 mdcb; - - if (hdl->val != val) { - if (val) { - mdcb.dlg = dlg; - mdcb.group = hdl->group; - listarray_enum(dlg->dlg, drsv_cb, &mdcb); - } - hdl->val = val; - drawctrls(dlg, hdl); - } -} - -static void dlgradio_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { - - if (x < (hdl->c.dt.pt.x + MENUDLG_SXRADIO)) { - dlgradio_setval(dlg, hdl, 1); - dlg->proc(DLGMSG_COMMAND, hdl->id, 0); - } - (void)y; -} - - -// ---- check - -static void dlgcheck_paint(MENUDLG dlg, DLGHDL hdl) { - - POINT_T pt; - RECT_T rct; - UINT32 basecol; - UINT32 txtcol; - - vram_filldat(dlg->vram, &hdl->rect, menucolor[MVC_STATIC]); - rct.left = hdl->rect.left; - rct.top = hdl->rect.top; - rct.right = rct.left + MENUDLG_CXCHECK; - rct.bottom = rct.top + MENUDLG_CYCHECK; - if (!(hdl->flag & MENU_GRAY)) { - basecol = MVC_HILIGHT; - txtcol = MVC_TEXT; - } - else { - basecol = MVC_STATIC; - txtcol = MVC_GRAYTEXT1; - } - vram_filldat(dlg->vram, &rct, menucolor[basecol]); - menuvram_box2(dlg->vram, &rct, - MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_DARK, MVC_LIGHT)); - if (hdl->val) { - pt.x = rct.left + (MENU_LINE * 2); - pt.y = rct.top + (MENU_LINE * 2); - menuvram_res3put(dlg->vram, &menures_check, &pt, txtcol); - } - pt.x = rct.left + MENUDLG_SXCHECK; - pt.y = rct.top; - dlg_text(dlg, hdl, &pt, &hdl->rect); -} - -static void dlgcheck_setval(MENUDLG dlg, DLGHDL hdl, int val) { - - if (hdl->val != val) { - hdl->val = val; - drawctrls(dlg, hdl); - } -} - -static void dlgcheck_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { - - if (x < (hdl->c.dt.pt.x + MENUDLG_SXCHECK)) { - dlgcheck_setval(dlg, hdl, !hdl->val); - dlg->proc(DLGMSG_COMMAND, hdl->id, 0); - } - (void)y; -} - - -// ---- text - -static void dlgtext_paint(MENUDLG dlg, DLGHDL hdl) { - - POINT_T sz; - POINT_T pt; - void (*getpt)(POINT_T *pt, const RECT_T *rect, const POINT_T *sz); - - vram_filldat(dlg->vram, &hdl->rect, menucolor[MVC_STATIC]); - if (gettextsz(hdl, &sz) == SUCCESS) { - switch(hdl->flag & MST_POSMASK) { - case MST_LEFT: - default: - getpt = getleft; - break; - - case MST_CENTER: - getpt = getcenter; - break; - - case MST_RIGHT: - getpt = getright; - break; - } - getpt(&pt, &hdl->rect, &sz); - dlg_text(dlg, hdl, &pt, &hdl->rect); - } -} - -static void dlgtext_itemset(MENUDLG dlg, DLGHDL hdl, const OEMCHAR *str) { - - if (hdl->prm) { - if (str == NULL) { - str = str_null; - } - milstr_ncpy(hdl->prm->str, str, NELEMENTS(hdl->prm->str)); - fontmng_getsize(hdl->c.dt.font, str, &hdl->c.dt.pt); - } - (void)dlg; -} - -static void dlgtext_iconset(MENUDLG dlg, DLGHDL hdl, UINT arg) { - - if (hdl->prm) { - resattachicon(dlg, hdl->prm, (UINT16)arg, hdl->c.dt.pt.y, hdl->c.dt.pt.y); - } - (void)dlg; -} - - -// ---- icon/vram - -static void iconpaint(MENUDLG dlg, DLGHDL hdl, VRAMHDL src) { - - RECT_U r; - UINT32 bgcol; - - r.p.x = hdl->rect.left; - r.p.y = hdl->rect.top; - bgcol = menucolor[MVC_STATIC]; - if (src) { - if (src->alpha) { - r.r.right = r.r.left + src->width; - r.r.bottom = r.r.top + src->height; - vram_filldat(dlg->vram, &r.r, bgcol); - vramcpy_cpyex(dlg->vram, &r.p, src, NULL); - } - else { - vramcpy_cpy(dlg->vram, &r.p, src, NULL); - } - } - else { - vram_filldat(dlg->vram, &hdl->rect, bgcol); - } -} - -static BRESULT dlgicon_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { - - hdl->prm = resappend(dlg, NULL); - resattachicon(dlg, hdl->prm, (UINT16)(long)arg, - hdl->rect.right - hdl->rect.left, hdl->rect.bottom - hdl->rect.top); - return(SUCCESS); -} - -static void dlgicon_paint(MENUDLG dlg, DLGHDL hdl) { - - DLGPRM prm; - - prm = hdl->prm; - if (prm) { - iconpaint(dlg, hdl, prm->icon); - } -} - -static BRESULT dlgvram_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { - - hdl->c.dv.vram = (VRAMHDL)arg; - (void)dlg; - return(SUCCESS); -} - -static void dlgvram_paint(MENUDLG dlg, DLGHDL hdl) { - - iconpaint(dlg, hdl, hdl->c.dv.vram); -} - - -// ---- line - -static void dlgline_paint(MENUDLG dlg, DLGHDL hdl) { - - if (!(hdl->flag & MSL_VERT)) { - menuvram_linex(dlg->vram, hdl->rect.left, hdl->rect.top, - hdl->rect.right, MVC_SHADOW); - menuvram_linex(dlg->vram, hdl->rect.left, hdl->rect.top + MENU_LINE, - hdl->rect.right, MVC_HILIGHT); - } - else { - menuvram_liney(dlg->vram, hdl->rect.left, hdl->rect.top, - hdl->rect.bottom, MVC_SHADOW); - menuvram_liney(dlg->vram, hdl->rect.left+MENU_LINE, hdl->rect.top, - hdl->rect.bottom, MVC_HILIGHT); - } -} - - -// ---- box - -static void dlgbox_paint(MENUDLG dlg, DLGHDL hdl) { - - menuvram_box2(dlg->vram, &hdl->rect, - MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_HILIGHT, MVC_SHADOW)); -} - - -// ---- procs - -static BRESULT _cre(MENUDLG dlg, DLGHDL hdl, const void *arg) { - - (void)dlg; - (void)hdl; - (void)arg; - return(SUCCESS); -} - -#if 0 // not used -static void _paint(MENUDLG dlg, DLGHDL hdl) { - - (void)dlg; - (void)hdl; -} -#endif - -#if 0 // not used -static void _onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { - - (void)dlg; - (void)hdl; - (void)x; - (void)y; -} -#endif - -static void _setval(MENUDLG dlg, DLGHDL hdl, int val) { - - (void)dlg; - (void)hdl; - (void)val; -} - -static void _moverel(MENUDLG dlg, DLGHDL hdl, int focus) { - - (void)dlg; - (void)hdl; - (void)focus; -} - -typedef BRESULT (*DLGCRE)(MENUDLG dlg, DLGHDL hdl, const void *arg); -typedef void (*DLGPAINT)(MENUDLG dlg, DLGHDL hdl); -typedef void (*DLGSETVAL)(MENUDLG dlg, DLGHDL hdl, int val); -typedef void (*DLGCLICK)(MENUDLG dlg, DLGHDL hdl, int x, int y); -typedef void (*DLGMOV)(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus); -typedef void (*DLGREL)(MENUDLG dlg, DLGHDL hdl, int focus); - -static const DLGCRE dlgcre[] = { - dlgbase_create, // DLGTYPE_BASE - _cre, // DLGTYPE_CLOSE - _cre_settext, // DLGTYPE_BUTTON - dlglist_create, // DLGTYPE_LIST - dlgslider_create, // DLGTYPE_SLIDER - dlgtablist_create, // DLGTYPE_TABLIST - _cre_settext, // DLGTYPE_RADIO - _cre_settext, // DLGTYPE_CHECK - _cre_settext, // DLGTYPE_FRAME - _cre_settext, // DLGTYPE_EDIT - _cre_settext, // DLGTYPE_TEXT - dlgicon_create, // DLGTYPE_ICON - dlgvram_create, // DLGTYPE_VRAM - _cre, // DLGTYPE_LINE - _cre // DLGTYPE_BOX -}; - -static const DLGPAINT dlgpaint[] = { - dlgbase_paint, // DLGTYPE_BASE - dlgclose_paint, // DLGTYPE_CLOSE - dlgbtn_paint, // DLGTYPE_BUTTON - dlglist_paint, // DLGTYPE_LIST - dlgslider_paint, // DLGTYPE_SLIDER - dlgtablist_paint, // DLGTYPE_TABLIST - dlgradio_paint, // DLGTYPE_RADIO - dlgcheck_paint, // DLGTYPE_CHECK - dlgframe_paint, // DLGTYPE_FRAME - dlgedit_paint, // DLGTYPE_EDIT - dlgtext_paint, // DLGTYPE_TEXT - dlgicon_paint, // DLGTYPE_ICON - dlgvram_paint, // DLGTYPE_VRAM - dlgline_paint, // DLGTYPE_LINE - dlgbox_paint // DLGTYPE_BOX -}; - -static const DLGSETVAL dlgsetval[] = { - _setval, // DLGTYPE_BASE - _setval, // DLGTYPE_CLOSE - _setval, // DLGTYPE_BUTTON - dlglist_setval, // DLGTYPE_LIST - dlgslider_setval, // DLGTYPE_SLIDER - dlgtablist_setval, // DLGTYPE_TABLIST - dlgradio_setval, // DLGTYPE_RADIO - dlgcheck_setval // DLGTYPE_CHECK -}; - -static const DLGCLICK dlgclick[] = { - dlgbase_onclick, // DLGTYPE_BASE - dlgclose_onclick, // DLGTYPE_CLOSE - dlgbtn_onclick, // DLGTYPE_BUTTON - dlglist_onclick, // DLGTYPE_LIST - dlgslider_onclick, // DLGTYPE_SLIDER - dlgtablist_onclick, // DLGTYPE_TABLIST - dlgradio_onclick, // DLGTYPE_RADIO - dlgcheck_onclick // DLGTYPE_CHECK -}; - -static const DLGMOV dlgmov[] = { - dlgbase_move, // DLGTYPE_BASE - dlgclose_move, // DLGTYPE_CLOSE - dlgbtn_move, // DLGTYPE_BUTTON - dlglist_move, // DLGTYPE_LIST - dlgslider_move // DLGTYPE_SLIDER -}; - -static const DLGREL dlgrel[] = { - _moverel, // DLGTYPE_BASE - dlgclose_rel, // DLGTYPE_CLOSE - dlgbtn_rel, // DLGTYPE_BUTTON - dlglist_rel, // DLGTYPE_LIST - dlgslider_rel // DLGTYPE_SLIDER -}; - - -// ---- draw - -static void draw(VRAMHDL dst, const RECT_T *rect, void *arg) { - - MENUDLG dlg; - - dlg = (MENUDLG)arg; - vrammix_cpy2(dst, rect, dlg->vram, NULL, 2); -} - - -typedef struct { - MENUDLG dlg; - DLGHDL hdl; - RECT_T rect; -} MDCB2; - -static BOOL dc_cb(void *vpItem, void *vpArg) { - - DLGHDL hdl; - MDCB2 *mdcb; - - hdl = (DLGHDL)vpItem; - mdcb = (MDCB2 *)vpArg; - if (hdl == mdcb->hdl) { - mdcb->hdl = NULL; - } - if ((mdcb->hdl != NULL) || (hdl->flag & MENU_DISABLE)) { - goto dccb_exit; - } - if (rect_isoverlap(&mdcb->rect, &hdl->rect)) { - hdl->flag |= MENU_REDRAW; - } - -dccb_exit: - return(FALSE); -} - - -static BOOL dc_cb2(void *vpItem, void *vpArg) { - - MENUDLG dlg; - DLGHDL hdl; - - hdl = (DLGHDL)vpItem; - dlg = (MENUDLG)vpArg; - if (hdl->flag & MENU_REDRAW) { - hdl->flag &= ~MENU_REDRAW; - if ((!(hdl->flag & MENU_DISABLE)) && - ((UINT)hdl->type < NELEMENTS(dlgpaint))) { - dlgpaint[hdl->type](dlg, hdl); - menubase_setrect(dlg->vram, &hdl->rect); - } - } - return(FALSE); -} - - -static void drawctrls(MENUDLG dlg, DLGHDL hdl) { - - MDCB2 mdcb; - - if (hdl) { - if (hdl->flag & MENU_DISABLE) { - goto dcs_end; - } - mdcb.rect = hdl->rect; - } - else { - mdcb.rect.left = 0; - mdcb.rect.top = 0; - mdcb.rect.right = dlg->vram->width; - mdcb.rect.bottom = dlg->vram->height; - } - mdcb.dlg = dlg; - mdcb.hdl = hdl; - listarray_enum(dlg->dlg, dc_cb, &mdcb); - if (!dlg->locked) { - listarray_enum(dlg->dlg, dc_cb2, dlg); - menubase_draw(draw, dlg); - } - -dcs_end: - return; -} - -static void drawlock(BOOL lock) { - - MENUDLG dlg; - - dlg = &menudlg; - if (lock) { - dlg->locked++; - } - else { - dlg->locked--; - if (!dlg->locked) { - listarray_enum(dlg->dlg, dc_cb2, dlg); - menubase_draw(draw, dlg); - } - } -} - - -// ---- - -static int defproc(int msg, MENUID id, long param) { - - if (msg == DLGMSG_CLOSE) { - menubase_close(); - } - (void)id; - (void)param; - return(0); -} - - -BRESULT menudlg_create(int width, int height, const OEMCHAR *str, - int (*proc)(int msg, MENUID id, long param)) { - - MENUBASE *mb; - MENUDLG dlg; - - dlg = &menudlg; - if (menubase_open(2) != SUCCESS) { - goto mdcre_err; - } - ZeroMemory(dlg, sizeof(_MENUDLG)); - if ((width <= 0) || (height <= 0)) { - goto mdcre_err; - } - width += (MENU_FBORDER + MENU_BORDER) * 2; - height += ((MENU_FBORDER + MENU_BORDER) * 2) + - MENUDLG_CYCAPTION + MENUDLG_BORDER; - mb = &menubase; - dlg->font = mb->font; - dlg->vram = vram_create(width, height, FALSE, mb->bpp); - if (dlg->vram == NULL) { - goto mdcre_err; - } - dlg->vram->posx = (mb->width - width) >> 1; - dlg->vram->posy = (mb->height - height) >> 1; - dlg->dlg = listarray_new(sizeof(_DLGHDL), 32); - if (dlg->dlg == NULL) { - goto mdcre_err; - } - dlg->res = listarray_new(sizeof(_DLGPRM), 32); - if (dlg->res == NULL) { - goto mdcre_err; - } - if (menudlg_append(DLGTYPE_BASE, SID_CAPTION, 0, str, - 0, 0, width, height) != SUCCESS) { - goto mdcre_err; - } - if (menudlg_append(DLGTYPE_CLOSE, SID_CLOSE, 0, NULL, - width - (MENU_FBORDER + MENU_BORDER) - - (MENUDLG_CXCLOSE + MENUDLG_PXCAPTION), - (MENU_FBORDER + MENU_BORDER) + - ((MENUDLG_CYCAPTION - MENUDLG_CYCLOSE) / 2), - MENUDLG_CXCLOSE, MENUDLG_CYCLOSE) != SUCCESS) { - goto mdcre_err; - } - dlg->sx = (MENU_FBORDER + MENU_BORDER); - dlg->sy = (MENU_FBORDER + MENU_BORDER) + - (MENUDLG_CYCAPTION + MENUDLG_BORDER); - if (proc == NULL) { - proc = defproc; - } - dlg->proc = proc; - dlg->locked = 0; - drawlock(TRUE); - proc(DLGMSG_CREATE, 0, 0); - drawctrls(dlg, NULL); - drawlock(FALSE); - - return(SUCCESS); - -mdcre_err: - menubase_close(); - return(FAILURE); -} - - -static BOOL mdds_cb(void *vpItem, void *vpArg) { - - vram_destroy(((DLGHDL)vpItem)->vram); - (void)vpArg; - return(FALSE); -} - -static BOOL delicon(void *vpItem, void *vpArg) { - - menuicon_unlock(((DLGPRM)vpItem)->icon); - (void)vpArg; - return(FALSE); -} - -void menudlg_destroy(void) { - - MENUDLG dlg; - - dlg = &menudlg; - - if (dlg->closing) { - return; - } - dlg->closing = 1; - dlg->proc(DLGMSG_DESTROY, 0, 0); - listarray_enum(dlg->dlg, mdds_cb, NULL); - menubase_clrrect(dlg->vram); - vram_destroy(dlg->vram); - dlg->vram = NULL; - listarray_destroy(dlg->dlg); - dlg->dlg = NULL; - listarray_enum(dlg->res, delicon, NULL); - listarray_destroy(dlg->res); - dlg->res = NULL; -} - - -// ---- - -BRESULT menudlg_appends(const MENUPRM *res, int count) { - - BRESULT r; - - r = SUCCESS; - while(count--) { - r |= menudlg_append(res->type, res->id, res->flg, res->arg, - res->posx, res->posy, res->width, res->height); - res++; - } - return(r); -} - -BRESULT menudlg_append(int type, MENUID id, MENUFLG flg, const void *arg, - int posx, int posy, int width, int height) { - - MENUDLG dlg; - DLGHDL hdl; - _DLGHDL dhdl; - - dlg = &menudlg; - - if (flg & MENU_TABSTOP) { - dlg->group++; - } - switch(type) { - case DLGTYPE_LTEXT: - type = DLGTYPE_TEXT; - flg &= ~MST_POSMASK; - flg |= MST_LEFT; - break; - - case DLGTYPE_CTEXT: - type = DLGTYPE_TEXT; - flg &= ~MST_POSMASK; - flg |= MST_CENTER; - break; - - case DLGTYPE_RTEXT: - type = DLGTYPE_TEXT; - flg &= ~MST_POSMASK; - flg |= MST_RIGHT; - break; - } - - ZeroMemory(&dhdl, sizeof(dhdl)); - dhdl.type = type; - dhdl.id = id; - dhdl.flag = flg; - dhdl.page = dlg->page; - dhdl.group = dlg->group; - dhdl.rect.left = dlg->sx + posx; - dhdl.rect.top = dlg->sy + posy; - dhdl.rect.right = dhdl.rect.left + width; - dhdl.rect.bottom = dhdl.rect.top + height; - dhdl.prm = NULL; - dhdl.prmcnt = 0; - dhdl.val = 0; - if (((UINT)type >= NELEMENTS(dlgcre)) || - (dlgcre[type](dlg, &dhdl, arg))) { - goto mda_err; - } - drawlock(TRUE); - hdl = (DLGHDL)listarray_append(dlg->dlg, &dhdl); - drawctrls(dlg, hdl); - drawlock(FALSE); - return(SUCCESS); - -mda_err: - return(FAILURE); -} - - -// ---- moving - -typedef struct { - int x; - int y; - DLGHDL ret; -} MDCB3; - -static BOOL hps_cb(void *vpItem, void *vpArg) { - - DLGHDL hdl; - MDCB3 *mdcb; - - hdl = (DLGHDL)vpItem; - mdcb = (MDCB3 *)vpArg; - if ((!(hdl->flag & (MENU_DISABLE | MENU_GRAY))) && - (rect_in(&hdl->rect, mdcb->x, mdcb->y))) { - mdcb->ret = hdl; - } - return(FALSE); -} - -static DLGHDL hdlpossea(MENUDLG dlg, int x, int y) { - - MDCB3 mdcb; - - mdcb.x = x; - mdcb.y = y; - mdcb.ret = NULL; - listarray_enum(dlg->dlg, hps_cb, &mdcb); - return(mdcb.ret); -} - -void menudlg_moving(int x, int y, int btn) { - - MENUDLG dlg; - DLGHDL hdl; - int focus; - - drawlock(TRUE); - dlg = &menudlg; - x -= dlg->vram->posx; - y -= dlg->vram->posy; - if (!dlg->btn) { - if (btn == 1) { - hdl = hdlpossea(dlg, x, y); - if (hdl) { - x -= hdl->rect.left; - y -= hdl->rect.top; - dlg->btn = 1; - dlg->lastid = hdl->id; - if ((UINT)hdl->type < NELEMENTS(dlgclick)) { - dlgclick[hdl->type](dlg, hdl, x, y); - } - } - } - } - else { - hdl = dlghdlsea(dlg, dlg->lastid); - if (hdl) { - focus = rect_in(&hdl->rect, x, y); - x -= hdl->rect.left; - y -= hdl->rect.top; - if ((UINT)hdl->type < NELEMENTS(dlgmov)) { - dlgmov[hdl->type](dlg, hdl, x, y, focus); - } - if (btn == 2) { - dlg->btn = 0; - if ((UINT)hdl->type < NELEMENTS(dlgrel)) { - dlgrel[hdl->type](dlg, hdl, focus); - } - } - } - } - drawlock(FALSE); -} - - -// ---- ctrl - -INTPTR menudlg_msg(int ctrl, MENUID id, INTPTR arg) { - - INTPTR ret; - MENUDLG dlg; - DLGHDL hdl; - int flg; - - ret = 0; - dlg = &menudlg; - hdl = dlghdlsea(dlg, id); - if (hdl == NULL) { - goto mdm_exit; - } - drawlock(TRUE); - switch(ctrl) { - case DMSG_SETHIDE: - ret = (hdl->flag & MENU_DISABLE) ? 1 : 0; - flg = (arg) ? MENU_DISABLE : 0; - if ((hdl->flag ^ flg) & MENU_DISABLE) { - hdl->flag ^= MENU_DISABLE; - if (flg) { - drawctrls(dlg, NULL); - } - else { - drawctrls(dlg, hdl); - } - } - break; - - case DMSG_GETHIDE: - ret = (hdl->flag & MENU_DISABLE) ? 1 : 0; - break; - - case DMSG_SETENABLE: - ret = (hdl->flag & MENU_GRAY) ? 0 : 1; - flg = (arg) ? 0 : MENU_GRAY; - if ((hdl->flag ^ flg) & MENU_GRAY) { - hdl->flag ^= MENU_GRAY; - drawctrls(dlg, hdl); - } - break; - - case DMSG_GETENABLE: - ret = (hdl->flag & MENU_GRAY) ? 0 : 1; - break; - - case DMSG_SETVAL: - ret = hdl->val; - if ((UINT)hdl->type < NELEMENTS(dlgsetval)) { - dlgsetval[hdl->type](dlg, hdl, (int)arg); - } - break; - - case DMSG_GETVAL: - ret = hdl->val; - break; - - case DMSG_SETVRAM: - if (hdl->type == DLGTYPE_VRAM) { - ret = (INTPTR)hdl->c.dv.vram; - hdl->c.dv.vram = (VRAMHDL)arg; - drawctrls(dlg, hdl); - } - break; - - case DMSG_SETTEXT: - switch(hdl->type) { - case DLGTYPE_BUTTON: - case DLGTYPE_RADIO: - case DLGTYPE_CHECK: - case DLGTYPE_EDIT: - case DLGTYPE_TEXT: - dlgtext_itemset(dlg, hdl, (OEMCHAR*)arg); - drawctrls(dlg, hdl); - break; - } - break; - - case DMSG_SETICON: - switch(hdl->type) { - case DLGTYPE_BUTTON: - case DLGTYPE_RADIO: - case DLGTYPE_CHECK: - case DLGTYPE_EDIT: - case DLGTYPE_TEXT: - dlgtext_iconset(dlg, hdl, (UINT)arg); - drawctrls(dlg, hdl); - break; - } - break; - - case DMSG_ITEMAPPEND: - switch(hdl->type) { - case DLGTYPE_LIST: - if (dlglist_append(dlg, hdl, (OEMCHAR*)arg)) { - drawctrls(dlg, hdl); - } - break; - - case DLGTYPE_TABLIST: - dlgtablist_append(dlg, hdl, (OEMCHAR*)arg); - drawctrls(dlg, hdl); - break; - } - break; - - case DMSG_ITEMRESET: - if ((dlg->btn) && (dlg->lastid == hdl->id)) { - dlg->btn = 0; - if ((UINT)hdl->type < NELEMENTS(dlgrel)) { - dlgrel[hdl->type](dlg, hdl, FALSE); - } - } - if (hdl->type == DLGTYPE_LIST) { - dlglist_reset(dlg, hdl); - drawctrls(dlg, hdl); - } - break; - - case DMSG_ITEMSETEX: - if (hdl->type == DLGTYPE_LIST) { - if (dlglist_setex(dlg, hdl, (ITEMEXPRM *)arg)) { - drawctrls(dlg, hdl); - } - } - break; - - case DMSG_SETLISTPOS: - if (hdl->type == DLGTYPE_LIST) { - ret = hdl->c.dl.basepos; - dlglist_setbasepos(dlg, hdl, (int)arg); - drawctrls(dlg, hdl); - } - break; - - case DMSG_GETRECT: - ret = (INTPTR)&hdl->rect; - break; - - case DMSG_SETRECT: - ret = (INTPTR)&hdl->rect; - if ((hdl->type == DLGTYPE_TEXT) && (arg)) { - drawctrls(dlg, hdl); - hdl->rect = *(RECT_T *)arg; - drawctrls(dlg, hdl); - } - break; - - case DMSG_SETFONT: - if (hdl->type == DLGTYPE_LIST) { - ret = (INTPTR)dlglist_setfont(hdl, (void*)arg); - drawctrls(dlg, hdl); - } - else if (hdl->type == DLGTYPE_TABLIST) { - ret = (INTPTR)dlgtablist_setfont(hdl, (void*)arg); - drawctrls(dlg, hdl); - } - else if (hdl->type == DLGTYPE_TEXT) { - ret = (INTPTR)hdl->c.dt.font; - hdl->c.dt.font = (void*)arg; - drawctrls(dlg, hdl); - } - break; - - case DMSG_GETFONT: - if (hdl->type == DLGTYPE_LIST) { - ret = (INTPTR)hdl->c.dl.font; - } - else if (hdl->type == DLGTYPE_TABLIST) { - ret = (INTPTR)hdl->c.dtl.font; - } - else if (hdl->type == DLGTYPE_TEXT) { - ret = (INTPTR)hdl->c.dt.font; - } - break; - - } - drawlock(FALSE); - -mdm_exit: - return(ret); -} - - -// --- page - -void menudlg_setpage(MENUID page) { - - MENUDLG dlg; - - dlg = &menudlg; - dlg->page = page; -} - - -typedef struct { - MENUID page; - MENUFLG flag; -} MDCB4; - -static BOOL mddph_cb(void *vpItem, void *vpArg) { - - DLGHDL hdl; - MDCB4 *mdcb; - - hdl = (DLGHDL)vpItem; - mdcb = (MDCB4 *)vpArg; - if ((hdl->page == mdcb->page) && - ((hdl->flag ^ mdcb->flag) & MENU_DISABLE)) { - hdl->flag ^= MENU_DISABLE; - } - return(FALSE); -} - -void menudlg_disppagehidden(MENUID page, BOOL hidden) { - - MENUDLG dlg; - MDCB4 mdcb; - - dlg = &menudlg; - mdcb.page = page; - mdcb.flag = (hidden)?MENU_DISABLE:0; - listarray_enum(dlg->dlg, mddph_cb, &mdcb); - drawlock(TRUE); - drawctrls(dlg, NULL); - drawlock(FALSE); -} - +#include +#include +#include +#include +#include +#include "menudeco.inc" +#include + + +typedef struct _dprm { +struct _dprm *next; + UINT16 width; + UINT16 num; + VRAMHDL icon; + OEMCHAR str[96]; +} _DLGPRM, *DLGPRM; + +#define PRMNEXT_EMPTY ((DLGPRM)-1) + +typedef struct { + POINT_T pt; + void *font; +} DLGTEXT; + +typedef struct { + void *font; + int fontsize; +} DLGTAB; + +typedef struct { + void *font; + SINT16 fontsize; + SINT16 scrollbar; + SINT16 dispmax; + SINT16 basepos; +} DLGLIST; + +typedef struct { + SINT16 minval; + SINT16 maxval; + int pos; + UINT8 type; + UINT8 moving; + UINT8 sldh; + UINT8 sldv; +} DLGSLD; + +typedef struct { + VRAMHDL vram; +} DLGVRAM; + +typedef struct _ditem { + int type; + MENUID id; + MENUFLG flag; + MENUID page; + MENUID group; + RECT_T rect; + DLGPRM prm; + int prmcnt; + int val; + VRAMHDL vram; + union { + DLGTEXT dt; + DLGTAB dtl; + DLGLIST dl; + DLGSLD ds; + DLGVRAM dv; + } c; +} _DLGHDL, *DLGHDL; + +typedef struct { + VRAMHDL vram; + LISTARRAY dlg; + LISTARRAY res; + int locked; + int closing; + int sx; + int sy; + void *font; + MENUID page; + MENUID group; + int (*proc)(int msg, MENUID id, long param); + + int dragflg; + int btn; + int lastx; + int lasty; + MENUID lastid; +} _MENUDLG, *MENUDLG; + + +static _MENUDLG menudlg; + +static void drawctrls(MENUDLG dlg, DLGHDL hdl); + + +// ---- + +static BOOL seaprmempty(void *vpItem, void *vpArg) { + + if (((DLGPRM)vpItem)->next == PRMNEXT_EMPTY) { + menuicon_unlock(((DLGPRM)vpItem)->icon); + ((DLGPRM)vpItem)->icon = NULL; + return(TRUE); + } + (void)vpArg; + return(FALSE); +} + +static DLGPRM resappend(MENUDLG dlg, const OEMCHAR *str) { + + DLGPRM prm; + + prm = (DLGPRM)listarray_enum(dlg->res, seaprmempty, NULL); + if (prm == NULL) { + prm = (DLGPRM)listarray_append(dlg->res, NULL); + } + if (prm) { + prm->next = NULL; + prm->width = 0; + prm->num = 0; + prm->icon = NULL; + prm->str[0] = '\0'; + if (str) { + milstr_ncpy(prm->str, str, NELEMENTS(prm->str)); + } + } + return(prm); +} + +static void resattachicon(MENUDLG dlg, DLGPRM prm, UINT16 icon, + int width, int height) { + + if (prm) { + menuicon_unlock(prm->icon); + prm->num = icon; + prm->icon = menuicon_lock(icon, width, height, dlg->vram->bpp); + } +} + +static DLGPRM ressea(DLGHDL hdl, int pos) { + + DLGPRM prm; + + if (pos >= 0) { + prm = hdl->prm; + while(prm) { + if (!pos) { + return(prm); + } + pos--; + prm = prm->next; + } + } + return(NULL); +} + +static BOOL dsbyid(void *vpItem, void *vpArg) { + + if (((DLGHDL)vpItem)->id == (MENUID)(unsigned long)vpArg) { + return(TRUE); + } + return(FALSE); +} + +static DLGHDL dlghdlsea(MENUDLG dlg, MENUID id) { + + return((DLGHDL)listarray_enum(dlg->dlg, dsbyid, (void *)(long)id)); +} + +static BRESULT gettextsz(DLGHDL hdl, POINT_T *sz) { + + DLGPRM prm; + + prm = hdl->prm; + if (prm == NULL) { + goto gts_err; + } + *sz = hdl->c.dt.pt; + if (prm->icon) { + if (sz->x) { +#if defined(NP2_SIZE_QVGA) + sz->x += 1; +#else + sz->x += 2; +#endif + } + sz->x += sz->y; + } + return(SUCCESS); + +gts_err: + return(FAILURE); +} + +static void getleft(POINT_T *pt, const RECT_T *rect, const POINT_T *sz) { + + pt->x = rect->left; + pt->y = rect->top; + (void)sz; +} + +static void getcenter(POINT_T *pt, const RECT_T *rect, const POINT_T *sz) { + + pt->x = rect->left; + pt->x += (rect->right - rect->left - sz->x) >> 1; + pt->y = rect->top; +} + +static void getright(POINT_T *pt, const RECT_T *rect, const POINT_T *sz) { + + pt->x = rect->right - sz->x - MENU_DSTEXT; + pt->y = rect->top; +} + +static void getmid(POINT_T *pt, const RECT_T *rect, const POINT_T *sz) { + + pt->x = rect->left; + pt->x += (rect->right - rect->left - sz->x) >> 1; + pt->y = rect->top; + pt->y += (rect->bottom - rect->top - sz->y) >> 1; +} + + +static BRESULT _cre_settext(MENUDLG dlg, DLGHDL hdl, const void *arg) { + +const OEMCHAR *str; + + str = (OEMCHAR *)arg; + if (str == NULL) { + str = str_null; + } + hdl->prm = resappend(dlg, str); + hdl->c.dt.font = dlg->font; + fontmng_getsize(dlg->font, str, &hdl->c.dt.pt); + return(SUCCESS); +} + +static void dlg_text(MENUDLG dlg, DLGHDL hdl, + const POINT_T *pt, const RECT_T *rect) { + + VRAMHDL icon; +const OEMCHAR *string; + int color; + POINT_T fp; + POINT_T p; + + if (hdl->prm == NULL) { + return; + } + fp = *pt; + icon = hdl->prm->icon; + if (icon) { + if (icon->alpha) { + vramcpy_cpyex(dlg->vram, &fp, icon, NULL); + } + else { + vramcpy_cpy(dlg->vram, &fp, icon, NULL); + } + fp.x += icon->width; +#if defined(NP2_SIZE_QVGA) + fp.x += 1; +#else + fp.x += 2; +#endif + } + string = hdl->prm->str; + if (string) { + if (!(hdl->flag & MENU_GRAY)) { + color = MVC_TEXT; + } + else { + p.x = fp.x + MENU_DSTEXT; + p.y = fp.y + MENU_DSTEXT; + vrammix_text(dlg->vram, hdl->c.dt.font, string, + menucolor[MVC_GRAYTEXT2], &p, rect); + color = MVC_GRAYTEXT1; + } + vrammix_text(dlg->vram, hdl->c.dt.font, string, + menucolor[color], &fp, rect); + } +} + + +// ---- base + +static BRESULT dlgbase_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { + + RECT_T rct; + + rct.right = hdl->rect.right - hdl->rect.left - + ((MENU_FBORDER + MENU_BORDER) * 2); + hdl->vram = vram_create(rct.right, MENUDLG_CYCAPTION, FALSE, menubase.bpp); + if (hdl->vram == NULL) { + goto dbcre_err; + } + hdl->vram->posx = (MENU_FBORDER + MENU_BORDER); + hdl->vram->posy = (MENU_FBORDER + MENU_BORDER); + rct.left = 0; + rct.top = 0; + rct.bottom = MENUDLG_CYCAPTION; + menuvram_caption(hdl->vram, &rct, MICON_NULL, (OEMCHAR *)arg); + return(SUCCESS); + +dbcre_err: + (void)dlg; + return(FAILURE); +} + + +static void dlgbase_paint(MENUDLG dlg, DLGHDL hdl) { + + OEMCHAR *title; + + title = NULL; + if (hdl->prm) { + title = hdl->prm->str; + } + menuvram_base(dlg->vram); + vrammix_cpy(dlg->vram, NULL, hdl->vram, NULL); + menubase_setrect(dlg->vram, NULL); +} + + +static void dlgbase_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { + + RECT_T rct; + + vram_getrect(hdl->vram, &rct); + dlg->dragflg = rect_in(&rct, x, y); + dlg->lastx = x; + dlg->lasty = y; +} + + +static void dlgbase_move(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus) { + + if (dlg->dragflg) { + x -= dlg->lastx; + y -= dlg->lasty; + if ((x) || (y)) { + menubase_clrrect(dlg->vram); + dlg->vram->posx += x; + dlg->vram->posy += y; + menubase_setrect(dlg->vram, NULL); + } + } + (void)hdl; + (void)focus; +} + + +// ---- close + +static void dlgclose_paint(MENUDLG dlg, DLGHDL hdl) { + + menuvram_closebtn(dlg->vram, &hdl->rect, hdl->val); +} + + +static void dlgclose_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { + + hdl->val = 1; + drawctrls(dlg, hdl); + (void)x; + (void)y; +} + + +static void dlgclose_move(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus) { + + if (hdl->val != focus) { + hdl->val = focus; + drawctrls(dlg, hdl); + } + (void)x; + (void)y; +} + + +static void dlgclose_rel(MENUDLG dlg, DLGHDL hdl, int focus) { + + if (focus) { + dlg->proc(DLGMSG_CLOSE, 0, 0); + } + (void)hdl; +} + + +// ---- button + +static void dlgbtn_paint(MENUDLG dlg, DLGHDL hdl) { + + POINT_T sz; + POINT_T pt; + UINT c; + + vram_filldat(dlg->vram, &hdl->rect, menucolor[MVC_BTNFACE]); + if (!hdl->val) { + c = MVC4(MVC_HILIGHT, MVC_DARK, MVC_LIGHT, MVC_SHADOW); + } + else { + c = MVC4(MVC_DARK, MVC_DARK, MVC_SHADOW, MVC_SHADOW); + } + menuvram_box2(dlg->vram, &hdl->rect, c); + + if (gettextsz(hdl, &sz) == SUCCESS) { + getmid(&pt, &hdl->rect, &sz); + if (hdl->val) { + pt.x += MENU_DSTEXT; + pt.y += MENU_DSTEXT; + } + dlg_text(dlg, hdl, &pt, &hdl->rect); + } +} + + +static void dlgbtn_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { + + hdl->val = 1; + drawctrls(dlg, hdl); + (void)x; + (void)y; +} + +static void dlgbtn_move(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus) { + + if (hdl->val != focus) { + hdl->val = focus; + drawctrls(dlg, hdl); + } + (void)x; + (void)y; +} + +static void dlgbtn_rel(MENUDLG dlg, DLGHDL hdl, int focus) { + + if (hdl->val != 0) { + hdl->val = 0; + drawctrls(dlg, hdl); + } + if (focus) { + dlg->proc(DLGMSG_COMMAND, hdl->id, 0); + } +} + + +// ---- list + +static void *dlglist_setfont(DLGHDL hdl, void *font) { + // 後でスクロールバーの調整をすべし + void *ret; + POINT_T pt; + + ret = hdl->c.dl.font; + hdl->c.dl.font = font; + fontmng_getsize(font, mstr_fontcheck, &pt); + if ((pt.y <= 0) || (pt.y >= 65536)) { + pt.y = 16; + } + hdl->c.dl.fontsize = (SINT16)pt.y; + hdl->c.dl.dispmax = (SINT16)(hdl->vram->height / pt.y); + return(ret); +} + +static void dlglist_reset(MENUDLG dlg, DLGHDL hdl) { + + DLGPRM dp; + DLGPRM next; + + vram_filldat(hdl->vram, NULL, 0xffffff); + dp = hdl->prm; + while(dp) { + next = dp->next; + dp->next = PRMNEXT_EMPTY; + dp = next; + } + hdl->prm = NULL; + hdl->prmcnt = 0; + hdl->val = -1; + hdl->c.dl.scrollbar = 0; + hdl->c.dl.basepos = 0; +} + +static BRESULT dlglist_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { + + int width; + int height; + + width = hdl->rect.right - hdl->rect.left - (MENU_LINE * 4); + height = hdl->rect.bottom - hdl->rect.top - (MENU_LINE * 4); + hdl->vram = vram_create(width, height, FALSE, menubase.bpp); + if (hdl->vram == NULL) { + goto dlcre_err; + } + hdl->vram->posx = hdl->rect.left + (MENU_LINE * 2); + hdl->vram->posy = hdl->rect.top + (MENU_LINE * 2); + dlglist_setfont(hdl, dlg->font); + dlglist_reset(dlg, hdl); + return(SUCCESS); + +dlcre_err: + (void)dlg; + (void)arg; + return(FAILURE); +} + +static void dlglist_paint(MENUDLG dlg, DLGHDL hdl) { + + menuvram_box2(dlg->vram, &hdl->rect, + MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_DARK, MVC_LIGHT)); + vrammix_cpy(dlg->vram, NULL, hdl->vram, NULL); +} + +static void dlglist_drawitem(DLGHDL hdl, DLGPRM prm, int focus, + POINT_T *pt, RECT_T *rct) { + + VRAMHDL icon; + POINT_T fp; + + vram_filldat(hdl->vram, rct, menucolor[focus?MVC_CURBACK:MVC_HILIGHT]); + fp.x = pt->x; + fp.y = pt->y; + icon = prm->icon; + if (icon) { + if (icon->alpha) { + vramcpy_cpyex(hdl->vram, &fp, icon, NULL); + } + else { + vramcpy_cpy(hdl->vram, &fp, icon, NULL); + } + fp.x += icon->width; +#if defined(NP2_SIZE_QVGA) + fp.x += 1; +#else + fp.x += 2; +#endif + } + vrammix_text(hdl->vram, hdl->c.dl.font, prm->str, + menucolor[focus?MVC_CURTEXT:MVC_TEXT], &fp, rct); +} + +static BOOL dlglist_drawsub(DLGHDL hdl, int pos, int focus) { + + DLGPRM prm; + POINT_T pt; + RECT_T rct; + + prm = ressea(hdl, pos); + if (prm == NULL) { + return(FALSE); + } + pos -= hdl->c.dl.basepos; + if (pos < 0) { + return(FALSE); + } + pt.x = 0; + pt.y = pos * hdl->c.dl.fontsize; + if (pt.y >= hdl->vram->height) { + return(FALSE); + } + rct.left = 0; + rct.top = pt.y; + rct.right = hdl->vram->width; + if (hdl->prmcnt > hdl->c.dl.dispmax) { + rct.right -= MENUDLG_CXVSCR; + } + rct.bottom = rct.top + hdl->c.dl.fontsize; + dlglist_drawitem(hdl, prm, focus, &pt, &rct); + return(TRUE); +} + +static void dlglist_setbtn(DLGHDL hdl, int flg) { + + RECT_T rct; + POINT_T pt; + UINT mvc4; +const MENURES2 *res; + + res = menures_scrbtn; + rct.right = hdl->vram->width; + rct.left = rct.right - MENUDLG_CXVSCR; + if (!(flg & 2)) { + rct.top = 0; + } + else { + rct.top = hdl->vram->height - MENUDLG_CYVSCR; + if (rct.top < MENUDLG_CYVSCR) { + rct.top = MENUDLG_CYVSCR; + } + res++; + } + rct.bottom = rct.top + MENUDLG_CYVSCR; + + vram_filldat(hdl->vram, &rct, menucolor[MVC_BTNFACE]); + if (flg & 1) { + mvc4 = MVC4(MVC_SHADOW, MVC_SHADOW, MVC_LIGHT, MVC_LIGHT); + } + else { + mvc4 = MVC4(MVC_LIGHT, MVC_DARK, MVC_HILIGHT, MVC_SHADOW); + } + menuvram_box2(hdl->vram, &rct, mvc4); + pt.x = rct.left + (MENU_LINE * 2); + pt.y = rct.top + (MENU_LINE * 2); + if (flg & 1) { + pt.x += MENU_DSTEXT; + pt.y += MENU_DSTEXT; + } + menuvram_res3put(hdl->vram, res, &pt, MVC_TEXT); +} + +static void dlglist_drawall(DLGHDL hdl) { + + DLGPRM prm; + POINT_T pt; + RECT_T rct; + int pos; + + rct.left = 0; + rct.top = 0 - (hdl->c.dl.basepos * hdl->c.dl.fontsize); + rct.right = hdl->vram->width; + if (hdl->prmcnt > hdl->c.dl.dispmax) { + rct.right -= MENUDLG_CXVSCR; + } + + prm = hdl->prm; + pos = 0; + while(prm) { + if (rct.top >= hdl->vram->height) { + break; + } + if (rct.top >= 0) { + rct.bottom = rct.top + hdl->c.dl.fontsize; + pt.x = 0; + pt.y = rct.top; + dlglist_drawitem(hdl, prm, (pos == hdl->val), &pt, &rct); + } + prm = prm->next; + pos++; + rct.top += hdl->c.dl.fontsize; + } + rct.bottom = hdl->vram->height; + vram_filldat(hdl->vram, &rct, menucolor[MVC_HILIGHT]); +} + +static int dlglist_barpos(DLGHDL hdl) { + + int ret; + + ret = hdl->vram->height - (MENUDLG_CYVSCR * 2); + ret -= hdl->c.dl.scrollbar; + ret *= hdl->c.dl.basepos; + ret /= (hdl->prmcnt - hdl->c.dl.dispmax); + return(ret); +} + +static void dlglist_drawbar(DLGHDL hdl) { + + RECT_T rct; + + rct.right = hdl->vram->width; + rct.left = rct.right - MENUDLG_CXVSCR; + rct.top = MENUDLG_CYVSCR; + rct.bottom = hdl->vram->height - MENUDLG_CYVSCR; + vram_filldat(hdl->vram, &rct, menucolor[MVC_SCROLLBAR]); + + rct.top += dlglist_barpos(hdl); + rct.bottom = rct.top + hdl->c.dl.scrollbar; + vram_filldat(hdl->vram, &rct, menucolor[MVC_BTNFACE]); + menuvram_box2(hdl->vram, &rct, + MVC4(MVC_LIGHT, MVC_DARK, MVC_HILIGHT, MVC_SHADOW)); +} + +static BOOL dlglist_append(MENUDLG dlg, DLGHDL hdl, const OEMCHAR* arg) { + + BOOL r; + DLGPRM *sto; + int barsize; + + r = FALSE; + sto = &hdl->prm; + while(*sto) { + sto = &((*sto)->next); + } + *sto = resappend(dlg, arg); + if (*sto) { + r = dlglist_drawsub(hdl, hdl->prmcnt, FALSE); + hdl->prmcnt++; + if (hdl->prmcnt > hdl->c.dl.dispmax) { + barsize = hdl->vram->height - (MENUDLG_CYVSCR * 2); + if (barsize >= 8) { + barsize *= hdl->c.dl.dispmax; + barsize /= hdl->prmcnt; + barsize = MAX(barsize, 6); + if (!hdl->c.dl.scrollbar) { + dlglist_drawall(hdl); + dlglist_setbtn(hdl, 0); + dlglist_setbtn(hdl, 2); + } + hdl->c.dl.scrollbar = barsize; + dlglist_drawbar(hdl); + } + } + } + return(r); +} + +static BOOL dlglist_setex(MENUDLG dlg, DLGHDL hdl, const ITEMEXPRM *arg) { + + DLGPRM dp; + UINT cnt; + + if ((arg == NULL) || (arg->pos >= hdl->prmcnt)) { + return(FALSE); + } + cnt = arg->pos; + dp = hdl->prm; + while((cnt) && (dp)) { + cnt--; + dp = dp->next; + } + if (dp == NULL) { + return(FALSE); + } + resattachicon(dlg, dp, arg->icon, hdl->c.dl.fontsize, + hdl->c.dl.fontsize); + milstr_ncpy(dp->str, arg->str, NELEMENTS(dp->str)); + return(dlglist_drawsub(hdl, arg->pos, (arg->pos == hdl->val))); +} + +static int dlglist_getpos(DLGHDL hdl, int y) { + + int val; + + val = (y / hdl->c.dl.fontsize) + hdl->c.dl.basepos; + if ((unsigned int)val < (unsigned int)hdl->prmcnt) { + return(val); + } + else { + return(-1); + } +} + +enum { + DLCUR_OUT = -1, + DLCUR_INLIST = 0, + DLCUR_UP = 1, + DLCUR_INBAR = 2, + DLCUR_DOWN = 3, + DLCUR_PGUP = 4, + DLCUR_PGDN = 5, + DLCUR_INCUR = 6 +}; + +static int dlglist_getpc(DLGHDL hdl, int x, int y) { + + if ((unsigned int)x >= (unsigned int)hdl->vram->width) { + goto dlgp_out; + } + if ((unsigned int)y >= (unsigned int)hdl->vram->height) { + goto dlgp_out; + } + + if ((hdl->prmcnt < hdl->c.dl.dispmax) || + (x < (hdl->vram->width - MENUDLG_CXVSCR))) { + return(DLCUR_INLIST); + } + else if (y < MENUDLG_CYVSCR) { + return(DLCUR_UP); + } + else if (y >= (hdl->vram->height - MENUDLG_CYVSCR)) { + return(DLCUR_DOWN); + } + y -= MENUDLG_CYVSCR; + y -= dlglist_barpos(hdl); + if (y < 0) { + return(DLCUR_PGUP); + } + else if (y < (int)hdl->c.dl.scrollbar) { + return(DLCUR_INBAR); + } + else { + return(DLCUR_PGDN); + } + +dlgp_out: + return(DLCUR_OUT); +} + +static void dlglist_setval(MENUDLG dlg, DLGHDL hdl, int val) { + + BOOL r; + + if ((unsigned int)val >= (unsigned int)hdl->prmcnt) { + val = -1; + } + if (val != hdl->val) { + r = dlglist_drawsub(hdl, hdl->val, FALSE); + r |= dlglist_drawsub(hdl, val, TRUE); + hdl->val = val; + if (r) { + drawctrls(dlg, hdl); + } + } +} + +static void dlglist_setbasepos(MENUDLG dlg, DLGHDL hdl, int pos) { + + int displimit; + + if (pos < 0) { + pos = 0; + } + else { + displimit = hdl->prmcnt - hdl->c.dl.dispmax; + if (displimit < 0) { + displimit = 0; + } + if (pos > displimit) { + pos = displimit; + } + } + if (hdl->c.dl.basepos != pos) { + hdl->c.dl.basepos = pos; + dlglist_drawall(hdl); + dlglist_drawbar(hdl); + } + (void)dlg; +} + +static void dlglist_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { + + int flg; + int val; + + x -= (MENU_LINE * 2); + y -= (MENU_LINE * 2); + flg = dlglist_getpc(hdl, x, y); + dlg->dragflg = flg; + switch(flg) { + case DLCUR_INLIST: + val = dlglist_getpos(hdl, y); + if ((val == hdl->val) && (val != -1)) { + dlg->dragflg = DLCUR_INCUR; + } + dlglist_setval(dlg, hdl, val); + dlg->proc(DLGMSG_COMMAND, hdl->id, 0); + break; + + case 1: + case 3: + dlglist_setbtn(hdl, flg); + dlglist_setbasepos(dlg, hdl, hdl->c.dl.basepos + flg - 2); + drawctrls(dlg, hdl); + break; + + case DLCUR_INBAR: + y -= MENUDLG_CYVSCR; + y -= dlglist_barpos(hdl); + if ((unsigned int)y < (unsigned int)hdl->c.dl.scrollbar) { + dlg->lasty = y; + } + else { + dlg->lasty = -1; + } + break; + + case DLCUR_PGUP: + dlglist_setbasepos(dlg, hdl, hdl->c.dl.basepos + - hdl->c.dl.dispmax); + drawctrls(dlg, hdl); + break; + + case DLCUR_PGDN: + dlglist_setbasepos(dlg, hdl, hdl->c.dl.basepos + + hdl->c.dl.dispmax); + drawctrls(dlg, hdl); + break; + } +} + +static void dlglist_move(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus) { + + int flg; + int val; + int height; + + x -= (MENU_LINE * 2); + y -= (MENU_LINE * 2); + flg = dlglist_getpc(hdl, x, y); + switch(dlg->dragflg) { + case DLCUR_INLIST: + case DLCUR_INCUR: + if (flg == DLCUR_INLIST) { + val = dlglist_getpos(hdl, y); + if (val != hdl->val) { + dlg->dragflg = DLCUR_INLIST; + dlglist_setval(dlg, hdl, val); + dlg->proc(DLGMSG_COMMAND, hdl->id, 0); + } + } + break; + + case 1: + case 3: + dlglist_setbtn(hdl, dlg->dragflg - ((dlg->dragflg == flg)?0:1)); + drawctrls(dlg, hdl); + break; + + case DLCUR_INBAR: + if (dlg->lasty >= 0) { + y -= MENUDLG_CYVSCR; + y -= dlg->lasty; + height = hdl->vram->height - (MENUDLG_CYVSCR * 2); + height -= hdl->c.dl.scrollbar; + if (y < 0) { + y = 0; + } + else if (y > height) { + y = height; + } + y *= (hdl->prmcnt - hdl->c.dl.dispmax); + y /= height; + dlglist_setbasepos(dlg, hdl, y); + drawctrls(dlg, hdl); + } + break; + } + (void)focus; +} + +static void dlglist_rel(MENUDLG dlg, DLGHDL hdl, int focus) { + + switch(dlg->dragflg) { + case 1: + case 3: + dlglist_setbtn(hdl, dlg->dragflg - 1); + drawctrls(dlg, hdl); + break; + + case DLCUR_INCUR: + dlg->proc(DLGMSG_COMMAND, hdl->id, 1); + break; + } + (void)focus; +} + + +// ---- slider + +static void dlgslider_setflag(DLGHDL hdl) { + + int size; + UINT type; + + if (!(hdl->flag & MSS_VERT)) { + size = hdl->rect.bottom - hdl->rect.top; + } + else { + size = hdl->rect.right - hdl->rect.left; + } + if (size < 13) { + type = 0 + (9 << 8) + (5 << 16); + } + else if (size < 21) { + type = 1 + (13 << 8) + (7 << 16); + } + else { + type = 2 + (21 << 8) + (11 << 16); + } + hdl->c.ds.type = (UINT8)type; + if (!(hdl->flag & MSS_VERT)) { + hdl->c.ds.sldh = (UINT8)(type >> 16); + hdl->c.ds.sldv = (UINT8)(type >> 8); + } + else { + hdl->c.ds.sldh = (UINT8)(type >> 8); + hdl->c.ds.sldv = (UINT8)(type >> 16); + } +} + +static int dlgslider_setpos(DLGHDL hdl, int val) { + + int range; + int width; + int dir; + + range = hdl->c.ds.maxval - hdl->c.ds.minval; + if (range) { + dir = (range > 0)?1:-1; + val -= hdl->c.ds.minval; + val *= dir; + range *= dir; + if (val < 0) { + val = 0; + } + else if (val >= range) { + val = range; + } + hdl->val = hdl->c.ds.minval + (val * dir); + if (!(hdl->flag & MSS_VERT)) { + width = hdl->rect.right - hdl->rect.left; + width -= hdl->c.ds.sldh; + } + else { + width = hdl->rect.bottom - hdl->rect.top; + width -= hdl->c.ds.sldv; + } + if ((width > 0) || (range)) { + val *= width; + val /= range; + } + else { + val = 0; + } + } + else { + val = 0; + } + return(val); +} + +static BRESULT dlgslider_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { + + hdl->c.ds.minval = (SINT16)(long)arg; + hdl->c.ds.maxval = (SINT16)((long)arg >> 16); + hdl->c.ds.moving = 0; + dlgslider_setflag(hdl); + hdl->c.ds.pos = dlgslider_setpos(hdl, 0); + (void)dlg; + return(SUCCESS); +} + +static void dlgslider_paint(MENUDLG dlg, DLGHDL hdl) { + + UINT flag; + int ptr; + RECT_U rct; + POINT_T pt; + MENURES2 src; + + flag = hdl->flag; + switch(flag & MSS_POSMASK) { + case MSS_BOTH: + ptr = 1; + break; + case MSS_TOP: + ptr = 2; + break; + default: + ptr = 0; + break; + } + vram_filldat(dlg->vram, &hdl->rect, menucolor[MVC_STATIC]); + if (!(hdl->flag & MSS_VERT)) { + rct.r.left = hdl->rect.left; + rct.r.right = hdl->rect.right; + rct.r.top = hdl->rect.top + ptr + + (hdl->c.ds.sldv / 2) - (MENU_LINE * 2); + rct.r.bottom = rct.r.top + (MENU_LINE * 4); + menuvram_box2(dlg->vram, &rct.r, + MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_DARK, MVC_LIGHT)); + pt.x = hdl->rect.left + hdl->c.ds.pos; + pt.y = hdl->rect.top; + } + else { + rct.r.left = hdl->rect.left + ptr + + (hdl->c.ds.sldh / 2) - (MENU_LINE * 2); + rct.r.right = rct.r.left + (MENU_LINE * 4); + rct.r.top = hdl->rect.top; + rct.r.bottom = hdl->rect.bottom; + menuvram_box2(dlg->vram, &rct.r, + MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_DARK, MVC_LIGHT)); + pt.x = hdl->rect.left; + pt.y = hdl->rect.top + hdl->c.ds.pos; + ptr += 3; + } + ptr *= 2; + if ((hdl->flag & MENU_GRAY) || (hdl->c.ds.moving)) { + ptr++; + } + src.width = hdl->c.ds.sldh; + src.height = hdl->c.ds.sldv; + src.pat = menures_slddat + menures_sldpos[hdl->c.ds.type][ptr]; + menuvram_res2put(dlg->vram, &src, &pt); +} + +static void dlgslider_setval(MENUDLG dlg, DLGHDL hdl, int val) { + + int pos; + + pos = dlgslider_setpos(hdl, val); + if (hdl->c.ds.pos != pos) { + hdl->c.ds.pos = pos; + drawctrls(dlg, hdl); + } +} + +static void dlgslider_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { + + int width; + int range; + int dir; + + if (!(hdl->flag & MSS_VERT)) { + width = hdl->c.ds.sldh; + } + else { + width = hdl->c.ds.sldv; + x = y; + } + x -= hdl->c.ds.pos; + if ((x >= -1) && (x <= width)) { + dlg->dragflg = x; + hdl->c.ds.moving = 1; + drawctrls(dlg, hdl); + } + else { + dlg->dragflg = -1; + dir = (x > 0)?1:0; + range = hdl->c.ds.maxval - hdl->c.ds.minval; + if (range < 0) { + range = 0 - range; + dir ^= 1; + } + if (range < 16) { + range = 16; + } + range >>= 4; + if (!dir) { + range = 0 - range; + } + dlgslider_setval(dlg, hdl, hdl->val + range); + dlg->proc(DLGMSG_COMMAND, hdl->id, 0); + } +} + +static void dlgslider_move(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus) { + + int range; + int width; + int dir; + + if (hdl->c.ds.moving) { + range = hdl->c.ds.maxval - hdl->c.ds.minval; + if (range) { + dir = (range > 0)?1:-1; + range *= dir; + if (!(hdl->flag & MSS_VERT)) { + width = hdl->rect.right - hdl->rect.left; + width -= hdl->c.ds.sldh; + } + else { + width = hdl->rect.bottom - hdl->rect.top; + width -= hdl->c.ds.sldv; + x = y; + } + x -= dlg->dragflg; + if ((x < 0) || (width <= 0)) { + x = 0; + } + else if (x >= width) { + x = range; + } + else { + x *= range; + x += (width >> 1); + x /= width; + } + x = hdl->c.ds.minval + (x * dir); + dlgslider_setval(dlg, hdl, x); + dlg->proc(DLGMSG_COMMAND, hdl->id, 0); + } + } + (void)focus; +} + + +static void dlgslider_rel(MENUDLG dlg, DLGHDL hdl, int focus) { + + if (hdl->c.ds.moving) { + hdl->c.ds.moving = 0; + drawctrls(dlg, hdl); + } + (void)focus; +} + + +// ---- tablist + +static void *dlgtablist_setfont(DLGHDL hdl, void *font) { + + void *ret; + POINT_T pt; + DLGPRM prm; + + ret = hdl->c.dtl.font; + hdl->c.dtl.font = font; + fontmng_getsize(font, mstr_fontcheck, &pt); + if ((pt.y <= 0) || (pt.y >= 65536)) { + pt.y = 16; + } + hdl->c.dtl.fontsize = pt.y; + prm = hdl->prm; + while(prm) { + fontmng_getsize(hdl->c.dtl.font, prm->str, &pt); + prm->width = pt.x; + prm = prm->next; + } + return(ret); +} + +static BRESULT dlgtablist_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { + + RECT_T rct; + + rct.right = hdl->rect.right - hdl->rect.left; + hdl->val = -1; + dlgtablist_setfont(hdl, dlg->font); + (void)arg; + return(SUCCESS); +} + +static void dlgtablist_paint(MENUDLG dlg, DLGHDL hdl) { + + VRAMHDL dst; + DLGPRM prm; + POINT_T pt; + RECT_T rct; + int posx; + int lx; + int cnt; + int tabey; + int tabdy; + + dst = dlg->vram; + rct = hdl->rect; + vram_filldat(dst, &rct, menucolor[MVC_STATIC]); + tabey = rct.top + hdl->c.dtl.fontsize + + MENUDLG_SYTAB + MENUDLG_TYTAB + MENUDLG_EYTAB; + rct.top = tabey; + menuvram_box2(dst, &rct, + MVC4(MVC_HILIGHT, MVC_DARK, MVC_LIGHT, MVC_SHADOW)); + + posx = hdl->rect.left + (MENU_LINE * 2); + prm = hdl->prm; + cnt = hdl->val; + while(prm) { + if (cnt) { + pt.x = posx; + pt.y = hdl->rect.top + MENUDLG_SYTAB; + menuvram_liney(dst, pt.x, pt.y + (MENU_LINE * 2), + tabey, MVC_HILIGHT); + pt.x += MENU_LINE; + menuvram_liney(dst, pt.x, pt.y + MENU_LINE, + pt.y + (MENU_LINE * 2), MVC_HILIGHT); + menuvram_liney(dst, pt.x, pt.y + (MENU_LINE * 2), + tabey, MVC_LIGHT); + pt.x += MENU_LINE; + lx = pt.x + prm->width + (MENUDLG_TXTAB * 2); + menuvram_linex(dst, pt.x, pt.y, lx, MVC_HILIGHT); + menuvram_linex(dst, pt.x, pt.y + MENU_LINE, lx, MVC_LIGHT); + + menuvram_liney(dst, lx, pt.y + MENU_LINE, + pt.y + (MENU_LINE * 2), MVC_DARK); + menuvram_liney(dst, lx, pt.y + (MENU_LINE * 2), + tabey, MVC_SHADOW); + lx++; + menuvram_liney(dst, lx, pt.y + (MENU_LINE * 2), + tabey, MVC_DARK); + pt.x += MENUDLG_TXTAB; + pt.y += MENUDLG_TYTAB; + vrammix_text(dst, hdl->c.dtl.font, prm->str, + menucolor[MVC_TEXT], &pt, NULL); + } + cnt--; + posx += prm->width + (MENU_LINE * 4) + (MENUDLG_TXTAB) * 2; + prm = prm->next; + } + + posx = hdl->rect.left; + prm = hdl->prm; + cnt = hdl->val; + while(prm) { + if (!cnt) { + pt.x = posx; + pt.y = hdl->rect.top; + if (posx == hdl->rect.left) { + tabdy = tabey + 2; + } + else { + tabdy = tabey + 1; + menuvram_linex(dst, pt.x, tabdy, + pt.x + (MENU_LINE * 2), MVC_STATIC); + } + menuvram_liney(dst, pt.x, pt.y + (MENU_LINE * 2), + tabdy, MVC_HILIGHT); + pt.x += MENU_LINE; + menuvram_liney(dst, pt.x, pt.y + MENU_LINE, + pt.y + (MENU_LINE * 2), MVC_HILIGHT); + menuvram_liney(dst, pt.x, pt.y + (MENU_LINE * 2), + tabdy, MVC_LIGHT); + pt.x += MENU_LINE; + lx = pt.x + prm->width + (MENU_LINE * 4) + (MENUDLG_TXTAB * 2); + menuvram_linex(dst, pt.x, pt.y, lx, MVC_HILIGHT); + menuvram_linex(dst, pt.x, pt.y + MENU_LINE, lx, MVC_LIGHT); + menuvram_linex(dst, pt.x, tabey, lx, MVC_STATIC); + menuvram_linex(dst, pt.x, tabey + MENU_LINE, lx, MVC_STATIC); + tabdy = tabey + 1; + menuvram_liney(dst, lx, pt.y + MENU_LINE, + pt.y + (MENU_LINE * 2), MVC_DARK); + menuvram_liney(dst, lx, pt.y + (MENU_LINE * 2), + tabdy, MVC_SHADOW); + lx++; + menuvram_liney(dst, lx, pt.y + (MENU_LINE * 2), + tabdy, MVC_DARK); + pt.x += MENUDLG_TXTAB + (MENU_LINE * 2); + pt.y += MENUDLG_TYTAB; + vrammix_text(dst, hdl->c.dtl.font, prm->str, + menucolor[MVC_TEXT], &pt, NULL); + break; + } + cnt--; + posx += prm->width + (MENU_LINE * 4) + (MENUDLG_TXTAB * 2); + prm = prm->next; + } +} + +static void dlgtablist_setval(MENUDLG dlg, DLGHDL hdl, int val) { + + if (hdl->val != val) { + hdl->val = val; + drawctrls(dlg, hdl); + } +} + +static void dlgtablist_append(MENUDLG dlg, DLGHDL hdl, const OEMCHAR *arg) { + + DLGPRM res; + DLGPRM *sto; + POINT_T pt; + + sto = &hdl->prm; + while(*sto) { + sto = &((*sto)->next); + } + res = resappend(dlg, arg); + if (res) { + *sto = res; + fontmng_getsize(hdl->c.dtl.font, (OEMCHAR *)arg, &pt); + res->width = pt.x; + hdl->prmcnt++; + } +} + +static void dlgtablist_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { + + DLGPRM prm; + int pos; + + if (y < (hdl->c.dtl.fontsize + + MENUDLG_SYTAB + MENUDLG_TYTAB + MENUDLG_EYTAB)) { + pos = 0; + prm = hdl->prm; + while(prm) { + x -= (MENU_LINE * 4); + if (x < 0) { + break; + } + x -= prm->width + (MENUDLG_TXTAB * 2); + if (x < 0) { + dlgtablist_setval(dlg, hdl, pos); + dlg->proc(DLGMSG_COMMAND, hdl->id, 0); + break; + } + pos++; + prm = prm->next; + } + } +} + + +// ---- edit + +static void dlgedit_paint(MENUDLG dlg, DLGHDL hdl) { + + RECT_T rct; + POINT_T pt; +const OEMCHAR *string; + + rct = hdl->rect; + menuvram_box2(dlg->vram, &rct, + MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_DARK, MVC_LIGHT)); + rct.left += (MENU_LINE * 2); + rct.top += (MENU_LINE * 2); + rct.right -= (MENU_LINE * 2); + rct.bottom -= (MENU_LINE * 2); + vram_filldat(dlg->vram, &rct, menucolor[ + (hdl->flag & MENU_GRAY)?MVC_STATIC:MVC_HILIGHT]); + if (hdl->prm == NULL) { + goto dged_exit; + } + string = hdl->prm->str; + if (string == NULL) { + goto dged_exit; + } + pt.x = rct.left + MENU_LINE; + pt.y = rct.top + MENU_LINE; + vrammix_text(dlg->vram, hdl->c.dt.font, string, + menucolor[MVC_TEXT], &pt, &rct); + +dged_exit: + return; +} + + +// ---- frame + +static void dlgframe_paint(MENUDLG dlg, DLGHDL hdl) { + + RECT_T rct; + POINT_T pt; + + rct.left = hdl->rect.left; + rct.top = hdl->rect.top + MENUDLG_SYFRAME; + rct.right = hdl->rect.right; + rct.bottom = hdl->rect.bottom; + menuvram_box2(dlg->vram, &rct, + MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_HILIGHT, MVC_SHADOW)); + rct.left += MENUDLG_SXFRAME; + rct.top = hdl->rect.top; + rct.right = rct.left + (MENUDLG_PXFRAME * 2) + hdl->c.dt.pt.x; + rct.bottom = rct.top + hdl->c.dt.pt.y + MENU_DSTEXT; + vram_filldat(dlg->vram, &rct, menucolor[MVC_STATIC]); + if (hdl->prm) { + pt.x = rct.left + MENUDLG_PXFRAME; + pt.y = rct.top; + dlg_text(dlg, hdl, &pt, &rct); + } +} + + +// ---- radio + +typedef struct { + MENUDLG dlg; + MENUID group; +} MDCB1; + +static void dlgradio_paint(MENUDLG dlg, DLGHDL hdl) { + + POINT_T pt; +const MENURES2 *src; + int pat; + + vram_filldat(dlg->vram, &hdl->rect, menucolor[MVC_STATIC]); + pt.x = hdl->rect.left; + pt.y = hdl->rect.top; + src = menures_radio; + pat = (hdl->flag & MENU_GRAY)?1:0; + menuvram_res2put(dlg->vram, src + pat, &pt); + if (hdl->val) { + menuvram_res3put(dlg->vram, src + 2, &pt, + (hdl->flag & MENU_GRAY)?MVC_GRAYTEXT1:MVC_TEXT); + } + pt.x += MENUDLG_SXRADIO; + dlg_text(dlg, hdl, &pt, &hdl->rect); +} + +static BOOL drsv_cb(void *vpItem, void *vpArg) { + + DLGHDL item; + + item = (DLGHDL)vpItem; + if ((item->type == DLGTYPE_RADIO) && (item->val) && + (item->group == ((MDCB1 *)vpArg)->group)) { + item->val = 0; + drawctrls(((MDCB1 *)vpArg)->dlg, item); + } + return(FALSE); +} + +static void dlgradio_setval(MENUDLG dlg, DLGHDL hdl, int val) { + + MDCB1 mdcb; + + if (hdl->val != val) { + if (val) { + mdcb.dlg = dlg; + mdcb.group = hdl->group; + listarray_enum(dlg->dlg, drsv_cb, &mdcb); + } + hdl->val = val; + drawctrls(dlg, hdl); + } +} + +static void dlgradio_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { + + if (x < (hdl->c.dt.pt.x + MENUDLG_SXRADIO)) { + dlgradio_setval(dlg, hdl, 1); + dlg->proc(DLGMSG_COMMAND, hdl->id, 0); + } + (void)y; +} + + +// ---- check + +static void dlgcheck_paint(MENUDLG dlg, DLGHDL hdl) { + + POINT_T pt; + RECT_T rct; + UINT32 basecol; + UINT32 txtcol; + + vram_filldat(dlg->vram, &hdl->rect, menucolor[MVC_STATIC]); + rct.left = hdl->rect.left; + rct.top = hdl->rect.top; + rct.right = rct.left + MENUDLG_CXCHECK; + rct.bottom = rct.top + MENUDLG_CYCHECK; + if (!(hdl->flag & MENU_GRAY)) { + basecol = MVC_HILIGHT; + txtcol = MVC_TEXT; + } + else { + basecol = MVC_STATIC; + txtcol = MVC_GRAYTEXT1; + } + vram_filldat(dlg->vram, &rct, menucolor[basecol]); + menuvram_box2(dlg->vram, &rct, + MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_DARK, MVC_LIGHT)); + if (hdl->val) { + pt.x = rct.left + (MENU_LINE * 2); + pt.y = rct.top + (MENU_LINE * 2); + menuvram_res3put(dlg->vram, &menures_check, &pt, txtcol); + } + pt.x = rct.left + MENUDLG_SXCHECK; + pt.y = rct.top; + dlg_text(dlg, hdl, &pt, &hdl->rect); +} + +static void dlgcheck_setval(MENUDLG dlg, DLGHDL hdl, int val) { + + if (hdl->val != val) { + hdl->val = val; + drawctrls(dlg, hdl); + } +} + +static void dlgcheck_onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { + + if (x < (hdl->c.dt.pt.x + MENUDLG_SXCHECK)) { + dlgcheck_setval(dlg, hdl, !hdl->val); + dlg->proc(DLGMSG_COMMAND, hdl->id, 0); + } + (void)y; +} + + +// ---- text + +static void dlgtext_paint(MENUDLG dlg, DLGHDL hdl) { + + POINT_T sz; + POINT_T pt; + void (*getpt)(POINT_T *pt, const RECT_T *rect, const POINT_T *sz); + + vram_filldat(dlg->vram, &hdl->rect, menucolor[MVC_STATIC]); + if (gettextsz(hdl, &sz) == SUCCESS) { + switch(hdl->flag & MST_POSMASK) { + case MST_LEFT: + default: + getpt = getleft; + break; + + case MST_CENTER: + getpt = getcenter; + break; + + case MST_RIGHT: + getpt = getright; + break; + } + getpt(&pt, &hdl->rect, &sz); + dlg_text(dlg, hdl, &pt, &hdl->rect); + } +} + +static void dlgtext_itemset(MENUDLG dlg, DLGHDL hdl, const OEMCHAR *str) { + + if (hdl->prm) { + if (str == NULL) { + str = str_null; + } + milstr_ncpy(hdl->prm->str, str, NELEMENTS(hdl->prm->str)); + fontmng_getsize(hdl->c.dt.font, str, &hdl->c.dt.pt); + } + (void)dlg; +} + +static void dlgtext_iconset(MENUDLG dlg, DLGHDL hdl, UINT arg) { + + if (hdl->prm) { + resattachicon(dlg, hdl->prm, (UINT16)arg, hdl->c.dt.pt.y, hdl->c.dt.pt.y); + } + (void)dlg; +} + + +// ---- icon/vram + +static void iconpaint(MENUDLG dlg, DLGHDL hdl, VRAMHDL src) { + + RECT_U r; + UINT32 bgcol; + + r.p.x = hdl->rect.left; + r.p.y = hdl->rect.top; + bgcol = menucolor[MVC_STATIC]; + if (src) { + if (src->alpha) { + r.r.right = r.r.left + src->width; + r.r.bottom = r.r.top + src->height; + vram_filldat(dlg->vram, &r.r, bgcol); + vramcpy_cpyex(dlg->vram, &r.p, src, NULL); + } + else { + vramcpy_cpy(dlg->vram, &r.p, src, NULL); + } + } + else { + vram_filldat(dlg->vram, &hdl->rect, bgcol); + } +} + +static BRESULT dlgicon_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { + + hdl->prm = resappend(dlg, NULL); + resattachicon(dlg, hdl->prm, (UINT16)(long)arg, + hdl->rect.right - hdl->rect.left, hdl->rect.bottom - hdl->rect.top); + return(SUCCESS); +} + +static void dlgicon_paint(MENUDLG dlg, DLGHDL hdl) { + + DLGPRM prm; + + prm = hdl->prm; + if (prm) { + iconpaint(dlg, hdl, prm->icon); + } +} + +static BRESULT dlgvram_create(MENUDLG dlg, DLGHDL hdl, const void *arg) { + + hdl->c.dv.vram = (VRAMHDL)arg; + (void)dlg; + return(SUCCESS); +} + +static void dlgvram_paint(MENUDLG dlg, DLGHDL hdl) { + + iconpaint(dlg, hdl, hdl->c.dv.vram); +} + + +// ---- line + +static void dlgline_paint(MENUDLG dlg, DLGHDL hdl) { + + if (!(hdl->flag & MSL_VERT)) { + menuvram_linex(dlg->vram, hdl->rect.left, hdl->rect.top, + hdl->rect.right, MVC_SHADOW); + menuvram_linex(dlg->vram, hdl->rect.left, hdl->rect.top + MENU_LINE, + hdl->rect.right, MVC_HILIGHT); + } + else { + menuvram_liney(dlg->vram, hdl->rect.left, hdl->rect.top, + hdl->rect.bottom, MVC_SHADOW); + menuvram_liney(dlg->vram, hdl->rect.left+MENU_LINE, hdl->rect.top, + hdl->rect.bottom, MVC_HILIGHT); + } +} + + +// ---- box + +static void dlgbox_paint(MENUDLG dlg, DLGHDL hdl) { + + menuvram_box2(dlg->vram, &hdl->rect, + MVC4(MVC_SHADOW, MVC_HILIGHT, MVC_HILIGHT, MVC_SHADOW)); +} + + +// ---- procs + +static BRESULT _cre(MENUDLG dlg, DLGHDL hdl, const void *arg) { + + (void)dlg; + (void)hdl; + (void)arg; + return(SUCCESS); +} + +#if 0 // not used +static void _paint(MENUDLG dlg, DLGHDL hdl) { + + (void)dlg; + (void)hdl; +} +#endif + +#if 0 // not used +static void _onclick(MENUDLG dlg, DLGHDL hdl, int x, int y) { + + (void)dlg; + (void)hdl; + (void)x; + (void)y; +} +#endif + +static void _setval(MENUDLG dlg, DLGHDL hdl, int val) { + + (void)dlg; + (void)hdl; + (void)val; +} + +static void _moverel(MENUDLG dlg, DLGHDL hdl, int focus) { + + (void)dlg; + (void)hdl; + (void)focus; +} + +typedef BRESULT (*DLGCRE)(MENUDLG dlg, DLGHDL hdl, const void *arg); +typedef void (*DLGPAINT)(MENUDLG dlg, DLGHDL hdl); +typedef void (*DLGSETVAL)(MENUDLG dlg, DLGHDL hdl, int val); +typedef void (*DLGCLICK)(MENUDLG dlg, DLGHDL hdl, int x, int y); +typedef void (*DLGMOV)(MENUDLG dlg, DLGHDL hdl, int x, int y, int focus); +typedef void (*DLGREL)(MENUDLG dlg, DLGHDL hdl, int focus); + +static const DLGCRE dlgcre[] = { + dlgbase_create, // DLGTYPE_BASE + _cre, // DLGTYPE_CLOSE + _cre_settext, // DLGTYPE_BUTTON + dlglist_create, // DLGTYPE_LIST + dlgslider_create, // DLGTYPE_SLIDER + dlgtablist_create, // DLGTYPE_TABLIST + _cre_settext, // DLGTYPE_RADIO + _cre_settext, // DLGTYPE_CHECK + _cre_settext, // DLGTYPE_FRAME + _cre_settext, // DLGTYPE_EDIT + _cre_settext, // DLGTYPE_TEXT + dlgicon_create, // DLGTYPE_ICON + dlgvram_create, // DLGTYPE_VRAM + _cre, // DLGTYPE_LINE + _cre // DLGTYPE_BOX +}; + +static const DLGPAINT dlgpaint[] = { + dlgbase_paint, // DLGTYPE_BASE + dlgclose_paint, // DLGTYPE_CLOSE + dlgbtn_paint, // DLGTYPE_BUTTON + dlglist_paint, // DLGTYPE_LIST + dlgslider_paint, // DLGTYPE_SLIDER + dlgtablist_paint, // DLGTYPE_TABLIST + dlgradio_paint, // DLGTYPE_RADIO + dlgcheck_paint, // DLGTYPE_CHECK + dlgframe_paint, // DLGTYPE_FRAME + dlgedit_paint, // DLGTYPE_EDIT + dlgtext_paint, // DLGTYPE_TEXT + dlgicon_paint, // DLGTYPE_ICON + dlgvram_paint, // DLGTYPE_VRAM + dlgline_paint, // DLGTYPE_LINE + dlgbox_paint // DLGTYPE_BOX +}; + +static const DLGSETVAL dlgsetval[] = { + _setval, // DLGTYPE_BASE + _setval, // DLGTYPE_CLOSE + _setval, // DLGTYPE_BUTTON + dlglist_setval, // DLGTYPE_LIST + dlgslider_setval, // DLGTYPE_SLIDER + dlgtablist_setval, // DLGTYPE_TABLIST + dlgradio_setval, // DLGTYPE_RADIO + dlgcheck_setval // DLGTYPE_CHECK +}; + +static const DLGCLICK dlgclick[] = { + dlgbase_onclick, // DLGTYPE_BASE + dlgclose_onclick, // DLGTYPE_CLOSE + dlgbtn_onclick, // DLGTYPE_BUTTON + dlglist_onclick, // DLGTYPE_LIST + dlgslider_onclick, // DLGTYPE_SLIDER + dlgtablist_onclick, // DLGTYPE_TABLIST + dlgradio_onclick, // DLGTYPE_RADIO + dlgcheck_onclick // DLGTYPE_CHECK +}; + +static const DLGMOV dlgmov[] = { + dlgbase_move, // DLGTYPE_BASE + dlgclose_move, // DLGTYPE_CLOSE + dlgbtn_move, // DLGTYPE_BUTTON + dlglist_move, // DLGTYPE_LIST + dlgslider_move // DLGTYPE_SLIDER +}; + +static const DLGREL dlgrel[] = { + _moverel, // DLGTYPE_BASE + dlgclose_rel, // DLGTYPE_CLOSE + dlgbtn_rel, // DLGTYPE_BUTTON + dlglist_rel, // DLGTYPE_LIST + dlgslider_rel // DLGTYPE_SLIDER +}; + + +// ---- draw + +static void draw(VRAMHDL dst, const RECT_T *rect, void *arg) { + + MENUDLG dlg; + + dlg = (MENUDLG)arg; + vrammix_cpy2(dst, rect, dlg->vram, NULL, 2); +} + + +typedef struct { + MENUDLG dlg; + DLGHDL hdl; + RECT_T rect; +} MDCB2; + +static BOOL dc_cb(void *vpItem, void *vpArg) { + + DLGHDL hdl; + MDCB2 *mdcb; + + hdl = (DLGHDL)vpItem; + mdcb = (MDCB2 *)vpArg; + if (hdl == mdcb->hdl) { + mdcb->hdl = NULL; + } + if ((mdcb->hdl != NULL) || (hdl->flag & MENU_DISABLE)) { + goto dccb_exit; + } + if (rect_isoverlap(&mdcb->rect, &hdl->rect)) { + hdl->flag |= MENU_REDRAW; + } + +dccb_exit: + return(FALSE); +} + + +static BOOL dc_cb2(void *vpItem, void *vpArg) { + + MENUDLG dlg; + DLGHDL hdl; + + hdl = (DLGHDL)vpItem; + dlg = (MENUDLG)vpArg; + if (hdl->flag & MENU_REDRAW) { + hdl->flag &= ~MENU_REDRAW; + if ((!(hdl->flag & MENU_DISABLE)) && + ((UINT)hdl->type < NELEMENTS(dlgpaint))) { + dlgpaint[hdl->type](dlg, hdl); + menubase_setrect(dlg->vram, &hdl->rect); + } + } + return(FALSE); +} + + +static void drawctrls(MENUDLG dlg, DLGHDL hdl) { + + MDCB2 mdcb; + + if (hdl) { + if (hdl->flag & MENU_DISABLE) { + goto dcs_end; + } + mdcb.rect = hdl->rect; + } + else { + mdcb.rect.left = 0; + mdcb.rect.top = 0; + mdcb.rect.right = dlg->vram->width; + mdcb.rect.bottom = dlg->vram->height; + } + mdcb.dlg = dlg; + mdcb.hdl = hdl; + listarray_enum(dlg->dlg, dc_cb, &mdcb); + if (!dlg->locked) { + listarray_enum(dlg->dlg, dc_cb2, dlg); + menubase_draw(draw, dlg); + } + +dcs_end: + return; +} + +static void drawlock(BOOL lock) { + + MENUDLG dlg; + + dlg = &menudlg; + if (lock) { + dlg->locked++; + } + else { + dlg->locked--; + if (!dlg->locked) { + listarray_enum(dlg->dlg, dc_cb2, dlg); + menubase_draw(draw, dlg); + } + } +} + + +// ---- + +static int defproc(int msg, MENUID id, long param) { + + if (msg == DLGMSG_CLOSE) { + menubase_close(); + } + (void)id; + (void)param; + return(0); +} + + +BRESULT menudlg_create(int width, int height, const OEMCHAR *str, + int (*proc)(int msg, MENUID id, long param)) { + + MENUBASE *mb; + MENUDLG dlg; + + dlg = &menudlg; + if (menubase_open(2) != SUCCESS) { + goto mdcre_err; + } + ZeroMemory(dlg, sizeof(_MENUDLG)); + if ((width <= 0) || (height <= 0)) { + goto mdcre_err; + } + width += (MENU_FBORDER + MENU_BORDER) * 2; + height += ((MENU_FBORDER + MENU_BORDER) * 2) + + MENUDLG_CYCAPTION + MENUDLG_BORDER; + mb = &menubase; + dlg->font = mb->font; + dlg->vram = vram_create(width, height, FALSE, mb->bpp); + if (dlg->vram == NULL) { + goto mdcre_err; + } + dlg->vram->posx = (mb->width - width) >> 1; + dlg->vram->posy = (mb->height - height) >> 1; + dlg->dlg = listarray_new(sizeof(_DLGHDL), 32); + if (dlg->dlg == NULL) { + goto mdcre_err; + } + dlg->res = listarray_new(sizeof(_DLGPRM), 32); + if (dlg->res == NULL) { + goto mdcre_err; + } + if (menudlg_append(DLGTYPE_BASE, SID_CAPTION, 0, str, + 0, 0, width, height) != SUCCESS) { + goto mdcre_err; + } + if (menudlg_append(DLGTYPE_CLOSE, SID_CLOSE, 0, NULL, + width - (MENU_FBORDER + MENU_BORDER) - + (MENUDLG_CXCLOSE + MENUDLG_PXCAPTION), + (MENU_FBORDER + MENU_BORDER) + + ((MENUDLG_CYCAPTION - MENUDLG_CYCLOSE) / 2), + MENUDLG_CXCLOSE, MENUDLG_CYCLOSE) != SUCCESS) { + goto mdcre_err; + } + dlg->sx = (MENU_FBORDER + MENU_BORDER); + dlg->sy = (MENU_FBORDER + MENU_BORDER) + + (MENUDLG_CYCAPTION + MENUDLG_BORDER); + if (proc == NULL) { + proc = defproc; + } + dlg->proc = proc; + dlg->locked = 0; + drawlock(TRUE); + proc(DLGMSG_CREATE, 0, 0); + drawctrls(dlg, NULL); + drawlock(FALSE); + + return(SUCCESS); + +mdcre_err: + menubase_close(); + return(FAILURE); +} + + +static BOOL mdds_cb(void *vpItem, void *vpArg) { + + vram_destroy(((DLGHDL)vpItem)->vram); + (void)vpArg; + return(FALSE); +} + +static BOOL delicon(void *vpItem, void *vpArg) { + + menuicon_unlock(((DLGPRM)vpItem)->icon); + (void)vpArg; + return(FALSE); +} + +void menudlg_destroy(void) { + + MENUDLG dlg; + + dlg = &menudlg; + + if (dlg->closing) { + return; + } + dlg->closing = 1; + dlg->proc(DLGMSG_DESTROY, 0, 0); + listarray_enum(dlg->dlg, mdds_cb, NULL); + menubase_clrrect(dlg->vram); + vram_destroy(dlg->vram); + dlg->vram = NULL; + listarray_destroy(dlg->dlg); + dlg->dlg = NULL; + listarray_enum(dlg->res, delicon, NULL); + listarray_destroy(dlg->res); + dlg->res = NULL; +} + + +// ---- + +BRESULT menudlg_appends(const MENUPRM *res, int count) { + + BRESULT r; + + r = SUCCESS; + while(count--) { + r |= menudlg_append(res->type, res->id, res->flg, res->arg, + res->posx, res->posy, res->width, res->height); + res++; + } + return(r); +} + +BRESULT menudlg_append(int type, MENUID id, MENUFLG flg, const void *arg, + int posx, int posy, int width, int height) { + + MENUDLG dlg; + DLGHDL hdl; + _DLGHDL dhdl; + + dlg = &menudlg; + + if (flg & MENU_TABSTOP) { + dlg->group++; + } + switch(type) { + case DLGTYPE_LTEXT: + type = DLGTYPE_TEXT; + flg &= ~MST_POSMASK; + flg |= MST_LEFT; + break; + + case DLGTYPE_CTEXT: + type = DLGTYPE_TEXT; + flg &= ~MST_POSMASK; + flg |= MST_CENTER; + break; + + case DLGTYPE_RTEXT: + type = DLGTYPE_TEXT; + flg &= ~MST_POSMASK; + flg |= MST_RIGHT; + break; + } + + ZeroMemory(&dhdl, sizeof(dhdl)); + dhdl.type = type; + dhdl.id = id; + dhdl.flag = flg; + dhdl.page = dlg->page; + dhdl.group = dlg->group; + dhdl.rect.left = dlg->sx + posx; + dhdl.rect.top = dlg->sy + posy; + dhdl.rect.right = dhdl.rect.left + width; + dhdl.rect.bottom = dhdl.rect.top + height; + dhdl.prm = NULL; + dhdl.prmcnt = 0; + dhdl.val = 0; + if (((UINT)type >= NELEMENTS(dlgcre)) || + (dlgcre[type](dlg, &dhdl, arg))) { + goto mda_err; + } + drawlock(TRUE); + hdl = (DLGHDL)listarray_append(dlg->dlg, &dhdl); + drawctrls(dlg, hdl); + drawlock(FALSE); + return(SUCCESS); + +mda_err: + return(FAILURE); +} + + +// ---- moving + +typedef struct { + int x; + int y; + DLGHDL ret; +} MDCB3; + +static BOOL hps_cb(void *vpItem, void *vpArg) { + + DLGHDL hdl; + MDCB3 *mdcb; + + hdl = (DLGHDL)vpItem; + mdcb = (MDCB3 *)vpArg; + if ((!(hdl->flag & (MENU_DISABLE | MENU_GRAY))) && + (rect_in(&hdl->rect, mdcb->x, mdcb->y))) { + mdcb->ret = hdl; + } + return(FALSE); +} + +static DLGHDL hdlpossea(MENUDLG dlg, int x, int y) { + + MDCB3 mdcb; + + mdcb.x = x; + mdcb.y = y; + mdcb.ret = NULL; + listarray_enum(dlg->dlg, hps_cb, &mdcb); + return(mdcb.ret); +} + +void menudlg_moving(int x, int y, int btn) { + + MENUDLG dlg; + DLGHDL hdl; + int focus; + + drawlock(TRUE); + dlg = &menudlg; + x -= dlg->vram->posx; + y -= dlg->vram->posy; + if (!dlg->btn) { + if (btn == 1) { + hdl = hdlpossea(dlg, x, y); + if (hdl) { + x -= hdl->rect.left; + y -= hdl->rect.top; + dlg->btn = 1; + dlg->lastid = hdl->id; + if ((UINT)hdl->type < NELEMENTS(dlgclick)) { + dlgclick[hdl->type](dlg, hdl, x, y); + } + } + } + } + else { + hdl = dlghdlsea(dlg, dlg->lastid); + if (hdl) { + focus = rect_in(&hdl->rect, x, y); + x -= hdl->rect.left; + y -= hdl->rect.top; + if ((UINT)hdl->type < NELEMENTS(dlgmov)) { + dlgmov[hdl->type](dlg, hdl, x, y, focus); + } + if (btn == 2) { + dlg->btn = 0; + if ((UINT)hdl->type < NELEMENTS(dlgrel)) { + dlgrel[hdl->type](dlg, hdl, focus); + } + } + } + } + drawlock(FALSE); +} + + +// ---- ctrl + +INTPTR menudlg_msg(int ctrl, MENUID id, INTPTR arg) { + + INTPTR ret; + MENUDLG dlg; + DLGHDL hdl; + int flg; + + ret = 0; + dlg = &menudlg; + hdl = dlghdlsea(dlg, id); + if (hdl == NULL) { + goto mdm_exit; + } + drawlock(TRUE); + switch(ctrl) { + case DMSG_SETHIDE: + ret = (hdl->flag & MENU_DISABLE) ? 1 : 0; + flg = (arg) ? MENU_DISABLE : 0; + if ((hdl->flag ^ flg) & MENU_DISABLE) { + hdl->flag ^= MENU_DISABLE; + if (flg) { + drawctrls(dlg, NULL); + } + else { + drawctrls(dlg, hdl); + } + } + break; + + case DMSG_GETHIDE: + ret = (hdl->flag & MENU_DISABLE) ? 1 : 0; + break; + + case DMSG_SETENABLE: + ret = (hdl->flag & MENU_GRAY) ? 0 : 1; + flg = (arg) ? 0 : MENU_GRAY; + if ((hdl->flag ^ flg) & MENU_GRAY) { + hdl->flag ^= MENU_GRAY; + drawctrls(dlg, hdl); + } + break; + + case DMSG_GETENABLE: + ret = (hdl->flag & MENU_GRAY) ? 0 : 1; + break; + + case DMSG_SETVAL: + ret = hdl->val; + if ((UINT)hdl->type < NELEMENTS(dlgsetval)) { + dlgsetval[hdl->type](dlg, hdl, (int)arg); + } + break; + + case DMSG_GETVAL: + ret = hdl->val; + break; + + case DMSG_SETVRAM: + if (hdl->type == DLGTYPE_VRAM) { + ret = (INTPTR)hdl->c.dv.vram; + hdl->c.dv.vram = (VRAMHDL)arg; + drawctrls(dlg, hdl); + } + break; + + case DMSG_SETTEXT: + switch(hdl->type) { + case DLGTYPE_BUTTON: + case DLGTYPE_RADIO: + case DLGTYPE_CHECK: + case DLGTYPE_EDIT: + case DLGTYPE_TEXT: + dlgtext_itemset(dlg, hdl, (OEMCHAR*)arg); + drawctrls(dlg, hdl); + break; + } + break; + + case DMSG_SETICON: + switch(hdl->type) { + case DLGTYPE_BUTTON: + case DLGTYPE_RADIO: + case DLGTYPE_CHECK: + case DLGTYPE_EDIT: + case DLGTYPE_TEXT: + dlgtext_iconset(dlg, hdl, (UINT)arg); + drawctrls(dlg, hdl); + break; + } + break; + + case DMSG_ITEMAPPEND: + switch(hdl->type) { + case DLGTYPE_LIST: + if (dlglist_append(dlg, hdl, (OEMCHAR*)arg)) { + drawctrls(dlg, hdl); + } + break; + + case DLGTYPE_TABLIST: + dlgtablist_append(dlg, hdl, (OEMCHAR*)arg); + drawctrls(dlg, hdl); + break; + } + break; + + case DMSG_ITEMRESET: + if ((dlg->btn) && (dlg->lastid == hdl->id)) { + dlg->btn = 0; + if ((UINT)hdl->type < NELEMENTS(dlgrel)) { + dlgrel[hdl->type](dlg, hdl, FALSE); + } + } + if (hdl->type == DLGTYPE_LIST) { + dlglist_reset(dlg, hdl); + drawctrls(dlg, hdl); + } + break; + + case DMSG_ITEMSETEX: + if (hdl->type == DLGTYPE_LIST) { + if (dlglist_setex(dlg, hdl, (ITEMEXPRM *)arg)) { + drawctrls(dlg, hdl); + } + } + break; + + case DMSG_SETLISTPOS: + if (hdl->type == DLGTYPE_LIST) { + ret = hdl->c.dl.basepos; + dlglist_setbasepos(dlg, hdl, (int)arg); + drawctrls(dlg, hdl); + } + break; + + case DMSG_GETRECT: + ret = (INTPTR)&hdl->rect; + break; + + case DMSG_SETRECT: + ret = (INTPTR)&hdl->rect; + if ((hdl->type == DLGTYPE_TEXT) && (arg)) { + drawctrls(dlg, hdl); + hdl->rect = *(RECT_T *)arg; + drawctrls(dlg, hdl); + } + break; + + case DMSG_SETFONT: + if (hdl->type == DLGTYPE_LIST) { + ret = (INTPTR)dlglist_setfont(hdl, (void*)arg); + drawctrls(dlg, hdl); + } + else if (hdl->type == DLGTYPE_TABLIST) { + ret = (INTPTR)dlgtablist_setfont(hdl, (void*)arg); + drawctrls(dlg, hdl); + } + else if (hdl->type == DLGTYPE_TEXT) { + ret = (INTPTR)hdl->c.dt.font; + hdl->c.dt.font = (void*)arg; + drawctrls(dlg, hdl); + } + break; + + case DMSG_GETFONT: + if (hdl->type == DLGTYPE_LIST) { + ret = (INTPTR)hdl->c.dl.font; + } + else if (hdl->type == DLGTYPE_TABLIST) { + ret = (INTPTR)hdl->c.dtl.font; + } + else if (hdl->type == DLGTYPE_TEXT) { + ret = (INTPTR)hdl->c.dt.font; + } + break; + + } + drawlock(FALSE); + +mdm_exit: + return(ret); +} + + +// --- page + +void menudlg_setpage(MENUID page) { + + MENUDLG dlg; + + dlg = &menudlg; + dlg->page = page; +} + + +typedef struct { + MENUID page; + MENUFLG flag; +} MDCB4; + +static BOOL mddph_cb(void *vpItem, void *vpArg) { + + DLGHDL hdl; + MDCB4 *mdcb; + + hdl = (DLGHDL)vpItem; + mdcb = (MDCB4 *)vpArg; + if ((hdl->page == mdcb->page) && + ((hdl->flag ^ mdcb->flag) & MENU_DISABLE)) { + hdl->flag ^= MENU_DISABLE; + } + return(FALSE); +} + +void menudlg_disppagehidden(MENUID page, BOOL hidden) { + + MENUDLG dlg; + MDCB4 mdcb; + + dlg = &menudlg; + mdcb.page = page; + mdcb.flag = (hidden)?MENU_DISABLE:0; + listarray_enum(dlg->dlg, mddph_cb, &mdcb); + drawlock(TRUE); + drawctrls(dlg, NULL); + drawlock(FALSE); +} + diff --git a/embed/menubase/menudlg.h b/embed/menubase/menudlg.h old mode 100755 new mode 100644 index b10fff63..476f9a0b --- a/embed/menubase/menudlg.h +++ b/embed/menubase/menudlg.h @@ -1,145 +1,145 @@ - -enum { - DLGMSG_CREATE = 0, - DLGMSG_COMMAND, - DLGMSG_CLOSE, - DLGMSG_DESTROY -}; - -enum { - DMSG_SETHIDE = 0, - DMSG_GETHIDE, - DMSG_SETENABLE, - DMSG_GETENABLE, - DMSG_SETVAL, - DMSG_GETVAL, - DMSG_SETVRAM, - DMSG_SETTEXT, - DMSG_SETICON, - DMSG_ITEMAPPEND, - DMSG_ITEMRESET, - DMSG_ITEMSET, - DMSG_ITEMSETEX, - DMSG_SETLISTPOS, - DMSG_SETRECT, - DMSG_GETRECT, - DMSG_SETFONT, - DMSG_GETFONT -}; - -enum { - MSS_TOP = 0x0020, - MSS_BOTH = 0x0010, - MSS_POSMASK = 0x0030, - MSS_VERT = 0x0040, - - MSL_VERT = 0x0010, - - MST_LEFT = 0x0000, - MST_CENTER = 0x0010, - MST_RIGHT = 0x0020, - MST_POSMASK = 0x0030 -}; - - -enum { - DLGTYPE_BASE = 0, - DLGTYPE_CLOSE, - DLGTYPE_BUTTON, - DLGTYPE_LIST, - - DLGTYPE_SLIDER, - - DLGTYPE_TABLIST, - DLGTYPE_RADIO, - DLGTYPE_CHECK, - - DLGTYPE_FRAME, - DLGTYPE_EDIT, - DLGTYPE_TEXT, - DLGTYPE_ICON, - DLGTYPE_VRAM, - DLGTYPE_LINE, - DLGTYPE_BOX, - -// 互換用… - DLGTYPE_LTEXT, - DLGTYPE_CTEXT, - DLGTYPE_RTEXT -}; - -typedef struct { - int type; - MENUID id; - MENUFLG flg; -const void *arg; - int posx; - int posy; - int width; - int height; -} MENUPRM; - -typedef struct { - UINT16 pos; - UINT16 icon; -const OEMCHAR *str; -} ITEMEXPRM; - -#define SLIDERPOS(a, b) (((UINT16)a) | (((UINT16)b) << 16)) - - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT menudlg_create(int width, int height, const OEMCHAR *str, - int (*proc)(int msg, MENUID id, long param)); -void menudlg_destroy(void); - -BRESULT menudlg_appends(const MENUPRM *res, int count); -BRESULT menudlg_append(int type, MENUID id, MENUFLG flg, const void *arg, - int posx, int posy, int width, int height); - -void menudlg_moving(int x, int y, int btn); - -INTPTR menudlg_msg(int ctrl, MENUID id, INTPTR arg); -void menudlg_setpage(MENUID page); -void menudlg_disppagehidden(MENUID page, BOOL hidden); - -#ifdef __cplusplus -} -#endif - - -// ---- MACRO - -#define menudlg_sethide(id, hidden) \ - menudlg_msg(DMSG_SETHIDE, (id), (hidden)) -#define menudlg_setenable(id, enable) \ - menudlg_msg(DMSG_SETENABLE, (id), (enable)) -#define menudlg_setval(id, val) \ - menudlg_msg(DMSG_SETVAL, (id), (UINT)(val)) -#define menudlg_getval(id) \ - ((UINT)menudlg_msg(DMSG_GETVAL, (id), 0)) -#define menudlg_setvram(id, vram) \ - ((VRAMHDL)menudlg_msg(DMSG_SETVRAM, (id), (INTPTR)(vram))) -#define menudlg_settext(id, arg) \ - menudlg_msg(DMSG_SETTEXT, (id), (INTPTR)(arg)) -#define menudlg_seticon(id, val) \ - menudlg_msg(DMSG_SETICON, (id), (val)) -#define menudlg_itemappend(id, arg) \ - menudlg_msg(DMSG_ITEMAPPEND, (id), (INTPTR)(arg)) -#define menudlg_itemreset(id) \ - menudlg_msg(DMSG_ITEMRESET, (id), 0) -#define menudlg_itemsetex(id, arg) \ - menudlg_msg(DMSG_ITEMSETEX, (id), (INTPTR)(arg)) -#define menudlg_setlistpos(id, num) \ - menudlg_msg(DMSG_SETLISTPOS, (id), (num)) -#define menudlg_setrect(id, rect) \ - menudlg_msg(DMSG_SETRECT, (id), (INTPTR)(rect)) -#define menudlg_getrect(id) \ - ((RECT_T *)menudlg_msg(DMSG_GETRECT, (id), 0)) -#define menudlg_setfont(id, font) \ - menudlg_msg(DMSG_SETFONT, (id), (INTPTR)(font)) -#define menudlg_getfont(id) \ - menudlg_msg(DMSG_GETFONT, (id), 0) + +enum { + DLGMSG_CREATE = 0, + DLGMSG_COMMAND, + DLGMSG_CLOSE, + DLGMSG_DESTROY +}; + +enum { + DMSG_SETHIDE = 0, + DMSG_GETHIDE, + DMSG_SETENABLE, + DMSG_GETENABLE, + DMSG_SETVAL, + DMSG_GETVAL, + DMSG_SETVRAM, + DMSG_SETTEXT, + DMSG_SETICON, + DMSG_ITEMAPPEND, + DMSG_ITEMRESET, + DMSG_ITEMSET, + DMSG_ITEMSETEX, + DMSG_SETLISTPOS, + DMSG_SETRECT, + DMSG_GETRECT, + DMSG_SETFONT, + DMSG_GETFONT +}; + +enum { + MSS_TOP = 0x0020, + MSS_BOTH = 0x0010, + MSS_POSMASK = 0x0030, + MSS_VERT = 0x0040, + + MSL_VERT = 0x0010, + + MST_LEFT = 0x0000, + MST_CENTER = 0x0010, + MST_RIGHT = 0x0020, + MST_POSMASK = 0x0030 +}; + + +enum { + DLGTYPE_BASE = 0, + DLGTYPE_CLOSE, + DLGTYPE_BUTTON, + DLGTYPE_LIST, + + DLGTYPE_SLIDER, + + DLGTYPE_TABLIST, + DLGTYPE_RADIO, + DLGTYPE_CHECK, + + DLGTYPE_FRAME, + DLGTYPE_EDIT, + DLGTYPE_TEXT, + DLGTYPE_ICON, + DLGTYPE_VRAM, + DLGTYPE_LINE, + DLGTYPE_BOX, + +// 互換用… + DLGTYPE_LTEXT, + DLGTYPE_CTEXT, + DLGTYPE_RTEXT +}; + +typedef struct { + int type; + MENUID id; + MENUFLG flg; +const void *arg; + int posx; + int posy; + int width; + int height; +} MENUPRM; + +typedef struct { + UINT16 pos; + UINT16 icon; +const OEMCHAR *str; +} ITEMEXPRM; + +#define SLIDERPOS(a, b) (((UINT16)a) | (((UINT16)b) << 16)) + + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT menudlg_create(int width, int height, const OEMCHAR *str, + int (*proc)(int msg, MENUID id, long param)); +void menudlg_destroy(void); + +BRESULT menudlg_appends(const MENUPRM *res, int count); +BRESULT menudlg_append(int type, MENUID id, MENUFLG flg, const void *arg, + int posx, int posy, int width, int height); + +void menudlg_moving(int x, int y, int btn); + +INTPTR menudlg_msg(int ctrl, MENUID id, INTPTR arg); +void menudlg_setpage(MENUID page); +void menudlg_disppagehidden(MENUID page, BOOL hidden); + +#ifdef __cplusplus +} +#endif + + +// ---- MACRO + +#define menudlg_sethide(id, hidden) \ + menudlg_msg(DMSG_SETHIDE, (id), (hidden)) +#define menudlg_setenable(id, enable) \ + menudlg_msg(DMSG_SETENABLE, (id), (enable)) +#define menudlg_setval(id, val) \ + menudlg_msg(DMSG_SETVAL, (id), (UINT)(val)) +#define menudlg_getval(id) \ + ((UINT)menudlg_msg(DMSG_GETVAL, (id), 0)) +#define menudlg_setvram(id, vram) \ + ((VRAMHDL)menudlg_msg(DMSG_SETVRAM, (id), (INTPTR)(vram))) +#define menudlg_settext(id, arg) \ + menudlg_msg(DMSG_SETTEXT, (id), (INTPTR)(arg)) +#define menudlg_seticon(id, val) \ + menudlg_msg(DMSG_SETICON, (id), (val)) +#define menudlg_itemappend(id, arg) \ + menudlg_msg(DMSG_ITEMAPPEND, (id), (INTPTR)(arg)) +#define menudlg_itemreset(id) \ + menudlg_msg(DMSG_ITEMRESET, (id), 0) +#define menudlg_itemsetex(id, arg) \ + menudlg_msg(DMSG_ITEMSETEX, (id), (INTPTR)(arg)) +#define menudlg_setlistpos(id, num) \ + menudlg_msg(DMSG_SETLISTPOS, (id), (num)) +#define menudlg_setrect(id, rect) \ + menudlg_msg(DMSG_SETRECT, (id), (INTPTR)(rect)) +#define menudlg_getrect(id) \ + ((RECT_T *)menudlg_msg(DMSG_GETRECT, (id), 0)) +#define menudlg_setfont(id, font) \ + menudlg_msg(DMSG_SETFONT, (id), (INTPTR)(font)) +#define menudlg_getfont(id) \ + menudlg_msg(DMSG_GETFONT, (id), 0) diff --git a/embed/menubase/menuicon.c b/embed/menubase/menuicon.c old mode 100755 new mode 100644 index 81a6607e..546ef53b --- a/embed/menubase/menuicon.c +++ b/embed/menubase/menuicon.c @@ -1,283 +1,283 @@ -#include -#include -#include - - -#define MICON_MAX 16 -#define MICON_CACHE 8 - - -typedef struct { -// UINT16 type; -const void *res; -} ICONREG; - -typedef struct { - UINT16 id; - UINT16 count; - VRAMHDL hdl; -} ICONCACHE; - - -static ICONREG iconreg[MICON_MAX - 1]; -static ICONCACHE iconcache[MICON_CACHE]; - -static const UINT8 icon24a[178] = { // 32x32 - 0x07,0x17,0x00,0x00,0x80,0x01,0x7f,0xff,0x01,0x16,0x2b,0x56,0x34, - 0x44,0xff,0x2e,0x29,0x31,0x2f,0x2c,0xaf,0x32,0xac,0x2e,0x3b,0x31, - 0x23,0x2f,0xc2,0x00,0x14,0xff,0x2e,0x14,0x00,0x02,0x26,0x9d,0x10, - 0x16,0x2e,0x27,0x00,0x05,0x2e,0x1a,0x10,0x19,0xff,0x8c,0x9e,0x00, - 0x0e,0x2e,0x1a,0x10,0x16,0x5f,0xaa,0x20,0x91,0x3e,0xa0,0x2f,0x8b, - 0xff,0xeb,0x1a,0x23,0x94,0x2e,0x22,0x31,0x0c,0x2f,0x9a,0x26,0x91, - 0x2e,0x28,0x2f,0xa7,0xff,0x31,0x1a,0x1a,0x9d,0x2f,0xa9,0x31,0x14, - 0x19,0x20,0x2f,0xff,0x8f,0xe6,0xef,0xdc,0xff,0x26,0x94,0x31,0x28, - 0x2f,0x86,0x31,0x17,0x23,0x9a,0x31,0x22,0x2e,0x09,0x2f,0x94,0xff, - 0x20,0xa0,0x10,0x1f,0x2f,0x9e,0x20,0x8b,0x9e,0xa0,0x5f,0xa0,0x31, - 0x1a,0xe0,0x9c,0xff,0x2e,0x27,0xf4,0x20,0x01,0x2b,0x2e,0x15,0x2f, - 0xe2,0x31,0x43,0x2e,0x1b,0x31,0x0a,0xff,0x32,0xb2,0x1a,0x83,0x00, - 0x29,0x31,0x2e,0x2c,0xaa,0x64,0x10,0x34,0x1a,0x10,0x06,0xf8,0x00, - 0x3e,0x34,0x0a,0x01,0x0c,0x00,0x7f,0x00,0x66}; - -static const UINT8 icon24am[83] = { // 32x32 - 0x06,0x5f,0x00,0x00,0x09,0xff,0x00,0x06,0x04,0x8a,0x07,0x11,0x08, - 0x96,0x07,0x8d,0xff,0x08,0x0f,0x07,0x4f,0x08,0x4e,0x07,0x93,0x08, - 0x0a,0x07,0x95,0x08,0x09,0x07,0xd7,0xfe,0x08,0x06,0x07,0x98,0x08, - 0x05,0x07,0x9a,0x07,0xe0,0x08,0x03,0x07,0xdc,0xff,0xff,0x07,0x9e, - 0x07,0xff,0x00,0x3f,0x00,0x3f,0x00,0x21,0x38,0x3f,0x57,0xdf,0x68, - 0x21,0xff,0x78,0x7b,0x98,0x24,0xa8,0x61,0xb8,0x5f,0xc8,0x60,0xd8, - 0x60,0xe8,0x61,0xf8,0x56}; - -static const UINT8 icon24b[195] = { // 32x32 - 0x06,0x61,0x80,0x00,0x3f,0x00,0x3f,0xc0,0xc0,0xc0,0xff,0x00,0x10, - 0xff,0x05,0x02,0x15,0xbf,0x15,0x93,0x1a,0x3f,0x16,0x6b,0x19,0x75, - 0x16,0x6f,0x00,0x0b,0x73,0x00,0x00,0x1c,0x17,0x17,0x33,0x83,0x00, - 0x00,0x00,0x8e,0x38,0xd7,0xff,0x17,0x35,0x13,0x49,0x18,0xb4,0x5c, - 0xdb,0x13,0x45,0x04,0x51,0x05,0xd1,0x24,0x8a,0xff,0x2f,0x26,0x13, - 0x55,0x17,0xdf,0x30,0x85,0x8c,0x27,0x13,0x4d,0x62,0xcf,0x93,0x99, - 0xff,0x18,0x8b,0x9e,0x1d,0x5b,0x4c,0x17,0x22,0x30,0x91,0xb9,0x29, - 0x17,0x26,0x17,0xf5,0xff,0x17,0x29,0x17,0xfb,0xf7,0x66,0x2f,0xf9, - 0xf2,0xe8,0x8f,0xe4,0x00,0x34,0x8f,0xce,0xff,0x30,0xa3,0x92,0x0f, - 0x2f,0x28,0x30,0xa7,0xa6,0x68,0x2f,0x11,0x30,0xa4,0xbe,0x74,0xff, - 0x00,0x0b,0x05,0xc2,0x47,0xff,0x17,0x19,0x18,0xa3,0x5d,0xb2,0x18, - 0x94,0x93,0xb2,0xff,0x5c,0xd7,0x18,0x97,0x19,0x69,0x16,0x45,0x17, - 0x29,0x19,0x4e,0x1a,0x17,0x15,0x88,0xff,0x16,0x72,0x1a,0x23,0x15, - 0xbf,0x7f,0x5f,0x17,0xff,0x17,0xff,0x18,0xbf,0x17,0xff,0xfe,0x18, - 0x9f,0x17,0xff,0x7c,0x62,0x11,0x7f,0x00,0x3f,0x00,0x3f,0x00,0x26}; - -static const UINT8 icon24bm[97] = { // 32x32 - 0x06,0x5f,0x00,0x00,0x09,0xff,0x00,0x06,0x04,0x8a,0x07,0x11,0x08, - 0x95,0x07,0x4d,0xff,0x08,0x50,0x07,0x91,0x08,0x0c,0x07,0x93,0x08, - 0x0a,0x07,0x95,0x08,0x08,0x07,0x97,0xff,0x08,0x06,0x07,0x99,0x08, - 0x05,0x07,0xdb,0x08,0x02,0x07,0x9c,0x08,0x02,0x07,0xfe,0xff,0x00, - 0x3f,0x00,0x3f,0x30,0x3f,0x48,0x5f,0x60,0x63,0x70,0x5f,0x80,0x60, - 0x90,0x60,0xff,0xa0,0x60,0xb0,0x60,0xc0,0x60,0xd0,0x61,0x08,0x4a, - 0x07,0xd9,0x08,0x05,0x07,0xda,0xfc,0x08,0x04,0x07,0xdb,0x08,0x03, - 0x07,0xdc,0x08,0x02,0x03,0x0a}; - -static const UINT8 icon24c[200] = { // 32x32 - 0x07,0x19,0x00,0x80,0x80,0x01,0x7f,0x01,0x04,0xff,0xff,0x01,0x02, - 0x0e,0xc0,0xc0,0xc0,0x00,0x00,0x50,0x2e,0x07,0x31,0x0b,0x80,0xff, - 0x00,0x49,0x2f,0x8e,0x01,0x03,0x2f,0xc9,0x2e,0x12,0x61,0x4c,0x2f, - 0x94,0x61,0x47,0xff,0x2e,0x18,0x61,0x46,0x2f,0x9a,0x61,0x41,0x2e, - 0x1e,0x61,0x40,0x2f,0x8b,0x25,0x05,0xff,0x00,0x05,0x05,0x83,0x61, - 0x40,0x5e,0x0f,0x00,0x0e,0x61,0x40,0x2f,0xa6,0x61,0x35,0xff,0xbc, - 0x92,0x2f,0x99,0x61,0x32,0x2f,0xac,0x61,0x2f,0x2e,0x12,0x2f,0x9f, - 0x61,0x2c,0xff,0x2f,0x95,0x0a,0x02,0x00,0x08,0x40,0x16,0x2e,0x39, - 0x50,0x87,0x00,0x05,0x05,0x83,0xff,0x10,0x16,0x2f,0xb8,0x91,0x0c, - 0x10,0x19,0x2e,0x39,0x91,0x08,0x11,0x99,0x61,0x20,0xff,0x2f,0x9d, - 0x1f,0x05,0x8e,0x14,0x61,0x23,0x5e,0x1e,0x91,0x08,0x10,0x1c,0x61, - 0x1a,0xff,0x2f,0xa4,0x01,0x23,0x2f,0x93,0x2e,0x23,0x4d,0x85,0x91, - 0x20,0x61,0x14,0x8e,0x27,0xff,0x00,0x08,0x61,0x2b,0x8c,0xa7,0x2f, - 0xa8,0x61,0x0e,0x2f,0xa6,0x8f,0xa6,0x61,0x11,0xff,0xec,0xc8,0x2f, - 0xe7,0xf1,0x11,0x31,0x4a,0x2e,0x11,0x31,0x09,0x00,0x46,0x2e,0x11, - 0xc0,0x00,0x7f,0x00,0x3c}; - -static const UINT8 icon24cm[106] = { // 32x32 - 0x06,0x47,0x00,0x00,0x0b,0xff,0xff,0xff,0x03,0xcc,0x00,0x0e,0x07, - 0x82,0xff,0x08,0x1b,0x07,0x84,0x08,0x5a,0x07,0xc7,0x08,0x16,0x07, - 0x88,0x08,0x16,0x07,0xde,0xff,0x07,0x8a,0x08,0x14,0x07,0xde,0x07, - 0x8c,0x08,0x12,0x07,0xde,0x07,0x8e,0x08,0x10,0xff,0x07,0xde,0x07, - 0x90,0x08,0x0e,0x07,0xde,0x07,0x92,0x08,0x0c,0x07,0xde,0x07,0x94, - 0xff,0x08,0x0a,0x07,0xde,0x07,0x96,0x08,0x08,0x07,0xde,0x07,0x98, - 0x08,0x06,0x07,0xde,0xff,0x07,0x9a,0x08,0x04,0x07,0xde,0x07,0x9c, - 0x08,0x02,0x07,0xfe,0x00,0x20,0x18,0x20,0xe0,0x08,0x1e,0x50,0x63, - 0x60,0x5b}; - -static const UINT8 icon24d[179] = { // 32x32 - 0x07,0x43,0x80,0x00,0x7f,0xc0,0xc0,0xc0,0xff,0x00,0x10,0x0a,0x02, - 0xf8,0x2b,0x53,0x34,0x44,0x2c,0xa6,0x32,0xb5,0x1f,0x17,0xff,0x00, - 0x00,0xdf,0x01,0x08,0x40,0x17,0x00,0x00,0x1c,0x2e,0x17,0x1c,0x85, - 0x01,0x0f,0x14,0x18,0xff,0x2e,0x31,0x2f,0xab,0x31,0x14,0xb9,0xa0, - 0x8f,0xa6,0x16,0x08,0x5e,0x2d,0x00,0x31,0xff,0x29,0x85,0x00,0x08, - 0x47,0x9d,0x00,0x32,0x61,0x05,0x2f,0x88,0x46,0xa0,0xbf,0xac,0xff, - 0x61,0x11,0x79,0xa6,0x2f,0xff,0x2f,0xff,0x2f,0xd8,0xf7,0x02,0x2f, - 0xcd,0x28,0x02,0xff,0x2f,0x8b,0x61,0x24,0x2f,0xab,0x2e,0x0e,0x61, - 0x24,0x2f,0xa8,0x5e,0x11,0x61,0x1e,0xff,0x2c,0x8e,0x32,0x9f,0x2e, - 0x14,0x00,0x02,0x0b,0x82,0xf4,0x24,0x8c,0xae,0x31,0x4a,0xff,0x2e, - 0x1d,0x31,0x08,0xc5,0xa1,0xb9,0xa8,0x31,0x17,0x32,0xa9,0x2c,0x85, - 0x2e,0x29,0xff,0x32,0x8e,0x34,0x17,0x2b,0x08,0x2c,0xb2,0x34,0x23, - 0x2b,0x41,0xfe,0x9d,0x2f,0xff,0xff,0x31,0x3f,0x2f,0xd6,0x31,0x08, - 0x2f,0xd9,0xf8,0x88,0x2f,0xd9,0x00,0x7f,0x00,0x0c}; - -static const UINT8 icon24dm[97] = { // 32x32 - 0x06,0x5f,0x00,0x00,0x09,0xff,0x00,0x06,0x04,0x8a,0x07,0x11,0x08, - 0x95,0x07,0x4d,0xff,0x08,0x50,0x07,0x91,0x08,0x0c,0x07,0x93,0x08, - 0x0a,0x07,0x95,0x08,0x08,0x07,0x97,0xff,0x08,0x06,0x07,0x99,0x08, - 0x05,0x07,0xdb,0x08,0x02,0x07,0x9c,0x08,0x02,0x07,0xfe,0xff,0x00, - 0x3f,0x00,0x3f,0x30,0x3f,0x48,0x5f,0x60,0x63,0x70,0x5f,0x80,0x60, - 0x90,0x60,0xff,0xa0,0x60,0xb0,0x60,0xc0,0x60,0xd0,0x61,0x08,0x4a, - 0x07,0xd9,0x08,0x05,0x07,0xda,0xfc,0x08,0x04,0x07,0xdb,0x08,0x03, - 0x07,0xdc,0x08,0x02,0x03,0x0a}; - -static const UINT8 iconfld[75] = { // 32x32 - 0x09,0x18,0x00,0x9c,0x9c,0x04,0x84,0x00,0x41,0x9c,0x9c,0xff,0x3f, - 0xff,0xff,0x06,0x02,0x04,0x14,0xc4,0x3f,0xb8,0x1c,0xc4,0x3f,0xb8, - 0x22,0x83,0xc4,0x39,0x9c,0x9c,0x63,0xce,0xce,0x04,0x29,0xc4,0x03, - 0xaf,0x04,0x2e,0xff,0x00,0x55,0x00,0x00,0x05,0xbe,0x04,0x06,0x02, - 0x04,0x50,0x1f,0x63,0xce,0xce,0xbf,0xff,0xbf,0xff,0xbf,0xff,0xbe, - 0xc5,0x10,0x02,0xe0,0x04,0x56,0xbe,0x03,0x01,0xde}; - -static const UINT8 iconflp[113] = { // 32x32 - 0x09,0x18,0x00,0x9c,0x9c,0x04,0x84,0x00,0x41,0x9c,0x9c,0xff,0x3f, - 0xff,0xff,0x06,0x02,0x04,0x14,0xc4,0x3f,0xb8,0x1c,0xc4,0x3f,0xb8, - 0x22,0x83,0xc4,0x39,0x9c,0x9c,0x63,0xce,0xce,0x04,0x29,0xc4,0x03, - 0xaf,0x04,0x2e,0xff,0x00,0x55,0x00,0x00,0x05,0xbe,0x04,0x06,0x02, - 0x04,0x50,0x1f,0x63,0xce,0xce,0xbe,0xdd,0x3a,0x03,0x3e,0x02,0xbe, - 0x55,0xb8,0x05,0xff,0xc4,0x3b,0xbe,0x7a,0xb8,0x0b,0xc4,0x38,0xbe, - 0x77,0xb8,0x11,0xc4,0x35,0xbe,0x77,0xff,0xd0,0x0e,0xac,0x2f,0xbe, - 0xef,0x00,0x29,0xbe,0x2f,0xc4,0x2f,0xbe,0x32,0x04,0x3b,0xf8,0xbf, - 0x28,0x10,0x02,0x04,0x56,0xbe,0x03,0x01,0xde}; - -static const UINT8 iconfldm[38] = { // 32x32 - 0x0a,0x5f,0x00,0x00,0x22,0xff,0x00,0x08,0x78,0x1e,0x80,0x14,0x78, - 0x0b,0x80,0x12,0xfb,0x78,0x0d,0x80,0x10,0x78,0x0f,0xb0,0x0f,0x7c, - 0x1d,0xff,0x7c,0x1f,0x02,0x60,0x60,0x00,0x78,0x1e,0x00,0x7f}; - -static const UINT8 iconfil[178] = { // 32x32 - 0x07,0x5b,0x84,0x00,0x6a,0xff,0x00,0x34,0x1c,0x02,0x00,0x00,0x22, - 0x2f,0xbb,0xc7,0x31,0x23,0x2f,0xbb,0xc6,0xc6,0xc6,0x31,0x20,0x2f, - 0xbb,0x02,0x82,0xff,0x31,0x20,0x2f,0xbe,0x31,0x20,0xef,0xff,0x00, - 0x27,0x62,0x82,0x2f,0xff,0x2f,0xfe,0xff,0x1a,0x8b,0x2f,0xcd,0xdd, - 0x97,0x2f,0xb2,0x4d,0x91,0x27,0x8b,0x18,0x04,0x01,0x04,0xff,0x31, - 0x10,0x2f,0xac,0x02,0x88,0x2e,0x0d,0x2f,0x8a,0x31,0x07,0x8f,0xb5, - 0x84,0x91,0xff,0x2f,0xc7,0xdd,0x11,0x5e,0x0c,0x1b,0x09,0x2f,0xbc, - 0x02,0x88,0x2b,0x07,0xb8,0x8a,0xff,0xf1,0x16,0x8f,0xae,0x01,0x0b, - 0xee,0x8b,0x28,0x83,0x01,0x03,0x2f,0xb8,0x90,0x10,0xff,0xee,0x8d, - 0x2f,0x87,0x0b,0x88,0x2f,0xb5,0x90,0x0a,0xee,0x8d,0x2f,0xc0,0x90, - 0x10,0xff,0xee,0x93,0x32,0x84,0xef,0xb6,0x8f,0x92,0xee,0x98,0x2f, - 0xb7,0x02,0x88,0x25,0x14,0xff,0x0d,0x0b,0x8f,0xb5,0x2c,0x9a,0x76, - 0x17,0xbf,0xad,0x00,0x31,0x2f,0xff,0x2f,0xff,0xfc,0x2f,0xff,0x2f, - 0xfa,0x0d,0x02,0x00,0x44,0x2f,0x94,0x00,0x56}; - -static const UINT8 iconfilm[34] = { // 32x32 - 0x0b,0x0f,0x00,0x00,0x00,0xff,0x00,0x12,0xb0,0x02,0x00,0x08,0xf8, - 0x13,0x55,0xff,0xf8,0x1f,0xff,0xf8,0x1f,0xff,0xf8,0x1f,0xff,0xf8, - 0x1f,0x50,0xff,0xf8,0x1f,0xff,0xfb,0x22}; - -static const MENURES icon24[7] = { - {32, 32, icon24a, icon24am}, {32, 32, icon24b, icon24bm}, - {32, 32, icon24c, icon24cm}, {32, 32, icon24d, icon24dm}, - {32, 32, iconfld, iconfldm}, {32, 32, iconflp, iconfldm}, - {32, 32, iconfil, iconfilm}}; - - -void menuicon_initialize(void) { - - int i; - - ZeroMemory(iconreg, sizeof(iconreg)); - ZeroMemory(iconcache, sizeof(iconcache)); - for (i=0; i<7; i++) { - iconreg[i].res = icon24 + i; - } -} - -void menuicon_deinitialize(void) { - - ICONCACHE *ic; - ICONCACHE *icterm; - - ic = iconcache; - icterm = ic + MICON_CACHE; - do { - vram_destroy(ic->hdl); - } while(++ic < icterm); - ZeroMemory(iconcache, sizeof(iconcache)); -} - -void menuicon_regist(UINT16 id, const MENURES *res) { - - if ((id != 0) && (id < MICON_MAX)) { - iconreg[id - 1].res = res; - } -} - -VRAMHDL menuicon_lock(UINT16 id, int width, int height, int bpp) { - - ICONCACHE *icorg; - ICONCACHE *ic; - ICONCACHE *icterm; - VRAMHDL hdl; -const MENURES *res; - VRAMHDL ret; - - if ((id == 0) || (id >= MICON_MAX)) { - return(NULL); - } - icorg = iconcache; - ic = icorg; - icterm = icorg + MICON_CACHE; - do { - if (ic->id == id) { - hdl = ic->hdl; - if ((hdl->width == width) && (hdl->height == height) && - (hdl->bpp == bpp)) { - ic->count++; - return(hdl); - } - } - } while(++ic < icterm); - res = (MENURES *)(iconreg[id - 1].res); - if (res == NULL) { - return(NULL); - } - hdl = menuvram_resload(res, 24); - ret = vram_resize(hdl, width, height, bpp); - vram_destroy(hdl); - if (ret) { - do { - ic--; - if (ic->count == 0) { - vram_destroy(ic->hdl); - while(ic > icorg) { - CopyMemory(ic, ic - 1, sizeof(ICONCACHE)); - ic--; - } - ic->id = id; - ic->count = 1; - ic->hdl = ret; - break; - } - } while(ic > icorg); - } - return(ret); -} - -void menuicon_unlock(VRAMHDL vram) { - - ICONCACHE *ic; - ICONCACHE *icterm; - - if (vram) { - ic = iconcache; - icterm = ic + MICON_CACHE; - do { - if (ic->hdl == vram) { - ic->count--; - return; - } - } while(++ic < icterm); - vram_destroy(vram); - } -} - +#include +#include +#include + + +#define MICON_MAX 16 +#define MICON_CACHE 8 + + +typedef struct { +// UINT16 type; +const void *res; +} ICONREG; + +typedef struct { + UINT16 id; + UINT16 count; + VRAMHDL hdl; +} ICONCACHE; + + +static ICONREG iconreg[MICON_MAX - 1]; +static ICONCACHE iconcache[MICON_CACHE]; + +static const UINT8 icon24a[178] = { // 32x32 + 0x07,0x17,0x00,0x00,0x80,0x01,0x7f,0xff,0x01,0x16,0x2b,0x56,0x34, + 0x44,0xff,0x2e,0x29,0x31,0x2f,0x2c,0xaf,0x32,0xac,0x2e,0x3b,0x31, + 0x23,0x2f,0xc2,0x00,0x14,0xff,0x2e,0x14,0x00,0x02,0x26,0x9d,0x10, + 0x16,0x2e,0x27,0x00,0x05,0x2e,0x1a,0x10,0x19,0xff,0x8c,0x9e,0x00, + 0x0e,0x2e,0x1a,0x10,0x16,0x5f,0xaa,0x20,0x91,0x3e,0xa0,0x2f,0x8b, + 0xff,0xeb,0x1a,0x23,0x94,0x2e,0x22,0x31,0x0c,0x2f,0x9a,0x26,0x91, + 0x2e,0x28,0x2f,0xa7,0xff,0x31,0x1a,0x1a,0x9d,0x2f,0xa9,0x31,0x14, + 0x19,0x20,0x2f,0xff,0x8f,0xe6,0xef,0xdc,0xff,0x26,0x94,0x31,0x28, + 0x2f,0x86,0x31,0x17,0x23,0x9a,0x31,0x22,0x2e,0x09,0x2f,0x94,0xff, + 0x20,0xa0,0x10,0x1f,0x2f,0x9e,0x20,0x8b,0x9e,0xa0,0x5f,0xa0,0x31, + 0x1a,0xe0,0x9c,0xff,0x2e,0x27,0xf4,0x20,0x01,0x2b,0x2e,0x15,0x2f, + 0xe2,0x31,0x43,0x2e,0x1b,0x31,0x0a,0xff,0x32,0xb2,0x1a,0x83,0x00, + 0x29,0x31,0x2e,0x2c,0xaa,0x64,0x10,0x34,0x1a,0x10,0x06,0xf8,0x00, + 0x3e,0x34,0x0a,0x01,0x0c,0x00,0x7f,0x00,0x66}; + +static const UINT8 icon24am[83] = { // 32x32 + 0x06,0x5f,0x00,0x00,0x09,0xff,0x00,0x06,0x04,0x8a,0x07,0x11,0x08, + 0x96,0x07,0x8d,0xff,0x08,0x0f,0x07,0x4f,0x08,0x4e,0x07,0x93,0x08, + 0x0a,0x07,0x95,0x08,0x09,0x07,0xd7,0xfe,0x08,0x06,0x07,0x98,0x08, + 0x05,0x07,0x9a,0x07,0xe0,0x08,0x03,0x07,0xdc,0xff,0xff,0x07,0x9e, + 0x07,0xff,0x00,0x3f,0x00,0x3f,0x00,0x21,0x38,0x3f,0x57,0xdf,0x68, + 0x21,0xff,0x78,0x7b,0x98,0x24,0xa8,0x61,0xb8,0x5f,0xc8,0x60,0xd8, + 0x60,0xe8,0x61,0xf8,0x56}; + +static const UINT8 icon24b[195] = { // 32x32 + 0x06,0x61,0x80,0x00,0x3f,0x00,0x3f,0xc0,0xc0,0xc0,0xff,0x00,0x10, + 0xff,0x05,0x02,0x15,0xbf,0x15,0x93,0x1a,0x3f,0x16,0x6b,0x19,0x75, + 0x16,0x6f,0x00,0x0b,0x73,0x00,0x00,0x1c,0x17,0x17,0x33,0x83,0x00, + 0x00,0x00,0x8e,0x38,0xd7,0xff,0x17,0x35,0x13,0x49,0x18,0xb4,0x5c, + 0xdb,0x13,0x45,0x04,0x51,0x05,0xd1,0x24,0x8a,0xff,0x2f,0x26,0x13, + 0x55,0x17,0xdf,0x30,0x85,0x8c,0x27,0x13,0x4d,0x62,0xcf,0x93,0x99, + 0xff,0x18,0x8b,0x9e,0x1d,0x5b,0x4c,0x17,0x22,0x30,0x91,0xb9,0x29, + 0x17,0x26,0x17,0xf5,0xff,0x17,0x29,0x17,0xfb,0xf7,0x66,0x2f,0xf9, + 0xf2,0xe8,0x8f,0xe4,0x00,0x34,0x8f,0xce,0xff,0x30,0xa3,0x92,0x0f, + 0x2f,0x28,0x30,0xa7,0xa6,0x68,0x2f,0x11,0x30,0xa4,0xbe,0x74,0xff, + 0x00,0x0b,0x05,0xc2,0x47,0xff,0x17,0x19,0x18,0xa3,0x5d,0xb2,0x18, + 0x94,0x93,0xb2,0xff,0x5c,0xd7,0x18,0x97,0x19,0x69,0x16,0x45,0x17, + 0x29,0x19,0x4e,0x1a,0x17,0x15,0x88,0xff,0x16,0x72,0x1a,0x23,0x15, + 0xbf,0x7f,0x5f,0x17,0xff,0x17,0xff,0x18,0xbf,0x17,0xff,0xfe,0x18, + 0x9f,0x17,0xff,0x7c,0x62,0x11,0x7f,0x00,0x3f,0x00,0x3f,0x00,0x26}; + +static const UINT8 icon24bm[97] = { // 32x32 + 0x06,0x5f,0x00,0x00,0x09,0xff,0x00,0x06,0x04,0x8a,0x07,0x11,0x08, + 0x95,0x07,0x4d,0xff,0x08,0x50,0x07,0x91,0x08,0x0c,0x07,0x93,0x08, + 0x0a,0x07,0x95,0x08,0x08,0x07,0x97,0xff,0x08,0x06,0x07,0x99,0x08, + 0x05,0x07,0xdb,0x08,0x02,0x07,0x9c,0x08,0x02,0x07,0xfe,0xff,0x00, + 0x3f,0x00,0x3f,0x30,0x3f,0x48,0x5f,0x60,0x63,0x70,0x5f,0x80,0x60, + 0x90,0x60,0xff,0xa0,0x60,0xb0,0x60,0xc0,0x60,0xd0,0x61,0x08,0x4a, + 0x07,0xd9,0x08,0x05,0x07,0xda,0xfc,0x08,0x04,0x07,0xdb,0x08,0x03, + 0x07,0xdc,0x08,0x02,0x03,0x0a}; + +static const UINT8 icon24c[200] = { // 32x32 + 0x07,0x19,0x00,0x80,0x80,0x01,0x7f,0x01,0x04,0xff,0xff,0x01,0x02, + 0x0e,0xc0,0xc0,0xc0,0x00,0x00,0x50,0x2e,0x07,0x31,0x0b,0x80,0xff, + 0x00,0x49,0x2f,0x8e,0x01,0x03,0x2f,0xc9,0x2e,0x12,0x61,0x4c,0x2f, + 0x94,0x61,0x47,0xff,0x2e,0x18,0x61,0x46,0x2f,0x9a,0x61,0x41,0x2e, + 0x1e,0x61,0x40,0x2f,0x8b,0x25,0x05,0xff,0x00,0x05,0x05,0x83,0x61, + 0x40,0x5e,0x0f,0x00,0x0e,0x61,0x40,0x2f,0xa6,0x61,0x35,0xff,0xbc, + 0x92,0x2f,0x99,0x61,0x32,0x2f,0xac,0x61,0x2f,0x2e,0x12,0x2f,0x9f, + 0x61,0x2c,0xff,0x2f,0x95,0x0a,0x02,0x00,0x08,0x40,0x16,0x2e,0x39, + 0x50,0x87,0x00,0x05,0x05,0x83,0xff,0x10,0x16,0x2f,0xb8,0x91,0x0c, + 0x10,0x19,0x2e,0x39,0x91,0x08,0x11,0x99,0x61,0x20,0xff,0x2f,0x9d, + 0x1f,0x05,0x8e,0x14,0x61,0x23,0x5e,0x1e,0x91,0x08,0x10,0x1c,0x61, + 0x1a,0xff,0x2f,0xa4,0x01,0x23,0x2f,0x93,0x2e,0x23,0x4d,0x85,0x91, + 0x20,0x61,0x14,0x8e,0x27,0xff,0x00,0x08,0x61,0x2b,0x8c,0xa7,0x2f, + 0xa8,0x61,0x0e,0x2f,0xa6,0x8f,0xa6,0x61,0x11,0xff,0xec,0xc8,0x2f, + 0xe7,0xf1,0x11,0x31,0x4a,0x2e,0x11,0x31,0x09,0x00,0x46,0x2e,0x11, + 0xc0,0x00,0x7f,0x00,0x3c}; + +static const UINT8 icon24cm[106] = { // 32x32 + 0x06,0x47,0x00,0x00,0x0b,0xff,0xff,0xff,0x03,0xcc,0x00,0x0e,0x07, + 0x82,0xff,0x08,0x1b,0x07,0x84,0x08,0x5a,0x07,0xc7,0x08,0x16,0x07, + 0x88,0x08,0x16,0x07,0xde,0xff,0x07,0x8a,0x08,0x14,0x07,0xde,0x07, + 0x8c,0x08,0x12,0x07,0xde,0x07,0x8e,0x08,0x10,0xff,0x07,0xde,0x07, + 0x90,0x08,0x0e,0x07,0xde,0x07,0x92,0x08,0x0c,0x07,0xde,0x07,0x94, + 0xff,0x08,0x0a,0x07,0xde,0x07,0x96,0x08,0x08,0x07,0xde,0x07,0x98, + 0x08,0x06,0x07,0xde,0xff,0x07,0x9a,0x08,0x04,0x07,0xde,0x07,0x9c, + 0x08,0x02,0x07,0xfe,0x00,0x20,0x18,0x20,0xe0,0x08,0x1e,0x50,0x63, + 0x60,0x5b}; + +static const UINT8 icon24d[179] = { // 32x32 + 0x07,0x43,0x80,0x00,0x7f,0xc0,0xc0,0xc0,0xff,0x00,0x10,0x0a,0x02, + 0xf8,0x2b,0x53,0x34,0x44,0x2c,0xa6,0x32,0xb5,0x1f,0x17,0xff,0x00, + 0x00,0xdf,0x01,0x08,0x40,0x17,0x00,0x00,0x1c,0x2e,0x17,0x1c,0x85, + 0x01,0x0f,0x14,0x18,0xff,0x2e,0x31,0x2f,0xab,0x31,0x14,0xb9,0xa0, + 0x8f,0xa6,0x16,0x08,0x5e,0x2d,0x00,0x31,0xff,0x29,0x85,0x00,0x08, + 0x47,0x9d,0x00,0x32,0x61,0x05,0x2f,0x88,0x46,0xa0,0xbf,0xac,0xff, + 0x61,0x11,0x79,0xa6,0x2f,0xff,0x2f,0xff,0x2f,0xd8,0xf7,0x02,0x2f, + 0xcd,0x28,0x02,0xff,0x2f,0x8b,0x61,0x24,0x2f,0xab,0x2e,0x0e,0x61, + 0x24,0x2f,0xa8,0x5e,0x11,0x61,0x1e,0xff,0x2c,0x8e,0x32,0x9f,0x2e, + 0x14,0x00,0x02,0x0b,0x82,0xf4,0x24,0x8c,0xae,0x31,0x4a,0xff,0x2e, + 0x1d,0x31,0x08,0xc5,0xa1,0xb9,0xa8,0x31,0x17,0x32,0xa9,0x2c,0x85, + 0x2e,0x29,0xff,0x32,0x8e,0x34,0x17,0x2b,0x08,0x2c,0xb2,0x34,0x23, + 0x2b,0x41,0xfe,0x9d,0x2f,0xff,0xff,0x31,0x3f,0x2f,0xd6,0x31,0x08, + 0x2f,0xd9,0xf8,0x88,0x2f,0xd9,0x00,0x7f,0x00,0x0c}; + +static const UINT8 icon24dm[97] = { // 32x32 + 0x06,0x5f,0x00,0x00,0x09,0xff,0x00,0x06,0x04,0x8a,0x07,0x11,0x08, + 0x95,0x07,0x4d,0xff,0x08,0x50,0x07,0x91,0x08,0x0c,0x07,0x93,0x08, + 0x0a,0x07,0x95,0x08,0x08,0x07,0x97,0xff,0x08,0x06,0x07,0x99,0x08, + 0x05,0x07,0xdb,0x08,0x02,0x07,0x9c,0x08,0x02,0x07,0xfe,0xff,0x00, + 0x3f,0x00,0x3f,0x30,0x3f,0x48,0x5f,0x60,0x63,0x70,0x5f,0x80,0x60, + 0x90,0x60,0xff,0xa0,0x60,0xb0,0x60,0xc0,0x60,0xd0,0x61,0x08,0x4a, + 0x07,0xd9,0x08,0x05,0x07,0xda,0xfc,0x08,0x04,0x07,0xdb,0x08,0x03, + 0x07,0xdc,0x08,0x02,0x03,0x0a}; + +static const UINT8 iconfld[75] = { // 32x32 + 0x09,0x18,0x00,0x9c,0x9c,0x04,0x84,0x00,0x41,0x9c,0x9c,0xff,0x3f, + 0xff,0xff,0x06,0x02,0x04,0x14,0xc4,0x3f,0xb8,0x1c,0xc4,0x3f,0xb8, + 0x22,0x83,0xc4,0x39,0x9c,0x9c,0x63,0xce,0xce,0x04,0x29,0xc4,0x03, + 0xaf,0x04,0x2e,0xff,0x00,0x55,0x00,0x00,0x05,0xbe,0x04,0x06,0x02, + 0x04,0x50,0x1f,0x63,0xce,0xce,0xbf,0xff,0xbf,0xff,0xbf,0xff,0xbe, + 0xc5,0x10,0x02,0xe0,0x04,0x56,0xbe,0x03,0x01,0xde}; + +static const UINT8 iconflp[113] = { // 32x32 + 0x09,0x18,0x00,0x9c,0x9c,0x04,0x84,0x00,0x41,0x9c,0x9c,0xff,0x3f, + 0xff,0xff,0x06,0x02,0x04,0x14,0xc4,0x3f,0xb8,0x1c,0xc4,0x3f,0xb8, + 0x22,0x83,0xc4,0x39,0x9c,0x9c,0x63,0xce,0xce,0x04,0x29,0xc4,0x03, + 0xaf,0x04,0x2e,0xff,0x00,0x55,0x00,0x00,0x05,0xbe,0x04,0x06,0x02, + 0x04,0x50,0x1f,0x63,0xce,0xce,0xbe,0xdd,0x3a,0x03,0x3e,0x02,0xbe, + 0x55,0xb8,0x05,0xff,0xc4,0x3b,0xbe,0x7a,0xb8,0x0b,0xc4,0x38,0xbe, + 0x77,0xb8,0x11,0xc4,0x35,0xbe,0x77,0xff,0xd0,0x0e,0xac,0x2f,0xbe, + 0xef,0x00,0x29,0xbe,0x2f,0xc4,0x2f,0xbe,0x32,0x04,0x3b,0xf8,0xbf, + 0x28,0x10,0x02,0x04,0x56,0xbe,0x03,0x01,0xde}; + +static const UINT8 iconfldm[38] = { // 32x32 + 0x0a,0x5f,0x00,0x00,0x22,0xff,0x00,0x08,0x78,0x1e,0x80,0x14,0x78, + 0x0b,0x80,0x12,0xfb,0x78,0x0d,0x80,0x10,0x78,0x0f,0xb0,0x0f,0x7c, + 0x1d,0xff,0x7c,0x1f,0x02,0x60,0x60,0x00,0x78,0x1e,0x00,0x7f}; + +static const UINT8 iconfil[178] = { // 32x32 + 0x07,0x5b,0x84,0x00,0x6a,0xff,0x00,0x34,0x1c,0x02,0x00,0x00,0x22, + 0x2f,0xbb,0xc7,0x31,0x23,0x2f,0xbb,0xc6,0xc6,0xc6,0x31,0x20,0x2f, + 0xbb,0x02,0x82,0xff,0x31,0x20,0x2f,0xbe,0x31,0x20,0xef,0xff,0x00, + 0x27,0x62,0x82,0x2f,0xff,0x2f,0xfe,0xff,0x1a,0x8b,0x2f,0xcd,0xdd, + 0x97,0x2f,0xb2,0x4d,0x91,0x27,0x8b,0x18,0x04,0x01,0x04,0xff,0x31, + 0x10,0x2f,0xac,0x02,0x88,0x2e,0x0d,0x2f,0x8a,0x31,0x07,0x8f,0xb5, + 0x84,0x91,0xff,0x2f,0xc7,0xdd,0x11,0x5e,0x0c,0x1b,0x09,0x2f,0xbc, + 0x02,0x88,0x2b,0x07,0xb8,0x8a,0xff,0xf1,0x16,0x8f,0xae,0x01,0x0b, + 0xee,0x8b,0x28,0x83,0x01,0x03,0x2f,0xb8,0x90,0x10,0xff,0xee,0x8d, + 0x2f,0x87,0x0b,0x88,0x2f,0xb5,0x90,0x0a,0xee,0x8d,0x2f,0xc0,0x90, + 0x10,0xff,0xee,0x93,0x32,0x84,0xef,0xb6,0x8f,0x92,0xee,0x98,0x2f, + 0xb7,0x02,0x88,0x25,0x14,0xff,0x0d,0x0b,0x8f,0xb5,0x2c,0x9a,0x76, + 0x17,0xbf,0xad,0x00,0x31,0x2f,0xff,0x2f,0xff,0xfc,0x2f,0xff,0x2f, + 0xfa,0x0d,0x02,0x00,0x44,0x2f,0x94,0x00,0x56}; + +static const UINT8 iconfilm[34] = { // 32x32 + 0x0b,0x0f,0x00,0x00,0x00,0xff,0x00,0x12,0xb0,0x02,0x00,0x08,0xf8, + 0x13,0x55,0xff,0xf8,0x1f,0xff,0xf8,0x1f,0xff,0xf8,0x1f,0xff,0xf8, + 0x1f,0x50,0xff,0xf8,0x1f,0xff,0xfb,0x22}; + +static const MENURES icon24[7] = { + {32, 32, icon24a, icon24am}, {32, 32, icon24b, icon24bm}, + {32, 32, icon24c, icon24cm}, {32, 32, icon24d, icon24dm}, + {32, 32, iconfld, iconfldm}, {32, 32, iconflp, iconfldm}, + {32, 32, iconfil, iconfilm}}; + + +void menuicon_initialize(void) { + + int i; + + ZeroMemory(iconreg, sizeof(iconreg)); + ZeroMemory(iconcache, sizeof(iconcache)); + for (i=0; i<7; i++) { + iconreg[i].res = icon24 + i; + } +} + +void menuicon_deinitialize(void) { + + ICONCACHE *ic; + ICONCACHE *icterm; + + ic = iconcache; + icterm = ic + MICON_CACHE; + do { + vram_destroy(ic->hdl); + } while(++ic < icterm); + ZeroMemory(iconcache, sizeof(iconcache)); +} + +void menuicon_regist(UINT16 id, const MENURES *res) { + + if ((id != 0) && (id < MICON_MAX)) { + iconreg[id - 1].res = res; + } +} + +VRAMHDL menuicon_lock(UINT16 id, int width, int height, int bpp) { + + ICONCACHE *icorg; + ICONCACHE *ic; + ICONCACHE *icterm; + VRAMHDL hdl; +const MENURES *res; + VRAMHDL ret; + + if ((id == 0) || (id >= MICON_MAX)) { + return(NULL); + } + icorg = iconcache; + ic = icorg; + icterm = icorg + MICON_CACHE; + do { + if (ic->id == id) { + hdl = ic->hdl; + if ((hdl->width == width) && (hdl->height == height) && + (hdl->bpp == bpp)) { + ic->count++; + return(hdl); + } + } + } while(++ic < icterm); + res = (MENURES *)(iconreg[id - 1].res); + if (res == NULL) { + return(NULL); + } + hdl = menuvram_resload(res, 24); + ret = vram_resize(hdl, width, height, bpp); + vram_destroy(hdl); + if (ret) { + do { + ic--; + if (ic->count == 0) { + vram_destroy(ic->hdl); + while(ic > icorg) { + CopyMemory(ic, ic - 1, sizeof(ICONCACHE)); + ic--; + } + ic->id = id; + ic->count = 1; + ic->hdl = ret; + break; + } + } while(ic > icorg); + } + return(ret); +} + +void menuicon_unlock(VRAMHDL vram) { + + ICONCACHE *ic; + ICONCACHE *icterm; + + if (vram) { + ic = iconcache; + icterm = ic + MICON_CACHE; + do { + if (ic->hdl == vram) { + ic->count--; + return; + } + } while(++ic < icterm); + vram_destroy(vram); + } +} + diff --git a/embed/menubase/menuicon.h b/embed/menubase/menuicon.h old mode 100755 new mode 100644 index c189e4df..633da951 --- a/embed/menubase/menuicon.h +++ b/embed/menubase/menuicon.h @@ -1,27 +1,27 @@ - -enum { - MICON_NULL = 0, - MICON_STOP, - MICON_QUESTION, - MICON_EXCLAME, - MICON_INFO, - MICON_FOLDER, - MICON_FOLDERPARENT, - MICON_FILE, - MICON_USER -}; - -#ifdef __cplusplus -extern "C" { -#endif - -void menuicon_initialize(void); -void menuicon_deinitialize(void); -void menuicon_regist(UINT16 id, const MENURES *res); -VRAMHDL menuicon_lock(UINT16 id, int width, int height, int bpp); -void menuicon_unlock(VRAMHDL vram); - -#ifdef __cplusplus -} -#endif - + +enum { + MICON_NULL = 0, + MICON_STOP, + MICON_QUESTION, + MICON_EXCLAME, + MICON_INFO, + MICON_FOLDER, + MICON_FOLDERPARENT, + MICON_FILE, + MICON_USER +}; + +#ifdef __cplusplus +extern "C" { +#endif + +void menuicon_initialize(void); +void menuicon_deinitialize(void); +void menuicon_regist(UINT16 id, const MENURES *res); +VRAMHDL menuicon_lock(UINT16 id, int width, int height, int bpp); +void menuicon_unlock(VRAMHDL vram); + +#ifdef __cplusplus +} +#endif + diff --git a/embed/menubase/menumbox.c b/embed/menubase/menumbox.c old mode 100755 new mode 100644 index 43ed774c..e62a3733 --- a/embed/menubase/menumbox.c +++ b/embed/menubase/menumbox.c @@ -1,238 +1,238 @@ -#include -#include -#include -#include "menudeco.inc" -#include - - -typedef struct { - int ret; - UINT type; - int width; - int height; - int lines; - int fontsize; - OEMCHAR string[MENUMBOX_MAXLINE][MENUMBOX_MAXTEXT]; -} MBOX; - -static MBOX mbox; - -static const OEMCHAR *menumbox_txt[7] = { - mstr_ok, mstr_cancel, mstr_abort, mstr_retry, - mstr_ignore, mstr_yes, mstr_no}; - -static const UINT8 b_res[6][4] = { - {1, DID_OK, 0, 0}, - {2, DID_OK, DID_CANCEL, 0}, - {3, DID_ABORT, DID_RETRY, DID_IGNORE}, - {3, DID_YES, DID_NO, DID_CANCEL}, - {2, DID_YES, DID_NO, 0}, - {2, DID_RETRY, DID_NO, 0}}; - - -// ---- - -static BRESULT setmboxitem(MBOX *mb, const OEMCHAR *str, UINT type) { - - OEMCHAR *dst; - int rem; - int w; - OEMCHAR work[4]; - int width; - POINT_T pt; - int leng; - - if (mb == NULL) { - goto smbi_err; - } - ZeroMemory(mb, sizeof(MBOX)); - if (str == NULL) { - goto smbi_set; - } - if ((type & 0xf) >= 6) { - type &= ~0x0f; - } - mb->type = type; - width = MENUMBOX_WIDTH - - (MENUMBOX_SX + MENUMBOX_PXTEXT + MENUMBOX_LXTEXT); - if (mb->type & 0xf0) { - width -= MENUMBOX_CXICON; - } - dst = NULL; - rem = 0; - w = 0; - while(1) { - leng = milstr_charsize(str); - if (leng == 0) { - break; - } - if ((str[0] >= 0) && (str[0] < 0x20)) { - if (str[0] == '\n') { - dst = mb->string[mb->lines]; - mb->lines++; - if (mb->lines >= MENUMBOX_MAXLINE) { - break; - } - rem = NELEMENTS(mb->string[0]) - 1; - if (mb->width < w) { - mb->width = w; - } - w = 0; - } - } - else { - CopyMemory(work, str, leng * sizeof(OEMCHAR)); - work[leng] = '\0'; - fontmng_getsize(menubase.font, work, &pt); - if ((rem < leng) || ((w + pt.x) > width)) { - dst = mb->string[mb->lines]; - mb->lines++; - if (mb->lines >= MENUMBOX_MAXLINE) { - break; - } - rem = NELEMENTS(mb->string[0]) - 1; - if (mb->width < w) { - mb->width = w; - } - w = 0; - } - w += pt.x; - CopyMemory(dst, str, leng * sizeof(OEMCHAR)); - dst += leng; - rem -= leng; - } - str += leng; - } - if (mb->width < w) { - mb->width = w; - } - -smbi_set: - mb->width += (MENUMBOX_SX + MENUMBOX_PXTEXT + MENUMBOX_LXTEXT); - fontmng_getsize(menubase.font, mstr_fontcheck, &pt); - mb->fontsize = pt.y; - mb->height = mb->lines * mb->fontsize; - if (mb->type & 0xf0) { - mb->width += MENUMBOX_CXICON; - if (mb->height < MENUMBOX_CYICON) { - mb->height = MENUMBOX_CYICON; - } - } - mb->height += MENUMBOX_SY + - MENUMBOX_SYBTN + MENUMBOX_CYBTN + MENUMBOX_LYBTN; - - width = b_res[mb->type & 0x0f][0]; - width *= (MENUMBOX_CXBTN + MENUMBOX_PXBTN); - width += (MENUMBOX_SXBTN * 2) - MENUMBOX_PXBTN; - if (mb->width < width) { - mb->width = width; - } - return(SUCCESS); - -smbi_err: - return(FAILURE); -} - - -static void mbox_open(MBOX *mb) { - - int posy; - int posx; -const UINT8 *btn; - int cnt; - int btnid; - - posx = MENUMBOX_SX + MENUMBOX_PXTEXT; - posy = 0; - if (mb->type & 0xf0) { - menudlg_append(DLGTYPE_ICON, 0, 0, (void *)(INTPTR)((mb->type >> 4) & 0xf), - MENUMBOX_SX, MENUMBOX_SY, MENUMBOX_SZICON, MENUMBOX_SZICON); - posx += MENUMBOX_CXICON; - posy = MENUMBOX_CYICON - (mb->lines * mb->fontsize); - } - if (posy > 0) { - posy /= 2; - posy += MENUMBOX_SY; - } - else { - posy = MENUMBOX_SY; - } - cnt = 0; - while(cnt < mb->lines) { - menudlg_append(DLGTYPE_LTEXT, 0, 0, mb->string[cnt], - posx, posy, mb->width - posx, mb->fontsize); - posy += mb->fontsize; - cnt++; - } - - cnt = mb->type & 0x0f; - if (cnt >= 6) { - cnt = 0; - } - btn = b_res[cnt]; - cnt = *btn++; - posy = mb->height - (MENUMBOX_CYBTN + MENUMBOX_LYBTN); - posx = mb->width; - posx -= ((MENUMBOX_CXBTN + MENUMBOX_PXBTN) * cnt) - MENUMBOX_PXBTN; - posx >>= 1; - while(cnt) { - cnt--; - btnid = *btn++; - menudlg_append(DLGTYPE_BUTTON, (MENUID)btnid, 0, - menumbox_txt[btnid-1], - posx, posy, MENUMBOX_CXBTN, MENUMBOX_CYBTN); - posx += MENUMBOX_CXBTN + MENUMBOX_PXBTN; - } -} - - -static int mbox_cmd(int msg, MENUID id, long param) { - - MBOX *mb; - - switch(msg) { - case DLGMSG_CREATE: - mb = &mbox; - mbox_open(mb); - break; - - case DLGMSG_COMMAND: - switch(id) { - case DID_OK: - case DID_CANCEL: - case DID_ABORT: - case DID_RETRY: - case DID_IGNORE: - case DID_YES: - case DID_NO: - mb = &mbox; - mb->ret = id; - menubase_close(); - break; - } - break; - - case DLGMSG_CLOSE: - menubase_close(); - break; - } - (void)param; - return(0); -} - - -int menumbox(const OEMCHAR *string, const OEMCHAR *title, UINT type) { - - MBOX *mb; - - mb = &mbox; - if (setmboxitem(mb, string, type) == SUCCESS) { - menudlg_create(mb->width, mb->height, title, mbox_cmd); - menubase_modalproc(); - return(mb->ret); - } - else { - return(0); - } -} - +#include +#include +#include +#include "menudeco.inc" +#include + + +typedef struct { + int ret; + UINT type; + int width; + int height; + int lines; + int fontsize; + OEMCHAR string[MENUMBOX_MAXLINE][MENUMBOX_MAXTEXT]; +} MBOX; + +static MBOX mbox; + +static const OEMCHAR *menumbox_txt[7] = { + mstr_ok, mstr_cancel, mstr_abort, mstr_retry, + mstr_ignore, mstr_yes, mstr_no}; + +static const UINT8 b_res[6][4] = { + {1, DID_OK, 0, 0}, + {2, DID_OK, DID_CANCEL, 0}, + {3, DID_ABORT, DID_RETRY, DID_IGNORE}, + {3, DID_YES, DID_NO, DID_CANCEL}, + {2, DID_YES, DID_NO, 0}, + {2, DID_RETRY, DID_NO, 0}}; + + +// ---- + +static BRESULT setmboxitem(MBOX *mb, const OEMCHAR *str, UINT type) { + + OEMCHAR *dst; + int rem; + int w; + OEMCHAR work[4]; + int width; + POINT_T pt; + int leng; + + if (mb == NULL) { + goto smbi_err; + } + ZeroMemory(mb, sizeof(MBOX)); + if (str == NULL) { + goto smbi_set; + } + if ((type & 0xf) >= 6) { + type &= ~0x0f; + } + mb->type = type; + width = MENUMBOX_WIDTH - + (MENUMBOX_SX + MENUMBOX_PXTEXT + MENUMBOX_LXTEXT); + if (mb->type & 0xf0) { + width -= MENUMBOX_CXICON; + } + dst = NULL; + rem = 0; + w = 0; + while(1) { + leng = milstr_charsize(str); + if (leng == 0) { + break; + } + if ((str[0] >= 0) && (str[0] < 0x20)) { + if (str[0] == '\n') { + dst = mb->string[mb->lines]; + mb->lines++; + if (mb->lines >= MENUMBOX_MAXLINE) { + break; + } + rem = NELEMENTS(mb->string[0]) - 1; + if (mb->width < w) { + mb->width = w; + } + w = 0; + } + } + else { + CopyMemory(work, str, leng * sizeof(OEMCHAR)); + work[leng] = '\0'; + fontmng_getsize(menubase.font, work, &pt); + if ((rem < leng) || ((w + pt.x) > width)) { + dst = mb->string[mb->lines]; + mb->lines++; + if (mb->lines >= MENUMBOX_MAXLINE) { + break; + } + rem = NELEMENTS(mb->string[0]) - 1; + if (mb->width < w) { + mb->width = w; + } + w = 0; + } + w += pt.x; + CopyMemory(dst, str, leng * sizeof(OEMCHAR)); + dst += leng; + rem -= leng; + } + str += leng; + } + if (mb->width < w) { + mb->width = w; + } + +smbi_set: + mb->width += (MENUMBOX_SX + MENUMBOX_PXTEXT + MENUMBOX_LXTEXT); + fontmng_getsize(menubase.font, mstr_fontcheck, &pt); + mb->fontsize = pt.y; + mb->height = mb->lines * mb->fontsize; + if (mb->type & 0xf0) { + mb->width += MENUMBOX_CXICON; + if (mb->height < MENUMBOX_CYICON) { + mb->height = MENUMBOX_CYICON; + } + } + mb->height += MENUMBOX_SY + + MENUMBOX_SYBTN + MENUMBOX_CYBTN + MENUMBOX_LYBTN; + + width = b_res[mb->type & 0x0f][0]; + width *= (MENUMBOX_CXBTN + MENUMBOX_PXBTN); + width += (MENUMBOX_SXBTN * 2) - MENUMBOX_PXBTN; + if (mb->width < width) { + mb->width = width; + } + return(SUCCESS); + +smbi_err: + return(FAILURE); +} + + +static void mbox_open(MBOX *mb) { + + int posy; + int posx; +const UINT8 *btn; + int cnt; + int btnid; + + posx = MENUMBOX_SX + MENUMBOX_PXTEXT; + posy = 0; + if (mb->type & 0xf0) { + menudlg_append(DLGTYPE_ICON, 0, 0, (void *)(INTPTR)((mb->type >> 4) & 0xf), + MENUMBOX_SX, MENUMBOX_SY, MENUMBOX_SZICON, MENUMBOX_SZICON); + posx += MENUMBOX_CXICON; + posy = MENUMBOX_CYICON - (mb->lines * mb->fontsize); + } + if (posy > 0) { + posy /= 2; + posy += MENUMBOX_SY; + } + else { + posy = MENUMBOX_SY; + } + cnt = 0; + while(cnt < mb->lines) { + menudlg_append(DLGTYPE_LTEXT, 0, 0, mb->string[cnt], + posx, posy, mb->width - posx, mb->fontsize); + posy += mb->fontsize; + cnt++; + } + + cnt = mb->type & 0x0f; + if (cnt >= 6) { + cnt = 0; + } + btn = b_res[cnt]; + cnt = *btn++; + posy = mb->height - (MENUMBOX_CYBTN + MENUMBOX_LYBTN); + posx = mb->width; + posx -= ((MENUMBOX_CXBTN + MENUMBOX_PXBTN) * cnt) - MENUMBOX_PXBTN; + posx >>= 1; + while(cnt) { + cnt--; + btnid = *btn++; + menudlg_append(DLGTYPE_BUTTON, (MENUID)btnid, 0, + menumbox_txt[btnid-1], + posx, posy, MENUMBOX_CXBTN, MENUMBOX_CYBTN); + posx += MENUMBOX_CXBTN + MENUMBOX_PXBTN; + } +} + + +static int mbox_cmd(int msg, MENUID id, long param) { + + MBOX *mb; + + switch(msg) { + case DLGMSG_CREATE: + mb = &mbox; + mbox_open(mb); + break; + + case DLGMSG_COMMAND: + switch(id) { + case DID_OK: + case DID_CANCEL: + case DID_ABORT: + case DID_RETRY: + case DID_IGNORE: + case DID_YES: + case DID_NO: + mb = &mbox; + mb->ret = id; + menubase_close(); + break; + } + break; + + case DLGMSG_CLOSE: + menubase_close(); + break; + } + (void)param; + return(0); +} + + +int menumbox(const OEMCHAR *string, const OEMCHAR *title, UINT type) { + + MBOX *mb; + + mb = &mbox; + if (setmboxitem(mb, string, type) == SUCCESS) { + menudlg_create(mb->width, mb->height, title, mbox_cmd); + menubase_modalproc(); + return(mb->ret); + } + else { + return(0); + } +} + diff --git a/embed/menubase/menumbox.h b/embed/menubase/menumbox.h old mode 100755 new mode 100644 index e212e2ab..15444171 --- a/embed/menubase/menumbox.h +++ b/embed/menubase/menumbox.h @@ -1,24 +1,24 @@ - -enum { - MBOX_OK = 0x0000, - MBOX_OKCANCEL = 0x0001, - MBOX_ABORT = 0x0002, - MBOX_YESNOCAN = 0x0003, - MBOX_YESNO = 0x0004, - MBOX_RETRY = 0x0005, - MBOX_ICONSTOP = 0x0010, - MBOX_ICONQUESTION = 0x0020, - MBOX_ICONEXCLAME = 0x0030, - MBOX_ICONINFO = 0x0040 -}; - -#ifdef __cplusplus -extern "C" { -#endif - -int menumbox(const OEMCHAR *string, const OEMCHAR *title, UINT type); - -#ifdef __cplusplus -} -#endif - + +enum { + MBOX_OK = 0x0000, + MBOX_OKCANCEL = 0x0001, + MBOX_ABORT = 0x0002, + MBOX_YESNOCAN = 0x0003, + MBOX_YESNO = 0x0004, + MBOX_RETRY = 0x0005, + MBOX_ICONSTOP = 0x0010, + MBOX_ICONQUESTION = 0x0020, + MBOX_ICONEXCLAME = 0x0030, + MBOX_ICONINFO = 0x0040 +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int menumbox(const OEMCHAR *string, const OEMCHAR *title, UINT type); + +#ifdef __cplusplus +} +#endif + diff --git a/embed/menubase/menures.c b/embed/menubase/menures.c old mode 100755 new mode 100644 index 43cb4132..5402a0e3 --- a/embed/menubase/menures.c +++ b/embed/menubase/menures.c @@ -1,343 +1,343 @@ -#include -#include -#include - - -#if defined(OSLANG_SJIS) && !defined(RESOURCE_US) -const OEMCHAR mstr_fontcheck[] = " "; -const OEMCHAR mstr_ok[] = "OK"; - // キャンセル -const OEMCHAR mstr_cancel[] = "\267\254\335\276\331"; - // 中止 -const OEMCHAR mstr_abort[] = "\222\206\216\176"; - // 再試行 -const OEMCHAR mstr_retry[] = "\215\304\216\216\215\163"; - // 無視 -const OEMCHAR mstr_ignore[] = "\226\263\216\213"; - // はい -const OEMCHAR mstr_yes[] = "\202\315\202\242"; - // いいえ -const OEMCHAR mstr_no[] = "\202\242\202\242\202\246"; -#elif defined(OSLANG_EUC) && !defined(RESOURCE_US) -const OEMCHAR mstr_fontcheck[] = " "; -const OEMCHAR mstr_ok[] = "OK"; - // キャンセル -const OEMCHAR mstr_cancel[] = "\216\267\216\254\216\335\216\276\216\331"; - // 中止 -const OEMCHAR mstr_abort[] = "\303\346\273\337"; - // 再試行 -const OEMCHAR mstr_retry[] = "\272\306\273\356\271\324"; - // 無視 -const OEMCHAR mstr_ignore[] = "\314\265\273\353"; - // はい -const OEMCHAR mstr_yes[] = "\244\317\244\244"; - // いいえ -const OEMCHAR mstr_no[] = "\244\244\244\244\244\250"; -#elif defined(OSLANG_UTF8) && !defined(RESOURCE_US) -const OEMCHAR mstr_fontcheck[] = " "; -const OEMCHAR mstr_ok[] = "OK"; - // キャンセル -const OEMCHAR mstr_cancel[] = "\357\275\267\357\275\254\357\276\235" \ - "\357\275\276\357\276\231"; - // 中止 -const OEMCHAR mstr_abort[] = "\344\270\255\346\255\242"; - // 再試行 -const OEMCHAR mstr_retry[] = "\345\206\215\350\251\246\350\241\214"; - // 無視 -const OEMCHAR mstr_ignore[] = "\347\204\241\350\246\226"; - // はい -const OEMCHAR mstr_yes[] = "\343\201\257\343\201\204"; - // いいえ -const OEMCHAR mstr_no[] = "\343\201\204\343\201\204\343\201\210"; -#else -const OEMCHAR mstr_fontcheck[] = OEMTEXT(" "); -const OEMCHAR mstr_ok[] = OEMTEXT("OK"); -const OEMCHAR mstr_cancel[] = OEMTEXT("Cancel"); -const OEMCHAR mstr_abort[] = OEMTEXT("Abort"); -const OEMCHAR mstr_retry[] = OEMTEXT("Retry"); -const OEMCHAR mstr_ignore[] = OEMTEXT("Ignore"); -const OEMCHAR mstr_yes[] = OEMTEXT("Yes"); -const OEMCHAR mstr_no[] = OEMTEXT("No"); -#endif - - -#ifndef NP2_SIZE_QVGA - -// ---- minimize, close - -static const UINT8 minimize1[4] = { // 12x10 - 0x6d,0x66,0x96,0x00}; - -const MENURES2 menures_minimize = {12, 10, minimize1}; - - -static const UINT8 close1[14] = { // 12x10 - 0xe8,0x42,0x52,0x22,0x72,0x84,0x29,0x98,0x74,0x22,0x52,0x42,0x92, - 0x0a}; - -const MENURES2 menures_close = {12, 10, close1}; - - -// ---- sys - -static const UINT8 scheck[7] = { // 8x16 - 0xda,0x41,0x11,0x42,0x63,0xb1,0x0c}; - -static const UINT8 snext[9] = { // 8x16 - 0xc9,0x71,0x62,0x53,0x44,0x53,0x62,0xb1,0x03}; - -const MENURES2 menures_sys[2] = {{8, 16, scheck}, {8, 16, snext}}; - - -// ---- radio - -static const UINT8 radio[43] = { // 12x12 - 0x08,0x48,0x0a,0x44,0x58,0x44,0x07,0x54,0x85,0x51,0x25,0x00,0x54, - 0x1a,0x23,0x40,0xc5,0x31,0x42,0xc5,0x31,0x42,0xc5,0x31,0x42,0xc5, - 0x31,0x02,0x54,0x1a,0x23,0x00,0x34,0x83,0x31,0x23,0x07,0x22,0x38, - 0x22,0x0a,0x28,0x08}; - -static const UINT8 radiog[43] = { // 12x12 - 0x08,0x48,0x0a,0x44,0x58,0x44,0x07,0x54,0x85,0x56,0x25,0x00,0x54, - 0x6a,0x23,0x40,0xc5,0x36,0x42,0xc5,0x36,0x42,0xc5,0x36,0x42,0xc5, - 0x36,0x02,0x54,0x6a,0x23,0x00,0x34,0x83,0x36,0x23,0x07,0x22,0x38, - 0x22,0x0a,0x28,0x08}; - -static const UINT8 radiohit[7] = { // 12x12 - 0x5b,0x82,0x49,0x88,0x84,0x29,0x5b}; - -const MENURES2 menures_radio[3] = {{12, 12, radio}, {12, 12, radiog}, - {12, 12, radiohit}}; - - -// ---- check - -static const UINT8 checkhit[11] = { // 9x9 - 0x09,0x71,0x22,0x31,0x23,0x12,0x33,0x55,0x73,0x81,0x0e}; - -const MENURES2 menures_check = {9, 9, checkhit}; - - -// ---- btn - -static const UINT8 btnup[7] = { // 12x12 - 0x5b,0x81,0x3a,0x88,0x65,0xb7,0x03}; - -static const UINT8 btndn[7] = { // 12x12 - 0x2b,0x67,0x85,0x38,0xa8,0xb1,0x06}; - -const MENURES2 menures_scrbtn[2] = {{12, 12, btnup}, {12, 12, btndn}}; - -#else - -// ---- minimize, close - -static const UINT8 minimize1[3] = { // 8x8 - 0x1b,0x85,0x0a}; - -const MENURES2 menures_minimize = {8, 8, minimize1}; - - -static const UINT8 close1[11] = { // 8x8 - 0x98,0x31,0x41,0x11,0x61,0x61,0x11,0x41,0x31,0x91,0x02}; - -const MENURES2 menures_close = {8, 8, close1}; - - -// ---- sys - -static const UINT8 scheck[7] = { // 8x12 - 0x5a,0x41,0x11,0x42,0x63,0xa1,0x04}; - -static const UINT8 snext[7] = { // 8x12 - 0xb9,0x71,0x62,0x53,0x62,0xa1,0x04}; - -const MENURES2 menures_sys[2] = {{8, 12, scheck}, {8, 12, snext}}; - - -// ---- radio - -static const UINT8 radio[40] = { // 11x11 - 0x08,0x47,0x0a,0x44,0x57,0x44,0x07,0x54,0x75,0x51,0x25,0x00,0x54, - 0x19,0x23,0x40,0xb5,0x31,0x42,0xb5,0x31,0x42,0xb5,0x31,0x02,0x54, - 0x19,0x23,0x00,0x34,0x73,0x31,0x23,0x07,0x22,0x37,0x22,0x0a,0x27, - 0x08}; - -static const UINT8 radiog[40] = { // 11x11 - 0x08,0x47,0x0a,0x44,0x57,0x44,0x07,0x54,0x75,0x56,0x25,0x00,0x54, - 0x69,0x23,0x40,0xb5,0x36,0x42,0xb5,0x36,0x42,0xb5,0x36,0x02,0x54, - 0x69,0x23,0x00,0x34,0x73,0x36,0x23,0x07,0x22,0x37,0x22,0x0a,0x27, - 0x08}; - -static const UINT8 radiohit[6] = { // 11x11 - 0x1b,0x81,0x39,0x98,0xb1,0x01}; - -const MENURES2 menures_radio[3] = {{11, 11, radio}, {11, 11, radiog}, - {11, 11, radiohit}}; - - -// ---- check - -static const UINT8 checkhit[8] = { // 7x7 - 0xc8,0x51,0x22,0x11,0x32,0x53,0x81,0x0b}; - -const MENURES2 menures_check = {7, 7, checkhit}; - - -// ---- btn - -static const UINT8 btnup[5] = { // 6x6 - 0x88,0x41,0x23,0x85,0x0d}; - - -static const UINT8 btndn[4] = { // 6x6 - 0x56,0x32,0x14,0xf8}; - -const MENURES2 menures_scrbtn[2] = {{6, 6, btnup}, {6, 6, btndn}}; - -#endif - - -// ---- slider - -const UINT8 menures_slddat[] = { - 0x28,0x25,0x33,0x54,0x32,0x43,0x25,0x33,0x54,0x32,0x43,0x25,0x33, - 0x54,0x32,0x43,0x05,0x42,0x75,0x50,0x00, - - 0x28,0x25,0x33,0x54,0x32,0x46,0x25,0x63,0x54,0x32,0x46,0x25,0x63, - 0x54,0x32,0x46,0x05,0x42,0x75,0x50,0x00, - - 0x28,0x25,0x33,0x54,0x32,0x43,0x25,0x33,0x54,0x32,0x43,0x25,0x33, - 0x54,0x32,0x43,0x25,0x47,0x5a, - - 0x28,0x25,0x33,0x54,0x32,0x46,0x25,0x63,0x54,0x32,0x46,0x25,0x63, - 0x54,0x32,0x46,0x25,0x47,0x5a, - - 0x00,0x75,0x20,0x54,0x20,0x33,0x54,0x32,0x43,0x25,0x33,0x54,0x32, - 0x43,0x25,0x33,0x54,0x72,0xa4,0x05, - - 0x00,0x75,0x20,0x54,0x20,0x63,0x54,0x32,0x46,0x25,0x63,0x54,0x32, - 0x46,0x25,0x63,0x54,0x72,0xa4,0x05, - - 0x2b,0x00,0xa2,0x23,0x20,0x3a,0x54,0xa2,0x54,0xb0,0x05,0x00, - - 0x2b,0x00,0xa2,0x23,0x20,0x93,0x46,0x25,0x4a,0x05,0x5b,0x00, - - 0x2c,0x25,0x3a,0x54,0xa2,0x43,0x25,0x4b,0x5e, - - 0x2c,0x25,0x3a,0x54,0x32,0x69,0x54,0xb2,0xe4,0x05, - - 0x00,0x2a,0x05,0x92,0x43,0x55,0x94,0x43,0x05,0xa5,0x54,0x00,0x5b, - - 0x00,0x2a,0x05,0x92,0x43,0x55,0x94,0x46,0x05,0xa5,0x54,0x00,0x5b, - - 0x2a,0x25,0x38,0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25,0x38, - 0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25,0x38,0x54,0x20,0x33, - 0x54,0x07,0x42,0x95,0x50,0x07, - - 0x2a,0x25,0x38,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54, - 0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32, - 0x67,0x54,0x20,0x63,0x54,0x07,0x42,0x95,0x50,0x07, - - 0x2a,0x25,0x38,0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25,0x38, - 0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43, - 0x25,0x49,0x5c, - - 0x2a,0x25,0x38,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54, - 0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32, - 0x67,0x54,0x32,0x67,0x54,0x92,0xc4,0x05, - - 0x07,0x95,0x20,0x54,0x07,0x32,0x43,0x05,0x82,0x43,0x25,0x38,0x54, - 0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25, - 0x38,0x54,0x92,0xc4,0x05, - - 0x07,0x95,0x20,0x54,0x07,0x32,0x46,0x05,0x32,0x67,0x54,0x32,0x67, - 0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54, - 0x32,0x67,0x54,0x32,0x67,0x54,0x92,0xc4,0x05, - - 0x2e,0x07,0xd2,0x23,0x00,0xe2,0x23,0x20,0x3e,0x54,0xd2,0x43,0x05, - 0xd2,0x54,0x00,0x5e,0x07, - - 0x2e,0x07,0xd2,0x23,0x00,0x32,0x6c,0x23,0x20,0xd3,0x46,0x25,0xc3, - 0x46,0x05,0xd2,0x54,0x00,0x5e,0x07, - - 0x2f,0x52,0xe2,0x43,0x25,0x3e,0x54,0xe2,0x43,0x25,0x3e,0x54,0xf2, - 0xf4,0x75,0x05, - - 0x2f,0x52,0xe2,0x43,0x25,0xd3,0x46,0x25,0xd3,0x46,0x25,0xd3,0x46, - 0x25,0x4f,0x5f,0x57, - - 0x07,0x2d,0x05,0x20,0x3c,0x54,0x20,0x3d,0x54,0x45,0x3d,0x54,0x50, - 0xc4,0x43,0x05,0x50,0x4d,0x75,0xe0,0x05, - - 0x07,0x2d,0x05,0x20,0x3c,0x54,0x20,0xc3,0x46,0x55,0xd4,0x46,0x05, - 0x45,0x6c,0x54,0x00,0xd5,0x54,0x07,0x5e, - - 0x2e,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c, - 0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43, - 0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54, - 0x20,0x3a,0x54,0x07,0x82,0x43,0x95,0x20,0x33,0x54,0x0b,0x42,0xd5, - 0x50,0x09, - - 0x2e,0x25,0x3c,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54, - 0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32, - 0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b, - 0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x20,0x93,0x46,0x75,0x20,0x73, - 0x46,0x95,0x20,0x63,0x54,0x0b,0x42,0xd5,0x50,0x09, - - 0x2e,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c, - 0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43, - 0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54, - 0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x4d,0x5f,0x05, - - 0x2e,0x25,0x3c,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54, - 0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32, - 0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b, - 0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54, - 0x32,0x6b,0x54,0xd2,0xf4,0x55, - - 0x09,0xd5,0x20,0x54,0x0b,0x32,0x43,0x95,0x20,0x38,0x54,0x07,0xa2, - 0x43,0x05,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2, - 0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c, - 0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xd2,0xf4, - 0x55, - - 0x09,0xd5,0x20,0x54,0x0b,0x32,0x46,0x95,0x20,0x73,0x46,0x75,0x20, - 0x93,0x46,0x05,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32, - 0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b, - 0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54, - 0x32,0x6b,0x54,0x32,0x6b,0x54,0xd2,0xf4,0x55, - - 0x2f,0x29,0x09,0xf2,0x83,0x23,0x08,0xf2,0x93,0x23,0x07,0xf2,0xa3, - 0x23,0x00,0xf2,0xb3,0x23,0x20,0x3f,0x3b,0x54,0xf2,0xa3,0x43,0x05, - 0xf2,0x93,0x43,0x05,0x20,0x3f,0x38,0x54,0x07,0xf2,0x84,0x54,0x08, - 0x5f,0x59,0x09, - - 0x2f,0x29,0x09,0xf2,0x83,0x23,0x08,0x32,0x6f,0x67,0x23,0x07,0x32, - 0x6f,0x68,0x23,0x00,0x32,0x6f,0x69,0x23,0x20,0xf3,0xa6,0x46,0x25, - 0xf3,0x96,0x46,0x05,0x32,0x6f,0x68,0x54,0x00,0x32,0x6f,0x67,0x54, - 0x07,0xf2,0x84,0x54,0x08,0x5f,0x59,0x09, - - 0x2f,0x2d,0x25,0x3f,0x3b,0x54,0xf2,0xb3,0x43,0x25,0x3f,0x3b,0x54, - 0xf2,0xb3,0x43,0x25,0x3f,0x3b,0x54,0xf2,0xb3,0x43,0x25,0x3f,0x3b, - 0x54,0xf2,0xb3,0x43,0x25,0x4f,0x4c,0x5f,0x5f, - - 0x2f,0x2d,0x25,0x3f,0x3b,0x54,0x32,0x6f,0x6a,0x54,0x32,0x6f,0x6a, - 0x54,0x32,0x6f,0x6a,0x54,0x32,0x6f,0x6a,0x54,0x32,0x6f,0x6a,0x54, - 0x32,0x6f,0x6a,0x54,0x32,0x6f,0x6a,0x54,0xf2,0xc4,0xf4,0xf5,0x05, - - 0x09,0x2f,0x28,0x85,0x20,0x3f,0x37,0x54,0x07,0xf2,0x83,0x43,0x05, - 0x20,0x3f,0x39,0x54,0x20,0x3f,0x3a,0x54,0x45,0x3f,0x3a,0x54,0x50, - 0xf4,0x93,0x43,0x05,0x50,0xf4,0x83,0x43,0x75,0x50,0xf4,0x73,0x43, - 0x85,0x50,0x4f,0x48,0x95,0xf0,0x95,0x05, - - 0x09,0x2f,0x28,0x85,0x20,0x3f,0x37,0x54,0x07,0x32,0x6f,0x67,0x54, - 0x00,0x32,0x6f,0x68,0x54,0x20,0xf3,0x96,0x46,0x55,0xf4,0xa6,0x46, - 0x05,0x45,0x6f,0x69,0x54,0x00,0x45,0x6f,0x68,0x54,0x07,0x45,0x6f, - 0x67,0x54,0x08,0xf5,0x84,0x54,0x09,0x5f,0x59}; - -const UINT16 menures_sldpos[3][12] = { - { 0, 21, 42, 61, 80, 100, 120, 132, 144, 153, 163, 176}, - {189, 221, 257, 286, 320, 351, 386, 404, 424, 440, 457, 478}, - {499, 553, 615, 665, 723, 776, 837, 879, 926, 961,1000,1047}}; - +#include +#include +#include + + +#if defined(OSLANG_SJIS) && !defined(RESOURCE_US) +const OEMCHAR mstr_fontcheck[] = " "; +const OEMCHAR mstr_ok[] = "OK"; + // キャンセル +const OEMCHAR mstr_cancel[] = "\267\254\335\276\331"; + // 中止 +const OEMCHAR mstr_abort[] = "\222\206\216\176"; + // 再試行 +const OEMCHAR mstr_retry[] = "\215\304\216\216\215\163"; + // 無視 +const OEMCHAR mstr_ignore[] = "\226\263\216\213"; + // はい +const OEMCHAR mstr_yes[] = "\202\315\202\242"; + // いいえ +const OEMCHAR mstr_no[] = "\202\242\202\242\202\246"; +#elif defined(OSLANG_EUC) && !defined(RESOURCE_US) +const OEMCHAR mstr_fontcheck[] = " "; +const OEMCHAR mstr_ok[] = "OK"; + // キャンセル +const OEMCHAR mstr_cancel[] = "\216\267\216\254\216\335\216\276\216\331"; + // 中止 +const OEMCHAR mstr_abort[] = "\303\346\273\337"; + // 再試行 +const OEMCHAR mstr_retry[] = "\272\306\273\356\271\324"; + // 無視 +const OEMCHAR mstr_ignore[] = "\314\265\273\353"; + // はい +const OEMCHAR mstr_yes[] = "\244\317\244\244"; + // いいえ +const OEMCHAR mstr_no[] = "\244\244\244\244\244\250"; +#elif defined(OSLANG_UTF8) && !defined(RESOURCE_US) +const OEMCHAR mstr_fontcheck[] = " "; +const OEMCHAR mstr_ok[] = "OK"; + // キャンセル +const OEMCHAR mstr_cancel[] = "\357\275\267\357\275\254\357\276\235" \ + "\357\275\276\357\276\231"; + // 中止 +const OEMCHAR mstr_abort[] = "\344\270\255\346\255\242"; + // 再試行 +const OEMCHAR mstr_retry[] = "\345\206\215\350\251\246\350\241\214"; + // 無視 +const OEMCHAR mstr_ignore[] = "\347\204\241\350\246\226"; + // はい +const OEMCHAR mstr_yes[] = "\343\201\257\343\201\204"; + // いいえ +const OEMCHAR mstr_no[] = "\343\201\204\343\201\204\343\201\210"; +#else +const OEMCHAR mstr_fontcheck[] = OEMTEXT(" "); +const OEMCHAR mstr_ok[] = OEMTEXT("OK"); +const OEMCHAR mstr_cancel[] = OEMTEXT("Cancel"); +const OEMCHAR mstr_abort[] = OEMTEXT("Abort"); +const OEMCHAR mstr_retry[] = OEMTEXT("Retry"); +const OEMCHAR mstr_ignore[] = OEMTEXT("Ignore"); +const OEMCHAR mstr_yes[] = OEMTEXT("Yes"); +const OEMCHAR mstr_no[] = OEMTEXT("No"); +#endif + + +#ifndef NP2_SIZE_QVGA + +// ---- minimize, close + +static const UINT8 minimize1[4] = { // 12x10 + 0x6d,0x66,0x96,0x00}; + +const MENURES2 menures_minimize = {12, 10, minimize1}; + + +static const UINT8 close1[14] = { // 12x10 + 0xe8,0x42,0x52,0x22,0x72,0x84,0x29,0x98,0x74,0x22,0x52,0x42,0x92, + 0x0a}; + +const MENURES2 menures_close = {12, 10, close1}; + + +// ---- sys + +static const UINT8 scheck[7] = { // 8x16 + 0xda,0x41,0x11,0x42,0x63,0xb1,0x0c}; + +static const UINT8 snext[9] = { // 8x16 + 0xc9,0x71,0x62,0x53,0x44,0x53,0x62,0xb1,0x03}; + +const MENURES2 menures_sys[2] = {{8, 16, scheck}, {8, 16, snext}}; + + +// ---- radio + +static const UINT8 radio[43] = { // 12x12 + 0x08,0x48,0x0a,0x44,0x58,0x44,0x07,0x54,0x85,0x51,0x25,0x00,0x54, + 0x1a,0x23,0x40,0xc5,0x31,0x42,0xc5,0x31,0x42,0xc5,0x31,0x42,0xc5, + 0x31,0x02,0x54,0x1a,0x23,0x00,0x34,0x83,0x31,0x23,0x07,0x22,0x38, + 0x22,0x0a,0x28,0x08}; + +static const UINT8 radiog[43] = { // 12x12 + 0x08,0x48,0x0a,0x44,0x58,0x44,0x07,0x54,0x85,0x56,0x25,0x00,0x54, + 0x6a,0x23,0x40,0xc5,0x36,0x42,0xc5,0x36,0x42,0xc5,0x36,0x42,0xc5, + 0x36,0x02,0x54,0x6a,0x23,0x00,0x34,0x83,0x36,0x23,0x07,0x22,0x38, + 0x22,0x0a,0x28,0x08}; + +static const UINT8 radiohit[7] = { // 12x12 + 0x5b,0x82,0x49,0x88,0x84,0x29,0x5b}; + +const MENURES2 menures_radio[3] = {{12, 12, radio}, {12, 12, radiog}, + {12, 12, radiohit}}; + + +// ---- check + +static const UINT8 checkhit[11] = { // 9x9 + 0x09,0x71,0x22,0x31,0x23,0x12,0x33,0x55,0x73,0x81,0x0e}; + +const MENURES2 menures_check = {9, 9, checkhit}; + + +// ---- btn + +static const UINT8 btnup[7] = { // 12x12 + 0x5b,0x81,0x3a,0x88,0x65,0xb7,0x03}; + +static const UINT8 btndn[7] = { // 12x12 + 0x2b,0x67,0x85,0x38,0xa8,0xb1,0x06}; + +const MENURES2 menures_scrbtn[2] = {{12, 12, btnup}, {12, 12, btndn}}; + +#else + +// ---- minimize, close + +static const UINT8 minimize1[3] = { // 8x8 + 0x1b,0x85,0x0a}; + +const MENURES2 menures_minimize = {8, 8, minimize1}; + + +static const UINT8 close1[11] = { // 8x8 + 0x98,0x31,0x41,0x11,0x61,0x61,0x11,0x41,0x31,0x91,0x02}; + +const MENURES2 menures_close = {8, 8, close1}; + + +// ---- sys + +static const UINT8 scheck[7] = { // 8x12 + 0x5a,0x41,0x11,0x42,0x63,0xa1,0x04}; + +static const UINT8 snext[7] = { // 8x12 + 0xb9,0x71,0x62,0x53,0x62,0xa1,0x04}; + +const MENURES2 menures_sys[2] = {{8, 12, scheck}, {8, 12, snext}}; + + +// ---- radio + +static const UINT8 radio[40] = { // 11x11 + 0x08,0x47,0x0a,0x44,0x57,0x44,0x07,0x54,0x75,0x51,0x25,0x00,0x54, + 0x19,0x23,0x40,0xb5,0x31,0x42,0xb5,0x31,0x42,0xb5,0x31,0x02,0x54, + 0x19,0x23,0x00,0x34,0x73,0x31,0x23,0x07,0x22,0x37,0x22,0x0a,0x27, + 0x08}; + +static const UINT8 radiog[40] = { // 11x11 + 0x08,0x47,0x0a,0x44,0x57,0x44,0x07,0x54,0x75,0x56,0x25,0x00,0x54, + 0x69,0x23,0x40,0xb5,0x36,0x42,0xb5,0x36,0x42,0xb5,0x36,0x02,0x54, + 0x69,0x23,0x00,0x34,0x73,0x36,0x23,0x07,0x22,0x37,0x22,0x0a,0x27, + 0x08}; + +static const UINT8 radiohit[6] = { // 11x11 + 0x1b,0x81,0x39,0x98,0xb1,0x01}; + +const MENURES2 menures_radio[3] = {{11, 11, radio}, {11, 11, radiog}, + {11, 11, radiohit}}; + + +// ---- check + +static const UINT8 checkhit[8] = { // 7x7 + 0xc8,0x51,0x22,0x11,0x32,0x53,0x81,0x0b}; + +const MENURES2 menures_check = {7, 7, checkhit}; + + +// ---- btn + +static const UINT8 btnup[5] = { // 6x6 + 0x88,0x41,0x23,0x85,0x0d}; + + +static const UINT8 btndn[4] = { // 6x6 + 0x56,0x32,0x14,0xf8}; + +const MENURES2 menures_scrbtn[2] = {{6, 6, btnup}, {6, 6, btndn}}; + +#endif + + +// ---- slider + +const UINT8 menures_slddat[] = { + 0x28,0x25,0x33,0x54,0x32,0x43,0x25,0x33,0x54,0x32,0x43,0x25,0x33, + 0x54,0x32,0x43,0x05,0x42,0x75,0x50,0x00, + + 0x28,0x25,0x33,0x54,0x32,0x46,0x25,0x63,0x54,0x32,0x46,0x25,0x63, + 0x54,0x32,0x46,0x05,0x42,0x75,0x50,0x00, + + 0x28,0x25,0x33,0x54,0x32,0x43,0x25,0x33,0x54,0x32,0x43,0x25,0x33, + 0x54,0x32,0x43,0x25,0x47,0x5a, + + 0x28,0x25,0x33,0x54,0x32,0x46,0x25,0x63,0x54,0x32,0x46,0x25,0x63, + 0x54,0x32,0x46,0x25,0x47,0x5a, + + 0x00,0x75,0x20,0x54,0x20,0x33,0x54,0x32,0x43,0x25,0x33,0x54,0x32, + 0x43,0x25,0x33,0x54,0x72,0xa4,0x05, + + 0x00,0x75,0x20,0x54,0x20,0x63,0x54,0x32,0x46,0x25,0x63,0x54,0x32, + 0x46,0x25,0x63,0x54,0x72,0xa4,0x05, + + 0x2b,0x00,0xa2,0x23,0x20,0x3a,0x54,0xa2,0x54,0xb0,0x05,0x00, + + 0x2b,0x00,0xa2,0x23,0x20,0x93,0x46,0x25,0x4a,0x05,0x5b,0x00, + + 0x2c,0x25,0x3a,0x54,0xa2,0x43,0x25,0x4b,0x5e, + + 0x2c,0x25,0x3a,0x54,0x32,0x69,0x54,0xb2,0xe4,0x05, + + 0x00,0x2a,0x05,0x92,0x43,0x55,0x94,0x43,0x05,0xa5,0x54,0x00,0x5b, + + 0x00,0x2a,0x05,0x92,0x43,0x55,0x94,0x46,0x05,0xa5,0x54,0x00,0x5b, + + 0x2a,0x25,0x38,0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25,0x38, + 0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25,0x38,0x54,0x20,0x33, + 0x54,0x07,0x42,0x95,0x50,0x07, + + 0x2a,0x25,0x38,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54, + 0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32, + 0x67,0x54,0x20,0x63,0x54,0x07,0x42,0x95,0x50,0x07, + + 0x2a,0x25,0x38,0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25,0x38, + 0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43, + 0x25,0x49,0x5c, + + 0x2a,0x25,0x38,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54, + 0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32, + 0x67,0x54,0x32,0x67,0x54,0x92,0xc4,0x05, + + 0x07,0x95,0x20,0x54,0x07,0x32,0x43,0x05,0x82,0x43,0x25,0x38,0x54, + 0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25,0x38,0x54,0x82,0x43,0x25, + 0x38,0x54,0x92,0xc4,0x05, + + 0x07,0x95,0x20,0x54,0x07,0x32,0x46,0x05,0x32,0x67,0x54,0x32,0x67, + 0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54,0x32,0x67,0x54, + 0x32,0x67,0x54,0x32,0x67,0x54,0x92,0xc4,0x05, + + 0x2e,0x07,0xd2,0x23,0x00,0xe2,0x23,0x20,0x3e,0x54,0xd2,0x43,0x05, + 0xd2,0x54,0x00,0x5e,0x07, + + 0x2e,0x07,0xd2,0x23,0x00,0x32,0x6c,0x23,0x20,0xd3,0x46,0x25,0xc3, + 0x46,0x05,0xd2,0x54,0x00,0x5e,0x07, + + 0x2f,0x52,0xe2,0x43,0x25,0x3e,0x54,0xe2,0x43,0x25,0x3e,0x54,0xf2, + 0xf4,0x75,0x05, + + 0x2f,0x52,0xe2,0x43,0x25,0xd3,0x46,0x25,0xd3,0x46,0x25,0xd3,0x46, + 0x25,0x4f,0x5f,0x57, + + 0x07,0x2d,0x05,0x20,0x3c,0x54,0x20,0x3d,0x54,0x45,0x3d,0x54,0x50, + 0xc4,0x43,0x05,0x50,0x4d,0x75,0xe0,0x05, + + 0x07,0x2d,0x05,0x20,0x3c,0x54,0x20,0xc3,0x46,0x55,0xd4,0x46,0x05, + 0x45,0x6c,0x54,0x00,0xd5,0x54,0x07,0x5e, + + 0x2e,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c, + 0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43, + 0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54, + 0x20,0x3a,0x54,0x07,0x82,0x43,0x95,0x20,0x33,0x54,0x0b,0x42,0xd5, + 0x50,0x09, + + 0x2e,0x25,0x3c,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54, + 0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32, + 0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b, + 0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x20,0x93,0x46,0x75,0x20,0x73, + 0x46,0x95,0x20,0x63,0x54,0x0b,0x42,0xd5,0x50,0x09, + + 0x2e,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c, + 0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43, + 0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54, + 0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x4d,0x5f,0x05, + + 0x2e,0x25,0x3c,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54, + 0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32, + 0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b, + 0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54, + 0x32,0x6b,0x54,0xd2,0xf4,0x55, + + 0x09,0xd5,0x20,0x54,0x0b,0x32,0x43,0x95,0x20,0x38,0x54,0x07,0xa2, + 0x43,0x05,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2, + 0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c, + 0x54,0xc2,0x43,0x25,0x3c,0x54,0xc2,0x43,0x25,0x3c,0x54,0xd2,0xf4, + 0x55, + + 0x09,0xd5,0x20,0x54,0x0b,0x32,0x46,0x95,0x20,0x73,0x46,0x75,0x20, + 0x93,0x46,0x05,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32, + 0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b, + 0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54,0x32,0x6b,0x54, + 0x32,0x6b,0x54,0x32,0x6b,0x54,0xd2,0xf4,0x55, + + 0x2f,0x29,0x09,0xf2,0x83,0x23,0x08,0xf2,0x93,0x23,0x07,0xf2,0xa3, + 0x23,0x00,0xf2,0xb3,0x23,0x20,0x3f,0x3b,0x54,0xf2,0xa3,0x43,0x05, + 0xf2,0x93,0x43,0x05,0x20,0x3f,0x38,0x54,0x07,0xf2,0x84,0x54,0x08, + 0x5f,0x59,0x09, + + 0x2f,0x29,0x09,0xf2,0x83,0x23,0x08,0x32,0x6f,0x67,0x23,0x07,0x32, + 0x6f,0x68,0x23,0x00,0x32,0x6f,0x69,0x23,0x20,0xf3,0xa6,0x46,0x25, + 0xf3,0x96,0x46,0x05,0x32,0x6f,0x68,0x54,0x00,0x32,0x6f,0x67,0x54, + 0x07,0xf2,0x84,0x54,0x08,0x5f,0x59,0x09, + + 0x2f,0x2d,0x25,0x3f,0x3b,0x54,0xf2,0xb3,0x43,0x25,0x3f,0x3b,0x54, + 0xf2,0xb3,0x43,0x25,0x3f,0x3b,0x54,0xf2,0xb3,0x43,0x25,0x3f,0x3b, + 0x54,0xf2,0xb3,0x43,0x25,0x4f,0x4c,0x5f,0x5f, + + 0x2f,0x2d,0x25,0x3f,0x3b,0x54,0x32,0x6f,0x6a,0x54,0x32,0x6f,0x6a, + 0x54,0x32,0x6f,0x6a,0x54,0x32,0x6f,0x6a,0x54,0x32,0x6f,0x6a,0x54, + 0x32,0x6f,0x6a,0x54,0x32,0x6f,0x6a,0x54,0xf2,0xc4,0xf4,0xf5,0x05, + + 0x09,0x2f,0x28,0x85,0x20,0x3f,0x37,0x54,0x07,0xf2,0x83,0x43,0x05, + 0x20,0x3f,0x39,0x54,0x20,0x3f,0x3a,0x54,0x45,0x3f,0x3a,0x54,0x50, + 0xf4,0x93,0x43,0x05,0x50,0xf4,0x83,0x43,0x75,0x50,0xf4,0x73,0x43, + 0x85,0x50,0x4f,0x48,0x95,0xf0,0x95,0x05, + + 0x09,0x2f,0x28,0x85,0x20,0x3f,0x37,0x54,0x07,0x32,0x6f,0x67,0x54, + 0x00,0x32,0x6f,0x68,0x54,0x20,0xf3,0x96,0x46,0x55,0xf4,0xa6,0x46, + 0x05,0x45,0x6f,0x69,0x54,0x00,0x45,0x6f,0x68,0x54,0x07,0x45,0x6f, + 0x67,0x54,0x08,0xf5,0x84,0x54,0x09,0x5f,0x59}; + +const UINT16 menures_sldpos[3][12] = { + { 0, 21, 42, 61, 80, 100, 120, 132, 144, 153, 163, 176}, + {189, 221, 257, 286, 320, 351, 386, 404, 424, 440, 457, 478}, + {499, 553, 615, 665, 723, 776, 837, 879, 926, 961,1000,1047}}; + diff --git a/embed/menubase/menures.h b/embed/menubase/menures.h old mode 100755 new mode 100644 index 2707c5a0..159dfc29 --- a/embed/menubase/menures.h +++ b/embed/menubase/menures.h @@ -1,30 +1,30 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -extern const OEMCHAR mstr_fontcheck[]; -extern const OEMCHAR mstr_ok[]; -extern const OEMCHAR mstr_cancel[]; -extern const OEMCHAR mstr_abort[]; -extern const OEMCHAR mstr_retry[]; -extern const OEMCHAR mstr_ignore[]; -extern const OEMCHAR mstr_yes[]; -extern const OEMCHAR mstr_no[]; - -extern const MENURES2 menures_minimize; -extern const MENURES2 menures_close; - -extern const MENURES2 menures_sys[2]; - -extern const MENURES2 menures_radio[3]; -extern const MENURES2 menures_check; -extern const MENURES2 menures_scrbtn[2]; - -extern const UINT8 menures_slddat[]; -extern const UINT16 menures_sldpos[3][12]; - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +extern const OEMCHAR mstr_fontcheck[]; +extern const OEMCHAR mstr_ok[]; +extern const OEMCHAR mstr_cancel[]; +extern const OEMCHAR mstr_abort[]; +extern const OEMCHAR mstr_retry[]; +extern const OEMCHAR mstr_ignore[]; +extern const OEMCHAR mstr_yes[]; +extern const OEMCHAR mstr_no[]; + +extern const MENURES2 menures_minimize; +extern const MENURES2 menures_close; + +extern const MENURES2 menures_sys[2]; + +extern const MENURES2 menures_radio[3]; +extern const MENURES2 menures_check; +extern const MENURES2 menures_scrbtn[2]; + +extern const UINT8 menures_slddat[]; +extern const UINT16 menures_sldpos[3][12]; + +#ifdef __cplusplus +} +#endif + diff --git a/embed/menubase/menusys.c b/embed/menubase/menusys.c old mode 100755 new mode 100644 index daba671c..c79e8069 --- a/embed/menubase/menusys.c +++ b/embed/menubase/menusys.c @@ -1,1178 +1,1178 @@ -#include -#include -#include -#include -#include -#include "menudeco.inc" -#include -#include - - -typedef struct _mhdl { -struct _mhdl *chain; -struct _mhdl *next; -struct _mhdl *child; - MENUID id; - MENUFLG flag; - RECT_T rct; - OEMCHAR string[32]; -} _MENUHDL, *MENUHDL; - -typedef struct { - VRAMHDL vram; - MENUHDL menu; - int items; - int focus; -} _MSYSWND, *MSYSWND; - -typedef struct { - _MSYSWND wnd[MENUSYS_MAX]; - LISTARRAY res; - MENUHDL lastres; - MENUHDL root; - UINT16 icon; - UINT16 style; - void (*cmd)(MENUID id); - int depth; - int opened; - int lastdepth; - int lastpos; - int popupx; - int popupy; - OEMCHAR title[128]; -} MENUSYS; - - -static MENUSYS menusys; - -#if defined(OSLANG_SJIS) && !defined(RESOURCE_US) -static const OEMCHAR str_sysr[] = // 元のサイズに戻す - "\214\263\202\314\203\124\203\103\203\131\202\311" \ - "\226\337\202\267"; -static const OEMCHAR str_sysm[] = // 移動 - "\210\332\223\256"; -static const OEMCHAR str_syss[] = // サイズ変更 - "\203\124\203\103\203\131\225\317\215\130"; -static const OEMCHAR str_sysn[] = // 最小化 - "\215\305\217\254\211\273"; -static const OEMCHAR str_sysx[] = // 最大化 - "\215\305\221\345\211\273"; -static const OEMCHAR str_sysc[] = // 閉じる - "\225\302\202\266\202\351"; -#elif defined(OSLANG_EUC) && !defined(RESOURCE_US) -static const OEMCHAR str_sysr[] = // 元のサイズに戻す - "\270\265\244\316\245\265\245\244\245\272\244\313" \ - "\314\341\244\271"; -static const OEMCHAR str_sysm[] = // 移動 - "\260\334\306\260"; -static const OEMCHAR str_syss[] = // サイズ変更 - "\245\265\245\244\245\272\312\321\271\271"; -static const OEMCHAR str_sysn[] = // 最小化 - "\272\307\276\256\262\275"; -static const OEMCHAR str_sysx[] = // 最大化 - "\272\307\302\347\262\275"; -static const OEMCHAR str_sysc[] = // 閉じる - "\312\304\244\270\244\353"; -#elif defined(OSLANG_UTF8) && !defined(RESOURCE_US) -static const OEMCHAR str_sysr[] = // 元のサイズに戻す - "\345\205\203\343\201\256\343\202\265\343\202\244\343\202\272" \ - "\343\201\253\346\210\273\343\201\231"; -static const OEMCHAR str_sysm[] = // 移動 - "\347\247\273\345\213\225"; -static const OEMCHAR str_syss[] = // サイズ変更 - "\343\202\265\343\202\244\343\202\272\345\244\211\346\233\264"; -static const OEMCHAR str_sysn[] = // 最小化 - "\346\234\200\345\260\217\345\214\226"; -static const OEMCHAR str_sysx[] = // 最大化 - "\346\234\200\345\244\247\345\214\226"; -static const OEMCHAR str_sysc[] = // 閉じる - "\351\226\211\343\201\230\343\202\213"; -#else -static const OEMCHAR str_sysr[] = OEMTEXT("Restore"); -static const OEMCHAR str_sysm[] = OEMTEXT("Move"); -static const OEMCHAR str_syss[] = OEMTEXT("Size"); -static const OEMCHAR str_sysn[] = OEMTEXT("Minimize"); -static const OEMCHAR str_sysx[] = OEMTEXT("Maximize"); -static const OEMCHAR str_sysc[] = OEMTEXT("Close"); -#endif - - -static const MSYSITEM s_exit[] = { - {str_sysr, NULL, 0, MENU_GRAY}, - {str_sysm, NULL, 0, MENU_GRAY}, - {str_syss, NULL, 0, MENU_GRAY}, -#if defined(MENU_TASKMINIMIZE) - {str_sysn, NULL, SID_MINIMIZE, 0}, -#else - {str_sysn, NULL, 0, MENU_GRAY}, -#endif - {str_sysx, NULL, 0, MENU_GRAY}, - {NULL, NULL, 0, MENU_SEPARATOR}, - {str_sysc, NULL, SID_CLOSE, MENU_DELETED}}; - -static const MSYSITEM s_root[] = { - {NULL, s_exit, 0, MENUS_SYSTEM}, -#if defined(MENU_TASKMINIMIZE) - {NULL, NULL, SID_MINIMIZE, MENUS_MINIMIZE}, -#endif - {NULL, NULL, SID_CLOSE, MENUS_CLOSE | - MENU_DELETED}}; - - -// ---- regist - -static BOOL seaempty(void *vpItem, void *vpArg) { - - if (((MENUHDL)vpItem)->flag & MENU_DELETED) { - return(TRUE); - } - (void)vpArg; - return(FALSE); -} - -static MENUHDL append1(MENUSYS *sys, const MSYSITEM *item) { - - MENUHDL ret; - _MENUHDL hdl; - - ZeroMemory(&hdl, sizeof(hdl)); - hdl.id = item->id; - hdl.flag = item->flag & (~MENU_DELETED); - if (item->string) { - milstr_ncpy(hdl.string, item->string, NELEMENTS(hdl.string)); - } - ret = (MENUHDL)listarray_enum(sys->res, seaempty, NULL); - if (ret) { - *ret = hdl; - } - else { - ret = (MENUHDL)listarray_append(sys->res, &hdl); - } - if (ret) { - if (sys->lastres) { - sys->lastres->chain = ret; - } - sys->lastres = ret; - } - return(ret); -} - -static MENUHDL appends(MENUSYS *sys, const MSYSITEM *item) { - - MENUHDL ret; - MENUHDL cur; - - ret = append1(sys, item); - cur = ret; - while(1) { - if (cur == NULL) { - goto ap_err; - } - if (item->child) { - cur->child = appends(sys, item->child); - } - if (item->flag & MENU_DELETED) { - break; - } - item++; - cur->next = append1(sys, item); - cur = cur->next; - } - return(ret); - -ap_err: - return(NULL); -} - - -// ---- - -static void draw(VRAMHDL dst, const RECT_T *rect, void *arg) { - - MENUSYS *sys; - int cnt; - MSYSWND wnd; - - sys = &menusys; - wnd = sys->wnd; - cnt = sys->depth; - while(cnt--) { - vrammix_cpy2(dst, rect, wnd->vram, NULL, 2); - wnd++; - } - (void)arg; -} - -static MENUHDL getitem(MENUSYS *sys, int depth, int pos) { - - MENUHDL ret; - - if ((unsigned int)depth >= (unsigned int)sys->depth) { - goto gi_err; - } - ret = sys->wnd[depth].menu; - while(ret) { - if (!pos) { - if (!(ret->flag & (MENU_DISABLE | MENU_SEPARATOR))) { - return(ret); - } - else { - break; - } - } - pos--; - ret = ret->next; - } - -gi_err: - return(NULL); -} - -static void wndclose(MENUSYS *sys, int depth) { - - MSYSWND wnd; - - sys->depth = depth; - wnd = sys->wnd + depth; - while(depth < MENUSYS_MAX) { - menubase_clrrect(wnd->vram); - vram_destroy(wnd->vram); - wnd->vram = NULL; - wnd++; - depth++; - } -} - -static void bitemdraw(VRAMHDL vram, MENUHDL menu, int flag) { - - void *font; - POINT_T pt; - UINT32 color; - int pos; - int menutype; - - font = menubase.font; - menutype = menu->flag & MENUS_CTRLMASK; - if (menutype == 0) { - vram_filldat(vram, &menu->rct, menucolor[MVC_STATIC]); - pos = 0; - if (flag) { - pos = 1; - } - if (!(menu->flag & MENU_GRAY)) { - color = menucolor[MVC_TEXT]; - } - else { -#if 0 - if (flag == 2) { - flag = 0; - pos = 0; - } -#endif - pt.x = menu->rct.left + pos + MENUSYS_SXSYS + MENU_DSTEXT; - pt.y = menu->rct.top + pos + MENUSYS_SYSYS + MENU_DSTEXT; - vrammix_text(vram, font, menu->string, - menucolor[MVC_GRAYTEXT2], &pt, NULL); - color = menucolor[MVC_GRAYTEXT1]; - } - pt.x = menu->rct.left + pos + MENUSYS_SXSYS; - pt.y = menu->rct.top + pos + MENUSYS_SYSYS; - vrammix_text(vram, font, menu->string, color, &pt, NULL); - if (flag) { - menuvram_box(vram, &menu->rct, - MVC2(MVC_SHADOW, MVC_HILIGHT), (flag==2)); - } - } -} - -enum { - MEXIST_SYS = 0x01, - MEXIST_MINIMIZE = 0x02, - MEXIST_CLOSE = 0x04, - MEXIST_ITEM = 0x08 -}; - -static BRESULT wndopenbase(MENUSYS *sys) { - - MENUHDL menu; - RECT_T mrect; - VRAMHDL vram; - int items; - int posx; - UINT rootflg; - int menutype; - int height; - POINT_T pt; - - wndclose(sys, 0); - - rootflg = 0; - menu = sys->root; - while(menu) { // メニュー内容を調べる。 - if (!(menu->flag & (MENU_DISABLE | MENU_SEPARATOR))) { - switch(menu->flag & MENUS_CTRLMASK) { - case MENUS_POPUP: - break; - - case MENUS_SYSTEM: - rootflg |= MEXIST_SYS; - break; - - case MENUS_MINIMIZE: - rootflg |= MEXIST_MINIMIZE; - break; - - case MENUS_CLOSE: - rootflg |= MEXIST_CLOSE; - break; - - default: - rootflg |= MEXIST_ITEM; - break; - } - } - menu = menu->next; - } - - mrect.left = MENU_FBORDER + MENU_BORDER; - mrect.top = MENU_FBORDER + MENU_BORDER; - mrect.right = menubase.width - (MENU_FBORDER + MENU_BORDER); - mrect.bottom = (MENU_FBORDER + MENU_BORDER) + MENUSYS_CYCAPTION; - height = ((MENU_FBORDER + MENU_BORDER) * 2) + MENUSYS_CYCAPTION; - if (rootflg & MEXIST_ITEM) { - height += (MENUSYS_BCAPTION * 3) + MENUSYS_CYSYS; - mrect.left += MENUSYS_BCAPTION; - mrect.top += MENUSYS_BCAPTION; - mrect.right -= MENUSYS_BCAPTION; - mrect.bottom += MENUSYS_BCAPTION; - } - vram = menuvram_create(menubase.width, height, menubase.bpp); - sys->wnd[0].vram = vram; - if (vram == NULL) { - goto wopn0_err; - } - if (sys->style & MENUSTYLE_BOTTOM) { - vram->posy = MAX(0, menuvram->height - height); - } - menuvram_caption(vram, &mrect, sys->icon, sys->title); - menubase_setrect(vram, NULL); - menu = sys->root; - sys->wnd[0].menu = menu; - sys->wnd[0].focus = -1; - sys->depth++; - items = 0; - posx = MENU_FBORDER + MENU_BORDER + MENUSYS_BCAPTION; - while(menu) { - if (!(menu->flag & (MENU_DISABLE | MENU_SEPARATOR))) { - menutype = menu->flag & MENUS_CTRLMASK; - if (menutype == MENUS_POPUP) { - } - else if (menutype == MENUS_SYSTEM) { - menu->rct.left = mrect.left + MENU_PXCAPTION; - menu->rct.right = menu->rct.left; - menu->rct.top = mrect.top + MENU_PYCAPTION; - menu->rct.bottom = menu->rct.top; - if (sys->icon) { - menu->rct.right += MENUSYS_SZICON; - menu->rct.bottom += MENUSYS_SZICON; - } - } - else if (menutype == MENUS_MINIMIZE) { - menu->rct.right = mrect.right - MENU_PXCAPTION; - if (rootflg & MEXIST_CLOSE) { - menu->rct.right -= MENUSYS_CXCLOSE + (MENU_LINE * 2); - } - menu->rct.left = menu->rct.right - MENUSYS_CXCLOSE; - menu->rct.top = mrect.top + - ((MENUSYS_CYCAPTION - MENUSYS_CYCLOSE) / 2); - menu->rct.bottom = menu->rct.top + MENUSYS_CYCLOSE; - menuvram_minimizebtn(vram, &menu->rct, 0); - } - else if (menutype == MENUS_CLOSE) { - menu->rct.right = mrect.right - MENU_PXCAPTION; - menu->rct.left = menu->rct.right - MENUSYS_CXCLOSE; - menu->rct.top = mrect.top + - ((MENUSYS_CYCAPTION - MENUSYS_CYCLOSE) / 2); - menu->rct.bottom = menu->rct.top + MENUSYS_CYCLOSE; - menuvram_closebtn(vram, &menu->rct, 0); - } - else { - menu->rct.left = posx; - menu->rct.top = mrect.bottom + MENUSYS_BCAPTION; - menu->rct.bottom = menu->rct.top + MENUSYS_CYSYS; - fontmng_getsize(menubase.font, menu->string, &pt); - posx += MENUSYS_SXSYS + pt.x + MENUSYS_LXSYS; - if (posx >= (menubase.width - - (MENU_FBORDER + MENU_BORDER + MENUSYS_BCAPTION))) { - break; - } - menu->rct.right = posx; - bitemdraw(vram, menu, 0); - } - } - items++; - menu = menu->next; - } - sys->wnd[0].items = items; - return(SUCCESS); - -wopn0_err: - return(FAILURE); -} - - -// ---- - -static void citemdraw2(VRAMHDL vram, MENUHDL menu, UINT mvc, int pos) { - -const MENURES2 *res; - POINT_T pt; - - res = menures_sys; - if (menu->flag & MENU_CHECKED) { - pt.x = menu->rct.left + MENUSYS_SXITEM + pos, - pt.y = menu->rct.top + pos; - menuvram_res3put(vram, res, &pt, mvc); - } - if (menu->child) { - pt.x = menu->rct.right - MENUSYS_SXITEM - res[1].width + pos, - pt.y = menu->rct.top + pos; - menuvram_res3put(vram, res+1, &pt, mvc); - } -} - -static void citemdraw(VRAMHDL vram, MENUHDL menu, int flag) { - - POINT_T pt; - void *font; - int left; - int right; - int top; - UINT32 txtcol; - - vram_filldat(vram, &menu->rct, (flag != 0)?0x000080:0xc0c0c0); - - if (menu->flag & MENU_SEPARATOR) { - left = menu->rct.left + MENUSYS_SXSEP; - right = menu->rct.right - MENUSYS_LXSEP; - top = menu->rct.top + MENUSYS_SYSEP; - menuvram_linex(vram, left, top, right, MVC_SHADOW); - menuvram_linex(vram, left, top + MENU_LINE, right, MVC_HILIGHT); - } - else { - left = menu->rct.left + MENUSYS_SXITEM + MENUSYS_CXCHECK; - top = menu->rct.top + MENUSYS_SYITEM; - font = menubase.font; - if (!(menu->flag & MENU_GRAY)) { - txtcol = (flag != 0)?MVC_CURTEXT:MVC_TEXT; - } - else { - if (flag == 0) { - pt.x = left + MENU_DSTEXT; - pt.y = top + MENU_DSTEXT; - vrammix_text(vram, font, menu->string, - menucolor[MVC_GRAYTEXT2], &pt, NULL); - citemdraw2(vram, menu, MVC_GRAYTEXT2, 1); - } - txtcol = MVC_GRAYTEXT1; - } - pt.x = left; - pt.y = top; - vrammix_text(vram, font, menu->string, menucolor[txtcol], &pt, NULL); - citemdraw2(vram, menu, txtcol, 0); - } -} - -static BRESULT childopn(MENUSYS *sys, int depth, int pos) { - - MENUHDL menu; - RECT_T parent; - int dir; - int width; - int height; - int items; - MSYSWND wnd; - int drawitems; - POINT_T pt; - - menu = getitem(sys, depth, pos); - if ((menu == NULL) || (menu->child == NULL)) { - TRACEOUT(("child not found.")); - goto copn_err; - } - wnd = sys->wnd + depth; - if ((menu->flag & MENUS_CTRLMASK) == MENUS_POPUP) { - parent.left = sys->popupx; - parent.top = MAX(sys->popupy, wnd->vram->height); - parent.right = parent.left; - parent.bottom = parent.top; - dir = 0; - } - else { - parent.left = wnd->vram->posx + menu->rct.left; - parent.top = wnd->vram->posy + menu->rct.top; - parent.right = wnd->vram->posx + menu->rct.right; - parent.bottom = wnd->vram->posy + menu->rct.bottom; - dir = depth + 1; - } - if (depth >= (MENUSYS_MAX - 1)) { - TRACEOUT(("menu max.")); - goto copn_err; - } - wnd++; - width = 0; - height = (MENU_FBORDER + MENU_BORDER); - items = 0; - drawitems = 0; - menu = menu->child; - wnd->menu = menu; - while(menu) { - if (!(menu->flag & MENU_DISABLE)) { - menu->rct.left = (MENU_FBORDER + MENU_BORDER); - menu->rct.top = height; - if (menu->flag & MENU_SEPARATOR) { - if (height > (menubase.height - MENUSYS_CYSEP - - (MENU_FBORDER + MENU_BORDER))) { - break; - } - height += MENUSYS_CYSEP; - menu->rct.bottom = height; - } - else { - if (height > (menubase.height - MENUSYS_CYITEM - - (MENU_FBORDER + MENU_BORDER))) { - break; - } - height += MENUSYS_CYITEM; - menu->rct.bottom = height; - fontmng_getsize(menubase.font, menu->string, &pt); - if (width < pt.x) { - width = pt.x; - } - } - } - items++; - menu = menu->next; - } - width += ((MENU_FBORDER + MENU_BORDER + MENUSYS_SXITEM) * 2) + - MENUSYS_CXCHECK + MENUSYS_CXNEXT; - if (width >= menubase.width) { - width = menubase.width; - } - height += (MENU_FBORDER + MENU_BORDER); - wnd->vram = menuvram_create(width, height, menubase.bpp); - if (wnd->vram == NULL) { - TRACEOUT(("sub menu vram couldn't create")); - goto copn_err; - } - if (dir == 1) { - if ((parent.top < height) || - (parent.bottom < (menubase.height - height))) { - parent.top = parent.bottom; - } - else { - parent.top -= height; - } - } - else if (dir >= 2) { - if ((parent.left < width) || - (parent.right < (menubase.width - width))) { - parent.left = parent.right; - } - else { - parent.left -= width; - } - if ((parent.top > (menubase.height - height)) && - (parent.bottom >= height)) { - parent.top = parent.bottom - height; - } - } - wnd->vram->posx = MIN(parent.left, menubase.width - width); - wnd->vram->posy = MIN(parent.top, menubase.height - height); - wnd->items = items; - wnd->focus = -1; - sys->depth++; - menu = wnd->menu; - drawitems = items; - while(drawitems--) { - if (!(menu->flag & MENU_DISABLE)) { - menu->rct.right = width - (MENU_FBORDER + MENU_BORDER); - citemdraw(wnd->vram, menu, 0); - } - menu = menu->next; - } - menubase_setrect(wnd->vram, NULL); - return(SUCCESS); - -copn_err: - return(FAILURE); -} - -static int openpopup(MENUSYS *sys) { - - MENUHDL menu; - int pos; - - if (sys->depth == 1) { - pos = 0; - menu = sys->root; - while(menu) { - if (!(menu->flag & (MENU_DISABLE | MENU_SEPARATOR))) { - if ((menu->flag & MENUS_CTRLMASK) == MENUS_POPUP) { - sys->wnd[0].focus = pos; - childopn(sys, 0, pos); - return(1); - } - } - menu = menu->next; - pos++; - } - } - return(0); -} - -static void itemdraw(MENUSYS *sys, int depth, int pos, int flag) { - - MENUHDL menu; - VRAMHDL vram; - void (*drawfn)(VRAMHDL vram, MENUHDL menu, int flag); - - menu = getitem(sys, depth, pos); - if (menu) { - vram = sys->wnd[depth].vram; - drawfn = (depth)?citemdraw:bitemdraw; - drawfn(vram, menu, flag); - menubase_setrect(vram, &menu->rct); - } -} - - -// ---- - -typedef struct { - int depth; - int pos; - MSYSWND wnd; - MENUHDL menu; -} MENUPOS; - -static void getposinfo(MENUSYS *sys, MENUPOS *pos, int x, int y) { - - RECT_T rct; - int cnt; - MSYSWND wnd; - MENUHDL menu; - - cnt = sys->depth; - wnd = sys->wnd + cnt; - while(cnt--) { - wnd--; - if (wnd->vram) { - vram_getrect(wnd->vram, &rct); - if (rect_in(&rct, x, y)) { - x -= wnd->vram->posx; - y -= wnd->vram->posy; - break; - } - } - } - if (cnt >= 0) { - pos->depth = cnt; - pos->wnd = wnd; - menu = wnd->menu; - cnt = 0; - while((menu) && (cnt < wnd->items)) { - if (!(menu->flag & (MENU_DISABLE | MENU_SEPARATOR))) { - if (rect_in(&menu->rct, x, y)) { - pos->pos = cnt; - pos->menu = menu; - return; - } - } - cnt++; - menu = menu->next; - } - } - else { - pos->depth = -1; - pos->wnd = NULL; - } - pos->pos = -1; - pos->menu = NULL; -} - - -// ---- - -static void defcmd(MENUID id) { - - (void)id; -} - -BRESULT menusys_create(const MSYSITEM *item, void (*cmd)(MENUID id), - UINT16 icon, const OEMCHAR *title) { - - MENUSYS *ret; - LISTARRAY r; - MENUHDL hdl; - - ret = &menusys; - ZeroMemory(ret, sizeof(MENUSYS)); - ret->icon = icon; - if (cmd == NULL) { - cmd = defcmd; - } - ret->cmd = cmd; - if (title) { - milstr_ncpy(ret->title, title, NELEMENTS(ret->title)); - } - r = listarray_new(sizeof(_MENUHDL), 32); - if (r == NULL) { - goto mscre_err; - } - ret->res = r; - hdl = appends(ret, s_root); - if (hdl == NULL) { - goto mscre_err; - } - ret->root = hdl; - if (item) { - while(hdl->next) { - hdl = hdl->next; - } - hdl->next = appends(ret, item); - } - return(SUCCESS); - -mscre_err: - return(FAILURE); -} - -void menusys_destroy(void) { - - MENUSYS *sys; - - sys = &menusys; - wndclose(sys, 0); - if (sys->res) { - listarray_destroy(sys->res); - } -} - -BRESULT menusys_open(int x, int y) { - - MENUSYS *sys; - - sys = &menusys; - - if (menubase_open(1) != SUCCESS) { - goto msopn_err; - } - sys->opened = 0; - sys->lastdepth = -1; - sys->lastpos = -1; - if (wndopenbase(sys) != SUCCESS) { - goto msopn_err; - } - sys->popupx = x; - sys->popupy = y; - sys->opened = openpopup(sys); - menubase_draw(draw, sys); - return(SUCCESS); - -msopn_err: - menubase_close(); - return(FAILURE); -} - -void menusys_close(void) { - - MENUSYS *sys; - - sys = &menusys; - wndclose(sys, 0); -} - -void menusys_moving(int x, int y, int btn) { - - MENUSYS *sys; - MENUPOS cur; - int topwnd; - - sys = &menusys; - getposinfo(sys, &cur, x, y); - - // メニューを閉じる〜 - if (cur.depth < 0) { - if (btn == 2) { - menubase_close(); - return; - } - } - topwnd = sys->depth - 1; - if (cur.menu != NULL) { - if (cur.wnd->focus != cur.pos) { - if (sys->opened) { - if (cur.depth != topwnd) { - wndclose(sys, cur.depth + 1); - } - if ((!(cur.menu->flag & MENU_GRAY)) && - (cur.menu->child != NULL)) { - childopn(sys, cur.depth, cur.pos); - } - } - itemdraw(sys, cur.depth, cur.wnd->focus, 0); - itemdraw(sys, cur.depth, cur.pos, 2 - sys->opened); - cur.wnd->focus = cur.pos; - } - if (!(cur.menu->flag & MENU_GRAY)) { - if (btn == 1) { - if ((!sys->opened) && (cur.depth == 0) && - (cur.menu->child != NULL)) { - wndclose(sys, 1); - itemdraw(sys, 0, cur.pos, 1); - childopn(sys, 0, cur.pos); - sys->opened = 1; - } - } - else if (btn == 2) { - if ((cur.menu->id) && (!(cur.menu->flag & MENU_NOSEND)) && (cur.menu->id != MID_DBSS)) { - menubase_close(); - sys->cmd(cur.menu->id); - return; - } - } - } - } - else { - if ((btn == 1) && (cur.depth == 0)) { - wndclose(sys, 1); - itemdraw(sys, 0, cur.wnd->focus, 0); - sys->opened = openpopup(sys); - } - else if (cur.depth != topwnd) { - cur.depth = topwnd; - cur.pos = -1; - cur.wnd = sys->wnd + cur.depth; - if (cur.wnd->focus != cur.pos) { - itemdraw(sys, cur.depth, cur.wnd->focus, 0); - cur.wnd->focus = cur.pos; - } - } - } - menubase_draw(draw, sys); -} - -static void focusmove(MENUSYS *sys, int depth, int dir) { - - MSYSWND wnd; - MENUHDL menu; - int pos; - MENUHDL target; - int tarpos; - - wnd = sys->wnd + depth; - target = NULL; - tarpos = 0; - pos = 0; - menu = wnd->menu; - while(menu) { - if (pos == wnd->focus) { - if ((dir < 0) && (target != NULL)) { - break; - } - } - else if (((menu->flag & MENUS_CTRLMASK) <= MENUS_SYSTEM) && - (!(menu->flag & - (MENU_DISABLE | MENU_GRAY | MENU_SEPARATOR)))) { - if (dir < 0) { - target = menu; - tarpos = pos; - } - else { - if (pos < wnd->focus) { - if (target == NULL) { - target = menu; - tarpos = pos; - } - } - else { - target = menu; - tarpos = pos; - break; - } - } - } - pos++; - menu = menu->next; - } - if (target == NULL) { - return; - } - itemdraw(sys, depth, wnd->focus, 0); - itemdraw(sys, depth, tarpos, 2 - sys->opened); - wnd->focus = tarpos; -// TRACEOUT(("focus = %d", tarpos)); - if (depth == 0) { - if (sys->opened) { - wndclose(sys, 1); - childopn(sys, 0, tarpos); - } - } - else { - if (depth != (sys->depth - 1)) { - wndclose(sys, depth + 1); - } - } -} - -static void focusenter(MENUSYS *sys, int depth, BOOL exec) { - - MENUHDL menu; - MSYSWND wnd; - - wnd = sys->wnd + depth; - menu = getitem(sys, depth, wnd->focus); - if ((menu) && (!(menu->flag & MENU_GRAY)) && - (menu->child != NULL)) { - if (depth == 0) { - wndclose(sys, 1); - itemdraw(sys, 0, wnd->focus, 1); - sys->opened = 1; - } - childopn(sys, depth, wnd->focus); - } - else if (exec) { - if ((menu) && (menu->id)) { - menubase_close(); - sys->cmd(menu->id); - } - } - else { - focusmove(sys, 0, 1); - } -} - -void menusys_key(UINT key) { - - MENUSYS *sys; - int topwnd; - - sys = &menusys; - topwnd = sys->depth - 1; - if (topwnd == 0) { - if (key & NP2_KEY_LEFT) { - focusmove(sys, 0, -1); - } - if (key & NP2_KEY_RIGHT) { - focusmove(sys, 0, 1); - } - if (key & NP2_KEY_DOWN) { - focusenter(sys, 0, FALSE); - } - if (key & KEY_ENTER) { - focusenter(sys, 0, TRUE); - } - } - else { - if (key & NP2_KEY_UP) { - focusmove(sys, topwnd, -1); - } - if (key & NP2_KEY_DOWN) { - focusmove(sys, topwnd, 1); - } - if (key & NP2_KEY_LEFT) { - if (topwnd >= 2) { - wndclose(sys, topwnd); - } - else { - focusmove(sys, 0, -1); - } - } - if (key & NP2_KEY_RIGHT) { - focusenter(sys, topwnd, FALSE); - } - if (key & KEY_ENTER) { - focusenter(sys, topwnd, TRUE); - } - } - menubase_draw(draw, sys); -} - - -// ---- - -typedef struct { - MENUHDL ret; - MENUID id; -} ITEMSEA; - -static BOOL _itemsea(void *vpItem, void *vpArg) { - - if (((MENUHDL)vpItem)->id == ((ITEMSEA *)vpArg)->id) { - ((ITEMSEA *)vpArg)->ret = (MENUHDL)vpItem; - return(TRUE); - } - return(FALSE); -} - -static MENUHDL itemsea(MENUSYS *sys, MENUID id) { - - ITEMSEA sea; - - sea.ret = NULL; - sea.id = id; - listarray_enum(sys->res, _itemsea, &sea); - return(sea.ret); -} - -static void menusys_setflag(MENUID id, MENUFLG flag, MENUFLG mask) { - - MENUSYS *sys; - MENUHDL itm; - int depth; - int pos; - int focus; - - sys = &menusys; - itm = itemsea(sys, id); - if (itm == NULL) { - goto mssf_end; - } - flag ^= itm->flag; - flag &= mask; - if (!flag) { - goto mssf_end; - } - itm->flag ^= flag; - - // リドローが必要? - depth = 0; - while(depth < sys->depth) { - itm = sys->wnd[depth].menu; - pos = 0; - while(itm) { - if (itm->id == id) { - if (!(itm->flag & (MENU_DISABLE | MENU_SEPARATOR))) { - focus = 0; - if (sys->wnd[depth].focus == pos) { - focus = 2 - sys->opened; - } - itemdraw(sys, depth, pos, focus); - menubase_draw(draw, sys); - goto mssf_end; - } - } - pos++; - itm = itm->next; - } - depth++; - } - -mssf_end: - return; -} - -static void menusys_settxt(MENUID id, const OEMCHAR *arg) { - - MENUSYS *sys; - MENUHDL itm; - int depth; - int pos; - int focus; - - sys = &menusys; - itm = itemsea(sys, id); - if (itm == NULL) { - goto msst_end; - } - - if (arg) { - milstr_ncpy(itm->string, arg, NELEMENTS(itm->string)); - } - else { - itm->string[0] = '\0'; - } - - // リドローが必要? (ToDo: 再オープンすべし) - depth = 0; - while(depth < sys->depth) { - itm = sys->wnd[depth].menu; - pos = 0; - while(itm) { - if (itm->id == id) { - if (!(itm->flag & (MENU_DISABLE | MENU_SEPARATOR))) { - focus = 0; - if (sys->wnd[depth].focus == pos) { - focus = 2 - sys->opened; - } - itemdraw(sys, depth, pos, focus); - menubase_draw(draw, sys); - goto msst_end; - } - } - pos++; - itm = itm->next; - } - depth++; - } - -msst_end: - return; -} - -INTPTR menusys_msg(int ctrl, MENUID id, INTPTR arg) { - - INTPTR ret; - MENUSYS *sys; - MENUHDL itm; - - ret = 0; - sys = &menusys; - itm = itemsea(sys, id); - if (itm == NULL) { - goto msmsg_exit; - } - - switch(ctrl) { - case SMSG_SETHIDE: - ret = (itm->flag & MENU_DISABLE) ? 1 : 0; - menusys_setflag(id, (MENUFLG)((arg) ? MENU_DISABLE : 0), MENU_DISABLE); - break; - - case SMSG_GETHIDE: - ret = (itm->flag & MENU_DISABLE) ? 1 : 0; - break; - - case SMSG_SETENABLE: - ret = (itm->flag & MENU_GRAY) ? 0 : 1; - menusys_setflag(id, (MENUFLG)((arg) ? 0 : MENU_GRAY), MENU_GRAY); - break; - - case SMSG_GETENABLE: - ret = (itm->flag & MENU_GRAY) ? 0 : 1; - break; - - case SMSG_SETCHECK: - ret = (itm->flag & MENU_CHECKED) ? 1 : 0; - menusys_setflag(id, (MENUFLG)((arg) ? MENU_CHECKED : 0), MENU_CHECKED); - break; - - case SMSG_GETCHECK: - ret = (itm->flag & MENU_CHECKED) ? 1 : 0; - break; - - case SMSG_SETTEXT: - menusys_settxt(id, (OEMCHAR*)arg); - break; - } - -msmsg_exit: - return(ret); -} - -void menusys_setstyle(UINT16 style) { - - menusys.style = style; -} - +#include +#include +#include +#include +#include +#include "menudeco.inc" +#include +#include + + +typedef struct _mhdl { +struct _mhdl *chain; +struct _mhdl *next; +struct _mhdl *child; + MENUID id; + MENUFLG flag; + RECT_T rct; + OEMCHAR string[32]; +} _MENUHDL, *MENUHDL; + +typedef struct { + VRAMHDL vram; + MENUHDL menu; + int items; + int focus; +} _MSYSWND, *MSYSWND; + +typedef struct { + _MSYSWND wnd[MENUSYS_MAX]; + LISTARRAY res; + MENUHDL lastres; + MENUHDL root; + UINT16 icon; + UINT16 style; + void (*cmd)(MENUID id); + int depth; + int opened; + int lastdepth; + int lastpos; + int popupx; + int popupy; + OEMCHAR title[128]; +} MENUSYS; + + +static MENUSYS menusys; + +#if defined(OSLANG_SJIS) && !defined(RESOURCE_US) +static const OEMCHAR str_sysr[] = // 元のサイズに戻す + "\214\263\202\314\203\124\203\103\203\131\202\311" \ + "\226\337\202\267"; +static const OEMCHAR str_sysm[] = // 移動 + "\210\332\223\256"; +static const OEMCHAR str_syss[] = // サイズ変更 + "\203\124\203\103\203\131\225\317\215\130"; +static const OEMCHAR str_sysn[] = // 最小化 + "\215\305\217\254\211\273"; +static const OEMCHAR str_sysx[] = // 最大化 + "\215\305\221\345\211\273"; +static const OEMCHAR str_sysc[] = // 閉じる + "\225\302\202\266\202\351"; +#elif defined(OSLANG_EUC) && !defined(RESOURCE_US) +static const OEMCHAR str_sysr[] = // 元のサイズに戻す + "\270\265\244\316\245\265\245\244\245\272\244\313" \ + "\314\341\244\271"; +static const OEMCHAR str_sysm[] = // 移動 + "\260\334\306\260"; +static const OEMCHAR str_syss[] = // サイズ変更 + "\245\265\245\244\245\272\312\321\271\271"; +static const OEMCHAR str_sysn[] = // 最小化 + "\272\307\276\256\262\275"; +static const OEMCHAR str_sysx[] = // 最大化 + "\272\307\302\347\262\275"; +static const OEMCHAR str_sysc[] = // 閉じる + "\312\304\244\270\244\353"; +#elif defined(OSLANG_UTF8) && !defined(RESOURCE_US) +static const OEMCHAR str_sysr[] = // 元のサイズに戻す + "\345\205\203\343\201\256\343\202\265\343\202\244\343\202\272" \ + "\343\201\253\346\210\273\343\201\231"; +static const OEMCHAR str_sysm[] = // 移動 + "\347\247\273\345\213\225"; +static const OEMCHAR str_syss[] = // サイズ変更 + "\343\202\265\343\202\244\343\202\272\345\244\211\346\233\264"; +static const OEMCHAR str_sysn[] = // 最小化 + "\346\234\200\345\260\217\345\214\226"; +static const OEMCHAR str_sysx[] = // 最大化 + "\346\234\200\345\244\247\345\214\226"; +static const OEMCHAR str_sysc[] = // 閉じる + "\351\226\211\343\201\230\343\202\213"; +#else +static const OEMCHAR str_sysr[] = OEMTEXT("Restore"); +static const OEMCHAR str_sysm[] = OEMTEXT("Move"); +static const OEMCHAR str_syss[] = OEMTEXT("Size"); +static const OEMCHAR str_sysn[] = OEMTEXT("Minimize"); +static const OEMCHAR str_sysx[] = OEMTEXT("Maximize"); +static const OEMCHAR str_sysc[] = OEMTEXT("Close"); +#endif + + +static const MSYSITEM s_exit[] = { + {str_sysr, NULL, 0, MENU_GRAY}, + {str_sysm, NULL, 0, MENU_GRAY}, + {str_syss, NULL, 0, MENU_GRAY}, +#if defined(MENU_TASKMINIMIZE) + {str_sysn, NULL, SID_MINIMIZE, 0}, +#else + {str_sysn, NULL, 0, MENU_GRAY}, +#endif + {str_sysx, NULL, 0, MENU_GRAY}, + {NULL, NULL, 0, MENU_SEPARATOR}, + {str_sysc, NULL, SID_CLOSE, MENU_DELETED}}; + +static const MSYSITEM s_root[] = { + {NULL, s_exit, 0, MENUS_SYSTEM}, +#if defined(MENU_TASKMINIMIZE) + {NULL, NULL, SID_MINIMIZE, MENUS_MINIMIZE}, +#endif + {NULL, NULL, SID_CLOSE, MENUS_CLOSE | + MENU_DELETED}}; + + +// ---- regist + +static BOOL seaempty(void *vpItem, void *vpArg) { + + if (((MENUHDL)vpItem)->flag & MENU_DELETED) { + return(TRUE); + } + (void)vpArg; + return(FALSE); +} + +static MENUHDL append1(MENUSYS *sys, const MSYSITEM *item) { + + MENUHDL ret; + _MENUHDL hdl; + + ZeroMemory(&hdl, sizeof(hdl)); + hdl.id = item->id; + hdl.flag = item->flag & (~MENU_DELETED); + if (item->string) { + milstr_ncpy(hdl.string, item->string, NELEMENTS(hdl.string)); + } + ret = (MENUHDL)listarray_enum(sys->res, seaempty, NULL); + if (ret) { + *ret = hdl; + } + else { + ret = (MENUHDL)listarray_append(sys->res, &hdl); + } + if (ret) { + if (sys->lastres) { + sys->lastres->chain = ret; + } + sys->lastres = ret; + } + return(ret); +} + +static MENUHDL appends(MENUSYS *sys, const MSYSITEM *item) { + + MENUHDL ret; + MENUHDL cur; + + ret = append1(sys, item); + cur = ret; + while(1) { + if (cur == NULL) { + goto ap_err; + } + if (item->child) { + cur->child = appends(sys, item->child); + } + if (item->flag & MENU_DELETED) { + break; + } + item++; + cur->next = append1(sys, item); + cur = cur->next; + } + return(ret); + +ap_err: + return(NULL); +} + + +// ---- + +static void draw(VRAMHDL dst, const RECT_T *rect, void *arg) { + + MENUSYS *sys; + int cnt; + MSYSWND wnd; + + sys = &menusys; + wnd = sys->wnd; + cnt = sys->depth; + while(cnt--) { + vrammix_cpy2(dst, rect, wnd->vram, NULL, 2); + wnd++; + } + (void)arg; +} + +static MENUHDL getitem(MENUSYS *sys, int depth, int pos) { + + MENUHDL ret; + + if ((unsigned int)depth >= (unsigned int)sys->depth) { + goto gi_err; + } + ret = sys->wnd[depth].menu; + while(ret) { + if (!pos) { + if (!(ret->flag & (MENU_DISABLE | MENU_SEPARATOR))) { + return(ret); + } + else { + break; + } + } + pos--; + ret = ret->next; + } + +gi_err: + return(NULL); +} + +static void wndclose(MENUSYS *sys, int depth) { + + MSYSWND wnd; + + sys->depth = depth; + wnd = sys->wnd + depth; + while(depth < MENUSYS_MAX) { + menubase_clrrect(wnd->vram); + vram_destroy(wnd->vram); + wnd->vram = NULL; + wnd++; + depth++; + } +} + +static void bitemdraw(VRAMHDL vram, MENUHDL menu, int flag) { + + void *font; + POINT_T pt; + UINT32 color; + int pos; + int menutype; + + font = menubase.font; + menutype = menu->flag & MENUS_CTRLMASK; + if (menutype == 0) { + vram_filldat(vram, &menu->rct, menucolor[MVC_STATIC]); + pos = 0; + if (flag) { + pos = 1; + } + if (!(menu->flag & MENU_GRAY)) { + color = menucolor[MVC_TEXT]; + } + else { +#if 0 + if (flag == 2) { + flag = 0; + pos = 0; + } +#endif + pt.x = menu->rct.left + pos + MENUSYS_SXSYS + MENU_DSTEXT; + pt.y = menu->rct.top + pos + MENUSYS_SYSYS + MENU_DSTEXT; + vrammix_text(vram, font, menu->string, + menucolor[MVC_GRAYTEXT2], &pt, NULL); + color = menucolor[MVC_GRAYTEXT1]; + } + pt.x = menu->rct.left + pos + MENUSYS_SXSYS; + pt.y = menu->rct.top + pos + MENUSYS_SYSYS; + vrammix_text(vram, font, menu->string, color, &pt, NULL); + if (flag) { + menuvram_box(vram, &menu->rct, + MVC2(MVC_SHADOW, MVC_HILIGHT), (flag==2)); + } + } +} + +enum { + MEXIST_SYS = 0x01, + MEXIST_MINIMIZE = 0x02, + MEXIST_CLOSE = 0x04, + MEXIST_ITEM = 0x08 +}; + +static BRESULT wndopenbase(MENUSYS *sys) { + + MENUHDL menu; + RECT_T mrect; + VRAMHDL vram; + int items; + int posx; + UINT rootflg; + int menutype; + int height; + POINT_T pt; + + wndclose(sys, 0); + + rootflg = 0; + menu = sys->root; + while(menu) { // メニュー内容を調べる。 + if (!(menu->flag & (MENU_DISABLE | MENU_SEPARATOR))) { + switch(menu->flag & MENUS_CTRLMASK) { + case MENUS_POPUP: + break; + + case MENUS_SYSTEM: + rootflg |= MEXIST_SYS; + break; + + case MENUS_MINIMIZE: + rootflg |= MEXIST_MINIMIZE; + break; + + case MENUS_CLOSE: + rootflg |= MEXIST_CLOSE; + break; + + default: + rootflg |= MEXIST_ITEM; + break; + } + } + menu = menu->next; + } + + mrect.left = MENU_FBORDER + MENU_BORDER; + mrect.top = MENU_FBORDER + MENU_BORDER; + mrect.right = menubase.width - (MENU_FBORDER + MENU_BORDER); + mrect.bottom = (MENU_FBORDER + MENU_BORDER) + MENUSYS_CYCAPTION; + height = ((MENU_FBORDER + MENU_BORDER) * 2) + MENUSYS_CYCAPTION; + if (rootflg & MEXIST_ITEM) { + height += (MENUSYS_BCAPTION * 3) + MENUSYS_CYSYS; + mrect.left += MENUSYS_BCAPTION; + mrect.top += MENUSYS_BCAPTION; + mrect.right -= MENUSYS_BCAPTION; + mrect.bottom += MENUSYS_BCAPTION; + } + vram = menuvram_create(menubase.width, height, menubase.bpp); + sys->wnd[0].vram = vram; + if (vram == NULL) { + goto wopn0_err; + } + if (sys->style & MENUSTYLE_BOTTOM) { + vram->posy = MAX(0, menuvram->height - height); + } + menuvram_caption(vram, &mrect, sys->icon, sys->title); + menubase_setrect(vram, NULL); + menu = sys->root; + sys->wnd[0].menu = menu; + sys->wnd[0].focus = -1; + sys->depth++; + items = 0; + posx = MENU_FBORDER + MENU_BORDER + MENUSYS_BCAPTION; + while(menu) { + if (!(menu->flag & (MENU_DISABLE | MENU_SEPARATOR))) { + menutype = menu->flag & MENUS_CTRLMASK; + if (menutype == MENUS_POPUP) { + } + else if (menutype == MENUS_SYSTEM) { + menu->rct.left = mrect.left + MENU_PXCAPTION; + menu->rct.right = menu->rct.left; + menu->rct.top = mrect.top + MENU_PYCAPTION; + menu->rct.bottom = menu->rct.top; + if (sys->icon) { + menu->rct.right += MENUSYS_SZICON; + menu->rct.bottom += MENUSYS_SZICON; + } + } + else if (menutype == MENUS_MINIMIZE) { + menu->rct.right = mrect.right - MENU_PXCAPTION; + if (rootflg & MEXIST_CLOSE) { + menu->rct.right -= MENUSYS_CXCLOSE + (MENU_LINE * 2); + } + menu->rct.left = menu->rct.right - MENUSYS_CXCLOSE; + menu->rct.top = mrect.top + + ((MENUSYS_CYCAPTION - MENUSYS_CYCLOSE) / 2); + menu->rct.bottom = menu->rct.top + MENUSYS_CYCLOSE; + menuvram_minimizebtn(vram, &menu->rct, 0); + } + else if (menutype == MENUS_CLOSE) { + menu->rct.right = mrect.right - MENU_PXCAPTION; + menu->rct.left = menu->rct.right - MENUSYS_CXCLOSE; + menu->rct.top = mrect.top + + ((MENUSYS_CYCAPTION - MENUSYS_CYCLOSE) / 2); + menu->rct.bottom = menu->rct.top + MENUSYS_CYCLOSE; + menuvram_closebtn(vram, &menu->rct, 0); + } + else { + menu->rct.left = posx; + menu->rct.top = mrect.bottom + MENUSYS_BCAPTION; + menu->rct.bottom = menu->rct.top + MENUSYS_CYSYS; + fontmng_getsize(menubase.font, menu->string, &pt); + posx += MENUSYS_SXSYS + pt.x + MENUSYS_LXSYS; + if (posx >= (menubase.width - + (MENU_FBORDER + MENU_BORDER + MENUSYS_BCAPTION))) { + break; + } + menu->rct.right = posx; + bitemdraw(vram, menu, 0); + } + } + items++; + menu = menu->next; + } + sys->wnd[0].items = items; + return(SUCCESS); + +wopn0_err: + return(FAILURE); +} + + +// ---- + +static void citemdraw2(VRAMHDL vram, MENUHDL menu, UINT mvc, int pos) { + +const MENURES2 *res; + POINT_T pt; + + res = menures_sys; + if (menu->flag & MENU_CHECKED) { + pt.x = menu->rct.left + MENUSYS_SXITEM + pos, + pt.y = menu->rct.top + pos; + menuvram_res3put(vram, res, &pt, mvc); + } + if (menu->child) { + pt.x = menu->rct.right - MENUSYS_SXITEM - res[1].width + pos, + pt.y = menu->rct.top + pos; + menuvram_res3put(vram, res+1, &pt, mvc); + } +} + +static void citemdraw(VRAMHDL vram, MENUHDL menu, int flag) { + + POINT_T pt; + void *font; + int left; + int right; + int top; + UINT32 txtcol; + + vram_filldat(vram, &menu->rct, (flag != 0)?0x000080:0xc0c0c0); + + if (menu->flag & MENU_SEPARATOR) { + left = menu->rct.left + MENUSYS_SXSEP; + right = menu->rct.right - MENUSYS_LXSEP; + top = menu->rct.top + MENUSYS_SYSEP; + menuvram_linex(vram, left, top, right, MVC_SHADOW); + menuvram_linex(vram, left, top + MENU_LINE, right, MVC_HILIGHT); + } + else { + left = menu->rct.left + MENUSYS_SXITEM + MENUSYS_CXCHECK; + top = menu->rct.top + MENUSYS_SYITEM; + font = menubase.font; + if (!(menu->flag & MENU_GRAY)) { + txtcol = (flag != 0)?MVC_CURTEXT:MVC_TEXT; + } + else { + if (flag == 0) { + pt.x = left + MENU_DSTEXT; + pt.y = top + MENU_DSTEXT; + vrammix_text(vram, font, menu->string, + menucolor[MVC_GRAYTEXT2], &pt, NULL); + citemdraw2(vram, menu, MVC_GRAYTEXT2, 1); + } + txtcol = MVC_GRAYTEXT1; + } + pt.x = left; + pt.y = top; + vrammix_text(vram, font, menu->string, menucolor[txtcol], &pt, NULL); + citemdraw2(vram, menu, txtcol, 0); + } +} + +static BRESULT childopn(MENUSYS *sys, int depth, int pos) { + + MENUHDL menu; + RECT_T parent; + int dir; + int width; + int height; + int items; + MSYSWND wnd; + int drawitems; + POINT_T pt; + + menu = getitem(sys, depth, pos); + if ((menu == NULL) || (menu->child == NULL)) { + TRACEOUT(("child not found.")); + goto copn_err; + } + wnd = sys->wnd + depth; + if ((menu->flag & MENUS_CTRLMASK) == MENUS_POPUP) { + parent.left = sys->popupx; + parent.top = MAX(sys->popupy, wnd->vram->height); + parent.right = parent.left; + parent.bottom = parent.top; + dir = 0; + } + else { + parent.left = wnd->vram->posx + menu->rct.left; + parent.top = wnd->vram->posy + menu->rct.top; + parent.right = wnd->vram->posx + menu->rct.right; + parent.bottom = wnd->vram->posy + menu->rct.bottom; + dir = depth + 1; + } + if (depth >= (MENUSYS_MAX - 1)) { + TRACEOUT(("menu max.")); + goto copn_err; + } + wnd++; + width = 0; + height = (MENU_FBORDER + MENU_BORDER); + items = 0; + drawitems = 0; + menu = menu->child; + wnd->menu = menu; + while(menu) { + if (!(menu->flag & MENU_DISABLE)) { + menu->rct.left = (MENU_FBORDER + MENU_BORDER); + menu->rct.top = height; + if (menu->flag & MENU_SEPARATOR) { + if (height > (menubase.height - MENUSYS_CYSEP - + (MENU_FBORDER + MENU_BORDER))) { + break; + } + height += MENUSYS_CYSEP; + menu->rct.bottom = height; + } + else { + if (height > (menubase.height - MENUSYS_CYITEM - + (MENU_FBORDER + MENU_BORDER))) { + break; + } + height += MENUSYS_CYITEM; + menu->rct.bottom = height; + fontmng_getsize(menubase.font, menu->string, &pt); + if (width < pt.x) { + width = pt.x; + } + } + } + items++; + menu = menu->next; + } + width += ((MENU_FBORDER + MENU_BORDER + MENUSYS_SXITEM) * 2) + + MENUSYS_CXCHECK + MENUSYS_CXNEXT; + if (width >= menubase.width) { + width = menubase.width; + } + height += (MENU_FBORDER + MENU_BORDER); + wnd->vram = menuvram_create(width, height, menubase.bpp); + if (wnd->vram == NULL) { + TRACEOUT(("sub menu vram couldn't create")); + goto copn_err; + } + if (dir == 1) { + if ((parent.top < height) || + (parent.bottom < (menubase.height - height))) { + parent.top = parent.bottom; + } + else { + parent.top -= height; + } + } + else if (dir >= 2) { + if ((parent.left < width) || + (parent.right < (menubase.width - width))) { + parent.left = parent.right; + } + else { + parent.left -= width; + } + if ((parent.top > (menubase.height - height)) && + (parent.bottom >= height)) { + parent.top = parent.bottom - height; + } + } + wnd->vram->posx = MIN(parent.left, menubase.width - width); + wnd->vram->posy = MIN(parent.top, menubase.height - height); + wnd->items = items; + wnd->focus = -1; + sys->depth++; + menu = wnd->menu; + drawitems = items; + while(drawitems--) { + if (!(menu->flag & MENU_DISABLE)) { + menu->rct.right = width - (MENU_FBORDER + MENU_BORDER); + citemdraw(wnd->vram, menu, 0); + } + menu = menu->next; + } + menubase_setrect(wnd->vram, NULL); + return(SUCCESS); + +copn_err: + return(FAILURE); +} + +static int openpopup(MENUSYS *sys) { + + MENUHDL menu; + int pos; + + if (sys->depth == 1) { + pos = 0; + menu = sys->root; + while(menu) { + if (!(menu->flag & (MENU_DISABLE | MENU_SEPARATOR))) { + if ((menu->flag & MENUS_CTRLMASK) == MENUS_POPUP) { + sys->wnd[0].focus = pos; + childopn(sys, 0, pos); + return(1); + } + } + menu = menu->next; + pos++; + } + } + return(0); +} + +static void itemdraw(MENUSYS *sys, int depth, int pos, int flag) { + + MENUHDL menu; + VRAMHDL vram; + void (*drawfn)(VRAMHDL vram, MENUHDL menu, int flag); + + menu = getitem(sys, depth, pos); + if (menu) { + vram = sys->wnd[depth].vram; + drawfn = (depth)?citemdraw:bitemdraw; + drawfn(vram, menu, flag); + menubase_setrect(vram, &menu->rct); + } +} + + +// ---- + +typedef struct { + int depth; + int pos; + MSYSWND wnd; + MENUHDL menu; +} MENUPOS; + +static void getposinfo(MENUSYS *sys, MENUPOS *pos, int x, int y) { + + RECT_T rct; + int cnt; + MSYSWND wnd; + MENUHDL menu; + + cnt = sys->depth; + wnd = sys->wnd + cnt; + while(cnt--) { + wnd--; + if (wnd->vram) { + vram_getrect(wnd->vram, &rct); + if (rect_in(&rct, x, y)) { + x -= wnd->vram->posx; + y -= wnd->vram->posy; + break; + } + } + } + if (cnt >= 0) { + pos->depth = cnt; + pos->wnd = wnd; + menu = wnd->menu; + cnt = 0; + while((menu) && (cnt < wnd->items)) { + if (!(menu->flag & (MENU_DISABLE | MENU_SEPARATOR))) { + if (rect_in(&menu->rct, x, y)) { + pos->pos = cnt; + pos->menu = menu; + return; + } + } + cnt++; + menu = menu->next; + } + } + else { + pos->depth = -1; + pos->wnd = NULL; + } + pos->pos = -1; + pos->menu = NULL; +} + + +// ---- + +static void defcmd(MENUID id) { + + (void)id; +} + +BRESULT menusys_create(const MSYSITEM *item, void (*cmd)(MENUID id), + UINT16 icon, const OEMCHAR *title) { + + MENUSYS *ret; + LISTARRAY r; + MENUHDL hdl; + + ret = &menusys; + ZeroMemory(ret, sizeof(MENUSYS)); + ret->icon = icon; + if (cmd == NULL) { + cmd = defcmd; + } + ret->cmd = cmd; + if (title) { + milstr_ncpy(ret->title, title, NELEMENTS(ret->title)); + } + r = listarray_new(sizeof(_MENUHDL), 32); + if (r == NULL) { + goto mscre_err; + } + ret->res = r; + hdl = appends(ret, s_root); + if (hdl == NULL) { + goto mscre_err; + } + ret->root = hdl; + if (item) { + while(hdl->next) { + hdl = hdl->next; + } + hdl->next = appends(ret, item); + } + return(SUCCESS); + +mscre_err: + return(FAILURE); +} + +void menusys_destroy(void) { + + MENUSYS *sys; + + sys = &menusys; + wndclose(sys, 0); + if (sys->res) { + listarray_destroy(sys->res); + } +} + +BRESULT menusys_open(int x, int y) { + + MENUSYS *sys; + + sys = &menusys; + + if (menubase_open(1) != SUCCESS) { + goto msopn_err; + } + sys->opened = 0; + sys->lastdepth = -1; + sys->lastpos = -1; + if (wndopenbase(sys) != SUCCESS) { + goto msopn_err; + } + sys->popupx = x; + sys->popupy = y; + sys->opened = openpopup(sys); + menubase_draw(draw, sys); + return(SUCCESS); + +msopn_err: + menubase_close(); + return(FAILURE); +} + +void menusys_close(void) { + + MENUSYS *sys; + + sys = &menusys; + wndclose(sys, 0); +} + +void menusys_moving(int x, int y, int btn) { + + MENUSYS *sys; + MENUPOS cur; + int topwnd; + + sys = &menusys; + getposinfo(sys, &cur, x, y); + + // メニューを閉じる〜 + if (cur.depth < 0) { + if (btn == 2) { + menubase_close(); + return; + } + } + topwnd = sys->depth - 1; + if (cur.menu != NULL) { + if (cur.wnd->focus != cur.pos) { + if (sys->opened) { + if (cur.depth != topwnd) { + wndclose(sys, cur.depth + 1); + } + if ((!(cur.menu->flag & MENU_GRAY)) && + (cur.menu->child != NULL)) { + childopn(sys, cur.depth, cur.pos); + } + } + itemdraw(sys, cur.depth, cur.wnd->focus, 0); + itemdraw(sys, cur.depth, cur.pos, 2 - sys->opened); + cur.wnd->focus = cur.pos; + } + if (!(cur.menu->flag & MENU_GRAY)) { + if (btn == 1) { + if ((!sys->opened) && (cur.depth == 0) && + (cur.menu->child != NULL)) { + wndclose(sys, 1); + itemdraw(sys, 0, cur.pos, 1); + childopn(sys, 0, cur.pos); + sys->opened = 1; + } + } + else if (btn == 2) { + if ((cur.menu->id) && (!(cur.menu->flag & MENU_NOSEND)) && (cur.menu->id != MID_DBSS)) { + menubase_close(); + sys->cmd(cur.menu->id); + return; + } + } + } + } + else { + if ((btn == 1) && (cur.depth == 0)) { + wndclose(sys, 1); + itemdraw(sys, 0, cur.wnd->focus, 0); + sys->opened = openpopup(sys); + } + else if (cur.depth != topwnd) { + cur.depth = topwnd; + cur.pos = -1; + cur.wnd = sys->wnd + cur.depth; + if (cur.wnd->focus != cur.pos) { + itemdraw(sys, cur.depth, cur.wnd->focus, 0); + cur.wnd->focus = cur.pos; + } + } + } + menubase_draw(draw, sys); +} + +static void focusmove(MENUSYS *sys, int depth, int dir) { + + MSYSWND wnd; + MENUHDL menu; + int pos; + MENUHDL target; + int tarpos; + + wnd = sys->wnd + depth; + target = NULL; + tarpos = 0; + pos = 0; + menu = wnd->menu; + while(menu) { + if (pos == wnd->focus) { + if ((dir < 0) && (target != NULL)) { + break; + } + } + else if (((menu->flag & MENUS_CTRLMASK) <= MENUS_SYSTEM) && + (!(menu->flag & + (MENU_DISABLE | MENU_GRAY | MENU_SEPARATOR)))) { + if (dir < 0) { + target = menu; + tarpos = pos; + } + else { + if (pos < wnd->focus) { + if (target == NULL) { + target = menu; + tarpos = pos; + } + } + else { + target = menu; + tarpos = pos; + break; + } + } + } + pos++; + menu = menu->next; + } + if (target == NULL) { + return; + } + itemdraw(sys, depth, wnd->focus, 0); + itemdraw(sys, depth, tarpos, 2 - sys->opened); + wnd->focus = tarpos; +// TRACEOUT(("focus = %d", tarpos)); + if (depth == 0) { + if (sys->opened) { + wndclose(sys, 1); + childopn(sys, 0, tarpos); + } + } + else { + if (depth != (sys->depth - 1)) { + wndclose(sys, depth + 1); + } + } +} + +static void focusenter(MENUSYS *sys, int depth, BOOL exec) { + + MENUHDL menu; + MSYSWND wnd; + + wnd = sys->wnd + depth; + menu = getitem(sys, depth, wnd->focus); + if ((menu) && (!(menu->flag & MENU_GRAY)) && + (menu->child != NULL)) { + if (depth == 0) { + wndclose(sys, 1); + itemdraw(sys, 0, wnd->focus, 1); + sys->opened = 1; + } + childopn(sys, depth, wnd->focus); + } + else if (exec) { + if ((menu) && (menu->id)) { + menubase_close(); + sys->cmd(menu->id); + } + } + else { + focusmove(sys, 0, 1); + } +} + +void menusys_key(UINT key) { + + MENUSYS *sys; + int topwnd; + + sys = &menusys; + topwnd = sys->depth - 1; + if (topwnd == 0) { + if (key & NP2_KEY_LEFT) { + focusmove(sys, 0, -1); + } + if (key & NP2_KEY_RIGHT) { + focusmove(sys, 0, 1); + } + if (key & NP2_KEY_DOWN) { + focusenter(sys, 0, FALSE); + } + if (key & KEY_ENTER) { + focusenter(sys, 0, TRUE); + } + } + else { + if (key & NP2_KEY_UP) { + focusmove(sys, topwnd, -1); + } + if (key & NP2_KEY_DOWN) { + focusmove(sys, topwnd, 1); + } + if (key & NP2_KEY_LEFT) { + if (topwnd >= 2) { + wndclose(sys, topwnd); + } + else { + focusmove(sys, 0, -1); + } + } + if (key & NP2_KEY_RIGHT) { + focusenter(sys, topwnd, FALSE); + } + if (key & KEY_ENTER) { + focusenter(sys, topwnd, TRUE); + } + } + menubase_draw(draw, sys); +} + + +// ---- + +typedef struct { + MENUHDL ret; + MENUID id; +} ITEMSEA; + +static BOOL _itemsea(void *vpItem, void *vpArg) { + + if (((MENUHDL)vpItem)->id == ((ITEMSEA *)vpArg)->id) { + ((ITEMSEA *)vpArg)->ret = (MENUHDL)vpItem; + return(TRUE); + } + return(FALSE); +} + +static MENUHDL itemsea(MENUSYS *sys, MENUID id) { + + ITEMSEA sea; + + sea.ret = NULL; + sea.id = id; + listarray_enum(sys->res, _itemsea, &sea); + return(sea.ret); +} + +static void menusys_setflag(MENUID id, MENUFLG flag, MENUFLG mask) { + + MENUSYS *sys; + MENUHDL itm; + int depth; + int pos; + int focus; + + sys = &menusys; + itm = itemsea(sys, id); + if (itm == NULL) { + goto mssf_end; + } + flag ^= itm->flag; + flag &= mask; + if (!flag) { + goto mssf_end; + } + itm->flag ^= flag; + + // リドローが必要? + depth = 0; + while(depth < sys->depth) { + itm = sys->wnd[depth].menu; + pos = 0; + while(itm) { + if (itm->id == id) { + if (!(itm->flag & (MENU_DISABLE | MENU_SEPARATOR))) { + focus = 0; + if (sys->wnd[depth].focus == pos) { + focus = 2 - sys->opened; + } + itemdraw(sys, depth, pos, focus); + menubase_draw(draw, sys); + goto mssf_end; + } + } + pos++; + itm = itm->next; + } + depth++; + } + +mssf_end: + return; +} + +static void menusys_settxt(MENUID id, const OEMCHAR *arg) { + + MENUSYS *sys; + MENUHDL itm; + int depth; + int pos; + int focus; + + sys = &menusys; + itm = itemsea(sys, id); + if (itm == NULL) { + goto msst_end; + } + + if (arg) { + milstr_ncpy(itm->string, arg, NELEMENTS(itm->string)); + } + else { + itm->string[0] = '\0'; + } + + // リドローが必要? (ToDo: 再オープンすべし) + depth = 0; + while(depth < sys->depth) { + itm = sys->wnd[depth].menu; + pos = 0; + while(itm) { + if (itm->id == id) { + if (!(itm->flag & (MENU_DISABLE | MENU_SEPARATOR))) { + focus = 0; + if (sys->wnd[depth].focus == pos) { + focus = 2 - sys->opened; + } + itemdraw(sys, depth, pos, focus); + menubase_draw(draw, sys); + goto msst_end; + } + } + pos++; + itm = itm->next; + } + depth++; + } + +msst_end: + return; +} + +INTPTR menusys_msg(int ctrl, MENUID id, INTPTR arg) { + + INTPTR ret; + MENUSYS *sys; + MENUHDL itm; + + ret = 0; + sys = &menusys; + itm = itemsea(sys, id); + if (itm == NULL) { + goto msmsg_exit; + } + + switch(ctrl) { + case SMSG_SETHIDE: + ret = (itm->flag & MENU_DISABLE) ? 1 : 0; + menusys_setflag(id, (MENUFLG)((arg) ? MENU_DISABLE : 0), MENU_DISABLE); + break; + + case SMSG_GETHIDE: + ret = (itm->flag & MENU_DISABLE) ? 1 : 0; + break; + + case SMSG_SETENABLE: + ret = (itm->flag & MENU_GRAY) ? 0 : 1; + menusys_setflag(id, (MENUFLG)((arg) ? 0 : MENU_GRAY), MENU_GRAY); + break; + + case SMSG_GETENABLE: + ret = (itm->flag & MENU_GRAY) ? 0 : 1; + break; + + case SMSG_SETCHECK: + ret = (itm->flag & MENU_CHECKED) ? 1 : 0; + menusys_setflag(id, (MENUFLG)((arg) ? MENU_CHECKED : 0), MENU_CHECKED); + break; + + case SMSG_GETCHECK: + ret = (itm->flag & MENU_CHECKED) ? 1 : 0; + break; + + case SMSG_SETTEXT: + menusys_settxt(id, (OEMCHAR*)arg); + break; + } + +msmsg_exit: + return(ret); +} + +void menusys_setstyle(UINT16 style) { + + menusys.style = style; +} + diff --git a/embed/menubase/menusys.h b/embed/menubase/menusys.h old mode 100755 new mode 100644 index 1b0be1f4..db27c881 --- a/embed/menubase/menusys.h +++ b/embed/menubase/menusys.h @@ -1,78 +1,78 @@ - -enum { - MENUSYS_MAX = 8 -}; - -enum { - SMSG_SETHIDE = 0, - SMSG_GETHIDE, - SMSG_SETENABLE, - SMSG_GETENABLE, - SMSG_SETCHECK, - SMSG_GETCHECK, - SMSG_SETTEXT -}; - -enum { - MENUS_POPUP = 0x0010, - MENUS_SYSTEM = 0x0020, - MENUS_MINIMIZE = 0x0030, - MENUS_CLOSE = 0x0040, - MENUS_CTRLMASK = 0x0070 -}; - -enum { - MENUSTYLE_BOTTOM = 0x0001 -}; - -typedef struct _smi { -const OEMCHAR *string; -const struct _smi *child; - MENUID id; - MENUFLG flag; -} MSYSITEM; - - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT menusys_create(const MSYSITEM *item, void (*cmd)(MENUID id), - UINT16 icon, const OEMCHAR *title); -void menusys_destroy(void); - -BRESULT menusys_open(int x, int y); -void menusys_close(void); - -void menusys_moving(int x, int y, int btn); -void menusys_key(UINT key); - -INTPTR menusys_msg(int ctrl, MENUID id, INTPTR arg); - -void menusys_setstyle(UINT16 style); - -#ifdef __cplusplus -} -#endif - - -// ---- MACRO - -#define menusys_sethide(id, hide) \ - menusys_msg(SMSG_SETHIDE, (id), (INTPTR)(hide)) -#define menusys_gethide(id) \ - ((int)menusys_msg(SMSG_GETHIDE, (id), 0)) - -#define menusys_setenable(id, enable) \ - menusys_msg(SMSG_SETENABLE, (id), (long)(enable)) -#define menusys_getenable(id) \ - ((int)menusys_msg(SMSG_GETENABLE, (id), 0)) - -#define menusys_setcheck(id, checked) \ - menusys_msg(SMSG_SETCHECK, (id), (long)(checked)) -#define menusys_getcheck(id) \ - ((int)menusys_msg(SMSG_GETCHECK, (id), 0)) - -#define menusys_settext(id, str) \ - menusys_msg(SMSG_SETTEXT, (id), (INTPTR)(str)) - + +enum { + MENUSYS_MAX = 8 +}; + +enum { + SMSG_SETHIDE = 0, + SMSG_GETHIDE, + SMSG_SETENABLE, + SMSG_GETENABLE, + SMSG_SETCHECK, + SMSG_GETCHECK, + SMSG_SETTEXT +}; + +enum { + MENUS_POPUP = 0x0010, + MENUS_SYSTEM = 0x0020, + MENUS_MINIMIZE = 0x0030, + MENUS_CLOSE = 0x0040, + MENUS_CTRLMASK = 0x0070 +}; + +enum { + MENUSTYLE_BOTTOM = 0x0001 +}; + +typedef struct _smi { +const OEMCHAR *string; +const struct _smi *child; + MENUID id; + MENUFLG flag; +} MSYSITEM; + + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT menusys_create(const MSYSITEM *item, void (*cmd)(MENUID id), + UINT16 icon, const OEMCHAR *title); +void menusys_destroy(void); + +BRESULT menusys_open(int x, int y); +void menusys_close(void); + +void menusys_moving(int x, int y, int btn); +void menusys_key(UINT key); + +INTPTR menusys_msg(int ctrl, MENUID id, INTPTR arg); + +void menusys_setstyle(UINT16 style); + +#ifdef __cplusplus +} +#endif + + +// ---- MACRO + +#define menusys_sethide(id, hide) \ + menusys_msg(SMSG_SETHIDE, (id), (INTPTR)(hide)) +#define menusys_gethide(id) \ + ((int)menusys_msg(SMSG_GETHIDE, (id), 0)) + +#define menusys_setenable(id, enable) \ + menusys_msg(SMSG_SETENABLE, (id), (long)(enable)) +#define menusys_getenable(id) \ + ((int)menusys_msg(SMSG_GETENABLE, (id), 0)) + +#define menusys_setcheck(id, checked) \ + menusys_msg(SMSG_SETCHECK, (id), (long)(checked)) +#define menusys_getcheck(id) \ + ((int)menusys_msg(SMSG_GETCHECK, (id), 0)) + +#define menusys_settext(id, str) \ + menusys_msg(SMSG_SETTEXT, (id), (INTPTR)(str)) + diff --git a/embed/menubase/menuvram.c b/embed/menubase/menuvram.c old mode 100755 new mode 100644 index ce387580..aef46526 --- a/embed/menubase/menuvram.c +++ b/embed/menubase/menuvram.c @@ -1,1229 +1,1229 @@ -#include -#include -#include -#include "menudeco.inc" -#include - - -UINT32 menucolor[] = { - 0xffffff, // MVC_BACK - 0xffffff, // MVC_HILIGHT - 0xc0c0c0, // MVC_LIGHT - 0x808080, // MVC_SHADOW - 0x000000, // MVC_DARK - 0xe0e0e0, // MVC_SCROLLBAR - - 0xc0c0c0, // MVC_STATIC - 0x000000, // MVC_TEXT - 0x808080, // MVC_GRAYTEXT1 - 0xffffff, // MVC_GRAYTEXT2 - 0xc0c0c0, // MVC_BTNFACE - 0xffffff, // MVC_CURTEXT - 0x000080, // MVC_CURBACK -}; - - -static const UINT8 __pat[64] = { - 0x00, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x44, 0x00, - 0x55, 0x00, 0x44, 0x00, - 0x55, 0x00, 0x55, 0x00, - 0x55, 0x22, 0x55, 0x00, - 0x55, 0x22, 0x55, 0x88, - 0x55, 0xaa, 0x55, 0x88, - 0x55, 0xaa, 0x55, 0xaa, - 0x77, 0xaa, 0x55, 0xaa, - 0x77, 0xaa, 0xdd, 0xaa, - 0xff, 0xaa, 0xdd, 0xaa, - 0xff, 0xaa, 0xff, 0xaa, - 0xff, 0xbb, 0xff, 0xaa, - 0xff, 0xbb, 0xff, 0xee, - 0xff, 0xff, 0xff, 0xee}; - - -typedef struct { - int width; - int height; - int pos; - int step; - int linedel; -} RESPUT; - -static BRESULT resputprepare(VRAMHDL vram, const MENURES2 *res, - const POINT_T *pt, RESPUT *rp) { - - int width; - int height; - int step; - int pos; - - if ((vram == NULL) || (res == NULL)) { - goto rpp_err; - } - width = res->width; - height = res->height; - step = 0; - pos = pt->x; - if (pos < 0) { - width += pos; - step += pos; - pos = 0; - } - rp->pos = (pos * vram->xalign); - pos = vram->width - pos; - if (width > pos) { - width = pos; - } - if (width <= 0) { - goto rpp_err; - } - rp->width = width; - - pos = pt->y; - if (pos < 0) { - height += pos; - step += pos * res->width; - pos = 0; - } - rp->pos += (pos * vram->yalign); - pos = vram->height - pos; - if (height > pos) { - height = pos; - } - if (height <= 0) { - goto rpp_err; - } - rp->height = height; - rp->step = step; - rp->linedel = width - res->width; - return(SUCCESS); - -rpp_err: - return(FAILURE); -} - - -#ifdef SUPPORT_16BPP - -static const UINT16 menucolor16[] = { - MAKE16PAL(0xffffff), // MVC_BACK - MAKE16PAL(0xffffff), // MVC_HILIGHT - MAKE16PAL(0xc0c0c0), // MVC_LIGHT - MAKE16PAL(0x808080), // MVC_SHADOW - MAKE16PAL(0x000000), // MVC_DARK - MAKE16PAL(0xe0e0e0), // MVC_SCROLLBAR - - MAKE16PAL(0xc0c0c0), // MVC_STATIC - MAKE16PAL(0x000000), // MVC_TEXT - MAKE16PAL(0x808080), // MVC_GRAYTEXT1 - MAKE16PAL(0xffffff), // MVC_GRAYTEXT2 - MAKE16PAL(0xc0c0c0), // MVC_BTNFACE - MAKE16PAL(0xffffff), // MVC_CURTEXT - MAKE16PAL(0x000080), // MVC_CURBACK -}; - -static const int __rsft[] = {1, 7, 12}; - -static void res2put16(VRAMHDL vram, const MENURES2 *res, RESPUT *rp) { - - int width; -const UINT8 *p; - UINT8 *q; - int cnt; - int step; - int bit; - int pix = 0; // for cygwin - int c; - UINT16 dat; - - p = res->pat; - q = vram->ptr + rp->pos; - step = vram->yalign - (rp->width * 2); - cnt = rp->step; - width = rp->width; - bit = 0; - while(1) { - while(cnt <= 0) { - cnt++; - pix = ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - if (pix >= 7) { - cnt += (pix - 7) + 2; - pix = ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - } - } - c = MIN(cnt, width); - cnt -= c; - width -= c; - if (pix) { - dat = menucolor16[pix - 1]; - do { - *(UINT16 *)q = (UINT16)dat; - q += 2; - } while(--c); - } - else { - q += c * 2; - } - if (!width) { - rp->height--; - if (!rp->height) { - break; - } - width = rp->width; - cnt += rp->linedel; - q += step; - } - } -} - -static void res3put16(VRAMHDL vram, const MENURES2 *res, RESPUT *rp, - UINT mvc) { - - int width; -const UINT8 *p; - UINT8 *q; - int cnt; - int step; - int bit; - int pix; - int c; - UINT16 dat; - - dat = menucolor16[mvc]; - p = res->pat; - q = vram->ptr + rp->pos; - step = vram->yalign - (rp->width * 2); - cnt = rp->step; - width = rp->width; - pix = 0; - bit = 0; - while(1) { - while(cnt <= 0) { - pix ^= 1; - c = ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - if (c & 8) { - c -= 8; - c <<= 4; - c |= ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - } - cnt += c; - } - c = MIN(cnt, width); - cnt -= c; - width -= c; - if (!pix) { - do { - *(UINT16 *)q = (UINT16)dat; - q += 2; - } while(--c); - } - else { - q += c * 2; - } - if (!width) { - rp->height--; - if (!rp->height) { - break; - } - width = rp->width; - cnt += rp->linedel; - q += step; - } - } -} - -static void captionbar16(VRAMHDL vram, const RECT_T *rect, - UINT32 color1, UINT32 color2) { - - RECT_T rct; - int width; - int height; - int i; - int x; - int y; - int col[3]; - int step[3]; - int dir[3]; - int tmp; - int sft; - UINT8 *p; - UINT8 *q; -const UINT8 *r; - UINT pat[4]; - int cur; - UINT8 mask; - int c; - - if (vram_cliprect(&rct, vram, rect) != SUCCESS) { - goto mvcb_end; - } - width = rct.right - rct.left; - height = rct.bottom - rct.top; - i = 0; - do { - sft = (i << 3) + 4; - col[i] = ((color1 >> sft) & 0xf); - tmp = ((color2 >> sft) & 0xf) - col[i]; - if (tmp == 0) { - dir[i] = 0; - step[i] = 0; - } - else { - if (tmp > 0) { - dir[i] = 1; - } - else { - dir[i] = -1; - tmp = 0 - tmp; - } - tmp <<= 4; // x16 - tmp <<= 16; - step[i] = tmp / width; - } - } while(++i < 3); - p = vram->ptr; - p += rct.left * vram->xalign; - p += rct.top * vram->yalign; - x = 0; - do { - q = p; - p += 2; - y = 0; - do { - pat[y] = 0; - } while(++y < 4); - mask = 0x80 >> (x & 7); - i = 0; - do { - cur = (x * step[i]) >> 16; - r = __pat + ((cur & 15) << 2); - cur >>= 4; - cur *= dir[i]; - cur += col[i]; - y = 0; - do { - c = cur; - if (r[y] & mask) { - c += dir[i]; - } - pat[y] |= (c << __rsft[i]); - } while(++y < 4); - } while(++i < 3); - y = 0; - do { - q[0] = (UINT8)pat[y & 3]; - q[1] = (UINT8)(pat[y & 3] >> 8); - q += vram->yalign; - } while(++y < height); - } while(++x < width); - -mvcb_end: - return; -} - -#endif - -#ifdef SUPPORT_24BPP - -static void res2put24(VRAMHDL vram, const MENURES2 *res, RESPUT *rp) { - - int width; -const UINT8 *p; - UINT8 *q; - int cnt; - int step; - int bit; - int pix; - int c; - UINT32 dat; - - p = res->pat; - q = vram->ptr + rp->pos; - step = vram->yalign - (rp->width * 3); - cnt = rp->step; - width = rp->width; - bit = 0; - pix = 0; - while(1) { - while(cnt <= 0) { - cnt++; - pix = ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - if (pix >= 7) { - cnt += (pix - 7) + 2; - pix = ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - } - } - c = MIN(cnt, width); - cnt -= c; - width -= c; - if (pix) { - dat = menucolor[pix - 1]; - do { - *q++ = (UINT8)dat; - *q++ = (UINT8)(dat >> 8); - *q++ = (UINT8)(dat >> 16); - } while(--c); - } - else { - q += c * 3; - } - if (!width) { - rp->height--; - if (!rp->height) { - break; - } - width = rp->width; - cnt += rp->linedel; - q += step; - } - } -} - -static void res3put24(VRAMHDL vram, const MENURES2 *res, RESPUT *rp, - UINT mvc) { - - int width; -const UINT8 *p; - UINT8 *q; - int cnt; - int step; - int bit; - int pix; - int c; - UINT32 dat; - - dat = menucolor[mvc]; - p = res->pat; - q = vram->ptr + rp->pos; - step = vram->yalign - (rp->width * 3); - cnt = rp->step; - width = rp->width; - pix = 0; - bit = 0; - while(1) { - while(cnt <= 0) { - pix ^= 1; - c = ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - if (c & 8) { - c -= 8; - c <<= 4; - c |= ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - } - cnt += c; - } - c = MIN(cnt, width); - cnt -= c; - width -= c; - if (!pix) { - do { - *q++ = (UINT8)dat; - *q++ = (UINT8)(dat >> 8); - *q++ = (UINT8)(dat >> 16); - } while(--c); - } - else { - q += c * 3; - } - if (!width) { - rp->height--; - if (!rp->height) { - break; - } - width = rp->width; - cnt += rp->linedel; - q += step; - } - } -} - -static void captionbar24(VRAMHDL vram, const RECT_T *rect, - UINT32 color1, UINT32 color2) { - - RECT_T rct; - int width; - int height; - int i; - int x; - int y; - int col[3]; - int step[3]; - int dir[3]; - int tmp; - int sft; - UINT8 *p; - UINT8 *q; -const UINT8 *r; - UINT8 pat[3][4]; - int cur; - UINT8 mask; - int c; - - if (vram_cliprect(&rct, vram, rect) != SUCCESS) { - goto mvcb_end; - } - width = rct.right - rct.left; - height = rct.bottom - rct.top; - i = 0; - do { - sft = (i << 3) + 4; - col[i] = ((color1 >> sft) & 0xf); - tmp = ((color2 >> sft) & 0xf) - col[i]; - if (tmp == 0) { - dir[i] = 0; - step[i] = 0; - } - else { - if (tmp > 0) { - dir[i] = 1; - } - else { - dir[i] = -1; - tmp = 0 - tmp; - } - tmp <<= 4; // x16 - tmp <<= 16; - step[i] = tmp / width; - } - } while(++i < 3); - p = vram->ptr; - p += rct.left * vram->xalign; - p += rct.top * vram->yalign; - x = 0; - do { - q = p; - p += 3; - mask = 0x80 >> (x & 7); - i = 0; - do { - cur = (x * step[i]) >> 16; - r = __pat + ((cur & 15) << 2); - cur >>= 4; - cur *= dir[i]; - cur += col[i]; - y = 0; - do { - c = cur; - if (r[y] & mask) { - c += dir[i]; - } - pat[i][y] = (UINT8)((c << 4) | c); - } while(++y < 4); - } while(++i < 3); - y = 0; - do { - q[0] = pat[0][y & 3]; - q[1] = pat[1][y & 3]; - q[2] = pat[2][y & 3]; - q += vram->yalign; - } while(++y < height); - } while(++x < width); - -mvcb_end: - return; -} - -#endif - -#ifdef SUPPORT_32BPP - -static void res2put32(VRAMHDL vram, const MENURES2 *res, RESPUT *rp) { - - int width; -const UINT8 *p; - UINT8 *q; - int cnt; - int step; - int bit; - int pix; - int c; - UINT32 dat; - - p = res->pat; - q = vram->ptr + rp->pos; - step = vram->yalign - (rp->width * 4); - cnt = rp->step; - width = rp->width; - bit = 0; - pix = 0; - while(1) { - while(cnt <= 0) { - cnt++; - pix = ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - if (pix >= 7) { - cnt += (pix - 7) + 2; - pix = ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - } - } - c = MIN(cnt, width); - cnt -= c; - width -= c; - if (pix) { - dat = menucolor[pix - 1]; - do { - *q++ = (UINT8)dat; - *q++ = (UINT8)(dat >> 8); - *q++ = (UINT8)(dat >> 16); - q++; - } while(--c); - } - else { - q += c * 4; - } - if (!width) { - rp->height--; - if (!rp->height) { - - break; - } - width = rp->width; - cnt += rp->linedel; - q += step; - } - } -} - -static void res3put32(VRAMHDL vram, const MENURES2 *res, RESPUT *rp, - UINT mvc) { - - int width; -const UINT8 *p; - UINT8 *q; - int cnt; - int step; - int bit; - int pix; - int c; - UINT32 dat; - - dat = menucolor[mvc]; - p = res->pat; - q = vram->ptr + rp->pos; - step = vram->yalign - (rp->width * 4); - cnt = rp->step; - width = rp->width; - pix = 0; - bit = 0; - while(1) { - while(cnt <= 0) { - pix ^= 1; - c = ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - if (c & 8) { - c -= 8; - c <<= 4; - c |= ((*p) >> bit) & 0x0f; - bit ^= 4; - if (!bit) { - p++; - } - } - cnt += c; - } - c = MIN(cnt, width); - cnt -= c; - width -= c; - if (!pix) { - do { - *q++ = (UINT8)dat; - *q++ = (UINT8)(dat >> 8); - *q++ = (UINT8)(dat >> 16); - q++; - } while(--c); - } - else { - q += c * 4; - } - if (!width) { - rp->height--; - if (!rp->height) { - break; - } - width = rp->width; - cnt += rp->linedel; - q += step; - } - } -} - -static void captionbar32(VRAMHDL vram, const RECT_T *rect, - UINT32 color1, UINT32 color2) { - - RECT_T rct; - int width; - int height; - int i; - int x; - int y; - int col[3]; - int step[3]; - int dir[3]; - int tmp; - int sft; - UINT8 *p; - UINT8 *q; -const UINT8 *r; - UINT8 pat[3][4]; - int cur; - UINT8 mask; - int c; - - if (vram_cliprect(&rct, vram, rect) != SUCCESS) { - goto mvcb_end; - } - width = rct.right - rct.left; - height = rct.bottom - rct.top; - i = 0; - do { - sft = (i << 3) + 4; - col[i] = ((color1 >> sft) & 0xf); - tmp = ((color2 >> sft) & 0xf) - col[i]; - if (tmp == 0) { - dir[i] = 0; - step[i] = 0; - } - else { - if (tmp > 0) { - dir[i] = 1; - } - else { - dir[i] = -1; - tmp = 0 - tmp; - } - tmp <<= 4; // x16 - tmp <<= 16; - step[i] = tmp / width; - } - } while(++i < 3); - p = vram->ptr; - p += rct.left * vram->xalign; - p += rct.top * vram->yalign; - x = 0; - do { - q = p; - p += 4; - mask = 0x80 >> (x & 7); - i = 0; - do { - cur = (x * step[i]) >> 16; - r = __pat + ((cur & 15) << 2); - cur >>= 4; - cur *= dir[i]; - cur += col[i]; - y = 0; - do { - c = cur; - if (r[y] & mask) { - c += dir[i]; - } - pat[i][y] = (UINT8)((c << 4) | c); - } while(++y < 4); - } while(++i < 3); - y = 0; - do { - q[0] = pat[0][y & 3]; - q[1] = pat[1][y & 3]; - q[2] = pat[2][y & 3]; - q += vram->yalign; - } while(++y < height); - } while(++x < width); - -mvcb_end: - return; -} - -#endif - -// ---- - -static void vramlzxsolve(UINT8 *ptr, int size, const UINT8 *dat) { - - int level; - UINT8 ctrl; - UINT8 bit; - UINT mask; - UINT tmp; - int pos; - int leng; - - ctrl = 0; - bit = 0; - level = *dat++; - mask = (1 << level) - 1; - while(size) { - if (!bit) { - ctrl = *dat++; - bit = 0x80; - } - if (ctrl & bit) { - tmp = *dat++; - tmp <<= 8; - tmp |= *dat++; - pos = -1 - (tmp >> level); - leng = (tmp & mask) + 1; - leng = MIN(leng, size); - size -= leng; - while(leng--) { - *ptr = *(ptr + pos); - ptr++; - } - } - else { - *ptr++ = *dat++; - size--; - } - bit >>= 1; - } -} - - -// ---- - -VRAMHDL menuvram_resload(const MENURES *res, int bpp) { - - VRAMHDL ret; - int size; - BOOL alpha; - - alpha = (res->alpha)?TRUE:FALSE; - ret = vram_create(res->width, res->height, alpha, bpp); - if (ret == NULL) { - goto mvrl_err; - } - size = res->width * res->height; - vramlzxsolve(ret->ptr, size * ret->xalign, res->data); - if (alpha) { - vramlzxsolve(ret->alpha, size, res->alpha); - } - -mvrl_err: - return(ret); -} - - -void menuvram_res2put(VRAMHDL vram, const MENURES2 *res, const POINT_T *pt) { - - RESPUT rp; - - if (resputprepare(vram, res, pt, &rp) != SUCCESS) { - goto mvr2_end; - } - switch(vram->bpp) { -#ifdef SUPPORT_16BPP - case 16: - res2put16(vram, res, &rp); - break; -#endif -#ifdef SUPPORT_24BPP - case 24: - res2put24(vram, res, &rp); - break; -#endif -#ifdef SUPPORT_32BPP - case 32: - res2put32(vram, res, &rp); - break; -#endif - default: - TRACEOUT(("menuvram_res2put: unspport %dbpp", vram->bpp)); - break; - } - -mvr2_end: - return; -} - - -void menuvram_res3put(VRAMHDL vram, const MENURES2 *res, const POINT_T *pt, - UINT mvc) { - - RESPUT rp; - - if (resputprepare(vram, res, pt, &rp) != SUCCESS) { - goto mvr3_end; - } - switch(vram->bpp) { -#ifdef SUPPORT_16BPP - case 16: - res3put16(vram, res, &rp, mvc); - break; -#endif -#ifdef SUPPORT_24BPP - case 24: - res3put24(vram, res, &rp, mvc); - break; -#endif -#ifdef SUPPORT_32BPP - case 32: - res3put32(vram, res, &rp, mvc); - break; -#endif - default: - TRACEOUT(("menuvram_res3put: unspport %dbpp", vram->bpp)); - break; - } - -mvr3_end: - return; -} - - -// ---- - -void menuvram_linex(VRAMHDL vram, int posx, int posy, int term, UINT mvc) { - - UINT8 *p; - - if ((vram == NULL) || - (posy < 0) || (posy >= vram->height)) { - goto mvlx_end; - } - if (posx < 0) { - posx = 0; - } - if (term >= vram->width) { - term = vram->width; - } - p = vram->ptr; - p += posy * vram->yalign; - p += posx * vram->xalign; - -#ifdef SUPPORT_16BPP - if (vram->bpp == 16) { - UINT16 color; - color = menucolor16[mvc]; - while(posx < term) { - posx++; - *(UINT16 *)p = (UINT16)color; - p += 2; - } - } -#endif -#ifdef SUPPORT_24BPP - if (vram->bpp == 24) { - UINT32 color; - UINT8 col[3]; - color = menucolor[mvc]; - col[0] = (UINT8)color; - col[1] = (UINT8)(color >> 8); - col[2] = (UINT8)(color >> 16); - while(posx < term) { - posx++; - p[0] = col[0]; - p[1] = col[1]; - p[2] = col[2]; - p += 3; - } - } -#endif -#ifdef SUPPORT_32BPP - if (vram->bpp == 32) { - UINT32 color; - UINT8 col[3]; - color = menucolor[mvc]; - col[0] = (UINT8)color; - col[1] = (UINT8)(color >> 8); - col[2] = (UINT8)(color >> 16); - while(posx < term) { - posx++; - p[0] = col[0]; - p[1] = col[1]; - p[2] = col[2]; - p += 4; - } - } -#endif - -mvlx_end: - return; -} - - -void menuvram_liney(VRAMHDL vram, int posx, int posy, int term, UINT mvc) { - - UINT8 *p; - - if ((vram == NULL) || - (posx < 0) || (posx >= vram->width)) { - goto mvly_end; - } - if (posy < 0) { - posy = 0; - } - if (term >= vram->height) { - term = vram->height; - } - p = vram->ptr; - p += posy * vram->yalign; - p += posx * vram->xalign; - -#ifdef SUPPORT_16BPP - if (vram->bpp == 16) { - UINT16 color; - color = menucolor16[mvc]; - while(posy < term) { - posy++; - *(UINT16 *)p = (UINT16)color; - p += vram->yalign; - } - } -#endif -#ifdef SUPPORT_24BPP - if (vram->bpp == 24) { - UINT32 color; - UINT8 col[3]; - color = menucolor[mvc]; - col[0] = (UINT8)color; - col[1] = (UINT8)(color >> 8); - col[2] = (UINT8)(color >> 16); - while(posy < term) { - posy++; - p[0] = col[0]; - p[1] = col[1]; - p[2] = col[2]; - p += vram->yalign; - } - } -#endif -#ifdef SUPPORT_32BPP - if (vram->bpp == 32) { - UINT32 color; - UINT8 col[3]; - color = menucolor[mvc]; - col[0] = (UINT8)color; - col[1] = (UINT8)(color >> 8); - col[2] = (UINT8)(color >> 16); - while(posy < term) { - posy++; - p[0] = col[0]; - p[1] = col[1]; - p[2] = col[2]; - p += vram->yalign; - } - } -#endif - -mvly_end: - return; -} - - -void menuvram_box(VRAMHDL vram, const RECT_T *rect, UINT mvc2, int reverse) { - - UINT c1; - UINT c2; - - if (rect == NULL) { - goto mvb_exit; - } - - if (!reverse) { - c1 = mvc2 & 0x0f; - c2 = (mvc2 >> 4) & 0x0f; - } - else { - c1 = (mvc2 >> 4) & 0x0f; - c2 = mvc2 & 0x0f; - } - menuvram_linex(vram, rect->left+0, rect->top+0, rect->right-1, c1); - menuvram_liney(vram, rect->left+0, rect->top+1, rect->bottom-1, c1); - menuvram_linex(vram, rect->left+0, rect->bottom-1, rect->right-1, c2); - menuvram_liney(vram, rect->right-1, rect->top+0, rect->bottom-0, c2); - -mvb_exit: - return; -} - - -void menuvram_box2(VRAMHDL vram, const RECT_T *rect, UINT mvc4) { - - UINT col; - - if (rect == NULL) { - goto mvb2_exit; - } - - col = mvc4 & 0x0f; - menuvram_linex(vram, rect->left+0, rect->top+0, rect->right-1, col); - menuvram_liney(vram, rect->left+0, rect->top+1, rect->bottom-1, col); - - col = (mvc4 >> 4) & 0x0f; - menuvram_linex(vram, rect->left+0, rect->bottom-1, rect->right-1, col); - menuvram_liney(vram, rect->right-1, rect->top+0, rect->bottom-0, col); - - col = (mvc4 >> 8) & 0x0f; - menuvram_linex(vram, rect->left+1, rect->top+1, rect->right-2, col); - menuvram_liney(vram, rect->left+1, rect->top+2, rect->bottom-2, col); - - col = (mvc4 >> 12) & 0x0f; - menuvram_linex(vram, rect->left+1, rect->bottom-2, rect->right-2, col); - menuvram_liney(vram, rect->right-2, rect->top+1, rect->bottom-1, col); - -mvb2_exit: - return; -} - - -void menuvram_base(VRAMHDL vram) { - - RECT_T rct; - - vram_filldat(vram, NULL, menucolor[MVC_STATIC]); - rct.left = 0; - rct.top = 0; - rct.right = vram->width; - rct.bottom = vram->height; - menuvram_box2(vram, &rct, - MVC4(MVC_LIGHT, MVC_DARK, MVC_HILIGHT, MVC_SHADOW)); -} - - -VRAMHDL menuvram_create(int width, int height, UINT bpp) { - - VRAMHDL ret; - - ret = vram_create(width, height, FALSE, bpp); - if (ret == NULL) { - goto mvcre_err; - } - menuvram_base(ret); - -mvcre_err: - return(ret); -} - -void menuvram_caption(VRAMHDL vram, const RECT_T *rect, - UINT16 icon, const OEMCHAR *caption) { - - POINT_T pt; - VRAMHDL work; - - if ((vram == NULL) || (rect == NULL)) { - goto mvpt_exit; - } - -#ifdef SUPPORT_16BPP - if (vram->bpp == 16) { - captionbar16(vram, rect, 0x000080, 0x000000); - } -#endif -#ifdef SUPPORT_24BPP - if (vram->bpp == 24) { - captionbar24(vram, rect, 0x000080, 0x000000); - } -#endif -#ifdef SUPPORT_32BPP - if (vram->bpp == 32) { - captionbar32(vram, rect, 0x000080, 0x000000); - } -#endif - pt.x = rect->left + MENU_PXCAPTION; - if (icon) { - pt.y = rect->top + MENU_PYCAPTION; - work = menuicon_lock(icon, MENUSYS_SZICON, MENUSYS_SZICON, vram->bpp); - if (work) { - if (work->alpha) { - vramcpy_cpyex(vram, &pt, work, NULL); - } - else { - vramcpy_cpy(vram, &pt, work, NULL); - } - menuicon_unlock(work); - } - pt.x += MENUSYS_SZICON + MENU_PXCAPTION; - } - pt.y = rect->top + (rect->bottom - rect->top - MENU_FONTSIZE) / 2; - vrammix_text(vram, menubase.font, caption, 0xffffff, &pt, rect); - -mvpt_exit: - return; -} - - -static void putbtn(VRAMHDL vram, const RECT_T *rect, - const MENURES2 *res, BOOL focus) { - RECT_T rct; - POINT_T pt; - UINT mvc4; - - if (rect) { - rct = *rect; - } - else { - vram_getrect(vram, &rct); - } - - if (!focus) { - mvc4 = MVC4(MVC_LIGHT, MVC_DARK, MVC_HILIGHT, MVC_SHADOW); - } - else { - mvc4 = MVC4(MVC_DARK, MVC_LIGHT, MVC_SHADOW, MVC_HILIGHT); - } - menuvram_box2(vram, &rct, mvc4); - rct.left += MENU_LINE * 2; - rct.top += MENU_LINE * 2; - rct.right -= MENU_LINE * 2; - rct.bottom -= MENU_LINE * 2; - vram_filldat(vram, &rct, menucolor[MVC_BTNFACE]); - pt.x = rct.left; - pt.y = rct.top; - if (focus) { - pt.x += MENU_LINE; - pt.y += MENU_LINE; - } - menuvram_res3put(vram, res, &pt, MVC_TEXT); -} - -void menuvram_minimizebtn(VRAMHDL vram, const RECT_T *rect, BOOL focus) { - - putbtn(vram, rect, &menures_minimize, focus); -} - -void menuvram_closebtn(VRAMHDL vram, const RECT_T *rect, BOOL focus) { - - putbtn(vram, rect, &menures_close, focus); -} - +#include +#include +#include +#include "menudeco.inc" +#include + + +UINT32 menucolor[] = { + 0xffffff, // MVC_BACK + 0xffffff, // MVC_HILIGHT + 0xc0c0c0, // MVC_LIGHT + 0x808080, // MVC_SHADOW + 0x000000, // MVC_DARK + 0xe0e0e0, // MVC_SCROLLBAR + + 0xc0c0c0, // MVC_STATIC + 0x000000, // MVC_TEXT + 0x808080, // MVC_GRAYTEXT1 + 0xffffff, // MVC_GRAYTEXT2 + 0xc0c0c0, // MVC_BTNFACE + 0xffffff, // MVC_CURTEXT + 0x000080, // MVC_CURBACK +}; + + +static const UINT8 __pat[64] = { + 0x00, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x44, 0x00, + 0x55, 0x00, 0x44, 0x00, + 0x55, 0x00, 0x55, 0x00, + 0x55, 0x22, 0x55, 0x00, + 0x55, 0x22, 0x55, 0x88, + 0x55, 0xaa, 0x55, 0x88, + 0x55, 0xaa, 0x55, 0xaa, + 0x77, 0xaa, 0x55, 0xaa, + 0x77, 0xaa, 0xdd, 0xaa, + 0xff, 0xaa, 0xdd, 0xaa, + 0xff, 0xaa, 0xff, 0xaa, + 0xff, 0xbb, 0xff, 0xaa, + 0xff, 0xbb, 0xff, 0xee, + 0xff, 0xff, 0xff, 0xee}; + + +typedef struct { + int width; + int height; + int pos; + int step; + int linedel; +} RESPUT; + +static BRESULT resputprepare(VRAMHDL vram, const MENURES2 *res, + const POINT_T *pt, RESPUT *rp) { + + int width; + int height; + int step; + int pos; + + if ((vram == NULL) || (res == NULL)) { + goto rpp_err; + } + width = res->width; + height = res->height; + step = 0; + pos = pt->x; + if (pos < 0) { + width += pos; + step += pos; + pos = 0; + } + rp->pos = (pos * vram->xalign); + pos = vram->width - pos; + if (width > pos) { + width = pos; + } + if (width <= 0) { + goto rpp_err; + } + rp->width = width; + + pos = pt->y; + if (pos < 0) { + height += pos; + step += pos * res->width; + pos = 0; + } + rp->pos += (pos * vram->yalign); + pos = vram->height - pos; + if (height > pos) { + height = pos; + } + if (height <= 0) { + goto rpp_err; + } + rp->height = height; + rp->step = step; + rp->linedel = width - res->width; + return(SUCCESS); + +rpp_err: + return(FAILURE); +} + + +#ifdef SUPPORT_16BPP + +static const UINT16 menucolor16[] = { + MAKE16PAL(0xffffff), // MVC_BACK + MAKE16PAL(0xffffff), // MVC_HILIGHT + MAKE16PAL(0xc0c0c0), // MVC_LIGHT + MAKE16PAL(0x808080), // MVC_SHADOW + MAKE16PAL(0x000000), // MVC_DARK + MAKE16PAL(0xe0e0e0), // MVC_SCROLLBAR + + MAKE16PAL(0xc0c0c0), // MVC_STATIC + MAKE16PAL(0x000000), // MVC_TEXT + MAKE16PAL(0x808080), // MVC_GRAYTEXT1 + MAKE16PAL(0xffffff), // MVC_GRAYTEXT2 + MAKE16PAL(0xc0c0c0), // MVC_BTNFACE + MAKE16PAL(0xffffff), // MVC_CURTEXT + MAKE16PAL(0x000080), // MVC_CURBACK +}; + +static const int __rsft[] = {1, 7, 12}; + +static void res2put16(VRAMHDL vram, const MENURES2 *res, RESPUT *rp) { + + int width; +const UINT8 *p; + UINT8 *q; + int cnt; + int step; + int bit; + int pix = 0; // for cygwin + int c; + UINT16 dat; + + p = res->pat; + q = vram->ptr + rp->pos; + step = vram->yalign - (rp->width * 2); + cnt = rp->step; + width = rp->width; + bit = 0; + while(1) { + while(cnt <= 0) { + cnt++; + pix = ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + if (pix >= 7) { + cnt += (pix - 7) + 2; + pix = ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + } + } + c = MIN(cnt, width); + cnt -= c; + width -= c; + if (pix) { + dat = menucolor16[pix - 1]; + do { + *(UINT16 *)q = (UINT16)dat; + q += 2; + } while(--c); + } + else { + q += c * 2; + } + if (!width) { + rp->height--; + if (!rp->height) { + break; + } + width = rp->width; + cnt += rp->linedel; + q += step; + } + } +} + +static void res3put16(VRAMHDL vram, const MENURES2 *res, RESPUT *rp, + UINT mvc) { + + int width; +const UINT8 *p; + UINT8 *q; + int cnt; + int step; + int bit; + int pix; + int c; + UINT16 dat; + + dat = menucolor16[mvc]; + p = res->pat; + q = vram->ptr + rp->pos; + step = vram->yalign - (rp->width * 2); + cnt = rp->step; + width = rp->width; + pix = 0; + bit = 0; + while(1) { + while(cnt <= 0) { + pix ^= 1; + c = ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + if (c & 8) { + c -= 8; + c <<= 4; + c |= ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + } + cnt += c; + } + c = MIN(cnt, width); + cnt -= c; + width -= c; + if (!pix) { + do { + *(UINT16 *)q = (UINT16)dat; + q += 2; + } while(--c); + } + else { + q += c * 2; + } + if (!width) { + rp->height--; + if (!rp->height) { + break; + } + width = rp->width; + cnt += rp->linedel; + q += step; + } + } +} + +static void captionbar16(VRAMHDL vram, const RECT_T *rect, + UINT32 color1, UINT32 color2) { + + RECT_T rct; + int width; + int height; + int i; + int x; + int y; + int col[3]; + int step[3]; + int dir[3]; + int tmp; + int sft; + UINT8 *p; + UINT8 *q; +const UINT8 *r; + UINT pat[4]; + int cur; + UINT8 mask; + int c; + + if (vram_cliprect(&rct, vram, rect) != SUCCESS) { + goto mvcb_end; + } + width = rct.right - rct.left; + height = rct.bottom - rct.top; + i = 0; + do { + sft = (i << 3) + 4; + col[i] = ((color1 >> sft) & 0xf); + tmp = ((color2 >> sft) & 0xf) - col[i]; + if (tmp == 0) { + dir[i] = 0; + step[i] = 0; + } + else { + if (tmp > 0) { + dir[i] = 1; + } + else { + dir[i] = -1; + tmp = 0 - tmp; + } + tmp <<= 4; // x16 + tmp <<= 16; + step[i] = tmp / width; + } + } while(++i < 3); + p = vram->ptr; + p += rct.left * vram->xalign; + p += rct.top * vram->yalign; + x = 0; + do { + q = p; + p += 2; + y = 0; + do { + pat[y] = 0; + } while(++y < 4); + mask = 0x80 >> (x & 7); + i = 0; + do { + cur = (x * step[i]) >> 16; + r = __pat + ((cur & 15) << 2); + cur >>= 4; + cur *= dir[i]; + cur += col[i]; + y = 0; + do { + c = cur; + if (r[y] & mask) { + c += dir[i]; + } + pat[y] |= (c << __rsft[i]); + } while(++y < 4); + } while(++i < 3); + y = 0; + do { + q[0] = (UINT8)pat[y & 3]; + q[1] = (UINT8)(pat[y & 3] >> 8); + q += vram->yalign; + } while(++y < height); + } while(++x < width); + +mvcb_end: + return; +} + +#endif + +#ifdef SUPPORT_24BPP + +static void res2put24(VRAMHDL vram, const MENURES2 *res, RESPUT *rp) { + + int width; +const UINT8 *p; + UINT8 *q; + int cnt; + int step; + int bit; + int pix; + int c; + UINT32 dat; + + p = res->pat; + q = vram->ptr + rp->pos; + step = vram->yalign - (rp->width * 3); + cnt = rp->step; + width = rp->width; + bit = 0; + pix = 0; + while(1) { + while(cnt <= 0) { + cnt++; + pix = ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + if (pix >= 7) { + cnt += (pix - 7) + 2; + pix = ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + } + } + c = MIN(cnt, width); + cnt -= c; + width -= c; + if (pix) { + dat = menucolor[pix - 1]; + do { + *q++ = (UINT8)dat; + *q++ = (UINT8)(dat >> 8); + *q++ = (UINT8)(dat >> 16); + } while(--c); + } + else { + q += c * 3; + } + if (!width) { + rp->height--; + if (!rp->height) { + break; + } + width = rp->width; + cnt += rp->linedel; + q += step; + } + } +} + +static void res3put24(VRAMHDL vram, const MENURES2 *res, RESPUT *rp, + UINT mvc) { + + int width; +const UINT8 *p; + UINT8 *q; + int cnt; + int step; + int bit; + int pix; + int c; + UINT32 dat; + + dat = menucolor[mvc]; + p = res->pat; + q = vram->ptr + rp->pos; + step = vram->yalign - (rp->width * 3); + cnt = rp->step; + width = rp->width; + pix = 0; + bit = 0; + while(1) { + while(cnt <= 0) { + pix ^= 1; + c = ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + if (c & 8) { + c -= 8; + c <<= 4; + c |= ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + } + cnt += c; + } + c = MIN(cnt, width); + cnt -= c; + width -= c; + if (!pix) { + do { + *q++ = (UINT8)dat; + *q++ = (UINT8)(dat >> 8); + *q++ = (UINT8)(dat >> 16); + } while(--c); + } + else { + q += c * 3; + } + if (!width) { + rp->height--; + if (!rp->height) { + break; + } + width = rp->width; + cnt += rp->linedel; + q += step; + } + } +} + +static void captionbar24(VRAMHDL vram, const RECT_T *rect, + UINT32 color1, UINT32 color2) { + + RECT_T rct; + int width; + int height; + int i; + int x; + int y; + int col[3]; + int step[3]; + int dir[3]; + int tmp; + int sft; + UINT8 *p; + UINT8 *q; +const UINT8 *r; + UINT8 pat[3][4]; + int cur; + UINT8 mask; + int c; + + if (vram_cliprect(&rct, vram, rect) != SUCCESS) { + goto mvcb_end; + } + width = rct.right - rct.left; + height = rct.bottom - rct.top; + i = 0; + do { + sft = (i << 3) + 4; + col[i] = ((color1 >> sft) & 0xf); + tmp = ((color2 >> sft) & 0xf) - col[i]; + if (tmp == 0) { + dir[i] = 0; + step[i] = 0; + } + else { + if (tmp > 0) { + dir[i] = 1; + } + else { + dir[i] = -1; + tmp = 0 - tmp; + } + tmp <<= 4; // x16 + tmp <<= 16; + step[i] = tmp / width; + } + } while(++i < 3); + p = vram->ptr; + p += rct.left * vram->xalign; + p += rct.top * vram->yalign; + x = 0; + do { + q = p; + p += 3; + mask = 0x80 >> (x & 7); + i = 0; + do { + cur = (x * step[i]) >> 16; + r = __pat + ((cur & 15) << 2); + cur >>= 4; + cur *= dir[i]; + cur += col[i]; + y = 0; + do { + c = cur; + if (r[y] & mask) { + c += dir[i]; + } + pat[i][y] = (UINT8)((c << 4) | c); + } while(++y < 4); + } while(++i < 3); + y = 0; + do { + q[0] = pat[0][y & 3]; + q[1] = pat[1][y & 3]; + q[2] = pat[2][y & 3]; + q += vram->yalign; + } while(++y < height); + } while(++x < width); + +mvcb_end: + return; +} + +#endif + +#ifdef SUPPORT_32BPP + +static void res2put32(VRAMHDL vram, const MENURES2 *res, RESPUT *rp) { + + int width; +const UINT8 *p; + UINT8 *q; + int cnt; + int step; + int bit; + int pix; + int c; + UINT32 dat; + + p = res->pat; + q = vram->ptr + rp->pos; + step = vram->yalign - (rp->width * 4); + cnt = rp->step; + width = rp->width; + bit = 0; + pix = 0; + while(1) { + while(cnt <= 0) { + cnt++; + pix = ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + if (pix >= 7) { + cnt += (pix - 7) + 2; + pix = ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + } + } + c = MIN(cnt, width); + cnt -= c; + width -= c; + if (pix) { + dat = menucolor[pix - 1]; + do { + *q++ = (UINT8)dat; + *q++ = (UINT8)(dat >> 8); + *q++ = (UINT8)(dat >> 16); + q++; + } while(--c); + } + else { + q += c * 4; + } + if (!width) { + rp->height--; + if (!rp->height) { + + break; + } + width = rp->width; + cnt += rp->linedel; + q += step; + } + } +} + +static void res3put32(VRAMHDL vram, const MENURES2 *res, RESPUT *rp, + UINT mvc) { + + int width; +const UINT8 *p; + UINT8 *q; + int cnt; + int step; + int bit; + int pix; + int c; + UINT32 dat; + + dat = menucolor[mvc]; + p = res->pat; + q = vram->ptr + rp->pos; + step = vram->yalign - (rp->width * 4); + cnt = rp->step; + width = rp->width; + pix = 0; + bit = 0; + while(1) { + while(cnt <= 0) { + pix ^= 1; + c = ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + if (c & 8) { + c -= 8; + c <<= 4; + c |= ((*p) >> bit) & 0x0f; + bit ^= 4; + if (!bit) { + p++; + } + } + cnt += c; + } + c = MIN(cnt, width); + cnt -= c; + width -= c; + if (!pix) { + do { + *q++ = (UINT8)dat; + *q++ = (UINT8)(dat >> 8); + *q++ = (UINT8)(dat >> 16); + q++; + } while(--c); + } + else { + q += c * 4; + } + if (!width) { + rp->height--; + if (!rp->height) { + break; + } + width = rp->width; + cnt += rp->linedel; + q += step; + } + } +} + +static void captionbar32(VRAMHDL vram, const RECT_T *rect, + UINT32 color1, UINT32 color2) { + + RECT_T rct; + int width; + int height; + int i; + int x; + int y; + int col[3]; + int step[3]; + int dir[3]; + int tmp; + int sft; + UINT8 *p; + UINT8 *q; +const UINT8 *r; + UINT8 pat[3][4]; + int cur; + UINT8 mask; + int c; + + if (vram_cliprect(&rct, vram, rect) != SUCCESS) { + goto mvcb_end; + } + width = rct.right - rct.left; + height = rct.bottom - rct.top; + i = 0; + do { + sft = (i << 3) + 4; + col[i] = ((color1 >> sft) & 0xf); + tmp = ((color2 >> sft) & 0xf) - col[i]; + if (tmp == 0) { + dir[i] = 0; + step[i] = 0; + } + else { + if (tmp > 0) { + dir[i] = 1; + } + else { + dir[i] = -1; + tmp = 0 - tmp; + } + tmp <<= 4; // x16 + tmp <<= 16; + step[i] = tmp / width; + } + } while(++i < 3); + p = vram->ptr; + p += rct.left * vram->xalign; + p += rct.top * vram->yalign; + x = 0; + do { + q = p; + p += 4; + mask = 0x80 >> (x & 7); + i = 0; + do { + cur = (x * step[i]) >> 16; + r = __pat + ((cur & 15) << 2); + cur >>= 4; + cur *= dir[i]; + cur += col[i]; + y = 0; + do { + c = cur; + if (r[y] & mask) { + c += dir[i]; + } + pat[i][y] = (UINT8)((c << 4) | c); + } while(++y < 4); + } while(++i < 3); + y = 0; + do { + q[0] = pat[0][y & 3]; + q[1] = pat[1][y & 3]; + q[2] = pat[2][y & 3]; + q += vram->yalign; + } while(++y < height); + } while(++x < width); + +mvcb_end: + return; +} + +#endif + +// ---- + +static void vramlzxsolve(UINT8 *ptr, int size, const UINT8 *dat) { + + int level; + UINT8 ctrl; + UINT8 bit; + UINT mask; + UINT tmp; + int pos; + int leng; + + ctrl = 0; + bit = 0; + level = *dat++; + mask = (1 << level) - 1; + while(size) { + if (!bit) { + ctrl = *dat++; + bit = 0x80; + } + if (ctrl & bit) { + tmp = *dat++; + tmp <<= 8; + tmp |= *dat++; + pos = -1 - (tmp >> level); + leng = (tmp & mask) + 1; + leng = MIN(leng, size); + size -= leng; + while(leng--) { + *ptr = *(ptr + pos); + ptr++; + } + } + else { + *ptr++ = *dat++; + size--; + } + bit >>= 1; + } +} + + +// ---- + +VRAMHDL menuvram_resload(const MENURES *res, int bpp) { + + VRAMHDL ret; + int size; + BOOL alpha; + + alpha = (res->alpha)?TRUE:FALSE; + ret = vram_create(res->width, res->height, alpha, bpp); + if (ret == NULL) { + goto mvrl_err; + } + size = res->width * res->height; + vramlzxsolve(ret->ptr, size * ret->xalign, res->data); + if (alpha) { + vramlzxsolve(ret->alpha, size, res->alpha); + } + +mvrl_err: + return(ret); +} + + +void menuvram_res2put(VRAMHDL vram, const MENURES2 *res, const POINT_T *pt) { + + RESPUT rp; + + if (resputprepare(vram, res, pt, &rp) != SUCCESS) { + goto mvr2_end; + } + switch(vram->bpp) { +#ifdef SUPPORT_16BPP + case 16: + res2put16(vram, res, &rp); + break; +#endif +#ifdef SUPPORT_24BPP + case 24: + res2put24(vram, res, &rp); + break; +#endif +#ifdef SUPPORT_32BPP + case 32: + res2put32(vram, res, &rp); + break; +#endif + default: + TRACEOUT(("menuvram_res2put: unspport %dbpp", vram->bpp)); + break; + } + +mvr2_end: + return; +} + + +void menuvram_res3put(VRAMHDL vram, const MENURES2 *res, const POINT_T *pt, + UINT mvc) { + + RESPUT rp; + + if (resputprepare(vram, res, pt, &rp) != SUCCESS) { + goto mvr3_end; + } + switch(vram->bpp) { +#ifdef SUPPORT_16BPP + case 16: + res3put16(vram, res, &rp, mvc); + break; +#endif +#ifdef SUPPORT_24BPP + case 24: + res3put24(vram, res, &rp, mvc); + break; +#endif +#ifdef SUPPORT_32BPP + case 32: + res3put32(vram, res, &rp, mvc); + break; +#endif + default: + TRACEOUT(("menuvram_res3put: unspport %dbpp", vram->bpp)); + break; + } + +mvr3_end: + return; +} + + +// ---- + +void menuvram_linex(VRAMHDL vram, int posx, int posy, int term, UINT mvc) { + + UINT8 *p; + + if ((vram == NULL) || + (posy < 0) || (posy >= vram->height)) { + goto mvlx_end; + } + if (posx < 0) { + posx = 0; + } + if (term >= vram->width) { + term = vram->width; + } + p = vram->ptr; + p += posy * vram->yalign; + p += posx * vram->xalign; + +#ifdef SUPPORT_16BPP + if (vram->bpp == 16) { + UINT16 color; + color = menucolor16[mvc]; + while(posx < term) { + posx++; + *(UINT16 *)p = (UINT16)color; + p += 2; + } + } +#endif +#ifdef SUPPORT_24BPP + if (vram->bpp == 24) { + UINT32 color; + UINT8 col[3]; + color = menucolor[mvc]; + col[0] = (UINT8)color; + col[1] = (UINT8)(color >> 8); + col[2] = (UINT8)(color >> 16); + while(posx < term) { + posx++; + p[0] = col[0]; + p[1] = col[1]; + p[2] = col[2]; + p += 3; + } + } +#endif +#ifdef SUPPORT_32BPP + if (vram->bpp == 32) { + UINT32 color; + UINT8 col[3]; + color = menucolor[mvc]; + col[0] = (UINT8)color; + col[1] = (UINT8)(color >> 8); + col[2] = (UINT8)(color >> 16); + while(posx < term) { + posx++; + p[0] = col[0]; + p[1] = col[1]; + p[2] = col[2]; + p += 4; + } + } +#endif + +mvlx_end: + return; +} + + +void menuvram_liney(VRAMHDL vram, int posx, int posy, int term, UINT mvc) { + + UINT8 *p; + + if ((vram == NULL) || + (posx < 0) || (posx >= vram->width)) { + goto mvly_end; + } + if (posy < 0) { + posy = 0; + } + if (term >= vram->height) { + term = vram->height; + } + p = vram->ptr; + p += posy * vram->yalign; + p += posx * vram->xalign; + +#ifdef SUPPORT_16BPP + if (vram->bpp == 16) { + UINT16 color; + color = menucolor16[mvc]; + while(posy < term) { + posy++; + *(UINT16 *)p = (UINT16)color; + p += vram->yalign; + } + } +#endif +#ifdef SUPPORT_24BPP + if (vram->bpp == 24) { + UINT32 color; + UINT8 col[3]; + color = menucolor[mvc]; + col[0] = (UINT8)color; + col[1] = (UINT8)(color >> 8); + col[2] = (UINT8)(color >> 16); + while(posy < term) { + posy++; + p[0] = col[0]; + p[1] = col[1]; + p[2] = col[2]; + p += vram->yalign; + } + } +#endif +#ifdef SUPPORT_32BPP + if (vram->bpp == 32) { + UINT32 color; + UINT8 col[3]; + color = menucolor[mvc]; + col[0] = (UINT8)color; + col[1] = (UINT8)(color >> 8); + col[2] = (UINT8)(color >> 16); + while(posy < term) { + posy++; + p[0] = col[0]; + p[1] = col[1]; + p[2] = col[2]; + p += vram->yalign; + } + } +#endif + +mvly_end: + return; +} + + +void menuvram_box(VRAMHDL vram, const RECT_T *rect, UINT mvc2, int reverse) { + + UINT c1; + UINT c2; + + if (rect == NULL) { + goto mvb_exit; + } + + if (!reverse) { + c1 = mvc2 & 0x0f; + c2 = (mvc2 >> 4) & 0x0f; + } + else { + c1 = (mvc2 >> 4) & 0x0f; + c2 = mvc2 & 0x0f; + } + menuvram_linex(vram, rect->left+0, rect->top+0, rect->right-1, c1); + menuvram_liney(vram, rect->left+0, rect->top+1, rect->bottom-1, c1); + menuvram_linex(vram, rect->left+0, rect->bottom-1, rect->right-1, c2); + menuvram_liney(vram, rect->right-1, rect->top+0, rect->bottom-0, c2); + +mvb_exit: + return; +} + + +void menuvram_box2(VRAMHDL vram, const RECT_T *rect, UINT mvc4) { + + UINT col; + + if (rect == NULL) { + goto mvb2_exit; + } + + col = mvc4 & 0x0f; + menuvram_linex(vram, rect->left+0, rect->top+0, rect->right-1, col); + menuvram_liney(vram, rect->left+0, rect->top+1, rect->bottom-1, col); + + col = (mvc4 >> 4) & 0x0f; + menuvram_linex(vram, rect->left+0, rect->bottom-1, rect->right-1, col); + menuvram_liney(vram, rect->right-1, rect->top+0, rect->bottom-0, col); + + col = (mvc4 >> 8) & 0x0f; + menuvram_linex(vram, rect->left+1, rect->top+1, rect->right-2, col); + menuvram_liney(vram, rect->left+1, rect->top+2, rect->bottom-2, col); + + col = (mvc4 >> 12) & 0x0f; + menuvram_linex(vram, rect->left+1, rect->bottom-2, rect->right-2, col); + menuvram_liney(vram, rect->right-2, rect->top+1, rect->bottom-1, col); + +mvb2_exit: + return; +} + + +void menuvram_base(VRAMHDL vram) { + + RECT_T rct; + + vram_filldat(vram, NULL, menucolor[MVC_STATIC]); + rct.left = 0; + rct.top = 0; + rct.right = vram->width; + rct.bottom = vram->height; + menuvram_box2(vram, &rct, + MVC4(MVC_LIGHT, MVC_DARK, MVC_HILIGHT, MVC_SHADOW)); +} + + +VRAMHDL menuvram_create(int width, int height, UINT bpp) { + + VRAMHDL ret; + + ret = vram_create(width, height, FALSE, bpp); + if (ret == NULL) { + goto mvcre_err; + } + menuvram_base(ret); + +mvcre_err: + return(ret); +} + +void menuvram_caption(VRAMHDL vram, const RECT_T *rect, + UINT16 icon, const OEMCHAR *caption) { + + POINT_T pt; + VRAMHDL work; + + if ((vram == NULL) || (rect == NULL)) { + goto mvpt_exit; + } + +#ifdef SUPPORT_16BPP + if (vram->bpp == 16) { + captionbar16(vram, rect, 0x000080, 0x000000); + } +#endif +#ifdef SUPPORT_24BPP + if (vram->bpp == 24) { + captionbar24(vram, rect, 0x000080, 0x000000); + } +#endif +#ifdef SUPPORT_32BPP + if (vram->bpp == 32) { + captionbar32(vram, rect, 0x000080, 0x000000); + } +#endif + pt.x = rect->left + MENU_PXCAPTION; + if (icon) { + pt.y = rect->top + MENU_PYCAPTION; + work = menuicon_lock(icon, MENUSYS_SZICON, MENUSYS_SZICON, vram->bpp); + if (work) { + if (work->alpha) { + vramcpy_cpyex(vram, &pt, work, NULL); + } + else { + vramcpy_cpy(vram, &pt, work, NULL); + } + menuicon_unlock(work); + } + pt.x += MENUSYS_SZICON + MENU_PXCAPTION; + } + pt.y = rect->top + (rect->bottom - rect->top - MENU_FONTSIZE) / 2; + vrammix_text(vram, menubase.font, caption, 0xffffff, &pt, rect); + +mvpt_exit: + return; +} + + +static void putbtn(VRAMHDL vram, const RECT_T *rect, + const MENURES2 *res, BOOL focus) { + RECT_T rct; + POINT_T pt; + UINT mvc4; + + if (rect) { + rct = *rect; + } + else { + vram_getrect(vram, &rct); + } + + if (!focus) { + mvc4 = MVC4(MVC_LIGHT, MVC_DARK, MVC_HILIGHT, MVC_SHADOW); + } + else { + mvc4 = MVC4(MVC_DARK, MVC_LIGHT, MVC_SHADOW, MVC_HILIGHT); + } + menuvram_box2(vram, &rct, mvc4); + rct.left += MENU_LINE * 2; + rct.top += MENU_LINE * 2; + rct.right -= MENU_LINE * 2; + rct.bottom -= MENU_LINE * 2; + vram_filldat(vram, &rct, menucolor[MVC_BTNFACE]); + pt.x = rct.left; + pt.y = rct.top; + if (focus) { + pt.x += MENU_LINE; + pt.y += MENU_LINE; + } + menuvram_res3put(vram, res, &pt, MVC_TEXT); +} + +void menuvram_minimizebtn(VRAMHDL vram, const RECT_T *rect, BOOL focus) { + + putbtn(vram, rect, &menures_minimize, focus); +} + +void menuvram_closebtn(VRAMHDL vram, const RECT_T *rect, BOOL focus) { + + putbtn(vram, rect, &menures_close, focus); +} + diff --git a/embed/menubase/menuvram.h b/embed/menubase/menuvram.h old mode 100755 new mode 100644 index 2c38d81f..5d3ede16 --- a/embed/menubase/menuvram.h +++ b/embed/menubase/menuvram.h @@ -1,62 +1,62 @@ - -enum { - MVC_BACK, - MVC_HILIGHT, - MVC_LIGHT, - MVC_SHADOW, - MVC_DARK, - MVC_SCROLLBAR, - - MVC_STATIC, - MVC_TEXT, - MVC_GRAYTEXT1, - MVC_GRAYTEXT2, - MVC_BTNFACE, - MVC_CURTEXT, - MVC_CURBACK -}; - -typedef struct { - int width; - int height; -const UINT8 *data; -const UINT8 *alpha; -} MENURES; - -typedef struct { - int width; - int height; -const UINT8 *pat; -} MENURES2; - -#define MVC2(a, b) (a | (b << 4)) -#define MVC4(a, b, c, d) (a | (b << 4) | (c << 8) | (d << 12)) - -#ifdef __cplusplus -extern "C" { -#endif - -extern UINT32 menucolor[]; - -VRAMHDL menuvram_resload(const MENURES *res, int bpp); -void menuvram_res2put(VRAMHDL vram, const MENURES2 *res, const POINT_T *pt); -void menuvram_res3put(VRAMHDL vram, const MENURES2 *res, const POINT_T *pt, - UINT mvc); - -void menuvram_linex(VRAMHDL vram, int posx, int posy, int term, UINT mvc); -void menuvram_liney(VRAMHDL vram, int posx, int posy, int term, UINT mvc); - -void menuvram_box(VRAMHDL vram, const RECT_T *rect, UINT mvc2, int reverse); -void menuvram_box2(VRAMHDL vram, const RECT_T *rect, UINT mvc4); - -void menuvram_base(VRAMHDL vram); -VRAMHDL menuvram_create(int width, int height, UINT bpp); -void menuvram_caption(VRAMHDL vram, const RECT_T *rect, - UINT16 icon, const OEMCHAR *caption); -void menuvram_minimizebtn(VRAMHDL vram, const RECT_T *rect, BOOL focus); -void menuvram_closebtn(VRAMHDL vram, const RECT_T *rect, BOOL focus); - -#ifdef __cplusplus -} -#endif - + +enum { + MVC_BACK, + MVC_HILIGHT, + MVC_LIGHT, + MVC_SHADOW, + MVC_DARK, + MVC_SCROLLBAR, + + MVC_STATIC, + MVC_TEXT, + MVC_GRAYTEXT1, + MVC_GRAYTEXT2, + MVC_BTNFACE, + MVC_CURTEXT, + MVC_CURBACK +}; + +typedef struct { + int width; + int height; +const UINT8 *data; +const UINT8 *alpha; +} MENURES; + +typedef struct { + int width; + int height; +const UINT8 *pat; +} MENURES2; + +#define MVC2(a, b) (a | (b << 4)) +#define MVC4(a, b, c, d) (a | (b << 4) | (c << 8) | (d << 12)) + +#ifdef __cplusplus +extern "C" { +#endif + +extern UINT32 menucolor[]; + +VRAMHDL menuvram_resload(const MENURES *res, int bpp); +void menuvram_res2put(VRAMHDL vram, const MENURES2 *res, const POINT_T *pt); +void menuvram_res3put(VRAMHDL vram, const MENURES2 *res, const POINT_T *pt, + UINT mvc); + +void menuvram_linex(VRAMHDL vram, int posx, int posy, int term, UINT mvc); +void menuvram_liney(VRAMHDL vram, int posx, int posy, int term, UINT mvc); + +void menuvram_box(VRAMHDL vram, const RECT_T *rect, UINT mvc2, int reverse); +void menuvram_box2(VRAMHDL vram, const RECT_T *rect, UINT mvc4); + +void menuvram_base(VRAMHDL vram); +VRAMHDL menuvram_create(int width, int height, UINT bpp); +void menuvram_caption(VRAMHDL vram, const RECT_T *rect, + UINT16 icon, const OEMCHAR *caption); +void menuvram_minimizebtn(VRAMHDL vram, const RECT_T *rect, BOOL focus); +void menuvram_closebtn(VRAMHDL vram, const RECT_T *rect, BOOL focus); + +#ifdef __cplusplus +} +#endif + diff --git a/embed/readme.txt b/embed/readme.txt old mode 100755 new mode 100644 index b657f0d0..80734609 --- a/embed/readme.txt +++ b/embed/readme.txt @@ -1,8 +1,8 @@ - - あの妖しい組み込み専用関数群が復活(?) - - 組み込みマシン以外はリンク不要です。 - - - っていうか、ドロップダウンリストほすぃ… - + + あの妖しい組み込み専用関数群が復活(?) + + 組み込みマシン以外はリンク不要です。 + + + っていうか、ドロップダウンリストほすぃ… + diff --git a/embed/vramhdl.c b/embed/vramhdl.c old mode 100755 new mode 100644 index 691ba5a9..94fd7711 --- a/embed/vramhdl.c +++ b/embed/vramhdl.c @@ -1,751 +1,751 @@ -#include -#include -#include - - -VRAMHDL vram_create(int width, int height, BOOL alpha, int bpp) { - - int size; - int allocsize; - int xalign; - int alphasize; - VRAMHDL ret; - -//#if defined(SCREEN_BPP) -// if (bpp == DEFAULT_BPP) { -// bpp = SCREEN_BPP; -// } -//#endif - size = width * height; - xalign = (bpp + 7) >> 3; - if ((width <= 0) || (size <= 0) || (size > 0x1000000) || - (xalign <= 0) || (xalign > 4)) { - return(NULL); - } - allocsize = sizeof(_VRAMHDL); - allocsize += size * xalign; - alphasize = 0; - if (alpha) { - alphasize = (size + 7) & (~7); // boundary!! - allocsize += alphasize; - } -#ifdef MEMTRACE - { - char buf[128]; - sprintf(buf, "VRAM %dx%d (%d)", width, height, bpp); - ret = (VRAMHDL)_MALLOC(allocsize, buf); - } -#else - ret = (VRAMHDL)_MALLOC(allocsize, "VRAM"); -#endif - if (ret) { - ZeroMemory(ret, allocsize); - ret->width = width; - ret->height = height; - ret->xalign = xalign; - ret->yalign = xalign * width; - ret->bpp = bpp; - ret->scrnsize = size; - if (alpha) { - ret->alpha = (UINT8 *)(ret + 1); - ret->ptr = ret->alpha + alphasize; - } - else { - ret->ptr = (UINT8 *)(ret + 1); - } - } - return(ret); -} - -void vram_destroy(VRAMHDL hdl) { - - if (hdl) { - if ((hdl->alpha) && (hdl->alpha != (UINT8 *)(hdl + 1))) { - _MFREE(hdl->alpha); - } - _MFREE(hdl); - } -} - -BRESULT vram_allocalpha(VRAMHDL hdl) { - - if (hdl == NULL) { - return(FAILURE); - } - if (hdl->alpha == NULL) { - hdl->alpha = (UINT8 *)_MALLOC(hdl->scrnsize, "alpha plane"); - if (hdl->alpha == NULL) { - return(FAILURE); - } - ZeroMemory(hdl->alpha, hdl->scrnsize); - } - return(SUCCESS); -} - -void vram_zerofill(VRAMHDL hdl, const RECT_T *rect) { - - int ptr; - int width; - int height; - int pos; - int remain; - UINT8 *p; - - if (hdl) { - if (rect == NULL) { - ZeroMemory(hdl->ptr, hdl->scrnsize * hdl->xalign); - if (hdl->alpha) { - ZeroMemory(hdl->alpha, hdl->scrnsize); - } - } - else { - pos = MAX(rect->left, 0); - ptr = pos; - width = MIN(rect->right, hdl->width) - pos; - pos = MAX(rect->top, 0); - ptr += pos * hdl->width; - height = MIN(rect->bottom, hdl->height) - pos; - if ((width > 0) && (height > 0)) { - p = hdl->ptr; - p += ptr * hdl->xalign; - remain = height; - do { - ZeroMemory(p, width * hdl->xalign); - p += hdl->yalign; - } while(--remain); - - if (hdl->alpha) { - p = hdl->alpha + ptr; - remain = height; - do { - ZeroMemory(p, width); - p += hdl->width; - } while(--remain); - } - } - } - } -} - -void vram_fill(VRAMHDL hdl, const RECT_T *rect, UINT32 color, UINT8 alpha) { - - int ptr; - int width; - int height; - int pos; - int remain; - UINT8 *p; -#ifdef SUPPORT_16BPP - UINT c16; -#endif -#ifdef SUPPORT_24BPP - UINT8 c24[3]; -#endif -#ifdef SUPPORT_32BPP - UINT8 c32[3]; -#endif - - if (hdl == NULL) { - return; - } - if (rect == NULL) { - p = hdl->ptr; - remain = hdl->scrnsize; - switch(hdl->bpp) { - case 8: - do { - *p++ = (UINT8)color; - } while(--remain); - break; -#ifdef SUPPORT_16BPP - case 16: - c16 = MAKE16PAL(color); - do { - *(UINT16 *)p = (UINT16)c16; - p += 2; - } while(--remain); - break; -#endif -#ifdef SUPPORT_24BPP - case 24: - c24[0] = (UINT8)color; - c24[1] = (UINT8)(color >> 8); - c24[2] = (UINT8)(color >> 16); - do { - p[0] = c24[0]; - p[1] = c24[1]; - p[2] = c24[2]; - p += 3; - } while(--remain); - break; -#endif -#ifdef SUPPORT_32BPP - case 32: - c32[0] = (UINT8)color; - c32[1] = (UINT8)(color >> 8); - c32[2] = (UINT8)(color >> 16); - do { - p[0] = c32[0]; - p[1] = c32[1]; - p[2] = c32[2]; - p += 4; - } while(--remain); - break; -#endif - default: - TRACEOUT(("vram_fill: unsupport %dbpp", hdl->bpp)); - break; - } - if (hdl->alpha) { - FillMemory(hdl->alpha, hdl->scrnsize, alpha); - } - } - else { - pos = MAX(rect->left, 0); - ptr = pos; - width = MIN(rect->right, hdl->width) - pos; - pos = MAX(rect->top, 0); - ptr += pos * hdl->width; - height = MIN(rect->bottom, hdl->height) - pos; - if ((width > 0) && (height > 0)) { - p = hdl->ptr; - p += ptr * hdl->xalign; - switch(hdl->bpp) { - case 8: - remain = height; - do { - int r = width; - do { - *p++ = (UINT8)color; - } while(--r); - p += hdl->yalign - width; - } while(--remain); - break; -#ifdef SUPPORT_16BPP - case 16: - c16 = MAKE16PAL(color); - remain = height; - do { - int r = width; - do { - *(UINT16 *)p = (UINT16)c16; - p += 2; - } while(--r); - p += hdl->yalign - (width * 2); - } while(--remain); - break; -#endif -#ifdef SUPPORT_24BPP - case 24: - c24[0] = (UINT8)color; - c24[1] = (UINT8)(color >> 8); - c24[2] = (UINT8)(color >> 16); - remain = height; - do { - int r = width; - do { - p[0] = c24[0]; - p[1] = c24[1]; - p[2] = c24[2]; - p += 3; - } while(--r); - p += hdl->yalign - (width * 3); - } while(--remain); - break; -#endif -#ifdef SUPPORT_32BPP - case 32: - c32[0] = (UINT8)color; - c32[1] = (UINT8)(color >> 8); - c32[2] = (UINT8)(color >> 16); - remain = height; - do { - int r = width; - do { - p[0] = c32[0]; - p[1] = c32[1]; - p[2] = c32[2]; - p += 4; - } while(--r); - p += hdl->yalign - (width * 4); - } while(--remain); - break; -#endif - default: - TRACEOUT(("vram_fill: unsupport %dbpp", hdl->bpp)); - break; - } - if (hdl->alpha) { - p = hdl->alpha + ptr; - remain = height; - do { - FillMemory(p, width, alpha); - p += hdl->width; - } while(--remain); - } - } - } -} - -void vram_filldat(VRAMHDL hdl, const RECT_T *rect, UINT32 color) { - - int ptr; - int width; - int height; - int pos; - int remain; - UINT8 *p; -#ifdef SUPPORT_16BPP - UINT c16; -#endif -#ifdef SUPPORT_24BPP - UINT8 c24[3]; -#endif -#ifdef SUPPORT_32BPP - UINT8 c32[3]; -#endif - - if (hdl == NULL) { - return; - } - if (rect == NULL) { - p = hdl->ptr; - remain = hdl->scrnsize; - switch(hdl->bpp) { - case 8: - do { - *p++ = (UINT8)color; - } while(--remain); - break; -#ifdef SUPPORT_16BPP - case 16: - c16 = MAKE16PAL(color); - do { - *(UINT16 *)p = (UINT16)c16; - p += 2; - } while(--remain); - break; -#endif -#ifdef SUPPORT_24BPP - case 24: - c24[0] = (UINT8)color; - c24[1] = (UINT8)(color >> 8); - c24[2] = (UINT8)(color >> 16); - do { - p[0] = c24[0]; - p[1] = c24[1]; - p[2] = c24[2]; - p += 3; - } while(--remain); - break; -#endif -#ifdef SUPPORT_32BPP - case 32: - c32[0] = (UINT8)color; - c32[1] = (UINT8)(color >> 8); - c32[2] = (UINT8)(color >> 16); - do { - p[0] = c32[0]; - p[1] = c32[1]; - p[2] = c32[2]; - p += 4; - } while(--remain); - break; -#endif - default: - TRACEOUT(("vram_filldat: unsupport %dbpp", hdl->bpp)); - break; - } - } - else { - pos = MAX(rect->left, 0); - ptr = pos; - width = MIN(rect->right, hdl->width) - pos; - pos = MAX(rect->top, 0); - ptr += pos * hdl->width; - height = MIN(rect->bottom, hdl->height) - pos; - if ((width > 0) && (height > 0)) { - p = hdl->ptr; - p += ptr * hdl->xalign; - switch(hdl->bpp) { - case 8: - remain = height; - do { - int r = width; - do { - *p++ = (UINT8)color; - } while(--r); - p += hdl->yalign - width; - } while(--remain); - break; -#ifdef SUPPORT_16BPP - case 16: - c16 = MAKE16PAL(color); - remain = height; - do { - int r = width; - do { - *(UINT16 *)p = (UINT16)c16; - p += 2; - } while(--r); - p += hdl->yalign - (width * 2); - } while(--remain); - break; -#endif -#ifdef SUPPORT_24BPP - case 24: - c24[0] = (UINT8)color; - c24[1] = (UINT8)(color >> 8); - c24[2] = (UINT8)(color >> 16); - remain = height; - do { - int r = width; - do { - p[0] = c24[0]; - p[1] = c24[1]; - p[2] = c24[2]; - p += 3; - } while(--r); - p += hdl->yalign - (width * 3); - } while(--remain); - break; -#endif -#ifdef SUPPORT_32BPP - case 32: - c32[0] = (UINT8)color; - c32[1] = (UINT8)(color >> 8); - c32[2] = (UINT8)(color >> 16); - remain = height; - do { - int r = width; - do { - p[0] = c32[0]; - p[1] = c32[1]; - p[2] = c32[2]; - p += 4; - } while(--r); - p += hdl->yalign - (width * 4); - } while(--remain); - break; -#endif - default: - TRACEOUT(("vram_filldat: unsupport %dbpp", hdl->bpp)); - break; - } - } - } -} - -void vram_fillalpha(VRAMHDL hdl, const RECT_T *rect, UINT8 alpha) { - - int ptr; - int width; - int height; - int pos; - int remain; - UINT8 *p; - - if ((hdl == NULL) || (hdl->alpha == NULL)) { - return; - } - if (rect == NULL) { - p = hdl->ptr; - remain = hdl->scrnsize; - FillMemory(hdl->alpha, hdl->scrnsize, alpha); - } - else { - pos = MAX(rect->left, 0); - ptr = pos; - width = MIN(rect->right, hdl->width) - pos; - pos = MAX(rect->top, 0); - ptr += pos * hdl->width; - height = MIN(rect->bottom, hdl->height) - pos; - if ((width > 0) && (height > 0)) { - p = hdl->alpha + ptr; - remain = height; - do { - FillMemory(p, width, alpha); - p += hdl->width; - } while(--remain); - } - } -} - -void vram_fillex(VRAMHDL hdl, const RECT_T *rect, UINT32 color, UINT8 alpha) { - - int ptr; - int width; - int height; - int pos; - int remain; - UINT8 *p; -#ifdef SUPPORT_16BPP - int tmp; - int c16[3]; -#endif -#ifdef SUPPORT_24BPP - int c24[3]; -#endif -#ifdef SUPPORT_32BPP - int c32[3]; -#endif - - if (hdl == NULL) { - return; - } - if (rect == NULL) { - p = hdl->ptr; - remain = hdl->scrnsize; - switch(hdl->bpp) { -#ifdef SUPPORT_16BPP - case 16: - tmp = MAKE16PAL(color); - c16[0] = tmp & B16MASK; - c16[1] = tmp & G16MASK; - c16[2] = tmp & R16MASK; - tmp = 64 - alpha; - do { - UINT s, d; - s = *(UINT16 *)p; - d = MAKEALPHA16s(c16[0], s, B16MASK, tmp, 6); - d |= MAKEALPHA16s(c16[1], s, G16MASK, tmp, 6); - d |= MAKEALPHA16s(c16[2], s, R16MASK, tmp, 6); - *(UINT16 *)p = (UINT16)d; - p += 2; - } while(--remain); - break; -#endif -#ifdef SUPPORT_24BPP - case 24: - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - do { - p[0] = (UINT8)MAKEALPHA24(p[0], c24[0], alpha, 6); - p[1] = (UINT8)MAKEALPHA24(p[1], c24[1], alpha, 6); - p[2] = (UINT8)MAKEALPHA24(p[2], c24[2], alpha, 6); - p += 3; - } while(--remain); - break; -#endif -#ifdef SUPPORT_32BPP - case 32: - c32[0] = color & 0xff; - c32[1] = (color >> 8) & 0xff; - c32[2] = (color >> 16) & 0xff; - do { - p[0] = (UINT8)MAKEALPHA24(p[0], c32[0], alpha, 6); - p[1] = (UINT8)MAKEALPHA24(p[1], c32[1], alpha, 6); - p[2] = (UINT8)MAKEALPHA24(p[2], c32[2], alpha, 6); - p += 4; - } while(--remain); - break; -#endif - default: - TRACEOUT(("vram_fillex: unsupport %dbpp", hdl->bpp)); - break; - } - } - else { - pos = MAX(rect->left, 0); - ptr = pos; - width = MIN(rect->right, hdl->width) - pos; - pos = MAX(rect->top, 0); - ptr += pos * hdl->width; - height = MIN(rect->bottom, hdl->height) - pos; - if ((width > 0) && (height > 0)) { - p = hdl->ptr; - p += ptr * hdl->xalign; - switch(hdl->bpp) { -#ifdef SUPPORT_16BPP - case 16: - tmp = MAKE16PAL(color); - c16[0] = tmp & B16MASK; - c16[1] = tmp & G16MASK; - c16[2] = tmp & R16MASK; - tmp = 64 - alpha; - remain = height; - do { - int r = width; - do { - UINT s, d; - s = *(UINT16 *)p; - d = MAKEALPHA16s(c16[0], s, B16MASK, tmp, 6); - d |= MAKEALPHA16s(c16[1], s, G16MASK, tmp, 6); - d |= MAKEALPHA16s(c16[2], s, R16MASK, tmp, 6); - *(UINT16 *)p = (UINT16)d; - p += 2; - } while(--r); - p += hdl->yalign - (width * 2); - } while(--remain); - break; -#endif -#ifdef SUPPORT_24BPP - case 24: - remain = height; - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - do { - int r = width; - do { - p[0] = (UINT8)MAKEALPHA24(p[0], c24[0], alpha, 6); - p[1] = (UINT8)MAKEALPHA24(p[1], c24[1], alpha, 6); - p[2] = (UINT8)MAKEALPHA24(p[2], c24[2], alpha, 6); - p += 3; - } while(--r); - p += hdl->yalign - (width * 3); - } while(--remain); - break; -#endif -#ifdef SUPPORT_32BPP - case 32: - remain = height; - c32[0] = color & 0xff; - c32[1] = (color >> 8) & 0xff; - c32[2] = (color >> 16) & 0xff; - do { - int r = width; - do { - p[0] = (UINT8)MAKEALPHA24(p[0], c32[0], alpha, 6); - p[1] = (UINT8)MAKEALPHA24(p[1], c32[1], alpha, 6); - p[2] = (UINT8)MAKEALPHA24(p[2], c32[2], alpha, 6); - p += 4; - } while(--r); - p += hdl->yalign - (width * 4); - } while(--remain); - break; -#endif - default: - TRACEOUT(("vram_fillex: unsupport %dbpp", hdl->bpp)); - break; - } - } - } -} - -VRAMHDL vram_resize(VRAMHDL base, int width, int height, int bpp) { - - VRAMHDL ret; - RSZHDL rsz; - - if (base == NULL) { - goto vrs_err1; - } - ret = vram_create(width, height, (base->alpha != NULL), bpp); - if (ret == NULL) { - goto vrs_err1; - } - rsz = resize(width, height, base->width, base->height); - if (rsz == NULL) { - goto vrs_err2; - } - (*rsz->func)(rsz, resize_gettype(bpp, base->bpp), - ret->ptr, ret->yalign, base->ptr, base->yalign); - if (base->alpha) { - (*rsz->func)(rsz, RSZFN_8BPP, - ret->alpha, ret->width, base->alpha, base->width); - } - _MFREE(rsz); - return(ret); - -vrs_err2: - vram_destroy(ret); - -vrs_err1: - return(NULL); -} - -void vram_getrect(const VRAMHDL hdl, RECT_T *rct) { - - int x, y; - - if ((hdl) && (rct)) { - x = hdl->posx; - y = hdl->posy; - rct->left = x; - rct->top = y; - rct->right = x + hdl->width; - rct->bottom = y + hdl->height; - } -} - -VRAMHDL vram_dupe(const VRAMHDL hdl) { - - VRAMHDL ret = NULL; - int size; - int datsize; - - if (hdl == NULL) { - goto vd_exit; - } - datsize = hdl->scrnsize * hdl->xalign; - size = sizeof(_VRAMHDL); - size += datsize; - if (hdl->alpha) { - size += hdl->scrnsize; - } - ret = (VRAMHDL)_MALLOC(size, "VRAM copy"); - if (ret == NULL) { - goto vd_exit; - } - *ret = *hdl; - if (hdl->alpha) { - ret->alpha = (UINT8 *)(ret + 1); - CopyMemory(ret->alpha, hdl->alpha, hdl->scrnsize); - ret->ptr = ret->alpha + hdl->scrnsize; - } - else { - ret->ptr = (UINT8 *)(ret + 1); - } - CopyMemory(ret->ptr, hdl->ptr, datsize); - -vd_exit: - return(ret); -} - -BRESULT vram_cliprect(RECT_T *clip, const VRAMHDL vram, const RECT_T *rct) { - - if (vram == NULL) { - return(FAILURE); - } - if (rct == NULL) { - clip->left = 0; - clip->top = 0; - clip->right = vram->width; - clip->bottom = vram->height; - return(SUCCESS); - } - if ((rct->bottom <= 0) || (rct->right <= 0) || - (rct->left >= vram->width) || (rct->top >= vram->height)) { - return(FAILURE); - } - clip->left = MAX(rct->left, 0); - clip->top = MAX(rct->top, 0); - clip->right = MIN(rct->right, vram->width); - clip->bottom = MIN(rct->bottom, vram->height); - if ((clip->top >= clip->bottom) || (clip->left >= clip->right)) { - return(FAILURE); - } - return(SUCCESS); -} - -BRESULT vram_cliprectex(RECT_T *clip, const VRAMHDL vram, const RECT_T *rct) { - - if ((vram == NULL) || (clip == NULL)) { - return(FAILURE); - } - vram_getrect(vram, clip); - if (rct == NULL) { - return(SUCCESS); - } - clip->left = MAX(clip->left, rct->left); - clip->top = MAX(clip->top, rct->top); - clip->right = MIN(clip->right, rct->right); - clip->bottom = MIN(clip->bottom, rct->bottom); - if ((clip->left >= clip->right) || (clip->top >= clip->bottom)) { - return(FAILURE); - } - return(SUCCESS); -} - +#include +#include +#include + + +VRAMHDL vram_create(int width, int height, BOOL alpha, int bpp) { + + int size; + int allocsize; + int xalign; + int alphasize; + VRAMHDL ret; + +//#if defined(SCREEN_BPP) +// if (bpp == DEFAULT_BPP) { +// bpp = SCREEN_BPP; +// } +//#endif + size = width * height; + xalign = (bpp + 7) >> 3; + if ((width <= 0) || (size <= 0) || (size > 0x1000000) || + (xalign <= 0) || (xalign > 4)) { + return(NULL); + } + allocsize = sizeof(_VRAMHDL); + allocsize += size * xalign; + alphasize = 0; + if (alpha) { + alphasize = (size + 7) & (~7); // boundary!! + allocsize += alphasize; + } +#ifdef MEMTRACE + { + char buf[128]; + sprintf(buf, "VRAM %dx%d (%d)", width, height, bpp); + ret = (VRAMHDL)_MALLOC(allocsize, buf); + } +#else + ret = (VRAMHDL)_MALLOC(allocsize, "VRAM"); +#endif + if (ret) { + ZeroMemory(ret, allocsize); + ret->width = width; + ret->height = height; + ret->xalign = xalign; + ret->yalign = xalign * width; + ret->bpp = bpp; + ret->scrnsize = size; + if (alpha) { + ret->alpha = (UINT8 *)(ret + 1); + ret->ptr = ret->alpha + alphasize; + } + else { + ret->ptr = (UINT8 *)(ret + 1); + } + } + return(ret); +} + +void vram_destroy(VRAMHDL hdl) { + + if (hdl) { + if ((hdl->alpha) && (hdl->alpha != (UINT8 *)(hdl + 1))) { + _MFREE(hdl->alpha); + } + _MFREE(hdl); + } +} + +BRESULT vram_allocalpha(VRAMHDL hdl) { + + if (hdl == NULL) { + return(FAILURE); + } + if (hdl->alpha == NULL) { + hdl->alpha = (UINT8 *)_MALLOC(hdl->scrnsize, "alpha plane"); + if (hdl->alpha == NULL) { + return(FAILURE); + } + ZeroMemory(hdl->alpha, hdl->scrnsize); + } + return(SUCCESS); +} + +void vram_zerofill(VRAMHDL hdl, const RECT_T *rect) { + + int ptr; + int width; + int height; + int pos; + int remain; + UINT8 *p; + + if (hdl) { + if (rect == NULL) { + ZeroMemory(hdl->ptr, hdl->scrnsize * hdl->xalign); + if (hdl->alpha) { + ZeroMemory(hdl->alpha, hdl->scrnsize); + } + } + else { + pos = MAX(rect->left, 0); + ptr = pos; + width = MIN(rect->right, hdl->width) - pos; + pos = MAX(rect->top, 0); + ptr += pos * hdl->width; + height = MIN(rect->bottom, hdl->height) - pos; + if ((width > 0) && (height > 0)) { + p = hdl->ptr; + p += ptr * hdl->xalign; + remain = height; + do { + ZeroMemory(p, width * hdl->xalign); + p += hdl->yalign; + } while(--remain); + + if (hdl->alpha) { + p = hdl->alpha + ptr; + remain = height; + do { + ZeroMemory(p, width); + p += hdl->width; + } while(--remain); + } + } + } + } +} + +void vram_fill(VRAMHDL hdl, const RECT_T *rect, UINT32 color, UINT8 alpha) { + + int ptr; + int width; + int height; + int pos; + int remain; + UINT8 *p; +#ifdef SUPPORT_16BPP + UINT c16; +#endif +#ifdef SUPPORT_24BPP + UINT8 c24[3]; +#endif +#ifdef SUPPORT_32BPP + UINT8 c32[3]; +#endif + + if (hdl == NULL) { + return; + } + if (rect == NULL) { + p = hdl->ptr; + remain = hdl->scrnsize; + switch(hdl->bpp) { + case 8: + do { + *p++ = (UINT8)color; + } while(--remain); + break; +#ifdef SUPPORT_16BPP + case 16: + c16 = MAKE16PAL(color); + do { + *(UINT16 *)p = (UINT16)c16; + p += 2; + } while(--remain); + break; +#endif +#ifdef SUPPORT_24BPP + case 24: + c24[0] = (UINT8)color; + c24[1] = (UINT8)(color >> 8); + c24[2] = (UINT8)(color >> 16); + do { + p[0] = c24[0]; + p[1] = c24[1]; + p[2] = c24[2]; + p += 3; + } while(--remain); + break; +#endif +#ifdef SUPPORT_32BPP + case 32: + c32[0] = (UINT8)color; + c32[1] = (UINT8)(color >> 8); + c32[2] = (UINT8)(color >> 16); + do { + p[0] = c32[0]; + p[1] = c32[1]; + p[2] = c32[2]; + p += 4; + } while(--remain); + break; +#endif + default: + TRACEOUT(("vram_fill: unsupport %dbpp", hdl->bpp)); + break; + } + if (hdl->alpha) { + FillMemory(hdl->alpha, hdl->scrnsize, alpha); + } + } + else { + pos = MAX(rect->left, 0); + ptr = pos; + width = MIN(rect->right, hdl->width) - pos; + pos = MAX(rect->top, 0); + ptr += pos * hdl->width; + height = MIN(rect->bottom, hdl->height) - pos; + if ((width > 0) && (height > 0)) { + p = hdl->ptr; + p += ptr * hdl->xalign; + switch(hdl->bpp) { + case 8: + remain = height; + do { + int r = width; + do { + *p++ = (UINT8)color; + } while(--r); + p += hdl->yalign - width; + } while(--remain); + break; +#ifdef SUPPORT_16BPP + case 16: + c16 = MAKE16PAL(color); + remain = height; + do { + int r = width; + do { + *(UINT16 *)p = (UINT16)c16; + p += 2; + } while(--r); + p += hdl->yalign - (width * 2); + } while(--remain); + break; +#endif +#ifdef SUPPORT_24BPP + case 24: + c24[0] = (UINT8)color; + c24[1] = (UINT8)(color >> 8); + c24[2] = (UINT8)(color >> 16); + remain = height; + do { + int r = width; + do { + p[0] = c24[0]; + p[1] = c24[1]; + p[2] = c24[2]; + p += 3; + } while(--r); + p += hdl->yalign - (width * 3); + } while(--remain); + break; +#endif +#ifdef SUPPORT_32BPP + case 32: + c32[0] = (UINT8)color; + c32[1] = (UINT8)(color >> 8); + c32[2] = (UINT8)(color >> 16); + remain = height; + do { + int r = width; + do { + p[0] = c32[0]; + p[1] = c32[1]; + p[2] = c32[2]; + p += 4; + } while(--r); + p += hdl->yalign - (width * 4); + } while(--remain); + break; +#endif + default: + TRACEOUT(("vram_fill: unsupport %dbpp", hdl->bpp)); + break; + } + if (hdl->alpha) { + p = hdl->alpha + ptr; + remain = height; + do { + FillMemory(p, width, alpha); + p += hdl->width; + } while(--remain); + } + } + } +} + +void vram_filldat(VRAMHDL hdl, const RECT_T *rect, UINT32 color) { + + int ptr; + int width; + int height; + int pos; + int remain; + UINT8 *p; +#ifdef SUPPORT_16BPP + UINT c16; +#endif +#ifdef SUPPORT_24BPP + UINT8 c24[3]; +#endif +#ifdef SUPPORT_32BPP + UINT8 c32[3]; +#endif + + if (hdl == NULL) { + return; + } + if (rect == NULL) { + p = hdl->ptr; + remain = hdl->scrnsize; + switch(hdl->bpp) { + case 8: + do { + *p++ = (UINT8)color; + } while(--remain); + break; +#ifdef SUPPORT_16BPP + case 16: + c16 = MAKE16PAL(color); + do { + *(UINT16 *)p = (UINT16)c16; + p += 2; + } while(--remain); + break; +#endif +#ifdef SUPPORT_24BPP + case 24: + c24[0] = (UINT8)color; + c24[1] = (UINT8)(color >> 8); + c24[2] = (UINT8)(color >> 16); + do { + p[0] = c24[0]; + p[1] = c24[1]; + p[2] = c24[2]; + p += 3; + } while(--remain); + break; +#endif +#ifdef SUPPORT_32BPP + case 32: + c32[0] = (UINT8)color; + c32[1] = (UINT8)(color >> 8); + c32[2] = (UINT8)(color >> 16); + do { + p[0] = c32[0]; + p[1] = c32[1]; + p[2] = c32[2]; + p += 4; + } while(--remain); + break; +#endif + default: + TRACEOUT(("vram_filldat: unsupport %dbpp", hdl->bpp)); + break; + } + } + else { + pos = MAX(rect->left, 0); + ptr = pos; + width = MIN(rect->right, hdl->width) - pos; + pos = MAX(rect->top, 0); + ptr += pos * hdl->width; + height = MIN(rect->bottom, hdl->height) - pos; + if ((width > 0) && (height > 0)) { + p = hdl->ptr; + p += ptr * hdl->xalign; + switch(hdl->bpp) { + case 8: + remain = height; + do { + int r = width; + do { + *p++ = (UINT8)color; + } while(--r); + p += hdl->yalign - width; + } while(--remain); + break; +#ifdef SUPPORT_16BPP + case 16: + c16 = MAKE16PAL(color); + remain = height; + do { + int r = width; + do { + *(UINT16 *)p = (UINT16)c16; + p += 2; + } while(--r); + p += hdl->yalign - (width * 2); + } while(--remain); + break; +#endif +#ifdef SUPPORT_24BPP + case 24: + c24[0] = (UINT8)color; + c24[1] = (UINT8)(color >> 8); + c24[2] = (UINT8)(color >> 16); + remain = height; + do { + int r = width; + do { + p[0] = c24[0]; + p[1] = c24[1]; + p[2] = c24[2]; + p += 3; + } while(--r); + p += hdl->yalign - (width * 3); + } while(--remain); + break; +#endif +#ifdef SUPPORT_32BPP + case 32: + c32[0] = (UINT8)color; + c32[1] = (UINT8)(color >> 8); + c32[2] = (UINT8)(color >> 16); + remain = height; + do { + int r = width; + do { + p[0] = c32[0]; + p[1] = c32[1]; + p[2] = c32[2]; + p += 4; + } while(--r); + p += hdl->yalign - (width * 4); + } while(--remain); + break; +#endif + default: + TRACEOUT(("vram_filldat: unsupport %dbpp", hdl->bpp)); + break; + } + } + } +} + +void vram_fillalpha(VRAMHDL hdl, const RECT_T *rect, UINT8 alpha) { + + int ptr; + int width; + int height; + int pos; + int remain; + UINT8 *p; + + if ((hdl == NULL) || (hdl->alpha == NULL)) { + return; + } + if (rect == NULL) { + p = hdl->ptr; + remain = hdl->scrnsize; + FillMemory(hdl->alpha, hdl->scrnsize, alpha); + } + else { + pos = MAX(rect->left, 0); + ptr = pos; + width = MIN(rect->right, hdl->width) - pos; + pos = MAX(rect->top, 0); + ptr += pos * hdl->width; + height = MIN(rect->bottom, hdl->height) - pos; + if ((width > 0) && (height > 0)) { + p = hdl->alpha + ptr; + remain = height; + do { + FillMemory(p, width, alpha); + p += hdl->width; + } while(--remain); + } + } +} + +void vram_fillex(VRAMHDL hdl, const RECT_T *rect, UINT32 color, UINT8 alpha) { + + int ptr; + int width; + int height; + int pos; + int remain; + UINT8 *p; +#ifdef SUPPORT_16BPP + int tmp; + int c16[3]; +#endif +#ifdef SUPPORT_24BPP + int c24[3]; +#endif +#ifdef SUPPORT_32BPP + int c32[3]; +#endif + + if (hdl == NULL) { + return; + } + if (rect == NULL) { + p = hdl->ptr; + remain = hdl->scrnsize; + switch(hdl->bpp) { +#ifdef SUPPORT_16BPP + case 16: + tmp = MAKE16PAL(color); + c16[0] = tmp & B16MASK; + c16[1] = tmp & G16MASK; + c16[2] = tmp & R16MASK; + tmp = 64 - alpha; + do { + UINT s, d; + s = *(UINT16 *)p; + d = MAKEALPHA16s(c16[0], s, B16MASK, tmp, 6); + d |= MAKEALPHA16s(c16[1], s, G16MASK, tmp, 6); + d |= MAKEALPHA16s(c16[2], s, R16MASK, tmp, 6); + *(UINT16 *)p = (UINT16)d; + p += 2; + } while(--remain); + break; +#endif +#ifdef SUPPORT_24BPP + case 24: + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + do { + p[0] = (UINT8)MAKEALPHA24(p[0], c24[0], alpha, 6); + p[1] = (UINT8)MAKEALPHA24(p[1], c24[1], alpha, 6); + p[2] = (UINT8)MAKEALPHA24(p[2], c24[2], alpha, 6); + p += 3; + } while(--remain); + break; +#endif +#ifdef SUPPORT_32BPP + case 32: + c32[0] = color & 0xff; + c32[1] = (color >> 8) & 0xff; + c32[2] = (color >> 16) & 0xff; + do { + p[0] = (UINT8)MAKEALPHA24(p[0], c32[0], alpha, 6); + p[1] = (UINT8)MAKEALPHA24(p[1], c32[1], alpha, 6); + p[2] = (UINT8)MAKEALPHA24(p[2], c32[2], alpha, 6); + p += 4; + } while(--remain); + break; +#endif + default: + TRACEOUT(("vram_fillex: unsupport %dbpp", hdl->bpp)); + break; + } + } + else { + pos = MAX(rect->left, 0); + ptr = pos; + width = MIN(rect->right, hdl->width) - pos; + pos = MAX(rect->top, 0); + ptr += pos * hdl->width; + height = MIN(rect->bottom, hdl->height) - pos; + if ((width > 0) && (height > 0)) { + p = hdl->ptr; + p += ptr * hdl->xalign; + switch(hdl->bpp) { +#ifdef SUPPORT_16BPP + case 16: + tmp = MAKE16PAL(color); + c16[0] = tmp & B16MASK; + c16[1] = tmp & G16MASK; + c16[2] = tmp & R16MASK; + tmp = 64 - alpha; + remain = height; + do { + int r = width; + do { + UINT s, d; + s = *(UINT16 *)p; + d = MAKEALPHA16s(c16[0], s, B16MASK, tmp, 6); + d |= MAKEALPHA16s(c16[1], s, G16MASK, tmp, 6); + d |= MAKEALPHA16s(c16[2], s, R16MASK, tmp, 6); + *(UINT16 *)p = (UINT16)d; + p += 2; + } while(--r); + p += hdl->yalign - (width * 2); + } while(--remain); + break; +#endif +#ifdef SUPPORT_24BPP + case 24: + remain = height; + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + do { + int r = width; + do { + p[0] = (UINT8)MAKEALPHA24(p[0], c24[0], alpha, 6); + p[1] = (UINT8)MAKEALPHA24(p[1], c24[1], alpha, 6); + p[2] = (UINT8)MAKEALPHA24(p[2], c24[2], alpha, 6); + p += 3; + } while(--r); + p += hdl->yalign - (width * 3); + } while(--remain); + break; +#endif +#ifdef SUPPORT_32BPP + case 32: + remain = height; + c32[0] = color & 0xff; + c32[1] = (color >> 8) & 0xff; + c32[2] = (color >> 16) & 0xff; + do { + int r = width; + do { + p[0] = (UINT8)MAKEALPHA24(p[0], c32[0], alpha, 6); + p[1] = (UINT8)MAKEALPHA24(p[1], c32[1], alpha, 6); + p[2] = (UINT8)MAKEALPHA24(p[2], c32[2], alpha, 6); + p += 4; + } while(--r); + p += hdl->yalign - (width * 4); + } while(--remain); + break; +#endif + default: + TRACEOUT(("vram_fillex: unsupport %dbpp", hdl->bpp)); + break; + } + } + } +} + +VRAMHDL vram_resize(VRAMHDL base, int width, int height, int bpp) { + + VRAMHDL ret; + RSZHDL rsz; + + if (base == NULL) { + goto vrs_err1; + } + ret = vram_create(width, height, (base->alpha != NULL), bpp); + if (ret == NULL) { + goto vrs_err1; + } + rsz = resize(width, height, base->width, base->height); + if (rsz == NULL) { + goto vrs_err2; + } + (*rsz->func)(rsz, resize_gettype(bpp, base->bpp), + ret->ptr, ret->yalign, base->ptr, base->yalign); + if (base->alpha) { + (*rsz->func)(rsz, RSZFN_8BPP, + ret->alpha, ret->width, base->alpha, base->width); + } + _MFREE(rsz); + return(ret); + +vrs_err2: + vram_destroy(ret); + +vrs_err1: + return(NULL); +} + +void vram_getrect(const VRAMHDL hdl, RECT_T *rct) { + + int x, y; + + if ((hdl) && (rct)) { + x = hdl->posx; + y = hdl->posy; + rct->left = x; + rct->top = y; + rct->right = x + hdl->width; + rct->bottom = y + hdl->height; + } +} + +VRAMHDL vram_dupe(const VRAMHDL hdl) { + + VRAMHDL ret = NULL; + int size; + int datsize; + + if (hdl == NULL) { + goto vd_exit; + } + datsize = hdl->scrnsize * hdl->xalign; + size = sizeof(_VRAMHDL); + size += datsize; + if (hdl->alpha) { + size += hdl->scrnsize; + } + ret = (VRAMHDL)_MALLOC(size, "VRAM copy"); + if (ret == NULL) { + goto vd_exit; + } + *ret = *hdl; + if (hdl->alpha) { + ret->alpha = (UINT8 *)(ret + 1); + CopyMemory(ret->alpha, hdl->alpha, hdl->scrnsize); + ret->ptr = ret->alpha + hdl->scrnsize; + } + else { + ret->ptr = (UINT8 *)(ret + 1); + } + CopyMemory(ret->ptr, hdl->ptr, datsize); + +vd_exit: + return(ret); +} + +BRESULT vram_cliprect(RECT_T *clip, const VRAMHDL vram, const RECT_T *rct) { + + if (vram == NULL) { + return(FAILURE); + } + if (rct == NULL) { + clip->left = 0; + clip->top = 0; + clip->right = vram->width; + clip->bottom = vram->height; + return(SUCCESS); + } + if ((rct->bottom <= 0) || (rct->right <= 0) || + (rct->left >= vram->width) || (rct->top >= vram->height)) { + return(FAILURE); + } + clip->left = MAX(rct->left, 0); + clip->top = MAX(rct->top, 0); + clip->right = MIN(rct->right, vram->width); + clip->bottom = MIN(rct->bottom, vram->height); + if ((clip->top >= clip->bottom) || (clip->left >= clip->right)) { + return(FAILURE); + } + return(SUCCESS); +} + +BRESULT vram_cliprectex(RECT_T *clip, const VRAMHDL vram, const RECT_T *rct) { + + if ((vram == NULL) || (clip == NULL)) { + return(FAILURE); + } + vram_getrect(vram, clip); + if (rct == NULL) { + return(SUCCESS); + } + clip->left = MAX(clip->left, rct->left); + clip->top = MAX(clip->top, rct->top); + clip->right = MIN(clip->right, rct->right); + clip->bottom = MIN(clip->bottom, rct->bottom); + if ((clip->left >= clip->right) || (clip->top >= clip->bottom)) { + return(FAILURE); + } + return(SUCCESS); +} + diff --git a/embed/vramhdl.h b/embed/vramhdl.h old mode 100755 new mode 100644 index 92c2ee7d..91044e1f --- a/embed/vramhdl.h +++ b/embed/vramhdl.h @@ -1,91 +1,91 @@ -#ifndef NP2_VRAMHDL_H -#define NP2_VRAMHDL_H - -#define DEFAULT_BPP 0 - -#define MAKEPALETTE(r, g, b) (((r) << 16) | ((g) << 8) | (b)) - - -#ifdef SUPPORT_16BPP -enum { - B16MASK = 0x001f, - G16MASK = 0x07e0, - R16MASK = 0xf800 -}; - -#define MAKE16PAL(c24) ((((c24) & 0x0000f8) >> 3) | \ - (((c24) & 0x00fc00) >> 5) | \ - (((c24) & 0xf80000) >> 8)) - -#define MAKE24B(c16) ((((c16) << 3) & 0xf8) | (((c16) >> 2) & 0x07)) -#define MAKE24G(c16) ((((c16) >> 3) & 0xfc) | (((c16) >> 9) & 0x03)) -#define MAKE24R(c16) ((((c16) >> 8) & 0xf8) | (((c16) >> 13) & 0x07)) - -#define MAKEALPHA16(d, s, m, a, b) ((((d) & (m)) + \ - ((((int)((s) & (m)) - (int)((d) & (m))) \ - * (a)) >> (b))) & (m)) - -#define MAKEALPHA16s(d, s, m, a, b) (((d) + \ - ((((int)((s) & (m)) - (int)(d)) \ - * (a)) >> (b))) & (m)) -#endif - -#if defined(SUPPORT_24BPP) || defined(SUPPORT_32BPP) -#define MAKEALPHA24(d, s, a, b) ((d) + \ - ((((int)(s) - (int)(d)) * (a)) >> (b))) -#endif - - -typedef struct { - int srcpos; - int dstpos; - int width; - int height; -} MIX_RECT; - -typedef struct { - int width; - int height; - int xalign; - int yalign; - int posx; - int posy; - int bpp; - int scrnsize; - UINT8 *ptr; - UINT8 *alpha; -} _VRAMHDL, *VRAMHDL; - - -#ifdef __cplusplus -extern "C" { -#endif - -VRAMHDL vram_create(int width, int height, BOOL alpha, int bpp); -void vram_destroy(VRAMHDL hdl); -BRESULT vram_allocalpha(VRAMHDL hdl); -void vram_zerofill(VRAMHDL hdl, const RECT_T *rect); -void vram_fill(VRAMHDL hdl, const RECT_T *rect, UINT32 color, UINT8 alpha); -void vram_filldat(VRAMHDL hdl, const RECT_T *rect, UINT32 color); -void vram_fillalpha(VRAMHDL hdl, const RECT_T *rect, UINT8 alpha); -void vram_fillex(VRAMHDL hdl, const RECT_T *rect, UINT32 color, UINT8 alpha); - -VRAMHDL vram_resize(VRAMHDL base, int width, int height, int bpp); - -void vram_getrect(const VRAMHDL hdl, RECT_T *rect); - -VRAMHDL vram_dupe(const VRAMHDL hdl); -BRESULT vram_cliprect(RECT_T *clip, const VRAMHDL vram, const RECT_T *rct); -BRESULT vram_cliprectex(RECT_T *clip, const VRAMHDL vram, const RECT_T *rct); - -#ifdef __cplusplus -} -#endif - - -// ---- macros - -#define VRAM_RELEASE(a) { VRAMHDL v; v = (a); (a) = NULL; vram_destroy(v); } - -#endif /* NP2_VRAMHDL_H */ - +#ifndef NP2_VRAMHDL_H +#define NP2_VRAMHDL_H + +#define DEFAULT_BPP 0 + +#define MAKEPALETTE(r, g, b) (((r) << 16) | ((g) << 8) | (b)) + + +#ifdef SUPPORT_16BPP +enum { + B16MASK = 0x001f, + G16MASK = 0x07e0, + R16MASK = 0xf800 +}; + +#define MAKE16PAL(c24) ((((c24) & 0x0000f8) >> 3) | \ + (((c24) & 0x00fc00) >> 5) | \ + (((c24) & 0xf80000) >> 8)) + +#define MAKE24B(c16) ((((c16) << 3) & 0xf8) | (((c16) >> 2) & 0x07)) +#define MAKE24G(c16) ((((c16) >> 3) & 0xfc) | (((c16) >> 9) & 0x03)) +#define MAKE24R(c16) ((((c16) >> 8) & 0xf8) | (((c16) >> 13) & 0x07)) + +#define MAKEALPHA16(d, s, m, a, b) ((((d) & (m)) + \ + ((((int)((s) & (m)) - (int)((d) & (m))) \ + * (a)) >> (b))) & (m)) + +#define MAKEALPHA16s(d, s, m, a, b) (((d) + \ + ((((int)((s) & (m)) - (int)(d)) \ + * (a)) >> (b))) & (m)) +#endif + +#if defined(SUPPORT_24BPP) || defined(SUPPORT_32BPP) +#define MAKEALPHA24(d, s, a, b) ((d) + \ + ((((int)(s) - (int)(d)) * (a)) >> (b))) +#endif + + +typedef struct { + int srcpos; + int dstpos; + int width; + int height; +} MIX_RECT; + +typedef struct { + int width; + int height; + int xalign; + int yalign; + int posx; + int posy; + int bpp; + int scrnsize; + UINT8 *ptr; + UINT8 *alpha; +} _VRAMHDL, *VRAMHDL; + + +#ifdef __cplusplus +extern "C" { +#endif + +VRAMHDL vram_create(int width, int height, BOOL alpha, int bpp); +void vram_destroy(VRAMHDL hdl); +BRESULT vram_allocalpha(VRAMHDL hdl); +void vram_zerofill(VRAMHDL hdl, const RECT_T *rect); +void vram_fill(VRAMHDL hdl, const RECT_T *rect, UINT32 color, UINT8 alpha); +void vram_filldat(VRAMHDL hdl, const RECT_T *rect, UINT32 color); +void vram_fillalpha(VRAMHDL hdl, const RECT_T *rect, UINT8 alpha); +void vram_fillex(VRAMHDL hdl, const RECT_T *rect, UINT32 color, UINT8 alpha); + +VRAMHDL vram_resize(VRAMHDL base, int width, int height, int bpp); + +void vram_getrect(const VRAMHDL hdl, RECT_T *rect); + +VRAMHDL vram_dupe(const VRAMHDL hdl); +BRESULT vram_cliprect(RECT_T *clip, const VRAMHDL vram, const RECT_T *rct); +BRESULT vram_cliprectex(RECT_T *clip, const VRAMHDL vram, const RECT_T *rct); + +#ifdef __cplusplus +} +#endif + + +// ---- macros + +#define VRAM_RELEASE(a) { VRAMHDL v; v = (a); (a) = NULL; vram_destroy(v); } + +#endif /* NP2_VRAMHDL_H */ + diff --git a/embed/vrammix.c b/embed/vrammix.c old mode 100755 new mode 100644 index f6144294..ab797169 --- a/embed/vrammix.c +++ b/embed/vrammix.c @@ -1,3841 +1,3841 @@ -#include -#include -#include -#include - - -enum { - VRAMALPHABASE = (1 << VRAMALPHABIT) - VRAMALPHA, - FDATDEPTHBASE = (1 << FDAT_DEPTHBIT) - FDAT_DEPTH -}; - - -static BRESULT cpyrect(MIX_RECT *r, const VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct) { - - POINT_T p; - int width; - int height; - - if ((dst == NULL) || (src == NULL)) { - return(FAILURE); - } - if (pt) { - p = *pt; - } - else { - p.x = 0; - p.y = 0; - } - r->srcpos = 0; - if (rct) { - width = MIN(rct->right, src->width); - if (rct->left >= 0) { - r->srcpos += rct->left; - width -= rct->left; - } - else { - p.x -= rct->left; - } - height = MIN(rct->bottom, src->height); - if (rct->top >= 0) { - r->srcpos += rct->top * src->width; - height -= rct->top; - } - else { - p.y -= rct->top; - } - } - else { - width = src->width; - height = src->height; - } - - r->dstpos = 0; - r->width = MIN(width + p.x, dst->width); - if (p.x > 0) { - r->dstpos += p.x; - r->width = MIN(r->width, dst->width) - p.x; - } - else { - r->srcpos -= p.x; - } - if (r->width <= 0) { - return(FAILURE); - } - - r->height = MIN(height + p.y, dst->height); - if (p.y > 0) { - r->dstpos += p.y * dst->width; - r->height = MIN(r->height, dst->height) - p.y; - } - else { - r->srcpos -= p.y * src->width; - } - if (r->height <= 0) { - return(FAILURE); - } - return(SUCCESS); -} - -static BRESULT mixrect(MIX_RECT *r, const VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt) { - - int pos; - RECT_T s; - - if ((dst == NULL) || (src == NULL)) { - return(FAILURE); - } - r->srcpos = 0; - if (rct == NULL) { - s.left = 0; - s.top = 0; - s.right = dst->width; - s.bottom = dst->height; - r->dstpos = 0; - } - else { - if ((rct->bottom <= 0) || (rct->right <= 0) || - (rct->left >= dst->width) || (rct->top >= dst->height)) { - return(FAILURE); - } - s.left = MAX(rct->left, 0); - s.top = MAX(rct->top, 0); - s.right = MIN(rct->right, dst->width); - s.bottom = MIN(rct->bottom, dst->height); - if ((s.top >= s.bottom) || (s.left >= s.right)) { - return(FAILURE); - } - r->dstpos = s.top * dst->width; - r->dstpos += s.left; - } - - pos = src->posy - s.top; - if (pt) { - pos += pt->y; - } - if (pos < 0) { - r->srcpos -= pos * src->width; - r->height = MIN(src->height + pos, s.bottom - s.top); - } - else { - r->dstpos += pos * dst->width; - r->height = MIN(s.bottom - s.top - pos, src->height); - } - if (r->height <= 0) { - return(FAILURE); - } - - pos = src->posx - s.left; - if (pt) { - pos += pt->x; - } - if (pos < 0) { - r->srcpos -= pos; - r->width = MIN(src->width + pos, s.right - s.left); - } - else { - r->dstpos += pos; - r->width = MIN(s.right - s.left - pos, src->width); - } - if (r->width <= 0) { - return(FAILURE); - } - return(SUCCESS); -} - - -// ---- - -typedef struct { - int orgpos; - int srcpos; - int dstpos; - int width; - int height; -} MIXRECTEX; - -static BRESULT cpyrectex(MIXRECTEX *r, const VRAMHDL dst, const POINT_T *pt, - const VRAMHDL org, const VRAMHDL src, const RECT_T *rct) { - - POINT_T p; - int width; - int height; - int dstwidth; - int dstheight; - - if ((dst == NULL) || (org == NULL) || (src == NULL) || - (dst->bpp != org->bpp) || (dst->bpp != src->bpp)) { - return(FAILURE); - } - if (pt) { - p = *pt; - } - else { - p.x = 0; - p.y = 0; - } - - r->srcpos = 0; - if (rct) { - width = MIN(rct->right, src->width); - if (rct->left >= 0) { - r->srcpos += rct->left; - width -= rct->left; - } - else { - p.x -= rct->left; - } - height = MIN(rct->bottom, src->height); - if (rct->top >= 0) { - r->srcpos += rct->top * src->width; - height -= rct->top; - } - else { - p.y -= rct->top; - } - } - else { - width = src->width; - height = src->height; - } - - r->orgpos = 0; - r->dstpos = 0; - dstwidth = MIN(dst->width, org->width); - r->width = MIN(width + p.x, dstwidth); - if (p.x > 0) { - r->orgpos += p.x; - r->dstpos += p.x; - r->width = MIN(r->width, dstwidth) - p.x; - } - else { - r->srcpos -= p.x; - } - if (r->width <= 0) { - return(FAILURE); - } - - dstheight = MIN(dst->height, org->height); - r->height = MIN(height + p.y, dstheight); - if (p.y > 0) { - r->orgpos += p.y * org->width; - r->dstpos += p.y * dst->width; - r->height = MIN(r->height, dstheight) - p.y; - } - else { - r->srcpos -= p.y * src->width; - } - if (r->height <= 0) { - return(FAILURE); - } - return(SUCCESS); -} - -static BRESULT mixrectex(MIXRECTEX *r, const VRAMHDL dst, const VRAMHDL org, - const RECT_T *rct, const VRAMHDL src, const POINT_T *pt) { - - int pos; - RECT_T s; - int dstwidth; - int dstheight; - - if ((dst == NULL) || (org == NULL) || (src == NULL) || - (dst->bpp != org->bpp) || (dst->bpp != src->bpp)) { - return(FAILURE); - } - dstwidth = MIN(dst->width, org->width); - dstheight = MIN(dst->height, org->height); - r->srcpos = 0; - if (rct == NULL) { - s.left = 0; - s.top = 0; - s.right = dstwidth; - s.bottom = dstheight; - r->orgpos = 0; - r->dstpos = 0; - } - else { - if ((rct->bottom <= 0) || (rct->right <= 0) || - (rct->left >= dstwidth) || (rct->top >= dstheight)) { - return(FAILURE); - } - s.left = MAX(rct->left, 0); - s.top = MAX(rct->top, 0); - s.right = MIN(rct->right, dstwidth); - s.bottom = MIN(rct->bottom, dstheight); - if ((s.top >= s.bottom) || (s.left >= s.right)) { - return(FAILURE); - } - r->orgpos = s.top * org->width; - r->orgpos += s.left; - r->dstpos = s.top * dst->width; - r->dstpos += s.left; - } - - pos = src->posy - s.top; - if (pt) { - pos += pt->y; - } - if (pos < 0) { - r->srcpos -= pos * src->width; - r->height = MIN(src->height + pos, s.bottom - s.top); - } - else { - r->orgpos += pos * org->width; - r->dstpos += pos * dst->width; - r->height = MIN(s.bottom - s.top - pos, src->height); - } - if (r->height <= 0) { - return(FAILURE); - } - - pos = src->posx - s.left; - if (pt) { - pos += pt->x; - } - if (pos < 0) { - r->srcpos -= pos; - r->width = MIN(src->width + pos, s.right - s.left); - } - else { - r->orgpos += pos; - r->dstpos += pos; - r->width = MIN(s.right - s.left - pos, src->width); - } - if (r->width <= 0) { - return(FAILURE); - } - return(SUCCESS); -} - - -// ---- - -static void vramsub_cpy(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - - p = src->ptr + (mr->srcpos * src->xalign); - q = dst->ptr + (mr->dstpos * src->xalign); - do { - CopyMemory(q, p, mr->width * src->xalign); - p += src->yalign; - q += dst->yalign; - } while(--mr->height); -} - -static void vramsub_move(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int align; - int r; - - align = mr->width * src->xalign; - p = src->ptr + (mr->srcpos * src->xalign); - q = dst->ptr + (mr->dstpos * src->xalign); - if ((src->ptr != dst->ptr) || (p >= q)) { - do { - CopyMemory(q, p, align); - p += src->yalign; - q += dst->yalign; - } while(--mr->height); - } - else { - p += (mr->height * src->yalign); - q += (mr->height * dst->yalign); - do { - p -= src->yalign - align; - q -= dst->yalign - align; - r = align; - do { - p--; - q--; - *q = *p; - } while(--r); - } while(--mr->height); - } -} -static void vramsub_cpyall(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int height; - - p = src->ptr + (mr->srcpos * src->xalign); - q = dst->ptr + (mr->dstpos * src->xalign); - height = mr->height; - do { - CopyMemory(q, p, mr->width * src->xalign); - p += src->yalign; - q += dst->yalign; - } while(--height); - if ((src->alpha) && (dst->alpha)) { - p = src->alpha + mr->srcpos; - q = dst->alpha + mr->dstpos; - do { - CopyMemory(q, p, mr->width); - p += src->width; - q += dst->width; - } while(--mr->height); - } -} - -static void vramsub_cpy2(VRAMHDL dst, const VRAMHDL src, UINT alpha, - MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT8 *r; - - p = src->ptr + (mr->srcpos * src->xalign); - q = dst->ptr + (mr->dstpos * src->xalign); - r = dst->alpha + mr->dstpos; - do { - CopyMemory(q, p, mr->width * src->xalign); - FillMemory(r, mr->width, alpha); - p += src->yalign; - q += dst->yalign; - r += dst->width; - } while(--mr->height); -} - - -// ---- bpp=16 - -#ifdef SUPPORT_16BPP - -static void vramsub_cpyp16(VRAMHDL dst, const VRAMHDL src, const UINT8 *pat8, - MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int posx; - int posy; - - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - posx = mr->dstpos % dst->width; - posy = mr->dstpos / dst->width; - step = mr->width * 2; - - do { - UINT pat; - x = mr->width; - pat = pat8[posy & 7]; - posy++; - pat <<= (posx & 7); - pat |= (pat >> 8); - do { - pat <<= 1; - if (pat & 0x100) { - *(UINT16 *)q = *(UINT16 *)p; - pat++; - } - p += 2; - q += 2; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyp16w16(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int posx; - - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - posx = mr->dstpos % dst->width; - step = mr->width * 2; - - do { - UINT32 pat; - x = mr->width; - pat = pat16; - pat |= (pat << 16); - pat >>= (posx & 15); - do { - if (pat & 1) { - *(UINT16 *)q = *(UINT16 *)p; - pat |= 0x10000; - } - pat >>= 1; - p += 2; - q += 2; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyp16h16(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int step; - int posy; - - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - posy = mr->dstpos / dst->width; - step = mr->width * 2; - - do { - if (pat16 & (1 << (posy & 15))) { - CopyMemory(q, p, step); - } - posy++; - p += src->yalign; - q += dst->yalign; - } while(--mr->height); -} - -static void vramsub_cpyex16(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - step = mr->width * 2; - - do { - x = mr->width; - do { - UINT16 dat; - dat = *(UINT16 *)p; - p += 2; - if (dat) { - *(UINT16 *)q = dat; - } - q += 2; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyex16a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - - a = src->alpha + mr->srcpos; - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - step = mr->width * 2; - - do { - x = mr->width; - do { - UINT alpha; - alpha = *a++; - if (alpha) { - UINT s1, s2, d; - s1 = *(UINT16 *)p; - s2 = *(UINT16 *)q; - alpha += VRAMALPHABASE; - d = MAKEALPHA16(s2, s1, B16MASK, alpha, VRAMALPHABIT); - d |= MAKEALPHA16(s2, s1, G16MASK, alpha, VRAMALPHABIT); - d |= MAKEALPHA16(s2, s1, R16MASK, alpha, VRAMALPHABIT); - *(UINT16 *)q = (UINT16)d; - } - p += 2; - q += 2; - } while(--x); - a += src->width - mr->width; - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyex16a2(VRAMHDL dst, const VRAMHDL src, - UINT alpha64, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - - a = src->alpha + mr->srcpos; - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - step = mr->width * 2; - - do { - x = mr->width; - do { - UINT alpha; - alpha = *a++; - if (alpha) { - UINT s1, s2, d; - alpha = (alpha + VRAMALPHABASE) * alpha64; - s1 = *(UINT16 *)p; - s2 = *(UINT16 *)q; - d = MAKEALPHA16(s2, s1, B16MASK, alpha, VRAMALPHABIT+6); - d |= MAKEALPHA16(s2, s1, G16MASK, alpha, VRAMALPHABIT+6); - d |= MAKEALPHA16(s2, s1, R16MASK, alpha, VRAMALPHABIT+6); - *(UINT16 *)q = (UINT16)d; - } - p += 2; - q += 2; - } while(--x); - a += src->width - mr->width; - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyexa16a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - UINT8 *b; - int x; - int step; - - p = src->ptr + (mr->srcpos * 2); - a = src->alpha + mr->srcpos; - q = dst->ptr + (mr->dstpos * 2); - b = dst->alpha + mr->dstpos; - step = mr->width * 2; - - do { - x = mr->width; - do { - UINT alpha; - alpha = *a++; - if (alpha) { - UINT s1, s2, d; - s1 = *(UINT16 *)p; - s2 = *(UINT16 *)q; - alpha += VRAMALPHABASE; - d = MAKEALPHA16(s2, s1, B16MASK, alpha, VRAMALPHABIT); - d |= MAKEALPHA16(s2, s1, G16MASK, alpha, VRAMALPHABIT); - d |= MAKEALPHA16(s2, s1, R16MASK, alpha, VRAMALPHABIT); - *(UINT16 *)q = (UINT16)d; - b[0] = VRAMALPHA; - } - p += 2; - q += 2; - b += 1; - } while(--x); - p += src->yalign - step; - a += src->width - mr->width; - q += dst->yalign - step; - b += dst->width - mr->width; - } while(--mr->height); -} - -static void vramsub_cpya16(VRAMHDL dst, const VRAMHDL src, - UINT alpha256, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - step = mr->width * 2; - - do { - x = mr->width; - do { - UINT s1, s2, d; - s1 = *(UINT16 *)p; - s2 = *(UINT16 *)q; - d = MAKEALPHA16(s2, s1, B16MASK, alpha256, 8); - d |= MAKEALPHA16(s2, s1, G16MASK, alpha256, 8); - d |= MAKEALPHA16(s2, s1, R16MASK, alpha256, 8); - *(UINT16 *)q = (UINT16)d; - p += 2; - q += 2; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyexp16w16(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - int posx; - - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - a = src->alpha + mr->srcpos; - posx = mr->dstpos % dst->width; - step = mr->width * 2; - - do { - UINT32 pat; - x = mr->width; - pat = pat16; - pat |= (pat << 16); - pat >>= (posx & 15); - do { - if (pat & 1) { - UINT alpha; - alpha = *a; - if (alpha) { - UINT s1, s2, d; - s1 = *(UINT16 *)p; - s2 = *(UINT16 *)q; - alpha += VRAMALPHABASE; - d = MAKEALPHA16(s2, s1, B16MASK, alpha, VRAMALPHABIT); - d |= MAKEALPHA16(s2, s1, G16MASK, alpha, VRAMALPHABIT); - d |= MAKEALPHA16(s2, s1, R16MASK, alpha, VRAMALPHABIT); - *(UINT16 *)q = (UINT16)d; - } - pat |= 0x10000; - } - pat >>= 1; - p += 2; - q += 2; - a += 1; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - a += src->width - mr->width; - } while(--mr->height); -} - -static void vramsub_cpyexp16h16(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - int posy; - - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - a = src->alpha + mr->srcpos; - posy = mr->dstpos / dst->width; - step = mr->width * 2; - - do { - if (pat16 & (1 << (posy & 15))) { - x = mr->width; - do { - UINT alpha; - alpha = *a; - if (alpha) { - UINT s1, s2, d; - s1 = *(UINT16 *)p; - s2 = *(UINT16 *)q; - alpha += VRAMALPHABASE; - d = MAKEALPHA16(s2, s1, B16MASK, alpha, VRAMALPHABIT); - d |= MAKEALPHA16(s2, s1, G16MASK, alpha, VRAMALPHABIT); - d |= MAKEALPHA16(s2, s1, R16MASK, alpha, VRAMALPHABIT); - *(UINT16 *)q = (UINT16)d; - } - p += 2; - q += 2; - a += 1; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - a += src->width - mr->width; - } - else { - p += src->yalign; - q += dst->yalign; - a += src->width; - } - posy++; - } while(--mr->height); -} - -static void vramsub_mix16(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, - UINT alpha64, MIXRECTEX *mr) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int x; - int ostep; - int sstep; - int dstep; - - p = org->ptr + (mr->orgpos * 2); - q = src->ptr + (mr->srcpos * 2); - r = dst->ptr + (mr->dstpos * 2); - ostep = org->yalign - (mr->width * 2); - sstep = src->yalign - (mr->width * 2); - dstep = dst->yalign - (mr->width * 2); - - do { - x = mr->width; - do { - UINT s1, s2, d; - s1 = *(UINT16 *)p; - s2 = *(UINT16 *)q; - d = MAKEALPHA16(s1, s2, B16MASK, alpha64, 6); - d |= MAKEALPHA16(s1, s2, G16MASK, alpha64, 6); - d |= MAKEALPHA16(s1, s2, R16MASK, alpha64, 6); - *(UINT16 *)r = (UINT16)d; - p += 2; - q += 2; - r += 2; - } while(--x); - p += ostep; - q += sstep; - r += dstep; - } while(--mr->height); -} - -static void vramsub_mixcol16(VRAMHDL dst, const VRAMHDL src, UINT32 color, - UINT alpha64, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int tmp; - int c16[3]; - - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - step = mr->width * 2; - - tmp = MAKE16PAL(color); - c16[0] = tmp & B16MASK; - c16[1] = tmp & G16MASK; - c16[2] = tmp & R16MASK; - do { - x = mr->width; - do { - UINT s, d; - s = *(UINT16 *)p; - d = MAKEALPHA16s(c16[0], s, B16MASK, alpha64, 6); - d |= MAKEALPHA16s(c16[1], s, G16MASK, alpha64, 6); - d |= MAKEALPHA16s(c16[2], s, R16MASK, alpha64, 6); - *(UINT16 *)q = (UINT16)d; - p += 2; - q += 2; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_mixalpha16(VRAMHDL dst, const VRAMHDL src, UINT32 color, - MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int tmp; - int c16[3]; - - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - step = mr->width * 2; - - tmp = MAKE16PAL(color); - c16[0] = tmp & B16MASK; - c16[1] = tmp & G16MASK; - c16[2] = tmp & R16MASK; - do { - x = mr->width; - do { - UINT s, d, e; - int a; - s = *(UINT16 *)q; - e = *(UINT16 *)p; - e ^= 0xffff; - a = e & 0x1f; - if (a) { - a++; - } - d = MAKEALPHA16s(c16[0], s, B16MASK, a, 5); - a = (e >> 5) & 0x3f; - if (a) { - a++; - } - d |= MAKEALPHA16s(c16[1], s, G16MASK, a, 6); - a = (e >> 11) & 0x1f; - if (a) { - a++; - } - d |= MAKEALPHA16s(c16[2], s, R16MASK, a, 5); - *(UINT16 *)q = (UINT16)d; - p += 2; - q += 2; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_gray16(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, - const VRAMHDL bmp, int delta, MIXRECTEX *mr) { - -const UINT8 *p; -const UINT8 *q; -const UINT8 *a; - UINT8 *r; - int rm; - int x, y; - int ostep; - int sstep; - int dstep; - int xstep; - int ystep; - - if ((bmp == NULL) || (bmp->bpp != 8)) { - return; - } - - p = org->ptr + (mr->orgpos * 2); - q = src->ptr + (mr->srcpos * 2); - r = dst->ptr + (mr->dstpos * 2); - ostep = org->yalign - (mr->width * 2); - sstep = src->yalign - (mr->width * 2); - dstep = dst->yalign - (mr->width * 2); - - xstep = (bmp->width << 10) / mr->width; - ystep = (bmp->height << 10) / mr->height; - - y = 0; - do { - a = bmp->ptr + ((y >> 10) * bmp->yalign); - rm = mr->width; - x = 0; - do { - int alpha; - alpha = a[x >> 10] + delta + 1; - if (alpha >= 256) { - *(UINT16 *)r = *(UINT16 *)q; - } - else if (alpha > 0) { - UINT s1, s2, d; - s1 = *(UINT16 *)p; - s2 = *(UINT16 *)q; - d = MAKEALPHA16(s1, s2, B16MASK, alpha, 8); - d |= MAKEALPHA16(s1, s2, G16MASK, alpha, 8); - d |= MAKEALPHA16(s1, s2, R16MASK, alpha, 8); - *(UINT16 *)r = (UINT16)d; - } - else { - *(UINT16 *)r = *(UINT16 *)p; - } - p += 2; - q += 2; - r += 2; - x += xstep; - } while(--rm); - p += ostep; - q += sstep; - r += dstep; - y += ystep; - } while(--mr->height); -} - -static void vramsub_zoom16(VRAMHDL dst, const VRAMHDL src, int dot, - MIX_RECT *mr) { - -const UINT8 *pbase; -const UINT8 *p; - UINT8 *qbase; - UINT8 *q; - int x; - int dstep; - int xstep; - int ystep; - int xx; - int yy; - int xstep2; - UINT16 col; - - pbase = src->ptr + (mr->srcpos * 2); - qbase = dst->ptr + (mr->dstpos * 2); - dstep = (dst->yalign * dot) - (mr->width * 2); - - do { - p = pbase; - ystep = MIN(mr->height, dot); - x = mr->width; - do { - xstep = MIN(x, dot); - xstep2 = xstep * 2; - q = qbase; - yy = ystep; - col = *(UINT16 *)p; - do { - xx = xstep; - do { - *(UINT16 *)q = col; - q += 2; - } while(--xx); - q += dst->yalign; - q -= xstep2; - } while(--yy); - p += 2; - qbase += xstep2; - x -= xstep; - } while(x); - pbase += src->yalign; - qbase += dstep; - mr->height -= ystep; - } while(mr->height); -} - -static void vramsub_mosaic16(VRAMHDL dst, const VRAMHDL src, int dot, - MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT8 *r; - int x; - int sstep; - int dstep; - int xstep; - int ystep; - int xx; - int yy; - int xstep2; - UINT16 col; - - p = src->ptr + (mr->srcpos * 2); - q = dst->ptr + (mr->dstpos * 2); - sstep = (src->yalign * dot) - (mr->width * 2); - dstep = (dst->yalign * dot) - (mr->width * 2); - - do { - ystep = MIN(mr->height, dot); - x = mr->width; - do { - xstep = MIN(x, dot); - xstep2 = xstep * 2; - r = q; - yy = ystep; - col = *(UINT16 *)p; - do { - xx = xstep; - do { - *(UINT16 *)r = col; - r += 2; - } while(--xx); - r += dst->yalign; - r -= xstep2; - } while(--yy); - p += xstep2; - q += xstep2; - x -= xstep; - } while(x); - p += sstep; - q += dstep; - mr->height -= ystep; - } while(mr->height); -} - -static void vramsub_colex16(VRAMHDL dst, const VRAMHDL src, UINT32 color, - MIX_RECT *mr) { - - UINT8 *p, *q; - int x; - int step; - UINT tmp; - int c16[3]; - int a; - - tmp = MAKE16PAL(color); - c16[0] = tmp & B16MASK; - c16[1] = tmp & G16MASK; - c16[2] = tmp & R16MASK; - - p = src->ptr + mr->srcpos; - q = dst->ptr + (mr->dstpos * 2); - step = mr->width * 2; - - do { - x = mr->width; - do { - a = p[0]; - if (a) { - UINT s, d; - a = VRAMALPHA - a; - s = *(UINT16 *)q; - d = MAKEALPHA16s(c16[0], s, B16MASK, a, VRAMALPHABIT); - d |= MAKEALPHA16s(c16[1], s, G16MASK, a, VRAMALPHABIT); - d |= MAKEALPHA16s(c16[2], s, R16MASK, a, VRAMALPHABIT); - *(UINT16 *)q = (UINT16)d; - } - p += 1; - q += 2; - } while(--x); - p += src->width - mr->width; - q += dst->yalign - step; - } while(--mr->height); -} -#endif - - -// ---- bpp=24 - -#ifdef SUPPORT_24BPP - -static void vramsub_cpyp24(VRAMHDL dst, const VRAMHDL src, const UINT8 *pat8, - MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int posx; - int posy; - - p = src->ptr + (mr->srcpos * 3); - q = dst->ptr + (mr->dstpos * 3); - posx = mr->dstpos % dst->width; - posy = mr->dstpos / dst->width; - step = mr->width * 3; - - do { - UINT pat; - x = mr->width; - pat = pat8[posy & 7]; - posy++; - pat <<= (posx & 7); - pat |= (pat >> 8); - do { - pat <<= 1; - if (pat & 0x100) { - q[0] = p[0]; - q[1] = p[1]; - q[2] = p[2]; - pat++; - } - p += 3; - q += 3; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyp16w24(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int posx; - - p = src->ptr + (mr->srcpos * 3); - q = dst->ptr + (mr->dstpos * 3); - posx = mr->dstpos % dst->width; - step = mr->width * 3; - - do { - UINT32 pat; - x = mr->width; - pat = pat16; - pat |= (pat << 16); - pat >>= (posx & 15); - do { - if (pat & 1) { - q[0] = p[0]; - q[1] = p[1]; - q[2] = p[2]; - pat |= 0x10000; - } - pat >>= 1; - p += 3; - q += 3; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyp16h24(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int step; - int posy; - - p = src->ptr + (mr->srcpos * 3); - q = dst->ptr + (mr->dstpos * 3); - posy = mr->dstpos / dst->width; - step = mr->width * 3; - - do { - if (pat16 & (1 << (posy & 15))) { - CopyMemory(q, p, step); - } - posy++; - p += src->yalign; - q += dst->yalign; - } while(--mr->height); -} - -static void vramsub_cpyex24(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - - p = src->ptr + (mr->srcpos * src->xalign); - q = dst->ptr + (mr->dstpos * src->xalign); - step = mr->width * 3; - - do { - x = mr->width; - do { - UINT8 r, g, b; - b = p[0]; - g = p[1]; - r = p[2]; - p += 3; - if ((b) || (g) || (r)) { - q[0] = b; - q[1] = g; - q[2] = r; - } - q += 3; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyex24a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - - a = src->alpha + mr->srcpos; - p = src->ptr + (mr->srcpos * 3); - q = dst->ptr + (mr->dstpos * 3); - step = mr->width * 3; - - do { - x = mr->width; - do { - UINT alpha; - alpha = *a++; - if (alpha) { - alpha += VRAMALPHABASE; - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); - } - p += 3; - q += 3; - } while(--x); - a += src->width - mr->width; - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyex24a2(VRAMHDL dst, const VRAMHDL src, - UINT alpha64, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - - a = src->alpha + mr->srcpos; - p = src->ptr + (mr->srcpos * 3); - q = dst->ptr + (mr->dstpos * 3); - step = mr->width * 3; - - do { - x = mr->width; - do { - UINT alpha; - alpha = *a++; - if (alpha) { - alpha = (alpha + VRAMALPHABASE) * alpha64; - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT+6); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT+6); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT+6); - } - p += 3; - q += 3; - } while(--x); - a += src->width - mr->width; - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyexa24a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - UINT8 *b; - int x; - int step; - - p = src->ptr + (mr->srcpos * 3); - a = src->alpha + mr->srcpos; - q = dst->ptr + (mr->dstpos * 3); - b = dst->alpha + mr->dstpos; - step = mr->width * 3; - - do { - x = mr->width; - do { - UINT alpha; - alpha = *a++; - if (alpha) { - alpha += VRAMALPHABASE; - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); - b[0] = VRAMALPHA; - } - p += 3; - q += 3; - b += 1; - } while(--x); - p += src->yalign - step; - a += src->width - mr->width; - q += dst->yalign - step; - b += dst->width - mr->width; - } while(--mr->height); -} - -static void vramsub_cpya24(VRAMHDL dst, const VRAMHDL src, - UINT alpha256, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - - p = src->ptr + (mr->srcpos * 3); - q = dst->ptr + (mr->dstpos * 3); - step = mr->width * 3; - - do { - x = mr->width; - do { - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha256, 8); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha256, 8); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha256, 8); - p += 3; - q += 3; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyexp16w24(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - int posx; - - p = src->ptr + (mr->srcpos * 3); - q = dst->ptr + (mr->dstpos * 3); - a = src->alpha + mr->srcpos; - posx = mr->dstpos % dst->width; - step = mr->width * 3; - - do { - UINT32 pat; - x = mr->width; - pat = pat16; - pat |= (pat << 16); - pat >>= (posx & 15); - do { - if (pat & 1) { - UINT alpha; - alpha = *a; - if (alpha) { - alpha += VRAMALPHABASE; - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); - } - pat |= 0x10000; - } - pat >>= 1; - p += 3; - q += 3; - a += 1; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - a += src->width - mr->width; - } while(--mr->height); -} - -static void vramsub_cpyexp16h24(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - int posy; - - p = src->ptr + (mr->srcpos * 3); - q = dst->ptr + (mr->dstpos * 3); - a = src->alpha + mr->srcpos; - posy = mr->dstpos / dst->width; - step = mr->width * 3; - - do { - if (pat16 & (1 << (posy & 15))) { - x = mr->width; - do { - UINT alpha; - alpha = *a; - if (alpha) { - alpha += VRAMALPHABASE; - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); - } - p += 3; - q += 3; - a += 1; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - a += src->width - mr->width; - } - else { - p += src->yalign; - q += dst->yalign; - a += src->width; - } - posy++; - } while(--mr->height); -} - -static void vramsub_mix24(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, - UINT alpha64, MIXRECTEX *mr) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int x; - int ostep; - int sstep; - int dstep; - - p = org->ptr + (mr->orgpos * 3); - q = src->ptr + (mr->srcpos * 3); - r = dst->ptr + (mr->dstpos * 3); - ostep = org->yalign - (mr->width * 3); - sstep = src->yalign - (mr->width * 3); - dstep = dst->yalign - (mr->width * 3); - - do { - x = mr->width; - do { - r[0] = (UINT8)MAKEALPHA24(p[0], q[0], alpha64, 6); - r[1] = (UINT8)MAKEALPHA24(p[1], q[1], alpha64, 6); - r[2] = (UINT8)MAKEALPHA24(p[2], q[2], alpha64, 6); - p += 3; - q += 3; - r += 3; - } while(--x); - p += ostep; - q += sstep; - r += dstep; - } while(--mr->height); -} - -static void vramsub_mixcol24(VRAMHDL dst, const VRAMHDL src, UINT32 color, - UINT alpha64, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int c24[3]; - - p = src->ptr + (mr->srcpos * 3); - q = dst->ptr + (mr->dstpos * 3); - step = mr->width * 3; - - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - do { - x = mr->width; - do { - q[0] = (UINT8)MAKEALPHA24(c24[0], p[0], alpha64, 6); - q[1] = (UINT8)MAKEALPHA24(c24[1], p[1], alpha64, 6); - q[2] = (UINT8)MAKEALPHA24(c24[2], p[2], alpha64, 6); - p += 3; - q += 3; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_mixalpha24(VRAMHDL dst, const VRAMHDL src, UINT32 color, - MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int c24[3]; - - p = src->ptr + (mr->srcpos * src->xalign); - q = dst->ptr + (mr->dstpos * src->xalign); - step = mr->width * 3; - - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - do { - x = mr->width; - do { - int a; - a = p[0]; - if (a) { - a++; - } - q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], a, 8); - a = p[1]; - if (a) { - a++; - } - q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], a, 8); - a = p[2]; - if (a) { - a++; - } - q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], a, 8); - p += 3; - q += 3; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_gray24(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, - const VRAMHDL bmp, int delta, MIXRECTEX *mr) { - -const UINT8 *p; -const UINT8 *q; -const UINT8 *a; - UINT8 *r; - int rm; - int x, y; - int ostep; - int sstep; - int dstep; - int xstep; - int ystep; - - if ((bmp == NULL) || (bmp->bpp != 8)) { - return; - } - - p = org->ptr + (mr->orgpos * 3); - q = src->ptr + (mr->srcpos * 3); - r = dst->ptr + (mr->dstpos * 3); - ostep = org->yalign - (mr->width * 3); - sstep = src->yalign - (mr->width * 3); - dstep = dst->yalign - (mr->width * 3); - - xstep = (bmp->width << 10) / mr->width; - ystep = (bmp->height << 10) / mr->height; - - y = 0; - do { - a = bmp->ptr + ((y >> 10) * bmp->yalign); - rm = mr->width; - x = 0; - do { - int alpha; - alpha = a[x >> 10] + delta + 1; - if (alpha >= 256) { - r[0] = q[0]; - r[1] = q[1]; - r[2] = q[2]; - } - else if (alpha > 0) { - r[0] = (UINT8)MAKEALPHA24(p[0], q[0], alpha, 8); - r[1] = (UINT8)MAKEALPHA24(p[1], q[1], alpha, 8); - r[2] = (UINT8)MAKEALPHA24(p[2], q[2], alpha, 8); - } - else { - r[0] = p[0]; - r[1] = p[1]; - r[2] = p[2]; - } - p += 3; - q += 3; - r += 3; - x += xstep; - } while(--rm); - p += ostep; - q += sstep; - r += dstep; - y += ystep; - } while(--mr->height); -} - -static void vramsub_zoom24(VRAMHDL dst, const VRAMHDL src, int dot, - MIX_RECT *mr) { - -const UINT8 *pbase; -const UINT8 *p; - UINT8 *qbase; - UINT8 *q; - int x; - int dstep; - int xstep; - int ystep; - int xx; - int yy; - int xstep3; - - pbase = src->ptr + (mr->srcpos * 3); - qbase = dst->ptr + (mr->dstpos * 3); - dstep = (dst->yalign * dot) - (mr->width * 3); - - do { - p = pbase; - ystep = MIN(mr->height, dot); - x = mr->width; - do { - xstep = MIN(x, dot); - xstep3 = xstep * 3; - q = qbase; - yy = ystep; - do { - xx = xstep; - do { - q[0] = p[0]; - q[1] = p[1]; - q[2] = p[2]; - q += 3; - } while(--xx); - q += dst->yalign; - q -= xstep3; - } while(--yy); - p += 3; - qbase += xstep3; - x -= xstep; - } while(x); - pbase += src->yalign; - qbase += dstep; - mr->height -= ystep; - } while(mr->height); -} - -static void vramsub_mosaic24(VRAMHDL dst, const VRAMHDL src, int dot, - MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT8 *r; - int x; - int sstep; - int dstep; - int xstep; - int ystep; - int xx; - int yy; - int xstep3; - - p = src->ptr + (mr->srcpos * 3); - q = dst->ptr + (mr->dstpos * 3); - sstep = (src->yalign * dot) - (mr->width * 3); - dstep = (dst->yalign * dot) - (mr->width * 3); - - do { - ystep = MIN(mr->height, dot); - x = mr->width; - do { - xstep = MIN(x, dot); - xstep3 = xstep * 3; - r = q; - yy = ystep; - do { - xx = xstep; - do { - r[0] = p[0]; - r[1] = p[1]; - r[2] = p[2]; - r += 3; - } while(--xx); - r += dst->yalign; - r -= xstep3; - } while(--yy); - p += xstep3; - q += xstep3; - x -= xstep; - } while(x); - p += sstep; - q += dstep; - mr->height -= ystep; - } while(mr->height); -} - -static void vramsub_colex24(VRAMHDL dst, const VRAMHDL src, UINT32 color, - MIX_RECT *mr) { - - UINT8 *p, *q; - int x; - int step; - int c24[3]; - int a; - - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - - p = src->ptr + mr->srcpos; - q = dst->ptr + (mr->dstpos * dst->xalign); - step = mr->width * 3; - - do { - x = mr->width; - do { - a = p[0]; - if (a) { - a += VRAMALPHABASE; - q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], a, VRAMALPHABIT); - q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], a, VRAMALPHABIT); - q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], a, VRAMALPHABIT); - } - p += 1; - q += 3; - } while(--x); - p += src->width - mr->width; - q += dst->yalign - step; - } while(--mr->height); -} -#endif - - -// ---- bpp=32 - -#ifdef SUPPORT_32BPP - -static void vramsub_cpyp32(VRAMHDL dst, const VRAMHDL src, const UINT8 *pat8, - MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int posx; - int posy; - - p = src->ptr + (mr->srcpos * 4); - q = dst->ptr + (mr->dstpos * 4); - posx = mr->dstpos % dst->width; - posy = mr->dstpos / dst->width; - step = mr->width * 4; - - do { - UINT pat; - x = mr->width; - pat = pat8[posy & 7]; - posy++; - pat <<= (posx & 7); - pat |= (pat >> 8); - do { - pat <<= 1; - if (pat & 0x100) { - q[0] = p[0]; - q[1] = p[1]; - q[2] = p[2]; - pat++; - } - p += 4; - q += 4; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyp16w32(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int posx; - - p = src->ptr + (mr->srcpos * 4); - q = dst->ptr + (mr->dstpos * 4); - posx = mr->dstpos % dst->width; - step = mr->width * 4; - - do { - UINT32 pat; - x = mr->width; - pat = pat16; - pat |= (pat << 16); - pat >>= (posx & 15); - do { - if (pat & 1) { - q[0] = p[0]; - q[1] = p[1]; - q[2] = p[2]; - pat |= 0x10000; - } - pat >>= 1; - p += 4; - q += 4; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyp16h32(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int step; - int posy; - - p = src->ptr + (mr->srcpos * 4); - q = dst->ptr + (mr->dstpos * 4); - posy = mr->dstpos / dst->width; - step = mr->width * 4; - - do { - if (pat16 & (1 << (posy & 15))) { - CopyMemory(q, p, step); - } - posy++; - p += src->yalign; - q += dst->yalign; - } while(--mr->height); -} - -static void vramsub_cpyex32(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - - p = src->ptr + (mr->srcpos * src->xalign); - q = dst->ptr + (mr->dstpos * src->xalign); - step = mr->width * 4; - - do { - x = mr->width; - do { - UINT8 r, g, b; - b = p[0]; - g = p[1]; - r = p[2]; - p += 4; - if ((b) || (g) || (r)) { - q[0] = b; - q[1] = g; - q[2] = r; - } - q += 4; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyex32a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - - a = src->alpha + mr->srcpos; - p = src->ptr + (mr->srcpos * 4); - q = dst->ptr + (mr->dstpos * 4); - step = mr->width * 4; - - do { - x = mr->width; - do { - UINT alpha; - alpha = *a++; - if (alpha) { - alpha += VRAMALPHABASE; - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); - } - p += 4; - q += 4; - } while(--x); - a += src->width - mr->width; - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyex32a2(VRAMHDL dst, const VRAMHDL src, - UINT alpha64, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - - a = src->alpha + mr->srcpos; - p = src->ptr + (mr->srcpos * 4); - q = dst->ptr + (mr->dstpos * 4); - step = mr->width * 4; - - do { - x = mr->width; - do { - UINT alpha; - alpha = *a++; - if (alpha) { - alpha = (alpha + VRAMALPHABASE) * alpha64; - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT+6); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT+6); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT+6); - } - p += 4; - q += 4; - } while(--x); - a += src->width - mr->width; - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyexa32a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - UINT8 *b; - int x; - int step; - - p = src->ptr + (mr->srcpos * 4); - - a = src->alpha + mr->srcpos; - q = dst->ptr + (mr->dstpos * 4); - b = dst->alpha + mr->dstpos; - step = mr->width * 4; - - do { - x = mr->width; - do { - UINT alpha; - alpha = *a++; - if (alpha) { - alpha += VRAMALPHABASE; - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); - b[0] = VRAMALPHA; - } - p += 4; - q += 4; - b += 1; - } while(--x); - p += src->yalign - step; - a += src->width - mr->width; - q += dst->yalign - step; - b += dst->width - mr->width; - } while(--mr->height); -} - -static void vramsub_cpya32(VRAMHDL dst, const VRAMHDL src, - UINT alpha256, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - - p = src->ptr + (mr->srcpos * 4); - q = dst->ptr + (mr->dstpos * 4); - step = mr->width * 4; - - do { - x = mr->width; - do { - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha256, 8); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha256, 8); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha256, 8); - p += 4; - q += 4; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_cpyexp16w32(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - int posx; - - p = src->ptr + (mr->srcpos * 4); - q = dst->ptr + (mr->dstpos * 4); - a = src->alpha + mr->srcpos; - posx = mr->dstpos % dst->width; - step = mr->width * 4; - - do { - UINT32 pat; - x = mr->width; - pat = pat16; - pat |= (pat << 16); - pat >>= (posx & 15); - do { - if (pat & 1) { - UINT alpha; - alpha = *a; - if (alpha) { - alpha += VRAMALPHABASE; - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); - } - pat |= 0x10000; - } - pat >>= 1; - p += 4; - q += 4; - a += 1; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - a += src->width - mr->width; - } while(--mr->height); -} - -static void vramsub_cpyexp16h32(VRAMHDL dst, const VRAMHDL src, - UINT pat16, MIX_RECT *mr) { - -const UINT8 *p; -const UINT8 *a; - UINT8 *q; - int x; - int step; - int posy; - - p = src->ptr + (mr->srcpos * 4); - q = dst->ptr + (mr->dstpos * 4); - a = src->alpha + mr->srcpos; - posy = mr->dstpos / dst->width; - step = mr->width * 4; - - do { - if (pat16 & (1 << (posy & 15))) { - x = mr->width; - do { - UINT alpha; - alpha = *a; - if (alpha) { - alpha += VRAMALPHABASE; - q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); - q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); - q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); - } - p += 4; - q += 4; - a += 1; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - a += src->width - mr->width; - } - else { - p += src->yalign; - q += dst->yalign; - a += src->width; - } - posy++; - } while(--mr->height); -} - -static void vramsub_mix32(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, - UINT alpha64, MIXRECTEX *mr) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int x; - int ostep; - int sstep; - int dstep; - - p = org->ptr + (mr->orgpos * 4); - q = src->ptr + (mr->srcpos * 4); - r = dst->ptr + (mr->dstpos * 4); - ostep = org->yalign - (mr->width * 4); - sstep = src->yalign - (mr->width * 4); - dstep = dst->yalign - (mr->width * 4); - - do { - x = mr->width; - do { - r[0] = (UINT8)MAKEALPHA24(p[0], q[0], alpha64, 6); - r[1] = (UINT8)MAKEALPHA24(p[1], q[1], alpha64, 6); - r[2] = (UINT8)MAKEALPHA24(p[2], q[2], alpha64, 6); - p += 4; - q += 4; - r += 4; - } while(--x); - p += ostep; - q += sstep; - r += dstep; - } while(--mr->height); -} - -static void vramsub_mixcol32(VRAMHDL dst, const VRAMHDL src, UINT32 color, - UINT alpha64, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int c24[3]; - - p = src->ptr + (mr->srcpos * 4); - q = dst->ptr + (mr->dstpos * 4); - step = mr->width * 4; - - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - do { - x = mr->width; - do { - q[0] = (UINT8)MAKEALPHA24(c24[0], p[0], alpha64, 6); - q[1] = (UINT8)MAKEALPHA24(c24[1], p[1], alpha64, 6); - q[2] = (UINT8)MAKEALPHA24(c24[2], p[2], alpha64, 6); - p += 4; - q += 4; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_mixalpha32(VRAMHDL dst, const VRAMHDL src, UINT32 color, - MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - int x; - int step; - int c24[3]; - - p = src->ptr + (mr->srcpos * src->xalign); - q = dst->ptr + (mr->dstpos * src->xalign); - step = mr->width * 4; - - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - do { - x = mr->width; - do { - int a; - a = p[0]; - if (a) { - a++; - } - q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], a, 8); - a = p[1]; - if (a) { - a++; - } - q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], a, 8); - a = p[2]; - if (a) { - a++; - } - q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], a, 8); - p += 4; - q += 4; - } while(--x); - p += src->yalign - step; - q += dst->yalign - step; - } while(--mr->height); -} - -static void vramsub_gray32(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, - const VRAMHDL bmp, int delta, MIXRECTEX *mr) { - -const UINT8 *p; -const UINT8 *q; -const UINT8 *a; - UINT8 *r; - int rm; - int x, y; - int ostep; - int sstep; - int dstep; - int xstep; - int ystep; - - if ((bmp == NULL) || (bmp->bpp != 8)) { - return; - } - - p = org->ptr + (mr->orgpos * 4); - q = src->ptr + (mr->srcpos * 4); - r = dst->ptr + (mr->dstpos * 4); - ostep = org->yalign - (mr->width * 4); - sstep = src->yalign - (mr->width * 4); - dstep = dst->yalign - (mr->width * 4); - - xstep = (bmp->width << 10) / mr->width; - ystep = (bmp->height << 10) / mr->height; - - y = 0; - do { - a = bmp->ptr + ((y >> 10) * bmp->yalign); - rm = mr->width; - x = 0; - do { - int alpha; - alpha = a[x >> 10] + delta + 1; - if (alpha >= 256) { - r[0] = q[0]; - r[1] = q[1]; - r[2] = q[2]; - } - else if (alpha > 0) { - r[0] = (UINT8)MAKEALPHA24(p[0], q[0], alpha, 8); - r[1] = (UINT8)MAKEALPHA24(p[1], q[1], alpha, 8); - r[2] = (UINT8)MAKEALPHA24(p[2], q[2], alpha, 8); - } - else { - r[0] = p[0]; - r[1] = p[1]; - r[2] = p[2]; - } - p += 4; - q += 4; - r += 4; - x += xstep; - } while(--rm); - p += ostep; - q += sstep; - r += dstep; - y += ystep; - } while(--mr->height); -} - -static void vramsub_zoom32(VRAMHDL dst, const VRAMHDL src, int dot, - MIX_RECT *mr) { - -const UINT8 *pbase; -const UINT8 *p; - UINT8 *qbase; - UINT8 *q; - int x; - int dstep; - int xstep; - int ystep; - int xx; - int yy; - int xstep3; - - pbase = src->ptr + (mr->srcpos * 4); - qbase = dst->ptr + (mr->dstpos * 4); - dstep = (dst->yalign * dot) - (mr->width * 4); - - do { - p = pbase; - ystep = MIN(mr->height, dot); - x = mr->width; - do { - xstep = MIN(x, dot); - xstep3 = xstep * 4; - q = qbase; - yy = ystep; - do { - xx = xstep; - do { - q[0] = p[0]; - q[1] = p[1]; - q[2] = p[2]; - q += 4; - } while(--xx); - q += dst->yalign; - q -= xstep3; - } while(--yy); - p += 4; - qbase += xstep3; - x -= xstep; - } while(x); - pbase += src->yalign; - qbase += dstep; - mr->height -= ystep; - } while(mr->height); -} - -static void vramsub_mosaic32(VRAMHDL dst, const VRAMHDL src, int dot, - MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT8 *r; - int x; - int sstep; - int dstep; - int xstep; - int ystep; - int xx; - int yy; - int xstep3; - - p = src->ptr + (mr->srcpos * 4); - q = dst->ptr + (mr->dstpos * 4); - sstep = (src->yalign * dot) - (mr->width * 4); - dstep = (dst->yalign * dot) - (mr->width * 4); - - do { - ystep = MIN(mr->height, dot); - x = mr->width; - do { - xstep = MIN(x, dot); - xstep3 = xstep * 4; - r = q; - yy = ystep; - do { - xx = xstep; - do { - r[0] = p[0]; - r[1] = p[1]; - r[2] = p[2]; - r += 4; - } while(--xx); - r += dst->yalign; - r -= xstep3; - } while(--yy); - p += xstep3; - q += xstep3; - x -= xstep; - } while(x); - p += sstep; - q += dstep; - mr->height -= ystep; - } while(mr->height); -} - -static void vramsub_colex32(VRAMHDL dst, const VRAMHDL src, UINT32 color, - MIX_RECT *mr) { - - UINT8 *p, *q; - int x; - int step; - int c24[3]; - - int a; - - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - - p = src->ptr + mr->srcpos; - q = dst->ptr + (mr->dstpos * dst->xalign); - step = mr->width * 4; - - do { - x = mr->width; - do { - a = p[0]; - if (a) { - a += VRAMALPHABASE; - q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], a, VRAMALPHABIT); - q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], a, VRAMALPHABIT); - q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], a, VRAMALPHABIT); - } - p += 1; - q += 4; - } while(--x); - p += src->width - mr->width; - q += dst->yalign - step; - } while(--mr->height); -} -#endif - -// ---- - -// サーフェスをバッファとして使う場合… -// dst(posx, posy) <-src:rct - -void vramcpy_cpy(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct) { - - MIX_RECT mr; - - if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } - vramsub_cpy(dst, src, &mr); -} - -void vramcpy_move(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct) { - - MIX_RECT mr; - - if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } - vramsub_move(dst, src, &mr); -} - -void vramcpy_cpyall(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct) { - - MIX_RECT mr; - - if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } - vramsub_cpyall(dst, src, &mr); -} - -void vramcpy_cpypat(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - const UINT8 *pat8) { - - MIX_RECT mr; - - if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_cpyp16(dst, src, pat8, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_cpyp24(dst, src, pat8, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_cpyp32(dst, src, pat8, &mr); - } -#endif -} - -void vramcpy_cpyex(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct) { - - MIX_RECT mr; - - if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - if (!src->alpha) { - vramsub_cpyex16(dst, src, &mr); - } - else { - vramsub_cpyex16a(dst, src, &mr); - } - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - if (!src->alpha) { - vramsub_cpyex24(dst, src, &mr); - } - else { - vramsub_cpyex24a(dst, src, &mr); - } - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - if (!src->alpha) { - vramsub_cpyex32(dst, src, &mr); - } - else { - vramsub_cpyex32a(dst, src, &mr); - } - } -#endif -} - -void vramcpy_cpyexa(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct) { - - MIX_RECT mr; - - if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || - (dst->bpp != src->bpp) || - (dst->alpha == NULL) || (src->alpha == NULL)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_cpyexa16a(dst, src, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_cpyexa24a(dst, src, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_cpyexa32a(dst, src, &mr); - } -#endif -} - -void vramcpy_cpyalpha(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - UINT alpha256) { - - MIX_RECT mr; - - if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } - if (alpha256 < 256) { - alpha256 = 256 - alpha256; - } - else { - alpha256 = 0; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_cpya16(dst, src, alpha256, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_cpya24(dst, src, alpha256, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_cpya32(dst, src, alpha256, &mr); - } -#endif -} - -void vramcpy_mix(VRAMHDL dst, const VRAMHDL org, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - UINT alpha64) { - - MIXRECTEX mr; - - if (cpyrectex(&mr, dst, pt, org, src, rct) != SUCCESS) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_mix16(dst, org, src, alpha64, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_mix24(dst, org, src, alpha64, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_mix32(dst, org, src, alpha64, &mr); - } -#endif -} - -void vramcpy_mixcol(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - UINT32 color, UINT alpha64) { - - MIX_RECT mr; - - if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_mixcol16(dst, src, color, alpha64, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_mixcol24(dst, src, color, alpha64, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_mixcol32(dst, src, color, alpha64, &mr); - } -#endif -} - -void vramcpy_zoom(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - int dot) { - - MIX_RECT mr; - - if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } - - if (dot <= 0) { - vramsub_cpy(dst, src, &mr); - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_zoom16(dst, src, dot, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_zoom24(dst, src, dot, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_zoom32(dst, src, dot, &mr); - } -#endif -} - -void vramcpy_mosaic(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - int dot) { - - MIX_RECT mr; - - if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } - - if (dot <= 0) { - vramsub_cpy(dst, src, &mr); - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_mosaic16(dst, src, dot, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_mosaic24(dst, src, dot, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_mosaic32(dst, src, dot, &mr); - } -#endif -} - - -// ---- - -// サーフェスをウィンドウとして使う場合… -// dst:rct <- src(posx, posy) - -void vrammix_cpy(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } - vramsub_cpy(dst, src, &mr); -} - -void vrammix_cpyall(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } - vramsub_cpyall(dst, src, &mr); -} - -void vrammix_cpy2(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT alpha) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (dst->bpp != src->bpp) || (dst->alpha == NULL)) { - return; - } - vramsub_cpy2(dst, src, alpha, &mr); -} - -void vrammix_cpypat(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const UINT8 *pat8) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_cpyp16(dst, src, pat8, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_cpyp24(dst, src, pat8, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_cpyp32(dst, src, pat8, &mr); - } -#endif -} - -void vrammix_cpypat16w(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const UINT pat16) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_cpyp16w16(dst, src, pat16, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_cpyp16w24(dst, src, pat16, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_cpyp16w32(dst, src, pat16, &mr); - } -#endif -} - -void vrammix_cpypat16h(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const UINT pat16) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_cpyp16h16(dst, src, pat16, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_cpyp16h24(dst, src, pat16, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_cpyp16h32(dst, src, pat16, &mr); - } -#endif -} - -void vrammix_cpyex(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - if (!src->alpha) { - vramsub_cpyex16(dst, src, &mr); - } - else { - vramsub_cpyex16a(dst, src, &mr); - } - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - if (!src->alpha) { - vramsub_cpyex24(dst, src, &mr); - } - else { - vramsub_cpyex24a(dst, src, &mr); - } - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - if (!src->alpha) { - vramsub_cpyex32(dst, src, &mr); - } - else { - vramsub_cpyex32a(dst, src, &mr); - } - } -#endif -} - -void vrammix_cpyex2(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT alpha64) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (src->alpha == NULL) || (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_cpyex16a2(dst, src, alpha64, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_cpyex24a2(dst, src, alpha64, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_cpyex32a2(dst, src, alpha64, &mr); - } -#endif -} - -void vrammix_cpyexpat16w(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const UINT pat16) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (src->alpha == NULL) || (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_cpyexp16w16(dst, src, pat16, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_cpyexp16w24(dst, src, pat16, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_cpyexp16w32(dst, src, pat16, &mr); - } -#endif -} - -void vrammix_cpyexpat16h(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const UINT pat16) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (src->alpha == NULL) || (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_cpyexp16h16(dst, src, pat16, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_cpyexp16h24(dst, src, pat16, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_cpyexp16h32(dst, src, pat16, &mr); - } -#endif -} - -void vrammix_mix(VRAMHDL dst, const VRAMHDL org, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT alpha64) { - - MIXRECTEX mr; - - if (mixrectex(&mr, dst, org, rct, src, pt) != SUCCESS) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_mix16(dst, org, src, alpha64, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_mix24(dst, org, src, alpha64, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_mix32(dst, org, src, alpha64, &mr); - } -#endif -} - -void vrammix_mixcol(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT32 color, UINT alpha64) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_mixcol16(dst, src, color, alpha64, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_mixcol24(dst, src, color, alpha64, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_mixcol32(dst, src, color, alpha64, &mr); - } -#endif -} - -void vrammix_mixalpha(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT32 color) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || - (dst->bpp != src->bpp)) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_mixalpha16(dst, src, color, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_mixalpha24(dst, src, color, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_mixalpha32(dst, src, color, &mr); - } -#endif -} - -void vrammix_graybmp(VRAMHDL dst, const VRAMHDL org, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const VRAMHDL bmp, int delta) { - - MIXRECTEX mr; - - if (mixrectex(&mr, dst, org, rct, src, pt) != SUCCESS) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_gray16(dst, org, src, bmp, delta, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_gray24(dst, org, src, bmp, delta, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_gray32(dst, org, src, bmp, delta, &mr); - } -#endif -} - -void vrammix_colex(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT32 color) { - - MIX_RECT mr; - - if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || (src->bpp != 8)) { - return; - } - -#ifdef SUPPORT_16BPP - if (dst->bpp == 16) { - vramsub_colex16(dst, src, color, &mr); - } -#endif -#ifdef SUPPORT_24BPP - if (dst->bpp == 24) { - vramsub_colex24(dst, src, color, &mr); - } -#endif -#ifdef SUPPORT_32BPP - if (dst->bpp == 32) { - vramsub_colex32(dst, src, color, &mr); - } -#endif -} - - -// ---- resize - -#ifdef SUPPORT_16BPP -static void vramsub_resize16(VRAMHDL dst, MIX_RECT *drct, - const VRAMHDL src, const MIX_RECT *srct) { - -const UINT8 *p; - UINT8 *q; -const UINT8 *r; -const UINT8 *s; - int dstep; - int xstep; - int ystep; - int xx; - int yy; - int x; - - p = src->ptr + (srct->srcpos * 2); - q = dst->ptr + (drct->dstpos * 2); - dstep = dst->yalign - (drct->width * 2); - - xstep = (srct->width << 10) / drct->width; - ystep = (srct->height << 10) / drct->height; - yy = 0; - do { - xx = 0; - r = p; - r += (yy >> 10) * src->yalign; - x = drct->width; - do { - s = r + ((xx >> 10) * 2); - *(UINT16 *)q = *(UINT16 *)s; - xx += xstep; - q += 2; - } while(--x); - yy += ystep; - q += dstep; - } while(--drct->height); -} -#endif - -#ifdef SUPPORT_24BPP -static void vramsub_resize24(VRAMHDL dst, MIX_RECT *drct, - const VRAMHDL src, const MIX_RECT *srct) { - -const UINT8 *p; - UINT8 *q; -const UINT8 *r; -const UINT8 *s; - int dstep; - int xstep; - int ystep; - int xx; - int yy; - int x; - - p = src->ptr + (srct->srcpos * 3); - q = dst->ptr + (drct->dstpos * 3); - dstep = dst->yalign - (drct->width * 3); - - xstep = (srct->width << 10) / drct->width; - ystep = (srct->height << 10) / drct->height; - yy = 0; - do { - xx = 0; - r = p; - r += (yy >> 10) * src->yalign; - x = drct->width; - do { - s = r + ((xx >> 10) * 3); - q[0] = s[0]; - q[1] = s[1]; - q[2] = s[2]; - xx += xstep; - q += 3; - } while(--x); - yy += ystep; - q += dstep; - } while(--drct->height); -} -#endif - -#ifdef SUPPORT_32BPP -static void vramsub_resize32(VRAMHDL dst, MIX_RECT *drct, - const VRAMHDL src, const MIX_RECT *srct) { - -const UINT8 *p; - UINT8 *q; -const UINT8 *r; -const UINT8 *s; - int dstep; - int xstep; - int ystep; - int xx; - int yy; - int x; - - p = src->ptr + (srct->srcpos * 4); - q = dst->ptr + (drct->dstpos * 4); - dstep = dst->yalign - (drct->width * 4); - - xstep = (srct->width << 10) / drct->width; - ystep = (srct->height << 10) / drct->height; - yy = 0; - do { - xx = 0; - r = p; - r += (yy >> 10) * src->yalign; - x = drct->width; - do { - s = r + ((xx >> 10) * 4); - q[0] = s[0]; - q[1] = s[1]; - q[2] = s[2]; - xx += xstep; - q += 4; - } while(--x); - yy += ystep; - q += dstep; - } while(--drct->height); -} -#endif - -static BRESULT cliprect(const VRAMHDL hdl, const RECT_T *rct, MIX_RECT *r) { - - RECT_T rect; - - if (vram_cliprect(&rect, hdl, rct) != SUCCESS) { - return(FAILURE); - } - r->srcpos = (rect.top * hdl->width) + rect.left; - r->dstpos = r->srcpos; - r->width = rect.right - rect.left; - r->height = rect.bottom - rect.top; - return(SUCCESS); -} - -void vrammix_resize(VRAMHDL dst, const RECT_T *drct, - const VRAMHDL src, const RECT_T *srct) { - - MIX_RECT drect; - MIX_RECT srect; - - if ((cliprect(src, srct, &srect) != SUCCESS) || - (cliprect(dst, drct, &drect) != SUCCESS)) { - return; - } - if (dst->bpp != src->bpp) { - return; - } -#ifdef SUPPORT_16BPP - if (src->bpp == 16) { - vramsub_resize16(dst, &drect, src, &srect); - } -#endif -#ifdef SUPPORT_24BPP - if (src->bpp == 24) { - vramsub_resize24(dst, &drect, src, &srect); - } -#endif -#ifdef SUPPORT_32BPP - if (src->bpp == 32) { - vramsub_resize32(dst, &drect, src, &srect); - } -#endif -} - - -// ---- font - -static BRESULT txtrect(VRAMHDL dst, const FNTDAT fnt, const POINT_T *pt, - const RECT_T *rct, MIX_RECT *r) { - - int pos; - - r->srcpos = 0; - r->dstpos = pt->y * dst->width; - r->dstpos += pt->x; - - pos = pt->y - rct->top; - if (pos < 0) { - r->srcpos -= pos * fnt->width; - r->height = MIN(fnt->height + pos, rct->bottom - rct->top); - } - else { - r->height = MIN(rct->bottom - rct->top - pos, fnt->height); - } - if (r->height <= 0) { - return(FAILURE); - } - - pos = pt->x - rct->left; - if (pos < 0) { - r->srcpos -= pos; - r->width = MIN(fnt->width + pos, rct->right - rct->left); - } - else { - r->width = MIN(rct->right - rct->left - pos, fnt->width); - } - if (r->width <= 0) { - return(FAILURE); - } - return(SUCCESS); -} - -static void vramsub_txt8p(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT alpha; - int cnt; - - p = (UINT8 *)(fnt + 1); - p += mr->srcpos; - q = dst->ptr + mr->dstpos; - do { - cnt = mr->width; - do { - alpha = *p++; - if (alpha) { - alpha = alpha * color / FDAT_DEPTH; - q[0] = (UINT8)alpha; - } - q += 1; - } while(--cnt); - p += fnt->width - mr->width; - q += dst->width - mr->width; - } while(--mr->height); -} - -#ifdef SUPPORT_16BPP -static void vramsub_txt16p(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT alpha; - int cnt; - UINT col16; - int c16[3]; - - col16 = MAKE16PAL(color); - c16[0] = col16 & B16MASK; - c16[1] = col16 & G16MASK; - c16[2] = col16 & R16MASK; - - p = (UINT8 *)(fnt + 1); - p += mr->srcpos; - q = dst->ptr + (mr->dstpos * 2); - do { - cnt = mr->width; - do { - alpha = *p++; - if (alpha) { - alpha = FDAT_DEPTH - alpha; - if (!alpha) { - *(UINT16 *)q = (UINT16)col16; - } - else { - UINT d, s; - s = *(UINT16 *)q; - d = MAKEALPHA16s(c16[0], s, B16MASK, - alpha, FDAT_DEPTHBIT); - d |= MAKEALPHA16s(c16[1], s, G16MASK, - alpha, FDAT_DEPTHBIT); - d |= MAKEALPHA16s(c16[2], s, R16MASK, - alpha, FDAT_DEPTHBIT); - *(UINT16 *)q = (UINT16)d; - } - } - q += 2; - } while(--cnt); - p += fnt->width - mr->width; - q += (dst->width - mr->width) * 2; - } while(--mr->height); -} - -static void vramsub_txt16a(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT8 *a; - UINT alpha; - int cnt; - UINT col16; - int c16[3]; - - col16 = MAKE16PAL(color); - c16[0] = col16 & B16MASK; - c16[1] = col16 & G16MASK; - c16[2] = col16 & R16MASK; - - p = (UINT8 *)(fnt + 1); - p += mr->srcpos; - q = dst->ptr + (mr->dstpos * 2); - a = dst->alpha + mr->dstpos; - do { - cnt = mr->width; - do { - alpha = *p++; - if (alpha) { - alpha = FDAT_DEPTH - alpha; - if (!alpha) { - *(UINT16 *)q = (UINT16)col16; - } - else { - UINT d, s; - s = *(UINT16 *)q; - d = MAKEALPHA16s(c16[0], s, B16MASK, - alpha, FDAT_DEPTHBIT); - d |= MAKEALPHA16s(c16[1], s, G16MASK, - alpha, FDAT_DEPTHBIT); - d |= MAKEALPHA16s(c16[2], s, R16MASK, - alpha, FDAT_DEPTHBIT); - *(UINT16 *)q = (UINT16)d; - } - a[0] = VRAMALPHA; - } - q += 2; - a += 1; - } while(--cnt); - p += fnt->width - mr->width; - q += (dst->width - mr->width) * 2; - a += dst->width - mr->width; - } while(--mr->height); -} - -static void vramsub_txt16e(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT8 *a; - UINT alpha; - int cnt; - UINT col16; - int c16[3]; - - col16 = MAKE16PAL(color); - c16[0] = col16 & B16MASK; - c16[1] = col16 & G16MASK; - c16[2] = col16 & R16MASK; - - p = (UINT8 *)(fnt + 1); - p += mr->srcpos; - q = dst->ptr + (mr->dstpos * 2); - - a = dst->alpha + mr->dstpos; - do { - cnt = mr->width; - do { - alpha = (*p++) * VRAMALPHA / FDAT_DEPTH; - if (alpha) { - *(UINT16 *)q = (UINT16)col16; - a[0] = (UINT8)alpha; - } - q += 2; - a += 1; - } while(--cnt); - p += fnt->width - mr->width; - q += (dst->width - mr->width) * 2; - a += dst->width - mr->width; - } while(--mr->height); -} -#endif - -#ifdef SUPPORT_24BPP -static void vramsub_txt24p(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT alpha; - int cnt; - int c24[3]; - - p = (UINT8 *)(fnt + 1); - p += mr->srcpos; - q = dst->ptr + (mr->dstpos * 3); - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - do { - cnt = mr->width; - do { - alpha = *p++; - if (alpha) { - if (alpha == FDAT_DEPTH) { - q[0] = (UINT8)c24[0]; - q[1] = (UINT8)c24[1]; - q[2] = (UINT8)c24[2]; - } - else { - alpha += FDATDEPTHBASE; - q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], - alpha, FDAT_DEPTHBIT); - q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], - alpha, FDAT_DEPTHBIT); - q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], - alpha, FDAT_DEPTHBIT); - } - } - q += 3; - } while(--cnt); - p += (fnt->width - mr->width); - q += (dst->width - mr->width) * 3; - } while(--mr->height); -} - -static void vramsub_txt24a(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT8 *a; - UINT alpha; - int cnt; - int c24[3]; - - p = (UINT8 *)(fnt + 1); - p += mr->srcpos; - q = dst->ptr + (mr->dstpos * 3); - a = dst->alpha + mr->dstpos; - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - do { - cnt = mr->width; - do { - alpha = *p++; - if (alpha) { - if (alpha == FDAT_DEPTH) { - q[0] = (UINT8)c24[0]; - q[1] = (UINT8)c24[1]; - q[2] = (UINT8)c24[2]; - } - else { - alpha += FDATDEPTHBASE; - q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], - alpha, FDAT_DEPTHBIT); - q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], - alpha, FDAT_DEPTHBIT); - q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], - alpha, FDAT_DEPTHBIT); - } - a[0] = VRAMALPHA; - } - q += 3; - a += 1; - } while(--cnt); - p += (fnt->width - mr->width); - q += (dst->width - mr->width) * 3; - a += dst->width - mr->width; - } while(--mr->height); -} - -static void vramsub_txt24e(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT8 *a; - UINT alpha; - int cnt; - int c24[3]; - - p = (UINT8 *)(fnt + 1); - p += mr->srcpos; - q = dst->ptr + (mr->dstpos * 3); - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - a = dst->alpha + mr->dstpos; - do { - cnt = mr->width; - do { - alpha = (*p++) * VRAMALPHA / FDAT_DEPTH; - if (alpha) { - q[0] = (UINT8)c24[0]; - q[1] = (UINT8)c24[1]; - q[2] = (UINT8)c24[2]; - a[0] = (UINT8)alpha; - } - q += 3; - a += 1; - } while(--cnt); - p += (fnt->width - mr->width); - q += (dst->width - mr->width) * 3; - a += dst->width - mr->width; - } while(--mr->height); -} -#endif - -#ifdef SUPPORT_32BPP -static void vramsub_txt32p(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT alpha; - int cnt; - int c24[3]; - - p = (UINT8 *)(fnt + 1); - p += mr->srcpos; - q = dst->ptr + (mr->dstpos * 4); - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - do { - cnt = mr->width; - do { - alpha = *p++; - if (alpha) { - if (alpha == FDAT_DEPTH) { - q[0] = (UINT8)c24[0]; - q[1] = (UINT8)c24[1]; - q[2] = (UINT8)c24[2]; - } - else { - alpha += FDATDEPTHBASE; - q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], - alpha, FDAT_DEPTHBIT); - q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], - alpha, FDAT_DEPTHBIT); - q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], - alpha, FDAT_DEPTHBIT); - } - } - q += 4; - } while(--cnt); - p += (fnt->width - mr->width); - q += (dst->width - mr->width) * 4; - } while(--mr->height); -} - -static void vramsub_txt32a(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT8 *a; - UINT alpha; - int cnt; - int c24[3]; - - p = (UINT8 *)(fnt + 1); - p += mr->srcpos; - q = dst->ptr + (mr->dstpos * 4); - a = dst->alpha + mr->dstpos; - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - do { - cnt = mr->width; - do { - alpha = *p++; - if (alpha) { - if (alpha == FDAT_DEPTH) { - q[0] = (UINT8)c24[0]; - q[1] = (UINT8)c24[1]; - q[2] = (UINT8)c24[2]; - } - else { - alpha += FDATDEPTHBASE; - q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], - alpha, FDAT_DEPTHBIT); - q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], - alpha, FDAT_DEPTHBIT); - q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], - alpha, FDAT_DEPTHBIT); - } - a[0] = VRAMALPHA; - } - q += 4; - a += 1; - } while(--cnt); - p += (fnt->width - mr->width); - q += (dst->width - mr->width) * 4; - a += dst->width - mr->width; - } while(--mr->height); -} - -static void vramsub_txt32e(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr) { - -const UINT8 *p; - UINT8 *q; - UINT8 *a; - UINT alpha; - int cnt; - int c24[3]; - - p = (UINT8 *)(fnt + 1); - p += mr->srcpos; - q = dst->ptr + (mr->dstpos * 4); - c24[0] = color & 0xff; - c24[1] = (color >> 8) & 0xff; - c24[2] = (color >> 16) & 0xff; - a = dst->alpha + mr->dstpos; - do { - cnt = mr->width; - do { - alpha = (*p++) * VRAMALPHA / FDAT_DEPTH; - if (alpha) { - q[0] = (UINT8)c24[0]; - q[1] = (UINT8)c24[1]; - q[2] = (UINT8)c24[2]; - a[0] = (UINT8)alpha; - } - q += 4; - a += 1; - } while(--cnt); - p += (fnt->width - mr->width); - q += (dst->width - mr->width) * 4; - a += dst->width - mr->width; - } while(--mr->height); -} -#endif - -static void vramsub_text(VRAMHDL dst, void *fhdl, const OEMCHAR *str, - UINT32 color, POINT_T *pt, const RECT_T *rct, - void (*func)(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr)) { - - int leng; - OEMCHAR buf[4]; - RECT_T rect; - FNTDAT fnt; - MIX_RECT mr; - - if ((str == NULL) || (pt == NULL) || (func == NULL) || - (vram_cliprect(&rect, dst, rct) != SUCCESS)) { - goto vstxt_end; - } - - while(1) { - leng = milstr_charsize(str); - if (!leng) { - break; - } - CopyMemory(buf, str, leng * sizeof(OEMCHAR)); - buf[leng] = '\0'; - str += leng; - fnt = fontmng_get(fhdl, buf); - if (fnt) { - if (txtrect(dst, fnt, pt, &rect, &mr) == SUCCESS) { - func(dst, fnt, color, &mr); - } - pt->x += fnt->pitch; - } - } - -vstxt_end: - return; -} - -void vrammix_text(VRAMHDL dst, void *fhdl, const OEMCHAR *str, - UINT32 color, POINT_T *pt, const RECT_T *rct) { - - void (*func)(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr); - - if (dst == NULL) { - return; - } - func = NULL; - if (dst->bpp == 8) { - func = vramsub_txt8p; - } -#ifdef SUPPORT_16BPP - if (dst->bpp == 16) { - if (dst->alpha) { - func = vramsub_txt16a; - } - else { - func = vramsub_txt16p; - } - } -#endif -#ifdef SUPPORT_24BPP - if (dst->bpp == 24) { - if (dst->alpha) { - func = vramsub_txt24a; - } - else { - func = vramsub_txt24p; - } - } -#endif -#ifdef SUPPORT_32BPP - if (dst->bpp == 32) { - if (dst->alpha) { - func = vramsub_txt32a; - } - else { - func = vramsub_txt32p; - } - } -#endif - vramsub_text(dst, fhdl, str, color, pt, rct, func); -} - -void vrammix_textex(VRAMHDL dst, void *fhdl, const OEMCHAR *str, - UINT32 color, POINT_T *pt, const RECT_T *rct) { - - void (*func)(VRAMHDL dst, const FNTDAT fnt, - UINT32 color, MIX_RECT *mr); - - if (dst == NULL) { - return; - } - func = NULL; - if (dst->bpp == 8) { - func = vramsub_txt8p; - } -#ifdef SUPPORT_16BPP - if (dst->bpp == 16) { - if (dst->alpha) { - func = vramsub_txt16e; - } - else { - func = vramsub_txt16p; - } - } -#endif -#ifdef SUPPORT_24BPP - if (dst->bpp == 24) { - if (dst->alpha) { - func = vramsub_txt24e; - } - else { - func = vramsub_txt24p; - } - } -#endif -#ifdef SUPPORT_32BPP - if (dst->bpp == 32) { - if (dst->alpha) { - func = vramsub_txt32e; - } - else { - func = vramsub_txt32p; - } - } -#endif - vramsub_text(dst, fhdl, str, color, pt, rct, func); -} - +#include +#include +#include +#include + + +enum { + VRAMALPHABASE = (1 << VRAMALPHABIT) - VRAMALPHA, + FDATDEPTHBASE = (1 << FDAT_DEPTHBIT) - FDAT_DEPTH +}; + + +static BRESULT cpyrect(MIX_RECT *r, const VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct) { + + POINT_T p; + int width; + int height; + + if ((dst == NULL) || (src == NULL)) { + return(FAILURE); + } + if (pt) { + p = *pt; + } + else { + p.x = 0; + p.y = 0; + } + r->srcpos = 0; + if (rct) { + width = MIN(rct->right, src->width); + if (rct->left >= 0) { + r->srcpos += rct->left; + width -= rct->left; + } + else { + p.x -= rct->left; + } + height = MIN(rct->bottom, src->height); + if (rct->top >= 0) { + r->srcpos += rct->top * src->width; + height -= rct->top; + } + else { + p.y -= rct->top; + } + } + else { + width = src->width; + height = src->height; + } + + r->dstpos = 0; + r->width = MIN(width + p.x, dst->width); + if (p.x > 0) { + r->dstpos += p.x; + r->width = MIN(r->width, dst->width) - p.x; + } + else { + r->srcpos -= p.x; + } + if (r->width <= 0) { + return(FAILURE); + } + + r->height = MIN(height + p.y, dst->height); + if (p.y > 0) { + r->dstpos += p.y * dst->width; + r->height = MIN(r->height, dst->height) - p.y; + } + else { + r->srcpos -= p.y * src->width; + } + if (r->height <= 0) { + return(FAILURE); + } + return(SUCCESS); +} + +static BRESULT mixrect(MIX_RECT *r, const VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt) { + + int pos; + RECT_T s; + + if ((dst == NULL) || (src == NULL)) { + return(FAILURE); + } + r->srcpos = 0; + if (rct == NULL) { + s.left = 0; + s.top = 0; + s.right = dst->width; + s.bottom = dst->height; + r->dstpos = 0; + } + else { + if ((rct->bottom <= 0) || (rct->right <= 0) || + (rct->left >= dst->width) || (rct->top >= dst->height)) { + return(FAILURE); + } + s.left = MAX(rct->left, 0); + s.top = MAX(rct->top, 0); + s.right = MIN(rct->right, dst->width); + s.bottom = MIN(rct->bottom, dst->height); + if ((s.top >= s.bottom) || (s.left >= s.right)) { + return(FAILURE); + } + r->dstpos = s.top * dst->width; + r->dstpos += s.left; + } + + pos = src->posy - s.top; + if (pt) { + pos += pt->y; + } + if (pos < 0) { + r->srcpos -= pos * src->width; + r->height = MIN(src->height + pos, s.bottom - s.top); + } + else { + r->dstpos += pos * dst->width; + r->height = MIN(s.bottom - s.top - pos, src->height); + } + if (r->height <= 0) { + return(FAILURE); + } + + pos = src->posx - s.left; + if (pt) { + pos += pt->x; + } + if (pos < 0) { + r->srcpos -= pos; + r->width = MIN(src->width + pos, s.right - s.left); + } + else { + r->dstpos += pos; + r->width = MIN(s.right - s.left - pos, src->width); + } + if (r->width <= 0) { + return(FAILURE); + } + return(SUCCESS); +} + + +// ---- + +typedef struct { + int orgpos; + int srcpos; + int dstpos; + int width; + int height; +} MIXRECTEX; + +static BRESULT cpyrectex(MIXRECTEX *r, const VRAMHDL dst, const POINT_T *pt, + const VRAMHDL org, const VRAMHDL src, const RECT_T *rct) { + + POINT_T p; + int width; + int height; + int dstwidth; + int dstheight; + + if ((dst == NULL) || (org == NULL) || (src == NULL) || + (dst->bpp != org->bpp) || (dst->bpp != src->bpp)) { + return(FAILURE); + } + if (pt) { + p = *pt; + } + else { + p.x = 0; + p.y = 0; + } + + r->srcpos = 0; + if (rct) { + width = MIN(rct->right, src->width); + if (rct->left >= 0) { + r->srcpos += rct->left; + width -= rct->left; + } + else { + p.x -= rct->left; + } + height = MIN(rct->bottom, src->height); + if (rct->top >= 0) { + r->srcpos += rct->top * src->width; + height -= rct->top; + } + else { + p.y -= rct->top; + } + } + else { + width = src->width; + height = src->height; + } + + r->orgpos = 0; + r->dstpos = 0; + dstwidth = MIN(dst->width, org->width); + r->width = MIN(width + p.x, dstwidth); + if (p.x > 0) { + r->orgpos += p.x; + r->dstpos += p.x; + r->width = MIN(r->width, dstwidth) - p.x; + } + else { + r->srcpos -= p.x; + } + if (r->width <= 0) { + return(FAILURE); + } + + dstheight = MIN(dst->height, org->height); + r->height = MIN(height + p.y, dstheight); + if (p.y > 0) { + r->orgpos += p.y * org->width; + r->dstpos += p.y * dst->width; + r->height = MIN(r->height, dstheight) - p.y; + } + else { + r->srcpos -= p.y * src->width; + } + if (r->height <= 0) { + return(FAILURE); + } + return(SUCCESS); +} + +static BRESULT mixrectex(MIXRECTEX *r, const VRAMHDL dst, const VRAMHDL org, + const RECT_T *rct, const VRAMHDL src, const POINT_T *pt) { + + int pos; + RECT_T s; + int dstwidth; + int dstheight; + + if ((dst == NULL) || (org == NULL) || (src == NULL) || + (dst->bpp != org->bpp) || (dst->bpp != src->bpp)) { + return(FAILURE); + } + dstwidth = MIN(dst->width, org->width); + dstheight = MIN(dst->height, org->height); + r->srcpos = 0; + if (rct == NULL) { + s.left = 0; + s.top = 0; + s.right = dstwidth; + s.bottom = dstheight; + r->orgpos = 0; + r->dstpos = 0; + } + else { + if ((rct->bottom <= 0) || (rct->right <= 0) || + (rct->left >= dstwidth) || (rct->top >= dstheight)) { + return(FAILURE); + } + s.left = MAX(rct->left, 0); + s.top = MAX(rct->top, 0); + s.right = MIN(rct->right, dstwidth); + s.bottom = MIN(rct->bottom, dstheight); + if ((s.top >= s.bottom) || (s.left >= s.right)) { + return(FAILURE); + } + r->orgpos = s.top * org->width; + r->orgpos += s.left; + r->dstpos = s.top * dst->width; + r->dstpos += s.left; + } + + pos = src->posy - s.top; + if (pt) { + pos += pt->y; + } + if (pos < 0) { + r->srcpos -= pos * src->width; + r->height = MIN(src->height + pos, s.bottom - s.top); + } + else { + r->orgpos += pos * org->width; + r->dstpos += pos * dst->width; + r->height = MIN(s.bottom - s.top - pos, src->height); + } + if (r->height <= 0) { + return(FAILURE); + } + + pos = src->posx - s.left; + if (pt) { + pos += pt->x; + } + if (pos < 0) { + r->srcpos -= pos; + r->width = MIN(src->width + pos, s.right - s.left); + } + else { + r->orgpos += pos; + r->dstpos += pos; + r->width = MIN(s.right - s.left - pos, src->width); + } + if (r->width <= 0) { + return(FAILURE); + } + return(SUCCESS); +} + + +// ---- + +static void vramsub_cpy(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + + p = src->ptr + (mr->srcpos * src->xalign); + q = dst->ptr + (mr->dstpos * src->xalign); + do { + CopyMemory(q, p, mr->width * src->xalign); + p += src->yalign; + q += dst->yalign; + } while(--mr->height); +} + +static void vramsub_move(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int align; + int r; + + align = mr->width * src->xalign; + p = src->ptr + (mr->srcpos * src->xalign); + q = dst->ptr + (mr->dstpos * src->xalign); + if ((src->ptr != dst->ptr) || (p >= q)) { + do { + CopyMemory(q, p, align); + p += src->yalign; + q += dst->yalign; + } while(--mr->height); + } + else { + p += (mr->height * src->yalign); + q += (mr->height * dst->yalign); + do { + p -= src->yalign - align; + q -= dst->yalign - align; + r = align; + do { + p--; + q--; + *q = *p; + } while(--r); + } while(--mr->height); + } +} +static void vramsub_cpyall(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int height; + + p = src->ptr + (mr->srcpos * src->xalign); + q = dst->ptr + (mr->dstpos * src->xalign); + height = mr->height; + do { + CopyMemory(q, p, mr->width * src->xalign); + p += src->yalign; + q += dst->yalign; + } while(--height); + if ((src->alpha) && (dst->alpha)) { + p = src->alpha + mr->srcpos; + q = dst->alpha + mr->dstpos; + do { + CopyMemory(q, p, mr->width); + p += src->width; + q += dst->width; + } while(--mr->height); + } +} + +static void vramsub_cpy2(VRAMHDL dst, const VRAMHDL src, UINT alpha, + MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT8 *r; + + p = src->ptr + (mr->srcpos * src->xalign); + q = dst->ptr + (mr->dstpos * src->xalign); + r = dst->alpha + mr->dstpos; + do { + CopyMemory(q, p, mr->width * src->xalign); + FillMemory(r, mr->width, alpha); + p += src->yalign; + q += dst->yalign; + r += dst->width; + } while(--mr->height); +} + + +// ---- bpp=16 + +#ifdef SUPPORT_16BPP + +static void vramsub_cpyp16(VRAMHDL dst, const VRAMHDL src, const UINT8 *pat8, + MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int posx; + int posy; + + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + posx = mr->dstpos % dst->width; + posy = mr->dstpos / dst->width; + step = mr->width * 2; + + do { + UINT pat; + x = mr->width; + pat = pat8[posy & 7]; + posy++; + pat <<= (posx & 7); + pat |= (pat >> 8); + do { + pat <<= 1; + if (pat & 0x100) { + *(UINT16 *)q = *(UINT16 *)p; + pat++; + } + p += 2; + q += 2; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyp16w16(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int posx; + + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + posx = mr->dstpos % dst->width; + step = mr->width * 2; + + do { + UINT32 pat; + x = mr->width; + pat = pat16; + pat |= (pat << 16); + pat >>= (posx & 15); + do { + if (pat & 1) { + *(UINT16 *)q = *(UINT16 *)p; + pat |= 0x10000; + } + pat >>= 1; + p += 2; + q += 2; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyp16h16(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int step; + int posy; + + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + posy = mr->dstpos / dst->width; + step = mr->width * 2; + + do { + if (pat16 & (1 << (posy & 15))) { + CopyMemory(q, p, step); + } + posy++; + p += src->yalign; + q += dst->yalign; + } while(--mr->height); +} + +static void vramsub_cpyex16(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + step = mr->width * 2; + + do { + x = mr->width; + do { + UINT16 dat; + dat = *(UINT16 *)p; + p += 2; + if (dat) { + *(UINT16 *)q = dat; + } + q += 2; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyex16a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + + a = src->alpha + mr->srcpos; + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + step = mr->width * 2; + + do { + x = mr->width; + do { + UINT alpha; + alpha = *a++; + if (alpha) { + UINT s1, s2, d; + s1 = *(UINT16 *)p; + s2 = *(UINT16 *)q; + alpha += VRAMALPHABASE; + d = MAKEALPHA16(s2, s1, B16MASK, alpha, VRAMALPHABIT); + d |= MAKEALPHA16(s2, s1, G16MASK, alpha, VRAMALPHABIT); + d |= MAKEALPHA16(s2, s1, R16MASK, alpha, VRAMALPHABIT); + *(UINT16 *)q = (UINT16)d; + } + p += 2; + q += 2; + } while(--x); + a += src->width - mr->width; + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyex16a2(VRAMHDL dst, const VRAMHDL src, + UINT alpha64, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + + a = src->alpha + mr->srcpos; + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + step = mr->width * 2; + + do { + x = mr->width; + do { + UINT alpha; + alpha = *a++; + if (alpha) { + UINT s1, s2, d; + alpha = (alpha + VRAMALPHABASE) * alpha64; + s1 = *(UINT16 *)p; + s2 = *(UINT16 *)q; + d = MAKEALPHA16(s2, s1, B16MASK, alpha, VRAMALPHABIT+6); + d |= MAKEALPHA16(s2, s1, G16MASK, alpha, VRAMALPHABIT+6); + d |= MAKEALPHA16(s2, s1, R16MASK, alpha, VRAMALPHABIT+6); + *(UINT16 *)q = (UINT16)d; + } + p += 2; + q += 2; + } while(--x); + a += src->width - mr->width; + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyexa16a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + UINT8 *b; + int x; + int step; + + p = src->ptr + (mr->srcpos * 2); + a = src->alpha + mr->srcpos; + q = dst->ptr + (mr->dstpos * 2); + b = dst->alpha + mr->dstpos; + step = mr->width * 2; + + do { + x = mr->width; + do { + UINT alpha; + alpha = *a++; + if (alpha) { + UINT s1, s2, d; + s1 = *(UINT16 *)p; + s2 = *(UINT16 *)q; + alpha += VRAMALPHABASE; + d = MAKEALPHA16(s2, s1, B16MASK, alpha, VRAMALPHABIT); + d |= MAKEALPHA16(s2, s1, G16MASK, alpha, VRAMALPHABIT); + d |= MAKEALPHA16(s2, s1, R16MASK, alpha, VRAMALPHABIT); + *(UINT16 *)q = (UINT16)d; + b[0] = VRAMALPHA; + } + p += 2; + q += 2; + b += 1; + } while(--x); + p += src->yalign - step; + a += src->width - mr->width; + q += dst->yalign - step; + b += dst->width - mr->width; + } while(--mr->height); +} + +static void vramsub_cpya16(VRAMHDL dst, const VRAMHDL src, + UINT alpha256, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + step = mr->width * 2; + + do { + x = mr->width; + do { + UINT s1, s2, d; + s1 = *(UINT16 *)p; + s2 = *(UINT16 *)q; + d = MAKEALPHA16(s2, s1, B16MASK, alpha256, 8); + d |= MAKEALPHA16(s2, s1, G16MASK, alpha256, 8); + d |= MAKEALPHA16(s2, s1, R16MASK, alpha256, 8); + *(UINT16 *)q = (UINT16)d; + p += 2; + q += 2; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyexp16w16(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + int posx; + + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + a = src->alpha + mr->srcpos; + posx = mr->dstpos % dst->width; + step = mr->width * 2; + + do { + UINT32 pat; + x = mr->width; + pat = pat16; + pat |= (pat << 16); + pat >>= (posx & 15); + do { + if (pat & 1) { + UINT alpha; + alpha = *a; + if (alpha) { + UINT s1, s2, d; + s1 = *(UINT16 *)p; + s2 = *(UINT16 *)q; + alpha += VRAMALPHABASE; + d = MAKEALPHA16(s2, s1, B16MASK, alpha, VRAMALPHABIT); + d |= MAKEALPHA16(s2, s1, G16MASK, alpha, VRAMALPHABIT); + d |= MAKEALPHA16(s2, s1, R16MASK, alpha, VRAMALPHABIT); + *(UINT16 *)q = (UINT16)d; + } + pat |= 0x10000; + } + pat >>= 1; + p += 2; + q += 2; + a += 1; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + a += src->width - mr->width; + } while(--mr->height); +} + +static void vramsub_cpyexp16h16(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + int posy; + + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + a = src->alpha + mr->srcpos; + posy = mr->dstpos / dst->width; + step = mr->width * 2; + + do { + if (pat16 & (1 << (posy & 15))) { + x = mr->width; + do { + UINT alpha; + alpha = *a; + if (alpha) { + UINT s1, s2, d; + s1 = *(UINT16 *)p; + s2 = *(UINT16 *)q; + alpha += VRAMALPHABASE; + d = MAKEALPHA16(s2, s1, B16MASK, alpha, VRAMALPHABIT); + d |= MAKEALPHA16(s2, s1, G16MASK, alpha, VRAMALPHABIT); + d |= MAKEALPHA16(s2, s1, R16MASK, alpha, VRAMALPHABIT); + *(UINT16 *)q = (UINT16)d; + } + p += 2; + q += 2; + a += 1; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + a += src->width - mr->width; + } + else { + p += src->yalign; + q += dst->yalign; + a += src->width; + } + posy++; + } while(--mr->height); +} + +static void vramsub_mix16(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, + UINT alpha64, MIXRECTEX *mr) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int x; + int ostep; + int sstep; + int dstep; + + p = org->ptr + (mr->orgpos * 2); + q = src->ptr + (mr->srcpos * 2); + r = dst->ptr + (mr->dstpos * 2); + ostep = org->yalign - (mr->width * 2); + sstep = src->yalign - (mr->width * 2); + dstep = dst->yalign - (mr->width * 2); + + do { + x = mr->width; + do { + UINT s1, s2, d; + s1 = *(UINT16 *)p; + s2 = *(UINT16 *)q; + d = MAKEALPHA16(s1, s2, B16MASK, alpha64, 6); + d |= MAKEALPHA16(s1, s2, G16MASK, alpha64, 6); + d |= MAKEALPHA16(s1, s2, R16MASK, alpha64, 6); + *(UINT16 *)r = (UINT16)d; + p += 2; + q += 2; + r += 2; + } while(--x); + p += ostep; + q += sstep; + r += dstep; + } while(--mr->height); +} + +static void vramsub_mixcol16(VRAMHDL dst, const VRAMHDL src, UINT32 color, + UINT alpha64, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int tmp; + int c16[3]; + + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + step = mr->width * 2; + + tmp = MAKE16PAL(color); + c16[0] = tmp & B16MASK; + c16[1] = tmp & G16MASK; + c16[2] = tmp & R16MASK; + do { + x = mr->width; + do { + UINT s, d; + s = *(UINT16 *)p; + d = MAKEALPHA16s(c16[0], s, B16MASK, alpha64, 6); + d |= MAKEALPHA16s(c16[1], s, G16MASK, alpha64, 6); + d |= MAKEALPHA16s(c16[2], s, R16MASK, alpha64, 6); + *(UINT16 *)q = (UINT16)d; + p += 2; + q += 2; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_mixalpha16(VRAMHDL dst, const VRAMHDL src, UINT32 color, + MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int tmp; + int c16[3]; + + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + step = mr->width * 2; + + tmp = MAKE16PAL(color); + c16[0] = tmp & B16MASK; + c16[1] = tmp & G16MASK; + c16[2] = tmp & R16MASK; + do { + x = mr->width; + do { + UINT s, d, e; + int a; + s = *(UINT16 *)q; + e = *(UINT16 *)p; + e ^= 0xffff; + a = e & 0x1f; + if (a) { + a++; + } + d = MAKEALPHA16s(c16[0], s, B16MASK, a, 5); + a = (e >> 5) & 0x3f; + if (a) { + a++; + } + d |= MAKEALPHA16s(c16[1], s, G16MASK, a, 6); + a = (e >> 11) & 0x1f; + if (a) { + a++; + } + d |= MAKEALPHA16s(c16[2], s, R16MASK, a, 5); + *(UINT16 *)q = (UINT16)d; + p += 2; + q += 2; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_gray16(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, + const VRAMHDL bmp, int delta, MIXRECTEX *mr) { + +const UINT8 *p; +const UINT8 *q; +const UINT8 *a; + UINT8 *r; + int rm; + int x, y; + int ostep; + int sstep; + int dstep; + int xstep; + int ystep; + + if ((bmp == NULL) || (bmp->bpp != 8)) { + return; + } + + p = org->ptr + (mr->orgpos * 2); + q = src->ptr + (mr->srcpos * 2); + r = dst->ptr + (mr->dstpos * 2); + ostep = org->yalign - (mr->width * 2); + sstep = src->yalign - (mr->width * 2); + dstep = dst->yalign - (mr->width * 2); + + xstep = (bmp->width << 10) / mr->width; + ystep = (bmp->height << 10) / mr->height; + + y = 0; + do { + a = bmp->ptr + ((y >> 10) * bmp->yalign); + rm = mr->width; + x = 0; + do { + int alpha; + alpha = a[x >> 10] + delta + 1; + if (alpha >= 256) { + *(UINT16 *)r = *(UINT16 *)q; + } + else if (alpha > 0) { + UINT s1, s2, d; + s1 = *(UINT16 *)p; + s2 = *(UINT16 *)q; + d = MAKEALPHA16(s1, s2, B16MASK, alpha, 8); + d |= MAKEALPHA16(s1, s2, G16MASK, alpha, 8); + d |= MAKEALPHA16(s1, s2, R16MASK, alpha, 8); + *(UINT16 *)r = (UINT16)d; + } + else { + *(UINT16 *)r = *(UINT16 *)p; + } + p += 2; + q += 2; + r += 2; + x += xstep; + } while(--rm); + p += ostep; + q += sstep; + r += dstep; + y += ystep; + } while(--mr->height); +} + +static void vramsub_zoom16(VRAMHDL dst, const VRAMHDL src, int dot, + MIX_RECT *mr) { + +const UINT8 *pbase; +const UINT8 *p; + UINT8 *qbase; + UINT8 *q; + int x; + int dstep; + int xstep; + int ystep; + int xx; + int yy; + int xstep2; + UINT16 col; + + pbase = src->ptr + (mr->srcpos * 2); + qbase = dst->ptr + (mr->dstpos * 2); + dstep = (dst->yalign * dot) - (mr->width * 2); + + do { + p = pbase; + ystep = MIN(mr->height, dot); + x = mr->width; + do { + xstep = MIN(x, dot); + xstep2 = xstep * 2; + q = qbase; + yy = ystep; + col = *(UINT16 *)p; + do { + xx = xstep; + do { + *(UINT16 *)q = col; + q += 2; + } while(--xx); + q += dst->yalign; + q -= xstep2; + } while(--yy); + p += 2; + qbase += xstep2; + x -= xstep; + } while(x); + pbase += src->yalign; + qbase += dstep; + mr->height -= ystep; + } while(mr->height); +} + +static void vramsub_mosaic16(VRAMHDL dst, const VRAMHDL src, int dot, + MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT8 *r; + int x; + int sstep; + int dstep; + int xstep; + int ystep; + int xx; + int yy; + int xstep2; + UINT16 col; + + p = src->ptr + (mr->srcpos * 2); + q = dst->ptr + (mr->dstpos * 2); + sstep = (src->yalign * dot) - (mr->width * 2); + dstep = (dst->yalign * dot) - (mr->width * 2); + + do { + ystep = MIN(mr->height, dot); + x = mr->width; + do { + xstep = MIN(x, dot); + xstep2 = xstep * 2; + r = q; + yy = ystep; + col = *(UINT16 *)p; + do { + xx = xstep; + do { + *(UINT16 *)r = col; + r += 2; + } while(--xx); + r += dst->yalign; + r -= xstep2; + } while(--yy); + p += xstep2; + q += xstep2; + x -= xstep; + } while(x); + p += sstep; + q += dstep; + mr->height -= ystep; + } while(mr->height); +} + +static void vramsub_colex16(VRAMHDL dst, const VRAMHDL src, UINT32 color, + MIX_RECT *mr) { + + UINT8 *p, *q; + int x; + int step; + UINT tmp; + int c16[3]; + int a; + + tmp = MAKE16PAL(color); + c16[0] = tmp & B16MASK; + c16[1] = tmp & G16MASK; + c16[2] = tmp & R16MASK; + + p = src->ptr + mr->srcpos; + q = dst->ptr + (mr->dstpos * 2); + step = mr->width * 2; + + do { + x = mr->width; + do { + a = p[0]; + if (a) { + UINT s, d; + a = VRAMALPHA - a; + s = *(UINT16 *)q; + d = MAKEALPHA16s(c16[0], s, B16MASK, a, VRAMALPHABIT); + d |= MAKEALPHA16s(c16[1], s, G16MASK, a, VRAMALPHABIT); + d |= MAKEALPHA16s(c16[2], s, R16MASK, a, VRAMALPHABIT); + *(UINT16 *)q = (UINT16)d; + } + p += 1; + q += 2; + } while(--x); + p += src->width - mr->width; + q += dst->yalign - step; + } while(--mr->height); +} +#endif + + +// ---- bpp=24 + +#ifdef SUPPORT_24BPP + +static void vramsub_cpyp24(VRAMHDL dst, const VRAMHDL src, const UINT8 *pat8, + MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int posx; + int posy; + + p = src->ptr + (mr->srcpos * 3); + q = dst->ptr + (mr->dstpos * 3); + posx = mr->dstpos % dst->width; + posy = mr->dstpos / dst->width; + step = mr->width * 3; + + do { + UINT pat; + x = mr->width; + pat = pat8[posy & 7]; + posy++; + pat <<= (posx & 7); + pat |= (pat >> 8); + do { + pat <<= 1; + if (pat & 0x100) { + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[2]; + pat++; + } + p += 3; + q += 3; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyp16w24(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int posx; + + p = src->ptr + (mr->srcpos * 3); + q = dst->ptr + (mr->dstpos * 3); + posx = mr->dstpos % dst->width; + step = mr->width * 3; + + do { + UINT32 pat; + x = mr->width; + pat = pat16; + pat |= (pat << 16); + pat >>= (posx & 15); + do { + if (pat & 1) { + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[2]; + pat |= 0x10000; + } + pat >>= 1; + p += 3; + q += 3; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyp16h24(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int step; + int posy; + + p = src->ptr + (mr->srcpos * 3); + q = dst->ptr + (mr->dstpos * 3); + posy = mr->dstpos / dst->width; + step = mr->width * 3; + + do { + if (pat16 & (1 << (posy & 15))) { + CopyMemory(q, p, step); + } + posy++; + p += src->yalign; + q += dst->yalign; + } while(--mr->height); +} + +static void vramsub_cpyex24(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + + p = src->ptr + (mr->srcpos * src->xalign); + q = dst->ptr + (mr->dstpos * src->xalign); + step = mr->width * 3; + + do { + x = mr->width; + do { + UINT8 r, g, b; + b = p[0]; + g = p[1]; + r = p[2]; + p += 3; + if ((b) || (g) || (r)) { + q[0] = b; + q[1] = g; + q[2] = r; + } + q += 3; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyex24a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + + a = src->alpha + mr->srcpos; + p = src->ptr + (mr->srcpos * 3); + q = dst->ptr + (mr->dstpos * 3); + step = mr->width * 3; + + do { + x = mr->width; + do { + UINT alpha; + alpha = *a++; + if (alpha) { + alpha += VRAMALPHABASE; + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); + } + p += 3; + q += 3; + } while(--x); + a += src->width - mr->width; + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyex24a2(VRAMHDL dst, const VRAMHDL src, + UINT alpha64, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + + a = src->alpha + mr->srcpos; + p = src->ptr + (mr->srcpos * 3); + q = dst->ptr + (mr->dstpos * 3); + step = mr->width * 3; + + do { + x = mr->width; + do { + UINT alpha; + alpha = *a++; + if (alpha) { + alpha = (alpha + VRAMALPHABASE) * alpha64; + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT+6); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT+6); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT+6); + } + p += 3; + q += 3; + } while(--x); + a += src->width - mr->width; + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyexa24a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + UINT8 *b; + int x; + int step; + + p = src->ptr + (mr->srcpos * 3); + a = src->alpha + mr->srcpos; + q = dst->ptr + (mr->dstpos * 3); + b = dst->alpha + mr->dstpos; + step = mr->width * 3; + + do { + x = mr->width; + do { + UINT alpha; + alpha = *a++; + if (alpha) { + alpha += VRAMALPHABASE; + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); + b[0] = VRAMALPHA; + } + p += 3; + q += 3; + b += 1; + } while(--x); + p += src->yalign - step; + a += src->width - mr->width; + q += dst->yalign - step; + b += dst->width - mr->width; + } while(--mr->height); +} + +static void vramsub_cpya24(VRAMHDL dst, const VRAMHDL src, + UINT alpha256, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + + p = src->ptr + (mr->srcpos * 3); + q = dst->ptr + (mr->dstpos * 3); + step = mr->width * 3; + + do { + x = mr->width; + do { + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha256, 8); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha256, 8); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha256, 8); + p += 3; + q += 3; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyexp16w24(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + int posx; + + p = src->ptr + (mr->srcpos * 3); + q = dst->ptr + (mr->dstpos * 3); + a = src->alpha + mr->srcpos; + posx = mr->dstpos % dst->width; + step = mr->width * 3; + + do { + UINT32 pat; + x = mr->width; + pat = pat16; + pat |= (pat << 16); + pat >>= (posx & 15); + do { + if (pat & 1) { + UINT alpha; + alpha = *a; + if (alpha) { + alpha += VRAMALPHABASE; + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); + } + pat |= 0x10000; + } + pat >>= 1; + p += 3; + q += 3; + a += 1; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + a += src->width - mr->width; + } while(--mr->height); +} + +static void vramsub_cpyexp16h24(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + int posy; + + p = src->ptr + (mr->srcpos * 3); + q = dst->ptr + (mr->dstpos * 3); + a = src->alpha + mr->srcpos; + posy = mr->dstpos / dst->width; + step = mr->width * 3; + + do { + if (pat16 & (1 << (posy & 15))) { + x = mr->width; + do { + UINT alpha; + alpha = *a; + if (alpha) { + alpha += VRAMALPHABASE; + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); + } + p += 3; + q += 3; + a += 1; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + a += src->width - mr->width; + } + else { + p += src->yalign; + q += dst->yalign; + a += src->width; + } + posy++; + } while(--mr->height); +} + +static void vramsub_mix24(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, + UINT alpha64, MIXRECTEX *mr) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int x; + int ostep; + int sstep; + int dstep; + + p = org->ptr + (mr->orgpos * 3); + q = src->ptr + (mr->srcpos * 3); + r = dst->ptr + (mr->dstpos * 3); + ostep = org->yalign - (mr->width * 3); + sstep = src->yalign - (mr->width * 3); + dstep = dst->yalign - (mr->width * 3); + + do { + x = mr->width; + do { + r[0] = (UINT8)MAKEALPHA24(p[0], q[0], alpha64, 6); + r[1] = (UINT8)MAKEALPHA24(p[1], q[1], alpha64, 6); + r[2] = (UINT8)MAKEALPHA24(p[2], q[2], alpha64, 6); + p += 3; + q += 3; + r += 3; + } while(--x); + p += ostep; + q += sstep; + r += dstep; + } while(--mr->height); +} + +static void vramsub_mixcol24(VRAMHDL dst, const VRAMHDL src, UINT32 color, + UINT alpha64, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int c24[3]; + + p = src->ptr + (mr->srcpos * 3); + q = dst->ptr + (mr->dstpos * 3); + step = mr->width * 3; + + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + do { + x = mr->width; + do { + q[0] = (UINT8)MAKEALPHA24(c24[0], p[0], alpha64, 6); + q[1] = (UINT8)MAKEALPHA24(c24[1], p[1], alpha64, 6); + q[2] = (UINT8)MAKEALPHA24(c24[2], p[2], alpha64, 6); + p += 3; + q += 3; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_mixalpha24(VRAMHDL dst, const VRAMHDL src, UINT32 color, + MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int c24[3]; + + p = src->ptr + (mr->srcpos * src->xalign); + q = dst->ptr + (mr->dstpos * src->xalign); + step = mr->width * 3; + + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + do { + x = mr->width; + do { + int a; + a = p[0]; + if (a) { + a++; + } + q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], a, 8); + a = p[1]; + if (a) { + a++; + } + q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], a, 8); + a = p[2]; + if (a) { + a++; + } + q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], a, 8); + p += 3; + q += 3; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_gray24(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, + const VRAMHDL bmp, int delta, MIXRECTEX *mr) { + +const UINT8 *p; +const UINT8 *q; +const UINT8 *a; + UINT8 *r; + int rm; + int x, y; + int ostep; + int sstep; + int dstep; + int xstep; + int ystep; + + if ((bmp == NULL) || (bmp->bpp != 8)) { + return; + } + + p = org->ptr + (mr->orgpos * 3); + q = src->ptr + (mr->srcpos * 3); + r = dst->ptr + (mr->dstpos * 3); + ostep = org->yalign - (mr->width * 3); + sstep = src->yalign - (mr->width * 3); + dstep = dst->yalign - (mr->width * 3); + + xstep = (bmp->width << 10) / mr->width; + ystep = (bmp->height << 10) / mr->height; + + y = 0; + do { + a = bmp->ptr + ((y >> 10) * bmp->yalign); + rm = mr->width; + x = 0; + do { + int alpha; + alpha = a[x >> 10] + delta + 1; + if (alpha >= 256) { + r[0] = q[0]; + r[1] = q[1]; + r[2] = q[2]; + } + else if (alpha > 0) { + r[0] = (UINT8)MAKEALPHA24(p[0], q[0], alpha, 8); + r[1] = (UINT8)MAKEALPHA24(p[1], q[1], alpha, 8); + r[2] = (UINT8)MAKEALPHA24(p[2], q[2], alpha, 8); + } + else { + r[0] = p[0]; + r[1] = p[1]; + r[2] = p[2]; + } + p += 3; + q += 3; + r += 3; + x += xstep; + } while(--rm); + p += ostep; + q += sstep; + r += dstep; + y += ystep; + } while(--mr->height); +} + +static void vramsub_zoom24(VRAMHDL dst, const VRAMHDL src, int dot, + MIX_RECT *mr) { + +const UINT8 *pbase; +const UINT8 *p; + UINT8 *qbase; + UINT8 *q; + int x; + int dstep; + int xstep; + int ystep; + int xx; + int yy; + int xstep3; + + pbase = src->ptr + (mr->srcpos * 3); + qbase = dst->ptr + (mr->dstpos * 3); + dstep = (dst->yalign * dot) - (mr->width * 3); + + do { + p = pbase; + ystep = MIN(mr->height, dot); + x = mr->width; + do { + xstep = MIN(x, dot); + xstep3 = xstep * 3; + q = qbase; + yy = ystep; + do { + xx = xstep; + do { + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[2]; + q += 3; + } while(--xx); + q += dst->yalign; + q -= xstep3; + } while(--yy); + p += 3; + qbase += xstep3; + x -= xstep; + } while(x); + pbase += src->yalign; + qbase += dstep; + mr->height -= ystep; + } while(mr->height); +} + +static void vramsub_mosaic24(VRAMHDL dst, const VRAMHDL src, int dot, + MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT8 *r; + int x; + int sstep; + int dstep; + int xstep; + int ystep; + int xx; + int yy; + int xstep3; + + p = src->ptr + (mr->srcpos * 3); + q = dst->ptr + (mr->dstpos * 3); + sstep = (src->yalign * dot) - (mr->width * 3); + dstep = (dst->yalign * dot) - (mr->width * 3); + + do { + ystep = MIN(mr->height, dot); + x = mr->width; + do { + xstep = MIN(x, dot); + xstep3 = xstep * 3; + r = q; + yy = ystep; + do { + xx = xstep; + do { + r[0] = p[0]; + r[1] = p[1]; + r[2] = p[2]; + r += 3; + } while(--xx); + r += dst->yalign; + r -= xstep3; + } while(--yy); + p += xstep3; + q += xstep3; + x -= xstep; + } while(x); + p += sstep; + q += dstep; + mr->height -= ystep; + } while(mr->height); +} + +static void vramsub_colex24(VRAMHDL dst, const VRAMHDL src, UINT32 color, + MIX_RECT *mr) { + + UINT8 *p, *q; + int x; + int step; + int c24[3]; + int a; + + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + + p = src->ptr + mr->srcpos; + q = dst->ptr + (mr->dstpos * dst->xalign); + step = mr->width * 3; + + do { + x = mr->width; + do { + a = p[0]; + if (a) { + a += VRAMALPHABASE; + q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], a, VRAMALPHABIT); + q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], a, VRAMALPHABIT); + q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], a, VRAMALPHABIT); + } + p += 1; + q += 3; + } while(--x); + p += src->width - mr->width; + q += dst->yalign - step; + } while(--mr->height); +} +#endif + + +// ---- bpp=32 + +#ifdef SUPPORT_32BPP + +static void vramsub_cpyp32(VRAMHDL dst, const VRAMHDL src, const UINT8 *pat8, + MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int posx; + int posy; + + p = src->ptr + (mr->srcpos * 4); + q = dst->ptr + (mr->dstpos * 4); + posx = mr->dstpos % dst->width; + posy = mr->dstpos / dst->width; + step = mr->width * 4; + + do { + UINT pat; + x = mr->width; + pat = pat8[posy & 7]; + posy++; + pat <<= (posx & 7); + pat |= (pat >> 8); + do { + pat <<= 1; + if (pat & 0x100) { + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[2]; + pat++; + } + p += 4; + q += 4; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyp16w32(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int posx; + + p = src->ptr + (mr->srcpos * 4); + q = dst->ptr + (mr->dstpos * 4); + posx = mr->dstpos % dst->width; + step = mr->width * 4; + + do { + UINT32 pat; + x = mr->width; + pat = pat16; + pat |= (pat << 16); + pat >>= (posx & 15); + do { + if (pat & 1) { + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[2]; + pat |= 0x10000; + } + pat >>= 1; + p += 4; + q += 4; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyp16h32(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int step; + int posy; + + p = src->ptr + (mr->srcpos * 4); + q = dst->ptr + (mr->dstpos * 4); + posy = mr->dstpos / dst->width; + step = mr->width * 4; + + do { + if (pat16 & (1 << (posy & 15))) { + CopyMemory(q, p, step); + } + posy++; + p += src->yalign; + q += dst->yalign; + } while(--mr->height); +} + +static void vramsub_cpyex32(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + + p = src->ptr + (mr->srcpos * src->xalign); + q = dst->ptr + (mr->dstpos * src->xalign); + step = mr->width * 4; + + do { + x = mr->width; + do { + UINT8 r, g, b; + b = p[0]; + g = p[1]; + r = p[2]; + p += 4; + if ((b) || (g) || (r)) { + q[0] = b; + q[1] = g; + q[2] = r; + } + q += 4; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyex32a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + + a = src->alpha + mr->srcpos; + p = src->ptr + (mr->srcpos * 4); + q = dst->ptr + (mr->dstpos * 4); + step = mr->width * 4; + + do { + x = mr->width; + do { + UINT alpha; + alpha = *a++; + if (alpha) { + alpha += VRAMALPHABASE; + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); + } + p += 4; + q += 4; + } while(--x); + a += src->width - mr->width; + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyex32a2(VRAMHDL dst, const VRAMHDL src, + UINT alpha64, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + + a = src->alpha + mr->srcpos; + p = src->ptr + (mr->srcpos * 4); + q = dst->ptr + (mr->dstpos * 4); + step = mr->width * 4; + + do { + x = mr->width; + do { + UINT alpha; + alpha = *a++; + if (alpha) { + alpha = (alpha + VRAMALPHABASE) * alpha64; + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT+6); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT+6); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT+6); + } + p += 4; + q += 4; + } while(--x); + a += src->width - mr->width; + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyexa32a(VRAMHDL dst, const VRAMHDL src, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + UINT8 *b; + int x; + int step; + + p = src->ptr + (mr->srcpos * 4); + + a = src->alpha + mr->srcpos; + q = dst->ptr + (mr->dstpos * 4); + b = dst->alpha + mr->dstpos; + step = mr->width * 4; + + do { + x = mr->width; + do { + UINT alpha; + alpha = *a++; + if (alpha) { + alpha += VRAMALPHABASE; + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); + b[0] = VRAMALPHA; + } + p += 4; + q += 4; + b += 1; + } while(--x); + p += src->yalign - step; + a += src->width - mr->width; + q += dst->yalign - step; + b += dst->width - mr->width; + } while(--mr->height); +} + +static void vramsub_cpya32(VRAMHDL dst, const VRAMHDL src, + UINT alpha256, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + + p = src->ptr + (mr->srcpos * 4); + q = dst->ptr + (mr->dstpos * 4); + step = mr->width * 4; + + do { + x = mr->width; + do { + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha256, 8); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha256, 8); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha256, 8); + p += 4; + q += 4; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_cpyexp16w32(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + int posx; + + p = src->ptr + (mr->srcpos * 4); + q = dst->ptr + (mr->dstpos * 4); + a = src->alpha + mr->srcpos; + posx = mr->dstpos % dst->width; + step = mr->width * 4; + + do { + UINT32 pat; + x = mr->width; + pat = pat16; + pat |= (pat << 16); + pat >>= (posx & 15); + do { + if (pat & 1) { + UINT alpha; + alpha = *a; + if (alpha) { + alpha += VRAMALPHABASE; + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); + } + pat |= 0x10000; + } + pat >>= 1; + p += 4; + q += 4; + a += 1; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + a += src->width - mr->width; + } while(--mr->height); +} + +static void vramsub_cpyexp16h32(VRAMHDL dst, const VRAMHDL src, + UINT pat16, MIX_RECT *mr) { + +const UINT8 *p; +const UINT8 *a; + UINT8 *q; + int x; + int step; + int posy; + + p = src->ptr + (mr->srcpos * 4); + q = dst->ptr + (mr->dstpos * 4); + a = src->alpha + mr->srcpos; + posy = mr->dstpos / dst->width; + step = mr->width * 4; + + do { + if (pat16 & (1 << (posy & 15))) { + x = mr->width; + do { + UINT alpha; + alpha = *a; + if (alpha) { + alpha += VRAMALPHABASE; + q[0] = (UINT8)MAKEALPHA24(q[0], p[0], alpha, VRAMALPHABIT); + q[1] = (UINT8)MAKEALPHA24(q[1], p[1], alpha, VRAMALPHABIT); + q[2] = (UINT8)MAKEALPHA24(q[2], p[2], alpha, VRAMALPHABIT); + } + p += 4; + q += 4; + a += 1; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + a += src->width - mr->width; + } + else { + p += src->yalign; + q += dst->yalign; + a += src->width; + } + posy++; + } while(--mr->height); +} + +static void vramsub_mix32(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, + UINT alpha64, MIXRECTEX *mr) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int x; + int ostep; + int sstep; + int dstep; + + p = org->ptr + (mr->orgpos * 4); + q = src->ptr + (mr->srcpos * 4); + r = dst->ptr + (mr->dstpos * 4); + ostep = org->yalign - (mr->width * 4); + sstep = src->yalign - (mr->width * 4); + dstep = dst->yalign - (mr->width * 4); + + do { + x = mr->width; + do { + r[0] = (UINT8)MAKEALPHA24(p[0], q[0], alpha64, 6); + r[1] = (UINT8)MAKEALPHA24(p[1], q[1], alpha64, 6); + r[2] = (UINT8)MAKEALPHA24(p[2], q[2], alpha64, 6); + p += 4; + q += 4; + r += 4; + } while(--x); + p += ostep; + q += sstep; + r += dstep; + } while(--mr->height); +} + +static void vramsub_mixcol32(VRAMHDL dst, const VRAMHDL src, UINT32 color, + UINT alpha64, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int c24[3]; + + p = src->ptr + (mr->srcpos * 4); + q = dst->ptr + (mr->dstpos * 4); + step = mr->width * 4; + + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + do { + x = mr->width; + do { + q[0] = (UINT8)MAKEALPHA24(c24[0], p[0], alpha64, 6); + q[1] = (UINT8)MAKEALPHA24(c24[1], p[1], alpha64, 6); + q[2] = (UINT8)MAKEALPHA24(c24[2], p[2], alpha64, 6); + p += 4; + q += 4; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_mixalpha32(VRAMHDL dst, const VRAMHDL src, UINT32 color, + MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + int x; + int step; + int c24[3]; + + p = src->ptr + (mr->srcpos * src->xalign); + q = dst->ptr + (mr->dstpos * src->xalign); + step = mr->width * 4; + + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + do { + x = mr->width; + do { + int a; + a = p[0]; + if (a) { + a++; + } + q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], a, 8); + a = p[1]; + if (a) { + a++; + } + q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], a, 8); + a = p[2]; + if (a) { + a++; + } + q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], a, 8); + p += 4; + q += 4; + } while(--x); + p += src->yalign - step; + q += dst->yalign - step; + } while(--mr->height); +} + +static void vramsub_gray32(VRAMHDL dst, const VRAMHDL org, const VRAMHDL src, + const VRAMHDL bmp, int delta, MIXRECTEX *mr) { + +const UINT8 *p; +const UINT8 *q; +const UINT8 *a; + UINT8 *r; + int rm; + int x, y; + int ostep; + int sstep; + int dstep; + int xstep; + int ystep; + + if ((bmp == NULL) || (bmp->bpp != 8)) { + return; + } + + p = org->ptr + (mr->orgpos * 4); + q = src->ptr + (mr->srcpos * 4); + r = dst->ptr + (mr->dstpos * 4); + ostep = org->yalign - (mr->width * 4); + sstep = src->yalign - (mr->width * 4); + dstep = dst->yalign - (mr->width * 4); + + xstep = (bmp->width << 10) / mr->width; + ystep = (bmp->height << 10) / mr->height; + + y = 0; + do { + a = bmp->ptr + ((y >> 10) * bmp->yalign); + rm = mr->width; + x = 0; + do { + int alpha; + alpha = a[x >> 10] + delta + 1; + if (alpha >= 256) { + r[0] = q[0]; + r[1] = q[1]; + r[2] = q[2]; + } + else if (alpha > 0) { + r[0] = (UINT8)MAKEALPHA24(p[0], q[0], alpha, 8); + r[1] = (UINT8)MAKEALPHA24(p[1], q[1], alpha, 8); + r[2] = (UINT8)MAKEALPHA24(p[2], q[2], alpha, 8); + } + else { + r[0] = p[0]; + r[1] = p[1]; + r[2] = p[2]; + } + p += 4; + q += 4; + r += 4; + x += xstep; + } while(--rm); + p += ostep; + q += sstep; + r += dstep; + y += ystep; + } while(--mr->height); +} + +static void vramsub_zoom32(VRAMHDL dst, const VRAMHDL src, int dot, + MIX_RECT *mr) { + +const UINT8 *pbase; +const UINT8 *p; + UINT8 *qbase; + UINT8 *q; + int x; + int dstep; + int xstep; + int ystep; + int xx; + int yy; + int xstep3; + + pbase = src->ptr + (mr->srcpos * 4); + qbase = dst->ptr + (mr->dstpos * 4); + dstep = (dst->yalign * dot) - (mr->width * 4); + + do { + p = pbase; + ystep = MIN(mr->height, dot); + x = mr->width; + do { + xstep = MIN(x, dot); + xstep3 = xstep * 4; + q = qbase; + yy = ystep; + do { + xx = xstep; + do { + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[2]; + q += 4; + } while(--xx); + q += dst->yalign; + q -= xstep3; + } while(--yy); + p += 4; + qbase += xstep3; + x -= xstep; + } while(x); + pbase += src->yalign; + qbase += dstep; + mr->height -= ystep; + } while(mr->height); +} + +static void vramsub_mosaic32(VRAMHDL dst, const VRAMHDL src, int dot, + MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT8 *r; + int x; + int sstep; + int dstep; + int xstep; + int ystep; + int xx; + int yy; + int xstep3; + + p = src->ptr + (mr->srcpos * 4); + q = dst->ptr + (mr->dstpos * 4); + sstep = (src->yalign * dot) - (mr->width * 4); + dstep = (dst->yalign * dot) - (mr->width * 4); + + do { + ystep = MIN(mr->height, dot); + x = mr->width; + do { + xstep = MIN(x, dot); + xstep3 = xstep * 4; + r = q; + yy = ystep; + do { + xx = xstep; + do { + r[0] = p[0]; + r[1] = p[1]; + r[2] = p[2]; + r += 4; + } while(--xx); + r += dst->yalign; + r -= xstep3; + } while(--yy); + p += xstep3; + q += xstep3; + x -= xstep; + } while(x); + p += sstep; + q += dstep; + mr->height -= ystep; + } while(mr->height); +} + +static void vramsub_colex32(VRAMHDL dst, const VRAMHDL src, UINT32 color, + MIX_RECT *mr) { + + UINT8 *p, *q; + int x; + int step; + int c24[3]; + + int a; + + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + + p = src->ptr + mr->srcpos; + q = dst->ptr + (mr->dstpos * dst->xalign); + step = mr->width * 4; + + do { + x = mr->width; + do { + a = p[0]; + if (a) { + a += VRAMALPHABASE; + q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], a, VRAMALPHABIT); + q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], a, VRAMALPHABIT); + q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], a, VRAMALPHABIT); + } + p += 1; + q += 4; + } while(--x); + p += src->width - mr->width; + q += dst->yalign - step; + } while(--mr->height); +} +#endif + +// ---- + +// サーフェスをバッファとして使う場合… +// dst(posx, posy) <-src:rct + +void vramcpy_cpy(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct) { + + MIX_RECT mr; + + if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } + vramsub_cpy(dst, src, &mr); +} + +void vramcpy_move(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct) { + + MIX_RECT mr; + + if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } + vramsub_move(dst, src, &mr); +} + +void vramcpy_cpyall(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct) { + + MIX_RECT mr; + + if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } + vramsub_cpyall(dst, src, &mr); +} + +void vramcpy_cpypat(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + const UINT8 *pat8) { + + MIX_RECT mr; + + if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_cpyp16(dst, src, pat8, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_cpyp24(dst, src, pat8, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_cpyp32(dst, src, pat8, &mr); + } +#endif +} + +void vramcpy_cpyex(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct) { + + MIX_RECT mr; + + if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + if (!src->alpha) { + vramsub_cpyex16(dst, src, &mr); + } + else { + vramsub_cpyex16a(dst, src, &mr); + } + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + if (!src->alpha) { + vramsub_cpyex24(dst, src, &mr); + } + else { + vramsub_cpyex24a(dst, src, &mr); + } + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + if (!src->alpha) { + vramsub_cpyex32(dst, src, &mr); + } + else { + vramsub_cpyex32a(dst, src, &mr); + } + } +#endif +} + +void vramcpy_cpyexa(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct) { + + MIX_RECT mr; + + if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || + (dst->bpp != src->bpp) || + (dst->alpha == NULL) || (src->alpha == NULL)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_cpyexa16a(dst, src, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_cpyexa24a(dst, src, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_cpyexa32a(dst, src, &mr); + } +#endif +} + +void vramcpy_cpyalpha(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + UINT alpha256) { + + MIX_RECT mr; + + if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } + if (alpha256 < 256) { + alpha256 = 256 - alpha256; + } + else { + alpha256 = 0; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_cpya16(dst, src, alpha256, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_cpya24(dst, src, alpha256, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_cpya32(dst, src, alpha256, &mr); + } +#endif +} + +void vramcpy_mix(VRAMHDL dst, const VRAMHDL org, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + UINT alpha64) { + + MIXRECTEX mr; + + if (cpyrectex(&mr, dst, pt, org, src, rct) != SUCCESS) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_mix16(dst, org, src, alpha64, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_mix24(dst, org, src, alpha64, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_mix32(dst, org, src, alpha64, &mr); + } +#endif +} + +void vramcpy_mixcol(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + UINT32 color, UINT alpha64) { + + MIX_RECT mr; + + if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_mixcol16(dst, src, color, alpha64, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_mixcol24(dst, src, color, alpha64, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_mixcol32(dst, src, color, alpha64, &mr); + } +#endif +} + +void vramcpy_zoom(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + int dot) { + + MIX_RECT mr; + + if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } + + if (dot <= 0) { + vramsub_cpy(dst, src, &mr); + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_zoom16(dst, src, dot, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_zoom24(dst, src, dot, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_zoom32(dst, src, dot, &mr); + } +#endif +} + +void vramcpy_mosaic(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + int dot) { + + MIX_RECT mr; + + if ((cpyrect(&mr, dst, pt, src, rct) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } + + if (dot <= 0) { + vramsub_cpy(dst, src, &mr); + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_mosaic16(dst, src, dot, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_mosaic24(dst, src, dot, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_mosaic32(dst, src, dot, &mr); + } +#endif +} + + +// ---- + +// サーフェスをウィンドウとして使う場合… +// dst:rct <- src(posx, posy) + +void vrammix_cpy(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } + vramsub_cpy(dst, src, &mr); +} + +void vrammix_cpyall(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } + vramsub_cpyall(dst, src, &mr); +} + +void vrammix_cpy2(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT alpha) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (dst->bpp != src->bpp) || (dst->alpha == NULL)) { + return; + } + vramsub_cpy2(dst, src, alpha, &mr); +} + +void vrammix_cpypat(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const UINT8 *pat8) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_cpyp16(dst, src, pat8, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_cpyp24(dst, src, pat8, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_cpyp32(dst, src, pat8, &mr); + } +#endif +} + +void vrammix_cpypat16w(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const UINT pat16) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_cpyp16w16(dst, src, pat16, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_cpyp16w24(dst, src, pat16, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_cpyp16w32(dst, src, pat16, &mr); + } +#endif +} + +void vrammix_cpypat16h(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const UINT pat16) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_cpyp16h16(dst, src, pat16, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_cpyp16h24(dst, src, pat16, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_cpyp16h32(dst, src, pat16, &mr); + } +#endif +} + +void vrammix_cpyex(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + if (!src->alpha) { + vramsub_cpyex16(dst, src, &mr); + } + else { + vramsub_cpyex16a(dst, src, &mr); + } + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + if (!src->alpha) { + vramsub_cpyex24(dst, src, &mr); + } + else { + vramsub_cpyex24a(dst, src, &mr); + } + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + if (!src->alpha) { + vramsub_cpyex32(dst, src, &mr); + } + else { + vramsub_cpyex32a(dst, src, &mr); + } + } +#endif +} + +void vrammix_cpyex2(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT alpha64) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (src->alpha == NULL) || (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_cpyex16a2(dst, src, alpha64, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_cpyex24a2(dst, src, alpha64, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_cpyex32a2(dst, src, alpha64, &mr); + } +#endif +} + +void vrammix_cpyexpat16w(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const UINT pat16) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (src->alpha == NULL) || (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_cpyexp16w16(dst, src, pat16, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_cpyexp16w24(dst, src, pat16, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_cpyexp16w32(dst, src, pat16, &mr); + } +#endif +} + +void vrammix_cpyexpat16h(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const UINT pat16) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (src->alpha == NULL) || (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_cpyexp16h16(dst, src, pat16, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_cpyexp16h24(dst, src, pat16, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_cpyexp16h32(dst, src, pat16, &mr); + } +#endif +} + +void vrammix_mix(VRAMHDL dst, const VRAMHDL org, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT alpha64) { + + MIXRECTEX mr; + + if (mixrectex(&mr, dst, org, rct, src, pt) != SUCCESS) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_mix16(dst, org, src, alpha64, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_mix24(dst, org, src, alpha64, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_mix32(dst, org, src, alpha64, &mr); + } +#endif +} + +void vrammix_mixcol(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT32 color, UINT alpha64) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_mixcol16(dst, src, color, alpha64, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_mixcol24(dst, src, color, alpha64, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_mixcol32(dst, src, color, alpha64, &mr); + } +#endif +} + +void vrammix_mixalpha(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT32 color) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || + (dst->bpp != src->bpp)) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_mixalpha16(dst, src, color, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_mixalpha24(dst, src, color, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_mixalpha32(dst, src, color, &mr); + } +#endif +} + +void vrammix_graybmp(VRAMHDL dst, const VRAMHDL org, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const VRAMHDL bmp, int delta) { + + MIXRECTEX mr; + + if (mixrectex(&mr, dst, org, rct, src, pt) != SUCCESS) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_gray16(dst, org, src, bmp, delta, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_gray24(dst, org, src, bmp, delta, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_gray32(dst, org, src, bmp, delta, &mr); + } +#endif +} + +void vrammix_colex(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT32 color) { + + MIX_RECT mr; + + if ((mixrect(&mr, dst, rct, src, pt) != SUCCESS) || (src->bpp != 8)) { + return; + } + +#ifdef SUPPORT_16BPP + if (dst->bpp == 16) { + vramsub_colex16(dst, src, color, &mr); + } +#endif +#ifdef SUPPORT_24BPP + if (dst->bpp == 24) { + vramsub_colex24(dst, src, color, &mr); + } +#endif +#ifdef SUPPORT_32BPP + if (dst->bpp == 32) { + vramsub_colex32(dst, src, color, &mr); + } +#endif +} + + +// ---- resize + +#ifdef SUPPORT_16BPP +static void vramsub_resize16(VRAMHDL dst, MIX_RECT *drct, + const VRAMHDL src, const MIX_RECT *srct) { + +const UINT8 *p; + UINT8 *q; +const UINT8 *r; +const UINT8 *s; + int dstep; + int xstep; + int ystep; + int xx; + int yy; + int x; + + p = src->ptr + (srct->srcpos * 2); + q = dst->ptr + (drct->dstpos * 2); + dstep = dst->yalign - (drct->width * 2); + + xstep = (srct->width << 10) / drct->width; + ystep = (srct->height << 10) / drct->height; + yy = 0; + do { + xx = 0; + r = p; + r += (yy >> 10) * src->yalign; + x = drct->width; + do { + s = r + ((xx >> 10) * 2); + *(UINT16 *)q = *(UINT16 *)s; + xx += xstep; + q += 2; + } while(--x); + yy += ystep; + q += dstep; + } while(--drct->height); +} +#endif + +#ifdef SUPPORT_24BPP +static void vramsub_resize24(VRAMHDL dst, MIX_RECT *drct, + const VRAMHDL src, const MIX_RECT *srct) { + +const UINT8 *p; + UINT8 *q; +const UINT8 *r; +const UINT8 *s; + int dstep; + int xstep; + int ystep; + int xx; + int yy; + int x; + + p = src->ptr + (srct->srcpos * 3); + q = dst->ptr + (drct->dstpos * 3); + dstep = dst->yalign - (drct->width * 3); + + xstep = (srct->width << 10) / drct->width; + ystep = (srct->height << 10) / drct->height; + yy = 0; + do { + xx = 0; + r = p; + r += (yy >> 10) * src->yalign; + x = drct->width; + do { + s = r + ((xx >> 10) * 3); + q[0] = s[0]; + q[1] = s[1]; + q[2] = s[2]; + xx += xstep; + q += 3; + } while(--x); + yy += ystep; + q += dstep; + } while(--drct->height); +} +#endif + +#ifdef SUPPORT_32BPP +static void vramsub_resize32(VRAMHDL dst, MIX_RECT *drct, + const VRAMHDL src, const MIX_RECT *srct) { + +const UINT8 *p; + UINT8 *q; +const UINT8 *r; +const UINT8 *s; + int dstep; + int xstep; + int ystep; + int xx; + int yy; + int x; + + p = src->ptr + (srct->srcpos * 4); + q = dst->ptr + (drct->dstpos * 4); + dstep = dst->yalign - (drct->width * 4); + + xstep = (srct->width << 10) / drct->width; + ystep = (srct->height << 10) / drct->height; + yy = 0; + do { + xx = 0; + r = p; + r += (yy >> 10) * src->yalign; + x = drct->width; + do { + s = r + ((xx >> 10) * 4); + q[0] = s[0]; + q[1] = s[1]; + q[2] = s[2]; + xx += xstep; + q += 4; + } while(--x); + yy += ystep; + q += dstep; + } while(--drct->height); +} +#endif + +static BRESULT cliprect(const VRAMHDL hdl, const RECT_T *rct, MIX_RECT *r) { + + RECT_T rect; + + if (vram_cliprect(&rect, hdl, rct) != SUCCESS) { + return(FAILURE); + } + r->srcpos = (rect.top * hdl->width) + rect.left; + r->dstpos = r->srcpos; + r->width = rect.right - rect.left; + r->height = rect.bottom - rect.top; + return(SUCCESS); +} + +void vrammix_resize(VRAMHDL dst, const RECT_T *drct, + const VRAMHDL src, const RECT_T *srct) { + + MIX_RECT drect; + MIX_RECT srect; + + if ((cliprect(src, srct, &srect) != SUCCESS) || + (cliprect(dst, drct, &drect) != SUCCESS)) { + return; + } + if (dst->bpp != src->bpp) { + return; + } +#ifdef SUPPORT_16BPP + if (src->bpp == 16) { + vramsub_resize16(dst, &drect, src, &srect); + } +#endif +#ifdef SUPPORT_24BPP + if (src->bpp == 24) { + vramsub_resize24(dst, &drect, src, &srect); + } +#endif +#ifdef SUPPORT_32BPP + if (src->bpp == 32) { + vramsub_resize32(dst, &drect, src, &srect); + } +#endif +} + + +// ---- font + +static BRESULT txtrect(VRAMHDL dst, const FNTDAT fnt, const POINT_T *pt, + const RECT_T *rct, MIX_RECT *r) { + + int pos; + + r->srcpos = 0; + r->dstpos = pt->y * dst->width; + r->dstpos += pt->x; + + pos = pt->y - rct->top; + if (pos < 0) { + r->srcpos -= pos * fnt->width; + r->height = MIN(fnt->height + pos, rct->bottom - rct->top); + } + else { + r->height = MIN(rct->bottom - rct->top - pos, fnt->height); + } + if (r->height <= 0) { + return(FAILURE); + } + + pos = pt->x - rct->left; + if (pos < 0) { + r->srcpos -= pos; + r->width = MIN(fnt->width + pos, rct->right - rct->left); + } + else { + r->width = MIN(rct->right - rct->left - pos, fnt->width); + } + if (r->width <= 0) { + return(FAILURE); + } + return(SUCCESS); +} + +static void vramsub_txt8p(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT alpha; + int cnt; + + p = (UINT8 *)(fnt + 1); + p += mr->srcpos; + q = dst->ptr + mr->dstpos; + do { + cnt = mr->width; + do { + alpha = *p++; + if (alpha) { + alpha = alpha * color / FDAT_DEPTH; + q[0] = (UINT8)alpha; + } + q += 1; + } while(--cnt); + p += fnt->width - mr->width; + q += dst->width - mr->width; + } while(--mr->height); +} + +#ifdef SUPPORT_16BPP +static void vramsub_txt16p(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT alpha; + int cnt; + UINT col16; + int c16[3]; + + col16 = MAKE16PAL(color); + c16[0] = col16 & B16MASK; + c16[1] = col16 & G16MASK; + c16[2] = col16 & R16MASK; + + p = (UINT8 *)(fnt + 1); + p += mr->srcpos; + q = dst->ptr + (mr->dstpos * 2); + do { + cnt = mr->width; + do { + alpha = *p++; + if (alpha) { + alpha = FDAT_DEPTH - alpha; + if (!alpha) { + *(UINT16 *)q = (UINT16)col16; + } + else { + UINT d, s; + s = *(UINT16 *)q; + d = MAKEALPHA16s(c16[0], s, B16MASK, + alpha, FDAT_DEPTHBIT); + d |= MAKEALPHA16s(c16[1], s, G16MASK, + alpha, FDAT_DEPTHBIT); + d |= MAKEALPHA16s(c16[2], s, R16MASK, + alpha, FDAT_DEPTHBIT); + *(UINT16 *)q = (UINT16)d; + } + } + q += 2; + } while(--cnt); + p += fnt->width - mr->width; + q += (dst->width - mr->width) * 2; + } while(--mr->height); +} + +static void vramsub_txt16a(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT8 *a; + UINT alpha; + int cnt; + UINT col16; + int c16[3]; + + col16 = MAKE16PAL(color); + c16[0] = col16 & B16MASK; + c16[1] = col16 & G16MASK; + c16[2] = col16 & R16MASK; + + p = (UINT8 *)(fnt + 1); + p += mr->srcpos; + q = dst->ptr + (mr->dstpos * 2); + a = dst->alpha + mr->dstpos; + do { + cnt = mr->width; + do { + alpha = *p++; + if (alpha) { + alpha = FDAT_DEPTH - alpha; + if (!alpha) { + *(UINT16 *)q = (UINT16)col16; + } + else { + UINT d, s; + s = *(UINT16 *)q; + d = MAKEALPHA16s(c16[0], s, B16MASK, + alpha, FDAT_DEPTHBIT); + d |= MAKEALPHA16s(c16[1], s, G16MASK, + alpha, FDAT_DEPTHBIT); + d |= MAKEALPHA16s(c16[2], s, R16MASK, + alpha, FDAT_DEPTHBIT); + *(UINT16 *)q = (UINT16)d; + } + a[0] = VRAMALPHA; + } + q += 2; + a += 1; + } while(--cnt); + p += fnt->width - mr->width; + q += (dst->width - mr->width) * 2; + a += dst->width - mr->width; + } while(--mr->height); +} + +static void vramsub_txt16e(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT8 *a; + UINT alpha; + int cnt; + UINT col16; + int c16[3]; + + col16 = MAKE16PAL(color); + c16[0] = col16 & B16MASK; + c16[1] = col16 & G16MASK; + c16[2] = col16 & R16MASK; + + p = (UINT8 *)(fnt + 1); + p += mr->srcpos; + q = dst->ptr + (mr->dstpos * 2); + + a = dst->alpha + mr->dstpos; + do { + cnt = mr->width; + do { + alpha = (*p++) * VRAMALPHA / FDAT_DEPTH; + if (alpha) { + *(UINT16 *)q = (UINT16)col16; + a[0] = (UINT8)alpha; + } + q += 2; + a += 1; + } while(--cnt); + p += fnt->width - mr->width; + q += (dst->width - mr->width) * 2; + a += dst->width - mr->width; + } while(--mr->height); +} +#endif + +#ifdef SUPPORT_24BPP +static void vramsub_txt24p(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT alpha; + int cnt; + int c24[3]; + + p = (UINT8 *)(fnt + 1); + p += mr->srcpos; + q = dst->ptr + (mr->dstpos * 3); + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + do { + cnt = mr->width; + do { + alpha = *p++; + if (alpha) { + if (alpha == FDAT_DEPTH) { + q[0] = (UINT8)c24[0]; + q[1] = (UINT8)c24[1]; + q[2] = (UINT8)c24[2]; + } + else { + alpha += FDATDEPTHBASE; + q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], + alpha, FDAT_DEPTHBIT); + q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], + alpha, FDAT_DEPTHBIT); + q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], + alpha, FDAT_DEPTHBIT); + } + } + q += 3; + } while(--cnt); + p += (fnt->width - mr->width); + q += (dst->width - mr->width) * 3; + } while(--mr->height); +} + +static void vramsub_txt24a(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT8 *a; + UINT alpha; + int cnt; + int c24[3]; + + p = (UINT8 *)(fnt + 1); + p += mr->srcpos; + q = dst->ptr + (mr->dstpos * 3); + a = dst->alpha + mr->dstpos; + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + do { + cnt = mr->width; + do { + alpha = *p++; + if (alpha) { + if (alpha == FDAT_DEPTH) { + q[0] = (UINT8)c24[0]; + q[1] = (UINT8)c24[1]; + q[2] = (UINT8)c24[2]; + } + else { + alpha += FDATDEPTHBASE; + q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], + alpha, FDAT_DEPTHBIT); + q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], + alpha, FDAT_DEPTHBIT); + q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], + alpha, FDAT_DEPTHBIT); + } + a[0] = VRAMALPHA; + } + q += 3; + a += 1; + } while(--cnt); + p += (fnt->width - mr->width); + q += (dst->width - mr->width) * 3; + a += dst->width - mr->width; + } while(--mr->height); +} + +static void vramsub_txt24e(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT8 *a; + UINT alpha; + int cnt; + int c24[3]; + + p = (UINT8 *)(fnt + 1); + p += mr->srcpos; + q = dst->ptr + (mr->dstpos * 3); + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + a = dst->alpha + mr->dstpos; + do { + cnt = mr->width; + do { + alpha = (*p++) * VRAMALPHA / FDAT_DEPTH; + if (alpha) { + q[0] = (UINT8)c24[0]; + q[1] = (UINT8)c24[1]; + q[2] = (UINT8)c24[2]; + a[0] = (UINT8)alpha; + } + q += 3; + a += 1; + } while(--cnt); + p += (fnt->width - mr->width); + q += (dst->width - mr->width) * 3; + a += dst->width - mr->width; + } while(--mr->height); +} +#endif + +#ifdef SUPPORT_32BPP +static void vramsub_txt32p(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT alpha; + int cnt; + int c24[3]; + + p = (UINT8 *)(fnt + 1); + p += mr->srcpos; + q = dst->ptr + (mr->dstpos * 4); + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + do { + cnt = mr->width; + do { + alpha = *p++; + if (alpha) { + if (alpha == FDAT_DEPTH) { + q[0] = (UINT8)c24[0]; + q[1] = (UINT8)c24[1]; + q[2] = (UINT8)c24[2]; + } + else { + alpha += FDATDEPTHBASE; + q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], + alpha, FDAT_DEPTHBIT); + q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], + alpha, FDAT_DEPTHBIT); + q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], + alpha, FDAT_DEPTHBIT); + } + } + q += 4; + } while(--cnt); + p += (fnt->width - mr->width); + q += (dst->width - mr->width) * 4; + } while(--mr->height); +} + +static void vramsub_txt32a(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT8 *a; + UINT alpha; + int cnt; + int c24[3]; + + p = (UINT8 *)(fnt + 1); + p += mr->srcpos; + q = dst->ptr + (mr->dstpos * 4); + a = dst->alpha + mr->dstpos; + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + do { + cnt = mr->width; + do { + alpha = *p++; + if (alpha) { + if (alpha == FDAT_DEPTH) { + q[0] = (UINT8)c24[0]; + q[1] = (UINT8)c24[1]; + q[2] = (UINT8)c24[2]; + } + else { + alpha += FDATDEPTHBASE; + q[0] = (UINT8)MAKEALPHA24(q[0], c24[0], + alpha, FDAT_DEPTHBIT); + q[1] = (UINT8)MAKEALPHA24(q[1], c24[1], + alpha, FDAT_DEPTHBIT); + q[2] = (UINT8)MAKEALPHA24(q[2], c24[2], + alpha, FDAT_DEPTHBIT); + } + a[0] = VRAMALPHA; + } + q += 4; + a += 1; + } while(--cnt); + p += (fnt->width - mr->width); + q += (dst->width - mr->width) * 4; + a += dst->width - mr->width; + } while(--mr->height); +} + +static void vramsub_txt32e(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr) { + +const UINT8 *p; + UINT8 *q; + UINT8 *a; + UINT alpha; + int cnt; + int c24[3]; + + p = (UINT8 *)(fnt + 1); + p += mr->srcpos; + q = dst->ptr + (mr->dstpos * 4); + c24[0] = color & 0xff; + c24[1] = (color >> 8) & 0xff; + c24[2] = (color >> 16) & 0xff; + a = dst->alpha + mr->dstpos; + do { + cnt = mr->width; + do { + alpha = (*p++) * VRAMALPHA / FDAT_DEPTH; + if (alpha) { + q[0] = (UINT8)c24[0]; + q[1] = (UINT8)c24[1]; + q[2] = (UINT8)c24[2]; + a[0] = (UINT8)alpha; + } + q += 4; + a += 1; + } while(--cnt); + p += (fnt->width - mr->width); + q += (dst->width - mr->width) * 4; + a += dst->width - mr->width; + } while(--mr->height); +} +#endif + +static void vramsub_text(VRAMHDL dst, void *fhdl, const OEMCHAR *str, + UINT32 color, POINT_T *pt, const RECT_T *rct, + void (*func)(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr)) { + + int leng; + OEMCHAR buf[4]; + RECT_T rect; + FNTDAT fnt; + MIX_RECT mr; + + if ((str == NULL) || (pt == NULL) || (func == NULL) || + (vram_cliprect(&rect, dst, rct) != SUCCESS)) { + goto vstxt_end; + } + + while(1) { + leng = milstr_charsize(str); + if (!leng) { + break; + } + CopyMemory(buf, str, leng * sizeof(OEMCHAR)); + buf[leng] = '\0'; + str += leng; + fnt = fontmng_get(fhdl, buf); + if (fnt) { + if (txtrect(dst, fnt, pt, &rect, &mr) == SUCCESS) { + func(dst, fnt, color, &mr); + } + pt->x += fnt->pitch; + } + } + +vstxt_end: + return; +} + +void vrammix_text(VRAMHDL dst, void *fhdl, const OEMCHAR *str, + UINT32 color, POINT_T *pt, const RECT_T *rct) { + + void (*func)(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr); + + if (dst == NULL) { + return; + } + func = NULL; + if (dst->bpp == 8) { + func = vramsub_txt8p; + } +#ifdef SUPPORT_16BPP + if (dst->bpp == 16) { + if (dst->alpha) { + func = vramsub_txt16a; + } + else { + func = vramsub_txt16p; + } + } +#endif +#ifdef SUPPORT_24BPP + if (dst->bpp == 24) { + if (dst->alpha) { + func = vramsub_txt24a; + } + else { + func = vramsub_txt24p; + } + } +#endif +#ifdef SUPPORT_32BPP + if (dst->bpp == 32) { + if (dst->alpha) { + func = vramsub_txt32a; + } + else { + func = vramsub_txt32p; + } + } +#endif + vramsub_text(dst, fhdl, str, color, pt, rct, func); +} + +void vrammix_textex(VRAMHDL dst, void *fhdl, const OEMCHAR *str, + UINT32 color, POINT_T *pt, const RECT_T *rct) { + + void (*func)(VRAMHDL dst, const FNTDAT fnt, + UINT32 color, MIX_RECT *mr); + + if (dst == NULL) { + return; + } + func = NULL; + if (dst->bpp == 8) { + func = vramsub_txt8p; + } +#ifdef SUPPORT_16BPP + if (dst->bpp == 16) { + if (dst->alpha) { + func = vramsub_txt16e; + } + else { + func = vramsub_txt16p; + } + } +#endif +#ifdef SUPPORT_24BPP + if (dst->bpp == 24) { + if (dst->alpha) { + func = vramsub_txt24e; + } + else { + func = vramsub_txt24p; + } + } +#endif +#ifdef SUPPORT_32BPP + if (dst->bpp == 32) { + if (dst->alpha) { + func = vramsub_txt32e; + } + else { + func = vramsub_txt32p; + } + } +#endif + vramsub_text(dst, fhdl, str, color, pt, rct, func); +} + diff --git a/embed/vrammix.h b/embed/vrammix.h old mode 100755 new mode 100644 index 383a1601..b2b38a7e --- a/embed/vrammix.h +++ b/embed/vrammix.h @@ -1,95 +1,95 @@ - -enum { - VRAMALPHA = 255, - VRAMALPHABIT = 8 -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -void vramcpy_cpy(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct); -void vramcpy_move(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct); -void vramcpy_cpyall(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct); -void vramcpy_cpypat(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - const UINT8 *pat8); -void vramcpy_cpyex(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct); -void vramcpy_cpyexa(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct); -void vramcpy_cpyalpha(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - UINT alpha256); -void vramcpy_mix(VRAMHDL dst, const VRAMHDL org, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - UINT alpha64); -void vramcpy_mixcol(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - UINT32 color, UINT alpha64); -void vramcpy_zoom(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - int dot); -void vramcpy_mosaic(VRAMHDL dst, const POINT_T *pt, - const VRAMHDL src, const RECT_T *rct, - int dot); - -void vrammix_cpy(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt); -void vrammix_cpyall(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt); -void vrammix_cpy2(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT alpha); -void vrammix_cpypat(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const UINT8 *pat8); -void vrammix_cpypat16w(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const UINT pat16); -void vrammix_cpypat16h(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const UINT pat16); -void vrammix_cpyex(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt); -void vrammix_cpyex2(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT alpha64); -void vrammix_cpyexpat16w(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const UINT pat16); -void vrammix_cpyexpat16h(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const UINT pat16); -void vrammix_mix(VRAMHDL dst, const VRAMHDL org, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT alpha64); -void vrammix_mixcol(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT32 color, UINT alpha64); -void vrammix_mixalpha(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT32 color); -void vrammix_graybmp(VRAMHDL dst, const VRAMHDL org, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - const VRAMHDL bmp, int delta); -void vrammix_colex(VRAMHDL dst, const RECT_T *rct, - const VRAMHDL src, const POINT_T *pt, - UINT32 color); - -void vrammix_resize(VRAMHDL dst, const RECT_T *drct, - const VRAMHDL src, const RECT_T *srct); - -void vrammix_text(VRAMHDL dst, void *fhdl, const OEMCHAR *str, - UINT32 color, POINT_T *pt, const RECT_T *rct); -void vrammix_textex(VRAMHDL dst, void *fhdl, const OEMCHAR *str, - UINT32 color, POINT_T *pt, const RECT_T *rct); - -#ifdef __cplusplus -} -#endif - + +enum { + VRAMALPHA = 255, + VRAMALPHABIT = 8 +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +void vramcpy_cpy(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct); +void vramcpy_move(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct); +void vramcpy_cpyall(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct); +void vramcpy_cpypat(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + const UINT8 *pat8); +void vramcpy_cpyex(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct); +void vramcpy_cpyexa(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct); +void vramcpy_cpyalpha(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + UINT alpha256); +void vramcpy_mix(VRAMHDL dst, const VRAMHDL org, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + UINT alpha64); +void vramcpy_mixcol(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + UINT32 color, UINT alpha64); +void vramcpy_zoom(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + int dot); +void vramcpy_mosaic(VRAMHDL dst, const POINT_T *pt, + const VRAMHDL src, const RECT_T *rct, + int dot); + +void vrammix_cpy(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt); +void vrammix_cpyall(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt); +void vrammix_cpy2(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT alpha); +void vrammix_cpypat(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const UINT8 *pat8); +void vrammix_cpypat16w(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const UINT pat16); +void vrammix_cpypat16h(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const UINT pat16); +void vrammix_cpyex(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt); +void vrammix_cpyex2(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT alpha64); +void vrammix_cpyexpat16w(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const UINT pat16); +void vrammix_cpyexpat16h(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const UINT pat16); +void vrammix_mix(VRAMHDL dst, const VRAMHDL org, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT alpha64); +void vrammix_mixcol(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT32 color, UINT alpha64); +void vrammix_mixalpha(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT32 color); +void vrammix_graybmp(VRAMHDL dst, const VRAMHDL org, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + const VRAMHDL bmp, int delta); +void vrammix_colex(VRAMHDL dst, const RECT_T *rct, + const VRAMHDL src, const POINT_T *pt, + UINT32 color); + +void vrammix_resize(VRAMHDL dst, const RECT_T *drct, + const VRAMHDL src, const RECT_T *srct); + +void vrammix_text(VRAMHDL dst, void *fhdl, const OEMCHAR *str, + UINT32 color, POINT_T *pt, const RECT_T *rct); +void vrammix_textex(VRAMHDL dst, void *fhdl, const OEMCHAR *str, + UINT32 color, POINT_T *pt, const RECT_T *rct); + +#ifdef __cplusplus +} +#endif + diff --git a/fdd/d88head.h b/fdd/d88head.h old mode 100755 new mode 100644 index ffaafad7..14637cf5 --- a/fdd/d88head.h +++ b/fdd/d88head.h @@ -1,63 +1,63 @@ - -enum { - D88_TRACKMAX = 164, - D88_HEADERSIZE = 0x20 + (D88_TRACKMAX * 4) -}; - - -#if defined(__GNUC__) -// D88ヘッダ (size: 2b0h bytes) -typedef struct { - UINT8 fd_name[17]; // Disk Name - UINT8 reserved1[9]; // Reserved - UINT8 protect; // Write Protect bit:4 - UINT8 fd_type; // Disk Format - UINT8 fd_size[4]; // Disk Size - UINT8 trackp[D88_TRACKMAX][4]; -} __attribute__ ((packed)) _D88HEAD, *D88HEAD; - -// D88セクタ (size: 16bytes) -typedef struct { - UINT8 c; - UINT8 h; - UINT8 r; - UINT8 n; - UINT8 sectors[2]; // Sector Count - UINT8 mfm_flg; // sides - UINT8 del_flg; // DELETED DATA - UINT8 stat; // STATUS (FDC ret) - UINT8 seektime; // Seek Time - UINT8 reserved[3]; // Reserved - UINT8 rpm_flg; // rpm 0:1.2 1:1.44 - UINT8 size[2]; // Sector Size -} __attribute__ ((packed)) _D88SEC, *D88SEC; -#else -#pragma pack(push, 1) -// D88ヘッダ (size: 2b0h bytes) -typedef struct { - UINT8 fd_name[17]; // Disk Name - UINT8 reserved1[9]; // Reserved - UINT8 protect; // Write Protect bit:4 - UINT8 fd_type; // Disk Format - UINT8 fd_size[4]; // Disk Size - UINT8 trackp[D88_TRACKMAX][4]; -} _D88HEAD, *D88HEAD; - -// D88セクタ (size: 16bytes) -typedef struct { - UINT8 c; - UINT8 h; - UINT8 r; - UINT8 n; - UINT8 sectors[2]; // Sector Count - UINT8 mfm_flg; // sides - UINT8 del_flg; // DELETED DATA - UINT8 stat; // STATUS (FDC ret) - UINT8 seektime; // Seek Time - UINT8 reserved[3]; // Reserved - UINT8 rpm_flg; // rpm 0:1.2 1:1.44 - UINT8 size[2]; // Sector Size -} _D88SEC, *D88SEC; -#pragma pack(pop) -#endif - + +enum { + D88_TRACKMAX = 164, + D88_HEADERSIZE = 0x20 + (D88_TRACKMAX * 4) +}; + + +#if defined(__GNUC__) +// D88ヘッダ (size: 2b0h bytes) +typedef struct { + UINT8 fd_name[17]; // Disk Name + UINT8 reserved1[9]; // Reserved + UINT8 protect; // Write Protect bit:4 + UINT8 fd_type; // Disk Format + UINT8 fd_size[4]; // Disk Size + UINT8 trackp[D88_TRACKMAX][4]; +} __attribute__ ((packed)) _D88HEAD, *D88HEAD; + +// D88セクタ (size: 16bytes) +typedef struct { + UINT8 c; + UINT8 h; + UINT8 r; + UINT8 n; + UINT8 sectors[2]; // Sector Count + UINT8 mfm_flg; // sides + UINT8 del_flg; // DELETED DATA + UINT8 stat; // STATUS (FDC ret) + UINT8 seektime; // Seek Time + UINT8 reserved[3]; // Reserved + UINT8 rpm_flg; // rpm 0:1.2 1:1.44 + UINT8 size[2]; // Sector Size +} __attribute__ ((packed)) _D88SEC, *D88SEC; +#else +#pragma pack(push, 1) +// D88ヘッダ (size: 2b0h bytes) +typedef struct { + UINT8 fd_name[17]; // Disk Name + UINT8 reserved1[9]; // Reserved + UINT8 protect; // Write Protect bit:4 + UINT8 fd_type; // Disk Format + UINT8 fd_size[4]; // Disk Size + UINT8 trackp[D88_TRACKMAX][4]; +} _D88HEAD, *D88HEAD; + +// D88セクタ (size: 16bytes) +typedef struct { + UINT8 c; + UINT8 h; + UINT8 r; + UINT8 n; + UINT8 sectors[2]; // Sector Count + UINT8 mfm_flg; // sides + UINT8 del_flg; // DELETED DATA + UINT8 stat; // STATUS (FDC ret) + UINT8 seektime; // Seek Time + UINT8 reserved[3]; // Reserved + UINT8 rpm_flg; // rpm 0:1.2 1:1.44 + UINT8 size[2]; // Sector Size +} _D88SEC, *D88SEC; +#pragma pack(pop) +#endif + diff --git a/fdd/diskdrv.c b/fdd/diskdrv.c old mode 100755 new mode 100644 index 5102b03f..368da834 --- a/fdd/diskdrv.c +++ b/fdd/diskdrv.c @@ -1,286 +1,286 @@ -/** - * @file diskdrv.c - * @brief Implementation of the disk-drive - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DISK_DELAY 20 /*!< Delay 0.4sec */ - -static int diskdrv_delay[4]; /*!< delay */ -static OEMCHAR diskdrv_fname[4][MAX_PATH]; /*!< path */ -static UINT diskdrv_ftype[4]; /*!< type */ -static int diskdrv_ro[4]; /*!< readonly */ - -/** - * Set SxSI image - * @param[in] drv The ID of the drive - * @param[in] fname The filename - */ -void diskdrv_setsxsi(REG8 drv, const OEMCHAR *fname) -{ - UINT num; - OEMCHAR *p; - int leng; - - num = drv & 0x0f; - p = NULL; - leng = 0; - if (!(drv & 0x20)) - { - /* SASI or IDE */ -#if defined(SUPPORT_IDEIO) - if (num < SASIHDD_MAX) - { - if(sxsi_getdevtype(num)!=SXSIDEV_CDROM){ - p = np2cfg.sasihdd[num]; - leng = NELEMENTS(np2cfg.sasihdd[0]); - } - } -#else - if (num < 2) - { - p = np2cfg.sasihdd[num]; - leng = NELEMENTS(np2cfg.sasihdd[0]); - } -#endif - } -#if defined(SUPPORT_SCSI) - else - { - /* SCSI */ - if (num < SCSIHDD_MAX) - { - p = np2cfg.scsihdd[num]; - leng = NELEMENTS(np2cfg.scsihdd[0]); - } - } -#endif - if (p) - { - if (fname) - { - file_cpyname(p, fname, leng); - } - else - { - p[0] = '\0'; - } - sysmng_update(SYS_UPDATEHDD | SYS_UPDATECFG); - } - else - { - sxsi_devopen(drv, fname); - } -} - -/** - * Get current SxSI files - * @param[in] drv The ID of the drive - * @return The filename - */ -const OEMCHAR *diskdrv_getsxsi(REG8 drv) -{ - UINT num; - - num = drv & 0x0f; - if (!(drv & 0x20)) - { - /* SASI or IDE */ -#if defined(SUPPORT_IDEIO) - if (num < SASIHDD_MAX) -#else - if (num < 2) -#endif - { - return np2cfg.sasihdd[num]; - } - } -#if defined(SUPPORT_SCSI) - else - { - /* SCSI */ - if (num < SCSIHDD_MAX) - { - return np2cfg.scsihdd[num]; - } - } -#endif - return sxsi_getfilename(drv); -} - -/** - * Bind all fixed drives - */ -void diskdrv_hddbind(void) -{ - REG8 drv; - -#if defined(SUPPORT_IDEIO) - for (drv = 0x00; drv < 0x00 + SASIHDD_MAX; drv++) - { - sxsi_devclose(drv); - } -#else - for (drv = 0x00; drv < 0x02; drv++) - { - sxsi_devclose(drv); - } -#endif -#if defined(SUPPORT_SCSI) - for (drv = 0x20; drv < 0x20 + SCSIHDD_MAX; drv++) - { - sxsi_devclose(drv); - } -#endif /* defined(SUPPORT_SCSI) */ - -#if defined(SUPPORT_IDEIO) - for (drv = 0x00; drv < 0x00 + SASIHDD_MAX; drv++) - { - sxsi_setdevtype(drv, np2cfg.idetype[drv]); - if(np2cfg.idetype[drv]==SXSIDEV_HDD) - { - if (sxsi_devopen(drv, np2cfg.sasihdd[drv & 0x0f]) != SUCCESS) - { - sxsi_setdevtype(drv, SXSIDEV_NC); - if(np2cfg.sasihdd[drv & 0x0f]!=NULL && np2cfg.sasihdd[drv & 0x0f][0]!='\0') - { - char strbuf[] = "IDE# file open error"; - strbuf[4] = '0'+drv; - msgbox("HD image file open error", strbuf); - } - } - } - else if(np2cfg.idetype[drv]==SXSIDEV_CDROM) - { - SXSIDEV sxsi = sxsi_getptr(drv); - if (sxsicd_open(sxsi, np2cfg.idecd[drv & 0x0f]) == SUCCESS) { - file_cpyname(sxsi->fname, np2cfg.idecd[drv & 0x0f], NELEMENTS(sxsi->fname)); - sxsi->flag = SXSIFLAG_READY | SXSIFLAG_FILEOPENED; - } - } - } -#else - for (drv = 0x00; drv < 0x02; drv++) - { - sxsi_setdevtype(drv, SXSIDEV_HDD); - if (sxsi_devopen(drv, np2cfg.sasihdd[drv & 0x0f]) != SUCCESS) - { - sxsi_setdevtype(drv, SXSIDEV_NC); - if(np2cfg.sasihdd[drv & 0x0f]!=NULL && np2cfg.sasihdd[drv & 0x0f][0]!='\0') - { - char strbuf[] = "SASI# file open error"; - strbuf[5] = '0'+drv; - msgbox("HD image file open error", strbuf); - } - } - } -#endif -#if defined(SUPPORT_SCSI) - for (drv = 0x20; drv < 0x20 + SCSIHDD_MAX; drv++) - { - sxsi_setdevtype(drv, SXSIDEV_HDD); - if (sxsi_devopen(drv, np2cfg.scsihdd[drv & 0x0f]) != SUCCESS) - { - sxsi_setdevtype(drv, SXSIDEV_NC); - } - } -#endif /* defined(SUPPORT_SCSI) */ -} - -/** - * Set FDD image (force) - * @param[in] drv The number of the drive - * @param[in] fname The filename of the disk - * @param[in] ftype the type of the disk - * @param[in] readonly The flags of file - */ -void diskdrv_readyfddex(REG8 drv, const OEMCHAR *fname, UINT ftype, int readonly) -{ - if ((drv < 4) && (fdc.equip & (1 << drv))) - { - if ((fname != NULL) && (fname[0] != '\0')) - { - short attr; - - attr = file_attr(fname); - if(attr & FILEATTR_READONLY) { - readonly = 1; - } - - fdd_set(drv, fname, ftype, readonly); - if ((!(fdc.chgreg & 4)) || (fdc.ctrlreg & 0x08)){ - fdc.stat[drv] = FDCRLT_AI | drv; - fdc.us = drv; - fdc_interrupt(); - } - sysmng_update(SYS_UPDATEFDD); - } - } -} - -/** - * Set FDD image - * @param[in] drv The number of the drive - * @param[in] fname The filename of the disk - * @param[in] ftype the type of the disk - * @param[in] readonly The flags of file - */ -void diskdrv_setfddex(REG8 drv, const OEMCHAR *fname, UINT ftype, int readonly) -{ - if ((drv < 4) && (fdc.equip & (1 << drv))) - { - fdd_eject(drv); - diskdrv_delay[drv] = 0; - diskdrv_fname[drv][0] = '\0'; - np2cfg.fddfile[drv][0] = '\0'; - fdc.stat[drv] = FDCRLT_AI | FDCRLT_NR | drv; - fdc.us = drv; - fdc_interrupt(); - - if (fname) - { - short attr; - - attr = file_attr(fname); - if(attr & FILEATTR_READONLY) { - readonly = 1; - } - - diskdrv_delay[drv] = DISK_DELAY; - diskdrv_ftype[drv] = ftype; - diskdrv_ro[drv] = readonly; - file_cpyname(diskdrv_fname[drv], fname, NELEMENTS(diskdrv_fname[drv])); - file_cpyname(np2cfg.fddfile[drv], fname, NELEMENTS(np2cfg.fddfile[drv])); - } - sysmng_update(SYS_UPDATEFDD); - } -} - -/** - * Callback - */ -void diskdrv_callback(void) -{ - REG8 drv; - - for (drv = 0; drv < 4; drv++) - { - if (diskdrv_delay[drv]) - { - diskdrv_delay[drv]--; - if (!diskdrv_delay[drv]) - { - diskdrv_readyfddex(drv, diskdrv_fname[drv], diskdrv_ftype[drv], diskdrv_ro[drv]); - diskdrv_fname[drv][0] = '\0'; - } - } - } -} +/** + * @file diskdrv.c + * @brief Implementation of the disk-drive + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DISK_DELAY 20 /*!< Delay 0.4sec */ + +static int diskdrv_delay[4]; /*!< delay */ +static OEMCHAR diskdrv_fname[4][MAX_PATH]; /*!< path */ +static UINT diskdrv_ftype[4]; /*!< type */ +static int diskdrv_ro[4]; /*!< readonly */ + +/** + * Set SxSI image + * @param[in] drv The ID of the drive + * @param[in] fname The filename + */ +void diskdrv_setsxsi(REG8 drv, const OEMCHAR *fname) +{ + UINT num; + OEMCHAR *p; + int leng; + + num = drv & 0x0f; + p = NULL; + leng = 0; + if (!(drv & 0x20)) + { + /* SASI or IDE */ +#if defined(SUPPORT_IDEIO) + if (num < SASIHDD_MAX) + { + if(sxsi_getdevtype(num)!=SXSIDEV_CDROM){ + p = np2cfg.sasihdd[num]; + leng = NELEMENTS(np2cfg.sasihdd[0]); + } + } +#else + if (num < 2) + { + p = np2cfg.sasihdd[num]; + leng = NELEMENTS(np2cfg.sasihdd[0]); + } +#endif + } +#if defined(SUPPORT_SCSI) + else + { + /* SCSI */ + if (num < SCSIHDD_MAX) + { + p = np2cfg.scsihdd[num]; + leng = NELEMENTS(np2cfg.scsihdd[0]); + } + } +#endif + if (p) + { + if (fname) + { + file_cpyname(p, fname, leng); + } + else + { + p[0] = '\0'; + } + sysmng_update(SYS_UPDATEHDD | SYS_UPDATECFG); + } + else + { + sxsi_devopen(drv, fname); + } +} + +/** + * Get current SxSI files + * @param[in] drv The ID of the drive + * @return The filename + */ +const OEMCHAR *diskdrv_getsxsi(REG8 drv) +{ + UINT num; + + num = drv & 0x0f; + if (!(drv & 0x20)) + { + /* SASI or IDE */ +#if defined(SUPPORT_IDEIO) + if (num < SASIHDD_MAX) +#else + if (num < 2) +#endif + { + return np2cfg.sasihdd[num]; + } + } +#if defined(SUPPORT_SCSI) + else + { + /* SCSI */ + if (num < SCSIHDD_MAX) + { + return np2cfg.scsihdd[num]; + } + } +#endif + return sxsi_getfilename(drv); +} + +/** + * Bind all fixed drives + */ +void diskdrv_hddbind(void) +{ + REG8 drv; + +#if defined(SUPPORT_IDEIO) + for (drv = 0x00; drv < 0x00 + SASIHDD_MAX; drv++) + { + sxsi_devclose(drv); + } +#else + for (drv = 0x00; drv < 0x02; drv++) + { + sxsi_devclose(drv); + } +#endif +#if defined(SUPPORT_SCSI) + for (drv = 0x20; drv < 0x20 + SCSIHDD_MAX; drv++) + { + sxsi_devclose(drv); + } +#endif /* defined(SUPPORT_SCSI) */ + +#if defined(SUPPORT_IDEIO) + for (drv = 0x00; drv < 0x00 + SASIHDD_MAX; drv++) + { + sxsi_setdevtype(drv, np2cfg.idetype[drv]); + if(np2cfg.idetype[drv]==SXSIDEV_HDD) + { + if (sxsi_devopen(drv, np2cfg.sasihdd[drv & 0x0f]) != SUCCESS) + { + sxsi_setdevtype(drv, SXSIDEV_NC); + if(np2cfg.sasihdd[drv & 0x0f]!=NULL && np2cfg.sasihdd[drv & 0x0f][0]!='\0') + { + char strbuf[] = "IDE# file open error"; + strbuf[4] = '0'+drv; + msgbox("HD image file open error", strbuf); + } + } + } + else if(np2cfg.idetype[drv]==SXSIDEV_CDROM) + { + SXSIDEV sxsi = sxsi_getptr(drv); + if (sxsicd_open(sxsi, np2cfg.idecd[drv & 0x0f]) == SUCCESS) { + file_cpyname(sxsi->fname, np2cfg.idecd[drv & 0x0f], NELEMENTS(sxsi->fname)); + sxsi->flag = SXSIFLAG_READY | SXSIFLAG_FILEOPENED; + } + } + } +#else + for (drv = 0x00; drv < 0x02; drv++) + { + sxsi_setdevtype(drv, SXSIDEV_HDD); + if (sxsi_devopen(drv, np2cfg.sasihdd[drv & 0x0f]) != SUCCESS) + { + sxsi_setdevtype(drv, SXSIDEV_NC); + if(np2cfg.sasihdd[drv & 0x0f]!=NULL && np2cfg.sasihdd[drv & 0x0f][0]!='\0') + { + char strbuf[] = "SASI# file open error"; + strbuf[5] = '0'+drv; + msgbox("HD image file open error", strbuf); + } + } + } +#endif +#if defined(SUPPORT_SCSI) + for (drv = 0x20; drv < 0x20 + SCSIHDD_MAX; drv++) + { + sxsi_setdevtype(drv, SXSIDEV_HDD); + if (sxsi_devopen(drv, np2cfg.scsihdd[drv & 0x0f]) != SUCCESS) + { + sxsi_setdevtype(drv, SXSIDEV_NC); + } + } +#endif /* defined(SUPPORT_SCSI) */ +} + +/** + * Set FDD image (force) + * @param[in] drv The number of the drive + * @param[in] fname The filename of the disk + * @param[in] ftype the type of the disk + * @param[in] readonly The flags of file + */ +void diskdrv_readyfddex(REG8 drv, const OEMCHAR *fname, UINT ftype, int readonly) +{ + if ((drv < 4) && (fdc.equip & (1 << drv))) + { + if ((fname != NULL) && (fname[0] != '\0')) + { + short attr; + + attr = file_attr(fname); + if(attr & FILEATTR_READONLY) { + readonly = 1; + } + + fdd_set(drv, fname, ftype, readonly); + if ((!(fdc.chgreg & 4)) || (fdc.ctrlreg & 0x08)){ + fdc.stat[drv] = FDCRLT_AI | drv; + fdc.us = drv; + fdc_interrupt(); + } + sysmng_update(SYS_UPDATEFDD); + } + } +} + +/** + * Set FDD image + * @param[in] drv The number of the drive + * @param[in] fname The filename of the disk + * @param[in] ftype the type of the disk + * @param[in] readonly The flags of file + */ +void diskdrv_setfddex(REG8 drv, const OEMCHAR *fname, UINT ftype, int readonly) +{ + if ((drv < 4) && (fdc.equip & (1 << drv))) + { + fdd_eject(drv); + diskdrv_delay[drv] = 0; + diskdrv_fname[drv][0] = '\0'; + np2cfg.fddfile[drv][0] = '\0'; + fdc.stat[drv] = FDCRLT_AI | FDCRLT_NR | drv; + fdc.us = drv; + fdc_interrupt(); + + if (fname) + { + short attr; + + attr = file_attr(fname); + if(attr & FILEATTR_READONLY) { + readonly = 1; + } + + diskdrv_delay[drv] = DISK_DELAY; + diskdrv_ftype[drv] = ftype; + diskdrv_ro[drv] = readonly; + file_cpyname(diskdrv_fname[drv], fname, NELEMENTS(diskdrv_fname[drv])); + file_cpyname(np2cfg.fddfile[drv], fname, NELEMENTS(np2cfg.fddfile[drv])); + } + sysmng_update(SYS_UPDATEFDD); + } +} + +/** + * Callback + */ +void diskdrv_callback(void) +{ + REG8 drv; + + for (drv = 0; drv < 4; drv++) + { + if (diskdrv_delay[drv]) + { + diskdrv_delay[drv]--; + if (!diskdrv_delay[drv]) + { + diskdrv_readyfddex(drv, diskdrv_fname[drv], diskdrv_ftype[drv], diskdrv_ro[drv]); + diskdrv_fname[drv][0] = '\0'; + } + } + } +} diff --git a/fdd/diskdrv.h b/fdd/diskdrv.h old mode 100755 new mode 100644 index 5c8b797f..7ac2fda5 --- a/fdd/diskdrv.h +++ b/fdd/diskdrv.h @@ -1,28 +1,28 @@ -/** - * @file diskdrv.h - * @brief Interface of the disk-drive - */ - -#pragma once - -#ifdef __cplusplus -extern "C" -{ -#endif - -void diskdrv_setsxsi(REG8 drv, const OEMCHAR *fname); -const OEMCHAR *diskdrv_getsxsi(REG8 drv); -void diskdrv_hddbind(void); - -void diskdrv_readyfddex(REG8 drv, const OEMCHAR *fname, UINT ftype, int readonly); -void diskdrv_setfddex(REG8 drv, const OEMCHAR *fname, UINT ftype, int readonly); -void diskdrv_callback(void); - -#ifdef __cplusplus -} -#endif - - -/* macro */ -#define diskdrv_readyfdd(d, f, r) diskdrv_readyfddex(d, f, FTYPE_NONE, r) /*!< set disk (force) */ -#define diskdrv_setfdd(d, f, r) diskdrv_setfddex(d, f, FTYPE_NONE, r) /*!< set disk */ +/** + * @file diskdrv.h + * @brief Interface of the disk-drive + */ + +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +void diskdrv_setsxsi(REG8 drv, const OEMCHAR *fname); +const OEMCHAR *diskdrv_getsxsi(REG8 drv); +void diskdrv_hddbind(void); + +void diskdrv_readyfddex(REG8 drv, const OEMCHAR *fname, UINT ftype, int readonly); +void diskdrv_setfddex(REG8 drv, const OEMCHAR *fname, UINT ftype, int readonly); +void diskdrv_callback(void); + +#ifdef __cplusplus +} +#endif + + +/* macro */ +#define diskdrv_readyfdd(d, f, r) diskdrv_readyfddex(d, f, FTYPE_NONE, r) /*!< set disk (force) */ +#define diskdrv_setfdd(d, f, r) diskdrv_setfddex(d, f, FTYPE_NONE, r) /*!< set disk */ diff --git a/fdd/fdd_mtr.h b/fdd/fdd_mtr.h old mode 100755 new mode 100644 index 2c1a42ef..cc628bed --- a/fdd/fdd_mtr.h +++ b/fdd/fdd_mtr.h @@ -1,37 +1,37 @@ - -typedef struct { - int busy; - UINT8 head[4]; - UINT nextevent; - UINT8 curevent; -} _FDDMTR, *FDDMTR; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern _FDDMTR fddmtr; - -void fdbiosout(NEVENTITEM item); - -void fddmtr_initialize(void); -void fddmtr_callback(UINT time); -void fddmtr_seek(REG8 drv, REG8 c, UINT size); -void fddmtr_reset(void); - - -#if defined(SUPPORT_SWSEEKSND) -void fddmtrsnd_initialize(UINT rate); -void fddmtrsnd_bind(void); -void fddmtrsnd_deinitialize(void); -#else -#define fddmtrsnd_initialize(r) -#define fddmtrsnd_bind() -#define fddmtrsnd_deinitialize() -#endif - -#ifdef __cplusplus -} -#endif - + +typedef struct { + int busy; + UINT8 head[4]; + UINT nextevent; + UINT8 curevent; +} _FDDMTR, *FDDMTR; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _FDDMTR fddmtr; + +void fdbiosout(NEVENTITEM item); + +void fddmtr_initialize(void); +void fddmtr_callback(UINT time); +void fddmtr_seek(REG8 drv, REG8 c, UINT size); +void fddmtr_reset(void); + + +#if defined(SUPPORT_SWSEEKSND) +void fddmtrsnd_initialize(UINT rate); +void fddmtrsnd_bind(void); +void fddmtrsnd_deinitialize(void); +#else +#define fddmtrsnd_initialize(r) +#define fddmtrsnd_bind() +#define fddmtrsnd_deinitialize() +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/fdd/hdd_vhd.h b/fdd/hdd_vhd.h old mode 100755 new mode 100644 index f7179d2a..92ec80b2 --- a/fdd/hdd_vhd.h +++ b/fdd/hdd_vhd.h @@ -1,181 +1,181 @@ -/* - a minimal support for VirtualPC VHD images - (fixed disk image only, for now...) - - author: lpproj - license: same as xnp2 (under the 2-clause BSD) -*/ -#ifndef HDD_VPCVHD_H -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include "hdd_vpc.h" -#endif - -#define LOADBEWORD LOADMOTOROLAWORD -#define LOADBEDWORD LOADMOTOROLADWORD -#define LOADBEQWORD LOADMOTOROLAQWORD -#define STOREBEWORD STOREMOTOROLAWORD -#define STOREBEDWORD STOREMOTOROLADWORD -#define STOREBEQWORD STOREMOTOROLAQWORD - -static const UINT8 CookieVPCVHDFooter[8] = { 'c','o','n','e','c','t','i','x' }; -static const UINT8 CookieVPCVHDDDH[8] = { 'c','x','s','p','a','r','s','e' }; -static const UINT8 CookieVPCQEMUCreator[4] = { 'q','e','m','u' }; - -/* load/store with "network order" (big endian) */ - -#if 0 -static UINT16 LOADBEWORD(const void *p) -{ - const UINT8 *b = (UINT8 *)p; - return( ((UINT16)(b[0])<<8) | b[1] ); -} -static UINT32 LOADBEDWORD(const void *p) -{ - const UINT8 *b = (UINT8 *)p; - return( ((UINT32)(b[0])<<24) | ((UINT32)(b[1])<<16) | ((UINT32)(b[2])<<8) | b[3] ); -} -static UINT64 LOADBEQWORD(const void *p) -{ - const UINT8 *b = (UINT8 *)p; - return( ((UINT64)(b[0])<<56) | ((UINT64)(b[1])<<48) | ((UINT64)(b[2])<<40) | ((UINT64)(b[3])<<32) | ((UINT32)(b[4])<<24) | ((UINT32)(b[5])<<16) | ((UINT32)(b[6])<<8) | b[7] ); -} - -static UINT16 STOREBEWORD(void *p, UINT16 v) -{ - UINT8 *b = (UINT8 *)p; - b[0] = (UINT8)(v>>8); - b[1] = (UINT8)v; - return(v); -} -static UINT32 STOREBEDWORD(void *p, UINT32 v) -{ - UINT8 *b = (UINT8 *)p; - b[0] = (UINT8)(v>>24); - b[1] = (UINT8)(v>>16); - b[2] = (UINT8)(v>>8); - b[3] = (UINT8)v; - return(v); -} -static UINT64 STOREBEQWORD(void *p, UINT64 v) -{ - UINT8 *b = (UINT8 *)p; - b[0] = (UINT8)(v>>56); - b[1] = (UINT8)(v>>48); - b[2] = (UINT8)(v>>40); - b[3] = (UINT8)(v>>32); - b[4] = (UINT8)(v>>24); - b[5] = (UINT8)(v>>16); - b[6] = (UINT8)(v>>8); - b[7] = (UINT8)v; - return(v); -} -#endif - -/* checksum adapted from http://superuser.com/a/434816 */ -UINT32 vpc_calc_checksum(UINT8* buf, size_t size) -{ - UINT32 res = 0; - size_t i; - - for (i = 0; i < size; i++) - res += buf[i]; - - return ~res; -} - -BRESULT sxsihdd_vpcvhd_mount(SXSIDEV sxsi, FILEH fh) -{ - VPCVHDFOOTER footer; - VPCVHD_FPOS vhdlen, readlen; - size_t footerlen; - - UINT32 disktype, formatversion, checksum, mychecksum; - UINT32 surfaces, cylinders, sectors; - UINT64 totals; - - footerlen = sizeof(footer); /* 512 */ - ZeroMemory(&footer, footerlen); - vhdlen = file_seek(fh, 0, FSEEK_END); - if (vhdlen == (VPCVHD_FPOS)-1 || (vhdlen >= 0 && vhdlen < (VPCVHD_FPOS)footerlen)) - return(FAILURE); - file_seek(fh, (FILEPOS)(vhdlen - footerlen), FSEEK_SET); - readlen = file_read(fh, &footer, sizeof(footer.Cookie)); - if (memcmp(footer.Cookie, CookieVPCVHDFooter, sizeof(footer.Cookie)) != 0) { - CopyMemory(&(footer.Cookie[0]), &(footer.Cookie[1]), sizeof(footer.Cookie)-1); - file_read(fh, &(footer.Cookie[sizeof(footer.Cookie)-1]), 1); - --footerlen; - } - if (memcmp(footer.Cookie, CookieVPCVHDFooter, sizeof(footer.Cookie)) != 0) - return(FAILURE); - readlen = file_read(fh, (UINT8 *)(&footer) + sizeof(footer.Cookie), (UINT)(footerlen - sizeof(footer.Cookie))); - if (readlen < (VPCVHD_FPOS)(footerlen - sizeof(footer.Cookie))) - return(FAILURE); - - // validate footer's checksum - checksum = LOADBEDWORD(footer.CheckSum); - STOREBEDWORD(footer.CheckSum, 0); - mychecksum = vpc_calc_checksum((UINT8*)&footer,footerlen); - if (mychecksum != checksum) { - TRACEOUT(("vpc_vhd: bad checksum (file=%x, calc=%x)",checksum,mychecksum)); - return(FAILURE); - } - - formatversion = LOADBEDWORD(footer.FileFormatVersion); - disktype = LOADBEDWORD(footer.DiskType); - sectors = footer.SectorsPerCylinder; - surfaces = footer.Heads; - cylinders = LOADBEWORD(footer.Cylinder); - if (formatversion != 0x00010000 || disktype != VPCVHD_DISK_FIXED) { - /* todo: support dynamic disk */ - TRACEOUT(("vpc_vhd: unsupported vhd image")); - return(FAILURE); - } - totals = (UINT64)sectors * surfaces * cylinders; - if (totals == 0) - return(FAILURE); - - /* QEMU hack */ - if (!memcmp(footer.CreatorApplication, CookieVPCQEMUCreator, sizeof(footer.CreatorApplication)) && (totals * 512U + footerlen > (UINT64)vhdlen)) { - --cylinders; - totals = (UINT64)sectors * surfaces * cylinders; - } - - if (disktype == VPCVHD_DISK_FIXED) { - if (totals * 512U + footerlen > (UINT64)vhdlen) - return(FALSE); -#if defined(SUPPORT_LARGE_HDD) - sxsi->totals = totals; -#else - sxsi->totals = (long)totals; - if ((UINT64)(sxsi->totals) != totals) { /* overflow? */ - sxsi->totals = 0; - return(FALSE); - } -#endif - /* the simplest way: reuse built-in methods for fixed image */ - sxsi->reopen = hdd_reopen; - sxsi->read = hdd_read; - sxsi->write = hdd_write; - sxsi->format = hdd_format; - sxsi->close = hdd_close; - - sxsi->hdl = (INTPTR)fh; - sxsi->cylinders = (UINT16)cylinders; - sxsi->size = 512; /* 512 only */ - sxsi->sectors = (UINT8)sectors; - sxsi->surfaces = (UINT8)surfaces; - sxsi->headersize = 0; /* footer only in the fixed image */ - sxsi->mediatype = gethddtype(sxsi); - file_seek(fh, 0, FSEEK_SET); /* rewind the pointer, for a proof */ - TRACEOUT(("vpc_vhd: vhd fixed image mounted (c=%u h=%u s=%u %luMbytes)", (unsigned)cylinders, (unsigned)surfaces, (unsigned)sectors, (unsigned long)(totals /2U / 1024U))); - return(SUCCESS); - } - return(FAILURE); -} - +/* + a minimal support for VirtualPC VHD images + (fixed disk image only, for now...) + + author: lpproj + license: same as xnp2 (under the 2-clause BSD) +*/ +#ifndef HDD_VPCVHD_H +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include "hdd_vpc.h" +#endif + +#define LOADBEWORD LOADMOTOROLAWORD +#define LOADBEDWORD LOADMOTOROLADWORD +#define LOADBEQWORD LOADMOTOROLAQWORD +#define STOREBEWORD STOREMOTOROLAWORD +#define STOREBEDWORD STOREMOTOROLADWORD +#define STOREBEQWORD STOREMOTOROLAQWORD + +static const UINT8 CookieVPCVHDFooter[8] = { 'c','o','n','e','c','t','i','x' }; +static const UINT8 CookieVPCVHDDDH[8] = { 'c','x','s','p','a','r','s','e' }; +static const UINT8 CookieVPCQEMUCreator[4] = { 'q','e','m','u' }; + +/* load/store with "network order" (big endian) */ + +#if 0 +static UINT16 LOADBEWORD(const void *p) +{ + const UINT8 *b = (UINT8 *)p; + return( ((UINT16)(b[0])<<8) | b[1] ); +} +static UINT32 LOADBEDWORD(const void *p) +{ + const UINT8 *b = (UINT8 *)p; + return( ((UINT32)(b[0])<<24) | ((UINT32)(b[1])<<16) | ((UINT32)(b[2])<<8) | b[3] ); +} +static UINT64 LOADBEQWORD(const void *p) +{ + const UINT8 *b = (UINT8 *)p; + return( ((UINT64)(b[0])<<56) | ((UINT64)(b[1])<<48) | ((UINT64)(b[2])<<40) | ((UINT64)(b[3])<<32) | ((UINT32)(b[4])<<24) | ((UINT32)(b[5])<<16) | ((UINT32)(b[6])<<8) | b[7] ); +} + +static UINT16 STOREBEWORD(void *p, UINT16 v) +{ + UINT8 *b = (UINT8 *)p; + b[0] = (UINT8)(v>>8); + b[1] = (UINT8)v; + return(v); +} +static UINT32 STOREBEDWORD(void *p, UINT32 v) +{ + UINT8 *b = (UINT8 *)p; + b[0] = (UINT8)(v>>24); + b[1] = (UINT8)(v>>16); + b[2] = (UINT8)(v>>8); + b[3] = (UINT8)v; + return(v); +} +static UINT64 STOREBEQWORD(void *p, UINT64 v) +{ + UINT8 *b = (UINT8 *)p; + b[0] = (UINT8)(v>>56); + b[1] = (UINT8)(v>>48); + b[2] = (UINT8)(v>>40); + b[3] = (UINT8)(v>>32); + b[4] = (UINT8)(v>>24); + b[5] = (UINT8)(v>>16); + b[6] = (UINT8)(v>>8); + b[7] = (UINT8)v; + return(v); +} +#endif + +/* checksum adapted from http://superuser.com/a/434816 */ +UINT32 vpc_calc_checksum(UINT8* buf, size_t size) +{ + UINT32 res = 0; + size_t i; + + for (i = 0; i < size; i++) + res += buf[i]; + + return ~res; +} + +BRESULT sxsihdd_vpcvhd_mount(SXSIDEV sxsi, FILEH fh) +{ + VPCVHDFOOTER footer; + VPCVHD_FPOS vhdlen, readlen; + size_t footerlen; + + UINT32 disktype, formatversion, checksum, mychecksum; + UINT32 surfaces, cylinders, sectors; + UINT64 totals; + + footerlen = sizeof(footer); /* 512 */ + ZeroMemory(&footer, footerlen); + vhdlen = file_seek(fh, 0, FSEEK_END); + if (vhdlen == (VPCVHD_FPOS)-1 || (vhdlen >= 0 && vhdlen < (VPCVHD_FPOS)footerlen)) + return(FAILURE); + file_seek(fh, (FILEPOS)(vhdlen - footerlen), FSEEK_SET); + readlen = file_read(fh, &footer, sizeof(footer.Cookie)); + if (memcmp(footer.Cookie, CookieVPCVHDFooter, sizeof(footer.Cookie)) != 0) { + CopyMemory(&(footer.Cookie[0]), &(footer.Cookie[1]), sizeof(footer.Cookie)-1); + file_read(fh, &(footer.Cookie[sizeof(footer.Cookie)-1]), 1); + --footerlen; + } + if (memcmp(footer.Cookie, CookieVPCVHDFooter, sizeof(footer.Cookie)) != 0) + return(FAILURE); + readlen = file_read(fh, (UINT8 *)(&footer) + sizeof(footer.Cookie), (UINT)(footerlen - sizeof(footer.Cookie))); + if (readlen < (VPCVHD_FPOS)(footerlen - sizeof(footer.Cookie))) + return(FAILURE); + + // validate footer's checksum + checksum = LOADBEDWORD(footer.CheckSum); + STOREBEDWORD(footer.CheckSum, 0); + mychecksum = vpc_calc_checksum((UINT8*)&footer,footerlen); + if (mychecksum != checksum) { + TRACEOUT(("vpc_vhd: bad checksum (file=%x, calc=%x)",checksum,mychecksum)); + return(FAILURE); + } + + formatversion = LOADBEDWORD(footer.FileFormatVersion); + disktype = LOADBEDWORD(footer.DiskType); + sectors = footer.SectorsPerCylinder; + surfaces = footer.Heads; + cylinders = LOADBEWORD(footer.Cylinder); + if (formatversion != 0x00010000 || disktype != VPCVHD_DISK_FIXED) { + /* todo: support dynamic disk */ + TRACEOUT(("vpc_vhd: unsupported vhd image")); + return(FAILURE); + } + totals = (UINT64)sectors * surfaces * cylinders; + if (totals == 0) + return(FAILURE); + + /* QEMU hack */ + if (!memcmp(footer.CreatorApplication, CookieVPCQEMUCreator, sizeof(footer.CreatorApplication)) && (totals * 512U + footerlen > (UINT64)vhdlen)) { + --cylinders; + totals = (UINT64)sectors * surfaces * cylinders; + } + + if (disktype == VPCVHD_DISK_FIXED) { + if (totals * 512U + footerlen > (UINT64)vhdlen) + return(FALSE); +#if defined(SUPPORT_LARGE_HDD) + sxsi->totals = totals; +#else + sxsi->totals = (long)totals; + if ((UINT64)(sxsi->totals) != totals) { /* overflow? */ + sxsi->totals = 0; + return(FALSE); + } +#endif + /* the simplest way: reuse built-in methods for fixed image */ + sxsi->reopen = hdd_reopen; + sxsi->read = hdd_read; + sxsi->write = hdd_write; + sxsi->format = hdd_format; + sxsi->close = hdd_close; + + sxsi->hdl = (INTPTR)fh; + sxsi->cylinders = (UINT16)cylinders; + sxsi->size = 512; /* 512 only */ + sxsi->sectors = (UINT8)sectors; + sxsi->surfaces = (UINT8)surfaces; + sxsi->headersize = 0; /* footer only in the fixed image */ + sxsi->mediatype = gethddtype(sxsi); + file_seek(fh, 0, FSEEK_SET); /* rewind the pointer, for a proof */ + TRACEOUT(("vpc_vhd: vhd fixed image mounted (c=%u h=%u s=%u %luMbytes)", (unsigned)cylinders, (unsigned)surfaces, (unsigned)sectors, (unsigned long)(totals /2U / 1024U))); + return(SUCCESS); + } + return(FAILURE); +} + diff --git a/fdd/hdd_vpc.h b/fdd/hdd_vpc.h old mode 100755 new mode 100644 index 5b1dafb2..ae2cbf98 --- a/fdd/hdd_vpc.h +++ b/fdd/hdd_vpc.h @@ -1,68 +1,68 @@ -#ifndef HDD_VPCVHD_H -#define HDD_VPCVHD_H - -#if defined(SUPPORT_LARGE_HDD) -typedef FILEPOS VPCVHD_FPOS; // prepare for 64bits length -#else -typedef long VPCVHD_FPOS; -#endif - -enum { - VPCVHD_DISK_NONE = 0, - VPCVHD_DISK_FIXED = 2, - VPCVHD_DISK_DYNAMIC = 3, - VPCVHD_DISK_DIFFERENCING = 4 -}; - -typedef struct VPCVHDFOOTER { - UINT8 Cookie[8]; // 'conectix' - UINT8 Features[4]; - UINT8 FileFormatVersion[4]; - UINT8 DataOffset[8]; - UINT8 TimeStamp[4]; - UINT8 CreatorApplication[4]; - UINT8 CreatorVersion[4]; - UINT8 CreatorHostOS[4]; - UINT8 OriginalSize[8]; - UINT8 CurrentSize[8]; - UINT8 Cylinder[2]; - UINT8 Heads; - UINT8 SectorsPerCylinder; - UINT8 DiskType[4]; - UINT8 CheckSum[4]; - UINT8 UniqueID[16]; - UINT8 SavedState[1]; - UINT8 ReservedUpto512[427]; // note: up to 511bytes on some images -} VPCVHDFOOTER; - -typedef struct VPCVHDDDH { - UINT8 Cookie[8]; // 'cxsparse' - UINT8 DataOffset[8]; - UINT8 TableOffset[8]; - UINT8 HeaderVersion[4]; - UINT8 MaxTableEntries[4]; - UINT8 BlockSize[4]; - UINT8 CheckSum[4]; - UINT8 ParentUniqueID[16]; - UINT8 ParentTimeStamp[4]; - UINT8 Reserved0[4]; - UINT8 ParentUnicodeName[512]; // UTF16BE - UINT8 ParentLocatorEntries[24 * 8]; - UINT8 ReservedUpto1024[256]; -} VPCVHDDDH; - - -#ifdef __cplusplus -extern "C" { -#endif - -UINT32 vpc_calc_checksum(UINT8* buf, size_t size); -BRESULT sxsihdd_vpcvhd_mount(SXSIDEV sxsi, FILEH fh); - - -#ifdef __cplusplus -} -#endif - - +#ifndef HDD_VPCVHD_H +#define HDD_VPCVHD_H + +#if defined(SUPPORT_LARGE_HDD) +typedef FILEPOS VPCVHD_FPOS; // prepare for 64bits length +#else +typedef long VPCVHD_FPOS; +#endif + +enum { + VPCVHD_DISK_NONE = 0, + VPCVHD_DISK_FIXED = 2, + VPCVHD_DISK_DYNAMIC = 3, + VPCVHD_DISK_DIFFERENCING = 4 +}; + +typedef struct VPCVHDFOOTER { + UINT8 Cookie[8]; // 'conectix' + UINT8 Features[4]; + UINT8 FileFormatVersion[4]; + UINT8 DataOffset[8]; + UINT8 TimeStamp[4]; + UINT8 CreatorApplication[4]; + UINT8 CreatorVersion[4]; + UINT8 CreatorHostOS[4]; + UINT8 OriginalSize[8]; + UINT8 CurrentSize[8]; + UINT8 Cylinder[2]; + UINT8 Heads; + UINT8 SectorsPerCylinder; + UINT8 DiskType[4]; + UINT8 CheckSum[4]; + UINT8 UniqueID[16]; + UINT8 SavedState[1]; + UINT8 ReservedUpto512[427]; // note: up to 511bytes on some images +} VPCVHDFOOTER; + +typedef struct VPCVHDDDH { + UINT8 Cookie[8]; // 'cxsparse' + UINT8 DataOffset[8]; + UINT8 TableOffset[8]; + UINT8 HeaderVersion[4]; + UINT8 MaxTableEntries[4]; + UINT8 BlockSize[4]; + UINT8 CheckSum[4]; + UINT8 ParentUniqueID[16]; + UINT8 ParentTimeStamp[4]; + UINT8 Reserved0[4]; + UINT8 ParentUnicodeName[512]; // UTF16BE + UINT8 ParentLocatorEntries[24 * 8]; + UINT8 ReservedUpto1024[256]; +} VPCVHDDDH; + + +#ifdef __cplusplus +extern "C" { +#endif + +UINT32 vpc_calc_checksum(UINT8* buf, size_t size); +BRESULT sxsihdd_vpcvhd_mount(SXSIDEV sxsi, FILEH fh); + + +#ifdef __cplusplus +} +#endif + + #endif \ No newline at end of file diff --git a/fdd/newdisk.c b/fdd/newdisk.c old mode 100755 new mode 100644 index 14291611..6e483065 --- a/fdd/newdisk.c +++ b/fdd/newdisk.c @@ -1,546 +1,546 @@ -#include -#if defined(OSLANG_UTF8) || defined(OSLANG_UCS2) -#include "oemtext.h" -#endif -#include -#include "newdisk.h" -#include -#include -#include "hddboot.res" - -#ifdef SUPPORT_VPCVHD -#include "hdd_vpc.h" -#endif - - -// ---- fdd - -void newdisk_fdd(const OEMCHAR *fname, REG8 type, const OEMCHAR *label) { - - _D88HEAD d88head; - FILEH fh; - - ZeroMemory(&d88head, sizeof(d88head)); - STOREINTELDWORD(d88head.fd_size, sizeof(d88head)); -#if defined(OSLANG_UTF8) || defined(OSLANG_UCS2) - oemtext_oemtosjis((char *)d88head.fd_name, sizeof(d88head.fd_name), - label, (UINT)-1); -#else - milstr_ncpy((char *)d88head.fd_name, label, sizeof(d88head.fd_name)); -#endif - d88head.fd_type = type; - fh = file_create(fname); - if (fh != FILEH_INVALID) { - file_write(fh, &d88head, sizeof(d88head)); - file_close(fh); - } -} - -void newdisk_123mb_fdd(const OEMCHAR *fname) { - - FILEH fh; - char databuf[8192] = {0}; - int fdsize = 1261568; - - fh = file_create(fname); - if (fh != FILEH_INVALID) { - while(fdsize){ - if(fdsize < sizeof(databuf)){ - file_write(fh, &databuf, fdsize); - break; - }else{ - file_write(fh, &databuf, sizeof(databuf)); - fdsize -= sizeof(databuf); - } - } - file_close(fh); - } -} - -void newdisk_144mb_fdd(const OEMCHAR *fname) { - - FILEH fh; - char databuf[8192] = {0}; - int fdsize = 1474560; - - fh = file_create(fname); - if (fh != FILEH_INVALID) { - while(fdsize){ - if(fdsize < sizeof(databuf)){ - file_write(fh, &databuf, fdsize); - break; - }else{ - file_write(fh, &databuf, sizeof(databuf)); - fdsize -= sizeof(databuf); - } - } - file_close(fh); - } -} - - - -// ---- hdd - -static BRESULT writezero(FILEH fh, FILELEN size) { - - UINT8 work[256]; - FILELEN wsize; - - ZeroMemory(work, sizeof(work)); - while(size) { - wsize = MIN(size, sizeof(work)); - if (file_write(fh, work, (UINT)wsize) != wsize) { - return(FAILURE); - } - size -= wsize; - } - return(SUCCESS); -} - -static BRESULT writehddiplex2(FILEH fh, UINT ssize, FILELEN tsize, int blank, int *progress, int *cancel) { - - UINT8 *work; - FILELEN size; - FILELEN progtotal; - int worksize = 65536; - - if(tsize < worksize) worksize = (int)tsize; - if(tsize > 1024*1024) worksize = 1024*1024; - if(tsize > 8*1024*1024) worksize = 8*1024*1024; - if(worksize < sizeof(hdddiskboot)) worksize = sizeof(hdddiskboot); - work = (UINT8*)malloc(worksize); - if (!work) { - return(FAILURE); - } - - progtotal = tsize; - *progress = 0; - ZeroMemory(work, worksize); - if(!blank){ - CopyMemory(work, hdddiskboot, sizeof(hdddiskboot)); - if (ssize < 1024) { - work[ssize - 2] = 0x55; - work[ssize - 1] = 0xaa; - } - } - if (file_write(fh, work, worksize) != worksize) { - free(work); - return(FAILURE); - } - if (tsize > worksize) { - tsize -= worksize; - ZeroMemory(work, worksize); - while(tsize) { - size = MIN(tsize, worksize); - tsize -= size; - if (file_write(fh, work, (UINT)size) != size) { - free(work); - return(FAILURE); - } - *progress = (UINT32)((progtotal - tsize) * 100 / progtotal); - if(*cancel){ - free(work); - return(FAILURE); - } - } - } - free(work); - return(SUCCESS); -} -static BRESULT writehddiplex(FILEH fh, UINT ssize, FILELEN tsize, int *progress, int *cancel) { - - return writehddiplex2(fh, ssize, tsize, 0, progress, cancel); -} -static BRESULT writehddipl(FILEH fh, UINT ssize, FILELEN tsize) { - - int progress; - int cancel = 0; - return writehddiplex(fh, ssize, tsize, &progress, &cancel); -} - -static void hddsize2CHS(UINT hddsizeMB, UINT32 *C, UINT16 *H, UINT16 *S, UINT16 *SS) { - - FILELEN size; -#ifdef SUPPORT_LARGE_HDD - if(hddsizeMB <= 4351){ - size = (FILELEN)hddsizeMB * 15; - *C = (UINT32)size; - *H = 8; - *S = 17; - *SS = 512; - }else if(hddsizeMB <= 32255){ - size = (FILELEN)hddsizeMB * 15 * 17 / 2 / 63; - *C = (UINT32)size; - *H = 16; - *S = 63; - *SS = 512; - }else{ - size = (FILELEN)hddsizeMB * 15 * 17 / 2 / 255; - *C = (UINT32)size; - *H = 16; - *S = 255; - *SS = 512; - } -#else - size = hddsizeMB * 15; - *C = (UINT32)size; - *H = 8; - *S = 17; - *SS = 512; -#endif -} - -void newdisk_thd(const OEMCHAR *fname, UINT hddsize) { - - FILEH fh; - UINT8 work[256]; - UINT size; - BRESULT r; - - if ((fname == NULL) || (hddsize < 5) || (hddsize > 256)) { - goto ndthd_err; - } - fh = file_create(fname); - if (fh == FILEH_INVALID) { - goto ndthd_err; - } - ZeroMemory(work, 256); - size = hddsize * (1024 * 1024 / 8 / 256) / 33; - STOREINTELWORD(work, size); - r = (file_write(fh, work, 256) == 256) ? SUCCESS : FAILURE; - r |= writehddipl(fh, 256, 0); - file_close(fh); - if (r != SUCCESS) { - file_delete(fname); - } - -ndthd_err: - return; -} - -void newdisk_nhd_ex_CHS(const OEMCHAR *fname, UINT32 C, UINT16 H, UINT16 S, UINT16 SS, int blank, int *progress, int *cancel) { - - FILEH fh; - NHDHDR nhd; - FILELEN hddsize; - BRESULT r; - - hddsize = (FILELEN)C * H * S * SS / 1024 / 1024; - - if ((fname == NULL) || (hddsize < 1) || (hddsize > NHD_MAXSIZE2)) { - goto ndnhd_err; - } - fh = file_create(fname); - if (fh == FILEH_INVALID) { - goto ndnhd_err; - } - ZeroMemory(&nhd, sizeof(nhd)); - CopyMemory(&nhd.sig, sig_nhd, 15); - STOREINTELDWORD(nhd.headersize, sizeof(nhd)); - STOREINTELDWORD(nhd.cylinders, C); - STOREINTELWORD(nhd.surfaces, H); - STOREINTELWORD(nhd.sectors, S); - STOREINTELWORD(nhd.sectorsize, SS); - r = (file_write(fh, &nhd, sizeof(nhd)) == sizeof(nhd)) ? SUCCESS : FAILURE; - r |= writehddiplex2(fh, SS, (FILELEN)C * H * S * SS, blank, progress, cancel); - file_close(fh); - if (r != SUCCESS) { - file_delete(fname); - } - -ndnhd_err: - return; -} -void newdisk_nhd_ex(const OEMCHAR *fname, UINT hddsize, int blank, int *progress, int *cancel) { - - UINT32 C; - UINT16 H; - UINT16 S; - UINT16 SS; - - hddsize2CHS(hddsize, &C, &H, &S, &SS); - - newdisk_nhd_ex_CHS(fname, C, H, S, SS, blank, progress, cancel); -} -void newdisk_nhd(const OEMCHAR *fname, UINT hddsize) { - - int progress; - int cancel = 0; - - newdisk_nhd_ex(fname, hddsize, 0, &progress, &cancel); -} - -// hddtype = 0:5MB / 1:10MB / 2:15MB / 3:20MB / 5:30MB / 6:40MB -void newdisk_hdi(const OEMCHAR *fname, UINT hddtype) { - -const SASIHDD *sasi; - FILEH fh; - HDIHDR hdi; - UINT32 size; - BRESULT r; - - hddtype &= 7; - if ((fname == NULL) || (hddtype == 7)) { - goto ndhdi_err; - } - sasi = sasihdd + hddtype; - fh = file_create(fname); - if (fh == FILEH_INVALID) { - goto ndhdi_err; - } - ZeroMemory(&hdi, sizeof(hdi)); - size = 256 * sasi->sectors * sasi->surfaces * sasi->cylinders; -// STOREINTELDWORD(hdi.hddtype, 0); - STOREINTELDWORD(hdi.headersize, 4096); - STOREINTELDWORD(hdi.hddsize, size); - STOREINTELDWORD(hdi.sectorsize, 256); - STOREINTELDWORD(hdi.sectors, sasi->sectors); - STOREINTELDWORD(hdi.surfaces, sasi->surfaces); - STOREINTELDWORD(hdi.cylinders, sasi->cylinders); - r = (file_write(fh, &hdi, sizeof(hdi)) == sizeof(hdi)) ? SUCCESS : FAILURE; - r |= writezero(fh, 4096 - sizeof(hdi)); - r |= writehddipl(fh, 256, size); - file_close(fh); - if (r != SUCCESS) { - file_delete(fname); - } - -ndhdi_err: - return; -} -void newdisk_hdi_ex_CHS(const OEMCHAR *fname, UINT32 C, UINT16 H, UINT16 S, UINT16 SS, int blank, int *progress, int *cancel) { - - FILEH fh; - HDIHDR hdi; - FILELEN hddsize; - BRESULT r; - - hddsize = (FILELEN)C * H * S * SS / 1024 / 1024; - - if ((fname == NULL) || (hddsize < 1) || (hddsize > NHD_MAXSIZE2)) { - goto ndhdi_err; - } - fh = file_create(fname); - if (fh == FILEH_INVALID) { - goto ndhdi_err; - } - ZeroMemory(&hdi, sizeof(hdi)); - hddsize = (FILELEN)SS * S * H * C; - STOREINTELDWORD(hdi.headersize, 4096); - STOREINTELDWORD(hdi.hddsize, hddsize); - STOREINTELDWORD(hdi.sectorsize, SS); - STOREINTELDWORD(hdi.sectors, S); - STOREINTELDWORD(hdi.surfaces, H); - STOREINTELDWORD(hdi.cylinders, C); - r = (file_write(fh, &hdi, sizeof(hdi)) == sizeof(hdi)) ? SUCCESS : FAILURE; - r |= writezero(fh, 4096 - sizeof(hdi)); - r |= writehddiplex2(fh, SS, (FILELEN)C * H * S * SS, blank, progress, cancel); - file_close(fh); - if (r != SUCCESS) { - file_delete(fname); - } - -ndhdi_err: - return; -} -void newdisk_hdi_ex(const OEMCHAR *fname, UINT hddsize, int blank, int *progress, int *cancel) { - - UINT32 C; - UINT16 H; - UINT16 S; - UINT16 SS; - - hddsize2CHS(hddsize, &C, &H, &S, &SS); - - newdisk_hdi_ex_CHS(fname, C, H, S, SS, blank, progress, cancel); -} - -void newdisk_vhd(const OEMCHAR *fname, UINT hddsize) { - - FILEH fh; - VHDHDR vhd; - UINT tmp; - BRESULT r; - - if ((fname == NULL) || (hddsize < 2) || (hddsize > 512)) { - goto ndvhd_err; - } - fh = file_create(fname); - if (fh == FILEH_INVALID) { - goto ndvhd_err; - } - ZeroMemory(&vhd, sizeof(vhd)); - CopyMemory(&vhd.sig, sig_vhd, 7); - STOREINTELWORD(vhd.mbsize, (UINT16)hddsize); - STOREINTELWORD(vhd.sectorsize, 256); - vhd.sectors = 32; - vhd.surfaces = 8; - tmp = hddsize * 16; // = * 1024 * 1024 / (8 * 32 * 256); - STOREINTELWORD(vhd.cylinders, (UINT16)tmp); - tmp *= 8 * 32; - STOREINTELDWORD(vhd.totals, tmp); - r = (file_write(fh, &vhd, sizeof(vhd)) == sizeof(vhd)) ? SUCCESS : FAILURE; - r |= writehddipl(fh, 256, 0); - file_close(fh); - if (r != SUCCESS) { - file_delete(fname); - } - -ndvhd_err: - return; -} - -void newdisk_hdn(const OEMCHAR *fname, UINT hddsize) { - - FILEH fh; - FILELEN tmp; - BRESULT r; - - // HDN : RaSCSI HD image (suitable for NEC PC-9801-55/92) - // structure : flat - // sectors/track : 25 (fixed) - // heads : 8 (fixed) - // cylinders : up to 4095 (12bits) (for old BIOS) = 399MiB - // 65535 (16bits) = 6399MiB - if ((fname == NULL) || (hddsize < 2) || (hddsize > 6399)) { - goto ndhdn_err; - } - fh = file_create(fname); - if (fh == FILEH_INVALID) { - goto ndhdn_err; - } - tmp = (FILELEN)hddsize * 1024 * 1024; - // round up - if ((tmp % (512 * 25 * 8)) != 0) { - tmp = tmp / (512 * 25 * 8) + 1; - tmp *= (512 * 25 * 8); - } - r = writezero(fh, tmp); - file_close(fh); - if (r != SUCCESS) { - file_delete(fname); - } - -ndhdn_err: - return; -} - -#ifdef SUPPORT_VPCVHD -const char vpcvhd_sig[] = "conectix"; -const char vpcvhd_sigDH[] = "cxsparse"; -const char vpcvhd_creator[] = "vpc "; -const char vpcvhd_os[] = "Wi2k"; - -void newdisk_vpcvhd_ex_CHS(const OEMCHAR *fname, UINT32 C, UINT16 H, UINT16 S, UINT16 SS, int dynamic, int blank, int *progress, int *cancel) { - - FILEH fh; - VPCVHDFOOTER vpcvhd; - VPCVHDDDH vpcvhd_dh; - BRESULT r = 0; - UINT64 origsize; - UINT32 checksum; - size_t footerlen; - FILELEN hddsize; - - hddsize = (FILELEN)C * H * S * SS / 1024 / 1024; - - if ((fname == NULL) || (hddsize < 1) || (hddsize > NHD_MAXSIZE2)) { - goto vpcvhd_err; - } - fh = file_create(fname); - if (fh == FILEH_INVALID) { - goto vpcvhd_err; - } - - footerlen = sizeof(VPCVHDFOOTER); - ZeroMemory(&vpcvhd, footerlen); - - CopyMemory(&vpcvhd.Cookie, vpcvhd_sig, 8); - STOREMOTOROLADWORD(vpcvhd.Features, 2); - STOREMOTOROLADWORD(vpcvhd.FileFormatVersion, 0x10000); - CopyMemory(&vpcvhd.CreatorApplication, vpcvhd_creator, 4); - STOREMOTOROLADWORD(vpcvhd.CreatorVersion, 0x50003); - CopyMemory(&vpcvhd.CreatorHostOS, vpcvhd_os, 4); - STOREMOTOROLAQWORD(vpcvhd.DataOffset, (SINT64)-1); - STOREMOTOROLADWORD(vpcvhd.DiskType, 2); - - STOREMOTOROLAWORD(vpcvhd.Cylinder, C <= 65535 ? (UINT16)C : 65535); - vpcvhd.Heads = (H <= 255 ? (UINT8)H : 255); - vpcvhd.SectorsPerCylinder = (S <= 255 ? (UINT8)S : 255); - origsize = (UINT64)C * H * S * SS; - STOREMOTOROLAQWORD(vpcvhd.OriginalSize, origsize); - CopyMemory(&vpcvhd.CurrentSize, &vpcvhd.OriginalSize, 8); - - if(dynamic){ - UINT32 blockcount; - UINT32 i; - UINT32 blocksize = 0x00200000; - UINT32 nodata = 0xffffffff; - - STOREMOTOROLAQWORD(vpcvhd.DataOffset, (UINT64)(sizeof(VPCVHDFOOTER))); - STOREMOTOROLADWORD(vpcvhd.DiskType, 3); - - checksum = vpc_calc_checksum((UINT8*)(&vpcvhd), footerlen); - STOREMOTOROLADWORD(vpcvhd.CheckSum, checksum); - - blockcount = (UINT32)((origsize + blocksize - 1) / blocksize); - ZeroMemory(&vpcvhd_dh, sizeof(VPCVHDDDH)); - CopyMemory(&vpcvhd_dh.Cookie, vpcvhd_sigDH, 8); - STOREMOTOROLAQWORD(vpcvhd_dh.DataOffset, (SINT64)-1); - STOREMOTOROLAQWORD(vpcvhd_dh.TableOffset, (UINT64)(sizeof(VPCVHDFOOTER) + sizeof(VPCVHDDDH))); - STOREMOTOROLADWORD(vpcvhd_dh.HeaderVersion, 0x00010000); - STOREMOTOROLADWORD(vpcvhd_dh.MaxTableEntries, blockcount); - STOREMOTOROLADWORD(vpcvhd_dh.BlockSize, blocksize); - - checksum = vpc_calc_checksum((UINT8*)(&vpcvhd_dh), sizeof(VPCVHDDDH)); - STOREMOTOROLADWORD(vpcvhd_dh.CheckSum, checksum); - - r |= (file_write(fh, &vpcvhd, sizeof(vpcvhd)) == sizeof(vpcvhd)) ? SUCCESS : FAILURE; - r |= (file_write(fh, &vpcvhd_dh, sizeof(vpcvhd_dh)) == sizeof(vpcvhd_dh)) ? SUCCESS : FAILURE; - for(i=0;i +#if defined(OSLANG_UTF8) || defined(OSLANG_UCS2) +#include "oemtext.h" +#endif +#include +#include "newdisk.h" +#include +#include +#include "hddboot.res" + +#ifdef SUPPORT_VPCVHD +#include "hdd_vpc.h" +#endif + + +// ---- fdd + +void newdisk_fdd(const OEMCHAR *fname, REG8 type, const OEMCHAR *label) { + + _D88HEAD d88head; + FILEH fh; + + ZeroMemory(&d88head, sizeof(d88head)); + STOREINTELDWORD(d88head.fd_size, sizeof(d88head)); +#if defined(OSLANG_UTF8) || defined(OSLANG_UCS2) + oemtext_oemtosjis((char *)d88head.fd_name, sizeof(d88head.fd_name), + label, (UINT)-1); +#else + milstr_ncpy((char *)d88head.fd_name, label, sizeof(d88head.fd_name)); +#endif + d88head.fd_type = type; + fh = file_create(fname); + if (fh != FILEH_INVALID) { + file_write(fh, &d88head, sizeof(d88head)); + file_close(fh); + } +} + +void newdisk_123mb_fdd(const OEMCHAR *fname) { + + FILEH fh; + char databuf[8192] = {0}; + int fdsize = 1261568; + + fh = file_create(fname); + if (fh != FILEH_INVALID) { + while(fdsize){ + if(fdsize < sizeof(databuf)){ + file_write(fh, &databuf, fdsize); + break; + }else{ + file_write(fh, &databuf, sizeof(databuf)); + fdsize -= sizeof(databuf); + } + } + file_close(fh); + } +} + +void newdisk_144mb_fdd(const OEMCHAR *fname) { + + FILEH fh; + char databuf[8192] = {0}; + int fdsize = 1474560; + + fh = file_create(fname); + if (fh != FILEH_INVALID) { + while(fdsize){ + if(fdsize < sizeof(databuf)){ + file_write(fh, &databuf, fdsize); + break; + }else{ + file_write(fh, &databuf, sizeof(databuf)); + fdsize -= sizeof(databuf); + } + } + file_close(fh); + } +} + + + +// ---- hdd + +static BRESULT writezero(FILEH fh, FILELEN size) { + + UINT8 work[256]; + FILELEN wsize; + + ZeroMemory(work, sizeof(work)); + while(size) { + wsize = MIN(size, sizeof(work)); + if (file_write(fh, work, (UINT)wsize) != wsize) { + return(FAILURE); + } + size -= wsize; + } + return(SUCCESS); +} + +static BRESULT writehddiplex2(FILEH fh, UINT ssize, FILELEN tsize, int blank, int *progress, int *cancel) { + + UINT8 *work; + FILELEN size; + FILELEN progtotal; + int worksize = 65536; + + if(tsize < worksize) worksize = (int)tsize; + if(tsize > 1024*1024) worksize = 1024*1024; + if(tsize > 8*1024*1024) worksize = 8*1024*1024; + if(worksize < sizeof(hdddiskboot)) worksize = sizeof(hdddiskboot); + work = (UINT8*)malloc(worksize); + if (!work) { + return(FAILURE); + } + + progtotal = tsize; + *progress = 0; + ZeroMemory(work, worksize); + if(!blank){ + CopyMemory(work, hdddiskboot, sizeof(hdddiskboot)); + if (ssize < 1024) { + work[ssize - 2] = 0x55; + work[ssize - 1] = 0xaa; + } + } + if (file_write(fh, work, worksize) != worksize) { + free(work); + return(FAILURE); + } + if (tsize > worksize) { + tsize -= worksize; + ZeroMemory(work, worksize); + while(tsize) { + size = MIN(tsize, worksize); + tsize -= size; + if (file_write(fh, work, (UINT)size) != size) { + free(work); + return(FAILURE); + } + *progress = (UINT32)((progtotal - tsize) * 100 / progtotal); + if(*cancel){ + free(work); + return(FAILURE); + } + } + } + free(work); + return(SUCCESS); +} +static BRESULT writehddiplex(FILEH fh, UINT ssize, FILELEN tsize, int *progress, int *cancel) { + + return writehddiplex2(fh, ssize, tsize, 0, progress, cancel); +} +static BRESULT writehddipl(FILEH fh, UINT ssize, FILELEN tsize) { + + int progress; + int cancel = 0; + return writehddiplex(fh, ssize, tsize, &progress, &cancel); +} + +static void hddsize2CHS(UINT hddsizeMB, UINT32 *C, UINT16 *H, UINT16 *S, UINT16 *SS) { + + FILELEN size; +#ifdef SUPPORT_LARGE_HDD + if(hddsizeMB <= 4351){ + size = (FILELEN)hddsizeMB * 15; + *C = (UINT32)size; + *H = 8; + *S = 17; + *SS = 512; + }else if(hddsizeMB <= 32255){ + size = (FILELEN)hddsizeMB * 15 * 17 / 2 / 63; + *C = (UINT32)size; + *H = 16; + *S = 63; + *SS = 512; + }else{ + size = (FILELEN)hddsizeMB * 15 * 17 / 2 / 255; + *C = (UINT32)size; + *H = 16; + *S = 255; + *SS = 512; + } +#else + size = hddsizeMB * 15; + *C = (UINT32)size; + *H = 8; + *S = 17; + *SS = 512; +#endif +} + +void newdisk_thd(const OEMCHAR *fname, UINT hddsize) { + + FILEH fh; + UINT8 work[256]; + UINT size; + BRESULT r; + + if ((fname == NULL) || (hddsize < 5) || (hddsize > 256)) { + goto ndthd_err; + } + fh = file_create(fname); + if (fh == FILEH_INVALID) { + goto ndthd_err; + } + ZeroMemory(work, 256); + size = hddsize * (1024 * 1024 / 8 / 256) / 33; + STOREINTELWORD(work, size); + r = (file_write(fh, work, 256) == 256) ? SUCCESS : FAILURE; + r |= writehddipl(fh, 256, 0); + file_close(fh); + if (r != SUCCESS) { + file_delete(fname); + } + +ndthd_err: + return; +} + +void newdisk_nhd_ex_CHS(const OEMCHAR *fname, UINT32 C, UINT16 H, UINT16 S, UINT16 SS, int blank, int *progress, int *cancel) { + + FILEH fh; + NHDHDR nhd; + FILELEN hddsize; + BRESULT r; + + hddsize = (FILELEN)C * H * S * SS / 1024 / 1024; + + if ((fname == NULL) || (hddsize < 1) || (hddsize > NHD_MAXSIZE2)) { + goto ndnhd_err; + } + fh = file_create(fname); + if (fh == FILEH_INVALID) { + goto ndnhd_err; + } + ZeroMemory(&nhd, sizeof(nhd)); + CopyMemory(&nhd.sig, sig_nhd, 15); + STOREINTELDWORD(nhd.headersize, sizeof(nhd)); + STOREINTELDWORD(nhd.cylinders, C); + STOREINTELWORD(nhd.surfaces, H); + STOREINTELWORD(nhd.sectors, S); + STOREINTELWORD(nhd.sectorsize, SS); + r = (file_write(fh, &nhd, sizeof(nhd)) == sizeof(nhd)) ? SUCCESS : FAILURE; + r |= writehddiplex2(fh, SS, (FILELEN)C * H * S * SS, blank, progress, cancel); + file_close(fh); + if (r != SUCCESS) { + file_delete(fname); + } + +ndnhd_err: + return; +} +void newdisk_nhd_ex(const OEMCHAR *fname, UINT hddsize, int blank, int *progress, int *cancel) { + + UINT32 C; + UINT16 H; + UINT16 S; + UINT16 SS; + + hddsize2CHS(hddsize, &C, &H, &S, &SS); + + newdisk_nhd_ex_CHS(fname, C, H, S, SS, blank, progress, cancel); +} +void newdisk_nhd(const OEMCHAR *fname, UINT hddsize) { + + int progress; + int cancel = 0; + + newdisk_nhd_ex(fname, hddsize, 0, &progress, &cancel); +} + +// hddtype = 0:5MB / 1:10MB / 2:15MB / 3:20MB / 5:30MB / 6:40MB +void newdisk_hdi(const OEMCHAR *fname, UINT hddtype) { + +const SASIHDD *sasi; + FILEH fh; + HDIHDR hdi; + UINT32 size; + BRESULT r; + + hddtype &= 7; + if ((fname == NULL) || (hddtype == 7)) { + goto ndhdi_err; + } + sasi = sasihdd + hddtype; + fh = file_create(fname); + if (fh == FILEH_INVALID) { + goto ndhdi_err; + } + ZeroMemory(&hdi, sizeof(hdi)); + size = 256 * sasi->sectors * sasi->surfaces * sasi->cylinders; +// STOREINTELDWORD(hdi.hddtype, 0); + STOREINTELDWORD(hdi.headersize, 4096); + STOREINTELDWORD(hdi.hddsize, size); + STOREINTELDWORD(hdi.sectorsize, 256); + STOREINTELDWORD(hdi.sectors, sasi->sectors); + STOREINTELDWORD(hdi.surfaces, sasi->surfaces); + STOREINTELDWORD(hdi.cylinders, sasi->cylinders); + r = (file_write(fh, &hdi, sizeof(hdi)) == sizeof(hdi)) ? SUCCESS : FAILURE; + r |= writezero(fh, 4096 - sizeof(hdi)); + r |= writehddipl(fh, 256, size); + file_close(fh); + if (r != SUCCESS) { + file_delete(fname); + } + +ndhdi_err: + return; +} +void newdisk_hdi_ex_CHS(const OEMCHAR *fname, UINT32 C, UINT16 H, UINT16 S, UINT16 SS, int blank, int *progress, int *cancel) { + + FILEH fh; + HDIHDR hdi; + FILELEN hddsize; + BRESULT r; + + hddsize = (FILELEN)C * H * S * SS / 1024 / 1024; + + if ((fname == NULL) || (hddsize < 1) || (hddsize > NHD_MAXSIZE2)) { + goto ndhdi_err; + } + fh = file_create(fname); + if (fh == FILEH_INVALID) { + goto ndhdi_err; + } + ZeroMemory(&hdi, sizeof(hdi)); + hddsize = (FILELEN)SS * S * H * C; + STOREINTELDWORD(hdi.headersize, 4096); + STOREINTELDWORD(hdi.hddsize, hddsize); + STOREINTELDWORD(hdi.sectorsize, SS); + STOREINTELDWORD(hdi.sectors, S); + STOREINTELDWORD(hdi.surfaces, H); + STOREINTELDWORD(hdi.cylinders, C); + r = (file_write(fh, &hdi, sizeof(hdi)) == sizeof(hdi)) ? SUCCESS : FAILURE; + r |= writezero(fh, 4096 - sizeof(hdi)); + r |= writehddiplex2(fh, SS, (FILELEN)C * H * S * SS, blank, progress, cancel); + file_close(fh); + if (r != SUCCESS) { + file_delete(fname); + } + +ndhdi_err: + return; +} +void newdisk_hdi_ex(const OEMCHAR *fname, UINT hddsize, int blank, int *progress, int *cancel) { + + UINT32 C; + UINT16 H; + UINT16 S; + UINT16 SS; + + hddsize2CHS(hddsize, &C, &H, &S, &SS); + + newdisk_hdi_ex_CHS(fname, C, H, S, SS, blank, progress, cancel); +} + +void newdisk_vhd(const OEMCHAR *fname, UINT hddsize) { + + FILEH fh; + VHDHDR vhd; + UINT tmp; + BRESULT r; + + if ((fname == NULL) || (hddsize < 2) || (hddsize > 512)) { + goto ndvhd_err; + } + fh = file_create(fname); + if (fh == FILEH_INVALID) { + goto ndvhd_err; + } + ZeroMemory(&vhd, sizeof(vhd)); + CopyMemory(&vhd.sig, sig_vhd, 7); + STOREINTELWORD(vhd.mbsize, (UINT16)hddsize); + STOREINTELWORD(vhd.sectorsize, 256); + vhd.sectors = 32; + vhd.surfaces = 8; + tmp = hddsize * 16; // = * 1024 * 1024 / (8 * 32 * 256); + STOREINTELWORD(vhd.cylinders, (UINT16)tmp); + tmp *= 8 * 32; + STOREINTELDWORD(vhd.totals, tmp); + r = (file_write(fh, &vhd, sizeof(vhd)) == sizeof(vhd)) ? SUCCESS : FAILURE; + r |= writehddipl(fh, 256, 0); + file_close(fh); + if (r != SUCCESS) { + file_delete(fname); + } + +ndvhd_err: + return; +} + +void newdisk_hdn(const OEMCHAR *fname, UINT hddsize) { + + FILEH fh; + FILELEN tmp; + BRESULT r; + + // HDN : RaSCSI HD image (suitable for NEC PC-9801-55/92) + // structure : flat + // sectors/track : 25 (fixed) + // heads : 8 (fixed) + // cylinders : up to 4095 (12bits) (for old BIOS) = 399MiB + // 65535 (16bits) = 6399MiB + if ((fname == NULL) || (hddsize < 2) || (hddsize > 6399)) { + goto ndhdn_err; + } + fh = file_create(fname); + if (fh == FILEH_INVALID) { + goto ndhdn_err; + } + tmp = (FILELEN)hddsize * 1024 * 1024; + // round up + if ((tmp % (512 * 25 * 8)) != 0) { + tmp = tmp / (512 * 25 * 8) + 1; + tmp *= (512 * 25 * 8); + } + r = writezero(fh, tmp); + file_close(fh); + if (r != SUCCESS) { + file_delete(fname); + } + +ndhdn_err: + return; +} + +#ifdef SUPPORT_VPCVHD +const char vpcvhd_sig[] = "conectix"; +const char vpcvhd_sigDH[] = "cxsparse"; +const char vpcvhd_creator[] = "vpc "; +const char vpcvhd_os[] = "Wi2k"; + +void newdisk_vpcvhd_ex_CHS(const OEMCHAR *fname, UINT32 C, UINT16 H, UINT16 S, UINT16 SS, int dynamic, int blank, int *progress, int *cancel) { + + FILEH fh; + VPCVHDFOOTER vpcvhd; + VPCVHDDDH vpcvhd_dh; + BRESULT r = 0; + UINT64 origsize; + UINT32 checksum; + size_t footerlen; + FILELEN hddsize; + + hddsize = (FILELEN)C * H * S * SS / 1024 / 1024; + + if ((fname == NULL) || (hddsize < 1) || (hddsize > NHD_MAXSIZE2)) { + goto vpcvhd_err; + } + fh = file_create(fname); + if (fh == FILEH_INVALID) { + goto vpcvhd_err; + } + + footerlen = sizeof(VPCVHDFOOTER); + ZeroMemory(&vpcvhd, footerlen); + + CopyMemory(&vpcvhd.Cookie, vpcvhd_sig, 8); + STOREMOTOROLADWORD(vpcvhd.Features, 2); + STOREMOTOROLADWORD(vpcvhd.FileFormatVersion, 0x10000); + CopyMemory(&vpcvhd.CreatorApplication, vpcvhd_creator, 4); + STOREMOTOROLADWORD(vpcvhd.CreatorVersion, 0x50003); + CopyMemory(&vpcvhd.CreatorHostOS, vpcvhd_os, 4); + STOREMOTOROLAQWORD(vpcvhd.DataOffset, (SINT64)-1); + STOREMOTOROLADWORD(vpcvhd.DiskType, 2); + + STOREMOTOROLAWORD(vpcvhd.Cylinder, C <= 65535 ? (UINT16)C : 65535); + vpcvhd.Heads = (H <= 255 ? (UINT8)H : 255); + vpcvhd.SectorsPerCylinder = (S <= 255 ? (UINT8)S : 255); + origsize = (UINT64)C * H * S * SS; + STOREMOTOROLAQWORD(vpcvhd.OriginalSize, origsize); + CopyMemory(&vpcvhd.CurrentSize, &vpcvhd.OriginalSize, 8); + + if(dynamic){ + UINT32 blockcount; + UINT32 i; + UINT32 blocksize = 0x00200000; + UINT32 nodata = 0xffffffff; + + STOREMOTOROLAQWORD(vpcvhd.DataOffset, (UINT64)(sizeof(VPCVHDFOOTER))); + STOREMOTOROLADWORD(vpcvhd.DiskType, 3); + + checksum = vpc_calc_checksum((UINT8*)(&vpcvhd), footerlen); + STOREMOTOROLADWORD(vpcvhd.CheckSum, checksum); + + blockcount = (UINT32)((origsize + blocksize - 1) / blocksize); + ZeroMemory(&vpcvhd_dh, sizeof(VPCVHDDDH)); + CopyMemory(&vpcvhd_dh.Cookie, vpcvhd_sigDH, 8); + STOREMOTOROLAQWORD(vpcvhd_dh.DataOffset, (SINT64)-1); + STOREMOTOROLAQWORD(vpcvhd_dh.TableOffset, (UINT64)(sizeof(VPCVHDFOOTER) + sizeof(VPCVHDDDH))); + STOREMOTOROLADWORD(vpcvhd_dh.HeaderVersion, 0x00010000); + STOREMOTOROLADWORD(vpcvhd_dh.MaxTableEntries, blockcount); + STOREMOTOROLADWORD(vpcvhd_dh.BlockSize, blocksize); + + checksum = vpc_calc_checksum((UINT8*)(&vpcvhd_dh), sizeof(VPCVHDDDH)); + STOREMOTOROLADWORD(vpcvhd_dh.CheckSum, checksum); + + r |= (file_write(fh, &vpcvhd, sizeof(vpcvhd)) == sizeof(vpcvhd)) ? SUCCESS : FAILURE; + r |= (file_write(fh, &vpcvhd_dh, sizeof(vpcvhd_dh)) == sizeof(vpcvhd_dh)) ? SUCCESS : FAILURE; + for(i=0;i -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_IDEIO) -#include -#endif -#if !defined(_MSC_VER) -#include -#endif -#if defined(SUPPORT_MULTITHREAD) -#include -#endif - -#if defined(_MSC_VER) -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#endif - - _SXSIDEV sxsi_dev[SASIHDD_MAX + SCSIHDD_MAX]; - -#if !defined(_WIN32) -unsigned GetTickCount() -{ - struct timeval tv; - if(gettimeofday(&tv, NULL) != 0) - return 0; - - return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); -} -#endif /* _WIN32 */ - -// ---- - -static BRESULT nc_reopen(SXSIDEV sxsi) { - - (void)sxsi; - return(FAILURE); -} - -static REG8 nc_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { - - (void)sxsi; - (void)pos; - (void)buf; - (void)size; - return(0x60); -} - -static REG8 nc_write(SXSIDEV sxsi, FILEPOS pos, const UINT8 *buf, UINT size) { - - (void)sxsi; - (void)pos; - (void)buf; - (void)size; - return(0x60); -} - -static REG8 nc_format(SXSIDEV sxsi, FILEPOS pos) { - - (void)sxsi; - (void)pos; - return(0x60); -} - -static void nc_close(SXSIDEV sxsi) { - - (void)sxsi; -} - -static void nc_destroy(SXSIDEV sxsi) { - - (void)sxsi; -} - - -static void sxsi_disconnect(SXSIDEV sxsi) { - - if (sxsi) { - if (sxsi->flag & SXSIFLAG_FILEOPENED) { -#if defined(SUPPORT_IDEIO) - ideio_notify(sxsi->drv, 0); -#endif - (*sxsi->close)(sxsi); - } - if (sxsi->flag & SXSIFLAG_READY) { - (*sxsi->destroy)(sxsi); - } - sxsi->flag = 0; - sxsi->reopen = nc_reopen; - sxsi->read = nc_read; - sxsi->write = nc_write; - sxsi->format = nc_format; - sxsi->close = nc_close; - sxsi->destroy = nc_destroy; - } -} - - -// ---- - -void sxsi_initialize(void) { - - UINT i; - - ZeroMemory(sxsi_dev, sizeof(sxsi_dev)); - for (i=0; iflag & SXSIFLAG_FILEOPENED) { - sxsi->flag &= ~SXSIFLAG_FILEOPENED; - (*sxsi->close)(sxsi); - } - sxsi++; - } -} - -void sxsi_alltrash(void) { - - SXSIDEV sxsi; - SXSIDEV sxsiterm; - - sxsi = sxsi_dev; - sxsiterm = sxsi + NELEMENTS(sxsi_dev); - while(sxsi < sxsiterm) { - sxsi_disconnect(sxsi); - sxsi++; - } -} - -BOOL sxsi_isconnect(SXSIDEV sxsi) { - - if (sxsi) { - switch(sxsi->devtype) { - case SXSIDEV_HDD: - if (sxsi->flag & SXSIFLAG_READY) { - return(TRUE); - } - break; - - case SXSIDEV_CDROM: - return(TRUE); - } - } - return(FALSE); -} - -BRESULT sxsi_prepare(SXSIDEV sxsi) { - - if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY))) { - return(FAILURE); - } - if (!(sxsi->flag & SXSIFLAG_FILEOPENED)) { - if ((*sxsi->reopen)(sxsi) == SUCCESS) { - sxsi->flag |= SXSIFLAG_FILEOPENED; - } - else { - return(FAILURE); - } - } - sysmng_hddaccess(sxsi->drv); - return(SUCCESS); -} - - -// ---- - -SXSIDEV sxsi_getptr(REG8 drv) { - - UINT num; - - num = drv & 0x0f; - if (!(drv & 0x20)) { // SASI or IDE - if (num < SASIHDD_MAX) { - return(sxsi_dev + num); - } - } -#if defined(SUPPORT_SCSI) - else { - if (num < SCSIHDD_MAX) { // SCSI - return(sxsi_dev + SASIHDD_MAX + num); - } - } -#endif - return(NULL); -} - -OEMCHAR *sxsi_getfilename(REG8 drv) { - - SXSIDEV sxsi; - - sxsi = sxsi_getptr(drv); - if ((sxsi) && (sxsi->flag & SXSIFLAG_READY)) { - return(sxsi->fname); - } - return(NULL); -} - -BRESULT sxsi_setdevtype(REG8 drv, UINT8 dev) { - - SXSIDEV sxsi; - - sxsi = sxsi_getptr(drv); - if (sxsi) { - if (sxsi->devtype != dev) { - sxsi_disconnect(sxsi); - sxsi->devtype = dev; - } - return(SUCCESS); - } - else { - return(FAILURE); - } -} - -UINT8 sxsi_getdevtype(REG8 drv) { - - SXSIDEV sxsi; - - sxsi = sxsi_getptr(drv); - if (sxsi) { - return(sxsi->devtype); - } - else { - return(SXSIDEV_NC); - } -} - -// CD入れ替えのタイムアウト(投げやり) -char cdchange_flag = 0; -DWORD cdchange_reqtime = 0; -REG8 cdchange_drv; -OEMCHAR cdchange_fname[MAX_PATH]; -void cdchange_timeoutproc(NEVENTITEM item) { - - if(!cdchange_flag) return; - cdchange_flag = 0; - sxsi_devopen(cdchange_drv, cdchange_fname); -#if defined(SUPPORT_IDEIO) - ideio_mediachange(cdchange_drv); -#endif -#if defined(NP2_WIN) - sysmng_requestupdatecaption(SYS_UPDATECAPTION_FDD); -#endif -} -static void cdchange_timeoutset(void) { - - nevent_setbyms(NEVENT_CDWAIT, 6000, cdchange_timeoutproc, NEVENT_ABSOLUTE); -} - -#ifdef SUPPORT_NVL_IMAGES -BRESULT sxsihdd_nvl_open(SXSIDEV sxsi, const OEMCHAR *fname); -#endif - -BRESULT sxsi_devopen(REG8 drv, const OEMCHAR *fname) { - - SXSIDEV sxsi; - BRESULT r; - - sxsi = sxsi_getptr(drv); - if (sxsi == NULL) { - goto sxsiope_err; - } - switch(sxsi->devtype) { - case SXSIDEV_HDD: - if ((fname == NULL) || (fname[0] == '\0')) { - goto sxsiope_err; - } - r = sxsihdd_open(sxsi, fname); -#ifdef SUPPORT_NVL_IMAGES - if (r == FAILURE) - { - r = sxsihdd_nvl_open(sxsi, fname); - } -#endif - break; - - case SXSIDEV_CDROM: -#if defined(SUPPORT_IDEIO) - if (cdchange_flag) { - // CD交換中 - if(GetTickCount()-cdchange_reqtime>5000){ - // 強制交換 - cdchange_timeoutproc(NULL); - } - return(FAILURE); - } - if ((fname == NULL) || (fname[0] == '\0')) { - int num = drv & 0x03; - if (sxsi->flag & SXSIFLAG_FILEOPENED) { - ideio_notify(sxsi->drv, 0); - (*sxsi->close)(sxsi); - } - if (sxsi->flag & SXSIFLAG_READY) { - (*sxsi->destroy)(sxsi); - } - file_cpyname(sxsi->fname, _T("\0\0\0\0"), 1); - sxsi->flag = 0; - file_cpyname(np2cfg.idecd[num], _T("\0\0\0\0"), 1); - sysmng_updatecaption(1); // SYS_UPDATECAPTION_FDD - return(SUCCESS); - } - else { - if((sxsi->flag & SXSIFLAG_READY) && (_tcsnicmp(sxsi->fname, OEMTEXT("\\\\.\\"), 4)!=0 || _tcsicmp(sxsi->fname, np2cfg.idecd[drv & 0x0f])==0) ){ - // いったん取り出す - if (sxsi->flag & SXSIFLAG_FILEOPENED) { - ideio_notify(sxsi->drv, 0); - (*sxsi->close)(sxsi); - } - if (sxsi->flag & SXSIFLAG_READY) { - (*sxsi->destroy)(sxsi); - } - sxsi->flag = 0; - cdchange_drv = drv; - file_cpyname(sxsi->fname, _T("\0\0\0\0"), 1); - file_cpyname(np2cfg.idecd[drv & 0x03], _T("\0\0\0\0"), NELEMENTS(cdchange_fname)); - file_cpyname(cdchange_fname, fname, NELEMENTS(cdchange_fname)); - cdchange_flag = 1; - cdchange_timeoutset(); - cdchange_reqtime = GetTickCount(); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - return(FAILURE); // XXX: ここで失敗返してええの? - } - r = sxsicd_open(sxsi, fname); - if (r == SUCCESS || _tcsnicmp(fname, OEMTEXT("\\\\.\\"), 4)==0) { - int num = drv & 0x03; - file_cpyname(np2cfg.idecd[num], fname, MAX_PATH); - if(r != SUCCESS && _tcsnicmp(fname, OEMTEXT("\\\\.\\"), 4)==0){ - ideio_notify(sxsi->drv, 0); - } - }else{ - int num = drv & 0x03; - file_cpyname(np2cfg.idecd[num], _T("\0\0\0\0"), 1); - } - sysmng_updatecaption(1); // SYS_UPDATECAPTION_FDD - ideio_mediachange(drv); - } -#endif - break; - - default: - r = FAILURE; - break; - } - if (r != SUCCESS) { - goto sxsiope_err; - } - file_cpyname(sxsi->fname, fname, NELEMENTS(sxsi->fname)); - sxsi->flag = SXSIFLAG_READY | SXSIFLAG_FILEOPENED; -#if defined(SUPPORT_IDEIO) - ideio_notify(sxsi->drv, 1); -#endif - return(SUCCESS); - -sxsiope_err: - return(FAILURE); -} - -void sxsi_devclose(REG8 drv) { - - SXSIDEV sxsi; - - sxsi = sxsi_getptr(drv); - sxsi_disconnect(sxsi); -} - -BOOL sxsi_issasi(void) { - - REG8 drv; - SXSIDEV sxsi; - BOOL ret; - - ret = FALSE; - for (drv=0x00; drv<0x04; drv++) { - sxsi = sxsi_getptr(drv); - if (sxsi) { - if ((drv < 0x02) && (sxsi->devtype == SXSIDEV_HDD)) { - if (sxsi->flag & SXSIFLAG_READY) { - if (sxsi->mediatype & SXSIMEDIA_INVSASI) { - return(FALSE); - } - ret = TRUE; - } - } - else { - return(FALSE); - } - } - } - return(ret); -} - -BOOL sxsi_isscsi(void) { - - REG8 drv; - SXSIDEV sxsi; - - for (drv=0x20; drv<0x28; drv++) { - sxsi = sxsi_getptr(drv); - if (sxsi_isconnect(sxsi)) { - return(TRUE); - } - } - return(FALSE); -} - -BOOL sxsi_iside(void) { - - REG8 drv; - SXSIDEV sxsi; - - for (drv=0x00; drv<0x04; drv++) { - sxsi = sxsi_getptr(drv); - if (sxsi_isconnect(sxsi)) { - return(TRUE); - } - } - return(FALSE); -} - - - -REG8 sxsi_read(REG8 drv, FILEPOS pos, UINT8 *buf, UINT size) { - - SXSIDEV sxsi; - - sxsi = sxsi_getptr(drv); - if (sxsi != NULL) { - return(sxsi->read(sxsi, pos, buf, size)); - } - else { - return(0x60); - } -} - -REG8 sxsi_write(REG8 drv, FILEPOS pos, const UINT8 *buf, UINT size) { - - SXSIDEV sxsi; - - sxsi = sxsi_getptr(drv); - if (sxsi != NULL) { - return(sxsi->write(sxsi, pos, buf, size)); - } - else { - return(0x60); - } -} - -REG8 sxsi_format(REG8 drv, FILEPOS pos) { - - SXSIDEV sxsi; - - sxsi = sxsi_getptr(drv); - if (sxsi != NULL) { - return(sxsi->format(sxsi, pos)); - } - else { - return(0x60); - } -} - -BRESULT sxsi_state_save(const OEMCHAR *ext) { - SXSIDEV sxsi; - SXSIDEV sxsiterm; - - sxsi = sxsi_dev; - sxsiterm = sxsi + NELEMENTS(sxsi_dev); - while(sxsi < sxsiterm) { - if (sxsi->state_save != NULL) { - _SYSTIME st; - OEMCHAR dt[64]; - OEMCHAR sfname[MAX_PATH]; - BRESULT r; - - timemng_gettime(&st); - OEMSNPRINTF(dt, sizeof(dt), - OEMTEXT("%04d%02d%02d%02d%02d%02d%03d"), - st.year, st.month, st.day, - st.hour, st.minute, st.second, - st.milli); - - file_cpyname(sfname, sxsi->fname, NELEMENTS(sfname)); - file_catname(sfname, OEMTEXT("_"), NELEMENTS(sfname)); - file_catname(sfname, ext, NELEMENTS(sfname)); - file_catname(sfname, OEMTEXT("_"), NELEMENTS(sfname)); - file_catname(sfname, dt, NELEMENTS(sfname)); - - r = (*sxsi->state_save)(sxsi, sfname); - if (r != SUCCESS) { - return(r); - } - } - - sxsi++; - } -} - -static int str_get_mem_size(const OEMCHAR *str) -{ - return ((int)((OEMCHAR *)milstr_chr(str, 0) - str)); -} - -static BRESULT state_load(SXSIDEV sxsi, const OEMCHAR *ext) -{ - OEMCHAR dir[MAX_PATH]; - FLINFO fli; - FLISTH flh; - OEMCHAR rname[MAX_PATH]; - int rnamesize; - OEMCHAR tname[MAX_PATH]; - - file_cpyname(dir, sxsi->fname, NELEMENTS(dir)); - file_cutname(dir); - file_cutseparator(dir); - - flh = file_list1st(dir, &fli); - if (flh == FLISTH_INVALID) - { - return (SUCCESS); - } - - file_cpyname(rname, file_getname(sxsi->fname), NELEMENTS(rname)); - file_catname(rname, OEMTEXT("_"), NELEMENTS(rname)); - file_catname(rname, ext, NELEMENTS(rname)); - file_catname(rname, OEMTEXT("_"), NELEMENTS(rname)); - rnamesize = str_get_mem_size(rname); - - ZeroMemory(tname, sizeof(OEMCHAR) * MAX_PATH); - - do - { - int namesize; - - if ((fli.attr & FILEATTR_VOLUME) || - (fli.attr & FILEATTR_DIRECTORY)) - { - continue; - } - - namesize = str_get_mem_size(fli.path); - - if (namesize <= rnamesize) - { - continue; - } - - if (milstr_memcmp(fli.path, rname) != 0) - { - continue; - } - - if (file_cmpname(fli.path, tname) > 0) - { - file_cpyname(tname, fli.path, NELEMENTS(tname)); - } - } while (file_listnext(flh, &fli) == SUCCESS); - - if (OEMSTRLEN(tname) == 0) - { - return (SUCCESS); - } - - file_setseparator(dir, NELEMENTS(dir)); - file_catname(dir, tname, NELEMENTS(dir)); - - return ((*sxsi->state_load)(sxsi, dir)); -} - -BRESULT sxsi_state_load(const OEMCHAR *ext) -{ - SXSIDEV sxsi; - SXSIDEV sxsiterm; - - sxsi = sxsi_dev; - sxsiterm = sxsi + NELEMENTS(sxsi_dev); - while (sxsi < sxsiterm) { - if (sxsi->state_load != NULL) { - BRESULT r; - - r = state_load(sxsi, ext); - if (r != SUCCESS) - { - return(r); - } - } - - sxsi++; - } -} - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_IDEIO) +#include +#endif +#if !defined(_MSC_VER) +#include +#endif +#if defined(SUPPORT_MULTITHREAD) +#include +#endif + +#if defined(_MSC_VER) +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#endif + + _SXSIDEV sxsi_dev[SASIHDD_MAX + SCSIHDD_MAX]; + +#if !defined(_WIN32) +unsigned GetTickCount() +{ + struct timeval tv; + if(gettimeofday(&tv, NULL) != 0) + return 0; + + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); +} +#endif /* _WIN32 */ + +// ---- + +static BRESULT nc_reopen(SXSIDEV sxsi) { + + (void)sxsi; + return(FAILURE); +} + +static REG8 nc_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { + + (void)sxsi; + (void)pos; + (void)buf; + (void)size; + return(0x60); +} + +static REG8 nc_write(SXSIDEV sxsi, FILEPOS pos, const UINT8 *buf, UINT size) { + + (void)sxsi; + (void)pos; + (void)buf; + (void)size; + return(0x60); +} + +static REG8 nc_format(SXSIDEV sxsi, FILEPOS pos) { + + (void)sxsi; + (void)pos; + return(0x60); +} + +static void nc_close(SXSIDEV sxsi) { + + (void)sxsi; +} + +static void nc_destroy(SXSIDEV sxsi) { + + (void)sxsi; +} + + +static void sxsi_disconnect(SXSIDEV sxsi) { + + if (sxsi) { + if (sxsi->flag & SXSIFLAG_FILEOPENED) { +#if defined(SUPPORT_IDEIO) + ideio_notify(sxsi->drv, 0); +#endif + (*sxsi->close)(sxsi); + } + if (sxsi->flag & SXSIFLAG_READY) { + (*sxsi->destroy)(sxsi); + } + sxsi->flag = 0; + sxsi->reopen = nc_reopen; + sxsi->read = nc_read; + sxsi->write = nc_write; + sxsi->format = nc_format; + sxsi->close = nc_close; + sxsi->destroy = nc_destroy; + } +} + + +// ---- + +void sxsi_initialize(void) { + + UINT i; + + ZeroMemory(sxsi_dev, sizeof(sxsi_dev)); + for (i=0; iflag & SXSIFLAG_FILEOPENED) { + sxsi->flag &= ~SXSIFLAG_FILEOPENED; + (*sxsi->close)(sxsi); + } + sxsi++; + } +} + +void sxsi_alltrash(void) { + + SXSIDEV sxsi; + SXSIDEV sxsiterm; + + sxsi = sxsi_dev; + sxsiterm = sxsi + NELEMENTS(sxsi_dev); + while(sxsi < sxsiterm) { + sxsi_disconnect(sxsi); + sxsi++; + } +} + +BOOL sxsi_isconnect(SXSIDEV sxsi) { + + if (sxsi) { + switch(sxsi->devtype) { + case SXSIDEV_HDD: + if (sxsi->flag & SXSIFLAG_READY) { + return(TRUE); + } + break; + + case SXSIDEV_CDROM: + return(TRUE); + } + } + return(FALSE); +} + +BRESULT sxsi_prepare(SXSIDEV sxsi) { + + if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY))) { + return(FAILURE); + } + if (!(sxsi->flag & SXSIFLAG_FILEOPENED)) { + if ((*sxsi->reopen)(sxsi) == SUCCESS) { + sxsi->flag |= SXSIFLAG_FILEOPENED; + } + else { + return(FAILURE); + } + } + sysmng_hddaccess(sxsi->drv); + return(SUCCESS); +} + + +// ---- + +SXSIDEV sxsi_getptr(REG8 drv) { + + UINT num; + + num = drv & 0x0f; + if (!(drv & 0x20)) { // SASI or IDE + if (num < SASIHDD_MAX) { + return(sxsi_dev + num); + } + } +#if defined(SUPPORT_SCSI) + else { + if (num < SCSIHDD_MAX) { // SCSI + return(sxsi_dev + SASIHDD_MAX + num); + } + } +#endif + return(NULL); +} + +OEMCHAR *sxsi_getfilename(REG8 drv) { + + SXSIDEV sxsi; + + sxsi = sxsi_getptr(drv); + if ((sxsi) && (sxsi->flag & SXSIFLAG_READY)) { + return(sxsi->fname); + } + return(NULL); +} + +BRESULT sxsi_setdevtype(REG8 drv, UINT8 dev) { + + SXSIDEV sxsi; + + sxsi = sxsi_getptr(drv); + if (sxsi) { + if (sxsi->devtype != dev) { + sxsi_disconnect(sxsi); + sxsi->devtype = dev; + } + return(SUCCESS); + } + else { + return(FAILURE); + } +} + +UINT8 sxsi_getdevtype(REG8 drv) { + + SXSIDEV sxsi; + + sxsi = sxsi_getptr(drv); + if (sxsi) { + return(sxsi->devtype); + } + else { + return(SXSIDEV_NC); + } +} + +// CD入れ替えのタイムアウト(投げやり) +char cdchange_flag = 0; +DWORD cdchange_reqtime = 0; +REG8 cdchange_drv; +OEMCHAR cdchange_fname[MAX_PATH]; +void cdchange_timeoutproc(NEVENTITEM item) { + + if(!cdchange_flag) return; + cdchange_flag = 0; + sxsi_devopen(cdchange_drv, cdchange_fname); +#if defined(SUPPORT_IDEIO) + ideio_mediachange(cdchange_drv); +#endif +#if defined(NP2_WIN) + sysmng_requestupdatecaption(SYS_UPDATECAPTION_FDD); +#endif +} +static void cdchange_timeoutset(void) { + + nevent_setbyms(NEVENT_CDWAIT, 6000, cdchange_timeoutproc, NEVENT_ABSOLUTE); +} + +#ifdef SUPPORT_NVL_IMAGES +BRESULT sxsihdd_nvl_open(SXSIDEV sxsi, const OEMCHAR *fname); +#endif + +BRESULT sxsi_devopen(REG8 drv, const OEMCHAR *fname) { + + SXSIDEV sxsi; + BRESULT r; + + sxsi = sxsi_getptr(drv); + if (sxsi == NULL) { + goto sxsiope_err; + } + switch(sxsi->devtype) { + case SXSIDEV_HDD: + if ((fname == NULL) || (fname[0] == '\0')) { + goto sxsiope_err; + } + r = sxsihdd_open(sxsi, fname); +#ifdef SUPPORT_NVL_IMAGES + if (r == FAILURE) + { + r = sxsihdd_nvl_open(sxsi, fname); + } +#endif + break; + + case SXSIDEV_CDROM: +#if defined(SUPPORT_IDEIO) + if (cdchange_flag) { + // CD交換中 + if(GetTickCount()-cdchange_reqtime>5000){ + // 強制交換 + cdchange_timeoutproc(NULL); + } + return(FAILURE); + } + if ((fname == NULL) || (fname[0] == '\0')) { + int num = drv & 0x03; + if (sxsi->flag & SXSIFLAG_FILEOPENED) { + ideio_notify(sxsi->drv, 0); + (*sxsi->close)(sxsi); + } + if (sxsi->flag & SXSIFLAG_READY) { + (*sxsi->destroy)(sxsi); + } + file_cpyname(sxsi->fname, _T("\0\0\0\0"), 1); + sxsi->flag = 0; + file_cpyname(np2cfg.idecd[num], _T("\0\0\0\0"), 1); + sysmng_updatecaption(1); // SYS_UPDATECAPTION_FDD + return(SUCCESS); + } + else { + if((sxsi->flag & SXSIFLAG_READY) && (_tcsnicmp(sxsi->fname, OEMTEXT("\\\\.\\"), 4)!=0 || _tcsicmp(sxsi->fname, np2cfg.idecd[drv & 0x0f])==0) ){ + // いったん取り出す + if (sxsi->flag & SXSIFLAG_FILEOPENED) { + ideio_notify(sxsi->drv, 0); + (*sxsi->close)(sxsi); + } + if (sxsi->flag & SXSIFLAG_READY) { + (*sxsi->destroy)(sxsi); + } + sxsi->flag = 0; + cdchange_drv = drv; + file_cpyname(sxsi->fname, _T("\0\0\0\0"), 1); + file_cpyname(np2cfg.idecd[drv & 0x03], _T("\0\0\0\0"), NELEMENTS(cdchange_fname)); + file_cpyname(cdchange_fname, fname, NELEMENTS(cdchange_fname)); + cdchange_flag = 1; + cdchange_timeoutset(); + cdchange_reqtime = GetTickCount(); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + return(FAILURE); // XXX: ここで失敗返してええの? + } + r = sxsicd_open(sxsi, fname); + if (r == SUCCESS || _tcsnicmp(fname, OEMTEXT("\\\\.\\"), 4)==0) { + int num = drv & 0x03; + file_cpyname(np2cfg.idecd[num], fname, MAX_PATH); + if(r != SUCCESS && _tcsnicmp(fname, OEMTEXT("\\\\.\\"), 4)==0){ + ideio_notify(sxsi->drv, 0); + } + }else{ + int num = drv & 0x03; + file_cpyname(np2cfg.idecd[num], _T("\0\0\0\0"), 1); + } + sysmng_updatecaption(1); // SYS_UPDATECAPTION_FDD + ideio_mediachange(drv); + } +#endif + break; + + default: + r = FAILURE; + break; + } + if (r != SUCCESS) { + goto sxsiope_err; + } + file_cpyname(sxsi->fname, fname, NELEMENTS(sxsi->fname)); + sxsi->flag = SXSIFLAG_READY | SXSIFLAG_FILEOPENED; +#if defined(SUPPORT_IDEIO) + ideio_notify(sxsi->drv, 1); +#endif + return(SUCCESS); + +sxsiope_err: + return(FAILURE); +} + +void sxsi_devclose(REG8 drv) { + + SXSIDEV sxsi; + + sxsi = sxsi_getptr(drv); + sxsi_disconnect(sxsi); +} + +BOOL sxsi_issasi(void) { + + REG8 drv; + SXSIDEV sxsi; + BOOL ret; + + ret = FALSE; + for (drv=0x00; drv<0x04; drv++) { + sxsi = sxsi_getptr(drv); + if (sxsi) { + if ((drv < 0x02) && (sxsi->devtype == SXSIDEV_HDD)) { + if (sxsi->flag & SXSIFLAG_READY) { + if (sxsi->mediatype & SXSIMEDIA_INVSASI) { + return(FALSE); + } + ret = TRUE; + } + } + else { + return(FALSE); + } + } + } + return(ret); +} + +BOOL sxsi_isscsi(void) { + + REG8 drv; + SXSIDEV sxsi; + + for (drv=0x20; drv<0x28; drv++) { + sxsi = sxsi_getptr(drv); + if (sxsi_isconnect(sxsi)) { + return(TRUE); + } + } + return(FALSE); +} + +BOOL sxsi_iside(void) { + + REG8 drv; + SXSIDEV sxsi; + + for (drv=0x00; drv<0x04; drv++) { + sxsi = sxsi_getptr(drv); + if (sxsi_isconnect(sxsi)) { + return(TRUE); + } + } + return(FALSE); +} + + + +REG8 sxsi_read(REG8 drv, FILEPOS pos, UINT8 *buf, UINT size) { + + SXSIDEV sxsi; + + sxsi = sxsi_getptr(drv); + if (sxsi != NULL) { + return(sxsi->read(sxsi, pos, buf, size)); + } + else { + return(0x60); + } +} + +REG8 sxsi_write(REG8 drv, FILEPOS pos, const UINT8 *buf, UINT size) { + + SXSIDEV sxsi; + + sxsi = sxsi_getptr(drv); + if (sxsi != NULL) { + return(sxsi->write(sxsi, pos, buf, size)); + } + else { + return(0x60); + } +} + +REG8 sxsi_format(REG8 drv, FILEPOS pos) { + + SXSIDEV sxsi; + + sxsi = sxsi_getptr(drv); + if (sxsi != NULL) { + return(sxsi->format(sxsi, pos)); + } + else { + return(0x60); + } +} + +BRESULT sxsi_state_save(const OEMCHAR *ext) { + SXSIDEV sxsi; + SXSIDEV sxsiterm; + + sxsi = sxsi_dev; + sxsiterm = sxsi + NELEMENTS(sxsi_dev); + while(sxsi < sxsiterm) { + if (sxsi->state_save != NULL) { + _SYSTIME st; + OEMCHAR dt[64]; + OEMCHAR sfname[MAX_PATH]; + BRESULT r; + + timemng_gettime(&st); + OEMSNPRINTF(dt, sizeof(dt), + OEMTEXT("%04d%02d%02d%02d%02d%02d%03d"), + st.year, st.month, st.day, + st.hour, st.minute, st.second, + st.milli); + + file_cpyname(sfname, sxsi->fname, NELEMENTS(sfname)); + file_catname(sfname, OEMTEXT("_"), NELEMENTS(sfname)); + file_catname(sfname, ext, NELEMENTS(sfname)); + file_catname(sfname, OEMTEXT("_"), NELEMENTS(sfname)); + file_catname(sfname, dt, NELEMENTS(sfname)); + + r = (*sxsi->state_save)(sxsi, sfname); + if (r != SUCCESS) { + return(r); + } + } + + sxsi++; + } +} + +static int str_get_mem_size(const OEMCHAR *str) +{ + return ((int)((OEMCHAR *)milstr_chr(str, 0) - str)); +} + +static BRESULT state_load(SXSIDEV sxsi, const OEMCHAR *ext) +{ + OEMCHAR dir[MAX_PATH]; + FLINFO fli; + FLISTH flh; + OEMCHAR rname[MAX_PATH]; + int rnamesize; + OEMCHAR tname[MAX_PATH]; + + file_cpyname(dir, sxsi->fname, NELEMENTS(dir)); + file_cutname(dir); + file_cutseparator(dir); + + flh = file_list1st(dir, &fli); + if (flh == FLISTH_INVALID) + { + return (SUCCESS); + } + + file_cpyname(rname, file_getname(sxsi->fname), NELEMENTS(rname)); + file_catname(rname, OEMTEXT("_"), NELEMENTS(rname)); + file_catname(rname, ext, NELEMENTS(rname)); + file_catname(rname, OEMTEXT("_"), NELEMENTS(rname)); + rnamesize = str_get_mem_size(rname); + + ZeroMemory(tname, sizeof(OEMCHAR) * MAX_PATH); + + do + { + int namesize; + + if ((fli.attr & FILEATTR_VOLUME) || + (fli.attr & FILEATTR_DIRECTORY)) + { + continue; + } + + namesize = str_get_mem_size(fli.path); + + if (namesize <= rnamesize) + { + continue; + } + + if (milstr_memcmp(fli.path, rname) != 0) + { + continue; + } + + if (file_cmpname(fli.path, tname) > 0) + { + file_cpyname(tname, fli.path, NELEMENTS(tname)); + } + } while (file_listnext(flh, &fli) == SUCCESS); + + if (OEMSTRLEN(tname) == 0) + { + return (SUCCESS); + } + + file_setseparator(dir, NELEMENTS(dir)); + file_catname(dir, tname, NELEMENTS(dir)); + + return ((*sxsi->state_load)(sxsi, dir)); +} + +BRESULT sxsi_state_load(const OEMCHAR *ext) +{ + SXSIDEV sxsi; + SXSIDEV sxsiterm; + + sxsi = sxsi_dev; + sxsiterm = sxsi + NELEMENTS(sxsi_dev); + while (sxsi < sxsiterm) { + if (sxsi->state_load != NULL) { + BRESULT r; + + r = state_load(sxsi, ext); + if (r != SUCCESS) + { + return(r); + } + } + + sxsi++; + } +} + diff --git a/fdd/sxsi.h b/fdd/sxsi.h old mode 100755 new mode 100644 index 2cb9ed01..93d8eba9 --- a/fdd/sxsi.h +++ b/fdd/sxsi.h @@ -1,115 +1,115 @@ -#ifndef _SXSI_H_ -#define _SXSI_H_ - -#if defined(SUPPORT_SCSI) -enum { - SASIHDD_MAX = 4, - SCSIHDD_MAX = 8 -}; -#else -enum { - SASIHDD_MAX = 4, - SCSIHDD_MAX = 0 -}; -#endif - -enum { - SXSIDRV_UNITMASK = 0x0f, - SXSIDRV_SASI = 0x00, - SXSIDRV_SCSI = 0x20, - SXSIDRV_IFMASK = 0x20, - - SXSIDEV_NC = 0x00, - SXSIDEV_HDD = 0x01, - SXSIDEV_CDROM = 0x02, - SXSIDEV_MO = 0x03, - SXSIDEV_SCANNER = 0x04, - - SXSIFLAG_READY = 0x01, - SXSIFLAG_FILEOPENED = 0x02 -}; - -enum { - CD_ECC_NOERROR = 0, - CD_ECC_RECOVERED = 1, - CD_ECC_ERROR = 2, - CD_ECC_BITMASK = 0x03, -}; - - -struct _sxsidev; -typedef struct _sxsidev _SXSIDEV; -typedef struct _sxsidev *SXSIDEV; - -#include "sxsihdd.h" -#include "sxsicd.h" - -struct _sxsidev { - UINT8 drv; - UINT8 devtype; - UINT8 flag; - UINT8 __caps; - - BRESULT (*reopen)(SXSIDEV sxsi); - REG8 (*read)(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); - REG8 (*write)(SXSIDEV sxsi, FILEPOS pos, const UINT8 *buf, UINT size); - REG8 (*format)(SXSIDEV sxsi, FILEPOS pos); - void (*close)(SXSIDEV sxsi); - void (*destroy)(SXSIDEV sxsi); - BRESULT (*state_save)(SXSIDEV sxsi, const OEMCHAR *sfname); - BRESULT (*state_load)(SXSIDEV sxsi, const OEMCHAR *sfname); - - INTPTR hdl; - FILELEN totals; - UINT16 cylinders; - UINT16 size; - UINT8 sectors; - UINT8 surfaces; - UINT8 mediatype; - UINT8 padding; - UINT32 headersize; - - UINT8 cdflag_ecc; - - OEMCHAR fname[MAX_PATH]; - UINT ftype; -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern _SXSIDEV sxsi_dev[SASIHDD_MAX + SCSIHDD_MAX]; - -#if !defined(_WIN32) -unsigned GetTickCount(); -#endif - -void sxsi_initialize(void); -void sxsi_allflash(void); -void sxsi_alltrash(void); -BOOL sxsi_isconnect(SXSIDEV sxsi); -BRESULT sxsi_prepare(SXSIDEV sxsi); - -SXSIDEV sxsi_getptr(REG8 drv); -OEMCHAR *sxsi_getfilename(REG8 drv); -BRESULT sxsi_setdevtype(REG8 drv, UINT8 dev); -UINT8 sxsi_getdevtype(REG8 drv); -BRESULT sxsi_devopen(REG8 drv, const OEMCHAR *fname); -void sxsi_devclose(REG8 drv); -REG8 sxsi_read(REG8 drv, FILEPOS pos, UINT8 *buf, UINT size); -REG8 sxsi_write(REG8 drv, FILEPOS pos, const UINT8 *buf, UINT size); -REG8 sxsi_format(REG8 drv, FILEPOS pos); -BRESULT sxsi_state_save(const OEMCHAR *ext); -BRESULT sxsi_state_load(const OEMCHAR *ext); - -BOOL sxsi_issasi(void); -BOOL sxsi_isscsi(void); -BOOL sxsi_iside(void); - -#ifdef __cplusplus -} -#endif - -#endif // _SXSI_H_ +#ifndef _SXSI_H_ +#define _SXSI_H_ + +#if defined(SUPPORT_SCSI) +enum { + SASIHDD_MAX = 4, + SCSIHDD_MAX = 8 +}; +#else +enum { + SASIHDD_MAX = 4, + SCSIHDD_MAX = 0 +}; +#endif + +enum { + SXSIDRV_UNITMASK = 0x0f, + SXSIDRV_SASI = 0x00, + SXSIDRV_SCSI = 0x20, + SXSIDRV_IFMASK = 0x20, + + SXSIDEV_NC = 0x00, + SXSIDEV_HDD = 0x01, + SXSIDEV_CDROM = 0x02, + SXSIDEV_MO = 0x03, + SXSIDEV_SCANNER = 0x04, + + SXSIFLAG_READY = 0x01, + SXSIFLAG_FILEOPENED = 0x02 +}; + +enum { + CD_ECC_NOERROR = 0, + CD_ECC_RECOVERED = 1, + CD_ECC_ERROR = 2, + CD_ECC_BITMASK = 0x03, +}; + + +struct _sxsidev; +typedef struct _sxsidev _SXSIDEV; +typedef struct _sxsidev *SXSIDEV; + +#include "sxsihdd.h" +#include "sxsicd.h" + +struct _sxsidev { + UINT8 drv; + UINT8 devtype; + UINT8 flag; + UINT8 __caps; + + BRESULT (*reopen)(SXSIDEV sxsi); + REG8 (*read)(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size); + REG8 (*write)(SXSIDEV sxsi, FILEPOS pos, const UINT8 *buf, UINT size); + REG8 (*format)(SXSIDEV sxsi, FILEPOS pos); + void (*close)(SXSIDEV sxsi); + void (*destroy)(SXSIDEV sxsi); + BRESULT (*state_save)(SXSIDEV sxsi, const OEMCHAR *sfname); + BRESULT (*state_load)(SXSIDEV sxsi, const OEMCHAR *sfname); + + INTPTR hdl; + FILELEN totals; + UINT16 cylinders; + UINT16 size; + UINT8 sectors; + UINT8 surfaces; + UINT8 mediatype; + UINT8 padding; + UINT32 headersize; + + UINT8 cdflag_ecc; + + OEMCHAR fname[MAX_PATH]; + UINT ftype; +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _SXSIDEV sxsi_dev[SASIHDD_MAX + SCSIHDD_MAX]; + +#if !defined(_WIN32) +unsigned GetTickCount(); +#endif + +void sxsi_initialize(void); +void sxsi_allflash(void); +void sxsi_alltrash(void); +BOOL sxsi_isconnect(SXSIDEV sxsi); +BRESULT sxsi_prepare(SXSIDEV sxsi); + +SXSIDEV sxsi_getptr(REG8 drv); +OEMCHAR *sxsi_getfilename(REG8 drv); +BRESULT sxsi_setdevtype(REG8 drv, UINT8 dev); +UINT8 sxsi_getdevtype(REG8 drv); +BRESULT sxsi_devopen(REG8 drv, const OEMCHAR *fname); +void sxsi_devclose(REG8 drv); +REG8 sxsi_read(REG8 drv, FILEPOS pos, UINT8 *buf, UINT size); +REG8 sxsi_write(REG8 drv, FILEPOS pos, const UINT8 *buf, UINT size); +REG8 sxsi_format(REG8 drv, FILEPOS pos); +BRESULT sxsi_state_save(const OEMCHAR *ext); +BRESULT sxsi_state_load(const OEMCHAR *ext); + +BOOL sxsi_issasi(void); +BOOL sxsi_isscsi(void); +BOOL sxsi_iside(void); + +#ifdef __cplusplus +} +#endif + +#endif // _SXSI_H_ diff --git a/fdd/sxsicd.c b/fdd/sxsicd.c old mode 100755 new mode 100644 index 701f419b..d166afed --- a/fdd/sxsicd.c +++ b/fdd/sxsicd.c @@ -1,604 +1,604 @@ -#include -#include -#include -#include -#include -#include - -#ifdef SUPPORT_PHYSICAL_CDDRV - -#include - -#endif - -#ifdef SUPPORT_KAI_IMAGES -#include "diskimage/cddfile.h" -#include "diskimage/cd/cdd_iso.h" -#include "diskimage/cd/cdd_cue.h" -#include "diskimage/cd/cdd_ccd.h" -#include "diskimage/cd/cdd_mds.h" -#include "diskimage/cd/cdd_nrg.h" -#ifdef SUPPORT_PHYSICAL_CDDRV -#include "diskimage/cd/cdd_real.h" -#endif - -BRESULT sxsicd_open(SXSIDEV sxsi, const OEMCHAR *fname) { - - const OEMCHAR *ext; - -#ifdef SUPPORT_PHYSICAL_CDDRV - // XXX: 手抜き判定注意(実CDドライブ) - if(_tcsnicmp(fname, OEMTEXT("\\\\.\\"), 4)==0){ - return(openrealcdd(sxsi, fname)); - } -#endif - - // とりあえず拡張子で判断 - ext = file_getext(fname); - if (!file_cmpname(ext, str_cue)) { // CUEシート(*.cue) - return(opencue(sxsi, fname)); - } - else if (!file_cmpname(ext, str_ccd)) { // CloneCD(*.ccd)に対応 - return(openccd(sxsi, fname)); - } - else if (!file_cmpname(ext, str_cdm)) { // CD Manipulator(*.cdm)に対応(読み方はCloneCDと一緒) - return(openccd(sxsi, fname)); -// return(opencdm(sxsi, fname)); - } - else if (!file_cmpname(ext, str_mds)) { // Media Descriptor(*.mds)に対応 - return(openmds(sxsi, fname)); - } - else if (!file_cmpname(ext, str_nrg)) { // Nero(*.nrg)に対応 - return(opennrg(sxsi, fname)); - } - - return(openiso(sxsi, fname)); // 知らない拡張子なら、とりあえずISOとして開いてみる -} - -CDTRK sxsicd_gettrk(SXSIDEV sxsi, UINT *tracks) { - - CDINFO cdinfo; - - cdinfo = (CDINFO)sxsi->hdl; - if (tracks) { - *tracks = cdinfo->trks; - } - return(cdinfo->trk); -} - -BRESULT sxsicd_readraw(SXSIDEV sxsi, FILEPOS pos, void *buf) { - - CDINFO cdinfo; - FILEH fh; - FILEPOS fpos; - UINT16 secsize = 0; - SINT32 i; - UINT32 secs; -// UINT64 trk_offset; - - int isPhysicalCD = 0; - - // 範囲外は失敗 - if ((pos < 0) || (sxsi->totals < pos)) { - return(FAILURE); - } - - cdinfo = (CDINFO)sxsi->hdl; - -#ifdef SUPPORT_PHYSICAL_CDDRV - - // XXX: 事前に判定して記録しておくべき・・・ - isPhysicalCD = (cdinfo->path[0] == '\\' && cdinfo->path[1] == '\\' && cdinfo->path[2] == '.' && cdinfo->path[3] == '\\'); - -#endif - - if (cdinfo->trks == 0) { - return(FAILURE); - } - - // pos位置のセクタサイズを取得 - for (i = cdinfo->trks - 1; i >= 0; i--) { - if (cdinfo->trk[i].pos <= (UINT32)pos) { - secsize = cdinfo->trk[i].sector_size; - break; - } - } - if (secsize == 0) { - return(FAILURE); - } - if (secsize == 2048 && !isPhysicalCD) { - return(FAILURE); - } - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(FAILURE); - } - - fh = ((CDINFO)sxsi->hdl)->fh; - fpos = 0; - secs = 0; - for (i = 0; i < cdinfo->trks; i++) { - if (cdinfo->trk[i].str_sec <= (UINT32)pos && (UINT32)pos <= cdinfo->trk[i].end_sec) { - fpos += (pos - secs) * cdinfo->trk[i].sector_size; - break; - } - fpos += (FILEPOS)cdinfo->trk[i].sectors * cdinfo->trk[i].sector_size; - secs += cdinfo->trk[i].sectors; - } - fpos += (FILEPOS)(cdinfo->trk[0].start_offset); -#ifdef SUPPORT_PHYSICAL_CDDRV - if(isPhysicalCD){ - DWORD BytesReturned; - RAW_READ_INFO rawReadInfo; - rawReadInfo.TrackMode = CDDA; - rawReadInfo.SectorCount = 1; - rawReadInfo.DiskOffset.QuadPart = fpos; - if (!DeviceIoControl(fh,IOCTL_CDROM_RAW_READ,&rawReadInfo,sizeof(RAW_READ_INFO), buf, 2352, &BytesReturned,0)) { - return(FAILURE); - } - if (BytesReturned != 2352) { - return(FAILURE); - } - }else{ -#endif - if ((file_seek(fh, fpos, FSEEK_SET) != fpos) || - (file_read(fh, buf, 2352) != 2352)) { - return(FAILURE); - } -#ifdef SUPPORT_PHYSICAL_CDDRV - } -#endif - - return(SUCCESS); -} - -UINT sxsicd_readraw_forhash(SXSIDEV sxsi, UINT uSecNo, UINT8 *pu8Buf, UINT* puSize) { - UINT uRes = 0; - CDINFO cdinfo; - FILEH fh; - FILEPOS fpos; - UINT16 secsize; - UINT i; - UINT32 secs; - - if(!pu8Buf || !puSize) { - uRes = 1; - } - if(!uRes) { - cdinfo = (CDINFO)sxsi->hdl; - if(!cdinfo) { - uRes = 2; - } - } -#ifdef SUPPORT_PHYSICAL_CDDRV - if(!uRes) { - if(cdinfo->path[0] == '\\' && cdinfo->path[1] == '\\' && cdinfo->path[2] == '.' && cdinfo->path[3] == '\\') { - uRes = 3; - } - } -#endif - if(!uRes) { - fh = ((CDINFO)sxsi->hdl)->fh; - if(!fh) { - uRes = 5; - } - } - if(!uRes) { - fpos = 0; - secs = 0; - for(i = 0; i < cdinfo->trks; i++) { - if(cdinfo->trk[i].str_sec <= uSecNo && uSecNo <= cdinfo->trk[i].str_sec + cdinfo->trk[i].sectors) { - fpos += (uSecNo - secs) * cdinfo->trk[i].sector_size; - secsize = cdinfo->trk[i].sector_size; - break; - } - fpos += cdinfo->trk[i].sectors * cdinfo->trk[i].sector_size; - secs += cdinfo->trk[i].sectors; - } - fpos += (FILEPOS)(cdinfo->trk[0].start_offset); - if(file_seek(fh, fpos, FSEEK_SET) != fpos) { - uRes = 6; - } - } - if(!uRes) { - *puSize = file_read(fh, pu8Buf, secsize); - } - if(uRes) { - *puSize = 0; - } - - return uRes; -} - -#else /* SUPPORT_KAI_IMAGES */ -// 旧処理もとりあえず残しておく -#include -#include - -static const UINT8 cd001[7] = {0x01,'C','D','0','0','1',0x01}; - -typedef struct { - FILEH fh; - UINT type; - UINT trks; - _CDTRK trk[100]; - OEMCHAR path[MAX_PATH]; -} _CDINFO, *CDINFO; - - -// ---- セクタ2048 - -static int issec2048(FILEH fh) { - - FILEPOS fpos; - UINT8 buf[2048]; - UINT secsize; - UINT fsize; - - fpos = 16 * 2048; - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - goto sec2048_err; - } - if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { - goto sec2048_err; - } - if (memcmp(buf, cd001, 7) != 0) { - goto sec2048_err; - } - secsize = LOADINTELWORD(buf + 128); - if (secsize != 2048) { - goto sec2048_err; - } - fsize = file_getsize(fh); - if ((fsize % 2048) != 0) { - goto sec2048_err; - } - return(fsize / 2048); - -sec2048_err: - return(-1); -} - -static REG8 sec2048_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { - - FILEH fh; - UINT rsize; - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(0x40); - } - pos = pos * 2048; - fh = ((CDINFO)sxsi->hdl)->fh; - if (file_seek(fh, pos, FSEEK_SET) != pos) { - return(0xd0); - } - while(size) { - rsize = MIN(size, 2048); - CPU_REMCLOCK -= rsize; - if (file_read(fh, buf, rsize) != rsize) { - return(0xd0); - } - buf += rsize; - size -= rsize; - } - return(0x00); -} - - -// ---- セクタ2352 - -static int issec2352(FILEH fh) { - - FILEPOS fpos; - UINT8 buf[2048]; - UINT secsize; - UINT fsize; - - fpos = (16 * 2352) + 16; - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - goto sec2352_err; - } - if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { - goto sec2352_err; - } - if (memcmp(buf, cd001, 7) != 0) { - goto sec2352_err; - } - secsize = LOADINTELWORD(buf + 128); - if (secsize != 2048) { - goto sec2352_err; - } - fsize = file_getsize(fh); - if ((fsize % 2352) != 0) { - goto sec2352_err; - } - return(fsize / 2352); - -sec2352_err: - return(-1); -} - -static REG8 sec2352_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { - - FILEH fh; - FILEPOS fpos; - UINT rsize; - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(0x40); - } - fh = ((CDINFO)sxsi->hdl)->fh; - while(size) { - fpos = (pos * 2352) + 16; - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - return(0xd0); - } - rsize = MIN(size, 2048); - CPU_REMCLOCK -= rsize; - if (file_read(fh, buf, rsize) != rsize) { - return(0xd0); - } - buf += rsize; - size -= rsize; - pos++; - } - return(0x00); -} - - -// ---- - -static BRESULT cd_reopen(SXSIDEV sxsi) { - - CDINFO cdinfo; - FILEH fh; - - cdinfo = (CDINFO)sxsi->hdl; - fh = file_open_rb(cdinfo->path); - if (fh != FILEH_INVALID) { - cdinfo->fh = fh; - return(SUCCESS); - } - else { - return(FAILURE); - } -} - -static void cd_close(SXSIDEV sxsi) { - - CDINFO cdinfo; - - cdinfo = (CDINFO)sxsi->hdl; - file_close(cdinfo->fh); -} - -static void cd_destroy(SXSIDEV sxsi) { - - if(sxsi->hdl){ - _MFREE((CDINFO)sxsi->hdl); - sxsi->hdl = NULL; - } -} - - -// ---- - -static const OEMCHAR str_cue[] = OEMTEXT("cue"); -static const OEMCHAR str_file[] = OEMTEXT("FILE"); -static const OEMCHAR str_track[] = OEMTEXT("TRACK"); -static const OEMCHAR str_mode1[] = OEMTEXT("MODE1/2352"); -static const OEMCHAR str_index[] = OEMTEXT("INDEX"); -static const OEMCHAR str_audio[] = OEMTEXT("AUDIO"); - - -static BRESULT openimg(SXSIDEV sxsi, const OEMCHAR *path, - const _CDTRK *trk, UINT trks) { - - FILEH fh; - UINT type; - FILEPOS totals; - CDINFO cdinfo; - UINT mediatype; - UINT i; - - fh = file_open_rb(path); - if (fh == FILEH_INVALID) { - goto sxsiope_err1; - } - type = 2048; - totals = issec2048(fh); - if (totals < 0) { - type = 2352; - totals = issec2352(fh); - } - if (totals < 0) { - goto sxsiope_err2; - } - cdinfo = (CDINFO)_MALLOC(sizeof(_CDINFO), path); - if (cdinfo == NULL) { - goto sxsiope_err2; - } - ZeroMemory(cdinfo, sizeof(_CDINFO)); - cdinfo->fh = fh; - cdinfo->type = type; - if ((trk != NULL) && (trks != 0)) { - trks = MIN(trks, NELEMENTS(cdinfo->trk) - 1); - CopyMemory(cdinfo->trk, trk, trks * sizeof(_CDTRK)); - } - else { - cdinfo->trk[0].type = 0x14; - cdinfo->trk[0].track = 1; -// cdinfo->trk[0].pos = 0; - trks = 1; - } - mediatype = 0; - for (i=0; itrk[i].type == 0x14) { - mediatype |= SXSIMEDIA_DATA; - } - else if (cdinfo->trk[i].type == 0x10) { - mediatype |= SXSIMEDIA_AUDIO; - } - } - cdinfo->trk[trks].type = 0x10; - cdinfo->trk[trks].track = 0xaa; - cdinfo->trk[trks].pos = totals; - cdinfo->trks = trks; - file_cpyname(cdinfo->path, path, NELEMENTS(cdinfo->path)); - - sxsi->reopen = cd_reopen; - if (type == 2048) { - sxsi->read = sec2048_read; - } - else { - sxsi->read = sec2352_read; - } - sxsi->close = cd_close; - sxsi->destroy = cd_destroy; - sxsi->hdl = (INTPTR)cdinfo; - sxsi->totals = totals; - sxsi->cylinders = 0; - sxsi->size = 2048; - sxsi->sectors = 1; - sxsi->surfaces = 1; - sxsi->headersize = 0; - sxsi->mediatype = mediatype; - return(SUCCESS); - -sxsiope_err2: - file_close(fh); - -sxsiope_err1: - return(FAILURE); -} - -static BRESULT getint2(const OEMCHAR *str, UINT *val) { - - if ((str[0] < '0') || (str[0] > '9') || - (str[1] < '0') || (str[1] > '9')) { - return(FAILURE); - } - if (val) { - *val = ((str[0] - '0') * 10) + (str[1] - '0'); - } - return(SUCCESS); -} - -static UINT32 getpos(const OEMCHAR *str) { - - UINT m; - UINT s; - UINT f; - - if ((getint2(str + 0, &m) != SUCCESS) || (str[2] != ':') || - (getint2(str + 3, &s) != SUCCESS) || (str[5] != ':') || - (getint2(str + 6, &f) != SUCCESS)) { - return(0); - } - return((((m * 60) + s) * 75) + f); -} - -static BRESULT opencue(SXSIDEV sxsi, const OEMCHAR *fname) { - - _CDTRK trk[99]; - OEMCHAR path[MAX_PATH]; - UINT idx; - UINT8 curtrk; - UINT curtype; - TEXTFILEH tfh; - OEMCHAR buf[512]; - OEMCHAR *argv[8]; - int argc; - - ZeroMemory(trk, sizeof(trk)); - path[0] = '\0'; - idx = 0; - curtrk = 1; - curtype = 0x14; - tfh = textfile_open(fname, 0x800); - if (tfh == NULL) { - return(FAILURE); - } - while(textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) { - argc = milstr_getarg(buf, argv, NELEMENTS(argv)); - if ((argc >= 3) && (!milstr_cmp(argv[0], str_file))) { - file_cpyname(path, fname, NELEMENTS(path)); - file_cutname(path); - file_catname(path, argv[1], NELEMENTS(path)); - } - else if ((argc >= 3) && (!milstr_cmp(argv[0], str_track))) { - curtrk = (UINT8)milstr_solveINT(argv[1]); - if (!milstr_cmp(argv[2], str_mode1)) { - curtype = 0x14; - } - else if (!milstr_cmp(argv[2], str_audio)) { - curtype = 0x10; - } - } - else if ((argc >= 3) && (!milstr_cmp(argv[0], str_index))) { - if (idx < NELEMENTS(trk)) { - trk[idx].type = curtype; - trk[idx].track = curtrk; - trk[idx].pos = getpos(argv[2]); - idx++; - } - } - } - textfile_close(tfh); - return(openimg(sxsi, path, trk, idx)); -} - -BRESULT sxsicd_open(SXSIDEV sxsi, const OEMCHAR *fname) { - -const OEMCHAR *ext; - - ext = file_getext(fname); - if (!file_cmpname(ext, str_cue)) { - return(opencue(sxsi, fname)); - } - return(openimg(sxsi, fname, NULL, 0)); -} - -CDTRK sxsicd_gettrk(SXSIDEV sxsi, UINT *tracks) { - - CDINFO cdinfo; - - cdinfo = (CDINFO)sxsi->hdl; - if (tracks) { - *tracks = cdinfo->trks; - } - return(cdinfo->trk); -} - -BRESULT sxsicd_readraw(SXSIDEV sxsi, FILEPOS pos, void *buf) { - - CDINFO cdinfo; - FILEH fh; - FILEPOS fpos; - - cdinfo = (CDINFO)sxsi->hdl; - if (cdinfo->type != 2352) { - return(FAILURE); - } - if (sxsi_prepare(sxsi) != SUCCESS) { - return(FAILURE); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(FAILURE); - } - fh = ((CDINFO)sxsi->hdl)->fh; - fpos = pos * 2352; - if ((file_seek(fh, fpos, FSEEK_SET) != fpos) || - (file_read(fh, buf, 2352) != 2352)) { - return(FAILURE); - } - return(SUCCESS); -} - -#endif /* SUPPORT_KAI_IMAGES */ +#include +#include +#include +#include +#include +#include + +#ifdef SUPPORT_PHYSICAL_CDDRV + +#include + +#endif + +#ifdef SUPPORT_KAI_IMAGES +#include "diskimage/cddfile.h" +#include "diskimage/cd/cdd_iso.h" +#include "diskimage/cd/cdd_cue.h" +#include "diskimage/cd/cdd_ccd.h" +#include "diskimage/cd/cdd_mds.h" +#include "diskimage/cd/cdd_nrg.h" +#ifdef SUPPORT_PHYSICAL_CDDRV +#include "diskimage/cd/cdd_real.h" +#endif + +BRESULT sxsicd_open(SXSIDEV sxsi, const OEMCHAR *fname) { + + const OEMCHAR *ext; + +#ifdef SUPPORT_PHYSICAL_CDDRV + // XXX: 手抜き判定注意(実CDドライブ) + if(_tcsnicmp(fname, OEMTEXT("\\\\.\\"), 4)==0){ + return(openrealcdd(sxsi, fname)); + } +#endif + + // とりあえず拡張子で判断 + ext = file_getext(fname); + if (!file_cmpname(ext, str_cue)) { // CUEシート(*.cue) + return(opencue(sxsi, fname)); + } + else if (!file_cmpname(ext, str_ccd)) { // CloneCD(*.ccd)に対応 + return(openccd(sxsi, fname)); + } + else if (!file_cmpname(ext, str_cdm)) { // CD Manipulator(*.cdm)に対応(読み方はCloneCDと一緒) + return(openccd(sxsi, fname)); +// return(opencdm(sxsi, fname)); + } + else if (!file_cmpname(ext, str_mds)) { // Media Descriptor(*.mds)に対応 + return(openmds(sxsi, fname)); + } + else if (!file_cmpname(ext, str_nrg)) { // Nero(*.nrg)に対応 + return(opennrg(sxsi, fname)); + } + + return(openiso(sxsi, fname)); // 知らない拡張子なら、とりあえずISOとして開いてみる +} + +CDTRK sxsicd_gettrk(SXSIDEV sxsi, UINT *tracks) { + + CDINFO cdinfo; + + cdinfo = (CDINFO)sxsi->hdl; + if (tracks) { + *tracks = cdinfo->trks; + } + return(cdinfo->trk); +} + +BRESULT sxsicd_readraw(SXSIDEV sxsi, FILEPOS pos, void *buf) { + + CDINFO cdinfo; + FILEH fh; + FILEPOS fpos; + UINT16 secsize = 0; + SINT32 i; + UINT32 secs; +// UINT64 trk_offset; + + int isPhysicalCD = 0; + + // 範囲外は失敗 + if ((pos < 0) || (sxsi->totals < pos)) { + return(FAILURE); + } + + cdinfo = (CDINFO)sxsi->hdl; + +#ifdef SUPPORT_PHYSICAL_CDDRV + + // XXX: 事前に判定して記録しておくべき・・・ + isPhysicalCD = (cdinfo->path[0] == '\\' && cdinfo->path[1] == '\\' && cdinfo->path[2] == '.' && cdinfo->path[3] == '\\'); + +#endif + + if (cdinfo->trks == 0) { + return(FAILURE); + } + + // pos位置のセクタサイズを取得 + for (i = cdinfo->trks - 1; i >= 0; i--) { + if (cdinfo->trk[i].pos <= (UINT32)pos) { + secsize = cdinfo->trk[i].sector_size; + break; + } + } + if (secsize == 0) { + return(FAILURE); + } + if (secsize == 2048 && !isPhysicalCD) { + return(FAILURE); + } + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(FAILURE); + } + + fh = ((CDINFO)sxsi->hdl)->fh; + fpos = 0; + secs = 0; + for (i = 0; i < cdinfo->trks; i++) { + if (cdinfo->trk[i].str_sec <= (UINT32)pos && (UINT32)pos <= cdinfo->trk[i].end_sec) { + fpos += (pos - secs) * cdinfo->trk[i].sector_size; + break; + } + fpos += (FILEPOS)cdinfo->trk[i].sectors * cdinfo->trk[i].sector_size; + secs += cdinfo->trk[i].sectors; + } + fpos += (FILEPOS)(cdinfo->trk[0].start_offset); +#ifdef SUPPORT_PHYSICAL_CDDRV + if(isPhysicalCD){ + DWORD BytesReturned; + RAW_READ_INFO rawReadInfo; + rawReadInfo.TrackMode = CDDA; + rawReadInfo.SectorCount = 1; + rawReadInfo.DiskOffset.QuadPart = fpos; + if (!DeviceIoControl(fh,IOCTL_CDROM_RAW_READ,&rawReadInfo,sizeof(RAW_READ_INFO), buf, 2352, &BytesReturned,0)) { + return(FAILURE); + } + if (BytesReturned != 2352) { + return(FAILURE); + } + }else{ +#endif + if ((file_seek(fh, fpos, FSEEK_SET) != fpos) || + (file_read(fh, buf, 2352) != 2352)) { + return(FAILURE); + } +#ifdef SUPPORT_PHYSICAL_CDDRV + } +#endif + + return(SUCCESS); +} + +UINT sxsicd_readraw_forhash(SXSIDEV sxsi, UINT uSecNo, UINT8 *pu8Buf, UINT* puSize) { + UINT uRes = 0; + CDINFO cdinfo; + FILEH fh; + FILEPOS fpos; + UINT16 secsize; + UINT i; + UINT32 secs; + + if(!pu8Buf || !puSize) { + uRes = 1; + } + if(!uRes) { + cdinfo = (CDINFO)sxsi->hdl; + if(!cdinfo) { + uRes = 2; + } + } +#ifdef SUPPORT_PHYSICAL_CDDRV + if(!uRes) { + if(cdinfo->path[0] == '\\' && cdinfo->path[1] == '\\' && cdinfo->path[2] == '.' && cdinfo->path[3] == '\\') { + uRes = 3; + } + } +#endif + if(!uRes) { + fh = ((CDINFO)sxsi->hdl)->fh; + if(!fh) { + uRes = 5; + } + } + if(!uRes) { + fpos = 0; + secs = 0; + for(i = 0; i < cdinfo->trks; i++) { + if(cdinfo->trk[i].str_sec <= uSecNo && uSecNo <= cdinfo->trk[i].str_sec + cdinfo->trk[i].sectors) { + fpos += (uSecNo - secs) * cdinfo->trk[i].sector_size; + secsize = cdinfo->trk[i].sector_size; + break; + } + fpos += cdinfo->trk[i].sectors * cdinfo->trk[i].sector_size; + secs += cdinfo->trk[i].sectors; + } + fpos += (FILEPOS)(cdinfo->trk[0].start_offset); + if(file_seek(fh, fpos, FSEEK_SET) != fpos) { + uRes = 6; + } + } + if(!uRes) { + *puSize = file_read(fh, pu8Buf, secsize); + } + if(uRes) { + *puSize = 0; + } + + return uRes; +} + +#else /* SUPPORT_KAI_IMAGES */ +// 旧処理もとりあえず残しておく +#include +#include + +static const UINT8 cd001[7] = {0x01,'C','D','0','0','1',0x01}; + +typedef struct { + FILEH fh; + UINT type; + UINT trks; + _CDTRK trk[100]; + OEMCHAR path[MAX_PATH]; +} _CDINFO, *CDINFO; + + +// ---- セクタ2048 + +static int issec2048(FILEH fh) { + + FILEPOS fpos; + UINT8 buf[2048]; + UINT secsize; + UINT fsize; + + fpos = 16 * 2048; + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + goto sec2048_err; + } + if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { + goto sec2048_err; + } + if (memcmp(buf, cd001, 7) != 0) { + goto sec2048_err; + } + secsize = LOADINTELWORD(buf + 128); + if (secsize != 2048) { + goto sec2048_err; + } + fsize = file_getsize(fh); + if ((fsize % 2048) != 0) { + goto sec2048_err; + } + return(fsize / 2048); + +sec2048_err: + return(-1); +} + +static REG8 sec2048_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { + + FILEH fh; + UINT rsize; + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(0x40); + } + pos = pos * 2048; + fh = ((CDINFO)sxsi->hdl)->fh; + if (file_seek(fh, pos, FSEEK_SET) != pos) { + return(0xd0); + } + while(size) { + rsize = MIN(size, 2048); + CPU_REMCLOCK -= rsize; + if (file_read(fh, buf, rsize) != rsize) { + return(0xd0); + } + buf += rsize; + size -= rsize; + } + return(0x00); +} + + +// ---- セクタ2352 + +static int issec2352(FILEH fh) { + + FILEPOS fpos; + UINT8 buf[2048]; + UINT secsize; + UINT fsize; + + fpos = (16 * 2352) + 16; + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + goto sec2352_err; + } + if (file_read(fh, buf, sizeof(buf)) != sizeof(buf)) { + goto sec2352_err; + } + if (memcmp(buf, cd001, 7) != 0) { + goto sec2352_err; + } + secsize = LOADINTELWORD(buf + 128); + if (secsize != 2048) { + goto sec2352_err; + } + fsize = file_getsize(fh); + if ((fsize % 2352) != 0) { + goto sec2352_err; + } + return(fsize / 2352); + +sec2352_err: + return(-1); +} + +static REG8 sec2352_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { + + FILEH fh; + FILEPOS fpos; + UINT rsize; + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(0x40); + } + fh = ((CDINFO)sxsi->hdl)->fh; + while(size) { + fpos = (pos * 2352) + 16; + if (file_seek(fh, fpos, FSEEK_SET) != fpos) { + return(0xd0); + } + rsize = MIN(size, 2048); + CPU_REMCLOCK -= rsize; + if (file_read(fh, buf, rsize) != rsize) { + return(0xd0); + } + buf += rsize; + size -= rsize; + pos++; + } + return(0x00); +} + + +// ---- + +static BRESULT cd_reopen(SXSIDEV sxsi) { + + CDINFO cdinfo; + FILEH fh; + + cdinfo = (CDINFO)sxsi->hdl; + fh = file_open_rb(cdinfo->path); + if (fh != FILEH_INVALID) { + cdinfo->fh = fh; + return(SUCCESS); + } + else { + return(FAILURE); + } +} + +static void cd_close(SXSIDEV sxsi) { + + CDINFO cdinfo; + + cdinfo = (CDINFO)sxsi->hdl; + file_close(cdinfo->fh); +} + +static void cd_destroy(SXSIDEV sxsi) { + + if(sxsi->hdl){ + _MFREE((CDINFO)sxsi->hdl); + sxsi->hdl = NULL; + } +} + + +// ---- + +static const OEMCHAR str_cue[] = OEMTEXT("cue"); +static const OEMCHAR str_file[] = OEMTEXT("FILE"); +static const OEMCHAR str_track[] = OEMTEXT("TRACK"); +static const OEMCHAR str_mode1[] = OEMTEXT("MODE1/2352"); +static const OEMCHAR str_index[] = OEMTEXT("INDEX"); +static const OEMCHAR str_audio[] = OEMTEXT("AUDIO"); + + +static BRESULT openimg(SXSIDEV sxsi, const OEMCHAR *path, + const _CDTRK *trk, UINT trks) { + + FILEH fh; + UINT type; + FILEPOS totals; + CDINFO cdinfo; + UINT mediatype; + UINT i; + + fh = file_open_rb(path); + if (fh == FILEH_INVALID) { + goto sxsiope_err1; + } + type = 2048; + totals = issec2048(fh); + if (totals < 0) { + type = 2352; + totals = issec2352(fh); + } + if (totals < 0) { + goto sxsiope_err2; + } + cdinfo = (CDINFO)_MALLOC(sizeof(_CDINFO), path); + if (cdinfo == NULL) { + goto sxsiope_err2; + } + ZeroMemory(cdinfo, sizeof(_CDINFO)); + cdinfo->fh = fh; + cdinfo->type = type; + if ((trk != NULL) && (trks != 0)) { + trks = MIN(trks, NELEMENTS(cdinfo->trk) - 1); + CopyMemory(cdinfo->trk, trk, trks * sizeof(_CDTRK)); + } + else { + cdinfo->trk[0].type = 0x14; + cdinfo->trk[0].track = 1; +// cdinfo->trk[0].pos = 0; + trks = 1; + } + mediatype = 0; + for (i=0; itrk[i].type == 0x14) { + mediatype |= SXSIMEDIA_DATA; + } + else if (cdinfo->trk[i].type == 0x10) { + mediatype |= SXSIMEDIA_AUDIO; + } + } + cdinfo->trk[trks].type = 0x10; + cdinfo->trk[trks].track = 0xaa; + cdinfo->trk[trks].pos = totals; + cdinfo->trks = trks; + file_cpyname(cdinfo->path, path, NELEMENTS(cdinfo->path)); + + sxsi->reopen = cd_reopen; + if (type == 2048) { + sxsi->read = sec2048_read; + } + else { + sxsi->read = sec2352_read; + } + sxsi->close = cd_close; + sxsi->destroy = cd_destroy; + sxsi->hdl = (INTPTR)cdinfo; + sxsi->totals = totals; + sxsi->cylinders = 0; + sxsi->size = 2048; + sxsi->sectors = 1; + sxsi->surfaces = 1; + sxsi->headersize = 0; + sxsi->mediatype = mediatype; + return(SUCCESS); + +sxsiope_err2: + file_close(fh); + +sxsiope_err1: + return(FAILURE); +} + +static BRESULT getint2(const OEMCHAR *str, UINT *val) { + + if ((str[0] < '0') || (str[0] > '9') || + (str[1] < '0') || (str[1] > '9')) { + return(FAILURE); + } + if (val) { + *val = ((str[0] - '0') * 10) + (str[1] - '0'); + } + return(SUCCESS); +} + +static UINT32 getpos(const OEMCHAR *str) { + + UINT m; + UINT s; + UINT f; + + if ((getint2(str + 0, &m) != SUCCESS) || (str[2] != ':') || + (getint2(str + 3, &s) != SUCCESS) || (str[5] != ':') || + (getint2(str + 6, &f) != SUCCESS)) { + return(0); + } + return((((m * 60) + s) * 75) + f); +} + +static BRESULT opencue(SXSIDEV sxsi, const OEMCHAR *fname) { + + _CDTRK trk[99]; + OEMCHAR path[MAX_PATH]; + UINT idx; + UINT8 curtrk; + UINT curtype; + TEXTFILEH tfh; + OEMCHAR buf[512]; + OEMCHAR *argv[8]; + int argc; + + ZeroMemory(trk, sizeof(trk)); + path[0] = '\0'; + idx = 0; + curtrk = 1; + curtype = 0x14; + tfh = textfile_open(fname, 0x800); + if (tfh == NULL) { + return(FAILURE); + } + while(textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) { + argc = milstr_getarg(buf, argv, NELEMENTS(argv)); + if ((argc >= 3) && (!milstr_cmp(argv[0], str_file))) { + file_cpyname(path, fname, NELEMENTS(path)); + file_cutname(path); + file_catname(path, argv[1], NELEMENTS(path)); + } + else if ((argc >= 3) && (!milstr_cmp(argv[0], str_track))) { + curtrk = (UINT8)milstr_solveINT(argv[1]); + if (!milstr_cmp(argv[2], str_mode1)) { + curtype = 0x14; + } + else if (!milstr_cmp(argv[2], str_audio)) { + curtype = 0x10; + } + } + else if ((argc >= 3) && (!milstr_cmp(argv[0], str_index))) { + if (idx < NELEMENTS(trk)) { + trk[idx].type = curtype; + trk[idx].track = curtrk; + trk[idx].pos = getpos(argv[2]); + idx++; + } + } + } + textfile_close(tfh); + return(openimg(sxsi, path, trk, idx)); +} + +BRESULT sxsicd_open(SXSIDEV sxsi, const OEMCHAR *fname) { + +const OEMCHAR *ext; + + ext = file_getext(fname); + if (!file_cmpname(ext, str_cue)) { + return(opencue(sxsi, fname)); + } + return(openimg(sxsi, fname, NULL, 0)); +} + +CDTRK sxsicd_gettrk(SXSIDEV sxsi, UINT *tracks) { + + CDINFO cdinfo; + + cdinfo = (CDINFO)sxsi->hdl; + if (tracks) { + *tracks = cdinfo->trks; + } + return(cdinfo->trk); +} + +BRESULT sxsicd_readraw(SXSIDEV sxsi, FILEPOS pos, void *buf) { + + CDINFO cdinfo; + FILEH fh; + FILEPOS fpos; + + cdinfo = (CDINFO)sxsi->hdl; + if (cdinfo->type != 2352) { + return(FAILURE); + } + if (sxsi_prepare(sxsi) != SUCCESS) { + return(FAILURE); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(FAILURE); + } + fh = ((CDINFO)sxsi->hdl)->fh; + fpos = pos * 2352; + if ((file_seek(fh, fpos, FSEEK_SET) != fpos) || + (file_read(fh, buf, 2352) != 2352)) { + return(FAILURE); + } + return(SUCCESS); +} + +#endif /* SUPPORT_KAI_IMAGES */ diff --git a/fdd/sxsicd.h b/fdd/sxsicd.h old mode 100755 new mode 100644 index 7754d42a..487d224e --- a/fdd/sxsicd.h +++ b/fdd/sxsicd.h @@ -1,178 +1,178 @@ -#ifndef _SXSICD_H_ -#define _SXSICD_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - SXSIMEDIA_DATA = 0x10, - SXSIMEDIA_AUDIO = 0x20 -}; - -#ifdef SUPPORT_KAI_IMAGES - -// WinDDKの構造体の名前と被っちゃったので TRACK -> TRACKTYPE に変更 np21w ver0.86 rev33 -#define TRACKTYPE_DATA 0x14 -#define TRACKTYPE_AUDIO 0x10 - -typedef struct { - UINT8 adr_ctl; // Adr/Ctl - // ISO:0x14 - // CUE:MODE1=0x14、MODE2=0x14、AUDIO=0x10 - // CCD: - // CDM: - // MDS:MDS_TrackBlock.adr_ctl - UINT8 point; // Track Number - // ISO:1 - // CUE:TRACK ??=?? - // CCD: - // CDM: - // MDS:MDS_TrackBlock.point - UINT32 pos; // トラックのイメージファイル内での開始セクタ位置 - // ISO:0 - // CUE:INDEX 1 - // CCD: - // CDM: - // MDS:((MDS_TrackBlock.min * 60) + MDS_TrackBlock.sec) * 75 + MDS_TrackBlock.frame -// -------- - UINT32 pos0; // CUEシートの"INDEX 00"等で指定されたPREGAPのイメージ内での開始セクタ位置 - // ISO:0 - // CUE:INDEX 0 - // CCD: - // CDM: - // MDS:0 - UINT32 str_sec; // トラックのイメージファイル上での開始セクタ位置 - // ISO: - // CUE: - // CCD: - // CDM: - // MDS: - UINT32 end_sec; // トラックのイメージファイル上での終了セクタ位置 - // ISO: - // CUE: - // CCD: - // CDM: - // MDS: - UINT32 sectors; // トラックのイメージファイル上でのセクタ数 - // ISO: - // CUE: - // CCD: - // CDM: - // MDS: -// -------- - UINT16 sector_size; // トラックのセクタサイズ - // ISO:2048 or 2352 or 2448(ファイルサイズを割って余りの出ない数値) - // CUE:MODE1/????=????、MODE2/????=????、AUDIO=2352 - // CCD:2352(固定で正しい?) - // CDM:2352(固定で正しい?) - // MDS:MDS_TrackBlock.sector_size - // NRG:NRG_DAO_Block.sector_size - - // CD上の各セクタ開始位置 - // ※イメージファイル上のPREGAPの扱いによって後述のイメージファイル上の各セクタ開始位置と - //  ずれた値になることもある - UINT32 pregap_sector; // トラックのPREGAP開始セクタ位置 - // ※PREGAPが無い場合やPREGAPの実体が無い場合は - //  トラックのstart_sectorと同じ値 - // ISO:0 - // CUE: - // CCD: - // CDM: - // MDS:start_sector - pregap_sectors - UINT32 start_sector; // トラックの開始セクタ位置 - // ISO:0 - // CUE: - // CCD: - // CDM: - // MDS:MDS_TrackBlock.start_sector(リトルエンディアン) - UINT32 end_sector; // トラックの終了セクタ位置 - // ISO:track_sectors - 1 - // CUE: - // CCD: - // CDM: - // MDS:start_sector + track_sectors - 1 - - // イメージファイル上の各セクタ開始位置 - UINT32 img_pregap_sec; // トラックのPREGAP開始セクタ位置 - // ※PREGAPが無い場合やPREGAPの実体が無い場合は - //  トラックのstart_sectorと同じ値 - // ISO:0 - // CUE: - // CCD: - // CDM: - // MDS: - UINT32 img_start_sec; // トラックの開始セクタ位置 - // ISO:0 - // CUE: - // CCD: - // CDM: - // MDS: - UINT32 img_end_sec; // トラックの終了セクタ位置 - // ISO:track_sectors - 1 - // CUE: - // CCD: - // CDM: - // MDS: - - // 各セクタ開始位置のイメージファイル上でのoffset - UINT64 pregap_offset; // イメージファイル上のトラックのPREGAPのoffset - // ※通常は前トラックのend_offsetと同じ値 - // ※PREGAPが無い場合やPREGAPの実体が無い場合は - //  start_offsetと同じ値 - // ISO:0 - // CUE: - // CCD: - // CDM: - // MDS:start_offset - UINT64 start_offset; // イメージファイル上のトラック開始位置のoffset - // ※PREGAPが無い場合やPREGAPの実体が無い場合は - //  前トラックのend_offsetと同じ値 - // ISO:0 - // CUE: - // CCD: - // CDM: - // MDS:MDS_TrackBlock.start_offset(リトルエンディアン) - UINT64 end_offset; // イメージファイル上のトラック終了位置のoffset - // ISO:track_sectors * sector_size - // CUE: - // CCD: - // CDM: - // MDS:start_offset + (track_sectors * sector_size) - - UINT32 pregap_sectors; // トラックのPREGAPのセクタ数 - // ISO:0 - // CUE:PREGAP - // CCD: - // CDM: - // MDS:MDS_TrackExtraBlock.pregap(リトルエンディアン) - UINT32 track_sectors; // トラックのセクタ数 - // ISO:ファイルサイズ / sector_size - // CUE: - // CCD: - // CDM: - // MDS:MDS_TrackExtraBlock.length(リトルエンディアン) -// -------- -} _CDTRK, *CDTRK; - -#else -typedef struct { - UINT8 type; - UINT8 track; - FILEPOS pos; -} _CDTRK, *CDTRK; - -#endif - -BRESULT sxsicd_open(SXSIDEV sxsi, const OEMCHAR *fname); - -CDTRK sxsicd_gettrk(SXSIDEV sxsi, UINT *tracks); -BRESULT sxsicd_readraw(SXSIDEV sxsi, FILEPOS pos, void *buf); -UINT sxsicd_readraw_forhash(SXSIDEV sxsi, UINT uSecNo, UINT8 *pu8Buf, UINT* puSize); - -#ifdef __cplusplus -} -#endif - -#endif // _SXSICD_H_ - +#ifndef _SXSICD_H_ +#define _SXSICD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + SXSIMEDIA_DATA = 0x10, + SXSIMEDIA_AUDIO = 0x20 +}; + +#ifdef SUPPORT_KAI_IMAGES + +// WinDDKの構造体の名前と被っちゃったので TRACK -> TRACKTYPE に変更 np21w ver0.86 rev33 +#define TRACKTYPE_DATA 0x14 +#define TRACKTYPE_AUDIO 0x10 + +typedef struct { + UINT8 adr_ctl; // Adr/Ctl + // ISO:0x14 + // CUE:MODE1=0x14、MODE2=0x14、AUDIO=0x10 + // CCD: + // CDM: + // MDS:MDS_TrackBlock.adr_ctl + UINT8 point; // Track Number + // ISO:1 + // CUE:TRACK ??=?? + // CCD: + // CDM: + // MDS:MDS_TrackBlock.point + UINT32 pos; // トラックのイメージファイル内での開始セクタ位置 + // ISO:0 + // CUE:INDEX 1 + // CCD: + // CDM: + // MDS:((MDS_TrackBlock.min * 60) + MDS_TrackBlock.sec) * 75 + MDS_TrackBlock.frame +// -------- + UINT32 pos0; // CUEシートの"INDEX 00"等で指定されたPREGAPのイメージ内での開始セクタ位置 + // ISO:0 + // CUE:INDEX 0 + // CCD: + // CDM: + // MDS:0 + UINT32 str_sec; // トラックのイメージファイル上での開始セクタ位置 + // ISO: + // CUE: + // CCD: + // CDM: + // MDS: + UINT32 end_sec; // トラックのイメージファイル上での終了セクタ位置 + // ISO: + // CUE: + // CCD: + // CDM: + // MDS: + UINT32 sectors; // トラックのイメージファイル上でのセクタ数 + // ISO: + // CUE: + // CCD: + // CDM: + // MDS: +// -------- + UINT16 sector_size; // トラックのセクタサイズ + // ISO:2048 or 2352 or 2448(ファイルサイズを割って余りの出ない数値) + // CUE:MODE1/????=????、MODE2/????=????、AUDIO=2352 + // CCD:2352(固定で正しい?) + // CDM:2352(固定で正しい?) + // MDS:MDS_TrackBlock.sector_size + // NRG:NRG_DAO_Block.sector_size + + // CD上の各セクタ開始位置 + // ※イメージファイル上のPREGAPの扱いによって後述のイメージファイル上の各セクタ開始位置と + //  ずれた値になることもある + UINT32 pregap_sector; // トラックのPREGAP開始セクタ位置 + // ※PREGAPが無い場合やPREGAPの実体が無い場合は + //  トラックのstart_sectorと同じ値 + // ISO:0 + // CUE: + // CCD: + // CDM: + // MDS:start_sector - pregap_sectors + UINT32 start_sector; // トラックの開始セクタ位置 + // ISO:0 + // CUE: + // CCD: + // CDM: + // MDS:MDS_TrackBlock.start_sector(リトルエンディアン) + UINT32 end_sector; // トラックの終了セクタ位置 + // ISO:track_sectors - 1 + // CUE: + // CCD: + // CDM: + // MDS:start_sector + track_sectors - 1 + + // イメージファイル上の各セクタ開始位置 + UINT32 img_pregap_sec; // トラックのPREGAP開始セクタ位置 + // ※PREGAPが無い場合やPREGAPの実体が無い場合は + //  トラックのstart_sectorと同じ値 + // ISO:0 + // CUE: + // CCD: + // CDM: + // MDS: + UINT32 img_start_sec; // トラックの開始セクタ位置 + // ISO:0 + // CUE: + // CCD: + // CDM: + // MDS: + UINT32 img_end_sec; // トラックの終了セクタ位置 + // ISO:track_sectors - 1 + // CUE: + // CCD: + // CDM: + // MDS: + + // 各セクタ開始位置のイメージファイル上でのoffset + UINT64 pregap_offset; // イメージファイル上のトラックのPREGAPのoffset + // ※通常は前トラックのend_offsetと同じ値 + // ※PREGAPが無い場合やPREGAPの実体が無い場合は + //  start_offsetと同じ値 + // ISO:0 + // CUE: + // CCD: + // CDM: + // MDS:start_offset + UINT64 start_offset; // イメージファイル上のトラック開始位置のoffset + // ※PREGAPが無い場合やPREGAPの実体が無い場合は + //  前トラックのend_offsetと同じ値 + // ISO:0 + // CUE: + // CCD: + // CDM: + // MDS:MDS_TrackBlock.start_offset(リトルエンディアン) + UINT64 end_offset; // イメージファイル上のトラック終了位置のoffset + // ISO:track_sectors * sector_size + // CUE: + // CCD: + // CDM: + // MDS:start_offset + (track_sectors * sector_size) + + UINT32 pregap_sectors; // トラックのPREGAPのセクタ数 + // ISO:0 + // CUE:PREGAP + // CCD: + // CDM: + // MDS:MDS_TrackExtraBlock.pregap(リトルエンディアン) + UINT32 track_sectors; // トラックのセクタ数 + // ISO:ファイルサイズ / sector_size + // CUE: + // CCD: + // CDM: + // MDS:MDS_TrackExtraBlock.length(リトルエンディアン) +// -------- +} _CDTRK, *CDTRK; + +#else +typedef struct { + UINT8 type; + UINT8 track; + FILEPOS pos; +} _CDTRK, *CDTRK; + +#endif + +BRESULT sxsicd_open(SXSIDEV sxsi, const OEMCHAR *fname); + +CDTRK sxsicd_gettrk(SXSIDEV sxsi, UINT *tracks); +BRESULT sxsicd_readraw(SXSIDEV sxsi, FILEPOS pos, void *buf); +UINT sxsicd_readraw_forhash(SXSIDEV sxsi, UINT uSecNo, UINT8 *pu8Buf, UINT* puSize); + +#ifdef __cplusplus +} +#endif + +#endif // _SXSICD_H_ + diff --git a/fdd/sxsihdd.c b/fdd/sxsihdd.c old mode 100755 new mode 100644 index 90183602..922a4aa8 --- a/fdd/sxsihdd.c +++ b/fdd/sxsihdd.c @@ -1,324 +1,324 @@ -#include -#include -#include -#include -#include -#include -#include -#ifdef SUPPORT_VPCVHD -#include "hdd_vpc.h" -#endif - -const char sig_vhd[8] = "VHD1.00"; -const char sig_nhd[15] = "T98HDDIMAGE.R0"; -const char sig_slh[] = "HDIM"; - -const SASIHDD sasihdd[7] = { - {33, 4, 153}, // 5MB - {33, 4, 310}, // 10MB - {33, 6, 310}, // 15MB - {33, 8, 310}, // 20MB - {33, 4, 615}, // 20MB (not used!) - {33, 6, 615}, // 30MB - {33, 8, 615}}; // 40MB - - -// ---- - -static BRESULT hdd_reopen(SXSIDEV sxsi) { - - FILEH fh; - - fh = file_open(sxsi->fname); - if (fh != FILEH_INVALID) { - sxsi->hdl = (INTPTR)fh; - return(SUCCESS); - } - else { - return(FAILURE); - } -} - -static REG8 hdd_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { - - FILEH fh; - FILEPOS r; - UINT rsize; - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(0x40); - } - pos = pos * sxsi->size + sxsi->headersize; - fh = (FILEH)sxsi->hdl; - r = file_seek(fh, pos, FSEEK_SET); - if (pos != r) { - return(0xd0); - } - while(size) { - rsize = MIN(size, sxsi->size); - CPU_REMCLOCK -= rsize; - if (file_read(fh, buf, rsize) != rsize) { - return(0xd0); - } - buf += rsize; - size -= rsize; - } - return(0x00); -} - -static REG8 hdd_write(SXSIDEV sxsi, FILEPOS pos, const UINT8 *buf, UINT size) { - - FILEH fh; - FILEPOS r; - UINT wsize; - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(0x40); - } - pos = pos * sxsi->size + sxsi->headersize; - fh = (FILEH)sxsi->hdl; - r = file_seek(fh, pos, FSEEK_SET); - if (pos != r) { - return(0xd0); - } - while(size) { - wsize = MIN(size, sxsi->size); - CPU_REMCLOCK -= wsize; - if (file_write(fh, buf, wsize) != wsize) { - return(0x70); - } - buf += wsize; - size -= wsize; - } - return(0x00); -} - -static REG8 hdd_format(SXSIDEV sxsi, FILEPOS pos) { - - FILEH fh; - FILEPOS r; - UINT16 i; - UINT8 work[256]; - UINT size; - UINT wsize; - - if (sxsi_prepare(sxsi) != SUCCESS) { - return(0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) { - return(0x40); - } - pos = pos * sxsi->size + sxsi->headersize; - fh = (FILEH)sxsi->hdl; - r = file_seek(fh, pos, FSEEK_SET); - if (pos != r) { - return(0xd0); - } - FillMemory(work, sizeof(work), 0xe5); - for (i=0; isectors; i++) { - size = sxsi->size; - while(size) { - wsize = MIN(size, sizeof(work)); - size -= wsize; - CPU_REMCLOCK -= wsize; - if (file_write(fh, work, wsize) != wsize) { - return(0x70); - } - } - } - return(0x00); -} - -static void hdd_close(SXSIDEV sxsi) { - - file_close((FILEH)sxsi->hdl); -} - - -// ---- - -// SASI規格HDDかチェック -static UINT8 gethddtype(SXSIDEV sxsi) { - -const SASIHDD *sasi; - UINT i; - - if (sxsi->size == 256) { - sasi = sasihdd; - for (i=0; isectors == sasi->sectors) && - (sxsi->surfaces == sasi->surfaces) && - (sxsi->cylinders == sasi->cylinders)) { - return((UINT8)i); - } - } - } - return(SXSIMEDIA_INVSASI + 7); -} - -BRESULT sxsihdd_open(SXSIDEV sxsi, const OEMCHAR *fname) { - - FILEH fh; -const OEMCHAR *ext; - REG8 iftype; - FILEPOS totals; - UINT32 headersize; - UINT32 surfaces; - UINT32 cylinders; - UINT32 sectors; - UINT32 size; - - fh = file_open(fname); - if (fh == FILEH_INVALID) { - goto sxsiope_err1; - } - ext = file_getext(fname); - iftype = sxsi->drv & SXSIDRV_IFMASK; - if ((iftype == SXSIDRV_SASI) && (!file_cmpname(ext, str_thd))) { - THDHDR thd; // T98 HDD (IDE) - if (file_read(fh, &thd, sizeof(thd)) != sizeof(thd)) { - goto sxsiope_err2; - } - headersize = 256; - surfaces = 8; - cylinders = LOADINTELWORD(thd.cylinders); - sectors = 33; - size = 256; - totals = (FILEPOS)cylinders * sectors * surfaces; - } - else if ((iftype == SXSIDRV_SASI || iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_nhd))) { - NHDHDR nhd; // T98Next HDD (IDE) - if ((file_read(fh, &nhd, sizeof(nhd)) != sizeof(nhd)) || - (memcmp(nhd.sig, sig_nhd, 15))) { - goto sxsiope_err2; - } - headersize = LOADINTELDWORD(nhd.headersize); - surfaces = LOADINTELWORD(nhd.surfaces); - cylinders = LOADINTELDWORD(nhd.cylinders); - sectors = LOADINTELWORD(nhd.sectors); - size = LOADINTELWORD(nhd.sectorsize); - totals = (FILEPOS)cylinders * sectors * surfaces; - } - else if ((iftype == SXSIDRV_SASI || iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_hdi))) { - HDIHDR hdi; // ANEX86 HDD (SASI) thanx Mamiya - if (file_read(fh, &hdi, sizeof(hdi)) != sizeof(hdi)) { - goto sxsiope_err2; - } - headersize = LOADINTELDWORD(hdi.headersize); - surfaces = LOADINTELDWORD(hdi.surfaces); - cylinders = LOADINTELDWORD(hdi.cylinders); - sectors = LOADINTELDWORD(hdi.sectors); - size = LOADINTELDWORD(hdi.sectorsize); - totals = (FILEPOS)cylinders * sectors * surfaces; - } - else if ((iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_hdd))) { - VHDHDR vhd; // Virtual98 HDD (SCSI) - if ((file_read(fh, &vhd, sizeof(vhd)) != sizeof(vhd)) || - (memcmp(vhd.sig, sig_vhd, 5))) { - goto sxsiope_err2; - } - headersize = sizeof(vhd); - surfaces = vhd.surfaces; - cylinders = LOADINTELWORD(vhd.cylinders); - sectors = vhd.sectors; - size = LOADINTELWORD(vhd.sectorsize); - totals = (SINT32)LOADINTELDWORD(vhd.totals); - } - else if ((iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_hdn))) { - // RaSCSI flat disk image for NEC PC-9801-55 - FILELEN fsize = file_getsize(fh); - headersize = 0; - size = 512; - surfaces = 8; - if(np2cfg.rascsi92){ - sectors = 32; - }else{ - sectors = 25; - } - cylinders = (UINT32)(fsize / ((FILELEN)sectors * surfaces * size)); - totals = fsize / size; - // totals = (FILEPOS)cylinders * sectors * surfaces; - } - else if ((iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_hds))) { - // RaSCSI flat disk image - FILELEN fsize = file_getsize(fh); - headersize = 0; - size = 512; - surfaces = 8; - sectors = 32; - cylinders = (UINT32)(fsize / ((FILELEN)sectors * surfaces * size)); - totals = fsize / size; - // totals = (FILEPOS)cylinders * sectors * surfaces; - } - else if ((iftype == SXSIDRV_SASI) && (!file_cmpname(ext, str_slh))) { - SLHHDR slh; // SL9821 HDD (IDE) - if ((file_read(fh, &slh, sizeof(slh)) != sizeof(slh)) || - (memcmp(slh.sig, sig_slh, 4))) { - goto sxsiope_err2; - } - headersize = 512; - surfaces = LOADINTELDWORD(slh.surfaces); - cylinders = LOADINTELDWORD(slh.cylinders); - sectors = LOADINTELDWORD(slh.sectors); - size = LOADINTELDWORD(slh.sectorsize); - totals = (FILEPOS)cylinders * sectors * surfaces; - } -#ifdef SUPPORT_VPCVHD - else if ((iftype == SXSIDRV_SASI || iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_vhd))) { - // Microsoft VirtualPC VHD (SASI/IDE) - BRESULT rc = sxsihdd_vpcvhd_mount(sxsi, fh); - if (rc == FAILURE) { - file_close(fh); - } - return (rc); - } -#endif - else { - goto sxsiope_err2; - } - - // フォーマット確認〜 - if ((surfaces == 0) || (surfaces >= 256) || - (cylinders == 0) || (cylinders >= 65536) || - (sectors == 0) || (sectors >= 256) || - (size == 0) || ((size & (size - 1)) != 0)) { - goto sxsiope_err2; - } - if (iftype == SXSIDRV_SCSI) { - if (!(size & 0x700)) { // not 256,512,1024 - goto sxsiope_err2; - } - } - sxsi->reopen = hdd_reopen; - sxsi->read = hdd_read; - sxsi->write = hdd_write; - sxsi->format = hdd_format; - sxsi->close = hdd_close; - - sxsi->hdl = (INTPTR)fh; - sxsi->totals = totals; - sxsi->cylinders = (UINT16)cylinders; - sxsi->size = (UINT16)size; - sxsi->sectors = (UINT8)sectors; - sxsi->surfaces = (UINT8)surfaces; - sxsi->headersize = headersize; - sxsi->mediatype = gethddtype(sxsi); - return(SUCCESS); - -sxsiope_err2: - file_close(fh); - -sxsiope_err1: - return(FAILURE); -} - -#ifdef SUPPORT_VPCVHD -#define HDD_VPC_INCLUDE -#include "hdd_vhd.h" -#endif +#include +#include +#include +#include +#include +#include +#include +#ifdef SUPPORT_VPCVHD +#include "hdd_vpc.h" +#endif + +const char sig_vhd[8] = "VHD1.00"; +const char sig_nhd[15] = "T98HDDIMAGE.R0"; +const char sig_slh[] = "HDIM"; + +const SASIHDD sasihdd[7] = { + {33, 4, 153}, // 5MB + {33, 4, 310}, // 10MB + {33, 6, 310}, // 15MB + {33, 8, 310}, // 20MB + {33, 4, 615}, // 20MB (not used!) + {33, 6, 615}, // 30MB + {33, 8, 615}}; // 40MB + + +// ---- + +static BRESULT hdd_reopen(SXSIDEV sxsi) { + + FILEH fh; + + fh = file_open(sxsi->fname); + if (fh != FILEH_INVALID) { + sxsi->hdl = (INTPTR)fh; + return(SUCCESS); + } + else { + return(FAILURE); + } +} + +static REG8 hdd_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) { + + FILEH fh; + FILEPOS r; + UINT rsize; + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(0x40); + } + pos = pos * sxsi->size + sxsi->headersize; + fh = (FILEH)sxsi->hdl; + r = file_seek(fh, pos, FSEEK_SET); + if (pos != r) { + return(0xd0); + } + while(size) { + rsize = MIN(size, sxsi->size); + CPU_REMCLOCK -= rsize; + if (file_read(fh, buf, rsize) != rsize) { + return(0xd0); + } + buf += rsize; + size -= rsize; + } + return(0x00); +} + +static REG8 hdd_write(SXSIDEV sxsi, FILEPOS pos, const UINT8 *buf, UINT size) { + + FILEH fh; + FILEPOS r; + UINT wsize; + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(0x40); + } + pos = pos * sxsi->size + sxsi->headersize; + fh = (FILEH)sxsi->hdl; + r = file_seek(fh, pos, FSEEK_SET); + if (pos != r) { + return(0xd0); + } + while(size) { + wsize = MIN(size, sxsi->size); + CPU_REMCLOCK -= wsize; + if (file_write(fh, buf, wsize) != wsize) { + return(0x70); + } + buf += wsize; + size -= wsize; + } + return(0x00); +} + +static REG8 hdd_format(SXSIDEV sxsi, FILEPOS pos) { + + FILEH fh; + FILEPOS r; + UINT16 i; + UINT8 work[256]; + UINT size; + UINT wsize; + + if (sxsi_prepare(sxsi) != SUCCESS) { + return(0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) { + return(0x40); + } + pos = pos * sxsi->size + sxsi->headersize; + fh = (FILEH)sxsi->hdl; + r = file_seek(fh, pos, FSEEK_SET); + if (pos != r) { + return(0xd0); + } + FillMemory(work, sizeof(work), 0xe5); + for (i=0; isectors; i++) { + size = sxsi->size; + while(size) { + wsize = MIN(size, sizeof(work)); + size -= wsize; + CPU_REMCLOCK -= wsize; + if (file_write(fh, work, wsize) != wsize) { + return(0x70); + } + } + } + return(0x00); +} + +static void hdd_close(SXSIDEV sxsi) { + + file_close((FILEH)sxsi->hdl); +} + + +// ---- + +// SASI規格HDDかチェック +static UINT8 gethddtype(SXSIDEV sxsi) { + +const SASIHDD *sasi; + UINT i; + + if (sxsi->size == 256) { + sasi = sasihdd; + for (i=0; isectors == sasi->sectors) && + (sxsi->surfaces == sasi->surfaces) && + (sxsi->cylinders == sasi->cylinders)) { + return((UINT8)i); + } + } + } + return(SXSIMEDIA_INVSASI + 7); +} + +BRESULT sxsihdd_open(SXSIDEV sxsi, const OEMCHAR *fname) { + + FILEH fh; +const OEMCHAR *ext; + REG8 iftype; + FILEPOS totals; + UINT32 headersize; + UINT32 surfaces; + UINT32 cylinders; + UINT32 sectors; + UINT32 size; + + fh = file_open(fname); + if (fh == FILEH_INVALID) { + goto sxsiope_err1; + } + ext = file_getext(fname); + iftype = sxsi->drv & SXSIDRV_IFMASK; + if ((iftype == SXSIDRV_SASI) && (!file_cmpname(ext, str_thd))) { + THDHDR thd; // T98 HDD (IDE) + if (file_read(fh, &thd, sizeof(thd)) != sizeof(thd)) { + goto sxsiope_err2; + } + headersize = 256; + surfaces = 8; + cylinders = LOADINTELWORD(thd.cylinders); + sectors = 33; + size = 256; + totals = (FILEPOS)cylinders * sectors * surfaces; + } + else if ((iftype == SXSIDRV_SASI || iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_nhd))) { + NHDHDR nhd; // T98Next HDD (IDE) + if ((file_read(fh, &nhd, sizeof(nhd)) != sizeof(nhd)) || + (memcmp(nhd.sig, sig_nhd, 15))) { + goto sxsiope_err2; + } + headersize = LOADINTELDWORD(nhd.headersize); + surfaces = LOADINTELWORD(nhd.surfaces); + cylinders = LOADINTELDWORD(nhd.cylinders); + sectors = LOADINTELWORD(nhd.sectors); + size = LOADINTELWORD(nhd.sectorsize); + totals = (FILEPOS)cylinders * sectors * surfaces; + } + else if ((iftype == SXSIDRV_SASI || iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_hdi))) { + HDIHDR hdi; // ANEX86 HDD (SASI) thanx Mamiya + if (file_read(fh, &hdi, sizeof(hdi)) != sizeof(hdi)) { + goto sxsiope_err2; + } + headersize = LOADINTELDWORD(hdi.headersize); + surfaces = LOADINTELDWORD(hdi.surfaces); + cylinders = LOADINTELDWORD(hdi.cylinders); + sectors = LOADINTELDWORD(hdi.sectors); + size = LOADINTELDWORD(hdi.sectorsize); + totals = (FILEPOS)cylinders * sectors * surfaces; + } + else if ((iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_hdd))) { + VHDHDR vhd; // Virtual98 HDD (SCSI) + if ((file_read(fh, &vhd, sizeof(vhd)) != sizeof(vhd)) || + (memcmp(vhd.sig, sig_vhd, 5))) { + goto sxsiope_err2; + } + headersize = sizeof(vhd); + surfaces = vhd.surfaces; + cylinders = LOADINTELWORD(vhd.cylinders); + sectors = vhd.sectors; + size = LOADINTELWORD(vhd.sectorsize); + totals = (SINT32)LOADINTELDWORD(vhd.totals); + } + else if ((iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_hdn))) { + // RaSCSI flat disk image for NEC PC-9801-55 + FILELEN fsize = file_getsize(fh); + headersize = 0; + size = 512; + surfaces = 8; + if(np2cfg.rascsi92){ + sectors = 32; + }else{ + sectors = 25; + } + cylinders = (UINT32)(fsize / ((FILELEN)sectors * surfaces * size)); + totals = fsize / size; + // totals = (FILEPOS)cylinders * sectors * surfaces; + } + else if ((iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_hds))) { + // RaSCSI flat disk image + FILELEN fsize = file_getsize(fh); + headersize = 0; + size = 512; + surfaces = 8; + sectors = 32; + cylinders = (UINT32)(fsize / ((FILELEN)sectors * surfaces * size)); + totals = fsize / size; + // totals = (FILEPOS)cylinders * sectors * surfaces; + } + else if ((iftype == SXSIDRV_SASI) && (!file_cmpname(ext, str_slh))) { + SLHHDR slh; // SL9821 HDD (IDE) + if ((file_read(fh, &slh, sizeof(slh)) != sizeof(slh)) || + (memcmp(slh.sig, sig_slh, 4))) { + goto sxsiope_err2; + } + headersize = 512; + surfaces = LOADINTELDWORD(slh.surfaces); + cylinders = LOADINTELDWORD(slh.cylinders); + sectors = LOADINTELDWORD(slh.sectors); + size = LOADINTELDWORD(slh.sectorsize); + totals = (FILEPOS)cylinders * sectors * surfaces; + } +#ifdef SUPPORT_VPCVHD + else if ((iftype == SXSIDRV_SASI || iftype == SXSIDRV_SCSI) && (!file_cmpname(ext, str_vhd))) { + // Microsoft VirtualPC VHD (SASI/IDE) + BRESULT rc = sxsihdd_vpcvhd_mount(sxsi, fh); + if (rc == FAILURE) { + file_close(fh); + } + return (rc); + } +#endif + else { + goto sxsiope_err2; + } + + // フォーマット確認〜 + if ((surfaces == 0) || (surfaces >= 256) || + (cylinders == 0) || (cylinders >= 65536) || + (sectors == 0) || (sectors >= 256) || + (size == 0) || ((size & (size - 1)) != 0)) { + goto sxsiope_err2; + } + if (iftype == SXSIDRV_SCSI) { + if (!(size & 0x700)) { // not 256,512,1024 + goto sxsiope_err2; + } + } + sxsi->reopen = hdd_reopen; + sxsi->read = hdd_read; + sxsi->write = hdd_write; + sxsi->format = hdd_format; + sxsi->close = hdd_close; + + sxsi->hdl = (INTPTR)fh; + sxsi->totals = totals; + sxsi->cylinders = (UINT16)cylinders; + sxsi->size = (UINT16)size; + sxsi->sectors = (UINT8)sectors; + sxsi->surfaces = (UINT8)surfaces; + sxsi->headersize = headersize; + sxsi->mediatype = gethddtype(sxsi); + return(SUCCESS); + +sxsiope_err2: + file_close(fh); + +sxsiope_err1: + return(FAILURE); +} + +#ifdef SUPPORT_VPCVHD +#define HDD_VPC_INCLUDE +#include "hdd_vhd.h" +#endif diff --git a/fdd/sxsihdd.h b/fdd/sxsihdd.h old mode 100755 new mode 100644 index 874771b9..dad3df38 --- a/fdd/sxsihdd.h +++ b/fdd/sxsihdd.h @@ -1,81 +1,81 @@ - -enum { - SXSIMEDIA_SASITYPE = 0x07, - SXSIMEDIA_INVSASI = 0x08 -}; - -typedef struct { - UINT8 sectors; - UINT8 surfaces; - UINT16 cylinders; -} SASIHDD; - -typedef struct { - UINT8 cylinders[2]; -} THDHDR; - -typedef struct { - char sig[16]; - char comment[0x100]; - UINT8 headersize[4]; - UINT8 cylinders[4]; - UINT8 surfaces[2]; - UINT8 sectors[2]; - UINT8 sectorsize[2]; - UINT8 reserved[0xe2]; -} NHDHDR; - -typedef struct { - UINT8 dummy[4]; - UINT8 hddtype[4]; - UINT8 headersize[4]; - UINT8 hddsize[4]; - UINT8 sectorsize[4]; - UINT8 sectors[4]; - UINT8 surfaces[4]; - UINT8 cylinders[4]; -} HDIHDR; - -typedef struct { - char sig[3]; - char ver[4]; - char delimita; - char comment[128]; - UINT8 padding1[4]; - UINT8 mbsize[2]; - UINT8 sectorsize[2]; - UINT8 sectors; - UINT8 surfaces; - UINT8 cylinders[2]; - UINT8 totals[4]; - UINT8 padding2[0x44]; -} VHDHDR; - -typedef struct { - char sig[4]; - UINT8 drvsize[8]; - UINT8 sectorsize[4]; - UINT8 cylinders[4]; - UINT8 surfaces[4]; - UINT8 sectors[4]; - UINT8 serialnum[20]; - UINT8 revision[8]; - char model[40]; -} SLHHDR; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern const char sig_vhd[8]; -extern const char sig_nhd[15]; -extern const SASIHDD sasihdd[7]; - -BRESULT sxsihdd_open(SXSIDEV sxsi, const OEMCHAR *fname); - -#ifdef __cplusplus -} -#endif - - + +enum { + SXSIMEDIA_SASITYPE = 0x07, + SXSIMEDIA_INVSASI = 0x08 +}; + +typedef struct { + UINT8 sectors; + UINT8 surfaces; + UINT16 cylinders; +} SASIHDD; + +typedef struct { + UINT8 cylinders[2]; +} THDHDR; + +typedef struct { + char sig[16]; + char comment[0x100]; + UINT8 headersize[4]; + UINT8 cylinders[4]; + UINT8 surfaces[2]; + UINT8 sectors[2]; + UINT8 sectorsize[2]; + UINT8 reserved[0xe2]; +} NHDHDR; + +typedef struct { + UINT8 dummy[4]; + UINT8 hddtype[4]; + UINT8 headersize[4]; + UINT8 hddsize[4]; + UINT8 sectorsize[4]; + UINT8 sectors[4]; + UINT8 surfaces[4]; + UINT8 cylinders[4]; +} HDIHDR; + +typedef struct { + char sig[3]; + char ver[4]; + char delimita; + char comment[128]; + UINT8 padding1[4]; + UINT8 mbsize[2]; + UINT8 sectorsize[2]; + UINT8 sectors; + UINT8 surfaces; + UINT8 cylinders[2]; + UINT8 totals[4]; + UINT8 padding2[0x44]; +} VHDHDR; + +typedef struct { + char sig[4]; + UINT8 drvsize[8]; + UINT8 sectorsize[4]; + UINT8 cylinders[4]; + UINT8 surfaces[4]; + UINT8 sectors[4]; + UINT8 serialnum[20]; + UINT8 revision[8]; + char model[40]; +} SLHHDR; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern const char sig_vhd[8]; +extern const char sig_nhd[15]; +extern const SASIHDD sasihdd[7]; + +BRESULT sxsihdd_open(SXSIDEV sxsi, const OEMCHAR *fname); + +#ifdef __cplusplus +} +#endif + + diff --git a/fdd/sxsihdd_nvl.c b/fdd/sxsihdd_nvl.c old mode 100755 new mode 100644 index 3c790364..70f1913a --- a/fdd/sxsihdd_nvl.c +++ b/fdd/sxsihdd_nvl.c @@ -1,506 +1,506 @@ -#include - -#ifdef SUPPORT_NVL_IMAGES - -#if !defined(_WIN32) -#include -#endif -#include -#include -#include -#include -#include -#include - - -#if defined(_WIN32) -typedef void *sxsihdd_nvl_1(LPCTSTR path, BOOL ro); -#else -typedef void *sxsihdd_nvl_1(const char *path, SINT32 ro); -#endif -typedef void sxsihdd_nvl_2(void *pv); -typedef void sxsihdd_nvl_3(void *pv, UINT32 *a); -#if defined(_WIN32) -typedef BOOL sxsihdd_nvl_4(void *pv, INT64 p, UINT32 s, void *b); -typedef BOOL sxsihdd_nvl_5(void *pv, INT64 p, UINT32 s, const void *b); -#else -typedef SINT32 sxsihdd_nvl_4(void *pv, SINT64 p, UINT32 s, void *b); -typedef SINT32 sxsihdd_nvl_5(void *pv, SINT64 p, UINT32 s, const void *b); -#endif -#if defined(_WIN32) -typedef BOOL sxsihdd_nvl_7(LPCTSTR spath, LPCTSTR path); -#else -typedef BOOL sxsihdd_nvl_7(const char *spath, const char *path); -#endif - - -typedef struct _sxsihdd_nvl -{ -#if defined(_WIN32) - HMODULE hModule; -#else - void *hModule; -#endif - sxsihdd_nvl_1 *f1; - sxsihdd_nvl_2 *f2; - sxsihdd_nvl_3 *f3; - sxsihdd_nvl_4 *f4; - sxsihdd_nvl_5 *f5; - void *pv; -} sxsihdd_nvl; - -BOOL nvl_check() -{ -#if defined(_WIN32) - HMODULE hModule = NULL; - - hModule = LoadLibrary(_T("NVL.DLL")); -#else - void *hModule = NULL; - - hModule = dlopen("libnvl.so", RTLD_LAZY); -#endif - if(!hModule) return FALSE; - -#if defined(_WIN32) - if(!GetProcAddress(hModule, MAKEINTRESOURCEA(1))) goto check_err; - if(!GetProcAddress(hModule, MAKEINTRESOURCEA(2))) goto check_err; - if(!GetProcAddress(hModule, MAKEINTRESOURCEA(3))) goto check_err; - if(!GetProcAddress(hModule, MAKEINTRESOURCEA(4))) goto check_err; - if(!GetProcAddress(hModule, MAKEINTRESOURCEA(5))) goto check_err; - if(!GetProcAddress(hModule, MAKEINTRESOURCEA(7))) goto check_err; - - FreeLibrary(hModule); -#else - if(!dlsym(hModule, "_1")) goto check_err; - if(!dlsym(hModule, "_2")) goto check_err; - if(!dlsym(hModule, "_3")) goto check_err; - if(!dlsym(hModule, "_4")) goto check_err; - if(!dlsym(hModule, "_5")) goto check_err; - if(!dlsym(hModule, "_7")) goto check_err; - - dlclose(hModule); -#endif - - return TRUE; -check_err: - return FALSE; -} - - -static void nvl_close(sxsihdd_nvl *p) -{ - if (p == NULL) - { - return; - } - - if (p->pv != NULL) - { - (*p->f2)(p->pv); - } - - if (p->hModule != NULL) - { -#if defined(_WIN32) - FreeLibrary(p->hModule); -#else - dlclose(p->hModule); -#endif - } - - _MFREE(p); -} - - -static sxsihdd_nvl *nvl_open(const OEMCHAR *fname) -{ - sxsihdd_nvl *p = NULL; -#if defined(_WIN32) - HMODULE hModule = NULL; -#else - void *hModule = NULL; -#endif - - p = (sxsihdd_nvl*)_MALLOC(sizeof(sxsihdd_nvl), "sxsihdd_nvl_open"); - if (p == NULL) - { - goto sxsiope_err; - } - - p->hModule = NULL; - p->pv = NULL; - -#if defined(_WIN32) - p->hModule = LoadLibrary(_T("NVL.DLL")); -#else - p->hModule = dlopen("libnvl.so", RTLD_LAZY); -#endif - if (p->hModule == NULL) - { - goto sxsiope_err; - } - -#if defined(_WIN32) - p->f1 = (sxsihdd_nvl_1 *)GetProcAddress(p->hModule, MAKEINTRESOURCEA(1)); - p->f2 = (sxsihdd_nvl_2 *)GetProcAddress(p->hModule, MAKEINTRESOURCEA(2)); - p->f3 = (sxsihdd_nvl_3 *)GetProcAddress(p->hModule, MAKEINTRESOURCEA(3)); - p->f4 = (sxsihdd_nvl_4 *)GetProcAddress(p->hModule, MAKEINTRESOURCEA(4)); - p->f5 = (sxsihdd_nvl_5 *)GetProcAddress(p->hModule, MAKEINTRESOURCEA(5)); - - p->pv = (*p->f1)(fname, FALSE); -#else - p->f1 = (sxsihdd_nvl_1 *)dlsym(p->hModule, "_1"); - p->f2 = (sxsihdd_nvl_2 *)dlsym(p->hModule, "_2"); - p->f3 = (sxsihdd_nvl_3 *)dlsym(p->hModule, "_3"); - p->f4 = (sxsihdd_nvl_4 *)dlsym(p->hModule, "_4"); - p->f5 = (sxsihdd_nvl_5 *)dlsym(p->hModule, "_5"); - - p->pv = (*p->f1)(fname, 0); -#endif - if (p->pv == NULL) - { - goto sxsiope_err; - } - - return (p); - -sxsiope_err: - if (p != NULL) - { - nvl_close(p); - } - - return (NULL); -} - - -static BRESULT hdd_reopen(SXSIDEV sxsi) -{ - sxsihdd_nvl *p = NULL; - - p = nvl_open(sxsi->fname); - if (p == NULL) - { - return (FAILURE); - } - - sxsi->hdl = (INTPTR)p; - return (SUCCESS); -} - - -static REG8 hdd_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) -{ - sxsihdd_nvl *p = NULL; - - if (sxsi_prepare(sxsi) != SUCCESS) - { - return (0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) - { - return (0x40); - } - p = (sxsihdd_nvl *)sxsi->hdl; - if(p == NULL){ - return (0x60); - } - - p = (sxsihdd_nvl *)sxsi->hdl; - - pos = pos * sxsi->size; - - while (size) - { - UINT rsize; - - rsize = MIN(size, sxsi->size); - CPU_REMCLOCK -= rsize; - - if (!(*p->f4)(p->pv, pos, rsize, buf)) - { - return (0xd0); - } - - buf += rsize; - size -= rsize; - pos += rsize; - } - - return (0x00); -} - - -static REG8 hdd_write(SXSIDEV sxsi, FILEPOS pos, const UINT8 *buf, UINT size) -{ - sxsihdd_nvl *p = NULL; - - if (sxsi_prepare(sxsi) != SUCCESS) - { - return (0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) - { - return (0x40); - } - p = (sxsihdd_nvl *)sxsi->hdl; - if(p == NULL){ - return (0x60); - } - - pos = pos * sxsi->size; - - while (size) - { - UINT wsize; - - wsize = MIN(size, sxsi->size); - CPU_REMCLOCK -= wsize; - - if (!(*p->f5)(p->pv, pos, wsize, buf)) - { - return (0x70); - } - - buf += wsize; - size -= wsize; - pos += wsize; - } - - return (0x00); -} - - -static REG8 hdd_format(SXSIDEV sxsi, FILEPOS pos) -{ - sxsihdd_nvl *p = NULL; - UINT16 i; - UINT8 work[256]; - - if (sxsi_prepare(sxsi) != SUCCESS) - { - return (0x60); - } - if ((pos < 0) || (pos >= sxsi->totals)) - { - return (0x40); - } - p = (sxsihdd_nvl *)sxsi->hdl; - if(p == NULL){ - return (0x60); - } - - p = (sxsihdd_nvl *)sxsi->hdl; - - pos = pos * sxsi->size; - - FillMemory(work, sizeof(work), 0xe5); - for (i = 0; i < sxsi->sectors; i++) - { - UINT size; - - size = sxsi->size; - while (size) - { - UINT wsize; - - wsize = MIN(size, sizeof(work)); - size -= wsize; - CPU_REMCLOCK -= wsize; - - if (!(*p->f5)(p->pv, pos, wsize, work)) - { - return (0x70); - } - - pos += wsize; - } - } - - return (0x00); -} - - -static void hdd_close(SXSIDEV sxsi) -{ - sxsihdd_nvl *p = (sxsihdd_nvl *)sxsi->hdl; - - nvl_close(p); -} - - -static UINT8 gethddtype(SXSIDEV sxsi) -{ - const SASIHDD *sasi; - UINT i; - - if (sxsi->size == 256) - { - sasi = sasihdd; - for (i = 0; i < NELEMENTS(sasihdd); i++, sasi++) - { - if ((sxsi->sectors == sasi->sectors) && - (sxsi->surfaces == sasi->surfaces) && - (sxsi->cylinders == sasi->cylinders)) - { - return ((UINT8)i); - } - } - } - return (SXSIMEDIA_INVSASI + 7); -} - - -static BRESULT hdd_state_save(SXSIDEV sxsi, const OEMCHAR *sfname) -{ - BRESULT r; -#if defined(_WIN32) - HMODULE hModule = NULL; -#else - void *hModule = NULL; -#endif - sxsihdd_nvl_7 *f7; - -#if defined(_WIN32) - hModule = LoadLibrary(_T("NVL.DLL")); -#else - hModule = dlopen("libnvl.so", RTLD_LAZY); -#endif - if (!hModule) - { - r = FAILURE; - goto sxsiope_err; - } - -#if defined(_WIN32) - f7 = (sxsihdd_nvl_7 *)GetProcAddress(hModule, MAKEINTRESOURCEA(7)); -#else - f7 = (sxsihdd_nvl_7 *)dlsym(hModule, "_7"); -#endif - - if (file_rename(sxsi->fname, sfname) != 0) - { - r = FAILURE; - goto sxsiope_err; - } - - if (!f7(sfname, sxsi->fname)) - { - r = FAILURE; - goto sxsiope_err; - } - - r = SUCCESS; - -sxsiope_err: - if (hModule != NULL) - { -#if defined(_WIN32) - FreeLibrary(hModule); -#else - dlclose(hModule); -#endif - } - - return (r); -} - - -static BRESULT hdd_state_load(SXSIDEV sxsi, const OEMCHAR *sfname) -{ - BRESULT r; -#if defined(_WIN32) - HMODULE hModule = NULL; -#else - void *hModule = NULL; -#endif - sxsihdd_nvl_7 *f7; - -#if defined(_WIN32) - hModule = LoadLibrary(_T("NVL.DLL")); -#else - hModule = dlopen("libnvl.so", RTLD_LAZY); -#endif - if (!hModule) - { - r = FAILURE; - goto sxsiope_err; - } - -#if defined(_WIN32) - f7 = (sxsihdd_nvl_7 *)GetProcAddress(hModule, MAKEINTRESOURCEA(7)); -#else - f7 = (sxsihdd_nvl_7 *)dlsym(hModule, "_7"); -#endif - - if (file_delete(sxsi->fname) != 0) - { - r = FAILURE; - goto sxsiope_err; - } - - if (!f7(sfname, sxsi->fname)) - { - r = FAILURE; - goto sxsiope_err; - } - - r = SUCCESS; - -sxsiope_err: - if (hModule != NULL) - { -#if defined(_WIN32) - FreeLibrary(hModule); -#else - dlclose(hModule); -#endif - } - - return (r); -} - - -BRESULT sxsihdd_nvl_open(SXSIDEV sxsi, const OEMCHAR *fname) -{ - sxsihdd_nvl *p = NULL; - UINT32 a[4]; - - p = nvl_open(fname); - if (p == NULL) - { - goto sxsiope_err; - } - - (*p->f3)(p->pv, a); - - sxsi->reopen = hdd_reopen; - sxsi->read = hdd_read; - sxsi->write = hdd_write; - sxsi->format = hdd_format; - sxsi->close = hdd_close; - sxsi->state_save = hdd_state_save; - sxsi->state_load = hdd_state_load; - - sxsi->hdl = (INTPTR)p; - sxsi->totals = a[0]; - sxsi->cylinders = (UINT16)(a[0] / (a[2] * a[1])); - sxsi->size = (UINT16)a[3]; - sxsi->sectors = (UINT8)a[2]; - sxsi->surfaces = (UINT8)a[1]; - sxsi->headersize = 0; - sxsi->mediatype = gethddtype(sxsi); - - return (SUCCESS); - -sxsiope_err: - if (p != NULL) - { - nvl_close(p); - } - - return (FAILURE); -} - -#endif +#include + +#ifdef SUPPORT_NVL_IMAGES + +#if !defined(_WIN32) +#include +#endif +#include +#include +#include +#include +#include +#include + + +#if defined(_WIN32) +typedef void *sxsihdd_nvl_1(LPCTSTR path, BOOL ro); +#else +typedef void *sxsihdd_nvl_1(const char *path, SINT32 ro); +#endif +typedef void sxsihdd_nvl_2(void *pv); +typedef void sxsihdd_nvl_3(void *pv, UINT32 *a); +#if defined(_WIN32) +typedef BOOL sxsihdd_nvl_4(void *pv, INT64 p, UINT32 s, void *b); +typedef BOOL sxsihdd_nvl_5(void *pv, INT64 p, UINT32 s, const void *b); +#else +typedef SINT32 sxsihdd_nvl_4(void *pv, SINT64 p, UINT32 s, void *b); +typedef SINT32 sxsihdd_nvl_5(void *pv, SINT64 p, UINT32 s, const void *b); +#endif +#if defined(_WIN32) +typedef BOOL sxsihdd_nvl_7(LPCTSTR spath, LPCTSTR path); +#else +typedef BOOL sxsihdd_nvl_7(const char *spath, const char *path); +#endif + + +typedef struct _sxsihdd_nvl +{ +#if defined(_WIN32) + HMODULE hModule; +#else + void *hModule; +#endif + sxsihdd_nvl_1 *f1; + sxsihdd_nvl_2 *f2; + sxsihdd_nvl_3 *f3; + sxsihdd_nvl_4 *f4; + sxsihdd_nvl_5 *f5; + void *pv; +} sxsihdd_nvl; + +BOOL nvl_check() +{ +#if defined(_WIN32) + HMODULE hModule = NULL; + + hModule = LoadLibrary(_T("NVL.DLL")); +#else + void *hModule = NULL; + + hModule = dlopen("libnvl.so", RTLD_LAZY); +#endif + if(!hModule) return FALSE; + +#if defined(_WIN32) + if(!GetProcAddress(hModule, MAKEINTRESOURCEA(1))) goto check_err; + if(!GetProcAddress(hModule, MAKEINTRESOURCEA(2))) goto check_err; + if(!GetProcAddress(hModule, MAKEINTRESOURCEA(3))) goto check_err; + if(!GetProcAddress(hModule, MAKEINTRESOURCEA(4))) goto check_err; + if(!GetProcAddress(hModule, MAKEINTRESOURCEA(5))) goto check_err; + if(!GetProcAddress(hModule, MAKEINTRESOURCEA(7))) goto check_err; + + FreeLibrary(hModule); +#else + if(!dlsym(hModule, "_1")) goto check_err; + if(!dlsym(hModule, "_2")) goto check_err; + if(!dlsym(hModule, "_3")) goto check_err; + if(!dlsym(hModule, "_4")) goto check_err; + if(!dlsym(hModule, "_5")) goto check_err; + if(!dlsym(hModule, "_7")) goto check_err; + + dlclose(hModule); +#endif + + return TRUE; +check_err: + return FALSE; +} + + +static void nvl_close(sxsihdd_nvl *p) +{ + if (p == NULL) + { + return; + } + + if (p->pv != NULL) + { + (*p->f2)(p->pv); + } + + if (p->hModule != NULL) + { +#if defined(_WIN32) + FreeLibrary(p->hModule); +#else + dlclose(p->hModule); +#endif + } + + _MFREE(p); +} + + +static sxsihdd_nvl *nvl_open(const OEMCHAR *fname) +{ + sxsihdd_nvl *p = NULL; +#if defined(_WIN32) + HMODULE hModule = NULL; +#else + void *hModule = NULL; +#endif + + p = (sxsihdd_nvl*)_MALLOC(sizeof(sxsihdd_nvl), "sxsihdd_nvl_open"); + if (p == NULL) + { + goto sxsiope_err; + } + + p->hModule = NULL; + p->pv = NULL; + +#if defined(_WIN32) + p->hModule = LoadLibrary(_T("NVL.DLL")); +#else + p->hModule = dlopen("libnvl.so", RTLD_LAZY); +#endif + if (p->hModule == NULL) + { + goto sxsiope_err; + } + +#if defined(_WIN32) + p->f1 = (sxsihdd_nvl_1 *)GetProcAddress(p->hModule, MAKEINTRESOURCEA(1)); + p->f2 = (sxsihdd_nvl_2 *)GetProcAddress(p->hModule, MAKEINTRESOURCEA(2)); + p->f3 = (sxsihdd_nvl_3 *)GetProcAddress(p->hModule, MAKEINTRESOURCEA(3)); + p->f4 = (sxsihdd_nvl_4 *)GetProcAddress(p->hModule, MAKEINTRESOURCEA(4)); + p->f5 = (sxsihdd_nvl_5 *)GetProcAddress(p->hModule, MAKEINTRESOURCEA(5)); + + p->pv = (*p->f1)(fname, FALSE); +#else + p->f1 = (sxsihdd_nvl_1 *)dlsym(p->hModule, "_1"); + p->f2 = (sxsihdd_nvl_2 *)dlsym(p->hModule, "_2"); + p->f3 = (sxsihdd_nvl_3 *)dlsym(p->hModule, "_3"); + p->f4 = (sxsihdd_nvl_4 *)dlsym(p->hModule, "_4"); + p->f5 = (sxsihdd_nvl_5 *)dlsym(p->hModule, "_5"); + + p->pv = (*p->f1)(fname, 0); +#endif + if (p->pv == NULL) + { + goto sxsiope_err; + } + + return (p); + +sxsiope_err: + if (p != NULL) + { + nvl_close(p); + } + + return (NULL); +} + + +static BRESULT hdd_reopen(SXSIDEV sxsi) +{ + sxsihdd_nvl *p = NULL; + + p = nvl_open(sxsi->fname); + if (p == NULL) + { + return (FAILURE); + } + + sxsi->hdl = (INTPTR)p; + return (SUCCESS); +} + + +static REG8 hdd_read(SXSIDEV sxsi, FILEPOS pos, UINT8 *buf, UINT size) +{ + sxsihdd_nvl *p = NULL; + + if (sxsi_prepare(sxsi) != SUCCESS) + { + return (0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) + { + return (0x40); + } + p = (sxsihdd_nvl *)sxsi->hdl; + if(p == NULL){ + return (0x60); + } + + p = (sxsihdd_nvl *)sxsi->hdl; + + pos = pos * sxsi->size; + + while (size) + { + UINT rsize; + + rsize = MIN(size, sxsi->size); + CPU_REMCLOCK -= rsize; + + if (!(*p->f4)(p->pv, pos, rsize, buf)) + { + return (0xd0); + } + + buf += rsize; + size -= rsize; + pos += rsize; + } + + return (0x00); +} + + +static REG8 hdd_write(SXSIDEV sxsi, FILEPOS pos, const UINT8 *buf, UINT size) +{ + sxsihdd_nvl *p = NULL; + + if (sxsi_prepare(sxsi) != SUCCESS) + { + return (0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) + { + return (0x40); + } + p = (sxsihdd_nvl *)sxsi->hdl; + if(p == NULL){ + return (0x60); + } + + pos = pos * sxsi->size; + + while (size) + { + UINT wsize; + + wsize = MIN(size, sxsi->size); + CPU_REMCLOCK -= wsize; + + if (!(*p->f5)(p->pv, pos, wsize, buf)) + { + return (0x70); + } + + buf += wsize; + size -= wsize; + pos += wsize; + } + + return (0x00); +} + + +static REG8 hdd_format(SXSIDEV sxsi, FILEPOS pos) +{ + sxsihdd_nvl *p = NULL; + UINT16 i; + UINT8 work[256]; + + if (sxsi_prepare(sxsi) != SUCCESS) + { + return (0x60); + } + if ((pos < 0) || (pos >= sxsi->totals)) + { + return (0x40); + } + p = (sxsihdd_nvl *)sxsi->hdl; + if(p == NULL){ + return (0x60); + } + + p = (sxsihdd_nvl *)sxsi->hdl; + + pos = pos * sxsi->size; + + FillMemory(work, sizeof(work), 0xe5); + for (i = 0; i < sxsi->sectors; i++) + { + UINT size; + + size = sxsi->size; + while (size) + { + UINT wsize; + + wsize = MIN(size, sizeof(work)); + size -= wsize; + CPU_REMCLOCK -= wsize; + + if (!(*p->f5)(p->pv, pos, wsize, work)) + { + return (0x70); + } + + pos += wsize; + } + } + + return (0x00); +} + + +static void hdd_close(SXSIDEV sxsi) +{ + sxsihdd_nvl *p = (sxsihdd_nvl *)sxsi->hdl; + + nvl_close(p); +} + + +static UINT8 gethddtype(SXSIDEV sxsi) +{ + const SASIHDD *sasi; + UINT i; + + if (sxsi->size == 256) + { + sasi = sasihdd; + for (i = 0; i < NELEMENTS(sasihdd); i++, sasi++) + { + if ((sxsi->sectors == sasi->sectors) && + (sxsi->surfaces == sasi->surfaces) && + (sxsi->cylinders == sasi->cylinders)) + { + return ((UINT8)i); + } + } + } + return (SXSIMEDIA_INVSASI + 7); +} + + +static BRESULT hdd_state_save(SXSIDEV sxsi, const OEMCHAR *sfname) +{ + BRESULT r; +#if defined(_WIN32) + HMODULE hModule = NULL; +#else + void *hModule = NULL; +#endif + sxsihdd_nvl_7 *f7; + +#if defined(_WIN32) + hModule = LoadLibrary(_T("NVL.DLL")); +#else + hModule = dlopen("libnvl.so", RTLD_LAZY); +#endif + if (!hModule) + { + r = FAILURE; + goto sxsiope_err; + } + +#if defined(_WIN32) + f7 = (sxsihdd_nvl_7 *)GetProcAddress(hModule, MAKEINTRESOURCEA(7)); +#else + f7 = (sxsihdd_nvl_7 *)dlsym(hModule, "_7"); +#endif + + if (file_rename(sxsi->fname, sfname) != 0) + { + r = FAILURE; + goto sxsiope_err; + } + + if (!f7(sfname, sxsi->fname)) + { + r = FAILURE; + goto sxsiope_err; + } + + r = SUCCESS; + +sxsiope_err: + if (hModule != NULL) + { +#if defined(_WIN32) + FreeLibrary(hModule); +#else + dlclose(hModule); +#endif + } + + return (r); +} + + +static BRESULT hdd_state_load(SXSIDEV sxsi, const OEMCHAR *sfname) +{ + BRESULT r; +#if defined(_WIN32) + HMODULE hModule = NULL; +#else + void *hModule = NULL; +#endif + sxsihdd_nvl_7 *f7; + +#if defined(_WIN32) + hModule = LoadLibrary(_T("NVL.DLL")); +#else + hModule = dlopen("libnvl.so", RTLD_LAZY); +#endif + if (!hModule) + { + r = FAILURE; + goto sxsiope_err; + } + +#if defined(_WIN32) + f7 = (sxsihdd_nvl_7 *)GetProcAddress(hModule, MAKEINTRESOURCEA(7)); +#else + f7 = (sxsihdd_nvl_7 *)dlsym(hModule, "_7"); +#endif + + if (file_delete(sxsi->fname) != 0) + { + r = FAILURE; + goto sxsiope_err; + } + + if (!f7(sfname, sxsi->fname)) + { + r = FAILURE; + goto sxsiope_err; + } + + r = SUCCESS; + +sxsiope_err: + if (hModule != NULL) + { +#if defined(_WIN32) + FreeLibrary(hModule); +#else + dlclose(hModule); +#endif + } + + return (r); +} + + +BRESULT sxsihdd_nvl_open(SXSIDEV sxsi, const OEMCHAR *fname) +{ + sxsihdd_nvl *p = NULL; + UINT32 a[4]; + + p = nvl_open(fname); + if (p == NULL) + { + goto sxsiope_err; + } + + (*p->f3)(p->pv, a); + + sxsi->reopen = hdd_reopen; + sxsi->read = hdd_read; + sxsi->write = hdd_write; + sxsi->format = hdd_format; + sxsi->close = hdd_close; + sxsi->state_save = hdd_state_save; + sxsi->state_load = hdd_state_load; + + sxsi->hdl = (INTPTR)p; + sxsi->totals = a[0]; + sxsi->cylinders = (UINT16)(a[0] / (a[2] * a[1])); + sxsi->size = (UINT16)a[3]; + sxsi->sectors = (UINT8)a[2]; + sxsi->surfaces = (UINT8)a[1]; + sxsi->headersize = 0; + sxsi->mediatype = gethddtype(sxsi); + + return (SUCCESS); + +sxsiope_err: + if (p != NULL) + { + nvl_close(p); + } + + return (FAILURE); +} + +#endif diff --git a/font/font.h b/font/font.h old mode 100755 new mode 100644 index 61bbf067..be4bbb26 --- a/font/font.h +++ b/font/font.h @@ -1,47 +1,47 @@ -/** - * @file font.h - * @brief CGROM and font loader - * - * @author $Author: yui $ - * @date $Date: 2011/02/23 10:11:44 $ - */ - -#define FONTMEMORYBIND // 520KBくらいメモリ削除(ぉぃ - -#define FONTMEMORYSIZE 0x84000 - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef FONTMEMORYBIND -#define fontrom (mem + FONT_ADRS) -#else -extern UINT8 __font[FONTMEMORYSIZE]; -#define fontrom (__font) -#endif - -void font_initialize(void); -void font_setchargraph(BOOL epson); -UINT8 font_load(const OEMCHAR *filename, BOOL force, const OEMCHAR* defaultfontface); - -#define HF_FILENAME "hook_fontrom.txt" -typedef void(*hook_fontrom_output_t)(const char* strOutput); -extern UINT hf_enable; -extern UINT hf_codeul, hf_count; -void hook_fontrom_defenable(void); -void hook_fontrom_defdisable(void); -void hook_fontrom_setoutput(hook_fontrom_output_t fncOutput); -void hook_fontrom_flush(void); -void hook_fontrom(UINT32 u32Address); - -#if defined(SUPPORT_TEXTHOOK) -unsigned short font_Jis2Sjis( unsigned short jis ); -unsigned short font_Jis2Sjis2( unsigned short jis ); -void font_outhooktest( wchar_t* thw ); -#endif - -#ifdef __cplusplus -} -#endif - +/** + * @file font.h + * @brief CGROM and font loader + * + * @author $Author: yui $ + * @date $Date: 2011/02/23 10:11:44 $ + */ + +#define FONTMEMORYBIND // 520KBくらいメモリ削除(ぉぃ + +#define FONTMEMORYSIZE 0x84000 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef FONTMEMORYBIND +#define fontrom (mem + FONT_ADRS) +#else +extern UINT8 __font[FONTMEMORYSIZE]; +#define fontrom (__font) +#endif + +void font_initialize(void); +void font_setchargraph(BOOL epson); +UINT8 font_load(const OEMCHAR *filename, BOOL force, const OEMCHAR* defaultfontface); + +#define HF_FILENAME "hook_fontrom.txt" +typedef void(*hook_fontrom_output_t)(const char* strOutput); +extern UINT hf_enable; +extern UINT hf_codeul, hf_count; +void hook_fontrom_defenable(void); +void hook_fontrom_defdisable(void); +void hook_fontrom_setoutput(hook_fontrom_output_t fncOutput); +void hook_fontrom_flush(void); +void hook_fontrom(UINT32 u32Address); + +#if defined(SUPPORT_TEXTHOOK) +unsigned short font_Jis2Sjis( unsigned short jis ); +unsigned short font_Jis2Sjis2( unsigned short jis ); +void font_outhooktest( wchar_t* thw ); +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/font/fontdata.c b/font/fontdata.c old mode 100755 new mode 100644 index 0c37f23c..86a41abd --- a/font/fontdata.c +++ b/font/fontdata.c @@ -1,89 +1,89 @@ -#include -#include -#include -#include "fontdata.h" -#include "fontdata.res" - - -const OEMCHAR pc88ankname[] = OEMTEXT("PC88.FNT"); -const OEMCHAR pc88knj1name[] = OEMTEXT("KANJI1.ROM"); -const OEMCHAR pc88knj2name[] = OEMTEXT("KANJI2.ROM"); -const OEMCHAR pc98fontname[] = OEMTEXT("FONT.BMP"); -const OEMCHAR pc98fontname_s[] = OEMTEXT("font.bmp"); -const OEMCHAR v98fontname[] = OEMTEXT("FONT.ROM"); -const OEMCHAR v98fontname_s[] = OEMTEXT("font.rom"); -const OEMCHAR fm7ankname[] = OEMTEXT("SUBSYS_C.ROM"); -const OEMCHAR fm7knjname[] = OEMTEXT("KANJI.ROM"); -const OEMCHAR x1ank1name[] = OEMTEXT("FNT0808.X1"); -const OEMCHAR x1ank2name[] = OEMTEXT("FNT0816.X1"); -const OEMCHAR x1knjname[] = OEMTEXT("FNT1616.X1"); -const OEMCHAR x68kfontname[] = OEMTEXT("CGROM.DAT"); -const OEMCHAR x68kfontname_s[] = OEMTEXT("cgrom.dat"); - - -static void patch29(UINT jish, const UINT8 *src) { - - UINT i; - UINT8 *p; - - p = fontrom + 0x21000 + (jish << 4); - for (i=0x21; i<0x7f; i++) { - CopyMemory(p, src, 16); - p += 0x1000; - src += 16; - } -} - -static void patch2c(void) { - - UINT i; - UINT j; -const UINT8 *p; - UINT8 *q; - - p = fontdata_2c; - q = fontrom + 0x240c0; - for (i=0x24; i<0x70; i++) { - for (j=0; j<16; j++) { - q[j + 0x800] = p[0]; - q[j + 0x000] = p[1]; - p += 2; - } - q += 0x1000; - } -} - - -// ---- - -void fontdata_ank8store(const UINT8 *ptr, UINT pos, UINT cnt) { - - UINT8 *dat; - - dat = fontrom + 0x82000 + (pos * 16); - while(cnt--) { - CopyMemory(dat, ptr, 8); - dat += 16; - ptr += 8; - } -} - -void fontdata_patch16a(void) { - - CopyMemory(fontrom + 0x80000, fontdata_16 + 0*32*16, 32*16); -} - -void fontdata_patch16b(void) { - - CopyMemory(fontrom + 0x80800, fontdata_16 + 1*32*16, 32*16); - CopyMemory(fontrom + 0x80e00, fontdata_16 + 2*32*16, 32*16); -} - -void fontdata_patchjis(void) { - - patch29(0x09, fontdata_29); - patch29(0x0a, fontdata_2a); - patch29(0x0b, fontdata_2b); - patch2c(); -} - +#include +#include +#include +#include "fontdata.h" +#include "fontdata.res" + + +const OEMCHAR pc88ankname[] = OEMTEXT("PC88.FNT"); +const OEMCHAR pc88knj1name[] = OEMTEXT("KANJI1.ROM"); +const OEMCHAR pc88knj2name[] = OEMTEXT("KANJI2.ROM"); +const OEMCHAR pc98fontname[] = OEMTEXT("FONT.BMP"); +const OEMCHAR pc98fontname_s[] = OEMTEXT("font.bmp"); +const OEMCHAR v98fontname[] = OEMTEXT("FONT.ROM"); +const OEMCHAR v98fontname_s[] = OEMTEXT("font.rom"); +const OEMCHAR fm7ankname[] = OEMTEXT("SUBSYS_C.ROM"); +const OEMCHAR fm7knjname[] = OEMTEXT("KANJI.ROM"); +const OEMCHAR x1ank1name[] = OEMTEXT("FNT0808.X1"); +const OEMCHAR x1ank2name[] = OEMTEXT("FNT0816.X1"); +const OEMCHAR x1knjname[] = OEMTEXT("FNT1616.X1"); +const OEMCHAR x68kfontname[] = OEMTEXT("CGROM.DAT"); +const OEMCHAR x68kfontname_s[] = OEMTEXT("cgrom.dat"); + + +static void patch29(UINT jish, const UINT8 *src) { + + UINT i; + UINT8 *p; + + p = fontrom + 0x21000 + (jish << 4); + for (i=0x21; i<0x7f; i++) { + CopyMemory(p, src, 16); + p += 0x1000; + src += 16; + } +} + +static void patch2c(void) { + + UINT i; + UINT j; +const UINT8 *p; + UINT8 *q; + + p = fontdata_2c; + q = fontrom + 0x240c0; + for (i=0x24; i<0x70; i++) { + for (j=0; j<16; j++) { + q[j + 0x800] = p[0]; + q[j + 0x000] = p[1]; + p += 2; + } + q += 0x1000; + } +} + + +// ---- + +void fontdata_ank8store(const UINT8 *ptr, UINT pos, UINT cnt) { + + UINT8 *dat; + + dat = fontrom + 0x82000 + (pos * 16); + while(cnt--) { + CopyMemory(dat, ptr, 8); + dat += 16; + ptr += 8; + } +} + +void fontdata_patch16a(void) { + + CopyMemory(fontrom + 0x80000, fontdata_16 + 0*32*16, 32*16); +} + +void fontdata_patch16b(void) { + + CopyMemory(fontrom + 0x80800, fontdata_16 + 1*32*16, 32*16); + CopyMemory(fontrom + 0x80e00, fontdata_16 + 2*32*16, 32*16); +} + +void fontdata_patchjis(void) { + + patch29(0x09, fontdata_29); + patch29(0x0a, fontdata_2a); + patch29(0x0b, fontdata_2b); + patch2c(); +} + diff --git a/font/fontdata.h b/font/fontdata.h old mode 100755 new mode 100644 index 3791e356..e5a79330 --- a/font/fontdata.h +++ b/font/fontdata.h @@ -1,69 +1,69 @@ - -enum { - FONT_ANK8 = 0x01, - FONT_ANK16a = 0x02, - FONT_ANK16b = 0x04, - FONT_KNJ1 = 0x08, - FONT_KNJ2 = 0x10, - FONT_KNJ3 = 0x20, - - FONTLOAD_KNJ = (FONT_KNJ1 | FONT_KNJ2 | FONT_KNJ3), - FONTLOAD_ANK = (FONT_ANK16a | FONT_ANK16b), - FONTLOAD_16 = (FONTLOAD_ANK | FONTLOAD_KNJ), - FONTLOAD_ALL = (FONT_ANK8 | FONTLOAD_16) -}; - -enum { - FONTTYPE_NONE = 0, - FONTTYPE_PC98, - FONTTYPE_V98, - FONTTYPE_PC88, - FONTTYPE_FM7, - FONTTYPE_X1, - FONTTYPE_X68 -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern const OEMCHAR pc88ankname[]; -extern const OEMCHAR pc88knj1name[]; -extern const OEMCHAR pc88knj2name[]; -extern const OEMCHAR pc98fontname[]; -extern const OEMCHAR pc98fontname_s[]; -extern const OEMCHAR v98fontname[]; -extern const OEMCHAR v98fontname_s[]; -extern const OEMCHAR fm7ankname[]; -extern const OEMCHAR fm7knjname[]; -extern const OEMCHAR x1ank1name[]; -extern const OEMCHAR x1ank2name[]; -extern const OEMCHAR x1knjname[]; -extern const OEMCHAR x68kfontname[]; -extern const OEMCHAR x68kfontname_s[]; - -extern const UINT8 fontdata_8[256*8]; -extern const UINT8 fontdata_16[3*32*16]; -extern const UINT8 fontdata_29[94*16]; -extern const UINT8 fontdata_2a[94*16]; -extern const UINT8 fontdata_2b[94*16]; -extern const UINT8 fontdata_2c[76*16*2]; - - -void fontdata_ank8store(const UINT8 *ptr, UINT pos, UINT cnt); -void fontdata_patch16a(void); -void fontdata_patch16b(void); -void fontdata_patchjis(void); - -UINT8 fontpc88_read(const OEMCHAR *filename, UINT8 loading); -UINT8 fontpc98_read(const OEMCHAR *filename, UINT8 loading); -UINT8 fontv98_read(const OEMCHAR *filename, UINT8 loading); -UINT8 fontfm7_read(const OEMCHAR *filename, UINT8 loading); -UINT8 fontx1_read(const OEMCHAR *filename, UINT8 loading); -UINT8 fontx68k_read(const OEMCHAR *filename, UINT8 loading); - -#ifdef __cplusplus -} -#endif - + +enum { + FONT_ANK8 = 0x01, + FONT_ANK16a = 0x02, + FONT_ANK16b = 0x04, + FONT_KNJ1 = 0x08, + FONT_KNJ2 = 0x10, + FONT_KNJ3 = 0x20, + + FONTLOAD_KNJ = (FONT_KNJ1 | FONT_KNJ2 | FONT_KNJ3), + FONTLOAD_ANK = (FONT_ANK16a | FONT_ANK16b), + FONTLOAD_16 = (FONTLOAD_ANK | FONTLOAD_KNJ), + FONTLOAD_ALL = (FONT_ANK8 | FONTLOAD_16) +}; + +enum { + FONTTYPE_NONE = 0, + FONTTYPE_PC98, + FONTTYPE_V98, + FONTTYPE_PC88, + FONTTYPE_FM7, + FONTTYPE_X1, + FONTTYPE_X68 +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern const OEMCHAR pc88ankname[]; +extern const OEMCHAR pc88knj1name[]; +extern const OEMCHAR pc88knj2name[]; +extern const OEMCHAR pc98fontname[]; +extern const OEMCHAR pc98fontname_s[]; +extern const OEMCHAR v98fontname[]; +extern const OEMCHAR v98fontname_s[]; +extern const OEMCHAR fm7ankname[]; +extern const OEMCHAR fm7knjname[]; +extern const OEMCHAR x1ank1name[]; +extern const OEMCHAR x1ank2name[]; +extern const OEMCHAR x1knjname[]; +extern const OEMCHAR x68kfontname[]; +extern const OEMCHAR x68kfontname_s[]; + +extern const UINT8 fontdata_8[256*8]; +extern const UINT8 fontdata_16[3*32*16]; +extern const UINT8 fontdata_29[94*16]; +extern const UINT8 fontdata_2a[94*16]; +extern const UINT8 fontdata_2b[94*16]; +extern const UINT8 fontdata_2c[76*16*2]; + + +void fontdata_ank8store(const UINT8 *ptr, UINT pos, UINT cnt); +void fontdata_patch16a(void); +void fontdata_patch16b(void); +void fontdata_patchjis(void); + +UINT8 fontpc88_read(const OEMCHAR *filename, UINT8 loading); +UINT8 fontpc98_read(const OEMCHAR *filename, UINT8 loading); +UINT8 fontv98_read(const OEMCHAR *filename, UINT8 loading); +UINT8 fontfm7_read(const OEMCHAR *filename, UINT8 loading); +UINT8 fontx1_read(const OEMCHAR *filename, UINT8 loading); +UINT8 fontx68k_read(const OEMCHAR *filename, UINT8 loading); + +#ifdef __cplusplus +} +#endif + diff --git a/font/fontfm7.c b/font/fontfm7.c old mode 100755 new mode 100644 index 14568df2..58a06991 --- a/font/fontfm7.c +++ b/font/fontfm7.c @@ -1,126 +1,126 @@ -#include -#include -#include -#include -#include "fontdata.h" - - -static void fm7ankcpy(UINT8 *dst, const UINT8 *src, int from, int to) { - - int y; -const UINT8 *p; - int ank; - - for (ank=from; ank= 0x01) && (i < 0x08)) { // 2121〜277e - p = src + ((j & 0x1f) * 0x20) + (i * 0x400); - - if (j >= 0x60) { - p += 0x2000; - } - else if (j >= 0x40) { - p += 0x4000; - } - } - else if ((i >= 0x10) && (i < 0x20)) { // 3021〜3f7e - p = src + 0x08000 + ((j & 0x1f) * 0x20) - + ((i - 0x10) * 0x400) - + (((j / 0x20) - 1) * 0x4000); - } - else if ((i >= 0x20) && (i < 0x50)) { // 4021〜4f7e - p = src + 0x14000 + ((j & 0x1f) * 0x20) - + ((i - 0x20) * 0x400) - + (((j / 0x20) - 1) * 0x4000); - } - if (p) { // 規格内コードならば - // コピーする - for (k=0; k<16; k++) { - *(q+k+0x000) = p[0]; - *(q+k+0x800) = p[1]; - p += 2; - } - } - q += 0x1000; - } - } -} - -UINT8 fontfm7_read(const OEMCHAR *filename, UINT8 loading) { - - FILEH fh; - UINT8 *work; - OEMCHAR fname[MAX_PATH]; - - work = (UINT8 *)_MALLOC(0x20000, "fm7font"); - if (work == NULL) { - goto frf7_err1; - } - file_cpyname(fname, filename, NELEMENTS(fname)); - - // 8dot ANKを読み込む必要はある? - if (loading & FONT_ANK8) { - file_cutname(fname); - file_catname(fname, fm7ankname, NELEMENTS(fname)); - fh = file_open_rb(fname); - if (fh != FILEH_INVALID) { - if (file_read(fh, work, 2048) == 2048) { - loading &= ~FONT_ANK8; - fontdata_ank8store(work + 0x100, 0x20, 0x60); - fontdata_ank8store(work + 0x500, 0xa0, 0x40); - } - file_close(fh); - } - } - - // 16dot ASCII 及び 漢字を読み込む必要はあるか? - if (loading & (FONT_ANK16a | FONT_KNJ1)) { - file_cutname(fname); - file_catname(fname, fm7knjname, NELEMENTS(fname)); - fh = file_open_rb(fname); - if (fh != FILEH_INVALID) { - if (file_read(fh, work, 0x20000) == 0x20000) { - - // 16dot ASCIIを読み込む? - if (loading & FONT_ANK16a) { - loading &= ~FONT_ANK16a; - fm7ankcpy(fontrom + 0x80200, work, 0x20, 0x7f); - fontdata_patch16a(); - } - - // 第一水準漢字を読み込む? - if (loading & FONT_KNJ1) { - loading &= ~FONT_KNJ1; - fm7knjcpy(fontrom, work, 0x01, 0x30); - fontdata_patchjis(); - } - } - file_close(fh); - } - } - _MFREE(work); - -frf7_err1: - return(loading); -} - +#include +#include +#include +#include +#include "fontdata.h" + + +static void fm7ankcpy(UINT8 *dst, const UINT8 *src, int from, int to) { + + int y; +const UINT8 *p; + int ank; + + for (ank=from; ank= 0x01) && (i < 0x08)) { // 2121〜277e + p = src + ((j & 0x1f) * 0x20) + (i * 0x400); + + if (j >= 0x60) { + p += 0x2000; + } + else if (j >= 0x40) { + p += 0x4000; + } + } + else if ((i >= 0x10) && (i < 0x20)) { // 3021〜3f7e + p = src + 0x08000 + ((j & 0x1f) * 0x20) + + ((i - 0x10) * 0x400) + + (((j / 0x20) - 1) * 0x4000); + } + else if ((i >= 0x20) && (i < 0x50)) { // 4021〜4f7e + p = src + 0x14000 + ((j & 0x1f) * 0x20) + + ((i - 0x20) * 0x400) + + (((j / 0x20) - 1) * 0x4000); + } + if (p) { // 規格内コードならば + // コピーする + for (k=0; k<16; k++) { + *(q+k+0x000) = p[0]; + *(q+k+0x800) = p[1]; + p += 2; + } + } + q += 0x1000; + } + } +} + +UINT8 fontfm7_read(const OEMCHAR *filename, UINT8 loading) { + + FILEH fh; + UINT8 *work; + OEMCHAR fname[MAX_PATH]; + + work = (UINT8 *)_MALLOC(0x20000, "fm7font"); + if (work == NULL) { + goto frf7_err1; + } + file_cpyname(fname, filename, NELEMENTS(fname)); + + // 8dot ANKを読み込む必要はある? + if (loading & FONT_ANK8) { + file_cutname(fname); + file_catname(fname, fm7ankname, NELEMENTS(fname)); + fh = file_open_rb(fname); + if (fh != FILEH_INVALID) { + if (file_read(fh, work, 2048) == 2048) { + loading &= ~FONT_ANK8; + fontdata_ank8store(work + 0x100, 0x20, 0x60); + fontdata_ank8store(work + 0x500, 0xa0, 0x40); + } + file_close(fh); + } + } + + // 16dot ASCII 及び 漢字を読み込む必要はあるか? + if (loading & (FONT_ANK16a | FONT_KNJ1)) { + file_cutname(fname); + file_catname(fname, fm7knjname, NELEMENTS(fname)); + fh = file_open_rb(fname); + if (fh != FILEH_INVALID) { + if (file_read(fh, work, 0x20000) == 0x20000) { + + // 16dot ASCIIを読み込む? + if (loading & FONT_ANK16a) { + loading &= ~FONT_ANK16a; + fm7ankcpy(fontrom + 0x80200, work, 0x20, 0x7f); + fontdata_patch16a(); + } + + // 第一水準漢字を読み込む? + if (loading & FONT_KNJ1) { + loading &= ~FONT_KNJ1; + fm7knjcpy(fontrom, work, 0x01, 0x30); + fontdata_patchjis(); + } + } + file_close(fh); + } + } + _MFREE(work); + +frf7_err1: + return(loading); +} + diff --git a/font/fontmake.c b/font/fontmake.c old mode 100755 new mode 100644 index f59490d6..f8d6356d --- a/font/fontmake.c +++ b/font/fontmake.c @@ -1,660 +1,660 @@ -#include -#include -#include -#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) -#include "oemtext.h" -#endif -#include -#include -#include -#include "fontdata.h" -#include "fontmake.h" - - -typedef struct { - UINT16 jis1; - UINT16 jis2; -} JISPAIR; - -static const BMPDATA fntinf = {2048, 2048, 1}; -static const UINT8 fntpal[8] = {0x00,0x00,0x00,0x00, 0xff,0xff,0xff,0x00}; - -static const UINT8 deltable[] = { - // del del del del del - 0x0f, 0x5f, 0, - 0x01, 0x10, 0x1a, 0x21, 0x3b, 0x41, 0x5b, 0x5f, 0, - 0x54, 0x5f, 0, - 0x57, 0x5f, 0, - 0x19, 0x21, 0x39, 0x5f, 0, - 0x22, 0x31, 0x52, 0x5f, 0, - 0x01, 0x5f, 0, - 0x01, 0x5f, 0, - 0x01, 0x5f, 0, - 0x01, 0x5f, 0, - 0x01, 0x5f, 0, - 0x1f, 0x20, 0x37, 0x3f, 0x5d, 0x5f, 0}; - -static const JISPAIR jis7883[] = { - {0x3646, 0x7421}, /* 尭:堯 */ {0x4b6a, 0x7422}, /* 槙:槇 */ - {0x4d5a, 0x7423}, /* 遥:遙 */ {0x596a, 0x7424}, /* 搖:瑤 */ }; - -static const JISPAIR jis8390[] = { - {0x724d, 0x3033}, /* 鰺:鯵 */ {0x7274, 0x3229}, /* 鶯:鴬 */ - {0x695a, 0x3342}, /* 蠣:蛎 */ {0x5978, 0x3349}, /* 攪:撹 */ - {0x635e, 0x3376}, /* 竈:竃 */ {0x5e75, 0x3443}, /* 灌:潅 */ - {0x6b5d, 0x3452}, /* 諫:諌 */ {0x7074, 0x375b}, /* 頸:頚 */ - {0x6268, 0x395c}, /* 礦:砿 */ {0x6922, 0x3c49}, /* 蘂:蕊 */ - {0x7057, 0x3f59}, /* 靱:靭 */ {0x6c4d, 0x4128}, /* 賤:賎 */ - {0x5464, 0x445b}, /* 壺:壷 */ {0x626a, 0x4557}, /* 礪:砺 */ - {0x5b6d, 0x456e}, /* 檮:梼 */ {0x5e39, 0x4573}, /* 濤:涛 */ - {0x6d6e, 0x4676}, /* 邇:迩 */ {0x6a24, 0x4768}, /* 蠅:蝿 */ - {0x5b58, 0x4930}, /* 檜:桧 */ {0x5056, 0x4b79}, /* 儘:侭 */ - {0x692e, 0x4c79}, /* 藪:薮 */ {0x6446, 0x4f36}, /* 籠:篭 */ }; - - -static UINT16 cnvjis(UINT16 jis, const JISPAIR *tbl, UINT tblsize) { - -const JISPAIR *tblterm; - - tblterm = (JISPAIR *)(((UINT8 *)tbl) + tblsize); - while(tbl < tblterm) { - if (jis == tbl->jis1) { - return(tbl->jis2); - } - else if (jis == tbl->jis2) { - return(tbl->jis1); - } - tbl++; - } - return(jis); -} - -static BOOL ispc98jis(UINT16 jis) { - -const UINT8 *p; - UINT tmp; - - switch(jis >> 8) { - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2a: - case 0x2b: - case 0x2c: - case 0x2d: - p = deltable; - tmp = (jis >> 8) - 0x22; - while(tmp) { - tmp--; - while(*p++) { } - } - tmp = (jis & 0xff) - 0x20; - while(*p) { - if ((tmp >= (UINT)p[0]) && (tmp < (UINT)p[1])) { - return(FALSE); - } - p += 2; - } - break; - - case 0x4f: - tmp = jis & 0xff; - if (tmp >= 0x54) { - return(FALSE); - } - break; - - case 0x7c: - tmp = jis & 0xff; - if ((tmp == 0x6f) || (tmp == 0x70)) { - return(FALSE); - } - break; - - case 0x2e: - case 0x2f: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: - case 0x7d: - case 0x7e: - case 0x7f: - return(FALSE); - } - return(TRUE); -} - -static void setank(UINT8 *ptr, void *fnt, UINT from, UINT to) { - - char work[2]; - FNTDAT dat; -const UINT8 *p; - UINT8 *q; - int width; - int height; - UINT8 bit; - int i; -#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) - OEMCHAR oemwork[4]; -#endif - - ptr += (2048 * (2048 / 8)) + from; - work[1] = '\0'; - while(from < to) { - work[0] = (char)from; -#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) - oemtext_sjistooem(oemwork, NELEMENTS(oemwork), work, -1); - dat = fontmng_get(fnt, oemwork); -#else - dat = fontmng_get(fnt, work); -#endif - if (dat) { - width = MIN(dat->width, 8); - height = MIN(dat->height, 16); - p = (UINT8 *)(dat + 1); - q = ptr; - while(height > 0) { - height--; - q -= (2048 / 8); - bit = 0xff; - for (i=0; i> i); - } - } - *q = bit; - p += dat->width; - } - } - from++; - ptr++; - } -} - -static void patchank(UINT8 *ptr, const UINT8 *fnt, UINT from) { - - int r; - int y; - - ptr += (2048 * (2048 / 8)) + from; - r = 0x20; - do { - y = 16; - do { - ptr -= (2048 / 8); - *ptr = ~(*fnt++); - } while(--y); - ptr += (16 * (2048 / 8)) + 1; - } while(--r); -} - -static void setjis(UINT8 *ptr, void *fnt) { - - char work[4]; - UINT16 h; - UINT16 l; - UINT16 jis; - UINT sjis; - FNTDAT dat; -const UINT8 *p; - UINT8 *q; - int width; - int height; - UINT16 bit; - int i; -#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) - OEMCHAR oemwork[4]; -#endif - - work[2] = '\0'; - ptr += ((0x80 - 0x21) * 16 * (2048 / 8)) + 2; - for (h=0x2100; h<0x8000; h+=0x100) { - for (l=0x21; l<0x7f; l++) { - jis = h + l; - if (ispc98jis(jis)) { - jis = cnvjis(jis, jis7883, sizeof(jis7883)); - jis = cnvjis(jis, jis8390, sizeof(jis8390)); - sjis = jis2sjis(jis); - work[0] = (UINT8)(sjis >> 8); - work[1] = (UINT8)sjis; -#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) - oemtext_sjistooem(oemwork, NELEMENTS(oemwork), work, -1); - dat = fontmng_get(fnt, oemwork); -#else - dat = fontmng_get(fnt, work); -#endif - if (dat) { - width = MIN(dat->width, 16); - height = MIN(dat->height, 16); - p = (UINT8 *)(dat + 1); - q = ptr; - while(height > 0) { - height--; - q -= (2048 / 8); - bit = 0xffff; - for (i=0; i> i); - } - } - q[0] = (UINT8)(bit >> 8); - q[1] = (UINT8)bit; - p += dat->width; - } - } - } - ptr -= 16 * (2048 / 8); - } - ptr += ((0x7f - 0x21) * 16 * (2048 / 8)) + 2; - } -} - -static void patchextank(UINT8 *ptr, const UINT8 *fnt, UINT pos) { - - UINT r; - - ptr += ((0x80 - 0x21) * 16 * (2048 / 8)) + (pos * 2); - r = 0x5e * 16; - do { - ptr -= (2048 / 8); - *ptr = ~(*fnt++); - } while(--r); -} - -static void patchextfnt(UINT8 *ptr, const UINT8 *fnt) { // 2c24-2c6f - - UINT r; - - ptr += ((0x80 - 0x24) * 16 * (2048 / 8)) + (0x0c * 2); - r = 0x4c * 16; - do { - ptr -= (2048 / 8); - ptr[0] = (UINT8)(~fnt[0]); - ptr[1] = (UINT8)(~fnt[1]); - fnt += 2; - } while(--r); -} - -#define COPYGLYPH_LEFTPART 0x1 // 16 -> 8のとき縮小せず左半分をコピー -#define COPYGLYPH_RIGHTPART 0x2 // 16 -> 8のとき縮小せず右半分をコピー -#define COPYGLYPH_ADJUSTPART 0x4 // 16 -> 8のときデータがあるX座標を起点にコピー -#define COPYGLYPH_ADJUSTPARTR 0x8 // 16 -> 8のときデータがあるX座標を起点にコピー(右揃え) -#define COPYGLYPH_WITHVMARK 0x10 // コピー後に濁点を付ける -#define COPYGLYPH_WITHPMARK 0x20 // コピー後に半濁点を付ける -#define COPYGLYPH_REVERSEXSH1 0x40 // 左右反転して1pxシフトする -#define COPYGLYPH_7TO6 0x80 // 幅を1px縮小 - -// 文字コピー -static void copyglyph(UINT8* ptr, UINT srccode, int srcwidth, UINT dstcode, int dstwidth, int copyflag) { - - int i; - int stride = 2048 / 8; - int stridedst = 2048 / 8; - UINT8 reversebuf[16 * 2]; - UINT8* srcptr; - UINT8* dstptr; - UINT8* dstptrbase; - if (srccode <= 0xff) { - srcptr = ptr + (2048 / 16 - 1) * (2048 / 8 * 16) + srccode; - } - else { - int jisy = (srccode & 0xff); - int jisx = ((srccode >> 8) & 0xff) - 0x20; - srcptr = ptr + (2048 / 16 - 1 - jisy) * (2048 / 8 * 16) + jisx * 2; - } - if (dstcode <= 0xff) { - dstptr = ptr + (2048 / 16 - 1) * (2048 / 8 * 16) + dstcode; - } - else { - int jisy = (dstcode & 0xff); - int jisx = ((dstcode >> 8) & 0xff) - 0x20; - dstptr = ptr + (2048 / 16 - 1 - jisy) * (2048 / 8 * 16) + jisx * 2; - } - dstptrbase = dstptr; - if (copyflag & COPYGLYPH_REVERSEXSH1) { - memset(reversebuf, 0xff, sizeof(reversebuf)); - if (srcwidth == 8) { - UINT8 tmp; - UINT8 bitstate = 0xff; - for (i = 0; i < 16; i++) { - tmp = *srcptr; - tmp = ((tmp & 0x0f) << 4) | ((tmp >> 4) & 0x0f); - tmp = ((tmp & 0x33) << 2) | ((tmp >> 2) & 0x33); - tmp = ((tmp & 0x55) << 1) | ((tmp >> 1) & 0x55); - bitstate &= tmp; - reversebuf[i * 2] = tmp; - srcptr += stride; - } - if (bitstate & 0x01) { - // 右端が空いていれば1pxずらす - for (i = 0; i < 16; i++) { - *(UINT8*)(reversebuf + i * 2) = (*(UINT8*)(reversebuf + i * 2) >> 1) | 0x80; - } - } - } - else if (srcwidth == 16) { - UINT16 tmp; - UINT16 bitstate = 0xffff; - for (i = 0; i < 16; i++) { - tmp = *((UINT16*)srcptr); - tmp = ((tmp & 0x00ff) << 8) | ((tmp >> 8) & 0x00ff); - tmp = ((tmp & 0x0f0f) << 4) | ((tmp >> 4) & 0x0f0f); - tmp = ((tmp & 0x3333) << 2) | ((tmp >> 2) & 0x3333); - tmp = ((tmp & 0x5555) << 1) | ((tmp >> 1) & 0x5555); - bitstate &= tmp; - reversebuf[i * 2] = (tmp >> 8) & 0xff; - reversebuf[i * 2 + 1] = tmp & 0xff; - srcptr += stride; - } - if (bitstate & 0x0001) { - // 右端が空いていれば1pxずらす - for (i = 0; i < 16; i++) { - *((UINT16*)(reversebuf + i * 2)) = (*((UINT16*)(reversebuf + i * 2)) >> 1) | 0x8000; - } - } - } - srcptr = reversebuf; - stride = 2; - } - if (srcwidth == 8 && dstwidth == 8) { - // 半角→半角 - for (i = 0; i < 16; i++) { - *dstptr = *srcptr; - srcptr += stride; - dstptr += stridedst; - } - } - else if (srcwidth == 16 && dstwidth == 16) { - // 全角→全角 - for (i = 0; i < 16; i++) { - *dstptr = *srcptr; - *(dstptr + 1) = *(srcptr + 1); - srcptr += stride; - dstptr += stridedst; - } - } - else if (srcwidth == 8 && dstwidth == 16) { - // 半角→全角(右側空白) - for (i = 0; i < 16; i++) { - *dstptr = *srcptr; - *(dstptr + 1) = 0xff; - srcptr += stride; - dstptr += stridedst; - } - } - else if (srcwidth == 16 && dstwidth == 8) { - // 全角→半角 - if (copyflag & COPYGLYPH_LEFTPART) { - // 左側のみ - for (i = 0; i < 16; i++) { - *dstptr = *srcptr; - srcptr += stride; - dstptr += stridedst; - } - } - else if(copyflag & COPYGLYPH_RIGHTPART) { - // 右側のみ - for (i = 0; i < 16; i++) { - *dstptr = *(srcptr + 1); - srcptr += stride; - dstptr += stridedst; - } - } - else if (copyflag & (COPYGLYPH_ADJUSTPART | COPYGLYPH_ADJUSTPARTR)) { - // データがあるX座標を起点 - int beginX = 0; - int endX = 0; - UINT16 bitstate = 0xffff; - UINT16 bitstateTmp; - UINT8* srcptr2 = srcptr; - for (i = 0; i < 16; i++) { - bitstate &= (UINT16)(*srcptr2) << 8 | *(srcptr2 + 1); - srcptr2 += stride; - } - bitstateTmp = bitstate; - for (beginX = 0; beginX < 16; beginX++) { - if (!(bitstateTmp & 0x8000)) break; - bitstateTmp <<= 1; - } - endX = 16; - bitstateTmp = bitstate; - for (endX = 16; endX > beginX; endX--) { - if (!(bitstateTmp & 0x1)) break; - bitstateTmp >>= 1; - } - if (copyflag & COPYGLYPH_ADJUSTPARTR) { - beginX -= 8 - (endX - beginX); // 右揃えにする - if (beginX < 0) beginX = 0; - } - else { - if (endX - beginX < 8 && beginX > 0) beginX--; // 一番左端は避ける - } - for (i = 0; i < 16; i++) { - UINT8 src1 = *srcptr; - UINT8 src2 = *(srcptr + 1); - if (beginX < 8) { - src1 = src1 << beginX; - src1 |= src2 >> (8 - beginX); - } - else { - src1 = src2 << (beginX - 8); - src1 |= 0xff >> (8 - (beginX - 8)); - } - *dstptr = src1; - srcptr += stride; - dstptr += stridedst; - } - } - else { - // 半幅化 - for (i = 0; i < 16; i++) { - UINT8 src1 = *srcptr; - UINT8 src2 = *(srcptr + 1); - src1 &= src1 >> 1; - src1 &= 0x55; - src2 &= src2 >> 1; - src2 &= 0x55; - *dstptr = ((src1 << 1) & 0x80) | ((src1 << 2) & 0x40) | ((src1 << 3) & 0x20) | ((src1 << 4) & 0x10) | - ((src2 >> 3) & 0x08) | ((src2 >> 2) & 0x04) | ((src2 >> 1) & 0x02) | ((src2 >> 0) & 0x01); - srcptr += stride; - dstptr += stridedst; - } - } - } - dstptr = dstptrbase; - if (copyflag & COPYGLYPH_WITHVMARK) { - dstptr += stridedst * 14; - if (dstwidth == 16) { - dstptr++; // 右側につける - } - *dstptr &= 0xfa; - *dstptr |= 0x02; - dstptr += stridedst; - *dstptr &= 0xfa; - *dstptr |= 0x02; - } - else if (copyflag & COPYGLYPH_WITHPMARK) { - dstptr += stridedst * 12; - if (dstwidth == 16) { - dstptr++; // 右側につける - } - *dstptr &= 0xfd; - *dstptr |= 0x05; - dstptr += stridedst; - *dstptr &= 0xfa; - *dstptr |= 0x02; - dstptr += stridedst; - *dstptr &= 0xfa; - *dstptr |= 0x02; - dstptr += stridedst; - *dstptr &= 0xfd; - *dstptr |= 0x05; - } - dstptr = dstptrbase; - if (copyflag & COPYGLYPH_7TO6) { - memset(reversebuf, 0xff, sizeof(reversebuf)); - if (dstwidth == 8) { - UINT8 tmp; - UINT8 bitstate = 0xff; - UINT8 bitsame = 0x00; - for (i = 0; i < 16; i++) { - tmp = *dstptr; - bitstate &= tmp; - bitsame |= tmp ^ (tmp << 1); - dstptr += stridedst; - } - if (bitstate & 0x01) { - // 右端が空いていれば何もしなくてよい - } - else if ((bitstate & 0xc0) == 0xc0) { - // 左端が2px空いていれば左へ1pxずらす - dstptr = dstptrbase; - for (i = 0; i < 16; i++) { - *dstptr = (*dstptr << 1) | 0x01; - dstptr += stridedst; - } - } - else { - // 中央に同じ内容が連続していたらそこを削る - dstptr = dstptrbase; - if (!(bitsame & 0x08)) { - for (i = 0; i < 16; i++) { - tmp = *dstptr; - tmp = (tmp & 0xf0) | ((tmp & 0x7) << 1) | 0x01; - *dstptr = tmp; - dstptr += stridedst; - } - } - else if (!(bitsame & 0x10)) { - for (i = 0; i < 16; i++) { - tmp = *dstptr; - tmp = (tmp & 0xe0) | ((tmp & 0xf) << 1) | 0x01; - *dstptr = tmp; - dstptr += stridedst; - } - } - } - } - else if (srcwidth == 16) { - // 未実装 - } - } -} - -void makepc98bmp(const OEMCHAR *filename, const OEMCHAR* fontface) { - - void *fnt; - BMPFILE bf; - UINT size; - BMPINFO bi; - UINT8 *ptr; - FILEH fh; - BOOL r; - int i; - -#if defined(FDAT_SHIFTJIS) - fnt = fontmng_create(16, FDAT_SHIFTJIS, fontface); -#else - fnt = fontmng_create(16, 0, fontface); -#endif - if (fnt == NULL) { - goto mfnt_err1; - } - size = bmpdata_setinfo(&bi, &fntinf); - bmpdata_sethead(&bf, &bi); - ptr = (UINT8 *)_MALLOC(size, filename); - if (ptr == NULL) { - goto mfnt_err2; - } - FillMemory(ptr, size, 0xff); - setank(ptr, fnt, 0x20, 0x7f); - setank(ptr, fnt, 0xa1, 0xe0); - patchank(ptr, fontdata_16 + 0*32*16, 0x00); - patchank(ptr, fontdata_16 + 1*32*16, 0x80); - patchank(ptr, fontdata_16 + 2*32*16, 0xe0); - setjis(ptr, fnt); - patchextank(ptr, fontdata_2b, 0x0b); - patchextfnt(ptr, fontdata_2c); -#ifdef USE_BUILTIN_FONT - // ねこー内蔵代替フォント - patchextank(ptr, fontdata_29, 0x09); - patchextank(ptr, fontdata_2a, 0x0a); -#else - // 指定フォントから擬似的に生成 - copyglyph(ptr, 0x315f, 16, 0xf1, 8, 0); // 円 - copyglyph(ptr, 0x472f, 16, 0xf2, 8, 0); // 年 - copyglyph(ptr, 0x376e, 16, 0xf3, 8, 0); // 月 - copyglyph(ptr, 0x467c, 16, 0xf4, 8, 0); // 日 - copyglyph(ptr, 0x3b7e, 16, 0xf5, 8, 0); // 時 - copyglyph(ptr, 0x4a2c, 16, 0xf6, 8, 0); // 分 - copyglyph(ptr, 0x4943, 16, 0xf7, 8, 0); // 秒 - for (i = 0; i < 0x7f - 0x21; i++) { - copyglyph(ptr, 0x21 + i, 8, 0x2921 + i, 8, 0); // 数字英字など - } - for (i = 0x20; i < 0x39; i++) { - copyglyph(ptr, 0x21 + i, 8, 0x2921 + i, 8, COPYGLYPH_7TO6); // ascii部分だけ可能なら狭幅にする - } - for (i = 0x40; i < 0x59; i++) { - copyglyph(ptr, 0x21 + i, 8, 0x2921 + i, 8, COPYGLYPH_7TO6); // ascii部分だけ可能なら狭幅にする - } - for (i = 0; i < 0x60 - 0x21; i++) { - copyglyph(ptr, 0xa1 + i, 8, 0x2a21 + i, 8, 0); // カナなど - } - copyglyph(ptr, 0x2570, 16, 0x2a60, 8, 0); // ヰ - copyglyph(ptr, 0x2571, 16, 0x2a61, 8, 0); // ヱ - copyglyph(ptr, 0x256e, 16, 0x2a62, 8, 0); // ヮ - copyglyph(ptr, 0x2575, 16, 0x2a63, 8, 0); // ヵ - copyglyph(ptr, 0x2576, 16, 0x2a64, 8, 0); // ヶ - copyglyph(ptr, 0xb3, 8, 0x2a65, 8, COPYGLYPH_WITHVMARK); // ヴ - for (i = 0; i < 15; i++) { - // ガ行、ザ行、ダ行 - copyglyph(ptr, 0xb6 + i, 8, 0x2a66 + i, 8, COPYGLYPH_WITHVMARK); - } - for (i = 0; i < 5; i++) { - // バ行、パ行 - copyglyph(ptr, 0xca + i, 8, 0x2a75 + i * 2, 8, COPYGLYPH_WITHVMARK); - copyglyph(ptr, 0xca + i, 8, 0x2a75 + i * 2 + 1, 8, COPYGLYPH_WITHPMARK); - } - copyglyph(ptr, 0x214c, 16, 0x2b74, 8, COPYGLYPH_ADJUSTPARTR); // 〔 - copyglyph(ptr, 0x214d, 16, 0x2b75, 8, COPYGLYPH_ADJUSTPART); // 〕 - copyglyph(ptr, 0x2152, 16, 0x2b76, 8, COPYGLYPH_ADJUSTPARTR); // 〈 - copyglyph(ptr, 0x2153, 16, 0x2b77, 8, COPYGLYPH_ADJUSTPART); // 〉 - copyglyph(ptr, 0x2154, 16, 0x2b78, 8, COPYGLYPH_ADJUSTPARTR); // 《 - copyglyph(ptr, 0x2155, 16, 0x2b79, 8, COPYGLYPH_ADJUSTPART); // 》 - copyglyph(ptr, 0x2158, 16, 0x2b7a, 8, COPYGLYPH_ADJUSTPARTR); // 『 - copyglyph(ptr, 0x2159, 16, 0x2b7b, 8, COPYGLYPH_ADJUSTPART); // 』 - copyglyph(ptr, 0x215a, 16, 0x2b7c, 8, COPYGLYPH_ADJUSTPARTR); // 【 - copyglyph(ptr, 0x215b, 16, 0x2b7d, 8, COPYGLYPH_ADJUSTPART); // 】 - copyglyph(ptr, '-', 8, 0x2b7e, 8, 0); // - - copyglyph(ptr, '/', 8, 0xfc, 8, COPYGLYPH_REVERSEXSH1); // バックスラッシュ -#endif - - fh = file_create(filename); - if (fh == FILEH_INVALID) { - goto mfnt_err3; - } - r = (file_write(fh, &bf, sizeof(bf)) == sizeof(bf)) && - (file_write(fh, &bi, sizeof(bi)) == sizeof(bi)) && - (file_write(fh, fntpal, sizeof(fntpal)) == sizeof(fntpal)) && - (file_write(fh, ptr, size) == size); - file_close(fh); - if (!r) { - file_delete(filename); - } - -mfnt_err3: - _MFREE(ptr); - -mfnt_err2: - fontmng_destroy(fnt); - -mfnt_err1: - return; -} +#include +#include +#include +#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) +#include "oemtext.h" +#endif +#include +#include +#include +#include "fontdata.h" +#include "fontmake.h" + + +typedef struct { + UINT16 jis1; + UINT16 jis2; +} JISPAIR; + +static const BMPDATA fntinf = {2048, 2048, 1}; +static const UINT8 fntpal[8] = {0x00,0x00,0x00,0x00, 0xff,0xff,0xff,0x00}; + +static const UINT8 deltable[] = { + // del del del del del + 0x0f, 0x5f, 0, + 0x01, 0x10, 0x1a, 0x21, 0x3b, 0x41, 0x5b, 0x5f, 0, + 0x54, 0x5f, 0, + 0x57, 0x5f, 0, + 0x19, 0x21, 0x39, 0x5f, 0, + 0x22, 0x31, 0x52, 0x5f, 0, + 0x01, 0x5f, 0, + 0x01, 0x5f, 0, + 0x01, 0x5f, 0, + 0x01, 0x5f, 0, + 0x01, 0x5f, 0, + 0x1f, 0x20, 0x37, 0x3f, 0x5d, 0x5f, 0}; + +static const JISPAIR jis7883[] = { + {0x3646, 0x7421}, /* 尭:堯 */ {0x4b6a, 0x7422}, /* 槙:槇 */ + {0x4d5a, 0x7423}, /* 遥:遙 */ {0x596a, 0x7424}, /* 搖:瑤 */ }; + +static const JISPAIR jis8390[] = { + {0x724d, 0x3033}, /* 鰺:鯵 */ {0x7274, 0x3229}, /* 鶯:鴬 */ + {0x695a, 0x3342}, /* 蠣:蛎 */ {0x5978, 0x3349}, /* 攪:撹 */ + {0x635e, 0x3376}, /* 竈:竃 */ {0x5e75, 0x3443}, /* 灌:潅 */ + {0x6b5d, 0x3452}, /* 諫:諌 */ {0x7074, 0x375b}, /* 頸:頚 */ + {0x6268, 0x395c}, /* 礦:砿 */ {0x6922, 0x3c49}, /* 蘂:蕊 */ + {0x7057, 0x3f59}, /* 靱:靭 */ {0x6c4d, 0x4128}, /* 賤:賎 */ + {0x5464, 0x445b}, /* 壺:壷 */ {0x626a, 0x4557}, /* 礪:砺 */ + {0x5b6d, 0x456e}, /* 檮:梼 */ {0x5e39, 0x4573}, /* 濤:涛 */ + {0x6d6e, 0x4676}, /* 邇:迩 */ {0x6a24, 0x4768}, /* 蠅:蝿 */ + {0x5b58, 0x4930}, /* 檜:桧 */ {0x5056, 0x4b79}, /* 儘:侭 */ + {0x692e, 0x4c79}, /* 藪:薮 */ {0x6446, 0x4f36}, /* 籠:篭 */ }; + + +static UINT16 cnvjis(UINT16 jis, const JISPAIR *tbl, UINT tblsize) { + +const JISPAIR *tblterm; + + tblterm = (JISPAIR *)(((UINT8 *)tbl) + tblsize); + while(tbl < tblterm) { + if (jis == tbl->jis1) { + return(tbl->jis2); + } + else if (jis == tbl->jis2) { + return(tbl->jis1); + } + tbl++; + } + return(jis); +} + +static BOOL ispc98jis(UINT16 jis) { + +const UINT8 *p; + UINT tmp; + + switch(jis >> 8) { + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2d: + p = deltable; + tmp = (jis >> 8) - 0x22; + while(tmp) { + tmp--; + while(*p++) { } + } + tmp = (jis & 0xff) - 0x20; + while(*p) { + if ((tmp >= (UINT)p[0]) && (tmp < (UINT)p[1])) { + return(FALSE); + } + p += 2; + } + break; + + case 0x4f: + tmp = jis & 0xff; + if (tmp >= 0x54) { + return(FALSE); + } + break; + + case 0x7c: + tmp = jis & 0xff; + if ((tmp == 0x6f) || (tmp == 0x70)) { + return(FALSE); + } + break; + + case 0x2e: + case 0x2f: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x7d: + case 0x7e: + case 0x7f: + return(FALSE); + } + return(TRUE); +} + +static void setank(UINT8 *ptr, void *fnt, UINT from, UINT to) { + + char work[2]; + FNTDAT dat; +const UINT8 *p; + UINT8 *q; + int width; + int height; + UINT8 bit; + int i; +#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) + OEMCHAR oemwork[4]; +#endif + + ptr += (2048 * (2048 / 8)) + from; + work[1] = '\0'; + while(from < to) { + work[0] = (char)from; +#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) + oemtext_sjistooem(oemwork, NELEMENTS(oemwork), work, -1); + dat = fontmng_get(fnt, oemwork); +#else + dat = fontmng_get(fnt, work); +#endif + if (dat) { + width = MIN(dat->width, 8); + height = MIN(dat->height, 16); + p = (UINT8 *)(dat + 1); + q = ptr; + while(height > 0) { + height--; + q -= (2048 / 8); + bit = 0xff; + for (i=0; i> i); + } + } + *q = bit; + p += dat->width; + } + } + from++; + ptr++; + } +} + +static void patchank(UINT8 *ptr, const UINT8 *fnt, UINT from) { + + int r; + int y; + + ptr += (2048 * (2048 / 8)) + from; + r = 0x20; + do { + y = 16; + do { + ptr -= (2048 / 8); + *ptr = ~(*fnt++); + } while(--y); + ptr += (16 * (2048 / 8)) + 1; + } while(--r); +} + +static void setjis(UINT8 *ptr, void *fnt) { + + char work[4]; + UINT16 h; + UINT16 l; + UINT16 jis; + UINT sjis; + FNTDAT dat; +const UINT8 *p; + UINT8 *q; + int width; + int height; + UINT16 bit; + int i; +#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) + OEMCHAR oemwork[4]; +#endif + + work[2] = '\0'; + ptr += ((0x80 - 0x21) * 16 * (2048 / 8)) + 2; + for (h=0x2100; h<0x8000; h+=0x100) { + for (l=0x21; l<0x7f; l++) { + jis = h + l; + if (ispc98jis(jis)) { + jis = cnvjis(jis, jis7883, sizeof(jis7883)); + jis = cnvjis(jis, jis8390, sizeof(jis8390)); + sjis = jis2sjis(jis); + work[0] = (UINT8)(sjis >> 8); + work[1] = (UINT8)sjis; +#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) + oemtext_sjistooem(oemwork, NELEMENTS(oemwork), work, -1); + dat = fontmng_get(fnt, oemwork); +#else + dat = fontmng_get(fnt, work); +#endif + if (dat) { + width = MIN(dat->width, 16); + height = MIN(dat->height, 16); + p = (UINT8 *)(dat + 1); + q = ptr; + while(height > 0) { + height--; + q -= (2048 / 8); + bit = 0xffff; + for (i=0; i> i); + } + } + q[0] = (UINT8)(bit >> 8); + q[1] = (UINT8)bit; + p += dat->width; + } + } + } + ptr -= 16 * (2048 / 8); + } + ptr += ((0x7f - 0x21) * 16 * (2048 / 8)) + 2; + } +} + +static void patchextank(UINT8 *ptr, const UINT8 *fnt, UINT pos) { + + UINT r; + + ptr += ((0x80 - 0x21) * 16 * (2048 / 8)) + (pos * 2); + r = 0x5e * 16; + do { + ptr -= (2048 / 8); + *ptr = ~(*fnt++); + } while(--r); +} + +static void patchextfnt(UINT8 *ptr, const UINT8 *fnt) { // 2c24-2c6f + + UINT r; + + ptr += ((0x80 - 0x24) * 16 * (2048 / 8)) + (0x0c * 2); + r = 0x4c * 16; + do { + ptr -= (2048 / 8); + ptr[0] = (UINT8)(~fnt[0]); + ptr[1] = (UINT8)(~fnt[1]); + fnt += 2; + } while(--r); +} + +#define COPYGLYPH_LEFTPART 0x1 // 16 -> 8のとき縮小せず左半分をコピー +#define COPYGLYPH_RIGHTPART 0x2 // 16 -> 8のとき縮小せず右半分をコピー +#define COPYGLYPH_ADJUSTPART 0x4 // 16 -> 8のときデータがあるX座標を起点にコピー +#define COPYGLYPH_ADJUSTPARTR 0x8 // 16 -> 8のときデータがあるX座標を起点にコピー(右揃え) +#define COPYGLYPH_WITHVMARK 0x10 // コピー後に濁点を付ける +#define COPYGLYPH_WITHPMARK 0x20 // コピー後に半濁点を付ける +#define COPYGLYPH_REVERSEXSH1 0x40 // 左右反転して1pxシフトする +#define COPYGLYPH_7TO6 0x80 // 幅を1px縮小 + +// 文字コピー +static void copyglyph(UINT8* ptr, UINT srccode, int srcwidth, UINT dstcode, int dstwidth, int copyflag) { + + int i; + int stride = 2048 / 8; + int stridedst = 2048 / 8; + UINT8 reversebuf[16 * 2]; + UINT8* srcptr; + UINT8* dstptr; + UINT8* dstptrbase; + if (srccode <= 0xff) { + srcptr = ptr + (2048 / 16 - 1) * (2048 / 8 * 16) + srccode; + } + else { + int jisy = (srccode & 0xff); + int jisx = ((srccode >> 8) & 0xff) - 0x20; + srcptr = ptr + (2048 / 16 - 1 - jisy) * (2048 / 8 * 16) + jisx * 2; + } + if (dstcode <= 0xff) { + dstptr = ptr + (2048 / 16 - 1) * (2048 / 8 * 16) + dstcode; + } + else { + int jisy = (dstcode & 0xff); + int jisx = ((dstcode >> 8) & 0xff) - 0x20; + dstptr = ptr + (2048 / 16 - 1 - jisy) * (2048 / 8 * 16) + jisx * 2; + } + dstptrbase = dstptr; + if (copyflag & COPYGLYPH_REVERSEXSH1) { + memset(reversebuf, 0xff, sizeof(reversebuf)); + if (srcwidth == 8) { + UINT8 tmp; + UINT8 bitstate = 0xff; + for (i = 0; i < 16; i++) { + tmp = *srcptr; + tmp = ((tmp & 0x0f) << 4) | ((tmp >> 4) & 0x0f); + tmp = ((tmp & 0x33) << 2) | ((tmp >> 2) & 0x33); + tmp = ((tmp & 0x55) << 1) | ((tmp >> 1) & 0x55); + bitstate &= tmp; + reversebuf[i * 2] = tmp; + srcptr += stride; + } + if (bitstate & 0x01) { + // 右端が空いていれば1pxずらす + for (i = 0; i < 16; i++) { + *(UINT8*)(reversebuf + i * 2) = (*(UINT8*)(reversebuf + i * 2) >> 1) | 0x80; + } + } + } + else if (srcwidth == 16) { + UINT16 tmp; + UINT16 bitstate = 0xffff; + for (i = 0; i < 16; i++) { + tmp = *((UINT16*)srcptr); + tmp = ((tmp & 0x00ff) << 8) | ((tmp >> 8) & 0x00ff); + tmp = ((tmp & 0x0f0f) << 4) | ((tmp >> 4) & 0x0f0f); + tmp = ((tmp & 0x3333) << 2) | ((tmp >> 2) & 0x3333); + tmp = ((tmp & 0x5555) << 1) | ((tmp >> 1) & 0x5555); + bitstate &= tmp; + reversebuf[i * 2] = (tmp >> 8) & 0xff; + reversebuf[i * 2 + 1] = tmp & 0xff; + srcptr += stride; + } + if (bitstate & 0x0001) { + // 右端が空いていれば1pxずらす + for (i = 0; i < 16; i++) { + *((UINT16*)(reversebuf + i * 2)) = (*((UINT16*)(reversebuf + i * 2)) >> 1) | 0x8000; + } + } + } + srcptr = reversebuf; + stride = 2; + } + if (srcwidth == 8 && dstwidth == 8) { + // 半角→半角 + for (i = 0; i < 16; i++) { + *dstptr = *srcptr; + srcptr += stride; + dstptr += stridedst; + } + } + else if (srcwidth == 16 && dstwidth == 16) { + // 全角→全角 + for (i = 0; i < 16; i++) { + *dstptr = *srcptr; + *(dstptr + 1) = *(srcptr + 1); + srcptr += stride; + dstptr += stridedst; + } + } + else if (srcwidth == 8 && dstwidth == 16) { + // 半角→全角(右側空白) + for (i = 0; i < 16; i++) { + *dstptr = *srcptr; + *(dstptr + 1) = 0xff; + srcptr += stride; + dstptr += stridedst; + } + } + else if (srcwidth == 16 && dstwidth == 8) { + // 全角→半角 + if (copyflag & COPYGLYPH_LEFTPART) { + // 左側のみ + for (i = 0; i < 16; i++) { + *dstptr = *srcptr; + srcptr += stride; + dstptr += stridedst; + } + } + else if(copyflag & COPYGLYPH_RIGHTPART) { + // 右側のみ + for (i = 0; i < 16; i++) { + *dstptr = *(srcptr + 1); + srcptr += stride; + dstptr += stridedst; + } + } + else if (copyflag & (COPYGLYPH_ADJUSTPART | COPYGLYPH_ADJUSTPARTR)) { + // データがあるX座標を起点 + int beginX = 0; + int endX = 0; + UINT16 bitstate = 0xffff; + UINT16 bitstateTmp; + UINT8* srcptr2 = srcptr; + for (i = 0; i < 16; i++) { + bitstate &= (UINT16)(*srcptr2) << 8 | *(srcptr2 + 1); + srcptr2 += stride; + } + bitstateTmp = bitstate; + for (beginX = 0; beginX < 16; beginX++) { + if (!(bitstateTmp & 0x8000)) break; + bitstateTmp <<= 1; + } + endX = 16; + bitstateTmp = bitstate; + for (endX = 16; endX > beginX; endX--) { + if (!(bitstateTmp & 0x1)) break; + bitstateTmp >>= 1; + } + if (copyflag & COPYGLYPH_ADJUSTPARTR) { + beginX -= 8 - (endX - beginX); // 右揃えにする + if (beginX < 0) beginX = 0; + } + else { + if (endX - beginX < 8 && beginX > 0) beginX--; // 一番左端は避ける + } + for (i = 0; i < 16; i++) { + UINT8 src1 = *srcptr; + UINT8 src2 = *(srcptr + 1); + if (beginX < 8) { + src1 = src1 << beginX; + src1 |= src2 >> (8 - beginX); + } + else { + src1 = src2 << (beginX - 8); + src1 |= 0xff >> (8 - (beginX - 8)); + } + *dstptr = src1; + srcptr += stride; + dstptr += stridedst; + } + } + else { + // 半幅化 + for (i = 0; i < 16; i++) { + UINT8 src1 = *srcptr; + UINT8 src2 = *(srcptr + 1); + src1 &= src1 >> 1; + src1 &= 0x55; + src2 &= src2 >> 1; + src2 &= 0x55; + *dstptr = ((src1 << 1) & 0x80) | ((src1 << 2) & 0x40) | ((src1 << 3) & 0x20) | ((src1 << 4) & 0x10) | + ((src2 >> 3) & 0x08) | ((src2 >> 2) & 0x04) | ((src2 >> 1) & 0x02) | ((src2 >> 0) & 0x01); + srcptr += stride; + dstptr += stridedst; + } + } + } + dstptr = dstptrbase; + if (copyflag & COPYGLYPH_WITHVMARK) { + dstptr += stridedst * 14; + if (dstwidth == 16) { + dstptr++; // 右側につける + } + *dstptr &= 0xfa; + *dstptr |= 0x02; + dstptr += stridedst; + *dstptr &= 0xfa; + *dstptr |= 0x02; + } + else if (copyflag & COPYGLYPH_WITHPMARK) { + dstptr += stridedst * 12; + if (dstwidth == 16) { + dstptr++; // 右側につける + } + *dstptr &= 0xfd; + *dstptr |= 0x05; + dstptr += stridedst; + *dstptr &= 0xfa; + *dstptr |= 0x02; + dstptr += stridedst; + *dstptr &= 0xfa; + *dstptr |= 0x02; + dstptr += stridedst; + *dstptr &= 0xfd; + *dstptr |= 0x05; + } + dstptr = dstptrbase; + if (copyflag & COPYGLYPH_7TO6) { + memset(reversebuf, 0xff, sizeof(reversebuf)); + if (dstwidth == 8) { + UINT8 tmp; + UINT8 bitstate = 0xff; + UINT8 bitsame = 0x00; + for (i = 0; i < 16; i++) { + tmp = *dstptr; + bitstate &= tmp; + bitsame |= tmp ^ (tmp << 1); + dstptr += stridedst; + } + if (bitstate & 0x01) { + // 右端が空いていれば何もしなくてよい + } + else if ((bitstate & 0xc0) == 0xc0) { + // 左端が2px空いていれば左へ1pxずらす + dstptr = dstptrbase; + for (i = 0; i < 16; i++) { + *dstptr = (*dstptr << 1) | 0x01; + dstptr += stridedst; + } + } + else { + // 中央に同じ内容が連続していたらそこを削る + dstptr = dstptrbase; + if (!(bitsame & 0x08)) { + for (i = 0; i < 16; i++) { + tmp = *dstptr; + tmp = (tmp & 0xf0) | ((tmp & 0x7) << 1) | 0x01; + *dstptr = tmp; + dstptr += stridedst; + } + } + else if (!(bitsame & 0x10)) { + for (i = 0; i < 16; i++) { + tmp = *dstptr; + tmp = (tmp & 0xe0) | ((tmp & 0xf) << 1) | 0x01; + *dstptr = tmp; + dstptr += stridedst; + } + } + } + } + else if (srcwidth == 16) { + // 未実装 + } + } +} + +void makepc98bmp(const OEMCHAR *filename, const OEMCHAR* fontface) { + + void *fnt; + BMPFILE bf; + UINT size; + BMPINFO bi; + UINT8 *ptr; + FILEH fh; + BOOL r; + int i; + +#if defined(FDAT_SHIFTJIS) + fnt = fontmng_create(16, FDAT_SHIFTJIS, fontface); +#else + fnt = fontmng_create(16, 0, fontface); +#endif + if (fnt == NULL) { + goto mfnt_err1; + } + size = bmpdata_setinfo(&bi, &fntinf); + bmpdata_sethead(&bf, &bi); + ptr = (UINT8 *)_MALLOC(size, filename); + if (ptr == NULL) { + goto mfnt_err2; + } + FillMemory(ptr, size, 0xff); + setank(ptr, fnt, 0x20, 0x7f); + setank(ptr, fnt, 0xa1, 0xe0); + patchank(ptr, fontdata_16 + 0*32*16, 0x00); + patchank(ptr, fontdata_16 + 1*32*16, 0x80); + patchank(ptr, fontdata_16 + 2*32*16, 0xe0); + setjis(ptr, fnt); + patchextank(ptr, fontdata_2b, 0x0b); + patchextfnt(ptr, fontdata_2c); +#ifdef USE_BUILTIN_FONT + // ねこー内蔵代替フォント + patchextank(ptr, fontdata_29, 0x09); + patchextank(ptr, fontdata_2a, 0x0a); +#else + // 指定フォントから擬似的に生成 + copyglyph(ptr, 0x315f, 16, 0xf1, 8, 0); // 円 + copyglyph(ptr, 0x472f, 16, 0xf2, 8, 0); // 年 + copyglyph(ptr, 0x376e, 16, 0xf3, 8, 0); // 月 + copyglyph(ptr, 0x467c, 16, 0xf4, 8, 0); // 日 + copyglyph(ptr, 0x3b7e, 16, 0xf5, 8, 0); // 時 + copyglyph(ptr, 0x4a2c, 16, 0xf6, 8, 0); // 分 + copyglyph(ptr, 0x4943, 16, 0xf7, 8, 0); // 秒 + for (i = 0; i < 0x7f - 0x21; i++) { + copyglyph(ptr, 0x21 + i, 8, 0x2921 + i, 8, 0); // 数字英字など + } + for (i = 0x20; i < 0x39; i++) { + copyglyph(ptr, 0x21 + i, 8, 0x2921 + i, 8, COPYGLYPH_7TO6); // ascii部分だけ可能なら狭幅にする + } + for (i = 0x40; i < 0x59; i++) { + copyglyph(ptr, 0x21 + i, 8, 0x2921 + i, 8, COPYGLYPH_7TO6); // ascii部分だけ可能なら狭幅にする + } + for (i = 0; i < 0x60 - 0x21; i++) { + copyglyph(ptr, 0xa1 + i, 8, 0x2a21 + i, 8, 0); // カナなど + } + copyglyph(ptr, 0x2570, 16, 0x2a60, 8, 0); // ヰ + copyglyph(ptr, 0x2571, 16, 0x2a61, 8, 0); // ヱ + copyglyph(ptr, 0x256e, 16, 0x2a62, 8, 0); // ヮ + copyglyph(ptr, 0x2575, 16, 0x2a63, 8, 0); // ヵ + copyglyph(ptr, 0x2576, 16, 0x2a64, 8, 0); // ヶ + copyglyph(ptr, 0xb3, 8, 0x2a65, 8, COPYGLYPH_WITHVMARK); // ヴ + for (i = 0; i < 15; i++) { + // ガ行、ザ行、ダ行 + copyglyph(ptr, 0xb6 + i, 8, 0x2a66 + i, 8, COPYGLYPH_WITHVMARK); + } + for (i = 0; i < 5; i++) { + // バ行、パ行 + copyglyph(ptr, 0xca + i, 8, 0x2a75 + i * 2, 8, COPYGLYPH_WITHVMARK); + copyglyph(ptr, 0xca + i, 8, 0x2a75 + i * 2 + 1, 8, COPYGLYPH_WITHPMARK); + } + copyglyph(ptr, 0x214c, 16, 0x2b74, 8, COPYGLYPH_ADJUSTPARTR); // 〔 + copyglyph(ptr, 0x214d, 16, 0x2b75, 8, COPYGLYPH_ADJUSTPART); // 〕 + copyglyph(ptr, 0x2152, 16, 0x2b76, 8, COPYGLYPH_ADJUSTPARTR); // 〈 + copyglyph(ptr, 0x2153, 16, 0x2b77, 8, COPYGLYPH_ADJUSTPART); // 〉 + copyglyph(ptr, 0x2154, 16, 0x2b78, 8, COPYGLYPH_ADJUSTPARTR); // 《 + copyglyph(ptr, 0x2155, 16, 0x2b79, 8, COPYGLYPH_ADJUSTPART); // 》 + copyglyph(ptr, 0x2158, 16, 0x2b7a, 8, COPYGLYPH_ADJUSTPARTR); // 『 + copyglyph(ptr, 0x2159, 16, 0x2b7b, 8, COPYGLYPH_ADJUSTPART); // 』 + copyglyph(ptr, 0x215a, 16, 0x2b7c, 8, COPYGLYPH_ADJUSTPARTR); // 【 + copyglyph(ptr, 0x215b, 16, 0x2b7d, 8, COPYGLYPH_ADJUSTPART); // 】 + copyglyph(ptr, '-', 8, 0x2b7e, 8, 0); // - + copyglyph(ptr, '/', 8, 0xfc, 8, COPYGLYPH_REVERSEXSH1); // バックスラッシュ +#endif + + fh = file_create(filename); + if (fh == FILEH_INVALID) { + goto mfnt_err3; + } + r = (file_write(fh, &bf, sizeof(bf)) == sizeof(bf)) && + (file_write(fh, &bi, sizeof(bi)) == sizeof(bi)) && + (file_write(fh, fntpal, sizeof(fntpal)) == sizeof(fntpal)) && + (file_write(fh, ptr, size) == size); + file_close(fh); + if (!r) { + file_delete(filename); + } + +mfnt_err3: + _MFREE(ptr); + +mfnt_err2: + fontmng_destroy(fnt); + +mfnt_err1: + return; +} diff --git a/font/fontmake.h b/font/fontmake.h old mode 100755 new mode 100644 index 573dde71..fff4c0a6 --- a/font/fontmake.h +++ b/font/fontmake.h @@ -1,11 +1,11 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void makepc98bmp(const OEMCHAR *filename, const OEMCHAR* fontface); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void makepc98bmp(const OEMCHAR *filename, const OEMCHAR* fontface); + +#ifdef __cplusplus +} +#endif + diff --git a/font/fontpc88.c b/font/fontpc88.c old mode 100755 new mode 100644 index 9f437e96..3c715b66 --- a/font/fontpc88.c +++ b/font/fontpc88.c @@ -1,194 +1,194 @@ -#include -#include -#include -#include -#include "fontdata.h" - - -static void pc88knjcpy1(UINT8 *dst, const UINT8 *src, int from, int to) { - - int i; - int j; - int k; -const UINT8 *p; - UINT8 *q; - - for (i=from; i= 0x01) && (i <= 0x07)) { - p = src + ((j & 0x1f) * 0x20) + (i * 0x400) - + ((j & 0x60) * 0x100); - } - // 3021〜4f7e - else if ((i >= 0x10) && (i <= 0x2f)) { - p = src + ((j & 0x1f) * 0x20) + ((i & 0x7) * 0x400) - + ((((i - 0x10) / 0x8) ^ 2) * 0x2000) - + (((j & 0x60) / 0x20) * 0x8000); - } - if (p) { // 規格内コードならば - // コピーする - for (k=0; k<16; k++) { - *(q+k+0x000) = p[0]; - *(q+k+0x800) = p[1]; - p += 2; - } - } - q += 0x1000; - } - } -} - -static void pc88knjcpy2(UINT8 *dst, const UINT8 *src, int from, int to) { - - int i, j, k; -const UINT8 *p; - UINT8 *q; - - for (i=from; i= 0x50) && (i <= 0x53)) { - p = src + ((j & 0x1f) * 0x20) - + ((i - 0x50) * 0x400) - + ((j & 0x60) * 0x100); - } - // 5021〜6f7e - else if ((i >= 0x30) && (i <= 0x4f)) { - p = src + ((j & 0x1f) * 0x20) - + ((i & 0x7) * 0x400) - + (((i - 0x30) / 0x8) * 0x2000) - + (((j & 0x60) / 0x20) * 0x8000); - } - if (p) { // 規格内コードならば - // コピーする - for (k=0; k<16; k++) { - *(q+k) = *p++; - *(q+k+0x800) = *p++; - } - } - q += 0x1000; - } - } -} - -UINT8 fontpc88_read(const OEMCHAR *filename, UINT8 loading) { - - FILEH fh; - UINT8 *work; - OEMCHAR fname[MAX_PATH]; - - work = (UINT8 *)_MALLOC(0x20000, "pc88font"); - if (work == NULL) { - goto fr88_err1; - } - file_cpyname(fname, filename, NELEMENTS(fname)); - - // 第2水準以外を読む必要はある? - if (loading & (FONT_ANK8 | FONTLOAD_ANK | FONT_KNJ1)) { - - // あったら読み込んでみる - file_cutname(fname); - file_catname(fname, pc88knj1name, NELEMENTS(fname)); - fh = file_open_rb(fname); - if (fh != FILEH_INVALID) { - if (file_read(fh, work, 0x20000) == 0x20000) { - - // 8dot ANKを読む必要があるか - if (loading & FONT_ANK8) { - loading &= ~FONT_ANK8; - fontdata_ank8store(work + 0x1000, 0, 256); - } - - // 16dot ASCIIを読む必要があるか - if (loading & FONT_ANK16a) { - loading &= ~FONT_ANK16a; - CopyMemory(fontrom + 0x80000, work + 0x0000, 16*128); - } - - // 16dot ANK(0x80〜)を読む必要があるか - if (loading & FONT_ANK16b) { - loading &= ~FONT_ANK16b; - CopyMemory(fontrom + 0x80800, work + 0x0800, 16*128); - } - - // 第一水準漢字を読み込む? - if (loading & FONT_KNJ1) { - loading &= ~FONT_KNJ1; - pc88knjcpy1(fontrom, work, 0x01, 0x30); - fontdata_patchjis(); - } - } - - // クローズして セクション終わり - file_close(fh); - } - } - - // 第2水準を読む必要はある? - if (loading & FONT_KNJ2) { - - // あったら読み込んでみる - file_cutname(fname); - file_catname(fname, pc88knj2name, NELEMENTS(fname)); - fh = file_open_rb(fname); - if (fh != FILEH_INVALID) { - if (file_read(fh, work, 0x20000) == 0x20000) { - - loading &= ~FONT_KNJ2; - pc88knjcpy2(fontrom, work, 0x31, 0x56); - } - - // クローズして セクション終わり - file_close(fh); - } - } - - // ANKを読み込む必要はある? - if (loading & (FONT_ANK8 | FONTLOAD_ANK)) { - - // あったら読み込んでみる - file_cutname(fname); - file_catname(fname, pc88ankname, NELEMENTS(fname)); - fh = file_open_rb(fname); - if (fh != FILEH_INVALID) { - - // 読み込んでみる - if (file_read(fh, work, 0x1800) == 0x1800) { - - // 8dot ANKを読む必要があるか - if (loading & FONT_ANK8) { - loading &= ~FONT_ANK8; - fontdata_ank8store(work + 0x0000, 0, 256); - } - - // 16dot ASCIIを読む必要があるか - if (loading & FONT_ANK16a) { - loading &= ~FONT_ANK16a; - CopyMemory(fontrom + 0x80000, work + 0x0800, 16*128); - } - - // 16dot ANK(0x80〜)を読む必要があるか - if (loading & FONT_ANK16b) { - loading &= ~FONT_ANK16b; - CopyMemory(fontrom + 0x80800, work + 0x1000, 16*128); - } - } - - // クローズして ANKは終わり - file_close(fh); - } - } - - _MFREE(work); - -fr88_err1: - return(loading); -} - +#include +#include +#include +#include +#include "fontdata.h" + + +static void pc88knjcpy1(UINT8 *dst, const UINT8 *src, int from, int to) { + + int i; + int j; + int k; +const UINT8 *p; + UINT8 *q; + + for (i=from; i= 0x01) && (i <= 0x07)) { + p = src + ((j & 0x1f) * 0x20) + (i * 0x400) + + ((j & 0x60) * 0x100); + } + // 3021〜4f7e + else if ((i >= 0x10) && (i <= 0x2f)) { + p = src + ((j & 0x1f) * 0x20) + ((i & 0x7) * 0x400) + + ((((i - 0x10) / 0x8) ^ 2) * 0x2000) + + (((j & 0x60) / 0x20) * 0x8000); + } + if (p) { // 規格内コードならば + // コピーする + for (k=0; k<16; k++) { + *(q+k+0x000) = p[0]; + *(q+k+0x800) = p[1]; + p += 2; + } + } + q += 0x1000; + } + } +} + +static void pc88knjcpy2(UINT8 *dst, const UINT8 *src, int from, int to) { + + int i, j, k; +const UINT8 *p; + UINT8 *q; + + for (i=from; i= 0x50) && (i <= 0x53)) { + p = src + ((j & 0x1f) * 0x20) + + ((i - 0x50) * 0x400) + + ((j & 0x60) * 0x100); + } + // 5021〜6f7e + else if ((i >= 0x30) && (i <= 0x4f)) { + p = src + ((j & 0x1f) * 0x20) + + ((i & 0x7) * 0x400) + + (((i - 0x30) / 0x8) * 0x2000) + + (((j & 0x60) / 0x20) * 0x8000); + } + if (p) { // 規格内コードならば + // コピーする + for (k=0; k<16; k++) { + *(q+k) = *p++; + *(q+k+0x800) = *p++; + } + } + q += 0x1000; + } + } +} + +UINT8 fontpc88_read(const OEMCHAR *filename, UINT8 loading) { + + FILEH fh; + UINT8 *work; + OEMCHAR fname[MAX_PATH]; + + work = (UINT8 *)_MALLOC(0x20000, "pc88font"); + if (work == NULL) { + goto fr88_err1; + } + file_cpyname(fname, filename, NELEMENTS(fname)); + + // 第2水準以外を読む必要はある? + if (loading & (FONT_ANK8 | FONTLOAD_ANK | FONT_KNJ1)) { + + // あったら読み込んでみる + file_cutname(fname); + file_catname(fname, pc88knj1name, NELEMENTS(fname)); + fh = file_open_rb(fname); + if (fh != FILEH_INVALID) { + if (file_read(fh, work, 0x20000) == 0x20000) { + + // 8dot ANKを読む必要があるか + if (loading & FONT_ANK8) { + loading &= ~FONT_ANK8; + fontdata_ank8store(work + 0x1000, 0, 256); + } + + // 16dot ASCIIを読む必要があるか + if (loading & FONT_ANK16a) { + loading &= ~FONT_ANK16a; + CopyMemory(fontrom + 0x80000, work + 0x0000, 16*128); + } + + // 16dot ANK(0x80〜)を読む必要があるか + if (loading & FONT_ANK16b) { + loading &= ~FONT_ANK16b; + CopyMemory(fontrom + 0x80800, work + 0x0800, 16*128); + } + + // 第一水準漢字を読み込む? + if (loading & FONT_KNJ1) { + loading &= ~FONT_KNJ1; + pc88knjcpy1(fontrom, work, 0x01, 0x30); + fontdata_patchjis(); + } + } + + // クローズして セクション終わり + file_close(fh); + } + } + + // 第2水準を読む必要はある? + if (loading & FONT_KNJ2) { + + // あったら読み込んでみる + file_cutname(fname); + file_catname(fname, pc88knj2name, NELEMENTS(fname)); + fh = file_open_rb(fname); + if (fh != FILEH_INVALID) { + if (file_read(fh, work, 0x20000) == 0x20000) { + + loading &= ~FONT_KNJ2; + pc88knjcpy2(fontrom, work, 0x31, 0x56); + } + + // クローズして セクション終わり + file_close(fh); + } + } + + // ANKを読み込む必要はある? + if (loading & (FONT_ANK8 | FONTLOAD_ANK)) { + + // あったら読み込んでみる + file_cutname(fname); + file_catname(fname, pc88ankname, NELEMENTS(fname)); + fh = file_open_rb(fname); + if (fh != FILEH_INVALID) { + + // 読み込んでみる + if (file_read(fh, work, 0x1800) == 0x1800) { + + // 8dot ANKを読む必要があるか + if (loading & FONT_ANK8) { + loading &= ~FONT_ANK8; + fontdata_ank8store(work + 0x0000, 0, 256); + } + + // 16dot ASCIIを読む必要があるか + if (loading & FONT_ANK16a) { + loading &= ~FONT_ANK16a; + CopyMemory(fontrom + 0x80000, work + 0x0800, 16*128); + } + + // 16dot ANK(0x80〜)を読む必要があるか + if (loading & FONT_ANK16b) { + loading &= ~FONT_ANK16b; + CopyMemory(fontrom + 0x80800, work + 0x1000, 16*128); + } + } + + // クローズして ANKは終わり + file_close(fh); + } + } + + _MFREE(work); + +fr88_err1: + return(loading); +} + diff --git a/font/fontpc98.c b/font/fontpc98.c old mode 100755 new mode 100644 index 67b6c234..175a0052 --- a/font/fontpc98.c +++ b/font/fontpc98.c @@ -1,142 +1,142 @@ -#include -#include -#include -#include -#include -#include "fontdata.h" - - -#define FONTYSIZE 16 - -#define BMPWIDTH 2048L -#define BMPHEIGHT 2048L - -#define BMPLINESIZE (BMPWIDTH / 8) // 割り切れる^^; - -#define BMPDATASIZE (BMPLINESIZE * BMPHEIGHT) - - -static void pc98ankcpy(UINT8 *dst, const UINT8 *src, int from, int to) { - - int y; -const UINT8 *p; - int ank; - - for (ank=from; ank +#include +#include +#include +#include +#include "fontdata.h" + + +#define FONTYSIZE 16 + +#define BMPWIDTH 2048L +#define BMPHEIGHT 2048L + +#define BMPLINESIZE (BMPWIDTH / 8) // 割り切れる^^; + +#define BMPDATASIZE (BMPLINESIZE * BMPHEIGHT) + + +static void pc98ankcpy(UINT8 *dst, const UINT8 *src, int from, int to) { + + int y; +const UINT8 *p; + int ank; + + for (ank=from; ank -#include -#include -#include -#include "fontdata.h" - - -#define V98FILESIZE 0x46800 - -static void v98knjcpy(UINT8 *dst, const UINT8 *src, int from, int to) { - - int i, j, k; -const UINT8 *p; - UINT8 *q; - - for (i=from; i +#include +#include +#include +#include "fontdata.h" + + +#define V98FILESIZE 0x46800 + +static void v98knjcpy(UINT8 *dst, const UINT8 *src, int from, int to) { + + int i, j, k; +const UINT8 *p; + UINT8 *q; + + for (i=from; i -#include -#include -#include -#include -#include "fontdata.h" - - -static void x1knjcpy(UINT8 *dst, const UINT8 *src, int from, int to) { - - int i, j, k; -const UINT8 *p; - UINT8 *q; - UINT sjis; - - for (i=from; i= 0x8140 && sjis < 0x84c0) { - p = src + 0x00000 + ((sjis - 0x8140) << 5); - } - else if (sjis >= 0x8890 && sjis < 0xa000) { - p = src + 0x07000 + ((sjis - 0x8890) << 5); - } - else if (sjis >= 0xe040 && sjis < 0xeab0) { - p = src + 0x35e00 + ((sjis - 0xe040) << 5); - } - if (p) { // 規格内コードならば - // コピーする - for (k=0; k<16; k++) { - *(q+k) = *p++; - *(q+k+0x800) = *p++; - } - } - q += 0x1000; - } - } -} - -UINT8 fontx1_read(const OEMCHAR *filename, UINT8 loading) { - - FILEH fh; - UINT8 *work; - OEMCHAR fname[MAX_PATH]; - - work = (UINT8 *)_MALLOC(306176, "x1font"); - if (work == NULL) { - goto frx1_err1; - } - file_cpyname(fname, filename, NELEMENTS(fname)); - - // 8dot ANKを読み込む必要はある? - if (loading & FONT_ANK8) { - file_cutname(fname); - file_catname(fname, x1ank1name, NELEMENTS(fname)); - fh = file_open_rb(fname); - if (fh != FILEH_INVALID) { - if (file_read(fh, work, 2048) == 2048) { - loading &= ~FONT_ANK8; - fontdata_ank8store(work + 0x100, 0x20, 0x60); - fontdata_ank8store(work + 0x500, 0xa0, 0x40); - } - file_close(fh); - } - } - - // 16dot ANKを読み込む必要はあるか? - if (loading & FONTLOAD_ANK) { - file_cutname(fname); - file_catname(fname, x1ank2name, NELEMENTS(fname)); - fh = file_open_rb(fname); - if (fh != FILEH_INVALID) { - if (file_read(fh, work, 4096) == 4096) { - - // 16dot ASCIIを読む必要があるか - if (loading & FONT_ANK16a) { - loading &= ~FONT_ANK16a; - CopyMemory(fontrom + 0x80200, work + 0x200, 0x60*16); - fontdata_patch16a(); - } - - // 16dot ANK(0x80〜)を読む必要があるか - if (loading & FONT_ANK16b) { - loading &= ~FONT_ANK16b; - CopyMemory(fontrom + 0x80a00, work + 0xa00, 0x40*16); - fontdata_patch16b(); - } - } - file_close(fh); - } - } - - // 漢字を読み込む必要はあるか? - if (loading & (FONT_KNJ1 | FONT_KNJ2)) { - file_cutname(fname); - file_catname(fname, x1knjname, NELEMENTS(fname)); - fh = file_open_rb(fname); - if (fh != FILEH_INVALID) { - if (file_read(fh, work, 306176) == 306176) { - - // 第一水準漢字を読み込む? - if (loading & FONT_KNJ1) { - loading &= ~FONT_KNJ1; - x1knjcpy(fontrom, work, 0x01, 0x30); - fontdata_patchjis(); - } - - // 第二水準を読む必要はある? - if (loading & FONT_KNJ2) { - loading &= ~FONT_KNJ2; - x1knjcpy(fontrom, work, 0x31, 0x50); - } - } - file_close(fh); - } - } - - // メモリを解放する - _MFREE(work); - -frx1_err1: - return(loading); -} - +#include +#include +#include +#include +#include +#include "fontdata.h" + + +static void x1knjcpy(UINT8 *dst, const UINT8 *src, int from, int to) { + + int i, j, k; +const UINT8 *p; + UINT8 *q; + UINT sjis; + + for (i=from; i= 0x8140 && sjis < 0x84c0) { + p = src + 0x00000 + ((sjis - 0x8140) << 5); + } + else if (sjis >= 0x8890 && sjis < 0xa000) { + p = src + 0x07000 + ((sjis - 0x8890) << 5); + } + else if (sjis >= 0xe040 && sjis < 0xeab0) { + p = src + 0x35e00 + ((sjis - 0xe040) << 5); + } + if (p) { // 規格内コードならば + // コピーする + for (k=0; k<16; k++) { + *(q+k) = *p++; + *(q+k+0x800) = *p++; + } + } + q += 0x1000; + } + } +} + +UINT8 fontx1_read(const OEMCHAR *filename, UINT8 loading) { + + FILEH fh; + UINT8 *work; + OEMCHAR fname[MAX_PATH]; + + work = (UINT8 *)_MALLOC(306176, "x1font"); + if (work == NULL) { + goto frx1_err1; + } + file_cpyname(fname, filename, NELEMENTS(fname)); + + // 8dot ANKを読み込む必要はある? + if (loading & FONT_ANK8) { + file_cutname(fname); + file_catname(fname, x1ank1name, NELEMENTS(fname)); + fh = file_open_rb(fname); + if (fh != FILEH_INVALID) { + if (file_read(fh, work, 2048) == 2048) { + loading &= ~FONT_ANK8; + fontdata_ank8store(work + 0x100, 0x20, 0x60); + fontdata_ank8store(work + 0x500, 0xa0, 0x40); + } + file_close(fh); + } + } + + // 16dot ANKを読み込む必要はあるか? + if (loading & FONTLOAD_ANK) { + file_cutname(fname); + file_catname(fname, x1ank2name, NELEMENTS(fname)); + fh = file_open_rb(fname); + if (fh != FILEH_INVALID) { + if (file_read(fh, work, 4096) == 4096) { + + // 16dot ASCIIを読む必要があるか + if (loading & FONT_ANK16a) { + loading &= ~FONT_ANK16a; + CopyMemory(fontrom + 0x80200, work + 0x200, 0x60*16); + fontdata_patch16a(); + } + + // 16dot ANK(0x80〜)を読む必要があるか + if (loading & FONT_ANK16b) { + loading &= ~FONT_ANK16b; + CopyMemory(fontrom + 0x80a00, work + 0xa00, 0x40*16); + fontdata_patch16b(); + } + } + file_close(fh); + } + } + + // 漢字を読み込む必要はあるか? + if (loading & (FONT_KNJ1 | FONT_KNJ2)) { + file_cutname(fname); + file_catname(fname, x1knjname, NELEMENTS(fname)); + fh = file_open_rb(fname); + if (fh != FILEH_INVALID) { + if (file_read(fh, work, 306176) == 306176) { + + // 第一水準漢字を読み込む? + if (loading & FONT_KNJ1) { + loading &= ~FONT_KNJ1; + x1knjcpy(fontrom, work, 0x01, 0x30); + fontdata_patchjis(); + } + + // 第二水準を読む必要はある? + if (loading & FONT_KNJ2) { + loading &= ~FONT_KNJ2; + x1knjcpy(fontrom, work, 0x31, 0x50); + } + } + file_close(fh); + } + } + + // メモリを解放する + _MFREE(work); + +frx1_err1: + return(loading); +} + diff --git a/font/fontx68k.c b/font/fontx68k.c old mode 100755 new mode 100644 index 501c1ef9..056116b3 --- a/font/fontx68k.c +++ b/font/fontx68k.c @@ -1,112 +1,112 @@ -#include -#include -#include -#include -#include "fontdata.h" - - -static void x68kknjcpy(UINT8 *dst, const UINT8 *src, int from, int to) { - - int i, j, k; -const UINT8 *p; - UINT8 *q; - - for (i=from; i= 0x01) && (i < 0x08)) { // 2121〜277e - p = src + 0x00000 - + ((((i - 0x01) * 0x5e) + (j - 0x21)) * 0x20); - } - else if ((i >= 0x10) && (i < 0x30)) { // 3021〜5f7e - p = src + 0x05e00 - + ((((i - 0x10) * 0x5e) + (j - 0x21)) * 0x20); - } - else if ((i >= 0x30) && (i < 0x54)) { // 5021〜737e - p = src + 0x1d600 - + ((((i - 0x30) * 0x5e) + (j - 0x21)) * 0x20); - } - else if ((i == 0x54) && (j < 0x25)) { // 7421〜7424 - p = src + 0x1d600 - + ((((0x54 - 0x30) * 0x5e) + (j - 0x21)) * 0x20); - } - if (p) { // 規格内コードならば - // コピーする - for (k=0; k<16; k++) { - *(q+k) = *p++; - *(q+k+0x800) = *p++; - } - } - q += 0x1000; - } - } -} - -UINT8 fontx68k_read(const OEMCHAR *filename, UINT8 loading) { - - FILEH fh; - UINT8 *work; - - // ファイルをオープン - fh = file_open_rb(filename); - if (fh == FILEH_INVALID) { - goto fr68_err1; - } - - // メモリアロケート - work = (UINT8 *)_MALLOC(0x3b800, "x68kfont"); - if (work == NULL) { - goto fr68_err2; - } - - // CGROM.DAT の読み込み - if (file_read(fh, work, 0x3b800) != 0x3b800) { - goto fr68_err3; - } - - // 8dot ANKを読む必要があるか - if (loading & FONT_ANK8) { - loading &= ~FONT_ANK8; - fontdata_ank8store(work + 0x3a100, 0x20, 0x60); - fontdata_ank8store(work + 0x3a500, 0xa0, 0x40); - } - - // 16dot ASCIIを読む必要があるか - if (loading & FONT_ANK16a) { - loading &= ~FONT_ANK16a; - CopyMemory(fontrom + 0x80200, work + 0x3aa00, 0x60*16); - fontdata_patch16a(); - } - - // 16dot ANK(0x80〜)を読む必要があるか - if (loading & FONT_ANK16b) { - loading &= ~FONT_ANK16b; - CopyMemory(fontrom + 0x80a00, work + 0x3b200, 0x40*16); - fontdata_patch16b(); - } - - // 第一水準漢字を読み込む? - if (loading & FONT_KNJ1) { - loading &= ~FONT_KNJ1; - x68kknjcpy(fontrom, work, 0x01, 0x30); - fontdata_patchjis(); - } - - // 第二水準を読む必要はある? - if (loading & FONT_KNJ2) { - loading &= ~FONT_KNJ2; - x68kknjcpy(fontrom, work, 0x30, 0x60); - } - -fr68_err3: - _MFREE(work); - -fr68_err2: - file_close(fh); - -fr68_err1: - return(loading); -} - +#include +#include +#include +#include +#include "fontdata.h" + + +static void x68kknjcpy(UINT8 *dst, const UINT8 *src, int from, int to) { + + int i, j, k; +const UINT8 *p; + UINT8 *q; + + for (i=from; i= 0x01) && (i < 0x08)) { // 2121〜277e + p = src + 0x00000 + + ((((i - 0x01) * 0x5e) + (j - 0x21)) * 0x20); + } + else if ((i >= 0x10) && (i < 0x30)) { // 3021〜5f7e + p = src + 0x05e00 + + ((((i - 0x10) * 0x5e) + (j - 0x21)) * 0x20); + } + else if ((i >= 0x30) && (i < 0x54)) { // 5021〜737e + p = src + 0x1d600 + + ((((i - 0x30) * 0x5e) + (j - 0x21)) * 0x20); + } + else if ((i == 0x54) && (j < 0x25)) { // 7421〜7424 + p = src + 0x1d600 + + ((((0x54 - 0x30) * 0x5e) + (j - 0x21)) * 0x20); + } + if (p) { // 規格内コードならば + // コピーする + for (k=0; k<16; k++) { + *(q+k) = *p++; + *(q+k+0x800) = *p++; + } + } + q += 0x1000; + } + } +} + +UINT8 fontx68k_read(const OEMCHAR *filename, UINT8 loading) { + + FILEH fh; + UINT8 *work; + + // ファイルをオープン + fh = file_open_rb(filename); + if (fh == FILEH_INVALID) { + goto fr68_err1; + } + + // メモリアロケート + work = (UINT8 *)_MALLOC(0x3b800, "x68kfont"); + if (work == NULL) { + goto fr68_err2; + } + + // CGROM.DAT の読み込み + if (file_read(fh, work, 0x3b800) != 0x3b800) { + goto fr68_err3; + } + + // 8dot ANKを読む必要があるか + if (loading & FONT_ANK8) { + loading &= ~FONT_ANK8; + fontdata_ank8store(work + 0x3a100, 0x20, 0x60); + fontdata_ank8store(work + 0x3a500, 0xa0, 0x40); + } + + // 16dot ASCIIを読む必要があるか + if (loading & FONT_ANK16a) { + loading &= ~FONT_ANK16a; + CopyMemory(fontrom + 0x80200, work + 0x3aa00, 0x60*16); + fontdata_patch16a(); + } + + // 16dot ANK(0x80〜)を読む必要があるか + if (loading & FONT_ANK16b) { + loading &= ~FONT_ANK16b; + CopyMemory(fontrom + 0x80a00, work + 0x3b200, 0x40*16); + fontdata_patch16b(); + } + + // 第一水準漢字を読み込む? + if (loading & FONT_KNJ1) { + loading &= ~FONT_KNJ1; + x68kknjcpy(fontrom, work, 0x01, 0x30); + fontdata_patchjis(); + } + + // 第二水準を読む必要はある? + if (loading & FONT_KNJ2) { + loading &= ~FONT_KNJ2; + x68kknjcpy(fontrom, work, 0x30, 0x60); + } + +fr68_err3: + _MFREE(work); + +fr68_err2: + file_close(fh); + +fr68_err1: + return(loading); +} + diff --git a/font/readme.txt b/font/readme.txt old mode 100755 new mode 100644 index 51ec13e4..83dbe873 --- a/font/readme.txt +++ b/font/readme.txt @@ -1,19 +1,19 @@ - - 本フォルダのソースファイルについては特に説明しません。 - - ノーチェックの部分もあります。 - - - あくまでオリジナルフォントや個人的なフォントの模様替えの為であって -他のエミュレータまでに御迷惑をお掛けしたくありません。 - - また、違法行為を助長する為の物でもありません。 - - - -font[] - ANK 8x 8 - 0x82000 + (ank << 3) - ANK 8x16 - 0x80000 + (ank << 4) - KNJ 8x16 - 0x00000 + ((jish - 0x20) << 4) + (jisl << 12) (left) - 0x00800 + ((jish - 0x20) << 4) + (jisl << 12) (right) - + + 本フォルダのソースファイルについては特に説明しません。 + + ノーチェックの部分もあります。 + + + あくまでオリジナルフォントや個人的なフォントの模様替えの為であって +他のエミュレータまでに御迷惑をお掛けしたくありません。 + + また、違法行為を助長する為の物でもありません。 + + + +font[] + ANK 8x 8 - 0x82000 + (ank << 3) + ANK 8x16 - 0x80000 + (ank << 4) + KNJ 8x16 - 0x00000 + ((jish - 0x20) << 4) + (jisl << 12) (left) + 0x00800 + ((jish - 0x20) << 4) + (jisl << 12) (right) + diff --git a/generic/cmjasts.c b/generic/cmjasts.c old mode 100755 new mode 100644 index a4b82843..ee481d84 --- a/generic/cmjasts.c +++ b/generic/cmjasts.c @@ -1,148 +1,148 @@ -#include -#include -#include -#include -#include - - -#define JSEVENTS 512 - -typedef struct { - SINT32 clock; - SINT32 pcm; -} JSEVT; - -typedef struct { - SINT32 pcm; -#if defined(JSEVENTS) - SINT32 lastpcm; - UINT events; - JSEVT event[JSEVENTS]; -#endif -} _CMJAST, *CMJAST; - - -static UINT jsread(COMMNG self, UINT8 *data) { - - (void)self; - (void)data; - return(0); -} - -static UINT jswrite(COMMNG self, UINT8 data) { - - CMJAST js; - SINT32 pcm; - - js = (CMJAST)(self + 1); - pcm = data << 5; - js->pcm = pcm; -#if defined(JSEVENTS) - if (js->events < JSEVENTS) { - JSEVT *e; - e = js->event + js->events; - e->clock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK - - soundcfg.lastclock; - e->pcm = pcm; - js->events++; - if (js->events == JSEVENTS) { - sound_sync(); - } - } -#else - sound_sync(); -#endif - return(1); -} - -static UINT8 jsgetstat(COMMNG self) { - - (void)self; - return(0); -} - -static INTPTR jsmsg(COMMNG self, UINT msg, INTPTR param) { - - (void)self; - (void)msg; - (void)param; - return(0); -} - -static void jsrelease(COMMNG self) { - - _MFREE(self); -} - -static void SOUNDCALL js_getpcm(CMJAST hdl, SINT32 *pcm, UINT count) { - - SINT32 pcmdata; - -#if defined(JSEVENTS) - UINT pos; - UINT pterm; - JSEVT *e; - JSEVT *eterm; - - pos = 0; - e = hdl->event; - eterm = e + hdl->events; - hdl->events = 0; - pcmdata = hdl->lastpcm; - hdl->lastpcm = hdl->pcm; - while(e < eterm) { - pterm = (e->clock * soundcfg.hzbase) / soundcfg.clockbase; - if (pterm >= count) { - break; - } - while(pos < pterm) { - pos++; - pcm[0] += pcmdata; - pcm[1] += pcmdata; - pcm += 2; - } - pcmdata = e->pcm; - e++; - } - count -= pos; - if (e >= eterm) { - pcmdata = hdl->pcm; - } -#else - pcmdata = hdl->pcm; -#endif - if (pcmdata) { - while(count) { - count--; - pcm[0] += pcmdata; - pcm[1] += pcmdata; - pcm += 2; - } - } -} - - -COMMNG cmjasts_create(void) { - - COMMNG ret; - CMJAST js; - - ret = (COMMNG)_MALLOC(sizeof(_COMMNG) + sizeof(_CMJAST), "JAST"); - if (ret == NULL) { - goto cmjscre_err; - } - ret->connect = COMCONNECT_PARALLEL; - ret->read = jsread; - ret->write = jswrite; - ret->getstat = jsgetstat; - ret->msg = jsmsg; - ret->release = jsrelease; - js = (CMJAST)(ret + 1); - ZeroMemory(js, sizeof(_CMJAST)); - sound_streamregist((void *)js, (SOUNDCB)js_getpcm); - return(ret); - -cmjscre_err: - return(NULL); -} - +#include +#include +#include +#include +#include + + +#define JSEVENTS 512 + +typedef struct { + SINT32 clock; + SINT32 pcm; +} JSEVT; + +typedef struct { + SINT32 pcm; +#if defined(JSEVENTS) + SINT32 lastpcm; + UINT events; + JSEVT event[JSEVENTS]; +#endif +} _CMJAST, *CMJAST; + + +static UINT jsread(COMMNG self, UINT8 *data) { + + (void)self; + (void)data; + return(0); +} + +static UINT jswrite(COMMNG self, UINT8 data) { + + CMJAST js; + SINT32 pcm; + + js = (CMJAST)(self + 1); + pcm = data << 5; + js->pcm = pcm; +#if defined(JSEVENTS) + if (js->events < JSEVENTS) { + JSEVT *e; + e = js->event + js->events; + e->clock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK - + soundcfg.lastclock; + e->pcm = pcm; + js->events++; + if (js->events == JSEVENTS) { + sound_sync(); + } + } +#else + sound_sync(); +#endif + return(1); +} + +static UINT8 jsgetstat(COMMNG self) { + + (void)self; + return(0); +} + +static INTPTR jsmsg(COMMNG self, UINT msg, INTPTR param) { + + (void)self; + (void)msg; + (void)param; + return(0); +} + +static void jsrelease(COMMNG self) { + + _MFREE(self); +} + +static void SOUNDCALL js_getpcm(CMJAST hdl, SINT32 *pcm, UINT count) { + + SINT32 pcmdata; + +#if defined(JSEVENTS) + UINT pos; + UINT pterm; + JSEVT *e; + JSEVT *eterm; + + pos = 0; + e = hdl->event; + eterm = e + hdl->events; + hdl->events = 0; + pcmdata = hdl->lastpcm; + hdl->lastpcm = hdl->pcm; + while(e < eterm) { + pterm = (e->clock * soundcfg.hzbase) / soundcfg.clockbase; + if (pterm >= count) { + break; + } + while(pos < pterm) { + pos++; + pcm[0] += pcmdata; + pcm[1] += pcmdata; + pcm += 2; + } + pcmdata = e->pcm; + e++; + } + count -= pos; + if (e >= eterm) { + pcmdata = hdl->pcm; + } +#else + pcmdata = hdl->pcm; +#endif + if (pcmdata) { + while(count) { + count--; + pcm[0] += pcmdata; + pcm[1] += pcmdata; + pcm += 2; + } + } +} + + +COMMNG cmjasts_create(void) { + + COMMNG ret; + CMJAST js; + + ret = (COMMNG)_MALLOC(sizeof(_COMMNG) + sizeof(_CMJAST), "JAST"); + if (ret == NULL) { + goto cmjscre_err; + } + ret->connect = COMCONNECT_PARALLEL; + ret->read = jsread; + ret->write = jswrite; + ret->getstat = jsgetstat; + ret->msg = jsmsg; + ret->release = jsrelease; + js = (CMJAST)(ret + 1); + ZeroMemory(js, sizeof(_CMJAST)); + sound_streamregist((void *)js, (SOUNDCB)js_getpcm); + return(ret); + +cmjscre_err: + return(NULL); +} + diff --git a/generic/cmjasts.h b/generic/cmjasts.h old mode 100755 new mode 100644 index 8f20efec..1ad967fa --- a/generic/cmjasts.h +++ b/generic/cmjasts.h @@ -1,13 +1,13 @@ - -// ---- com manager jast sound - -#ifdef __cplusplus -extern "C" { -#endif - -COMMNG cmjasts_create(void); - -#ifdef __cplusplus -} -#endif - + +// ---- com manager jast sound + +#ifdef __cplusplus +extern "C" { +#endif + +COMMNG cmjasts_create(void); + +#ifdef __cplusplus +} +#endif + diff --git a/generic/cmndraw.c b/generic/cmndraw.c old mode 100755 new mode 100644 index e65be5e3..1efd09c7 --- a/generic/cmndraw.c +++ b/generic/cmndraw.c @@ -1,472 +1,472 @@ -#include -#include -#include -#include -#include -#include "minifont.res" - - -void cmndraw_makegrad(RGB32 *pal, int pals, RGB32 bg, RGB32 fg) { - - int i; - - if (pals <= 0) { - return; - } - pals--; - for (i=0; iptr + (x * vram->xalign) + (y * vram->yalign); - dalign = vram->yalign - (vram->xalign * cx); - switch(vram->bpp) { -#if defined(SUPPORT_8BPP) - case 8: - do { - r = cx; - do { - *p = fg.pal8; - p += vram->xalign; - } while(--r); - p += dalign; - } while(--cy); - break; -#endif -#if defined(SUPPORT_16BPP) - case 16: - do { - r = cx; - do { - *(UINT16 *)p = fg.pal16; - p += vram->xalign; - } while(--r); - p += dalign; - } while(--cy); - break; -#endif -#if defined(SUPPORT_24BPP) - case 24: - do { - r = cx; - do { - p[RGB24_R] = fg.pal32.p.r; - p[RGB24_G] = fg.pal32.p.g; - p[RGB24_B] = fg.pal32.p.b; - p += vram->xalign; - } while(--r); - p += dalign; - } while(--cy); - break; -#endif -#if defined(SUPPORT_32BPP) - case 32: - do { - r = cx; - do { - *(UINT32 *)p = fg.pal32.d; - p += vram->xalign; - } while(--r); - p += dalign; - } while(--cy); - break; -#endif - } -} - -void cmndraw_setfg(const CMNVRAM *vram, const UINT8 *src, - int x, int y, CMNPAL fg) { - -const UINT8 *p; - UINT8 *q; - UINT8 cy; - int dalign; - UINT8 c; - UINT8 bit; - UINT8 cx; - - if (vram == NULL) { - return; - } - p = src + 2; - q = vram->ptr + (x * vram->xalign) + (y * vram->yalign); - dalign = vram->yalign - (vram->xalign * src[0]); - cy = src[1]; - do { - cx = src[0]; - bit = 0; - c = 0; - switch(vram->bpp) { -#if defined(SUPPORT_8BPP) - case 8: - do { - if (!bit) { - bit = 0x80; - c = *p++; - } - if (c & bit) { - *q = fg.pal8; - } - bit >>= 1; - q += vram->xalign; - } while(--cx); - break; -#endif -#if defined(SUPPORT_16BPP) - case 16: - do { - if (!bit) { - bit = 0x80; - c = *p++; - } - if (c & bit) { - *(UINT16 *)q = fg.pal16; - } - bit >>= 1; - q += vram->xalign; - } while(--cx); - break; -#endif -#if defined(SUPPORT_24BPP) - case 24: - do { - if (!bit) { - bit = 0x80; - c = *p++; - } - if (c & bit) { - q[RGB24_R] = fg.pal32.p.r; - q[RGB24_G] = fg.pal32.p.g; - q[RGB24_B] = fg.pal32.p.b; - } - bit >>= 1; - q += vram->xalign; - } while(--cx); - break; -#endif -#if defined(SUPPORT_32BPP) - case 32: - do { - if (!bit) { - bit = 0x80; - c = *p++; - } - if (c & bit) { - *(UINT32 *)q = fg.pal32.d; - } - bit >>= 1; - q += vram->xalign; - } while(--cx); - break; -#endif - } - q += dalign; - } while(--cy); -} - -void cmndraw_setpat(const CMNVRAM *vram, const UINT8 *src, - int x, int y, CMNPAL bg, CMNPAL fg) { - -const UINT8 *p; - UINT8 *q; - UINT8 cy; - int dalign; - UINT8 c; - UINT8 bit; - UINT8 cx; - - p = src + 2; - q = vram->ptr + (x * vram->xalign) + (y * vram->yalign); - dalign = vram->yalign - (vram->xalign * src[0]); - cy = src[1]; - do { - cx = src[0]; - bit = 0; - c = 0; - switch(vram->bpp) { -#if defined(SUPPORT_8BPP) - case 8: - do { - if (!bit) { - bit = 0x80; - c = *p++; - } - if (c & bit) { - *q = fg.pal8; - } - else { - *q = bg.pal8; - } - bit >>= 1; - q += vram->xalign; - } while(--cx); - break; -#endif -#if defined(SUPPORT_16BPP) - case 16: - do { - if (!bit) { - bit = 0x80; - c = *p++; - } - if (c & bit) { - *(UINT16 *)q = fg.pal16; - } - else { - *(UINT16 *)q = bg.pal16; - } - bit >>= 1; - q += vram->xalign; - } while(--cx); - break; -#endif -#if defined(SUPPORT_24BPP) - case 24: - do { - if (!bit) { - bit = 0x80; - c = *p++; - } - if (c & bit) { - q[RGB24_R] = fg.pal32.p.r; - q[RGB24_G] = fg.pal32.p.g; - q[RGB24_B] = fg.pal32.p.b; - } - else { - q[RGB24_R] = bg.pal32.p.r; - q[RGB24_G] = bg.pal32.p.g; - q[RGB24_B] = bg.pal32.p.b; - } - bit >>= 1; - q += vram->xalign; - } while(--cx); - break; -#endif -#if defined(SUPPORT_32BPP) - case 32: - do { - if (!bit) { - bit = 0x80; - c = *p++; - } - if (c & bit) { - *(UINT32 *)q = fg.pal32.d; - } - else { - *(UINT32 *)q = bg.pal32.d; - } - bit >>= 1; - q += vram->xalign; - } while(--cx); - break; -#endif - } - q += dalign; - } while(--cy); -} - - -// ---- - -void cmddraw_text8(CMNVRAM *vram, int x, int y, const char *str, CMNPAL fg) { - - UINT s; -const UINT8 *ptr; - UINT8 src[10]; - - if ((vram == NULL) || (str == NULL)) { - return; - } - src[0] = 0; - src[1] = 7; - while(*str) { - s = (UINT)(*str++); - ptr = NULL; - if ((s >= 0x20) && (s < 0x80)) { - ptr = minifont + (s - 0x20) * 8; - } - else if ((s >= 0xa0) && (s < 0xe0)) { - ptr = minifont + (s - 0xa0 + 0x60) * 8; - } - if (ptr == NULL) { - continue; - } - src[0] = ptr[0]; - CopyMemory(src + 2, ptr + 1, 7); - cmndraw_setfg(vram, src, x, y, fg); - x += ptr[0] + 1; - } -} - - -// ---- bmp - -BRESULT cmndraw_bmp4inf(CMNBMP *bmp, const void *ptr) { - -const BMPFILE *bf; -const BMPINFO *bi; -const UINT8 *palptr; - BMPDATA inf; - UINT8 *src; - int bmpalign; - UINT pals; - UINT c; - - if ((bmp == NULL) || (ptr == NULL)) { - return(FAILURE); - } - bf = (BMPFILE *)ptr; - bi = (BMPINFO *)(bf + 1); - palptr = (UINT8 *)(bi + 1); - if (((bf->bfType[0] != 'B') && (bf->bfType[1] != 'M')) || - (bmpdata_getinfo(bi, &inf) != SUCCESS) || (inf.bpp != 4)) { - return(FAILURE); - } - pals = MIN(LOADINTELDWORD(bi->biClrUsed), 16); - - src = (UINT8 *)bf + (LOADINTELDWORD(bf->bfOffBits)); - bmpalign = bmpdata_getalign(bi); - if (inf.height > 0) { - bmp->ptr = src + ((inf.height - 1) * bmpalign); - bmp->width = inf.width; - bmp->height = inf.height; - bmp->align = bmpalign * -1; - } - else { - bmp->ptr = src; - bmp->width = inf.width; - bmp->height = inf.height * -1; - bmp->align = bmpalign; - } - bmp->pals = pals; - ZeroMemory(bmp->paltbl, sizeof(bmp->paltbl)); - for (c=0; cpaltbl[c].p.b = palptr[c*4+0]; - bmp->paltbl[c].p.g = palptr[c*4+1]; - bmp->paltbl[c].p.r = palptr[c*4+2]; - } - return(SUCCESS); -} - -void cmndraw_bmp16(CMNVRAM *vram, const void *ptr, CMNPALCNV cnv, UINT flag) { - - CMNBMP bmp; - CMNPAL pal[16]; - UINT8 *src; - UINT8 *dst; - int yalign; - int x; - int y; - UINT c; - - if ((vram == NULL) || (cnv == NULL) || - (cmndraw_bmp4inf(&bmp, ptr) != SUCCESS) || - (vram->width < bmp.width) || (vram->height < bmp.height)) { - return; - } - (*cnv)(pal, bmp.paltbl, bmp.pals, vram->bpp); - src = bmp.ptr; - dst = vram->ptr; - switch(flag & 0x03) { - case CMNBMP_CENTER: - dst += ((vram->width - bmp.width) / 2) * vram->xalign; - break; - - case CMNBMP_RIGHT: - dst += (vram->width - bmp.width) * vram->xalign; - break; - } - switch(flag & 0x0c) { - case CMNBMP_MIDDLE: - dst += ((vram->height - bmp.height) / 2) * vram->yalign; - break; - - case CMNBMP_BOTTOM: - dst += (vram->height - bmp.height) * vram->yalign; - break; - } - yalign = vram->yalign - (bmp.width * vram->xalign); - for (y=0; ybpp) { -#if defined(SUPPORT_8BPP) - case 8: - for (x=0; x> 1] >> 4; - } - else { - c = src[x >> 1] & 15; - } - *dst = pal[c].pal8; - dst += vram->xalign; - } - break; -#endif -#if defined(SUPPORT_16BPP) - case 16: - for (x=0; x> 1] >> 4; - } - else { - c = src[x >> 1] & 15; - } - *(UINT16 *)dst = pal[c].pal16; - dst += vram->xalign; - } - break; -#endif -#if defined(SUPPORT_24BPP) - case 24: - for (x=0; x> 1] >> 4; - } - else { - c = src[x >> 1] & 15; - } - dst[RGB24_R] = pal[c].pal32.p.r; - dst[RGB24_G] = pal[c].pal32.p.g; - dst[RGB24_B] = pal[c].pal32.p.b; - dst += vram->xalign; - } - break; -#endif -#if defined(SUPPORT_32BPP) - case 32: - for (x=0; x> 1] >> 4; - } - else { - c = src[x >> 1] & 15; - } - *(UINT32 *)dst = pal[c].pal32.d; - dst += vram->xalign; - } - break; -#endif - } - src += bmp.align; - dst += yalign; - } -} - +#include +#include +#include +#include +#include +#include "minifont.res" + + +void cmndraw_makegrad(RGB32 *pal, int pals, RGB32 bg, RGB32 fg) { + + int i; + + if (pals <= 0) { + return; + } + pals--; + for (i=0; iptr + (x * vram->xalign) + (y * vram->yalign); + dalign = vram->yalign - (vram->xalign * cx); + switch(vram->bpp) { +#if defined(SUPPORT_8BPP) + case 8: + do { + r = cx; + do { + *p = fg.pal8; + p += vram->xalign; + } while(--r); + p += dalign; + } while(--cy); + break; +#endif +#if defined(SUPPORT_16BPP) + case 16: + do { + r = cx; + do { + *(UINT16 *)p = fg.pal16; + p += vram->xalign; + } while(--r); + p += dalign; + } while(--cy); + break; +#endif +#if defined(SUPPORT_24BPP) + case 24: + do { + r = cx; + do { + p[RGB24_R] = fg.pal32.p.r; + p[RGB24_G] = fg.pal32.p.g; + p[RGB24_B] = fg.pal32.p.b; + p += vram->xalign; + } while(--r); + p += dalign; + } while(--cy); + break; +#endif +#if defined(SUPPORT_32BPP) + case 32: + do { + r = cx; + do { + *(UINT32 *)p = fg.pal32.d; + p += vram->xalign; + } while(--r); + p += dalign; + } while(--cy); + break; +#endif + } +} + +void cmndraw_setfg(const CMNVRAM *vram, const UINT8 *src, + int x, int y, CMNPAL fg) { + +const UINT8 *p; + UINT8 *q; + UINT8 cy; + int dalign; + UINT8 c; + UINT8 bit; + UINT8 cx; + + if (vram == NULL) { + return; + } + p = src + 2; + q = vram->ptr + (x * vram->xalign) + (y * vram->yalign); + dalign = vram->yalign - (vram->xalign * src[0]); + cy = src[1]; + do { + cx = src[0]; + bit = 0; + c = 0; + switch(vram->bpp) { +#if defined(SUPPORT_8BPP) + case 8: + do { + if (!bit) { + bit = 0x80; + c = *p++; + } + if (c & bit) { + *q = fg.pal8; + } + bit >>= 1; + q += vram->xalign; + } while(--cx); + break; +#endif +#if defined(SUPPORT_16BPP) + case 16: + do { + if (!bit) { + bit = 0x80; + c = *p++; + } + if (c & bit) { + *(UINT16 *)q = fg.pal16; + } + bit >>= 1; + q += vram->xalign; + } while(--cx); + break; +#endif +#if defined(SUPPORT_24BPP) + case 24: + do { + if (!bit) { + bit = 0x80; + c = *p++; + } + if (c & bit) { + q[RGB24_R] = fg.pal32.p.r; + q[RGB24_G] = fg.pal32.p.g; + q[RGB24_B] = fg.pal32.p.b; + } + bit >>= 1; + q += vram->xalign; + } while(--cx); + break; +#endif +#if defined(SUPPORT_32BPP) + case 32: + do { + if (!bit) { + bit = 0x80; + c = *p++; + } + if (c & bit) { + *(UINT32 *)q = fg.pal32.d; + } + bit >>= 1; + q += vram->xalign; + } while(--cx); + break; +#endif + } + q += dalign; + } while(--cy); +} + +void cmndraw_setpat(const CMNVRAM *vram, const UINT8 *src, + int x, int y, CMNPAL bg, CMNPAL fg) { + +const UINT8 *p; + UINT8 *q; + UINT8 cy; + int dalign; + UINT8 c; + UINT8 bit; + UINT8 cx; + + p = src + 2; + q = vram->ptr + (x * vram->xalign) + (y * vram->yalign); + dalign = vram->yalign - (vram->xalign * src[0]); + cy = src[1]; + do { + cx = src[0]; + bit = 0; + c = 0; + switch(vram->bpp) { +#if defined(SUPPORT_8BPP) + case 8: + do { + if (!bit) { + bit = 0x80; + c = *p++; + } + if (c & bit) { + *q = fg.pal8; + } + else { + *q = bg.pal8; + } + bit >>= 1; + q += vram->xalign; + } while(--cx); + break; +#endif +#if defined(SUPPORT_16BPP) + case 16: + do { + if (!bit) { + bit = 0x80; + c = *p++; + } + if (c & bit) { + *(UINT16 *)q = fg.pal16; + } + else { + *(UINT16 *)q = bg.pal16; + } + bit >>= 1; + q += vram->xalign; + } while(--cx); + break; +#endif +#if defined(SUPPORT_24BPP) + case 24: + do { + if (!bit) { + bit = 0x80; + c = *p++; + } + if (c & bit) { + q[RGB24_R] = fg.pal32.p.r; + q[RGB24_G] = fg.pal32.p.g; + q[RGB24_B] = fg.pal32.p.b; + } + else { + q[RGB24_R] = bg.pal32.p.r; + q[RGB24_G] = bg.pal32.p.g; + q[RGB24_B] = bg.pal32.p.b; + } + bit >>= 1; + q += vram->xalign; + } while(--cx); + break; +#endif +#if defined(SUPPORT_32BPP) + case 32: + do { + if (!bit) { + bit = 0x80; + c = *p++; + } + if (c & bit) { + *(UINT32 *)q = fg.pal32.d; + } + else { + *(UINT32 *)q = bg.pal32.d; + } + bit >>= 1; + q += vram->xalign; + } while(--cx); + break; +#endif + } + q += dalign; + } while(--cy); +} + + +// ---- + +void cmddraw_text8(CMNVRAM *vram, int x, int y, const char *str, CMNPAL fg) { + + UINT s; +const UINT8 *ptr; + UINT8 src[10]; + + if ((vram == NULL) || (str == NULL)) { + return; + } + src[0] = 0; + src[1] = 7; + while(*str) { + s = (UINT)(*str++); + ptr = NULL; + if ((s >= 0x20) && (s < 0x80)) { + ptr = minifont + (s - 0x20) * 8; + } + else if ((s >= 0xa0) && (s < 0xe0)) { + ptr = minifont + (s - 0xa0 + 0x60) * 8; + } + if (ptr == NULL) { + continue; + } + src[0] = ptr[0]; + CopyMemory(src + 2, ptr + 1, 7); + cmndraw_setfg(vram, src, x, y, fg); + x += ptr[0] + 1; + } +} + + +// ---- bmp + +BRESULT cmndraw_bmp4inf(CMNBMP *bmp, const void *ptr) { + +const BMPFILE *bf; +const BMPINFO *bi; +const UINT8 *palptr; + BMPDATA inf; + UINT8 *src; + int bmpalign; + UINT pals; + UINT c; + + if ((bmp == NULL) || (ptr == NULL)) { + return(FAILURE); + } + bf = (BMPFILE *)ptr; + bi = (BMPINFO *)(bf + 1); + palptr = (UINT8 *)(bi + 1); + if (((bf->bfType[0] != 'B') && (bf->bfType[1] != 'M')) || + (bmpdata_getinfo(bi, &inf) != SUCCESS) || (inf.bpp != 4)) { + return(FAILURE); + } + pals = MIN(LOADINTELDWORD(bi->biClrUsed), 16); + + src = (UINT8 *)bf + (LOADINTELDWORD(bf->bfOffBits)); + bmpalign = bmpdata_getalign(bi); + if (inf.height > 0) { + bmp->ptr = src + ((inf.height - 1) * bmpalign); + bmp->width = inf.width; + bmp->height = inf.height; + bmp->align = bmpalign * -1; + } + else { + bmp->ptr = src; + bmp->width = inf.width; + bmp->height = inf.height * -1; + bmp->align = bmpalign; + } + bmp->pals = pals; + ZeroMemory(bmp->paltbl, sizeof(bmp->paltbl)); + for (c=0; cpaltbl[c].p.b = palptr[c*4+0]; + bmp->paltbl[c].p.g = palptr[c*4+1]; + bmp->paltbl[c].p.r = palptr[c*4+2]; + } + return(SUCCESS); +} + +void cmndraw_bmp16(CMNVRAM *vram, const void *ptr, CMNPALCNV cnv, UINT flag) { + + CMNBMP bmp; + CMNPAL pal[16]; + UINT8 *src; + UINT8 *dst; + int yalign; + int x; + int y; + UINT c; + + if ((vram == NULL) || (cnv == NULL) || + (cmndraw_bmp4inf(&bmp, ptr) != SUCCESS) || + (vram->width < bmp.width) || (vram->height < bmp.height)) { + return; + } + (*cnv)(pal, bmp.paltbl, bmp.pals, vram->bpp); + src = bmp.ptr; + dst = vram->ptr; + switch(flag & 0x03) { + case CMNBMP_CENTER: + dst += ((vram->width - bmp.width) / 2) * vram->xalign; + break; + + case CMNBMP_RIGHT: + dst += (vram->width - bmp.width) * vram->xalign; + break; + } + switch(flag & 0x0c) { + case CMNBMP_MIDDLE: + dst += ((vram->height - bmp.height) / 2) * vram->yalign; + break; + + case CMNBMP_BOTTOM: + dst += (vram->height - bmp.height) * vram->yalign; + break; + } + yalign = vram->yalign - (bmp.width * vram->xalign); + for (y=0; ybpp) { +#if defined(SUPPORT_8BPP) + case 8: + for (x=0; x> 1] >> 4; + } + else { + c = src[x >> 1] & 15; + } + *dst = pal[c].pal8; + dst += vram->xalign; + } + break; +#endif +#if defined(SUPPORT_16BPP) + case 16: + for (x=0; x> 1] >> 4; + } + else { + c = src[x >> 1] & 15; + } + *(UINT16 *)dst = pal[c].pal16; + dst += vram->xalign; + } + break; +#endif +#if defined(SUPPORT_24BPP) + case 24: + for (x=0; x> 1] >> 4; + } + else { + c = src[x >> 1] & 15; + } + dst[RGB24_R] = pal[c].pal32.p.r; + dst[RGB24_G] = pal[c].pal32.p.g; + dst[RGB24_B] = pal[c].pal32.p.b; + dst += vram->xalign; + } + break; +#endif +#if defined(SUPPORT_32BPP) + case 32: + for (x=0; x> 1] >> 4; + } + else { + c = src[x >> 1] & 15; + } + *(UINT32 *)dst = pal[c].pal32.d; + dst += vram->xalign; + } + break; +#endif + } + src += bmp.align; + dst += yalign; + } +} + diff --git a/generic/cmndraw.h b/generic/cmndraw.h old mode 100755 new mode 100644 index 7e1f2d17..c17ac07c --- a/generic/cmndraw.h +++ b/generic/cmndraw.h @@ -1,65 +1,65 @@ - -#ifndef __CMNDRAW -#define __CMNDRAW - -typedef union { - RGB32 pal32; - UINT16 pal16; - UINT8 pal8; -} CMNPAL; - -typedef struct { - UINT8 *ptr; - int width; - int height; - int xalign; - int yalign; - int bpp; -} CMNVRAM; - -typedef void (*CMNPALCNV)(CMNPAL *dst, const RGB32 *src, UINT pals, UINT bpp); - -#ifdef __cplusplus -extern "C" { -#endif - -void cmndraw_makegrad(RGB32 *pal, int pals, RGB32 bg, RGB32 fg); - -void cmndraw_fill(const CMNVRAM *vram, int x, int y, - int cx, int cy, CMNPAL fg); -void cmndraw_setfg(const CMNVRAM *vram, const UINT8 *src, - int x, int y, CMNPAL fg); -void cmndraw_setpat(const CMNVRAM *vram, const UINT8 *src, - int x, int y, CMNPAL bg, CMNPAL fg); -void cmddraw_text8(CMNVRAM *vram, int x, int y, const char *str, CMNPAL fg); - - -// ---- - -enum { - CMNBMP_LEFT = 0x00, - CMNBMP_CENTER = 0x01, - CMNBMP_RIGHT = 0x02, - CMNBMP_TOP = 0x00, - CMNBMP_MIDDLE = 0x04, - CMNBMP_BOTTOM = 0x08 -}; - -typedef struct { - UINT8 *ptr; - int width; - int height; - int align; - UINT pals; - RGB32 paltbl[16]; -} CMNBMP; - -BRESULT cmndraw_bmp4inf(CMNBMP *bmp, const void *ptr); -void cmndraw_bmp16(CMNVRAM *vram, const void *ptr, CMNPALCNV cnv, UINT flag); - -#ifdef __cplusplus -} -#endif - -#endif - + +#ifndef __CMNDRAW +#define __CMNDRAW + +typedef union { + RGB32 pal32; + UINT16 pal16; + UINT8 pal8; +} CMNPAL; + +typedef struct { + UINT8 *ptr; + int width; + int height; + int xalign; + int yalign; + int bpp; +} CMNVRAM; + +typedef void (*CMNPALCNV)(CMNPAL *dst, const RGB32 *src, UINT pals, UINT bpp); + +#ifdef __cplusplus +extern "C" { +#endif + +void cmndraw_makegrad(RGB32 *pal, int pals, RGB32 bg, RGB32 fg); + +void cmndraw_fill(const CMNVRAM *vram, int x, int y, + int cx, int cy, CMNPAL fg); +void cmndraw_setfg(const CMNVRAM *vram, const UINT8 *src, + int x, int y, CMNPAL fg); +void cmndraw_setpat(const CMNVRAM *vram, const UINT8 *src, + int x, int y, CMNPAL bg, CMNPAL fg); +void cmddraw_text8(CMNVRAM *vram, int x, int y, const char *str, CMNPAL fg); + + +// ---- + +enum { + CMNBMP_LEFT = 0x00, + CMNBMP_CENTER = 0x01, + CMNBMP_RIGHT = 0x02, + CMNBMP_TOP = 0x00, + CMNBMP_MIDDLE = 0x04, + CMNBMP_BOTTOM = 0x08 +}; + +typedef struct { + UINT8 *ptr; + int width; + int height; + int align; + UINT pals; + RGB32 paltbl[16]; +} CMNBMP; + +BRESULT cmndraw_bmp4inf(CMNBMP *bmp, const void *ptr); +void cmndraw_bmp16(CMNVRAM *vram, const void *ptr, CMNPALCNV cnv, UINT flag); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/generic/cmver.c b/generic/cmver.c old mode 100755 new mode 100644 index b4752b0b..216af7ac --- a/generic/cmver.c +++ b/generic/cmver.c @@ -1,462 +1,462 @@ -#include -#include -//#include - - -#if defined(VERMOUTH_LIB) - -#include -#include "sound/vermouth/vermouth.h" -#include - -#define MIDIOUTS(a, b, c) (((c) << 16) + (b << 8) + (a)) -#define MIDIOUTS2(a) ((a)[0] + ((a)[1] << 8)) -#define MIDIOUTS3(a) ((a)[0] + ((a)[1] << 8) + ((a)[2] << 16)) - -static const UINT8 EXCV_GMRESET[] = { - 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7}; - -enum { - MIDI_EXCLUSIVE = 0xf0, - MIDI_TIMECODE = 0xf1, - MIDI_SONGPOS = 0xf2, - MIDI_SONGSELECT = 0xf3, - MIDI_CABLESELECT = 0xf5, - MIDI_TUNEREQUEST = 0xf6, - MIDI_EOX = 0xf7, - MIDI_TIMING = 0xf8, - MIDI_START = 0xfa, - MIDI_CONTINUE = 0xfb, - MIDI_STOP = 0xfc, - MIDI_ACTIVESENSE = 0xfe, - MIDI_SYSTEMRESET = 0xff -}; - -enum { - MIDI_BUFFER = (1 << 10), - MIDIIN_MAX = 4, - - MIDICTRL_READY = 0, - MIDICTRL_2BYTES, - MIDICTRL_3BYTES, - MIDICTRL_EXCLUSIVE, - MIDICTRL_TIMECODE, - MIDICTRL_SYSTEM -}; - -typedef struct { - UINT8 prog; - UINT8 press; - UINT16 bend; - UINT8 ctrl[28]; -} _MIDICH, *MIDICH; - -typedef struct { - MIDIHDL midihdl; - UINT midictrl; - UINT midisyscnt; - UINT mpos; - UINT8 midilast; - _MIDICH mch[16]; - UINT8 buffer[MIDI_BUFFER]; -} _CMMIDI, *CMMIDI; - -typedef struct { - MIDIMOD vermouth; - UINT rate; -} CMVER; - -static const UINT8 midictrltbl[] = { 0, 1, 5, 7, 10, 11, 64, - 65, 66, 67, 84, 91, 93, - 94, // for SC-88 - 71, 72, 73, 74}; // for XG - -static CMVER cmver; -static UINT8 midictrlindex[128]; - - -// ---- - -static void SOUNDCALL vermouth_getpcm(MIDIHDL hdl, SINT32 *pcm, UINT count) { - -const SINT32 *ptr; - UINT size; - - while(count) { - size = count; - ptr = midiout_get(hdl, &size); - if (ptr == NULL) { - break; - } - count -= size; - do { - pcm[0] += ptr[0]; - pcm[1] += ptr[1]; - ptr += 2; - pcm += 2; - } while(--size); - } -} - -static void midireset(CMMIDI midi) { - - UINT8 work[4]; - - midiout_longmsg(midi->midihdl, EXCV_GMRESET, sizeof(EXCV_GMRESET)); - - work[1] = 0x7b; - work[2] = 0x00; - for (work[0]=0xb0; work[0]<0xc0; work[0]++) { - keydisp_midi(work); - sound_sync(); - midiout_shortmsg(midi->midihdl, MIDIOUTS3(work)); - } -} - -static void midisetparam(CMMIDI midi) { - - UINT8 i; - UINT j; - MIDICH mch; - - mch = midi->mch; - sound_sync(); - for (i=0; i<16; i++, mch++) { - if (mch->press != 0xff) { - midiout_shortmsg(midi->midihdl, MIDIOUTS(0xa0+i, mch->press, 0)); - } - if (mch->bend != 0xffff) { - midiout_shortmsg(midi->midihdl, (mch->bend << 8) + 0xe0+i); - } - for (j=0; jctrl[j+1] != 0xff) { - midiout_shortmsg(midi->midihdl, - MIDIOUTS(0xb0+i, midictrltbl[j], mch->ctrl[j+1])); - } - } - if (mch->prog != 0xff) { - midiout_shortmsg(midi->midihdl, MIDIOUTS(0xc0+i, mch->prog, 0)); - } - } -} - - -// ---- - -static UINT midiread(COMMNG self, UINT8 *data) { - - (void)self; - (void)data; - return(0); -} - -static UINT midiwrite(COMMNG self, UINT8 data) { - - CMMIDI midi; - MIDICH mch; - - midi = (CMMIDI)(self + 1); - switch(data) { - case MIDI_TIMING: - case MIDI_START: - case MIDI_CONTINUE: - case MIDI_STOP: - case MIDI_ACTIVESENSE: - case MIDI_SYSTEMRESET: - return(1); - } - if (midi->midictrl == MIDICTRL_READY) { - if (data & 0x80) { - midi->mpos = 0; - switch(data & 0xf0) { - case 0xc0: - case 0xd0: - midi->midictrl = MIDICTRL_2BYTES; - break; - - case 0x80: - case 0x90: - case 0xa0: - case 0xb0: - case 0xe0: - midi->midictrl = MIDICTRL_3BYTES; - midi->midilast = data; - break; - - default: - switch(data) { - case MIDI_EXCLUSIVE: - midi->midictrl = MIDICTRL_EXCLUSIVE; - break; - - case MIDI_TIMECODE: - midi->midictrl = MIDICTRL_TIMECODE; - break; - - case MIDI_SONGPOS: - midi->midictrl = MIDICTRL_SYSTEM; - midi->midisyscnt = 3; - break; - - case MIDI_SONGSELECT: - midi->midictrl = MIDICTRL_SYSTEM; - midi->midisyscnt = 2; - break; - - case MIDI_CABLESELECT: - midi->midictrl = MIDICTRL_SYSTEM; - midi->midisyscnt = 1; - break; - -// case MIDI_TUNEREQUEST: -// case MIDI_EOX: - default: - return(1); - } - break; - } - } - else { // Key-onのみな気がしたんだけど忘れた… - // running status - midi->buffer[0] = midi->midilast; - midi->mpos = 1; - midi->midictrl = MIDICTRL_3BYTES; - } - } - midi->buffer[midi->mpos] = data; - midi->mpos++; - - switch(midi->midictrl) { - case MIDICTRL_2BYTES: - if (midi->mpos >= 2) { - midi->buffer[1] &= 0x7f; - mch = midi->mch + (midi->buffer[0] & 0xf); - switch(midi->buffer[0] & 0xf0) { - case 0xa0: - mch->press = midi->buffer[1]; - break; - - case 0xc0: - mch->prog = midi->buffer[1]; - break; - } - keydisp_midi(midi->buffer); - sound_sync(); - midiout_shortmsg(midi->midihdl, MIDIOUTS2(midi->buffer)); - midi->midictrl = MIDICTRL_READY; - return(2); - } - break; - - case MIDICTRL_3BYTES: - if (midi->mpos >= 3) { - midi->buffer[1] &= 0x7f; - midi->buffer[2] &= 0x7f; - mch = midi->mch + (midi->buffer[0] & 0xf); - switch(midi->buffer[0] & 0xf0) { - case 0xb0: - if (midi->buffer[1] == 123) { - mch->press = 0; - mch->bend = 0x4000; - mch->ctrl[1+1] = 0; // Modulation - mch->ctrl[5+1] = 127; // Explession - mch->ctrl[6+1] = 0; // Hold - mch->ctrl[7+1] = 0; // Portament - mch->ctrl[8+1] = 0; // Sostenute - mch->ctrl[9+1] = 0; // Soft - } - else { - mch->ctrl[midictrlindex[midi->buffer[1]]] - = midi->buffer[2]; - } - break; - - case 0xe0: - mch->bend = LOADINTELWORD(midi->buffer + 1); - break; - } - keydisp_midi(midi->buffer); - sound_sync(); - midiout_shortmsg(midi->midihdl, MIDIOUTS3(midi->buffer)); - midi->midictrl = MIDICTRL_READY; - return(3); - } - break; - - case MIDICTRL_EXCLUSIVE: - if (data == MIDI_EOX) { - midiout_longmsg(midi->midihdl, midi->buffer, midi->mpos); - midi->midictrl = MIDICTRL_READY; - return(midi->mpos); - } - else if (midi->mpos >= MIDI_BUFFER) { // おーばーふろー - midi->midictrl = MIDICTRL_READY; - } - break; - - case MIDICTRL_TIMECODE: - if (midi->mpos >= 2) { - if ((data == 0x7e) || (data == 0x7f)) { - // exclusiveと同じでいい筈… - midi->midictrl = MIDICTRL_EXCLUSIVE; - } - else { - midi->midictrl = MIDICTRL_READY; - return(2); - } - } - break; - - case MIDICTRL_SYSTEM: - if (midi->mpos >= midi->midisyscnt) { - midi->midictrl = MIDICTRL_READY; - return(midi->midisyscnt); - } - break; - } - return(0); -} - -static UINT8 midigetstat(COMMNG self) { - - return(0x00); -} - -static INTPTR midimsg(COMMNG self, UINT msg, INTPTR param) { - - CMMIDI midi; - COMFLAG flag; - - midi = (CMMIDI)(self + 1); - switch(msg) { - case COMMSG_MIDIRESET: - midireset(midi); - return(1); - - case COMMSG_SETFLAG: - flag = (COMFLAG)param; - if ((flag) && - (flag->size == sizeof(_COMFLAG) + sizeof(midi->mch)) && - (flag->sig == COMSIG_MIDI)) { - CopyMemory(midi->mch, flag + 1, sizeof(midi->mch)); - midisetparam(midi); - return(1); - } - break; - - case COMMSG_GETFLAG: - flag = (COMFLAG)_MALLOC(sizeof(_COMFLAG) + sizeof(midi->mch), - "MIDI FLAG"); - if (flag) { - flag->size = sizeof(_COMFLAG) + sizeof(midi->mch); - flag->sig = COMSIG_MIDI; - flag->ver = 0; - flag->param = 0; - CopyMemory(flag + 1, midi->mch, sizeof(midi->mch)); - return((INTPTR)flag); - } - break; - } - return(0); -} - -static void midirelease(COMMNG self) { - - CMMIDI midi; - - midi = (CMMIDI)(self + 1); - midiout_destroy(midi->midihdl); - _MFREE(self); -} - - -// ---- - -void cmvermouth_initialize(void) { - - UINT i; - - ZeroMemory(midictrlindex, sizeof(midictrlindex)); - for (i=0; iconnect = COMCONNECT_MIDI; - ret->read = midiread; - ret->write = midiwrite; - ret->getstat = midigetstat; - ret->msg = midimsg; - ret->release = midirelease; - midi = (CMMIDI)(ret + 1); - ZeroMemory(midi, sizeof(_CMMIDI)); - midi->midihdl = midihdl; - sound_streamregist((void *)midihdl, (SOUNDCB)vermouth_getpcm); - midi->midictrl = MIDICTRL_READY; -// midi->midisyscnt = 0; -// midi->mpos = 0; - midi->midilast = 0x80; - FillMemory(midi->mch, sizeof(midi->mch), 0xff); - return(ret); - -cmcre_err2: - midiout_destroy(midihdl); - -cmcre_err1: - return(NULL); -} - -#else - -void cmvermouth_initialize(void) { -} - -COMMNG cmvermouth_create(void) { - - return(NULL); -} - -#endif - +#include +#include +//#include + + +#if defined(VERMOUTH_LIB) + +#include +#include "sound/vermouth/vermouth.h" +#include + +#define MIDIOUTS(a, b, c) (((c) << 16) + (b << 8) + (a)) +#define MIDIOUTS2(a) ((a)[0] + ((a)[1] << 8)) +#define MIDIOUTS3(a) ((a)[0] + ((a)[1] << 8) + ((a)[2] << 16)) + +static const UINT8 EXCV_GMRESET[] = { + 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7}; + +enum { + MIDI_EXCLUSIVE = 0xf0, + MIDI_TIMECODE = 0xf1, + MIDI_SONGPOS = 0xf2, + MIDI_SONGSELECT = 0xf3, + MIDI_CABLESELECT = 0xf5, + MIDI_TUNEREQUEST = 0xf6, + MIDI_EOX = 0xf7, + MIDI_TIMING = 0xf8, + MIDI_START = 0xfa, + MIDI_CONTINUE = 0xfb, + MIDI_STOP = 0xfc, + MIDI_ACTIVESENSE = 0xfe, + MIDI_SYSTEMRESET = 0xff +}; + +enum { + MIDI_BUFFER = (1 << 10), + MIDIIN_MAX = 4, + + MIDICTRL_READY = 0, + MIDICTRL_2BYTES, + MIDICTRL_3BYTES, + MIDICTRL_EXCLUSIVE, + MIDICTRL_TIMECODE, + MIDICTRL_SYSTEM +}; + +typedef struct { + UINT8 prog; + UINT8 press; + UINT16 bend; + UINT8 ctrl[28]; +} _MIDICH, *MIDICH; + +typedef struct { + MIDIHDL midihdl; + UINT midictrl; + UINT midisyscnt; + UINT mpos; + UINT8 midilast; + _MIDICH mch[16]; + UINT8 buffer[MIDI_BUFFER]; +} _CMMIDI, *CMMIDI; + +typedef struct { + MIDIMOD vermouth; + UINT rate; +} CMVER; + +static const UINT8 midictrltbl[] = { 0, 1, 5, 7, 10, 11, 64, + 65, 66, 67, 84, 91, 93, + 94, // for SC-88 + 71, 72, 73, 74}; // for XG + +static CMVER cmver; +static UINT8 midictrlindex[128]; + + +// ---- + +static void SOUNDCALL vermouth_getpcm(MIDIHDL hdl, SINT32 *pcm, UINT count) { + +const SINT32 *ptr; + UINT size; + + while(count) { + size = count; + ptr = midiout_get(hdl, &size); + if (ptr == NULL) { + break; + } + count -= size; + do { + pcm[0] += ptr[0]; + pcm[1] += ptr[1]; + ptr += 2; + pcm += 2; + } while(--size); + } +} + +static void midireset(CMMIDI midi) { + + UINT8 work[4]; + + midiout_longmsg(midi->midihdl, EXCV_GMRESET, sizeof(EXCV_GMRESET)); + + work[1] = 0x7b; + work[2] = 0x00; + for (work[0]=0xb0; work[0]<0xc0; work[0]++) { + keydisp_midi(work); + sound_sync(); + midiout_shortmsg(midi->midihdl, MIDIOUTS3(work)); + } +} + +static void midisetparam(CMMIDI midi) { + + UINT8 i; + UINT j; + MIDICH mch; + + mch = midi->mch; + sound_sync(); + for (i=0; i<16; i++, mch++) { + if (mch->press != 0xff) { + midiout_shortmsg(midi->midihdl, MIDIOUTS(0xa0+i, mch->press, 0)); + } + if (mch->bend != 0xffff) { + midiout_shortmsg(midi->midihdl, (mch->bend << 8) + 0xe0+i); + } + for (j=0; jctrl[j+1] != 0xff) { + midiout_shortmsg(midi->midihdl, + MIDIOUTS(0xb0+i, midictrltbl[j], mch->ctrl[j+1])); + } + } + if (mch->prog != 0xff) { + midiout_shortmsg(midi->midihdl, MIDIOUTS(0xc0+i, mch->prog, 0)); + } + } +} + + +// ---- + +static UINT midiread(COMMNG self, UINT8 *data) { + + (void)self; + (void)data; + return(0); +} + +static UINT midiwrite(COMMNG self, UINT8 data) { + + CMMIDI midi; + MIDICH mch; + + midi = (CMMIDI)(self + 1); + switch(data) { + case MIDI_TIMING: + case MIDI_START: + case MIDI_CONTINUE: + case MIDI_STOP: + case MIDI_ACTIVESENSE: + case MIDI_SYSTEMRESET: + return(1); + } + if (midi->midictrl == MIDICTRL_READY) { + if (data & 0x80) { + midi->mpos = 0; + switch(data & 0xf0) { + case 0xc0: + case 0xd0: + midi->midictrl = MIDICTRL_2BYTES; + break; + + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: + case 0xe0: + midi->midictrl = MIDICTRL_3BYTES; + midi->midilast = data; + break; + + default: + switch(data) { + case MIDI_EXCLUSIVE: + midi->midictrl = MIDICTRL_EXCLUSIVE; + break; + + case MIDI_TIMECODE: + midi->midictrl = MIDICTRL_TIMECODE; + break; + + case MIDI_SONGPOS: + midi->midictrl = MIDICTRL_SYSTEM; + midi->midisyscnt = 3; + break; + + case MIDI_SONGSELECT: + midi->midictrl = MIDICTRL_SYSTEM; + midi->midisyscnt = 2; + break; + + case MIDI_CABLESELECT: + midi->midictrl = MIDICTRL_SYSTEM; + midi->midisyscnt = 1; + break; + +// case MIDI_TUNEREQUEST: +// case MIDI_EOX: + default: + return(1); + } + break; + } + } + else { // Key-onのみな気がしたんだけど忘れた… + // running status + midi->buffer[0] = midi->midilast; + midi->mpos = 1; + midi->midictrl = MIDICTRL_3BYTES; + } + } + midi->buffer[midi->mpos] = data; + midi->mpos++; + + switch(midi->midictrl) { + case MIDICTRL_2BYTES: + if (midi->mpos >= 2) { + midi->buffer[1] &= 0x7f; + mch = midi->mch + (midi->buffer[0] & 0xf); + switch(midi->buffer[0] & 0xf0) { + case 0xa0: + mch->press = midi->buffer[1]; + break; + + case 0xc0: + mch->prog = midi->buffer[1]; + break; + } + keydisp_midi(midi->buffer); + sound_sync(); + midiout_shortmsg(midi->midihdl, MIDIOUTS2(midi->buffer)); + midi->midictrl = MIDICTRL_READY; + return(2); + } + break; + + case MIDICTRL_3BYTES: + if (midi->mpos >= 3) { + midi->buffer[1] &= 0x7f; + midi->buffer[2] &= 0x7f; + mch = midi->mch + (midi->buffer[0] & 0xf); + switch(midi->buffer[0] & 0xf0) { + case 0xb0: + if (midi->buffer[1] == 123) { + mch->press = 0; + mch->bend = 0x4000; + mch->ctrl[1+1] = 0; // Modulation + mch->ctrl[5+1] = 127; // Explession + mch->ctrl[6+1] = 0; // Hold + mch->ctrl[7+1] = 0; // Portament + mch->ctrl[8+1] = 0; // Sostenute + mch->ctrl[9+1] = 0; // Soft + } + else { + mch->ctrl[midictrlindex[midi->buffer[1]]] + = midi->buffer[2]; + } + break; + + case 0xe0: + mch->bend = LOADINTELWORD(midi->buffer + 1); + break; + } + keydisp_midi(midi->buffer); + sound_sync(); + midiout_shortmsg(midi->midihdl, MIDIOUTS3(midi->buffer)); + midi->midictrl = MIDICTRL_READY; + return(3); + } + break; + + case MIDICTRL_EXCLUSIVE: + if (data == MIDI_EOX) { + midiout_longmsg(midi->midihdl, midi->buffer, midi->mpos); + midi->midictrl = MIDICTRL_READY; + return(midi->mpos); + } + else if (midi->mpos >= MIDI_BUFFER) { // おーばーふろー + midi->midictrl = MIDICTRL_READY; + } + break; + + case MIDICTRL_TIMECODE: + if (midi->mpos >= 2) { + if ((data == 0x7e) || (data == 0x7f)) { + // exclusiveと同じでいい筈… + midi->midictrl = MIDICTRL_EXCLUSIVE; + } + else { + midi->midictrl = MIDICTRL_READY; + return(2); + } + } + break; + + case MIDICTRL_SYSTEM: + if (midi->mpos >= midi->midisyscnt) { + midi->midictrl = MIDICTRL_READY; + return(midi->midisyscnt); + } + break; + } + return(0); +} + +static UINT8 midigetstat(COMMNG self) { + + return(0x00); +} + +static INTPTR midimsg(COMMNG self, UINT msg, INTPTR param) { + + CMMIDI midi; + COMFLAG flag; + + midi = (CMMIDI)(self + 1); + switch(msg) { + case COMMSG_MIDIRESET: + midireset(midi); + return(1); + + case COMMSG_SETFLAG: + flag = (COMFLAG)param; + if ((flag) && + (flag->size == sizeof(_COMFLAG) + sizeof(midi->mch)) && + (flag->sig == COMSIG_MIDI)) { + CopyMemory(midi->mch, flag + 1, sizeof(midi->mch)); + midisetparam(midi); + return(1); + } + break; + + case COMMSG_GETFLAG: + flag = (COMFLAG)_MALLOC(sizeof(_COMFLAG) + sizeof(midi->mch), + "MIDI FLAG"); + if (flag) { + flag->size = sizeof(_COMFLAG) + sizeof(midi->mch); + flag->sig = COMSIG_MIDI; + flag->ver = 0; + flag->param = 0; + CopyMemory(flag + 1, midi->mch, sizeof(midi->mch)); + return((INTPTR)flag); + } + break; + } + return(0); +} + +static void midirelease(COMMNG self) { + + CMMIDI midi; + + midi = (CMMIDI)(self + 1); + midiout_destroy(midi->midihdl); + _MFREE(self); +} + + +// ---- + +void cmvermouth_initialize(void) { + + UINT i; + + ZeroMemory(midictrlindex, sizeof(midictrlindex)); + for (i=0; iconnect = COMCONNECT_MIDI; + ret->read = midiread; + ret->write = midiwrite; + ret->getstat = midigetstat; + ret->msg = midimsg; + ret->release = midirelease; + midi = (CMMIDI)(ret + 1); + ZeroMemory(midi, sizeof(_CMMIDI)); + midi->midihdl = midihdl; + sound_streamregist((void *)midihdl, (SOUNDCB)vermouth_getpcm); + midi->midictrl = MIDICTRL_READY; +// midi->midisyscnt = 0; +// midi->mpos = 0; + midi->midilast = 0x80; + FillMemory(midi->mch, sizeof(midi->mch), 0xff); + return(ret); + +cmcre_err2: + midiout_destroy(midihdl); + +cmcre_err1: + return(NULL); +} + +#else + +void cmvermouth_initialize(void) { +} + +COMMNG cmvermouth_create(void) { + + return(NULL); +} + +#endif + diff --git a/generic/cmver.h b/generic/cmver.h old mode 100755 new mode 100644 index 2e56127c..d2ef2d3c --- a/generic/cmver.h +++ b/generic/cmver.h @@ -1,25 +1,25 @@ - -// vermouthのみ使用のCOMMNG-MIDI -// あまりに一緒すぎるんで 関数名変えてこっちへ - -#include - -// ---- com manager midi for vermouth - -#define COMSIG_MIDI 0x4944494d - -#ifdef __cplusplus -extern "C" { -#endif - -void cmvermouth_initialize(void); -COMMNG cmvermouth_create(void); -#if defined(VERMOUTH_LIB) -void cmvermouth_load(UINT rate); -void cmvermouth_unload(void); -#endif - -#ifdef __cplusplus -} -#endif - + +// vermouthのみ使用のCOMMNG-MIDI +// あまりに一緒すぎるんで 関数名変えてこっちへ + +#include + +// ---- com manager midi for vermouth + +#define COMSIG_MIDI 0x4944494d + +#ifdef __cplusplus +extern "C" { +#endif + +void cmvermouth_initialize(void); +COMMNG cmvermouth_create(void); +#if defined(VERMOUTH_LIB) +void cmvermouth_load(UINT rate); +void cmvermouth_unload(void); +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/generic/dipswbmp.c b/generic/dipswbmp.c old mode 100755 new mode 100644 index 5beadf04..f92dc98c --- a/generic/dipswbmp.c +++ b/generic/dipswbmp.c @@ -1,453 +1,453 @@ -#include -#include -#include -#include "dipswbmp.res" - -#if defined(USE_RESOURCE_BMP) - -typedef struct { - BMPDATA inf; - UINT8 *ptr; - int yalign; -} DIPBMP; - - -static UINT8 *getbmp(const UINT8 *dat, DIPBMP *dipbmp) { - - BMPFILE *ret; - - ret = (BMPFILE *)bmpdata_solvedata(dat); - if (ret == NULL) { - goto gb_err1; - } - if ((ret->bfType[0] != 'B') || (ret->bfType[1] != 'M')) { - goto gb_err2; - } - if (bmpdata_getinfo((BMPINFO *)(ret + 1), &dipbmp->inf) != SUCCESS) { - goto gb_err2; - } - dipbmp->yalign = bmpdata_getalign((BMPINFO *)(ret + 1)); - dipbmp->ptr = ((UINT8 *)ret) + (LOADINTELDWORD(ret->bfOffBits)); - if (dipbmp->inf.height < 0) { - dipbmp->inf.height *= -1; - } - else { - dipbmp->ptr += (dipbmp->inf.height - 1) * dipbmp->yalign; - dipbmp->yalign *= -1; - } - return((UINT8 *)ret); - -gb_err2: - _MFREE(ret); - -gb_err1: - return(NULL); -} - -static UINT8 *getbmpres(const OEMCHAR* resname, DIPBMP *dipbmp) { - -#if defined(_WIN32) - BMPFILE *ret; - HRSRC hRsrc; - HANDLE hRes; - LPVOID hBmpRes; - int ressize; - - hRsrc = FindResource(NULL, resname, OEMTEXT("RAWBMP")); - if (hRsrc == NULL) { - goto gb_err1; - } - hRes = LoadResource(NULL, hRsrc); - if (hRes == NULL) { - goto gb_err1; - } - hBmpRes = LockResource(hRes); - if (hBmpRes == NULL) { - goto gb_err1; - } - ressize = SizeofResource(NULL, hRsrc); - ret = (BMPFILE*)_MALLOC(ressize, "res"); - if (ret == NULL) { - goto gb_err1; - } - memcpy(ret, hBmpRes, ressize); - if ((ret->bfType[0] != 'B') || (ret->bfType[1] != 'M')) { - goto gb_err2; - } - if (bmpdata_getinfo((BMPINFO *)(ret + 1), &dipbmp->inf) != SUCCESS) { - goto gb_err2; - } - dipbmp->yalign = bmpdata_getalign((BMPINFO *)(ret + 1)); - dipbmp->ptr = ((UINT8 *)ret) + (LOADINTELDWORD(ret->bfOffBits)); - if (dipbmp->inf.height < 0) { - dipbmp->inf.height *= -1; - } - else { - dipbmp->ptr += (dipbmp->inf.height - 1) * dipbmp->yalign; - dipbmp->yalign *= -1; - } - return((UINT8 *)ret); - -gb_err2: - _MFREE(ret); - -gb_err1: -#endif - return(NULL); -} - -static void line4x(const DIPBMP *dipbmp, int x, int y, int l, UINT8 c) { - - UINT8 *ptr; - - ptr = dipbmp->ptr + (y * dipbmp->yalign); - while(l--) { - if (x & 1) { - ptr[x/2] &= 0xf0; - ptr[x/2] |= c; - } - else { - ptr[x/2] &= 0x0f; - ptr[x/2] |= (c << 4); - } - x++; - } -} - -static void line4y(const DIPBMP *dipbmp, int x, int y, int l, UINT8 c) { - - UINT8 *ptr; - UINT8 mask; - - ptr = dipbmp->ptr + (x / 2) + (y * dipbmp->yalign); - if (x & 1) { - mask = 0xf0; - } - else { - mask = 0x0f; - c <<= 4; - } - while(l--) { - *ptr &= mask; - *ptr |= c; - ptr += dipbmp->yalign; - } -} - - -// ---- jumper - -static void setjumperx(const DIPBMP *dipbmp, int x, int y) { - - int i; - - x *= 9; - y *= 9; - for (i=0; i<2; i++) { - line4x(dipbmp, x, y+0+i, 19, 0); - line4x(dipbmp, x, y+8+i, 19, 0); - line4y(dipbmp, x+ 0+i, y, 9, 0); - line4y(dipbmp, x+17+i, y, 9, 0); - } -} - -static void setjumpery(const DIPBMP *dipbmp, int x, int y) { - - int i; - - x *= 9; - y *= 9; - for (i=0; i<2; i++) { - line4x(dipbmp, x, y+ 0+i, 9, 0); - line4x(dipbmp, x, y+17+i, 9, 0); - line4y(dipbmp, x+0+i, y, 19, 0); - line4y(dipbmp, x+8+i, y, 19, 0); - } -} - -static void setjumperxex(const DIPBMP *dipbmp, int ofsx, int ofsy, int x, int y, UINT8 c) { - - int i; - - x *= 9; - y *= 9; - x += ofsx; - y += ofsy; - for (i=0; i<2; i++) { - line4x(dipbmp, x, y+0+i, 19, c); - line4x(dipbmp, x, y+8+i, 19, c); - line4y(dipbmp, x+ 0+i, y, 9, c); - line4y(dipbmp, x+17+i, y, 9, c); - } -} - -static void setjumperyex(const DIPBMP *dipbmp, int ofsx, int ofsy, int x, int y, UINT8 c) { - - int i; - - x *= 9; - y *= 9; - x += ofsx; - y += ofsy; - for (i=0; i<2; i++) { - line4x(dipbmp, x, y+ 0+i, 9, c); - line4x(dipbmp, x, y+17+i, 9, c); - line4y(dipbmp, x+0+i, y, 19, c); - line4y(dipbmp, x+8+i, y, 19, c); - } -} - - -// ---- pc-9861k - -static void setdip9861(const DIPBMP *dipbmp, const DIP9861 *pos, UINT8 cfg) { - - int x; - UINT c; - int y; - int l; - - x = (pos->x * 9) + 1; - c = pos->cnt; - do { - y = pos->y * 9 + ((cfg & 0x01)?5:9); - l = 0; - do { - line4x(dipbmp, x, y + l, 7, 0); - } while(++l < 3); - x += 9; - cfg >>= 1; - } while(--c); -} - -static void setjmp9861(const DIPBMP *dipbmp, const DIP9861 *pos, UINT8 cfg) { - - int x; - int y; - UINT c; - - x = pos->x; - y = pos->y; - c = pos->cnt; - do { - if (cfg & 0x01) { - setjumpery(dipbmp, x, y); - } - x++; - cfg >>= 1; - } while(--c); -} - -UINT8 *dipswbmp_get9861(const UINT8 *s, const UINT8 *j) { - - UINT8 *ret; - DIPBMP dipbmp; - int i; - - ret = getbmp(bmp9861, &dipbmp); - if (ret) { - for (i=0; i<3; i++) { - setdip9861(&dipbmp, dip9861s + i, s[i]); - } - for (i=0; i<6; i++) { - setjmp9861(&dipbmp, dip9861j + i, j[i]); - } - } - return(ret); -} - - -// ---- sound - -static void setsnd26io(const DIPBMP *dipbmp, int px, int py, UINT8 cfg) { - - setjumpery(dipbmp, px + ((cfg & 0x10)?1:0), py); -} - -static void setsnd26int(const DIPBMP *dipbmp, int px, int py, UINT8 cfg) { - - setjumperx(dipbmp, px + ((cfg & 0x80)?0:1), py); - setjumperx(dipbmp, px + ((cfg & 0x40)?0:1), py + 1); -} - -static void setsnd26rom(const DIPBMP *dipbmp, int px, int py, UINT8 cfg) { - - cfg &= 7; - if (cfg >= 4) { - cfg = 4; - } - setjumpery(dipbmp, px + cfg, py); -} - -UINT8 *dipswbmp_getsnd26(UINT8 cfg) { - - UINT8 *ret; - DIPBMP dipbmp; - - ret = getbmp(bmp26, &dipbmp); - if (ret) { - setsnd26io(&dipbmp, 15, 1, cfg); - setsnd26int(&dipbmp, 9, 1, cfg); - setsnd26rom(&dipbmp, 2, 1, cfg); - } - return(ret); -} - -UINT8 *dipswbmp_getsnd86(UINT8 cfg) { - - UINT8 *ret; - DIPBMP dipbmp; - int i; - int x; - int y; - int l; - - ret = getbmp(bmp86, &dipbmp); - if (ret) { - for (i=0; i<8; i++) { - x = i * 8 + 17; - y = (cfg & (1 << i))?16:9; - l = 0; - do { - line4x(&dipbmp, x, y + l, 6, 3); - } while(++l < 7); - } - } - return(ret); -} - -UINT8 *dipswbmp_getsndspb(UINT8 cfg, UINT8 vrc) { - - UINT8 *ret; - DIPBMP dipbmp; - - ret = getbmp(bmpspb, &dipbmp); - if (ret) { - setsnd26int(&dipbmp, 2, 1, cfg); - setsnd26io(&dipbmp, 10, 1, cfg); - setsnd26rom(&dipbmp, 14, 1, cfg); - if (cfg & 0x20) { - setjumpery(&dipbmp, 7, 1); - } - setjumperx(&dipbmp, ((vrc & 2)?21:22), 1); - setjumperx(&dipbmp, ((vrc & 1)?21:22), 2); - } - return(ret); -} - -UINT8 *dipswbmp_getmpu(UINT8 cfg) { - - UINT8 *ret; - DIPBMP dipbmp; - int i; - int x; - int y; - int l; - - ret = getbmp(bmpmpu, &dipbmp); - if (ret) { - for (i=0; i<4; i++) { - x = (i + 2) * 9 + 1; - y = (1 * 9) + ((cfg & (0x80 >> i))?5:9); - l = 0; - do { - line4x(&dipbmp, x, y + l, 7, 2); - } while(++l < 3); - } - setjumpery(&dipbmp, 9 + 3 - (cfg & 3), 1); - } - return(ret); -} -UINT8 *dipswbmp_getsmpu(UINT8 cfg) { - - UINT8 *ret; - DIPBMP dipbmp; - int i; - int x; - int y; - int l; - - ret = getbmp(bmpmpu, &dipbmp); - if (ret) { - for (i=0; i<4; i++) { - x = (i + 2) * 9 + 1; - y = (1 * 9) + ((cfg & (0x10 << i))?5:9); // 左右逆なだけっぽい - l = 0; - do { - line4x(&dipbmp, x, y + l, 7, 2); - } while(++l < 3); - } - setjumpery(&dipbmp, 9 + 3 - (cfg & 3), 1); - } - return(ret); -} - -UINT8 *dipswbmp_getsnd118(UINT16 snd118io, UINT8 snd118dma, UINT8 snd118irqf, UINT8 snd118irqp, UINT8 snd118irqm, UINT8 snd118rom) { - - UINT8 *ret; - DIPBMP dipbmp; - - ret = getbmpres(OEMTEXT("JUMPER118"), &dipbmp); - if (ret) { - int jmpflag[2]; - setjumperyex(&dipbmp, 18, 9, 0, 0, 15); // #12 常時OFF どこにも影響しない? - setjumperyex(&dipbmp, 18, 9, 1, 0, 15); // #11 YMF297の制御? - setjumperyex(&dipbmp, 18, 9, 2, snd118irqm==0xff ? 1 : 0, 15); // #10 - - // PCM INT (#8,#9)=(OFF,OFF):INT5(IRQ12), (OFF,ON):INT1(IRQ5), (ON,OFF):INT41(IRQ10), (ON,ON):INT0(IRQ3) - switch(snd118irqp){ - case 12: - jmpflag[0] = 0; jmpflag[1] = 0; - break; - case 5: - jmpflag[0] = 0; jmpflag[1] = 1; - break; - case 10: - jmpflag[0] = 1; jmpflag[1] = 0; - break; - case 3: - jmpflag[0] = 1; jmpflag[1] = 1; - break; - default: - jmpflag[0] = jmpflag[1] = 0; - break; - } - setjumperyex(&dipbmp, 18, 9, 3, jmpflag[1], 15); // #9 - setjumperyex(&dipbmp, 18, 9, 4, jmpflag[0], 15); // #8 - - setjumperyex(&dipbmp, 18, 9, 5, 0, 15); // #7 ON:DMA 2ch, OFF:DMA 1ch - - // FM INT (#5,#6)=(OFF,OFF):INT5(IRQ12), (OFF,ON):INT41(IRQ10), (ON,OFF):INT6(IRQ13), (ON,ON):INT0(IRQ3) - switch(snd118irqf){ - case 12: - jmpflag[0] = 0; jmpflag[1] = 0; - break; - case 10: - jmpflag[0] = 0; jmpflag[1] = 1; - break; - case 13: - jmpflag[0] = 1; jmpflag[1] = 0; - break; - case 3: - jmpflag[0] = 1; jmpflag[1] = 1; - break; - default: - jmpflag[0] = jmpflag[1] = 0; - break; - } - setjumperyex(&dipbmp, 18, 9, 6, jmpflag[1], 15); // #6 - setjumperyex(&dipbmp, 18, 9, 7, jmpflag[0], 15); // #5 - - setjumperyex(&dipbmp, 18, 9, 8, snd118rom ? 0 : 1, 15); // #4 ON:Sound BIOS Disable, OFF:Sound BIOS Enable - - // (#2,#3)=(OFF,OFF):Normal, (OFF,ON):CS4231&OPNA Disable, (ON,OFF):CS4231 Disable, (ON,ON):禁止 - setjumperyex(&dipbmp, 18, 9, 9, 0, 15); // #3 - setjumperyex(&dipbmp, 18, 9, 10, 0, 15); // #2 - - setjumperyex(&dipbmp, 18, 9, 11, 0, 15); // #1 ON:PnP Enable, OFF:PnP Disable - } - return(ret); -} - -#endif // defined(USE_RESOURCE_BMP) - +#include +#include +#include +#include "dipswbmp.res" + +#if defined(USE_RESOURCE_BMP) + +typedef struct { + BMPDATA inf; + UINT8 *ptr; + int yalign; +} DIPBMP; + + +static UINT8 *getbmp(const UINT8 *dat, DIPBMP *dipbmp) { + + BMPFILE *ret; + + ret = (BMPFILE *)bmpdata_solvedata(dat); + if (ret == NULL) { + goto gb_err1; + } + if ((ret->bfType[0] != 'B') || (ret->bfType[1] != 'M')) { + goto gb_err2; + } + if (bmpdata_getinfo((BMPINFO *)(ret + 1), &dipbmp->inf) != SUCCESS) { + goto gb_err2; + } + dipbmp->yalign = bmpdata_getalign((BMPINFO *)(ret + 1)); + dipbmp->ptr = ((UINT8 *)ret) + (LOADINTELDWORD(ret->bfOffBits)); + if (dipbmp->inf.height < 0) { + dipbmp->inf.height *= -1; + } + else { + dipbmp->ptr += (dipbmp->inf.height - 1) * dipbmp->yalign; + dipbmp->yalign *= -1; + } + return((UINT8 *)ret); + +gb_err2: + _MFREE(ret); + +gb_err1: + return(NULL); +} + +static UINT8 *getbmpres(const OEMCHAR* resname, DIPBMP *dipbmp) { + +#if defined(_WIN32) + BMPFILE *ret; + HRSRC hRsrc; + HANDLE hRes; + LPVOID hBmpRes; + int ressize; + + hRsrc = FindResource(NULL, resname, OEMTEXT("RAWBMP")); + if (hRsrc == NULL) { + goto gb_err1; + } + hRes = LoadResource(NULL, hRsrc); + if (hRes == NULL) { + goto gb_err1; + } + hBmpRes = LockResource(hRes); + if (hBmpRes == NULL) { + goto gb_err1; + } + ressize = SizeofResource(NULL, hRsrc); + ret = (BMPFILE*)_MALLOC(ressize, "res"); + if (ret == NULL) { + goto gb_err1; + } + memcpy(ret, hBmpRes, ressize); + if ((ret->bfType[0] != 'B') || (ret->bfType[1] != 'M')) { + goto gb_err2; + } + if (bmpdata_getinfo((BMPINFO *)(ret + 1), &dipbmp->inf) != SUCCESS) { + goto gb_err2; + } + dipbmp->yalign = bmpdata_getalign((BMPINFO *)(ret + 1)); + dipbmp->ptr = ((UINT8 *)ret) + (LOADINTELDWORD(ret->bfOffBits)); + if (dipbmp->inf.height < 0) { + dipbmp->inf.height *= -1; + } + else { + dipbmp->ptr += (dipbmp->inf.height - 1) * dipbmp->yalign; + dipbmp->yalign *= -1; + } + return((UINT8 *)ret); + +gb_err2: + _MFREE(ret); + +gb_err1: +#endif + return(NULL); +} + +static void line4x(const DIPBMP *dipbmp, int x, int y, int l, UINT8 c) { + + UINT8 *ptr; + + ptr = dipbmp->ptr + (y * dipbmp->yalign); + while(l--) { + if (x & 1) { + ptr[x/2] &= 0xf0; + ptr[x/2] |= c; + } + else { + ptr[x/2] &= 0x0f; + ptr[x/2] |= (c << 4); + } + x++; + } +} + +static void line4y(const DIPBMP *dipbmp, int x, int y, int l, UINT8 c) { + + UINT8 *ptr; + UINT8 mask; + + ptr = dipbmp->ptr + (x / 2) + (y * dipbmp->yalign); + if (x & 1) { + mask = 0xf0; + } + else { + mask = 0x0f; + c <<= 4; + } + while(l--) { + *ptr &= mask; + *ptr |= c; + ptr += dipbmp->yalign; + } +} + + +// ---- jumper + +static void setjumperx(const DIPBMP *dipbmp, int x, int y) { + + int i; + + x *= 9; + y *= 9; + for (i=0; i<2; i++) { + line4x(dipbmp, x, y+0+i, 19, 0); + line4x(dipbmp, x, y+8+i, 19, 0); + line4y(dipbmp, x+ 0+i, y, 9, 0); + line4y(dipbmp, x+17+i, y, 9, 0); + } +} + +static void setjumpery(const DIPBMP *dipbmp, int x, int y) { + + int i; + + x *= 9; + y *= 9; + for (i=0; i<2; i++) { + line4x(dipbmp, x, y+ 0+i, 9, 0); + line4x(dipbmp, x, y+17+i, 9, 0); + line4y(dipbmp, x+0+i, y, 19, 0); + line4y(dipbmp, x+8+i, y, 19, 0); + } +} + +static void setjumperxex(const DIPBMP *dipbmp, int ofsx, int ofsy, int x, int y, UINT8 c) { + + int i; + + x *= 9; + y *= 9; + x += ofsx; + y += ofsy; + for (i=0; i<2; i++) { + line4x(dipbmp, x, y+0+i, 19, c); + line4x(dipbmp, x, y+8+i, 19, c); + line4y(dipbmp, x+ 0+i, y, 9, c); + line4y(dipbmp, x+17+i, y, 9, c); + } +} + +static void setjumperyex(const DIPBMP *dipbmp, int ofsx, int ofsy, int x, int y, UINT8 c) { + + int i; + + x *= 9; + y *= 9; + x += ofsx; + y += ofsy; + for (i=0; i<2; i++) { + line4x(dipbmp, x, y+ 0+i, 9, c); + line4x(dipbmp, x, y+17+i, 9, c); + line4y(dipbmp, x+0+i, y, 19, c); + line4y(dipbmp, x+8+i, y, 19, c); + } +} + + +// ---- pc-9861k + +static void setdip9861(const DIPBMP *dipbmp, const DIP9861 *pos, UINT8 cfg) { + + int x; + UINT c; + int y; + int l; + + x = (pos->x * 9) + 1; + c = pos->cnt; + do { + y = pos->y * 9 + ((cfg & 0x01)?5:9); + l = 0; + do { + line4x(dipbmp, x, y + l, 7, 0); + } while(++l < 3); + x += 9; + cfg >>= 1; + } while(--c); +} + +static void setjmp9861(const DIPBMP *dipbmp, const DIP9861 *pos, UINT8 cfg) { + + int x; + int y; + UINT c; + + x = pos->x; + y = pos->y; + c = pos->cnt; + do { + if (cfg & 0x01) { + setjumpery(dipbmp, x, y); + } + x++; + cfg >>= 1; + } while(--c); +} + +UINT8 *dipswbmp_get9861(const UINT8 *s, const UINT8 *j) { + + UINT8 *ret; + DIPBMP dipbmp; + int i; + + ret = getbmp(bmp9861, &dipbmp); + if (ret) { + for (i=0; i<3; i++) { + setdip9861(&dipbmp, dip9861s + i, s[i]); + } + for (i=0; i<6; i++) { + setjmp9861(&dipbmp, dip9861j + i, j[i]); + } + } + return(ret); +} + + +// ---- sound + +static void setsnd26io(const DIPBMP *dipbmp, int px, int py, UINT8 cfg) { + + setjumpery(dipbmp, px + ((cfg & 0x10)?1:0), py); +} + +static void setsnd26int(const DIPBMP *dipbmp, int px, int py, UINT8 cfg) { + + setjumperx(dipbmp, px + ((cfg & 0x80)?0:1), py); + setjumperx(dipbmp, px + ((cfg & 0x40)?0:1), py + 1); +} + +static void setsnd26rom(const DIPBMP *dipbmp, int px, int py, UINT8 cfg) { + + cfg &= 7; + if (cfg >= 4) { + cfg = 4; + } + setjumpery(dipbmp, px + cfg, py); +} + +UINT8 *dipswbmp_getsnd26(UINT8 cfg) { + + UINT8 *ret; + DIPBMP dipbmp; + + ret = getbmp(bmp26, &dipbmp); + if (ret) { + setsnd26io(&dipbmp, 15, 1, cfg); + setsnd26int(&dipbmp, 9, 1, cfg); + setsnd26rom(&dipbmp, 2, 1, cfg); + } + return(ret); +} + +UINT8 *dipswbmp_getsnd86(UINT8 cfg) { + + UINT8 *ret; + DIPBMP dipbmp; + int i; + int x; + int y; + int l; + + ret = getbmp(bmp86, &dipbmp); + if (ret) { + for (i=0; i<8; i++) { + x = i * 8 + 17; + y = (cfg & (1 << i))?16:9; + l = 0; + do { + line4x(&dipbmp, x, y + l, 6, 3); + } while(++l < 7); + } + } + return(ret); +} + +UINT8 *dipswbmp_getsndspb(UINT8 cfg, UINT8 vrc) { + + UINT8 *ret; + DIPBMP dipbmp; + + ret = getbmp(bmpspb, &dipbmp); + if (ret) { + setsnd26int(&dipbmp, 2, 1, cfg); + setsnd26io(&dipbmp, 10, 1, cfg); + setsnd26rom(&dipbmp, 14, 1, cfg); + if (cfg & 0x20) { + setjumpery(&dipbmp, 7, 1); + } + setjumperx(&dipbmp, ((vrc & 2)?21:22), 1); + setjumperx(&dipbmp, ((vrc & 1)?21:22), 2); + } + return(ret); +} + +UINT8 *dipswbmp_getmpu(UINT8 cfg) { + + UINT8 *ret; + DIPBMP dipbmp; + int i; + int x; + int y; + int l; + + ret = getbmp(bmpmpu, &dipbmp); + if (ret) { + for (i=0; i<4; i++) { + x = (i + 2) * 9 + 1; + y = (1 * 9) + ((cfg & (0x80 >> i))?5:9); + l = 0; + do { + line4x(&dipbmp, x, y + l, 7, 2); + } while(++l < 3); + } + setjumpery(&dipbmp, 9 + 3 - (cfg & 3), 1); + } + return(ret); +} +UINT8 *dipswbmp_getsmpu(UINT8 cfg) { + + UINT8 *ret; + DIPBMP dipbmp; + int i; + int x; + int y; + int l; + + ret = getbmp(bmpmpu, &dipbmp); + if (ret) { + for (i=0; i<4; i++) { + x = (i + 2) * 9 + 1; + y = (1 * 9) + ((cfg & (0x10 << i))?5:9); // 左右逆なだけっぽい + l = 0; + do { + line4x(&dipbmp, x, y + l, 7, 2); + } while(++l < 3); + } + setjumpery(&dipbmp, 9 + 3 - (cfg & 3), 1); + } + return(ret); +} + +UINT8 *dipswbmp_getsnd118(UINT16 snd118io, UINT8 snd118dma, UINT8 snd118irqf, UINT8 snd118irqp, UINT8 snd118irqm, UINT8 snd118rom) { + + UINT8 *ret; + DIPBMP dipbmp; + + ret = getbmpres(OEMTEXT("JUMPER118"), &dipbmp); + if (ret) { + int jmpflag[2]; + setjumperyex(&dipbmp, 18, 9, 0, 0, 15); // #12 常時OFF どこにも影響しない? + setjumperyex(&dipbmp, 18, 9, 1, 0, 15); // #11 YMF297の制御? + setjumperyex(&dipbmp, 18, 9, 2, snd118irqm==0xff ? 1 : 0, 15); // #10 + + // PCM INT (#8,#9)=(OFF,OFF):INT5(IRQ12), (OFF,ON):INT1(IRQ5), (ON,OFF):INT41(IRQ10), (ON,ON):INT0(IRQ3) + switch(snd118irqp){ + case 12: + jmpflag[0] = 0; jmpflag[1] = 0; + break; + case 5: + jmpflag[0] = 0; jmpflag[1] = 1; + break; + case 10: + jmpflag[0] = 1; jmpflag[1] = 0; + break; + case 3: + jmpflag[0] = 1; jmpflag[1] = 1; + break; + default: + jmpflag[0] = jmpflag[1] = 0; + break; + } + setjumperyex(&dipbmp, 18, 9, 3, jmpflag[1], 15); // #9 + setjumperyex(&dipbmp, 18, 9, 4, jmpflag[0], 15); // #8 + + setjumperyex(&dipbmp, 18, 9, 5, 0, 15); // #7 ON:DMA 2ch, OFF:DMA 1ch + + // FM INT (#5,#6)=(OFF,OFF):INT5(IRQ12), (OFF,ON):INT41(IRQ10), (ON,OFF):INT6(IRQ13), (ON,ON):INT0(IRQ3) + switch(snd118irqf){ + case 12: + jmpflag[0] = 0; jmpflag[1] = 0; + break; + case 10: + jmpflag[0] = 0; jmpflag[1] = 1; + break; + case 13: + jmpflag[0] = 1; jmpflag[1] = 0; + break; + case 3: + jmpflag[0] = 1; jmpflag[1] = 1; + break; + default: + jmpflag[0] = jmpflag[1] = 0; + break; + } + setjumperyex(&dipbmp, 18, 9, 6, jmpflag[1], 15); // #6 + setjumperyex(&dipbmp, 18, 9, 7, jmpflag[0], 15); // #5 + + setjumperyex(&dipbmp, 18, 9, 8, snd118rom ? 0 : 1, 15); // #4 ON:Sound BIOS Disable, OFF:Sound BIOS Enable + + // (#2,#3)=(OFF,OFF):Normal, (OFF,ON):CS4231&OPNA Disable, (ON,OFF):CS4231 Disable, (ON,ON):禁止 + setjumperyex(&dipbmp, 18, 9, 9, 0, 15); // #3 + setjumperyex(&dipbmp, 18, 9, 10, 0, 15); // #2 + + setjumperyex(&dipbmp, 18, 9, 11, 0, 15); // #1 ON:PnP Enable, OFF:PnP Disable + } + return(ret); +} + +#endif // defined(USE_RESOURCE_BMP) + diff --git a/generic/dipswbmp.h b/generic/dipswbmp.h old mode 100755 new mode 100644 index 22887647..9c1c674e --- a/generic/dipswbmp.h +++ b/generic/dipswbmp.h @@ -1,24 +1,24 @@ -#if defined(USE_RESOURCE_BMP) - -#ifdef __cplusplus -extern "C"{ -#endif - - -// それぞれ 4bit BMPが返る (メモリ解放を行なうこと) - -UINT8 *dipswbmp_get9861(const UINT8 *s, const UINT8 *j); - -UINT8 *dipswbmp_getsnd26(UINT8 cfg); -UINT8 *dipswbmp_getsnd86(UINT8 cfg); -UINT8 *dipswbmp_getsndspb(UINT8 cfg, UINT8 vrc); -UINT8 *dipswbmp_getmpu(UINT8 cfg); -UINT8 *dipswbmp_getsmpu(UINT8 cfg); -UINT8 *dipswbmp_getsnd118(UINT16 snd118io, UINT8 snd118dma, UINT8 snd118irqf, UINT8 snd118irqp, UINT8 snd118irqm, UINT8 snd118rom); - -#ifdef __cplusplus -} -#endif - -#endif // defined(USE_RESOURCE_BMP) - +#if defined(USE_RESOURCE_BMP) + +#ifdef __cplusplus +extern "C"{ +#endif + + +// それぞれ 4bit BMPが返る (メモリ解放を行なうこと) + +UINT8 *dipswbmp_get9861(const UINT8 *s, const UINT8 *j); + +UINT8 *dipswbmp_getsnd26(UINT8 cfg); +UINT8 *dipswbmp_getsnd86(UINT8 cfg); +UINT8 *dipswbmp_getsndspb(UINT8 cfg, UINT8 vrc); +UINT8 *dipswbmp_getmpu(UINT8 cfg); +UINT8 *dipswbmp_getsmpu(UINT8 cfg); +UINT8 *dipswbmp_getsnd118(UINT16 snd118io, UINT8 snd118dma, UINT8 snd118irqf, UINT8 snd118irqp, UINT8 snd118irqm, UINT8 snd118rom); + +#ifdef __cplusplus +} +#endif + +#endif // defined(USE_RESOURCE_BMP) + diff --git a/generic/hostdrv.c b/generic/hostdrv.c old mode 100755 new mode 100644 index 58a44662..abcf406a --- a/generic/hostdrv.c +++ b/generic/hostdrv.c @@ -1,2098 +1,2098 @@ -#include - -#if defined(SUPPORT_HOSTDRV) - -/* - ゲストOS(DOS)からホストOS(Win)にアクセスするの〜 - 完全にDOS(3.1以上)依存だお(汗 - ネットワークインタフェイス搭載前の繋ぎだけど - 更に、手抜き版だし(マテ -*/ - -#include -#include -#include -#include -#include -#include -#include "hostdrv.tbl" - -// 性能上最適化で優先しない方がいいコードなのでわざと別セグメントに置く -#pragma code_seg(".MISCCODE") - -#if 0 -#undef TRACEOUT -static void trace_fmt_ex(const char* fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "\n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#endif /* 1 */ - - - -#define IS_PERMITWRITE (np2cfg.hdrvacc & HDFMODE_WRITE) -#define IS_PERMITDELETE (np2cfg.hdrvacc & HDFMODE_DELETE) - -#define ROOTPATH_NAME_NEW "A:\\" -#define ROOTPATH_NAME_OLD "\\\\HOSTDRV\\" -#define ROOTPATH_SIZE_NEW (sizeof(ROOTPATH_NAME_NEW) - 1) -#define ROOTPATH_SIZE_OLD (sizeof(ROOTPATH_NAME_OLD) - 1) - -static int ROOTPATH_SIZE = ROOTPATH_SIZE_OLD; -static char ROOTPATH[] = ROOTPATH_NAME_OLD; -static const HDRVFILE hdd_volume = {{'_','H','O','S','T','D','R','I','V','E','_'}, 0, 0, 0x08, {0}, {0}}; - - HOSTDRV hostdrv; - -// XXX: DTA単位の複数検索に対応 本当はステートセーブすべき -#define HOSTDRV_FINDHANDLE_INVALID 0xffffffff -#define HOSTDRV_FINDHANDLE_MAX 256 // さすがに同時に256検索出来れば十分でしょう… -static UINT32 hostdrv_findhandle_currentindex = HOSTDRV_FINDHANDLE_INVALID; // 現在有効なハンドルが格納されているインデックス -static HOSTDRV_FINDHANDLE hostdrv_findhandles[HOSTDRV_FINDHANDLE_MAX] = { 0 }; // 検索ハンドルリスト -static UINT32 hostdrv_writepos = 0; // リストへの書き込み位置 -static UINT32 hostdrv_findhandles_count = 0; // リスト項目数 - -static void hostdrv_findhandles_add(LISTARRAY flist, UINT flistpos) -{ - static UINT16 flistidx = 0; // 仮想的なクラスタ番号 - int i; - - if (flist == NULL) - { - // 無効 - hostdrv_findhandle_currentindex = HOSTDRV_FINDHANDLE_INVALID; - return; - } - for (i = 0; i < HOSTDRV_FINDHANDLE_MAX; i++) - { - if (hostdrv_findhandles[i].flist == flist) - { - hostdrv_findhandle_currentindex = i; - return; // 二重登録防止 - } - } - // 新規 - if (hostdrv_writepos == hostdrv_findhandle_currentindex) - { - // 現在使用中の場所は破棄できないのでずらす - hostdrv_writepos = (hostdrv_writepos + 1) % HOSTDRV_FINDHANDLE_MAX; - } - if (hostdrv_findhandles[hostdrv_writepos].flist != NULL) - { - listarray_destroy(hostdrv_findhandles[hostdrv_writepos].flist); // ハンドル閉じる - // カウント減らす - hostdrv_findhandles_count--; - } - hostdrv_findhandles[hostdrv_writepos].flist = flist; - hostdrv_findhandles[hostdrv_writepos].flistpos = flistpos; - hostdrv_findhandles[hostdrv_writepos].flistidx = flistidx; - flistidx++; - - // 現在有効なハンドルにする - hostdrv_findhandle_currentindex = hostdrv_writepos; - - // 次の書き込み位置を指定 - hostdrv_writepos = (hostdrv_writepos + 1) % HOSTDRV_FINDHANDLE_MAX; - - // カウント増やす - hostdrv_findhandles_count++; -} -static void hostdrv_findhandles_setcurrentbyflistidx(UINT16 flistidx) -{ - int i; - // 仮想クラスタ番号から検索ハンドルを選択 - for (i = 0; i < HOSTDRV_FINDHANDLE_MAX; i++) - { - if (hostdrv_findhandles[i].flist && hostdrv_findhandles[i].flistidx == flistidx) - { - hostdrv_findhandle_currentindex = i; - return; - } - } - hostdrv_findhandle_currentindex = HOSTDRV_FINDHANDLE_INVALID; -} -static HOSTDRV_FINDHANDLE* hostdrv_findhandles_getcurrent() -{ - if (hostdrv_findhandle_currentindex == HOSTDRV_FINDHANDLE_INVALID) return NULL; - - // 現在有効なハンドルを取得 - return &hostdrv_findhandles[hostdrv_findhandle_currentindex]; -} -static void hostdrv_findhandles_close() -{ - if (hostdrv_findhandle_currentindex == HOSTDRV_FINDHANDLE_INVALID) return; - - // 現在有効なハンドルを閉じる - hostdrv_findhandles[hostdrv_findhandle_currentindex].flist = NULL; - hostdrv_findhandles[hostdrv_findhandle_currentindex].flistpos = 0; - - // カウント減らす - hostdrv_findhandles_count--; - - if (hostdrv_findhandle_currentindex + 1 == hostdrv_writepos) - { - // この項目の次が書き込み位置になっていたとき、書き込み位置を戻して無駄に場所を使うのを避ける - hostdrv_writepos = hostdrv_findhandle_currentindex; - if (hostdrv_findhandles_count > 1) - { - // 更に手前のデータがない位置まで書き込み位置を戻して無駄に場所を使うのを避ける - int i; - for (i = 0; i < HOSTDRV_FINDHANDLE_MAX; i++) - { - UINT32 tmpWritePos = (hostdrv_writepos + HOSTDRV_FINDHANDLE_MAX - 1) % HOSTDRV_FINDHANDLE_MAX; - if (hostdrv_findhandles[tmpWritePos].flist != NULL) - { - break; - } - hostdrv_writepos = tmpWritePos; - } - } - } - hostdrv_findhandle_currentindex = HOSTDRV_FINDHANDLE_INVALID; -} -static void hostdrv_findhandles_clear() -{ - int i; - for (i = 0; i < HOSTDRV_FINDHANDLE_MAX; i++) - { - if (hostdrv_findhandles[i].flist) - { - listarray_destroy(hostdrv_findhandles[i].flist); // ハンドル閉じる - hostdrv_findhandles[i].flist = NULL; - hostdrv_findhandles[i].flistpos = 0; - hostdrv_findhandles[i].flistidx = 0; - } - } - // カウント0にする - hostdrv_findhandles_count = 0; -} - -// ---- i/f - -static void succeed(INTRST intrst) { - - intrst->r.b.flag_l &= ~C_FLAG; - STOREINTELWORD(intrst->r.w.ax, ERR_NOERROR); -} - -static void fail(INTRST intrst, UINT16 err_code) { - - intrst->r.b.flag_l |= C_FLAG; - STOREINTELWORD(intrst->r.w.ax, err_code); -} - - -static void fetch_if4dos(void) { - - REG16 off; - REG16 seg; - IF4DOS if4dos; - - off = MEMR_READ16(IF4DOSPTR_SEG, IF4DOSPTR_OFF + 0); - seg = MEMR_READ16(IF4DOSPTR_SEG, IF4DOSPTR_OFF + 2); - MEMR_READS(seg, off, &if4dos, sizeof(if4dos)); - hostdrv.stat.drive_no = if4dos.drive_no; - hostdrv.stat.dosver_major = if4dos.dosver_major; - hostdrv.stat.dosver_minor = if4dos.dosver_minor; - hostdrv.stat.sda_off = LOADINTELWORD(if4dos.sda_off); - hostdrv.stat.sda_seg = LOADINTELWORD(if4dos.sda_seg); - - TRACEOUT(("hostdrv:drive_no = %d", if4dos.drive_no)); - TRACEOUT(("hostdrv:dosver = %d.%.2d", if4dos.dosver_major, if4dos.dosver_minor)); - TRACEOUT(("hostdrv.sda = %.4x:%.4x", hostdrv.stat.sda_seg, hostdrv.stat.sda_off)); -} - - -static void fetch_intr_regs(INTRST is) { - - MEMR_READS(CPU_SS, CPU_BP, &is->r, sizeof(is->r)); -} - -static void store_intr_regs(INTRST is) { - - MEMR_WRITES(CPU_SS, CPU_BP, &is->r, sizeof(is->r)); -} - - -static void fetch_sda_currcds(SDACDS sc) { - - REG16 off; - REG16 seg; - - if (hostdrv.stat.dosver_major == 3) { - MEMR_READS(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, - &sc->ver3.sda, sizeof(sc->ver3.sda)); - off = LOADINTELWORD(sc->ver3.sda.cdsptr.off); - seg = LOADINTELWORD(sc->ver3.sda.cdsptr.seg); - MEMR_READS(seg, off, &sc->ver3.cds, sizeof(sc->ver3.cds)); - } - else { - MEMR_READS(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, - &sc->ver4.sda, sizeof(sc->ver4.sda)); - off = LOADINTELWORD(sc->ver4.sda.cdsptr.off); - seg = LOADINTELWORD(sc->ver4.sda.cdsptr.seg); - MEMR_READS(seg, off, &sc->ver4.cds, sizeof(sc->ver4.cds)); - } -} - -static void store_sda_currcds(SDACDS sc) { - - REG16 off; - REG16 seg; - - if (hostdrv.stat.dosver_major == 3) { - MEMR_WRITES(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, - &sc->ver3.sda, sizeof(sc->ver3.sda)); - off = LOADINTELWORD(sc->ver3.sda.cdsptr.off); - seg = LOADINTELWORD(sc->ver3.sda.cdsptr.seg); - MEMR_WRITES(seg, off, &sc->ver3.cds, sizeof(sc->ver3.cds)); - } - else { - MEMR_WRITES(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, - &sc->ver4.sda, sizeof(sc->ver4.sda)); - off = LOADINTELWORD(sc->ver4.sda.cdsptr.off); - seg = LOADINTELWORD(sc->ver4.sda.cdsptr.seg); - MEMR_WRITES(seg, off, &sc->ver4.cds, sizeof(sc->ver4.cds)); - } -} - - -static void fetch_sft(INTRST is, SFTREC sft) { - - REG16 off; - REG16 seg; - - off = LOADINTELWORD(is->r.w.di); - seg = LOADINTELWORD(is->r.w.es); - MEMR_READS(seg, off, sft, sizeof(_SFTREC)); -} - -static void store_sft(INTRST is, SFTREC sft) { - - REG16 off; - REG16 seg; - - off = LOADINTELWORD(is->r.w.di); - seg = LOADINTELWORD(is->r.w.es); - MEMR_WRITES(seg, off, sft, sizeof(_SFTREC)); -} - - -static void store_srch(INTRST is) { - - SRCHREC srchrec; - - // SDA内のSRCHRECにセット - srchrec = is->srchrec_ptr; - srchrec->drive_no = 0xc0 | hostdrv.stat.drive_no; - CopyMemory(srchrec->srch_mask, is->fcbname_ptr, 11); - srchrec->attr_mask = *is->srch_attr_ptr; - STOREINTELWORD(srchrec->dir_entry_no, ((UINT16)-1)); - STOREINTELWORD(srchrec->dir_sector, hostdrv_findhandle_currentindex == HOSTDRV_FINDHANDLE_INVALID ? 0xffff : (UINT16)hostdrv_findhandles[hostdrv_findhandle_currentindex].flistidx); // 仮想クラスタ番号 -} - -static void store_dir(INTRST is, const HDRVFILE *phdf) { - - DIRREC dirrec; - UINT8 attr; - UINT16 reg; - - // SDA内のDIRRECにセット - dirrec = is->dirrec_ptr; - CopyMemory(dirrec->file_name, phdf->fcbname, 11); - attr = (UINT8)(phdf->attr & 0x3f); - if (!IS_PERMITWRITE) { - attr |= 0x01; - } - dirrec->file_attr = attr; - reg = 0; - if (phdf->caps & FLICAPS_TIME) { - reg |= (phdf->time.hour & 0x1f) << 11; - reg |= (phdf->time.minute & 0x3f) << 5; - reg |= (phdf->time.second & 0x3e) >> 1; - } - STOREINTELWORD(dirrec->file_time, reg); - reg = 0; - if (phdf->caps & FLICAPS_DATE) { - reg |= ((phdf->date.year - 1980) & 0x7f) << 9; - reg |= (phdf->date.month & 0x0f) << 5; - reg |= phdf->date.day & 0x1f; - } - STOREINTELWORD(dirrec->file_date, reg); - STOREINTELWORD(dirrec->start_sector, ((UINT16)-1)); - STOREINTELDWORD(dirrec->file_size, phdf->size); -} - -static void fill_sft(INTRST is, SFTREC sft, UINT num, const HDRVFILE *phdf) { - - UINT8 attr; - UINT16 reg; - - attr = phdf->attr; - if (!IS_PERMITWRITE) { - attr |= 0x01; - } - sft->file_attr = attr; - STOREINTELWORD(sft->start_sector, (UINT16)num); - - reg = 0; - if (phdf->caps & FLICAPS_TIME) { - reg |= (phdf->time.hour & 0x1f) << 11; - reg |= (phdf->time.minute & 0x3f) << 5; - reg |= (phdf->time.second & 0x3e) >> 1; - } - STOREINTELWORD(sft->file_time, reg); - reg = 0; - if (phdf->caps & FLICAPS_DATE) { - reg |= ((phdf->date.year - 1980) & 0x7f) << 9; - reg |= (phdf->date.month & 0x0f) << 5; - reg |= phdf->date.day & 0x1f; - } - STOREINTELWORD(sft->file_date, reg); - STOREINTELDWORD(sft->file_size, phdf->size); - STOREINTELWORD(sft->dir_sector, (UINT16)-1); - sft->dir_entry_no = (UINT8)-1; - CopyMemory(sft->file_name, is->fcbname_ptr, 11); - TRACEOUT(("open -> size %d", phdf->size)); -} - -static void init_sft(SFTREC sft) { - - if (sft->open_mode[1] & 0x80) { // fcb mode - sft->open_mode[0] |= 0xf0; - } - else { - sft->open_mode[0] &= 0x0f; - } - sft->dev_info_word[0] = (UINT8)(0x40 | hostdrv.stat.drive_no); - sft->dev_info_word[1] = 0x80; - STOREINTELDWORD(sft->dev_drvr_ptr, 0); - STOREINTELDWORD(sft->file_pos, 0); - STOREINTELWORD(sft->rel_sector, (UINT16)-1); - STOREINTELWORD(sft->abs_sector, (UINT16)-1); - if (sft->open_mode[1] & 0x80) { // fcb mode - CPU_FLAG |= C_FLAG; - } -} - - -static BOOL is_wildcards(const char *path) { - - int i; - - for (i=0; i<11; i++) { - if (path[i] == '?') { - return(TRUE); - } - } - return(FALSE); -} - - -// ぽいんた初期化 -static void setup_ptrs(INTRST is, SDACDS sc) { - - char *rootpath; - int off; - - if (hostdrv.stat.dosver_major == 3) { - is->fcbname_ptr = sc->ver3.sda.fcb_name; - is->filename_ptr = sc->ver3.sda.file_name + ROOTPATH_SIZE - 1; - is->fcbname_ptr_2 = sc->ver3.sda.fcb_name_2; - is->filename_ptr_2 = sc->ver3.sda.file_name_2 + ROOTPATH_SIZE - 1; - - is->srchrec_ptr = &sc->ver3.sda.srchrec; - is->dirrec_ptr = &sc->ver3.sda.dirrec; - is->srchrec_ptr_2 = &sc->ver3.sda.rename_srchrec; - is->dirrec_ptr_2 = &sc->ver3.sda.rename_dirrec; - is->srch_attr_ptr = &sc->ver3.sda.srch_attr; - - rootpath = sc->ver3.cds.current_path; - off = LOADINTELWORD(sc->ver3.cds.root_ofs); - is->root_path = rootpath; - is->current_path = rootpath + off; - } - else { - is->fcbname_ptr = sc->ver4.sda.fcb_name; - is->filename_ptr = sc->ver4.sda.file_name + ROOTPATH_SIZE - 1; - is->fcbname_ptr_2 = sc->ver4.sda.fcb_name_2; - is->filename_ptr_2 = sc->ver4.sda.file_name_2 + ROOTPATH_SIZE - 1; - - is->srchrec_ptr = &sc->ver4.sda.srchrec; - is->dirrec_ptr = &sc->ver4.sda.dirrec; - is->srchrec_ptr_2 = &sc->ver4.sda.rename_srchrec; - is->dirrec_ptr_2 = &sc->ver4.sda.rename_dirrec; - is->srch_attr_ptr = &sc->ver4.sda.srch_attr; - - rootpath = sc->ver4.cds.current_path; - off = LOADINTELWORD(sc->ver4.cds.root_ofs); - is->root_path = rootpath; - is->current_path = rootpath + off; - } -} - - -static BRESULT pathishostdrv(INTRST is, SDACDS sc) { - - fetch_sda_currcds(sc); - setup_ptrs(is, sc); - - if (memcmp(is->root_path, ROOTPATH, ROOTPATH_SIZE)) { - CPU_FLAG &= ~Z_FLAG; // chain - return(FAILURE); - } - if (is->is_chardev) { - fail(is, ERR_ACCESSDENIED); - return(FAILURE); - } - return(SUCCESS); -} - - -static BRESULT read_data(UINT num, UINT32 pos, UINT size, UINT seg, UINT off) { - - HDRVHANDLE hdf; - FILEH fh; - UINT8 work[1024]; - UINT r; - - hdf = (HDRVHANDLE)listarray_getitem(hostdrv.fhdl, num); - if (hdf == NULL) { - return(FAILURE); - } - fh = (FILEH)hdf->hdl; - if (file_seek(fh, (long)pos, FSEEK_SET) != (long)pos) { - return(FAILURE); - } - while(size) { - r = MIN(size, sizeof(work)); - if (file_read(fh, work, r) != r) { - return(FAILURE); - } - MEMR_WRITES(seg, off, work, r); - off += r; - size -= r; - } - return(SUCCESS); -} - -static BRESULT write_data(UINT num, UINT32 pos, UINT size, UINT seg, UINT off) { - - HDRVHANDLE hdf; - FILEH fh; - UINT8 work[1024]; - UINT r; - - hdf = (HDRVHANDLE)listarray_getitem(hostdrv.fhdl, num); - if (hdf == NULL) { - return(FAILURE); - } - fh = (FILEH)hdf->hdl; - if (file_seek(fh, (long)pos, FSEEK_SET) != (long)pos) { - return(FAILURE); - } - if (!size) { - file_write(fh, work, 0); - } - else { - do { - r = MIN(size, sizeof(work)); - MEMR_READS(seg, off, work, r); - if (file_write(fh, work, r) != r) { - return(FAILURE); - } - off += r; - size -= r; - } while(size); - } - return(SUCCESS); -} - - -static BRESULT find_file(INTRST is) -{ - HDRVLST hdl; - - hdl = (HDRVLST)listarray_getitem(hostdrv.flist, hostdrv.stat.flistpos); - if (hdl != NULL) - { - store_srch(is); - store_dir(is, &hdl->file); - hostdrv.stat.flistpos++; - return SUCCESS; - } - else - { - listarray_destroy(hostdrv.flist); - hostdrv.flist = NULL; - return FAILURE; - } -} - - -// ---- - -/* cmd in int2f11 */ -/* 00 */ -static void inst_check(INTRST intrst) { - - intrst->r.b.flag_l &= ~C_FLAG; - intrst->r.b.al = 0xff; // インストール済み。追加OKだお -} - -/* 01 */ -static void remove_dir(INTRST intrst) -{ - _SDACDS sc; - UINT nResult; - HDRVPATH hdp; - - if (pathishostdrv(intrst, &sc) != SUCCESS) - { - return; - } - - nResult = ERR_NOERROR; - do - { - if (is_wildcards(intrst->fcbname_ptr)) - { - nResult = ERR_PATHNOTFOUND; - break; - } - - if (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != ERR_NOERROR) - { - nResult = ERR_PATHNOTFOUND; - break; - } - if ((hdp.file.attr & 0x10) == 0) - { - nResult = ERR_ACCESSDENIED; - break; - } - TRACEOUT(("remove_dir: %s -> %s", intrst->filename_ptr, hdp.szPath)); - - if (!IS_PERMITDELETE) - { - nResult = ERR_ACCESSDENIED; - break; - } - - if (file_dirdelete(hdp.szPath)) - { - nResult = ERR_ACCESSDENIED; - break; - } - succeed(intrst); - return; - } while (FALSE /*CONSTCOND*/); - - fail(intrst, (UINT16)nResult); -} - -/* 03 */ -static void make_dir(INTRST intrst) -{ - _SDACDS sc; - UINT nResult; - HDRVPATH hdp; - - if (pathishostdrv(intrst, &sc) != SUCCESS) - { - return; - } - - nResult = ERR_NOERROR; - do - { - if (is_wildcards(intrst->fcbname_ptr)) - { - nResult = ERR_PATHNOTFOUND; - break; - } - - nResult = hostdrvs_getrealpath(&hdp, intrst->filename_ptr); - if (nResult == ERR_NOERROR) - { - nResult = ERR_ACCESSDENIED; - break; - } - else if (nResult != ERR_FILENOTFOUND) - { - break; - } - TRACEOUT(("make_dir: %s -> %s", intrst->filename_ptr, hdp.szPath)); - - if (!IS_PERMITWRITE) - { - nResult = ERR_ACCESSDENIED; - break; - } - - if (file_dircreate(hdp.szPath)) - { - nResult = ERR_ACCESSDENIED; - break; - } - nResult = ERR_NOERROR; - } while (FALSE /*CONSTCOND*/); - - if (nResult == ERR_NOERROR) - { - succeed(intrst); - } - else - { - fail(intrst, (UINT16)nResult); - } -} - -/* 05 */ -static void change_currdir(INTRST intrst) { - - _SDACDS sc; - char *ptr; - HDRVPATH hdp; - - if (pathishostdrv(intrst, &sc) != SUCCESS) { - return; - } - - ptr = intrst->filename_ptr; - TRACEOUT(("change_currdir %s", intrst->filename_ptr)); - if (ptr[0] == '\0' || (ptr[0] == '\\' && ptr[1] == '\0')) { // るーと - strcpy(intrst->filename_ptr, "\\"); - strcpy(intrst->current_path, intrst->filename_ptr); - store_sda_currcds(&sc); - succeed(intrst); - return; - } - if ((strlen(intrst->filename_ptr) >= (67 - ROOTPATH_SIZE)) || - (is_wildcards(intrst->fcbname_ptr) != FALSE) || - (hostdrvs_getrealpath(&hdp, ptr) != ERR_NOERROR) || - (hdp.file.fcbname[0] == ' ') || (!(hdp.file.attr & 0x10))) { - fail(intrst, ERR_PATHNOTFOUND); - return; - } - strcpy(intrst->current_path, intrst->filename_ptr); - store_sda_currcds(&sc); - succeed(intrst); -} - -/* 06 */ -static void close_file(INTRST intrst) { - - _SDACDS sc; - _SFTREC sft; - UINT16 handle_count; - UINT16 start_sector; - HDRVHANDLE hdf; - - fetch_sda_currcds(&sc); - fetch_sft(intrst, &sft); - setup_ptrs(intrst, &sc); - - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - handle_count = LOADINTELWORD(sft.handle_count); - - if (handle_count) { - handle_count--; - } - if (handle_count == 0) { - start_sector = LOADINTELWORD(sft.start_sector); - hdf = (HDRVHANDLE)listarray_getitem(hostdrv.fhdl, start_sector); - if (hdf) { - file_close((FILEH)hdf->hdl); - hdf->hdl = (INTPTR)FILEH_INVALID; - hdf->path[0] = '\0'; - } - } - STOREINTELWORD(sft.handle_count, handle_count); - store_sft(intrst, &sft); - succeed(intrst); -} - -/* 07 */ -static void commit_file(INTRST intrst) { - - _SDACDS sc; - _SFTREC sft; - - fetch_sda_currcds(&sc); - fetch_sft(intrst, &sft); - - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - - // なんもしないよー - succeed(intrst); -} - -/* 08 */ -static void read_file(INTRST intrst) { - - _SDACDS sc; - _SFTREC sft; - UINT16 cx; - UINT file_size; - UINT32 file_pos; - - fetch_sda_currcds(&sc); - fetch_sft(intrst, &sft); - setup_ptrs(intrst, &sc); - - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - if (sft.open_mode[0] & 1) { - fail(intrst, ERR_ACCESSDENIED); - return; - } - - cx = LOADINTELWORD(intrst->r.w.cx); - file_size = LOADINTELDWORD(sft.file_size); - file_pos = LOADINTELDWORD(sft.file_pos); - if (cx > (file_size - file_pos)) { - cx = (UINT16)(file_size - file_pos); - STOREINTELWORD(intrst->r.w.cx, cx); - } - if (cx == 0) { - succeed(intrst); - return; - } - if (read_data(LOADINTELWORD(sft.start_sector), file_pos, cx, - LOADINTELWORD(sc.ver3.sda.current_dta.seg), - LOADINTELWORD(sc.ver3.sda.current_dta.off)) != SUCCESS) { - fail(intrst, ERR_READFAULT); - return; - } - - file_pos += cx; - STOREINTELDWORD(sft.file_pos, file_pos); - - store_sft(intrst, &sft); -// store_sda_currcds(&sc); // ver0.74 Yui / sdaは変更無し - succeed(intrst); -} - -/* 09 */ -static void write_file(INTRST intrst) { - - _SDACDS sc; - _SFTREC sft; - UINT16 cx; - UINT file_size; - UINT32 file_pos; - - fetch_sda_currcds(&sc); - fetch_sft(intrst, &sft); - setup_ptrs(intrst, &sc); - - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - - if ((!IS_PERMITWRITE) || - (!(sft.open_mode[0] & 3))) { // read only - fail(intrst, ERR_ACCESSDENIED); - return; - } - - cx = LOADINTELWORD(intrst->r.w.cx); - file_size = LOADINTELDWORD(sft.file_size); - file_pos = LOADINTELDWORD(sft.file_pos); - if (write_data(LOADINTELWORD(sft.start_sector), file_pos, cx, - LOADINTELWORD(sc.ver3.sda.current_dta.seg), - LOADINTELWORD(sc.ver3.sda.current_dta.off)) != SUCCESS) { - fail(intrst, ERR_WRITEFAULT); - return; - } - if (cx) { - file_pos += cx; - if (file_size < file_pos) { - file_size = file_pos; - } - } - else { - file_size = file_pos; - } - - STOREINTELDWORD(sft.file_size, file_size); - STOREINTELDWORD(sft.file_pos, file_pos); - store_sft(intrst, &sft); - succeed(intrst); -} - -/* 0A */ -static void lock_file(INTRST intrst) { - - _SDACDS sc; - _SFTREC sft; - - fetch_sda_currcds(&sc); - fetch_sft(intrst, &sft); - - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - // 未実装 - TRACEOUT(("hostdrv: lock_file")); -} - -/* 0B */ -static void unlock_file(INTRST intrst) { - - _SDACDS sc; - _SFTREC sft; - - fetch_sda_currcds(&sc); - fetch_sft(intrst, &sft); - - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - // 未実装 - TRACEOUT(("hostdrv: unlock_file")); -} - -/* 0C */ -static void get_diskspace(INTRST intrst) -{ - _SDACDS sc; - - if (pathishostdrv(intrst, &sc) != SUCCESS) - { - return; - } - - intrst->r.b.flag_l &= ~C_FLAG; - STOREINTELWORD(intrst->r.w.ax, 0xf840); - STOREINTELWORD(intrst->r.w.bx, 0x8000); - STOREINTELWORD(intrst->r.w.cx, 0x0200); - STOREINTELWORD(intrst->r.w.dx, 0x8000); -} - -/* 0E */ -static void set_fileattr(INTRST intrst) { - - _SDACDS sc; - HDRVPATH hdp; - REG16 attr; - UINT32 hostattr; - - if (pathishostdrv(intrst, &sc) != SUCCESS) { - return; - } - if ((is_wildcards(intrst->fcbname_ptr)) || - (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != ERR_NOERROR)) { - fail(intrst, ERR_FILENOTFOUND); - return; - } - if (!IS_PERMITWRITE) { - fail(intrst, ERR_ACCESSDENIED); - return; - } - attr = MEMR_READ16(CPU_SS, CPU_BP + sizeof(IF4INTR)) & 0x37; - - hostattr = file_attr(hdp.szPath); -#if defined(NP2_WIN) - hostattr &= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM); - if (attr & 0x01) - { - hostattr |= FILE_ATTRIBUTE_READONLY; - } - if (attr & 0x02) - { - hostattr |= FILE_ATTRIBUTE_HIDDEN; - } - if (attr & 0x04) - { - hostattr |= FILE_ATTRIBUTE_SYSTEM; - } - if (attr & 0x20) - { - hostattr |= FILE_ATTRIBUTE_ARCHIVE; - } - if (hostattr == 0) - { - hostattr |= FILE_ATTRIBUTE_NORMAL; - } - if (file_setattr(hdp.szPath, hostattr)) - { - fail(intrst, ERR_ACCESSDENIED); - } - else - { - succeed(intrst); - } -#else - succeed(intrst); -#endif -} - -/* 0F */ -static void get_fileattr(INTRST intrst) { - - _SDACDS sc; - HDRVPATH hdp; - UINT16 ax; - FILEH fh; - int isRoot; - - if (pathishostdrv(intrst, &sc) != SUCCESS) { - return; - } - - TRACEOUT(("get_fileattr: ->%s", intrst->fcbname_ptr)); - isRoot = intrst->filename_ptr[0] == '¥0' || (intrst->filename_ptr[0] == OEMPATHDIVC && intrst->filename_ptr[1] == '¥0'); - if(!isRoot && (strcmp(intrst->fcbname_ptr, "???????????") || intrst->filename_ptr[0])){ // XXX: Win用特例 - if (is_wildcards(intrst->fcbname_ptr) || (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != ERR_NOERROR)) - { - fail(intrst, ERR_FILENOTFOUND); - return; - } - }else{ - if (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != ERR_NOERROR) { - fail(intrst, ERR_FILENOTFOUND); - return; - } - } - TRACEOUT(("get_fileattr: %s - %x", hdp.szPath, hdp.file.attr)); - ax = hdp.file.attr & 0x37; - if (!IS_PERMITWRITE) { - ax |= 0x01; - } - intrst->r.b.flag_l &= ~C_FLAG; - STOREINTELWORD(intrst->r.w.ax, ax); - - fh = file_open(hdp.szPath); - if (fh != FILEH_INVALID) - { - DOSDATE date; - DOSTIME time; - UINT16 datestamp; - UINT16 timestamp; - UINT32 size = (UINT32)file_getsize(fh); - STOREINTELWORD(intrst->r.w.bx, (UINT16)(size >> 16)); - STOREINTELWORD(intrst->r.w.di, (UINT16)(size)); - file_getdatetime(fh, &date, &time); - datestamp = ((UINT16)(date.year - 1980) << 9) | ((UINT16)date.month << 5) | ((UINT16)date.day); - timestamp = ((UINT16)time.hour << 11) | ((UINT16)time.minute << 5) | ((UINT16)time.second / 2); - STOREINTELWORD(intrst->r.w.dx, datestamp); - STOREINTELWORD(intrst->r.w.cx, timestamp); - file_close(fh); - } -} - -/* 11 */ -static void rename_file(INTRST intrst) -{ - _SDACDS sc; - UINT nResult; - HDRVPATH hdp1; - char fcbname1[11]; - HDRVPATH hdp2; - char fcbname2[11]; - LISTARRAY lst; - UINT nIndex; - HDRVLST phdl; - OEMCHAR szPath[MAX_PATH]; - HDRVPATH hdp; - UINT i; - char fcbname[11]; - - if (pathishostdrv(intrst, &sc) != SUCCESS) - { - return; - } - - nResult = ERR_NOERROR; - lst = NULL; - do - { - TRACEOUT(("rename_file: %s -> %s", intrst->filename_ptr, intrst->filename_ptr_2)); - nResult = hostdrvs_getrealdir(&hdp1, fcbname1, intrst->filename_ptr); - if (nResult != ERR_NOERROR) - { - break; - } - - nResult = hostdrvs_getrealdir(&hdp2, fcbname2, intrst->filename_ptr_2); - if (nResult != ERR_NOERROR) - { - break; - } - - lst = hostdrvs_getpathlist(&hdp1, fcbname1, 0x37); - if (lst == NULL) - { - nResult = ERR_FILENOTFOUND; - break; - } - - if (!IS_PERMITDELETE) - { - nResult = ERR_ACCESSDENIED; - break; - } - - nIndex = 0; - while (TRUE /*CONSTCOND*/) - { - phdl = (HDRVLST)listarray_getitem(lst, nIndex++); - if (phdl == NULL) - { - break; - } - file_cpyname(szPath, hdp1.szPath, NELEMENTS(szPath)); - file_setseparator(szPath, NELEMENTS(szPath)); - file_catname(szPath, phdl->szFilename, NELEMENTS(szPath)); - - hdp = hdp2; - for (i = 0; i < 11; i++) - { - fcbname[i] = (fcbname2[i] != '?') ? fcbname2[i] : phdl->file.fcbname[i]; - } - if (hostdrvs_appendname(&hdp, fcbname) != ERR_FILENOTFOUND) - { - nResult = ERR_ACCESSDENIED; - break; - } - - TRACEOUT(("renamed: %s -> %s", szPath, hdp.szPath)); - if (file_rename(szPath, hdp.szPath) != 0) - { - nResult = ERR_ACCESSDENIED; - break; - } - } - } while (FALSE /*CONSTCOND*/); - - if (lst != NULL) - { - listarray_destroy(lst); - } - if (nResult == ERR_NOERROR) - { - succeed(intrst); - } - else - { - fail(intrst, (UINT16)nResult); - } -} - -/* 13 */ -static void delete_file(INTRST intrst) -{ - _SDACDS sc; - UINT nResult; - HDRVPATH hdp; - char fcbname[11]; - LISTARRAY lst; - UINT nIndex; - HDRVLST phdl; - OEMCHAR szPath[MAX_PATH]; - - if (pathishostdrv(intrst, &sc) != SUCCESS) - { - return; - } - - nResult = ERR_NOERROR; - lst = NULL; - do - { - nResult = hostdrvs_getrealdir(&hdp, fcbname, intrst->filename_ptr); - if (nResult != ERR_NOERROR) - { - break; - } - - if (!is_wildcards(fcbname)) - { - nResult = hostdrvs_appendname(&hdp, fcbname); - if (nResult != ERR_NOERROR) - { - break; - } - - if (hdp.file.attr & 0x10) - { - nResult = ERR_ACCESSDENIED; - break; - } - TRACEOUT(("delete_file: %s -> %s", intrst->filename_ptr, hdp.szPath)); - - if (!IS_PERMITDELETE) - { - nResult = ERR_ACCESSDENIED; - break; - } - - if (file_delete(hdp.szPath)) - { - nResult = ERR_ACCESSDENIED; - break; - } - } - else - { - lst = hostdrvs_getpathlist(&hdp, fcbname, 0x27); - if (lst == NULL) - { - nResult = ERR_FILENOTFOUND; - break; - } - - if (!IS_PERMITDELETE) - { - nResult = ERR_ACCESSDENIED; - break; - } - - nIndex = 0; - while (TRUE /*CONSTCOND*/) - { - phdl = (HDRVLST)listarray_getitem(lst, nIndex++); - if (phdl == NULL) - { - break; - } - file_cpyname(szPath, hdp.szPath, NELEMENTS(szPath)); - file_setseparator(szPath, NELEMENTS(szPath)); - file_catname(szPath, phdl->szFilename, NELEMENTS(szPath)); - - TRACEOUT(("delete_file: %s -> %s", intrst->filename_ptr, szPath)); - if (file_delete(szPath)) - { - nResult = ERR_ACCESSDENIED; - break; - } - } - } - } while (FALSE /*CONSTCOND*/); - - if (lst != NULL) - { - listarray_destroy(lst); - } - if (nResult == ERR_NOERROR) - { - succeed(intrst); - } - else - { - fail(intrst, (UINT16)nResult); - } -} - -/* 16 */ -static void open_file(INTRST intrst) -{ - _SDACDS sc; - _SFTREC sft; - UINT nResult; - HDRVPATH hdp; - UINT nMode; - FILEH fh = FILEH_INVALID; - HDRVHANDLE hdf; - - if (pathishostdrv(intrst, &sc) != SUCCESS) - { - return; - } - fetch_sft(intrst, &sft); - - nResult = ERR_NOERROR; - do - { - if (is_wildcards(intrst->fcbname_ptr)) - { - nResult = ERR_FILENOTFOUND; - break; - } - - nResult = hostdrvs_getrealpath(&hdp, intrst->filename_ptr); - if (nResult != ERR_NOERROR) - { - break; - } - if (hdp.file.attr & 0x10) - { - nResult = ERR_ACCESSDENIED; - break; - } - TRACEOUT(("open_file: %s -> %s %d", intrst->filename_ptr, hdp.szPath, sft.open_mode[0] & 7)); - switch (sft.open_mode[0] & 7) - { - case 0: /* read only */ - nMode = HDFMODE_READ; - break; - - case 1: /* write only */ - nMode = HDFMODE_WRITE; - break; - - case 2: /* read/write */ - nMode = HDFMODE_READ | HDFMODE_WRITE; - break; - - default: - nMode = 0; - break; - } - if (nMode == 0) - { - nResult = ERR_INVALDACCESSMODE; - break; - } - - if (nMode & HDFMODE_WRITE) - { - if (!IS_PERMITWRITE) - { - nResult = ERR_ACCESSDENIED; - break; - } - fh = file_open(hdp.szPath); - } - else - { - fh = file_open_rb(hdp.szPath); - } - if (fh == FILEH_INVALID) - { - TRACEOUT(("file open error!")); - nResult = ERR_FILENOTFOUND; - break; - } - - hdf = hostdrvs_fhdlsea(hostdrv.fhdl); - if (hdf == NULL) - { - nResult = ERR_NOHANDLESLEFT; - break; - } - - hdf->hdl = (INTPTR)fh; - hdf->mode = nMode; - file_cpyname(hdf->path, hdp.szPath, NELEMENTS(hdf->path)); - - fill_sft(intrst, &sft, listarray_getpos(hostdrv.fhdl, hdf), &hdp.file); - init_sft(&sft); - - store_sft(intrst, &sft); - store_sda_currcds(&sc); - succeed(intrst); - return; - } while (FALSE /*CONSTCOND*/); - - if (fh != FILEH_INVALID) - { - file_close(fh); - } - fail(intrst, (UINT16)nResult); -} - -/* 17 */ -static void create_file(INTRST intrst) -{ - _SDACDS sc; - _SFTREC sft; - UINT nResult; - HDRVPATH hdp; - HDRVHANDLE hdf; - FILEH fh; - - if (pathishostdrv(intrst, &sc) != SUCCESS) - { - return; - } - fetch_sft(intrst, &sft); - - nResult = ERR_NOERROR; - do - { - if (is_wildcards(intrst->fcbname_ptr)) - { - nResult = ERR_FILENOTFOUND; - break; - } - - nResult = hostdrvs_getrealpath(&hdp, intrst->filename_ptr); - if (nResult == ERR_NOERROR) - { - if (hdp.file.attr & 0x10) - { - nResult = ERR_ACCESSDENIED; - break; - } - } - else if (nResult == ERR_FILENOTFOUND) - { - nResult = ERR_NOERROR; - } - else - { - break; - } - - TRACEOUT(("create_file: %s -> %s %d", intrst->filename_ptr, hdp.szPath, sft.open_mode[0] & 7)); - - if (!IS_PERMITWRITE) - { - nResult = ERR_ACCESSDENIED; - break; - } - - hdf = hostdrvs_fhdlsea(hostdrv.fhdl); - if (hdf == NULL) - { - nResult = ERR_ACCESSDENIED; - break; - } - fh = file_create(hdp.szPath); - if (fh == FILEH_INVALID) - { - TRACEOUT(("file create error!")); - nResult = ERR_ACCESSDENIED; - break; - } - - hdf->hdl = (INTPTR)fh; - hdf->mode = HDFMODE_READ | HDFMODE_WRITE; - file_cpyname(hdf->path, hdp.szPath, NELEMENTS(hdf->path)); - - fill_sft(intrst, &sft, listarray_getpos(hostdrv.fhdl, hdf), &hdp.file); - init_sft(&sft); - - store_sft(intrst, &sft); - store_sda_currcds(&sc); - } while (FALSE /*CONSTCOND*/); - - if (nResult == ERR_NOERROR) - { - succeed(intrst); - } - else - { - fail(intrst, (UINT16)nResult); - } -} - -/* 1B */ -static void find_first(INTRST intrst) { - - _SDACDS sc; - HDRVPATH hdp; - char fcbname[11]; - - if (pathishostdrv(intrst, &sc) != SUCCESS) - { - return; - } - - if (*intrst->srch_attr_ptr == 0x08) /* ボリュームラベル */ - { - store_srch(intrst); - store_dir(intrst, &hdd_volume); - } - else - { - if (hostdrvs_getrealdir(&hdp, fcbname, intrst->filename_ptr) != ERR_NOERROR) - { - fail(intrst, ERR_PATHNOTFOUND); - return; - } - - TRACEOUT(("find_first %s -> %s", intrst->filename_ptr, hdp.szPath)); - hostdrv.flist = hostdrvs_getpathlist(&hdp, intrst->fcbname_ptr, *intrst->srch_attr_ptr); - hostdrv.stat.flistpos = 0; - hostdrv_findhandles_add(hostdrv.flist, hostdrv.stat.flistpos); - if (find_file(intrst) != SUCCESS) - { - hostdrv_findhandles_close(); // 列挙失敗ならハンドル閉じる - fail(intrst, ERR_FILENOTFOUND); - return; - } - } - store_sda_currcds(&sc); - succeed(intrst); -} - -/* 1C */ -static void find_next(INTRST intrst) { - - _SDACDS sc; - SRCHREC srchrec; - UINT16 flistidx; - HOSTDRV_FINDHANDLE* findHandle; - - fetch_sda_currcds(&sc); - setup_ptrs(intrst, &sc); - - // DTAを読み取ってクラスタ番号を取得 - flistidx = MEMR_READ16(LOADINTELWORD(sc.ver3.sda.current_dta.seg), LOADINTELWORD(sc.ver3.sda.current_dta.off) + 0x0f); - findHandle = hostdrv_findhandles_getcurrent(); - - // 現在対象の場所と違う場所でfind_nextされたとき、検索ハンドルリストにあるか確認してそれを使用 - if (!hostdrv.flist || findHandle == NULL || findHandle->flistidx != flistidx) { - hostdrv_findhandles_setcurrentbyflistidx(flistidx); - findHandle = hostdrv_findhandles_getcurrent(); - if (findHandle) { - // 退避していた検索ハンドルに置き換え - hostdrv.flist = findHandle->flist; - hostdrv.stat.flistpos = findHandle->flistpos; - } - } - - srchrec = intrst->srchrec_ptr; - if ((!(srchrec->drive_no & 0x40)) || - ((srchrec->drive_no & 0x1f) != hostdrv.stat.drive_no)) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - if (find_file(intrst) != SUCCESS) { - hostdrv_findhandles_close(); // 列挙が終わったならハンドル閉じる - fail(intrst, ERR_NOMOREFILES); - return; - } - if (findHandle) { - findHandle->flistpos = hostdrv.stat.flistpos; // 検索位置更新 - } - store_sda_currcds(&sc); - succeed(intrst); -} -#if 1 -/* 1E */ -static void do_redir(INTRST intrst) { - - _SDACDS sc; - REG16 mode; - REG16 bx; - char tmp[4]; - - TRACEOUT(("do_redir")); - if (pathishostdrv(intrst, &sc) != SUCCESS) { - return; - } - mode = MEMR_READ16(CPU_SS, CPU_BP + sizeof(IF4INTR)); - TRACEOUT(("do_redir: %.4x", mode)); - switch(mode) { - case 0x5f02: - bx = LOADINTELWORD(intrst->r.w.bx); - if (bx) { - fail(intrst, 0x12); - return; - } - MEMR_WRITE16(CPU_DS, CPU_BX + 2, 4); - MEMR_WRITE16(CPU_DS, CPU_BX + 4, 1); - tmp[0] = (char)('A' + hostdrv.stat.drive_no); - tmp[1] = ':'; - tmp[2] = '\0'; - MEMR_WRITES(LOADINTELWORD(intrst->r.w.ds), - LOADINTELWORD(intrst->r.w.si), tmp, 3); - MEMR_WRITES(LOADINTELWORD(intrst->r.w.es), - LOADINTELWORD(intrst->r.w.di), - ROOTPATH, ROOTPATH_SIZE + 1); - break; - - default: - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - succeed(intrst); -} -#endif - -/* 21 */ -// dos4以降呼ばれることはあんまない・・・ -static void seek_fromend(INTRST intrst) { - - _SDACDS sc; - _SFTREC sft; - UINT16 reg; - UINT32 pos; - UINT file_size; - - fetch_sda_currcds(&sc); - fetch_sft(intrst, &sft); - - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - reg = LOADINTELWORD(intrst->r.w.cx); - pos = reg << 16; - reg = LOADINTELWORD(intrst->r.w.dx); - pos += reg; - file_size = LOADINTELDWORD(sft.file_size); - if (pos > file_size) { - pos = file_size; - } - reg = (UINT16)(pos >> 16); - STOREINTELWORD(intrst->r.w.dx, reg); - reg = (UINT16)pos; - STOREINTELWORD(intrst->r.w.ax, reg); - pos = file_size - pos; - STOREINTELDWORD(sft.file_pos, pos); - - store_sft(intrst, &sft); - intrst->r.b.flag_l &= ~C_FLAG; -} - -#if 0 -/* 2D */ -static void qualify_remote_filename(INTRST intrst) -{ - int i; - char driveLetter; - char srcpath[MAX_PATH] = { 0 }; - char dstpath[MAX_PATH] = { 0 }; - UINT16 seg; - UINT16 off; - UINT16 bufsize; - - seg = LOADINTELWORD(intrst->r.w.ds); - off = LOADINTELWORD(intrst->r.w.si); - for (i = 0; i < MAX_PATH - 1; i++) - { - srcpath[i] = MEMR_READ8(seg, off); - if ('a' <= srcpath[i] && srcpath[i] <= 'z') - { - srcpath[i] -= 0x20; // 小文字から0x20を引けば大文字のコード - } - if (srcpath[i] == '\0') break; - off++; - } - - driveLetter = (char)('A' + hostdrv.stat.drive_no); - if (srcpath[0] == driveLetter && srcpath[1] == ':' && srcpath[2] == '\\') - { - // 先頭がドライブレターで始まる場合、ドライブレターをネットワーク名に変更 - //memcpy(dstpath, srcpath, MAX_PATH); - //dstpath[0] = 'Z'; - strcpy(dstpath, ROOTPATH_NAME); - //strcat(dstpath, "SHARE\\"); - strcat(dstpath, srcpath + 3); - //strcpy(dstpath, srcpath + 2); - } - else if (strnicmp(srcpath, ROOTPATH_NAME, ROOTPATH_SIZE) == 0) - { - // 先頭がネットワーク名で始まる場合、変更不要 - memcpy(dstpath, srcpath, MAX_PATH); - //sprintf(dstpath, "%c:\\", driveLetter); - //strcat(dstpath, srcpath + ROOTPATH_SIZE); - //strcpy(dstpath, srcpath + ROOTPATH_SIZE - 1); - } - else - { - // HOSTDRVのパスではない - CPU_FLAG &= ~Z_FLAG; // chain - return; - } - -#if 1 - // 結果を書き込み - seg = LOADINTELWORD(intrst->r.w.es); - off = LOADINTELWORD(intrst->r.w.di); - for (i = 0; i < 128 - 1; i++) - { - MEMR_WRITE8(seg, off, dstpath[i]); - if (dstpath[i] == '\0') break; // NULLが来たら終わり - off++; - } - - succeed(intrst); -#else - // error - intrst->r.b.flag_l |= C_FLAG; - STOREINTELWORD(intrst->r.w.ax, 1); -#endif -} -#endif - -/* 2D */ -static void unknownfunc_2d(INTRST intrst) { - - _SDACDS sc; - _SFTREC sft; - - fetch_sda_currcds(&sc); - fetch_sft(intrst, &sft); - if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { - CPU_FLAG &= ~Z_FLAG; // chain - return; - } -#if 1 - TRACEOUT(("unknownfunc_2d")); -#else - intr_regs.flags &= ~C_FLAG; - intr_regs.ax = 2; -#endif -} - -/* 2E */ -// for dos4+ -static void ext_openfile(INTRST intrst) -{ - _SDACDS sc; - _SFTREC sft; - UINT nResult; - HDRVPATH hdp; - UINT mode; - BOOL create; - REG16 act; - REG16 cx; - FILEH fh; - HDRVHANDLE hdf; - - if (pathishostdrv(intrst, &sc) != SUCCESS) - { - return; - } - fetch_sft(intrst, &sft); - - nResult = ERR_NOERROR; - do - { - if (is_wildcards(intrst->fcbname_ptr)) - { - nResult = ERR_FILENOTFOUND; - break; - } - - sft.open_mode[0] = sc.ver4.sda.mode_2E[0] & 0x7f; - sft.open_mode[1] = sc.ver4.sda.mode_2E[1] & 0x00; - switch (sft.open_mode[0] & 7) - { - case 1: // write only - mode = HDFMODE_WRITE; - break; - - case 2: // read/write - mode = HDFMODE_READ | HDFMODE_WRITE; - break; - - default: - mode = HDFMODE_READ; - break; - } - act = LOADINTELWORD(sc.ver4.sda.action_2E); - create = FALSE; - - nResult = hostdrvs_getrealpath(&hdp, intrst->filename_ptr); - if (nResult == ERR_NOERROR) /* ファイルが存在 */ - { - if (hdp.file.attr & 0x10) - { - nResult = ERR_ACCESSDENIED; - } - switch (act & 3) - { - case 1: - cx = 1; - break; - - case 2: - create = TRUE; - cx = 3; - break; - - default: - nResult = ERR_FILE_EXISTS; - fail(intrst, (UINT16)nResult); - return; - } - } - else if (nResult == ERR_FILENOTFOUND) /* 新規ファイル */ - { - if (act & 0x10) - { - create = TRUE; - cx = 2; - nResult = ERR_NOERROR; - } - } - if (nResult != ERR_NOERROR) - { - break; - } - - fh = FILEH_INVALID; - if (create) - { - if (IS_PERMITWRITE) - { - fh = file_create(hdp.szPath); - } - } - else if (mode & HDFMODE_WRITE) - { - if (IS_PERMITWRITE) - { - fh = file_open(hdp.szPath); - } - } - else - { - fh = file_open_rb(hdp.szPath); - } - - if (fh == FILEH_INVALID) - { - TRACEOUT(("file open error!")); - nResult = ERR_ACCESSDENIED; - break; - } - - hdf = hostdrvs_fhdlsea(hostdrv.fhdl); - if (hdf == NULL) - { - file_close(fh); - nResult = ERR_ACCESSDENIED; - break; - } - - hdf->hdl = (INTPTR)fh; - hdf->mode = mode; - file_cpyname(hdf->path, hdp.szPath, NELEMENTS(hdf->path)); - - STOREINTELWORD(intrst->r.w.cx, cx); - fill_sft(intrst, &sft, listarray_getpos(hostdrv.fhdl, hdf), &hdp.file); - init_sft(&sft); - store_sft(intrst, &sft); - - store_sda_currcds(&sc); - } while (FALSE /*CONSTCOND*/); - - if (nResult == ERR_NOERROR) - { - succeed(intrst); - } - else - { - fail(intrst, (UINT16)nResult); - } -} - - -// ---- - -typedef void (*HDINTRFN)(INTRST intrst); - -static const HDINTRFN intr_func[] = { - inst_check, /* 00 */ - remove_dir, /* 01 */ - NULL, - make_dir, /* 03 */ - NULL, - change_currdir, /* 05 */ - close_file, /* 06 */ - commit_file, /* 07 */ - read_file, /* 08 */ - write_file, /* 09 */ - lock_file, /* 0A */ - unlock_file, /* 0B */ - get_diskspace, /* 0C */ - NULL, - set_fileattr, /* 0E */ - get_fileattr, /* 0F */ - NULL, - rename_file, /* 11 */ - NULL, - delete_file, /* 13 */ - NULL, - NULL, - open_file, /* 16 */ - create_file, /* 17 */ - NULL, - NULL, - NULL, - find_first, /* 1B */ - find_next, /* 1C */ - NULL, - do_redir, - NULL, - NULL, - seek_fromend, /* 21 */ - NULL, - NULL, //qualify_remote_filename, /* 23 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - unknownfunc_2d, /* 2D */ - ext_openfile /* 2E */ -}; - - -// ---- - -// 始めに一回だけ呼んでね(はーと -void hostdrv_initialize(void) { - - ZeroMemory(&hostdrv, sizeof(hostdrv)); - hostdrv.fhdl = listarray_new(sizeof(_HDRVHANDLE), 16); - - // 旧プロトコル互換セット - ROOTPATH_SIZE = ROOTPATH_SIZE_OLD; - strcpy(ROOTPATH, ROOTPATH_NAME_OLD); - TRACEOUT(("hostdrv: Switch to old protocol")); - - TRACEOUT(("hostdrv_initialize")); -} - -// 終わりに一回だけ呼んでね(はーと -void hostdrv_deinitialize(void) { - - if (hostdrv.flist) - { - listarray_destroy(hostdrv.flist); - hostdrv.flist = NULL; - hostdrv_findhandles_close(); - } - hostdrv_findhandles_clear(); - hostdrvs_fhdlallclose(hostdrv.fhdl); - listarray_destroy(hostdrv.fhdl); - TRACEOUT(("hostdrv_deinitialize")); -} - -// リセットルーチンで呼ぶべしべし -void hostdrv_reset(void) { - - hostdrv_deinitialize(); - hostdrv_initialize(); -} - - -// ---- for np2sysp - -void hostdrv_mount(const void *arg1, long arg2) { - - if ((np2cfg.hdrvroot[0] == '\0') || (!np2cfg.hdrvenable) || (hostdrv.stat.is_mount)) { - np2sysp_outstr(OEMTEXT("ng"), 0); - return; - } - hostdrv.stat.is_mount = 1; - hostdrv.stat.newprotocol = 0; - fetch_if4dos(); - np2sysp_outstr(OEMTEXT("ok"), 0); - (void)arg1; - (void)arg2; -} - -void hostdrv_unmount(const void *arg1, long arg2) { - - if (hostdrv.stat.is_mount) { - hostdrv_reset(); - } - (void)arg1; - (void)arg2; -} - -void hostdrv_intr(const void *arg1, long arg2) { - - _INTRST intrst; - - ZeroMemory(&intrst, sizeof(intrst)); - intrst.is_chardev = (CPU_FLAG & C_FLAG) == 0; - CPU_FLAG &= ~(C_FLAG | Z_FLAG); // not fcb / chain - - if (!np2cfg.hdrvenable) { - return; - } - if (!hostdrv.stat.is_mount) { - return; - } - - fetch_intr_regs(&intrst); - - TRACEOUT(("hostdrv: AL=%.2x", intrst.r.b.al)); - - if ((intrst.r.b.al >= NELEMENTS(intr_func)) || - (intr_func[intrst.r.b.al] == NULL)) { - return; - } - - CPU_FLAG |= Z_FLAG; // not chain - (*intr_func[intrst.r.b.al])(&intrst); - - store_intr_regs(&intrst); - - (void)arg1; - (void)arg2; -} - -void hostdrv_setn(const void* arg1, long arg2) -{ - if (hostdrv.stat.is_mount) - { - // マウント中の場合新プロトコル有効化 - hostdrv.stat.newprotocol = 1; - - // 新プロトコルセット - ROOTPATH_SIZE = ROOTPATH_SIZE_NEW; - strcpy(ROOTPATH, ROOTPATH_NAME_NEW); - ROOTPATH[0] = 'A' + hostdrv.stat.drive_no; - } - - np2sysp_outstr(OEMTEXT("pok"), 0); - - (void)arg1; - (void)arg2; -} - - - -// ---- for statsave - -typedef struct { - UINT stat; - UINT files; - UINT flists; -} SFHDRV; - -static BOOL fhdl_wr(void *vpItem, void *vpArg) { - - OEMCHAR *p; - UINT len; - - p = ((HDRVHANDLE)vpItem)->path; - len = (UINT)OEMSTRLEN(p); - statflag_write((STFLAGH)vpArg, &len, sizeof(len)); - if (len) { - if (len < MAX_PATH) { - ZeroMemory(p + len, (MAX_PATH - len) * sizeof(OEMCHAR)); - } - statflag_write((STFLAGH)vpArg, vpItem, sizeof(_HDRVHANDLE)); - } - return(FALSE); -} - -static BOOL flist_wr(void *vpItem, void *vpArg) { - - OEMCHAR *p; - UINT len; - - p = ((HDRVLST)vpItem)->szFilename; - len = (UINT)OEMSTRLEN(p); - if (len < MAX_PATH) { - ZeroMemory(p + len, (MAX_PATH - len) * sizeof(OEMCHAR)); - } - statflag_write((STFLAGH)vpArg, vpItem, sizeof(_HDRVLST)); - return(FALSE); -} - -int hostdrv_sfsave(STFLAGH sfh, const SFENTRY *tbl) { - - SFHDRV sfhdrv; - int ret; - - if (!hostdrv.stat.is_mount) { - return(STATFLAG_SUCCESS); - } - sfhdrv.stat = sizeof(hostdrv.stat); - sfhdrv.files = listarray_getitems(hostdrv.fhdl); - sfhdrv.flists = listarray_getitems(hostdrv.flist); - ret = statflag_write(sfh, &sfhdrv, sizeof(sfhdrv)); - ret |= statflag_write(sfh, &hostdrv.stat, sizeof(hostdrv.stat)); - listarray_enum(hostdrv.fhdl, fhdl_wr, sfh); - listarray_enum(hostdrv.flist, flist_wr, sfh); - (void)tbl; - return(ret); -} - -int hostdrv_sfload(STFLAGH sfh, const SFENTRY *tbl) { - - SFHDRV sfhdrv; - int ret; - UINT i; - UINT len; - HDRVHANDLE hdf; - FILEH fh; - HDRVLST hdl; - - listarray_clr(hostdrv.fhdl); - listarray_clr(hostdrv.flist); - - ret = statflag_read(sfh, &sfhdrv, sizeof(sfhdrv)); - if (sfhdrv.stat != sizeof(hostdrv.stat)) { - return(STATFLAG_FAILURE); - } - ret |= statflag_read(sfh, &hostdrv.stat, sizeof(hostdrv.stat)); - for (i=0; imode & HDFMODE_WRITE) { - fh = file_open(hdf->path); - } - else { - fh = file_open_rb(hdf->path); - } - hdf->hdl = (INTPTR)fh; - } - } - if (sfhdrv.flists > 0) - { - hostdrv.flist = listarray_new(sizeof(_HDRVLST), 64); - for (i = 0; i < sfhdrv.flists; i++) - { - hdl = (HDRVLST)listarray_append(hostdrv.flist, NULL); - if (hdl == NULL) - { - return(STATFLAG_FAILURE); - } - ret |= statflag_read(sfh, hdl, sizeof(_HDRVLST)); - } - } - if (hostdrv.stat.newprotocol == 1) - { - // 新プロトコルセット - ROOTPATH_SIZE = ROOTPATH_SIZE_NEW; - strcpy(ROOTPATH, ROOTPATH_NAME_NEW); - ROOTPATH[0] = 'A' + hostdrv.stat.drive_no; - TRACEOUT(("hostdrv: Switch to new protocol")); - } - else - { - // 旧プロトコル互換セット - ROOTPATH_SIZE = ROOTPATH_SIZE_OLD; - strcpy(ROOTPATH, ROOTPATH_NAME_OLD); - TRACEOUT(("hostdrv: Switch to old protocol")); - } - (void)tbl; - return(ret); -} - -#pragma code_seg() - -#endif +#include + +#if defined(SUPPORT_HOSTDRV) + +/* + ゲストOS(DOS)からホストOS(Win)にアクセスするの〜 + 完全にDOS(3.1以上)依存だお(汗 + ネットワークインタフェイス搭載前の繋ぎだけど + 更に、手抜き版だし(マテ +*/ + +#include +#include +#include +#include +#include +#include +#include "hostdrv.tbl" + +// 性能上最適化で優先しない方がいいコードなのでわざと別セグメントに置く +#pragma code_seg(".MISCCODE") + +#if 0 +#undef TRACEOUT +static void trace_fmt_ex(const char* fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "\n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#endif /* 1 */ + + + +#define IS_PERMITWRITE (np2cfg.hdrvacc & HDFMODE_WRITE) +#define IS_PERMITDELETE (np2cfg.hdrvacc & HDFMODE_DELETE) + +#define ROOTPATH_NAME_NEW "A:\\" +#define ROOTPATH_NAME_OLD "\\\\HOSTDRV\\" +#define ROOTPATH_SIZE_NEW (sizeof(ROOTPATH_NAME_NEW) - 1) +#define ROOTPATH_SIZE_OLD (sizeof(ROOTPATH_NAME_OLD) - 1) + +static int ROOTPATH_SIZE = ROOTPATH_SIZE_OLD; +static char ROOTPATH[] = ROOTPATH_NAME_OLD; +static const HDRVFILE hdd_volume = {{'_','H','O','S','T','D','R','I','V','E','_'}, 0, 0, 0x08, {0}, {0}}; + + HOSTDRV hostdrv; + +// XXX: DTA単位の複数検索に対応 本当はステートセーブすべき +#define HOSTDRV_FINDHANDLE_INVALID 0xffffffff +#define HOSTDRV_FINDHANDLE_MAX 256 // さすがに同時に256検索出来れば十分でしょう… +static UINT32 hostdrv_findhandle_currentindex = HOSTDRV_FINDHANDLE_INVALID; // 現在有効なハンドルが格納されているインデックス +static HOSTDRV_FINDHANDLE hostdrv_findhandles[HOSTDRV_FINDHANDLE_MAX] = { 0 }; // 検索ハンドルリスト +static UINT32 hostdrv_writepos = 0; // リストへの書き込み位置 +static UINT32 hostdrv_findhandles_count = 0; // リスト項目数 + +static void hostdrv_findhandles_add(LISTARRAY flist, UINT flistpos) +{ + static UINT16 flistidx = 0; // 仮想的なクラスタ番号 + int i; + + if (flist == NULL) + { + // 無効 + hostdrv_findhandle_currentindex = HOSTDRV_FINDHANDLE_INVALID; + return; + } + for (i = 0; i < HOSTDRV_FINDHANDLE_MAX; i++) + { + if (hostdrv_findhandles[i].flist == flist) + { + hostdrv_findhandle_currentindex = i; + return; // 二重登録防止 + } + } + // 新規 + if (hostdrv_writepos == hostdrv_findhandle_currentindex) + { + // 現在使用中の場所は破棄できないのでずらす + hostdrv_writepos = (hostdrv_writepos + 1) % HOSTDRV_FINDHANDLE_MAX; + } + if (hostdrv_findhandles[hostdrv_writepos].flist != NULL) + { + listarray_destroy(hostdrv_findhandles[hostdrv_writepos].flist); // ハンドル閉じる + // カウント減らす + hostdrv_findhandles_count--; + } + hostdrv_findhandles[hostdrv_writepos].flist = flist; + hostdrv_findhandles[hostdrv_writepos].flistpos = flistpos; + hostdrv_findhandles[hostdrv_writepos].flistidx = flistidx; + flistidx++; + + // 現在有効なハンドルにする + hostdrv_findhandle_currentindex = hostdrv_writepos; + + // 次の書き込み位置を指定 + hostdrv_writepos = (hostdrv_writepos + 1) % HOSTDRV_FINDHANDLE_MAX; + + // カウント増やす + hostdrv_findhandles_count++; +} +static void hostdrv_findhandles_setcurrentbyflistidx(UINT16 flistidx) +{ + int i; + // 仮想クラスタ番号から検索ハンドルを選択 + for (i = 0; i < HOSTDRV_FINDHANDLE_MAX; i++) + { + if (hostdrv_findhandles[i].flist && hostdrv_findhandles[i].flistidx == flistidx) + { + hostdrv_findhandle_currentindex = i; + return; + } + } + hostdrv_findhandle_currentindex = HOSTDRV_FINDHANDLE_INVALID; +} +static HOSTDRV_FINDHANDLE* hostdrv_findhandles_getcurrent() +{ + if (hostdrv_findhandle_currentindex == HOSTDRV_FINDHANDLE_INVALID) return NULL; + + // 現在有効なハンドルを取得 + return &hostdrv_findhandles[hostdrv_findhandle_currentindex]; +} +static void hostdrv_findhandles_close() +{ + if (hostdrv_findhandle_currentindex == HOSTDRV_FINDHANDLE_INVALID) return; + + // 現在有効なハンドルを閉じる + hostdrv_findhandles[hostdrv_findhandle_currentindex].flist = NULL; + hostdrv_findhandles[hostdrv_findhandle_currentindex].flistpos = 0; + + // カウント減らす + hostdrv_findhandles_count--; + + if (hostdrv_findhandle_currentindex + 1 == hostdrv_writepos) + { + // この項目の次が書き込み位置になっていたとき、書き込み位置を戻して無駄に場所を使うのを避ける + hostdrv_writepos = hostdrv_findhandle_currentindex; + if (hostdrv_findhandles_count > 1) + { + // 更に手前のデータがない位置まで書き込み位置を戻して無駄に場所を使うのを避ける + int i; + for (i = 0; i < HOSTDRV_FINDHANDLE_MAX; i++) + { + UINT32 tmpWritePos = (hostdrv_writepos + HOSTDRV_FINDHANDLE_MAX - 1) % HOSTDRV_FINDHANDLE_MAX; + if (hostdrv_findhandles[tmpWritePos].flist != NULL) + { + break; + } + hostdrv_writepos = tmpWritePos; + } + } + } + hostdrv_findhandle_currentindex = HOSTDRV_FINDHANDLE_INVALID; +} +static void hostdrv_findhandles_clear() +{ + int i; + for (i = 0; i < HOSTDRV_FINDHANDLE_MAX; i++) + { + if (hostdrv_findhandles[i].flist) + { + listarray_destroy(hostdrv_findhandles[i].flist); // ハンドル閉じる + hostdrv_findhandles[i].flist = NULL; + hostdrv_findhandles[i].flistpos = 0; + hostdrv_findhandles[i].flistidx = 0; + } + } + // カウント0にする + hostdrv_findhandles_count = 0; +} + +// ---- i/f + +static void succeed(INTRST intrst) { + + intrst->r.b.flag_l &= ~C_FLAG; + STOREINTELWORD(intrst->r.w.ax, ERR_NOERROR); +} + +static void fail(INTRST intrst, UINT16 err_code) { + + intrst->r.b.flag_l |= C_FLAG; + STOREINTELWORD(intrst->r.w.ax, err_code); +} + + +static void fetch_if4dos(void) { + + REG16 off; + REG16 seg; + IF4DOS if4dos; + + off = MEMR_READ16(IF4DOSPTR_SEG, IF4DOSPTR_OFF + 0); + seg = MEMR_READ16(IF4DOSPTR_SEG, IF4DOSPTR_OFF + 2); + MEMR_READS(seg, off, &if4dos, sizeof(if4dos)); + hostdrv.stat.drive_no = if4dos.drive_no; + hostdrv.stat.dosver_major = if4dos.dosver_major; + hostdrv.stat.dosver_minor = if4dos.dosver_minor; + hostdrv.stat.sda_off = LOADINTELWORD(if4dos.sda_off); + hostdrv.stat.sda_seg = LOADINTELWORD(if4dos.sda_seg); + + TRACEOUT(("hostdrv:drive_no = %d", if4dos.drive_no)); + TRACEOUT(("hostdrv:dosver = %d.%.2d", if4dos.dosver_major, if4dos.dosver_minor)); + TRACEOUT(("hostdrv.sda = %.4x:%.4x", hostdrv.stat.sda_seg, hostdrv.stat.sda_off)); +} + + +static void fetch_intr_regs(INTRST is) { + + MEMR_READS(CPU_SS, CPU_BP, &is->r, sizeof(is->r)); +} + +static void store_intr_regs(INTRST is) { + + MEMR_WRITES(CPU_SS, CPU_BP, &is->r, sizeof(is->r)); +} + + +static void fetch_sda_currcds(SDACDS sc) { + + REG16 off; + REG16 seg; + + if (hostdrv.stat.dosver_major == 3) { + MEMR_READS(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, + &sc->ver3.sda, sizeof(sc->ver3.sda)); + off = LOADINTELWORD(sc->ver3.sda.cdsptr.off); + seg = LOADINTELWORD(sc->ver3.sda.cdsptr.seg); + MEMR_READS(seg, off, &sc->ver3.cds, sizeof(sc->ver3.cds)); + } + else { + MEMR_READS(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, + &sc->ver4.sda, sizeof(sc->ver4.sda)); + off = LOADINTELWORD(sc->ver4.sda.cdsptr.off); + seg = LOADINTELWORD(sc->ver4.sda.cdsptr.seg); + MEMR_READS(seg, off, &sc->ver4.cds, sizeof(sc->ver4.cds)); + } +} + +static void store_sda_currcds(SDACDS sc) { + + REG16 off; + REG16 seg; + + if (hostdrv.stat.dosver_major == 3) { + MEMR_WRITES(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, + &sc->ver3.sda, sizeof(sc->ver3.sda)); + off = LOADINTELWORD(sc->ver3.sda.cdsptr.off); + seg = LOADINTELWORD(sc->ver3.sda.cdsptr.seg); + MEMR_WRITES(seg, off, &sc->ver3.cds, sizeof(sc->ver3.cds)); + } + else { + MEMR_WRITES(hostdrv.stat.sda_seg, hostdrv.stat.sda_off, + &sc->ver4.sda, sizeof(sc->ver4.sda)); + off = LOADINTELWORD(sc->ver4.sda.cdsptr.off); + seg = LOADINTELWORD(sc->ver4.sda.cdsptr.seg); + MEMR_WRITES(seg, off, &sc->ver4.cds, sizeof(sc->ver4.cds)); + } +} + + +static void fetch_sft(INTRST is, SFTREC sft) { + + REG16 off; + REG16 seg; + + off = LOADINTELWORD(is->r.w.di); + seg = LOADINTELWORD(is->r.w.es); + MEMR_READS(seg, off, sft, sizeof(_SFTREC)); +} + +static void store_sft(INTRST is, SFTREC sft) { + + REG16 off; + REG16 seg; + + off = LOADINTELWORD(is->r.w.di); + seg = LOADINTELWORD(is->r.w.es); + MEMR_WRITES(seg, off, sft, sizeof(_SFTREC)); +} + + +static void store_srch(INTRST is) { + + SRCHREC srchrec; + + // SDA内のSRCHRECにセット + srchrec = is->srchrec_ptr; + srchrec->drive_no = 0xc0 | hostdrv.stat.drive_no; + CopyMemory(srchrec->srch_mask, is->fcbname_ptr, 11); + srchrec->attr_mask = *is->srch_attr_ptr; + STOREINTELWORD(srchrec->dir_entry_no, ((UINT16)-1)); + STOREINTELWORD(srchrec->dir_sector, hostdrv_findhandle_currentindex == HOSTDRV_FINDHANDLE_INVALID ? 0xffff : (UINT16)hostdrv_findhandles[hostdrv_findhandle_currentindex].flistidx); // 仮想クラスタ番号 +} + +static void store_dir(INTRST is, const HDRVFILE *phdf) { + + DIRREC dirrec; + UINT8 attr; + UINT16 reg; + + // SDA内のDIRRECにセット + dirrec = is->dirrec_ptr; + CopyMemory(dirrec->file_name, phdf->fcbname, 11); + attr = (UINT8)(phdf->attr & 0x3f); + if (!IS_PERMITWRITE) { + attr |= 0x01; + } + dirrec->file_attr = attr; + reg = 0; + if (phdf->caps & FLICAPS_TIME) { + reg |= (phdf->time.hour & 0x1f) << 11; + reg |= (phdf->time.minute & 0x3f) << 5; + reg |= (phdf->time.second & 0x3e) >> 1; + } + STOREINTELWORD(dirrec->file_time, reg); + reg = 0; + if (phdf->caps & FLICAPS_DATE) { + reg |= ((phdf->date.year - 1980) & 0x7f) << 9; + reg |= (phdf->date.month & 0x0f) << 5; + reg |= phdf->date.day & 0x1f; + } + STOREINTELWORD(dirrec->file_date, reg); + STOREINTELWORD(dirrec->start_sector, ((UINT16)-1)); + STOREINTELDWORD(dirrec->file_size, phdf->size); +} + +static void fill_sft(INTRST is, SFTREC sft, UINT num, const HDRVFILE *phdf) { + + UINT8 attr; + UINT16 reg; + + attr = phdf->attr; + if (!IS_PERMITWRITE) { + attr |= 0x01; + } + sft->file_attr = attr; + STOREINTELWORD(sft->start_sector, (UINT16)num); + + reg = 0; + if (phdf->caps & FLICAPS_TIME) { + reg |= (phdf->time.hour & 0x1f) << 11; + reg |= (phdf->time.minute & 0x3f) << 5; + reg |= (phdf->time.second & 0x3e) >> 1; + } + STOREINTELWORD(sft->file_time, reg); + reg = 0; + if (phdf->caps & FLICAPS_DATE) { + reg |= ((phdf->date.year - 1980) & 0x7f) << 9; + reg |= (phdf->date.month & 0x0f) << 5; + reg |= phdf->date.day & 0x1f; + } + STOREINTELWORD(sft->file_date, reg); + STOREINTELDWORD(sft->file_size, phdf->size); + STOREINTELWORD(sft->dir_sector, (UINT16)-1); + sft->dir_entry_no = (UINT8)-1; + CopyMemory(sft->file_name, is->fcbname_ptr, 11); + TRACEOUT(("open -> size %d", phdf->size)); +} + +static void init_sft(SFTREC sft) { + + if (sft->open_mode[1] & 0x80) { // fcb mode + sft->open_mode[0] |= 0xf0; + } + else { + sft->open_mode[0] &= 0x0f; + } + sft->dev_info_word[0] = (UINT8)(0x40 | hostdrv.stat.drive_no); + sft->dev_info_word[1] = 0x80; + STOREINTELDWORD(sft->dev_drvr_ptr, 0); + STOREINTELDWORD(sft->file_pos, 0); + STOREINTELWORD(sft->rel_sector, (UINT16)-1); + STOREINTELWORD(sft->abs_sector, (UINT16)-1); + if (sft->open_mode[1] & 0x80) { // fcb mode + CPU_FLAG |= C_FLAG; + } +} + + +static BOOL is_wildcards(const char *path) { + + int i; + + for (i=0; i<11; i++) { + if (path[i] == '?') { + return(TRUE); + } + } + return(FALSE); +} + + +// ぽいんた初期化 +static void setup_ptrs(INTRST is, SDACDS sc) { + + char *rootpath; + int off; + + if (hostdrv.stat.dosver_major == 3) { + is->fcbname_ptr = sc->ver3.sda.fcb_name; + is->filename_ptr = sc->ver3.sda.file_name + ROOTPATH_SIZE - 1; + is->fcbname_ptr_2 = sc->ver3.sda.fcb_name_2; + is->filename_ptr_2 = sc->ver3.sda.file_name_2 + ROOTPATH_SIZE - 1; + + is->srchrec_ptr = &sc->ver3.sda.srchrec; + is->dirrec_ptr = &sc->ver3.sda.dirrec; + is->srchrec_ptr_2 = &sc->ver3.sda.rename_srchrec; + is->dirrec_ptr_2 = &sc->ver3.sda.rename_dirrec; + is->srch_attr_ptr = &sc->ver3.sda.srch_attr; + + rootpath = sc->ver3.cds.current_path; + off = LOADINTELWORD(sc->ver3.cds.root_ofs); + is->root_path = rootpath; + is->current_path = rootpath + off; + } + else { + is->fcbname_ptr = sc->ver4.sda.fcb_name; + is->filename_ptr = sc->ver4.sda.file_name + ROOTPATH_SIZE - 1; + is->fcbname_ptr_2 = sc->ver4.sda.fcb_name_2; + is->filename_ptr_2 = sc->ver4.sda.file_name_2 + ROOTPATH_SIZE - 1; + + is->srchrec_ptr = &sc->ver4.sda.srchrec; + is->dirrec_ptr = &sc->ver4.sda.dirrec; + is->srchrec_ptr_2 = &sc->ver4.sda.rename_srchrec; + is->dirrec_ptr_2 = &sc->ver4.sda.rename_dirrec; + is->srch_attr_ptr = &sc->ver4.sda.srch_attr; + + rootpath = sc->ver4.cds.current_path; + off = LOADINTELWORD(sc->ver4.cds.root_ofs); + is->root_path = rootpath; + is->current_path = rootpath + off; + } +} + + +static BRESULT pathishostdrv(INTRST is, SDACDS sc) { + + fetch_sda_currcds(sc); + setup_ptrs(is, sc); + + if (memcmp(is->root_path, ROOTPATH, ROOTPATH_SIZE)) { + CPU_FLAG &= ~Z_FLAG; // chain + return(FAILURE); + } + if (is->is_chardev) { + fail(is, ERR_ACCESSDENIED); + return(FAILURE); + } + return(SUCCESS); +} + + +static BRESULT read_data(UINT num, UINT32 pos, UINT size, UINT seg, UINT off) { + + HDRVHANDLE hdf; + FILEH fh; + UINT8 work[1024]; + UINT r; + + hdf = (HDRVHANDLE)listarray_getitem(hostdrv.fhdl, num); + if (hdf == NULL) { + return(FAILURE); + } + fh = (FILEH)hdf->hdl; + if (file_seek(fh, (long)pos, FSEEK_SET) != (long)pos) { + return(FAILURE); + } + while(size) { + r = MIN(size, sizeof(work)); + if (file_read(fh, work, r) != r) { + return(FAILURE); + } + MEMR_WRITES(seg, off, work, r); + off += r; + size -= r; + } + return(SUCCESS); +} + +static BRESULT write_data(UINT num, UINT32 pos, UINT size, UINT seg, UINT off) { + + HDRVHANDLE hdf; + FILEH fh; + UINT8 work[1024]; + UINT r; + + hdf = (HDRVHANDLE)listarray_getitem(hostdrv.fhdl, num); + if (hdf == NULL) { + return(FAILURE); + } + fh = (FILEH)hdf->hdl; + if (file_seek(fh, (long)pos, FSEEK_SET) != (long)pos) { + return(FAILURE); + } + if (!size) { + file_write(fh, work, 0); + } + else { + do { + r = MIN(size, sizeof(work)); + MEMR_READS(seg, off, work, r); + if (file_write(fh, work, r) != r) { + return(FAILURE); + } + off += r; + size -= r; + } while(size); + } + return(SUCCESS); +} + + +static BRESULT find_file(INTRST is) +{ + HDRVLST hdl; + + hdl = (HDRVLST)listarray_getitem(hostdrv.flist, hostdrv.stat.flistpos); + if (hdl != NULL) + { + store_srch(is); + store_dir(is, &hdl->file); + hostdrv.stat.flistpos++; + return SUCCESS; + } + else + { + listarray_destroy(hostdrv.flist); + hostdrv.flist = NULL; + return FAILURE; + } +} + + +// ---- + +/* cmd in int2f11 */ +/* 00 */ +static void inst_check(INTRST intrst) { + + intrst->r.b.flag_l &= ~C_FLAG; + intrst->r.b.al = 0xff; // インストール済み。追加OKだお +} + +/* 01 */ +static void remove_dir(INTRST intrst) +{ + _SDACDS sc; + UINT nResult; + HDRVPATH hdp; + + if (pathishostdrv(intrst, &sc) != SUCCESS) + { + return; + } + + nResult = ERR_NOERROR; + do + { + if (is_wildcards(intrst->fcbname_ptr)) + { + nResult = ERR_PATHNOTFOUND; + break; + } + + if (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != ERR_NOERROR) + { + nResult = ERR_PATHNOTFOUND; + break; + } + if ((hdp.file.attr & 0x10) == 0) + { + nResult = ERR_ACCESSDENIED; + break; + } + TRACEOUT(("remove_dir: %s -> %s", intrst->filename_ptr, hdp.szPath)); + + if (!IS_PERMITDELETE) + { + nResult = ERR_ACCESSDENIED; + break; + } + + if (file_dirdelete(hdp.szPath)) + { + nResult = ERR_ACCESSDENIED; + break; + } + succeed(intrst); + return; + } while (FALSE /*CONSTCOND*/); + + fail(intrst, (UINT16)nResult); +} + +/* 03 */ +static void make_dir(INTRST intrst) +{ + _SDACDS sc; + UINT nResult; + HDRVPATH hdp; + + if (pathishostdrv(intrst, &sc) != SUCCESS) + { + return; + } + + nResult = ERR_NOERROR; + do + { + if (is_wildcards(intrst->fcbname_ptr)) + { + nResult = ERR_PATHNOTFOUND; + break; + } + + nResult = hostdrvs_getrealpath(&hdp, intrst->filename_ptr); + if (nResult == ERR_NOERROR) + { + nResult = ERR_ACCESSDENIED; + break; + } + else if (nResult != ERR_FILENOTFOUND) + { + break; + } + TRACEOUT(("make_dir: %s -> %s", intrst->filename_ptr, hdp.szPath)); + + if (!IS_PERMITWRITE) + { + nResult = ERR_ACCESSDENIED; + break; + } + + if (file_dircreate(hdp.szPath)) + { + nResult = ERR_ACCESSDENIED; + break; + } + nResult = ERR_NOERROR; + } while (FALSE /*CONSTCOND*/); + + if (nResult == ERR_NOERROR) + { + succeed(intrst); + } + else + { + fail(intrst, (UINT16)nResult); + } +} + +/* 05 */ +static void change_currdir(INTRST intrst) { + + _SDACDS sc; + char *ptr; + HDRVPATH hdp; + + if (pathishostdrv(intrst, &sc) != SUCCESS) { + return; + } + + ptr = intrst->filename_ptr; + TRACEOUT(("change_currdir %s", intrst->filename_ptr)); + if (ptr[0] == '\0' || (ptr[0] == '\\' && ptr[1] == '\0')) { // るーと + strcpy(intrst->filename_ptr, "\\"); + strcpy(intrst->current_path, intrst->filename_ptr); + store_sda_currcds(&sc); + succeed(intrst); + return; + } + if ((strlen(intrst->filename_ptr) >= (67 - ROOTPATH_SIZE)) || + (is_wildcards(intrst->fcbname_ptr) != FALSE) || + (hostdrvs_getrealpath(&hdp, ptr) != ERR_NOERROR) || + (hdp.file.fcbname[0] == ' ') || (!(hdp.file.attr & 0x10))) { + fail(intrst, ERR_PATHNOTFOUND); + return; + } + strcpy(intrst->current_path, intrst->filename_ptr); + store_sda_currcds(&sc); + succeed(intrst); +} + +/* 06 */ +static void close_file(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + UINT16 handle_count; + UINT16 start_sector; + HDRVHANDLE hdf; + + fetch_sda_currcds(&sc); + fetch_sft(intrst, &sft); + setup_ptrs(intrst, &sc); + + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + handle_count = LOADINTELWORD(sft.handle_count); + + if (handle_count) { + handle_count--; + } + if (handle_count == 0) { + start_sector = LOADINTELWORD(sft.start_sector); + hdf = (HDRVHANDLE)listarray_getitem(hostdrv.fhdl, start_sector); + if (hdf) { + file_close((FILEH)hdf->hdl); + hdf->hdl = (INTPTR)FILEH_INVALID; + hdf->path[0] = '\0'; + } + } + STOREINTELWORD(sft.handle_count, handle_count); + store_sft(intrst, &sft); + succeed(intrst); +} + +/* 07 */ +static void commit_file(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + + fetch_sda_currcds(&sc); + fetch_sft(intrst, &sft); + + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + + // なんもしないよー + succeed(intrst); +} + +/* 08 */ +static void read_file(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + UINT16 cx; + UINT file_size; + UINT32 file_pos; + + fetch_sda_currcds(&sc); + fetch_sft(intrst, &sft); + setup_ptrs(intrst, &sc); + + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + if (sft.open_mode[0] & 1) { + fail(intrst, ERR_ACCESSDENIED); + return; + } + + cx = LOADINTELWORD(intrst->r.w.cx); + file_size = LOADINTELDWORD(sft.file_size); + file_pos = LOADINTELDWORD(sft.file_pos); + if (cx > (file_size - file_pos)) { + cx = (UINT16)(file_size - file_pos); + STOREINTELWORD(intrst->r.w.cx, cx); + } + if (cx == 0) { + succeed(intrst); + return; + } + if (read_data(LOADINTELWORD(sft.start_sector), file_pos, cx, + LOADINTELWORD(sc.ver3.sda.current_dta.seg), + LOADINTELWORD(sc.ver3.sda.current_dta.off)) != SUCCESS) { + fail(intrst, ERR_READFAULT); + return; + } + + file_pos += cx; + STOREINTELDWORD(sft.file_pos, file_pos); + + store_sft(intrst, &sft); +// store_sda_currcds(&sc); // ver0.74 Yui / sdaは変更無し + succeed(intrst); +} + +/* 09 */ +static void write_file(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + UINT16 cx; + UINT file_size; + UINT32 file_pos; + + fetch_sda_currcds(&sc); + fetch_sft(intrst, &sft); + setup_ptrs(intrst, &sc); + + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + + if ((!IS_PERMITWRITE) || + (!(sft.open_mode[0] & 3))) { // read only + fail(intrst, ERR_ACCESSDENIED); + return; + } + + cx = LOADINTELWORD(intrst->r.w.cx); + file_size = LOADINTELDWORD(sft.file_size); + file_pos = LOADINTELDWORD(sft.file_pos); + if (write_data(LOADINTELWORD(sft.start_sector), file_pos, cx, + LOADINTELWORD(sc.ver3.sda.current_dta.seg), + LOADINTELWORD(sc.ver3.sda.current_dta.off)) != SUCCESS) { + fail(intrst, ERR_WRITEFAULT); + return; + } + if (cx) { + file_pos += cx; + if (file_size < file_pos) { + file_size = file_pos; + } + } + else { + file_size = file_pos; + } + + STOREINTELDWORD(sft.file_size, file_size); + STOREINTELDWORD(sft.file_pos, file_pos); + store_sft(intrst, &sft); + succeed(intrst); +} + +/* 0A */ +static void lock_file(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + + fetch_sda_currcds(&sc); + fetch_sft(intrst, &sft); + + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + // 未実装 + TRACEOUT(("hostdrv: lock_file")); +} + +/* 0B */ +static void unlock_file(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + + fetch_sda_currcds(&sc); + fetch_sft(intrst, &sft); + + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + // 未実装 + TRACEOUT(("hostdrv: unlock_file")); +} + +/* 0C */ +static void get_diskspace(INTRST intrst) +{ + _SDACDS sc; + + if (pathishostdrv(intrst, &sc) != SUCCESS) + { + return; + } + + intrst->r.b.flag_l &= ~C_FLAG; + STOREINTELWORD(intrst->r.w.ax, 0xf840); + STOREINTELWORD(intrst->r.w.bx, 0x8000); + STOREINTELWORD(intrst->r.w.cx, 0x0200); + STOREINTELWORD(intrst->r.w.dx, 0x8000); +} + +/* 0E */ +static void set_fileattr(INTRST intrst) { + + _SDACDS sc; + HDRVPATH hdp; + REG16 attr; + UINT32 hostattr; + + if (pathishostdrv(intrst, &sc) != SUCCESS) { + return; + } + if ((is_wildcards(intrst->fcbname_ptr)) || + (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != ERR_NOERROR)) { + fail(intrst, ERR_FILENOTFOUND); + return; + } + if (!IS_PERMITWRITE) { + fail(intrst, ERR_ACCESSDENIED); + return; + } + attr = MEMR_READ16(CPU_SS, CPU_BP + sizeof(IF4INTR)) & 0x37; + + hostattr = file_attr(hdp.szPath); +#if defined(NP2_WIN) + hostattr &= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM); + if (attr & 0x01) + { + hostattr |= FILE_ATTRIBUTE_READONLY; + } + if (attr & 0x02) + { + hostattr |= FILE_ATTRIBUTE_HIDDEN; + } + if (attr & 0x04) + { + hostattr |= FILE_ATTRIBUTE_SYSTEM; + } + if (attr & 0x20) + { + hostattr |= FILE_ATTRIBUTE_ARCHIVE; + } + if (hostattr == 0) + { + hostattr |= FILE_ATTRIBUTE_NORMAL; + } + if (file_setattr(hdp.szPath, hostattr)) + { + fail(intrst, ERR_ACCESSDENIED); + } + else + { + succeed(intrst); + } +#else + succeed(intrst); +#endif +} + +/* 0F */ +static void get_fileattr(INTRST intrst) { + + _SDACDS sc; + HDRVPATH hdp; + UINT16 ax; + FILEH fh; + int isRoot; + + if (pathishostdrv(intrst, &sc) != SUCCESS) { + return; + } + + TRACEOUT(("get_fileattr: ->%s", intrst->fcbname_ptr)); + isRoot = intrst->filename_ptr[0] == '¥0' || (intrst->filename_ptr[0] == OEMPATHDIVC && intrst->filename_ptr[1] == '¥0'); + if(!isRoot && (strcmp(intrst->fcbname_ptr, "???????????") || intrst->filename_ptr[0])){ // XXX: Win用特例 + if (is_wildcards(intrst->fcbname_ptr) || (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != ERR_NOERROR)) + { + fail(intrst, ERR_FILENOTFOUND); + return; + } + }else{ + if (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != ERR_NOERROR) { + fail(intrst, ERR_FILENOTFOUND); + return; + } + } + TRACEOUT(("get_fileattr: %s - %x", hdp.szPath, hdp.file.attr)); + ax = hdp.file.attr & 0x37; + if (!IS_PERMITWRITE) { + ax |= 0x01; + } + intrst->r.b.flag_l &= ~C_FLAG; + STOREINTELWORD(intrst->r.w.ax, ax); + + fh = file_open(hdp.szPath); + if (fh != FILEH_INVALID) + { + DOSDATE date; + DOSTIME time; + UINT16 datestamp; + UINT16 timestamp; + UINT32 size = (UINT32)file_getsize(fh); + STOREINTELWORD(intrst->r.w.bx, (UINT16)(size >> 16)); + STOREINTELWORD(intrst->r.w.di, (UINT16)(size)); + file_getdatetime(fh, &date, &time); + datestamp = ((UINT16)(date.year - 1980) << 9) | ((UINT16)date.month << 5) | ((UINT16)date.day); + timestamp = ((UINT16)time.hour << 11) | ((UINT16)time.minute << 5) | ((UINT16)time.second / 2); + STOREINTELWORD(intrst->r.w.dx, datestamp); + STOREINTELWORD(intrst->r.w.cx, timestamp); + file_close(fh); + } +} + +/* 11 */ +static void rename_file(INTRST intrst) +{ + _SDACDS sc; + UINT nResult; + HDRVPATH hdp1; + char fcbname1[11]; + HDRVPATH hdp2; + char fcbname2[11]; + LISTARRAY lst; + UINT nIndex; + HDRVLST phdl; + OEMCHAR szPath[MAX_PATH]; + HDRVPATH hdp; + UINT i; + char fcbname[11]; + + if (pathishostdrv(intrst, &sc) != SUCCESS) + { + return; + } + + nResult = ERR_NOERROR; + lst = NULL; + do + { + TRACEOUT(("rename_file: %s -> %s", intrst->filename_ptr, intrst->filename_ptr_2)); + nResult = hostdrvs_getrealdir(&hdp1, fcbname1, intrst->filename_ptr); + if (nResult != ERR_NOERROR) + { + break; + } + + nResult = hostdrvs_getrealdir(&hdp2, fcbname2, intrst->filename_ptr_2); + if (nResult != ERR_NOERROR) + { + break; + } + + lst = hostdrvs_getpathlist(&hdp1, fcbname1, 0x37); + if (lst == NULL) + { + nResult = ERR_FILENOTFOUND; + break; + } + + if (!IS_PERMITDELETE) + { + nResult = ERR_ACCESSDENIED; + break; + } + + nIndex = 0; + while (TRUE /*CONSTCOND*/) + { + phdl = (HDRVLST)listarray_getitem(lst, nIndex++); + if (phdl == NULL) + { + break; + } + file_cpyname(szPath, hdp1.szPath, NELEMENTS(szPath)); + file_setseparator(szPath, NELEMENTS(szPath)); + file_catname(szPath, phdl->szFilename, NELEMENTS(szPath)); + + hdp = hdp2; + for (i = 0; i < 11; i++) + { + fcbname[i] = (fcbname2[i] != '?') ? fcbname2[i] : phdl->file.fcbname[i]; + } + if (hostdrvs_appendname(&hdp, fcbname) != ERR_FILENOTFOUND) + { + nResult = ERR_ACCESSDENIED; + break; + } + + TRACEOUT(("renamed: %s -> %s", szPath, hdp.szPath)); + if (file_rename(szPath, hdp.szPath) != 0) + { + nResult = ERR_ACCESSDENIED; + break; + } + } + } while (FALSE /*CONSTCOND*/); + + if (lst != NULL) + { + listarray_destroy(lst); + } + if (nResult == ERR_NOERROR) + { + succeed(intrst); + } + else + { + fail(intrst, (UINT16)nResult); + } +} + +/* 13 */ +static void delete_file(INTRST intrst) +{ + _SDACDS sc; + UINT nResult; + HDRVPATH hdp; + char fcbname[11]; + LISTARRAY lst; + UINT nIndex; + HDRVLST phdl; + OEMCHAR szPath[MAX_PATH]; + + if (pathishostdrv(intrst, &sc) != SUCCESS) + { + return; + } + + nResult = ERR_NOERROR; + lst = NULL; + do + { + nResult = hostdrvs_getrealdir(&hdp, fcbname, intrst->filename_ptr); + if (nResult != ERR_NOERROR) + { + break; + } + + if (!is_wildcards(fcbname)) + { + nResult = hostdrvs_appendname(&hdp, fcbname); + if (nResult != ERR_NOERROR) + { + break; + } + + if (hdp.file.attr & 0x10) + { + nResult = ERR_ACCESSDENIED; + break; + } + TRACEOUT(("delete_file: %s -> %s", intrst->filename_ptr, hdp.szPath)); + + if (!IS_PERMITDELETE) + { + nResult = ERR_ACCESSDENIED; + break; + } + + if (file_delete(hdp.szPath)) + { + nResult = ERR_ACCESSDENIED; + break; + } + } + else + { + lst = hostdrvs_getpathlist(&hdp, fcbname, 0x27); + if (lst == NULL) + { + nResult = ERR_FILENOTFOUND; + break; + } + + if (!IS_PERMITDELETE) + { + nResult = ERR_ACCESSDENIED; + break; + } + + nIndex = 0; + while (TRUE /*CONSTCOND*/) + { + phdl = (HDRVLST)listarray_getitem(lst, nIndex++); + if (phdl == NULL) + { + break; + } + file_cpyname(szPath, hdp.szPath, NELEMENTS(szPath)); + file_setseparator(szPath, NELEMENTS(szPath)); + file_catname(szPath, phdl->szFilename, NELEMENTS(szPath)); + + TRACEOUT(("delete_file: %s -> %s", intrst->filename_ptr, szPath)); + if (file_delete(szPath)) + { + nResult = ERR_ACCESSDENIED; + break; + } + } + } + } while (FALSE /*CONSTCOND*/); + + if (lst != NULL) + { + listarray_destroy(lst); + } + if (nResult == ERR_NOERROR) + { + succeed(intrst); + } + else + { + fail(intrst, (UINT16)nResult); + } +} + +/* 16 */ +static void open_file(INTRST intrst) +{ + _SDACDS sc; + _SFTREC sft; + UINT nResult; + HDRVPATH hdp; + UINT nMode; + FILEH fh = FILEH_INVALID; + HDRVHANDLE hdf; + + if (pathishostdrv(intrst, &sc) != SUCCESS) + { + return; + } + fetch_sft(intrst, &sft); + + nResult = ERR_NOERROR; + do + { + if (is_wildcards(intrst->fcbname_ptr)) + { + nResult = ERR_FILENOTFOUND; + break; + } + + nResult = hostdrvs_getrealpath(&hdp, intrst->filename_ptr); + if (nResult != ERR_NOERROR) + { + break; + } + if (hdp.file.attr & 0x10) + { + nResult = ERR_ACCESSDENIED; + break; + } + TRACEOUT(("open_file: %s -> %s %d", intrst->filename_ptr, hdp.szPath, sft.open_mode[0] & 7)); + switch (sft.open_mode[0] & 7) + { + case 0: /* read only */ + nMode = HDFMODE_READ; + break; + + case 1: /* write only */ + nMode = HDFMODE_WRITE; + break; + + case 2: /* read/write */ + nMode = HDFMODE_READ | HDFMODE_WRITE; + break; + + default: + nMode = 0; + break; + } + if (nMode == 0) + { + nResult = ERR_INVALDACCESSMODE; + break; + } + + if (nMode & HDFMODE_WRITE) + { + if (!IS_PERMITWRITE) + { + nResult = ERR_ACCESSDENIED; + break; + } + fh = file_open(hdp.szPath); + } + else + { + fh = file_open_rb(hdp.szPath); + } + if (fh == FILEH_INVALID) + { + TRACEOUT(("file open error!")); + nResult = ERR_FILENOTFOUND; + break; + } + + hdf = hostdrvs_fhdlsea(hostdrv.fhdl); + if (hdf == NULL) + { + nResult = ERR_NOHANDLESLEFT; + break; + } + + hdf->hdl = (INTPTR)fh; + hdf->mode = nMode; + file_cpyname(hdf->path, hdp.szPath, NELEMENTS(hdf->path)); + + fill_sft(intrst, &sft, listarray_getpos(hostdrv.fhdl, hdf), &hdp.file); + init_sft(&sft); + + store_sft(intrst, &sft); + store_sda_currcds(&sc); + succeed(intrst); + return; + } while (FALSE /*CONSTCOND*/); + + if (fh != FILEH_INVALID) + { + file_close(fh); + } + fail(intrst, (UINT16)nResult); +} + +/* 17 */ +static void create_file(INTRST intrst) +{ + _SDACDS sc; + _SFTREC sft; + UINT nResult; + HDRVPATH hdp; + HDRVHANDLE hdf; + FILEH fh; + + if (pathishostdrv(intrst, &sc) != SUCCESS) + { + return; + } + fetch_sft(intrst, &sft); + + nResult = ERR_NOERROR; + do + { + if (is_wildcards(intrst->fcbname_ptr)) + { + nResult = ERR_FILENOTFOUND; + break; + } + + nResult = hostdrvs_getrealpath(&hdp, intrst->filename_ptr); + if (nResult == ERR_NOERROR) + { + if (hdp.file.attr & 0x10) + { + nResult = ERR_ACCESSDENIED; + break; + } + } + else if (nResult == ERR_FILENOTFOUND) + { + nResult = ERR_NOERROR; + } + else + { + break; + } + + TRACEOUT(("create_file: %s -> %s %d", intrst->filename_ptr, hdp.szPath, sft.open_mode[0] & 7)); + + if (!IS_PERMITWRITE) + { + nResult = ERR_ACCESSDENIED; + break; + } + + hdf = hostdrvs_fhdlsea(hostdrv.fhdl); + if (hdf == NULL) + { + nResult = ERR_ACCESSDENIED; + break; + } + fh = file_create(hdp.szPath); + if (fh == FILEH_INVALID) + { + TRACEOUT(("file create error!")); + nResult = ERR_ACCESSDENIED; + break; + } + + hdf->hdl = (INTPTR)fh; + hdf->mode = HDFMODE_READ | HDFMODE_WRITE; + file_cpyname(hdf->path, hdp.szPath, NELEMENTS(hdf->path)); + + fill_sft(intrst, &sft, listarray_getpos(hostdrv.fhdl, hdf), &hdp.file); + init_sft(&sft); + + store_sft(intrst, &sft); + store_sda_currcds(&sc); + } while (FALSE /*CONSTCOND*/); + + if (nResult == ERR_NOERROR) + { + succeed(intrst); + } + else + { + fail(intrst, (UINT16)nResult); + } +} + +/* 1B */ +static void find_first(INTRST intrst) { + + _SDACDS sc; + HDRVPATH hdp; + char fcbname[11]; + + if (pathishostdrv(intrst, &sc) != SUCCESS) + { + return; + } + + if (*intrst->srch_attr_ptr == 0x08) /* ボリュームラベル */ + { + store_srch(intrst); + store_dir(intrst, &hdd_volume); + } + else + { + if (hostdrvs_getrealdir(&hdp, fcbname, intrst->filename_ptr) != ERR_NOERROR) + { + fail(intrst, ERR_PATHNOTFOUND); + return; + } + + TRACEOUT(("find_first %s -> %s", intrst->filename_ptr, hdp.szPath)); + hostdrv.flist = hostdrvs_getpathlist(&hdp, intrst->fcbname_ptr, *intrst->srch_attr_ptr); + hostdrv.stat.flistpos = 0; + hostdrv_findhandles_add(hostdrv.flist, hostdrv.stat.flistpos); + if (find_file(intrst) != SUCCESS) + { + hostdrv_findhandles_close(); // 列挙失敗ならハンドル閉じる + fail(intrst, ERR_FILENOTFOUND); + return; + } + } + store_sda_currcds(&sc); + succeed(intrst); +} + +/* 1C */ +static void find_next(INTRST intrst) { + + _SDACDS sc; + SRCHREC srchrec; + UINT16 flistidx; + HOSTDRV_FINDHANDLE* findHandle; + + fetch_sda_currcds(&sc); + setup_ptrs(intrst, &sc); + + // DTAを読み取ってクラスタ番号を取得 + flistidx = MEMR_READ16(LOADINTELWORD(sc.ver3.sda.current_dta.seg), LOADINTELWORD(sc.ver3.sda.current_dta.off) + 0x0f); + findHandle = hostdrv_findhandles_getcurrent(); + + // 現在対象の場所と違う場所でfind_nextされたとき、検索ハンドルリストにあるか確認してそれを使用 + if (!hostdrv.flist || findHandle == NULL || findHandle->flistidx != flistidx) { + hostdrv_findhandles_setcurrentbyflistidx(flistidx); + findHandle = hostdrv_findhandles_getcurrent(); + if (findHandle) { + // 退避していた検索ハンドルに置き換え + hostdrv.flist = findHandle->flist; + hostdrv.stat.flistpos = findHandle->flistpos; + } + } + + srchrec = intrst->srchrec_ptr; + if ((!(srchrec->drive_no & 0x40)) || + ((srchrec->drive_no & 0x1f) != hostdrv.stat.drive_no)) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + if (find_file(intrst) != SUCCESS) { + hostdrv_findhandles_close(); // 列挙が終わったならハンドル閉じる + fail(intrst, ERR_NOMOREFILES); + return; + } + if (findHandle) { + findHandle->flistpos = hostdrv.stat.flistpos; // 検索位置更新 + } + store_sda_currcds(&sc); + succeed(intrst); +} +#if 1 +/* 1E */ +static void do_redir(INTRST intrst) { + + _SDACDS sc; + REG16 mode; + REG16 bx; + char tmp[4]; + + TRACEOUT(("do_redir")); + if (pathishostdrv(intrst, &sc) != SUCCESS) { + return; + } + mode = MEMR_READ16(CPU_SS, CPU_BP + sizeof(IF4INTR)); + TRACEOUT(("do_redir: %.4x", mode)); + switch(mode) { + case 0x5f02: + bx = LOADINTELWORD(intrst->r.w.bx); + if (bx) { + fail(intrst, 0x12); + return; + } + MEMR_WRITE16(CPU_DS, CPU_BX + 2, 4); + MEMR_WRITE16(CPU_DS, CPU_BX + 4, 1); + tmp[0] = (char)('A' + hostdrv.stat.drive_no); + tmp[1] = ':'; + tmp[2] = '\0'; + MEMR_WRITES(LOADINTELWORD(intrst->r.w.ds), + LOADINTELWORD(intrst->r.w.si), tmp, 3); + MEMR_WRITES(LOADINTELWORD(intrst->r.w.es), + LOADINTELWORD(intrst->r.w.di), + ROOTPATH, ROOTPATH_SIZE + 1); + break; + + default: + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + succeed(intrst); +} +#endif + +/* 21 */ +// dos4以降呼ばれることはあんまない・・・ +static void seek_fromend(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + UINT16 reg; + UINT32 pos; + UINT file_size; + + fetch_sda_currcds(&sc); + fetch_sft(intrst, &sft); + + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + reg = LOADINTELWORD(intrst->r.w.cx); + pos = reg << 16; + reg = LOADINTELWORD(intrst->r.w.dx); + pos += reg; + file_size = LOADINTELDWORD(sft.file_size); + if (pos > file_size) { + pos = file_size; + } + reg = (UINT16)(pos >> 16); + STOREINTELWORD(intrst->r.w.dx, reg); + reg = (UINT16)pos; + STOREINTELWORD(intrst->r.w.ax, reg); + pos = file_size - pos; + STOREINTELDWORD(sft.file_pos, pos); + + store_sft(intrst, &sft); + intrst->r.b.flag_l &= ~C_FLAG; +} + +#if 0 +/* 2D */ +static void qualify_remote_filename(INTRST intrst) +{ + int i; + char driveLetter; + char srcpath[MAX_PATH] = { 0 }; + char dstpath[MAX_PATH] = { 0 }; + UINT16 seg; + UINT16 off; + UINT16 bufsize; + + seg = LOADINTELWORD(intrst->r.w.ds); + off = LOADINTELWORD(intrst->r.w.si); + for (i = 0; i < MAX_PATH - 1; i++) + { + srcpath[i] = MEMR_READ8(seg, off); + if ('a' <= srcpath[i] && srcpath[i] <= 'z') + { + srcpath[i] -= 0x20; // 小文字から0x20を引けば大文字のコード + } + if (srcpath[i] == '\0') break; + off++; + } + + driveLetter = (char)('A' + hostdrv.stat.drive_no); + if (srcpath[0] == driveLetter && srcpath[1] == ':' && srcpath[2] == '\\') + { + // 先頭がドライブレターで始まる場合、ドライブレターをネットワーク名に変更 + //memcpy(dstpath, srcpath, MAX_PATH); + //dstpath[0] = 'Z'; + strcpy(dstpath, ROOTPATH_NAME); + //strcat(dstpath, "SHARE\\"); + strcat(dstpath, srcpath + 3); + //strcpy(dstpath, srcpath + 2); + } + else if (strnicmp(srcpath, ROOTPATH_NAME, ROOTPATH_SIZE) == 0) + { + // 先頭がネットワーク名で始まる場合、変更不要 + memcpy(dstpath, srcpath, MAX_PATH); + //sprintf(dstpath, "%c:\\", driveLetter); + //strcat(dstpath, srcpath + ROOTPATH_SIZE); + //strcpy(dstpath, srcpath + ROOTPATH_SIZE - 1); + } + else + { + // HOSTDRVのパスではない + CPU_FLAG &= ~Z_FLAG; // chain + return; + } + +#if 1 + // 結果を書き込み + seg = LOADINTELWORD(intrst->r.w.es); + off = LOADINTELWORD(intrst->r.w.di); + for (i = 0; i < 128 - 1; i++) + { + MEMR_WRITE8(seg, off, dstpath[i]); + if (dstpath[i] == '\0') break; // NULLが来たら終わり + off++; + } + + succeed(intrst); +#else + // error + intrst->r.b.flag_l |= C_FLAG; + STOREINTELWORD(intrst->r.w.ax, 1); +#endif +} +#endif + +/* 2D */ +static void unknownfunc_2d(INTRST intrst) { + + _SDACDS sc; + _SFTREC sft; + + fetch_sda_currcds(&sc); + fetch_sft(intrst, &sft); + if ((sft.dev_info_word[0] & 0x3f) != hostdrv.stat.drive_no) { + CPU_FLAG &= ~Z_FLAG; // chain + return; + } +#if 1 + TRACEOUT(("unknownfunc_2d")); +#else + intr_regs.flags &= ~C_FLAG; + intr_regs.ax = 2; +#endif +} + +/* 2E */ +// for dos4+ +static void ext_openfile(INTRST intrst) +{ + _SDACDS sc; + _SFTREC sft; + UINT nResult; + HDRVPATH hdp; + UINT mode; + BOOL create; + REG16 act; + REG16 cx; + FILEH fh; + HDRVHANDLE hdf; + + if (pathishostdrv(intrst, &sc) != SUCCESS) + { + return; + } + fetch_sft(intrst, &sft); + + nResult = ERR_NOERROR; + do + { + if (is_wildcards(intrst->fcbname_ptr)) + { + nResult = ERR_FILENOTFOUND; + break; + } + + sft.open_mode[0] = sc.ver4.sda.mode_2E[0] & 0x7f; + sft.open_mode[1] = sc.ver4.sda.mode_2E[1] & 0x00; + switch (sft.open_mode[0] & 7) + { + case 1: // write only + mode = HDFMODE_WRITE; + break; + + case 2: // read/write + mode = HDFMODE_READ | HDFMODE_WRITE; + break; + + default: + mode = HDFMODE_READ; + break; + } + act = LOADINTELWORD(sc.ver4.sda.action_2E); + create = FALSE; + + nResult = hostdrvs_getrealpath(&hdp, intrst->filename_ptr); + if (nResult == ERR_NOERROR) /* ファイルが存在 */ + { + if (hdp.file.attr & 0x10) + { + nResult = ERR_ACCESSDENIED; + } + switch (act & 3) + { + case 1: + cx = 1; + break; + + case 2: + create = TRUE; + cx = 3; + break; + + default: + nResult = ERR_FILE_EXISTS; + fail(intrst, (UINT16)nResult); + return; + } + } + else if (nResult == ERR_FILENOTFOUND) /* 新規ファイル */ + { + if (act & 0x10) + { + create = TRUE; + cx = 2; + nResult = ERR_NOERROR; + } + } + if (nResult != ERR_NOERROR) + { + break; + } + + fh = FILEH_INVALID; + if (create) + { + if (IS_PERMITWRITE) + { + fh = file_create(hdp.szPath); + } + } + else if (mode & HDFMODE_WRITE) + { + if (IS_PERMITWRITE) + { + fh = file_open(hdp.szPath); + } + } + else + { + fh = file_open_rb(hdp.szPath); + } + + if (fh == FILEH_INVALID) + { + TRACEOUT(("file open error!")); + nResult = ERR_ACCESSDENIED; + break; + } + + hdf = hostdrvs_fhdlsea(hostdrv.fhdl); + if (hdf == NULL) + { + file_close(fh); + nResult = ERR_ACCESSDENIED; + break; + } + + hdf->hdl = (INTPTR)fh; + hdf->mode = mode; + file_cpyname(hdf->path, hdp.szPath, NELEMENTS(hdf->path)); + + STOREINTELWORD(intrst->r.w.cx, cx); + fill_sft(intrst, &sft, listarray_getpos(hostdrv.fhdl, hdf), &hdp.file); + init_sft(&sft); + store_sft(intrst, &sft); + + store_sda_currcds(&sc); + } while (FALSE /*CONSTCOND*/); + + if (nResult == ERR_NOERROR) + { + succeed(intrst); + } + else + { + fail(intrst, (UINT16)nResult); + } +} + + +// ---- + +typedef void (*HDINTRFN)(INTRST intrst); + +static const HDINTRFN intr_func[] = { + inst_check, /* 00 */ + remove_dir, /* 01 */ + NULL, + make_dir, /* 03 */ + NULL, + change_currdir, /* 05 */ + close_file, /* 06 */ + commit_file, /* 07 */ + read_file, /* 08 */ + write_file, /* 09 */ + lock_file, /* 0A */ + unlock_file, /* 0B */ + get_diskspace, /* 0C */ + NULL, + set_fileattr, /* 0E */ + get_fileattr, /* 0F */ + NULL, + rename_file, /* 11 */ + NULL, + delete_file, /* 13 */ + NULL, + NULL, + open_file, /* 16 */ + create_file, /* 17 */ + NULL, + NULL, + NULL, + find_first, /* 1B */ + find_next, /* 1C */ + NULL, + do_redir, + NULL, + NULL, + seek_fromend, /* 21 */ + NULL, + NULL, //qualify_remote_filename, /* 23 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + unknownfunc_2d, /* 2D */ + ext_openfile /* 2E */ +}; + + +// ---- + +// 始めに一回だけ呼んでね(はーと +void hostdrv_initialize(void) { + + ZeroMemory(&hostdrv, sizeof(hostdrv)); + hostdrv.fhdl = listarray_new(sizeof(_HDRVHANDLE), 16); + + // 旧プロトコル互換セット + ROOTPATH_SIZE = ROOTPATH_SIZE_OLD; + strcpy(ROOTPATH, ROOTPATH_NAME_OLD); + TRACEOUT(("hostdrv: Switch to old protocol")); + + TRACEOUT(("hostdrv_initialize")); +} + +// 終わりに一回だけ呼んでね(はーと +void hostdrv_deinitialize(void) { + + if (hostdrv.flist) + { + listarray_destroy(hostdrv.flist); + hostdrv.flist = NULL; + hostdrv_findhandles_close(); + } + hostdrv_findhandles_clear(); + hostdrvs_fhdlallclose(hostdrv.fhdl); + listarray_destroy(hostdrv.fhdl); + TRACEOUT(("hostdrv_deinitialize")); +} + +// リセットルーチンで呼ぶべしべし +void hostdrv_reset(void) { + + hostdrv_deinitialize(); + hostdrv_initialize(); +} + + +// ---- for np2sysp + +void hostdrv_mount(const void *arg1, long arg2) { + + if ((np2cfg.hdrvroot[0] == '\0') || (!np2cfg.hdrvenable) || (hostdrv.stat.is_mount)) { + np2sysp_outstr(OEMTEXT("ng"), 0); + return; + } + hostdrv.stat.is_mount = 1; + hostdrv.stat.newprotocol = 0; + fetch_if4dos(); + np2sysp_outstr(OEMTEXT("ok"), 0); + (void)arg1; + (void)arg2; +} + +void hostdrv_unmount(const void *arg1, long arg2) { + + if (hostdrv.stat.is_mount) { + hostdrv_reset(); + } + (void)arg1; + (void)arg2; +} + +void hostdrv_intr(const void *arg1, long arg2) { + + _INTRST intrst; + + ZeroMemory(&intrst, sizeof(intrst)); + intrst.is_chardev = (CPU_FLAG & C_FLAG) == 0; + CPU_FLAG &= ~(C_FLAG | Z_FLAG); // not fcb / chain + + if (!np2cfg.hdrvenable) { + return; + } + if (!hostdrv.stat.is_mount) { + return; + } + + fetch_intr_regs(&intrst); + + TRACEOUT(("hostdrv: AL=%.2x", intrst.r.b.al)); + + if ((intrst.r.b.al >= NELEMENTS(intr_func)) || + (intr_func[intrst.r.b.al] == NULL)) { + return; + } + + CPU_FLAG |= Z_FLAG; // not chain + (*intr_func[intrst.r.b.al])(&intrst); + + store_intr_regs(&intrst); + + (void)arg1; + (void)arg2; +} + +void hostdrv_setn(const void* arg1, long arg2) +{ + if (hostdrv.stat.is_mount) + { + // マウント中の場合新プロトコル有効化 + hostdrv.stat.newprotocol = 1; + + // 新プロトコルセット + ROOTPATH_SIZE = ROOTPATH_SIZE_NEW; + strcpy(ROOTPATH, ROOTPATH_NAME_NEW); + ROOTPATH[0] = 'A' + hostdrv.stat.drive_no; + } + + np2sysp_outstr(OEMTEXT("pok"), 0); + + (void)arg1; + (void)arg2; +} + + + +// ---- for statsave + +typedef struct { + UINT stat; + UINT files; + UINT flists; +} SFHDRV; + +static BOOL fhdl_wr(void *vpItem, void *vpArg) { + + OEMCHAR *p; + UINT len; + + p = ((HDRVHANDLE)vpItem)->path; + len = (UINT)OEMSTRLEN(p); + statflag_write((STFLAGH)vpArg, &len, sizeof(len)); + if (len) { + if (len < MAX_PATH) { + ZeroMemory(p + len, (MAX_PATH - len) * sizeof(OEMCHAR)); + } + statflag_write((STFLAGH)vpArg, vpItem, sizeof(_HDRVHANDLE)); + } + return(FALSE); +} + +static BOOL flist_wr(void *vpItem, void *vpArg) { + + OEMCHAR *p; + UINT len; + + p = ((HDRVLST)vpItem)->szFilename; + len = (UINT)OEMSTRLEN(p); + if (len < MAX_PATH) { + ZeroMemory(p + len, (MAX_PATH - len) * sizeof(OEMCHAR)); + } + statflag_write((STFLAGH)vpArg, vpItem, sizeof(_HDRVLST)); + return(FALSE); +} + +int hostdrv_sfsave(STFLAGH sfh, const SFENTRY *tbl) { + + SFHDRV sfhdrv; + int ret; + + if (!hostdrv.stat.is_mount) { + return(STATFLAG_SUCCESS); + } + sfhdrv.stat = sizeof(hostdrv.stat); + sfhdrv.files = listarray_getitems(hostdrv.fhdl); + sfhdrv.flists = listarray_getitems(hostdrv.flist); + ret = statflag_write(sfh, &sfhdrv, sizeof(sfhdrv)); + ret |= statflag_write(sfh, &hostdrv.stat, sizeof(hostdrv.stat)); + listarray_enum(hostdrv.fhdl, fhdl_wr, sfh); + listarray_enum(hostdrv.flist, flist_wr, sfh); + (void)tbl; + return(ret); +} + +int hostdrv_sfload(STFLAGH sfh, const SFENTRY *tbl) { + + SFHDRV sfhdrv; + int ret; + UINT i; + UINT len; + HDRVHANDLE hdf; + FILEH fh; + HDRVLST hdl; + + listarray_clr(hostdrv.fhdl); + listarray_clr(hostdrv.flist); + + ret = statflag_read(sfh, &sfhdrv, sizeof(sfhdrv)); + if (sfhdrv.stat != sizeof(hostdrv.stat)) { + return(STATFLAG_FAILURE); + } + ret |= statflag_read(sfh, &hostdrv.stat, sizeof(hostdrv.stat)); + for (i=0; imode & HDFMODE_WRITE) { + fh = file_open(hdf->path); + } + else { + fh = file_open_rb(hdf->path); + } + hdf->hdl = (INTPTR)fh; + } + } + if (sfhdrv.flists > 0) + { + hostdrv.flist = listarray_new(sizeof(_HDRVLST), 64); + for (i = 0; i < sfhdrv.flists; i++) + { + hdl = (HDRVLST)listarray_append(hostdrv.flist, NULL); + if (hdl == NULL) + { + return(STATFLAG_FAILURE); + } + ret |= statflag_read(sfh, hdl, sizeof(_HDRVLST)); + } + } + if (hostdrv.stat.newprotocol == 1) + { + // 新プロトコルセット + ROOTPATH_SIZE = ROOTPATH_SIZE_NEW; + strcpy(ROOTPATH, ROOTPATH_NAME_NEW); + ROOTPATH[0] = 'A' + hostdrv.stat.drive_no; + TRACEOUT(("hostdrv: Switch to new protocol")); + } + else + { + // 旧プロトコル互換セット + ROOTPATH_SIZE = ROOTPATH_SIZE_OLD; + strcpy(ROOTPATH, ROOTPATH_NAME_OLD); + TRACEOUT(("hostdrv: Switch to old protocol")); + } + (void)tbl; + return(ret); +} + +#pragma code_seg() + +#endif diff --git a/generic/hostdrv.h b/generic/hostdrv.h old mode 100755 new mode 100644 index d2e546ae..5bcdcf96 --- a/generic/hostdrv.h +++ b/generic/hostdrv.h @@ -1,83 +1,83 @@ -/** - * @file hostdrv.h - * @brief Interface of host drive - */ - -#pragma once - -#if defined(SUPPORT_HOSTDRV) - -#include - -#define DIRMAX_DEPTH 8 - -enum { - HDFMODE_READ = 0x01, - HDFMODE_WRITE = 0x02, - HDFMODE_DELETE = 0x04 -}; - -/** - * @brief ファイル ハンドル - */ -struct tagHostDrvHandle -{ - INTPTR hdl; - UINT mode; - OEMCHAR path[MAX_PATH]; -}; -typedef struct tagHostDrvHandle _HDRVHANDLE; -typedef struct tagHostDrvHandle *HDRVHANDLE; - -typedef struct { - struct { - UINT8 is_mount:6; - UINT8 newprotocol:2; - UINT8 drive_no; - UINT8 dosver_major; - UINT8 dosver_minor; - UINT16 sda_off; - UINT16 sda_seg; - UINT flistpos; - } stat; - -// LISTARRAY cache[DIRMAX_DEPTH]; - LISTARRAY fhdl; - LISTARRAY flist; -} HOSTDRV; - -typedef struct -{ - LISTARRAY flist; - UINT flistpos; // 検索列挙位置 - UINT16 flistidx; // 仮想クラスタ番号 -} HOSTDRV_FINDHANDLE; - - - -#ifdef __cplusplus -extern "C" { -#endif - -extern HOSTDRV hostdrv; - -void hostdrv_initialize(void); -void hostdrv_deinitialize(void); -void hostdrv_reset(void); -// void save_hostdrv(void); -// void load_hostdrv(void); - -void hostdrv_mount(const void *arg1, long arg2); -void hostdrv_unmount(const void *arg1, long arg2); -void hostdrv_intr(const void *arg1, long arg2); -void hostdrv_setn(const void* arg1, long arg2); - -int hostdrv_sfsave(STFLAGH sfh, const SFENTRY *tbl); -int hostdrv_sfload(STFLAGH sfh, const SFENTRY *tbl); - -#ifdef __cplusplus -} -#endif - -#endif - +/** + * @file hostdrv.h + * @brief Interface of host drive + */ + +#pragma once + +#if defined(SUPPORT_HOSTDRV) + +#include + +#define DIRMAX_DEPTH 8 + +enum { + HDFMODE_READ = 0x01, + HDFMODE_WRITE = 0x02, + HDFMODE_DELETE = 0x04 +}; + +/** + * @brief ファイル ハンドル + */ +struct tagHostDrvHandle +{ + INTPTR hdl; + UINT mode; + OEMCHAR path[MAX_PATH]; +}; +typedef struct tagHostDrvHandle _HDRVHANDLE; +typedef struct tagHostDrvHandle *HDRVHANDLE; + +typedef struct { + struct { + UINT8 is_mount:6; + UINT8 newprotocol:2; + UINT8 drive_no; + UINT8 dosver_major; + UINT8 dosver_minor; + UINT16 sda_off; + UINT16 sda_seg; + UINT flistpos; + } stat; + +// LISTARRAY cache[DIRMAX_DEPTH]; + LISTARRAY fhdl; + LISTARRAY flist; +} HOSTDRV; + +typedef struct +{ + LISTARRAY flist; + UINT flistpos; // 検索列挙位置 + UINT16 flistidx; // 仮想クラスタ番号 +} HOSTDRV_FINDHANDLE; + + + +#ifdef __cplusplus +extern "C" { +#endif + +extern HOSTDRV hostdrv; + +void hostdrv_initialize(void); +void hostdrv_deinitialize(void); +void hostdrv_reset(void); +// void save_hostdrv(void); +// void load_hostdrv(void); + +void hostdrv_mount(const void *arg1, long arg2); +void hostdrv_unmount(const void *arg1, long arg2); +void hostdrv_intr(const void *arg1, long arg2); +void hostdrv_setn(const void* arg1, long arg2); + +int hostdrv_sfsave(STFLAGH sfh, const SFENTRY *tbl); +int hostdrv_sfload(STFLAGH sfh, const SFENTRY *tbl); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/generic/hostdrvs.c b/generic/hostdrvs.c old mode 100755 new mode 100644 index 4a6026f9..ad256c8d --- a/generic/hostdrvs.c +++ b/generic/hostdrvs.c @@ -1,596 +1,596 @@ -/** - * @file hostdrvs.c - * @brief Implementation of host-drive - */ - -#include -#include - -#if defined(SUPPORT_HOSTDRV) - -#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) -#include "oemtext.h" -#endif -#include -#include "ini.h" - -//#include - - // 性能上最適化で優先しない方がいいコードなのでわざと別セグメントに置く -#pragma code_seg(".MISCCODE") - -/*! ルート情報 */ -static const HDRVFILE s_hddroot = {{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, 0, 0, 0x10, {0}, {0}}; - -/*! 自分 */ -static const char s_self[11] = {'.',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; - -/*! 親 */ -static const char s_parent[11] = {'.','.',' ',' ',' ',' ',' ',' ',' ',' ',' '}; - -/*! DOSで許可されるキャラクタ */ -static const UINT8 s_cDosCharacters[] = -{ - 0xfa, 0x23, /* '&%$#"! /.-,+*)( */ - 0xff, 0x03, /* 76543210 ?>=<;:98 */ - 0xff, 0xff, /* GFEDCBA@ ONMLKJIH */ - 0xff, 0xef, /* WVUTSRQP _^]\[ZYX */ - 0x01, 0x00, /* gfedcba` onmlkjih */ - 0x00, 0x40 /* wvutsrqp ~}|{zyx */ -}; - -/** - * パスを FCB に変換 - * @param[out] lpFcbname FCB - * @param[in] cchFcbname FCB バッファ サイズ - * @param[in] lpPath パス - */ -static void RealPath2FcbSub(char *lpFcbname, UINT cchFcbname, const char *lpPath) -{ - REG8 c; - - while (cchFcbname) - { - c = (UINT8)*lpPath++; - if (c == 0) - { - break; - } -#if defined(OSLANG_SJIS) || defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) - if ((((c ^ 0x20) - 0xa1) & 0xff) < 0x3c) - { - if (lpPath[0] == '\0') - { - break; - } - if (cchFcbname < 2) - { - break; - } - lpFcbname[0] = c; - lpFcbname[1] = *lpPath++; - lpFcbname += 2; - cchFcbname -= 2; - } - else if (((c - 0x20) & 0xff) < 0x60) - { - if (((c - 'a') & 0xff) < 26) - { - c -= 0x20; - } - if (s_cDosCharacters[(c >> 3) - (0x20 >> 3)] & (1 << (c & 7))) - { - *lpFcbname++ = c; - cchFcbname--; - } - } - else if (((c - 0xa0) & 0xff) < 0x40) - { - *lpFcbname++ = c; - cchFcbname--; - } -#else - if (((c - 0x20) & 0xff) < 0x60) - { - if (((c - 'a') & 0xff) < 26) - { - c -= 0x20; - } - if (s_cDosCharacters[(c >> 3) - (0x20 >> 3)] & (1 << (c & 7))) - { - *lpFcbname++ = c; - cchFcbname--; - } - } - else if (c >= 0x80) - { - *lpFcbname++ = c; - cchFcbname--; - } -#endif - } -} - -/** - * パスを FCB に変換 - * @param[out] lpFcbname FCB - * @param[in] lpPath パス - */ -static void RealName2Fcb(char *lpFcbname, const OEMCHAR *lpPath) -{ - OEMCHAR *ext; -#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) - char sjis[MAX_PATH]; -#endif - OEMCHAR szFilename[MAX_PATH]; - - FillMemory(lpFcbname, 11, ' '); - - ext = file_getext(lpPath); -#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) - oemtext_oemtosjis(sjis, NELEMENTS(sjis), ext, (UINT)-1); - RealPath2FcbSub(lpFcbname + 8, 3, sjis); -#else - RealPath2FcbSub(lpFcbname + 8, 3, ext); -#endif - - file_cpyname(szFilename, lpPath, NELEMENTS(szFilename)); - file_cutext(szFilename); -#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) - oemtext_oemtosjis(sjis, NELEMENTS(sjis), szFilename, (UINT)-1); - RealPath2FcbSub(lpFcbname + 0, 8, sjis); -#else - RealPath2FcbSub(lpFcbname + 0, 8, szFilename); -#endif -} - -/** - * FCB 名が一致するか? - * @param[in] phdf ファイル情報 - * @param[in] lpMask マスク - * @param[in] nAttr アトリビュート マスク - * @retval TRUE 一致 - * @retval FALSE 不一致 - */ -static BOOL IsMatchFcb(const HDRVFILE *phdf, const char *lpMask, UINT nAttr) -{ - UINT i; - - if ((phdf->attr & (~nAttr)) & 0x16) - { - return FALSE; - } - if (lpMask != NULL) - { - for (i = 0; i < 11; i++) - { - if ((phdf->fcbname[i] != lpMask[i]) && (lpMask[i] != '?')) - { - return FALSE; - } - } - } - return TRUE; -} - -/** - * FCB 名が一致するか - * @param[in] vpItem アイテム - * @param[in] vpArg ユーザ引数 - * @retval TRUE 一致 - * @retval FALSE 不一致 - */ -static BOOL IsMatchName(void *vpItem, void *vpArg) -{ - return IsMatchFcb((HDRVFILE *)vpItem, (char *)vpArg, 0x16); -} - -/** - * ファイル一覧を取得 - * @param[in] phdp パス - * @param[in] lpMask マスク - * @param[in] nAttr アトリビュート - * @return ファイル一覧 - */ -LISTARRAY hostdrvs_getpathlist(const HDRVPATH *phdp, const char *lpMask, UINT nAttr) -{ - LISTARRAY ret; - LISTARRAY lst; - HDRVFILE file; - HDRVLST hdd; - FLISTH flh; - FLINFO fli; - int isRoot = phdp->szPath && (_tcsicmp(phdp->szPath, np2cfg.hdrvroot) == 0); - - ret = listarray_new(sizeof(_HDRVLST), 64); - if (ret != NULL) - { - lst = listarray_new(sizeof(file), 64); - - if (phdp->file.attr & 0x10) - { - file = phdp->file; - memcpy(file.fcbname, s_self, 11); - listarray_append(lst, &file); - if (!isRoot && IsMatchFcb(&file, lpMask, nAttr)) - { - hdd = (HDRVLST)listarray_append(ret, NULL); - if (hdd != NULL) - { - hdd->file = file; - file_cpyname(hdd->szFilename, OEMTEXT("."), NELEMENTS(hdd->szFilename)); - } - } - - file = phdp->file; - memcpy(file.fcbname, s_parent, 11); - listarray_append(lst, &file); - if (!isRoot && IsMatchFcb(&file, lpMask, nAttr)) - { - hdd = (HDRVLST)listarray_append(ret, NULL); - if (hdd != NULL) - { - hdd->file = file; - file_cpyname(hdd->szFilename, OEMTEXT(".."), NELEMENTS(hdd->szFilename)); - } - } - } - - flh = file_list1st(phdp->szPath, &fli); - if (flh != FLISTH_INVALID) - { - do - { - RealName2Fcb(file.fcbname, fli.path); - if ((file.fcbname[0] == ' ') || (listarray_enum(lst, IsMatchName, file.fcbname) != NULL)) - { - continue; - } - - file.caps = fli.caps; - file.size = fli.size; - file.attr = fli.attr; - file.date = fli.date; - file.time = fli.time; - listarray_append(lst, &file); - if (IsMatchFcb(&file, lpMask, nAttr)) - { - hdd = (HDRVLST)listarray_append(ret, NULL); - if (hdd != NULL) - { - hdd->file = file; - file_cpyname(hdd->szFilename, fli.path, NELEMENTS(hdd->szFilename)); - } - } - } while (file_listnext(flh, &fli) == SUCCESS); - file_listclose(flh); - } - if (listarray_getitems(ret) == 0) - { - listarray_destroy(ret); - ret = NULL; - } - listarray_destroy(lst); - } - return ret; -} - -/* ---- */ - -/** - * DOS 名を FCB に変換 - * @param[out] lpFcbname FCB - * @param[in] cchFcbname FCB バッファ サイズ - * @param[in] lpDosPath DOS パス - * @return 次の DOS パス - */ -static const char *DosPath2FcbSub(char *lpFcbname, UINT cchFcbname, const char *lpDosPath) -{ - char c; - - while (cchFcbname) - { - c = lpDosPath[0]; - if ((c == 0) || (c == '.') || (c == '\\')) - { - break; - } - if ((((c ^ 0x20) - 0xa1) & 0xff) < 0x3c) - { - if (lpDosPath[1] == '\0') - { - break; - } - if (cchFcbname < 2) - { - break; - } - lpDosPath++; - lpFcbname[0] = c; - lpFcbname[1] = *lpDosPath; - lpFcbname += 2; - cchFcbname -= 2; - } - else - { - *lpFcbname++ = c; - cchFcbname--; - } - lpDosPath++; - } - return lpDosPath; -} - -/** - * DOS 名を FCB に変換 - * @param[out] lpFcbname FCB - * @param[in] lpDosPath DOS パス - * @return 次の DOS パス - */ -static const char *DosPath2Fcb(char *lpFcbname, const char *lpDosPath) -{ - FillMemory(lpFcbname, 11, ' '); - lpDosPath = DosPath2FcbSub(lpFcbname, 8, lpDosPath); - if (lpDosPath[0] == '.') - { - lpDosPath = DosPath2FcbSub(lpFcbname + 8, 3, lpDosPath + 1); - } - return lpDosPath; -} - -/** - * パス検索 - * @param[in,out] phdp HostDrv パス - * @param[in] lpFcbname FCB 名 - * @retval SUCCESS 成功 - * @retval FAILURE 失敗 - */ -static BRESULT FindSinglePath(HDRVPATH *phdp, const char *lpFcbname) -{ - BOOL r; - FLISTH flh; - FLINFO fli; - char fcbname[11]; - - r = FALSE; - flh = file_list1st(phdp->szPath, &fli); - if (flh != FLISTH_INVALID) - { - do - { - RealName2Fcb(fcbname, fli.path); - if (memcmp(fcbname, lpFcbname, 11) == 0) - { - memcpy(phdp->file.fcbname, fcbname, 11); - phdp->file.caps = fli.caps; - phdp->file.size = fli.size; - phdp->file.attr = fli.attr; - phdp->file.date = fli.date; - phdp->file.time = fli.time; - file_setseparator(phdp->szPath, NELEMENTS(phdp->szPath)); - file_catname(phdp->szPath, fli.path, NELEMENTS(phdp->szPath)); - r = TRUE; - break; - } - } while (file_listnext(flh, &fli) == SUCCESS); - file_listclose(flh); - } - return (r) ? SUCCESS : FAILURE; -} - -/** - * ディレクトリを得る - * @param[out] phdp HostDrv パス - * @param[out] lpFcbname FCB 名 - * @param[in] lpDosPath DOS パス - * @return DOS エラー コード - */ -BOOL PathIsRelative(char *path) { - if(path[0] == '/') { - return TRUE; - } - return FALSE; -} - -#define _countof(array) (sizeof(array) / sizeof(array[0])) - -UINT hostdrvs_getrealdir(HDRVPATH *phdp, char *lpFcbname, const char *lpDosPath) -{ - phdp->file = s_hddroot; - if(PathIsRelative(np2cfg.hdrvroot)){ - TCHAR pathbuf[MAX_PATH+1]; - TCHAR *pathtmp; - initgetfile(pathbuf, _countof(pathbuf)); -#if defined(_WIN32) - pathtmp = strrchr(pathbuf, '\\'); -#else /* _WIN32 */ - pathtmp = strrchr(pathbuf, '/'); -#endif /* _WIN32 */ - if(pathtmp){ - *(pathtmp+1) = 0; - }else{ - pathbuf[0] = 0; - } - strcat(pathbuf, np2cfg.hdrvroot); - file_cpyname(phdp->szPath, pathbuf, NELEMENTS(phdp->szPath)); - }else{ - file_cpyname(phdp->szPath, np2cfg.hdrvroot, NELEMENTS(phdp->szPath)); - } - - if (lpDosPath[0] == '\\') - { - lpDosPath++; - } - else if (lpDosPath[0] != '\0') - { - return ERR_PATHNOTFOUND; - } - while (TRUE /*CONSTCOND*/) - { - lpDosPath = DosPath2Fcb(lpFcbname, lpDosPath); - if (lpDosPath[0] != '\\') - { - break; - } - if ((FindSinglePath(phdp, lpFcbname) != SUCCESS) || ((phdp->file.attr & 0x10) == 0)) - { - return FAILURE; - } - lpDosPath++; - } - return (lpDosPath[0] == '\0') ? ERR_NOERROR : ERR_PATHNOTFOUND; -} - -/** - * パスを結合する - * @param[in,out] phdp HostDrv パス - * @param[in] lpFcbname FCB 名 - * @return DOS エラー コード - */ -UINT hostdrvs_appendname(HDRVPATH *phdp, const char *lpFcbname) -{ - char szDosName[16]; - char *p; - UINT i; -#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) - OEMCHAR oemname[64]; -#endif - - if (lpFcbname[0] == ' ') - { - return ERR_PATHNOTFOUND; - } - else if (FindSinglePath(phdp, lpFcbname) == SUCCESS) - { - return ERR_NOERROR; - } - else - { - memset(&phdp->file, 0, sizeof(phdp->file)); - memcpy(phdp->file.fcbname, lpFcbname, 11); - file_setseparator(phdp->szPath, NELEMENTS(phdp->szPath)); - - p = szDosName; - for (i = 0; (i < 8) && (lpFcbname[i] != ' '); i++) - { - *p++ = lpFcbname[i]; - } - if (lpFcbname[8] != ' ') - { - *p++ = '.'; - for (i = 8; (i < 11) && (lpFcbname[i] != ' '); i++) - { - *p++ = lpFcbname[i]; - } - } - *p = '\0'; -#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) - oemtext_sjistooem(oemname, NELEMENTS(oemname), szDosName, (UINT)-1); - file_catname(phdp->szPath, oemname, NELEMENTS(phdp->szPath)); -#else - file_catname(phdp->szPath, szDosName, NELEMENTS(phdp->szPath)); -#endif - return ERR_FILENOTFOUND; - } -} - -/** - * パスを得る - * @param[out] phdp HostDrv パス - * @param[in] lpDosPath DOS パス - * @return DOS エラー コード - */ -UINT hostdrvs_getrealpath(HDRVPATH *phdp, const char *lpDosPath) -{ - char fcbname[11]; - UINT nResult; - - if (lpDosPath[0] == '\0' || (lpDosPath[0] == '\\' && lpDosPath[1] == '\0')) // root check - { - file_cpyname(phdp->szPath, np2cfg.hdrvroot, NELEMENTS(phdp->szPath)); // copy root path - return ERR_NOERROR; - } - nResult = hostdrvs_getrealdir(phdp, fcbname, lpDosPath); - if (nResult == ERR_NOERROR) - { - nResult = hostdrvs_appendname(phdp, fcbname); - } - return nResult; -} - -/* ---- */ - -/** - * ファイルハンドルをクローズする - * @param[in] vpItem アイテム - * @param[in] vpArg ユーザ引数 - * @retval FALSE 継続 - */ -static BOOL CloseFileHandle(void *vpItem, void *vpArg) -{ - INTPTR fh; - - fh = ((HDRVHANDLE)vpItem)->hdl; - if (fh != (INTPTR)FILEH_INVALID) - { - ((HDRVHANDLE)vpItem)->hdl = (INTPTR)FILEH_INVALID; - file_close((FILEH)fh); - } - (void)vpArg; - return FALSE; -} - -/** - * すべてクローズ - * @param[in] fileArray ファイル リスト ハンドル - */ -void hostdrvs_fhdlallclose(LISTARRAY fileArray) -{ - listarray_enum(fileArray, CloseFileHandle, NULL); -} - -/** - * 空ハンドルを見つけるコールバック - * @param[in] vpItem アイテム - * @param[in] vpArg ユーザ引数 - * @retval TRUE 見つかった - * @retval FALSE 見つからなかった - */ -static BOOL IsHandleInvalid(void *vpItem, void *vpArg) -{ - if (((HDRVHANDLE)vpItem)->hdl == (INTPTR)FILEH_INVALID) - { - return TRUE; - } - (void)vpArg; - return FALSE; -} - -/** - * 新しいハンドルを得る - * @param[in] fileArray ファイル リスト ハンドル - * @return 新しいハンドル - */ -HDRVHANDLE hostdrvs_fhdlsea(LISTARRAY fileArray) -{ - HDRVHANDLE ret; - - if (fileArray == NULL) - { - TRACEOUT(("hostdrvs_fhdlsea hdl == NULL")); - } - ret = (HDRVHANDLE)listarray_enum(fileArray, IsHandleInvalid, NULL); - if (ret == NULL) - { - ret = (HDRVHANDLE)listarray_append(fileArray, NULL); - if (ret != NULL) - { - ret->hdl = (INTPTR)FILEH_INVALID; - } - } - return ret; -} - -#pragma code_seg() - -#endif +/** + * @file hostdrvs.c + * @brief Implementation of host-drive + */ + +#include +#include + +#if defined(SUPPORT_HOSTDRV) + +#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) +#include "oemtext.h" +#endif +#include +#include "ini.h" + +//#include + + // 性能上最適化で優先しない方がいいコードなのでわざと別セグメントに置く +#pragma code_seg(".MISCCODE") + +/*! ルート情報 */ +static const HDRVFILE s_hddroot = {{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}, 0, 0, 0x10, {0}, {0}}; + +/*! 自分 */ +static const char s_self[11] = {'.',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; + +/*! 親 */ +static const char s_parent[11] = {'.','.',' ',' ',' ',' ',' ',' ',' ',' ',' '}; + +/*! DOSで許可されるキャラクタ */ +static const UINT8 s_cDosCharacters[] = +{ + 0xfa, 0x23, /* '&%$#"! /.-,+*)( */ + 0xff, 0x03, /* 76543210 ?>=<;:98 */ + 0xff, 0xff, /* GFEDCBA@ ONMLKJIH */ + 0xff, 0xef, /* WVUTSRQP _^]\[ZYX */ + 0x01, 0x00, /* gfedcba` onmlkjih */ + 0x00, 0x40 /* wvutsrqp ~}|{zyx */ +}; + +/** + * パスを FCB に変換 + * @param[out] lpFcbname FCB + * @param[in] cchFcbname FCB バッファ サイズ + * @param[in] lpPath パス + */ +static void RealPath2FcbSub(char *lpFcbname, UINT cchFcbname, const char *lpPath) +{ + REG8 c; + + while (cchFcbname) + { + c = (UINT8)*lpPath++; + if (c == 0) + { + break; + } +#if defined(OSLANG_SJIS) || defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) + if ((((c ^ 0x20) - 0xa1) & 0xff) < 0x3c) + { + if (lpPath[0] == '\0') + { + break; + } + if (cchFcbname < 2) + { + break; + } + lpFcbname[0] = c; + lpFcbname[1] = *lpPath++; + lpFcbname += 2; + cchFcbname -= 2; + } + else if (((c - 0x20) & 0xff) < 0x60) + { + if (((c - 'a') & 0xff) < 26) + { + c -= 0x20; + } + if (s_cDosCharacters[(c >> 3) - (0x20 >> 3)] & (1 << (c & 7))) + { + *lpFcbname++ = c; + cchFcbname--; + } + } + else if (((c - 0xa0) & 0xff) < 0x40) + { + *lpFcbname++ = c; + cchFcbname--; + } +#else + if (((c - 0x20) & 0xff) < 0x60) + { + if (((c - 'a') & 0xff) < 26) + { + c -= 0x20; + } + if (s_cDosCharacters[(c >> 3) - (0x20 >> 3)] & (1 << (c & 7))) + { + *lpFcbname++ = c; + cchFcbname--; + } + } + else if (c >= 0x80) + { + *lpFcbname++ = c; + cchFcbname--; + } +#endif + } +} + +/** + * パスを FCB に変換 + * @param[out] lpFcbname FCB + * @param[in] lpPath パス + */ +static void RealName2Fcb(char *lpFcbname, const OEMCHAR *lpPath) +{ + OEMCHAR *ext; +#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) + char sjis[MAX_PATH]; +#endif + OEMCHAR szFilename[MAX_PATH]; + + FillMemory(lpFcbname, 11, ' '); + + ext = file_getext(lpPath); +#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) + oemtext_oemtosjis(sjis, NELEMENTS(sjis), ext, (UINT)-1); + RealPath2FcbSub(lpFcbname + 8, 3, sjis); +#else + RealPath2FcbSub(lpFcbname + 8, 3, ext); +#endif + + file_cpyname(szFilename, lpPath, NELEMENTS(szFilename)); + file_cutext(szFilename); +#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) + oemtext_oemtosjis(sjis, NELEMENTS(sjis), szFilename, (UINT)-1); + RealPath2FcbSub(lpFcbname + 0, 8, sjis); +#else + RealPath2FcbSub(lpFcbname + 0, 8, szFilename); +#endif +} + +/** + * FCB 名が一致するか? + * @param[in] phdf ファイル情報 + * @param[in] lpMask マスク + * @param[in] nAttr アトリビュート マスク + * @retval TRUE 一致 + * @retval FALSE 不一致 + */ +static BOOL IsMatchFcb(const HDRVFILE *phdf, const char *lpMask, UINT nAttr) +{ + UINT i; + + if ((phdf->attr & (~nAttr)) & 0x16) + { + return FALSE; + } + if (lpMask != NULL) + { + for (i = 0; i < 11; i++) + { + if ((phdf->fcbname[i] != lpMask[i]) && (lpMask[i] != '?')) + { + return FALSE; + } + } + } + return TRUE; +} + +/** + * FCB 名が一致するか + * @param[in] vpItem アイテム + * @param[in] vpArg ユーザ引数 + * @retval TRUE 一致 + * @retval FALSE 不一致 + */ +static BOOL IsMatchName(void *vpItem, void *vpArg) +{ + return IsMatchFcb((HDRVFILE *)vpItem, (char *)vpArg, 0x16); +} + +/** + * ファイル一覧を取得 + * @param[in] phdp パス + * @param[in] lpMask マスク + * @param[in] nAttr アトリビュート + * @return ファイル一覧 + */ +LISTARRAY hostdrvs_getpathlist(const HDRVPATH *phdp, const char *lpMask, UINT nAttr) +{ + LISTARRAY ret; + LISTARRAY lst; + HDRVFILE file; + HDRVLST hdd; + FLISTH flh; + FLINFO fli; + int isRoot = phdp->szPath && (_tcsicmp(phdp->szPath, np2cfg.hdrvroot) == 0); + + ret = listarray_new(sizeof(_HDRVLST), 64); + if (ret != NULL) + { + lst = listarray_new(sizeof(file), 64); + + if (phdp->file.attr & 0x10) + { + file = phdp->file; + memcpy(file.fcbname, s_self, 11); + listarray_append(lst, &file); + if (!isRoot && IsMatchFcb(&file, lpMask, nAttr)) + { + hdd = (HDRVLST)listarray_append(ret, NULL); + if (hdd != NULL) + { + hdd->file = file; + file_cpyname(hdd->szFilename, OEMTEXT("."), NELEMENTS(hdd->szFilename)); + } + } + + file = phdp->file; + memcpy(file.fcbname, s_parent, 11); + listarray_append(lst, &file); + if (!isRoot && IsMatchFcb(&file, lpMask, nAttr)) + { + hdd = (HDRVLST)listarray_append(ret, NULL); + if (hdd != NULL) + { + hdd->file = file; + file_cpyname(hdd->szFilename, OEMTEXT(".."), NELEMENTS(hdd->szFilename)); + } + } + } + + flh = file_list1st(phdp->szPath, &fli); + if (flh != FLISTH_INVALID) + { + do + { + RealName2Fcb(file.fcbname, fli.path); + if ((file.fcbname[0] == ' ') || (listarray_enum(lst, IsMatchName, file.fcbname) != NULL)) + { + continue; + } + + file.caps = fli.caps; + file.size = fli.size; + file.attr = fli.attr; + file.date = fli.date; + file.time = fli.time; + listarray_append(lst, &file); + if (IsMatchFcb(&file, lpMask, nAttr)) + { + hdd = (HDRVLST)listarray_append(ret, NULL); + if (hdd != NULL) + { + hdd->file = file; + file_cpyname(hdd->szFilename, fli.path, NELEMENTS(hdd->szFilename)); + } + } + } while (file_listnext(flh, &fli) == SUCCESS); + file_listclose(flh); + } + if (listarray_getitems(ret) == 0) + { + listarray_destroy(ret); + ret = NULL; + } + listarray_destroy(lst); + } + return ret; +} + +/* ---- */ + +/** + * DOS 名を FCB に変換 + * @param[out] lpFcbname FCB + * @param[in] cchFcbname FCB バッファ サイズ + * @param[in] lpDosPath DOS パス + * @return 次の DOS パス + */ +static const char *DosPath2FcbSub(char *lpFcbname, UINT cchFcbname, const char *lpDosPath) +{ + char c; + + while (cchFcbname) + { + c = lpDosPath[0]; + if ((c == 0) || (c == '.') || (c == '\\')) + { + break; + } + if ((((c ^ 0x20) - 0xa1) & 0xff) < 0x3c) + { + if (lpDosPath[1] == '\0') + { + break; + } + if (cchFcbname < 2) + { + break; + } + lpDosPath++; + lpFcbname[0] = c; + lpFcbname[1] = *lpDosPath; + lpFcbname += 2; + cchFcbname -= 2; + } + else + { + *lpFcbname++ = c; + cchFcbname--; + } + lpDosPath++; + } + return lpDosPath; +} + +/** + * DOS 名を FCB に変換 + * @param[out] lpFcbname FCB + * @param[in] lpDosPath DOS パス + * @return 次の DOS パス + */ +static const char *DosPath2Fcb(char *lpFcbname, const char *lpDosPath) +{ + FillMemory(lpFcbname, 11, ' '); + lpDosPath = DosPath2FcbSub(lpFcbname, 8, lpDosPath); + if (lpDosPath[0] == '.') + { + lpDosPath = DosPath2FcbSub(lpFcbname + 8, 3, lpDosPath + 1); + } + return lpDosPath; +} + +/** + * パス検索 + * @param[in,out] phdp HostDrv パス + * @param[in] lpFcbname FCB 名 + * @retval SUCCESS 成功 + * @retval FAILURE 失敗 + */ +static BRESULT FindSinglePath(HDRVPATH *phdp, const char *lpFcbname) +{ + BOOL r; + FLISTH flh; + FLINFO fli; + char fcbname[11]; + + r = FALSE; + flh = file_list1st(phdp->szPath, &fli); + if (flh != FLISTH_INVALID) + { + do + { + RealName2Fcb(fcbname, fli.path); + if (memcmp(fcbname, lpFcbname, 11) == 0) + { + memcpy(phdp->file.fcbname, fcbname, 11); + phdp->file.caps = fli.caps; + phdp->file.size = fli.size; + phdp->file.attr = fli.attr; + phdp->file.date = fli.date; + phdp->file.time = fli.time; + file_setseparator(phdp->szPath, NELEMENTS(phdp->szPath)); + file_catname(phdp->szPath, fli.path, NELEMENTS(phdp->szPath)); + r = TRUE; + break; + } + } while (file_listnext(flh, &fli) == SUCCESS); + file_listclose(flh); + } + return (r) ? SUCCESS : FAILURE; +} + +/** + * ディレクトリを得る + * @param[out] phdp HostDrv パス + * @param[out] lpFcbname FCB 名 + * @param[in] lpDosPath DOS パス + * @return DOS エラー コード + */ +BOOL PathIsRelative(char *path) { + if(path[0] == '/') { + return TRUE; + } + return FALSE; +} + +#define _countof(array) (sizeof(array) / sizeof(array[0])) + +UINT hostdrvs_getrealdir(HDRVPATH *phdp, char *lpFcbname, const char *lpDosPath) +{ + phdp->file = s_hddroot; + if(PathIsRelative(np2cfg.hdrvroot)){ + TCHAR pathbuf[MAX_PATH+1]; + TCHAR *pathtmp; + initgetfile(pathbuf, _countof(pathbuf)); +#if defined(_WIN32) + pathtmp = strrchr(pathbuf, '\\'); +#else /* _WIN32 */ + pathtmp = strrchr(pathbuf, '/'); +#endif /* _WIN32 */ + if(pathtmp){ + *(pathtmp+1) = 0; + }else{ + pathbuf[0] = 0; + } + strcat(pathbuf, np2cfg.hdrvroot); + file_cpyname(phdp->szPath, pathbuf, NELEMENTS(phdp->szPath)); + }else{ + file_cpyname(phdp->szPath, np2cfg.hdrvroot, NELEMENTS(phdp->szPath)); + } + + if (lpDosPath[0] == '\\') + { + lpDosPath++; + } + else if (lpDosPath[0] != '\0') + { + return ERR_PATHNOTFOUND; + } + while (TRUE /*CONSTCOND*/) + { + lpDosPath = DosPath2Fcb(lpFcbname, lpDosPath); + if (lpDosPath[0] != '\\') + { + break; + } + if ((FindSinglePath(phdp, lpFcbname) != SUCCESS) || ((phdp->file.attr & 0x10) == 0)) + { + return FAILURE; + } + lpDosPath++; + } + return (lpDosPath[0] == '\0') ? ERR_NOERROR : ERR_PATHNOTFOUND; +} + +/** + * パスを結合する + * @param[in,out] phdp HostDrv パス + * @param[in] lpFcbname FCB 名 + * @return DOS エラー コード + */ +UINT hostdrvs_appendname(HDRVPATH *phdp, const char *lpFcbname) +{ + char szDosName[16]; + char *p; + UINT i; +#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) + OEMCHAR oemname[64]; +#endif + + if (lpFcbname[0] == ' ') + { + return ERR_PATHNOTFOUND; + } + else if (FindSinglePath(phdp, lpFcbname) == SUCCESS) + { + return ERR_NOERROR; + } + else + { + memset(&phdp->file, 0, sizeof(phdp->file)); + memcpy(phdp->file.fcbname, lpFcbname, 11); + file_setseparator(phdp->szPath, NELEMENTS(phdp->szPath)); + + p = szDosName; + for (i = 0; (i < 8) && (lpFcbname[i] != ' '); i++) + { + *p++ = lpFcbname[i]; + } + if (lpFcbname[8] != ' ') + { + *p++ = '.'; + for (i = 8; (i < 11) && (lpFcbname[i] != ' '); i++) + { + *p++ = lpFcbname[i]; + } + } + *p = '\0'; +#if defined(OSLANG_EUC) || defined(OSLANG_UTF8) || defined(OSLANG_UCS2) + oemtext_sjistooem(oemname, NELEMENTS(oemname), szDosName, (UINT)-1); + file_catname(phdp->szPath, oemname, NELEMENTS(phdp->szPath)); +#else + file_catname(phdp->szPath, szDosName, NELEMENTS(phdp->szPath)); +#endif + return ERR_FILENOTFOUND; + } +} + +/** + * パスを得る + * @param[out] phdp HostDrv パス + * @param[in] lpDosPath DOS パス + * @return DOS エラー コード + */ +UINT hostdrvs_getrealpath(HDRVPATH *phdp, const char *lpDosPath) +{ + char fcbname[11]; + UINT nResult; + + if (lpDosPath[0] == '\0' || (lpDosPath[0] == '\\' && lpDosPath[1] == '\0')) // root check + { + file_cpyname(phdp->szPath, np2cfg.hdrvroot, NELEMENTS(phdp->szPath)); // copy root path + return ERR_NOERROR; + } + nResult = hostdrvs_getrealdir(phdp, fcbname, lpDosPath); + if (nResult == ERR_NOERROR) + { + nResult = hostdrvs_appendname(phdp, fcbname); + } + return nResult; +} + +/* ---- */ + +/** + * ファイルハンドルをクローズする + * @param[in] vpItem アイテム + * @param[in] vpArg ユーザ引数 + * @retval FALSE 継続 + */ +static BOOL CloseFileHandle(void *vpItem, void *vpArg) +{ + INTPTR fh; + + fh = ((HDRVHANDLE)vpItem)->hdl; + if (fh != (INTPTR)FILEH_INVALID) + { + ((HDRVHANDLE)vpItem)->hdl = (INTPTR)FILEH_INVALID; + file_close((FILEH)fh); + } + (void)vpArg; + return FALSE; +} + +/** + * すべてクローズ + * @param[in] fileArray ファイル リスト ハンドル + */ +void hostdrvs_fhdlallclose(LISTARRAY fileArray) +{ + listarray_enum(fileArray, CloseFileHandle, NULL); +} + +/** + * 空ハンドルを見つけるコールバック + * @param[in] vpItem アイテム + * @param[in] vpArg ユーザ引数 + * @retval TRUE 見つかった + * @retval FALSE 見つからなかった + */ +static BOOL IsHandleInvalid(void *vpItem, void *vpArg) +{ + if (((HDRVHANDLE)vpItem)->hdl == (INTPTR)FILEH_INVALID) + { + return TRUE; + } + (void)vpArg; + return FALSE; +} + +/** + * 新しいハンドルを得る + * @param[in] fileArray ファイル リスト ハンドル + * @return 新しいハンドル + */ +HDRVHANDLE hostdrvs_fhdlsea(LISTARRAY fileArray) +{ + HDRVHANDLE ret; + + if (fileArray == NULL) + { + TRACEOUT(("hostdrvs_fhdlsea hdl == NULL")); + } + ret = (HDRVHANDLE)listarray_enum(fileArray, IsHandleInvalid, NULL); + if (ret == NULL) + { + ret = (HDRVHANDLE)listarray_append(fileArray, NULL); + if (ret != NULL) + { + ret->hdl = (INTPTR)FILEH_INVALID; + } + } + return ret; +} + +#pragma code_seg() + +#endif diff --git a/generic/hostdrvs.h b/generic/hostdrvs.h old mode 100755 new mode 100644 index 80f50456..8eeee7ea --- a/generic/hostdrvs.h +++ b/generic/hostdrvs.h @@ -1,74 +1,74 @@ -/** - * @file hostdrvs.h - * @brief Interface of host-drive - */ - -#pragma once - -#if defined(SUPPORT_HOSTDRV) - -#include -#include - -/** - * dos error codes : see int2159-BX0000 - */ -enum -{ - ERR_NOERROR = 0x00, - ERR_FILENOTFOUND = 0x02, /*!< File not found */ - ERR_PATHNOTFOUND = 0x03, /*!< Path not found */ - ERR_NOHANDLESLEFT = 0x04, /*!< No handles left */ - ERR_ACCESSDENIED = 0x05, - ERR_INVALDACCESSMODE = 0x0c, /*!< Invalid access mode */ - ERR_ATTEMPTEDCURRDIR = 0x10, - ERR_NOMOREFILES = 0x12, - ERR_DISKWRITEPROTECTED = 0x13, - ERR_WRITEFAULT = 0x1d, - ERR_READFAULT = 0x1e, - ERR_FILE_EXISTS = 0x50 -}; - -/** - * @brief DOS ファイル情報 - */ -struct tagHostDrvFile -{ - char fcbname[11]; /*!< FCB 名 */ - UINT caps; /*!< 情報フラグ */ - UINT32 size; /*!< サイズ */ - UINT32 attr; /*!< 属性 */ - DOSDATE date; /*!< 日付 */ - DOSTIME time; /*!< 時間 */ -}; -typedef struct tagHostDrvFile HDRVFILE; /*!< 定義 */ - -/** - * @brief ファイル リスト情報 - */ -struct tagHostDrvList -{ - HDRVFILE file; /*!< DOS ファイル情報 */ - OEMCHAR szFilename[MAX_PATH]; /*!< ファイル名 */ -}; -typedef struct tagHostDrvList _HDRVLST; /*!< 定義 */ -typedef struct tagHostDrvList *HDRVLST; /*!< 定義 */ - -/** - * @brief パス情報 - */ -struct tagHostDrvPath -{ - HDRVFILE file; /*!< DOS ファイル情報 */ - OEMCHAR szPath[MAX_PATH]; /*!< パス */ -}; -typedef struct tagHostDrvPath HDRVPATH; /*!< 定義 */ - -LISTARRAY hostdrvs_getpathlist(const HDRVPATH *phdp, const char *lpMask, UINT nAttr); -UINT hostdrvs_getrealdir(HDRVPATH *phdp, char *lpFcbname, const char *lpDosPath); -UINT hostdrvs_appendname(HDRVPATH *phdp, const char *lpFcbname); -UINT hostdrvs_getrealpath(HDRVPATH *phdp, const char *lpDosPath); -void hostdrvs_fhdlallclose(LISTARRAY fileArray); -HDRVHANDLE hostdrvs_fhdlsea(LISTARRAY fileArray); - -#endif /* defined(SUPPORT_HOSTDRV) */ +/** + * @file hostdrvs.h + * @brief Interface of host-drive + */ + +#pragma once + +#if defined(SUPPORT_HOSTDRV) + +#include +#include + +/** + * dos error codes : see int2159-BX0000 + */ +enum +{ + ERR_NOERROR = 0x00, + ERR_FILENOTFOUND = 0x02, /*!< File not found */ + ERR_PATHNOTFOUND = 0x03, /*!< Path not found */ + ERR_NOHANDLESLEFT = 0x04, /*!< No handles left */ + ERR_ACCESSDENIED = 0x05, + ERR_INVALDACCESSMODE = 0x0c, /*!< Invalid access mode */ + ERR_ATTEMPTEDCURRDIR = 0x10, + ERR_NOMOREFILES = 0x12, + ERR_DISKWRITEPROTECTED = 0x13, + ERR_WRITEFAULT = 0x1d, + ERR_READFAULT = 0x1e, + ERR_FILE_EXISTS = 0x50 +}; + +/** + * @brief DOS ファイル情報 + */ +struct tagHostDrvFile +{ + char fcbname[11]; /*!< FCB 名 */ + UINT caps; /*!< 情報フラグ */ + UINT32 size; /*!< サイズ */ + UINT32 attr; /*!< 属性 */ + DOSDATE date; /*!< 日付 */ + DOSTIME time; /*!< 時間 */ +}; +typedef struct tagHostDrvFile HDRVFILE; /*!< 定義 */ + +/** + * @brief ファイル リスト情報 + */ +struct tagHostDrvList +{ + HDRVFILE file; /*!< DOS ファイル情報 */ + OEMCHAR szFilename[MAX_PATH]; /*!< ファイル名 */ +}; +typedef struct tagHostDrvList _HDRVLST; /*!< 定義 */ +typedef struct tagHostDrvList *HDRVLST; /*!< 定義 */ + +/** + * @brief パス情報 + */ +struct tagHostDrvPath +{ + HDRVFILE file; /*!< DOS ファイル情報 */ + OEMCHAR szPath[MAX_PATH]; /*!< パス */ +}; +typedef struct tagHostDrvPath HDRVPATH; /*!< 定義 */ + +LISTARRAY hostdrvs_getpathlist(const HDRVPATH *phdp, const char *lpMask, UINT nAttr); +UINT hostdrvs_getrealdir(HDRVPATH *phdp, char *lpFcbname, const char *lpDosPath); +UINT hostdrvs_appendname(HDRVPATH *phdp, const char *lpFcbname); +UINT hostdrvs_getrealpath(HDRVPATH *phdp, const char *lpDosPath); +void hostdrvs_fhdlallclose(LISTARRAY fileArray); +HDRVHANDLE hostdrvs_fhdlsea(LISTARRAY fileArray); + +#endif /* defined(SUPPORT_HOSTDRV) */ diff --git a/generic/keydisp.c b/generic/keydisp.c old mode 100755 new mode 100644 index aa671b7c..f5d67a11 --- a/generic/keydisp.c +++ b/generic/keydisp.c @@ -1,1320 +1,1320 @@ -/** - * @file keydisp.c - * @brief Implementation of the key display - */ - -#include - -#if defined(SUPPORT_KEYDISP) - -#include -#include -#include -#include -#include "sound/psggen.h" - -typedef struct -{ - UINT8 k[KEYDISP_NOTEMAX]; - UINT8 r[KEYDISP_NOTEMAX]; - UINT remain; - UINT8 flag; - UINT8 padding[3]; -} KDCHANNEL; - -typedef struct -{ - UINT8 ch; - UINT8 key; -} KDDELAYE; - -typedef struct -{ - UINT pos; - UINT rem; - UINT8 warm; - UINT8 warmbase; -} KDDELAY; - -/** - * @brief Channel - */ -struct tagFmChannel -{ - UINT16 nFNumber; /*!< F-Number */ - UINT8 cLastNote; /*!< The last note */ - UINT8 cKeyOn; /*!< KeyOn */ -}; -typedef struct tagFmChannel FMCHANNEL; - -/** - * @brief OPNA - */ -struct tagOpnaControl -{ - const UINT8 *pcRegister; /*!< The pointer of the register */ - UINT8 cChannelNum; /*!< The number of the channel */ - UINT8 cFMChannels; /*!< The channels of FM */ - UINT16 wFNumber[13]; /*!< The list of F-number */ - FMCHANNEL ch[6]; /*!< The information of FM */ -}; -typedef struct tagOpnaControl OPNACTL; - -/** - * @brief PSG - */ -struct tagPsgControl -{ - const UINT8 *pcRegister; /*!< The pointer of the register */ - REG16 nLastTone[4]; - UINT8 cLastNote[4]; - UINT16 wTone[13]; /*!< The list of Tone */ - UINT8 cChannelNum; /*!< The number of the channel */ - UINT8 cPsgOn; - UINT8 cLastMixer; -}; -typedef struct tagPsgControl PSGCTL; - -/** - * @brief OPL3 - */ -struct tagOpl3Control -{ - const UINT8 *pcRegister; /*!< The pointer of the register */ - UINT8 cChannelNum; /*!< The number of the channel */ - UINT8 cFMChannels; /*!< The channels of FM */ - UINT16 wFNumber[13]; /*!< The list of F-number */ - FMCHANNEL ch[18]; /*!< The information of FM */ -}; -typedef struct tagOpl3Control OPL3CTL; - -typedef struct -{ - UINT8 mode; - UINT8 dispflag; - UINT8 framepast; - UINT8 keymax; - UINT8 opnamax; - UINT8 psgmax; - UINT8 opl3max; - KDDELAY delay; - KDCHANNEL ch[KEYDISP_CHMAX]; - OPNACTL opnactl[5]; /*!< OPNA */ - PSGCTL psgctl[3]; /*!< PSG */ - OPL3CTL opl3ctl[8]; /*!< OPL3 */ - KDDELAYE delaye[KEYDISP_DELAYEVENTS]; -} KEYDISP; - -static KEYDISP s_keydisp; - -/** - * @brief The table of the notes - */ -struct TagNotePattern -{ - UINT16 nPosX; /*!< X-Coorinate */ - UINT8 nType; /*!< type */ - const UINT8 *lpImage; /*!< image */ -}; -typedef struct TagNotePattern NOTEPATTERN; /*!< The define of the note's pattern */ - -/** - * @brief const data - */ -struct KeyDispConstData -{ - UINT8 pal8[KEYDISP_PALS]; /*!< 8npp palettes */ - UINT16 pal16[2][KEYDISP_LEVEL]; /*!< 16bpp palettes */ - RGB32 pal32[2][KEYDISP_LEVEL]; /*!< 32bpp palettes */ - NOTEPATTERN pattern[128]; /*!< pattern */ -}; - -/*! const data */ -static struct KeyDispConstData s_constData; - -#include "keydisp.res" - - -/* ---- event */ - -static void keyon(KEYDISP *keydisp, UINT ch, UINT8 note) -{ - UINT i; - KDCHANNEL *kdch; - - note &= 0x7f; - kdch = keydisp->ch + ch; - for (i = 0; i < kdch->remain; i++) - { - if (kdch->k[i] == note) - { - /* ヒットした */ - for (; i < (kdch->remain - 1); i++) - { - kdch->k[i] = kdch->k[i + 1]; - kdch->r[i] = kdch->r[i + 1]; - } - kdch->k[i] = note; - kdch->r[i] = KEYDISP_LEVEL_MAX; - kdch->flag |= 1; - return; - } - } - if (i < KEYDISP_NOTEMAX) - { - kdch->k[i] = note; - kdch->r[i] = KEYDISP_LEVEL_MAX; - kdch->flag |= 1; - kdch->remain++; - } -} - -static void keyoff(KEYDISP *keydisp, UINT ch, UINT8 note) -{ - UINT i; - KDCHANNEL *kdch; - - note &= 0x7f; - kdch = keydisp->ch + ch; - for (i = 0; i < kdch->remain; i++) - { - if (kdch->k[i] == note) - { - /* ヒットした */ - kdch->r[i] = (KEYDISP_LEVEL_MAX - 1); - kdch->flag |= 1; - break; - } - } -} - -static void chkeyoff(KEYDISP *keydisp, UINT ch) -{ - UINT i; - KDCHANNEL *kdch; - - kdch = keydisp->ch + ch; - for (i = 0; i < kdch->remain; i++) - { - if (kdch->r[i] >= KEYDISP_LEVEL_MAX) - { - kdch->r[i] = (KEYDISP_LEVEL_MAX - 1); - kdch->flag |= 1; - } - } -} - -static void keyalloff(KEYDISP *keydisp) -{ - UINT i; - - for (i = 0; i < KEYDISP_CHMAX; i++) - { - chkeyoff(keydisp, i); - } -} - -static void keyallreload(KEYDISP *keydisp) -{ - UINT i; - - for (i = 0; i < KEYDISP_CHMAX; i++) - { - keydisp->ch[i].flag = 2; - } -} - -static void keyallclear(KEYDISP *keydisp) -{ - memset(keydisp->ch, 0, sizeof(keydisp->ch)); - keyallreload(keydisp); -} - - -/* ---- delay event */ - -static void ClearDelayList(KEYDISP *keydisp) -{ - keydisp->delay.warm = keydisp->delay.warmbase; - keydisp->delay.pos = 0; - keydisp->delay.rem = 0; - memset(keydisp->delaye, 0, sizeof(keydisp->delaye)); - keyalloff(keydisp); -} - -static void delayexecevent(KEYDISP *keydisp, UINT8 framepast) -{ - KDDELAYE *ebase; - UINT pos; - UINT rem; - KDDELAYE *ev; - - ebase = keydisp->delaye; - pos = keydisp->delay.pos; - rem = keydisp->delay.rem; - while ((keydisp->delay.warm) && (framepast)) - { - keydisp->delay.warm--; - framepast--; - if (rem >= KEYDISP_DELAYEVENTS) - { - ev = ebase + pos; - rem--; - if (ev->ch == 0xff) - { - keydisp->delay.warm++; - } - else if (ev->key & 0x80) - { - keyon(keydisp, ev->ch, ev->key); - rem--; - } - else - { - keyoff(keydisp, ev->ch, ev->key); - } - pos = (pos + 1) & (KEYDISP_DELAYEVENTS - 1); - } - ebase[(pos + rem) & (KEYDISP_DELAYEVENTS - 1)].ch = 0xff; - rem++; - } - while (framepast) - { - framepast--; - while (rem) - { - rem--; - ev = ebase + pos; - if (ev->ch == 0xff) - { - pos = (pos + 1) & (KEYDISP_DELAYEVENTS - 1); - break; - } - if (ev->key & 0x80) - { - keyon(keydisp, ev->ch, ev->key); - } - else - { - keyoff(keydisp, ev->ch, ev->key); - } - pos = (pos + 1) & (KEYDISP_DELAYEVENTS - 1); - } - ebase[(pos + rem) & (KEYDISP_DELAYEVENTS - 1)].ch = 0xff; - rem++; - } - keydisp->delay.pos = pos; - keydisp->delay.rem = rem; -} - -static void delaysetevent(KEYDISP *keydisp, REG8 ch, REG8 key) -{ - KDDELAYE *e; - - e = keydisp->delaye; - if (keydisp->delay.rem < KEYDISP_DELAYEVENTS) - { - e += (keydisp->delay.pos + keydisp->delay.rem) & (KEYDISP_DELAYEVENTS - 1); - keydisp->delay.rem++; - e->ch = ch; - e->key = key; - } - else - { - e += keydisp->delay.pos; - keydisp->delay.pos = (keydisp->delay.pos + 1) & (KEYDISP_DELAYEVENTS - 1); - if (e->ch == 0xff) - { - keydisp->delay.warm++; - } - else if (e->key & 0x80) - { - keyon(keydisp, e->ch, e->key); - } - else - { - keyoff(keydisp, e->ch, e->key); - } - e->ch = ch; - e->key = key; - } -} - - -/* ---- OPNA */ - -static UINT8 GetOpnaNote(const OPNACTL *k, UINT16 wFNum) -{ - UINT nOct; - UINT nKey; - - nOct = ((wFNum >> 11) & 7) + 2; - wFNum &= 0x7ff; - - while (wFNum < k->wFNumber[0]) - { - if (!nOct) - { - return 0; - } - nOct--; - wFNum <<= 1; - } - while (wFNum > k->wFNumber[12]) - { - wFNum >>= 1; - nOct++; - } - - for (nKey = 0; wFNum > k->wFNumber[nKey + 1]; nKey++) - { - } - - nKey += nOct * 12; - return (int)(MIN(nKey, 127)); -} - -static void opnakeyoff(KEYDISP *keydisp, OPNACTL *k, UINT nChannel) -{ - delaysetevent(keydisp, (REG8)(k->cChannelNum + nChannel), k->ch[nChannel].cLastNote); -} - -static void opnakeyon(KEYDISP *keydisp, OPNACTL *k, UINT nChannelNum) -{ - const UINT8 *pReg; - - opnakeyoff(keydisp, k, nChannelNum); - - pReg = k->pcRegister + ((nChannelNum / 3) << 8) + 0xa0 + (nChannelNum % 3); - k->ch[nChannelNum].nFNumber = ((pReg[4] & 0x3f) << 8) + pReg[0]; - k->ch[nChannelNum].cLastNote = GetOpnaNote(k, k->ch[nChannelNum].nFNumber); - delaysetevent(keydisp, (REG8)(k->cChannelNum + nChannelNum), (REG8)(k->ch[nChannelNum].cLastNote | 0x80)); -} - -static void opnakeyreset(KEYDISP *keydisp) -{ - UINT i; - - for (i = 0; i < NELEMENTS(keydisp->opnactl); i++) - { - memset(keydisp->opnactl[i].ch, 0, sizeof(keydisp->opnactl[i].ch)); - } -} - -void keydisp_opnakeyon(const UINT8 *pcRegister, REG8 cData) -{ - UINT i; - OPNACTL *k; - UINT nChannelNum; - - if (s_keydisp.mode != KEYDISP_MODEFM) - { - return; - } - - if ((cData & 3) == 3) - { - return; - } - - for (i = 0; i < s_keydisp.opnamax; i++) - { - k = &s_keydisp.opnactl[i]; - if (k->pcRegister == pcRegister) - { - nChannelNum = cData & 7; - cData &= 0xf0; - if (nChannelNum >= 4) - { - nChannelNum--; - } - if (nChannelNum >= NELEMENTS(k->ch)) { - continue; - } - if ((nChannelNum < k->cFMChannels) && (k->ch[nChannelNum].cKeyOn != cData)) - { - if (cData) - { - opnakeyon(&s_keydisp, k, nChannelNum); - } - else - { - opnakeyoff(&s_keydisp, k, nChannelNum); - } - k->ch[nChannelNum].cKeyOn = cData; - } - break; - } - } -} - -static void opnakeysync(KEYDISP *keydisp) -{ - UINT i; - OPNACTL *k; - const UINT8 *pReg; - UINT j; - UINT8 n; - UINT16 fnum; - - for (i = 0; i < keydisp->opnamax; i++) - { - k = &keydisp->opnactl[i]; - for (j = 0; j < k->cFMChannels; j++) - { - if (k->ch[j].cKeyOn) - { - pReg = k->pcRegister + ((j / 3) << 8) + 0xa0 + (j % 3); - fnum = ((pReg[4] & 0x3f) << 8) + pReg[0]; - if (k->ch[j].nFNumber != fnum) - { - k->ch[j].nFNumber = fnum; - n = GetOpnaNote(k, fnum); - if (k->ch[j].cLastNote != n) - { - opnakeyoff(keydisp, k, j); - } - k->ch[j].cLastNote = n; - delaysetevent(keydisp, (REG8)(k->cChannelNum + j), (REG8)(n | 0x80)); - } - } - } - } -} - - -/* ---- PSG */ - -/** - * Get pointer of controller - * @param[in] pcRegister The instance of PSG - * @return The pointer of controller - */ -static PSGCTL *GetController(KEYDISP *keydisp, const UINT8 *pcRegister) -{ - UINT i; - PSGCTL *k; - - if (keydisp->mode != KEYDISP_MODEFM) - { - return NULL; - } - - for (i = 0; i < keydisp->psgmax; i++) - { - k = &keydisp->psgctl[i]; - if (k->pcRegister == pcRegister) - { - return k; - } - } - return NULL; -} - -static UINT8 GetPSGNote(const PSGCTL *k, UINT16 nTone) -{ - UINT nOct; - UINT nKey; - - nOct = 5; - nTone &= 0xfff; - - while (nTone > k->wTone[0]) - { - if (!nOct) - { - return 0; - } - nTone >>= 1; - nOct--; - } - - if (!nTone) - { - return 127; - } - - while (nTone < k->wTone[12]) - { - nTone <<= 1; - nOct++; - } - for (nKey = 0; nTone < k->wTone[nKey + 1]; nKey++) - { - } - nKey += nOct * 12; - return (int)(MIN(nKey, 127)); -} - -static void psgmix(KEYDISP *keydisp, PSGCTL *k) -{ - const PSGREG *pReg; - - pReg = (const PSGREG *)k->pcRegister; - if ((k->cLastMixer ^ pReg->mixer) & 7) - { - UINT8 i, bit, pos; - k->cLastMixer = pReg->mixer; - pos = k->cChannelNum; - for (i = 0, bit = 1; i < 3; i++, pos++, bit <<= 1) - { - if (k->cPsgOn & bit) - { - k->cPsgOn ^= bit; - delaysetevent(keydisp, pos, k->cLastNote[i]); - } - else if ((!(k->cLastMixer & bit)) && (pReg->vol[i] & 0x1f)) - { - k->cPsgOn |= bit; - k->nLastTone[i] = LOADINTELWORD(pReg->tune[i]) & 0xfff; - k->cLastNote[i] = GetPSGNote(k, k->nLastTone[i]); - delaysetevent(keydisp, pos, (UINT8)(k->cLastNote[i] | 0x80)); - } - } - } -} - -static void psgvol(KEYDISP *keydisp, PSGCTL *k, UINT ch) -{ - const PSGREG *pReg; - UINT8 bit; - UINT8 pos; - UINT16 tune; - - pReg = (const PSGREG *)k->pcRegister; - bit = (1 << ch); - pos = k->cChannelNum + ch; - if (pReg->vol[ch] & 0x1f) - { - if (!((k->cLastMixer | k->cPsgOn) & bit)) - { - k->cPsgOn |= bit; - tune = LOADINTELWORD(pReg->tune[ch]); - tune &= 0xfff; - k->nLastTone[ch] = tune; - k->cLastNote[ch] = GetPSGNote(k, tune); - delaysetevent(keydisp, pos, (UINT8)(k->cLastNote[ch] | 0x80)); - } - } - else if (k->cPsgOn & bit) - { - k->cPsgOn ^= bit; - delaysetevent(keydisp, pos, k->cLastNote[ch]); - } -} - -static void psgkeyreset(KEYDISP *keydisp) -{ - UINT i; - - for (i = 0; i < NELEMENTS(keydisp->psgctl); i++) - { - keydisp->psgctl[i].cPsgOn = 0; - } -} - -/** - * Update keyboard - * @param[in] pcRegister The instance - * @param[in] nAddress The written register - */ -void keydisp_psg(const UINT8 *pcRegister, UINT nAddress) -{ - PSGCTL *k = GetController(&s_keydisp, pcRegister); - if (k != NULL) - { - switch (nAddress) - { - case 7: - psgmix(&s_keydisp, k); - break; - - case 8: - case 9: - case 10: - psgvol(&s_keydisp, k, nAddress - 8); - break; - } - } -} - -static void psgkeysync(KEYDISP *keydisp) -{ - UINT8 ch; - const PSGREG *pReg; - PSGCTL *k; - UINT8 bit; - UINT8 i; - UINT8 pos; - UINT16 tune; - UINT8 n; - - for (ch = 0, k = keydisp->psgctl; ch < keydisp->psgmax; ch++, k++) - { - pReg = (const PSGREG *)k->pcRegister; - pos = k->cChannelNum; - for (i = 0, bit = 1; i < 3; i++, pos++, bit <<= 1) - { - if (k->cPsgOn & bit) - { - tune = LOADINTELWORD(pReg->tune[i]); - tune &= 0xfff; - if (k->nLastTone[i] != tune) - { - k->nLastTone[i] = tune; - n = GetPSGNote(k, tune); - if (k->cLastNote[i] != n) - { - delaysetevent(keydisp, pos, k->cLastNote[i]); - k->cLastNote[i] = n; - delaysetevent(keydisp, pos, (UINT8)(n | 0x80)); - } - } - } - } - } -} - - - -/* ---- OPL3 */ - -static UINT8 GetOpl3Note(const OPL3CTL *k, UINT16 wFNum) -{ - UINT nOct; - UINT nKey; - - nOct = ((wFNum >> 10) & 7) + 2; - wFNum &= 0x3ff; - - while (wFNum < k->wFNumber[0]) - { - if (!nOct) - { - return 0; - } - nOct--; - wFNum <<= 1; - } - while (wFNum > k->wFNumber[12]) - { - wFNum >>= 1; - nOct++; - } - - for (nKey = 0; wFNum > k->wFNumber[nKey + 1]; nKey++) - { - } - - nKey += nOct * 12; - return (int)(MIN(nKey, 127)); -} - -static void opl3keyoff(KEYDISP *keydisp, OPL3CTL *k, UINT nChannel) -{ - delaysetevent(keydisp, (REG8)(k->cChannelNum + nChannel), k->ch[nChannel].cLastNote); -} - -static void opl3keyon(KEYDISP *keydisp, OPL3CTL *k, UINT nChannelNum) -{ - const UINT8 *pReg; - - opl3keyoff(keydisp, k, nChannelNum); - - pReg = k->pcRegister + ((nChannelNum / 9) << 8) + 0xa0 + (nChannelNum % 9); - k->ch[nChannelNum].nFNumber = ((pReg[0x10] & 0x1f) << 8) + pReg[0x00]; - k->ch[nChannelNum].cLastNote = GetOpl3Note(k, k->ch[nChannelNum].nFNumber); - delaysetevent(keydisp, (REG8)(k->cChannelNum + nChannelNum), (REG8)(k->ch[nChannelNum].cLastNote | 0x80)); -} - -static void opl3keyreset(KEYDISP *keydisp) -{ - UINT i; - - for (i = 0; i < NELEMENTS(keydisp->opl3ctl); i++) - { - memset(keydisp->opl3ctl[i].ch, 0, sizeof(keydisp->opl3ctl[i].ch)); - } -} - -void keydisp_opl3keyon(const UINT8 *pcRegister, REG8 nChannelNum, REG8 cData) -{ - UINT i; - OPL3CTL *k; - - if (s_keydisp.mode != KEYDISP_MODEFM) - { - return; - } - - for (i = 0; i < s_keydisp.opl3max; i++) - { - k = &s_keydisp.opl3ctl[i]; - if (k->pcRegister == pcRegister) - { - cData &= 0x20; - if (k->ch[nChannelNum].cKeyOn != cData) - { - if (cData) - { - opl3keyon(&s_keydisp, k, nChannelNum); - } - else - { - opl3keyoff(&s_keydisp, k, nChannelNum); - } - k->ch[nChannelNum].cKeyOn = cData; - } - break; - } - } -} - -static void opl3keysync(KEYDISP *keydisp) -{ - UINT i; - OPL3CTL *k; - const UINT8 *pReg; - UINT j; - UINT8 n; - UINT16 fnum; - - for (i = 0; i < keydisp->opl3max; i++) - { - k = &keydisp->opl3ctl[i]; - for (j = 0; j < k->cFMChannels; j++) - { - if (k->ch[j].cKeyOn) - { - pReg = k->pcRegister + ((j / 9) << 8) + 0xa0 + (j % 9); - fnum = ((pReg[0x10] & 0x1f) << 8) + pReg[0x00]; - if (k->ch[j].nFNumber != fnum) - { - k->ch[j].nFNumber = fnum; - n = GetOpl3Note(k, fnum); - if (k->ch[j].cLastNote != n) - { - opl3keyoff(keydisp, k, j); - } - k->ch[j].cLastNote = n; - delaysetevent(keydisp, (REG8)(k->cChannelNum + j), (REG8)(n | 0x80)); - } - } - } - } -} - - - -/* ---- BOARD change... */ - -/** - * Reset - */ -void keydisp_reset(void) -{ - s_keydisp.keymax = 0; - s_keydisp.opnamax = 0; - s_keydisp.psgmax = 0; - s_keydisp.opl3max = 0; - - ClearDelayList(&s_keydisp); - memset(&s_keydisp.opnactl, 0, sizeof(s_keydisp.opnactl)); - memset(&s_keydisp.psgctl, 0, sizeof(s_keydisp.psgctl)); - memset(&s_keydisp.opl3ctl, 0, sizeof(s_keydisp.opl3ctl)); - - if (s_keydisp.mode == KEYDISP_MODEFM) - { - s_keydisp.dispflag |= KEYDISP_FLAGSIZING; - } -} - -/** - * bind - */ -void keydisp_bindopna(const UINT8 *pcRegister, UINT nChannels, UINT nBaseClock) -{ - OPNACTL *k; - UINT i; - - if (((s_keydisp.keymax + nChannels) <= KEYDISP_CHMAX) && (s_keydisp.opnamax < NELEMENTS(s_keydisp.opnactl))) - { - k = &s_keydisp.opnactl[s_keydisp.opnamax]; - k->cChannelNum = s_keydisp.keymax; - k->pcRegister = pcRegister; - k->cFMChannels = nChannels; - for (i = 0; i < NELEMENTS(k->wFNumber); i++) - { - k->wFNumber[i] = (UINT16)(440.0 * pow(2.0, (((double)i - 9.5) / 12.0) + 17.0) * 72.0 / (double)nBaseClock); - } - s_keydisp.opnamax++; - s_keydisp.keymax += nChannels; - } - - if (s_keydisp.mode == KEYDISP_MODEFM) - { - s_keydisp.dispflag |= KEYDISP_FLAGSIZING; - } -} - -/** - * bind - */ -void keydisp_bindpsg(const UINT8 *pcRegister, UINT nBaseClock) -{ - PSGCTL *k; - UINT i; - - if (((s_keydisp.keymax + 3) <= KEYDISP_CHMAX) && (s_keydisp.psgmax < NELEMENTS(s_keydisp.psgctl))) - { - k = &s_keydisp.psgctl[s_keydisp.psgmax]; - k->cChannelNum = s_keydisp.keymax; - k->pcRegister = pcRegister; - for (i = 0; i < NELEMENTS(k->wTone); i++) - { - k->wTone[i] = (UINT16)((double)nBaseClock / 32.0 / (440.0 * pow(2.0, ((double)i - 9.5) / 12.0))); - } - s_keydisp.psgmax++; - s_keydisp.keymax += 3; - } - - if (s_keydisp.mode == KEYDISP_MODEFM) - { - s_keydisp.dispflag |= KEYDISP_FLAGSIZING; - } -} - -/** - * bind - */ -void keydisp_bindopl3(const UINT8 *pcRegister, UINT nChannels, UINT nBaseClock) -{ - OPL3CTL *k; - UINT i; - - if (((s_keydisp.keymax + nChannels) <= KEYDISP_CHMAX) && (s_keydisp.opl3max < NELEMENTS(s_keydisp.opl3ctl))) - { - k = &s_keydisp.opl3ctl[s_keydisp.opl3max]; - k->cChannelNum = s_keydisp.keymax; - k->pcRegister = pcRegister; - k->cFMChannels = nChannels; - for (i = 0; i < NELEMENTS(k->wFNumber); i++) - { - k->wFNumber[i] = (UINT16)(440.0 * pow(2.0, (((double)i - 9.5) / 12.0) + 16.0) * 72.0 / (double)nBaseClock); - } - s_keydisp.opl3max++; - s_keydisp.keymax += nChannels; - } - - if (s_keydisp.mode == KEYDISP_MODEFM) - { - s_keydisp.dispflag |= KEYDISP_FLAGSIZING; - } -} - - - -/* ---- MIDI */ - -void keydisp_midi(const UINT8 *cmd) -{ - if (s_keydisp.mode != KEYDISP_MODEMIDI) - { - return; - } - switch (cmd[0] & 0xf0) - { - case 0x80: - keyoff(&s_keydisp, cmd[0] & 0x0f, cmd[1]); - break; - - case 0x90: - if (cmd[2] & 0x7f) - { - keyon(&s_keydisp, cmd[0] & 0x0f, cmd[1]); - } - else - { - keyoff(&s_keydisp, cmd[0] & 0x0f, cmd[1]); - } - break; - - case 0xb0: - if ((cmd[1] == 0x78) || (cmd[1] == 0x79) || (cmd[1] == 0x7b)) - { - chkeyoff(&s_keydisp, cmd[0] & 0x0f); - } - break; - } - if (cmd[0] == 0xfe) { - keyalloff(&s_keydisp); - } -} - - -/* ---- draw */ - -static UINT getdispkeys(const KEYDISP *keydisp) -{ - UINT keys; - - switch (keydisp->mode) - { - case KEYDISP_MODEFM: - keys = keydisp->keymax; - break; - - case KEYDISP_MODEMIDI: - keys = 16; - break; - - default: - keys = 0; - break; - } - return MIN(keys, KEYDISP_CHMAX); -} - -static void clearrect(CMNVRAM *vram, int x, int y, int cx, int cy) -{ - CMNPAL col; - - switch (vram->bpp) - { -#if defined(SUPPORT_8BPP) - case 8: - col.pal8 = s_constData.pal8[KEYDISP_PALBG]; - break; -#endif -#if defined(SUPPORT_16BPP) - case 16: - col.pal16 = s_constData.pal16[1][0]; - break; -#endif -#if defined(SUPPORT_24BPP) || defined(SUPPORT_32BPP) - case 24: - case 32: - col.pal32 = s_constData.pal32[1][0]; - break; -#endif - default: - return; - } - cmndraw_fill(vram, x, y, cx, cy, col); -} - -static void drawkeybg(CMNVRAM *vram) -{ - CMNPAL bg; - CMNPAL fg; - int i; - - switch (vram->bpp) - { -#if defined(SUPPORT_8BPP) - case 8: - bg.pal8 = s_constData.pal8[KEYDISP_PALBG]; - fg.pal8 = s_constData.pal8[KEYDISP_PALFG]; - break; -#endif -#if defined(SUPPORT_16BPP) - case 16: - bg.pal16 = s_constData.pal16[1][0]; - fg.pal16 = s_constData.pal16[0][0]; - break; -#endif -#if defined(SUPPORT_24BPP) || defined(SUPPORT_32BPP) - case 24: - case 32: - bg.pal32 = s_constData.pal32[1][0]; - fg.pal32 = s_constData.pal32[0][0]; - break; -#endif - default: - return; - } - for (i = 0; i < 10; i++) - { - cmndraw_setpat(vram, keybrd1, i * KEYDISP_KEYCX, 0, bg, fg); - } - cmndraw_setpat(vram, keybrd2, 10 * KEYDISP_KEYCX, 0, bg, fg); -} - -static BOOL draw1key(CMNVRAM *vram, KDCHANNEL *kdch, UINT n) -{ - const NOTEPATTERN *pPattern; - UINT pal; - CMNPAL fg; - - pPattern = s_constData.pattern + (kdch->k[n] & 0x7f); - pal = kdch->r[n]; - switch (vram->bpp) - { -#if defined(SUPPORT_8BPP) - case 8: - if (pal != KEYDISP_LEVEL_MAX) - { - fg.pal8 = s_constData.pal8[(pPattern->nType) ? KEYDISP_PALBG : KEYDISP_PALFG]; - cmndraw_setfg(vram, pPattern->lpImage, pPattern->nPosX, 0, fg); - kdch->r[n] = 0; - return TRUE; - } - fg.pal8 = s_constData.pal8[KEYDISP_PALHIT]; - break; -#endif -#if defined(SUPPORT_16BPP) - case 16: - fg.pal16 = s_constData.pal16[pPattern->nType][pal]; - break; -#endif -#if defined(SUPPORT_24BPP) || defined(SUPPORT_32BPP) - case 24: - case 32: - fg.pal32 = s_constData.pal32[pPattern->nType][pal]; - break; -#endif - default: - return FALSE; - } - cmndraw_setfg(vram, pPattern->lpImage, pPattern->nPosX, 0, fg); - return FALSE; -} - -static BOOL draw1ch(CMNVRAM *vram, UINT8 framepast, KDCHANNEL *kdch) -{ - BOOL draw; - UINT i; - BOOL coll; - UINT8 nextf; - UINT j; - - draw = FALSE; - if (kdch->flag & 2) - { - drawkeybg(vram); - draw = TRUE; - } - if (kdch->flag) - { - coll = FALSE; - nextf = 0; - for (i = 0; i < kdch->remain; i++) - { - if ((kdch->r[i]) || (kdch->flag & 2)) - { - if (kdch->r[i] < KEYDISP_LEVEL_MAX) - { - if (kdch->r[i] > framepast) - { - kdch->r[i] -= framepast; - nextf = 1; - } - else - { - kdch->r[i] = 0; - coll = TRUE; - } - } - coll |= draw1key(vram, kdch, i); - draw = TRUE; - } - } - if (coll) - { - for (i = 0; i < kdch->remain; i++) - { - if (!kdch->r[i]) - { - break; - } - } - for (j = i; i < kdch->remain; i++) - { - if (kdch->r[i]) - { - kdch->k[j] = kdch->k[i]; - kdch->r[j] = kdch->r[i]; - j++; - } - } - kdch->remain = j; - } - kdch->flag = nextf; - } - return draw; -} - - -/* ---- */ - -void keydisp_initialize(void) -{ - int r; - UINT16 x; - int i; - - r = 0; - x = 0; - do - { - for (i = 0; i < 12 && r < 128; i++, r++) - { - s_constData.pattern[r].nPosX = s_notepattern[i].nPosX + x; - s_constData.pattern[r].nType = s_notepattern[i].nType; - s_constData.pattern[r].lpImage = s_notepattern[i].lpImage; - } - x += 28; - } while (r < 128); - keyallclear(&s_keydisp); -} - -void keydisp_setpal(CMNPALFN *palfn) -{ - UINT i; - RGB32 pal32[KEYDISP_PALS]; - - if (palfn == NULL) - { - return; - } - if (palfn->get8) - { - for (i = 0; i < KEYDISP_PALS; i++) - { - s_constData.pal8[i] = (*palfn->get8)(palfn, i); - } - } - if (palfn->get32) - { - for (i = 0; i < KEYDISP_PALS; i++) - { - pal32[i].d = (*palfn->get32)(palfn, i); - cmndraw_makegrad(s_constData.pal32[0], KEYDISP_LEVEL, pal32[KEYDISP_PALFG], pal32[KEYDISP_PALHIT]); - cmndraw_makegrad(s_constData.pal32[1], KEYDISP_LEVEL, pal32[KEYDISP_PALBG], pal32[KEYDISP_PALHIT]); - } - if (palfn->cnv16) - { - for (i = 0; i < KEYDISP_LEVEL; i++) - { - s_constData.pal16[0][i] = (*palfn->cnv16)(palfn, s_constData.pal32[0][i]); - s_constData.pal16[1][i] = (*palfn->cnv16)(palfn, s_constData.pal32[1][i]); - } - } - } - s_keydisp.dispflag |= KEYDISP_FLAGREDRAW; -} - -void keydisp_setmode(UINT8 mode) -{ - if (s_keydisp.mode != mode) - { - s_keydisp.mode = mode; - s_keydisp.dispflag |= KEYDISP_FLAGREDRAW | KEYDISP_FLAGSIZING; - keyallclear(&s_keydisp); - if (mode == KEYDISP_MODEFM) - { - ClearDelayList(&s_keydisp); - opnakeyreset(&s_keydisp); - psgkeyreset(&s_keydisp); - opl3keyreset(&s_keydisp); - } - } - else - { - keyalloff(&s_keydisp); - } -} - -void keydisp_setdelay(UINT8 frames) -{ - s_keydisp.delay.warmbase = frames; - ClearDelayList(&s_keydisp); -} - -UINT8 keydisp_process(UINT8 framepast) -{ - UINT keys; - UINT i; - - if (framepast) - { - if (s_keydisp.mode == KEYDISP_MODEFM) - { - opnakeysync(&s_keydisp); - psgkeysync(&s_keydisp); - opl3keysync(&s_keydisp); - delayexecevent(&s_keydisp, framepast); - } - s_keydisp.framepast += framepast; - } - - keys = getdispkeys(&s_keydisp); - for (i = 0; i < keys; i++) - { - if (s_keydisp.ch[i].flag) - { - s_keydisp.dispflag |= KEYDISP_FLAGDRAW; - break; - } - } - return s_keydisp.dispflag; -} - -void keydisp_getsize(int *width, int *height) -{ - if (width) - { - *width = KEYDISP_WIDTH; - } - if (height) - { - *height = (getdispkeys(&s_keydisp) * KEYDISP_KEYCY) + 1; - } - s_keydisp.dispflag &= ~KEYDISP_FLAGSIZING; -} - -BOOL keydisp_paint(CMNVRAM *vram, BOOL redraw) -{ - BOOL draw; - UINT keys; - UINT i; - KDCHANNEL *p; - - draw = FALSE; - if ((vram == NULL) || (vram->width < KEYDISP_WIDTH) || (vram->height <= 0)) - { - goto kdpnt_exit; - } - if (s_keydisp.dispflag & KEYDISP_FLAGREDRAW) - { - redraw = TRUE; - } - if (redraw) - { - keyallreload(&s_keydisp); - clearrect(vram, 0, 0, KEYDISP_WIDTH, 1); - clearrect(vram, 0, 0, 1, vram->height); - draw = TRUE; - } - vram->ptr += vram->xalign + vram->yalign; - keys = (vram->height - 1) / KEYDISP_KEYCY; - keys = MIN(keys, getdispkeys(&s_keydisp)); - for (i = 0, p = s_keydisp.ch; i < keys; i++, p++) - { - draw |= draw1ch(vram, s_keydisp.framepast, p); - vram->ptr += KEYDISP_KEYCY * vram->yalign; - } - s_keydisp.dispflag &= ~(KEYDISP_FLAGDRAW | KEYDISP_FLAGREDRAW); - s_keydisp.framepast = 0; - -kdpnt_exit: - return draw; -} -/** - * Set Resize Flag - */ -void keydisp_setresizeflag(void) -{ - s_keydisp.dispflag |= KEYDISP_FLAGSIZING; -} -#endif +/** + * @file keydisp.c + * @brief Implementation of the key display + */ + +#include + +#if defined(SUPPORT_KEYDISP) + +#include +#include +#include +#include +#include "sound/psggen.h" + +typedef struct +{ + UINT8 k[KEYDISP_NOTEMAX]; + UINT8 r[KEYDISP_NOTEMAX]; + UINT remain; + UINT8 flag; + UINT8 padding[3]; +} KDCHANNEL; + +typedef struct +{ + UINT8 ch; + UINT8 key; +} KDDELAYE; + +typedef struct +{ + UINT pos; + UINT rem; + UINT8 warm; + UINT8 warmbase; +} KDDELAY; + +/** + * @brief Channel + */ +struct tagFmChannel +{ + UINT16 nFNumber; /*!< F-Number */ + UINT8 cLastNote; /*!< The last note */ + UINT8 cKeyOn; /*!< KeyOn */ +}; +typedef struct tagFmChannel FMCHANNEL; + +/** + * @brief OPNA + */ +struct tagOpnaControl +{ + const UINT8 *pcRegister; /*!< The pointer of the register */ + UINT8 cChannelNum; /*!< The number of the channel */ + UINT8 cFMChannels; /*!< The channels of FM */ + UINT16 wFNumber[13]; /*!< The list of F-number */ + FMCHANNEL ch[6]; /*!< The information of FM */ +}; +typedef struct tagOpnaControl OPNACTL; + +/** + * @brief PSG + */ +struct tagPsgControl +{ + const UINT8 *pcRegister; /*!< The pointer of the register */ + REG16 nLastTone[4]; + UINT8 cLastNote[4]; + UINT16 wTone[13]; /*!< The list of Tone */ + UINT8 cChannelNum; /*!< The number of the channel */ + UINT8 cPsgOn; + UINT8 cLastMixer; +}; +typedef struct tagPsgControl PSGCTL; + +/** + * @brief OPL3 + */ +struct tagOpl3Control +{ + const UINT8 *pcRegister; /*!< The pointer of the register */ + UINT8 cChannelNum; /*!< The number of the channel */ + UINT8 cFMChannels; /*!< The channels of FM */ + UINT16 wFNumber[13]; /*!< The list of F-number */ + FMCHANNEL ch[18]; /*!< The information of FM */ +}; +typedef struct tagOpl3Control OPL3CTL; + +typedef struct +{ + UINT8 mode; + UINT8 dispflag; + UINT8 framepast; + UINT8 keymax; + UINT8 opnamax; + UINT8 psgmax; + UINT8 opl3max; + KDDELAY delay; + KDCHANNEL ch[KEYDISP_CHMAX]; + OPNACTL opnactl[5]; /*!< OPNA */ + PSGCTL psgctl[3]; /*!< PSG */ + OPL3CTL opl3ctl[8]; /*!< OPL3 */ + KDDELAYE delaye[KEYDISP_DELAYEVENTS]; +} KEYDISP; + +static KEYDISP s_keydisp; + +/** + * @brief The table of the notes + */ +struct TagNotePattern +{ + UINT16 nPosX; /*!< X-Coorinate */ + UINT8 nType; /*!< type */ + const UINT8 *lpImage; /*!< image */ +}; +typedef struct TagNotePattern NOTEPATTERN; /*!< The define of the note's pattern */ + +/** + * @brief const data + */ +struct KeyDispConstData +{ + UINT8 pal8[KEYDISP_PALS]; /*!< 8npp palettes */ + UINT16 pal16[2][KEYDISP_LEVEL]; /*!< 16bpp palettes */ + RGB32 pal32[2][KEYDISP_LEVEL]; /*!< 32bpp palettes */ + NOTEPATTERN pattern[128]; /*!< pattern */ +}; + +/*! const data */ +static struct KeyDispConstData s_constData; + +#include "keydisp.res" + + +/* ---- event */ + +static void keyon(KEYDISP *keydisp, UINT ch, UINT8 note) +{ + UINT i; + KDCHANNEL *kdch; + + note &= 0x7f; + kdch = keydisp->ch + ch; + for (i = 0; i < kdch->remain; i++) + { + if (kdch->k[i] == note) + { + /* ヒットした */ + for (; i < (kdch->remain - 1); i++) + { + kdch->k[i] = kdch->k[i + 1]; + kdch->r[i] = kdch->r[i + 1]; + } + kdch->k[i] = note; + kdch->r[i] = KEYDISP_LEVEL_MAX; + kdch->flag |= 1; + return; + } + } + if (i < KEYDISP_NOTEMAX) + { + kdch->k[i] = note; + kdch->r[i] = KEYDISP_LEVEL_MAX; + kdch->flag |= 1; + kdch->remain++; + } +} + +static void keyoff(KEYDISP *keydisp, UINT ch, UINT8 note) +{ + UINT i; + KDCHANNEL *kdch; + + note &= 0x7f; + kdch = keydisp->ch + ch; + for (i = 0; i < kdch->remain; i++) + { + if (kdch->k[i] == note) + { + /* ヒットした */ + kdch->r[i] = (KEYDISP_LEVEL_MAX - 1); + kdch->flag |= 1; + break; + } + } +} + +static void chkeyoff(KEYDISP *keydisp, UINT ch) +{ + UINT i; + KDCHANNEL *kdch; + + kdch = keydisp->ch + ch; + for (i = 0; i < kdch->remain; i++) + { + if (kdch->r[i] >= KEYDISP_LEVEL_MAX) + { + kdch->r[i] = (KEYDISP_LEVEL_MAX - 1); + kdch->flag |= 1; + } + } +} + +static void keyalloff(KEYDISP *keydisp) +{ + UINT i; + + for (i = 0; i < KEYDISP_CHMAX; i++) + { + chkeyoff(keydisp, i); + } +} + +static void keyallreload(KEYDISP *keydisp) +{ + UINT i; + + for (i = 0; i < KEYDISP_CHMAX; i++) + { + keydisp->ch[i].flag = 2; + } +} + +static void keyallclear(KEYDISP *keydisp) +{ + memset(keydisp->ch, 0, sizeof(keydisp->ch)); + keyallreload(keydisp); +} + + +/* ---- delay event */ + +static void ClearDelayList(KEYDISP *keydisp) +{ + keydisp->delay.warm = keydisp->delay.warmbase; + keydisp->delay.pos = 0; + keydisp->delay.rem = 0; + memset(keydisp->delaye, 0, sizeof(keydisp->delaye)); + keyalloff(keydisp); +} + +static void delayexecevent(KEYDISP *keydisp, UINT8 framepast) +{ + KDDELAYE *ebase; + UINT pos; + UINT rem; + KDDELAYE *ev; + + ebase = keydisp->delaye; + pos = keydisp->delay.pos; + rem = keydisp->delay.rem; + while ((keydisp->delay.warm) && (framepast)) + { + keydisp->delay.warm--; + framepast--; + if (rem >= KEYDISP_DELAYEVENTS) + { + ev = ebase + pos; + rem--; + if (ev->ch == 0xff) + { + keydisp->delay.warm++; + } + else if (ev->key & 0x80) + { + keyon(keydisp, ev->ch, ev->key); + rem--; + } + else + { + keyoff(keydisp, ev->ch, ev->key); + } + pos = (pos + 1) & (KEYDISP_DELAYEVENTS - 1); + } + ebase[(pos + rem) & (KEYDISP_DELAYEVENTS - 1)].ch = 0xff; + rem++; + } + while (framepast) + { + framepast--; + while (rem) + { + rem--; + ev = ebase + pos; + if (ev->ch == 0xff) + { + pos = (pos + 1) & (KEYDISP_DELAYEVENTS - 1); + break; + } + if (ev->key & 0x80) + { + keyon(keydisp, ev->ch, ev->key); + } + else + { + keyoff(keydisp, ev->ch, ev->key); + } + pos = (pos + 1) & (KEYDISP_DELAYEVENTS - 1); + } + ebase[(pos + rem) & (KEYDISP_DELAYEVENTS - 1)].ch = 0xff; + rem++; + } + keydisp->delay.pos = pos; + keydisp->delay.rem = rem; +} + +static void delaysetevent(KEYDISP *keydisp, REG8 ch, REG8 key) +{ + KDDELAYE *e; + + e = keydisp->delaye; + if (keydisp->delay.rem < KEYDISP_DELAYEVENTS) + { + e += (keydisp->delay.pos + keydisp->delay.rem) & (KEYDISP_DELAYEVENTS - 1); + keydisp->delay.rem++; + e->ch = ch; + e->key = key; + } + else + { + e += keydisp->delay.pos; + keydisp->delay.pos = (keydisp->delay.pos + 1) & (KEYDISP_DELAYEVENTS - 1); + if (e->ch == 0xff) + { + keydisp->delay.warm++; + } + else if (e->key & 0x80) + { + keyon(keydisp, e->ch, e->key); + } + else + { + keyoff(keydisp, e->ch, e->key); + } + e->ch = ch; + e->key = key; + } +} + + +/* ---- OPNA */ + +static UINT8 GetOpnaNote(const OPNACTL *k, UINT16 wFNum) +{ + UINT nOct; + UINT nKey; + + nOct = ((wFNum >> 11) & 7) + 2; + wFNum &= 0x7ff; + + while (wFNum < k->wFNumber[0]) + { + if (!nOct) + { + return 0; + } + nOct--; + wFNum <<= 1; + } + while (wFNum > k->wFNumber[12]) + { + wFNum >>= 1; + nOct++; + } + + for (nKey = 0; wFNum > k->wFNumber[nKey + 1]; nKey++) + { + } + + nKey += nOct * 12; + return (int)(MIN(nKey, 127)); +} + +static void opnakeyoff(KEYDISP *keydisp, OPNACTL *k, UINT nChannel) +{ + delaysetevent(keydisp, (REG8)(k->cChannelNum + nChannel), k->ch[nChannel].cLastNote); +} + +static void opnakeyon(KEYDISP *keydisp, OPNACTL *k, UINT nChannelNum) +{ + const UINT8 *pReg; + + opnakeyoff(keydisp, k, nChannelNum); + + pReg = k->pcRegister + ((nChannelNum / 3) << 8) + 0xa0 + (nChannelNum % 3); + k->ch[nChannelNum].nFNumber = ((pReg[4] & 0x3f) << 8) + pReg[0]; + k->ch[nChannelNum].cLastNote = GetOpnaNote(k, k->ch[nChannelNum].nFNumber); + delaysetevent(keydisp, (REG8)(k->cChannelNum + nChannelNum), (REG8)(k->ch[nChannelNum].cLastNote | 0x80)); +} + +static void opnakeyreset(KEYDISP *keydisp) +{ + UINT i; + + for (i = 0; i < NELEMENTS(keydisp->opnactl); i++) + { + memset(keydisp->opnactl[i].ch, 0, sizeof(keydisp->opnactl[i].ch)); + } +} + +void keydisp_opnakeyon(const UINT8 *pcRegister, REG8 cData) +{ + UINT i; + OPNACTL *k; + UINT nChannelNum; + + if (s_keydisp.mode != KEYDISP_MODEFM) + { + return; + } + + if ((cData & 3) == 3) + { + return; + } + + for (i = 0; i < s_keydisp.opnamax; i++) + { + k = &s_keydisp.opnactl[i]; + if (k->pcRegister == pcRegister) + { + nChannelNum = cData & 7; + cData &= 0xf0; + if (nChannelNum >= 4) + { + nChannelNum--; + } + if (nChannelNum >= NELEMENTS(k->ch)) { + continue; + } + if ((nChannelNum < k->cFMChannels) && (k->ch[nChannelNum].cKeyOn != cData)) + { + if (cData) + { + opnakeyon(&s_keydisp, k, nChannelNum); + } + else + { + opnakeyoff(&s_keydisp, k, nChannelNum); + } + k->ch[nChannelNum].cKeyOn = cData; + } + break; + } + } +} + +static void opnakeysync(KEYDISP *keydisp) +{ + UINT i; + OPNACTL *k; + const UINT8 *pReg; + UINT j; + UINT8 n; + UINT16 fnum; + + for (i = 0; i < keydisp->opnamax; i++) + { + k = &keydisp->opnactl[i]; + for (j = 0; j < k->cFMChannels; j++) + { + if (k->ch[j].cKeyOn) + { + pReg = k->pcRegister + ((j / 3) << 8) + 0xa0 + (j % 3); + fnum = ((pReg[4] & 0x3f) << 8) + pReg[0]; + if (k->ch[j].nFNumber != fnum) + { + k->ch[j].nFNumber = fnum; + n = GetOpnaNote(k, fnum); + if (k->ch[j].cLastNote != n) + { + opnakeyoff(keydisp, k, j); + } + k->ch[j].cLastNote = n; + delaysetevent(keydisp, (REG8)(k->cChannelNum + j), (REG8)(n | 0x80)); + } + } + } + } +} + + +/* ---- PSG */ + +/** + * Get pointer of controller + * @param[in] pcRegister The instance of PSG + * @return The pointer of controller + */ +static PSGCTL *GetController(KEYDISP *keydisp, const UINT8 *pcRegister) +{ + UINT i; + PSGCTL *k; + + if (keydisp->mode != KEYDISP_MODEFM) + { + return NULL; + } + + for (i = 0; i < keydisp->psgmax; i++) + { + k = &keydisp->psgctl[i]; + if (k->pcRegister == pcRegister) + { + return k; + } + } + return NULL; +} + +static UINT8 GetPSGNote(const PSGCTL *k, UINT16 nTone) +{ + UINT nOct; + UINT nKey; + + nOct = 5; + nTone &= 0xfff; + + while (nTone > k->wTone[0]) + { + if (!nOct) + { + return 0; + } + nTone >>= 1; + nOct--; + } + + if (!nTone) + { + return 127; + } + + while (nTone < k->wTone[12]) + { + nTone <<= 1; + nOct++; + } + for (nKey = 0; nTone < k->wTone[nKey + 1]; nKey++) + { + } + nKey += nOct * 12; + return (int)(MIN(nKey, 127)); +} + +static void psgmix(KEYDISP *keydisp, PSGCTL *k) +{ + const PSGREG *pReg; + + pReg = (const PSGREG *)k->pcRegister; + if ((k->cLastMixer ^ pReg->mixer) & 7) + { + UINT8 i, bit, pos; + k->cLastMixer = pReg->mixer; + pos = k->cChannelNum; + for (i = 0, bit = 1; i < 3; i++, pos++, bit <<= 1) + { + if (k->cPsgOn & bit) + { + k->cPsgOn ^= bit; + delaysetevent(keydisp, pos, k->cLastNote[i]); + } + else if ((!(k->cLastMixer & bit)) && (pReg->vol[i] & 0x1f)) + { + k->cPsgOn |= bit; + k->nLastTone[i] = LOADINTELWORD(pReg->tune[i]) & 0xfff; + k->cLastNote[i] = GetPSGNote(k, k->nLastTone[i]); + delaysetevent(keydisp, pos, (UINT8)(k->cLastNote[i] | 0x80)); + } + } + } +} + +static void psgvol(KEYDISP *keydisp, PSGCTL *k, UINT ch) +{ + const PSGREG *pReg; + UINT8 bit; + UINT8 pos; + UINT16 tune; + + pReg = (const PSGREG *)k->pcRegister; + bit = (1 << ch); + pos = k->cChannelNum + ch; + if (pReg->vol[ch] & 0x1f) + { + if (!((k->cLastMixer | k->cPsgOn) & bit)) + { + k->cPsgOn |= bit; + tune = LOADINTELWORD(pReg->tune[ch]); + tune &= 0xfff; + k->nLastTone[ch] = tune; + k->cLastNote[ch] = GetPSGNote(k, tune); + delaysetevent(keydisp, pos, (UINT8)(k->cLastNote[ch] | 0x80)); + } + } + else if (k->cPsgOn & bit) + { + k->cPsgOn ^= bit; + delaysetevent(keydisp, pos, k->cLastNote[ch]); + } +} + +static void psgkeyreset(KEYDISP *keydisp) +{ + UINT i; + + for (i = 0; i < NELEMENTS(keydisp->psgctl); i++) + { + keydisp->psgctl[i].cPsgOn = 0; + } +} + +/** + * Update keyboard + * @param[in] pcRegister The instance + * @param[in] nAddress The written register + */ +void keydisp_psg(const UINT8 *pcRegister, UINT nAddress) +{ + PSGCTL *k = GetController(&s_keydisp, pcRegister); + if (k != NULL) + { + switch (nAddress) + { + case 7: + psgmix(&s_keydisp, k); + break; + + case 8: + case 9: + case 10: + psgvol(&s_keydisp, k, nAddress - 8); + break; + } + } +} + +static void psgkeysync(KEYDISP *keydisp) +{ + UINT8 ch; + const PSGREG *pReg; + PSGCTL *k; + UINT8 bit; + UINT8 i; + UINT8 pos; + UINT16 tune; + UINT8 n; + + for (ch = 0, k = keydisp->psgctl; ch < keydisp->psgmax; ch++, k++) + { + pReg = (const PSGREG *)k->pcRegister; + pos = k->cChannelNum; + for (i = 0, bit = 1; i < 3; i++, pos++, bit <<= 1) + { + if (k->cPsgOn & bit) + { + tune = LOADINTELWORD(pReg->tune[i]); + tune &= 0xfff; + if (k->nLastTone[i] != tune) + { + k->nLastTone[i] = tune; + n = GetPSGNote(k, tune); + if (k->cLastNote[i] != n) + { + delaysetevent(keydisp, pos, k->cLastNote[i]); + k->cLastNote[i] = n; + delaysetevent(keydisp, pos, (UINT8)(n | 0x80)); + } + } + } + } + } +} + + + +/* ---- OPL3 */ + +static UINT8 GetOpl3Note(const OPL3CTL *k, UINT16 wFNum) +{ + UINT nOct; + UINT nKey; + + nOct = ((wFNum >> 10) & 7) + 2; + wFNum &= 0x3ff; + + while (wFNum < k->wFNumber[0]) + { + if (!nOct) + { + return 0; + } + nOct--; + wFNum <<= 1; + } + while (wFNum > k->wFNumber[12]) + { + wFNum >>= 1; + nOct++; + } + + for (nKey = 0; wFNum > k->wFNumber[nKey + 1]; nKey++) + { + } + + nKey += nOct * 12; + return (int)(MIN(nKey, 127)); +} + +static void opl3keyoff(KEYDISP *keydisp, OPL3CTL *k, UINT nChannel) +{ + delaysetevent(keydisp, (REG8)(k->cChannelNum + nChannel), k->ch[nChannel].cLastNote); +} + +static void opl3keyon(KEYDISP *keydisp, OPL3CTL *k, UINT nChannelNum) +{ + const UINT8 *pReg; + + opl3keyoff(keydisp, k, nChannelNum); + + pReg = k->pcRegister + ((nChannelNum / 9) << 8) + 0xa0 + (nChannelNum % 9); + k->ch[nChannelNum].nFNumber = ((pReg[0x10] & 0x1f) << 8) + pReg[0x00]; + k->ch[nChannelNum].cLastNote = GetOpl3Note(k, k->ch[nChannelNum].nFNumber); + delaysetevent(keydisp, (REG8)(k->cChannelNum + nChannelNum), (REG8)(k->ch[nChannelNum].cLastNote | 0x80)); +} + +static void opl3keyreset(KEYDISP *keydisp) +{ + UINT i; + + for (i = 0; i < NELEMENTS(keydisp->opl3ctl); i++) + { + memset(keydisp->opl3ctl[i].ch, 0, sizeof(keydisp->opl3ctl[i].ch)); + } +} + +void keydisp_opl3keyon(const UINT8 *pcRegister, REG8 nChannelNum, REG8 cData) +{ + UINT i; + OPL3CTL *k; + + if (s_keydisp.mode != KEYDISP_MODEFM) + { + return; + } + + for (i = 0; i < s_keydisp.opl3max; i++) + { + k = &s_keydisp.opl3ctl[i]; + if (k->pcRegister == pcRegister) + { + cData &= 0x20; + if (k->ch[nChannelNum].cKeyOn != cData) + { + if (cData) + { + opl3keyon(&s_keydisp, k, nChannelNum); + } + else + { + opl3keyoff(&s_keydisp, k, nChannelNum); + } + k->ch[nChannelNum].cKeyOn = cData; + } + break; + } + } +} + +static void opl3keysync(KEYDISP *keydisp) +{ + UINT i; + OPL3CTL *k; + const UINT8 *pReg; + UINT j; + UINT8 n; + UINT16 fnum; + + for (i = 0; i < keydisp->opl3max; i++) + { + k = &keydisp->opl3ctl[i]; + for (j = 0; j < k->cFMChannels; j++) + { + if (k->ch[j].cKeyOn) + { + pReg = k->pcRegister + ((j / 9) << 8) + 0xa0 + (j % 9); + fnum = ((pReg[0x10] & 0x1f) << 8) + pReg[0x00]; + if (k->ch[j].nFNumber != fnum) + { + k->ch[j].nFNumber = fnum; + n = GetOpl3Note(k, fnum); + if (k->ch[j].cLastNote != n) + { + opl3keyoff(keydisp, k, j); + } + k->ch[j].cLastNote = n; + delaysetevent(keydisp, (REG8)(k->cChannelNum + j), (REG8)(n | 0x80)); + } + } + } + } +} + + + +/* ---- BOARD change... */ + +/** + * Reset + */ +void keydisp_reset(void) +{ + s_keydisp.keymax = 0; + s_keydisp.opnamax = 0; + s_keydisp.psgmax = 0; + s_keydisp.opl3max = 0; + + ClearDelayList(&s_keydisp); + memset(&s_keydisp.opnactl, 0, sizeof(s_keydisp.opnactl)); + memset(&s_keydisp.psgctl, 0, sizeof(s_keydisp.psgctl)); + memset(&s_keydisp.opl3ctl, 0, sizeof(s_keydisp.opl3ctl)); + + if (s_keydisp.mode == KEYDISP_MODEFM) + { + s_keydisp.dispflag |= KEYDISP_FLAGSIZING; + } +} + +/** + * bind + */ +void keydisp_bindopna(const UINT8 *pcRegister, UINT nChannels, UINT nBaseClock) +{ + OPNACTL *k; + UINT i; + + if (((s_keydisp.keymax + nChannels) <= KEYDISP_CHMAX) && (s_keydisp.opnamax < NELEMENTS(s_keydisp.opnactl))) + { + k = &s_keydisp.opnactl[s_keydisp.opnamax]; + k->cChannelNum = s_keydisp.keymax; + k->pcRegister = pcRegister; + k->cFMChannels = nChannels; + for (i = 0; i < NELEMENTS(k->wFNumber); i++) + { + k->wFNumber[i] = (UINT16)(440.0 * pow(2.0, (((double)i - 9.5) / 12.0) + 17.0) * 72.0 / (double)nBaseClock); + } + s_keydisp.opnamax++; + s_keydisp.keymax += nChannels; + } + + if (s_keydisp.mode == KEYDISP_MODEFM) + { + s_keydisp.dispflag |= KEYDISP_FLAGSIZING; + } +} + +/** + * bind + */ +void keydisp_bindpsg(const UINT8 *pcRegister, UINT nBaseClock) +{ + PSGCTL *k; + UINT i; + + if (((s_keydisp.keymax + 3) <= KEYDISP_CHMAX) && (s_keydisp.psgmax < NELEMENTS(s_keydisp.psgctl))) + { + k = &s_keydisp.psgctl[s_keydisp.psgmax]; + k->cChannelNum = s_keydisp.keymax; + k->pcRegister = pcRegister; + for (i = 0; i < NELEMENTS(k->wTone); i++) + { + k->wTone[i] = (UINT16)((double)nBaseClock / 32.0 / (440.0 * pow(2.0, ((double)i - 9.5) / 12.0))); + } + s_keydisp.psgmax++; + s_keydisp.keymax += 3; + } + + if (s_keydisp.mode == KEYDISP_MODEFM) + { + s_keydisp.dispflag |= KEYDISP_FLAGSIZING; + } +} + +/** + * bind + */ +void keydisp_bindopl3(const UINT8 *pcRegister, UINT nChannels, UINT nBaseClock) +{ + OPL3CTL *k; + UINT i; + + if (((s_keydisp.keymax + nChannels) <= KEYDISP_CHMAX) && (s_keydisp.opl3max < NELEMENTS(s_keydisp.opl3ctl))) + { + k = &s_keydisp.opl3ctl[s_keydisp.opl3max]; + k->cChannelNum = s_keydisp.keymax; + k->pcRegister = pcRegister; + k->cFMChannels = nChannels; + for (i = 0; i < NELEMENTS(k->wFNumber); i++) + { + k->wFNumber[i] = (UINT16)(440.0 * pow(2.0, (((double)i - 9.5) / 12.0) + 16.0) * 72.0 / (double)nBaseClock); + } + s_keydisp.opl3max++; + s_keydisp.keymax += nChannels; + } + + if (s_keydisp.mode == KEYDISP_MODEFM) + { + s_keydisp.dispflag |= KEYDISP_FLAGSIZING; + } +} + + + +/* ---- MIDI */ + +void keydisp_midi(const UINT8 *cmd) +{ + if (s_keydisp.mode != KEYDISP_MODEMIDI) + { + return; + } + switch (cmd[0] & 0xf0) + { + case 0x80: + keyoff(&s_keydisp, cmd[0] & 0x0f, cmd[1]); + break; + + case 0x90: + if (cmd[2] & 0x7f) + { + keyon(&s_keydisp, cmd[0] & 0x0f, cmd[1]); + } + else + { + keyoff(&s_keydisp, cmd[0] & 0x0f, cmd[1]); + } + break; + + case 0xb0: + if ((cmd[1] == 0x78) || (cmd[1] == 0x79) || (cmd[1] == 0x7b)) + { + chkeyoff(&s_keydisp, cmd[0] & 0x0f); + } + break; + } + if (cmd[0] == 0xfe) { + keyalloff(&s_keydisp); + } +} + + +/* ---- draw */ + +static UINT getdispkeys(const KEYDISP *keydisp) +{ + UINT keys; + + switch (keydisp->mode) + { + case KEYDISP_MODEFM: + keys = keydisp->keymax; + break; + + case KEYDISP_MODEMIDI: + keys = 16; + break; + + default: + keys = 0; + break; + } + return MIN(keys, KEYDISP_CHMAX); +} + +static void clearrect(CMNVRAM *vram, int x, int y, int cx, int cy) +{ + CMNPAL col; + + switch (vram->bpp) + { +#if defined(SUPPORT_8BPP) + case 8: + col.pal8 = s_constData.pal8[KEYDISP_PALBG]; + break; +#endif +#if defined(SUPPORT_16BPP) + case 16: + col.pal16 = s_constData.pal16[1][0]; + break; +#endif +#if defined(SUPPORT_24BPP) || defined(SUPPORT_32BPP) + case 24: + case 32: + col.pal32 = s_constData.pal32[1][0]; + break; +#endif + default: + return; + } + cmndraw_fill(vram, x, y, cx, cy, col); +} + +static void drawkeybg(CMNVRAM *vram) +{ + CMNPAL bg; + CMNPAL fg; + int i; + + switch (vram->bpp) + { +#if defined(SUPPORT_8BPP) + case 8: + bg.pal8 = s_constData.pal8[KEYDISP_PALBG]; + fg.pal8 = s_constData.pal8[KEYDISP_PALFG]; + break; +#endif +#if defined(SUPPORT_16BPP) + case 16: + bg.pal16 = s_constData.pal16[1][0]; + fg.pal16 = s_constData.pal16[0][0]; + break; +#endif +#if defined(SUPPORT_24BPP) || defined(SUPPORT_32BPP) + case 24: + case 32: + bg.pal32 = s_constData.pal32[1][0]; + fg.pal32 = s_constData.pal32[0][0]; + break; +#endif + default: + return; + } + for (i = 0; i < 10; i++) + { + cmndraw_setpat(vram, keybrd1, i * KEYDISP_KEYCX, 0, bg, fg); + } + cmndraw_setpat(vram, keybrd2, 10 * KEYDISP_KEYCX, 0, bg, fg); +} + +static BOOL draw1key(CMNVRAM *vram, KDCHANNEL *kdch, UINT n) +{ + const NOTEPATTERN *pPattern; + UINT pal; + CMNPAL fg; + + pPattern = s_constData.pattern + (kdch->k[n] & 0x7f); + pal = kdch->r[n]; + switch (vram->bpp) + { +#if defined(SUPPORT_8BPP) + case 8: + if (pal != KEYDISP_LEVEL_MAX) + { + fg.pal8 = s_constData.pal8[(pPattern->nType) ? KEYDISP_PALBG : KEYDISP_PALFG]; + cmndraw_setfg(vram, pPattern->lpImage, pPattern->nPosX, 0, fg); + kdch->r[n] = 0; + return TRUE; + } + fg.pal8 = s_constData.pal8[KEYDISP_PALHIT]; + break; +#endif +#if defined(SUPPORT_16BPP) + case 16: + fg.pal16 = s_constData.pal16[pPattern->nType][pal]; + break; +#endif +#if defined(SUPPORT_24BPP) || defined(SUPPORT_32BPP) + case 24: + case 32: + fg.pal32 = s_constData.pal32[pPattern->nType][pal]; + break; +#endif + default: + return FALSE; + } + cmndraw_setfg(vram, pPattern->lpImage, pPattern->nPosX, 0, fg); + return FALSE; +} + +static BOOL draw1ch(CMNVRAM *vram, UINT8 framepast, KDCHANNEL *kdch) +{ + BOOL draw; + UINT i; + BOOL coll; + UINT8 nextf; + UINT j; + + draw = FALSE; + if (kdch->flag & 2) + { + drawkeybg(vram); + draw = TRUE; + } + if (kdch->flag) + { + coll = FALSE; + nextf = 0; + for (i = 0; i < kdch->remain; i++) + { + if ((kdch->r[i]) || (kdch->flag & 2)) + { + if (kdch->r[i] < KEYDISP_LEVEL_MAX) + { + if (kdch->r[i] > framepast) + { + kdch->r[i] -= framepast; + nextf = 1; + } + else + { + kdch->r[i] = 0; + coll = TRUE; + } + } + coll |= draw1key(vram, kdch, i); + draw = TRUE; + } + } + if (coll) + { + for (i = 0; i < kdch->remain; i++) + { + if (!kdch->r[i]) + { + break; + } + } + for (j = i; i < kdch->remain; i++) + { + if (kdch->r[i]) + { + kdch->k[j] = kdch->k[i]; + kdch->r[j] = kdch->r[i]; + j++; + } + } + kdch->remain = j; + } + kdch->flag = nextf; + } + return draw; +} + + +/* ---- */ + +void keydisp_initialize(void) +{ + int r; + UINT16 x; + int i; + + r = 0; + x = 0; + do + { + for (i = 0; i < 12 && r < 128; i++, r++) + { + s_constData.pattern[r].nPosX = s_notepattern[i].nPosX + x; + s_constData.pattern[r].nType = s_notepattern[i].nType; + s_constData.pattern[r].lpImage = s_notepattern[i].lpImage; + } + x += 28; + } while (r < 128); + keyallclear(&s_keydisp); +} + +void keydisp_setpal(CMNPALFN *palfn) +{ + UINT i; + RGB32 pal32[KEYDISP_PALS]; + + if (palfn == NULL) + { + return; + } + if (palfn->get8) + { + for (i = 0; i < KEYDISP_PALS; i++) + { + s_constData.pal8[i] = (*palfn->get8)(palfn, i); + } + } + if (palfn->get32) + { + for (i = 0; i < KEYDISP_PALS; i++) + { + pal32[i].d = (*palfn->get32)(palfn, i); + cmndraw_makegrad(s_constData.pal32[0], KEYDISP_LEVEL, pal32[KEYDISP_PALFG], pal32[KEYDISP_PALHIT]); + cmndraw_makegrad(s_constData.pal32[1], KEYDISP_LEVEL, pal32[KEYDISP_PALBG], pal32[KEYDISP_PALHIT]); + } + if (palfn->cnv16) + { + for (i = 0; i < KEYDISP_LEVEL; i++) + { + s_constData.pal16[0][i] = (*palfn->cnv16)(palfn, s_constData.pal32[0][i]); + s_constData.pal16[1][i] = (*palfn->cnv16)(palfn, s_constData.pal32[1][i]); + } + } + } + s_keydisp.dispflag |= KEYDISP_FLAGREDRAW; +} + +void keydisp_setmode(UINT8 mode) +{ + if (s_keydisp.mode != mode) + { + s_keydisp.mode = mode; + s_keydisp.dispflag |= KEYDISP_FLAGREDRAW | KEYDISP_FLAGSIZING; + keyallclear(&s_keydisp); + if (mode == KEYDISP_MODEFM) + { + ClearDelayList(&s_keydisp); + opnakeyreset(&s_keydisp); + psgkeyreset(&s_keydisp); + opl3keyreset(&s_keydisp); + } + } + else + { + keyalloff(&s_keydisp); + } +} + +void keydisp_setdelay(UINT8 frames) +{ + s_keydisp.delay.warmbase = frames; + ClearDelayList(&s_keydisp); +} + +UINT8 keydisp_process(UINT8 framepast) +{ + UINT keys; + UINT i; + + if (framepast) + { + if (s_keydisp.mode == KEYDISP_MODEFM) + { + opnakeysync(&s_keydisp); + psgkeysync(&s_keydisp); + opl3keysync(&s_keydisp); + delayexecevent(&s_keydisp, framepast); + } + s_keydisp.framepast += framepast; + } + + keys = getdispkeys(&s_keydisp); + for (i = 0; i < keys; i++) + { + if (s_keydisp.ch[i].flag) + { + s_keydisp.dispflag |= KEYDISP_FLAGDRAW; + break; + } + } + return s_keydisp.dispflag; +} + +void keydisp_getsize(int *width, int *height) +{ + if (width) + { + *width = KEYDISP_WIDTH; + } + if (height) + { + *height = (getdispkeys(&s_keydisp) * KEYDISP_KEYCY) + 1; + } + s_keydisp.dispflag &= ~KEYDISP_FLAGSIZING; +} + +BOOL keydisp_paint(CMNVRAM *vram, BOOL redraw) +{ + BOOL draw; + UINT keys; + UINT i; + KDCHANNEL *p; + + draw = FALSE; + if ((vram == NULL) || (vram->width < KEYDISP_WIDTH) || (vram->height <= 0)) + { + goto kdpnt_exit; + } + if (s_keydisp.dispflag & KEYDISP_FLAGREDRAW) + { + redraw = TRUE; + } + if (redraw) + { + keyallreload(&s_keydisp); + clearrect(vram, 0, 0, KEYDISP_WIDTH, 1); + clearrect(vram, 0, 0, 1, vram->height); + draw = TRUE; + } + vram->ptr += vram->xalign + vram->yalign; + keys = (vram->height - 1) / KEYDISP_KEYCY; + keys = MIN(keys, getdispkeys(&s_keydisp)); + for (i = 0, p = s_keydisp.ch; i < keys; i++, p++) + { + draw |= draw1ch(vram, s_keydisp.framepast, p); + vram->ptr += KEYDISP_KEYCY * vram->yalign; + } + s_keydisp.dispflag &= ~(KEYDISP_FLAGDRAW | KEYDISP_FLAGREDRAW); + s_keydisp.framepast = 0; + +kdpnt_exit: + return draw; +} +/** + * Set Resize Flag + */ +void keydisp_setresizeflag(void) +{ + s_keydisp.dispflag |= KEYDISP_FLAGSIZING; +} +#endif diff --git a/generic/keydisp.h b/generic/keydisp.h old mode 100755 new mode 100644 index 4619c9ec..d8ac75dd --- a/generic/keydisp.h +++ b/generic/keydisp.h @@ -1,105 +1,105 @@ -/** - * @file keydisp.h - * @brief Interface of the key display - */ - -#pragma once - -#if defined(SUPPORT_KEYDISP) - -#include - -struct _cmnpalfn -{ - UINT8 (*get8)(struct _cmnpalfn *fn, UINT num); - UINT32 (*get32)(struct _cmnpalfn *fn, UINT num); - UINT16 (*cnv16)(struct _cmnpalfn *fn, RGB32 pal32); - INTPTR userdata; -}; -typedef struct _cmnpalfn CMNPALFN; - -enum -{ - KEYDISP_MODENONE = 0, - KEYDISP_MODEFM, - KEYDISP_MODEMIDI -}; - -enum -{ - KEYDISP_CHMAX = 64, -}; - -enum -{ - KEYDISP_NOTEMAX = 16, - - KEYDISP_KEYCX = 28, - KEYDISP_KEYCY = 14, - - KEYDISP_LEVEL = (1 << 4), - KEYDISP_LEVEL_MAX = KEYDISP_LEVEL - 1, - - KEYDISP_WIDTH = 301, - KEYDISP_HEIGHT = (KEYDISP_KEYCY * KEYDISP_CHMAX) + 1, - - KEYDISP_DELAYEVENTS = 2048, -}; - -enum -{ - KEYDISP_PALBG = 0, - KEYDISP_PALFG, - KEYDISP_PALHIT, - - KEYDISP_PALS -}; - -enum -{ - KEYDISP_FLAGDRAW = 0x01, - KEYDISP_FLAGREDRAW = 0x02, - KEYDISP_FLAGSIZING = 0x04 -}; - - -#ifdef __cplusplus -extern "C" -{ -#endif - -void keydisp_initialize(void); -void keydisp_setmode(UINT8 mode); -void keydisp_setpal(CMNPALFN *palfn); -void keydisp_setdelay(UINT8 frames); -UINT8 keydisp_process(UINT8 framepast); -void keydisp_getsize(int *width, int *height); -BOOL keydisp_paint(CMNVRAM *vram, BOOL redraw); - -void keydisp_reset(void); -void keydisp_bindopna(const UINT8 *pcRegister, UINT nChannels, UINT nBaseClock); -void keydisp_bindpsg(const UINT8 *pcRegister, UINT nBaseClock); -void keydisp_bindopl3(const UINT8 *pcRegister, UINT nChannels, UINT nBaseClock); -void keydisp_opnakeyon(const UINT8 *pcRegister, REG8 cData); -void keydisp_psg(const UINT8 *pcRegister, UINT nAddress); -void keydisp_opl3keyon(const UINT8 *pcRegister, REG8 nChannelNum, REG8 cData); -void keydisp_midi(const UINT8 *msg); -void keydisp_setresizeflag(void); - -#ifdef __cplusplus -} -#endif - -#else - -#define keydisp_draw(a) -#define keydisp_reset() -#define keydisp_bindopna(r, c, b) -#define keydisp_bindpsg(r, b) -#define keydisp_bindopl3(r, c, b) -#define keydisp_opnakeyon(r, d) -#define keydisp_psg(r, a) -#define keydisp_opl3keyon(r, c, d) -#define keydisp_midi(a) - -#endif +/** + * @file keydisp.h + * @brief Interface of the key display + */ + +#pragma once + +#if defined(SUPPORT_KEYDISP) + +#include + +struct _cmnpalfn +{ + UINT8 (*get8)(struct _cmnpalfn *fn, UINT num); + UINT32 (*get32)(struct _cmnpalfn *fn, UINT num); + UINT16 (*cnv16)(struct _cmnpalfn *fn, RGB32 pal32); + INTPTR userdata; +}; +typedef struct _cmnpalfn CMNPALFN; + +enum +{ + KEYDISP_MODENONE = 0, + KEYDISP_MODEFM, + KEYDISP_MODEMIDI +}; + +enum +{ + KEYDISP_CHMAX = 64, +}; + +enum +{ + KEYDISP_NOTEMAX = 16, + + KEYDISP_KEYCX = 28, + KEYDISP_KEYCY = 14, + + KEYDISP_LEVEL = (1 << 4), + KEYDISP_LEVEL_MAX = KEYDISP_LEVEL - 1, + + KEYDISP_WIDTH = 301, + KEYDISP_HEIGHT = (KEYDISP_KEYCY * KEYDISP_CHMAX) + 1, + + KEYDISP_DELAYEVENTS = 2048, +}; + +enum +{ + KEYDISP_PALBG = 0, + KEYDISP_PALFG, + KEYDISP_PALHIT, + + KEYDISP_PALS +}; + +enum +{ + KEYDISP_FLAGDRAW = 0x01, + KEYDISP_FLAGREDRAW = 0x02, + KEYDISP_FLAGSIZING = 0x04 +}; + + +#ifdef __cplusplus +extern "C" +{ +#endif + +void keydisp_initialize(void); +void keydisp_setmode(UINT8 mode); +void keydisp_setpal(CMNPALFN *palfn); +void keydisp_setdelay(UINT8 frames); +UINT8 keydisp_process(UINT8 framepast); +void keydisp_getsize(int *width, int *height); +BOOL keydisp_paint(CMNVRAM *vram, BOOL redraw); + +void keydisp_reset(void); +void keydisp_bindopna(const UINT8 *pcRegister, UINT nChannels, UINT nBaseClock); +void keydisp_bindpsg(const UINT8 *pcRegister, UINT nBaseClock); +void keydisp_bindopl3(const UINT8 *pcRegister, UINT nChannels, UINT nBaseClock); +void keydisp_opnakeyon(const UINT8 *pcRegister, REG8 cData); +void keydisp_psg(const UINT8 *pcRegister, UINT nAddress); +void keydisp_opl3keyon(const UINT8 *pcRegister, REG8 nChannelNum, REG8 cData); +void keydisp_midi(const UINT8 *msg); +void keydisp_setresizeflag(void); + +#ifdef __cplusplus +} +#endif + +#else + +#define keydisp_draw(a) +#define keydisp_reset() +#define keydisp_bindopna(r, c, b) +#define keydisp_bindpsg(r, b) +#define keydisp_bindopl3(r, c, b) +#define keydisp_opnakeyon(r, d) +#define keydisp_psg(r, a) +#define keydisp_opl3keyon(r, c, d) +#define keydisp_midi(a) + +#endif diff --git a/generic/memdbg32.c b/generic/memdbg32.c old mode 100755 new mode 100644 index ef9b22b9..d6aa8cff --- a/generic/memdbg32.c +++ b/generic/memdbg32.c @@ -1,159 +1,159 @@ -#include - -#if defined(CPUCORE_IA32) && defined(SUPPORT_MEMDBG32) - -#include -#include -#include -#include -#include - -#define MEMDBG32_MAXMEM 16 -#define MEMDBG32_DATAPERLINE 128 -#define MEMDBG32_LEFTMARGIN 8 - -typedef struct { - UINT mode; - int width; - int height; - int bpp; - CMNPAL pal[MEMDBG32_PALS]; -} MEMDBG32; - -static MEMDBG32 memdbg32; - -static const char _mode0[] = "Real Mode"; -static const char _mode1[] = "Protected Mode"; -static const char _mode2[] = "Virtual86"; -static const char *modestr[3] = {_mode0, _mode1, _mode2}; -static const RGB32 md32pal[MEMDBG32_PALS] = { - RGB32D(0x33, 0x33, 0x33), - RGB32D(0x00, 0x00, 0x00), - RGB32D(0xff, 0xaa, 0x00), - RGB32D(0xff, 0x00, 0x00), - RGB32D(0x11, 0x88, 0x11), - RGB32D(0x00, 0xff, 0x00), - RGB32D(0xff, 0xff, 0xff)}; - - -void memdbg32_initialize(void) { - - ZeroMemory(&memdbg32, sizeof(memdbg32)); - memdbg32.width = (MEMDBG32_BLOCKW * MEMDBG32_DATAPERLINE) + MEMDBG32_LEFTMARGIN; - memdbg32.height = (MEMDBG32_BLOCKH * 2 * MEMDBG32_MAXMEM) + 8; -} - -void memdbg32_getsize(int *width, int *height) { - - if (width) { - *width = memdbg32.width; - } - if (height) { - *height = memdbg32.height; - } -} - -REG8 memdbg32_process(void) { - - return(MEMDBG32_FLAGDRAW); -} - -BOOL memdbg32_paint(CMNVRAM *vram, CMNPALCNV cnv, BOOL redraw) { - - UINT mode; - UINT8 use[MEMDBG32_MAXMEM*MEMDBG32_DATAPERLINE*2 + 256]; - UINT32 pd[1024]; - UINT pdmax; - UINT i, j; - UINT32 pde; - UINT32 pdea; - UINT32 pte; - char str[4]; - - mode = 0; - if (CPU_STAT_PM) { - mode = 1; - } - if (CPU_STAT_VM86) { - mode = 2; - } - if (memdbg32.mode != mode) { - memdbg32.mode = mode; - redraw = TRUE; - } - if ((!redraw) && (!CPU_STAT_PAGING)) { - return(FALSE); - } - if (vram == NULL) { - return(FALSE); - } - if ((memdbg32.bpp != vram->bpp) || (redraw)) { - if (cnv == NULL) { - return(FALSE); - } - (*cnv)(memdbg32.pal, md32pal, MEMDBG32_PALS, vram->bpp); - memdbg32.bpp = vram->bpp; - } - - cmndraw_fill(vram, 0, 0, memdbg32.width, memdbg32.height, - memdbg32.pal[MEMDBG32_PALBDR]); - ZeroMemory(use, sizeof(use)); - if (CPU_STAT_PAGING) { - pdmax = 0; - for (i=0; i<1024; i++) { - pde = cpu_memoryread_d(CPU_STAT_PDE_BASE + (i * 4)); - if (pde & CPU_PDE_PRESENT) { - for (j=0; j> 12] = MEMDBG32_PALPAGE1; - } - else if (!use[pte >> 12]) { - use[pte >> 12] = MEMDBG32_PALPAGE0; - } - } - } - } - } - else { - FillMemory(use, 256, MEMDBG32_PALREAL); - FillMemory(use + (0xfa0000 >> 12), (0x60000 >> 12), MEMDBG32_PALREAL); - if ((CPU_STAT_PM) && (pccore.extmem)) { - FillMemory(use + 256, MIN(MEMDBG32_DATAPERLINE * 2 * pccore.extmem, sizeof(use) - 256), MEMDBG32_PALPM); - } - } - for (i=0; i + +#if defined(CPUCORE_IA32) && defined(SUPPORT_MEMDBG32) + +#include +#include +#include +#include +#include + +#define MEMDBG32_MAXMEM 16 +#define MEMDBG32_DATAPERLINE 128 +#define MEMDBG32_LEFTMARGIN 8 + +typedef struct { + UINT mode; + int width; + int height; + int bpp; + CMNPAL pal[MEMDBG32_PALS]; +} MEMDBG32; + +static MEMDBG32 memdbg32; + +static const char _mode0[] = "Real Mode"; +static const char _mode1[] = "Protected Mode"; +static const char _mode2[] = "Virtual86"; +static const char *modestr[3] = {_mode0, _mode1, _mode2}; +static const RGB32 md32pal[MEMDBG32_PALS] = { + RGB32D(0x33, 0x33, 0x33), + RGB32D(0x00, 0x00, 0x00), + RGB32D(0xff, 0xaa, 0x00), + RGB32D(0xff, 0x00, 0x00), + RGB32D(0x11, 0x88, 0x11), + RGB32D(0x00, 0xff, 0x00), + RGB32D(0xff, 0xff, 0xff)}; + + +void memdbg32_initialize(void) { + + ZeroMemory(&memdbg32, sizeof(memdbg32)); + memdbg32.width = (MEMDBG32_BLOCKW * MEMDBG32_DATAPERLINE) + MEMDBG32_LEFTMARGIN; + memdbg32.height = (MEMDBG32_BLOCKH * 2 * MEMDBG32_MAXMEM) + 8; +} + +void memdbg32_getsize(int *width, int *height) { + + if (width) { + *width = memdbg32.width; + } + if (height) { + *height = memdbg32.height; + } +} + +REG8 memdbg32_process(void) { + + return(MEMDBG32_FLAGDRAW); +} + +BOOL memdbg32_paint(CMNVRAM *vram, CMNPALCNV cnv, BOOL redraw) { + + UINT mode; + UINT8 use[MEMDBG32_MAXMEM*MEMDBG32_DATAPERLINE*2 + 256]; + UINT32 pd[1024]; + UINT pdmax; + UINT i, j; + UINT32 pde; + UINT32 pdea; + UINT32 pte; + char str[4]; + + mode = 0; + if (CPU_STAT_PM) { + mode = 1; + } + if (CPU_STAT_VM86) { + mode = 2; + } + if (memdbg32.mode != mode) { + memdbg32.mode = mode; + redraw = TRUE; + } + if ((!redraw) && (!CPU_STAT_PAGING)) { + return(FALSE); + } + if (vram == NULL) { + return(FALSE); + } + if ((memdbg32.bpp != vram->bpp) || (redraw)) { + if (cnv == NULL) { + return(FALSE); + } + (*cnv)(memdbg32.pal, md32pal, MEMDBG32_PALS, vram->bpp); + memdbg32.bpp = vram->bpp; + } + + cmndraw_fill(vram, 0, 0, memdbg32.width, memdbg32.height, + memdbg32.pal[MEMDBG32_PALBDR]); + ZeroMemory(use, sizeof(use)); + if (CPU_STAT_PAGING) { + pdmax = 0; + for (i=0; i<1024; i++) { + pde = cpu_memoryread_d(CPU_STAT_PDE_BASE + (i * 4)); + if (pde & CPU_PDE_PRESENT) { + for (j=0; j> 12] = MEMDBG32_PALPAGE1; + } + else if (!use[pte >> 12]) { + use[pte >> 12] = MEMDBG32_PALPAGE0; + } + } + } + } + } + else { + FillMemory(use, 256, MEMDBG32_PALREAL); + FillMemory(use + (0xfa0000 >> 12), (0x60000 >> 12), MEMDBG32_PALREAL); + if ((CPU_STAT_PM) && (pccore.extmem)) { + FillMemory(use + 256, MIN(MEMDBG32_DATAPERLINE * 2 * pccore.extmem, sizeof(use) - 256), MEMDBG32_PALPM); + } + } + for (i=0; i - -enum { - MEMDBG32_BLOCKW = 3, - MEMDBG32_BLOCKH = 6, -}; - -enum { - MEMDBG32_PALBG = 0, - MEMDBG32_PALBDR, - MEMDBG32_PALREAL, - MEMDBG32_PALPM, - MEMDBG32_PALPAGE0, - MEMDBG32_PALPAGE1, - MEMDBG32_PALTXT, - - MEMDBG32_PALS -}; - -enum { - MEMDBG32_FLAGDRAW = 0x01, - MEMDBG32_FLAGREDRAW = 0x02 -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -void memdbg32_initialize(void); -void memdbg32_getsize(int *width, int *height); -REG8 memdbg32_process(void); -BOOL memdbg32_paint(CMNVRAM *vram, CMNPALCNV cnv, BOOL redraw); - -#ifdef __cplusplus -} -#endif - -#endif - + +#if defined(CPUCORE_IA32) && defined(SUPPORT_MEMDBG32) + +#include + +enum { + MEMDBG32_BLOCKW = 3, + MEMDBG32_BLOCKH = 6, +}; + +enum { + MEMDBG32_PALBG = 0, + MEMDBG32_PALBDR, + MEMDBG32_PALREAL, + MEMDBG32_PALPM, + MEMDBG32_PALPAGE0, + MEMDBG32_PALPAGE1, + MEMDBG32_PALTXT, + + MEMDBG32_PALS +}; + +enum { + MEMDBG32_FLAGDRAW = 0x01, + MEMDBG32_FLAGREDRAW = 0x02 +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +void memdbg32_initialize(void); +void memdbg32_getsize(int *width, int *height); +REG8 memdbg32_process(void); +BOOL memdbg32_paint(CMNVRAM *vram, CMNPALCNV cnv, BOOL redraw); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/generic/np2info.c b/generic/np2info.c old mode 100755 new mode 100644 index 16c38e7f..a93aa45a --- a/generic/np2info.c +++ b/generic/np2info.c @@ -1,629 +1,629 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_IDEIO) -#include -#endif -#if defined(SUPPORT_GPIB) -#include -#endif - -static const OEMCHAR str_comma[] = OEMTEXT(", "); -static const OEMCHAR str_2halfMHz[] = OEMTEXT("2.5MHz"); -#define str_5MHz (str_2halfMHz + 2) -static const OEMCHAR str_8MHz[] = OEMTEXT("8MHz"); -static const OEMCHAR str_notexist[] = OEMTEXT("not exist"); -static const OEMCHAR str_disable[] = OEMTEXT("disable"); - -static const OEMCHAR str_cpu[] = OEMTEXT("8086-2\00070116\00080286\00080386\00080486\0Pentium\0PentiumPro"); -static const OEMCHAR str_winclr[] = OEMTEXT("256-colors\00065536-colors\0full color\0true color"); -static const OEMCHAR str_winmode[] = OEMTEXT(" (window)\0 (fullscreen)"); -static const OEMCHAR str_grcgchip[] = OEMTEXT("\0GRCG \0GRCG CG-Window \0EGC CG-Window "); -static const OEMCHAR str_vrammode[] = OEMTEXT("Digital\0Analog\000256colors"); -static const OEMCHAR str_vrampage[] = OEMTEXT(" page-0\0 page-1\0 page-all"); -static const OEMCHAR str_chpan[] = OEMTEXT("none\0Mono-R\0Mono-L\0Stereo"); -static const OEMCHAR str_fpu[] = OEMTEXT(" none\0 Berkeley SoftFloat 80bit Extended Precision FPU\0 64bit Double Precision FPU\0 64bit Double Precision FPU + INT64 Load/Store"); -static const OEMCHAR str_simd_mmx[] = OEMTEXT("MMX "); -static const OEMCHAR str_simd_sse[] = OEMTEXT("SSE "); -static const OEMCHAR str_simd_sse2[] = OEMTEXT("SSE2 "); -static const OEMCHAR str_simd_sse3[] = OEMTEXT("SSE3 "); -static const OEMCHAR str_simd_ssse3[] = OEMTEXT("SSSE3 "); -static const OEMCHAR str_simd_sse4_1[] = OEMTEXT("SSE4.1 "); -static const OEMCHAR str_simd_sse4_2[] = OEMTEXT("SSE4.2 "); -static const OEMCHAR str_simd_3dnow[] = OEMTEXT("3DNow! "); -static const OEMCHAR str_simd_e3dnow[] = OEMTEXT("Enhanced 3DNow! "); - -static const OEMCHAR str_clockfmt[] = OEMTEXT("%d.%1dMHz"); -static const OEMCHAR str_memfmt[] = OEMTEXT("%3uKB"); -static const OEMCHAR str_memfmt2[] = OEMTEXT("%3uKB + %uKB"); -static const OEMCHAR str_memfmt3[] = OEMTEXT("%d.%1dMB"); -static const OEMCHAR str_twidth[] = OEMTEXT("width-%u"); -static const OEMCHAR str_dispclock[] = OEMTEXT("%u.%.2ukHz / %u.%uHz"); - -static const OEMCHAR str_pcm86a[] = OEMTEXT(" PCM: %dHz %dbit %s"); -static const OEMCHAR str_pcm86b[] = OEMTEXT(" %d / %d / 32768"); -static const OEMCHAR str_rhythm[] = OEMTEXT("BSCHTR"); - - -// ---- common - -static void info_ver(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - milstr_ncpy(str, np2version, maxlen); - (void)ex; -} - -static void info_cpu(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - -#if defined(NP2_WIN) -#if defined(CPUCORE_IA32) -#ifdef UNICODE - MultiByteToWideChar(CP_ACP, 0, i386cpuid.cpu_brandstring, -1, str, maxlen); -#else - milstr_ncpy(str, i386cpuid.cpu_brandstring, maxlen); -#endif - if(i386cpuid.allow_movCS){ - milstr_ncat(str, OEMTEXT(" (+MOV CS,xx)"), maxlen - OEMSTRLEN(str)); - } -#else - UINT family; -#if defined(CPU_FAMILY) - family = MIN(CPU_FAMILY, 6); -#else - family = (CPU_TYPE & CPUTYPE_V30)?1:2; -#endif - milstr_ncpy(str, milstr_list(str_cpu, family), maxlen); - -#endif -#endif - - (void)ex; -} - -static void info_clock(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - UINT32 clk; - OEMCHAR clockstr[64]; - - clk = (pccore.realclock + 50000) / 100000; - OEMSNPRINTF(clockstr, sizeof(clockstr), str_clockfmt, clk/10, clk % 10); - milstr_ncpy(str, clockstr, maxlen); - (void)ex; -} - -static void info_base(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - milstr_ncpy(str, - (pccore.cpumode & CPUMODE_8MHZ)?str_8MHz:str_5MHz, maxlen); - (void)ex; -} - -static void info_mem1(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - UINT memsize; - OEMCHAR memstr[64]; - - memsize = np2cfg.memsw[2] & 7; - if (memsize < 6) { - memsize = (memsize + 1) * 128; - } - else { - memsize = 640; - } - if (pccore.extmem) { - OEMSNPRINTF(memstr, sizeof(memstr), str_memfmt2, memsize, pccore.extmem * 1024); - } - else { - OEMSNPRINTF(memstr, sizeof(memstr), str_memfmt, memsize); - } - milstr_ncpy(str, memstr, maxlen); - (void)ex; -} - -static void info_mem2(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - UINT memsize; - OEMCHAR memstr[64]; - - memsize = np2cfg.memsw[2] & 7; - if (memsize < 6) { - memsize = (memsize + 1) * 128; - } - else { - memsize = 640; - } - memsize += pccore.extmem * 1024; - OEMSNPRINTF(memstr, sizeof(memstr), str_memfmt, memsize); - milstr_ncpy(str, memstr, maxlen); - (void)ex; -} - -static void info_mem3(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - UINT memsize; - OEMCHAR memstr[64]; - - memsize = np2cfg.memsw[2] & 7; - if (memsize < 6) { - memsize = (memsize + 1) * 128; - } - else { - memsize = 640; - } - if (pccore.extmem > 1) { - OEMSNPRINTF(memstr, sizeof(memstr), str_memfmt3, pccore.extmem, memsize / 100); - } - else { - OEMSNPRINTF(memstr, sizeof(memstr), str_memfmt, memsize); - } - milstr_ncpy(str, memstr, maxlen); - (void)ex; -} - -static void info_gdc(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - milstr_ncpy(str, milstr_list(str_grcgchip, grcg.chip & 3), maxlen); - milstr_ncat(str, str_2halfMHz + ((gdc.clock & 0x80)?2:0), maxlen); - (void)ex; -} - -static void info_gdc2(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - OEMCHAR textstr[64]; - - OEMSNPRINTF(textstr, sizeof(textstr), str_dispclock, - gdc.hclock / 1000, (gdc.hclock / 10) % 100, - gdc.vclock / 10, gdc.vclock % 10); - milstr_ncpy(str, textstr, maxlen); - (void)ex; -} - -static void info_text(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - -const OEMCHAR *p; - OEMCHAR textstr[128]; - - if (!(gdcs.textdisp & GDCSCRN_ENABLE)) { - p = str_disable; - } - else { - OEMSNPRINTF(textstr, sizeof(textstr), str_twidth, ((gdc.mode1 & 0x4)?40:80)); - p = textstr; - } - milstr_ncpy(str, p, maxlen); - (void)ex; -} - -static void info_grph(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - -const OEMCHAR *p; - UINT md; - UINT pg; - OEMCHAR work[32]; - - if (!(gdcs.grphdisp & GDCSCRN_ENABLE)) { - p = str_disable; - } - else { - md = (gdc.analog & (1 << GDCANALOG_16))?1:0; - pg = gdcs.access; -#if defined(SUPPORT_PC9821) - if (gdc.analog & (1 << (GDCANALOG_256))) { - md = 2; - if (gdc.analog & (1 << (GDCANALOG_256E))) { - pg = 2; - } - } -#endif - milstr_ncpy(work, milstr_list(str_vrammode, md), NELEMENTS(work)); - milstr_ncat(work, milstr_list(str_vrampage, pg), NELEMENTS(work)); - p = work; - } - milstr_ncpy(str, p, maxlen); - (void)ex; -} - -static void info_sound(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) -{ - const OEMCHAR *lpBoard; - - lpBoard = OEMTEXT("none"); - switch (g_nSoundID) - { - case SOUNDID_NONE: - break; - - case SOUNDID_PC_9801_14: - lpBoard = OEMTEXT("PC-9801-14"); - break; - - case SOUNDID_PC_9801_26K: - lpBoard = OEMTEXT("PC-9801-26"); - break; - - case SOUNDID_PC_9801_86: - lpBoard = OEMTEXT("PC-9801-86"); - break; - - case SOUNDID_PC_9801_86_26K: - lpBoard = OEMTEXT("PC-9801-26 + 86"); - break; - - case SOUNDID_PC_9801_118: - lpBoard = OEMTEXT("PC-9801-118"); - break; - - case SOUNDID_PC_9801_86_WSS: - lpBoard = OEMTEXT("PC-9801-86 + Mate-X PCM"); - break; - - case SOUNDID_PC_9801_86_118: - lpBoard = OEMTEXT("PC-9801-86 + PC-9801-118"); - break; - - case SOUNDID_MATE_X_PCM: - lpBoard = OEMTEXT("Mate-X PCM"); - break; - - case SOUNDID_PC_9801_86_ADPCM: - lpBoard = OEMTEXT("PC-9801-86 + Chibi-oto"); - break; - - case SOUNDID_WAVESTAR: - lpBoard = OEMTEXT("Wave Star"); - break; - - case SOUNDID_SPEAKBOARD: - lpBoard = OEMTEXT("Speak board"); - break; - - case SOUNDID_86_SPEAKBOARD: - lpBoard = OEMTEXT("PC-9801-86 + Speak board"); - break; - - case SOUNDID_SPARKBOARD: - lpBoard = OEMTEXT("Spark board"); - break; - - case SOUNDID_AMD98: - lpBoard = OEMTEXT("AMD-98"); - break; - - case SOUNDID_SOUNDORCHESTRA: - lpBoard = OEMTEXT("SOUND ORCHESTRA"); - break; - - case SOUNDID_SOUNDORCHESTRAV: - lpBoard = OEMTEXT("SOUND ORCHESTRA-V"); - break; - - case SOUNDID_LITTLEORCHESTRAL: - lpBoard = OEMTEXT("LITTLE ORCHESTRA L"); - break; - - case SOUNDID_MMORCHESTRA: - lpBoard = OEMTEXT("MULTIMEDIA ORCHESTRA"); - break; - -#if defined(SUPPORT_SOUND_SB16) - case SOUNDID_SB16: - lpBoard = OEMTEXT("Sound Blaster 16"); - break; - - case SOUNDID_PC_9801_86_SB16: - lpBoard = OEMTEXT("PC-9801-86 + Sound Blaster 16"); - break; - - case SOUNDID_WSS_SB16: - lpBoard = OEMTEXT("Mate-X PCM + Sound Blaster 16"); - break; - - case SOUNDID_PC_9801_86_WSS_SB16: - lpBoard = OEMTEXT("PC-9801-86 + Mate-X PCM + Sound Blaster 16"); - break; - - case SOUNDID_PC_9801_118_SB16: - lpBoard = OEMTEXT("PC-9801-118 + Sound Blaster 16"); - break; - - case SOUNDID_PC_9801_86_118_SB16: - lpBoard = OEMTEXT("PC-9801-86 + PC-9801-118 + Sound Blaster 16"); - break; -#endif // defined(SUPPORT_SOUND_SB16) - -#if defined(SUPPORT_PX) - case SOUNDID_PX1: - lpBoard = OEMTEXT("Otomi-chanx2"); - break; - - case SOUNDID_PX2: - lpBoard = OEMTEXT("Otomi-chanx2 + 86"); - break; -#endif // defined(SUPPORT_PX) - - default: - lpBoard = OEMTEXT("unknown"); - break; - } - milstr_ncpy(str, lpBoard, maxlen); - (void)ex; -} - -static void info_extsnd(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - OEMCHAR buf[128]; - - info_sound(str, maxlen, ex); - if (g_nSoundID & 4) { - milstr_ncat(str, ex->cr, maxlen); - OEMSNPRINTF(buf, sizeof(buf), str_pcm86a, - pcm86rate8[g_pcm86.fifo & 7] >> 3, - (16 - ((g_pcm86.dactrl >> 3) & 8)), - milstr_list(str_chpan, (g_pcm86.dactrl >> 4) & 3)); - milstr_ncat(str, buf, maxlen); - milstr_ncat(str, ex->cr, maxlen); - OEMSNPRINTF(buf, sizeof(buf), str_pcm86b, g_pcm86.virbuf, g_pcm86.fifosize); - milstr_ncat(str, buf, maxlen); - } -} - -static void info_bios(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - str[0] = '\0'; - if (pccore.rom & PCROM_BIOS) { - milstr_ncat(str, str_biosrom, maxlen); - } - if (soundrom.name[0]) { - if (str[0]) { - milstr_ncat(str, str_comma, maxlen); - } - milstr_ncat(str, soundrom.name, maxlen); - } -#if defined(SUPPORT_IDEIO) - if (ideio.bios) { - if (str[0]) { - milstr_ncat(str, str_comma, maxlen); - } - milstr_ncat(str, ideio.biosname, maxlen); - } -#endif -#if defined(SUPPORT_PCI) - if (pcidev.biosname[0]) { - if (str[0]) { - milstr_ncat(str, str_comma, maxlen); - } - milstr_ncat(str, pcidev.biosname, maxlen); - } -#endif -#if defined(SUPPORT_GPIB) - if (gpib.enable) { - if (str[0]) { - milstr_ncat(str, str_comma, maxlen); - } - milstr_ncat(str, OEMTEXT("gpib.rom"), maxlen); - } -#endif - if (str[0] == '\0') { - milstr_ncat(str, str_notexist, maxlen); - } - (void)ex; -} - -static void info_rhythm(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - OEMCHAR rhythmstr[8]; - UINT exist; - UINT i; - - exist = rhythm_getcaps(); - milstr_ncpy(rhythmstr, str_rhythm, NELEMENTS(rhythmstr)); - for (i=0; i<6; i++) { - if (!(exist & (1 << i))) { - rhythmstr[i] = '_'; - } - } - milstr_ncpy(str, rhythmstr, maxlen); - (void)ex; -} - -static void info_display(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - UINT bpp; - OEMCHAR buf[128] = {0}; - - bpp = scrnmng_getbpp(); - milstr_ncpy(str, milstr_list(str_winclr, ((bpp >> 3) - 1) & 3), maxlen); -// OEMSNPRINTF(buf, sizeof(buf), OEMTEXT(" %dx%d"), scrnmngp->width, scrnmngp->height); -// milstr_ncat(str, buf, maxlen); - milstr_ncat(str, milstr_list(str_winmode, (scrnmng_isfullscreen())?1:0), - maxlen); - (void)ex; -} - -static void info_fpu(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - -#if defined(CPUCORE_IA32) - if(i386cpuid.cpu_feature & CPU_FEATURE_FPU){ - if(i386cpuid.fpu_type < 3){ - milstr_ncpy(str, milstr_list(str_fpu, 1+i386cpuid.fpu_type), maxlen); - }else{ - milstr_ncpy(str, OEMTEXT(" unknown"), maxlen); - } - }else -#endif - { - milstr_ncpy(str, milstr_list(str_fpu, 0), maxlen); - } -} - -static void info_simd(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { - - int simdcount = 0; - milstr_ncpy(str, OEMTEXT(" "), maxlen); -#if defined(CPUCORE_IA32) - if(i386cpuid.cpu_feature & CPU_FEATURE_MMX){ - milstr_ncat(str, str_simd_mmx, maxlen); - simdcount++; - } - if(i386cpuid.cpu_feature & CPU_FEATURE_SSE){ - milstr_ncat(str, str_simd_sse, maxlen); - simdcount++; - } - if(i386cpuid.cpu_feature & CPU_FEATURE_SSE2){ - milstr_ncat(str, str_simd_sse2, maxlen); - simdcount++; - } - if(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSE3){ - milstr_ncat(str, str_simd_sse3, maxlen); - simdcount++; - } - if(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSSE3){ - milstr_ncat(str, str_simd_ssse3, maxlen); - simdcount++; - } - if(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSE4_1){ - milstr_ncat(str, str_simd_sse4_1, maxlen); - simdcount++; - } - if(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSE4_2){ - milstr_ncat(str, str_simd_sse4_2, maxlen); - simdcount++; - } - if(i386cpuid.cpu_feature_ex & CPU_FEATURE_EX_3DNOW){ - milstr_ncat(str, str_simd_3dnow, maxlen); - simdcount++; - } - if(i386cpuid.cpu_feature_ex & CPU_FEATURE_EX_E3DNOW){ - milstr_ncat(str, str_simd_e3dnow, maxlen); - simdcount++; - } -#endif - if(simdcount==0){ - milstr_ncat(str, OEMTEXT("none"), maxlen); - } -} - - -// ---- make string - -typedef struct { - OEMCHAR key[8]; - void (*proc)(OEMCHAR *str, int maxlen, const NP2INFOEX *ex); -} INFOPROC; - -static const INFOPROC infoproc[] = { - {OEMTEXT("VER"), info_ver}, - {OEMTEXT("CPU"), info_cpu}, - {OEMTEXT("CLOCK"), info_clock}, - {OEMTEXT("BASE"), info_base}, - {OEMTEXT("MEM1"), info_mem1}, - {OEMTEXT("MEM2"), info_mem2}, - {OEMTEXT("MEM3"), info_mem3}, - {OEMTEXT("FPU"), info_fpu}, - {OEMTEXT("SIMD"), info_simd}, - {OEMTEXT("GDC"), info_gdc}, - {OEMTEXT("GDC2"), info_gdc2}, - {OEMTEXT("TEXT"), info_text}, - {OEMTEXT("GRPH"), info_grph}, - {OEMTEXT("SND"), info_sound}, - {OEMTEXT("EXSND"), info_extsnd}, - {OEMTEXT("BIOS"), info_bios}, - {OEMTEXT("RHYTHM"), info_rhythm}, - {OEMTEXT("DISP"), info_display}}; - - -static BOOL defext(OEMCHAR *dst, const OEMCHAR *key, int maxlen, - const NP2INFOEX *ex) { - - milstr_ncpy(dst, key, maxlen); - (void)ex; - return(TRUE); -} - -void np2info(OEMCHAR *dst, const OEMCHAR *src, int maxlen, - const NP2INFOEX *ex) { - - NP2INFOEX statex; - OEMCHAR c; - UINT leng; - OEMCHAR infwork[12]; -const INFOPROC *inf; -const INFOPROC *infterm; - - if ((dst == NULL) || (maxlen <= 0) || (src == NULL)) { - return; - } - if (ex == NULL) { - milstr_ncpy(statex.cr, str_oscr, NELEMENTS(statex.cr)); - statex.ext = NULL; - } - else { - statex = *ex; - } - if (statex.ext == NULL) { - statex.ext = defext; - } - while(maxlen > 0) { - c = *src++; - if (c == '\0') { - break; - } - else if (c == '\n') { - milstr_ncpy(dst, statex.cr, maxlen); - } - else if (c != '%') { - *dst++ = c; - maxlen--; - continue; - } - else if (*src == '%') { - src++; - *dst++ = c; - maxlen--; - continue; - } - else { - leng = 0; - while(1) { - c = *src; - if (c == '\0') { - break; - } - src++; - if (c == '%') { - break; - } - if (leng < (NELEMENTS(infwork) - 1)) { - infwork[leng++] = c; - } - } - infwork[leng] = '\0'; - inf = infoproc; - infterm = infoproc + NELEMENTS(infoproc); - while(inf < infterm) { - if (!milstr_cmp(infwork, inf->key)) { - inf->proc(dst, maxlen, &statex); - break; - } - inf++; - } - if (inf >= infterm) { - if (!(*statex.ext)(dst, infwork, maxlen, &statex)) { - continue; - } - } - } - leng = (UINT)OEMSTRLEN(dst); - dst += leng; - maxlen -= leng; - } - *dst = '\0'; -} - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_IDEIO) +#include +#endif +#if defined(SUPPORT_GPIB) +#include +#endif + +static const OEMCHAR str_comma[] = OEMTEXT(", "); +static const OEMCHAR str_2halfMHz[] = OEMTEXT("2.5MHz"); +#define str_5MHz (str_2halfMHz + 2) +static const OEMCHAR str_8MHz[] = OEMTEXT("8MHz"); +static const OEMCHAR str_notexist[] = OEMTEXT("not exist"); +static const OEMCHAR str_disable[] = OEMTEXT("disable"); + +static const OEMCHAR str_cpu[] = OEMTEXT("8086-2\00070116\00080286\00080386\00080486\0Pentium\0PentiumPro"); +static const OEMCHAR str_winclr[] = OEMTEXT("256-colors\00065536-colors\0full color\0true color"); +static const OEMCHAR str_winmode[] = OEMTEXT(" (window)\0 (fullscreen)"); +static const OEMCHAR str_grcgchip[] = OEMTEXT("\0GRCG \0GRCG CG-Window \0EGC CG-Window "); +static const OEMCHAR str_vrammode[] = OEMTEXT("Digital\0Analog\000256colors"); +static const OEMCHAR str_vrampage[] = OEMTEXT(" page-0\0 page-1\0 page-all"); +static const OEMCHAR str_chpan[] = OEMTEXT("none\0Mono-R\0Mono-L\0Stereo"); +static const OEMCHAR str_fpu[] = OEMTEXT(" none\0 Berkeley SoftFloat 80bit Extended Precision FPU\0 64bit Double Precision FPU\0 64bit Double Precision FPU + INT64 Load/Store"); +static const OEMCHAR str_simd_mmx[] = OEMTEXT("MMX "); +static const OEMCHAR str_simd_sse[] = OEMTEXT("SSE "); +static const OEMCHAR str_simd_sse2[] = OEMTEXT("SSE2 "); +static const OEMCHAR str_simd_sse3[] = OEMTEXT("SSE3 "); +static const OEMCHAR str_simd_ssse3[] = OEMTEXT("SSSE3 "); +static const OEMCHAR str_simd_sse4_1[] = OEMTEXT("SSE4.1 "); +static const OEMCHAR str_simd_sse4_2[] = OEMTEXT("SSE4.2 "); +static const OEMCHAR str_simd_3dnow[] = OEMTEXT("3DNow! "); +static const OEMCHAR str_simd_e3dnow[] = OEMTEXT("Enhanced 3DNow! "); + +static const OEMCHAR str_clockfmt[] = OEMTEXT("%d.%1dMHz"); +static const OEMCHAR str_memfmt[] = OEMTEXT("%3uKB"); +static const OEMCHAR str_memfmt2[] = OEMTEXT("%3uKB + %uKB"); +static const OEMCHAR str_memfmt3[] = OEMTEXT("%d.%1dMB"); +static const OEMCHAR str_twidth[] = OEMTEXT("width-%u"); +static const OEMCHAR str_dispclock[] = OEMTEXT("%u.%.2ukHz / %u.%uHz"); + +static const OEMCHAR str_pcm86a[] = OEMTEXT(" PCM: %dHz %dbit %s"); +static const OEMCHAR str_pcm86b[] = OEMTEXT(" %d / %d / 32768"); +static const OEMCHAR str_rhythm[] = OEMTEXT("BSCHTR"); + + +// ---- common + +static void info_ver(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + milstr_ncpy(str, np2version, maxlen); + (void)ex; +} + +static void info_cpu(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + +#if defined(NP2_WIN) +#if defined(CPUCORE_IA32) +#ifdef UNICODE + MultiByteToWideChar(CP_ACP, 0, i386cpuid.cpu_brandstring, -1, str, maxlen); +#else + milstr_ncpy(str, i386cpuid.cpu_brandstring, maxlen); +#endif + if(i386cpuid.allow_movCS){ + milstr_ncat(str, OEMTEXT(" (+MOV CS,xx)"), maxlen - OEMSTRLEN(str)); + } +#else + UINT family; +#if defined(CPU_FAMILY) + family = MIN(CPU_FAMILY, 6); +#else + family = (CPU_TYPE & CPUTYPE_V30)?1:2; +#endif + milstr_ncpy(str, milstr_list(str_cpu, family), maxlen); + +#endif +#endif + + (void)ex; +} + +static void info_clock(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + UINT32 clk; + OEMCHAR clockstr[64]; + + clk = (pccore.realclock + 50000) / 100000; + OEMSNPRINTF(clockstr, sizeof(clockstr), str_clockfmt, clk/10, clk % 10); + milstr_ncpy(str, clockstr, maxlen); + (void)ex; +} + +static void info_base(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + milstr_ncpy(str, + (pccore.cpumode & CPUMODE_8MHZ)?str_8MHz:str_5MHz, maxlen); + (void)ex; +} + +static void info_mem1(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + UINT memsize; + OEMCHAR memstr[64]; + + memsize = np2cfg.memsw[2] & 7; + if (memsize < 6) { + memsize = (memsize + 1) * 128; + } + else { + memsize = 640; + } + if (pccore.extmem) { + OEMSNPRINTF(memstr, sizeof(memstr), str_memfmt2, memsize, pccore.extmem * 1024); + } + else { + OEMSNPRINTF(memstr, sizeof(memstr), str_memfmt, memsize); + } + milstr_ncpy(str, memstr, maxlen); + (void)ex; +} + +static void info_mem2(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + UINT memsize; + OEMCHAR memstr[64]; + + memsize = np2cfg.memsw[2] & 7; + if (memsize < 6) { + memsize = (memsize + 1) * 128; + } + else { + memsize = 640; + } + memsize += pccore.extmem * 1024; + OEMSNPRINTF(memstr, sizeof(memstr), str_memfmt, memsize); + milstr_ncpy(str, memstr, maxlen); + (void)ex; +} + +static void info_mem3(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + UINT memsize; + OEMCHAR memstr[64]; + + memsize = np2cfg.memsw[2] & 7; + if (memsize < 6) { + memsize = (memsize + 1) * 128; + } + else { + memsize = 640; + } + if (pccore.extmem > 1) { + OEMSNPRINTF(memstr, sizeof(memstr), str_memfmt3, pccore.extmem, memsize / 100); + } + else { + OEMSNPRINTF(memstr, sizeof(memstr), str_memfmt, memsize); + } + milstr_ncpy(str, memstr, maxlen); + (void)ex; +} + +static void info_gdc(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + milstr_ncpy(str, milstr_list(str_grcgchip, grcg.chip & 3), maxlen); + milstr_ncat(str, str_2halfMHz + ((gdc.clock & 0x80)?2:0), maxlen); + (void)ex; +} + +static void info_gdc2(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + OEMCHAR textstr[64]; + + OEMSNPRINTF(textstr, sizeof(textstr), str_dispclock, + gdc.hclock / 1000, (gdc.hclock / 10) % 100, + gdc.vclock / 10, gdc.vclock % 10); + milstr_ncpy(str, textstr, maxlen); + (void)ex; +} + +static void info_text(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + +const OEMCHAR *p; + OEMCHAR textstr[128]; + + if (!(gdcs.textdisp & GDCSCRN_ENABLE)) { + p = str_disable; + } + else { + OEMSNPRINTF(textstr, sizeof(textstr), str_twidth, ((gdc.mode1 & 0x4)?40:80)); + p = textstr; + } + milstr_ncpy(str, p, maxlen); + (void)ex; +} + +static void info_grph(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + +const OEMCHAR *p; + UINT md; + UINT pg; + OEMCHAR work[32]; + + if (!(gdcs.grphdisp & GDCSCRN_ENABLE)) { + p = str_disable; + } + else { + md = (gdc.analog & (1 << GDCANALOG_16))?1:0; + pg = gdcs.access; +#if defined(SUPPORT_PC9821) + if (gdc.analog & (1 << (GDCANALOG_256))) { + md = 2; + if (gdc.analog & (1 << (GDCANALOG_256E))) { + pg = 2; + } + } +#endif + milstr_ncpy(work, milstr_list(str_vrammode, md), NELEMENTS(work)); + milstr_ncat(work, milstr_list(str_vrampage, pg), NELEMENTS(work)); + p = work; + } + milstr_ncpy(str, p, maxlen); + (void)ex; +} + +static void info_sound(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) +{ + const OEMCHAR *lpBoard; + + lpBoard = OEMTEXT("none"); + switch (g_nSoundID) + { + case SOUNDID_NONE: + break; + + case SOUNDID_PC_9801_14: + lpBoard = OEMTEXT("PC-9801-14"); + break; + + case SOUNDID_PC_9801_26K: + lpBoard = OEMTEXT("PC-9801-26"); + break; + + case SOUNDID_PC_9801_86: + lpBoard = OEMTEXT("PC-9801-86"); + break; + + case SOUNDID_PC_9801_86_26K: + lpBoard = OEMTEXT("PC-9801-26 + 86"); + break; + + case SOUNDID_PC_9801_118: + lpBoard = OEMTEXT("PC-9801-118"); + break; + + case SOUNDID_PC_9801_86_WSS: + lpBoard = OEMTEXT("PC-9801-86 + Mate-X PCM"); + break; + + case SOUNDID_PC_9801_86_118: + lpBoard = OEMTEXT("PC-9801-86 + PC-9801-118"); + break; + + case SOUNDID_MATE_X_PCM: + lpBoard = OEMTEXT("Mate-X PCM"); + break; + + case SOUNDID_PC_9801_86_ADPCM: + lpBoard = OEMTEXT("PC-9801-86 + Chibi-oto"); + break; + + case SOUNDID_WAVESTAR: + lpBoard = OEMTEXT("Wave Star"); + break; + + case SOUNDID_SPEAKBOARD: + lpBoard = OEMTEXT("Speak board"); + break; + + case SOUNDID_86_SPEAKBOARD: + lpBoard = OEMTEXT("PC-9801-86 + Speak board"); + break; + + case SOUNDID_SPARKBOARD: + lpBoard = OEMTEXT("Spark board"); + break; + + case SOUNDID_AMD98: + lpBoard = OEMTEXT("AMD-98"); + break; + + case SOUNDID_SOUNDORCHESTRA: + lpBoard = OEMTEXT("SOUND ORCHESTRA"); + break; + + case SOUNDID_SOUNDORCHESTRAV: + lpBoard = OEMTEXT("SOUND ORCHESTRA-V"); + break; + + case SOUNDID_LITTLEORCHESTRAL: + lpBoard = OEMTEXT("LITTLE ORCHESTRA L"); + break; + + case SOUNDID_MMORCHESTRA: + lpBoard = OEMTEXT("MULTIMEDIA ORCHESTRA"); + break; + +#if defined(SUPPORT_SOUND_SB16) + case SOUNDID_SB16: + lpBoard = OEMTEXT("Sound Blaster 16"); + break; + + case SOUNDID_PC_9801_86_SB16: + lpBoard = OEMTEXT("PC-9801-86 + Sound Blaster 16"); + break; + + case SOUNDID_WSS_SB16: + lpBoard = OEMTEXT("Mate-X PCM + Sound Blaster 16"); + break; + + case SOUNDID_PC_9801_86_WSS_SB16: + lpBoard = OEMTEXT("PC-9801-86 + Mate-X PCM + Sound Blaster 16"); + break; + + case SOUNDID_PC_9801_118_SB16: + lpBoard = OEMTEXT("PC-9801-118 + Sound Blaster 16"); + break; + + case SOUNDID_PC_9801_86_118_SB16: + lpBoard = OEMTEXT("PC-9801-86 + PC-9801-118 + Sound Blaster 16"); + break; +#endif // defined(SUPPORT_SOUND_SB16) + +#if defined(SUPPORT_PX) + case SOUNDID_PX1: + lpBoard = OEMTEXT("Otomi-chanx2"); + break; + + case SOUNDID_PX2: + lpBoard = OEMTEXT("Otomi-chanx2 + 86"); + break; +#endif // defined(SUPPORT_PX) + + default: + lpBoard = OEMTEXT("unknown"); + break; + } + milstr_ncpy(str, lpBoard, maxlen); + (void)ex; +} + +static void info_extsnd(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + OEMCHAR buf[128]; + + info_sound(str, maxlen, ex); + if (g_nSoundID & 4) { + milstr_ncat(str, ex->cr, maxlen); + OEMSNPRINTF(buf, sizeof(buf), str_pcm86a, + pcm86rate8[g_pcm86.fifo & 7] >> 3, + (16 - ((g_pcm86.dactrl >> 3) & 8)), + milstr_list(str_chpan, (g_pcm86.dactrl >> 4) & 3)); + milstr_ncat(str, buf, maxlen); + milstr_ncat(str, ex->cr, maxlen); + OEMSNPRINTF(buf, sizeof(buf), str_pcm86b, g_pcm86.virbuf, g_pcm86.fifosize); + milstr_ncat(str, buf, maxlen); + } +} + +static void info_bios(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + str[0] = '\0'; + if (pccore.rom & PCROM_BIOS) { + milstr_ncat(str, str_biosrom, maxlen); + } + if (soundrom.name[0]) { + if (str[0]) { + milstr_ncat(str, str_comma, maxlen); + } + milstr_ncat(str, soundrom.name, maxlen); + } +#if defined(SUPPORT_IDEIO) + if (ideio.bios) { + if (str[0]) { + milstr_ncat(str, str_comma, maxlen); + } + milstr_ncat(str, ideio.biosname, maxlen); + } +#endif +#if defined(SUPPORT_PCI) + if (pcidev.biosname[0]) { + if (str[0]) { + milstr_ncat(str, str_comma, maxlen); + } + milstr_ncat(str, pcidev.biosname, maxlen); + } +#endif +#if defined(SUPPORT_GPIB) + if (gpib.enable) { + if (str[0]) { + milstr_ncat(str, str_comma, maxlen); + } + milstr_ncat(str, OEMTEXT("gpib.rom"), maxlen); + } +#endif + if (str[0] == '\0') { + milstr_ncat(str, str_notexist, maxlen); + } + (void)ex; +} + +static void info_rhythm(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + OEMCHAR rhythmstr[8]; + UINT exist; + UINT i; + + exist = rhythm_getcaps(); + milstr_ncpy(rhythmstr, str_rhythm, NELEMENTS(rhythmstr)); + for (i=0; i<6; i++) { + if (!(exist & (1 << i))) { + rhythmstr[i] = '_'; + } + } + milstr_ncpy(str, rhythmstr, maxlen); + (void)ex; +} + +static void info_display(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + UINT bpp; + OEMCHAR buf[128] = {0}; + + bpp = scrnmng_getbpp(); + milstr_ncpy(str, milstr_list(str_winclr, ((bpp >> 3) - 1) & 3), maxlen); +// OEMSNPRINTF(buf, sizeof(buf), OEMTEXT(" %dx%d"), scrnmngp->width, scrnmngp->height); +// milstr_ncat(str, buf, maxlen); + milstr_ncat(str, milstr_list(str_winmode, (scrnmng_isfullscreen())?1:0), + maxlen); + (void)ex; +} + +static void info_fpu(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + +#if defined(CPUCORE_IA32) + if(i386cpuid.cpu_feature & CPU_FEATURE_FPU){ + if(i386cpuid.fpu_type < 3){ + milstr_ncpy(str, milstr_list(str_fpu, 1+i386cpuid.fpu_type), maxlen); + }else{ + milstr_ncpy(str, OEMTEXT(" unknown"), maxlen); + } + }else +#endif + { + milstr_ncpy(str, milstr_list(str_fpu, 0), maxlen); + } +} + +static void info_simd(OEMCHAR *str, int maxlen, const NP2INFOEX *ex) { + + int simdcount = 0; + milstr_ncpy(str, OEMTEXT(" "), maxlen); +#if defined(CPUCORE_IA32) + if(i386cpuid.cpu_feature & CPU_FEATURE_MMX){ + milstr_ncat(str, str_simd_mmx, maxlen); + simdcount++; + } + if(i386cpuid.cpu_feature & CPU_FEATURE_SSE){ + milstr_ncat(str, str_simd_sse, maxlen); + simdcount++; + } + if(i386cpuid.cpu_feature & CPU_FEATURE_SSE2){ + milstr_ncat(str, str_simd_sse2, maxlen); + simdcount++; + } + if(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSE3){ + milstr_ncat(str, str_simd_sse3, maxlen); + simdcount++; + } + if(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSSE3){ + milstr_ncat(str, str_simd_ssse3, maxlen); + simdcount++; + } + if(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSE4_1){ + milstr_ncat(str, str_simd_sse4_1, maxlen); + simdcount++; + } + if(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSE4_2){ + milstr_ncat(str, str_simd_sse4_2, maxlen); + simdcount++; + } + if(i386cpuid.cpu_feature_ex & CPU_FEATURE_EX_3DNOW){ + milstr_ncat(str, str_simd_3dnow, maxlen); + simdcount++; + } + if(i386cpuid.cpu_feature_ex & CPU_FEATURE_EX_E3DNOW){ + milstr_ncat(str, str_simd_e3dnow, maxlen); + simdcount++; + } +#endif + if(simdcount==0){ + milstr_ncat(str, OEMTEXT("none"), maxlen); + } +} + + +// ---- make string + +typedef struct { + OEMCHAR key[8]; + void (*proc)(OEMCHAR *str, int maxlen, const NP2INFOEX *ex); +} INFOPROC; + +static const INFOPROC infoproc[] = { + {OEMTEXT("VER"), info_ver}, + {OEMTEXT("CPU"), info_cpu}, + {OEMTEXT("CLOCK"), info_clock}, + {OEMTEXT("BASE"), info_base}, + {OEMTEXT("MEM1"), info_mem1}, + {OEMTEXT("MEM2"), info_mem2}, + {OEMTEXT("MEM3"), info_mem3}, + {OEMTEXT("FPU"), info_fpu}, + {OEMTEXT("SIMD"), info_simd}, + {OEMTEXT("GDC"), info_gdc}, + {OEMTEXT("GDC2"), info_gdc2}, + {OEMTEXT("TEXT"), info_text}, + {OEMTEXT("GRPH"), info_grph}, + {OEMTEXT("SND"), info_sound}, + {OEMTEXT("EXSND"), info_extsnd}, + {OEMTEXT("BIOS"), info_bios}, + {OEMTEXT("RHYTHM"), info_rhythm}, + {OEMTEXT("DISP"), info_display}}; + + +static BOOL defext(OEMCHAR *dst, const OEMCHAR *key, int maxlen, + const NP2INFOEX *ex) { + + milstr_ncpy(dst, key, maxlen); + (void)ex; + return(TRUE); +} + +void np2info(OEMCHAR *dst, const OEMCHAR *src, int maxlen, + const NP2INFOEX *ex) { + + NP2INFOEX statex; + OEMCHAR c; + UINT leng; + OEMCHAR infwork[12]; +const INFOPROC *inf; +const INFOPROC *infterm; + + if ((dst == NULL) || (maxlen <= 0) || (src == NULL)) { + return; + } + if (ex == NULL) { + milstr_ncpy(statex.cr, str_oscr, NELEMENTS(statex.cr)); + statex.ext = NULL; + } + else { + statex = *ex; + } + if (statex.ext == NULL) { + statex.ext = defext; + } + while(maxlen > 0) { + c = *src++; + if (c == '\0') { + break; + } + else if (c == '\n') { + milstr_ncpy(dst, statex.cr, maxlen); + } + else if (c != '%') { + *dst++ = c; + maxlen--; + continue; + } + else if (*src == '%') { + src++; + *dst++ = c; + maxlen--; + continue; + } + else { + leng = 0; + while(1) { + c = *src; + if (c == '\0') { + break; + } + src++; + if (c == '%') { + break; + } + if (leng < (NELEMENTS(infwork) - 1)) { + infwork[leng++] = c; + } + } + infwork[leng] = '\0'; + inf = infoproc; + infterm = infoproc + NELEMENTS(infoproc); + while(inf < infterm) { + if (!milstr_cmp(infwork, inf->key)) { + inf->proc(dst, maxlen, &statex); + break; + } + inf++; + } + if (inf >= infterm) { + if (!(*statex.ext)(dst, infwork, maxlen, &statex)) { + continue; + } + } + } + leng = (UINT)OEMSTRLEN(dst); + dst += leng; + maxlen -= leng; + } + *dst = '\0'; +} + diff --git a/generic/np2info.h b/generic/np2info.h old mode 100755 new mode 100644 index ed83eadc..ac21dc24 --- a/generic/np2info.h +++ b/generic/np2info.h @@ -1,22 +1,22 @@ - -struct _np2infoex; -typedef struct _np2infoex NP2INFOEX; - -struct _np2infoex { - OEMCHAR cr[4]; - BOOL (*ext)(OEMCHAR *dst, const OEMCHAR *key, int maxlen, - const NP2INFOEX *ex); -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -void np2info(OEMCHAR *dst, const OEMCHAR *src, int maxlen, - const NP2INFOEX *ex); - -#ifdef __cplusplus -} -#endif - + +struct _np2infoex; +typedef struct _np2infoex NP2INFOEX; + +struct _np2infoex { + OEMCHAR cr[4]; + BOOL (*ext)(OEMCHAR *dst, const OEMCHAR *key, int maxlen, + const NP2INFOEX *ex); +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +void np2info(OEMCHAR *dst, const OEMCHAR *src, int maxlen, + const NP2INFOEX *ex); + +#ifdef __cplusplus +} +#endif + diff --git a/generic/readme.txt b/generic/readme.txt old mode 100755 new mode 100644 index 47379d42..0eb3a8c0 --- a/generic/readme.txt +++ b/generic/readme.txt @@ -1,7 +1,7 @@ - - 一般的な奴。 - - keydispとか - hostdrvとかもここ? - ジャストサウンド?(汗; - + + 一般的な奴。 + + keydispとか + hostdrvとかもここ? + ジャストサウンド?(汗; + diff --git a/generic/softkbd.c b/generic/softkbd.c old mode 100755 new mode 100644 index fd5b9d07..4130fc84 --- a/generic/softkbd.c +++ b/generic/softkbd.c @@ -1,155 +1,155 @@ -#include - -#if defined(SUPPORT_SOFTKBD) - -#include -#include -#include - - -#define SOFTKEY_MENU 0xfe -#define SOFTKEY_NC 0xff - - -typedef struct { - UINT8 key; - UINT8 key2; - UINT8 led; - UINT8 flag; - void *ptr; - CMNBMP bmp; - CMNPAL pal[16]; -} SOFTKBD; - -static SOFTKBD softkbd; - -#if (SUPPORT_SOFTKBD == 1) -#if defined(NP2_SIZE_QVGA) -#include "softkbd1.res" -#else -#include "softkbd2.res" -#endif -#elif (SUPPORT_SOFTKBD == 2) -#error not support (SUPPORT_SOFTKBD == 2) -#else -#if !defined(SUPPORT_PC9801_119) -#include "softkbd.res" -#else -#include "softkbd3.res" -#endif -#endif - - -static void loadbmp(const char *filename) { - - void *ptr; - - softkbd.ptr = NULL; - ptr = (void *)bmpdata_solvedata(np2kbd_bmp); - if (ptr != NULL) { - if (cmndraw_bmp4inf(&softkbd.bmp, ptr) == SUCCESS) { - softkbd.ptr = ptr; - } - else { - _MFREE(ptr); - } - } - softkbd.flag |= SOFTKEY_FLAGREDRAW; - (void)filename; -} - -void softkbd_initialize(void) { - - softkbd.key = SOFTKEY_NC; - softkbd.led = 0; - loadbmp(NULL); -} - -void softkbd_deinitialize(void) { - - void *ptr; - - ptr = softkbd.ptr; - softkbd.ptr = NULL; - if (ptr) { - _MFREE(ptr); - } -} - -BRESULT softkbd_getsize(int *width, int *height) { - - if (softkbd.ptr == NULL) { - return(FAILURE); - } - if (width) { - *width = softkbd.bmp.width; - } - if (height) { - *height = softkbd.bmp.height; - } - return(SUCCESS); -} - -REG8 softkbd_process(void) { - - return(softkbd.flag); -} - -BOOL softkbd_paint(CMNVRAM *vram, CMNPALCNV cnv, BOOL redraw) { - - UINT8 flag; - BOOL ret; - - flag = softkbd.flag; - softkbd.flag = 0; - if (redraw) { - flag = SOFTKEY_FLAGREDRAW | SOFTKEY_FLAGDRAW; - } - ret = FALSE; - if ((flag & SOFTKEY_FLAGREDRAW) && (vram) && (cnv)) { - (*cnv)(softkbd.pal, softkbd.bmp.paltbl, softkbd.bmp.pals, vram->bpp); - cmndraw_bmp16(vram, softkbd.ptr, cnv, CMNBMP_LEFT | CMNBMP_TOP); - ret = TRUE; - } - if (flag & SOFTKEY_FLAGDRAW) { - TRACEOUT(("softkbd_paint")); - ledpaint(vram); - ret = TRUE; - } - return(ret); -} - -BOOL softkbd_down(int x, int y) { - - UINT8 key; - - softkbd_up(); - key = getsoftkbd(x, y); - if (key == SOFTKEY_MENU) { - return(TRUE); - } - else if (key != SOFTKEY_NC) { - keystat_down(&key, 1, NKEYREF_SOFTKBD); - softkbd.key = key; - } - return(FALSE); -} - -void softkbd_up(void) { - - if (softkbd.key != SOFTKEY_NC) { - keystat_up(&softkbd.key, 1, NKEYREF_SOFTKBD); - softkbd.key = SOFTKEY_NC; - } -} - -void softkbd_led(REG8 led) { - - TRACEOUT(("softkbd_led(%x)", led)); - if (softkbd.led != led) { - softkbd.led = led; - softkbd.flag |= SOFTKEY_FLAGDRAW; - } -} -#endif - +#include + +#if defined(SUPPORT_SOFTKBD) + +#include +#include +#include + + +#define SOFTKEY_MENU 0xfe +#define SOFTKEY_NC 0xff + + +typedef struct { + UINT8 key; + UINT8 key2; + UINT8 led; + UINT8 flag; + void *ptr; + CMNBMP bmp; + CMNPAL pal[16]; +} SOFTKBD; + +static SOFTKBD softkbd; + +#if (SUPPORT_SOFTKBD == 1) +#if defined(NP2_SIZE_QVGA) +#include "softkbd1.res" +#else +#include "softkbd2.res" +#endif +#elif (SUPPORT_SOFTKBD == 2) +#error not support (SUPPORT_SOFTKBD == 2) +#else +#if !defined(SUPPORT_PC9801_119) +#include "softkbd.res" +#else +#include "softkbd3.res" +#endif +#endif + + +static void loadbmp(const char *filename) { + + void *ptr; + + softkbd.ptr = NULL; + ptr = (void *)bmpdata_solvedata(np2kbd_bmp); + if (ptr != NULL) { + if (cmndraw_bmp4inf(&softkbd.bmp, ptr) == SUCCESS) { + softkbd.ptr = ptr; + } + else { + _MFREE(ptr); + } + } + softkbd.flag |= SOFTKEY_FLAGREDRAW; + (void)filename; +} + +void softkbd_initialize(void) { + + softkbd.key = SOFTKEY_NC; + softkbd.led = 0; + loadbmp(NULL); +} + +void softkbd_deinitialize(void) { + + void *ptr; + + ptr = softkbd.ptr; + softkbd.ptr = NULL; + if (ptr) { + _MFREE(ptr); + } +} + +BRESULT softkbd_getsize(int *width, int *height) { + + if (softkbd.ptr == NULL) { + return(FAILURE); + } + if (width) { + *width = softkbd.bmp.width; + } + if (height) { + *height = softkbd.bmp.height; + } + return(SUCCESS); +} + +REG8 softkbd_process(void) { + + return(softkbd.flag); +} + +BOOL softkbd_paint(CMNVRAM *vram, CMNPALCNV cnv, BOOL redraw) { + + UINT8 flag; + BOOL ret; + + flag = softkbd.flag; + softkbd.flag = 0; + if (redraw) { + flag = SOFTKEY_FLAGREDRAW | SOFTKEY_FLAGDRAW; + } + ret = FALSE; + if ((flag & SOFTKEY_FLAGREDRAW) && (vram) && (cnv)) { + (*cnv)(softkbd.pal, softkbd.bmp.paltbl, softkbd.bmp.pals, vram->bpp); + cmndraw_bmp16(vram, softkbd.ptr, cnv, CMNBMP_LEFT | CMNBMP_TOP); + ret = TRUE; + } + if (flag & SOFTKEY_FLAGDRAW) { + TRACEOUT(("softkbd_paint")); + ledpaint(vram); + ret = TRUE; + } + return(ret); +} + +BOOL softkbd_down(int x, int y) { + + UINT8 key; + + softkbd_up(); + key = getsoftkbd(x, y); + if (key == SOFTKEY_MENU) { + return(TRUE); + } + else if (key != SOFTKEY_NC) { + keystat_down(&key, 1, NKEYREF_SOFTKBD); + softkbd.key = key; + } + return(FALSE); +} + +void softkbd_up(void) { + + if (softkbd.key != SOFTKEY_NC) { + keystat_up(&softkbd.key, 1, NKEYREF_SOFTKBD); + softkbd.key = SOFTKEY_NC; + } +} + +void softkbd_led(REG8 led) { + + TRACEOUT(("softkbd_led(%x)", led)); + if (softkbd.led != led) { + softkbd.led = led; + softkbd.flag |= SOFTKEY_FLAGDRAW; + } +} +#endif + diff --git a/generic/softkbd.h b/generic/softkbd.h old mode 100755 new mode 100644 index 9bf9871c..4d957cb9 --- a/generic/softkbd.h +++ b/generic/softkbd.h @@ -1,36 +1,36 @@ - -#if defined(SUPPORT_SOFTKBD) - -#include - -enum { - LEDFLAG_NUM = 0x01, - LEDFLAG_CAPS = 0x04, - LEDFLAG_KANA = 0x08 -}; - -enum { - SOFTKEY_FLAGDRAW = 0x01, - SOFTKEY_FLAGREDRAW = 0x02 -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -void softkbd_initialize(void); -void softkbd_deinitialize(void); -BRESULT softkbd_getsize(int *width, int *height); -REG8 softkbd_process(void); -BOOL softkbd_paint(CMNVRAM *vram, CMNPALCNV cnv, BOOL redraw); -BOOL softkbd_down(int x, int y); -void softkbd_up(void); -void softkbd_led(REG8 led); - -#ifdef __cplusplus -} -#endif - -#endif - + +#if defined(SUPPORT_SOFTKBD) + +#include + +enum { + LEDFLAG_NUM = 0x01, + LEDFLAG_CAPS = 0x04, + LEDFLAG_KANA = 0x08 +}; + +enum { + SOFTKEY_FLAGDRAW = 0x01, + SOFTKEY_FLAGREDRAW = 0x02 +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +void softkbd_initialize(void); +void softkbd_deinitialize(void); +BRESULT softkbd_getsize(int *width, int *height); +REG8 softkbd_process(void); +BOOL softkbd_paint(CMNVRAM *vram, CMNPALCNV cnv, BOOL redraw); +BOOL softkbd_down(int x, int y); +void softkbd_up(void); +void softkbd_led(REG8 led); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/generic/unasm.c b/generic/unasm.c old mode 100755 new mode 100644 index f6a985a8..570a6a9f --- a/generic/unasm.c +++ b/generic/unasm.c @@ -1,591 +1,591 @@ -#include -#include -#include "unasmdef.tbl" -#include "unasmstr.tbl" -#include "unasmop3.tbl" -#include "unasmop.tbl" -#include "unasmop8.tbl" -#include "unasmfpu.tbl" - - -static const char strhex[] = "0123456789abcdef"; - -static char *set_str(char *p, const char *string) { - - char c; - - while(1) { - c = *string++; - if (c == '\0') { - break; - } - *p++ = c; - } - return(p); -} - -static char *set_reg(char *p, UINT reg) { - -const char *r; - - r = rstr.reg[0][reg]; - p[0] = r[0]; - p[1] = r[1]; - p += 2; - if (r[2]) { - *p++ = r[2]; - if (r[3]) { - *p++ = r[3]; - } - } - return(p); -} - -static char *set_shex(char *str, UINT32 value, UINT bit) { - - if (!(value & (1 << (bit - 1)))) { - *str++ = '+'; - } - else { - *str++ = '-'; - value = 0 - value; - } - do { - bit -= 4; - *str++ = strhex[(value >> bit) & 15]; - } while(bit); - return(str); -} - -static char *set_hex(char *str, UINT32 value, UINT bit) { - - do { - bit -= 4; - *str++ = strhex[(value >> bit) & 15]; - } while(bit); - return(str); -} - -// ---- - -UINT unasm(UNASM r, const UINT8 *ptr, UINT leng, BOOL d, UINT32 addr) { - -const UINT8 *org; -const UINT8 *term; - UINT flag; - REG8 ope; - UINT32 ctl; - char *p; - UINT type; - UINT mnemonic; - UINT regtype; - UINT f; - _UNASM una; - - if (r == NULL) { - r = &una; - } - - org = ptr; - term = ptr + leng; - flag = 0; - if (ptr >= term) { - return(0); - } - ope = *ptr++; - ctl = optbl[ope]; - if (ctl & 1) { - do { - if (ptr >= term) { - return(0); - } - ope = *ptr++; // next - - type = (ctl >> 1) & 7; - ctl >>= 4; - switch(type) { - case OPF_SOR: - flag &= ~(UAFLAG_SOMASK << UAFLAG_SOR); - flag += ctl << UAFLAG_SOR; - ctl = optbl[ope]; - break; - - case OPF_REP: - flag &= ~(UAFLAG_REPMASK << UAFLAG_REP); - flag += ctl << UAFLAG_REP; - ctl = optbl[ope]; - break; - - case OPF_OPE: - flag |= 1 << UAFLAG_OPE; - ctl = optbl[ope]; - break; - - case OPF_ADDR: - flag |= 1 << UAFLAG_ADDR; - ctl = optbl[ope]; - break; - - case OPF_286: - ctl = op8tbl[ope]; - break; - - case OPF_OP3: - ctl = op3tbl[ctl][(ope >> 3) & 7]; - break; - - case OPF_FPU: - if (ope < 0xc0) { - ctl = opefpu1[ctl][(ope >> 3) & 7]; - } - else { - ctl = opefpu2[ctl][ope - 0xc0]; - } - break; - } - } while(ctl & 1); - } - if (d) { - flag ^= (1 << UAFLAG_D) + (1 << UAFLAG_OPE) + (1 << UAFLAG_ADDR); - } - - if (ctl & 0x10) { - if (ptr >= term) { - return(0); - } - ope = *ptr++; - } - if (!(ctl & 0x20)) { - regtype = (flag << (3 - UAFLAG_OPE)) & 8; - } - else { - regtype = RSTR_8 << 3; - flag |= (1 << UAFLAG_8BIT); - } - - mnemonic = (ctl >> 7) & 0x1ff; - type = (ctl >> 16) & 0x3f; - ctl >>= 22; - p = r->operand; - -opeana_st: - switch(type) { - case 0: - goto opeana_ed; - - case OP_CL: - p[0] = 'c'; - p[1] = 'l'; - p += 2; - break; - - case OP_1: - *p++ = '1'; - break; - - case OP_I8: - if (ptr >= term) { - return(0); - } - p = set_hex(p, *ptr++, 8); - break; - - case OP_IS8: - if (ptr >= term) { - return(0); - } - p = set_shex(p, *ptr++, 8); - break; - - case OP_I16: - ptr += 2; - if (ptr > term) { - return(0); - } - p = set_hex(p, LOADINTELWORD(ptr - 2), 16); - break; - - case OP_IMM: - if (flag & (1 << UAFLAG_8BIT)) { - if (ptr >= term) { - return(0); - } - p = set_hex(p, *ptr++, 8); - } - else if (!(flag & (1 << UAFLAG_OPE))) { - ptr += 2; - if (ptr > term) { - return(0); - } - p = set_hex(p, LOADINTELWORD(ptr - 2), 16); - } - else { - ptr += 4; - if (ptr > term) { - return(0); - } - p = set_hex(p, LOADINTELDWORD(ptr - 4), 32); - } - break; - - case OP_EA: - if (ope >= 0xc0) { - p = set_reg(p, regtype + (ope & 7)); - break; - } -opeana_ea: - f = (flag >> UAFLAG_SOR) & UAFLAG_SOMASK; - if (f) { - p[0] = rstr.reg[RSTR_SEG][f - 1][0]; - p[1] = rstr.reg[RSTR_SEG][f - 1][1]; - p[2] = ':'; - p += 3; - } - *p++ = '['; - if (!(flag & (1 << UAFLAG_ADDR))) { - if ((ope & 0xc7) != 0x06) { - p = set_str(p, rstr.lea[ope & 7]); - switch(ope & 0xc0) { - case 0x40: - if (ptr >= term) { - return(0); - } - p = set_shex(p, *ptr++, 8); - break; - - case 0x80: - ptr += 2; - if (ptr > term) { - return(0); - } - *p++ = '+'; - p = set_hex(p, LOADINTELWORD(ptr - 2), 16); - break; - } - } - else { - ptr += 2; - if (ptr > term) { - return(0); - } - p = set_hex(p, LOADINTELWORD(ptr - 2), 16); - } - } - else { - if ((ope & 7) != 4) { - f = ope & 0xc7; - } - else { - if (ptr >= term) { - return(0); - } - f = (ptr[0] >> 3) & 7; - if (f != 4) { - p = set_str(p, rstr.reg[RSTR_32][f]); - if (ptr[0] & 0xc0) { - p[0] = '*'; - p[1] = (char)('0' + (1 << (ptr[0] >> 6))); - p += 2; - } - *p++ = '+'; - } - f = (ope & 0xc0) + (ptr[0] & 7); - ptr++; - } - if (f != 0x05) { - p = set_str(p, rstr.reg[RSTR_32][f & 7]); - switch(f & 0xc0) { - case 0x40: - if (ptr >= term) { - return(0); - } - p = set_shex(p, *ptr++, 8); - break; - - case 0x80: - ptr += 4; - if (ptr > term) { - return(0); - } - *p++ = '+'; - p = set_hex(p, LOADINTELDWORD(ptr - 4), 32); - break; - } - } - else { - ptr += 4; - if (ptr > term) { - return(0); - } - p = set_hex(p, LOADINTELDWORD(ptr - 4), 32); - } - } - *p++ = ']'; - break; - - case OP_PEA: - if (ope >= 0xc0) { - p = set_reg(p, regtype + (ope & 7)); - break; - } - p = set_str(p, rstr.ptr[regtype >> 3]); - goto opeana_ea; - - case OP_REG: - p = set_reg(p, regtype + ((ope >> 3) & 7)); - break; - - case OP_SEG: - p = set_str(p, rstr.reg[RSTR_SEG][(ope >> 3) & 7]); - break; - - case OP_MEM: - f = (flag >> UAFLAG_SOR) & UAFLAG_SOMASK; - if (f) { - p[0] = rstr.reg[RSTR_SEG][f - 1][0]; - p[1] = rstr.reg[RSTR_SEG][f - 1][1]; - p[2] = ':'; - p += 3; - } - *p++ = '['; - if (!(flag & (1 << UAFLAG_D))) { - ptr += 2; - if (ptr > term) { - return(0); - } - p = set_hex(p, LOADINTELWORD(ptr - 2), 16); - } - else { - ptr += 4; - if (ptr > term) { - return(0); - } - p = set_hex(p, LOADINTELDWORD(ptr - 4), 32); - } - *p++ = ']'; - break; - - case OP_AX: - p = set_reg(p, regtype); - break; - - case OP_DX: - p[0] = 'd'; - p[1] = 'x'; - p += 2; - break; - - case OP_MR: - p = set_reg(p, regtype + (ope & 7)); - break; - - case OP1_32: - mnemonic += ((flag >> UAFLAG_OPE) & 1); - break; - - case OP1_3: - *p++ = '3'; - break; - - case OP1_STR: - mnemonic += (regtype >> 3); - f = (flag >> UAFLAG_REP) & UAFLAG_REPMASK; - if (f) { - p = set_str(p, rstr.ope[mnemonic]); - mnemonic = RSTR_REP + (f - 1); - } - f = (flag >> UAFLAG_SOR) & UAFLAG_SOMASK; - if (f) { - p[0] = ' '; - p[1] = rstr.reg[RSTR_SEG][f - 1][0]; - p[1] = rstr.reg[RSTR_SEG][f - 1][1]; - p[3] = ':'; - p += 4; - } - break; - - case OP1_JCXZ: - mnemonic += ((flag >> UAFLAG_OPE) & 1); - - case OP1_SHORT: - if (ptr >= term) { - return(0); - } - addr += (SINT32)(SINT8)(*ptr++); - addr += (int)(ptr - org); - p = set_hex(p, addr, (flag & (1 << UAFLAG_D))?32:16); - break; - - case OP1_NEAR: - if (!(flag & (1 << UAFLAG_D))) { - ptr += 2; - if (ptr > term) { - return(0); - } - addr += LOADINTELWORD(ptr - 2); - addr += (int)(ptr - org); - p = set_hex(p, addr, 16); - } - else { - ptr += 4; - if (ptr > term) { - return(0); - } - addr += LOADINTELDWORD(ptr - 4); - addr += (int)(ptr - org); - p = set_hex(p, addr, 32); - } - break; - - case OP1_FAR: - if (!(flag & (1 << UAFLAG_D))) { - ptr += 4; - if (ptr > term) { - return(0); - } - p = set_hex(p, LOADINTELWORD(ptr - 2), 16); - *p++ = ':'; - p = set_hex(p, LOADINTELWORD(ptr - 4), 16); - } - else { - ptr += 6; - if (ptr > term) { - return(0); - } - p = set_hex(p, LOADINTELWORD(ptr - 2), 16); - *p++ = ':'; - p = set_hex(p, LOADINTELDWORD(ptr - 6), 32); - } - break; - - case OP1_I10: - if (ptr >= term) { - return(0); - } - if (*ptr != 10) { - p = set_hex(p, *ptr, 8); - } - ptr++; - break; - - case OP1_SOR: - f = (flag >> UAFLAG_SOR) & UAFLAG_SOMASK; - if (f) { - p[0] = rstr.reg[RSTR_SEG][f - 1][0]; - p[1] = rstr.reg[RSTR_SEG][f - 1][1]; - p[2] = ':'; - p += 3; - } - break; - - case OP1_FEA: - if (ope >= 0xc0) { // 有り得ないけど - p = set_reg(p, regtype + (ope & 7)); - break; - } - p = set_str(p, "far "); - goto opeana_ea; - - case OP1_REx: - p = set_reg(p, (RSTR_32 << 3) + (ope & 7)); - p[0] = ','; - p[1] = ' '; - p[2] = (char)mnemonic; - p[3] = 'r'; - p[4] = (char)('0' + ((ope >> 3) & 7)); - p += 5; - mnemonic = RSTR_MOV; - break; - - case OP1_ExR: - p[0] = (char)mnemonic; - p[1] = 'r'; - p[2] = (char)('0' + ((ope >> 3) & 7)); - p[3] = ','; - p[4] = ' '; - p += 5; - p = set_reg(p, (RSTR_32 << 3) + (ope & 7)); - mnemonic = RSTR_MOV; - break; - - case OP1_E2: - p = set_str(p, "word ptr "); - goto opeana_ea; - - case OP1_E4: - p = set_str(p, "dword ptr "); - goto opeana_ea; - - case OP1_E8: - p = set_str(p, "qword ptr "); - goto opeana_ea; - - case OP1_ET: - p = set_str(p, "tword ptr "); - goto opeana_ea; - - case OP1_ST: - p[0] = 's'; - p[1] = 't'; - p[2] = '('; - p[3] = (char)('0' + (ope & 7)); - p[4] = ')'; - p += 5; - break; - - case OP1_ST1: - p[0] = 's'; - p[1] = 't'; - p[2] = '('; - p[3] = (char)('0' + (ope & 7)); - p[4] = ')'; - p[5] = ','; - p[6] = ' '; - p[7] = 's'; - p[8] = 't'; - p += 9; - break; - - case OP1_ST2: - p[0] = 's'; - p[1] = 't'; - p[2] = ','; - p[3] = ' '; - p[4] = 's'; - p[5] = 't'; - p[6] = '('; - p[7] = (char)('0' + (ope & 7)); - p[8] = ')'; - p += 9; - break; - - case OE_MX0: - p = set_reg(p, regtype + ((ope >> 3) & 7)); - regtype = RSTR_8 << 3; - break; - - case OE_MX1: - p = set_reg(p, regtype + ((ope >> 3) & 7)); - regtype = RSTR_16 << 3; - break; - - default: - return(0); - } - type = ctl & 0x1f; - ctl >>= 5; - if (type) { - p[0] = ','; - p[1] = ' '; - p += 2; - goto opeana_st; - } - -opeana_ed: - if (mnemonic < NELEMENTS(rstr.ope)) { - r->mnemonic = rstr.ope[mnemonic]; - } - p[0] = '\0'; - return((UINT)(ptr - org)); -} - +#include +#include +#include "unasmdef.tbl" +#include "unasmstr.tbl" +#include "unasmop3.tbl" +#include "unasmop.tbl" +#include "unasmop8.tbl" +#include "unasmfpu.tbl" + + +static const char strhex[] = "0123456789abcdef"; + +static char *set_str(char *p, const char *string) { + + char c; + + while(1) { + c = *string++; + if (c == '\0') { + break; + } + *p++ = c; + } + return(p); +} + +static char *set_reg(char *p, UINT reg) { + +const char *r; + + r = rstr.reg[0][reg]; + p[0] = r[0]; + p[1] = r[1]; + p += 2; + if (r[2]) { + *p++ = r[2]; + if (r[3]) { + *p++ = r[3]; + } + } + return(p); +} + +static char *set_shex(char *str, UINT32 value, UINT bit) { + + if (!(value & (1 << (bit - 1)))) { + *str++ = '+'; + } + else { + *str++ = '-'; + value = 0 - value; + } + do { + bit -= 4; + *str++ = strhex[(value >> bit) & 15]; + } while(bit); + return(str); +} + +static char *set_hex(char *str, UINT32 value, UINT bit) { + + do { + bit -= 4; + *str++ = strhex[(value >> bit) & 15]; + } while(bit); + return(str); +} + +// ---- + +UINT unasm(UNASM r, const UINT8 *ptr, UINT leng, BOOL d, UINT32 addr) { + +const UINT8 *org; +const UINT8 *term; + UINT flag; + REG8 ope; + UINT32 ctl; + char *p; + UINT type; + UINT mnemonic; + UINT regtype; + UINT f; + _UNASM una; + + if (r == NULL) { + r = &una; + } + + org = ptr; + term = ptr + leng; + flag = 0; + if (ptr >= term) { + return(0); + } + ope = *ptr++; + ctl = optbl[ope]; + if (ctl & 1) { + do { + if (ptr >= term) { + return(0); + } + ope = *ptr++; // next + + type = (ctl >> 1) & 7; + ctl >>= 4; + switch(type) { + case OPF_SOR: + flag &= ~(UAFLAG_SOMASK << UAFLAG_SOR); + flag += ctl << UAFLAG_SOR; + ctl = optbl[ope]; + break; + + case OPF_REP: + flag &= ~(UAFLAG_REPMASK << UAFLAG_REP); + flag += ctl << UAFLAG_REP; + ctl = optbl[ope]; + break; + + case OPF_OPE: + flag |= 1 << UAFLAG_OPE; + ctl = optbl[ope]; + break; + + case OPF_ADDR: + flag |= 1 << UAFLAG_ADDR; + ctl = optbl[ope]; + break; + + case OPF_286: + ctl = op8tbl[ope]; + break; + + case OPF_OP3: + ctl = op3tbl[ctl][(ope >> 3) & 7]; + break; + + case OPF_FPU: + if (ope < 0xc0) { + ctl = opefpu1[ctl][(ope >> 3) & 7]; + } + else { + ctl = opefpu2[ctl][ope - 0xc0]; + } + break; + } + } while(ctl & 1); + } + if (d) { + flag ^= (1 << UAFLAG_D) + (1 << UAFLAG_OPE) + (1 << UAFLAG_ADDR); + } + + if (ctl & 0x10) { + if (ptr >= term) { + return(0); + } + ope = *ptr++; + } + if (!(ctl & 0x20)) { + regtype = (flag << (3 - UAFLAG_OPE)) & 8; + } + else { + regtype = RSTR_8 << 3; + flag |= (1 << UAFLAG_8BIT); + } + + mnemonic = (ctl >> 7) & 0x1ff; + type = (ctl >> 16) & 0x3f; + ctl >>= 22; + p = r->operand; + +opeana_st: + switch(type) { + case 0: + goto opeana_ed; + + case OP_CL: + p[0] = 'c'; + p[1] = 'l'; + p += 2; + break; + + case OP_1: + *p++ = '1'; + break; + + case OP_I8: + if (ptr >= term) { + return(0); + } + p = set_hex(p, *ptr++, 8); + break; + + case OP_IS8: + if (ptr >= term) { + return(0); + } + p = set_shex(p, *ptr++, 8); + break; + + case OP_I16: + ptr += 2; + if (ptr > term) { + return(0); + } + p = set_hex(p, LOADINTELWORD(ptr - 2), 16); + break; + + case OP_IMM: + if (flag & (1 << UAFLAG_8BIT)) { + if (ptr >= term) { + return(0); + } + p = set_hex(p, *ptr++, 8); + } + else if (!(flag & (1 << UAFLAG_OPE))) { + ptr += 2; + if (ptr > term) { + return(0); + } + p = set_hex(p, LOADINTELWORD(ptr - 2), 16); + } + else { + ptr += 4; + if (ptr > term) { + return(0); + } + p = set_hex(p, LOADINTELDWORD(ptr - 4), 32); + } + break; + + case OP_EA: + if (ope >= 0xc0) { + p = set_reg(p, regtype + (ope & 7)); + break; + } +opeana_ea: + f = (flag >> UAFLAG_SOR) & UAFLAG_SOMASK; + if (f) { + p[0] = rstr.reg[RSTR_SEG][f - 1][0]; + p[1] = rstr.reg[RSTR_SEG][f - 1][1]; + p[2] = ':'; + p += 3; + } + *p++ = '['; + if (!(flag & (1 << UAFLAG_ADDR))) { + if ((ope & 0xc7) != 0x06) { + p = set_str(p, rstr.lea[ope & 7]); + switch(ope & 0xc0) { + case 0x40: + if (ptr >= term) { + return(0); + } + p = set_shex(p, *ptr++, 8); + break; + + case 0x80: + ptr += 2; + if (ptr > term) { + return(0); + } + *p++ = '+'; + p = set_hex(p, LOADINTELWORD(ptr - 2), 16); + break; + } + } + else { + ptr += 2; + if (ptr > term) { + return(0); + } + p = set_hex(p, LOADINTELWORD(ptr - 2), 16); + } + } + else { + if ((ope & 7) != 4) { + f = ope & 0xc7; + } + else { + if (ptr >= term) { + return(0); + } + f = (ptr[0] >> 3) & 7; + if (f != 4) { + p = set_str(p, rstr.reg[RSTR_32][f]); + if (ptr[0] & 0xc0) { + p[0] = '*'; + p[1] = (char)('0' + (1 << (ptr[0] >> 6))); + p += 2; + } + *p++ = '+'; + } + f = (ope & 0xc0) + (ptr[0] & 7); + ptr++; + } + if (f != 0x05) { + p = set_str(p, rstr.reg[RSTR_32][f & 7]); + switch(f & 0xc0) { + case 0x40: + if (ptr >= term) { + return(0); + } + p = set_shex(p, *ptr++, 8); + break; + + case 0x80: + ptr += 4; + if (ptr > term) { + return(0); + } + *p++ = '+'; + p = set_hex(p, LOADINTELDWORD(ptr - 4), 32); + break; + } + } + else { + ptr += 4; + if (ptr > term) { + return(0); + } + p = set_hex(p, LOADINTELDWORD(ptr - 4), 32); + } + } + *p++ = ']'; + break; + + case OP_PEA: + if (ope >= 0xc0) { + p = set_reg(p, regtype + (ope & 7)); + break; + } + p = set_str(p, rstr.ptr[regtype >> 3]); + goto opeana_ea; + + case OP_REG: + p = set_reg(p, regtype + ((ope >> 3) & 7)); + break; + + case OP_SEG: + p = set_str(p, rstr.reg[RSTR_SEG][(ope >> 3) & 7]); + break; + + case OP_MEM: + f = (flag >> UAFLAG_SOR) & UAFLAG_SOMASK; + if (f) { + p[0] = rstr.reg[RSTR_SEG][f - 1][0]; + p[1] = rstr.reg[RSTR_SEG][f - 1][1]; + p[2] = ':'; + p += 3; + } + *p++ = '['; + if (!(flag & (1 << UAFLAG_D))) { + ptr += 2; + if (ptr > term) { + return(0); + } + p = set_hex(p, LOADINTELWORD(ptr - 2), 16); + } + else { + ptr += 4; + if (ptr > term) { + return(0); + } + p = set_hex(p, LOADINTELDWORD(ptr - 4), 32); + } + *p++ = ']'; + break; + + case OP_AX: + p = set_reg(p, regtype); + break; + + case OP_DX: + p[0] = 'd'; + p[1] = 'x'; + p += 2; + break; + + case OP_MR: + p = set_reg(p, regtype + (ope & 7)); + break; + + case OP1_32: + mnemonic += ((flag >> UAFLAG_OPE) & 1); + break; + + case OP1_3: + *p++ = '3'; + break; + + case OP1_STR: + mnemonic += (regtype >> 3); + f = (flag >> UAFLAG_REP) & UAFLAG_REPMASK; + if (f) { + p = set_str(p, rstr.ope[mnemonic]); + mnemonic = RSTR_REP + (f - 1); + } + f = (flag >> UAFLAG_SOR) & UAFLAG_SOMASK; + if (f) { + p[0] = ' '; + p[1] = rstr.reg[RSTR_SEG][f - 1][0]; + p[1] = rstr.reg[RSTR_SEG][f - 1][1]; + p[3] = ':'; + p += 4; + } + break; + + case OP1_JCXZ: + mnemonic += ((flag >> UAFLAG_OPE) & 1); + + case OP1_SHORT: + if (ptr >= term) { + return(0); + } + addr += (SINT32)(SINT8)(*ptr++); + addr += (int)(ptr - org); + p = set_hex(p, addr, (flag & (1 << UAFLAG_D))?32:16); + break; + + case OP1_NEAR: + if (!(flag & (1 << UAFLAG_D))) { + ptr += 2; + if (ptr > term) { + return(0); + } + addr += LOADINTELWORD(ptr - 2); + addr += (int)(ptr - org); + p = set_hex(p, addr, 16); + } + else { + ptr += 4; + if (ptr > term) { + return(0); + } + addr += LOADINTELDWORD(ptr - 4); + addr += (int)(ptr - org); + p = set_hex(p, addr, 32); + } + break; + + case OP1_FAR: + if (!(flag & (1 << UAFLAG_D))) { + ptr += 4; + if (ptr > term) { + return(0); + } + p = set_hex(p, LOADINTELWORD(ptr - 2), 16); + *p++ = ':'; + p = set_hex(p, LOADINTELWORD(ptr - 4), 16); + } + else { + ptr += 6; + if (ptr > term) { + return(0); + } + p = set_hex(p, LOADINTELWORD(ptr - 2), 16); + *p++ = ':'; + p = set_hex(p, LOADINTELDWORD(ptr - 6), 32); + } + break; + + case OP1_I10: + if (ptr >= term) { + return(0); + } + if (*ptr != 10) { + p = set_hex(p, *ptr, 8); + } + ptr++; + break; + + case OP1_SOR: + f = (flag >> UAFLAG_SOR) & UAFLAG_SOMASK; + if (f) { + p[0] = rstr.reg[RSTR_SEG][f - 1][0]; + p[1] = rstr.reg[RSTR_SEG][f - 1][1]; + p[2] = ':'; + p += 3; + } + break; + + case OP1_FEA: + if (ope >= 0xc0) { // 有り得ないけど + p = set_reg(p, regtype + (ope & 7)); + break; + } + p = set_str(p, "far "); + goto opeana_ea; + + case OP1_REx: + p = set_reg(p, (RSTR_32 << 3) + (ope & 7)); + p[0] = ','; + p[1] = ' '; + p[2] = (char)mnemonic; + p[3] = 'r'; + p[4] = (char)('0' + ((ope >> 3) & 7)); + p += 5; + mnemonic = RSTR_MOV; + break; + + case OP1_ExR: + p[0] = (char)mnemonic; + p[1] = 'r'; + p[2] = (char)('0' + ((ope >> 3) & 7)); + p[3] = ','; + p[4] = ' '; + p += 5; + p = set_reg(p, (RSTR_32 << 3) + (ope & 7)); + mnemonic = RSTR_MOV; + break; + + case OP1_E2: + p = set_str(p, "word ptr "); + goto opeana_ea; + + case OP1_E4: + p = set_str(p, "dword ptr "); + goto opeana_ea; + + case OP1_E8: + p = set_str(p, "qword ptr "); + goto opeana_ea; + + case OP1_ET: + p = set_str(p, "tword ptr "); + goto opeana_ea; + + case OP1_ST: + p[0] = 's'; + p[1] = 't'; + p[2] = '('; + p[3] = (char)('0' + (ope & 7)); + p[4] = ')'; + p += 5; + break; + + case OP1_ST1: + p[0] = 's'; + p[1] = 't'; + p[2] = '('; + p[3] = (char)('0' + (ope & 7)); + p[4] = ')'; + p[5] = ','; + p[6] = ' '; + p[7] = 's'; + p[8] = 't'; + p += 9; + break; + + case OP1_ST2: + p[0] = 's'; + p[1] = 't'; + p[2] = ','; + p[3] = ' '; + p[4] = 's'; + p[5] = 't'; + p[6] = '('; + p[7] = (char)('0' + (ope & 7)); + p[8] = ')'; + p += 9; + break; + + case OE_MX0: + p = set_reg(p, regtype + ((ope >> 3) & 7)); + regtype = RSTR_8 << 3; + break; + + case OE_MX1: + p = set_reg(p, regtype + ((ope >> 3) & 7)); + regtype = RSTR_16 << 3; + break; + + default: + return(0); + } + type = ctl & 0x1f; + ctl >>= 5; + if (type) { + p[0] = ','; + p[1] = ' '; + p += 2; + goto opeana_st; + } + +opeana_ed: + if (mnemonic < NELEMENTS(rstr.ope)) { + r->mnemonic = rstr.ope[mnemonic]; + } + p[0] = '\0'; + return((UINT)(ptr - org)); +} + diff --git a/generic/unasm.h b/generic/unasm.h old mode 100755 new mode 100644 index 2234a4c2..8f40b2c4 --- a/generic/unasm.h +++ b/generic/unasm.h @@ -1,17 +1,17 @@ - -typedef struct { -const char *mnemonic; - char operand[44]; -} _UNASM, *UNASM; - - -#ifdef __cplusplus -extern "C" { -#endif - -UINT unasm(UNASM r, const UINT8 *ptr, UINT leng, BOOL d, UINT32 addr); - -#ifdef __cplusplus -} -#endif - + +typedef struct { +const char *mnemonic; + char operand[44]; +} _UNASM, *UNASM; + + +#ifdef __cplusplus +extern "C" { +#endif + +UINT unasm(UNASM r, const UINT8 *ptr, UINT leng, BOOL d, UINT32 addr); + +#ifdef __cplusplus +} +#endif + diff --git a/i286c/cpumem.h b/i286c/cpumem.h old mode 100755 new mode 100644 index 878dac6f..97e5a874 --- a/i286c/cpumem.h +++ b/i286c/cpumem.h @@ -1,118 +1,118 @@ - -#pragma once - -#ifndef MEMCALL -#define MEMCALL -#endif - - -// 000000-0fffff メインメモリ -// 100000-10ffef HMA -// 10fff0-10ffff HIMEM -// 110000-193fff FONT-ROM/RAM -// 1a8000-1bffff VRAM1 -// 1c0000-1c7fff ITF-ROM BAK -// 1c8000-1dffff EPSON RAM -// 1e0000-1e7fff VRAM1 -// 1f8000-1fffff ITF-ROM - -#define USE_HIMEM 0x110000 - -enum { - VRAM_STEP = 0x100000, - VRAM_B = 0x0a8000, - VRAM_R = 0x0b0000, - VRAM_G = 0x0b8000, - VRAM_E = 0x0e0000, - - VRAM0_B = VRAM_B, - VRAM0_R = VRAM_R, - VRAM0_G = VRAM_G, - VRAM0_E = VRAM_E, - VRAM1_B = (VRAM_STEP + VRAM_B), - VRAM1_R = (VRAM_STEP + VRAM_R), - VRAM1_G = (VRAM_STEP + VRAM_G), - VRAM1_E = (VRAM_STEP + VRAM_E), - - FONT_ADRS = 0x110000, - ITF_ADRS = (VRAM_STEP + 0xf8000) -}; - -#define VRAMADDRMASKEX(a) ((a) & (VRAM_STEP | 0x7fff)) - - -#ifdef __cplusplus -extern "C" { -#endif - -extern UINT8 mem[0x200000]; - -void MEMCALL memm_arch(UINT type); -void MEMCALL memm_vram(UINT operate); - -REG8 MEMCALL memp_read8(UINT32 address); -REG16 MEMCALL memp_read16(UINT32 address); -UINT32 MEMCALL memp_read32(UINT32 address); -void MEMCALL memp_write8(UINT32 address, REG8 value); -void MEMCALL memp_write16(UINT32 address, REG16 value); -void MEMCALL memp_write32(UINT32 address, UINT32 value); - -void MEMCALL memp_reads(UINT32 address, void *dat, UINT leng); -void MEMCALL memp_writes(UINT32 address, const void *dat, UINT leng); - -REG8 MEMCALL memr_read8(UINT seg, UINT off); -REG16 MEMCALL memr_read16(UINT seg, UINT off); -void MEMCALL memr_write8(UINT seg, UINT off, REG8 value); -void MEMCALL memr_write16(UINT seg, UINT off, REG16 value); -void MEMCALL memr_reads(UINT seg, UINT off, void *dat, UINT leng); -void MEMCALL memr_writes(UINT seg, UINT off, const void *dat, UINT leng); - -#ifdef __cplusplus -} -#endif - - -// ---- Memory map - -#define MEMM_ARCH(t) memm_arch(t) -#define MEMM_VRAM(o) memm_vram(o) - - -// ---- Physical Space (DMA) - -#define MEMP_READ8(addr) \ - memp_read8((addr)) -#define MEMP_READ16(addr) \ - memp_read16((addr)) -#define MEMP_WRITE8(addr, dat) \ - memp_write8((addr), (dat)) - - -// ---- Logical Space (BIOS) - -#define MEML_READ8(addr) \ - memp_read8((addr)) -#define MEML_READ16(addr) \ - memp_read16((addr)) -#define MEML_WRITE8(addr, dat) \ - memp_write8((addr), (dat)) -#define MEML_WRITE16(addr, dat) \ - memp_write16((addr), (dat)) -#define MEML_READS(addr, dat, leng) \ - memp_reads((addr), (dat), (leng)) -#define MEML_WRITES(addr, dat, leng) \ - memp_writes((addr), (dat), (leng)) - -#define MEMR_READ8(seg, off) \ - memr_read8((seg), (off)) -#define MEMR_READ16(seg, off) \ - memr_read16((seg), (off)) -#define MEMR_WRITE8(seg, off, dat) \ - memr_write8((seg), (off), (dat)) -#define MEMR_WRITE16(seg, off, dat) \ - memr_write16((seg), (off), (dat)) -#define MEMR_READS(seg, off, dat, leng) \ - memr_reads((seg), (off), (dat), (leng)) -#define MEMR_WRITES(seg, off, dat, leng) \ - memr_writes((seg), (off), (dat), (leng)) - + +#pragma once + +#ifndef MEMCALL +#define MEMCALL +#endif + + +// 000000-0fffff メインメモリ +// 100000-10ffef HMA +// 10fff0-10ffff HIMEM +// 110000-193fff FONT-ROM/RAM +// 1a8000-1bffff VRAM1 +// 1c0000-1c7fff ITF-ROM BAK +// 1c8000-1dffff EPSON RAM +// 1e0000-1e7fff VRAM1 +// 1f8000-1fffff ITF-ROM + +#define USE_HIMEM 0x110000 + +enum { + VRAM_STEP = 0x100000, + VRAM_B = 0x0a8000, + VRAM_R = 0x0b0000, + VRAM_G = 0x0b8000, + VRAM_E = 0x0e0000, + + VRAM0_B = VRAM_B, + VRAM0_R = VRAM_R, + VRAM0_G = VRAM_G, + VRAM0_E = VRAM_E, + VRAM1_B = (VRAM_STEP + VRAM_B), + VRAM1_R = (VRAM_STEP + VRAM_R), + VRAM1_G = (VRAM_STEP + VRAM_G), + VRAM1_E = (VRAM_STEP + VRAM_E), + + FONT_ADRS = 0x110000, + ITF_ADRS = (VRAM_STEP + 0xf8000) +}; + +#define VRAMADDRMASKEX(a) ((a) & (VRAM_STEP | 0x7fff)) + + +#ifdef __cplusplus +extern "C" { +#endif + +extern UINT8 mem[0x200000]; + +void MEMCALL memm_arch(UINT type); +void MEMCALL memm_vram(UINT operate); + +REG8 MEMCALL memp_read8(UINT32 address); +REG16 MEMCALL memp_read16(UINT32 address); +UINT32 MEMCALL memp_read32(UINT32 address); +void MEMCALL memp_write8(UINT32 address, REG8 value); +void MEMCALL memp_write16(UINT32 address, REG16 value); +void MEMCALL memp_write32(UINT32 address, UINT32 value); + +void MEMCALL memp_reads(UINT32 address, void *dat, UINT leng); +void MEMCALL memp_writes(UINT32 address, const void *dat, UINT leng); + +REG8 MEMCALL memr_read8(UINT seg, UINT off); +REG16 MEMCALL memr_read16(UINT seg, UINT off); +void MEMCALL memr_write8(UINT seg, UINT off, REG8 value); +void MEMCALL memr_write16(UINT seg, UINT off, REG16 value); +void MEMCALL memr_reads(UINT seg, UINT off, void *dat, UINT leng); +void MEMCALL memr_writes(UINT seg, UINT off, const void *dat, UINT leng); + +#ifdef __cplusplus +} +#endif + + +// ---- Memory map + +#define MEMM_ARCH(t) memm_arch(t) +#define MEMM_VRAM(o) memm_vram(o) + + +// ---- Physical Space (DMA) + +#define MEMP_READ8(addr) \ + memp_read8((addr)) +#define MEMP_READ16(addr) \ + memp_read16((addr)) +#define MEMP_WRITE8(addr, dat) \ + memp_write8((addr), (dat)) + + +// ---- Logical Space (BIOS) + +#define MEML_READ8(addr) \ + memp_read8((addr)) +#define MEML_READ16(addr) \ + memp_read16((addr)) +#define MEML_WRITE8(addr, dat) \ + memp_write8((addr), (dat)) +#define MEML_WRITE16(addr, dat) \ + memp_write16((addr), (dat)) +#define MEML_READS(addr, dat, leng) \ + memp_reads((addr), (dat), (leng)) +#define MEML_WRITES(addr, dat, leng) \ + memp_writes((addr), (dat), (leng)) + +#define MEMR_READ8(seg, off) \ + memr_read8((seg), (off)) +#define MEMR_READ16(seg, off) \ + memr_read16((seg), (off)) +#define MEMR_WRITE8(seg, off, dat) \ + memr_write8((seg), (off), (dat)) +#define MEMR_WRITE16(seg, off, dat) \ + memr_write16((seg), (off), (dat)) +#define MEMR_READS(seg, off, dat, leng) \ + memr_reads((seg), (off), (dat), (leng)) +#define MEMR_WRITES(seg, off, dat, leng) \ + memr_writes((seg), (off), (dat), (leng)) + diff --git a/i286c/i286c.h b/i286c/i286c.h old mode 100755 new mode 100644 index 1cd3019a..8a762d16 --- a/i286c/i286c.h +++ b/i286c/i286c.h @@ -1,161 +1,161 @@ - -#define INTR_FAST - -// #define I286C_TEST -#if defined(I286C_TEST) -#undef MEMOPTIMIZE -#endif - - -#define I286_STAT i286core.s.r - -#define I286_REG i286core.s.r -#define I286_SEGREG i286core.s.r.w.es - -#define I286_AX i286core.s.r.w.ax -#define I286_BX i286core.s.r.w.bx -#define I286_CX i286core.s.r.w.cx -#define I286_DX i286core.s.r.w.dx -#define I286_SI i286core.s.r.w.si -#define I286_DI i286core.s.r.w.di -#define I286_BP i286core.s.r.w.bp -#define I286_SP i286core.s.r.w.sp -#define I286_CS i286core.s.r.w.cs -#define I286_DS i286core.s.r.w.ds -#define I286_ES i286core.s.r.w.es -#define I286_SS i286core.s.r.w.ss -#define I286_IP i286core.s.r.w.ip - -#define SEG_BASE i286core.s.es_base -#define ES_BASE i286core.s.es_base -#define CS_BASE i286core.s.cs_base -#define SS_BASE i286core.s.ss_base -#define DS_BASE i286core.s.ds_base -#define SS_FIX i286core.s.ss_fix -#define DS_FIX i286core.s.ds_fix - -#define I286_AL i286core.s.r.b.al -#define I286_BL i286core.s.r.b.bl -#define I286_CL i286core.s.r.b.cl -#define I286_DL i286core.s.r.b.dl -#define I286_AH i286core.s.r.b.ah -#define I286_BH i286core.s.r.b.bh -#define I286_CH i286core.s.r.b.ch -#define I286_DH i286core.s.r.b.dh - -#define I286_FLAG i286core.s.r.w.flag -#define I286_FLAGL i286core.s.r.b.flag_l -#define I286_FLAGH i286core.s.r.b.flag_h -#define I286_TRAP i286core.s.trap -#define I286_OV i286core.s.ovflag - -#define I286_GDTR i286core.s.GDTR -#define I286_IDTR i286core.s.IDTR -#define I286_LDTR i286core.s.LDTR -#define I286_LDTRC i286core.s.LDTRC -#define I286_TR i286core.s.TR -#define I286_TRC i286core.s.TRC -#define I286_MSW i286core.s.MSW - -#define I286_REMCLOCK i286core.s.remainclock -#define I286_BASECLOCK i286core.s.baseclock -#define I286_CLOCK i286core.s.clock -#define I286_ADRSMASK i286core.s.adrsmask - -#define I286_PREFIX i286core.s.prefix - -#define I286_INPADRS i286core.e.inport - - -#define I286FN static void -#define I286EXT void - -typedef void (*I286OP)(void); - -extern void CPUCALL i286c_intnum(UINT vect, REG16 IP); -extern UINT32 i286c_selector(UINT sel); - -#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) -extern void i286cea_initialize(void); -#endif - -extern const I286OP i286op[]; -extern const I286OP i286op_repe[]; -extern const I286OP i286op_repne[]; - -#define I286_0F static void CPUCALL -typedef void (CPUCALL * I286OP_0F)(UINT op); - -I286EXT i286c_cts(void); - - -#define I286_8X static void CPUCALL -typedef void (CPUCALL * I286OP8XREG8)(UINT8 *p); -typedef void (CPUCALL * I286OP8XEXT8)(UINT32 madr); -typedef void (CPUCALL * I286OP8XREG16)(UINT16 *p, UINT32 src); -typedef void (CPUCALL * I286OP8XEXT16)(UINT32 madr, UINT32 src); - -extern const I286OP8XREG8 c_op8xreg8_table[]; -extern const I286OP8XEXT8 c_op8xext8_table[]; -extern const I286OP8XREG16 c_op8xreg16_table[]; -extern const I286OP8XEXT16 c_op8xext16_table[]; - - -#define I286_SFT static void CPUCALL -typedef void (CPUCALL * I286OPSFTR8)(UINT8 *p); -typedef void (CPUCALL * I286OPSFTE8)(UINT32 madr); -typedef void (CPUCALL * I286OPSFTR16)(UINT16 *p); -typedef void (CPUCALL * I286OPSFTE16)(UINT32 madr); -typedef void (CPUCALL * I286OPSFTR8CL)(UINT8 *p, REG8 cl); -typedef void (CPUCALL * I286OPSFTE8CL)(UINT32 madr, REG8 cl); -typedef void (CPUCALL * I286OPSFTR16CL)(UINT16 *p, REG8 cl); -typedef void (CPUCALL * I286OPSFTE16CL)(UINT32 madr, REG8 cl); - -extern const I286OPSFTR8 sft_r8_table[]; -extern const I286OPSFTE8 sft_e8_table[]; -extern const I286OPSFTR16 sft_r16_table[]; -extern const I286OPSFTE16 sft_e16_table[]; -extern const I286OPSFTR8CL sft_r8cl_table[]; -extern const I286OPSFTE8CL sft_e8cl_table[]; -extern const I286OPSFTR16CL sft_r16cl_table[]; -extern const I286OPSFTE16CL sft_e16cl_table[]; - - -#define I286_F6 static void CPUCALL -typedef void (CPUCALL * I286OPF6)(UINT op); - -extern const I286OPF6 c_ope0xf6_table[]; -extern const I286OPF6 c_ope0xf7_table[]; - - -extern const I286OPF6 c_ope0xfe_table[]; -extern const I286OPF6 c_ope0xff_table[]; - - -extern I286EXT i286c_rep_insb(void); -extern I286EXT i286c_rep_insw(void); -extern I286EXT i286c_rep_outsb(void); -extern I286EXT i286c_rep_outsw(void); -extern I286EXT i286c_rep_movsb(void); -extern I286EXT i286c_rep_movsw(void); -extern I286EXT i286c_rep_lodsb(void); -extern I286EXT i286c_rep_lodsw(void); -extern I286EXT i286c_rep_stosb(void); -extern I286EXT i286c_rep_stosw(void); -extern I286EXT i286c_repe_cmpsb(void); -extern I286EXT i286c_repne_cmpsb(void); -extern I286EXT i286c_repe_cmpsw(void); -extern I286EXT i286c_repne_cmpsw(void); -extern I286EXT i286c_repe_scasb(void); -extern I286EXT i286c_repne_scasb(void); -extern I286EXT i286c_repe_scasw(void); -extern I286EXT i286c_repne_scasw(void); - - -#define i286_memoryread(a) memp_read8(a) -#define i286_memoryread_w(a) memp_read16(a) -#define i286_memoryread_d(a) memp_read32(a) -#define i286_memorywrite(a, v) memp_write8(a, v) -#define i286_memorywrite_w(a, v) memp_write16(a, v) -#define i286_memorywrite_d(a, v) memp_write32(a, v) - + +#define INTR_FAST + +// #define I286C_TEST +#if defined(I286C_TEST) +#undef MEMOPTIMIZE +#endif + + +#define I286_STAT i286core.s.r + +#define I286_REG i286core.s.r +#define I286_SEGREG i286core.s.r.w.es + +#define I286_AX i286core.s.r.w.ax +#define I286_BX i286core.s.r.w.bx +#define I286_CX i286core.s.r.w.cx +#define I286_DX i286core.s.r.w.dx +#define I286_SI i286core.s.r.w.si +#define I286_DI i286core.s.r.w.di +#define I286_BP i286core.s.r.w.bp +#define I286_SP i286core.s.r.w.sp +#define I286_CS i286core.s.r.w.cs +#define I286_DS i286core.s.r.w.ds +#define I286_ES i286core.s.r.w.es +#define I286_SS i286core.s.r.w.ss +#define I286_IP i286core.s.r.w.ip + +#define SEG_BASE i286core.s.es_base +#define ES_BASE i286core.s.es_base +#define CS_BASE i286core.s.cs_base +#define SS_BASE i286core.s.ss_base +#define DS_BASE i286core.s.ds_base +#define SS_FIX i286core.s.ss_fix +#define DS_FIX i286core.s.ds_fix + +#define I286_AL i286core.s.r.b.al +#define I286_BL i286core.s.r.b.bl +#define I286_CL i286core.s.r.b.cl +#define I286_DL i286core.s.r.b.dl +#define I286_AH i286core.s.r.b.ah +#define I286_BH i286core.s.r.b.bh +#define I286_CH i286core.s.r.b.ch +#define I286_DH i286core.s.r.b.dh + +#define I286_FLAG i286core.s.r.w.flag +#define I286_FLAGL i286core.s.r.b.flag_l +#define I286_FLAGH i286core.s.r.b.flag_h +#define I286_TRAP i286core.s.trap +#define I286_OV i286core.s.ovflag + +#define I286_GDTR i286core.s.GDTR +#define I286_IDTR i286core.s.IDTR +#define I286_LDTR i286core.s.LDTR +#define I286_LDTRC i286core.s.LDTRC +#define I286_TR i286core.s.TR +#define I286_TRC i286core.s.TRC +#define I286_MSW i286core.s.MSW + +#define I286_REMCLOCK i286core.s.remainclock +#define I286_BASECLOCK i286core.s.baseclock +#define I286_CLOCK i286core.s.clock +#define I286_ADRSMASK i286core.s.adrsmask + +#define I286_PREFIX i286core.s.prefix + +#define I286_INPADRS i286core.e.inport + + +#define I286FN static void +#define I286EXT void + +typedef void (*I286OP)(void); + +extern void CPUCALL i286c_intnum(UINT vect, REG16 IP); +extern UINT32 i286c_selector(UINT sel); + +#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) +extern void i286cea_initialize(void); +#endif + +extern const I286OP i286op[]; +extern const I286OP i286op_repe[]; +extern const I286OP i286op_repne[]; + +#define I286_0F static void CPUCALL +typedef void (CPUCALL * I286OP_0F)(UINT op); + +I286EXT i286c_cts(void); + + +#define I286_8X static void CPUCALL +typedef void (CPUCALL * I286OP8XREG8)(UINT8 *p); +typedef void (CPUCALL * I286OP8XEXT8)(UINT32 madr); +typedef void (CPUCALL * I286OP8XREG16)(UINT16 *p, UINT32 src); +typedef void (CPUCALL * I286OP8XEXT16)(UINT32 madr, UINT32 src); + +extern const I286OP8XREG8 c_op8xreg8_table[]; +extern const I286OP8XEXT8 c_op8xext8_table[]; +extern const I286OP8XREG16 c_op8xreg16_table[]; +extern const I286OP8XEXT16 c_op8xext16_table[]; + + +#define I286_SFT static void CPUCALL +typedef void (CPUCALL * I286OPSFTR8)(UINT8 *p); +typedef void (CPUCALL * I286OPSFTE8)(UINT32 madr); +typedef void (CPUCALL * I286OPSFTR16)(UINT16 *p); +typedef void (CPUCALL * I286OPSFTE16)(UINT32 madr); +typedef void (CPUCALL * I286OPSFTR8CL)(UINT8 *p, REG8 cl); +typedef void (CPUCALL * I286OPSFTE8CL)(UINT32 madr, REG8 cl); +typedef void (CPUCALL * I286OPSFTR16CL)(UINT16 *p, REG8 cl); +typedef void (CPUCALL * I286OPSFTE16CL)(UINT32 madr, REG8 cl); + +extern const I286OPSFTR8 sft_r8_table[]; +extern const I286OPSFTE8 sft_e8_table[]; +extern const I286OPSFTR16 sft_r16_table[]; +extern const I286OPSFTE16 sft_e16_table[]; +extern const I286OPSFTR8CL sft_r8cl_table[]; +extern const I286OPSFTE8CL sft_e8cl_table[]; +extern const I286OPSFTR16CL sft_r16cl_table[]; +extern const I286OPSFTE16CL sft_e16cl_table[]; + + +#define I286_F6 static void CPUCALL +typedef void (CPUCALL * I286OPF6)(UINT op); + +extern const I286OPF6 c_ope0xf6_table[]; +extern const I286OPF6 c_ope0xf7_table[]; + + +extern const I286OPF6 c_ope0xfe_table[]; +extern const I286OPF6 c_ope0xff_table[]; + + +extern I286EXT i286c_rep_insb(void); +extern I286EXT i286c_rep_insw(void); +extern I286EXT i286c_rep_outsb(void); +extern I286EXT i286c_rep_outsw(void); +extern I286EXT i286c_rep_movsb(void); +extern I286EXT i286c_rep_movsw(void); +extern I286EXT i286c_rep_lodsb(void); +extern I286EXT i286c_rep_lodsw(void); +extern I286EXT i286c_rep_stosb(void); +extern I286EXT i286c_rep_stosw(void); +extern I286EXT i286c_repe_cmpsb(void); +extern I286EXT i286c_repne_cmpsb(void); +extern I286EXT i286c_repe_cmpsw(void); +extern I286EXT i286c_repne_cmpsw(void); +extern I286EXT i286c_repe_scasb(void); +extern I286EXT i286c_repne_scasb(void); +extern I286EXT i286c_repe_scasw(void); +extern I286EXT i286c_repne_scasw(void); + + +#define i286_memoryread(a) memp_read8(a) +#define i286_memoryread_w(a) memp_read16(a) +#define i286_memoryread_d(a) memp_read32(a) +#define i286_memorywrite(a, v) memp_write8(a, v) +#define i286_memorywrite_w(a, v) memp_write16(a, v) +#define i286_memorywrite_d(a, v) memp_write32(a, v) + diff --git a/i286c/i286c.mcr b/i286c/i286c.mcr old mode 100755 new mode 100644 index 5b4da6e7..14945f23 --- a/i286c/i286c.mcr +++ b/i286c/i286c.mcr @@ -1,508 +1,508 @@ - -#if defined(X11) && (defined(i386) || defined(__i386__)) -#define INHIBIT_WORDP(m) ((m) >= (I286_MEMWRITEMAX - 1)) -#elif (defined(ARM) || defined(X11)) && defined(BYTESEX_LITTLE) -#define INHIBIT_WORDP(m) (((m) & 1) || ((m) >= I286_MEMWRITEMAX)) -#elif (defined(_WIN32)) || (defined(_WIN64)) -#define INHIBIT_WORDP(m) ((m) >= (I286_MEMWRITEMAX - 1)) -#else -#define INHIBIT_WORDP(m) (1) -#endif - -#define __CBW(src) (UINT16)((SINT8)(src)) -#define __CBD(src) ((SINT8)(src)) -#define WORD2LONG(src) ((SINT16)(src)) - - -#define SEGMENTPTR(s) (((UINT16 *)&I286_SEGREG) + (s)) - -#define REAL_FLAGREG (UINT16)((I286_FLAG & 0x7ff) | (I286_OV?O_FLAG:0)) - -#define STRING_DIR ((I286_FLAG & D_FLAG)?-1:1) -#define STRING_DIRx2 ((I286_FLAG & D_FLAG)?-2:2) - - -// ---- flags - -#if defined(I286C_TEST) - -extern UINT8 BYTESZPF(UINT r); -extern UINT8 BYTESZPCF(UINT r); -#define BYTESZPCF2(a) BYTESZPCF((a) & 0x1ff) -extern UINT8 WORDSZPF(UINT32 r); -extern UINT8 WORDSZPCF(UINT32 r); - -#elif !defined(MEMOPTIMIZE) - -extern UINT8 _szpflag16[0x10000]; -#define BYTESZPF(a) (iflags[(a)]) -#define BYTESZPCF(a) (iflags[(a)]) -#define BYTESZPCF2(a) (iflags[(a) & 0x1ff]) -#define WORDSZPF(a) (_szpflag16[(a)]) -#define WORDSZPCF(a) (_szpflag16[LOW16(a)] + (((a) >> 16) & 1)) - -#else - -#define BYTESZPF(a) (iflags[(a)]) -#define BYTESZPCF(a) (iflags[(a)]) -#define BYTESZPCF2(a) (iflags[(a) & 0x1ff]) -#define WORDSZPF(a) ((iflags[(a) & 0xff] & P_FLAG) + \ - (((a))?0:Z_FLAG) + (((a) >> 8) & S_FLAG)) -#define WORDSZPCF(a) ((iflags[(a) & 0xff] & P_FLAG) + \ - ((LOW16(a))?0:Z_FLAG) + (((a) >> 8) & S_FLAG) + \ - (((a) >> 16) & 1)) - -#endif - - -// ---- reg position - -#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) -extern UINT8 *_reg8_b53[256]; -extern UINT8 *_reg8_b20[256]; -#define REG8_B53(op) _reg8_b53[(op)] -#define REG8_B20(op) _reg8_b20[(op)] -#else -#if defined(BYTESEX_LITTLE) -#define REG8_B53(op) \ - (((UINT8 *)&I286_REG) + (((op) >> 2) & 6) + (((op) >> 5) & 1)) -#define REG8_B20(op) \ - (((UINT8 *)&I286_REG) + (((op) & 3) * 2) + (((op) >> 2) & 1)) -#else -#define REG8_B53(op) (((UINT8 *)&I286_REG) + (((op) >> 2) & 6) + \ - ((((op) >> 5) & 1) ^ 1)) -#define REG8_B20(op) (((UINT8 *)&I286_REG) + (((op) & 3) * 2) + \ - ((((op) >> 2) & 1) ^ 1)) -#endif -#endif - -#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) -extern UINT16 *_reg16_b53[256]; -extern UINT16 *_reg16_b20[256]; -#define REG16_B53(op) _reg16_b53[(op)] -#define REG16_B20(op) _reg16_b20[(op)] -#else -#define REG16_B53(op) (((UINT16 *)&I286_REG) + (((op) >> 3) & 7)) -#define REG16_B20(op) (((UINT16 *)&I286_REG) + ((op) & 7)) -#endif - - -// ---- ea - -#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) -typedef UINT32 (*CALCEA)(void); -typedef UINT16 (*CALCLEA)(void); -typedef UINT (*GETLEA)(UINT32 *seg); -extern CALCEA _calc_ea_dst[]; -extern CALCLEA _calc_lea[]; -extern GETLEA _get_ea[]; -#define CALC_EA(o) (_calc_ea_dst[(o)]()) -#define CALC_LEA(o) (_calc_lea[(o)]()) -#define GET_EA(o, s) (_get_ea[(o)](s)) -#else -extern UINT32 calc_ea_dst(UINT op); -extern UINT16 calc_lea(UINT op); -extern UINT calc_a(UINT op, UINT32 *seg); -#define CALC_EA(o) (calc_ea_dst(o)) -#define CALC_LEA(o) (calc_lea(o)) -#define GET_EA(o, s) (calc_a(o, s)) -#endif - - -#define SWAPBYTE(p, q) { \ - REG8 tmp; \ - tmp = (p); \ - (p) = (q); \ - (q) = tmp; \ - } - -#define SWAPWORD(p, q) { \ - REG16 tmp; \ - tmp = (p); \ - (p) = (q); \ - (q) = tmp; \ - } - - -#define I286IRQCHECKTERM \ - if (I286_REMCLOCK > 0) { \ - I286_BASECLOCK -= I286_REMCLOCK; \ - I286_REMCLOCK = 0; \ - } - - -#define REMOVE_PREFIX \ - SS_FIX = SS_BASE; \ - DS_FIX = DS_BASE; - - -#define I286_WORKCLOCK(c) I286_REMCLOCK -= (c) - - -#define GET_PCBYTE(b) \ - (b) = i286_memoryread(CS_BASE + I286_IP); \ - I286_IP++; - - -#define GET_PCBYTES(b) \ - (b) = __CBW(i286_memoryread(CS_BASE + I286_IP)); \ - I286_IP++; - - -#define GET_PCBYTESD(b) \ - (b) = __CBD(i286_memoryread(CS_BASE + I286_IP)); \ - I286_IP++; - - -#define GET_PCWORD(b) \ - (b) = i286_memoryread_w(CS_BASE + I286_IP); \ - I286_IP += 2; - - -#define PREPART_EA_REG8(b, d_s) \ - GET_PCBYTE((b)) \ - (d_s) = *(REG8_B53(b)); - - -#define PREPART_EA_REG8P(b, d_s) \ - GET_PCBYTE((b)) \ - (d_s) = REG8_B53(b); - - -#define PREPART_EA_REG16(b, d_s) \ - GET_PCBYTE((b)) \ - (d_s) = *(REG16_B53(b)); - - -#define PREPART_EA_REG16P(b, d_s) \ - GET_PCBYTE((b)) \ - (d_s) = REG16_B53(b); - - -#define PREPART_REG8_EA(b, s, d, regclk, memclk) \ - GET_PCBYTE((b)) \ - if ((b) >= 0xc0) { \ - I286_WORKCLOCK(regclk); \ - (s) = *(REG8_B20(b)); \ - } \ - else { \ - I286_WORKCLOCK(memclk); \ - (s) = i286_memoryread(CALC_EA(b)); \ - } \ - (d) = REG8_B53(b); - - -#define PREPART_REG16_EA(b, s, d, regclk, memclk) \ - GET_PCBYTE(b) \ - if (b >= 0xc0) { \ - I286_WORKCLOCK(regclk); \ - s = *(REG16_B20(b)); \ - } \ - else { \ - I286_WORKCLOCK(memclk); \ - s = i286_memoryread_w(CALC_EA(b)); \ - } \ - d = REG16_B53(b); - - -#define ADDBYTE(r, d, s) \ - (r) = (s) + (d); \ - I286_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80; \ - I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - I286_FLAGL |= BYTESZPCF(r); - -#define ADDWORD(r, d, s) \ - (r) = (s) + (d); \ - I286_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x8000; \ - I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - I286_FLAGL |= WORDSZPCF(r); - - -// flag no check -#define ORBYTE(d, s) \ - (d) |= (s); \ - I286_OV = 0; \ - I286_FLAGL = BYTESZPF(d); - -#define ORWORD(d, s) \ - (d) |= (s); \ - I286_OV = 0; \ - I286_FLAGL = WORDSZPF(d); - - -#define ADCBYTE(r, d, s) \ - (r) = (I286_FLAGL & 1) + (s) + (d); \ - I286_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80; \ - I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - I286_FLAGL |= BYTESZPCF(r); - -#define ADCWORD(r, d, s) \ - (r) = (I286_FLAGL & 1) + (s) + (d); \ - I286_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x8000; \ - I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - I286_FLAGL |= WORDSZPCF(r); - - -// flag no check -#define SBBBYTE(r, d, s) \ - (r) = (d) - (s) - (I286_FLAGL & 1); \ - I286_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80; \ - I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - I286_FLAGL |= BYTESZPCF2(r); - -#define SBBWORD(r, d, s) \ - (r) = (d) - (s) - (I286_FLAGL & 1); \ - I286_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x8000; \ - I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - I286_FLAGL |= WORDSZPCF(r); - - -// flag no check -#define ANDBYTE(d, s) \ - (d) &= (s); \ - I286_OV = 0; \ - I286_FLAGL = BYTESZPF(d); - -#define ANDWORD(d, s) \ - (d) &= (s); \ - I286_OV = 0; \ - I286_FLAGL = WORDSZPF(d); - - -// flag no check -#define SUBBYTE(r, d, s) \ - (r) = (d) - (s); \ - I286_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80; \ - I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - I286_FLAGL |= BYTESZPCF2(r); - -#define SUBWORD(r, d, s) \ - (r) = (d) - (s); \ - I286_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x8000; \ - I286_FLAGL = ((r) ^ (d) ^ (s)) & A_FLAG; \ - I286_FLAGL |= WORDSZPCF(r); - - -// flag no check -#define XORBYTE(d, s) \ - (d) ^= s; \ - I286_OV = 0; \ - I286_FLAGL = BYTESZPF(d); - -#define XORWORD(d, s) \ - (d) ^= (s); \ - I286_OV = 0; \ - I286_FLAGL = WORDSZPF(d); - - -#define NEGBYTE(d, s) \ - (d) = 0 - (s); \ - I286_OV = ((d) & (s)) & 0x80; \ - I286_FLAGL = (UINT8)(((d) ^ (s)) & A_FLAG); \ - I286_FLAGL |= BYTESZPCF2(d); - -#define NEGWORD(d, s) \ - (d) = 0 - (s); \ - I286_OV = ((d) & (s)) & 0x8000; \ - I286_FLAGL = (UINT8)(((d) ^ (s)) & A_FLAG); \ - I286_FLAGL |= WORDSZPCF(d); - - -#define BYTE_MUL(r, d, s) \ - I286_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ - (r) = (UINT8)(d) * (UINT8)(s); \ - I286_OV = (r) >> 8; \ - if (I286_OV) { \ - I286_FLAGL |= C_FLAG; \ - } - -#define WORD_MUL(r, d, s) \ - I286_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ - (r) = (UINT16)(d) * (UINT16)(s); \ - I286_OV = (r) >> 16; \ - if (I286_OV) { \ - I286_FLAGL |= C_FLAG; \ - } - - -#define BYTE_IMUL(r, d, s) \ - I286_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ - (r) = (SINT8)(d) * (SINT8)(s); \ - I286_OV = ((r) + 0x80) & 0xffffff00; \ - if (I286_OV) { \ - I286_FLAGL |= C_FLAG; \ - } - -#define WORD_IMUL(r, d, s) \ - I286_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ - (r) = (SINT16)(d) * (SINT16)(s); \ - I286_OV = ((r) + 0x8000) & 0xffff0000; \ - if (I286_OV) { \ - I286_FLAGL |= C_FLAG; \ - } - - -// flag no check -#define INCBYTE(s) { \ - UINT b = (s); \ - (s)++; \ - I286_OV = (s) & (b ^ (s)) & 0x80; \ - I286_FLAGL &= C_FLAG; \ - I286_FLAGL |= (UINT8)((b ^ (s)) & A_FLAG); \ - I286_FLAGL |= BYTESZPF((UINT8)(s)); \ - } - -#define INCWORD(s) { \ - UINT32 b = (s); \ - (s)++; \ - I286_OV = (s) & (b ^ (s)) & 0x8000; \ - I286_FLAGL &= C_FLAG; \ - I286_FLAGL |= (UINT8)((b ^ (s)) & A_FLAG); \ - I286_FLAGL |= WORDSZPF((UINT16)(s)); \ - } - - -// flag no check -#define DECBYTE(s) { \ - UINT b = (s); \ - b--; \ - I286_OV = (s) & (b ^ (s)) & 0x80; \ - I286_FLAGL &= C_FLAG; \ - I286_FLAGL |= (UINT8)((b ^ (s)) & A_FLAG); \ - I286_FLAGL |= BYTESZPF((UINT8)b); \ - (s) = b; \ - } - -#define DECWORD(s) { \ - UINT32 b = (s); \ - b--; \ - I286_OV = (s) & (b ^ (s)) & 0x8000; \ - I286_FLAGL &= C_FLAG; \ - I286_FLAGL |= (UINT8)((b ^ (s)) & A_FLAG); \ - I286_FLAGL |= WORDSZPF((UINT16)b); \ - (s) = b; \ - } - - -// flag no check -#define INCWORD2(r, clock) { \ - REG16 s = (r); \ - REG16 d = (r); \ - d++; \ - (r) = (UINT16)d; \ - I286_OV = d & (d ^ s) & 0x8000; \ - I286_FLAGL &= C_FLAG; \ - I286_FLAGL |= (UINT8)((d ^ s) & A_FLAG); \ - I286_FLAGL |= WORDSZPF((UINT16)d); \ - I286_WORKCLOCK(clock); \ - } - -#define DECWORD2(r, clock) { \ - REG16 s = (r); \ - REG16 d = (r); \ - d--; \ - (r) = (UINT16)d; \ - I286_OV = s & (d ^ s) & 0x8000; \ - I286_FLAGL &= C_FLAG; \ - I286_FLAGL |= (UINT8)((d ^ s) & A_FLAG); \ - I286_FLAGL |= WORDSZPF((UINT16)d); \ - I286_WORKCLOCK(clock); \ - } - - -// ---- stack - -#define REGPUSH0(reg) \ - I286_SP -= 2; \ - i286_memorywrite_w(I286_SP + SS_BASE, reg); - -#define REGPOP0(reg) \ - reg = i286_memoryread_w(I286_SP + SS_BASE); \ - I286_SP += 2; - -#if (defined(ARM) || defined(X11)) && defined(BYTESEX_LITTLE) - -#define REGPUSH(reg, clock) { \ - UINT32 addr; \ - I286_WORKCLOCK(clock); \ - I286_SP -= 2; \ - addr = I286_SP + SS_BASE; \ - if (INHIBIT_WORDP(addr)) { \ - i286_memorywrite_w(addr, reg); \ - } \ - else { \ - *(UINT16 *)(mem + addr) = (reg); \ - } \ - } - -#define REGPOP(reg, clock) { \ - UINT32 addr; \ - I286_WORKCLOCK(clock); \ - addr = I286_SP + SS_BASE; \ - if (INHIBIT_WORDP(addr)) { \ - (reg) = i286_memoryread_w(addr); \ - } \ - else { \ - (reg) = *(UINT16 *)(mem + addr); \ - } \ - I286_SP += 2; \ - } - -#else - -#define REGPUSH(reg, clock) { \ - I286_WORKCLOCK(clock); \ - I286_SP -= 2; \ - i286_memorywrite_w(I286_SP + SS_BASE, reg); \ - } - -#define REGPOP(reg, clock) { \ - I286_WORKCLOCK(clock); \ - reg = i286_memoryread_w(I286_SP + SS_BASE); \ - I286_SP += 2; \ - } - -#endif - -#define SP_PUSH(reg, clock) { \ - REG16 sp = (reg); \ - I286_SP -= 2; \ - i286_memorywrite_w(I286_SP + SS_BASE, sp); \ - I286_WORKCLOCK(clock); \ - } - -#define SP_POP(reg, clock) { \ - I286_WORKCLOCK(clock); \ - reg = i286_memoryread_w(I286_SP + SS_BASE); \ - } - - -#define JMPSHORT(clock) { \ - I286_WORKCLOCK(clock); \ - I286_IP += __CBW(i286_memoryread(CS_BASE + I286_IP)); \ - I286_IP++; \ - } - - -#define JMPNOP(clock) { \ - I286_WORKCLOCK(clock); \ - I286_IP++; \ - } - - -#define MOVIMM8(reg) { \ - I286_WORKCLOCK(2); \ - GET_PCBYTE(reg) \ - } - - -#define MOVIMM16(reg) { \ - I286_WORKCLOCK(2); \ - GET_PCWORD(reg) \ - } - - -#define SEGSELECT(c) ((I286_MSW & MSW_PE)?i286c_selector(c):((c) << 4)) - -#define INT_NUM(a, b) i286c_intnum((a), (REG16)(b)) - + +#if defined(X11) && (defined(i386) || defined(__i386__)) +#define INHIBIT_WORDP(m) ((m) >= (I286_MEMWRITEMAX - 1)) +#elif (defined(ARM) || defined(X11)) && defined(BYTESEX_LITTLE) +#define INHIBIT_WORDP(m) (((m) & 1) || ((m) >= I286_MEMWRITEMAX)) +#elif (defined(_WIN32)) || (defined(_WIN64)) +#define INHIBIT_WORDP(m) ((m) >= (I286_MEMWRITEMAX - 1)) +#else +#define INHIBIT_WORDP(m) (1) +#endif + +#define __CBW(src) (UINT16)((SINT8)(src)) +#define __CBD(src) ((SINT8)(src)) +#define WORD2LONG(src) ((SINT16)(src)) + + +#define SEGMENTPTR(s) (((UINT16 *)&I286_SEGREG) + (s)) + +#define REAL_FLAGREG (UINT16)((I286_FLAG & 0x7ff) | (I286_OV?O_FLAG:0)) + +#define STRING_DIR ((I286_FLAG & D_FLAG)?-1:1) +#define STRING_DIRx2 ((I286_FLAG & D_FLAG)?-2:2) + + +// ---- flags + +#if defined(I286C_TEST) + +extern UINT8 BYTESZPF(UINT r); +extern UINT8 BYTESZPCF(UINT r); +#define BYTESZPCF2(a) BYTESZPCF((a) & 0x1ff) +extern UINT8 WORDSZPF(UINT32 r); +extern UINT8 WORDSZPCF(UINT32 r); + +#elif !defined(MEMOPTIMIZE) + +extern UINT8 _szpflag16[0x10000]; +#define BYTESZPF(a) (iflags[(a)]) +#define BYTESZPCF(a) (iflags[(a)]) +#define BYTESZPCF2(a) (iflags[(a) & 0x1ff]) +#define WORDSZPF(a) (_szpflag16[(a)]) +#define WORDSZPCF(a) (_szpflag16[LOW16(a)] + (((a) >> 16) & 1)) + +#else + +#define BYTESZPF(a) (iflags[(a)]) +#define BYTESZPCF(a) (iflags[(a)]) +#define BYTESZPCF2(a) (iflags[(a) & 0x1ff]) +#define WORDSZPF(a) ((iflags[(a) & 0xff] & P_FLAG) + \ + (((a))?0:Z_FLAG) + (((a) >> 8) & S_FLAG)) +#define WORDSZPCF(a) ((iflags[(a) & 0xff] & P_FLAG) + \ + ((LOW16(a))?0:Z_FLAG) + (((a) >> 8) & S_FLAG) + \ + (((a) >> 16) & 1)) + +#endif + + +// ---- reg position + +#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) +extern UINT8 *_reg8_b53[256]; +extern UINT8 *_reg8_b20[256]; +#define REG8_B53(op) _reg8_b53[(op)] +#define REG8_B20(op) _reg8_b20[(op)] +#else +#if defined(BYTESEX_LITTLE) +#define REG8_B53(op) \ + (((UINT8 *)&I286_REG) + (((op) >> 2) & 6) + (((op) >> 5) & 1)) +#define REG8_B20(op) \ + (((UINT8 *)&I286_REG) + (((op) & 3) * 2) + (((op) >> 2) & 1)) +#else +#define REG8_B53(op) (((UINT8 *)&I286_REG) + (((op) >> 2) & 6) + \ + ((((op) >> 5) & 1) ^ 1)) +#define REG8_B20(op) (((UINT8 *)&I286_REG) + (((op) & 3) * 2) + \ + ((((op) >> 2) & 1) ^ 1)) +#endif +#endif + +#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) +extern UINT16 *_reg16_b53[256]; +extern UINT16 *_reg16_b20[256]; +#define REG16_B53(op) _reg16_b53[(op)] +#define REG16_B20(op) _reg16_b20[(op)] +#else +#define REG16_B53(op) (((UINT16 *)&I286_REG) + (((op) >> 3) & 7)) +#define REG16_B20(op) (((UINT16 *)&I286_REG) + ((op) & 7)) +#endif + + +// ---- ea + +#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) +typedef UINT32 (*CALCEA)(void); +typedef UINT16 (*CALCLEA)(void); +typedef UINT (*GETLEA)(UINT32 *seg); +extern CALCEA _calc_ea_dst[]; +extern CALCLEA _calc_lea[]; +extern GETLEA _get_ea[]; +#define CALC_EA(o) (_calc_ea_dst[(o)]()) +#define CALC_LEA(o) (_calc_lea[(o)]()) +#define GET_EA(o, s) (_get_ea[(o)](s)) +#else +extern UINT32 calc_ea_dst(UINT op); +extern UINT16 calc_lea(UINT op); +extern UINT calc_a(UINT op, UINT32 *seg); +#define CALC_EA(o) (calc_ea_dst(o)) +#define CALC_LEA(o) (calc_lea(o)) +#define GET_EA(o, s) (calc_a(o, s)) +#endif + + +#define SWAPBYTE(p, q) { \ + REG8 tmp; \ + tmp = (p); \ + (p) = (q); \ + (q) = tmp; \ + } + +#define SWAPWORD(p, q) { \ + REG16 tmp; \ + tmp = (p); \ + (p) = (q); \ + (q) = tmp; \ + } + + +#define I286IRQCHECKTERM \ + if (I286_REMCLOCK > 0) { \ + I286_BASECLOCK -= I286_REMCLOCK; \ + I286_REMCLOCK = 0; \ + } + + +#define REMOVE_PREFIX \ + SS_FIX = SS_BASE; \ + DS_FIX = DS_BASE; + + +#define I286_WORKCLOCK(c) I286_REMCLOCK -= (c) + + +#define GET_PCBYTE(b) \ + (b) = i286_memoryread(CS_BASE + I286_IP); \ + I286_IP++; + + +#define GET_PCBYTES(b) \ + (b) = __CBW(i286_memoryread(CS_BASE + I286_IP)); \ + I286_IP++; + + +#define GET_PCBYTESD(b) \ + (b) = __CBD(i286_memoryread(CS_BASE + I286_IP)); \ + I286_IP++; + + +#define GET_PCWORD(b) \ + (b) = i286_memoryread_w(CS_BASE + I286_IP); \ + I286_IP += 2; + + +#define PREPART_EA_REG8(b, d_s) \ + GET_PCBYTE((b)) \ + (d_s) = *(REG8_B53(b)); + + +#define PREPART_EA_REG8P(b, d_s) \ + GET_PCBYTE((b)) \ + (d_s) = REG8_B53(b); + + +#define PREPART_EA_REG16(b, d_s) \ + GET_PCBYTE((b)) \ + (d_s) = *(REG16_B53(b)); + + +#define PREPART_EA_REG16P(b, d_s) \ + GET_PCBYTE((b)) \ + (d_s) = REG16_B53(b); + + +#define PREPART_REG8_EA(b, s, d, regclk, memclk) \ + GET_PCBYTE((b)) \ + if ((b) >= 0xc0) { \ + I286_WORKCLOCK(regclk); \ + (s) = *(REG8_B20(b)); \ + } \ + else { \ + I286_WORKCLOCK(memclk); \ + (s) = i286_memoryread(CALC_EA(b)); \ + } \ + (d) = REG8_B53(b); + + +#define PREPART_REG16_EA(b, s, d, regclk, memclk) \ + GET_PCBYTE(b) \ + if (b >= 0xc0) { \ + I286_WORKCLOCK(regclk); \ + s = *(REG16_B20(b)); \ + } \ + else { \ + I286_WORKCLOCK(memclk); \ + s = i286_memoryread_w(CALC_EA(b)); \ + } \ + d = REG16_B53(b); + + +#define ADDBYTE(r, d, s) \ + (r) = (s) + (d); \ + I286_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80; \ + I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + I286_FLAGL |= BYTESZPCF(r); + +#define ADDWORD(r, d, s) \ + (r) = (s) + (d); \ + I286_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x8000; \ + I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + I286_FLAGL |= WORDSZPCF(r); + + +// flag no check +#define ORBYTE(d, s) \ + (d) |= (s); \ + I286_OV = 0; \ + I286_FLAGL = BYTESZPF(d); + +#define ORWORD(d, s) \ + (d) |= (s); \ + I286_OV = 0; \ + I286_FLAGL = WORDSZPF(d); + + +#define ADCBYTE(r, d, s) \ + (r) = (I286_FLAGL & 1) + (s) + (d); \ + I286_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80; \ + I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + I286_FLAGL |= BYTESZPCF(r); + +#define ADCWORD(r, d, s) \ + (r) = (I286_FLAGL & 1) + (s) + (d); \ + I286_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x8000; \ + I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + I286_FLAGL |= WORDSZPCF(r); + + +// flag no check +#define SBBBYTE(r, d, s) \ + (r) = (d) - (s) - (I286_FLAGL & 1); \ + I286_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80; \ + I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + I286_FLAGL |= BYTESZPCF2(r); + +#define SBBWORD(r, d, s) \ + (r) = (d) - (s) - (I286_FLAGL & 1); \ + I286_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x8000; \ + I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + I286_FLAGL |= WORDSZPCF(r); + + +// flag no check +#define ANDBYTE(d, s) \ + (d) &= (s); \ + I286_OV = 0; \ + I286_FLAGL = BYTESZPF(d); + +#define ANDWORD(d, s) \ + (d) &= (s); \ + I286_OV = 0; \ + I286_FLAGL = WORDSZPF(d); + + +// flag no check +#define SUBBYTE(r, d, s) \ + (r) = (d) - (s); \ + I286_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80; \ + I286_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + I286_FLAGL |= BYTESZPCF2(r); + +#define SUBWORD(r, d, s) \ + (r) = (d) - (s); \ + I286_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x8000; \ + I286_FLAGL = ((r) ^ (d) ^ (s)) & A_FLAG; \ + I286_FLAGL |= WORDSZPCF(r); + + +// flag no check +#define XORBYTE(d, s) \ + (d) ^= s; \ + I286_OV = 0; \ + I286_FLAGL = BYTESZPF(d); + +#define XORWORD(d, s) \ + (d) ^= (s); \ + I286_OV = 0; \ + I286_FLAGL = WORDSZPF(d); + + +#define NEGBYTE(d, s) \ + (d) = 0 - (s); \ + I286_OV = ((d) & (s)) & 0x80; \ + I286_FLAGL = (UINT8)(((d) ^ (s)) & A_FLAG); \ + I286_FLAGL |= BYTESZPCF2(d); + +#define NEGWORD(d, s) \ + (d) = 0 - (s); \ + I286_OV = ((d) & (s)) & 0x8000; \ + I286_FLAGL = (UINT8)(((d) ^ (s)) & A_FLAG); \ + I286_FLAGL |= WORDSZPCF(d); + + +#define BYTE_MUL(r, d, s) \ + I286_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ + (r) = (UINT8)(d) * (UINT8)(s); \ + I286_OV = (r) >> 8; \ + if (I286_OV) { \ + I286_FLAGL |= C_FLAG; \ + } + +#define WORD_MUL(r, d, s) \ + I286_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ + (r) = (UINT16)(d) * (UINT16)(s); \ + I286_OV = (r) >> 16; \ + if (I286_OV) { \ + I286_FLAGL |= C_FLAG; \ + } + + +#define BYTE_IMUL(r, d, s) \ + I286_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ + (r) = (SINT8)(d) * (SINT8)(s); \ + I286_OV = ((r) + 0x80) & 0xffffff00; \ + if (I286_OV) { \ + I286_FLAGL |= C_FLAG; \ + } + +#define WORD_IMUL(r, d, s) \ + I286_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ + (r) = (SINT16)(d) * (SINT16)(s); \ + I286_OV = ((r) + 0x8000) & 0xffff0000; \ + if (I286_OV) { \ + I286_FLAGL |= C_FLAG; \ + } + + +// flag no check +#define INCBYTE(s) { \ + UINT b = (s); \ + (s)++; \ + I286_OV = (s) & (b ^ (s)) & 0x80; \ + I286_FLAGL &= C_FLAG; \ + I286_FLAGL |= (UINT8)((b ^ (s)) & A_FLAG); \ + I286_FLAGL |= BYTESZPF((UINT8)(s)); \ + } + +#define INCWORD(s) { \ + UINT32 b = (s); \ + (s)++; \ + I286_OV = (s) & (b ^ (s)) & 0x8000; \ + I286_FLAGL &= C_FLAG; \ + I286_FLAGL |= (UINT8)((b ^ (s)) & A_FLAG); \ + I286_FLAGL |= WORDSZPF((UINT16)(s)); \ + } + + +// flag no check +#define DECBYTE(s) { \ + UINT b = (s); \ + b--; \ + I286_OV = (s) & (b ^ (s)) & 0x80; \ + I286_FLAGL &= C_FLAG; \ + I286_FLAGL |= (UINT8)((b ^ (s)) & A_FLAG); \ + I286_FLAGL |= BYTESZPF((UINT8)b); \ + (s) = b; \ + } + +#define DECWORD(s) { \ + UINT32 b = (s); \ + b--; \ + I286_OV = (s) & (b ^ (s)) & 0x8000; \ + I286_FLAGL &= C_FLAG; \ + I286_FLAGL |= (UINT8)((b ^ (s)) & A_FLAG); \ + I286_FLAGL |= WORDSZPF((UINT16)b); \ + (s) = b; \ + } + + +// flag no check +#define INCWORD2(r, clock) { \ + REG16 s = (r); \ + REG16 d = (r); \ + d++; \ + (r) = (UINT16)d; \ + I286_OV = d & (d ^ s) & 0x8000; \ + I286_FLAGL &= C_FLAG; \ + I286_FLAGL |= (UINT8)((d ^ s) & A_FLAG); \ + I286_FLAGL |= WORDSZPF((UINT16)d); \ + I286_WORKCLOCK(clock); \ + } + +#define DECWORD2(r, clock) { \ + REG16 s = (r); \ + REG16 d = (r); \ + d--; \ + (r) = (UINT16)d; \ + I286_OV = s & (d ^ s) & 0x8000; \ + I286_FLAGL &= C_FLAG; \ + I286_FLAGL |= (UINT8)((d ^ s) & A_FLAG); \ + I286_FLAGL |= WORDSZPF((UINT16)d); \ + I286_WORKCLOCK(clock); \ + } + + +// ---- stack + +#define REGPUSH0(reg) \ + I286_SP -= 2; \ + i286_memorywrite_w(I286_SP + SS_BASE, reg); + +#define REGPOP0(reg) \ + reg = i286_memoryread_w(I286_SP + SS_BASE); \ + I286_SP += 2; + +#if (defined(ARM) || defined(X11)) && defined(BYTESEX_LITTLE) + +#define REGPUSH(reg, clock) { \ + UINT32 addr; \ + I286_WORKCLOCK(clock); \ + I286_SP -= 2; \ + addr = I286_SP + SS_BASE; \ + if (INHIBIT_WORDP(addr)) { \ + i286_memorywrite_w(addr, reg); \ + } \ + else { \ + *(UINT16 *)(mem + addr) = (reg); \ + } \ + } + +#define REGPOP(reg, clock) { \ + UINT32 addr; \ + I286_WORKCLOCK(clock); \ + addr = I286_SP + SS_BASE; \ + if (INHIBIT_WORDP(addr)) { \ + (reg) = i286_memoryread_w(addr); \ + } \ + else { \ + (reg) = *(UINT16 *)(mem + addr); \ + } \ + I286_SP += 2; \ + } + +#else + +#define REGPUSH(reg, clock) { \ + I286_WORKCLOCK(clock); \ + I286_SP -= 2; \ + i286_memorywrite_w(I286_SP + SS_BASE, reg); \ + } + +#define REGPOP(reg, clock) { \ + I286_WORKCLOCK(clock); \ + reg = i286_memoryread_w(I286_SP + SS_BASE); \ + I286_SP += 2; \ + } + +#endif + +#define SP_PUSH(reg, clock) { \ + REG16 sp = (reg); \ + I286_SP -= 2; \ + i286_memorywrite_w(I286_SP + SS_BASE, sp); \ + I286_WORKCLOCK(clock); \ + } + +#define SP_POP(reg, clock) { \ + I286_WORKCLOCK(clock); \ + reg = i286_memoryread_w(I286_SP + SS_BASE); \ + } + + +#define JMPSHORT(clock) { \ + I286_WORKCLOCK(clock); \ + I286_IP += __CBW(i286_memoryread(CS_BASE + I286_IP)); \ + I286_IP++; \ + } + + +#define JMPNOP(clock) { \ + I286_WORKCLOCK(clock); \ + I286_IP++; \ + } + + +#define MOVIMM8(reg) { \ + I286_WORKCLOCK(2); \ + GET_PCBYTE(reg) \ + } + + +#define MOVIMM16(reg) { \ + I286_WORKCLOCK(2); \ + GET_PCWORD(reg) \ + } + + +#define SEGSELECT(c) ((I286_MSW & MSW_PE)?i286c_selector(c):((c) << 4)) + +#define INT_NUM(a, b) i286c_intnum((a), (REG16)(b)) + diff --git a/i286c/i286c_0f.c b/i286c/i286c_0f.c old mode 100755 new mode 100644 index 4f18f464..f8673259 --- a/i286c/i286c_0f.c +++ b/i286c/i286c_0f.c @@ -1,288 +1,288 @@ -#include -#include -#include "i286c.h" -#include "i286c.mcr" - - -I286_0F _sldt(UINT op) { - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - *(REG16_B20(op)) = I286_LDTR; - } - else { - I286_WORKCLOCK(3); - i286_memorywrite_w(CALC_EA(op), I286_LDTR); - } -} - -I286_0F _str(UINT op) { - - if (op >= 0xc0) { - I286_WORKCLOCK(3); - *(REG16_B20(op)) = I286_TR; - } - else { - I286_WORKCLOCK(6); - i286_memorywrite_w(CALC_EA(op), I286_TR); - } -} - -I286_0F _lldt(UINT op) { - - REG16 r; - UINT32 addr; - - if (op >= 0xc0) { - I286_WORKCLOCK(17); - r = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(19); - r = i286_memoryread_w(CALC_EA(op)); - } - addr = i286c_selector(r); - I286_LDTR = r; - I286_LDTRC.limit = i286_memoryread_w(addr); - I286_LDTRC.base = i286_memoryread_w(addr + 2); - I286_LDTRC.base24 = i286_memoryread(addr + 4); -} - -I286_0F _ltr(UINT op) { - - REG16 r; - UINT32 addr; - - if (op >= 0xc0) { - I286_WORKCLOCK(17); - r = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(19); - r = i286_memoryread_w(CALC_EA(op)); - } - addr = i286c_selector(r); - I286_TR = r; - I286_TRC.limit = i286_memoryread_w(addr); - I286_TRC.base = i286_memoryread_w(addr + 2); - I286_TRC.base24 = i286_memoryread(addr + 4); -} - -I286_0F _verr(UINT op) { - - REG16 r; - - if (op >= 0xc0) { - I286_WORKCLOCK(14); - r = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(16); - r = i286_memoryread_w(CALC_EA(op)); - } -} - -I286_0F _verw(UINT op) { - - REG16 r; - - if (op >= 0xc0) { - I286_WORKCLOCK(14); - r = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(16); - r = i286_memoryread_w(CALC_EA(op)); - } -} - -I286_0F __sgdt(UINT op) { - - UINT32 addr; - - I286_WORKCLOCK(11); - if (op < 0xc0) { - addr = CALC_EA(op); - i286_memorywrite_w(addr, I286_GDTR.limit); - i286_memorywrite_w(addr + 2, I286_GDTR.base); - i286_memorywrite_w(addr + 4, (REG16)(0xff00 + I286_GDTR.base24)); - } - else { - INT_NUM(6, I286_IP - 2); - } -} - -I286_0F _sidt(UINT op) { - - UINT32 addr; - - I286_WORKCLOCK(12); - if (op < 0xc0) { - addr = CALC_EA(op); - i286_memorywrite_w(addr, I286_IDTR.limit); - i286_memorywrite_w(addr + 2, I286_IDTR.base); - i286_memorywrite_w(addr + 4, (REG16)(0xff00 + I286_IDTR.base24)); - } - else { - INT_NUM(6, I286_IP - 2); - } -} - -I286_0F __lgdt(UINT op) { - - UINT32 addr; - - I286_WORKCLOCK(11); - if (op < 0xc0) { - addr = CALC_EA(op); - I286_GDTR.limit = i286_memoryread_w(addr); - I286_GDTR.base = i286_memoryread_w(addr + 2); - I286_GDTR.base24 = i286_memoryread(addr + 4); - } - else { - INT_NUM(6, I286_IP - 2); - } -} - -I286_0F _lidt(UINT op) { - - UINT32 addr; - - I286_WORKCLOCK(12); - if (op < 0xc0) { - addr = CALC_EA(op); - I286_IDTR.limit = i286_memoryread_w(addr); - I286_IDTR.base = i286_memoryread_w(addr + 2); - I286_IDTR.base24 = i286_memoryread(addr + 4); - } - else { - INT_NUM(6, I286_IP - 2); - } -} - -I286_0F _smsw(UINT op) { - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - *(REG16_B20(op)) = I286_MSW; - } - else { - I286_WORKCLOCK(3); - i286_memorywrite_w(CALC_EA(op), I286_MSW); - } -} - -I286_0F _lmsw(UINT op) { - - REG16 msw; - - if (op >= 0xc0) { - I286_WORKCLOCK(3); - msw = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(6); - msw = i286_memoryread_w(CALC_EA(op)); - } - I286_MSW = msw | (I286_MSW & MSW_PE); - if (msw & MSW_PE) { - TRACEOUT(("80286 ProtectMode Enable... / MSW=%.4x [%.4x:%.4x]", - I286_MSW, I286_CS, I286_IP)); - } -} - -static const I286OP_0F cts0_table[] = { - _sldt, _str, _lldt, _ltr, - _verr, _verw, _verr, _verw}; - -static const I286OP_0F cts1_table[] = { - __sgdt, _sidt, __lgdt, _lidt, - _smsw, _smsw, _lmsw, _lmsw}; - - -I286_0F _loadall286(void) { - - UINT16 tmp; - UINT32 base; - - I286_WORKCLOCK(195); - I286_MSW = LOADINTELWORD(mem + 0x804); - I286_TR = LOADINTELWORD(mem + 0x816); // ver0.73 - tmp = LOADINTELWORD(mem + 0x818); - I286_OV = tmp & O_FLAG; - I286_FLAG = tmp & (0xfff ^ O_FLAG); - I286_TRAP = ((tmp & 0x300) == 0x300); - I286_IP = LOADINTELWORD(mem + 0x81a); - I286_LDTR = LOADINTELWORD(mem + 0x81c); // ver0.73 - I286_DS = LOADINTELWORD(mem + 0x81e); - I286_SS = LOADINTELWORD(mem + 0x820); - I286_CS = LOADINTELWORD(mem + 0x822); - I286_ES = LOADINTELWORD(mem + 0x824); - I286_DI = LOADINTELWORD(mem + 0x826); - I286_SI = LOADINTELWORD(mem + 0x828); - I286_BP = LOADINTELWORD(mem + 0x82a); - I286_SP = LOADINTELWORD(mem + 0x82c); - I286_BX = LOADINTELWORD(mem + 0x82e); - I286_DX = LOADINTELWORD(mem + 0x830); - I286_CX = LOADINTELWORD(mem + 0x832); - I286_AX = LOADINTELWORD(mem + 0x834); - base = LOADINTELDWORD(mem + 0x836) & 0x00ffffff; - ES_BASE = base; - base = LOADINTELDWORD(mem + 0x83c) & 0x00ffffff; - CS_BASE = base; - base = LOADINTELDWORD(mem + 0x842) & 0x00ffffff; - SS_BASE = base; - SS_FIX = base; - base = LOADINTELDWORD(mem + 0x848) & 0x00ffffff; - DS_BASE = base; - DS_FIX = base; - - I286_GDTR.base = LOADINTELWORD(mem + 0x84e); - *(UINT16 *)(&I286_GDTR.base24) = LOADINTELWORD(mem + 0x850); - I286_GDTR.limit = LOADINTELWORD(mem + 0x852); - - I286_LDTRC.base = LOADINTELWORD(mem + 0x854); - *(UINT16 *)(&I286_LDTRC.base24) = LOADINTELWORD(mem + 0x856); - I286_LDTRC.limit = LOADINTELWORD(mem + 0x858); - - I286_IDTR.base = LOADINTELWORD(mem + 0x85a); - *(UINT16 *)(&I286_IDTR.base24) = LOADINTELWORD(mem + 0x85c); - I286_IDTR.limit = LOADINTELWORD(mem + 0x85e); - - I286_TRC.base = LOADINTELWORD(mem + 0x860); - *(UINT16 *)(&I286_TRC.base24) = LOADINTELWORD(mem + 0x8620); - I286_TRC.limit = LOADINTELWORD(mem + 0x864); - - I286IRQCHECKTERM -} - -I286EXT i286c_cts(void) { - - UINT16 ip; - UINT op; - UINT op2; - - ip = I286_IP; - GET_PCBYTE(op); - - if (op == 0) { - if (!(I286_MSW & MSW_PE)) { - INT_NUM(6, ip - 1); - } - else { - GET_PCBYTE(op2); - cts0_table[(op2 >> 3) & 7](op2); - } - } - else if (op == 1) { - GET_PCBYTE(op2); - cts1_table[(op2 >> 3) & 7](op2); - } - else if (op == 5) { - _loadall286(); - } - else { - INT_NUM(6, ip - 1); - } -} - +#include +#include +#include "i286c.h" +#include "i286c.mcr" + + +I286_0F _sldt(UINT op) { + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + *(REG16_B20(op)) = I286_LDTR; + } + else { + I286_WORKCLOCK(3); + i286_memorywrite_w(CALC_EA(op), I286_LDTR); + } +} + +I286_0F _str(UINT op) { + + if (op >= 0xc0) { + I286_WORKCLOCK(3); + *(REG16_B20(op)) = I286_TR; + } + else { + I286_WORKCLOCK(6); + i286_memorywrite_w(CALC_EA(op), I286_TR); + } +} + +I286_0F _lldt(UINT op) { + + REG16 r; + UINT32 addr; + + if (op >= 0xc0) { + I286_WORKCLOCK(17); + r = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(19); + r = i286_memoryread_w(CALC_EA(op)); + } + addr = i286c_selector(r); + I286_LDTR = r; + I286_LDTRC.limit = i286_memoryread_w(addr); + I286_LDTRC.base = i286_memoryread_w(addr + 2); + I286_LDTRC.base24 = i286_memoryread(addr + 4); +} + +I286_0F _ltr(UINT op) { + + REG16 r; + UINT32 addr; + + if (op >= 0xc0) { + I286_WORKCLOCK(17); + r = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(19); + r = i286_memoryread_w(CALC_EA(op)); + } + addr = i286c_selector(r); + I286_TR = r; + I286_TRC.limit = i286_memoryread_w(addr); + I286_TRC.base = i286_memoryread_w(addr + 2); + I286_TRC.base24 = i286_memoryread(addr + 4); +} + +I286_0F _verr(UINT op) { + + REG16 r; + + if (op >= 0xc0) { + I286_WORKCLOCK(14); + r = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(16); + r = i286_memoryread_w(CALC_EA(op)); + } +} + +I286_0F _verw(UINT op) { + + REG16 r; + + if (op >= 0xc0) { + I286_WORKCLOCK(14); + r = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(16); + r = i286_memoryread_w(CALC_EA(op)); + } +} + +I286_0F __sgdt(UINT op) { + + UINT32 addr; + + I286_WORKCLOCK(11); + if (op < 0xc0) { + addr = CALC_EA(op); + i286_memorywrite_w(addr, I286_GDTR.limit); + i286_memorywrite_w(addr + 2, I286_GDTR.base); + i286_memorywrite_w(addr + 4, (REG16)(0xff00 + I286_GDTR.base24)); + } + else { + INT_NUM(6, I286_IP - 2); + } +} + +I286_0F _sidt(UINT op) { + + UINT32 addr; + + I286_WORKCLOCK(12); + if (op < 0xc0) { + addr = CALC_EA(op); + i286_memorywrite_w(addr, I286_IDTR.limit); + i286_memorywrite_w(addr + 2, I286_IDTR.base); + i286_memorywrite_w(addr + 4, (REG16)(0xff00 + I286_IDTR.base24)); + } + else { + INT_NUM(6, I286_IP - 2); + } +} + +I286_0F __lgdt(UINT op) { + + UINT32 addr; + + I286_WORKCLOCK(11); + if (op < 0xc0) { + addr = CALC_EA(op); + I286_GDTR.limit = i286_memoryread_w(addr); + I286_GDTR.base = i286_memoryread_w(addr + 2); + I286_GDTR.base24 = i286_memoryread(addr + 4); + } + else { + INT_NUM(6, I286_IP - 2); + } +} + +I286_0F _lidt(UINT op) { + + UINT32 addr; + + I286_WORKCLOCK(12); + if (op < 0xc0) { + addr = CALC_EA(op); + I286_IDTR.limit = i286_memoryread_w(addr); + I286_IDTR.base = i286_memoryread_w(addr + 2); + I286_IDTR.base24 = i286_memoryread(addr + 4); + } + else { + INT_NUM(6, I286_IP - 2); + } +} + +I286_0F _smsw(UINT op) { + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + *(REG16_B20(op)) = I286_MSW; + } + else { + I286_WORKCLOCK(3); + i286_memorywrite_w(CALC_EA(op), I286_MSW); + } +} + +I286_0F _lmsw(UINT op) { + + REG16 msw; + + if (op >= 0xc0) { + I286_WORKCLOCK(3); + msw = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(6); + msw = i286_memoryread_w(CALC_EA(op)); + } + I286_MSW = msw | (I286_MSW & MSW_PE); + if (msw & MSW_PE) { + TRACEOUT(("80286 ProtectMode Enable... / MSW=%.4x [%.4x:%.4x]", + I286_MSW, I286_CS, I286_IP)); + } +} + +static const I286OP_0F cts0_table[] = { + _sldt, _str, _lldt, _ltr, + _verr, _verw, _verr, _verw}; + +static const I286OP_0F cts1_table[] = { + __sgdt, _sidt, __lgdt, _lidt, + _smsw, _smsw, _lmsw, _lmsw}; + + +I286_0F _loadall286(void) { + + UINT16 tmp; + UINT32 base; + + I286_WORKCLOCK(195); + I286_MSW = LOADINTELWORD(mem + 0x804); + I286_TR = LOADINTELWORD(mem + 0x816); // ver0.73 + tmp = LOADINTELWORD(mem + 0x818); + I286_OV = tmp & O_FLAG; + I286_FLAG = tmp & (0xfff ^ O_FLAG); + I286_TRAP = ((tmp & 0x300) == 0x300); + I286_IP = LOADINTELWORD(mem + 0x81a); + I286_LDTR = LOADINTELWORD(mem + 0x81c); // ver0.73 + I286_DS = LOADINTELWORD(mem + 0x81e); + I286_SS = LOADINTELWORD(mem + 0x820); + I286_CS = LOADINTELWORD(mem + 0x822); + I286_ES = LOADINTELWORD(mem + 0x824); + I286_DI = LOADINTELWORD(mem + 0x826); + I286_SI = LOADINTELWORD(mem + 0x828); + I286_BP = LOADINTELWORD(mem + 0x82a); + I286_SP = LOADINTELWORD(mem + 0x82c); + I286_BX = LOADINTELWORD(mem + 0x82e); + I286_DX = LOADINTELWORD(mem + 0x830); + I286_CX = LOADINTELWORD(mem + 0x832); + I286_AX = LOADINTELWORD(mem + 0x834); + base = LOADINTELDWORD(mem + 0x836) & 0x00ffffff; + ES_BASE = base; + base = LOADINTELDWORD(mem + 0x83c) & 0x00ffffff; + CS_BASE = base; + base = LOADINTELDWORD(mem + 0x842) & 0x00ffffff; + SS_BASE = base; + SS_FIX = base; + base = LOADINTELDWORD(mem + 0x848) & 0x00ffffff; + DS_BASE = base; + DS_FIX = base; + + I286_GDTR.base = LOADINTELWORD(mem + 0x84e); + *(UINT16 *)(&I286_GDTR.base24) = LOADINTELWORD(mem + 0x850); + I286_GDTR.limit = LOADINTELWORD(mem + 0x852); + + I286_LDTRC.base = LOADINTELWORD(mem + 0x854); + *(UINT16 *)(&I286_LDTRC.base24) = LOADINTELWORD(mem + 0x856); + I286_LDTRC.limit = LOADINTELWORD(mem + 0x858); + + I286_IDTR.base = LOADINTELWORD(mem + 0x85a); + *(UINT16 *)(&I286_IDTR.base24) = LOADINTELWORD(mem + 0x85c); + I286_IDTR.limit = LOADINTELWORD(mem + 0x85e); + + I286_TRC.base = LOADINTELWORD(mem + 0x860); + *(UINT16 *)(&I286_TRC.base24) = LOADINTELWORD(mem + 0x8620); + I286_TRC.limit = LOADINTELWORD(mem + 0x864); + + I286IRQCHECKTERM +} + +I286EXT i286c_cts(void) { + + UINT16 ip; + UINT op; + UINT op2; + + ip = I286_IP; + GET_PCBYTE(op); + + if (op == 0) { + if (!(I286_MSW & MSW_PE)) { + INT_NUM(6, ip - 1); + } + else { + GET_PCBYTE(op2); + cts0_table[(op2 >> 3) & 7](op2); + } + } + else if (op == 1) { + GET_PCBYTE(op2); + cts1_table[(op2 >> 3) & 7](op2); + } + else if (op == 5) { + _loadall286(); + } + else { + INT_NUM(6, ip - 1); + } +} + diff --git a/i286c/i286c_8x.c b/i286c/i286c_8x.c old mode 100755 new mode 100644 index 06e10e01..de9b2ade --- a/i286c/i286c_8x.c +++ b/i286c/i286c_8x.c @@ -1,374 +1,374 @@ -#include -#include -#include "i286c.h" -#include "i286c.mcr" - - -// -------------------------------------------------------- opecode 0x80,1,2,3 - -// ----- reg8 - -I286_8X _add_r8_i(UINT8 *p) { - - UINT src; - UINT dst; - UINT res; - - GET_PCBYTE(src) - dst = *p; - ADDBYTE(res, dst, src); - *p = (UINT8)res; -} - -I286_8X _or_r8_i(UINT8 *p) { - - UINT src; - UINT dst; - - GET_PCBYTE(src) - dst = *p; - ORBYTE(dst, src); - *p = (UINT8)dst; -} - -I286_8X _adc_r8_i(UINT8 *p) { - - UINT src; - UINT dst; - UINT res; - - GET_PCBYTE(src) - dst = *p; - ADCBYTE(res, dst, src); - *p = (UINT8)res; -} - -I286_8X _sbb_r8_i(UINT8 *p) { - - UINT src; - UINT dst; - UINT res; - - GET_PCBYTE(src) - dst = *p; - SBBBYTE(res, dst, src); - *p = (UINT8)res; -} - -I286_8X _and_r8_i(UINT8 *p) { - - UINT src; - UINT dst; - - GET_PCBYTE(src) - dst = *p; - ANDBYTE(dst, src); - *p = (UINT8)dst; -} - -I286_8X _sub_r8_i(UINT8 *p) { - - UINT src; - UINT dst; - UINT res; - - GET_PCBYTE(src) - dst = *p; - SUBBYTE(res, dst, src); - *p = (UINT8)res; -} - -I286_8X _xor_r8_i(UINT8 *p) { - - UINT src; - UINT dst; - - GET_PCBYTE(src) - dst = *p; - XORBYTE(dst, src); - *p = (UINT8)dst; -} - -I286_8X _cmp_r8_i(UINT8 *p) { - - UINT src; - UINT dst; - UINT res; - - GET_PCBYTE(src) - dst = *p; - SUBBYTE(res, dst, src); -} - - -// ----- ext8 - -I286_8X _add_ext8_i(UINT32 madr) { - - UINT src; - UINT dst; - UINT res; - - GET_PCBYTE(src) - dst = i286_memoryread(madr); - ADDBYTE(res, dst, src); - i286_memorywrite(madr, (REG8)res); -} - -I286_8X _or_ext8_i(UINT32 madr) { - - UINT src; - UINT dst; - - GET_PCBYTE(src) - dst = i286_memoryread(madr); - ORBYTE(dst, src); - i286_memorywrite(madr, (REG8)dst); -} - -I286_8X _adc_ext8_i(UINT32 madr) { - - UINT src; - UINT dst; - UINT res; - - GET_PCBYTE(src) - dst = i286_memoryread(madr); - ADCBYTE(res, dst, src); - i286_memorywrite(madr, (REG8)res); -} - -I286_8X _sbb_ext8_i(UINT32 madr) { - - UINT src; - UINT dst; - UINT res; - - GET_PCBYTE(src) - dst = i286_memoryread(madr); - SBBBYTE(res, dst, src); - i286_memorywrite(madr, (REG8)res); -} - -I286_8X _and_ext8_i(UINT32 madr) { - - UINT src; - UINT dst; - - GET_PCBYTE(src) - dst = i286_memoryread(madr); - ANDBYTE(dst, src); - i286_memorywrite(madr, (REG8)dst); -} - -I286_8X _sub_ext8_i(UINT32 madr) { - - UINT src; - UINT dst; - UINT res; - - GET_PCBYTE(src) - dst = i286_memoryread(madr); - SUBBYTE(res, dst, src); - i286_memorywrite(madr, (REG8)res); -} - -I286_8X _xor_ext8_i(UINT32 madr) { - - UINT src; - UINT dst; - - GET_PCBYTE(src) - dst = i286_memoryread(madr); - XORBYTE(dst, src); - i286_memorywrite(madr, (REG8)dst); -} - -I286_8X _cmp_ext8_i(UINT32 madr) { - - UINT src; - UINT dst; - UINT res; - - GET_PCBYTE(src) - dst = i286_memoryread(madr); - SUBBYTE(res, dst, src); -} - - -const I286OP8XREG8 c_op8xreg8_table[] = { - _add_r8_i, _or_r8_i, _adc_r8_i, _sbb_r8_i, - _and_r8_i, _sub_r8_i, _xor_r8_i, _cmp_r8_i}; - -const I286OP8XEXT8 c_op8xext8_table[] = { - _add_ext8_i, _or_ext8_i, _adc_ext8_i, _sbb_ext8_i, - _and_ext8_i, _sub_ext8_i, _xor_ext8_i, _cmp_ext8_i}; - -// ------------------------------------------------------------------------- - -// ----- reg16 - -I286_8X _add_r16_i(UINT16 *p, UINT32 src) { - - UINT32 dst; - UINT32 res; - - dst = *p; - ADDWORD(res, dst, src); - *p = (UINT16)res; -} - -I286_8X _or_r16_i(UINT16 *p, UINT32 src) { - - UINT32 dst; - - dst = *p; - ORWORD(dst, src); - *p = (UINT16)dst; -} - -I286_8X _adc_r16_i(UINT16 *p, UINT32 src) { - - UINT32 dst; - UINT32 res; - - dst = *p; - ADCWORD(res, dst, src); - *p = (UINT16)res; -} - -I286_8X _sbb_r16_i(UINT16 *p, UINT32 src) { - - UINT32 dst; - UINT32 res; - - dst = *p; - SBBWORD(res, dst, src); - *p = (UINT16)res; -} - -I286_8X _and_r16_i(UINT16 *p, UINT32 src) { - - UINT32 dst; - - dst = *p; - ANDWORD(dst, src); - *p = (UINT16)dst; -} - -I286_8X _sub_r16_i(UINT16 *p, UINT32 src) { - - UINT32 dst; - UINT32 res; - - dst = *p; - SUBWORD(res, dst, src); - *p = (UINT16)res; -} - -I286_8X _xor_r16_i(UINT16 *p, UINT32 src) { - - UINT32 dst; - - dst = *p; - XORWORD(dst, src); - *p = (UINT16)dst; -} - -I286_8X _cmp_r16_i(UINT16 *p, UINT32 src) { - - UINT32 dst; - UINT32 res; - - dst = *p; - SUBWORD(res, dst, src); -} - - -// ----- ext16 - -I286_8X _add_ext16_i(UINT32 madr, UINT32 src) { - - UINT32 dst; - UINT32 res; - - dst = i286_memoryread_w(madr); - ADDWORD(res, dst, src); - i286_memorywrite_w(madr, (REG16)res); -} - -I286_8X _or_ext16_i(UINT32 madr, UINT32 src) { - - UINT32 dst; - - dst = i286_memoryread_w(madr); - ORWORD(dst, src); - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_8X _adc_ext16_i(UINT32 madr, UINT32 src) { - - UINT32 dst; - UINT32 res; - - dst = i286_memoryread_w(madr); - ADCWORD(res, dst, src); - i286_memorywrite_w(madr, (REG16)res); -} - -I286_8X _sbb_ext16_i(UINT32 madr, UINT32 src) { - - UINT32 dst; - UINT32 res; - - dst = i286_memoryread_w(madr); - SBBWORD(res, dst, src); - i286_memorywrite_w(madr, (REG16)res); -} - -I286_8X _and_ext16_i(UINT32 madr, UINT32 src) { - - UINT32 dst; - - dst = i286_memoryread_w(madr); - ANDWORD(dst, src); - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_8X _sub_ext16_i(UINT32 madr, UINT32 src) { - - UINT32 dst; - UINT32 res; - - dst = i286_memoryread_w(madr); - SUBWORD(res, dst, src); - i286_memorywrite_w(madr, (REG16)res); -} - -I286_8X _xor_ext16_i(UINT32 madr, UINT32 src) { - - UINT32 dst; - - dst = i286_memoryread_w(madr); - XORWORD(dst, src); - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_8X _cmp_ext16_i(UINT32 madr, UINT32 src) { - - UINT32 dst; - UINT32 res; - - dst = i286_memoryread_w(madr); - SUBWORD(res, dst, src); -} - - -const I286OP8XREG16 c_op8xreg16_table[] = { - _add_r16_i, _or_r16_i, _adc_r16_i, _sbb_r16_i, - _and_r16_i, _sub_r16_i, _xor_r16_i, _cmp_r16_i}; - -const I286OP8XEXT16 c_op8xext16_table[] = { - _add_ext16_i, _or_ext16_i, _adc_ext16_i, _sbb_ext16_i, - _and_ext16_i, _sub_ext16_i, _xor_ext16_i, _cmp_ext16_i}; - +#include +#include +#include "i286c.h" +#include "i286c.mcr" + + +// -------------------------------------------------------- opecode 0x80,1,2,3 + +// ----- reg8 + +I286_8X _add_r8_i(UINT8 *p) { + + UINT src; + UINT dst; + UINT res; + + GET_PCBYTE(src) + dst = *p; + ADDBYTE(res, dst, src); + *p = (UINT8)res; +} + +I286_8X _or_r8_i(UINT8 *p) { + + UINT src; + UINT dst; + + GET_PCBYTE(src) + dst = *p; + ORBYTE(dst, src); + *p = (UINT8)dst; +} + +I286_8X _adc_r8_i(UINT8 *p) { + + UINT src; + UINT dst; + UINT res; + + GET_PCBYTE(src) + dst = *p; + ADCBYTE(res, dst, src); + *p = (UINT8)res; +} + +I286_8X _sbb_r8_i(UINT8 *p) { + + UINT src; + UINT dst; + UINT res; + + GET_PCBYTE(src) + dst = *p; + SBBBYTE(res, dst, src); + *p = (UINT8)res; +} + +I286_8X _and_r8_i(UINT8 *p) { + + UINT src; + UINT dst; + + GET_PCBYTE(src) + dst = *p; + ANDBYTE(dst, src); + *p = (UINT8)dst; +} + +I286_8X _sub_r8_i(UINT8 *p) { + + UINT src; + UINT dst; + UINT res; + + GET_PCBYTE(src) + dst = *p; + SUBBYTE(res, dst, src); + *p = (UINT8)res; +} + +I286_8X _xor_r8_i(UINT8 *p) { + + UINT src; + UINT dst; + + GET_PCBYTE(src) + dst = *p; + XORBYTE(dst, src); + *p = (UINT8)dst; +} + +I286_8X _cmp_r8_i(UINT8 *p) { + + UINT src; + UINT dst; + UINT res; + + GET_PCBYTE(src) + dst = *p; + SUBBYTE(res, dst, src); +} + + +// ----- ext8 + +I286_8X _add_ext8_i(UINT32 madr) { + + UINT src; + UINT dst; + UINT res; + + GET_PCBYTE(src) + dst = i286_memoryread(madr); + ADDBYTE(res, dst, src); + i286_memorywrite(madr, (REG8)res); +} + +I286_8X _or_ext8_i(UINT32 madr) { + + UINT src; + UINT dst; + + GET_PCBYTE(src) + dst = i286_memoryread(madr); + ORBYTE(dst, src); + i286_memorywrite(madr, (REG8)dst); +} + +I286_8X _adc_ext8_i(UINT32 madr) { + + UINT src; + UINT dst; + UINT res; + + GET_PCBYTE(src) + dst = i286_memoryread(madr); + ADCBYTE(res, dst, src); + i286_memorywrite(madr, (REG8)res); +} + +I286_8X _sbb_ext8_i(UINT32 madr) { + + UINT src; + UINT dst; + UINT res; + + GET_PCBYTE(src) + dst = i286_memoryread(madr); + SBBBYTE(res, dst, src); + i286_memorywrite(madr, (REG8)res); +} + +I286_8X _and_ext8_i(UINT32 madr) { + + UINT src; + UINT dst; + + GET_PCBYTE(src) + dst = i286_memoryread(madr); + ANDBYTE(dst, src); + i286_memorywrite(madr, (REG8)dst); +} + +I286_8X _sub_ext8_i(UINT32 madr) { + + UINT src; + UINT dst; + UINT res; + + GET_PCBYTE(src) + dst = i286_memoryread(madr); + SUBBYTE(res, dst, src); + i286_memorywrite(madr, (REG8)res); +} + +I286_8X _xor_ext8_i(UINT32 madr) { + + UINT src; + UINT dst; + + GET_PCBYTE(src) + dst = i286_memoryread(madr); + XORBYTE(dst, src); + i286_memorywrite(madr, (REG8)dst); +} + +I286_8X _cmp_ext8_i(UINT32 madr) { + + UINT src; + UINT dst; + UINT res; + + GET_PCBYTE(src) + dst = i286_memoryread(madr); + SUBBYTE(res, dst, src); +} + + +const I286OP8XREG8 c_op8xreg8_table[] = { + _add_r8_i, _or_r8_i, _adc_r8_i, _sbb_r8_i, + _and_r8_i, _sub_r8_i, _xor_r8_i, _cmp_r8_i}; + +const I286OP8XEXT8 c_op8xext8_table[] = { + _add_ext8_i, _or_ext8_i, _adc_ext8_i, _sbb_ext8_i, + _and_ext8_i, _sub_ext8_i, _xor_ext8_i, _cmp_ext8_i}; + +// ------------------------------------------------------------------------- + +// ----- reg16 + +I286_8X _add_r16_i(UINT16 *p, UINT32 src) { + + UINT32 dst; + UINT32 res; + + dst = *p; + ADDWORD(res, dst, src); + *p = (UINT16)res; +} + +I286_8X _or_r16_i(UINT16 *p, UINT32 src) { + + UINT32 dst; + + dst = *p; + ORWORD(dst, src); + *p = (UINT16)dst; +} + +I286_8X _adc_r16_i(UINT16 *p, UINT32 src) { + + UINT32 dst; + UINT32 res; + + dst = *p; + ADCWORD(res, dst, src); + *p = (UINT16)res; +} + +I286_8X _sbb_r16_i(UINT16 *p, UINT32 src) { + + UINT32 dst; + UINT32 res; + + dst = *p; + SBBWORD(res, dst, src); + *p = (UINT16)res; +} + +I286_8X _and_r16_i(UINT16 *p, UINT32 src) { + + UINT32 dst; + + dst = *p; + ANDWORD(dst, src); + *p = (UINT16)dst; +} + +I286_8X _sub_r16_i(UINT16 *p, UINT32 src) { + + UINT32 dst; + UINT32 res; + + dst = *p; + SUBWORD(res, dst, src); + *p = (UINT16)res; +} + +I286_8X _xor_r16_i(UINT16 *p, UINT32 src) { + + UINT32 dst; + + dst = *p; + XORWORD(dst, src); + *p = (UINT16)dst; +} + +I286_8X _cmp_r16_i(UINT16 *p, UINT32 src) { + + UINT32 dst; + UINT32 res; + + dst = *p; + SUBWORD(res, dst, src); +} + + +// ----- ext16 + +I286_8X _add_ext16_i(UINT32 madr, UINT32 src) { + + UINT32 dst; + UINT32 res; + + dst = i286_memoryread_w(madr); + ADDWORD(res, dst, src); + i286_memorywrite_w(madr, (REG16)res); +} + +I286_8X _or_ext16_i(UINT32 madr, UINT32 src) { + + UINT32 dst; + + dst = i286_memoryread_w(madr); + ORWORD(dst, src); + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_8X _adc_ext16_i(UINT32 madr, UINT32 src) { + + UINT32 dst; + UINT32 res; + + dst = i286_memoryread_w(madr); + ADCWORD(res, dst, src); + i286_memorywrite_w(madr, (REG16)res); +} + +I286_8X _sbb_ext16_i(UINT32 madr, UINT32 src) { + + UINT32 dst; + UINT32 res; + + dst = i286_memoryread_w(madr); + SBBWORD(res, dst, src); + i286_memorywrite_w(madr, (REG16)res); +} + +I286_8X _and_ext16_i(UINT32 madr, UINT32 src) { + + UINT32 dst; + + dst = i286_memoryread_w(madr); + ANDWORD(dst, src); + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_8X _sub_ext16_i(UINT32 madr, UINT32 src) { + + UINT32 dst; + UINT32 res; + + dst = i286_memoryread_w(madr); + SUBWORD(res, dst, src); + i286_memorywrite_w(madr, (REG16)res); +} + +I286_8X _xor_ext16_i(UINT32 madr, UINT32 src) { + + UINT32 dst; + + dst = i286_memoryread_w(madr); + XORWORD(dst, src); + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_8X _cmp_ext16_i(UINT32 madr, UINT32 src) { + + UINT32 dst; + UINT32 res; + + dst = i286_memoryread_w(madr); + SUBWORD(res, dst, src); +} + + +const I286OP8XREG16 c_op8xreg16_table[] = { + _add_r16_i, _or_r16_i, _adc_r16_i, _sbb_r16_i, + _and_r16_i, _sub_r16_i, _xor_r16_i, _cmp_r16_i}; + +const I286OP8XEXT16 c_op8xext16_table[] = { + _add_ext16_i, _or_ext16_i, _adc_ext16_i, _sbb_ext16_i, + _and_ext16_i, _sub_ext16_i, _xor_ext16_i, _cmp_ext16_i}; + diff --git a/i286c/i286c_ea.c b/i286c/i286c_ea.c old mode 100755 new mode 100644 index f2830e5d..3cc08797 --- a/i286c/i286c_ea.c +++ b/i286c/i286c_ea.c @@ -1,991 +1,991 @@ -#include -#include -#include "i286c.h" -#include "i286c.mcr" - - -enum { - EA_BX_SI = 0, - EA_BX_DI, - EA_BP_SI, - EA_BP_DI, - EA_SI, - EA_DI, - EA_DISP16, - EA_BX, - EA_BX_SI_DISP8, - EA_BX_DI_DISP8, - EA_BP_SI_DISP8, - EA_BP_DI_DISP8, - EA_SI_DISP8, - EA_DI_DISP8, - EA_BP_DISP8, - EA_BX_DISP8, - EA_BX_SI_DISP16, - EA_BX_DI_DISP16, - EA_BP_SI_DISP16, - EA_BP_DI_DISP16, - EA_SI_DISP16, - EA_DI_DISP16, - EA_BP_DISP16, - EA_BX_DISP16 -}; - - -#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) - -static UINT32 ea_bx_si(void) { - - return(LOW16(I286_BX + I286_SI) + DS_FIX); -} - -static UINT32 ea_bx_si_disp8(void) { - - SINT32 adrs; - - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BX + I286_SI) + DS_FIX); -} - -static UINT32 ea_bx_si_disp16(void) { - - UINT32 adrs; - - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX + I286_SI) + DS_FIX); -} - -static UINT32 ea_bx_di(void) { - - return(LOW16(I286_BX + I286_DI) + DS_FIX); -} - -static UINT32 ea_bx_di_disp8(void) { - - SINT32 adrs; - - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BX + I286_DI) + DS_FIX); -} - -static UINT32 ea_bx_di_disp16(void) { - - UINT32 adrs; - - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX + I286_DI) + DS_FIX); -} - -static UINT32 ea_bp_si(void) { - - return(LOW16(I286_BP + I286_SI) + SS_FIX); -} - -static UINT32 ea_bp_si_disp8(void) { - - SINT32 adrs; - - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BP + I286_SI) + SS_FIX); -} - -static UINT32 ea_bp_si_disp16(void) { - - UINT32 adrs; - - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP + I286_SI) + SS_FIX); -} - -static UINT32 ea_bp_di(void) { - - return(LOW16(I286_BP + I286_DI) + SS_FIX); -} - -static UINT32 ea_bp_di_disp8(void) { - - SINT32 adrs; - - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BP + I286_DI) + SS_FIX); -} - -static UINT32 ea_bp_di_disp16(void) { - - UINT32 adrs; - - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP + I286_DI) + SS_FIX); -} - -static UINT32 ea_si(void) { - - return(I286_SI + DS_FIX); -} - -static UINT32 ea_si_disp8(void) { - - SINT32 adrs; - - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_SI) + DS_FIX); -} - -static UINT32 ea_si_disp16(void) { - - UINT32 adrs; - - GET_PCWORD(adrs); - return(LOW16(adrs + I286_SI) + DS_FIX); -} - -static UINT32 ea_di(void) { - - return(I286_DI + DS_FIX); -} - -static UINT32 ea_di_disp8(void) { - - SINT32 adrs; - - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_DI) + DS_FIX); -} - -static UINT32 ea_di_disp16(void) { - - UINT32 adrs; - - GET_PCWORD(adrs); - return(LOW16(adrs + I286_DI) + DS_FIX); -} - -static UINT32 ea_disp16(void) { - - UINT32 adrs; - - GET_PCWORD(adrs); - return(adrs + DS_FIX); -} - -static UINT32 ea_bp_disp8(void) { - - SINT32 adrs; - - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BP) + SS_FIX); -} - -static UINT32 ea_bp_disp16(void) { - - UINT32 adrs; - - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP) + SS_FIX); -} - -static UINT32 ea_bx(void) { - - return(I286_BX + DS_FIX); -} - -static UINT32 ea_bx_disp8(void) { - - SINT32 adrs; - - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BX) + DS_FIX); -} - -static UINT32 ea_bx_disp16(void) { - - UINT32 adrs; - - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX) + DS_FIX); -} - -static const CALCEA i286c_ea_dst_tbl[] = { - ea_bx_si, ea_bx_di, - ea_bp_si, ea_bp_di, - ea_si, ea_di, - ea_disp16, ea_bx, - ea_bx_si_disp8, ea_bx_di_disp8, - ea_bp_si_disp8, ea_bp_di_disp8, - ea_si_disp8, ea_di_disp8, - ea_bp_disp8, ea_bx_disp8, - ea_bx_si_disp16, ea_bx_di_disp16, - ea_bp_si_disp16, ea_bp_di_disp16, - ea_si_disp16, ea_di_disp16, - ea_bp_disp16, ea_bx_disp16}; - - -// ---- - -static UINT16 lea_bx_si(void) { - - return(I286_BX + I286_SI); -} - -static UINT16 lea_bx_si_disp8(void) { - - UINT16 adrs; - - GET_PCBYTES(adrs); - return(adrs + I286_BX + I286_SI); -} - -static UINT16 lea_bx_si_disp16(void) { - - UINT16 adrs; - - GET_PCWORD(adrs); - return(adrs + I286_BX + I286_SI); -} - -static UINT16 lea_bx_di(void) { - - return(I286_BX + I286_DI); -} - -static UINT16 lea_bx_di_disp8(void) { - - UINT16 adrs; - - GET_PCBYTES(adrs); - return(adrs + I286_BX + I286_DI); -} - -static UINT16 lea_bx_di_disp16(void) { - - UINT16 adrs; - - GET_PCWORD(adrs); - return(adrs + I286_BX + I286_DI); -} - -static UINT16 lea_bp_si(void) { - - return(I286_BP + I286_SI); -} - -static UINT16 lea_bp_si_disp8(void) { - - UINT16 adrs; - - GET_PCBYTES(adrs); - return(adrs + I286_BP + I286_SI); -} - -static UINT16 lea_bp_si_disp16(void) { - - UINT16 adrs; - - GET_PCWORD(adrs); - return(adrs + I286_BP + I286_SI); -} - -static UINT16 lea_bp_di(void) { - - return(I286_BP + I286_DI); -} - -static UINT16 lea_bp_di_disp8(void) { - - UINT16 adrs; - - GET_PCBYTES(adrs); - return(adrs + I286_BP + I286_DI); -} - -static UINT16 lea_bp_di_disp16(void) { - - UINT16 adrs; - - GET_PCWORD(adrs); - return(adrs + I286_BP + I286_DI); -} - -static UINT16 lea_si(void) { - - return(I286_SI); -} - -static UINT16 lea_si_disp8(void) { - - UINT16 adrs; - - GET_PCBYTES(adrs); - return(adrs + I286_SI); -} - -static UINT16 lea_si_disp16(void) { - - UINT16 adrs; - - GET_PCWORD(adrs); - return(adrs + I286_SI); -} - -static UINT16 lea_di(void) { - - return(I286_DI); -} - -static UINT16 lea_di_disp8(void) { - - UINT16 adrs; - - GET_PCBYTES(adrs); - return(adrs + I286_DI); -} - -static UINT16 lea_di_disp16(void) { - - UINT16 adrs; - - GET_PCWORD(adrs); - return(adrs + I286_DI); -} - -static UINT16 lea_disp16(void) { - - UINT16 adrs; - - GET_PCWORD(adrs); - return(adrs); -} - -static UINT16 lea_bp_disp8(void) { - - UINT16 adrs; - - GET_PCBYTES(adrs); - return(adrs + I286_BP); -} - -static UINT16 lea_bp_disp16(void) { - - UINT16 adrs; - - GET_PCWORD(adrs); - return(adrs + I286_BP); -} - -static UINT16 lea_bx(void) { - - return(I286_BX); -} - -static UINT16 lea_bx_disp8(void) { - - UINT16 adrs; - - GET_PCBYTES(adrs); - return(adrs + I286_BX); -} - -static UINT16 lea_bx_disp16(void) { - - UINT16 adrs; - - GET_PCWORD(adrs); - return(adrs + I286_BX); -} - -static const CALCLEA i286c_lea_tbl[] = { - lea_bx_si, lea_bx_di, - lea_bp_si, lea_bp_di, - lea_si, lea_di, - lea_disp16, lea_bx, - lea_bx_si_disp8, lea_bx_di_disp8, - lea_bp_si_disp8, lea_bp_di_disp8, - lea_si_disp8, lea_di_disp8, - lea_bp_disp8, lea_bx_disp8, - lea_bx_si_disp16, lea_bx_di_disp16, - lea_bp_si_disp16, lea_bp_di_disp16, - lea_si_disp16, lea_di_disp16, - lea_bp_disp16, lea_bx_disp16}; - - -// ---- - -static UINT a_bx_si(UINT32 *seg) { - - *seg = DS_FIX; - return(LOW16(I286_BX + I286_SI)); -} - -static UINT a_bx_si_disp8(UINT32 *seg) { - - UINT adrs; - - *seg = DS_FIX; - GET_PCBYTES(adrs); - return(LOW16(adrs + I286_BX + I286_SI)); -} - -static UINT a_bx_si_disp16(UINT32 *seg) { - - UINT adrs; - - *seg = DS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX + I286_SI)); -} - -static UINT a_bx_di(UINT32 *seg) { - - *seg = DS_FIX; - return(LOW16(I286_BX + I286_DI)); -} - -static UINT a_bx_di_disp8(UINT32 *seg) { - - UINT adrs; - - *seg = DS_FIX; - GET_PCBYTES(adrs); - return(LOW16(adrs + I286_BX + I286_DI)); -} - -static UINT a_bx_di_disp16(UINT32 *seg) { - - UINT adrs; - - *seg = DS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX + I286_DI)); -} - -static UINT a_bp_si(UINT32 *seg) { - - *seg = SS_FIX; - return(LOW16(I286_BP + I286_SI)); -} - -static UINT a_bp_si_disp8(UINT32 *seg) { - - UINT adrs; - - *seg = SS_FIX; - GET_PCBYTES(adrs); - return(LOW16(adrs + I286_BP + I286_SI)); -} - -static UINT a_bp_si_disp16(UINT32 *seg) { - - UINT adrs; - - *seg = SS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP + I286_SI)); -} - -static UINT a_bp_di(UINT32 *seg) { - - *seg = SS_FIX; - return(LOW16(I286_BP + I286_DI)); -} - -static UINT a_bp_di_disp8(UINT32 *seg) { - - UINT adrs; - - *seg = SS_FIX; - GET_PCBYTES(adrs); - return(LOW16(adrs + I286_BP + I286_DI)); -} - -static UINT a_bp_di_disp16(UINT32 *seg) { - - UINT adrs; - - *seg = SS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP + I286_DI)); -} - -static UINT a_si(UINT32 *seg) { - - *seg = DS_FIX; - return(I286_SI); -} - -static UINT a_si_disp8(UINT32 *seg) { - - UINT adrs; - - *seg = DS_FIX; - GET_PCBYTES(adrs); - return(LOW16(adrs + I286_SI)); -} - -static UINT a_si_disp16(UINT32 *seg) { - - UINT adrs; - - *seg = DS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_SI)); -} - -static UINT a_di(UINT32 *seg) { - - *seg = DS_FIX; - return(I286_DI); -} - -static UINT a_di_disp8(UINT32 *seg) { - - UINT adrs; - - *seg = DS_FIX; - GET_PCBYTES(adrs); - return(LOW16(adrs + I286_DI)); -} - -static UINT a_di_disp16(UINT32 *seg) { - - UINT adrs; - - *seg = DS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_DI)); -} - -static UINT a_disp16(UINT32 *seg) { - - UINT adrs; - - *seg = DS_FIX; - GET_PCWORD(adrs); - return(adrs); -} - -static UINT a_bp_disp8(UINT32 *seg) { - - UINT adrs; - - *seg = SS_FIX; - GET_PCBYTES(adrs); - return(LOW16(adrs + I286_BP)); -} - -static UINT a_bp_disp16(UINT32 *seg) { - - UINT adrs; - - *seg = SS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP)); -} - -static UINT a_bx(UINT32 *seg) { - - *seg = DS_FIX; - return(I286_BX); -} - -static UINT a_bx_disp8(UINT32 *seg) { - - UINT adrs; - - *seg = DS_FIX; - GET_PCBYTES(adrs); - return(LOW16(adrs + I286_BX)); -} - -static UINT a_bx_disp16(UINT32 *seg) { - - UINT adrs; - - *seg = DS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX)); -} - -static const GETLEA i286c_ea_tbl[] = { - a_bx_si, a_bx_di, - a_bp_si, a_bp_di, - a_si, a_di, - a_disp16, a_bx, - a_bx_si_disp8, a_bx_di_disp8, - a_bp_si_disp8, a_bp_di_disp8, - a_si_disp8, a_di_disp8, - a_bp_disp8, a_bx_disp8, - a_bx_si_disp16, a_bx_di_disp16, - a_bp_si_disp16, a_bp_di_disp16, - a_si_disp16, a_di_disp16, - a_bp_disp16, a_bx_disp16}; - - -// ---- - - CALCEA _calc_ea_dst[256]; - CALCLEA _calc_lea[192]; - GETLEA _get_ea[192]; - -static UINT32 ea_nop(void) { - - return(0); -} - -void i286cea_initialize(void) { - - UINT i; - UINT pos; - - for (i=0; i<0xc0; i++) { - pos = ((i >> 3) & 0x18) + (i & 0x07); - _calc_ea_dst[i] = i286c_ea_dst_tbl[pos]; - _calc_lea[i] = i286c_lea_tbl[pos]; - _get_ea[i] = i286c_ea_tbl[pos]; - } - for (; i<0x100; i++) { - _calc_ea_dst[i] = ea_nop; - } -} - -#else // ARMだとswitchにしたほーが早いはず… - -UINT32 calc_ea_dst(UINT op) { - - UINT32 adrs; - - switch(((op >> 3) & 0x18) + (op & 0x07)) { - case EA_BX_SI: - return(LOW16(I286_BX + I286_SI) + DS_FIX); - - case EA_BX_SI_DISP8: - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BX + I286_SI) + DS_FIX); - - case EA_BX_SI_DISP16: - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX + I286_SI) + DS_FIX); - - case EA_BX_DI: - return(LOW16(I286_BX + I286_DI) + DS_FIX); - - case EA_BX_DI_DISP8: - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BX + I286_DI) + DS_FIX); - - case EA_BX_DI_DISP16: - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX + I286_DI) + DS_FIX); - - case EA_BP_SI: - return(LOW16(I286_BP + I286_SI) + SS_FIX); - - case EA_BP_SI_DISP8: - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BP + I286_SI) + SS_FIX); - - case EA_BP_SI_DISP16: - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP + I286_SI) + SS_FIX); - - case EA_BP_DI: - return(LOW16(I286_BP + I286_DI) + SS_FIX); - - case EA_BP_DI_DISP8: - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BP + I286_DI) + SS_FIX); - - case EA_BP_DI_DISP16: - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP + I286_DI) + SS_FIX); - - case EA_SI: - return(I286_SI + DS_FIX); - - case EA_SI_DISP8: - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_SI) + DS_FIX); - - case EA_SI_DISP16: - GET_PCWORD(adrs); - return(LOW16(adrs + I286_SI) + DS_FIX); - - case EA_DI: - return(I286_DI + DS_FIX); - - case EA_DI_DISP8: - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_DI) + DS_FIX); - - case EA_DI_DISP16: - GET_PCWORD(adrs); - return(LOW16(adrs + I286_DI) + DS_FIX); - - case EA_BX: - return(I286_BX + DS_FIX); - - case EA_BX_DISP8: - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BX) + DS_FIX); - - case EA_BX_DISP16: - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX) + DS_FIX); - - case EA_BP_DISP8: - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BP) + SS_FIX); - - case EA_BP_DISP16: - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP) + SS_FIX); - - case EA_DISP16: - GET_PCWORD(adrs); - return(adrs + DS_FIX); - - default: - return(0); - } -} - -UINT16 calc_lea(UINT op) { - - UINT16 adrs; - - switch(((op >> 3) & 0x18) + (op & 0x07)) { - case EA_BX_SI: - return(I286_BX + I286_SI); - - case EA_BX_SI_DISP8: - GET_PCBYTESD(adrs); - return(adrs + I286_BX + I286_SI); - - case EA_BX_SI_DISP16: - GET_PCWORD(adrs); - return(adrs + I286_BX + I286_SI); - - case EA_BX_DI: - return(I286_BX + I286_DI); - - case EA_BX_DI_DISP8: - GET_PCBYTESD(adrs); - return(adrs + I286_BX + I286_DI); - - case EA_BX_DI_DISP16: - GET_PCWORD(adrs); - return(adrs + I286_BX + I286_DI); - - case EA_BP_SI: - return(I286_BP + I286_SI); - - case EA_BP_SI_DISP8: - GET_PCBYTESD(adrs); - return(adrs + I286_BP + I286_SI); - - case EA_BP_SI_DISP16: - GET_PCWORD(adrs); - return(adrs + I286_BP + I286_SI); - - case EA_BP_DI: - return(I286_BP + I286_DI); - - case EA_BP_DI_DISP8: - GET_PCBYTESD(adrs); - return(adrs + I286_BP + I286_DI); - - case EA_BP_DI_DISP16: - GET_PCWORD(adrs); - return(adrs + I286_BP + I286_DI); - - case EA_SI: - return(I286_SI); - - case EA_SI_DISP8: - GET_PCBYTESD(adrs); - return(adrs + I286_SI); - - case EA_SI_DISP16: - GET_PCWORD(adrs); - return(adrs + I286_SI); - - case EA_DI: - return(I286_DI); - - case EA_DI_DISP8: - GET_PCBYTESD(adrs); - return(adrs + I286_DI); - - case EA_DI_DISP16: - GET_PCWORD(adrs); - return(adrs + I286_DI); - - case EA_BX: - return(I286_BX); - - case EA_BX_DISP8: - GET_PCBYTESD(adrs); - return(adrs + I286_BX); - - case EA_BX_DISP16: - GET_PCWORD(adrs); - return(adrs + I286_BX); - - case EA_BP_DISP8: - GET_PCBYTESD(adrs); - return(adrs + I286_BP); - - case EA_BP_DISP16: - GET_PCWORD(adrs); - return(adrs + I286_BP); - - case EA_DISP16: - GET_PCWORD(adrs); - return(adrs); - - default: - return(0); - } -} - -UINT calc_a(UINT op, UINT32 *seg) { - - UINT adrs; - - switch(((op >> 3) & 0x18) + (op & 0x07)) { - case EA_BX_SI: - *seg = DS_FIX; - return(LOW16(I286_BX + I286_SI)); - - case EA_BX_SI_DISP8: - *seg = DS_FIX; - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BX + I286_SI)); - - case EA_BX_SI_DISP16: - *seg = DS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX + I286_SI)); - - case EA_BX_DI: - *seg = DS_FIX; - return(LOW16(I286_BX + I286_DI)); - - case EA_BX_DI_DISP8: - *seg = DS_FIX; - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BX + I286_DI)); - - case EA_BX_DI_DISP16: - *seg = DS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX + I286_DI)); - - case EA_BP_SI: - *seg = SS_FIX; - return(LOW16(I286_BP + I286_SI)); - - case EA_BP_SI_DISP8: - *seg = SS_FIX; - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BP + I286_SI)); - - case EA_BP_SI_DISP16: - *seg = SS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP + I286_SI)); - - case EA_BP_DI: - *seg = SS_FIX; - return(LOW16(I286_BP + I286_DI)); - - case EA_BP_DI_DISP8: - *seg = SS_FIX; - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BP + I286_DI)); - - case EA_BP_DI_DISP16: - *seg = SS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP + I286_DI)); - - case EA_SI: - *seg = DS_FIX; - return(I286_SI); - - case EA_SI_DISP8: - *seg = DS_FIX; - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_SI)); - - case EA_SI_DISP16: - *seg = DS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_SI)); - - case EA_DI: - *seg = DS_FIX; - return(I286_DI); - - case EA_DI_DISP8: - *seg = DS_FIX; - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_DI)); - - case EA_DI_DISP16: - *seg = DS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_DI)); - - case EA_BX: - *seg = DS_FIX; - return(I286_BX); - - case EA_BX_DISP8: - *seg = DS_FIX; - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BX)); - - case EA_BX_DISP16: - *seg = DS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BX)); - - case EA_BP_DISP8: - *seg = SS_FIX; - GET_PCBYTESD(adrs); - return(LOW16(adrs + I286_BP)); - - case EA_BP_DISP16: - *seg = SS_FIX; - GET_PCWORD(adrs); - return(LOW16(adrs + I286_BP)); - - case EA_DISP16: - *seg = DS_FIX; - GET_PCWORD(adrs); - return(adrs); - - default: - *seg = 0; - return(0); - } -} - -#endif - - -UINT32 i286c_selector(UINT sel) { - - I286DTR *dtr; - UINT32 addr; - UINT32 ret; - - dtr = (sel & 4)?&I286_LDTRC:&I286_GDTR; - addr = (dtr->base24 << 16) + dtr->base + (sel & (~7)); - ret = i286_memoryread_w(addr+2); - ret += i286_memoryread(addr+4) << 16; - TRACEOUT(("ProtectMode: selector idx=%x %s rpl=%d - real addr = %.6x", - (sel >> 3), (sel & 4)?"LDT":"GDT", sel & 3, ret)); - return(ret); -} - +#include +#include +#include "i286c.h" +#include "i286c.mcr" + + +enum { + EA_BX_SI = 0, + EA_BX_DI, + EA_BP_SI, + EA_BP_DI, + EA_SI, + EA_DI, + EA_DISP16, + EA_BX, + EA_BX_SI_DISP8, + EA_BX_DI_DISP8, + EA_BP_SI_DISP8, + EA_BP_DI_DISP8, + EA_SI_DISP8, + EA_DI_DISP8, + EA_BP_DISP8, + EA_BX_DISP8, + EA_BX_SI_DISP16, + EA_BX_DI_DISP16, + EA_BP_SI_DISP16, + EA_BP_DI_DISP16, + EA_SI_DISP16, + EA_DI_DISP16, + EA_BP_DISP16, + EA_BX_DISP16 +}; + + +#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) + +static UINT32 ea_bx_si(void) { + + return(LOW16(I286_BX + I286_SI) + DS_FIX); +} + +static UINT32 ea_bx_si_disp8(void) { + + SINT32 adrs; + + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BX + I286_SI) + DS_FIX); +} + +static UINT32 ea_bx_si_disp16(void) { + + UINT32 adrs; + + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX + I286_SI) + DS_FIX); +} + +static UINT32 ea_bx_di(void) { + + return(LOW16(I286_BX + I286_DI) + DS_FIX); +} + +static UINT32 ea_bx_di_disp8(void) { + + SINT32 adrs; + + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BX + I286_DI) + DS_FIX); +} + +static UINT32 ea_bx_di_disp16(void) { + + UINT32 adrs; + + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX + I286_DI) + DS_FIX); +} + +static UINT32 ea_bp_si(void) { + + return(LOW16(I286_BP + I286_SI) + SS_FIX); +} + +static UINT32 ea_bp_si_disp8(void) { + + SINT32 adrs; + + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BP + I286_SI) + SS_FIX); +} + +static UINT32 ea_bp_si_disp16(void) { + + UINT32 adrs; + + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP + I286_SI) + SS_FIX); +} + +static UINT32 ea_bp_di(void) { + + return(LOW16(I286_BP + I286_DI) + SS_FIX); +} + +static UINT32 ea_bp_di_disp8(void) { + + SINT32 adrs; + + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BP + I286_DI) + SS_FIX); +} + +static UINT32 ea_bp_di_disp16(void) { + + UINT32 adrs; + + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP + I286_DI) + SS_FIX); +} + +static UINT32 ea_si(void) { + + return(I286_SI + DS_FIX); +} + +static UINT32 ea_si_disp8(void) { + + SINT32 adrs; + + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_SI) + DS_FIX); +} + +static UINT32 ea_si_disp16(void) { + + UINT32 adrs; + + GET_PCWORD(adrs); + return(LOW16(adrs + I286_SI) + DS_FIX); +} + +static UINT32 ea_di(void) { + + return(I286_DI + DS_FIX); +} + +static UINT32 ea_di_disp8(void) { + + SINT32 adrs; + + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_DI) + DS_FIX); +} + +static UINT32 ea_di_disp16(void) { + + UINT32 adrs; + + GET_PCWORD(adrs); + return(LOW16(adrs + I286_DI) + DS_FIX); +} + +static UINT32 ea_disp16(void) { + + UINT32 adrs; + + GET_PCWORD(adrs); + return(adrs + DS_FIX); +} + +static UINT32 ea_bp_disp8(void) { + + SINT32 adrs; + + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BP) + SS_FIX); +} + +static UINT32 ea_bp_disp16(void) { + + UINT32 adrs; + + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP) + SS_FIX); +} + +static UINT32 ea_bx(void) { + + return(I286_BX + DS_FIX); +} + +static UINT32 ea_bx_disp8(void) { + + SINT32 adrs; + + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BX) + DS_FIX); +} + +static UINT32 ea_bx_disp16(void) { + + UINT32 adrs; + + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX) + DS_FIX); +} + +static const CALCEA i286c_ea_dst_tbl[] = { + ea_bx_si, ea_bx_di, + ea_bp_si, ea_bp_di, + ea_si, ea_di, + ea_disp16, ea_bx, + ea_bx_si_disp8, ea_bx_di_disp8, + ea_bp_si_disp8, ea_bp_di_disp8, + ea_si_disp8, ea_di_disp8, + ea_bp_disp8, ea_bx_disp8, + ea_bx_si_disp16, ea_bx_di_disp16, + ea_bp_si_disp16, ea_bp_di_disp16, + ea_si_disp16, ea_di_disp16, + ea_bp_disp16, ea_bx_disp16}; + + +// ---- + +static UINT16 lea_bx_si(void) { + + return(I286_BX + I286_SI); +} + +static UINT16 lea_bx_si_disp8(void) { + + UINT16 adrs; + + GET_PCBYTES(adrs); + return(adrs + I286_BX + I286_SI); +} + +static UINT16 lea_bx_si_disp16(void) { + + UINT16 adrs; + + GET_PCWORD(adrs); + return(adrs + I286_BX + I286_SI); +} + +static UINT16 lea_bx_di(void) { + + return(I286_BX + I286_DI); +} + +static UINT16 lea_bx_di_disp8(void) { + + UINT16 adrs; + + GET_PCBYTES(adrs); + return(adrs + I286_BX + I286_DI); +} + +static UINT16 lea_bx_di_disp16(void) { + + UINT16 adrs; + + GET_PCWORD(adrs); + return(adrs + I286_BX + I286_DI); +} + +static UINT16 lea_bp_si(void) { + + return(I286_BP + I286_SI); +} + +static UINT16 lea_bp_si_disp8(void) { + + UINT16 adrs; + + GET_PCBYTES(adrs); + return(adrs + I286_BP + I286_SI); +} + +static UINT16 lea_bp_si_disp16(void) { + + UINT16 adrs; + + GET_PCWORD(adrs); + return(adrs + I286_BP + I286_SI); +} + +static UINT16 lea_bp_di(void) { + + return(I286_BP + I286_DI); +} + +static UINT16 lea_bp_di_disp8(void) { + + UINT16 adrs; + + GET_PCBYTES(adrs); + return(adrs + I286_BP + I286_DI); +} + +static UINT16 lea_bp_di_disp16(void) { + + UINT16 adrs; + + GET_PCWORD(adrs); + return(adrs + I286_BP + I286_DI); +} + +static UINT16 lea_si(void) { + + return(I286_SI); +} + +static UINT16 lea_si_disp8(void) { + + UINT16 adrs; + + GET_PCBYTES(adrs); + return(adrs + I286_SI); +} + +static UINT16 lea_si_disp16(void) { + + UINT16 adrs; + + GET_PCWORD(adrs); + return(adrs + I286_SI); +} + +static UINT16 lea_di(void) { + + return(I286_DI); +} + +static UINT16 lea_di_disp8(void) { + + UINT16 adrs; + + GET_PCBYTES(adrs); + return(adrs + I286_DI); +} + +static UINT16 lea_di_disp16(void) { + + UINT16 adrs; + + GET_PCWORD(adrs); + return(adrs + I286_DI); +} + +static UINT16 lea_disp16(void) { + + UINT16 adrs; + + GET_PCWORD(adrs); + return(adrs); +} + +static UINT16 lea_bp_disp8(void) { + + UINT16 adrs; + + GET_PCBYTES(adrs); + return(adrs + I286_BP); +} + +static UINT16 lea_bp_disp16(void) { + + UINT16 adrs; + + GET_PCWORD(adrs); + return(adrs + I286_BP); +} + +static UINT16 lea_bx(void) { + + return(I286_BX); +} + +static UINT16 lea_bx_disp8(void) { + + UINT16 adrs; + + GET_PCBYTES(adrs); + return(adrs + I286_BX); +} + +static UINT16 lea_bx_disp16(void) { + + UINT16 adrs; + + GET_PCWORD(adrs); + return(adrs + I286_BX); +} + +static const CALCLEA i286c_lea_tbl[] = { + lea_bx_si, lea_bx_di, + lea_bp_si, lea_bp_di, + lea_si, lea_di, + lea_disp16, lea_bx, + lea_bx_si_disp8, lea_bx_di_disp8, + lea_bp_si_disp8, lea_bp_di_disp8, + lea_si_disp8, lea_di_disp8, + lea_bp_disp8, lea_bx_disp8, + lea_bx_si_disp16, lea_bx_di_disp16, + lea_bp_si_disp16, lea_bp_di_disp16, + lea_si_disp16, lea_di_disp16, + lea_bp_disp16, lea_bx_disp16}; + + +// ---- + +static UINT a_bx_si(UINT32 *seg) { + + *seg = DS_FIX; + return(LOW16(I286_BX + I286_SI)); +} + +static UINT a_bx_si_disp8(UINT32 *seg) { + + UINT adrs; + + *seg = DS_FIX; + GET_PCBYTES(adrs); + return(LOW16(adrs + I286_BX + I286_SI)); +} + +static UINT a_bx_si_disp16(UINT32 *seg) { + + UINT adrs; + + *seg = DS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX + I286_SI)); +} + +static UINT a_bx_di(UINT32 *seg) { + + *seg = DS_FIX; + return(LOW16(I286_BX + I286_DI)); +} + +static UINT a_bx_di_disp8(UINT32 *seg) { + + UINT adrs; + + *seg = DS_FIX; + GET_PCBYTES(adrs); + return(LOW16(adrs + I286_BX + I286_DI)); +} + +static UINT a_bx_di_disp16(UINT32 *seg) { + + UINT adrs; + + *seg = DS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX + I286_DI)); +} + +static UINT a_bp_si(UINT32 *seg) { + + *seg = SS_FIX; + return(LOW16(I286_BP + I286_SI)); +} + +static UINT a_bp_si_disp8(UINT32 *seg) { + + UINT adrs; + + *seg = SS_FIX; + GET_PCBYTES(adrs); + return(LOW16(adrs + I286_BP + I286_SI)); +} + +static UINT a_bp_si_disp16(UINT32 *seg) { + + UINT adrs; + + *seg = SS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP + I286_SI)); +} + +static UINT a_bp_di(UINT32 *seg) { + + *seg = SS_FIX; + return(LOW16(I286_BP + I286_DI)); +} + +static UINT a_bp_di_disp8(UINT32 *seg) { + + UINT adrs; + + *seg = SS_FIX; + GET_PCBYTES(adrs); + return(LOW16(adrs + I286_BP + I286_DI)); +} + +static UINT a_bp_di_disp16(UINT32 *seg) { + + UINT adrs; + + *seg = SS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP + I286_DI)); +} + +static UINT a_si(UINT32 *seg) { + + *seg = DS_FIX; + return(I286_SI); +} + +static UINT a_si_disp8(UINT32 *seg) { + + UINT adrs; + + *seg = DS_FIX; + GET_PCBYTES(adrs); + return(LOW16(adrs + I286_SI)); +} + +static UINT a_si_disp16(UINT32 *seg) { + + UINT adrs; + + *seg = DS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_SI)); +} + +static UINT a_di(UINT32 *seg) { + + *seg = DS_FIX; + return(I286_DI); +} + +static UINT a_di_disp8(UINT32 *seg) { + + UINT adrs; + + *seg = DS_FIX; + GET_PCBYTES(adrs); + return(LOW16(adrs + I286_DI)); +} + +static UINT a_di_disp16(UINT32 *seg) { + + UINT adrs; + + *seg = DS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_DI)); +} + +static UINT a_disp16(UINT32 *seg) { + + UINT adrs; + + *seg = DS_FIX; + GET_PCWORD(adrs); + return(adrs); +} + +static UINT a_bp_disp8(UINT32 *seg) { + + UINT adrs; + + *seg = SS_FIX; + GET_PCBYTES(adrs); + return(LOW16(adrs + I286_BP)); +} + +static UINT a_bp_disp16(UINT32 *seg) { + + UINT adrs; + + *seg = SS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP)); +} + +static UINT a_bx(UINT32 *seg) { + + *seg = DS_FIX; + return(I286_BX); +} + +static UINT a_bx_disp8(UINT32 *seg) { + + UINT adrs; + + *seg = DS_FIX; + GET_PCBYTES(adrs); + return(LOW16(adrs + I286_BX)); +} + +static UINT a_bx_disp16(UINT32 *seg) { + + UINT adrs; + + *seg = DS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX)); +} + +static const GETLEA i286c_ea_tbl[] = { + a_bx_si, a_bx_di, + a_bp_si, a_bp_di, + a_si, a_di, + a_disp16, a_bx, + a_bx_si_disp8, a_bx_di_disp8, + a_bp_si_disp8, a_bp_di_disp8, + a_si_disp8, a_di_disp8, + a_bp_disp8, a_bx_disp8, + a_bx_si_disp16, a_bx_di_disp16, + a_bp_si_disp16, a_bp_di_disp16, + a_si_disp16, a_di_disp16, + a_bp_disp16, a_bx_disp16}; + + +// ---- + + CALCEA _calc_ea_dst[256]; + CALCLEA _calc_lea[192]; + GETLEA _get_ea[192]; + +static UINT32 ea_nop(void) { + + return(0); +} + +void i286cea_initialize(void) { + + UINT i; + UINT pos; + + for (i=0; i<0xc0; i++) { + pos = ((i >> 3) & 0x18) + (i & 0x07); + _calc_ea_dst[i] = i286c_ea_dst_tbl[pos]; + _calc_lea[i] = i286c_lea_tbl[pos]; + _get_ea[i] = i286c_ea_tbl[pos]; + } + for (; i<0x100; i++) { + _calc_ea_dst[i] = ea_nop; + } +} + +#else // ARMだとswitchにしたほーが早いはず… + +UINT32 calc_ea_dst(UINT op) { + + UINT32 adrs; + + switch(((op >> 3) & 0x18) + (op & 0x07)) { + case EA_BX_SI: + return(LOW16(I286_BX + I286_SI) + DS_FIX); + + case EA_BX_SI_DISP8: + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BX + I286_SI) + DS_FIX); + + case EA_BX_SI_DISP16: + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX + I286_SI) + DS_FIX); + + case EA_BX_DI: + return(LOW16(I286_BX + I286_DI) + DS_FIX); + + case EA_BX_DI_DISP8: + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BX + I286_DI) + DS_FIX); + + case EA_BX_DI_DISP16: + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX + I286_DI) + DS_FIX); + + case EA_BP_SI: + return(LOW16(I286_BP + I286_SI) + SS_FIX); + + case EA_BP_SI_DISP8: + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BP + I286_SI) + SS_FIX); + + case EA_BP_SI_DISP16: + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP + I286_SI) + SS_FIX); + + case EA_BP_DI: + return(LOW16(I286_BP + I286_DI) + SS_FIX); + + case EA_BP_DI_DISP8: + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BP + I286_DI) + SS_FIX); + + case EA_BP_DI_DISP16: + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP + I286_DI) + SS_FIX); + + case EA_SI: + return(I286_SI + DS_FIX); + + case EA_SI_DISP8: + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_SI) + DS_FIX); + + case EA_SI_DISP16: + GET_PCWORD(adrs); + return(LOW16(adrs + I286_SI) + DS_FIX); + + case EA_DI: + return(I286_DI + DS_FIX); + + case EA_DI_DISP8: + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_DI) + DS_FIX); + + case EA_DI_DISP16: + GET_PCWORD(adrs); + return(LOW16(adrs + I286_DI) + DS_FIX); + + case EA_BX: + return(I286_BX + DS_FIX); + + case EA_BX_DISP8: + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BX) + DS_FIX); + + case EA_BX_DISP16: + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX) + DS_FIX); + + case EA_BP_DISP8: + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BP) + SS_FIX); + + case EA_BP_DISP16: + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP) + SS_FIX); + + case EA_DISP16: + GET_PCWORD(adrs); + return(adrs + DS_FIX); + + default: + return(0); + } +} + +UINT16 calc_lea(UINT op) { + + UINT16 adrs; + + switch(((op >> 3) & 0x18) + (op & 0x07)) { + case EA_BX_SI: + return(I286_BX + I286_SI); + + case EA_BX_SI_DISP8: + GET_PCBYTESD(adrs); + return(adrs + I286_BX + I286_SI); + + case EA_BX_SI_DISP16: + GET_PCWORD(adrs); + return(adrs + I286_BX + I286_SI); + + case EA_BX_DI: + return(I286_BX + I286_DI); + + case EA_BX_DI_DISP8: + GET_PCBYTESD(adrs); + return(adrs + I286_BX + I286_DI); + + case EA_BX_DI_DISP16: + GET_PCWORD(adrs); + return(adrs + I286_BX + I286_DI); + + case EA_BP_SI: + return(I286_BP + I286_SI); + + case EA_BP_SI_DISP8: + GET_PCBYTESD(adrs); + return(adrs + I286_BP + I286_SI); + + case EA_BP_SI_DISP16: + GET_PCWORD(adrs); + return(adrs + I286_BP + I286_SI); + + case EA_BP_DI: + return(I286_BP + I286_DI); + + case EA_BP_DI_DISP8: + GET_PCBYTESD(adrs); + return(adrs + I286_BP + I286_DI); + + case EA_BP_DI_DISP16: + GET_PCWORD(adrs); + return(adrs + I286_BP + I286_DI); + + case EA_SI: + return(I286_SI); + + case EA_SI_DISP8: + GET_PCBYTESD(adrs); + return(adrs + I286_SI); + + case EA_SI_DISP16: + GET_PCWORD(adrs); + return(adrs + I286_SI); + + case EA_DI: + return(I286_DI); + + case EA_DI_DISP8: + GET_PCBYTESD(adrs); + return(adrs + I286_DI); + + case EA_DI_DISP16: + GET_PCWORD(adrs); + return(adrs + I286_DI); + + case EA_BX: + return(I286_BX); + + case EA_BX_DISP8: + GET_PCBYTESD(adrs); + return(adrs + I286_BX); + + case EA_BX_DISP16: + GET_PCWORD(adrs); + return(adrs + I286_BX); + + case EA_BP_DISP8: + GET_PCBYTESD(adrs); + return(adrs + I286_BP); + + case EA_BP_DISP16: + GET_PCWORD(adrs); + return(adrs + I286_BP); + + case EA_DISP16: + GET_PCWORD(adrs); + return(adrs); + + default: + return(0); + } +} + +UINT calc_a(UINT op, UINT32 *seg) { + + UINT adrs; + + switch(((op >> 3) & 0x18) + (op & 0x07)) { + case EA_BX_SI: + *seg = DS_FIX; + return(LOW16(I286_BX + I286_SI)); + + case EA_BX_SI_DISP8: + *seg = DS_FIX; + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BX + I286_SI)); + + case EA_BX_SI_DISP16: + *seg = DS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX + I286_SI)); + + case EA_BX_DI: + *seg = DS_FIX; + return(LOW16(I286_BX + I286_DI)); + + case EA_BX_DI_DISP8: + *seg = DS_FIX; + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BX + I286_DI)); + + case EA_BX_DI_DISP16: + *seg = DS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX + I286_DI)); + + case EA_BP_SI: + *seg = SS_FIX; + return(LOW16(I286_BP + I286_SI)); + + case EA_BP_SI_DISP8: + *seg = SS_FIX; + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BP + I286_SI)); + + case EA_BP_SI_DISP16: + *seg = SS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP + I286_SI)); + + case EA_BP_DI: + *seg = SS_FIX; + return(LOW16(I286_BP + I286_DI)); + + case EA_BP_DI_DISP8: + *seg = SS_FIX; + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BP + I286_DI)); + + case EA_BP_DI_DISP16: + *seg = SS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP + I286_DI)); + + case EA_SI: + *seg = DS_FIX; + return(I286_SI); + + case EA_SI_DISP8: + *seg = DS_FIX; + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_SI)); + + case EA_SI_DISP16: + *seg = DS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_SI)); + + case EA_DI: + *seg = DS_FIX; + return(I286_DI); + + case EA_DI_DISP8: + *seg = DS_FIX; + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_DI)); + + case EA_DI_DISP16: + *seg = DS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_DI)); + + case EA_BX: + *seg = DS_FIX; + return(I286_BX); + + case EA_BX_DISP8: + *seg = DS_FIX; + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BX)); + + case EA_BX_DISP16: + *seg = DS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BX)); + + case EA_BP_DISP8: + *seg = SS_FIX; + GET_PCBYTESD(adrs); + return(LOW16(adrs + I286_BP)); + + case EA_BP_DISP16: + *seg = SS_FIX; + GET_PCWORD(adrs); + return(LOW16(adrs + I286_BP)); + + case EA_DISP16: + *seg = DS_FIX; + GET_PCWORD(adrs); + return(adrs); + + default: + *seg = 0; + return(0); + } +} + +#endif + + +UINT32 i286c_selector(UINT sel) { + + I286DTR *dtr; + UINT32 addr; + UINT32 ret; + + dtr = (sel & 4)?&I286_LDTRC:&I286_GDTR; + addr = (dtr->base24 << 16) + dtr->base + (sel & (~7)); + ret = i286_memoryread_w(addr+2); + ret += i286_memoryread(addr+4) << 16; + TRACEOUT(("ProtectMode: selector idx=%x %s rpl=%d - real addr = %.6x", + (sel >> 3), (sel & 4)?"LDT":"GDT", sel & 3, ret)); + return(ret); +} + diff --git a/i286c/i286c_f6.c b/i286c/i286c_f6.c old mode 100755 new mode 100644 index a7f7461c..4acda19b --- a/i286c/i286c_f6.c +++ b/i286c/i286c_f6.c @@ -1,329 +1,329 @@ -#include -#include -#include "i286c.h" -#include -#include "i286c.mcr" - - -// ------------------------------------------------------------ opecode 0xf6,7 - -I286_F6 _test_ea8_data8(UINT op) { - - UINT src; - UINT dst; - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - dst = *(REG8_B20(op)); - } - else { - I286_WORKCLOCK(6); - dst = i286_memoryread(CALC_EA(op)); - } - GET_PCBYTE(src) - ANDBYTE(dst, src) -} - -I286_F6 _not_ea8(UINT op) { - - UINT32 madr; - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - *(REG8_B20(op)) ^= 0xff; - } - else { - I286_WORKCLOCK(7); - madr = CALC_EA(op); - if (madr >= I286_MEMWRITEMAX) { - REG8 value = i286_memoryread(madr); - value ^= 0xff; - i286_memorywrite(madr, value); - return; - } - *(mem + madr) ^= 0xff; - } -} - -I286_F6 _neg_ea8(UINT op) { - - UINT8 *out; - UINT src; - UINT dst; - UINT32 madr; - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - out = REG8_B20(op); - } - else { - I286_WORKCLOCK(7); - madr = CALC_EA(op); - if (madr >= I286_MEMWRITEMAX) { - src = i286_memoryread(madr); - NEGBYTE(dst, src) - i286_memorywrite(madr, (REG8)dst); - return; - } - out = mem + madr; - } - src = *out; - NEGBYTE(dst, src) - *out = (UINT8)dst; -} - -I286_F6 _mul_ea8(UINT op) { - - UINT8 src; - UINT res; - - if (op >= 0xc0) { - I286_WORKCLOCK(13); - src = *(REG8_B20(op)); - } - else { - I286_WORKCLOCK(16); - src = i286_memoryread(CALC_EA(op)); - } - BYTE_MUL(res, I286_AL, src) - I286_AX = (UINT16)res; -} - -I286_F6 _imul_ea8(UINT op) { - - UINT8 src; - SINT32 res; - - if (op >= 0xc0) { - I286_WORKCLOCK(13); - src = *(REG8_B20(op)); - } - else { - I286_WORKCLOCK(16); - src = i286_memoryread(CALC_EA(op)); - } - BYTE_IMUL(res, I286_AL, src) - I286_AX = (UINT16)res; -} - -I286_F6 _div_ea8(UINT op) { - - UINT16 tmp; - UINT8 src; - UINT16 ip; - - ip = I286_IP; - if (op >= 0xc0) { - I286_WORKCLOCK(14); - src = *(REG8_B20(op)); - } - else { - I286_WORKCLOCK(17); - src = i286_memoryread(CALC_EA(op)); - } - tmp = I286_AX; - if ((src) && (tmp < ((UINT16)src << 8))) { - I286_AL = tmp / src; - I286_AH = tmp % src; - } - else { - INT_NUM(0, ip - 2); // 80x86 - } -} - -I286_F6 _idiv_ea8(UINT op) { - - SINT16 tmp, r; - SINT8 src; - UINT16 ip; - - ip = I286_IP; - if (op >= 0xc0) { - I286_WORKCLOCK(17); - src = *(REG8_B20(op)); - } - else { - I286_WORKCLOCK(20); - src = i286_memoryread(CALC_EA(op)); - } - tmp = (SINT16)I286_AX; - if (src) { - r = tmp / src; - if (!((r + 0x80) & 0xff00)) { - I286_AL = (UINT8)r; - I286_AH = tmp % src; - return; - } - } - INT_NUM(0, ip - 2); // 80x86 -} - - -I286_F6 _test_ea16_data16(UINT op) { - - UINT32 src; - UINT32 dst; - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - dst = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(6); - dst = i286_memoryread_w(CALC_EA(op)); - } - GET_PCWORD(src) - ANDWORD(dst, src) -} - -I286_F6 _not_ea16(UINT op) { - - UINT32 madr; - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - *(REG16_B20(op)) ^= 0xffff; - } - else { - I286_WORKCLOCK(7); - madr = CALC_EA(op); - if (!(INHIBIT_WORDP(madr))) { - *((UINT16*)(mem + madr)) ^= 0xffff; - } - else { - REG16 value = i286_memoryread_w(madr); - value = ~value; - i286_memorywrite_w(madr, value); - } - } -} - -I286_F6 _neg_ea16(UINT op) { - - UINT16 *out; - UINT32 src; - UINT32 dst; - UINT32 madr; - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - out = REG16_B20(op); - } - else { - I286_WORKCLOCK(7); - madr = CALC_EA(op); - if (INHIBIT_WORDP(madr)) { - src = i286_memoryread_w(madr); - NEGWORD(dst, src) - i286_memorywrite_w(madr, (REG16)dst); - return; - } - out = (UINT16 *)(mem + madr); - } - src = *out; - NEGWORD(dst, src) - *out = (UINT16)dst; -} - -I286_F6 _mul_ea16(UINT op) { - - UINT16 src; - UINT32 res; - - if (op >= 0xc0) { - I286_WORKCLOCK(21); - src = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(24); - src = i286_memoryread_w(CALC_EA(op)); - } - WORD_MUL(res, I286_AX, src) - I286_AX = (UINT16)res; - I286_DX = (UINT16)(res >> 16); -} - -I286_F6 _imul_ea16(UINT op) { - - SINT16 src; - SINT32 res; - - if (op >= 0xc0) { - I286_WORKCLOCK(21); - src = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(24); - src = i286_memoryread_w(CALC_EA(op)); - } - WORD_IMUL(res, I286_AX, src) - I286_AX = (UINT16)res; - I286_DX = (UINT16)(res >> 16); -} - -I286_F6 _div_ea16(UINT op) { - - UINT32 tmp; - UINT32 src; - UINT16 ip; - - ip = I286_IP; - if (op >= 0xc0) { - I286_WORKCLOCK(22); - src = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(25); - src = i286_memoryread_w(CALC_EA(op)); - } - tmp = (I286_DX << 16) + I286_AX; - if ((src) && (tmp < (src << 16))) { - I286_AX = tmp / src; - I286_DX = tmp % src; - } - else { - INT_NUM(0, ip - 2); // 80x86 - } -} - -I286_F6 _idiv_ea16(UINT op) { - - SINT32 tmp; - SINT32 r; - SINT16 src; - UINT16 ip; - - ip = I286_IP; - if (op >= 0xc0) { - I286_WORKCLOCK(25); - src = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(28); - src = i286_memoryread_w(CALC_EA(op)); - } - tmp = (SINT32)((I286_DX << 16) + I286_AX); - if ((src) && (tmp != INT_MIN)) { - r = tmp / src; - if (!((r + 0x8000) & 0xffff0000)) { - I286_AX = (SINT16)r; - I286_DX = tmp % src; - return; - } - } - INT_NUM(0, ip - 2); // 80x86 -} - - -const I286OPF6 c_ope0xf6_table[] = { - _test_ea8_data8, _test_ea8_data8, - _not_ea8, _neg_ea8, - _mul_ea8, _imul_ea8, - _div_ea8, _idiv_ea8}; - -const I286OPF6 c_ope0xf7_table[] = { - _test_ea16_data16, _test_ea16_data16, - _not_ea16, _neg_ea16, - _mul_ea16, _imul_ea16, - _div_ea16, _idiv_ea16}; - +#include +#include +#include "i286c.h" +#include +#include "i286c.mcr" + + +// ------------------------------------------------------------ opecode 0xf6,7 + +I286_F6 _test_ea8_data8(UINT op) { + + UINT src; + UINT dst; + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + dst = *(REG8_B20(op)); + } + else { + I286_WORKCLOCK(6); + dst = i286_memoryread(CALC_EA(op)); + } + GET_PCBYTE(src) + ANDBYTE(dst, src) +} + +I286_F6 _not_ea8(UINT op) { + + UINT32 madr; + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + *(REG8_B20(op)) ^= 0xff; + } + else { + I286_WORKCLOCK(7); + madr = CALC_EA(op); + if (madr >= I286_MEMWRITEMAX) { + REG8 value = i286_memoryread(madr); + value ^= 0xff; + i286_memorywrite(madr, value); + return; + } + *(mem + madr) ^= 0xff; + } +} + +I286_F6 _neg_ea8(UINT op) { + + UINT8 *out; + UINT src; + UINT dst; + UINT32 madr; + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + out = REG8_B20(op); + } + else { + I286_WORKCLOCK(7); + madr = CALC_EA(op); + if (madr >= I286_MEMWRITEMAX) { + src = i286_memoryread(madr); + NEGBYTE(dst, src) + i286_memorywrite(madr, (REG8)dst); + return; + } + out = mem + madr; + } + src = *out; + NEGBYTE(dst, src) + *out = (UINT8)dst; +} + +I286_F6 _mul_ea8(UINT op) { + + UINT8 src; + UINT res; + + if (op >= 0xc0) { + I286_WORKCLOCK(13); + src = *(REG8_B20(op)); + } + else { + I286_WORKCLOCK(16); + src = i286_memoryread(CALC_EA(op)); + } + BYTE_MUL(res, I286_AL, src) + I286_AX = (UINT16)res; +} + +I286_F6 _imul_ea8(UINT op) { + + UINT8 src; + SINT32 res; + + if (op >= 0xc0) { + I286_WORKCLOCK(13); + src = *(REG8_B20(op)); + } + else { + I286_WORKCLOCK(16); + src = i286_memoryread(CALC_EA(op)); + } + BYTE_IMUL(res, I286_AL, src) + I286_AX = (UINT16)res; +} + +I286_F6 _div_ea8(UINT op) { + + UINT16 tmp; + UINT8 src; + UINT16 ip; + + ip = I286_IP; + if (op >= 0xc0) { + I286_WORKCLOCK(14); + src = *(REG8_B20(op)); + } + else { + I286_WORKCLOCK(17); + src = i286_memoryread(CALC_EA(op)); + } + tmp = I286_AX; + if ((src) && (tmp < ((UINT16)src << 8))) { + I286_AL = tmp / src; + I286_AH = tmp % src; + } + else { + INT_NUM(0, ip - 2); // 80x86 + } +} + +I286_F6 _idiv_ea8(UINT op) { + + SINT16 tmp, r; + SINT8 src; + UINT16 ip; + + ip = I286_IP; + if (op >= 0xc0) { + I286_WORKCLOCK(17); + src = *(REG8_B20(op)); + } + else { + I286_WORKCLOCK(20); + src = i286_memoryread(CALC_EA(op)); + } + tmp = (SINT16)I286_AX; + if (src) { + r = tmp / src; + if (!((r + 0x80) & 0xff00)) { + I286_AL = (UINT8)r; + I286_AH = tmp % src; + return; + } + } + INT_NUM(0, ip - 2); // 80x86 +} + + +I286_F6 _test_ea16_data16(UINT op) { + + UINT32 src; + UINT32 dst; + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + dst = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(6); + dst = i286_memoryread_w(CALC_EA(op)); + } + GET_PCWORD(src) + ANDWORD(dst, src) +} + +I286_F6 _not_ea16(UINT op) { + + UINT32 madr; + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + *(REG16_B20(op)) ^= 0xffff; + } + else { + I286_WORKCLOCK(7); + madr = CALC_EA(op); + if (!(INHIBIT_WORDP(madr))) { + *((UINT16*)(mem + madr)) ^= 0xffff; + } + else { + REG16 value = i286_memoryread_w(madr); + value = ~value; + i286_memorywrite_w(madr, value); + } + } +} + +I286_F6 _neg_ea16(UINT op) { + + UINT16 *out; + UINT32 src; + UINT32 dst; + UINT32 madr; + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + out = REG16_B20(op); + } + else { + I286_WORKCLOCK(7); + madr = CALC_EA(op); + if (INHIBIT_WORDP(madr)) { + src = i286_memoryread_w(madr); + NEGWORD(dst, src) + i286_memorywrite_w(madr, (REG16)dst); + return; + } + out = (UINT16 *)(mem + madr); + } + src = *out; + NEGWORD(dst, src) + *out = (UINT16)dst; +} + +I286_F6 _mul_ea16(UINT op) { + + UINT16 src; + UINT32 res; + + if (op >= 0xc0) { + I286_WORKCLOCK(21); + src = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(24); + src = i286_memoryread_w(CALC_EA(op)); + } + WORD_MUL(res, I286_AX, src) + I286_AX = (UINT16)res; + I286_DX = (UINT16)(res >> 16); +} + +I286_F6 _imul_ea16(UINT op) { + + SINT16 src; + SINT32 res; + + if (op >= 0xc0) { + I286_WORKCLOCK(21); + src = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(24); + src = i286_memoryread_w(CALC_EA(op)); + } + WORD_IMUL(res, I286_AX, src) + I286_AX = (UINT16)res; + I286_DX = (UINT16)(res >> 16); +} + +I286_F6 _div_ea16(UINT op) { + + UINT32 tmp; + UINT32 src; + UINT16 ip; + + ip = I286_IP; + if (op >= 0xc0) { + I286_WORKCLOCK(22); + src = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(25); + src = i286_memoryread_w(CALC_EA(op)); + } + tmp = (I286_DX << 16) + I286_AX; + if ((src) && (tmp < (src << 16))) { + I286_AX = tmp / src; + I286_DX = tmp % src; + } + else { + INT_NUM(0, ip - 2); // 80x86 + } +} + +I286_F6 _idiv_ea16(UINT op) { + + SINT32 tmp; + SINT32 r; + SINT16 src; + UINT16 ip; + + ip = I286_IP; + if (op >= 0xc0) { + I286_WORKCLOCK(25); + src = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(28); + src = i286_memoryread_w(CALC_EA(op)); + } + tmp = (SINT32)((I286_DX << 16) + I286_AX); + if ((src) && (tmp != INT_MIN)) { + r = tmp / src; + if (!((r + 0x8000) & 0xffff0000)) { + I286_AX = (SINT16)r; + I286_DX = tmp % src; + return; + } + } + INT_NUM(0, ip - 2); // 80x86 +} + + +const I286OPF6 c_ope0xf6_table[] = { + _test_ea8_data8, _test_ea8_data8, + _not_ea8, _neg_ea8, + _mul_ea8, _imul_ea8, + _div_ea8, _idiv_ea8}; + +const I286OPF6 c_ope0xf7_table[] = { + _test_ea16_data16, _test_ea16_data16, + _not_ea16, _neg_ea16, + _mul_ea16, _imul_ea16, + _div_ea16, _idiv_ea16}; + diff --git a/i286c/i286c_fe.c b/i286c/i286c_fe.c old mode 100755 new mode 100644 index fc8bfd47..858d92be --- a/i286c/i286c_fe.c +++ b/i286c/i286c_fe.c @@ -1,222 +1,222 @@ -#include -#include -#include "i286c.h" -#include "i286c.mcr" - - -// ------------------------------------------------------------ opecode 0xfe,f - -#if 0 -I286_F6 _nop_int(UINT op) { - - INT_NUM(6, I286_IP - 2); -} -#endif - -I286_F6 _inc_ea8(UINT op) { - - UINT32 madr; - UINT8 *out; - REG8 res; - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - out = REG8_B20(op); - } - else { - I286_WORKCLOCK(7); - madr = CALC_EA(op); - if (madr >= I286_MEMWRITEMAX) { - res = i286_memoryread(madr); - INCBYTE(res) - i286_memorywrite(madr, res); - return; - } - out = mem + madr; - } - res = *out; - INCBYTE(res) - *out = (UINT8)res; -} - -I286_F6 _dec_ea8(UINT op) { - - UINT32 madr; - UINT8 *out; - REG8 res; - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - out = REG8_B20(op); - } - else { - I286_WORKCLOCK(7); - madr = CALC_EA(op); - if (madr >= I286_MEMWRITEMAX) { - res = i286_memoryread(madr); - DECBYTE(res) - i286_memorywrite(madr, res); - return; - } - out = mem + madr; - } - res = *out; - DECBYTE(res) - *out = (UINT8)res; -} - -I286_F6 _inc_ea16(UINT op) { - - UINT32 madr; - UINT16 *out; - REG16 res; - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - out = REG16_B20(op); - } - else { - I286_WORKCLOCK(7); - madr = CALC_EA(op); - if (INHIBIT_WORDP(madr)) { - res = i286_memoryread_w(madr); - INCWORD(res) - i286_memorywrite_w(madr, res); - return; - } - out = (UINT16 *)(mem + madr); - } - res = *out; - INCWORD(res) - *out = (UINT16)res; -} - -I286_F6 _dec_ea16(UINT op) { - - UINT32 madr; - UINT16 *out; - REG16 res; - - if (op >= 0xc0) { - I286_WORKCLOCK(2); - out = REG16_B20(op); - } - else { - I286_WORKCLOCK(7); - madr = CALC_EA(op); - if (INHIBIT_WORDP(madr)) { - res = i286_memoryread_w(madr); - DECWORD(res) - i286_memorywrite_w(madr, res); - return; - } - out = (UINT16 *)(mem + madr); - } - res = *out; - DECWORD(res) - *out = (UINT16)res; -} - -I286_F6 _call_ea16(UINT op) { - - UINT16 src; - - if (op >= 0xc0) { - I286_WORKCLOCK(7); - src = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(11); - src = i286_memoryread_w(CALC_EA(op)); - } - REGPUSH0(I286_IP); - I286_IP = src; -} - -I286_F6 _call_far_ea16(UINT op) { - - UINT32 seg; - UINT ad; - - I286_WORKCLOCK(16); - if (op < 0xc0) { - ad = GET_EA(op, &seg); - REGPUSH0(I286_CS) // ToDo - REGPUSH0(I286_IP) - I286_IP = i286_memoryread_w(seg + ad); - I286_CS = i286_memoryread_w(seg + LOW16(ad + 2)); - CS_BASE = SEGSELECT(I286_CS); - } - else { - INT_NUM(6, I286_IP - 2); - } -} - -I286_F6 _jmp_ea16(UINT op) { - - if (op >= 0xc0) { - I286_WORKCLOCK(7); - I286_IP = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(11); - I286_IP = i286_memoryread_w(CALC_EA(op)); - } -} - -I286_F6 _jmp_far_ea16(UINT op) { - - UINT32 seg; - UINT ad; - - I286_WORKCLOCK(11); - if (op < 0xc0) { - ad = GET_EA(op, &seg); - I286_IP = i286_memoryread_w(seg + ad); - I286_CS = i286_memoryread_w(seg + LOW16(ad + 2)); - CS_BASE = SEGSELECT(I286_CS); - } - else { - INT_NUM(6, I286_IP - 2); - } -} - -I286_F6 _push_ea16(UINT op) { - - UINT16 src; - - if (op >= 0xc0) { - I286_WORKCLOCK(3); - src = *(REG16_B20(op)); - } - else { - I286_WORKCLOCK(5); - src = i286_memoryread_w(CALC_EA(op)); - } - REGPUSH0(src); -} - -I286_F6 _pop_ea16(UINT op) { - - UINT16 src; - - REGPOP0(src); - I286_WORKCLOCK(5); - if (op >= 0xc0) { - *(REG16_B20(op)) = src; - } - else { - i286_memorywrite_w(CALC_EA(op), src); - } -} - - -const I286OPF6 c_ope0xfe_table[] = { - _inc_ea8, _dec_ea8}; - -const I286OPF6 c_ope0xff_table[] = { - _inc_ea16, _dec_ea16, - _call_ea16, _call_far_ea16, - _jmp_ea16, _jmp_far_ea16, - _push_ea16, _pop_ea16}; - +#include +#include +#include "i286c.h" +#include "i286c.mcr" + + +// ------------------------------------------------------------ opecode 0xfe,f + +#if 0 +I286_F6 _nop_int(UINT op) { + + INT_NUM(6, I286_IP - 2); +} +#endif + +I286_F6 _inc_ea8(UINT op) { + + UINT32 madr; + UINT8 *out; + REG8 res; + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + out = REG8_B20(op); + } + else { + I286_WORKCLOCK(7); + madr = CALC_EA(op); + if (madr >= I286_MEMWRITEMAX) { + res = i286_memoryread(madr); + INCBYTE(res) + i286_memorywrite(madr, res); + return; + } + out = mem + madr; + } + res = *out; + INCBYTE(res) + *out = (UINT8)res; +} + +I286_F6 _dec_ea8(UINT op) { + + UINT32 madr; + UINT8 *out; + REG8 res; + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + out = REG8_B20(op); + } + else { + I286_WORKCLOCK(7); + madr = CALC_EA(op); + if (madr >= I286_MEMWRITEMAX) { + res = i286_memoryread(madr); + DECBYTE(res) + i286_memorywrite(madr, res); + return; + } + out = mem + madr; + } + res = *out; + DECBYTE(res) + *out = (UINT8)res; +} + +I286_F6 _inc_ea16(UINT op) { + + UINT32 madr; + UINT16 *out; + REG16 res; + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + out = REG16_B20(op); + } + else { + I286_WORKCLOCK(7); + madr = CALC_EA(op); + if (INHIBIT_WORDP(madr)) { + res = i286_memoryread_w(madr); + INCWORD(res) + i286_memorywrite_w(madr, res); + return; + } + out = (UINT16 *)(mem + madr); + } + res = *out; + INCWORD(res) + *out = (UINT16)res; +} + +I286_F6 _dec_ea16(UINT op) { + + UINT32 madr; + UINT16 *out; + REG16 res; + + if (op >= 0xc0) { + I286_WORKCLOCK(2); + out = REG16_B20(op); + } + else { + I286_WORKCLOCK(7); + madr = CALC_EA(op); + if (INHIBIT_WORDP(madr)) { + res = i286_memoryread_w(madr); + DECWORD(res) + i286_memorywrite_w(madr, res); + return; + } + out = (UINT16 *)(mem + madr); + } + res = *out; + DECWORD(res) + *out = (UINT16)res; +} + +I286_F6 _call_ea16(UINT op) { + + UINT16 src; + + if (op >= 0xc0) { + I286_WORKCLOCK(7); + src = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(11); + src = i286_memoryread_w(CALC_EA(op)); + } + REGPUSH0(I286_IP); + I286_IP = src; +} + +I286_F6 _call_far_ea16(UINT op) { + + UINT32 seg; + UINT ad; + + I286_WORKCLOCK(16); + if (op < 0xc0) { + ad = GET_EA(op, &seg); + REGPUSH0(I286_CS) // ToDo + REGPUSH0(I286_IP) + I286_IP = i286_memoryread_w(seg + ad); + I286_CS = i286_memoryread_w(seg + LOW16(ad + 2)); + CS_BASE = SEGSELECT(I286_CS); + } + else { + INT_NUM(6, I286_IP - 2); + } +} + +I286_F6 _jmp_ea16(UINT op) { + + if (op >= 0xc0) { + I286_WORKCLOCK(7); + I286_IP = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(11); + I286_IP = i286_memoryread_w(CALC_EA(op)); + } +} + +I286_F6 _jmp_far_ea16(UINT op) { + + UINT32 seg; + UINT ad; + + I286_WORKCLOCK(11); + if (op < 0xc0) { + ad = GET_EA(op, &seg); + I286_IP = i286_memoryread_w(seg + ad); + I286_CS = i286_memoryread_w(seg + LOW16(ad + 2)); + CS_BASE = SEGSELECT(I286_CS); + } + else { + INT_NUM(6, I286_IP - 2); + } +} + +I286_F6 _push_ea16(UINT op) { + + UINT16 src; + + if (op >= 0xc0) { + I286_WORKCLOCK(3); + src = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(5); + src = i286_memoryread_w(CALC_EA(op)); + } + REGPUSH0(src); +} + +I286_F6 _pop_ea16(UINT op) { + + UINT16 src; + + REGPOP0(src); + I286_WORKCLOCK(5); + if (op >= 0xc0) { + *(REG16_B20(op)) = src; + } + else { + i286_memorywrite_w(CALC_EA(op), src); + } +} + + +const I286OPF6 c_ope0xfe_table[] = { + _inc_ea8, _dec_ea8}; + +const I286OPF6 c_ope0xff_table[] = { + _inc_ea16, _dec_ea16, + _call_ea16, _call_far_ea16, + _jmp_ea16, _jmp_far_ea16, + _push_ea16, _pop_ea16}; + diff --git a/i286c/i286c_rp.c b/i286c/i286c_rp.c old mode 100755 new mode 100644 index 5ead2705..33b7e1b0 --- a/i286c/i286c_rp.c +++ b/i286c/i286c_rp.c @@ -1,423 +1,423 @@ -#include -#include -#include "i286c.h" -#include -#include -#include "i286c.mcr" - - -// ---------------------------------------------------------------------- ins - -I286EXT i286c_rep_insb(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIR; - do { - REG8 dat = iocore_inp8(I286_DX); - i286_memorywrite(I286_DI + ES_BASE, dat); - I286_DI += stp; - I286_WORKCLOCK(4); - } while (--I286_CX); - } -} - -I286EXT i286c_rep_insw(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIRx2; - do { - REG16 dat = iocore_inp16(I286_DX); - i286_memorywrite_w(I286_DI + ES_BASE, dat); - I286_DI += stp; - I286_WORKCLOCK(4); - } while(--I286_CX); - } -} - -// ---------------------------------------------------------------------- outs - -I286EXT i286c_rep_outsb(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIR; - do { - REG8 dat = i286_memoryread(I286_SI + DS_FIX); - I286_SI += stp; - iocore_out8(I286_DX, (UINT8)dat); - I286_WORKCLOCK(4); - } while(--I286_CX); - } -} - -I286EXT i286c_rep_outsw(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIRx2; - do { - REG16 dat = i286_memoryread_w(I286_SI + DS_FIX); - I286_SI += stp; - iocore_out16(I286_DX, (UINT16)dat); - I286_WORKCLOCK(4); - } while(--I286_CX); - } -} - - -// ---------------------------------------------------------------------- movs - -#if 1 -I286EXT i286c_rep_movsb(void) { - - UINT16 r_cx; - int stp; - UINT16 r_si; - UINT16 r_di; - - I286_WORKCLOCK(5); - r_cx = I286_CX; - if (r_cx) { - stp = STRING_DIR; - r_si = I286_SI; - r_di = I286_DI; - while(1) { - REG8 dat = i286_memoryread(DS_FIX + r_si); - i286_memorywrite(ES_BASE + r_di, dat); - r_si += stp; - r_di += stp; - I286_WORKCLOCK(4); - r_cx--; - if (!r_cx) { - break; - } - if (I286_REMCLOCK <= 0) { - I286_IP -= I286_PREFIX + 1; - break; - } - } - I286_CX = r_cx; - I286_SI = r_si; - I286_DI = r_di; - } -} - -I286EXT i286c_rep_movsw(void) { - - UINT16 r_cx; - int stp; - UINT16 r_si; - UINT16 r_di; - - I286_WORKCLOCK(5); - r_cx = I286_CX; - if (r_cx) { - stp = STRING_DIRx2; - r_si = I286_SI; - r_di = I286_DI; - while(1) { - REG16 dat = i286_memoryread_w(DS_FIX + r_si); - i286_memorywrite_w(ES_BASE + r_di, dat); - r_si += stp; - r_di += stp; - I286_WORKCLOCK(4); - r_cx--; - if (!r_cx) { - break; - } - if (I286_REMCLOCK <= 0) { - I286_IP -= I286_PREFIX + 1; - break; - } - } - I286_CX = r_cx; - I286_SI = r_si; - I286_DI = r_di; - } -} -#else -I286EXT i286c_rep_movsb(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIR; - while(1) { - REG8 dat = i286_memoryread(I286_SI + DS_FIX); - i286_memorywrite(I286_DI + ES_BASE, dat); - I286_SI += stp; - I286_DI += stp; - I286_WORKCLOCK(4); - I286_CX--; - if (!I286_CX) { - break; - } - if (I286_REMCLOCK <= 0) { - I286_IP -= I286_PREFIX + 1; - break; - } - } - } -} - -I286EXT i286c_rep_movsw(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIRx2; - while(1) { - REG16 dat = i286_memoryread_w(I286_SI + DS_FIX); - i286_memorywrite_w(I286_DI + ES_BASE, dat); - I286_SI += stp; - I286_DI += stp; - I286_WORKCLOCK(4); - I286_CX--; - if (!I286_CX) { - break; - } - if (I286_REMCLOCK <= 0) { - I286_IP -= I286_PREFIX + 1; - break; - } - } - } -} -#endif - - -// ---------------------------------------------------------------------- lods - -I286EXT i286c_rep_lodsb(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIR; - while(1) { - I286_AL = i286_memoryread(I286_SI + DS_FIX); - I286_SI += stp; - I286_WORKCLOCK(4); - I286_CX--; - if (!I286_CX) { - break; - } - if (I286_REMCLOCK <= 0) { - I286_IP -= I286_PREFIX + 1; - break; - } - } - } -} - -I286EXT i286c_rep_lodsw(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIRx2; - while(1) { - I286_AX = i286_memoryread_w(I286_SI + DS_FIX); - I286_SI += stp; - I286_WORKCLOCK(4); - I286_CX--; - if (!I286_CX) { - break; - } - if (I286_REMCLOCK <= 0) { - I286_IP -= I286_PREFIX + 1; - break; - } - } - } -} - - -// ---------------------------------------------------------------------- stos - -I286EXT i286c_rep_stosb(void) { - - I286_WORKCLOCK(4); - if (I286_CX) { - int stp = STRING_DIR; - while(1) { - i286_memorywrite(I286_DI + ES_BASE, I286_AL); - I286_DI += stp; - I286_WORKCLOCK(3); - I286_CX--; - if (!I286_CX) { - break; - } - if (I286_REMCLOCK <= 0) { - I286_IP -= I286_PREFIX + 1; - break; - } - } - } -} - -I286EXT i286c_rep_stosw(void) { - - I286_WORKCLOCK(4); - if (I286_CX) { - int stp = STRING_DIRx2; - while(1) { - i286_memorywrite_w(I286_DI + ES_BASE, I286_AX); - I286_DI += stp; - I286_WORKCLOCK(3); - I286_CX--; - if (!I286_CX) { - break; - } - if (I286_REMCLOCK <= 0) { - I286_IP -= I286_PREFIX + 1; - break; - } - } - } -} - - -// ---------------------------------------------------------------------- cmps - -I286EXT i286c_repe_cmpsb(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIR; - do { - UINT res; - UINT dst = i286_memoryread(I286_SI + DS_FIX); - UINT src = i286_memoryread(I286_DI + ES_BASE); - I286_SI += stp; - I286_DI += stp; - I286_WORKCLOCK(9); - SUBBYTE(res, dst, src) - I286_CX--; - } while((I286_CX) && (I286_FLAGL & Z_FLAG)); - } -} - -I286EXT i286c_repne_cmpsb(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIR; - do { - UINT res; - UINT dst = i286_memoryread(I286_SI + DS_FIX); - UINT src = i286_memoryread(I286_DI + ES_BASE); - I286_SI += stp; - I286_DI += stp; - I286_WORKCLOCK(9); - SUBBYTE(res, dst, src) - I286_CX--; - } while((I286_CX) && (!(I286_FLAGL & Z_FLAG))); - } -} - -I286EXT i286c_repe_cmpsw(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIRx2; - do { - UINT32 res; - UINT32 dst = i286_memoryread_w(I286_SI + DS_FIX); - UINT32 src = i286_memoryread_w(I286_DI + ES_BASE); - I286_SI += stp; - I286_DI += stp; - I286_WORKCLOCK(9); - SUBWORD(res, dst, src) - I286_CX--; - } while((I286_CX) && (I286_FLAGL & Z_FLAG)); - } -} - -I286EXT i286c_repne_cmpsw(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIRx2; - do { - UINT32 res; - UINT32 dst = i286_memoryread_w(I286_SI + DS_FIX); - UINT32 src = i286_memoryread_w(I286_DI + ES_BASE); - I286_SI += stp; - I286_DI += stp; - I286_WORKCLOCK(9); - SUBWORD(res, dst, src) - I286_CX--; - } while((I286_CX) && (!(I286_FLAGL & Z_FLAG))); - } -} - - -// ---------------------------------------------------------------------- scas - -I286EXT i286c_repe_scasb(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIR; - UINT dst = I286_AL; - do { - UINT res; - UINT src = i286_memoryread(I286_DI + ES_BASE); - I286_DI += stp; - I286_WORKCLOCK(8); - SUBBYTE(res, dst, src) - I286_CX--; - } while((I286_CX) && (I286_FLAGL & Z_FLAG)); - } -} - -I286EXT i286c_repne_scasb(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIR; - UINT dst = I286_AL; - do { - UINT res; - UINT src = i286_memoryread(I286_DI + ES_BASE); - I286_DI += stp; - I286_WORKCLOCK(8); - SUBBYTE(res, dst, src) - I286_CX--; - } while((I286_CX) && (!(I286_FLAGL & Z_FLAG))); - } -} - -I286EXT i286c_repe_scasw(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIRx2; - UINT32 dst = I286_AX; - do { - UINT32 res; - UINT32 src = i286_memoryread_w(I286_DI + ES_BASE); - I286_DI += stp; - I286_WORKCLOCK(8); - SUBWORD(res, dst, src) - I286_CX--; - } while((I286_CX) && (I286_FLAGL & Z_FLAG)); - } -} - -I286EXT i286c_repne_scasw(void) { - - I286_WORKCLOCK(5); - if (I286_CX) { - int stp = STRING_DIRx2; - UINT32 dst = I286_AX; - do { - UINT32 res; - UINT32 src = i286_memoryread_w(I286_DI + ES_BASE); - I286_DI += stp; - I286_WORKCLOCK(8); - SUBWORD(res, dst, src) - I286_CX--; - } while((I286_CX) && (!(I286_FLAGL & Z_FLAG))); - } -} - +#include +#include +#include "i286c.h" +#include +#include +#include "i286c.mcr" + + +// ---------------------------------------------------------------------- ins + +I286EXT i286c_rep_insb(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIR; + do { + REG8 dat = iocore_inp8(I286_DX); + i286_memorywrite(I286_DI + ES_BASE, dat); + I286_DI += stp; + I286_WORKCLOCK(4); + } while (--I286_CX); + } +} + +I286EXT i286c_rep_insw(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIRx2; + do { + REG16 dat = iocore_inp16(I286_DX); + i286_memorywrite_w(I286_DI + ES_BASE, dat); + I286_DI += stp; + I286_WORKCLOCK(4); + } while(--I286_CX); + } +} + +// ---------------------------------------------------------------------- outs + +I286EXT i286c_rep_outsb(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIR; + do { + REG8 dat = i286_memoryread(I286_SI + DS_FIX); + I286_SI += stp; + iocore_out8(I286_DX, (UINT8)dat); + I286_WORKCLOCK(4); + } while(--I286_CX); + } +} + +I286EXT i286c_rep_outsw(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIRx2; + do { + REG16 dat = i286_memoryread_w(I286_SI + DS_FIX); + I286_SI += stp; + iocore_out16(I286_DX, (UINT16)dat); + I286_WORKCLOCK(4); + } while(--I286_CX); + } +} + + +// ---------------------------------------------------------------------- movs + +#if 1 +I286EXT i286c_rep_movsb(void) { + + UINT16 r_cx; + int stp; + UINT16 r_si; + UINT16 r_di; + + I286_WORKCLOCK(5); + r_cx = I286_CX; + if (r_cx) { + stp = STRING_DIR; + r_si = I286_SI; + r_di = I286_DI; + while(1) { + REG8 dat = i286_memoryread(DS_FIX + r_si); + i286_memorywrite(ES_BASE + r_di, dat); + r_si += stp; + r_di += stp; + I286_WORKCLOCK(4); + r_cx--; + if (!r_cx) { + break; + } + if (I286_REMCLOCK <= 0) { + I286_IP -= I286_PREFIX + 1; + break; + } + } + I286_CX = r_cx; + I286_SI = r_si; + I286_DI = r_di; + } +} + +I286EXT i286c_rep_movsw(void) { + + UINT16 r_cx; + int stp; + UINT16 r_si; + UINT16 r_di; + + I286_WORKCLOCK(5); + r_cx = I286_CX; + if (r_cx) { + stp = STRING_DIRx2; + r_si = I286_SI; + r_di = I286_DI; + while(1) { + REG16 dat = i286_memoryread_w(DS_FIX + r_si); + i286_memorywrite_w(ES_BASE + r_di, dat); + r_si += stp; + r_di += stp; + I286_WORKCLOCK(4); + r_cx--; + if (!r_cx) { + break; + } + if (I286_REMCLOCK <= 0) { + I286_IP -= I286_PREFIX + 1; + break; + } + } + I286_CX = r_cx; + I286_SI = r_si; + I286_DI = r_di; + } +} +#else +I286EXT i286c_rep_movsb(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIR; + while(1) { + REG8 dat = i286_memoryread(I286_SI + DS_FIX); + i286_memorywrite(I286_DI + ES_BASE, dat); + I286_SI += stp; + I286_DI += stp; + I286_WORKCLOCK(4); + I286_CX--; + if (!I286_CX) { + break; + } + if (I286_REMCLOCK <= 0) { + I286_IP -= I286_PREFIX + 1; + break; + } + } + } +} + +I286EXT i286c_rep_movsw(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIRx2; + while(1) { + REG16 dat = i286_memoryread_w(I286_SI + DS_FIX); + i286_memorywrite_w(I286_DI + ES_BASE, dat); + I286_SI += stp; + I286_DI += stp; + I286_WORKCLOCK(4); + I286_CX--; + if (!I286_CX) { + break; + } + if (I286_REMCLOCK <= 0) { + I286_IP -= I286_PREFIX + 1; + break; + } + } + } +} +#endif + + +// ---------------------------------------------------------------------- lods + +I286EXT i286c_rep_lodsb(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIR; + while(1) { + I286_AL = i286_memoryread(I286_SI + DS_FIX); + I286_SI += stp; + I286_WORKCLOCK(4); + I286_CX--; + if (!I286_CX) { + break; + } + if (I286_REMCLOCK <= 0) { + I286_IP -= I286_PREFIX + 1; + break; + } + } + } +} + +I286EXT i286c_rep_lodsw(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIRx2; + while(1) { + I286_AX = i286_memoryread_w(I286_SI + DS_FIX); + I286_SI += stp; + I286_WORKCLOCK(4); + I286_CX--; + if (!I286_CX) { + break; + } + if (I286_REMCLOCK <= 0) { + I286_IP -= I286_PREFIX + 1; + break; + } + } + } +} + + +// ---------------------------------------------------------------------- stos + +I286EXT i286c_rep_stosb(void) { + + I286_WORKCLOCK(4); + if (I286_CX) { + int stp = STRING_DIR; + while(1) { + i286_memorywrite(I286_DI + ES_BASE, I286_AL); + I286_DI += stp; + I286_WORKCLOCK(3); + I286_CX--; + if (!I286_CX) { + break; + } + if (I286_REMCLOCK <= 0) { + I286_IP -= I286_PREFIX + 1; + break; + } + } + } +} + +I286EXT i286c_rep_stosw(void) { + + I286_WORKCLOCK(4); + if (I286_CX) { + int stp = STRING_DIRx2; + while(1) { + i286_memorywrite_w(I286_DI + ES_BASE, I286_AX); + I286_DI += stp; + I286_WORKCLOCK(3); + I286_CX--; + if (!I286_CX) { + break; + } + if (I286_REMCLOCK <= 0) { + I286_IP -= I286_PREFIX + 1; + break; + } + } + } +} + + +// ---------------------------------------------------------------------- cmps + +I286EXT i286c_repe_cmpsb(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIR; + do { + UINT res; + UINT dst = i286_memoryread(I286_SI + DS_FIX); + UINT src = i286_memoryread(I286_DI + ES_BASE); + I286_SI += stp; + I286_DI += stp; + I286_WORKCLOCK(9); + SUBBYTE(res, dst, src) + I286_CX--; + } while((I286_CX) && (I286_FLAGL & Z_FLAG)); + } +} + +I286EXT i286c_repne_cmpsb(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIR; + do { + UINT res; + UINT dst = i286_memoryread(I286_SI + DS_FIX); + UINT src = i286_memoryread(I286_DI + ES_BASE); + I286_SI += stp; + I286_DI += stp; + I286_WORKCLOCK(9); + SUBBYTE(res, dst, src) + I286_CX--; + } while((I286_CX) && (!(I286_FLAGL & Z_FLAG))); + } +} + +I286EXT i286c_repe_cmpsw(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIRx2; + do { + UINT32 res; + UINT32 dst = i286_memoryread_w(I286_SI + DS_FIX); + UINT32 src = i286_memoryread_w(I286_DI + ES_BASE); + I286_SI += stp; + I286_DI += stp; + I286_WORKCLOCK(9); + SUBWORD(res, dst, src) + I286_CX--; + } while((I286_CX) && (I286_FLAGL & Z_FLAG)); + } +} + +I286EXT i286c_repne_cmpsw(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIRx2; + do { + UINT32 res; + UINT32 dst = i286_memoryread_w(I286_SI + DS_FIX); + UINT32 src = i286_memoryread_w(I286_DI + ES_BASE); + I286_SI += stp; + I286_DI += stp; + I286_WORKCLOCK(9); + SUBWORD(res, dst, src) + I286_CX--; + } while((I286_CX) && (!(I286_FLAGL & Z_FLAG))); + } +} + + +// ---------------------------------------------------------------------- scas + +I286EXT i286c_repe_scasb(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIR; + UINT dst = I286_AL; + do { + UINT res; + UINT src = i286_memoryread(I286_DI + ES_BASE); + I286_DI += stp; + I286_WORKCLOCK(8); + SUBBYTE(res, dst, src) + I286_CX--; + } while((I286_CX) && (I286_FLAGL & Z_FLAG)); + } +} + +I286EXT i286c_repne_scasb(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIR; + UINT dst = I286_AL; + do { + UINT res; + UINT src = i286_memoryread(I286_DI + ES_BASE); + I286_DI += stp; + I286_WORKCLOCK(8); + SUBBYTE(res, dst, src) + I286_CX--; + } while((I286_CX) && (!(I286_FLAGL & Z_FLAG))); + } +} + +I286EXT i286c_repe_scasw(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIRx2; + UINT32 dst = I286_AX; + do { + UINT32 res; + UINT32 src = i286_memoryread_w(I286_DI + ES_BASE); + I286_DI += stp; + I286_WORKCLOCK(8); + SUBWORD(res, dst, src) + I286_CX--; + } while((I286_CX) && (I286_FLAGL & Z_FLAG)); + } +} + +I286EXT i286c_repne_scasw(void) { + + I286_WORKCLOCK(5); + if (I286_CX) { + int stp = STRING_DIRx2; + UINT32 dst = I286_AX; + do { + UINT32 res; + UINT32 src = i286_memoryread_w(I286_DI + ES_BASE); + I286_DI += stp; + I286_WORKCLOCK(8); + SUBWORD(res, dst, src) + I286_CX--; + } while((I286_CX) && (!(I286_FLAGL & Z_FLAG))); + } +} + diff --git a/i286c/i286c_sf.c b/i286c/i286c_sf.c old mode 100755 new mode 100644 index f6a3e3a7..671129b2 --- a/i286c/i286c_sf.c +++ b/i286c/i286c_sf.c @@ -1,617 +1,617 @@ -#include -#include -#include "i286c.h" -#include "i286c.mcr" -#include "i286c_sf.mcr" - - -// ------------------------------------------------------------------------ - -I286_SFT _rol_r8_1(UINT8 *p) { - - UINT src; - UINT dst; - - src = *p; - BYTE_ROL1(dst, src) - *p = (UINT8)dst; -} - -I286_SFT _ror_r8_1(UINT8 *p) { - - UINT src; - UINT dst; - - src = *p; - BYTE_ROR1(dst, src) - *p = (UINT8)dst; -} - -I286_SFT _rcl_r8_1(UINT8 *p) { - - UINT src; - UINT dst; - - src = *p; - BYTE_RCL1(dst, src) - *p = (UINT8)dst; -} - -I286_SFT _rcr_r8_1(UINT8 *p) { - - UINT src; - UINT dst; - - src = *p; - BYTE_RCR1(dst, src) - *p = (UINT8)dst; -} - -I286_SFT _shl_r8_1(UINT8 *p) { - - UINT src; - UINT dst; - - src = *p; - BYTE_SHL1(dst, src) - *p = (UINT8)dst; -} - -I286_SFT _shr_r8_1(UINT8 *p) { - - UINT src; - UINT dst; - - src = *p; - BYTE_SHR1(dst, src) - *p = (UINT8)dst; -} - -I286_SFT _sar_r8_1(UINT8 *p) { - - UINT src; - UINT dst; - - src = *p; - BYTE_SAR1(dst, src) - *p = (UINT8)dst; -} - - -I286_SFT _rol_e8_1(UINT32 madr) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_ROL1(dst, src) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _ror_e8_1(UINT32 madr) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_ROR1(dst, src) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _rcl_e8_1(UINT32 madr) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_RCL1(dst, src) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _rcr_e8_1(UINT32 madr) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_RCR1(dst, src) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _shl_e8_1(UINT32 madr) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_SHL1(dst, src) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _shr_e8_1(UINT32 madr) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_SHR1(dst, src) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _sar_e8_1(UINT32 madr) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_SAR1(dst, src) - i286_memorywrite(madr, (REG8)dst); -} - - -const I286OPSFTR8 sft_r8_table[] = { - _rol_r8_1, _ror_r8_1, _rcl_r8_1, _rcr_r8_1, - _shl_r8_1, _shr_r8_1, _shl_r8_1, _sar_r8_1}; - -const I286OPSFTE8 sft_e8_table[] = { - _rol_e8_1, _ror_e8_1, _rcl_e8_1, _rcr_e8_1, - _shl_e8_1, _shr_e8_1, _shl_e8_1, _sar_e8_1}; - - -// ------------------------------------------------------------------------ - -I286_SFT _rol_r16_1(UINT16 *p) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_ROL1(dst, src) - *p = (UINT16)dst; -} - -I286_SFT _ror_r16_1(UINT16 *p) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_ROR1(dst, src) - *p = (UINT16)dst; -} - -I286_SFT _rcl_r16_1(UINT16 *p) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_RCL1(dst, src) - *p = (UINT16)dst; -} - -I286_SFT _rcr_r16_1(UINT16 *p) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_RCR1(dst, src) - *p = (UINT16)dst; -} - -I286_SFT _shl_r16_1(UINT16 *p) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_SHL1(dst, src) - *p = (UINT16)dst; -} - -I286_SFT _shr_r16_1(UINT16 *p) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_SHR1(dst, src) - *p = (UINT16)dst; -} - -I286_SFT _sar_r16_1(UINT16 *p) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_SAR1(dst, src) - *p = (UINT16)dst; -} - - -I286_SFT _rol_e16_1(UINT32 madr) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_ROL1(dst, src) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _ror_e16_1(UINT32 madr) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_ROR1(dst, src) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _rcl_e16_1(UINT32 madr) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_RCL1(dst, src) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _rcr_e16_1(UINT32 madr) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_RCR1(dst, src) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _shl_e16_1(UINT32 madr) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_SHL1(dst, src) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _shr_e16_1(UINT32 madr) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_SHR1(dst, src) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _sar_e16_1(UINT32 madr) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_SAR1(dst, src) - i286_memorywrite_w(madr, (REG16)dst); -} - - -const I286OPSFTR16 sft_r16_table[] = { - _rol_r16_1, _ror_r16_1, _rcl_r16_1, _rcr_r16_1, - _shl_r16_1, _shr_r16_1, _shl_r16_1, _sar_r16_1}; - -const I286OPSFTE16 sft_e16_table[] = { - _rol_e16_1, _ror_e16_1, _rcl_e16_1, _rcr_e16_1, - _shl_e16_1, _shr_e16_1, _shl_e16_1, _sar_e16_1}; - -// ------------------------------------------------------------------------ - -I286_SFT _rol_r8_cl(UINT8 *p, REG8 cl) { - - UINT src; - UINT dst; - - src = *p; - BYTE_ROLCL(dst, src, cl) - *p = (UINT8)dst; -} - -I286_SFT _ror_r8_cl(UINT8 *p, REG8 cl) { - - UINT src; - UINT dst; - - src = *p; - BYTE_RORCL(dst, src, cl) - *p = (UINT8)dst; -} - -I286_SFT _rcl_r8_cl(UINT8 *p, REG8 cl) { - - UINT src; - UINT dst; - - src = *p; - BYTE_RCLCL(dst, src, cl) - *p = (UINT8)dst; -} - -I286_SFT _rcr_r8_cl(UINT8 *p, REG8 cl) { - - UINT src; - UINT dst; - - src = *p; - BYTE_RCRCL(dst, src, cl) - *p = (UINT8)dst; -} - -I286_SFT _shl_r8_cl(UINT8 *p, REG8 cl) { - - UINT src; - UINT dst; - - src = *p; - BYTE_SHLCL(dst, src, cl) - *p = (UINT8)dst; -} - -I286_SFT _shr_r8_cl(UINT8 *p, REG8 cl) { - - UINT src; - UINT dst; - - src = *p; - BYTE_SHRCL(dst, src, cl) - *p = (UINT8)dst; -} - -I286_SFT _sar_r8_cl(UINT8 *p, REG8 cl) { - - UINT src; - UINT dst; - - src = *p; - BYTE_SARCL(dst, src, cl) - *p = (UINT8)dst; -} - - -I286_SFT _rol_e8_cl(UINT32 madr, REG8 cl) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_ROLCL(dst, src, cl) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _ror_e8_cl(UINT32 madr, REG8 cl) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_RORCL(dst, src, cl) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _rcl_e8_cl(UINT32 madr, REG8 cl) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_RCLCL(dst, src, cl) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _rcr_e8_cl(UINT32 madr, REG8 cl) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_RCRCL(dst, src, cl) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _shl_e8_cl(UINT32 madr, REG8 cl) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_SHLCL(dst, src, cl) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _shr_e8_cl(UINT32 madr, REG8 cl) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_SHRCL(dst, src, cl) - i286_memorywrite(madr, (REG8)dst); -} - -I286_SFT _sar_e8_cl(UINT32 madr, REG8 cl) { - - UINT src; - UINT dst; - - src = i286_memoryread(madr); - BYTE_SARCL(dst, src, cl) - i286_memorywrite(madr, (REG8)dst); -} - - -const I286OPSFTR8CL sft_r8cl_table[] = { - _rol_r8_cl, _ror_r8_cl, _rcl_r8_cl, _rcr_r8_cl, - _shl_r8_cl, _shr_r8_cl, _shl_r8_cl, _sar_r8_cl}; - -const I286OPSFTE8CL sft_e8cl_table[] = { - _rol_e8_cl, _ror_e8_cl, _rcl_e8_cl, _rcr_e8_cl, - _shl_e8_cl, _shr_e8_cl, _shl_e8_cl, _sar_e8_cl}; - - -// ------------------------------------------------------------------------ - -I286_SFT _rol_r16_cl(UINT16 *p, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_ROLCL(dst, src, cl) - *p = (UINT16)dst; -} - -I286_SFT _ror_r16_cl(UINT16 *p, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_RORCL(dst, src, cl) - *p = (UINT16)dst; -} - -I286_SFT _rcl_r16_cl(UINT16 *p, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_RCLCL(dst, src, cl) - *p = (UINT16)dst; -} - -I286_SFT _rcr_r16_cl(UINT16 *p, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_RCRCL(dst, src, cl) - *p = (UINT16)dst; -} - -I286_SFT _shl_r16_cl(UINT16 *p, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_SHLCL(dst, src, cl) - *p = (UINT16)dst; -} - -I286_SFT _shr_r16_cl(UINT16 *p, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_SHRCL(dst, src, cl) - *p = (UINT16)dst; -} - -I286_SFT _sar_r16_cl(UINT16 *p, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = *p; - WORD_SARCL(dst, src, cl) - *p = (UINT16)dst; -} - - -I286_SFT _rol_e16_cl(UINT32 madr, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_ROLCL(dst, src, cl) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _ror_e16_cl(UINT32 madr, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_RORCL(dst, src, cl) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _rcl_e16_cl(UINT32 madr, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_RCLCL(dst, src, cl) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _rcr_e16_cl(UINT32 madr, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_RCRCL(dst, src, cl) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _shl_e16_cl(UINT32 madr, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_SHLCL(dst, src, cl) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _shr_e16_cl(UINT32 madr, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_SHRCL(dst, src, cl) - i286_memorywrite_w(madr, (REG16)dst); -} - -I286_SFT _sar_e16_cl(UINT32 madr, REG8 cl) { - - UINT32 src; - UINT32 dst; - - src = i286_memoryread_w(madr); - WORD_SARCL(dst, src, cl) - i286_memorywrite_w(madr, (REG16)dst); -} - - -const I286OPSFTR16CL sft_r16cl_table[] = { - _rol_r16_cl, _ror_r16_cl, _rcl_r16_cl, _rcr_r16_cl, - _shl_r16_cl, _shr_r16_cl, _shl_r16_cl, _sar_r16_cl}; - -const I286OPSFTE16CL sft_e16cl_table[] = { - _rol_e16_cl, _ror_e16_cl, _rcl_e16_cl, _rcr_e16_cl, - _shl_e16_cl, _shr_e16_cl, _shl_e16_cl, _sar_e16_cl}; - +#include +#include +#include "i286c.h" +#include "i286c.mcr" +#include "i286c_sf.mcr" + + +// ------------------------------------------------------------------------ + +I286_SFT _rol_r8_1(UINT8 *p) { + + UINT src; + UINT dst; + + src = *p; + BYTE_ROL1(dst, src) + *p = (UINT8)dst; +} + +I286_SFT _ror_r8_1(UINT8 *p) { + + UINT src; + UINT dst; + + src = *p; + BYTE_ROR1(dst, src) + *p = (UINT8)dst; +} + +I286_SFT _rcl_r8_1(UINT8 *p) { + + UINT src; + UINT dst; + + src = *p; + BYTE_RCL1(dst, src) + *p = (UINT8)dst; +} + +I286_SFT _rcr_r8_1(UINT8 *p) { + + UINT src; + UINT dst; + + src = *p; + BYTE_RCR1(dst, src) + *p = (UINT8)dst; +} + +I286_SFT _shl_r8_1(UINT8 *p) { + + UINT src; + UINT dst; + + src = *p; + BYTE_SHL1(dst, src) + *p = (UINT8)dst; +} + +I286_SFT _shr_r8_1(UINT8 *p) { + + UINT src; + UINT dst; + + src = *p; + BYTE_SHR1(dst, src) + *p = (UINT8)dst; +} + +I286_SFT _sar_r8_1(UINT8 *p) { + + UINT src; + UINT dst; + + src = *p; + BYTE_SAR1(dst, src) + *p = (UINT8)dst; +} + + +I286_SFT _rol_e8_1(UINT32 madr) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_ROL1(dst, src) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _ror_e8_1(UINT32 madr) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_ROR1(dst, src) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _rcl_e8_1(UINT32 madr) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_RCL1(dst, src) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _rcr_e8_1(UINT32 madr) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_RCR1(dst, src) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _shl_e8_1(UINT32 madr) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_SHL1(dst, src) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _shr_e8_1(UINT32 madr) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_SHR1(dst, src) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _sar_e8_1(UINT32 madr) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_SAR1(dst, src) + i286_memorywrite(madr, (REG8)dst); +} + + +const I286OPSFTR8 sft_r8_table[] = { + _rol_r8_1, _ror_r8_1, _rcl_r8_1, _rcr_r8_1, + _shl_r8_1, _shr_r8_1, _shl_r8_1, _sar_r8_1}; + +const I286OPSFTE8 sft_e8_table[] = { + _rol_e8_1, _ror_e8_1, _rcl_e8_1, _rcr_e8_1, + _shl_e8_1, _shr_e8_1, _shl_e8_1, _sar_e8_1}; + + +// ------------------------------------------------------------------------ + +I286_SFT _rol_r16_1(UINT16 *p) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_ROL1(dst, src) + *p = (UINT16)dst; +} + +I286_SFT _ror_r16_1(UINT16 *p) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_ROR1(dst, src) + *p = (UINT16)dst; +} + +I286_SFT _rcl_r16_1(UINT16 *p) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_RCL1(dst, src) + *p = (UINT16)dst; +} + +I286_SFT _rcr_r16_1(UINT16 *p) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_RCR1(dst, src) + *p = (UINT16)dst; +} + +I286_SFT _shl_r16_1(UINT16 *p) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_SHL1(dst, src) + *p = (UINT16)dst; +} + +I286_SFT _shr_r16_1(UINT16 *p) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_SHR1(dst, src) + *p = (UINT16)dst; +} + +I286_SFT _sar_r16_1(UINT16 *p) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_SAR1(dst, src) + *p = (UINT16)dst; +} + + +I286_SFT _rol_e16_1(UINT32 madr) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_ROL1(dst, src) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _ror_e16_1(UINT32 madr) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_ROR1(dst, src) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _rcl_e16_1(UINT32 madr) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_RCL1(dst, src) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _rcr_e16_1(UINT32 madr) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_RCR1(dst, src) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _shl_e16_1(UINT32 madr) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_SHL1(dst, src) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _shr_e16_1(UINT32 madr) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_SHR1(dst, src) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _sar_e16_1(UINT32 madr) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_SAR1(dst, src) + i286_memorywrite_w(madr, (REG16)dst); +} + + +const I286OPSFTR16 sft_r16_table[] = { + _rol_r16_1, _ror_r16_1, _rcl_r16_1, _rcr_r16_1, + _shl_r16_1, _shr_r16_1, _shl_r16_1, _sar_r16_1}; + +const I286OPSFTE16 sft_e16_table[] = { + _rol_e16_1, _ror_e16_1, _rcl_e16_1, _rcr_e16_1, + _shl_e16_1, _shr_e16_1, _shl_e16_1, _sar_e16_1}; + +// ------------------------------------------------------------------------ + +I286_SFT _rol_r8_cl(UINT8 *p, REG8 cl) { + + UINT src; + UINT dst; + + src = *p; + BYTE_ROLCL(dst, src, cl) + *p = (UINT8)dst; +} + +I286_SFT _ror_r8_cl(UINT8 *p, REG8 cl) { + + UINT src; + UINT dst; + + src = *p; + BYTE_RORCL(dst, src, cl) + *p = (UINT8)dst; +} + +I286_SFT _rcl_r8_cl(UINT8 *p, REG8 cl) { + + UINT src; + UINT dst; + + src = *p; + BYTE_RCLCL(dst, src, cl) + *p = (UINT8)dst; +} + +I286_SFT _rcr_r8_cl(UINT8 *p, REG8 cl) { + + UINT src; + UINT dst; + + src = *p; + BYTE_RCRCL(dst, src, cl) + *p = (UINT8)dst; +} + +I286_SFT _shl_r8_cl(UINT8 *p, REG8 cl) { + + UINT src; + UINT dst; + + src = *p; + BYTE_SHLCL(dst, src, cl) + *p = (UINT8)dst; +} + +I286_SFT _shr_r8_cl(UINT8 *p, REG8 cl) { + + UINT src; + UINT dst; + + src = *p; + BYTE_SHRCL(dst, src, cl) + *p = (UINT8)dst; +} + +I286_SFT _sar_r8_cl(UINT8 *p, REG8 cl) { + + UINT src; + UINT dst; + + src = *p; + BYTE_SARCL(dst, src, cl) + *p = (UINT8)dst; +} + + +I286_SFT _rol_e8_cl(UINT32 madr, REG8 cl) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_ROLCL(dst, src, cl) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _ror_e8_cl(UINT32 madr, REG8 cl) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_RORCL(dst, src, cl) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _rcl_e8_cl(UINT32 madr, REG8 cl) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_RCLCL(dst, src, cl) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _rcr_e8_cl(UINT32 madr, REG8 cl) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_RCRCL(dst, src, cl) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _shl_e8_cl(UINT32 madr, REG8 cl) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_SHLCL(dst, src, cl) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _shr_e8_cl(UINT32 madr, REG8 cl) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_SHRCL(dst, src, cl) + i286_memorywrite(madr, (REG8)dst); +} + +I286_SFT _sar_e8_cl(UINT32 madr, REG8 cl) { + + UINT src; + UINT dst; + + src = i286_memoryread(madr); + BYTE_SARCL(dst, src, cl) + i286_memorywrite(madr, (REG8)dst); +} + + +const I286OPSFTR8CL sft_r8cl_table[] = { + _rol_r8_cl, _ror_r8_cl, _rcl_r8_cl, _rcr_r8_cl, + _shl_r8_cl, _shr_r8_cl, _shl_r8_cl, _sar_r8_cl}; + +const I286OPSFTE8CL sft_e8cl_table[] = { + _rol_e8_cl, _ror_e8_cl, _rcl_e8_cl, _rcr_e8_cl, + _shl_e8_cl, _shr_e8_cl, _shl_e8_cl, _sar_e8_cl}; + + +// ------------------------------------------------------------------------ + +I286_SFT _rol_r16_cl(UINT16 *p, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_ROLCL(dst, src, cl) + *p = (UINT16)dst; +} + +I286_SFT _ror_r16_cl(UINT16 *p, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_RORCL(dst, src, cl) + *p = (UINT16)dst; +} + +I286_SFT _rcl_r16_cl(UINT16 *p, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_RCLCL(dst, src, cl) + *p = (UINT16)dst; +} + +I286_SFT _rcr_r16_cl(UINT16 *p, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_RCRCL(dst, src, cl) + *p = (UINT16)dst; +} + +I286_SFT _shl_r16_cl(UINT16 *p, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_SHLCL(dst, src, cl) + *p = (UINT16)dst; +} + +I286_SFT _shr_r16_cl(UINT16 *p, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_SHRCL(dst, src, cl) + *p = (UINT16)dst; +} + +I286_SFT _sar_r16_cl(UINT16 *p, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = *p; + WORD_SARCL(dst, src, cl) + *p = (UINT16)dst; +} + + +I286_SFT _rol_e16_cl(UINT32 madr, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_ROLCL(dst, src, cl) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _ror_e16_cl(UINT32 madr, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_RORCL(dst, src, cl) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _rcl_e16_cl(UINT32 madr, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_RCLCL(dst, src, cl) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _rcr_e16_cl(UINT32 madr, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_RCRCL(dst, src, cl) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _shl_e16_cl(UINT32 madr, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_SHLCL(dst, src, cl) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _shr_e16_cl(UINT32 madr, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_SHRCL(dst, src, cl) + i286_memorywrite_w(madr, (REG16)dst); +} + +I286_SFT _sar_e16_cl(UINT32 madr, REG8 cl) { + + UINT32 src; + UINT32 dst; + + src = i286_memoryread_w(madr); + WORD_SARCL(dst, src, cl) + i286_memorywrite_w(madr, (REG16)dst); +} + + +const I286OPSFTR16CL sft_r16cl_table[] = { + _rol_r16_cl, _ror_r16_cl, _rcl_r16_cl, _rcr_r16_cl, + _shl_r16_cl, _shr_r16_cl, _shl_r16_cl, _sar_r16_cl}; + +const I286OPSFTE16CL sft_e16cl_table[] = { + _rol_e16_cl, _ror_e16_cl, _rcl_e16_cl, _rcr_e16_cl, + _shl_e16_cl, _shr_e16_cl, _shl_e16_cl, _sar_e16_cl}; + diff --git a/i286c/i286c_sf.mcr b/i286c/i286c_sf.mcr old mode 100755 new mode 100644 index 2326520e..34fc543d --- a/i286c/i286c_sf.mcr +++ b/i286c/i286c_sf.mcr @@ -1,349 +1,349 @@ -// wordはかなりノーチェック - - -#define BYTE_ROL1(d, s) { \ - UINT tmp = ((s) >> 7); \ - (d) = ((s) << 1) + tmp; \ - I286_FLAGL &= ~C_FLAG; \ - I286_FLAGL |= tmp; \ - I286_OV = ((s) ^ (d)) & 0x80; \ - } - -#define BYTE_ROR1(d, s) { \ - UINT tmp = ((s) & 1); \ - (d) = ((tmp << 8) + (s)) >> 1; \ - I286_FLAGL &= ~C_FLAG; \ - I286_FLAGL |= tmp; \ - I286_OV = ((s) ^ (d)) & 0x80; \ - } - -#define BYTE_RCL1(d, s) \ - (d) = ((s) << 1) | (I286_FLAGL & C_FLAG); \ - I286_FLAGL &= ~C_FLAG; \ - I286_FLAGL |= ((s) >> 7); \ - I286_OV = ((s) ^ (d)) & 0x80; - -#define BYTE_RCR1(d, s) \ - (d) = (((I286_FLAGL & C_FLAG) << 8) | (s)) >> 1; \ - I286_FLAGL &= ~C_FLAG; \ - I286_FLAGL |= ((s) & 1); \ - I286_OV = ((s) ^ (d)) & 0x80; - -#define BYTE_SHL1(d, s) \ - (d) = (s) << 1; \ - I286_OV = ((s) ^ (d)) & 0x80; \ - I286_FLAGL = BYTESZPCF(d) | A_FLAG; - -#define BYTE_SHR1(d, s) \ - (d) = (s) >> 1; \ - I286_OV = (s) & 0x80; \ - I286_FLAGL = (UINT8)(BYTESZPF(d) | A_FLAG | ((s) & 1)); - -#if 1 -#define BYTE_SAR1(d, s) \ - (d) = ((s) & 0x80) + ((s) >> 1); \ - I286_OV = 0; \ - I286_FLAGL = (UINT8)(BYTESZPF(d) | A_FLAG | ((s) & 1)); -#else // eVC3/4 compiler bug -#define BYTE_SAR1(d, s) \ - (d) = (UINT8)(((SINT8)(s)) >> 1); \ - I286_OV = 0; \ - I286_FLAGL = (UINT8)(BYTESZPF(d) | A_FLAG | ((s) & 1)); -#endif - - -#define WORD_ROL1(d, s) { \ - UINT32 tmp = ((s) >> 15); \ - (d) = ((s) << 1) + tmp; \ - I286_FLAGL &= ~C_FLAG; \ - I286_FLAGL |= tmp; \ - I286_OV = ((s) ^ (d)) & 0x8000; \ - } - -#define WORD_ROR1(d, s) { \ - UINT32 tmp = ((s) & 1); \ - (d) = ((tmp << 16) + (s)) >> 1; \ - I286_FLAGL &= ~C_FLAG; \ - I286_FLAGL |= tmp; \ - I286_OV = ((s) ^ (d)) & 0x8000; \ - } - -#define WORD_RCL1(d, s) \ - (d) = ((s) << 1) | (I286_FLAGL & 1); \ - I286_FLAGL &= ~C_FLAG; \ - I286_FLAGL |= ((s) >> 15); \ - I286_OV = ((s) ^ (d)) & 0x8000; - -#define WORD_RCR1(d, s) \ - (d) = (((I286_FLAGL & 1) << 16) + (s)) >> 1; \ - I286_FLAGL &= ~C_FLAG; \ - I286_FLAGL |= ((s) & 1); \ - I286_OV = ((s) ^ (d)) & 0x8000; - -#define WORD_SHL1(d, s) \ - (d) = (s) << 1; \ - I286_OV = ((s) ^ (d)) & 0x8000; \ - I286_FLAGL = WORDSZPCF(d) + A_FLAG; - -#define WORD_SHR1(d, s) \ - (d) = (s) >> 1; \ - I286_OV = (s) & 0x8000; \ - I286_FLAGL = (UINT8)(WORDSZPF(d) | A_FLAG | ((s) & 1)); - -#if 1 -#define WORD_SAR1(d, s) \ - (d) = ((s) & 0x8000) + ((s) >> 1); \ - I286_OV = 0; \ - I286_FLAGL = (UINT8)(WORDSZPF(d) | A_FLAG | ((s) & 1)); -#else // eVC3/4 compiler bug -#define WORD_SAR1(d, s) \ - (d) = (UINT16)(((SINT16)(s)) >> 1); \ - I286_OV = 0; \ - I286_FLAGL = (UINT8)(WORDSZPF(d) | A_FLAG | ((s) & 1)); -#endif - - - -#define BYTE_ROLCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - (c) = ((c) - 1) & 7; \ - if (c) { \ - (s) = ((s) << (c)) | ((s) >> (8 - (c))); \ - (s) &= 0xff; \ - } \ - BYTE_ROL1(d, s) \ - } \ - else { \ - (d) = (s); \ - } - -#define BYTE_RORCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - (c) = ((c) - 1) & 7; \ - if (c) { \ - (s) = ((s) >> (c)) | ((s) << (8 - (c))); \ - (s) &= 0xff; \ - } \ - BYTE_ROR1(d, s) \ - } \ - else { \ - (d) = (s); \ - } - -#define BYTE_RCLCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - UINT tmp; \ - tmp = I286_FLAGL & C_FLAG; \ - I286_FLAGL &= ~C_FLAG; \ - while((c)--) { \ - (s) = (((s) << 1) | tmp) & 0x1ff; \ - tmp = (s) >> 8; \ - } \ - I286_OV = ((s) ^ (s >> 1)) & 0x80; \ - I286_FLAGL |= tmp; \ - } \ - (d) = (s); - -#define BYTE_RCRCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - UINT tmp; \ - tmp = I286_FLAGL & C_FLAG; \ - I286_FLAGL &= ~C_FLAG; \ - while((c)--) { \ - (s) |= tmp << 8; \ - tmp = (s) & 1; \ - (s) >>= 1; \ - } \ - I286_OV = ((s) ^ (s >> 1)) & 0x40; \ - I286_FLAGL |= tmp; \ - } \ - (d) = (s); - -#define BYTE_SHLCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - if ((c) > 10) { \ - (c) = 10; \ - } \ - (s) <<= (c); \ - (s) &= 0x1ff; \ - I286_FLAGL = BYTESZPCF(s) + A_FLAG; \ - I286_OV = ((s) ^ ((s) >> 1)) & 0x80; \ - } \ - (d) = (s); - -#define BYTE_SHRCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - if ((c) >= 10) { \ - (c) = 10; \ - } \ - (s) >>= ((c) - 1); \ - I286_FLAGL = (UINT8)((s) & 1); \ - (s) >>= 1; \ - I286_OV = ((s) ^ ((s) >> 1)) & 0x40; \ - I286_FLAGL |= BYTESZPF(s) + A_FLAG; \ - } \ - (d) = (s); - -#if !defined(_WIN32_WCE) || (_WIN32_WCE < 300) -#define BYTE_SARCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - (s) = ((SINT8)(s)) >> ((c) - 1); \ - I286_FLAGL = (UINT8)((s) & 1); \ - (s) = (UINT8)(((SINT8)s) >> 1); \ - I286_OV = 0; \ - I286_FLAGL |= BYTESZPF(s) | A_FLAG; \ - } \ - (d) = (s); -#else -#define BYTE_SARCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - SINT32 t; \ - t = (s) << 24; \ - t = t >> ((c) - 1); \ - I286_FLAGL = (UINT8)((t >> 24) & 1); \ - (s) = (t >> 25) & 0xff; \ - I286_OV = 0; \ - I286_FLAGL |= BYTESZPF(s) | A_FLAG; \ - } \ - (d) = (s); -#endif - -#define WORD_ROLCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - UINT tmp; \ - (c)--; \ - if (c) { \ - (c) &= 0x0f; \ - (s) = ((s) << (c)) | ((s) >> (16 - (c))); \ - (s) &= 0xffff; \ - } \ - else { \ - I286_OV = ((s) + 0x4000) & 0x8000; \ - } \ - tmp = ((s) >> 15); \ - (s) = ((s) << 1) + tmp; \ - I286_FLAGL &= ~C_FLAG; \ - I286_FLAGL |= tmp; \ - } \ - (d) = (s); - -#define WORD_RORCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - UINT32 tmp; \ - (c)--; \ - if (c) { \ - (c) &= 0x0f; \ - (s) = ((s) >> (c)) | ((s) << (16 - (c))); \ - (s) &= 0xffff; \ - } \ - else { \ - I286_OV = ((s) >> 15) ^ ((s) & 1); \ - } \ - tmp = (s) & 1; \ - (s) = ((tmp << 16) + (s)) >> 1; \ - I286_FLAGL &= ~C_FLAG; \ - I286_FLAGL |= tmp; \ - } \ - (d) = (s); - -#define WORD_RCLCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - UINT tmp; \ - tmp = I286_FLAGL & C_FLAG; \ - I286_FLAGL &= ~C_FLAG; \ - if ((c) == 1) { \ - I286_OV = ((s) + 0x4000) & 0x8000; \ - } \ - while((c)--) { \ - (s) = (((s) << 1) + tmp) & 0x1ffff; \ - tmp = (s) >> 16; \ - } \ - I286_FLAGL |= tmp; \ - } \ - (d) = (s); - -#define WORD_RCRCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - UINT32 tmp; \ - tmp = I286_FLAGL & C_FLAG; \ - I286_FLAGL &= ~C_FLAG; \ - if ((c) == 1) { \ - I286_OV = ((s) >> 15) ^ tmp; \ - } \ - while((c)--) { \ - (s) |= tmp << 16; \ - tmp = (s) & 1; \ - (s) >>= 1; \ - } \ - I286_FLAGL |= tmp; \ - } \ - (d) = (s); - -#define WORD_SHLCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - I286_OV = 0; \ - if ((c) == 1) { \ - I286_OV = ((s) + 0x4000) & 0x8000; \ - } \ - (s) <<= (c); \ - (s) &= 0x1ffff; \ - I286_FLAGL = WORDSZPCF(s); \ - } \ - (d) = (s); - -#define WORD_SHRCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - (c)--; \ - if (c) { \ - (s) >>= (c); \ - I286_OV = 0; \ - } \ - else { \ - I286_OV = (s) & 0x8000; \ - } \ - I286_FLAGL = (UINT8)((s) & 1); \ - (s) >>= 1; \ - I286_FLAGL |= WORDSZPF(s); \ - } \ - (d) = (s); - -#if !defined(_WIN32_WCE) || (_WIN32_WCE < 300) -#define WORD_SARCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - (s) = ((SINT16)(s)) >> ((c) - 1); \ - I286_FLAGL = (UINT8)((s) & 1); \ - (s) = (UINT16)(((SINT16)s) >> 1); \ - I286_OV = 0; \ - I286_FLAGL |= WORDSZPF(s); \ - } \ - (d) = (s); -#else // eVC〜 -#define WORD_SARCL(d, s, c) \ - (c) &= 0x1f; \ - if (c) { \ - SINT32 tmp; \ - tmp = (s) << 16; \ - tmp = tmp >> (16 + (c) - 1); \ - I286_FLAGL = (UINT8)(tmp & 1); \ - (s) = (UINT16)(tmp >> 1); \ - I286_OV = 0; \ - I286_FLAGL |= WORDSZPF(s); \ - } \ - (d) = (s); -#endif - +// wordはかなりノーチェック + + +#define BYTE_ROL1(d, s) { \ + UINT tmp = ((s) >> 7); \ + (d) = ((s) << 1) + tmp; \ + I286_FLAGL &= ~C_FLAG; \ + I286_FLAGL |= tmp; \ + I286_OV = ((s) ^ (d)) & 0x80; \ + } + +#define BYTE_ROR1(d, s) { \ + UINT tmp = ((s) & 1); \ + (d) = ((tmp << 8) + (s)) >> 1; \ + I286_FLAGL &= ~C_FLAG; \ + I286_FLAGL |= tmp; \ + I286_OV = ((s) ^ (d)) & 0x80; \ + } + +#define BYTE_RCL1(d, s) \ + (d) = ((s) << 1) | (I286_FLAGL & C_FLAG); \ + I286_FLAGL &= ~C_FLAG; \ + I286_FLAGL |= ((s) >> 7); \ + I286_OV = ((s) ^ (d)) & 0x80; + +#define BYTE_RCR1(d, s) \ + (d) = (((I286_FLAGL & C_FLAG) << 8) | (s)) >> 1; \ + I286_FLAGL &= ~C_FLAG; \ + I286_FLAGL |= ((s) & 1); \ + I286_OV = ((s) ^ (d)) & 0x80; + +#define BYTE_SHL1(d, s) \ + (d) = (s) << 1; \ + I286_OV = ((s) ^ (d)) & 0x80; \ + I286_FLAGL = BYTESZPCF(d) | A_FLAG; + +#define BYTE_SHR1(d, s) \ + (d) = (s) >> 1; \ + I286_OV = (s) & 0x80; \ + I286_FLAGL = (UINT8)(BYTESZPF(d) | A_FLAG | ((s) & 1)); + +#if 1 +#define BYTE_SAR1(d, s) \ + (d) = ((s) & 0x80) + ((s) >> 1); \ + I286_OV = 0; \ + I286_FLAGL = (UINT8)(BYTESZPF(d) | A_FLAG | ((s) & 1)); +#else // eVC3/4 compiler bug +#define BYTE_SAR1(d, s) \ + (d) = (UINT8)(((SINT8)(s)) >> 1); \ + I286_OV = 0; \ + I286_FLAGL = (UINT8)(BYTESZPF(d) | A_FLAG | ((s) & 1)); +#endif + + +#define WORD_ROL1(d, s) { \ + UINT32 tmp = ((s) >> 15); \ + (d) = ((s) << 1) + tmp; \ + I286_FLAGL &= ~C_FLAG; \ + I286_FLAGL |= tmp; \ + I286_OV = ((s) ^ (d)) & 0x8000; \ + } + +#define WORD_ROR1(d, s) { \ + UINT32 tmp = ((s) & 1); \ + (d) = ((tmp << 16) + (s)) >> 1; \ + I286_FLAGL &= ~C_FLAG; \ + I286_FLAGL |= tmp; \ + I286_OV = ((s) ^ (d)) & 0x8000; \ + } + +#define WORD_RCL1(d, s) \ + (d) = ((s) << 1) | (I286_FLAGL & 1); \ + I286_FLAGL &= ~C_FLAG; \ + I286_FLAGL |= ((s) >> 15); \ + I286_OV = ((s) ^ (d)) & 0x8000; + +#define WORD_RCR1(d, s) \ + (d) = (((I286_FLAGL & 1) << 16) + (s)) >> 1; \ + I286_FLAGL &= ~C_FLAG; \ + I286_FLAGL |= ((s) & 1); \ + I286_OV = ((s) ^ (d)) & 0x8000; + +#define WORD_SHL1(d, s) \ + (d) = (s) << 1; \ + I286_OV = ((s) ^ (d)) & 0x8000; \ + I286_FLAGL = WORDSZPCF(d) + A_FLAG; + +#define WORD_SHR1(d, s) \ + (d) = (s) >> 1; \ + I286_OV = (s) & 0x8000; \ + I286_FLAGL = (UINT8)(WORDSZPF(d) | A_FLAG | ((s) & 1)); + +#if 1 +#define WORD_SAR1(d, s) \ + (d) = ((s) & 0x8000) + ((s) >> 1); \ + I286_OV = 0; \ + I286_FLAGL = (UINT8)(WORDSZPF(d) | A_FLAG | ((s) & 1)); +#else // eVC3/4 compiler bug +#define WORD_SAR1(d, s) \ + (d) = (UINT16)(((SINT16)(s)) >> 1); \ + I286_OV = 0; \ + I286_FLAGL = (UINT8)(WORDSZPF(d) | A_FLAG | ((s) & 1)); +#endif + + + +#define BYTE_ROLCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + (c) = ((c) - 1) & 7; \ + if (c) { \ + (s) = ((s) << (c)) | ((s) >> (8 - (c))); \ + (s) &= 0xff; \ + } \ + BYTE_ROL1(d, s) \ + } \ + else { \ + (d) = (s); \ + } + +#define BYTE_RORCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + (c) = ((c) - 1) & 7; \ + if (c) { \ + (s) = ((s) >> (c)) | ((s) << (8 - (c))); \ + (s) &= 0xff; \ + } \ + BYTE_ROR1(d, s) \ + } \ + else { \ + (d) = (s); \ + } + +#define BYTE_RCLCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + UINT tmp; \ + tmp = I286_FLAGL & C_FLAG; \ + I286_FLAGL &= ~C_FLAG; \ + while((c)--) { \ + (s) = (((s) << 1) | tmp) & 0x1ff; \ + tmp = (s) >> 8; \ + } \ + I286_OV = ((s) ^ (s >> 1)) & 0x80; \ + I286_FLAGL |= tmp; \ + } \ + (d) = (s); + +#define BYTE_RCRCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + UINT tmp; \ + tmp = I286_FLAGL & C_FLAG; \ + I286_FLAGL &= ~C_FLAG; \ + while((c)--) { \ + (s) |= tmp << 8; \ + tmp = (s) & 1; \ + (s) >>= 1; \ + } \ + I286_OV = ((s) ^ (s >> 1)) & 0x40; \ + I286_FLAGL |= tmp; \ + } \ + (d) = (s); + +#define BYTE_SHLCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + if ((c) > 10) { \ + (c) = 10; \ + } \ + (s) <<= (c); \ + (s) &= 0x1ff; \ + I286_FLAGL = BYTESZPCF(s) + A_FLAG; \ + I286_OV = ((s) ^ ((s) >> 1)) & 0x80; \ + } \ + (d) = (s); + +#define BYTE_SHRCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + if ((c) >= 10) { \ + (c) = 10; \ + } \ + (s) >>= ((c) - 1); \ + I286_FLAGL = (UINT8)((s) & 1); \ + (s) >>= 1; \ + I286_OV = ((s) ^ ((s) >> 1)) & 0x40; \ + I286_FLAGL |= BYTESZPF(s) + A_FLAG; \ + } \ + (d) = (s); + +#if !defined(_WIN32_WCE) || (_WIN32_WCE < 300) +#define BYTE_SARCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + (s) = ((SINT8)(s)) >> ((c) - 1); \ + I286_FLAGL = (UINT8)((s) & 1); \ + (s) = (UINT8)(((SINT8)s) >> 1); \ + I286_OV = 0; \ + I286_FLAGL |= BYTESZPF(s) | A_FLAG; \ + } \ + (d) = (s); +#else +#define BYTE_SARCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + SINT32 t; \ + t = (s) << 24; \ + t = t >> ((c) - 1); \ + I286_FLAGL = (UINT8)((t >> 24) & 1); \ + (s) = (t >> 25) & 0xff; \ + I286_OV = 0; \ + I286_FLAGL |= BYTESZPF(s) | A_FLAG; \ + } \ + (d) = (s); +#endif + +#define WORD_ROLCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + UINT tmp; \ + (c)--; \ + if (c) { \ + (c) &= 0x0f; \ + (s) = ((s) << (c)) | ((s) >> (16 - (c))); \ + (s) &= 0xffff; \ + } \ + else { \ + I286_OV = ((s) + 0x4000) & 0x8000; \ + } \ + tmp = ((s) >> 15); \ + (s) = ((s) << 1) + tmp; \ + I286_FLAGL &= ~C_FLAG; \ + I286_FLAGL |= tmp; \ + } \ + (d) = (s); + +#define WORD_RORCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + UINT32 tmp; \ + (c)--; \ + if (c) { \ + (c) &= 0x0f; \ + (s) = ((s) >> (c)) | ((s) << (16 - (c))); \ + (s) &= 0xffff; \ + } \ + else { \ + I286_OV = ((s) >> 15) ^ ((s) & 1); \ + } \ + tmp = (s) & 1; \ + (s) = ((tmp << 16) + (s)) >> 1; \ + I286_FLAGL &= ~C_FLAG; \ + I286_FLAGL |= tmp; \ + } \ + (d) = (s); + +#define WORD_RCLCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + UINT tmp; \ + tmp = I286_FLAGL & C_FLAG; \ + I286_FLAGL &= ~C_FLAG; \ + if ((c) == 1) { \ + I286_OV = ((s) + 0x4000) & 0x8000; \ + } \ + while((c)--) { \ + (s) = (((s) << 1) + tmp) & 0x1ffff; \ + tmp = (s) >> 16; \ + } \ + I286_FLAGL |= tmp; \ + } \ + (d) = (s); + +#define WORD_RCRCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + UINT32 tmp; \ + tmp = I286_FLAGL & C_FLAG; \ + I286_FLAGL &= ~C_FLAG; \ + if ((c) == 1) { \ + I286_OV = ((s) >> 15) ^ tmp; \ + } \ + while((c)--) { \ + (s) |= tmp << 16; \ + tmp = (s) & 1; \ + (s) >>= 1; \ + } \ + I286_FLAGL |= tmp; \ + } \ + (d) = (s); + +#define WORD_SHLCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + I286_OV = 0; \ + if ((c) == 1) { \ + I286_OV = ((s) + 0x4000) & 0x8000; \ + } \ + (s) <<= (c); \ + (s) &= 0x1ffff; \ + I286_FLAGL = WORDSZPCF(s); \ + } \ + (d) = (s); + +#define WORD_SHRCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + (c)--; \ + if (c) { \ + (s) >>= (c); \ + I286_OV = 0; \ + } \ + else { \ + I286_OV = (s) & 0x8000; \ + } \ + I286_FLAGL = (UINT8)((s) & 1); \ + (s) >>= 1; \ + I286_FLAGL |= WORDSZPF(s); \ + } \ + (d) = (s); + +#if !defined(_WIN32_WCE) || (_WIN32_WCE < 300) +#define WORD_SARCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + (s) = ((SINT16)(s)) >> ((c) - 1); \ + I286_FLAGL = (UINT8)((s) & 1); \ + (s) = (UINT16)(((SINT16)s) >> 1); \ + I286_OV = 0; \ + I286_FLAGL |= WORDSZPF(s); \ + } \ + (d) = (s); +#else // eVC〜 +#define WORD_SARCL(d, s, c) \ + (c) &= 0x1f; \ + if (c) { \ + SINT32 tmp; \ + tmp = (s) << 16; \ + tmp = tmp >> (16 + (c) - 1); \ + I286_FLAGL = (UINT8)(tmp & 1); \ + (s) = (UINT16)(tmp >> 1); \ + I286_OV = 0; \ + I286_FLAGL |= WORDSZPF(s); \ + } \ + (d) = (s); +#endif + diff --git a/i286x/cpucore.h b/i286x/cpucore.h old mode 100755 new mode 100644 index c9f724a8..e76acd9c --- a/i286x/cpucore.h +++ b/i286x/cpucore.h @@ -1,312 +1,312 @@ -//---------------------------------------------------------------------------- -// -// i286x : 80286 Engine for Pentium ver0.05 -// -// Copyright by Yui/Studio Milmake 1999-2003 -// -//---------------------------------------------------------------------------- - - -#if defined(CPUCORE_IA32) -#error : not support CPUCORE_IA32 -#endif -#if defined(CPUSTRUC_MEMWAIT) -#error : not support CPUSTRUC_MEMWAIT -#endif - -#include "cpumem.h" - - -#if !defined(CPUDEBUG) -#if defined(SUPPORT_BMS) // Added by Shinra -enum { - I286_MEMREADMAX = 0x80000, - I286_MEMWRITEMAX = 0x80000 -}; -#else -enum { - I286_MEMREADMAX = 0xa4000, - I286_MEMWRITEMAX = 0xa0000 -}; -#endif -#else // ダイレクトアクセス範囲を狭める -enum { - I286_MEMWRITEMAX = 0xa0000 -}; -#endif - -enum { - C_FLAG = 0x0001, - P_FLAG = 0x0004, - A_FLAG = 0x0010, - Z_FLAG = 0x0040, - S_FLAG = 0x0080, - T_FLAG = 0x0100, - I_FLAG = 0x0200, - D_FLAG = 0x0400, - O_FLAG = 0x0800 -}; - -enum { - MSW_PE = 0x0001, - MSW_MP = 0x0002, - MSW_EM = 0x0004, - MSW_TS = 0x0008 -}; - -enum { - CPUTYPE_V30 = 0x01 -}; - -#ifndef CPUCALL -#define CPUCALL __fastcall -#endif - -#if defined(BYTESEX_LITTLE) - -typedef struct { - UINT8 al; - UINT8 ah; - UINT8 cl; - UINT8 ch; - UINT8 dl; - UINT8 dh; - UINT8 bl; - UINT8 bh; - UINT8 sp_l; - UINT8 sp_h; - UINT8 bp_l; - UINT8 bp_h; - UINT8 si_l; - UINT8 si_h; - UINT8 di_l; - UINT8 di_h; - UINT8 es_l; - UINT8 es_h; - UINT8 cs_l; - UINT8 cs_h; - UINT8 ss_l; - UINT8 ss_h; - UINT8 ds_l; - UINT8 ds_h; - UINT8 flag_l; - UINT8 flag_h; - UINT8 ip_l; - UINT8 ip_h; -} I286REG8; - -#else - -typedef struct { - UINT8 ah; - UINT8 al; - UINT8 ch; - UINT8 cl; - UINT8 dh; - UINT8 dl; - UINT8 bh; - UINT8 bl; - UINT8 sp_h; - UINT8 sp_l; - UINT8 bp_h; - UINT8 bp_l; - UINT8 si_h; - UINT8 si_l; - UINT8 di_h; - UINT8 di_l; - UINT8 es_h; - UINT8 es_l; - UINT8 cs_h; - UINT8 cs_l; - UINT8 ss_h; - UINT8 ss_l; - UINT8 ds_h; - UINT8 ds_l; - UINT8 flag_h; - UINT8 flag_l; - UINT8 ip_h; - UINT8 ip_l; -} I286REG8; - -#endif - -typedef struct { - UINT16 ax; - UINT16 cx; - UINT16 dx; - UINT16 bx; - UINT16 sp; - UINT16 bp; - UINT16 si; - UINT16 di; - UINT16 es; - UINT16 cs; - UINT16 ss; - UINT16 ds; - UINT16 flag; - UINT16 ip; -} I286REG16; - -typedef struct { - UINT16 limit; - UINT16 base; - UINT8 base24; - UINT8 reserved; -} I286DTR; - -typedef struct { - union { - I286REG8 b; - I286REG16 w; - } r; - UINT32 es_base; - UINT32 cs_base; - UINT32 ss_base; - UINT32 ds_base; - UINT32 ss_fix; - UINT32 ds_fix; - UINT32 adrsmask; // ver0.72 - UINT16 prefix; - UINT8 trap; - UINT8 resetreq; // ver0.72 - UINT8 prefetchque[4]; - I286DTR GDTR; - UINT16 MSW; - I286DTR IDTR; - UINT16 LDTR; // ver0.73 - I286DTR LDTRC; - UINT16 TR; - I286DTR TRC; - UINT8 padding[2]; - - UINT8 cpu_type; - UINT8 itfbank; // ver0.72 - UINT16 ram_d0; - SINT32 remainclock; - SINT32 baseclock; - UINT32 clock; -} I286STAT; - -typedef struct { // for ver0.73 - UINT8 *ext; - UINT32 extsize; - UINT8 *ems[4]; - UINT32 repbak; - UINT32 inport; -} I286EXT; - -typedef struct { - I286STAT s; // STATsaveされる奴 - I286EXT e; -} I286CORE; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern I286CORE i286core; -extern const UINT8 iflags[]; - -void i286x_initialize(void); -void i286x_deinitialize(void); -void i286x_reset(void); -void i286x_shut(void); -void i286x_resetprefetch(void); -void i286x_setextsize(UINT32 size); -void i286x_setemm(UINT frame, UINT32 addr); - -void CPUCALL i286x_interrupt(UINT8 vect); - -void i286x(void); -void i286x_step(void); - -void v30x(void); -void v30x_step(void); - -#ifdef __cplusplus -} -#endif - - -// ---- macros - -#define CPU_STATSAVE i286core.s - -#define CPU_AX i286core.s.r.w.ax -#define CPU_BX i286core.s.r.w.bx -#define CPU_CX i286core.s.r.w.cx -#define CPU_DX i286core.s.r.w.dx -#define CPU_SI i286core.s.r.w.si -#define CPU_DI i286core.s.r.w.di -#define CPU_BP i286core.s.r.w.bp -#define CPU_SP i286core.s.r.w.sp -#define CPU_CS i286core.s.r.w.cs -#define CPU_DS i286core.s.r.w.ds -#define CPU_ES i286core.s.r.w.es -#define CPU_SS i286core.s.r.w.ss -#define CPU_IP i286core.s.r.w.ip - -#define CPU_EAX i286core.s.r.w.ax -#define CPU_EBX i286core.s.r.w.bx -#define CPU_ECX i286core.s.r.w.cx -#define CPU_EDX i286core.s.r.w.dx -#define CPU_ESI i286core.s.r.w.si -#define CPU_EDI i286core.s.r.w.di -#define CPU_EBP i286core.s.r.w.bp -#define CPU_ESP i286core.s.r.w.sp -#define CPU_EIP i286core.s.r.w.ip - -#define ES_BASE i286core.s.es_base -#define CS_BASE i286core.s.cs_base -#define SS_BASE i286core.s.ss_base -#define DS_BASE i286core.s.ds_base - -#define CPU_AL i286core.s.r.b.al -#define CPU_BL i286core.s.r.b.bl -#define CPU_CL i286core.s.r.b.cl -#define CPU_DL i286core.s.r.b.dl -#define CPU_AH i286core.s.r.b.ah -#define CPU_BH i286core.s.r.b.bh -#define CPU_CH i286core.s.r.b.ch -#define CPU_DH i286core.s.r.b.dh - -#define CPU_FLAG i286core.s.r.w.flag -#define CPU_FLAGL i286core.s.r.b.flag_l - -#define CPU_REMCLOCK i286core.s.remainclock -#define CPU_BASECLOCK i286core.s.baseclock -#define CPU_CLOCK i286core.s.clock -#define CPU_ADRSMASK i286core.s.adrsmask -#define CPU_MSW i286core.s.MSW -#define CPU_RESETREQ i286core.s.resetreq -#define CPU_ITFBANK i286core.s.itfbank -#define CPU_RAM_D000 i286core.s.ram_d0 - -#define CPU_EXTMEM i286core.e.ext -#define CPU_EXTMEMSIZE i286core.e.extsize -#define CPU_INPADRS i286core.e.inport - -#define CPU_TYPE i286core.s.cpu_type - -#define CPU_isDI (!(i286core.s.r.w.flag & I_FLAG)) -#define CPU_isEI (i286core.s.r.w.flag & I_FLAG) -#define CPU_CLI i286core.s.r.w.flag &= ~I_FLAG; \ - i286core.s.trap = 0; -#define CPU_STI i286core.s.r.w.flag |= I_FLAG; \ - i286core.s.trap = (i286core.s.r.w.flag >> 8) & 1; -#define CPU_A20EN(en) CPU_ADRSMASK = (en)?0x00ffffff:0x000fffff; - -#define CPU_INITIALIZE i286x_initialize -#define CPU_DEINITIALIZE i286x_deinitialize -#define CPU_RESET i286x_reset -#define CPU_CLEARPREFETCH i286x_resetprefetch -#define CPU_INTERRUPT(vect, soft) i286x_interrupt(vect) -#define CPU_EXEC i286x -#define CPU_EXECV30 v30x -#define CPU_SHUT i286x_shut -#define CPU_SETEXTSIZE(size) i286x_setextsize((UINT32)(size) << 20) -#define CPU_SETEMM(frame, addr) i286x_setemm(frame, addr) - -#define CPU_STEPEXEC i286x_step - +//---------------------------------------------------------------------------- +// +// i286x : 80286 Engine for Pentium ver0.05 +// +// Copyright by Yui/Studio Milmake 1999-2003 +// +//---------------------------------------------------------------------------- + + +#if defined(CPUCORE_IA32) +#error : not support CPUCORE_IA32 +#endif +#if defined(CPUSTRUC_MEMWAIT) +#error : not support CPUSTRUC_MEMWAIT +#endif + +#include "cpumem.h" + + +#if !defined(CPUDEBUG) +#if defined(SUPPORT_BMS) // Added by Shinra +enum { + I286_MEMREADMAX = 0x80000, + I286_MEMWRITEMAX = 0x80000 +}; +#else +enum { + I286_MEMREADMAX = 0xa4000, + I286_MEMWRITEMAX = 0xa0000 +}; +#endif +#else // ダイレクトアクセス範囲を狭める +enum { + I286_MEMWRITEMAX = 0xa0000 +}; +#endif + +enum { + C_FLAG = 0x0001, + P_FLAG = 0x0004, + A_FLAG = 0x0010, + Z_FLAG = 0x0040, + S_FLAG = 0x0080, + T_FLAG = 0x0100, + I_FLAG = 0x0200, + D_FLAG = 0x0400, + O_FLAG = 0x0800 +}; + +enum { + MSW_PE = 0x0001, + MSW_MP = 0x0002, + MSW_EM = 0x0004, + MSW_TS = 0x0008 +}; + +enum { + CPUTYPE_V30 = 0x01 +}; + +#ifndef CPUCALL +#define CPUCALL __fastcall +#endif + +#if defined(BYTESEX_LITTLE) + +typedef struct { + UINT8 al; + UINT8 ah; + UINT8 cl; + UINT8 ch; + UINT8 dl; + UINT8 dh; + UINT8 bl; + UINT8 bh; + UINT8 sp_l; + UINT8 sp_h; + UINT8 bp_l; + UINT8 bp_h; + UINT8 si_l; + UINT8 si_h; + UINT8 di_l; + UINT8 di_h; + UINT8 es_l; + UINT8 es_h; + UINT8 cs_l; + UINT8 cs_h; + UINT8 ss_l; + UINT8 ss_h; + UINT8 ds_l; + UINT8 ds_h; + UINT8 flag_l; + UINT8 flag_h; + UINT8 ip_l; + UINT8 ip_h; +} I286REG8; + +#else + +typedef struct { + UINT8 ah; + UINT8 al; + UINT8 ch; + UINT8 cl; + UINT8 dh; + UINT8 dl; + UINT8 bh; + UINT8 bl; + UINT8 sp_h; + UINT8 sp_l; + UINT8 bp_h; + UINT8 bp_l; + UINT8 si_h; + UINT8 si_l; + UINT8 di_h; + UINT8 di_l; + UINT8 es_h; + UINT8 es_l; + UINT8 cs_h; + UINT8 cs_l; + UINT8 ss_h; + UINT8 ss_l; + UINT8 ds_h; + UINT8 ds_l; + UINT8 flag_h; + UINT8 flag_l; + UINT8 ip_h; + UINT8 ip_l; +} I286REG8; + +#endif + +typedef struct { + UINT16 ax; + UINT16 cx; + UINT16 dx; + UINT16 bx; + UINT16 sp; + UINT16 bp; + UINT16 si; + UINT16 di; + UINT16 es; + UINT16 cs; + UINT16 ss; + UINT16 ds; + UINT16 flag; + UINT16 ip; +} I286REG16; + +typedef struct { + UINT16 limit; + UINT16 base; + UINT8 base24; + UINT8 reserved; +} I286DTR; + +typedef struct { + union { + I286REG8 b; + I286REG16 w; + } r; + UINT32 es_base; + UINT32 cs_base; + UINT32 ss_base; + UINT32 ds_base; + UINT32 ss_fix; + UINT32 ds_fix; + UINT32 adrsmask; // ver0.72 + UINT16 prefix; + UINT8 trap; + UINT8 resetreq; // ver0.72 + UINT8 prefetchque[4]; + I286DTR GDTR; + UINT16 MSW; + I286DTR IDTR; + UINT16 LDTR; // ver0.73 + I286DTR LDTRC; + UINT16 TR; + I286DTR TRC; + UINT8 padding[2]; + + UINT8 cpu_type; + UINT8 itfbank; // ver0.72 + UINT16 ram_d0; + SINT32 remainclock; + SINT32 baseclock; + UINT32 clock; +} I286STAT; + +typedef struct { // for ver0.73 + UINT8 *ext; + UINT32 extsize; + UINT8 *ems[4]; + UINT32 repbak; + UINT32 inport; +} I286EXT; + +typedef struct { + I286STAT s; // STATsaveされる奴 + I286EXT e; +} I286CORE; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern I286CORE i286core; +extern const UINT8 iflags[]; + +void i286x_initialize(void); +void i286x_deinitialize(void); +void i286x_reset(void); +void i286x_shut(void); +void i286x_resetprefetch(void); +void i286x_setextsize(UINT32 size); +void i286x_setemm(UINT frame, UINT32 addr); + +void CPUCALL i286x_interrupt(UINT8 vect); + +void i286x(void); +void i286x_step(void); + +void v30x(void); +void v30x_step(void); + +#ifdef __cplusplus +} +#endif + + +// ---- macros + +#define CPU_STATSAVE i286core.s + +#define CPU_AX i286core.s.r.w.ax +#define CPU_BX i286core.s.r.w.bx +#define CPU_CX i286core.s.r.w.cx +#define CPU_DX i286core.s.r.w.dx +#define CPU_SI i286core.s.r.w.si +#define CPU_DI i286core.s.r.w.di +#define CPU_BP i286core.s.r.w.bp +#define CPU_SP i286core.s.r.w.sp +#define CPU_CS i286core.s.r.w.cs +#define CPU_DS i286core.s.r.w.ds +#define CPU_ES i286core.s.r.w.es +#define CPU_SS i286core.s.r.w.ss +#define CPU_IP i286core.s.r.w.ip + +#define CPU_EAX i286core.s.r.w.ax +#define CPU_EBX i286core.s.r.w.bx +#define CPU_ECX i286core.s.r.w.cx +#define CPU_EDX i286core.s.r.w.dx +#define CPU_ESI i286core.s.r.w.si +#define CPU_EDI i286core.s.r.w.di +#define CPU_EBP i286core.s.r.w.bp +#define CPU_ESP i286core.s.r.w.sp +#define CPU_EIP i286core.s.r.w.ip + +#define ES_BASE i286core.s.es_base +#define CS_BASE i286core.s.cs_base +#define SS_BASE i286core.s.ss_base +#define DS_BASE i286core.s.ds_base + +#define CPU_AL i286core.s.r.b.al +#define CPU_BL i286core.s.r.b.bl +#define CPU_CL i286core.s.r.b.cl +#define CPU_DL i286core.s.r.b.dl +#define CPU_AH i286core.s.r.b.ah +#define CPU_BH i286core.s.r.b.bh +#define CPU_CH i286core.s.r.b.ch +#define CPU_DH i286core.s.r.b.dh + +#define CPU_FLAG i286core.s.r.w.flag +#define CPU_FLAGL i286core.s.r.b.flag_l + +#define CPU_REMCLOCK i286core.s.remainclock +#define CPU_BASECLOCK i286core.s.baseclock +#define CPU_CLOCK i286core.s.clock +#define CPU_ADRSMASK i286core.s.adrsmask +#define CPU_MSW i286core.s.MSW +#define CPU_RESETREQ i286core.s.resetreq +#define CPU_ITFBANK i286core.s.itfbank +#define CPU_RAM_D000 i286core.s.ram_d0 + +#define CPU_EXTMEM i286core.e.ext +#define CPU_EXTMEMSIZE i286core.e.extsize +#define CPU_INPADRS i286core.e.inport + +#define CPU_TYPE i286core.s.cpu_type + +#define CPU_isDI (!(i286core.s.r.w.flag & I_FLAG)) +#define CPU_isEI (i286core.s.r.w.flag & I_FLAG) +#define CPU_CLI i286core.s.r.w.flag &= ~I_FLAG; \ + i286core.s.trap = 0; +#define CPU_STI i286core.s.r.w.flag |= I_FLAG; \ + i286core.s.trap = (i286core.s.r.w.flag >> 8) & 1; +#define CPU_A20EN(en) CPU_ADRSMASK = (en)?0x00ffffff:0x000fffff; + +#define CPU_INITIALIZE i286x_initialize +#define CPU_DEINITIALIZE i286x_deinitialize +#define CPU_RESET i286x_reset +#define CPU_CLEARPREFETCH i286x_resetprefetch +#define CPU_INTERRUPT(vect, soft) i286x_interrupt(vect) +#define CPU_EXEC i286x +#define CPU_EXECV30 v30x +#define CPU_SHUT i286x_shut +#define CPU_SETEXTSIZE(size) i286x_setextsize((UINT32)(size) << 20) +#define CPU_SETEMM(frame, addr) i286x_setemm(frame, addr) + +#define CPU_STEPEXEC i286x_step + diff --git a/i286x/cpucore.inc b/i286x/cpucore.inc old mode 100755 new mode 100644 index 51e6636d..c10146c6 --- a/i286x/cpucore.inc +++ b/i286x/cpucore.inc @@ -1,62 +1,62 @@ - -USE_HIMEM equ 0x110000 - -VRAM_STEP equ 0x100000 -VRAM_B equ 0x0a8000 -VRAM_R equ 0x0b0000 -VRAM_G equ 0x0b8000 -VRAM_E equ 0x0e0000 - -VRAM0_B equ VRAM_B -VRAM0_R equ VRAM_R -VRAM0_G equ VRAM_G -VRAM0_E equ VRAM_E -VRAM1_B equ VRAM_B + VRAM_STEP -VRAM1_R equ VRAM_R + VRAM_STEP -VRAM1_G equ VRAM_G + VRAM_STEP -VRAM1_E equ VRAM_E + VRAM_STEP - -FONT_ADRS equ 0x110000 -ITF_ADRS equ 0x1f8000 - -%macro VRAMPOS 1 - and %1, VRAM_STEP | 7fffh -%endmacro - - - struc cpucore_t -.reg resw 14 -.es_base resd 1 -.cs_base resd 1 -.ss_base resd 1 -.ds_base resd 1 -.ss_fix resd 1 -.ds_fix resd 1 -.adrsmask resd 1 -.prefix resw 1 -.trap resb 1 -.resetreq resb 1 -.prefetchque resd 1 -.GDTR resb 6 -.MSW resw 1 -.IDTR resb 6 -.LDTR resw 1 -.LDTRC resb 6 -.TR resw 1 -.TRC resb 6 - resb 2 - -.cpu_type resb 1 -.itfbank resb 1 -.ram_d0 resw 1 -.remainclock resd 1 -.baseclock resd 1 -.clock resd 1 - -.ext resd 1 -.extsize resd 1 -.ems resd 4 -.repbak resd 1 -.inport resd 1 - endstruc - + +USE_HIMEM equ 0x110000 + +VRAM_STEP equ 0x100000 +VRAM_B equ 0x0a8000 +VRAM_R equ 0x0b0000 +VRAM_G equ 0x0b8000 +VRAM_E equ 0x0e0000 + +VRAM0_B equ VRAM_B +VRAM0_R equ VRAM_R +VRAM0_G equ VRAM_G +VRAM0_E equ VRAM_E +VRAM1_B equ VRAM_B + VRAM_STEP +VRAM1_R equ VRAM_R + VRAM_STEP +VRAM1_G equ VRAM_G + VRAM_STEP +VRAM1_E equ VRAM_E + VRAM_STEP + +FONT_ADRS equ 0x110000 +ITF_ADRS equ 0x1f8000 + +%macro VRAMPOS 1 + and %1, VRAM_STEP | 7fffh +%endmacro + + + struc cpucore_t +.reg resw 14 +.es_base resd 1 +.cs_base resd 1 +.ss_base resd 1 +.ds_base resd 1 +.ss_fix resd 1 +.ds_fix resd 1 +.adrsmask resd 1 +.prefix resw 1 +.trap resb 1 +.resetreq resb 1 +.prefetchque resd 1 +.GDTR resb 6 +.MSW resw 1 +.IDTR resb 6 +.LDTR resw 1 +.LDTRC resb 6 +.TR resw 1 +.TRC resb 6 + resb 2 + +.cpu_type resb 1 +.itfbank resb 1 +.ram_d0 resw 1 +.remainclock resd 1 +.baseclock resd 1 +.clock resd 1 + +.ext resd 1 +.extsize resd 1 +.ems resd 4 +.repbak resd 1 +.inport resd 1 + endstruc + diff --git a/i286x/cpumem.h b/i286x/cpumem.h old mode 100755 new mode 100644 index a7147d24..2731ed71 --- a/i286x/cpumem.h +++ b/i286x/cpumem.h @@ -1,119 +1,119 @@ - -#pragma once - -#ifndef MEMCALL -#define MEMCALL -#endif - -#if defined(MEMORDERTYPE) && (MEMORDERTYPE != 0) -#error : MEMORDERTYPE != 0 -#endif - - -// 000000-0fffff メインメモリ -// 100000-10ffef HMA -// 110000-193fff FONT-ROM/RAM -// 1a8000-1bffff VRAM1 -// 1c0000-1c7fff ITF-ROM BAK -// 1c8000-1dffff EPSON RAM -// 1e0000-1e7fff VRAM1 -// 1f8000-1fffff ITF-ROM - -#define USE_HIMEM 0x110000 - -enum { - VRAM_STEP = 0x100000, - VRAM_B = 0x0a8000, - VRAM_R = 0x0b0000, - VRAM_G = 0x0b8000, - VRAM_E = 0x0e0000, - - VRAM0_B = VRAM_B, - VRAM0_R = VRAM_R, - VRAM0_G = VRAM_G, - VRAM0_E = VRAM_E, - VRAM1_B = (VRAM_STEP + VRAM_B), - VRAM1_R = (VRAM_STEP + VRAM_R), - VRAM1_G = (VRAM_STEP + VRAM_G), - VRAM1_E = (VRAM_STEP + VRAM_E), - - FONT_ADRS = 0x110000, - ITF_ADRS = 0x1f8000 -}; - -#define VRAMADDRMASKEX(a) ((a) & (VRAM_STEP | 0x7fff)) - - -#ifdef __cplusplus -extern "C" { -#endif - -extern UINT8 mem[0x200000]; - -void MEMCALL i286_memorymap(UINT type); -void MEMCALL i286_vram_dispatch(UINT operate); - -UINT8 MEMCALL i286_memoryread(UINT32 address); -UINT16 MEMCALL i286_memoryread_w(UINT32 address); -void MEMCALL i286_memorywrite(UINT32 address, UINT8 value); -void MEMCALL i286_memorywrite_w(UINT32 address, UINT16 value); - -UINT8 MEMCALL i286_membyte_read(UINT seg, UINT off); -UINT16 MEMCALL i286_memword_read(UINT seg, UINT off); -void MEMCALL i286_membyte_write(UINT seg, UINT off, UINT8 value); -void MEMCALL i286_memword_write(UINT seg, UINT off, UINT16 value); - -void MEMCALL i286_memstr_read(UINT seg, UINT off, void *dat, UINT leng); -void MEMCALL i286_memstr_write(UINT seg, UINT off, - const void *dat, UINT leng); - -void MEMCALL i286_memx_read(UINT32 address, void *dat, UINT leng); -void MEMCALL i286_memx_write(UINT32 address, const void *dat, UINT leng); - -#ifdef __cplusplus -} -#endif - - -// ---- Memory map - -#define MEMM_ARCH(t) i286_memorymap(t) -#define MEMM_VRAM(o) i286_vram_dispatch(o) - - -// ---- Physical Space (DMA) - -#define MEMP_READ8(addr) \ - i286_memoryread((addr)) -#define MEMP_WRITE8(addr, dat) \ - i286_memorywrite((addr), (dat)) - - -// ---- Logical Space (BIOS) - -#define MEML_READ8(addr) \ - i286_memoryread((addr)) -#define MEML_READ16(addr) \ - i286_memoryread_w((addr)) -#define MEML_WRITE8(addr, dat) \ - i286_memorywrite((addr), (dat)) -#define MEML_WRITE16(addr, dat) \ - i286_memorywrite_w((addr), (dat)) -#define MEML_READS(addr, dat, leng) \ - i286_memx_read((addr), (dat), (leng)) -#define MEML_WRITES(addr, dat, leng) \ - i286_memx_write((addr), (dat), (leng)) - -#define MEMR_READ8(seg, off) \ - i286_membyte_read((seg), (off)) -#define MEMR_READ16(seg, off) \ - i286_memword_read((seg), (off)) -#define MEMR_WRITE8(seg, off, dat) \ - i286_membyte_write((seg), (off), (dat)) -#define MEMR_WRITE16(seg, off, dat) \ - i286_memword_write((seg), (off), (dat)) -#define MEMR_READS(seg, off, dat, leng) \ - i286_memstr_read((seg), (off), (dat), (leng)) -#define MEMR_WRITES(seg, off, dat, leng) \ - i286_memstr_write((seg), (off), (dat), (leng)) - + +#pragma once + +#ifndef MEMCALL +#define MEMCALL +#endif + +#if defined(MEMORDERTYPE) && (MEMORDERTYPE != 0) +#error : MEMORDERTYPE != 0 +#endif + + +// 000000-0fffff メインメモリ +// 100000-10ffef HMA +// 110000-193fff FONT-ROM/RAM +// 1a8000-1bffff VRAM1 +// 1c0000-1c7fff ITF-ROM BAK +// 1c8000-1dffff EPSON RAM +// 1e0000-1e7fff VRAM1 +// 1f8000-1fffff ITF-ROM + +#define USE_HIMEM 0x110000 + +enum { + VRAM_STEP = 0x100000, + VRAM_B = 0x0a8000, + VRAM_R = 0x0b0000, + VRAM_G = 0x0b8000, + VRAM_E = 0x0e0000, + + VRAM0_B = VRAM_B, + VRAM0_R = VRAM_R, + VRAM0_G = VRAM_G, + VRAM0_E = VRAM_E, + VRAM1_B = (VRAM_STEP + VRAM_B), + VRAM1_R = (VRAM_STEP + VRAM_R), + VRAM1_G = (VRAM_STEP + VRAM_G), + VRAM1_E = (VRAM_STEP + VRAM_E), + + FONT_ADRS = 0x110000, + ITF_ADRS = 0x1f8000 +}; + +#define VRAMADDRMASKEX(a) ((a) & (VRAM_STEP | 0x7fff)) + + +#ifdef __cplusplus +extern "C" { +#endif + +extern UINT8 mem[0x200000]; + +void MEMCALL i286_memorymap(UINT type); +void MEMCALL i286_vram_dispatch(UINT operate); + +UINT8 MEMCALL i286_memoryread(UINT32 address); +UINT16 MEMCALL i286_memoryread_w(UINT32 address); +void MEMCALL i286_memorywrite(UINT32 address, UINT8 value); +void MEMCALL i286_memorywrite_w(UINT32 address, UINT16 value); + +UINT8 MEMCALL i286_membyte_read(UINT seg, UINT off); +UINT16 MEMCALL i286_memword_read(UINT seg, UINT off); +void MEMCALL i286_membyte_write(UINT seg, UINT off, UINT8 value); +void MEMCALL i286_memword_write(UINT seg, UINT off, UINT16 value); + +void MEMCALL i286_memstr_read(UINT seg, UINT off, void *dat, UINT leng); +void MEMCALL i286_memstr_write(UINT seg, UINT off, + const void *dat, UINT leng); + +void MEMCALL i286_memx_read(UINT32 address, void *dat, UINT leng); +void MEMCALL i286_memx_write(UINT32 address, const void *dat, UINT leng); + +#ifdef __cplusplus +} +#endif + + +// ---- Memory map + +#define MEMM_ARCH(t) i286_memorymap(t) +#define MEMM_VRAM(o) i286_vram_dispatch(o) + + +// ---- Physical Space (DMA) + +#define MEMP_READ8(addr) \ + i286_memoryread((addr)) +#define MEMP_WRITE8(addr, dat) \ + i286_memorywrite((addr), (dat)) + + +// ---- Logical Space (BIOS) + +#define MEML_READ8(addr) \ + i286_memoryread((addr)) +#define MEML_READ16(addr) \ + i286_memoryread_w((addr)) +#define MEML_WRITE8(addr, dat) \ + i286_memorywrite((addr), (dat)) +#define MEML_WRITE16(addr, dat) \ + i286_memorywrite_w((addr), (dat)) +#define MEML_READS(addr, dat, leng) \ + i286_memx_read((addr), (dat), (leng)) +#define MEML_WRITES(addr, dat, leng) \ + i286_memx_write((addr), (dat), (leng)) + +#define MEMR_READ8(seg, off) \ + i286_membyte_read((seg), (off)) +#define MEMR_READ16(seg, off) \ + i286_memword_read((seg), (off)) +#define MEMR_WRITE8(seg, off, dat) \ + i286_membyte_write((seg), (off), (dat)) +#define MEMR_WRITE16(seg, off, dat) \ + i286_memword_write((seg), (off), (dat)) +#define MEMR_READS(seg, off, dat, leng) \ + i286_memstr_read((seg), (off), (dat), (leng)) +#define MEMR_WRITES(seg, off, dat, leng) \ + i286_memstr_write((seg), (off), (dat), (leng)) + diff --git a/i286x/i286x.cpp b/i286x/i286x.cpp old mode 100755 new mode 100644 index d5565c9c..95a5c3b0 --- a/i286x/i286x.cpp +++ b/i286x/i286x.cpp @@ -1,5539 +1,5539 @@ -#include -#include -#include "i286x.h" -#include "i286xadr.h" -#include "i286xs.h" -#include "i286xrep.h" -#include "i286xcts.h" -#include -#include -#include "i286x.mcr" -#include "i286xea.mcr" -#include "v30patch.h" -#include -#include "dmap.h" -#if defined(ENABLE_TRAP) -#include "trap/inttrap.h" -#include "trap/steptrap.h" -#endif - - - I286CORE i286core; - -const UINT8 iflags[256] = { // Z_FLAG, S_FLAG, P_FLAG - 0x44, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84}; - - -void i286x_initialize(void) { - - i286xadr_init(); - if (CPU_TYPE == CPUTYPE_V30) { - v30xinit(); - } -} - -void i286x_deinitialize(void) { - - if (CPU_EXTMEM) { - _MFREE(CPU_EXTMEM); - CPU_EXTMEM = NULL; - CPU_EXTMEMSIZE = 0; - } -} - -static void i286x_initreg(void) { - // V30はV30PATCH.CPPに別途用意 - I286_CS = 0xf000; - CS_BASE = 0xf0000; - I286_IP = 0xfff0; - i286core.s.adrsmask = 0xfffff; - i286x_resetprefetch(); -} - -#if defined(VAEG_FIX) -void i286x_reset(void) { - ZeroMemory(&i286core.s, sizeof(i286core.s)); - if (CPU_TYPE == CPUTYPE_V30) { - v30x_initreg(); - } - else { - i286x_initreg(); - } -} -#else -void i286x_reset(void) { - ZeroMemory(&i286core.s, sizeof(i286core.s)); - i286x_initreg(); -} -#endif - -void i286x_shut(void) { - - ZeroMemory(&i286core.s, offsetof(I286STAT, cpu_type)); - i286x_initreg(); -} - -void i286x_setextsize(UINT32 size) { - - if (CPU_EXTMEMSIZE != size) { - if (CPU_EXTMEM) { - _MFREE(CPU_EXTMEM); - CPU_EXTMEM = NULL; - } - if (size) { - CPU_EXTMEM = (UINT8 *)_MALLOC(size + 16, "EXTMEM"); - if (CPU_EXTMEM == NULL) { - size = 0; - } - } - CPU_EXTMEMSIZE = size; - } - i286core.e.ems[0] = mem + 0xc0000; - i286core.e.ems[1] = mem + 0xc4000; - i286core.e.ems[2] = mem + 0xc8000; - i286core.e.ems[3] = mem + 0xcc000; -} - -void i286x_setemm(UINT frame, UINT32 addr) { - - UINT8 *ptr; - - frame &= 3; - if (addr < USE_HIMEM) { - ptr = mem + addr; - } - else if ((addr - 0x100000 + 0x4000) <= CPU_EXTMEMSIZE) { - ptr = CPU_EXTMEM + (addr - 0x100000); - } - else { - ptr = mem + 0xc0000 + (frame << 14); - } - i286core.e.ems[frame] = ptr; -} - - -LABEL void i286x_resetprefetch(void) { - - __asm { - pushad - movzx esi, I286_IP - RESET_XPREFETCH - mov dword ptr (i286core.s.prefetchque), ebx - popad - ret - } -} - -LABEL void __fastcall i286x_interrupt(UINT8 vect) { - - __asm { - pushad - push ecx - - movzx ebx, I286_SP - sub bx, 2 - - // hlt.. - cmp byte ptr (i286core.s.prefetchque), 0f4h // hlt - jne short nonhlt - inc I286_IP -nonhlt: mov edi, SS_BASE - lea ecx, [edi + ebx] - sub bx, 2 - mov dx, I286_FLAG - and dh, 0fh - and I286_FLAG, not (T_FLAG or I_FLAG) - mov I286_TRAP, 0 - call i286_memorywrite_w - lea ecx, [edi + ebx] - sub bx, 2 - mov dx, I286_CS - call i286_memorywrite_w - mov I286_SP, bx - lea ecx, [edi + ebx] - mov dx, I286_IP - call i286_memorywrite_w - pop ecx - - xor eax, eax - mov al, cl - mov eax, dword ptr I286_MEM[eax*4] - - mov I286_IP, ax - movzx esi, ax - shr eax, 16 - mov I286_CS, ax - shl eax, 4 // make segreg - mov CS_BASE, eax - RESET_XPREFETCH - mov dword ptr (i286core.s.prefetchque), ebx - - popad - ret - } -} - - -// I286xルーチンのローカルからの割り込み -LABEL void __fastcall i286x_localint(void) { - - __asm { - push ecx - movzx ebx, I286_SP - sub bx, 2 - - mov edi, SS_BASE - lea ecx, [edi + ebx] - sub bx, 2 - mov dx, I286_FLAG - and dh, 0fh - and I286_FLAG, not (T_FLAG or I_FLAG) - mov I286_TRAP, 0 - call i286_memorywrite_w - lea ecx, [edi + ebx] - sub bx, 2 - mov dx, I286_CS - call i286_memorywrite_w - mov I286_SP, bx - lea ecx, [edi + ebx] - mov dx, si // I286_IP - call i286_memorywrite_w - pop ecx - mov eax, dword ptr I286_MEM[ecx*4] - - mov si, ax - shr eax, 16 - mov I286_CS, ax - shl eax, 4 // make segreg - mov CS_BASE, eax - - RESET_XPREFETCH - ret - } -} - - -// プロテクトモードのセレクタ(in ax / ret eax) -LABEL void __fastcall i286x_selector(void) { - - __asm { - mov ecx, dword ptr (I286_GDTR.base) - test eax, 4 - je short ixsl_1 - mov ecx, dword ptr (I286_LDTRC.base) -ixsl_1: and eax, not 7 - and ecx, 0ffffffh - lea ecx, [ecx + eax + 2] - call i286_memoryread_w - push eax - add ecx, 2 - call i286_memoryread - pop ecx - and eax, 0ffh - movzx ecx, cx - shl eax, 16 - add eax, ecx - ret - } -} - - -LABEL void i286x(void) { - - __asm { - pushad - mov ebx, dword ptr (i286core.s.prefetchque) - movzx esi, I286_IP - - cmp I286_TRAP, 0 - jne short i286_trapping - cmp dmac.working, 0 - jne short i286_dma_mnlp - -i286_mnlp: -#if defined(ENABLE_TRAP) - mov edx, esi - movzx ecx, I286_CS - call steptrap -#endif - movzx eax, bl - call i286op[eax*4] - cmp I286_REMCLOCK, 0 - jg i286_mnlp - mov dword ptr (i286core.s.prefetchque), ebx - mov I286_IP, si - popad - ret - - align 16 -i286_dma_mnlp: -#if defined(ENABLE_TRAP) - mov edx, esi - movzx ecx, I286_CS - call steptrap -#endif - movzx eax, bl - call i286op[eax*4] - call dmap_i286 - cmp I286_REMCLOCK, 0 - jg i286_dma_mnlp - mov dword ptr (i286core.s.prefetchque), ebx - mov I286_IP, si - popad - ret - - align 16 -i286_trapping: -#if defined(ENABLE_TRAP) - mov edx, esi - movzx ecx, I286_CS - call steptrap -#endif - movzx eax, bl - call i286op[eax*4] - cmp I286_TRAP, 0 - je i286notrap - mov ecx, 1 - call i286x_localint -i286notrap: mov dword ptr (i286core.s.prefetchque), ebx - mov I286_IP, si - popad - ret - } -} - - - -LABEL void i286x_step(void) { - - __asm { - pushad - mov ebx, dword ptr (i286core.s.prefetchque) - movzx esi, I286_IP - -#if defined(ENABLE_TRAP) - mov edx, esi - movzx ecx, I286_CS - call steptrap -#endif - - movzx eax, bl - call i286op[eax*4] - - cmp I286_TRAP, 0 - je short nexts - mov ecx, 1 - call i286x_localint -nexts: - mov dword ptr (i286core.s.prefetchque), ebx - mov I286_IP, si - - call dmap_i286 - popad - ret - } -} - - - - -LABEL void removeprefix(void) { - - __asm { - mov i286core.s.prefix, 0 - mov eax, DS_BASE - mov DS_FIX, eax - mov eax, SS_BASE - mov SS_FIX, eax - ret - } -} - - -I286 _reserved(void) { - - __asm { -// inc si // 01/08/31 - INT_NUM(6) - } -} - -// ---- - -I286 add_ea_r8(void) { // 00: add EA, REG8 - - __asm { - PREPART_EA_REG8(2) - add byte ptr I286_REG[eax], dl - FLAG_STORE_OF - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG8(7) - MEMORY_EA_REG8_X(7, 16) - add byte ptr I286_MEM[ecx], dl - FLAG_STORE_OF - ret - EXTMEM_EA_REG8 - add al, byte ptr I286_REG[ebp] - mov dl, al - FLAG_STORE_OF - jmp i286_memorywrite - } -} - -I286 add_ea_r16(void) { // 01: add EA, REG16 - - __asm { - PREPART_EA_REG16(2) - add word ptr I286_REG[eax*2], dx - FLAG_STORE_OF - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG16(7) - MEMORY_EA_REG16_X(7, 16) - add word ptr I286_MEM[ecx], dx - FLAG_STORE_OF - ret - EXTMEM_EA_REG16 - add ax, word ptr I286_REG[ebp] - mov dx, ax - FLAG_STORE_OF - jmp i286_memorywrite_w - } -} - -I286 add_r8_ea(void) { // 02: add REG8, EA - - __asm { - //PREPART_REG8_EA(2, 7) - PREPART_REG8_EA_X(2, 7, 2, 16) - add I286_REG[ebp], al - FLAG_STORE_OF - ret - } -} - -I286 add_r16_ea(void) { // 03: add REG16, EA - - __asm { - //PREPART_REG16_EA(2, 7) - PREPART_REG16_EA_X(2, 7, 2, 16) - add I286_REG[ebp], ax - FLAG_STORE_OF - ret - } -} - -I286 add_al_data8(void) { // 04: add al, DATA8 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - add I286_AL, bh - FLAG_STORE_OF - GET_NEXTPRE2 - ret - } -} - -I286 add_ax_data16(void) { // 05: add ax, DATA16 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE3a - add I286_AX, bx - FLAG_STORE_OF - GET_NEXTPRE3b - ret - } -} - -I286 push_es(void) { // 06: push es - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_ES) - } -} - -I286 pop_es(void) { // 07: pop es - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - REGPOP(I286_ES) - movzx eax, ax - test byte ptr (I286_MSW), MSW_PE - jne short pop_es_pe - shl eax, 4 // make segreg -pop_es_base: mov ES_BASE, eax - GET_NEXTPRE1 - ret - -pop_es_pe: push offset pop_es_base - jmp i286x_selector - } -} - -I286 or_ea_r8(void) { // 08: or EA, REG8 - - __asm { - PREPART_EA_REG8(2) - or byte ptr I286_REG[eax], dl - FLAG_STORE0 - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG8(7) - MEMORY_EA_REG8_X(7, 16) - or byte ptr I286_MEM[ecx], dl - FLAG_STORE0 - ret - EXTMEM_EA_REG8 - or al, byte ptr I286_REG[ebp] - mov dl, al - FLAG_STORE0 - jmp i286_memorywrite - } -} - -I286 or_ea_r16(void) { // 09: or EA, REG16 - - __asm { - PREPART_EA_REG16(2) - or word ptr I286_REG[eax*2], dx - FLAG_STORE0 - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG16(7) - MEMORY_EA_REG16_X(7, 16) - or word ptr I286_MEM[ecx], dx - FLAG_STORE0 - ret - EXTMEM_EA_REG16 - or ax, word ptr I286_REG[ebp] - mov dx, ax - FLAG_STORE0 - jmp i286_memorywrite_w - } -} - -I286 or_r8_ea(void) { // 0A: or REG8, EA - - __asm { - //PREPART_REG8_EA(2, 7) - PREPART_REG8_EA_X(2, 7, 2, 11) - or I286_REG[ebp], al - FLAG_STORE0 - ret - } -} - -I286 or_r16_ea(void) { // 0B: or REG16, EA - - __asm { - //PREPART_REG16_EA(2, 7) - PREPART_REG16_EA_X(2, 7, 2, 11) - or I286_REG[ebp], ax - FLAG_STORE0 - ret - } -} - -I286 or_al_data8(void) { // 0C: or al, DATA8 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - or I286_AL, bh - FLAG_STORE0 - GET_NEXTPRE2 - ret - } -} - -I286 or_ax_data16(void) { // 0D: or ax, DATA16 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE3a - or I286_AX, bx - FLAG_STORE0 - GET_NEXTPRE3b - ret - } -} - -I286 push_cs(void) { // 0E: push es - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_CS) - } -} - - -I286 adc_ea_r8(void) { // 10: adc EA, REG8 - - __asm { - PREPART_EA_REG8(2) - CFLAG_LOAD - adc byte ptr I286_REG[eax], dl - FLAG_STORE_OF - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG8(7) - MEMORY_EA_REG8_X(7, 16) - CFLAG_LOAD - adc byte ptr I286_MEM[ecx], dl - FLAG_STORE_OF - ret - EXTMEM_EA_REG8 - CFLAG_LOAD - adc al, byte ptr I286_REG[ebp] - mov dl, al - FLAG_STORE_OF - jmp i286_memorywrite - } -} - -I286 adc_ea_r16(void) { // 11: adc EA, REG16 - - __asm { - PREPART_EA_REG16(2) - CFLAG_LOAD - adc word ptr I286_REG[eax*2], dx - FLAG_STORE_OF - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG16(7) - MEMORY_EA_REG16_X(7, 16) - CFLAG_LOAD - adc word ptr I286_MEM[ecx], dx - FLAG_STORE_OF - ret - EXTMEM_EA_REG16 - CFLAG_LOAD - adc ax, word ptr I286_REG[ebp] - mov dx, ax - FLAG_STORE_OF - jmp i286_memorywrite_w - } -} - -I286 adc_r8_ea(void) { // 12: adc REG8, EA - - __asm { - //PREPART_REG8_EA(2, 7) - PREPART_REG8_EA_X(2, 7, 2, 11) - CFLAG_LOAD - adc I286_REG[ebp], al - FLAG_STORE_OF - ret - } -} - -I286 adc_r16_ea(void) { // 13: adc REG16, EA - - __asm { - //PREPART_REG16_EA(2, 7) - PREPART_REG16_EA_X(2, 7, 2, 11) - CFLAG_LOAD - adc I286_REG[ebp], ax - FLAG_STORE_OF - ret - } -} - -I286 adc_al_data8(void) { // 14: adc al, DATA8 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - CFLAG_LOAD - adc I286_AL, bh - FLAG_STORE_OF - GET_NEXTPRE2 - ret - } -} - -I286 adc_ax_data16(void) { // 15: adc ax, DATA16 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE3a - CFLAG_LOAD - adc I286_AX, bx - FLAG_STORE_OF - GET_NEXTPRE3b - ret - } -} - -I286 push_ss(void) { // 16: push ss - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_SS) - } -} - -I286 pop_ss(void) { // 17: pop ss - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - REGPOP(I286_SS) - movzx eax, ax - test byte ptr (I286_MSW), MSW_PE - jne short pop_ss_pe - shl eax, 4 // make segreg -pop_ss_base: mov SS_BASE, eax - mov SS_FIX, eax - cmp i286core.s.prefix, 0 // 00/06/24 - jne prefix_exist - noprefix: - movzx ebp, bh - GET_NEXTPRE1 - jmp i286op[ebp*4] - -pop_ss_pe: push offset pop_ss_base - jmp i286x_selector - -prefix_exist: pop eax // eax<-offset removeprefix - call eax - jmp noprefix - } -} - -I286 sbb_ea_r8(void) { // 18: sbb EA, REG8 - - __asm { - PREPART_EA_REG8(2) - CFLAG_LOAD - sbb byte ptr I286_REG[eax], dl - FLAG_STORE_OF - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG8(7) - MEMORY_EA_REG8_X(7, 16) - CFLAG_LOAD - sbb byte ptr I286_MEM[ecx], dl - FLAG_STORE_OF - ret - EXTMEM_EA_REG8 - CFLAG_LOAD - sbb al, byte ptr I286_REG[ebp] - mov dl, al - FLAG_STORE_OF - jmp i286_memorywrite - } -} - -I286 sbb_ea_r16(void) { // 19: sbb EA, REG16 - - __asm { - PREPART_EA_REG16(2) - CFLAG_LOAD - sbb word ptr I286_REG[eax*2], dx - FLAG_STORE_OF - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG16(7) - MEMORY_EA_REG16_X(7, 16) - CFLAG_LOAD - sbb word ptr I286_MEM[ecx], dx - FLAG_STORE_OF - ret - EXTMEM_EA_REG16 - CFLAG_LOAD - sbb ax, word ptr I286_REG[ebp] - mov dx, ax - FLAG_STORE_OF - jmp i286_memorywrite_w - } -} - -I286 sbb_r8_ea(void) { // 1A: sbb REG8, EA - - __asm { - //PREPART_REG8_EA(2, 7) - PREPART_REG8_EA_X(2, 7, 2, 11) - CFLAG_LOAD - sbb I286_REG[ebp], al - FLAG_STORE_OF - ret - } -} - -I286 sbb_r16_ea(void) { // 1B: sbb REG16, EA - - __asm { - //PREPART_REG16_EA(2, 7) - PREPART_REG16_EA_X(2, 7, 2, 11) - CFLAG_LOAD - sbb I286_REG[ebp], ax - FLAG_STORE_OF - ret - } -} - -I286 sbb_al_data8(void) { // 1C: sbb al, DATA8 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - CFLAG_LOAD - sbb I286_AL, bh - FLAG_STORE_OF - GET_NEXTPRE2 - ret - } -} - -I286 sbb_ax_data16(void) { // 1D: sbb ax, DATA16 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE3a - CFLAG_LOAD - sbb I286_AX, bx - FLAG_STORE_OF - GET_NEXTPRE3b - ret - } -} - -I286 push_ds(void) { // 1E: push ds - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_DS) - } -} - -I286 pop_ds(void) { // 1F: pop ds - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - REGPOP(I286_DS) - movzx eax, ax - test byte ptr (I286_MSW), MSW_PE - jne short pop_ds_pe - shl eax, 4 // make segreg -pop_ds_base: mov DS_BASE, eax - mov DS_FIX, eax - GET_NEXTPRE1 - ret - -pop_ds_pe: push offset pop_ds_base - jmp i286x_selector - } -} - -I286 and_ea_r8(void) { // 20: and EA, REG8 - - __asm { - PREPART_EA_REG8(2) - and byte ptr I286_REG[eax], dl - FLAG_STORE0 - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG8(7) - MEMORY_EA_REG8_X(7, 16) - and byte ptr I286_MEM[ecx], dl - FLAG_STORE0 - ret - EXTMEM_EA_REG8 - and al, byte ptr I286_REG[ebp] - mov dl, al - FLAG_STORE0 - jmp i286_memorywrite - } -} - -I286 and_ea_r16(void) { // 21: and EA, REG16 - - __asm { - PREPART_EA_REG16(2) - and word ptr I286_REG[eax*2], dx - FLAG_STORE0 - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG16(7) - MEMORY_EA_REG16_X(7, 16) - and word ptr I286_MEM[ecx], dx - FLAG_STORE0 - ret - EXTMEM_EA_REG16 - and ax, word ptr I286_REG[ebp] - mov dx, ax - FLAG_STORE0 - jmp i286_memorywrite_w - } -} - -I286 and_r8_ea(void) { // 22: and REG8, EA - - __asm { - //PREPART_REG8_EA(2, 7) - PREPART_REG8_EA_X(2, 7, 2, 11) - and I286_REG[ebp], al - FLAG_STORE0 - ret - } -} - -I286 and_r16_ea(void) { // 23: and REG16, EA - - __asm { - //PREPART_REG16_EA(2, 7) - PREPART_REG16_EA_X(2, 7, 2, 11) - and I286_REG[ebp], ax - FLAG_STORE0 - ret - } -} - -I286 and_al_data8(void) { // 24: and al, DATA8 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - and I286_AL, bh - FLAG_STORE0 - GET_NEXTPRE2 - ret - } -} - -I286 and_ax_data16(void) { // 25: and ax, DATA16 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE3a - and I286_AX, bx - FLAG_STORE0 - GET_NEXTPRE3b - ret - } -} - -I286 segprefix_es(void) { // 26: es: - - __asm { - mov eax, ES_BASE - mov DS_FIX, eax - mov SS_FIX, eax - I286PREFIX(i286op) - } -} - -I286 _daa(void) { // 27: daa - - __asm { - I286CLOCK(3) - FLAG_LOAD - mov ax, I286_AX - daa - mov I286_AX, ax - FLAG_STORE - GET_NEXTPRE1 - ret - } -} - -I286 sub_ea_r8(void) { // 28: sub EA, REG8 - - __asm { - PREPART_EA_REG8(2) - sub byte ptr I286_REG[eax], dl - FLAG_STORE_OF - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG8(7) - MEMORY_EA_REG8_X(7, 16) - sub byte ptr I286_MEM[ecx], dl - FLAG_STORE_OF - ret - EXTMEM_EA_REG8 - sub al, byte ptr I286_REG[ebp] - mov dl, al - FLAG_STORE_OF - jmp i286_memorywrite - } -} - -I286 sub_ea_r16(void) { // 29: sub EA, REG16 - - __asm { - PREPART_EA_REG16(2) - sub word ptr I286_REG[eax*2], dx - FLAG_STORE_OF - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG16(7) - MEMORY_EA_REG16_X(7, 16) - sub word ptr I286_MEM[ecx], dx - FLAG_STORE_OF - ret - EXTMEM_EA_REG16 - sub ax, word ptr I286_REG[ebp] - mov dx, ax - FLAG_STORE_OF - jmp i286_memorywrite_w - } -} - -I286 sub_r8_ea(void) { // 2A: sub REG8, EA - - __asm { - //PREPART_REG8_EA(2, 7) - PREPART_REG8_EA_X(2, 7, 2, 11) - sub I286_REG[ebp], al - FLAG_STORE_OF - ret - } -} - -I286 sub_r16_ea(void) { // 2B: sub REG16, EA - - __asm { - //PREPART_REG16_EA(2, 7) - PREPART_REG16_EA_X(2, 7, 2, 11) - sub I286_REG[ebp], ax - FLAG_STORE_OF - ret - } -} - -I286 sub_al_data8(void) { // 2C: sub al, DATA8 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - sub I286_AL, bh - FLAG_STORE_OF - GET_NEXTPRE2 - ret - } -} - -I286 sub_ax_data16(void) { // 2D: sub ax, DATA16 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE3a - sub I286_AX, bx - FLAG_STORE_OF - GET_NEXTPRE3b - ret - } -} - -I286 segprefix_cs(void) { // 2E: cs: - - __asm { - mov eax, CS_BASE - mov DS_FIX, eax - mov SS_FIX, eax - I286PREFIX(i286op) - } -} - -I286 _das(void) { // 2F: das - - __asm { - I286CLOCK(3) - FLAG_LOAD - mov ax, I286_AX - das - mov I286_AX, ax - FLAG_STORE - GET_NEXTPRE1 - ret - } -} - - -I286 xor_ea_r8(void) { // 30: xor EA, REG8 - - __asm { - PREPART_EA_REG8(2) - xor byte ptr I286_REG[eax], dl - FLAG_STORE0 - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG8(7) - MEMORY_EA_REG8_X(7, 16) - xor byte ptr I286_MEM[ecx], dl - FLAG_STORE0 - ret - EXTMEM_EA_REG8 - xor al, byte ptr I286_REG[ebp] - mov dl, al - FLAG_STORE0 - jmp i286_memorywrite - } -} - -I286 xor_ea_r16(void) { // 31: xor EA, REG16 - - __asm { - PREPART_EA_REG16(2) - xor word ptr I286_REG[eax*2], dx - FLAG_STORE0 - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG16(7) - MEMORY_EA_REG16_X(7, 16) - xor word ptr I286_MEM[ecx], dx - FLAG_STORE0 - ret - EXTMEM_EA_REG16 - xor ax, word ptr I286_REG[ebp] - mov dx, ax - FLAG_STORE0 - jmp i286_memorywrite_w - } -} - -I286 xor_r8_ea(void) { // 32: xor REG8, EA - - __asm { - //PREPART_REG8_EA(2, 7) - PREPART_REG8_EA_X(2, 7, 2, 11) - xor byte ptr I286_REG[ebp], al - FLAG_STORE0 - ret - } -} - -I286 xor_r16_ea(void) { // 33: xor REG16, EA - - __asm { - //PREPART_REG16_EA(2, 7) - PREPART_REG16_EA_X(2, 7, 2, 11) - xor word ptr I286_REG[ebp], ax - FLAG_STORE0 - ret - } -} - -I286 xor_al_data8(void) { // 34: xor al, DATA8 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - xor I286_AL, bh - FLAG_STORE0 - GET_NEXTPRE2 - ret - } -} - -I286 xor_ax_data16(void) { // 35: xor ax, DATA16 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE3a - xor I286_AX, bx - FLAG_STORE0 - GET_NEXTPRE3b - ret - } -} - -I286 segprefix_ss(void) { // 36: ss: - - __asm { - mov eax, SS_BASE - mov DS_FIX, eax - mov SS_FIX, eax - I286PREFIX(i286op) - } -} - -I286 _aaa(void) { // 37: aaa - - __asm { - I286CLOCK(3) - FLAG_LOAD - mov ax, I286_AX - aaa - mov I286_AX, ax - FLAG_STORE - GET_NEXTPRE1 - ret - } -} - -I286 cmp_ea_r8(void) { // 38: cmp EA, REG8 - - __asm { - PREPART_EA_REG8(2) - cmp byte ptr I286_REG[eax], dl - FLAG_STORE_OF - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG8(6) - MEMORY_EA_REG8_X(6, 11) - cmp byte ptr I286_MEM[ecx], dl - FLAG_STORE_OF - ret - EXTMEM_EA_REG8 - cmp al, byte ptr I286_REG[ebp] - FLAG_STORE_OF - ret - } -} - -I286 cmp_ea_r16(void) { // 39: cmp EA, REG16 - - __asm { - PREPART_EA_REG16(2) - cmp I286_REG[eax*2], dx - FLAG_STORE_OF - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG16(6) - MEMORY_EA_REG16_X(6, 11) - cmp word ptr I286_MEM[ecx], dx - FLAG_STORE_OF - ret - EXTMEM_EA_REG16 - cmp ax, I286_REG[ebp] - FLAG_STORE_OF - ret - } -} - -I286 cmp_r8_ea(void) { // 3A: cmp REG8, EA - - __asm { - //PREPART_REG8_EA(2, 6) - PREPART_REG8_EA_X(2, 6, 2, 11) - cmp I286_REG[ebp], al - FLAG_STORE_OF - ret - } -} - -I286 cmp_r16_ea(void) { // 3B: cmp REG16, EA - - __asm { - //PREPART_REG16_EA(2, 6) - PREPART_REG16_EA_X(2, 6, 2, 11) - cmp I286_REG[ebp], ax - FLAG_STORE_OF - ret - } -} - -I286 cmp_al_data8(void) { // 3C: cmp al, DATA8 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - cmp I286_AL, bh - FLAG_STORE_OF - GET_NEXTPRE2 - ret - } -} - -I286 cmp_ax_data16(void) { // 3D: cmp ax, DATA16 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE3a - cmp I286_AX, bx - FLAG_STORE_OF - GET_NEXTPRE3b - ret - } -} - -I286 segprefix_ds(void) { // 3E: ds: - - __asm { - mov eax, DS_BASE - mov DS_FIX, eax - mov SS_FIX, eax - I286PREFIX(i286op) - } -} - -I286 _aas(void) { // 3F: aas - - __asm { - I286CLOCK(3) - FLAG_LOAD - mov ax, I286_AX - aas - mov I286_AX, ax - FLAG_STORE - GET_NEXTPRE1 - ret - } -} - - -I286 inc_ax(void) { // 40: inc ax - - __asm { - I286CLOCK(2) - inc I286_AX - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 inc_cx(void) { // 41: inc cx - - __asm { - I286CLOCK(2) - inc I286_CX - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 inc_dx(void) { // 42: inc dx - - __asm { - I286CLOCK(2) - inc I286_DX - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 inc_bx(void) { // 43: inc bx - - __asm { - I286CLOCK(2) - inc I286_BX - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 inc_sp(void) { // 44: inc sp - - __asm { - I286CLOCK(2) - inc I286_SP - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 inc_bp(void) { // 45: inc bp - - __asm { - I286CLOCK(2) - inc I286_BP - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 inc_si(void) { // 46: inc si - - __asm { - I286CLOCK(2) - inc I286_SI - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 inc_di(void) { // 47: inc di - - __asm { - I286CLOCK(2) - inc I286_DI - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 dec_ax(void) { // 48: dec ax - - __asm { - I286CLOCK(2) - dec I286_AX - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 dec_cx(void) { // 49: dec cx - - __asm { - I286CLOCK(2) - dec I286_CX - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 dec_dx(void) { // 4a: dec dx - - __asm { - I286CLOCK(2) - dec I286_DX - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 dec_bx(void) { // 4b: dec bx - - __asm { - I286CLOCK(2) - dec I286_BX - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 dec_sp(void) { // 4c: dec sp - - __asm { - I286CLOCK(2) - dec I286_SP - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 dec_bp(void) { // 4d: dec bp - - __asm { - I286CLOCK(2) - dec I286_BP - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 dec_si(void) { // 4e: dec si - - __asm { - I286CLOCK(2) - dec I286_SI - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - -I286 dec_di(void) { // 4f: dec di - - __asm { - I286CLOCK(2) - dec I286_DI - FLAG_STORE_NC - GET_NEXTPRE1 - ret - } -} - - -I286 push_ax(void) { // 50: push ax - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_AX) - } -} - -I286 push_cx(void) { // 51: push cx - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_CX) - } -} - -I286 push_dx(void) { // 52: push dx - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_DX) - } -} - -I286 push_bx(void) { // 53: push bx - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_BX) - } -} - -I286 push_sp(void) { // 54: push sp - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_SP) - } -} - -I286 push_bp(void) { // 55: push bp - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_BP) - } -} - -I286 push_si(void) { // 56: push si - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_SI) - } -} - -I286 push_di(void) { // 57: push di - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - REGPUSH1(I286_DI) - } -} - -I286 pop_ax(void) { // 58: pop ax - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - REGPOP(I286_AX) - GET_NEXTPRE1 - ret - } -} - -I286 pop_cx(void) { // 59: pop cx - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - REGPOP(I286_CX) - GET_NEXTPRE1 - ret - } -} - -I286 pop_dx(void) { // 5A: pop dx - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - REGPOP(I286_DX) - GET_NEXTPRE1 - ret - } -} - -I286 pop_bx(void) { // 5B: pop bx - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - REGPOP(I286_BX) - GET_NEXTPRE1 - ret - } -} - -I286 pop_sp(void) { // 5C: pop sp - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - movzx ecx, I286_SP - add ecx, SS_BASE - call i286_memoryread_w - mov I286_SP, ax - GET_NEXTPRE1 - ret - } -} - -I286 pop_bp(void) { // 5D: pop bp - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - REGPOP(I286_BP) - GET_NEXTPRE1 - ret - } -} - -I286 pop_si(void) { // 5E: pop si - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - REGPOP(I286_SI) - GET_NEXTPRE1 - ret - } -} - -I286 pop_di(void) { // 5F: pop di - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - REGPOP(I286_DI) - GET_NEXTPRE1 - ret - } -} - - -I286 _pusha(void) { // 60: pusha - - __asm { - movzx ebp, I286_SP - sub bp, 2 - - GET_NEXTPRE1 - //I286CLOCK(17) - I286CLOCK_X(a, 17, 35) - mov edi, SS_BASE - - lea ecx, [edi + ebp] - sub bp, 2 - mov dx, I286_AX - call i286_memorywrite_w - - lea ecx, [edi + ebp] - sub bp, 2 - mov dx, I286_CX - call i286_memorywrite_w - - lea ecx, [edi + ebp] - sub bp, 2 - mov dx, I286_DX - call i286_memorywrite_w - - lea ecx, [edi + ebp] - sub bp, 2 - mov dx, I286_BX - call i286_memorywrite_w - - lea ecx, [edi + ebp] - sub bp, 2 - mov dx, I286_SP - call i286_memorywrite_w - - lea ecx, [edi + ebp] - sub bp, 2 - mov dx, I286_BP - call i286_memorywrite_w - - lea ecx, [edi + ebp] - sub bp, 2 - mov dx, I286_SI - call i286_memorywrite_w - - mov I286_SP, bp - lea ecx, [edi + ebp] - mov dx, I286_DI - jmp i286_memorywrite_w - } -} - -I286 _popa(void) { // 61: popa - - __asm { - GET_NEXTPRE1 - //I286CLOCK(19) - I286CLOCK_X(a, 19, 43) - mov edi, SS_BASE - movzx ebp, I286_SP - - lea ecx, [edi + ebp] - add bp, 2 - call i286_memoryread_w - mov I286_DI, ax - - lea ecx, [edi + ebp] - add bp, 2 - call i286_memoryread_w - mov I286_SI, ax - - lea ecx, [edi + ebp] - add bp, 4 - call i286_memoryread_w - mov I286_BP, ax - - lea ecx, [edi + ebp] - add bp, 2 - call i286_memoryread_w - mov I286_BX, ax - - lea ecx, [edi + ebp] - add bp, 2 - call i286_memoryread_w - mov I286_DX, ax - - lea ecx, [edi + ebp] - add bp, 2 - call i286_memoryread_w - mov I286_CX, ax - - lea ecx, [edi + ebp] - call i286_memoryread_w - mov I286_AX, ax - add I286_SP, 16 - ret - } -} - -I286 _bound(void) { - - __asm { - movzx eax, bh - mov ebp, 6 - cmp al, 0c0h - jnc bountint - mov ebp, eax - shr ebp, 3-1 - and ebp, 7*2 - I286CLOCK(13) - call p_ea_dst[eax*4] - call i286_memoryread_w - cmp I286_REG[ebp], ax - jb bounttrue - add ecx, 2 - call i286_memoryread_w - cmp I286_REG[ebp], ax - ja bounttrue - ret - - align 16 -bounttrue: mov ebp, 5 -bountint: INT_NUM(ebp) - } -} - -I286 _arpl(void) { - - __asm { - xor eax, eax - cmp bh, 0c0h - setc al - // add si, ax - add eax, 10 - I286CLOCK(eax) - INT_NUM(6) - } -} - -I286 push_data16(void) { // 68: push DATA16 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 7) - GET_NEXTPRE3a - REGPUSH(bx) - GET_NEXTPRE3b - ret - } -} - -I286 imul_reg_ea_data16(void) { // 69: imul REG, EA, DATA16 - - __asm { - //PREPART_REG16_EA(21, 24) - PREPART_REG16_EA_X(21, 24, 45, 49) - imul bx - mov I286_REG[ebp], ax - - mov al, ah - lahf - and ah, 0feh - and I286_FLAGL, 0feh - or I286_FLAGL, ah - rcl al, 1 - adc dx, 0 -#if defined(VAEG_FIX) - jz imulnooverflow -#else - jne imulnooverflow -#endif - or I286_FLAG, (O_FLAG or C_FLAG) - -imulnooverflow: GET_NEXTPRE2 - ret - } -} - -I286 push_data8(void) { // 6A: push DATA8 - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - mov al, bh - cbw - REGPUSH(ax) - - GET_NEXTPRE2 - ret - } -} - -I286 imul_reg_ea_data8(void) { // 6B: imul REG, EA, DATA8 - - __asm { - PREPART_REG16_EA(21, 24) - movsx edx, bl - imul dx - mov I286_REG[ebp], ax - - mov al, ah - lahf - and ah, 0feh - and I286_FLAGL, 0feh - or I286_FLAGL, ah - rcl al, 1 - adc dx, 0 -#if defined(VAEG_FIX) - jz imulnooverflow -#else - jne imulnooverflow -#endif - or I286_FLAG, (O_FLAG or C_FLAG) - -imulnooverflow: GET_NEXTPRE1 - ret - } -} - -I286 _insb(void) { // 6C: insb - - __asm { - GET_NEXTPRE1 - I286CLOCK(5) - movzx ecx, I286_DX - call iocore_inp8 - mov dl, al - movzx ecx, I286_ES - shl ecx, 4 - movzx eax, I286_DI - add ecx, eax - STRING_DIR - add I286_DI, ax - jmp i286_memorywrite - } -} - -I286 _insw(void) { // 6D: insw - - __asm { - GET_NEXTPRE1 - I286CLOCK(5) - movzx ecx, I286_DX - call iocore_inp16 - mov dx, ax - movzx ecx, I286_ES - shl ecx, 4 - movzx eax, I286_DI - add ecx, eax - STRING_DIRx2 - add I286_DI, ax - jmp i286_memorywrite_w - } -} - -I286 _outsb(void) { // 6E: outsb - - __asm { - GET_NEXTPRE1 - I286CLOCK(3) - movzx ecx, I286_SI - add ecx, DS_FIX - call i286_memoryread - mov dl, al - STRING_DIR - add I286_SI, ax - movzx ecx, I286_DX - jmp iocore_out8 - } -} - -I286 _outsw(void) { // 6F: outsw - - __asm { - GET_NEXTPRE1 - I286CLOCK(3) - movzx ecx, I286_SI - add ecx, DS_FIX - call i286_memoryread_w - mov dx, ax - STRING_DIRx2 - add I286_SI, ax - movzx ecx, I286_DX - jmp iocore_out16 - } -} - - -I286 jo_short(void) { // 70: jo short - - __asm { - test I286_FLAG, O_FLAG - jne flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jno_short(void) { // 71: jno short - - __asm { - test I286_FLAG, O_FLAG - je flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jc_short(void) { // 72: jnae/jb/jc short - - __asm { - test I286_FLAG, C_FLAG - jne flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jnc_short(void) { // 73: jae/jnb/jnc short - - __asm { - test I286_FLAG, C_FLAG - je flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jz_short(void) { // 74: je/jz short - - __asm { - test I286_FLAG, Z_FLAG - jne flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jnz_short(void) { // 75: jne/jnz short - - __asm { - test I286_FLAG, Z_FLAG - jne flagnonjump - - //I286CLOCK(7) // ジャンプする事が多いと思う - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - -flagnonjump: //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - } -} - -I286 jna_short(void) { // 76: jna/jbe short - - __asm { - test I286_FLAG, (Z_FLAG or C_FLAG) - jne flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 ja_short(void) { // 77: ja/jnbe short - - __asm { - test I286_FLAG, (Z_FLAG or C_FLAG) - je flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 js_short(void) { // 78: js short - - __asm { - test I286_FLAG, S_FLAG - jne flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jns_short(void) { // 79: jns short - - __asm { - test I286_FLAG, S_FLAG - je flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jp_short(void) { // 7A: jp/jpe short - - __asm { - test I286_FLAG, P_FLAG - jne flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jnp_short(void) { // 7B: jnp/jpo short - - __asm { - test I286_FLAG, P_FLAG - je flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jl_short(void) { // 7C: jl/jnge short - - __asm { - mov dx, I286_FLAG - shl dh, 4 - xor dl, dh - js flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jnl_short(void) { // 7D: jnl/jge short - - __asm { - mov dx, I286_FLAG - shl dh, 4 - xor dl, dh - jns flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jle_short(void) { // 7E: jle/jng short - - __asm { - mov dx, I286_FLAG - test dx, Z_FLAG - jne flagjump - shl dh, 4 - xor dl, dh - js flagjump - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - - align 16 -flagjump: //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 jnle_short(void) { // 7F: jg/jnle short - - __asm { - mov dx, I286_FLAG - test dx, Z_FLAG - jne notjump - shl dh, 4 - xor dl, dh - js notjump - //I286CLOCK(7) - I286CLOCK_X(b, 7, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - - align 16 -notjump: //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - GET_NEXTPRE2 - ret - } -} - - -I286 calc_ea8_i8(void) { // 80,82: op EA8, DATA8 - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 // opcode - cmp al, 0c0h - jc memory_eareg8 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - bt ax, 2 - rcl eax, 1 - and eax, 7 - lea ebp, I286_REG[eax] - mov edx, ebx - shr edx, 16 - GET_NEXTPRE3 - jmp op8xreg8_xtable[edi] - align 16 - memory_eareg8: - //I286CLOCK(7) - I286CLOCK_X(b, 7, 18) - call p_ea_dst[eax*4] - cmp ecx, I286_MEMWRITEMAX - jnc extmem_eareg8 - lea ebp, I286_MEM[ecx] - mov edx, ebx - GET_NEXTPRE1 - jmp op8xreg8_xtable[edi] - align 16 - extmem_eareg8: - call i286_memoryread - mov dl, al - call op8xext8_xtable[edi] - GET_NEXTPRE1 - ret - } -} - -I286 calc_ea16_i16(void) { // 81: op EA16, DATA16 - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 // opcode - cmp al, 0c0h - jc memory_eareg8 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - and eax, 7 - lea ebp, word ptr I286_REG[eax*2] - mov edx, ebx - shr edx, 16 - GET_NEXTPRE4 - jmp op8xreg16_xtable[edi] - align 16 - memory_eareg8: - //I286CLOCK(7) - I286CLOCK_X(b, 7, 18) - call p_ea_dst[eax*4] - cmp ecx, I286_MEMWRITEMAX - jnc extmem_eareg8 - lea ebp, word ptr I286_MEM[ecx] - mov edx, ebx - GET_NEXTPRE2 - jmp op8xreg16_xtable[edi] - align 16 - extmem_eareg8: - call i286_memoryread_w - mov edx, eax - call op8xext16_xtable[edi] - GET_NEXTPRE2 - ret - } -} - -I286 calc_ea16_i8(void) { // 83: op EA16, DATA8 - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 // opcode - cmp al, 0c0h - jc memory_eareg8 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - and eax, 7 - lea ebp, I286_REG[eax*2] - GET_NEXTPRE2 - movsx edx, bl - GET_NEXTPRE1 - jmp op8xreg16_xtable[edi] - align 16 - memory_eareg8: - //I286CLOCK(7) - I286CLOCK_X(b, 7, 18) - call p_ea_dst[eax*4] - cmp ecx, (I286_MEMWRITEMAX-1) - jnc extmem_eareg8 - lea ebp, I286_MEM[ecx] - movsx edx, bl - GET_NEXTPRE1 - jmp op8xreg16_xtable[edi] - align 16 - extmem_eareg8: - call i286_memoryread_w - mov edx, eax - movsx eax, bl - call op8xext16_atable[edi] - GET_NEXTPRE1 - ret - } -} - -I286 test_ea_r8(void) { // 84: test EA, REG8 - - __asm { - PREPART_EA_REG8(2) - test I286_REG[eax], dl - FLAG_STORE0 - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG8(7) - MEMORY_EA_REG8_X(7, 10) - test I286_MEM[ecx], dl - FLAG_STORE0 - ret - EXTMEM_EA_REG8 - test al, I286_REG[ebp] - FLAG_STORE0 - ret - } -} - -I286 test_ea_r16(void) { // 85: test EA, REG16 - - __asm { - PREPART_EA_REG16(2) - test I286_REG[eax*2], dx - FLAG_STORE0 - GET_NEXTPRE2 // ea_regの regregだけ - ret - //MEMORY_EA_REG16(6) - MEMORY_EA_REG16_X(6, 10) - test word ptr I286_MEM[ecx], dx - FLAG_STORE0 - ret - EXTMEM_EA_REG16 - test ax, I286_REG[ebp] - FLAG_STORE0 - ret - } -} - -I286 xchg_ea_r8(void) { // 86: xchg EA, REG8 - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3 - bt di, 2 - rcl edi, 1 - and edi, 7 - cmp al, 0c0h - jc memory_eareg8 - bt ax, 2 - rcl eax, 1 - and eax, 7 - I286CLOCK(3) - mov dl, I286_REG[edi] - xchg dl, I286_REG[eax] - mov I286_REG[edi], dl - GET_NEXTPRE2 - ret - align 16 - memory_eareg8: - //I286CLOCK(5) - I286CLOCK_X(b, 5, 16) - call p_ea_dst[eax*4] - cmp ecx, I286_MEMREADMAX - jae extmem_eareg8 - mov dl, I286_REG[edi] - xchg I286_MEM[ecx], dl - mov I286_REG[edi], dl - ret - align 16 - extmem_eareg8: - call i286_memoryread - xchg al, I286_REG[edi] - mov dl, al - jmp i286_memorywrite - } -} - -I286 xchg_ea_r16(void) { // 87: xchg EA, REG16 - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-1 - and edi, 7*2 - cmp al, 0c0h - jc memory_eareg16 - and eax, 7 - I286CLOCK(3) - mov dx, I286_REG[edi] - xchg dx, I286_REG[eax*2] - mov I286_REG[edi], dx - GET_NEXTPRE2 - ret - align 16 - memory_eareg16: - //I286CLOCK(5) - I286CLOCK_X(b, 5, 16) - call p_ea_dst[eax*4] - cmp ecx, (I286_MEMREADMAX-1) - jae extmem_eareg16 - mov dx, word ptr I286_MEM[ecx] - xchg dx, I286_REG[edi] - mov word ptr I286_MEM[ecx], dx - ret - align 16 - extmem_eareg16: - call i286_memoryread_w - xchg ax, I286_REG[edi] - mov dx, ax - jmp i286_memorywrite_w - } -} - -I286 mov_ea_r8(void) { // 88: mov EA, REG8 - - __asm { - PREPART_EA_REG8(2) - mov I286_REG[eax], dl - GET_NEXTPRE2 // ea_regの regregだけ - ret - align 16 - memory_eareg8: - //I286CLOCK(3) - I286CLOCK_X(b, 3, 9) - call p_ea_dst[eax*4] - mov dl, I286_REG[ebp] - jmp i286_memorywrite - } -} - -I286 mov_ea_r16(void) { // 89: mov EA, REG16 - - __asm { - PREPART_EA_REG16(2) - mov I286_REG[eax*2], dx - GET_NEXTPRE2 // ea_regの regregだけ - ret - memory_eareg16: - //I286CLOCK(3) - I286CLOCK_X(b, 3, 9) - call p_ea_dst[eax*4] - mov dx, I286_REG[ebp] - jmp i286_memorywrite_w - } -} - -I286 mov_r8_ea(void) { // 8A: mov REG8, EA - - __asm { - //PREPART_REG8_EA(2, 5) - PREPART_REG8_EA_X(2, 5, 2, 11) - mov I286_REG[ebp], al - ret - } -} - -I286 mov_r16_ea(void) { // 8B: add REG16, EA - - __asm { - //PREPART_REG16_EA(2, 5) - PREPART_REG16_EA_X(2, 5, 2, 11) - mov I286_REG[ebp], ax - ret - } -} - -I286 mov_ea_seg(void) { // 8C: mov EA, segreg - - __asm { - movzx eax, bh - mov ebp, eax - shr ebp, 3-1 - and ebp, 3*2 - mov dx, word ptr I286_SEGREG[ebp] - cmp al, 0c0h - jc memory_eareg16 - I286CLOCK(2) - and eax, 7 - mov word ptr I286_REG[eax*2], dx - GET_NEXTPRE2 - ret - align 16 - memory_eareg16: - //I286CLOCK(3) - I286CLOCK_X(b, 3, 10) - call p_ea_dst[eax*4] - jmp i286_memorywrite_w - } -} - -I286 lea_r16_ea(void) { // 8D: lea REG16, EA - - __asm { - cmp bh, 0c0h - jnc src_register - //I286CLOCK(3) - I286CLOCK_X(a, 3, 4) - movzx eax, bh - mov ebp, eax - shr ebp, 3-1 - and ebp, 7*2 - call p_lea[eax*4] - mov word ptr I286_REG[ebp], ax - ret - align 16 - src_register: - INT_NUM(6) - } -} - -I286 mov_seg_ea(void) { // 8E: mov segrem, EA - - __asm { - movzx eax, bh - mov ebp, eax - shr ebp, 3-1 - and ebp, 3*2 -#if 1 - cmp ebp, 1*2 - je fixcs -#endif - cmp al, 0c0h - jc src_memory - I286CLOCK(2) - and eax, 7 - mov edi, eax - GET_NEXTPRE2 - mov ax, word ptr I286_REG[edi*2] - jmp segset - align 4 - src_memory: - //I286CLOCK(5) - I286CLOCK_X(b, 5, 11) - call p_ea_dst[eax*4] - call i286_memoryread_w - segset: - mov word ptr I286_SEGREG[ebp], ax - movzx eax, ax - test byte ptr (I286_MSW), MSW_PE - jne short mov_seg_pe - shl eax, 4 // make segreg -mov_seg_base: mov SEG_BASE[ebp*2], eax - sub ebp, 2*2 - jc short segsetr - mov SS_FIX[ebp*2], eax - je short setss - segsetr:ret - - setss: cmp i286core.s.prefix, 0 // 00/05/13 - je noprefix - pop eax - call eax // eax<-offset removeprefix - noprefix: - movzx eax, bl - jmp i286op[eax*4] - -mov_seg_pe: push offset mov_seg_base - jmp i286x_selector - - fixcs: INT_NUM(6) - } -} - -I286 pop_ea(void) { // 8F: pop EA - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 17) - movzx ecx, I286_SP - add ecx, SS_BASE - call i286_memoryread_w - add I286_SP, 2 - mov dx, ax - movzx eax, bh - cmp al, 0c0h - jnc src_register - call p_ea_dst[eax*4] - jmp i286_memorywrite_w - align 16 - src_register: - and eax, 7 - mov word ptr I286_REG[eax*2], dx - GET_NEXTPRE2 - ret - } -} - - -I286 _nop(void) { // 90: nop / bios func - - __asm { - I286CLOCK(3) - GET_NEXTPRE1 -#if 1 - lea ecx, [esi - 1] - add ecx, CS_BASE - cmp ecx, 0f8000h - jc biosend - cmp ecx, 100000h - jnc biosend - mov I286_IP, si - call biosfunc - cmp al, ah - je biosend - movzx esi, I286_IP - movzx eax, I286_ES - shl eax, 4 - mov ES_BASE, eax - movzx eax, I286_CS - shl eax, 4 - mov CS_BASE, eax - movzx eax, I286_SS - shl eax, 4 - mov SS_BASE, eax - mov SS_FIX, eax - movzx eax, I286_DS - shl eax, 4 - mov DS_BASE, eax - mov DS_FIX, eax - RESET_XPREFETCH - biosend: -#endif - ret - } -} - -I286 xchg_ax_cx(void) { // 91: xchg ax, cx - - __asm { - GET_NEXTPRE1 - I286CLOCK(3) - mov ax, I286_AX - xchg ax, I286_CX - mov I286_AX, ax - ret - } -} - -I286 xchg_ax_dx(void) { // 92: xchg ax, dx - - __asm { - GET_NEXTPRE1 - I286CLOCK(3) - mov ax, I286_AX - xchg ax, I286_DX - mov I286_AX, ax - ret - } -} - -I286 xchg_ax_bx(void) { // 93: xchg ax, bx - - __asm { - GET_NEXTPRE1 - I286CLOCK(3) - mov ax, I286_AX - xchg ax, I286_BX - mov I286_AX, ax - ret - } -} - -I286 xchg_ax_sp(void) { // 94: xchg ax, sp - - __asm { - GET_NEXTPRE1 - I286CLOCK(3) - mov ax, I286_AX - xchg ax, I286_SP - mov I286_AX, ax - ret - } -} - -I286 xchg_ax_bp(void) { // 95: xchg ax, bp - - __asm { - GET_NEXTPRE1 - I286CLOCK(3) - mov ax, I286_AX - xchg ax, I286_BP - mov I286_AX, ax - ret - } -} - -I286 xchg_ax_si(void) { // 96: xchg ax, si - - __asm { - GET_NEXTPRE1 - I286CLOCK(3) - mov ax, I286_AX - xchg ax, I286_SI - mov I286_AX, ax - ret - } -} - -I286 xchg_ax_di(void) { // 97: xchg ax, di - - __asm { - GET_NEXTPRE1 - I286CLOCK(3) - mov ax, I286_AX - xchg ax, I286_DI - mov I286_AX, ax - ret - } -} - -I286 _cbw(void) { // 98: cbw - - __asm { - GET_NEXTPRE1 - I286CLOCK(2) - test I286_AL, 80h - setz I286_AH - dec I286_AH - ret - } -} - -I286 _cwd(void) { // 99: cwd - - __asm { - GET_NEXTPRE1 - I286CLOCK(2) - mov ax, 80h - test I286_AH, al - setz al - dec ax - mov I286_DX, ax - ret - } -} - -I286 call_far(void) { // 9A: call far - - __asm { - GET_NEXTPRE1 - //I286CLOCK(13) - I286CLOCK_X(a, 13, (21+4)) - mov edi, SS_BASE - movzx ebp, I286_SP - mov dx, I286_CS - sub bp, 2 - lea ecx, [edi + ebp] - call i286_memorywrite_w - sub bp, 2 - lea ecx, [edi + ebp] - lea edx, [esi + 4] - call i286_memorywrite_w - mov I286_SP, bp - mov si, bx - shr ebx, 16 - mov I286_CS, bx - test byte ptr (I286_MSW), MSW_PE - jne short call_far_pe - shl ebx, 4 - mov CS_BASE, ebx -call_far_base: RESET_XPREFETCH - ret - -call_far_pe: mov eax, ebx - call i286x_selector - mov CS_BASE, eax - jmp short call_far_base - } -} - -I286 _wait(void) { // 9B: wait - - __asm { - GET_NEXTPRE1 - ret - } -} - -I286 _pushf(void) { // 9C: pushf - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - mov dx, I286_FLAG - and dx, 0fffh // 286 - sub I286_SP, 2 - movzx ecx, I286_SP - add ecx, SS_BASE - jmp i286_memorywrite_w - } -} - -I286 _popf(void) { // 9D: popf - - __asm { - GET_NEXTPRE1 - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - movzx ecx, I286_SP - add ecx, SS_BASE - call i286_memoryread_w - add I286_SP, 2 - and ax, 0fffh // 286 - mov I286_FLAG, ax -#if defined(VAEG_FIX) - and ah, 1 - cmp ah, 1 -#else - and ah, 3 - cmp ah, 3 -#endif - sete I286_TRAP - - je irqcheck // fast_intr - test ah, 2 - je nextop - mov al, pic.pi[0 * (type _PICITEM)].imr - mov ah, pic.pi[1 * (type _PICITEM)].imr - not ax - test al, pic.pi[0 * (type _PICITEM)].irr - jne irqcheck - test ah, pic.pi[1 * (type _PICITEM)].irr - jne irqcheck -nextop: ret - -irqcheck: I286IRQCHECKTERM - } -} - -I286 _sahf(void) { // 9E: sahf - - __asm { - GET_NEXTPRE1 - //I286CLOCK(2) - I286CLOCK_X(a, 2, 3) - mov al, I286_AH - and ax, 0fffh // 286 - mov I286_FLAGL, al - ret - } -} - -I286 _lahf(void) { // 9F: lahf - - __asm { - GET_NEXTPRE1 - I286CLOCK(2) - mov al, I286_FLAGL - and ax, 0fffh // 286 - mov I286_AH, al - ret - } -} - - -I286 mov_al_m8(void) { // A0: mov al, m8 - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 10) - mov ecx, ebx - shr ecx, 8 - and ecx, 0ffffh - add ecx, DS_FIX - call i286_memoryread - mov I286_AL, al - GET_NEXTPRE3 - ret - } -} - -I286 mov_ax_m16(void) { // A1: mov ax, m16 - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 10) - mov ecx, ebx - shr ecx, 8 - and ecx, 0ffffh - add ecx, DS_FIX - call i286_memoryread_w - mov I286_AX, ax - GET_NEXTPRE3 - ret - - } -} - -I286 mov_m8_al(void) { // A2: mov m8, al - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 9) - mov edi, ebx - shr edi, 8 - and edi, 0ffffh - add edi, DS_FIX - GET_NEXTPRE3 - mov ecx, edi - mov dl, I286_AL - jmp i286_memorywrite - } -} - -I286 mov_m16_ax(void) { // A3: mov m16, ax - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 9) - mov edi, ebx - shr edi, 8 - and edi, 0ffffh - add edi, DS_FIX - GET_NEXTPRE3 - mov ecx, edi - mov dx, I286_AX - jmp i286_memorywrite_w - } -} - -I286 _movsb(void) { // A4: movsb - - __asm { - GET_NEXTPRE1 - //I286CLOCK(5) - I286CLOCK_X(a, 5, 11) - movzx ecx, I286_SI - add ecx, DS_FIX - call i286_memoryread - mov dl, al - movzx ecx, I286_DI - add ecx, ES_BASE - STRING_DIR - add I286_SI, ax - add I286_DI, ax - jmp i286_memorywrite - } -} - -I286 _movsw(void) { // A5: movsw - - __asm { - GET_NEXTPRE1 - //I286CLOCK(5) - I286CLOCK_X(a, 5, 11) - movzx ecx, I286_SI - add ecx, DS_FIX - call i286_memoryread_w - mov dx, ax - movzx ecx, I286_DI - add ecx, ES_BASE - STRING_DIRx2 - add I286_SI, ax - add I286_DI, ax - jmp i286_memorywrite_w - } -} - -I286 _cmpsb(void) { // A6: cmpsb - - __asm { - GET_NEXTPRE1 - //I286CLOCK(8) - I286CLOCK_X(a, 8, 13) - movzx ecx, I286_SI - add ecx, DS_FIX - call i286_memoryread - mov dl, al - movzx ecx, I286_DI - add ecx, ES_BASE - call i286_memoryread - cmp dl, al - FLAG_STORE_OF - STRING_DIR - add I286_SI, ax - add I286_DI, ax - ret - } -} - -I286 _cmpsw(void) { // A7: cmpsw - - __asm { - GET_NEXTPRE1 - //I286CLOCK(8) - I286CLOCK_X(a, 8, 13) - movzx ecx, I286_SI - add ecx, DS_FIX - call i286_memoryread_w - mov edx, eax - movzx ecx, I286_DI - add ecx, ES_BASE - call i286_memoryread_w - cmp dx, ax - FLAG_STORE_OF - STRING_DIRx2 - add I286_SI, ax - add I286_DI, ax - ret - } -} - -I286 test_al_data8(void) { // A8: test al, DATA8 - - __asm { - I286CLOCK(3) - test I286_AL, bh - FLAG_STORE0 - GET_NEXTPRE2 - ret - } -} - -I286 test_ax_data16(void) { // A9: test ax, DATA16 - - __asm { - I286CLOCK(3) - GET_NEXTPRE3a - test I286_AX, bx - FLAG_STORE0 - GET_NEXTPRE3b - ret - } -} - -I286 _stosb(void) { // AA: stosb - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 7) - movzx ecx, I286_DI - add ecx, ES_BASE - STRING_DIR - add I286_DI, ax - mov dl, I286_AL - jmp i286_memorywrite - } -} - -I286 _stosw(void) { // AB: stosw - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 7) - movzx ecx, I286_DI - add ecx, ES_BASE - STRING_DIRx2 - add I286_DI, ax - mov dx, I286_AX - jmp i286_memorywrite_w - } -} - -I286 _lodsb(void) { // AC: lodsb - - __asm { - GET_NEXTPRE1 - //I286CLOCK(5) - I286CLOCK_X(a, 5, 7) - movzx ecx, I286_SI - add ecx, DS_FIX - call i286_memoryread - mov I286_AL, al - STRING_DIR - add I286_SI, ax - ret - } -} - -I286 _lodsw(void) { // AD: lodsw - - __asm { - GET_NEXTPRE1 - //I286CLOCK(5) - I286CLOCK_X(a, 5, 7) - movzx ecx, I286_SI - add ecx, DS_FIX - call i286_memoryread_w - mov I286_AX, ax - STRING_DIRx2 - add I286_SI, ax - ret - } -} - -I286 _scasb(void) { // AE: scasb - - __asm { - GET_NEXTPRE1 - //I286CLOCK(7) - I286CLOCK_X(a, 7, 7) - movzx ecx, I286_DI - add ecx, ES_BASE - call i286_memoryread - cmp I286_AL, al - FLAG_STORE_OF - STRING_DIR - add I286_DI, ax - ret - } -} - -I286 _scasw(void) { // AF: scasw - - __asm { - GET_NEXTPRE1 - //I286CLOCK(7) - I286CLOCK_X(a, 7, 7) - movzx ecx, I286_DI - add ecx, ES_BASE - call i286_memoryread_w - cmp I286_AX, ax - FLAG_STORE_OF - STRING_DIRx2 - add I286_DI, ax - ret - } -} - - -I286 mov_al_imm(void) { // B0: mov al, imm8 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - mov I286_AL, bh - GET_NEXTPRE2 - ret - } -} - -I286 mov_cl_imm(void) { // B1: mov cl, imm8 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - mov I286_CL, bh - GET_NEXTPRE2 - ret - } -} - -I286 mov_dl_imm(void) { // B2: mov dl, imm8 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - mov I286_DL, bh - GET_NEXTPRE2 - ret - } -} - -I286 mov_bl_imm(void) { // B3: mov bl, imm8 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - mov I286_BL, bh - GET_NEXTPRE2 - ret - } -} - -I286 mov_ah_imm(void) { // B4: mov ah, imm8 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - mov I286_AH, bh - GET_NEXTPRE2 - ret - } -} - -I286 mov_ch_imm(void) { // B5: mov ch, imm8 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - mov I286_CH, bh - GET_NEXTPRE2 - ret - } -} - -I286 mov_dh_imm(void) { // B6: mov dh, imm8 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - mov I286_DH, bh - GET_NEXTPRE2 - ret - } -} - -I286 mov_bh_imm(void) { // B7: mov bh, imm8 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - mov I286_BH, bh - GET_NEXTPRE2 - ret - } -} - -I286 mov_ax_imm(void) { // B8: mov ax, imm16 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - GET_NEXTPRE3a - mov I286_AX, bx - GET_NEXTPRE3b - ret - } -} - -I286 mov_cx_imm(void) { // B9: mov cx, imm16 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - GET_NEXTPRE3a - mov I286_CX, bx - GET_NEXTPRE3b - ret - } -} - -I286 mov_dx_imm(void) { // BA: mov dx, imm16 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - GET_NEXTPRE3a - mov I286_DX, bx - GET_NEXTPRE3b - ret - } -} - -I286 mov_bx_imm(void) { // BB: mov bx, imm16 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - GET_NEXTPRE3a - mov I286_BX, bx - GET_NEXTPRE3b - ret - } -} - -I286 mov_sp_imm(void) { // BC: mov sp, imm16 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - GET_NEXTPRE3a - mov I286_SP, bx - GET_NEXTPRE3b - ret - } -} - -I286 mov_bp_imm(void) { // BD: mov bp, imm16 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - GET_NEXTPRE3a - mov I286_BP, bx - GET_NEXTPRE3b - ret - } -} - -I286 mov_si_imm(void) { // BE: mov si, imm16 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - GET_NEXTPRE3a - mov I286_SI, bx - GET_NEXTPRE3b - ret - } -} - -I286 mov_di_imm(void) { // BF: mov di, imm16 - - __asm { - //I286CLOCK(2) - I286CLOCK_X(a, 2, 4) - GET_NEXTPRE3a - mov I286_DI, bx - GET_NEXTPRE3b - ret - } -} - -I286 shift_ea8_data8(void) { // C0: shift EA8, DATA8 - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 // opcode - cmp al, 0c0h - jc memory_eareg8 - I286CLOCK(5) - bt ax, 2 - rcl eax, 1 - and eax, 7 - lea edx, I286_REG[eax] - mov ecx, ebx - shr ecx, 16 - and ecx, 31 - I286CLOCK(ecx) - push ecx - GET_NEXTPRE3 - pop ecx - jmp sftreg8cl_xtable[edi] - align 16 - memory_eareg8: - I286CLOCK(8) - call p_ea_dst[eax*4] - cmp ecx, I286_MEMWRITEMAX - jnc extmem_eareg8 - lea edx, I286_MEM[ecx] - mov ecx, ebx - and ecx, 31 - I286CLOCK(ecx) - push ecx - GET_NEXTPRE1 - pop ecx - jmp sftreg8cl_xtable[edi] - align 16 - extmem_eareg8: - call i286_memoryread - mov ebp, ecx - mov edx, eax - mov ecx, ebx - and ecx, 31 - I286CLOCK(ecx) - push ecx - GET_NEXTPRE1 - pop ecx - jmp sftext8cl_xtable[edi] - } -} - -I286 shift_ea16_data8(void) { // C1: shift EA16, DATA8 - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 // opcode - cmp al, 0c0h - jc memory_eareg16 - and eax, 7 - I286CLOCK(5) - lea edx, I286_REG[eax*2] - mov ecx, ebx - shr ecx, 16 - and ecx, 31 - I286CLOCK(ecx) - push ecx - GET_NEXTPRE3 - pop ecx - jmp sftreg16cl_xtable[edi] - align 16 - memory_eareg16: - I286CLOCK(8) - call p_ea_dst[eax*4] - cmp ecx, (I286_MEMWRITEMAX-1) - jnc extmem_eareg16 - lea edx, I286_MEM[ecx] - mov ecx, ebx - and ecx, 31 - I286CLOCK(ecx) - push ecx - GET_NEXTPRE1 - pop ecx - jmp sftreg16cl_xtable[edi] - align 16 - extmem_eareg16: - call i286_memoryread_w - mov ebp, ecx - mov edx, eax - mov ecx, ebx - and ecx, 31 - I286CLOCK(ecx) - push ecx - GET_NEXTPRE1 - pop ecx - jmp sftext16cl_xtable[edi] - } -} - -I286 ret_near_data16(void) { // C2: ret near DATA16 - - __asm { - //I286CLOCK(11) - I286CLOCK_X(a, 11, (20+4)) - shr ebx, 8 - add ebx, 2 - movzx ecx, I286_SP - add ecx, SS_BASE - add I286_SP, bx - call i286_memoryread_w - mov si, ax - RESET_XPREFETCH - ret - } -} - -I286 ret_near(void) { // C3: ret near - - __asm { - //I286CLOCK(11) - I286CLOCK_X(a, 11, (15+4)) - REGPOP(si) - RESET_XPREFETCH - ret - } -} - -I286 les_r16_ea(void) { // C4: les REG16, EA - - __asm { - cmp bh, 0c0h - jnc src_register - //I286CLOCK(3) - I286CLOCK_X(a, 3, 18) - movzx eax, bh - push eax - call p_get_ea[eax*4] - lea ecx, [edi + ebp] - call i286_memoryread_w - add bp, 2 - pop edx - shr edx, 3-1 - and edx, 7*2 - mov word ptr I286_REG[edx], ax - lea ecx, [edi + ebp] - call i286_memoryread_w - mov I286_ES, ax - movzx eax, ax - test byte ptr (I286_MSW), MSW_PE - jne short les_pe - shl eax, 4 // make segreg -les_base: mov ES_BASE, eax - ret - -les_pe: push offset les_base - jmp i286x_selector - -src_register: INT_NUM(6) - } -} - -I286 lds_r16_ea(void) { // C5: lds REG16, EA - - __asm { - cmp bh, 0c0h - jnc src_register - //I286CLOCK(3) - I286CLOCK_X(a, 3, 18) - movzx eax, bh - push eax - call p_get_ea[eax*4] - lea ecx, [edi + ebp] - call i286_memoryread_w - add bp, 2 - pop edx - shr edx, 3-1 - and edx, 7*2 - mov word ptr I286_REG[edx], ax - lea ecx, [edi + ebp] - call i286_memoryread_w - mov I286_DS, ax - movzx eax, ax - test byte ptr (I286_MSW), MSW_PE - jne short lds_pe - shl eax, 4 // make segreg -lds_base: mov DS_BASE, eax - mov DS_FIX, eax - ret - -lds_pe: push offset lds_base - jmp i286x_selector - -src_register: INT_NUM(6) - - } -} - -I286 mov_ea8_data8(void) { // C6: mov EA8, DATA8 - - __asm { - cmp bh, 0c0h - jc memory_eareg8 - I286CLOCK(2) - mov edx, ebx - shr edx, 8 - mov bp, dx - bt bp, 2 - rcl ebp, 1 - and ebp, 7 - GET_NEXTPRE2 - mov byte ptr I286_REG[ebp], dh - ret - align 16 - memory_eareg8: - //I286CLOCK(3) - I286CLOCK_X(b, 3, 11) - movzx eax, bh - call p_get_ea[eax*4] - mov dl, bl - GET_NEXTPRE1 - lea ecx, [edi + ebp] - jmp i286_memorywrite - } -} - -I286 mov_ea16_data16(void) { // C7: mov EA16, DATA16 - - __asm { - cmp bh, 0c0h - jc memory_eareg8 - I286CLOCK(2) - movzx ebp, bh - and ebp, 7 - mov edx, ebx - shr edx, 16 - GET_NEXTPRE4 - mov word ptr I286_REG[ebp*2], dx - ret - align 16 - memory_eareg8: - //I286CLOCK(3) - I286CLOCK_X(b, 3, 11) - movzx eax, bh - call p_get_ea[eax*4] - mov dx, bx - GET_NEXTPRE2 - lea ecx, [edi + ebp] - jmp i286_memorywrite_w - } -} - -I286 _enter(void) { // C8: enter DATA16, DATA8 - - __asm { - mov edi, SS_BASE - movzx ebp, I286_SP - sub bp, 2 - lea ecx, [edi + ebp] - mov dx, I286_BP - call i286_memorywrite_w - - shld eax, ebx, 8 - shr ebx, 8 - and eax, 1fh - je enter0 - dec eax - je enter1 - lea ecx, [eax*4 + 12] - I286CLOCK(ecx) // ToDo: V30 - push ebx - movzx ebx, I286_BP - mov I286_BP, bp - enter_lp: - push eax - sub bx, 2 - lea ecx, [edi + ebx] - call i286_memoryread_w - mov edx, eax - sub bp, 2 - lea ecx, [edi + ebp] - call i286_memorywrite_w - pop eax - dec eax - jne enter_lp - pop ebx - sub bp, 2 - lea ecx, [edi + ebp] - mov dx, I286_BP - sub bp, bx - mov I286_SP, bp - push ecx - GET_NEXTPRE4 - pop ecx - jmp i286_memorywrite_w - - align 16 - enter1: - I286CLOCK(15) - mov dx, bp - sub bp, 2 - lea ecx, [edi + ebp] - mov I286_BP, dx - sub bp, bx - mov I286_SP, bp - push ecx - GET_NEXTPRE4 - pop ecx - jmp i286_memorywrite_w - - align 16 - enter0: - I286CLOCK(11) - mov I286_BP, bp - sub bp, bx - mov I286_SP, bp - GET_NEXTPRE4 - ret - } -} - -I286 leave(void) { // C9: leave - - __asm { - GET_NEXTPRE1 - I286CLOCK(5) // ToDo: V30 - mov ax, I286_BP - mov I286_SP, ax - REGPOP(I286_BP) - ret - } -} - -I286 ret_far_data16(void) { // CA: ret far DATA16 - - __asm { - //I286CLOCK(15) - I286CLOCK_X(a, 15, (24+4)) - shr ebx, 8 - mov edi, SS_BASE - movzx ebp, I286_SP - add I286_SP, bx - lea ecx, [edi + ebp] - add bp, 2 - call i286_memoryread_w - mov si, ax - lea ecx, [edi + ebp] - call i286_memoryread_w - mov I286_CS, ax - movzx eax, ax - test byte ptr (I286_MSW), MSW_PE - jne short ret_far16_pe - shl eax, 4 // make segreg -ret_far16_base: mov CS_BASE, eax - add I286_SP, 4 - RESET_XPREFETCH - ret - -ret_far16_pe: push offset ret_far16_base - jmp i286x_selector - } -} - -I286 ret_far(void) { // CB: ret far - - __asm { - //I286CLOCK(15) - I286CLOCK_X(a, 15, (21+4)) - mov edi, SS_BASE - movzx ebx, I286_SP - lea ecx, [edi + ebx] - add bx, 2 - call i286_memoryread_w - mov si, ax - lea ecx, [edi + ebx] - add bx, 2 - call i286_memoryread_w - mov I286_CS, ax - movzx eax, ax - test byte ptr (I286_MSW), MSW_PE - jne short ret_far_pe - shl eax, 4 // make segreg -ret_far_base: mov CS_BASE, eax - mov ebp, eax - mov I286_SP, bx - RESET_XPREFETCH - ret - -ret_far_pe: push offset ret_far_base - jmp i286x_selector - } -} - -I286 int_03(void) { // CC: int 3 - - __asm { - //I286CLOCK(23) - I286CLOCK_X(a, 23, (38+4)) - inc si - INT_NUM(3) - } -} - - -I286 int_data8(void) { // CD: int DATA8 - - __asm { - //I286CLOCK(23) - I286CLOCK_X(a, 23, (38+4)) - mov edi, SS_BASE - movzx ebp, I286_SP - sub bp, 2 - mov dx, I286_FLAG - and I286_FLAG, not (T_FLAG or I_FLAG) - mov I286_TRAP, 0 - lea ecx, [edi + ebp] - call i286_memorywrite_w - sub bp, 2 - lea ecx, [edi + ebp] - mov dx, I286_CS - call i286_memorywrite_w -#if defined(ENABLE_TRAP) - movzx eax, bh - push eax - lea edx, [esi - 1] - movzx ecx, I286_CS - call softinttrap -#endif - movzx eax, bh - sub bp, 2 - mov I286_SP, bp - lea edx, [esi + 2] - mov eax, dword ptr I286_MEM[eax*4] - mov si, ax - shr eax, 16 - mov I286_CS, ax - shl eax, 4 // make segreg - mov CS_BASE, eax - RESET_XPREFETCH - lea ecx, [edi + ebp] - jmp i286_memorywrite_w - } -} - -I286 _into(void) { // CE: into - - __asm { - I286CLOCK(4) - test I286_FLAG, O_FLAG - jne intovf - GET_NEXTPRE1 - ret - - intovf: inc si // ver0.80 - INT_NUM(4) - } -} - -I286 _iret(void) { // CF: iret - // V30用はV30PATCH.CPPに別途作成(Shinra) - __asm { - I286CLOCK(31) - mov edi, SS_BASE - movzx ebx, I286_SP - lea ecx, [edi + ebx] - add bx, 2 - call i286_memoryread_w - mov si, ax - lea ecx, [edi + ebx] - add bx, 2 - call i286_memoryread_w - mov I286_CS, ax - and eax, 0000ffffh - shl eax, 4 // make segreg - mov CS_BASE, eax - lea ecx, [edi + ebx] - add bx, 2 - call i286_memoryread_w - mov I286_SP, bx - and ah, 0fh - mov I286_FLAG, ax -#if defined(VAEG_FIX) - and ah, 1 - cmp ah, 1 -#else - and ah, 3 - cmp ah, 3 -#endif - sete I286_TRAP - RESET_XPREFETCH - - cmp I286_TRAP, 0 // fast_intr - jne irqcheck - test I286_FLAG, I_FLAG - je nextop - mov al, pic.pi[0 * (type _PICITEM)].imr - mov ah, pic.pi[1 * (type _PICITEM)].imr - not ax - test al, pic.pi[0 * (type _PICITEM)].irr - jne irqcheck - test ah, pic.pi[1 * (type _PICITEM)].irr - jne irqcheck -nextop: ret - -irqcheck: I286IRQCHECKTERM - } -} - - -I286 shift_ea8_1(void) { // D0: shift EA8, 1 - - __asm { - movzx edx, bh - mov edi, edx - shr edi, 3-2 - and edi, 7*4 // opcode - cmp bh, 0c0h - jc memory_eareg8 - bt dx, 2 - rcl edx, 1 - and edx, 7 - I286CLOCK(2) - GET_NEXTPRE2 - jmp sftreg8_xtable[edi] - align 16 - memory_eareg8: - I286CLOCK(7) - call p_ea_dst[edx*4] - cmp ecx, I286_MEMWRITEMAX - jnc extmem_eareg8 - jmp sftmem8_xtable[edi] - align 16 - extmem_eareg8: - call i286_memoryread - mov edx, eax - jmp sftext8_xtable[edi] - } -} - -I286 shift_ea16_1(void) { // D1: shift EA16, 1 - - __asm { - movzx edx, bh - mov edi, edx - shr edi, 3-2 - and edi, 7*4 // opcode - cmp bh, 0c0h - jc memory_eareg16 - I286CLOCK(2) - and edx, 7 - GET_NEXTPRE2 - jmp sftreg16_xtable[edi] - align 16 - memory_eareg16: - I286CLOCK(7) - call p_ea_dst[edx*4] - cmp ecx, (I286_MEMWRITEMAX-1) - jnc extmem_eareg16 - jmp sftmem16_xtable[edi] - align 16 - extmem_eareg16: - call i286_memoryread_w - mov edx, eax - jmp sftext16_xtable[edi] - } -} - -I286 shift_ea8_cl(void) { // D2: shift EA8, cl - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 // opcode - cmp al, 0c0h - jc memory_eareg8 - I286CLOCK(5) - bt ax, 2 - rcl eax, 1 - and eax, 7 - lea edx, I286_REG[eax] - GET_NEXTPRE2 - movzx ecx, I286_CL - and ecx, 31 - I286CLOCK(ecx) - jmp sftreg8cl_xtable[edi] - align 16 - memory_eareg8: - I286CLOCK(8) - call p_ea_dst[eax*4] - cmp ecx, I286_MEMWRITEMAX - jnc extmem_eareg8 - lea edx, I286_MEM[ecx] - movzx ecx, I286_CL - and ecx, 31 - I286CLOCK(ecx) - jmp sftreg8cl_xtable[edi] - align 16 - extmem_eareg8: - call i286_memoryread - mov edx, eax - mov ebp, ecx - movzx ecx, I286_CL - and ecx, 31 - I286CLOCK(ecx) - jmp sftext8cl_xtable[edi] - } -} - -I286 shift_ea16_cl(void) { // D3: shift EA16, cl - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 // opcode - cmp al, 0c0h - jc memory_eareg16 - I286CLOCK(5) - and eax, 7 - lea edx, I286_REG[eax*2] - GET_NEXTPRE2 - movzx ecx, I286_CL - and ecx, 31 - I286CLOCK(ecx) - jmp sftreg16cl_xtable[edi] - align 16 - memory_eareg16: - I286CLOCK(8) - call p_ea_dst[eax*4] - cmp ecx, (I286_MEMWRITEMAX-1) - jnc extmem_eareg16 - lea edx, I286_MEM[ecx] - movzx ecx, I286_CL - and ecx, 31 - I286CLOCK(ecx) - jmp sftreg16cl_xtable[edi] - align 16 - extmem_eareg16: - call i286_memoryread_w - mov edx, eax - mov ebp, ecx - movzx ecx, I286_CL - and ecx, 31 - I286CLOCK(ecx) - jmp sftext16cl_xtable[edi] - } -} - -I286 _aam(void) { // D4: AAM - - __asm { // todo: flag !!! - cmp bh, 0 - je div0 - I286CLOCK(16) - movzx eax, I286_AL - div bh - xchg al, ah - mov I286_AX, ax - and I286_FLAGL, not (S_FLAG or Z_FLAG or P_FLAG) - mov dh, ah - and dh, S_FLAG - test ax, ax - jne short nzflagsed - or dh, Z_FLAG -nzflagsed: xor al, ah - and eax, 00ffh - mov al, iflags[eax] - and al, P_FLAG - or al, dh - or I286_FLAGL, al - GET_NEXTPRE2 - ret - - div0: INT_NUM(0) - } -} - -I286 _aad(void) { // D5: AAD - - __asm { // todo: flag !!! - I286CLOCK(14) - mov al, I286_AH - mul bh - add al, I286_AL - mov ah, 0 - mov I286_AX, ax - and I286_FLAGL, not (S_FLAG or Z_FLAG or P_FLAG) - and eax, 00ffh - mov al, iflags[eax] - and al, P_FLAG or Z_FLAG - or I286_FLAGL, al - GET_NEXTPRE2 - ret - } -} - -I286 _setalc(void) { // D6: setalc(80286) - - __asm { - setnc I286_AL - dec I286_AL - GET_NEXTPRE1 - ret - } -} - -I286 _xlat(void) { // D7: xlat - - __asm { - I286CLOCK(5) - movzx ecx, I286_AL - add cx, I286_BX - add ecx, DS_FIX - call i286_memoryread - mov I286_AL, al - GET_NEXTPRE1 - ret - } -} - -I286 _esc(void) { // D8-DF: esc - - __asm { - cmp bh, 0c0h - jnc ea_reg8 - movzx eax, bh - jmp p_lea[eax*4] - align 16 - ea_reg8: - GET_NEXTPRE2 - ret - } -} - - -I286 _loopnz(void) { // E0: loopnz - - __asm { - dec I286_CX - je loopend - test I286_FLAG, Z_FLAG - jne loopend - //I286CLOCK(8) - I286CLOCK_X(a, 8, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - align 16 -loopend: //I286CLOCK(4) - I286CLOCK_X(b, 4, 5) - GET_NEXTPRE2 - ret - } -} - -I286 _loopz(void) { // E1: loopz - - __asm { - dec I286_CX - je loopend - test I286_FLAG, Z_FLAG - je loopend - //I286CLOCK(8) - I286CLOCK_X(a, 8, (14+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - align 16 -loopend: I286CLOCK(4) - GET_NEXTPRE2 - ret - } -} - -I286 _loop(void) { // E2: loop - - __asm { - dec I286_CX - je loopend - //I286CLOCK(8) - I286CLOCK_X(a, 8, (13 + 4)) // V30は13clock+4clock(命令読み込み時間分) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - align 16 -loopend: //I286CLOCK(4) - I286CLOCK_X(b, 4, 5) - GET_NEXTPRE2 - ret - } -} - -I286 _jcxz(void) { // E3: jcxz - - __asm { - cmp I286_CX, 0 - jne loopend - //I286CLOCK(8) - I286CLOCK_X(a, 8, (13+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - align 16 -loopend: //I286CLOCK(4) - I286CLOCK_X(b, 4, 5) - GET_NEXTPRE2 - ret - } -} - -I286 in_al_data8(void) { // E4: in al, DATA8 - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 9) - lea eax, [esi + 2] - add eax, CS_BASE - mov I286_INPADRS, eax - movzx ecx, bh - call iocore_inp8 - mov I286_AL, al - mov I286_INPADRS, 0 - GET_NEXTPRE2 - ret - } -} - -I286 in_ax_data8(void) { // E5: in ax, DATA8 - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 9) - lea eax, [esi + 2] - add eax, CS_BASE - movzx ecx, bh - call iocore_inp16 - mov I286_AX, ax - GET_NEXTPRE2 - ret - } -} - -I286 out_data8_al(void) { // E6: out DATA8, al - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - movzx ecx, bh - push ecx - GET_NEXTPRE2 - pop ecx - mov dl, I286_AL - jmp iocore_out8 - } -} - -I286 out_data8_ax(void) { // E7: out DATA8, ax - - __asm { - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - movzx ecx, bh - push ecx - GET_NEXTPRE2 - pop ecx - mov dx, I286_AX - jmp iocore_out16 - } -} - -I286 call_near(void) { // E8: call near - - __asm { - //I286CLOCK(7) - I286CLOCK_X(a, 7, (16+4)) - shr ebx, 8 - add si, 3 - mov dx, si - add si, bx - RESET_XPREFETCH - sub I286_SP, 2 - movzx ecx, I286_SP - add ecx, SS_BASE - jmp i286_memorywrite_w - } -} - -I286 jmp_near(void) { // E9: jmp near - - __asm { - //I286CLOCK(7) - I286CLOCK_X(a, 7, (13+4)) - shr ebx, 8 - add si, 3 - add si, bx - RESET_XPREFETCH - ret - } -} - -I286 jmp_far(void) { // EA: jmp far - - __asm { - //I286CLOCK(11) - I286CLOCK_X(a, 11, (15+4)) - GET_NEXTPRE1 - mov si, bx - shr ebx, 16 - mov I286_CS, bx - test byte ptr (I286_MSW), MSW_PE - jne short jmp_far_pe - shl ebx, 4 // make segreg - mov CS_BASE, ebx -jmp_far_base: RESET_XPREFETCH - ret - -jmp_far_pe: mov eax, ebx - call i286x_selector - mov CS_BASE, eax - jmp short jmp_far_base - } -} - -I286 jmp_short(void) { // EB: jmp short - - __asm { - //I286CLOCK(7) - I286CLOCK_X(a, 7, (12+4)) - movsx eax, bh - add si, ax - add si, 2 - RESET_XPREFETCH - ret - } -} - -I286 in_al_dx(void) { // EC: in al, dx - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - movzx ecx, I286_DX - call iocore_inp8 - mov I286_AL, al - GET_NEXTPRE1 - ret - } -} - -I286 in_ax_dx(void) { // ED: in ax, dx - - __asm { - //I286CLOCK(5) - I286CLOCK_X(a, 5, 8) - movzx ecx, I286_DX - call iocore_inp16 - mov I286_AX, ax - GET_NEXTPRE1 - ret - } -} - -I286 out_dx_al(void) { // EE: out dx, al - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - movzx ecx, I286_DX - mov dl, I286_AL - jmp iocore_out8 - } -} - -I286 out_dx_ax(void) { // EF: out dx, ax - - __asm { - GET_NEXTPRE1 - //I286CLOCK(3) - I286CLOCK_X(a, 3, 8) - movzx ecx, I286_DX - mov dx, I286_AX - jmp iocore_out16 - } -} - -I286 _lock(void) { // F0: lock - - __asm { - GET_NEXTPRE1 - ret - } -} - -I286 _repne(void) { // F2: repne - - __asm { - I286PREFIX(i286op_repne) - } -} - -I286 _repe(void) { // F3: repe - - __asm { - I286PREFIX(i286op_repe) - } -} - -I286 _hlt(void) { // F4: hlt - - __asm { - mov I286_REMCLOCK, -1 - ret - } -} - -I286 _cmc(void) { // F5: cmc - - __asm { - I286CLOCK(2) - xor I286_FLAG, C_FLAG - GET_NEXTPRE1 - ret - } -} - -I286 _ope0xf6(void) { // F6: - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 - jmp ope0xf6_xtable[edi] - } -} - -I286 _ope0xf7(void) { // F7: - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 - jmp ope0xf7_xtable[edi] - } -} - -I286 _clc(void) { // F8: clc - - __asm { - GET_NEXTPRE1 - I286CLOCK(2) - and I286_FLAG, not C_FLAG - ret - } -} - -I286 _stc(void) { // F9: stc - - __asm { - GET_NEXTPRE1 - I286CLOCK(2) - or I286_FLAG, C_FLAG - ret - } -} - -I286 _cli(void) { // FA: cli - - __asm { - GET_NEXTPRE1 - I286CLOCK(2) - and I286_FLAG, not I_FLAG -#if defined(VAEG_FIX) - // シングルステップ割り込みは割り込み許可フラグの影響を受けない -#else - mov I286_TRAP, 0 -#endif - ret - } -} - -I286 _sti(void) { // FB: sti - - __asm { - GET_NEXTPRE1 - I286CLOCK(2) - cmp i286core.s.prefix, 0 // ver0.26 00/10/08 - jne prefix_exist // 前方分岐ジャンプなので。 - noprefix: - movzx ebp, bl - bts I286_FLAG, 9 - jne jmp_nextop -#if defined(VAEG_FIX) - // シングルステップ割り込みは割り込み許可フラグの影響を受けない -#else - test I286_FLAG, T_FLAG - setne I286_TRAP -#endif - - jne nextopandexit // fast_intr - mov al, pic.pi[0 * (type _PICITEM)].imr - mov ah, pic.pi[1 * (type _PICITEM)].imr - not ax - test al, pic.pi[0 * (type _PICITEM)].irr - jne nextopandexit - test ah, pic.pi[1 * (type _PICITEM)].irr - jne nextopandexit -jmp_nextop: jmp i286op[ebp*4] - -nextopandexit: call i286op[ebp*4] - I286IRQCHECKTERM - -prefix_exist: pop eax // eax<-offset removeprefix - call eax - jmp noprefix - } -} - -I286 _cld(void) { // FC: cld - - __asm { - GET_NEXTPRE1 - I286CLOCK(2) - and I286_FLAG, not D_FLAG - ret - } -} - -I286 _std(void) { // FD: std - - __asm { - GET_NEXTPRE1 - I286CLOCK(2) - or I286_FLAG, D_FLAG - ret - } -} - -I286 _ope0xfe(void) { // FE: - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 1*4 - jmp ope0xfe_xtable[edi] - } -} - -I286 _ope0xff(void) { // FF: - - __asm { - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 - jmp ope0xff_xtable[edi] - } -} - - -// ------------------------------------------------------------------------- - -const I286TBL i286op[256] = { - add_ea_r8, // 00: add EA, REG8 - add_ea_r16, // 01: add EA, REG16 - add_r8_ea, // 02: add REG8, EA - add_r16_ea, // 03: add REG16, EA - add_al_data8, // 04: add al, DATA8 - add_ax_data16, // 05: add ax, DATA16 - push_es, // 06: push es - pop_es, // 07: pop es - or_ea_r8, // 08: or EA, REGF8 - or_ea_r16, // 09: or EA, REG16 - or_r8_ea, // 0A: or REG8, EA - or_r16_ea, // 0B: or REG16, EA - or_al_data8, // 0C: or al, DATA8 - or_ax_data16, // 0D: or ax, DATA16 - push_cs, // 0E: push cs - _xcts, // 0F: i286 upper opcode - - adc_ea_r8, // 10: adc EA, REG8 - adc_ea_r16, // 11: adc EA, REG16 - adc_r8_ea, // 12: adc REG8, EA - adc_r16_ea, // 13: adc REG16, EA - adc_al_data8, // 14: adc al, DATA8 - adc_ax_data16, // 15: adc ax, DATA16 - push_ss, // 16: push ss - pop_ss, // 17: pop ss - sbb_ea_r8, // 18: sbb EA, REG8 - sbb_ea_r16, // 19: sbb EA, REG16 - sbb_r8_ea, // 1A: sbb REG8, EA - sbb_r16_ea, // 1B: sbb REG16, EA - sbb_al_data8, // 1C: sbb al, DATA8 - sbb_ax_data16, // 1D: sbb ax, DATA16 - push_ds, // 1E: push ds - pop_ds, // 1F: pop ds - - and_ea_r8, // 20: and EA, REG8 - and_ea_r16, // 21: and EA, REG16 - and_r8_ea, // 22: and REG8, EA - and_r16_ea, // 23: and REG16, EA - and_al_data8, // 24: and al, DATA8 - and_ax_data16, // 25: and ax, DATA16 - segprefix_es, // 26: es: - _daa, // 27: daa - sub_ea_r8, // 28: sub EA, REG8 - sub_ea_r16, // 29: sub EA, REG16 - sub_r8_ea, // 2A: sub REG8, EA - sub_r16_ea, // 2B: sub REG16, EA - sub_al_data8, // 2C: sub al, DATA8 - sub_ax_data16, // 2D: sub ax, DATA16 - segprefix_cs, // 2E: cs: - _das, // 2F: das - - xor_ea_r8, // 30: xor EA, REG8 - xor_ea_r16, // 31: xor EA, REG16 - xor_r8_ea, // 32: xor REG8, EA - xor_r16_ea, // 33: xor REG16, EA - xor_al_data8, // 34: xor al, DATA8 - xor_ax_data16, // 35: xor ax, DATA16 - segprefix_ss, // 36: ss: - _aaa, // 37: aaa - cmp_ea_r8, // 38: cmp EA, REG8 - cmp_ea_r16, // 39: cmp EA, REG16 - cmp_r8_ea, // 3A: cmp REG8, EA - cmp_r16_ea, // 3B: cmp REG16, EA - cmp_al_data8, // 3C: cmp al, DATA8 - cmp_ax_data16, // 3D: cmp ax, DATA16 - segprefix_ds, // 3E: ds: - _aas, // 3F: aas - - inc_ax, // 40: inc ax - inc_cx, // 41: inc cx - inc_dx, // 42: inc dx - inc_bx, // 43: inc bx - inc_sp, // 44: inc sp - inc_bp, // 45: inc bp - inc_si, // 46: inc si - inc_di, // 47: inc di - dec_ax, // 48: dec ax - dec_cx, // 49: dec cx - dec_dx, // 4A: dec dx - dec_bx, // 4B: dec bx - dec_sp, // 4C: dec sp - dec_bp, // 4D: dec bp - dec_si, // 4E: dec si - dec_di, // 4F: dec di - - push_ax, // 50: push ax - push_cx, // 51: push cx - push_dx, // 52: push dx - push_bx, // 53: push bx - push_sp, // 54: push sp - push_bp, // 55: push bp - push_si, // 56: push si - push_di, // 57: push di - pop_ax, // 58: pop ax - pop_cx, // 59: pop cx - pop_dx, // 5A: pop dx - pop_bx, // 5B: pop bx - pop_sp, // 5C: pop sp - pop_bp, // 5D: pop bp - pop_si, // 5E: pop si - pop_di, // 5F: pop di - - _pusha, // 60: pusha - _popa, // 61: popa - _bound, // 62: bound - _arpl, // 63: arpl - _reserved, // 64: reserved - _reserved, // 65: reserved - _reserved, // 66: reserved - _reserved, // 67: reserved - push_data16, // 68: push DATA16 - imul_reg_ea_data16, // 69: imul REG, EA, DATA16 - push_data8, // 6A: push DATA8 - imul_reg_ea_data8, // 6B: imul REG, EA, DATA8 - _insb, // 6C: insb - _insw, // 6D: insw - _outsb, // 6E: outsb - _outsw, // 6F: outsw - - jo_short, // 70: jo short - jno_short, // 71: jno short - jc_short, // 72: jnae/jb/jc short - jnc_short, // 73: jae/jnb/jnc short - jz_short, // 74: je/jz short - jnz_short, // 75: jne/jnz short - jna_short, // 76: jna/jbe short - ja_short, // 77: ja/jnbe short - js_short, // 78: js short - jns_short, // 79: jns short - jp_short, // 7A: jp/jpe short - jnp_short, // 7B: jnp/jpo short - jl_short, // 7C: jl/jnge short - jnl_short, // 7D: jnl/jge short - jle_short, // 7E: jle/jng short - jnle_short, // 7F: jg/jnle short - - calc_ea8_i8, // 80: op EA8, DATA8 - calc_ea16_i16, // 81: op EA16, DATA16 - calc_ea8_i8, // 82: op EA8, DATA8 - calc_ea16_i8, // 83: op EA16, DATA8 - test_ea_r8, // 84: test EA, REG8 - test_ea_r16, // 85: test EA, REG16 - xchg_ea_r8, // 86: xchg EA, REG8 - xchg_ea_r16, // 87: xchg EA, REG16 - mov_ea_r8, // 88: mov EA, REG8 - mov_ea_r16, // 89: mov EA, REG16 - mov_r8_ea, // 8A: mov REG8, EA - mov_r16_ea, // 8B: add REG16, EA - mov_ea_seg, // 8C: mov EA, segreg - lea_r16_ea, // 8D: lea REG16, EA - mov_seg_ea, // 8E: mov segrem, EA - pop_ea, // 8F: pop EA - - _nop, // 90: xchg ax, ax - xchg_ax_cx, // 91: xchg ax, cx - xchg_ax_dx, // 92: xchg ax, dx - xchg_ax_bx, // 93: xchg ax, bx - xchg_ax_sp, // 94: xchg ax, sp - xchg_ax_bp, // 95: xchg ax, bp - xchg_ax_si, // 96: xchg ax, si - xchg_ax_di, // 97: xchg ax, di - _cbw, // 98: cbw - _cwd, // 99: cwd - call_far, // 9A: call far - _wait, // 9B: wait - _pushf, // 9C: pushf - _popf, // 9D: popf - _sahf, // 9E: sahf - _lahf, // 9F: lahf - - mov_al_m8, // A0: mov al, m8 - mov_ax_m16, // A1: mov ax, m16 - mov_m8_al, // A2: mov m8, al - mov_m16_ax, // A3: mov m16, ax - _movsb, // A4: movsb - _movsw, // A5: movsw - _cmpsb, // A6: cmpsb - _cmpsw, // A7: cmpsw - test_al_data8, // A8: test al, DATA8 - test_ax_data16, // A9: test ax, DATA16 - _stosb, // AA: stosw - _stosw, // AB: stosw - _lodsb, // AC: lodsb - _lodsw, // AD: lodsw - _scasb, // AE: scasb - _scasw, // AF: scasw - - mov_al_imm, // B0: mov al, imm8 - mov_cl_imm, // B1: mov cl, imm8 - mov_dl_imm, // B2: mov dl, imm8 - mov_bl_imm, // B3: mov bl, imm8 - mov_ah_imm, // B4: mov ah, imm8 - mov_ch_imm, // B5: mov ch, imm8 - mov_dh_imm, // B6: mov dh, imm8 - mov_bh_imm, // B7: mov bh, imm8 - mov_ax_imm, // B8: mov ax, imm16 - mov_cx_imm, // B9: mov cx, imm16 - mov_dx_imm, // BA: mov dx, imm16 - mov_bx_imm, // BB: mov bx, imm16 - mov_sp_imm, // BC: mov sp, imm16 - mov_bp_imm, // BD: mov bp, imm16 - mov_si_imm, // BE: mov si, imm16 - mov_di_imm, // BF: mov di, imm16 - - shift_ea8_data8, // C0: shift EA8, DATA8 - shift_ea16_data8, // C1: shift EA16, DATA8 - ret_near_data16, // C2: ret near DATA16 - ret_near, // C3: ret near - les_r16_ea, // C4: les REG16, EA - lds_r16_ea, // C5: lds REG16, EA - mov_ea8_data8, // C6: mov EA8, DATA8 - mov_ea16_data16, // C7: mov EA16, DATA16 - _enter, // C8: enter DATA16, DATA8 - leave, // C9: leave - ret_far_data16, // CA: ret far DATA16 - ret_far, // CB: ret far - int_03, // CC: int 3 - int_data8, // CD: int DATA8 - _into, // CE: into - _iret, // CF: iret - - shift_ea8_1, // D0: shift EA8, 1 - shift_ea16_1, // D1: shift EA16, 1 - shift_ea8_cl, // D2: shift EA8, cl - shift_ea16_cl, // D3: shift EA16, cl - _aam, // D4: AAM - _aad, // D5: AAD - _setalc, // D6: setalc (80286) - _xlat, // D7: xlat - _esc, // D8: esc - _esc, // D9: esc - _esc, // DA: esc - _esc, // DB: esc - _esc, // DC: esc - _esc, // DD: esc - _esc, // DE: esc - _esc, // DF: esc - - _loopnz, // E0: loopnz - _loopz, // E1: loopz - _loop, // E2: loop - _jcxz, // E3: jcxz - in_al_data8, // E4: in al, DATA8 - in_ax_data8, // E5: in ax, DATA8 - out_data8_al, // E6: out DATA8, al - out_data8_ax, // E7: out DATA8, ax - call_near, // E8: call near - jmp_near, // E9: jmp near - jmp_far, // EA: jmp far - jmp_short, // EB: jmp short - in_al_dx, // EC: in al, dx - in_ax_dx, // ED: in ax, dx - out_dx_al, // EE: out dx, al - out_dx_ax, // EF: out dx, ax - - _lock, // F0: lock - _lock, // F1: lock - _repne, // F2: repne - _repe, // F3: repe - _hlt, // F4: hlt - _cmc, // F5: cmc - _ope0xf6, // F6: - _ope0xf7, // F7: - _clc, // F8: clc - _stc, // F9: stc - _cli, // FA: cli - _sti, // FB: sti - _cld, // FC: cld - _std, // FD: std - _ope0xfe, // FE: - _ope0xff, // FF: -}; - -// ----------------------------------------------------------------- repe - -I286 repe_segprefix_es(void) { - - __asm { - mov eax, ES_BASE - mov DS_FIX, eax - mov SS_FIX, eax - GET_NEXTPRE1 - movzx eax, bl - jmp i286op_repe[eax*4] - } -} - -I286 repe_segprefix_cs(void) { - - __asm { - mov eax, CS_BASE - mov DS_FIX, eax - mov SS_FIX, eax - GET_NEXTPRE1 - movzx eax, bl - jmp i286op_repe[eax*4] - } -} - -I286 repe_segprefix_ss(void) { - - __asm { - mov eax, SS_BASE - mov DS_FIX, eax - mov SS_FIX, eax - GET_NEXTPRE1 - movzx eax, bl - jmp i286op_repe[eax*4] - } -} - -I286 repe_segprefix_ds(void) { - - __asm { - mov eax, DS_BASE - mov DS_FIX, eax - mov SS_FIX, eax - GET_NEXTPRE1 - movzx eax, bl - jmp i286op_repe[eax*4] - } -} - -const I286TBL i286op_repe[256] = { - add_ea_r8, // 00: add EA, REG8 - add_ea_r16, // 01: add EA, REG16 - add_r8_ea, // 02: add REG8, EA - add_r16_ea, // 03: add REG16, EA - add_al_data8, // 04: add al, DATA8 - add_ax_data16, // 05: add ax, DATA16 - push_es, // 06: push es - pop_es, // 07: pop es - or_ea_r8, // 08: or EA, REGF8 - or_ea_r16, // 09: or EA, REG16 - or_r8_ea, // 0A: or REG8, EA - or_r16_ea, // 0B: or REG16, EA - or_al_data8, // 0C: or al, DATA8 - or_ax_data16, // 0D: or ax, DATA16 - push_cs, // 0E: push cs - _xcts, // 0F: i286 upper opcode - - adc_ea_r8, // 10: adc EA, REG8 - adc_ea_r16, // 11: adc EA, REG16 - adc_r8_ea, // 12: adc REG8, EA - adc_r16_ea, // 13: adc REG16, EA - adc_al_data8, // 14: adc al, DATA8 - adc_ax_data16, // 15: adc ax, DATA16 - push_ss, // 16: push ss - pop_ss, // 17: pop ss - sbb_ea_r8, // 18: sbb EA, REG8 - sbb_ea_r16, // 19: sbb EA, REG16 - sbb_r8_ea, // 1A: sbb REG8, EA - sbb_r16_ea, // 1B: sbb REG16, EA - sbb_al_data8, // 1C: sbb al, DATA8 - sbb_ax_data16, // 1D: sbb ax, DATA16 - push_ds, // 1E: push ds - pop_ds, // 1F: pop ds - - and_ea_r8, // 20: and EA, REG8 - and_ea_r16, // 21: and EA, REG16 - and_r8_ea, // 22: and REG8, EA - and_r16_ea, // 23: and REG16, EA - and_al_data8, // 24: and al, DATA8 - and_ax_data16, // 25: and ax, DATA16 - repe_segprefix_es, // 26: repe es: - _daa, // 27: daa - sub_ea_r8, // 28: sub EA, REG8 - sub_ea_r16, // 29: sub EA, REG16 - sub_r8_ea, // 2A: sub REG8, EA - sub_r16_ea, // 2B: sub REG16, EA - sub_al_data8, // 2C: sub al, DATA8 - sub_ax_data16, // 2D: sub ax, DATA16 - repe_segprefix_cs, // 2E: repe cs: - _das, // 2F: das - - xor_ea_r8, // 30: xor EA, REG8 - xor_ea_r16, // 31: xor EA, REG16 - xor_r8_ea, // 32: xor REG8, EA - xor_r16_ea, // 33: xor REG16, EA - xor_al_data8, // 34: xor al, DATA8 - xor_ax_data16, // 35: xor ax, DATA16 - repe_segprefix_ss, // 36: repe ss: - _aaa, // 37: aaa - cmp_ea_r8, // 38: cmp EA, REG8 - cmp_ea_r16, // 39: cmp EA, REG16 - cmp_r8_ea, // 3A: cmp REG8, EA - cmp_r16_ea, // 3B: cmp REG16, EA - cmp_al_data8, // 3C: cmp al, DATA8 - cmp_ax_data16, // 3D: cmp ax, DATA16 - repe_segprefix_ds, // 3E: repe ds: - _aas, // 3F: aas - - inc_ax, // 40: inc ax - inc_cx, // 41: inc cx - inc_dx, // 42: inc dx - inc_bx, // 43: inc bx - inc_sp, // 44: inc sp - inc_bp, // 45: inc bp - inc_si, // 46: inc si - inc_di, // 47: inc di - dec_ax, // 48: dec ax - dec_cx, // 49: dec cx - dec_dx, // 4A: dec dx - dec_bx, // 4B: dec bx - dec_sp, // 4C: dec sp - dec_bp, // 4D: dec bp - dec_si, // 4E: dec si - dec_di, // 4F: dec di - - push_ax, // 50: push ax - push_cx, // 51: push cx - push_dx, // 52: push dx - push_bx, // 53: push bx - push_sp, // 54: push sp - push_bp, // 55: push bp - push_si, // 56: push si - push_di, // 57: push di - pop_ax, // 58: pop ax - pop_cx, // 59: pop cx - pop_dx, // 5A: pop dx - pop_bx, // 5B: pop bx - pop_sp, // 5C: pop sp - pop_bp, // 5D: pop bp - pop_si, // 5E: pop si - pop_di, // 5F: pop di - - _pusha, // 60: pusha - _popa, // 61: popa - _bound, // 62: bound - _arpl, // 63: arpl - _reserved, // 64: reserved - _reserved, // 65: reserved - _reserved, // 66: reserved - _reserved, // 67: reserved - push_data16, // 68: push DATA16 - imul_reg_ea_data16, // 69: imul REG, EA, DATA16 - push_data8, // 6A: push DATA8 - imul_reg_ea_data8, // 6B: imul REG, EA, DATA8 - rep_xinsb, // 6C: rep insb - rep_xinsw, // 6D: rep insw - rep_xoutsb, // 6E: rep outsb - rep_xoutsw, // 6F: rep outsw - - jo_short, // 70: jo short - jno_short, // 71: jno short - jc_short, // 72: jnae/jb/jc short - jnc_short, // 73: jae/jnb/jnc short - jz_short, // 74: je/jz short - jnz_short, // 75: jne/jnz short - jna_short, // 76: jna/jbe short - ja_short, // 77: ja/jnbe short - js_short, // 78: js short - jns_short, // 79: jns short - jp_short, // 7A: jp/jpe short - jnp_short, // 7B: jnp/jpo short - jl_short, // 7C: jl/jnge short - jnl_short, // 7D: jnl/jge short - jle_short, // 7E: jle/jng short - jnle_short, // 7F: jg/jnle short - - calc_ea8_i8, // 80: op EA8, DATA8 - calc_ea16_i16, // 81: op EA16, DATA16 - calc_ea8_i8, // 82: op EA8, DATA8 - calc_ea16_i8, // 83: op EA16, DATA8 - test_ea_r8, // 84: test EA, REG8 - test_ea_r16, // 85: test EA, REG16 - xchg_ea_r8, // 86: xchg EA, REG8 - xchg_ea_r16, // 87: xchg EA, REG16 - mov_ea_r8, // 88: mov EA, REG8 - mov_ea_r16, // 89: mov EA, REG16 - mov_r8_ea, // 8A: mov REG8, EA - mov_r16_ea, // 8B: add REG16, EA - mov_ea_seg, // 8C: mov EA, segreg - lea_r16_ea, // 8D: lea REG16, EA - mov_seg_ea, // 8E: mov segrem, EA - pop_ea, // 8F: pop EA - - _nop, // 90: xchg ax, ax - xchg_ax_cx, // 91: xchg ax, cx - xchg_ax_dx, // 92: xchg ax, dx - xchg_ax_bx, // 93: xchg ax, bx - xchg_ax_sp, // 94: xchg ax, sp - xchg_ax_bp, // 95: xchg ax, bp - xchg_ax_si, // 96: xchg ax, si - xchg_ax_di, // 97: xchg ax, di - _cbw, // 98: cbw - _cwd, // 99: cwd - call_far, // 9A: call far - _wait, // 9B: wait - _pushf, // 9C: pushf - _popf, // 9D: popf - _sahf, // 9E: sahf - _lahf, // 9F: lahf - - mov_al_m8, // A0: mov al, m8 - mov_ax_m16, // A1: mov ax, m16 - mov_m8_al, // A2: mov m8, al - mov_m16_ax, // A3: mov m16, ax - rep_xmovsb, // A4: rep movsb - rep_xmovsw, // A5: rep movsw - repe_xcmpsb, // A6: repe cmpsb - repe_xcmpsw, // A7: repe cmpsw - test_al_data8, // A8: test al, DATA8 - test_ax_data16, // A9: test ax, DATA16 - rep_xstosb, // AA: rep stosw - rep_xstosw, // AB: rep stosw - rep_xlodsb, // AC: rep lodsb - rep_xlodsw, // AD: rep lodsw - repe_xscasb, // AE: repe scasb - repe_xscasw, // AF: repe scasw - - mov_al_imm, // B0: mov al, imm8 - mov_cl_imm, // B1: mov cl, imm8 - mov_dl_imm, // B2: mov dl, imm8 - mov_bl_imm, // B3: mov bl, imm8 - mov_ah_imm, // B4: mov ah, imm8 - mov_ch_imm, // B5: mov ch, imm8 - mov_dh_imm, // B6: mov dh, imm8 - mov_bh_imm, // B7: mov bh, imm8 - mov_ax_imm, // B8: mov ax, imm16 - mov_cx_imm, // B9: mov cx, imm16 - mov_dx_imm, // BA: mov dx, imm16 - mov_bx_imm, // BB: mov bx, imm16 - mov_sp_imm, // BC: mov sp, imm16 - mov_bp_imm, // BD: mov bp, imm16 - mov_si_imm, // BE: mov si, imm16 - mov_di_imm, // BF: mov di, imm16 - - shift_ea8_data8, // C0: shift EA8, DATA8 - shift_ea16_data8, // C1: shift EA16, DATA8 - ret_near_data16, // C2: ret near DATA16 - ret_near, // C3: ret near - les_r16_ea, // C4: les REG16, EA - lds_r16_ea, // C5: lds REG16, EA - mov_ea8_data8, // C6: mov EA8, DATA8 - mov_ea16_data16, // C7: mov EA16, DATA16 - _enter, // C8: enter DATA16, DATA8 - leave, // C9: leave - ret_far_data16, // CA: ret far DATA16 - ret_far, // CB: ret far - int_03, // CC: int 3 - int_data8, // CD: int DATA8 - _into, // CE: into - _iret, // CF: iret - - shift_ea8_1, // D0: shift EA8, 1 - shift_ea16_1, // D1: shift EA16, 1 - shift_ea8_cl, // D2: shift EA8, cl - shift_ea16_cl, // D3: shift EA16, cl - _aam, // D4: AAM - _aad, // D5: AAD - _setalc, // D6: setalc (80286) - _xlat, // D7: xlat - _esc, // D8: esc - _esc, // D9: esc - _esc, // DA: esc - _esc, // DB: esc - _esc, // DC: esc - _esc, // DD: esc - _esc, // DE: esc - _esc, // DF: esc - - _loopnz, // E0: loopnz - _loopz, // E1: loopz - _loop, // E2: loop - _jcxz, // E3: jcxz - in_al_data8, // E4: in al, DATA8 - in_ax_data8, // E5: in ax, DATA8 - out_data8_al, // E6: out DATA8, al - out_data8_ax, // E7: out DATA8, ax - call_near, // E8: call near - jmp_near, // E9: jmp near - jmp_far, // EA: jmp far - jmp_short, // EB: jmp short - in_al_dx, // EC: in al, dx - in_ax_dx, // ED: in ax, dx - out_dx_al, // EE: out dx, al - out_dx_ax, // EF: out dx, ax - - _lock, // F0: lock - _lock, // F1: lock - _repne, // F2: repne - _repe, // F3: repe - _hlt, // F4: hlt - _cmc, // F5: cmc - _ope0xf6, // F6: - _ope0xf7, // F7: - _clc, // F8: clc - _stc, // F9: stc - _cli, // FA: cli - _sti, // FB: sti - _cld, // FC: cld - _std, // FD: std - _ope0xfe, // FE: - _ope0xff, // FF: -}; - -// ----------------------------------------------------------------- repne - -I286 repne_segprefix_es(void) { - - __asm { - mov eax, ES_BASE - mov DS_FIX, eax - mov SS_FIX, eax - GET_NEXTPRE1 - movzx eax, bl - jmp i286op_repne[eax*4] - } -} - -I286 repne_segprefix_cs(void) { - - __asm { - mov eax, CS_BASE - mov DS_FIX, eax - mov SS_FIX, eax - GET_NEXTPRE1 - movzx eax, bl - jmp i286op_repne[eax*4] - } -} - -I286 repne_segprefix_ss(void) { - - __asm { - mov eax, SS_BASE - mov DS_FIX, eax - mov SS_FIX, eax - GET_NEXTPRE1 - movzx eax, bl - jmp i286op_repne[eax*4] - } -} - -I286 repne_segprefix_ds(void) { - - __asm { - mov eax, DS_BASE - mov DS_FIX, eax - mov SS_FIX, eax - GET_NEXTPRE1 - movzx eax, bl - jmp i286op_repne[eax*4] - } -} - -const I286TBL i286op_repne[256] = { - add_ea_r8, // 00: add EA, REG8 - add_ea_r16, // 01: add EA, REG16 - add_r8_ea, // 02: add REG8, EA - add_r16_ea, // 03: add REG16, EA - add_al_data8, // 04: add al, DATA8 - add_ax_data16, // 05: add ax, DATA16 - push_es, // 06: push es - pop_es, // 07: pop es - or_ea_r8, // 08: or EA, REGF8 - or_ea_r16, // 09: or EA, REG16 - or_r8_ea, // 0A: or REG8, EA - or_r16_ea, // 0B: or REG16, EA - or_al_data8, // 0C: or al, DATA8 - or_ax_data16, // 0D: or ax, DATA16 - push_cs, // 0E: push cs - _xcts, // 0F: i286 upper opcode - - adc_ea_r8, // 10: adc EA, REG8 - adc_ea_r16, // 11: adc EA, REG16 - adc_r8_ea, // 12: adc REG8, EA - adc_r16_ea, // 13: adc REG16, EA - adc_al_data8, // 14: adc al, DATA8 - adc_ax_data16, // 15: adc ax, DATA16 - push_ss, // 16: push ss - pop_ss, // 17: pop ss - sbb_ea_r8, // 18: sbb EA, REG8 - sbb_ea_r16, // 19: sbb EA, REG16 - sbb_r8_ea, // 1A: sbb REG8, EA - sbb_r16_ea, // 1B: sbb REG16, EA - sbb_al_data8, // 1C: sbb al, DATA8 - sbb_ax_data16, // 1D: sbb ax, DATA16 - push_ds, // 1E: push ds - pop_ds, // 1F: pop ds - - and_ea_r8, // 20: and EA, REG8 - and_ea_r16, // 21: and EA, REG16 - and_r8_ea, // 22: and REG8, EA - and_r16_ea, // 23: and REG16, EA - and_al_data8, // 24: and al, DATA8 - and_ax_data16, // 25: and ax, DATA16 - repne_segprefix_es, // 26: repne es: - _daa, // 27: daa - sub_ea_r8, // 28: sub EA, REG8 - sub_ea_r16, // 29: sub EA, REG16 - sub_r8_ea, // 2A: sub REG8, EA - sub_r16_ea, // 2B: sub REG16, EA - sub_al_data8, // 2C: sub al, DATA8 - sub_ax_data16, // 2D: sub ax, DATA16 - repne_segprefix_cs, // 2E: repne cs: - _das, // 2F: das - - xor_ea_r8, // 30: xor EA, REG8 - xor_ea_r16, // 31: xor EA, REG16 - xor_r8_ea, // 32: xor REG8, EA - xor_r16_ea, // 33: xor REG16, EA - xor_al_data8, // 34: xor al, DATA8 - xor_ax_data16, // 35: xor ax, DATA16 - repne_segprefix_ss, // 36: repne ss: - _aaa, // 37: aaa - cmp_ea_r8, // 38: cmp EA, REG8 - cmp_ea_r16, // 39: cmp EA, REG16 - cmp_r8_ea, // 3A: cmp REG8, EA - cmp_r16_ea, // 3B: cmp REG16, EA - cmp_al_data8, // 3C: cmp al, DATA8 - cmp_ax_data16, // 3D: cmp ax, DATA16 - repne_segprefix_ds, // 3E: repne ds: - _aas, // 3F: aas - - inc_ax, // 40: inc ax - inc_cx, // 41: inc cx - inc_dx, // 42: inc dx - inc_bx, // 43: inc bx - inc_sp, // 44: inc sp - inc_bp, // 45: inc bp - inc_si, // 46: inc si - inc_di, // 47: inc di - dec_ax, // 48: dec ax - dec_cx, // 49: dec cx - dec_dx, // 4A: dec dx - dec_bx, // 4B: dec bx - dec_sp, // 4C: dec sp - dec_bp, // 4D: dec bp - dec_si, // 4E: dec si - dec_di, // 4F: dec di - - push_ax, // 50: push ax - push_cx, // 51: push cx - push_dx, // 52: push dx - push_bx, // 53: push bx - push_sp, // 54: push sp - push_bp, // 55: push bp - push_si, // 56: push si - push_di, // 57: push di - pop_ax, // 58: pop ax - pop_cx, // 59: pop cx - pop_dx, // 5A: pop dx - pop_bx, // 5B: pop bx - pop_sp, // 5C: pop sp - pop_bp, // 5D: pop bp - pop_si, // 5E: pop si - pop_di, // 5F: pop di - - _pusha, // 60: pusha - _popa, // 61: popa - _bound, // 62: bound - _arpl, // 63: arpl - _reserved, // 64: reserved - _reserved, // 65: reserved - _reserved, // 66: reserved - _reserved, // 67: reserved - push_data16, // 68: push DATA16 - imul_reg_ea_data16, // 69: imul REG, EA, DATA16 - push_data8, // 6A: push DATA8 - imul_reg_ea_data8, // 6B: imul REG, EA, DATA8 - rep_xinsb, // 6C: rep insb - rep_xinsw, // 6D: rep insw - rep_xoutsb, // 6E: rep outsb - rep_xoutsw, // 6F: rep outsw - - jo_short, // 70: jo short - jno_short, // 71: jno short - jc_short, // 72: jnae/jb/jc short - jnc_short, // 73: jae/jnb/jnc short - jz_short, // 74: je/jz short - jnz_short, // 75: jne/jnz short - jna_short, // 76: jna/jbe short - ja_short, // 77: ja/jnbe short - js_short, // 78: js short - jns_short, // 79: jns short - jp_short, // 7A: jp/jpe short - jnp_short, // 7B: jnp/jpo short - jl_short, // 7C: jl/jnge short - jnl_short, // 7D: jnl/jge short - jle_short, // 7E: jle/jng short - jnle_short, // 7F: jg/jnle short - - calc_ea8_i8, // 80: op EA8, DATA8 - calc_ea16_i16, // 81: op EA16, DATA16 - calc_ea8_i8, // 82: op EA8, DATA8 - calc_ea16_i8, // 83: op EA16, DATA8 - test_ea_r8, // 84: test EA, REG8 - test_ea_r16, // 85: test EA, REG16 - xchg_ea_r8, // 86: xchg EA, REG8 - xchg_ea_r16, // 87: xchg EA, REG16 - mov_ea_r8, // 88: mov EA, REG8 - mov_ea_r16, // 89: mov EA, REG16 - mov_r8_ea, // 8A: mov REG8, EA - mov_r16_ea, // 8B: add REG16, EA - mov_ea_seg, // 8C: mov EA, segreg - lea_r16_ea, // 8D: lea REG16, EA - mov_seg_ea, // 8E: mov segrem, EA - pop_ea, // 8F: pop EA - - _nop, // 90: xchg ax, ax - xchg_ax_cx, // 91: xchg ax, cx - xchg_ax_dx, // 92: xchg ax, dx - xchg_ax_bx, // 93: xchg ax, bx - xchg_ax_sp, // 94: xchg ax, sp - xchg_ax_bp, // 95: xchg ax, bp - xchg_ax_si, // 96: xchg ax, si - xchg_ax_di, // 97: xchg ax, di - _cbw, // 98: cbw - _cwd, // 99: cwd - call_far, // 9A: call far - _wait, // 9B: wait - _pushf, // 9C: pushf - _popf, // 9D: popf - _sahf, // 9E: sahf - _lahf, // 9F: lahf - - mov_al_m8, // A0: mov al, m8 - mov_ax_m16, // A1: mov ax, m16 - mov_m8_al, // A2: mov m8, al - mov_m16_ax, // A3: mov m16, ax - rep_xmovsb, // A4: rep movsb - rep_xmovsw, // A5: rep movsw - repne_xcmpsb, // A6: repne cmpsb - repne_xcmpsw, // A7: repne cmpsw - test_al_data8, // A8: test al, DATA8 - test_ax_data16, // A9: test ax, DATA16 - rep_xstosb, // AA: rep stosw - rep_xstosw, // AB: rep stosw - rep_xlodsb, // AC: rep lodsb - rep_xlodsw, // AD: rep lodsw - repne_xscasb, // AE: repne scasb - repne_xscasw, // AF: repne scasw - - mov_al_imm, // B0: mov al, imm8 - mov_cl_imm, // B1: mov cl, imm8 - mov_dl_imm, // B2: mov dl, imm8 - mov_bl_imm, // B3: mov bl, imm8 - mov_ah_imm, // B4: mov ah, imm8 - mov_ch_imm, // B5: mov ch, imm8 - mov_dh_imm, // B6: mov dh, imm8 - mov_bh_imm, // B7: mov bh, imm8 - mov_ax_imm, // B8: mov ax, imm16 - mov_cx_imm, // B9: mov cx, imm16 - mov_dx_imm, // BA: mov dx, imm16 - mov_bx_imm, // BB: mov bx, imm16 - mov_sp_imm, // BC: mov sp, imm16 - mov_bp_imm, // BD: mov bp, imm16 - mov_si_imm, // BE: mov si, imm16 - mov_di_imm, // BF: mov di, imm16 - - shift_ea8_data8, // C0: shift EA8, DATA8 - shift_ea16_data8, // C1: shift EA16, DATA8 - ret_near_data16, // C2: ret near DATA16 - ret_near, // C3: ret near - les_r16_ea, // C4: les REG16, EA - lds_r16_ea, // C5: lds REG16, EA - mov_ea8_data8, // C6: mov EA8, DATA8 - mov_ea16_data16, // C7: mov EA16, DATA16 - _enter, // C8: enter DATA16, DATA8 - leave, // C9: leave - ret_far_data16, // CA: ret far DATA16 - ret_far, // CB: ret far - int_03, // CC: int 3 - int_data8, // CD: int DATA8 - _into, // CE: into - _iret, // CF: iret - - shift_ea8_1, // D0: shift EA8, 1 - shift_ea16_1, // D1: shift EA16, 1 - shift_ea8_cl, // D2: shift EA8, cl - shift_ea16_cl, // D3: shift EA16, cl - _aam, // D4: AAM - _aad, // D5: AAD - _setalc, // D6: setalc (80286) - _xlat, // D7: xlat - _esc, // D8: esc - _esc, // D9: esc - _esc, // DA: esc - _esc, // DB: esc - _esc, // DC: esc - _esc, // DD: esc - _esc, // DE: esc - _esc, // DF: esc - - _loopnz, // E0: loopnz - _loopz, // E1: loopz - _loop, // E2: loop - _jcxz, // E3: jcxz - in_al_data8, // E4: in al, DATA8 - in_ax_data8, // E5: in ax, DATA8 - out_data8_al, // E6: out DATA8, al - out_data8_ax, // E7: out DATA8, ax - call_near, // E8: call near - jmp_near, // E9: jmp near - jmp_far, // EA: jmp far - jmp_short, // EB: jmp short - in_al_dx, // EC: in al, dx - in_ax_dx, // ED: in ax, dx - out_dx_al, // EE: out dx, al - out_dx_ax, // EF: out dx, ax - - _lock, // F0: lock - _lock, // F1: lock - _repne, // F2: repne - _repe, // F3: repe - _hlt, // F4: hlt - _cmc, // F5: cmc - _ope0xf6, // F6: - _ope0xf7, // F7: - _clc, // F8: clc - _stc, // F9: stc - _cli, // FA: cli - _sti, // FB: sti - _cld, // FC: cld - _std, // FD: std - _ope0xfe, // FE: - _ope0xff, // FF: -}; - +#include +#include +#include "i286x.h" +#include "i286xadr.h" +#include "i286xs.h" +#include "i286xrep.h" +#include "i286xcts.h" +#include +#include +#include "i286x.mcr" +#include "i286xea.mcr" +#include "v30patch.h" +#include +#include "dmap.h" +#if defined(ENABLE_TRAP) +#include "trap/inttrap.h" +#include "trap/steptrap.h" +#endif + + + I286CORE i286core; + +const UINT8 iflags[256] = { // Z_FLAG, S_FLAG, P_FLAG + 0x44, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84}; + + +void i286x_initialize(void) { + + i286xadr_init(); + if (CPU_TYPE == CPUTYPE_V30) { + v30xinit(); + } +} + +void i286x_deinitialize(void) { + + if (CPU_EXTMEM) { + _MFREE(CPU_EXTMEM); + CPU_EXTMEM = NULL; + CPU_EXTMEMSIZE = 0; + } +} + +static void i286x_initreg(void) { + // V30はV30PATCH.CPPに別途用意 + I286_CS = 0xf000; + CS_BASE = 0xf0000; + I286_IP = 0xfff0; + i286core.s.adrsmask = 0xfffff; + i286x_resetprefetch(); +} + +#if defined(VAEG_FIX) +void i286x_reset(void) { + ZeroMemory(&i286core.s, sizeof(i286core.s)); + if (CPU_TYPE == CPUTYPE_V30) { + v30x_initreg(); + } + else { + i286x_initreg(); + } +} +#else +void i286x_reset(void) { + ZeroMemory(&i286core.s, sizeof(i286core.s)); + i286x_initreg(); +} +#endif + +void i286x_shut(void) { + + ZeroMemory(&i286core.s, offsetof(I286STAT, cpu_type)); + i286x_initreg(); +} + +void i286x_setextsize(UINT32 size) { + + if (CPU_EXTMEMSIZE != size) { + if (CPU_EXTMEM) { + _MFREE(CPU_EXTMEM); + CPU_EXTMEM = NULL; + } + if (size) { + CPU_EXTMEM = (UINT8 *)_MALLOC(size + 16, "EXTMEM"); + if (CPU_EXTMEM == NULL) { + size = 0; + } + } + CPU_EXTMEMSIZE = size; + } + i286core.e.ems[0] = mem + 0xc0000; + i286core.e.ems[1] = mem + 0xc4000; + i286core.e.ems[2] = mem + 0xc8000; + i286core.e.ems[3] = mem + 0xcc000; +} + +void i286x_setemm(UINT frame, UINT32 addr) { + + UINT8 *ptr; + + frame &= 3; + if (addr < USE_HIMEM) { + ptr = mem + addr; + } + else if ((addr - 0x100000 + 0x4000) <= CPU_EXTMEMSIZE) { + ptr = CPU_EXTMEM + (addr - 0x100000); + } + else { + ptr = mem + 0xc0000 + (frame << 14); + } + i286core.e.ems[frame] = ptr; +} + + +LABEL void i286x_resetprefetch(void) { + + __asm { + pushad + movzx esi, I286_IP + RESET_XPREFETCH + mov dword ptr (i286core.s.prefetchque), ebx + popad + ret + } +} + +LABEL void __fastcall i286x_interrupt(UINT8 vect) { + + __asm { + pushad + push ecx + + movzx ebx, I286_SP + sub bx, 2 + + // hlt.. + cmp byte ptr (i286core.s.prefetchque), 0f4h // hlt + jne short nonhlt + inc I286_IP +nonhlt: mov edi, SS_BASE + lea ecx, [edi + ebx] + sub bx, 2 + mov dx, I286_FLAG + and dh, 0fh + and I286_FLAG, not (T_FLAG or I_FLAG) + mov I286_TRAP, 0 + call i286_memorywrite_w + lea ecx, [edi + ebx] + sub bx, 2 + mov dx, I286_CS + call i286_memorywrite_w + mov I286_SP, bx + lea ecx, [edi + ebx] + mov dx, I286_IP + call i286_memorywrite_w + pop ecx + + xor eax, eax + mov al, cl + mov eax, dword ptr I286_MEM[eax*4] + + mov I286_IP, ax + movzx esi, ax + shr eax, 16 + mov I286_CS, ax + shl eax, 4 // make segreg + mov CS_BASE, eax + RESET_XPREFETCH + mov dword ptr (i286core.s.prefetchque), ebx + + popad + ret + } +} + + +// I286xルーチンのローカルからの割り込み +LABEL void __fastcall i286x_localint(void) { + + __asm { + push ecx + movzx ebx, I286_SP + sub bx, 2 + + mov edi, SS_BASE + lea ecx, [edi + ebx] + sub bx, 2 + mov dx, I286_FLAG + and dh, 0fh + and I286_FLAG, not (T_FLAG or I_FLAG) + mov I286_TRAP, 0 + call i286_memorywrite_w + lea ecx, [edi + ebx] + sub bx, 2 + mov dx, I286_CS + call i286_memorywrite_w + mov I286_SP, bx + lea ecx, [edi + ebx] + mov dx, si // I286_IP + call i286_memorywrite_w + pop ecx + mov eax, dword ptr I286_MEM[ecx*4] + + mov si, ax + shr eax, 16 + mov I286_CS, ax + shl eax, 4 // make segreg + mov CS_BASE, eax + + RESET_XPREFETCH + ret + } +} + + +// プロテクトモードのセレクタ(in ax / ret eax) +LABEL void __fastcall i286x_selector(void) { + + __asm { + mov ecx, dword ptr (I286_GDTR.base) + test eax, 4 + je short ixsl_1 + mov ecx, dword ptr (I286_LDTRC.base) +ixsl_1: and eax, not 7 + and ecx, 0ffffffh + lea ecx, [ecx + eax + 2] + call i286_memoryread_w + push eax + add ecx, 2 + call i286_memoryread + pop ecx + and eax, 0ffh + movzx ecx, cx + shl eax, 16 + add eax, ecx + ret + } +} + + +LABEL void i286x(void) { + + __asm { + pushad + mov ebx, dword ptr (i286core.s.prefetchque) + movzx esi, I286_IP + + cmp I286_TRAP, 0 + jne short i286_trapping + cmp dmac.working, 0 + jne short i286_dma_mnlp + +i286_mnlp: +#if defined(ENABLE_TRAP) + mov edx, esi + movzx ecx, I286_CS + call steptrap +#endif + movzx eax, bl + call i286op[eax*4] + cmp I286_REMCLOCK, 0 + jg i286_mnlp + mov dword ptr (i286core.s.prefetchque), ebx + mov I286_IP, si + popad + ret + + align 16 +i286_dma_mnlp: +#if defined(ENABLE_TRAP) + mov edx, esi + movzx ecx, I286_CS + call steptrap +#endif + movzx eax, bl + call i286op[eax*4] + call dmap_i286 + cmp I286_REMCLOCK, 0 + jg i286_dma_mnlp + mov dword ptr (i286core.s.prefetchque), ebx + mov I286_IP, si + popad + ret + + align 16 +i286_trapping: +#if defined(ENABLE_TRAP) + mov edx, esi + movzx ecx, I286_CS + call steptrap +#endif + movzx eax, bl + call i286op[eax*4] + cmp I286_TRAP, 0 + je i286notrap + mov ecx, 1 + call i286x_localint +i286notrap: mov dword ptr (i286core.s.prefetchque), ebx + mov I286_IP, si + popad + ret + } +} + + + +LABEL void i286x_step(void) { + + __asm { + pushad + mov ebx, dword ptr (i286core.s.prefetchque) + movzx esi, I286_IP + +#if defined(ENABLE_TRAP) + mov edx, esi + movzx ecx, I286_CS + call steptrap +#endif + + movzx eax, bl + call i286op[eax*4] + + cmp I286_TRAP, 0 + je short nexts + mov ecx, 1 + call i286x_localint +nexts: + mov dword ptr (i286core.s.prefetchque), ebx + mov I286_IP, si + + call dmap_i286 + popad + ret + } +} + + + + +LABEL void removeprefix(void) { + + __asm { + mov i286core.s.prefix, 0 + mov eax, DS_BASE + mov DS_FIX, eax + mov eax, SS_BASE + mov SS_FIX, eax + ret + } +} + + +I286 _reserved(void) { + + __asm { +// inc si // 01/08/31 + INT_NUM(6) + } +} + +// ---- + +I286 add_ea_r8(void) { // 00: add EA, REG8 + + __asm { + PREPART_EA_REG8(2) + add byte ptr I286_REG[eax], dl + FLAG_STORE_OF + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG8(7) + MEMORY_EA_REG8_X(7, 16) + add byte ptr I286_MEM[ecx], dl + FLAG_STORE_OF + ret + EXTMEM_EA_REG8 + add al, byte ptr I286_REG[ebp] + mov dl, al + FLAG_STORE_OF + jmp i286_memorywrite + } +} + +I286 add_ea_r16(void) { // 01: add EA, REG16 + + __asm { + PREPART_EA_REG16(2) + add word ptr I286_REG[eax*2], dx + FLAG_STORE_OF + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG16(7) + MEMORY_EA_REG16_X(7, 16) + add word ptr I286_MEM[ecx], dx + FLAG_STORE_OF + ret + EXTMEM_EA_REG16 + add ax, word ptr I286_REG[ebp] + mov dx, ax + FLAG_STORE_OF + jmp i286_memorywrite_w + } +} + +I286 add_r8_ea(void) { // 02: add REG8, EA + + __asm { + //PREPART_REG8_EA(2, 7) + PREPART_REG8_EA_X(2, 7, 2, 16) + add I286_REG[ebp], al + FLAG_STORE_OF + ret + } +} + +I286 add_r16_ea(void) { // 03: add REG16, EA + + __asm { + //PREPART_REG16_EA(2, 7) + PREPART_REG16_EA_X(2, 7, 2, 16) + add I286_REG[ebp], ax + FLAG_STORE_OF + ret + } +} + +I286 add_al_data8(void) { // 04: add al, DATA8 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + add I286_AL, bh + FLAG_STORE_OF + GET_NEXTPRE2 + ret + } +} + +I286 add_ax_data16(void) { // 05: add ax, DATA16 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE3a + add I286_AX, bx + FLAG_STORE_OF + GET_NEXTPRE3b + ret + } +} + +I286 push_es(void) { // 06: push es + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_ES) + } +} + +I286 pop_es(void) { // 07: pop es + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + REGPOP(I286_ES) + movzx eax, ax + test byte ptr (I286_MSW), MSW_PE + jne short pop_es_pe + shl eax, 4 // make segreg +pop_es_base: mov ES_BASE, eax + GET_NEXTPRE1 + ret + +pop_es_pe: push offset pop_es_base + jmp i286x_selector + } +} + +I286 or_ea_r8(void) { // 08: or EA, REG8 + + __asm { + PREPART_EA_REG8(2) + or byte ptr I286_REG[eax], dl + FLAG_STORE0 + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG8(7) + MEMORY_EA_REG8_X(7, 16) + or byte ptr I286_MEM[ecx], dl + FLAG_STORE0 + ret + EXTMEM_EA_REG8 + or al, byte ptr I286_REG[ebp] + mov dl, al + FLAG_STORE0 + jmp i286_memorywrite + } +} + +I286 or_ea_r16(void) { // 09: or EA, REG16 + + __asm { + PREPART_EA_REG16(2) + or word ptr I286_REG[eax*2], dx + FLAG_STORE0 + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG16(7) + MEMORY_EA_REG16_X(7, 16) + or word ptr I286_MEM[ecx], dx + FLAG_STORE0 + ret + EXTMEM_EA_REG16 + or ax, word ptr I286_REG[ebp] + mov dx, ax + FLAG_STORE0 + jmp i286_memorywrite_w + } +} + +I286 or_r8_ea(void) { // 0A: or REG8, EA + + __asm { + //PREPART_REG8_EA(2, 7) + PREPART_REG8_EA_X(2, 7, 2, 11) + or I286_REG[ebp], al + FLAG_STORE0 + ret + } +} + +I286 or_r16_ea(void) { // 0B: or REG16, EA + + __asm { + //PREPART_REG16_EA(2, 7) + PREPART_REG16_EA_X(2, 7, 2, 11) + or I286_REG[ebp], ax + FLAG_STORE0 + ret + } +} + +I286 or_al_data8(void) { // 0C: or al, DATA8 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + or I286_AL, bh + FLAG_STORE0 + GET_NEXTPRE2 + ret + } +} + +I286 or_ax_data16(void) { // 0D: or ax, DATA16 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE3a + or I286_AX, bx + FLAG_STORE0 + GET_NEXTPRE3b + ret + } +} + +I286 push_cs(void) { // 0E: push es + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_CS) + } +} + + +I286 adc_ea_r8(void) { // 10: adc EA, REG8 + + __asm { + PREPART_EA_REG8(2) + CFLAG_LOAD + adc byte ptr I286_REG[eax], dl + FLAG_STORE_OF + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG8(7) + MEMORY_EA_REG8_X(7, 16) + CFLAG_LOAD + adc byte ptr I286_MEM[ecx], dl + FLAG_STORE_OF + ret + EXTMEM_EA_REG8 + CFLAG_LOAD + adc al, byte ptr I286_REG[ebp] + mov dl, al + FLAG_STORE_OF + jmp i286_memorywrite + } +} + +I286 adc_ea_r16(void) { // 11: adc EA, REG16 + + __asm { + PREPART_EA_REG16(2) + CFLAG_LOAD + adc word ptr I286_REG[eax*2], dx + FLAG_STORE_OF + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG16(7) + MEMORY_EA_REG16_X(7, 16) + CFLAG_LOAD + adc word ptr I286_MEM[ecx], dx + FLAG_STORE_OF + ret + EXTMEM_EA_REG16 + CFLAG_LOAD + adc ax, word ptr I286_REG[ebp] + mov dx, ax + FLAG_STORE_OF + jmp i286_memorywrite_w + } +} + +I286 adc_r8_ea(void) { // 12: adc REG8, EA + + __asm { + //PREPART_REG8_EA(2, 7) + PREPART_REG8_EA_X(2, 7, 2, 11) + CFLAG_LOAD + adc I286_REG[ebp], al + FLAG_STORE_OF + ret + } +} + +I286 adc_r16_ea(void) { // 13: adc REG16, EA + + __asm { + //PREPART_REG16_EA(2, 7) + PREPART_REG16_EA_X(2, 7, 2, 11) + CFLAG_LOAD + adc I286_REG[ebp], ax + FLAG_STORE_OF + ret + } +} + +I286 adc_al_data8(void) { // 14: adc al, DATA8 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + CFLAG_LOAD + adc I286_AL, bh + FLAG_STORE_OF + GET_NEXTPRE2 + ret + } +} + +I286 adc_ax_data16(void) { // 15: adc ax, DATA16 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE3a + CFLAG_LOAD + adc I286_AX, bx + FLAG_STORE_OF + GET_NEXTPRE3b + ret + } +} + +I286 push_ss(void) { // 16: push ss + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_SS) + } +} + +I286 pop_ss(void) { // 17: pop ss + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + REGPOP(I286_SS) + movzx eax, ax + test byte ptr (I286_MSW), MSW_PE + jne short pop_ss_pe + shl eax, 4 // make segreg +pop_ss_base: mov SS_BASE, eax + mov SS_FIX, eax + cmp i286core.s.prefix, 0 // 00/06/24 + jne prefix_exist + noprefix: + movzx ebp, bh + GET_NEXTPRE1 + jmp i286op[ebp*4] + +pop_ss_pe: push offset pop_ss_base + jmp i286x_selector + +prefix_exist: pop eax // eax<-offset removeprefix + call eax + jmp noprefix + } +} + +I286 sbb_ea_r8(void) { // 18: sbb EA, REG8 + + __asm { + PREPART_EA_REG8(2) + CFLAG_LOAD + sbb byte ptr I286_REG[eax], dl + FLAG_STORE_OF + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG8(7) + MEMORY_EA_REG8_X(7, 16) + CFLAG_LOAD + sbb byte ptr I286_MEM[ecx], dl + FLAG_STORE_OF + ret + EXTMEM_EA_REG8 + CFLAG_LOAD + sbb al, byte ptr I286_REG[ebp] + mov dl, al + FLAG_STORE_OF + jmp i286_memorywrite + } +} + +I286 sbb_ea_r16(void) { // 19: sbb EA, REG16 + + __asm { + PREPART_EA_REG16(2) + CFLAG_LOAD + sbb word ptr I286_REG[eax*2], dx + FLAG_STORE_OF + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG16(7) + MEMORY_EA_REG16_X(7, 16) + CFLAG_LOAD + sbb word ptr I286_MEM[ecx], dx + FLAG_STORE_OF + ret + EXTMEM_EA_REG16 + CFLAG_LOAD + sbb ax, word ptr I286_REG[ebp] + mov dx, ax + FLAG_STORE_OF + jmp i286_memorywrite_w + } +} + +I286 sbb_r8_ea(void) { // 1A: sbb REG8, EA + + __asm { + //PREPART_REG8_EA(2, 7) + PREPART_REG8_EA_X(2, 7, 2, 11) + CFLAG_LOAD + sbb I286_REG[ebp], al + FLAG_STORE_OF + ret + } +} + +I286 sbb_r16_ea(void) { // 1B: sbb REG16, EA + + __asm { + //PREPART_REG16_EA(2, 7) + PREPART_REG16_EA_X(2, 7, 2, 11) + CFLAG_LOAD + sbb I286_REG[ebp], ax + FLAG_STORE_OF + ret + } +} + +I286 sbb_al_data8(void) { // 1C: sbb al, DATA8 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + CFLAG_LOAD + sbb I286_AL, bh + FLAG_STORE_OF + GET_NEXTPRE2 + ret + } +} + +I286 sbb_ax_data16(void) { // 1D: sbb ax, DATA16 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE3a + CFLAG_LOAD + sbb I286_AX, bx + FLAG_STORE_OF + GET_NEXTPRE3b + ret + } +} + +I286 push_ds(void) { // 1E: push ds + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_DS) + } +} + +I286 pop_ds(void) { // 1F: pop ds + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + REGPOP(I286_DS) + movzx eax, ax + test byte ptr (I286_MSW), MSW_PE + jne short pop_ds_pe + shl eax, 4 // make segreg +pop_ds_base: mov DS_BASE, eax + mov DS_FIX, eax + GET_NEXTPRE1 + ret + +pop_ds_pe: push offset pop_ds_base + jmp i286x_selector + } +} + +I286 and_ea_r8(void) { // 20: and EA, REG8 + + __asm { + PREPART_EA_REG8(2) + and byte ptr I286_REG[eax], dl + FLAG_STORE0 + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG8(7) + MEMORY_EA_REG8_X(7, 16) + and byte ptr I286_MEM[ecx], dl + FLAG_STORE0 + ret + EXTMEM_EA_REG8 + and al, byte ptr I286_REG[ebp] + mov dl, al + FLAG_STORE0 + jmp i286_memorywrite + } +} + +I286 and_ea_r16(void) { // 21: and EA, REG16 + + __asm { + PREPART_EA_REG16(2) + and word ptr I286_REG[eax*2], dx + FLAG_STORE0 + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG16(7) + MEMORY_EA_REG16_X(7, 16) + and word ptr I286_MEM[ecx], dx + FLAG_STORE0 + ret + EXTMEM_EA_REG16 + and ax, word ptr I286_REG[ebp] + mov dx, ax + FLAG_STORE0 + jmp i286_memorywrite_w + } +} + +I286 and_r8_ea(void) { // 22: and REG8, EA + + __asm { + //PREPART_REG8_EA(2, 7) + PREPART_REG8_EA_X(2, 7, 2, 11) + and I286_REG[ebp], al + FLAG_STORE0 + ret + } +} + +I286 and_r16_ea(void) { // 23: and REG16, EA + + __asm { + //PREPART_REG16_EA(2, 7) + PREPART_REG16_EA_X(2, 7, 2, 11) + and I286_REG[ebp], ax + FLAG_STORE0 + ret + } +} + +I286 and_al_data8(void) { // 24: and al, DATA8 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + and I286_AL, bh + FLAG_STORE0 + GET_NEXTPRE2 + ret + } +} + +I286 and_ax_data16(void) { // 25: and ax, DATA16 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE3a + and I286_AX, bx + FLAG_STORE0 + GET_NEXTPRE3b + ret + } +} + +I286 segprefix_es(void) { // 26: es: + + __asm { + mov eax, ES_BASE + mov DS_FIX, eax + mov SS_FIX, eax + I286PREFIX(i286op) + } +} + +I286 _daa(void) { // 27: daa + + __asm { + I286CLOCK(3) + FLAG_LOAD + mov ax, I286_AX + daa + mov I286_AX, ax + FLAG_STORE + GET_NEXTPRE1 + ret + } +} + +I286 sub_ea_r8(void) { // 28: sub EA, REG8 + + __asm { + PREPART_EA_REG8(2) + sub byte ptr I286_REG[eax], dl + FLAG_STORE_OF + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG8(7) + MEMORY_EA_REG8_X(7, 16) + sub byte ptr I286_MEM[ecx], dl + FLAG_STORE_OF + ret + EXTMEM_EA_REG8 + sub al, byte ptr I286_REG[ebp] + mov dl, al + FLAG_STORE_OF + jmp i286_memorywrite + } +} + +I286 sub_ea_r16(void) { // 29: sub EA, REG16 + + __asm { + PREPART_EA_REG16(2) + sub word ptr I286_REG[eax*2], dx + FLAG_STORE_OF + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG16(7) + MEMORY_EA_REG16_X(7, 16) + sub word ptr I286_MEM[ecx], dx + FLAG_STORE_OF + ret + EXTMEM_EA_REG16 + sub ax, word ptr I286_REG[ebp] + mov dx, ax + FLAG_STORE_OF + jmp i286_memorywrite_w + } +} + +I286 sub_r8_ea(void) { // 2A: sub REG8, EA + + __asm { + //PREPART_REG8_EA(2, 7) + PREPART_REG8_EA_X(2, 7, 2, 11) + sub I286_REG[ebp], al + FLAG_STORE_OF + ret + } +} + +I286 sub_r16_ea(void) { // 2B: sub REG16, EA + + __asm { + //PREPART_REG16_EA(2, 7) + PREPART_REG16_EA_X(2, 7, 2, 11) + sub I286_REG[ebp], ax + FLAG_STORE_OF + ret + } +} + +I286 sub_al_data8(void) { // 2C: sub al, DATA8 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + sub I286_AL, bh + FLAG_STORE_OF + GET_NEXTPRE2 + ret + } +} + +I286 sub_ax_data16(void) { // 2D: sub ax, DATA16 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE3a + sub I286_AX, bx + FLAG_STORE_OF + GET_NEXTPRE3b + ret + } +} + +I286 segprefix_cs(void) { // 2E: cs: + + __asm { + mov eax, CS_BASE + mov DS_FIX, eax + mov SS_FIX, eax + I286PREFIX(i286op) + } +} + +I286 _das(void) { // 2F: das + + __asm { + I286CLOCK(3) + FLAG_LOAD + mov ax, I286_AX + das + mov I286_AX, ax + FLAG_STORE + GET_NEXTPRE1 + ret + } +} + + +I286 xor_ea_r8(void) { // 30: xor EA, REG8 + + __asm { + PREPART_EA_REG8(2) + xor byte ptr I286_REG[eax], dl + FLAG_STORE0 + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG8(7) + MEMORY_EA_REG8_X(7, 16) + xor byte ptr I286_MEM[ecx], dl + FLAG_STORE0 + ret + EXTMEM_EA_REG8 + xor al, byte ptr I286_REG[ebp] + mov dl, al + FLAG_STORE0 + jmp i286_memorywrite + } +} + +I286 xor_ea_r16(void) { // 31: xor EA, REG16 + + __asm { + PREPART_EA_REG16(2) + xor word ptr I286_REG[eax*2], dx + FLAG_STORE0 + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG16(7) + MEMORY_EA_REG16_X(7, 16) + xor word ptr I286_MEM[ecx], dx + FLAG_STORE0 + ret + EXTMEM_EA_REG16 + xor ax, word ptr I286_REG[ebp] + mov dx, ax + FLAG_STORE0 + jmp i286_memorywrite_w + } +} + +I286 xor_r8_ea(void) { // 32: xor REG8, EA + + __asm { + //PREPART_REG8_EA(2, 7) + PREPART_REG8_EA_X(2, 7, 2, 11) + xor byte ptr I286_REG[ebp], al + FLAG_STORE0 + ret + } +} + +I286 xor_r16_ea(void) { // 33: xor REG16, EA + + __asm { + //PREPART_REG16_EA(2, 7) + PREPART_REG16_EA_X(2, 7, 2, 11) + xor word ptr I286_REG[ebp], ax + FLAG_STORE0 + ret + } +} + +I286 xor_al_data8(void) { // 34: xor al, DATA8 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + xor I286_AL, bh + FLAG_STORE0 + GET_NEXTPRE2 + ret + } +} + +I286 xor_ax_data16(void) { // 35: xor ax, DATA16 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE3a + xor I286_AX, bx + FLAG_STORE0 + GET_NEXTPRE3b + ret + } +} + +I286 segprefix_ss(void) { // 36: ss: + + __asm { + mov eax, SS_BASE + mov DS_FIX, eax + mov SS_FIX, eax + I286PREFIX(i286op) + } +} + +I286 _aaa(void) { // 37: aaa + + __asm { + I286CLOCK(3) + FLAG_LOAD + mov ax, I286_AX + aaa + mov I286_AX, ax + FLAG_STORE + GET_NEXTPRE1 + ret + } +} + +I286 cmp_ea_r8(void) { // 38: cmp EA, REG8 + + __asm { + PREPART_EA_REG8(2) + cmp byte ptr I286_REG[eax], dl + FLAG_STORE_OF + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG8(6) + MEMORY_EA_REG8_X(6, 11) + cmp byte ptr I286_MEM[ecx], dl + FLAG_STORE_OF + ret + EXTMEM_EA_REG8 + cmp al, byte ptr I286_REG[ebp] + FLAG_STORE_OF + ret + } +} + +I286 cmp_ea_r16(void) { // 39: cmp EA, REG16 + + __asm { + PREPART_EA_REG16(2) + cmp I286_REG[eax*2], dx + FLAG_STORE_OF + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG16(6) + MEMORY_EA_REG16_X(6, 11) + cmp word ptr I286_MEM[ecx], dx + FLAG_STORE_OF + ret + EXTMEM_EA_REG16 + cmp ax, I286_REG[ebp] + FLAG_STORE_OF + ret + } +} + +I286 cmp_r8_ea(void) { // 3A: cmp REG8, EA + + __asm { + //PREPART_REG8_EA(2, 6) + PREPART_REG8_EA_X(2, 6, 2, 11) + cmp I286_REG[ebp], al + FLAG_STORE_OF + ret + } +} + +I286 cmp_r16_ea(void) { // 3B: cmp REG16, EA + + __asm { + //PREPART_REG16_EA(2, 6) + PREPART_REG16_EA_X(2, 6, 2, 11) + cmp I286_REG[ebp], ax + FLAG_STORE_OF + ret + } +} + +I286 cmp_al_data8(void) { // 3C: cmp al, DATA8 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + cmp I286_AL, bh + FLAG_STORE_OF + GET_NEXTPRE2 + ret + } +} + +I286 cmp_ax_data16(void) { // 3D: cmp ax, DATA16 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE3a + cmp I286_AX, bx + FLAG_STORE_OF + GET_NEXTPRE3b + ret + } +} + +I286 segprefix_ds(void) { // 3E: ds: + + __asm { + mov eax, DS_BASE + mov DS_FIX, eax + mov SS_FIX, eax + I286PREFIX(i286op) + } +} + +I286 _aas(void) { // 3F: aas + + __asm { + I286CLOCK(3) + FLAG_LOAD + mov ax, I286_AX + aas + mov I286_AX, ax + FLAG_STORE + GET_NEXTPRE1 + ret + } +} + + +I286 inc_ax(void) { // 40: inc ax + + __asm { + I286CLOCK(2) + inc I286_AX + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 inc_cx(void) { // 41: inc cx + + __asm { + I286CLOCK(2) + inc I286_CX + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 inc_dx(void) { // 42: inc dx + + __asm { + I286CLOCK(2) + inc I286_DX + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 inc_bx(void) { // 43: inc bx + + __asm { + I286CLOCK(2) + inc I286_BX + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 inc_sp(void) { // 44: inc sp + + __asm { + I286CLOCK(2) + inc I286_SP + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 inc_bp(void) { // 45: inc bp + + __asm { + I286CLOCK(2) + inc I286_BP + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 inc_si(void) { // 46: inc si + + __asm { + I286CLOCK(2) + inc I286_SI + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 inc_di(void) { // 47: inc di + + __asm { + I286CLOCK(2) + inc I286_DI + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 dec_ax(void) { // 48: dec ax + + __asm { + I286CLOCK(2) + dec I286_AX + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 dec_cx(void) { // 49: dec cx + + __asm { + I286CLOCK(2) + dec I286_CX + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 dec_dx(void) { // 4a: dec dx + + __asm { + I286CLOCK(2) + dec I286_DX + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 dec_bx(void) { // 4b: dec bx + + __asm { + I286CLOCK(2) + dec I286_BX + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 dec_sp(void) { // 4c: dec sp + + __asm { + I286CLOCK(2) + dec I286_SP + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 dec_bp(void) { // 4d: dec bp + + __asm { + I286CLOCK(2) + dec I286_BP + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 dec_si(void) { // 4e: dec si + + __asm { + I286CLOCK(2) + dec I286_SI + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + +I286 dec_di(void) { // 4f: dec di + + __asm { + I286CLOCK(2) + dec I286_DI + FLAG_STORE_NC + GET_NEXTPRE1 + ret + } +} + + +I286 push_ax(void) { // 50: push ax + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_AX) + } +} + +I286 push_cx(void) { // 51: push cx + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_CX) + } +} + +I286 push_dx(void) { // 52: push dx + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_DX) + } +} + +I286 push_bx(void) { // 53: push bx + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_BX) + } +} + +I286 push_sp(void) { // 54: push sp + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_SP) + } +} + +I286 push_bp(void) { // 55: push bp + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_BP) + } +} + +I286 push_si(void) { // 56: push si + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_SI) + } +} + +I286 push_di(void) { // 57: push di + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + REGPUSH1(I286_DI) + } +} + +I286 pop_ax(void) { // 58: pop ax + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + REGPOP(I286_AX) + GET_NEXTPRE1 + ret + } +} + +I286 pop_cx(void) { // 59: pop cx + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + REGPOP(I286_CX) + GET_NEXTPRE1 + ret + } +} + +I286 pop_dx(void) { // 5A: pop dx + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + REGPOP(I286_DX) + GET_NEXTPRE1 + ret + } +} + +I286 pop_bx(void) { // 5B: pop bx + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + REGPOP(I286_BX) + GET_NEXTPRE1 + ret + } +} + +I286 pop_sp(void) { // 5C: pop sp + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + movzx ecx, I286_SP + add ecx, SS_BASE + call i286_memoryread_w + mov I286_SP, ax + GET_NEXTPRE1 + ret + } +} + +I286 pop_bp(void) { // 5D: pop bp + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + REGPOP(I286_BP) + GET_NEXTPRE1 + ret + } +} + +I286 pop_si(void) { // 5E: pop si + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + REGPOP(I286_SI) + GET_NEXTPRE1 + ret + } +} + +I286 pop_di(void) { // 5F: pop di + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + REGPOP(I286_DI) + GET_NEXTPRE1 + ret + } +} + + +I286 _pusha(void) { // 60: pusha + + __asm { + movzx ebp, I286_SP + sub bp, 2 + + GET_NEXTPRE1 + //I286CLOCK(17) + I286CLOCK_X(a, 17, 35) + mov edi, SS_BASE + + lea ecx, [edi + ebp] + sub bp, 2 + mov dx, I286_AX + call i286_memorywrite_w + + lea ecx, [edi + ebp] + sub bp, 2 + mov dx, I286_CX + call i286_memorywrite_w + + lea ecx, [edi + ebp] + sub bp, 2 + mov dx, I286_DX + call i286_memorywrite_w + + lea ecx, [edi + ebp] + sub bp, 2 + mov dx, I286_BX + call i286_memorywrite_w + + lea ecx, [edi + ebp] + sub bp, 2 + mov dx, I286_SP + call i286_memorywrite_w + + lea ecx, [edi + ebp] + sub bp, 2 + mov dx, I286_BP + call i286_memorywrite_w + + lea ecx, [edi + ebp] + sub bp, 2 + mov dx, I286_SI + call i286_memorywrite_w + + mov I286_SP, bp + lea ecx, [edi + ebp] + mov dx, I286_DI + jmp i286_memorywrite_w + } +} + +I286 _popa(void) { // 61: popa + + __asm { + GET_NEXTPRE1 + //I286CLOCK(19) + I286CLOCK_X(a, 19, 43) + mov edi, SS_BASE + movzx ebp, I286_SP + + lea ecx, [edi + ebp] + add bp, 2 + call i286_memoryread_w + mov I286_DI, ax + + lea ecx, [edi + ebp] + add bp, 2 + call i286_memoryread_w + mov I286_SI, ax + + lea ecx, [edi + ebp] + add bp, 4 + call i286_memoryread_w + mov I286_BP, ax + + lea ecx, [edi + ebp] + add bp, 2 + call i286_memoryread_w + mov I286_BX, ax + + lea ecx, [edi + ebp] + add bp, 2 + call i286_memoryread_w + mov I286_DX, ax + + lea ecx, [edi + ebp] + add bp, 2 + call i286_memoryread_w + mov I286_CX, ax + + lea ecx, [edi + ebp] + call i286_memoryread_w + mov I286_AX, ax + add I286_SP, 16 + ret + } +} + +I286 _bound(void) { + + __asm { + movzx eax, bh + mov ebp, 6 + cmp al, 0c0h + jnc bountint + mov ebp, eax + shr ebp, 3-1 + and ebp, 7*2 + I286CLOCK(13) + call p_ea_dst[eax*4] + call i286_memoryread_w + cmp I286_REG[ebp], ax + jb bounttrue + add ecx, 2 + call i286_memoryread_w + cmp I286_REG[ebp], ax + ja bounttrue + ret + + align 16 +bounttrue: mov ebp, 5 +bountint: INT_NUM(ebp) + } +} + +I286 _arpl(void) { + + __asm { + xor eax, eax + cmp bh, 0c0h + setc al + // add si, ax + add eax, 10 + I286CLOCK(eax) + INT_NUM(6) + } +} + +I286 push_data16(void) { // 68: push DATA16 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 7) + GET_NEXTPRE3a + REGPUSH(bx) + GET_NEXTPRE3b + ret + } +} + +I286 imul_reg_ea_data16(void) { // 69: imul REG, EA, DATA16 + + __asm { + //PREPART_REG16_EA(21, 24) + PREPART_REG16_EA_X(21, 24, 45, 49) + imul bx + mov I286_REG[ebp], ax + + mov al, ah + lahf + and ah, 0feh + and I286_FLAGL, 0feh + or I286_FLAGL, ah + rcl al, 1 + adc dx, 0 +#if defined(VAEG_FIX) + jz imulnooverflow +#else + jne imulnooverflow +#endif + or I286_FLAG, (O_FLAG or C_FLAG) + +imulnooverflow: GET_NEXTPRE2 + ret + } +} + +I286 push_data8(void) { // 6A: push DATA8 + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + mov al, bh + cbw + REGPUSH(ax) + + GET_NEXTPRE2 + ret + } +} + +I286 imul_reg_ea_data8(void) { // 6B: imul REG, EA, DATA8 + + __asm { + PREPART_REG16_EA(21, 24) + movsx edx, bl + imul dx + mov I286_REG[ebp], ax + + mov al, ah + lahf + and ah, 0feh + and I286_FLAGL, 0feh + or I286_FLAGL, ah + rcl al, 1 + adc dx, 0 +#if defined(VAEG_FIX) + jz imulnooverflow +#else + jne imulnooverflow +#endif + or I286_FLAG, (O_FLAG or C_FLAG) + +imulnooverflow: GET_NEXTPRE1 + ret + } +} + +I286 _insb(void) { // 6C: insb + + __asm { + GET_NEXTPRE1 + I286CLOCK(5) + movzx ecx, I286_DX + call iocore_inp8 + mov dl, al + movzx ecx, I286_ES + shl ecx, 4 + movzx eax, I286_DI + add ecx, eax + STRING_DIR + add I286_DI, ax + jmp i286_memorywrite + } +} + +I286 _insw(void) { // 6D: insw + + __asm { + GET_NEXTPRE1 + I286CLOCK(5) + movzx ecx, I286_DX + call iocore_inp16 + mov dx, ax + movzx ecx, I286_ES + shl ecx, 4 + movzx eax, I286_DI + add ecx, eax + STRING_DIRx2 + add I286_DI, ax + jmp i286_memorywrite_w + } +} + +I286 _outsb(void) { // 6E: outsb + + __asm { + GET_NEXTPRE1 + I286CLOCK(3) + movzx ecx, I286_SI + add ecx, DS_FIX + call i286_memoryread + mov dl, al + STRING_DIR + add I286_SI, ax + movzx ecx, I286_DX + jmp iocore_out8 + } +} + +I286 _outsw(void) { // 6F: outsw + + __asm { + GET_NEXTPRE1 + I286CLOCK(3) + movzx ecx, I286_SI + add ecx, DS_FIX + call i286_memoryread_w + mov dx, ax + STRING_DIRx2 + add I286_SI, ax + movzx ecx, I286_DX + jmp iocore_out16 + } +} + + +I286 jo_short(void) { // 70: jo short + + __asm { + test I286_FLAG, O_FLAG + jne flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jno_short(void) { // 71: jno short + + __asm { + test I286_FLAG, O_FLAG + je flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jc_short(void) { // 72: jnae/jb/jc short + + __asm { + test I286_FLAG, C_FLAG + jne flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jnc_short(void) { // 73: jae/jnb/jnc short + + __asm { + test I286_FLAG, C_FLAG + je flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jz_short(void) { // 74: je/jz short + + __asm { + test I286_FLAG, Z_FLAG + jne flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jnz_short(void) { // 75: jne/jnz short + + __asm { + test I286_FLAG, Z_FLAG + jne flagnonjump + + //I286CLOCK(7) // ジャンプする事が多いと思う + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + +flagnonjump: //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + } +} + +I286 jna_short(void) { // 76: jna/jbe short + + __asm { + test I286_FLAG, (Z_FLAG or C_FLAG) + jne flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 ja_short(void) { // 77: ja/jnbe short + + __asm { + test I286_FLAG, (Z_FLAG or C_FLAG) + je flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 js_short(void) { // 78: js short + + __asm { + test I286_FLAG, S_FLAG + jne flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jns_short(void) { // 79: jns short + + __asm { + test I286_FLAG, S_FLAG + je flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jp_short(void) { // 7A: jp/jpe short + + __asm { + test I286_FLAG, P_FLAG + jne flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jnp_short(void) { // 7B: jnp/jpo short + + __asm { + test I286_FLAG, P_FLAG + je flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jl_short(void) { // 7C: jl/jnge short + + __asm { + mov dx, I286_FLAG + shl dh, 4 + xor dl, dh + js flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jnl_short(void) { // 7D: jnl/jge short + + __asm { + mov dx, I286_FLAG + shl dh, 4 + xor dl, dh + jns flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jle_short(void) { // 7E: jle/jng short + + __asm { + mov dx, I286_FLAG + test dx, Z_FLAG + jne flagjump + shl dh, 4 + xor dl, dh + js flagjump + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + + align 16 +flagjump: //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 jnle_short(void) { // 7F: jg/jnle short + + __asm { + mov dx, I286_FLAG + test dx, Z_FLAG + jne notjump + shl dh, 4 + xor dl, dh + js notjump + //I286CLOCK(7) + I286CLOCK_X(b, 7, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + + align 16 +notjump: //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + GET_NEXTPRE2 + ret + } +} + + +I286 calc_ea8_i8(void) { // 80,82: op EA8, DATA8 + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 // opcode + cmp al, 0c0h + jc memory_eareg8 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + bt ax, 2 + rcl eax, 1 + and eax, 7 + lea ebp, I286_REG[eax] + mov edx, ebx + shr edx, 16 + GET_NEXTPRE3 + jmp op8xreg8_xtable[edi] + align 16 + memory_eareg8: + //I286CLOCK(7) + I286CLOCK_X(b, 7, 18) + call p_ea_dst[eax*4] + cmp ecx, I286_MEMWRITEMAX + jnc extmem_eareg8 + lea ebp, I286_MEM[ecx] + mov edx, ebx + GET_NEXTPRE1 + jmp op8xreg8_xtable[edi] + align 16 + extmem_eareg8: + call i286_memoryread + mov dl, al + call op8xext8_xtable[edi] + GET_NEXTPRE1 + ret + } +} + +I286 calc_ea16_i16(void) { // 81: op EA16, DATA16 + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 // opcode + cmp al, 0c0h + jc memory_eareg8 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + and eax, 7 + lea ebp, word ptr I286_REG[eax*2] + mov edx, ebx + shr edx, 16 + GET_NEXTPRE4 + jmp op8xreg16_xtable[edi] + align 16 + memory_eareg8: + //I286CLOCK(7) + I286CLOCK_X(b, 7, 18) + call p_ea_dst[eax*4] + cmp ecx, I286_MEMWRITEMAX + jnc extmem_eareg8 + lea ebp, word ptr I286_MEM[ecx] + mov edx, ebx + GET_NEXTPRE2 + jmp op8xreg16_xtable[edi] + align 16 + extmem_eareg8: + call i286_memoryread_w + mov edx, eax + call op8xext16_xtable[edi] + GET_NEXTPRE2 + ret + } +} + +I286 calc_ea16_i8(void) { // 83: op EA16, DATA8 + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 // opcode + cmp al, 0c0h + jc memory_eareg8 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + and eax, 7 + lea ebp, I286_REG[eax*2] + GET_NEXTPRE2 + movsx edx, bl + GET_NEXTPRE1 + jmp op8xreg16_xtable[edi] + align 16 + memory_eareg8: + //I286CLOCK(7) + I286CLOCK_X(b, 7, 18) + call p_ea_dst[eax*4] + cmp ecx, (I286_MEMWRITEMAX-1) + jnc extmem_eareg8 + lea ebp, I286_MEM[ecx] + movsx edx, bl + GET_NEXTPRE1 + jmp op8xreg16_xtable[edi] + align 16 + extmem_eareg8: + call i286_memoryread_w + mov edx, eax + movsx eax, bl + call op8xext16_atable[edi] + GET_NEXTPRE1 + ret + } +} + +I286 test_ea_r8(void) { // 84: test EA, REG8 + + __asm { + PREPART_EA_REG8(2) + test I286_REG[eax], dl + FLAG_STORE0 + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG8(7) + MEMORY_EA_REG8_X(7, 10) + test I286_MEM[ecx], dl + FLAG_STORE0 + ret + EXTMEM_EA_REG8 + test al, I286_REG[ebp] + FLAG_STORE0 + ret + } +} + +I286 test_ea_r16(void) { // 85: test EA, REG16 + + __asm { + PREPART_EA_REG16(2) + test I286_REG[eax*2], dx + FLAG_STORE0 + GET_NEXTPRE2 // ea_regの regregだけ + ret + //MEMORY_EA_REG16(6) + MEMORY_EA_REG16_X(6, 10) + test word ptr I286_MEM[ecx], dx + FLAG_STORE0 + ret + EXTMEM_EA_REG16 + test ax, I286_REG[ebp] + FLAG_STORE0 + ret + } +} + +I286 xchg_ea_r8(void) { // 86: xchg EA, REG8 + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3 + bt di, 2 + rcl edi, 1 + and edi, 7 + cmp al, 0c0h + jc memory_eareg8 + bt ax, 2 + rcl eax, 1 + and eax, 7 + I286CLOCK(3) + mov dl, I286_REG[edi] + xchg dl, I286_REG[eax] + mov I286_REG[edi], dl + GET_NEXTPRE2 + ret + align 16 + memory_eareg8: + //I286CLOCK(5) + I286CLOCK_X(b, 5, 16) + call p_ea_dst[eax*4] + cmp ecx, I286_MEMREADMAX + jae extmem_eareg8 + mov dl, I286_REG[edi] + xchg I286_MEM[ecx], dl + mov I286_REG[edi], dl + ret + align 16 + extmem_eareg8: + call i286_memoryread + xchg al, I286_REG[edi] + mov dl, al + jmp i286_memorywrite + } +} + +I286 xchg_ea_r16(void) { // 87: xchg EA, REG16 + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-1 + and edi, 7*2 + cmp al, 0c0h + jc memory_eareg16 + and eax, 7 + I286CLOCK(3) + mov dx, I286_REG[edi] + xchg dx, I286_REG[eax*2] + mov I286_REG[edi], dx + GET_NEXTPRE2 + ret + align 16 + memory_eareg16: + //I286CLOCK(5) + I286CLOCK_X(b, 5, 16) + call p_ea_dst[eax*4] + cmp ecx, (I286_MEMREADMAX-1) + jae extmem_eareg16 + mov dx, word ptr I286_MEM[ecx] + xchg dx, I286_REG[edi] + mov word ptr I286_MEM[ecx], dx + ret + align 16 + extmem_eareg16: + call i286_memoryread_w + xchg ax, I286_REG[edi] + mov dx, ax + jmp i286_memorywrite_w + } +} + +I286 mov_ea_r8(void) { // 88: mov EA, REG8 + + __asm { + PREPART_EA_REG8(2) + mov I286_REG[eax], dl + GET_NEXTPRE2 // ea_regの regregだけ + ret + align 16 + memory_eareg8: + //I286CLOCK(3) + I286CLOCK_X(b, 3, 9) + call p_ea_dst[eax*4] + mov dl, I286_REG[ebp] + jmp i286_memorywrite + } +} + +I286 mov_ea_r16(void) { // 89: mov EA, REG16 + + __asm { + PREPART_EA_REG16(2) + mov I286_REG[eax*2], dx + GET_NEXTPRE2 // ea_regの regregだけ + ret + memory_eareg16: + //I286CLOCK(3) + I286CLOCK_X(b, 3, 9) + call p_ea_dst[eax*4] + mov dx, I286_REG[ebp] + jmp i286_memorywrite_w + } +} + +I286 mov_r8_ea(void) { // 8A: mov REG8, EA + + __asm { + //PREPART_REG8_EA(2, 5) + PREPART_REG8_EA_X(2, 5, 2, 11) + mov I286_REG[ebp], al + ret + } +} + +I286 mov_r16_ea(void) { // 8B: add REG16, EA + + __asm { + //PREPART_REG16_EA(2, 5) + PREPART_REG16_EA_X(2, 5, 2, 11) + mov I286_REG[ebp], ax + ret + } +} + +I286 mov_ea_seg(void) { // 8C: mov EA, segreg + + __asm { + movzx eax, bh + mov ebp, eax + shr ebp, 3-1 + and ebp, 3*2 + mov dx, word ptr I286_SEGREG[ebp] + cmp al, 0c0h + jc memory_eareg16 + I286CLOCK(2) + and eax, 7 + mov word ptr I286_REG[eax*2], dx + GET_NEXTPRE2 + ret + align 16 + memory_eareg16: + //I286CLOCK(3) + I286CLOCK_X(b, 3, 10) + call p_ea_dst[eax*4] + jmp i286_memorywrite_w + } +} + +I286 lea_r16_ea(void) { // 8D: lea REG16, EA + + __asm { + cmp bh, 0c0h + jnc src_register + //I286CLOCK(3) + I286CLOCK_X(a, 3, 4) + movzx eax, bh + mov ebp, eax + shr ebp, 3-1 + and ebp, 7*2 + call p_lea[eax*4] + mov word ptr I286_REG[ebp], ax + ret + align 16 + src_register: + INT_NUM(6) + } +} + +I286 mov_seg_ea(void) { // 8E: mov segrem, EA + + __asm { + movzx eax, bh + mov ebp, eax + shr ebp, 3-1 + and ebp, 3*2 +#if 1 + cmp ebp, 1*2 + je fixcs +#endif + cmp al, 0c0h + jc src_memory + I286CLOCK(2) + and eax, 7 + mov edi, eax + GET_NEXTPRE2 + mov ax, word ptr I286_REG[edi*2] + jmp segset + align 4 + src_memory: + //I286CLOCK(5) + I286CLOCK_X(b, 5, 11) + call p_ea_dst[eax*4] + call i286_memoryread_w + segset: + mov word ptr I286_SEGREG[ebp], ax + movzx eax, ax + test byte ptr (I286_MSW), MSW_PE + jne short mov_seg_pe + shl eax, 4 // make segreg +mov_seg_base: mov SEG_BASE[ebp*2], eax + sub ebp, 2*2 + jc short segsetr + mov SS_FIX[ebp*2], eax + je short setss + segsetr:ret + + setss: cmp i286core.s.prefix, 0 // 00/05/13 + je noprefix + pop eax + call eax // eax<-offset removeprefix + noprefix: + movzx eax, bl + jmp i286op[eax*4] + +mov_seg_pe: push offset mov_seg_base + jmp i286x_selector + + fixcs: INT_NUM(6) + } +} + +I286 pop_ea(void) { // 8F: pop EA + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 17) + movzx ecx, I286_SP + add ecx, SS_BASE + call i286_memoryread_w + add I286_SP, 2 + mov dx, ax + movzx eax, bh + cmp al, 0c0h + jnc src_register + call p_ea_dst[eax*4] + jmp i286_memorywrite_w + align 16 + src_register: + and eax, 7 + mov word ptr I286_REG[eax*2], dx + GET_NEXTPRE2 + ret + } +} + + +I286 _nop(void) { // 90: nop / bios func + + __asm { + I286CLOCK(3) + GET_NEXTPRE1 +#if 1 + lea ecx, [esi - 1] + add ecx, CS_BASE + cmp ecx, 0f8000h + jc biosend + cmp ecx, 100000h + jnc biosend + mov I286_IP, si + call biosfunc + cmp al, ah + je biosend + movzx esi, I286_IP + movzx eax, I286_ES + shl eax, 4 + mov ES_BASE, eax + movzx eax, I286_CS + shl eax, 4 + mov CS_BASE, eax + movzx eax, I286_SS + shl eax, 4 + mov SS_BASE, eax + mov SS_FIX, eax + movzx eax, I286_DS + shl eax, 4 + mov DS_BASE, eax + mov DS_FIX, eax + RESET_XPREFETCH + biosend: +#endif + ret + } +} + +I286 xchg_ax_cx(void) { // 91: xchg ax, cx + + __asm { + GET_NEXTPRE1 + I286CLOCK(3) + mov ax, I286_AX + xchg ax, I286_CX + mov I286_AX, ax + ret + } +} + +I286 xchg_ax_dx(void) { // 92: xchg ax, dx + + __asm { + GET_NEXTPRE1 + I286CLOCK(3) + mov ax, I286_AX + xchg ax, I286_DX + mov I286_AX, ax + ret + } +} + +I286 xchg_ax_bx(void) { // 93: xchg ax, bx + + __asm { + GET_NEXTPRE1 + I286CLOCK(3) + mov ax, I286_AX + xchg ax, I286_BX + mov I286_AX, ax + ret + } +} + +I286 xchg_ax_sp(void) { // 94: xchg ax, sp + + __asm { + GET_NEXTPRE1 + I286CLOCK(3) + mov ax, I286_AX + xchg ax, I286_SP + mov I286_AX, ax + ret + } +} + +I286 xchg_ax_bp(void) { // 95: xchg ax, bp + + __asm { + GET_NEXTPRE1 + I286CLOCK(3) + mov ax, I286_AX + xchg ax, I286_BP + mov I286_AX, ax + ret + } +} + +I286 xchg_ax_si(void) { // 96: xchg ax, si + + __asm { + GET_NEXTPRE1 + I286CLOCK(3) + mov ax, I286_AX + xchg ax, I286_SI + mov I286_AX, ax + ret + } +} + +I286 xchg_ax_di(void) { // 97: xchg ax, di + + __asm { + GET_NEXTPRE1 + I286CLOCK(3) + mov ax, I286_AX + xchg ax, I286_DI + mov I286_AX, ax + ret + } +} + +I286 _cbw(void) { // 98: cbw + + __asm { + GET_NEXTPRE1 + I286CLOCK(2) + test I286_AL, 80h + setz I286_AH + dec I286_AH + ret + } +} + +I286 _cwd(void) { // 99: cwd + + __asm { + GET_NEXTPRE1 + I286CLOCK(2) + mov ax, 80h + test I286_AH, al + setz al + dec ax + mov I286_DX, ax + ret + } +} + +I286 call_far(void) { // 9A: call far + + __asm { + GET_NEXTPRE1 + //I286CLOCK(13) + I286CLOCK_X(a, 13, (21+4)) + mov edi, SS_BASE + movzx ebp, I286_SP + mov dx, I286_CS + sub bp, 2 + lea ecx, [edi + ebp] + call i286_memorywrite_w + sub bp, 2 + lea ecx, [edi + ebp] + lea edx, [esi + 4] + call i286_memorywrite_w + mov I286_SP, bp + mov si, bx + shr ebx, 16 + mov I286_CS, bx + test byte ptr (I286_MSW), MSW_PE + jne short call_far_pe + shl ebx, 4 + mov CS_BASE, ebx +call_far_base: RESET_XPREFETCH + ret + +call_far_pe: mov eax, ebx + call i286x_selector + mov CS_BASE, eax + jmp short call_far_base + } +} + +I286 _wait(void) { // 9B: wait + + __asm { + GET_NEXTPRE1 + ret + } +} + +I286 _pushf(void) { // 9C: pushf + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + mov dx, I286_FLAG + and dx, 0fffh // 286 + sub I286_SP, 2 + movzx ecx, I286_SP + add ecx, SS_BASE + jmp i286_memorywrite_w + } +} + +I286 _popf(void) { // 9D: popf + + __asm { + GET_NEXTPRE1 + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + movzx ecx, I286_SP + add ecx, SS_BASE + call i286_memoryread_w + add I286_SP, 2 + and ax, 0fffh // 286 + mov I286_FLAG, ax +#if defined(VAEG_FIX) + and ah, 1 + cmp ah, 1 +#else + and ah, 3 + cmp ah, 3 +#endif + sete I286_TRAP + + je irqcheck // fast_intr + test ah, 2 + je nextop + mov al, pic.pi[0 * (type _PICITEM)].imr + mov ah, pic.pi[1 * (type _PICITEM)].imr + not ax + test al, pic.pi[0 * (type _PICITEM)].irr + jne irqcheck + test ah, pic.pi[1 * (type _PICITEM)].irr + jne irqcheck +nextop: ret + +irqcheck: I286IRQCHECKTERM + } +} + +I286 _sahf(void) { // 9E: sahf + + __asm { + GET_NEXTPRE1 + //I286CLOCK(2) + I286CLOCK_X(a, 2, 3) + mov al, I286_AH + and ax, 0fffh // 286 + mov I286_FLAGL, al + ret + } +} + +I286 _lahf(void) { // 9F: lahf + + __asm { + GET_NEXTPRE1 + I286CLOCK(2) + mov al, I286_FLAGL + and ax, 0fffh // 286 + mov I286_AH, al + ret + } +} + + +I286 mov_al_m8(void) { // A0: mov al, m8 + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 10) + mov ecx, ebx + shr ecx, 8 + and ecx, 0ffffh + add ecx, DS_FIX + call i286_memoryread + mov I286_AL, al + GET_NEXTPRE3 + ret + } +} + +I286 mov_ax_m16(void) { // A1: mov ax, m16 + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 10) + mov ecx, ebx + shr ecx, 8 + and ecx, 0ffffh + add ecx, DS_FIX + call i286_memoryread_w + mov I286_AX, ax + GET_NEXTPRE3 + ret + + } +} + +I286 mov_m8_al(void) { // A2: mov m8, al + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 9) + mov edi, ebx + shr edi, 8 + and edi, 0ffffh + add edi, DS_FIX + GET_NEXTPRE3 + mov ecx, edi + mov dl, I286_AL + jmp i286_memorywrite + } +} + +I286 mov_m16_ax(void) { // A3: mov m16, ax + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 9) + mov edi, ebx + shr edi, 8 + and edi, 0ffffh + add edi, DS_FIX + GET_NEXTPRE3 + mov ecx, edi + mov dx, I286_AX + jmp i286_memorywrite_w + } +} + +I286 _movsb(void) { // A4: movsb + + __asm { + GET_NEXTPRE1 + //I286CLOCK(5) + I286CLOCK_X(a, 5, 11) + movzx ecx, I286_SI + add ecx, DS_FIX + call i286_memoryread + mov dl, al + movzx ecx, I286_DI + add ecx, ES_BASE + STRING_DIR + add I286_SI, ax + add I286_DI, ax + jmp i286_memorywrite + } +} + +I286 _movsw(void) { // A5: movsw + + __asm { + GET_NEXTPRE1 + //I286CLOCK(5) + I286CLOCK_X(a, 5, 11) + movzx ecx, I286_SI + add ecx, DS_FIX + call i286_memoryread_w + mov dx, ax + movzx ecx, I286_DI + add ecx, ES_BASE + STRING_DIRx2 + add I286_SI, ax + add I286_DI, ax + jmp i286_memorywrite_w + } +} + +I286 _cmpsb(void) { // A6: cmpsb + + __asm { + GET_NEXTPRE1 + //I286CLOCK(8) + I286CLOCK_X(a, 8, 13) + movzx ecx, I286_SI + add ecx, DS_FIX + call i286_memoryread + mov dl, al + movzx ecx, I286_DI + add ecx, ES_BASE + call i286_memoryread + cmp dl, al + FLAG_STORE_OF + STRING_DIR + add I286_SI, ax + add I286_DI, ax + ret + } +} + +I286 _cmpsw(void) { // A7: cmpsw + + __asm { + GET_NEXTPRE1 + //I286CLOCK(8) + I286CLOCK_X(a, 8, 13) + movzx ecx, I286_SI + add ecx, DS_FIX + call i286_memoryread_w + mov edx, eax + movzx ecx, I286_DI + add ecx, ES_BASE + call i286_memoryread_w + cmp dx, ax + FLAG_STORE_OF + STRING_DIRx2 + add I286_SI, ax + add I286_DI, ax + ret + } +} + +I286 test_al_data8(void) { // A8: test al, DATA8 + + __asm { + I286CLOCK(3) + test I286_AL, bh + FLAG_STORE0 + GET_NEXTPRE2 + ret + } +} + +I286 test_ax_data16(void) { // A9: test ax, DATA16 + + __asm { + I286CLOCK(3) + GET_NEXTPRE3a + test I286_AX, bx + FLAG_STORE0 + GET_NEXTPRE3b + ret + } +} + +I286 _stosb(void) { // AA: stosb + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 7) + movzx ecx, I286_DI + add ecx, ES_BASE + STRING_DIR + add I286_DI, ax + mov dl, I286_AL + jmp i286_memorywrite + } +} + +I286 _stosw(void) { // AB: stosw + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 7) + movzx ecx, I286_DI + add ecx, ES_BASE + STRING_DIRx2 + add I286_DI, ax + mov dx, I286_AX + jmp i286_memorywrite_w + } +} + +I286 _lodsb(void) { // AC: lodsb + + __asm { + GET_NEXTPRE1 + //I286CLOCK(5) + I286CLOCK_X(a, 5, 7) + movzx ecx, I286_SI + add ecx, DS_FIX + call i286_memoryread + mov I286_AL, al + STRING_DIR + add I286_SI, ax + ret + } +} + +I286 _lodsw(void) { // AD: lodsw + + __asm { + GET_NEXTPRE1 + //I286CLOCK(5) + I286CLOCK_X(a, 5, 7) + movzx ecx, I286_SI + add ecx, DS_FIX + call i286_memoryread_w + mov I286_AX, ax + STRING_DIRx2 + add I286_SI, ax + ret + } +} + +I286 _scasb(void) { // AE: scasb + + __asm { + GET_NEXTPRE1 + //I286CLOCK(7) + I286CLOCK_X(a, 7, 7) + movzx ecx, I286_DI + add ecx, ES_BASE + call i286_memoryread + cmp I286_AL, al + FLAG_STORE_OF + STRING_DIR + add I286_DI, ax + ret + } +} + +I286 _scasw(void) { // AF: scasw + + __asm { + GET_NEXTPRE1 + //I286CLOCK(7) + I286CLOCK_X(a, 7, 7) + movzx ecx, I286_DI + add ecx, ES_BASE + call i286_memoryread_w + cmp I286_AX, ax + FLAG_STORE_OF + STRING_DIRx2 + add I286_DI, ax + ret + } +} + + +I286 mov_al_imm(void) { // B0: mov al, imm8 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + mov I286_AL, bh + GET_NEXTPRE2 + ret + } +} + +I286 mov_cl_imm(void) { // B1: mov cl, imm8 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + mov I286_CL, bh + GET_NEXTPRE2 + ret + } +} + +I286 mov_dl_imm(void) { // B2: mov dl, imm8 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + mov I286_DL, bh + GET_NEXTPRE2 + ret + } +} + +I286 mov_bl_imm(void) { // B3: mov bl, imm8 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + mov I286_BL, bh + GET_NEXTPRE2 + ret + } +} + +I286 mov_ah_imm(void) { // B4: mov ah, imm8 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + mov I286_AH, bh + GET_NEXTPRE2 + ret + } +} + +I286 mov_ch_imm(void) { // B5: mov ch, imm8 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + mov I286_CH, bh + GET_NEXTPRE2 + ret + } +} + +I286 mov_dh_imm(void) { // B6: mov dh, imm8 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + mov I286_DH, bh + GET_NEXTPRE2 + ret + } +} + +I286 mov_bh_imm(void) { // B7: mov bh, imm8 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + mov I286_BH, bh + GET_NEXTPRE2 + ret + } +} + +I286 mov_ax_imm(void) { // B8: mov ax, imm16 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + GET_NEXTPRE3a + mov I286_AX, bx + GET_NEXTPRE3b + ret + } +} + +I286 mov_cx_imm(void) { // B9: mov cx, imm16 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + GET_NEXTPRE3a + mov I286_CX, bx + GET_NEXTPRE3b + ret + } +} + +I286 mov_dx_imm(void) { // BA: mov dx, imm16 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + GET_NEXTPRE3a + mov I286_DX, bx + GET_NEXTPRE3b + ret + } +} + +I286 mov_bx_imm(void) { // BB: mov bx, imm16 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + GET_NEXTPRE3a + mov I286_BX, bx + GET_NEXTPRE3b + ret + } +} + +I286 mov_sp_imm(void) { // BC: mov sp, imm16 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + GET_NEXTPRE3a + mov I286_SP, bx + GET_NEXTPRE3b + ret + } +} + +I286 mov_bp_imm(void) { // BD: mov bp, imm16 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + GET_NEXTPRE3a + mov I286_BP, bx + GET_NEXTPRE3b + ret + } +} + +I286 mov_si_imm(void) { // BE: mov si, imm16 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + GET_NEXTPRE3a + mov I286_SI, bx + GET_NEXTPRE3b + ret + } +} + +I286 mov_di_imm(void) { // BF: mov di, imm16 + + __asm { + //I286CLOCK(2) + I286CLOCK_X(a, 2, 4) + GET_NEXTPRE3a + mov I286_DI, bx + GET_NEXTPRE3b + ret + } +} + +I286 shift_ea8_data8(void) { // C0: shift EA8, DATA8 + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 // opcode + cmp al, 0c0h + jc memory_eareg8 + I286CLOCK(5) + bt ax, 2 + rcl eax, 1 + and eax, 7 + lea edx, I286_REG[eax] + mov ecx, ebx + shr ecx, 16 + and ecx, 31 + I286CLOCK(ecx) + push ecx + GET_NEXTPRE3 + pop ecx + jmp sftreg8cl_xtable[edi] + align 16 + memory_eareg8: + I286CLOCK(8) + call p_ea_dst[eax*4] + cmp ecx, I286_MEMWRITEMAX + jnc extmem_eareg8 + lea edx, I286_MEM[ecx] + mov ecx, ebx + and ecx, 31 + I286CLOCK(ecx) + push ecx + GET_NEXTPRE1 + pop ecx + jmp sftreg8cl_xtable[edi] + align 16 + extmem_eareg8: + call i286_memoryread + mov ebp, ecx + mov edx, eax + mov ecx, ebx + and ecx, 31 + I286CLOCK(ecx) + push ecx + GET_NEXTPRE1 + pop ecx + jmp sftext8cl_xtable[edi] + } +} + +I286 shift_ea16_data8(void) { // C1: shift EA16, DATA8 + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 // opcode + cmp al, 0c0h + jc memory_eareg16 + and eax, 7 + I286CLOCK(5) + lea edx, I286_REG[eax*2] + mov ecx, ebx + shr ecx, 16 + and ecx, 31 + I286CLOCK(ecx) + push ecx + GET_NEXTPRE3 + pop ecx + jmp sftreg16cl_xtable[edi] + align 16 + memory_eareg16: + I286CLOCK(8) + call p_ea_dst[eax*4] + cmp ecx, (I286_MEMWRITEMAX-1) + jnc extmem_eareg16 + lea edx, I286_MEM[ecx] + mov ecx, ebx + and ecx, 31 + I286CLOCK(ecx) + push ecx + GET_NEXTPRE1 + pop ecx + jmp sftreg16cl_xtable[edi] + align 16 + extmem_eareg16: + call i286_memoryread_w + mov ebp, ecx + mov edx, eax + mov ecx, ebx + and ecx, 31 + I286CLOCK(ecx) + push ecx + GET_NEXTPRE1 + pop ecx + jmp sftext16cl_xtable[edi] + } +} + +I286 ret_near_data16(void) { // C2: ret near DATA16 + + __asm { + //I286CLOCK(11) + I286CLOCK_X(a, 11, (20+4)) + shr ebx, 8 + add ebx, 2 + movzx ecx, I286_SP + add ecx, SS_BASE + add I286_SP, bx + call i286_memoryread_w + mov si, ax + RESET_XPREFETCH + ret + } +} + +I286 ret_near(void) { // C3: ret near + + __asm { + //I286CLOCK(11) + I286CLOCK_X(a, 11, (15+4)) + REGPOP(si) + RESET_XPREFETCH + ret + } +} + +I286 les_r16_ea(void) { // C4: les REG16, EA + + __asm { + cmp bh, 0c0h + jnc src_register + //I286CLOCK(3) + I286CLOCK_X(a, 3, 18) + movzx eax, bh + push eax + call p_get_ea[eax*4] + lea ecx, [edi + ebp] + call i286_memoryread_w + add bp, 2 + pop edx + shr edx, 3-1 + and edx, 7*2 + mov word ptr I286_REG[edx], ax + lea ecx, [edi + ebp] + call i286_memoryread_w + mov I286_ES, ax + movzx eax, ax + test byte ptr (I286_MSW), MSW_PE + jne short les_pe + shl eax, 4 // make segreg +les_base: mov ES_BASE, eax + ret + +les_pe: push offset les_base + jmp i286x_selector + +src_register: INT_NUM(6) + } +} + +I286 lds_r16_ea(void) { // C5: lds REG16, EA + + __asm { + cmp bh, 0c0h + jnc src_register + //I286CLOCK(3) + I286CLOCK_X(a, 3, 18) + movzx eax, bh + push eax + call p_get_ea[eax*4] + lea ecx, [edi + ebp] + call i286_memoryread_w + add bp, 2 + pop edx + shr edx, 3-1 + and edx, 7*2 + mov word ptr I286_REG[edx], ax + lea ecx, [edi + ebp] + call i286_memoryread_w + mov I286_DS, ax + movzx eax, ax + test byte ptr (I286_MSW), MSW_PE + jne short lds_pe + shl eax, 4 // make segreg +lds_base: mov DS_BASE, eax + mov DS_FIX, eax + ret + +lds_pe: push offset lds_base + jmp i286x_selector + +src_register: INT_NUM(6) + + } +} + +I286 mov_ea8_data8(void) { // C6: mov EA8, DATA8 + + __asm { + cmp bh, 0c0h + jc memory_eareg8 + I286CLOCK(2) + mov edx, ebx + shr edx, 8 + mov bp, dx + bt bp, 2 + rcl ebp, 1 + and ebp, 7 + GET_NEXTPRE2 + mov byte ptr I286_REG[ebp], dh + ret + align 16 + memory_eareg8: + //I286CLOCK(3) + I286CLOCK_X(b, 3, 11) + movzx eax, bh + call p_get_ea[eax*4] + mov dl, bl + GET_NEXTPRE1 + lea ecx, [edi + ebp] + jmp i286_memorywrite + } +} + +I286 mov_ea16_data16(void) { // C7: mov EA16, DATA16 + + __asm { + cmp bh, 0c0h + jc memory_eareg8 + I286CLOCK(2) + movzx ebp, bh + and ebp, 7 + mov edx, ebx + shr edx, 16 + GET_NEXTPRE4 + mov word ptr I286_REG[ebp*2], dx + ret + align 16 + memory_eareg8: + //I286CLOCK(3) + I286CLOCK_X(b, 3, 11) + movzx eax, bh + call p_get_ea[eax*4] + mov dx, bx + GET_NEXTPRE2 + lea ecx, [edi + ebp] + jmp i286_memorywrite_w + } +} + +I286 _enter(void) { // C8: enter DATA16, DATA8 + + __asm { + mov edi, SS_BASE + movzx ebp, I286_SP + sub bp, 2 + lea ecx, [edi + ebp] + mov dx, I286_BP + call i286_memorywrite_w + + shld eax, ebx, 8 + shr ebx, 8 + and eax, 1fh + je enter0 + dec eax + je enter1 + lea ecx, [eax*4 + 12] + I286CLOCK(ecx) // ToDo: V30 + push ebx + movzx ebx, I286_BP + mov I286_BP, bp + enter_lp: + push eax + sub bx, 2 + lea ecx, [edi + ebx] + call i286_memoryread_w + mov edx, eax + sub bp, 2 + lea ecx, [edi + ebp] + call i286_memorywrite_w + pop eax + dec eax + jne enter_lp + pop ebx + sub bp, 2 + lea ecx, [edi + ebp] + mov dx, I286_BP + sub bp, bx + mov I286_SP, bp + push ecx + GET_NEXTPRE4 + pop ecx + jmp i286_memorywrite_w + + align 16 + enter1: + I286CLOCK(15) + mov dx, bp + sub bp, 2 + lea ecx, [edi + ebp] + mov I286_BP, dx + sub bp, bx + mov I286_SP, bp + push ecx + GET_NEXTPRE4 + pop ecx + jmp i286_memorywrite_w + + align 16 + enter0: + I286CLOCK(11) + mov I286_BP, bp + sub bp, bx + mov I286_SP, bp + GET_NEXTPRE4 + ret + } +} + +I286 leave(void) { // C9: leave + + __asm { + GET_NEXTPRE1 + I286CLOCK(5) // ToDo: V30 + mov ax, I286_BP + mov I286_SP, ax + REGPOP(I286_BP) + ret + } +} + +I286 ret_far_data16(void) { // CA: ret far DATA16 + + __asm { + //I286CLOCK(15) + I286CLOCK_X(a, 15, (24+4)) + shr ebx, 8 + mov edi, SS_BASE + movzx ebp, I286_SP + add I286_SP, bx + lea ecx, [edi + ebp] + add bp, 2 + call i286_memoryread_w + mov si, ax + lea ecx, [edi + ebp] + call i286_memoryread_w + mov I286_CS, ax + movzx eax, ax + test byte ptr (I286_MSW), MSW_PE + jne short ret_far16_pe + shl eax, 4 // make segreg +ret_far16_base: mov CS_BASE, eax + add I286_SP, 4 + RESET_XPREFETCH + ret + +ret_far16_pe: push offset ret_far16_base + jmp i286x_selector + } +} + +I286 ret_far(void) { // CB: ret far + + __asm { + //I286CLOCK(15) + I286CLOCK_X(a, 15, (21+4)) + mov edi, SS_BASE + movzx ebx, I286_SP + lea ecx, [edi + ebx] + add bx, 2 + call i286_memoryread_w + mov si, ax + lea ecx, [edi + ebx] + add bx, 2 + call i286_memoryread_w + mov I286_CS, ax + movzx eax, ax + test byte ptr (I286_MSW), MSW_PE + jne short ret_far_pe + shl eax, 4 // make segreg +ret_far_base: mov CS_BASE, eax + mov ebp, eax + mov I286_SP, bx + RESET_XPREFETCH + ret + +ret_far_pe: push offset ret_far_base + jmp i286x_selector + } +} + +I286 int_03(void) { // CC: int 3 + + __asm { + //I286CLOCK(23) + I286CLOCK_X(a, 23, (38+4)) + inc si + INT_NUM(3) + } +} + + +I286 int_data8(void) { // CD: int DATA8 + + __asm { + //I286CLOCK(23) + I286CLOCK_X(a, 23, (38+4)) + mov edi, SS_BASE + movzx ebp, I286_SP + sub bp, 2 + mov dx, I286_FLAG + and I286_FLAG, not (T_FLAG or I_FLAG) + mov I286_TRAP, 0 + lea ecx, [edi + ebp] + call i286_memorywrite_w + sub bp, 2 + lea ecx, [edi + ebp] + mov dx, I286_CS + call i286_memorywrite_w +#if defined(ENABLE_TRAP) + movzx eax, bh + push eax + lea edx, [esi - 1] + movzx ecx, I286_CS + call softinttrap +#endif + movzx eax, bh + sub bp, 2 + mov I286_SP, bp + lea edx, [esi + 2] + mov eax, dword ptr I286_MEM[eax*4] + mov si, ax + shr eax, 16 + mov I286_CS, ax + shl eax, 4 // make segreg + mov CS_BASE, eax + RESET_XPREFETCH + lea ecx, [edi + ebp] + jmp i286_memorywrite_w + } +} + +I286 _into(void) { // CE: into + + __asm { + I286CLOCK(4) + test I286_FLAG, O_FLAG + jne intovf + GET_NEXTPRE1 + ret + + intovf: inc si // ver0.80 + INT_NUM(4) + } +} + +I286 _iret(void) { // CF: iret + // V30用はV30PATCH.CPPに別途作成(Shinra) + __asm { + I286CLOCK(31) + mov edi, SS_BASE + movzx ebx, I286_SP + lea ecx, [edi + ebx] + add bx, 2 + call i286_memoryread_w + mov si, ax + lea ecx, [edi + ebx] + add bx, 2 + call i286_memoryread_w + mov I286_CS, ax + and eax, 0000ffffh + shl eax, 4 // make segreg + mov CS_BASE, eax + lea ecx, [edi + ebx] + add bx, 2 + call i286_memoryread_w + mov I286_SP, bx + and ah, 0fh + mov I286_FLAG, ax +#if defined(VAEG_FIX) + and ah, 1 + cmp ah, 1 +#else + and ah, 3 + cmp ah, 3 +#endif + sete I286_TRAP + RESET_XPREFETCH + + cmp I286_TRAP, 0 // fast_intr + jne irqcheck + test I286_FLAG, I_FLAG + je nextop + mov al, pic.pi[0 * (type _PICITEM)].imr + mov ah, pic.pi[1 * (type _PICITEM)].imr + not ax + test al, pic.pi[0 * (type _PICITEM)].irr + jne irqcheck + test ah, pic.pi[1 * (type _PICITEM)].irr + jne irqcheck +nextop: ret + +irqcheck: I286IRQCHECKTERM + } +} + + +I286 shift_ea8_1(void) { // D0: shift EA8, 1 + + __asm { + movzx edx, bh + mov edi, edx + shr edi, 3-2 + and edi, 7*4 // opcode + cmp bh, 0c0h + jc memory_eareg8 + bt dx, 2 + rcl edx, 1 + and edx, 7 + I286CLOCK(2) + GET_NEXTPRE2 + jmp sftreg8_xtable[edi] + align 16 + memory_eareg8: + I286CLOCK(7) + call p_ea_dst[edx*4] + cmp ecx, I286_MEMWRITEMAX + jnc extmem_eareg8 + jmp sftmem8_xtable[edi] + align 16 + extmem_eareg8: + call i286_memoryread + mov edx, eax + jmp sftext8_xtable[edi] + } +} + +I286 shift_ea16_1(void) { // D1: shift EA16, 1 + + __asm { + movzx edx, bh + mov edi, edx + shr edi, 3-2 + and edi, 7*4 // opcode + cmp bh, 0c0h + jc memory_eareg16 + I286CLOCK(2) + and edx, 7 + GET_NEXTPRE2 + jmp sftreg16_xtable[edi] + align 16 + memory_eareg16: + I286CLOCK(7) + call p_ea_dst[edx*4] + cmp ecx, (I286_MEMWRITEMAX-1) + jnc extmem_eareg16 + jmp sftmem16_xtable[edi] + align 16 + extmem_eareg16: + call i286_memoryread_w + mov edx, eax + jmp sftext16_xtable[edi] + } +} + +I286 shift_ea8_cl(void) { // D2: shift EA8, cl + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 // opcode + cmp al, 0c0h + jc memory_eareg8 + I286CLOCK(5) + bt ax, 2 + rcl eax, 1 + and eax, 7 + lea edx, I286_REG[eax] + GET_NEXTPRE2 + movzx ecx, I286_CL + and ecx, 31 + I286CLOCK(ecx) + jmp sftreg8cl_xtable[edi] + align 16 + memory_eareg8: + I286CLOCK(8) + call p_ea_dst[eax*4] + cmp ecx, I286_MEMWRITEMAX + jnc extmem_eareg8 + lea edx, I286_MEM[ecx] + movzx ecx, I286_CL + and ecx, 31 + I286CLOCK(ecx) + jmp sftreg8cl_xtable[edi] + align 16 + extmem_eareg8: + call i286_memoryread + mov edx, eax + mov ebp, ecx + movzx ecx, I286_CL + and ecx, 31 + I286CLOCK(ecx) + jmp sftext8cl_xtable[edi] + } +} + +I286 shift_ea16_cl(void) { // D3: shift EA16, cl + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 // opcode + cmp al, 0c0h + jc memory_eareg16 + I286CLOCK(5) + and eax, 7 + lea edx, I286_REG[eax*2] + GET_NEXTPRE2 + movzx ecx, I286_CL + and ecx, 31 + I286CLOCK(ecx) + jmp sftreg16cl_xtable[edi] + align 16 + memory_eareg16: + I286CLOCK(8) + call p_ea_dst[eax*4] + cmp ecx, (I286_MEMWRITEMAX-1) + jnc extmem_eareg16 + lea edx, I286_MEM[ecx] + movzx ecx, I286_CL + and ecx, 31 + I286CLOCK(ecx) + jmp sftreg16cl_xtable[edi] + align 16 + extmem_eareg16: + call i286_memoryread_w + mov edx, eax + mov ebp, ecx + movzx ecx, I286_CL + and ecx, 31 + I286CLOCK(ecx) + jmp sftext16cl_xtable[edi] + } +} + +I286 _aam(void) { // D4: AAM + + __asm { // todo: flag !!! + cmp bh, 0 + je div0 + I286CLOCK(16) + movzx eax, I286_AL + div bh + xchg al, ah + mov I286_AX, ax + and I286_FLAGL, not (S_FLAG or Z_FLAG or P_FLAG) + mov dh, ah + and dh, S_FLAG + test ax, ax + jne short nzflagsed + or dh, Z_FLAG +nzflagsed: xor al, ah + and eax, 00ffh + mov al, iflags[eax] + and al, P_FLAG + or al, dh + or I286_FLAGL, al + GET_NEXTPRE2 + ret + + div0: INT_NUM(0) + } +} + +I286 _aad(void) { // D5: AAD + + __asm { // todo: flag !!! + I286CLOCK(14) + mov al, I286_AH + mul bh + add al, I286_AL + mov ah, 0 + mov I286_AX, ax + and I286_FLAGL, not (S_FLAG or Z_FLAG or P_FLAG) + and eax, 00ffh + mov al, iflags[eax] + and al, P_FLAG or Z_FLAG + or I286_FLAGL, al + GET_NEXTPRE2 + ret + } +} + +I286 _setalc(void) { // D6: setalc(80286) + + __asm { + setnc I286_AL + dec I286_AL + GET_NEXTPRE1 + ret + } +} + +I286 _xlat(void) { // D7: xlat + + __asm { + I286CLOCK(5) + movzx ecx, I286_AL + add cx, I286_BX + add ecx, DS_FIX + call i286_memoryread + mov I286_AL, al + GET_NEXTPRE1 + ret + } +} + +I286 _esc(void) { // D8-DF: esc + + __asm { + cmp bh, 0c0h + jnc ea_reg8 + movzx eax, bh + jmp p_lea[eax*4] + align 16 + ea_reg8: + GET_NEXTPRE2 + ret + } +} + + +I286 _loopnz(void) { // E0: loopnz + + __asm { + dec I286_CX + je loopend + test I286_FLAG, Z_FLAG + jne loopend + //I286CLOCK(8) + I286CLOCK_X(a, 8, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + align 16 +loopend: //I286CLOCK(4) + I286CLOCK_X(b, 4, 5) + GET_NEXTPRE2 + ret + } +} + +I286 _loopz(void) { // E1: loopz + + __asm { + dec I286_CX + je loopend + test I286_FLAG, Z_FLAG + je loopend + //I286CLOCK(8) + I286CLOCK_X(a, 8, (14+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + align 16 +loopend: I286CLOCK(4) + GET_NEXTPRE2 + ret + } +} + +I286 _loop(void) { // E2: loop + + __asm { + dec I286_CX + je loopend + //I286CLOCK(8) + I286CLOCK_X(a, 8, (13 + 4)) // V30は13clock+4clock(命令読み込み時間分) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + align 16 +loopend: //I286CLOCK(4) + I286CLOCK_X(b, 4, 5) + GET_NEXTPRE2 + ret + } +} + +I286 _jcxz(void) { // E3: jcxz + + __asm { + cmp I286_CX, 0 + jne loopend + //I286CLOCK(8) + I286CLOCK_X(a, 8, (13+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + align 16 +loopend: //I286CLOCK(4) + I286CLOCK_X(b, 4, 5) + GET_NEXTPRE2 + ret + } +} + +I286 in_al_data8(void) { // E4: in al, DATA8 + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 9) + lea eax, [esi + 2] + add eax, CS_BASE + mov I286_INPADRS, eax + movzx ecx, bh + call iocore_inp8 + mov I286_AL, al + mov I286_INPADRS, 0 + GET_NEXTPRE2 + ret + } +} + +I286 in_ax_data8(void) { // E5: in ax, DATA8 + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 9) + lea eax, [esi + 2] + add eax, CS_BASE + movzx ecx, bh + call iocore_inp16 + mov I286_AX, ax + GET_NEXTPRE2 + ret + } +} + +I286 out_data8_al(void) { // E6: out DATA8, al + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + movzx ecx, bh + push ecx + GET_NEXTPRE2 + pop ecx + mov dl, I286_AL + jmp iocore_out8 + } +} + +I286 out_data8_ax(void) { // E7: out DATA8, ax + + __asm { + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + movzx ecx, bh + push ecx + GET_NEXTPRE2 + pop ecx + mov dx, I286_AX + jmp iocore_out16 + } +} + +I286 call_near(void) { // E8: call near + + __asm { + //I286CLOCK(7) + I286CLOCK_X(a, 7, (16+4)) + shr ebx, 8 + add si, 3 + mov dx, si + add si, bx + RESET_XPREFETCH + sub I286_SP, 2 + movzx ecx, I286_SP + add ecx, SS_BASE + jmp i286_memorywrite_w + } +} + +I286 jmp_near(void) { // E9: jmp near + + __asm { + //I286CLOCK(7) + I286CLOCK_X(a, 7, (13+4)) + shr ebx, 8 + add si, 3 + add si, bx + RESET_XPREFETCH + ret + } +} + +I286 jmp_far(void) { // EA: jmp far + + __asm { + //I286CLOCK(11) + I286CLOCK_X(a, 11, (15+4)) + GET_NEXTPRE1 + mov si, bx + shr ebx, 16 + mov I286_CS, bx + test byte ptr (I286_MSW), MSW_PE + jne short jmp_far_pe + shl ebx, 4 // make segreg + mov CS_BASE, ebx +jmp_far_base: RESET_XPREFETCH + ret + +jmp_far_pe: mov eax, ebx + call i286x_selector + mov CS_BASE, eax + jmp short jmp_far_base + } +} + +I286 jmp_short(void) { // EB: jmp short + + __asm { + //I286CLOCK(7) + I286CLOCK_X(a, 7, (12+4)) + movsx eax, bh + add si, ax + add si, 2 + RESET_XPREFETCH + ret + } +} + +I286 in_al_dx(void) { // EC: in al, dx + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + movzx ecx, I286_DX + call iocore_inp8 + mov I286_AL, al + GET_NEXTPRE1 + ret + } +} + +I286 in_ax_dx(void) { // ED: in ax, dx + + __asm { + //I286CLOCK(5) + I286CLOCK_X(a, 5, 8) + movzx ecx, I286_DX + call iocore_inp16 + mov I286_AX, ax + GET_NEXTPRE1 + ret + } +} + +I286 out_dx_al(void) { // EE: out dx, al + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + movzx ecx, I286_DX + mov dl, I286_AL + jmp iocore_out8 + } +} + +I286 out_dx_ax(void) { // EF: out dx, ax + + __asm { + GET_NEXTPRE1 + //I286CLOCK(3) + I286CLOCK_X(a, 3, 8) + movzx ecx, I286_DX + mov dx, I286_AX + jmp iocore_out16 + } +} + +I286 _lock(void) { // F0: lock + + __asm { + GET_NEXTPRE1 + ret + } +} + +I286 _repne(void) { // F2: repne + + __asm { + I286PREFIX(i286op_repne) + } +} + +I286 _repe(void) { // F3: repe + + __asm { + I286PREFIX(i286op_repe) + } +} + +I286 _hlt(void) { // F4: hlt + + __asm { + mov I286_REMCLOCK, -1 + ret + } +} + +I286 _cmc(void) { // F5: cmc + + __asm { + I286CLOCK(2) + xor I286_FLAG, C_FLAG + GET_NEXTPRE1 + ret + } +} + +I286 _ope0xf6(void) { // F6: + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 + jmp ope0xf6_xtable[edi] + } +} + +I286 _ope0xf7(void) { // F7: + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 + jmp ope0xf7_xtable[edi] + } +} + +I286 _clc(void) { // F8: clc + + __asm { + GET_NEXTPRE1 + I286CLOCK(2) + and I286_FLAG, not C_FLAG + ret + } +} + +I286 _stc(void) { // F9: stc + + __asm { + GET_NEXTPRE1 + I286CLOCK(2) + or I286_FLAG, C_FLAG + ret + } +} + +I286 _cli(void) { // FA: cli + + __asm { + GET_NEXTPRE1 + I286CLOCK(2) + and I286_FLAG, not I_FLAG +#if defined(VAEG_FIX) + // シングルステップ割り込みは割り込み許可フラグの影響を受けない +#else + mov I286_TRAP, 0 +#endif + ret + } +} + +I286 _sti(void) { // FB: sti + + __asm { + GET_NEXTPRE1 + I286CLOCK(2) + cmp i286core.s.prefix, 0 // ver0.26 00/10/08 + jne prefix_exist // 前方分岐ジャンプなので。 + noprefix: + movzx ebp, bl + bts I286_FLAG, 9 + jne jmp_nextop +#if defined(VAEG_FIX) + // シングルステップ割り込みは割り込み許可フラグの影響を受けない +#else + test I286_FLAG, T_FLAG + setne I286_TRAP +#endif + + jne nextopandexit // fast_intr + mov al, pic.pi[0 * (type _PICITEM)].imr + mov ah, pic.pi[1 * (type _PICITEM)].imr + not ax + test al, pic.pi[0 * (type _PICITEM)].irr + jne nextopandexit + test ah, pic.pi[1 * (type _PICITEM)].irr + jne nextopandexit +jmp_nextop: jmp i286op[ebp*4] + +nextopandexit: call i286op[ebp*4] + I286IRQCHECKTERM + +prefix_exist: pop eax // eax<-offset removeprefix + call eax + jmp noprefix + } +} + +I286 _cld(void) { // FC: cld + + __asm { + GET_NEXTPRE1 + I286CLOCK(2) + and I286_FLAG, not D_FLAG + ret + } +} + +I286 _std(void) { // FD: std + + __asm { + GET_NEXTPRE1 + I286CLOCK(2) + or I286_FLAG, D_FLAG + ret + } +} + +I286 _ope0xfe(void) { // FE: + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 1*4 + jmp ope0xfe_xtable[edi] + } +} + +I286 _ope0xff(void) { // FF: + + __asm { + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 + jmp ope0xff_xtable[edi] + } +} + + +// ------------------------------------------------------------------------- + +const I286TBL i286op[256] = { + add_ea_r8, // 00: add EA, REG8 + add_ea_r16, // 01: add EA, REG16 + add_r8_ea, // 02: add REG8, EA + add_r16_ea, // 03: add REG16, EA + add_al_data8, // 04: add al, DATA8 + add_ax_data16, // 05: add ax, DATA16 + push_es, // 06: push es + pop_es, // 07: pop es + or_ea_r8, // 08: or EA, REGF8 + or_ea_r16, // 09: or EA, REG16 + or_r8_ea, // 0A: or REG8, EA + or_r16_ea, // 0B: or REG16, EA + or_al_data8, // 0C: or al, DATA8 + or_ax_data16, // 0D: or ax, DATA16 + push_cs, // 0E: push cs + _xcts, // 0F: i286 upper opcode + + adc_ea_r8, // 10: adc EA, REG8 + adc_ea_r16, // 11: adc EA, REG16 + adc_r8_ea, // 12: adc REG8, EA + adc_r16_ea, // 13: adc REG16, EA + adc_al_data8, // 14: adc al, DATA8 + adc_ax_data16, // 15: adc ax, DATA16 + push_ss, // 16: push ss + pop_ss, // 17: pop ss + sbb_ea_r8, // 18: sbb EA, REG8 + sbb_ea_r16, // 19: sbb EA, REG16 + sbb_r8_ea, // 1A: sbb REG8, EA + sbb_r16_ea, // 1B: sbb REG16, EA + sbb_al_data8, // 1C: sbb al, DATA8 + sbb_ax_data16, // 1D: sbb ax, DATA16 + push_ds, // 1E: push ds + pop_ds, // 1F: pop ds + + and_ea_r8, // 20: and EA, REG8 + and_ea_r16, // 21: and EA, REG16 + and_r8_ea, // 22: and REG8, EA + and_r16_ea, // 23: and REG16, EA + and_al_data8, // 24: and al, DATA8 + and_ax_data16, // 25: and ax, DATA16 + segprefix_es, // 26: es: + _daa, // 27: daa + sub_ea_r8, // 28: sub EA, REG8 + sub_ea_r16, // 29: sub EA, REG16 + sub_r8_ea, // 2A: sub REG8, EA + sub_r16_ea, // 2B: sub REG16, EA + sub_al_data8, // 2C: sub al, DATA8 + sub_ax_data16, // 2D: sub ax, DATA16 + segprefix_cs, // 2E: cs: + _das, // 2F: das + + xor_ea_r8, // 30: xor EA, REG8 + xor_ea_r16, // 31: xor EA, REG16 + xor_r8_ea, // 32: xor REG8, EA + xor_r16_ea, // 33: xor REG16, EA + xor_al_data8, // 34: xor al, DATA8 + xor_ax_data16, // 35: xor ax, DATA16 + segprefix_ss, // 36: ss: + _aaa, // 37: aaa + cmp_ea_r8, // 38: cmp EA, REG8 + cmp_ea_r16, // 39: cmp EA, REG16 + cmp_r8_ea, // 3A: cmp REG8, EA + cmp_r16_ea, // 3B: cmp REG16, EA + cmp_al_data8, // 3C: cmp al, DATA8 + cmp_ax_data16, // 3D: cmp ax, DATA16 + segprefix_ds, // 3E: ds: + _aas, // 3F: aas + + inc_ax, // 40: inc ax + inc_cx, // 41: inc cx + inc_dx, // 42: inc dx + inc_bx, // 43: inc bx + inc_sp, // 44: inc sp + inc_bp, // 45: inc bp + inc_si, // 46: inc si + inc_di, // 47: inc di + dec_ax, // 48: dec ax + dec_cx, // 49: dec cx + dec_dx, // 4A: dec dx + dec_bx, // 4B: dec bx + dec_sp, // 4C: dec sp + dec_bp, // 4D: dec bp + dec_si, // 4E: dec si + dec_di, // 4F: dec di + + push_ax, // 50: push ax + push_cx, // 51: push cx + push_dx, // 52: push dx + push_bx, // 53: push bx + push_sp, // 54: push sp + push_bp, // 55: push bp + push_si, // 56: push si + push_di, // 57: push di + pop_ax, // 58: pop ax + pop_cx, // 59: pop cx + pop_dx, // 5A: pop dx + pop_bx, // 5B: pop bx + pop_sp, // 5C: pop sp + pop_bp, // 5D: pop bp + pop_si, // 5E: pop si + pop_di, // 5F: pop di + + _pusha, // 60: pusha + _popa, // 61: popa + _bound, // 62: bound + _arpl, // 63: arpl + _reserved, // 64: reserved + _reserved, // 65: reserved + _reserved, // 66: reserved + _reserved, // 67: reserved + push_data16, // 68: push DATA16 + imul_reg_ea_data16, // 69: imul REG, EA, DATA16 + push_data8, // 6A: push DATA8 + imul_reg_ea_data8, // 6B: imul REG, EA, DATA8 + _insb, // 6C: insb + _insw, // 6D: insw + _outsb, // 6E: outsb + _outsw, // 6F: outsw + + jo_short, // 70: jo short + jno_short, // 71: jno short + jc_short, // 72: jnae/jb/jc short + jnc_short, // 73: jae/jnb/jnc short + jz_short, // 74: je/jz short + jnz_short, // 75: jne/jnz short + jna_short, // 76: jna/jbe short + ja_short, // 77: ja/jnbe short + js_short, // 78: js short + jns_short, // 79: jns short + jp_short, // 7A: jp/jpe short + jnp_short, // 7B: jnp/jpo short + jl_short, // 7C: jl/jnge short + jnl_short, // 7D: jnl/jge short + jle_short, // 7E: jle/jng short + jnle_short, // 7F: jg/jnle short + + calc_ea8_i8, // 80: op EA8, DATA8 + calc_ea16_i16, // 81: op EA16, DATA16 + calc_ea8_i8, // 82: op EA8, DATA8 + calc_ea16_i8, // 83: op EA16, DATA8 + test_ea_r8, // 84: test EA, REG8 + test_ea_r16, // 85: test EA, REG16 + xchg_ea_r8, // 86: xchg EA, REG8 + xchg_ea_r16, // 87: xchg EA, REG16 + mov_ea_r8, // 88: mov EA, REG8 + mov_ea_r16, // 89: mov EA, REG16 + mov_r8_ea, // 8A: mov REG8, EA + mov_r16_ea, // 8B: add REG16, EA + mov_ea_seg, // 8C: mov EA, segreg + lea_r16_ea, // 8D: lea REG16, EA + mov_seg_ea, // 8E: mov segrem, EA + pop_ea, // 8F: pop EA + + _nop, // 90: xchg ax, ax + xchg_ax_cx, // 91: xchg ax, cx + xchg_ax_dx, // 92: xchg ax, dx + xchg_ax_bx, // 93: xchg ax, bx + xchg_ax_sp, // 94: xchg ax, sp + xchg_ax_bp, // 95: xchg ax, bp + xchg_ax_si, // 96: xchg ax, si + xchg_ax_di, // 97: xchg ax, di + _cbw, // 98: cbw + _cwd, // 99: cwd + call_far, // 9A: call far + _wait, // 9B: wait + _pushf, // 9C: pushf + _popf, // 9D: popf + _sahf, // 9E: sahf + _lahf, // 9F: lahf + + mov_al_m8, // A0: mov al, m8 + mov_ax_m16, // A1: mov ax, m16 + mov_m8_al, // A2: mov m8, al + mov_m16_ax, // A3: mov m16, ax + _movsb, // A4: movsb + _movsw, // A5: movsw + _cmpsb, // A6: cmpsb + _cmpsw, // A7: cmpsw + test_al_data8, // A8: test al, DATA8 + test_ax_data16, // A9: test ax, DATA16 + _stosb, // AA: stosw + _stosw, // AB: stosw + _lodsb, // AC: lodsb + _lodsw, // AD: lodsw + _scasb, // AE: scasb + _scasw, // AF: scasw + + mov_al_imm, // B0: mov al, imm8 + mov_cl_imm, // B1: mov cl, imm8 + mov_dl_imm, // B2: mov dl, imm8 + mov_bl_imm, // B3: mov bl, imm8 + mov_ah_imm, // B4: mov ah, imm8 + mov_ch_imm, // B5: mov ch, imm8 + mov_dh_imm, // B6: mov dh, imm8 + mov_bh_imm, // B7: mov bh, imm8 + mov_ax_imm, // B8: mov ax, imm16 + mov_cx_imm, // B9: mov cx, imm16 + mov_dx_imm, // BA: mov dx, imm16 + mov_bx_imm, // BB: mov bx, imm16 + mov_sp_imm, // BC: mov sp, imm16 + mov_bp_imm, // BD: mov bp, imm16 + mov_si_imm, // BE: mov si, imm16 + mov_di_imm, // BF: mov di, imm16 + + shift_ea8_data8, // C0: shift EA8, DATA8 + shift_ea16_data8, // C1: shift EA16, DATA8 + ret_near_data16, // C2: ret near DATA16 + ret_near, // C3: ret near + les_r16_ea, // C4: les REG16, EA + lds_r16_ea, // C5: lds REG16, EA + mov_ea8_data8, // C6: mov EA8, DATA8 + mov_ea16_data16, // C7: mov EA16, DATA16 + _enter, // C8: enter DATA16, DATA8 + leave, // C9: leave + ret_far_data16, // CA: ret far DATA16 + ret_far, // CB: ret far + int_03, // CC: int 3 + int_data8, // CD: int DATA8 + _into, // CE: into + _iret, // CF: iret + + shift_ea8_1, // D0: shift EA8, 1 + shift_ea16_1, // D1: shift EA16, 1 + shift_ea8_cl, // D2: shift EA8, cl + shift_ea16_cl, // D3: shift EA16, cl + _aam, // D4: AAM + _aad, // D5: AAD + _setalc, // D6: setalc (80286) + _xlat, // D7: xlat + _esc, // D8: esc + _esc, // D9: esc + _esc, // DA: esc + _esc, // DB: esc + _esc, // DC: esc + _esc, // DD: esc + _esc, // DE: esc + _esc, // DF: esc + + _loopnz, // E0: loopnz + _loopz, // E1: loopz + _loop, // E2: loop + _jcxz, // E3: jcxz + in_al_data8, // E4: in al, DATA8 + in_ax_data8, // E5: in ax, DATA8 + out_data8_al, // E6: out DATA8, al + out_data8_ax, // E7: out DATA8, ax + call_near, // E8: call near + jmp_near, // E9: jmp near + jmp_far, // EA: jmp far + jmp_short, // EB: jmp short + in_al_dx, // EC: in al, dx + in_ax_dx, // ED: in ax, dx + out_dx_al, // EE: out dx, al + out_dx_ax, // EF: out dx, ax + + _lock, // F0: lock + _lock, // F1: lock + _repne, // F2: repne + _repe, // F3: repe + _hlt, // F4: hlt + _cmc, // F5: cmc + _ope0xf6, // F6: + _ope0xf7, // F7: + _clc, // F8: clc + _stc, // F9: stc + _cli, // FA: cli + _sti, // FB: sti + _cld, // FC: cld + _std, // FD: std + _ope0xfe, // FE: + _ope0xff, // FF: +}; + +// ----------------------------------------------------------------- repe + +I286 repe_segprefix_es(void) { + + __asm { + mov eax, ES_BASE + mov DS_FIX, eax + mov SS_FIX, eax + GET_NEXTPRE1 + movzx eax, bl + jmp i286op_repe[eax*4] + } +} + +I286 repe_segprefix_cs(void) { + + __asm { + mov eax, CS_BASE + mov DS_FIX, eax + mov SS_FIX, eax + GET_NEXTPRE1 + movzx eax, bl + jmp i286op_repe[eax*4] + } +} + +I286 repe_segprefix_ss(void) { + + __asm { + mov eax, SS_BASE + mov DS_FIX, eax + mov SS_FIX, eax + GET_NEXTPRE1 + movzx eax, bl + jmp i286op_repe[eax*4] + } +} + +I286 repe_segprefix_ds(void) { + + __asm { + mov eax, DS_BASE + mov DS_FIX, eax + mov SS_FIX, eax + GET_NEXTPRE1 + movzx eax, bl + jmp i286op_repe[eax*4] + } +} + +const I286TBL i286op_repe[256] = { + add_ea_r8, // 00: add EA, REG8 + add_ea_r16, // 01: add EA, REG16 + add_r8_ea, // 02: add REG8, EA + add_r16_ea, // 03: add REG16, EA + add_al_data8, // 04: add al, DATA8 + add_ax_data16, // 05: add ax, DATA16 + push_es, // 06: push es + pop_es, // 07: pop es + or_ea_r8, // 08: or EA, REGF8 + or_ea_r16, // 09: or EA, REG16 + or_r8_ea, // 0A: or REG8, EA + or_r16_ea, // 0B: or REG16, EA + or_al_data8, // 0C: or al, DATA8 + or_ax_data16, // 0D: or ax, DATA16 + push_cs, // 0E: push cs + _xcts, // 0F: i286 upper opcode + + adc_ea_r8, // 10: adc EA, REG8 + adc_ea_r16, // 11: adc EA, REG16 + adc_r8_ea, // 12: adc REG8, EA + adc_r16_ea, // 13: adc REG16, EA + adc_al_data8, // 14: adc al, DATA8 + adc_ax_data16, // 15: adc ax, DATA16 + push_ss, // 16: push ss + pop_ss, // 17: pop ss + sbb_ea_r8, // 18: sbb EA, REG8 + sbb_ea_r16, // 19: sbb EA, REG16 + sbb_r8_ea, // 1A: sbb REG8, EA + sbb_r16_ea, // 1B: sbb REG16, EA + sbb_al_data8, // 1C: sbb al, DATA8 + sbb_ax_data16, // 1D: sbb ax, DATA16 + push_ds, // 1E: push ds + pop_ds, // 1F: pop ds + + and_ea_r8, // 20: and EA, REG8 + and_ea_r16, // 21: and EA, REG16 + and_r8_ea, // 22: and REG8, EA + and_r16_ea, // 23: and REG16, EA + and_al_data8, // 24: and al, DATA8 + and_ax_data16, // 25: and ax, DATA16 + repe_segprefix_es, // 26: repe es: + _daa, // 27: daa + sub_ea_r8, // 28: sub EA, REG8 + sub_ea_r16, // 29: sub EA, REG16 + sub_r8_ea, // 2A: sub REG8, EA + sub_r16_ea, // 2B: sub REG16, EA + sub_al_data8, // 2C: sub al, DATA8 + sub_ax_data16, // 2D: sub ax, DATA16 + repe_segprefix_cs, // 2E: repe cs: + _das, // 2F: das + + xor_ea_r8, // 30: xor EA, REG8 + xor_ea_r16, // 31: xor EA, REG16 + xor_r8_ea, // 32: xor REG8, EA + xor_r16_ea, // 33: xor REG16, EA + xor_al_data8, // 34: xor al, DATA8 + xor_ax_data16, // 35: xor ax, DATA16 + repe_segprefix_ss, // 36: repe ss: + _aaa, // 37: aaa + cmp_ea_r8, // 38: cmp EA, REG8 + cmp_ea_r16, // 39: cmp EA, REG16 + cmp_r8_ea, // 3A: cmp REG8, EA + cmp_r16_ea, // 3B: cmp REG16, EA + cmp_al_data8, // 3C: cmp al, DATA8 + cmp_ax_data16, // 3D: cmp ax, DATA16 + repe_segprefix_ds, // 3E: repe ds: + _aas, // 3F: aas + + inc_ax, // 40: inc ax + inc_cx, // 41: inc cx + inc_dx, // 42: inc dx + inc_bx, // 43: inc bx + inc_sp, // 44: inc sp + inc_bp, // 45: inc bp + inc_si, // 46: inc si + inc_di, // 47: inc di + dec_ax, // 48: dec ax + dec_cx, // 49: dec cx + dec_dx, // 4A: dec dx + dec_bx, // 4B: dec bx + dec_sp, // 4C: dec sp + dec_bp, // 4D: dec bp + dec_si, // 4E: dec si + dec_di, // 4F: dec di + + push_ax, // 50: push ax + push_cx, // 51: push cx + push_dx, // 52: push dx + push_bx, // 53: push bx + push_sp, // 54: push sp + push_bp, // 55: push bp + push_si, // 56: push si + push_di, // 57: push di + pop_ax, // 58: pop ax + pop_cx, // 59: pop cx + pop_dx, // 5A: pop dx + pop_bx, // 5B: pop bx + pop_sp, // 5C: pop sp + pop_bp, // 5D: pop bp + pop_si, // 5E: pop si + pop_di, // 5F: pop di + + _pusha, // 60: pusha + _popa, // 61: popa + _bound, // 62: bound + _arpl, // 63: arpl + _reserved, // 64: reserved + _reserved, // 65: reserved + _reserved, // 66: reserved + _reserved, // 67: reserved + push_data16, // 68: push DATA16 + imul_reg_ea_data16, // 69: imul REG, EA, DATA16 + push_data8, // 6A: push DATA8 + imul_reg_ea_data8, // 6B: imul REG, EA, DATA8 + rep_xinsb, // 6C: rep insb + rep_xinsw, // 6D: rep insw + rep_xoutsb, // 6E: rep outsb + rep_xoutsw, // 6F: rep outsw + + jo_short, // 70: jo short + jno_short, // 71: jno short + jc_short, // 72: jnae/jb/jc short + jnc_short, // 73: jae/jnb/jnc short + jz_short, // 74: je/jz short + jnz_short, // 75: jne/jnz short + jna_short, // 76: jna/jbe short + ja_short, // 77: ja/jnbe short + js_short, // 78: js short + jns_short, // 79: jns short + jp_short, // 7A: jp/jpe short + jnp_short, // 7B: jnp/jpo short + jl_short, // 7C: jl/jnge short + jnl_short, // 7D: jnl/jge short + jle_short, // 7E: jle/jng short + jnle_short, // 7F: jg/jnle short + + calc_ea8_i8, // 80: op EA8, DATA8 + calc_ea16_i16, // 81: op EA16, DATA16 + calc_ea8_i8, // 82: op EA8, DATA8 + calc_ea16_i8, // 83: op EA16, DATA8 + test_ea_r8, // 84: test EA, REG8 + test_ea_r16, // 85: test EA, REG16 + xchg_ea_r8, // 86: xchg EA, REG8 + xchg_ea_r16, // 87: xchg EA, REG16 + mov_ea_r8, // 88: mov EA, REG8 + mov_ea_r16, // 89: mov EA, REG16 + mov_r8_ea, // 8A: mov REG8, EA + mov_r16_ea, // 8B: add REG16, EA + mov_ea_seg, // 8C: mov EA, segreg + lea_r16_ea, // 8D: lea REG16, EA + mov_seg_ea, // 8E: mov segrem, EA + pop_ea, // 8F: pop EA + + _nop, // 90: xchg ax, ax + xchg_ax_cx, // 91: xchg ax, cx + xchg_ax_dx, // 92: xchg ax, dx + xchg_ax_bx, // 93: xchg ax, bx + xchg_ax_sp, // 94: xchg ax, sp + xchg_ax_bp, // 95: xchg ax, bp + xchg_ax_si, // 96: xchg ax, si + xchg_ax_di, // 97: xchg ax, di + _cbw, // 98: cbw + _cwd, // 99: cwd + call_far, // 9A: call far + _wait, // 9B: wait + _pushf, // 9C: pushf + _popf, // 9D: popf + _sahf, // 9E: sahf + _lahf, // 9F: lahf + + mov_al_m8, // A0: mov al, m8 + mov_ax_m16, // A1: mov ax, m16 + mov_m8_al, // A2: mov m8, al + mov_m16_ax, // A3: mov m16, ax + rep_xmovsb, // A4: rep movsb + rep_xmovsw, // A5: rep movsw + repe_xcmpsb, // A6: repe cmpsb + repe_xcmpsw, // A7: repe cmpsw + test_al_data8, // A8: test al, DATA8 + test_ax_data16, // A9: test ax, DATA16 + rep_xstosb, // AA: rep stosw + rep_xstosw, // AB: rep stosw + rep_xlodsb, // AC: rep lodsb + rep_xlodsw, // AD: rep lodsw + repe_xscasb, // AE: repe scasb + repe_xscasw, // AF: repe scasw + + mov_al_imm, // B0: mov al, imm8 + mov_cl_imm, // B1: mov cl, imm8 + mov_dl_imm, // B2: mov dl, imm8 + mov_bl_imm, // B3: mov bl, imm8 + mov_ah_imm, // B4: mov ah, imm8 + mov_ch_imm, // B5: mov ch, imm8 + mov_dh_imm, // B6: mov dh, imm8 + mov_bh_imm, // B7: mov bh, imm8 + mov_ax_imm, // B8: mov ax, imm16 + mov_cx_imm, // B9: mov cx, imm16 + mov_dx_imm, // BA: mov dx, imm16 + mov_bx_imm, // BB: mov bx, imm16 + mov_sp_imm, // BC: mov sp, imm16 + mov_bp_imm, // BD: mov bp, imm16 + mov_si_imm, // BE: mov si, imm16 + mov_di_imm, // BF: mov di, imm16 + + shift_ea8_data8, // C0: shift EA8, DATA8 + shift_ea16_data8, // C1: shift EA16, DATA8 + ret_near_data16, // C2: ret near DATA16 + ret_near, // C3: ret near + les_r16_ea, // C4: les REG16, EA + lds_r16_ea, // C5: lds REG16, EA + mov_ea8_data8, // C6: mov EA8, DATA8 + mov_ea16_data16, // C7: mov EA16, DATA16 + _enter, // C8: enter DATA16, DATA8 + leave, // C9: leave + ret_far_data16, // CA: ret far DATA16 + ret_far, // CB: ret far + int_03, // CC: int 3 + int_data8, // CD: int DATA8 + _into, // CE: into + _iret, // CF: iret + + shift_ea8_1, // D0: shift EA8, 1 + shift_ea16_1, // D1: shift EA16, 1 + shift_ea8_cl, // D2: shift EA8, cl + shift_ea16_cl, // D3: shift EA16, cl + _aam, // D4: AAM + _aad, // D5: AAD + _setalc, // D6: setalc (80286) + _xlat, // D7: xlat + _esc, // D8: esc + _esc, // D9: esc + _esc, // DA: esc + _esc, // DB: esc + _esc, // DC: esc + _esc, // DD: esc + _esc, // DE: esc + _esc, // DF: esc + + _loopnz, // E0: loopnz + _loopz, // E1: loopz + _loop, // E2: loop + _jcxz, // E3: jcxz + in_al_data8, // E4: in al, DATA8 + in_ax_data8, // E5: in ax, DATA8 + out_data8_al, // E6: out DATA8, al + out_data8_ax, // E7: out DATA8, ax + call_near, // E8: call near + jmp_near, // E9: jmp near + jmp_far, // EA: jmp far + jmp_short, // EB: jmp short + in_al_dx, // EC: in al, dx + in_ax_dx, // ED: in ax, dx + out_dx_al, // EE: out dx, al + out_dx_ax, // EF: out dx, ax + + _lock, // F0: lock + _lock, // F1: lock + _repne, // F2: repne + _repe, // F3: repe + _hlt, // F4: hlt + _cmc, // F5: cmc + _ope0xf6, // F6: + _ope0xf7, // F7: + _clc, // F8: clc + _stc, // F9: stc + _cli, // FA: cli + _sti, // FB: sti + _cld, // FC: cld + _std, // FD: std + _ope0xfe, // FE: + _ope0xff, // FF: +}; + +// ----------------------------------------------------------------- repne + +I286 repne_segprefix_es(void) { + + __asm { + mov eax, ES_BASE + mov DS_FIX, eax + mov SS_FIX, eax + GET_NEXTPRE1 + movzx eax, bl + jmp i286op_repne[eax*4] + } +} + +I286 repne_segprefix_cs(void) { + + __asm { + mov eax, CS_BASE + mov DS_FIX, eax + mov SS_FIX, eax + GET_NEXTPRE1 + movzx eax, bl + jmp i286op_repne[eax*4] + } +} + +I286 repne_segprefix_ss(void) { + + __asm { + mov eax, SS_BASE + mov DS_FIX, eax + mov SS_FIX, eax + GET_NEXTPRE1 + movzx eax, bl + jmp i286op_repne[eax*4] + } +} + +I286 repne_segprefix_ds(void) { + + __asm { + mov eax, DS_BASE + mov DS_FIX, eax + mov SS_FIX, eax + GET_NEXTPRE1 + movzx eax, bl + jmp i286op_repne[eax*4] + } +} + +const I286TBL i286op_repne[256] = { + add_ea_r8, // 00: add EA, REG8 + add_ea_r16, // 01: add EA, REG16 + add_r8_ea, // 02: add REG8, EA + add_r16_ea, // 03: add REG16, EA + add_al_data8, // 04: add al, DATA8 + add_ax_data16, // 05: add ax, DATA16 + push_es, // 06: push es + pop_es, // 07: pop es + or_ea_r8, // 08: or EA, REGF8 + or_ea_r16, // 09: or EA, REG16 + or_r8_ea, // 0A: or REG8, EA + or_r16_ea, // 0B: or REG16, EA + or_al_data8, // 0C: or al, DATA8 + or_ax_data16, // 0D: or ax, DATA16 + push_cs, // 0E: push cs + _xcts, // 0F: i286 upper opcode + + adc_ea_r8, // 10: adc EA, REG8 + adc_ea_r16, // 11: adc EA, REG16 + adc_r8_ea, // 12: adc REG8, EA + adc_r16_ea, // 13: adc REG16, EA + adc_al_data8, // 14: adc al, DATA8 + adc_ax_data16, // 15: adc ax, DATA16 + push_ss, // 16: push ss + pop_ss, // 17: pop ss + sbb_ea_r8, // 18: sbb EA, REG8 + sbb_ea_r16, // 19: sbb EA, REG16 + sbb_r8_ea, // 1A: sbb REG8, EA + sbb_r16_ea, // 1B: sbb REG16, EA + sbb_al_data8, // 1C: sbb al, DATA8 + sbb_ax_data16, // 1D: sbb ax, DATA16 + push_ds, // 1E: push ds + pop_ds, // 1F: pop ds + + and_ea_r8, // 20: and EA, REG8 + and_ea_r16, // 21: and EA, REG16 + and_r8_ea, // 22: and REG8, EA + and_r16_ea, // 23: and REG16, EA + and_al_data8, // 24: and al, DATA8 + and_ax_data16, // 25: and ax, DATA16 + repne_segprefix_es, // 26: repne es: + _daa, // 27: daa + sub_ea_r8, // 28: sub EA, REG8 + sub_ea_r16, // 29: sub EA, REG16 + sub_r8_ea, // 2A: sub REG8, EA + sub_r16_ea, // 2B: sub REG16, EA + sub_al_data8, // 2C: sub al, DATA8 + sub_ax_data16, // 2D: sub ax, DATA16 + repne_segprefix_cs, // 2E: repne cs: + _das, // 2F: das + + xor_ea_r8, // 30: xor EA, REG8 + xor_ea_r16, // 31: xor EA, REG16 + xor_r8_ea, // 32: xor REG8, EA + xor_r16_ea, // 33: xor REG16, EA + xor_al_data8, // 34: xor al, DATA8 + xor_ax_data16, // 35: xor ax, DATA16 + repne_segprefix_ss, // 36: repne ss: + _aaa, // 37: aaa + cmp_ea_r8, // 38: cmp EA, REG8 + cmp_ea_r16, // 39: cmp EA, REG16 + cmp_r8_ea, // 3A: cmp REG8, EA + cmp_r16_ea, // 3B: cmp REG16, EA + cmp_al_data8, // 3C: cmp al, DATA8 + cmp_ax_data16, // 3D: cmp ax, DATA16 + repne_segprefix_ds, // 3E: repne ds: + _aas, // 3F: aas + + inc_ax, // 40: inc ax + inc_cx, // 41: inc cx + inc_dx, // 42: inc dx + inc_bx, // 43: inc bx + inc_sp, // 44: inc sp + inc_bp, // 45: inc bp + inc_si, // 46: inc si + inc_di, // 47: inc di + dec_ax, // 48: dec ax + dec_cx, // 49: dec cx + dec_dx, // 4A: dec dx + dec_bx, // 4B: dec bx + dec_sp, // 4C: dec sp + dec_bp, // 4D: dec bp + dec_si, // 4E: dec si + dec_di, // 4F: dec di + + push_ax, // 50: push ax + push_cx, // 51: push cx + push_dx, // 52: push dx + push_bx, // 53: push bx + push_sp, // 54: push sp + push_bp, // 55: push bp + push_si, // 56: push si + push_di, // 57: push di + pop_ax, // 58: pop ax + pop_cx, // 59: pop cx + pop_dx, // 5A: pop dx + pop_bx, // 5B: pop bx + pop_sp, // 5C: pop sp + pop_bp, // 5D: pop bp + pop_si, // 5E: pop si + pop_di, // 5F: pop di + + _pusha, // 60: pusha + _popa, // 61: popa + _bound, // 62: bound + _arpl, // 63: arpl + _reserved, // 64: reserved + _reserved, // 65: reserved + _reserved, // 66: reserved + _reserved, // 67: reserved + push_data16, // 68: push DATA16 + imul_reg_ea_data16, // 69: imul REG, EA, DATA16 + push_data8, // 6A: push DATA8 + imul_reg_ea_data8, // 6B: imul REG, EA, DATA8 + rep_xinsb, // 6C: rep insb + rep_xinsw, // 6D: rep insw + rep_xoutsb, // 6E: rep outsb + rep_xoutsw, // 6F: rep outsw + + jo_short, // 70: jo short + jno_short, // 71: jno short + jc_short, // 72: jnae/jb/jc short + jnc_short, // 73: jae/jnb/jnc short + jz_short, // 74: je/jz short + jnz_short, // 75: jne/jnz short + jna_short, // 76: jna/jbe short + ja_short, // 77: ja/jnbe short + js_short, // 78: js short + jns_short, // 79: jns short + jp_short, // 7A: jp/jpe short + jnp_short, // 7B: jnp/jpo short + jl_short, // 7C: jl/jnge short + jnl_short, // 7D: jnl/jge short + jle_short, // 7E: jle/jng short + jnle_short, // 7F: jg/jnle short + + calc_ea8_i8, // 80: op EA8, DATA8 + calc_ea16_i16, // 81: op EA16, DATA16 + calc_ea8_i8, // 82: op EA8, DATA8 + calc_ea16_i8, // 83: op EA16, DATA8 + test_ea_r8, // 84: test EA, REG8 + test_ea_r16, // 85: test EA, REG16 + xchg_ea_r8, // 86: xchg EA, REG8 + xchg_ea_r16, // 87: xchg EA, REG16 + mov_ea_r8, // 88: mov EA, REG8 + mov_ea_r16, // 89: mov EA, REG16 + mov_r8_ea, // 8A: mov REG8, EA + mov_r16_ea, // 8B: add REG16, EA + mov_ea_seg, // 8C: mov EA, segreg + lea_r16_ea, // 8D: lea REG16, EA + mov_seg_ea, // 8E: mov segrem, EA + pop_ea, // 8F: pop EA + + _nop, // 90: xchg ax, ax + xchg_ax_cx, // 91: xchg ax, cx + xchg_ax_dx, // 92: xchg ax, dx + xchg_ax_bx, // 93: xchg ax, bx + xchg_ax_sp, // 94: xchg ax, sp + xchg_ax_bp, // 95: xchg ax, bp + xchg_ax_si, // 96: xchg ax, si + xchg_ax_di, // 97: xchg ax, di + _cbw, // 98: cbw + _cwd, // 99: cwd + call_far, // 9A: call far + _wait, // 9B: wait + _pushf, // 9C: pushf + _popf, // 9D: popf + _sahf, // 9E: sahf + _lahf, // 9F: lahf + + mov_al_m8, // A0: mov al, m8 + mov_ax_m16, // A1: mov ax, m16 + mov_m8_al, // A2: mov m8, al + mov_m16_ax, // A3: mov m16, ax + rep_xmovsb, // A4: rep movsb + rep_xmovsw, // A5: rep movsw + repne_xcmpsb, // A6: repne cmpsb + repne_xcmpsw, // A7: repne cmpsw + test_al_data8, // A8: test al, DATA8 + test_ax_data16, // A9: test ax, DATA16 + rep_xstosb, // AA: rep stosw + rep_xstosw, // AB: rep stosw + rep_xlodsb, // AC: rep lodsb + rep_xlodsw, // AD: rep lodsw + repne_xscasb, // AE: repne scasb + repne_xscasw, // AF: repne scasw + + mov_al_imm, // B0: mov al, imm8 + mov_cl_imm, // B1: mov cl, imm8 + mov_dl_imm, // B2: mov dl, imm8 + mov_bl_imm, // B3: mov bl, imm8 + mov_ah_imm, // B4: mov ah, imm8 + mov_ch_imm, // B5: mov ch, imm8 + mov_dh_imm, // B6: mov dh, imm8 + mov_bh_imm, // B7: mov bh, imm8 + mov_ax_imm, // B8: mov ax, imm16 + mov_cx_imm, // B9: mov cx, imm16 + mov_dx_imm, // BA: mov dx, imm16 + mov_bx_imm, // BB: mov bx, imm16 + mov_sp_imm, // BC: mov sp, imm16 + mov_bp_imm, // BD: mov bp, imm16 + mov_si_imm, // BE: mov si, imm16 + mov_di_imm, // BF: mov di, imm16 + + shift_ea8_data8, // C0: shift EA8, DATA8 + shift_ea16_data8, // C1: shift EA16, DATA8 + ret_near_data16, // C2: ret near DATA16 + ret_near, // C3: ret near + les_r16_ea, // C4: les REG16, EA + lds_r16_ea, // C5: lds REG16, EA + mov_ea8_data8, // C6: mov EA8, DATA8 + mov_ea16_data16, // C7: mov EA16, DATA16 + _enter, // C8: enter DATA16, DATA8 + leave, // C9: leave + ret_far_data16, // CA: ret far DATA16 + ret_far, // CB: ret far + int_03, // CC: int 3 + int_data8, // CD: int DATA8 + _into, // CE: into + _iret, // CF: iret + + shift_ea8_1, // D0: shift EA8, 1 + shift_ea16_1, // D1: shift EA16, 1 + shift_ea8_cl, // D2: shift EA8, cl + shift_ea16_cl, // D3: shift EA16, cl + _aam, // D4: AAM + _aad, // D5: AAD + _setalc, // D6: setalc (80286) + _xlat, // D7: xlat + _esc, // D8: esc + _esc, // D9: esc + _esc, // DA: esc + _esc, // DB: esc + _esc, // DC: esc + _esc, // DD: esc + _esc, // DE: esc + _esc, // DF: esc + + _loopnz, // E0: loopnz + _loopz, // E1: loopz + _loop, // E2: loop + _jcxz, // E3: jcxz + in_al_data8, // E4: in al, DATA8 + in_ax_data8, // E5: in ax, DATA8 + out_data8_al, // E6: out DATA8, al + out_data8_ax, // E7: out DATA8, ax + call_near, // E8: call near + jmp_near, // E9: jmp near + jmp_far, // EA: jmp far + jmp_short, // EB: jmp short + in_al_dx, // EC: in al, dx + in_ax_dx, // ED: in ax, dx + out_dx_al, // EE: out dx, al + out_dx_ax, // EF: out dx, ax + + _lock, // F0: lock + _lock, // F1: lock + _repne, // F2: repne + _repe, // F3: repe + _hlt, // F4: hlt + _cmc, // F5: cmc + _ope0xf6, // F6: + _ope0xf7, // F7: + _clc, // F8: clc + _stc, // F9: stc + _cli, // FA: cli + _sti, // FB: sti + _cld, // FC: cld + _std, // FD: std + _ope0xfe, // FE: + _ope0xff, // FF: +}; + diff --git a/i286x/i286x.h b/i286x/i286x.h old mode 100755 new mode 100644 index a19ee519..335cb677 --- a/i286x/i286x.h +++ b/i286x/i286x.h @@ -1,103 +1,103 @@ - -#define I286_MEM mem - -#define I286_STAT i286core.s.r - -#define I286_REG i286core.s.r -#define I286_SEGREG i286core.s.r.w.es - -#define I286_AX i286core.s.r.w.ax -#define I286_BX i286core.s.r.w.bx -#define I286_CX i286core.s.r.w.cx -#define I286_DX i286core.s.r.w.dx -#define I286_SI i286core.s.r.w.si -#define I286_DI i286core.s.r.w.di -#define I286_BP i286core.s.r.w.bp -#define I286_SP i286core.s.r.w.sp -#define I286_CS i286core.s.r.w.cs -#define I286_DS i286core.s.r.w.ds -#define I286_ES i286core.s.r.w.es -#define I286_SS i286core.s.r.w.ss -#define I286_IP i286core.s.r.w.ip - -#define SEG_BASE i286core.s.es_base -#define ES_BASE i286core.s.es_base -#define CS_BASE i286core.s.cs_base -#define SS_BASE i286core.s.ss_base -#define DS_BASE i286core.s.ds_base -#define SS_FIX i286core.s.ss_fix -#define DS_FIX i286core.s.ds_fix - -#define I286_AL i286core.s.r.b.al -#define I286_BL i286core.s.r.b.bl -#define I286_CL i286core.s.r.b.cl -#define I286_DL i286core.s.r.b.dl -#define I286_AH i286core.s.r.b.ah -#define I286_BH i286core.s.r.b.bh -#define I286_CH i286core.s.r.b.ch -#define I286_DH i286core.s.r.b.dh - -#define I286_FLAG i286core.s.r.w.flag -#define I286_FLAGL i286core.s.r.b.flag_l -#define I286_FLAGH i286core.s.r.b.flag_h -#define I286_TRAP i286core.s.trap -#define I286_OV i286core.s.ovflag - -#define I286_GDTR i286core.s.GDTR -#define I286_MSW i286core.s.MSW -#define I286_IDTR i286core.s.IDTR -#define I286_LDTR i286core.s.LDTR -#define I286_LDTRC i286core.s.LDTRC -#define I286_TR i286core.s.TR -#define I286_TRC i286core.s.TRC - -#define I286_ADRSMASK i286core.s.adrsmask -#define I286_REMCLOCK i286core.s.remainclock -#define I286_BASECLOCK i286core.s.baseclock -#define I286_CLOCK i286core.s.clock - -#define I286_REPPOSBAK i286core.e.repbak -#define I286_INPADRS i286core.e.inport - - -#define I286 __declspec(naked) static void -#define I286EXT __declspec(naked) void - -typedef void (*I286TBL)(void); - - -#define I286IRQCHECKTERM \ - __asm { xor eax, eax } \ - __asm { cmp I286_REMCLOCK, eax } \ - __asm { jle short nonremainclr } \ - __asm { xchg I286_REMCLOCK, eax } \ - __asm { sub I286_BASECLOCK, eax } \ - nonremainclr: \ - __asm { ret } - - -#define I286PREFIX(proc) \ - __asm { bts i286core.s.prefix, 0 } \ - __asm { jc fixed } \ - __asm { mov I286_REPPOSBAK, esi } \ - __asm { push offset removeprefix } \ - fixed: \ - GET_NEXTPRE1 \ - __asm { movzx eax, bl } \ - __asm { jmp (proc)[eax*4] } - - -extern void __fastcall i286x_localint(void); -extern void __fastcall i286x_selector(void); -extern void removeprefix(void); - -extern const I286TBL i286op[256]; -extern const I286TBL i286op_repne[256]; -extern const I286TBL i286op_repe[256]; - -extern I286TBL v30op[256]; -extern I286TBL v30op_repne[256]; -extern I286TBL v30op_repe[256]; - -void i286xadr_init(void); - + +#define I286_MEM mem + +#define I286_STAT i286core.s.r + +#define I286_REG i286core.s.r +#define I286_SEGREG i286core.s.r.w.es + +#define I286_AX i286core.s.r.w.ax +#define I286_BX i286core.s.r.w.bx +#define I286_CX i286core.s.r.w.cx +#define I286_DX i286core.s.r.w.dx +#define I286_SI i286core.s.r.w.si +#define I286_DI i286core.s.r.w.di +#define I286_BP i286core.s.r.w.bp +#define I286_SP i286core.s.r.w.sp +#define I286_CS i286core.s.r.w.cs +#define I286_DS i286core.s.r.w.ds +#define I286_ES i286core.s.r.w.es +#define I286_SS i286core.s.r.w.ss +#define I286_IP i286core.s.r.w.ip + +#define SEG_BASE i286core.s.es_base +#define ES_BASE i286core.s.es_base +#define CS_BASE i286core.s.cs_base +#define SS_BASE i286core.s.ss_base +#define DS_BASE i286core.s.ds_base +#define SS_FIX i286core.s.ss_fix +#define DS_FIX i286core.s.ds_fix + +#define I286_AL i286core.s.r.b.al +#define I286_BL i286core.s.r.b.bl +#define I286_CL i286core.s.r.b.cl +#define I286_DL i286core.s.r.b.dl +#define I286_AH i286core.s.r.b.ah +#define I286_BH i286core.s.r.b.bh +#define I286_CH i286core.s.r.b.ch +#define I286_DH i286core.s.r.b.dh + +#define I286_FLAG i286core.s.r.w.flag +#define I286_FLAGL i286core.s.r.b.flag_l +#define I286_FLAGH i286core.s.r.b.flag_h +#define I286_TRAP i286core.s.trap +#define I286_OV i286core.s.ovflag + +#define I286_GDTR i286core.s.GDTR +#define I286_MSW i286core.s.MSW +#define I286_IDTR i286core.s.IDTR +#define I286_LDTR i286core.s.LDTR +#define I286_LDTRC i286core.s.LDTRC +#define I286_TR i286core.s.TR +#define I286_TRC i286core.s.TRC + +#define I286_ADRSMASK i286core.s.adrsmask +#define I286_REMCLOCK i286core.s.remainclock +#define I286_BASECLOCK i286core.s.baseclock +#define I286_CLOCK i286core.s.clock + +#define I286_REPPOSBAK i286core.e.repbak +#define I286_INPADRS i286core.e.inport + + +#define I286 __declspec(naked) static void +#define I286EXT __declspec(naked) void + +typedef void (*I286TBL)(void); + + +#define I286IRQCHECKTERM \ + __asm { xor eax, eax } \ + __asm { cmp I286_REMCLOCK, eax } \ + __asm { jle short nonremainclr } \ + __asm { xchg I286_REMCLOCK, eax } \ + __asm { sub I286_BASECLOCK, eax } \ + nonremainclr: \ + __asm { ret } + + +#define I286PREFIX(proc) \ + __asm { bts i286core.s.prefix, 0 } \ + __asm { jc fixed } \ + __asm { mov I286_REPPOSBAK, esi } \ + __asm { push offset removeprefix } \ + fixed: \ + GET_NEXTPRE1 \ + __asm { movzx eax, bl } \ + __asm { jmp (proc)[eax*4] } + + +extern void __fastcall i286x_localint(void); +extern void __fastcall i286x_selector(void); +extern void removeprefix(void); + +extern const I286TBL i286op[256]; +extern const I286TBL i286op_repne[256]; +extern const I286TBL i286op_repe[256]; + +extern I286TBL v30op[256]; +extern I286TBL v30op_repne[256]; +extern I286TBL v30op_repe[256]; + +void i286xadr_init(void); + diff --git a/i286x/i286xadr.cpp b/i286x/i286xadr.cpp old mode 100755 new mode 100644 index 6ecc3c1d..eb5c0a61 --- a/i286x/i286xadr.cpp +++ b/i286x/i286xadr.cpp @@ -1,1027 +1,1027 @@ -#include -#include -#include "i286x.h" -#include "i286x.mcr" -#include "i286xea.mcr" - - -LABEL static void p2ea_nop(void) { - - __asm { - ret - } -} - -LABEL static void p2ea_bx_si(void) { - - __asm { - GET_NEXTPRE2 - movzx ecx, I286_BX - add cx, I286_SI - add ecx, DS_FIX - ret - } -} - -LABEL static void p2ea_bx_si_disp8(void) { - - __asm { - mov eax, ebx - shr eax, 16 - cbw - add ax, I286_BX - add ax, I286_SI - add eax, DS_FIX - push eax - GET_NEXTPRE3 - pop ecx - ret - } -} - -LABEL static void p2ea_bx_si_disp16(void) { - - __asm { - shr ebx, 16 - add bx, I286_BX - add bx, I286_SI - add ebx, DS_FIX - push ebx - GET_NEXTPRE4 - pop ecx - ret - } -} - -LABEL static void p2ea_bx_di(void) { - - __asm { - GET_NEXTPRE2 - movzx ecx, I286_BX - add cx, I286_DI - add ecx, DS_FIX - ret - } -} - -LABEL static void p2ea_bx_di_disp8(void) { - - __asm { - mov eax, ebx - shr eax, 16 - cbw - add ax, I286_BX - add ax, I286_DI - add eax, DS_FIX - push eax - GET_NEXTPRE3 - pop ecx - ret - } -} - -LABEL static void p2ea_bx_di_disp16(void) { - - __asm { - shr ebx, 16 - add bx, I286_BX - add bx, I286_DI - add ebx, DS_FIX - push ebx - GET_NEXTPRE4 - pop ecx - ret - } -} - -LABEL static void p2ea_bp_si(void) { - - __asm { - GET_NEXTPRE2 - movzx ecx, I286_BP - add cx, I286_SI - add ecx, SS_FIX - ret - } -} - -LABEL static void p2ea_bp_si_disp8(void) { - - __asm { - mov eax, ebx - shr eax, 16 - cbw - add ax, I286_BP - add ax, I286_SI - add eax, SS_FIX - push eax - GET_NEXTPRE3 - pop ecx - ret - } -} - -LABEL static void p2ea_bp_si_disp16(void) { - - __asm { - shr ebx, 16 - add bx, I286_BP - add bx, I286_SI - add ebx, SS_FIX - push ebx - GET_NEXTPRE4 - pop ecx - ret - } -} - -LABEL static void p2ea_bp_di(void) { - - __asm { - GET_NEXTPRE2 - movzx ecx, I286_BP - add cx, I286_DI - add ecx, SS_FIX - ret - } -} - -LABEL static void p2ea_bp_di_disp8(void) { - - __asm { - mov eax, ebx - shr eax, 16 - cbw - add ax, I286_BP - add ax, I286_DI - add eax, SS_FIX - push eax - GET_NEXTPRE3 - pop ecx - ret - } -} - -LABEL static void p2ea_bp_di_disp16(void) { - - __asm { - shr ebx, 16 - add bx, I286_BP - add bx, I286_DI - add ebx, SS_FIX - push ebx - GET_NEXTPRE4 - pop ecx - ret - } -} - -LABEL static void p2ea_si(void) { - - __asm { - GET_NEXTPRE2 - movzx ecx, I286_SI - add ecx, DS_FIX - ret - } -} - -LABEL static void p2ea_si_disp8(void) { - - __asm { - mov eax, ebx - shr eax, 16 - cbw - add ax, I286_SI - add eax, DS_FIX - push eax - GET_NEXTPRE3 - pop ecx - ret - } -} - -LABEL static void p2ea_si_disp16(void) { - - __asm { - shr ebx, 16 - add bx, I286_SI - add ebx, DS_FIX - push ebx - GET_NEXTPRE4 - pop ecx - ret - } -} - -LABEL static void p2ea_di(void) { - - __asm { - GET_NEXTPRE2 - movzx ecx, I286_DI - add ecx, DS_FIX - ret - } -} - -LABEL static void p2ea_di_disp8(void) { - - __asm { - mov eax, ebx - shr eax, 16 - cbw - add ax, I286_DI - add eax, DS_FIX - push eax - GET_NEXTPRE3 - pop ecx - ret - } -} - -LABEL static void p2ea_di_disp16(void) { - - __asm { - shr ebx, 16 - add bx, I286_DI - add ebx, DS_FIX - push ebx - GET_NEXTPRE4 - pop ecx - ret - } -} - -LABEL static void p2ea_disp16(void) { - - __asm { - shr ebx, 16 - add ebx, DS_FIX - push ebx - GET_NEXTPRE4 - pop ecx - ret - } -} - -LABEL static void p2ea_bp_disp8(void) { - - __asm { - mov eax, ebx - shr eax, 16 - cbw - add ax, I286_BP - add eax, SS_FIX - push eax - GET_NEXTPRE3 - pop ecx - ret - } -} - -LABEL static void p2ea_bp_disp16(void) { - - __asm { - shr ebx, 16 - add bx, I286_BP - add ebx, SS_FIX - push ebx - GET_NEXTPRE4 - pop ecx - ret - } -} - -LABEL static void p2ea_bx(void) { - - __asm { - GET_NEXTPRE2 - movzx ecx, I286_BX - add ecx, DS_FIX - ret - } -} - -LABEL static void p2ea_bx_disp8(void) { - - __asm { - mov eax, ebx - shr eax, 16 - cbw - add ax, I286_BX - add eax, DS_FIX - push eax - GET_NEXTPRE3 - pop ecx - ret - } -} - -LABEL static void p2ea_bx_disp16(void) { - - __asm { - shr ebx, 16 - add bx, I286_BX - add ebx, DS_FIX - push ebx - GET_NEXTPRE4 - pop ecx - ret - } -} - -static const I286TBL peadst_tbl[] = { - p2ea_bx_si, p2ea_bx_di, - p2ea_bp_si, p2ea_bp_di, - p2ea_si, p2ea_di, - p2ea_disp16, p2ea_bx, - - p2ea_bx_si_disp8, p2ea_bx_di_disp8, - p2ea_bp_si_disp8, p2ea_bp_di_disp8, - p2ea_si_disp8, p2ea_di_disp8, - p2ea_bp_disp8, p2ea_bx_disp8, - - p2ea_bx_si_disp16, p2ea_bx_di_disp16, - p2ea_bp_si_disp16, p2ea_bp_di_disp16, - p2ea_si_disp16, p2ea_di_disp16, - p2ea_bp_disp16, p2ea_bx_disp16}; - - -// -------------------------------------------------------------------------- - -LABEL static void p2lea_bx_si(void) { - - __asm { - GET_NEXTPRE2 - mov ax, I286_BX - add ax, I286_SI - ret - } -} - -LABEL static void p2lea_bx_si_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - cbw - add ax, I286_BX - add ax, I286_SI - ret - } -} - -LABEL static void p2lea_bx_si_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - add ax, I286_BX - add ax, I286_SI - ret - } -} - -LABEL static void p2lea_bx_di(void) { - - __asm { - GET_NEXTPRE2 - mov ax, I286_BX - add ax, I286_DI - ret - } -} - -LABEL static void p2lea_bx_di_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - cbw - add ax, I286_BX - add ax, I286_DI - ret - } -} - -LABEL static void p2lea_bx_di_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - add ax, I286_BX - add ax, I286_DI - ret - } -} - -LABEL static void p2lea_bp_si(void) { - - __asm { - GET_NEXTPRE2 - mov ax, I286_BP - add ax, I286_SI - ret - } -} - -LABEL static void p2lea_bp_si_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - cbw - add ax, I286_BP - add ax, I286_SI - ret - } -} - -LABEL static void p2lea_bp_si_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - add ax, I286_BP - add ax, I286_SI - ret - } -} - -LABEL static void p2lea_bp_di(void) { - - __asm { - GET_NEXTPRE2 - mov ax, I286_BP - add ax, I286_DI - ret - } -} - -LABEL static void p2lea_bp_di_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - cbw - add ax, I286_BP - add ax, I286_DI - ret - } -} - -LABEL static void p2lea_bp_di_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - add ax, I286_BP - add ax, I286_DI - ret - } -} - -LABEL static void p2lea_si(void) { - - __asm { - GET_NEXTPRE2 - mov ax, I286_SI - ret - } -} - -LABEL static void p2lea_si_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - cbw - add ax, I286_SI - ret - } -} - -LABEL static void p2lea_si_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - add ax, I286_SI - ret - } -} - -LABEL static void p2lea_di(void) { - - __asm { - GET_NEXTPRE2 - mov ax, I286_DI - ret - } -} - -LABEL static void p2lea_di_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - cbw - add ax, I286_DI - ret - } -} - -LABEL static void p2lea_di_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - add ax, I286_DI - ret - } -} - -LABEL static void p2lea_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - ret - } -} - -LABEL static void p2lea_bp_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - cbw - add ax, I286_BP - ret - } -} - -LABEL static void p2lea_bp_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - add ax, I286_BP - ret - } -} - -LABEL static void p2lea_bx(void) { - - __asm { - GET_NEXTPRE2 - mov ax, I286_BX - ret - } -} - -LABEL static void p2lea_bx_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - cbw - add ax, I286_BX - ret - } -} - -LABEL static void p2lea_bx_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - add ax, I286_BX - ret - } -} - -static const I286TBL plea_tbl[] = { - p2lea_bx_si, p2lea_bx_di, - p2lea_bp_si, p2lea_bp_di, - p2lea_si, p2lea_di, - p2lea_disp16, p2lea_bx, - - p2lea_bx_si_disp8, p2lea_bx_di_disp8, - p2lea_bp_si_disp8, p2lea_bp_di_disp8, - p2lea_si_disp8, p2lea_di_disp8, - p2lea_bp_disp8, p2lea_bx_disp8, - - p2lea_bx_si_disp16, p2lea_bx_di_disp16, - p2lea_bp_si_disp16, p2lea_bp_di_disp16, - p2lea_si_disp16, p2lea_di_disp16, - p2lea_bp_disp16, p2lea_bx_disp16}; - - -// -------------------------------------------------------------------------- - -LABEL static void a_bx_si(void) { - - __asm { - GET_NEXTPRE2 - movzx ebp, I286_BX - add bp, I286_SI - GET_PREFIX_DS - ret - } -} - -LABEL static void a_bx_si_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - movzx ebp, I286_BX - add bp, I286_SI - cbw - add bp, ax - GET_PREFIX_DS - ret - } -} - -LABEL static void a_bx_si_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - movzx ebp, I286_BX - add bp, I286_SI - add bp, ax - GET_PREFIX_DS - ret - } -} - -LABEL static void a_bx_di(void) { - - __asm { - GET_NEXTPRE2 - movzx ebp, I286_BX - add bp, I286_DI - GET_PREFIX_DS - ret - } -} - -LABEL static void a_bx_di_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - movzx ebp, I286_BX - add bp, I286_DI - cbw - add bp, ax - GET_PREFIX_DS - ret - } -} - -LABEL static void a_bx_di_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - movzx ebp, I286_BX - add bp, I286_DI - add bp, ax - GET_PREFIX_DS - ret - } -} - -LABEL static void a_bp_si(void) { - - __asm { - GET_NEXTPRE2 - movzx ebp, I286_BP - add bp, I286_SI - GET_PREFIX_SS - ret - } -} - -LABEL static void a_bp_si_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - movzx ebp, I286_BP - add bp, I286_SI - cbw - add bp, ax - GET_PREFIX_SS - ret - } -} - -LABEL static void a_bp_si_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - movzx ebp, I286_BP - add bp, I286_SI - add bp, ax - GET_PREFIX_SS - ret - } -} - -LABEL static void a_bp_di(void) { - - __asm { - GET_NEXTPRE2 - movzx ebp, I286_BP - add bp, I286_DI - GET_PREFIX_SS - ret - } -} - -LABEL static void a_bp_di_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - movzx ebp, I286_BP - add bp, I286_DI - cbw - add bp, ax - GET_PREFIX_SS - ret - } -} - -LABEL static void a_bp_di_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - movzx ebp, I286_BP - add bp, I286_DI - add bp, ax - GET_PREFIX_SS - ret - } -} - -LABEL static void a_si(void) { - - __asm { - GET_NEXTPRE2 - movzx ebp, I286_SI - GET_PREFIX_DS - ret - } -} - -LABEL static void a_si_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - movzx ebp, I286_SI - cbw - add bp, ax - GET_PREFIX_DS - ret - } -} - -LABEL static void a_si_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - movzx ebp, I286_SI - add bp, ax - GET_PREFIX_DS - ret - } -} - -LABEL static void a_di(void) { - - __asm { - GET_NEXTPRE2 - movzx ebp, I286_DI - GET_PREFIX_DS - ret - } -} - -LABEL static void a_di_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - movzx ebp, I286_DI - cbw - add bp, ax - GET_PREFIX_DS - ret - } -} - -LABEL static void a_di_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - movzx ebp, I286_DI - add bp, ax - GET_PREFIX_DS - ret - } -} - -LABEL static void a_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop ebp - shr ebp, 16 - GET_PREFIX_DS - ret - } -} - -LABEL static void a_bp_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - movzx ebp, I286_BP - cbw - add bp, ax - GET_PREFIX_SS - ret - } -} - -LABEL static void a_bp_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - movzx ebp, I286_BP - add bp, ax - GET_PREFIX_SS - ret - } -} - -LABEL static void a_bx(void) { - - __asm { - GET_NEXTPRE2 - movzx ebp, I286_BX - GET_PREFIX_DS - ret - } -} - -LABEL static void a_bx_disp8(void) { - - __asm { - push ebx - GET_NEXTPRE3 - pop eax - shr eax, 16 - movzx ebp, I286_BX - cbw - add bp, ax - GET_PREFIX_DS - ret - } -} - -LABEL static void a_bx_disp16(void) { - - __asm { - push ebx - GET_NEXTPRE4 - pop eax - shr eax, 16 - movzx ebp, I286_BX - add bp, ax - GET_PREFIX_DS - ret - } -} - -static const I286TBL pgetea_tbl[] = { - a_bx_si, a_bx_di, - a_bp_si, a_bp_di, - a_si, a_di, - a_disp16, a_bx, - - a_bx_si_disp8, a_bx_di_disp8, - a_bp_si_disp8, a_bp_di_disp8, - a_si_disp8, a_di_disp8, - a_bp_disp8, a_bx_disp8, - - a_bx_si_disp16, a_bx_di_disp16, - a_bp_si_disp16, a_bp_di_disp16, - a_si_disp16, a_di_disp16, - a_bp_disp16, a_bx_disp16}; - - -// -------------------------------------------------------------------------- - - I286TBL p_ea_dst[256]; - I286TBL p_lea[256]; - I286TBL p_get_ea[256]; - - -void i286xadr_init(void) { - - int i; - int j; - - for (i=0; i<0x100; i++) { - if (i < 0xc0) { - j = ((i >> 3) & 0x18) | (i & 7); - p_ea_dst[i] = peadst_tbl[j]; - p_lea[i] = plea_tbl[j]; - p_get_ea[i] = pgetea_tbl[j]; - } - else { - // 来る事はない筈だが… - p_ea_dst[i] = p2ea_nop; - p_lea[i] = p2ea_nop; - p_get_ea[i] = p2ea_nop; - } - } -} - +#include +#include +#include "i286x.h" +#include "i286x.mcr" +#include "i286xea.mcr" + + +LABEL static void p2ea_nop(void) { + + __asm { + ret + } +} + +LABEL static void p2ea_bx_si(void) { + + __asm { + GET_NEXTPRE2 + movzx ecx, I286_BX + add cx, I286_SI + add ecx, DS_FIX + ret + } +} + +LABEL static void p2ea_bx_si_disp8(void) { + + __asm { + mov eax, ebx + shr eax, 16 + cbw + add ax, I286_BX + add ax, I286_SI + add eax, DS_FIX + push eax + GET_NEXTPRE3 + pop ecx + ret + } +} + +LABEL static void p2ea_bx_si_disp16(void) { + + __asm { + shr ebx, 16 + add bx, I286_BX + add bx, I286_SI + add ebx, DS_FIX + push ebx + GET_NEXTPRE4 + pop ecx + ret + } +} + +LABEL static void p2ea_bx_di(void) { + + __asm { + GET_NEXTPRE2 + movzx ecx, I286_BX + add cx, I286_DI + add ecx, DS_FIX + ret + } +} + +LABEL static void p2ea_bx_di_disp8(void) { + + __asm { + mov eax, ebx + shr eax, 16 + cbw + add ax, I286_BX + add ax, I286_DI + add eax, DS_FIX + push eax + GET_NEXTPRE3 + pop ecx + ret + } +} + +LABEL static void p2ea_bx_di_disp16(void) { + + __asm { + shr ebx, 16 + add bx, I286_BX + add bx, I286_DI + add ebx, DS_FIX + push ebx + GET_NEXTPRE4 + pop ecx + ret + } +} + +LABEL static void p2ea_bp_si(void) { + + __asm { + GET_NEXTPRE2 + movzx ecx, I286_BP + add cx, I286_SI + add ecx, SS_FIX + ret + } +} + +LABEL static void p2ea_bp_si_disp8(void) { + + __asm { + mov eax, ebx + shr eax, 16 + cbw + add ax, I286_BP + add ax, I286_SI + add eax, SS_FIX + push eax + GET_NEXTPRE3 + pop ecx + ret + } +} + +LABEL static void p2ea_bp_si_disp16(void) { + + __asm { + shr ebx, 16 + add bx, I286_BP + add bx, I286_SI + add ebx, SS_FIX + push ebx + GET_NEXTPRE4 + pop ecx + ret + } +} + +LABEL static void p2ea_bp_di(void) { + + __asm { + GET_NEXTPRE2 + movzx ecx, I286_BP + add cx, I286_DI + add ecx, SS_FIX + ret + } +} + +LABEL static void p2ea_bp_di_disp8(void) { + + __asm { + mov eax, ebx + shr eax, 16 + cbw + add ax, I286_BP + add ax, I286_DI + add eax, SS_FIX + push eax + GET_NEXTPRE3 + pop ecx + ret + } +} + +LABEL static void p2ea_bp_di_disp16(void) { + + __asm { + shr ebx, 16 + add bx, I286_BP + add bx, I286_DI + add ebx, SS_FIX + push ebx + GET_NEXTPRE4 + pop ecx + ret + } +} + +LABEL static void p2ea_si(void) { + + __asm { + GET_NEXTPRE2 + movzx ecx, I286_SI + add ecx, DS_FIX + ret + } +} + +LABEL static void p2ea_si_disp8(void) { + + __asm { + mov eax, ebx + shr eax, 16 + cbw + add ax, I286_SI + add eax, DS_FIX + push eax + GET_NEXTPRE3 + pop ecx + ret + } +} + +LABEL static void p2ea_si_disp16(void) { + + __asm { + shr ebx, 16 + add bx, I286_SI + add ebx, DS_FIX + push ebx + GET_NEXTPRE4 + pop ecx + ret + } +} + +LABEL static void p2ea_di(void) { + + __asm { + GET_NEXTPRE2 + movzx ecx, I286_DI + add ecx, DS_FIX + ret + } +} + +LABEL static void p2ea_di_disp8(void) { + + __asm { + mov eax, ebx + shr eax, 16 + cbw + add ax, I286_DI + add eax, DS_FIX + push eax + GET_NEXTPRE3 + pop ecx + ret + } +} + +LABEL static void p2ea_di_disp16(void) { + + __asm { + shr ebx, 16 + add bx, I286_DI + add ebx, DS_FIX + push ebx + GET_NEXTPRE4 + pop ecx + ret + } +} + +LABEL static void p2ea_disp16(void) { + + __asm { + shr ebx, 16 + add ebx, DS_FIX + push ebx + GET_NEXTPRE4 + pop ecx + ret + } +} + +LABEL static void p2ea_bp_disp8(void) { + + __asm { + mov eax, ebx + shr eax, 16 + cbw + add ax, I286_BP + add eax, SS_FIX + push eax + GET_NEXTPRE3 + pop ecx + ret + } +} + +LABEL static void p2ea_bp_disp16(void) { + + __asm { + shr ebx, 16 + add bx, I286_BP + add ebx, SS_FIX + push ebx + GET_NEXTPRE4 + pop ecx + ret + } +} + +LABEL static void p2ea_bx(void) { + + __asm { + GET_NEXTPRE2 + movzx ecx, I286_BX + add ecx, DS_FIX + ret + } +} + +LABEL static void p2ea_bx_disp8(void) { + + __asm { + mov eax, ebx + shr eax, 16 + cbw + add ax, I286_BX + add eax, DS_FIX + push eax + GET_NEXTPRE3 + pop ecx + ret + } +} + +LABEL static void p2ea_bx_disp16(void) { + + __asm { + shr ebx, 16 + add bx, I286_BX + add ebx, DS_FIX + push ebx + GET_NEXTPRE4 + pop ecx + ret + } +} + +static const I286TBL peadst_tbl[] = { + p2ea_bx_si, p2ea_bx_di, + p2ea_bp_si, p2ea_bp_di, + p2ea_si, p2ea_di, + p2ea_disp16, p2ea_bx, + + p2ea_bx_si_disp8, p2ea_bx_di_disp8, + p2ea_bp_si_disp8, p2ea_bp_di_disp8, + p2ea_si_disp8, p2ea_di_disp8, + p2ea_bp_disp8, p2ea_bx_disp8, + + p2ea_bx_si_disp16, p2ea_bx_di_disp16, + p2ea_bp_si_disp16, p2ea_bp_di_disp16, + p2ea_si_disp16, p2ea_di_disp16, + p2ea_bp_disp16, p2ea_bx_disp16}; + + +// -------------------------------------------------------------------------- + +LABEL static void p2lea_bx_si(void) { + + __asm { + GET_NEXTPRE2 + mov ax, I286_BX + add ax, I286_SI + ret + } +} + +LABEL static void p2lea_bx_si_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + cbw + add ax, I286_BX + add ax, I286_SI + ret + } +} + +LABEL static void p2lea_bx_si_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + add ax, I286_BX + add ax, I286_SI + ret + } +} + +LABEL static void p2lea_bx_di(void) { + + __asm { + GET_NEXTPRE2 + mov ax, I286_BX + add ax, I286_DI + ret + } +} + +LABEL static void p2lea_bx_di_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + cbw + add ax, I286_BX + add ax, I286_DI + ret + } +} + +LABEL static void p2lea_bx_di_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + add ax, I286_BX + add ax, I286_DI + ret + } +} + +LABEL static void p2lea_bp_si(void) { + + __asm { + GET_NEXTPRE2 + mov ax, I286_BP + add ax, I286_SI + ret + } +} + +LABEL static void p2lea_bp_si_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + cbw + add ax, I286_BP + add ax, I286_SI + ret + } +} + +LABEL static void p2lea_bp_si_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + add ax, I286_BP + add ax, I286_SI + ret + } +} + +LABEL static void p2lea_bp_di(void) { + + __asm { + GET_NEXTPRE2 + mov ax, I286_BP + add ax, I286_DI + ret + } +} + +LABEL static void p2lea_bp_di_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + cbw + add ax, I286_BP + add ax, I286_DI + ret + } +} + +LABEL static void p2lea_bp_di_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + add ax, I286_BP + add ax, I286_DI + ret + } +} + +LABEL static void p2lea_si(void) { + + __asm { + GET_NEXTPRE2 + mov ax, I286_SI + ret + } +} + +LABEL static void p2lea_si_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + cbw + add ax, I286_SI + ret + } +} + +LABEL static void p2lea_si_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + add ax, I286_SI + ret + } +} + +LABEL static void p2lea_di(void) { + + __asm { + GET_NEXTPRE2 + mov ax, I286_DI + ret + } +} + +LABEL static void p2lea_di_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + cbw + add ax, I286_DI + ret + } +} + +LABEL static void p2lea_di_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + add ax, I286_DI + ret + } +} + +LABEL static void p2lea_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + ret + } +} + +LABEL static void p2lea_bp_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + cbw + add ax, I286_BP + ret + } +} + +LABEL static void p2lea_bp_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + add ax, I286_BP + ret + } +} + +LABEL static void p2lea_bx(void) { + + __asm { + GET_NEXTPRE2 + mov ax, I286_BX + ret + } +} + +LABEL static void p2lea_bx_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + cbw + add ax, I286_BX + ret + } +} + +LABEL static void p2lea_bx_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + add ax, I286_BX + ret + } +} + +static const I286TBL plea_tbl[] = { + p2lea_bx_si, p2lea_bx_di, + p2lea_bp_si, p2lea_bp_di, + p2lea_si, p2lea_di, + p2lea_disp16, p2lea_bx, + + p2lea_bx_si_disp8, p2lea_bx_di_disp8, + p2lea_bp_si_disp8, p2lea_bp_di_disp8, + p2lea_si_disp8, p2lea_di_disp8, + p2lea_bp_disp8, p2lea_bx_disp8, + + p2lea_bx_si_disp16, p2lea_bx_di_disp16, + p2lea_bp_si_disp16, p2lea_bp_di_disp16, + p2lea_si_disp16, p2lea_di_disp16, + p2lea_bp_disp16, p2lea_bx_disp16}; + + +// -------------------------------------------------------------------------- + +LABEL static void a_bx_si(void) { + + __asm { + GET_NEXTPRE2 + movzx ebp, I286_BX + add bp, I286_SI + GET_PREFIX_DS + ret + } +} + +LABEL static void a_bx_si_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + movzx ebp, I286_BX + add bp, I286_SI + cbw + add bp, ax + GET_PREFIX_DS + ret + } +} + +LABEL static void a_bx_si_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + movzx ebp, I286_BX + add bp, I286_SI + add bp, ax + GET_PREFIX_DS + ret + } +} + +LABEL static void a_bx_di(void) { + + __asm { + GET_NEXTPRE2 + movzx ebp, I286_BX + add bp, I286_DI + GET_PREFIX_DS + ret + } +} + +LABEL static void a_bx_di_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + movzx ebp, I286_BX + add bp, I286_DI + cbw + add bp, ax + GET_PREFIX_DS + ret + } +} + +LABEL static void a_bx_di_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + movzx ebp, I286_BX + add bp, I286_DI + add bp, ax + GET_PREFIX_DS + ret + } +} + +LABEL static void a_bp_si(void) { + + __asm { + GET_NEXTPRE2 + movzx ebp, I286_BP + add bp, I286_SI + GET_PREFIX_SS + ret + } +} + +LABEL static void a_bp_si_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + movzx ebp, I286_BP + add bp, I286_SI + cbw + add bp, ax + GET_PREFIX_SS + ret + } +} + +LABEL static void a_bp_si_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + movzx ebp, I286_BP + add bp, I286_SI + add bp, ax + GET_PREFIX_SS + ret + } +} + +LABEL static void a_bp_di(void) { + + __asm { + GET_NEXTPRE2 + movzx ebp, I286_BP + add bp, I286_DI + GET_PREFIX_SS + ret + } +} + +LABEL static void a_bp_di_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + movzx ebp, I286_BP + add bp, I286_DI + cbw + add bp, ax + GET_PREFIX_SS + ret + } +} + +LABEL static void a_bp_di_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + movzx ebp, I286_BP + add bp, I286_DI + add bp, ax + GET_PREFIX_SS + ret + } +} + +LABEL static void a_si(void) { + + __asm { + GET_NEXTPRE2 + movzx ebp, I286_SI + GET_PREFIX_DS + ret + } +} + +LABEL static void a_si_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + movzx ebp, I286_SI + cbw + add bp, ax + GET_PREFIX_DS + ret + } +} + +LABEL static void a_si_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + movzx ebp, I286_SI + add bp, ax + GET_PREFIX_DS + ret + } +} + +LABEL static void a_di(void) { + + __asm { + GET_NEXTPRE2 + movzx ebp, I286_DI + GET_PREFIX_DS + ret + } +} + +LABEL static void a_di_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + movzx ebp, I286_DI + cbw + add bp, ax + GET_PREFIX_DS + ret + } +} + +LABEL static void a_di_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + movzx ebp, I286_DI + add bp, ax + GET_PREFIX_DS + ret + } +} + +LABEL static void a_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop ebp + shr ebp, 16 + GET_PREFIX_DS + ret + } +} + +LABEL static void a_bp_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + movzx ebp, I286_BP + cbw + add bp, ax + GET_PREFIX_SS + ret + } +} + +LABEL static void a_bp_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + movzx ebp, I286_BP + add bp, ax + GET_PREFIX_SS + ret + } +} + +LABEL static void a_bx(void) { + + __asm { + GET_NEXTPRE2 + movzx ebp, I286_BX + GET_PREFIX_DS + ret + } +} + +LABEL static void a_bx_disp8(void) { + + __asm { + push ebx + GET_NEXTPRE3 + pop eax + shr eax, 16 + movzx ebp, I286_BX + cbw + add bp, ax + GET_PREFIX_DS + ret + } +} + +LABEL static void a_bx_disp16(void) { + + __asm { + push ebx + GET_NEXTPRE4 + pop eax + shr eax, 16 + movzx ebp, I286_BX + add bp, ax + GET_PREFIX_DS + ret + } +} + +static const I286TBL pgetea_tbl[] = { + a_bx_si, a_bx_di, + a_bp_si, a_bp_di, + a_si, a_di, + a_disp16, a_bx, + + a_bx_si_disp8, a_bx_di_disp8, + a_bp_si_disp8, a_bp_di_disp8, + a_si_disp8, a_di_disp8, + a_bp_disp8, a_bx_disp8, + + a_bx_si_disp16, a_bx_di_disp16, + a_bp_si_disp16, a_bp_di_disp16, + a_si_disp16, a_di_disp16, + a_bp_disp16, a_bx_disp16}; + + +// -------------------------------------------------------------------------- + + I286TBL p_ea_dst[256]; + I286TBL p_lea[256]; + I286TBL p_get_ea[256]; + + +void i286xadr_init(void) { + + int i; + int j; + + for (i=0; i<0x100; i++) { + if (i < 0xc0) { + j = ((i >> 3) & 0x18) | (i & 7); + p_ea_dst[i] = peadst_tbl[j]; + p_lea[i] = plea_tbl[j]; + p_get_ea[i] = pgetea_tbl[j]; + } + else { + // 来る事はない筈だが… + p_ea_dst[i] = p2ea_nop; + p_lea[i] = p2ea_nop; + p_get_ea[i] = p2ea_nop; + } + } +} + diff --git a/i286x/i286xadr.h b/i286x/i286xadr.h old mode 100755 new mode 100644 index 64ae55b4..43aa0498 --- a/i286x/i286xadr.h +++ b/i286x/i286xadr.h @@ -1,5 +1,5 @@ - -extern I286TBL p_ea_dst[256]; -extern I286TBL p_lea[256]; -extern I286TBL p_get_ea[256]; - + +extern I286TBL p_ea_dst[256]; +extern I286TBL p_lea[256]; +extern I286TBL p_get_ea[256]; + diff --git a/i286x/i286xcts.cpp b/i286x/i286xcts.cpp old mode 100755 new mode 100644 index ccf809ab..8aadca4c --- a/i286x/i286xcts.cpp +++ b/i286x/i286xcts.cpp @@ -1,387 +1,387 @@ -#include -#include -#include "i286x.h" -#include "i286xadr.h" -#include "i286xcts.h" -#include "i286x.mcr" -#include "i286xea.mcr" - - -typedef void (*I286OP_0F)(void); - - -// ---- 0f 00 - -I286 _sldt(void) { - - __asm { - PREPART_EA16(2) - mov dx, I286_LDTR - mov word ptr I286_REG[eax*2], dx - GET_NEXTPRE2 - ret - MEMORY_EA16(3) - mov ax, I286_LDTR - mov word ptr I286_MEM[ecx], ax - ret - extmem_eareg16: - mov dx, I286_LDTR - jmp i286_memorywrite_w - } -} - -I286 _str(void) { - - __asm { - PREPART_EA16(3) - mov dx, I286_TR - mov word ptr I286_REG[eax*2], dx - GET_NEXTPRE2 - ret - MEMORY_EA16(6) - mov ax, I286_TR - mov word ptr I286_MEM[ecx], ax - ret - extmem_eareg16: - mov dx, I286_TR - jmp i286_memorywrite_w - } -} - -I286 _lldt(void) { - - __asm { - PREPART_EA16(17) - mov ax, word ptr I286_REG[eax*2] - call lldt_sub - GET_NEXTPRE2 - ret - MEMORY_EA16(19) - mov ax, word ptr I286_MEM[ecx] - jmp short lldt_sub - EXTMEM_EA16 - -lldt_sub: mov word ptr I286_LDTR, ax - call i286x_selector - mov ecx, eax - call i286_memoryread_w - mov I286_LDTRC.limit, ax - add ecx, 2 - call i286_memoryread_w - mov I286_LDTRC.base, ax - add ecx, 2 - call i286_memoryread - mov I286_LDTRC.base24, al - ret - } -} - -I286 _ltr(void) { - - __asm { - PREPART_EA16(17) - mov ax, word ptr I286_REG[eax*2] - call ltr_sub - GET_NEXTPRE2 - ret - MEMORY_EA16(19) - mov ax, word ptr I286_MEM[ecx] - jmp short ltr_sub - EXTMEM_EA16 - -ltr_sub: mov word ptr I286_TR, ax - call i286x_selector - mov ecx, eax - call i286_memoryread_w - mov I286_TRC.limit, ax - add ecx, 2 - call i286_memoryread_w - mov I286_TRC.base, ax - add ecx, 2 - call i286_memoryread - mov I286_TRC.base24, al - ret - } -} - -I286 _verr(void) { - - __asm { - PREPART_EA16(14) - mov ax, word ptr I286_REG[eax*2] - GET_NEXTPRE2 - ret - MEMORY_EA16(16) - mov ax, word ptr I286_MEM[ecx] - ret - EXTMEM_EA16 - ret - } -} - -I286 _verw(void) { - - __asm { - PREPART_EA16(14) - mov ax, word ptr I286_REG[eax*2] - GET_NEXTPRE2 - ret - MEMORY_EA16(16) - mov ax, word ptr I286_MEM[ecx] - ret - EXTMEM_EA16 - ret - } -} - -static const I286OP_0F cts0x_table[] = { - _sldt, _str, _lldt, _ltr, - _verr, _verw, _verr, _verw}; - - -// ---- 0f 01 - -I286 _sgdt(void) { - - __asm { - cmp al, 0c0h - jnc register_eareg16 - I286CLOCK(11) - call p_ea_dst[eax*4] - mov dx, word ptr I286_GDTR - call i286_memorywrite_w - add ecx, 2 - mov dx, word ptr (I286_GDTR + 2) - call i286_memorywrite_w - add ecx, 2 - mov dl, byte ptr (I286_GDTR + 4) - mov dh, -1 - jmp i286_memorywrite_w - align 4 - register_eareg16: - INT_NUM(6) - } -} - -I286 _sidt(void) { - - __asm { - cmp al, 0c0h - jnc register_eareg16 - I286CLOCK(12) - call p_ea_dst[eax*4] - mov dx, word ptr I286_IDTR - call i286_memorywrite_w - add ecx, 2 - mov dx, word ptr (I286_IDTR + 2) - call i286_memorywrite_w - add ecx, 2 - mov dl, byte ptr (I286_IDTR + 4) - mov dh, -1 - jmp i286_memorywrite_w - align 4 - register_eareg16: - INT_NUM(6) - } -} - -I286 _lgdt(void) { - - __asm { - cmp al, 0c0h - jnc register_eareg16 - I286CLOCK(11) - call p_ea_dst[eax*4] - call i286_memoryread_w - mov word ptr I286_GDTR, ax - add ecx, 2 - call i286_memoryread_w - mov word ptr (I286_GDTR + 2), ax - add ecx, 2 - call i286_memoryread - mov byte ptr (I286_GDTR + 4), al - ret - align 4 - register_eareg16: - INT_NUM(6) - } -} - -I286 _lidt(void) { - - __asm { - cmp al, 0c0h - jnc register_eareg16 - I286CLOCK(12) - call p_ea_dst[eax*4] - call i286_memoryread_w - mov word ptr I286_IDTR, ax - add ecx, 2 - call i286_memoryread_w - mov word ptr (I286_IDTR + 2), ax - add ecx, 2 - call i286_memoryread - mov byte ptr (I286_IDTR + 4), al - ret - align 4 - register_eareg16: - INT_NUM(6) - } -} - -I286 _smsw(void) { - - __asm { - PREPART_EA16(3) - mov dx, I286_MSW - mov word ptr I286_REG[eax*2], dx - GET_NEXTPRE2 - ret - MEMORY_EA16(6) - mov ax, I286_MSW - mov word ptr I286_MEM[ecx], ax - ret - extmem_eareg16: - mov dx, I286_MSW - jmp i286_memorywrite_w - } -} - -I286 _lmsw(void) { - - __asm { - and I286_MSW, MSW_PE - PREPART_EA16(2) - mov ax, word ptr I286_REG[eax*2] - or I286_MSW, ax - GET_NEXTPRE2 - ret - MEMORY_EA16(3) - mov ax, word ptr I286_MEM[ecx] - or I286_MSW, ax - ret - EXTMEM_EA16 - or I286_MSW, ax - ret - } -} - -static const I286OP_0F cts1x_table[] = { - _sgdt, _sidt, _lgdt, _lidt, - _smsw, _smsw, _lmsw, _lmsw}; - - -// ---- - -I286EXT _xcts(void) { - - __asm { - mov edi, esi - GET_NEXTPRE1 - test bl, bl - je short i286_cts0 - dec bl - je short i286_cts1 - cmp bl, (5 - 1) - je short loadall286 - jmp expint6 - - align 4 -i286_cts0: test I286_MSW, MSW_PE - je expint6 - movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 - jmp cts0x_table[edi] - - align 4 -i286_cts1: movzx eax, bh - mov edi, eax - shr edi, 3-2 - and edi, 7*4 - jmp cts1x_table[edi] - - align 4 -loadall286: I286CLOCK(195) - mov ax, word ptr mem[0x0804] // MSW - mov I286_MSW, ax - mov ax, word ptr mem[0x0816] // TR - mov I286_TR, ax - mov ax, word ptr mem[0x0818] // flag - mov I286_FLAG, ax - and ah, 3 - cmp ah, 3 - sete I286_TRAP - mov si, word ptr mem[0x081a] // ip - mov ax, word ptr mem[0x081c] // LDTR - mov I286_LDTR, ax - mov ax, word ptr mem[0x081e] // ds - mov I286_DS, ax - mov ax, word ptr mem[0x0820] // ss - mov I286_SS, ax - mov ax, word ptr mem[0x0822] // cs - mov I286_CS, ax - mov ax, word ptr mem[0x0824] // es - mov I286_ES, ax - mov ax, word ptr mem[0x0826] // di - mov I286_DI, ax - mov ax, word ptr mem[0x0828] // si - mov I286_SI, ax - mov ax, word ptr mem[0x082a] // bp - mov I286_BP, ax - mov ax, word ptr mem[0x082c] // sp - mov I286_SP, ax - mov ax, word ptr mem[0x082e] // bx - mov I286_BX, ax - mov ax, word ptr mem[0x0830] // dx - mov I286_DX, ax - mov ax, word ptr mem[0x0832] // cx - mov I286_CX, ax - mov ax, word ptr mem[0x0834] // ax - mov I286_AX, ax - mov eax, dword ptr mem[0x0836] // es_desc - and eax, 00ffffffh - mov ES_BASE, eax - mov eax, dword ptr mem[0x083c] // cs_desc - and eax, 00ffffffh - mov CS_BASE, eax - mov eax, dword ptr mem[0x0842] // ss_desc - and eax, 00ffffffh - mov SS_BASE, eax - mov SS_FIX, eax - mov eax, dword ptr mem[0x0848] // ds_desc - and eax, 00ffffffh - mov DS_BASE, eax - mov DS_FIX, eax - - mov eax, dword ptr mem[0x084e] // GDTR - mov dword ptr (I286_GDTR.base), eax - mov ax, word ptr mem[0x0852] - mov I286_GDTR.limit, ax - - mov eax, dword ptr mem[0x0854] // LDTRC - mov dword ptr (I286_LDTRC.base), eax - mov ax, word ptr mem[0x0858] - mov I286_LDTRC.limit, ax - - mov eax, dword ptr mem[0x085a] // IDTR - mov dword ptr (I286_IDTR.base), eax - mov ax, word ptr mem[0x085e] - mov I286_IDTR.limit, ax - - mov eax, dword ptr mem[0x0860] // TRC - mov dword ptr (I286_TRC.base), eax - mov ax, word ptr mem[0x0864] - mov I286_TRC.limit, ax - - RESET_XPREFETCH - I286IRQCHECKTERM - - align 4 -expint6: mov si, di // ver0.27 このタイプ・・・ - I286CLOCK(20) // 全部修正しなきゃ(汗 - INT_NUM(6) // i286とi386で挙動が違うから - } // いやらしいね… -} - +#include +#include +#include "i286x.h" +#include "i286xadr.h" +#include "i286xcts.h" +#include "i286x.mcr" +#include "i286xea.mcr" + + +typedef void (*I286OP_0F)(void); + + +// ---- 0f 00 + +I286 _sldt(void) { + + __asm { + PREPART_EA16(2) + mov dx, I286_LDTR + mov word ptr I286_REG[eax*2], dx + GET_NEXTPRE2 + ret + MEMORY_EA16(3) + mov ax, I286_LDTR + mov word ptr I286_MEM[ecx], ax + ret + extmem_eareg16: + mov dx, I286_LDTR + jmp i286_memorywrite_w + } +} + +I286 _str(void) { + + __asm { + PREPART_EA16(3) + mov dx, I286_TR + mov word ptr I286_REG[eax*2], dx + GET_NEXTPRE2 + ret + MEMORY_EA16(6) + mov ax, I286_TR + mov word ptr I286_MEM[ecx], ax + ret + extmem_eareg16: + mov dx, I286_TR + jmp i286_memorywrite_w + } +} + +I286 _lldt(void) { + + __asm { + PREPART_EA16(17) + mov ax, word ptr I286_REG[eax*2] + call lldt_sub + GET_NEXTPRE2 + ret + MEMORY_EA16(19) + mov ax, word ptr I286_MEM[ecx] + jmp short lldt_sub + EXTMEM_EA16 + +lldt_sub: mov word ptr I286_LDTR, ax + call i286x_selector + mov ecx, eax + call i286_memoryread_w + mov I286_LDTRC.limit, ax + add ecx, 2 + call i286_memoryread_w + mov I286_LDTRC.base, ax + add ecx, 2 + call i286_memoryread + mov I286_LDTRC.base24, al + ret + } +} + +I286 _ltr(void) { + + __asm { + PREPART_EA16(17) + mov ax, word ptr I286_REG[eax*2] + call ltr_sub + GET_NEXTPRE2 + ret + MEMORY_EA16(19) + mov ax, word ptr I286_MEM[ecx] + jmp short ltr_sub + EXTMEM_EA16 + +ltr_sub: mov word ptr I286_TR, ax + call i286x_selector + mov ecx, eax + call i286_memoryread_w + mov I286_TRC.limit, ax + add ecx, 2 + call i286_memoryread_w + mov I286_TRC.base, ax + add ecx, 2 + call i286_memoryread + mov I286_TRC.base24, al + ret + } +} + +I286 _verr(void) { + + __asm { + PREPART_EA16(14) + mov ax, word ptr I286_REG[eax*2] + GET_NEXTPRE2 + ret + MEMORY_EA16(16) + mov ax, word ptr I286_MEM[ecx] + ret + EXTMEM_EA16 + ret + } +} + +I286 _verw(void) { + + __asm { + PREPART_EA16(14) + mov ax, word ptr I286_REG[eax*2] + GET_NEXTPRE2 + ret + MEMORY_EA16(16) + mov ax, word ptr I286_MEM[ecx] + ret + EXTMEM_EA16 + ret + } +} + +static const I286OP_0F cts0x_table[] = { + _sldt, _str, _lldt, _ltr, + _verr, _verw, _verr, _verw}; + + +// ---- 0f 01 + +I286 _sgdt(void) { + + __asm { + cmp al, 0c0h + jnc register_eareg16 + I286CLOCK(11) + call p_ea_dst[eax*4] + mov dx, word ptr I286_GDTR + call i286_memorywrite_w + add ecx, 2 + mov dx, word ptr (I286_GDTR + 2) + call i286_memorywrite_w + add ecx, 2 + mov dl, byte ptr (I286_GDTR + 4) + mov dh, -1 + jmp i286_memorywrite_w + align 4 + register_eareg16: + INT_NUM(6) + } +} + +I286 _sidt(void) { + + __asm { + cmp al, 0c0h + jnc register_eareg16 + I286CLOCK(12) + call p_ea_dst[eax*4] + mov dx, word ptr I286_IDTR + call i286_memorywrite_w + add ecx, 2 + mov dx, word ptr (I286_IDTR + 2) + call i286_memorywrite_w + add ecx, 2 + mov dl, byte ptr (I286_IDTR + 4) + mov dh, -1 + jmp i286_memorywrite_w + align 4 + register_eareg16: + INT_NUM(6) + } +} + +I286 _lgdt(void) { + + __asm { + cmp al, 0c0h + jnc register_eareg16 + I286CLOCK(11) + call p_ea_dst[eax*4] + call i286_memoryread_w + mov word ptr I286_GDTR, ax + add ecx, 2 + call i286_memoryread_w + mov word ptr (I286_GDTR + 2), ax + add ecx, 2 + call i286_memoryread + mov byte ptr (I286_GDTR + 4), al + ret + align 4 + register_eareg16: + INT_NUM(6) + } +} + +I286 _lidt(void) { + + __asm { + cmp al, 0c0h + jnc register_eareg16 + I286CLOCK(12) + call p_ea_dst[eax*4] + call i286_memoryread_w + mov word ptr I286_IDTR, ax + add ecx, 2 + call i286_memoryread_w + mov word ptr (I286_IDTR + 2), ax + add ecx, 2 + call i286_memoryread + mov byte ptr (I286_IDTR + 4), al + ret + align 4 + register_eareg16: + INT_NUM(6) + } +} + +I286 _smsw(void) { + + __asm { + PREPART_EA16(3) + mov dx, I286_MSW + mov word ptr I286_REG[eax*2], dx + GET_NEXTPRE2 + ret + MEMORY_EA16(6) + mov ax, I286_MSW + mov word ptr I286_MEM[ecx], ax + ret + extmem_eareg16: + mov dx, I286_MSW + jmp i286_memorywrite_w + } +} + +I286 _lmsw(void) { + + __asm { + and I286_MSW, MSW_PE + PREPART_EA16(2) + mov ax, word ptr I286_REG[eax*2] + or I286_MSW, ax + GET_NEXTPRE2 + ret + MEMORY_EA16(3) + mov ax, word ptr I286_MEM[ecx] + or I286_MSW, ax + ret + EXTMEM_EA16 + or I286_MSW, ax + ret + } +} + +static const I286OP_0F cts1x_table[] = { + _sgdt, _sidt, _lgdt, _lidt, + _smsw, _smsw, _lmsw, _lmsw}; + + +// ---- + +I286EXT _xcts(void) { + + __asm { + mov edi, esi + GET_NEXTPRE1 + test bl, bl + je short i286_cts0 + dec bl + je short i286_cts1 + cmp bl, (5 - 1) + je short loadall286 + jmp expint6 + + align 4 +i286_cts0: test I286_MSW, MSW_PE + je expint6 + movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 + jmp cts0x_table[edi] + + align 4 +i286_cts1: movzx eax, bh + mov edi, eax + shr edi, 3-2 + and edi, 7*4 + jmp cts1x_table[edi] + + align 4 +loadall286: I286CLOCK(195) + mov ax, word ptr mem[0x0804] // MSW + mov I286_MSW, ax + mov ax, word ptr mem[0x0816] // TR + mov I286_TR, ax + mov ax, word ptr mem[0x0818] // flag + mov I286_FLAG, ax + and ah, 3 + cmp ah, 3 + sete I286_TRAP + mov si, word ptr mem[0x081a] // ip + mov ax, word ptr mem[0x081c] // LDTR + mov I286_LDTR, ax + mov ax, word ptr mem[0x081e] // ds + mov I286_DS, ax + mov ax, word ptr mem[0x0820] // ss + mov I286_SS, ax + mov ax, word ptr mem[0x0822] // cs + mov I286_CS, ax + mov ax, word ptr mem[0x0824] // es + mov I286_ES, ax + mov ax, word ptr mem[0x0826] // di + mov I286_DI, ax + mov ax, word ptr mem[0x0828] // si + mov I286_SI, ax + mov ax, word ptr mem[0x082a] // bp + mov I286_BP, ax + mov ax, word ptr mem[0x082c] // sp + mov I286_SP, ax + mov ax, word ptr mem[0x082e] // bx + mov I286_BX, ax + mov ax, word ptr mem[0x0830] // dx + mov I286_DX, ax + mov ax, word ptr mem[0x0832] // cx + mov I286_CX, ax + mov ax, word ptr mem[0x0834] // ax + mov I286_AX, ax + mov eax, dword ptr mem[0x0836] // es_desc + and eax, 00ffffffh + mov ES_BASE, eax + mov eax, dword ptr mem[0x083c] // cs_desc + and eax, 00ffffffh + mov CS_BASE, eax + mov eax, dword ptr mem[0x0842] // ss_desc + and eax, 00ffffffh + mov SS_BASE, eax + mov SS_FIX, eax + mov eax, dword ptr mem[0x0848] // ds_desc + and eax, 00ffffffh + mov DS_BASE, eax + mov DS_FIX, eax + + mov eax, dword ptr mem[0x084e] // GDTR + mov dword ptr (I286_GDTR.base), eax + mov ax, word ptr mem[0x0852] + mov I286_GDTR.limit, ax + + mov eax, dword ptr mem[0x0854] // LDTRC + mov dword ptr (I286_LDTRC.base), eax + mov ax, word ptr mem[0x0858] + mov I286_LDTRC.limit, ax + + mov eax, dword ptr mem[0x085a] // IDTR + mov dword ptr (I286_IDTR.base), eax + mov ax, word ptr mem[0x085e] + mov I286_IDTR.limit, ax + + mov eax, dword ptr mem[0x0860] // TRC + mov dword ptr (I286_TRC.base), eax + mov ax, word ptr mem[0x0864] + mov I286_TRC.limit, ax + + RESET_XPREFETCH + I286IRQCHECKTERM + + align 4 +expint6: mov si, di // ver0.27 このタイプ・・・ + I286CLOCK(20) // 全部修正しなきゃ(汗 + INT_NUM(6) // i286とi386で挙動が違うから + } // いやらしいね… +} + diff --git a/i286x/i286xcts.h b/i286x/i286xcts.h old mode 100755 new mode 100644 index 82cb44fd..11030abd --- a/i286x/i286xcts.h +++ b/i286x/i286xcts.h @@ -1,3 +1,3 @@ - -void _xcts(void); - + +void _xcts(void); + diff --git a/i286x/i286xrep.h b/i286x/i286xrep.h old mode 100755 new mode 100644 index e234cd26..cef187a8 --- a/i286x/i286xrep.h +++ b/i286x/i286xrep.h @@ -1,20 +1,20 @@ -void rep_xinsb(void); -void rep_xinsw(void); -void rep_xoutsb(void); -void rep_xoutsw(void); -void rep_xmovsb(void); -void rep_xmovsw(void); -void rep_xlodsb(void); -void rep_xlodsw(void); -void rep_xstosb(void); -void rep_xstosw(void); - -void repe_xcmpsb(void); -void repne_xcmpsb(void); -void repe_xcmpsw(void); -void repne_xcmpsw(void); - -void repe_xscasb(void); -void repne_xscasb(void); -void repe_xscasw(void); -void repne_xscasw(void); +void rep_xinsb(void); +void rep_xinsw(void); +void rep_xoutsb(void); +void rep_xoutsw(void); +void rep_xmovsb(void); +void rep_xmovsw(void); +void rep_xlodsb(void); +void rep_xlodsw(void); +void rep_xstosb(void); +void rep_xstosw(void); + +void repe_xcmpsb(void); +void repne_xcmpsb(void); +void repe_xcmpsw(void); +void repne_xcmpsw(void); + +void repe_xscasb(void); +void repne_xscasb(void); +void repe_xscasw(void); +void repne_xscasw(void); diff --git a/i286x/i286xs.h b/i286x/i286xs.h old mode 100755 new mode 100644 index b52e1d9a..75cb3665 --- a/i286x/i286xs.h +++ b/i286x/i286xs.h @@ -1,24 +1,24 @@ - -extern const I286TBL op8xreg8_xtable[8]; -extern const I286TBL op8xext8_xtable[8]; -extern const I286TBL op8xreg16_xtable[8]; -extern const I286TBL op8xext16_xtable[8]; -extern const I286TBL op8xext16_atable[8]; - -extern const I286TBL sftreg8_xtable[8]; -extern const I286TBL sftmem8_xtable[8]; -extern const I286TBL sftext8_xtable[8]; -extern const I286TBL sftreg16_xtable[8]; -extern const I286TBL sftmem16_xtable[8]; -extern const I286TBL sftext16_xtable[8]; - -extern const I286TBL sftreg8cl_xtable[8]; -extern const I286TBL sftext8cl_xtable[8]; -extern const I286TBL sftreg16cl_xtable[8]; -extern const I286TBL sftext16cl_xtable[8]; - -extern const I286TBL ope0xf6_xtable[8]; -extern const I286TBL ope0xf7_xtable[8]; -extern const I286TBL ope0xfe_xtable[2]; -extern const I286TBL ope0xff_xtable[8]; - + +extern const I286TBL op8xreg8_xtable[8]; +extern const I286TBL op8xext8_xtable[8]; +extern const I286TBL op8xreg16_xtable[8]; +extern const I286TBL op8xext16_xtable[8]; +extern const I286TBL op8xext16_atable[8]; + +extern const I286TBL sftreg8_xtable[8]; +extern const I286TBL sftmem8_xtable[8]; +extern const I286TBL sftext8_xtable[8]; +extern const I286TBL sftreg16_xtable[8]; +extern const I286TBL sftmem16_xtable[8]; +extern const I286TBL sftext16_xtable[8]; + +extern const I286TBL sftreg8cl_xtable[8]; +extern const I286TBL sftext8cl_xtable[8]; +extern const I286TBL sftreg16cl_xtable[8]; +extern const I286TBL sftext16cl_xtable[8]; + +extern const I286TBL ope0xf6_xtable[8]; +extern const I286TBL ope0xf7_xtable[8]; +extern const I286TBL ope0xfe_xtable[2]; +extern const I286TBL ope0xff_xtable[8]; + diff --git a/i386c/cpucore.c b/i386c/cpucore.c old mode 100755 new mode 100644 index fc614f4d..24b08b95 --- a/i386c/cpucore.c +++ b/i386c/cpucore.c @@ -1,98 +1,98 @@ -#include -#include - -/* Z_FLAG, S_FLAG, P_FLAG, C_FLAG */ -const UINT8 iflags[512] = { - 0x44, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, - 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, - 0x45, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, - 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, - 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, - 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, - 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, - 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, - 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, - 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, - 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, - 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, - 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, - 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, - 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, - 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, - 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, - 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, - 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, - 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, - 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, - 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, - 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, - 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, - 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, - 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, - 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, - 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, - 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, - 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, - 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, - 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, - 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, - 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85 -}; - -UINT8 szpflag_w[0x10000]; - - -void i386c_initialize(void) { - - UINT32 bit; - UINT i; - UINT8 f; - - for (i=0; i<0x10000; i++) { - f = P_FLAG; - for (bit=0x80; bit; bit>>=1) { - if (i & bit) { - f ^= P_FLAG; - } - } - if (!i) { - f |= Z_FLAG; - } - if (i & 0x8000) { - f |= S_FLAG; - } - szpflag_w[i] = f; - } - - ia32_init(); -} +#include +#include + +/* Z_FLAG, S_FLAG, P_FLAG, C_FLAG */ +const UINT8 iflags[512] = { + 0x44, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, + 0x04, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x84, 0x80, 0x80, 0x84, 0x80, 0x84, 0x84, 0x80, + 0x80, 0x84, 0x84, 0x80, 0x84, 0x80, 0x80, 0x84, + 0x45, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, + 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, + 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, + 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, + 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, + 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, + 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, + 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, + 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, + 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, + 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, + 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, + 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, + 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, + 0x01, 0x05, 0x05, 0x01, 0x05, 0x01, 0x01, 0x05, + 0x05, 0x01, 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, + 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, + 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, + 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, + 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, + 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, + 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, + 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, + 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, + 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, + 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, + 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, + 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, + 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85, + 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, + 0x85, 0x81, 0x81, 0x85, 0x81, 0x85, 0x85, 0x81, + 0x81, 0x85, 0x85, 0x81, 0x85, 0x81, 0x81, 0x85 +}; + +UINT8 szpflag_w[0x10000]; + + +void i386c_initialize(void) { + + UINT32 bit; + UINT i; + UINT8 f; + + for (i=0; i<0x10000; i++) { + f = P_FLAG; + for (bit=0x80; bit; bit>>=1) { + if (i & bit) { + f ^= P_FLAG; + } + } + if (!i) { + f |= Z_FLAG; + } + if (i & 0x8000) { + f |= S_FLAG; + } + szpflag_w[i] = f; + } + + ia32_init(); +} diff --git a/i386c/cpucore.h b/i386c/cpucore.h old mode 100755 new mode 100644 index 0d9687ae..3b327257 --- a/i386c/cpucore.h +++ b/i386c/cpucore.h @@ -1,9 +1,9 @@ -#ifndef NP2_I386C_CPUCORE_H__ -#define NP2_I386C_CPUCORE_H__ - -#include - -#define I286_MEMREADMAX CPU_MEMREADMAX -#define I286_MEMWRITEMAX CPU_MEMWRITEMAX - -#endif /* !NP2_I386C_CPUCORE_H__ */ +#ifndef NP2_I386C_CPUCORE_H__ +#define NP2_I386C_CPUCORE_H__ + +#include + +#define I286_MEMREADMAX CPU_MEMREADMAX +#define I286_MEMWRITEMAX CPU_MEMWRITEMAX + +#endif /* !NP2_I386C_CPUCORE_H__ */ diff --git a/i386c/cpumem.c b/i386c/cpumem.c old mode 100755 new mode 100644 index 2a0c0f31..7683533a --- a/i386c/cpumem.c +++ b/i386c/cpumem.c @@ -1,1810 +1,1810 @@ -#include - -#if 0 -#undef TRACEOUT -//#define USE_TRACEOUT_VS -//#define MEM_BDA_TRACEOUT -//#define MEM_D8_TRACEOUT -#ifdef USE_TRACEOUT_VS -static void trace_fmt_ex(const char *fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "\n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#else -#define TRACEOUT(s) (void)(s) -#endif -#endif /* 1 */ - -#ifndef NP2_MEMORY_ASM - -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_PC9821) -#include -#endif -#include -#include -#include -#include -#if defined(SUPPORT_CL_GD5430) -#include -#endif -#if defined(SUPPORT_PCI) -#include -#endif -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif - - -#if defined(SUPPORT_IA32_HAXM) - UINT8 *mem = NULL; // Alloc in pccore_mem_malloc() -#else - UINT8 mem[0x200000]; -#endif - - -typedef void (MEMCALL * MEM8WRITE)(UINT32 address, REG8 value); -typedef REG8 (MEMCALL * MEM8READ)(UINT32 address); -typedef void (MEMCALL * MEM16WRITE)(UINT32 address, REG16 value); -typedef REG16 (MEMCALL * MEM16READ)(UINT32 address); -typedef void (MEMCALL * MEM32WRITE)(UINT32 address, UINT32 value); -typedef UINT32 (MEMCALL * MEM32READ)(UINT32 address); - - -// ---- MAIN - -static REG8 MEMCALL memmain_rd8(UINT32 address) { - - return(mem[address]); -} - -static REG16 MEMCALL memmain_rd16(UINT32 address) { - -const UINT8 *ptr; - - ptr = mem + address; - return(LOADINTELWORD(ptr)); -} - -static UINT32 MEMCALL memmain_rd32(UINT32 address) { - -const UINT8 *ptr; - - ptr = mem + address; - return(LOADINTELDWORD(ptr)); -} - -static void MEMCALL memmain_wr8(UINT32 address, REG8 value) { - - mem[address] = (UINT8)value; -} - -static void MEMCALL memmain_wr16(UINT32 address, REG16 value) { - - UINT8 *ptr; - - ptr = mem + address; - STOREINTELWORD(ptr, value); -} - -static void MEMCALL memmain_wr32(UINT32 address, UINT32 value) { - - UINT8 *ptr; - - ptr = mem + address; - STOREINTELDWORD(ptr, value); -} - - -// ---- N/C - -static REG8 MEMCALL memnc_rd8(UINT32 address) { - - (void)address; - return(0xff); -} - -static REG16 MEMCALL memnc_rd16(UINT32 address) { - - (void)address; - return(0xffff); -} - -static UINT32 MEMCALL memnc_rd32(UINT32 address) { - - (void)address; - return(0xffffffff); -} - -static void MEMCALL memnc_wr8(UINT32 address, REG8 value) { - - (void)address; - (void)value; -} - -static void MEMCALL memnc_wr16(UINT32 address, REG16 value) { - -// 強制RAM化 -// (void)address; -// (void)value; - - UINT8 *ptr; - UINT16 bit; - - ptr = mem + address; - bit = 1 << ((address >> 12) & 15); - if ((address + 1) & 0xfff) { - if (CPU_RAM_D000 & bit) { - STOREINTELWORD(ptr, value); - } - } - else { - if (CPU_RAM_D000 & bit) { - ptr[0] = (UINT8)value; - } - if (CPU_RAM_D000 & (bit << 1)) { - ptr[1] = (UINT8)(value >> 8); - } - } -// -} - -static void MEMCALL memnc_wr32(UINT32 address, UINT32 value) { - - (void)address; - (void)value; -} - - -// ---- memory 000000-0ffffff + 64KB - -typedef struct { - MEM8READ rd8[0x22]; - MEM8WRITE wr8[0x22]; - MEM16READ rd16[0x22]; - MEM16WRITE wr16[0x22]; - MEM32READ rd32[0x22]; - MEM32WRITE wr32[0x22]; -} MEMFN0; - -typedef struct { - MEM8READ brd8; // E8000-F7FFF byte read - MEM8READ ird8; // F8000-FFFFF byte read - MEM8WRITE bwr8; // E8000-FFFFF byte write - MEM16READ brd16; // E8000-F7FFF word read - MEM16READ ird16; // F8000-FFFFF word read - MEM16WRITE bwr16; // F8000-FFFFF word write - MEM32READ brd32; // E8000-F7FFF word read - MEM32READ ird32; // F8000-FFFFF word read - MEM32WRITE bwr32; // F8000-FFFFF word write -} MMAPTBL; - -typedef struct { - MEM8READ rd8; - MEM8WRITE wr8; - MEM16READ rd16; - MEM16WRITE wr16; - MEM32READ rd32; - MEM32WRITE wr32; -} VACCTBL; - -static MEMFN0 memfn0 = { - {memmain_rd8, memmain_rd8, memmain_rd8, memmain_rd8, // 00 - memmain_rd8, memmain_rd8, memmain_rd8, memmain_rd8, // 20 - memmain_rd8, memmain_rd8, memmain_rd8, memmain_rd8, // 40 - memmain_rd8, memmain_rd8, memmain_rd8, memmain_rd8, // 60 - memmain_rd8, memmain_rd8, memmain_rd8, memmain_rd8, // 80 - memtram_rd8, memvram0_rd8, memvram0_rd8, memvram0_rd8, // a0 - memems_rd8, memems_rd8, memmain_rd8, memmain_rd8, // c0 - memvram0_rd8, memmain_rd8, memmain_rd8, memf800_rd8, // e0 - memmain_rd8, memmain_rd8}, - - {memmain_wr8, memmain_wr8, memmain_wr8, memmain_wr8, // 00 - memmain_wr8, memmain_wr8, memmain_wr8, memmain_wr8, // 20 - memmain_wr8, memmain_wr8, memmain_wr8, memmain_wr8, // 40 - memmain_wr8, memmain_wr8, memmain_wr8, memmain_wr8, // 60 - memmain_wr8, memmain_wr8, memmain_wr8, memmain_wr8, // 80 - memtram_wr8, memvram0_wr8, memvram0_wr8, memvram0_wr8, // a0 - memems_wr8, memems_wr8, memd000_wr8, memd000_wr8, // c0 - memvram0_wr8, memnc_wr8, memnc_wr8, memnc_wr8, // e0 - memmain_wr8, memmain_wr8}, - - {memmain_rd16, memmain_rd16, memmain_rd16, memmain_rd16, // 00 - memmain_rd16, memmain_rd16, memmain_rd16, memmain_rd16, // 20 - memmain_rd16, memmain_rd16, memmain_rd16, memmain_rd16, // 40 - memmain_rd16, memmain_rd16, memmain_rd16, memmain_rd16, // 60 - memmain_rd16, memmain_rd16, memmain_rd16, memmain_rd16, // 80 - memtram_rd16, memvram0_rd16, memvram0_rd16, memvram0_rd16, // a0 - memems_rd16, memems_rd16, memmain_rd16, memmain_rd16, // c0 - memvram0_rd16, memmain_rd16, memmain_rd16, memf800_rd16, // e0 - memmain_rd16, memmain_rd16}, - - {memmain_wr16, memmain_wr16, memmain_wr16, memmain_wr16, // 00 - memmain_wr16, memmain_wr16, memmain_wr16, memmain_wr16, // 20 - memmain_wr16, memmain_wr16, memmain_wr16, memmain_wr16, // 40 - memmain_wr16, memmain_wr16, memmain_wr16, memmain_wr16, // 60 - memmain_wr16, memmain_wr16, memmain_wr16, memmain_wr16, // 80 - memtram_wr16, memvram0_wr16, memvram0_wr16, memvram0_wr16, // a0 - memems_wr16, memems_wr16, memd000_wr16, memd000_wr16, // c0 - memvram0_wr16, memnc_wr16, memnc_wr16, memnc_wr16, // e0 - memmain_wr16, memmain_wr16}, - - {memmain_rd32, memmain_rd32, memmain_rd32, memmain_rd32, // 00 - memmain_rd32, memmain_rd32, memmain_rd32, memmain_rd32, // 20 - memmain_rd32, memmain_rd32, memmain_rd32, memmain_rd32, // 40 - memmain_rd32, memmain_rd32, memmain_rd32, memmain_rd32, // 60 - memmain_rd32, memmain_rd32, memmain_rd32, memmain_rd32, // 80 - memtram_rd32, memvram0_rd32, memvram0_rd32, memvram0_rd32, // a0 - memems_rd32, memems_rd32, memmain_rd32, memmain_rd32, // c0 - memvram0_rd32, memmain_rd32, memmain_rd32, memf800_rd32, // e0 - memmain_rd32, memmain_rd32}, - - {memmain_wr32, memmain_wr32, memmain_wr32, memmain_wr32, // 00 - memmain_wr32, memmain_wr32, memmain_wr32, memmain_wr32, // 20 - memmain_wr32, memmain_wr32, memmain_wr32, memmain_wr32, // 40 - memmain_wr32, memmain_wr32, memmain_wr32, memmain_wr32, // 60 - memmain_wr32, memmain_wr32, memmain_wr32, memmain_wr32, // 80 - memtram_wr32, memvram0_wr32, memvram0_wr32, memvram0_wr32, // a0 - memems_wr32, memems_wr32, memd000_wr32, memd000_wr32, // c0 - memvram0_wr32, memnc_wr32, memnc_wr32, memnc_wr32, // e0 - memmain_wr32, memmain_wr32}}; - -static const MMAPTBL mmaptbl[2] = { - {memmain_rd8, memf800_rd8, memnc_wr8, - memmain_rd16, memf800_rd16, memnc_wr16, - memmain_rd32, memf800_rd32, memnc_wr32}, - {memf800_rd8, memf800_rd8, memepson_wr8, - memf800_rd16, memf800_rd16, memepson_wr16, - memf800_rd32, memf800_rd32, memepson_wr32}}; - -static const VACCTBL vacctbl[0x10] = { - {memvram0_rd8, memvram0_wr8, memvram0_rd16, memvram0_wr16, memvram0_rd32, memvram0_wr32, }, // 00 - {memvram1_rd8, memvram1_wr8, memvram1_rd16, memvram1_wr16, memvram1_rd32, memvram1_wr32, }, - {memvram0_rd8, memvram0_wr8, memvram0_rd16, memvram0_wr16, memvram0_rd32, memvram0_wr32, }, - {memvram1_rd8, memvram1_wr8, memvram1_rd16, memvram1_wr16, memvram1_rd32, memvram1_wr32, }, - {memvram0_rd8, memvram0_wr8, memvram0_rd16, memvram0_wr16, memvram0_rd32, memvram0_wr32, }, // 40 - {memvram1_rd8, memvram1_wr8, memvram1_rd16, memvram1_wr16, memvram1_rd32, memvram1_wr32, }, - {memvram0_rd8, memvram0_wr8, memvram0_rd16, memvram0_wr16, memvram0_rd32, memvram0_wr32, }, - {memvram1_rd8, memvram1_wr8, memvram1_rd16, memvram1_wr16, memvram1_rd32, memvram1_wr32, }, - {memtcr0_rd8, memtdw0_wr8, memtcr0_rd16, memtdw0_wr16, memtcr0_rd32, memtdw0_wr32, }, // 80 - {memtcr1_rd8, memtdw1_wr8, memtcr1_rd16, memtdw1_wr16, memtcr1_rd32, memtdw1_wr32, }, - {memegc_rd8, memegc_wr8, memegc_rd16, memegc_wr16, memegc_rd32, memegc_wr32, }, - {memegc_rd8, memegc_wr8, memegc_rd16, memegc_wr16, memegc_rd32, memegc_wr32, }, - {memvram0_rd8, memrmw0_wr8, memvram0_rd16, memrmw0_wr16, memvram0_rd32, memrmw0_wr32, }, // c0 - {memvram1_rd8, memrmw1_wr8, memvram1_rd16, memrmw1_wr16, memvram1_rd32, memrmw1_wr32, }, - {memegc_rd8, memegc_wr8, memegc_rd16, memegc_wr16, memegc_rd32, memegc_wr32, }, - {memegc_rd8, memegc_wr8, memegc_rd16, memegc_wr16, memegc_rd32, memegc_wr32, }}; - - -void MEMCALL memm_arch(UINT type) { - -const MMAPTBL *mm; - - mm = mmaptbl + (type & 1); - - memfn0.rd8[0xe8000 >> 15] = mm->brd8; - memfn0.rd8[0xf0000 >> 15] = mm->brd8; - memfn0.rd8[0xf8000 >> 15] = mm->ird8; - memfn0.wr8[0xe8000 >> 15] = mm->bwr8; - memfn0.wr8[0xf0000 >> 15] = mm->bwr8; - memfn0.wr8[0xf8000 >> 15] = mm->bwr8; - - memfn0.rd16[0xe8000 >> 15] = mm->brd16; - memfn0.rd16[0xf0000 >> 15] = mm->brd16; - memfn0.rd16[0xf8000 >> 15] = mm->ird16; - memfn0.wr16[0xe8000 >> 15] = mm->bwr16; - memfn0.wr16[0xf0000 >> 15] = mm->bwr16; - memfn0.wr16[0xf8000 >> 15] = mm->bwr16; - - memfn0.rd32[0xe8000 >> 15] = mm->brd32; - memfn0.rd32[0xf0000 >> 15] = mm->brd32; - memfn0.rd32[0xf8000 >> 15] = mm->ird32; - memfn0.wr32[0xe8000 >> 15] = mm->bwr32; - memfn0.wr32[0xf0000 >> 15] = mm->bwr32; - memfn0.wr32[0xf8000 >> 15] = mm->bwr32; -} - -void MEMCALL memm_vram(UINT func) { - -const VACCTBL *vacc; - -#if defined(SUPPORT_PC9821) - if (!(func & 0x20)) { -#endif // defined(SUPPORT_PC9821) - vacc = vacctbl + (func & 0x0f); -#if defined(SUPPORT_IA32_HAXM) - if (np2hax.enable) { - if ((func & 0x0f) < 8) { - if(np2haxcore.lastVRAMMMIO){ - i386hax_vm_setmemoryarea(mem+0xA8000, 0xA8000, 0x8000); - i386hax_vm_setmemoryarea(mem+0xB0000, 0xB0000, 0x10000); - np2haxcore.lastVRAMMMIO = 0; - } - }else{ - if(!np2haxcore.lastVRAMMMIO){ - i386hax_vm_removememoryarea(mem+0xA8000, 0xA8000, 0x8000); - i386hax_vm_removememoryarea(mem+0xB0000, 0xB0000, 0x10000); - np2haxcore.lastVRAMMMIO = 1; - } - } - } -#endif - - memfn0.rd8[0xa8000 >> 15] = vacc->rd8; - memfn0.rd8[0xb0000 >> 15] = vacc->rd8; - memfn0.rd8[0xb8000 >> 15] = vacc->rd8; - memfn0.rd8[0xe0000 >> 15] = vacc->rd8; - - memfn0.wr8[0xa8000 >> 15] = vacc->wr8; - memfn0.wr8[0xb0000 >> 15] = vacc->wr8; - memfn0.wr8[0xb8000 >> 15] = vacc->wr8; - memfn0.wr8[0xe0000 >> 15] = vacc->wr8; - - memfn0.rd16[0xa8000 >> 15] = vacc->rd16; - memfn0.rd16[0xb0000 >> 15] = vacc->rd16; - memfn0.rd16[0xb8000 >> 15] = vacc->rd16; - memfn0.rd16[0xe0000 >> 15] = vacc->rd16; - - memfn0.wr16[0xa8000 >> 15] = vacc->wr16; - memfn0.wr16[0xb0000 >> 15] = vacc->wr16; - memfn0.wr16[0xb8000 >> 15] = vacc->wr16; - memfn0.wr16[0xe0000 >> 15] = vacc->wr16; - - memfn0.rd32[0xa8000 >> 15] = vacc->rd32; - memfn0.rd32[0xb0000 >> 15] = vacc->rd32; - memfn0.rd32[0xb8000 >> 15] = vacc->rd32; - memfn0.rd32[0xe0000 >> 15] = vacc->rd32; - - memfn0.wr32[0xa8000 >> 15] = vacc->wr32; - memfn0.wr32[0xb0000 >> 15] = vacc->wr32; - memfn0.wr32[0xb8000 >> 15] = vacc->wr32; - memfn0.wr32[0xe0000 >> 15] = vacc->wr32; - - if (!(func & (1 << VOPBIT_ANALOG))) { // digital - memfn0.rd8[0xe0000 >> 15] = memnc_rd8; - memfn0.wr8[0xe0000 >> 15] = memnc_wr8; - memfn0.rd16[0xe0000 >> 15] = memnc_rd16; - memfn0.wr16[0xe0000 >> 15] = memnc_wr16; - memfn0.rd32[0xe0000 >> 15] = memnc_rd32; - memfn0.wr32[0xe0000 >> 15] = memnc_wr32; - } -#if defined(SUPPORT_PC9821) - } - else { -#if defined(SUPPORT_IA32_HAXM) - if (np2hax.enable) { - if(!np2haxcore.lastVRAMMMIO){ - i386hax_vm_removememoryarea(mem+0xA8000, 0xA8000, 0x8000); - i386hax_vm_removememoryarea(mem+0xB0000, 0xB0000, 0x10000); - np2haxcore.lastVRAMMMIO = 1; - } - } -#endif - - memfn0.rd8[0xa8000 >> 15] = memvga0_rd8; - memfn0.rd8[0xb0000 >> 15] = memvga1_rd8; - memfn0.rd8[0xb8000 >> 15] = memnc_rd8; - memfn0.rd8[0xe0000 >> 15] = memvgaio_rd8; - - memfn0.wr8[0xa8000 >> 15] = memvga0_wr8; - memfn0.wr8[0xb0000 >> 15] = memvga1_wr8; - memfn0.wr8[0xb8000 >> 15] = memnc_wr8; - memfn0.wr8[0xe0000 >> 15] = memvgaio_wr8; - - memfn0.rd16[0xa8000 >> 15] = memvga0_rd16; - memfn0.rd16[0xb0000 >> 15] = memvga1_rd16; - memfn0.rd16[0xb8000 >> 15] = memnc_rd16; - memfn0.rd16[0xe0000 >> 15] = memvgaio_rd16; - - memfn0.wr16[0xa8000 >> 15] = memvga0_wr16; - memfn0.wr16[0xb0000 >> 15] = memvga1_wr16; - memfn0.wr16[0xb8000 >> 15] = memnc_wr16; - memfn0.wr16[0xe0000 >> 15] = memvgaio_wr16; - - memfn0.rd32[0xa8000 >> 15] = memvga0_rd32; - memfn0.rd32[0xb0000 >> 15] = memvga1_rd32; - memfn0.rd32[0xb8000 >> 15] = memnc_rd32; - memfn0.rd32[0xe0000 >> 15] = memvgaio_rd32; - - memfn0.wr32[0xa8000 >> 15] = memvga0_wr32; - memfn0.wr32[0xb0000 >> 15] = memvga1_wr32; - memfn0.wr32[0xb8000 >> 15] = memnc_wr32; - memfn0.wr32[0xe0000 >> 15] = memvgaio_wr32; - } -#endif // defined(SUPPORT_PC9821) -} - - -// ---- memory f00000-fffffff - -typedef struct { - MEM8READ rd8[8]; - MEM8WRITE wr8[8]; - MEM16READ rd16[8]; - MEM16WRITE wr16[8]; - MEM32READ rd32[8]; - MEM32WRITE wr32[8]; -} MEMFNF; - - -static REG8 MEMCALL memsys_rd8(UINT32 address) { - - address -= 0xf00000; - return(memfn0.rd8[address >> 15](address)); -} - -static REG16 MEMCALL memsys_rd16(UINT32 address) { - - address -= 0xf00000; - return(memfn0.rd16[address >> 15](address)); -} - -static UINT32 MEMCALL memsys_rd32(UINT32 address) { - - address -= 0xf00000; - return(memfn0.rd32[address >> 15](address)); -} - -static void MEMCALL memsys_wr8(UINT32 address, REG8 value) { - - address -= 0xf00000; - memfn0.wr8[address >> 15](address, value); -} - -static void MEMCALL memsys_wr16(UINT32 address, REG16 value) { - - address -= 0xf00000; - memfn0.wr16[address >> 15](address, value); -} - -static void MEMCALL memsys_wr32(UINT32 address, UINT32 value) { - - address -= 0xf00000; - memfn0.wr32[address >> 15](address, value); -} - -#if defined(SUPPORT_PC9821) -static const MEMFNF memfnf = { - {memvgaf_rd8, memvgaf_rd8, memvgaf_rd8, memvgaf_rd8, - memnc_rd8, memsys_rd8, memsys_rd8, memsys_rd8}, - {memvgaf_wr8, memvgaf_wr8, memvgaf_wr8, memvgaf_wr8, - memnc_wr8, memsys_wr8, memsys_wr8, memsys_wr8}, - - {memvgaf_rd16, memvgaf_rd16, memvgaf_rd16, memvgaf_rd16, - memnc_rd16, memsys_rd16, memsys_rd16, memsys_rd16}, - {memvgaf_wr16, memvgaf_wr16, memvgaf_wr16, memvgaf_wr16, - memnc_wr16, memsys_wr16, memsys_wr16, memsys_wr16}, - - {memvgaf_rd32, memvgaf_rd32, memvgaf_rd32, memvgaf_rd32, - memnc_rd32, memsys_rd32, memsys_rd32, memsys_rd32}, - {memvgaf_wr32, memvgaf_wr32, memvgaf_wr32, memvgaf_wr32, - memnc_wr32, memsys_wr32, memsys_wr32, memsys_wr32}}; -#else -static const MEMFNF memfnf = { - {memnc_rd8, memnc_rd8, memnc_rd8, memnc_rd8, - memnc_rd8, memsys_rd8, memsys_rd8, memsys_rd8}, - {memnc_wr8, memnc_wr8, memnc_wr8, memnc_wr8, - memnc_wr8, memsys_wr8, memsys_wr8, memsys_wr8}, - - {memnc_rd16, memnc_rd16, memnc_rd16, memnc_rd16, - memnc_rd16, memsys_rd16, memsys_rd16, memsys_rd16}, - {memnc_wr16, memnc_wr16, memnc_wr16, memnc_wr16, - memnc_wr16, memsys_wr16, memsys_wr16, memsys_wr16}, - - {memvgaf_rd32, memvgaf_rd32, memvgaf_rd32, memvgaf_rd32, - memnc_rd32, memsys_rd32, memsys_rd32, memsys_rd32}, - {memvgaf_wr32, memvgaf_wr32, memvgaf_wr32, memvgaf_wr32, - memnc_wr32, memsys_wr32, memsys_wr32, memsys_wr32}}; -#endif - -// ---- -REG8 MEMCALL memp_read8(UINT32 address) { - -#ifdef MEM_BDA_TRACEOUT - if(0x400 <= address && address < 0x600){ - switch(address){ - case 0x55f: - case 0x58a: - break; - default: - TRACEOUT(("BDA (read8): %x ret %x", address, mem[address])); - } - } -#endif -#ifdef MEM_D8_TRACEOUT - if(0xD8000 <= address && address < 0xDC000){ - TRACEOUT(("D8000h (read8): %x ret %x", address, mem[address])); - } -#endif - //if (0xD4000 <= address && address <= 0xD5FFF) { - // printf("GP-IB BIOS memread"); - //} - //if (0x400 <= address && address <= 0x5ff) { - // printf("BDA (read8): %x ret %x", address, mem[address]); - //} - //if (address == 0xf0000) { - // printf("SYS (read8): %x ret %x", address, *((UINT8*)(mem+address))); - //} - if (address < I286_MEMREADMAX) { - return(mem[address]); - } - else { -#if defined(SUPPORT_CL_GD5430) - if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ - UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; - UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; - UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; - if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ - UINT32 addrofs = address - np2clvga.pciLFB_Addr; - if(addrofs < 0x1000000){ - return cirrus_linear_readb(cirrusvga_opaque, address); - }else if( addrofs < 0x1000000 + 0x400000){ - return cirrus_linear_bitblt_readb(cirrusvga_opaque, address); - }else{ - return 0xff; - } - }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ - if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI || ((np2clvga.pciMMIO_Addr & 0xfff00000) != 0xf00000 || !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))) - return cirrus_mmio_read[0](cirrusvga_opaque, address); - } - if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ - if(vramWndAddr){ - if(vramWndAddr <= address){ - if(address < vramWndAddr + VRAMWINDOW_SIZE){ - return cirrus_linear_readb(cirrusvga_opaque, address); - }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ - if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT) - return cirrus_linear_readb(cirrusvga_opaque, address); - } - } - } - if(vramWndAddr3){ - UINT32 addr3 = address; - if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX && !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))){ - return CIRRUS_VRAMWND3_FUNC_rb(cirrusvga_opaque, addr3); - } - } - if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ - UINT32 addr2 = address; - if((vramWndAddr2 & 0xfff00000UL) == 0){ - UINT32 addrtmp = addr2 & 0xfff80000UL; - if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ - // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF - addr2 = addr2 & 0xfffff; - } - } - if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ - return CIRRUS_VRAMWND2_FUNC_rb(cirrusvga_opaque, addr2); - } - } - } - } -#endif - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - return(memfn0.rd8[address >> 15](address)); - } - else if (address < CPU_EXTLIMIT16) { - return(CPU_EXTMEMBASE[address]); - } - else if (address < 0x00f00000) { - return(0xff); - } - else if (address < 0x01000000) { - return(memfnf.rd8[(address >> 17) & 7](address)); - } -#if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - return(CPU_EXTMEMBASE[address]); - } -#endif // defined(CPU_EXTLIMIT) -#if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - return(memvgaf_rd8(address)); - } -#endif // defined(SUPPORT_PC9821) - else { -// TRACEOUT(("out of mem (read8): %x", address)); - return(0xff); - } - } -} - -REG16 MEMCALL memp_read16(UINT32 address) { - - REG16 ret; - -#ifdef MEM_BDA_TRACEOUT - if(0x400 <= address && address < 0x600){ - switch(address){ - case 0x55f: - case 0x58a: - break; - default: - TRACEOUT(("BDA (read16): %x ret %x", address, *((UINT16*)(mem+address)))); - } - } -#endif -#ifdef MEM_D8_TRACEOUT - if(0xD8000 <= address && address < 0xDC000){ - TRACEOUT(("D8000h (read16): %x ret %x", address, *((UINT16*)(mem+address)))); - } -#endif - //if (address == 0xf0000) { - // printf("SYS (read16): %x ret %x", address, *((UINT16*)(mem+address))); - //} - //if (0x400 <= address && address <= 0x5ff && address != 0x58a && address != 0x58b) { - // printf("BDA (read16): %x ret %x", address, *((UINT16*)(mem+address))); - //} - if (address < (I286_MEMREADMAX - 1)) { - return(LOADINTELWORD(mem + address)); - } - else { - if ((address + 1) & 0x7fff) { // non 32kb boundary -#if defined(SUPPORT_CL_GD5430) - if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ - UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; - UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; - UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; - if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ - UINT32 addrofs = address - np2clvga.pciLFB_Addr; - if(addrofs < 0x1000000){ - return cirrus_linear_readw(cirrusvga_opaque, address); - }else if( addrofs < 0x1000000 + 0x400000){ - return cirrus_linear_bitblt_readw(cirrusvga_opaque, address); - }else{ - return 0xffff; - } - }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ - if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI || ((np2clvga.pciMMIO_Addr & 0xfff00000) != 0xf00000 || !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))) - return cirrus_mmio_read[1](cirrusvga_opaque, address); - } - if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ - if(vramWndAddr){ - if(vramWndAddr <= address){ - if(address < vramWndAddr + VRAMWINDOW_SIZE){ - return cirrus_linear_readw(cirrusvga_opaque, address); - }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ - if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT) - return cirrus_linear_readw(cirrusvga_opaque, address); - } - } - } - if(vramWndAddr3){ - UINT32 addr3 = address; - if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX && !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))){ - return CIRRUS_VRAMWND3_FUNC_rw(cirrusvga_opaque, addr3); - } - } - if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ - UINT32 addr2 = address; - if((vramWndAddr2 & 0xfff00000UL) == 0){ - UINT32 addrtmp = addr2 & 0xfff80000UL; - if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ - // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF - addr2 = addr2 & 0xfffff; - } - } - if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ - return CIRRUS_VRAMWND2_FUNC_rw(cirrusvga_opaque, addr2); - } - } - } - } -#endif - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - return(memfn0.rd16[address >> 15](address)); - } - else if (address < CPU_EXTLIMIT16) { - return(LOADINTELWORD(CPU_EXTMEMBASE + address)); - } - else if (address < 0x00f00000) { - return(0xffff); - } - else if (address < 0x01000000) { - return(memfnf.rd16[(address >> 17) & 7](address)); - } - #if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - return(LOADINTELWORD(CPU_EXTMEMBASE + address)); - } - #endif // defined(CPU_EXTLIMIT) - #if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - return(memvgaf_rd16(address)); - } - #endif // defined(SUPPORT_PC9821) - else { - // TRACEOUT(("out of mem (read16): %x", address)); - return(0xffff); - } - } - else { - ret = memp_read8(address + 0); - ret |= (REG16)(memp_read8(address + 1) << 8); - return(ret); - } - } -} - -UINT32 MEMCALL memp_read32(UINT32 address) { - - //UINT32 pos; - UINT32 ret; - -#ifdef MEM_BDA_TRACEOUT - if(0x400 <= address && address < 0x600){ - switch(address){ - case 0x55f: - case 0x58a: - break; - default: - TRACEOUT(("BDA (read32): %x ret %x", address, *((UINT32*)(mem+address)))); - } - } -#endif -#ifdef MEM_D8_TRACEOUT - if(0xD8000 <= address && address < 0xDC000){ - TRACEOUT(("D8000h (read32): %x ret %x", address, *((UINT32*)(mem+address)))); - } -#endif - //if (0x400 <= address && address <= 0x5ff) { - // printf("BDA (read32): %x ret %x", address, *((UINT32*)(mem+address))); - //} - //if (address == 0xf0000) { - // printf("SYS (read32): %x ret %x", address, *((UINT32*)(mem+address))); - //} - if (address < (I286_MEMREADMAX - 3)) { - return(LOADINTELDWORD(mem + address)); - } - else{ - if ((address & 0x7fff) <= 0x8000 - 4) { // non 32kb boundary -#if defined(SUPPORT_CL_GD5430) - if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ - UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; - UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; - UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; - if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ - UINT32 addrofs = address - np2clvga.pciLFB_Addr; - if(addrofs < 0x1000000){ - return cirrus_linear_readl(cirrusvga_opaque, address); - }else if( addrofs < 0x1000000 + 0x400000){ - return cirrus_linear_bitblt_readl(cirrusvga_opaque, address); - }else{ - return 0xffffffff; - } - }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ - if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI || ((np2clvga.pciMMIO_Addr & 0xfff00000) != 0xf00000 || !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))) - return cirrus_mmio_read[2](cirrusvga_opaque, address); - } - if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ - if(vramWndAddr){ - if(vramWndAddr <= address){ - if(address < vramWndAddr + VRAMWINDOW_SIZE){ - return cirrus_linear_readl(cirrusvga_opaque, address); - }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ - if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT) - return cirrus_linear_readl(cirrusvga_opaque, address); - } - } - } - if(vramWndAddr3){ - UINT32 addr3 = address; - if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX && !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))){ - return CIRRUS_VRAMWND3_FUNC_rl(cirrusvga_opaque, addr3); - } - } - if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ - UINT32 addr2 = address; - if((vramWndAddr2 & 0xfff00000UL) == 0){ - UINT32 addrtmp = addr2 & 0xfff80000UL; - if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ - // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF - addr2 = addr2 & 0xfffff; - } - } - if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ - return CIRRUS_VRAMWND2_FUNC_rl(cirrusvga_opaque, addr2); - } - } - } - } -#endif - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - return(memfn0.rd32[address >> 15](address)); - } - else if (address < CPU_EXTLIMIT16) { - return(LOADINTELDWORD(CPU_EXTMEMBASE + address)); - } - else if (address < 0x00f00000) { - return(0xffff); - } - else if (address < 0x01000000) { - return(memfnf.rd32[(address >> 17) & 7](address)); - } - #if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - return(LOADINTELDWORD(CPU_EXTMEMBASE + address)); - } - #endif // defined(CPU_EXTLIMIT) - #if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - return(memvgaf_rd32(address)); - } - #endif // defined(SUPPORT_PC9821) - else { - // TRACEOUT(("out of mem (read32): %x", address)); - return(0xffffffff); - } - } - else { - if (!(address & 1)) { - ret = memp_read16(address + 0); - ret |= (UINT32)memp_read16(address + 2) << 16; - } - else { - ret = memp_read8(address + 0); - ret |= (UINT32)memp_read16(address + 1) << 8; - ret |= (UINT32)memp_read8(address + 3) << 24; - } - return(ret); - } - } -} - -// ---- -PF_UINT8 MEMCALL memp_read8_codefetch(UINT32 address) { - - if (address < I286_MEMREADMAX) { - return(mem[address]); - } - else { - //if(pcidev.bios32entrypoint <= address && address < pcidev.bios32entrypoint + sizeof(pcidev.biosdata.data8)){ - // printf("BIOS32 (read8): %x"); - //} - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - return(memfn0.rd8[address >> 15](address)); - } - else if (address < CPU_EXTLIMIT16) { - return(CPU_EXTMEMBASE[address]); - } - else if (address < 0x00f00000) { - return(0xff); - } - else if (address < 0x01000000) { - return(memfnf.rd8[(address >> 17) & 7](address)); - } -#if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - return(CPU_EXTMEMBASE[address]); - } -#endif // defined(CPU_EXTLIMIT) -#if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - return(memvgaf_rd8(address)); - } -#endif // defined(SUPPORT_PC9821) - else { -// TRACEOUT(("out of mem (read8): %x", address)); - return(0xff); - } - } -} -PF_UINT16 MEMCALL memp_read16_codefetch(UINT32 address) { - - PF_UINT16 ret; - - if (address < (I286_MEMREADMAX - 1)) { - return(LOADINTELWORD(mem + address)); - } - else { - if ((address + 1) & 0x7fff) { // non 32kb boundary - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - return(memfn0.rd16[address >> 15](address)); - } - else if (address < CPU_EXTLIMIT16) { - return(LOADINTELWORD(CPU_EXTMEMBASE + address)); - } - else if (address < 0x00f00000) { - return(0xffff); - } - else if (address < 0x01000000) { - return(memfnf.rd16[(address >> 17) & 7](address)); - } - #if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - return(LOADINTELWORD(CPU_EXTMEMBASE + address)); - } - #endif // defined(CPU_EXTLIMIT) - #if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - return(memvgaf_rd16(address)); - } - #endif // defined(SUPPORT_PC9821) - else { - // TRACEOUT(("out of mem (read16): %x", address)); - return(0xffff); - } - } - else { - ret = memp_read8(address + 0); - ret |= (REG16)(memp_read8(address + 1) << 8); - return(ret); - } - } -} - -UINT32 MEMCALL memp_read32_codefetch(UINT32 address) { - - //UINT32 pos; - UINT32 ret; - - if (address < (I286_MEMREADMAX - 3)) { - return(LOADINTELDWORD(mem + address)); - } - else{ - if ((address & 0x7fff) <= 0x8000 - 4) { // non 32kb boundary - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - return(memfn0.rd32[address >> 15](address)); - } - else if (address < CPU_EXTLIMIT16) { - return(LOADINTELDWORD(CPU_EXTMEMBASE + address)); - } - else if (address < 0x00f00000) { - return(0xffff); - } - else if (address < 0x01000000) { - return(memfnf.rd32[(address >> 17) & 7](address)); - } - #if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - return(LOADINTELDWORD(CPU_EXTMEMBASE + address)); - } - #endif // defined(CPU_EXTLIMIT) - #if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - return(memvgaf_rd32(address)); - } - #endif // defined(SUPPORT_PC9821) - else { - // TRACEOUT(("out of mem (read32): %x", address)); - return(0xffffffff); - } - } - else { - if (!(address & 1)) { - ret = memp_read16(address + 0); - ret |= (UINT32)memp_read16(address + 2) << 16; - } - else { - ret = memp_read8(address + 0); - ret |= (UINT32)memp_read16(address + 1) << 8; - ret |= (UINT32)memp_read8(address + 3) << 24; - } - return(ret); - } - } -} - -// ---- -PF_UINT8 MEMCALL memp_read8_paging(UINT32 address) { - - return memp_read8_codefetch(address); -} -PF_UINT16 MEMCALL memp_read16_paging(UINT32 address) { - - return memp_read16_codefetch(address); -} - -PF_UINT32 MEMCALL memp_read32_paging(UINT32 address) { - - return memp_read32_codefetch(address); -} - -void MEMCALL memp_write8(UINT32 address, REG8 value) { - -#ifdef MEM_BDA_TRACEOUT - if(0x400 <= address && address < 0x600){ - switch(address){ - case 0x55e: - case 0x564: - case 0x565: - case 0x566: - case 0x567: - case 0x568: - case 0x569: - case 0x56a: - case 0x58a: - break; - case 0x4f8: - case 0x4f9: - case 0x4fa: - case 0x4fb: - case 0x4fc: - break; - default: - TRACEOUT(("BDA (write8): %x val %x -> %x", address, mem[address], value)); - } - } -#endif - if (address==0x0457) return; // XXX: IDEのデータ破壊回避のための暫定 - if (address < I286_MEMWRITEMAX) { - mem[address] = (UINT8)value; - } - else { -#if defined(SUPPORT_CL_GD5430) - if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ - UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; - UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; - UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; - if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ - UINT32 addrofs = address - np2clvga.pciLFB_Addr; - if(addrofs < 0x1000000){ - cirrus_linear_writeb(cirrusvga_opaque, address, value); - }else if( addrofs < 0x1000000 + 0x400000){ - cirrus_linear_bitblt_writeb(cirrusvga_opaque, address, value); - } - return; - }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ - cirrus_mmio_write[0](cirrusvga_opaque, address, value); - if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI) - return; - } - //if(TEST_START_ADDR < address && address <= TEST_END_ADDR){ - // printf("%d: %d\n", address, value); - //} -#if defined(SUPPORT_VGA_MODEX) - // PC/AT互換機 標準VGA相当 書き込み限定で許可 - if(np2clvga.modex && vramWndAddr3==0xa0000){ - UINT32 addr3 = address; - if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ - cirrus_vga_mem_writeb(cirrusvga_opaque, addr3, value); - vramWndAddr3 = 0; - } - } -#endif - if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ - if(vramWndAddr){ - if(vramWndAddr <= address){ - if(address < vramWndAddr + VRAMWINDOW_SIZE){ - g_cirrus_linear_write[0](cirrusvga_opaque, address, value); - return; - }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ - if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT){ - g_cirrus_linear_write[0](cirrusvga_opaque, address, value); - return; - } - } - } - } - if(vramWndAddr3){ - UINT32 addr3 = address; - if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ - CIRRUS_VRAMWND3_FUNC_wb(cirrusvga_opaque, addr3, value); - //TRACEOUT(("mem (write8): %x", address)); - //if(!(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) - // return; - } - } - if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ - UINT32 addr2 = address; - if((vramWndAddr2 & 0xfff00000UL) == 0){ - UINT32 addrtmp = addr2 & 0xfff80000UL; - if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ - // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF - addr2 = addr2 & 0xfffff; - } - } - if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ - CIRRUS_VRAMWND2_FUNC_wb(cirrusvga_opaque, addr2, value); - //if((vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) && !(gdc.display & (1 << GDCDISP_31))) - // return; - } - } - } - } -#endif -// 強制RAM化 - if ((address >= 0xa5000) && (address < 0xa7fff)) { - if (CPU_RAM_D000 & (1 << ((address >> 12) & 15))) { - mem[address] = (UINT8)value; - } - } -// - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - memfn0.wr8[address >> 15](address, value); - } - else if (address < CPU_EXTLIMIT16) { - CPU_EXTMEMBASE[address] = (UINT8)value; - } - else if (address < 0x00f00000) { - } - else if (address < 0x01000000) { - memfnf.wr8[(address >> 17) & 7](address, value); - } -#if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - CPU_EXTMEMBASE[address] = (UINT8)value; - } -#endif // defined(CPU_EXTLIMIT) -#if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - memvgaf_wr8(address, value); - } -#endif // defined(SUPPORT_PC9821) - else { - TRACEOUT(("out of mem (write8): %x", address)); - } - } -} - -void MEMCALL memp_write16(UINT32 address, REG16 value) { - - -#ifdef MEM_BDA_TRACEOUT - if(0x400 <= address && address < 0x600){ - switch(address){ - case 0x55e: - case 0x58a: - break; - case 0x4f8: - case 0x4f9: - case 0x4fa: - case 0x4fb: - case 0x4fc: - case 0x4fd: - break; - default: - TRACEOUT(("BDA (write16): %x val %x -> %x", address, *((UINT16*)(mem+address)), value)); - } - } -#endif - if (address < (I286_MEMWRITEMAX - 1)) { - STOREINTELWORD(mem + address, value); - } - else{ - if (((address + 1) & 0x7fff) && ((address + 2) & 0x7fff) && ((address + 3) & 0x7fff)) { // non 32kb boundary -#if defined(SUPPORT_CL_GD5430) - if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ - UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; - UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; - UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; - if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ - UINT32 addrofs = address - np2clvga.pciLFB_Addr; - if(addrofs < 0x1000000){ - cirrus_linear_writew(cirrusvga_opaque, address, value); - }else if( addrofs < 0x1000000 + 0x400000){ - cirrus_linear_bitblt_writew(cirrusvga_opaque, address, value); - } - return; - }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ - cirrus_mmio_write[1](cirrusvga_opaque, address, value); - if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI) - return; - } - //if(TEST_START_ADDR < address && address <= TEST_END_ADDR){ - // printf("%d: %d\n", address, value); - //} -#if defined(SUPPORT_VGA_MODEX) - // PC/AT互換機 標準VGA相当 書き込み限定で許可 - if(np2clvga.modex && vramWndAddr3==0xa0000){ - UINT32 addr3 = address; - if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ - cirrus_vga_mem_writew(cirrusvga_opaque, addr3, value); - vramWndAddr3 = 0; - } - } -#endif - if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ - if(vramWndAddr){ - if(vramWndAddr <= address){ - if(address < vramWndAddr + VRAMWINDOW_SIZE){ - g_cirrus_linear_write[1](cirrusvga_opaque, address, value); - return; - }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ - if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT){ - g_cirrus_linear_write[1](cirrusvga_opaque, address, value); - return; - } - } - } - } - if(vramWndAddr3){ - UINT32 addr3 = address; - if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ - CIRRUS_VRAMWND3_FUNC_ww(cirrusvga_opaque, addr3, value); - //TRACEOUT(("mem (write16): %x", address)); - //if(!(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) - // return; - } - } - if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ - UINT32 addr2 = address; - if((vramWndAddr2 & 0xfff00000UL) == 0){ - UINT32 addrtmp = addr2 & 0xfff80000UL; - if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ - // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF - addr2 = addr2 & 0xfffff; - } - } - if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ - CIRRUS_VRAMWND2_FUNC_ww(cirrusvga_opaque, addr2, value); - //if((vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) && !(gdc.display & (1 << GDCDISP_31))) - // return; - } - } - } - } -#endif -// 強制RAM化 - if ((address >= 0xa5000) && (address < 0xa7fff)) { - - UINT8 *ptr; - UINT16 bit; - - ptr = mem + address; - bit = 1 << ((address >> 12) & 15); - if ((address + 1) & 0xfff) { - if (CPU_RAM_D000 & bit) { - STOREINTELWORD(ptr, value); - } - } - else { - if (CPU_RAM_D000 & bit) { - ptr[0] = (UINT8)value; - } - if (CPU_RAM_D000 & (bit << 1)) { - ptr[1] = (UINT8)(value >> 8); - } - } - } -// - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - memfn0.wr16[address >> 15](address, value); - } - else if (address < CPU_EXTLIMIT16) { - STOREINTELWORD(CPU_EXTMEMBASE + address, value); - } - else if (address < 0x00f00000) { - } - else if (address < 0x01000000) { - memfnf.wr16[(address >> 17) & 7](address, value); - } -#if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - STOREINTELWORD(CPU_EXTMEMBASE + address, value); - } -#endif // defined(CPU_EXTLIMIT) -#if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - memvgaf_wr16(address, value); - } -#endif // defined(SUPPORT_PC9821) - else { - TRACEOUT(("out of mem (write16): %x", address)); - } - } - else { - memp_write8(address + 0, (UINT8)value); - memp_write8(address + 1, (UINT8)(value >> 8)); - } - } -} - -void MEMCALL memp_write32(UINT32 address, UINT32 value) { - - //UINT32 pos; - -#ifdef MEM_BDA_TRACEOUT - if(0x400 <= address && address < 0x600){ - switch(address){ - case 0x55e: - case 0x58a: - break; - case 0x4f8: - case 0x4f9: - case 0x4fa: - case 0x4fb: - case 0x4fc: - case 0x4fd: - break; - default: - TRACEOUT(("BDA (write32): %x val %x -> %x", address, *((UINT32*)(mem+address)), value)); - } - } -#endif - if (address < (I286_MEMWRITEMAX - 3)) { - STOREINTELDWORD(mem + address, value); - return; - } - else{ - if ((address + 1) & 0x7fff) { // non 32kb boundary -#if defined(SUPPORT_CL_GD5430) - if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ - UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; - UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; - UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; - if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ - UINT32 addrofs = address - np2clvga.pciLFB_Addr; - if(addrofs < 0x1000000){ - cirrus_linear_writel(cirrusvga_opaque, address, value); - }else if( addrofs < 0x1000000 + 0x400000){ - cirrus_linear_bitblt_writel(cirrusvga_opaque, address, value); - } - return; - }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ - cirrus_mmio_write[2](cirrusvga_opaque, address, value); - if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI) - return; - } - //if(TEST_START_ADDR < address && address <= TEST_END_ADDR){ - // printf("%d: %d\n", address, value); - //} -#if defined(SUPPORT_VGA_MODEX) - // PC/AT互換機 標準VGA相当 書き込み限定で許可 - if(np2clvga.modex && vramWndAddr3==0xa0000){ - UINT32 addr3 = address; - if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ - cirrus_vga_mem_writel(cirrusvga_opaque, addr3, value); - vramWndAddr3 = 0; - } - } -#endif - if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ - if(vramWndAddr){ - if(vramWndAddr <= address){ - if(address < vramWndAddr + VRAMWINDOW_SIZE){ - g_cirrus_linear_write[2](cirrusvga_opaque, address, value); - return; - }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ - if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT){ - g_cirrus_linear_write[2](cirrusvga_opaque, address, value); - return; - } - } - } - } - if(vramWndAddr3){ - UINT32 addr3 = address; - if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ - CIRRUS_VRAMWND3_FUNC_wl(cirrusvga_opaque, addr3, value); - //TRACEOUT(("mem (write32): %x", address)); - //if(!(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) - // return; - } - } - if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ - UINT32 addr2 = address; - if((vramWndAddr2 & 0xfff00000UL) == 0){ - UINT32 addrtmp = addr2 & 0xfff80000UL; - if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ - // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF - addr2 = addr2 & 0xfffff; - } - } - if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ - CIRRUS_VRAMWND2_FUNC_wl(cirrusvga_opaque, addr2, value); - //if((vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) && !(gdc.display & (1 << GDCDISP_31))) - // return; - } - } - } - } -#endif - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - memfn0.wr32[address >> 15](address, value); - } - else if (address < CPU_EXTLIMIT16) { - STOREINTELDWORD(CPU_EXTMEMBASE + address, value); - } - else if (address < 0x00f00000) { - } - else if (address < 0x01000000) { - memfnf.wr32[(address >> 17) & 7](address, value); - } -#if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - STOREINTELDWORD(CPU_EXTMEMBASE + address, value); - } -#endif // defined(CPU_EXTLIMIT) -#if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - memvgaf_wr32(address, value); - } -#endif // defined(SUPPORT_PC9821) - else { - TRACEOUT(("out of mem (write32): %x", address)); - } - } - else { - if (!(address & 1)) { - memp_write16(address + 0, (UINT16)value); - memp_write16(address + 2, (UINT16)(value >> 16)); - } - else { - memp_write8(address + 0, (UINT8)value); - memp_write16(address + 1, (UINT16)(value >> 8)); - memp_write8(address + 3, (UINT8)(value >> 24)); - } - } - } -} - -void MEMCALL memp_write8_paging(UINT32 address, REG8 value) { - - //if (address==0x0457) return; // XXX: IDEのデータ破壊回避のための暫定 - if (address < I286_MEMWRITEMAX) { - mem[address] = (UINT8)value; - } - else { - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - memfn0.wr8[address >> 15](address, value); - } - else if (address < CPU_EXTLIMIT16) { - CPU_EXTMEMBASE[address] = (UINT8)value; - } - else if (address < 0x00f00000) { - } - else if (address < 0x01000000) { - memfnf.wr8[(address >> 17) & 7](address, value); - } -#if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - CPU_EXTMEMBASE[address] = (UINT8)value; - } -#endif // defined(CPU_EXTLIMIT) -#if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - memvgaf_wr8(address, value); - } -#endif // defined(SUPPORT_PC9821) - else { - TRACEOUT(("out of mem (write8): %x", address)); - } - } -} - -void MEMCALL memp_write16_paging(UINT32 address, REG16 value) { - - if (address < (I286_MEMWRITEMAX - 1)) { - STOREINTELWORD(mem + address, value); - } - else{ - if ((address + 1) & 0x7fff) { // non 32kb boundary - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - memfn0.wr16[address >> 15](address, value); - } - else if (address < CPU_EXTLIMIT16) { - STOREINTELWORD(CPU_EXTMEMBASE + address, value); - } - else if (address < 0x00f00000) { - } - else if (address < 0x01000000) { - memfnf.wr16[(address >> 17) & 7](address, value); - } -#if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - STOREINTELWORD(CPU_EXTMEMBASE + address, value); - } -#endif // defined(CPU_EXTLIMIT) -#if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - memvgaf_wr16(address, value); - } -#endif // defined(SUPPORT_PC9821) - else { - TRACEOUT(("out of mem (write16): %x", address)); - } - } - else { - memp_write8_paging(address + 0, (UINT8)value); - memp_write8_paging(address + 1, (UINT8)(value >> 8)); - } - } -} - -void MEMCALL memp_write32_paging(UINT32 address, UINT32 value) { - - if (address < (I286_MEMWRITEMAX - 3)) { - STOREINTELDWORD(mem + address, value); - return; - } - else{ - if ((address + 1) & 0x7fff) { // non 32kb boundary - address = address & CPU_ADRSMASK; - if (address < USE_HIMEM) { - memfn0.wr32[address >> 15](address, value); - } - else if (address < CPU_EXTLIMIT16) { - STOREINTELDWORD(CPU_EXTMEMBASE + address, value); - } - else if (address < 0x00f00000) { - } - else if (address < 0x01000000) { - memfnf.wr32[(address >> 17) & 7](address, value); - } -#if defined(CPU_EXTLIMIT) - else if (address < CPU_EXTLIMIT) { - STOREINTELDWORD(CPU_EXTMEMBASE + address, value); - } -#endif // defined(CPU_EXTLIMIT) -#if defined(SUPPORT_PC9821) - else if ((address >= 0xfff00000) && (address < 0xfff80000)) { - memvgaf_wr32(address, value); - } -#endif // defined(SUPPORT_PC9821) - else { - TRACEOUT(("out of mem (write32): %x", address)); - } - } - else { - if (!(address & 1)) { - memp_write16_paging(address + 0, (UINT16)value); - memp_write16_paging(address + 2, (UINT16)(value >> 16)); - } - else { - memp_write8_paging(address + 0, (UINT8)value); - memp_write16_paging(address + 1, (UINT16)(value >> 8)); - memp_write8_paging(address + 3, (UINT8)(value >> 24)); - } - } - } -} - - -void MEMCALL memp_reads(UINT32 address, void *dat, UINT leng) { - - UINT8 *out = (UINT8 *)dat; - UINT diff; - - /* fast memory access */ - if ((address + leng) < I286_MEMREADMAX) { - CopyMemory(dat, mem + address, leng); - return; - } - address = address & CPU_ADRSMASK; - if ((address >= USE_HIMEM) && (address < CPU_EXTLIMIT16)) { - diff = CPU_EXTLIMIT16 - address; - if (diff >= leng) { - CopyMemory(dat, CPU_EXTMEMBASE + address, leng); - return; - } - CopyMemory(dat, CPU_EXTMEMBASE + address, diff); - out += diff; - leng -= diff; - address += diff; - } - - /* slow memory access */ - while (leng-- > 0) { - *out++ = memp_read8(address++); - } -} - -void MEMCALL memp_writes(UINT32 address, const void *dat, UINT leng) { - - const UINT8 *out = (UINT8 *)dat; - UINT diff; - - /* fast memory access */ - if ((address + leng) < I286_MEMREADMAX) { - CopyMemory(mem + address, dat, leng); - return; - } - address = address & CPU_ADRSMASK; - if ((address >= USE_HIMEM) && (address < CPU_EXTLIMIT16)) { - diff = CPU_EXTLIMIT16 - address; - if (diff >= leng) { - CopyMemory(CPU_EXTMEMBASE + address, dat, leng); - return; - } - CopyMemory(CPU_EXTMEMBASE + address, dat, diff); - out += diff; - leng -= diff; - address += diff; - } - - /* slow memory access */ - while (leng-- > 0) { - memp_write8(address++, *out++); - } -} - - -// ---- Logical Space (BIOS) - -static UINT32 MEMCALL physicaladdr(UINT32 addr, BOOL wr) { - - UINT32 a; - UINT32 pde; - UINT32 pte; - - a = CPU_STAT_PDE_BASE + ((addr >> 20) & 0xffc); - pde = memp_read32(a); - if (!(pde & CPU_PDE_PRESENT)) { - goto retdummy; - } - if (!(pde & CPU_PDE_ACCESS)) { - memp_write8(a, (UINT8)(pde | CPU_PDE_ACCESS)); - } - a = (pde & CPU_PDE_BASEADDR_MASK) + ((addr >> 10) & 0xffc); - pte = cpu_memoryread_d(a); - if (!(pte & CPU_PTE_PRESENT)) { - goto retdummy; - } - if (!(pte & CPU_PTE_ACCESS)) { - memp_write8(a, (UINT8)(pte | CPU_PTE_ACCESS)); - } - if ((wr) && (!(pte & CPU_PTE_DIRTY))) { - memp_write8(a, (UINT8)(pte | CPU_PTE_DIRTY)); - } - addr = (pte & CPU_PTE_BASEADDR_MASK) + (addr & 0x00000fff); - return(addr); - - retdummy: - return(0x01000000); /* XXX */ -} - - -void MEMCALL meml_reads(UINT32 address, void *dat, UINT leng) { - - UINT size; - - if (!CPU_STAT_PAGING) { - memp_reads(address, dat, leng); - } - else { - while(leng) { - size = 0x1000 - (address & 0xfff); - size = MIN(size, leng); - memp_reads(physicaladdr(address, FALSE), dat, size); - address += size; - dat = ((UINT8 *)dat) + size; - leng -= size; - } - } -} - -void MEMCALL meml_writes(UINT32 address, const void *dat, UINT leng) { - - UINT size; - - if (!CPU_STAT_PAGING) { - memp_writes(address, dat, leng); - } - else { - while(leng) { - size = 0x1000 - (address & 0xfff); - size = MIN(size, leng); - memp_writes(physicaladdr(address, TRUE), dat, size); - address += size; - dat = ((UINT8 *)dat) + size; - leng -= size; - } - } -} - - -REG8 MEMCALL memr_read8(UINT seg, UINT off) { - - UINT32 addr; - - addr = (seg << 4) + LOW16(off); - if (CPU_STAT_PAGING) { - addr = physicaladdr(addr, FALSE); - } - return(memp_read8(addr)); -} - -REG16 MEMCALL memr_read16(UINT seg, UINT off) { - - UINT32 addr; - - addr = (seg << 4) + LOW16(off); - if (!CPU_STAT_PAGING) { - return(memp_read16(addr)); - } - else if ((addr + 1) & 0xfff) { - return(memp_read16(physicaladdr(addr, FALSE))); - } - return(memr_read8(seg, off) + (memr_read8(seg, off + 1) << 8)); -} - -void MEMCALL memr_write8(UINT seg, UINT off, REG8 dat) { - - UINT32 addr; - - addr = (seg << 4) + LOW16(off); - if (CPU_STAT_PAGING) { - addr = physicaladdr(addr, TRUE); - } - memp_write8(addr, dat); -} - -void MEMCALL memr_write16(UINT seg, UINT off, REG16 dat) { - - UINT32 addr; - - addr = (seg << 4) + LOW16(off); - if (!CPU_STAT_PAGING) { - memp_write16(addr, dat); - } - else if ((addr + 1) & 0xfff) { - memp_write16(physicaladdr(addr, TRUE), dat); - } - else { - memr_write8(seg, off, (REG8)dat); - memr_write8(seg, off + 1, (REG8)(dat >> 8)); - } -} - -void MEMCALL memr_reads(UINT seg, UINT off, void *dat, UINT leng) { - - UINT32 addr; - UINT rem; - UINT size; - - while(leng) { - off = LOW16(off); - addr = (seg << 4) + off; - rem = 0x10000 - off; - size = MIN(leng, rem); - if (CPU_STAT_PAGING) { - rem = 0x1000 - (addr & 0xfff); - size = MIN(size, rem); - addr = physicaladdr(addr, FALSE); - } - memp_reads(addr, dat, size); - off += size; - dat = ((UINT8 *)dat) + size; - leng -= size; - } -} - -void MEMCALL memr_writes(UINT seg, UINT off, const void *dat, UINT leng) { - - UINT32 addr; - UINT rem; - UINT size; - - while(leng) { - off = LOW16(off); - addr = (seg << 4) + off; - rem = 0x10000 - off; - size = MIN(leng, rem); - if (CPU_STAT_PAGING) { - rem = 0x1000 - (addr & 0xfff); - size = MIN(size, rem); - addr = physicaladdr(addr, TRUE); - } - memp_writes(addr, dat, size); - off += size; - dat = ((UINT8 *)dat) + size; - leng -= size; - } -} - -#endif +#include + +#if 0 +#undef TRACEOUT +//#define USE_TRACEOUT_VS +//#define MEM_BDA_TRACEOUT +//#define MEM_D8_TRACEOUT +#ifdef USE_TRACEOUT_VS +static void trace_fmt_ex(const char *fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "\n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#else +#define TRACEOUT(s) (void)(s) +#endif +#endif /* 1 */ + +#ifndef NP2_MEMORY_ASM + +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_PC9821) +#include +#endif +#include +#include +#include +#include +#if defined(SUPPORT_CL_GD5430) +#include +#endif +#if defined(SUPPORT_PCI) +#include +#endif +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif + + +#if defined(SUPPORT_IA32_HAXM) + UINT8 *mem = NULL; // Alloc in pccore_mem_malloc() +#else + UINT8 mem[0x200000]; +#endif + + +typedef void (MEMCALL * MEM8WRITE)(UINT32 address, REG8 value); +typedef REG8 (MEMCALL * MEM8READ)(UINT32 address); +typedef void (MEMCALL * MEM16WRITE)(UINT32 address, REG16 value); +typedef REG16 (MEMCALL * MEM16READ)(UINT32 address); +typedef void (MEMCALL * MEM32WRITE)(UINT32 address, UINT32 value); +typedef UINT32 (MEMCALL * MEM32READ)(UINT32 address); + + +// ---- MAIN + +static REG8 MEMCALL memmain_rd8(UINT32 address) { + + return(mem[address]); +} + +static REG16 MEMCALL memmain_rd16(UINT32 address) { + +const UINT8 *ptr; + + ptr = mem + address; + return(LOADINTELWORD(ptr)); +} + +static UINT32 MEMCALL memmain_rd32(UINT32 address) { + +const UINT8 *ptr; + + ptr = mem + address; + return(LOADINTELDWORD(ptr)); +} + +static void MEMCALL memmain_wr8(UINT32 address, REG8 value) { + + mem[address] = (UINT8)value; +} + +static void MEMCALL memmain_wr16(UINT32 address, REG16 value) { + + UINT8 *ptr; + + ptr = mem + address; + STOREINTELWORD(ptr, value); +} + +static void MEMCALL memmain_wr32(UINT32 address, UINT32 value) { + + UINT8 *ptr; + + ptr = mem + address; + STOREINTELDWORD(ptr, value); +} + + +// ---- N/C + +static REG8 MEMCALL memnc_rd8(UINT32 address) { + + (void)address; + return(0xff); +} + +static REG16 MEMCALL memnc_rd16(UINT32 address) { + + (void)address; + return(0xffff); +} + +static UINT32 MEMCALL memnc_rd32(UINT32 address) { + + (void)address; + return(0xffffffff); +} + +static void MEMCALL memnc_wr8(UINT32 address, REG8 value) { + + (void)address; + (void)value; +} + +static void MEMCALL memnc_wr16(UINT32 address, REG16 value) { + +// 強制RAM化 +// (void)address; +// (void)value; + + UINT8 *ptr; + UINT16 bit; + + ptr = mem + address; + bit = 1 << ((address >> 12) & 15); + if ((address + 1) & 0xfff) { + if (CPU_RAM_D000 & bit) { + STOREINTELWORD(ptr, value); + } + } + else { + if (CPU_RAM_D000 & bit) { + ptr[0] = (UINT8)value; + } + if (CPU_RAM_D000 & (bit << 1)) { + ptr[1] = (UINT8)(value >> 8); + } + } +// +} + +static void MEMCALL memnc_wr32(UINT32 address, UINT32 value) { + + (void)address; + (void)value; +} + + +// ---- memory 000000-0ffffff + 64KB + +typedef struct { + MEM8READ rd8[0x22]; + MEM8WRITE wr8[0x22]; + MEM16READ rd16[0x22]; + MEM16WRITE wr16[0x22]; + MEM32READ rd32[0x22]; + MEM32WRITE wr32[0x22]; +} MEMFN0; + +typedef struct { + MEM8READ brd8; // E8000-F7FFF byte read + MEM8READ ird8; // F8000-FFFFF byte read + MEM8WRITE bwr8; // E8000-FFFFF byte write + MEM16READ brd16; // E8000-F7FFF word read + MEM16READ ird16; // F8000-FFFFF word read + MEM16WRITE bwr16; // F8000-FFFFF word write + MEM32READ brd32; // E8000-F7FFF word read + MEM32READ ird32; // F8000-FFFFF word read + MEM32WRITE bwr32; // F8000-FFFFF word write +} MMAPTBL; + +typedef struct { + MEM8READ rd8; + MEM8WRITE wr8; + MEM16READ rd16; + MEM16WRITE wr16; + MEM32READ rd32; + MEM32WRITE wr32; +} VACCTBL; + +static MEMFN0 memfn0 = { + {memmain_rd8, memmain_rd8, memmain_rd8, memmain_rd8, // 00 + memmain_rd8, memmain_rd8, memmain_rd8, memmain_rd8, // 20 + memmain_rd8, memmain_rd8, memmain_rd8, memmain_rd8, // 40 + memmain_rd8, memmain_rd8, memmain_rd8, memmain_rd8, // 60 + memmain_rd8, memmain_rd8, memmain_rd8, memmain_rd8, // 80 + memtram_rd8, memvram0_rd8, memvram0_rd8, memvram0_rd8, // a0 + memems_rd8, memems_rd8, memmain_rd8, memmain_rd8, // c0 + memvram0_rd8, memmain_rd8, memmain_rd8, memf800_rd8, // e0 + memmain_rd8, memmain_rd8}, + + {memmain_wr8, memmain_wr8, memmain_wr8, memmain_wr8, // 00 + memmain_wr8, memmain_wr8, memmain_wr8, memmain_wr8, // 20 + memmain_wr8, memmain_wr8, memmain_wr8, memmain_wr8, // 40 + memmain_wr8, memmain_wr8, memmain_wr8, memmain_wr8, // 60 + memmain_wr8, memmain_wr8, memmain_wr8, memmain_wr8, // 80 + memtram_wr8, memvram0_wr8, memvram0_wr8, memvram0_wr8, // a0 + memems_wr8, memems_wr8, memd000_wr8, memd000_wr8, // c0 + memvram0_wr8, memnc_wr8, memnc_wr8, memnc_wr8, // e0 + memmain_wr8, memmain_wr8}, + + {memmain_rd16, memmain_rd16, memmain_rd16, memmain_rd16, // 00 + memmain_rd16, memmain_rd16, memmain_rd16, memmain_rd16, // 20 + memmain_rd16, memmain_rd16, memmain_rd16, memmain_rd16, // 40 + memmain_rd16, memmain_rd16, memmain_rd16, memmain_rd16, // 60 + memmain_rd16, memmain_rd16, memmain_rd16, memmain_rd16, // 80 + memtram_rd16, memvram0_rd16, memvram0_rd16, memvram0_rd16, // a0 + memems_rd16, memems_rd16, memmain_rd16, memmain_rd16, // c0 + memvram0_rd16, memmain_rd16, memmain_rd16, memf800_rd16, // e0 + memmain_rd16, memmain_rd16}, + + {memmain_wr16, memmain_wr16, memmain_wr16, memmain_wr16, // 00 + memmain_wr16, memmain_wr16, memmain_wr16, memmain_wr16, // 20 + memmain_wr16, memmain_wr16, memmain_wr16, memmain_wr16, // 40 + memmain_wr16, memmain_wr16, memmain_wr16, memmain_wr16, // 60 + memmain_wr16, memmain_wr16, memmain_wr16, memmain_wr16, // 80 + memtram_wr16, memvram0_wr16, memvram0_wr16, memvram0_wr16, // a0 + memems_wr16, memems_wr16, memd000_wr16, memd000_wr16, // c0 + memvram0_wr16, memnc_wr16, memnc_wr16, memnc_wr16, // e0 + memmain_wr16, memmain_wr16}, + + {memmain_rd32, memmain_rd32, memmain_rd32, memmain_rd32, // 00 + memmain_rd32, memmain_rd32, memmain_rd32, memmain_rd32, // 20 + memmain_rd32, memmain_rd32, memmain_rd32, memmain_rd32, // 40 + memmain_rd32, memmain_rd32, memmain_rd32, memmain_rd32, // 60 + memmain_rd32, memmain_rd32, memmain_rd32, memmain_rd32, // 80 + memtram_rd32, memvram0_rd32, memvram0_rd32, memvram0_rd32, // a0 + memems_rd32, memems_rd32, memmain_rd32, memmain_rd32, // c0 + memvram0_rd32, memmain_rd32, memmain_rd32, memf800_rd32, // e0 + memmain_rd32, memmain_rd32}, + + {memmain_wr32, memmain_wr32, memmain_wr32, memmain_wr32, // 00 + memmain_wr32, memmain_wr32, memmain_wr32, memmain_wr32, // 20 + memmain_wr32, memmain_wr32, memmain_wr32, memmain_wr32, // 40 + memmain_wr32, memmain_wr32, memmain_wr32, memmain_wr32, // 60 + memmain_wr32, memmain_wr32, memmain_wr32, memmain_wr32, // 80 + memtram_wr32, memvram0_wr32, memvram0_wr32, memvram0_wr32, // a0 + memems_wr32, memems_wr32, memd000_wr32, memd000_wr32, // c0 + memvram0_wr32, memnc_wr32, memnc_wr32, memnc_wr32, // e0 + memmain_wr32, memmain_wr32}}; + +static const MMAPTBL mmaptbl[2] = { + {memmain_rd8, memf800_rd8, memnc_wr8, + memmain_rd16, memf800_rd16, memnc_wr16, + memmain_rd32, memf800_rd32, memnc_wr32}, + {memf800_rd8, memf800_rd8, memepson_wr8, + memf800_rd16, memf800_rd16, memepson_wr16, + memf800_rd32, memf800_rd32, memepson_wr32}}; + +static const VACCTBL vacctbl[0x10] = { + {memvram0_rd8, memvram0_wr8, memvram0_rd16, memvram0_wr16, memvram0_rd32, memvram0_wr32, }, // 00 + {memvram1_rd8, memvram1_wr8, memvram1_rd16, memvram1_wr16, memvram1_rd32, memvram1_wr32, }, + {memvram0_rd8, memvram0_wr8, memvram0_rd16, memvram0_wr16, memvram0_rd32, memvram0_wr32, }, + {memvram1_rd8, memvram1_wr8, memvram1_rd16, memvram1_wr16, memvram1_rd32, memvram1_wr32, }, + {memvram0_rd8, memvram0_wr8, memvram0_rd16, memvram0_wr16, memvram0_rd32, memvram0_wr32, }, // 40 + {memvram1_rd8, memvram1_wr8, memvram1_rd16, memvram1_wr16, memvram1_rd32, memvram1_wr32, }, + {memvram0_rd8, memvram0_wr8, memvram0_rd16, memvram0_wr16, memvram0_rd32, memvram0_wr32, }, + {memvram1_rd8, memvram1_wr8, memvram1_rd16, memvram1_wr16, memvram1_rd32, memvram1_wr32, }, + {memtcr0_rd8, memtdw0_wr8, memtcr0_rd16, memtdw0_wr16, memtcr0_rd32, memtdw0_wr32, }, // 80 + {memtcr1_rd8, memtdw1_wr8, memtcr1_rd16, memtdw1_wr16, memtcr1_rd32, memtdw1_wr32, }, + {memegc_rd8, memegc_wr8, memegc_rd16, memegc_wr16, memegc_rd32, memegc_wr32, }, + {memegc_rd8, memegc_wr8, memegc_rd16, memegc_wr16, memegc_rd32, memegc_wr32, }, + {memvram0_rd8, memrmw0_wr8, memvram0_rd16, memrmw0_wr16, memvram0_rd32, memrmw0_wr32, }, // c0 + {memvram1_rd8, memrmw1_wr8, memvram1_rd16, memrmw1_wr16, memvram1_rd32, memrmw1_wr32, }, + {memegc_rd8, memegc_wr8, memegc_rd16, memegc_wr16, memegc_rd32, memegc_wr32, }, + {memegc_rd8, memegc_wr8, memegc_rd16, memegc_wr16, memegc_rd32, memegc_wr32, }}; + + +void MEMCALL memm_arch(UINT type) { + +const MMAPTBL *mm; + + mm = mmaptbl + (type & 1); + + memfn0.rd8[0xe8000 >> 15] = mm->brd8; + memfn0.rd8[0xf0000 >> 15] = mm->brd8; + memfn0.rd8[0xf8000 >> 15] = mm->ird8; + memfn0.wr8[0xe8000 >> 15] = mm->bwr8; + memfn0.wr8[0xf0000 >> 15] = mm->bwr8; + memfn0.wr8[0xf8000 >> 15] = mm->bwr8; + + memfn0.rd16[0xe8000 >> 15] = mm->brd16; + memfn0.rd16[0xf0000 >> 15] = mm->brd16; + memfn0.rd16[0xf8000 >> 15] = mm->ird16; + memfn0.wr16[0xe8000 >> 15] = mm->bwr16; + memfn0.wr16[0xf0000 >> 15] = mm->bwr16; + memfn0.wr16[0xf8000 >> 15] = mm->bwr16; + + memfn0.rd32[0xe8000 >> 15] = mm->brd32; + memfn0.rd32[0xf0000 >> 15] = mm->brd32; + memfn0.rd32[0xf8000 >> 15] = mm->ird32; + memfn0.wr32[0xe8000 >> 15] = mm->bwr32; + memfn0.wr32[0xf0000 >> 15] = mm->bwr32; + memfn0.wr32[0xf8000 >> 15] = mm->bwr32; +} + +void MEMCALL memm_vram(UINT func) { + +const VACCTBL *vacc; + +#if defined(SUPPORT_PC9821) + if (!(func & 0x20)) { +#endif // defined(SUPPORT_PC9821) + vacc = vacctbl + (func & 0x0f); +#if defined(SUPPORT_IA32_HAXM) + if (np2hax.enable) { + if ((func & 0x0f) < 8) { + if(np2haxcore.lastVRAMMMIO){ + i386hax_vm_setmemoryarea(mem+0xA8000, 0xA8000, 0x8000); + i386hax_vm_setmemoryarea(mem+0xB0000, 0xB0000, 0x10000); + np2haxcore.lastVRAMMMIO = 0; + } + }else{ + if(!np2haxcore.lastVRAMMMIO){ + i386hax_vm_removememoryarea(mem+0xA8000, 0xA8000, 0x8000); + i386hax_vm_removememoryarea(mem+0xB0000, 0xB0000, 0x10000); + np2haxcore.lastVRAMMMIO = 1; + } + } + } +#endif + + memfn0.rd8[0xa8000 >> 15] = vacc->rd8; + memfn0.rd8[0xb0000 >> 15] = vacc->rd8; + memfn0.rd8[0xb8000 >> 15] = vacc->rd8; + memfn0.rd8[0xe0000 >> 15] = vacc->rd8; + + memfn0.wr8[0xa8000 >> 15] = vacc->wr8; + memfn0.wr8[0xb0000 >> 15] = vacc->wr8; + memfn0.wr8[0xb8000 >> 15] = vacc->wr8; + memfn0.wr8[0xe0000 >> 15] = vacc->wr8; + + memfn0.rd16[0xa8000 >> 15] = vacc->rd16; + memfn0.rd16[0xb0000 >> 15] = vacc->rd16; + memfn0.rd16[0xb8000 >> 15] = vacc->rd16; + memfn0.rd16[0xe0000 >> 15] = vacc->rd16; + + memfn0.wr16[0xa8000 >> 15] = vacc->wr16; + memfn0.wr16[0xb0000 >> 15] = vacc->wr16; + memfn0.wr16[0xb8000 >> 15] = vacc->wr16; + memfn0.wr16[0xe0000 >> 15] = vacc->wr16; + + memfn0.rd32[0xa8000 >> 15] = vacc->rd32; + memfn0.rd32[0xb0000 >> 15] = vacc->rd32; + memfn0.rd32[0xb8000 >> 15] = vacc->rd32; + memfn0.rd32[0xe0000 >> 15] = vacc->rd32; + + memfn0.wr32[0xa8000 >> 15] = vacc->wr32; + memfn0.wr32[0xb0000 >> 15] = vacc->wr32; + memfn0.wr32[0xb8000 >> 15] = vacc->wr32; + memfn0.wr32[0xe0000 >> 15] = vacc->wr32; + + if (!(func & (1 << VOPBIT_ANALOG))) { // digital + memfn0.rd8[0xe0000 >> 15] = memnc_rd8; + memfn0.wr8[0xe0000 >> 15] = memnc_wr8; + memfn0.rd16[0xe0000 >> 15] = memnc_rd16; + memfn0.wr16[0xe0000 >> 15] = memnc_wr16; + memfn0.rd32[0xe0000 >> 15] = memnc_rd32; + memfn0.wr32[0xe0000 >> 15] = memnc_wr32; + } +#if defined(SUPPORT_PC9821) + } + else { +#if defined(SUPPORT_IA32_HAXM) + if (np2hax.enable) { + if(!np2haxcore.lastVRAMMMIO){ + i386hax_vm_removememoryarea(mem+0xA8000, 0xA8000, 0x8000); + i386hax_vm_removememoryarea(mem+0xB0000, 0xB0000, 0x10000); + np2haxcore.lastVRAMMMIO = 1; + } + } +#endif + + memfn0.rd8[0xa8000 >> 15] = memvga0_rd8; + memfn0.rd8[0xb0000 >> 15] = memvga1_rd8; + memfn0.rd8[0xb8000 >> 15] = memnc_rd8; + memfn0.rd8[0xe0000 >> 15] = memvgaio_rd8; + + memfn0.wr8[0xa8000 >> 15] = memvga0_wr8; + memfn0.wr8[0xb0000 >> 15] = memvga1_wr8; + memfn0.wr8[0xb8000 >> 15] = memnc_wr8; + memfn0.wr8[0xe0000 >> 15] = memvgaio_wr8; + + memfn0.rd16[0xa8000 >> 15] = memvga0_rd16; + memfn0.rd16[0xb0000 >> 15] = memvga1_rd16; + memfn0.rd16[0xb8000 >> 15] = memnc_rd16; + memfn0.rd16[0xe0000 >> 15] = memvgaio_rd16; + + memfn0.wr16[0xa8000 >> 15] = memvga0_wr16; + memfn0.wr16[0xb0000 >> 15] = memvga1_wr16; + memfn0.wr16[0xb8000 >> 15] = memnc_wr16; + memfn0.wr16[0xe0000 >> 15] = memvgaio_wr16; + + memfn0.rd32[0xa8000 >> 15] = memvga0_rd32; + memfn0.rd32[0xb0000 >> 15] = memvga1_rd32; + memfn0.rd32[0xb8000 >> 15] = memnc_rd32; + memfn0.rd32[0xe0000 >> 15] = memvgaio_rd32; + + memfn0.wr32[0xa8000 >> 15] = memvga0_wr32; + memfn0.wr32[0xb0000 >> 15] = memvga1_wr32; + memfn0.wr32[0xb8000 >> 15] = memnc_wr32; + memfn0.wr32[0xe0000 >> 15] = memvgaio_wr32; + } +#endif // defined(SUPPORT_PC9821) +} + + +// ---- memory f00000-fffffff + +typedef struct { + MEM8READ rd8[8]; + MEM8WRITE wr8[8]; + MEM16READ rd16[8]; + MEM16WRITE wr16[8]; + MEM32READ rd32[8]; + MEM32WRITE wr32[8]; +} MEMFNF; + + +static REG8 MEMCALL memsys_rd8(UINT32 address) { + + address -= 0xf00000; + return(memfn0.rd8[address >> 15](address)); +} + +static REG16 MEMCALL memsys_rd16(UINT32 address) { + + address -= 0xf00000; + return(memfn0.rd16[address >> 15](address)); +} + +static UINT32 MEMCALL memsys_rd32(UINT32 address) { + + address -= 0xf00000; + return(memfn0.rd32[address >> 15](address)); +} + +static void MEMCALL memsys_wr8(UINT32 address, REG8 value) { + + address -= 0xf00000; + memfn0.wr8[address >> 15](address, value); +} + +static void MEMCALL memsys_wr16(UINT32 address, REG16 value) { + + address -= 0xf00000; + memfn0.wr16[address >> 15](address, value); +} + +static void MEMCALL memsys_wr32(UINT32 address, UINT32 value) { + + address -= 0xf00000; + memfn0.wr32[address >> 15](address, value); +} + +#if defined(SUPPORT_PC9821) +static const MEMFNF memfnf = { + {memvgaf_rd8, memvgaf_rd8, memvgaf_rd8, memvgaf_rd8, + memnc_rd8, memsys_rd8, memsys_rd8, memsys_rd8}, + {memvgaf_wr8, memvgaf_wr8, memvgaf_wr8, memvgaf_wr8, + memnc_wr8, memsys_wr8, memsys_wr8, memsys_wr8}, + + {memvgaf_rd16, memvgaf_rd16, memvgaf_rd16, memvgaf_rd16, + memnc_rd16, memsys_rd16, memsys_rd16, memsys_rd16}, + {memvgaf_wr16, memvgaf_wr16, memvgaf_wr16, memvgaf_wr16, + memnc_wr16, memsys_wr16, memsys_wr16, memsys_wr16}, + + {memvgaf_rd32, memvgaf_rd32, memvgaf_rd32, memvgaf_rd32, + memnc_rd32, memsys_rd32, memsys_rd32, memsys_rd32}, + {memvgaf_wr32, memvgaf_wr32, memvgaf_wr32, memvgaf_wr32, + memnc_wr32, memsys_wr32, memsys_wr32, memsys_wr32}}; +#else +static const MEMFNF memfnf = { + {memnc_rd8, memnc_rd8, memnc_rd8, memnc_rd8, + memnc_rd8, memsys_rd8, memsys_rd8, memsys_rd8}, + {memnc_wr8, memnc_wr8, memnc_wr8, memnc_wr8, + memnc_wr8, memsys_wr8, memsys_wr8, memsys_wr8}, + + {memnc_rd16, memnc_rd16, memnc_rd16, memnc_rd16, + memnc_rd16, memsys_rd16, memsys_rd16, memsys_rd16}, + {memnc_wr16, memnc_wr16, memnc_wr16, memnc_wr16, + memnc_wr16, memsys_wr16, memsys_wr16, memsys_wr16}, + + {memvgaf_rd32, memvgaf_rd32, memvgaf_rd32, memvgaf_rd32, + memnc_rd32, memsys_rd32, memsys_rd32, memsys_rd32}, + {memvgaf_wr32, memvgaf_wr32, memvgaf_wr32, memvgaf_wr32, + memnc_wr32, memsys_wr32, memsys_wr32, memsys_wr32}}; +#endif + +// ---- +REG8 MEMCALL memp_read8(UINT32 address) { + +#ifdef MEM_BDA_TRACEOUT + if(0x400 <= address && address < 0x600){ + switch(address){ + case 0x55f: + case 0x58a: + break; + default: + TRACEOUT(("BDA (read8): %x ret %x", address, mem[address])); + } + } +#endif +#ifdef MEM_D8_TRACEOUT + if(0xD8000 <= address && address < 0xDC000){ + TRACEOUT(("D8000h (read8): %x ret %x", address, mem[address])); + } +#endif + //if (0xD4000 <= address && address <= 0xD5FFF) { + // printf("GP-IB BIOS memread"); + //} + //if (0x400 <= address && address <= 0x5ff) { + // printf("BDA (read8): %x ret %x", address, mem[address]); + //} + //if (address == 0xf0000) { + // printf("SYS (read8): %x ret %x", address, *((UINT8*)(mem+address))); + //} + if (address < I286_MEMREADMAX) { + return(mem[address]); + } + else { +#if defined(SUPPORT_CL_GD5430) + if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ + UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; + UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; + UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; + if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ + UINT32 addrofs = address - np2clvga.pciLFB_Addr; + if(addrofs < 0x1000000){ + return cirrus_linear_readb(cirrusvga_opaque, address); + }else if( addrofs < 0x1000000 + 0x400000){ + return cirrus_linear_bitblt_readb(cirrusvga_opaque, address); + }else{ + return 0xff; + } + }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ + if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI || ((np2clvga.pciMMIO_Addr & 0xfff00000) != 0xf00000 || !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))) + return cirrus_mmio_read[0](cirrusvga_opaque, address); + } + if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ + if(vramWndAddr){ + if(vramWndAddr <= address){ + if(address < vramWndAddr + VRAMWINDOW_SIZE){ + return cirrus_linear_readb(cirrusvga_opaque, address); + }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ + if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT) + return cirrus_linear_readb(cirrusvga_opaque, address); + } + } + } + if(vramWndAddr3){ + UINT32 addr3 = address; + if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX && !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))){ + return CIRRUS_VRAMWND3_FUNC_rb(cirrusvga_opaque, addr3); + } + } + if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ + UINT32 addr2 = address; + if((vramWndAddr2 & 0xfff00000UL) == 0){ + UINT32 addrtmp = addr2 & 0xfff80000UL; + if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ + // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF + addr2 = addr2 & 0xfffff; + } + } + if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ + return CIRRUS_VRAMWND2_FUNC_rb(cirrusvga_opaque, addr2); + } + } + } + } +#endif + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + return(memfn0.rd8[address >> 15](address)); + } + else if (address < CPU_EXTLIMIT16) { + return(CPU_EXTMEMBASE[address]); + } + else if (address < 0x00f00000) { + return(0xff); + } + else if (address < 0x01000000) { + return(memfnf.rd8[(address >> 17) & 7](address)); + } +#if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + return(CPU_EXTMEMBASE[address]); + } +#endif // defined(CPU_EXTLIMIT) +#if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + return(memvgaf_rd8(address)); + } +#endif // defined(SUPPORT_PC9821) + else { +// TRACEOUT(("out of mem (read8): %x", address)); + return(0xff); + } + } +} + +REG16 MEMCALL memp_read16(UINT32 address) { + + REG16 ret; + +#ifdef MEM_BDA_TRACEOUT + if(0x400 <= address && address < 0x600){ + switch(address){ + case 0x55f: + case 0x58a: + break; + default: + TRACEOUT(("BDA (read16): %x ret %x", address, *((UINT16*)(mem+address)))); + } + } +#endif +#ifdef MEM_D8_TRACEOUT + if(0xD8000 <= address && address < 0xDC000){ + TRACEOUT(("D8000h (read16): %x ret %x", address, *((UINT16*)(mem+address)))); + } +#endif + //if (address == 0xf0000) { + // printf("SYS (read16): %x ret %x", address, *((UINT16*)(mem+address))); + //} + //if (0x400 <= address && address <= 0x5ff && address != 0x58a && address != 0x58b) { + // printf("BDA (read16): %x ret %x", address, *((UINT16*)(mem+address))); + //} + if (address < (I286_MEMREADMAX - 1)) { + return(LOADINTELWORD(mem + address)); + } + else { + if ((address + 1) & 0x7fff) { // non 32kb boundary +#if defined(SUPPORT_CL_GD5430) + if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ + UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; + UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; + UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; + if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ + UINT32 addrofs = address - np2clvga.pciLFB_Addr; + if(addrofs < 0x1000000){ + return cirrus_linear_readw(cirrusvga_opaque, address); + }else if( addrofs < 0x1000000 + 0x400000){ + return cirrus_linear_bitblt_readw(cirrusvga_opaque, address); + }else{ + return 0xffff; + } + }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ + if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI || ((np2clvga.pciMMIO_Addr & 0xfff00000) != 0xf00000 || !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))) + return cirrus_mmio_read[1](cirrusvga_opaque, address); + } + if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ + if(vramWndAddr){ + if(vramWndAddr <= address){ + if(address < vramWndAddr + VRAMWINDOW_SIZE){ + return cirrus_linear_readw(cirrusvga_opaque, address); + }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ + if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT) + return cirrus_linear_readw(cirrusvga_opaque, address); + } + } + } + if(vramWndAddr3){ + UINT32 addr3 = address; + if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX && !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))){ + return CIRRUS_VRAMWND3_FUNC_rw(cirrusvga_opaque, addr3); + } + } + if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ + UINT32 addr2 = address; + if((vramWndAddr2 & 0xfff00000UL) == 0){ + UINT32 addrtmp = addr2 & 0xfff80000UL; + if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ + // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF + addr2 = addr2 & 0xfffff; + } + } + if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ + return CIRRUS_VRAMWND2_FUNC_rw(cirrusvga_opaque, addr2); + } + } + } + } +#endif + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + return(memfn0.rd16[address >> 15](address)); + } + else if (address < CPU_EXTLIMIT16) { + return(LOADINTELWORD(CPU_EXTMEMBASE + address)); + } + else if (address < 0x00f00000) { + return(0xffff); + } + else if (address < 0x01000000) { + return(memfnf.rd16[(address >> 17) & 7](address)); + } + #if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + return(LOADINTELWORD(CPU_EXTMEMBASE + address)); + } + #endif // defined(CPU_EXTLIMIT) + #if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + return(memvgaf_rd16(address)); + } + #endif // defined(SUPPORT_PC9821) + else { + // TRACEOUT(("out of mem (read16): %x", address)); + return(0xffff); + } + } + else { + ret = memp_read8(address + 0); + ret |= (REG16)(memp_read8(address + 1) << 8); + return(ret); + } + } +} + +UINT32 MEMCALL memp_read32(UINT32 address) { + + //UINT32 pos; + UINT32 ret; + +#ifdef MEM_BDA_TRACEOUT + if(0x400 <= address && address < 0x600){ + switch(address){ + case 0x55f: + case 0x58a: + break; + default: + TRACEOUT(("BDA (read32): %x ret %x", address, *((UINT32*)(mem+address)))); + } + } +#endif +#ifdef MEM_D8_TRACEOUT + if(0xD8000 <= address && address < 0xDC000){ + TRACEOUT(("D8000h (read32): %x ret %x", address, *((UINT32*)(mem+address)))); + } +#endif + //if (0x400 <= address && address <= 0x5ff) { + // printf("BDA (read32): %x ret %x", address, *((UINT32*)(mem+address))); + //} + //if (address == 0xf0000) { + // printf("SYS (read32): %x ret %x", address, *((UINT32*)(mem+address))); + //} + if (address < (I286_MEMREADMAX - 3)) { + return(LOADINTELDWORD(mem + address)); + } + else{ + if ((address & 0x7fff) <= 0x8000 - 4) { // non 32kb boundary +#if defined(SUPPORT_CL_GD5430) + if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ + UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; + UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; + UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; + if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ + UINT32 addrofs = address - np2clvga.pciLFB_Addr; + if(addrofs < 0x1000000){ + return cirrus_linear_readl(cirrusvga_opaque, address); + }else if( addrofs < 0x1000000 + 0x400000){ + return cirrus_linear_bitblt_readl(cirrusvga_opaque, address); + }else{ + return 0xffffffff; + } + }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ + if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI || ((np2clvga.pciMMIO_Addr & 0xfff00000) != 0xf00000 || !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))) + return cirrus_mmio_read[2](cirrusvga_opaque, address); + } + if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ + if(vramWndAddr){ + if(vramWndAddr <= address){ + if(address < vramWndAddr + VRAMWINDOW_SIZE){ + return cirrus_linear_readl(cirrusvga_opaque, address); + }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ + if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT) + return cirrus_linear_readl(cirrusvga_opaque, address); + } + } + } + if(vramWndAddr3){ + UINT32 addr3 = address; + if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX && !(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))){ + return CIRRUS_VRAMWND3_FUNC_rl(cirrusvga_opaque, addr3); + } + } + if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ + UINT32 addr2 = address; + if((vramWndAddr2 & 0xfff00000UL) == 0){ + UINT32 addrtmp = addr2 & 0xfff80000UL; + if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ + // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF + addr2 = addr2 & 0xfffff; + } + } + if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ + return CIRRUS_VRAMWND2_FUNC_rl(cirrusvga_opaque, addr2); + } + } + } + } +#endif + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + return(memfn0.rd32[address >> 15](address)); + } + else if (address < CPU_EXTLIMIT16) { + return(LOADINTELDWORD(CPU_EXTMEMBASE + address)); + } + else if (address < 0x00f00000) { + return(0xffff); + } + else if (address < 0x01000000) { + return(memfnf.rd32[(address >> 17) & 7](address)); + } + #if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + return(LOADINTELDWORD(CPU_EXTMEMBASE + address)); + } + #endif // defined(CPU_EXTLIMIT) + #if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + return(memvgaf_rd32(address)); + } + #endif // defined(SUPPORT_PC9821) + else { + // TRACEOUT(("out of mem (read32): %x", address)); + return(0xffffffff); + } + } + else { + if (!(address & 1)) { + ret = memp_read16(address + 0); + ret |= (UINT32)memp_read16(address + 2) << 16; + } + else { + ret = memp_read8(address + 0); + ret |= (UINT32)memp_read16(address + 1) << 8; + ret |= (UINT32)memp_read8(address + 3) << 24; + } + return(ret); + } + } +} + +// ---- +PF_UINT8 MEMCALL memp_read8_codefetch(UINT32 address) { + + if (address < I286_MEMREADMAX) { + return(mem[address]); + } + else { + //if(pcidev.bios32entrypoint <= address && address < pcidev.bios32entrypoint + sizeof(pcidev.biosdata.data8)){ + // printf("BIOS32 (read8): %x"); + //} + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + return(memfn0.rd8[address >> 15](address)); + } + else if (address < CPU_EXTLIMIT16) { + return(CPU_EXTMEMBASE[address]); + } + else if (address < 0x00f00000) { + return(0xff); + } + else if (address < 0x01000000) { + return(memfnf.rd8[(address >> 17) & 7](address)); + } +#if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + return(CPU_EXTMEMBASE[address]); + } +#endif // defined(CPU_EXTLIMIT) +#if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + return(memvgaf_rd8(address)); + } +#endif // defined(SUPPORT_PC9821) + else { +// TRACEOUT(("out of mem (read8): %x", address)); + return(0xff); + } + } +} +PF_UINT16 MEMCALL memp_read16_codefetch(UINT32 address) { + + PF_UINT16 ret; + + if (address < (I286_MEMREADMAX - 1)) { + return(LOADINTELWORD(mem + address)); + } + else { + if ((address + 1) & 0x7fff) { // non 32kb boundary + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + return(memfn0.rd16[address >> 15](address)); + } + else if (address < CPU_EXTLIMIT16) { + return(LOADINTELWORD(CPU_EXTMEMBASE + address)); + } + else if (address < 0x00f00000) { + return(0xffff); + } + else if (address < 0x01000000) { + return(memfnf.rd16[(address >> 17) & 7](address)); + } + #if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + return(LOADINTELWORD(CPU_EXTMEMBASE + address)); + } + #endif // defined(CPU_EXTLIMIT) + #if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + return(memvgaf_rd16(address)); + } + #endif // defined(SUPPORT_PC9821) + else { + // TRACEOUT(("out of mem (read16): %x", address)); + return(0xffff); + } + } + else { + ret = memp_read8(address + 0); + ret |= (REG16)(memp_read8(address + 1) << 8); + return(ret); + } + } +} + +UINT32 MEMCALL memp_read32_codefetch(UINT32 address) { + + //UINT32 pos; + UINT32 ret; + + if (address < (I286_MEMREADMAX - 3)) { + return(LOADINTELDWORD(mem + address)); + } + else{ + if ((address & 0x7fff) <= 0x8000 - 4) { // non 32kb boundary + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + return(memfn0.rd32[address >> 15](address)); + } + else if (address < CPU_EXTLIMIT16) { + return(LOADINTELDWORD(CPU_EXTMEMBASE + address)); + } + else if (address < 0x00f00000) { + return(0xffff); + } + else if (address < 0x01000000) { + return(memfnf.rd32[(address >> 17) & 7](address)); + } + #if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + return(LOADINTELDWORD(CPU_EXTMEMBASE + address)); + } + #endif // defined(CPU_EXTLIMIT) + #if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + return(memvgaf_rd32(address)); + } + #endif // defined(SUPPORT_PC9821) + else { + // TRACEOUT(("out of mem (read32): %x", address)); + return(0xffffffff); + } + } + else { + if (!(address & 1)) { + ret = memp_read16(address + 0); + ret |= (UINT32)memp_read16(address + 2) << 16; + } + else { + ret = memp_read8(address + 0); + ret |= (UINT32)memp_read16(address + 1) << 8; + ret |= (UINT32)memp_read8(address + 3) << 24; + } + return(ret); + } + } +} + +// ---- +PF_UINT8 MEMCALL memp_read8_paging(UINT32 address) { + + return memp_read8_codefetch(address); +} +PF_UINT16 MEMCALL memp_read16_paging(UINT32 address) { + + return memp_read16_codefetch(address); +} + +PF_UINT32 MEMCALL memp_read32_paging(UINT32 address) { + + return memp_read32_codefetch(address); +} + +void MEMCALL memp_write8(UINT32 address, REG8 value) { + +#ifdef MEM_BDA_TRACEOUT + if(0x400 <= address && address < 0x600){ + switch(address){ + case 0x55e: + case 0x564: + case 0x565: + case 0x566: + case 0x567: + case 0x568: + case 0x569: + case 0x56a: + case 0x58a: + break; + case 0x4f8: + case 0x4f9: + case 0x4fa: + case 0x4fb: + case 0x4fc: + break; + default: + TRACEOUT(("BDA (write8): %x val %x -> %x", address, mem[address], value)); + } + } +#endif + if (address==0x0457) return; // XXX: IDEのデータ破壊回避のための暫定 + if (address < I286_MEMWRITEMAX) { + mem[address] = (UINT8)value; + } + else { +#if defined(SUPPORT_CL_GD5430) + if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ + UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; + UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; + UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; + if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ + UINT32 addrofs = address - np2clvga.pciLFB_Addr; + if(addrofs < 0x1000000){ + cirrus_linear_writeb(cirrusvga_opaque, address, value); + }else if( addrofs < 0x1000000 + 0x400000){ + cirrus_linear_bitblt_writeb(cirrusvga_opaque, address, value); + } + return; + }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ + cirrus_mmio_write[0](cirrusvga_opaque, address, value); + if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI) + return; + } + //if(TEST_START_ADDR < address && address <= TEST_END_ADDR){ + // printf("%d: %d\n", address, value); + //} +#if defined(SUPPORT_VGA_MODEX) + // PC/AT互換機 標準VGA相当 書き込み限定で許可 + if(np2clvga.modex && vramWndAddr3==0xa0000){ + UINT32 addr3 = address; + if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ + cirrus_vga_mem_writeb(cirrusvga_opaque, addr3, value); + vramWndAddr3 = 0; + } + } +#endif + if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ + if(vramWndAddr){ + if(vramWndAddr <= address){ + if(address < vramWndAddr + VRAMWINDOW_SIZE){ + g_cirrus_linear_write[0](cirrusvga_opaque, address, value); + return; + }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ + if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT){ + g_cirrus_linear_write[0](cirrusvga_opaque, address, value); + return; + } + } + } + } + if(vramWndAddr3){ + UINT32 addr3 = address; + if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ + CIRRUS_VRAMWND3_FUNC_wb(cirrusvga_opaque, addr3, value); + //TRACEOUT(("mem (write8): %x", address)); + //if(!(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) + // return; + } + } + if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ + UINT32 addr2 = address; + if((vramWndAddr2 & 0xfff00000UL) == 0){ + UINT32 addrtmp = addr2 & 0xfff80000UL; + if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ + // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF + addr2 = addr2 & 0xfffff; + } + } + if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ + CIRRUS_VRAMWND2_FUNC_wb(cirrusvga_opaque, addr2, value); + //if((vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) && !(gdc.display & (1 << GDCDISP_31))) + // return; + } + } + } + } +#endif +// 強制RAM化 + if ((address >= 0xa5000) && (address < 0xa7fff)) { + if (CPU_RAM_D000 & (1 << ((address >> 12) & 15))) { + mem[address] = (UINT8)value; + } + } +// + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + memfn0.wr8[address >> 15](address, value); + } + else if (address < CPU_EXTLIMIT16) { + CPU_EXTMEMBASE[address] = (UINT8)value; + } + else if (address < 0x00f00000) { + } + else if (address < 0x01000000) { + memfnf.wr8[(address >> 17) & 7](address, value); + } +#if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + CPU_EXTMEMBASE[address] = (UINT8)value; + } +#endif // defined(CPU_EXTLIMIT) +#if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + memvgaf_wr8(address, value); + } +#endif // defined(SUPPORT_PC9821) + else { + TRACEOUT(("out of mem (write8): %x", address)); + } + } +} + +void MEMCALL memp_write16(UINT32 address, REG16 value) { + + +#ifdef MEM_BDA_TRACEOUT + if(0x400 <= address && address < 0x600){ + switch(address){ + case 0x55e: + case 0x58a: + break; + case 0x4f8: + case 0x4f9: + case 0x4fa: + case 0x4fb: + case 0x4fc: + case 0x4fd: + break; + default: + TRACEOUT(("BDA (write16): %x val %x -> %x", address, *((UINT16*)(mem+address)), value)); + } + } +#endif + if (address < (I286_MEMWRITEMAX - 1)) { + STOREINTELWORD(mem + address, value); + } + else{ + if (((address + 1) & 0x7fff) && ((address + 2) & 0x7fff) && ((address + 3) & 0x7fff)) { // non 32kb boundary +#if defined(SUPPORT_CL_GD5430) + if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ + UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; + UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; + UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; + if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ + UINT32 addrofs = address - np2clvga.pciLFB_Addr; + if(addrofs < 0x1000000){ + cirrus_linear_writew(cirrusvga_opaque, address, value); + }else if( addrofs < 0x1000000 + 0x400000){ + cirrus_linear_bitblt_writew(cirrusvga_opaque, address, value); + } + return; + }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ + cirrus_mmio_write[1](cirrusvga_opaque, address, value); + if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI) + return; + } + //if(TEST_START_ADDR < address && address <= TEST_END_ADDR){ + // printf("%d: %d\n", address, value); + //} +#if defined(SUPPORT_VGA_MODEX) + // PC/AT互換機 標準VGA相当 書き込み限定で許可 + if(np2clvga.modex && vramWndAddr3==0xa0000){ + UINT32 addr3 = address; + if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ + cirrus_vga_mem_writew(cirrusvga_opaque, addr3, value); + vramWndAddr3 = 0; + } + } +#endif + if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ + if(vramWndAddr){ + if(vramWndAddr <= address){ + if(address < vramWndAddr + VRAMWINDOW_SIZE){ + g_cirrus_linear_write[1](cirrusvga_opaque, address, value); + return; + }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ + if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT){ + g_cirrus_linear_write[1](cirrusvga_opaque, address, value); + return; + } + } + } + } + if(vramWndAddr3){ + UINT32 addr3 = address; + if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ + CIRRUS_VRAMWND3_FUNC_ww(cirrusvga_opaque, addr3, value); + //TRACEOUT(("mem (write16): %x", address)); + //if(!(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) + // return; + } + } + if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ + UINT32 addr2 = address; + if((vramWndAddr2 & 0xfff00000UL) == 0){ + UINT32 addrtmp = addr2 & 0xfff80000UL; + if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ + // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF + addr2 = addr2 & 0xfffff; + } + } + if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ + CIRRUS_VRAMWND2_FUNC_ww(cirrusvga_opaque, addr2, value); + //if((vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) && !(gdc.display & (1 << GDCDISP_31))) + // return; + } + } + } + } +#endif +// 強制RAM化 + if ((address >= 0xa5000) && (address < 0xa7fff)) { + + UINT8 *ptr; + UINT16 bit; + + ptr = mem + address; + bit = 1 << ((address >> 12) & 15); + if ((address + 1) & 0xfff) { + if (CPU_RAM_D000 & bit) { + STOREINTELWORD(ptr, value); + } + } + else { + if (CPU_RAM_D000 & bit) { + ptr[0] = (UINT8)value; + } + if (CPU_RAM_D000 & (bit << 1)) { + ptr[1] = (UINT8)(value >> 8); + } + } + } +// + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + memfn0.wr16[address >> 15](address, value); + } + else if (address < CPU_EXTLIMIT16) { + STOREINTELWORD(CPU_EXTMEMBASE + address, value); + } + else if (address < 0x00f00000) { + } + else if (address < 0x01000000) { + memfnf.wr16[(address >> 17) & 7](address, value); + } +#if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + STOREINTELWORD(CPU_EXTMEMBASE + address, value); + } +#endif // defined(CPU_EXTLIMIT) +#if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + memvgaf_wr16(address, value); + } +#endif // defined(SUPPORT_PC9821) + else { + TRACEOUT(("out of mem (write16): %x", address)); + } + } + else { + memp_write8(address + 0, (UINT8)value); + memp_write8(address + 1, (UINT8)(value >> 8)); + } + } +} + +void MEMCALL memp_write32(UINT32 address, UINT32 value) { + + //UINT32 pos; + +#ifdef MEM_BDA_TRACEOUT + if(0x400 <= address && address < 0x600){ + switch(address){ + case 0x55e: + case 0x58a: + break; + case 0x4f8: + case 0x4f9: + case 0x4fa: + case 0x4fb: + case 0x4fc: + case 0x4fd: + break; + default: + TRACEOUT(("BDA (write32): %x val %x -> %x", address, *((UINT32*)(mem+address)), value)); + } + } +#endif + if (address < (I286_MEMWRITEMAX - 3)) { + STOREINTELDWORD(mem + address, value); + return; + } + else{ + if ((address + 1) & 0x7fff) { // non 32kb boundary +#if defined(SUPPORT_CL_GD5430) + if(np2clvga.enabled && cirrusvga_opaque && (cirrusvga_wab_46e8 & 0x08)){ + UINT32 vramWndAddr = np2clvga.VRAMWindowAddr; + UINT32 vramWndAddr2 = np2clvga.VRAMWindowAddr2; + UINT32 vramWndAddr3 = np2clvga.VRAMWindowAddr3; + if(np2clvga.pciLFB_Addr && (address & np2clvga.pciLFB_Mask) == np2clvga.pciLFB_Addr){ + UINT32 addrofs = address - np2clvga.pciLFB_Addr; + if(addrofs < 0x1000000){ + cirrus_linear_writel(cirrusvga_opaque, address, value); + }else if( addrofs < 0x1000000 + 0x400000){ + cirrus_linear_bitblt_writel(cirrusvga_opaque, address, value); + } + return; + }else if(np2clvga.pciMMIO_Addr && (address & np2clvga.pciMMIO_Mask) == np2clvga.pciMMIO_Addr){ + cirrus_mmio_write[2](cirrusvga_opaque, address, value); + if(np2clvga.gd54xxtype==CIRRUS_98ID_PCI) + return; + } + //if(TEST_START_ADDR < address && address <= TEST_END_ADDR){ + // printf("%d: %d\n", address, value); + //} +#if defined(SUPPORT_VGA_MODEX) + // PC/AT互換機 標準VGA相当 書き込み限定で許可 + if(np2clvga.modex && vramWndAddr3==0xa0000){ + UINT32 addr3 = address; + if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ + cirrus_vga_mem_writel(cirrusvga_opaque, addr3, value); + vramWndAddr3 = 0; + } + } +#endif + if(np2clvga.gd54xxtype!=CIRRUS_98ID_PCI){ + if(vramWndAddr){ + if(vramWndAddr <= address){ + if(address < vramWndAddr + VRAMWINDOW_SIZE){ + g_cirrus_linear_write[2](cirrusvga_opaque, address, value); + return; + }else if(address < vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SIZE){ + if(address >= vramWndAddr + VRAMWINDOW_SIZE + EXT_WINDOW_SHFT){ + g_cirrus_linear_write[2](cirrusvga_opaque, address, value); + return; + } + } + } + } + if(vramWndAddr3){ + UINT32 addr3 = address; + if(vramWndAddr3 <= addr3 && addr3 < vramWndAddr3 + VRA3WINDOW_SIZEX){ + CIRRUS_VRAMWND3_FUNC_wl(cirrusvga_opaque, addr3, value); + //TRACEOUT(("mem (write32): %x", address)); + //if(!(gdc.analog & ((1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) + // return; + } + } + if(vramWndAddr2 && (vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E))))){ + UINT32 addr2 = address; + if((vramWndAddr2 & 0xfff00000UL) == 0){ + UINT32 addrtmp = addr2 & 0xfff80000UL; + if(addrtmp == 0xfff80000UL || addrtmp == 0x00f80000UL){ + // XXX: 0xFFFA0000 - 0xFFFFFFFF or 0xFA0000 - 0xFFFFFF + addr2 = addr2 & 0xfffff; + } + } + if((addr2 & CIRRUS_VRAMWINDOW2MASK) == vramWndAddr2){ + CIRRUS_VRAMWND2_FUNC_wl(cirrusvga_opaque, addr2, value); + //if((vramWndAddr2 != 0xE0000 || !(gdc.analog & ((1 << GDCANALOG_16) | (1 << GDCANALOG_256) | (1 << GDCANALOG_256E)))) && !(gdc.display & (1 << GDCDISP_31))) + // return; + } + } + } + } +#endif + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + memfn0.wr32[address >> 15](address, value); + } + else if (address < CPU_EXTLIMIT16) { + STOREINTELDWORD(CPU_EXTMEMBASE + address, value); + } + else if (address < 0x00f00000) { + } + else if (address < 0x01000000) { + memfnf.wr32[(address >> 17) & 7](address, value); + } +#if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + STOREINTELDWORD(CPU_EXTMEMBASE + address, value); + } +#endif // defined(CPU_EXTLIMIT) +#if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + memvgaf_wr32(address, value); + } +#endif // defined(SUPPORT_PC9821) + else { + TRACEOUT(("out of mem (write32): %x", address)); + } + } + else { + if (!(address & 1)) { + memp_write16(address + 0, (UINT16)value); + memp_write16(address + 2, (UINT16)(value >> 16)); + } + else { + memp_write8(address + 0, (UINT8)value); + memp_write16(address + 1, (UINT16)(value >> 8)); + memp_write8(address + 3, (UINT8)(value >> 24)); + } + } + } +} + +void MEMCALL memp_write8_paging(UINT32 address, REG8 value) { + + //if (address==0x0457) return; // XXX: IDEのデータ破壊回避のための暫定 + if (address < I286_MEMWRITEMAX) { + mem[address] = (UINT8)value; + } + else { + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + memfn0.wr8[address >> 15](address, value); + } + else if (address < CPU_EXTLIMIT16) { + CPU_EXTMEMBASE[address] = (UINT8)value; + } + else if (address < 0x00f00000) { + } + else if (address < 0x01000000) { + memfnf.wr8[(address >> 17) & 7](address, value); + } +#if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + CPU_EXTMEMBASE[address] = (UINT8)value; + } +#endif // defined(CPU_EXTLIMIT) +#if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + memvgaf_wr8(address, value); + } +#endif // defined(SUPPORT_PC9821) + else { + TRACEOUT(("out of mem (write8): %x", address)); + } + } +} + +void MEMCALL memp_write16_paging(UINT32 address, REG16 value) { + + if (address < (I286_MEMWRITEMAX - 1)) { + STOREINTELWORD(mem + address, value); + } + else{ + if ((address + 1) & 0x7fff) { // non 32kb boundary + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + memfn0.wr16[address >> 15](address, value); + } + else if (address < CPU_EXTLIMIT16) { + STOREINTELWORD(CPU_EXTMEMBASE + address, value); + } + else if (address < 0x00f00000) { + } + else if (address < 0x01000000) { + memfnf.wr16[(address >> 17) & 7](address, value); + } +#if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + STOREINTELWORD(CPU_EXTMEMBASE + address, value); + } +#endif // defined(CPU_EXTLIMIT) +#if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + memvgaf_wr16(address, value); + } +#endif // defined(SUPPORT_PC9821) + else { + TRACEOUT(("out of mem (write16): %x", address)); + } + } + else { + memp_write8_paging(address + 0, (UINT8)value); + memp_write8_paging(address + 1, (UINT8)(value >> 8)); + } + } +} + +void MEMCALL memp_write32_paging(UINT32 address, UINT32 value) { + + if (address < (I286_MEMWRITEMAX - 3)) { + STOREINTELDWORD(mem + address, value); + return; + } + else{ + if ((address + 1) & 0x7fff) { // non 32kb boundary + address = address & CPU_ADRSMASK; + if (address < USE_HIMEM) { + memfn0.wr32[address >> 15](address, value); + } + else if (address < CPU_EXTLIMIT16) { + STOREINTELDWORD(CPU_EXTMEMBASE + address, value); + } + else if (address < 0x00f00000) { + } + else if (address < 0x01000000) { + memfnf.wr32[(address >> 17) & 7](address, value); + } +#if defined(CPU_EXTLIMIT) + else if (address < CPU_EXTLIMIT) { + STOREINTELDWORD(CPU_EXTMEMBASE + address, value); + } +#endif // defined(CPU_EXTLIMIT) +#if defined(SUPPORT_PC9821) + else if ((address >= 0xfff00000) && (address < 0xfff80000)) { + memvgaf_wr32(address, value); + } +#endif // defined(SUPPORT_PC9821) + else { + TRACEOUT(("out of mem (write32): %x", address)); + } + } + else { + if (!(address & 1)) { + memp_write16_paging(address + 0, (UINT16)value); + memp_write16_paging(address + 2, (UINT16)(value >> 16)); + } + else { + memp_write8_paging(address + 0, (UINT8)value); + memp_write16_paging(address + 1, (UINT16)(value >> 8)); + memp_write8_paging(address + 3, (UINT8)(value >> 24)); + } + } + } +} + + +void MEMCALL memp_reads(UINT32 address, void *dat, UINT leng) { + + UINT8 *out = (UINT8 *)dat; + UINT diff; + + /* fast memory access */ + if ((address + leng) < I286_MEMREADMAX) { + CopyMemory(dat, mem + address, leng); + return; + } + address = address & CPU_ADRSMASK; + if ((address >= USE_HIMEM) && (address < CPU_EXTLIMIT16)) { + diff = CPU_EXTLIMIT16 - address; + if (diff >= leng) { + CopyMemory(dat, CPU_EXTMEMBASE + address, leng); + return; + } + CopyMemory(dat, CPU_EXTMEMBASE + address, diff); + out += diff; + leng -= diff; + address += diff; + } + + /* slow memory access */ + while (leng-- > 0) { + *out++ = memp_read8(address++); + } +} + +void MEMCALL memp_writes(UINT32 address, const void *dat, UINT leng) { + + const UINT8 *out = (UINT8 *)dat; + UINT diff; + + /* fast memory access */ + if ((address + leng) < I286_MEMREADMAX) { + CopyMemory(mem + address, dat, leng); + return; + } + address = address & CPU_ADRSMASK; + if ((address >= USE_HIMEM) && (address < CPU_EXTLIMIT16)) { + diff = CPU_EXTLIMIT16 - address; + if (diff >= leng) { + CopyMemory(CPU_EXTMEMBASE + address, dat, leng); + return; + } + CopyMemory(CPU_EXTMEMBASE + address, dat, diff); + out += diff; + leng -= diff; + address += diff; + } + + /* slow memory access */ + while (leng-- > 0) { + memp_write8(address++, *out++); + } +} + + +// ---- Logical Space (BIOS) + +static UINT32 MEMCALL physicaladdr(UINT32 addr, BOOL wr) { + + UINT32 a; + UINT32 pde; + UINT32 pte; + + a = CPU_STAT_PDE_BASE + ((addr >> 20) & 0xffc); + pde = memp_read32(a); + if (!(pde & CPU_PDE_PRESENT)) { + goto retdummy; + } + if (!(pde & CPU_PDE_ACCESS)) { + memp_write8(a, (UINT8)(pde | CPU_PDE_ACCESS)); + } + a = (pde & CPU_PDE_BASEADDR_MASK) + ((addr >> 10) & 0xffc); + pte = cpu_memoryread_d(a); + if (!(pte & CPU_PTE_PRESENT)) { + goto retdummy; + } + if (!(pte & CPU_PTE_ACCESS)) { + memp_write8(a, (UINT8)(pte | CPU_PTE_ACCESS)); + } + if ((wr) && (!(pte & CPU_PTE_DIRTY))) { + memp_write8(a, (UINT8)(pte | CPU_PTE_DIRTY)); + } + addr = (pte & CPU_PTE_BASEADDR_MASK) + (addr & 0x00000fff); + return(addr); + + retdummy: + return(0x01000000); /* XXX */ +} + + +void MEMCALL meml_reads(UINT32 address, void *dat, UINT leng) { + + UINT size; + + if (!CPU_STAT_PAGING) { + memp_reads(address, dat, leng); + } + else { + while(leng) { + size = 0x1000 - (address & 0xfff); + size = MIN(size, leng); + memp_reads(physicaladdr(address, FALSE), dat, size); + address += size; + dat = ((UINT8 *)dat) + size; + leng -= size; + } + } +} + +void MEMCALL meml_writes(UINT32 address, const void *dat, UINT leng) { + + UINT size; + + if (!CPU_STAT_PAGING) { + memp_writes(address, dat, leng); + } + else { + while(leng) { + size = 0x1000 - (address & 0xfff); + size = MIN(size, leng); + memp_writes(physicaladdr(address, TRUE), dat, size); + address += size; + dat = ((UINT8 *)dat) + size; + leng -= size; + } + } +} + + +REG8 MEMCALL memr_read8(UINT seg, UINT off) { + + UINT32 addr; + + addr = (seg << 4) + LOW16(off); + if (CPU_STAT_PAGING) { + addr = physicaladdr(addr, FALSE); + } + return(memp_read8(addr)); +} + +REG16 MEMCALL memr_read16(UINT seg, UINT off) { + + UINT32 addr; + + addr = (seg << 4) + LOW16(off); + if (!CPU_STAT_PAGING) { + return(memp_read16(addr)); + } + else if ((addr + 1) & 0xfff) { + return(memp_read16(physicaladdr(addr, FALSE))); + } + return(memr_read8(seg, off) + (memr_read8(seg, off + 1) << 8)); +} + +void MEMCALL memr_write8(UINT seg, UINT off, REG8 dat) { + + UINT32 addr; + + addr = (seg << 4) + LOW16(off); + if (CPU_STAT_PAGING) { + addr = physicaladdr(addr, TRUE); + } + memp_write8(addr, dat); +} + +void MEMCALL memr_write16(UINT seg, UINT off, REG16 dat) { + + UINT32 addr; + + addr = (seg << 4) + LOW16(off); + if (!CPU_STAT_PAGING) { + memp_write16(addr, dat); + } + else if ((addr + 1) & 0xfff) { + memp_write16(physicaladdr(addr, TRUE), dat); + } + else { + memr_write8(seg, off, (REG8)dat); + memr_write8(seg, off + 1, (REG8)(dat >> 8)); + } +} + +void MEMCALL memr_reads(UINT seg, UINT off, void *dat, UINT leng) { + + UINT32 addr; + UINT rem; + UINT size; + + while(leng) { + off = LOW16(off); + addr = (seg << 4) + off; + rem = 0x10000 - off; + size = MIN(leng, rem); + if (CPU_STAT_PAGING) { + rem = 0x1000 - (addr & 0xfff); + size = MIN(size, rem); + addr = physicaladdr(addr, FALSE); + } + memp_reads(addr, dat, size); + off += size; + dat = ((UINT8 *)dat) + size; + leng -= size; + } +} + +void MEMCALL memr_writes(UINT seg, UINT off, const void *dat, UINT leng) { + + UINT32 addr; + UINT rem; + UINT size; + + while(leng) { + off = LOW16(off); + addr = (seg << 4) + off; + rem = 0x10000 - off; + size = MIN(leng, rem); + if (CPU_STAT_PAGING) { + rem = 0x1000 - (addr & 0xfff); + size = MIN(size, rem); + addr = physicaladdr(addr, TRUE); + } + memp_writes(addr, dat, size); + off += size; + dat = ((UINT8 *)dat) + size; + leng -= size; + } +} + +#endif diff --git a/i386c/cpumem.h b/i386c/cpumem.h old mode 100755 new mode 100644 index 46a3900f..bd6aef1c --- a/i386c/cpumem.h +++ b/i386c/cpumem.h @@ -1,160 +1,160 @@ -#ifndef NP2_I386C_CPUMEM_H__ -#define NP2_I386C_CPUMEM_H__ - -#ifdef NP2_MEMORY_ASM // アセンブラ版は 必ずfastcallで -#undef MEMCALL -#define MEMCALL FASTCALL -#endif - -#if !defined(MEMCALL) -#define MEMCALL -#endif - -// 000000-0fffff メインメモリ -// 100000-10ffef HMA -// 110000-193fff FONT-ROM/RAM -// 1a8000-1bffff VRAM1 -// 1c0000-1c7fff ITF-ROM BAK -// 1c8000-1dffff EPSON RAM -// 1e0000-1e7fff VRAM1 -// 1f8000-1fffff ITF-ROM - -#define CPU_MEMREADMAX 0x0a4000 -#define CPU_MEMWRITEMAX 0x0a0000 - -#define VRAM_STEP 0x100000 -#define VRAM_B 0x0a8000 -#define VRAM_R 0x0b0000 -#define VRAM_G 0x0b8000 -#define VRAM_E 0x0e0000 - -#define VRAMADDRMASKEX(a) ((a) & (VRAM_STEP | 0x7fff)) - -#define VRAM0_B VRAM_B -#define VRAM0_R VRAM_R -#define VRAM0_G VRAM_G -#define VRAM0_E VRAM_E -#define VRAM1_B (VRAM_STEP + VRAM_B) -#define VRAM1_R (VRAM_STEP + VRAM_R) -#define VRAM1_G (VRAM_STEP + VRAM_G) -#define VRAM1_E (VRAM_STEP + VRAM_E) - -#define FONT_ADRS 0x110000 -#define ITF_ADRS 0x1f8000 - -#define USE_HIMEM 0x110000 - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(SUPPORT_IA32_HAXM) -extern UINT8 membase[0x200000]; -extern UINT8 *mem; -#else -extern UINT8 mem[0x200000]; -#endif - -void MEMCALL memm_arch(UINT type); -void MEMCALL memm_vram(UINT operate); - -REG8 MEMCALL memp_read8(UINT32 address); -REG16 MEMCALL memp_read16(UINT32 address); -UINT32 MEMCALL memp_read32(UINT32 address); -void MEMCALL memp_write8(UINT32 address, REG8 value); -void MEMCALL memp_write16(UINT32 address, REG16 value); -void MEMCALL memp_write32(UINT32 address, UINT32 value); -void MEMCALL memp_reads(UINT32 address, void *dat, UINT leng); -void MEMCALL memp_writes(UINT32 address, const void *dat, UINT leng); -PF_UINT8 MEMCALL memp_read8_codefetch(UINT32 address); -PF_UINT16 MEMCALL memp_read16_codefetch(UINT32 address); -PF_UINT32 MEMCALL memp_read32_codefetch(UINT32 address); -PF_UINT8 MEMCALL memp_read8_paging(UINT32 address); -PF_UINT16 MEMCALL memp_read16_paging(UINT32 address); -PF_UINT32 MEMCALL memp_read32_paging(UINT32 address); -void MEMCALL memp_write8_paging(UINT32 address, REG8 value); -void MEMCALL memp_write16_paging(UINT32 address, REG16 value); -void MEMCALL memp_write32_paging(UINT32 address, UINT32 value); - -REG8 MEMCALL meml_read8(UINT32 address); -REG16 MEMCALL meml_read16(UINT32 address); -UINT32 MEMCALL meml_read32(UINT32 address); -void MEMCALL meml_write8(UINT32 address, REG8 dat); -void MEMCALL meml_write16(UINT32 address, REG16 dat); -void MEMCALL meml_write32(UINT32 address, UINT32 dat); -void MEMCALL meml_reads(UINT32 address, void *dat, UINT leng); -void MEMCALL meml_writes(UINT32 address, const void *dat, UINT leng); - -REG8 MEMCALL memr_read8(UINT seg, UINT off); -REG16 MEMCALL memr_read16(UINT seg, UINT off); -UINT32 MEMCALL memr_read32(UINT seg, UINT off); -void MEMCALL memr_write8(UINT seg, UINT off, REG8 dat); -void MEMCALL memr_write16(UINT seg, UINT off, REG16 dat); -void MEMCALL memr_write32(UINT seg, UINT off, UINT32 dat); -void MEMCALL memr_reads(UINT seg, UINT off, void *dat, UINT leng); -void MEMCALL memr_writes(UINT seg, UINT off, const void *dat, UINT leng); - -#ifdef __cplusplus -} -#endif - - -// ---- Memory map - -#define MEMM_ARCH(t) memm_arch(t) -#define MEMM_VRAM(o) memm_vram(o) - - -// ---- Physical Space (DMA) - -#define MEMP_READ8(addr) \ - memp_read8((addr)) -#define MEMP_READ16(addr) \ - memp_read16((addr)) -#define MEMP_READ32(addr) \ - memp_read32((addr)) -#define MEMP_WRITE8(addr, dat) \ - memp_write8((addr), (dat)) -#define MEMP_WRITE16(addr, dat) \ - memp_write16((addr), (dat)) -#define MEMP_WRITE32(addr, dat) \ - memp_write32((addr), (dat)) -#define MEMP_READS(addr, dat, leng) \ - memp_reads((addr), (dat), (leng)) -#define MEMP_WRITES(addr, dat, leng) \ - memp_writes((addr), (dat), (leng)) - - -// ---- Logical Space (BIOS) - -#define MEML_READ8(addr) \ - meml_read8((addr)) -#define MEML_READ16(addr) \ - meml_read16((addr)) -#define MEML_READ32(addr) \ - meml_read32((addr)) -#define MEML_WRITE8(addr, dat) \ - meml_write8((addr), (dat)) -#define MEML_WRITE16(addr, dat) \ - meml_write16((addr), (dat)) -#define MEML_WRITE32(addr, dat) \ - meml_write32((addr), (dat)) -#define MEML_READS(addr, dat, leng) \ - meml_reads((addr), (dat), (leng)) -#define MEML_WRITES(addr, dat, leng) \ - meml_writes((addr), (dat), (leng)) - -#define MEMR_READ8(seg, off) \ - memr_read8((seg), (off)) -#define MEMR_READ16(seg, off) \ - memr_read16((seg), (off)) -#define MEMR_WRITE8(seg, off, dat) \ - memr_write8((seg), (off), (dat)) -#define MEMR_WRITE16(seg, off, dat) \ - memr_write16((seg), (off), (dat)) -#define MEMR_READS(seg, off, dat, leng) \ - memr_reads((seg), (off), (dat), (leng)) -#define MEMR_WRITES(seg, off, dat, leng) \ - memr_writes((seg), (off), (dat), (leng)) - -#endif /* !NP2_I386C_CPUMEM_H__ */ +#ifndef NP2_I386C_CPUMEM_H__ +#define NP2_I386C_CPUMEM_H__ + +#ifdef NP2_MEMORY_ASM // アセンブラ版は 必ずfastcallで +#undef MEMCALL +#define MEMCALL FASTCALL +#endif + +#if !defined(MEMCALL) +#define MEMCALL +#endif + +// 000000-0fffff メインメモリ +// 100000-10ffef HMA +// 110000-193fff FONT-ROM/RAM +// 1a8000-1bffff VRAM1 +// 1c0000-1c7fff ITF-ROM BAK +// 1c8000-1dffff EPSON RAM +// 1e0000-1e7fff VRAM1 +// 1f8000-1fffff ITF-ROM + +#define CPU_MEMREADMAX 0x0a4000 +#define CPU_MEMWRITEMAX 0x0a0000 + +#define VRAM_STEP 0x100000 +#define VRAM_B 0x0a8000 +#define VRAM_R 0x0b0000 +#define VRAM_G 0x0b8000 +#define VRAM_E 0x0e0000 + +#define VRAMADDRMASKEX(a) ((a) & (VRAM_STEP | 0x7fff)) + +#define VRAM0_B VRAM_B +#define VRAM0_R VRAM_R +#define VRAM0_G VRAM_G +#define VRAM0_E VRAM_E +#define VRAM1_B (VRAM_STEP + VRAM_B) +#define VRAM1_R (VRAM_STEP + VRAM_R) +#define VRAM1_G (VRAM_STEP + VRAM_G) +#define VRAM1_E (VRAM_STEP + VRAM_E) + +#define FONT_ADRS 0x110000 +#define ITF_ADRS 0x1f8000 + +#define USE_HIMEM 0x110000 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(SUPPORT_IA32_HAXM) +extern UINT8 membase[0x200000]; +extern UINT8 *mem; +#else +extern UINT8 mem[0x200000]; +#endif + +void MEMCALL memm_arch(UINT type); +void MEMCALL memm_vram(UINT operate); + +REG8 MEMCALL memp_read8(UINT32 address); +REG16 MEMCALL memp_read16(UINT32 address); +UINT32 MEMCALL memp_read32(UINT32 address); +void MEMCALL memp_write8(UINT32 address, REG8 value); +void MEMCALL memp_write16(UINT32 address, REG16 value); +void MEMCALL memp_write32(UINT32 address, UINT32 value); +void MEMCALL memp_reads(UINT32 address, void *dat, UINT leng); +void MEMCALL memp_writes(UINT32 address, const void *dat, UINT leng); +PF_UINT8 MEMCALL memp_read8_codefetch(UINT32 address); +PF_UINT16 MEMCALL memp_read16_codefetch(UINT32 address); +PF_UINT32 MEMCALL memp_read32_codefetch(UINT32 address); +PF_UINT8 MEMCALL memp_read8_paging(UINT32 address); +PF_UINT16 MEMCALL memp_read16_paging(UINT32 address); +PF_UINT32 MEMCALL memp_read32_paging(UINT32 address); +void MEMCALL memp_write8_paging(UINT32 address, REG8 value); +void MEMCALL memp_write16_paging(UINT32 address, REG16 value); +void MEMCALL memp_write32_paging(UINT32 address, UINT32 value); + +REG8 MEMCALL meml_read8(UINT32 address); +REG16 MEMCALL meml_read16(UINT32 address); +UINT32 MEMCALL meml_read32(UINT32 address); +void MEMCALL meml_write8(UINT32 address, REG8 dat); +void MEMCALL meml_write16(UINT32 address, REG16 dat); +void MEMCALL meml_write32(UINT32 address, UINT32 dat); +void MEMCALL meml_reads(UINT32 address, void *dat, UINT leng); +void MEMCALL meml_writes(UINT32 address, const void *dat, UINT leng); + +REG8 MEMCALL memr_read8(UINT seg, UINT off); +REG16 MEMCALL memr_read16(UINT seg, UINT off); +UINT32 MEMCALL memr_read32(UINT seg, UINT off); +void MEMCALL memr_write8(UINT seg, UINT off, REG8 dat); +void MEMCALL memr_write16(UINT seg, UINT off, REG16 dat); +void MEMCALL memr_write32(UINT seg, UINT off, UINT32 dat); +void MEMCALL memr_reads(UINT seg, UINT off, void *dat, UINT leng); +void MEMCALL memr_writes(UINT seg, UINT off, const void *dat, UINT leng); + +#ifdef __cplusplus +} +#endif + + +// ---- Memory map + +#define MEMM_ARCH(t) memm_arch(t) +#define MEMM_VRAM(o) memm_vram(o) + + +// ---- Physical Space (DMA) + +#define MEMP_READ8(addr) \ + memp_read8((addr)) +#define MEMP_READ16(addr) \ + memp_read16((addr)) +#define MEMP_READ32(addr) \ + memp_read32((addr)) +#define MEMP_WRITE8(addr, dat) \ + memp_write8((addr), (dat)) +#define MEMP_WRITE16(addr, dat) \ + memp_write16((addr), (dat)) +#define MEMP_WRITE32(addr, dat) \ + memp_write32((addr), (dat)) +#define MEMP_READS(addr, dat, leng) \ + memp_reads((addr), (dat), (leng)) +#define MEMP_WRITES(addr, dat, leng) \ + memp_writes((addr), (dat), (leng)) + + +// ---- Logical Space (BIOS) + +#define MEML_READ8(addr) \ + meml_read8((addr)) +#define MEML_READ16(addr) \ + meml_read16((addr)) +#define MEML_READ32(addr) \ + meml_read32((addr)) +#define MEML_WRITE8(addr, dat) \ + meml_write8((addr), (dat)) +#define MEML_WRITE16(addr, dat) \ + meml_write16((addr), (dat)) +#define MEML_WRITE32(addr, dat) \ + meml_write32((addr), (dat)) +#define MEML_READS(addr, dat, leng) \ + meml_reads((addr), (dat), (leng)) +#define MEML_WRITES(addr, dat, leng) \ + meml_writes((addr), (dat), (leng)) + +#define MEMR_READ8(seg, off) \ + memr_read8((seg), (off)) +#define MEMR_READ16(seg, off) \ + memr_read16((seg), (off)) +#define MEMR_WRITE8(seg, off, dat) \ + memr_write8((seg), (off), (dat)) +#define MEMR_WRITE16(seg, off, dat) \ + memr_write16((seg), (off), (dat)) +#define MEMR_READS(seg, off, dat, leng) \ + memr_reads((seg), (off), (dat), (leng)) +#define MEMR_WRITES(seg, off, dat, leng) \ + memr_writes((seg), (off), (dat), (leng)) + +#endif /* !NP2_I386C_CPUMEM_H__ */ diff --git a/i386c/ia32/cpu.c b/i386c/ia32/cpu.c old mode 100755 new mode 100644 index 077259cf..480bf539 --- a/i386c/ia32/cpu.c +++ b/i386c/ia32/cpu.c @@ -1,633 +1,633 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "cpu.h" -#include "ia32.mcr" - -#include "inst_table.h" - -#if defined(ENABLE_TRAP) -#include "trap/steptrap.h" -#endif - -#if defined(SUPPORT_ASYNC_CPU) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_SMPU98) -#include -#endif -#endif - -sigjmp_buf exec_1step_jmpbuf; - -#if defined(IA32_INSTRUCTION_TRACE) -typedef struct { - CPU_REGS regs; - disasm_context_t disasm; - - BYTE op[MAX_PREFIX + 2]; - int opbytes; -} ia32_context_t; - -#define NCTX 1024 - -ia32_context_t ctx[NCTX]; -int ctx_index = 0; - -int cpu_inst_trace = 0; -#endif - -#if defined(DEBUG) -int cpu_debug_rep_cont = 0; -CPU_REGS cpu_debug_rep_regs; -#endif - -void -exec_1step(void) -{ - int prefix; - UINT32 op; - - CPU_PREV_EIP = CPU_EIP; - CPU_STATSAVE.cpu_inst = CPU_STATSAVE.cpu_inst_default; - -#if defined(ENABLE_TRAP) - steptrap(CPU_CS, CPU_EIP); -#endif - -#if defined(IA32_INSTRUCTION_TRACE) - ctx[ctx_index].regs = CPU_STATSAVE.cpu_regs; - if (cpu_inst_trace) { - disasm_context_t *d = &ctx[ctx_index].disasm; - UINT32 eip = CPU_EIP; - int rv; - - rv = disasm(&eip, d); - if (rv == 0) { - char buf[256]; - char tmp[32]; - int len = d->nopbytes > 8 ? 8 : d->nopbytes; - int i; - - buf[0] = '\0'; - for (i = 0; i < len; i++) { - snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); - milstr_ncat(buf, tmp, sizeof(buf)); - } - for (; i < 8; i++) { - milstr_ncat(buf, " ", sizeof(buf)); - } - VERBOSE(("%04x:%08x: %s%s", CPU_CS, CPU_EIP, buf, d->str)); - - buf[0] = '\0'; - for (; i < d->nopbytes; i++) { - snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); - milstr_ncat(buf, tmp, sizeof(buf)); - if ((i % 8) == 7) { - VERBOSE((" : %s", buf)); - buf[0] = '\0'; - } - } - if ((i % 8) != 0) { - VERBOSE((" : %s", buf)); - } - } - } - ctx[ctx_index].opbytes = 0; -#endif - - for (prefix = 0; prefix < MAX_PREFIX; prefix++) { - GET_PCBYTE(op); -#if defined(IA32_INSTRUCTION_TRACE) - ctx[ctx_index].op[prefix] = op; - ctx[ctx_index].opbytes++; -#endif - - /* prefix */ - if (insttable_info[op] & INST_PREFIX) { - (*insttable_1byte[0][op])(); - continue; - } - break; - } - if (prefix == MAX_PREFIX) { - EXCEPTION(UD_EXCEPTION, 0); - } - -#if defined(IA32_INSTRUCTION_TRACE) - if (op == 0x0f) { - BYTE op2; - op2 = cpu_codefetch(CPU_EIP); - ctx[ctx_index].op[prefix + 1] = op2; - ctx[ctx_index].opbytes++; - } - ctx_index = (ctx_index + 1) % NELEMENTS(ctx); -#endif - - /* normal / rep, but not use */ - if (!(insttable_info[op] & INST_STRING) || !CPU_INST_REPUSE) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - (*insttable_1byte[CPU_INST_OP32][op])(); - return; - } - - /* rep */ - CPU_WORKCLOCK(5); -#if defined(DEBUG) - if (!cpu_debug_rep_cont) { - cpu_debug_rep_cont = 1; - cpu_debug_rep_regs = CPU_STATSAVE.cpu_regs; - } -#endif - if (!CPU_INST_AS32) { - if (CPU_CX != 0) { - if (!(insttable_info[op] & REP_CHECKZF)) { - /* rep */ - for (;;) { - (*insttable_1byte[CPU_INST_OP32][op])(); - if (--CPU_CX == 0) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } else if (CPU_INST_REPUSE != 0xf2) { - /* repe */ - for (;;) { - (*insttable_1byte[CPU_INST_OP32][op])(); - if (--CPU_CX == 0 || CC_NZ) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } else { - /* repne */ - for (;;) { - (*insttable_1byte[CPU_INST_OP32][op])(); - if (--CPU_CX == 0 || CC_Z) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } - } - } else { - if (CPU_ECX != 0) { - if (!(insttable_info[op] & REP_CHECKZF)) { - /* rep */ - for (;;) { - (*insttable_1byte[CPU_INST_OP32][op])(); - if (--CPU_ECX == 0) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } else if (CPU_INST_REPUSE != 0xf2) { - /* repe */ - for (;;) { - (*insttable_1byte[CPU_INST_OP32][op])(); - if (--CPU_ECX == 0 || CC_NZ) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } else { - /* repne */ - for (;;) { - (*insttable_1byte[CPU_INST_OP32][op])(); - if (--CPU_ECX == 0 || CC_Z) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } - } - } -} - -void -exec_allstep(void) -{ - int prefix; - UINT32 op; - void (*func)(void); - - do { - - CPU_PREV_EIP = CPU_EIP; - CPU_STATSAVE.cpu_inst = CPU_STATSAVE.cpu_inst_default; - -#if defined(ENABLE_TRAP) - steptrap(CPU_CS, CPU_EIP); -#endif - -#if defined(IA32_INSTRUCTION_TRACE) - ctx[ctx_index].regs = CPU_STATSAVE.cpu_regs; - if (cpu_inst_trace) { - disasm_context_t *d = &ctx[ctx_index].disasm; - UINT32 eip = CPU_EIP; - int rv; - - rv = disasm(&eip, d); - if (rv == 0) { - char buf[256]; - char tmp[32]; - int len = d->nopbytes > 8 ? 8 : d->nopbytes; - int i; - - buf[0] = '\0'; - for (i = 0; i < len; i++) { - snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); - milstr_ncat(buf, tmp, sizeof(buf)); - } - for (; i < 8; i++) { - milstr_ncat(buf, " ", sizeof(buf)); - } - VERBOSE(("%04x:%08x: %s%s", CPU_CS, CPU_EIP, buf, d->str)); - - buf[0] = '\0'; - for (; i < d->nopbytes; i++) { - snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); - milstr_ncat(buf, tmp, sizeof(buf)); - if ((i % 8) == 7) { - VERBOSE((" : %s", buf)); - buf[0] = '\0'; - } - } - if ((i % 8) != 0) { - VERBOSE((" : %s", buf)); - } - } - } - ctx[ctx_index].opbytes = 0; -#endif - - for (prefix = 0; prefix < MAX_PREFIX; prefix++) - { -#if defined(USE_CPU_MODRMPREFETCH) - if ((CPU_EIP + 1) & CPU_PAGE_MASK) - { - op = cpu_opcodefetch(CPU_EIP); -#if defined(USE_CPU_EIPMASK) - CPU_EIP = (CPU_EIP + 1) & CPU_EIPMASK; -#else - if (CPU_STATSAVE.cpu_inst_default.op_32) - { - CPU_EIP = (CPU_EIP + 1); - } - else - { - CPU_EIP = (CPU_EIP + 1) & 0xffff; - } -#endif - } - else -#endif - { - GET_PCBYTE(op); - } -#if defined(IA32_INSTRUCTION_TRACE) - ctx[ctx_index].op[prefix] = op; - ctx[ctx_index].opbytes++; -#endif - - /* prefix */ - if (insttable_info[op] & INST_PREFIX) - { -#if defined(USE_CPU_INLINEINST) - // インライン命令群 関数テーブルよりも呼び出しが高速だが、多く置きすぎるとifが増えて逆に遅くなる。なので呼び出し頻度が高い物を優先して配置 - if (!(op & 0x26)) { - (*insttable_1byte[0][op])(); - continue; - } - else { - if (op == 0x66) - { - CPU_INST_OP32 = !CPU_STATSAVE.cpu_inst_default.op_32; - continue; - } - else if (op == 0x26) - { - CPU_INST_SEGUSE = 1; - CPU_INST_SEGREG_INDEX = CPU_ES_INDEX; - continue; - } - else if (op == 0x67) - { - CPU_INST_AS32 = !CPU_STATSAVE.cpu_inst_default.as_32; - continue; - } - else if (op == 0x2E) - { - CPU_INST_SEGUSE = 1; - CPU_INST_SEGREG_INDEX = CPU_CS_INDEX; - continue; - } - //else if (op == 0xF3) - //{ - // CPU_INST_REPUSE = 0xf3; - // continue; - //} - else - { - (*insttable_1byte[0][op])(); - continue; - } - } -#else - - (*insttable_1byte[0][op])(); - continue; -#endif - } - break; - } - if (prefix == MAX_PREFIX) { - EXCEPTION(UD_EXCEPTION, 0); - } - -#if defined(IA32_INSTRUCTION_TRACE) - if (op == 0x0f) { - BYTE op2; - op2 = cpu_codefetch(CPU_EIP); - ctx[ctx_index].op[prefix + 1] = op2; - ctx[ctx_index].opbytes++; - } - ctx_index = (ctx_index + 1) % NELEMENTS(ctx); -#endif - - /* normal / rep, but not use */ -#if defined(USE_CPU_INLINEINST) - if (CPU_INST_OP32) - { - // インライン命令群 関数テーブルよりも呼び出しが高速だが、多く置きすぎるとifが増えて逆に遅くなる。なので呼び出し頻度が高い物を優先して配置 - if (op == 0x8b) - { - UINT32* out; - UINT32 op2, src; - - PREPART_REG32_EA(op2, src, out, 2, 5); - *out = src; - continue; - } - else if (op == 0x0f) - { - UINT8 repuse = CPU_INST_REPUSE; - - GET_MODRM_PCBYTE(op); -#ifdef USE_SSE - if (insttable_2byte660F_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32) - { - (*insttable_2byte660F_32[op])(); - } - else if (insttable_2byteF20F_32[op] && repuse == 0xf2) - { - (*insttable_2byteF20F_32[op])(); - } - else if (insttable_2byteF30F_32[op] && repuse == 0xf3) - { - (*insttable_2byteF30F_32[op])(); - } - else - { - (*insttable_2byte[1][op])(); - } -#else - (*insttable_2byte[1][op])(); -#endif - continue; - } - else if (op == 0x74) - { - if (CC_NZ) - { - JMPNOP(2, 1); - } - else - { - JMPSHORT(7); - } - continue; - } - } -#endif - if (!(insttable_info[op] & INST_STRING) || !CPU_INST_REPUSE) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - (*insttable_1byte[CPU_INST_OP32][op])(); - continue; - } - - /* rep */ - CPU_WORKCLOCK(5); -#if defined(DEBUG) - if (!cpu_debug_rep_cont) { - cpu_debug_rep_cont = 1; - cpu_debug_rep_regs = CPU_STATSAVE.cpu_regs; - } -#endif - func = insttable_1byte[CPU_INST_OP32][op]; - if (!CPU_INST_AS32) { - if (CPU_CX != 0) { - if(CPU_CX==1){ - (*func)(); - --CPU_CX; - }else{ - if (!(insttable_info[op] & REP_CHECKZF)) { - if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ - (*insttable_1byte_repfunc[CPU_INST_OP32][op])(0); - }else{ - /* rep */ - for (;;) { - (*func)(); - if (--CPU_CX == 0) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } - } else if (CPU_INST_REPUSE != 0xf2) { - if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ - (*insttable_1byte_repfunc[CPU_INST_OP32][op])(1); - }else{ - /* repe */ - for (;;) { - (*func)(); - if (--CPU_CX == 0 || CC_NZ) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } - } else { - if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ - (*insttable_1byte_repfunc[CPU_INST_OP32][op])(2); - }else{ - /* repne */ - for (;;) { - (*func)(); - if (--CPU_CX == 0 || CC_Z) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } - } - } - } - } else { - if (CPU_ECX != 0) { - if(CPU_ECX==1){ - (*func)(); - --CPU_ECX; - }else{ - if (!(insttable_info[op] & REP_CHECKZF)) { - if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ - (*insttable_1byte_repfunc[CPU_INST_OP32][op])(0); - }else{ - /* rep */ - for (;;) { - (*func)(); - if (--CPU_ECX == 0) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } - } else if (CPU_INST_REPUSE != 0xf2) { - if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ - (*insttable_1byte_repfunc[CPU_INST_OP32][op])(1); - }else{ - /* repe */ - for (;;) { - (*func)(); - if (--CPU_ECX == 0 || CC_NZ) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } - } else { - if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ - (*insttable_1byte_repfunc[CPU_INST_OP32][op])(2); - }else{ - /* repne */ - for (;;) { - (*func)(); - if (--CPU_ECX == 0 || CC_Z) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } - } - } - } - } - } while (CPU_REMCLOCK > 0); -} +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "cpu.h" +#include "ia32.mcr" + +#include "inst_table.h" + +#if defined(ENABLE_TRAP) +#include "trap/steptrap.h" +#endif + +#if defined(SUPPORT_ASYNC_CPU) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_SMPU98) +#include +#endif +#endif + +sigjmp_buf exec_1step_jmpbuf; + +#if defined(IA32_INSTRUCTION_TRACE) +typedef struct { + CPU_REGS regs; + disasm_context_t disasm; + + BYTE op[MAX_PREFIX + 2]; + int opbytes; +} ia32_context_t; + +#define NCTX 1024 + +ia32_context_t ctx[NCTX]; +int ctx_index = 0; + +int cpu_inst_trace = 0; +#endif + +#if defined(DEBUG) +int cpu_debug_rep_cont = 0; +CPU_REGS cpu_debug_rep_regs; +#endif + +void +exec_1step(void) +{ + int prefix; + UINT32 op; + + CPU_PREV_EIP = CPU_EIP; + CPU_STATSAVE.cpu_inst = CPU_STATSAVE.cpu_inst_default; + +#if defined(ENABLE_TRAP) + steptrap(CPU_CS, CPU_EIP); +#endif + +#if defined(IA32_INSTRUCTION_TRACE) + ctx[ctx_index].regs = CPU_STATSAVE.cpu_regs; + if (cpu_inst_trace) { + disasm_context_t *d = &ctx[ctx_index].disasm; + UINT32 eip = CPU_EIP; + int rv; + + rv = disasm(&eip, d); + if (rv == 0) { + char buf[256]; + char tmp[32]; + int len = d->nopbytes > 8 ? 8 : d->nopbytes; + int i; + + buf[0] = '\0'; + for (i = 0; i < len; i++) { + snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); + milstr_ncat(buf, tmp, sizeof(buf)); + } + for (; i < 8; i++) { + milstr_ncat(buf, " ", sizeof(buf)); + } + VERBOSE(("%04x:%08x: %s%s", CPU_CS, CPU_EIP, buf, d->str)); + + buf[0] = '\0'; + for (; i < d->nopbytes; i++) { + snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); + milstr_ncat(buf, tmp, sizeof(buf)); + if ((i % 8) == 7) { + VERBOSE((" : %s", buf)); + buf[0] = '\0'; + } + } + if ((i % 8) != 0) { + VERBOSE((" : %s", buf)); + } + } + } + ctx[ctx_index].opbytes = 0; +#endif + + for (prefix = 0; prefix < MAX_PREFIX; prefix++) { + GET_PCBYTE(op); +#if defined(IA32_INSTRUCTION_TRACE) + ctx[ctx_index].op[prefix] = op; + ctx[ctx_index].opbytes++; +#endif + + /* prefix */ + if (insttable_info[op] & INST_PREFIX) { + (*insttable_1byte[0][op])(); + continue; + } + break; + } + if (prefix == MAX_PREFIX) { + EXCEPTION(UD_EXCEPTION, 0); + } + +#if defined(IA32_INSTRUCTION_TRACE) + if (op == 0x0f) { + BYTE op2; + op2 = cpu_codefetch(CPU_EIP); + ctx[ctx_index].op[prefix + 1] = op2; + ctx[ctx_index].opbytes++; + } + ctx_index = (ctx_index + 1) % NELEMENTS(ctx); +#endif + + /* normal / rep, but not use */ + if (!(insttable_info[op] & INST_STRING) || !CPU_INST_REPUSE) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + (*insttable_1byte[CPU_INST_OP32][op])(); + return; + } + + /* rep */ + CPU_WORKCLOCK(5); +#if defined(DEBUG) + if (!cpu_debug_rep_cont) { + cpu_debug_rep_cont = 1; + cpu_debug_rep_regs = CPU_STATSAVE.cpu_regs; + } +#endif + if (!CPU_INST_AS32) { + if (CPU_CX != 0) { + if (!(insttable_info[op] & REP_CHECKZF)) { + /* rep */ + for (;;) { + (*insttable_1byte[CPU_INST_OP32][op])(); + if (--CPU_CX == 0) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } else if (CPU_INST_REPUSE != 0xf2) { + /* repe */ + for (;;) { + (*insttable_1byte[CPU_INST_OP32][op])(); + if (--CPU_CX == 0 || CC_NZ) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } else { + /* repne */ + for (;;) { + (*insttable_1byte[CPU_INST_OP32][op])(); + if (--CPU_CX == 0 || CC_Z) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } + } + } else { + if (CPU_ECX != 0) { + if (!(insttable_info[op] & REP_CHECKZF)) { + /* rep */ + for (;;) { + (*insttable_1byte[CPU_INST_OP32][op])(); + if (--CPU_ECX == 0) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } else if (CPU_INST_REPUSE != 0xf2) { + /* repe */ + for (;;) { + (*insttable_1byte[CPU_INST_OP32][op])(); + if (--CPU_ECX == 0 || CC_NZ) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } else { + /* repne */ + for (;;) { + (*insttable_1byte[CPU_INST_OP32][op])(); + if (--CPU_ECX == 0 || CC_Z) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } + } + } +} + +void +exec_allstep(void) +{ + int prefix; + UINT32 op; + void (*func)(void); + + do { + + CPU_PREV_EIP = CPU_EIP; + CPU_STATSAVE.cpu_inst = CPU_STATSAVE.cpu_inst_default; + +#if defined(ENABLE_TRAP) + steptrap(CPU_CS, CPU_EIP); +#endif + +#if defined(IA32_INSTRUCTION_TRACE) + ctx[ctx_index].regs = CPU_STATSAVE.cpu_regs; + if (cpu_inst_trace) { + disasm_context_t *d = &ctx[ctx_index].disasm; + UINT32 eip = CPU_EIP; + int rv; + + rv = disasm(&eip, d); + if (rv == 0) { + char buf[256]; + char tmp[32]; + int len = d->nopbytes > 8 ? 8 : d->nopbytes; + int i; + + buf[0] = '\0'; + for (i = 0; i < len; i++) { + snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); + milstr_ncat(buf, tmp, sizeof(buf)); + } + for (; i < 8; i++) { + milstr_ncat(buf, " ", sizeof(buf)); + } + VERBOSE(("%04x:%08x: %s%s", CPU_CS, CPU_EIP, buf, d->str)); + + buf[0] = '\0'; + for (; i < d->nopbytes; i++) { + snprintf(tmp, sizeof(tmp), "%02x ", d->opbyte[i]); + milstr_ncat(buf, tmp, sizeof(buf)); + if ((i % 8) == 7) { + VERBOSE((" : %s", buf)); + buf[0] = '\0'; + } + } + if ((i % 8) != 0) { + VERBOSE((" : %s", buf)); + } + } + } + ctx[ctx_index].opbytes = 0; +#endif + + for (prefix = 0; prefix < MAX_PREFIX; prefix++) + { +#if defined(USE_CPU_MODRMPREFETCH) + if ((CPU_EIP + 1) & CPU_PAGE_MASK) + { + op = cpu_opcodefetch(CPU_EIP); +#if defined(USE_CPU_EIPMASK) + CPU_EIP = (CPU_EIP + 1) & CPU_EIPMASK; +#else + if (CPU_STATSAVE.cpu_inst_default.op_32) + { + CPU_EIP = (CPU_EIP + 1); + } + else + { + CPU_EIP = (CPU_EIP + 1) & 0xffff; + } +#endif + } + else +#endif + { + GET_PCBYTE(op); + } +#if defined(IA32_INSTRUCTION_TRACE) + ctx[ctx_index].op[prefix] = op; + ctx[ctx_index].opbytes++; +#endif + + /* prefix */ + if (insttable_info[op] & INST_PREFIX) + { +#if defined(USE_CPU_INLINEINST) + // インライン命令群 関数テーブルよりも呼び出しが高速だが、多く置きすぎるとifが増えて逆に遅くなる。なので呼び出し頻度が高い物を優先して配置 + if (!(op & 0x26)) { + (*insttable_1byte[0][op])(); + continue; + } + else { + if (op == 0x66) + { + CPU_INST_OP32 = !CPU_STATSAVE.cpu_inst_default.op_32; + continue; + } + else if (op == 0x26) + { + CPU_INST_SEGUSE = 1; + CPU_INST_SEGREG_INDEX = CPU_ES_INDEX; + continue; + } + else if (op == 0x67) + { + CPU_INST_AS32 = !CPU_STATSAVE.cpu_inst_default.as_32; + continue; + } + else if (op == 0x2E) + { + CPU_INST_SEGUSE = 1; + CPU_INST_SEGREG_INDEX = CPU_CS_INDEX; + continue; + } + //else if (op == 0xF3) + //{ + // CPU_INST_REPUSE = 0xf3; + // continue; + //} + else + { + (*insttable_1byte[0][op])(); + continue; + } + } +#else + + (*insttable_1byte[0][op])(); + continue; +#endif + } + break; + } + if (prefix == MAX_PREFIX) { + EXCEPTION(UD_EXCEPTION, 0); + } + +#if defined(IA32_INSTRUCTION_TRACE) + if (op == 0x0f) { + BYTE op2; + op2 = cpu_codefetch(CPU_EIP); + ctx[ctx_index].op[prefix + 1] = op2; + ctx[ctx_index].opbytes++; + } + ctx_index = (ctx_index + 1) % NELEMENTS(ctx); +#endif + + /* normal / rep, but not use */ +#if defined(USE_CPU_INLINEINST) + if (CPU_INST_OP32) + { + // インライン命令群 関数テーブルよりも呼び出しが高速だが、多く置きすぎるとifが増えて逆に遅くなる。なので呼び出し頻度が高い物を優先して配置 + if (op == 0x8b) + { + UINT32* out; + UINT32 op2, src; + + PREPART_REG32_EA(op2, src, out, 2, 5); + *out = src; + continue; + } + else if (op == 0x0f) + { + UINT8 repuse = CPU_INST_REPUSE; + + GET_MODRM_PCBYTE(op); +#ifdef USE_SSE + if (insttable_2byte660F_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32) + { + (*insttable_2byte660F_32[op])(); + } + else if (insttable_2byteF20F_32[op] && repuse == 0xf2) + { + (*insttable_2byteF20F_32[op])(); + } + else if (insttable_2byteF30F_32[op] && repuse == 0xf3) + { + (*insttable_2byteF30F_32[op])(); + } + else + { + (*insttable_2byte[1][op])(); + } +#else + (*insttable_2byte[1][op])(); +#endif + continue; + } + else if (op == 0x74) + { + if (CC_NZ) + { + JMPNOP(2, 1); + } + else + { + JMPSHORT(7); + } + continue; + } + } +#endif + if (!(insttable_info[op] & INST_STRING) || !CPU_INST_REPUSE) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + (*insttable_1byte[CPU_INST_OP32][op])(); + continue; + } + + /* rep */ + CPU_WORKCLOCK(5); +#if defined(DEBUG) + if (!cpu_debug_rep_cont) { + cpu_debug_rep_cont = 1; + cpu_debug_rep_regs = CPU_STATSAVE.cpu_regs; + } +#endif + func = insttable_1byte[CPU_INST_OP32][op]; + if (!CPU_INST_AS32) { + if (CPU_CX != 0) { + if(CPU_CX==1){ + (*func)(); + --CPU_CX; + }else{ + if (!(insttable_info[op] & REP_CHECKZF)) { + if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ + (*insttable_1byte_repfunc[CPU_INST_OP32][op])(0); + }else{ + /* rep */ + for (;;) { + (*func)(); + if (--CPU_CX == 0) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } + } else if (CPU_INST_REPUSE != 0xf2) { + if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ + (*insttable_1byte_repfunc[CPU_INST_OP32][op])(1); + }else{ + /* repe */ + for (;;) { + (*func)(); + if (--CPU_CX == 0 || CC_NZ) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } + } else { + if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ + (*insttable_1byte_repfunc[CPU_INST_OP32][op])(2); + }else{ + /* repne */ + for (;;) { + (*func)(); + if (--CPU_CX == 0 || CC_Z) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } + } + } + } + } else { + if (CPU_ECX != 0) { + if(CPU_ECX==1){ + (*func)(); + --CPU_ECX; + }else{ + if (!(insttable_info[op] & REP_CHECKZF)) { + if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ + (*insttable_1byte_repfunc[CPU_INST_OP32][op])(0); + }else{ + /* rep */ + for (;;) { + (*func)(); + if (--CPU_ECX == 0) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } + } else if (CPU_INST_REPUSE != 0xf2) { + if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ + (*insttable_1byte_repfunc[CPU_INST_OP32][op])(1); + }else{ + /* repe */ + for (;;) { + (*func)(); + if (--CPU_ECX == 0 || CC_NZ) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } + } else { + if(insttable_1byte_repfunc[CPU_INST_OP32][op]){ + (*insttable_1byte_repfunc[CPU_INST_OP32][op])(2); + }else{ + /* repne */ + for (;;) { + (*func)(); + if (--CPU_ECX == 0 || CC_Z) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } + } + } + } + } + } while (CPU_REMCLOCK > 0); +} diff --git a/i386c/ia32/cpu.h b/i386c/ia32/cpu.h old mode 100755 new mode 100644 index 0e9d0b4a..0a2e3742 --- a/i386c/ia32/cpu.h +++ b/i386c/ia32/cpu.h @@ -1,1480 +1,1480 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -/* - Intel Architecture 32-bit Processor Interpreter Engine for Pentium - - Copyright by Yui/Studio Milmake 1999-2000 - Copyright by Norio HATTORI 2000,2001 - Copyright by NONAKA Kimihiro 2002-2004 -*/ - -#ifndef IA32_CPU_CPU_H__ -#define IA32_CPU_CPU_H__ - -#include "interface.h" -#if defined(SUPPORT_FPU_SOFTFLOAT) && !defined(SUPPORT_FPU_SOFTFLOAT3) -#include "instructions/fpu/softfloat/softfloat.h" -#endif -#if defined(SUPPORT_FPU_SOFTFLOAT3) -#include "instructions/fpu/softfloat3/softfloat.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef union { -#if defined(BYTESEX_LITTLE) - struct { - UINT8 l; - UINT8 h; - UINT8 _hl; - UINT8 _hh; - } b; - struct { - UINT16 w; - UINT16 _hw; - } w; -#elif defined(BYTESEX_BIG) - struct { - UINT8 _hh; - UINT8 _hl; - UINT8 h; - UINT8 l; - } b; - struct { - UINT16 _hw; - UINT16 w; - } w; -#endif - UINT32 d; -} REG32; - -typedef union { - UINT8 b[10]; - UINT16 w[5]; - struct { - UINT32 l[2]; - UINT16 h; - } d; -} REG80; - -#ifdef __cplusplus -} -#endif - -#include "segments.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - CPU_EAX_INDEX = 0, - CPU_ECX_INDEX = 1, - CPU_EDX_INDEX = 2, - CPU_EBX_INDEX = 3, - CPU_ESP_INDEX = 4, - CPU_EBP_INDEX = 5, - CPU_ESI_INDEX = 6, - CPU_EDI_INDEX = 7, - CPU_REG_NUM -}; - -enum { - CPU_ES_INDEX = 0, - CPU_CS_INDEX = 1, - CPU_SS_INDEX = 2, - CPU_DS_INDEX = 3, - CPU_SEGREG286_NUM = 4, - CPU_FS_INDEX = 4, - CPU_GS_INDEX = 5, - CPU_SEGREG_NUM -}; - -enum { - CPU_TEST_REG_NUM = 8 -}; - -enum { - CPU_DEBUG_REG_NUM = 8, - CPU_DEBUG_REG_INDEX_NUM = 4 -}; - -enum { - MAX_PREFIX = 8 -}; - -typedef struct { - REG32 reg[CPU_REG_NUM]; - UINT16 sreg[CPU_SEGREG_NUM]; - - REG32 eflags; - REG32 eip; - - REG32 prev_eip; - REG32 prev_esp; - - UINT32 tr[CPU_TEST_REG_NUM]; - UINT32 dr[CPU_DEBUG_REG_NUM]; -} CPU_REGS; - -typedef struct { - UINT16 gdtr_limit; - UINT16 pad0; - UINT32 gdtr_base; - UINT16 idtr_limit; - UINT16 pad1; - UINT32 idtr_base; - - UINT16 ldtr; - UINT16 tr; - - UINT32 cr0; - UINT32 cr1; - UINT32 cr2; - UINT32 cr3; - UINT32 cr4; - UINT32 mxcsr; -} CPU_SYSREGS; - -typedef struct { - descriptor_t sreg[CPU_SEGREG_NUM]; - descriptor_t ldtr; - descriptor_t tr; - - UINT32 adrsmask; - UINT32 ovflag; - - UINT8 ss_32; - UINT8 resetreq; - UINT8 trap; - - UINT8 page_wp; - - UINT8 protected_mode; - UINT8 paging; - UINT8 vm86; - UINT8 user_mode; - - UINT8 hlt; - UINT8 bp; /* break point bitmap */ - UINT8 bp_ev; /* break point event */ - - UINT8 backout_sp; /* backout ESP, when exception */ - - UINT32 pde_base; - - UINT32 ioaddr; /* I/O bitmap linear address */ - UINT16 iolimit; /* I/O bitmap count */ - - UINT8 nerror; /* double fault/ triple fault */ - UINT8 prev_exception; -} CPU_STAT; - -typedef struct { - UINT8 op_32; - UINT8 as_32; - UINT8 rep_used; - UINT8 seg_used; - UINT32 seg_base; -} CPU_INST; - -/* FPU */ -enum { - FPU_REG_NUM = 8, - XMM_REG_NUM = 8 -}; - -typedef struct { - UINT16 seg; - UINT16 pad; - UINT32 offset; -} FPU_PTR; - -typedef struct { - UINT16 control; // 制御レジスター - UINT16 status; // ステータスレジスター - UINT16 op; // オペコードレジスター - UINT16 tag; // タグワードレジスター - - FPU_PTR inst; // ラスト命令ポインタレジスター - FPU_PTR data; // ラストデータポインタレジスター -} FPU_REGS_S; - -#if 0 - -typedef struct { - UINT8 valid; - UINT8 sign; - UINT8 zero; - UINT8 inf; - UINT8 nan; - UINT8 denorm; - SINT16 exp; - UINT64 num; -} FP_REG; - -typedef struct { - UINT8 top; - UINT8 pc; - UINT8 rc; - UINT8 dmy[1]; - - FP_REG reg[FPU_REG_NUM]; // R0 to R7 -} FPU_STAT; - -#else - -typedef enum { - TAG_Valid = 0, - TAG_Zero = 1, - TAG_Weird = 2, - TAG_Empty = 3 -} FP_TAG; - -typedef enum { - ROUND_Nearest = 0, - ROUND_Down = 1, - ROUND_Up = 2, - ROUND_Chop = 3 -} FP_RND; - -typedef union { -#if defined(SUPPORT_FPU_SOFTFLOAT) && !defined(SUPPORT_FPU_SOFTFLOAT3) - floatx80 d; -#endif -#if defined(SUPPORT_FPU_SOFTFLOAT3) - sw_extFloat80_t d; -#endif - double d64; - struct { - UINT32 lower; - SINT32 upper; - SINT16 ext; - } l; - struct { - UINT32 lower; - UINT32 upper; - SINT16 ext; - } ul; - SINT64 ll; - UINT8 b[10]; -} FP_REG; - -typedef union { - struct { - UINT32 m1; - UINT32 m2; - UINT16 m3; - } ul32; - struct { - UINT32 m1; - UINT32 m2; - SINT16 m3; - } l32; - struct { - UINT64 m12; - UINT16 m3; - } ul64; - struct { - UINT64 m12; - SINT16 m3; - } l64; -} FP_INT_REG; - -typedef union { - float f[4]; - double d[2]; - UINT8 ul8[16]; - UINT16 ul16[8]; - UINT32 ul32[4]; - UINT64 ul64[2]; -} XMM_REG; - -typedef struct { - UINT8 top; - UINT8 pc; - UINT8 rc; - UINT8 dmy[1]; - - FP_REG reg[FPU_REG_NUM+1]; // R0 to R7 + α - FP_TAG tag[FPU_REG_NUM+1]; // R0 to R7 + α - FP_RND round; -#if defined(SUPPORT_FPU_DOSBOX2) // XXX: 整数間だけ正確にするため用 - FP_INT_REG int_reg[FPU_REG_NUM+1]; - UINT8 int_regvalid[FPU_REG_NUM+1]; -#elif defined(SUPPORT_FPU_DOSBOX2_COMPATIBLE) // XXX: 互換維持用 未使用 - FP_INT_REG reserved_fpu1[FPU_REG_NUM + 1]; - UINT8 reserved_fpu2[FPU_REG_NUM + 1]; -#endif -#ifdef USE_SSE - XMM_REG xmm_reg[XMM_REG_NUM+1]; // xmm0 to xmm7 -#endif -#ifdef USE_MMX - UINT8 mmxenable; -#endif -} FPU_STAT_S; - -#endif - -typedef struct { - CPU_REGS cpu_regs; - CPU_SYSREGS cpu_sysregs; - CPU_STAT cpu_stat; - CPU_INST cpu_inst; - CPU_INST cpu_inst_default; - -#if defined(USE_FPU) - FPU_REGS_S fpu_regs; - FPU_STAT_S fpu_stat; -#endif - - /* protected by cpu shut */ - UINT8 cpu_type; - UINT8 itfbank; - UINT16 ram_d0; - SINT32 remainclock; - SINT32 baseclock; - UINT32 clock; - -#if defined(USE_TSC) - UINT64 cpu_tsc; -#endif -} I386STAT; - -typedef struct { - UINT8 *ext; - UINT32 extsize; - UINT8 *extbase; /* = ext - 0x100000 */ - UINT32 extlimit16mb; /* = extsize + 0x100000 (MAX:16MB) */ - UINT32 extlimit4gb; /* = extsize + 0x100000 */ - UINT32 inport; - UINT8 *ems[4]; -} I386EXT; - -typedef struct { - I386STAT s; /* STATsave'ed */ - I386EXT e; -} I386CORE; - -#define I386CPUID_VERSION 1 -typedef struct { - UINT32 version; // CPUIDバージョン(ステートセーブ互換性を維持するため用)I386CPUID_VERSIONが最新 - char cpu_vendor[16]; // ベンダー(12byte) - UINT32 cpu_family; // ファミリ - UINT32 cpu_model; // モデル - UINT32 cpu_stepping; // ステッピング - UINT32 cpu_feature; // 機能フラグ - UINT32 cpu_feature_ex; // 拡張機能フラグ - char cpu_brandstring[64]; // ブランド名(48byte) - UINT32 cpu_brandid; // ブランドID - UINT32 cpu_feature_ecx; // ECX機能フラグ - UINT32 cpu_eflags_mask; // EFLAGSマスク(1のところがマスク状態) - - UINT8 allow_movCS; // mov cs,xxを許可する - UINT8 reserved8[3]; // 将来の拡張のためにとりあえず - UINT32 cpu_feature_ex_ecx; // ECX拡張機能フラグ - UINT32 reserved[29]; // 将来の拡張のためにとりあえず32bit*29個用意しておく - - UINT8 fpu_type; // FPU種類 -} I386CPUID; - -#define I386MSR_VERSION 1 -typedef struct { - UINT64 ia32_sysenter_cs; // SYSENTER CSレジスタ - UINT64 ia32_sysenter_esp; // SYSENTER ESPレジスタ - UINT64 ia32_sysenter_eip; // SYSENTER EIPレジスタ -} I386MSR_REG; -typedef struct { - UINT32 version; // MSRバージョン(ステートセーブ互換性を維持するため用)I386MSR_VERSIONが最新 - union{ - UINT64 regs[32]; // 将来の拡張のためにとりあえず64bit*32個用意しておく - I386MSR_REG reg; - }; -} I386MSR; - -extern I386CORE i386core; -extern I386CPUID i386cpuid; -extern I386MSR i386msr; - -#if defined(USE_CPU_MODRMPREFETCH) -extern UINT32 opCache; -#endif - -#define CPU_STATSAVE i386core.s - -#define CPU_ADRSMASK i386core.s.cpu_stat.adrsmask -#define CPU_RESETREQ i386core.s.cpu_stat.resetreq - -#define CPU_REMCLOCK i386core.s.remainclock -#define CPU_BASECLOCK i386core.s.baseclock -#define CPU_CLOCK i386core.s.clock -#define CPU_ITFBANK i386core.s.itfbank -#define CPU_RAM_D000 i386core.s.ram_d0 - -#define CPU_TYPE i386core.s.cpu_type -#define CPUTYPE_V30 0x01 - -#define CPU_EXTMEM i386core.e.ext -#define CPU_EXTMEMSIZE i386core.e.extsize -#define CPU_EXTMEMBASE i386core.e.extbase -#define CPU_EXTLIMIT16 i386core.e.extlimit16mb -#define CPU_EXTLIMIT i386core.e.extlimit4gb -#define CPU_INPADRS i386core.e.inport -#define CPU_EMSPTR i386core.e.ems - -extern sigjmp_buf exec_1step_jmpbuf; - -/* - * CPUID - */ -/*** vendor ***/ -#define CPU_VENDOR_INTEL "GenuineIntel" -#define CPU_VENDOR_AMD "AuthenticAMD" -#define CPU_VENDOR_AMD2 "AMDisbetter!" -#define CPU_VENDOR_CYRIX "CyrixInstead" -#define CPU_VENDOR_NEXGEN "NexGenDriven" -#define CPU_VENDOR_CENTAUR "CentaurHauls" -#define CPU_VENDOR_TRANSMETA "GenuineTMx86" -#define CPU_VENDOR_TRANSMETA2 "TransmetaCPU" -#define CPU_VENDOR_NSC "Geode by NSC" -#define CPU_VENDOR_RISE "RiseRiseRise" -#define CPU_VENDOR_UMC "UMC UMC UMC " -#define CPU_VENDOR_SIS "SiS SiS SiS " -#define CPU_VENDOR_VIA "VIA VIA VIA " -#define CPU_VENDOR_NEKOPRO "Neko Project" - -// デフォルト設定 -#define CPU_VENDOR CPU_VENDOR_INTEL - -/*** version ***/ -#define CPU_CORE_I_FAMILY 6 -#define CPU_CORE_I_MODEL 37 /* Core i5 Nehalem */ // 25 -#define CPU_CORE_I_STEPPING 5 - -#define CPU_CORE_2_DUOW_FAMILY 6 -#define CPU_CORE_2_DUOW_MODEL 23 /* Core 2 Duo Wolfdale */ // 17 -#define CPU_CORE_2_DUOW_STEPPING 6 - -#define CPU_CORE_2_DUO_FAMILY 6 -#define CPU_CORE_2_DUO_MODEL 15 /* Core 2 Duo Conroe */ // 15 -#define CPU_CORE_2_DUO_STEPPING 13 - -#define CPU_PENTIUM_4_FAMILY 15 -#define CPU_PENTIUM_4_MODEL 2 /* Pentium 4 */ -#define CPU_PENTIUM_4_STEPPING 4 - -#define CPU_PENTIUM_M_FAMILY 6 -#define CPU_PENTIUM_M_MODEL 9 /* Pentium M */ -#define CPU_PENTIUM_M_STEPPING 5 - -#define CPU_PENTIUM_III_FAMILY 6 -#define CPU_PENTIUM_III_MODEL 7 /* Pentium III */ -#define CPU_PENTIUM_III_STEPPING 2 - -#define CPU_PENTIUM_II_FAMILY 6 -#define CPU_PENTIUM_II_MODEL 3 /* Pentium II */ -#define CPU_PENTIUM_II_STEPPING 3 - -#define CPU_PENTIUM_PRO_FAMILY 6 -#define CPU_PENTIUM_PRO_MODEL 1 /* Pentium Pro */ -#define CPU_PENTIUM_PRO_STEPPING 1 - -#define CPU_MMX_PENTIUM_FAMILY 5 -#define CPU_MMX_PENTIUM_MODEL 4 /* MMX Pentium */ -#define CPU_MMX_PENTIUM_STEPPING 4 - -#define CPU_PENTIUM_FAMILY 5 -#define CPU_PENTIUM_MODEL 2 /* Pentium */ -#define CPU_PENTIUM_STEPPING 5 - -#define CPU_I486DX_FAMILY 4 -#define CPU_I486DX_MODEL 1 /* 486DX */ -#define CPU_I486DX_STEPPING 3 - -#define CPU_I486SX_FAMILY 4 -#define CPU_I486SX_MODEL 2 /* 486SX */ -#define CPU_I486SX_STEPPING 3 - -#define CPU_80386_FAMILY 3 -#define CPU_80386_MODEL 0 /* 80386 */ -#define CPU_80386_STEPPING 8 - -#define CPU_80286_FAMILY 2 -#define CPU_80286_MODEL 1 /* 80286 */ -#define CPU_80286_STEPPING 1 - - -#define CPU_AMD_K10_PHENOM_FAMILY 16 -#define CPU_AMD_K10_PHENOM_MODEL 2 /* AMD K10 Phenom */ -#define CPU_AMD_K10_PHENOM_STEPPING 2 - -#define CPU_AMD_K8_ATHLON_64X2_FAMILY 15 -#define CPU_AMD_K8_ATHLON_64X2_MODEL 44 /* AMD K8 Athlon 64 X2 */ -#define CPU_AMD_K8_ATHLON_64X2_STEPPING 2 - -#define CPU_AMD_K8_ATHLON_64_FAMILY 15 -#define CPU_AMD_K8_ATHLON_64_MODEL 4 /* AMD K8 Athlon 64 */ -#define CPU_AMD_K8_ATHLON_64_STEPPING 8 - -#define CPU_AMD_K7_ATHLON_XP_FAMILY 6 -#define CPU_AMD_K7_ATHLON_XP_MODEL 6 /* AMD K7 Athlon XP */ -#define CPU_AMD_K7_ATHLON_XP_STEPPING 2 - -#define CPU_AMD_K7_ATHLON_FAMILY 6 -#define CPU_AMD_K7_ATHLON_MODEL 1 /* AMD K7 Athlon */ -#define CPU_AMD_K7_ATHLON_STEPPING 2 - -#define CPU_AMD_K6_III_FAMILY 5 -#define CPU_AMD_K6_III_MODEL 9 /* AMD K6-III */ -#define CPU_AMD_K6_III_STEPPING 1 - -#define CPU_AMD_K6_2_FAMILY 5 -#define CPU_AMD_K6_2_MODEL 8 /* AMD K6-2 */ -#define CPU_AMD_K6_2_STEPPING 12 - - -/*** feature ***/ -#define CPU_FEATURE_FPU (1 << 0) -#define CPU_FEATURE_VME (1 << 1) -#define CPU_FEATURE_DE (1 << 2) -#define CPU_FEATURE_PSE (1 << 3) -#define CPU_FEATURE_TSC (1 << 4) -#define CPU_FEATURE_MSR (1 << 5) -#define CPU_FEATURE_PAE (1 << 6) -#define CPU_FEATURE_MCE (1 << 7) -#define CPU_FEATURE_CX8 (1 << 8) -#define CPU_FEATURE_APIC (1 << 9) -/* (1 << 10) */ -#define CPU_FEATURE_SEP (1 << 11) -#define CPU_FEATURE_MTRR (1 << 12) -#define CPU_FEATURE_PGE (1 << 13) -#define CPU_FEATURE_MCA (1 << 14) -#define CPU_FEATURE_CMOV (1 << 15) -#define CPU_FEATURE_FGPAT (1 << 16) -#define CPU_FEATURE_PSE36 (1 << 17) -#define CPU_FEATURE_PN (1 << 18) -#define CPU_FEATURE_CLFSH (1 << 19) -/* (1 << 20) */ -#define CPU_FEATURE_DS (1 << 21) -#define CPU_FEATURE_ACPI (1 << 22) -#define CPU_FEATURE_MMX (1 << 23) -#define CPU_FEATURE_FXSR (1 << 24) -#define CPU_FEATURE_SSE (1 << 25) -#define CPU_FEATURE_SSE2 (1 << 26) -#define CPU_FEATURE_SS (1 << 27) -#define CPU_FEATURE_HTT (1 << 28) -#define CPU_FEATURE_TM (1 << 29) -/* (1 << 30) */ -#define CPU_FEATURE_PBE (1 << 31) - -//#define CPU_FEATURE_XMM CPU_FEATURE_SSE - -#if defined(USE_FPU) -#define CPU_FEATURE_FPU_FLAG CPU_FEATURE_FPU -#else -#define CPU_FEATURE_FPU_FLAG 0 -#endif - -#if defined(USE_TSC) -#define CPU_FEATURE_TSC_FLAG CPU_FEATURE_TSC -#else -#define CPU_FEATURE_TSC_FLAG 0 -#endif - -#if defined(USE_VME) -#define CPU_FEATURE_VME_FLAG CPU_FEATURE_VME -#else -#define CPU_FEATURE_VME_FLAG 0 -#endif - -#if defined(USE_MMX)&&defined(USE_FPU) -#define CPU_FEATURE_MMX_FLAG CPU_FEATURE_MMX|CPU_FEATURE_FXSR -#else -#define CPU_FEATURE_MMX_FLAG 0 -#endif - -#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE) -#define CPU_FEATURE_SSE_FLAG CPU_FEATURE_SSE|CPU_FEATURE_CLFSH -#else -#define CPU_FEATURE_SSE_FLAG 0 -#endif - -#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE)&&defined(USE_SSE2) -#define CPU_FEATURE_SSE2_FLAG CPU_FEATURE_SSE2 -#else -#define CPU_FEATURE_SSE2_FLAG 0 -#endif - -/* 使用できる機能全部 */ -#define CPU_FEATURES_ALL (CPU_FEATURE_FPU_FLAG|CPU_FEATURE_CX8|CPU_FEATURE_TSC_FLAG|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_MMX_FLAG|CPU_FEATURE_SSE_FLAG|CPU_FEATURE_SSE2_FLAG|CPU_FEATURE_SEP) - -#define CPU_FEATURES_CORE_I (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) -#define CPU_FEATURES_CORE_2_DUOW (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) -#define CPU_FEATURES_CORE_2_DUO (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) -#define CPU_FEATURES_PENTIUM_4 (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) -#define CPU_FEATURES_PENTIUM_M (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) -#define CPU_FEATURES_PENTIUM_III (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE) -#define CPU_FEATURES_PENTIUM_II (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX) -#define CPU_FEATURES_PENTIUM_PRO (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR) -#define CPU_FEATURES_MMX_PENTIUM (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_MMX) -#define CPU_FEATURES_PENTIUM (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG) -#define CPU_FEATURES_I486DX (CPU_FEATURE_FPU) -#define CPU_FEATURES_I486SX (0) -#define CPU_FEATURES_80386 (0) -#define CPU_FEATURES_80286 (0) - -#define CPU_FEATURES_AMD_K10_PHENOM (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) -#define CPU_FEATURES_AMD_K8_ATHLON_64X2 (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) -#define CPU_FEATURES_AMD_K8_ATHLON_64 (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) -#define CPU_FEATURES_AMD_K7_ATHLON_XP (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE) -#define CPU_FEATURES_AMD_K7_ATHLON (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_MMX) -#define CPU_FEATURES_AMD_K6_III (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_MMX) -#define CPU_FEATURES_AMD_K6_2 (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_MMX) - -/*** extended feature ***/ -#define CPU_FEATURE_EX_SYSCALL (1 << 11) -#define CPU_FEATURE_EX_XDBIT (1 << 20) -#define CPU_FEATURE_EX_EM64T (1 << 29) -#define CPU_FEATURE_EX_E3DNOW (1 << 30) -#define CPU_FEATURE_EX_3DNOW (1 << 31) - -#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_3DNOW) -#define CPU_FEATURE_EX_3DNOW_FLAG CPU_FEATURE_EX_3DNOW -#else -#define CPU_FEATURE_EX_3DNOW_FLAG 0 -#endif - -#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_3DNOW)&&defined(USE_SSE) -#define CPU_FEATURE_EX_E3DNOW_FLAG CPU_FEATURE_EX_E3DNOW -#else -#define CPU_FEATURE_EX_E3DNOW_FLAG 0 -#endif - -/* 使用できる機能全部 */ -#define CPU_FEATURES_EX_ALL (CPU_FEATURE_EX_3DNOW_FLAG|CPU_FEATURE_EX_E3DNOW_FLAG) - -#define CPU_FEATURES_EX_CORE_I (0) -#define CPU_FEATURES_EX_CORE_2_DUOW (0) -#define CPU_FEATURES_EX_CORE_2_DUO (0) -#define CPU_FEATURES_EX_PENTIUM_4 (0) -#define CPU_FEATURES_EX_PENTIUM_M (0) -#define CPU_FEATURES_EX_PENTIUM_III (0) -#define CPU_FEATURES_EX_PENTIUM_II (0) -#define CPU_FEATURES_EX_PENTIUM_PRO (0) -#define CPU_FEATURES_EX_MMX_PENTIUM (0) -#define CPU_FEATURES_EX_PENTIUM (0) -#define CPU_FEATURES_EX_I486DX (0) -#define CPU_FEATURES_EX_I486SX (0) -#define CPU_FEATURES_EX_80386 (0) -#define CPU_FEATURES_EX_80286 (0) - -#define CPU_FEATURES_EX_AMD_K10_PHENOM (CPU_FEATURE_EX_3DNOW|CPU_FEATURE_EX_E3DNOW) -#define CPU_FEATURES_EX_AMD_K8_ATHLON_64X2 (CPU_FEATURE_EX_3DNOW|CPU_FEATURE_EX_E3DNOW) -#define CPU_FEATURES_EX_AMD_K8_ATHLON_64 (CPU_FEATURE_EX_3DNOW|CPU_FEATURE_EX_E3DNOW) -#define CPU_FEATURES_EX_AMD_K7_ATHLON_XP (CPU_FEATURE_EX_3DNOW|CPU_FEATURE_EX_E3DNOW) -#define CPU_FEATURES_EX_AMD_K7_ATHLON (CPU_FEATURE_EX_3DNOW|CPU_FEATURE_EX_E3DNOW) -#define CPU_FEATURES_EX_AMD_K6_III (CPU_FEATURE_EX_3DNOW) -#define CPU_FEATURES_EX_AMD_K6_2 (CPU_FEATURE_EX_3DNOW) - -/*** extended ECX feature ***/ -#define CPU_FEATURE_EX_ECX_SSE4A (1 << 6) - -#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_3DNOW)&&defined(USE_SSE)&&defined(USE_SSE2)&&defined(USE_SSE3)&&defined(USE_SSE4A) -#define CPU_FEATURE_EX_ECX_SSE4A_FLAG CPU_FEATURE_EX_ECX_SSE4A -#else -#define CPU_FEATURE_EX_ECX_SSE4A_FLAG 0 -#endif - -/* 使用できる機能全部 */ -#define CPU_FEATURES_EX_ECX_ALL (CPU_FEATURE_EX_ECX_SSE4A_FLAG) - -#define CPU_FEATURES_EX_ECX_CORE_I (0) -#define CPU_FEATURES_EX_ECX_CORE_2_DUOW (0) -#define CPU_FEATURES_EX_ECX_CORE_2_DUO (0) -#define CPU_FEATURES_EX_ECX_PENTIUM_4 (0) -#define CPU_FEATURES_EX_ECX_PENTIUM_M (0) -#define CPU_FEATURES_EX_ECX_PENTIUM_III (0) -#define CPU_FEATURES_EX_ECX_PENTIUM_II (0) -#define CPU_FEATURES_EX_ECX_PENTIUM_PRO (0) -#define CPU_FEATURES_EX_ECX_MMX_PENTIUM (0) -#define CPU_FEATURES_EX_ECX_PENTIUM (0) -#define CPU_FEATURES_EX_ECX_I486DX (0) -#define CPU_FEATURES_EX_ECX_I486SX (0) -#define CPU_FEATURES_EX_ECX_80386 (0) -#define CPU_FEATURES_EX_ECX_80286 (0) - -#define CPU_FEATURES_EX_ECX_AMD_K10_PHENOM (CPU_FEATURE_EX_ECX_SSE4A_FLAG) -#define CPU_FEATURES_EX_ECX_AMD_K8_ATHLON_64X2 (0) -#define CPU_FEATURES_EX_ECX_AMD_K8_ATHLON_64 (0) -#define CPU_FEATURES_EX_ECX_AMD_K7_ATHLON_XP (0) -#define CPU_FEATURES_EX_ECX_AMD_K7_ATHLON (0) -#define CPU_FEATURES_EX_ECX_AMD_K6_III (0) -#define CPU_FEATURES_EX_ECX_AMD_K6_2 (0) - -/*** ECX feature ***/ -#define CPU_FEATURE_ECX_SSE3 (1 << 0) -#define CPU_FEATURE_ECX_PCLMULDQ (1 << 1) -#define CPU_FEATURE_ECX_DTES64 (1 << 2) -#define CPU_FEATURE_ECX_MONITOR (1 << 3) -#define CPU_FEATURE_ECX_DSCPL (1 << 4) -#define CPU_FEATURE_ECX_VMX (1 << 5) -#define CPU_FEATURE_ECX_SMX (1 << 6) -#define CPU_FEATURE_ECX_EST (1 << 7) -#define CPU_FEATURE_ECX_TM2 (1 << 8) -#define CPU_FEATURE_ECX_SSSE3 (1 << 9) -#define CPU_FEATURE_ECX_CNXT1D (1 << 10) -/* (1 << 11) */ -/* (1 << 12) */ -#define CPU_FEATURE_ECX_CX16 (1 << 13) -#define CPU_FEATURE_ECX_xTPR (1 << 14) -#define CPU_FEATURE_ECX_PDCM (1 << 15) -/* (1 << 16) */ -/* (1 << 17) */ -#define CPU_FEATURE_ECX_DCA (1 << 18) -#define CPU_FEATURE_ECX_SSE4_1 (1 << 19) -#define CPU_FEATURE_ECX_SSE4_2 (1 << 20) -#define CPU_FEATURE_ECX_x2APIC (1 << 21) -#define CPU_FEATURE_ECX_MOVBE (1 << 22) -#define CPU_FEATURE_ECX_POPCNT (1 << 23) -/* (1 << 24) */ -#define CPU_FEATURE_ECX_AES (1 << 25) -#define CPU_FEATURE_ECX_XSAVE (1 << 26) -#define CPU_FEATURE_ECX_OSXSAVE (1 << 27) -/* (1 << 28) */ -/* (1 << 29) */ -/* (1 << 30) */ -/* (1 << 31) */ - -#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE)&&defined(USE_SSE2)&&defined(USE_SSE3) -#define CPU_FEATURE_ECX_SSE3_FLAG CPU_FEATURE_ECX_SSE3 -#else -#define CPU_FEATURE_ECX_SSE3_FLAG 0 -#endif - -#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE)&&defined(USE_SSE2)&&defined(USE_SSE3)&&defined(USE_SSSE3) -#define CPU_FEATURE_ECX_SSSE3_FLAG CPU_FEATURE_ECX_SSSE3 -#else -#define CPU_FEATURE_ECX_SSSE3_FLAG 0 -#endif - -#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE)&&defined(USE_SSE2)&&defined(USE_SSE3)&&defined(USE_SSSE3)&&defined(USE_SSE4_1) -#define CPU_FEATURE_ECX_SSE4_1_FLAG CPU_FEATURE_ECX_SSE4_1 -#else -#define CPU_FEATURE_ECX_SSE4_1_FLAG 0 -#endif - -#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE)&&defined(USE_SSE2)&&defined(USE_SSE3)&&defined(USE_SSSE3)&&defined(USE_SSE4_1)&&defined(USE_SSE4_2) -#define CPU_FEATURE_ECX_SSE4_2_FLAG CPU_FEATURE_ECX_SSE4_2 -#define CPU_FEATURE_ECX_POPCNT_FLAG CPU_FEATURE_ECX_POPCNT -#else -#define CPU_FEATURE_ECX_SSE4_2_FLAG 0 -#define CPU_FEATURE_ECX_POPCNT_FLAG 0 -#endif - -/* 使用できる機能全部 */ -#define CPU_FEATURES_ECX_ALL (CPU_FEATURE_ECX_SSE3_FLAG|CPU_FEATURE_ECX_SSSE3_FLAG|CPU_FEATURE_ECX_SSE4_1_FLAG|CPU_FEATURE_ECX_SSE4_2_FLAG|CPU_FEATURE_ECX_POPCNT_FLAG) - -#define CPU_FEATURES_ECX_CORE_I (CPU_FEATURE_ECX_SSE3|CPU_FEATURE_ECX_SSSE3|CPU_FEATURE_ECX_SSE4_1|CPU_FEATURE_ECX_SSE4_2|CPU_FEATURE_ECX_POPCNT) -#define CPU_FEATURES_ECX_CORE_2_DUOW (CPU_FEATURE_ECX_SSE3|CPU_FEATURE_ECX_SSSE3|CPU_FEATURE_ECX_SSE4_1) -#define CPU_FEATURES_ECX_CORE_2_DUO (CPU_FEATURE_ECX_SSE3|CPU_FEATURE_ECX_SSSE3) -#define CPU_FEATURES_ECX_PENTIUM_4 (CPU_FEATURE_ECX_SSE3) -#define CPU_FEATURES_ECX_PENTIUM_M (0) -#define CPU_FEATURES_ECX_PENTIUM_III (0) -#define CPU_FEATURES_ECX_PENTIUM_II (0) -#define CPU_FEATURES_ECX_PENTIUM_PRO (0) -#define CPU_FEATURES_ECX_MMX_PENTIUM (0) -#define CPU_FEATURES_ECX_PENTIUM (0) -#define CPU_FEATURES_ECX_I486DX (0) -#define CPU_FEATURES_ECX_I486SX (0) -#define CPU_FEATURES_ECX_80386 (0) -#define CPU_FEATURES_ECX_80286 (0) - -#define CPU_FEATURES_ECX_AMD_K10_PHENOM (CPU_FEATURE_ECX_SSE3|CPU_FEATURE_ECX_POPCNT) -#define CPU_FEATURES_ECX_AMD_K8_ATHLON_64X2 (CPU_FEATURE_ECX_SSE3) -#define CPU_FEATURES_ECX_AMD_K8_ATHLON_64 (0) -#define CPU_FEATURES_ECX_AMD_K7_ATHLON_XP (0) -#define CPU_FEATURES_ECX_AMD_K7_ATHLON (0) -#define CPU_FEATURES_ECX_AMD_K6_III (0) -#define CPU_FEATURES_ECX_AMD_K6_2 (0) - - -/* EFLAGS MASK */ -#define CPU_EFLAGS_MASK_CORE_I (0) -#define CPU_EFLAGS_MASK_CORE_2_DUOW (0) -#define CPU_EFLAGS_MASK_CORE_2_DUO (0) -#define CPU_EFLAGS_MASK_PENTIUM_4 (0) -#define CPU_EFLAGS_MASK_PENTIUM_M (0) -#define CPU_EFLAGS_MASK_PENTIUM_III (0) -#define CPU_EFLAGS_MASK_PENTIUM_II (0) -#define CPU_EFLAGS_MASK_PENTIUM_PRO (0) -#define CPU_EFLAGS_MASK_MMX_PENTIUM (0) -#define CPU_EFLAGS_MASK_PENTIUM (0) -#define CPU_EFLAGS_MASK_I486DX (0) -#define CPU_EFLAGS_MASK_I486SX (0) -#define CPU_EFLAGS_MASK_80386 ((1 << 18)) -#define CPU_EFLAGS_MASK_80286 ((1 << 18)) - -#define CPU_EFLAGS_MASK_AMD_K10_PHENOM (0) -#define CPU_EFLAGS_MASK_AMD_K8_ATHLON_64X2 (0) -#define CPU_EFLAGS_MASK_AMD_K8_ATHLON_64 (0) -#define CPU_EFLAGS_MASK_AMD_K7_ATHLON_XP (0) -#define CPU_EFLAGS_MASK_AMD_K7_ATHLON (0) -#define CPU_EFLAGS_MASK_AMD_K6_III (0) -#define CPU_EFLAGS_MASK_AMD_K6_2 (0) - - -/* brand string */ -#define CPU_BRAND_STRING_CORE_I "Intel(R) Core(TM) i3/5/7 CPU " -#define CPU_BRAND_STRING_CORE_2_DUOW "Intel(R) Core(TM)2 CPU SSE4.1 " -#define CPU_BRAND_STRING_CORE_2_DUO "Intel(R) Core(TM)2 CPU " -#define CPU_BRAND_STRING_PENTIUM_4 "Intel(R) Pentium(R) 4 CPU " -#define CPU_BRAND_STRING_PENTIUM_M "Intel(R) Pentium(R) M processor " -#define CPU_BRAND_STRING_PENTIUM_III "Intel(R) Pentium(R) III CPU " -#define CPU_BRAND_STRING_PENTIUM_II "Intel(R) Pentium(R) II CPU " -#define CPU_BRAND_STRING_PENTIUM_PRO "Intel(R) Pentium(R) Pro CPU " -#define CPU_BRAND_STRING_MMX_PENTIUM "Intel(R) Pentium(R) with MMX " -#define CPU_BRAND_STRING_PENTIUM "Intel(R) Pentium(R) Processor " -#define CPU_BRAND_STRING_I486DX "Intel(R) i486DX Processor " -#define CPU_BRAND_STRING_I486SX "Intel(R) i486SX Processor " -#define CPU_BRAND_STRING_80386 "Intel(R) 80386 Processor " -#define CPU_BRAND_STRING_80286 "Intel(R) 80286 Processor " -#define CPU_BRAND_STRING_AMD_K10_PHENOM "AMD Phenom(tm) Processor " -#define CPU_BRAND_STRING_AMD_K8_ATHLON_64X2 "AMD Athlon(tm) 64 Processor " -#define CPU_BRAND_STRING_AMD_K8_ATHLON_64 "AMD Athlon(tm) 64 Processor " -#define CPU_BRAND_STRING_AMD_K7_ATHLON_XP "AMD Athlon(tm) XP " -#define CPU_BRAND_STRING_AMD_K7_ATHLON "AMD-K7(tm) Processor " -#define CPU_BRAND_STRING_AMD_K6_III "AMD-K6(tm) 3D+ Processor " -#define CPU_BRAND_STRING_AMD_K6_2 "AMD-K6(tm) 3D processor " -#define CPU_BRAND_STRING_NEKOPRO "Neko Processor " // カスタム設定 -#define CPU_BRAND_STRING_NEKOPRO2 "Neko Processor II " // 全機能使用可能 - - -/* brand id */ -#define CPU_BRAND_ID_CORE_I 0 -#define CPU_BRAND_ID_CORE_2_DUOW 0 -#define CPU_BRAND_ID_CORE_2_DUO 0 -#define CPU_BRAND_ID_PENTIUM_4 0x9 -#define CPU_BRAND_ID_PENTIUM_M 0x16 -#define CPU_BRAND_ID_PENTIUM_III 0x2 -#define CPU_BRAND_ID_PENTIUM_II 0 -#define CPU_BRAND_ID_PENTIUM_PRO 0 -#define CPU_BRAND_ID_MMX_PENTIUM 0 -#define CPU_BRAND_ID_PENTIUM 0 -#define CPU_BRAND_ID_I486DX 0 -#define CPU_BRAND_ID_I486SX 0 -#define CPU_BRAND_ID_80386 0 -#define CPU_BRAND_ID_80286 0 -#define CPU_BRAND_ID_AMD_K10_PHENOM 0 -#define CPU_BRAND_ID_AMD_K8_ATHLON_64X2 0 -#define CPU_BRAND_ID_AMD_K8_ATHLON_64 0 -#define CPU_BRAND_ID_AMD_K7_ATHLON_XP 0 -#define CPU_BRAND_ID_AMD_K7_ATHLON 0 -#define CPU_BRAND_ID_AMD_K6_III 0 -#define CPU_BRAND_ID_AMD_K6_2 0 -#define CPU_BRAND_ID_NEKOPRO 0 // カスタム設定 -#define CPU_BRAND_ID_NEKOPRO2 0 // 全機能使用可能 - -#define CPU_BRAND_ID_AUTO 0xffffffff // BrandID自動設定(過去バージョンとの互換維持用) - -// CPUID デフォルト設定 -#if defined(USE_FPU) -#if defined(USE_SSE3) -#define CPU_FAMILY CPU_PENTIUM_III_FAMILY -#define CPU_MODEL CPU_PENTIUM_III_MODEL /* Pentium III */ -#define CPU_STEPPING CPU_PENTIUM_III_STEPPING -#define CPU_FEATURES CPU_FEATURES_PENTIUM_III -#define CPU_FEATURES_EX CPU_FEATURES_EX_PENTIUM_III -#define CPU_FEATURES_ECX CPU_FEATURES_ECX_PENTIUM_III -#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_PENTIUM_III -#define CPU_BRAND_STRING CPU_BRAND_STRING_PENTIUM_III -#define CPU_BRAND_ID CPU_BRAND_ID_PENTIUM_III -#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_PENTIUM_III -#elif defined(USE_SSE2) -#define CPU_FAMILY CPU_PENTIUM_III_FAMILY -#define CPU_MODEL CPU_PENTIUM_III_MODEL /* Pentium III */ -#define CPU_STEPPING CPU_PENTIUM_III_STEPPING -#define CPU_FEATURES CPU_FEATURES_PENTIUM_III -#define CPU_FEATURES_EX CPU_FEATURES_EX_PENTIUM_III -#define CPU_FEATURES_ECX CPU_FEATURES_ECX_PENTIUM_III -#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_PENTIUM_III -#define CPU_BRAND_STRING CPU_BRAND_STRING_PENTIUM_III -#define CPU_BRAND_ID CPU_BRAND_ID_PENTIUM_III -#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_PENTIUM_III -#elif defined(USE_SSE) -#define CPU_FAMILY CPU_PENTIUM_III_FAMILY -#define CPU_MODEL CPU_PENTIUM_III_MODEL /* Pentium III */ -#define CPU_STEPPING CPU_PENTIUM_III_STEPPING -#define CPU_FEATURES CPU_FEATURES_PENTIUM_III -#define CPU_FEATURES_EX CPU_FEATURES_EX_PENTIUM_III -#define CPU_FEATURES_ECX CPU_FEATURES_ECX_PENTIUM_III -#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_PENTIUM_III -#define CPU_BRAND_STRING CPU_BRAND_STRING_PENTIUM_III -#define CPU_BRAND_ID CPU_BRAND_ID_PENTIUM_III -#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_PENTIUM_III -#elif defined(USE_MMX) -#define CPU_FAMILY CPU_PENTIUM_II_FAMILY -#define CPU_MODEL CPU_PENTIUM_II_MODEL /* Pentium II */ -#define CPU_STEPPING CPU_PENTIUM_II_STEPPING -#define CPU_FEATURES CPU_FEATURES_PENTIUM_II -#define CPU_FEATURES_EX CPU_FEATURES_EX_PENTIUM_II -#define CPU_FEATURES_ECX CPU_FEATURES_ECX_PENTIUM_II -#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_PENTIUM_II -#define CPU_BRAND_STRING CPU_BRAND_STRING_PENTIUM_II -#define CPU_BRAND_ID CPU_BRAND_ID_PENTIUM_II -#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_PENTIUM_II -#else -#define CPU_FAMILY CPU_PENTIUM_FAMILY -#define CPU_MODEL CPU_PENTIUM_MODEL /* Pentium */ -#define CPU_STEPPING CPU_PENTIUM_STEPPING -#define CPU_FEATURES CPU_FEATURES_PENTIUM -#define CPU_FEATURES_EX CPU_FEATURES_EX_PENTIUM -#define CPU_FEATURES_ECX CPU_FEATURES_ECX_PENTIUM -#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_PENTIUM -#define CPU_BRAND_STRING CPU_BRAND_STRING_PENTIUM -#define CPU_BRAND_ID CPU_BRAND_ID_PENTIUM -#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_PENTIUM -#endif -#else -#define CPU_FAMILY CPU_I486SX_FAMILY -#define CPU_MODEL CPU_I486SX_MODEL /* 486SX */ -#define CPU_STEPPING CPU_I486SX_STEPPING -#define CPU_FEATURES CPU_FEATURES_I486SX -#define CPU_FEATURES_EX CPU_FEATURES_EX_I486SX -#define CPU_FEATURES_ECX CPU_FEATURES_ECX_I486SX -#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_I486SX -#define CPU_BRAND_STRING CPU_BRAND_STRING_I486SX -#define CPU_BRAND_ID CPU_BRAND_ID_I486SX -#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_I486SX -#endif - - - -#define CPU_REGS_BYTEL(n) CPU_STATSAVE.cpu_regs.reg[(n)].b.l -#define CPU_REGS_BYTEH(n) CPU_STATSAVE.cpu_regs.reg[(n)].b.h -#define CPU_REGS_WORD(n) CPU_STATSAVE.cpu_regs.reg[(n)].w.w -#define CPU_REGS_DWORD(n) CPU_STATSAVE.cpu_regs.reg[(n)].d -#define CPU_REGS_SREG(n) CPU_STATSAVE.cpu_regs.sreg[(n)] - -#if defined(USE_CPU_DIRECTREG) -#define CPU_REG16_B53_V(n) CPU_REGS_WORD(((n) >> 3) & 7) -#define CPU_REG16_B20_V(n) CPU_REGS_WORD((n) & 7) -#define CPU_REG32_B53_V(n) CPU_REGS_DWORD(((n) >> 3) & 7) -#define CPU_REG32_B20_V(n) CPU_REGS_DWORD((n) & 7) - -#define CPU_REG16_B53(n) (&CPU_REG16_B53_V(n)) -#define CPU_REG16_B20(n) (&CPU_REG16_B20_V(n)) -#define CPU_REG32_B53(n) (&CPU_REG32_B53_V(n)) -#define CPU_REG32_B20(n) (&CPU_REG32_B20_V(n)) -#else -#define CPU_REG16_B53_V(n) (*CPU_REG16_B53(n)) -#define CPU_REG16_B20_V(n) (*CPU_REG16_B20(n)) -#define CPU_REG32_B53_V(n) (*CPU_REG32_B53(n)) -#define CPU_REG32_B20_V(n) (*CPU_REG32_B20(n)) - -#define CPU_REG16_B53(n) reg16_b53[n] -#define CPU_REG16_B20(n) reg16_b20[n] -#define CPU_REG32_B53(n) reg32_b53[n] -#define CPU_REG32_B20(n) reg32_b20[n] -#endif - -#define CPU_STAT_SREG(n) CPU_STATSAVE.cpu_stat.sreg[(n)] -#define CPU_STAT_SREGBASE(n) CPU_STAT_SREG((n)).u.seg.segbase -#define CPU_STAT_SREGLIMIT(n) CPU_STAT_SREG((n)).u.seg.limit - - -#define CPU_AL CPU_REGS_BYTEL(CPU_EAX_INDEX) -#define CPU_CL CPU_REGS_BYTEL(CPU_ECX_INDEX) -#define CPU_DL CPU_REGS_BYTEL(CPU_EDX_INDEX) -#define CPU_BL CPU_REGS_BYTEL(CPU_EBX_INDEX) -#define CPU_AH CPU_REGS_BYTEH(CPU_EAX_INDEX) -#define CPU_CH CPU_REGS_BYTEH(CPU_ECX_INDEX) -#define CPU_DH CPU_REGS_BYTEH(CPU_EDX_INDEX) -#define CPU_BH CPU_REGS_BYTEH(CPU_EBX_INDEX) - -#define CPU_AX CPU_REGS_WORD(CPU_EAX_INDEX) -#define CPU_CX CPU_REGS_WORD(CPU_ECX_INDEX) -#define CPU_DX CPU_REGS_WORD(CPU_EDX_INDEX) -#define CPU_BX CPU_REGS_WORD(CPU_EBX_INDEX) -#define CPU_SP CPU_REGS_WORD(CPU_ESP_INDEX) -#define CPU_BP CPU_REGS_WORD(CPU_EBP_INDEX) -#define CPU_SI CPU_REGS_WORD(CPU_ESI_INDEX) -#define CPU_DI CPU_REGS_WORD(CPU_EDI_INDEX) -#define CPU_IP CPU_STATSAVE.cpu_regs.eip.w.w - -#define CPU_EAX CPU_REGS_DWORD(CPU_EAX_INDEX) -#define CPU_ECX CPU_REGS_DWORD(CPU_ECX_INDEX) -#define CPU_EDX CPU_REGS_DWORD(CPU_EDX_INDEX) -#define CPU_EBX CPU_REGS_DWORD(CPU_EBX_INDEX) -#define CPU_ESP CPU_REGS_DWORD(CPU_ESP_INDEX) -#define CPU_EBP CPU_REGS_DWORD(CPU_EBP_INDEX) -#define CPU_ESI CPU_REGS_DWORD(CPU_ESI_INDEX) -#define CPU_EDI CPU_REGS_DWORD(CPU_EDI_INDEX) -#define CPU_EIP CPU_STATSAVE.cpu_regs.eip.d -#if defined(USE_CPU_EIPMASK) -#define CPU_EIPMASK cpu_eipMask -#endif -#define CPU_PREV_EIP CPU_STATSAVE.cpu_regs.prev_eip.d -#define CPU_PREV_ESP CPU_STATSAVE.cpu_regs.prev_esp.d - -#define CPU_ES CPU_REGS_SREG(CPU_ES_INDEX) -#define CPU_CS CPU_REGS_SREG(CPU_CS_INDEX) -#define CPU_SS CPU_REGS_SREG(CPU_SS_INDEX) -#define CPU_DS CPU_REGS_SREG(CPU_DS_INDEX) -#define CPU_FS CPU_REGS_SREG(CPU_FS_INDEX) -#define CPU_GS CPU_REGS_SREG(CPU_GS_INDEX) - -#define CPU_ES_DESC CPU_STAT_SREG(CPU_ES_INDEX) -#define CPU_CS_DESC CPU_STAT_SREG(CPU_CS_INDEX) -#define CPU_SS_DESC CPU_STAT_SREG(CPU_SS_INDEX) -#define CPU_DS_DESC CPU_STAT_SREG(CPU_DS_INDEX) -#define CPU_FS_DESC CPU_STAT_SREG(CPU_FS_INDEX) -#define CPU_GS_DESC CPU_STAT_SREG(CPU_GS_INDEX) - -#define ES_BASE CPU_STAT_SREGBASE(CPU_ES_INDEX) -#define CS_BASE CPU_STAT_SREGBASE(CPU_CS_INDEX) -#define SS_BASE CPU_STAT_SREGBASE(CPU_SS_INDEX) -#define DS_BASE CPU_STAT_SREGBASE(CPU_DS_INDEX) -#define FS_BASE CPU_STAT_SREGBASE(CPU_FS_INDEX) -#define GS_BASE CPU_STAT_SREGBASE(CPU_GS_INDEX) - -#define CPU_EFLAG CPU_STATSAVE.cpu_regs.eflags.d -#define CPU_FLAG CPU_STATSAVE.cpu_regs.eflags.w.w -#define CPU_FLAGL CPU_STATSAVE.cpu_regs.eflags.b.l -#define CPU_FLAGH CPU_STATSAVE.cpu_regs.eflags.b.h -#define CPU_TRAP CPU_STATSAVE.cpu_stat.trap -#define CPU_INPORT CPU_STATSAVE.cpu_stat.inport -#define CPU_OV CPU_STATSAVE.cpu_stat.ovflag - -#define C_FLAG (1 << 0) -#define P_FLAG (1 << 2) -#define A_FLAG (1 << 4) -#define Z_FLAG (1 << 6) -#define S_FLAG (1 << 7) -#define T_FLAG (1 << 8) -#define I_FLAG (1 << 9) -#define D_FLAG (1 << 10) -#define O_FLAG (1 << 11) -#define IOPL_FLAG (3 << 12) -#define NT_FLAG (1 << 14) -#define RF_FLAG (1 << 16) -#define VM_FLAG (1 << 17) -#define AC_FLAG (1 << 18) -#define VIF_FLAG (1 << 19) -#define VIP_FLAG (1 << 20) -#define ID_FLAG (1 << 21) -#define SZP_FLAG (P_FLAG|Z_FLAG|S_FLAG) -#define SZAP_FLAG (P_FLAG|A_FLAG|Z_FLAG|S_FLAG) -#define SZPC_FLAG (C_FLAG|P_FLAG|Z_FLAG|S_FLAG) -#define SZAPC_FLAG (C_FLAG|P_FLAG|A_FLAG|Z_FLAG|S_FLAG) -#define ALL_FLAG (SZAPC_FLAG|T_FLAG|I_FLAG|D_FLAG|O_FLAG|IOPL_FLAG|NT_FLAG) -#define ALL_EFLAG (ALL_FLAG|RF_FLAG|VM_FLAG|AC_FLAG|VIF_FLAG|VIP_FLAG|ID_FLAG) - -#define REAL_FLAGREG ((CPU_FLAG & 0xf7ff) | (CPU_OV ? O_FLAG : 0) | 2) -#define REAL_EFLAGREG ((CPU_EFLAG & 0xfffff7ff) | (CPU_OV ? O_FLAG : 0) | 2) - -void CPUCALL set_flags(UINT16 new_flags, UINT16 mask); -void CPUCALL set_eflags(UINT32 new_flags, UINT32 mask); - - -#define CPU_INST_OP32 CPU_STATSAVE.cpu_inst.op_32 -#define CPU_INST_AS32 CPU_STATSAVE.cpu_inst.as_32 -#define CPU_INST_REPUSE CPU_STATSAVE.cpu_inst.rep_used -#define CPU_INST_SEGUSE CPU_STATSAVE.cpu_inst.seg_used -#define CPU_INST_SEGREG_INDEX CPU_STATSAVE.cpu_inst.seg_base -#define DS_FIX (!CPU_INST_SEGUSE ? CPU_DS_INDEX : CPU_INST_SEGREG_INDEX) -#define SS_FIX (!CPU_INST_SEGUSE ? CPU_SS_INDEX : CPU_INST_SEGREG_INDEX) - -#define CPU_STAT_CS_BASE CPU_STAT_SREGBASE(CPU_CS_INDEX) -#define CPU_STAT_CS_LIMIT CPU_STAT_SREGLIMIT(CPU_CS_INDEX) - -#define CPU_STAT_ADRSMASK CPU_STATSAVE.cpu_stat.adrsmask -#define CPU_STAT_SS32 CPU_STATSAVE.cpu_stat.ss_32 -#define CPU_STAT_RESETREQ CPU_STATSAVE.cpu_stat.resetreq -#define CPU_STAT_PM CPU_STATSAVE.cpu_stat.protected_mode -#define CPU_STAT_PAGING CPU_STATSAVE.cpu_stat.paging -#define CPU_STAT_VM86 CPU_STATSAVE.cpu_stat.vm86 -#define CPU_STAT_WP CPU_STATSAVE.cpu_stat.page_wp -#define CPU_STAT_CPL CPU_CS_DESC.rpl -#define CPU_STAT_USER_MODE CPU_STATSAVE.cpu_stat.user_mode -#define CPU_STAT_PDE_BASE CPU_STATSAVE.cpu_stat.pde_base -#define CPU_SET_PREV_ESP1(esp) \ -do { \ - CPU_STATSAVE.cpu_stat.backout_sp = 1; \ - CPU_PREV_ESP = (esp); \ -} while (/*CONSTCOND*/0) -#define CPU_SET_PREV_ESP() CPU_SET_PREV_ESP1(CPU_ESP) -#define CPU_CLEAR_PREV_ESP() \ -do { \ - CPU_STATSAVE.cpu_stat.backout_sp = 0; \ -} while (/*CONSTCOND*/0) - -#define CPU_STAT_HLT CPU_STATSAVE.cpu_stat.hlt - -#define CPU_STAT_IOPL ((CPU_EFLAG & IOPL_FLAG) >> 12) -#define CPU_IOPL0 0 -#define CPU_IOPL1 1 -#define CPU_IOPL2 2 -#define CPU_IOPL3 3 - -#define CPU_STAT_IOADDR CPU_STATSAVE.cpu_stat.ioaddr -#define CPU_STAT_IOLIMIT CPU_STATSAVE.cpu_stat.iolimit - -#define CPU_STAT_PREV_EXCEPTION CPU_STATSAVE.cpu_stat.prev_exception -#define CPU_STAT_EXCEPTION_COUNTER CPU_STATSAVE.cpu_stat.nerror -#define CPU_STAT_EXCEPTION_COUNTER_INC() CPU_STATSAVE.cpu_stat.nerror++ -#define CPU_STAT_EXCEPTION_COUNTER_CLEAR() CPU_STATSAVE.cpu_stat.nerror = 0 - -#define CPU_MODE_SUPERVISER 0 -#define CPU_MODE_USER (1 << 3) - -#if defined(SUPPORT_IA32_HAXM) -#define CPU_CLI \ -do { \ - CPU_FLAG &= ~I_FLAG; \ - CPU_TRAP = 0; \ - np2haxstat.update_regs = 1; \ -} while (/*CONSTCOND*/0) - -#define CPU_STI \ -do { \ - CPU_FLAG |= I_FLAG; \ - CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG) ; \ - np2haxstat.update_regs = 1; \ -} while (/*CONSTCOND*/0) - -#else -#define CPU_CLI \ -do { \ - CPU_FLAG &= ~I_FLAG; \ - CPU_TRAP = 0; \ -} while (/*CONSTCOND*/0) - -#define CPU_STI \ -do { \ - CPU_FLAG |= I_FLAG; \ - CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG) ; \ -} while (/*CONSTCOND*/0) -#endif - -#define CPU_GDTR_LIMIT CPU_STATSAVE.cpu_sysregs.gdtr_limit -#define CPU_GDTR_BASE CPU_STATSAVE.cpu_sysregs.gdtr_base -#define CPU_IDTR_LIMIT CPU_STATSAVE.cpu_sysregs.idtr_limit -#define CPU_IDTR_BASE CPU_STATSAVE.cpu_sysregs.idtr_base -#define CPU_LDTR CPU_STATSAVE.cpu_sysregs.ldtr -#define CPU_LDTR_DESC CPU_STATSAVE.cpu_stat.ldtr -#define CPU_LDTR_BASE CPU_LDTR_DESC.u.seg.segbase -#define CPU_LDTR_LIMIT CPU_LDTR_DESC.u.seg.limit -#define CPU_TR CPU_STATSAVE.cpu_sysregs.tr -#define CPU_TR_DESC CPU_STATSAVE.cpu_stat.tr -#define CPU_TR_BASE CPU_TR_DESC.u.seg.segbase -#define CPU_TR_LIMIT CPU_TR_DESC.u.seg.limit - -/* - * control register - */ -#define CPU_MSW CPU_STATSAVE.cpu_sysregs.cr0 - -#define CPU_CR0 CPU_STATSAVE.cpu_sysregs.cr0 -#define CPU_CR1 CPU_STATSAVE.cpu_sysregs.cr1 -#define CPU_CR2 CPU_STATSAVE.cpu_sysregs.cr2 -#define CPU_CR3 CPU_STATSAVE.cpu_sysregs.cr3 -#define CPU_CR4 CPU_STATSAVE.cpu_sysregs.cr4 -#define CPU_MXCSR CPU_STATSAVE.cpu_sysregs.mxcsr - -#define CPU_MSR_TSC CPU_STATSAVE.cpu_tsc - -#define CPU_CR0_PE (1 << 0) -#define CPU_CR0_MP (1 << 1) -#define CPU_CR0_EM (1 << 2) -#define CPU_CR0_TS (1 << 3) -#define CPU_CR0_ET (1 << 4) -#define CPU_CR0_NE (1 << 5) -#define CPU_CR0_WP (1 << 16) -#define CPU_CR0_AM (1 << 18) -#define CPU_CR0_NW (1 << 29) -#define CPU_CR0_CD (1 << 30) -#define CPU_CR0_PG (1 << 31) -#define CPU_CR0_ALL (CPU_CR0_PE|CPU_CR0_MP|CPU_CR0_EM|CPU_CR0_TS|CPU_CR0_ET|CPU_CR0_NE|CPU_CR0_WP|CPU_CR0_AM|CPU_CR0_NW|CPU_CR0_CD|CPU_CR0_PG) - -#define CPU_CR3_PD_MASK 0xfffff000 -#define CPU_CR3_PWT (1 << 3) -#define CPU_CR3_PCD (1 << 4) -#define CPU_CR3_MASK (CPU_CR3_PD_MASK|CPU_CR3_PWT|CPU_CR3_PCD) - -#define CPU_CR4_VME (1 << 0) -#define CPU_CR4_PVI (1 << 1) -#define CPU_CR4_TSD (1 << 2) -#define CPU_CR4_DE (1 << 3) -#define CPU_CR4_PSE (1 << 4) -#define CPU_CR4_PAE (1 << 5) -#define CPU_CR4_MCE (1 << 6) -#define CPU_CR4_PGE (1 << 7) -#define CPU_CR4_PCE (1 << 8) -#define CPU_CR4_OSFXSR (1 << 9) -#define CPU_CR4_OSXMMEXCPT (1 << 10) - -/* - * debug register - */ -#define CPU_DR(r) CPU_STATSAVE.cpu_regs.dr[(r)] -#define CPU_DR6 CPU_DR(6) -#define CPU_DR7 CPU_DR(7) - -#define CPU_STAT_BP CPU_STATSAVE.cpu_stat.bp -#define CPU_STAT_BP_EVENT CPU_STATSAVE.cpu_stat.bp_ev -#define CPU_STAT_BP_EVENT_B(r) (1 << (r)) -#define CPU_STAT_BP_EVENT_DR (1 << 4) /* fault */ -#define CPU_STAT_BP_EVENT_STEP (1 << 5) /* as CPU_TRAP */ -#define CPU_STAT_BP_EVENT_TASK (1 << 6) -#define CPU_STAT_BP_EVENT_RF (1 << 7) /* RF_FLAG */ - -#define CPU_DR6_B(r) (1 << (r)) -#define CPU_DR6_BD (1 << 13) -#define CPU_DR6_BS (1 << 14) -#define CPU_DR6_BT (1 << 15) - -#define CPU_DR7_L(r) (1 << ((r) * 2)) -#define CPU_DR7_G(r) (1 << ((r) * 2 + 1)) -#define CPU_DR7_LE (1 << 8) -#define CPU_DR7_GE (1 << 9) -#define CPU_DR7_GD (1 << 13) -#define CPU_DR7_RW(r) (3 << ((r) * 4 + 16)) -#define CPU_DR7_LEN(r) (3 << ((r) * 4 + 16 + 2)) - -#define CPU_DR7_GET_RW(r) ((CPU_DR7) >> (16 + (r) * 4)) -#define CPU_DR7_RW_CODE 0 -#define CPU_DR7_RW_RO 1 -#define CPU_DR7_RW_IO 2 -#define CPU_DR7_RW_RW 3 - -#define CPU_DR7_GET_LEN(r) ((CPU_DR7) >> (16 + 2 + (r) * 4)) - -void ia32_init(void); -void ia32_initreg(void); -void ia32_setextsize(UINT32 size); -void ia32_setemm(UINT frame, UINT32 addr); - -void ia32reset(void); -void ia32shut(void); -void ia32a20enable(BOOL enable); -void ia32(void); -void ia32_step(void); -void CPUCALL ia32_interrupt(int vect, int soft); - -void exec_1step(void); -void exec_allstep(void); -#define INST_PREFIX (1 << 0) -#define INST_STRING (1 << 1) -#define REP_CHECKZF (1 << 7) - -void ia32_printf(const char *buf, ...); -void ia32_warning(const char *buf, ...); -void ia32_panic(const char *buf, ...); - -void ia32_bioscall(void); - -void CPUCALL change_pm(BOOL onoff); -void CPUCALL change_vm(BOOL onoff); -void CPUCALL change_pg(BOOL onoff); - -void CPUCALL set_cr3(UINT32 new_cr3); -void CPUCALL set_cpl(int new_cpl); - -extern const UINT8 iflags[]; -#define szpcflag iflags -extern UINT8 szpflag_w[0x10000]; - -#if defined(USE_CPU_EIPMASK) -extern UINT32 cpu_eipMask; -#endif - -extern UINT8 *reg8_b20[0x100]; -extern UINT8 *reg8_b53[0x100]; -#if !defined(USE_CPU_DIRECTREG) -extern UINT16 *reg16_b20[0x100]; -extern UINT16 *reg16_b53[0x100]; -extern UINT32 *reg32_b20[0x100]; -extern UINT32 *reg32_b53[0x100]; -#endif - -extern const char *reg8_str[CPU_REG_NUM]; -extern const char *reg16_str[CPU_REG_NUM]; -extern const char *reg32_str[CPU_REG_NUM]; -extern const char *sreg_str[CPU_SEGREG_NUM]; - -char *cpu_reg2str(void); -#if defined(USE_FPU) -char *fpu_reg2str(void); -#endif -void put_cpuinfo(void); -void dbg_printf(const char *str, ...); - - -/* - * FPU - */ -#define FPU_REGS CPU_STATSAVE.fpu_regs -#define FPU_CTRLWORD FPU_REGS.control -#define FPU_CTRLWORDMASK FPU_REGS.cw_mask_all -#define FPU_STATUSWORD FPU_REGS.status -#define FPU_INSTPTR FPU_REGS.inst -#define FPU_DATAPTR FPU_REGS.data -#define FPU_LASTINSTOP FPU_REGS.op -#define FPU_INSTPTR_OFFSET FPU_REGS.inst.offset -#define FPU_INSTPTR_SEG FPU_REGS.inst.seg -#define FPU_DATAPTR_OFFSET FPU_REGS.data.offset -#define FPU_DATAPTR_SEG FPU_REGS.data.seg - -#define FPU_STAT CPU_STATSAVE.fpu_stat -#define FPU_STAT_TOP FPU_STAT.top -#define FPU_STAT_PC FPU_STAT.pc -#define FPU_STAT_RC FPU_STAT.rc - -/* - * SSE - */ -#ifdef USE_SSE -#define SSE_MXCSR CPU_MXCSR -#define SSE_XMMREG(i) FPU_STAT.xmm_reg[i] -#endif - -#if 0 -#define FPU_ST(i) FPU_STAT.reg[((i) + FPU_STAT_TOP) & 7] -#else -#define FPU_ST(i) ((FPU_STAT_TOP+ (i) ) & 7) -#endif -#define FPU_REG(i) FPU_STAT.reg[i] - -/* FPU status register */ -#define FP_IE_FLAG (1 << 0) /* 無効な動作 */ -#define FP_DE_FLAG (1 << 1) /* デノーマライズド・オペランド */ -#define FP_ZE_FLAG (1 << 2) /* ゼロによる除算 */ -#define FP_OE_FLAG (1 << 3) /* オーバーフロー */ -#define FP_UE_FLAG (1 << 4) /* アンダーフロー */ -#define FP_PE_FLAG (1 << 5) /* 精度 */ -#define FP_SF_FLAG (1 << 6) /* スタックフォルト */ -#define FP_ES_FLAG (1 << 7) /* エラーサマリステータス */ -#define FP_C0_FLAG (1 << 8) /* 条件コード */ -#define FP_C1_FLAG (1 << 9) /* 条件コード */ -#define FP_C2_FLAG (1 << 10) /* 条件コード */ -#define FP_TOP_FLAG (7 << 11) /* スタックポイントのトップ */ -#define FP_C3_FLAG (1 << 14) /* 条件コード */ -#define FP_B_FLAG (1 << 15) /* FPU ビジー */ - -#define FP_TOP_SHIFT 11 -#define FP_TOP_GET() ((FPU_STATUSWORD & FP_TOP_FLAG) >> FP_TOP_SHIFT) -#define FP_TOP_SET(v) \ -do { \ - FPU_STATUSWORD = ((FPU_STATUSWORD & ~FP_TOP_FLAG) | (((v) & 0x7) << FP_TOP_SHIFT)); \ -} while (/*CONSTCOND*/0) - -#define FPU_STAT_TOP_INC() \ -do { \ - FPU_STAT.top = (FPU_STAT.top + 1) & 7; \ -} while (/*CONSTCOND*/0) -#define FPU_STAT_TOP_DEC() \ -do { \ - FPU_STAT.top = (FPU_STAT.top - 1) & 7; \ -} while (/*CONSTCOND*/0) - -/* FPU control register */ -#define FP_CTRL_PC_SHIFT 8 /* 精度制御 */ -#define FP_CTRL_RC_SHIFT 10 /* 丸め制御 */ - -#define FP_CTRL_PC_24 0 /* 単精度 */ -#define FP_CTRL_PC_53 1 /* 倍精度 */ -#define FP_CTRL_PC_64 3 /* 拡張精度 */ - -#define FP_CTRL_RC_NEAREST_EVEN 0 -#define FP_CTRL_RC_DOWN 1 -#define FP_CTRL_RC_UP 2 -#define FP_CTRL_RC_TO_ZERO 3 - - -/* - * Misc. - */ -void memory_dump(int idx, UINT32 madr); -void gdtr_dump(UINT32 base, UINT limit); -void idtr_dump(UINT32 base, UINT limit); -void ldtr_dump(UINT32 base, UINT limit); -void tr_dump(UINT16 selector, UINT32 base, UINT limit); -UINT32 pde_dump(UINT32 base, int idx); -void segdesc_dump(descriptor_t *sdp); -UINT32 convert_laddr_to_paddr(UINT32 laddr); -UINT32 convert_vaddr_to_paddr(unsigned int idx, UINT32 offset); - -/* - * disasm - */ -/* context */ -typedef struct { - UINT32 val; - - UINT32 eip; - BOOL op32; - BOOL as32; - - UINT32 baseaddr; - UINT8 opcode[3]; - UINT8 modrm; - UINT8 sib; - - BOOL useseg; - int seg; - - UINT8 opbyte[32]; - int nopbytes; - - char str[256]; - size_t remain; - - char *next; - char *prefix; - char *op; - char *arg[3]; - int narg; - - char pad; -} disasm_context_t; - -int disasm(UINT32 *eip, disasm_context_t *ctx); -char *cpu_disasm2str(UINT32 eip); - -#ifdef __cplusplus -} -#endif - -#include "cpu_io.h" -#include "cpu_mem.h" -#include "exception.h" -#include "paging.h" -#include "resolve.h" -#include "task.h" - -#endif /* !IA32_CPU_CPU_H__ */ +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +/* + Intel Architecture 32-bit Processor Interpreter Engine for Pentium + + Copyright by Yui/Studio Milmake 1999-2000 + Copyright by Norio HATTORI 2000,2001 + Copyright by NONAKA Kimihiro 2002-2004 +*/ + +#ifndef IA32_CPU_CPU_H__ +#define IA32_CPU_CPU_H__ + +#include "interface.h" +#if defined(SUPPORT_FPU_SOFTFLOAT) && !defined(SUPPORT_FPU_SOFTFLOAT3) +#include "instructions/fpu/softfloat/softfloat.h" +#endif +#if defined(SUPPORT_FPU_SOFTFLOAT3) +#include "instructions/fpu/softfloat3/softfloat.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef union { +#if defined(BYTESEX_LITTLE) + struct { + UINT8 l; + UINT8 h; + UINT8 _hl; + UINT8 _hh; + } b; + struct { + UINT16 w; + UINT16 _hw; + } w; +#elif defined(BYTESEX_BIG) + struct { + UINT8 _hh; + UINT8 _hl; + UINT8 h; + UINT8 l; + } b; + struct { + UINT16 _hw; + UINT16 w; + } w; +#endif + UINT32 d; +} REG32; + +typedef union { + UINT8 b[10]; + UINT16 w[5]; + struct { + UINT32 l[2]; + UINT16 h; + } d; +} REG80; + +#ifdef __cplusplus +} +#endif + +#include "segments.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + CPU_EAX_INDEX = 0, + CPU_ECX_INDEX = 1, + CPU_EDX_INDEX = 2, + CPU_EBX_INDEX = 3, + CPU_ESP_INDEX = 4, + CPU_EBP_INDEX = 5, + CPU_ESI_INDEX = 6, + CPU_EDI_INDEX = 7, + CPU_REG_NUM +}; + +enum { + CPU_ES_INDEX = 0, + CPU_CS_INDEX = 1, + CPU_SS_INDEX = 2, + CPU_DS_INDEX = 3, + CPU_SEGREG286_NUM = 4, + CPU_FS_INDEX = 4, + CPU_GS_INDEX = 5, + CPU_SEGREG_NUM +}; + +enum { + CPU_TEST_REG_NUM = 8 +}; + +enum { + CPU_DEBUG_REG_NUM = 8, + CPU_DEBUG_REG_INDEX_NUM = 4 +}; + +enum { + MAX_PREFIX = 8 +}; + +typedef struct { + REG32 reg[CPU_REG_NUM]; + UINT16 sreg[CPU_SEGREG_NUM]; + + REG32 eflags; + REG32 eip; + + REG32 prev_eip; + REG32 prev_esp; + + UINT32 tr[CPU_TEST_REG_NUM]; + UINT32 dr[CPU_DEBUG_REG_NUM]; +} CPU_REGS; + +typedef struct { + UINT16 gdtr_limit; + UINT16 pad0; + UINT32 gdtr_base; + UINT16 idtr_limit; + UINT16 pad1; + UINT32 idtr_base; + + UINT16 ldtr; + UINT16 tr; + + UINT32 cr0; + UINT32 cr1; + UINT32 cr2; + UINT32 cr3; + UINT32 cr4; + UINT32 mxcsr; +} CPU_SYSREGS; + +typedef struct { + descriptor_t sreg[CPU_SEGREG_NUM]; + descriptor_t ldtr; + descriptor_t tr; + + UINT32 adrsmask; + UINT32 ovflag; + + UINT8 ss_32; + UINT8 resetreq; + UINT8 trap; + + UINT8 page_wp; + + UINT8 protected_mode; + UINT8 paging; + UINT8 vm86; + UINT8 user_mode; + + UINT8 hlt; + UINT8 bp; /* break point bitmap */ + UINT8 bp_ev; /* break point event */ + + UINT8 backout_sp; /* backout ESP, when exception */ + + UINT32 pde_base; + + UINT32 ioaddr; /* I/O bitmap linear address */ + UINT16 iolimit; /* I/O bitmap count */ + + UINT8 nerror; /* double fault/ triple fault */ + UINT8 prev_exception; +} CPU_STAT; + +typedef struct { + UINT8 op_32; + UINT8 as_32; + UINT8 rep_used; + UINT8 seg_used; + UINT32 seg_base; +} CPU_INST; + +/* FPU */ +enum { + FPU_REG_NUM = 8, + XMM_REG_NUM = 8 +}; + +typedef struct { + UINT16 seg; + UINT16 pad; + UINT32 offset; +} FPU_PTR; + +typedef struct { + UINT16 control; // 制御レジスター + UINT16 status; // ステータスレジスター + UINT16 op; // オペコードレジスター + UINT16 tag; // タグワードレジスター + + FPU_PTR inst; // ラスト命令ポインタレジスター + FPU_PTR data; // ラストデータポインタレジスター +} FPU_REGS_S; + +#if 0 + +typedef struct { + UINT8 valid; + UINT8 sign; + UINT8 zero; + UINT8 inf; + UINT8 nan; + UINT8 denorm; + SINT16 exp; + UINT64 num; +} FP_REG; + +typedef struct { + UINT8 top; + UINT8 pc; + UINT8 rc; + UINT8 dmy[1]; + + FP_REG reg[FPU_REG_NUM]; // R0 to R7 +} FPU_STAT; + +#else + +typedef enum { + TAG_Valid = 0, + TAG_Zero = 1, + TAG_Weird = 2, + TAG_Empty = 3 +} FP_TAG; + +typedef enum { + ROUND_Nearest = 0, + ROUND_Down = 1, + ROUND_Up = 2, + ROUND_Chop = 3 +} FP_RND; + +typedef union { +#if defined(SUPPORT_FPU_SOFTFLOAT) && !defined(SUPPORT_FPU_SOFTFLOAT3) + floatx80 d; +#endif +#if defined(SUPPORT_FPU_SOFTFLOAT3) + sw_extFloat80_t d; +#endif + double d64; + struct { + UINT32 lower; + SINT32 upper; + SINT16 ext; + } l; + struct { + UINT32 lower; + UINT32 upper; + SINT16 ext; + } ul; + SINT64 ll; + UINT8 b[10]; +} FP_REG; + +typedef union { + struct { + UINT32 m1; + UINT32 m2; + UINT16 m3; + } ul32; + struct { + UINT32 m1; + UINT32 m2; + SINT16 m3; + } l32; + struct { + UINT64 m12; + UINT16 m3; + } ul64; + struct { + UINT64 m12; + SINT16 m3; + } l64; +} FP_INT_REG; + +typedef union { + float f[4]; + double d[2]; + UINT8 ul8[16]; + UINT16 ul16[8]; + UINT32 ul32[4]; + UINT64 ul64[2]; +} XMM_REG; + +typedef struct { + UINT8 top; + UINT8 pc; + UINT8 rc; + UINT8 dmy[1]; + + FP_REG reg[FPU_REG_NUM+1]; // R0 to R7 + α + FP_TAG tag[FPU_REG_NUM+1]; // R0 to R7 + α + FP_RND round; +#if defined(SUPPORT_FPU_DOSBOX2) // XXX: 整数間だけ正確にするため用 + FP_INT_REG int_reg[FPU_REG_NUM+1]; + UINT8 int_regvalid[FPU_REG_NUM+1]; +#elif defined(SUPPORT_FPU_DOSBOX2_COMPATIBLE) // XXX: 互換維持用 未使用 + FP_INT_REG reserved_fpu1[FPU_REG_NUM + 1]; + UINT8 reserved_fpu2[FPU_REG_NUM + 1]; +#endif +#ifdef USE_SSE + XMM_REG xmm_reg[XMM_REG_NUM+1]; // xmm0 to xmm7 +#endif +#ifdef USE_MMX + UINT8 mmxenable; +#endif +} FPU_STAT_S; + +#endif + +typedef struct { + CPU_REGS cpu_regs; + CPU_SYSREGS cpu_sysregs; + CPU_STAT cpu_stat; + CPU_INST cpu_inst; + CPU_INST cpu_inst_default; + +#if defined(USE_FPU) + FPU_REGS_S fpu_regs; + FPU_STAT_S fpu_stat; +#endif + + /* protected by cpu shut */ + UINT8 cpu_type; + UINT8 itfbank; + UINT16 ram_d0; + SINT32 remainclock; + SINT32 baseclock; + UINT32 clock; + +#if defined(USE_TSC) + UINT64 cpu_tsc; +#endif +} I386STAT; + +typedef struct { + UINT8 *ext; + UINT32 extsize; + UINT8 *extbase; /* = ext - 0x100000 */ + UINT32 extlimit16mb; /* = extsize + 0x100000 (MAX:16MB) */ + UINT32 extlimit4gb; /* = extsize + 0x100000 */ + UINT32 inport; + UINT8 *ems[4]; +} I386EXT; + +typedef struct { + I386STAT s; /* STATsave'ed */ + I386EXT e; +} I386CORE; + +#define I386CPUID_VERSION 1 +typedef struct { + UINT32 version; // CPUIDバージョン(ステートセーブ互換性を維持するため用)I386CPUID_VERSIONが最新 + char cpu_vendor[16]; // ベンダー(12byte) + UINT32 cpu_family; // ファミリ + UINT32 cpu_model; // モデル + UINT32 cpu_stepping; // ステッピング + UINT32 cpu_feature; // 機能フラグ + UINT32 cpu_feature_ex; // 拡張機能フラグ + char cpu_brandstring[64]; // ブランド名(48byte) + UINT32 cpu_brandid; // ブランドID + UINT32 cpu_feature_ecx; // ECX機能フラグ + UINT32 cpu_eflags_mask; // EFLAGSマスク(1のところがマスク状態) + + UINT8 allow_movCS; // mov cs,xxを許可する + UINT8 reserved8[3]; // 将来の拡張のためにとりあえず + UINT32 cpu_feature_ex_ecx; // ECX拡張機能フラグ + UINT32 reserved[29]; // 将来の拡張のためにとりあえず32bit*29個用意しておく + + UINT8 fpu_type; // FPU種類 +} I386CPUID; + +#define I386MSR_VERSION 1 +typedef struct { + UINT64 ia32_sysenter_cs; // SYSENTER CSレジスタ + UINT64 ia32_sysenter_esp; // SYSENTER ESPレジスタ + UINT64 ia32_sysenter_eip; // SYSENTER EIPレジスタ +} I386MSR_REG; +typedef struct { + UINT32 version; // MSRバージョン(ステートセーブ互換性を維持するため用)I386MSR_VERSIONが最新 + union{ + UINT64 regs[32]; // 将来の拡張のためにとりあえず64bit*32個用意しておく + I386MSR_REG reg; + }; +} I386MSR; + +extern I386CORE i386core; +extern I386CPUID i386cpuid; +extern I386MSR i386msr; + +#if defined(USE_CPU_MODRMPREFETCH) +extern UINT32 opCache; +#endif + +#define CPU_STATSAVE i386core.s + +#define CPU_ADRSMASK i386core.s.cpu_stat.adrsmask +#define CPU_RESETREQ i386core.s.cpu_stat.resetreq + +#define CPU_REMCLOCK i386core.s.remainclock +#define CPU_BASECLOCK i386core.s.baseclock +#define CPU_CLOCK i386core.s.clock +#define CPU_ITFBANK i386core.s.itfbank +#define CPU_RAM_D000 i386core.s.ram_d0 + +#define CPU_TYPE i386core.s.cpu_type +#define CPUTYPE_V30 0x01 + +#define CPU_EXTMEM i386core.e.ext +#define CPU_EXTMEMSIZE i386core.e.extsize +#define CPU_EXTMEMBASE i386core.e.extbase +#define CPU_EXTLIMIT16 i386core.e.extlimit16mb +#define CPU_EXTLIMIT i386core.e.extlimit4gb +#define CPU_INPADRS i386core.e.inport +#define CPU_EMSPTR i386core.e.ems + +extern sigjmp_buf exec_1step_jmpbuf; + +/* + * CPUID + */ +/*** vendor ***/ +#define CPU_VENDOR_INTEL "GenuineIntel" +#define CPU_VENDOR_AMD "AuthenticAMD" +#define CPU_VENDOR_AMD2 "AMDisbetter!" +#define CPU_VENDOR_CYRIX "CyrixInstead" +#define CPU_VENDOR_NEXGEN "NexGenDriven" +#define CPU_VENDOR_CENTAUR "CentaurHauls" +#define CPU_VENDOR_TRANSMETA "GenuineTMx86" +#define CPU_VENDOR_TRANSMETA2 "TransmetaCPU" +#define CPU_VENDOR_NSC "Geode by NSC" +#define CPU_VENDOR_RISE "RiseRiseRise" +#define CPU_VENDOR_UMC "UMC UMC UMC " +#define CPU_VENDOR_SIS "SiS SiS SiS " +#define CPU_VENDOR_VIA "VIA VIA VIA " +#define CPU_VENDOR_NEKOPRO "Neko Project" + +// デフォルト設定 +#define CPU_VENDOR CPU_VENDOR_INTEL + +/*** version ***/ +#define CPU_CORE_I_FAMILY 6 +#define CPU_CORE_I_MODEL 37 /* Core i5 Nehalem */ // 25 +#define CPU_CORE_I_STEPPING 5 + +#define CPU_CORE_2_DUOW_FAMILY 6 +#define CPU_CORE_2_DUOW_MODEL 23 /* Core 2 Duo Wolfdale */ // 17 +#define CPU_CORE_2_DUOW_STEPPING 6 + +#define CPU_CORE_2_DUO_FAMILY 6 +#define CPU_CORE_2_DUO_MODEL 15 /* Core 2 Duo Conroe */ // 15 +#define CPU_CORE_2_DUO_STEPPING 13 + +#define CPU_PENTIUM_4_FAMILY 15 +#define CPU_PENTIUM_4_MODEL 2 /* Pentium 4 */ +#define CPU_PENTIUM_4_STEPPING 4 + +#define CPU_PENTIUM_M_FAMILY 6 +#define CPU_PENTIUM_M_MODEL 9 /* Pentium M */ +#define CPU_PENTIUM_M_STEPPING 5 + +#define CPU_PENTIUM_III_FAMILY 6 +#define CPU_PENTIUM_III_MODEL 7 /* Pentium III */ +#define CPU_PENTIUM_III_STEPPING 2 + +#define CPU_PENTIUM_II_FAMILY 6 +#define CPU_PENTIUM_II_MODEL 3 /* Pentium II */ +#define CPU_PENTIUM_II_STEPPING 3 + +#define CPU_PENTIUM_PRO_FAMILY 6 +#define CPU_PENTIUM_PRO_MODEL 1 /* Pentium Pro */ +#define CPU_PENTIUM_PRO_STEPPING 1 + +#define CPU_MMX_PENTIUM_FAMILY 5 +#define CPU_MMX_PENTIUM_MODEL 4 /* MMX Pentium */ +#define CPU_MMX_PENTIUM_STEPPING 4 + +#define CPU_PENTIUM_FAMILY 5 +#define CPU_PENTIUM_MODEL 2 /* Pentium */ +#define CPU_PENTIUM_STEPPING 5 + +#define CPU_I486DX_FAMILY 4 +#define CPU_I486DX_MODEL 1 /* 486DX */ +#define CPU_I486DX_STEPPING 3 + +#define CPU_I486SX_FAMILY 4 +#define CPU_I486SX_MODEL 2 /* 486SX */ +#define CPU_I486SX_STEPPING 3 + +#define CPU_80386_FAMILY 3 +#define CPU_80386_MODEL 0 /* 80386 */ +#define CPU_80386_STEPPING 8 + +#define CPU_80286_FAMILY 2 +#define CPU_80286_MODEL 1 /* 80286 */ +#define CPU_80286_STEPPING 1 + + +#define CPU_AMD_K10_PHENOM_FAMILY 16 +#define CPU_AMD_K10_PHENOM_MODEL 2 /* AMD K10 Phenom */ +#define CPU_AMD_K10_PHENOM_STEPPING 2 + +#define CPU_AMD_K8_ATHLON_64X2_FAMILY 15 +#define CPU_AMD_K8_ATHLON_64X2_MODEL 44 /* AMD K8 Athlon 64 X2 */ +#define CPU_AMD_K8_ATHLON_64X2_STEPPING 2 + +#define CPU_AMD_K8_ATHLON_64_FAMILY 15 +#define CPU_AMD_K8_ATHLON_64_MODEL 4 /* AMD K8 Athlon 64 */ +#define CPU_AMD_K8_ATHLON_64_STEPPING 8 + +#define CPU_AMD_K7_ATHLON_XP_FAMILY 6 +#define CPU_AMD_K7_ATHLON_XP_MODEL 6 /* AMD K7 Athlon XP */ +#define CPU_AMD_K7_ATHLON_XP_STEPPING 2 + +#define CPU_AMD_K7_ATHLON_FAMILY 6 +#define CPU_AMD_K7_ATHLON_MODEL 1 /* AMD K7 Athlon */ +#define CPU_AMD_K7_ATHLON_STEPPING 2 + +#define CPU_AMD_K6_III_FAMILY 5 +#define CPU_AMD_K6_III_MODEL 9 /* AMD K6-III */ +#define CPU_AMD_K6_III_STEPPING 1 + +#define CPU_AMD_K6_2_FAMILY 5 +#define CPU_AMD_K6_2_MODEL 8 /* AMD K6-2 */ +#define CPU_AMD_K6_2_STEPPING 12 + + +/*** feature ***/ +#define CPU_FEATURE_FPU (1 << 0) +#define CPU_FEATURE_VME (1 << 1) +#define CPU_FEATURE_DE (1 << 2) +#define CPU_FEATURE_PSE (1 << 3) +#define CPU_FEATURE_TSC (1 << 4) +#define CPU_FEATURE_MSR (1 << 5) +#define CPU_FEATURE_PAE (1 << 6) +#define CPU_FEATURE_MCE (1 << 7) +#define CPU_FEATURE_CX8 (1 << 8) +#define CPU_FEATURE_APIC (1 << 9) +/* (1 << 10) */ +#define CPU_FEATURE_SEP (1 << 11) +#define CPU_FEATURE_MTRR (1 << 12) +#define CPU_FEATURE_PGE (1 << 13) +#define CPU_FEATURE_MCA (1 << 14) +#define CPU_FEATURE_CMOV (1 << 15) +#define CPU_FEATURE_FGPAT (1 << 16) +#define CPU_FEATURE_PSE36 (1 << 17) +#define CPU_FEATURE_PN (1 << 18) +#define CPU_FEATURE_CLFSH (1 << 19) +/* (1 << 20) */ +#define CPU_FEATURE_DS (1 << 21) +#define CPU_FEATURE_ACPI (1 << 22) +#define CPU_FEATURE_MMX (1 << 23) +#define CPU_FEATURE_FXSR (1 << 24) +#define CPU_FEATURE_SSE (1 << 25) +#define CPU_FEATURE_SSE2 (1 << 26) +#define CPU_FEATURE_SS (1 << 27) +#define CPU_FEATURE_HTT (1 << 28) +#define CPU_FEATURE_TM (1 << 29) +/* (1 << 30) */ +#define CPU_FEATURE_PBE (1 << 31) + +//#define CPU_FEATURE_XMM CPU_FEATURE_SSE + +#if defined(USE_FPU) +#define CPU_FEATURE_FPU_FLAG CPU_FEATURE_FPU +#else +#define CPU_FEATURE_FPU_FLAG 0 +#endif + +#if defined(USE_TSC) +#define CPU_FEATURE_TSC_FLAG CPU_FEATURE_TSC +#else +#define CPU_FEATURE_TSC_FLAG 0 +#endif + +#if defined(USE_VME) +#define CPU_FEATURE_VME_FLAG CPU_FEATURE_VME +#else +#define CPU_FEATURE_VME_FLAG 0 +#endif + +#if defined(USE_MMX)&&defined(USE_FPU) +#define CPU_FEATURE_MMX_FLAG CPU_FEATURE_MMX|CPU_FEATURE_FXSR +#else +#define CPU_FEATURE_MMX_FLAG 0 +#endif + +#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE) +#define CPU_FEATURE_SSE_FLAG CPU_FEATURE_SSE|CPU_FEATURE_CLFSH +#else +#define CPU_FEATURE_SSE_FLAG 0 +#endif + +#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE)&&defined(USE_SSE2) +#define CPU_FEATURE_SSE2_FLAG CPU_FEATURE_SSE2 +#else +#define CPU_FEATURE_SSE2_FLAG 0 +#endif + +/* 使用できる機能全部 */ +#define CPU_FEATURES_ALL (CPU_FEATURE_FPU_FLAG|CPU_FEATURE_CX8|CPU_FEATURE_TSC_FLAG|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_MMX_FLAG|CPU_FEATURE_SSE_FLAG|CPU_FEATURE_SSE2_FLAG|CPU_FEATURE_SEP) + +#define CPU_FEATURES_CORE_I (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) +#define CPU_FEATURES_CORE_2_DUOW (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) +#define CPU_FEATURES_CORE_2_DUO (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) +#define CPU_FEATURES_PENTIUM_4 (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) +#define CPU_FEATURES_PENTIUM_M (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) +#define CPU_FEATURES_PENTIUM_III (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE) +#define CPU_FEATURES_PENTIUM_II (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX) +#define CPU_FEATURES_PENTIUM_PRO (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR) +#define CPU_FEATURES_MMX_PENTIUM (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_MMX) +#define CPU_FEATURES_PENTIUM (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG) +#define CPU_FEATURES_I486DX (CPU_FEATURE_FPU) +#define CPU_FEATURES_I486SX (0) +#define CPU_FEATURES_80386 (0) +#define CPU_FEATURES_80286 (0) + +#define CPU_FEATURES_AMD_K10_PHENOM (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) +#define CPU_FEATURES_AMD_K8_ATHLON_64X2 (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) +#define CPU_FEATURES_AMD_K8_ATHLON_64 (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE|CPU_FEATURE_SSE2) +#define CPU_FEATURES_AMD_K7_ATHLON_XP (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_FXSR|CPU_FEATURE_MMX|CPU_FEATURE_CLFSH|CPU_FEATURE_SSE) +#define CPU_FEATURES_AMD_K7_ATHLON (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_CMOV|CPU_FEATURE_MMX) +#define CPU_FEATURES_AMD_K6_III (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_MMX) +#define CPU_FEATURES_AMD_K6_2 (CPU_FEATURE_FPU|CPU_FEATURE_CX8|CPU_FEATURE_TSC|CPU_FEATURE_VME_FLAG|CPU_FEATURE_MMX) + +/*** extended feature ***/ +#define CPU_FEATURE_EX_SYSCALL (1 << 11) +#define CPU_FEATURE_EX_XDBIT (1 << 20) +#define CPU_FEATURE_EX_EM64T (1 << 29) +#define CPU_FEATURE_EX_E3DNOW (1 << 30) +#define CPU_FEATURE_EX_3DNOW (1 << 31) + +#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_3DNOW) +#define CPU_FEATURE_EX_3DNOW_FLAG CPU_FEATURE_EX_3DNOW +#else +#define CPU_FEATURE_EX_3DNOW_FLAG 0 +#endif + +#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_3DNOW)&&defined(USE_SSE) +#define CPU_FEATURE_EX_E3DNOW_FLAG CPU_FEATURE_EX_E3DNOW +#else +#define CPU_FEATURE_EX_E3DNOW_FLAG 0 +#endif + +/* 使用できる機能全部 */ +#define CPU_FEATURES_EX_ALL (CPU_FEATURE_EX_3DNOW_FLAG|CPU_FEATURE_EX_E3DNOW_FLAG) + +#define CPU_FEATURES_EX_CORE_I (0) +#define CPU_FEATURES_EX_CORE_2_DUOW (0) +#define CPU_FEATURES_EX_CORE_2_DUO (0) +#define CPU_FEATURES_EX_PENTIUM_4 (0) +#define CPU_FEATURES_EX_PENTIUM_M (0) +#define CPU_FEATURES_EX_PENTIUM_III (0) +#define CPU_FEATURES_EX_PENTIUM_II (0) +#define CPU_FEATURES_EX_PENTIUM_PRO (0) +#define CPU_FEATURES_EX_MMX_PENTIUM (0) +#define CPU_FEATURES_EX_PENTIUM (0) +#define CPU_FEATURES_EX_I486DX (0) +#define CPU_FEATURES_EX_I486SX (0) +#define CPU_FEATURES_EX_80386 (0) +#define CPU_FEATURES_EX_80286 (0) + +#define CPU_FEATURES_EX_AMD_K10_PHENOM (CPU_FEATURE_EX_3DNOW|CPU_FEATURE_EX_E3DNOW) +#define CPU_FEATURES_EX_AMD_K8_ATHLON_64X2 (CPU_FEATURE_EX_3DNOW|CPU_FEATURE_EX_E3DNOW) +#define CPU_FEATURES_EX_AMD_K8_ATHLON_64 (CPU_FEATURE_EX_3DNOW|CPU_FEATURE_EX_E3DNOW) +#define CPU_FEATURES_EX_AMD_K7_ATHLON_XP (CPU_FEATURE_EX_3DNOW|CPU_FEATURE_EX_E3DNOW) +#define CPU_FEATURES_EX_AMD_K7_ATHLON (CPU_FEATURE_EX_3DNOW|CPU_FEATURE_EX_E3DNOW) +#define CPU_FEATURES_EX_AMD_K6_III (CPU_FEATURE_EX_3DNOW) +#define CPU_FEATURES_EX_AMD_K6_2 (CPU_FEATURE_EX_3DNOW) + +/*** extended ECX feature ***/ +#define CPU_FEATURE_EX_ECX_SSE4A (1 << 6) + +#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_3DNOW)&&defined(USE_SSE)&&defined(USE_SSE2)&&defined(USE_SSE3)&&defined(USE_SSE4A) +#define CPU_FEATURE_EX_ECX_SSE4A_FLAG CPU_FEATURE_EX_ECX_SSE4A +#else +#define CPU_FEATURE_EX_ECX_SSE4A_FLAG 0 +#endif + +/* 使用できる機能全部 */ +#define CPU_FEATURES_EX_ECX_ALL (CPU_FEATURE_EX_ECX_SSE4A_FLAG) + +#define CPU_FEATURES_EX_ECX_CORE_I (0) +#define CPU_FEATURES_EX_ECX_CORE_2_DUOW (0) +#define CPU_FEATURES_EX_ECX_CORE_2_DUO (0) +#define CPU_FEATURES_EX_ECX_PENTIUM_4 (0) +#define CPU_FEATURES_EX_ECX_PENTIUM_M (0) +#define CPU_FEATURES_EX_ECX_PENTIUM_III (0) +#define CPU_FEATURES_EX_ECX_PENTIUM_II (0) +#define CPU_FEATURES_EX_ECX_PENTIUM_PRO (0) +#define CPU_FEATURES_EX_ECX_MMX_PENTIUM (0) +#define CPU_FEATURES_EX_ECX_PENTIUM (0) +#define CPU_FEATURES_EX_ECX_I486DX (0) +#define CPU_FEATURES_EX_ECX_I486SX (0) +#define CPU_FEATURES_EX_ECX_80386 (0) +#define CPU_FEATURES_EX_ECX_80286 (0) + +#define CPU_FEATURES_EX_ECX_AMD_K10_PHENOM (CPU_FEATURE_EX_ECX_SSE4A_FLAG) +#define CPU_FEATURES_EX_ECX_AMD_K8_ATHLON_64X2 (0) +#define CPU_FEATURES_EX_ECX_AMD_K8_ATHLON_64 (0) +#define CPU_FEATURES_EX_ECX_AMD_K7_ATHLON_XP (0) +#define CPU_FEATURES_EX_ECX_AMD_K7_ATHLON (0) +#define CPU_FEATURES_EX_ECX_AMD_K6_III (0) +#define CPU_FEATURES_EX_ECX_AMD_K6_2 (0) + +/*** ECX feature ***/ +#define CPU_FEATURE_ECX_SSE3 (1 << 0) +#define CPU_FEATURE_ECX_PCLMULDQ (1 << 1) +#define CPU_FEATURE_ECX_DTES64 (1 << 2) +#define CPU_FEATURE_ECX_MONITOR (1 << 3) +#define CPU_FEATURE_ECX_DSCPL (1 << 4) +#define CPU_FEATURE_ECX_VMX (1 << 5) +#define CPU_FEATURE_ECX_SMX (1 << 6) +#define CPU_FEATURE_ECX_EST (1 << 7) +#define CPU_FEATURE_ECX_TM2 (1 << 8) +#define CPU_FEATURE_ECX_SSSE3 (1 << 9) +#define CPU_FEATURE_ECX_CNXT1D (1 << 10) +/* (1 << 11) */ +/* (1 << 12) */ +#define CPU_FEATURE_ECX_CX16 (1 << 13) +#define CPU_FEATURE_ECX_xTPR (1 << 14) +#define CPU_FEATURE_ECX_PDCM (1 << 15) +/* (1 << 16) */ +/* (1 << 17) */ +#define CPU_FEATURE_ECX_DCA (1 << 18) +#define CPU_FEATURE_ECX_SSE4_1 (1 << 19) +#define CPU_FEATURE_ECX_SSE4_2 (1 << 20) +#define CPU_FEATURE_ECX_x2APIC (1 << 21) +#define CPU_FEATURE_ECX_MOVBE (1 << 22) +#define CPU_FEATURE_ECX_POPCNT (1 << 23) +/* (1 << 24) */ +#define CPU_FEATURE_ECX_AES (1 << 25) +#define CPU_FEATURE_ECX_XSAVE (1 << 26) +#define CPU_FEATURE_ECX_OSXSAVE (1 << 27) +/* (1 << 28) */ +/* (1 << 29) */ +/* (1 << 30) */ +/* (1 << 31) */ + +#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE)&&defined(USE_SSE2)&&defined(USE_SSE3) +#define CPU_FEATURE_ECX_SSE3_FLAG CPU_FEATURE_ECX_SSE3 +#else +#define CPU_FEATURE_ECX_SSE3_FLAG 0 +#endif + +#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE)&&defined(USE_SSE2)&&defined(USE_SSE3)&&defined(USE_SSSE3) +#define CPU_FEATURE_ECX_SSSE3_FLAG CPU_FEATURE_ECX_SSSE3 +#else +#define CPU_FEATURE_ECX_SSSE3_FLAG 0 +#endif + +#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE)&&defined(USE_SSE2)&&defined(USE_SSE3)&&defined(USE_SSSE3)&&defined(USE_SSE4_1) +#define CPU_FEATURE_ECX_SSE4_1_FLAG CPU_FEATURE_ECX_SSE4_1 +#else +#define CPU_FEATURE_ECX_SSE4_1_FLAG 0 +#endif + +#if defined(USE_MMX)&&defined(USE_FPU)&&defined(USE_SSE)&&defined(USE_SSE2)&&defined(USE_SSE3)&&defined(USE_SSSE3)&&defined(USE_SSE4_1)&&defined(USE_SSE4_2) +#define CPU_FEATURE_ECX_SSE4_2_FLAG CPU_FEATURE_ECX_SSE4_2 +#define CPU_FEATURE_ECX_POPCNT_FLAG CPU_FEATURE_ECX_POPCNT +#else +#define CPU_FEATURE_ECX_SSE4_2_FLAG 0 +#define CPU_FEATURE_ECX_POPCNT_FLAG 0 +#endif + +/* 使用できる機能全部 */ +#define CPU_FEATURES_ECX_ALL (CPU_FEATURE_ECX_SSE3_FLAG|CPU_FEATURE_ECX_SSSE3_FLAG|CPU_FEATURE_ECX_SSE4_1_FLAG|CPU_FEATURE_ECX_SSE4_2_FLAG|CPU_FEATURE_ECX_POPCNT_FLAG) + +#define CPU_FEATURES_ECX_CORE_I (CPU_FEATURE_ECX_SSE3|CPU_FEATURE_ECX_SSSE3|CPU_FEATURE_ECX_SSE4_1|CPU_FEATURE_ECX_SSE4_2|CPU_FEATURE_ECX_POPCNT) +#define CPU_FEATURES_ECX_CORE_2_DUOW (CPU_FEATURE_ECX_SSE3|CPU_FEATURE_ECX_SSSE3|CPU_FEATURE_ECX_SSE4_1) +#define CPU_FEATURES_ECX_CORE_2_DUO (CPU_FEATURE_ECX_SSE3|CPU_FEATURE_ECX_SSSE3) +#define CPU_FEATURES_ECX_PENTIUM_4 (CPU_FEATURE_ECX_SSE3) +#define CPU_FEATURES_ECX_PENTIUM_M (0) +#define CPU_FEATURES_ECX_PENTIUM_III (0) +#define CPU_FEATURES_ECX_PENTIUM_II (0) +#define CPU_FEATURES_ECX_PENTIUM_PRO (0) +#define CPU_FEATURES_ECX_MMX_PENTIUM (0) +#define CPU_FEATURES_ECX_PENTIUM (0) +#define CPU_FEATURES_ECX_I486DX (0) +#define CPU_FEATURES_ECX_I486SX (0) +#define CPU_FEATURES_ECX_80386 (0) +#define CPU_FEATURES_ECX_80286 (0) + +#define CPU_FEATURES_ECX_AMD_K10_PHENOM (CPU_FEATURE_ECX_SSE3|CPU_FEATURE_ECX_POPCNT) +#define CPU_FEATURES_ECX_AMD_K8_ATHLON_64X2 (CPU_FEATURE_ECX_SSE3) +#define CPU_FEATURES_ECX_AMD_K8_ATHLON_64 (0) +#define CPU_FEATURES_ECX_AMD_K7_ATHLON_XP (0) +#define CPU_FEATURES_ECX_AMD_K7_ATHLON (0) +#define CPU_FEATURES_ECX_AMD_K6_III (0) +#define CPU_FEATURES_ECX_AMD_K6_2 (0) + + +/* EFLAGS MASK */ +#define CPU_EFLAGS_MASK_CORE_I (0) +#define CPU_EFLAGS_MASK_CORE_2_DUOW (0) +#define CPU_EFLAGS_MASK_CORE_2_DUO (0) +#define CPU_EFLAGS_MASK_PENTIUM_4 (0) +#define CPU_EFLAGS_MASK_PENTIUM_M (0) +#define CPU_EFLAGS_MASK_PENTIUM_III (0) +#define CPU_EFLAGS_MASK_PENTIUM_II (0) +#define CPU_EFLAGS_MASK_PENTIUM_PRO (0) +#define CPU_EFLAGS_MASK_MMX_PENTIUM (0) +#define CPU_EFLAGS_MASK_PENTIUM (0) +#define CPU_EFLAGS_MASK_I486DX (0) +#define CPU_EFLAGS_MASK_I486SX (0) +#define CPU_EFLAGS_MASK_80386 ((1 << 18)) +#define CPU_EFLAGS_MASK_80286 ((1 << 18)) + +#define CPU_EFLAGS_MASK_AMD_K10_PHENOM (0) +#define CPU_EFLAGS_MASK_AMD_K8_ATHLON_64X2 (0) +#define CPU_EFLAGS_MASK_AMD_K8_ATHLON_64 (0) +#define CPU_EFLAGS_MASK_AMD_K7_ATHLON_XP (0) +#define CPU_EFLAGS_MASK_AMD_K7_ATHLON (0) +#define CPU_EFLAGS_MASK_AMD_K6_III (0) +#define CPU_EFLAGS_MASK_AMD_K6_2 (0) + + +/* brand string */ +#define CPU_BRAND_STRING_CORE_I "Intel(R) Core(TM) i3/5/7 CPU " +#define CPU_BRAND_STRING_CORE_2_DUOW "Intel(R) Core(TM)2 CPU SSE4.1 " +#define CPU_BRAND_STRING_CORE_2_DUO "Intel(R) Core(TM)2 CPU " +#define CPU_BRAND_STRING_PENTIUM_4 "Intel(R) Pentium(R) 4 CPU " +#define CPU_BRAND_STRING_PENTIUM_M "Intel(R) Pentium(R) M processor " +#define CPU_BRAND_STRING_PENTIUM_III "Intel(R) Pentium(R) III CPU " +#define CPU_BRAND_STRING_PENTIUM_II "Intel(R) Pentium(R) II CPU " +#define CPU_BRAND_STRING_PENTIUM_PRO "Intel(R) Pentium(R) Pro CPU " +#define CPU_BRAND_STRING_MMX_PENTIUM "Intel(R) Pentium(R) with MMX " +#define CPU_BRAND_STRING_PENTIUM "Intel(R) Pentium(R) Processor " +#define CPU_BRAND_STRING_I486DX "Intel(R) i486DX Processor " +#define CPU_BRAND_STRING_I486SX "Intel(R) i486SX Processor " +#define CPU_BRAND_STRING_80386 "Intel(R) 80386 Processor " +#define CPU_BRAND_STRING_80286 "Intel(R) 80286 Processor " +#define CPU_BRAND_STRING_AMD_K10_PHENOM "AMD Phenom(tm) Processor " +#define CPU_BRAND_STRING_AMD_K8_ATHLON_64X2 "AMD Athlon(tm) 64 Processor " +#define CPU_BRAND_STRING_AMD_K8_ATHLON_64 "AMD Athlon(tm) 64 Processor " +#define CPU_BRAND_STRING_AMD_K7_ATHLON_XP "AMD Athlon(tm) XP " +#define CPU_BRAND_STRING_AMD_K7_ATHLON "AMD-K7(tm) Processor " +#define CPU_BRAND_STRING_AMD_K6_III "AMD-K6(tm) 3D+ Processor " +#define CPU_BRAND_STRING_AMD_K6_2 "AMD-K6(tm) 3D processor " +#define CPU_BRAND_STRING_NEKOPRO "Neko Processor " // カスタム設定 +#define CPU_BRAND_STRING_NEKOPRO2 "Neko Processor II " // 全機能使用可能 + + +/* brand id */ +#define CPU_BRAND_ID_CORE_I 0 +#define CPU_BRAND_ID_CORE_2_DUOW 0 +#define CPU_BRAND_ID_CORE_2_DUO 0 +#define CPU_BRAND_ID_PENTIUM_4 0x9 +#define CPU_BRAND_ID_PENTIUM_M 0x16 +#define CPU_BRAND_ID_PENTIUM_III 0x2 +#define CPU_BRAND_ID_PENTIUM_II 0 +#define CPU_BRAND_ID_PENTIUM_PRO 0 +#define CPU_BRAND_ID_MMX_PENTIUM 0 +#define CPU_BRAND_ID_PENTIUM 0 +#define CPU_BRAND_ID_I486DX 0 +#define CPU_BRAND_ID_I486SX 0 +#define CPU_BRAND_ID_80386 0 +#define CPU_BRAND_ID_80286 0 +#define CPU_BRAND_ID_AMD_K10_PHENOM 0 +#define CPU_BRAND_ID_AMD_K8_ATHLON_64X2 0 +#define CPU_BRAND_ID_AMD_K8_ATHLON_64 0 +#define CPU_BRAND_ID_AMD_K7_ATHLON_XP 0 +#define CPU_BRAND_ID_AMD_K7_ATHLON 0 +#define CPU_BRAND_ID_AMD_K6_III 0 +#define CPU_BRAND_ID_AMD_K6_2 0 +#define CPU_BRAND_ID_NEKOPRO 0 // カスタム設定 +#define CPU_BRAND_ID_NEKOPRO2 0 // 全機能使用可能 + +#define CPU_BRAND_ID_AUTO 0xffffffff // BrandID自動設定(過去バージョンとの互換維持用) + +// CPUID デフォルト設定 +#if defined(USE_FPU) +#if defined(USE_SSE3) +#define CPU_FAMILY CPU_PENTIUM_III_FAMILY +#define CPU_MODEL CPU_PENTIUM_III_MODEL /* Pentium III */ +#define CPU_STEPPING CPU_PENTIUM_III_STEPPING +#define CPU_FEATURES CPU_FEATURES_PENTIUM_III +#define CPU_FEATURES_EX CPU_FEATURES_EX_PENTIUM_III +#define CPU_FEATURES_ECX CPU_FEATURES_ECX_PENTIUM_III +#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_PENTIUM_III +#define CPU_BRAND_STRING CPU_BRAND_STRING_PENTIUM_III +#define CPU_BRAND_ID CPU_BRAND_ID_PENTIUM_III +#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_PENTIUM_III +#elif defined(USE_SSE2) +#define CPU_FAMILY CPU_PENTIUM_III_FAMILY +#define CPU_MODEL CPU_PENTIUM_III_MODEL /* Pentium III */ +#define CPU_STEPPING CPU_PENTIUM_III_STEPPING +#define CPU_FEATURES CPU_FEATURES_PENTIUM_III +#define CPU_FEATURES_EX CPU_FEATURES_EX_PENTIUM_III +#define CPU_FEATURES_ECX CPU_FEATURES_ECX_PENTIUM_III +#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_PENTIUM_III +#define CPU_BRAND_STRING CPU_BRAND_STRING_PENTIUM_III +#define CPU_BRAND_ID CPU_BRAND_ID_PENTIUM_III +#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_PENTIUM_III +#elif defined(USE_SSE) +#define CPU_FAMILY CPU_PENTIUM_III_FAMILY +#define CPU_MODEL CPU_PENTIUM_III_MODEL /* Pentium III */ +#define CPU_STEPPING CPU_PENTIUM_III_STEPPING +#define CPU_FEATURES CPU_FEATURES_PENTIUM_III +#define CPU_FEATURES_EX CPU_FEATURES_EX_PENTIUM_III +#define CPU_FEATURES_ECX CPU_FEATURES_ECX_PENTIUM_III +#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_PENTIUM_III +#define CPU_BRAND_STRING CPU_BRAND_STRING_PENTIUM_III +#define CPU_BRAND_ID CPU_BRAND_ID_PENTIUM_III +#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_PENTIUM_III +#elif defined(USE_MMX) +#define CPU_FAMILY CPU_PENTIUM_II_FAMILY +#define CPU_MODEL CPU_PENTIUM_II_MODEL /* Pentium II */ +#define CPU_STEPPING CPU_PENTIUM_II_STEPPING +#define CPU_FEATURES CPU_FEATURES_PENTIUM_II +#define CPU_FEATURES_EX CPU_FEATURES_EX_PENTIUM_II +#define CPU_FEATURES_ECX CPU_FEATURES_ECX_PENTIUM_II +#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_PENTIUM_II +#define CPU_BRAND_STRING CPU_BRAND_STRING_PENTIUM_II +#define CPU_BRAND_ID CPU_BRAND_ID_PENTIUM_II +#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_PENTIUM_II +#else +#define CPU_FAMILY CPU_PENTIUM_FAMILY +#define CPU_MODEL CPU_PENTIUM_MODEL /* Pentium */ +#define CPU_STEPPING CPU_PENTIUM_STEPPING +#define CPU_FEATURES CPU_FEATURES_PENTIUM +#define CPU_FEATURES_EX CPU_FEATURES_EX_PENTIUM +#define CPU_FEATURES_ECX CPU_FEATURES_ECX_PENTIUM +#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_PENTIUM +#define CPU_BRAND_STRING CPU_BRAND_STRING_PENTIUM +#define CPU_BRAND_ID CPU_BRAND_ID_PENTIUM +#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_PENTIUM +#endif +#else +#define CPU_FAMILY CPU_I486SX_FAMILY +#define CPU_MODEL CPU_I486SX_MODEL /* 486SX */ +#define CPU_STEPPING CPU_I486SX_STEPPING +#define CPU_FEATURES CPU_FEATURES_I486SX +#define CPU_FEATURES_EX CPU_FEATURES_EX_I486SX +#define CPU_FEATURES_ECX CPU_FEATURES_ECX_I486SX +#define CPU_FEATURES_EX_ECX CPU_FEATURES_EX_ECX_I486SX +#define CPU_BRAND_STRING CPU_BRAND_STRING_I486SX +#define CPU_BRAND_ID CPU_BRAND_ID_I486SX +#define CPU_EFLAGS_MASK CPU_EFLAGS_MASK_I486SX +#endif + + + +#define CPU_REGS_BYTEL(n) CPU_STATSAVE.cpu_regs.reg[(n)].b.l +#define CPU_REGS_BYTEH(n) CPU_STATSAVE.cpu_regs.reg[(n)].b.h +#define CPU_REGS_WORD(n) CPU_STATSAVE.cpu_regs.reg[(n)].w.w +#define CPU_REGS_DWORD(n) CPU_STATSAVE.cpu_regs.reg[(n)].d +#define CPU_REGS_SREG(n) CPU_STATSAVE.cpu_regs.sreg[(n)] + +#if defined(USE_CPU_DIRECTREG) +#define CPU_REG16_B53_V(n) CPU_REGS_WORD(((n) >> 3) & 7) +#define CPU_REG16_B20_V(n) CPU_REGS_WORD((n) & 7) +#define CPU_REG32_B53_V(n) CPU_REGS_DWORD(((n) >> 3) & 7) +#define CPU_REG32_B20_V(n) CPU_REGS_DWORD((n) & 7) + +#define CPU_REG16_B53(n) (&CPU_REG16_B53_V(n)) +#define CPU_REG16_B20(n) (&CPU_REG16_B20_V(n)) +#define CPU_REG32_B53(n) (&CPU_REG32_B53_V(n)) +#define CPU_REG32_B20(n) (&CPU_REG32_B20_V(n)) +#else +#define CPU_REG16_B53_V(n) (*CPU_REG16_B53(n)) +#define CPU_REG16_B20_V(n) (*CPU_REG16_B20(n)) +#define CPU_REG32_B53_V(n) (*CPU_REG32_B53(n)) +#define CPU_REG32_B20_V(n) (*CPU_REG32_B20(n)) + +#define CPU_REG16_B53(n) reg16_b53[n] +#define CPU_REG16_B20(n) reg16_b20[n] +#define CPU_REG32_B53(n) reg32_b53[n] +#define CPU_REG32_B20(n) reg32_b20[n] +#endif + +#define CPU_STAT_SREG(n) CPU_STATSAVE.cpu_stat.sreg[(n)] +#define CPU_STAT_SREGBASE(n) CPU_STAT_SREG((n)).u.seg.segbase +#define CPU_STAT_SREGLIMIT(n) CPU_STAT_SREG((n)).u.seg.limit + + +#define CPU_AL CPU_REGS_BYTEL(CPU_EAX_INDEX) +#define CPU_CL CPU_REGS_BYTEL(CPU_ECX_INDEX) +#define CPU_DL CPU_REGS_BYTEL(CPU_EDX_INDEX) +#define CPU_BL CPU_REGS_BYTEL(CPU_EBX_INDEX) +#define CPU_AH CPU_REGS_BYTEH(CPU_EAX_INDEX) +#define CPU_CH CPU_REGS_BYTEH(CPU_ECX_INDEX) +#define CPU_DH CPU_REGS_BYTEH(CPU_EDX_INDEX) +#define CPU_BH CPU_REGS_BYTEH(CPU_EBX_INDEX) + +#define CPU_AX CPU_REGS_WORD(CPU_EAX_INDEX) +#define CPU_CX CPU_REGS_WORD(CPU_ECX_INDEX) +#define CPU_DX CPU_REGS_WORD(CPU_EDX_INDEX) +#define CPU_BX CPU_REGS_WORD(CPU_EBX_INDEX) +#define CPU_SP CPU_REGS_WORD(CPU_ESP_INDEX) +#define CPU_BP CPU_REGS_WORD(CPU_EBP_INDEX) +#define CPU_SI CPU_REGS_WORD(CPU_ESI_INDEX) +#define CPU_DI CPU_REGS_WORD(CPU_EDI_INDEX) +#define CPU_IP CPU_STATSAVE.cpu_regs.eip.w.w + +#define CPU_EAX CPU_REGS_DWORD(CPU_EAX_INDEX) +#define CPU_ECX CPU_REGS_DWORD(CPU_ECX_INDEX) +#define CPU_EDX CPU_REGS_DWORD(CPU_EDX_INDEX) +#define CPU_EBX CPU_REGS_DWORD(CPU_EBX_INDEX) +#define CPU_ESP CPU_REGS_DWORD(CPU_ESP_INDEX) +#define CPU_EBP CPU_REGS_DWORD(CPU_EBP_INDEX) +#define CPU_ESI CPU_REGS_DWORD(CPU_ESI_INDEX) +#define CPU_EDI CPU_REGS_DWORD(CPU_EDI_INDEX) +#define CPU_EIP CPU_STATSAVE.cpu_regs.eip.d +#if defined(USE_CPU_EIPMASK) +#define CPU_EIPMASK cpu_eipMask +#endif +#define CPU_PREV_EIP CPU_STATSAVE.cpu_regs.prev_eip.d +#define CPU_PREV_ESP CPU_STATSAVE.cpu_regs.prev_esp.d + +#define CPU_ES CPU_REGS_SREG(CPU_ES_INDEX) +#define CPU_CS CPU_REGS_SREG(CPU_CS_INDEX) +#define CPU_SS CPU_REGS_SREG(CPU_SS_INDEX) +#define CPU_DS CPU_REGS_SREG(CPU_DS_INDEX) +#define CPU_FS CPU_REGS_SREG(CPU_FS_INDEX) +#define CPU_GS CPU_REGS_SREG(CPU_GS_INDEX) + +#define CPU_ES_DESC CPU_STAT_SREG(CPU_ES_INDEX) +#define CPU_CS_DESC CPU_STAT_SREG(CPU_CS_INDEX) +#define CPU_SS_DESC CPU_STAT_SREG(CPU_SS_INDEX) +#define CPU_DS_DESC CPU_STAT_SREG(CPU_DS_INDEX) +#define CPU_FS_DESC CPU_STAT_SREG(CPU_FS_INDEX) +#define CPU_GS_DESC CPU_STAT_SREG(CPU_GS_INDEX) + +#define ES_BASE CPU_STAT_SREGBASE(CPU_ES_INDEX) +#define CS_BASE CPU_STAT_SREGBASE(CPU_CS_INDEX) +#define SS_BASE CPU_STAT_SREGBASE(CPU_SS_INDEX) +#define DS_BASE CPU_STAT_SREGBASE(CPU_DS_INDEX) +#define FS_BASE CPU_STAT_SREGBASE(CPU_FS_INDEX) +#define GS_BASE CPU_STAT_SREGBASE(CPU_GS_INDEX) + +#define CPU_EFLAG CPU_STATSAVE.cpu_regs.eflags.d +#define CPU_FLAG CPU_STATSAVE.cpu_regs.eflags.w.w +#define CPU_FLAGL CPU_STATSAVE.cpu_regs.eflags.b.l +#define CPU_FLAGH CPU_STATSAVE.cpu_regs.eflags.b.h +#define CPU_TRAP CPU_STATSAVE.cpu_stat.trap +#define CPU_INPORT CPU_STATSAVE.cpu_stat.inport +#define CPU_OV CPU_STATSAVE.cpu_stat.ovflag + +#define C_FLAG (1 << 0) +#define P_FLAG (1 << 2) +#define A_FLAG (1 << 4) +#define Z_FLAG (1 << 6) +#define S_FLAG (1 << 7) +#define T_FLAG (1 << 8) +#define I_FLAG (1 << 9) +#define D_FLAG (1 << 10) +#define O_FLAG (1 << 11) +#define IOPL_FLAG (3 << 12) +#define NT_FLAG (1 << 14) +#define RF_FLAG (1 << 16) +#define VM_FLAG (1 << 17) +#define AC_FLAG (1 << 18) +#define VIF_FLAG (1 << 19) +#define VIP_FLAG (1 << 20) +#define ID_FLAG (1 << 21) +#define SZP_FLAG (P_FLAG|Z_FLAG|S_FLAG) +#define SZAP_FLAG (P_FLAG|A_FLAG|Z_FLAG|S_FLAG) +#define SZPC_FLAG (C_FLAG|P_FLAG|Z_FLAG|S_FLAG) +#define SZAPC_FLAG (C_FLAG|P_FLAG|A_FLAG|Z_FLAG|S_FLAG) +#define ALL_FLAG (SZAPC_FLAG|T_FLAG|I_FLAG|D_FLAG|O_FLAG|IOPL_FLAG|NT_FLAG) +#define ALL_EFLAG (ALL_FLAG|RF_FLAG|VM_FLAG|AC_FLAG|VIF_FLAG|VIP_FLAG|ID_FLAG) + +#define REAL_FLAGREG ((CPU_FLAG & 0xf7ff) | (CPU_OV ? O_FLAG : 0) | 2) +#define REAL_EFLAGREG ((CPU_EFLAG & 0xfffff7ff) | (CPU_OV ? O_FLAG : 0) | 2) + +void CPUCALL set_flags(UINT16 new_flags, UINT16 mask); +void CPUCALL set_eflags(UINT32 new_flags, UINT32 mask); + + +#define CPU_INST_OP32 CPU_STATSAVE.cpu_inst.op_32 +#define CPU_INST_AS32 CPU_STATSAVE.cpu_inst.as_32 +#define CPU_INST_REPUSE CPU_STATSAVE.cpu_inst.rep_used +#define CPU_INST_SEGUSE CPU_STATSAVE.cpu_inst.seg_used +#define CPU_INST_SEGREG_INDEX CPU_STATSAVE.cpu_inst.seg_base +#define DS_FIX (!CPU_INST_SEGUSE ? CPU_DS_INDEX : CPU_INST_SEGREG_INDEX) +#define SS_FIX (!CPU_INST_SEGUSE ? CPU_SS_INDEX : CPU_INST_SEGREG_INDEX) + +#define CPU_STAT_CS_BASE CPU_STAT_SREGBASE(CPU_CS_INDEX) +#define CPU_STAT_CS_LIMIT CPU_STAT_SREGLIMIT(CPU_CS_INDEX) + +#define CPU_STAT_ADRSMASK CPU_STATSAVE.cpu_stat.adrsmask +#define CPU_STAT_SS32 CPU_STATSAVE.cpu_stat.ss_32 +#define CPU_STAT_RESETREQ CPU_STATSAVE.cpu_stat.resetreq +#define CPU_STAT_PM CPU_STATSAVE.cpu_stat.protected_mode +#define CPU_STAT_PAGING CPU_STATSAVE.cpu_stat.paging +#define CPU_STAT_VM86 CPU_STATSAVE.cpu_stat.vm86 +#define CPU_STAT_WP CPU_STATSAVE.cpu_stat.page_wp +#define CPU_STAT_CPL CPU_CS_DESC.rpl +#define CPU_STAT_USER_MODE CPU_STATSAVE.cpu_stat.user_mode +#define CPU_STAT_PDE_BASE CPU_STATSAVE.cpu_stat.pde_base +#define CPU_SET_PREV_ESP1(esp) \ +do { \ + CPU_STATSAVE.cpu_stat.backout_sp = 1; \ + CPU_PREV_ESP = (esp); \ +} while (/*CONSTCOND*/0) +#define CPU_SET_PREV_ESP() CPU_SET_PREV_ESP1(CPU_ESP) +#define CPU_CLEAR_PREV_ESP() \ +do { \ + CPU_STATSAVE.cpu_stat.backout_sp = 0; \ +} while (/*CONSTCOND*/0) + +#define CPU_STAT_HLT CPU_STATSAVE.cpu_stat.hlt + +#define CPU_STAT_IOPL ((CPU_EFLAG & IOPL_FLAG) >> 12) +#define CPU_IOPL0 0 +#define CPU_IOPL1 1 +#define CPU_IOPL2 2 +#define CPU_IOPL3 3 + +#define CPU_STAT_IOADDR CPU_STATSAVE.cpu_stat.ioaddr +#define CPU_STAT_IOLIMIT CPU_STATSAVE.cpu_stat.iolimit + +#define CPU_STAT_PREV_EXCEPTION CPU_STATSAVE.cpu_stat.prev_exception +#define CPU_STAT_EXCEPTION_COUNTER CPU_STATSAVE.cpu_stat.nerror +#define CPU_STAT_EXCEPTION_COUNTER_INC() CPU_STATSAVE.cpu_stat.nerror++ +#define CPU_STAT_EXCEPTION_COUNTER_CLEAR() CPU_STATSAVE.cpu_stat.nerror = 0 + +#define CPU_MODE_SUPERVISER 0 +#define CPU_MODE_USER (1 << 3) + +#if defined(SUPPORT_IA32_HAXM) +#define CPU_CLI \ +do { \ + CPU_FLAG &= ~I_FLAG; \ + CPU_TRAP = 0; \ + np2haxstat.update_regs = 1; \ +} while (/*CONSTCOND*/0) + +#define CPU_STI \ +do { \ + CPU_FLAG |= I_FLAG; \ + CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG) ; \ + np2haxstat.update_regs = 1; \ +} while (/*CONSTCOND*/0) + +#else +#define CPU_CLI \ +do { \ + CPU_FLAG &= ~I_FLAG; \ + CPU_TRAP = 0; \ +} while (/*CONSTCOND*/0) + +#define CPU_STI \ +do { \ + CPU_FLAG |= I_FLAG; \ + CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG) ; \ +} while (/*CONSTCOND*/0) +#endif + +#define CPU_GDTR_LIMIT CPU_STATSAVE.cpu_sysregs.gdtr_limit +#define CPU_GDTR_BASE CPU_STATSAVE.cpu_sysregs.gdtr_base +#define CPU_IDTR_LIMIT CPU_STATSAVE.cpu_sysregs.idtr_limit +#define CPU_IDTR_BASE CPU_STATSAVE.cpu_sysregs.idtr_base +#define CPU_LDTR CPU_STATSAVE.cpu_sysregs.ldtr +#define CPU_LDTR_DESC CPU_STATSAVE.cpu_stat.ldtr +#define CPU_LDTR_BASE CPU_LDTR_DESC.u.seg.segbase +#define CPU_LDTR_LIMIT CPU_LDTR_DESC.u.seg.limit +#define CPU_TR CPU_STATSAVE.cpu_sysregs.tr +#define CPU_TR_DESC CPU_STATSAVE.cpu_stat.tr +#define CPU_TR_BASE CPU_TR_DESC.u.seg.segbase +#define CPU_TR_LIMIT CPU_TR_DESC.u.seg.limit + +/* + * control register + */ +#define CPU_MSW CPU_STATSAVE.cpu_sysregs.cr0 + +#define CPU_CR0 CPU_STATSAVE.cpu_sysregs.cr0 +#define CPU_CR1 CPU_STATSAVE.cpu_sysregs.cr1 +#define CPU_CR2 CPU_STATSAVE.cpu_sysregs.cr2 +#define CPU_CR3 CPU_STATSAVE.cpu_sysregs.cr3 +#define CPU_CR4 CPU_STATSAVE.cpu_sysregs.cr4 +#define CPU_MXCSR CPU_STATSAVE.cpu_sysregs.mxcsr + +#define CPU_MSR_TSC CPU_STATSAVE.cpu_tsc + +#define CPU_CR0_PE (1 << 0) +#define CPU_CR0_MP (1 << 1) +#define CPU_CR0_EM (1 << 2) +#define CPU_CR0_TS (1 << 3) +#define CPU_CR0_ET (1 << 4) +#define CPU_CR0_NE (1 << 5) +#define CPU_CR0_WP (1 << 16) +#define CPU_CR0_AM (1 << 18) +#define CPU_CR0_NW (1 << 29) +#define CPU_CR0_CD (1 << 30) +#define CPU_CR0_PG (1 << 31) +#define CPU_CR0_ALL (CPU_CR0_PE|CPU_CR0_MP|CPU_CR0_EM|CPU_CR0_TS|CPU_CR0_ET|CPU_CR0_NE|CPU_CR0_WP|CPU_CR0_AM|CPU_CR0_NW|CPU_CR0_CD|CPU_CR0_PG) + +#define CPU_CR3_PD_MASK 0xfffff000 +#define CPU_CR3_PWT (1 << 3) +#define CPU_CR3_PCD (1 << 4) +#define CPU_CR3_MASK (CPU_CR3_PD_MASK|CPU_CR3_PWT|CPU_CR3_PCD) + +#define CPU_CR4_VME (1 << 0) +#define CPU_CR4_PVI (1 << 1) +#define CPU_CR4_TSD (1 << 2) +#define CPU_CR4_DE (1 << 3) +#define CPU_CR4_PSE (1 << 4) +#define CPU_CR4_PAE (1 << 5) +#define CPU_CR4_MCE (1 << 6) +#define CPU_CR4_PGE (1 << 7) +#define CPU_CR4_PCE (1 << 8) +#define CPU_CR4_OSFXSR (1 << 9) +#define CPU_CR4_OSXMMEXCPT (1 << 10) + +/* + * debug register + */ +#define CPU_DR(r) CPU_STATSAVE.cpu_regs.dr[(r)] +#define CPU_DR6 CPU_DR(6) +#define CPU_DR7 CPU_DR(7) + +#define CPU_STAT_BP CPU_STATSAVE.cpu_stat.bp +#define CPU_STAT_BP_EVENT CPU_STATSAVE.cpu_stat.bp_ev +#define CPU_STAT_BP_EVENT_B(r) (1 << (r)) +#define CPU_STAT_BP_EVENT_DR (1 << 4) /* fault */ +#define CPU_STAT_BP_EVENT_STEP (1 << 5) /* as CPU_TRAP */ +#define CPU_STAT_BP_EVENT_TASK (1 << 6) +#define CPU_STAT_BP_EVENT_RF (1 << 7) /* RF_FLAG */ + +#define CPU_DR6_B(r) (1 << (r)) +#define CPU_DR6_BD (1 << 13) +#define CPU_DR6_BS (1 << 14) +#define CPU_DR6_BT (1 << 15) + +#define CPU_DR7_L(r) (1 << ((r) * 2)) +#define CPU_DR7_G(r) (1 << ((r) * 2 + 1)) +#define CPU_DR7_LE (1 << 8) +#define CPU_DR7_GE (1 << 9) +#define CPU_DR7_GD (1 << 13) +#define CPU_DR7_RW(r) (3 << ((r) * 4 + 16)) +#define CPU_DR7_LEN(r) (3 << ((r) * 4 + 16 + 2)) + +#define CPU_DR7_GET_RW(r) ((CPU_DR7) >> (16 + (r) * 4)) +#define CPU_DR7_RW_CODE 0 +#define CPU_DR7_RW_RO 1 +#define CPU_DR7_RW_IO 2 +#define CPU_DR7_RW_RW 3 + +#define CPU_DR7_GET_LEN(r) ((CPU_DR7) >> (16 + 2 + (r) * 4)) + +void ia32_init(void); +void ia32_initreg(void); +void ia32_setextsize(UINT32 size); +void ia32_setemm(UINT frame, UINT32 addr); + +void ia32reset(void); +void ia32shut(void); +void ia32a20enable(BOOL enable); +void ia32(void); +void ia32_step(void); +void CPUCALL ia32_interrupt(int vect, int soft); + +void exec_1step(void); +void exec_allstep(void); +#define INST_PREFIX (1 << 0) +#define INST_STRING (1 << 1) +#define REP_CHECKZF (1 << 7) + +void ia32_printf(const char *buf, ...); +void ia32_warning(const char *buf, ...); +void ia32_panic(const char *buf, ...); + +void ia32_bioscall(void); + +void CPUCALL change_pm(BOOL onoff); +void CPUCALL change_vm(BOOL onoff); +void CPUCALL change_pg(BOOL onoff); + +void CPUCALL set_cr3(UINT32 new_cr3); +void CPUCALL set_cpl(int new_cpl); + +extern const UINT8 iflags[]; +#define szpcflag iflags +extern UINT8 szpflag_w[0x10000]; + +#if defined(USE_CPU_EIPMASK) +extern UINT32 cpu_eipMask; +#endif + +extern UINT8 *reg8_b20[0x100]; +extern UINT8 *reg8_b53[0x100]; +#if !defined(USE_CPU_DIRECTREG) +extern UINT16 *reg16_b20[0x100]; +extern UINT16 *reg16_b53[0x100]; +extern UINT32 *reg32_b20[0x100]; +extern UINT32 *reg32_b53[0x100]; +#endif + +extern const char *reg8_str[CPU_REG_NUM]; +extern const char *reg16_str[CPU_REG_NUM]; +extern const char *reg32_str[CPU_REG_NUM]; +extern const char *sreg_str[CPU_SEGREG_NUM]; + +char *cpu_reg2str(void); +#if defined(USE_FPU) +char *fpu_reg2str(void); +#endif +void put_cpuinfo(void); +void dbg_printf(const char *str, ...); + + +/* + * FPU + */ +#define FPU_REGS CPU_STATSAVE.fpu_regs +#define FPU_CTRLWORD FPU_REGS.control +#define FPU_CTRLWORDMASK FPU_REGS.cw_mask_all +#define FPU_STATUSWORD FPU_REGS.status +#define FPU_INSTPTR FPU_REGS.inst +#define FPU_DATAPTR FPU_REGS.data +#define FPU_LASTINSTOP FPU_REGS.op +#define FPU_INSTPTR_OFFSET FPU_REGS.inst.offset +#define FPU_INSTPTR_SEG FPU_REGS.inst.seg +#define FPU_DATAPTR_OFFSET FPU_REGS.data.offset +#define FPU_DATAPTR_SEG FPU_REGS.data.seg + +#define FPU_STAT CPU_STATSAVE.fpu_stat +#define FPU_STAT_TOP FPU_STAT.top +#define FPU_STAT_PC FPU_STAT.pc +#define FPU_STAT_RC FPU_STAT.rc + +/* + * SSE + */ +#ifdef USE_SSE +#define SSE_MXCSR CPU_MXCSR +#define SSE_XMMREG(i) FPU_STAT.xmm_reg[i] +#endif + +#if 0 +#define FPU_ST(i) FPU_STAT.reg[((i) + FPU_STAT_TOP) & 7] +#else +#define FPU_ST(i) ((FPU_STAT_TOP+ (i) ) & 7) +#endif +#define FPU_REG(i) FPU_STAT.reg[i] + +/* FPU status register */ +#define FP_IE_FLAG (1 << 0) /* 無効な動作 */ +#define FP_DE_FLAG (1 << 1) /* デノーマライズド・オペランド */ +#define FP_ZE_FLAG (1 << 2) /* ゼロによる除算 */ +#define FP_OE_FLAG (1 << 3) /* オーバーフロー */ +#define FP_UE_FLAG (1 << 4) /* アンダーフロー */ +#define FP_PE_FLAG (1 << 5) /* 精度 */ +#define FP_SF_FLAG (1 << 6) /* スタックフォルト */ +#define FP_ES_FLAG (1 << 7) /* エラーサマリステータス */ +#define FP_C0_FLAG (1 << 8) /* 条件コード */ +#define FP_C1_FLAG (1 << 9) /* 条件コード */ +#define FP_C2_FLAG (1 << 10) /* 条件コード */ +#define FP_TOP_FLAG (7 << 11) /* スタックポイントのトップ */ +#define FP_C3_FLAG (1 << 14) /* 条件コード */ +#define FP_B_FLAG (1 << 15) /* FPU ビジー */ + +#define FP_TOP_SHIFT 11 +#define FP_TOP_GET() ((FPU_STATUSWORD & FP_TOP_FLAG) >> FP_TOP_SHIFT) +#define FP_TOP_SET(v) \ +do { \ + FPU_STATUSWORD = ((FPU_STATUSWORD & ~FP_TOP_FLAG) | (((v) & 0x7) << FP_TOP_SHIFT)); \ +} while (/*CONSTCOND*/0) + +#define FPU_STAT_TOP_INC() \ +do { \ + FPU_STAT.top = (FPU_STAT.top + 1) & 7; \ +} while (/*CONSTCOND*/0) +#define FPU_STAT_TOP_DEC() \ +do { \ + FPU_STAT.top = (FPU_STAT.top - 1) & 7; \ +} while (/*CONSTCOND*/0) + +/* FPU control register */ +#define FP_CTRL_PC_SHIFT 8 /* 精度制御 */ +#define FP_CTRL_RC_SHIFT 10 /* 丸め制御 */ + +#define FP_CTRL_PC_24 0 /* 単精度 */ +#define FP_CTRL_PC_53 1 /* 倍精度 */ +#define FP_CTRL_PC_64 3 /* 拡張精度 */ + +#define FP_CTRL_RC_NEAREST_EVEN 0 +#define FP_CTRL_RC_DOWN 1 +#define FP_CTRL_RC_UP 2 +#define FP_CTRL_RC_TO_ZERO 3 + + +/* + * Misc. + */ +void memory_dump(int idx, UINT32 madr); +void gdtr_dump(UINT32 base, UINT limit); +void idtr_dump(UINT32 base, UINT limit); +void ldtr_dump(UINT32 base, UINT limit); +void tr_dump(UINT16 selector, UINT32 base, UINT limit); +UINT32 pde_dump(UINT32 base, int idx); +void segdesc_dump(descriptor_t *sdp); +UINT32 convert_laddr_to_paddr(UINT32 laddr); +UINT32 convert_vaddr_to_paddr(unsigned int idx, UINT32 offset); + +/* + * disasm + */ +/* context */ +typedef struct { + UINT32 val; + + UINT32 eip; + BOOL op32; + BOOL as32; + + UINT32 baseaddr; + UINT8 opcode[3]; + UINT8 modrm; + UINT8 sib; + + BOOL useseg; + int seg; + + UINT8 opbyte[32]; + int nopbytes; + + char str[256]; + size_t remain; + + char *next; + char *prefix; + char *op; + char *arg[3]; + int narg; + + char pad; +} disasm_context_t; + +int disasm(UINT32 *eip, disasm_context_t *ctx); +char *cpu_disasm2str(UINT32 eip); + +#ifdef __cplusplus +} +#endif + +#include "cpu_io.h" +#include "cpu_mem.h" +#include "exception.h" +#include "paging.h" +#include "resolve.h" +#include "task.h" + +#endif /* !IA32_CPU_CPU_H__ */ diff --git a/i386c/ia32/cpu_io.c b/i386c/ia32/cpu_io.c old mode 100755 new mode 100644 index 933d4397..a684ef74 --- a/i386c/ia32/cpu_io.c +++ b/i386c/ia32/cpu_io.c @@ -1,119 +1,119 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include - -#include "cpu.h" -#include -#include -#include "cpumem.h" - -static void CPUCALL check_io(UINT port, UINT len); - -static void CPUCALL -check_io(UINT port, UINT len) -{ - UINT off; - UINT16 map; - UINT16 mask; - - if (CPU_STAT_IOLIMIT == 0) { - VERBOSE(("check_io: CPU_STAT_IOLIMIT == 0 (port = %04x, len = %d)", port, len)); - EXCEPTION(GP_EXCEPTION, 0); - } - - if ((port + len) / 8 >= CPU_STAT_IOLIMIT) { - VERBOSE(("check_io: out of range: CPU_STAT_IOLIMIT(%08x) (port = %04x, len = %d)", CPU_STAT_IOLIMIT, port, len)); - EXCEPTION(GP_EXCEPTION, 0); - } - - off = port / 8; - mask = ((1 << len) - 1) << (port % 8); - map = cpu_kmemoryread_w(CPU_STAT_IOADDR + off); - if (map & mask) { - VERBOSE(("check_io: (bitmap(0x%04x) & bit(0x%04x)) != 0 (CPU_STAT_IOADDR=0x%08x, offset=0x%04x, port = 0x%04x, len = %d)", map, mask, CPU_STAT_IOADDR, off, port, len)); - EXCEPTION(GP_EXCEPTION, 0); - } -} - -UINT8 IOINPCALL -cpu_in(UINT port) -{ - - if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { - check_io(port, 1); - } - return iocore_inp8(port); -} - -UINT16 IOINPCALL -cpu_in_w(UINT port) -{ - - if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { - check_io(port, 2); - } - return iocore_inp16(port); -} - -UINT32 IOINPCALL -cpu_in_d(UINT port) -{ - - if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { - check_io(port, 4); - } - return iocore_inp32(port); -} - -void IOOUTCALL -cpu_out(UINT port, UINT8 data) -{ - - if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { - check_io(port, 1); - } - iocore_out8(port, data); -} - -void IOOUTCALL -cpu_out_w(UINT port, UINT16 data) -{ - - if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { - check_io(port, 2); - } - iocore_out16(port, data); -} - -void IOOUTCALL -cpu_out_d(UINT port, UINT32 data) -{ - - if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { - check_io(port, 4); - } - iocore_out32(port, data); -} +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include + +#include "cpu.h" +#include +#include +#include "cpumem.h" + +static void CPUCALL check_io(UINT port, UINT len); + +static void CPUCALL +check_io(UINT port, UINT len) +{ + UINT off; + UINT16 map; + UINT16 mask; + + if (CPU_STAT_IOLIMIT == 0) { + VERBOSE(("check_io: CPU_STAT_IOLIMIT == 0 (port = %04x, len = %d)", port, len)); + EXCEPTION(GP_EXCEPTION, 0); + } + + if ((port + len) / 8 >= CPU_STAT_IOLIMIT) { + VERBOSE(("check_io: out of range: CPU_STAT_IOLIMIT(%08x) (port = %04x, len = %d)", CPU_STAT_IOLIMIT, port, len)); + EXCEPTION(GP_EXCEPTION, 0); + } + + off = port / 8; + mask = ((1 << len) - 1) << (port % 8); + map = cpu_kmemoryread_w(CPU_STAT_IOADDR + off); + if (map & mask) { + VERBOSE(("check_io: (bitmap(0x%04x) & bit(0x%04x)) != 0 (CPU_STAT_IOADDR=0x%08x, offset=0x%04x, port = 0x%04x, len = %d)", map, mask, CPU_STAT_IOADDR, off, port, len)); + EXCEPTION(GP_EXCEPTION, 0); + } +} + +UINT8 IOINPCALL +cpu_in(UINT port) +{ + + if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { + check_io(port, 1); + } + return iocore_inp8(port); +} + +UINT16 IOINPCALL +cpu_in_w(UINT port) +{ + + if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { + check_io(port, 2); + } + return iocore_inp16(port); +} + +UINT32 IOINPCALL +cpu_in_d(UINT port) +{ + + if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { + check_io(port, 4); + } + return iocore_inp32(port); +} + +void IOOUTCALL +cpu_out(UINT port, UINT8 data) +{ + + if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { + check_io(port, 1); + } + iocore_out8(port, data); +} + +void IOOUTCALL +cpu_out_w(UINT port, UINT16 data) +{ + + if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { + check_io(port, 2); + } + iocore_out16(port, data); +} + +void IOOUTCALL +cpu_out_d(UINT port, UINT32 data) +{ + + if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL > CPU_STAT_IOPL))) { + check_io(port, 4); + } + iocore_out32(port, data); +} diff --git a/i386c/ia32/cpu_mem.c b/i386c/ia32/cpu_mem.c old mode 100755 new mode 100644 index f0d5e273..e4f7f4fe --- a/i386c/ia32/cpu_mem.c +++ b/i386c/ia32/cpu_mem.c @@ -1,608 +1,608 @@ -/* - * Copyright (c) 2002-2004 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" -#include "cpumem.h" - - -/* - * memory access check - */ -static int MEMCALL check_limit_upstairs(descriptor_t *sdp, UINT32 offset, UINT len, BOOL is32bit); -static void MEMCALL cpu_memoryread_check(descriptor_t *sdp, UINT32 offset, UINT len, int e); -static void MEMCALL cpu_memorywrite_check(descriptor_t *sdp, UINT32 offset, UINT len, int e); - -static int MEMCALL -check_limit_upstairs(descriptor_t *sdp, UINT32 offset, UINT len, BOOL is32bit) -{ - UINT32 limit; - UINT32 end; - - __ASSERT(sdp != NULL); - __ASSERT(len > 0); - - len--; - end = offset + len; - - if (SEG_IS_DATA(sdp) && SEG_IS_EXPANDDOWN_DATA(sdp)) { - /* expand-down data segment */ - limit = SEG_IS_32BIT(sdp) ? 0xffffffff : 0x0000ffff; - if (sdp->u.seg.limit == 0) { - /* - * 32bit 16bit - * +-------+ +-------+ FFFFFFFFh - * | | | | - * | | + [1] + 0000FFFFh - * | valid | | | - * | | +-------+ 0000FFFFh - len -1 - * | | | valid | - * +-------+ +-------+ 00000000h - */ - if (!SEG_IS_32BIT(sdp)) { - if ((len > limit) /* len check */ - || (end > limit)) { /* [1] */ - goto exc; - } - } else { - sdp->flag |= CPU_DESC_FLAG_WHOLEADR; - } - } else { - /* - * 32bit 16bit - * +-------+ +-------+ FFFFFFFFh - * | [2] | | | - * +-------+ +.......+ FFFFFFFFh - len - 1 - * | | | [2] | - * | | +.......+ 0000FFFFh - * | valid | | | - * | | +-------+ 0000FFFFh - len - 1 - * | | | valid | - * +-------+ +-------+ seg.limit - * | [1] | | [1] | - * +-------+ +-------+ 00000000h - */ - if ((len > limit - sdp->u.seg.limit) /* len check */ - || (end < offset) /* wrap check */ - || (offset < sdp->u.seg.limit) /* [1] */ - || (end > limit)) { /* [2] */ - goto exc; - } - } - } else { - /* expand-up data or code segment */ - if (sdp->u.seg.limit == 0xffffffff) { - /* - * 16/32bit - * +-------+ FFFFFFFFh - * | | - * | | - * | valid | - * | | - * | | - * +-------+ 00000000h - */ - sdp->flag |= CPU_DESC_FLAG_WHOLEADR; - } else { - /* - * 16/32bit - * +-------+ FFFFFFFFh - * | | - * | | - * | [1] | - * +.......+ seg.limit - * | | - * +-------+ seg.limit - len - 1 - * | valid | - * +-------+ 00000000h - */ - if ((len > sdp->u.seg.limit) /* len check */ - || (end < offset) /* wrap check */ - || (end > sdp->u.seg.limit + 1)) { /* [1] */ - goto exc; - } - } - } - return 1; /* Ok! */ - -exc: - VERBOSE(("check_limit_upstairs: check failure: offset = 0x%08x, len = %d", offset, len + 1)); -#if defined(DEBUG) - segdesc_dump(sdp); -#endif - return 0; -} - -static void MEMCALL -cpu_memoryread_check(descriptor_t *sdp, UINT32 offset, UINT len, int e) -{ - - __ASSERT(sdp != NULL); - __ASSERT(len > 0); - - if (!SEG_IS_VALID(sdp)) { - e = GP_EXCEPTION; - goto exc; - } - if (!SEG_IS_PRESENT(sdp) - || SEG_IS_SYSTEM(sdp) - || (SEG_IS_CODE(sdp) && !SEG_IS_READABLE_CODE(sdp))) { - goto exc; - } - - switch (sdp->type) { - case 0: case 1: /* ro */ - case 2: case 3: /* rw */ - case 4: case 5: /* ro (expand down) */ - case 6: case 7: /* rw (expand down) */ - case 10: case 11: /* rx */ - case 14: case 15: /* rxc */ - if (!check_limit_upstairs(sdp, offset, len, SEG_IS_32BIT(sdp))) - goto exc; - break; - - default: - goto exc; - } - sdp->flag |= CPU_DESC_FLAG_READABLE; - return; - -exc: - VERBOSE(("cpu_memoryread_check: check failure: offset = 0x%08x, len = %d", offset, len)); -#if defined(DEBUG) - segdesc_dump(sdp); -#endif - EXCEPTION(e, 0); -} - -static void MEMCALL -cpu_memorywrite_check(descriptor_t *sdp, UINT32 offset, UINT len, int e) -{ - - __ASSERT(sdp != NULL); - __ASSERT(len > 0); - - if (!SEG_IS_VALID(sdp)) { - e = GP_EXCEPTION; - goto exc; - } - if (!SEG_IS_PRESENT(sdp) - || SEG_IS_SYSTEM(sdp) - || SEG_IS_CODE(sdp) - || (SEG_IS_DATA(sdp) && !SEG_IS_WRITABLE_DATA(sdp))) { - goto exc; - } - - switch (sdp->type) { - case 2: case 3: /* rw */ - case 6: case 7: /* rw (expand down) */ - if (!check_limit_upstairs(sdp, offset, len, SEG_IS_32BIT(sdp))) - goto exc; - break; - - default: - goto exc; - } - sdp->flag |= CPU_DESC_FLAG_WRITABLE | CPU_DESC_FLAG_READABLE; - return; - -exc: - VERBOSE(("cpu_memorywrite_check: check failure: offset = 0x%08x, len = %d", offset, len)); -#if defined(DEBUG) - segdesc_dump(sdp); -#endif - EXCEPTION(e, 0); -} - -void MEMCALL -cpu_stack_push_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len, - BOOL is32bit) -{ - UINT32 limit; - UINT32 start; - - __ASSERT(sdp != NULL); - __ASSERT(len > 0); - - len--; - - if (!SEG_IS_VALID(sdp) - || !SEG_IS_PRESENT(sdp) - || SEG_IS_SYSTEM(sdp) - || SEG_IS_CODE(sdp) - || !SEG_IS_WRITABLE_DATA(sdp)) { - goto exc; - } - - //start = sp - len; - //limit = is32bit ? 0xffffffff : 0x0000ffff; - limit = is32bit ? 0xffffffff : 0x0000ffff; - sp = (sp - 1) & limit; - start = (sp - len) & limit; - - - if (SEG_IS_EXPANDDOWN_DATA(sdp)) { - /* expand-down stack */ - if (!SEG_IS_32BIT(sdp)) { - if (sp > limit) { /* [*] */ - goto exc; - } - } - if (sdp->u.seg.limit == 0) { - /* - * 32bit 16bit - * +-------+ +-------+ FFFFFFFFh - * | | | [*] | - * | | +-------+ 0000FFFFh - * | valid | | | - * | | | valid | - * | | | | - * +-------+ +-------+ 00000000h - */ - if (!SEG_IS_32BIT(sdp)) { - if (sp > limit) { /* [1] */ - goto exc; - } - } else { - sdp->flag |= CPU_DESC_FLAG_WHOLEADR; - } - } else { - /* - * 32bit 16bit - * +-------+ +-------+ FFFFFFFFh - * | | | [*] | - * | valid | +-------+ 0000FFFFh - * | | | valid | - * +-------+ +-------+ seg.limit + len - 1 - * | | | | - * +..[1]..+ +..[1]..+ seg.limit - * | | | | - * +-------+ +-------+ 00000000h - */ - if ((len > limit - sdp->u.seg.limit) /* len check */ - || (start > sp) /* wrap check */ - || (start < sdp->u.seg.limit)) { /* [1] */ - goto exc; - } - } - } else { - /* expand-up stack */ - if (sdp->u.seg.limit == limit) { - /* - * 32bit 16bit - * +-------+ +-------+ FFFFFFFFh - * | | | [1] | - * | | +-------+ 0000FFFFh - * | valid | | | - * | | | valid | - * | | | | - * +-------+ +-------+ 00000000h - */ - if (!SEG_IS_32BIT(sdp)) { - if (sp > limit) { /* [1] */ - goto exc; - } - } else { - sdp->flag |= CPU_DESC_FLAG_WHOLEADR; - } - } else { - /* - * 32bit 16bit - * +-------+ +-------+ FFFFFFFFh - * | | | | - * | [1] | + [1] + 0000FFFFh - * | | | | - * +-------+ +-------+ seg.limit - * | valid | | valid | - * +.......+ +.......+ len - 1 - * | [+] | | [+] | - * +-------+ +-------+ 00000000h - * - * [+]: wrap check - */ - if ((len > sdp->u.seg.limit) /* len check */ - || (start > sp) /* wrap check */ - || (sp > sdp->u.seg.limit + 1)) { /* [1] */ - goto exc; - } - } - } - return; - -exc: - VERBOSE(("cpu_stack_push_check: check failure: selector = 0x%04x, sp = 0x%08x, len = %d", s, sp, len)); -#if defined(DEBUG) - segdesc_dump(sdp); -#endif - EXCEPTION(SS_EXCEPTION, s & 0xfffc); -} - -void MEMCALL -cpu_stack_pop_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len, - BOOL is32bit) -{ - - __ASSERT(sdp != NULL); - __ASSERT(len > 0); - - if (!SEG_IS_VALID(sdp) - || !SEG_IS_PRESENT(sdp) - || SEG_IS_SYSTEM(sdp) - || SEG_IS_CODE(sdp) - || !SEG_IS_WRITABLE_DATA(sdp)) { - goto exc; - } - - if (!check_limit_upstairs(sdp, sp, len, is32bit)) - goto exc; - return; - -exc: - VERBOSE(("cpu_stack_pop_check: check failure: selector = 0x%04x, sp = 0x%08x, len = %d", s, sp, len)); -#if defined(DEBUG) - segdesc_dump(sdp); -#endif - EXCEPTION(SS_EXCEPTION, s & 0xfffc); -} - - -/* - * code fetch - */ -PF_UINT8 MEMCALL -cpu_codefetch(UINT32 offset) -{ - const int ucrw = CPU_PAGE_READ_CODE | CPU_STAT_USER_MODE; - descriptor_t *sdp; - UINT32 addr; - - sdp = &CPU_CS_DESC; - addr = sdp->u.seg.segbase + offset; - - if (!CPU_STAT_PM) - return cpu_memoryread_codefetch(addr); - if (offset <= sdp->u.seg.limit) - return cpu_lmemoryread_codefetch(addr, ucrw); - - EXCEPTION(GP_EXCEPTION, 0); - return 0; /* compiler happy */ -} - -PF_UINT16 MEMCALL -cpu_codefetch_w(UINT32 offset) -{ - const int ucrw = CPU_PAGE_READ_CODE | CPU_STAT_USER_MODE; - descriptor_t *sdp; - UINT32 addr; - - sdp = &CPU_CS_DESC; - addr = sdp->u.seg.segbase + offset; - - if (!CPU_STAT_PM) - return cpu_memoryread_w_codefetch(addr); - if (offset <= sdp->u.seg.limit - 1) - return cpu_lmemoryread_w_codefetch(addr, ucrw); - - EXCEPTION(GP_EXCEPTION, 0); - return 0; /* compiler happy */ -} - -PF_UINT32 MEMCALL -cpu_codefetch_d(UINT32 offset) -{ - const int ucrw = CPU_PAGE_READ_CODE | CPU_STAT_USER_MODE; - descriptor_t *sdp; - UINT32 addr; - - sdp = &CPU_CS_DESC; - addr = sdp->u.seg.segbase + offset; - - if (!CPU_STAT_PM) - return cpu_memoryread_d_codefetch(addr); - - if (offset <= sdp->u.seg.limit - 3) - return cpu_lmemoryread_d_codefetch(addr, ucrw); - - EXCEPTION(GP_EXCEPTION, 0); - return 0; /* compiler happy */ -} - -#if defined(USE_CPU_MODRMPREFETCH) -PF_UINT8 MEMCALL -cpu_opcodefetch(UINT32 offset) -{ - const int ucrw = CPU_PAGE_READ_CODE | CPU_STAT_USER_MODE; - UINT32 limit; - UINT32 addr; - UINT32 opcode; - - limit = CPU_CS_DESC.u.seg.limit; - addr = CPU_CS_DESC.u.seg.segbase + offset; - - if (!CPU_STAT_PM) - { - return (opCache = cpu_memoryread_w_codefetch(addr)) & 0xff; - } - opcode = cpu_lmemoryread_w_codefetch(addr, ucrw); - if (offset <= limit - 1) - { - // 2byteとも違反でない場合キャッシュする - opCache = opcode; - return opcode & 0xff; - } - else if (offset <= limit) - { - // 2バイト目がはみ出している場合、命令長によっては#GPなので1byteだけ読んでキャッシュはしない - opCache = 0; - return opcode & 0xff; - } - - EXCEPTION(GP_EXCEPTION, 0); - return 0; /* compiler happy */ -} -#endif - -/* - * additional physical address memory access functions - */ -UINT64 MEMCALL -cpu_memoryread_q(UINT32 paddr) -{ - UINT64 value; - - value = cpu_memoryread_d(paddr); - value += (UINT64)cpu_memoryread_d(paddr + 4) << 32; - - return value; -} - -void MEMCALL -cpu_memorywrite_q(UINT32 paddr, UINT64 value) -{ - - cpu_memorywrite_d(paddr, (UINT32)value); - cpu_memorywrite_d(paddr + 4, (UINT32)(value >> 32)); -} - -REG80 MEMCALL -cpu_memoryread_f(UINT32 paddr) -{ - REG80 value; - //int i; - - //for (i = 0; i < (int)sizeof(REG80); ++i) { - // value.b[i] = cpu_memoryread(paddr + i); - //} - value.d.l[0] = cpu_memoryread_d(paddr); - value.d.l[1] = cpu_memoryread_d(paddr + 4); - value.d.h = cpu_memoryread_w(paddr + 8); - - return value; -} - -void MEMCALL -cpu_memorywrite_f(UINT32 paddr, const REG80 *value) -{ - //int i; - - //for (i = 0; i < (int)sizeof(REG80); ++i) { - // cpu_memorywrite(paddr + i, value->b[i]); - //} - cpu_memorywrite_d(paddr, value->d.l[0]); - cpu_memorywrite_d(paddr + 4, value->d.l[1]); - cpu_memorywrite_w(paddr + 8, value->d.h); -} - -/* - * virtual address memory access functions - */ -#define CHOOSE_EXCEPTION(sreg) \ - (((sreg) == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION) - -#include "cpu_mem.mcr" - -DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(b, UINT8, 1) -DECLARE_VIRTUAL_ADDRESS_MEMORY_RMW_FUNCTIONS(b, UINT8, 1) -DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(w, UINT16, 2) -DECLARE_VIRTUAL_ADDRESS_MEMORY_RMW_FUNCTIONS(w, UINT16, 2) -DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(d, UINT32, 4) -DECLARE_VIRTUAL_ADDRESS_MEMORY_RMW_FUNCTIONS(d, UINT32, 4) -DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(q, UINT64, 8) - -REG80 MEMCALL -cpu_vmemoryread_f(int idx, UINT32 offset) -{ - descriptor_t *sdp; - UINT32 addr; - int exc; - - __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); - - sdp = &CPU_STAT_SREG(idx); - addr = sdp->u.seg.segbase + offset; - - if (!CPU_STAT_PM) - return cpu_memoryread_f(addr); - - if (!SEG_IS_VALID(sdp)) { - exc = GP_EXCEPTION; - goto err; - } - if (!(sdp->flag & CPU_DESC_FLAG_READABLE)) { - cpu_memoryread_check(sdp, offset, 10, CHOOSE_EXCEPTION(idx)); - } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { - if (!check_limit_upstairs(sdp, offset, 10, SEG_IS_32BIT(sdp))) - goto range_failure; - } - return cpu_lmemoryread_f(addr, CPU_PAGE_READ_DATA | CPU_STAT_USER_MODE); - -range_failure: - VERBOSE(("cpu_vmemoryread_f: type = %d, offset = %08x, limit = %08x", sdp->type, offset, sdp->u.seg.limit)); - exc = CHOOSE_EXCEPTION(idx); -err: - EXCEPTION(exc, 0); - { - REG80 dummy; - memset(&dummy, 0, sizeof(dummy)); - return dummy; /* compiler happy */ - } -} - -void MEMCALL -cpu_vmemorywrite_f(int idx, UINT32 offset, const REG80 *value) -{ - descriptor_t *sdp; - UINT32 addr; - int exc; - - __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); - - sdp = &CPU_STAT_SREG(idx); - addr = sdp->u.seg.segbase + offset; - - if (!CPU_STAT_PM) { - cpu_memorywrite_f(addr, value); - return; - } - - if (!SEG_IS_VALID(sdp)) { - exc = GP_EXCEPTION; - goto err; - } - if (!(sdp->flag & CPU_DESC_FLAG_WRITABLE)) { - cpu_memorywrite_check(sdp, offset, 10, CHOOSE_EXCEPTION(idx)); - } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { - if (!check_limit_upstairs(sdp, offset, 10, SEG_IS_32BIT(sdp))) - goto range_failure; - } - cpu_lmemorywrite_f(addr, value, CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE); - return; - -range_failure: - VERBOSE(("cpu_vmemorywrite_f: type = %d, offset = %08x, limit = %08x", sdp->type, offset, sdp->u.seg.limit)); - exc = CHOOSE_EXCEPTION(idx); -err: - EXCEPTION(exc, 0); -} +/* + * Copyright (c) 2002-2004 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" +#include "cpumem.h" + + +/* + * memory access check + */ +static int MEMCALL check_limit_upstairs(descriptor_t *sdp, UINT32 offset, UINT len, BOOL is32bit); +static void MEMCALL cpu_memoryread_check(descriptor_t *sdp, UINT32 offset, UINT len, int e); +static void MEMCALL cpu_memorywrite_check(descriptor_t *sdp, UINT32 offset, UINT len, int e); + +static int MEMCALL +check_limit_upstairs(descriptor_t *sdp, UINT32 offset, UINT len, BOOL is32bit) +{ + UINT32 limit; + UINT32 end; + + __ASSERT(sdp != NULL); + __ASSERT(len > 0); + + len--; + end = offset + len; + + if (SEG_IS_DATA(sdp) && SEG_IS_EXPANDDOWN_DATA(sdp)) { + /* expand-down data segment */ + limit = SEG_IS_32BIT(sdp) ? 0xffffffff : 0x0000ffff; + if (sdp->u.seg.limit == 0) { + /* + * 32bit 16bit + * +-------+ +-------+ FFFFFFFFh + * | | | | + * | | + [1] + 0000FFFFh + * | valid | | | + * | | +-------+ 0000FFFFh - len -1 + * | | | valid | + * +-------+ +-------+ 00000000h + */ + if (!SEG_IS_32BIT(sdp)) { + if ((len > limit) /* len check */ + || (end > limit)) { /* [1] */ + goto exc; + } + } else { + sdp->flag |= CPU_DESC_FLAG_WHOLEADR; + } + } else { + /* + * 32bit 16bit + * +-------+ +-------+ FFFFFFFFh + * | [2] | | | + * +-------+ +.......+ FFFFFFFFh - len - 1 + * | | | [2] | + * | | +.......+ 0000FFFFh + * | valid | | | + * | | +-------+ 0000FFFFh - len - 1 + * | | | valid | + * +-------+ +-------+ seg.limit + * | [1] | | [1] | + * +-------+ +-------+ 00000000h + */ + if ((len > limit - sdp->u.seg.limit) /* len check */ + || (end < offset) /* wrap check */ + || (offset < sdp->u.seg.limit) /* [1] */ + || (end > limit)) { /* [2] */ + goto exc; + } + } + } else { + /* expand-up data or code segment */ + if (sdp->u.seg.limit == 0xffffffff) { + /* + * 16/32bit + * +-------+ FFFFFFFFh + * | | + * | | + * | valid | + * | | + * | | + * +-------+ 00000000h + */ + sdp->flag |= CPU_DESC_FLAG_WHOLEADR; + } else { + /* + * 16/32bit + * +-------+ FFFFFFFFh + * | | + * | | + * | [1] | + * +.......+ seg.limit + * | | + * +-------+ seg.limit - len - 1 + * | valid | + * +-------+ 00000000h + */ + if ((len > sdp->u.seg.limit) /* len check */ + || (end < offset) /* wrap check */ + || (end > sdp->u.seg.limit + 1)) { /* [1] */ + goto exc; + } + } + } + return 1; /* Ok! */ + +exc: + VERBOSE(("check_limit_upstairs: check failure: offset = 0x%08x, len = %d", offset, len + 1)); +#if defined(DEBUG) + segdesc_dump(sdp); +#endif + return 0; +} + +static void MEMCALL +cpu_memoryread_check(descriptor_t *sdp, UINT32 offset, UINT len, int e) +{ + + __ASSERT(sdp != NULL); + __ASSERT(len > 0); + + if (!SEG_IS_VALID(sdp)) { + e = GP_EXCEPTION; + goto exc; + } + if (!SEG_IS_PRESENT(sdp) + || SEG_IS_SYSTEM(sdp) + || (SEG_IS_CODE(sdp) && !SEG_IS_READABLE_CODE(sdp))) { + goto exc; + } + + switch (sdp->type) { + case 0: case 1: /* ro */ + case 2: case 3: /* rw */ + case 4: case 5: /* ro (expand down) */ + case 6: case 7: /* rw (expand down) */ + case 10: case 11: /* rx */ + case 14: case 15: /* rxc */ + if (!check_limit_upstairs(sdp, offset, len, SEG_IS_32BIT(sdp))) + goto exc; + break; + + default: + goto exc; + } + sdp->flag |= CPU_DESC_FLAG_READABLE; + return; + +exc: + VERBOSE(("cpu_memoryread_check: check failure: offset = 0x%08x, len = %d", offset, len)); +#if defined(DEBUG) + segdesc_dump(sdp); +#endif + EXCEPTION(e, 0); +} + +static void MEMCALL +cpu_memorywrite_check(descriptor_t *sdp, UINT32 offset, UINT len, int e) +{ + + __ASSERT(sdp != NULL); + __ASSERT(len > 0); + + if (!SEG_IS_VALID(sdp)) { + e = GP_EXCEPTION; + goto exc; + } + if (!SEG_IS_PRESENT(sdp) + || SEG_IS_SYSTEM(sdp) + || SEG_IS_CODE(sdp) + || (SEG_IS_DATA(sdp) && !SEG_IS_WRITABLE_DATA(sdp))) { + goto exc; + } + + switch (sdp->type) { + case 2: case 3: /* rw */ + case 6: case 7: /* rw (expand down) */ + if (!check_limit_upstairs(sdp, offset, len, SEG_IS_32BIT(sdp))) + goto exc; + break; + + default: + goto exc; + } + sdp->flag |= CPU_DESC_FLAG_WRITABLE | CPU_DESC_FLAG_READABLE; + return; + +exc: + VERBOSE(("cpu_memorywrite_check: check failure: offset = 0x%08x, len = %d", offset, len)); +#if defined(DEBUG) + segdesc_dump(sdp); +#endif + EXCEPTION(e, 0); +} + +void MEMCALL +cpu_stack_push_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len, + BOOL is32bit) +{ + UINT32 limit; + UINT32 start; + + __ASSERT(sdp != NULL); + __ASSERT(len > 0); + + len--; + + if (!SEG_IS_VALID(sdp) + || !SEG_IS_PRESENT(sdp) + || SEG_IS_SYSTEM(sdp) + || SEG_IS_CODE(sdp) + || !SEG_IS_WRITABLE_DATA(sdp)) { + goto exc; + } + + //start = sp - len; + //limit = is32bit ? 0xffffffff : 0x0000ffff; + limit = is32bit ? 0xffffffff : 0x0000ffff; + sp = (sp - 1) & limit; + start = (sp - len) & limit; + + + if (SEG_IS_EXPANDDOWN_DATA(sdp)) { + /* expand-down stack */ + if (!SEG_IS_32BIT(sdp)) { + if (sp > limit) { /* [*] */ + goto exc; + } + } + if (sdp->u.seg.limit == 0) { + /* + * 32bit 16bit + * +-------+ +-------+ FFFFFFFFh + * | | | [*] | + * | | +-------+ 0000FFFFh + * | valid | | | + * | | | valid | + * | | | | + * +-------+ +-------+ 00000000h + */ + if (!SEG_IS_32BIT(sdp)) { + if (sp > limit) { /* [1] */ + goto exc; + } + } else { + sdp->flag |= CPU_DESC_FLAG_WHOLEADR; + } + } else { + /* + * 32bit 16bit + * +-------+ +-------+ FFFFFFFFh + * | | | [*] | + * | valid | +-------+ 0000FFFFh + * | | | valid | + * +-------+ +-------+ seg.limit + len - 1 + * | | | | + * +..[1]..+ +..[1]..+ seg.limit + * | | | | + * +-------+ +-------+ 00000000h + */ + if ((len > limit - sdp->u.seg.limit) /* len check */ + || (start > sp) /* wrap check */ + || (start < sdp->u.seg.limit)) { /* [1] */ + goto exc; + } + } + } else { + /* expand-up stack */ + if (sdp->u.seg.limit == limit) { + /* + * 32bit 16bit + * +-------+ +-------+ FFFFFFFFh + * | | | [1] | + * | | +-------+ 0000FFFFh + * | valid | | | + * | | | valid | + * | | | | + * +-------+ +-------+ 00000000h + */ + if (!SEG_IS_32BIT(sdp)) { + if (sp > limit) { /* [1] */ + goto exc; + } + } else { + sdp->flag |= CPU_DESC_FLAG_WHOLEADR; + } + } else { + /* + * 32bit 16bit + * +-------+ +-------+ FFFFFFFFh + * | | | | + * | [1] | + [1] + 0000FFFFh + * | | | | + * +-------+ +-------+ seg.limit + * | valid | | valid | + * +.......+ +.......+ len - 1 + * | [+] | | [+] | + * +-------+ +-------+ 00000000h + * + * [+]: wrap check + */ + if ((len > sdp->u.seg.limit) /* len check */ + || (start > sp) /* wrap check */ + || (sp > sdp->u.seg.limit + 1)) { /* [1] */ + goto exc; + } + } + } + return; + +exc: + VERBOSE(("cpu_stack_push_check: check failure: selector = 0x%04x, sp = 0x%08x, len = %d", s, sp, len)); +#if defined(DEBUG) + segdesc_dump(sdp); +#endif + EXCEPTION(SS_EXCEPTION, s & 0xfffc); +} + +void MEMCALL +cpu_stack_pop_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len, + BOOL is32bit) +{ + + __ASSERT(sdp != NULL); + __ASSERT(len > 0); + + if (!SEG_IS_VALID(sdp) + || !SEG_IS_PRESENT(sdp) + || SEG_IS_SYSTEM(sdp) + || SEG_IS_CODE(sdp) + || !SEG_IS_WRITABLE_DATA(sdp)) { + goto exc; + } + + if (!check_limit_upstairs(sdp, sp, len, is32bit)) + goto exc; + return; + +exc: + VERBOSE(("cpu_stack_pop_check: check failure: selector = 0x%04x, sp = 0x%08x, len = %d", s, sp, len)); +#if defined(DEBUG) + segdesc_dump(sdp); +#endif + EXCEPTION(SS_EXCEPTION, s & 0xfffc); +} + + +/* + * code fetch + */ +PF_UINT8 MEMCALL +cpu_codefetch(UINT32 offset) +{ + const int ucrw = CPU_PAGE_READ_CODE | CPU_STAT_USER_MODE; + descriptor_t *sdp; + UINT32 addr; + + sdp = &CPU_CS_DESC; + addr = sdp->u.seg.segbase + offset; + + if (!CPU_STAT_PM) + return cpu_memoryread_codefetch(addr); + if (offset <= sdp->u.seg.limit) + return cpu_lmemoryread_codefetch(addr, ucrw); + + EXCEPTION(GP_EXCEPTION, 0); + return 0; /* compiler happy */ +} + +PF_UINT16 MEMCALL +cpu_codefetch_w(UINT32 offset) +{ + const int ucrw = CPU_PAGE_READ_CODE | CPU_STAT_USER_MODE; + descriptor_t *sdp; + UINT32 addr; + + sdp = &CPU_CS_DESC; + addr = sdp->u.seg.segbase + offset; + + if (!CPU_STAT_PM) + return cpu_memoryread_w_codefetch(addr); + if (offset <= sdp->u.seg.limit - 1) + return cpu_lmemoryread_w_codefetch(addr, ucrw); + + EXCEPTION(GP_EXCEPTION, 0); + return 0; /* compiler happy */ +} + +PF_UINT32 MEMCALL +cpu_codefetch_d(UINT32 offset) +{ + const int ucrw = CPU_PAGE_READ_CODE | CPU_STAT_USER_MODE; + descriptor_t *sdp; + UINT32 addr; + + sdp = &CPU_CS_DESC; + addr = sdp->u.seg.segbase + offset; + + if (!CPU_STAT_PM) + return cpu_memoryread_d_codefetch(addr); + + if (offset <= sdp->u.seg.limit - 3) + return cpu_lmemoryread_d_codefetch(addr, ucrw); + + EXCEPTION(GP_EXCEPTION, 0); + return 0; /* compiler happy */ +} + +#if defined(USE_CPU_MODRMPREFETCH) +PF_UINT8 MEMCALL +cpu_opcodefetch(UINT32 offset) +{ + const int ucrw = CPU_PAGE_READ_CODE | CPU_STAT_USER_MODE; + UINT32 limit; + UINT32 addr; + UINT32 opcode; + + limit = CPU_CS_DESC.u.seg.limit; + addr = CPU_CS_DESC.u.seg.segbase + offset; + + if (!CPU_STAT_PM) + { + return (opCache = cpu_memoryread_w_codefetch(addr)) & 0xff; + } + opcode = cpu_lmemoryread_w_codefetch(addr, ucrw); + if (offset <= limit - 1) + { + // 2byteとも違反でない場合キャッシュする + opCache = opcode; + return opcode & 0xff; + } + else if (offset <= limit) + { + // 2バイト目がはみ出している場合、命令長によっては#GPなので1byteだけ読んでキャッシュはしない + opCache = 0; + return opcode & 0xff; + } + + EXCEPTION(GP_EXCEPTION, 0); + return 0; /* compiler happy */ +} +#endif + +/* + * additional physical address memory access functions + */ +UINT64 MEMCALL +cpu_memoryread_q(UINT32 paddr) +{ + UINT64 value; + + value = cpu_memoryread_d(paddr); + value += (UINT64)cpu_memoryread_d(paddr + 4) << 32; + + return value; +} + +void MEMCALL +cpu_memorywrite_q(UINT32 paddr, UINT64 value) +{ + + cpu_memorywrite_d(paddr, (UINT32)value); + cpu_memorywrite_d(paddr + 4, (UINT32)(value >> 32)); +} + +REG80 MEMCALL +cpu_memoryread_f(UINT32 paddr) +{ + REG80 value; + //int i; + + //for (i = 0; i < (int)sizeof(REG80); ++i) { + // value.b[i] = cpu_memoryread(paddr + i); + //} + value.d.l[0] = cpu_memoryread_d(paddr); + value.d.l[1] = cpu_memoryread_d(paddr + 4); + value.d.h = cpu_memoryread_w(paddr + 8); + + return value; +} + +void MEMCALL +cpu_memorywrite_f(UINT32 paddr, const REG80 *value) +{ + //int i; + + //for (i = 0; i < (int)sizeof(REG80); ++i) { + // cpu_memorywrite(paddr + i, value->b[i]); + //} + cpu_memorywrite_d(paddr, value->d.l[0]); + cpu_memorywrite_d(paddr + 4, value->d.l[1]); + cpu_memorywrite_w(paddr + 8, value->d.h); +} + +/* + * virtual address memory access functions + */ +#define CHOOSE_EXCEPTION(sreg) \ + (((sreg) == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION) + +#include "cpu_mem.mcr" + +DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(b, UINT8, 1) +DECLARE_VIRTUAL_ADDRESS_MEMORY_RMW_FUNCTIONS(b, UINT8, 1) +DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(w, UINT16, 2) +DECLARE_VIRTUAL_ADDRESS_MEMORY_RMW_FUNCTIONS(w, UINT16, 2) +DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(d, UINT32, 4) +DECLARE_VIRTUAL_ADDRESS_MEMORY_RMW_FUNCTIONS(d, UINT32, 4) +DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(q, UINT64, 8) + +REG80 MEMCALL +cpu_vmemoryread_f(int idx, UINT32 offset) +{ + descriptor_t *sdp; + UINT32 addr; + int exc; + + __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); + + sdp = &CPU_STAT_SREG(idx); + addr = sdp->u.seg.segbase + offset; + + if (!CPU_STAT_PM) + return cpu_memoryread_f(addr); + + if (!SEG_IS_VALID(sdp)) { + exc = GP_EXCEPTION; + goto err; + } + if (!(sdp->flag & CPU_DESC_FLAG_READABLE)) { + cpu_memoryread_check(sdp, offset, 10, CHOOSE_EXCEPTION(idx)); + } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { + if (!check_limit_upstairs(sdp, offset, 10, SEG_IS_32BIT(sdp))) + goto range_failure; + } + return cpu_lmemoryread_f(addr, CPU_PAGE_READ_DATA | CPU_STAT_USER_MODE); + +range_failure: + VERBOSE(("cpu_vmemoryread_f: type = %d, offset = %08x, limit = %08x", sdp->type, offset, sdp->u.seg.limit)); + exc = CHOOSE_EXCEPTION(idx); +err: + EXCEPTION(exc, 0); + { + REG80 dummy; + memset(&dummy, 0, sizeof(dummy)); + return dummy; /* compiler happy */ + } +} + +void MEMCALL +cpu_vmemorywrite_f(int idx, UINT32 offset, const REG80 *value) +{ + descriptor_t *sdp; + UINT32 addr; + int exc; + + __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); + + sdp = &CPU_STAT_SREG(idx); + addr = sdp->u.seg.segbase + offset; + + if (!CPU_STAT_PM) { + cpu_memorywrite_f(addr, value); + return; + } + + if (!SEG_IS_VALID(sdp)) { + exc = GP_EXCEPTION; + goto err; + } + if (!(sdp->flag & CPU_DESC_FLAG_WRITABLE)) { + cpu_memorywrite_check(sdp, offset, 10, CHOOSE_EXCEPTION(idx)); + } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { + if (!check_limit_upstairs(sdp, offset, 10, SEG_IS_32BIT(sdp))) + goto range_failure; + } + cpu_lmemorywrite_f(addr, value, CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE); + return; + +range_failure: + VERBOSE(("cpu_vmemorywrite_f: type = %d, offset = %08x, limit = %08x", sdp->type, offset, sdp->u.seg.limit)); + exc = CHOOSE_EXCEPTION(idx); +err: + EXCEPTION(exc, 0); +} diff --git a/i386c/ia32/cpu_mem.h b/i386c/ia32/cpu_mem.h old mode 100755 new mode 100644 index d47f6fda..360ad8d4 --- a/i386c/ia32/cpu_mem.h +++ b/i386c/ia32/cpu_mem.h @@ -1,91 +1,91 @@ -/* - * Copyright (c) 2002-2004 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_CPU_MEM_H__ -#define IA32_CPU_CPU_MEM_H__ - -#include "cpumem.h" -#include "segments.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * memory access check - */ -void MEMCALL cpu_stack_push_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len, BOOL is32bit); -void MEMCALL cpu_stack_pop_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len, BOOL is32bit); -#define SS_PUSH_CHECK1(sp, len, is32bit) \ - cpu_stack_push_check(CPU_SS_INDEX, &CPU_SS_DESC, (sp), (len), (is32bit)) -#define SS_POP_CHECK1(sp, len, is32bit) \ - cpu_stack_pop_check(CPU_SS_INDEX, &CPU_SS_DESC, (sp), (len), (is32bit)) -#define SS_PUSH_CHECK(sp, len) \ - SS_PUSH_CHECK1((sp), (len), CPU_SS_DESC.d) -#define SS_POP_CHECK(sp, len) \ - SS_POP_CHECK1((sp), (len), CPU_SS_DESC.d) - -/* - * virtual address function - */ -void MEMCALL cpu_vmemorywrite_b(int idx, UINT32 offset, UINT8 value); -#define cpu_vmemorywrite(i,o,v) cpu_vmemorywrite_b(i,o,v) -void MEMCALL cpu_vmemorywrite_w(int idx, UINT32 offset, UINT16 value); -void MEMCALL cpu_vmemorywrite_d(int idx, UINT32 offset, UINT32 value); -void MEMCALL cpu_vmemorywrite_q(int idx, UINT32 offset, UINT64 value); -void MEMCALL cpu_vmemorywrite_f(int idx, UINT32 offset, const REG80 *value); -UINT8 MEMCALL cpu_vmemoryread_b(int idx, UINT32 offset); -#define cpu_vmemoryread(i,o) cpu_vmemoryread_b(i,o) -UINT16 MEMCALL cpu_vmemoryread_w(int idx, UINT32 offset); -UINT32 MEMCALL cpu_vmemoryread_d(int idx, UINT32 offset); -UINT64 MEMCALL cpu_vmemoryread_q(int idx, UINT32 offset); -REG80 MEMCALL cpu_vmemoryread_f(int idx, UINT32 offset); -UINT32 MEMCALL cpu_vmemory_RMW_b(int idx, UINT32 offset, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); -UINT32 MEMCALL cpu_vmemory_RMW_w(int idx, UINT32 offset, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); -UINT32 MEMCALL cpu_vmemory_RMW_d(int idx, UINT32 offset, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); - -/* - * code fetch - */ -PF_UINT8 MEMCALL cpu_codefetch(UINT32 offset); -PF_UINT16 MEMCALL cpu_codefetch_w(UINT32 offset); -PF_UINT32 MEMCALL cpu_codefetch_d(UINT32 offset); -#if defined(USE_CPU_MODRMPREFETCH) -PF_UINT8 MEMCALL cpu_opcodefetch(UINT32 offset); -#endif - -/* - * additional physical address function - */ -UINT64 MEMCALL cpu_memoryread_q(UINT32 paddr); -REG80 MEMCALL cpu_memoryread_f(UINT32 paddr); -void MEMCALL cpu_memorywrite_q(UINT32 paddr, UINT64 value); -void MEMCALL cpu_memorywrite_f(UINT32 paddr, const REG80 *value); - -#ifdef __cplusplus -} -#endif - -#endif /* !IA32_CPU_CPU_MEM_H__ */ +/* + * Copyright (c) 2002-2004 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_CPU_MEM_H__ +#define IA32_CPU_CPU_MEM_H__ + +#include "cpumem.h" +#include "segments.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * memory access check + */ +void MEMCALL cpu_stack_push_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len, BOOL is32bit); +void MEMCALL cpu_stack_pop_check(UINT16 s, descriptor_t *sdp, UINT32 sp, UINT len, BOOL is32bit); +#define SS_PUSH_CHECK1(sp, len, is32bit) \ + cpu_stack_push_check(CPU_SS_INDEX, &CPU_SS_DESC, (sp), (len), (is32bit)) +#define SS_POP_CHECK1(sp, len, is32bit) \ + cpu_stack_pop_check(CPU_SS_INDEX, &CPU_SS_DESC, (sp), (len), (is32bit)) +#define SS_PUSH_CHECK(sp, len) \ + SS_PUSH_CHECK1((sp), (len), CPU_SS_DESC.d) +#define SS_POP_CHECK(sp, len) \ + SS_POP_CHECK1((sp), (len), CPU_SS_DESC.d) + +/* + * virtual address function + */ +void MEMCALL cpu_vmemorywrite_b(int idx, UINT32 offset, UINT8 value); +#define cpu_vmemorywrite(i,o,v) cpu_vmemorywrite_b(i,o,v) +void MEMCALL cpu_vmemorywrite_w(int idx, UINT32 offset, UINT16 value); +void MEMCALL cpu_vmemorywrite_d(int idx, UINT32 offset, UINT32 value); +void MEMCALL cpu_vmemorywrite_q(int idx, UINT32 offset, UINT64 value); +void MEMCALL cpu_vmemorywrite_f(int idx, UINT32 offset, const REG80 *value); +UINT8 MEMCALL cpu_vmemoryread_b(int idx, UINT32 offset); +#define cpu_vmemoryread(i,o) cpu_vmemoryread_b(i,o) +UINT16 MEMCALL cpu_vmemoryread_w(int idx, UINT32 offset); +UINT32 MEMCALL cpu_vmemoryread_d(int idx, UINT32 offset); +UINT64 MEMCALL cpu_vmemoryread_q(int idx, UINT32 offset); +REG80 MEMCALL cpu_vmemoryread_f(int idx, UINT32 offset); +UINT32 MEMCALL cpu_vmemory_RMW_b(int idx, UINT32 offset, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); +UINT32 MEMCALL cpu_vmemory_RMW_w(int idx, UINT32 offset, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); +UINT32 MEMCALL cpu_vmemory_RMW_d(int idx, UINT32 offset, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); + +/* + * code fetch + */ +PF_UINT8 MEMCALL cpu_codefetch(UINT32 offset); +PF_UINT16 MEMCALL cpu_codefetch_w(UINT32 offset); +PF_UINT32 MEMCALL cpu_codefetch_d(UINT32 offset); +#if defined(USE_CPU_MODRMPREFETCH) +PF_UINT8 MEMCALL cpu_opcodefetch(UINT32 offset); +#endif + +/* + * additional physical address function + */ +UINT64 MEMCALL cpu_memoryread_q(UINT32 paddr); +REG80 MEMCALL cpu_memoryread_f(UINT32 paddr); +void MEMCALL cpu_memorywrite_q(UINT32 paddr, UINT64 value); +void MEMCALL cpu_memorywrite_f(UINT32 paddr, const REG80 *value); + +#ifdef __cplusplus +} +#endif + +#endif /* !IA32_CPU_CPU_MEM_H__ */ diff --git a/i386c/ia32/cpu_mem.mcr b/i386c/ia32/cpu_mem.mcr old mode 100755 new mode 100644 index 336325fb..f46cb3aa --- a/i386c/ia32/cpu_mem.mcr +++ b/i386c/ia32/cpu_mem.mcr @@ -1,142 +1,142 @@ -/* - * Copyright (c) 2004 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#define DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(width, valtype, length) \ -valtype MEMCALL \ -cpu_vmemoryread_##width(int idx, UINT32 offset) \ -{ \ - descriptor_t *sdp; \ - UINT32 addr; \ - int exc; \ -\ - __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); \ -\ - sdp = &CPU_STAT_SREG(idx); \ - addr = sdp->u.seg.segbase + offset; \ -\ - if (!CPU_STAT_PM) \ - return cpu_memoryread_##width(addr); \ -\ - if (!SEG_IS_VALID(sdp)) { \ - exc = GP_EXCEPTION; \ - goto err; \ - } \ - if (!(sdp->flag & CPU_DESC_FLAG_READABLE)) { \ - cpu_memoryread_check(sdp, offset, (length), \ - CHOOSE_EXCEPTION(idx)); \ - } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { \ - if (!check_limit_upstairs(sdp, offset, (length), SEG_IS_32BIT(sdp))) \ - goto range_failure; \ - } \ - return cpu_lmemoryread_##width(addr, CPU_PAGE_READ_DATA | CPU_STAT_USER_MODE); \ -\ -range_failure: \ - VERBOSE(("cpu_vmemoryread_" #width ": type = %d, offset = %08x, length = %d, limit = %08x", sdp->type, offset, length, sdp->u.seg.limit)); \ - exc = CHOOSE_EXCEPTION(idx); \ -err: \ - EXCEPTION(exc, 0); \ - return 0; /* compiler happy */ \ -} \ -\ -void MEMCALL \ -cpu_vmemorywrite_##width(int idx, UINT32 offset, valtype value) \ -{ \ - descriptor_t *sdp; \ - UINT32 addr; \ - int exc; \ -\ - __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); \ -\ - sdp = &CPU_STAT_SREG(idx); \ - addr = sdp->u.seg.segbase + offset; \ -\ - if (!CPU_STAT_PM) { \ - cpu_memorywrite_##width(addr, value); \ - return; \ - } \ -\ - if (!SEG_IS_VALID(sdp)) { \ - exc = GP_EXCEPTION; \ - goto err; \ - } \ - if (!(sdp->flag & CPU_DESC_FLAG_WRITABLE)) { \ - cpu_memorywrite_check(sdp, offset, (length), \ - CHOOSE_EXCEPTION(idx)); \ - } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { \ - if (!check_limit_upstairs(sdp, offset, (length), SEG_IS_32BIT(sdp))) \ - goto range_failure; \ - } \ - cpu_lmemorywrite_##width(addr, value, CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE); \ - return; \ -\ -range_failure: \ - VERBOSE(("cpu_vmemorywrite_" #width ": type = %d, offset = %08x, length = %d, limit = %08x", sdp->type, offset, length, sdp->u.seg.limit)); \ - exc = CHOOSE_EXCEPTION(idx); \ -err: \ - EXCEPTION(exc, 0); \ -} - -#define DECLARE_VIRTUAL_ADDRESS_MEMORY_RMW_FUNCTIONS(width, valtype, length) \ -UINT32 MEMCALL \ -cpu_vmemory_RMW_##width(int idx, UINT32 offset, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) \ -{ \ - descriptor_t *sdp; \ - UINT32 addr; \ - UINT32 result; \ - valtype value; \ - int exc; \ -\ - __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); \ -\ - sdp = &CPU_STAT_SREG(idx); \ - addr = sdp->u.seg.segbase + offset; \ -\ - if (!CPU_STAT_PM) { \ - value = cpu_memoryread_##width(addr); \ - result = (*func)(value, arg); \ - cpu_memorywrite_##width(addr, (valtype)result); \ - return value; \ - } \ -\ - if (!SEG_IS_VALID(sdp)) { \ - exc = GP_EXCEPTION; \ - goto err; \ - } \ - if (!(sdp->flag & CPU_DESC_FLAG_WRITABLE)) { \ - cpu_memorywrite_check(sdp, offset, (length), \ - CHOOSE_EXCEPTION(idx)); \ - } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { \ - if (!check_limit_upstairs(sdp, offset, (length), SEG_IS_32BIT(sdp))) \ - goto range_failure; \ - } \ - return cpu_lmemory_RMW_##width(addr, func, arg); \ -\ -range_failure: \ - VERBOSE(("cpu_vmemory_RMW_" #width ": type = %d, offset = %08x, length = %d, limit = %08x", sdp->type, offset, length, sdp->u.seg.limit)); \ - exc = CHOOSE_EXCEPTION(idx); \ -err: \ - EXCEPTION(exc, 0); \ - return 0; /* compiler happy */ \ -} +/* + * Copyright (c) 2004 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#define DECLARE_VIRTUAL_ADDRESS_MEMORY_RW_FUNCTIONS(width, valtype, length) \ +valtype MEMCALL \ +cpu_vmemoryread_##width(int idx, UINT32 offset) \ +{ \ + descriptor_t *sdp; \ + UINT32 addr; \ + int exc; \ +\ + __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); \ +\ + sdp = &CPU_STAT_SREG(idx); \ + addr = sdp->u.seg.segbase + offset; \ +\ + if (!CPU_STAT_PM) \ + return cpu_memoryread_##width(addr); \ +\ + if (!SEG_IS_VALID(sdp)) { \ + exc = GP_EXCEPTION; \ + goto err; \ + } \ + if (!(sdp->flag & CPU_DESC_FLAG_READABLE)) { \ + cpu_memoryread_check(sdp, offset, (length), \ + CHOOSE_EXCEPTION(idx)); \ + } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { \ + if (!check_limit_upstairs(sdp, offset, (length), SEG_IS_32BIT(sdp))) \ + goto range_failure; \ + } \ + return cpu_lmemoryread_##width(addr, CPU_PAGE_READ_DATA | CPU_STAT_USER_MODE); \ +\ +range_failure: \ + VERBOSE(("cpu_vmemoryread_" #width ": type = %d, offset = %08x, length = %d, limit = %08x", sdp->type, offset, length, sdp->u.seg.limit)); \ + exc = CHOOSE_EXCEPTION(idx); \ +err: \ + EXCEPTION(exc, 0); \ + return 0; /* compiler happy */ \ +} \ +\ +void MEMCALL \ +cpu_vmemorywrite_##width(int idx, UINT32 offset, valtype value) \ +{ \ + descriptor_t *sdp; \ + UINT32 addr; \ + int exc; \ +\ + __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); \ +\ + sdp = &CPU_STAT_SREG(idx); \ + addr = sdp->u.seg.segbase + offset; \ +\ + if (!CPU_STAT_PM) { \ + cpu_memorywrite_##width(addr, value); \ + return; \ + } \ +\ + if (!SEG_IS_VALID(sdp)) { \ + exc = GP_EXCEPTION; \ + goto err; \ + } \ + if (!(sdp->flag & CPU_DESC_FLAG_WRITABLE)) { \ + cpu_memorywrite_check(sdp, offset, (length), \ + CHOOSE_EXCEPTION(idx)); \ + } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { \ + if (!check_limit_upstairs(sdp, offset, (length), SEG_IS_32BIT(sdp))) \ + goto range_failure; \ + } \ + cpu_lmemorywrite_##width(addr, value, CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE); \ + return; \ +\ +range_failure: \ + VERBOSE(("cpu_vmemorywrite_" #width ": type = %d, offset = %08x, length = %d, limit = %08x", sdp->type, offset, length, sdp->u.seg.limit)); \ + exc = CHOOSE_EXCEPTION(idx); \ +err: \ + EXCEPTION(exc, 0); \ +} + +#define DECLARE_VIRTUAL_ADDRESS_MEMORY_RMW_FUNCTIONS(width, valtype, length) \ +UINT32 MEMCALL \ +cpu_vmemory_RMW_##width(int idx, UINT32 offset, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) \ +{ \ + descriptor_t *sdp; \ + UINT32 addr; \ + UINT32 result; \ + valtype value; \ + int exc; \ +\ + __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); \ +\ + sdp = &CPU_STAT_SREG(idx); \ + addr = sdp->u.seg.segbase + offset; \ +\ + if (!CPU_STAT_PM) { \ + value = cpu_memoryread_##width(addr); \ + result = (*func)(value, arg); \ + cpu_memorywrite_##width(addr, (valtype)result); \ + return value; \ + } \ +\ + if (!SEG_IS_VALID(sdp)) { \ + exc = GP_EXCEPTION; \ + goto err; \ + } \ + if (!(sdp->flag & CPU_DESC_FLAG_WRITABLE)) { \ + cpu_memorywrite_check(sdp, offset, (length), \ + CHOOSE_EXCEPTION(idx)); \ + } else if (!(sdp->flag & CPU_DESC_FLAG_WHOLEADR)) { \ + if (!check_limit_upstairs(sdp, offset, (length), SEG_IS_32BIT(sdp))) \ + goto range_failure; \ + } \ + return cpu_lmemory_RMW_##width(addr, func, arg); \ +\ +range_failure: \ + VERBOSE(("cpu_vmemory_RMW_" #width ": type = %d, offset = %08x, length = %d, limit = %08x", sdp->type, offset, length, sdp->u.seg.limit)); \ + exc = CHOOSE_EXCEPTION(idx); \ +err: \ + EXCEPTION(exc, 0); \ + return 0; /* compiler happy */ \ +} diff --git a/i386c/ia32/ctrlxfer.c b/i386c/ia32/ctrlxfer.c old mode 100755 new mode 100644 index 87c43440..c0b2533d --- a/i386c/ia32/ctrlxfer.c +++ b/i386c/ia32/ctrlxfer.c @@ -1,1436 +1,1436 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" -#include "ia32.mcr" - -#include "ctrlxfer.h" - - -/*------------------------------------------------------------------------------ - * JMPfar_pm - */ -static void CPUCALL JMPfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip); -static void CPUCALL JMPfar_pm_call_gate(const selector_t *callgate_sel); -static void CPUCALL JMPfar_pm_task_gate(selector_t *taskgate_sel); -static void CPUCALL JMPfar_pm_tss(selector_t *tss_sel); - -void CPUCALL -JMPfar_pm(UINT16 selector, UINT32 new_ip) -{ - selector_t jmp_sel; - int rv; - - VERBOSE(("JMPfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP)); - VERBOSE(("JMPfar_pm: selector = 0x%04x, new_ip = 0x%08x", selector, new_ip)); - - rv = parse_selector(&jmp_sel, selector); - if (rv < 0) { - VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d)", selector, rv)); - EXCEPTION(GP_EXCEPTION, jmp_sel.idx); - } - - if (!SEG_IS_SYSTEM(&jmp_sel.desc)) { - VERBOSE(("JMPfar_pm: code or data segment descriptor")); - - /* check segment type */ - if (SEG_IS_DATA(&jmp_sel.desc)) { - /* data segment */ - VERBOSE(("JMPfar_pm: data segment")); - EXCEPTION(GP_EXCEPTION, jmp_sel.idx); - } - - /* code segment descriptor */ - JMPfar_pm_code_segment(&jmp_sel, new_ip); - } else { - /* system descriptor */ - VERBOSE(("JMPfar_pm: system descriptor")); - - switch (jmp_sel.desc.type) { - case CPU_SYSDESC_TYPE_CALL_16: - case CPU_SYSDESC_TYPE_CALL_32: - JMPfar_pm_call_gate(&jmp_sel); - break; - - case CPU_SYSDESC_TYPE_TASK: - JMPfar_pm_task_gate(&jmp_sel); - break; - - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_TSS_32: - JMPfar_pm_tss(&jmp_sel); - break; - - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - VERBOSE(("JMPfar_pm: task is busy")); - /*FALLTHROUGH*/ - default: - VERBOSE(("JMPfar_pm: invalid descriptor type (type = %d)", jmp_sel.desc.type)); - EXCEPTION(GP_EXCEPTION, jmp_sel.idx); - break; - } - } - - VERBOSE(("JMPfar_pm: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); -} - -/*--- - * JMPfar: code segment - */ -static void CPUCALL -JMPfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip) -{ - - VERBOSE(("JMPfar_pm: CODE-SEGMENT")); - - /* check privilege level */ - if (!SEG_IS_CONFORMING_CODE(&cs_sel->desc)) { - VERBOSE(("JMPfar_pm: NON-CONFORMING-CODE-SEGMENT")); - /* 下巻 p.119 4.8.1.1. */ - if (cs_sel->rpl > CPU_STAT_CPL) { - VERBOSE(("JMPfar_pm: RPL(%d) > CPL(%d)", cs_sel->rpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel->idx); - } - if (cs_sel->desc.dpl != CPU_STAT_CPL) { - VERBOSE(("JMPfar_pm: DPL(%d) != CPL(%d)", cs_sel->desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel->idx); - } - } else { - VERBOSE(("JMPfar_pm: CONFORMING-CODE-SEGMENT")); - /* 下巻 p.120 4.8.1.2. */ - if (cs_sel->desc.dpl > CPU_STAT_CPL) { - VERBOSE(("JMPfar_pm: DPL(%d) > CPL(%d)", cs_sel->desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel->idx); - } - } - - /* not present */ - if (selector_is_not_present(cs_sel)) { - VERBOSE(("JMPfar_pm: code selector is not present")); - EXCEPTION(NP_EXCEPTION, cs_sel->idx); - } - - /* out of range */ - if (new_ip > cs_sel->desc.u.seg.limit) { - VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel->desc.u.seg.limit)); - EXCEPTION(GP_EXCEPTION, 0); - } - - load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL); - CPU_EIP = new_ip; -} - -/*--- - * JMPfar: call gate - */ -static void CPUCALL -JMPfar_pm_call_gate(const selector_t *callgate_sel) -{ - selector_t cs_sel; - int rv; - - VERBOSE(("JMPfar_pm: CALL-GATE")); - - /* check privilege level */ - if (callgate_sel->desc.dpl < CPU_STAT_CPL) { - VERBOSE(("JMPfar_pm: DPL(%d) < CPL(%d)", callgate_sel->desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, callgate_sel->idx); - } - if (callgate_sel->desc.dpl < callgate_sel->rpl) { - VERBOSE(("JMPfar_pm: DPL(%d) < RPL(%d)", callgate_sel->desc.dpl, callgate_sel->rpl)); - EXCEPTION(GP_EXCEPTION, callgate_sel->idx); - } - - /* not present */ - if (selector_is_not_present(callgate_sel)) { - VERBOSE(("JMPfar_pm: call gate selector is not present")); - EXCEPTION(NP_EXCEPTION, callgate_sel->idx); - } - - /* parse code segment selector */ - rv = parse_selector(&cs_sel, callgate_sel->desc.u.gate.selector); - if (rv < 0) { - VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d)", callgate_sel->desc.u.gate.selector, rv)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* check segment type */ - if (SEG_IS_SYSTEM(&cs_sel.desc)) { - VERBOSE(("JMPfar_pm: code segment is system segment")); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - if (SEG_IS_DATA(&cs_sel.desc)) { - VERBOSE(("JMPfar_pm: code segment is data segment")); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* check privilege level */ - if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc)) { - /* 下巻 p.119 4.8.1.1. */ - if (cs_sel.rpl > CPU_STAT_CPL) { - VERBOSE(("JMPfar_pm: RPL(%d) > CPL(%d)", cs_sel.rpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - if (cs_sel.desc.dpl != CPU_STAT_CPL) { - VERBOSE(("JMPfar_pm: DPL(%d) != CPL(%d)", cs_sel.desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - } else { - /* 下巻 p.120 4.8.1.2. */ - if (cs_sel.desc.dpl > CPU_STAT_CPL) { - VERBOSE(("JMPfar_pm: DPL(%d) > CPL(%d)", cs_sel.desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - } - - /* not present */ - if (selector_is_not_present(&cs_sel)) { - VERBOSE(("JMPfar_pm: code selector is not present")); - EXCEPTION(NP_EXCEPTION, cs_sel.idx); - } - - /* out of range */ - if (callgate_sel->desc.u.gate.offset > cs_sel.desc.u.seg.limit) { - VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", callgate_sel->desc.u.gate.offset, cs_sel.desc.u.seg.limit)); - EXCEPTION(GP_EXCEPTION, 0); - } - - load_cs(cs_sel.selector, &cs_sel.desc, CPU_STAT_CPL); - CPU_EIP = callgate_sel->desc.u.gate.offset; -} - -/*--- - * JMPfar: task gate - */ -static void CPUCALL -JMPfar_pm_task_gate(selector_t *taskgate_sel) -{ - selector_t tss_sel; - int rv; - - VERBOSE(("JMPfar_pm: TASK-GATE")); - - /* check privilege level */ - if (taskgate_sel->desc.dpl < CPU_STAT_CPL) { - VERBOSE(("JMPfar_pm: DPL(%d) < CPL(%d)", taskgate_sel->desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, taskgate_sel->idx); - } - if (taskgate_sel->desc.dpl < taskgate_sel->rpl) { - VERBOSE(("JMPfar_pm: DPL(%d) < RPL(%d)", taskgate_sel->desc.dpl, taskgate_sel->rpl)); - EXCEPTION(GP_EXCEPTION, taskgate_sel->idx); - } - - /* not present */ - if (selector_is_not_present(taskgate_sel)) { - VERBOSE(("JMPfar_pm: selector is not present")); - EXCEPTION(NP_EXCEPTION, taskgate_sel->idx); - } - - /* parse tss selector */ - rv = parse_selector(&tss_sel, taskgate_sel->desc.u.gate.selector); - if (rv < 0 || tss_sel.ldt) { - VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d, %cDT)", taskgate_sel->desc.u.gate.selector, rv, tss_sel.ldt ? 'L' : 'G')); - EXCEPTION(GP_EXCEPTION, tss_sel.idx); - } - - /* check descriptor type */ - switch (tss_sel.desc.type) { - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_TSS_32: - break; - - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - VERBOSE(("JMPfar_pm: task is busy")); - /*FALLTHROUGH*/ - default: - VERBOSE(("JMPfar_pm: invalid descriptor type (type = %d)", tss_sel.desc.type)); - EXCEPTION(GP_EXCEPTION, tss_sel.idx); - break; - } - - /* not present */ - if (selector_is_not_present(&tss_sel)) { - VERBOSE(("JMPfar_pm: selector is not present")); - EXCEPTION(NP_EXCEPTION, tss_sel.idx); - } - - task_switch(&tss_sel, TASK_SWITCH_JMP); - - /* out of range */ - if (CPU_EIP > CPU_STAT_CS_LIMIT) { - VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); - EXCEPTION(GP_EXCEPTION, 0); - } -} - -/*--- - * JMPfar: TSS - */ -static void CPUCALL -JMPfar_pm_tss(selector_t *tss_sel) -{ - - VERBOSE(("JMPfar_pm: TASK-STATE-SEGMENT")); - - /* check privilege level */ - if (tss_sel->desc.dpl < CPU_STAT_CPL) { - VERBOSE(("JMPfar_pm: DPL(%d) < CPL(%d)", tss_sel->desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, tss_sel->idx); - } - if (tss_sel->desc.dpl < tss_sel->rpl) { - VERBOSE(("JMPfar_pm: DPL(%d) < RPL(%d)", tss_sel->desc.dpl, tss_sel->rpl)); - EXCEPTION(GP_EXCEPTION, tss_sel->idx); - } - - /* not present */ - if (selector_is_not_present(tss_sel)) { - VERBOSE(("JMPfar_pm: selector is not present")); - EXCEPTION(NP_EXCEPTION, tss_sel->idx); - } - - task_switch(tss_sel, TASK_SWITCH_JMP); - - /* out of range */ - if (CPU_EIP > CPU_STAT_CS_LIMIT) { - VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); - EXCEPTION(GP_EXCEPTION, 0); - } -} - - -/*------------------------------------------------------------------------------ - * CALLfar_pm - */ -static void CPUCALL CALLfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip); -static void CPUCALL CALLfar_pm_call_gate(const selector_t *callgate_sel); -static void CPUCALL CALLfar_pm_task_gate(selector_t *taskgate_sel); -static void CPUCALL CALLfar_pm_tss(selector_t *tss_sel); - -void CPUCALL -CALLfar_pm(UINT16 selector, UINT32 new_ip) -{ - selector_t call_sel; - int rv; - - VERBOSE(("CALLfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP)); - VERBOSE(("CALLfar_pm: selector = 0x%04x, new_ip = 0x%08x", selector, new_ip)); - - rv = parse_selector(&call_sel, selector); - if (rv < 0) { - VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", selector, rv)); - EXCEPTION(GP_EXCEPTION, call_sel.idx); - } - - if (!SEG_IS_SYSTEM(&call_sel.desc)) { - /* code or data segment descriptor */ - VERBOSE(("CALLfar_pm: code or data segment descriptor")); - - if (SEG_IS_DATA(&call_sel.desc)) { - /* data segment */ - VERBOSE(("CALLfar_pm: data segment")); - EXCEPTION(GP_EXCEPTION, call_sel.idx); - } - - /* code segment descriptor */ - CALLfar_pm_code_segment(&call_sel, new_ip); - } else { - /* system descriptor */ - VERBOSE(("CALLfar_pm: system descriptor")); - - switch (call_sel.desc.type) { - case CPU_SYSDESC_TYPE_CALL_16: - case CPU_SYSDESC_TYPE_CALL_32: - CALLfar_pm_call_gate(&call_sel); - break; - - case CPU_SYSDESC_TYPE_TASK: - CALLfar_pm_task_gate(&call_sel); - break; - - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_TSS_32: - CALLfar_pm_tss(&call_sel); - break; - - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - VERBOSE(("CALLfar_pm: task is busy")); - /*FALLTHROUGH*/ - default: - VERBOSE(("CALLfar_pm: invalid descriptor type (type = %d)", call_sel.desc.type)); - EXCEPTION(GP_EXCEPTION, call_sel.idx); - break; - } - } - - VERBOSE(("CALLfar_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); -} - -/*--- - * CALLfar_pm: code segment - */ -static void CPUCALL -CALLfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip) -{ - UINT32 sp; - - VERBOSE(("CALLfar_pm: CODE-SEGMENT")); - - /* check privilege level */ - if (!SEG_IS_CONFORMING_CODE(&cs_sel->desc)) { - VERBOSE(("CALLfar_pm: NON-CONFORMING-CODE-SEGMENT")); - /* 下巻 p.119 4.8.1.1. */ - if (cs_sel->rpl > CPU_STAT_CPL) { - VERBOSE(("CALLfar_pm: RPL(%d) > CPL(%d)", cs_sel->rpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel->idx); - } - if (cs_sel->desc.dpl != CPU_STAT_CPL) { - VERBOSE(("CALLfar_pm: DPL(%d) != CPL(%d)", cs_sel->desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel->idx); - } - } else { - VERBOSE(("CALLfar_pm: CONFORMING-CODE-SEGMENT")); - /* 下巻 p.120 4.8.1.2. */ - if (cs_sel->desc.dpl > CPU_STAT_CPL) { - VERBOSE(("CALLfar_pm: DPL(%d) > CPL(%d)", cs_sel->desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel->idx); - } - } - - /* not present */ - if (selector_is_not_present(cs_sel)) { - VERBOSE(("CALLfar_pm: selector is not present")); - EXCEPTION(NP_EXCEPTION, cs_sel->idx); - } - - if (CPU_STAT_SS32) { - sp = CPU_ESP; - } else { - sp = CPU_SP; - } - if (CPU_INST_OP32) { - SS_PUSH_CHECK(sp, 8); - - /* out of range */ - if (new_ip > cs_sel->desc.u.seg.limit) { - VERBOSE(("CALLfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel->desc.u.seg.limit)); - EXCEPTION(GP_EXCEPTION, 0); - } - - PUSH0_32(CPU_CS); - PUSH0_32(CPU_EIP); - } else { - SS_PUSH_CHECK(sp, 4); - - /* out of range */ - if (new_ip > cs_sel->desc.u.seg.limit) { - VERBOSE(("CALLfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel->desc.u.seg.limit)); - EXCEPTION(GP_EXCEPTION, 0); - } - - PUSH0_16(CPU_CS); - PUSH0_16(CPU_IP); - } - - load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL); - CPU_EIP = new_ip; -} - -/*--- - * CALLfar_pm: call gate - */ -static void CPUCALL CALLfar_pm_call_gate_same_privilege(const selector_t *call_sel, selector_t *cs_sel); -static void CPUCALL CALLfar_pm_call_gate_more_privilege(const selector_t *call_sel, selector_t *cs_sel); - -static void CPUCALL -CALLfar_pm_call_gate(const selector_t *callgate_sel) -{ - selector_t cs_sel; - int rv; - - VERBOSE(("CALLfar_pm: CALL-GATE")); - - /* check privilege level */ - if (callgate_sel->desc.dpl < CPU_STAT_CPL) { - VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", callgate_sel->desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, callgate_sel->idx); - } - if (callgate_sel->desc.dpl < callgate_sel->rpl) { - VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", callgate_sel->desc.dpl, callgate_sel->rpl)); - EXCEPTION(GP_EXCEPTION, callgate_sel->idx); - } - - /* not present */ - if (selector_is_not_present(callgate_sel)) { - VERBOSE(("CALLfar_pm: selector is not present")); - EXCEPTION(NP_EXCEPTION, callgate_sel->idx); - } - - /* parse code segment descriptor */ - rv = parse_selector(&cs_sel, callgate_sel->desc.u.gate.selector); - if (rv < 0) { - VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", callgate_sel->desc.u.gate.selector, rv)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* check segment type */ - if (SEG_IS_SYSTEM(&cs_sel.desc)) { - VERBOSE(("CALLfar_pm: code segment is system segment")); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - if (SEG_IS_DATA(&cs_sel.desc)) { - VERBOSE(("CALLfar_pm: code segment is data segment")); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* check privilege level */ - if (cs_sel.desc.dpl > CPU_STAT_CPL) { - VERBOSE(("CALLfar_pm: DPL(%d) > CPL(%d)", cs_sel.desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* not present */ - if (selector_is_not_present(&cs_sel)) { - VERBOSE(("CALLfar_pm: selector is not present")); - EXCEPTION(NP_EXCEPTION, cs_sel.idx); - } - - /* out of range */ - if (callgate_sel->desc.u.gate.offset > cs_sel.desc.u.seg.limit) { - VERBOSE(("CALLfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", callgate_sel->desc.u.gate.offset, cs_sel.desc.u.seg.limit)); - EXCEPTION(GP_EXCEPTION, 0); - } - - if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc) && (cs_sel.desc.dpl < CPU_STAT_CPL)) { - CALLfar_pm_call_gate_more_privilege(callgate_sel, &cs_sel); - } else { - CALLfar_pm_call_gate_same_privilege(callgate_sel, &cs_sel); - } -} - -/*--- - * CALLfar_pm: call gate (SAME-PRIVILEGE) - */ -static void CPUCALL -CALLfar_pm_call_gate_same_privilege(const selector_t *callgate_sel, selector_t *cs_sel) -{ - UINT32 sp; - - VERBOSE(("CALLfar_pm: SAME-PRIVILEGE")); - - if (CPU_STAT_SS32) { - sp = CPU_ESP; - } else { - sp = CPU_SP; - } - if (callgate_sel->desc.type == CPU_SYSDESC_TYPE_CALL_32) { - SS_PUSH_CHECK(sp, 8); - - PUSH0_32(CPU_CS); - PUSH0_32(CPU_EIP); - } else { - SS_PUSH_CHECK(sp, 4); - - PUSH0_16(CPU_CS); - PUSH0_16(CPU_IP); - } - - load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL); - CPU_EIP = callgate_sel->desc.u.gate.offset; -} - -/*--- - * CALLfar_pm: call gate (MORE-PRIVILEGE) - */ -static void CPUCALL -CALLfar_pm_call_gate_more_privilege(const selector_t *callgate_sel, selector_t *cs_sel) -{ - UINT32 param[32]; /* copy param */ - selector_t ss_sel; - UINT stacksize; - UINT32 old_eip, old_esp; - UINT32 new_esp; - UINT16 old_cs, old_ss; - UINT16 new_ss; - int param_count; - int i; - int rv; - - VERBOSE(("CALLfar_pm: MORE-PRIVILEGE")); - - /* save register */ - old_cs = CPU_CS; - old_ss = CPU_SS; - old_eip = CPU_EIP; - old_esp = CPU_ESP; - if (!CPU_STAT_SS32) { - old_esp &= 0xffff; - } - - /* get stack pointer from TSS */ - get_stack_pointer_from_tss(cs_sel->desc.dpl, &new_ss, &new_esp); - - /* parse stack segment descriptor */ - rv = parse_selector(&ss_sel, new_ss); - if (rv < 0) { - VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", new_ss, rv)); - EXCEPTION(TS_EXCEPTION, ss_sel.idx); - } - - /* check privilege level */ - if (ss_sel.rpl != cs_sel->desc.dpl) { - VERBOSE(("CALLfar_pm: selector RPL[SS](%d) != DPL[CS](%d)", ss_sel.rpl, cs_sel->desc.dpl)); - EXCEPTION(TS_EXCEPTION, ss_sel.idx); - } - if (ss_sel.desc.dpl != cs_sel->desc.dpl) { - VERBOSE(("CALLfar_pm: descriptor DPL[SS](%d) != DPL[CS](%d)", ss_sel.desc.dpl, cs_sel->desc.dpl)); - EXCEPTION(TS_EXCEPTION, ss_sel.idx); - } - - /* stack segment must be writable data segment. */ - if (SEG_IS_SYSTEM(&ss_sel.desc)) { - VERBOSE(("CALLfar_pm: stack segment is system segment")); - EXCEPTION(TS_EXCEPTION, ss_sel.idx); - } - if (SEG_IS_CODE(&ss_sel.desc)) { - VERBOSE(("CALLfar_pm: stack segment is code segment")); - EXCEPTION(TS_EXCEPTION, ss_sel.idx); - } - if (!SEG_IS_WRITABLE_DATA(&ss_sel.desc)) { - VERBOSE(("CALLfar_pm: stack segment is read-only data segment")); - EXCEPTION(TS_EXCEPTION, ss_sel.idx); - } - - /* not present */ - if (selector_is_not_present(&ss_sel)) { - VERBOSE(("CALLfar_pm: stack segment selector is not present")); - EXCEPTION(SS_EXCEPTION, ss_sel.idx); - } - - param_count = callgate_sel->desc.u.gate.count; - VERBOSE(("CALLfar_pm: param_count = %d", param_count)); - - /* check stack size */ - if (cs_sel->desc.d) { - stacksize = 16; - } else { - stacksize = 8; - } - if (callgate_sel->desc.type == CPU_SYSDESC_TYPE_CALL_32) { - stacksize += param_count * 4; - } else { - stacksize += param_count * 2; - } - cpu_stack_push_check(ss_sel.idx, &ss_sel.desc, new_esp, stacksize, ss_sel.desc.d); - - if (callgate_sel->desc.type == CPU_SYSDESC_TYPE_CALL_32) { - /* dump param */ - for (i = 0; i < param_count; i++) { - param[i] = cpu_vmemoryread_d(CPU_SS_INDEX, old_esp + i * 4); - VERBOSE(("CALLfar_pm: get param[%d] = %08x", i, param[i])); - } - - load_ss(ss_sel.selector, &ss_sel.desc, ss_sel.desc.dpl); - if (CPU_STAT_SS32) { - CPU_ESP = new_esp; - } else { - CPU_SP = (UINT16)new_esp; - } - - load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->desc.dpl); - CPU_EIP = callgate_sel->desc.u.gate.offset; - - PUSH0_32(old_ss); - PUSH0_32(old_esp); - - /* restore param */ - for (i = param_count; i > 0; i--) { - PUSH0_32(param[i - 1]); - VERBOSE(("CALLfar_pm: set param[%d] = %08x", i - 1, param[i - 1])); - } - - PUSH0_32(old_cs); - PUSH0_32(old_eip); - } else { - /* dump param */ - for (i = 0; i < param_count; i++) { - param[i] = cpu_vmemoryread_w(CPU_SS_INDEX, old_esp + i * 2); - VERBOSE(("CALLfar_pm: get param[%d] = %04x", i, param[i])); - } - - load_ss(ss_sel.selector, &ss_sel.desc, ss_sel.desc.dpl); - if (CPU_STAT_SS32) { - CPU_ESP = new_esp; - } else { - CPU_SP = (UINT16)new_esp; - } - - load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->desc.dpl); - CPU_EIP = callgate_sel->desc.u.gate.offset; - - PUSH0_16(old_ss); - PUSH0_16(old_esp); - - /* restore param */ - for (i = param_count; i > 0; i--) { - PUSH0_16(param[i - 1]); - VERBOSE(("CALLfar_pm: set param[%d] = %04x", i - 1, param[i - 1])); - } - - PUSH0_16(old_cs); - PUSH0_16(old_eip); - } -} - -/*--- - * CALLfar_pm: task gate - */ -static void CPUCALL -CALLfar_pm_task_gate(selector_t *taskgate_sel) -{ - selector_t tss_sel; - int rv; - - VERBOSE(("CALLfar_pm: TASK-GATE")); - - /* check privilege level */ - if (taskgate_sel->desc.dpl < CPU_STAT_CPL) { - VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", taskgate_sel->desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, taskgate_sel->idx); - } - if (taskgate_sel->desc.dpl < taskgate_sel->rpl) { - VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", taskgate_sel->desc.dpl, taskgate_sel->rpl)); - EXCEPTION(GP_EXCEPTION, taskgate_sel->idx); - } - - /* not present */ - if (selector_is_not_present(taskgate_sel)) { - VERBOSE(("CALLfar_pm: selector is not present")); - EXCEPTION(NP_EXCEPTION, taskgate_sel->idx); - } - - /* tss descriptor */ - rv = parse_selector(&tss_sel, taskgate_sel->desc.u.gate.selector); - if (rv < 0 || tss_sel.ldt) { - VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d, %cDT)", tss_sel.selector, rv, tss_sel.ldt ? 'L' : 'G')); - EXCEPTION(GP_EXCEPTION, tss_sel.idx); - } - - /* check descriptor type */ - switch (tss_sel.desc.type) { - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_TSS_32: - break; - - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - VERBOSE(("CALLfar_pm: task is busy")); - /*FALLTHROUGH*/ - default: - VERBOSE(("CALLfar_pm: invalid descriptor type (type = %d)", tss_sel.desc.type)); - EXCEPTION(GP_EXCEPTION, tss_sel.idx); - break; - } - - /* not present */ - if (selector_is_not_present(&tss_sel)) { - VERBOSE(("CALLfar_pm: TSS selector is not present")); - EXCEPTION(NP_EXCEPTION, tss_sel.idx); - } - - task_switch(&tss_sel, TASK_SWITCH_CALL); - - /* out of range */ - if (CPU_EIP > CPU_STAT_CS_LIMIT) { - VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); - EXCEPTION(GP_EXCEPTION, 0); - } -} - -/*--- - * CALLfar_pm: TSS - */ -static void CPUCALL -CALLfar_pm_tss(selector_t *tss_sel) -{ - - VERBOSE(("TASK-STATE-SEGMENT")); - - /* check privilege level */ - if (tss_sel->desc.dpl < CPU_STAT_CPL) { - VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", tss_sel->desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, tss_sel->idx); - } - if (tss_sel->desc.dpl < tss_sel->rpl) { - VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", tss_sel->desc.dpl, tss_sel->rpl)); - EXCEPTION(GP_EXCEPTION, tss_sel->idx); - } - - /* not present */ - if (selector_is_not_present(tss_sel)) { - VERBOSE(("CALLfar_pm: TSS selector is not present")); - EXCEPTION(NP_EXCEPTION, tss_sel->idx); - } - - task_switch(tss_sel, TASK_SWITCH_CALL); - - /* out of range */ - if (CPU_EIP > CPU_STAT_CS_LIMIT) { - VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); - EXCEPTION(GP_EXCEPTION, 0); - } -} - - -/*------------------------------------------------------------------------------ - * RETfar_pm - */ - -void CPUCALL -RETfar_pm(UINT nbytes) -{ - selector_t cs_sel, ss_sel, temp_sel; - descriptor_t *sdp; - UINT32 sp; - UINT32 new_ip, new_sp; - UINT16 new_cs, new_ss; - int rv; - int i; - - VERBOSE(("RETfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x, nbytes = %d", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP, nbytes)); - - if (CPU_STAT_SS32) { - sp = CPU_ESP; - } else { - sp = CPU_SP; - } - if (CPU_INST_OP32) { - SS_POP_CHECK(sp, nbytes + 8); - new_ip = cpu_vmemoryread_d(CPU_SS_INDEX, sp); - new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4); - } else { - SS_POP_CHECK(sp, nbytes + 4); - new_ip = cpu_vmemoryread_w(CPU_SS_INDEX, sp); - new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 2); - } - - rv = parse_selector(&cs_sel, new_cs); - if (rv < 0) { - VERBOSE(("RETfar_pm: parse_selector (selector = %04x, rv = %d)", cs_sel.selector, rv)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* check segment type */ - if (SEG_IS_SYSTEM(&cs_sel.desc)) { - VERBOSE(("RETfar_pm: return to system segment")); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - if (SEG_IS_DATA(&cs_sel.desc)) { - VERBOSE(("RETfar_pm: return to data segment")); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* check privilege level */ - if (cs_sel.rpl < CPU_STAT_CPL) { - VERBOSE(("RETfar_pm: RPL(%d) < CPL(%d)", cs_sel.rpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc) && (cs_sel.desc.dpl > cs_sel.rpl)) { - VERBOSE(("RETfar_pm: NON-COMFORMING-CODE-SEGMENT and DPL(%d) > RPL(%d)", cs_sel.desc.dpl, cs_sel.rpl)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* not present */ - if (selector_is_not_present(&cs_sel)) { - VERBOSE(("RETfar_pm: returned code segment is not present")); - EXCEPTION(NP_EXCEPTION, cs_sel.idx); - } - - if (cs_sel.rpl == CPU_STAT_CPL) { - VERBOSE(("RETfar_pm: RETURN-TO-SAME-PRIVILEGE-LEVEL")); - - /* check code segment limit */ - if (new_ip > cs_sel.desc.u.seg.limit) { - VERBOSE(("RETfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel.desc.u.seg.limit)); - EXCEPTION(GP_EXCEPTION, 0); - } - - VERBOSE(("RETfar_pm: new_ip = %08x, new_cs = %04x", new_ip, cs_sel.selector)); - - if (CPU_INST_OP32) { - nbytes += 8; - } else { - nbytes += 4; - } - if (CPU_STAT_SS32) { - CPU_ESP += nbytes; - } else { - CPU_SP += (UINT16)nbytes; - } - - load_cs(cs_sel.selector, &cs_sel.desc, CPU_STAT_CPL); - CPU_EIP = new_ip; - } else { - VERBOSE(("RETfar_pm: RETURN-OUTER-PRIVILEGE-LEVEL")); - - if (CPU_INST_OP32) { - SS_POP_CHECK(sp, 8 + 8 + nbytes); - new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 8 + nbytes); - new_ss = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 8 + nbytes + 4); - } else { - SS_POP_CHECK(sp, 4 + 4 + nbytes); - new_sp = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4 + nbytes); - new_ss = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4 + nbytes + 2); - } - - rv = parse_selector(&ss_sel, new_ss); - if (rv < 0) { - VERBOSE(("RETfar_pm: parse_selector (selector = %04x, rv = %d)", ss_sel.selector, rv)); - EXCEPTION(GP_EXCEPTION, (rv == -2) ? 0 : ss_sel.idx); - } - - /* stack segment must be writable data segment. */ - if (SEG_IS_SYSTEM(&ss_sel.desc)) { - VERBOSE(("RETfar_pm: stack segment is system segment")); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - if (SEG_IS_CODE(&ss_sel.desc)) { - VERBOSE(("RETfar_pm: stack segment is code segment")); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - if (!SEG_IS_WRITABLE_DATA(&ss_sel.desc)) { - VERBOSE(("RETfar_pm: stack segment is read-only data segment")); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* check privilege level */ - if (ss_sel.rpl != cs_sel.rpl) { - VERBOSE(("RETfar_pm: selector RPL[SS](%d) != RPL[CS](%d)", ss_sel.rpl, cs_sel.rpl)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - if (ss_sel.desc.dpl != cs_sel.rpl) { - VERBOSE(("RETfar_pm: descriptor DPL[SS](%d) != RPL[CS](%d)", ss_sel.desc.dpl, cs_sel.rpl)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* not present */ - if (selector_is_not_present(&ss_sel)) { - VERBOSE(("RETfar_pm: stack segment is not present")); - EXCEPTION(SS_EXCEPTION, ss_sel.idx); - } - - /* check code segment limit */ - if (new_ip > cs_sel.desc.u.seg.limit) { - VERBOSE(("RETfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel.desc.u.seg.limit)); - EXCEPTION(GP_EXCEPTION, 0); - } - - VERBOSE(("RETfar_pm: new_ip = %08x, new_cs = %04x", new_ip, cs_sel.selector)); - VERBOSE(("RETfar_pm: new_sp = %08x, new_ss = %04x", new_sp, ss_sel.selector)); - - load_ss(ss_sel.selector, &ss_sel.desc, cs_sel.rpl); - if (CPU_STAT_SS32) { - CPU_ESP = new_sp + nbytes; - } else { - CPU_SP = (UINT16)(new_sp + nbytes); - } - - load_cs(cs_sel.selector, &cs_sel.desc, cs_sel.rpl); - CPU_EIP = new_ip; - - /* check segment register */ - for (i = 0; i < CPU_SEGREG_NUM; i++) { - if (i == CPU_SS_INDEX || i == CPU_CS_INDEX) - continue; - - sdp = &CPU_STAT_SREG(i); - if ((SEG_IS_DATA(sdp) || !SEG_IS_CONFORMING_CODE(sdp)) - && (CPU_STAT_CPL > sdp->dpl)) { - /* current segment descriptor is invalid */ - CPU_REGS_SREG(i) = 0; - memset(sdp, 0, sizeof(*sdp)); - continue; - } - - /* Reload segment descriptor */ - rv = parse_selector(&temp_sel, CPU_REGS_SREG(i)); - if (rv < 0) { - /* segment register is invalid */ - CPU_REGS_SREG(i) = 0; - memset(sdp, 0, sizeof(*sdp)); - continue; - } - - /* - * - system segment - * - execute-only code segment - * - data or conforming code segment && CPL > DPL - */ - if (SEG_IS_SYSTEM(&temp_sel.desc) - || (SEG_IS_CODE(&temp_sel.desc) - && !SEG_IS_READABLE_CODE(&temp_sel.desc)) - || ((SEG_IS_DATA(&temp_sel.desc) - || !SEG_IS_CONFORMING_CODE(&temp_sel.desc)) - && (CPU_STAT_CPL > temp_sel.desc.dpl))) { - /* segment descriptor is invalid */ - CPU_REGS_SREG(i) = 0; - memset(sdp, 0, sizeof(*sdp)); - } - } - } - - VERBOSE(("RETfar_pm: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); -} - - -/*------------------------------------------------------------------------------ - * IRET_pm - */ -static void IRET_pm_nested_task(void); -static void CPUCALL IRET_pm_protected_mode_return(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); -static void CPUCALL IRET_pm_protected_mode_return_same_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags); -static void CPUCALL IRET_pm_protected_mode_return_outer_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags); -static void CPUCALL IRET_pm_return_to_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); -static void CPUCALL IRET_pm_return_from_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); - -void -IRET_pm(void) -{ - UINT32 sp; - UINT32 new_ip, new_flags; - UINT16 new_cs; - - VERBOSE(("IRET_pm: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP)); - - if (!(CPU_EFLAG & VM_FLAG) && (CPU_EFLAG & NT_FLAG)) { - /* TASK-RETURN: PE=1, VM=0, NT=1 */ - IRET_pm_nested_task(); - } else { - if (CPU_STAT_SS32) { - sp = CPU_ESP; - } else { - sp = CPU_SP; - } - if (CPU_INST_OP32) { - SS_POP_CHECK(sp, 12); - new_ip = cpu_vmemoryread_d(CPU_SS_INDEX, sp); - new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4); - new_flags = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 8); - } else { - SS_POP_CHECK(sp, 6); - new_ip = cpu_vmemoryread_w(CPU_SS_INDEX, sp); - new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 2); - new_flags = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4); - } - - VERBOSE(("IRET_pm: new_ip = %08x, new_cs = %04x, new_eflags = %08x", new_ip, new_cs, new_flags)); - - if (CPU_EFLAG & VM_FLAG) { - /* RETURN-FROM-VIRTUAL-8086-MODE */ - IRET_pm_return_from_vm86(new_cs, new_ip, new_flags); - } else if ((new_flags & VM_FLAG) && CPU_STAT_CPL == 0) { - /* RETURN-TO-VIRTUAL-8086-MODE */ - IRET_pm_return_to_vm86(new_cs, new_ip, new_flags); - } else { - /* PROTECTED-MODE-RETURN */ - IRET_pm_protected_mode_return(new_cs, new_ip, new_flags); - } - } - - VERBOSE(("IRET_pm: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); -} - -/*--- - * IRET_pm: NT_FLAG - */ -static void -IRET_pm_nested_task(void) -{ - selector_t tss_sel; - UINT16 new_tss; - int rv; - - VERBOSE(("IRET_pm: TASK-RETURN: PE=1, VM=0, NT=1")); - - new_tss = get_backlink_selector_from_tss(); - - rv = parse_selector(&tss_sel, new_tss); - if (rv < 0 || tss_sel.ldt) { - VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d, %cDT)", tss_sel.selector, rv, tss_sel.ldt ? 'L' : 'G')); - EXCEPTION(GP_EXCEPTION, tss_sel.idx); - } - - /* check system segment */ - if (!SEG_IS_SYSTEM(&tss_sel.desc)) { - VERBOSE(("IRET_pm: task segment is %s segment", tss_sel.desc.u.seg.c ? "code" : "data")); - EXCEPTION(GP_EXCEPTION, tss_sel.idx); - } - - switch (tss_sel.desc.type) { - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - break; - - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_TSS_32: - VERBOSE(("IRET_pm: task is not busy")); - /*FALLTHROUGH*/ - default: - VERBOSE(("IRET_pm: invalid descriptor type (type = %d)", tss_sel.desc.type)); - EXCEPTION(GP_EXCEPTION, tss_sel.idx); - break; - } - - /* not present */ - if (selector_is_not_present(&tss_sel)) { - VERBOSE(("IRET_pm: tss segment is not present")); - EXCEPTION(NP_EXCEPTION, tss_sel.idx); - } - - task_switch(&tss_sel, TASK_SWITCH_IRET); - - /* out of range */ - if (CPU_EIP > CPU_STAT_CS_LIMIT) { - VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); - EXCEPTION(GP_EXCEPTION, 0); - } -} - -/*--- - * IRET_pm: PROTECTED-MODE-RETURN - */ -static void CPUCALL -IRET_pm_protected_mode_return(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags) -{ - selector_t cs_sel; - int rv; - - /* PROTECTED-MODE-RETURN */ - VERBOSE(("IRET_pm: PE=1, VM=0 in flags image")); - - rv = parse_selector(&cs_sel, new_cs); - if (rv < 0) { - VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d)", cs_sel.selector, rv)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* check code segment descriptor */ - if (SEG_IS_SYSTEM(&cs_sel.desc)) { - VERBOSE(("IRET_pm: return code segment is system segment")); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - if (SEG_IS_DATA(&cs_sel.desc)) { - VERBOSE(("IRET_pm: return code segment is data segment")); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* check privilege level */ - if (cs_sel.rpl < CPU_STAT_CPL) { - VERBOSE(("IRET_pm: RPL(%d) < CPL(%d)", cs_sel.rpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - if (SEG_IS_CONFORMING_CODE(&cs_sel.desc) && (cs_sel.desc.dpl > cs_sel.rpl)) { - VERBOSE(("IRET_pm: CONFORMING-CODE-SEGMENT and DPL(%d) > RPL(%d)", cs_sel.desc.dpl, cs_sel.rpl)); - EXCEPTION(GP_EXCEPTION, cs_sel.idx); - } - - /* not present */ - if (selector_is_not_present(&cs_sel)) { - VERBOSE(("IRET_pm: code segment is not present")); - EXCEPTION(NP_EXCEPTION, cs_sel.idx); - } - - if (cs_sel.rpl > CPU_STAT_CPL) { - IRET_pm_protected_mode_return_outer_privilege(&cs_sel, new_ip, new_flags); - } else { - IRET_pm_protected_mode_return_same_privilege(&cs_sel, new_ip, new_flags); - } -} - -/*--- - * IRET_pm: SAME-PRIVILEGE - */ -static void CPUCALL -IRET_pm_protected_mode_return_same_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags) -{ - UINT32 mask; - UINT stacksize; - - VERBOSE(("IRET_pm: RETURN-TO-SAME-PRIVILEGE-LEVEL")); - - /* check code segment limit */ - if (new_ip > cs_sel->desc.u.seg.limit) { - VERBOSE(("IRET_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel->desc.u.seg.limit)); - EXCEPTION(GP_EXCEPTION, 0); - } - - mask = 0; - if (CPU_INST_OP32) - mask |= RF_FLAG; - if (CPU_STAT_CPL <= CPU_STAT_IOPL) - mask |= I_FLAG; - if (CPU_STAT_CPL == 0) { - mask |= IOPL_FLAG; - if (CPU_INST_OP32) { - mask |= VM_FLAG|VIF_FLAG|VIP_FLAG; - } - } - - if (CPU_INST_OP32) { - stacksize = 12; - } else { - stacksize = 6; - } - - /* set new register */ - load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL); - CPU_EIP = new_ip; - - if (CPU_STAT_SS32) { - CPU_ESP += stacksize; - } else { - CPU_SP += (UINT16)stacksize; - } - - set_eflags(new_flags, mask); -} - -/*--- - * IRET_pm: OUTER-PRIVILEGE - */ -static void CPUCALL -IRET_pm_protected_mode_return_outer_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags) -{ - descriptor_t *sdp; - selector_t ss_sel; - UINT32 mask; - UINT32 sp; - UINT32 new_sp; - UINT16 new_ss; - int rv; - int i; - - VERBOSE(("IRET_pm: RETURN-OUTER-PRIVILEGE-LEVEL")); - - if (CPU_STAT_SS32) { - sp = CPU_ESP; - } else { - sp = CPU_SP; - } - if (CPU_INST_OP32) { - SS_POP_CHECK(sp, 20); - new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 12); - new_ss = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 16); - } else { - SS_POP_CHECK(sp, 10); - new_sp = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 6); - new_ss = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 8); - } - VERBOSE(("IRET_pm: new_sp = 0x%08x, new_ss = 0x%04x", new_sp, new_ss)); - - rv = parse_selector(&ss_sel, new_ss); - if (rv < 0) { - VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d)", ss_sel.selector, rv)); - EXCEPTION(GP_EXCEPTION, (rv == -2) ? 0 : ss_sel.idx); - } - - /* check privilege level */ - if (ss_sel.rpl != cs_sel->rpl) { - VERBOSE(("IRET_pm: selector RPL[SS](%d) != RPL[CS](%d)", ss_sel.rpl, cs_sel->rpl)); - EXCEPTION(GP_EXCEPTION, ss_sel.idx); - } -#if 0 - if (ss_sel.desc.dpl != cs_sel->rpl) { - VERBOSE(("IRET_pm: segment DPL[SS](%d) != RPL[CS](%d)", ss_sel.desc.dpl, cs_sel->rpl)); - EXCEPTION(GP_EXCEPTION, ss_sel.idx); - } - if (ss_sel.desc.rpl != cs_sel->rpl) { - VERBOSE(("IRET_pm: segment RPL[SS](%d) != RPL[CS](%d)", ss_sel.desc.rpl, cs_sel->rpl)); - EXCEPTION(GP_EXCEPTION, ss_sel.idx); - } -#endif - - /* stack segment must be writable data segment. */ - if (SEG_IS_SYSTEM(&ss_sel.desc)) { - VERBOSE(("IRET_pm: stack segment is system segment")); - EXCEPTION(GP_EXCEPTION, ss_sel.idx); - } - if (SEG_IS_CODE(&ss_sel.desc)) { - VERBOSE(("IRET_pm: stack segment is code segment")); - EXCEPTION(GP_EXCEPTION, ss_sel.idx); - } - if (!SEG_IS_WRITABLE_DATA(&ss_sel.desc)) { - VERBOSE(("IRET_pm: stack segment is read-only data segment")); - EXCEPTION(GP_EXCEPTION, ss_sel.idx); - } - - /* not present */ - if (selector_is_not_present(&ss_sel)) { - VERBOSE(("IRET_pm: stack segment is not present")); - EXCEPTION(SS_EXCEPTION, ss_sel.idx); - } - - /* check code segment limit */ - if (new_ip > cs_sel->desc.u.seg.limit) { - VERBOSE(("IRET_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel->desc.u.seg.limit)); - EXCEPTION(GP_EXCEPTION, 0); - } - - mask = 0; - if (CPU_INST_OP32) - mask |= RF_FLAG; - if (CPU_STAT_CPL <= CPU_STAT_IOPL) - mask |= I_FLAG; - if (CPU_STAT_CPL == 0) { - mask |= IOPL_FLAG; - if (CPU_INST_OP32) { - mask |= VM_FLAG|VIF_FLAG|VIP_FLAG; - } - } - - /* set new register */ - load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->rpl); - CPU_EIP = new_ip; - - load_ss(ss_sel.selector, &ss_sel.desc, cs_sel->rpl); - if (CPU_STAT_SS32) { - CPU_ESP = new_sp; - } else { - CPU_SP = (UINT16)new_sp; - } - - set_eflags(new_flags, mask); - - /* check segment register */ - for (i = 0; i < CPU_SEGREG_NUM; i++) { - if ((i != CPU_CS_INDEX) && (i != CPU_SS_INDEX)) { - sdp = &CPU_STAT_SREG(i); - if ((SEG_IS_DATA(sdp) || !SEG_IS_CONFORMING_CODE(sdp)) - && (sdp->dpl < CPU_STAT_CPL)) { - /* segment register is invalid */ - CPU_REGS_SREG(i) = 0; - memset(sdp, 0, sizeof(*sdp)); - } - } - } -} - -/*--- - * IRET_pm: new_flags & VM_FLAG - */ -static void CPUCALL -IRET_pm_return_to_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags) -{ - UINT16 segsel[CPU_SEGREG_NUM]; - UINT32 sp; - UINT32 new_sp; - int i; - - VERBOSE(("IRET_pm: Interrupt procedure was in virtual-8086 mode: PE=1, VM=1 in flags image")); - - if (!CPU_INST_OP32) { - ia32_panic("IRET_pm: 16bit mode"); - } - - if (CPU_STAT_SS32) { - sp = CPU_ESP; - } else { - sp = CPU_SP; - } - SS_POP_CHECK(sp, 36); - - new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 12); - segsel[CPU_SS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 16); - segsel[CPU_ES_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 20); - segsel[CPU_DS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 24); - segsel[CPU_FS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 28); - segsel[CPU_GS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 32); - segsel[CPU_CS_INDEX] = new_cs; - - for (i = 0; i < CPU_SEGREG_NUM; i++) { - segdesc_init(i, segsel[i], &CPU_STAT_SREG(i)); - } - - CPU_ESP = new_sp; - CPU_EIP = new_ip & 0xffff; - - /* to VM86 mode */ - set_eflags(new_flags, IOPL_FLAG|I_FLAG|VM_FLAG|RF_FLAG); -} - -/*--- - * IRET_pm: VM_FLAG - */ -static void CPUCALL -IRET_pm_return_from_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags) -{ - UINT stacksize; - - VERBOSE(("IRET_pm: virtual-8086 mode: VM=1")); - - if (CPU_STAT_IOPL == CPU_IOPL3) { - VERBOSE(("IRET_pm: virtual-8086 mode: IOPL=3")); -//vme_emulate: - if (CPU_INST_OP32) { - stacksize = 12; - } else { - stacksize = 6; - } - if (CPU_STAT_SS32) { - CPU_ESP += stacksize; - } else { - CPU_SP += stacksize; - } - - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - if (new_ip > CPU_STAT_CS_LIMIT) { - EXCEPTION(GP_EXCEPTION, 0); - } - CPU_EIP = new_ip; - - set_eflags(new_flags, I_FLAG|RF_FLAG); - return; - } - VERBOSE(("IRET_pm: trap to virtual-8086 monitor: VM=1, IOPL<3")); -#if defined(USE_VME) - //if(CPU_CR4 & CPU_CR4_VME){ - // if((CPU_EFLAG & VIP_FLAG) || (CPU_EFLAG & T_FLAG)){ - // EXCEPTION(GP_EXCEPTION, 0); - // }else{ - // new_flags = (new_flags & ~VIF_FLAG) | ((new_flags & I_FLAG) << 10); // IF → VIFにコピー - // new_flags = (new_flags & ~(IOPL_FLAG|I_FLAG)) | (CPU_EFLAG & (IOPL_FLAG|I_FLAG)); // IF, IOPLは変更させない - // goto vme_emulate; - // } - //}else{ - // EXCEPTION(GP_EXCEPTION, 0); - //} - EXCEPTION(GP_EXCEPTION, 0); // XXX: 一応動いてるけど実装しないとまずい・・・? -#else - EXCEPTION(GP_EXCEPTION, 0); -#endif -} +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" +#include "ia32.mcr" + +#include "ctrlxfer.h" + + +/*------------------------------------------------------------------------------ + * JMPfar_pm + */ +static void CPUCALL JMPfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip); +static void CPUCALL JMPfar_pm_call_gate(const selector_t *callgate_sel); +static void CPUCALL JMPfar_pm_task_gate(selector_t *taskgate_sel); +static void CPUCALL JMPfar_pm_tss(selector_t *tss_sel); + +void CPUCALL +JMPfar_pm(UINT16 selector, UINT32 new_ip) +{ + selector_t jmp_sel; + int rv; + + VERBOSE(("JMPfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP)); + VERBOSE(("JMPfar_pm: selector = 0x%04x, new_ip = 0x%08x", selector, new_ip)); + + rv = parse_selector(&jmp_sel, selector); + if (rv < 0) { + VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d)", selector, rv)); + EXCEPTION(GP_EXCEPTION, jmp_sel.idx); + } + + if (!SEG_IS_SYSTEM(&jmp_sel.desc)) { + VERBOSE(("JMPfar_pm: code or data segment descriptor")); + + /* check segment type */ + if (SEG_IS_DATA(&jmp_sel.desc)) { + /* data segment */ + VERBOSE(("JMPfar_pm: data segment")); + EXCEPTION(GP_EXCEPTION, jmp_sel.idx); + } + + /* code segment descriptor */ + JMPfar_pm_code_segment(&jmp_sel, new_ip); + } else { + /* system descriptor */ + VERBOSE(("JMPfar_pm: system descriptor")); + + switch (jmp_sel.desc.type) { + case CPU_SYSDESC_TYPE_CALL_16: + case CPU_SYSDESC_TYPE_CALL_32: + JMPfar_pm_call_gate(&jmp_sel); + break; + + case CPU_SYSDESC_TYPE_TASK: + JMPfar_pm_task_gate(&jmp_sel); + break; + + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_TSS_32: + JMPfar_pm_tss(&jmp_sel); + break; + + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + VERBOSE(("JMPfar_pm: task is busy")); + /*FALLTHROUGH*/ + default: + VERBOSE(("JMPfar_pm: invalid descriptor type (type = %d)", jmp_sel.desc.type)); + EXCEPTION(GP_EXCEPTION, jmp_sel.idx); + break; + } + } + + VERBOSE(("JMPfar_pm: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); +} + +/*--- + * JMPfar: code segment + */ +static void CPUCALL +JMPfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip) +{ + + VERBOSE(("JMPfar_pm: CODE-SEGMENT")); + + /* check privilege level */ + if (!SEG_IS_CONFORMING_CODE(&cs_sel->desc)) { + VERBOSE(("JMPfar_pm: NON-CONFORMING-CODE-SEGMENT")); + /* 下巻 p.119 4.8.1.1. */ + if (cs_sel->rpl > CPU_STAT_CPL) { + VERBOSE(("JMPfar_pm: RPL(%d) > CPL(%d)", cs_sel->rpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel->idx); + } + if (cs_sel->desc.dpl != CPU_STAT_CPL) { + VERBOSE(("JMPfar_pm: DPL(%d) != CPL(%d)", cs_sel->desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel->idx); + } + } else { + VERBOSE(("JMPfar_pm: CONFORMING-CODE-SEGMENT")); + /* 下巻 p.120 4.8.1.2. */ + if (cs_sel->desc.dpl > CPU_STAT_CPL) { + VERBOSE(("JMPfar_pm: DPL(%d) > CPL(%d)", cs_sel->desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel->idx); + } + } + + /* not present */ + if (selector_is_not_present(cs_sel)) { + VERBOSE(("JMPfar_pm: code selector is not present")); + EXCEPTION(NP_EXCEPTION, cs_sel->idx); + } + + /* out of range */ + if (new_ip > cs_sel->desc.u.seg.limit) { + VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel->desc.u.seg.limit)); + EXCEPTION(GP_EXCEPTION, 0); + } + + load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL); + CPU_EIP = new_ip; +} + +/*--- + * JMPfar: call gate + */ +static void CPUCALL +JMPfar_pm_call_gate(const selector_t *callgate_sel) +{ + selector_t cs_sel; + int rv; + + VERBOSE(("JMPfar_pm: CALL-GATE")); + + /* check privilege level */ + if (callgate_sel->desc.dpl < CPU_STAT_CPL) { + VERBOSE(("JMPfar_pm: DPL(%d) < CPL(%d)", callgate_sel->desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, callgate_sel->idx); + } + if (callgate_sel->desc.dpl < callgate_sel->rpl) { + VERBOSE(("JMPfar_pm: DPL(%d) < RPL(%d)", callgate_sel->desc.dpl, callgate_sel->rpl)); + EXCEPTION(GP_EXCEPTION, callgate_sel->idx); + } + + /* not present */ + if (selector_is_not_present(callgate_sel)) { + VERBOSE(("JMPfar_pm: call gate selector is not present")); + EXCEPTION(NP_EXCEPTION, callgate_sel->idx); + } + + /* parse code segment selector */ + rv = parse_selector(&cs_sel, callgate_sel->desc.u.gate.selector); + if (rv < 0) { + VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d)", callgate_sel->desc.u.gate.selector, rv)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* check segment type */ + if (SEG_IS_SYSTEM(&cs_sel.desc)) { + VERBOSE(("JMPfar_pm: code segment is system segment")); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + if (SEG_IS_DATA(&cs_sel.desc)) { + VERBOSE(("JMPfar_pm: code segment is data segment")); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* check privilege level */ + if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc)) { + /* 下巻 p.119 4.8.1.1. */ + if (cs_sel.rpl > CPU_STAT_CPL) { + VERBOSE(("JMPfar_pm: RPL(%d) > CPL(%d)", cs_sel.rpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + if (cs_sel.desc.dpl != CPU_STAT_CPL) { + VERBOSE(("JMPfar_pm: DPL(%d) != CPL(%d)", cs_sel.desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + } else { + /* 下巻 p.120 4.8.1.2. */ + if (cs_sel.desc.dpl > CPU_STAT_CPL) { + VERBOSE(("JMPfar_pm: DPL(%d) > CPL(%d)", cs_sel.desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + } + + /* not present */ + if (selector_is_not_present(&cs_sel)) { + VERBOSE(("JMPfar_pm: code selector is not present")); + EXCEPTION(NP_EXCEPTION, cs_sel.idx); + } + + /* out of range */ + if (callgate_sel->desc.u.gate.offset > cs_sel.desc.u.seg.limit) { + VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", callgate_sel->desc.u.gate.offset, cs_sel.desc.u.seg.limit)); + EXCEPTION(GP_EXCEPTION, 0); + } + + load_cs(cs_sel.selector, &cs_sel.desc, CPU_STAT_CPL); + CPU_EIP = callgate_sel->desc.u.gate.offset; +} + +/*--- + * JMPfar: task gate + */ +static void CPUCALL +JMPfar_pm_task_gate(selector_t *taskgate_sel) +{ + selector_t tss_sel; + int rv; + + VERBOSE(("JMPfar_pm: TASK-GATE")); + + /* check privilege level */ + if (taskgate_sel->desc.dpl < CPU_STAT_CPL) { + VERBOSE(("JMPfar_pm: DPL(%d) < CPL(%d)", taskgate_sel->desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, taskgate_sel->idx); + } + if (taskgate_sel->desc.dpl < taskgate_sel->rpl) { + VERBOSE(("JMPfar_pm: DPL(%d) < RPL(%d)", taskgate_sel->desc.dpl, taskgate_sel->rpl)); + EXCEPTION(GP_EXCEPTION, taskgate_sel->idx); + } + + /* not present */ + if (selector_is_not_present(taskgate_sel)) { + VERBOSE(("JMPfar_pm: selector is not present")); + EXCEPTION(NP_EXCEPTION, taskgate_sel->idx); + } + + /* parse tss selector */ + rv = parse_selector(&tss_sel, taskgate_sel->desc.u.gate.selector); + if (rv < 0 || tss_sel.ldt) { + VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d, %cDT)", taskgate_sel->desc.u.gate.selector, rv, tss_sel.ldt ? 'L' : 'G')); + EXCEPTION(GP_EXCEPTION, tss_sel.idx); + } + + /* check descriptor type */ + switch (tss_sel.desc.type) { + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_TSS_32: + break; + + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + VERBOSE(("JMPfar_pm: task is busy")); + /*FALLTHROUGH*/ + default: + VERBOSE(("JMPfar_pm: invalid descriptor type (type = %d)", tss_sel.desc.type)); + EXCEPTION(GP_EXCEPTION, tss_sel.idx); + break; + } + + /* not present */ + if (selector_is_not_present(&tss_sel)) { + VERBOSE(("JMPfar_pm: selector is not present")); + EXCEPTION(NP_EXCEPTION, tss_sel.idx); + } + + task_switch(&tss_sel, TASK_SWITCH_JMP); + + /* out of range */ + if (CPU_EIP > CPU_STAT_CS_LIMIT) { + VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); + EXCEPTION(GP_EXCEPTION, 0); + } +} + +/*--- + * JMPfar: TSS + */ +static void CPUCALL +JMPfar_pm_tss(selector_t *tss_sel) +{ + + VERBOSE(("JMPfar_pm: TASK-STATE-SEGMENT")); + + /* check privilege level */ + if (tss_sel->desc.dpl < CPU_STAT_CPL) { + VERBOSE(("JMPfar_pm: DPL(%d) < CPL(%d)", tss_sel->desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, tss_sel->idx); + } + if (tss_sel->desc.dpl < tss_sel->rpl) { + VERBOSE(("JMPfar_pm: DPL(%d) < RPL(%d)", tss_sel->desc.dpl, tss_sel->rpl)); + EXCEPTION(GP_EXCEPTION, tss_sel->idx); + } + + /* not present */ + if (selector_is_not_present(tss_sel)) { + VERBOSE(("JMPfar_pm: selector is not present")); + EXCEPTION(NP_EXCEPTION, tss_sel->idx); + } + + task_switch(tss_sel, TASK_SWITCH_JMP); + + /* out of range */ + if (CPU_EIP > CPU_STAT_CS_LIMIT) { + VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); + EXCEPTION(GP_EXCEPTION, 0); + } +} + + +/*------------------------------------------------------------------------------ + * CALLfar_pm + */ +static void CPUCALL CALLfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip); +static void CPUCALL CALLfar_pm_call_gate(const selector_t *callgate_sel); +static void CPUCALL CALLfar_pm_task_gate(selector_t *taskgate_sel); +static void CPUCALL CALLfar_pm_tss(selector_t *tss_sel); + +void CPUCALL +CALLfar_pm(UINT16 selector, UINT32 new_ip) +{ + selector_t call_sel; + int rv; + + VERBOSE(("CALLfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP)); + VERBOSE(("CALLfar_pm: selector = 0x%04x, new_ip = 0x%08x", selector, new_ip)); + + rv = parse_selector(&call_sel, selector); + if (rv < 0) { + VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", selector, rv)); + EXCEPTION(GP_EXCEPTION, call_sel.idx); + } + + if (!SEG_IS_SYSTEM(&call_sel.desc)) { + /* code or data segment descriptor */ + VERBOSE(("CALLfar_pm: code or data segment descriptor")); + + if (SEG_IS_DATA(&call_sel.desc)) { + /* data segment */ + VERBOSE(("CALLfar_pm: data segment")); + EXCEPTION(GP_EXCEPTION, call_sel.idx); + } + + /* code segment descriptor */ + CALLfar_pm_code_segment(&call_sel, new_ip); + } else { + /* system descriptor */ + VERBOSE(("CALLfar_pm: system descriptor")); + + switch (call_sel.desc.type) { + case CPU_SYSDESC_TYPE_CALL_16: + case CPU_SYSDESC_TYPE_CALL_32: + CALLfar_pm_call_gate(&call_sel); + break; + + case CPU_SYSDESC_TYPE_TASK: + CALLfar_pm_task_gate(&call_sel); + break; + + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_TSS_32: + CALLfar_pm_tss(&call_sel); + break; + + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + VERBOSE(("CALLfar_pm: task is busy")); + /*FALLTHROUGH*/ + default: + VERBOSE(("CALLfar_pm: invalid descriptor type (type = %d)", call_sel.desc.type)); + EXCEPTION(GP_EXCEPTION, call_sel.idx); + break; + } + } + + VERBOSE(("CALLfar_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); +} + +/*--- + * CALLfar_pm: code segment + */ +static void CPUCALL +CALLfar_pm_code_segment(const selector_t *cs_sel, UINT32 new_ip) +{ + UINT32 sp; + + VERBOSE(("CALLfar_pm: CODE-SEGMENT")); + + /* check privilege level */ + if (!SEG_IS_CONFORMING_CODE(&cs_sel->desc)) { + VERBOSE(("CALLfar_pm: NON-CONFORMING-CODE-SEGMENT")); + /* 下巻 p.119 4.8.1.1. */ + if (cs_sel->rpl > CPU_STAT_CPL) { + VERBOSE(("CALLfar_pm: RPL(%d) > CPL(%d)", cs_sel->rpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel->idx); + } + if (cs_sel->desc.dpl != CPU_STAT_CPL) { + VERBOSE(("CALLfar_pm: DPL(%d) != CPL(%d)", cs_sel->desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel->idx); + } + } else { + VERBOSE(("CALLfar_pm: CONFORMING-CODE-SEGMENT")); + /* 下巻 p.120 4.8.1.2. */ + if (cs_sel->desc.dpl > CPU_STAT_CPL) { + VERBOSE(("CALLfar_pm: DPL(%d) > CPL(%d)", cs_sel->desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel->idx); + } + } + + /* not present */ + if (selector_is_not_present(cs_sel)) { + VERBOSE(("CALLfar_pm: selector is not present")); + EXCEPTION(NP_EXCEPTION, cs_sel->idx); + } + + if (CPU_STAT_SS32) { + sp = CPU_ESP; + } else { + sp = CPU_SP; + } + if (CPU_INST_OP32) { + SS_PUSH_CHECK(sp, 8); + + /* out of range */ + if (new_ip > cs_sel->desc.u.seg.limit) { + VERBOSE(("CALLfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel->desc.u.seg.limit)); + EXCEPTION(GP_EXCEPTION, 0); + } + + PUSH0_32(CPU_CS); + PUSH0_32(CPU_EIP); + } else { + SS_PUSH_CHECK(sp, 4); + + /* out of range */ + if (new_ip > cs_sel->desc.u.seg.limit) { + VERBOSE(("CALLfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel->desc.u.seg.limit)); + EXCEPTION(GP_EXCEPTION, 0); + } + + PUSH0_16(CPU_CS); + PUSH0_16(CPU_IP); + } + + load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL); + CPU_EIP = new_ip; +} + +/*--- + * CALLfar_pm: call gate + */ +static void CPUCALL CALLfar_pm_call_gate_same_privilege(const selector_t *call_sel, selector_t *cs_sel); +static void CPUCALL CALLfar_pm_call_gate_more_privilege(const selector_t *call_sel, selector_t *cs_sel); + +static void CPUCALL +CALLfar_pm_call_gate(const selector_t *callgate_sel) +{ + selector_t cs_sel; + int rv; + + VERBOSE(("CALLfar_pm: CALL-GATE")); + + /* check privilege level */ + if (callgate_sel->desc.dpl < CPU_STAT_CPL) { + VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", callgate_sel->desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, callgate_sel->idx); + } + if (callgate_sel->desc.dpl < callgate_sel->rpl) { + VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", callgate_sel->desc.dpl, callgate_sel->rpl)); + EXCEPTION(GP_EXCEPTION, callgate_sel->idx); + } + + /* not present */ + if (selector_is_not_present(callgate_sel)) { + VERBOSE(("CALLfar_pm: selector is not present")); + EXCEPTION(NP_EXCEPTION, callgate_sel->idx); + } + + /* parse code segment descriptor */ + rv = parse_selector(&cs_sel, callgate_sel->desc.u.gate.selector); + if (rv < 0) { + VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", callgate_sel->desc.u.gate.selector, rv)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* check segment type */ + if (SEG_IS_SYSTEM(&cs_sel.desc)) { + VERBOSE(("CALLfar_pm: code segment is system segment")); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + if (SEG_IS_DATA(&cs_sel.desc)) { + VERBOSE(("CALLfar_pm: code segment is data segment")); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* check privilege level */ + if (cs_sel.desc.dpl > CPU_STAT_CPL) { + VERBOSE(("CALLfar_pm: DPL(%d) > CPL(%d)", cs_sel.desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* not present */ + if (selector_is_not_present(&cs_sel)) { + VERBOSE(("CALLfar_pm: selector is not present")); + EXCEPTION(NP_EXCEPTION, cs_sel.idx); + } + + /* out of range */ + if (callgate_sel->desc.u.gate.offset > cs_sel.desc.u.seg.limit) { + VERBOSE(("CALLfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", callgate_sel->desc.u.gate.offset, cs_sel.desc.u.seg.limit)); + EXCEPTION(GP_EXCEPTION, 0); + } + + if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc) && (cs_sel.desc.dpl < CPU_STAT_CPL)) { + CALLfar_pm_call_gate_more_privilege(callgate_sel, &cs_sel); + } else { + CALLfar_pm_call_gate_same_privilege(callgate_sel, &cs_sel); + } +} + +/*--- + * CALLfar_pm: call gate (SAME-PRIVILEGE) + */ +static void CPUCALL +CALLfar_pm_call_gate_same_privilege(const selector_t *callgate_sel, selector_t *cs_sel) +{ + UINT32 sp; + + VERBOSE(("CALLfar_pm: SAME-PRIVILEGE")); + + if (CPU_STAT_SS32) { + sp = CPU_ESP; + } else { + sp = CPU_SP; + } + if (callgate_sel->desc.type == CPU_SYSDESC_TYPE_CALL_32) { + SS_PUSH_CHECK(sp, 8); + + PUSH0_32(CPU_CS); + PUSH0_32(CPU_EIP); + } else { + SS_PUSH_CHECK(sp, 4); + + PUSH0_16(CPU_CS); + PUSH0_16(CPU_IP); + } + + load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL); + CPU_EIP = callgate_sel->desc.u.gate.offset; +} + +/*--- + * CALLfar_pm: call gate (MORE-PRIVILEGE) + */ +static void CPUCALL +CALLfar_pm_call_gate_more_privilege(const selector_t *callgate_sel, selector_t *cs_sel) +{ + UINT32 param[32]; /* copy param */ + selector_t ss_sel; + UINT stacksize; + UINT32 old_eip, old_esp; + UINT32 new_esp; + UINT16 old_cs, old_ss; + UINT16 new_ss; + int param_count; + int i; + int rv; + + VERBOSE(("CALLfar_pm: MORE-PRIVILEGE")); + + /* save register */ + old_cs = CPU_CS; + old_ss = CPU_SS; + old_eip = CPU_EIP; + old_esp = CPU_ESP; + if (!CPU_STAT_SS32) { + old_esp &= 0xffff; + } + + /* get stack pointer from TSS */ + get_stack_pointer_from_tss(cs_sel->desc.dpl, &new_ss, &new_esp); + + /* parse stack segment descriptor */ + rv = parse_selector(&ss_sel, new_ss); + if (rv < 0) { + VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", new_ss, rv)); + EXCEPTION(TS_EXCEPTION, ss_sel.idx); + } + + /* check privilege level */ + if (ss_sel.rpl != cs_sel->desc.dpl) { + VERBOSE(("CALLfar_pm: selector RPL[SS](%d) != DPL[CS](%d)", ss_sel.rpl, cs_sel->desc.dpl)); + EXCEPTION(TS_EXCEPTION, ss_sel.idx); + } + if (ss_sel.desc.dpl != cs_sel->desc.dpl) { + VERBOSE(("CALLfar_pm: descriptor DPL[SS](%d) != DPL[CS](%d)", ss_sel.desc.dpl, cs_sel->desc.dpl)); + EXCEPTION(TS_EXCEPTION, ss_sel.idx); + } + + /* stack segment must be writable data segment. */ + if (SEG_IS_SYSTEM(&ss_sel.desc)) { + VERBOSE(("CALLfar_pm: stack segment is system segment")); + EXCEPTION(TS_EXCEPTION, ss_sel.idx); + } + if (SEG_IS_CODE(&ss_sel.desc)) { + VERBOSE(("CALLfar_pm: stack segment is code segment")); + EXCEPTION(TS_EXCEPTION, ss_sel.idx); + } + if (!SEG_IS_WRITABLE_DATA(&ss_sel.desc)) { + VERBOSE(("CALLfar_pm: stack segment is read-only data segment")); + EXCEPTION(TS_EXCEPTION, ss_sel.idx); + } + + /* not present */ + if (selector_is_not_present(&ss_sel)) { + VERBOSE(("CALLfar_pm: stack segment selector is not present")); + EXCEPTION(SS_EXCEPTION, ss_sel.idx); + } + + param_count = callgate_sel->desc.u.gate.count; + VERBOSE(("CALLfar_pm: param_count = %d", param_count)); + + /* check stack size */ + if (cs_sel->desc.d) { + stacksize = 16; + } else { + stacksize = 8; + } + if (callgate_sel->desc.type == CPU_SYSDESC_TYPE_CALL_32) { + stacksize += param_count * 4; + } else { + stacksize += param_count * 2; + } + cpu_stack_push_check(ss_sel.idx, &ss_sel.desc, new_esp, stacksize, ss_sel.desc.d); + + if (callgate_sel->desc.type == CPU_SYSDESC_TYPE_CALL_32) { + /* dump param */ + for (i = 0; i < param_count; i++) { + param[i] = cpu_vmemoryread_d(CPU_SS_INDEX, old_esp + i * 4); + VERBOSE(("CALLfar_pm: get param[%d] = %08x", i, param[i])); + } + + load_ss(ss_sel.selector, &ss_sel.desc, ss_sel.desc.dpl); + if (CPU_STAT_SS32) { + CPU_ESP = new_esp; + } else { + CPU_SP = (UINT16)new_esp; + } + + load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->desc.dpl); + CPU_EIP = callgate_sel->desc.u.gate.offset; + + PUSH0_32(old_ss); + PUSH0_32(old_esp); + + /* restore param */ + for (i = param_count; i > 0; i--) { + PUSH0_32(param[i - 1]); + VERBOSE(("CALLfar_pm: set param[%d] = %08x", i - 1, param[i - 1])); + } + + PUSH0_32(old_cs); + PUSH0_32(old_eip); + } else { + /* dump param */ + for (i = 0; i < param_count; i++) { + param[i] = cpu_vmemoryread_w(CPU_SS_INDEX, old_esp + i * 2); + VERBOSE(("CALLfar_pm: get param[%d] = %04x", i, param[i])); + } + + load_ss(ss_sel.selector, &ss_sel.desc, ss_sel.desc.dpl); + if (CPU_STAT_SS32) { + CPU_ESP = new_esp; + } else { + CPU_SP = (UINT16)new_esp; + } + + load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->desc.dpl); + CPU_EIP = callgate_sel->desc.u.gate.offset; + + PUSH0_16(old_ss); + PUSH0_16(old_esp); + + /* restore param */ + for (i = param_count; i > 0; i--) { + PUSH0_16(param[i - 1]); + VERBOSE(("CALLfar_pm: set param[%d] = %04x", i - 1, param[i - 1])); + } + + PUSH0_16(old_cs); + PUSH0_16(old_eip); + } +} + +/*--- + * CALLfar_pm: task gate + */ +static void CPUCALL +CALLfar_pm_task_gate(selector_t *taskgate_sel) +{ + selector_t tss_sel; + int rv; + + VERBOSE(("CALLfar_pm: TASK-GATE")); + + /* check privilege level */ + if (taskgate_sel->desc.dpl < CPU_STAT_CPL) { + VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", taskgate_sel->desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, taskgate_sel->idx); + } + if (taskgate_sel->desc.dpl < taskgate_sel->rpl) { + VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", taskgate_sel->desc.dpl, taskgate_sel->rpl)); + EXCEPTION(GP_EXCEPTION, taskgate_sel->idx); + } + + /* not present */ + if (selector_is_not_present(taskgate_sel)) { + VERBOSE(("CALLfar_pm: selector is not present")); + EXCEPTION(NP_EXCEPTION, taskgate_sel->idx); + } + + /* tss descriptor */ + rv = parse_selector(&tss_sel, taskgate_sel->desc.u.gate.selector); + if (rv < 0 || tss_sel.ldt) { + VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d, %cDT)", tss_sel.selector, rv, tss_sel.ldt ? 'L' : 'G')); + EXCEPTION(GP_EXCEPTION, tss_sel.idx); + } + + /* check descriptor type */ + switch (tss_sel.desc.type) { + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_TSS_32: + break; + + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + VERBOSE(("CALLfar_pm: task is busy")); + /*FALLTHROUGH*/ + default: + VERBOSE(("CALLfar_pm: invalid descriptor type (type = %d)", tss_sel.desc.type)); + EXCEPTION(GP_EXCEPTION, tss_sel.idx); + break; + } + + /* not present */ + if (selector_is_not_present(&tss_sel)) { + VERBOSE(("CALLfar_pm: TSS selector is not present")); + EXCEPTION(NP_EXCEPTION, tss_sel.idx); + } + + task_switch(&tss_sel, TASK_SWITCH_CALL); + + /* out of range */ + if (CPU_EIP > CPU_STAT_CS_LIMIT) { + VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); + EXCEPTION(GP_EXCEPTION, 0); + } +} + +/*--- + * CALLfar_pm: TSS + */ +static void CPUCALL +CALLfar_pm_tss(selector_t *tss_sel) +{ + + VERBOSE(("TASK-STATE-SEGMENT")); + + /* check privilege level */ + if (tss_sel->desc.dpl < CPU_STAT_CPL) { + VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", tss_sel->desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, tss_sel->idx); + } + if (tss_sel->desc.dpl < tss_sel->rpl) { + VERBOSE(("CALLfar_pm: DPL(%d) < CPL(%d)", tss_sel->desc.dpl, tss_sel->rpl)); + EXCEPTION(GP_EXCEPTION, tss_sel->idx); + } + + /* not present */ + if (selector_is_not_present(tss_sel)) { + VERBOSE(("CALLfar_pm: TSS selector is not present")); + EXCEPTION(NP_EXCEPTION, tss_sel->idx); + } + + task_switch(tss_sel, TASK_SWITCH_CALL); + + /* out of range */ + if (CPU_EIP > CPU_STAT_CS_LIMIT) { + VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); + EXCEPTION(GP_EXCEPTION, 0); + } +} + + +/*------------------------------------------------------------------------------ + * RETfar_pm + */ + +void CPUCALL +RETfar_pm(UINT nbytes) +{ + selector_t cs_sel, ss_sel, temp_sel; + descriptor_t *sdp; + UINT32 sp; + UINT32 new_ip, new_sp; + UINT16 new_cs, new_ss; + int rv; + int i; + + VERBOSE(("RETfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x, nbytes = %d", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP, nbytes)); + + if (CPU_STAT_SS32) { + sp = CPU_ESP; + } else { + sp = CPU_SP; + } + if (CPU_INST_OP32) { + SS_POP_CHECK(sp, nbytes + 8); + new_ip = cpu_vmemoryread_d(CPU_SS_INDEX, sp); + new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4); + } else { + SS_POP_CHECK(sp, nbytes + 4); + new_ip = cpu_vmemoryread_w(CPU_SS_INDEX, sp); + new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 2); + } + + rv = parse_selector(&cs_sel, new_cs); + if (rv < 0) { + VERBOSE(("RETfar_pm: parse_selector (selector = %04x, rv = %d)", cs_sel.selector, rv)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* check segment type */ + if (SEG_IS_SYSTEM(&cs_sel.desc)) { + VERBOSE(("RETfar_pm: return to system segment")); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + if (SEG_IS_DATA(&cs_sel.desc)) { + VERBOSE(("RETfar_pm: return to data segment")); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* check privilege level */ + if (cs_sel.rpl < CPU_STAT_CPL) { + VERBOSE(("RETfar_pm: RPL(%d) < CPL(%d)", cs_sel.rpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc) && (cs_sel.desc.dpl > cs_sel.rpl)) { + VERBOSE(("RETfar_pm: NON-COMFORMING-CODE-SEGMENT and DPL(%d) > RPL(%d)", cs_sel.desc.dpl, cs_sel.rpl)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* not present */ + if (selector_is_not_present(&cs_sel)) { + VERBOSE(("RETfar_pm: returned code segment is not present")); + EXCEPTION(NP_EXCEPTION, cs_sel.idx); + } + + if (cs_sel.rpl == CPU_STAT_CPL) { + VERBOSE(("RETfar_pm: RETURN-TO-SAME-PRIVILEGE-LEVEL")); + + /* check code segment limit */ + if (new_ip > cs_sel.desc.u.seg.limit) { + VERBOSE(("RETfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel.desc.u.seg.limit)); + EXCEPTION(GP_EXCEPTION, 0); + } + + VERBOSE(("RETfar_pm: new_ip = %08x, new_cs = %04x", new_ip, cs_sel.selector)); + + if (CPU_INST_OP32) { + nbytes += 8; + } else { + nbytes += 4; + } + if (CPU_STAT_SS32) { + CPU_ESP += nbytes; + } else { + CPU_SP += (UINT16)nbytes; + } + + load_cs(cs_sel.selector, &cs_sel.desc, CPU_STAT_CPL); + CPU_EIP = new_ip; + } else { + VERBOSE(("RETfar_pm: RETURN-OUTER-PRIVILEGE-LEVEL")); + + if (CPU_INST_OP32) { + SS_POP_CHECK(sp, 8 + 8 + nbytes); + new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 8 + nbytes); + new_ss = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 8 + nbytes + 4); + } else { + SS_POP_CHECK(sp, 4 + 4 + nbytes); + new_sp = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4 + nbytes); + new_ss = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4 + nbytes + 2); + } + + rv = parse_selector(&ss_sel, new_ss); + if (rv < 0) { + VERBOSE(("RETfar_pm: parse_selector (selector = %04x, rv = %d)", ss_sel.selector, rv)); + EXCEPTION(GP_EXCEPTION, (rv == -2) ? 0 : ss_sel.idx); + } + + /* stack segment must be writable data segment. */ + if (SEG_IS_SYSTEM(&ss_sel.desc)) { + VERBOSE(("RETfar_pm: stack segment is system segment")); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + if (SEG_IS_CODE(&ss_sel.desc)) { + VERBOSE(("RETfar_pm: stack segment is code segment")); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + if (!SEG_IS_WRITABLE_DATA(&ss_sel.desc)) { + VERBOSE(("RETfar_pm: stack segment is read-only data segment")); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* check privilege level */ + if (ss_sel.rpl != cs_sel.rpl) { + VERBOSE(("RETfar_pm: selector RPL[SS](%d) != RPL[CS](%d)", ss_sel.rpl, cs_sel.rpl)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + if (ss_sel.desc.dpl != cs_sel.rpl) { + VERBOSE(("RETfar_pm: descriptor DPL[SS](%d) != RPL[CS](%d)", ss_sel.desc.dpl, cs_sel.rpl)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* not present */ + if (selector_is_not_present(&ss_sel)) { + VERBOSE(("RETfar_pm: stack segment is not present")); + EXCEPTION(SS_EXCEPTION, ss_sel.idx); + } + + /* check code segment limit */ + if (new_ip > cs_sel.desc.u.seg.limit) { + VERBOSE(("RETfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel.desc.u.seg.limit)); + EXCEPTION(GP_EXCEPTION, 0); + } + + VERBOSE(("RETfar_pm: new_ip = %08x, new_cs = %04x", new_ip, cs_sel.selector)); + VERBOSE(("RETfar_pm: new_sp = %08x, new_ss = %04x", new_sp, ss_sel.selector)); + + load_ss(ss_sel.selector, &ss_sel.desc, cs_sel.rpl); + if (CPU_STAT_SS32) { + CPU_ESP = new_sp + nbytes; + } else { + CPU_SP = (UINT16)(new_sp + nbytes); + } + + load_cs(cs_sel.selector, &cs_sel.desc, cs_sel.rpl); + CPU_EIP = new_ip; + + /* check segment register */ + for (i = 0; i < CPU_SEGREG_NUM; i++) { + if (i == CPU_SS_INDEX || i == CPU_CS_INDEX) + continue; + + sdp = &CPU_STAT_SREG(i); + if ((SEG_IS_DATA(sdp) || !SEG_IS_CONFORMING_CODE(sdp)) + && (CPU_STAT_CPL > sdp->dpl)) { + /* current segment descriptor is invalid */ + CPU_REGS_SREG(i) = 0; + memset(sdp, 0, sizeof(*sdp)); + continue; + } + + /* Reload segment descriptor */ + rv = parse_selector(&temp_sel, CPU_REGS_SREG(i)); + if (rv < 0) { + /* segment register is invalid */ + CPU_REGS_SREG(i) = 0; + memset(sdp, 0, sizeof(*sdp)); + continue; + } + + /* + * - system segment + * - execute-only code segment + * - data or conforming code segment && CPL > DPL + */ + if (SEG_IS_SYSTEM(&temp_sel.desc) + || (SEG_IS_CODE(&temp_sel.desc) + && !SEG_IS_READABLE_CODE(&temp_sel.desc)) + || ((SEG_IS_DATA(&temp_sel.desc) + || !SEG_IS_CONFORMING_CODE(&temp_sel.desc)) + && (CPU_STAT_CPL > temp_sel.desc.dpl))) { + /* segment descriptor is invalid */ + CPU_REGS_SREG(i) = 0; + memset(sdp, 0, sizeof(*sdp)); + } + } + } + + VERBOSE(("RETfar_pm: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); +} + + +/*------------------------------------------------------------------------------ + * IRET_pm + */ +static void IRET_pm_nested_task(void); +static void CPUCALL IRET_pm_protected_mode_return(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); +static void CPUCALL IRET_pm_protected_mode_return_same_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags); +static void CPUCALL IRET_pm_protected_mode_return_outer_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags); +static void CPUCALL IRET_pm_return_to_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); +static void CPUCALL IRET_pm_return_from_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags); + +void +IRET_pm(void) +{ + UINT32 sp; + UINT32 new_ip, new_flags; + UINT16 new_cs; + + VERBOSE(("IRET_pm: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP)); + + if (!(CPU_EFLAG & VM_FLAG) && (CPU_EFLAG & NT_FLAG)) { + /* TASK-RETURN: PE=1, VM=0, NT=1 */ + IRET_pm_nested_task(); + } else { + if (CPU_STAT_SS32) { + sp = CPU_ESP; + } else { + sp = CPU_SP; + } + if (CPU_INST_OP32) { + SS_POP_CHECK(sp, 12); + new_ip = cpu_vmemoryread_d(CPU_SS_INDEX, sp); + new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4); + new_flags = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 8); + } else { + SS_POP_CHECK(sp, 6); + new_ip = cpu_vmemoryread_w(CPU_SS_INDEX, sp); + new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 2); + new_flags = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4); + } + + VERBOSE(("IRET_pm: new_ip = %08x, new_cs = %04x, new_eflags = %08x", new_ip, new_cs, new_flags)); + + if (CPU_EFLAG & VM_FLAG) { + /* RETURN-FROM-VIRTUAL-8086-MODE */ + IRET_pm_return_from_vm86(new_cs, new_ip, new_flags); + } else if ((new_flags & VM_FLAG) && CPU_STAT_CPL == 0) { + /* RETURN-TO-VIRTUAL-8086-MODE */ + IRET_pm_return_to_vm86(new_cs, new_ip, new_flags); + } else { + /* PROTECTED-MODE-RETURN */ + IRET_pm_protected_mode_return(new_cs, new_ip, new_flags); + } + } + + VERBOSE(("IRET_pm: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); +} + +/*--- + * IRET_pm: NT_FLAG + */ +static void +IRET_pm_nested_task(void) +{ + selector_t tss_sel; + UINT16 new_tss; + int rv; + + VERBOSE(("IRET_pm: TASK-RETURN: PE=1, VM=0, NT=1")); + + new_tss = get_backlink_selector_from_tss(); + + rv = parse_selector(&tss_sel, new_tss); + if (rv < 0 || tss_sel.ldt) { + VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d, %cDT)", tss_sel.selector, rv, tss_sel.ldt ? 'L' : 'G')); + EXCEPTION(GP_EXCEPTION, tss_sel.idx); + } + + /* check system segment */ + if (!SEG_IS_SYSTEM(&tss_sel.desc)) { + VERBOSE(("IRET_pm: task segment is %s segment", tss_sel.desc.u.seg.c ? "code" : "data")); + EXCEPTION(GP_EXCEPTION, tss_sel.idx); + } + + switch (tss_sel.desc.type) { + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + break; + + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_TSS_32: + VERBOSE(("IRET_pm: task is not busy")); + /*FALLTHROUGH*/ + default: + VERBOSE(("IRET_pm: invalid descriptor type (type = %d)", tss_sel.desc.type)); + EXCEPTION(GP_EXCEPTION, tss_sel.idx); + break; + } + + /* not present */ + if (selector_is_not_present(&tss_sel)) { + VERBOSE(("IRET_pm: tss segment is not present")); + EXCEPTION(NP_EXCEPTION, tss_sel.idx); + } + + task_switch(&tss_sel, TASK_SWITCH_IRET); + + /* out of range */ + if (CPU_EIP > CPU_STAT_CS_LIMIT) { + VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); + EXCEPTION(GP_EXCEPTION, 0); + } +} + +/*--- + * IRET_pm: PROTECTED-MODE-RETURN + */ +static void CPUCALL +IRET_pm_protected_mode_return(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags) +{ + selector_t cs_sel; + int rv; + + /* PROTECTED-MODE-RETURN */ + VERBOSE(("IRET_pm: PE=1, VM=0 in flags image")); + + rv = parse_selector(&cs_sel, new_cs); + if (rv < 0) { + VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d)", cs_sel.selector, rv)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* check code segment descriptor */ + if (SEG_IS_SYSTEM(&cs_sel.desc)) { + VERBOSE(("IRET_pm: return code segment is system segment")); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + if (SEG_IS_DATA(&cs_sel.desc)) { + VERBOSE(("IRET_pm: return code segment is data segment")); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* check privilege level */ + if (cs_sel.rpl < CPU_STAT_CPL) { + VERBOSE(("IRET_pm: RPL(%d) < CPL(%d)", cs_sel.rpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + if (SEG_IS_CONFORMING_CODE(&cs_sel.desc) && (cs_sel.desc.dpl > cs_sel.rpl)) { + VERBOSE(("IRET_pm: CONFORMING-CODE-SEGMENT and DPL(%d) > RPL(%d)", cs_sel.desc.dpl, cs_sel.rpl)); + EXCEPTION(GP_EXCEPTION, cs_sel.idx); + } + + /* not present */ + if (selector_is_not_present(&cs_sel)) { + VERBOSE(("IRET_pm: code segment is not present")); + EXCEPTION(NP_EXCEPTION, cs_sel.idx); + } + + if (cs_sel.rpl > CPU_STAT_CPL) { + IRET_pm_protected_mode_return_outer_privilege(&cs_sel, new_ip, new_flags); + } else { + IRET_pm_protected_mode_return_same_privilege(&cs_sel, new_ip, new_flags); + } +} + +/*--- + * IRET_pm: SAME-PRIVILEGE + */ +static void CPUCALL +IRET_pm_protected_mode_return_same_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags) +{ + UINT32 mask; + UINT stacksize; + + VERBOSE(("IRET_pm: RETURN-TO-SAME-PRIVILEGE-LEVEL")); + + /* check code segment limit */ + if (new_ip > cs_sel->desc.u.seg.limit) { + VERBOSE(("IRET_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel->desc.u.seg.limit)); + EXCEPTION(GP_EXCEPTION, 0); + } + + mask = 0; + if (CPU_INST_OP32) + mask |= RF_FLAG; + if (CPU_STAT_CPL <= CPU_STAT_IOPL) + mask |= I_FLAG; + if (CPU_STAT_CPL == 0) { + mask |= IOPL_FLAG; + if (CPU_INST_OP32) { + mask |= VM_FLAG|VIF_FLAG|VIP_FLAG; + } + } + + if (CPU_INST_OP32) { + stacksize = 12; + } else { + stacksize = 6; + } + + /* set new register */ + load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL); + CPU_EIP = new_ip; + + if (CPU_STAT_SS32) { + CPU_ESP += stacksize; + } else { + CPU_SP += (UINT16)stacksize; + } + + set_eflags(new_flags, mask); +} + +/*--- + * IRET_pm: OUTER-PRIVILEGE + */ +static void CPUCALL +IRET_pm_protected_mode_return_outer_privilege(const selector_t *cs_sel, UINT32 new_ip, UINT32 new_flags) +{ + descriptor_t *sdp; + selector_t ss_sel; + UINT32 mask; + UINT32 sp; + UINT32 new_sp; + UINT16 new_ss; + int rv; + int i; + + VERBOSE(("IRET_pm: RETURN-OUTER-PRIVILEGE-LEVEL")); + + if (CPU_STAT_SS32) { + sp = CPU_ESP; + } else { + sp = CPU_SP; + } + if (CPU_INST_OP32) { + SS_POP_CHECK(sp, 20); + new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 12); + new_ss = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 16); + } else { + SS_POP_CHECK(sp, 10); + new_sp = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 6); + new_ss = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 8); + } + VERBOSE(("IRET_pm: new_sp = 0x%08x, new_ss = 0x%04x", new_sp, new_ss)); + + rv = parse_selector(&ss_sel, new_ss); + if (rv < 0) { + VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d)", ss_sel.selector, rv)); + EXCEPTION(GP_EXCEPTION, (rv == -2) ? 0 : ss_sel.idx); + } + + /* check privilege level */ + if (ss_sel.rpl != cs_sel->rpl) { + VERBOSE(("IRET_pm: selector RPL[SS](%d) != RPL[CS](%d)", ss_sel.rpl, cs_sel->rpl)); + EXCEPTION(GP_EXCEPTION, ss_sel.idx); + } +#if 0 + if (ss_sel.desc.dpl != cs_sel->rpl) { + VERBOSE(("IRET_pm: segment DPL[SS](%d) != RPL[CS](%d)", ss_sel.desc.dpl, cs_sel->rpl)); + EXCEPTION(GP_EXCEPTION, ss_sel.idx); + } + if (ss_sel.desc.rpl != cs_sel->rpl) { + VERBOSE(("IRET_pm: segment RPL[SS](%d) != RPL[CS](%d)", ss_sel.desc.rpl, cs_sel->rpl)); + EXCEPTION(GP_EXCEPTION, ss_sel.idx); + } +#endif + + /* stack segment must be writable data segment. */ + if (SEG_IS_SYSTEM(&ss_sel.desc)) { + VERBOSE(("IRET_pm: stack segment is system segment")); + EXCEPTION(GP_EXCEPTION, ss_sel.idx); + } + if (SEG_IS_CODE(&ss_sel.desc)) { + VERBOSE(("IRET_pm: stack segment is code segment")); + EXCEPTION(GP_EXCEPTION, ss_sel.idx); + } + if (!SEG_IS_WRITABLE_DATA(&ss_sel.desc)) { + VERBOSE(("IRET_pm: stack segment is read-only data segment")); + EXCEPTION(GP_EXCEPTION, ss_sel.idx); + } + + /* not present */ + if (selector_is_not_present(&ss_sel)) { + VERBOSE(("IRET_pm: stack segment is not present")); + EXCEPTION(SS_EXCEPTION, ss_sel.idx); + } + + /* check code segment limit */ + if (new_ip > cs_sel->desc.u.seg.limit) { + VERBOSE(("IRET_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel->desc.u.seg.limit)); + EXCEPTION(GP_EXCEPTION, 0); + } + + mask = 0; + if (CPU_INST_OP32) + mask |= RF_FLAG; + if (CPU_STAT_CPL <= CPU_STAT_IOPL) + mask |= I_FLAG; + if (CPU_STAT_CPL == 0) { + mask |= IOPL_FLAG; + if (CPU_INST_OP32) { + mask |= VM_FLAG|VIF_FLAG|VIP_FLAG; + } + } + + /* set new register */ + load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->rpl); + CPU_EIP = new_ip; + + load_ss(ss_sel.selector, &ss_sel.desc, cs_sel->rpl); + if (CPU_STAT_SS32) { + CPU_ESP = new_sp; + } else { + CPU_SP = (UINT16)new_sp; + } + + set_eflags(new_flags, mask); + + /* check segment register */ + for (i = 0; i < CPU_SEGREG_NUM; i++) { + if ((i != CPU_CS_INDEX) && (i != CPU_SS_INDEX)) { + sdp = &CPU_STAT_SREG(i); + if ((SEG_IS_DATA(sdp) || !SEG_IS_CONFORMING_CODE(sdp)) + && (sdp->dpl < CPU_STAT_CPL)) { + /* segment register is invalid */ + CPU_REGS_SREG(i) = 0; + memset(sdp, 0, sizeof(*sdp)); + } + } + } +} + +/*--- + * IRET_pm: new_flags & VM_FLAG + */ +static void CPUCALL +IRET_pm_return_to_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags) +{ + UINT16 segsel[CPU_SEGREG_NUM]; + UINT32 sp; + UINT32 new_sp; + int i; + + VERBOSE(("IRET_pm: Interrupt procedure was in virtual-8086 mode: PE=1, VM=1 in flags image")); + + if (!CPU_INST_OP32) { + ia32_panic("IRET_pm: 16bit mode"); + } + + if (CPU_STAT_SS32) { + sp = CPU_ESP; + } else { + sp = CPU_SP; + } + SS_POP_CHECK(sp, 36); + + new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 12); + segsel[CPU_SS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 16); + segsel[CPU_ES_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 20); + segsel[CPU_DS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 24); + segsel[CPU_FS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 28); + segsel[CPU_GS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 32); + segsel[CPU_CS_INDEX] = new_cs; + + for (i = 0; i < CPU_SEGREG_NUM; i++) { + segdesc_init(i, segsel[i], &CPU_STAT_SREG(i)); + } + + CPU_ESP = new_sp; + CPU_EIP = new_ip & 0xffff; + + /* to VM86 mode */ + set_eflags(new_flags, IOPL_FLAG|I_FLAG|VM_FLAG|RF_FLAG); +} + +/*--- + * IRET_pm: VM_FLAG + */ +static void CPUCALL +IRET_pm_return_from_vm86(UINT16 new_cs, UINT32 new_ip, UINT32 new_flags) +{ + UINT stacksize; + + VERBOSE(("IRET_pm: virtual-8086 mode: VM=1")); + + if (CPU_STAT_IOPL == CPU_IOPL3) { + VERBOSE(("IRET_pm: virtual-8086 mode: IOPL=3")); +//vme_emulate: + if (CPU_INST_OP32) { + stacksize = 12; + } else { + stacksize = 6; + } + if (CPU_STAT_SS32) { + CPU_ESP += stacksize; + } else { + CPU_SP += stacksize; + } + + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; + + set_eflags(new_flags, I_FLAG|RF_FLAG); + return; + } + VERBOSE(("IRET_pm: trap to virtual-8086 monitor: VM=1, IOPL<3")); +#if defined(USE_VME) + //if(CPU_CR4 & CPU_CR4_VME){ + // if((CPU_EFLAG & VIP_FLAG) || (CPU_EFLAG & T_FLAG)){ + // EXCEPTION(GP_EXCEPTION, 0); + // }else{ + // new_flags = (new_flags & ~VIF_FLAG) | ((new_flags & I_FLAG) << 10); // IF → VIFにコピー + // new_flags = (new_flags & ~(IOPL_FLAG|I_FLAG)) | (CPU_EFLAG & (IOPL_FLAG|I_FLAG)); // IF, IOPLは変更させない + // goto vme_emulate; + // } + //}else{ + // EXCEPTION(GP_EXCEPTION, 0); + //} + EXCEPTION(GP_EXCEPTION, 0); // XXX: 一応動いてるけど実装しないとまずい・・・? +#else + EXCEPTION(GP_EXCEPTION, 0); +#endif +} diff --git a/i386c/ia32/ctrlxfer.h b/i386c/ia32/ctrlxfer.h old mode 100755 new mode 100644 index 39ebe021..da62f317 --- a/i386c/ia32/ctrlxfer.h +++ b/i386c/ia32/ctrlxfer.h @@ -1,42 +1,42 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_CTRLXFER_H__ -#define IA32_CPU_CTRLXFER_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -void CPUCALL JMPfar_pm(UINT16 selector, UINT32 new_ip); -void CPUCALL CALLfar_pm(UINT16 selector, UINT32 new_ip); -void CPUCALL RETfar_pm(UINT nbytes); -void IRET_pm(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_CTRLXFER_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_CTRLXFER_H__ +#define IA32_CPU_CTRLXFER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void CPUCALL JMPfar_pm(UINT16 selector, UINT32 new_ip); +void CPUCALL CALLfar_pm(UINT16 selector, UINT32 new_ip); +void CPUCALL RETfar_pm(UINT nbytes); +void IRET_pm(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_CTRLXFER_H__ */ diff --git a/i386c/ia32/debug.c b/i386c/ia32/debug.c old mode 100755 new mode 100644 index ddd41a68..e3a90c44 --- a/i386c/ia32/debug.c +++ b/i386c/ia32/debug.c @@ -1,402 +1,402 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include - -#include "cpu.h" -#if defined(USE_FPU) -#include "instructions/fpu/fp.h" -#endif - - -/* - * register strings - */ -const char *reg8_str[CPU_REG_NUM] = { - "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" -}; - -const char *reg16_str[CPU_REG_NUM] = { - "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" -}; - -const char *reg32_str[CPU_REG_NUM] = { - "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" -}; - -const char *sreg_str[CPU_SEGREG_NUM] = { - "es", "cs", "ss", "ds", "fs", "gs" -}; - - -char * -cpu_reg2str(void) -{ - static char buf[512]; - - snprintf(buf, sizeof(buf), - "eax=%08x ecx=%08x edx=%08x ebx=%08x\n" - "esp=%08x ebp=%08x esi=%08x edi=%08x\n" - "eip=%08x prev_eip=%08x\n" - "cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x\n" - "eflag=%08x " - /* ID VIP VIF AC VM RF NT IOPL OF DF IF TF SF ZF AF PF CF */ - "[ ID=%d VIP=%d VIF=%d AC=%d VM=%d RF=%d NT=%d IOPL=%d %s %s %s TF=%d %s %s %s %s %s ]\n" - "gdtr=%08x:%04x idtr=%08x:%04x\n" - "ldtr=%04x(%08x:%04x) tr=%04x(%08x:%04x)\n" - "cr0=%08x cr1=%08x cr2=%08x cr3=%08x cr4=%08x mxcsr=%08x", - CPU_EAX, CPU_ECX, CPU_EDX, CPU_EBX, - CPU_ESP, CPU_EBP,CPU_ESI, CPU_EDI, - CPU_EIP, CPU_PREV_EIP, - CPU_CS, CPU_SS, CPU_DS, CPU_ES, CPU_FS, CPU_GS, - CPU_EFLAG, - (CPU_EFLAG & ID_FLAG) != 0, - (CPU_EFLAG & VIP_FLAG) != 0, - (CPU_EFLAG & VIF_FLAG) != 0, - (CPU_EFLAG & AC_FLAG) != 0, - (CPU_EFLAG & VM_FLAG) != 0, - (CPU_EFLAG & RF_FLAG) != 0, - (CPU_EFLAG & NT_FLAG) != 0, - (int)((CPU_EFLAG >> 12) & 3), - CPU_OV ? "OV" : "NV", - CPU_EFLAG & D_FLAG ? "UP" : "DN", - CPU_EFLAG & I_FLAG ? "DI" : "EI", - (CPU_EFLAG & T_FLAG) != 0, - CPU_EFLAG & S_FLAG ? "NG" : "PL", - CPU_EFLAG & Z_FLAG ? "ZR" : "NZ", - CPU_EFLAG & A_FLAG ? "AC" : "NA", - CPU_EFLAG & P_FLAG ? "PE" : "PO", - CPU_EFLAG & C_FLAG ? "CY" : "NC", - CPU_GDTR_BASE, CPU_GDTR_LIMIT, CPU_IDTR_BASE, CPU_IDTR_LIMIT, - CPU_LDTR, CPU_LDTR_BASE, CPU_LDTR_LIMIT, - CPU_TR, CPU_TR_BASE, CPU_TR_LIMIT, - CPU_CR0, CPU_CR1, CPU_CR2, CPU_CR3, CPU_CR4, CPU_MXCSR); - - return buf; -} - -static char * -a20str(void) -{ - static char buf[32]; - - snprintf(buf, sizeof(buf), "a20line=%s\n", - (CPU_STAT_ADRSMASK == 0xffffffff) ? "enable" : "disable"); - return buf; -} - -void -put_cpuinfo(void) -{ - char buf[2048]; - - strcpy(buf, cpu_reg2str()); - strcat(buf, "\n"); -#if defined(USE_FPU) - strcat(buf, fpu_reg2str()); - strcat(buf, "\n"); -#endif - strcat(buf, a20str()); - - printf("%s", buf); -} - -void -dbg_printf(const char *str, ...) -{ - char buf[1024]; - va_list ap; - - va_start(ap, str); - vsnprintf(buf, sizeof(buf), str, ap); - va_end(ap); - buf[NELEMENTS(buf) - 2] = '\0'; - strcat(buf, "\n"); - - printf("%s", buf); -} - -void -memory_dump(int idx, UINT32 madr) -{ - UINT32 addr; - UINT32 size; - UINT32 s, i; - UINT8 buf[16]; - UINT8 c; - - if (madr < 0x80) { - size = madr + 0x80; - addr = 0; - } else { - size = 0x100; - addr = madr - 0x80; - } - VERBOSE(("memory dump\n--")); - for (s = 0; s < size; s++) { - if ((s % 16) == 0) { - VERBOSE(("%08x: ", addr + s)); - memset(buf, '.', sizeof(buf)); - } - - c = cpu_vmemoryread(idx, addr + s); - VERBOSE(("%02x ", c)); - if (c >= 0x20 && c <= 0x7e) - buf[s % 16] = c; - - if ((s % 16) == 15) { - VERBOSE(("| ")); - for (i = 0; i < sizeof(buf); i++) - VERBOSE(("%c", buf[i])); - VERBOSE(("\n")); - } - } -} - -void -gdtr_dump(UINT32 base, UINT limit) -{ - UINT32 v[2]; - UINT i; - - VERBOSE(("GDTR_DUMP: GDTR_BASE = 0x%08x, GDTR_LIMIT = 0x%04x", base, limit)); - - for (i = 0; i < limit; i += 8) { - v[0] = cpu_kmemoryread_d(base + i); - v[1] = cpu_kmemoryread_d(base + i + 4); - VERBOSE(("GDTR_DUMP: %08x: %08x%08x", base + i, v[0], v[1])); - } -} - -void -ldtr_dump(UINT32 base, UINT limit) -{ - UINT32 v[2]; - UINT i; - - VERBOSE(("LDTR_DUMP: LDTR_BASE = 0x%08x, LDTR_LIMIT = 0x%04x", base, limit)); - - for (i = 0; i < limit; i += 8) { - v[0] = cpu_kmemoryread_d(base + i); - v[1] = cpu_kmemoryread_d(base + i + 4); - VERBOSE(("LDTR_DUMP: %08x: %08x%08x", base + i, v[0], v[1])); - } -} - -void -idtr_dump(UINT32 base, UINT limit) -{ - UINT32 v[2]; - UINT i; - - VERBOSE(("IDTR_DUMP: IDTR_BASE = 0x%08x, IDTR_LIMIT = 0x%04x", base, limit)); - - for (i = 0; i < limit; i += 8) { - v[0] = cpu_kmemoryread_d(base + i); - v[1] = cpu_kmemoryread_d(base + i + 4); - VERBOSE(("IDTR_DUMP: %08x: %08x%08x", base + i, v[0], v[1])); - } -} - -void -tr_dump(UINT16 selector, UINT32 base, UINT limit) -{ - UINT32 v; - UINT i; - - VERBOSE(("TR_DUMP: selector = %04x", selector)); - - for (i = 0; i < limit; i += 4) { - v = cpu_kmemoryread_d(base + i); - VERBOSE(("TR_DUMP: %08x: %08x", base + i, v)); - } -} - -UINT32 -pde_dump(UINT32 base, int idx) -{ - UINT32 paddr; - UINT32 v; - int i; - - if (idx < 0 && idx > -8192) { - idx = -idx; - VERBOSE(("PDE_DUMP: address = 0x%08x, num = %d", base, idx)); - for (i = 0; i < idx; i++) { - paddr = (base & CPU_CR3_PD_MASK) | (idx << 2); - v = cpu_memoryread_d(paddr); - VERBOSE(("PDE_DUMP: 0x%08x: %08x", paddr, v)); - } - paddr = 0; - } else if (idx < 8192) { - VERBOSE(("PDE_DUMP: address = 0x%08x", base)); - paddr = (base & CPU_CR3_PD_MASK) | (idx << 2); - v = cpu_memoryread_d(paddr); - VERBOSE(("PDE_DUMP: 0x%08x: %08x", paddr, v)); - } else { - VERBOSE(("PDE_DUMP: invalid idx (%d)", idx)); - paddr = 0; - } - - return paddr; -} - -void -segdesc_dump(descriptor_t *sdp) -{ -#if defined(DEBUG) - const char *s; - - __ASSERT(sdp != NULL); - - VERBOSE(("dump descriptor: %p", sdp)); - - VERBOSE(("valid : %s", SEG_IS_VALID(sdp) ? "true" : "false")); - VERBOSE(("present : %s", SEG_IS_PRESENT(sdp) ? "true" : "false")); - VERBOSE(("DPL : %d", sdp->dpl)); - VERBOSE(("type : %d", sdp->type)); - VERBOSE(("kind : %s", SEG_IS_SYSTEM(sdp) ? "system" : "code/data")); - if (!SEG_IS_SYSTEM(sdp)) { - if (SEG_IS_CODE(sdp)) { - VERBOSE(("type : %dbit %sconforming code", - SEG_IS_32BIT(sdp) ? 32 : 16, - SEG_IS_CONFORMING_CODE(sdp) ? "" : "non-")); - VERBOSE(("access : execute%s", - SEG_IS_READABLE_CODE(sdp) ? "/read" : "")); - } else { - VERBOSE(("type : %dbit expand-%s data", - SEG_IS_32BIT(sdp) ? 32 : 16, - SEG_IS_EXPANDDOWN_DATA(sdp) ? "down" : "up")); - VERBOSE(("access : read%s", - SEG_IS_WRITABLE_DATA(sdp) ? "/write" : "")); - } - VERBOSE(("4k scale : %s", sdp->u.seg.g ? "true" : "false")); - VERBOSE(("baseadr : 0x%08x", sdp->u.seg.segbase)); - VERBOSE(("limit : 0x%08x", sdp->u.seg.limit)); - } else { - switch (sdp->type) { - case CPU_SYSDESC_TYPE_LDT: /* LDT */ - VERBOSE(("type : LDT")); - VERBOSE(("4k scale : %s", sdp->u.seg.g ? "true" : "false")); - VERBOSE(("baseadr : 0x%08x", sdp->u.seg.segbase)); - VERBOSE(("limit : 0x%08x", sdp->u.seg.limit)); - break; - - case CPU_SYSDESC_TYPE_TASK: /* task gate */ - VERBOSE(("type : task gate")); - VERBOSE(("selector : 0x%04x", sdp->u.gate.selector)); - break; - - case CPU_SYSDESC_TYPE_TSS_16: /* 286 TSS */ - case CPU_SYSDESC_TYPE_TSS_BUSY_16: /* 286 Busy TSS */ - case CPU_SYSDESC_TYPE_TSS_32: /* 386 TSS */ - case CPU_SYSDESC_TYPE_TSS_BUSY_32: /* 386 Busy TSS */ - VERBOSE(("type : %dbit %sTSS", - (sdp->type & CPU_SYSDESC_TYPE_32BIT) ? 32 : 16, - (sdp->type & CPU_SYSDESC_TYPE_TSS_BUSY_IND) ? - "Busy " : "")); - VERBOSE(("4k scale : %s", sdp->u.seg.g ? "true" : "false")); - VERBOSE(("baseadr : 0x%08x", sdp->u.seg.segbase)); - VERBOSE(("limit : 0x%08x", sdp->u.seg.limit)); - break; - - case CPU_SYSDESC_TYPE_CALL_16: /* 286 call gate */ - case CPU_SYSDESC_TYPE_INTR_16: /* 286 interrupt gate */ - case CPU_SYSDESC_TYPE_TRAP_16: /* 286 trap gate */ - case CPU_SYSDESC_TYPE_CALL_32: /* 386 call gate */ - case CPU_SYSDESC_TYPE_INTR_32: /* 386 interrupt gate */ - case CPU_SYSDESC_TYPE_TRAP_32: /* 386 trap gate */ - switch (sdp->type & CPU_SYSDESC_TYPE_MASKBIT) { - case CPU_SYSDESC_TYPE_CALL: - s = "call"; - break; - - case CPU_SYSDESC_TYPE_INTR: - s = "interrupt"; - break; - - case CPU_SYSDESC_TYPE_TRAP: - s = "trap"; - break; - - default: - s = "unknown"; - break; - } - VERBOSE(("type : %c86 %s gate", - (sdp->type & CPU_SYSDESC_TYPE_32BIT) ? '3':'2', s)); - VERBOSE(("selector : 0x%04x", sdp->u.gate.selector)); - VERBOSE(("offset : 0x%08x", sdp->u.gate.offset)); - VERBOSE(("count : %d", sdp->u.gate.count)); - break; - - case 0: case 8: case 10: case 13: /* reserved */ - default: - VERBOSE(("type : unknown descriptor")); - break; - } - } -#endif -} - -UINT32 -convert_laddr_to_paddr(UINT32 laddr) -{ - UINT32 paddr; /* physical address */ - UINT32 pde_addr; /* page directory entry address */ - UINT32 pde; /* page directory entry */ - UINT32 pte_addr; /* page table entry address */ - UINT32 pte; /* page table entry */ - - pde_addr = (CPU_CR3 & CPU_CR3_PD_MASK) | ((laddr >> 20) & 0xffc); - pde = cpu_memoryread_d(pde_addr); - - if ((CPU_CR4 & CPU_CR4_PSE) && (pde & CPU_PDE_PAGE_SIZE)) { - /* 4MB page size */ - paddr = (pde & CPU_PDE_4M_BASEADDR_MASK) | (laddr & 0x003fffff); - } else { - /* 4KB page size */ - pte_addr = (pde & CPU_PDE_BASEADDR_MASK) | ((laddr >> 10) & 0xffc); - pte = cpu_memoryread_d(pte_addr); - paddr = (pte & CPU_PTE_BASEADDR_MASK) | (laddr & 0x00000fff); - } - return paddr; -} - -UINT32 -convert_vaddr_to_paddr(unsigned int idx, UINT32 offset) -{ - descriptor_t *sdp; - UINT32 laddr; - - if (idx < CPU_SEGREG_NUM) { - sdp = &CPU_STAT_SREG(idx); - if (SEG_IS_VALID(sdp)) { - laddr = CPU_STAT_SREGBASE(idx) + offset; - return convert_laddr_to_paddr(laddr); - } - } - return 0; -} +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include + +#include "cpu.h" +#if defined(USE_FPU) +#include "instructions/fpu/fp.h" +#endif + + +/* + * register strings + */ +const char *reg8_str[CPU_REG_NUM] = { + "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" +}; + +const char *reg16_str[CPU_REG_NUM] = { + "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" +}; + +const char *reg32_str[CPU_REG_NUM] = { + "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" +}; + +const char *sreg_str[CPU_SEGREG_NUM] = { + "es", "cs", "ss", "ds", "fs", "gs" +}; + + +char * +cpu_reg2str(void) +{ + static char buf[512]; + + snprintf(buf, sizeof(buf), + "eax=%08x ecx=%08x edx=%08x ebx=%08x\n" + "esp=%08x ebp=%08x esi=%08x edi=%08x\n" + "eip=%08x prev_eip=%08x\n" + "cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x\n" + "eflag=%08x " + /* ID VIP VIF AC VM RF NT IOPL OF DF IF TF SF ZF AF PF CF */ + "[ ID=%d VIP=%d VIF=%d AC=%d VM=%d RF=%d NT=%d IOPL=%d %s %s %s TF=%d %s %s %s %s %s ]\n" + "gdtr=%08x:%04x idtr=%08x:%04x\n" + "ldtr=%04x(%08x:%04x) tr=%04x(%08x:%04x)\n" + "cr0=%08x cr1=%08x cr2=%08x cr3=%08x cr4=%08x mxcsr=%08x", + CPU_EAX, CPU_ECX, CPU_EDX, CPU_EBX, + CPU_ESP, CPU_EBP,CPU_ESI, CPU_EDI, + CPU_EIP, CPU_PREV_EIP, + CPU_CS, CPU_SS, CPU_DS, CPU_ES, CPU_FS, CPU_GS, + CPU_EFLAG, + (CPU_EFLAG & ID_FLAG) != 0, + (CPU_EFLAG & VIP_FLAG) != 0, + (CPU_EFLAG & VIF_FLAG) != 0, + (CPU_EFLAG & AC_FLAG) != 0, + (CPU_EFLAG & VM_FLAG) != 0, + (CPU_EFLAG & RF_FLAG) != 0, + (CPU_EFLAG & NT_FLAG) != 0, + (int)((CPU_EFLAG >> 12) & 3), + CPU_OV ? "OV" : "NV", + CPU_EFLAG & D_FLAG ? "UP" : "DN", + CPU_EFLAG & I_FLAG ? "DI" : "EI", + (CPU_EFLAG & T_FLAG) != 0, + CPU_EFLAG & S_FLAG ? "NG" : "PL", + CPU_EFLAG & Z_FLAG ? "ZR" : "NZ", + CPU_EFLAG & A_FLAG ? "AC" : "NA", + CPU_EFLAG & P_FLAG ? "PE" : "PO", + CPU_EFLAG & C_FLAG ? "CY" : "NC", + CPU_GDTR_BASE, CPU_GDTR_LIMIT, CPU_IDTR_BASE, CPU_IDTR_LIMIT, + CPU_LDTR, CPU_LDTR_BASE, CPU_LDTR_LIMIT, + CPU_TR, CPU_TR_BASE, CPU_TR_LIMIT, + CPU_CR0, CPU_CR1, CPU_CR2, CPU_CR3, CPU_CR4, CPU_MXCSR); + + return buf; +} + +static char * +a20str(void) +{ + static char buf[32]; + + snprintf(buf, sizeof(buf), "a20line=%s\n", + (CPU_STAT_ADRSMASK == 0xffffffff) ? "enable" : "disable"); + return buf; +} + +void +put_cpuinfo(void) +{ + char buf[2048]; + + strcpy(buf, cpu_reg2str()); + strcat(buf, "\n"); +#if defined(USE_FPU) + strcat(buf, fpu_reg2str()); + strcat(buf, "\n"); +#endif + strcat(buf, a20str()); + + printf("%s", buf); +} + +void +dbg_printf(const char *str, ...) +{ + char buf[1024]; + va_list ap; + + va_start(ap, str); + vsnprintf(buf, sizeof(buf), str, ap); + va_end(ap); + buf[NELEMENTS(buf) - 2] = '\0'; + strcat(buf, "\n"); + + printf("%s", buf); +} + +void +memory_dump(int idx, UINT32 madr) +{ + UINT32 addr; + UINT32 size; + UINT32 s, i; + UINT8 buf[16]; + UINT8 c; + + if (madr < 0x80) { + size = madr + 0x80; + addr = 0; + } else { + size = 0x100; + addr = madr - 0x80; + } + VERBOSE(("memory dump\n--")); + for (s = 0; s < size; s++) { + if ((s % 16) == 0) { + VERBOSE(("%08x: ", addr + s)); + memset(buf, '.', sizeof(buf)); + } + + c = cpu_vmemoryread(idx, addr + s); + VERBOSE(("%02x ", c)); + if (c >= 0x20 && c <= 0x7e) + buf[s % 16] = c; + + if ((s % 16) == 15) { + VERBOSE(("| ")); + for (i = 0; i < sizeof(buf); i++) + VERBOSE(("%c", buf[i])); + VERBOSE(("\n")); + } + } +} + +void +gdtr_dump(UINT32 base, UINT limit) +{ + UINT32 v[2]; + UINT i; + + VERBOSE(("GDTR_DUMP: GDTR_BASE = 0x%08x, GDTR_LIMIT = 0x%04x", base, limit)); + + for (i = 0; i < limit; i += 8) { + v[0] = cpu_kmemoryread_d(base + i); + v[1] = cpu_kmemoryread_d(base + i + 4); + VERBOSE(("GDTR_DUMP: %08x: %08x%08x", base + i, v[0], v[1])); + } +} + +void +ldtr_dump(UINT32 base, UINT limit) +{ + UINT32 v[2]; + UINT i; + + VERBOSE(("LDTR_DUMP: LDTR_BASE = 0x%08x, LDTR_LIMIT = 0x%04x", base, limit)); + + for (i = 0; i < limit; i += 8) { + v[0] = cpu_kmemoryread_d(base + i); + v[1] = cpu_kmemoryread_d(base + i + 4); + VERBOSE(("LDTR_DUMP: %08x: %08x%08x", base + i, v[0], v[1])); + } +} + +void +idtr_dump(UINT32 base, UINT limit) +{ + UINT32 v[2]; + UINT i; + + VERBOSE(("IDTR_DUMP: IDTR_BASE = 0x%08x, IDTR_LIMIT = 0x%04x", base, limit)); + + for (i = 0; i < limit; i += 8) { + v[0] = cpu_kmemoryread_d(base + i); + v[1] = cpu_kmemoryread_d(base + i + 4); + VERBOSE(("IDTR_DUMP: %08x: %08x%08x", base + i, v[0], v[1])); + } +} + +void +tr_dump(UINT16 selector, UINT32 base, UINT limit) +{ + UINT32 v; + UINT i; + + VERBOSE(("TR_DUMP: selector = %04x", selector)); + + for (i = 0; i < limit; i += 4) { + v = cpu_kmemoryread_d(base + i); + VERBOSE(("TR_DUMP: %08x: %08x", base + i, v)); + } +} + +UINT32 +pde_dump(UINT32 base, int idx) +{ + UINT32 paddr; + UINT32 v; + int i; + + if (idx < 0 && idx > -8192) { + idx = -idx; + VERBOSE(("PDE_DUMP: address = 0x%08x, num = %d", base, idx)); + for (i = 0; i < idx; i++) { + paddr = (base & CPU_CR3_PD_MASK) | (idx << 2); + v = cpu_memoryread_d(paddr); + VERBOSE(("PDE_DUMP: 0x%08x: %08x", paddr, v)); + } + paddr = 0; + } else if (idx < 8192) { + VERBOSE(("PDE_DUMP: address = 0x%08x", base)); + paddr = (base & CPU_CR3_PD_MASK) | (idx << 2); + v = cpu_memoryread_d(paddr); + VERBOSE(("PDE_DUMP: 0x%08x: %08x", paddr, v)); + } else { + VERBOSE(("PDE_DUMP: invalid idx (%d)", idx)); + paddr = 0; + } + + return paddr; +} + +void +segdesc_dump(descriptor_t *sdp) +{ +#if defined(DEBUG) + const char *s; + + __ASSERT(sdp != NULL); + + VERBOSE(("dump descriptor: %p", sdp)); + + VERBOSE(("valid : %s", SEG_IS_VALID(sdp) ? "true" : "false")); + VERBOSE(("present : %s", SEG_IS_PRESENT(sdp) ? "true" : "false")); + VERBOSE(("DPL : %d", sdp->dpl)); + VERBOSE(("type : %d", sdp->type)); + VERBOSE(("kind : %s", SEG_IS_SYSTEM(sdp) ? "system" : "code/data")); + if (!SEG_IS_SYSTEM(sdp)) { + if (SEG_IS_CODE(sdp)) { + VERBOSE(("type : %dbit %sconforming code", + SEG_IS_32BIT(sdp) ? 32 : 16, + SEG_IS_CONFORMING_CODE(sdp) ? "" : "non-")); + VERBOSE(("access : execute%s", + SEG_IS_READABLE_CODE(sdp) ? "/read" : "")); + } else { + VERBOSE(("type : %dbit expand-%s data", + SEG_IS_32BIT(sdp) ? 32 : 16, + SEG_IS_EXPANDDOWN_DATA(sdp) ? "down" : "up")); + VERBOSE(("access : read%s", + SEG_IS_WRITABLE_DATA(sdp) ? "/write" : "")); + } + VERBOSE(("4k scale : %s", sdp->u.seg.g ? "true" : "false")); + VERBOSE(("baseadr : 0x%08x", sdp->u.seg.segbase)); + VERBOSE(("limit : 0x%08x", sdp->u.seg.limit)); + } else { + switch (sdp->type) { + case CPU_SYSDESC_TYPE_LDT: /* LDT */ + VERBOSE(("type : LDT")); + VERBOSE(("4k scale : %s", sdp->u.seg.g ? "true" : "false")); + VERBOSE(("baseadr : 0x%08x", sdp->u.seg.segbase)); + VERBOSE(("limit : 0x%08x", sdp->u.seg.limit)); + break; + + case CPU_SYSDESC_TYPE_TASK: /* task gate */ + VERBOSE(("type : task gate")); + VERBOSE(("selector : 0x%04x", sdp->u.gate.selector)); + break; + + case CPU_SYSDESC_TYPE_TSS_16: /* 286 TSS */ + case CPU_SYSDESC_TYPE_TSS_BUSY_16: /* 286 Busy TSS */ + case CPU_SYSDESC_TYPE_TSS_32: /* 386 TSS */ + case CPU_SYSDESC_TYPE_TSS_BUSY_32: /* 386 Busy TSS */ + VERBOSE(("type : %dbit %sTSS", + (sdp->type & CPU_SYSDESC_TYPE_32BIT) ? 32 : 16, + (sdp->type & CPU_SYSDESC_TYPE_TSS_BUSY_IND) ? + "Busy " : "")); + VERBOSE(("4k scale : %s", sdp->u.seg.g ? "true" : "false")); + VERBOSE(("baseadr : 0x%08x", sdp->u.seg.segbase)); + VERBOSE(("limit : 0x%08x", sdp->u.seg.limit)); + break; + + case CPU_SYSDESC_TYPE_CALL_16: /* 286 call gate */ + case CPU_SYSDESC_TYPE_INTR_16: /* 286 interrupt gate */ + case CPU_SYSDESC_TYPE_TRAP_16: /* 286 trap gate */ + case CPU_SYSDESC_TYPE_CALL_32: /* 386 call gate */ + case CPU_SYSDESC_TYPE_INTR_32: /* 386 interrupt gate */ + case CPU_SYSDESC_TYPE_TRAP_32: /* 386 trap gate */ + switch (sdp->type & CPU_SYSDESC_TYPE_MASKBIT) { + case CPU_SYSDESC_TYPE_CALL: + s = "call"; + break; + + case CPU_SYSDESC_TYPE_INTR: + s = "interrupt"; + break; + + case CPU_SYSDESC_TYPE_TRAP: + s = "trap"; + break; + + default: + s = "unknown"; + break; + } + VERBOSE(("type : %c86 %s gate", + (sdp->type & CPU_SYSDESC_TYPE_32BIT) ? '3':'2', s)); + VERBOSE(("selector : 0x%04x", sdp->u.gate.selector)); + VERBOSE(("offset : 0x%08x", sdp->u.gate.offset)); + VERBOSE(("count : %d", sdp->u.gate.count)); + break; + + case 0: case 8: case 10: case 13: /* reserved */ + default: + VERBOSE(("type : unknown descriptor")); + break; + } + } +#endif +} + +UINT32 +convert_laddr_to_paddr(UINT32 laddr) +{ + UINT32 paddr; /* physical address */ + UINT32 pde_addr; /* page directory entry address */ + UINT32 pde; /* page directory entry */ + UINT32 pte_addr; /* page table entry address */ + UINT32 pte; /* page table entry */ + + pde_addr = (CPU_CR3 & CPU_CR3_PD_MASK) | ((laddr >> 20) & 0xffc); + pde = cpu_memoryread_d(pde_addr); + + if ((CPU_CR4 & CPU_CR4_PSE) && (pde & CPU_PDE_PAGE_SIZE)) { + /* 4MB page size */ + paddr = (pde & CPU_PDE_4M_BASEADDR_MASK) | (laddr & 0x003fffff); + } else { + /* 4KB page size */ + pte_addr = (pde & CPU_PDE_BASEADDR_MASK) | ((laddr >> 10) & 0xffc); + pte = cpu_memoryread_d(pte_addr); + paddr = (pte & CPU_PTE_BASEADDR_MASK) | (laddr & 0x00000fff); + } + return paddr; +} + +UINT32 +convert_vaddr_to_paddr(unsigned int idx, UINT32 offset) +{ + descriptor_t *sdp; + UINT32 laddr; + + if (idx < CPU_SEGREG_NUM) { + sdp = &CPU_STAT_SREG(idx); + if (SEG_IS_VALID(sdp)) { + laddr = CPU_STAT_SREGBASE(idx) + offset; + return convert_laddr_to_paddr(laddr); + } + } + return 0; +} diff --git a/i386c/ia32/disasm.c b/i386c/ia32/disasm.c old mode 100755 new mode 100644 index 571832be..06b9b880 --- a/i386c/ia32/disasm.c +++ b/i386c/ia32/disasm.c @@ -1,863 +1,863 @@ -/* - * Copyright (c) 2004 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" -#include "inst_table.h" - - -/* - * opcode strings - */ -static const char *opcode_1byte[2][256] = { -/* 16bit */ -{ -/*00*/ "addb", "addw", "addb", "addw", "addb", "addw", "push", "pop", - "orb", "orw", "orb", "orw", "orb", "orw", "push", NULL, -/*10*/ "adcb", "adcw", "adcb", "adcw", "adcb", "adcw", "push", "pop", - "sbbb", "sbbw", "sbbb", "sbbw", "sbbb", "sbbw", "push", "pop", -/*20*/ "andb", "andw", "andb", "andw", "andb", "andw", NULL, "daa", - "subb", "subw", "subb", "subw", "subb", "subw", NULL, "das", -/*30*/ "xorb", "xorw", "xorb", "xorw", "xorb", "xorw", NULL, "aaa", - "cmpb", "cmpw", "cmpb", "cmpw", "cmpb", "cmpw", NULL, "aas", -/*40*/ "incw", "incw", "incw", "incw", "incw", "incw", "incw", "incw", - "decw", "decw", "decw", "decw", "decw", "decw", "decw", "decw", -/*50*/ "push", "push", "push", "push", "push", "push", "push", "push", - "pop", "pop", "pop", "pop", "pop", "pop", "pop", "pop", -/*60*/ "pusha", "popa", "bound", "arpl", NULL, NULL, NULL, NULL, - "push", "imul", "push", "imul", "insb", "insw", "outsb", "outsw", -/*70*/ "jo", "jno", "jc", "jnc", "jz", "jnz", "jna", "ja", - "js", "jns", "jp", "jnp", "jl", "jnl", "jle", "jnle", -/*80*/ NULL, NULL, NULL, NULL, "testb", "testw", "xchgb", "xchgw", - "movb", "movw", "movb", "movw", "movw", "lea", "movw", "pop", -/*90*/ "nop", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", - "cbw", "cwd", "callf", "fwait", "pushf", "popf", "sahf", "lahf", -/*a0*/ "movb", "movw", "movb", "movw", "movsb", "movsw", "cmpsb", "cmpsw", - "testb", "testw", "stosb", "stosw", "lodsb", "lodsw", "scasb", "scasw", -/*b0*/ "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", - "movw", "movw", "movw", "movw", "movw", "movw", "movw", "movw", -/*c0*/ NULL, NULL, "ret", "ret", "les", "lds", "movb", "movw", - "enter", "leave", "retf", "retf", "int3", "int", "into", "iret", -/*d0*/ NULL, NULL, NULL, NULL, "aam", "aad", "salc", "xlat", - "esc0", "esc1", "esc2", "esc3", "esc4", "esc5", "esc6", "esc7", -/*e0*/ "loopne","loope", "loop", "jcxz", "inb", "inw", "outb", "outw", - "call", "jmp", "jmpf", "jmp", "inb", "inw", "outb", "outw", -/*f0*/ "lock:", "int1", "repne", "repe", "hlt", "cmc", NULL, NULL, - "clc", "stc", "cli", "sti", "cld", "std", NULL, NULL, -}, -/* 32bit */ -{ -/*00*/ "addb", "addl", "addb", "addl", "addb", "addl", "pushl", "popl", - "orb", "orl", "orb", "orl", "orb", "orl", "pushl", NULL, -/*10*/ "adcb", "adcl", "adcb", "adcl", "adcb", "adcl", "pushl", "popl", - "sbbb", "sbbl", "sbbb", "sbbl", "sbbb", "sbbl", "pushl", "popl", -/*20*/ "andb", "andl", "andb", "andl", "andb", "andl", NULL, "daa", - "subb", "subl", "subb", "subl", "subb", "subl", NULL, "das", -/*30*/ "xorb", "xorl", "xorb", "xorl", "xorb", "xorl", NULL, "aaa", - "cmpb", "cmpl", "cmpb", "cmpl", "cmpb", "cmpl", NULL, "aas", -/*40*/ "incl", "incl", "incl", "incl", "incl", "incl", "incl", "incl", - "decl", "decl", "decl", "decl", "decl", "decl", "decl", "decl", -/*50*/ "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", - "popl", "popl", "popl", "popl", "popl", "popl", "popl", "pop", -/*60*/ "pushad","popad", "bound", "arpl", NULL, NULL, NULL, NULL, - "pushl", "imul", "pushl", "imul", "insb", "insl", "outsb", "outsl", -/*70*/ "jo", "jno", "jc", "jnc", "jz", "jnz", "jna", "ja", - "js", "jns", "jp", "jnp", "jl", "jnl", "jle", "jnle", -/*80*/ NULL, NULL, NULL, NULL, "testb", "testl", "xchgb", "xchgl", - "movb", "movl", "movb", "movl", "movl", "lea", "movl", "popl", -/*90*/ "nop", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", - "cwde", "cdq", "callfl","fwait", "pushfd","popfd", "sahf", "lahf", -/*a0*/ "movb", "movl", "movb", "movl", "movsb", "movsd", "cmpsb", "cmpsd", - "testb", "testl", "stosb", "stosd", "lodsb", "lodsd", "scasb", "scasd", -/*b0*/ "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", - "movl", "movl", "movl", "movl", "movl", "movl", "movl", "movl", -/*c0*/ NULL, NULL, "ret", "ret", "les", "lds", "movb", "movl", - "enter", "leave", "retf", "retf", "int3", "int", "into", "iretd", -/*d0*/ NULL, NULL, NULL, NULL, "aam", "aad", "salc", "xlat", - "esc0", "esc1", "esc2", "esc3", "esc4", "esc5", "esc6", "esc7", -/*e0*/ "loopne","loope", "loop", "jecxz", "inb", "inl", "outb", "outl", - "call", "jmp", "jmpf", "jmp", "inb", "inl", "outb", "outl", -/*f0*/ "lock:", "int1", "repne", "repe", "hlt", "cmc", NULL, NULL, - "clc", "stc", "cli", "sti", "cld", "std", NULL, NULL, -} -}; - -static const char *opcode_2byte[2][256] = { -/* 16bit */ -{ -/*00*/ NULL, NULL, "lar", "lsl", - NULL, "loadall", "clts", NULL, - "invd", "wbinvd", NULL, "UD2", - NULL, "prefetch", "femms", NULL, -/*10*/ NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, -/*20*/ "movl", "movl", "movl", "movl", - "movl", NULL, "movl", NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, -/*30*/ "wrmsr", "rdtsc", "rdmsr", "rdpmc", - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, -/*40*/ "cmovo", "cmovno", "cmovc", "cmovnc", - "cmovz", "cmovnz", "cmovna", "cmova", - "cmovs", "cmovns", "cmovp", "cmovnp", - "cmovl", "cmovnl", "cmovle", "cmovnle", -/*50*/ NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, -/*60*/ "PUNPCKLBW", "PUNPCKLWD", "PUNPCKLDQ", "PACKSSWB", - "PCMPGTB", "PCMPGTW", "PCMPGTD", "PACKUSWB", - "PUNPCKHBW", "PUNPCKHWD", "PUNPCKHDQ", "PACKSSDW", - NULL, NULL, "MOVD", "MOVQ", -/*70*/ NULL, "PSxxW", "PSxxD", "PSxxQ", - "PCMPEQB", "PCMPEQW", "PCMPEQD", "EMMS", - NULL, NULL, NULL, NULL, - NULL, NULL, "MOVD", "MOVQ", -/*80*/ "jo", "jno", "jc", "jnc", - "jz", "jnz", "jna", "ja", - "js", "jns", "jp", "jnp", - "jl", "jnl", "jle", "jnle", -/*90*/ "seto", "setno", "setc", "setnc", - "setz", "setnz", "setna", "seta", - "sets", "setns", "setp", "setnp", - "setl", "setnl", "setle", "setnle", -/*a0*/ "push", "pop", "cpuid", "bt", - "shldb", "shldw", "cmpxchgb","cmpxchgw", - "push", "pop", "rsm", "bts", - "shrdb", "shrdw", NULL, "imul", -/*b0*/ "cmpxchgb","cmpxchgw","lss", "btr", - "lfs", "lgs", "movzb", "movzw", - NULL, "UD2", NULL, "btc", - "bsf", "bsr", "movsb", "movsw", -/*c0*/ "xaddb", "xaddw", NULL, NULL, - NULL, NULL, NULL, NULL, - "bswap", "bswap", "bswap", "bswap", - "bswap", "bswap", "bswap", "bswap", -/*d0*/ NULL, "PSRLW", "PSRLD", "PSRLQ", - NULL, "PMULLW", NULL, NULL, - "PSUBUSB", "PSUBUSW", NULL, "PAND", - "PADDUSB", "PADDUSW", NULL, "PANDN", -/*e0*/ NULL, "PSRAW", "PSRAD", NULL, - "PMULHUW", "PMULHW", NULL, NULL, - "PSUBSB", "PSUBSW", NULL, "POR", - "PADDSB", "PADDSW", NULL, "PXOR", -/*f0*/ NULL, "PSLLW", "PSLLD", "PSLLQ", - NULL, "PMADDWD", NULL, NULL, - "PSUBB", "PSUBW", "PSUBD", NULL, - "PADDB", "PADDW", "PADDD", NULL, -}, -/* 32bit */ -{ -/*00*/ NULL, NULL, "lar", "lsl", - NULL, "loadall", "clts", NULL, - "invd", "wbinvd", NULL, "UD2", - NULL, "prefetch", "femms", NULL, -/*10*/ NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, -/*20*/ "movl", "movl", "movl", "movl", - "movl", NULL, "movl", NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, -/*30*/ "wrmsr", "rdtsc", "rdmsr", NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, -/*40*/ "cmovo", "cmovno", "cmovc", "cmovnc", - "cmovz", "cmovnz", "cmovna", "cmova", - "cmovs", "cmovns", "cmovp", "cmovnp", - "cmovl", "cmovnl", "cmovle", "cmovnle", -/*50*/ NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, -/*60*/ "PUNPCKLBW", "PUNPCKLWD", "PUNPCKLDQ", "PACKSSWB", - "PCMPGTB", "PCMPGTW", "PCMPGTD", "PACKUSWB", - "PUNPCKHBW", "PUNPCKHWD", "PUNPCKHDQ", "PACKSSDW", - NULL, NULL, "MOVD", "MOVQ", -/*70*/ NULL, "PSxxW", "PSxxD", "PSxxQ", - "PCMPEQB", "PCMPEQW", "PCMPEQD", "EMMS", - NULL, NULL, NULL, NULL, - NULL, NULL, "MOVD", "MOVQ", -/*80*/ "jo", "jno", "jc", "jnc", - "jz", "jnz", "jna", "ja", - "js", "jns", "jp", "jnp", - "jl", "jnl", "jle", "jnle", -/*90*/ "seto", "setno", "setc", "setnc", - "setz", "setnz", "setna", "seta", - "sets", "setns", "setp", "setnp", - "setl", "setnl", "setle", "setnle", -/*a0*/ "push", "pop", "cpuid", "bt", - "shldb", "shldl", "cmpxchgb","cmpxchgl", - "push", "pop", "rsm", "bts", - "shrdb", "shrdl", NULL, "imul", -/*b0*/ "cmpxchgb","cmpxchgd","lss", "btr", - "lfs", "lgs", "movzbl", "movzwl", - NULL, "UD2", NULL, "btc", - "bsf", "bsr", "movsbl", "movswl", -/*c0*/ "xaddb", "xaddl", NULL, NULL, - NULL, NULL, NULL, NULL, - "bswapl", "bswapl", "bswapl", "bswapl", - "bswapl", "bswapl", "bswapl", "bswapl", -/*d0*/ NULL, "PSRLW", "PSRLD", "PSRLQ", - NULL, "PMULLW", NULL, NULL, - "PSUBUSB", "PSUBUSW", NULL, "PAND", - "PADDUSB", "PADDUSW", NULL, "PANDN", -/*e0*/ NULL, "PSRAW", "PSRAD", NULL, - "PMULHUW", "PMULHW", NULL, NULL, - "PSUBSB", "PSUBSW", NULL, "POR", - "PADDSB", "PADDSW", NULL, "PXOR", -/*f0*/ NULL, "PSLLW", "PSLLD", "PSLLQ", - NULL, "PMADDWD", NULL, NULL, - "PSUBB", "PSUBW", "PSUBD", NULL, - "PADDB", "PADDW", "PADDD", NULL, -} -}; - -static const char *opcode_0x8x[2][2][8] = { -/* 16bit */ -{ - { "addb", "orb", "adcb", "sbbb", "andb", "subb", "xorb", "cmpb" }, - { "addw", "orw", "adcw", "sbbw", "andw", "subw", "xorw", "cmpw" } -}, -/* 32bit */ -{ - { "addb", "orb", "adcb", "sbbb", "andb", "subb", "xorb", "cmpb" }, - { "addl", "orl", "adcl", "sbbl", "andl", "subl", "xorl", "cmpl" } -} -}; - -static const char *opcode_shift[2][2][8] = { -/* 16bit */ -{ - { "rolb", "rorb", "rclb", "rcrb", "shlb", "shrb", "shlb", "sarb" }, - { "rolw", "rorw", "rclw", "rcrw", "shlw", "shrw", "shlw", "sarw" } -}, -/* 32bit */ -{ - { "rolb", "rorb", "rclb", "rcrb", "shlb", "shrb", "shlb", "sarb" }, - { "roll", "rorl", "rcll", "rcrl", "shll", "shrl", "shll", "sarl" } -}, -}; - -static const char *opcode_0xf6[2][2][8] = { -/* 16bit */ -{ - { "testb", "testb", "notb", "negb", "mul", "imul", "div", "idiv" }, - { "testw", "testw", "notw", "negw", "mulw", "imulw", "divw", "idivw" } -}, -/* 32bit */ -{ - { "testb", "testb", "notb", "negb", "mul", "imul", "div", "idiv" }, - { "testl", "testl", "notl", "negl", "mull", "imull", "divl", "idivl" } -}, -}; - -static const char *opcode_0xfe[2][2][8] = { -/* 16bit */ -{ - { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL }, - { "incw", "decw", "call", "callf", "jmp", "jmpf", "push", NULL } -}, -/* 32bit */ -{ - { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL }, - { "incl", "decl", "call", "callf", "jmp", "jmpf", "pushl", NULL } -} -}; - -static const char *opcode2_g6[8] = { - "sldt", "str", "lldt", "ltr", "verr", "verw", NULL, NULL -}; - -static const char *opcode2_g7[8] = { - "sgdt", "sidt", "lgdt", "lidt", "smsw", NULL, "lmsw", "invlpg" -}; - -static const char *opcode2_g8[8] = { - NULL, NULL, NULL, NULL, "bt", "bts", "btr", "btc" -}; - -static const char *opcode2_g9[8] = { - NULL, "cmpxchg8b", NULL, NULL, NULL, NULL, NULL, NULL -}; - -#if 0 -static const char *sep[2] = { " ", ", " }; -#endif - -/** - * string copy - */ -static char * -ncpy(char *dest, const char *src, size_t n) -{ - strncpy(dest, src, n); - dest[n - 1] = '\0'; - return dest; -} - -/** - * string copy at - */ -static char * -ncat(char *dest, const char *src, size_t n) -{ - const size_t offset = strlen(dest); - ncpy(dest + offset, src, n - offset); - return dest; -} - -/* - * fetch memory - */ -static int -convert_address(disasm_context_t *ctx) -{ - UINT32 pde_addr; /* page directory entry address */ - UINT32 pde; /* page directory entry */ - UINT32 pte_addr; /* page table entry address */ - UINT32 pte; /* page table entry */ - UINT32 addr; - - if (CPU_STAT_SREG(CPU_CS_INDEX).valid) { - addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + ctx->eip; - if (CPU_STAT_PAGING) { - pde_addr = CPU_STAT_PDE_BASE + ((addr >> 20) & 0xffc); - pde = cpu_memoryread_d(pde_addr); - /* XXX: check */ - pte_addr = (pde & CPU_PDE_BASEADDR_MASK) + ((addr >> 10) & 0xffc); - pte = cpu_memoryread_d(pte_addr); - /* XXX: check */ - addr = (pte & CPU_PTE_BASEADDR_MASK) + (addr & 0x00000fff); - } - ctx->val = addr; - return 0; - } - return 1; -} - -static int -disasm_codefetch_1(disasm_context_t *ctx) -{ - UINT8 val; - int rv; - - rv = convert_address(ctx); - if (rv) - return rv; - - val = cpu_memoryread(ctx->val); - ctx->val = val; - - ctx->opbyte[ctx->nopbytes++] = (UINT8)ctx->val; - ctx->eip++; - - return 0; -} - -#if 0 -static int -disasm_codefetch_2(disasm_context_t *ctx) -{ - UINT16 val; - int rv; - - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - val = (UINT16)(ctx->val & 0xff); - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - val |= (UINT16)(ctx->val & 0xff) << 8; - - ctx->val = val; - return 0; -} - -static int -disasm_codefetch_4(disasm_context_t *ctx) -{ - UINT32 val; - int rv; - - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - val = ctx->val & 0xff; - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - val |= (UINT32)(ctx->val & 0xff) << 8; - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - val |= (UINT32)(ctx->val & 0xff) << 16; - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - val |= (UINT32)(ctx->val & 0xff) << 24; - - ctx->val = val; - return 0; -} - -/* - * get effective address. - */ - -static int -ea16(disasm_context_t *ctx, char *buf, size_t size) -{ - static const char *ea16_str[8] = { - "bx + si", "bx + di", "bp + si", "bp + di", - "si", "di", "bp", "bx" - }; - UINT32 val; - UINT mod, rm; - int rv; - - mod = (ctx->modrm >> 6) & 3; - rm = ctx->modrm & 7; - - if (mod == 0) { - if (rm == 6) { - /* disp16 */ - rv = disasm_codefetch_2(ctx); - if (rv) - return rv; - - snprintf(buf, size, "[0x%04x]", ctx->val); - } else { - snprintf(buf, size, "[%s]", ea16_str[rm]); - } - } else { - if (mod == 1) { - /* disp8 */ - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - - val = ctx->val; - if (val & 0x80) { - val |= 0xff00; - } - } else { - /* disp16 */ - rv = disasm_codefetch_2(ctx); - if (rv) - return rv; - - val = ctx->val; - } - snprintf(buf, size, "[%s + 0x%04x]", ea16_str[rm], val); - } - - return 0; -} - -static int -ea32(disasm_context_t *ctx, char *buf, size_t size) -{ - char tmp[32]; - UINT count[9]; - UINT32 val; - UINT mod, rm; - UINT sib; - UINT scale; - UINT idx; - UINT base; - int rv; - int i, n; - - memset(count, 0, sizeof(count)); - - mod = (ctx->modrm >> 6) & 3; - rm = ctx->modrm & 7; - - /* SIB */ - if (rm == 4) { - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - - sib = ctx->val; - scale = (sib >> 6) & 3; - idx = (sib >> 3) & 7; - base = sib & 7; - - /* base */ - if (mod == 0 && base == 5) { - /* disp32 */ - rv = disasm_codefetch_4(ctx); - if (rv) - return rv; - count[8] += ctx->val; - } else { - count[base]++; - } - - /* index & scale */ - if (idx != 4) { - count[idx] += 1 << scale; - } - } - - /* MOD/RM */ - if (mod == 0 && rm == 5) { - /* disp32 */ - rv = disasm_codefetch_4(ctx); - if (rv) - return rv; - count[8] += ctx->val; - } else { - /* mod */ - if (mod == 1) { - /* disp8 */ - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - - val = ctx->val; - if (val & 0x80) { - val |= 0xffffff00; - } - count[8] += val; - } else if (mod == 2) { - /* disp32 */ - rv = disasm_codefetch_4(ctx); - if (rv) - return rv; - count[8] += ctx->val; - } - - /* rm */ - if (rm != 4) { - count[rm]++; - } - } - - ncpy(buf, "[", size); - for (n = 0, i = 0; i < 8; i++) { - if (count[i] != 0) { - if (n > 0) { - ncat(buf, " + ", size); - } - if (count[i] > 1) { - snprintf(tmp, size, "%s * %d", - reg32_str[i], count[i]); - } else { - ncpy(tmp, reg32_str[i], sizeof(tmp)); - } - ncat(buf, tmp, size); - n++; - } - } - if (count[8] != 0) { - if (n > 0) { - ncat(buf, " + ", size); - } - snprintf(tmp, sizeof(tmp), "0x%08x", count[8]); - ncat(buf, tmp, size); - } - ncat(buf, "]", size); - - return 0; -} - -static int -ea(disasm_context_t *ctx) -{ - char buf[256]; - char tmp[8]; - size_t len; - int rv; - - memset(buf, 0, sizeof(buf)); - - if (!ctx->as32) - rv = ea16(ctx, buf, sizeof(buf)); - else - rv = ea32(ctx, buf, sizeof(buf)); - if (rv) - return rv; - - if (ctx->narg == 0) { - ncat(ctx->next, sep[0], ctx->remain); - } else { - ncat(ctx->next, sep[1], ctx->remain); - } - len = strlen(ctx->next); - len = (len < ctx->remain) ? len : ctx->remain; - ctx->next += len; - ctx->remain -= len; - - ctx->arg[ctx->narg++] = ctx->next; - if (ctx->useseg) { - snprintf(tmp, sizeof(tmp), "%s:", sreg_str[ctx->seg]); - ncat(ctx->next, tmp, ctx->remain); - } - ncat(ctx->next, buf, ctx->remain); - len = strlen(ctx->next); - len = (len < ctx->remain) ? len : ctx->remain; - ctx->next += len; - ctx->remain -= len; - - return 0; -} -#endif - -/* - * get opcode - */ -static int -get_opcode(disasm_context_t *ctx) -{ - const char *opcode; - UINT8 op[3]; - int prefix; - size_t len; - int rv; - int i; - - for (prefix = 0; prefix < MAX_PREFIX; prefix++) { - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - - op[0] = (UINT8)(ctx->val & 0xff); - if (!(insttable_info[op[0]] & INST_PREFIX)) - break; - - if (ctx->prefix == 0) - ctx->prefix = ctx->next; - - switch (op[0]) { - case 0x26: /* ES: */ - case 0x2e: /* CS: */ - case 0x36: /* SS: */ - case 0x3e: /* DS: */ - ctx->useseg = TRUE; - ctx->seg = (op[0] >> 3) & 3; - break; - - case 0x64: /* FS: */ - case 0x65: /* GS: */ - ctx->useseg = TRUE; - ctx->seg = (op[0] - 0x64) + 4; - break; - - case 0x66: /* OPSize: */ - ctx->op32 = !CPU_STATSAVE.cpu_inst_default.op_32; - break; - - case 0x67: /* AddrSize: */ - ctx->as32 = !CPU_STATSAVE.cpu_inst_default.as_32; - break; - } - } - if (prefix == MAX_PREFIX) - return 1; - - if (ctx->prefix) { - for (i = 0; i < prefix - 1; i++) { - opcode = opcode_1byte[ctx->op32][ctx->opbyte[i]]; - if (opcode) { - ncat(ctx->next, opcode, ctx->remain); - ncat(ctx->next, " ", ctx->remain); - } - } - len = strlen(ctx->next); - len = (len < ctx->remain) ? len : ctx->remain; - ctx->next += len; - ctx->remain -= len; - } - - ctx->opcode[0] = op[0]; - opcode = opcode_1byte[ctx->op32][op[0]]; - if (opcode == NULL) { - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - - op[1] = (UINT8)(ctx->val & 0xff); - ctx->opcode[1] = op[1]; - - switch (op[0]) { - case 0x0f: - opcode = opcode_2byte[ctx->op32][op[1]]; - if (opcode == NULL) { - rv = disasm_codefetch_1(ctx); - if (rv) - return rv; - - op[2] = (UINT8)(ctx->val & 0xff); - ctx->opcode[2] = op[2]; - - switch (op[1]) { - case 0x00: - opcode = opcode2_g6[(op[2]>>3)&7]; - ctx->modrm = op[2]; - break; - - case 0x01: - opcode = opcode2_g7[(op[2]>>3)&7]; - ctx->modrm = op[2]; - break; - - case 0xba: - opcode = opcode2_g8[(op[2]>>3)&7]; - ctx->modrm = op[2]; - break; - - case 0xc7: - opcode = opcode2_g9[(op[2]>>3)&7]; - ctx->modrm = op[2]; - break; - } - } - break; - - case 0x80: case 0x81: case 0x82: case 0x83: - opcode = opcode_0x8x[ctx->op32][op[0]&1][(op[1]>>3)&7]; - ctx->modrm = op[1]; - break; - - case 0xc0: case 0xc1: - case 0xd0: case 0xd1: case 0xd2: case 0xd3: - opcode = opcode_shift[ctx->op32][op[0]&1][(op[1]>>3)&7]; - ctx->modrm = op[1]; - break; - - case 0xf6: case 0xf7: - opcode = opcode_0xf6[ctx->op32][op[0]&1][(op[1]>>3)&7]; - ctx->modrm = op[1]; - break; - - case 0xfe: case 0xff: - opcode = opcode_0xfe[ctx->op32][op[0]&1][(op[1]>>3)&7]; - ctx->modrm = op[1]; - break; - } - } - if (opcode == NULL) - return 1; - - ncat(ctx->next, opcode, ctx->remain); - - return 0; -} - -/* - * interface - */ -int -disasm(UINT32 *eip, disasm_context_t *ctx) -{ - int rv; - - memset(ctx, 0, sizeof(disasm_context_t)); - ctx->remain = sizeof(ctx->str) - 1; - ctx->next = ctx->str; - ctx->prefix = 0; - ctx->op = 0; - ctx->arg[0] = 0; - ctx->arg[1] = 0; - ctx->arg[2] = 0; - - ctx->eip = *eip; - ctx->op32 = CPU_STATSAVE.cpu_inst_default.op_32; - ctx->as32 = CPU_STATSAVE.cpu_inst_default.as_32; - ctx->seg = -1; - - ctx->baseaddr = ctx->eip; - ctx->pad = ' '; - - rv = get_opcode(ctx); - if (rv) { - memset(ctx, 0, sizeof(disasm_context_t)); - return rv; - } - *eip = ctx->eip; - - return 0; -} - -char * -cpu_disasm2str(UINT32 eip) -{ - static char output[2048]; - disasm_context_t d; - UINT32 eip2 = eip; - int rv; - - output[0] = '\0'; - rv = disasm(&eip2, &d); - if (rv == 0) { - char buf[256]; - char tmp[32]; - int len = d.nopbytes > 8 ? 8 : d.nopbytes; - int i; - - buf[0] = '\0'; - for (i = 0; i < len; i++) { - snprintf(tmp, sizeof(tmp), "%02x ", d.opbyte[i]); - ncat(buf, tmp, sizeof(buf)); - } - for (; i < 8; i++) { - ncat(buf, " ", sizeof(buf)); - } - snprintf(output, sizeof(output), "%04x:%08x: %s%s", - CPU_CS, eip, buf, d.str); - - if (i < d.nopbytes) { - char t[256]; - buf[0] = '\0'; - for (; i < d.nopbytes; i++) { - snprintf(tmp, sizeof(tmp), "%02x ", - d.opbyte[i]); - ncat(buf, tmp, sizeof(buf)); - if ((i % 8) == 7) { - snprintf(t, sizeof(t), - "\n : %s", buf); - ncat(output, t, sizeof(output)); - buf[0] = '\0'; - } - } - if ((i % 8) != 0) { - snprintf(t, sizeof(t), - "\n : %s", buf); - ncat(output, t, sizeof(output)); - } - } - } - return output; -} +/* + * Copyright (c) 2004 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" +#include "inst_table.h" + + +/* + * opcode strings + */ +static const char *opcode_1byte[2][256] = { +/* 16bit */ +{ +/*00*/ "addb", "addw", "addb", "addw", "addb", "addw", "push", "pop", + "orb", "orw", "orb", "orw", "orb", "orw", "push", NULL, +/*10*/ "adcb", "adcw", "adcb", "adcw", "adcb", "adcw", "push", "pop", + "sbbb", "sbbw", "sbbb", "sbbw", "sbbb", "sbbw", "push", "pop", +/*20*/ "andb", "andw", "andb", "andw", "andb", "andw", NULL, "daa", + "subb", "subw", "subb", "subw", "subb", "subw", NULL, "das", +/*30*/ "xorb", "xorw", "xorb", "xorw", "xorb", "xorw", NULL, "aaa", + "cmpb", "cmpw", "cmpb", "cmpw", "cmpb", "cmpw", NULL, "aas", +/*40*/ "incw", "incw", "incw", "incw", "incw", "incw", "incw", "incw", + "decw", "decw", "decw", "decw", "decw", "decw", "decw", "decw", +/*50*/ "push", "push", "push", "push", "push", "push", "push", "push", + "pop", "pop", "pop", "pop", "pop", "pop", "pop", "pop", +/*60*/ "pusha", "popa", "bound", "arpl", NULL, NULL, NULL, NULL, + "push", "imul", "push", "imul", "insb", "insw", "outsb", "outsw", +/*70*/ "jo", "jno", "jc", "jnc", "jz", "jnz", "jna", "ja", + "js", "jns", "jp", "jnp", "jl", "jnl", "jle", "jnle", +/*80*/ NULL, NULL, NULL, NULL, "testb", "testw", "xchgb", "xchgw", + "movb", "movw", "movb", "movw", "movw", "lea", "movw", "pop", +/*90*/ "nop", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", "xchgw", + "cbw", "cwd", "callf", "fwait", "pushf", "popf", "sahf", "lahf", +/*a0*/ "movb", "movw", "movb", "movw", "movsb", "movsw", "cmpsb", "cmpsw", + "testb", "testw", "stosb", "stosw", "lodsb", "lodsw", "scasb", "scasw", +/*b0*/ "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", + "movw", "movw", "movw", "movw", "movw", "movw", "movw", "movw", +/*c0*/ NULL, NULL, "ret", "ret", "les", "lds", "movb", "movw", + "enter", "leave", "retf", "retf", "int3", "int", "into", "iret", +/*d0*/ NULL, NULL, NULL, NULL, "aam", "aad", "salc", "xlat", + "esc0", "esc1", "esc2", "esc3", "esc4", "esc5", "esc6", "esc7", +/*e0*/ "loopne","loope", "loop", "jcxz", "inb", "inw", "outb", "outw", + "call", "jmp", "jmpf", "jmp", "inb", "inw", "outb", "outw", +/*f0*/ "lock:", "int1", "repne", "repe", "hlt", "cmc", NULL, NULL, + "clc", "stc", "cli", "sti", "cld", "std", NULL, NULL, +}, +/* 32bit */ +{ +/*00*/ "addb", "addl", "addb", "addl", "addb", "addl", "pushl", "popl", + "orb", "orl", "orb", "orl", "orb", "orl", "pushl", NULL, +/*10*/ "adcb", "adcl", "adcb", "adcl", "adcb", "adcl", "pushl", "popl", + "sbbb", "sbbl", "sbbb", "sbbl", "sbbb", "sbbl", "pushl", "popl", +/*20*/ "andb", "andl", "andb", "andl", "andb", "andl", NULL, "daa", + "subb", "subl", "subb", "subl", "subb", "subl", NULL, "das", +/*30*/ "xorb", "xorl", "xorb", "xorl", "xorb", "xorl", NULL, "aaa", + "cmpb", "cmpl", "cmpb", "cmpl", "cmpb", "cmpl", NULL, "aas", +/*40*/ "incl", "incl", "incl", "incl", "incl", "incl", "incl", "incl", + "decl", "decl", "decl", "decl", "decl", "decl", "decl", "decl", +/*50*/ "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", "pushl", + "popl", "popl", "popl", "popl", "popl", "popl", "popl", "pop", +/*60*/ "pushad","popad", "bound", "arpl", NULL, NULL, NULL, NULL, + "pushl", "imul", "pushl", "imul", "insb", "insl", "outsb", "outsl", +/*70*/ "jo", "jno", "jc", "jnc", "jz", "jnz", "jna", "ja", + "js", "jns", "jp", "jnp", "jl", "jnl", "jle", "jnle", +/*80*/ NULL, NULL, NULL, NULL, "testb", "testl", "xchgb", "xchgl", + "movb", "movl", "movb", "movl", "movl", "lea", "movl", "popl", +/*90*/ "nop", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", "xchgl", + "cwde", "cdq", "callfl","fwait", "pushfd","popfd", "sahf", "lahf", +/*a0*/ "movb", "movl", "movb", "movl", "movsb", "movsd", "cmpsb", "cmpsd", + "testb", "testl", "stosb", "stosd", "lodsb", "lodsd", "scasb", "scasd", +/*b0*/ "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", + "movl", "movl", "movl", "movl", "movl", "movl", "movl", "movl", +/*c0*/ NULL, NULL, "ret", "ret", "les", "lds", "movb", "movl", + "enter", "leave", "retf", "retf", "int3", "int", "into", "iretd", +/*d0*/ NULL, NULL, NULL, NULL, "aam", "aad", "salc", "xlat", + "esc0", "esc1", "esc2", "esc3", "esc4", "esc5", "esc6", "esc7", +/*e0*/ "loopne","loope", "loop", "jecxz", "inb", "inl", "outb", "outl", + "call", "jmp", "jmpf", "jmp", "inb", "inl", "outb", "outl", +/*f0*/ "lock:", "int1", "repne", "repe", "hlt", "cmc", NULL, NULL, + "clc", "stc", "cli", "sti", "cld", "std", NULL, NULL, +} +}; + +static const char *opcode_2byte[2][256] = { +/* 16bit */ +{ +/*00*/ NULL, NULL, "lar", "lsl", + NULL, "loadall", "clts", NULL, + "invd", "wbinvd", NULL, "UD2", + NULL, "prefetch", "femms", NULL, +/*10*/ NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +/*20*/ "movl", "movl", "movl", "movl", + "movl", NULL, "movl", NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +/*30*/ "wrmsr", "rdtsc", "rdmsr", "rdpmc", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +/*40*/ "cmovo", "cmovno", "cmovc", "cmovnc", + "cmovz", "cmovnz", "cmovna", "cmova", + "cmovs", "cmovns", "cmovp", "cmovnp", + "cmovl", "cmovnl", "cmovle", "cmovnle", +/*50*/ NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +/*60*/ "PUNPCKLBW", "PUNPCKLWD", "PUNPCKLDQ", "PACKSSWB", + "PCMPGTB", "PCMPGTW", "PCMPGTD", "PACKUSWB", + "PUNPCKHBW", "PUNPCKHWD", "PUNPCKHDQ", "PACKSSDW", + NULL, NULL, "MOVD", "MOVQ", +/*70*/ NULL, "PSxxW", "PSxxD", "PSxxQ", + "PCMPEQB", "PCMPEQW", "PCMPEQD", "EMMS", + NULL, NULL, NULL, NULL, + NULL, NULL, "MOVD", "MOVQ", +/*80*/ "jo", "jno", "jc", "jnc", + "jz", "jnz", "jna", "ja", + "js", "jns", "jp", "jnp", + "jl", "jnl", "jle", "jnle", +/*90*/ "seto", "setno", "setc", "setnc", + "setz", "setnz", "setna", "seta", + "sets", "setns", "setp", "setnp", + "setl", "setnl", "setle", "setnle", +/*a0*/ "push", "pop", "cpuid", "bt", + "shldb", "shldw", "cmpxchgb","cmpxchgw", + "push", "pop", "rsm", "bts", + "shrdb", "shrdw", NULL, "imul", +/*b0*/ "cmpxchgb","cmpxchgw","lss", "btr", + "lfs", "lgs", "movzb", "movzw", + NULL, "UD2", NULL, "btc", + "bsf", "bsr", "movsb", "movsw", +/*c0*/ "xaddb", "xaddw", NULL, NULL, + NULL, NULL, NULL, NULL, + "bswap", "bswap", "bswap", "bswap", + "bswap", "bswap", "bswap", "bswap", +/*d0*/ NULL, "PSRLW", "PSRLD", "PSRLQ", + NULL, "PMULLW", NULL, NULL, + "PSUBUSB", "PSUBUSW", NULL, "PAND", + "PADDUSB", "PADDUSW", NULL, "PANDN", +/*e0*/ NULL, "PSRAW", "PSRAD", NULL, + "PMULHUW", "PMULHW", NULL, NULL, + "PSUBSB", "PSUBSW", NULL, "POR", + "PADDSB", "PADDSW", NULL, "PXOR", +/*f0*/ NULL, "PSLLW", "PSLLD", "PSLLQ", + NULL, "PMADDWD", NULL, NULL, + "PSUBB", "PSUBW", "PSUBD", NULL, + "PADDB", "PADDW", "PADDD", NULL, +}, +/* 32bit */ +{ +/*00*/ NULL, NULL, "lar", "lsl", + NULL, "loadall", "clts", NULL, + "invd", "wbinvd", NULL, "UD2", + NULL, "prefetch", "femms", NULL, +/*10*/ NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +/*20*/ "movl", "movl", "movl", "movl", + "movl", NULL, "movl", NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +/*30*/ "wrmsr", "rdtsc", "rdmsr", NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +/*40*/ "cmovo", "cmovno", "cmovc", "cmovnc", + "cmovz", "cmovnz", "cmovna", "cmova", + "cmovs", "cmovns", "cmovp", "cmovnp", + "cmovl", "cmovnl", "cmovle", "cmovnle", +/*50*/ NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +/*60*/ "PUNPCKLBW", "PUNPCKLWD", "PUNPCKLDQ", "PACKSSWB", + "PCMPGTB", "PCMPGTW", "PCMPGTD", "PACKUSWB", + "PUNPCKHBW", "PUNPCKHWD", "PUNPCKHDQ", "PACKSSDW", + NULL, NULL, "MOVD", "MOVQ", +/*70*/ NULL, "PSxxW", "PSxxD", "PSxxQ", + "PCMPEQB", "PCMPEQW", "PCMPEQD", "EMMS", + NULL, NULL, NULL, NULL, + NULL, NULL, "MOVD", "MOVQ", +/*80*/ "jo", "jno", "jc", "jnc", + "jz", "jnz", "jna", "ja", + "js", "jns", "jp", "jnp", + "jl", "jnl", "jle", "jnle", +/*90*/ "seto", "setno", "setc", "setnc", + "setz", "setnz", "setna", "seta", + "sets", "setns", "setp", "setnp", + "setl", "setnl", "setle", "setnle", +/*a0*/ "push", "pop", "cpuid", "bt", + "shldb", "shldl", "cmpxchgb","cmpxchgl", + "push", "pop", "rsm", "bts", + "shrdb", "shrdl", NULL, "imul", +/*b0*/ "cmpxchgb","cmpxchgd","lss", "btr", + "lfs", "lgs", "movzbl", "movzwl", + NULL, "UD2", NULL, "btc", + "bsf", "bsr", "movsbl", "movswl", +/*c0*/ "xaddb", "xaddl", NULL, NULL, + NULL, NULL, NULL, NULL, + "bswapl", "bswapl", "bswapl", "bswapl", + "bswapl", "bswapl", "bswapl", "bswapl", +/*d0*/ NULL, "PSRLW", "PSRLD", "PSRLQ", + NULL, "PMULLW", NULL, NULL, + "PSUBUSB", "PSUBUSW", NULL, "PAND", + "PADDUSB", "PADDUSW", NULL, "PANDN", +/*e0*/ NULL, "PSRAW", "PSRAD", NULL, + "PMULHUW", "PMULHW", NULL, NULL, + "PSUBSB", "PSUBSW", NULL, "POR", + "PADDSB", "PADDSW", NULL, "PXOR", +/*f0*/ NULL, "PSLLW", "PSLLD", "PSLLQ", + NULL, "PMADDWD", NULL, NULL, + "PSUBB", "PSUBW", "PSUBD", NULL, + "PADDB", "PADDW", "PADDD", NULL, +} +}; + +static const char *opcode_0x8x[2][2][8] = { +/* 16bit */ +{ + { "addb", "orb", "adcb", "sbbb", "andb", "subb", "xorb", "cmpb" }, + { "addw", "orw", "adcw", "sbbw", "andw", "subw", "xorw", "cmpw" } +}, +/* 32bit */ +{ + { "addb", "orb", "adcb", "sbbb", "andb", "subb", "xorb", "cmpb" }, + { "addl", "orl", "adcl", "sbbl", "andl", "subl", "xorl", "cmpl" } +} +}; + +static const char *opcode_shift[2][2][8] = { +/* 16bit */ +{ + { "rolb", "rorb", "rclb", "rcrb", "shlb", "shrb", "shlb", "sarb" }, + { "rolw", "rorw", "rclw", "rcrw", "shlw", "shrw", "shlw", "sarw" } +}, +/* 32bit */ +{ + { "rolb", "rorb", "rclb", "rcrb", "shlb", "shrb", "shlb", "sarb" }, + { "roll", "rorl", "rcll", "rcrl", "shll", "shrl", "shll", "sarl" } +}, +}; + +static const char *opcode_0xf6[2][2][8] = { +/* 16bit */ +{ + { "testb", "testb", "notb", "negb", "mul", "imul", "div", "idiv" }, + { "testw", "testw", "notw", "negw", "mulw", "imulw", "divw", "idivw" } +}, +/* 32bit */ +{ + { "testb", "testb", "notb", "negb", "mul", "imul", "div", "idiv" }, + { "testl", "testl", "notl", "negl", "mull", "imull", "divl", "idivl" } +}, +}; + +static const char *opcode_0xfe[2][2][8] = { +/* 16bit */ +{ + { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL }, + { "incw", "decw", "call", "callf", "jmp", "jmpf", "push", NULL } +}, +/* 32bit */ +{ + { "incb", "decb", NULL, NULL, NULL, NULL, NULL, NULL }, + { "incl", "decl", "call", "callf", "jmp", "jmpf", "pushl", NULL } +} +}; + +static const char *opcode2_g6[8] = { + "sldt", "str", "lldt", "ltr", "verr", "verw", NULL, NULL +}; + +static const char *opcode2_g7[8] = { + "sgdt", "sidt", "lgdt", "lidt", "smsw", NULL, "lmsw", "invlpg" +}; + +static const char *opcode2_g8[8] = { + NULL, NULL, NULL, NULL, "bt", "bts", "btr", "btc" +}; + +static const char *opcode2_g9[8] = { + NULL, "cmpxchg8b", NULL, NULL, NULL, NULL, NULL, NULL +}; + +#if 0 +static const char *sep[2] = { " ", ", " }; +#endif + +/** + * string copy + */ +static char * +ncpy(char *dest, const char *src, size_t n) +{ + strncpy(dest, src, n); + dest[n - 1] = '\0'; + return dest; +} + +/** + * string copy at + */ +static char * +ncat(char *dest, const char *src, size_t n) +{ + const size_t offset = strlen(dest); + ncpy(dest + offset, src, n - offset); + return dest; +} + +/* + * fetch memory + */ +static int +convert_address(disasm_context_t *ctx) +{ + UINT32 pde_addr; /* page directory entry address */ + UINT32 pde; /* page directory entry */ + UINT32 pte_addr; /* page table entry address */ + UINT32 pte; /* page table entry */ + UINT32 addr; + + if (CPU_STAT_SREG(CPU_CS_INDEX).valid) { + addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + ctx->eip; + if (CPU_STAT_PAGING) { + pde_addr = CPU_STAT_PDE_BASE + ((addr >> 20) & 0xffc); + pde = cpu_memoryread_d(pde_addr); + /* XXX: check */ + pte_addr = (pde & CPU_PDE_BASEADDR_MASK) + ((addr >> 10) & 0xffc); + pte = cpu_memoryread_d(pte_addr); + /* XXX: check */ + addr = (pte & CPU_PTE_BASEADDR_MASK) + (addr & 0x00000fff); + } + ctx->val = addr; + return 0; + } + return 1; +} + +static int +disasm_codefetch_1(disasm_context_t *ctx) +{ + UINT8 val; + int rv; + + rv = convert_address(ctx); + if (rv) + return rv; + + val = cpu_memoryread(ctx->val); + ctx->val = val; + + ctx->opbyte[ctx->nopbytes++] = (UINT8)ctx->val; + ctx->eip++; + + return 0; +} + +#if 0 +static int +disasm_codefetch_2(disasm_context_t *ctx) +{ + UINT16 val; + int rv; + + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + val = (UINT16)(ctx->val & 0xff); + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + val |= (UINT16)(ctx->val & 0xff) << 8; + + ctx->val = val; + return 0; +} + +static int +disasm_codefetch_4(disasm_context_t *ctx) +{ + UINT32 val; + int rv; + + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + val = ctx->val & 0xff; + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + val |= (UINT32)(ctx->val & 0xff) << 8; + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + val |= (UINT32)(ctx->val & 0xff) << 16; + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + val |= (UINT32)(ctx->val & 0xff) << 24; + + ctx->val = val; + return 0; +} + +/* + * get effective address. + */ + +static int +ea16(disasm_context_t *ctx, char *buf, size_t size) +{ + static const char *ea16_str[8] = { + "bx + si", "bx + di", "bp + si", "bp + di", + "si", "di", "bp", "bx" + }; + UINT32 val; + UINT mod, rm; + int rv; + + mod = (ctx->modrm >> 6) & 3; + rm = ctx->modrm & 7; + + if (mod == 0) { + if (rm == 6) { + /* disp16 */ + rv = disasm_codefetch_2(ctx); + if (rv) + return rv; + + snprintf(buf, size, "[0x%04x]", ctx->val); + } else { + snprintf(buf, size, "[%s]", ea16_str[rm]); + } + } else { + if (mod == 1) { + /* disp8 */ + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + + val = ctx->val; + if (val & 0x80) { + val |= 0xff00; + } + } else { + /* disp16 */ + rv = disasm_codefetch_2(ctx); + if (rv) + return rv; + + val = ctx->val; + } + snprintf(buf, size, "[%s + 0x%04x]", ea16_str[rm], val); + } + + return 0; +} + +static int +ea32(disasm_context_t *ctx, char *buf, size_t size) +{ + char tmp[32]; + UINT count[9]; + UINT32 val; + UINT mod, rm; + UINT sib; + UINT scale; + UINT idx; + UINT base; + int rv; + int i, n; + + memset(count, 0, sizeof(count)); + + mod = (ctx->modrm >> 6) & 3; + rm = ctx->modrm & 7; + + /* SIB */ + if (rm == 4) { + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + + sib = ctx->val; + scale = (sib >> 6) & 3; + idx = (sib >> 3) & 7; + base = sib & 7; + + /* base */ + if (mod == 0 && base == 5) { + /* disp32 */ + rv = disasm_codefetch_4(ctx); + if (rv) + return rv; + count[8] += ctx->val; + } else { + count[base]++; + } + + /* index & scale */ + if (idx != 4) { + count[idx] += 1 << scale; + } + } + + /* MOD/RM */ + if (mod == 0 && rm == 5) { + /* disp32 */ + rv = disasm_codefetch_4(ctx); + if (rv) + return rv; + count[8] += ctx->val; + } else { + /* mod */ + if (mod == 1) { + /* disp8 */ + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + + val = ctx->val; + if (val & 0x80) { + val |= 0xffffff00; + } + count[8] += val; + } else if (mod == 2) { + /* disp32 */ + rv = disasm_codefetch_4(ctx); + if (rv) + return rv; + count[8] += ctx->val; + } + + /* rm */ + if (rm != 4) { + count[rm]++; + } + } + + ncpy(buf, "[", size); + for (n = 0, i = 0; i < 8; i++) { + if (count[i] != 0) { + if (n > 0) { + ncat(buf, " + ", size); + } + if (count[i] > 1) { + snprintf(tmp, size, "%s * %d", + reg32_str[i], count[i]); + } else { + ncpy(tmp, reg32_str[i], sizeof(tmp)); + } + ncat(buf, tmp, size); + n++; + } + } + if (count[8] != 0) { + if (n > 0) { + ncat(buf, " + ", size); + } + snprintf(tmp, sizeof(tmp), "0x%08x", count[8]); + ncat(buf, tmp, size); + } + ncat(buf, "]", size); + + return 0; +} + +static int +ea(disasm_context_t *ctx) +{ + char buf[256]; + char tmp[8]; + size_t len; + int rv; + + memset(buf, 0, sizeof(buf)); + + if (!ctx->as32) + rv = ea16(ctx, buf, sizeof(buf)); + else + rv = ea32(ctx, buf, sizeof(buf)); + if (rv) + return rv; + + if (ctx->narg == 0) { + ncat(ctx->next, sep[0], ctx->remain); + } else { + ncat(ctx->next, sep[1], ctx->remain); + } + len = strlen(ctx->next); + len = (len < ctx->remain) ? len : ctx->remain; + ctx->next += len; + ctx->remain -= len; + + ctx->arg[ctx->narg++] = ctx->next; + if (ctx->useseg) { + snprintf(tmp, sizeof(tmp), "%s:", sreg_str[ctx->seg]); + ncat(ctx->next, tmp, ctx->remain); + } + ncat(ctx->next, buf, ctx->remain); + len = strlen(ctx->next); + len = (len < ctx->remain) ? len : ctx->remain; + ctx->next += len; + ctx->remain -= len; + + return 0; +} +#endif + +/* + * get opcode + */ +static int +get_opcode(disasm_context_t *ctx) +{ + const char *opcode; + UINT8 op[3]; + int prefix; + size_t len; + int rv; + int i; + + for (prefix = 0; prefix < MAX_PREFIX; prefix++) { + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + + op[0] = (UINT8)(ctx->val & 0xff); + if (!(insttable_info[op[0]] & INST_PREFIX)) + break; + + if (ctx->prefix == 0) + ctx->prefix = ctx->next; + + switch (op[0]) { + case 0x26: /* ES: */ + case 0x2e: /* CS: */ + case 0x36: /* SS: */ + case 0x3e: /* DS: */ + ctx->useseg = TRUE; + ctx->seg = (op[0] >> 3) & 3; + break; + + case 0x64: /* FS: */ + case 0x65: /* GS: */ + ctx->useseg = TRUE; + ctx->seg = (op[0] - 0x64) + 4; + break; + + case 0x66: /* OPSize: */ + ctx->op32 = !CPU_STATSAVE.cpu_inst_default.op_32; + break; + + case 0x67: /* AddrSize: */ + ctx->as32 = !CPU_STATSAVE.cpu_inst_default.as_32; + break; + } + } + if (prefix == MAX_PREFIX) + return 1; + + if (ctx->prefix) { + for (i = 0; i < prefix - 1; i++) { + opcode = opcode_1byte[ctx->op32][ctx->opbyte[i]]; + if (opcode) { + ncat(ctx->next, opcode, ctx->remain); + ncat(ctx->next, " ", ctx->remain); + } + } + len = strlen(ctx->next); + len = (len < ctx->remain) ? len : ctx->remain; + ctx->next += len; + ctx->remain -= len; + } + + ctx->opcode[0] = op[0]; + opcode = opcode_1byte[ctx->op32][op[0]]; + if (opcode == NULL) { + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + + op[1] = (UINT8)(ctx->val & 0xff); + ctx->opcode[1] = op[1]; + + switch (op[0]) { + case 0x0f: + opcode = opcode_2byte[ctx->op32][op[1]]; + if (opcode == NULL) { + rv = disasm_codefetch_1(ctx); + if (rv) + return rv; + + op[2] = (UINT8)(ctx->val & 0xff); + ctx->opcode[2] = op[2]; + + switch (op[1]) { + case 0x00: + opcode = opcode2_g6[(op[2]>>3)&7]; + ctx->modrm = op[2]; + break; + + case 0x01: + opcode = opcode2_g7[(op[2]>>3)&7]; + ctx->modrm = op[2]; + break; + + case 0xba: + opcode = opcode2_g8[(op[2]>>3)&7]; + ctx->modrm = op[2]; + break; + + case 0xc7: + opcode = opcode2_g9[(op[2]>>3)&7]; + ctx->modrm = op[2]; + break; + } + } + break; + + case 0x80: case 0x81: case 0x82: case 0x83: + opcode = opcode_0x8x[ctx->op32][op[0]&1][(op[1]>>3)&7]; + ctx->modrm = op[1]; + break; + + case 0xc0: case 0xc1: + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + opcode = opcode_shift[ctx->op32][op[0]&1][(op[1]>>3)&7]; + ctx->modrm = op[1]; + break; + + case 0xf6: case 0xf7: + opcode = opcode_0xf6[ctx->op32][op[0]&1][(op[1]>>3)&7]; + ctx->modrm = op[1]; + break; + + case 0xfe: case 0xff: + opcode = opcode_0xfe[ctx->op32][op[0]&1][(op[1]>>3)&7]; + ctx->modrm = op[1]; + break; + } + } + if (opcode == NULL) + return 1; + + ncat(ctx->next, opcode, ctx->remain); + + return 0; +} + +/* + * interface + */ +int +disasm(UINT32 *eip, disasm_context_t *ctx) +{ + int rv; + + memset(ctx, 0, sizeof(disasm_context_t)); + ctx->remain = sizeof(ctx->str) - 1; + ctx->next = ctx->str; + ctx->prefix = 0; + ctx->op = 0; + ctx->arg[0] = 0; + ctx->arg[1] = 0; + ctx->arg[2] = 0; + + ctx->eip = *eip; + ctx->op32 = CPU_STATSAVE.cpu_inst_default.op_32; + ctx->as32 = CPU_STATSAVE.cpu_inst_default.as_32; + ctx->seg = -1; + + ctx->baseaddr = ctx->eip; + ctx->pad = ' '; + + rv = get_opcode(ctx); + if (rv) { + memset(ctx, 0, sizeof(disasm_context_t)); + return rv; + } + *eip = ctx->eip; + + return 0; +} + +char * +cpu_disasm2str(UINT32 eip) +{ + static char output[2048]; + disasm_context_t d; + UINT32 eip2 = eip; + int rv; + + output[0] = '\0'; + rv = disasm(&eip2, &d); + if (rv == 0) { + char buf[256]; + char tmp[32]; + int len = d.nopbytes > 8 ? 8 : d.nopbytes; + int i; + + buf[0] = '\0'; + for (i = 0; i < len; i++) { + snprintf(tmp, sizeof(tmp), "%02x ", d.opbyte[i]); + ncat(buf, tmp, sizeof(buf)); + } + for (; i < 8; i++) { + ncat(buf, " ", sizeof(buf)); + } + snprintf(output, sizeof(output), "%04x:%08x: %s%s", + CPU_CS, eip, buf, d.str); + + if (i < d.nopbytes) { + char t[256]; + buf[0] = '\0'; + for (; i < d.nopbytes; i++) { + snprintf(tmp, sizeof(tmp), "%02x ", + d.opbyte[i]); + ncat(buf, tmp, sizeof(buf)); + if ((i % 8) == 7) { + snprintf(t, sizeof(t), + "\n : %s", buf); + ncat(output, t, sizeof(output)); + buf[0] = '\0'; + } + } + if ((i % 8) != 0) { + snprintf(t, sizeof(t), + "\n : %s", buf); + ncat(output, t, sizeof(output)); + } + } + } + return output; +} diff --git a/i386c/ia32/exception.c b/i386c/ia32/exception.c old mode 100755 new mode 100644 index 8baebad1..0ed6109f --- a/i386c/ia32/exception.c +++ b/i386c/ia32/exception.c @@ -1,663 +1,663 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" -#include "ia32.mcr" - -const char *exception_str[EXCEPTION_NUM] = { - "DE_EXCEPTION", - "DB_EXCEPTION", - "NMI_EXCEPTION", - "BP_EXCEPTION", - "OF_EXCEPTION", - "BR_EXCEPTION", - "UD_EXCEPTION", - "NM_EXCEPTION", - "DF_EXCEPTION", - "CoProcesser Segment Overrun", - "TS_EXCEPTION", - "NP_EXCEPTION", - "SS_EXCEPTION", - "GP_EXCEPTION", - "PF_EXCEPTION", - "Reserved", - "MF_EXCEPTION", - "AC_EXCEPTION", - "MC_EXCEPTION", - "XF_EXCEPTION", -}; - -static const int exctype[EXCEPTION_NUM] = { - 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, -}; - -static const int dftable[4][4] = { - { 0, 0, 0, 1, }, - { 0, 1, 0, 1, }, - { 0, 1, 1, 1, }, - { 1, 1, 1, 1, }, -}; - -void CPUCALL -exception(int num, int error_code) -{ -#if defined(DEBUG) - extern int cpu_debug_rep_cont; - extern CPU_REGS cpu_debug_rep_regs; -#endif - int errorp = 0; - - __ASSERT((unsigned int)num < EXCEPTION_NUM); - -#if 0 - iptrace_out(); - debugwriteseg("execption.bin", &CPU_CS_DESC, CPU_PREV_EIP & 0xffff0000, 0x10000); -#endif - - VERBOSE(("exception: -------------------------------------------------------------- start")); - VERBOSE(("exception: %s, error_code = %x at %04x:%08x", exception_str[num], error_code, CPU_CS, CPU_PREV_EIP)); - VERBOSE(("%s", cpu_reg2str())); - VERBOSE(("code: %dbit(%dbit), address: %dbit(%dbit)", CPU_INST_OP32 ? 32 : 16, CPU_STATSAVE.cpu_inst_default.op_32 ? 32 : 16, CPU_INST_AS32 ? 32 : 16, CPU_STATSAVE.cpu_inst_default.as_32 ? 32 : 16)); -#if defined(DEBUG) - if (cpu_debug_rep_cont) { - VERBOSE(("rep: original regs: ecx=%08x, esi=%08x, edi=%08x", cpu_debug_rep_regs.reg[CPU_ECX_INDEX].d, cpu_debug_rep_regs.reg[CPU_ESI_INDEX].d, cpu_debug_rep_regs.reg[CPU_EDI_INDEX].d)); - } - VERBOSE(("%s", cpu_disasm2str(CPU_PREV_EIP))); -#endif - - CPU_STAT_EXCEPTION_COUNTER_INC(); - if ((CPU_STAT_EXCEPTION_COUNTER >= 3) - || (CPU_STAT_EXCEPTION_COUNTER == 2 && CPU_STAT_PREV_EXCEPTION == DF_EXCEPTION)) { - /* Triple fault */ - ia32_panic("exception: catch triple fault!"); - } - - switch (num) { - case UD_EXCEPTION: /* (F) 無効オペコード */ - //ia32_warning("warning: undefined op!"); - //{ // TEST!! - // UINT32 op[5]; - // CPU_EIP = CPU_PREV_EIP; - // GET_PCBYTE(op[0]); - // GET_PCBYTE(op[1]); - // GET_PCBYTE(op[2]); - // GET_PCBYTE(op[3]); - // GET_PCBYTE(op[4]); - //} - case DE_EXCEPTION: /* (F) 除算エラー */ - case DB_EXCEPTION: /* (F/T) デバッグ */ - case BR_EXCEPTION: /* (F) BOUND の範囲外 */ - case NM_EXCEPTION: /* (F) デバイス使用不可 (FPU が無い) */ - case MF_EXCEPTION: /* (F) 浮動小数点エラー */ - CPU_EIP = CPU_PREV_EIP; - if (CPU_STATSAVE.cpu_stat.backout_sp) - CPU_ESP = CPU_PREV_ESP; - /*FALLTHROUGH*/ - case NMI_EXCEPTION: /* (I) NMI 割り込み */ - case BP_EXCEPTION: /* (T) ブレークポイント */ - case OF_EXCEPTION: /* (T) オーバーフロー */ - errorp = 0; - break; - - case DF_EXCEPTION: /* (A) ダブルフォルト (errcode: 0) */ - errorp = 1; - error_code = 0; - break; - - case AC_EXCEPTION: /* (F) アラインメントチェック (errcode: 0) */ - error_code = 0; - /*FALLTHROUGH*/ - case TS_EXCEPTION: /* (F) 無効 TSS (errcode) */ - case NP_EXCEPTION: /* (F) セグメント不在 (errcode) */ - case SS_EXCEPTION: /* (F) スタックセグメントフォルト (errcode) */ - case GP_EXCEPTION: /* (F) 一般保護例外 (errcode) */ - case PF_EXCEPTION: /* (F) ページフォルト (errcode) */ - CPU_EIP = CPU_PREV_EIP; - if (CPU_STATSAVE.cpu_stat.backout_sp) - CPU_ESP = CPU_PREV_ESP; - errorp = 1; - break; - - default: - ia32_panic("exception: unknown exception (%d)", num); - break; - } - - if (CPU_STAT_EXCEPTION_COUNTER >= 2) { - if (dftable[exctype[CPU_STAT_PREV_EXCEPTION]][exctype[num]]) { - num = DF_EXCEPTION; - errorp = 1; - error_code = 0; - } - } - CPU_STAT_PREV_EXCEPTION = num; - - VERBOSE(("exception: ---------------------------------------------------------------- end")); - - interrupt(num, INTR_TYPE_EXCEPTION, errorp, error_code); - CPU_STAT_EXCEPTION_COUNTER_CLEAR(); - siglongjmp(exec_1step_jmpbuf, 1); -} - -/* - * コール・ゲート・ディスクリプタ - * - * 31 16 15 14 13 12 8 7 5 4 0 - * +------------------------------------+--+-----+----------+-----+---------+ - * | オフセット 31..16 | P| DPL | 0 D 1 0 0|0 0 0|カウント | 4 - * +------------------------------------+--+-----+----------+-----+---------+ - * 31 16 15 0 - * +------------------------------------+-----------------------------------+ - * | セグメント・セレクタ | オフセット 15..0 | 0 - * +------------------------------------+-----------------------------------+ - */ - -/* - * 割り込みディスクリプタ - *-- - * タスク・ゲート - * - * 31 16 15 14 13 12 8 7 0 - * +------------------------------------+--+-----+----------+---------------+ - * | Reserved | P| DPL | 0 0 1 0 1| Reserved | 4 - * +------------------------------------+--+-----+----------+---------------+ - * 31 16 15 0 - * +------------------------------------+-----------------------------------+ - * | TSS セグメント・セレクタ | Reserved | 0 - * +------------------------------------+-----------------------------------+ - *-- - * 割り込み・ゲート - * - * 31 16 15 14 13 12 8 7 5 4 0 - * +------------------------------------+--+-----+----------+-----+---------+ - * | オフセット 31..16 | P| DPL | 0 D 1 1 0|0 0 0|Reserved | 4 - * +------------------------------------+--+-----+----------+-----+---------+ - * 31 16 15 0 - * +------------------------------------+-----------------------------------+ - * | セグメント・セレクタ | オフセット 15..0 | 0 - * +------------------------------------+-----------------------------------+ - *-- - * トラップ・ゲート - * - * 31 16 15 14 13 12 8 7 5 4 0 - * +------------------------------------+--+-----+----------+-----+---------+ - * | オフセット 31..16 | P| DPL | 0 D 1 1 1|0 0 0|Reserved | 4 - * +------------------------------------+--+-----+----------+-----+---------+ - * 31 16 15 0 - * +------------------------------------+-----------------------------------+ - * | セグメント・セレクタ | オフセット 15..0 | 0 - * +------------------------------------+-----------------------------------+ - *-- - * DPL : ディスクリプタ特権レベル - * オフセット : プロシージャ・エントリ・ポイントまでのオフセット - * P : セグメント存在フラグ - * セレクタ : ディスティネーション・コード・セグメントのセグメント・セレクタ - * D : ゲートのサイズ.0 = 16 bit, 1 = 32 bit - */ - -static void CPUCALL interrupt_task_gate(const descriptor_t *gsdp, int intrtype, int errorp, int error_code); -static void CPUCALL interrupt_intr_or_trap(const descriptor_t *gsdp, int intrtype, int errorp, int error_code); - -void CPUCALL -interrupt(int num, int intrtype, int errorp, int error_code) -{ - descriptor_t gsd; - UINT idt_idx; - UINT32 new_ip; - UINT16 new_cs; - int exc_errcode; - - VERBOSE(("interrupt: num = 0x%02x, intrtype = %s, errorp = %s, error_code = %08x", num, (intrtype == INTR_TYPE_EXTINTR) ? "external" : (intrtype == INTR_TYPE_EXCEPTION ? "exception" : "softint"), errorp ? "on" : "off", error_code)); - - CPU_SET_PREV_ESP(); - - if (!CPU_STAT_PM) { - /* real mode */ - CPU_WORKCLOCK(20); - - idt_idx = num * 4; - if (idt_idx + 3 > CPU_IDTR_LIMIT) { - VERBOSE(("interrupt: real-mode IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT)); - EXCEPTION(GP_EXCEPTION, idt_idx + 2); - } - - if ((intrtype == INTR_TYPE_EXTINTR) && CPU_STAT_HLT) { - VERBOSE(("interrupt: reset HTL in real mode")); - CPU_EIP++; - CPU_STAT_HLT = 0; - } - - REGPUSH0(REAL_FLAGREG); - REGPUSH0(CPU_CS); - REGPUSH0(CPU_IP); - - CPU_EFLAG &= ~(T_FLAG | I_FLAG | AC_FLAG | RF_FLAG); - CPU_TRAP = 0; - - new_ip = cpu_memoryread_w(CPU_IDTR_BASE + idt_idx); - new_cs = cpu_memoryread_w(CPU_IDTR_BASE + idt_idx + 2); - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - CPU_EIP = new_ip; - } else { - /* protected mode */ - CPU_WORKCLOCK(200); - - VERBOSE(("interrupt: -------------------------------------------------------------- start")); - VERBOSE(("interrupt: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); - -#if defined(DEBUG) - if (num == 0x80) { - /* Linux, FreeBSD, NetBSD, OpenBSD system call */ - VERBOSE(("interrupt: syscall# = %d\n%s", CPU_EAX, cpu_reg2str())); - } -#endif - - idt_idx = num * 8; - exc_errcode = idt_idx + 2; - if (intrtype == INTR_TYPE_EXTINTR) - exc_errcode++; - - if (idt_idx + 7 > CPU_IDTR_LIMIT) { - VERBOSE(("interrupt: IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT)); - EXCEPTION(GP_EXCEPTION, exc_errcode); - } - - /* load a gate descriptor from interrupt descriptor table */ - memset(&gsd, 0, sizeof(gsd)); - load_descriptor(&gsd, CPU_IDTR_BASE + idt_idx); - if (!SEG_IS_VALID(&gsd)) { - VERBOSE(("interrupt: gate descripter is invalid.")); - EXCEPTION(GP_EXCEPTION, exc_errcode); - } - if (!SEG_IS_SYSTEM(&gsd)) { - VERBOSE(("interrupt: gate descriptor is not system segment.")); - EXCEPTION(GP_EXCEPTION, exc_errcode); - } - - switch (gsd.type) { - case CPU_SYSDESC_TYPE_TASK: - case CPU_SYSDESC_TYPE_INTR_16: - case CPU_SYSDESC_TYPE_INTR_32: - case CPU_SYSDESC_TYPE_TRAP_16: - case CPU_SYSDESC_TYPE_TRAP_32: - break; - - default: - VERBOSE(("interrupt: invalid gate type (%d)", gsd.type)); - EXCEPTION(GP_EXCEPTION, exc_errcode); - break; - } - - /* 5.10.1.1. 例外/割り込みハンドラ・プロシージャの保護 */ - if ((intrtype == INTR_TYPE_SOFTINTR) && (gsd.dpl < CPU_STAT_CPL)) { - VERBOSE(("interrupt: intrtype(softint) && DPL(%d) < CPL(%d)", gsd.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, exc_errcode); - } - - if (!SEG_IS_PRESENT(&gsd)) { - VERBOSE(("interrupt: gate descriptor is not present.")); - EXCEPTION(NP_EXCEPTION, exc_errcode); - } - - if ((intrtype == INTR_TYPE_EXTINTR) && CPU_STAT_HLT) { - VERBOSE(("interrupt: reset HTL in protected mode")); - CPU_EIP++; - CPU_STAT_HLT = 0; - } - - switch (gsd.type) { - case CPU_SYSDESC_TYPE_TASK: - interrupt_task_gate(&gsd, intrtype, errorp, error_code); - break; - - case CPU_SYSDESC_TYPE_INTR_16: - case CPU_SYSDESC_TYPE_INTR_32: - case CPU_SYSDESC_TYPE_TRAP_16: - case CPU_SYSDESC_TYPE_TRAP_32: - interrupt_intr_or_trap(&gsd, intrtype, errorp, error_code); - break; - - default: - EXCEPTION(GP_EXCEPTION, exc_errcode); - break; - } - - VERBOSE(("interrupt: ---------------------------------------------------------------- end")); - } - - CPU_CLEAR_PREV_ESP(); -} - -static void CPUCALL -interrupt_task_gate(const descriptor_t *gsdp, int intrtype, int errorp, int error_code) -{ - selector_t task_sel; - int rv; - - VERBOSE(("interrupt: TASK-GATE")); - - rv = parse_selector(&task_sel, gsdp->u.gate.selector); - if (rv < 0 || task_sel.ldt || !SEG_IS_SYSTEM(&task_sel.desc)) { - VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d, %cDT, type = %s)", gsdp->u.gate.selector, rv, task_sel.ldt ? 'L' : 'G', task_sel.desc.s ? "code/data" : "system")); - EXCEPTION(TS_EXCEPTION, task_sel.idx); - } - - /* check gate type */ - switch (task_sel.desc.type) { - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_TSS_32: - break; - - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - VERBOSE(("interrupt: task is busy.")); - /*FALLTHROUGH*/ - default: - VERBOSE(("interrupt: invalid gate type (%d)", task_sel.desc.type)); - EXCEPTION(TS_EXCEPTION, task_sel.idx); - break; - } - - /* not present */ - if (selector_is_not_present(&task_sel)) { - VERBOSE(("interrupt: selector is not present")); - EXCEPTION(NP_EXCEPTION, task_sel.idx); - } - - task_switch(&task_sel, TASK_SWITCH_INTR); - - CPU_SET_PREV_ESP(); - - if (errorp) { - VERBOSE(("interrupt: push error code (%08x)", error_code)); - if (task_sel.desc.type == CPU_SYSDESC_TYPE_TSS_32) { - PUSH0_32(error_code); - } else { - PUSH0_16(error_code); - } - } - - /* out of range */ - if (CPU_EIP > CPU_STAT_CS_LIMIT) { - VERBOSE(("interrupt: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); - EXCEPTION(GP_EXCEPTION, 0); - } -} - -static void CPUCALL -interrupt_intr_or_trap(const descriptor_t *gsdp, int intrtype, int errorp, int error_code) -{ - selector_t cs_sel, ss_sel; - UINT stacksize; - UINT32 old_flags; - UINT32 new_flags; - UINT32 mask; - UINT32 sp; - UINT32 new_ip, new_sp; - UINT32 old_ip, old_sp; - UINT16 old_cs, old_ss, new_ss; - BOOL is32bit; - int exc_errcode; - int rv; - - new_ip = gsdp->u.gate.offset; - old_ss = CPU_SS; - old_cs = CPU_CS; - old_ip = CPU_EIP; - old_sp = CPU_ESP; - old_flags = REAL_EFLAGREG; - new_flags = REAL_EFLAGREG & ~(T_FLAG|RF_FLAG|NT_FLAG|VM_FLAG); - mask = T_FLAG|RF_FLAG|NT_FLAG|VM_FLAG; - - switch (gsdp->type) { - case CPU_SYSDESC_TYPE_INTR_16: - case CPU_SYSDESC_TYPE_INTR_32: - VERBOSE(("interrupt: INTERRUPT-GATE")); - new_flags &= ~I_FLAG; - mask |= I_FLAG; - break; - - case CPU_SYSDESC_TYPE_TRAP_16: - case CPU_SYSDESC_TYPE_TRAP_32: - VERBOSE(("interrupt: TRAP-GATE")); - break; - - default: - ia32_panic("interrupt: gate descriptor type is invalid (type = %d)", gsdp->type); - break; - } - - exc_errcode = gsdp->u.gate.selector & ~3; - if (intrtype == INTR_TYPE_EXTINTR) - exc_errcode++; - - rv = parse_selector(&cs_sel, gsdp->u.gate.selector); - if (rv < 0) { - VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d)", gsdp->u.gate.selector, rv)); - EXCEPTION(GP_EXCEPTION, exc_errcode); - } - - /* check segment type */ - if (SEG_IS_SYSTEM(&cs_sel.desc)) { - VERBOSE(("interrupt: code segment is system segment")); - EXCEPTION(GP_EXCEPTION, exc_errcode); - } - if (SEG_IS_DATA(&cs_sel.desc)) { - VERBOSE(("interrupt: code segment is data segment")); - EXCEPTION(GP_EXCEPTION, exc_errcode); - } - - /* check privilege level */ - if (cs_sel.desc.dpl > CPU_STAT_CPL) { - VERBOSE(("interrupt: DPL(%d) > CPL(%d)", cs_sel.desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, exc_errcode); - } - - /* not present */ - if (selector_is_not_present(&cs_sel)) { - VERBOSE(("interrupt: selector is not present")); - EXCEPTION(NP_EXCEPTION, exc_errcode); - } - - is32bit = gsdp->type & CPU_SYSDESC_TYPE_32BIT; - if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc) && (cs_sel.desc.dpl < CPU_STAT_CPL)) { - stacksize = errorp ? 12 : 10; - if (!CPU_STAT_VM86) { - VERBOSE(("interrupt: INTER-PRIVILEGE-LEVEL-INTERRUPT")); - } else { - /* VM86 */ - VERBOSE(("interrupt: INTERRUPT-FROM-VIRTUAL-8086-MODE")); - if (cs_sel.desc.dpl != 0) { - /* 16.3.1.1 */ - VERBOSE(("interrupt: DPL[CS](%d) != 0", cs_sel.desc.dpl)); - EXCEPTION(GP_EXCEPTION, exc_errcode); - } - stacksize += 8; - } - if (is32bit) { - stacksize *= 2; - } - - /* get stack pointer from TSS */ - get_stack_pointer_from_tss(cs_sel.desc.dpl, &new_ss, &new_sp); - - /* parse stack segment descriptor */ - rv = parse_selector(&ss_sel, new_ss); - - /* update exception error code */ - exc_errcode = ss_sel.idx; - if (intrtype == INTR_TYPE_EXTINTR) - exc_errcode++; - - if (rv < 0) { - VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d)", new_ss, rv)); - EXCEPTION(TS_EXCEPTION, exc_errcode); - } - - /* check privilege level */ - if (ss_sel.rpl != cs_sel.desc.dpl) { - VERBOSE(("interrupt: selector RPL[SS](%d) != DPL[CS](%d)", ss_sel.rpl, cs_sel.desc.dpl)); - EXCEPTION(TS_EXCEPTION, exc_errcode); - } - if (ss_sel.desc.dpl != cs_sel.desc.dpl) { - VERBOSE(("interrupt: descriptor DPL[SS](%d) != DPL[CS](%d)", ss_sel.desc.dpl, cs_sel.desc.dpl)); - EXCEPTION(TS_EXCEPTION, exc_errcode); - } - - /* stack segment must be writable data segment. */ - if (SEG_IS_SYSTEM(&ss_sel.desc)) { - VERBOSE(("interrupt: stack segment is system segment")); - EXCEPTION(TS_EXCEPTION, exc_errcode); - } - if (SEG_IS_CODE(&ss_sel.desc)) { - VERBOSE(("interrupt: stack segment is code segment")); - EXCEPTION(TS_EXCEPTION, exc_errcode); - } - if (!SEG_IS_WRITABLE_DATA(&ss_sel.desc)) { - VERBOSE(("interrupt: stack segment is read-only data segment")); - EXCEPTION(TS_EXCEPTION, exc_errcode); - } - - /* not present */ - if (selector_is_not_present(&ss_sel)) { - VERBOSE(("interrupt: selector is not present")); - EXCEPTION(SS_EXCEPTION, exc_errcode); - } - - /* check stack room size */ - cpu_stack_push_check(ss_sel.idx, &ss_sel.desc, new_sp, stacksize, ss_sel.desc.d); - - /* out of range */ - if (new_ip > cs_sel.desc.u.seg.limit) { - VERBOSE(("interrupt: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel.desc.u.seg.limit)); - EXCEPTION(GP_EXCEPTION, 0); - } - - load_ss(ss_sel.selector, &ss_sel.desc, cs_sel.desc.dpl); - CPU_ESP = new_sp; - - load_cs(cs_sel.selector, &cs_sel.desc, cs_sel.desc.dpl); - CPU_EIP = new_ip; - - if (is32bit) { - if (CPU_STAT_VM86) { - PUSH0_32(CPU_GS); - PUSH0_32(CPU_FS); - PUSH0_32(CPU_DS); - PUSH0_32(CPU_ES); - - LOAD_SEGREG(CPU_GS_INDEX, 0); - CPU_STAT_SREG(CPU_GS_INDEX).valid = 0; - LOAD_SEGREG(CPU_FS_INDEX, 0); - CPU_STAT_SREG(CPU_FS_INDEX).valid = 0; - LOAD_SEGREG(CPU_DS_INDEX, 0); - CPU_STAT_SREG(CPU_DS_INDEX).valid = 0; - LOAD_SEGREG(CPU_ES_INDEX, 0); - CPU_STAT_SREG(CPU_ES_INDEX).valid = 0; - } - PUSH0_32(old_ss); - PUSH0_32(old_sp); - PUSH0_32(old_flags); - PUSH0_32(old_cs); - PUSH0_32(old_ip); - if (errorp) { - PUSH0_32(error_code); - } - } else { - if (CPU_STAT_VM86) { - ia32_panic("interrupt: 16bit gate && VM86"); - } - PUSH0_16(old_ss); - PUSH0_16(old_sp); - PUSH0_16(old_flags); - PUSH0_16(old_cs); - PUSH0_16(old_ip); - if (errorp) { - PUSH0_16(error_code); - } - } - } else { - if (CPU_STAT_VM86) { - VERBOSE(("interrupt: VM86")); - EXCEPTION(GP_EXCEPTION, exc_errcode); - } - if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc) && (cs_sel.desc.dpl != CPU_STAT_CPL)) { - VERBOSE(("interrupt: %sCONFORMING-CODE-SEGMENT(%d) && DPL[CS](%d) != CPL", SEG_IS_CONFORMING_CODE(&cs_sel.desc) ? "" : "NON-", cs_sel.desc.dpl, CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, exc_errcode); - } - - VERBOSE(("interrupt: INTRA-PRIVILEGE-LEVEL-INTERRUPT")); - - stacksize = errorp ? 8 : 6; - if (is32bit) { - stacksize *= 2; - } - - /* check stack room size */ - if (CPU_STAT_SS32) { - sp = CPU_ESP; - } else { - sp = CPU_SP; - } - /* - * 17.1 - * コールゲート、割り込みゲート、またはトラップゲートを通じて - * プログラムの制御を他のコード・セグメントに移行するときは、 - * 移行中に使用されるオペランド・サイズは使用されるゲートの - * タイプ(16 ビットまたは32 ビット)によって決まる(移行命 - * 令のD フラグ、プリフィックスのいずれにもよらない)。 - */ - SS_PUSH_CHECK1(sp, stacksize, is32bit); - - /* out of range */ - if (new_ip > cs_sel.desc.u.seg.limit) { - VERBOSE(("interrupt: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel.desc.u.seg.limit)); - EXCEPTION(GP_EXCEPTION, 0); - } - - load_cs(cs_sel.selector, &cs_sel.desc, CPU_STAT_CPL); - CPU_EIP = new_ip; - - if (is32bit) { - PUSH0_32(old_flags); - PUSH0_32(old_cs); - PUSH0_32(old_ip); - if (errorp) { - PUSH0_32(error_code); - } - } else { - PUSH0_16(old_flags); - PUSH0_16(old_cs); - PUSH0_16(old_ip); - if (errorp) { - PUSH0_16(error_code); - } - } - } - set_eflags(new_flags, mask); - - VERBOSE(("interrupt: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); -} +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" +#include "ia32.mcr" + +const char *exception_str[EXCEPTION_NUM] = { + "DE_EXCEPTION", + "DB_EXCEPTION", + "NMI_EXCEPTION", + "BP_EXCEPTION", + "OF_EXCEPTION", + "BR_EXCEPTION", + "UD_EXCEPTION", + "NM_EXCEPTION", + "DF_EXCEPTION", + "CoProcesser Segment Overrun", + "TS_EXCEPTION", + "NP_EXCEPTION", + "SS_EXCEPTION", + "GP_EXCEPTION", + "PF_EXCEPTION", + "Reserved", + "MF_EXCEPTION", + "AC_EXCEPTION", + "MC_EXCEPTION", + "XF_EXCEPTION", +}; + +static const int exctype[EXCEPTION_NUM] = { + 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, +}; + +static const int dftable[4][4] = { + { 0, 0, 0, 1, }, + { 0, 1, 0, 1, }, + { 0, 1, 1, 1, }, + { 1, 1, 1, 1, }, +}; + +void CPUCALL +exception(int num, int error_code) +{ +#if defined(DEBUG) + extern int cpu_debug_rep_cont; + extern CPU_REGS cpu_debug_rep_regs; +#endif + int errorp = 0; + + __ASSERT((unsigned int)num < EXCEPTION_NUM); + +#if 0 + iptrace_out(); + debugwriteseg("execption.bin", &CPU_CS_DESC, CPU_PREV_EIP & 0xffff0000, 0x10000); +#endif + + VERBOSE(("exception: -------------------------------------------------------------- start")); + VERBOSE(("exception: %s, error_code = %x at %04x:%08x", exception_str[num], error_code, CPU_CS, CPU_PREV_EIP)); + VERBOSE(("%s", cpu_reg2str())); + VERBOSE(("code: %dbit(%dbit), address: %dbit(%dbit)", CPU_INST_OP32 ? 32 : 16, CPU_STATSAVE.cpu_inst_default.op_32 ? 32 : 16, CPU_INST_AS32 ? 32 : 16, CPU_STATSAVE.cpu_inst_default.as_32 ? 32 : 16)); +#if defined(DEBUG) + if (cpu_debug_rep_cont) { + VERBOSE(("rep: original regs: ecx=%08x, esi=%08x, edi=%08x", cpu_debug_rep_regs.reg[CPU_ECX_INDEX].d, cpu_debug_rep_regs.reg[CPU_ESI_INDEX].d, cpu_debug_rep_regs.reg[CPU_EDI_INDEX].d)); + } + VERBOSE(("%s", cpu_disasm2str(CPU_PREV_EIP))); +#endif + + CPU_STAT_EXCEPTION_COUNTER_INC(); + if ((CPU_STAT_EXCEPTION_COUNTER >= 3) + || (CPU_STAT_EXCEPTION_COUNTER == 2 && CPU_STAT_PREV_EXCEPTION == DF_EXCEPTION)) { + /* Triple fault */ + ia32_panic("exception: catch triple fault!"); + } + + switch (num) { + case UD_EXCEPTION: /* (F) 無効オペコード */ + //ia32_warning("warning: undefined op!"); + //{ // TEST!! + // UINT32 op[5]; + // CPU_EIP = CPU_PREV_EIP; + // GET_PCBYTE(op[0]); + // GET_PCBYTE(op[1]); + // GET_PCBYTE(op[2]); + // GET_PCBYTE(op[3]); + // GET_PCBYTE(op[4]); + //} + case DE_EXCEPTION: /* (F) 除算エラー */ + case DB_EXCEPTION: /* (F/T) デバッグ */ + case BR_EXCEPTION: /* (F) BOUND の範囲外 */ + case NM_EXCEPTION: /* (F) デバイス使用不可 (FPU が無い) */ + case MF_EXCEPTION: /* (F) 浮動小数点エラー */ + CPU_EIP = CPU_PREV_EIP; + if (CPU_STATSAVE.cpu_stat.backout_sp) + CPU_ESP = CPU_PREV_ESP; + /*FALLTHROUGH*/ + case NMI_EXCEPTION: /* (I) NMI 割り込み */ + case BP_EXCEPTION: /* (T) ブレークポイント */ + case OF_EXCEPTION: /* (T) オーバーフロー */ + errorp = 0; + break; + + case DF_EXCEPTION: /* (A) ダブルフォルト (errcode: 0) */ + errorp = 1; + error_code = 0; + break; + + case AC_EXCEPTION: /* (F) アラインメントチェック (errcode: 0) */ + error_code = 0; + /*FALLTHROUGH*/ + case TS_EXCEPTION: /* (F) 無効 TSS (errcode) */ + case NP_EXCEPTION: /* (F) セグメント不在 (errcode) */ + case SS_EXCEPTION: /* (F) スタックセグメントフォルト (errcode) */ + case GP_EXCEPTION: /* (F) 一般保護例外 (errcode) */ + case PF_EXCEPTION: /* (F) ページフォルト (errcode) */ + CPU_EIP = CPU_PREV_EIP; + if (CPU_STATSAVE.cpu_stat.backout_sp) + CPU_ESP = CPU_PREV_ESP; + errorp = 1; + break; + + default: + ia32_panic("exception: unknown exception (%d)", num); + break; + } + + if (CPU_STAT_EXCEPTION_COUNTER >= 2) { + if (dftable[exctype[CPU_STAT_PREV_EXCEPTION]][exctype[num]]) { + num = DF_EXCEPTION; + errorp = 1; + error_code = 0; + } + } + CPU_STAT_PREV_EXCEPTION = num; + + VERBOSE(("exception: ---------------------------------------------------------------- end")); + + interrupt(num, INTR_TYPE_EXCEPTION, errorp, error_code); + CPU_STAT_EXCEPTION_COUNTER_CLEAR(); + siglongjmp(exec_1step_jmpbuf, 1); +} + +/* + * コール・ゲート・ディスクリプタ + * + * 31 16 15 14 13 12 8 7 5 4 0 + * +------------------------------------+--+-----+----------+-----+---------+ + * | オフセット 31..16 | P| DPL | 0 D 1 0 0|0 0 0|カウント | 4 + * +------------------------------------+--+-----+----------+-----+---------+ + * 31 16 15 0 + * +------------------------------------+-----------------------------------+ + * | セグメント・セレクタ | オフセット 15..0 | 0 + * +------------------------------------+-----------------------------------+ + */ + +/* + * 割り込みディスクリプタ + *-- + * タスク・ゲート + * + * 31 16 15 14 13 12 8 7 0 + * +------------------------------------+--+-----+----------+---------------+ + * | Reserved | P| DPL | 0 0 1 0 1| Reserved | 4 + * +------------------------------------+--+-----+----------+---------------+ + * 31 16 15 0 + * +------------------------------------+-----------------------------------+ + * | TSS セグメント・セレクタ | Reserved | 0 + * +------------------------------------+-----------------------------------+ + *-- + * 割り込み・ゲート + * + * 31 16 15 14 13 12 8 7 5 4 0 + * +------------------------------------+--+-----+----------+-----+---------+ + * | オフセット 31..16 | P| DPL | 0 D 1 1 0|0 0 0|Reserved | 4 + * +------------------------------------+--+-----+----------+-----+---------+ + * 31 16 15 0 + * +------------------------------------+-----------------------------------+ + * | セグメント・セレクタ | オフセット 15..0 | 0 + * +------------------------------------+-----------------------------------+ + *-- + * トラップ・ゲート + * + * 31 16 15 14 13 12 8 7 5 4 0 + * +------------------------------------+--+-----+----------+-----+---------+ + * | オフセット 31..16 | P| DPL | 0 D 1 1 1|0 0 0|Reserved | 4 + * +------------------------------------+--+-----+----------+-----+---------+ + * 31 16 15 0 + * +------------------------------------+-----------------------------------+ + * | セグメント・セレクタ | オフセット 15..0 | 0 + * +------------------------------------+-----------------------------------+ + *-- + * DPL : ディスクリプタ特権レベル + * オフセット : プロシージャ・エントリ・ポイントまでのオフセット + * P : セグメント存在フラグ + * セレクタ : ディスティネーション・コード・セグメントのセグメント・セレクタ + * D : ゲートのサイズ.0 = 16 bit, 1 = 32 bit + */ + +static void CPUCALL interrupt_task_gate(const descriptor_t *gsdp, int intrtype, int errorp, int error_code); +static void CPUCALL interrupt_intr_or_trap(const descriptor_t *gsdp, int intrtype, int errorp, int error_code); + +void CPUCALL +interrupt(int num, int intrtype, int errorp, int error_code) +{ + descriptor_t gsd; + UINT idt_idx; + UINT32 new_ip; + UINT16 new_cs; + int exc_errcode; + + VERBOSE(("interrupt: num = 0x%02x, intrtype = %s, errorp = %s, error_code = %08x", num, (intrtype == INTR_TYPE_EXTINTR) ? "external" : (intrtype == INTR_TYPE_EXCEPTION ? "exception" : "softint"), errorp ? "on" : "off", error_code)); + + CPU_SET_PREV_ESP(); + + if (!CPU_STAT_PM) { + /* real mode */ + CPU_WORKCLOCK(20); + + idt_idx = num * 4; + if (idt_idx + 3 > CPU_IDTR_LIMIT) { + VERBOSE(("interrupt: real-mode IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT)); + EXCEPTION(GP_EXCEPTION, idt_idx + 2); + } + + if ((intrtype == INTR_TYPE_EXTINTR) && CPU_STAT_HLT) { + VERBOSE(("interrupt: reset HTL in real mode")); + CPU_EIP++; + CPU_STAT_HLT = 0; + } + + REGPUSH0(REAL_FLAGREG); + REGPUSH0(CPU_CS); + REGPUSH0(CPU_IP); + + CPU_EFLAG &= ~(T_FLAG | I_FLAG | AC_FLAG | RF_FLAG); + CPU_TRAP = 0; + + new_ip = cpu_memoryread_w(CPU_IDTR_BASE + idt_idx); + new_cs = cpu_memoryread_w(CPU_IDTR_BASE + idt_idx + 2); + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + } else { + /* protected mode */ + CPU_WORKCLOCK(200); + + VERBOSE(("interrupt: -------------------------------------------------------------- start")); + VERBOSE(("interrupt: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); + +#if defined(DEBUG) + if (num == 0x80) { + /* Linux, FreeBSD, NetBSD, OpenBSD system call */ + VERBOSE(("interrupt: syscall# = %d\n%s", CPU_EAX, cpu_reg2str())); + } +#endif + + idt_idx = num * 8; + exc_errcode = idt_idx + 2; + if (intrtype == INTR_TYPE_EXTINTR) + exc_errcode++; + + if (idt_idx + 7 > CPU_IDTR_LIMIT) { + VERBOSE(("interrupt: IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT)); + EXCEPTION(GP_EXCEPTION, exc_errcode); + } + + /* load a gate descriptor from interrupt descriptor table */ + memset(&gsd, 0, sizeof(gsd)); + load_descriptor(&gsd, CPU_IDTR_BASE + idt_idx); + if (!SEG_IS_VALID(&gsd)) { + VERBOSE(("interrupt: gate descripter is invalid.")); + EXCEPTION(GP_EXCEPTION, exc_errcode); + } + if (!SEG_IS_SYSTEM(&gsd)) { + VERBOSE(("interrupt: gate descriptor is not system segment.")); + EXCEPTION(GP_EXCEPTION, exc_errcode); + } + + switch (gsd.type) { + case CPU_SYSDESC_TYPE_TASK: + case CPU_SYSDESC_TYPE_INTR_16: + case CPU_SYSDESC_TYPE_INTR_32: + case CPU_SYSDESC_TYPE_TRAP_16: + case CPU_SYSDESC_TYPE_TRAP_32: + break; + + default: + VERBOSE(("interrupt: invalid gate type (%d)", gsd.type)); + EXCEPTION(GP_EXCEPTION, exc_errcode); + break; + } + + /* 5.10.1.1. 例外/割り込みハンドラ・プロシージャの保護 */ + if ((intrtype == INTR_TYPE_SOFTINTR) && (gsd.dpl < CPU_STAT_CPL)) { + VERBOSE(("interrupt: intrtype(softint) && DPL(%d) < CPL(%d)", gsd.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, exc_errcode); + } + + if (!SEG_IS_PRESENT(&gsd)) { + VERBOSE(("interrupt: gate descriptor is not present.")); + EXCEPTION(NP_EXCEPTION, exc_errcode); + } + + if ((intrtype == INTR_TYPE_EXTINTR) && CPU_STAT_HLT) { + VERBOSE(("interrupt: reset HTL in protected mode")); + CPU_EIP++; + CPU_STAT_HLT = 0; + } + + switch (gsd.type) { + case CPU_SYSDESC_TYPE_TASK: + interrupt_task_gate(&gsd, intrtype, errorp, error_code); + break; + + case CPU_SYSDESC_TYPE_INTR_16: + case CPU_SYSDESC_TYPE_INTR_32: + case CPU_SYSDESC_TYPE_TRAP_16: + case CPU_SYSDESC_TYPE_TRAP_32: + interrupt_intr_or_trap(&gsd, intrtype, errorp, error_code); + break; + + default: + EXCEPTION(GP_EXCEPTION, exc_errcode); + break; + } + + VERBOSE(("interrupt: ---------------------------------------------------------------- end")); + } + + CPU_CLEAR_PREV_ESP(); +} + +static void CPUCALL +interrupt_task_gate(const descriptor_t *gsdp, int intrtype, int errorp, int error_code) +{ + selector_t task_sel; + int rv; + + VERBOSE(("interrupt: TASK-GATE")); + + rv = parse_selector(&task_sel, gsdp->u.gate.selector); + if (rv < 0 || task_sel.ldt || !SEG_IS_SYSTEM(&task_sel.desc)) { + VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d, %cDT, type = %s)", gsdp->u.gate.selector, rv, task_sel.ldt ? 'L' : 'G', task_sel.desc.s ? "code/data" : "system")); + EXCEPTION(TS_EXCEPTION, task_sel.idx); + } + + /* check gate type */ + switch (task_sel.desc.type) { + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_TSS_32: + break; + + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + VERBOSE(("interrupt: task is busy.")); + /*FALLTHROUGH*/ + default: + VERBOSE(("interrupt: invalid gate type (%d)", task_sel.desc.type)); + EXCEPTION(TS_EXCEPTION, task_sel.idx); + break; + } + + /* not present */ + if (selector_is_not_present(&task_sel)) { + VERBOSE(("interrupt: selector is not present")); + EXCEPTION(NP_EXCEPTION, task_sel.idx); + } + + task_switch(&task_sel, TASK_SWITCH_INTR); + + CPU_SET_PREV_ESP(); + + if (errorp) { + VERBOSE(("interrupt: push error code (%08x)", error_code)); + if (task_sel.desc.type == CPU_SYSDESC_TYPE_TSS_32) { + PUSH0_32(error_code); + } else { + PUSH0_16(error_code); + } + } + + /* out of range */ + if (CPU_EIP > CPU_STAT_CS_LIMIT) { + VERBOSE(("interrupt: new_ip is out of range. new_ip = %08x, limit = %08x", CPU_EIP, CPU_STAT_CS_LIMIT)); + EXCEPTION(GP_EXCEPTION, 0); + } +} + +static void CPUCALL +interrupt_intr_or_trap(const descriptor_t *gsdp, int intrtype, int errorp, int error_code) +{ + selector_t cs_sel, ss_sel; + UINT stacksize; + UINT32 old_flags; + UINT32 new_flags; + UINT32 mask; + UINT32 sp; + UINT32 new_ip, new_sp; + UINT32 old_ip, old_sp; + UINT16 old_cs, old_ss, new_ss; + BOOL is32bit; + int exc_errcode; + int rv; + + new_ip = gsdp->u.gate.offset; + old_ss = CPU_SS; + old_cs = CPU_CS; + old_ip = CPU_EIP; + old_sp = CPU_ESP; + old_flags = REAL_EFLAGREG; + new_flags = REAL_EFLAGREG & ~(T_FLAG|RF_FLAG|NT_FLAG|VM_FLAG); + mask = T_FLAG|RF_FLAG|NT_FLAG|VM_FLAG; + + switch (gsdp->type) { + case CPU_SYSDESC_TYPE_INTR_16: + case CPU_SYSDESC_TYPE_INTR_32: + VERBOSE(("interrupt: INTERRUPT-GATE")); + new_flags &= ~I_FLAG; + mask |= I_FLAG; + break; + + case CPU_SYSDESC_TYPE_TRAP_16: + case CPU_SYSDESC_TYPE_TRAP_32: + VERBOSE(("interrupt: TRAP-GATE")); + break; + + default: + ia32_panic("interrupt: gate descriptor type is invalid (type = %d)", gsdp->type); + break; + } + + exc_errcode = gsdp->u.gate.selector & ~3; + if (intrtype == INTR_TYPE_EXTINTR) + exc_errcode++; + + rv = parse_selector(&cs_sel, gsdp->u.gate.selector); + if (rv < 0) { + VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d)", gsdp->u.gate.selector, rv)); + EXCEPTION(GP_EXCEPTION, exc_errcode); + } + + /* check segment type */ + if (SEG_IS_SYSTEM(&cs_sel.desc)) { + VERBOSE(("interrupt: code segment is system segment")); + EXCEPTION(GP_EXCEPTION, exc_errcode); + } + if (SEG_IS_DATA(&cs_sel.desc)) { + VERBOSE(("interrupt: code segment is data segment")); + EXCEPTION(GP_EXCEPTION, exc_errcode); + } + + /* check privilege level */ + if (cs_sel.desc.dpl > CPU_STAT_CPL) { + VERBOSE(("interrupt: DPL(%d) > CPL(%d)", cs_sel.desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, exc_errcode); + } + + /* not present */ + if (selector_is_not_present(&cs_sel)) { + VERBOSE(("interrupt: selector is not present")); + EXCEPTION(NP_EXCEPTION, exc_errcode); + } + + is32bit = gsdp->type & CPU_SYSDESC_TYPE_32BIT; + if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc) && (cs_sel.desc.dpl < CPU_STAT_CPL)) { + stacksize = errorp ? 12 : 10; + if (!CPU_STAT_VM86) { + VERBOSE(("interrupt: INTER-PRIVILEGE-LEVEL-INTERRUPT")); + } else { + /* VM86 */ + VERBOSE(("interrupt: INTERRUPT-FROM-VIRTUAL-8086-MODE")); + if (cs_sel.desc.dpl != 0) { + /* 16.3.1.1 */ + VERBOSE(("interrupt: DPL[CS](%d) != 0", cs_sel.desc.dpl)); + EXCEPTION(GP_EXCEPTION, exc_errcode); + } + stacksize += 8; + } + if (is32bit) { + stacksize *= 2; + } + + /* get stack pointer from TSS */ + get_stack_pointer_from_tss(cs_sel.desc.dpl, &new_ss, &new_sp); + + /* parse stack segment descriptor */ + rv = parse_selector(&ss_sel, new_ss); + + /* update exception error code */ + exc_errcode = ss_sel.idx; + if (intrtype == INTR_TYPE_EXTINTR) + exc_errcode++; + + if (rv < 0) { + VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d)", new_ss, rv)); + EXCEPTION(TS_EXCEPTION, exc_errcode); + } + + /* check privilege level */ + if (ss_sel.rpl != cs_sel.desc.dpl) { + VERBOSE(("interrupt: selector RPL[SS](%d) != DPL[CS](%d)", ss_sel.rpl, cs_sel.desc.dpl)); + EXCEPTION(TS_EXCEPTION, exc_errcode); + } + if (ss_sel.desc.dpl != cs_sel.desc.dpl) { + VERBOSE(("interrupt: descriptor DPL[SS](%d) != DPL[CS](%d)", ss_sel.desc.dpl, cs_sel.desc.dpl)); + EXCEPTION(TS_EXCEPTION, exc_errcode); + } + + /* stack segment must be writable data segment. */ + if (SEG_IS_SYSTEM(&ss_sel.desc)) { + VERBOSE(("interrupt: stack segment is system segment")); + EXCEPTION(TS_EXCEPTION, exc_errcode); + } + if (SEG_IS_CODE(&ss_sel.desc)) { + VERBOSE(("interrupt: stack segment is code segment")); + EXCEPTION(TS_EXCEPTION, exc_errcode); + } + if (!SEG_IS_WRITABLE_DATA(&ss_sel.desc)) { + VERBOSE(("interrupt: stack segment is read-only data segment")); + EXCEPTION(TS_EXCEPTION, exc_errcode); + } + + /* not present */ + if (selector_is_not_present(&ss_sel)) { + VERBOSE(("interrupt: selector is not present")); + EXCEPTION(SS_EXCEPTION, exc_errcode); + } + + /* check stack room size */ + cpu_stack_push_check(ss_sel.idx, &ss_sel.desc, new_sp, stacksize, ss_sel.desc.d); + + /* out of range */ + if (new_ip > cs_sel.desc.u.seg.limit) { + VERBOSE(("interrupt: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel.desc.u.seg.limit)); + EXCEPTION(GP_EXCEPTION, 0); + } + + load_ss(ss_sel.selector, &ss_sel.desc, cs_sel.desc.dpl); + CPU_ESP = new_sp; + + load_cs(cs_sel.selector, &cs_sel.desc, cs_sel.desc.dpl); + CPU_EIP = new_ip; + + if (is32bit) { + if (CPU_STAT_VM86) { + PUSH0_32(CPU_GS); + PUSH0_32(CPU_FS); + PUSH0_32(CPU_DS); + PUSH0_32(CPU_ES); + + LOAD_SEGREG(CPU_GS_INDEX, 0); + CPU_STAT_SREG(CPU_GS_INDEX).valid = 0; + LOAD_SEGREG(CPU_FS_INDEX, 0); + CPU_STAT_SREG(CPU_FS_INDEX).valid = 0; + LOAD_SEGREG(CPU_DS_INDEX, 0); + CPU_STAT_SREG(CPU_DS_INDEX).valid = 0; + LOAD_SEGREG(CPU_ES_INDEX, 0); + CPU_STAT_SREG(CPU_ES_INDEX).valid = 0; + } + PUSH0_32(old_ss); + PUSH0_32(old_sp); + PUSH0_32(old_flags); + PUSH0_32(old_cs); + PUSH0_32(old_ip); + if (errorp) { + PUSH0_32(error_code); + } + } else { + if (CPU_STAT_VM86) { + ia32_panic("interrupt: 16bit gate && VM86"); + } + PUSH0_16(old_ss); + PUSH0_16(old_sp); + PUSH0_16(old_flags); + PUSH0_16(old_cs); + PUSH0_16(old_ip); + if (errorp) { + PUSH0_16(error_code); + } + } + } else { + if (CPU_STAT_VM86) { + VERBOSE(("interrupt: VM86")); + EXCEPTION(GP_EXCEPTION, exc_errcode); + } + if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc) && (cs_sel.desc.dpl != CPU_STAT_CPL)) { + VERBOSE(("interrupt: %sCONFORMING-CODE-SEGMENT(%d) && DPL[CS](%d) != CPL", SEG_IS_CONFORMING_CODE(&cs_sel.desc) ? "" : "NON-", cs_sel.desc.dpl, CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, exc_errcode); + } + + VERBOSE(("interrupt: INTRA-PRIVILEGE-LEVEL-INTERRUPT")); + + stacksize = errorp ? 8 : 6; + if (is32bit) { + stacksize *= 2; + } + + /* check stack room size */ + if (CPU_STAT_SS32) { + sp = CPU_ESP; + } else { + sp = CPU_SP; + } + /* + * 17.1 + * コールゲート、割り込みゲート、またはトラップゲートを通じて + * プログラムの制御を他のコード・セグメントに移行するときは、 + * 移行中に使用されるオペランド・サイズは使用されるゲートの + * タイプ(16 ビットまたは32 ビット)によって決まる(移行命 + * 令のD フラグ、プリフィックスのいずれにもよらない)。 + */ + SS_PUSH_CHECK1(sp, stacksize, is32bit); + + /* out of range */ + if (new_ip > cs_sel.desc.u.seg.limit) { + VERBOSE(("interrupt: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel.desc.u.seg.limit)); + EXCEPTION(GP_EXCEPTION, 0); + } + + load_cs(cs_sel.selector, &cs_sel.desc, CPU_STAT_CPL); + CPU_EIP = new_ip; + + if (is32bit) { + PUSH0_32(old_flags); + PUSH0_32(old_cs); + PUSH0_32(old_ip); + if (errorp) { + PUSH0_32(error_code); + } + } else { + PUSH0_16(old_flags); + PUSH0_16(old_cs); + PUSH0_16(old_ip); + if (errorp) { + PUSH0_16(error_code); + } + } + } + set_eflags(new_flags, mask); + + VERBOSE(("interrupt: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP)); +} diff --git a/i386c/ia32/exception.h b/i386c/ia32/exception.h old mode 100755 new mode 100644 index ab54be03..f89ed85a --- a/i386c/ia32/exception.h +++ b/i386c/ia32/exception.h @@ -1,75 +1,75 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_EXCEPTION_H__ -#define IA32_CPU_EXCEPTION_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - DE_EXCEPTION = 0, /* F */ - DB_EXCEPTION = 1, /* F/T */ - NMI_EXCEPTION = 2, /* I */ - BP_EXCEPTION = 3, /* T */ - OF_EXCEPTION = 4, /* T */ - BR_EXCEPTION = 5, /* F */ - UD_EXCEPTION = 6, /* F */ - NM_EXCEPTION = 7, /* F */ - DF_EXCEPTION = 8, /* A, Err(0) */ - /* CoProcesser Segment Overrun = 9 */ - TS_EXCEPTION = 10, /* F */ - NP_EXCEPTION = 11, /* F, Err */ - SS_EXCEPTION = 12, /* F, Err */ - GP_EXCEPTION = 13, /* F, Err */ - PF_EXCEPTION = 14, /* F, Err */ - /* Reserved = 15 */ - MF_EXCEPTION = 16, /* F */ - AC_EXCEPTION = 17, /* F, Err(0) */ - MC_EXCEPTION = 18, /* A, Err(?) */ - XF_EXCEPTION = 19, /* F */ - EXCEPTION_NUM -}; - -enum { - INTR_TYPE_SOFTINTR = -1, /* software interrupt (INTn) */ - INTR_TYPE_EXTINTR = 0, /* external interrupt */ - INTR_TYPE_EXCEPTION = 1, /* exception */ -}; - -#define EXCEPTION(num, vec) \ - exception(num, vec); -#define INTERRUPT(num, softintp) \ - interrupt(num, softintp, 0, 0) - -void CPUCALL exception(int num, int vec); -void CPUCALL interrupt(int num, int intrtype, int errorp, int error_code); - -#ifdef __cplusplus -} -#endif - -#endif /* !IA32_CPU_EXCEPTION_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_EXCEPTION_H__ +#define IA32_CPU_EXCEPTION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + DE_EXCEPTION = 0, /* F */ + DB_EXCEPTION = 1, /* F/T */ + NMI_EXCEPTION = 2, /* I */ + BP_EXCEPTION = 3, /* T */ + OF_EXCEPTION = 4, /* T */ + BR_EXCEPTION = 5, /* F */ + UD_EXCEPTION = 6, /* F */ + NM_EXCEPTION = 7, /* F */ + DF_EXCEPTION = 8, /* A, Err(0) */ + /* CoProcesser Segment Overrun = 9 */ + TS_EXCEPTION = 10, /* F */ + NP_EXCEPTION = 11, /* F, Err */ + SS_EXCEPTION = 12, /* F, Err */ + GP_EXCEPTION = 13, /* F, Err */ + PF_EXCEPTION = 14, /* F, Err */ + /* Reserved = 15 */ + MF_EXCEPTION = 16, /* F */ + AC_EXCEPTION = 17, /* F, Err(0) */ + MC_EXCEPTION = 18, /* A, Err(?) */ + XF_EXCEPTION = 19, /* F */ + EXCEPTION_NUM +}; + +enum { + INTR_TYPE_SOFTINTR = -1, /* software interrupt (INTn) */ + INTR_TYPE_EXTINTR = 0, /* external interrupt */ + INTR_TYPE_EXCEPTION = 1, /* exception */ +}; + +#define EXCEPTION(num, vec) \ + exception(num, vec); +#define INTERRUPT(num, softintp) \ + interrupt(num, softintp, 0, 0) + +void CPUCALL exception(int num, int vec); +void CPUCALL interrupt(int num, int intrtype, int errorp, int error_code); + +#ifdef __cplusplus +} +#endif + +#endif /* !IA32_CPU_EXCEPTION_H__ */ diff --git a/i386c/ia32/groups.c b/i386c/ia32/groups.c old mode 100755 new mode 100644 index 84dd6ee3..b307d7e4 --- a/i386c/ia32/groups.c +++ b/i386c/ia32/groups.c @@ -1,488 +1,488 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" -#include "ia32.mcr" -#include "groups.h" -#include "inst_table.h" - -#if defined(USE_SSE3) -#include "ia32/instructions/sse3/sse3.h" -#endif - -/* group 1 */ -void -Grp1_EbIb(void) -{ - UINT8 *out; - UINT32 madr; - UINT32 op, src; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = reg8_b20[op]; - GET_PCBYTE(src); - (*insttable_G1EbIb[idx])(out, src); - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - GET_PCBYTE(src); - (*insttable_G1EbIb_ext[idx])(madr, src); - } -} - -void -Grp1_EwIb(void) -{ - UINT16 *out; - UINT32 madr, src; - UINT32 op; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG16_B20(op); - GET_PCBYTES(src); - (*insttable_G1EwIx[idx])(out, src); - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - GET_PCBYTES(src); - (*insttable_G1EwIx_ext[idx])(madr, src); - } -} - -void -Grp1_EdIb(void) -{ - UINT32 *out; - UINT32 madr, src; - UINT32 op; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG32_B20(op); - GET_PCBYTESD(src); - (*insttable_G1EdIx[idx])(out, src); - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - GET_PCBYTESD(src); - (*insttable_G1EdIx_ext[idx])(madr, src); - } -} - -void -Grp1_EwIw(void) -{ - UINT16 *out; - UINT32 madr, src; - UINT32 op; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG16_B20(op); - GET_PCWORD(src); - (*insttable_G1EwIx[idx])(out, src); - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - GET_PCWORD(src); - (*insttable_G1EwIx_ext[idx])(madr, src); - } -} - -void -Grp1_EdId(void) -{ - UINT32 *out; - UINT32 madr, src; - UINT32 op; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG32_B20(op); - GET_PCDWORD(src); - (*insttable_G1EdIx[idx])(out, src); - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - GET_PCDWORD(src); - (*insttable_G1EdIx_ext[idx])(madr, src); - } -} - - -/* group 2 */ -void -Grp2_EbIb(void) -{ - UINT8 *out; - UINT32 madr; - UINT32 op; - UINT32 cl; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - out = reg8_b20[op]; - GET_PCBYTE(cl); - CPU_WORKCLOCK(cl & 0x1f); - (*insttable_G2EbCL[idx])(out, cl); - } else { - CPU_WORKCLOCK(8); - madr = calc_ea_dst(op); - GET_PCBYTE(cl); - CPU_WORKCLOCK(cl & 0x1f); - (*insttable_G2EbCL_ext[idx])(madr, cl); - } -} - -void -Grp2_EwIb(void) -{ - UINT16 *out; - UINT32 madr; - UINT32 op; - UINT32 cl; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - out = CPU_REG16_B20(op); - GET_PCBYTE(cl); - CPU_WORKCLOCK(cl & 0x1f); - (*insttable_G2EwCL[idx])(out, cl); - } else { - CPU_WORKCLOCK(8); - madr = calc_ea_dst(op); - GET_PCBYTE(cl); - CPU_WORKCLOCK(cl & 0x1f); - (*insttable_G2EwCL_ext[idx])(madr, cl); - } -} - -void -Grp2_EdIb(void) -{ - UINT32 *out; - UINT32 madr; - UINT32 op; - UINT32 cl; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - out = CPU_REG32_B20(op); - GET_PCBYTE(cl); - CPU_WORKCLOCK(cl & 0x1f); - (*insttable_G2EdCL[idx])(out, cl); - } else { - CPU_WORKCLOCK(8); - madr = calc_ea_dst(op); - GET_PCBYTE(cl); - CPU_WORKCLOCK(cl & 0x1f); - (*insttable_G2EdCL_ext[idx])(madr, cl); - } -} - -void -Grp2_Eb(void) -{ - UINT32 op; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - (*insttable_G2Eb[idx])(reg8_b20[op]); - } else { - CPU_WORKCLOCK(7); - (*insttable_G2Eb_ext[idx])(calc_ea_dst(op)); - } -} - -void -Grp2_Ew(void) -{ - UINT32 op; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - (*insttable_G2Ew[idx])(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(7); - (*insttable_G2Ew_ext[idx])(calc_ea_dst(op)); - } -} - -void -Grp2_Ed(void) -{ - UINT32 op; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - (*insttable_G2Ed[idx])(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(7); - (*insttable_G2Ed_ext[idx])(calc_ea_dst(op)); - } -} - -void -Grp2_EbCL(void) -{ - UINT8 *out; - UINT32 madr; - UINT32 op; - UINT32 cl; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - out = reg8_b20[op]; - cl = CPU_CL; - cl &= 0x1f; - CPU_WORKCLOCK(cl); - (*insttable_G2EbCL[idx])(out, cl); - } else { - CPU_WORKCLOCK(8); - madr = calc_ea_dst(op); - cl = CPU_CL; - cl &= 0x1f; - CPU_WORKCLOCK(cl); - (*insttable_G2EbCL_ext[idx])(madr, cl); - } -} - -void -Grp2_EwCL(void) -{ - UINT16 *out; - UINT32 madr; - UINT32 op; - UINT32 cl; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - out = CPU_REG16_B20(op); - cl = CPU_CL; - cl &= 0x1f; - CPU_WORKCLOCK(cl); - (*insttable_G2EwCL[idx])(out, cl); - } else { - CPU_WORKCLOCK(8); - madr = calc_ea_dst(op); - cl = CPU_CL; - cl &= 0x1f; - CPU_WORKCLOCK(cl); - (*insttable_G2EwCL_ext[idx])(madr, cl); - } -} - -void -Grp2_EdCL(void) -{ - UINT32 *out; - UINT32 madr; - UINT32 op; - UINT32 cl; - int idx; - - GET_MODRM_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - out = CPU_REG32_B20(op); - cl = CPU_CL; - cl &= 0x1f; - CPU_WORKCLOCK(cl); - (*insttable_G2EdCL[idx])(out, cl); - } else { - CPU_WORKCLOCK(8); - madr = calc_ea_dst(op); - cl = CPU_CL; - cl &= 0x1f; - CPU_WORKCLOCK(cl); - (*insttable_G2EdCL_ext[idx])(madr, cl); - } -} - - -/* group 3 */ -void -Grp3_Eb(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); - (*insttable_G3Eb[(op >> 3) & 7])(op); -} - -void -Grp3_Ew(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); - (*insttable_G3Ew[(op >> 3) & 7])(op); -} - -void -Grp3_Ed(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); - (*insttable_G3Ed[(op >> 3) & 7])(op); -} - - -/* group 4 */ -void -Grp4(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); - (*insttable_G4[(op >> 3) & 7])(op); -} - - -/* group 5 */ -void -Grp5_Ew(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); - (*insttable_G5Ew[(op >> 3) & 7])(op); -} - -void -Grp5_Ed(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); - (*insttable_G5Ed[(op >> 3) & 7])(op); -} - - -/* group 6 */ -void -Grp6(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); - (*insttable_G6[(op >> 3) & 7])(op); -} - - -/* group 7 */ -void -Grp7(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); -#if defined(USE_SSE3) - if(op==0xC8){ - SSE3_MONITOR(); - return; - } - if(op==0xC9){ - SSE3_MWAIT(); - return; - } -#endif - (*insttable_G7[(op >> 3) & 7])(op); -} - - -/* group 8 */ -void -Grp8_EwIb(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); - (*insttable_G8EwIb[(op >> 3) & 7])(op); -} - -void -Grp8_EdIb(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); - (*insttable_G8EdIb[(op >> 3) & 7])(op); -} - - -/* group 9 */ -void -Grp9(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); - (*insttable_G9[(op >> 3) & 7])(op); -} +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" +#include "ia32.mcr" +#include "groups.h" +#include "inst_table.h" + +#if defined(USE_SSE3) +#include "ia32/instructions/sse3/sse3.h" +#endif + +/* group 1 */ +void +Grp1_EbIb(void) +{ + UINT8 *out; + UINT32 madr; + UINT32 op, src; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = reg8_b20[op]; + GET_PCBYTE(src); + (*insttable_G1EbIb[idx])(out, src); + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + GET_PCBYTE(src); + (*insttable_G1EbIb_ext[idx])(madr, src); + } +} + +void +Grp1_EwIb(void) +{ + UINT16 *out; + UINT32 madr, src; + UINT32 op; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG16_B20(op); + GET_PCBYTES(src); + (*insttable_G1EwIx[idx])(out, src); + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + GET_PCBYTES(src); + (*insttable_G1EwIx_ext[idx])(madr, src); + } +} + +void +Grp1_EdIb(void) +{ + UINT32 *out; + UINT32 madr, src; + UINT32 op; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG32_B20(op); + GET_PCBYTESD(src); + (*insttable_G1EdIx[idx])(out, src); + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + GET_PCBYTESD(src); + (*insttable_G1EdIx_ext[idx])(madr, src); + } +} + +void +Grp1_EwIw(void) +{ + UINT16 *out; + UINT32 madr, src; + UINT32 op; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG16_B20(op); + GET_PCWORD(src); + (*insttable_G1EwIx[idx])(out, src); + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + GET_PCWORD(src); + (*insttable_G1EwIx_ext[idx])(madr, src); + } +} + +void +Grp1_EdId(void) +{ + UINT32 *out; + UINT32 madr, src; + UINT32 op; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG32_B20(op); + GET_PCDWORD(src); + (*insttable_G1EdIx[idx])(out, src); + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + GET_PCDWORD(src); + (*insttable_G1EdIx_ext[idx])(madr, src); + } +} + + +/* group 2 */ +void +Grp2_EbIb(void) +{ + UINT8 *out; + UINT32 madr; + UINT32 op; + UINT32 cl; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + out = reg8_b20[op]; + GET_PCBYTE(cl); + CPU_WORKCLOCK(cl & 0x1f); + (*insttable_G2EbCL[idx])(out, cl); + } else { + CPU_WORKCLOCK(8); + madr = calc_ea_dst(op); + GET_PCBYTE(cl); + CPU_WORKCLOCK(cl & 0x1f); + (*insttable_G2EbCL_ext[idx])(madr, cl); + } +} + +void +Grp2_EwIb(void) +{ + UINT16 *out; + UINT32 madr; + UINT32 op; + UINT32 cl; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + out = CPU_REG16_B20(op); + GET_PCBYTE(cl); + CPU_WORKCLOCK(cl & 0x1f); + (*insttable_G2EwCL[idx])(out, cl); + } else { + CPU_WORKCLOCK(8); + madr = calc_ea_dst(op); + GET_PCBYTE(cl); + CPU_WORKCLOCK(cl & 0x1f); + (*insttable_G2EwCL_ext[idx])(madr, cl); + } +} + +void +Grp2_EdIb(void) +{ + UINT32 *out; + UINT32 madr; + UINT32 op; + UINT32 cl; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + out = CPU_REG32_B20(op); + GET_PCBYTE(cl); + CPU_WORKCLOCK(cl & 0x1f); + (*insttable_G2EdCL[idx])(out, cl); + } else { + CPU_WORKCLOCK(8); + madr = calc_ea_dst(op); + GET_PCBYTE(cl); + CPU_WORKCLOCK(cl & 0x1f); + (*insttable_G2EdCL_ext[idx])(madr, cl); + } +} + +void +Grp2_Eb(void) +{ + UINT32 op; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + (*insttable_G2Eb[idx])(reg8_b20[op]); + } else { + CPU_WORKCLOCK(7); + (*insttable_G2Eb_ext[idx])(calc_ea_dst(op)); + } +} + +void +Grp2_Ew(void) +{ + UINT32 op; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + (*insttable_G2Ew[idx])(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(7); + (*insttable_G2Ew_ext[idx])(calc_ea_dst(op)); + } +} + +void +Grp2_Ed(void) +{ + UINT32 op; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + (*insttable_G2Ed[idx])(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(7); + (*insttable_G2Ed_ext[idx])(calc_ea_dst(op)); + } +} + +void +Grp2_EbCL(void) +{ + UINT8 *out; + UINT32 madr; + UINT32 op; + UINT32 cl; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + out = reg8_b20[op]; + cl = CPU_CL; + cl &= 0x1f; + CPU_WORKCLOCK(cl); + (*insttable_G2EbCL[idx])(out, cl); + } else { + CPU_WORKCLOCK(8); + madr = calc_ea_dst(op); + cl = CPU_CL; + cl &= 0x1f; + CPU_WORKCLOCK(cl); + (*insttable_G2EbCL_ext[idx])(madr, cl); + } +} + +void +Grp2_EwCL(void) +{ + UINT16 *out; + UINT32 madr; + UINT32 op; + UINT32 cl; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + out = CPU_REG16_B20(op); + cl = CPU_CL; + cl &= 0x1f; + CPU_WORKCLOCK(cl); + (*insttable_G2EwCL[idx])(out, cl); + } else { + CPU_WORKCLOCK(8); + madr = calc_ea_dst(op); + cl = CPU_CL; + cl &= 0x1f; + CPU_WORKCLOCK(cl); + (*insttable_G2EwCL_ext[idx])(madr, cl); + } +} + +void +Grp2_EdCL(void) +{ + UINT32 *out; + UINT32 madr; + UINT32 op; + UINT32 cl; + int idx; + + GET_MODRM_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + out = CPU_REG32_B20(op); + cl = CPU_CL; + cl &= 0x1f; + CPU_WORKCLOCK(cl); + (*insttable_G2EdCL[idx])(out, cl); + } else { + CPU_WORKCLOCK(8); + madr = calc_ea_dst(op); + cl = CPU_CL; + cl &= 0x1f; + CPU_WORKCLOCK(cl); + (*insttable_G2EdCL_ext[idx])(madr, cl); + } +} + + +/* group 3 */ +void +Grp3_Eb(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); + (*insttable_G3Eb[(op >> 3) & 7])(op); +} + +void +Grp3_Ew(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); + (*insttable_G3Ew[(op >> 3) & 7])(op); +} + +void +Grp3_Ed(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); + (*insttable_G3Ed[(op >> 3) & 7])(op); +} + + +/* group 4 */ +void +Grp4(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); + (*insttable_G4[(op >> 3) & 7])(op); +} + + +/* group 5 */ +void +Grp5_Ew(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); + (*insttable_G5Ew[(op >> 3) & 7])(op); +} + +void +Grp5_Ed(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); + (*insttable_G5Ed[(op >> 3) & 7])(op); +} + + +/* group 6 */ +void +Grp6(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); + (*insttable_G6[(op >> 3) & 7])(op); +} + + +/* group 7 */ +void +Grp7(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); +#if defined(USE_SSE3) + if(op==0xC8){ + SSE3_MONITOR(); + return; + } + if(op==0xC9){ + SSE3_MWAIT(); + return; + } +#endif + (*insttable_G7[(op >> 3) & 7])(op); +} + + +/* group 8 */ +void +Grp8_EwIb(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); + (*insttable_G8EwIb[(op >> 3) & 7])(op); +} + +void +Grp8_EdIb(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); + (*insttable_G8EdIb[(op >> 3) & 7])(op); +} + + +/* group 9 */ +void +Grp9(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); + (*insttable_G9[(op >> 3) & 7])(op); +} diff --git a/i386c/ia32/groups.h b/i386c/ia32/groups.h old mode 100755 new mode 100644 index 4e25c9fe..929239e2 --- a/i386c/ia32/groups.h +++ b/i386c/ia32/groups.h @@ -1,80 +1,80 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_GROUPS_H__ -#define IA32_CPU_GROUPS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* group 1 */ -void Grp1_EbIb(void); -void Grp1_EwIb(void); -void Grp1_EdIb(void); -void Grp1_EwIw(void); -void Grp1_EdId(void); - -/* group 2 */ -void Grp2_Eb(void); -void Grp2_Ew(void); -void Grp2_Ed(void); -void Grp2_EbCL(void); -void Grp2_EwCL(void); -void Grp2_EdCL(void); -void Grp2_EbIb(void); -void Grp2_EwIb(void); -void Grp2_EdIb(void); - -/* group 3 */ -void Grp3_Eb(void); -void Grp3_Ew(void); -void Grp3_Ed(void); - -/* group 4 */ -void Grp4(void); - -/* group 5 */ -void Grp5_Ew(void); -void Grp5_Ed(void); - -/* group 6 */ -void Grp6(void); - -/* group 7 */ -void Grp7(void); - -/* group 8 */ -void Grp8_EwIb(void); -void Grp8_EdIb(void); - -/* group 9 */ -void Grp9(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_GROUPS_H__ */ +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_GROUPS_H__ +#define IA32_CPU_GROUPS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* group 1 */ +void Grp1_EbIb(void); +void Grp1_EwIb(void); +void Grp1_EdIb(void); +void Grp1_EwIw(void); +void Grp1_EdId(void); + +/* group 2 */ +void Grp2_Eb(void); +void Grp2_Ew(void); +void Grp2_Ed(void); +void Grp2_EbCL(void); +void Grp2_EwCL(void); +void Grp2_EdCL(void); +void Grp2_EbIb(void); +void Grp2_EwIb(void); +void Grp2_EdIb(void); + +/* group 3 */ +void Grp3_Eb(void); +void Grp3_Ew(void); +void Grp3_Ed(void); + +/* group 4 */ +void Grp4(void); + +/* group 5 */ +void Grp5_Ew(void); +void Grp5_Ed(void); + +/* group 6 */ +void Grp6(void); + +/* group 7 */ +void Grp7(void); + +/* group 8 */ +void Grp8_EwIb(void); +void Grp8_EdIb(void); + +/* group 9 */ +void Grp9(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_GROUPS_H__ */ diff --git a/i386c/ia32/ia32.c b/i386c/ia32/ia32.c old mode 100755 new mode 100644 index a65d66b1..1278a3c4 --- a/i386c/ia32/ia32.c +++ b/i386c/ia32/ia32.c @@ -1,335 +1,335 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" -#include "ia32.mcr" - -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif - -#if defined(USE_CPU_EIPMASK) -UINT32 cpu_eipMask; -#endif -I386CORE i386core; -#if defined(USE_CPU_MODRMPREFETCH) -UINT32 opCache; -#endif -UINT8 *reg8_b20[0x100]; -UINT8 *reg8_b53[0x100]; -#if !defined(USE_CPU_DIRECTREG) -UINT16 *reg16_b20[0x100]; -UINT16 *reg16_b53[0x100]; -UINT32 *reg32_b20[0x100]; -UINT32 *reg32_b53[0x100]; -#endif -I386CPUID i386cpuid = {I386CPUID_VERSION, CPU_VENDOR, CPU_FAMILY, CPU_MODEL, CPU_STEPPING, CPU_FEATURES, CPU_FEATURES_EX, CPU_BRAND_STRING, CPU_BRAND_ID, CPU_FEATURES_ECX, CPU_EFLAGS_MASK}; -I386MSR i386msr = {0}; - - -void -ia32_init(void) -{ - int i; - - i386msr.version = I386MSR_VERSION; - i386cpuid.version = I386CPUID_VERSION; - - memset(&i386core.s, 0, sizeof(i386core.s)); - ia32_initreg(); - memset(&i386msr.regs, 0, sizeof(i386msr.regs)); - - for (i = 0; i < 0x100; ++i) { - /* 8bit */ - if (i & 0x20) { - /* h */ - reg8_b53[i] = &CPU_REGS_BYTEH((i >> 3) & 3); - } else { - /* l */ - reg8_b53[i] = &CPU_REGS_BYTEL((i >> 3) & 3); - } - - if (i & 0x04) { - /* h */ - reg8_b20[i] = &CPU_REGS_BYTEH(i & 3); - } else { - /* l */ - reg8_b20[i] = &CPU_REGS_BYTEL(i & 3); - } - -#if !defined(USE_CPU_DIRECTREG) - /* 16bit */ - reg16_b53[i] = &CPU_REGS_WORD((i >> 3) & 7); - reg16_b20[i] = &CPU_REGS_WORD(i & 7); - - /* 32bit */ - reg32_b53[i] = &CPU_REGS_DWORD((i >> 3) & 7); - reg32_b20[i] = &CPU_REGS_DWORD(i & 7); -#endif - } - - resolve_init(); -} - -void -ia32_setextsize(UINT32 size) -{ -//#if defined(SUPPORT_LARGE_MEMORY)&&defined(_WIN32) && !defined(MEMTRACE) && !defined(MEMCHECK) -// static int vallocflag = 0; -// static int vallocsize = 0; -// static LPVOID memblock = NULL; -//#endif - - if (CPU_EXTMEMSIZE != size) { - UINT8 *extmem; - extmem = CPU_EXTMEM; - if (extmem != NULL) { -//#if defined(SUPPORT_LARGE_MEMORY) && defined(_WIN32) && !defined(MEMTRACE) && !defined(MEMCHECK) -// if(vallocflag){ -// VirtualFree((LPVOID)extmem, vallocsize, MEM_DECOMMIT); -// VirtualFree(memblock, 0, MEM_RELEASE); -// vallocflag = 0; -// }else -//#endif - { -#if defined(SUPPORT_IA32_HAXM) -#if defined(NP2_WIN) - _aligned_free(extmem); -#else - free(extmem); -#endif -#else - _MFREE(extmem); -#endif - } - extmem = NULL; - } - if (size != 0) { -//#if defined(SUPPORT_LARGE_MEMORY) && defined(_WIN32) && !defined(MEMTRACE) && !defined(MEMCHECK) -// if(size > (255 << 20)){ -// HANDLE hp = OpenProcess(PROCESS_ALL_ACCESS, TRUE, GetCurrentProcessId()); -// vallocsize = size + 16; -// SetProcessWorkingSetSize(hp, vallocsize + 50*1024*1024, vallocsize + 50*1024*1024); -// CloseHandle(hp); -// memblock = VirtualAlloc(NULL, vallocsize, MEM_RESERVE, PAGE_READWRITE); -// extmem = (UINT8 *)VirtualAlloc(memblock, vallocsize, MEM_COMMIT, PAGE_READWRITE); -// if(!extmem){ -// extmem = (UINT8 *)_MALLOC(size + 16, "EXTMEM"); -// }else{ -// vallocflag = 1; -// } -// }else -//#endif - { -#if defined(SUPPORT_IA32_HAXM) -#if defined(NP2_WIN) - extmem = (UINT8*)_aligned_malloc(size + 4096, 4096); -#else - posix_memalign(&extmem, 4096, size + 4096); -#endif -#else - extmem = (UINT8 *)_MALLOC(size + 16, "EXTMEM"); -#endif - } - } - if (extmem != NULL) { - ZeroMemory(extmem, size + 16); - CPU_EXTMEM = extmem; - CPU_EXTMEMSIZE = size; - CPU_EXTMEMBASE = CPU_EXTMEM - 0x100000; - CPU_EXTLIMIT16 = MIN(size + 0x100000, 0xf00000); - CPU_EXTLIMIT = size + 0x100000; - } - else { -#if defined(SUPPORT_LARGE_MEMORY) - if(size != 0){ - msgbox("Error", "Cannot allocate extended memory."); - } -#endif - CPU_EXTMEM = NULL; - CPU_EXTMEMSIZE = 0; - CPU_EXTMEMBASE = NULL; - CPU_EXTLIMIT16 = 0; - CPU_EXTLIMIT = 0; - } - } - CPU_EMSPTR[0] = mem + 0xc0000; - CPU_EMSPTR[1] = mem + 0xc4000; - CPU_EMSPTR[2] = mem + 0xc8000; - CPU_EMSPTR[3] = mem + 0xcc000; -} - -void -ia32_setemm(UINT frame, UINT32 addr) { - - UINT8 *ptr; - - frame &= 3; - if (addr < USE_HIMEM) { - ptr = mem + addr; - } - else if ((addr - 0x100000 + 0x4000) <= CPU_EXTMEMSIZE) { - ptr = CPU_EXTMEM + (addr - 0x100000); - } - else { - ptr = mem + 0xc0000 + (frame << 14); - } - CPU_EMSPTR[frame] = ptr; -} - - -/* - * モード遷移 - */ -void CPUCALL -change_pm(BOOL onoff) -{ - - if (onoff) { - VERBOSE(("change_pm: Entering to Protected-Mode...")); - } else { - VERBOSE(("change_pm: Leaveing from Protected-Mode...")); - } - - CPU_INST_OP32 = CPU_INST_AS32 = - CPU_STATSAVE.cpu_inst_default.op_32 = - CPU_STATSAVE.cpu_inst_default.as_32 = 0; -#if defined(USE_CPU_EIPMASK) - CPU_EIPMASK = 0xffff; -#endif - CPU_STAT_SS32 = 0; - set_cpl(0); - CPU_STAT_PM = onoff; -} - -void CPUCALL -change_pg(BOOL onoff) -{ - - if (onoff) { - VERBOSE(("change_pg: Entering to Paging-Mode...")); - } else { - VERBOSE(("change_pg: Leaveing from Paging-Mode...")); - } - - CPU_STAT_PAGING = onoff; -} - -void CPUCALL -change_vm(BOOL onoff) -{ - int i; - - CPU_STAT_VM86 = onoff; - if (onoff) { - VERBOSE(("change_vm: Entering to Virtual-8086-Mode...")); - for (i = 0; i < CPU_SEGREG_NUM; i++) { - LOAD_SEGREG(i, CPU_REGS_SREG(i)); - } - CPU_INST_OP32 = CPU_INST_AS32 = - CPU_STATSAVE.cpu_inst_default.op_32 = - CPU_STATSAVE.cpu_inst_default.as_32 = 0; -#if defined(USE_CPU_EIPMASK) - CPU_EIPMASK = 0xffff; -#endif - CPU_STAT_SS32 = 0; - set_cpl(3); - } else { - VERBOSE(("change_vm: Leaveing from Virtual-8086-Mode...")); - } -} - -/* - * flags - */ -static void CPUCALL -modify_eflags(UINT32 new_flags, UINT32 mask) -{ - UINT32 orig = CPU_EFLAG; - - new_flags &= ALL_EFLAG; - mask &= ALL_EFLAG; - CPU_EFLAG = (REAL_EFLAGREG & ~mask) | (new_flags & mask); - - CPU_OV = CPU_FLAG & O_FLAG; - CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG); - if (CPU_STAT_PM) { - if ((orig ^ CPU_EFLAG) & VM_FLAG) { - if (CPU_EFLAG & VM_FLAG) { - change_vm(1); - } else { - change_vm(0); - } - } - } -} - -void CPUCALL -set_flags(UINT16 new_flags, UINT16 mask) -{ - - mask &= I_FLAG|IOPL_FLAG; - mask |= SZAPC_FLAG|T_FLAG|D_FLAG|O_FLAG|NT_FLAG; - modify_eflags(new_flags, mask); -} - -void CPUCALL -set_eflags(UINT32 new_flags, UINT32 mask) -{ - - mask &= I_FLAG|IOPL_FLAG|RF_FLAG|VM_FLAG|VIF_FLAG|VIP_FLAG; - mask |= SZAPC_FLAG|T_FLAG|D_FLAG|O_FLAG|NT_FLAG; - mask |= AC_FLAG|ID_FLAG; - mask &= ~i386cpuid.cpu_eflags_mask; - modify_eflags(new_flags, mask); -} - -/* - * CR3 (Page Directory Entry base physical address) - */ -void CPUCALL -set_cr3(UINT32 new_cr3) -{ - - VERBOSE(("set_CR3: old = %08x, new = 0x%08x", CPU_CR3, new_cr3)); - - CPU_CR3 = new_cr3 & CPU_CR3_MASK; - CPU_STAT_PDE_BASE = CPU_CR3 & CPU_CR3_PD_MASK; - tlb_flush(); -} - -/* - * CPL (Current Privilege Level) - */ -void CPUCALL -set_cpl(int new_cpl) -{ - int cpl = new_cpl & 3; - - CPU_STAT_CPL = (UINT8)cpl; - CPU_STAT_USER_MODE = (cpl == 3) ? CPU_MODE_USER : CPU_MODE_SUPERVISER; -} +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" +#include "ia32.mcr" + +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif + +#if defined(USE_CPU_EIPMASK) +UINT32 cpu_eipMask; +#endif +I386CORE i386core; +#if defined(USE_CPU_MODRMPREFETCH) +UINT32 opCache; +#endif +UINT8 *reg8_b20[0x100]; +UINT8 *reg8_b53[0x100]; +#if !defined(USE_CPU_DIRECTREG) +UINT16 *reg16_b20[0x100]; +UINT16 *reg16_b53[0x100]; +UINT32 *reg32_b20[0x100]; +UINT32 *reg32_b53[0x100]; +#endif +I386CPUID i386cpuid = {I386CPUID_VERSION, CPU_VENDOR, CPU_FAMILY, CPU_MODEL, CPU_STEPPING, CPU_FEATURES, CPU_FEATURES_EX, CPU_BRAND_STRING, CPU_BRAND_ID, CPU_FEATURES_ECX, CPU_EFLAGS_MASK}; +I386MSR i386msr = {0}; + + +void +ia32_init(void) +{ + int i; + + i386msr.version = I386MSR_VERSION; + i386cpuid.version = I386CPUID_VERSION; + + memset(&i386core.s, 0, sizeof(i386core.s)); + ia32_initreg(); + memset(&i386msr.regs, 0, sizeof(i386msr.regs)); + + for (i = 0; i < 0x100; ++i) { + /* 8bit */ + if (i & 0x20) { + /* h */ + reg8_b53[i] = &CPU_REGS_BYTEH((i >> 3) & 3); + } else { + /* l */ + reg8_b53[i] = &CPU_REGS_BYTEL((i >> 3) & 3); + } + + if (i & 0x04) { + /* h */ + reg8_b20[i] = &CPU_REGS_BYTEH(i & 3); + } else { + /* l */ + reg8_b20[i] = &CPU_REGS_BYTEL(i & 3); + } + +#if !defined(USE_CPU_DIRECTREG) + /* 16bit */ + reg16_b53[i] = &CPU_REGS_WORD((i >> 3) & 7); + reg16_b20[i] = &CPU_REGS_WORD(i & 7); + + /* 32bit */ + reg32_b53[i] = &CPU_REGS_DWORD((i >> 3) & 7); + reg32_b20[i] = &CPU_REGS_DWORD(i & 7); +#endif + } + + resolve_init(); +} + +void +ia32_setextsize(UINT32 size) +{ +//#if defined(SUPPORT_LARGE_MEMORY)&&defined(_WIN32) && !defined(MEMTRACE) && !defined(MEMCHECK) +// static int vallocflag = 0; +// static int vallocsize = 0; +// static LPVOID memblock = NULL; +//#endif + + if (CPU_EXTMEMSIZE != size) { + UINT8 *extmem; + extmem = CPU_EXTMEM; + if (extmem != NULL) { +//#if defined(SUPPORT_LARGE_MEMORY) && defined(_WIN32) && !defined(MEMTRACE) && !defined(MEMCHECK) +// if(vallocflag){ +// VirtualFree((LPVOID)extmem, vallocsize, MEM_DECOMMIT); +// VirtualFree(memblock, 0, MEM_RELEASE); +// vallocflag = 0; +// }else +//#endif + { +#if defined(SUPPORT_IA32_HAXM) +#if defined(NP2_WIN) + _aligned_free(extmem); +#else + free(extmem); +#endif +#else + _MFREE(extmem); +#endif + } + extmem = NULL; + } + if (size != 0) { +//#if defined(SUPPORT_LARGE_MEMORY) && defined(_WIN32) && !defined(MEMTRACE) && !defined(MEMCHECK) +// if(size > (255 << 20)){ +// HANDLE hp = OpenProcess(PROCESS_ALL_ACCESS, TRUE, GetCurrentProcessId()); +// vallocsize = size + 16; +// SetProcessWorkingSetSize(hp, vallocsize + 50*1024*1024, vallocsize + 50*1024*1024); +// CloseHandle(hp); +// memblock = VirtualAlloc(NULL, vallocsize, MEM_RESERVE, PAGE_READWRITE); +// extmem = (UINT8 *)VirtualAlloc(memblock, vallocsize, MEM_COMMIT, PAGE_READWRITE); +// if(!extmem){ +// extmem = (UINT8 *)_MALLOC(size + 16, "EXTMEM"); +// }else{ +// vallocflag = 1; +// } +// }else +//#endif + { +#if defined(SUPPORT_IA32_HAXM) +#if defined(NP2_WIN) + extmem = (UINT8*)_aligned_malloc(size + 4096, 4096); +#else + posix_memalign(&extmem, 4096, size + 4096); +#endif +#else + extmem = (UINT8 *)_MALLOC(size + 16, "EXTMEM"); +#endif + } + } + if (extmem != NULL) { + ZeroMemory(extmem, size + 16); + CPU_EXTMEM = extmem; + CPU_EXTMEMSIZE = size; + CPU_EXTMEMBASE = CPU_EXTMEM - 0x100000; + CPU_EXTLIMIT16 = MIN(size + 0x100000, 0xf00000); + CPU_EXTLIMIT = size + 0x100000; + } + else { +#if defined(SUPPORT_LARGE_MEMORY) + if(size != 0){ + msgbox("Error", "Cannot allocate extended memory."); + } +#endif + CPU_EXTMEM = NULL; + CPU_EXTMEMSIZE = 0; + CPU_EXTMEMBASE = NULL; + CPU_EXTLIMIT16 = 0; + CPU_EXTLIMIT = 0; + } + } + CPU_EMSPTR[0] = mem + 0xc0000; + CPU_EMSPTR[1] = mem + 0xc4000; + CPU_EMSPTR[2] = mem + 0xc8000; + CPU_EMSPTR[3] = mem + 0xcc000; +} + +void +ia32_setemm(UINT frame, UINT32 addr) { + + UINT8 *ptr; + + frame &= 3; + if (addr < USE_HIMEM) { + ptr = mem + addr; + } + else if ((addr - 0x100000 + 0x4000) <= CPU_EXTMEMSIZE) { + ptr = CPU_EXTMEM + (addr - 0x100000); + } + else { + ptr = mem + 0xc0000 + (frame << 14); + } + CPU_EMSPTR[frame] = ptr; +} + + +/* + * モード遷移 + */ +void CPUCALL +change_pm(BOOL onoff) +{ + + if (onoff) { + VERBOSE(("change_pm: Entering to Protected-Mode...")); + } else { + VERBOSE(("change_pm: Leaveing from Protected-Mode...")); + } + + CPU_INST_OP32 = CPU_INST_AS32 = + CPU_STATSAVE.cpu_inst_default.op_32 = + CPU_STATSAVE.cpu_inst_default.as_32 = 0; +#if defined(USE_CPU_EIPMASK) + CPU_EIPMASK = 0xffff; +#endif + CPU_STAT_SS32 = 0; + set_cpl(0); + CPU_STAT_PM = onoff; +} + +void CPUCALL +change_pg(BOOL onoff) +{ + + if (onoff) { + VERBOSE(("change_pg: Entering to Paging-Mode...")); + } else { + VERBOSE(("change_pg: Leaveing from Paging-Mode...")); + } + + CPU_STAT_PAGING = onoff; +} + +void CPUCALL +change_vm(BOOL onoff) +{ + int i; + + CPU_STAT_VM86 = onoff; + if (onoff) { + VERBOSE(("change_vm: Entering to Virtual-8086-Mode...")); + for (i = 0; i < CPU_SEGREG_NUM; i++) { + LOAD_SEGREG(i, CPU_REGS_SREG(i)); + } + CPU_INST_OP32 = CPU_INST_AS32 = + CPU_STATSAVE.cpu_inst_default.op_32 = + CPU_STATSAVE.cpu_inst_default.as_32 = 0; +#if defined(USE_CPU_EIPMASK) + CPU_EIPMASK = 0xffff; +#endif + CPU_STAT_SS32 = 0; + set_cpl(3); + } else { + VERBOSE(("change_vm: Leaveing from Virtual-8086-Mode...")); + } +} + +/* + * flags + */ +static void CPUCALL +modify_eflags(UINT32 new_flags, UINT32 mask) +{ + UINT32 orig = CPU_EFLAG; + + new_flags &= ALL_EFLAG; + mask &= ALL_EFLAG; + CPU_EFLAG = (REAL_EFLAGREG & ~mask) | (new_flags & mask); + + CPU_OV = CPU_FLAG & O_FLAG; + CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG); + if (CPU_STAT_PM) { + if ((orig ^ CPU_EFLAG) & VM_FLAG) { + if (CPU_EFLAG & VM_FLAG) { + change_vm(1); + } else { + change_vm(0); + } + } + } +} + +void CPUCALL +set_flags(UINT16 new_flags, UINT16 mask) +{ + + mask &= I_FLAG|IOPL_FLAG; + mask |= SZAPC_FLAG|T_FLAG|D_FLAG|O_FLAG|NT_FLAG; + modify_eflags(new_flags, mask); +} + +void CPUCALL +set_eflags(UINT32 new_flags, UINT32 mask) +{ + + mask &= I_FLAG|IOPL_FLAG|RF_FLAG|VM_FLAG|VIF_FLAG|VIP_FLAG; + mask |= SZAPC_FLAG|T_FLAG|D_FLAG|O_FLAG|NT_FLAG; + mask |= AC_FLAG|ID_FLAG; + mask &= ~i386cpuid.cpu_eflags_mask; + modify_eflags(new_flags, mask); +} + +/* + * CR3 (Page Directory Entry base physical address) + */ +void CPUCALL +set_cr3(UINT32 new_cr3) +{ + + VERBOSE(("set_CR3: old = %08x, new = 0x%08x", CPU_CR3, new_cr3)); + + CPU_CR3 = new_cr3 & CPU_CR3_MASK; + CPU_STAT_PDE_BASE = CPU_CR3 & CPU_CR3_PD_MASK; + tlb_flush(); +} + +/* + * CPL (Current Privilege Level) + */ +void CPUCALL +set_cpl(int new_cpl) +{ + int cpl = new_cpl & 3; + + CPU_STAT_CPL = (UINT8)cpl; + CPU_STAT_USER_MODE = (cpl == 3) ? CPU_MODE_USER : CPU_MODE_SUPERVISER; +} diff --git a/i386c/ia32/ia32.mcr b/i386c/ia32/ia32.mcr old mode 100755 new mode 100644 index 5540dedc..6c1bce07 --- a/i386c/ia32/ia32.mcr +++ b/i386c/ia32/ia32.mcr @@ -1,983 +1,983 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_IA32_MCR__ -#define IA32_CPU_IA32_MCR__ - -/* - * misc - */ -#define __CBW(src) ((UINT16)((SINT8)(src))) -#define __CBD(src) ((UINT32)((SINT8)(src))) -#define __CWDE(src) ((SINT16)(src)) - -#ifndef PTR_TO_UINT32 -#define PTR_TO_UINT32(p) ((UINT32)((unsigned long)(p))) -#endif -#ifndef UINT32_TO_PTR -#define UINT32_TO_PTR(v) ((void *)((unsigned long)(UINT32)(v))) -#endif - -#define SWAP_BYTE(p, q) \ -do { \ - UINT8 __tmp = (p); \ - (p) = (q); \ - (q) = __tmp; \ -} while (/*CONSTCOND*/ 0) - -#define SWAP_WORD(p, q) \ -do { \ - UINT16 __tmp = (p); \ - (p) = (q); \ - (q) = __tmp; \ -} while (/*CONSTCOND*/ 0) - -#define SWAP_DWORD(p, q) \ -do { \ - UINT32 __tmp = (p); \ - (p) = (q); \ - (q) = __tmp; \ -} while (/*CONSTCOND*/ 0) - - -/* - * clock - */ -#define CPU_WORKCLOCK(clock) \ -do { \ - CPU_REMCLOCK -= (clock); \ -} while (/*CONSTCOND*/ 0) - -#define CPU_HALT() \ -do { \ - CPU_REMCLOCK = -1; \ -} while (/*CONSTCOND*/ 0) - -#define IRQCHECKTERM() \ -do { \ - if (CPU_REMCLOCK > 0) { \ - CPU_BASECLOCK -= CPU_REMCLOCK; \ - CPU_REMCLOCK = 0; \ - } \ -} while (/*CONSTCOND*/ 0) - - -/* - * instruction pointer - */ -/* コードフェッチに使用するので、OpSize の影響を受けてはいけない */ -#if defined(USE_CPU_MODRMPREFETCH) -#define _CLEAR_MODRMCACHE() \ -do { \ - opCache = 0; \ -} while (/*CONSTCOND*/ 0) -#else -#define _CLEAR_MODRMCACHE() (void)0 -#endif - -#if defined(USE_CPU_EIPMASK) -#define _ADD_EIP(v) \ -do { \ - CPU_EIP = (CPU_EIP + (v)) & CPU_EIPMASK; \ - _CLEAR_MODRMCACHE(); \ -} while (/*CONSTCOND*/ 0) -#else -#define _ADD_EIP(v) \ -do { \ - UINT32 __tmp_ip = CPU_EIP + (v); \ - if (!CPU_STATSAVE.cpu_inst_default.op_32) { \ - __tmp_ip &= 0xffff; \ - } \ - CPU_EIP = __tmp_ip; \ - _CLEAR_MODRMCACHE(); \ -} while (/*CONSTCOND*/ 0) -#endif - -#define GET_PCBYTE(v) \ -do { \ - (v) = cpu_codefetch(CPU_EIP); \ - _ADD_EIP(1); \ -} while (/*CONSTCOND*/ 0) - -#if defined(USE_CPU_MODRMPREFETCH) -#define GET_MODRM_PCBYTE(v) \ -do { \ - if (opCache) { \ - (v) = opCache >> 8; \ - } else { \ - (v) = cpu_codefetch(CPU_EIP); \ - } \ - _ADD_EIP(1); \ -} while (/*CONSTCOND*/ 0) -#else -#define GET_MODRM_PCBYTE(v) GET_PCBYTE(v) -#endif - -#define GET_PCBYTES(v) \ -do { \ - (v) = __CBW(cpu_codefetch(CPU_EIP)); \ - _ADD_EIP(1); \ -} while (/*CONSTCOND*/ 0) - -#define GET_PCBYTESD(v) \ -do { \ - (v) = __CBD(cpu_codefetch(CPU_EIP)); \ - _ADD_EIP(1); \ -} while (/*CONSTCOND*/ 0) - -#define GET_PCWORD(v) \ -do { \ - (v) = cpu_codefetch_w(CPU_EIP); \ - _ADD_EIP(2); \ -} while (/*CONSTCOND*/ 0) - -#define GET_PCWORDS(v) \ -do { \ - (v) = __CWDE(cpu_codefetch_w(CPU_EIP)); \ - _ADD_EIP(2); \ -} while (/*CONSTCOND*/ 0) - -#define GET_PCDWORD(v) \ -do { \ - (v) = cpu_codefetch_d(CPU_EIP); \ - _ADD_EIP(4); \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_EA_REG8(b, d_s) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - (d_s) = *(reg8_b53[(b)]); \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_EA_REG8P(b, d_s) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - (d_s) = reg8_b53[(b)]; \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_EA_REG16(b, d_s) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - (d_s) = CPU_REG16_B53_V(b); \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_EA_REG16P(b, d_s) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - (d_s) = CPU_REG16_B53((b)); \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_EA_REG32(b, d_s) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - (d_s) = CPU_REG32_B53_V(b); \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_EA_REG32P(b, d_s) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - (d_s) = CPU_REG32_B53((b)); \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_REG8_EA(b, s, d, regclk, memclk) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - if ((b) >= 0xc0) { \ - CPU_WORKCLOCK(regclk); \ - (s) = *(reg8_b20[(b)]); \ - } else { \ - UINT32 __t; \ - CPU_WORKCLOCK(memclk); \ - __t = calc_ea_dst((b)); \ - (s) = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, __t); \ - } \ - (d) = reg8_b53[(b)]; \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_REG16_EA(b, s, d, regclk, memclk) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - if ((b) >= 0xc0) { \ - CPU_WORKCLOCK(regclk); \ - (s) = CPU_REG16_B20_V(b); \ - } else { \ - UINT32 __t; \ - CPU_WORKCLOCK(memclk); \ - __t = calc_ea_dst((b)); \ - (s) = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, __t); \ - } \ - (d) = CPU_REG16_B53((b)); \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_REG16_EA8(b, s, d, regclk, memclk) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - if ((b) >= 0xc0) { \ - CPU_WORKCLOCK(regclk); \ - (s) = *(reg8_b20[(b)]); \ - } else { \ - UINT32 __t; \ - CPU_WORKCLOCK(memclk); \ - __t = calc_ea_dst((b)); \ - (s) = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, __t); \ - } \ - (d) = CPU_REG16_B53((b)); \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_REG32_EA(b, s, d, regclk, memclk) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - if ((b) >= 0xc0) { \ - CPU_WORKCLOCK(regclk); \ - (s) = CPU_REG32_B20_V(b); \ - } else { \ - UINT32 __t; \ - CPU_WORKCLOCK(memclk); \ - __t = calc_ea_dst((b)); \ - (s) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, __t); \ - } \ - (d) = CPU_REG32_B53((b)); \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_REG32_EA8(b, s, d, regclk, memclk) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - if ((b) >= 0xc0) { \ - CPU_WORKCLOCK(regclk); \ - (s) = *(reg8_b20[(b)]); \ - } else { \ - UINT32 __t; \ - CPU_WORKCLOCK(memclk); \ - __t = calc_ea_dst((b)); \ - (s) = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, __t); \ - } \ - (d) = CPU_REG32_B53((b)); \ -} while (/*CONSTCOND*/ 0) - -#define PREPART_REG32_EA16(b, s, d, regclk, memclk) \ -do { \ - GET_MODRM_PCBYTE((b)); \ - if ((b) >= 0xc0) { \ - CPU_WORKCLOCK(regclk); \ - (s) = CPU_REG16_B20_V(b); \ - } else { \ - UINT32 __t; \ - CPU_WORKCLOCK(memclk); \ - __t = calc_ea_dst((b)); \ - (s) = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, __t); \ - } \ - (d) = CPU_REG32_B53((b)); \ -} while (/*CONSTCOND*/ 0) - - -/* - * arith - */ -#define _ADD_BYTE(r, d, s) \ -do { \ - (r) = (s) + (d); \ - CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - CPU_FLAGL |= szpcflag[(r) & 0x1ff]; \ -} while (/*CONSTCOND*/ 0) - -#define _ADD_WORD(r, d, s) \ -do { \ - (r) = (s) + (d); \ - CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x8000; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - if ((r) & 0xffff0000) { \ - (r) &= 0x0000ffff; \ - CPU_FLAGL |= C_FLAG; \ - } \ - CPU_FLAGL |= szpflag_w[(UINT16)(r)]; \ -} while (/*CONSTCOND*/ 0) - -#define _ADD_DWORD(r, d, s) \ -do { \ - (r) = (s) + (d); \ - CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80000000; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - if ((r) < (s)) { \ - CPU_FLAGL |= C_FLAG; \ - } \ - if ((r) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } \ - if ((r) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= szpcflag[(UINT8)(r)] & P_FLAG; \ -} while (/*CONSTCOND*/ 0) - -#define _OR_BYTE(d, s) \ -do { \ - (d) |= (s); \ - CPU_OV = 0; \ - CPU_FLAGL = szpcflag[(UINT8)(d)]; \ -} while (/*CONSTCOND*/ 0) - -#define _OR_WORD(d, s) \ -do { \ - (d) |= (s); \ - CPU_OV = 0; \ - CPU_FLAGL = szpflag_w[(UINT16)(d)]; \ -} while (/*CONSTCOND*/ 0) - -#define _OR_DWORD(d, s) \ -do { \ - (d) |= (s); \ - CPU_OV = 0; \ - CPU_FLAGL = (UINT8)(szpcflag[(UINT8)(d)] & P_FLAG); \ - if ((d) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } \ - if ((d) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -/* flag no check */ -#define _ADC_BYTE(r, d, s) \ -do { \ - (r) = (CPU_FLAGL & C_FLAG) + (s) + (d); \ - CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - CPU_FLAGL |= szpcflag[(r) & 0x1ff]; \ -} while (/*CONSTCOND*/ 0) - -#define _ADC_WORD(r, d, s) \ -do { \ - (r) = (CPU_FLAGL & C_FLAG) + (s) + (d); \ - CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x8000; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - if ((r) & 0xffff0000) { \ - (r) &= 0x0000ffff; \ - CPU_FLAGL |= C_FLAG; \ - } \ - CPU_FLAGL |= szpflag_w[(UINT16)(r)]; \ -} while (/*CONSTCOND*/ 0) - -#define _ADC_DWORD(r, d, s) \ -do { \ - UINT32 __c = (CPU_FLAGL & C_FLAG); \ - (r) = (s) + (d) + __c; \ - CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80000000; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - if ((!__c && (r) < (s)) || (__c && (r) <= (s))) { \ - CPU_FLAGL |= C_FLAG; \ - } \ - if ((r) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } \ - if ((r) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= szpcflag[(UINT8)(r)] & P_FLAG; \ -} while (/*CONSTCOND*/ 0) - -/* flag no check */ -#define _BYTE_SBB(r, d, s) \ -do { \ - (r) = (d) - (s) - (CPU_FLAGL & C_FLAG); \ - CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - CPU_FLAGL |= szpcflag[(r) & 0x1ff]; \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_SBB(r, d, s) \ -do { \ - (r) = (d) - (s) - (CPU_FLAGL & C_FLAG); \ - CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x8000; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - if ((r) & 0xffff0000) { \ - (r) &= 0x0000ffff; \ - CPU_FLAGL |= C_FLAG; \ - } \ - CPU_FLAGL |= szpflag_w[(UINT16)(r)]; \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_SBB(r, d, s) \ -do { \ - UINT32 __c = (CPU_FLAGL & C_FLAG); \ - (r) = (d) - (s) - __c; \ - CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80000000; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - if ((!__c && (d) < (s)) || (__c && (d) <= (s))) { \ - CPU_FLAGL |= C_FLAG; \ - } \ - if ((r) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } \ - if ((r) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= szpcflag[(UINT8)(r)] & P_FLAG; \ -} while (/*CONSTCOND*/ 0) - -#define _AND_BYTE(d, s) \ -do { \ - (d) &= (s); \ - CPU_OV = 0; \ - CPU_FLAGL = szpcflag[(UINT8)(d)]; \ -} while (/*CONSTCOND*/ 0) - -#define _AND_WORD(d, s) \ -do { \ - (d) &= (s); \ - CPU_OV = 0; \ - CPU_FLAGL = szpflag_w[(UINT16)(d)]; \ -} while (/*CONSTCOND*/ 0) - -#define _AND_DWORD(d, s) \ -do { \ - (d) &= (s); \ - CPU_OV = 0; \ - CPU_FLAGL = (UINT8)(szpcflag[(UINT8)(d)] & P_FLAG); \ - if ((d) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } \ - if ((d) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_SUB(r, d, s) \ -do { \ - (r) = (d) - (s); \ - CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - CPU_FLAGL |= szpcflag[(r) & 0x1ff]; \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_SUB(r, d, s) \ -do { \ - (r) = (d) - (s); \ - CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x8000; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - if ((r) & 0xffff0000) { \ - (r) &= 0x0000ffff; \ - CPU_FLAGL |= C_FLAG; \ - } \ - CPU_FLAGL |= szpflag_w[(UINT16)(r)]; \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_SUB(r, d, s) \ -do { \ - (r) = (d) - (s); \ - CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80000000; \ - CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ - if ((d) < (s)) { \ - CPU_FLAGL |= C_FLAG; \ - } \ - if ((r) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } \ - if ((r) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= szpcflag[(UINT8)(r)] & P_FLAG; \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_XOR(d, s) \ -do { \ - (d) ^= s; \ - CPU_OV = 0; \ - CPU_FLAGL = szpcflag[(UINT8)(d)]; \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_XOR(d, s) \ -do { \ - (d) ^= (s); \ - CPU_OV = 0; \ - CPU_FLAGL = szpflag_w[(UINT16)(d)]; \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_XOR(d, s) \ -do { \ - (d) ^= (s); \ - CPU_OV = 0; \ - CPU_FLAGL = (UINT8)(szpcflag[(UINT8)(d)] & P_FLAG); \ - if ((d) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } \ - if ((d) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_NEG(d, s) \ -do { \ - (d) = 0 - (s); \ - CPU_OV = ((d) & (s)) & 0x80; \ - CPU_FLAGL = (UINT8)(((d) ^ (s)) & A_FLAG); \ - CPU_FLAGL |= szpcflag[(d) & 0x1ff]; \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_NEG(d, s) \ -do { \ - (d) = 0 - (s); \ - CPU_OV = ((d) & (s)) & 0x8000; \ - CPU_FLAGL = (UINT8)(((d) ^ (s)) & A_FLAG); \ - if ((d) & 0xffff0000) { \ - (d) &= 0x0000ffff; \ - CPU_FLAGL |= C_FLAG; \ - } \ - CPU_FLAGL |= szpflag_w[(UINT16)(d)]; \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_NEG(d, s) \ -do { \ - (d) = 0 - (s); \ - CPU_OV = ((d) & (s)) & 0x80000000; \ - CPU_FLAGL = (UINT8)(((d) ^ (s)) & A_FLAG); \ - if ((d) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } else { \ - CPU_FLAGL |= C_FLAG; \ - } \ - if ((d) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= szpcflag[(UINT8)(d)] & P_FLAG; \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_MUL(r, d, s) \ -do { \ - CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ - (r) = (UINT8)(d) * (UINT8)(s); \ - CPU_OV = (r) >> 8; \ - if (CPU_OV) { \ - CPU_FLAGL |= C_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_MUL(r, d, s) \ -do { \ - CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ - (r) = (UINT16)(d) * (UINT16)(s); \ - CPU_OV = (r) >> 16; \ - if (CPU_OV) { \ - CPU_FLAGL |= C_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_MUL(r, d, s) \ -do { \ - UINT64 __v; \ - CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ - __v = (UINT64)(d) * (UINT64)(s); \ - (r) = (UINT32)__v; \ - CPU_OV = (UINT32)(__v >> 32); \ - if (CPU_OV) { \ - CPU_FLAGL |= C_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_IMUL(r, d, s) \ -do { \ - CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ - (r) = (SINT8)(d) * (SINT8)(s); \ - CPU_OV = ((r) + 0x80) & 0xffffff00; \ - if (CPU_OV) { \ - CPU_FLAGL |= C_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_IMUL(r, d, s) \ -do { \ - CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ - (r) = (SINT16)(d) * (SINT16)(s); \ - CPU_OV = ((r) + 0x8000) & 0xffff0000; \ - if (CPU_OV) { \ - CPU_FLAGL |= C_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_IMUL(r, d, s) \ -do { \ - CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ - (r) = (SINT64)(d) * (SINT64)(s); \ - CPU_OV = (UINT32)(((r) + QWORD_CONST(0x80000000)) >> 32); \ - if (CPU_OV) { \ - CPU_FLAGL |= C_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -/* flag no check */ -#define _BYTE_INC(s) \ -do { \ - UINT8 __b = (s); \ - __b++; \ - CPU_OV = __b & (__b ^ (s)) & 0x80; \ - CPU_FLAGL &= C_FLAG; \ - CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ - CPU_FLAGL |= szpcflag[__b]; \ - (s) = __b; \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_INC(s) \ -do { \ - UINT16 __b = (s); \ - __b++; \ - CPU_OV = __b & (__b ^ (s)) & 0x8000; \ - CPU_FLAGL &= C_FLAG; \ - CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ - CPU_FLAGL |= szpflag_w[__b]; \ - (s) = __b; \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_INC(s) \ -do { \ - UINT32 __b = (s); \ - __b++; \ - CPU_OV = __b & (__b ^ (s)) & 0x80000000; \ - CPU_FLAGL &= C_FLAG; \ - CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ - if (__b == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } \ - if (__b & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= szpcflag[(UINT8)(__b)] & P_FLAG; \ - (s) = __b; \ -} while (/*CONSTCOND*/ 0) - -/* flag no check */ -#define _BYTE_DEC(s) \ -do { \ - UINT8 __b = (s); \ - __b--; \ - CPU_OV = (s) & (__b ^ (s)) & 0x80; \ - CPU_FLAGL &= C_FLAG; \ - CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ - CPU_FLAGL |= szpcflag[__b]; \ - (s) = __b; \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_DEC(s) \ -do { \ - UINT16 __b = (s); \ - __b--; \ - CPU_OV = (s) & (__b ^ (s)) & 0x8000; \ - CPU_FLAGL &= C_FLAG; \ - CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ - CPU_FLAGL |= szpflag_w[__b]; \ - (s) = __b; \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_DEC(s) \ -do { \ - UINT32 __b = (s); \ - __b--; \ - CPU_OV = (s) & (__b ^ (s)) & 0x80000000; \ - CPU_FLAGL &= C_FLAG; \ - CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ - if ((__b) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } \ - if ((__b) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= szpcflag[(UINT8)(__b)] & P_FLAG; \ - (s) = __b; \ -} while (/*CONSTCOND*/ 0) - -#define BYTE_NOT(s) \ -do { \ - (s) ^= 0xff; \ -} while (/*CONSTCOND*/ 0) - -#define WORD_NOT(s) \ -do { \ - (s) ^= 0xffff; \ -} while (/*CONSTCOND*/ 0) - -#define DWORD_NOT(s) \ -do { \ - (s) ^= 0xffffffff; \ -} while (/*CONSTCOND*/ 0) - - -/* - * stack - */ -#define REGPUSH(reg, clock) \ -do { \ - UINT16 __new_sp = CPU_SP - 2; \ - CPU_WORKCLOCK(clock); \ - cpu_vmemorywrite_w(CPU_SS_INDEX, __new_sp, reg); \ - CPU_SP = __new_sp; \ -} while (/*CONSTCOND*/ 0) - -#define REGPUSH_32(reg, clock) \ -do { \ - UINT32 __new_esp = CPU_ESP - 4; \ - CPU_WORKCLOCK(clock); \ - cpu_vmemorywrite_d(CPU_SS_INDEX, __new_esp, reg); \ - CPU_ESP = __new_esp; \ -} while (/*CONSTCOND*/ 0) - -#define REGPUSH0(reg) \ -do { \ - UINT16 __new_sp = CPU_SP - 2; \ - cpu_vmemorywrite_w(CPU_SS_INDEX, __new_sp, (UINT16)reg); \ - CPU_SP = __new_sp; \ -} while (/*CONSTCOND*/ 0) - -/* Operand Size == 16 && Stack Size == 32 */ -#define REGPUSH0_16_32(reg) \ -do { \ - UINT32 __new_esp = CPU_ESP - 2; \ - cpu_vmemorywrite_w(CPU_SS_INDEX, __new_esp, (UINT16)reg); \ - CPU_ESP = __new_esp; \ -} while (/*CONSTCOND*/ 0) - -/* Operand Size == 32 && Stack Size == 16 */ -#define REGPUSH0_32_16(reg) \ -do { \ - UINT16 __new_sp = CPU_SP - 4; \ - cpu_vmemorywrite_d(CPU_SS_INDEX, __new_sp, reg); \ - CPU_SP = __new_sp; \ -} while (/*CONSTCOND*/ 0) - -#define REGPUSH0_32(reg) \ -do { \ - UINT32 __new_esp = CPU_ESP - 4; \ - cpu_vmemorywrite_d(CPU_SS_INDEX, __new_esp, reg); \ - CPU_ESP = __new_esp; \ -} while (/*CONSTCOND*/ 0) - -#define PUSH0_16(reg) \ -do { \ - if (!CPU_STAT_SS32) { \ - REGPUSH0(reg); \ - } else { \ - REGPUSH0_16_32(reg); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define PUSH0_32(reg) \ -do { \ - if (CPU_STAT_SS32) { \ - REGPUSH0_32(reg); \ - } else { \ - REGPUSH0_32_16(reg); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XPUSH0(reg) \ -do { \ - if (!CPU_INST_OP32) { \ - PUSH0_16(reg); \ - } else { \ - PUSH0_32(reg); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define REGPOP(reg, clock) \ -do { \ - CPU_WORKCLOCK(clock); \ - (reg) = cpu_vmemoryread_w(CPU_SS_INDEX, CPU_SP); \ - CPU_SP += 2; \ -} while (/*CONSTCOND*/ 0) - -#define REGPOP_32(reg, clock) \ -do { \ - CPU_WORKCLOCK(clock); \ - (reg) = cpu_vmemoryread_d(CPU_SS_INDEX, CPU_ESP); \ - CPU_ESP += 4; \ -} while (/*CONSTCOND*/ 0) - -#define REGPOP0(reg) \ -do { \ - (reg) = cpu_vmemoryread_w(CPU_SS_INDEX, CPU_SP); \ - CPU_SP += 2; \ -} while (/*CONSTCOND*/ 0) - -#define REGPOP0_16_32(reg) \ -do { \ - (reg) = cpu_vmemoryread_w(CPU_SS_INDEX, CPU_ESP); \ - CPU_ESP += 2; \ -} while (/*CONSTCOND*/ 0) - -#define REGPOP0_32_16(reg) \ -do { \ - (reg) = cpu_vmemoryread_d(CPU_SS_INDEX, CPU_SP); \ - CPU_SP += 4; \ -} while (/*CONSTCOND*/ 0) - -#define REGPOP0_32(reg) \ -do { \ - (reg) = cpu_vmemoryread_d(CPU_SS_INDEX, CPU_ESP); \ - CPU_ESP += 4; \ -} while (/*CONSTCOND*/ 0) - -#define POP0_16(reg) \ -do { \ - if (!CPU_STAT_SS32) { \ - REGPOP0(reg); \ - } else { \ - REGPOP0_16_32(reg); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define POP0_32(reg) \ -do { \ - if (CPU_STAT_SS32) { \ - REGPOP0_32(reg); \ - } else { \ - REGPOP0_32_16(reg); \ - } \ -} while (/*CONSTCOND*/ 0) - -/* - * stack pointer - */ -#define SP_PUSH_16(reg) \ -do { \ - UINT16 __sp = CPU_SP; \ - if (!CPU_STAT_SS32) { \ - REGPUSH0(__sp); \ - } else { \ - REGPUSH0_16_32(__sp); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define ESP_PUSH_32(reg) \ -do { \ - UINT32 __esp = CPU_ESP; \ - if (!CPU_STAT_SS32) { \ - REGPUSH0_32_16(__esp); \ - } else { \ - REGPUSH0_32(__esp); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define SP_POP_16(reg) \ -do { \ - UINT32 __sp; \ - if (!CPU_STAT_SS32) { \ - __sp = CPU_SP; \ - } else { \ - __sp = CPU_ESP; \ - } \ - CPU_SP = cpu_vmemoryread_w(CPU_SS_INDEX, __sp); \ -} while (/*CONSTCOND*/ 0) - -#define ESP_POP_32(reg) \ -do { \ - UINT32 __esp; \ - if (!CPU_STAT_SS32) { \ - __esp = CPU_SP; \ - } else { \ - __esp = CPU_ESP; \ - } \ - CPU_ESP = cpu_vmemoryread_d(CPU_SS_INDEX, __esp); \ -} while (/*CONSTCOND*/ 0) - - -/* - * jump - */ -#define JMPSHORT(clock) \ -do { \ - UINT32 __new_ip; \ - UINT32 __dest; \ - CPU_WORKCLOCK(clock); \ - GET_PCBYTESD(__dest); \ - __new_ip = CPU_EIP + __dest; \ - if (!CPU_INST_OP32) { \ - __new_ip &= 0xffff; \ - } \ - if (__new_ip > CPU_STAT_CS_LIMIT) { \ - EXCEPTION(GP_EXCEPTION, 0); \ - } \ - CPU_EIP = __new_ip; \ -} while (/*CONSTCOND*/ 0) - -#define JMPNEAR(clock) \ -do { \ - UINT16 __new_ip; \ - SINT16 __dest; \ - CPU_WORKCLOCK(clock); \ - GET_PCWORDS(__dest); \ - __new_ip = CPU_IP + __dest; \ - if (__new_ip > CPU_STAT_CS_LIMIT) { \ - EXCEPTION(GP_EXCEPTION, 0); \ - } \ - CPU_EIP = __new_ip; \ -} while (/*CONSTCOND*/ 0) - -#define JMPNEAR32(clock) \ -do { \ - UINT32 __new_ip; \ - UINT32 __dest; \ - CPU_WORKCLOCK(clock); \ - GET_PCDWORD(__dest); \ - __new_ip = CPU_EIP + __dest; \ - if (__new_ip > CPU_STAT_CS_LIMIT) { \ - EXCEPTION(GP_EXCEPTION, 0); \ - } \ - CPU_EIP = __new_ip; \ -} while (/*CONSTCOND*/ 0) - -#define JMPNOP(clock, d) \ -do { \ - CPU_WORKCLOCK(clock); \ - _ADD_EIP((d)); \ -} while (/*CONSTCOND*/ 0) - - -/* - * conditions - */ -#define CC_O (CPU_OV) -#define CC_NO (!CPU_OV) -#define CC_C (CPU_FLAGL & C_FLAG) -#define CC_NC (!(CPU_FLAGL & C_FLAG)) -#define CC_Z (CPU_FLAGL & Z_FLAG) -#define CC_NZ (!(CPU_FLAGL & Z_FLAG)) -#define CC_NA (CPU_FLAGL & (Z_FLAG | C_FLAG)) -#define CC_A (!(CPU_FLAGL & (Z_FLAG | C_FLAG))) -#define CC_S (CPU_FLAGL & S_FLAG) -#define CC_NS (!(CPU_FLAGL & S_FLAG)) -#define CC_P (CPU_FLAGL & P_FLAG) -#define CC_NP (!(CPU_FLAGL & P_FLAG)) -#define CC_L (((CPU_FLAGL & S_FLAG) == 0) != (CPU_OV == 0)) -#define CC_NL (((CPU_FLAGL & S_FLAG) == 0) == (CPU_OV == 0)) -#define CC_LE ((CPU_FLAGL & Z_FLAG) || \ - (((CPU_FLAGL & S_FLAG) == 0) != (CPU_OV == 0))) -#define CC_NLE ((!(CPU_FLAGL & Z_FLAG)) && \ - (((CPU_FLAGL & S_FLAG) == 0) == (CPU_OV == 0))) - - -/* - * instruction check - */ -#include "ia32xc.mcr" - -#endif /* IA32_CPU_IA32_MCR__ */ +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_IA32_MCR__ +#define IA32_CPU_IA32_MCR__ + +/* + * misc + */ +#define __CBW(src) ((UINT16)((SINT8)(src))) +#define __CBD(src) ((UINT32)((SINT8)(src))) +#define __CWDE(src) ((SINT16)(src)) + +#ifndef PTR_TO_UINT32 +#define PTR_TO_UINT32(p) ((UINT32)((unsigned long)(p))) +#endif +#ifndef UINT32_TO_PTR +#define UINT32_TO_PTR(v) ((void *)((unsigned long)(UINT32)(v))) +#endif + +#define SWAP_BYTE(p, q) \ +do { \ + UINT8 __tmp = (p); \ + (p) = (q); \ + (q) = __tmp; \ +} while (/*CONSTCOND*/ 0) + +#define SWAP_WORD(p, q) \ +do { \ + UINT16 __tmp = (p); \ + (p) = (q); \ + (q) = __tmp; \ +} while (/*CONSTCOND*/ 0) + +#define SWAP_DWORD(p, q) \ +do { \ + UINT32 __tmp = (p); \ + (p) = (q); \ + (q) = __tmp; \ +} while (/*CONSTCOND*/ 0) + + +/* + * clock + */ +#define CPU_WORKCLOCK(clock) \ +do { \ + CPU_REMCLOCK -= (clock); \ +} while (/*CONSTCOND*/ 0) + +#define CPU_HALT() \ +do { \ + CPU_REMCLOCK = -1; \ +} while (/*CONSTCOND*/ 0) + +#define IRQCHECKTERM() \ +do { \ + if (CPU_REMCLOCK > 0) { \ + CPU_BASECLOCK -= CPU_REMCLOCK; \ + CPU_REMCLOCK = 0; \ + } \ +} while (/*CONSTCOND*/ 0) + + +/* + * instruction pointer + */ +/* コードフェッチに使用するので、OpSize の影響を受けてはいけない */ +#if defined(USE_CPU_MODRMPREFETCH) +#define _CLEAR_MODRMCACHE() \ +do { \ + opCache = 0; \ +} while (/*CONSTCOND*/ 0) +#else +#define _CLEAR_MODRMCACHE() (void)0 +#endif + +#if defined(USE_CPU_EIPMASK) +#define _ADD_EIP(v) \ +do { \ + CPU_EIP = (CPU_EIP + (v)) & CPU_EIPMASK; \ + _CLEAR_MODRMCACHE(); \ +} while (/*CONSTCOND*/ 0) +#else +#define _ADD_EIP(v) \ +do { \ + UINT32 __tmp_ip = CPU_EIP + (v); \ + if (!CPU_STATSAVE.cpu_inst_default.op_32) { \ + __tmp_ip &= 0xffff; \ + } \ + CPU_EIP = __tmp_ip; \ + _CLEAR_MODRMCACHE(); \ +} while (/*CONSTCOND*/ 0) +#endif + +#define GET_PCBYTE(v) \ +do { \ + (v) = cpu_codefetch(CPU_EIP); \ + _ADD_EIP(1); \ +} while (/*CONSTCOND*/ 0) + +#if defined(USE_CPU_MODRMPREFETCH) +#define GET_MODRM_PCBYTE(v) \ +do { \ + if (opCache) { \ + (v) = opCache >> 8; \ + } else { \ + (v) = cpu_codefetch(CPU_EIP); \ + } \ + _ADD_EIP(1); \ +} while (/*CONSTCOND*/ 0) +#else +#define GET_MODRM_PCBYTE(v) GET_PCBYTE(v) +#endif + +#define GET_PCBYTES(v) \ +do { \ + (v) = __CBW(cpu_codefetch(CPU_EIP)); \ + _ADD_EIP(1); \ +} while (/*CONSTCOND*/ 0) + +#define GET_PCBYTESD(v) \ +do { \ + (v) = __CBD(cpu_codefetch(CPU_EIP)); \ + _ADD_EIP(1); \ +} while (/*CONSTCOND*/ 0) + +#define GET_PCWORD(v) \ +do { \ + (v) = cpu_codefetch_w(CPU_EIP); \ + _ADD_EIP(2); \ +} while (/*CONSTCOND*/ 0) + +#define GET_PCWORDS(v) \ +do { \ + (v) = __CWDE(cpu_codefetch_w(CPU_EIP)); \ + _ADD_EIP(2); \ +} while (/*CONSTCOND*/ 0) + +#define GET_PCDWORD(v) \ +do { \ + (v) = cpu_codefetch_d(CPU_EIP); \ + _ADD_EIP(4); \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_EA_REG8(b, d_s) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + (d_s) = *(reg8_b53[(b)]); \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_EA_REG8P(b, d_s) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + (d_s) = reg8_b53[(b)]; \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_EA_REG16(b, d_s) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + (d_s) = CPU_REG16_B53_V(b); \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_EA_REG16P(b, d_s) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + (d_s) = CPU_REG16_B53((b)); \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_EA_REG32(b, d_s) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + (d_s) = CPU_REG32_B53_V(b); \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_EA_REG32P(b, d_s) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + (d_s) = CPU_REG32_B53((b)); \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_REG8_EA(b, s, d, regclk, memclk) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + if ((b) >= 0xc0) { \ + CPU_WORKCLOCK(regclk); \ + (s) = *(reg8_b20[(b)]); \ + } else { \ + UINT32 __t; \ + CPU_WORKCLOCK(memclk); \ + __t = calc_ea_dst((b)); \ + (s) = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, __t); \ + } \ + (d) = reg8_b53[(b)]; \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_REG16_EA(b, s, d, regclk, memclk) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + if ((b) >= 0xc0) { \ + CPU_WORKCLOCK(regclk); \ + (s) = CPU_REG16_B20_V(b); \ + } else { \ + UINT32 __t; \ + CPU_WORKCLOCK(memclk); \ + __t = calc_ea_dst((b)); \ + (s) = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, __t); \ + } \ + (d) = CPU_REG16_B53((b)); \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_REG16_EA8(b, s, d, regclk, memclk) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + if ((b) >= 0xc0) { \ + CPU_WORKCLOCK(regclk); \ + (s) = *(reg8_b20[(b)]); \ + } else { \ + UINT32 __t; \ + CPU_WORKCLOCK(memclk); \ + __t = calc_ea_dst((b)); \ + (s) = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, __t); \ + } \ + (d) = CPU_REG16_B53((b)); \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_REG32_EA(b, s, d, regclk, memclk) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + if ((b) >= 0xc0) { \ + CPU_WORKCLOCK(regclk); \ + (s) = CPU_REG32_B20_V(b); \ + } else { \ + UINT32 __t; \ + CPU_WORKCLOCK(memclk); \ + __t = calc_ea_dst((b)); \ + (s) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, __t); \ + } \ + (d) = CPU_REG32_B53((b)); \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_REG32_EA8(b, s, d, regclk, memclk) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + if ((b) >= 0xc0) { \ + CPU_WORKCLOCK(regclk); \ + (s) = *(reg8_b20[(b)]); \ + } else { \ + UINT32 __t; \ + CPU_WORKCLOCK(memclk); \ + __t = calc_ea_dst((b)); \ + (s) = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, __t); \ + } \ + (d) = CPU_REG32_B53((b)); \ +} while (/*CONSTCOND*/ 0) + +#define PREPART_REG32_EA16(b, s, d, regclk, memclk) \ +do { \ + GET_MODRM_PCBYTE((b)); \ + if ((b) >= 0xc0) { \ + CPU_WORKCLOCK(regclk); \ + (s) = CPU_REG16_B20_V(b); \ + } else { \ + UINT32 __t; \ + CPU_WORKCLOCK(memclk); \ + __t = calc_ea_dst((b)); \ + (s) = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, __t); \ + } \ + (d) = CPU_REG32_B53((b)); \ +} while (/*CONSTCOND*/ 0) + + +/* + * arith + */ +#define _ADD_BYTE(r, d, s) \ +do { \ + (r) = (s) + (d); \ + CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + CPU_FLAGL |= szpcflag[(r) & 0x1ff]; \ +} while (/*CONSTCOND*/ 0) + +#define _ADD_WORD(r, d, s) \ +do { \ + (r) = (s) + (d); \ + CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x8000; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + if ((r) & 0xffff0000) { \ + (r) &= 0x0000ffff; \ + CPU_FLAGL |= C_FLAG; \ + } \ + CPU_FLAGL |= szpflag_w[(UINT16)(r)]; \ +} while (/*CONSTCOND*/ 0) + +#define _ADD_DWORD(r, d, s) \ +do { \ + (r) = (s) + (d); \ + CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80000000; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + if ((r) < (s)) { \ + CPU_FLAGL |= C_FLAG; \ + } \ + if ((r) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } \ + if ((r) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= szpcflag[(UINT8)(r)] & P_FLAG; \ +} while (/*CONSTCOND*/ 0) + +#define _OR_BYTE(d, s) \ +do { \ + (d) |= (s); \ + CPU_OV = 0; \ + CPU_FLAGL = szpcflag[(UINT8)(d)]; \ +} while (/*CONSTCOND*/ 0) + +#define _OR_WORD(d, s) \ +do { \ + (d) |= (s); \ + CPU_OV = 0; \ + CPU_FLAGL = szpflag_w[(UINT16)(d)]; \ +} while (/*CONSTCOND*/ 0) + +#define _OR_DWORD(d, s) \ +do { \ + (d) |= (s); \ + CPU_OV = 0; \ + CPU_FLAGL = (UINT8)(szpcflag[(UINT8)(d)] & P_FLAG); \ + if ((d) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } \ + if ((d) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +/* flag no check */ +#define _ADC_BYTE(r, d, s) \ +do { \ + (r) = (CPU_FLAGL & C_FLAG) + (s) + (d); \ + CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + CPU_FLAGL |= szpcflag[(r) & 0x1ff]; \ +} while (/*CONSTCOND*/ 0) + +#define _ADC_WORD(r, d, s) \ +do { \ + (r) = (CPU_FLAGL & C_FLAG) + (s) + (d); \ + CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x8000; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + if ((r) & 0xffff0000) { \ + (r) &= 0x0000ffff; \ + CPU_FLAGL |= C_FLAG; \ + } \ + CPU_FLAGL |= szpflag_w[(UINT16)(r)]; \ +} while (/*CONSTCOND*/ 0) + +#define _ADC_DWORD(r, d, s) \ +do { \ + UINT32 __c = (CPU_FLAGL & C_FLAG); \ + (r) = (s) + (d) + __c; \ + CPU_OV = ((r) ^ (s)) & ((r) ^ (d)) & 0x80000000; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + if ((!__c && (r) < (s)) || (__c && (r) <= (s))) { \ + CPU_FLAGL |= C_FLAG; \ + } \ + if ((r) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } \ + if ((r) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= szpcflag[(UINT8)(r)] & P_FLAG; \ +} while (/*CONSTCOND*/ 0) + +/* flag no check */ +#define _BYTE_SBB(r, d, s) \ +do { \ + (r) = (d) - (s) - (CPU_FLAGL & C_FLAG); \ + CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + CPU_FLAGL |= szpcflag[(r) & 0x1ff]; \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_SBB(r, d, s) \ +do { \ + (r) = (d) - (s) - (CPU_FLAGL & C_FLAG); \ + CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x8000; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + if ((r) & 0xffff0000) { \ + (r) &= 0x0000ffff; \ + CPU_FLAGL |= C_FLAG; \ + } \ + CPU_FLAGL |= szpflag_w[(UINT16)(r)]; \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_SBB(r, d, s) \ +do { \ + UINT32 __c = (CPU_FLAGL & C_FLAG); \ + (r) = (d) - (s) - __c; \ + CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80000000; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + if ((!__c && (d) < (s)) || (__c && (d) <= (s))) { \ + CPU_FLAGL |= C_FLAG; \ + } \ + if ((r) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } \ + if ((r) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= szpcflag[(UINT8)(r)] & P_FLAG; \ +} while (/*CONSTCOND*/ 0) + +#define _AND_BYTE(d, s) \ +do { \ + (d) &= (s); \ + CPU_OV = 0; \ + CPU_FLAGL = szpcflag[(UINT8)(d)]; \ +} while (/*CONSTCOND*/ 0) + +#define _AND_WORD(d, s) \ +do { \ + (d) &= (s); \ + CPU_OV = 0; \ + CPU_FLAGL = szpflag_w[(UINT16)(d)]; \ +} while (/*CONSTCOND*/ 0) + +#define _AND_DWORD(d, s) \ +do { \ + (d) &= (s); \ + CPU_OV = 0; \ + CPU_FLAGL = (UINT8)(szpcflag[(UINT8)(d)] & P_FLAG); \ + if ((d) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } \ + if ((d) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_SUB(r, d, s) \ +do { \ + (r) = (d) - (s); \ + CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + CPU_FLAGL |= szpcflag[(r) & 0x1ff]; \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_SUB(r, d, s) \ +do { \ + (r) = (d) - (s); \ + CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x8000; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + if ((r) & 0xffff0000) { \ + (r) &= 0x0000ffff; \ + CPU_FLAGL |= C_FLAG; \ + } \ + CPU_FLAGL |= szpflag_w[(UINT16)(r)]; \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_SUB(r, d, s) \ +do { \ + (r) = (d) - (s); \ + CPU_OV = ((d) ^ (r)) & ((d) ^ (s)) & 0x80000000; \ + CPU_FLAGL = (UINT8)(((r) ^ (d) ^ (s)) & A_FLAG); \ + if ((d) < (s)) { \ + CPU_FLAGL |= C_FLAG; \ + } \ + if ((r) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } \ + if ((r) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= szpcflag[(UINT8)(r)] & P_FLAG; \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_XOR(d, s) \ +do { \ + (d) ^= s; \ + CPU_OV = 0; \ + CPU_FLAGL = szpcflag[(UINT8)(d)]; \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_XOR(d, s) \ +do { \ + (d) ^= (s); \ + CPU_OV = 0; \ + CPU_FLAGL = szpflag_w[(UINT16)(d)]; \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_XOR(d, s) \ +do { \ + (d) ^= (s); \ + CPU_OV = 0; \ + CPU_FLAGL = (UINT8)(szpcflag[(UINT8)(d)] & P_FLAG); \ + if ((d) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } \ + if ((d) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_NEG(d, s) \ +do { \ + (d) = 0 - (s); \ + CPU_OV = ((d) & (s)) & 0x80; \ + CPU_FLAGL = (UINT8)(((d) ^ (s)) & A_FLAG); \ + CPU_FLAGL |= szpcflag[(d) & 0x1ff]; \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_NEG(d, s) \ +do { \ + (d) = 0 - (s); \ + CPU_OV = ((d) & (s)) & 0x8000; \ + CPU_FLAGL = (UINT8)(((d) ^ (s)) & A_FLAG); \ + if ((d) & 0xffff0000) { \ + (d) &= 0x0000ffff; \ + CPU_FLAGL |= C_FLAG; \ + } \ + CPU_FLAGL |= szpflag_w[(UINT16)(d)]; \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_NEG(d, s) \ +do { \ + (d) = 0 - (s); \ + CPU_OV = ((d) & (s)) & 0x80000000; \ + CPU_FLAGL = (UINT8)(((d) ^ (s)) & A_FLAG); \ + if ((d) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } else { \ + CPU_FLAGL |= C_FLAG; \ + } \ + if ((d) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= szpcflag[(UINT8)(d)] & P_FLAG; \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_MUL(r, d, s) \ +do { \ + CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ + (r) = (UINT8)(d) * (UINT8)(s); \ + CPU_OV = (r) >> 8; \ + if (CPU_OV) { \ + CPU_FLAGL |= C_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_MUL(r, d, s) \ +do { \ + CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ + (r) = (UINT16)(d) * (UINT16)(s); \ + CPU_OV = (r) >> 16; \ + if (CPU_OV) { \ + CPU_FLAGL |= C_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_MUL(r, d, s) \ +do { \ + UINT64 __v; \ + CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ + __v = (UINT64)(d) * (UINT64)(s); \ + (r) = (UINT32)__v; \ + CPU_OV = (UINT32)(__v >> 32); \ + if (CPU_OV) { \ + CPU_FLAGL |= C_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_IMUL(r, d, s) \ +do { \ + CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ + (r) = (SINT8)(d) * (SINT8)(s); \ + CPU_OV = ((r) + 0x80) & 0xffffff00; \ + if (CPU_OV) { \ + CPU_FLAGL |= C_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_IMUL(r, d, s) \ +do { \ + CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ + (r) = (SINT16)(d) * (SINT16)(s); \ + CPU_OV = ((r) + 0x8000) & 0xffff0000; \ + if (CPU_OV) { \ + CPU_FLAGL |= C_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_IMUL(r, d, s) \ +do { \ + CPU_FLAGL &= (Z_FLAG | S_FLAG | A_FLAG | P_FLAG); \ + (r) = (SINT64)(d) * (SINT64)(s); \ + CPU_OV = (UINT32)(((r) + QWORD_CONST(0x80000000)) >> 32); \ + if (CPU_OV) { \ + CPU_FLAGL |= C_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +/* flag no check */ +#define _BYTE_INC(s) \ +do { \ + UINT8 __b = (s); \ + __b++; \ + CPU_OV = __b & (__b ^ (s)) & 0x80; \ + CPU_FLAGL &= C_FLAG; \ + CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ + CPU_FLAGL |= szpcflag[__b]; \ + (s) = __b; \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_INC(s) \ +do { \ + UINT16 __b = (s); \ + __b++; \ + CPU_OV = __b & (__b ^ (s)) & 0x8000; \ + CPU_FLAGL &= C_FLAG; \ + CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ + CPU_FLAGL |= szpflag_w[__b]; \ + (s) = __b; \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_INC(s) \ +do { \ + UINT32 __b = (s); \ + __b++; \ + CPU_OV = __b & (__b ^ (s)) & 0x80000000; \ + CPU_FLAGL &= C_FLAG; \ + CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ + if (__b == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } \ + if (__b & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= szpcflag[(UINT8)(__b)] & P_FLAG; \ + (s) = __b; \ +} while (/*CONSTCOND*/ 0) + +/* flag no check */ +#define _BYTE_DEC(s) \ +do { \ + UINT8 __b = (s); \ + __b--; \ + CPU_OV = (s) & (__b ^ (s)) & 0x80; \ + CPU_FLAGL &= C_FLAG; \ + CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ + CPU_FLAGL |= szpcflag[__b]; \ + (s) = __b; \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_DEC(s) \ +do { \ + UINT16 __b = (s); \ + __b--; \ + CPU_OV = (s) & (__b ^ (s)) & 0x8000; \ + CPU_FLAGL &= C_FLAG; \ + CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ + CPU_FLAGL |= szpflag_w[__b]; \ + (s) = __b; \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_DEC(s) \ +do { \ + UINT32 __b = (s); \ + __b--; \ + CPU_OV = (s) & (__b ^ (s)) & 0x80000000; \ + CPU_FLAGL &= C_FLAG; \ + CPU_FLAGL |= (UINT8)((__b ^ (s)) & A_FLAG); \ + if ((__b) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } \ + if ((__b) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= szpcflag[(UINT8)(__b)] & P_FLAG; \ + (s) = __b; \ +} while (/*CONSTCOND*/ 0) + +#define BYTE_NOT(s) \ +do { \ + (s) ^= 0xff; \ +} while (/*CONSTCOND*/ 0) + +#define WORD_NOT(s) \ +do { \ + (s) ^= 0xffff; \ +} while (/*CONSTCOND*/ 0) + +#define DWORD_NOT(s) \ +do { \ + (s) ^= 0xffffffff; \ +} while (/*CONSTCOND*/ 0) + + +/* + * stack + */ +#define REGPUSH(reg, clock) \ +do { \ + UINT16 __new_sp = CPU_SP - 2; \ + CPU_WORKCLOCK(clock); \ + cpu_vmemorywrite_w(CPU_SS_INDEX, __new_sp, reg); \ + CPU_SP = __new_sp; \ +} while (/*CONSTCOND*/ 0) + +#define REGPUSH_32(reg, clock) \ +do { \ + UINT32 __new_esp = CPU_ESP - 4; \ + CPU_WORKCLOCK(clock); \ + cpu_vmemorywrite_d(CPU_SS_INDEX, __new_esp, reg); \ + CPU_ESP = __new_esp; \ +} while (/*CONSTCOND*/ 0) + +#define REGPUSH0(reg) \ +do { \ + UINT16 __new_sp = CPU_SP - 2; \ + cpu_vmemorywrite_w(CPU_SS_INDEX, __new_sp, (UINT16)reg); \ + CPU_SP = __new_sp; \ +} while (/*CONSTCOND*/ 0) + +/* Operand Size == 16 && Stack Size == 32 */ +#define REGPUSH0_16_32(reg) \ +do { \ + UINT32 __new_esp = CPU_ESP - 2; \ + cpu_vmemorywrite_w(CPU_SS_INDEX, __new_esp, (UINT16)reg); \ + CPU_ESP = __new_esp; \ +} while (/*CONSTCOND*/ 0) + +/* Operand Size == 32 && Stack Size == 16 */ +#define REGPUSH0_32_16(reg) \ +do { \ + UINT16 __new_sp = CPU_SP - 4; \ + cpu_vmemorywrite_d(CPU_SS_INDEX, __new_sp, reg); \ + CPU_SP = __new_sp; \ +} while (/*CONSTCOND*/ 0) + +#define REGPUSH0_32(reg) \ +do { \ + UINT32 __new_esp = CPU_ESP - 4; \ + cpu_vmemorywrite_d(CPU_SS_INDEX, __new_esp, reg); \ + CPU_ESP = __new_esp; \ +} while (/*CONSTCOND*/ 0) + +#define PUSH0_16(reg) \ +do { \ + if (!CPU_STAT_SS32) { \ + REGPUSH0(reg); \ + } else { \ + REGPUSH0_16_32(reg); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define PUSH0_32(reg) \ +do { \ + if (CPU_STAT_SS32) { \ + REGPUSH0_32(reg); \ + } else { \ + REGPUSH0_32_16(reg); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XPUSH0(reg) \ +do { \ + if (!CPU_INST_OP32) { \ + PUSH0_16(reg); \ + } else { \ + PUSH0_32(reg); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define REGPOP(reg, clock) \ +do { \ + CPU_WORKCLOCK(clock); \ + (reg) = cpu_vmemoryread_w(CPU_SS_INDEX, CPU_SP); \ + CPU_SP += 2; \ +} while (/*CONSTCOND*/ 0) + +#define REGPOP_32(reg, clock) \ +do { \ + CPU_WORKCLOCK(clock); \ + (reg) = cpu_vmemoryread_d(CPU_SS_INDEX, CPU_ESP); \ + CPU_ESP += 4; \ +} while (/*CONSTCOND*/ 0) + +#define REGPOP0(reg) \ +do { \ + (reg) = cpu_vmemoryread_w(CPU_SS_INDEX, CPU_SP); \ + CPU_SP += 2; \ +} while (/*CONSTCOND*/ 0) + +#define REGPOP0_16_32(reg) \ +do { \ + (reg) = cpu_vmemoryread_w(CPU_SS_INDEX, CPU_ESP); \ + CPU_ESP += 2; \ +} while (/*CONSTCOND*/ 0) + +#define REGPOP0_32_16(reg) \ +do { \ + (reg) = cpu_vmemoryread_d(CPU_SS_INDEX, CPU_SP); \ + CPU_SP += 4; \ +} while (/*CONSTCOND*/ 0) + +#define REGPOP0_32(reg) \ +do { \ + (reg) = cpu_vmemoryread_d(CPU_SS_INDEX, CPU_ESP); \ + CPU_ESP += 4; \ +} while (/*CONSTCOND*/ 0) + +#define POP0_16(reg) \ +do { \ + if (!CPU_STAT_SS32) { \ + REGPOP0(reg); \ + } else { \ + REGPOP0_16_32(reg); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define POP0_32(reg) \ +do { \ + if (CPU_STAT_SS32) { \ + REGPOP0_32(reg); \ + } else { \ + REGPOP0_32_16(reg); \ + } \ +} while (/*CONSTCOND*/ 0) + +/* + * stack pointer + */ +#define SP_PUSH_16(reg) \ +do { \ + UINT16 __sp = CPU_SP; \ + if (!CPU_STAT_SS32) { \ + REGPUSH0(__sp); \ + } else { \ + REGPUSH0_16_32(__sp); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define ESP_PUSH_32(reg) \ +do { \ + UINT32 __esp = CPU_ESP; \ + if (!CPU_STAT_SS32) { \ + REGPUSH0_32_16(__esp); \ + } else { \ + REGPUSH0_32(__esp); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define SP_POP_16(reg) \ +do { \ + UINT32 __sp; \ + if (!CPU_STAT_SS32) { \ + __sp = CPU_SP; \ + } else { \ + __sp = CPU_ESP; \ + } \ + CPU_SP = cpu_vmemoryread_w(CPU_SS_INDEX, __sp); \ +} while (/*CONSTCOND*/ 0) + +#define ESP_POP_32(reg) \ +do { \ + UINT32 __esp; \ + if (!CPU_STAT_SS32) { \ + __esp = CPU_SP; \ + } else { \ + __esp = CPU_ESP; \ + } \ + CPU_ESP = cpu_vmemoryread_d(CPU_SS_INDEX, __esp); \ +} while (/*CONSTCOND*/ 0) + + +/* + * jump + */ +#define JMPSHORT(clock) \ +do { \ + UINT32 __new_ip; \ + UINT32 __dest; \ + CPU_WORKCLOCK(clock); \ + GET_PCBYTESD(__dest); \ + __new_ip = CPU_EIP + __dest; \ + if (!CPU_INST_OP32) { \ + __new_ip &= 0xffff; \ + } \ + if (__new_ip > CPU_STAT_CS_LIMIT) { \ + EXCEPTION(GP_EXCEPTION, 0); \ + } \ + CPU_EIP = __new_ip; \ +} while (/*CONSTCOND*/ 0) + +#define JMPNEAR(clock) \ +do { \ + UINT16 __new_ip; \ + SINT16 __dest; \ + CPU_WORKCLOCK(clock); \ + GET_PCWORDS(__dest); \ + __new_ip = CPU_IP + __dest; \ + if (__new_ip > CPU_STAT_CS_LIMIT) { \ + EXCEPTION(GP_EXCEPTION, 0); \ + } \ + CPU_EIP = __new_ip; \ +} while (/*CONSTCOND*/ 0) + +#define JMPNEAR32(clock) \ +do { \ + UINT32 __new_ip; \ + UINT32 __dest; \ + CPU_WORKCLOCK(clock); \ + GET_PCDWORD(__dest); \ + __new_ip = CPU_EIP + __dest; \ + if (__new_ip > CPU_STAT_CS_LIMIT) { \ + EXCEPTION(GP_EXCEPTION, 0); \ + } \ + CPU_EIP = __new_ip; \ +} while (/*CONSTCOND*/ 0) + +#define JMPNOP(clock, d) \ +do { \ + CPU_WORKCLOCK(clock); \ + _ADD_EIP((d)); \ +} while (/*CONSTCOND*/ 0) + + +/* + * conditions + */ +#define CC_O (CPU_OV) +#define CC_NO (!CPU_OV) +#define CC_C (CPU_FLAGL & C_FLAG) +#define CC_NC (!(CPU_FLAGL & C_FLAG)) +#define CC_Z (CPU_FLAGL & Z_FLAG) +#define CC_NZ (!(CPU_FLAGL & Z_FLAG)) +#define CC_NA (CPU_FLAGL & (Z_FLAG | C_FLAG)) +#define CC_A (!(CPU_FLAGL & (Z_FLAG | C_FLAG))) +#define CC_S (CPU_FLAGL & S_FLAG) +#define CC_NS (!(CPU_FLAGL & S_FLAG)) +#define CC_P (CPU_FLAGL & P_FLAG) +#define CC_NP (!(CPU_FLAGL & P_FLAG)) +#define CC_L (((CPU_FLAGL & S_FLAG) == 0) != (CPU_OV == 0)) +#define CC_NL (((CPU_FLAGL & S_FLAG) == 0) == (CPU_OV == 0)) +#define CC_LE ((CPU_FLAGL & Z_FLAG) || \ + (((CPU_FLAGL & S_FLAG) == 0) != (CPU_OV == 0))) +#define CC_NLE ((!(CPU_FLAGL & Z_FLAG)) && \ + (((CPU_FLAGL & S_FLAG) == 0) == (CPU_OV == 0))) + + +/* + * instruction check + */ +#include "ia32xc.mcr" + +#endif /* IA32_CPU_IA32_MCR__ */ diff --git a/i386c/ia32/ia32weak.txt b/i386c/ia32/ia32weak.txt old mode 100755 new mode 100644 index 443dad97..28e16354 --- a/i386c/ia32/ia32weak.txt +++ b/i386c/ia32/ia32weak.txt @@ -1,77 +1,77 @@ - - - 現状では問題になっていないが、将来問題になる点。 - - - -・結局のところ… -  メモリが一番スピードに関る、命令フェッチで毎回読む訳だし。 - -  ・引き数 int crw と int user_modeをどうにか一本に出来ないか? -    crw + (user_mode << 3) の形で持つ? - - →やってみました。どんなもんでしょ。 - - -・複雑なスタック処理の問題 -  pushaの esp==7,9,11,13,15の GPF(やる気しない - - - -・repe/ne string命令 -  現状、string命令中に外部割り込みを受け付けない。 -  ドラッケンみたいな repのカウンタ数が長く、かつ 特定タイミングで割り込みを -  必要とするソフトで不都合が生じる。 - - - -・デバグレジスタのブレーク -  現在はDRのブレークを使用するアプリは存在しないようだ。 -  もし対応するのであれば 現在の形ではなく exec_1step()を二重化し、 -  シングルステップ割り込みのように ia32()で振り分け処理を行なうとよい。 - - - -・シフトマクロ - if ((s) == 0) CPU_FLAGL |= Z_FLAG; - if ((s) & (1 << (SIZE - 1))) CPU_FLAGL |= S_FLAG; - - if ((s) == 0) CPU_FLAGL |= Z_FLAG; - else if ((s) & (1 << (SIZE - 1))) CPU_FLAGL |= S_FLAG; - -  どっちが高速?(elseでジャンプが生まれる…) - -  (所詮CPUによって変わるが) むしろ… - - if ((s) == 0) CPU_FLAGL |= Z_FLAG; - CPU_FLAGL |= ((s) >> (SIZE - 8)) & S_FLAG; - -  の方が面白い? - - - x86 ARM - cmp (s), 0 cmp (s), #0 - jne short @f orreq CPU_FLAGL, CPU_FLAGL, #Z_FLAG - or CPU_FLAGL, Z_FLAG -@@: test (s), 1 << (SIZE - 1) tst (s), #(1 << (SIZE - 1)) - je short @f orrne CPU_FLAGL, CPU_FLAGL, #S_FLAG - or CPU_FLAGL, S_FLAG -@@: - - cmp (s), 0 cmp (s), #0 - jne short @1 orreq CPU_FLAGL, CPU_FLAGL, #Z_FLAG - or CPU_FLAGL, Z_FLAG beq @2 - jmp short @2 -@1: test (s), 1 << (SIZE - 1) tst (s), #(1 << (SIZE - 1)) - je short @2 orrne CPU_FLAGL, CPU_FLAGL, #S_FLAG - or CPU_FLAGL, S_FLAG -@2: - - mov reg, (s) movs reg, (s) - cmp reg, 0 - jne short @f - or CPU_FLAGL, Z_FLAG orreq CPU_FLAGL, CPU_FLAGL, Z_FLAG -@@: shr reg, SIZE - 8 mov reg, reg lsr #(SIZE - 8) - and reg, S_FLAG and reg, reg, #S_FLAG - or CPU_FLAGL, reg orr CPU_FLAGL, reg, CPU_FLAGL - + + + 現状では問題になっていないが、将来問題になる点。 + + + +・結局のところ… +  メモリが一番スピードに関る、命令フェッチで毎回読む訳だし。 + +  ・引き数 int crw と int user_modeをどうにか一本に出来ないか? +    crw + (user_mode << 3) の形で持つ? + + →やってみました。どんなもんでしょ。 + + +・複雑なスタック処理の問題 +  pushaの esp==7,9,11,13,15の GPF(やる気しない + + + +・repe/ne string命令 +  現状、string命令中に外部割り込みを受け付けない。 +  ドラッケンみたいな repのカウンタ数が長く、かつ 特定タイミングで割り込みを +  必要とするソフトで不都合が生じる。 + + + +・デバグレジスタのブレーク +  現在はDRのブレークを使用するアプリは存在しないようだ。 +  もし対応するのであれば 現在の形ではなく exec_1step()を二重化し、 +  シングルステップ割り込みのように ia32()で振り分け処理を行なうとよい。 + + + +・シフトマクロ + if ((s) == 0) CPU_FLAGL |= Z_FLAG; + if ((s) & (1 << (SIZE - 1))) CPU_FLAGL |= S_FLAG; + + if ((s) == 0) CPU_FLAGL |= Z_FLAG; + else if ((s) & (1 << (SIZE - 1))) CPU_FLAGL |= S_FLAG; + +  どっちが高速?(elseでジャンプが生まれる…) + +  (所詮CPUによって変わるが) むしろ… + + if ((s) == 0) CPU_FLAGL |= Z_FLAG; + CPU_FLAGL |= ((s) >> (SIZE - 8)) & S_FLAG; + +  の方が面白い? + + + x86 ARM + cmp (s), 0 cmp (s), #0 + jne short @f orreq CPU_FLAGL, CPU_FLAGL, #Z_FLAG + or CPU_FLAGL, Z_FLAG +@@: test (s), 1 << (SIZE - 1) tst (s), #(1 << (SIZE - 1)) + je short @f orrne CPU_FLAGL, CPU_FLAGL, #S_FLAG + or CPU_FLAGL, S_FLAG +@@: + + cmp (s), 0 cmp (s), #0 + jne short @1 orreq CPU_FLAGL, CPU_FLAGL, #Z_FLAG + or CPU_FLAGL, Z_FLAG beq @2 + jmp short @2 +@1: test (s), 1 << (SIZE - 1) tst (s), #(1 << (SIZE - 1)) + je short @2 orrne CPU_FLAGL, CPU_FLAGL, #S_FLAG + or CPU_FLAGL, S_FLAG +@2: + + mov reg, (s) movs reg, (s) + cmp reg, 0 + jne short @f + or CPU_FLAGL, Z_FLAG orreq CPU_FLAGL, CPU_FLAGL, Z_FLAG +@@: shr reg, SIZE - 8 mov reg, reg lsr #(SIZE - 8) + and reg, S_FLAG and reg, reg, #S_FLAG + or CPU_FLAGL, reg orr CPU_FLAGL, reg, CPU_FLAGL + diff --git a/i386c/ia32/ia32xc.mcr b/i386c/ia32/ia32xc.mcr old mode 100755 new mode 100644 index 3592e169..1836ba68 --- a/i386c/ia32/ia32xc.mcr +++ b/i386c/ia32/ia32xc.mcr @@ -1,1710 +1,1710 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_IA32XC_MCR__ -#define IA32_CPU_IA32XC_MCR__ - -#if defined(IA32_CROSS_CHECK) && defined(GCC_CPU_ARCH_IA32) - -#define IA32_CPU_ENABLE_XC - -/* - * arith - */ -#define XC_ADD_BYTE(r, d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __d = (d) & 0xff; \ - UINT8 __r = __d; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _ADD_BYTE((r), (d), (s)); \ - __R = (r) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushl %%eax\n\t" \ - "movb %3, %%al\n\t" \ - "addb %4, %%al\n\t" \ - "movb %%al, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_ADD_BYTE: __s = %02x, __d = %02x", __s, __d); \ - ia32_warning("XC_ADD_BYTE: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_ADD_BYTE: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_ADD_BYTE: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_ADD_WORD(r, d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __d = (d) & 0xffff; \ - UINT16 __r = __d; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _ADD_WORD((r), (d), (s)); \ - __R = (r) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushl %%eax\n\t" \ - "movw %3, %%ax\n\t" \ - "addw %4, %%ax\n\t" \ - "movw %%ax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax", "ecx"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_ADD_WORD: __s = %04x, __d = %04x", __s, __d); \ - ia32_warning("XC_ADD_WORD: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_ADD_WORD: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_ADD_WORD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_ADD_DWORD(r, d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __d = (d); \ - UINT32 __r = __d; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _ADD_DWORD((r), (d), (s)); \ - __R = (r); \ - \ - __asm__ __volatile__ ( \ - "pushl %%eax\n\t" \ - "movl %3, %%eax\n\t" \ - "addl %4, %%eax\n\t" \ - "movl %%eax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax", "ecx"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_ADD_DWORD: __s = %08x, __d = %08x", __s, __d);\ - ia32_warning("XC_ADD_DWORD: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_ADD_DWORD: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_ADD_DWORD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_OR_BYTE(d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __d = (d) & 0xff; \ - UINT8 __r = __d; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _OR_BYTE((d), (s)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushl %%eax\n\t" \ - "movb %3, %%al\n\t" \ - "orb %4, %%al\n\t" \ - "movb %%al, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_OR_BYTE: __s = %02x, __d = %02x", __s, __d); \ - ia32_warning("XC_OR_BYTE: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_OR_BYTE: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ - ia32_warning("XC_OR_BYTE: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_OR_WORD(d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __d = (d) & 0xffff; \ - UINT16 __r = __d; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _OR_WORD((d), (s)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushl %%eax\n\t" \ - "movw %3, %%ax\n\t" \ - "orw %4, %%ax\n\t" \ - "movw %%ax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_OR_WORD: __s = %04x, __d = %04x", __s, __d); \ - ia32_warning("XC_OR_WORD: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_OR_WORD: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ - ia32_warning("XC_OR_WORD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_OR_DWORD(d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __d = (d); \ - UINT32 __r = __d; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _OR_DWORD((d), (s)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushl %%eax\n\t" \ - "movl %3, %%eax\n\t" \ - "orl %4, %%eax\n\t" \ - "movl %%eax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_OR_DWORD: __s = %08x, __d = %08x", __s, __d); \ - ia32_warning("XC_OR_DWORD: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_OR_DWORD: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ - ia32_warning("XC_OR_DWORD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -/* flag no check */ -#define XC_ADC_BYTE(r, d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __d = (d) & 0xff; \ - UINT8 __r = __d; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _ADC_BYTE((r), (d), (s)); \ - __R = (r) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "movb %3, %%al\n\t" \ - "adcb %4, %%al\n\t" \ - "movb %%al, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_ADC_BYTE: __s = %02x, __d = %02x", __s, __d); \ - ia32_warning("XC_ADC_BYTE: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_ADC_BYTE: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_ADC_BYTE: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_ADC_WORD(r, d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __d = (d) & 0xffff; \ - UINT16 __r = __d; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _ADC_WORD((r), (d), (s)); \ - __R = (r) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "movw %3, %%ax\n\t" \ - "adcw %4, %%ax\n\t" \ - "movw %%ax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_ADC_WORD: __s = %04x, __d = %04x", __s, __d); \ - ia32_warning("XC_ADC_WORD: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_ADC_WORD: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_ADC_WORD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_ADC_DWORD(r, d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __d = (d); \ - UINT32 __r = __d; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _ADC_DWORD((r), (d), (s)); \ - __R = (r); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "movl %3, %%eax\n\t" \ - "adcl %4, %%eax\n\t" \ - "movl %%eax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_ADC_DWORD: __s = %08x, __d = %08x", __s, __d);\ - ia32_warning("XC_ADC_DWORD: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_ADC_DWORD: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_ADC_DWORD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -/* flag no check */ -#define XC_BYTE_SBB(r, d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __d = (d) & 0xff; \ - UINT8 __r = __d; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _BYTE_SBB((r), (d), (s)); \ - __R = (r) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "movb %3, %%al\n\t" \ - "sbbb %4, %%al\n\t" \ - "movb %%al, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_SBB: __s = %02x, __d = %02x", __s, __d); \ - ia32_warning("XC_BYTE_SBB: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_SBB: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_BYTE_SBB: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_SBB(r, d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __d = (d) & 0xffff; \ - UINT16 __r = __d; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _WORD_SBB((r), (d), (s)); \ - __R = (r) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "movw %3, %%ax\n\t" \ - "sbbw %4, %%ax\n\t" \ - "movw %%ax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_SBB: __s = %04x, __d = %04x", __s, __d); \ - ia32_warning("XC_WORD_SBB: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_SBB: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_WORD_SBB: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_SBB(r, d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __d = (d); \ - UINT32 __r = __d; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _DWORD_SBB((r), (d), (s)); \ - __R = (r); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "movl %3, %%eax\n\t" \ - "sbbl %4, %%eax\n\t" \ - "movl %%eax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_SBB: __s = %08x, __d = %08x", __s, __d);\ - ia32_warning("XC_DWORD_SBB: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_SBB: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_DWORD_SBB: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_AND_BYTE(d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __d = (d) & 0xff; \ - UINT8 __r = __d; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _AND_BYTE((d), (s)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movb %3, %%al\n\t" \ - "andb %4, %%al\n\t" \ - "movb %%al, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_ANDBYTE: __s = %02x, __d = %02x", __s, __d); \ - ia32_warning("XC_ANDBYTE: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_ANDBYTE: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ - ia32_warning("XC_ANDBYTE: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_AND_WORD(d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __d = (d) & 0xffff; \ - UINT16 __r = __d; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _AND_WORD((d), (s)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movw %3, %%ax\n\t" \ - "andw %4, %%ax\n\t" \ - "movw %%ax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_ANDWORD: __s = %04x, __d = %04x", __s, __d); \ - ia32_warning("XC_ANDWORD: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_ANDWORD: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ - ia32_warning("XC_ANDWORD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_AND_DWORD(d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __d = (d); \ - UINT32 __r = __d; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _AND_DWORD((d), (s)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movl %3, %%eax\n\t" \ - "andl %4, %%eax\n\t" \ - "movl %%eax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_ANDDWORD: __s = %08x, __d = %08x", __s, __d); \ - ia32_warning("XC_ANDDWORD: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_ANDDWORD: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ - ia32_warning("XC_ANDDWORD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_SUB(r, d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __d = (d) & 0xff; \ - UINT8 __r = __d; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_SUB((r), (d), (s)); \ - __R = (r) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movb %3, %%al\n\t" \ - "subb %4, %%al\n\t" \ - "movb %%al, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_SUB: __s = %02x, __d = %02x", __s, __d); \ - ia32_warning("XC_BYTE_SUB: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_SUB: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_BYTE_SUB: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_SUB(r, d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __d = (d) & 0xffff; \ - UINT16 __r = __d; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_SUB((r), (d), (s)); \ - __R = (r) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movw %3, %%ax\n\t" \ - "subw %4, %%ax\n\t" \ - "movw %%ax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_SUB: __s = %04x, __d = %04x", __s, __d); \ - ia32_warning("XC_WORD_SUB: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_SUB: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_WORD_SUB: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_SUB(r, d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __d = (d); \ - UINT32 __r = __d; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_SUB((r), (d), (s)); \ - __R = (r); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movl %3, %%eax\n\t" \ - "subl %4, %%eax\n\t" \ - "movl %%eax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_SUB: __s = %08x, __d = %08x", __s, __d);\ - ia32_warning("XC_DWORD_SUB: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_SUB: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_DWORD_SUB: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_XOR(d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __d = (d) & 0xff; \ - UINT8 __r = __d; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_XOR((d), (s)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movb %3, %%al\n\t" \ - "xorb %4, %%al\n\t" \ - "movb %%al, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_XORBYTE: __s = %02x, __d = %02x", __s, __d); \ - ia32_warning("XC_XORBYTE: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_XORBYTE: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ - ia32_warning("XC_XORBYTE: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_XOR(d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __d = (d) & 0xffff; \ - UINT16 __r = __d; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_XOR((d), (s)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movw %3, %%ax\n\t" \ - "xorw %4, %%ax\n\t" \ - "movw %%ax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_XORWORD: __s = %04x, __d = %04x", __s, __d); \ - ia32_warning("XC_XORWORD: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_XORWORD: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ - ia32_warning("XC_XORWORD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_XOR(d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __d = (d); \ - UINT32 __r = __d; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_XOR((d), (s)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movl %3, %%eax\n\t" \ - "xorl %4, %%eax\n\t" \ - "movl %%eax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_XORDWORD: __s = %08x, __d = %08x", __s, __d); \ - ia32_warning("XC_XORDWORD: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_XORDWORD: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ - ia32_warning("XC_XORDWORD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_NEG(d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_NEG((d), (s)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "negb %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_NEG: __s = %02x", __s); \ - ia32_warning("XC_BYTE_NEG: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_NEG: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_BYTE_NEG: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_NEG(d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_NEG((d), (s)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "negw %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_NEG: __s = %04x", __s); \ - ia32_warning("XC_WORD_NEG: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_NEG: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_WORD_NEG: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_NEG(d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_NEG((d), (s)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "negl %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_NEG: __s = %08x", __s);\ - ia32_warning("XC_DWORD_NEG: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_NEG: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ - ia32_warning("XC_DWORD_NEG: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_MUL(r, d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __d = (d) & 0xff; \ - UINT16 __r; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_MUL((r), (d), (s)); \ - __R = (r) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movb %3, %%al\n\t" \ - "movb %4, %%ah\n\t" \ - "mulb %%ah\n\t" \ - "movw %%ax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "m" (__d), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_MUL: __s = %02x, __d = %02x", __s, __d); \ - ia32_warning("XC_BYTE_MUL: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_MUL: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_BYTE_MUL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_MUL(r, d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __d = (d) & 0xffff; \ - UINT32 __r; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_MUL((r), (d), (s)); \ - __R = (r); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "push %%edx\n\t" \ - "movw %3, %%ax\n\t" \ - "movw %4, %%dx\n\t" \ - "mulw %%dx\n\t" \ - "movw %%ax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "andl $0x0000ffff, %0\n\t" \ - "shll $16, %%edx\n\t" \ - "orl %%edx, %0\n\t" \ - "popl %%edx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "m" (__d), "m" (__s) \ - : "eax", "edx"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_MUL: __s = %04x, __d = %04x", __s, __d); \ - ia32_warning("XC_WORD_MUL: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_WORD_MUL: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_WORD_MUL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_MUL(r, d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __d = (d); \ - UINT32 __r; \ - UINT32 __h; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_MUL((r), (d), (s)); \ - __R = (r); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "push %%edx\n\t" \ - "movl %4, %%eax\n\t" \ - "movl %5, %%edx\n\t" \ - "mull %%edx\n\t" \ - "movl %%eax, %0\n\t" \ - "movl %%edx, %1\n\t" \ - "lahf\n\t" \ - "movb %%ah, %2\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %3\n\t" \ - "popl %%edx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__h), "=m" (__f), "=m" (__o) \ - : "m" (__d), "m" (__s) \ - : "eax", "edx"); \ - if ((__R != __r) || \ - (CPU_OV != __h) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_MUL: __s = %08x, __d = %08x", __s, __d);\ - ia32_warning("XC_DWORD_MUL: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_MUL: CPU_OV == %08x, __h == %08x", \ - CPU_OV, __h); \ - ia32_warning("XC_DWORD_MUL: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_DWORD_MUL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_IMUL(r, d, s) \ -do { \ - SINT8 __s = (s) & 0xff; \ - SINT8 __d = (d) & 0xff; \ - SINT16 __R; \ - SINT16 __r; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_IMUL((r), (d), (s)); \ - __R = (r) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "movb %3, %%al\n\t" \ - "movb %4, %%ah\n\t" \ - "imulb %%ah\n\t" \ - "movw %%ax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "m" (__d), "m" (__s) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_IMUL: __s = %02x, __d = %02x", __s, __d);\ - ia32_warning("XC_BYTE_IMUL: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_BYTE_IMUL: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_BYTE_IMUL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_IMUL(r, d, s) \ -do { \ - SINT16 __s = (s) & 0xffff; \ - SINT16 __d = (d) & 0xffff; \ - SINT32 __r; \ - SINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_IMUL((r), (d), (s)); \ - __R = (r); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "push %%edx\n\t" \ - "movw %3, %%ax\n\t" \ - "movw %4, %%dx\n\t" \ - "imulw %%dx\n\t" \ - "movw %%ax, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "andl $0x0000ffff, %0\n\t" \ - "shll $16, %%edx\n\t" \ - "orl %%edx, %0\n\t" \ - "popl %%edx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "m" (__d), "m" (__s) \ - : "eax", "edx"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_IMUL: __s = %04x, __d = %04x", __s, __d);\ - ia32_warning("XC_WORD_IMUL: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_WORD_IMUL: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_WORD_IMUL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_IMUL(r, d, s) \ -do { \ - SINT64 __R; \ - SINT32 __s = (s); \ - SINT32 __d = (d); \ - UINT32 __r; \ - UINT32 __h; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_IMUL((r), (d), (s)); \ - __R = (r); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "push %%edx\n\t" \ - "movl %4, %%eax\n\t" \ - "movl %5, %%edx\n\t" \ - "imull %%edx\n\t" \ - "movl %%eax, %0\n\t" \ - "movl %%edx, %1\n\t" \ - "lahf\n\t" \ - "movb %%ah, %2\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %3\n\t" \ - "popl %%edx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__h), "=m" (__f), "=m" (__o) \ - : "m" (__d), "m" (__s) \ - : "eax", "edx"); \ - if (((UINT32)__R != __r) || \ - ((UINT32)(__R >> 32) != __h) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_IMUL: __s = %08x, __d = %08x",__s, __d);\ - ia32_warning("XC_DWORD_IMUL: __Rl = %08x, __r = %08x", \ - (UINT32)__R, __r); \ - ia32_warning("XC_DWORD_IMUL: __Rh == %08x, __h == %08x", \ - (UINT32)(__R >> 32), __h); \ - ia32_warning("XC_DWORD_IMUL: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_DWORD_IMUL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert((UINT32)__R == __r); \ - assert((UINT32)(__R >> 32) == __h); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -/* flag no check */ -#define XC_BYTE_INC(s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_INC((s)); \ - __R = (s) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "incb %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_INC: __s = %02x", __s); \ - ia32_warning("XC_BYTE_INC: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_INC: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ - ia32_warning("XC_BYTE_INC: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_INC(s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_INC((s)); \ - __R = (s) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "incw %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_INC: __s = %04x", __s); \ - ia32_warning("XC_WORD_INC: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_INC: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ - ia32_warning("XC_WORD_INC: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_INC(s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_INC((s)); \ - __R = (s); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "incl %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_INC: __s = %08x", __s); \ - ia32_warning("XC_DWORD_INC: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_INC: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ - ia32_warning("XC_DWORD_INC: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -/* flag no check */ -#define XC_BYTE_DEC(s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_DEC((s)); \ - __R = (s) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "decb %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_DEC: __s = %02x", __s); \ - ia32_warning("XC_BYTE_DEC: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_DEC: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ - ia32_warning("XC_BYTE_DEC: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_DEC(s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_DEC((s)); \ - __R = (s) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "decw %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_DEC: __s = %04x", __s); \ - ia32_warning("XC_WORD_DEC: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_DEC: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ - ia32_warning("XC_WORD_DEC: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_DEC(s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_DEC((s)); \ - __R = (s); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "push %%eax\n\t" \ - "decl %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_DEC: __s = %08x", __s); \ - ia32_warning("XC_DWORD_DEC: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_DEC: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ - ia32_warning("XC_DWORD_DEC: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define BYTE_ADD(r, d, s) XC_ADD_BYTE(r, d, s) -#define WORD_ADD(r, d, s) XC_ADD_WORD(r, d, s) -#define DWORD_ADD(r, d, s) XC_ADD_DWORD(r, d, s) -#define BYTE_OR(d, s) XC_OR_BYTE(d, s) -#define WORD_OR(d, s) XC_OR_WORD(d, s) -#define DWORD_OR(d, s) XC_OR_DWORD(d, s) -#define BYTE_ADC(r, d, s) XC_ADC_BYTE(r, d, s) -#define WORD_ADC(r, d, s) XC_ADC_WORD(r, d, s) -#define DWORD_ADC(r, d, s) XC_ADC_DWORD(r, d, s) -#define BYTE_SBB(r, d, s) XC_BYTE_SBB(r, d, s) -#define WORD_SBB(r, d, s) XC_WORD_SBB(r, d, s) -#define DWORD_SBB(r, d, s) XC_DWORD_SBB(r, d, s) -#define BYTE_AND(d, s) XC_AND_BYTE(d, s) -#define WORD_AND(d, s) XC_AND_WORD(d, s) -#define DWORD_AND(d, s) XC_AND_DWORD(d, s) -#define BYTE_SUB(r, d, s) XC_BYTE_SUB(r, d, s) -#define WORD_SUB(r, d, s) XC_WORD_SUB(r, d, s) -#define DWORD_SUB(r, d, s) XC_DWORD_SUB(r, d, s) -#define BYTE_XOR(d, s) XC_BYTE_XOR(d, s) -#define WORD_XOR(d, s) XC_WORD_XOR(d, s) -#define DWORD_XOR(d, s) XC_DWORD_XOR(d, s) -#define BYTE_NEG(d, s) XC_BYTE_NEG(d, s) -#define WORD_NEG(d, s) XC_WORD_NEG(d, s) -#define DWORD_NEG(d, s) XC_DWORD_NEG(d, s) -#define BYTE_MUL(r, d, s) XC_BYTE_MUL(r, d, s) -#define WORD_MUL(r, d, s) XC_WORD_MUL(r, d, s) -#define DWORD_MUL(r, d, s) XC_DWORD_MUL(r, d, s) -#define BYTE_IMUL(r, d, s) XC_BYTE_IMUL(r, d, s) -#define WORD_IMUL(r, d, s) XC_WORD_IMUL(r, d, s) -#define DWORD_IMUL(r, d, s) XC_DWORD_IMUL(r, d, s) -#define BYTE_INC(s) XC_BYTE_INC(s) -#define WORD_INC(s) XC_WORD_INC(s) -#define DWORD_INC(s) XC_DWORD_INC(s) -#define BYTE_DEC(s) XC_BYTE_DEC(s) -#define WORD_DEC(s) XC_WORD_DEC(s) -#define DWORD_DEC(s) XC_DWORD_DEC(s) - -#define ADD_BYTE(r, d, s) XC_ADD_BYTE(r, d, s) -#define ADD_WORD(r, d, s) XC_ADD_WORD(r, d, s) -#define ADD_DWORD(r, d, s) XC_ADD_DWORD(r, d, s) -#define OR_BYTE(d, s) XC_OR_BYTE(d, s) -#define OR_WORD(d, s) XC_OR_WORD(d, s) -#define OR_DWORD(d, s) XC_OR_DWORD(d, s) -#define ADC_BYTE(r, d, s) XC_ADC_BYTE(r, d, s) -#define ADC_WORD(r, d, s) XC_ADC_WORD(r, d, s) -#define ADC_DWORD(r, d, s) XC_ADC_DWORD(r, d, s) -#define AND_BYTE(d, s) XC_AND_BYTE(d, s) -#define AND_WORD(d, s) XC_AND_WORD(d, s) -#define AND_DWORD(d, s) XC_AND_DWORD(d, s) - -#define XC_STORE_FLAGL() UINT8 __xc_flagl = CPU_FLAGL - -#elif defined(IA32_CROSS_CHECK) && defined(_MSC_VER) - -#include "ia32xc_msc.mcr" - -#else /* !(IA32_CROSS_CHECK && __GNUC__ && (i386) || __i386__)) */ - -#define BYTE_ADD(r, d, s) _ADD_BYTE(r, d, s) -#define WORD_ADD(r, d, s) _ADD_WORD(r, d, s) -#define DWORD_ADD(r, d, s) _ADD_DWORD(r, d, s) -#define BYTE_OR(d, s) _OR_BYTE(d, s) -#define WORD_OR(d, s) _OR_WORD(d, s) -#define DWORD_OR(d, s) _OR_DWORD(d, s) -#define BYTE_ADC(r, d, s) _ADC_BYTE(r, d, s) -#define WORD_ADC(r, d, s) _ADC_WORD(r, d, s) -#define DWORD_ADC(r, d, s) _ADC_DWORD(r, d, s) -#define BYTE_SBB(r, d, s) _BYTE_SBB(r, d, s) -#define WORD_SBB(r, d, s) _WORD_SBB(r, d, s) -#define DWORD_SBB(r, d, s) _DWORD_SBB(r, d, s) -#define BYTE_AND(d, s) _AND_BYTE(d, s) -#define WORD_AND(d, s) _AND_WORD(d, s) -#define DWORD_AND(d, s) _AND_DWORD(d, s) -#define BYTE_SUB(r, d, s) _BYTE_SUB(r, d, s) -#define WORD_SUB(r, d, s) _WORD_SUB(r, d, s) -#define DWORD_SUB(r, d, s) _DWORD_SUB(r, d, s) -#define BYTE_XOR(d, s) _BYTE_XOR(d, s) -#define WORD_XOR(d, s) _WORD_XOR(d, s) -#define DWORD_XOR(d, s) _DWORD_XOR(d, s) -#define BYTE_NEG(d, s) _BYTE_NEG(d, s) -#define WORD_NEG(d, s) _WORD_NEG(d, s) -#define DWORD_NEG(d, s) _DWORD_NEG(d, s) -#define BYTE_MUL(r, d, s) _BYTE_MUL(r, d, s) -#define WORD_MUL(r, d, s) _WORD_MUL(r, d, s) -#define DWORD_MUL(r, d, s) _DWORD_MUL(r, d, s) -#define BYTE_IMUL(r, d, s) _BYTE_IMUL(r, d, s) -#define WORD_IMUL(r, d, s) _WORD_IMUL(r, d, s) -#define DWORD_IMUL(r, d, s) _DWORD_IMUL(r, d, s) -#define BYTE_INC(s) _BYTE_INC(s) -#define WORD_INC(s) _WORD_INC(s) -#define DWORD_INC(s) _DWORD_INC(s) -#define BYTE_DEC(s) _BYTE_DEC(s) -#define WORD_DEC(s) _WORD_DEC(s) -#define DWORD_DEC(s) _DWORD_DEC(s) - -#define ADD_BYTE(r, d, s) _ADD_BYTE(r, d, s) -#define ADD_WORD(r, d, s) _ADD_WORD(r, d, s) -#define ADD_DWORD(r, d, s) _ADD_DWORD(r, d, s) -#define OR_BYTE(d, s) _OR_BYTE(d, s) -#define OR_WORD(d, s) _OR_WORD(d, s) -#define OR_DWORD(d, s) _OR_DWORD(d, s) -#define ADC_BYTE(r, d, s) _ADC_BYTE(r, d, s) -#define ADC_WORD(r, d, s) _ADC_WORD(r, d, s) -#define ADC_DWORD(r, d, s) _ADC_DWORD(r, d, s) -#define AND_BYTE(d, s) _AND_BYTE(d, s) -#define AND_WORD(d, s) _AND_WORD(d, s) -#define AND_DWORD(d, s) _AND_DWORD(d, s) - -#define XC_STORE_FLAGL() - -#endif /* IA32_CROSS_CHECK && GCC_CPU_ARCH_IA32 */ - -#endif /* IA32_CPU_IA32_MCR__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_IA32XC_MCR__ +#define IA32_CPU_IA32XC_MCR__ + +#if defined(IA32_CROSS_CHECK) && defined(GCC_CPU_ARCH_IA32) + +#define IA32_CPU_ENABLE_XC + +/* + * arith + */ +#define XC_ADD_BYTE(r, d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __d = (d) & 0xff; \ + UINT8 __r = __d; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _ADD_BYTE((r), (d), (s)); \ + __R = (r) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushl %%eax\n\t" \ + "movb %3, %%al\n\t" \ + "addb %4, %%al\n\t" \ + "movb %%al, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_ADD_BYTE: __s = %02x, __d = %02x", __s, __d); \ + ia32_warning("XC_ADD_BYTE: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_ADD_BYTE: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_ADD_BYTE: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_ADD_WORD(r, d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __d = (d) & 0xffff; \ + UINT16 __r = __d; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _ADD_WORD((r), (d), (s)); \ + __R = (r) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushl %%eax\n\t" \ + "movw %3, %%ax\n\t" \ + "addw %4, %%ax\n\t" \ + "movw %%ax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax", "ecx"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_ADD_WORD: __s = %04x, __d = %04x", __s, __d); \ + ia32_warning("XC_ADD_WORD: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_ADD_WORD: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_ADD_WORD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_ADD_DWORD(r, d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __d = (d); \ + UINT32 __r = __d; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _ADD_DWORD((r), (d), (s)); \ + __R = (r); \ + \ + __asm__ __volatile__ ( \ + "pushl %%eax\n\t" \ + "movl %3, %%eax\n\t" \ + "addl %4, %%eax\n\t" \ + "movl %%eax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax", "ecx"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_ADD_DWORD: __s = %08x, __d = %08x", __s, __d);\ + ia32_warning("XC_ADD_DWORD: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_ADD_DWORD: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_ADD_DWORD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_OR_BYTE(d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __d = (d) & 0xff; \ + UINT8 __r = __d; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _OR_BYTE((d), (s)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushl %%eax\n\t" \ + "movb %3, %%al\n\t" \ + "orb %4, %%al\n\t" \ + "movb %%al, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_OR_BYTE: __s = %02x, __d = %02x", __s, __d); \ + ia32_warning("XC_OR_BYTE: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_OR_BYTE: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ + ia32_warning("XC_OR_BYTE: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_OR_WORD(d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __d = (d) & 0xffff; \ + UINT16 __r = __d; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _OR_WORD((d), (s)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushl %%eax\n\t" \ + "movw %3, %%ax\n\t" \ + "orw %4, %%ax\n\t" \ + "movw %%ax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_OR_WORD: __s = %04x, __d = %04x", __s, __d); \ + ia32_warning("XC_OR_WORD: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_OR_WORD: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ + ia32_warning("XC_OR_WORD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_OR_DWORD(d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __d = (d); \ + UINT32 __r = __d; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _OR_DWORD((d), (s)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushl %%eax\n\t" \ + "movl %3, %%eax\n\t" \ + "orl %4, %%eax\n\t" \ + "movl %%eax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_OR_DWORD: __s = %08x, __d = %08x", __s, __d); \ + ia32_warning("XC_OR_DWORD: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_OR_DWORD: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ + ia32_warning("XC_OR_DWORD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +/* flag no check */ +#define XC_ADC_BYTE(r, d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __d = (d) & 0xff; \ + UINT8 __r = __d; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _ADC_BYTE((r), (d), (s)); \ + __R = (r) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "movb %3, %%al\n\t" \ + "adcb %4, %%al\n\t" \ + "movb %%al, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_ADC_BYTE: __s = %02x, __d = %02x", __s, __d); \ + ia32_warning("XC_ADC_BYTE: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_ADC_BYTE: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_ADC_BYTE: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_ADC_WORD(r, d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __d = (d) & 0xffff; \ + UINT16 __r = __d; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _ADC_WORD((r), (d), (s)); \ + __R = (r) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "movw %3, %%ax\n\t" \ + "adcw %4, %%ax\n\t" \ + "movw %%ax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_ADC_WORD: __s = %04x, __d = %04x", __s, __d); \ + ia32_warning("XC_ADC_WORD: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_ADC_WORD: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_ADC_WORD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_ADC_DWORD(r, d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __d = (d); \ + UINT32 __r = __d; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _ADC_DWORD((r), (d), (s)); \ + __R = (r); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "movl %3, %%eax\n\t" \ + "adcl %4, %%eax\n\t" \ + "movl %%eax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_ADC_DWORD: __s = %08x, __d = %08x", __s, __d);\ + ia32_warning("XC_ADC_DWORD: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_ADC_DWORD: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_ADC_DWORD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +/* flag no check */ +#define XC_BYTE_SBB(r, d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __d = (d) & 0xff; \ + UINT8 __r = __d; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _BYTE_SBB((r), (d), (s)); \ + __R = (r) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "movb %3, %%al\n\t" \ + "sbbb %4, %%al\n\t" \ + "movb %%al, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_SBB: __s = %02x, __d = %02x", __s, __d); \ + ia32_warning("XC_BYTE_SBB: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_SBB: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_BYTE_SBB: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_SBB(r, d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __d = (d) & 0xffff; \ + UINT16 __r = __d; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _WORD_SBB((r), (d), (s)); \ + __R = (r) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "movw %3, %%ax\n\t" \ + "sbbw %4, %%ax\n\t" \ + "movw %%ax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_SBB: __s = %04x, __d = %04x", __s, __d); \ + ia32_warning("XC_WORD_SBB: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_SBB: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_WORD_SBB: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_SBB(r, d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __d = (d); \ + UINT32 __r = __d; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _DWORD_SBB((r), (d), (s)); \ + __R = (r); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "movl %3, %%eax\n\t" \ + "sbbl %4, %%eax\n\t" \ + "movl %%eax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_SBB: __s = %08x, __d = %08x", __s, __d);\ + ia32_warning("XC_DWORD_SBB: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_SBB: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_DWORD_SBB: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_AND_BYTE(d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __d = (d) & 0xff; \ + UINT8 __r = __d; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _AND_BYTE((d), (s)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movb %3, %%al\n\t" \ + "andb %4, %%al\n\t" \ + "movb %%al, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_ANDBYTE: __s = %02x, __d = %02x", __s, __d); \ + ia32_warning("XC_ANDBYTE: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_ANDBYTE: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ + ia32_warning("XC_ANDBYTE: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_AND_WORD(d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __d = (d) & 0xffff; \ + UINT16 __r = __d; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _AND_WORD((d), (s)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movw %3, %%ax\n\t" \ + "andw %4, %%ax\n\t" \ + "movw %%ax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_ANDWORD: __s = %04x, __d = %04x", __s, __d); \ + ia32_warning("XC_ANDWORD: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_ANDWORD: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ + ia32_warning("XC_ANDWORD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_AND_DWORD(d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __d = (d); \ + UINT32 __r = __d; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _AND_DWORD((d), (s)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movl %3, %%eax\n\t" \ + "andl %4, %%eax\n\t" \ + "movl %%eax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_ANDDWORD: __s = %08x, __d = %08x", __s, __d); \ + ia32_warning("XC_ANDDWORD: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_ANDDWORD: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ + ia32_warning("XC_ANDDWORD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_SUB(r, d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __d = (d) & 0xff; \ + UINT8 __r = __d; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_SUB((r), (d), (s)); \ + __R = (r) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movb %3, %%al\n\t" \ + "subb %4, %%al\n\t" \ + "movb %%al, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_SUB: __s = %02x, __d = %02x", __s, __d); \ + ia32_warning("XC_BYTE_SUB: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_SUB: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_BYTE_SUB: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_SUB(r, d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __d = (d) & 0xffff; \ + UINT16 __r = __d; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_SUB((r), (d), (s)); \ + __R = (r) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movw %3, %%ax\n\t" \ + "subw %4, %%ax\n\t" \ + "movw %%ax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_SUB: __s = %04x, __d = %04x", __s, __d); \ + ia32_warning("XC_WORD_SUB: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_SUB: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_WORD_SUB: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_SUB(r, d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __d = (d); \ + UINT32 __r = __d; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_SUB((r), (d), (s)); \ + __R = (r); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movl %3, %%eax\n\t" \ + "subl %4, %%eax\n\t" \ + "movl %%eax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_SUB: __s = %08x, __d = %08x", __s, __d);\ + ia32_warning("XC_DWORD_SUB: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_SUB: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_DWORD_SUB: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_XOR(d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __d = (d) & 0xff; \ + UINT8 __r = __d; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_XOR((d), (s)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movb %3, %%al\n\t" \ + "xorb %4, %%al\n\t" \ + "movb %%al, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_XORBYTE: __s = %02x, __d = %02x", __s, __d); \ + ia32_warning("XC_XORBYTE: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_XORBYTE: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ + ia32_warning("XC_XORBYTE: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_XOR(d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __d = (d) & 0xffff; \ + UINT16 __r = __d; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_XOR((d), (s)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movw %3, %%ax\n\t" \ + "xorw %4, %%ax\n\t" \ + "movw %%ax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_XORWORD: __s = %04x, __d = %04x", __s, __d); \ + ia32_warning("XC_XORWORD: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_XORWORD: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ + ia32_warning("XC_XORWORD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_XOR(d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __d = (d); \ + UINT32 __r = __d; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_XOR((d), (s)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movl %3, %%eax\n\t" \ + "xorl %4, %%eax\n\t" \ + "movl %%eax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_XORDWORD: __s = %08x, __d = %08x", __s, __d); \ + ia32_warning("XC_XORDWORD: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_XORDWORD: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZP_FLAG); \ + ia32_warning("XC_XORDWORD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_NEG(d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_NEG((d), (s)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "negb %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_NEG: __s = %02x", __s); \ + ia32_warning("XC_BYTE_NEG: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_NEG: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_BYTE_NEG: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_NEG(d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_NEG((d), (s)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "negw %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_NEG: __s = %04x", __s); \ + ia32_warning("XC_WORD_NEG: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_NEG: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_WORD_NEG: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_NEG(d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_NEG((d), (s)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "negl %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_NEG: __s = %08x", __s);\ + ia32_warning("XC_DWORD_NEG: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_NEG: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); \ + ia32_warning("XC_DWORD_NEG: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_MUL(r, d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __d = (d) & 0xff; \ + UINT16 __r; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_MUL((r), (d), (s)); \ + __R = (r) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movb %3, %%al\n\t" \ + "movb %4, %%ah\n\t" \ + "mulb %%ah\n\t" \ + "movw %%ax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "m" (__d), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_MUL: __s = %02x, __d = %02x", __s, __d); \ + ia32_warning("XC_BYTE_MUL: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_MUL: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_BYTE_MUL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_MUL(r, d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __d = (d) & 0xffff; \ + UINT32 __r; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_MUL((r), (d), (s)); \ + __R = (r); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "push %%edx\n\t" \ + "movw %3, %%ax\n\t" \ + "movw %4, %%dx\n\t" \ + "mulw %%dx\n\t" \ + "movw %%ax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "andl $0x0000ffff, %0\n\t" \ + "shll $16, %%edx\n\t" \ + "orl %%edx, %0\n\t" \ + "popl %%edx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "m" (__d), "m" (__s) \ + : "eax", "edx"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_MUL: __s = %04x, __d = %04x", __s, __d); \ + ia32_warning("XC_WORD_MUL: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_WORD_MUL: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_WORD_MUL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_MUL(r, d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __d = (d); \ + UINT32 __r; \ + UINT32 __h; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_MUL((r), (d), (s)); \ + __R = (r); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "push %%edx\n\t" \ + "movl %4, %%eax\n\t" \ + "movl %5, %%edx\n\t" \ + "mull %%edx\n\t" \ + "movl %%eax, %0\n\t" \ + "movl %%edx, %1\n\t" \ + "lahf\n\t" \ + "movb %%ah, %2\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %3\n\t" \ + "popl %%edx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__h), "=m" (__f), "=m" (__o) \ + : "m" (__d), "m" (__s) \ + : "eax", "edx"); \ + if ((__R != __r) || \ + (CPU_OV != __h) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_MUL: __s = %08x, __d = %08x", __s, __d);\ + ia32_warning("XC_DWORD_MUL: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_MUL: CPU_OV == %08x, __h == %08x", \ + CPU_OV, __h); \ + ia32_warning("XC_DWORD_MUL: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_DWORD_MUL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_IMUL(r, d, s) \ +do { \ + SINT8 __s = (s) & 0xff; \ + SINT8 __d = (d) & 0xff; \ + SINT16 __R; \ + SINT16 __r; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_IMUL((r), (d), (s)); \ + __R = (r) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "movb %3, %%al\n\t" \ + "movb %4, %%ah\n\t" \ + "imulb %%ah\n\t" \ + "movw %%ax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "m" (__d), "m" (__s) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_IMUL: __s = %02x, __d = %02x", __s, __d);\ + ia32_warning("XC_BYTE_IMUL: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_BYTE_IMUL: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_BYTE_IMUL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_IMUL(r, d, s) \ +do { \ + SINT16 __s = (s) & 0xffff; \ + SINT16 __d = (d) & 0xffff; \ + SINT32 __r; \ + SINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_IMUL((r), (d), (s)); \ + __R = (r); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "push %%edx\n\t" \ + "movw %3, %%ax\n\t" \ + "movw %4, %%dx\n\t" \ + "imulw %%dx\n\t" \ + "movw %%ax, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "andl $0x0000ffff, %0\n\t" \ + "shll $16, %%edx\n\t" \ + "orl %%edx, %0\n\t" \ + "popl %%edx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "m" (__d), "m" (__s) \ + : "eax", "edx"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_IMUL: __s = %04x, __d = %04x", __s, __d);\ + ia32_warning("XC_WORD_IMUL: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_WORD_IMUL: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_WORD_IMUL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_IMUL(r, d, s) \ +do { \ + SINT64 __R; \ + SINT32 __s = (s); \ + SINT32 __d = (d); \ + UINT32 __r; \ + UINT32 __h; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_IMUL((r), (d), (s)); \ + __R = (r); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "push %%edx\n\t" \ + "movl %4, %%eax\n\t" \ + "movl %5, %%edx\n\t" \ + "imull %%edx\n\t" \ + "movl %%eax, %0\n\t" \ + "movl %%edx, %1\n\t" \ + "lahf\n\t" \ + "movb %%ah, %2\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %3\n\t" \ + "popl %%edx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__h), "=m" (__f), "=m" (__o) \ + : "m" (__d), "m" (__s) \ + : "eax", "edx"); \ + if (((UINT32)__R != __r) || \ + ((UINT32)(__R >> 32) != __h) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_IMUL: __s = %08x, __d = %08x",__s, __d);\ + ia32_warning("XC_DWORD_IMUL: __Rl = %08x, __r = %08x", \ + (UINT32)__R, __r); \ + ia32_warning("XC_DWORD_IMUL: __Rh == %08x, __h == %08x", \ + (UINT32)(__R >> 32), __h); \ + ia32_warning("XC_DWORD_IMUL: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_DWORD_IMUL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert((UINT32)__R == __r); \ + assert((UINT32)(__R >> 32) == __h); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +/* flag no check */ +#define XC_BYTE_INC(s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_INC((s)); \ + __R = (s) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "incb %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_INC: __s = %02x", __s); \ + ia32_warning("XC_BYTE_INC: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_INC: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ + ia32_warning("XC_BYTE_INC: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_INC(s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_INC((s)); \ + __R = (s) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "incw %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_INC: __s = %04x", __s); \ + ia32_warning("XC_WORD_INC: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_INC: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ + ia32_warning("XC_WORD_INC: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_INC(s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_INC((s)); \ + __R = (s); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "incl %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_INC: __s = %08x", __s); \ + ia32_warning("XC_DWORD_INC: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_INC: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ + ia32_warning("XC_DWORD_INC: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +/* flag no check */ +#define XC_BYTE_DEC(s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_DEC((s)); \ + __R = (s) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "decb %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_DEC: __s = %02x", __s); \ + ia32_warning("XC_BYTE_DEC: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_DEC: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ + ia32_warning("XC_BYTE_DEC: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_DEC(s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_DEC((s)); \ + __R = (s) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "decw %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_DEC: __s = %04x", __s); \ + ia32_warning("XC_WORD_DEC: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_DEC: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ + ia32_warning("XC_WORD_DEC: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_DEC(s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_DEC((s)); \ + __R = (s); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "push %%eax\n\t" \ + "decl %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZAP_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_DEC: __s = %08x", __s); \ + ia32_warning("XC_DWORD_DEC: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_DEC: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZAP_FLAG); \ + ia32_warning("XC_DWORD_DEC: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZAP_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define BYTE_ADD(r, d, s) XC_ADD_BYTE(r, d, s) +#define WORD_ADD(r, d, s) XC_ADD_WORD(r, d, s) +#define DWORD_ADD(r, d, s) XC_ADD_DWORD(r, d, s) +#define BYTE_OR(d, s) XC_OR_BYTE(d, s) +#define WORD_OR(d, s) XC_OR_WORD(d, s) +#define DWORD_OR(d, s) XC_OR_DWORD(d, s) +#define BYTE_ADC(r, d, s) XC_ADC_BYTE(r, d, s) +#define WORD_ADC(r, d, s) XC_ADC_WORD(r, d, s) +#define DWORD_ADC(r, d, s) XC_ADC_DWORD(r, d, s) +#define BYTE_SBB(r, d, s) XC_BYTE_SBB(r, d, s) +#define WORD_SBB(r, d, s) XC_WORD_SBB(r, d, s) +#define DWORD_SBB(r, d, s) XC_DWORD_SBB(r, d, s) +#define BYTE_AND(d, s) XC_AND_BYTE(d, s) +#define WORD_AND(d, s) XC_AND_WORD(d, s) +#define DWORD_AND(d, s) XC_AND_DWORD(d, s) +#define BYTE_SUB(r, d, s) XC_BYTE_SUB(r, d, s) +#define WORD_SUB(r, d, s) XC_WORD_SUB(r, d, s) +#define DWORD_SUB(r, d, s) XC_DWORD_SUB(r, d, s) +#define BYTE_XOR(d, s) XC_BYTE_XOR(d, s) +#define WORD_XOR(d, s) XC_WORD_XOR(d, s) +#define DWORD_XOR(d, s) XC_DWORD_XOR(d, s) +#define BYTE_NEG(d, s) XC_BYTE_NEG(d, s) +#define WORD_NEG(d, s) XC_WORD_NEG(d, s) +#define DWORD_NEG(d, s) XC_DWORD_NEG(d, s) +#define BYTE_MUL(r, d, s) XC_BYTE_MUL(r, d, s) +#define WORD_MUL(r, d, s) XC_WORD_MUL(r, d, s) +#define DWORD_MUL(r, d, s) XC_DWORD_MUL(r, d, s) +#define BYTE_IMUL(r, d, s) XC_BYTE_IMUL(r, d, s) +#define WORD_IMUL(r, d, s) XC_WORD_IMUL(r, d, s) +#define DWORD_IMUL(r, d, s) XC_DWORD_IMUL(r, d, s) +#define BYTE_INC(s) XC_BYTE_INC(s) +#define WORD_INC(s) XC_WORD_INC(s) +#define DWORD_INC(s) XC_DWORD_INC(s) +#define BYTE_DEC(s) XC_BYTE_DEC(s) +#define WORD_DEC(s) XC_WORD_DEC(s) +#define DWORD_DEC(s) XC_DWORD_DEC(s) + +#define ADD_BYTE(r, d, s) XC_ADD_BYTE(r, d, s) +#define ADD_WORD(r, d, s) XC_ADD_WORD(r, d, s) +#define ADD_DWORD(r, d, s) XC_ADD_DWORD(r, d, s) +#define OR_BYTE(d, s) XC_OR_BYTE(d, s) +#define OR_WORD(d, s) XC_OR_WORD(d, s) +#define OR_DWORD(d, s) XC_OR_DWORD(d, s) +#define ADC_BYTE(r, d, s) XC_ADC_BYTE(r, d, s) +#define ADC_WORD(r, d, s) XC_ADC_WORD(r, d, s) +#define ADC_DWORD(r, d, s) XC_ADC_DWORD(r, d, s) +#define AND_BYTE(d, s) XC_AND_BYTE(d, s) +#define AND_WORD(d, s) XC_AND_WORD(d, s) +#define AND_DWORD(d, s) XC_AND_DWORD(d, s) + +#define XC_STORE_FLAGL() UINT8 __xc_flagl = CPU_FLAGL + +#elif defined(IA32_CROSS_CHECK) && defined(_MSC_VER) + +#include "ia32xc_msc.mcr" + +#else /* !(IA32_CROSS_CHECK && __GNUC__ && (i386) || __i386__)) */ + +#define BYTE_ADD(r, d, s) _ADD_BYTE(r, d, s) +#define WORD_ADD(r, d, s) _ADD_WORD(r, d, s) +#define DWORD_ADD(r, d, s) _ADD_DWORD(r, d, s) +#define BYTE_OR(d, s) _OR_BYTE(d, s) +#define WORD_OR(d, s) _OR_WORD(d, s) +#define DWORD_OR(d, s) _OR_DWORD(d, s) +#define BYTE_ADC(r, d, s) _ADC_BYTE(r, d, s) +#define WORD_ADC(r, d, s) _ADC_WORD(r, d, s) +#define DWORD_ADC(r, d, s) _ADC_DWORD(r, d, s) +#define BYTE_SBB(r, d, s) _BYTE_SBB(r, d, s) +#define WORD_SBB(r, d, s) _WORD_SBB(r, d, s) +#define DWORD_SBB(r, d, s) _DWORD_SBB(r, d, s) +#define BYTE_AND(d, s) _AND_BYTE(d, s) +#define WORD_AND(d, s) _AND_WORD(d, s) +#define DWORD_AND(d, s) _AND_DWORD(d, s) +#define BYTE_SUB(r, d, s) _BYTE_SUB(r, d, s) +#define WORD_SUB(r, d, s) _WORD_SUB(r, d, s) +#define DWORD_SUB(r, d, s) _DWORD_SUB(r, d, s) +#define BYTE_XOR(d, s) _BYTE_XOR(d, s) +#define WORD_XOR(d, s) _WORD_XOR(d, s) +#define DWORD_XOR(d, s) _DWORD_XOR(d, s) +#define BYTE_NEG(d, s) _BYTE_NEG(d, s) +#define WORD_NEG(d, s) _WORD_NEG(d, s) +#define DWORD_NEG(d, s) _DWORD_NEG(d, s) +#define BYTE_MUL(r, d, s) _BYTE_MUL(r, d, s) +#define WORD_MUL(r, d, s) _WORD_MUL(r, d, s) +#define DWORD_MUL(r, d, s) _DWORD_MUL(r, d, s) +#define BYTE_IMUL(r, d, s) _BYTE_IMUL(r, d, s) +#define WORD_IMUL(r, d, s) _WORD_IMUL(r, d, s) +#define DWORD_IMUL(r, d, s) _DWORD_IMUL(r, d, s) +#define BYTE_INC(s) _BYTE_INC(s) +#define WORD_INC(s) _WORD_INC(s) +#define DWORD_INC(s) _DWORD_INC(s) +#define BYTE_DEC(s) _BYTE_DEC(s) +#define WORD_DEC(s) _WORD_DEC(s) +#define DWORD_DEC(s) _DWORD_DEC(s) + +#define ADD_BYTE(r, d, s) _ADD_BYTE(r, d, s) +#define ADD_WORD(r, d, s) _ADD_WORD(r, d, s) +#define ADD_DWORD(r, d, s) _ADD_DWORD(r, d, s) +#define OR_BYTE(d, s) _OR_BYTE(d, s) +#define OR_WORD(d, s) _OR_WORD(d, s) +#define OR_DWORD(d, s) _OR_DWORD(d, s) +#define ADC_BYTE(r, d, s) _ADC_BYTE(r, d, s) +#define ADC_WORD(r, d, s) _ADC_WORD(r, d, s) +#define ADC_DWORD(r, d, s) _ADC_DWORD(r, d, s) +#define AND_BYTE(d, s) _AND_BYTE(d, s) +#define AND_WORD(d, s) _AND_WORD(d, s) +#define AND_DWORD(d, s) _AND_DWORD(d, s) + +#define XC_STORE_FLAGL() + +#endif /* IA32_CROSS_CHECK && GCC_CPU_ARCH_IA32 */ + +#endif /* IA32_CPU_IA32_MCR__ */ diff --git a/i386c/ia32/ia32xc_msc.mcr b/i386c/ia32/ia32xc_msc.mcr old mode 100755 new mode 100644 index fb3cc9d6..287a6a28 --- a/i386c/ia32/ia32xc_msc.mcr +++ b/i386c/ia32/ia32xc_msc.mcr @@ -1,547 +1,547 @@ - -// Crosscheck for VC++ - -#define BYTE_ADC(r, d, s) { \ - UINT8 _d = (d); \ - UINT8 _s = (s); \ - UINT8 _r; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov al, _d } \ - __asm { adc al, _s } \ - __asm { mov _r, al } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _ADC_BYTE((r), (d), (s)); \ - if ((_r != (UINT8)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("adcb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_ADC(r, d, s) { \ - UINT16 _d = (d); \ - UINT16 _s = (s); \ - UINT16 _r; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov ax, _d } \ - __asm { adc ax, _s } \ - __asm { mov _r, ax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _ADC_WORD((r), (d), (s)); \ - if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("adcw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_ADC(r, d, s) { \ - UINT32 _d = (d); \ - UINT32 _s = (s); \ - UINT32 _r; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov eax, _d } \ - __asm { adc eax, _s } \ - __asm { mov _r, eax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _ADC_DWORD((r), (d), (s)); \ - if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("adcd r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_ADD(r, d, s) { \ - UINT8 _d = (d); \ - UINT8 _s = (s); \ - UINT8 _r; \ - UINT8 _f, _ov; \ - __asm { mov al, _d } \ - __asm { add al, _s } \ - __asm { mov _r, al } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _ADD_BYTE((r), (d), (s)); \ - if ((_r != (UINT8)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("addb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_ADD(r, d, s) { \ - UINT16 _d = (d); \ - UINT16 _s = (s); \ - UINT16 _r; \ - UINT8 _f, _ov; \ - __asm { mov ax, _d } \ - __asm { add ax, _s } \ - __asm { mov _r, ax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _ADD_WORD((r), (d), (s)); \ - if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("addw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_ADD(r, d, s) { \ - UINT32 _d = (d); \ - UINT32 _s = (s); \ - UINT32 _r; \ - UINT8 _f, _ov; \ - __asm { mov eax, _d } \ - __asm { add eax, _s } \ - __asm { mov _r, eax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _ADD_DWORD((r), (d), (s)); \ - if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("addd r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_AND(d, s) { \ - UINT8 _d = (d); \ - UINT8 _s = (s); \ - UINT8 _f, _ov; \ - __asm { mov al, _s } \ - __asm { and _d, al } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _AND_BYTE((d), (s)); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("andb r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_AND(d, s) { \ - UINT16 _d = (d); \ - UINT16 _s = (s); \ - UINT8 _f, _ov; \ - __asm { mov ax, _s } \ - __asm { and _d, ax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _AND_WORD((d), (s)); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("andw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_AND(d, s) { \ - UINT32 _d = (d); \ - UINT32 _s = (s); \ - UINT8 _f, _ov; \ - __asm { mov eax, _s } \ - __asm { and _d, eax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _AND_DWORD((d), (s)); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("andd r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_DEC(s) { \ - UINT8 _s = (s); \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { dec _s } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_DEC((s)); \ - if ((_s != (UINT8)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("decb r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_DEC(s) { \ - UINT16 _s = (s); \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { dec _s } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_DEC((s)); \ - if ((_s != (UINT16)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("decd r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_DEC(s) { \ - UINT32 _s = (s); \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { dec _s } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_DEC((s)); \ - if ((_s != (UINT32)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("decd r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_INC(s) { \ - UINT8 _s = (s); \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { inc _s } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_INC((s)); \ - if ((_s != (UINT8)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("incb r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_INC(s) { \ - UINT16 _s = (s); \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { inc _s } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_INC((s)); \ - if ((_s != (UINT16)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("incd r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_INC(s) { \ - UINT32 _s = (s); \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { inc _s } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_INC((s)); \ - if ((_s != (UINT32)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("incd r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_NEG(d, s) { \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - __asm { neg _d } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_NEG((d), (s)); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("negb r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_NEG(d, s) { \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - __asm { neg _d } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_NEG((d), (s)); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("negw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_NEG(d, s) { \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - __asm { neg _d } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_NEG((d), (s)); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("negd r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_OR(d, s) { \ - UINT8 _d = (d); \ - UINT8 _s = (s); \ - UINT8 _f, _ov; \ - __asm { mov al, _s } \ - __asm { or _d, al } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _OR_BYTE((d), (s)); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("orb r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_OR(d, s) { \ - UINT16 _d = (d); \ - UINT16 _s = (s); \ - UINT8 _f, _ov; \ - __asm { mov ax, _s } \ - __asm { or _d, ax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _OR_WORD((d), (s)); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("orw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_OR(d, s) { \ - UINT32 _d = (d); \ - UINT32 _s = (s); \ - UINT8 _f, _ov; \ - __asm { mov eax, _s } \ - __asm { or _d, eax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _OR_DWORD((d), (s)); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("ord r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_SBB(r, d, s) { \ - UINT8 _d = (d); \ - UINT8 _s = (s); \ - UINT8 _r; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov al, _d } \ - __asm { sbb al, _s } \ - __asm { mov _r, al } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_SBB((r), (d), (s)); \ - if ((_r != (UINT8)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sbbb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_SBB(r, d, s) { \ - UINT16 _d = (d); \ - UINT16 _s = (s); \ - UINT16 _r; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov ax, _d } \ - __asm { sbb ax, _s } \ - __asm { mov _r, ax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_SBB((r), (d), (s)); \ - if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sbbw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_SBB(r, d, s) { \ - UINT32 _d = (d); \ - UINT32 _s = (s); \ - UINT32 _r; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov eax, _d } \ - __asm { sbb eax, _s } \ - __asm { mov _r, eax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_SBB((r), (d), (s)); \ - if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sbbd r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_SUB(r, d, s) { \ - UINT8 _d = (d); \ - UINT8 _s = (s); \ - UINT8 _r; \ - UINT8 _f, _ov; \ - __asm { mov al, _d } \ - __asm { sub al, _s } \ - __asm { mov _r, al } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_SUB((r), (d), (s)); \ - if ((_r != (UINT8)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("subb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_SUB(r, d, s) { \ - UINT16 _d = (d); \ - UINT16 _s = (s); \ - UINT16 _r; \ - UINT8 _f, _ov; \ - __asm { mov ax, _d } \ - __asm { sub ax, _s } \ - __asm { mov _r, ax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_SUB((r), (d), (s)); \ - if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("subw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_SUB(r, d, s) { \ - UINT32 _d = (d); \ - UINT32 _s = (s); \ - UINT32 _r; \ - UINT8 _f, _ov; \ - __asm { mov eax, _d } \ - __asm { sub eax, _s } \ - __asm { mov _r, eax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_SUB((r), (d), (s)); \ - if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("subd r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_XOR(d, s) { \ - UINT8 _d = (d); \ - UINT8 _s = (s); \ - UINT8 _f, _ov; \ - __asm { mov al, _s } \ - __asm { xor _d, al } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_XOR((d), (s)); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("xorb r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_XOR(d, s) { \ - UINT16 _d = (d); \ - UINT16 _s = (s); \ - UINT8 _f, _ov; \ - __asm { mov ax, _s } \ - __asm { xor _d, ax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_XOR((d), (s)); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("xorw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_XOR(d, s) { \ - UINT32 _d = (d); \ - UINT32 _s = (s); \ - UINT8 _f, _ov; \ - __asm { mov eax, _s } \ - __asm { xor _d, eax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_XOR((d), (s)); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("xord r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - -// ---- - -#define BYTE_IMUL(r, d, s) { \ - UINT8 _d = (d); \ - UINT8 _s = (s); \ - UINT16 _r; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov al, _d } \ - __asm { imul _s } \ - __asm { mov _r, ax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_IMUL((r), (d), (s)); \ - if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("imulb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_IMUL(r, d, s) { \ - UINT16 _d = (d); \ - UINT16 _s = (s); \ - UINT16 _rl, _rh; \ - UINT32 _r; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov ax, _d } \ - __asm { imul _s } \ - __asm { mov _rl, ax } \ - __asm { mov _rh, dx } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _r = _rl + (_rh << 16); \ - _WORD_IMUL((r), (d), (s)); \ - if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("imulw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_IMUL(r, d, s) { \ - UINT32 _d = (d); \ - UINT32 _s = (s); \ - UINT32 _rl, _rh; \ - UINT64 _r; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov eax, _d } \ - __asm { imul _s } \ - __asm { mov _rl, eax } \ - __asm { mov _rh, edx } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _r = (UINT64)_rl + ((UINT64)_rh << 32); \ - _DWORD_IMUL((r), (d), (s)); \ - if ((_r != (UINT64)(r)) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("imuld r=%x%x:%x%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define BYTE_MUL(r, d, s) { \ - UINT8 _d = (d); \ - UINT8 _s = (s); \ - UINT16 _r; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov al, _d } \ - __asm { mul _s } \ - __asm { mov _r, ax } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_MUL((r), (d), (s)); \ - if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("mulb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_MUL(r, d, s) { \ - UINT16 _d = (d); \ - UINT16 _s = (s); \ - UINT16 _rl, _rh; \ - UINT32 _r; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov ax, _d } \ - __asm { mul _s } \ - __asm { mov _rl, ax } \ - __asm { mov _rh, dx } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _r = _rl + (_rh << 16); \ - _WORD_MUL((r), (d), (s)); \ - if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("mulw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_MUL(r, d, s) { \ - UINT32 _d = (d); \ - UINT32 _s = (s); \ - UINT32 _r, _o; \ - UINT8 _f, _ov; \ - __asm { bt CPU_FLAG, 0 } \ - __asm { mov eax, _d } \ - __asm { mul _s } \ - __asm { mov _r, eax } \ - __asm { mov _o, edx } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_MUL((r), (d), (s)); \ - if ((_r != (UINT32)(r)) || (_o != CPU_OV) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("muld r=%x%x:%x%x f=%x:%x o=%d %d", _o, _r, CPU_OV, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - -// ---- - -#define AND_BYTE(d, s) BYTE_AND(d, s) -#define AND_WORD(d, s) WORD_AND(d, s) -#define AND_DWORD(d, s) DWORD_AND(d, s) - -#define XC_STORE_FLAGL() - + +// Crosscheck for VC++ + +#define BYTE_ADC(r, d, s) { \ + UINT8 _d = (d); \ + UINT8 _s = (s); \ + UINT8 _r; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov al, _d } \ + __asm { adc al, _s } \ + __asm { mov _r, al } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _ADC_BYTE((r), (d), (s)); \ + if ((_r != (UINT8)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("adcb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_ADC(r, d, s) { \ + UINT16 _d = (d); \ + UINT16 _s = (s); \ + UINT16 _r; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov ax, _d } \ + __asm { adc ax, _s } \ + __asm { mov _r, ax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _ADC_WORD((r), (d), (s)); \ + if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("adcw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_ADC(r, d, s) { \ + UINT32 _d = (d); \ + UINT32 _s = (s); \ + UINT32 _r; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov eax, _d } \ + __asm { adc eax, _s } \ + __asm { mov _r, eax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _ADC_DWORD((r), (d), (s)); \ + if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("adcd r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_ADD(r, d, s) { \ + UINT8 _d = (d); \ + UINT8 _s = (s); \ + UINT8 _r; \ + UINT8 _f, _ov; \ + __asm { mov al, _d } \ + __asm { add al, _s } \ + __asm { mov _r, al } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _ADD_BYTE((r), (d), (s)); \ + if ((_r != (UINT8)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("addb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_ADD(r, d, s) { \ + UINT16 _d = (d); \ + UINT16 _s = (s); \ + UINT16 _r; \ + UINT8 _f, _ov; \ + __asm { mov ax, _d } \ + __asm { add ax, _s } \ + __asm { mov _r, ax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _ADD_WORD((r), (d), (s)); \ + if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("addw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_ADD(r, d, s) { \ + UINT32 _d = (d); \ + UINT32 _s = (s); \ + UINT32 _r; \ + UINT8 _f, _ov; \ + __asm { mov eax, _d } \ + __asm { add eax, _s } \ + __asm { mov _r, eax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _ADD_DWORD((r), (d), (s)); \ + if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("addd r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_AND(d, s) { \ + UINT8 _d = (d); \ + UINT8 _s = (s); \ + UINT8 _f, _ov; \ + __asm { mov al, _s } \ + __asm { and _d, al } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _AND_BYTE((d), (s)); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("andb r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_AND(d, s) { \ + UINT16 _d = (d); \ + UINT16 _s = (s); \ + UINT8 _f, _ov; \ + __asm { mov ax, _s } \ + __asm { and _d, ax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _AND_WORD((d), (s)); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("andw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_AND(d, s) { \ + UINT32 _d = (d); \ + UINT32 _s = (s); \ + UINT8 _f, _ov; \ + __asm { mov eax, _s } \ + __asm { and _d, eax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _AND_DWORD((d), (s)); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("andd r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_DEC(s) { \ + UINT8 _s = (s); \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { dec _s } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_DEC((s)); \ + if ((_s != (UINT8)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("decb r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_DEC(s) { \ + UINT16 _s = (s); \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { dec _s } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_DEC((s)); \ + if ((_s != (UINT16)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("decd r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_DEC(s) { \ + UINT32 _s = (s); \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { dec _s } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_DEC((s)); \ + if ((_s != (UINT32)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("decd r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_INC(s) { \ + UINT8 _s = (s); \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { inc _s } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_INC((s)); \ + if ((_s != (UINT8)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("incb r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_INC(s) { \ + UINT16 _s = (s); \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { inc _s } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_INC((s)); \ + if ((_s != (UINT16)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("incd r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_INC(s) { \ + UINT32 _s = (s); \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { inc _s } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_INC((s)); \ + if ((_s != (UINT32)(s)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("incd r=%x:%x f=%x:%x o=%d %d", _s, s, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_NEG(d, s) { \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + __asm { neg _d } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_NEG((d), (s)); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("negb r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_NEG(d, s) { \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + __asm { neg _d } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_NEG((d), (s)); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("negw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_NEG(d, s) { \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + __asm { neg _d } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_NEG((d), (s)); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("negd r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_OR(d, s) { \ + UINT8 _d = (d); \ + UINT8 _s = (s); \ + UINT8 _f, _ov; \ + __asm { mov al, _s } \ + __asm { or _d, al } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _OR_BYTE((d), (s)); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("orb r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_OR(d, s) { \ + UINT16 _d = (d); \ + UINT16 _s = (s); \ + UINT8 _f, _ov; \ + __asm { mov ax, _s } \ + __asm { or _d, ax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _OR_WORD((d), (s)); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("orw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_OR(d, s) { \ + UINT32 _d = (d); \ + UINT32 _s = (s); \ + UINT8 _f, _ov; \ + __asm { mov eax, _s } \ + __asm { or _d, eax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _OR_DWORD((d), (s)); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("ord r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_SBB(r, d, s) { \ + UINT8 _d = (d); \ + UINT8 _s = (s); \ + UINT8 _r; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov al, _d } \ + __asm { sbb al, _s } \ + __asm { mov _r, al } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_SBB((r), (d), (s)); \ + if ((_r != (UINT8)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sbbb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_SBB(r, d, s) { \ + UINT16 _d = (d); \ + UINT16 _s = (s); \ + UINT16 _r; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov ax, _d } \ + __asm { sbb ax, _s } \ + __asm { mov _r, ax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_SBB((r), (d), (s)); \ + if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sbbw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_SBB(r, d, s) { \ + UINT32 _d = (d); \ + UINT32 _s = (s); \ + UINT32 _r; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov eax, _d } \ + __asm { sbb eax, _s } \ + __asm { mov _r, eax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_SBB((r), (d), (s)); \ + if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sbbd r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_SUB(r, d, s) { \ + UINT8 _d = (d); \ + UINT8 _s = (s); \ + UINT8 _r; \ + UINT8 _f, _ov; \ + __asm { mov al, _d } \ + __asm { sub al, _s } \ + __asm { mov _r, al } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_SUB((r), (d), (s)); \ + if ((_r != (UINT8)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("subb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_SUB(r, d, s) { \ + UINT16 _d = (d); \ + UINT16 _s = (s); \ + UINT16 _r; \ + UINT8 _f, _ov; \ + __asm { mov ax, _d } \ + __asm { sub ax, _s } \ + __asm { mov _r, ax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_SUB((r), (d), (s)); \ + if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("subw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_SUB(r, d, s) { \ + UINT32 _d = (d); \ + UINT32 _s = (s); \ + UINT32 _r; \ + UINT8 _f, _ov; \ + __asm { mov eax, _d } \ + __asm { sub eax, _s } \ + __asm { mov _r, eax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_SUB((r), (d), (s)); \ + if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("subd r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_XOR(d, s) { \ + UINT8 _d = (d); \ + UINT8 _s = (s); \ + UINT8 _f, _ov; \ + __asm { mov al, _s } \ + __asm { xor _d, al } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_XOR((d), (s)); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("xorb r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_XOR(d, s) { \ + UINT16 _d = (d); \ + UINT16 _s = (s); \ + UINT8 _f, _ov; \ + __asm { mov ax, _s } \ + __asm { xor _d, ax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_XOR((d), (s)); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("xorw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_XOR(d, s) { \ + UINT32 _d = (d); \ + UINT32 _s = (s); \ + UINT8 _f, _ov; \ + __asm { mov eax, _s } \ + __asm { xor _d, eax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_XOR((d), (s)); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZAPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("xord r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + +// ---- + +#define BYTE_IMUL(r, d, s) { \ + UINT8 _d = (d); \ + UINT8 _s = (s); \ + UINT16 _r; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov al, _d } \ + __asm { imul _s } \ + __asm { mov _r, ax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_IMUL((r), (d), (s)); \ + if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("imulb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_IMUL(r, d, s) { \ + UINT16 _d = (d); \ + UINT16 _s = (s); \ + UINT16 _rl, _rh; \ + UINT32 _r; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov ax, _d } \ + __asm { imul _s } \ + __asm { mov _rl, ax } \ + __asm { mov _rh, dx } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _r = _rl + (_rh << 16); \ + _WORD_IMUL((r), (d), (s)); \ + if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("imulw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_IMUL(r, d, s) { \ + UINT32 _d = (d); \ + UINT32 _s = (s); \ + UINT32 _rl, _rh; \ + UINT64 _r; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov eax, _d } \ + __asm { imul _s } \ + __asm { mov _rl, eax } \ + __asm { mov _rh, edx } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _r = (UINT64)_rl + ((UINT64)_rh << 32); \ + _DWORD_IMUL((r), (d), (s)); \ + if ((_r != (UINT64)(r)) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("imuld r=%x%x:%x%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define BYTE_MUL(r, d, s) { \ + UINT8 _d = (d); \ + UINT8 _s = (s); \ + UINT16 _r; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov al, _d } \ + __asm { mul _s } \ + __asm { mov _r, ax } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_MUL((r), (d), (s)); \ + if ((_r != (UINT16)(r)) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("mulb r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_MUL(r, d, s) { \ + UINT16 _d = (d); \ + UINT16 _s = (s); \ + UINT16 _rl, _rh; \ + UINT32 _r; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov ax, _d } \ + __asm { mul _s } \ + __asm { mov _rl, ax } \ + __asm { mov _rh, dx } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _r = _rl + (_rh << 16); \ + _WORD_MUL((r), (d), (s)); \ + if ((_r != (UINT32)(r)) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("mulw r=%x:%x f=%x:%x o=%d %d", _r, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_MUL(r, d, s) { \ + UINT32 _d = (d); \ + UINT32 _s = (s); \ + UINT32 _r, _o; \ + UINT8 _f, _ov; \ + __asm { bt CPU_FLAG, 0 } \ + __asm { mov eax, _d } \ + __asm { mul _s } \ + __asm { mov _r, eax } \ + __asm { mov _o, edx } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_MUL((r), (d), (s)); \ + if ((_r != (UINT32)(r)) || (_o != CPU_OV) || ((_f ^ CPU_FLAGL) & C_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("muld r=%x%x:%x%x f=%x:%x o=%d %d", _o, _r, CPU_OV, r, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + +// ---- + +#define AND_BYTE(d, s) BYTE_AND(d, s) +#define AND_WORD(d, s) WORD_AND(d, s) +#define AND_DWORD(d, s) DWORD_AND(d, s) + +#define XC_STORE_FLAGL() + diff --git a/i386c/ia32/inst_table.c b/i386c/ia32/inst_table.c old mode 100755 new mode 100644 index 08b73ef8..1c2468a7 --- a/i386c/ia32/inst_table.c +++ b/i386c/ia32/inst_table.c @@ -1,4706 +1,4706 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" - -#include "inst_table.h" -#include "groups.h" - -#include "ia32/instructions/bin_arith.h" -#include "ia32/instructions/bit_byte.h" -#include "ia32/instructions/ctrl_trans.h" -#include "ia32/instructions/data_trans.h" -#include "ia32/instructions/dec_arith.h" -#include "ia32/instructions/flag_ctrl.h" -#include "ia32/instructions/logic_arith.h" -#include "ia32/instructions/misc_inst.h" -#include "ia32/instructions/seg_reg.h" -#include "ia32/instructions/shift_rotate.h" -#include "ia32/instructions/string_inst.h" -#include "ia32/instructions/system_inst.h" - -#include -#include "ia32/instructions/mmx/mmx.h" -#include "ia32/instructions/mmx/3dnow.h" -#include "ia32/instructions/sse/sse.h" -#include "ia32/instructions/sse2/sse2.h" -#include "ia32/instructions/sse3/sse3.h" -#include "ia32/instructions/ssse3/ssse3.h" -#include "ia32/instructions/sse4/sse4_1.h" -#include "ia32/instructions/sse4/sse4_2.h" -#include "ia32/instructions/sse4a/sse4a.h" - -/* - * UNDEF OP - */ -static void -undef_op(void) -{ - - EXCEPTION(UD_EXCEPTION, 0); -} - -static void CPUCALL -undef_op2(UINT32 v) -{ - - EXCEPTION(UD_EXCEPTION, 0); -} - - -UINT8 insttable_info[256] = { - 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 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - - 0, /* 20 */ - 0, - 0, - 0, - 0, - 0, - INST_PREFIX, /* ES: */ - 0, - 0, /* 28 */ - 0, - 0, - 0, - 0, - 0, - INST_PREFIX, /* CS: */ - 0, - - 0, /* 30 */ - 0, - 0, - 0, - 0, - 0, - INST_PREFIX, /* SS: */ - 0, - 0, /* 38 */ - 0, - 0, - 0, - 0, - 0, - INST_PREFIX, /* DS: */ - 0, - - 0, /* 40 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, /* 48 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - - 0, /* 50 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, /* 58 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - - 0, /* 60 */ - 0, - 0, - 0, - INST_PREFIX, /* FS: */ - INST_PREFIX, /* GS: */ - INST_PREFIX, /* OpSize: */ - INST_PREFIX, /* AddrSize: */ - 0, /* 68 */ - 0, - 0, - 0, - INST_STRING, /* INSB_YbDX */ - INST_STRING, /* INSW_YvDX */ - INST_STRING, /* OUTSB_DXXb */ - INST_STRING, /* OUTSW_DXXv */ - - 0, /* 70 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, /* 78 */ - 0, - 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 */ - 0, - 0, - INST_PREFIX, /* FWAIT */ - 0, - 0, - 0, - 0, - - 0, /* A0 */ - 0, - 0, - 0, - INST_STRING, /* MOVSB_XbYb */ - INST_STRING, /* MOVSW_XvYv */ - INST_STRING | REP_CHECKZF, /* CMPSB_XbYb */ - INST_STRING | REP_CHECKZF, /* CMPSW_XvYv */ - 0, /* A8 */ - 0, - INST_STRING, /* STOSB_YbAL */ - INST_STRING, /* STOSW_YveAX */ - INST_STRING, /* LODSB_ALXb */ - INST_STRING, /* LODSW_eAXXv */ - INST_STRING | REP_CHECKZF, /* SCASB_ALXb */ - INST_STRING | REP_CHECKZF, /* SCASW_eAXXv */ - - 0, /* B0 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, /* B8 */ - 0, - 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, - 0, - 0, - 0, - 0, - 0, - 0, - - 0, /* E0 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, /* E8 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - - INST_PREFIX, /* F0 *//* LOCK */ - 0, - INST_PREFIX, /* REPNE */ - INST_PREFIX, /* REPE */ - 0, - 0, - 0, - 0, - 0, /* F8 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, -}; - -void (*insttable_1byte[2][256])(void) = { - /* 16bit */ - { - ADD_EbGb, /* 00 */ - ADD_EwGw, - ADD_GbEb, - ADD_GwEw, - ADD_ALIb, - ADD_AXIw, - PUSH16_ES, - POP16_ES, - OR_EbGb, /* 08 */ - OR_EwGw, - OR_GbEb, - OR_GwEw, - OR_ALIb, - OR_AXIw, - PUSH16_CS, - _2byte_ESC16, - - ADC_EbGb, /* 10 */ - ADC_EwGw, - ADC_GbEb, - ADC_GwEw, - ADC_ALIb, - ADC_AXIw, - PUSH16_SS, - POP16_SS, - SBB_EbGb, /* 18 */ - SBB_EwGw, - SBB_GbEb, - SBB_GwEw, - SBB_ALIb, - SBB_AXIw, - PUSH16_DS, - POP16_DS, - - AND_EbGb, /* 20 */ - AND_EwGw, - AND_GbEb, - AND_GwEw, - AND_ALIb, - AND_AXIw, - Prefix_ES, - DAA, - SUB_EbGb, /* 28 */ - SUB_EwGw, - SUB_GbEb, - SUB_GwEw, - SUB_ALIb, - SUB_AXIw, - Prefix_CS, - DAS, - - XOR_EbGb, /* 30 */ - XOR_EwGw, - XOR_GbEb, - XOR_GwEw, - XOR_ALIb, - XOR_AXIw, - Prefix_SS, - AAA, - CMP_EbGb, /* 38 */ - CMP_EwGw, - CMP_GbEb, - CMP_GwEw, - CMP_ALIb, - CMP_AXIw, - Prefix_DS, - AAS, - - INC_AX, /* 40 */ - INC_CX, - INC_DX, - INC_BX, - INC_SP, - INC_BP, - INC_SI, - INC_DI, - DEC_AX, /* 48 */ - DEC_CX, - DEC_DX, - DEC_BX, - DEC_SP, - DEC_BP, - DEC_SI, - DEC_DI, - - PUSH_AX, /* 50 */ - PUSH_CX, - PUSH_DX, - PUSH_BX, - PUSH_SP, - PUSH_BP, - PUSH_SI, - PUSH_DI, - POP_AX, /* 58 */ - POP_CX, - POP_DX, - POP_BX, - POP_SP, - POP_BP, - POP_SI, - POP_DI, - - PUSHA, /* 60 */ - POPA, - BOUND_GwMa, - ARPL_EwGw, - Prefix_FS, - Prefix_GS, - OpSize, - AddrSize, - PUSH_Iw, /* 68 */ - IMUL_GwEwIw, - PUSH_Ib, - IMUL_GwEwIb, - INSB_YbDX, - INSW_YwDX, - OUTSB_DXXb, - OUTSW_DXXw, - - JO_Jb, /* 70 */ - JNO_Jb, - JC_Jb, - JNC_Jb, - JZ_Jb, - JNZ_Jb, - JNA_Jb, - JA_Jb, - JS_Jb, /* 78 */ - JNS_Jb, - JP_Jb, - JNP_Jb, - JL_Jb, - JNL_Jb, - JLE_Jb, - JNLE_Jb, - - Grp1_EbIb, /* 80 */ - Grp1_EwIw, - Grp1_EbIb, - Grp1_EwIb, - TEST_EbGb, - TEST_EwGw, - XCHG_EbGb, - XCHG_EwGw, - MOV_EbGb, /* 88 */ - MOV_EwGw, - MOV_GbEb, - MOV_GwEw, - MOV_EwSw, - LEA_GwM, - MOV_SwEw, - POP_Ew, - - _NOP, /* 90 */ - XCHG_CXAX, - XCHG_DXAX, - XCHG_BXAX, - XCHG_SPAX, - XCHG_BPAX, - XCHG_SIAX, - XCHG_DIAX, - CBW, /* 98 */ - CWD, - CALL16_Ap, - FPU_FWAIT, - PUSHF_Fw, - POPF_Fw, - SAHF, - LAHF, - - MOV_ALOb, /* A0 */ - MOV_AXOw, - MOV_ObAL, - MOV_OwAX, - MOVSB_XbYb, - MOVSW_XwYw, - CMPSB_XbYb, - CMPSW_XwYw, - TEST_ALIb, /* A8 */ - TEST_AXIw, - STOSB_YbAL, - STOSW_YwAX, - LODSB_ALXb, - LODSW_AXXw, - SCASB_ALXb, - SCASW_AXXw, - - MOV_ALIb, /* B0 */ - MOV_CLIb, - MOV_DLIb, - MOV_BLIb, - MOV_AHIb, - MOV_CHIb, - MOV_DHIb, - MOV_BHIb, - MOV_AXIw, /* B8 */ - MOV_CXIw, - MOV_DXIw, - MOV_BXIw, - MOV_SPIw, - MOV_BPIw, - MOV_SIIw, - MOV_DIIw, - - Grp2_EbIb, /* C0 */ - Grp2_EwIb, - RETnear16_Iw, - RETnear16, - LES_GwMp, - LDS_GwMp, - MOV_EbIb, - MOV_EwIw, - ENTER16_IwIb, /* C8 */ - LEAVE, - RETfar16_Iw, - RETfar16, - INT3, - INT_Ib, - INTO, - IRET, - - Grp2_Eb, /* D0 */ - Grp2_Ew, - Grp2_EbCL, - Grp2_EwCL, - AAM, - AAD, - SALC, /* undoc(8086) */ - XLAT, - NOFPU_ESC0, /* D8 */ - NOFPU_ESC1, - NOFPU_ESC2, - NOFPU_ESC3, - NOFPU_ESC4, - NOFPU_ESC5, - NOFPU_ESC6, - NOFPU_ESC7, - - LOOPNE_Jb, /* E0 */ - LOOPE_Jb, - LOOP_Jb, - JeCXZ_Jb, - IN_ALIb, - IN_AXIb, - OUT_IbAL, - OUT_IbAX, - CALL_Aw, /* E8 */ - JMP_Jw, - JMP16_Ap, - JMP_Jb, - IN_ALDX, - IN_AXDX, - OUT_DXAL, - OUT_DXAX, - - _LOCK, /* F0 */ - INT1, - _REPNE, - _REPE, - HLT, - CMC, - Grp3_Eb, - Grp3_Ew, - CLC, /* F8 */ - STC, - CLI, - STI, - CLD, - STD, - Grp4, - Grp5_Ew, - }, - - /* 32bit */ - { - ADD_EbGb, /* 00 */ - ADD_EdGd, - ADD_GbEb, - ADD_GdEd, - ADD_ALIb, - ADD_EAXId, - PUSH32_ES, - POP32_ES, - OR_EbGb, /* 08 */ - OR_EdGd, - OR_GbEb, - OR_GdEd, - OR_ALIb, - OR_EAXId, - PUSH32_CS, - _2byte_ESC32, - - ADC_EbGb, /* 10 */ - ADC_EdGd, - ADC_GbEb, - ADC_GdEd, - ADC_ALIb, - ADC_EAXId, - PUSH32_SS, - POP32_SS, - SBB_EbGb, /* 18 */ - SBB_EdGd, - SBB_GbEb, - SBB_GdEd, - SBB_ALIb, - SBB_EAXId, - PUSH32_DS, - POP32_DS, - - AND_EbGb, /* 20 */ - AND_EdGd, - AND_GbEb, - AND_GdEd, - AND_ALIb, - AND_EAXId, - undef_op, /* Prefix_ES */ - DAA, - SUB_EbGb, /* 28 */ - SUB_EdGd, - SUB_GbEb, - SUB_GdEd, - SUB_ALIb, - SUB_EAXId, - undef_op, /* Prefix_CS */ - DAS, - - XOR_EbGb, /* 30 */ - XOR_EdGd, - XOR_GbEb, - XOR_GdEd, - XOR_ALIb, - XOR_EAXId, - undef_op, /* Prefix_SS */ - AAA, - CMP_EbGb, /* 38 */ - CMP_EdGd, - CMP_GbEb, - CMP_GdEd, - CMP_ALIb, - CMP_EAXId, - undef_op, /* Prefix_DS */ - AAS, - - INC_EAX, /* 40 */ - INC_ECX, - INC_EDX, - INC_EBX, - INC_ESP, - INC_EBP, - INC_ESI, - INC_EDI, - DEC_EAX, /* 48 */ - DEC_ECX, - DEC_EDX, - DEC_EBX, - DEC_ESP, - DEC_EBP, - DEC_ESI, - DEC_EDI, - - PUSH_EAX, /* 50 */ - PUSH_ECX, - PUSH_EDX, - PUSH_EBX, - PUSH_ESP, - PUSH_EBP, - PUSH_ESI, - PUSH_EDI, - POP_EAX, /* 58 */ - POP_ECX, - POP_EDX, - POP_EBX, - POP_ESP, - POP_EBP, - POP_ESI, - POP_EDI, - - PUSHAD, /* 60 */ - POPAD, - BOUND_GdMa, - ARPL_EwGw, - undef_op, /* Prefix_FS */ - undef_op, /* Prefix_GS */ - undef_op, /* OpSize */ - undef_op, /* AddrSize */ - PUSH_Id, /* 68 */ - IMUL_GdEdId, - PUSH_Ib, - IMUL_GdEdIb, - INSB_YbDX, - INSD_YdDX, - OUTSB_DXXb, - OUTSD_DXXd, - - JO_Jb, /* 70 */ - JNO_Jb, - JC_Jb, - JNC_Jb, - JZ_Jb, - JNZ_Jb, - JNA_Jb, - JA_Jb, - JS_Jb, /* 78 */ - JNS_Jb, - JP_Jb, - JNP_Jb, - JL_Jb, - JNL_Jb, - JLE_Jb, - JNLE_Jb, - - Grp1_EbIb, /* 80 */ - Grp1_EdId, - Grp1_EbIb, - Grp1_EdIb, - TEST_EbGb, - TEST_EdGd, - XCHG_EbGb, - XCHG_EdGd, - MOV_EbGb, /* 88 */ - MOV_EdGd, - MOV_GbEb, - MOV_GdEd, - MOV_EdSw, - LEA_GdM, - MOV_SwEw, - POP_Ed, - - _NOP, /* 90 */ - XCHG_ECXEAX, - XCHG_EDXEAX, - XCHG_EBXEAX, - XCHG_ESPEAX, - XCHG_EBPEAX, - XCHG_ESIEAX, - XCHG_EDIEAX, - CWDE, /* 98 */ - CDQ, - CALL32_Ap, - undef_op, /* FWAIT */ - PUSHFD_Fd, - POPFD_Fd, - SAHF, - LAHF, - - MOV_ALOb, /* A0 */ - MOV_EAXOd, - MOV_ObAL, - MOV_OdEAX, - MOVSB_XbYb, - MOVSD_XdYd, - CMPSB_XbYb, - CMPSD_XdYd, - TEST_ALIb, /* A8 */ - TEST_EAXId, - STOSB_YbAL, - STOSD_YdEAX, - LODSB_ALXb, - LODSD_EAXXd, - SCASB_ALXb, - SCASD_EAXXd, - - MOV_ALIb, /* B0 */ - MOV_CLIb, - MOV_DLIb, - MOV_BLIb, - MOV_AHIb, - MOV_CHIb, - MOV_DHIb, - MOV_BHIb, - MOV_EAXId, /* B8 */ - MOV_ECXId, - MOV_EDXId, - MOV_EBXId, - MOV_ESPId, - MOV_EBPId, - MOV_ESIId, - MOV_EDIId, - - Grp2_EbIb, /* C0 */ - Grp2_EdIb, - RETnear32_Iw, - RETnear32, - LES_GdMp, - LDS_GdMp, - MOV_EbIb, - MOV_EdId, - ENTER32_IwIb, /* C8 */ - LEAVE, - RETfar32_Iw, - RETfar32, - INT3, - INT_Ib, - INTO, - IRET, - - Grp2_Eb, /* D0 */ - Grp2_Ed, - Grp2_EbCL, - Grp2_EdCL, - AAM, - AAD, - SALC, /* undoc(8086) */ - XLAT, - NOFPU_ESC0, /* D8 */ - NOFPU_ESC1, - NOFPU_ESC2, - NOFPU_ESC3, - NOFPU_ESC4, - NOFPU_ESC5, - NOFPU_ESC6, - NOFPU_ESC7, - - LOOPNE_Jb, /* E0 */ - LOOPE_Jb, - LOOP_Jb, - JeCXZ_Jb, - IN_ALIb, - IN_EAXIb, - OUT_IbAL, - OUT_IbEAX, - CALL_Ad, /* E8 */ - JMP_Jd, - JMP32_Ap, - JMP_Jb, - IN_ALDX, - IN_EAXDX, - OUT_DXAL, - OUT_DXEAX, - - _LOCK, /* F0 */ - INT1, - undef_op, /* repne */ - undef_op, /* repe */ - HLT, - CMC, - Grp3_Eb, - Grp3_Ed, - CLC, /* F8 */ - STC, - CLI, - STI, - CLD, - STD, - Grp4, - Grp5_Ed, - }, -}; - - -void (*insttable_1byte_repfunc[2][256])(int reptype) = { - /* 16bit */ - { - NULL, /* 00 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 08 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 10 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 18 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 20 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 28 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 30 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 40 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 48 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 50 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 58 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 60 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 68 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 70 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 78 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 80 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 88 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 90 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 98 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* A0 */ - NULL, - NULL, - NULL, - MOVSB_XbYb_rep, - MOVSW_XwYw_rep, - CMPSB_XbYb_rep, - CMPSW_XwYw_rep, - NULL, /* A8 */ - NULL, - STOSB_YbAL_rep, - STOSW_YwAX_rep, - NULL, - NULL, - NULL, - NULL, - - NULL, /* B0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* C0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* D0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* undoc(8086) */ - NULL, - NULL, /* D8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* E0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* F0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - }, - - /* 32bit */ - { - NULL, /* 00 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 08 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 10 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 18 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 20 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 28 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 30 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 40 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 48 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 50 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 58 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 60 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 68 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 70 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 78 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 80 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 88 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 90 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 98 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* A0 */ - NULL, - NULL, - NULL, - MOVSB_XbYb_rep, - MOVSD_XdYd_rep, - CMPSB_XbYb_rep, - CMPSD_XdYd_rep, - NULL, /* A8 */ - NULL, - STOSB_YbAL_rep, - STOSD_YdEAX_rep, - NULL, - NULL, - NULL, - NULL, - - NULL, /* B0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* C0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* D0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* undoc(8086) */ - NULL, - NULL, /* D8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* E0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* F0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - }, -}; - -void (*insttable_2byte[2][256])(void) = { - /* 16bit */ - { - Grp6, /* 00 */ - Grp7, - LAR_GwEw, - LSL_GwEw, - undef_op, - LOADALL286, /* undoc(286) */ - CLTS, - LOADALL, - INVD, /* 08 */ - WBINVD, - undef_op, - UD2, - undef_op, - AMD3DNOW_PREFETCH, - AMD3DNOW_FEMMS, - undef_op, - - SSE_MOVUPSmem2xmm, /* 10 */ - SSE_MOVUPSxmm2mem, - SSE_MOVLPSmem2xmm, // + MOVHLPS - SSE_MOVLPSxmm2mem, - SSE_UNPCKLPS, - SSE_UNPCKHPS, - SSE_MOVHPSmem2xmm, // + MOVLHPS - SSE_MOVHPSxmm2mem, - SSE_PREFETCHTx, /* 18 */ - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - - MOV_RdCd, /* 20 */ - MOV_RdDd, - MOV_CdRd, - MOV_DdRd, - MOV_RdTd, - undef_op, - MOV_TdRd, - undef_op, - SSE_MOVAPSmem2xmm, /* 28 */ - SSE_MOVAPSxmm2mem, - SSE_CVTPI2PS, - SSE_MOVNTPS, - SSE_CVTTPS2PI, - SSE_CVTPS2PI, - SSE_UCOMISS, - SSE_COMISS, - - WRMSR, /* 30 */ - RDTSC, - RDMSR, - RDPMC, - SYSENTER, - SYSEXIT, - undef_op, - undef_op, - _3byte_38ESC_16, /* 38 */ - undef_op, - _3byte_3AESC, - undef_op, - undef_op, - undef_op, - undef_op, - undef_op, - - CMOVO_GwEw, /* 40 */ - CMOVNO_GwEw, - CMOVC_GwEw, - CMOVNC_GwEw, - CMOVZ_GwEw, - CMOVNZ_GwEw, - CMOVNA_GwEw, - CMOVA_GwEw, - CMOVS_GwEw, /* 48 */ - CMOVNS_GwEw, - CMOVP_GwEw, - CMOVNP_GwEw, - CMOVL_GwEw, - CMOVNL_GwEw, - CMOVLE_GwEw, - CMOVNLE_GwEw, - - SSE_MOVMSKPS, /* 50 */ - SSE_SQRTPS, - SSE_RSQRTPS, - SSE_RCPPS, - SSE_ANDPS, - SSE_ANDNPS, - SSE_ORPS, - SSE_XORPS, - SSE_ADDPS, /* 58 */ - SSE_MULPS, - SSE2_CVTPS2PD, - SSE2_CVTDQ2PS, - SSE_SUBPS, - SSE_MINPS, - SSE_DIVPS, - SSE_MAXPS, - - MMX_PUNPCKLBW, /* 60 */ - MMX_PUNPCKLWD, - MMX_PUNPCKLDQ, - MMX_PACKSSWB, - MMX_PCMPGTB, - MMX_PCMPGTW, - MMX_PCMPGTD, - MMX_PACKUSWB, - MMX_PUNPCKHBW, /* 68 */ - MMX_PUNPCKHWD, - MMX_PUNPCKHDQ, - MMX_PACKSSDW, - undef_op, - undef_op, - MMX_MOVD_mm_rm32, - MMX_MOVQ_mm_mmm64, - - SSE_PSHUFW, /* 70 */ - MMX_PSxxW_imm8, - MMX_PSxxD_imm8, - MMX_PSxxQ_imm8, - MMX_PCMPEQB, - MMX_PCMPEQW, - MMX_PCMPEQD, - MMX_EMMS, - undef_op, /* 78 */ - undef_op, - undef_op, - undef_op, - undef_op, - undef_op, - MMX_MOVD_rm32_mm, - MMX_MOVQ_mmm64_mm, - - JO_Jw, /* 80 */ - JNO_Jw, - JC_Jw, - JNC_Jw, - JZ_Jw, - JNZ_Jw, - JNA_Jw, - JA_Jw, - JS_Jw, /* 88 */ - JNS_Jw, - JP_Jw, - JNP_Jw, - JL_Jw, - JNL_Jw, - JLE_Jw, - JNLE_Jw, - - SETO_Eb, /* 90 */ - SETNO_Eb, - SETC_Eb, - SETNC_Eb, - SETZ_Eb, - SETNZ_Eb, - SETNA_Eb, - SETA_Eb, - SETS_Eb, /* 98 */ - SETNS_Eb, - SETP_Eb, - SETNP_Eb, - SETL_Eb, - SETNL_Eb, - SETLE_Eb, - SETNLE_Eb, - - PUSH16_FS, /* A0 */ - POP16_FS, - _CPUID, - BT_EwGw, - SHLD_EwGwIb, - SHLD_EwGwCL, - CMPXCHG_EbGb, /* undoc(486) */ - CMPXCHG_EwGw, /* undoc(486) */ - PUSH16_GS, /* A8 */ - POP16_GS, - RSM, - BTS_EwGw, - SHRD_EwGwIb, - SHRD_EwGwCL, - NOFPU_FPU_FXSAVERSTOR, // + LDMXCSR + STMXCSR + SFENCE + LFENCE + CLFLUSH - IMUL_GwEw, - - CMPXCHG_EbGb, /* B0 */ - CMPXCHG_EwGw, - LSS_GwMp, - BTR_EwGw, - LFS_GwMp, - LGS_GwMp, - MOVZX_GwEb, - MOVZX_GwEw, - undef_op, /* B8 */ - UD2, - Grp8_EwIb, - BTC_EwGw, - BSF_GwEw, - BSR_GwEw, - MOVSX_GwEb, - MOVSX_GwEw, - - XADD_EbGb, /* C0 */ - XADD_EwGw, - SSE_CMPPS, - undef_op, - SSE_PINSRW, - SSE_PEXTRW, - SSE_SHUFPS, - Grp9, - BSWAP_EAX, /* C8 */ - BSWAP_ECX, - BSWAP_EDX, - BSWAP_EBX, - BSWAP_ESP, - BSWAP_EBP, - BSWAP_ESI, - BSWAP_EDI, - - undef_op, /* D0 */ - MMX_PSRLW, - MMX_PSRLD, - MMX_PSRLQ, - SSE2_PADDQmm, - MMX_PMULLW, - undef_op, - SSE_PMOVMSKB, - MMX_PSUBUSB, /* D8 */ - MMX_PSUBUSW, - SSE_PMINUB, - MMX_PAND, - MMX_PADDUSB, - MMX_PADDUSW, - SSE_PMAXUB, - MMX_PANDN, - - SSE_PAVGB, /* E0 */ - MMX_PSRAW, - MMX_PSRAD, - SSE_PAVGW, - SSE_PMULHUW, - MMX_PMULHW, - undef_op, - SSE_MOVNTQ, - MMX_PSUBSB, /* E8 */ - MMX_PSUBSW, - SSE_PMINSW, - MMX_POR, - MMX_PADDSB, - MMX_PADDSW, - SSE_PMAXSW, - MMX_PXOR, - - AMD3DNOW_F0, /* F0 */ - MMX_PSLLW, - MMX_PSLLD, - MMX_PSLLQ, - SSE2_PMULUDQmm, - MMX_PMADDWD, - SSE_PSADBW, - SSE_MASKMOVQ, - MMX_PSUBB, /* F8 */ - MMX_PSUBW, - MMX_PSUBD, - SSE2_PSUBQmm, - MMX_PADDB, - MMX_PADDW, - MMX_PADDD, - undef_op, - }, - - /* 32bit */ - { - Grp6, /* 00 */ - Grp7, - LAR_GdEw, - LSL_GdEw, - undef_op, - LOADALL286, /* undoc(286) */ - CLTS, - LOADALL, - INVD, /* 08 */ - WBINVD, - undef_op, - UD2, - undef_op, - AMD3DNOW_PREFETCH, - AMD3DNOW_FEMMS, - undef_op, - - SSE_MOVUPSmem2xmm, /* 10 */ - SSE_MOVUPSxmm2mem, - SSE_MOVLPSmem2xmm, // + MOVHLPS - SSE_MOVLPSxmm2mem, - SSE_UNPCKLPS, - SSE_UNPCKHPS, - SSE_MOVHPSmem2xmm, // + MOVLHPS - SSE_MOVHPSxmm2mem, - SSE_PREFETCHTx, /* 18 */ - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - SSE_NOPPREFETCH, - - MOV_RdCd, /* 20 */ - MOV_RdDd, - MOV_CdRd, - MOV_DdRd, - MOV_RdTd, - undef_op, - MOV_TdRd, - undef_op, - SSE_MOVAPSmem2xmm, /* 28 */ - SSE_MOVAPSxmm2mem, - SSE_CVTPI2PS, - SSE_MOVNTPS, - SSE_CVTTPS2PI, - SSE_CVTPS2PI, - SSE_UCOMISS, - SSE_COMISS, - - WRMSR, /* 30 */ - RDTSC, - RDMSR, - RDPMC, - SYSENTER, - SYSEXIT, - undef_op, - undef_op, - _3byte_38ESC, /* 38 */ - undef_op, - _3byte_3AESC, - undef_op, - undef_op, - undef_op, - undef_op, - undef_op, - - CMOVO_GdEd, /* 40 */ - CMOVNO_GdEd, - CMOVC_GdEd, - CMOVNC_GdEd, - CMOVZ_GdEd, - CMOVNZ_GdEd, - CMOVNA_GdEd, - CMOVA_GdEd, - CMOVS_GdEd, /* 48 */ - CMOVNS_GdEd, - CMOVP_GdEd, - CMOVNP_GdEd, - CMOVL_GdEd, - CMOVNL_GdEd, - CMOVLE_GdEd, - CMOVNLE_GdEd, - - SSE_MOVMSKPS, /* 50 */ - SSE_SQRTPS, - SSE_RSQRTPS, - SSE_RCPPS, - SSE_ANDPS, - SSE_ANDNPS, - SSE_ORPS, - SSE_XORPS, - SSE_ADDPS, /* 58 */ - SSE_MULPS, - SSE2_CVTPS2PD, - SSE2_CVTDQ2PS, - SSE_SUBPS, - SSE_MINPS, - SSE_DIVPS, - SSE_MAXPS, - - MMX_PUNPCKLBW, /* 60 */ - MMX_PUNPCKLWD, - MMX_PUNPCKLDQ, - MMX_PACKSSWB, - MMX_PCMPGTB, - MMX_PCMPGTW, - MMX_PCMPGTD, - MMX_PACKUSWB, - MMX_PUNPCKHBW, /* 68 */ - MMX_PUNPCKHWD, - MMX_PUNPCKHDQ, - MMX_PACKSSDW, - undef_op, - undef_op, - MMX_MOVD_mm_rm32, - MMX_MOVQ_mm_mmm64, - - SSE_PSHUFW, /* 70 */ - MMX_PSxxW_imm8, - MMX_PSxxD_imm8, - MMX_PSxxQ_imm8, - MMX_PCMPEQB, - MMX_PCMPEQW, - MMX_PCMPEQD, - MMX_EMMS, - undef_op, /* 78 */ - undef_op, - undef_op, - undef_op, - undef_op, - undef_op, - MMX_MOVD_rm32_mm, - MMX_MOVQ_mmm64_mm, - - JO_Jd, /* 80 */ - JNO_Jd, - JC_Jd, - JNC_Jd, - JZ_Jd, - JNZ_Jd, - JNA_Jd, - JA_Jd, - JS_Jd, /* 88 */ - JNS_Jd, - JP_Jd, - JNP_Jd, - JL_Jd, - JNL_Jd, - JLE_Jd, - JNLE_Jd, - - SETO_Eb, /* 90 */ - SETNO_Eb, - SETC_Eb, - SETNC_Eb, - SETZ_Eb, - SETNZ_Eb, - SETNA_Eb, - SETA_Eb, - SETS_Eb, /* 98 */ - SETNS_Eb, - SETP_Eb, - SETNP_Eb, - SETL_Eb, - SETNL_Eb, - SETLE_Eb, - SETNLE_Eb, - - PUSH32_FS, /* A0 */ - POP32_FS, - _CPUID, - BT_EdGd, - SHLD_EdGdIb, - SHLD_EdGdCL, - CMPXCHG_EbGb, /* undoc(486) */ - CMPXCHG_EdGd, /* undoc(486) */ - PUSH32_GS, /* A8 */ - POP32_GS, - RSM, - BTS_EdGd, - SHRD_EdGdIb, - SHRD_EdGdCL, - NOFPU_FPU_FXSAVERSTOR, // + LDMXCSR + STMXCSR + SFENCE + LFENCE + CLFLUSH - IMUL_GdEd, - - CMPXCHG_EbGb, /* B0 */ - CMPXCHG_EdGd, - LSS_GdMp, - BTR_EdGd, - LFS_GdMp, - LGS_GdMp, - MOVZX_GdEb, - MOVZX_GdEw, - undef_op, /* B8 */ - UD2, - Grp8_EdIb, - BTC_EdGd, - BSF_GdEd, - BSR_GdEd, - MOVSX_GdEb, - MOVSX_GdEw, - - XADD_EbGb, /* C0 */ - XADD_EdGd, - SSE_CMPPS, - SSE2_MOVNTI, - SSE_PINSRW, - SSE_PEXTRW, - SSE_SHUFPS, - Grp9, - BSWAP_EAX, /* C8 */ - BSWAP_ECX, - BSWAP_EDX, - BSWAP_EBX, - BSWAP_ESP, - BSWAP_EBP, - BSWAP_ESI, - BSWAP_EDI, - - undef_op, /* D0 */ - MMX_PSRLW, - MMX_PSRLD, - MMX_PSRLQ, - SSE2_PADDQmm, - MMX_PMULLW, - undef_op, - SSE_PMOVMSKB, - MMX_PSUBUSB, /* D8 */ - MMX_PSUBUSW, - SSE_PMINUB, - MMX_PAND, - MMX_PADDUSB, - MMX_PADDUSW, - SSE_PMAXUB, - MMX_PANDN, - - SSE_PAVGB, /* E0 */ - MMX_PSRAW, - MMX_PSRAD, - SSE_PAVGW, - SSE_PMULHUW, - MMX_PMULHW, - undef_op, - SSE_MOVNTQ, - MMX_PSUBSB, /* E8 */ - MMX_PSUBSW, - SSE_PMINSW, - MMX_POR, - MMX_PADDSB, - MMX_PADDSW, - SSE_PMAXSW, - MMX_PXOR, - - AMD3DNOW_F0, /* F0 */ - MMX_PSLLW, - MMX_PSLLD, - MMX_PSLLQ, - SSE2_PMULUDQmm, - MMX_PMADDWD, - SSE_PSADBW, - SSE_MASKMOVQ, - MMX_PSUBB, /* F8 */ - MMX_PSUBW, - MMX_PSUBD, - SSE2_PSUBQmm, - MMX_PADDB, - MMX_PADDW, - MMX_PADDD, - undef_op, - }, -}; - -void (*insttable_2byte660F_32[256])(void) = { - NULL, /* 00 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 08 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - SSE2_MOVUPDmem2xmm, /* 10 */ - SSE2_MOVUPDxmm2mem, - SSE2_MOVLPDmem2xmm, - SSE2_MOVLPDxmm2mem, - SSE2_UNPCKLPD, - SSE2_UNPCKHPD, - SSE2_MOVHPDmem2xmm, - SSE2_MOVHPDxmm2mem, - NULL, /* 18 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 20 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE2_MOVAPDmem2xmm, /* 28 */ - SSE2_MOVAPDxmm2mem, - SSE2_CVTPI2PD, - SSE2_MOVNTPD, - SSE2_CVTTPD2PI, - SSE2_CVTPD2PI, - SSE2_UCOMISD, - SSE2_COMISD, - - NULL, /* 30 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 40 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 48 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - SSE2_MOVMSKPD, /* 50 */ - SSE2_SQRTPD, - NULL, - NULL, - SSE2_ANDPD, - SSE2_ANDNPD, - SSE2_ORPD, - SSE2_XORPD, - SSE2_ADDPD, /* 58 */ - SSE2_MULPD, - SSE2_CVTPD2PS, - SSE2_CVTPS2DQ, - SSE2_SUBPD, - SSE2_MINPD, - SSE2_DIVPD, - SSE2_MAXPD, - - SSE2_PUNPCKLBW, /* 60 */ - SSE2_PUNPCKLWD, - SSE2_PUNPCKLDQ, - SSE2_PACKSSWB, - SSE2_PCMPGTB, - SSE2_PCMPGTW, - SSE2_PCMPGTD, - SSE2_PACKUSWB, - SSE2_PUNPCKHBW, /* 68 */ - SSE2_PUNPCKHWD, - SSE2_PUNPCKHDQ, - SSE2_PACKSSDW, - SSE2_PUNPCKLQDQ, - SSE2_PUNPCKHQDQ, - SSE2_MOVDrm2xmm, - SSE2_MOVDQAmem2xmm, - - SSE2_PSHUFD, /* 70 */ - SSE2_PSxxWimm, // PSLLWimm + PSRAWimm + PSRLWimm - SSE2_PSxxDimm, // PSLLDimm + PSRADimm + PSRLDimm - SSE2_PSxxQimm, // PSLLQimm + PSRAQimm + PSRLQimm + PSLLDQ + PSRLDQ - SSE2_PCMPEQB, - SSE2_PCMPEQW, - SSE2_PCMPEQD, - NULL, - SSE4a_EXTRQimm, /* 78 */ - SSE4a_EXTRQxmm, - NULL, - NULL, - SSE3_HADDPD, - SSE3_HSUBPD, - SSE2_MOVDxmm2rm, - SSE2_MOVDQAxmm2mem, - - NULL, /* 80 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 88 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 90 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 98 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* A0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* B0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* C0 */ - NULL, - SSE2_CMPPD, - SSE2_MOVNTI, - SSE2_PINSRW, - SSE2_PEXTRW, - SSE2_SHUFPD, - NULL, - NULL, /* C8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - SSE3_ADDSUBPD, /* D0 */ - SSE2_PSRLW, - SSE2_PSRLD, - SSE2_PSRLQ, - SSE2_PADDQxmm, - SSE2_PMULLW, - SSE2_MOVQxmm2mem, - SSE2_PMOVMSKB, - SSE2_PSUBUSB, /* D8 */ - SSE2_PSUBUSW, - SSE2_PMINUB, - SSE2_PAND, - SSE2_PADDUSB, - SSE2_PADDUSW, - SSE2_PMAXUB, - SSE2_PANDN, - - SSE2_PAVGB, /* E0 */ - SSE2_PSRAW, - SSE2_PSRAD, - SSE2_PAVGW, - SSE2_PMULHUW, - SSE2_PMULHW, - SSE2_CVTTPD2DQ, - SSE2_MOVNTDQ, - SSE2_PSUBSB, /* E8 */ - SSE2_PSUBSW, - SSE2_PMINSW, - SSE2_POR, - SSE2_PADDSB, - SSE2_PADDSW, - SSE2_PMAXSW, - SSE2_PXOR, - - NULL, /* F0 */ - SSE2_PSLLW, - SSE2_PSLLD, - SSE2_PSLLQ, - SSE2_PMULUDQxmm, - SSE2_PMADD, - SSE2_PSADBW, - SSE2_MASKMOVDQU, - SSE2_PSUBB, /* F8 */ - SSE2_PSUBW, - SSE2_PSUBD, - SSE2_PSUBQxmm, - SSE2_PADDB, - SSE2_PADDW, - SSE2_PADDD, - NULL, -}; - -void (*insttable_2byteF20F_32[256])(void) = { - NULL, /* 00 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 08 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - SSE2_MOVSDmem2xmm, /* 10 */ - SSE2_MOVSDxmm2mem, - SSE3_MOVDDUP, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 18 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 20 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 28 */ - NULL, - SSE2_CVTSI2SD, - SSE4a_MOVNTSD, - SSE2_CVTTSD2SI, - SSE2_CVTSD2SI, - NULL, - NULL, - - NULL, /* 30 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 40 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 48 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 50 */ - SSE2_SQRTSD, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE2_ADDSD, /* 58 */ - SSE2_MULSD, - SSE2_CVTSD2SS, - NULL, - SSE2_SUBSD, - SSE2_MINSD, - SSE2_DIVSD, - SSE2_MAXSD, - - NULL, /* 60 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 68 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - SSE2_PSHUFLW, /* 70 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE4a_INSERTQimm, /* 78 */ - SSE4a_INSERTQxmm, - NULL, - NULL, - SSE3_HADDPS, - SSE3_HSUBPS, - NULL, - NULL, - - NULL, /* 80 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 88 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 90 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 98 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* A0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* B0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* C0 */ - NULL, - SSE2_CMPSD, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - SSE3_ADDSUBPS, /* D0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - SSE2_MOVDQ2Q, - NULL, - NULL, /* D8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* E0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - SSE2_CVTPD2DQ, - NULL, - NULL, /* E8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - SSE3_LDDQU, /* F0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, -}; - -void (*insttable_2byteF30F_32[256])(void) = { - NULL, /* 00 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 08 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - SSE_MOVSSmem2xmm, /* 10 */ - SSE_MOVSSxmm2mem, - SSE3_MOVSLDUP, - NULL, - NULL, - NULL, - SSE3_MOVSHDUP, - NULL, - NULL, /* 18 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 20 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 28 */ - NULL, - SSE_CVTSI2SS, - SSE4a_MOVNTSS, - SSE_CVTTSS2SI, - SSE_CVTSS2SI, - NULL, - NULL, - - NULL, /* 30 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 40 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 48 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 50 */ - SSE_SQRTSS, - SSE_RSQRTSS, - SSE_RCPSS, - NULL, - NULL, - NULL, - NULL, - SSE_ADDSS, /* 58 */ - SSE_MULSS, - SSE2_CVTSS2SD, - SSE2_CVTTPS2DQ, - SSE_SUBSS, - SSE_MINSS, - SSE_DIVSS, - SSE_MAXSS, - - NULL, /* 60 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 68 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE2_MOVDQUmem2xmm, - - SSE2_PSHUFHW, /* 70 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 78 */ - NULL, - NULL, - NULL, - NULL, - NULL, - SSE2_MOVQmem2xmm, - SSE2_MOVDQUxmm2mem, - - NULL, /* 80 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 88 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* 90 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 98 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* A0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* B0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* C0 */ - NULL, - SSE_CMPSS, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* D0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - SSE2_MOVQ2DQ, - NULL, - NULL, /* D8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* E0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - SSE2_CVTDQ2PD, - NULL, - NULL, /* E8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - - NULL, /* F0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, -}; - -void (*insttable_2byte0F38_32[256])(void) = { - SSSE3_PSHUFB_MM, /* 00 */ - SSSE3_PHADDW_MM, - SSSE3_PHADDD_MM, - SSSE3_PHADDSW_MM, - SSSE3_PMADDUBSW_MM, - SSSE3_PHSUBW_MM, - SSSE3_PHSUBD_MM, - SSSE3_PHSUBSW_MM, - SSSE3_PSIGNB_MM, /* 08 */ - SSSE3_PSIGNW_MM, - SSSE3_PSIGND_MM, - SSSE3_PMULHRSW_MM, - NULL, - NULL, - NULL, - NULL, - NULL, /* 10 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 18 */ - NULL, - NULL, - NULL, - SSSE3_PABSB_MM, - SSSE3_PABSW_MM, - SSSE3_PABSD_MM, - NULL, - NULL, /* 20 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 28 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 30 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 40 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 48 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 50 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 58 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 60 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 68 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 70 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 78 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 80 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 88 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 90 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 98 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -void (*insttable_3byte660F38_32[256])(void) = { - SSSE3_PSHUFB, /* 00 */ - SSSE3_PHADDW, - SSSE3_PHADDD, - SSSE3_PHADDSW, - SSSE3_PMADDUBSW, - SSSE3_PHSUBW, - SSSE3_PHSUBD, - SSSE3_PHSUBSW, - SSSE3_PSIGNB, /* 08 */ - SSSE3_PSIGNW, - SSSE3_PSIGND, - SSSE3_PMULHRSW, - NULL, - NULL, - NULL, - NULL, - SSE4_1_PBLENDVB, /* 10 */ - NULL, - NULL, - NULL, - SSE4_1_BLENDVPS, - SSE4_1_BLENDVPD, - NULL, - SSE4_1_VPTEST, - NULL, /* 18 */ - NULL, - NULL, - NULL, - SSSE3_PABSB, - SSSE3_PABSW, - SSSE3_PABSD, - NULL, - SSE4_1_PMOVSXBW, /* 20 */ - SSE4_1_PMOVSXBD, - SSE4_1_PMOVSXBQ, - SSE4_1_PMOVSXWD, - SSE4_1_PMOVSXWQ, - SSE4_1_PMOVSXDQ, - NULL, - NULL, - SSE4_1_PMULDQ, /* 28 */ - SSE4_1_PCMPEQQ, - SSE4_1_MOVNTDQA, - SSE4_1_PACKUSDW, - NULL, - NULL, - NULL, - NULL, - SSE4_1_PMOVZXBW, /* 30 */ - SSE4_1_PMOVZXBD, - SSE4_1_PMOVZXBQ, - SSE4_1_PMOVZXWD, - SSE4_1_PMOVZXWQ, - SSE4_1_PMOVZXDQ, - NULL, - SSE4_2_PCMPGTQ, - SSE4_1_PMINSB, /* 38 */ - SSE4_1_PMINSD, - SSE4_1_PMINUW, - SSE4_1_PMINUD, - SSE4_1_PMAXSB, - SSE4_1_PMAXSD, - SSE4_1_PMAXUW, - SSE4_1_PMAXUD, - SSE4_1_PMULLD, /* 40 */ - SSE4_1_PHMINPOSUW, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 48 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 50 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 58 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 60 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 68 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 70 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 78 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 80 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 88 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 90 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 98 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -void (*insttable_2byte0F3A_32[256])(void) = { - NULL, /* 00 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 08 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSSE3_PALIGNR_MM, - NULL, /* 10 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 18 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 20 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 28 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 30 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 40 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 48 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 50 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 58 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 60 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 68 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 70 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 78 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 80 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 88 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 90 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 98 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -void (*insttable_3byte660F3A_32[256])(void) = { - NULL, /* 00 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE4_1_ROUNDPS, /* 08 */ - SSE4_1_ROUNDPD, - SSE4_1_ROUNDSS, - SSE4_1_ROUNDSD, - SSE4_1_PBLENDPS, - SSE4_1_PBLENDPD, - SSE4_1_PBLENDW, - SSSE3_PALIGNR, - NULL, /* 10 */ - NULL, - NULL, - NULL, - SSE4_1_PEXTRB, - SSE4_1_PEXTRW, - SSE4_1_PEXTRD, - SSE4_1_PEXTRACTPS, - NULL, /* 18 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE4_1_PINSRB, /* 20 */ - SSE4_1_INSERTPS, - SSE4_1_PINSRD, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 28 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 30 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE4_1_DPPS, /* 40 */ - SSE4_1_DPPD, - SSE4_1_MPSADBW, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 48 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 50 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 58 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE4_2_PCMPESTRM, /* 60 */ - SSE4_2_PCMPESTRI, - SSE4_2_PCMPISTRM, - SSE4_2_PCMPISTRI, - NULL, - NULL, - NULL, - NULL, - NULL, /* 68 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 70 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 78 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 80 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 88 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 90 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 98 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -void (*insttable_3byteF20F38_32[256])(void) = { - NULL, /* 00 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 08 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 10 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 18 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 20 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 28 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 30 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 40 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 48 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 50 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 58 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 60 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 68 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 70 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 78 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 80 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 88 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 90 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 98 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE4_2_POPCNT_32, /* B8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE4_2_CRC32_Gy_Eb, /* F0 */ - SSE4_2_CRC32_Gy_Ev, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - - -void (*insttable_3byteF20F38_16[256])(void) = { - NULL, /* 00 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 08 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 10 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 18 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 20 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 28 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 30 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 38 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 40 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 48 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 50 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 58 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 60 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 68 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 70 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 78 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 80 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 88 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 90 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* 98 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* A8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* B0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE4_2_POPCNT_16, /* B8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* C8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* D8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E0 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* E8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - SSE4_2_CRC32_Gy_Eb_16, /* F0 */ - SSE4_2_CRC32_Gy_Ev_16, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, /* F8 */ - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL -}; - - - -/* - * for group - */ - - /* group 1 */ -void (CPUCALL* insttable_G1EbIb[])(UINT8*, UINT32) = { - ADD_EbIb, - OR_EbIb, - ADC_EbIb, - SBB_EbIb, - AND_EbIb, - SUB_EbIb, - XOR_EbIb, - CMP_EbIb, -}; -void (CPUCALL* insttable_G1EbIb_ext[])(UINT32, UINT32) = { - ADD_EbIb_ext, - OR_EbIb_ext, - ADC_EbIb_ext, - SBB_EbIb_ext, - AND_EbIb_ext, - SUB_EbIb_ext, - XOR_EbIb_ext, - CMP_EbIb_ext, -}; - -void (CPUCALL* insttable_G1EwIx[])(UINT16*, UINT32) = { - ADD_EwIx, - OR_EwIx, - ADC_EwIx, - SBB_EwIx, - AND_EwIx, - SUB_EwIx, - XOR_EwIx, - CMP_EwIx, -}; -void (CPUCALL* insttable_G1EwIx_ext[])(UINT32, UINT32) = { - ADD_EwIx_ext, - OR_EwIx_ext, - ADC_EwIx_ext, - SBB_EwIx_ext, - AND_EwIx_ext, - SUB_EwIx_ext, - XOR_EwIx_ext, - CMP_EwIx_ext, -}; - -void (CPUCALL* insttable_G1EdIx[])(UINT32*, UINT32) = { - ADD_EdIx, - OR_EdIx, - ADC_EdIx, - SBB_EdIx, - AND_EdIx, - SUB_EdIx, - XOR_EdIx, - CMP_EdIx, -}; -void (CPUCALL* insttable_G1EdIx_ext[])(UINT32, UINT32) = { - ADD_EdIx_ext, - OR_EdIx_ext, - ADC_EdIx_ext, - SBB_EdIx_ext, - AND_EdIx_ext, - SUB_EdIx_ext, - XOR_EdIx_ext, - CMP_EdIx_ext, -}; - - -/* group 2 */ -void (CPUCALL* insttable_G2Eb[])(UINT8*) = { - ROL_Eb, - ROR_Eb, - RCL_Eb, - RCR_Eb, - SHL_Eb, - SHR_Eb, - SHL_Eb, - SAR_Eb, -}; -void (CPUCALL* insttable_G2Eb_ext[])(UINT32) = { - ROL_Eb_ext, - ROR_Eb_ext, - RCL_Eb_ext, - RCR_Eb_ext, - SHL_Eb_ext, - SHR_Eb_ext, - SHL_Eb_ext, - SAR_Eb_ext, -}; - -void (CPUCALL* insttable_G2Ew[])(UINT16*) = { - ROL_Ew, - ROR_Ew, - RCL_Ew, - RCR_Ew, - SHL_Ew, - SHR_Ew, - SHL_Ew, - SAR_Ew, -}; -void (CPUCALL* insttable_G2Ew_ext[])(UINT32) = { - ROL_Ew_ext, - ROR_Ew_ext, - RCL_Ew_ext, - RCR_Ew_ext, - SHL_Ew_ext, - SHR_Ew_ext, - SHL_Ew_ext, - SAR_Ew_ext, -}; - -void (CPUCALL* insttable_G2Ed[])(UINT32*) = { - ROL_Ed, - ROR_Ed, - RCL_Ed, - RCR_Ed, - SHL_Ed, - SHR_Ed, - SHL_Ed, - SAR_Ed, -}; -void (CPUCALL* insttable_G2Ed_ext[])(UINT32) = { - ROL_Ed_ext, - ROR_Ed_ext, - RCL_Ed_ext, - RCR_Ed_ext, - SHL_Ed_ext, - SHR_Ed_ext, - SHL_Ed_ext, - SAR_Ed_ext, -}; - -void (CPUCALL* insttable_G2EbCL[])(UINT8*, UINT) = { - ROL_EbCL, - ROR_EbCL, - RCL_EbCL, - RCR_EbCL, - SHL_EbCL, - SHR_EbCL, - SHL_EbCL, - SAR_EbCL, -}; -void (CPUCALL* insttable_G2EbCL_ext[])(UINT32, UINT) = { - ROL_EbCL_ext, - ROR_EbCL_ext, - RCL_EbCL_ext, - RCR_EbCL_ext, - SHL_EbCL_ext, - SHR_EbCL_ext, - SHL_EbCL_ext, - SAR_EbCL_ext, -}; - -void (CPUCALL* insttable_G2EwCL[])(UINT16*, UINT) = { - ROL_EwCL, - ROR_EwCL, - RCL_EwCL, - RCR_EwCL, - SHL_EwCL, - SHR_EwCL, - SHL_EwCL, - SAR_EwCL, -}; -void (CPUCALL* insttable_G2EwCL_ext[])(UINT32, UINT) = { - ROL_EwCL_ext, - ROR_EwCL_ext, - RCL_EwCL_ext, - RCR_EwCL_ext, - SHL_EwCL_ext, - SHR_EwCL_ext, - SHL_EwCL_ext, - SAR_EwCL_ext, -}; - -void (CPUCALL* insttable_G2EdCL[])(UINT32*, UINT) = { - ROL_EdCL, - ROR_EdCL, - RCL_EdCL, - RCR_EdCL, - SHL_EdCL, - SHR_EdCL, - SHL_EdCL, - SAR_EdCL, -}; -void (CPUCALL* insttable_G2EdCL_ext[])(UINT32, UINT) = { - ROL_EdCL_ext, - ROR_EdCL_ext, - RCL_EdCL_ext, - RCR_EdCL_ext, - SHL_EdCL_ext, - SHR_EdCL_ext, - SHL_EdCL_ext, - SAR_EdCL_ext, -}; - -/* group 3 */ -void (CPUCALL* insttable_G3Eb[])(UINT32) = { - TEST_EbIb, - TEST_EbIb, - NOT_Eb, - NEG_Eb, - MUL_ALEb, - IMUL_ALEb, - DIV_ALEb, - IDIV_ALEb, -}; - -void (CPUCALL* insttable_G3Ew[])(UINT32) = { - TEST_EwIw, - TEST_EwIw, - NOT_Ew, - NEG_Ew, - MUL_AXEw, - IMUL_AXEw, - DIV_AXEw, - IDIV_AXEw, -}; - -void (CPUCALL* insttable_G3Ed[])(UINT32) = { - TEST_EdId, - TEST_EdId, - NOT_Ed, - NEG_Ed, - MUL_EAXEd, - IMUL_EAXEd, - DIV_EAXEd, - IDIV_EAXEd, -}; - -/* group 4 */ -void (CPUCALL* insttable_G4[])(UINT32) = { - INC_Eb, - DEC_Eb, - undef_op2, - undef_op2, - undef_op2, - undef_op2, - undef_op2, - undef_op2, -}; - -/* group 5 */ -void (CPUCALL* insttable_G5Ew[])(UINT32) = { - INC_Ew, - DEC_Ew, - CALL_Ew, - CALL16_Ep, - JMP_Ew, - JMP16_Ep, - PUSH_Ew, - undef_op2, /* POP_Ew_G5 */ -}; - -void (CPUCALL* insttable_G5Ed[])(UINT32) = { - INC_Ed, - DEC_Ed, - CALL_Ed, - CALL32_Ep, - JMP_Ed, - JMP32_Ep, - PUSH_Ed, - undef_op2, /* POP_Ed_G5 */ -}; - -/* group 6 */ -void (CPUCALL* insttable_G6[])(UINT32) = { - SLDT_Ew, - STR_Ew, - LLDT_Ew, - LTR_Ew, - VERR_Ew, - VERW_Ew, - undef_op2, - undef_op2, -}; - -/* group 7 */ -void (CPUCALL* insttable_G7[])(UINT32) = { - SGDT_Ms, - SIDT_Ms, - LGDT_Ms, - LIDT_Ms, - SMSW_Ew, - undef_op2, - LMSW_Ew, - INVLPG, -}; - -/* group 8 */ -void (CPUCALL* insttable_G8EwIb[])(UINT32) = { - undef_op2, - undef_op2, - undef_op2, - undef_op2, - BT_EwIb, - BTS_EwIb, - BTR_EwIb, - BTC_EwIb, -}; - -void (CPUCALL* insttable_G8EdIb[])(UINT32) = { - undef_op2, - undef_op2, - undef_op2, - undef_op2, - BT_EdIb, - BTS_EdIb, - BTR_EdIb, - BTC_EdIb, -}; - -/* group 9 */ -void (CPUCALL* insttable_G9[])(UINT32) = { - undef_op2, - CMPXCHG8B, - undef_op2, - undef_op2, - undef_op2, - undef_op2, - undef_op2, - undef_op2, -}; +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" + +#include "inst_table.h" +#include "groups.h" + +#include "ia32/instructions/bin_arith.h" +#include "ia32/instructions/bit_byte.h" +#include "ia32/instructions/ctrl_trans.h" +#include "ia32/instructions/data_trans.h" +#include "ia32/instructions/dec_arith.h" +#include "ia32/instructions/flag_ctrl.h" +#include "ia32/instructions/logic_arith.h" +#include "ia32/instructions/misc_inst.h" +#include "ia32/instructions/seg_reg.h" +#include "ia32/instructions/shift_rotate.h" +#include "ia32/instructions/string_inst.h" +#include "ia32/instructions/system_inst.h" + +#include +#include "ia32/instructions/mmx/mmx.h" +#include "ia32/instructions/mmx/3dnow.h" +#include "ia32/instructions/sse/sse.h" +#include "ia32/instructions/sse2/sse2.h" +#include "ia32/instructions/sse3/sse3.h" +#include "ia32/instructions/ssse3/ssse3.h" +#include "ia32/instructions/sse4/sse4_1.h" +#include "ia32/instructions/sse4/sse4_2.h" +#include "ia32/instructions/sse4a/sse4a.h" + +/* + * UNDEF OP + */ +static void +undef_op(void) +{ + + EXCEPTION(UD_EXCEPTION, 0); +} + +static void CPUCALL +undef_op2(UINT32 v) +{ + + EXCEPTION(UD_EXCEPTION, 0); +} + + +UINT8 insttable_info[256] = { + 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 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + + 0, /* 20 */ + 0, + 0, + 0, + 0, + 0, + INST_PREFIX, /* ES: */ + 0, + 0, /* 28 */ + 0, + 0, + 0, + 0, + 0, + INST_PREFIX, /* CS: */ + 0, + + 0, /* 30 */ + 0, + 0, + 0, + 0, + 0, + INST_PREFIX, /* SS: */ + 0, + 0, /* 38 */ + 0, + 0, + 0, + 0, + 0, + INST_PREFIX, /* DS: */ + 0, + + 0, /* 40 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* 48 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + + 0, /* 50 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* 58 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + + 0, /* 60 */ + 0, + 0, + 0, + INST_PREFIX, /* FS: */ + INST_PREFIX, /* GS: */ + INST_PREFIX, /* OpSize: */ + INST_PREFIX, /* AddrSize: */ + 0, /* 68 */ + 0, + 0, + 0, + INST_STRING, /* INSB_YbDX */ + INST_STRING, /* INSW_YvDX */ + INST_STRING, /* OUTSB_DXXb */ + INST_STRING, /* OUTSW_DXXv */ + + 0, /* 70 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* 78 */ + 0, + 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 */ + 0, + 0, + INST_PREFIX, /* FWAIT */ + 0, + 0, + 0, + 0, + + 0, /* A0 */ + 0, + 0, + 0, + INST_STRING, /* MOVSB_XbYb */ + INST_STRING, /* MOVSW_XvYv */ + INST_STRING | REP_CHECKZF, /* CMPSB_XbYb */ + INST_STRING | REP_CHECKZF, /* CMPSW_XvYv */ + 0, /* A8 */ + 0, + INST_STRING, /* STOSB_YbAL */ + INST_STRING, /* STOSW_YveAX */ + INST_STRING, /* LODSB_ALXb */ + INST_STRING, /* LODSW_eAXXv */ + INST_STRING | REP_CHECKZF, /* SCASB_ALXb */ + INST_STRING | REP_CHECKZF, /* SCASW_eAXXv */ + + 0, /* B0 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* B8 */ + 0, + 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, + 0, + 0, + 0, + 0, + 0, + 0, + + 0, /* E0 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* E8 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + + INST_PREFIX, /* F0 *//* LOCK */ + 0, + INST_PREFIX, /* REPNE */ + INST_PREFIX, /* REPE */ + 0, + 0, + 0, + 0, + 0, /* F8 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, +}; + +void (*insttable_1byte[2][256])(void) = { + /* 16bit */ + { + ADD_EbGb, /* 00 */ + ADD_EwGw, + ADD_GbEb, + ADD_GwEw, + ADD_ALIb, + ADD_AXIw, + PUSH16_ES, + POP16_ES, + OR_EbGb, /* 08 */ + OR_EwGw, + OR_GbEb, + OR_GwEw, + OR_ALIb, + OR_AXIw, + PUSH16_CS, + _2byte_ESC16, + + ADC_EbGb, /* 10 */ + ADC_EwGw, + ADC_GbEb, + ADC_GwEw, + ADC_ALIb, + ADC_AXIw, + PUSH16_SS, + POP16_SS, + SBB_EbGb, /* 18 */ + SBB_EwGw, + SBB_GbEb, + SBB_GwEw, + SBB_ALIb, + SBB_AXIw, + PUSH16_DS, + POP16_DS, + + AND_EbGb, /* 20 */ + AND_EwGw, + AND_GbEb, + AND_GwEw, + AND_ALIb, + AND_AXIw, + Prefix_ES, + DAA, + SUB_EbGb, /* 28 */ + SUB_EwGw, + SUB_GbEb, + SUB_GwEw, + SUB_ALIb, + SUB_AXIw, + Prefix_CS, + DAS, + + XOR_EbGb, /* 30 */ + XOR_EwGw, + XOR_GbEb, + XOR_GwEw, + XOR_ALIb, + XOR_AXIw, + Prefix_SS, + AAA, + CMP_EbGb, /* 38 */ + CMP_EwGw, + CMP_GbEb, + CMP_GwEw, + CMP_ALIb, + CMP_AXIw, + Prefix_DS, + AAS, + + INC_AX, /* 40 */ + INC_CX, + INC_DX, + INC_BX, + INC_SP, + INC_BP, + INC_SI, + INC_DI, + DEC_AX, /* 48 */ + DEC_CX, + DEC_DX, + DEC_BX, + DEC_SP, + DEC_BP, + DEC_SI, + DEC_DI, + + PUSH_AX, /* 50 */ + PUSH_CX, + PUSH_DX, + PUSH_BX, + PUSH_SP, + PUSH_BP, + PUSH_SI, + PUSH_DI, + POP_AX, /* 58 */ + POP_CX, + POP_DX, + POP_BX, + POP_SP, + POP_BP, + POP_SI, + POP_DI, + + PUSHA, /* 60 */ + POPA, + BOUND_GwMa, + ARPL_EwGw, + Prefix_FS, + Prefix_GS, + OpSize, + AddrSize, + PUSH_Iw, /* 68 */ + IMUL_GwEwIw, + PUSH_Ib, + IMUL_GwEwIb, + INSB_YbDX, + INSW_YwDX, + OUTSB_DXXb, + OUTSW_DXXw, + + JO_Jb, /* 70 */ + JNO_Jb, + JC_Jb, + JNC_Jb, + JZ_Jb, + JNZ_Jb, + JNA_Jb, + JA_Jb, + JS_Jb, /* 78 */ + JNS_Jb, + JP_Jb, + JNP_Jb, + JL_Jb, + JNL_Jb, + JLE_Jb, + JNLE_Jb, + + Grp1_EbIb, /* 80 */ + Grp1_EwIw, + Grp1_EbIb, + Grp1_EwIb, + TEST_EbGb, + TEST_EwGw, + XCHG_EbGb, + XCHG_EwGw, + MOV_EbGb, /* 88 */ + MOV_EwGw, + MOV_GbEb, + MOV_GwEw, + MOV_EwSw, + LEA_GwM, + MOV_SwEw, + POP_Ew, + + _NOP, /* 90 */ + XCHG_CXAX, + XCHG_DXAX, + XCHG_BXAX, + XCHG_SPAX, + XCHG_BPAX, + XCHG_SIAX, + XCHG_DIAX, + CBW, /* 98 */ + CWD, + CALL16_Ap, + FPU_FWAIT, + PUSHF_Fw, + POPF_Fw, + SAHF, + LAHF, + + MOV_ALOb, /* A0 */ + MOV_AXOw, + MOV_ObAL, + MOV_OwAX, + MOVSB_XbYb, + MOVSW_XwYw, + CMPSB_XbYb, + CMPSW_XwYw, + TEST_ALIb, /* A8 */ + TEST_AXIw, + STOSB_YbAL, + STOSW_YwAX, + LODSB_ALXb, + LODSW_AXXw, + SCASB_ALXb, + SCASW_AXXw, + + MOV_ALIb, /* B0 */ + MOV_CLIb, + MOV_DLIb, + MOV_BLIb, + MOV_AHIb, + MOV_CHIb, + MOV_DHIb, + MOV_BHIb, + MOV_AXIw, /* B8 */ + MOV_CXIw, + MOV_DXIw, + MOV_BXIw, + MOV_SPIw, + MOV_BPIw, + MOV_SIIw, + MOV_DIIw, + + Grp2_EbIb, /* C0 */ + Grp2_EwIb, + RETnear16_Iw, + RETnear16, + LES_GwMp, + LDS_GwMp, + MOV_EbIb, + MOV_EwIw, + ENTER16_IwIb, /* C8 */ + LEAVE, + RETfar16_Iw, + RETfar16, + INT3, + INT_Ib, + INTO, + IRET, + + Grp2_Eb, /* D0 */ + Grp2_Ew, + Grp2_EbCL, + Grp2_EwCL, + AAM, + AAD, + SALC, /* undoc(8086) */ + XLAT, + NOFPU_ESC0, /* D8 */ + NOFPU_ESC1, + NOFPU_ESC2, + NOFPU_ESC3, + NOFPU_ESC4, + NOFPU_ESC5, + NOFPU_ESC6, + NOFPU_ESC7, + + LOOPNE_Jb, /* E0 */ + LOOPE_Jb, + LOOP_Jb, + JeCXZ_Jb, + IN_ALIb, + IN_AXIb, + OUT_IbAL, + OUT_IbAX, + CALL_Aw, /* E8 */ + JMP_Jw, + JMP16_Ap, + JMP_Jb, + IN_ALDX, + IN_AXDX, + OUT_DXAL, + OUT_DXAX, + + _LOCK, /* F0 */ + INT1, + _REPNE, + _REPE, + HLT, + CMC, + Grp3_Eb, + Grp3_Ew, + CLC, /* F8 */ + STC, + CLI, + STI, + CLD, + STD, + Grp4, + Grp5_Ew, + }, + + /* 32bit */ + { + ADD_EbGb, /* 00 */ + ADD_EdGd, + ADD_GbEb, + ADD_GdEd, + ADD_ALIb, + ADD_EAXId, + PUSH32_ES, + POP32_ES, + OR_EbGb, /* 08 */ + OR_EdGd, + OR_GbEb, + OR_GdEd, + OR_ALIb, + OR_EAXId, + PUSH32_CS, + _2byte_ESC32, + + ADC_EbGb, /* 10 */ + ADC_EdGd, + ADC_GbEb, + ADC_GdEd, + ADC_ALIb, + ADC_EAXId, + PUSH32_SS, + POP32_SS, + SBB_EbGb, /* 18 */ + SBB_EdGd, + SBB_GbEb, + SBB_GdEd, + SBB_ALIb, + SBB_EAXId, + PUSH32_DS, + POP32_DS, + + AND_EbGb, /* 20 */ + AND_EdGd, + AND_GbEb, + AND_GdEd, + AND_ALIb, + AND_EAXId, + undef_op, /* Prefix_ES */ + DAA, + SUB_EbGb, /* 28 */ + SUB_EdGd, + SUB_GbEb, + SUB_GdEd, + SUB_ALIb, + SUB_EAXId, + undef_op, /* Prefix_CS */ + DAS, + + XOR_EbGb, /* 30 */ + XOR_EdGd, + XOR_GbEb, + XOR_GdEd, + XOR_ALIb, + XOR_EAXId, + undef_op, /* Prefix_SS */ + AAA, + CMP_EbGb, /* 38 */ + CMP_EdGd, + CMP_GbEb, + CMP_GdEd, + CMP_ALIb, + CMP_EAXId, + undef_op, /* Prefix_DS */ + AAS, + + INC_EAX, /* 40 */ + INC_ECX, + INC_EDX, + INC_EBX, + INC_ESP, + INC_EBP, + INC_ESI, + INC_EDI, + DEC_EAX, /* 48 */ + DEC_ECX, + DEC_EDX, + DEC_EBX, + DEC_ESP, + DEC_EBP, + DEC_ESI, + DEC_EDI, + + PUSH_EAX, /* 50 */ + PUSH_ECX, + PUSH_EDX, + PUSH_EBX, + PUSH_ESP, + PUSH_EBP, + PUSH_ESI, + PUSH_EDI, + POP_EAX, /* 58 */ + POP_ECX, + POP_EDX, + POP_EBX, + POP_ESP, + POP_EBP, + POP_ESI, + POP_EDI, + + PUSHAD, /* 60 */ + POPAD, + BOUND_GdMa, + ARPL_EwGw, + undef_op, /* Prefix_FS */ + undef_op, /* Prefix_GS */ + undef_op, /* OpSize */ + undef_op, /* AddrSize */ + PUSH_Id, /* 68 */ + IMUL_GdEdId, + PUSH_Ib, + IMUL_GdEdIb, + INSB_YbDX, + INSD_YdDX, + OUTSB_DXXb, + OUTSD_DXXd, + + JO_Jb, /* 70 */ + JNO_Jb, + JC_Jb, + JNC_Jb, + JZ_Jb, + JNZ_Jb, + JNA_Jb, + JA_Jb, + JS_Jb, /* 78 */ + JNS_Jb, + JP_Jb, + JNP_Jb, + JL_Jb, + JNL_Jb, + JLE_Jb, + JNLE_Jb, + + Grp1_EbIb, /* 80 */ + Grp1_EdId, + Grp1_EbIb, + Grp1_EdIb, + TEST_EbGb, + TEST_EdGd, + XCHG_EbGb, + XCHG_EdGd, + MOV_EbGb, /* 88 */ + MOV_EdGd, + MOV_GbEb, + MOV_GdEd, + MOV_EdSw, + LEA_GdM, + MOV_SwEw, + POP_Ed, + + _NOP, /* 90 */ + XCHG_ECXEAX, + XCHG_EDXEAX, + XCHG_EBXEAX, + XCHG_ESPEAX, + XCHG_EBPEAX, + XCHG_ESIEAX, + XCHG_EDIEAX, + CWDE, /* 98 */ + CDQ, + CALL32_Ap, + undef_op, /* FWAIT */ + PUSHFD_Fd, + POPFD_Fd, + SAHF, + LAHF, + + MOV_ALOb, /* A0 */ + MOV_EAXOd, + MOV_ObAL, + MOV_OdEAX, + MOVSB_XbYb, + MOVSD_XdYd, + CMPSB_XbYb, + CMPSD_XdYd, + TEST_ALIb, /* A8 */ + TEST_EAXId, + STOSB_YbAL, + STOSD_YdEAX, + LODSB_ALXb, + LODSD_EAXXd, + SCASB_ALXb, + SCASD_EAXXd, + + MOV_ALIb, /* B0 */ + MOV_CLIb, + MOV_DLIb, + MOV_BLIb, + MOV_AHIb, + MOV_CHIb, + MOV_DHIb, + MOV_BHIb, + MOV_EAXId, /* B8 */ + MOV_ECXId, + MOV_EDXId, + MOV_EBXId, + MOV_ESPId, + MOV_EBPId, + MOV_ESIId, + MOV_EDIId, + + Grp2_EbIb, /* C0 */ + Grp2_EdIb, + RETnear32_Iw, + RETnear32, + LES_GdMp, + LDS_GdMp, + MOV_EbIb, + MOV_EdId, + ENTER32_IwIb, /* C8 */ + LEAVE, + RETfar32_Iw, + RETfar32, + INT3, + INT_Ib, + INTO, + IRET, + + Grp2_Eb, /* D0 */ + Grp2_Ed, + Grp2_EbCL, + Grp2_EdCL, + AAM, + AAD, + SALC, /* undoc(8086) */ + XLAT, + NOFPU_ESC0, /* D8 */ + NOFPU_ESC1, + NOFPU_ESC2, + NOFPU_ESC3, + NOFPU_ESC4, + NOFPU_ESC5, + NOFPU_ESC6, + NOFPU_ESC7, + + LOOPNE_Jb, /* E0 */ + LOOPE_Jb, + LOOP_Jb, + JeCXZ_Jb, + IN_ALIb, + IN_EAXIb, + OUT_IbAL, + OUT_IbEAX, + CALL_Ad, /* E8 */ + JMP_Jd, + JMP32_Ap, + JMP_Jb, + IN_ALDX, + IN_EAXDX, + OUT_DXAL, + OUT_DXEAX, + + _LOCK, /* F0 */ + INT1, + undef_op, /* repne */ + undef_op, /* repe */ + HLT, + CMC, + Grp3_Eb, + Grp3_Ed, + CLC, /* F8 */ + STC, + CLI, + STI, + CLD, + STD, + Grp4, + Grp5_Ed, + }, +}; + + +void (*insttable_1byte_repfunc[2][256])(int reptype) = { + /* 16bit */ + { + NULL, /* 00 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 08 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 10 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 18 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 28 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 30 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 40 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 48 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 50 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 58 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 60 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 68 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 70 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 78 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 80 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 88 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 90 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 98 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* A0 */ + NULL, + NULL, + NULL, + MOVSB_XbYb_rep, + MOVSW_XwYw_rep, + CMPSB_XbYb_rep, + CMPSW_XwYw_rep, + NULL, /* A8 */ + NULL, + STOSB_YbAL_rep, + STOSW_YwAX_rep, + NULL, + NULL, + NULL, + NULL, + + NULL, /* B0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* C0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* D0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* undoc(8086) */ + NULL, + NULL, /* D8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* E0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* F0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + }, + + /* 32bit */ + { + NULL, /* 00 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 08 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 10 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 18 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 28 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 30 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 40 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 48 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 50 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 58 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 60 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 68 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 70 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 78 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 80 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 88 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 90 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 98 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* A0 */ + NULL, + NULL, + NULL, + MOVSB_XbYb_rep, + MOVSD_XdYd_rep, + CMPSB_XbYb_rep, + CMPSD_XdYd_rep, + NULL, /* A8 */ + NULL, + STOSB_YbAL_rep, + STOSD_YdEAX_rep, + NULL, + NULL, + NULL, + NULL, + + NULL, /* B0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* C0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* D0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* undoc(8086) */ + NULL, + NULL, /* D8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* E0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* F0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + }, +}; + +void (*insttable_2byte[2][256])(void) = { + /* 16bit */ + { + Grp6, /* 00 */ + Grp7, + LAR_GwEw, + LSL_GwEw, + undef_op, + LOADALL286, /* undoc(286) */ + CLTS, + LOADALL, + INVD, /* 08 */ + WBINVD, + undef_op, + UD2, + undef_op, + AMD3DNOW_PREFETCH, + AMD3DNOW_FEMMS, + undef_op, + + SSE_MOVUPSmem2xmm, /* 10 */ + SSE_MOVUPSxmm2mem, + SSE_MOVLPSmem2xmm, // + MOVHLPS + SSE_MOVLPSxmm2mem, + SSE_UNPCKLPS, + SSE_UNPCKHPS, + SSE_MOVHPSmem2xmm, // + MOVLHPS + SSE_MOVHPSxmm2mem, + SSE_PREFETCHTx, /* 18 */ + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + + MOV_RdCd, /* 20 */ + MOV_RdDd, + MOV_CdRd, + MOV_DdRd, + MOV_RdTd, + undef_op, + MOV_TdRd, + undef_op, + SSE_MOVAPSmem2xmm, /* 28 */ + SSE_MOVAPSxmm2mem, + SSE_CVTPI2PS, + SSE_MOVNTPS, + SSE_CVTTPS2PI, + SSE_CVTPS2PI, + SSE_UCOMISS, + SSE_COMISS, + + WRMSR, /* 30 */ + RDTSC, + RDMSR, + RDPMC, + SYSENTER, + SYSEXIT, + undef_op, + undef_op, + _3byte_38ESC_16, /* 38 */ + undef_op, + _3byte_3AESC, + undef_op, + undef_op, + undef_op, + undef_op, + undef_op, + + CMOVO_GwEw, /* 40 */ + CMOVNO_GwEw, + CMOVC_GwEw, + CMOVNC_GwEw, + CMOVZ_GwEw, + CMOVNZ_GwEw, + CMOVNA_GwEw, + CMOVA_GwEw, + CMOVS_GwEw, /* 48 */ + CMOVNS_GwEw, + CMOVP_GwEw, + CMOVNP_GwEw, + CMOVL_GwEw, + CMOVNL_GwEw, + CMOVLE_GwEw, + CMOVNLE_GwEw, + + SSE_MOVMSKPS, /* 50 */ + SSE_SQRTPS, + SSE_RSQRTPS, + SSE_RCPPS, + SSE_ANDPS, + SSE_ANDNPS, + SSE_ORPS, + SSE_XORPS, + SSE_ADDPS, /* 58 */ + SSE_MULPS, + SSE2_CVTPS2PD, + SSE2_CVTDQ2PS, + SSE_SUBPS, + SSE_MINPS, + SSE_DIVPS, + SSE_MAXPS, + + MMX_PUNPCKLBW, /* 60 */ + MMX_PUNPCKLWD, + MMX_PUNPCKLDQ, + MMX_PACKSSWB, + MMX_PCMPGTB, + MMX_PCMPGTW, + MMX_PCMPGTD, + MMX_PACKUSWB, + MMX_PUNPCKHBW, /* 68 */ + MMX_PUNPCKHWD, + MMX_PUNPCKHDQ, + MMX_PACKSSDW, + undef_op, + undef_op, + MMX_MOVD_mm_rm32, + MMX_MOVQ_mm_mmm64, + + SSE_PSHUFW, /* 70 */ + MMX_PSxxW_imm8, + MMX_PSxxD_imm8, + MMX_PSxxQ_imm8, + MMX_PCMPEQB, + MMX_PCMPEQW, + MMX_PCMPEQD, + MMX_EMMS, + undef_op, /* 78 */ + undef_op, + undef_op, + undef_op, + undef_op, + undef_op, + MMX_MOVD_rm32_mm, + MMX_MOVQ_mmm64_mm, + + JO_Jw, /* 80 */ + JNO_Jw, + JC_Jw, + JNC_Jw, + JZ_Jw, + JNZ_Jw, + JNA_Jw, + JA_Jw, + JS_Jw, /* 88 */ + JNS_Jw, + JP_Jw, + JNP_Jw, + JL_Jw, + JNL_Jw, + JLE_Jw, + JNLE_Jw, + + SETO_Eb, /* 90 */ + SETNO_Eb, + SETC_Eb, + SETNC_Eb, + SETZ_Eb, + SETNZ_Eb, + SETNA_Eb, + SETA_Eb, + SETS_Eb, /* 98 */ + SETNS_Eb, + SETP_Eb, + SETNP_Eb, + SETL_Eb, + SETNL_Eb, + SETLE_Eb, + SETNLE_Eb, + + PUSH16_FS, /* A0 */ + POP16_FS, + _CPUID, + BT_EwGw, + SHLD_EwGwIb, + SHLD_EwGwCL, + CMPXCHG_EbGb, /* undoc(486) */ + CMPXCHG_EwGw, /* undoc(486) */ + PUSH16_GS, /* A8 */ + POP16_GS, + RSM, + BTS_EwGw, + SHRD_EwGwIb, + SHRD_EwGwCL, + NOFPU_FPU_FXSAVERSTOR, // + LDMXCSR + STMXCSR + SFENCE + LFENCE + CLFLUSH + IMUL_GwEw, + + CMPXCHG_EbGb, /* B0 */ + CMPXCHG_EwGw, + LSS_GwMp, + BTR_EwGw, + LFS_GwMp, + LGS_GwMp, + MOVZX_GwEb, + MOVZX_GwEw, + undef_op, /* B8 */ + UD2, + Grp8_EwIb, + BTC_EwGw, + BSF_GwEw, + BSR_GwEw, + MOVSX_GwEb, + MOVSX_GwEw, + + XADD_EbGb, /* C0 */ + XADD_EwGw, + SSE_CMPPS, + undef_op, + SSE_PINSRW, + SSE_PEXTRW, + SSE_SHUFPS, + Grp9, + BSWAP_EAX, /* C8 */ + BSWAP_ECX, + BSWAP_EDX, + BSWAP_EBX, + BSWAP_ESP, + BSWAP_EBP, + BSWAP_ESI, + BSWAP_EDI, + + undef_op, /* D0 */ + MMX_PSRLW, + MMX_PSRLD, + MMX_PSRLQ, + SSE2_PADDQmm, + MMX_PMULLW, + undef_op, + SSE_PMOVMSKB, + MMX_PSUBUSB, /* D8 */ + MMX_PSUBUSW, + SSE_PMINUB, + MMX_PAND, + MMX_PADDUSB, + MMX_PADDUSW, + SSE_PMAXUB, + MMX_PANDN, + + SSE_PAVGB, /* E0 */ + MMX_PSRAW, + MMX_PSRAD, + SSE_PAVGW, + SSE_PMULHUW, + MMX_PMULHW, + undef_op, + SSE_MOVNTQ, + MMX_PSUBSB, /* E8 */ + MMX_PSUBSW, + SSE_PMINSW, + MMX_POR, + MMX_PADDSB, + MMX_PADDSW, + SSE_PMAXSW, + MMX_PXOR, + + AMD3DNOW_F0, /* F0 */ + MMX_PSLLW, + MMX_PSLLD, + MMX_PSLLQ, + SSE2_PMULUDQmm, + MMX_PMADDWD, + SSE_PSADBW, + SSE_MASKMOVQ, + MMX_PSUBB, /* F8 */ + MMX_PSUBW, + MMX_PSUBD, + SSE2_PSUBQmm, + MMX_PADDB, + MMX_PADDW, + MMX_PADDD, + undef_op, + }, + + /* 32bit */ + { + Grp6, /* 00 */ + Grp7, + LAR_GdEw, + LSL_GdEw, + undef_op, + LOADALL286, /* undoc(286) */ + CLTS, + LOADALL, + INVD, /* 08 */ + WBINVD, + undef_op, + UD2, + undef_op, + AMD3DNOW_PREFETCH, + AMD3DNOW_FEMMS, + undef_op, + + SSE_MOVUPSmem2xmm, /* 10 */ + SSE_MOVUPSxmm2mem, + SSE_MOVLPSmem2xmm, // + MOVHLPS + SSE_MOVLPSxmm2mem, + SSE_UNPCKLPS, + SSE_UNPCKHPS, + SSE_MOVHPSmem2xmm, // + MOVLHPS + SSE_MOVHPSxmm2mem, + SSE_PREFETCHTx, /* 18 */ + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + SSE_NOPPREFETCH, + + MOV_RdCd, /* 20 */ + MOV_RdDd, + MOV_CdRd, + MOV_DdRd, + MOV_RdTd, + undef_op, + MOV_TdRd, + undef_op, + SSE_MOVAPSmem2xmm, /* 28 */ + SSE_MOVAPSxmm2mem, + SSE_CVTPI2PS, + SSE_MOVNTPS, + SSE_CVTTPS2PI, + SSE_CVTPS2PI, + SSE_UCOMISS, + SSE_COMISS, + + WRMSR, /* 30 */ + RDTSC, + RDMSR, + RDPMC, + SYSENTER, + SYSEXIT, + undef_op, + undef_op, + _3byte_38ESC, /* 38 */ + undef_op, + _3byte_3AESC, + undef_op, + undef_op, + undef_op, + undef_op, + undef_op, + + CMOVO_GdEd, /* 40 */ + CMOVNO_GdEd, + CMOVC_GdEd, + CMOVNC_GdEd, + CMOVZ_GdEd, + CMOVNZ_GdEd, + CMOVNA_GdEd, + CMOVA_GdEd, + CMOVS_GdEd, /* 48 */ + CMOVNS_GdEd, + CMOVP_GdEd, + CMOVNP_GdEd, + CMOVL_GdEd, + CMOVNL_GdEd, + CMOVLE_GdEd, + CMOVNLE_GdEd, + + SSE_MOVMSKPS, /* 50 */ + SSE_SQRTPS, + SSE_RSQRTPS, + SSE_RCPPS, + SSE_ANDPS, + SSE_ANDNPS, + SSE_ORPS, + SSE_XORPS, + SSE_ADDPS, /* 58 */ + SSE_MULPS, + SSE2_CVTPS2PD, + SSE2_CVTDQ2PS, + SSE_SUBPS, + SSE_MINPS, + SSE_DIVPS, + SSE_MAXPS, + + MMX_PUNPCKLBW, /* 60 */ + MMX_PUNPCKLWD, + MMX_PUNPCKLDQ, + MMX_PACKSSWB, + MMX_PCMPGTB, + MMX_PCMPGTW, + MMX_PCMPGTD, + MMX_PACKUSWB, + MMX_PUNPCKHBW, /* 68 */ + MMX_PUNPCKHWD, + MMX_PUNPCKHDQ, + MMX_PACKSSDW, + undef_op, + undef_op, + MMX_MOVD_mm_rm32, + MMX_MOVQ_mm_mmm64, + + SSE_PSHUFW, /* 70 */ + MMX_PSxxW_imm8, + MMX_PSxxD_imm8, + MMX_PSxxQ_imm8, + MMX_PCMPEQB, + MMX_PCMPEQW, + MMX_PCMPEQD, + MMX_EMMS, + undef_op, /* 78 */ + undef_op, + undef_op, + undef_op, + undef_op, + undef_op, + MMX_MOVD_rm32_mm, + MMX_MOVQ_mmm64_mm, + + JO_Jd, /* 80 */ + JNO_Jd, + JC_Jd, + JNC_Jd, + JZ_Jd, + JNZ_Jd, + JNA_Jd, + JA_Jd, + JS_Jd, /* 88 */ + JNS_Jd, + JP_Jd, + JNP_Jd, + JL_Jd, + JNL_Jd, + JLE_Jd, + JNLE_Jd, + + SETO_Eb, /* 90 */ + SETNO_Eb, + SETC_Eb, + SETNC_Eb, + SETZ_Eb, + SETNZ_Eb, + SETNA_Eb, + SETA_Eb, + SETS_Eb, /* 98 */ + SETNS_Eb, + SETP_Eb, + SETNP_Eb, + SETL_Eb, + SETNL_Eb, + SETLE_Eb, + SETNLE_Eb, + + PUSH32_FS, /* A0 */ + POP32_FS, + _CPUID, + BT_EdGd, + SHLD_EdGdIb, + SHLD_EdGdCL, + CMPXCHG_EbGb, /* undoc(486) */ + CMPXCHG_EdGd, /* undoc(486) */ + PUSH32_GS, /* A8 */ + POP32_GS, + RSM, + BTS_EdGd, + SHRD_EdGdIb, + SHRD_EdGdCL, + NOFPU_FPU_FXSAVERSTOR, // + LDMXCSR + STMXCSR + SFENCE + LFENCE + CLFLUSH + IMUL_GdEd, + + CMPXCHG_EbGb, /* B0 */ + CMPXCHG_EdGd, + LSS_GdMp, + BTR_EdGd, + LFS_GdMp, + LGS_GdMp, + MOVZX_GdEb, + MOVZX_GdEw, + undef_op, /* B8 */ + UD2, + Grp8_EdIb, + BTC_EdGd, + BSF_GdEd, + BSR_GdEd, + MOVSX_GdEb, + MOVSX_GdEw, + + XADD_EbGb, /* C0 */ + XADD_EdGd, + SSE_CMPPS, + SSE2_MOVNTI, + SSE_PINSRW, + SSE_PEXTRW, + SSE_SHUFPS, + Grp9, + BSWAP_EAX, /* C8 */ + BSWAP_ECX, + BSWAP_EDX, + BSWAP_EBX, + BSWAP_ESP, + BSWAP_EBP, + BSWAP_ESI, + BSWAP_EDI, + + undef_op, /* D0 */ + MMX_PSRLW, + MMX_PSRLD, + MMX_PSRLQ, + SSE2_PADDQmm, + MMX_PMULLW, + undef_op, + SSE_PMOVMSKB, + MMX_PSUBUSB, /* D8 */ + MMX_PSUBUSW, + SSE_PMINUB, + MMX_PAND, + MMX_PADDUSB, + MMX_PADDUSW, + SSE_PMAXUB, + MMX_PANDN, + + SSE_PAVGB, /* E0 */ + MMX_PSRAW, + MMX_PSRAD, + SSE_PAVGW, + SSE_PMULHUW, + MMX_PMULHW, + undef_op, + SSE_MOVNTQ, + MMX_PSUBSB, /* E8 */ + MMX_PSUBSW, + SSE_PMINSW, + MMX_POR, + MMX_PADDSB, + MMX_PADDSW, + SSE_PMAXSW, + MMX_PXOR, + + AMD3DNOW_F0, /* F0 */ + MMX_PSLLW, + MMX_PSLLD, + MMX_PSLLQ, + SSE2_PMULUDQmm, + MMX_PMADDWD, + SSE_PSADBW, + SSE_MASKMOVQ, + MMX_PSUBB, /* F8 */ + MMX_PSUBW, + MMX_PSUBD, + SSE2_PSUBQmm, + MMX_PADDB, + MMX_PADDW, + MMX_PADDD, + undef_op, + }, +}; + +void (*insttable_2byte660F_32[256])(void) = { + NULL, /* 00 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 08 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + SSE2_MOVUPDmem2xmm, /* 10 */ + SSE2_MOVUPDxmm2mem, + SSE2_MOVLPDmem2xmm, + SSE2_MOVLPDxmm2mem, + SSE2_UNPCKLPD, + SSE2_UNPCKHPD, + SSE2_MOVHPDmem2xmm, + SSE2_MOVHPDxmm2mem, + NULL, /* 18 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE2_MOVAPDmem2xmm, /* 28 */ + SSE2_MOVAPDxmm2mem, + SSE2_CVTPI2PD, + SSE2_MOVNTPD, + SSE2_CVTTPD2PI, + SSE2_CVTPD2PI, + SSE2_UCOMISD, + SSE2_COMISD, + + NULL, /* 30 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 40 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 48 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + SSE2_MOVMSKPD, /* 50 */ + SSE2_SQRTPD, + NULL, + NULL, + SSE2_ANDPD, + SSE2_ANDNPD, + SSE2_ORPD, + SSE2_XORPD, + SSE2_ADDPD, /* 58 */ + SSE2_MULPD, + SSE2_CVTPD2PS, + SSE2_CVTPS2DQ, + SSE2_SUBPD, + SSE2_MINPD, + SSE2_DIVPD, + SSE2_MAXPD, + + SSE2_PUNPCKLBW, /* 60 */ + SSE2_PUNPCKLWD, + SSE2_PUNPCKLDQ, + SSE2_PACKSSWB, + SSE2_PCMPGTB, + SSE2_PCMPGTW, + SSE2_PCMPGTD, + SSE2_PACKUSWB, + SSE2_PUNPCKHBW, /* 68 */ + SSE2_PUNPCKHWD, + SSE2_PUNPCKHDQ, + SSE2_PACKSSDW, + SSE2_PUNPCKLQDQ, + SSE2_PUNPCKHQDQ, + SSE2_MOVDrm2xmm, + SSE2_MOVDQAmem2xmm, + + SSE2_PSHUFD, /* 70 */ + SSE2_PSxxWimm, // PSLLWimm + PSRAWimm + PSRLWimm + SSE2_PSxxDimm, // PSLLDimm + PSRADimm + PSRLDimm + SSE2_PSxxQimm, // PSLLQimm + PSRAQimm + PSRLQimm + PSLLDQ + PSRLDQ + SSE2_PCMPEQB, + SSE2_PCMPEQW, + SSE2_PCMPEQD, + NULL, + SSE4a_EXTRQimm, /* 78 */ + SSE4a_EXTRQxmm, + NULL, + NULL, + SSE3_HADDPD, + SSE3_HSUBPD, + SSE2_MOVDxmm2rm, + SSE2_MOVDQAxmm2mem, + + NULL, /* 80 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 88 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 90 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 98 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* A0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* B0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* C0 */ + NULL, + SSE2_CMPPD, + SSE2_MOVNTI, + SSE2_PINSRW, + SSE2_PEXTRW, + SSE2_SHUFPD, + NULL, + NULL, /* C8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + SSE3_ADDSUBPD, /* D0 */ + SSE2_PSRLW, + SSE2_PSRLD, + SSE2_PSRLQ, + SSE2_PADDQxmm, + SSE2_PMULLW, + SSE2_MOVQxmm2mem, + SSE2_PMOVMSKB, + SSE2_PSUBUSB, /* D8 */ + SSE2_PSUBUSW, + SSE2_PMINUB, + SSE2_PAND, + SSE2_PADDUSB, + SSE2_PADDUSW, + SSE2_PMAXUB, + SSE2_PANDN, + + SSE2_PAVGB, /* E0 */ + SSE2_PSRAW, + SSE2_PSRAD, + SSE2_PAVGW, + SSE2_PMULHUW, + SSE2_PMULHW, + SSE2_CVTTPD2DQ, + SSE2_MOVNTDQ, + SSE2_PSUBSB, /* E8 */ + SSE2_PSUBSW, + SSE2_PMINSW, + SSE2_POR, + SSE2_PADDSB, + SSE2_PADDSW, + SSE2_PMAXSW, + SSE2_PXOR, + + NULL, /* F0 */ + SSE2_PSLLW, + SSE2_PSLLD, + SSE2_PSLLQ, + SSE2_PMULUDQxmm, + SSE2_PMADD, + SSE2_PSADBW, + SSE2_MASKMOVDQU, + SSE2_PSUBB, /* F8 */ + SSE2_PSUBW, + SSE2_PSUBD, + SSE2_PSUBQxmm, + SSE2_PADDB, + SSE2_PADDW, + SSE2_PADDD, + NULL, +}; + +void (*insttable_2byteF20F_32[256])(void) = { + NULL, /* 00 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 08 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + SSE2_MOVSDmem2xmm, /* 10 */ + SSE2_MOVSDxmm2mem, + SSE3_MOVDDUP, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 18 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 28 */ + NULL, + SSE2_CVTSI2SD, + SSE4a_MOVNTSD, + SSE2_CVTTSD2SI, + SSE2_CVTSD2SI, + NULL, + NULL, + + NULL, /* 30 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 40 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 48 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 50 */ + SSE2_SQRTSD, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE2_ADDSD, /* 58 */ + SSE2_MULSD, + SSE2_CVTSD2SS, + NULL, + SSE2_SUBSD, + SSE2_MINSD, + SSE2_DIVSD, + SSE2_MAXSD, + + NULL, /* 60 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 68 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + SSE2_PSHUFLW, /* 70 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE4a_INSERTQimm, /* 78 */ + SSE4a_INSERTQxmm, + NULL, + NULL, + SSE3_HADDPS, + SSE3_HSUBPS, + NULL, + NULL, + + NULL, /* 80 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 88 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 90 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 98 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* A0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* B0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* C0 */ + NULL, + SSE2_CMPSD, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + SSE3_ADDSUBPS, /* D0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + SSE2_MOVDQ2Q, + NULL, + NULL, /* D8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* E0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + SSE2_CVTPD2DQ, + NULL, + NULL, /* E8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + SSE3_LDDQU, /* F0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +void (*insttable_2byteF30F_32[256])(void) = { + NULL, /* 00 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 08 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + SSE_MOVSSmem2xmm, /* 10 */ + SSE_MOVSSxmm2mem, + SSE3_MOVSLDUP, + NULL, + NULL, + NULL, + SSE3_MOVSHDUP, + NULL, + NULL, /* 18 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 28 */ + NULL, + SSE_CVTSI2SS, + SSE4a_MOVNTSS, + SSE_CVTTSS2SI, + SSE_CVTSS2SI, + NULL, + NULL, + + NULL, /* 30 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 40 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 48 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 50 */ + SSE_SQRTSS, + SSE_RSQRTSS, + SSE_RCPSS, + NULL, + NULL, + NULL, + NULL, + SSE_ADDSS, /* 58 */ + SSE_MULSS, + SSE2_CVTSS2SD, + SSE2_CVTTPS2DQ, + SSE_SUBSS, + SSE_MINSS, + SSE_DIVSS, + SSE_MAXSS, + + NULL, /* 60 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 68 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE2_MOVDQUmem2xmm, + + SSE2_PSHUFHW, /* 70 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 78 */ + NULL, + NULL, + NULL, + NULL, + NULL, + SSE2_MOVQmem2xmm, + SSE2_MOVDQUxmm2mem, + + NULL, /* 80 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 88 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* 90 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 98 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* A0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* B0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* C0 */ + NULL, + SSE_CMPSS, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* D0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + SSE2_MOVQ2DQ, + NULL, + NULL, /* D8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* E0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + SSE2_CVTDQ2PD, + NULL, + NULL, /* E8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + NULL, /* F0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +void (*insttable_2byte0F38_32[256])(void) = { + SSSE3_PSHUFB_MM, /* 00 */ + SSSE3_PHADDW_MM, + SSSE3_PHADDD_MM, + SSSE3_PHADDSW_MM, + SSSE3_PMADDUBSW_MM, + SSSE3_PHSUBW_MM, + SSSE3_PHSUBD_MM, + SSSE3_PHSUBSW_MM, + SSSE3_PSIGNB_MM, /* 08 */ + SSSE3_PSIGNW_MM, + SSSE3_PSIGND_MM, + SSSE3_PMULHRSW_MM, + NULL, + NULL, + NULL, + NULL, + NULL, /* 10 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 18 */ + NULL, + NULL, + NULL, + SSSE3_PABSB_MM, + SSSE3_PABSW_MM, + SSSE3_PABSD_MM, + NULL, + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 28 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 30 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 40 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 48 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 50 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 58 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 60 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 68 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 70 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 78 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 80 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 88 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 90 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 98 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +void (*insttable_3byte660F38_32[256])(void) = { + SSSE3_PSHUFB, /* 00 */ + SSSE3_PHADDW, + SSSE3_PHADDD, + SSSE3_PHADDSW, + SSSE3_PMADDUBSW, + SSSE3_PHSUBW, + SSSE3_PHSUBD, + SSSE3_PHSUBSW, + SSSE3_PSIGNB, /* 08 */ + SSSE3_PSIGNW, + SSSE3_PSIGND, + SSSE3_PMULHRSW, + NULL, + NULL, + NULL, + NULL, + SSE4_1_PBLENDVB, /* 10 */ + NULL, + NULL, + NULL, + SSE4_1_BLENDVPS, + SSE4_1_BLENDVPD, + NULL, + SSE4_1_VPTEST, + NULL, /* 18 */ + NULL, + NULL, + NULL, + SSSE3_PABSB, + SSSE3_PABSW, + SSSE3_PABSD, + NULL, + SSE4_1_PMOVSXBW, /* 20 */ + SSE4_1_PMOVSXBD, + SSE4_1_PMOVSXBQ, + SSE4_1_PMOVSXWD, + SSE4_1_PMOVSXWQ, + SSE4_1_PMOVSXDQ, + NULL, + NULL, + SSE4_1_PMULDQ, /* 28 */ + SSE4_1_PCMPEQQ, + SSE4_1_MOVNTDQA, + SSE4_1_PACKUSDW, + NULL, + NULL, + NULL, + NULL, + SSE4_1_PMOVZXBW, /* 30 */ + SSE4_1_PMOVZXBD, + SSE4_1_PMOVZXBQ, + SSE4_1_PMOVZXWD, + SSE4_1_PMOVZXWQ, + SSE4_1_PMOVZXDQ, + NULL, + SSE4_2_PCMPGTQ, + SSE4_1_PMINSB, /* 38 */ + SSE4_1_PMINSD, + SSE4_1_PMINUW, + SSE4_1_PMINUD, + SSE4_1_PMAXSB, + SSE4_1_PMAXSD, + SSE4_1_PMAXUW, + SSE4_1_PMAXUD, + SSE4_1_PMULLD, /* 40 */ + SSE4_1_PHMINPOSUW, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 48 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 50 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 58 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 60 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 68 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 70 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 78 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 80 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 88 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 90 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 98 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +void (*insttable_2byte0F3A_32[256])(void) = { + NULL, /* 00 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 08 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSSE3_PALIGNR_MM, + NULL, /* 10 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 18 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 28 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 30 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 40 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 48 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 50 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 58 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 60 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 68 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 70 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 78 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 80 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 88 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 90 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 98 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +void (*insttable_3byte660F3A_32[256])(void) = { + NULL, /* 00 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE4_1_ROUNDPS, /* 08 */ + SSE4_1_ROUNDPD, + SSE4_1_ROUNDSS, + SSE4_1_ROUNDSD, + SSE4_1_PBLENDPS, + SSE4_1_PBLENDPD, + SSE4_1_PBLENDW, + SSSE3_PALIGNR, + NULL, /* 10 */ + NULL, + NULL, + NULL, + SSE4_1_PEXTRB, + SSE4_1_PEXTRW, + SSE4_1_PEXTRD, + SSE4_1_PEXTRACTPS, + NULL, /* 18 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE4_1_PINSRB, /* 20 */ + SSE4_1_INSERTPS, + SSE4_1_PINSRD, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 28 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 30 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE4_1_DPPS, /* 40 */ + SSE4_1_DPPD, + SSE4_1_MPSADBW, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 48 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 50 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 58 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE4_2_PCMPESTRM, /* 60 */ + SSE4_2_PCMPESTRI, + SSE4_2_PCMPISTRM, + SSE4_2_PCMPISTRI, + NULL, + NULL, + NULL, + NULL, + NULL, /* 68 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 70 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 78 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 80 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 88 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 90 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 98 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +void (*insttable_3byteF20F38_32[256])(void) = { + NULL, /* 00 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 08 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 10 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 18 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 28 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 30 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 40 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 48 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 50 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 58 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 60 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 68 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 70 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 78 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 80 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 88 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 90 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 98 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE4_2_POPCNT_32, /* B8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE4_2_CRC32_Gy_Eb, /* F0 */ + SSE4_2_CRC32_Gy_Ev, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + +void (*insttable_3byteF20F38_16[256])(void) = { + NULL, /* 00 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 08 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 10 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 18 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 28 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 30 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 40 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 48 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 50 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 58 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 60 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 68 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 70 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 78 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 80 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 88 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 90 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 98 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* A8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* B0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE4_2_POPCNT_16, /* B8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* C8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* D8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E0 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* E8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SSE4_2_CRC32_Gy_Eb_16, /* F0 */ + SSE4_2_CRC32_Gy_Ev_16, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* F8 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + + +/* + * for group + */ + + /* group 1 */ +void (CPUCALL* insttable_G1EbIb[])(UINT8*, UINT32) = { + ADD_EbIb, + OR_EbIb, + ADC_EbIb, + SBB_EbIb, + AND_EbIb, + SUB_EbIb, + XOR_EbIb, + CMP_EbIb, +}; +void (CPUCALL* insttable_G1EbIb_ext[])(UINT32, UINT32) = { + ADD_EbIb_ext, + OR_EbIb_ext, + ADC_EbIb_ext, + SBB_EbIb_ext, + AND_EbIb_ext, + SUB_EbIb_ext, + XOR_EbIb_ext, + CMP_EbIb_ext, +}; + +void (CPUCALL* insttable_G1EwIx[])(UINT16*, UINT32) = { + ADD_EwIx, + OR_EwIx, + ADC_EwIx, + SBB_EwIx, + AND_EwIx, + SUB_EwIx, + XOR_EwIx, + CMP_EwIx, +}; +void (CPUCALL* insttable_G1EwIx_ext[])(UINT32, UINT32) = { + ADD_EwIx_ext, + OR_EwIx_ext, + ADC_EwIx_ext, + SBB_EwIx_ext, + AND_EwIx_ext, + SUB_EwIx_ext, + XOR_EwIx_ext, + CMP_EwIx_ext, +}; + +void (CPUCALL* insttable_G1EdIx[])(UINT32*, UINT32) = { + ADD_EdIx, + OR_EdIx, + ADC_EdIx, + SBB_EdIx, + AND_EdIx, + SUB_EdIx, + XOR_EdIx, + CMP_EdIx, +}; +void (CPUCALL* insttable_G1EdIx_ext[])(UINT32, UINT32) = { + ADD_EdIx_ext, + OR_EdIx_ext, + ADC_EdIx_ext, + SBB_EdIx_ext, + AND_EdIx_ext, + SUB_EdIx_ext, + XOR_EdIx_ext, + CMP_EdIx_ext, +}; + + +/* group 2 */ +void (CPUCALL* insttable_G2Eb[])(UINT8*) = { + ROL_Eb, + ROR_Eb, + RCL_Eb, + RCR_Eb, + SHL_Eb, + SHR_Eb, + SHL_Eb, + SAR_Eb, +}; +void (CPUCALL* insttable_G2Eb_ext[])(UINT32) = { + ROL_Eb_ext, + ROR_Eb_ext, + RCL_Eb_ext, + RCR_Eb_ext, + SHL_Eb_ext, + SHR_Eb_ext, + SHL_Eb_ext, + SAR_Eb_ext, +}; + +void (CPUCALL* insttable_G2Ew[])(UINT16*) = { + ROL_Ew, + ROR_Ew, + RCL_Ew, + RCR_Ew, + SHL_Ew, + SHR_Ew, + SHL_Ew, + SAR_Ew, +}; +void (CPUCALL* insttable_G2Ew_ext[])(UINT32) = { + ROL_Ew_ext, + ROR_Ew_ext, + RCL_Ew_ext, + RCR_Ew_ext, + SHL_Ew_ext, + SHR_Ew_ext, + SHL_Ew_ext, + SAR_Ew_ext, +}; + +void (CPUCALL* insttable_G2Ed[])(UINT32*) = { + ROL_Ed, + ROR_Ed, + RCL_Ed, + RCR_Ed, + SHL_Ed, + SHR_Ed, + SHL_Ed, + SAR_Ed, +}; +void (CPUCALL* insttable_G2Ed_ext[])(UINT32) = { + ROL_Ed_ext, + ROR_Ed_ext, + RCL_Ed_ext, + RCR_Ed_ext, + SHL_Ed_ext, + SHR_Ed_ext, + SHL_Ed_ext, + SAR_Ed_ext, +}; + +void (CPUCALL* insttable_G2EbCL[])(UINT8*, UINT) = { + ROL_EbCL, + ROR_EbCL, + RCL_EbCL, + RCR_EbCL, + SHL_EbCL, + SHR_EbCL, + SHL_EbCL, + SAR_EbCL, +}; +void (CPUCALL* insttable_G2EbCL_ext[])(UINT32, UINT) = { + ROL_EbCL_ext, + ROR_EbCL_ext, + RCL_EbCL_ext, + RCR_EbCL_ext, + SHL_EbCL_ext, + SHR_EbCL_ext, + SHL_EbCL_ext, + SAR_EbCL_ext, +}; + +void (CPUCALL* insttable_G2EwCL[])(UINT16*, UINT) = { + ROL_EwCL, + ROR_EwCL, + RCL_EwCL, + RCR_EwCL, + SHL_EwCL, + SHR_EwCL, + SHL_EwCL, + SAR_EwCL, +}; +void (CPUCALL* insttable_G2EwCL_ext[])(UINT32, UINT) = { + ROL_EwCL_ext, + ROR_EwCL_ext, + RCL_EwCL_ext, + RCR_EwCL_ext, + SHL_EwCL_ext, + SHR_EwCL_ext, + SHL_EwCL_ext, + SAR_EwCL_ext, +}; + +void (CPUCALL* insttable_G2EdCL[])(UINT32*, UINT) = { + ROL_EdCL, + ROR_EdCL, + RCL_EdCL, + RCR_EdCL, + SHL_EdCL, + SHR_EdCL, + SHL_EdCL, + SAR_EdCL, +}; +void (CPUCALL* insttable_G2EdCL_ext[])(UINT32, UINT) = { + ROL_EdCL_ext, + ROR_EdCL_ext, + RCL_EdCL_ext, + RCR_EdCL_ext, + SHL_EdCL_ext, + SHR_EdCL_ext, + SHL_EdCL_ext, + SAR_EdCL_ext, +}; + +/* group 3 */ +void (CPUCALL* insttable_G3Eb[])(UINT32) = { + TEST_EbIb, + TEST_EbIb, + NOT_Eb, + NEG_Eb, + MUL_ALEb, + IMUL_ALEb, + DIV_ALEb, + IDIV_ALEb, +}; + +void (CPUCALL* insttable_G3Ew[])(UINT32) = { + TEST_EwIw, + TEST_EwIw, + NOT_Ew, + NEG_Ew, + MUL_AXEw, + IMUL_AXEw, + DIV_AXEw, + IDIV_AXEw, +}; + +void (CPUCALL* insttable_G3Ed[])(UINT32) = { + TEST_EdId, + TEST_EdId, + NOT_Ed, + NEG_Ed, + MUL_EAXEd, + IMUL_EAXEd, + DIV_EAXEd, + IDIV_EAXEd, +}; + +/* group 4 */ +void (CPUCALL* insttable_G4[])(UINT32) = { + INC_Eb, + DEC_Eb, + undef_op2, + undef_op2, + undef_op2, + undef_op2, + undef_op2, + undef_op2, +}; + +/* group 5 */ +void (CPUCALL* insttable_G5Ew[])(UINT32) = { + INC_Ew, + DEC_Ew, + CALL_Ew, + CALL16_Ep, + JMP_Ew, + JMP16_Ep, + PUSH_Ew, + undef_op2, /* POP_Ew_G5 */ +}; + +void (CPUCALL* insttable_G5Ed[])(UINT32) = { + INC_Ed, + DEC_Ed, + CALL_Ed, + CALL32_Ep, + JMP_Ed, + JMP32_Ep, + PUSH_Ed, + undef_op2, /* POP_Ed_G5 */ +}; + +/* group 6 */ +void (CPUCALL* insttable_G6[])(UINT32) = { + SLDT_Ew, + STR_Ew, + LLDT_Ew, + LTR_Ew, + VERR_Ew, + VERW_Ew, + undef_op2, + undef_op2, +}; + +/* group 7 */ +void (CPUCALL* insttable_G7[])(UINT32) = { + SGDT_Ms, + SIDT_Ms, + LGDT_Ms, + LIDT_Ms, + SMSW_Ew, + undef_op2, + LMSW_Ew, + INVLPG, +}; + +/* group 8 */ +void (CPUCALL* insttable_G8EwIb[])(UINT32) = { + undef_op2, + undef_op2, + undef_op2, + undef_op2, + BT_EwIb, + BTS_EwIb, + BTR_EwIb, + BTC_EwIb, +}; + +void (CPUCALL* insttable_G8EdIb[])(UINT32) = { + undef_op2, + undef_op2, + undef_op2, + undef_op2, + BT_EdIb, + BTS_EdIb, + BTR_EdIb, + BTC_EdIb, +}; + +/* group 9 */ +void (CPUCALL* insttable_G9[])(UINT32) = { + undef_op2, + CMPXCHG8B, + undef_op2, + undef_op2, + undef_op2, + undef_op2, + undef_op2, + undef_op2, +}; diff --git a/i386c/ia32/inst_table.h b/i386c/ia32/inst_table.h old mode 100755 new mode 100644 index dc8cf701..73b879dd --- a/i386c/ia32/inst_table.h +++ b/i386c/ia32/inst_table.h @@ -1,107 +1,107 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INST_TABLE_H__ -#define IA32_CPU_INST_TABLE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* info of instruction */ -extern UINT8 insttable_info[256]; - -/* table of instruction */ -extern void (*insttable_1byte[2][256])(void); -extern void (*insttable_1byte_repfunc[2][256])(int reptype); -extern void (*insttable_2byte[2][256])(void); - -extern void (*insttable_2byte660F_32[256])(void); -extern void (*insttable_2byteF20F_32[256])(void); -extern void (*insttable_2byteF30F_32[256])(void); - -extern void (*insttable_2byte0F38_32[256])(void); -extern void (*insttable_3byte660F38_32[256])(void); -extern void (*insttable_2byte0F3A_32[256])(void); -extern void (*insttable_3byte660F3A_32[256])(void); -extern void (*insttable_3byteF20F38_32[256])(void); -extern void (*insttable_3byteF20F38_16[256])(void); - -/* - * for group - */ - -/* group 1 */ -extern void (CPUCALL *insttable_G1EbIb[])(UINT8 *, UINT32); -extern void (CPUCALL *insttable_G1EwIx[])(UINT16 *, UINT32); -extern void (CPUCALL *insttable_G1EdIx[])(UINT32 *, UINT32); -extern void (CPUCALL *insttable_G1EbIb_ext[])(UINT32, UINT32); -extern void (CPUCALL *insttable_G1EwIx_ext[])(UINT32, UINT32); -extern void (CPUCALL *insttable_G1EdIx_ext[])(UINT32, UINT32); - -/* group 2 */ -extern void (CPUCALL *insttable_G2Eb[])(UINT8 *); -extern void (CPUCALL *insttable_G2Ew[])(UINT16 *); -extern void (CPUCALL *insttable_G2Ed[])(UINT32 *); -extern void (CPUCALL *insttable_G2EbCL[])(UINT8 *, UINT); -extern void (CPUCALL *insttable_G2EwCL[])(UINT16 *, UINT); -extern void (CPUCALL *insttable_G2EdCL[])(UINT32 *, UINT); -extern void (CPUCALL *insttable_G2Eb_ext[])(UINT32); -extern void (CPUCALL *insttable_G2Ew_ext[])(UINT32); -extern void (CPUCALL *insttable_G2Ed_ext[])(UINT32); -extern void (CPUCALL *insttable_G2EbCL_ext[])(UINT32, UINT); -extern void (CPUCALL *insttable_G2EwCL_ext[])(UINT32, UINT); -extern void (CPUCALL *insttable_G2EdCL_ext[])(UINT32, UINT); - -/* group 3 */ -extern void (CPUCALL *insttable_G3Eb[])(UINT32); -extern void (CPUCALL *insttable_G3Ew[])(UINT32); -extern void (CPUCALL *insttable_G3Ed[])(UINT32); - -/* group 4 */ -extern void (CPUCALL *insttable_G4[])(UINT32); - -/* group 5 */ -extern void (CPUCALL *insttable_G5Ew[])(UINT32); -extern void (CPUCALL *insttable_G5Ed[])(UINT32); - -/* group 6 */ -extern void (CPUCALL *insttable_G6[])(UINT32); - -/* group 7 */ -extern void (CPUCALL *insttable_G7[])(UINT32); - -/* group 8 */ -extern void (CPUCALL *insttable_G8EwIb[])(UINT32); -extern void (CPUCALL *insttable_G8EdIb[])(UINT32); - -/* group 9 */ -extern void (CPUCALL *insttable_G9[])(UINT32); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INST_TABLE_H__ */ +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INST_TABLE_H__ +#define IA32_CPU_INST_TABLE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* info of instruction */ +extern UINT8 insttable_info[256]; + +/* table of instruction */ +extern void (*insttable_1byte[2][256])(void); +extern void (*insttable_1byte_repfunc[2][256])(int reptype); +extern void (*insttable_2byte[2][256])(void); + +extern void (*insttable_2byte660F_32[256])(void); +extern void (*insttable_2byteF20F_32[256])(void); +extern void (*insttable_2byteF30F_32[256])(void); + +extern void (*insttable_2byte0F38_32[256])(void); +extern void (*insttable_3byte660F38_32[256])(void); +extern void (*insttable_2byte0F3A_32[256])(void); +extern void (*insttable_3byte660F3A_32[256])(void); +extern void (*insttable_3byteF20F38_32[256])(void); +extern void (*insttable_3byteF20F38_16[256])(void); + +/* + * for group + */ + +/* group 1 */ +extern void (CPUCALL *insttable_G1EbIb[])(UINT8 *, UINT32); +extern void (CPUCALL *insttable_G1EwIx[])(UINT16 *, UINT32); +extern void (CPUCALL *insttable_G1EdIx[])(UINT32 *, UINT32); +extern void (CPUCALL *insttable_G1EbIb_ext[])(UINT32, UINT32); +extern void (CPUCALL *insttable_G1EwIx_ext[])(UINT32, UINT32); +extern void (CPUCALL *insttable_G1EdIx_ext[])(UINT32, UINT32); + +/* group 2 */ +extern void (CPUCALL *insttable_G2Eb[])(UINT8 *); +extern void (CPUCALL *insttable_G2Ew[])(UINT16 *); +extern void (CPUCALL *insttable_G2Ed[])(UINT32 *); +extern void (CPUCALL *insttable_G2EbCL[])(UINT8 *, UINT); +extern void (CPUCALL *insttable_G2EwCL[])(UINT16 *, UINT); +extern void (CPUCALL *insttable_G2EdCL[])(UINT32 *, UINT); +extern void (CPUCALL *insttable_G2Eb_ext[])(UINT32); +extern void (CPUCALL *insttable_G2Ew_ext[])(UINT32); +extern void (CPUCALL *insttable_G2Ed_ext[])(UINT32); +extern void (CPUCALL *insttable_G2EbCL_ext[])(UINT32, UINT); +extern void (CPUCALL *insttable_G2EwCL_ext[])(UINT32, UINT); +extern void (CPUCALL *insttable_G2EdCL_ext[])(UINT32, UINT); + +/* group 3 */ +extern void (CPUCALL *insttable_G3Eb[])(UINT32); +extern void (CPUCALL *insttable_G3Ew[])(UINT32); +extern void (CPUCALL *insttable_G3Ed[])(UINT32); + +/* group 4 */ +extern void (CPUCALL *insttable_G4[])(UINT32); + +/* group 5 */ +extern void (CPUCALL *insttable_G5Ew[])(UINT32); +extern void (CPUCALL *insttable_G5Ed[])(UINT32); + +/* group 6 */ +extern void (CPUCALL *insttable_G6[])(UINT32); + +/* group 7 */ +extern void (CPUCALL *insttable_G7[])(UINT32); + +/* group 8 */ +extern void (CPUCALL *insttable_G8EwIb[])(UINT32); +extern void (CPUCALL *insttable_G8EdIb[])(UINT32); + +/* group 9 */ +extern void (CPUCALL *insttable_G9[])(UINT32); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INST_TABLE_H__ */ diff --git a/i386c/ia32/instructions/arith.mcr b/i386c/ia32/instructions/arith.mcr old mode 100755 new mode 100644 index d95eb031..4dc25233 --- a/i386c/ia32/instructions/arith.mcr +++ b/i386c/ia32/instructions/arith.mcr @@ -1,524 +1,524 @@ -/* - * Copyright (c) 2004 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_ARITH_MCR__ -#define IA32_CPU_ARITH_MCR__ - -/* args == 1 */ -#define ARITH_INSTRUCTION_1(inst) \ -static UINT32 CPUCALL \ -inst##1(UINT32 dst, void *arg) \ -{ \ - BYTE_##inst(dst); \ - return dst; \ -} \ -static UINT32 CPUCALL \ -inst##2(UINT32 dst, void *arg) \ -{ \ - WORD_##inst(dst); \ - return dst; \ -} \ -static UINT32 CPUCALL \ -inst##4(UINT32 dst, void *arg) \ -{ \ - DWORD_##inst(dst); \ - return dst; \ -} \ -\ -void CPUCALL \ -inst##_Eb(UINT32 op) \ -{ \ - UINT8 *out; \ - UINT32 dst, madr; \ -\ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(2); \ - out = reg8_b20[op]; \ - dst = *out; \ - BYTE_##inst(dst); \ - *out = (UINT8)dst; \ - } else { \ - CPU_WORKCLOCK(5); \ - madr = calc_ea_dst(op); \ - cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, 0); \ - } \ -} \ -\ -void CPUCALL \ -inst##_Ew(UINT32 op) \ -{ \ - UINT16 *out; \ - UINT32 dst, madr; \ -\ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(2); \ - out = CPU_REG16_B20(op); \ - dst = *out; \ - WORD_##inst(dst); \ - *out = (UINT16)dst; \ - } else { \ - CPU_WORKCLOCK(5); \ - madr = calc_ea_dst(op); \ - cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, 0); \ - } \ -} \ -\ -void CPUCALL \ -inst##_Ed(UINT32 op) \ -{ \ - UINT32 *out; \ - UINT32 dst, madr; \ -\ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(2); \ - out = CPU_REG32_B20(op); \ - dst = *out; \ - DWORD_##inst(dst); \ - *out = dst; \ - } else { \ - CPU_WORKCLOCK(5); \ - madr = calc_ea_dst(op); \ - cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, 0); \ - } \ -} - -/* args == 2 */ -#define ARITH_INSTRUCTION_2(inst) \ -static UINT32 CPUCALL \ -inst##1(UINT32 dst, void *arg) \ -{ \ - UINT32 src = PTR_TO_UINT32(arg); \ - BYTE_##inst(dst, src); \ - return dst; \ -} \ -static UINT32 CPUCALL \ -inst##2(UINT32 dst, void *arg) \ -{ \ - UINT32 src = PTR_TO_UINT32(arg); \ - WORD_##inst(dst, src); \ - return dst; \ -} \ -static UINT32 CPUCALL \ -inst##4(UINT32 dst, void *arg) \ -{ \ - UINT32 src = PTR_TO_UINT32(arg); \ - DWORD_##inst(dst, src); \ - return dst; \ -} \ -\ -void \ -inst##_EbGb(void) \ -{ \ - UINT8 *out; \ - UINT32 op, src, dst, madr; \ -\ - PREPART_EA_REG8(op, src); \ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(2); \ - out = reg8_b20[op]; \ - dst = *out; \ - BYTE_##inst(dst, src); \ - *out = (UINT8)dst; \ - } else { \ - CPU_WORKCLOCK(7); \ - madr = calc_ea_dst(op); \ - cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \ - } \ -} \ -\ -void \ -inst##_EwGw(void) \ -{ \ - UINT16 *out; \ - UINT32 op, src, dst, madr; \ -\ - PREPART_EA_REG16(op, src); \ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(2); \ - out = CPU_REG16_B20(op); \ - dst = *out; \ - WORD_##inst(dst, src); \ - *out = (UINT16)dst; \ - } else { \ - CPU_WORKCLOCK(7); \ - madr = calc_ea_dst(op); \ - cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \ - } \ -} \ -\ -void \ -inst##_EdGd(void) \ -{ \ - UINT32 *out; \ - UINT32 op, src, dst, madr; \ -\ - PREPART_EA_REG32(op, src); \ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(2); \ - out = CPU_REG32_B20(op); \ - dst = *out; \ - DWORD_##inst(dst, src); \ - *out = dst; \ - } else { \ - CPU_WORKCLOCK(7); \ - madr = calc_ea_dst(op); \ - cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \ - } \ -} \ -\ -void \ -inst##_GbEb(void) \ -{ \ - UINT8 *out; \ - UINT32 op, src, dst; \ -\ - PREPART_REG8_EA(op, src, out, 2, 7); \ - dst = *out; \ - BYTE_##inst(dst, src); \ - *out = (UINT8)dst; \ -} \ -\ -void \ -inst##_GwEw(void) \ -{ \ - UINT16 *out; \ - UINT32 op, src, dst; \ -\ - PREPART_REG16_EA(op, src, out, 2, 7); \ - dst = *out; \ - WORD_##inst(dst, src); \ - *out = (UINT16)dst; \ -} \ -\ -void \ -inst##_GdEd(void) \ -{ \ - UINT32 *out; \ - UINT32 op, src, dst; \ -\ - PREPART_REG32_EA(op, src, out, 2, 7); \ - dst = *out; \ - DWORD_##inst(dst, src); \ - *out = dst; \ -} \ -\ -void \ -inst##_ALIb(void) \ -{ \ - UINT32 src, dst; \ -\ - CPU_WORKCLOCK(3); \ - GET_MODRM_PCBYTE(src); \ - dst = CPU_AL; \ - BYTE_##inst(dst, src); \ - CPU_AL = (UINT8)dst; \ -} \ -\ -void \ -inst##_AXIw(void) \ -{ \ - UINT32 src, dst; \ -\ - CPU_WORKCLOCK(3); \ - GET_PCWORD(src); \ - dst = CPU_AX; \ - WORD_##inst(dst, src); \ - CPU_AX = (UINT16)dst; \ -} \ -\ -void \ -inst##_EAXId(void) \ -{ \ - UINT32 src, dst; \ -\ - CPU_WORKCLOCK(3); \ - GET_PCDWORD(src); \ - dst = CPU_EAX; \ - DWORD_##inst(dst, src); \ - CPU_EAX = dst; \ -} \ -\ -void CPUCALL \ -inst##_EbIb(UINT8 *regp, UINT32 src) \ -{ \ - UINT32 dst; \ -\ - dst = *regp; \ - BYTE_##inst(dst, src); \ - *regp = (UINT8)dst; \ -} \ -\ -void CPUCALL \ -inst##_EbIb_ext(UINT32 madr, UINT32 src) \ -{ \ -\ - cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \ -} \ -\ -void CPUCALL \ -inst##_EwIx(UINT16 *regp, UINT32 src) \ -{ \ - UINT32 dst; \ -\ - dst = *regp; \ - WORD_##inst(dst, src); \ - *regp = (UINT16)dst; \ -} \ -\ -void CPUCALL \ -inst##_EwIx_ext(UINT32 madr, UINT32 src) \ -{ \ -\ - cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \ -} \ -\ -void CPUCALL \ -inst##_EdIx(UINT32 *regp, UINT32 src) \ -{ \ - UINT32 dst; \ -\ - dst = *regp; \ - DWORD_##inst(dst, src); \ - *regp = dst; \ -} \ -\ -void CPUCALL \ -inst##_EdIx_ext(UINT32 madr, UINT32 src) \ -{ \ -\ - cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \ -} - -/* args == 3 */ -#define ARITH_INSTRUCTION_3(inst) \ -static UINT32 CPUCALL \ -inst##1(UINT32 dst, void *arg) \ -{ \ - UINT32 src = PTR_TO_UINT32(arg); \ - UINT32 res; \ - BYTE_##inst(res, dst, src); \ - return res; \ -} \ -static UINT32 CPUCALL \ -inst##2(UINT32 dst, void *arg) \ -{ \ - UINT32 src = PTR_TO_UINT32(arg); \ - UINT32 res; \ - WORD_##inst(res, dst, src); \ - return res; \ -} \ -static UINT32 CPUCALL \ -inst##4(UINT32 dst, void *arg) \ -{ \ - UINT32 src = PTR_TO_UINT32(arg); \ - UINT32 res; \ - DWORD_##inst(res, dst, src); \ - return res; \ -} \ -\ -void \ -inst##_EbGb(void) \ -{ \ - UINT8 *out; \ - UINT32 op, src, dst, res, madr; \ -\ - PREPART_EA_REG8(op, src); \ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(2); \ - out = reg8_b20[op]; \ - dst = *out; \ - BYTE_##inst(res, dst, src); \ - *out = (UINT8)res; \ - } else { \ - CPU_WORKCLOCK(7); \ - madr = calc_ea_dst(op); \ - cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \ - } \ -} \ -\ -void \ -inst##_EwGw(void) \ -{ \ - UINT16 *out; \ - UINT32 op, src, dst, res, madr; \ -\ - PREPART_EA_REG16(op, src); \ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(2); \ - out = CPU_REG16_B20(op); \ - dst = *out; \ - WORD_##inst(res, dst, src); \ - *out = (UINT16)res; \ - } else { \ - CPU_WORKCLOCK(7); \ - madr = calc_ea_dst(op); \ - cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \ - } \ -} \ -\ -void \ -inst##_EdGd(void) \ -{ \ - UINT32 *out; \ - UINT32 op, src, dst, res, madr; \ -\ - PREPART_EA_REG32(op, src); \ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(2); \ - out = CPU_REG32_B20(op); \ - dst = *out; \ - DWORD_##inst(res, dst, src); \ - *out = res; \ - } else { \ - CPU_WORKCLOCK(7); \ - madr = calc_ea_dst(op); \ - cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \ - } \ -} \ -\ -void \ -inst##_GbEb(void) \ -{ \ - UINT8 *out; \ - UINT32 op, src, dst, res; \ -\ - PREPART_REG8_EA(op, src, out, 2, 7); \ - dst = *out; \ - BYTE_##inst(res, dst, src); \ - *out = (UINT8)res; \ -} \ -\ -void \ -inst##_GwEw(void) \ -{ \ - UINT16 *out; \ - UINT32 op, src, dst, res; \ -\ - PREPART_REG16_EA(op, src, out, 2, 7); \ - dst = *out; \ - WORD_##inst(res, dst, src); \ - *out = (UINT16)res; \ -} \ -\ -void \ -inst##_GdEd(void) \ -{ \ - UINT32 *out; \ - UINT32 op, src, dst, res; \ -\ - PREPART_REG32_EA(op, src, out, 2, 7); \ - dst = *out; \ - DWORD_##inst(res, dst, src); \ - *out = res; \ -} \ -\ -void \ -inst##_ALIb(void) \ -{ \ - UINT32 src, dst, res; \ -\ - CPU_WORKCLOCK(2); \ - GET_MODRM_PCBYTE(src); \ - dst = CPU_AL; \ - BYTE_##inst(res, dst, src); \ - CPU_AL = (UINT8)res; \ -} \ -\ -void \ -inst##_AXIw(void) \ -{ \ - UINT32 src, dst, res; \ -\ - CPU_WORKCLOCK(2); \ - GET_PCWORD(src); \ - dst = CPU_AX; \ - WORD_##inst(res, dst, src); \ - CPU_AX = (UINT16)res; \ -} \ -\ -void \ -inst##_EAXId(void) \ -{ \ - UINT32 src, dst, res; \ -\ - CPU_WORKCLOCK(2); \ - GET_PCDWORD(src); \ - dst = CPU_EAX; \ - DWORD_##inst(res, dst, src); \ - CPU_EAX = res; \ -} \ -\ -void CPUCALL \ -inst##_EbIb(UINT8 *regp, UINT32 src) \ -{ \ - UINT32 dst, res; \ -\ - dst = *regp; \ - BYTE_##inst(res, dst, src); \ - *regp = (UINT8)res; \ -} \ -\ -void CPUCALL \ -inst##_EbIb_ext(UINT32 madr, UINT32 src) \ -{ \ -\ - cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \ -} \ -\ -void CPUCALL \ -inst##_EwIx(UINT16 *regp, UINT32 src) \ -{ \ - UINT32 dst, res; \ -\ - dst = *regp; \ - WORD_##inst(res, dst, src); \ - *regp = (UINT16)res; \ -} \ -\ -void CPUCALL \ -inst##_EwIx_ext(UINT32 madr, UINT32 src) \ -{ \ -\ - cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \ -} \ -\ -void CPUCALL \ -inst##_EdIx(UINT32 *regp, UINT32 src) \ -{ \ - UINT32 dst, res; \ -\ - dst = *regp; \ - DWORD_##inst(res, dst, src); \ - *regp = res; \ -} \ -\ -void CPUCALL \ -inst##_EdIx_ext(UINT32 madr, UINT32 src) \ -{ \ -\ - cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \ -} - -#endif /* IA32_CPU_ARITH_MCR__ */ +/* + * Copyright (c) 2004 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_ARITH_MCR__ +#define IA32_CPU_ARITH_MCR__ + +/* args == 1 */ +#define ARITH_INSTRUCTION_1(inst) \ +static UINT32 CPUCALL \ +inst##1(UINT32 dst, void *arg) \ +{ \ + BYTE_##inst(dst); \ + return dst; \ +} \ +static UINT32 CPUCALL \ +inst##2(UINT32 dst, void *arg) \ +{ \ + WORD_##inst(dst); \ + return dst; \ +} \ +static UINT32 CPUCALL \ +inst##4(UINT32 dst, void *arg) \ +{ \ + DWORD_##inst(dst); \ + return dst; \ +} \ +\ +void CPUCALL \ +inst##_Eb(UINT32 op) \ +{ \ + UINT8 *out; \ + UINT32 dst, madr; \ +\ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(2); \ + out = reg8_b20[op]; \ + dst = *out; \ + BYTE_##inst(dst); \ + *out = (UINT8)dst; \ + } else { \ + CPU_WORKCLOCK(5); \ + madr = calc_ea_dst(op); \ + cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, 0); \ + } \ +} \ +\ +void CPUCALL \ +inst##_Ew(UINT32 op) \ +{ \ + UINT16 *out; \ + UINT32 dst, madr; \ +\ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(2); \ + out = CPU_REG16_B20(op); \ + dst = *out; \ + WORD_##inst(dst); \ + *out = (UINT16)dst; \ + } else { \ + CPU_WORKCLOCK(5); \ + madr = calc_ea_dst(op); \ + cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, 0); \ + } \ +} \ +\ +void CPUCALL \ +inst##_Ed(UINT32 op) \ +{ \ + UINT32 *out; \ + UINT32 dst, madr; \ +\ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(2); \ + out = CPU_REG32_B20(op); \ + dst = *out; \ + DWORD_##inst(dst); \ + *out = dst; \ + } else { \ + CPU_WORKCLOCK(5); \ + madr = calc_ea_dst(op); \ + cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, 0); \ + } \ +} + +/* args == 2 */ +#define ARITH_INSTRUCTION_2(inst) \ +static UINT32 CPUCALL \ +inst##1(UINT32 dst, void *arg) \ +{ \ + UINT32 src = PTR_TO_UINT32(arg); \ + BYTE_##inst(dst, src); \ + return dst; \ +} \ +static UINT32 CPUCALL \ +inst##2(UINT32 dst, void *arg) \ +{ \ + UINT32 src = PTR_TO_UINT32(arg); \ + WORD_##inst(dst, src); \ + return dst; \ +} \ +static UINT32 CPUCALL \ +inst##4(UINT32 dst, void *arg) \ +{ \ + UINT32 src = PTR_TO_UINT32(arg); \ + DWORD_##inst(dst, src); \ + return dst; \ +} \ +\ +void \ +inst##_EbGb(void) \ +{ \ + UINT8 *out; \ + UINT32 op, src, dst, madr; \ +\ + PREPART_EA_REG8(op, src); \ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(2); \ + out = reg8_b20[op]; \ + dst = *out; \ + BYTE_##inst(dst, src); \ + *out = (UINT8)dst; \ + } else { \ + CPU_WORKCLOCK(7); \ + madr = calc_ea_dst(op); \ + cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \ + } \ +} \ +\ +void \ +inst##_EwGw(void) \ +{ \ + UINT16 *out; \ + UINT32 op, src, dst, madr; \ +\ + PREPART_EA_REG16(op, src); \ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(2); \ + out = CPU_REG16_B20(op); \ + dst = *out; \ + WORD_##inst(dst, src); \ + *out = (UINT16)dst; \ + } else { \ + CPU_WORKCLOCK(7); \ + madr = calc_ea_dst(op); \ + cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \ + } \ +} \ +\ +void \ +inst##_EdGd(void) \ +{ \ + UINT32 *out; \ + UINT32 op, src, dst, madr; \ +\ + PREPART_EA_REG32(op, src); \ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(2); \ + out = CPU_REG32_B20(op); \ + dst = *out; \ + DWORD_##inst(dst, src); \ + *out = dst; \ + } else { \ + CPU_WORKCLOCK(7); \ + madr = calc_ea_dst(op); \ + cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \ + } \ +} \ +\ +void \ +inst##_GbEb(void) \ +{ \ + UINT8 *out; \ + UINT32 op, src, dst; \ +\ + PREPART_REG8_EA(op, src, out, 2, 7); \ + dst = *out; \ + BYTE_##inst(dst, src); \ + *out = (UINT8)dst; \ +} \ +\ +void \ +inst##_GwEw(void) \ +{ \ + UINT16 *out; \ + UINT32 op, src, dst; \ +\ + PREPART_REG16_EA(op, src, out, 2, 7); \ + dst = *out; \ + WORD_##inst(dst, src); \ + *out = (UINT16)dst; \ +} \ +\ +void \ +inst##_GdEd(void) \ +{ \ + UINT32 *out; \ + UINT32 op, src, dst; \ +\ + PREPART_REG32_EA(op, src, out, 2, 7); \ + dst = *out; \ + DWORD_##inst(dst, src); \ + *out = dst; \ +} \ +\ +void \ +inst##_ALIb(void) \ +{ \ + UINT32 src, dst; \ +\ + CPU_WORKCLOCK(3); \ + GET_MODRM_PCBYTE(src); \ + dst = CPU_AL; \ + BYTE_##inst(dst, src); \ + CPU_AL = (UINT8)dst; \ +} \ +\ +void \ +inst##_AXIw(void) \ +{ \ + UINT32 src, dst; \ +\ + CPU_WORKCLOCK(3); \ + GET_PCWORD(src); \ + dst = CPU_AX; \ + WORD_##inst(dst, src); \ + CPU_AX = (UINT16)dst; \ +} \ +\ +void \ +inst##_EAXId(void) \ +{ \ + UINT32 src, dst; \ +\ + CPU_WORKCLOCK(3); \ + GET_PCDWORD(src); \ + dst = CPU_EAX; \ + DWORD_##inst(dst, src); \ + CPU_EAX = dst; \ +} \ +\ +void CPUCALL \ +inst##_EbIb(UINT8 *regp, UINT32 src) \ +{ \ + UINT32 dst; \ +\ + dst = *regp; \ + BYTE_##inst(dst, src); \ + *regp = (UINT8)dst; \ +} \ +\ +void CPUCALL \ +inst##_EbIb_ext(UINT32 madr, UINT32 src) \ +{ \ +\ + cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \ +} \ +\ +void CPUCALL \ +inst##_EwIx(UINT16 *regp, UINT32 src) \ +{ \ + UINT32 dst; \ +\ + dst = *regp; \ + WORD_##inst(dst, src); \ + *regp = (UINT16)dst; \ +} \ +\ +void CPUCALL \ +inst##_EwIx_ext(UINT32 madr, UINT32 src) \ +{ \ +\ + cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \ +} \ +\ +void CPUCALL \ +inst##_EdIx(UINT32 *regp, UINT32 src) \ +{ \ + UINT32 dst; \ +\ + dst = *regp; \ + DWORD_##inst(dst, src); \ + *regp = dst; \ +} \ +\ +void CPUCALL \ +inst##_EdIx_ext(UINT32 madr, UINT32 src) \ +{ \ +\ + cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \ +} + +/* args == 3 */ +#define ARITH_INSTRUCTION_3(inst) \ +static UINT32 CPUCALL \ +inst##1(UINT32 dst, void *arg) \ +{ \ + UINT32 src = PTR_TO_UINT32(arg); \ + UINT32 res; \ + BYTE_##inst(res, dst, src); \ + return res; \ +} \ +static UINT32 CPUCALL \ +inst##2(UINT32 dst, void *arg) \ +{ \ + UINT32 src = PTR_TO_UINT32(arg); \ + UINT32 res; \ + WORD_##inst(res, dst, src); \ + return res; \ +} \ +static UINT32 CPUCALL \ +inst##4(UINT32 dst, void *arg) \ +{ \ + UINT32 src = PTR_TO_UINT32(arg); \ + UINT32 res; \ + DWORD_##inst(res, dst, src); \ + return res; \ +} \ +\ +void \ +inst##_EbGb(void) \ +{ \ + UINT8 *out; \ + UINT32 op, src, dst, res, madr; \ +\ + PREPART_EA_REG8(op, src); \ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(2); \ + out = reg8_b20[op]; \ + dst = *out; \ + BYTE_##inst(res, dst, src); \ + *out = (UINT8)res; \ + } else { \ + CPU_WORKCLOCK(7); \ + madr = calc_ea_dst(op); \ + cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \ + } \ +} \ +\ +void \ +inst##_EwGw(void) \ +{ \ + UINT16 *out; \ + UINT32 op, src, dst, res, madr; \ +\ + PREPART_EA_REG16(op, src); \ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(2); \ + out = CPU_REG16_B20(op); \ + dst = *out; \ + WORD_##inst(res, dst, src); \ + *out = (UINT16)res; \ + } else { \ + CPU_WORKCLOCK(7); \ + madr = calc_ea_dst(op); \ + cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \ + } \ +} \ +\ +void \ +inst##_EdGd(void) \ +{ \ + UINT32 *out; \ + UINT32 op, src, dst, res, madr; \ +\ + PREPART_EA_REG32(op, src); \ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(2); \ + out = CPU_REG32_B20(op); \ + dst = *out; \ + DWORD_##inst(res, dst, src); \ + *out = res; \ + } else { \ + CPU_WORKCLOCK(7); \ + madr = calc_ea_dst(op); \ + cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \ + } \ +} \ +\ +void \ +inst##_GbEb(void) \ +{ \ + UINT8 *out; \ + UINT32 op, src, dst, res; \ +\ + PREPART_REG8_EA(op, src, out, 2, 7); \ + dst = *out; \ + BYTE_##inst(res, dst, src); \ + *out = (UINT8)res; \ +} \ +\ +void \ +inst##_GwEw(void) \ +{ \ + UINT16 *out; \ + UINT32 op, src, dst, res; \ +\ + PREPART_REG16_EA(op, src, out, 2, 7); \ + dst = *out; \ + WORD_##inst(res, dst, src); \ + *out = (UINT16)res; \ +} \ +\ +void \ +inst##_GdEd(void) \ +{ \ + UINT32 *out; \ + UINT32 op, src, dst, res; \ +\ + PREPART_REG32_EA(op, src, out, 2, 7); \ + dst = *out; \ + DWORD_##inst(res, dst, src); \ + *out = res; \ +} \ +\ +void \ +inst##_ALIb(void) \ +{ \ + UINT32 src, dst, res; \ +\ + CPU_WORKCLOCK(2); \ + GET_MODRM_PCBYTE(src); \ + dst = CPU_AL; \ + BYTE_##inst(res, dst, src); \ + CPU_AL = (UINT8)res; \ +} \ +\ +void \ +inst##_AXIw(void) \ +{ \ + UINT32 src, dst, res; \ +\ + CPU_WORKCLOCK(2); \ + GET_PCWORD(src); \ + dst = CPU_AX; \ + WORD_##inst(res, dst, src); \ + CPU_AX = (UINT16)res; \ +} \ +\ +void \ +inst##_EAXId(void) \ +{ \ + UINT32 src, dst, res; \ +\ + CPU_WORKCLOCK(2); \ + GET_PCDWORD(src); \ + dst = CPU_EAX; \ + DWORD_##inst(res, dst, src); \ + CPU_EAX = res; \ +} \ +\ +void CPUCALL \ +inst##_EbIb(UINT8 *regp, UINT32 src) \ +{ \ + UINT32 dst, res; \ +\ + dst = *regp; \ + BYTE_##inst(res, dst, src); \ + *regp = (UINT8)res; \ +} \ +\ +void CPUCALL \ +inst##_EbIb_ext(UINT32 madr, UINT32 src) \ +{ \ +\ + cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, UINT32_TO_PTR(src)); \ +} \ +\ +void CPUCALL \ +inst##_EwIx(UINT16 *regp, UINT32 src) \ +{ \ + UINT32 dst, res; \ +\ + dst = *regp; \ + WORD_##inst(res, dst, src); \ + *regp = (UINT16)res; \ +} \ +\ +void CPUCALL \ +inst##_EwIx_ext(UINT32 madr, UINT32 src) \ +{ \ +\ + cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, UINT32_TO_PTR(src)); \ +} \ +\ +void CPUCALL \ +inst##_EdIx(UINT32 *regp, UINT32 src) \ +{ \ + UINT32 dst, res; \ +\ + dst = *regp; \ + DWORD_##inst(res, dst, src); \ + *regp = res; \ +} \ +\ +void CPUCALL \ +inst##_EdIx_ext(UINT32 madr, UINT32 src) \ +{ \ +\ + cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, UINT32_TO_PTR(src)); \ +} + +#endif /* IA32_CPU_ARITH_MCR__ */ diff --git a/i386c/ia32/instructions/bin_arith.c b/i386c/ia32/instructions/bin_arith.c old mode 100755 new mode 100644 index 5cfd67fc..d6ef9197 --- a/i386c/ia32/instructions/bin_arith.c +++ b/i386c/ia32/instructions/bin_arith.c @@ -1,754 +1,754 @@ -/* - * Copyright (c) 2002-2004 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" -#include "arith.mcr" - -#include "bin_arith.h" -#include - - -/* - * arith - */ -ARITH_INSTRUCTION_3(ADD) -ARITH_INSTRUCTION_3(ADC) -ARITH_INSTRUCTION_3(SUB) -ARITH_INSTRUCTION_3(SBB) - - -/* - * IMUL - */ -void CPUCALL -IMUL_ALEb(UINT32 op) -{ - UINT32 madr; - SINT32 res; - SINT8 src, dst; - - if (op >= 0xc0) { - CPU_WORKCLOCK(13); - src = *(reg8_b20[op]); - } else { - CPU_WORKCLOCK(16); - madr = calc_ea_dst(op); - src = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); - } - dst = CPU_AL; - BYTE_IMUL(res, dst, src); - CPU_AX = (UINT16)res; -} - -void CPUCALL -IMUL_AXEw(UINT32 op) -{ - UINT32 madr; - SINT32 res; - SINT16 src, dst; - - if (op >= 0xc0) { - CPU_WORKCLOCK(21); - src = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(24); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - dst = CPU_AX; - WORD_IMUL(res, dst, src); - CPU_AX = (UINT16)(res & 0xffff); - CPU_DX = (UINT16)(res >> 16); -} - -void CPUCALL -IMUL_EAXEd(UINT32 op) -{ - UINT32 madr; - SINT64 res; - SINT32 src, dst; - - if (op >= 0xc0) { - CPU_WORKCLOCK(21); - src = *(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(24); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - dst = CPU_EAX; - DWORD_IMUL(res, dst, src); - CPU_EAX = (UINT32)res; - CPU_EDX = (UINT32)(res >> 32); -} - -void -IMUL_GwEw(void) -{ - UINT16 *out; - UINT32 op; - SINT32 res; - SINT16 src, dst; - - PREPART_REG16_EA(op, src, out, 21, 27); - dst = *out; - WORD_IMUL(res, dst, src); - *out = (UINT16)res; -} - -void -IMUL_GdEd(void) -{ - UINT32 *out; - UINT32 op; - SINT64 res; - SINT32 src, dst; - - PREPART_REG32_EA(op, src, out, 21, 27); - dst = *out; - DWORD_IMUL(res, dst, src); - *out = (UINT32)res; -} - -void -IMUL_GwEwIb(void) -{ - UINT16 *out; - UINT32 op; - SINT32 res; - SINT16 src, dst; - - PREPART_REG16_EA(op, src, out, 21, 24); - GET_PCBYTES(dst); - WORD_IMUL(res, dst, src); - *out = (UINT16)res; -} - -void -IMUL_GdEdIb(void) -{ - UINT32 *out; - UINT32 op; - SINT64 res; - SINT32 src, dst; - - PREPART_REG32_EA(op, src, out, 21, 24); - GET_PCBYTESD(dst); - DWORD_IMUL(res, dst, src); - *out = (UINT32)res; -} - -void -IMUL_GwEwIw(void) -{ - UINT16 *out; - UINT32 op; - SINT32 res; - SINT16 src, dst; - - PREPART_REG16_EA(op, src, out, 21, 24); - GET_PCWORD(dst); - WORD_IMUL(res, dst, src); - *out = (UINT16)res; -} - -void -IMUL_GdEdId(void) -{ - UINT32 *out; - UINT32 op; - SINT64 res; - SINT32 src, dst; - - PREPART_REG32_EA(op, src, out, 21, 24); - GET_PCDWORD(dst); - DWORD_IMUL(res, dst, src); - *out = (UINT32)res; -} - - -/* - * MUL - */ -void CPUCALL -MUL_ALEb(UINT32 op) -{ - UINT32 res, madr; - UINT8 src, dst; - - if (op >= 0xc0) { - CPU_WORKCLOCK(13); - src = *(reg8_b20[op]); - } else { - CPU_WORKCLOCK(16); - madr = calc_ea_dst(op); - src = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); - } - dst = CPU_AL; - BYTE_MUL(res, dst, src); - CPU_AX = (UINT16)res; -} - -void CPUCALL -MUL_AXEw(UINT32 op) -{ - UINT32 res, madr; - UINT16 src, dst; - - if (op >= 0xc0) { - CPU_WORKCLOCK(21); - src = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(24); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - dst = CPU_AX; - WORD_MUL(res, dst, src); - CPU_AX = (UINT16)res; - CPU_DX = (UINT16)(res >> 16); -} - -void CPUCALL -MUL_EAXEd(UINT32 op) -{ - UINT32 res, madr; - UINT32 src, dst; - - if (op >= 0xc0) { - CPU_WORKCLOCK(21); - src = *(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(24); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - dst = CPU_EAX; - DWORD_MUL(res, dst, src); - CPU_EAX = res; - CPU_EDX = CPU_OV; -} - - -/* - * IDIV - */ -void CPUCALL -IDIV_ALEb(UINT32 op) -{ - UINT32 madr; - SINT16 tmp, r; - SINT8 src; - - if (op >= 0xc0) { - CPU_WORKCLOCK(17); - src = *(reg8_b20[op]); - } else { - CPU_WORKCLOCK(25); - madr = calc_ea_dst(op); - src = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); - } - tmp = (SINT16)CPU_AX; - if (src != 0) { - r = tmp / src; - if (((r + 0x80) & 0xff00) == 0) { - CPU_AL = (SINT8)r; - CPU_AH = tmp % src; - if(i386cpuid.cpu_family == 4){ - CPU_FLAGL ^= A_FLAG; - } - return; - } - } - EXCEPTION(DE_EXCEPTION, 0); -} - -void CPUCALL -IDIV_AXEw(UINT32 op) -{ - SINT32 tmp, r; - UINT32 madr; - SINT16 src; - - if (op >= 0xc0) { - CPU_WORKCLOCK(17); - src = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(25); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - tmp = (SINT32)(((UINT32)CPU_DX << 16) + (UINT32)CPU_AX); - if ((src != 0) && (tmp != INT_MIN)) { - r = tmp / src; - if (((r + 0x8000) & 0xffff0000) == 0) { - CPU_AX = (SINT16)r; - CPU_DX = tmp % src; - if(i386cpuid.cpu_family == 4){ - CPU_FLAGL ^= A_FLAG; - } - return; - } - } - EXCEPTION(DE_EXCEPTION, 0); -} - -void CPUCALL -IDIV_EAXEd(UINT32 op) -{ - SINT64 tmp, r; - SINT32 src; - UINT32 madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(17); - src = *(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(25); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - tmp = (SINT64)(((UINT64)CPU_EDX << 32) + (SINT64)CPU_EAX); - if ((src != 0) && (tmp != QWORD_CONST(0x8000000000000000))) { - r = tmp / src; - if (((r + SQWORD_CONST(0x80000000)) & QWORD_CONST(0xffffffff00000000)) == 0) { - CPU_EAX = (SINT32)r; - CPU_EDX = (SINT32)(tmp % src); - if(i386cpuid.cpu_family == 4){ - CPU_FLAGL ^= A_FLAG; - } - return; - } - } - EXCEPTION(DE_EXCEPTION, 0); -} - - -/* - * DIV - */ -void CPUCALL -DIV_ALEb(UINT32 op) -{ - UINT32 madr; - UINT16 tmp; - UINT8 src; - - if (op >= 0xc0) { - CPU_WORKCLOCK(17); - src = *(reg8_b20[op]); - } else { - CPU_WORKCLOCK(25); - madr = calc_ea_dst(op); - src = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); - } - tmp = CPU_AX; - if (src != 0) { - if (tmp < ((UINT16)src << 8)) { - CPU_AL = tmp / src; - CPU_AH = tmp % src; - if(i386cpuid.cpu_family == 4){ - CPU_FLAGL ^= A_FLAG; - } - return; - } - } - EXCEPTION(DE_EXCEPTION, 0); -} - -void CPUCALL -DIV_AXEw(UINT32 op) -{ - UINT32 madr; - UINT32 tmp; - UINT16 src; - - if (op >= 0xc0) { - CPU_WORKCLOCK(17); - src = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(25); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - tmp = ((UINT32)CPU_DX << 16) + CPU_AX; - if (src != 0) { - if (tmp < ((UINT32)src << 16)) { - CPU_AX = (UINT16)(tmp / src); - CPU_DX = (UINT16)(tmp % src); - if(i386cpuid.cpu_family == 4){ - CPU_FLAGL ^= A_FLAG; - } - return; - } - } - EXCEPTION(DE_EXCEPTION, 0); -} - -void CPUCALL -DIV_EAXEd(UINT32 op) -{ - UINT32 madr; - UINT64 tmp; - UINT32 src; - - if (op >= 0xc0) { - CPU_WORKCLOCK(17); - src = *(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(25); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - tmp = ((UINT64)CPU_EDX << 32) + CPU_EAX; - if (src != 0) { - if (tmp < ((UINT64)src << 32)) { - CPU_EAX = (UINT32)(tmp / src); - CPU_EDX = (UINT32)(tmp % src); - if(i386cpuid.cpu_family == 4){ - CPU_FLAGL ^= A_FLAG; - } - return; - } - } - EXCEPTION(DE_EXCEPTION, 0); -} - - -/* - * INC - */ -ARITH_INSTRUCTION_1(INC) - -void INC_AX(void) { WORD_INC(CPU_AX); CPU_WORKCLOCK(2); } -void INC_CX(void) { WORD_INC(CPU_CX); CPU_WORKCLOCK(2); } -void INC_DX(void) { WORD_INC(CPU_DX); CPU_WORKCLOCK(2); } -void INC_BX(void) { WORD_INC(CPU_BX); CPU_WORKCLOCK(2); } -void INC_SP(void) { WORD_INC(CPU_SP); CPU_WORKCLOCK(2); } -void INC_BP(void) { WORD_INC(CPU_BP); CPU_WORKCLOCK(2); } -void INC_SI(void) { WORD_INC(CPU_SI); CPU_WORKCLOCK(2); } -void INC_DI(void) { WORD_INC(CPU_DI); CPU_WORKCLOCK(2); } - -void INC_EAX(void) { DWORD_INC(CPU_EAX); CPU_WORKCLOCK(2); } -void INC_ECX(void) { DWORD_INC(CPU_ECX); CPU_WORKCLOCK(2); } -void INC_EDX(void) { DWORD_INC(CPU_EDX); CPU_WORKCLOCK(2); } -void INC_EBX(void) { DWORD_INC(CPU_EBX); CPU_WORKCLOCK(2); } -void INC_ESP(void) { DWORD_INC(CPU_ESP); CPU_WORKCLOCK(2); } -void INC_EBP(void) { DWORD_INC(CPU_EBP); CPU_WORKCLOCK(2); } -void INC_ESI(void) { DWORD_INC(CPU_ESI); CPU_WORKCLOCK(2); } -void INC_EDI(void) { DWORD_INC(CPU_EDI); CPU_WORKCLOCK(2); } - - - -/* - * DEC - */ -ARITH_INSTRUCTION_1(DEC) - -void DEC_AX(void) { WORD_DEC(CPU_AX); CPU_WORKCLOCK(2); } -void DEC_CX(void) { WORD_DEC(CPU_CX); CPU_WORKCLOCK(2); } -void DEC_DX(void) { WORD_DEC(CPU_DX); CPU_WORKCLOCK(2); } -void DEC_BX(void) { WORD_DEC(CPU_BX); CPU_WORKCLOCK(2); } -void DEC_SP(void) { WORD_DEC(CPU_SP); CPU_WORKCLOCK(2); } -void DEC_BP(void) { WORD_DEC(CPU_BP); CPU_WORKCLOCK(2); } -void DEC_SI(void) { WORD_DEC(CPU_SI); CPU_WORKCLOCK(2); } -void DEC_DI(void) { WORD_DEC(CPU_DI); CPU_WORKCLOCK(2); } - -void DEC_EAX(void) { DWORD_DEC(CPU_EAX); CPU_WORKCLOCK(2); } -void DEC_ECX(void) { DWORD_DEC(CPU_ECX); CPU_WORKCLOCK(2); } -void DEC_EDX(void) { DWORD_DEC(CPU_EDX); CPU_WORKCLOCK(2); } -void DEC_EBX(void) { DWORD_DEC(CPU_EBX); CPU_WORKCLOCK(2); } -void DEC_ESP(void) { DWORD_DEC(CPU_ESP); CPU_WORKCLOCK(2); } -void DEC_EBP(void) { DWORD_DEC(CPU_EBP); CPU_WORKCLOCK(2); } -void DEC_ESI(void) { DWORD_DEC(CPU_ESI); CPU_WORKCLOCK(2); } -void DEC_EDI(void) { DWORD_DEC(CPU_EDI); CPU_WORKCLOCK(2); } - - -/* - * NEG - */ -static UINT32 CPUCALL -NEG1(UINT32 src, void *arg) -{ - UINT32 dst; - BYTE_NEG(dst, src); - return dst; -} - -static UINT32 CPUCALL -NEG2(UINT32 src, void *arg) -{ - UINT32 dst; - WORD_NEG(dst, src); - return dst; -} - -static UINT32 CPUCALL -NEG4(UINT32 src, void *arg) -{ - UINT32 dst; - DWORD_NEG(dst, src); - return dst; -} - -void CPUCALL -NEG_Eb(UINT32 op) -{ - UINT8 *out; - UINT32 src, dst, madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = reg8_b20[op]; - src = *out; - BYTE_NEG(dst, src); - *out = (UINT8)dst; - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, NEG1, 0); - } -} - -void CPUCALL -NEG_Ew(UINT32 op) -{ - UINT16 *out; - UINT32 src, dst, madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG16_B20(op); - src = *out; - WORD_NEG(dst, src); - *out = (UINT16)dst; - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, NEG2, 0); - } -} - -void CPUCALL -NEG_Ed(UINT32 op) -{ - UINT32 *out; - UINT32 src, dst, madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG32_B20(op); - src = *out; - DWORD_NEG(dst, src); - *out = dst; - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, NEG4, 0); - } -} - - -/* - * CMP - */ -void -CMP_EbGb(void) -{ - UINT8 *out; - UINT32 op, src, dst, res, madr; - - PREPART_EA_REG8(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = reg8_b20[op]; - dst = *out; - } else { - CPU_WORKCLOCK(5); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); - } - BYTE_SUB(res, dst, src); -} - -void -CMP_EwGw(void) -{ - UINT16 *out; - UINT32 op, src, dst, res, madr; - - PREPART_EA_REG16(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG16_B20(op); - dst = *out; - } else { - CPU_WORKCLOCK(5); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - WORD_SUB(res, dst, src); -} - -void -CMP_EdGd(void) -{ - UINT32 *out; - UINT32 op, src, dst, res, madr; - - PREPART_EA_REG32(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG32_B20(op); - dst = *out; - } else { - CPU_WORKCLOCK(5); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - DWORD_SUB(res, dst, src); -} - -void -CMP_GbEb(void) -{ - UINT8 *out; - UINT32 op, src, dst, res; - - PREPART_REG8_EA(op, src, out, 2, 5); - dst = *out; - BYTE_SUB(res, dst, src); -} - -void -CMP_GwEw(void) -{ - UINT16 *out; - UINT32 op, src, dst, res; - - PREPART_REG16_EA(op, src, out, 2, 5); - dst = *out; - WORD_SUB(res, dst, src); -} - -void -CMP_GdEd(void) -{ - UINT32 *out; - UINT32 op, src, dst, res; - - PREPART_REG32_EA(op, src, out, 2, 5); - dst = *out; - DWORD_SUB(res, dst, src); -} - -void -CMP_ALIb(void) -{ - UINT32 src, dst, res; - - CPU_WORKCLOCK(2); - GET_MODRM_PCBYTE(src); - dst = CPU_AL; - BYTE_SUB(res, dst, src); -} - -void -CMP_AXIw(void) -{ - UINT32 src, dst, res; - - CPU_WORKCLOCK(2); - GET_PCWORD(src); - dst = CPU_AX; - WORD_SUB(res, dst, src); -} - -void -CMP_EAXId(void) -{ - UINT32 src, dst, res; - - CPU_WORKCLOCK(2); - GET_PCDWORD(src); - dst = CPU_EAX; - DWORD_SUB(res, dst, src); -} - -void CPUCALL -CMP_EbIb(UINT8 *regp, UINT32 src) -{ - UINT32 dst, res; - - dst = *regp; - BYTE_SUB(res, dst, src); -} - -void CPUCALL -CMP_EbIb_ext(UINT32 madr, UINT32 src) -{ - UINT32 dst, res; - - dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); - BYTE_SUB(res, dst, src); -} - -void CPUCALL -CMP_EwIx(UINT16 *regp, UINT32 src) -{ - UINT32 dst, res; - - dst = *regp; - WORD_SUB(res, dst, src); -} - -void CPUCALL -CMP_EwIx_ext(UINT32 madr, UINT32 src) -{ - UINT32 dst, res; - - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - WORD_SUB(res, dst, src); -} - -void CPUCALL -CMP_EdIx(UINT32 *regp, UINT32 src) -{ - UINT32 dst, res; - - dst = *regp; - DWORD_SUB(res, dst, src); -} - -void CPUCALL -CMP_EdIx_ext(UINT32 madr, UINT32 src) -{ - UINT32 dst, res; - - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - DWORD_SUB(res, dst, src); -} +/* + * Copyright (c) 2002-2004 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" +#include "arith.mcr" + +#include "bin_arith.h" +#include + + +/* + * arith + */ +ARITH_INSTRUCTION_3(ADD) +ARITH_INSTRUCTION_3(ADC) +ARITH_INSTRUCTION_3(SUB) +ARITH_INSTRUCTION_3(SBB) + + +/* + * IMUL + */ +void CPUCALL +IMUL_ALEb(UINT32 op) +{ + UINT32 madr; + SINT32 res; + SINT8 src, dst; + + if (op >= 0xc0) { + CPU_WORKCLOCK(13); + src = *(reg8_b20[op]); + } else { + CPU_WORKCLOCK(16); + madr = calc_ea_dst(op); + src = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); + } + dst = CPU_AL; + BYTE_IMUL(res, dst, src); + CPU_AX = (UINT16)res; +} + +void CPUCALL +IMUL_AXEw(UINT32 op) +{ + UINT32 madr; + SINT32 res; + SINT16 src, dst; + + if (op >= 0xc0) { + CPU_WORKCLOCK(21); + src = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(24); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + dst = CPU_AX; + WORD_IMUL(res, dst, src); + CPU_AX = (UINT16)(res & 0xffff); + CPU_DX = (UINT16)(res >> 16); +} + +void CPUCALL +IMUL_EAXEd(UINT32 op) +{ + UINT32 madr; + SINT64 res; + SINT32 src, dst; + + if (op >= 0xc0) { + CPU_WORKCLOCK(21); + src = *(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(24); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + dst = CPU_EAX; + DWORD_IMUL(res, dst, src); + CPU_EAX = (UINT32)res; + CPU_EDX = (UINT32)(res >> 32); +} + +void +IMUL_GwEw(void) +{ + UINT16 *out; + UINT32 op; + SINT32 res; + SINT16 src, dst; + + PREPART_REG16_EA(op, src, out, 21, 27); + dst = *out; + WORD_IMUL(res, dst, src); + *out = (UINT16)res; +} + +void +IMUL_GdEd(void) +{ + UINT32 *out; + UINT32 op; + SINT64 res; + SINT32 src, dst; + + PREPART_REG32_EA(op, src, out, 21, 27); + dst = *out; + DWORD_IMUL(res, dst, src); + *out = (UINT32)res; +} + +void +IMUL_GwEwIb(void) +{ + UINT16 *out; + UINT32 op; + SINT32 res; + SINT16 src, dst; + + PREPART_REG16_EA(op, src, out, 21, 24); + GET_PCBYTES(dst); + WORD_IMUL(res, dst, src); + *out = (UINT16)res; +} + +void +IMUL_GdEdIb(void) +{ + UINT32 *out; + UINT32 op; + SINT64 res; + SINT32 src, dst; + + PREPART_REG32_EA(op, src, out, 21, 24); + GET_PCBYTESD(dst); + DWORD_IMUL(res, dst, src); + *out = (UINT32)res; +} + +void +IMUL_GwEwIw(void) +{ + UINT16 *out; + UINT32 op; + SINT32 res; + SINT16 src, dst; + + PREPART_REG16_EA(op, src, out, 21, 24); + GET_PCWORD(dst); + WORD_IMUL(res, dst, src); + *out = (UINT16)res; +} + +void +IMUL_GdEdId(void) +{ + UINT32 *out; + UINT32 op; + SINT64 res; + SINT32 src, dst; + + PREPART_REG32_EA(op, src, out, 21, 24); + GET_PCDWORD(dst); + DWORD_IMUL(res, dst, src); + *out = (UINT32)res; +} + + +/* + * MUL + */ +void CPUCALL +MUL_ALEb(UINT32 op) +{ + UINT32 res, madr; + UINT8 src, dst; + + if (op >= 0xc0) { + CPU_WORKCLOCK(13); + src = *(reg8_b20[op]); + } else { + CPU_WORKCLOCK(16); + madr = calc_ea_dst(op); + src = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); + } + dst = CPU_AL; + BYTE_MUL(res, dst, src); + CPU_AX = (UINT16)res; +} + +void CPUCALL +MUL_AXEw(UINT32 op) +{ + UINT32 res, madr; + UINT16 src, dst; + + if (op >= 0xc0) { + CPU_WORKCLOCK(21); + src = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(24); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + dst = CPU_AX; + WORD_MUL(res, dst, src); + CPU_AX = (UINT16)res; + CPU_DX = (UINT16)(res >> 16); +} + +void CPUCALL +MUL_EAXEd(UINT32 op) +{ + UINT32 res, madr; + UINT32 src, dst; + + if (op >= 0xc0) { + CPU_WORKCLOCK(21); + src = *(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(24); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + dst = CPU_EAX; + DWORD_MUL(res, dst, src); + CPU_EAX = res; + CPU_EDX = CPU_OV; +} + + +/* + * IDIV + */ +void CPUCALL +IDIV_ALEb(UINT32 op) +{ + UINT32 madr; + SINT16 tmp, r; + SINT8 src; + + if (op >= 0xc0) { + CPU_WORKCLOCK(17); + src = *(reg8_b20[op]); + } else { + CPU_WORKCLOCK(25); + madr = calc_ea_dst(op); + src = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); + } + tmp = (SINT16)CPU_AX; + if (src != 0) { + r = tmp / src; + if (((r + 0x80) & 0xff00) == 0) { + CPU_AL = (SINT8)r; + CPU_AH = tmp % src; + if(i386cpuid.cpu_family == 4){ + CPU_FLAGL ^= A_FLAG; + } + return; + } + } + EXCEPTION(DE_EXCEPTION, 0); +} + +void CPUCALL +IDIV_AXEw(UINT32 op) +{ + SINT32 tmp, r; + UINT32 madr; + SINT16 src; + + if (op >= 0xc0) { + CPU_WORKCLOCK(17); + src = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(25); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + tmp = (SINT32)(((UINT32)CPU_DX << 16) + (UINT32)CPU_AX); + if ((src != 0) && (tmp != INT_MIN)) { + r = tmp / src; + if (((r + 0x8000) & 0xffff0000) == 0) { + CPU_AX = (SINT16)r; + CPU_DX = tmp % src; + if(i386cpuid.cpu_family == 4){ + CPU_FLAGL ^= A_FLAG; + } + return; + } + } + EXCEPTION(DE_EXCEPTION, 0); +} + +void CPUCALL +IDIV_EAXEd(UINT32 op) +{ + SINT64 tmp, r; + SINT32 src; + UINT32 madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(17); + src = *(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(25); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + tmp = (SINT64)(((UINT64)CPU_EDX << 32) + (SINT64)CPU_EAX); + if ((src != 0) && (tmp != QWORD_CONST(0x8000000000000000))) { + r = tmp / src; + if (((r + SQWORD_CONST(0x80000000)) & QWORD_CONST(0xffffffff00000000)) == 0) { + CPU_EAX = (SINT32)r; + CPU_EDX = (SINT32)(tmp % src); + if(i386cpuid.cpu_family == 4){ + CPU_FLAGL ^= A_FLAG; + } + return; + } + } + EXCEPTION(DE_EXCEPTION, 0); +} + + +/* + * DIV + */ +void CPUCALL +DIV_ALEb(UINT32 op) +{ + UINT32 madr; + UINT16 tmp; + UINT8 src; + + if (op >= 0xc0) { + CPU_WORKCLOCK(17); + src = *(reg8_b20[op]); + } else { + CPU_WORKCLOCK(25); + madr = calc_ea_dst(op); + src = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); + } + tmp = CPU_AX; + if (src != 0) { + if (tmp < ((UINT16)src << 8)) { + CPU_AL = tmp / src; + CPU_AH = tmp % src; + if(i386cpuid.cpu_family == 4){ + CPU_FLAGL ^= A_FLAG; + } + return; + } + } + EXCEPTION(DE_EXCEPTION, 0); +} + +void CPUCALL +DIV_AXEw(UINT32 op) +{ + UINT32 madr; + UINT32 tmp; + UINT16 src; + + if (op >= 0xc0) { + CPU_WORKCLOCK(17); + src = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(25); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + tmp = ((UINT32)CPU_DX << 16) + CPU_AX; + if (src != 0) { + if (tmp < ((UINT32)src << 16)) { + CPU_AX = (UINT16)(tmp / src); + CPU_DX = (UINT16)(tmp % src); + if(i386cpuid.cpu_family == 4){ + CPU_FLAGL ^= A_FLAG; + } + return; + } + } + EXCEPTION(DE_EXCEPTION, 0); +} + +void CPUCALL +DIV_EAXEd(UINT32 op) +{ + UINT32 madr; + UINT64 tmp; + UINT32 src; + + if (op >= 0xc0) { + CPU_WORKCLOCK(17); + src = *(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(25); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + tmp = ((UINT64)CPU_EDX << 32) + CPU_EAX; + if (src != 0) { + if (tmp < ((UINT64)src << 32)) { + CPU_EAX = (UINT32)(tmp / src); + CPU_EDX = (UINT32)(tmp % src); + if(i386cpuid.cpu_family == 4){ + CPU_FLAGL ^= A_FLAG; + } + return; + } + } + EXCEPTION(DE_EXCEPTION, 0); +} + + +/* + * INC + */ +ARITH_INSTRUCTION_1(INC) + +void INC_AX(void) { WORD_INC(CPU_AX); CPU_WORKCLOCK(2); } +void INC_CX(void) { WORD_INC(CPU_CX); CPU_WORKCLOCK(2); } +void INC_DX(void) { WORD_INC(CPU_DX); CPU_WORKCLOCK(2); } +void INC_BX(void) { WORD_INC(CPU_BX); CPU_WORKCLOCK(2); } +void INC_SP(void) { WORD_INC(CPU_SP); CPU_WORKCLOCK(2); } +void INC_BP(void) { WORD_INC(CPU_BP); CPU_WORKCLOCK(2); } +void INC_SI(void) { WORD_INC(CPU_SI); CPU_WORKCLOCK(2); } +void INC_DI(void) { WORD_INC(CPU_DI); CPU_WORKCLOCK(2); } + +void INC_EAX(void) { DWORD_INC(CPU_EAX); CPU_WORKCLOCK(2); } +void INC_ECX(void) { DWORD_INC(CPU_ECX); CPU_WORKCLOCK(2); } +void INC_EDX(void) { DWORD_INC(CPU_EDX); CPU_WORKCLOCK(2); } +void INC_EBX(void) { DWORD_INC(CPU_EBX); CPU_WORKCLOCK(2); } +void INC_ESP(void) { DWORD_INC(CPU_ESP); CPU_WORKCLOCK(2); } +void INC_EBP(void) { DWORD_INC(CPU_EBP); CPU_WORKCLOCK(2); } +void INC_ESI(void) { DWORD_INC(CPU_ESI); CPU_WORKCLOCK(2); } +void INC_EDI(void) { DWORD_INC(CPU_EDI); CPU_WORKCLOCK(2); } + + + +/* + * DEC + */ +ARITH_INSTRUCTION_1(DEC) + +void DEC_AX(void) { WORD_DEC(CPU_AX); CPU_WORKCLOCK(2); } +void DEC_CX(void) { WORD_DEC(CPU_CX); CPU_WORKCLOCK(2); } +void DEC_DX(void) { WORD_DEC(CPU_DX); CPU_WORKCLOCK(2); } +void DEC_BX(void) { WORD_DEC(CPU_BX); CPU_WORKCLOCK(2); } +void DEC_SP(void) { WORD_DEC(CPU_SP); CPU_WORKCLOCK(2); } +void DEC_BP(void) { WORD_DEC(CPU_BP); CPU_WORKCLOCK(2); } +void DEC_SI(void) { WORD_DEC(CPU_SI); CPU_WORKCLOCK(2); } +void DEC_DI(void) { WORD_DEC(CPU_DI); CPU_WORKCLOCK(2); } + +void DEC_EAX(void) { DWORD_DEC(CPU_EAX); CPU_WORKCLOCK(2); } +void DEC_ECX(void) { DWORD_DEC(CPU_ECX); CPU_WORKCLOCK(2); } +void DEC_EDX(void) { DWORD_DEC(CPU_EDX); CPU_WORKCLOCK(2); } +void DEC_EBX(void) { DWORD_DEC(CPU_EBX); CPU_WORKCLOCK(2); } +void DEC_ESP(void) { DWORD_DEC(CPU_ESP); CPU_WORKCLOCK(2); } +void DEC_EBP(void) { DWORD_DEC(CPU_EBP); CPU_WORKCLOCK(2); } +void DEC_ESI(void) { DWORD_DEC(CPU_ESI); CPU_WORKCLOCK(2); } +void DEC_EDI(void) { DWORD_DEC(CPU_EDI); CPU_WORKCLOCK(2); } + + +/* + * NEG + */ +static UINT32 CPUCALL +NEG1(UINT32 src, void *arg) +{ + UINT32 dst; + BYTE_NEG(dst, src); + return dst; +} + +static UINT32 CPUCALL +NEG2(UINT32 src, void *arg) +{ + UINT32 dst; + WORD_NEG(dst, src); + return dst; +} + +static UINT32 CPUCALL +NEG4(UINT32 src, void *arg) +{ + UINT32 dst; + DWORD_NEG(dst, src); + return dst; +} + +void CPUCALL +NEG_Eb(UINT32 op) +{ + UINT8 *out; + UINT32 src, dst, madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = reg8_b20[op]; + src = *out; + BYTE_NEG(dst, src); + *out = (UINT8)dst; + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, NEG1, 0); + } +} + +void CPUCALL +NEG_Ew(UINT32 op) +{ + UINT16 *out; + UINT32 src, dst, madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG16_B20(op); + src = *out; + WORD_NEG(dst, src); + *out = (UINT16)dst; + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, NEG2, 0); + } +} + +void CPUCALL +NEG_Ed(UINT32 op) +{ + UINT32 *out; + UINT32 src, dst, madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG32_B20(op); + src = *out; + DWORD_NEG(dst, src); + *out = dst; + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, NEG4, 0); + } +} + + +/* + * CMP + */ +void +CMP_EbGb(void) +{ + UINT8 *out; + UINT32 op, src, dst, res, madr; + + PREPART_EA_REG8(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = reg8_b20[op]; + dst = *out; + } else { + CPU_WORKCLOCK(5); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); + } + BYTE_SUB(res, dst, src); +} + +void +CMP_EwGw(void) +{ + UINT16 *out; + UINT32 op, src, dst, res, madr; + + PREPART_EA_REG16(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG16_B20(op); + dst = *out; + } else { + CPU_WORKCLOCK(5); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + WORD_SUB(res, dst, src); +} + +void +CMP_EdGd(void) +{ + UINT32 *out; + UINT32 op, src, dst, res, madr; + + PREPART_EA_REG32(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG32_B20(op); + dst = *out; + } else { + CPU_WORKCLOCK(5); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + DWORD_SUB(res, dst, src); +} + +void +CMP_GbEb(void) +{ + UINT8 *out; + UINT32 op, src, dst, res; + + PREPART_REG8_EA(op, src, out, 2, 5); + dst = *out; + BYTE_SUB(res, dst, src); +} + +void +CMP_GwEw(void) +{ + UINT16 *out; + UINT32 op, src, dst, res; + + PREPART_REG16_EA(op, src, out, 2, 5); + dst = *out; + WORD_SUB(res, dst, src); +} + +void +CMP_GdEd(void) +{ + UINT32 *out; + UINT32 op, src, dst, res; + + PREPART_REG32_EA(op, src, out, 2, 5); + dst = *out; + DWORD_SUB(res, dst, src); +} + +void +CMP_ALIb(void) +{ + UINT32 src, dst, res; + + CPU_WORKCLOCK(2); + GET_MODRM_PCBYTE(src); + dst = CPU_AL; + BYTE_SUB(res, dst, src); +} + +void +CMP_AXIw(void) +{ + UINT32 src, dst, res; + + CPU_WORKCLOCK(2); + GET_PCWORD(src); + dst = CPU_AX; + WORD_SUB(res, dst, src); +} + +void +CMP_EAXId(void) +{ + UINT32 src, dst, res; + + CPU_WORKCLOCK(2); + GET_PCDWORD(src); + dst = CPU_EAX; + DWORD_SUB(res, dst, src); +} + +void CPUCALL +CMP_EbIb(UINT8 *regp, UINT32 src) +{ + UINT32 dst, res; + + dst = *regp; + BYTE_SUB(res, dst, src); +} + +void CPUCALL +CMP_EbIb_ext(UINT32 madr, UINT32 src) +{ + UINT32 dst, res; + + dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); + BYTE_SUB(res, dst, src); +} + +void CPUCALL +CMP_EwIx(UINT16 *regp, UINT32 src) +{ + UINT32 dst, res; + + dst = *regp; + WORD_SUB(res, dst, src); +} + +void CPUCALL +CMP_EwIx_ext(UINT32 madr, UINT32 src) +{ + UINT32 dst, res; + + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + WORD_SUB(res, dst, src); +} + +void CPUCALL +CMP_EdIx(UINT32 *regp, UINT32 src) +{ + UINT32 dst, res; + + dst = *regp; + DWORD_SUB(res, dst, src); +} + +void CPUCALL +CMP_EdIx_ext(UINT32 madr, UINT32 src) +{ + UINT32 dst, res; + + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + DWORD_SUB(res, dst, src); +} diff --git a/i386c/ia32/instructions/bin_arith.h b/i386c/ia32/instructions/bin_arith.h old mode 100755 new mode 100644 index 5906627c..3639b564 --- a/i386c/ia32/instructions/bin_arith.h +++ b/i386c/ia32/instructions/bin_arith.h @@ -1,195 +1,195 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_BIN_ARITH_H__ -#define IA32_CPU_INSTRUCTION_BIN_ARITH_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* ADD */ -void ADD_EbGb(void); -void ADD_EwGw(void); -void ADD_EdGd(void); -void ADD_GbEb(void); -void ADD_GwEw(void); -void ADD_GdEd(void); -void ADD_ALIb(void); -void ADD_AXIw(void); -void ADD_EAXId(void); -void CPUCALL ADD_EbIb(UINT8 *, UINT32); -void CPUCALL ADD_EwIx(UINT16 *, UINT32); -void CPUCALL ADD_EdIx(UINT32 *, UINT32); -void CPUCALL ADD_EbIb_ext(UINT32, UINT32); -void CPUCALL ADD_EwIx_ext(UINT32, UINT32); -void CPUCALL ADD_EdIx_ext(UINT32, UINT32); - -/* ADC */ -void ADC_EbGb(void); -void ADC_EwGw(void); -void ADC_EdGd(void); -void ADC_GbEb(void); -void ADC_GwEw(void); -void ADC_GdEd(void); -void ADC_ALIb(void); -void ADC_AXIw(void); -void ADC_EAXId(void); -void CPUCALL ADC_EbIb(UINT8 *, UINT32); -void CPUCALL ADC_EwIx(UINT16 *, UINT32); -void CPUCALL ADC_EdIx(UINT32 *, UINT32); -void CPUCALL ADC_EbIb_ext(UINT32, UINT32); -void CPUCALL ADC_EwIx_ext(UINT32, UINT32); -void CPUCALL ADC_EdIx_ext(UINT32, UINT32); - -/* SUB */ -void SUB_EbGb(void); -void SUB_EwGw(void); -void SUB_EdGd(void); -void SUB_GbEb(void); -void SUB_GwEw(void); -void SUB_GdEd(void); -void SUB_ALIb(void); -void SUB_AXIw(void); -void SUB_EAXId(void); -void CPUCALL SUB_EbIb(UINT8 *, UINT32); -void CPUCALL SUB_EwIx(UINT16 *, UINT32); -void CPUCALL SUB_EdIx(UINT32 *, UINT32); -void CPUCALL SUB_EbIb_ext(UINT32, UINT32); -void CPUCALL SUB_EwIx_ext(UINT32, UINT32); -void CPUCALL SUB_EdIx_ext(UINT32, UINT32); - -/* SBB */ -void SBB_EbGb(void); -void SBB_EwGw(void); -void SBB_EdGd(void); -void SBB_GbEb(void); -void SBB_GwEw(void); -void SBB_GdEd(void); -void SBB_ALIb(void); -void SBB_AXIw(void); -void SBB_EAXId(void); -void CPUCALL SBB_EbIb(UINT8 *, UINT32); -void CPUCALL SBB_EwIx(UINT16 *, UINT32); -void CPUCALL SBB_EdIx(UINT32 *, UINT32); -void CPUCALL SBB_EbIb_ext(UINT32, UINT32); -void CPUCALL SBB_EwIx_ext(UINT32, UINT32); -void CPUCALL SBB_EdIx_ext(UINT32, UINT32); - -/* IMUL */ -void CPUCALL IMUL_ALEb(UINT32 op); -void CPUCALL IMUL_AXEw(UINT32 op); -void CPUCALL IMUL_EAXEd(UINT32 op); -void IMUL_GwEw(void); -void IMUL_GdEd(void); -void IMUL_GwEwIb(void); -void IMUL_GdEdIb(void); -void IMUL_GwEwIw(void); -void IMUL_GdEdId(void); - -/* MUL */ -void CPUCALL MUL_ALEb(UINT32 op); -void CPUCALL MUL_AXEw(UINT32 op); -void CPUCALL MUL_EAXEd(UINT32 op); - -/* IDIV */ -void CPUCALL IDIV_ALEb(UINT32 op); -void CPUCALL IDIV_AXEw(UINT32 op); -void CPUCALL IDIV_EAXEd(UINT32 op); - -/* DIV */ -void CPUCALL DIV_ALEb(UINT32 op); -void CPUCALL DIV_AXEw(UINT32 op); -void CPUCALL DIV_EAXEd(UINT32 op); - -/* INC */ -void CPUCALL INC_Eb(UINT32 op); -void CPUCALL INC_Ew(UINT32 op); -void CPUCALL INC_Ed(UINT32 op); -void INC_AX(void); -void INC_CX(void); -void INC_DX(void); -void INC_BX(void); -void INC_SP(void); -void INC_BP(void); -void INC_SI(void); -void INC_DI(void); -void INC_EAX(void); -void INC_ECX(void); -void INC_EDX(void); -void INC_EBX(void); -void INC_ESP(void); -void INC_EBP(void); -void INC_ESI(void); -void INC_EDI(void); - -/* DEC */ -void CPUCALL DEC_Eb(UINT32 op); -void CPUCALL DEC_Ew(UINT32 op); -void CPUCALL DEC_Ed(UINT32 op); -void DEC_AX(void); -void DEC_CX(void); -void DEC_DX(void); -void DEC_BX(void); -void DEC_SP(void); -void DEC_BP(void); -void DEC_SI(void); -void DEC_DI(void); -void DEC_EAX(void); -void DEC_ECX(void); -void DEC_EDX(void); -void DEC_EBX(void); -void DEC_ESP(void); -void DEC_EBP(void); -void DEC_ESI(void); -void DEC_EDI(void); - -/* NEG */ -void CPUCALL NEG_Eb(UINT32 op); -void CPUCALL NEG_Ew(UINT32 op); -void CPUCALL NEG_Ed(UINT32 op); - -/* CMP */ -void CMP_EbGb(void); -void CMP_EwGw(void); -void CMP_EdGd(void); -void CMP_GbEb(void); -void CMP_GwEw(void); -void CMP_GdEd(void); -void CMP_ALIb(void); -void CMP_AXIw(void); -void CMP_EAXId(void); -void CPUCALL CMP_EbIb(UINT8 *, UINT32); -void CPUCALL CMP_EwIx(UINT16 *, UINT32); -void CPUCALL CMP_EdIx(UINT32 *, UINT32); -void CPUCALL CMP_EbIb_ext(UINT32, UINT32); -void CPUCALL CMP_EwIx_ext(UINT32, UINT32); -void CPUCALL CMP_EdIx_ext(UINT32, UINT32); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_BIN_ARITH_H__ */ +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_BIN_ARITH_H__ +#define IA32_CPU_INSTRUCTION_BIN_ARITH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ADD */ +void ADD_EbGb(void); +void ADD_EwGw(void); +void ADD_EdGd(void); +void ADD_GbEb(void); +void ADD_GwEw(void); +void ADD_GdEd(void); +void ADD_ALIb(void); +void ADD_AXIw(void); +void ADD_EAXId(void); +void CPUCALL ADD_EbIb(UINT8 *, UINT32); +void CPUCALL ADD_EwIx(UINT16 *, UINT32); +void CPUCALL ADD_EdIx(UINT32 *, UINT32); +void CPUCALL ADD_EbIb_ext(UINT32, UINT32); +void CPUCALL ADD_EwIx_ext(UINT32, UINT32); +void CPUCALL ADD_EdIx_ext(UINT32, UINT32); + +/* ADC */ +void ADC_EbGb(void); +void ADC_EwGw(void); +void ADC_EdGd(void); +void ADC_GbEb(void); +void ADC_GwEw(void); +void ADC_GdEd(void); +void ADC_ALIb(void); +void ADC_AXIw(void); +void ADC_EAXId(void); +void CPUCALL ADC_EbIb(UINT8 *, UINT32); +void CPUCALL ADC_EwIx(UINT16 *, UINT32); +void CPUCALL ADC_EdIx(UINT32 *, UINT32); +void CPUCALL ADC_EbIb_ext(UINT32, UINT32); +void CPUCALL ADC_EwIx_ext(UINT32, UINT32); +void CPUCALL ADC_EdIx_ext(UINT32, UINT32); + +/* SUB */ +void SUB_EbGb(void); +void SUB_EwGw(void); +void SUB_EdGd(void); +void SUB_GbEb(void); +void SUB_GwEw(void); +void SUB_GdEd(void); +void SUB_ALIb(void); +void SUB_AXIw(void); +void SUB_EAXId(void); +void CPUCALL SUB_EbIb(UINT8 *, UINT32); +void CPUCALL SUB_EwIx(UINT16 *, UINT32); +void CPUCALL SUB_EdIx(UINT32 *, UINT32); +void CPUCALL SUB_EbIb_ext(UINT32, UINT32); +void CPUCALL SUB_EwIx_ext(UINT32, UINT32); +void CPUCALL SUB_EdIx_ext(UINT32, UINT32); + +/* SBB */ +void SBB_EbGb(void); +void SBB_EwGw(void); +void SBB_EdGd(void); +void SBB_GbEb(void); +void SBB_GwEw(void); +void SBB_GdEd(void); +void SBB_ALIb(void); +void SBB_AXIw(void); +void SBB_EAXId(void); +void CPUCALL SBB_EbIb(UINT8 *, UINT32); +void CPUCALL SBB_EwIx(UINT16 *, UINT32); +void CPUCALL SBB_EdIx(UINT32 *, UINT32); +void CPUCALL SBB_EbIb_ext(UINT32, UINT32); +void CPUCALL SBB_EwIx_ext(UINT32, UINT32); +void CPUCALL SBB_EdIx_ext(UINT32, UINT32); + +/* IMUL */ +void CPUCALL IMUL_ALEb(UINT32 op); +void CPUCALL IMUL_AXEw(UINT32 op); +void CPUCALL IMUL_EAXEd(UINT32 op); +void IMUL_GwEw(void); +void IMUL_GdEd(void); +void IMUL_GwEwIb(void); +void IMUL_GdEdIb(void); +void IMUL_GwEwIw(void); +void IMUL_GdEdId(void); + +/* MUL */ +void CPUCALL MUL_ALEb(UINT32 op); +void CPUCALL MUL_AXEw(UINT32 op); +void CPUCALL MUL_EAXEd(UINT32 op); + +/* IDIV */ +void CPUCALL IDIV_ALEb(UINT32 op); +void CPUCALL IDIV_AXEw(UINT32 op); +void CPUCALL IDIV_EAXEd(UINT32 op); + +/* DIV */ +void CPUCALL DIV_ALEb(UINT32 op); +void CPUCALL DIV_AXEw(UINT32 op); +void CPUCALL DIV_EAXEd(UINT32 op); + +/* INC */ +void CPUCALL INC_Eb(UINT32 op); +void CPUCALL INC_Ew(UINT32 op); +void CPUCALL INC_Ed(UINT32 op); +void INC_AX(void); +void INC_CX(void); +void INC_DX(void); +void INC_BX(void); +void INC_SP(void); +void INC_BP(void); +void INC_SI(void); +void INC_DI(void); +void INC_EAX(void); +void INC_ECX(void); +void INC_EDX(void); +void INC_EBX(void); +void INC_ESP(void); +void INC_EBP(void); +void INC_ESI(void); +void INC_EDI(void); + +/* DEC */ +void CPUCALL DEC_Eb(UINT32 op); +void CPUCALL DEC_Ew(UINT32 op); +void CPUCALL DEC_Ed(UINT32 op); +void DEC_AX(void); +void DEC_CX(void); +void DEC_DX(void); +void DEC_BX(void); +void DEC_SP(void); +void DEC_BP(void); +void DEC_SI(void); +void DEC_DI(void); +void DEC_EAX(void); +void DEC_ECX(void); +void DEC_EDX(void); +void DEC_EBX(void); +void DEC_ESP(void); +void DEC_EBP(void); +void DEC_ESI(void); +void DEC_EDI(void); + +/* NEG */ +void CPUCALL NEG_Eb(UINT32 op); +void CPUCALL NEG_Ew(UINT32 op); +void CPUCALL NEG_Ed(UINT32 op); + +/* CMP */ +void CMP_EbGb(void); +void CMP_EwGw(void); +void CMP_EdGd(void); +void CMP_GbEb(void); +void CMP_GwEw(void); +void CMP_GdEd(void); +void CMP_ALIb(void); +void CMP_AXIw(void); +void CMP_EAXId(void); +void CPUCALL CMP_EbIb(UINT8 *, UINT32); +void CPUCALL CMP_EwIx(UINT16 *, UINT32); +void CPUCALL CMP_EdIx(UINT32 *, UINT32); +void CPUCALL CMP_EbIb_ext(UINT32, UINT32); +void CPUCALL CMP_EwIx_ext(UINT32, UINT32); +void CPUCALL CMP_EdIx_ext(UINT32, UINT32); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_BIN_ARITH_H__ */ diff --git a/i386c/ia32/instructions/bit_byte.c b/i386c/ia32/instructions/bit_byte.c old mode 100755 new mode 100644 index 3f4ade27..e281b854 --- a/i386c/ia32/instructions/bit_byte.c +++ b/i386c/ia32/instructions/bit_byte.c @@ -1,1056 +1,1056 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" - -#include "bit_byte.h" - -#define BIT_OFFSET16(v) (2 * (((SINT16)(v)) >> 4)) -#define BIT_INDEX16(v) ((v) & 0xf) -#define BIT_MAKEBIT16(v) (1 << BIT_INDEX16(v)) - -#define BIT_OFFSET32(v) (4 * (((SINT32)(v)) >> 5)) -#define BIT_INDEX32(v) ((v) & 0x1f) -#define BIT_MAKEBIT32(v) (1 << BIT_INDEX32(v)) - - -/* - * BT - */ -void -BT_EwGw(void) -{ - UINT32 op, src, dst, madr; - - PREPART_EA_REG16(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - dst = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - madr += BIT_OFFSET16(src); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - CPU_FLAGL &= ~C_FLAG; - CPU_FLAGL |= (dst >> BIT_INDEX16(src)) & 1; -} - -void -BT_EdGd(void) -{ - UINT32 op, src, dst, madr; - - PREPART_EA_REG32(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - dst = *(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - madr += BIT_OFFSET32(src); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - CPU_FLAGL &= ~C_FLAG; - CPU_FLAGL |= (dst >> BIT_INDEX32(src)) & 1; -} - -void CPUCALL -BT_EwIb(UINT32 op) -{ - UINT32 src, dst, madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - GET_MODRM_PCBYTE(src); - dst = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(6); - madr = calc_ea_dst(op); - GET_MODRM_PCBYTE(src); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - CPU_FLAGL &= ~C_FLAG; - CPU_FLAGL |= (dst >> BIT_INDEX16(src)) & 1; -} - -void CPUCALL -BT_EdIb(UINT32 op) -{ - UINT32 src, dst, madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - GET_MODRM_PCBYTE(src); - dst = *(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(6); - madr = calc_ea_dst(op); - GET_MODRM_PCBYTE(src); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - CPU_FLAGL &= ~C_FLAG; - CPU_FLAGL |= (dst >> BIT_INDEX32(src)) & 1; -} - -/* - * BTS - */ -void -BTS_EwGw(void) -{ - UINT16 *out; - UINT32 op, src, dst, res, madr; - UINT16 bit; - - PREPART_EA_REG16(op, src); - bit = BIT_MAKEBIT16(src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG16_B20(op); - dst = *out; - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - res = dst | bit; - *out = (UINT16)res; - } - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - madr += BIT_OFFSET16(src); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst | bit; - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); - } -} - -void -BTS_EdGd(void) -{ - UINT32 *out; - UINT32 op, src, dst, res, madr; - UINT32 bit; - - PREPART_EA_REG32(op, src); - bit = BIT_MAKEBIT32(src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG32_B20(op); - dst = *out; - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - res = dst | bit; - *out = res; - } - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - madr += BIT_OFFSET32(src); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst | bit; - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); - } -} - -void CPUCALL -BTS_EwIb(UINT32 op) -{ - UINT16 *out; - UINT32 src, dst, res, madr; - UINT16 bit; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - GET_MODRM_PCBYTE(src); - out = CPU_REG16_B20(op); - dst = *out; - bit = BIT_MAKEBIT16(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - res = dst | bit; - *out = (UINT16)res; - } - } else { - CPU_WORKCLOCK(6); - madr = calc_ea_dst(op); - GET_MODRM_PCBYTE(src); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - bit = BIT_MAKEBIT16(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst | bit; - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); - } -} - -void CPUCALL -BTS_EdIb(UINT32 op) -{ - UINT32 *out; - UINT32 src, dst, res, madr; - UINT32 bit; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - GET_MODRM_PCBYTE(src); - out = CPU_REG32_B20(op); - dst = *out; - bit = BIT_MAKEBIT32(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - res = dst | bit; - *out = res; - } - } else { - CPU_WORKCLOCK(6); - madr = calc_ea_dst(op); - GET_MODRM_PCBYTE(src); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - bit = BIT_MAKEBIT32(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst | bit; - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); - } -} - -/* - * BTR - */ -void -BTR_EwGw(void) -{ - UINT16 *out; - UINT32 op, src, dst, res, madr; - UINT16 bit; - - PREPART_EA_REG16(op, src); - bit = BIT_MAKEBIT16(src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG16_B20(op); - dst = *out; - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - res = dst & ~bit; - *out = (UINT16)res; - } else { - CPU_FLAGL &= ~C_FLAG; - } - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - madr += BIT_OFFSET16(src); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst & ~bit; - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); - } -} - -void -BTR_EdGd(void) -{ - UINT32 *out; - UINT32 op, src, dst, res, madr; - UINT32 bit; - - PREPART_EA_REG32(op, src); - bit = BIT_MAKEBIT32(src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG32_B20(op); - dst = *out; - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - res = dst & ~bit; - *out = res; - } else { - CPU_FLAGL &= ~C_FLAG; - } - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - madr += BIT_OFFSET32(src); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst & ~bit; - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); - } -} - -void CPUCALL -BTR_EwIb(UINT32 op) -{ - UINT16 *out; - UINT32 src, dst, res, madr; - UINT16 bit; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - GET_MODRM_PCBYTE(src); - out = CPU_REG16_B20(op); - dst = *out; - bit = BIT_MAKEBIT16(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - res = dst & ~bit; - *out = (UINT16)res; - } else { - CPU_FLAGL &= ~C_FLAG; - } - } else { - CPU_WORKCLOCK(6); - madr = calc_ea_dst(op); - GET_MODRM_PCBYTE(src); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - bit = BIT_MAKEBIT16(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst & ~bit; - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); - } -} - -void CPUCALL -BTR_EdIb(UINT32 op) -{ - UINT32 *out; - UINT32 src, dst, res, madr; - UINT32 bit; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - GET_MODRM_PCBYTE(src); - out = CPU_REG32_B20(op); - dst = *out; - bit = BIT_MAKEBIT32(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - res = dst & ~bit; - *out = res; - } else { - CPU_FLAGL &= ~C_FLAG; - } - } else { - CPU_WORKCLOCK(6); - madr = calc_ea_dst(op); - GET_MODRM_PCBYTE(src); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - bit = BIT_MAKEBIT32(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst & ~bit; - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); - } -} - -/* - * BTC - */ -void -BTC_EwGw(void) -{ - UINT16 *out; - UINT32 op, src, dst, res, madr; - UINT16 bit; - - PREPART_EA_REG16(op, src); - bit = BIT_MAKEBIT16(src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG16_B20(op); - dst = *out; - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst ^ bit; - *out = (UINT16)res; - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - madr += BIT_OFFSET16(src); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst ^ bit; - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); - } -} - -void -BTC_EdGd(void) -{ - UINT32 *out; - UINT32 op, src, dst, res, madr; - UINT32 bit; - - PREPART_EA_REG32(op, src); - bit = BIT_MAKEBIT32(src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG32_B20(op); - dst = *out; - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst ^ bit; - *out = res; - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - madr += BIT_OFFSET32(src); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst ^ bit; - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); - } -} - -void CPUCALL -BTC_EwIb(UINT32 op) -{ - UINT16 *out; - UINT32 src, dst, res, madr; - UINT16 bit; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - GET_MODRM_PCBYTE(src); - out = CPU_REG16_B20(op); - dst = *out; - bit = BIT_MAKEBIT16(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst ^ bit; - *out = (UINT16)res; - } else { - CPU_WORKCLOCK(6); - madr = calc_ea_dst(op); - GET_MODRM_PCBYTE(src); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - bit = BIT_MAKEBIT16(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst ^ bit; - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); - } -} - -void CPUCALL -BTC_EdIb(UINT32 op) -{ - UINT32 *out; - UINT32 src, dst, res, madr; - UINT32 bit; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - GET_MODRM_PCBYTE(src); - out = CPU_REG32_B20(op); - dst = *out; - bit = BIT_MAKEBIT32(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst ^ bit; - *out = res; - } else { - CPU_WORKCLOCK(6); - madr = calc_ea_dst(op); - GET_MODRM_PCBYTE(src); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - bit = BIT_MAKEBIT32(src); - if (dst & bit) { - CPU_FLAGL |= C_FLAG; - } else { - CPU_FLAGL &= ~C_FLAG; - } - res = dst ^ bit; - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); - } -} - -/* - * BSF - */ -void -BSF_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - int bit; - - PREPART_REG16_EA(op, src, out, 2, 7); - if (src == 0) { - CPU_FLAGL |= Z_FLAG; - /* dest reg is undefined */ - } else { - CPU_FLAGL &= ~Z_FLAG; - for (bit = 0; bit < 15; bit++) { - if (src & (1 << bit)) - break; - } - *out = (UINT16)bit; - } -} - -void -BSF_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - int bit; - - PREPART_REG32_EA(op, src, out, 2, 7); - if (src == 0) { - CPU_FLAGL |= Z_FLAG; - /* dest reg is undefined */ - } else { - CPU_FLAGL &= ~Z_FLAG; - for (bit = 0; bit < 31; bit++) { - if (src & (1 << bit)) - break; - } - *out = (UINT32)bit; - } -} - -/* - * BSR - */ -void -BSR_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - int bit; - - PREPART_REG16_EA(op, src, out, 2, 7); - if (src == 0) { - CPU_FLAGL |= Z_FLAG; - /* dest reg is undefined */ - } else { - CPU_FLAGL &= ~Z_FLAG; - for (bit = 15; bit > 0; bit--) { - if (src & (1 << bit)) - break; - } - *out = (UINT16)bit; - } -} - -void -BSR_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - int bit; - - PREPART_REG32_EA(op, src, out, 2, 7); - if (src == 0) { - CPU_FLAGL |= Z_FLAG; - /* dest reg is undefined */ - } else { - CPU_FLAGL &= ~Z_FLAG; - for (bit = 31; bit > 0; bit--) { - if (src & (1 << bit)) - break; - } - *out = (UINT32)bit; - } -} - -/* - * SETcc - */ -void -SETO_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_O?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETNO_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_NO?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETC_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_C?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETNC_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_NC?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETZ_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_Z?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETNZ_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_NZ?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETA_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_A?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETNA_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_NA?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETS_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_S?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETNS_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_NS?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETP_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_P?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETNP_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_NP?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETL_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_L?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETNL_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_NL?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETLE_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_LE?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -void -SETNLE_Eb(void) -{ - UINT32 op, madr; - UINT8 v = CC_NLE?1:0; - - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = v; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); - } -} - -/* - * TEST - */ -void -TEST_EbGb(void) -{ - UINT32 op, src, tmp, madr; - - PREPART_EA_REG8(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - tmp = *(reg8_b20[op]); - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); - } - BYTE_AND(tmp, src); -} - -void -TEST_EwGw(void) -{ - UINT32 op, src, tmp, madr; - - PREPART_EA_REG16(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - tmp = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - WORD_AND(tmp, src); -} - -void -TEST_EdGd(void) -{ - UINT32 op, src, tmp, madr; - - PREPART_EA_REG32(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - tmp = *(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - DWORD_AND(tmp, src); -} - -void -TEST_ALIb(void) -{ - UINT32 src, tmp; - - CPU_WORKCLOCK(3); - tmp = CPU_AL; - GET_MODRM_PCBYTE(src); - BYTE_AND(tmp, src); -} - -void -TEST_AXIw(void) -{ - UINT32 src, tmp; - - CPU_WORKCLOCK(3); - tmp = CPU_AX; - GET_PCWORD(src); - WORD_AND(tmp, src); -} - -void -TEST_EAXId(void) -{ - UINT32 src, tmp; - - CPU_WORKCLOCK(3); - tmp = CPU_EAX; - GET_PCDWORD(src); - DWORD_AND(tmp, src); -} - -void CPUCALL -TEST_EbIb(UINT32 op) -{ - UINT32 src, tmp, madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - tmp = *(reg8_b20[op]); - } else { - CPU_WORKCLOCK(6); - madr = calc_ea_dst(op); - tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); - } - GET_PCBYTE(src); - BYTE_AND(tmp, src); -} - -void CPUCALL -TEST_EwIw(UINT32 op) -{ - UINT32 src, tmp, madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - tmp = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(6); - madr = calc_ea_dst(op); - tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - GET_PCWORD(src); - WORD_AND(tmp, src); -} - -void CPUCALL -TEST_EdId(UINT32 op) -{ - UINT32 src, tmp, madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - tmp = *(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(6); - madr = calc_ea_dst(op); - tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - GET_PCDWORD(src); - DWORD_AND(tmp, src); +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" + +#include "bit_byte.h" + +#define BIT_OFFSET16(v) (2 * (((SINT16)(v)) >> 4)) +#define BIT_INDEX16(v) ((v) & 0xf) +#define BIT_MAKEBIT16(v) (1 << BIT_INDEX16(v)) + +#define BIT_OFFSET32(v) (4 * (((SINT32)(v)) >> 5)) +#define BIT_INDEX32(v) ((v) & 0x1f) +#define BIT_MAKEBIT32(v) (1 << BIT_INDEX32(v)) + + +/* + * BT + */ +void +BT_EwGw(void) +{ + UINT32 op, src, dst, madr; + + PREPART_EA_REG16(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + dst = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + madr += BIT_OFFSET16(src); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + CPU_FLAGL &= ~C_FLAG; + CPU_FLAGL |= (dst >> BIT_INDEX16(src)) & 1; +} + +void +BT_EdGd(void) +{ + UINT32 op, src, dst, madr; + + PREPART_EA_REG32(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + dst = *(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + madr += BIT_OFFSET32(src); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + CPU_FLAGL &= ~C_FLAG; + CPU_FLAGL |= (dst >> BIT_INDEX32(src)) & 1; +} + +void CPUCALL +BT_EwIb(UINT32 op) +{ + UINT32 src, dst, madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + GET_MODRM_PCBYTE(src); + dst = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(6); + madr = calc_ea_dst(op); + GET_MODRM_PCBYTE(src); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + CPU_FLAGL &= ~C_FLAG; + CPU_FLAGL |= (dst >> BIT_INDEX16(src)) & 1; +} + +void CPUCALL +BT_EdIb(UINT32 op) +{ + UINT32 src, dst, madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + GET_MODRM_PCBYTE(src); + dst = *(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(6); + madr = calc_ea_dst(op); + GET_MODRM_PCBYTE(src); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + CPU_FLAGL &= ~C_FLAG; + CPU_FLAGL |= (dst >> BIT_INDEX32(src)) & 1; +} + +/* + * BTS + */ +void +BTS_EwGw(void) +{ + UINT16 *out; + UINT32 op, src, dst, res, madr; + UINT16 bit; + + PREPART_EA_REG16(op, src); + bit = BIT_MAKEBIT16(src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG16_B20(op); + dst = *out; + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + res = dst | bit; + *out = (UINT16)res; + } + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + madr += BIT_OFFSET16(src); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst | bit; + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); + } +} + +void +BTS_EdGd(void) +{ + UINT32 *out; + UINT32 op, src, dst, res, madr; + UINT32 bit; + + PREPART_EA_REG32(op, src); + bit = BIT_MAKEBIT32(src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG32_B20(op); + dst = *out; + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + res = dst | bit; + *out = res; + } + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + madr += BIT_OFFSET32(src); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst | bit; + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); + } +} + +void CPUCALL +BTS_EwIb(UINT32 op) +{ + UINT16 *out; + UINT32 src, dst, res, madr; + UINT16 bit; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + GET_MODRM_PCBYTE(src); + out = CPU_REG16_B20(op); + dst = *out; + bit = BIT_MAKEBIT16(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + res = dst | bit; + *out = (UINT16)res; + } + } else { + CPU_WORKCLOCK(6); + madr = calc_ea_dst(op); + GET_MODRM_PCBYTE(src); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + bit = BIT_MAKEBIT16(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst | bit; + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); + } +} + +void CPUCALL +BTS_EdIb(UINT32 op) +{ + UINT32 *out; + UINT32 src, dst, res, madr; + UINT32 bit; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + GET_MODRM_PCBYTE(src); + out = CPU_REG32_B20(op); + dst = *out; + bit = BIT_MAKEBIT32(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + res = dst | bit; + *out = res; + } + } else { + CPU_WORKCLOCK(6); + madr = calc_ea_dst(op); + GET_MODRM_PCBYTE(src); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + bit = BIT_MAKEBIT32(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst | bit; + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); + } +} + +/* + * BTR + */ +void +BTR_EwGw(void) +{ + UINT16 *out; + UINT32 op, src, dst, res, madr; + UINT16 bit; + + PREPART_EA_REG16(op, src); + bit = BIT_MAKEBIT16(src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG16_B20(op); + dst = *out; + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + res = dst & ~bit; + *out = (UINT16)res; + } else { + CPU_FLAGL &= ~C_FLAG; + } + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + madr += BIT_OFFSET16(src); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst & ~bit; + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); + } +} + +void +BTR_EdGd(void) +{ + UINT32 *out; + UINT32 op, src, dst, res, madr; + UINT32 bit; + + PREPART_EA_REG32(op, src); + bit = BIT_MAKEBIT32(src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG32_B20(op); + dst = *out; + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + res = dst & ~bit; + *out = res; + } else { + CPU_FLAGL &= ~C_FLAG; + } + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + madr += BIT_OFFSET32(src); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst & ~bit; + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); + } +} + +void CPUCALL +BTR_EwIb(UINT32 op) +{ + UINT16 *out; + UINT32 src, dst, res, madr; + UINT16 bit; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + GET_MODRM_PCBYTE(src); + out = CPU_REG16_B20(op); + dst = *out; + bit = BIT_MAKEBIT16(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + res = dst & ~bit; + *out = (UINT16)res; + } else { + CPU_FLAGL &= ~C_FLAG; + } + } else { + CPU_WORKCLOCK(6); + madr = calc_ea_dst(op); + GET_MODRM_PCBYTE(src); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + bit = BIT_MAKEBIT16(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst & ~bit; + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); + } +} + +void CPUCALL +BTR_EdIb(UINT32 op) +{ + UINT32 *out; + UINT32 src, dst, res, madr; + UINT32 bit; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + GET_MODRM_PCBYTE(src); + out = CPU_REG32_B20(op); + dst = *out; + bit = BIT_MAKEBIT32(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + res = dst & ~bit; + *out = res; + } else { + CPU_FLAGL &= ~C_FLAG; + } + } else { + CPU_WORKCLOCK(6); + madr = calc_ea_dst(op); + GET_MODRM_PCBYTE(src); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + bit = BIT_MAKEBIT32(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst & ~bit; + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); + } +} + +/* + * BTC + */ +void +BTC_EwGw(void) +{ + UINT16 *out; + UINT32 op, src, dst, res, madr; + UINT16 bit; + + PREPART_EA_REG16(op, src); + bit = BIT_MAKEBIT16(src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG16_B20(op); + dst = *out; + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst ^ bit; + *out = (UINT16)res; + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + madr += BIT_OFFSET16(src); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst ^ bit; + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); + } +} + +void +BTC_EdGd(void) +{ + UINT32 *out; + UINT32 op, src, dst, res, madr; + UINT32 bit; + + PREPART_EA_REG32(op, src); + bit = BIT_MAKEBIT32(src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG32_B20(op); + dst = *out; + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst ^ bit; + *out = res; + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + madr += BIT_OFFSET32(src); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst ^ bit; + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); + } +} + +void CPUCALL +BTC_EwIb(UINT32 op) +{ + UINT16 *out; + UINT32 src, dst, res, madr; + UINT16 bit; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + GET_MODRM_PCBYTE(src); + out = CPU_REG16_B20(op); + dst = *out; + bit = BIT_MAKEBIT16(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst ^ bit; + *out = (UINT16)res; + } else { + CPU_WORKCLOCK(6); + madr = calc_ea_dst(op); + GET_MODRM_PCBYTE(src); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + bit = BIT_MAKEBIT16(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst ^ bit; + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); + } +} + +void CPUCALL +BTC_EdIb(UINT32 op) +{ + UINT32 *out; + UINT32 src, dst, res, madr; + UINT32 bit; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + GET_MODRM_PCBYTE(src); + out = CPU_REG32_B20(op); + dst = *out; + bit = BIT_MAKEBIT32(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst ^ bit; + *out = res; + } else { + CPU_WORKCLOCK(6); + madr = calc_ea_dst(op); + GET_MODRM_PCBYTE(src); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + bit = BIT_MAKEBIT32(src); + if (dst & bit) { + CPU_FLAGL |= C_FLAG; + } else { + CPU_FLAGL &= ~C_FLAG; + } + res = dst ^ bit; + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); + } +} + +/* + * BSF + */ +void +BSF_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + int bit; + + PREPART_REG16_EA(op, src, out, 2, 7); + if (src == 0) { + CPU_FLAGL |= Z_FLAG; + /* dest reg is undefined */ + } else { + CPU_FLAGL &= ~Z_FLAG; + for (bit = 0; bit < 15; bit++) { + if (src & (1 << bit)) + break; + } + *out = (UINT16)bit; + } +} + +void +BSF_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + int bit; + + PREPART_REG32_EA(op, src, out, 2, 7); + if (src == 0) { + CPU_FLAGL |= Z_FLAG; + /* dest reg is undefined */ + } else { + CPU_FLAGL &= ~Z_FLAG; + for (bit = 0; bit < 31; bit++) { + if (src & (1 << bit)) + break; + } + *out = (UINT32)bit; + } +} + +/* + * BSR + */ +void +BSR_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + int bit; + + PREPART_REG16_EA(op, src, out, 2, 7); + if (src == 0) { + CPU_FLAGL |= Z_FLAG; + /* dest reg is undefined */ + } else { + CPU_FLAGL &= ~Z_FLAG; + for (bit = 15; bit > 0; bit--) { + if (src & (1 << bit)) + break; + } + *out = (UINT16)bit; + } +} + +void +BSR_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + int bit; + + PREPART_REG32_EA(op, src, out, 2, 7); + if (src == 0) { + CPU_FLAGL |= Z_FLAG; + /* dest reg is undefined */ + } else { + CPU_FLAGL &= ~Z_FLAG; + for (bit = 31; bit > 0; bit--) { + if (src & (1 << bit)) + break; + } + *out = (UINT32)bit; + } +} + +/* + * SETcc + */ +void +SETO_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_O?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETNO_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_NO?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETC_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_C?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETNC_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_NC?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETZ_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_Z?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETNZ_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_NZ?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETA_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_A?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETNA_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_NA?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETS_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_S?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETNS_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_NS?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETP_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_P?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETNP_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_NP?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETL_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_L?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETNL_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_NL?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETLE_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_LE?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +void +SETNLE_Eb(void) +{ + UINT32 op, madr; + UINT8 v = CC_NLE?1:0; + + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = v; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, v); + } +} + +/* + * TEST + */ +void +TEST_EbGb(void) +{ + UINT32 op, src, tmp, madr; + + PREPART_EA_REG8(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + tmp = *(reg8_b20[op]); + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); + } + BYTE_AND(tmp, src); +} + +void +TEST_EwGw(void) +{ + UINT32 op, src, tmp, madr; + + PREPART_EA_REG16(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + tmp = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + WORD_AND(tmp, src); +} + +void +TEST_EdGd(void) +{ + UINT32 op, src, tmp, madr; + + PREPART_EA_REG32(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + tmp = *(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + DWORD_AND(tmp, src); +} + +void +TEST_ALIb(void) +{ + UINT32 src, tmp; + + CPU_WORKCLOCK(3); + tmp = CPU_AL; + GET_MODRM_PCBYTE(src); + BYTE_AND(tmp, src); +} + +void +TEST_AXIw(void) +{ + UINT32 src, tmp; + + CPU_WORKCLOCK(3); + tmp = CPU_AX; + GET_PCWORD(src); + WORD_AND(tmp, src); +} + +void +TEST_EAXId(void) +{ + UINT32 src, tmp; + + CPU_WORKCLOCK(3); + tmp = CPU_EAX; + GET_PCDWORD(src); + DWORD_AND(tmp, src); +} + +void CPUCALL +TEST_EbIb(UINT32 op) +{ + UINT32 src, tmp, madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + tmp = *(reg8_b20[op]); + } else { + CPU_WORKCLOCK(6); + madr = calc_ea_dst(op); + tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); + } + GET_PCBYTE(src); + BYTE_AND(tmp, src); +} + +void CPUCALL +TEST_EwIw(UINT32 op) +{ + UINT32 src, tmp, madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + tmp = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(6); + madr = calc_ea_dst(op); + tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + GET_PCWORD(src); + WORD_AND(tmp, src); +} + +void CPUCALL +TEST_EdId(UINT32 op) +{ + UINT32 src, tmp, madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + tmp = *(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(6); + madr = calc_ea_dst(op); + tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + GET_PCDWORD(src); + DWORD_AND(tmp, src); } \ No newline at end of file diff --git a/i386c/ia32/instructions/bit_byte.h b/i386c/ia32/instructions/bit_byte.h old mode 100755 new mode 100644 index b0b0b848..92f379ca --- a/i386c/ia32/instructions/bit_byte.h +++ b/i386c/ia32/instructions/bit_byte.h @@ -1,99 +1,99 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_BIT_BYTE_H__ -#define IA32_CPU_INSTRUCTION_BIT_BYTE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * BTx - */ -void BT_EwGw(void); -void BT_EdGd(void); -void CPUCALL BT_EwIb(UINT32); -void CPUCALL BT_EdIb(UINT32); -void BTS_EwGw(void); -void BTS_EdGd(void); -void CPUCALL BTS_EwIb(UINT32); -void CPUCALL BTS_EdIb(UINT32); -void BTR_EwGw(void); -void BTR_EdGd(void); -void CPUCALL BTR_EwIb(UINT32); -void CPUCALL BTR_EdIb(UINT32); -void BTC_EwGw(void); -void BTC_EdGd(void); -void CPUCALL BTC_EwIb(UINT32); -void CPUCALL BTC_EdIb(UINT32); - -/* - * BSx - */ -void BSF_GwEw(void); -void BSF_GdEd(void); -void BSR_GwEw(void); -void BSR_GdEd(void); - -/* - * SETcc - */ -void SETO_Eb(void); -void SETNO_Eb(void); -void SETC_Eb(void); -void SETNC_Eb(void); -void SETZ_Eb(void); -void SETNZ_Eb(void); -void SETA_Eb(void); -void SETNA_Eb(void); -void SETS_Eb(void); -void SETNS_Eb(void); -void SETP_Eb(void); -void SETNP_Eb(void); -void SETL_Eb(void); -void SETNL_Eb(void); -void SETLE_Eb(void); -void SETNLE_Eb(void); - -/* - * TEST - */ -void TEST_EbGb(void); -void TEST_EwGw(void); -void TEST_EdGd(void); -void TEST_ALIb(void); -void TEST_AXIw(void); -void TEST_EAXId(void); - -void CPUCALL TEST_EbIb(UINT32); -void CPUCALL TEST_EwIw(UINT32); -void CPUCALL TEST_EdId(UINT32); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_BIT_BYTE_H__ */ +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_BIT_BYTE_H__ +#define IA32_CPU_INSTRUCTION_BIT_BYTE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * BTx + */ +void BT_EwGw(void); +void BT_EdGd(void); +void CPUCALL BT_EwIb(UINT32); +void CPUCALL BT_EdIb(UINT32); +void BTS_EwGw(void); +void BTS_EdGd(void); +void CPUCALL BTS_EwIb(UINT32); +void CPUCALL BTS_EdIb(UINT32); +void BTR_EwGw(void); +void BTR_EdGd(void); +void CPUCALL BTR_EwIb(UINT32); +void CPUCALL BTR_EdIb(UINT32); +void BTC_EwGw(void); +void BTC_EdGd(void); +void CPUCALL BTC_EwIb(UINT32); +void CPUCALL BTC_EdIb(UINT32); + +/* + * BSx + */ +void BSF_GwEw(void); +void BSF_GdEd(void); +void BSR_GwEw(void); +void BSR_GdEd(void); + +/* + * SETcc + */ +void SETO_Eb(void); +void SETNO_Eb(void); +void SETC_Eb(void); +void SETNC_Eb(void); +void SETZ_Eb(void); +void SETNZ_Eb(void); +void SETA_Eb(void); +void SETNA_Eb(void); +void SETS_Eb(void); +void SETNS_Eb(void); +void SETP_Eb(void); +void SETNP_Eb(void); +void SETL_Eb(void); +void SETNL_Eb(void); +void SETLE_Eb(void); +void SETNLE_Eb(void); + +/* + * TEST + */ +void TEST_EbGb(void); +void TEST_EwGw(void); +void TEST_EdGd(void); +void TEST_ALIb(void); +void TEST_AXIw(void); +void TEST_EAXId(void); + +void CPUCALL TEST_EbIb(UINT32); +void CPUCALL TEST_EwIw(UINT32); +void CPUCALL TEST_EdId(UINT32); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_BIT_BYTE_H__ */ diff --git a/i386c/ia32/instructions/ctrl_trans.c b/i386c/ia32/instructions/ctrl_trans.c old mode 100755 new mode 100644 index 751a6247..9aad7cf3 --- a/i386c/ia32/instructions/ctrl_trans.c +++ b/i386c/ia32/instructions/ctrl_trans.c @@ -1,1602 +1,1602 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" -#include "ia32/ctrlxfer.h" - -#include "ctrl_trans.h" - -#if defined(ENABLE_TRAP) -#include "trap/inttrap.h" -#endif - -#ifdef SUPPORT_IA32_HAXM -#include -#endif - - -/* - * JMP - */ -void -JMP_Jb(void) -{ - - JMPSHORT(7); -} - -void -JMP_Jw(void) -{ - - JMPNEAR(7); -} - -void -JMP_Jd(void) -{ - - JMPNEAR32(7); -} - -void CPUCALL -JMP_Ew(UINT32 op) -{ - UINT32 madr; - UINT16 new_ip; - - if (op >= 0xc0) { - CPU_WORKCLOCK(7); - new_ip = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - if (new_ip > CPU_STAT_CS_LIMIT) { - EXCEPTION(GP_EXCEPTION, 0); - } - CPU_EIP = new_ip; -} - -void CPUCALL -JMP_Ed(UINT32 op) -{ - UINT32 madr; - UINT32 new_ip; - - if (op >= 0xc0) { - CPU_WORKCLOCK(7); - new_ip = *(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - if (new_ip > CPU_STAT_CS_LIMIT) { - EXCEPTION(GP_EXCEPTION, 0); - } - CPU_EIP = new_ip; -} - -void -JMP16_Ap(void) -{ - descriptor_t sd; - UINT16 new_ip; - UINT16 new_cs; - UINT16 sreg; - - CPU_WORKCLOCK(11); - GET_PCWORD(new_ip); - GET_PCWORD(new_cs); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - /* check new instrunction pointer with new code segment */ - load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - CPU_EIP = new_ip; - } else { - /* Protected mode */ - JMPfar_pm(new_cs, new_ip); - } -} - -void -JMP32_Ap(void) -{ - descriptor_t sd; - UINT32 new_ip; - UINT16 new_cs; - UINT16 sreg; - - CPU_WORKCLOCK(11); - GET_PCDWORD(new_ip); - GET_PCWORD(new_cs); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - /* check new instrunction pointer with new code segment */ - load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - CPU_EIP = new_ip; - } else { - /* Protected mode */ - JMPfar_pm(new_cs, new_ip); - } -} - -void CPUCALL -JMP16_Ep(UINT32 op) -{ - descriptor_t sd; - UINT32 madr; - UINT16 new_ip; - UINT16 new_cs; - UINT16 sreg; - - CPU_WORKCLOCK(11); - if (op < 0xc0) { - madr = calc_ea_dst(op); - new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - /* check new instrunction pointer with new code segment */ - load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - CPU_EIP = new_ip; - } else { - /* Protected mode */ - JMPfar_pm(new_cs, new_ip); - } - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -JMP32_Ep(UINT32 op) -{ - descriptor_t sd; - UINT32 madr; - UINT32 new_ip; - UINT16 new_cs; - UINT16 sreg; - - CPU_WORKCLOCK(11); - if (op < 0xc0) { - madr = calc_ea_dst(op); - new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - /* check new instrunction pointer with new code segment */ - load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - CPU_EIP = new_ip; - } else { - /* Protected mode */ - JMPfar_pm(new_cs, new_ip); - } - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -/* jo */ -void -JO_Jb(void) -{ - - if (CC_NO) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JO_Jw(void) -{ - - if (CC_NO) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JO_Jd(void) -{ - - if (CC_NO) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jno */ -void -JNO_Jb(void) -{ - - if (CC_O) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JNO_Jw(void) -{ - - if (CC_O) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JNO_Jd(void) -{ - - if (CC_O) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jc */ -void -JC_Jb(void) -{ - - if (CC_NC) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JC_Jw(void) -{ - - if (CC_NC) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JC_Jd(void) -{ - - if (CC_NC) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jnc */ -void -JNC_Jb(void) -{ - - if (CC_C) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} -void -JNC_Jw(void) -{ - - if (CC_C) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} -void -JNC_Jd(void) -{ - - if (CC_C) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jz */ -void -JZ_Jb(void) -{ - - if (CC_NZ) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JZ_Jw(void) -{ - - if (CC_NZ) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JZ_Jd(void) -{ - - if (CC_NZ) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jnz */ -void -JNZ_Jb(void) -{ - - if (CC_Z) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JNZ_Jw(void) -{ - - if (CC_Z) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JNZ_Jd(void) -{ - - if (CC_Z) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jna */ -void -JNA_Jb(void) -{ - - if (CC_A) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JNA_Jw(void) -{ - - if (CC_A) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JNA_Jd(void) -{ - - if (CC_A) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* ja */ -void -JA_Jb(void) -{ - - if (CC_NA) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JA_Jw(void) -{ - - if (CC_NA) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JA_Jd(void) -{ - - if (CC_NA) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* js */ -void -JS_Jb(void) -{ - - if (CC_NS) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JS_Jw(void) -{ - - if (CC_NS) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JS_Jd(void) -{ - - if (CC_NS) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jns */ -void -JNS_Jb(void) -{ - - if (CC_S) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JNS_Jw(void) -{ - - if (CC_S) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JNS_Jd(void) -{ - - if (CC_S) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jp */ -void -JP_Jb(void) -{ - - if (CC_NP) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JP_Jw(void) -{ - - if (CC_NP) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JP_Jd(void) -{ - - if (CC_NP) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jnp */ -void -JNP_Jb(void) -{ - - if (CC_P) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JNP_Jw(void) -{ - - if (CC_P) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JNP_Jd(void) -{ - - if (CC_P) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jl */ -void -JL_Jb(void) -{ - - if (CC_NL) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JL_Jw(void) -{ - - if (CC_NL) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JL_Jd(void) -{ - - if (CC_NL) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jnl */ -void -JNL_Jb(void) -{ - - if (CC_L) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JNL_Jw(void) -{ - - if (CC_L) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JNL_Jd(void) -{ - - if (CC_L) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jle */ -void -JLE_Jb(void) -{ - - if (CC_NLE) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JLE_Jw(void) -{ - - if (CC_NLE) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JLE_Jd(void) -{ - - if (CC_NLE) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jnle */ -void -JNLE_Jb(void) -{ - - if (CC_LE) { - JMPNOP(2, 1); - } else { - JMPSHORT(7); - } -} - -void -JNLE_Jw(void) -{ - - if (CC_LE) { - JMPNOP(2, 2); - } else { - JMPNEAR(7); - } -} - -void -JNLE_Jd(void) -{ - - if (CC_LE) { - JMPNOP(2, 4); - } else { - JMPNEAR32(7); - } -} - -/* jcxz */ -void -JeCXZ_Jb(void) -{ - - if (!CPU_INST_AS32) { - if (CPU_CX == 0) { - JMPSHORT(8); - } else { - JMPNOP(4, 1); - } - } else { - if (CPU_ECX == 0) { - JMPSHORT(8); - } else { - JMPNOP(4, 1); - } - } -} - -/* - * LOOPcc - */ -/* loopne */ -void -LOOPNE_Jb(void) -{ - UINT32 cx; - - if (!CPU_INST_AS32) { - cx = CPU_CX; - if (--cx != 0 && CC_NZ) { - JMPSHORT(8); - } else { - JMPNOP(4, 1); - } - CPU_CX--; - } else { - cx = CPU_ECX; - if (--cx != 0 && CC_NZ) { - JMPSHORT(8); - } else { - JMPNOP(4, 1); - } - CPU_ECX--; - } -} - -/* loope */ -void -LOOPE_Jb(void) -{ - UINT32 cx; - - if (!CPU_INST_AS32) { - cx = CPU_CX; - if (--cx != 0 && CC_Z) { - JMPSHORT(8); - } else { - JMPNOP(4, 1); - } - CPU_CX--; - } else { - cx = CPU_ECX; - if (--cx != 0 && CC_Z) { - JMPSHORT(8); - } else { - JMPNOP(4, 1); - } - CPU_ECX--; - } -} - -/* loop */ -void -LOOP_Jb(void) -{ - UINT32 cx; - - if (!CPU_INST_AS32) { - cx = CPU_CX; - if (--cx != 0) { - JMPSHORT(8); - } else { - JMPNOP(4, 1); - } - CPU_CX--; - } else { - cx = CPU_ECX; - if (--cx != 0) { - JMPSHORT(8); - } else { - JMPNOP(4, 1); - } - CPU_ECX--; - } -} - -/* - * CALL - */ -void -CALL_Aw(void) -{ - UINT16 new_ip; - SINT16 dest; - - CPU_WORKCLOCK(7); - CPU_SET_PREV_ESP(); - GET_PCWORDS(dest); - new_ip = CPU_EIP + dest; - if (new_ip > CPU_STAT_CS_LIMIT) { - EXCEPTION(GP_EXCEPTION, 0); - } - PUSH0_16(CPU_IP); - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); -} - -void -CALL_Ad(void) -{ - UINT32 new_ip; - UINT32 dest; - - CPU_WORKCLOCK(7); - CPU_SET_PREV_ESP(); - GET_PCDWORD(dest); - new_ip = CPU_EIP + dest; - if (new_ip > CPU_STAT_CS_LIMIT) { - EXCEPTION(GP_EXCEPTION, 0); - } - PUSH0_32(CPU_EIP); - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); -} - -void CPUCALL -CALL_Ew(UINT32 op) -{ - UINT32 madr; - UINT16 new_ip; - - CPU_SET_PREV_ESP(); - if (op >= 0xc0) { - CPU_WORKCLOCK(7); - new_ip = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - if (new_ip > CPU_STAT_CS_LIMIT) { - EXCEPTION(GP_EXCEPTION, 0); - } - PUSH0_16(CPU_IP); - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); -} - -void CPUCALL -CALL_Ed(UINT32 op) -{ - UINT32 madr; - UINT32 new_ip; - - CPU_SET_PREV_ESP(); - if (op >= 0xc0) { - CPU_WORKCLOCK(7); - new_ip = *(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - if (new_ip > CPU_STAT_CS_LIMIT) { - EXCEPTION(GP_EXCEPTION, 0); - } - PUSH0_32(CPU_EIP); - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); -} - -void -CALL16_Ap(void) -{ - descriptor_t sd; - UINT16 new_ip; - UINT16 new_cs; - UINT16 sreg; - - CPU_WORKCLOCK(13); - GET_PCWORD(new_ip); - GET_PCWORD(new_cs); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - CPU_SET_PREV_ESP(); - load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - - PUSH0_16(CPU_CS); - PUSH0_16(CPU_IP); - - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); - } else { - /* Protected mode */ - CALLfar_pm(new_cs, new_ip); - } -} - -void -CALL32_Ap(void) -{ - descriptor_t sd; - UINT32 new_ip; - UINT16 new_cs; - UINT16 sreg; - - CPU_WORKCLOCK(13); - GET_PCDWORD(new_ip); - GET_PCWORD(new_cs); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - CPU_SET_PREV_ESP(); - load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - - PUSH0_32(CPU_CS); - PUSH0_32(CPU_EIP); - - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); - } else { - /* Protected mode */ - CALLfar_pm(new_cs, new_ip); - } -} - -void CPUCALL -CALL16_Ep(UINT32 op) -{ - descriptor_t sd; - UINT32 madr; - UINT16 new_ip; - UINT16 new_cs; - UINT16 sreg; - - CPU_WORKCLOCK(16); - if (op < 0xc0) { - madr = calc_ea_dst(op); - new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - CPU_SET_PREV_ESP(); - load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - - PUSH0_16(CPU_CS); - PUSH0_16(CPU_IP); - - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); - } else { - /* Protected mode */ - CALLfar_pm(new_cs, new_ip); - } - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -CALL32_Ep(UINT32 op) -{ - descriptor_t sd; - UINT32 madr; - UINT32 new_ip; - UINT16 new_cs; - UINT16 sreg; - - CPU_WORKCLOCK(16); - if (op < 0xc0) { - madr = calc_ea_dst(op); - new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - CPU_SET_PREV_ESP(); - load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - - PUSH0_32(CPU_CS); - PUSH0_32(CPU_EIP); - - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); - } else { - /* Protected mode */ - CALLfar_pm(new_cs, new_ip); - } - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -/* - * RET - */ -void -RETnear16(void) -{ - UINT16 new_ip; - - CPU_WORKCLOCK(11); - CPU_SET_PREV_ESP(); - POP0_16(new_ip); - if (new_ip > CPU_STAT_CS_LIMIT) { - EXCEPTION(GP_EXCEPTION, 0); - } - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); -} - -void -RETnear32(void) -{ - UINT32 new_ip; - - CPU_WORKCLOCK(11); - CPU_SET_PREV_ESP(); - POP0_32(new_ip); - if (new_ip > CPU_STAT_CS_LIMIT) { - EXCEPTION(GP_EXCEPTION, 0); - } - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); -} - -void -RETnear16_Iw(void) -{ - UINT16 new_ip; - UINT16 size; - - CPU_WORKCLOCK(11); - CPU_SET_PREV_ESP(); - GET_PCWORD(size); - POP0_16(new_ip); - if (new_ip > CPU_STAT_CS_LIMIT) { - EXCEPTION(GP_EXCEPTION, 0); - } - CPU_EIP = new_ip; - if (!CPU_STAT_SS32) { - CPU_SP += size; - } else { - CPU_ESP += size; - } - CPU_CLEAR_PREV_ESP(); -} - -void -RETnear32_Iw(void) -{ - UINT32 new_ip; - UINT16 size; - - CPU_WORKCLOCK(11); - CPU_SET_PREV_ESP(); - GET_PCWORD(size); - POP0_32(new_ip); - if (new_ip > CPU_STAT_CS_LIMIT) { - EXCEPTION(GP_EXCEPTION, 0); - } - CPU_EIP = new_ip; - if (!CPU_STAT_SS32) { - CPU_SP += size; - } else { - CPU_ESP += size; - } - CPU_CLEAR_PREV_ESP(); -} - -void -RETfar16(void) -{ - descriptor_t sd; - UINT16 new_ip; - UINT16 new_cs; - UINT16 sreg; - - CPU_WORKCLOCK(15); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - CPU_SET_PREV_ESP(); - POP0_16(new_ip); - POP0_16(new_cs); - - /* check new instrunction pointer with new code segment */ - load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); - } else { - /* Protected mode */ - RETfar_pm(0); - } -} - -void -RETfar32(void) -{ - descriptor_t sd; - UINT32 new_ip; - UINT32 new_cs; - UINT16 sreg; - - CPU_WORKCLOCK(15); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - CPU_SET_PREV_ESP(); - POP0_32(new_ip); - POP0_32(new_cs); - - /* check new instrunction pointer with new code segment */ - load_segreg(CPU_CS_INDEX, (UINT16)new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - - LOAD_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); - CPU_EIP = new_ip; - CPU_CLEAR_PREV_ESP(); - } else { - /* Protected mode */ - RETfar_pm(0); - } -} - -void -RETfar16_Iw(void) -{ - descriptor_t sd; - UINT16 new_ip; - UINT16 new_cs; - UINT16 sreg; - UINT16 size; - - CPU_WORKCLOCK(15); - GET_PCWORD(size); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - CPU_SET_PREV_ESP(); - POP0_16(new_ip); - POP0_16(new_cs); - - /* check new instrunction pointer with new code segment */ - load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - - LOAD_SEGREG(CPU_CS_INDEX, new_cs); - CPU_EIP = new_ip; - if (!CPU_STAT_SS32) { - CPU_SP += size; - } else { - CPU_ESP += size; - } - CPU_CLEAR_PREV_ESP(); - } else { - /* Protected mode */ - RETfar_pm(size); - } -} - -void -RETfar32_Iw(void) -{ - descriptor_t sd; - UINT32 new_ip; - UINT32 new_cs; - UINT16 sreg; - UINT16 size; - - CPU_WORKCLOCK(15); - GET_PCWORD(size); - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* Real mode or VM86 mode */ - CPU_SET_PREV_ESP(); - POP0_32(new_ip); - POP0_32(new_cs); - - /* check new instrunction pointer with new code segment */ - load_segreg(CPU_CS_INDEX, (UINT16)new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - - LOAD_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); - CPU_EIP = new_ip; - if (!CPU_STAT_SS32) { - CPU_SP += size; - } else { - CPU_ESP += size; - } - CPU_CLEAR_PREV_ESP(); - } else { - /* Protected mode */ - RETfar_pm(size); - } -} - -void -IRET(void) -{ - descriptor_t sd; - UINT32 new_ip; - UINT32 new_flags; - UINT32 new_cs; - UINT32 mask; - UINT16 sreg; - - CPU_WORKCLOCK(22); - if (!CPU_STAT_PM) { - /* Real mode */ - CPU_SET_PREV_ESP(); - mask = I_FLAG|IOPL_FLAG; - if (!CPU_INST_OP32) { - POP0_16(new_ip); - POP0_16(new_cs); - POP0_16(new_flags); - } else { - POP0_32(new_ip); - POP0_32(new_cs); - POP0_32(new_flags); - mask |= RF_FLAG; - } - - /* check new instrunction pointer with new code segment */ - load_segreg(CPU_CS_INDEX, (UINT16)new_cs, &sreg, &sd, GP_EXCEPTION); - if (new_ip > sd.u.seg.limit) { - EXCEPTION(GP_EXCEPTION, 0); - } - - LOAD_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); - CPU_EIP = new_ip; - - set_eflags(new_flags, mask); - CPU_CLEAR_PREV_ESP(); - } else { - /* Protected mode */ - IRET_pm(); - } - IRQCHECKTERM(); -} - -/* - * INT - */ -void -INT1(void) -{ - - CPU_WORKCLOCK(33); - INTERRUPT(1, INTR_TYPE_SOFTINTR); -} - -void -INT3(void) -{ -#if defined(SUPPORT_IA32_HAXM) -#if defined(USE_CUSTOM_HOOKINST) - if(bioshookinfo.hookinst == 0xCC){ - if (!CPU_STAT_PM || CPU_STAT_VM86) { - UINT32 adrs; - adrs = CPU_PREV_EIP + (CPU_CS << 4); - if ((adrs >= 0xf8000) && (adrs < 0x100000)) { - ia32_bioscall(); - return; - } - } - } -#endif -#endif - - CPU_WORKCLOCK(33); - INTERRUPT(3, INTR_TYPE_SOFTINTR); -} - -void -INTO(void) -{ - - if (!CPU_OV) { - CPU_WORKCLOCK(3); - return; - } - CPU_WORKCLOCK(35); - INTERRUPT(4, INTR_TYPE_SOFTINTR); -} - -void -INT_Ib(void) -{ - UINT8 vect; - - CPU_WORKCLOCK(37); - if (!CPU_STAT_PM || !CPU_STAT_VM86 || (CPU_STAT_IOPL == CPU_IOPL3)) { - GET_MODRM_PCBYTE(vect); -#if defined(ENABLE_TRAP) - softinttrap(CPU_CS, CPU_EIP - 2, vect); -#endif - INTERRUPT(vect, INTR_TYPE_SOFTINTR); - return; - } - VERBOSE(("INT_Ib: VM86 && IOPL < 3 && INTn")); -#if defined(USE_VME) - EXCEPTION(GP_EXCEPTION, 0); // XXX: 一応動いてるけど実装しないとまずい・・・? -#else - EXCEPTION(GP_EXCEPTION, 0); -#endif -} - -void -BOUND_GwMa(void) -{ - UINT32 op, madr; - UINT16 reg; - - CPU_WORKCLOCK(13); - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - reg = *(CPU_REG16_B53(op)); - madr = calc_ea_dst(op); - if (reg >= cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr) && - reg <= cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2)) { - return; - } - EXCEPTION(BR_EXCEPTION, 0); - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -BOUND_GdMa(void) -{ - UINT32 op, madr; - UINT32 reg; - - CPU_WORKCLOCK(13); - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - reg = *(CPU_REG32_B53(op)); - madr = calc_ea_dst(op); - if (reg >= cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr) && - reg <= cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 4)) { - return; - } - EXCEPTION(BR_EXCEPTION, 0); - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -/* - * STACK - */ -void -ENTER16_IwIb(void) -{ - UINT32 sp, bp; - UINT32 val; - UINT16 dimsize; - UINT16 new_bp; - UINT8 level; - - GET_PCWORD(dimsize); - GET_PCBYTE(level); - level &= 0x1f; - - CPU_SET_PREV_ESP(); - PUSH0_16(CPU_BP); - if (level == 0) { /* enter level=0 */ - CPU_WORKCLOCK(11); - CPU_BP = CPU_SP; - if (!CPU_STAT_SS32) { - CPU_SP -= dimsize; - } else { - CPU_ESP -= dimsize; - } - } else { - --level; - if (level == 0) { /* enter level=1 */ - CPU_WORKCLOCK(15); - sp = CPU_SP; - PUSH0_16(sp); - CPU_BP = (UINT16)sp; - if (!CPU_STAT_SS32) { - CPU_SP -= dimsize; - } else { - CPU_ESP -= dimsize; - } - } else { /* enter level=2-31 */ - CPU_WORKCLOCK(12 + level * 4); - if (!CPU_STAT_SS32) { - bp = CPU_BP; - new_bp = CPU_SP; - while (level--) { - bp -= 2; - CPU_SP -= 2; - val = cpu_vmemoryread_w(CPU_SS_INDEX, bp); - cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_SP, (UINT16)val); - } - REGPUSH0(new_bp); - CPU_BP = new_bp; - CPU_SP -= dimsize; - } else { - bp = CPU_EBP; - new_bp = CPU_SP; - while (level--) { - bp -= 2; - CPU_ESP -= 2; - val = cpu_vmemoryread_w(CPU_SS_INDEX, bp); - cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_ESP, (UINT16)val); - } - REGPUSH0_16_32(new_bp); - CPU_BP = new_bp; - CPU_ESP -= dimsize; - } - } - } - CPU_CLEAR_PREV_ESP(); -} - -void -ENTER32_IwIb(void) -{ - UINT32 sp, bp; - UINT32 new_bp; - UINT32 val; - UINT16 dimsize; - UINT8 level; - - GET_PCWORD(dimsize); - GET_PCBYTE(level); - level &= 0x1f; - - CPU_SET_PREV_ESP(); - PUSH0_32(CPU_EBP); - if (level == 0) { /* enter level=0 */ - CPU_WORKCLOCK(11); - CPU_EBP = CPU_ESP; - if (!CPU_STAT_SS32) { - CPU_SP -= dimsize; - } else { - CPU_ESP -= dimsize; - } - } else { - --level; - if (level == 0) { /* enter level=1 */ - CPU_WORKCLOCK(15); - sp = CPU_ESP; - PUSH0_32(sp); - CPU_EBP = sp; - if (CPU_STAT_SS32) { - CPU_ESP -= dimsize; - } else { - CPU_SP -= dimsize; - } - } else { /* enter level=2-31 */ - CPU_WORKCLOCK(12 + level * 4); - if (CPU_STAT_SS32) { - bp = CPU_EBP; - new_bp = CPU_ESP; - while (level--) { - bp -= 4; - CPU_ESP -= 4; - val = cpu_vmemoryread_d(CPU_SS_INDEX, bp); - cpu_vmemorywrite_d(CPU_SS_INDEX, CPU_ESP, val); - } - REGPUSH0_32(new_bp); - CPU_EBP = new_bp; - CPU_ESP -= dimsize; - } else { - bp = CPU_BP; - new_bp = CPU_ESP; - while (level--) { - bp -= 4; - CPU_SP -= 4; - val = cpu_vmemoryread_d(CPU_SS_INDEX, bp); - cpu_vmemorywrite_d(CPU_SS_INDEX, CPU_SP, val); - } - REGPUSH0_32_16(new_bp); - CPU_EBP = new_bp; - CPU_SP -= dimsize; - } - } - } - CPU_CLEAR_PREV_ESP(); -} - -void -LEAVE(void) -{ - - CPU_WORKCLOCK(4); - - CPU_SET_PREV_ESP(); - if (!CPU_STAT_SS32) { - CPU_SP = CPU_BP; - } else { - CPU_ESP = CPU_EBP; - } - if (!CPU_INST_OP32) { - POP0_16(CPU_BP); - } else { - POP0_32(CPU_EBP); - } - CPU_CLEAR_PREV_ESP(); -} +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" +#include "ia32/ctrlxfer.h" + +#include "ctrl_trans.h" + +#if defined(ENABLE_TRAP) +#include "trap/inttrap.h" +#endif + +#ifdef SUPPORT_IA32_HAXM +#include +#endif + + +/* + * JMP + */ +void +JMP_Jb(void) +{ + + JMPSHORT(7); +} + +void +JMP_Jw(void) +{ + + JMPNEAR(7); +} + +void +JMP_Jd(void) +{ + + JMPNEAR32(7); +} + +void CPUCALL +JMP_Ew(UINT32 op) +{ + UINT32 madr; + UINT16 new_ip; + + if (op >= 0xc0) { + CPU_WORKCLOCK(7); + new_ip = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; +} + +void CPUCALL +JMP_Ed(UINT32 op) +{ + UINT32 madr; + UINT32 new_ip; + + if (op >= 0xc0) { + CPU_WORKCLOCK(7); + new_ip = *(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; +} + +void +JMP16_Ap(void) +{ + descriptor_t sd; + UINT16 new_ip; + UINT16 new_cs; + UINT16 sreg; + + CPU_WORKCLOCK(11); + GET_PCWORD(new_ip); + GET_PCWORD(new_cs); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + } else { + /* Protected mode */ + JMPfar_pm(new_cs, new_ip); + } +} + +void +JMP32_Ap(void) +{ + descriptor_t sd; + UINT32 new_ip; + UINT16 new_cs; + UINT16 sreg; + + CPU_WORKCLOCK(11); + GET_PCDWORD(new_ip); + GET_PCWORD(new_cs); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + } else { + /* Protected mode */ + JMPfar_pm(new_cs, new_ip); + } +} + +void CPUCALL +JMP16_Ep(UINT32 op) +{ + descriptor_t sd; + UINT32 madr; + UINT16 new_ip; + UINT16 new_cs; + UINT16 sreg; + + CPU_WORKCLOCK(11); + if (op < 0xc0) { + madr = calc_ea_dst(op); + new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + } else { + /* Protected mode */ + JMPfar_pm(new_cs, new_ip); + } + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +JMP32_Ep(UINT32 op) +{ + descriptor_t sd; + UINT32 madr; + UINT32 new_ip; + UINT16 new_cs; + UINT16 sreg; + + CPU_WORKCLOCK(11); + if (op < 0xc0) { + madr = calc_ea_dst(op); + new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + } else { + /* Protected mode */ + JMPfar_pm(new_cs, new_ip); + } + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +/* jo */ +void +JO_Jb(void) +{ + + if (CC_NO) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JO_Jw(void) +{ + + if (CC_NO) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JO_Jd(void) +{ + + if (CC_NO) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jno */ +void +JNO_Jb(void) +{ + + if (CC_O) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JNO_Jw(void) +{ + + if (CC_O) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JNO_Jd(void) +{ + + if (CC_O) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jc */ +void +JC_Jb(void) +{ + + if (CC_NC) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JC_Jw(void) +{ + + if (CC_NC) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JC_Jd(void) +{ + + if (CC_NC) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jnc */ +void +JNC_Jb(void) +{ + + if (CC_C) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} +void +JNC_Jw(void) +{ + + if (CC_C) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} +void +JNC_Jd(void) +{ + + if (CC_C) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jz */ +void +JZ_Jb(void) +{ + + if (CC_NZ) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JZ_Jw(void) +{ + + if (CC_NZ) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JZ_Jd(void) +{ + + if (CC_NZ) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jnz */ +void +JNZ_Jb(void) +{ + + if (CC_Z) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JNZ_Jw(void) +{ + + if (CC_Z) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JNZ_Jd(void) +{ + + if (CC_Z) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jna */ +void +JNA_Jb(void) +{ + + if (CC_A) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JNA_Jw(void) +{ + + if (CC_A) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JNA_Jd(void) +{ + + if (CC_A) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* ja */ +void +JA_Jb(void) +{ + + if (CC_NA) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JA_Jw(void) +{ + + if (CC_NA) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JA_Jd(void) +{ + + if (CC_NA) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* js */ +void +JS_Jb(void) +{ + + if (CC_NS) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JS_Jw(void) +{ + + if (CC_NS) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JS_Jd(void) +{ + + if (CC_NS) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jns */ +void +JNS_Jb(void) +{ + + if (CC_S) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JNS_Jw(void) +{ + + if (CC_S) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JNS_Jd(void) +{ + + if (CC_S) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jp */ +void +JP_Jb(void) +{ + + if (CC_NP) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JP_Jw(void) +{ + + if (CC_NP) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JP_Jd(void) +{ + + if (CC_NP) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jnp */ +void +JNP_Jb(void) +{ + + if (CC_P) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JNP_Jw(void) +{ + + if (CC_P) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JNP_Jd(void) +{ + + if (CC_P) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jl */ +void +JL_Jb(void) +{ + + if (CC_NL) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JL_Jw(void) +{ + + if (CC_NL) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JL_Jd(void) +{ + + if (CC_NL) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jnl */ +void +JNL_Jb(void) +{ + + if (CC_L) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JNL_Jw(void) +{ + + if (CC_L) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JNL_Jd(void) +{ + + if (CC_L) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jle */ +void +JLE_Jb(void) +{ + + if (CC_NLE) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JLE_Jw(void) +{ + + if (CC_NLE) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JLE_Jd(void) +{ + + if (CC_NLE) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jnle */ +void +JNLE_Jb(void) +{ + + if (CC_LE) { + JMPNOP(2, 1); + } else { + JMPSHORT(7); + } +} + +void +JNLE_Jw(void) +{ + + if (CC_LE) { + JMPNOP(2, 2); + } else { + JMPNEAR(7); + } +} + +void +JNLE_Jd(void) +{ + + if (CC_LE) { + JMPNOP(2, 4); + } else { + JMPNEAR32(7); + } +} + +/* jcxz */ +void +JeCXZ_Jb(void) +{ + + if (!CPU_INST_AS32) { + if (CPU_CX == 0) { + JMPSHORT(8); + } else { + JMPNOP(4, 1); + } + } else { + if (CPU_ECX == 0) { + JMPSHORT(8); + } else { + JMPNOP(4, 1); + } + } +} + +/* + * LOOPcc + */ +/* loopne */ +void +LOOPNE_Jb(void) +{ + UINT32 cx; + + if (!CPU_INST_AS32) { + cx = CPU_CX; + if (--cx != 0 && CC_NZ) { + JMPSHORT(8); + } else { + JMPNOP(4, 1); + } + CPU_CX--; + } else { + cx = CPU_ECX; + if (--cx != 0 && CC_NZ) { + JMPSHORT(8); + } else { + JMPNOP(4, 1); + } + CPU_ECX--; + } +} + +/* loope */ +void +LOOPE_Jb(void) +{ + UINT32 cx; + + if (!CPU_INST_AS32) { + cx = CPU_CX; + if (--cx != 0 && CC_Z) { + JMPSHORT(8); + } else { + JMPNOP(4, 1); + } + CPU_CX--; + } else { + cx = CPU_ECX; + if (--cx != 0 && CC_Z) { + JMPSHORT(8); + } else { + JMPNOP(4, 1); + } + CPU_ECX--; + } +} + +/* loop */ +void +LOOP_Jb(void) +{ + UINT32 cx; + + if (!CPU_INST_AS32) { + cx = CPU_CX; + if (--cx != 0) { + JMPSHORT(8); + } else { + JMPNOP(4, 1); + } + CPU_CX--; + } else { + cx = CPU_ECX; + if (--cx != 0) { + JMPSHORT(8); + } else { + JMPNOP(4, 1); + } + CPU_ECX--; + } +} + +/* + * CALL + */ +void +CALL_Aw(void) +{ + UINT16 new_ip; + SINT16 dest; + + CPU_WORKCLOCK(7); + CPU_SET_PREV_ESP(); + GET_PCWORDS(dest); + new_ip = CPU_EIP + dest; + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + PUSH0_16(CPU_IP); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); +} + +void +CALL_Ad(void) +{ + UINT32 new_ip; + UINT32 dest; + + CPU_WORKCLOCK(7); + CPU_SET_PREV_ESP(); + GET_PCDWORD(dest); + new_ip = CPU_EIP + dest; + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + PUSH0_32(CPU_EIP); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); +} + +void CPUCALL +CALL_Ew(UINT32 op) +{ + UINT32 madr; + UINT16 new_ip; + + CPU_SET_PREV_ESP(); + if (op >= 0xc0) { + CPU_WORKCLOCK(7); + new_ip = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + PUSH0_16(CPU_IP); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); +} + +void CPUCALL +CALL_Ed(UINT32 op) +{ + UINT32 madr; + UINT32 new_ip; + + CPU_SET_PREV_ESP(); + if (op >= 0xc0) { + CPU_WORKCLOCK(7); + new_ip = *(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + PUSH0_32(CPU_EIP); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); +} + +void +CALL16_Ap(void) +{ + descriptor_t sd; + UINT16 new_ip; + UINT16 new_cs; + UINT16 sreg; + + CPU_WORKCLOCK(13); + GET_PCWORD(new_ip); + GET_PCWORD(new_cs); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + + PUSH0_16(CPU_CS); + PUSH0_16(CPU_IP); + + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); + } else { + /* Protected mode */ + CALLfar_pm(new_cs, new_ip); + } +} + +void +CALL32_Ap(void) +{ + descriptor_t sd; + UINT32 new_ip; + UINT16 new_cs; + UINT16 sreg; + + CPU_WORKCLOCK(13); + GET_PCDWORD(new_ip); + GET_PCWORD(new_cs); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + + PUSH0_32(CPU_CS); + PUSH0_32(CPU_EIP); + + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); + } else { + /* Protected mode */ + CALLfar_pm(new_cs, new_ip); + } +} + +void CPUCALL +CALL16_Ep(UINT32 op) +{ + descriptor_t sd; + UINT32 madr; + UINT16 new_ip; + UINT16 new_cs; + UINT16 sreg; + + CPU_WORKCLOCK(16); + if (op < 0xc0) { + madr = calc_ea_dst(op); + new_ip = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + + PUSH0_16(CPU_CS); + PUSH0_16(CPU_IP); + + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); + } else { + /* Protected mode */ + CALLfar_pm(new_cs, new_ip); + } + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +CALL32_Ep(UINT32 op) +{ + descriptor_t sd; + UINT32 madr; + UINT32 new_ip; + UINT16 new_cs; + UINT16 sreg; + + CPU_WORKCLOCK(16); + if (op < 0xc0) { + madr = calc_ea_dst(op); + new_ip = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + new_cs = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + + PUSH0_32(CPU_CS); + PUSH0_32(CPU_EIP); + + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); + } else { + /* Protected mode */ + CALLfar_pm(new_cs, new_ip); + } + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +/* + * RET + */ +void +RETnear16(void) +{ + UINT16 new_ip; + + CPU_WORKCLOCK(11); + CPU_SET_PREV_ESP(); + POP0_16(new_ip); + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); +} + +void +RETnear32(void) +{ + UINT32 new_ip; + + CPU_WORKCLOCK(11); + CPU_SET_PREV_ESP(); + POP0_32(new_ip); + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); +} + +void +RETnear16_Iw(void) +{ + UINT16 new_ip; + UINT16 size; + + CPU_WORKCLOCK(11); + CPU_SET_PREV_ESP(); + GET_PCWORD(size); + POP0_16(new_ip); + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; + if (!CPU_STAT_SS32) { + CPU_SP += size; + } else { + CPU_ESP += size; + } + CPU_CLEAR_PREV_ESP(); +} + +void +RETnear32_Iw(void) +{ + UINT32 new_ip; + UINT16 size; + + CPU_WORKCLOCK(11); + CPU_SET_PREV_ESP(); + GET_PCWORD(size); + POP0_32(new_ip); + if (new_ip > CPU_STAT_CS_LIMIT) { + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_EIP = new_ip; + if (!CPU_STAT_SS32) { + CPU_SP += size; + } else { + CPU_ESP += size; + } + CPU_CLEAR_PREV_ESP(); +} + +void +RETfar16(void) +{ + descriptor_t sd; + UINT16 new_ip; + UINT16 new_cs; + UINT16 sreg; + + CPU_WORKCLOCK(15); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); + POP0_16(new_ip); + POP0_16(new_cs); + + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); + } else { + /* Protected mode */ + RETfar_pm(0); + } +} + +void +RETfar32(void) +{ + descriptor_t sd; + UINT32 new_ip; + UINT32 new_cs; + UINT16 sreg; + + CPU_WORKCLOCK(15); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); + POP0_32(new_ip); + POP0_32(new_cs); + + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, (UINT16)new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + + LOAD_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); + CPU_EIP = new_ip; + CPU_CLEAR_PREV_ESP(); + } else { + /* Protected mode */ + RETfar_pm(0); + } +} + +void +RETfar16_Iw(void) +{ + descriptor_t sd; + UINT16 new_ip; + UINT16 new_cs; + UINT16 sreg; + UINT16 size; + + CPU_WORKCLOCK(15); + GET_PCWORD(size); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); + POP0_16(new_ip); + POP0_16(new_cs); + + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + + LOAD_SEGREG(CPU_CS_INDEX, new_cs); + CPU_EIP = new_ip; + if (!CPU_STAT_SS32) { + CPU_SP += size; + } else { + CPU_ESP += size; + } + CPU_CLEAR_PREV_ESP(); + } else { + /* Protected mode */ + RETfar_pm(size); + } +} + +void +RETfar32_Iw(void) +{ + descriptor_t sd; + UINT32 new_ip; + UINT32 new_cs; + UINT16 sreg; + UINT16 size; + + CPU_WORKCLOCK(15); + GET_PCWORD(size); + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* Real mode or VM86 mode */ + CPU_SET_PREV_ESP(); + POP0_32(new_ip); + POP0_32(new_cs); + + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, (UINT16)new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + + LOAD_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); + CPU_EIP = new_ip; + if (!CPU_STAT_SS32) { + CPU_SP += size; + } else { + CPU_ESP += size; + } + CPU_CLEAR_PREV_ESP(); + } else { + /* Protected mode */ + RETfar_pm(size); + } +} + +void +IRET(void) +{ + descriptor_t sd; + UINT32 new_ip; + UINT32 new_flags; + UINT32 new_cs; + UINT32 mask; + UINT16 sreg; + + CPU_WORKCLOCK(22); + if (!CPU_STAT_PM) { + /* Real mode */ + CPU_SET_PREV_ESP(); + mask = I_FLAG|IOPL_FLAG; + if (!CPU_INST_OP32) { + POP0_16(new_ip); + POP0_16(new_cs); + POP0_16(new_flags); + } else { + POP0_32(new_ip); + POP0_32(new_cs); + POP0_32(new_flags); + mask |= RF_FLAG; + } + + /* check new instrunction pointer with new code segment */ + load_segreg(CPU_CS_INDEX, (UINT16)new_cs, &sreg, &sd, GP_EXCEPTION); + if (new_ip > sd.u.seg.limit) { + EXCEPTION(GP_EXCEPTION, 0); + } + + LOAD_SEGREG(CPU_CS_INDEX, (UINT16)new_cs); + CPU_EIP = new_ip; + + set_eflags(new_flags, mask); + CPU_CLEAR_PREV_ESP(); + } else { + /* Protected mode */ + IRET_pm(); + } + IRQCHECKTERM(); +} + +/* + * INT + */ +void +INT1(void) +{ + + CPU_WORKCLOCK(33); + INTERRUPT(1, INTR_TYPE_SOFTINTR); +} + +void +INT3(void) +{ +#if defined(SUPPORT_IA32_HAXM) +#if defined(USE_CUSTOM_HOOKINST) + if(bioshookinfo.hookinst == 0xCC){ + if (!CPU_STAT_PM || CPU_STAT_VM86) { + UINT32 adrs; + adrs = CPU_PREV_EIP + (CPU_CS << 4); + if ((adrs >= 0xf8000) && (adrs < 0x100000)) { + ia32_bioscall(); + return; + } + } + } +#endif +#endif + + CPU_WORKCLOCK(33); + INTERRUPT(3, INTR_TYPE_SOFTINTR); +} + +void +INTO(void) +{ + + if (!CPU_OV) { + CPU_WORKCLOCK(3); + return; + } + CPU_WORKCLOCK(35); + INTERRUPT(4, INTR_TYPE_SOFTINTR); +} + +void +INT_Ib(void) +{ + UINT8 vect; + + CPU_WORKCLOCK(37); + if (!CPU_STAT_PM || !CPU_STAT_VM86 || (CPU_STAT_IOPL == CPU_IOPL3)) { + GET_MODRM_PCBYTE(vect); +#if defined(ENABLE_TRAP) + softinttrap(CPU_CS, CPU_EIP - 2, vect); +#endif + INTERRUPT(vect, INTR_TYPE_SOFTINTR); + return; + } + VERBOSE(("INT_Ib: VM86 && IOPL < 3 && INTn")); +#if defined(USE_VME) + EXCEPTION(GP_EXCEPTION, 0); // XXX: 一応動いてるけど実装しないとまずい・・・? +#else + EXCEPTION(GP_EXCEPTION, 0); +#endif +} + +void +BOUND_GwMa(void) +{ + UINT32 op, madr; + UINT16 reg; + + CPU_WORKCLOCK(13); + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + reg = *(CPU_REG16_B53(op)); + madr = calc_ea_dst(op); + if (reg >= cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr) && + reg <= cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2)) { + return; + } + EXCEPTION(BR_EXCEPTION, 0); + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +BOUND_GdMa(void) +{ + UINT32 op, madr; + UINT32 reg; + + CPU_WORKCLOCK(13); + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + reg = *(CPU_REG32_B53(op)); + madr = calc_ea_dst(op); + if (reg >= cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr) && + reg <= cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 4)) { + return; + } + EXCEPTION(BR_EXCEPTION, 0); + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +/* + * STACK + */ +void +ENTER16_IwIb(void) +{ + UINT32 sp, bp; + UINT32 val; + UINT16 dimsize; + UINT16 new_bp; + UINT8 level; + + GET_PCWORD(dimsize); + GET_PCBYTE(level); + level &= 0x1f; + + CPU_SET_PREV_ESP(); + PUSH0_16(CPU_BP); + if (level == 0) { /* enter level=0 */ + CPU_WORKCLOCK(11); + CPU_BP = CPU_SP; + if (!CPU_STAT_SS32) { + CPU_SP -= dimsize; + } else { + CPU_ESP -= dimsize; + } + } else { + --level; + if (level == 0) { /* enter level=1 */ + CPU_WORKCLOCK(15); + sp = CPU_SP; + PUSH0_16(sp); + CPU_BP = (UINT16)sp; + if (!CPU_STAT_SS32) { + CPU_SP -= dimsize; + } else { + CPU_ESP -= dimsize; + } + } else { /* enter level=2-31 */ + CPU_WORKCLOCK(12 + level * 4); + if (!CPU_STAT_SS32) { + bp = CPU_BP; + new_bp = CPU_SP; + while (level--) { + bp -= 2; + CPU_SP -= 2; + val = cpu_vmemoryread_w(CPU_SS_INDEX, bp); + cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_SP, (UINT16)val); + } + REGPUSH0(new_bp); + CPU_BP = new_bp; + CPU_SP -= dimsize; + } else { + bp = CPU_EBP; + new_bp = CPU_SP; + while (level--) { + bp -= 2; + CPU_ESP -= 2; + val = cpu_vmemoryread_w(CPU_SS_INDEX, bp); + cpu_vmemorywrite_w(CPU_SS_INDEX, CPU_ESP, (UINT16)val); + } + REGPUSH0_16_32(new_bp); + CPU_BP = new_bp; + CPU_ESP -= dimsize; + } + } + } + CPU_CLEAR_PREV_ESP(); +} + +void +ENTER32_IwIb(void) +{ + UINT32 sp, bp; + UINT32 new_bp; + UINT32 val; + UINT16 dimsize; + UINT8 level; + + GET_PCWORD(dimsize); + GET_PCBYTE(level); + level &= 0x1f; + + CPU_SET_PREV_ESP(); + PUSH0_32(CPU_EBP); + if (level == 0) { /* enter level=0 */ + CPU_WORKCLOCK(11); + CPU_EBP = CPU_ESP; + if (!CPU_STAT_SS32) { + CPU_SP -= dimsize; + } else { + CPU_ESP -= dimsize; + } + } else { + --level; + if (level == 0) { /* enter level=1 */ + CPU_WORKCLOCK(15); + sp = CPU_ESP; + PUSH0_32(sp); + CPU_EBP = sp; + if (CPU_STAT_SS32) { + CPU_ESP -= dimsize; + } else { + CPU_SP -= dimsize; + } + } else { /* enter level=2-31 */ + CPU_WORKCLOCK(12 + level * 4); + if (CPU_STAT_SS32) { + bp = CPU_EBP; + new_bp = CPU_ESP; + while (level--) { + bp -= 4; + CPU_ESP -= 4; + val = cpu_vmemoryread_d(CPU_SS_INDEX, bp); + cpu_vmemorywrite_d(CPU_SS_INDEX, CPU_ESP, val); + } + REGPUSH0_32(new_bp); + CPU_EBP = new_bp; + CPU_ESP -= dimsize; + } else { + bp = CPU_BP; + new_bp = CPU_ESP; + while (level--) { + bp -= 4; + CPU_SP -= 4; + val = cpu_vmemoryread_d(CPU_SS_INDEX, bp); + cpu_vmemorywrite_d(CPU_SS_INDEX, CPU_SP, val); + } + REGPUSH0_32_16(new_bp); + CPU_EBP = new_bp; + CPU_SP -= dimsize; + } + } + } + CPU_CLEAR_PREV_ESP(); +} + +void +LEAVE(void) +{ + + CPU_WORKCLOCK(4); + + CPU_SET_PREV_ESP(); + if (!CPU_STAT_SS32) { + CPU_SP = CPU_BP; + } else { + CPU_ESP = CPU_EBP; + } + if (!CPU_INST_OP32) { + POP0_16(CPU_BP); + } else { + POP0_32(CPU_EBP); + } + CPU_CLEAR_PREV_ESP(); +} diff --git a/i386c/ia32/instructions/ctrl_trans.h b/i386c/ia32/instructions/ctrl_trans.h old mode 100755 new mode 100644 index 19ec91da..00d69e49 --- a/i386c/ia32/instructions/ctrl_trans.h +++ b/i386c/ia32/instructions/ctrl_trans.h @@ -1,153 +1,153 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_CTRL_TRANS_H__ -#define IA32_CPU_INSTRUCTION_CTRL_TRANS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * JMP - */ -void JMP_Jb(void); -void JMP_Jw(void); -void JMP_Jd(void); -void CPUCALL JMP_Ew(UINT32); -void CPUCALL JMP_Ed(UINT32); -void JMP16_Ap(void); -void JMP32_Ap(void); -void CPUCALL JMP16_Ep(UINT32); -void CPUCALL JMP32_Ep(UINT32); - -/* - * Jcc - */ -void JO_Jb(void); -void JO_Jw(void); -void JO_Jd(void); -void JNO_Jb(void); -void JNO_Jw(void); -void JNO_Jd(void); -void JC_Jb(void); -void JC_Jw(void); -void JC_Jd(void); -void JNC_Jb(void); -void JNC_Jw(void); -void JNC_Jd(void); -void JZ_Jb(void); -void JZ_Jw(void); -void JZ_Jd(void); -void JNZ_Jb(void); -void JNZ_Jw(void); -void JNZ_Jd(void); -void JA_Jb(void); -void JA_Jw(void); -void JA_Jd(void); -void JNA_Jb(void); -void JNA_Jw(void); -void JNA_Jd(void); -void JS_Jb(void); -void JS_Jw(void); -void JS_Jd(void); -void JNS_Jb(void); -void JNS_Jw(void); -void JNS_Jd(void); -void JP_Jb(void); -void JP_Jw(void); -void JP_Jd(void); -void JNP_Jb(void); -void JNP_Jw(void); -void JNP_Jd(void); -void JL_Jb(void); -void JL_Jw(void); -void JL_Jd(void); -void JNL_Jb(void); -void JNL_Jw(void); -void JNL_Jd(void); -void JLE_Jb(void); -void JLE_Jw(void); -void JLE_Jd(void); -void JNLE_Jb(void); -void JNLE_Jw(void); -void JNLE_Jd(void); -void JeCXZ_Jb(void); - -/* - * LOOPcc - */ -void LOOPNE_Jb(void); -void LOOPE_Jb(void); -void LOOP_Jb(void); - -/* - * CALL - */ -void CALL_Aw(void); -void CALL_Ad(void); -void CPUCALL CALL_Ew(UINT32); -void CPUCALL CALL_Ed(UINT32); -void CALL16_Ap(void); -void CALL32_Ap(void); -void CPUCALL CALL16_Ep(UINT32); -void CPUCALL CALL32_Ep(UINT32); - -/* - * RET - */ -void RETnear16(void); -void RETnear32(void); -void RETnear16_Iw(void); -void RETnear32_Iw(void); -void RETfar16(void); -void RETfar32(void); -void RETfar16_Iw(void); -void RETfar32_Iw(void); -void IRET(void); - -/* - * INT - */ -void INT1(void); -void INT3(void); -void INTO(void); -void INT_Ib(void); - -void BOUND_GwMa(void); -void BOUND_GdMa(void); - -/* - * STACK - */ -void ENTER16_IwIb(void); -void ENTER32_IwIb(void); -void LEAVE(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_CTRL_TRANS_H__ */ +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_CTRL_TRANS_H__ +#define IA32_CPU_INSTRUCTION_CTRL_TRANS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * JMP + */ +void JMP_Jb(void); +void JMP_Jw(void); +void JMP_Jd(void); +void CPUCALL JMP_Ew(UINT32); +void CPUCALL JMP_Ed(UINT32); +void JMP16_Ap(void); +void JMP32_Ap(void); +void CPUCALL JMP16_Ep(UINT32); +void CPUCALL JMP32_Ep(UINT32); + +/* + * Jcc + */ +void JO_Jb(void); +void JO_Jw(void); +void JO_Jd(void); +void JNO_Jb(void); +void JNO_Jw(void); +void JNO_Jd(void); +void JC_Jb(void); +void JC_Jw(void); +void JC_Jd(void); +void JNC_Jb(void); +void JNC_Jw(void); +void JNC_Jd(void); +void JZ_Jb(void); +void JZ_Jw(void); +void JZ_Jd(void); +void JNZ_Jb(void); +void JNZ_Jw(void); +void JNZ_Jd(void); +void JA_Jb(void); +void JA_Jw(void); +void JA_Jd(void); +void JNA_Jb(void); +void JNA_Jw(void); +void JNA_Jd(void); +void JS_Jb(void); +void JS_Jw(void); +void JS_Jd(void); +void JNS_Jb(void); +void JNS_Jw(void); +void JNS_Jd(void); +void JP_Jb(void); +void JP_Jw(void); +void JP_Jd(void); +void JNP_Jb(void); +void JNP_Jw(void); +void JNP_Jd(void); +void JL_Jb(void); +void JL_Jw(void); +void JL_Jd(void); +void JNL_Jb(void); +void JNL_Jw(void); +void JNL_Jd(void); +void JLE_Jb(void); +void JLE_Jw(void); +void JLE_Jd(void); +void JNLE_Jb(void); +void JNLE_Jw(void); +void JNLE_Jd(void); +void JeCXZ_Jb(void); + +/* + * LOOPcc + */ +void LOOPNE_Jb(void); +void LOOPE_Jb(void); +void LOOP_Jb(void); + +/* + * CALL + */ +void CALL_Aw(void); +void CALL_Ad(void); +void CPUCALL CALL_Ew(UINT32); +void CPUCALL CALL_Ed(UINT32); +void CALL16_Ap(void); +void CALL32_Ap(void); +void CPUCALL CALL16_Ep(UINT32); +void CPUCALL CALL32_Ep(UINT32); + +/* + * RET + */ +void RETnear16(void); +void RETnear32(void); +void RETnear16_Iw(void); +void RETnear32_Iw(void); +void RETfar16(void); +void RETfar32(void); +void RETfar16_Iw(void); +void RETfar32_Iw(void); +void IRET(void); + +/* + * INT + */ +void INT1(void); +void INT3(void); +void INTO(void); +void INT_Ib(void); + +void BOUND_GwMa(void); +void BOUND_GdMa(void); + +/* + * STACK + */ +void ENTER16_IwIb(void); +void ENTER32_IwIb(void); +void LEAVE(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_CTRL_TRANS_H__ */ diff --git a/i386c/ia32/instructions/data_trans.c b/i386c/ia32/instructions/data_trans.c old mode 100755 new mode 100644 index 094b53b2..60906fc4 --- a/i386c/ia32/instructions/data_trans.c +++ b/i386c/ia32/instructions/data_trans.c @@ -1,1763 +1,1763 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" - -#include "data_trans.h" - -/* - * MOV - */ -void -MOV_EbGb(void) -{ - UINT32 op, src, madr; - - PREPART_EA_REG8(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(reg8_b20[op]) = (UINT8)src; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, (UINT8)src); - } -} - -void -MOV_EwGw(void) -{ - UINT32 op, src, madr; - - PREPART_EA_REG16(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(CPU_REG16_B20(op)) = (UINT16)src; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)src); - } -} - -void -MOV_EdGd(void) -{ - UINT32 op, src, madr; - - PREPART_EA_REG32(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(CPU_REG32_B20(op)) = src; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); - } -} - -void -MOV_GbEb(void) -{ - UINT8 *out; - UINT32 op, src; - - PREPART_REG8_EA(op, src, out, 2, 5); - *out = (UINT8)src; -} - -void -MOV_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - *out = (UINT16)src; -} - -void -MOV_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - *out = src; -} - -void -MOV_EwSw(void) -{ - UINT32 op, src, madr; - UINT8 idx; - - GET_MODRM_PCBYTE(op); - idx = (UINT8)((op >> 3) & 7); - if (idx < CPU_SEGREG_NUM) { - src = CPU_REGS_SREG(idx); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(CPU_REG16_B20(op)) = (UINT16)src; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)src); - } - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -MOV_EdSw(void) -{ - UINT32 op, src, madr; - UINT8 idx; - - GET_MODRM_PCBYTE(op); - idx = (UINT8)((op >> 3) & 7); - if (idx < CPU_SEGREG_NUM) { - src = CPU_REGS_SREG(idx); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - *(CPU_REG32_B20(op)) = src; - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)src); - } - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -MOV_SwEw(void) -{ - UINT32 op, src, madr; - UINT8 idx; - - GET_MODRM_PCBYTE(op); - idx = ((UINT8)(op >> 3) & 7); - if ((idx != CPU_CS_INDEX || i386cpuid.allow_movCS) && idx < CPU_SEGREG_NUM) { - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - src = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(5); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - LOAD_SEGREG(idx, (UINT16)src); - if (idx == CPU_SS_INDEX) { - exec_1step(); - } - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -MOV_ALOb(void) -{ - UINT32 madr; - - CPU_WORKCLOCK(5); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - GET_PCWORD(madr); - } else { - GET_PCDWORD(madr); - } - CPU_AL = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); -} - -void -MOV_AXOw(void) -{ - UINT32 madr; - - CPU_WORKCLOCK(5); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - GET_PCWORD(madr); - } else { - GET_PCDWORD(madr); - } - CPU_AX = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); -} - -void -MOV_EAXOd(void) -{ - UINT32 madr; - - CPU_WORKCLOCK(5); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - GET_PCWORD(madr); - } else { - GET_PCDWORD(madr); - } - CPU_EAX = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); -} - -void -MOV_ObAL(void) -{ - UINT32 madr; - - CPU_WORKCLOCK(3); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - GET_PCWORD(madr); - } else { - GET_PCDWORD(madr); - } - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, CPU_AL); -} - -void -MOV_OwAX(void) -{ - UINT32 madr; - - CPU_WORKCLOCK(3); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - GET_PCWORD(madr); - } else { - GET_PCDWORD(madr); - } - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, CPU_AX); -} - -void -MOV_OdEAX(void) -{ - UINT32 madr; - - CPU_WORKCLOCK(3); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - GET_PCWORD(madr); - } else { - GET_PCDWORD(madr); - } - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, CPU_EAX); -} - -void -MOV_EbIb(void) -{ - UINT32 op, src, res, madr; - - PREPART_EA_REG8(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - GET_PCBYTE(res); - *(reg8_b20[op]) = (UINT8)res; - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - GET_PCBYTE(res); - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, (UINT8)res); - } -} - -void -MOV_EwIw(void) -{ - UINT32 op, src, res, madr; - - PREPART_EA_REG16(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - GET_PCWORD(res); - *(CPU_REG16_B20(op)) = (UINT16)res; - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - GET_PCWORD(res); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); - } -} - -void -MOV_EdId(void) -{ - UINT32 op, src, res, madr; - - PREPART_EA_REG32(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - GET_PCDWORD(res); - *(CPU_REG32_B20(op)) = res; - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - GET_PCDWORD(res); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); - } -} - -void MOV_ALIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_AL); } -void MOV_CLIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_CL); } -void MOV_DLIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_DL); } -void MOV_BLIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_BL); } -void MOV_AHIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_AH); } -void MOV_CHIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_CH); } -void MOV_DHIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_DH); } -void MOV_BHIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_BH); } - -void MOV_AXIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_AX); } -void MOV_CXIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_CX); } -void MOV_DXIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_DX); } -void MOV_BXIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_BX); } -void MOV_SPIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_SP); } -void MOV_BPIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_BP); } -void MOV_SIIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_SI); } -void MOV_DIIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_DI); } - -void MOV_EAXId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_EAX); } -void MOV_ECXId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_ECX); } -void MOV_EDXId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_EDX); } -void MOV_EBXId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_EBX); } -void MOV_ESPId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_ESP); } -void MOV_EBPId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_EBP); } -void MOV_ESIId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_ESI); } -void MOV_EDIId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_EDI); } - -/* - * CMOVcc - */ -void -CMOVO_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_O) { - *out = (UINT16)src; - } -} - -void -CMOVO_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_O) { - *out = src; - } -} - -void -CMOVNO_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_NO) { - *out = (UINT16)src; - } -} - -void -CMOVNO_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_NO) { - *out = src; - } -} - -void -CMOVC_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_C) { - *out = (UINT16)src; - } -} - -void -CMOVC_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_C) { - *out = src; - } -} - -void -CMOVNC_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_NC) { - *out = (UINT16)src; - } -} - -void -CMOVNC_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_NC) { - *out = src; - } -} - -void -CMOVZ_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_Z) { - *out = (UINT16)src; - } -} - -void -CMOVZ_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_Z) { - *out = src; - } -} - -void -CMOVNZ_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_NZ) { - *out = (UINT16)src; - } -} - -void -CMOVNZ_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_NZ) { - *out = src; - } -} - -void -CMOVA_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_A) { - *out = (UINT16)src; - } -} - -void -CMOVA_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_A) { - *out = src; - } -} - -void -CMOVNA_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_NA) { - *out = (UINT16)src; - } -} - -void -CMOVNA_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_NA) { - *out = src; - } -} - -void -CMOVS_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_S) { - *out = (UINT16)src; - } -} - -void -CMOVS_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_S) { - *out = src; - } -} - -void -CMOVNS_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_NS) { - *out = (UINT16)src; - } -} - -void -CMOVNS_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_NS) { - *out = src; - } -} - -void -CMOVP_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_P) { - *out = (UINT16)src; - } -} - -void -CMOVP_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_P) { - *out = src; - } -} - -void -CMOVNP_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_NP) { - *out = (UINT16)src; - } -} - -void -CMOVNP_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_NP) { - *out = src; - } -} - -void -CMOVL_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_L) { - *out = (UINT16)src; - } -} - -void -CMOVL_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_L) { - *out = src; - } -} - -void -CMOVNL_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_NL) { - *out = (UINT16)src; - } -} - -void -CMOVNL_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_NL) { - *out = src; - } -} - -void -CMOVLE_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_LE) { - *out = (UINT16)src; - } -} - -void -CMOVLE_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_LE) { - *out = src; - } -} - -void -CMOVNLE_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - if (CC_NLE) { - *out = (UINT16)src; - } -} - -void -CMOVNLE_GdEd(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA(op, src, out, 2, 5); - if (CC_NLE) { - *out = src; - } -} - -/* - * XCHG - */ -static UINT32 CPUCALL -XCHG(UINT32 dst, void *arg) -{ - UINT32 src = PTR_TO_UINT32(arg); - (void)dst; - return src; -} - -void -XCHG_EbGb(void) -{ - UINT8 *out, *src; - UINT32 op, madr; - - PREPART_EA_REG8P(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(3); - out = reg8_b20[op]; - SWAP_BYTE(*out, *src); - } else { - CPU_WORKCLOCK(5); - madr = calc_ea_dst(op); - *src = (UINT8)cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, XCHG, UINT32_TO_PTR(*src)); - } -} - -void -XCHG_EwGw(void) -{ - UINT16 *out, *src; - UINT32 op, madr; - - PREPART_EA_REG16P(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(3); - out = CPU_REG16_B20(op); - SWAP_WORD(*out, *src); - } else { - CPU_WORKCLOCK(5); - madr = calc_ea_dst(op); - *src = (UINT16)cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, XCHG, UINT32_TO_PTR(*src)); - } -} - -void -XCHG_EdGd(void) -{ - UINT32 *out, *src; - UINT32 op, madr; - - PREPART_EA_REG32P(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(3); - out = CPU_REG32_B20(op); - SWAP_DWORD(*out, *src); - } else { - CPU_WORKCLOCK(5); - madr = calc_ea_dst(op); - *src = cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, XCHG, UINT32_TO_PTR(*src)); - } -} - -/* void XCHG_AXAX(void) { } */ -void XCHG_CXAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_CX, CPU_AX); } -void XCHG_DXAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_DX, CPU_AX); } -void XCHG_BXAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_BX, CPU_AX); } -void XCHG_SPAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_SP, CPU_AX); } -void XCHG_BPAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_BP, CPU_AX); } -void XCHG_SIAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_SI, CPU_AX); } -void XCHG_DIAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_DI, CPU_AX); } - -/* void XCHG_EAXEAX(void) { } */ -void XCHG_ECXEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_ECX, CPU_EAX); } -void XCHG_EDXEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_EDX, CPU_EAX); } -void XCHG_EBXEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_EBX, CPU_EAX); } -void XCHG_ESPEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_ESP, CPU_EAX); } -void XCHG_EBPEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_EBP, CPU_EAX); } -void XCHG_ESIEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_ESI, CPU_EAX); } -void XCHG_EDIEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_EDI, CPU_EAX); } - -/* - * BSWAP - */ -static INLINE UINT32 CPUCALL -BSWAP_DWORD(UINT32 val) -{ - UINT32 v; - v = (val & 0x000000ff) << 24; - v |= (val & 0x0000ff00) << 8; - v |= (val & 0x00ff0000) >> 8; - v |= (val & 0xff000000) >> 24; - return v; -} - -void BSWAP_EAX(void) { CPU_WORKCLOCK(2); CPU_EAX = BSWAP_DWORD(CPU_EAX); } -void BSWAP_ECX(void) { CPU_WORKCLOCK(2); CPU_ECX = BSWAP_DWORD(CPU_ECX); } -void BSWAP_EDX(void) { CPU_WORKCLOCK(2); CPU_EDX = BSWAP_DWORD(CPU_EDX); } -void BSWAP_EBX(void) { CPU_WORKCLOCK(2); CPU_EBX = BSWAP_DWORD(CPU_EBX); } -void BSWAP_ESP(void) { CPU_WORKCLOCK(2); CPU_ESP = BSWAP_DWORD(CPU_ESP); } -void BSWAP_EBP(void) { CPU_WORKCLOCK(2); CPU_EBP = BSWAP_DWORD(CPU_EBP); } -void BSWAP_ESI(void) { CPU_WORKCLOCK(2); CPU_ESI = BSWAP_DWORD(CPU_ESI); } -void BSWAP_EDI(void) { CPU_WORKCLOCK(2); CPU_EDI = BSWAP_DWORD(CPU_EDI); } - -/* - * XADD - */ -static UINT32 CPUCALL -XADD1(UINT32 dst, void *arg) -{ - UINT32 src = PTR_TO_UINT32(arg); - UINT32 res; - BYTE_ADD(res, dst, src); - return res; -} - -static UINT32 CPUCALL -XADD2(UINT32 dst, void *arg) -{ - UINT32 src = PTR_TO_UINT32(arg); - UINT32 res; - WORD_ADD(res, dst, src); - return res; -} - -static UINT32 CPUCALL -XADD4(UINT32 dst, void *arg) -{ - UINT32 src = PTR_TO_UINT32(arg); - UINT32 res; - DWORD_ADD(res, dst, src); - return res; -} - -void -XADD_EbGb(void) -{ - UINT8 *out, *src; - UINT32 op, dst, res, madr; - - PREPART_EA_REG8P(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = reg8_b20[op]; - dst = *out; - BYTE_ADD(res, dst, *src); - *src = (UINT8)dst; - *out = (UINT8)res; - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - *src = (UINT8)cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, XADD1, UINT32_TO_PTR(*src)); - } -} - -void -XADD_EwGw(void) -{ - UINT16 *out, *src; - UINT32 op, dst, res, madr; - - PREPART_EA_REG16P(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG16_B20(op); - dst = *out; - WORD_ADD(res, dst, *src); - *src = (UINT16)dst; - *out = (UINT16)res; - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - *src = (UINT16)cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, XADD2, UINT32_TO_PTR(*src)); - } -} - -void -XADD_EdGd(void) -{ - UINT32 *out, *src; - UINT32 op, dst, res, madr; - - PREPART_EA_REG32P(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG32_B20(op); - dst = *out; - DWORD_ADD(res, dst, *src); - *src = dst; - *out = res; - } else { - CPU_WORKCLOCK(7); - madr = calc_ea_dst(op); - *src = cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, XADD4, UINT32_TO_PTR(*src)); - } -} - -/* - * CMPXCHG - */ -void -CMPXCHG_EbGb(void) -{ - UINT8 *out; - UINT32 op, src, dst, madr, tmp; - UINT8 al; - - PREPART_EA_REG8(op, src); - al = CPU_AL; - if (op >= 0xc0) { - out = reg8_b20[op]; - dst = *out; - if (al == dst) { - *out = (UINT8)src; - } else { - CPU_AL = (UINT8)dst; - } - } else { - madr = calc_ea_dst(op); - dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); - if (al == dst) { - cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, (UINT8)src); - } else { - CPU_AL = (UINT8)dst; - } - } - BYTE_SUB(tmp, al, dst); -} - -void -CMPXCHG_EwGw(void) -{ - UINT16 *out; - UINT32 op, src, dst, madr, tmp; - UINT16 ax; - - PREPART_EA_REG16(op, src); - ax = CPU_AX; - if (op >= 0xc0) { - out = CPU_REG16_B20(op); - dst = *out; - if (ax == dst) { - *out = (UINT16)src; - } else { - CPU_AX = (UINT16)dst; - } - } else { - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - if (ax == dst) { - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)src); - } else { - CPU_AX = (UINT16)dst; - } - } - WORD_SUB(tmp, ax, dst); -} - -void -CMPXCHG_EdGd(void) -{ - UINT32 *out; - UINT32 op, src, dst, madr, tmp; - UINT32 eax; - - PREPART_EA_REG32(op, src); - eax = CPU_EAX; - if (op >= 0xc0) { - out = CPU_REG32_B20(op); - dst = *out; - if (eax == dst) { - *out = src; - } else { - CPU_EAX = dst; - } - } else { - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - if (eax == dst) { - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); - } else { - CPU_EAX = dst; - } - } - DWORD_SUB(tmp, eax, dst); -} - -void CPUCALL -CMPXCHG8B(UINT32 op) -{ - UINT32 madr, dst_l, dst_h; - - if (op < 0xc0) { - CPU_WORKCLOCK(2); - madr = calc_ea_dst(op); - dst_l = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - dst_h = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 4); - if ((CPU_EDX == dst_h) && (CPU_EAX == dst_l)) { - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, CPU_EBX); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 4, CPU_ECX); - CPU_FLAGL |= Z_FLAG; - } else { - CPU_EDX = dst_h; - CPU_EAX = dst_l; - CPU_FLAGL &= ~Z_FLAG; - } - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -/* - * PUSH - */ -void PUSH_AX(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_AX); } -void PUSH_CX(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_CX); } -void PUSH_DX(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_DX); } -void PUSH_BX(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_BX); } -void PUSH_SP(void) { CPU_WORKCLOCK(3); SP_PUSH_16(CPU_SP); } -void PUSH_BP(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_BP); } -void PUSH_SI(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_SI); } -void PUSH_DI(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_DI); } - -void PUSH_EAX(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_EAX); } -void PUSH_ECX(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_ECX); } -void PUSH_EDX(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_EDX); } -void PUSH_EBX(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_EBX); } -void PUSH_ESP(void) { CPU_WORKCLOCK(3); ESP_PUSH_32(CPU_ESP); } -void PUSH_EBP(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_EBP); } -void PUSH_ESI(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_ESI); } -void PUSH_EDI(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_EDI); } - -void CPUCALL -PUSH_Ew(UINT32 op) -{ - UINT32 dst, madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - dst = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(5); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - PUSH0_16(dst); -} - -void CPUCALL -PUSH_Ed(UINT32 op) -{ - UINT32 dst, madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - dst = *(CPU_REG32_B20(op)); - } else { - CPU_WORKCLOCK(5); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - } - PUSH0_32(dst); -} - -void -PUSH_Ib(void) -{ - SINT32 val; - - CPU_WORKCLOCK(3); - GET_PCBYTESD(val); - XPUSH0(val); -} - -void -PUSH_Iw(void) -{ - UINT16 val; - - CPU_WORKCLOCK(3); - GET_PCWORD(val); - PUSH0_16(val); -} - -void -PUSH_Id(void) -{ - UINT32 val; - - CPU_WORKCLOCK(3); - GET_PCDWORD(val); - PUSH0_32(val); -} - -void PUSH16_ES(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_ES); } -void PUSH16_CS(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_CS); } -void PUSH16_SS(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_SS); } -void PUSH16_DS(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_DS); } -void PUSH16_FS(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_FS); } -void PUSH16_GS(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_GS); } - -void PUSH32_ES(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_ES); } -void PUSH32_CS(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_CS); } -void PUSH32_SS(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_SS); } -void PUSH32_DS(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_DS); } -void PUSH32_FS(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_FS); } -void PUSH32_GS(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_GS); } - -/* - * POP - */ -void POP_AX(void) { CPU_WORKCLOCK(5); POP0_16(CPU_AX); } -void POP_CX(void) { CPU_WORKCLOCK(5); POP0_16(CPU_CX); } -void POP_DX(void) { CPU_WORKCLOCK(5); POP0_16(CPU_DX); } -void POP_BX(void) { CPU_WORKCLOCK(5); POP0_16(CPU_BX); } -void POP_SP(void) { CPU_WORKCLOCK(5); SP_POP_16(CPU_SP); } -void POP_BP(void) { CPU_WORKCLOCK(5); POP0_16(CPU_BP); } -void POP_SI(void) { CPU_WORKCLOCK(5); POP0_16(CPU_SI); } -void POP_DI(void) { CPU_WORKCLOCK(5); POP0_16(CPU_DI); } - -void POP_EAX(void) { CPU_WORKCLOCK(5); POP0_32(CPU_EAX); } -void POP_ECX(void) { CPU_WORKCLOCK(5); POP0_32(CPU_ECX); } -void POP_EDX(void) { CPU_WORKCLOCK(5); POP0_32(CPU_EDX); } -void POP_EBX(void) { CPU_WORKCLOCK(5); POP0_32(CPU_EBX); } -void POP_ESP(void) { CPU_WORKCLOCK(5); ESP_POP_32(CPU_ESP); } -void POP_EBP(void) { CPU_WORKCLOCK(5); POP0_32(CPU_EBP); } -void POP_ESI(void) { CPU_WORKCLOCK(5); POP0_32(CPU_ESI); } -void POP_EDI(void) { CPU_WORKCLOCK(5); POP0_32(CPU_EDI); } - -void -POP_Ew(void) -{ - UINT32 op, madr; - UINT16 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_16(src); - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - *(CPU_REG16_B20(op)) = src; - } else { - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, src); - } - CPU_CLEAR_PREV_ESP(); -} - -void CPUCALL -POP_Ew_G5(UINT32 op) -{ - UINT32 madr; - UINT16 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_16(src); - if (op >= 0xc0) { - *(CPU_REG16_B20(op)) = src; - } else { - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, src); - } - CPU_CLEAR_PREV_ESP(); -} - -void -POP_Ed(void) -{ - UINT32 op, madr; - UINT32 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_32(src); - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - *(CPU_REG32_B20(op)) = src; - } else { - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); - } - CPU_CLEAR_PREV_ESP(); -} - -void CPUCALL -POP_Ed_G5(UINT32 op) -{ - UINT32 src, madr; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_32(src); - if (op >= 0xc0) { - *(CPU_REG32_B20(op)) = src; - } else { - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); - } - CPU_CLEAR_PREV_ESP(); -} - -void -POP16_ES(void) -{ - UINT16 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_16(src); - LOAD_SEGREG(CPU_ES_INDEX, src); - CPU_CLEAR_PREV_ESP(); -} - -void -POP32_ES(void) -{ - UINT32 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_32(src); - LOAD_SEGREG(CPU_ES_INDEX, (UINT16)src); - CPU_CLEAR_PREV_ESP(); -} - -void -POP16_SS(void) -{ - UINT16 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_16(src); - LOAD_SEGREG(CPU_SS_INDEX, src); - CPU_CLEAR_PREV_ESP(); - exec_1step(); -} - -void -POP32_SS(void) -{ - UINT32 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_32(src); - LOAD_SEGREG(CPU_SS_INDEX, (UINT16)src); - CPU_CLEAR_PREV_ESP(); - exec_1step(); -} - -void -POP16_DS(void) -{ - UINT16 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_16(src); - LOAD_SEGREG(CPU_DS_INDEX, src); - CPU_CLEAR_PREV_ESP(); -} - -void -POP32_DS(void) -{ - UINT32 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_32(src); - LOAD_SEGREG(CPU_DS_INDEX, (UINT16)src); - CPU_CLEAR_PREV_ESP(); -} - -void -POP16_FS(void) -{ - UINT16 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_16(src); - LOAD_SEGREG(CPU_FS_INDEX, src); - CPU_CLEAR_PREV_ESP(); -} - -void -POP32_FS(void) -{ - UINT32 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_32(src); - LOAD_SEGREG(CPU_FS_INDEX, (UINT16)src); - CPU_CLEAR_PREV_ESP(); -} - -void -POP16_GS(void) -{ - UINT16 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_16(src); - LOAD_SEGREG(CPU_GS_INDEX, src); - CPU_CLEAR_PREV_ESP(); -} - -void -POP32_GS(void) -{ - UINT32 src; - - CPU_WORKCLOCK(5); - - CPU_SET_PREV_ESP(); - POP0_32(src); - LOAD_SEGREG(CPU_GS_INDEX, (UINT16)src); - CPU_CLEAR_PREV_ESP(); -} - -/* - * PUSHA/POPA - */ -void -PUSHA(void) -{ - UINT16 sp = CPU_SP; - - CPU_WORKCLOCK(17); - CPU_SET_PREV_ESP(); - if (!CPU_STAT_SS32) { - REGPUSH0(CPU_AX); - REGPUSH0(CPU_CX); - REGPUSH0(CPU_DX); - REGPUSH0(CPU_BX); - REGPUSH0(sp); - REGPUSH0(CPU_BP); - REGPUSH0(CPU_SI); - REGPUSH0(CPU_DI); - } else { - REGPUSH0_16_32(CPU_AX); - REGPUSH0_16_32(CPU_CX); - REGPUSH0_16_32(CPU_DX); - REGPUSH0_16_32(CPU_BX); - REGPUSH0_16_32(sp); - REGPUSH0_16_32(CPU_BP); - REGPUSH0_16_32(CPU_SI); - REGPUSH0_16_32(CPU_DI); - } - CPU_CLEAR_PREV_ESP(); -} - -void -PUSHAD(void) -{ - UINT32 esp = CPU_ESP; - - CPU_WORKCLOCK(17); - CPU_SET_PREV_ESP(); - if (!CPU_STAT_SS32) { - REGPUSH0_32_16(CPU_EAX); - REGPUSH0_32_16(CPU_ECX); - REGPUSH0_32_16(CPU_EDX); - REGPUSH0_32_16(CPU_EBX); - REGPUSH0_32_16(esp); - REGPUSH0_32_16(CPU_EBP); - REGPUSH0_32_16(CPU_ESI); - REGPUSH0_32_16(CPU_EDI); - } else { - REGPUSH0_32(CPU_EAX); - REGPUSH0_32(CPU_ECX); - REGPUSH0_32(CPU_EDX); - REGPUSH0_32(CPU_EBX); - REGPUSH0_32(esp); - REGPUSH0_32(CPU_EBP); - REGPUSH0_32(CPU_ESI); - REGPUSH0_32(CPU_EDI); - } - CPU_CLEAR_PREV_ESP(); -} - -void -POPA(void) -{ - UINT16 ax, cx, dx, bx, bp, si, di; - - CPU_WORKCLOCK(19); - CPU_SET_PREV_ESP(); - if (!CPU_STAT_SS32) { - REGPOP0(di); - REGPOP0(si); - REGPOP0(bp); - CPU_SP += 2; - REGPOP0(bx); - REGPOP0(dx); - REGPOP0(cx); - REGPOP0(ax); - } else { - REGPOP0_16_32(di); - REGPOP0_16_32(si); - REGPOP0_16_32(bp); - CPU_ESP += 2; - REGPOP0_16_32(bx); - REGPOP0_16_32(dx); - REGPOP0_16_32(cx); - REGPOP0_16_32(ax); - } - CPU_CLEAR_PREV_ESP(); - - CPU_AX = ax; - CPU_CX = cx; - CPU_DX = dx; - CPU_BX = bx; - CPU_BP = bp; - CPU_SI = si; - CPU_DI = di; -} - -void -POPAD(void) -{ - UINT32 eax, ecx, edx, ebx, ebp, esi, edi; - - CPU_WORKCLOCK(19); - CPU_SET_PREV_ESP(); - if (!CPU_STAT_SS32) { - REGPOP0_32_16(edi); - REGPOP0_32_16(esi); - REGPOP0_32_16(ebp); - CPU_SP += 4; - REGPOP0_32_16(ebx); - REGPOP0_32_16(edx); - REGPOP0_32_16(ecx); - REGPOP0_32_16(eax); - } else { - REGPOP0_32(edi); - REGPOP0_32(esi); - REGPOP0_32(ebp); - CPU_ESP += 4; - REGPOP0_32(ebx); - REGPOP0_32(edx); - REGPOP0_32(ecx); - REGPOP0_32(eax); - } - CPU_CLEAR_PREV_ESP(); - - CPU_EAX = eax; - CPU_ECX = ecx; - CPU_EDX = edx; - CPU_EBX = ebx; - CPU_EBP = ebp; - CPU_ESI = esi; - CPU_EDI = edi; -} - -/* - * in port - */ -void -IN_ALDX(void) -{ - - CPU_WORKCLOCK(12); - CPU_AL = cpu_in(CPU_DX); -} - -void -IN_AXDX(void) -{ - - CPU_WORKCLOCK(12); - CPU_AX = cpu_in_w(CPU_DX); -} - -void -IN_EAXDX(void) -{ - - CPU_WORKCLOCK(12); - CPU_EAX = cpu_in_d(CPU_DX); -} - -void -IN_ALIb(void) -{ - UINT port; - - CPU_WORKCLOCK(12); - GET_MODRM_PCBYTE(port); - CPU_AL = cpu_in(port); -} - -void -IN_AXIb(void) -{ - UINT port; - - CPU_WORKCLOCK(12); - GET_MODRM_PCBYTE(port); - CPU_AX = cpu_in_w(port); -} - -void -IN_EAXIb(void) -{ - UINT port; - - CPU_WORKCLOCK(12); - GET_MODRM_PCBYTE(port); - CPU_EAX = cpu_in_d(port); -} - -/* - * out port - */ -void -OUT_DXAL(void) -{ - - CPU_WORKCLOCK(10); - cpu_out(CPU_DX, CPU_AL); -} - -void -OUT_DXAX(void) -{ - - CPU_WORKCLOCK(10); - cpu_out_w(CPU_DX, CPU_AX); -} - -void -OUT_DXEAX(void) -{ - - CPU_WORKCLOCK(10); - cpu_out_d(CPU_DX, CPU_EAX); -} - -void -OUT_IbAL(void) -{ - UINT port; - - CPU_WORKCLOCK(10); - GET_MODRM_PCBYTE(port); - cpu_out(port, CPU_AL); -} - -void -OUT_IbAX(void) -{ - UINT port; - - CPU_WORKCLOCK(10); - GET_MODRM_PCBYTE(port); - cpu_out_w(port, CPU_AX); -} - -void -OUT_IbEAX(void) -{ - UINT port; - - CPU_WORKCLOCK(10); - GET_MODRM_PCBYTE(port); - cpu_out_d(port, CPU_EAX); -} - -/* - * convert - */ -void -CWD(void) -{ - - CPU_WORKCLOCK(2); - if (CPU_AX & 0x8000) { - CPU_DX = 0xffff; - } else { - CPU_DX = 0; - } -} - -void -CDQ(void) -{ - - CPU_WORKCLOCK(2); - if (CPU_EAX & 0x80000000) { - CPU_EDX = 0xffffffff; - } else { - CPU_EDX = 0; - } -} - -void -CBW(void) -{ - UINT16 tmp; - - CPU_WORKCLOCK(2); - tmp = __CBW(CPU_AL); - CPU_AX = tmp; -} - -void -CWDE(void) -{ - UINT32 tmp; - - CPU_WORKCLOCK(2); - tmp = __CWDE(CPU_AX); - CPU_EAX = tmp; -} - -/* - * MOVSx - */ -void -MOVSX_GwEb(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA8(op, src, out, 2, 5); - *out = __CBW(src); -} - -void -MOVSX_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - *out = (UINT16)src; -} - -void -MOVSX_GdEb(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA8(op, src, out, 2, 5); - *out = __CBD(src); -} - -void -MOVSX_GdEw(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA16(op, src, out, 2, 5); - *out = __CWDE(src); -} - -/* - * MOVZx - */ -void -MOVZX_GwEb(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA8(op, src, out, 2, 5); - *out = (UINT8)src; -} - -void -MOVZX_GwEw(void) -{ - UINT16 *out; - UINT32 op, src; - - PREPART_REG16_EA(op, src, out, 2, 5); - *out = (UINT16)src; -} - -void -MOVZX_GdEb(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA8(op, src, out, 2, 5); - *out = (UINT8)src; -} - -void -MOVZX_GdEw(void) -{ - UINT32 *out; - UINT32 op, src; - - PREPART_REG32_EA16(op, src, out, 2, 5); - *out = (UINT16)src; +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" + +#include "data_trans.h" + +/* + * MOV + */ +void +MOV_EbGb(void) +{ + UINT32 op, src, madr; + + PREPART_EA_REG8(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(reg8_b20[op]) = (UINT8)src; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, (UINT8)src); + } +} + +void +MOV_EwGw(void) +{ + UINT32 op, src, madr; + + PREPART_EA_REG16(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(CPU_REG16_B20(op)) = (UINT16)src; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)src); + } +} + +void +MOV_EdGd(void) +{ + UINT32 op, src, madr; + + PREPART_EA_REG32(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(CPU_REG32_B20(op)) = src; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); + } +} + +void +MOV_GbEb(void) +{ + UINT8 *out; + UINT32 op, src; + + PREPART_REG8_EA(op, src, out, 2, 5); + *out = (UINT8)src; +} + +void +MOV_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + *out = (UINT16)src; +} + +void +MOV_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + *out = src; +} + +void +MOV_EwSw(void) +{ + UINT32 op, src, madr; + UINT8 idx; + + GET_MODRM_PCBYTE(op); + idx = (UINT8)((op >> 3) & 7); + if (idx < CPU_SEGREG_NUM) { + src = CPU_REGS_SREG(idx); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(CPU_REG16_B20(op)) = (UINT16)src; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)src); + } + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +MOV_EdSw(void) +{ + UINT32 op, src, madr; + UINT8 idx; + + GET_MODRM_PCBYTE(op); + idx = (UINT8)((op >> 3) & 7); + if (idx < CPU_SEGREG_NUM) { + src = CPU_REGS_SREG(idx); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + *(CPU_REG32_B20(op)) = src; + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)src); + } + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +MOV_SwEw(void) +{ + UINT32 op, src, madr; + UINT8 idx; + + GET_MODRM_PCBYTE(op); + idx = ((UINT8)(op >> 3) & 7); + if ((idx != CPU_CS_INDEX || i386cpuid.allow_movCS) && idx < CPU_SEGREG_NUM) { + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + src = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(5); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + LOAD_SEGREG(idx, (UINT16)src); + if (idx == CPU_SS_INDEX) { + exec_1step(); + } + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +MOV_ALOb(void) +{ + UINT32 madr; + + CPU_WORKCLOCK(5); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + GET_PCWORD(madr); + } else { + GET_PCDWORD(madr); + } + CPU_AL = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); +} + +void +MOV_AXOw(void) +{ + UINT32 madr; + + CPU_WORKCLOCK(5); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + GET_PCWORD(madr); + } else { + GET_PCDWORD(madr); + } + CPU_AX = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); +} + +void +MOV_EAXOd(void) +{ + UINT32 madr; + + CPU_WORKCLOCK(5); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + GET_PCWORD(madr); + } else { + GET_PCDWORD(madr); + } + CPU_EAX = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); +} + +void +MOV_ObAL(void) +{ + UINT32 madr; + + CPU_WORKCLOCK(3); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + GET_PCWORD(madr); + } else { + GET_PCDWORD(madr); + } + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, CPU_AL); +} + +void +MOV_OwAX(void) +{ + UINT32 madr; + + CPU_WORKCLOCK(3); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + GET_PCWORD(madr); + } else { + GET_PCDWORD(madr); + } + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, CPU_AX); +} + +void +MOV_OdEAX(void) +{ + UINT32 madr; + + CPU_WORKCLOCK(3); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + GET_PCWORD(madr); + } else { + GET_PCDWORD(madr); + } + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, CPU_EAX); +} + +void +MOV_EbIb(void) +{ + UINT32 op, src, res, madr; + + PREPART_EA_REG8(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + GET_PCBYTE(res); + *(reg8_b20[op]) = (UINT8)res; + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + GET_PCBYTE(res); + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, (UINT8)res); + } +} + +void +MOV_EwIw(void) +{ + UINT32 op, src, res, madr; + + PREPART_EA_REG16(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + GET_PCWORD(res); + *(CPU_REG16_B20(op)) = (UINT16)res; + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + GET_PCWORD(res); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)res); + } +} + +void +MOV_EdId(void) +{ + UINT32 op, src, res, madr; + + PREPART_EA_REG32(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + GET_PCDWORD(res); + *(CPU_REG32_B20(op)) = res; + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + GET_PCDWORD(res); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, res); + } +} + +void MOV_ALIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_AL); } +void MOV_CLIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_CL); } +void MOV_DLIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_DL); } +void MOV_BLIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_BL); } +void MOV_AHIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_AH); } +void MOV_CHIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_CH); } +void MOV_DHIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_DH); } +void MOV_BHIb(void) { CPU_WORKCLOCK(2); GET_MODRM_PCBYTE(CPU_BH); } + +void MOV_AXIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_AX); } +void MOV_CXIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_CX); } +void MOV_DXIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_DX); } +void MOV_BXIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_BX); } +void MOV_SPIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_SP); } +void MOV_BPIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_BP); } +void MOV_SIIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_SI); } +void MOV_DIIw(void) { CPU_WORKCLOCK(2); GET_PCWORD(CPU_DI); } + +void MOV_EAXId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_EAX); } +void MOV_ECXId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_ECX); } +void MOV_EDXId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_EDX); } +void MOV_EBXId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_EBX); } +void MOV_ESPId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_ESP); } +void MOV_EBPId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_EBP); } +void MOV_ESIId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_ESI); } +void MOV_EDIId(void) { CPU_WORKCLOCK(2); GET_PCDWORD(CPU_EDI); } + +/* + * CMOVcc + */ +void +CMOVO_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_O) { + *out = (UINT16)src; + } +} + +void +CMOVO_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_O) { + *out = src; + } +} + +void +CMOVNO_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_NO) { + *out = (UINT16)src; + } +} + +void +CMOVNO_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_NO) { + *out = src; + } +} + +void +CMOVC_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_C) { + *out = (UINT16)src; + } +} + +void +CMOVC_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_C) { + *out = src; + } +} + +void +CMOVNC_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_NC) { + *out = (UINT16)src; + } +} + +void +CMOVNC_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_NC) { + *out = src; + } +} + +void +CMOVZ_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_Z) { + *out = (UINT16)src; + } +} + +void +CMOVZ_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_Z) { + *out = src; + } +} + +void +CMOVNZ_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_NZ) { + *out = (UINT16)src; + } +} + +void +CMOVNZ_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_NZ) { + *out = src; + } +} + +void +CMOVA_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_A) { + *out = (UINT16)src; + } +} + +void +CMOVA_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_A) { + *out = src; + } +} + +void +CMOVNA_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_NA) { + *out = (UINT16)src; + } +} + +void +CMOVNA_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_NA) { + *out = src; + } +} + +void +CMOVS_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_S) { + *out = (UINT16)src; + } +} + +void +CMOVS_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_S) { + *out = src; + } +} + +void +CMOVNS_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_NS) { + *out = (UINT16)src; + } +} + +void +CMOVNS_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_NS) { + *out = src; + } +} + +void +CMOVP_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_P) { + *out = (UINT16)src; + } +} + +void +CMOVP_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_P) { + *out = src; + } +} + +void +CMOVNP_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_NP) { + *out = (UINT16)src; + } +} + +void +CMOVNP_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_NP) { + *out = src; + } +} + +void +CMOVL_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_L) { + *out = (UINT16)src; + } +} + +void +CMOVL_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_L) { + *out = src; + } +} + +void +CMOVNL_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_NL) { + *out = (UINT16)src; + } +} + +void +CMOVNL_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_NL) { + *out = src; + } +} + +void +CMOVLE_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_LE) { + *out = (UINT16)src; + } +} + +void +CMOVLE_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_LE) { + *out = src; + } +} + +void +CMOVNLE_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + if (CC_NLE) { + *out = (UINT16)src; + } +} + +void +CMOVNLE_GdEd(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA(op, src, out, 2, 5); + if (CC_NLE) { + *out = src; + } +} + +/* + * XCHG + */ +static UINT32 CPUCALL +XCHG(UINT32 dst, void *arg) +{ + UINT32 src = PTR_TO_UINT32(arg); + (void)dst; + return src; +} + +void +XCHG_EbGb(void) +{ + UINT8 *out, *src; + UINT32 op, madr; + + PREPART_EA_REG8P(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(3); + out = reg8_b20[op]; + SWAP_BYTE(*out, *src); + } else { + CPU_WORKCLOCK(5); + madr = calc_ea_dst(op); + *src = (UINT8)cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, XCHG, UINT32_TO_PTR(*src)); + } +} + +void +XCHG_EwGw(void) +{ + UINT16 *out, *src; + UINT32 op, madr; + + PREPART_EA_REG16P(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(3); + out = CPU_REG16_B20(op); + SWAP_WORD(*out, *src); + } else { + CPU_WORKCLOCK(5); + madr = calc_ea_dst(op); + *src = (UINT16)cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, XCHG, UINT32_TO_PTR(*src)); + } +} + +void +XCHG_EdGd(void) +{ + UINT32 *out, *src; + UINT32 op, madr; + + PREPART_EA_REG32P(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(3); + out = CPU_REG32_B20(op); + SWAP_DWORD(*out, *src); + } else { + CPU_WORKCLOCK(5); + madr = calc_ea_dst(op); + *src = cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, XCHG, UINT32_TO_PTR(*src)); + } +} + +/* void XCHG_AXAX(void) { } */ +void XCHG_CXAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_CX, CPU_AX); } +void XCHG_DXAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_DX, CPU_AX); } +void XCHG_BXAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_BX, CPU_AX); } +void XCHG_SPAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_SP, CPU_AX); } +void XCHG_BPAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_BP, CPU_AX); } +void XCHG_SIAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_SI, CPU_AX); } +void XCHG_DIAX(void) { CPU_WORKCLOCK(3); SWAP_WORD(CPU_DI, CPU_AX); } + +/* void XCHG_EAXEAX(void) { } */ +void XCHG_ECXEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_ECX, CPU_EAX); } +void XCHG_EDXEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_EDX, CPU_EAX); } +void XCHG_EBXEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_EBX, CPU_EAX); } +void XCHG_ESPEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_ESP, CPU_EAX); } +void XCHG_EBPEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_EBP, CPU_EAX); } +void XCHG_ESIEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_ESI, CPU_EAX); } +void XCHG_EDIEAX(void) { CPU_WORKCLOCK(3); SWAP_DWORD(CPU_EDI, CPU_EAX); } + +/* + * BSWAP + */ +static INLINE UINT32 CPUCALL +BSWAP_DWORD(UINT32 val) +{ + UINT32 v; + v = (val & 0x000000ff) << 24; + v |= (val & 0x0000ff00) << 8; + v |= (val & 0x00ff0000) >> 8; + v |= (val & 0xff000000) >> 24; + return v; +} + +void BSWAP_EAX(void) { CPU_WORKCLOCK(2); CPU_EAX = BSWAP_DWORD(CPU_EAX); } +void BSWAP_ECX(void) { CPU_WORKCLOCK(2); CPU_ECX = BSWAP_DWORD(CPU_ECX); } +void BSWAP_EDX(void) { CPU_WORKCLOCK(2); CPU_EDX = BSWAP_DWORD(CPU_EDX); } +void BSWAP_EBX(void) { CPU_WORKCLOCK(2); CPU_EBX = BSWAP_DWORD(CPU_EBX); } +void BSWAP_ESP(void) { CPU_WORKCLOCK(2); CPU_ESP = BSWAP_DWORD(CPU_ESP); } +void BSWAP_EBP(void) { CPU_WORKCLOCK(2); CPU_EBP = BSWAP_DWORD(CPU_EBP); } +void BSWAP_ESI(void) { CPU_WORKCLOCK(2); CPU_ESI = BSWAP_DWORD(CPU_ESI); } +void BSWAP_EDI(void) { CPU_WORKCLOCK(2); CPU_EDI = BSWAP_DWORD(CPU_EDI); } + +/* + * XADD + */ +static UINT32 CPUCALL +XADD1(UINT32 dst, void *arg) +{ + UINT32 src = PTR_TO_UINT32(arg); + UINT32 res; + BYTE_ADD(res, dst, src); + return res; +} + +static UINT32 CPUCALL +XADD2(UINT32 dst, void *arg) +{ + UINT32 src = PTR_TO_UINT32(arg); + UINT32 res; + WORD_ADD(res, dst, src); + return res; +} + +static UINT32 CPUCALL +XADD4(UINT32 dst, void *arg) +{ + UINT32 src = PTR_TO_UINT32(arg); + UINT32 res; + DWORD_ADD(res, dst, src); + return res; +} + +void +XADD_EbGb(void) +{ + UINT8 *out, *src; + UINT32 op, dst, res, madr; + + PREPART_EA_REG8P(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = reg8_b20[op]; + dst = *out; + BYTE_ADD(res, dst, *src); + *src = (UINT8)dst; + *out = (UINT8)res; + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + *src = (UINT8)cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, XADD1, UINT32_TO_PTR(*src)); + } +} + +void +XADD_EwGw(void) +{ + UINT16 *out, *src; + UINT32 op, dst, res, madr; + + PREPART_EA_REG16P(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG16_B20(op); + dst = *out; + WORD_ADD(res, dst, *src); + *src = (UINT16)dst; + *out = (UINT16)res; + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + *src = (UINT16)cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, XADD2, UINT32_TO_PTR(*src)); + } +} + +void +XADD_EdGd(void) +{ + UINT32 *out, *src; + UINT32 op, dst, res, madr; + + PREPART_EA_REG32P(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG32_B20(op); + dst = *out; + DWORD_ADD(res, dst, *src); + *src = dst; + *out = res; + } else { + CPU_WORKCLOCK(7); + madr = calc_ea_dst(op); + *src = cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, XADD4, UINT32_TO_PTR(*src)); + } +} + +/* + * CMPXCHG + */ +void +CMPXCHG_EbGb(void) +{ + UINT8 *out; + UINT32 op, src, dst, madr, tmp; + UINT8 al; + + PREPART_EA_REG8(op, src); + al = CPU_AL; + if (op >= 0xc0) { + out = reg8_b20[op]; + dst = *out; + if (al == dst) { + *out = (UINT8)src; + } else { + CPU_AL = (UINT8)dst; + } + } else { + madr = calc_ea_dst(op); + dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, madr); + if (al == dst) { + cpu_vmemorywrite(CPU_INST_SEGREG_INDEX, madr, (UINT8)src); + } else { + CPU_AL = (UINT8)dst; + } + } + BYTE_SUB(tmp, al, dst); +} + +void +CMPXCHG_EwGw(void) +{ + UINT16 *out; + UINT32 op, src, dst, madr, tmp; + UINT16 ax; + + PREPART_EA_REG16(op, src); + ax = CPU_AX; + if (op >= 0xc0) { + out = CPU_REG16_B20(op); + dst = *out; + if (ax == dst) { + *out = (UINT16)src; + } else { + CPU_AX = (UINT16)dst; + } + } else { + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + if (ax == dst) { + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)src); + } else { + CPU_AX = (UINT16)dst; + } + } + WORD_SUB(tmp, ax, dst); +} + +void +CMPXCHG_EdGd(void) +{ + UINT32 *out; + UINT32 op, src, dst, madr, tmp; + UINT32 eax; + + PREPART_EA_REG32(op, src); + eax = CPU_EAX; + if (op >= 0xc0) { + out = CPU_REG32_B20(op); + dst = *out; + if (eax == dst) { + *out = src; + } else { + CPU_EAX = dst; + } + } else { + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + if (eax == dst) { + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); + } else { + CPU_EAX = dst; + } + } + DWORD_SUB(tmp, eax, dst); +} + +void CPUCALL +CMPXCHG8B(UINT32 op) +{ + UINT32 madr, dst_l, dst_h; + + if (op < 0xc0) { + CPU_WORKCLOCK(2); + madr = calc_ea_dst(op); + dst_l = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + dst_h = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 4); + if ((CPU_EDX == dst_h) && (CPU_EAX == dst_l)) { + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, CPU_EBX); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 4, CPU_ECX); + CPU_FLAGL |= Z_FLAG; + } else { + CPU_EDX = dst_h; + CPU_EAX = dst_l; + CPU_FLAGL &= ~Z_FLAG; + } + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +/* + * PUSH + */ +void PUSH_AX(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_AX); } +void PUSH_CX(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_CX); } +void PUSH_DX(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_DX); } +void PUSH_BX(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_BX); } +void PUSH_SP(void) { CPU_WORKCLOCK(3); SP_PUSH_16(CPU_SP); } +void PUSH_BP(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_BP); } +void PUSH_SI(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_SI); } +void PUSH_DI(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_DI); } + +void PUSH_EAX(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_EAX); } +void PUSH_ECX(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_ECX); } +void PUSH_EDX(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_EDX); } +void PUSH_EBX(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_EBX); } +void PUSH_ESP(void) { CPU_WORKCLOCK(3); ESP_PUSH_32(CPU_ESP); } +void PUSH_EBP(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_EBP); } +void PUSH_ESI(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_ESI); } +void PUSH_EDI(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_EDI); } + +void CPUCALL +PUSH_Ew(UINT32 op) +{ + UINT32 dst, madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + dst = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(5); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + PUSH0_16(dst); +} + +void CPUCALL +PUSH_Ed(UINT32 op) +{ + UINT32 dst, madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + dst = *(CPU_REG32_B20(op)); + } else { + CPU_WORKCLOCK(5); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + } + PUSH0_32(dst); +} + +void +PUSH_Ib(void) +{ + SINT32 val; + + CPU_WORKCLOCK(3); + GET_PCBYTESD(val); + XPUSH0(val); +} + +void +PUSH_Iw(void) +{ + UINT16 val; + + CPU_WORKCLOCK(3); + GET_PCWORD(val); + PUSH0_16(val); +} + +void +PUSH_Id(void) +{ + UINT32 val; + + CPU_WORKCLOCK(3); + GET_PCDWORD(val); + PUSH0_32(val); +} + +void PUSH16_ES(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_ES); } +void PUSH16_CS(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_CS); } +void PUSH16_SS(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_SS); } +void PUSH16_DS(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_DS); } +void PUSH16_FS(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_FS); } +void PUSH16_GS(void) { CPU_WORKCLOCK(3); PUSH0_16(CPU_GS); } + +void PUSH32_ES(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_ES); } +void PUSH32_CS(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_CS); } +void PUSH32_SS(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_SS); } +void PUSH32_DS(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_DS); } +void PUSH32_FS(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_FS); } +void PUSH32_GS(void) { CPU_WORKCLOCK(3); PUSH0_32(CPU_GS); } + +/* + * POP + */ +void POP_AX(void) { CPU_WORKCLOCK(5); POP0_16(CPU_AX); } +void POP_CX(void) { CPU_WORKCLOCK(5); POP0_16(CPU_CX); } +void POP_DX(void) { CPU_WORKCLOCK(5); POP0_16(CPU_DX); } +void POP_BX(void) { CPU_WORKCLOCK(5); POP0_16(CPU_BX); } +void POP_SP(void) { CPU_WORKCLOCK(5); SP_POP_16(CPU_SP); } +void POP_BP(void) { CPU_WORKCLOCK(5); POP0_16(CPU_BP); } +void POP_SI(void) { CPU_WORKCLOCK(5); POP0_16(CPU_SI); } +void POP_DI(void) { CPU_WORKCLOCK(5); POP0_16(CPU_DI); } + +void POP_EAX(void) { CPU_WORKCLOCK(5); POP0_32(CPU_EAX); } +void POP_ECX(void) { CPU_WORKCLOCK(5); POP0_32(CPU_ECX); } +void POP_EDX(void) { CPU_WORKCLOCK(5); POP0_32(CPU_EDX); } +void POP_EBX(void) { CPU_WORKCLOCK(5); POP0_32(CPU_EBX); } +void POP_ESP(void) { CPU_WORKCLOCK(5); ESP_POP_32(CPU_ESP); } +void POP_EBP(void) { CPU_WORKCLOCK(5); POP0_32(CPU_EBP); } +void POP_ESI(void) { CPU_WORKCLOCK(5); POP0_32(CPU_ESI); } +void POP_EDI(void) { CPU_WORKCLOCK(5); POP0_32(CPU_EDI); } + +void +POP_Ew(void) +{ + UINT32 op, madr; + UINT16 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_16(src); + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + *(CPU_REG16_B20(op)) = src; + } else { + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, src); + } + CPU_CLEAR_PREV_ESP(); +} + +void CPUCALL +POP_Ew_G5(UINT32 op) +{ + UINT32 madr; + UINT16 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_16(src); + if (op >= 0xc0) { + *(CPU_REG16_B20(op)) = src; + } else { + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, src); + } + CPU_CLEAR_PREV_ESP(); +} + +void +POP_Ed(void) +{ + UINT32 op, madr; + UINT32 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_32(src); + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + *(CPU_REG32_B20(op)) = src; + } else { + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); + } + CPU_CLEAR_PREV_ESP(); +} + +void CPUCALL +POP_Ed_G5(UINT32 op) +{ + UINT32 src, madr; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_32(src); + if (op >= 0xc0) { + *(CPU_REG32_B20(op)) = src; + } else { + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); + } + CPU_CLEAR_PREV_ESP(); +} + +void +POP16_ES(void) +{ + UINT16 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_16(src); + LOAD_SEGREG(CPU_ES_INDEX, src); + CPU_CLEAR_PREV_ESP(); +} + +void +POP32_ES(void) +{ + UINT32 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_32(src); + LOAD_SEGREG(CPU_ES_INDEX, (UINT16)src); + CPU_CLEAR_PREV_ESP(); +} + +void +POP16_SS(void) +{ + UINT16 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_16(src); + LOAD_SEGREG(CPU_SS_INDEX, src); + CPU_CLEAR_PREV_ESP(); + exec_1step(); +} + +void +POP32_SS(void) +{ + UINT32 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_32(src); + LOAD_SEGREG(CPU_SS_INDEX, (UINT16)src); + CPU_CLEAR_PREV_ESP(); + exec_1step(); +} + +void +POP16_DS(void) +{ + UINT16 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_16(src); + LOAD_SEGREG(CPU_DS_INDEX, src); + CPU_CLEAR_PREV_ESP(); +} + +void +POP32_DS(void) +{ + UINT32 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_32(src); + LOAD_SEGREG(CPU_DS_INDEX, (UINT16)src); + CPU_CLEAR_PREV_ESP(); +} + +void +POP16_FS(void) +{ + UINT16 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_16(src); + LOAD_SEGREG(CPU_FS_INDEX, src); + CPU_CLEAR_PREV_ESP(); +} + +void +POP32_FS(void) +{ + UINT32 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_32(src); + LOAD_SEGREG(CPU_FS_INDEX, (UINT16)src); + CPU_CLEAR_PREV_ESP(); +} + +void +POP16_GS(void) +{ + UINT16 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_16(src); + LOAD_SEGREG(CPU_GS_INDEX, src); + CPU_CLEAR_PREV_ESP(); +} + +void +POP32_GS(void) +{ + UINT32 src; + + CPU_WORKCLOCK(5); + + CPU_SET_PREV_ESP(); + POP0_32(src); + LOAD_SEGREG(CPU_GS_INDEX, (UINT16)src); + CPU_CLEAR_PREV_ESP(); +} + +/* + * PUSHA/POPA + */ +void +PUSHA(void) +{ + UINT16 sp = CPU_SP; + + CPU_WORKCLOCK(17); + CPU_SET_PREV_ESP(); + if (!CPU_STAT_SS32) { + REGPUSH0(CPU_AX); + REGPUSH0(CPU_CX); + REGPUSH0(CPU_DX); + REGPUSH0(CPU_BX); + REGPUSH0(sp); + REGPUSH0(CPU_BP); + REGPUSH0(CPU_SI); + REGPUSH0(CPU_DI); + } else { + REGPUSH0_16_32(CPU_AX); + REGPUSH0_16_32(CPU_CX); + REGPUSH0_16_32(CPU_DX); + REGPUSH0_16_32(CPU_BX); + REGPUSH0_16_32(sp); + REGPUSH0_16_32(CPU_BP); + REGPUSH0_16_32(CPU_SI); + REGPUSH0_16_32(CPU_DI); + } + CPU_CLEAR_PREV_ESP(); +} + +void +PUSHAD(void) +{ + UINT32 esp = CPU_ESP; + + CPU_WORKCLOCK(17); + CPU_SET_PREV_ESP(); + if (!CPU_STAT_SS32) { + REGPUSH0_32_16(CPU_EAX); + REGPUSH0_32_16(CPU_ECX); + REGPUSH0_32_16(CPU_EDX); + REGPUSH0_32_16(CPU_EBX); + REGPUSH0_32_16(esp); + REGPUSH0_32_16(CPU_EBP); + REGPUSH0_32_16(CPU_ESI); + REGPUSH0_32_16(CPU_EDI); + } else { + REGPUSH0_32(CPU_EAX); + REGPUSH0_32(CPU_ECX); + REGPUSH0_32(CPU_EDX); + REGPUSH0_32(CPU_EBX); + REGPUSH0_32(esp); + REGPUSH0_32(CPU_EBP); + REGPUSH0_32(CPU_ESI); + REGPUSH0_32(CPU_EDI); + } + CPU_CLEAR_PREV_ESP(); +} + +void +POPA(void) +{ + UINT16 ax, cx, dx, bx, bp, si, di; + + CPU_WORKCLOCK(19); + CPU_SET_PREV_ESP(); + if (!CPU_STAT_SS32) { + REGPOP0(di); + REGPOP0(si); + REGPOP0(bp); + CPU_SP += 2; + REGPOP0(bx); + REGPOP0(dx); + REGPOP0(cx); + REGPOP0(ax); + } else { + REGPOP0_16_32(di); + REGPOP0_16_32(si); + REGPOP0_16_32(bp); + CPU_ESP += 2; + REGPOP0_16_32(bx); + REGPOP0_16_32(dx); + REGPOP0_16_32(cx); + REGPOP0_16_32(ax); + } + CPU_CLEAR_PREV_ESP(); + + CPU_AX = ax; + CPU_CX = cx; + CPU_DX = dx; + CPU_BX = bx; + CPU_BP = bp; + CPU_SI = si; + CPU_DI = di; +} + +void +POPAD(void) +{ + UINT32 eax, ecx, edx, ebx, ebp, esi, edi; + + CPU_WORKCLOCK(19); + CPU_SET_PREV_ESP(); + if (!CPU_STAT_SS32) { + REGPOP0_32_16(edi); + REGPOP0_32_16(esi); + REGPOP0_32_16(ebp); + CPU_SP += 4; + REGPOP0_32_16(ebx); + REGPOP0_32_16(edx); + REGPOP0_32_16(ecx); + REGPOP0_32_16(eax); + } else { + REGPOP0_32(edi); + REGPOP0_32(esi); + REGPOP0_32(ebp); + CPU_ESP += 4; + REGPOP0_32(ebx); + REGPOP0_32(edx); + REGPOP0_32(ecx); + REGPOP0_32(eax); + } + CPU_CLEAR_PREV_ESP(); + + CPU_EAX = eax; + CPU_ECX = ecx; + CPU_EDX = edx; + CPU_EBX = ebx; + CPU_EBP = ebp; + CPU_ESI = esi; + CPU_EDI = edi; +} + +/* + * in port + */ +void +IN_ALDX(void) +{ + + CPU_WORKCLOCK(12); + CPU_AL = cpu_in(CPU_DX); +} + +void +IN_AXDX(void) +{ + + CPU_WORKCLOCK(12); + CPU_AX = cpu_in_w(CPU_DX); +} + +void +IN_EAXDX(void) +{ + + CPU_WORKCLOCK(12); + CPU_EAX = cpu_in_d(CPU_DX); +} + +void +IN_ALIb(void) +{ + UINT port; + + CPU_WORKCLOCK(12); + GET_MODRM_PCBYTE(port); + CPU_AL = cpu_in(port); +} + +void +IN_AXIb(void) +{ + UINT port; + + CPU_WORKCLOCK(12); + GET_MODRM_PCBYTE(port); + CPU_AX = cpu_in_w(port); +} + +void +IN_EAXIb(void) +{ + UINT port; + + CPU_WORKCLOCK(12); + GET_MODRM_PCBYTE(port); + CPU_EAX = cpu_in_d(port); +} + +/* + * out port + */ +void +OUT_DXAL(void) +{ + + CPU_WORKCLOCK(10); + cpu_out(CPU_DX, CPU_AL); +} + +void +OUT_DXAX(void) +{ + + CPU_WORKCLOCK(10); + cpu_out_w(CPU_DX, CPU_AX); +} + +void +OUT_DXEAX(void) +{ + + CPU_WORKCLOCK(10); + cpu_out_d(CPU_DX, CPU_EAX); +} + +void +OUT_IbAL(void) +{ + UINT port; + + CPU_WORKCLOCK(10); + GET_MODRM_PCBYTE(port); + cpu_out(port, CPU_AL); +} + +void +OUT_IbAX(void) +{ + UINT port; + + CPU_WORKCLOCK(10); + GET_MODRM_PCBYTE(port); + cpu_out_w(port, CPU_AX); +} + +void +OUT_IbEAX(void) +{ + UINT port; + + CPU_WORKCLOCK(10); + GET_MODRM_PCBYTE(port); + cpu_out_d(port, CPU_EAX); +} + +/* + * convert + */ +void +CWD(void) +{ + + CPU_WORKCLOCK(2); + if (CPU_AX & 0x8000) { + CPU_DX = 0xffff; + } else { + CPU_DX = 0; + } +} + +void +CDQ(void) +{ + + CPU_WORKCLOCK(2); + if (CPU_EAX & 0x80000000) { + CPU_EDX = 0xffffffff; + } else { + CPU_EDX = 0; + } +} + +void +CBW(void) +{ + UINT16 tmp; + + CPU_WORKCLOCK(2); + tmp = __CBW(CPU_AL); + CPU_AX = tmp; +} + +void +CWDE(void) +{ + UINT32 tmp; + + CPU_WORKCLOCK(2); + tmp = __CWDE(CPU_AX); + CPU_EAX = tmp; +} + +/* + * MOVSx + */ +void +MOVSX_GwEb(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA8(op, src, out, 2, 5); + *out = __CBW(src); +} + +void +MOVSX_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + *out = (UINT16)src; +} + +void +MOVSX_GdEb(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA8(op, src, out, 2, 5); + *out = __CBD(src); +} + +void +MOVSX_GdEw(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA16(op, src, out, 2, 5); + *out = __CWDE(src); +} + +/* + * MOVZx + */ +void +MOVZX_GwEb(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA8(op, src, out, 2, 5); + *out = (UINT8)src; +} + +void +MOVZX_GwEw(void) +{ + UINT16 *out; + UINT32 op, src; + + PREPART_REG16_EA(op, src, out, 2, 5); + *out = (UINT16)src; +} + +void +MOVZX_GdEb(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA8(op, src, out, 2, 5); + *out = (UINT8)src; +} + +void +MOVZX_GdEw(void) +{ + UINT32 *out; + UINT32 op, src; + + PREPART_REG32_EA16(op, src, out, 2, 5); + *out = (UINT16)src; } \ No newline at end of file diff --git a/i386c/ia32/instructions/data_trans.h b/i386c/ia32/instructions/data_trans.h old mode 100755 new mode 100644 index 4fdc2ee2..df8a8f37 --- a/i386c/ia32/instructions/data_trans.h +++ b/i386c/ia32/instructions/data_trans.h @@ -1,284 +1,284 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_DATA_TRANS_H__ -#define IA32_CPU_INSTRUCTION_DATA_TRANS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * MOV - */ -void MOV_EbGb(void); -void MOV_EwGw(void); -void MOV_EdGd(void); -void MOV_GbEb(void); -void MOV_GwEw(void); -void MOV_GdEd(void); -void MOV_EwSw(void); -void MOV_EdSw(void); -void MOV_SwEw(void); -void MOV_ALOb(void); -void MOV_AXOw(void); -void MOV_EAXOd(void); -void MOV_ObAL(void); -void MOV_OwAX(void); -void MOV_OdEAX(void); -void MOV_EbIb(void); -void MOV_EwIw(void); -void MOV_EdId(void); -void MOV_ALIb(void); -void MOV_CLIb(void); -void MOV_DLIb(void); -void MOV_BLIb(void); -void MOV_AHIb(void); -void MOV_CHIb(void); -void MOV_DHIb(void); -void MOV_BHIb(void); -void MOV_AXIw(void); -void MOV_CXIw(void); -void MOV_DXIw(void); -void MOV_BXIw(void); -void MOV_SPIw(void); -void MOV_BPIw(void); -void MOV_SIIw(void); -void MOV_DIIw(void); -void MOV_EAXId(void); -void MOV_ECXId(void); -void MOV_EDXId(void); -void MOV_EBXId(void); -void MOV_ESPId(void); -void MOV_EBPId(void); -void MOV_ESIId(void); -void MOV_EDIId(void); - -/* - * CMOVcc - */ -void CMOVO_GwEw(void); -void CMOVO_GdEd(void); -void CMOVNO_GwEw(void); -void CMOVNO_GdEd(void); -void CMOVC_GwEw(void); -void CMOVC_GdEd(void); -void CMOVNC_GwEw(void); -void CMOVNC_GdEd(void); -void CMOVZ_GwEw(void); -void CMOVZ_GdEd(void); -void CMOVNZ_GwEw(void); -void CMOVNZ_GdEd(void); -void CMOVA_GwEw(void); -void CMOVA_GdEd(void); -void CMOVNA_GwEw(void); -void CMOVNA_GdEd(void); -void CMOVS_GwEw(void); -void CMOVS_GdEd(void); -void CMOVNS_GwEw(void); -void CMOVNS_GdEd(void); -void CMOVP_GwEw(void); -void CMOVP_GdEd(void); -void CMOVNP_GwEw(void); -void CMOVNP_GdEd(void); -void CMOVL_GwEw(void); -void CMOVL_GdEd(void); -void CMOVNL_GwEw(void); -void CMOVNL_GdEd(void); -void CMOVLE_GwEw(void); -void CMOVLE_GdEd(void); -void CMOVNLE_GwEw(void); -void CMOVNLE_GdEd(void); - -/* - * XCHG - */ -void XCHG_EbGb(void); -void XCHG_EwGw(void); -void XCHG_EdGd(void); -void XCHG_CXAX(void); -void XCHG_DXAX(void); -void XCHG_BXAX(void); -void XCHG_SPAX(void); -void XCHG_BPAX(void); -void XCHG_SIAX(void); -void XCHG_DIAX(void); -void XCHG_ECXEAX(void); -void XCHG_EDXEAX(void); -void XCHG_EBXEAX(void); -void XCHG_ESPEAX(void); -void XCHG_EBPEAX(void); -void XCHG_ESIEAX(void); -void XCHG_EDIEAX(void); - -/* - * BSWAP - */ -void BSWAP_EAX(void); -void BSWAP_ECX(void); -void BSWAP_EDX(void); -void BSWAP_EBX(void); -void BSWAP_ESP(void); -void BSWAP_EBP(void); -void BSWAP_ESI(void); -void BSWAP_EDI(void); - -/* - * XADD - */ -void XADD_EbGb(void); -void XADD_EwGw(void); -void XADD_EdGd(void); - -/* - * CMPXCHG - */ -void CMPXCHG_EbGb(void); -void CMPXCHG_EwGw(void); -void CMPXCHG_EdGd(void); -void CPUCALL CMPXCHG8B(UINT32); - -/* - * PUSH - */ -void PUSH_AX(void); -void PUSH_CX(void); -void PUSH_DX(void); -void PUSH_BX(void); -void PUSH_SP(void); -void PUSH_BP(void); -void PUSH_SI(void); -void PUSH_DI(void); -void PUSH_EAX(void); -void PUSH_ECX(void); -void PUSH_EDX(void); -void PUSH_EBX(void); -void PUSH_ESP(void); -void PUSH_EBP(void); -void PUSH_ESI(void); -void PUSH_EDI(void); -void PUSH_Ib(void); -void PUSH_Iw(void); -void PUSH_Id(void); -void PUSH16_ES(void); -void PUSH16_CS(void); -void PUSH16_SS(void); -void PUSH16_DS(void); -void PUSH16_FS(void); -void PUSH16_GS(void); -void PUSH32_ES(void); -void PUSH32_CS(void); -void PUSH32_SS(void); -void PUSH32_DS(void); -void PUSH32_FS(void); -void PUSH32_GS(void); - -void CPUCALL PUSH_Ew(UINT32); -void CPUCALL PUSH_Ed(UINT32); - -/* - * POP - */ -void POP_AX(void); -void POP_CX(void); -void POP_DX(void); -void POP_BX(void); -void POP_SP(void); -void POP_BP(void); -void POP_SI(void); -void POP_DI(void); -void POP_EAX(void); -void POP_ECX(void); -void POP_EDX(void); -void POP_EBX(void); -void POP_ESP(void); -void POP_EBP(void); -void POP_ESI(void); -void POP_EDI(void); -void POP_Ew(void); -void POP_Ed(void); -void POP16_ES(void); -void POP32_ES(void); -void POP16_SS(void); -void POP32_SS(void); -void POP16_DS(void); -void POP32_DS(void); -void POP16_FS(void); -void POP32_FS(void); -void POP16_GS(void); -void POP32_GS(void); - -void CPUCALL POP_Ew_G5(UINT32); -void CPUCALL POP_Ed_G5(UINT32); - -/* - * PUSHA/POPA - */ -void PUSHA(void); -void PUSHAD(void); -void POPA(void); -void POPAD(void); - -/* - * in/out - */ -void IN_ALDX(void); -void IN_AXDX(void); -void IN_EAXDX(void); -void IN_ALIb(void); -void IN_AXIb(void); -void IN_EAXIb(void); -void OUT_DXAL(void); -void OUT_DXAX(void); -void OUT_DXEAX(void); -void OUT_IbAL(void); -void OUT_IbAX(void); -void OUT_IbEAX(void); - -/* - * convert - */ -void CWD(void); -void CDQ(void); -void CBW(void); -void CWDE(void); - -/* - * MOVSx/MOVZx - */ -void MOVSX_GwEb(void); -void MOVSX_GwEw(void); -void MOVSX_GdEb(void); -void MOVSX_GdEw(void); -void MOVZX_GwEb(void); -void MOVZX_GwEw(void); -void MOVZX_GdEb(void); -void MOVZX_GdEw(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_DATA_TRANS_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_DATA_TRANS_H__ +#define IA32_CPU_INSTRUCTION_DATA_TRANS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * MOV + */ +void MOV_EbGb(void); +void MOV_EwGw(void); +void MOV_EdGd(void); +void MOV_GbEb(void); +void MOV_GwEw(void); +void MOV_GdEd(void); +void MOV_EwSw(void); +void MOV_EdSw(void); +void MOV_SwEw(void); +void MOV_ALOb(void); +void MOV_AXOw(void); +void MOV_EAXOd(void); +void MOV_ObAL(void); +void MOV_OwAX(void); +void MOV_OdEAX(void); +void MOV_EbIb(void); +void MOV_EwIw(void); +void MOV_EdId(void); +void MOV_ALIb(void); +void MOV_CLIb(void); +void MOV_DLIb(void); +void MOV_BLIb(void); +void MOV_AHIb(void); +void MOV_CHIb(void); +void MOV_DHIb(void); +void MOV_BHIb(void); +void MOV_AXIw(void); +void MOV_CXIw(void); +void MOV_DXIw(void); +void MOV_BXIw(void); +void MOV_SPIw(void); +void MOV_BPIw(void); +void MOV_SIIw(void); +void MOV_DIIw(void); +void MOV_EAXId(void); +void MOV_ECXId(void); +void MOV_EDXId(void); +void MOV_EBXId(void); +void MOV_ESPId(void); +void MOV_EBPId(void); +void MOV_ESIId(void); +void MOV_EDIId(void); + +/* + * CMOVcc + */ +void CMOVO_GwEw(void); +void CMOVO_GdEd(void); +void CMOVNO_GwEw(void); +void CMOVNO_GdEd(void); +void CMOVC_GwEw(void); +void CMOVC_GdEd(void); +void CMOVNC_GwEw(void); +void CMOVNC_GdEd(void); +void CMOVZ_GwEw(void); +void CMOVZ_GdEd(void); +void CMOVNZ_GwEw(void); +void CMOVNZ_GdEd(void); +void CMOVA_GwEw(void); +void CMOVA_GdEd(void); +void CMOVNA_GwEw(void); +void CMOVNA_GdEd(void); +void CMOVS_GwEw(void); +void CMOVS_GdEd(void); +void CMOVNS_GwEw(void); +void CMOVNS_GdEd(void); +void CMOVP_GwEw(void); +void CMOVP_GdEd(void); +void CMOVNP_GwEw(void); +void CMOVNP_GdEd(void); +void CMOVL_GwEw(void); +void CMOVL_GdEd(void); +void CMOVNL_GwEw(void); +void CMOVNL_GdEd(void); +void CMOVLE_GwEw(void); +void CMOVLE_GdEd(void); +void CMOVNLE_GwEw(void); +void CMOVNLE_GdEd(void); + +/* + * XCHG + */ +void XCHG_EbGb(void); +void XCHG_EwGw(void); +void XCHG_EdGd(void); +void XCHG_CXAX(void); +void XCHG_DXAX(void); +void XCHG_BXAX(void); +void XCHG_SPAX(void); +void XCHG_BPAX(void); +void XCHG_SIAX(void); +void XCHG_DIAX(void); +void XCHG_ECXEAX(void); +void XCHG_EDXEAX(void); +void XCHG_EBXEAX(void); +void XCHG_ESPEAX(void); +void XCHG_EBPEAX(void); +void XCHG_ESIEAX(void); +void XCHG_EDIEAX(void); + +/* + * BSWAP + */ +void BSWAP_EAX(void); +void BSWAP_ECX(void); +void BSWAP_EDX(void); +void BSWAP_EBX(void); +void BSWAP_ESP(void); +void BSWAP_EBP(void); +void BSWAP_ESI(void); +void BSWAP_EDI(void); + +/* + * XADD + */ +void XADD_EbGb(void); +void XADD_EwGw(void); +void XADD_EdGd(void); + +/* + * CMPXCHG + */ +void CMPXCHG_EbGb(void); +void CMPXCHG_EwGw(void); +void CMPXCHG_EdGd(void); +void CPUCALL CMPXCHG8B(UINT32); + +/* + * PUSH + */ +void PUSH_AX(void); +void PUSH_CX(void); +void PUSH_DX(void); +void PUSH_BX(void); +void PUSH_SP(void); +void PUSH_BP(void); +void PUSH_SI(void); +void PUSH_DI(void); +void PUSH_EAX(void); +void PUSH_ECX(void); +void PUSH_EDX(void); +void PUSH_EBX(void); +void PUSH_ESP(void); +void PUSH_EBP(void); +void PUSH_ESI(void); +void PUSH_EDI(void); +void PUSH_Ib(void); +void PUSH_Iw(void); +void PUSH_Id(void); +void PUSH16_ES(void); +void PUSH16_CS(void); +void PUSH16_SS(void); +void PUSH16_DS(void); +void PUSH16_FS(void); +void PUSH16_GS(void); +void PUSH32_ES(void); +void PUSH32_CS(void); +void PUSH32_SS(void); +void PUSH32_DS(void); +void PUSH32_FS(void); +void PUSH32_GS(void); + +void CPUCALL PUSH_Ew(UINT32); +void CPUCALL PUSH_Ed(UINT32); + +/* + * POP + */ +void POP_AX(void); +void POP_CX(void); +void POP_DX(void); +void POP_BX(void); +void POP_SP(void); +void POP_BP(void); +void POP_SI(void); +void POP_DI(void); +void POP_EAX(void); +void POP_ECX(void); +void POP_EDX(void); +void POP_EBX(void); +void POP_ESP(void); +void POP_EBP(void); +void POP_ESI(void); +void POP_EDI(void); +void POP_Ew(void); +void POP_Ed(void); +void POP16_ES(void); +void POP32_ES(void); +void POP16_SS(void); +void POP32_SS(void); +void POP16_DS(void); +void POP32_DS(void); +void POP16_FS(void); +void POP32_FS(void); +void POP16_GS(void); +void POP32_GS(void); + +void CPUCALL POP_Ew_G5(UINT32); +void CPUCALL POP_Ed_G5(UINT32); + +/* + * PUSHA/POPA + */ +void PUSHA(void); +void PUSHAD(void); +void POPA(void); +void POPAD(void); + +/* + * in/out + */ +void IN_ALDX(void); +void IN_AXDX(void); +void IN_EAXDX(void); +void IN_ALIb(void); +void IN_AXIb(void); +void IN_EAXIb(void); +void OUT_DXAL(void); +void OUT_DXAX(void); +void OUT_DXEAX(void); +void OUT_IbAL(void); +void OUT_IbAX(void); +void OUT_IbEAX(void); + +/* + * convert + */ +void CWD(void); +void CDQ(void); +void CBW(void); +void CWDE(void); + +/* + * MOVSx/MOVZx + */ +void MOVSX_GwEb(void); +void MOVSX_GwEw(void); +void MOVSX_GdEb(void); +void MOVSX_GdEw(void); +void MOVZX_GwEb(void); +void MOVZX_GwEw(void); +void MOVZX_GdEb(void); +void MOVZX_GdEw(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_DATA_TRANS_H__ */ diff --git a/i386c/ia32/instructions/dec_arith.c b/i386c/ia32/instructions/dec_arith.c old mode 100755 new mode 100644 index f50a3232..fd54b46d --- a/i386c/ia32/instructions/dec_arith.c +++ b/i386c/ia32/instructions/dec_arith.c @@ -1,300 +1,300 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" - -#include "dec_arith.h" - - -/* - * decimal arithmetic - */ -void -DAA(void) -{ -#if defined(IA32_CPU_ENABLE_XC) - UINT8 __s = CPU_AL; - UINT8 __r = __s; - UINT8 __R; - UINT8 __f; - XC_STORE_FLAGL(); -#endif - - CPU_WORKCLOCK(3); - if ((CPU_FLAGL & A_FLAG) || (CPU_AL & 0x0f) > 9) { - CPU_FLAGL |= A_FLAG; - CPU_FLAGL |= (((UINT16)CPU_AL + 6) >> 8) & 1; /* C_FLAG */ - CPU_AL += 6; - } - if ((CPU_FLAGL & C_FLAG) || (CPU_AL & 0xf0) > 0x90) { - CPU_FLAGL |= C_FLAG; - CPU_AL += 0x60; - } - CPU_FLAGL &= A_FLAG | C_FLAG; - CPU_FLAGL |= szpcflag[CPU_AL] & (S_FLAG | Z_FLAG | P_FLAG); - -#if defined(IA32_CPU_ENABLE_XC) - __R = CPU_AL; - - __asm__ __volatile__( - "pushf\n\t" - "pushl %%eax\n\t" - "movb %3, %%ah\n\t" - "sahf\n\t" - "movb %2, %%al\n\t" - "daa\n\t" - "movb %%al, %0\n\t" - "lahf\n\t" - "movb %%ah, %1\n\t" - "popl %%eax\n\t" - "popf\n\t" - : "=m" (__r), "=m" (__f) - : "0" (__r), "m" (__xc_flagl) - : "eax"); - if ((__R != __r) || - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0)) { - ia32_warning("XC_DAA: __s = %02x", __s); - ia32_warning("XC_DAA: __R = %02x, __r = %02x", __R, __r); - ia32_warning("XC_DAA: CPU_FLAGL = %02x, __f = %02x, " - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); - ia32_warning("XC_DAA: __xc_flagl = %02x", __xc_flagl); - __ASSERT(__R == __r); - __ASSERT(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); - } -#endif -} - -void -DAS(void) -{ - UINT32 OLD_AL = CPU_AL; - UINT32 OLD_C_FLAG = CPU_FLAGL & C_FLAG; -#if defined(IA32_CPU_ENABLE_XC) - UINT8 __s = CPU_AL; - UINT8 __r = __s; - UINT8 __R; - UINT8 __f; - XC_STORE_FLAGL(); -#endif - - CPU_WORKCLOCK(3); - if ((CPU_FLAGL & A_FLAG) || (CPU_AL & 0x0f) > 9) { - CPU_FLAGL |= A_FLAG; - CPU_FLAGL |= (((UINT16)CPU_AL - 6) >> 8) & 1; /* C_FLAG */ - CPU_AL -= 6; - } - if (OLD_C_FLAG || OLD_AL > 0x99) { - CPU_FLAGL |= C_FLAG; - CPU_AL -= 0x60; - } - CPU_FLAGL &= A_FLAG | C_FLAG; - CPU_FLAGL |= szpcflag[CPU_AL] & (S_FLAG | Z_FLAG | P_FLAG); - -#if defined(IA32_CPU_ENABLE_XC) - __R = CPU_AL; - - __asm__ __volatile__( - "pushf\n\t" - "pushl %%eax\n\t" - "movb %3, %%ah\n\t" - "sahf\n\t" - "movb %2, %%al\n\t" - "das\n\t" - "movb %%al, %0\n\t" - "lahf\n\t" - "movb %%ah, %1\n\t" - "popl %%eax\n\t" - "popf\n\t" - : "=m" (__r), "=m" (__f) - : "0" (__r), "m" (__xc_flagl) - : "eax"); - if ((__R != __r) || - (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0)) { - ia32_warning("XC_DAS: __s = %02x", __s); - ia32_warning("XC_DAS: __R = %02x, __r = %02x", __R, __r); - ia32_warning("XC_DAS: CPU_FLAGL = %02x, __f = %02x, " - "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); - ia32_warning("XC_DAS: __xc_flagl = %02x", __xc_flagl); - __ASSERT(__R == __r); - __ASSERT(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); - } -#endif -} - -void -AAA(void) -{ -#if defined(IA32_CPU_ENABLE_XC) - UINT8 __s = CPU_AL; - UINT8 __s1 = CPU_AH; - UINT8 __r = __s; - UINT8 __r1; - UINT8 __R; - UINT8 __R1; - UINT8 __f; - XC_STORE_FLAGL(); -#endif - - CPU_WORKCLOCK(3); - if ((CPU_FLAGL & A_FLAG) || (CPU_AL & 0x0f) > 9) { - CPU_AX += 6; - CPU_AH++; - CPU_FLAGL |= (A_FLAG | C_FLAG); - } else { - CPU_FLAGL &= ~(A_FLAG | C_FLAG); - } - CPU_AL &= 0x0f; - -#if defined(IA32_CPU_ENABLE_XC) - __R = CPU_AL; - __R1 = CPU_AH; - - __asm__ __volatile__( - "pushf\n\t" - "pushl %%eax\n\t" - "movb %4, %%ah\n\t" - "sahf\n\t" - "movb %3, %%al\n\t" - "aaa\n\t" - "movb %%al, %0\n\t" - "movb %%ah, %1\n\t" - "lahf\n\t" - "movb %%ah, %2\n\t" - "popl %%eax\n\t" - "popf\n\t" - : "=m" (__r), "=m" (__r1), "=m" (__f) - : "0" (__r), "m" (__xc_flagl) - : "eax"); - if ((__R != __r) || - (__R1 != __r1) || - (((__f ^ CPU_FLAGL) & (A_FLAG|C_FLAG)) != 0)) { - ia32_warning("XC_AAA: __s = %02x, __s1 = %02x", __s, __s1); - ia32_warning("XC_AAA: __R = %02x, __R1 = %02x", __R, __R1); - ia32_warning("XC_AAA: __r = %02x, __r1 = %02x", __r, __r1); - ia32_warning("XC_AAA: CPU_FLAGL = %02x, __f = %02x, " - "mask = %02x", CPU_FLAGL, __f, (A_FLAG|C_FLAG)); - ia32_warning("XC_AAA: __xc_flagl = %02x", __xc_flagl); - __ASSERT(__R == __r); - __ASSERT(__R1 == __r1); - __ASSERT(((__f ^ CPU_FLAGL) & (A_FLAG|C_FLAG)) == 0); - } -#endif -} - -void -AAS(void) -{ -#if defined(IA32_CPU_ENABLE_XC) - UINT8 __s = CPU_AL; - UINT8 __s1 = CPU_AH; - UINT8 __r = __s; - UINT8 __r1; - UINT8 __R; - UINT8 __R1; - UINT8 __f; - XC_STORE_FLAGL(); -#endif - - CPU_WORKCLOCK(3); - if ((CPU_FLAGL & A_FLAG) || (CPU_AL & 0x0f) > 9) { - CPU_AX -= 6; - CPU_AH--; - CPU_FLAGL |= (A_FLAG | C_FLAG); - } else { - CPU_FLAGL &= ~(A_FLAG | C_FLAG); - } - CPU_AL &= 0x0f; - -#if defined(IA32_CPU_ENABLE_XC) - __R = CPU_AL; - __R1 = CPU_AH; - - __asm__ __volatile__( - "pushf\n\t" - "pushl %%eax\n\t" - "movb %4, %%ah\n\t" - "sahf\n\t" - "movb %3, %%al\n\t" - "aas\n\t" - "movb %%al, %0\n\t" - "movb %%ah, %1\n\t" - "lahf\n\t" - "movb %%ah, %2\n\t" - "popl %%eax\n\t" - "popf\n\t" - : "=m" (__r), "=m" (__r1), "=m" (__f) - : "0" (__r), "m" (__xc_flagl) - : "eax"); - if ((__R != __r) || - (__R1 != __r1) || - (((__f ^ CPU_FLAGL) & (A_FLAG|C_FLAG)) != 0)) { - ia32_warning("XC_AAS: __s = %02x, __s1 = %02x", __s, __s1); - ia32_warning("XC_AAS: __R = %02x, __R1 = %02x", __R, __R1); - ia32_warning("XC_AAS: __r = %02x, __r1 = %02x", __r, __r1); - ia32_warning("XC_AAS: CPU_FLAGL = %02x, __f = %02x, " - "mask = %02x", CPU_FLAGL, __f, (A_FLAG|C_FLAG)); - ia32_warning("XC_AAS: __xc_flagl = %02x", __xc_flagl); - __ASSERT(__R == __r); - __ASSERT(__R1 == __r1); - __ASSERT(((__f ^ CPU_FLAGL) & (A_FLAG|C_FLAG)) == 0); - } -#endif -} - -void -AAM(void) -{ - UINT8 base; - UINT8 al; - - CPU_WORKCLOCK(16); - GET_MODRM_PCBYTE(base); - if (base != 0) { - al = CPU_AL; - CPU_AH = al / base; - CPU_AL = al % base; - // A_FLAG is undefined, but real i386 may clear this flag. - CPU_FLAGL &= ~(A_FLAG | S_FLAG | Z_FLAG | P_FLAG); - CPU_FLAGL |= szpcflag[CPU_AL]; - return; - } - EXCEPTION(DE_EXCEPTION, 0); -} - -void -AAD(void) -{ - UINT32 base; - - CPU_WORKCLOCK(14); - GET_MODRM_PCBYTE(base); - CPU_AL += (UINT8)(CPU_AH * base); - CPU_AH = 0; - // A_FLAG is undefined, but real i386 may clear this flag. - CPU_FLAGL &= ~(A_FLAG | S_FLAG | Z_FLAG | P_FLAG); - CPU_FLAGL |= szpcflag[CPU_AL]; +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" + +#include "dec_arith.h" + + +/* + * decimal arithmetic + */ +void +DAA(void) +{ +#if defined(IA32_CPU_ENABLE_XC) + UINT8 __s = CPU_AL; + UINT8 __r = __s; + UINT8 __R; + UINT8 __f; + XC_STORE_FLAGL(); +#endif + + CPU_WORKCLOCK(3); + if ((CPU_FLAGL & A_FLAG) || (CPU_AL & 0x0f) > 9) { + CPU_FLAGL |= A_FLAG; + CPU_FLAGL |= (((UINT16)CPU_AL + 6) >> 8) & 1; /* C_FLAG */ + CPU_AL += 6; + } + if ((CPU_FLAGL & C_FLAG) || (CPU_AL & 0xf0) > 0x90) { + CPU_FLAGL |= C_FLAG; + CPU_AL += 0x60; + } + CPU_FLAGL &= A_FLAG | C_FLAG; + CPU_FLAGL |= szpcflag[CPU_AL] & (S_FLAG | Z_FLAG | P_FLAG); + +#if defined(IA32_CPU_ENABLE_XC) + __R = CPU_AL; + + __asm__ __volatile__( + "pushf\n\t" + "pushl %%eax\n\t" + "movb %3, %%ah\n\t" + "sahf\n\t" + "movb %2, %%al\n\t" + "daa\n\t" + "movb %%al, %0\n\t" + "lahf\n\t" + "movb %%ah, %1\n\t" + "popl %%eax\n\t" + "popf\n\t" + : "=m" (__r), "=m" (__f) + : "0" (__r), "m" (__xc_flagl) + : "eax"); + if ((__R != __r) || + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0)) { + ia32_warning("XC_DAA: __s = %02x", __s); + ia32_warning("XC_DAA: __R = %02x, __r = %02x", __R, __r); + ia32_warning("XC_DAA: CPU_FLAGL = %02x, __f = %02x, " + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); + ia32_warning("XC_DAA: __xc_flagl = %02x", __xc_flagl); + __ASSERT(__R == __r); + __ASSERT(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); + } +#endif +} + +void +DAS(void) +{ + UINT32 OLD_AL = CPU_AL; + UINT32 OLD_C_FLAG = CPU_FLAGL & C_FLAG; +#if defined(IA32_CPU_ENABLE_XC) + UINT8 __s = CPU_AL; + UINT8 __r = __s; + UINT8 __R; + UINT8 __f; + XC_STORE_FLAGL(); +#endif + + CPU_WORKCLOCK(3); + if ((CPU_FLAGL & A_FLAG) || (CPU_AL & 0x0f) > 9) { + CPU_FLAGL |= A_FLAG; + CPU_FLAGL |= (((UINT16)CPU_AL - 6) >> 8) & 1; /* C_FLAG */ + CPU_AL -= 6; + } + if (OLD_C_FLAG || OLD_AL > 0x99) { + CPU_FLAGL |= C_FLAG; + CPU_AL -= 0x60; + } + CPU_FLAGL &= A_FLAG | C_FLAG; + CPU_FLAGL |= szpcflag[CPU_AL] & (S_FLAG | Z_FLAG | P_FLAG); + +#if defined(IA32_CPU_ENABLE_XC) + __R = CPU_AL; + + __asm__ __volatile__( + "pushf\n\t" + "pushl %%eax\n\t" + "movb %3, %%ah\n\t" + "sahf\n\t" + "movb %2, %%al\n\t" + "das\n\t" + "movb %%al, %0\n\t" + "lahf\n\t" + "movb %%ah, %1\n\t" + "popl %%eax\n\t" + "popf\n\t" + : "=m" (__r), "=m" (__f) + : "0" (__r), "m" (__xc_flagl) + : "eax"); + if ((__R != __r) || + (((__f ^ CPU_FLAGL) & SZAPC_FLAG) != 0)) { + ia32_warning("XC_DAS: __s = %02x", __s); + ia32_warning("XC_DAS: __R = %02x, __r = %02x", __R, __r); + ia32_warning("XC_DAS: CPU_FLAGL = %02x, __f = %02x, " + "mask = %02x", CPU_FLAGL, __f, SZAPC_FLAG); + ia32_warning("XC_DAS: __xc_flagl = %02x", __xc_flagl); + __ASSERT(__R == __r); + __ASSERT(((__f ^ CPU_FLAGL) & SZAPC_FLAG) == 0); + } +#endif +} + +void +AAA(void) +{ +#if defined(IA32_CPU_ENABLE_XC) + UINT8 __s = CPU_AL; + UINT8 __s1 = CPU_AH; + UINT8 __r = __s; + UINT8 __r1; + UINT8 __R; + UINT8 __R1; + UINT8 __f; + XC_STORE_FLAGL(); +#endif + + CPU_WORKCLOCK(3); + if ((CPU_FLAGL & A_FLAG) || (CPU_AL & 0x0f) > 9) { + CPU_AX += 6; + CPU_AH++; + CPU_FLAGL |= (A_FLAG | C_FLAG); + } else { + CPU_FLAGL &= ~(A_FLAG | C_FLAG); + } + CPU_AL &= 0x0f; + +#if defined(IA32_CPU_ENABLE_XC) + __R = CPU_AL; + __R1 = CPU_AH; + + __asm__ __volatile__( + "pushf\n\t" + "pushl %%eax\n\t" + "movb %4, %%ah\n\t" + "sahf\n\t" + "movb %3, %%al\n\t" + "aaa\n\t" + "movb %%al, %0\n\t" + "movb %%ah, %1\n\t" + "lahf\n\t" + "movb %%ah, %2\n\t" + "popl %%eax\n\t" + "popf\n\t" + : "=m" (__r), "=m" (__r1), "=m" (__f) + : "0" (__r), "m" (__xc_flagl) + : "eax"); + if ((__R != __r) || + (__R1 != __r1) || + (((__f ^ CPU_FLAGL) & (A_FLAG|C_FLAG)) != 0)) { + ia32_warning("XC_AAA: __s = %02x, __s1 = %02x", __s, __s1); + ia32_warning("XC_AAA: __R = %02x, __R1 = %02x", __R, __R1); + ia32_warning("XC_AAA: __r = %02x, __r1 = %02x", __r, __r1); + ia32_warning("XC_AAA: CPU_FLAGL = %02x, __f = %02x, " + "mask = %02x", CPU_FLAGL, __f, (A_FLAG|C_FLAG)); + ia32_warning("XC_AAA: __xc_flagl = %02x", __xc_flagl); + __ASSERT(__R == __r); + __ASSERT(__R1 == __r1); + __ASSERT(((__f ^ CPU_FLAGL) & (A_FLAG|C_FLAG)) == 0); + } +#endif +} + +void +AAS(void) +{ +#if defined(IA32_CPU_ENABLE_XC) + UINT8 __s = CPU_AL; + UINT8 __s1 = CPU_AH; + UINT8 __r = __s; + UINT8 __r1; + UINT8 __R; + UINT8 __R1; + UINT8 __f; + XC_STORE_FLAGL(); +#endif + + CPU_WORKCLOCK(3); + if ((CPU_FLAGL & A_FLAG) || (CPU_AL & 0x0f) > 9) { + CPU_AX -= 6; + CPU_AH--; + CPU_FLAGL |= (A_FLAG | C_FLAG); + } else { + CPU_FLAGL &= ~(A_FLAG | C_FLAG); + } + CPU_AL &= 0x0f; + +#if defined(IA32_CPU_ENABLE_XC) + __R = CPU_AL; + __R1 = CPU_AH; + + __asm__ __volatile__( + "pushf\n\t" + "pushl %%eax\n\t" + "movb %4, %%ah\n\t" + "sahf\n\t" + "movb %3, %%al\n\t" + "aas\n\t" + "movb %%al, %0\n\t" + "movb %%ah, %1\n\t" + "lahf\n\t" + "movb %%ah, %2\n\t" + "popl %%eax\n\t" + "popf\n\t" + : "=m" (__r), "=m" (__r1), "=m" (__f) + : "0" (__r), "m" (__xc_flagl) + : "eax"); + if ((__R != __r) || + (__R1 != __r1) || + (((__f ^ CPU_FLAGL) & (A_FLAG|C_FLAG)) != 0)) { + ia32_warning("XC_AAS: __s = %02x, __s1 = %02x", __s, __s1); + ia32_warning("XC_AAS: __R = %02x, __R1 = %02x", __R, __R1); + ia32_warning("XC_AAS: __r = %02x, __r1 = %02x", __r, __r1); + ia32_warning("XC_AAS: CPU_FLAGL = %02x, __f = %02x, " + "mask = %02x", CPU_FLAGL, __f, (A_FLAG|C_FLAG)); + ia32_warning("XC_AAS: __xc_flagl = %02x", __xc_flagl); + __ASSERT(__R == __r); + __ASSERT(__R1 == __r1); + __ASSERT(((__f ^ CPU_FLAGL) & (A_FLAG|C_FLAG)) == 0); + } +#endif +} + +void +AAM(void) +{ + UINT8 base; + UINT8 al; + + CPU_WORKCLOCK(16); + GET_MODRM_PCBYTE(base); + if (base != 0) { + al = CPU_AL; + CPU_AH = al / base; + CPU_AL = al % base; + // A_FLAG is undefined, but real i386 may clear this flag. + CPU_FLAGL &= ~(A_FLAG | S_FLAG | Z_FLAG | P_FLAG); + CPU_FLAGL |= szpcflag[CPU_AL]; + return; + } + EXCEPTION(DE_EXCEPTION, 0); +} + +void +AAD(void) +{ + UINT32 base; + + CPU_WORKCLOCK(14); + GET_MODRM_PCBYTE(base); + CPU_AL += (UINT8)(CPU_AH * base); + CPU_AH = 0; + // A_FLAG is undefined, but real i386 may clear this flag. + CPU_FLAGL &= ~(A_FLAG | S_FLAG | Z_FLAG | P_FLAG); + CPU_FLAGL |= szpcflag[CPU_AL]; } \ No newline at end of file diff --git a/i386c/ia32/instructions/dec_arith.h b/i386c/ia32/instructions/dec_arith.h old mode 100755 new mode 100644 index 87b4f4ee..11072a27 --- a/i386c/ia32/instructions/dec_arith.h +++ b/i386c/ia32/instructions/dec_arith.h @@ -1,47 +1,47 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_DEC_ARITH_H__ -#define IA32_CPU_INSTRUCTION_DEC_ARITH_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * decimal arithmetic - */ -void DAA(void); -void DAS(void); -void AAA(void); -void AAS(void); -void AAM(void); -void AAD(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_DEC_ARITH_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_DEC_ARITH_H__ +#define IA32_CPU_INSTRUCTION_DEC_ARITH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * decimal arithmetic + */ +void DAA(void); +void DAS(void); +void AAA(void); +void AAS(void); +void AAM(void); +void AAD(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_DEC_ARITH_H__ */ diff --git a/i386c/ia32/instructions/flag_ctrl.c b/i386c/ia32/instructions/flag_ctrl.c old mode 100755 new mode 100644 index 5346c2d0..06f508b0 --- a/i386c/ia32/instructions/flag_ctrl.c +++ b/i386c/ia32/instructions/flag_ctrl.c @@ -1,321 +1,321 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" - -#include "flag_ctrl.h" - - -/* - * flag contol instructions - */ -void -STC(void) -{ - - CPU_WORKCLOCK(2); - CPU_FLAGL |= C_FLAG; -} - -void -CLC(void) -{ - - CPU_WORKCLOCK(2); - CPU_FLAGL &= ~C_FLAG; -} - -void -CMC(void) -{ - - CPU_WORKCLOCK(2); - CPU_FLAGL ^= C_FLAG; -} - -void -CLD(void) -{ - - CPU_WORKCLOCK(2); - CPU_FLAG &= ~D_FLAG; -} - -void -STD(void) -{ - - CPU_WORKCLOCK(2); - CPU_FLAG |= D_FLAG; -} - -void -LAHF(void) -{ - - CPU_WORKCLOCK(2); - CPU_AH = (CPU_FLAGL & SZAPC_FLAG) | 0x2; /* SZ0A0P1C */ -} - -void -SAHF(void) -{ - - CPU_WORKCLOCK(2); - CPU_FLAGL = (CPU_AH & SZAPC_FLAG) | 0x2; /* SZ0A0P1C */ -} - -/* - * PUSHF/POPF - */ -void -PUSHF_Fw(void) -{ - - CPU_WORKCLOCK(3); - if (!CPU_STAT_PM || !CPU_STAT_VM86 || (CPU_STAT_IOPL == CPU_IOPL3)) { - UINT16 flags = REAL_FLAGREG; - flags = (flags & ALL_FLAG) | 2; - PUSH0_16(flags); - return; - } - /* VM86 && IOPL != 3 */ - EXCEPTION(GP_EXCEPTION, 0); -} - -void -PUSHFD_Fd(void) -{ - - CPU_WORKCLOCK(3); - if (!CPU_STAT_PM || !CPU_STAT_VM86 || (CPU_STAT_IOPL == CPU_IOPL3)) { - UINT32 flags = REAL_EFLAGREG & ~(RF_FLAG|VM_FLAG); - flags = (flags & ALL_EFLAG) | 2; - PUSH0_32(flags); - return; - } - /* VM86 && IOPL != 3 */ -#if defined(USE_VME) - if(CPU_CR4 & CPU_CR4_VME){ - if(CPU_EFLAG & VIP_FLAG){ - EXCEPTION(GP_EXCEPTION, 0); - }else{ - UINT32 flags = REAL_EFLAGREG & ~(RF_FLAG|VM_FLAG); - flags = (flags & ALL_EFLAG) | 2; - flags = (flags & ~I_FLAG) | ((flags & VIF_FLAG) >> 10); // VIF → IFにコピー - flags |= IOPL_FLAG; // IOPL == 3 の振りをする - PUSH0_32(flags); - return; - } - }else{ - EXCEPTION(GP_EXCEPTION, 0); - } -#else - EXCEPTION(GP_EXCEPTION, 0); -#endif -} - -void -POPF_Fw(void) -{ - UINT16 flags, mask; - - CPU_WORKCLOCK(3); - CPU_SET_PREV_ESP(); - if (!CPU_STAT_PM) { - /* Real Mode */ - POP0_16(flags); - mask = I_FLAG|IOPL_FLAG; - } else if (!CPU_STAT_VM86) { - /* Protected Mode */ - POP0_16(flags); - if (CPU_STAT_CPL == 0) { - mask = I_FLAG|IOPL_FLAG; - } else if (CPU_STAT_CPL <= CPU_STAT_IOPL) { - mask = I_FLAG; - } else { - mask = 0; - } - } else if (CPU_STAT_IOPL == CPU_IOPL3) { - /* Virtual-8086 Mode, IOPL == 3 */ - POP0_16(flags); - mask = I_FLAG; - } else { - EXCEPTION(GP_EXCEPTION, 0); - flags = 0; - mask = 0; - /* compiler happy */ - } - set_eflags(flags, mask); - CPU_CLEAR_PREV_ESP(); - IRQCHECKTERM(); -} - -void -POPFD_Fd(void) -{ - UINT32 flags, mask; - - CPU_WORKCLOCK(3); - CPU_SET_PREV_ESP(); - if (!CPU_STAT_PM) { - /* Real Mode */ - POP0_32(flags); - flags &= ~(RF_FLAG|VIF_FLAG|VIP_FLAG); - mask = I_FLAG|IOPL_FLAG|RF_FLAG|VIF_FLAG|VIP_FLAG; - } else if (!CPU_STAT_VM86) { - /* Protected Mode */ - POP0_32(flags); - flags &= ~RF_FLAG; - if (CPU_STAT_CPL == 0) { - flags &= ~(VIP_FLAG|VIF_FLAG); - mask = I_FLAG|IOPL_FLAG|RF_FLAG|VIF_FLAG|VIP_FLAG; - } else if (CPU_STAT_CPL <= CPU_STAT_IOPL) { - flags &= ~(VIP_FLAG|VIF_FLAG); - mask = I_FLAG|RF_FLAG|VIF_FLAG|VIP_FLAG; - } else { - mask = RF_FLAG; - } - } else if (CPU_STAT_IOPL == CPU_IOPL3) { - /* Virtual-8086 Mode, IOPL == 3 */ - POP0_32(flags); - mask = I_FLAG; - } else { - /* Virtual-8086 Mode, IOPL != 3 */ -#if defined(USE_VME) - if(CPU_CR4 & CPU_CR4_VME){ - if((CPU_EFLAG & VIP_FLAG) || (CPU_EFLAG & T_FLAG)){ - EXCEPTION(GP_EXCEPTION, 0); - flags = 0; - mask = 0; - }else{ - POP0_32(flags); - flags = (flags & ~VIF_FLAG) | ((flags & I_FLAG) << 10); // IF → VIFにコピー - mask = I_FLAG | IOPL_FLAG; // IF, IOPLは変更させない - } - }else{ - EXCEPTION(GP_EXCEPTION, 0); - flags = 0; - mask = 0; - } -#else - EXCEPTION(GP_EXCEPTION, 0); - flags = 0; - mask = 0; - /* compiler happy */ -#endif - } - set_eflags(flags, mask); - CPU_CLEAR_PREV_ESP(); - IRQCHECKTERM(); -} - -void -STI(void) -{ - - CPU_WORKCLOCK(2); - if (CPU_STAT_PM) { - if (!CPU_STAT_VM86) { - if (CPU_STAT_CPL > CPU_STAT_IOPL) { -#if defined(USE_VME) - if((CPU_CR4 & CPU_CR4_PVI) && CPU_STAT_CPL==3){ - if(CPU_EFLAG & VIP_FLAG){ - EXCEPTION(GP_EXCEPTION, 0); - }else{ - CPU_EFLAG |= VIF_FLAG; - return; - } - }else{ - EXCEPTION(GP_EXCEPTION, 0); - } -#else - EXCEPTION(GP_EXCEPTION, 0); -#endif - } - } else { - if (CPU_STAT_IOPL < 3) { -#if defined(USE_VME) - if(CPU_CR4 & CPU_CR4_VME){ - if(CPU_EFLAG & VIP_FLAG){ - EXCEPTION(GP_EXCEPTION, 0); - }else{ - CPU_EFLAG |= VIF_FLAG; - return; - } - }else{ - EXCEPTION(GP_EXCEPTION, 0); - } -#else - EXCEPTION(GP_EXCEPTION, 0); -#endif - } - } - } - CPU_FLAG |= I_FLAG; - CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG); - exec_1step(); - IRQCHECKTERM(); -} - -void -CLI(void) -{ - - CPU_WORKCLOCK(2); - if (CPU_STAT_PM) { - if (!CPU_STAT_VM86) { - if (CPU_STAT_CPL > CPU_STAT_IOPL) { -#if defined(USE_VME) - if((CPU_CR4 & CPU_CR4_PVI) && CPU_STAT_CPL==3){ - CPU_EFLAG &= ~VIF_FLAG; - return; - }else{ - EXCEPTION(GP_EXCEPTION, 0); - } -#else - EXCEPTION(GP_EXCEPTION, 0); -#endif - } - } else { - if (CPU_STAT_IOPL < 3) { -#if defined(USE_VME) - if(CPU_CR4 & CPU_CR4_VME){ - CPU_EFLAG &= ~VIF_FLAG; - return; - }else{ - EXCEPTION(GP_EXCEPTION, 0); - } -#else - EXCEPTION(GP_EXCEPTION, 0); -#endif - } - } - } - CPU_FLAG &= ~I_FLAG; - CPU_TRAP = 0; -} +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" + +#include "flag_ctrl.h" + + +/* + * flag contol instructions + */ +void +STC(void) +{ + + CPU_WORKCLOCK(2); + CPU_FLAGL |= C_FLAG; +} + +void +CLC(void) +{ + + CPU_WORKCLOCK(2); + CPU_FLAGL &= ~C_FLAG; +} + +void +CMC(void) +{ + + CPU_WORKCLOCK(2); + CPU_FLAGL ^= C_FLAG; +} + +void +CLD(void) +{ + + CPU_WORKCLOCK(2); + CPU_FLAG &= ~D_FLAG; +} + +void +STD(void) +{ + + CPU_WORKCLOCK(2); + CPU_FLAG |= D_FLAG; +} + +void +LAHF(void) +{ + + CPU_WORKCLOCK(2); + CPU_AH = (CPU_FLAGL & SZAPC_FLAG) | 0x2; /* SZ0A0P1C */ +} + +void +SAHF(void) +{ + + CPU_WORKCLOCK(2); + CPU_FLAGL = (CPU_AH & SZAPC_FLAG) | 0x2; /* SZ0A0P1C */ +} + +/* + * PUSHF/POPF + */ +void +PUSHF_Fw(void) +{ + + CPU_WORKCLOCK(3); + if (!CPU_STAT_PM || !CPU_STAT_VM86 || (CPU_STAT_IOPL == CPU_IOPL3)) { + UINT16 flags = REAL_FLAGREG; + flags = (flags & ALL_FLAG) | 2; + PUSH0_16(flags); + return; + } + /* VM86 && IOPL != 3 */ + EXCEPTION(GP_EXCEPTION, 0); +} + +void +PUSHFD_Fd(void) +{ + + CPU_WORKCLOCK(3); + if (!CPU_STAT_PM || !CPU_STAT_VM86 || (CPU_STAT_IOPL == CPU_IOPL3)) { + UINT32 flags = REAL_EFLAGREG & ~(RF_FLAG|VM_FLAG); + flags = (flags & ALL_EFLAG) | 2; + PUSH0_32(flags); + return; + } + /* VM86 && IOPL != 3 */ +#if defined(USE_VME) + if(CPU_CR4 & CPU_CR4_VME){ + if(CPU_EFLAG & VIP_FLAG){ + EXCEPTION(GP_EXCEPTION, 0); + }else{ + UINT32 flags = REAL_EFLAGREG & ~(RF_FLAG|VM_FLAG); + flags = (flags & ALL_EFLAG) | 2; + flags = (flags & ~I_FLAG) | ((flags & VIF_FLAG) >> 10); // VIF → IFにコピー + flags |= IOPL_FLAG; // IOPL == 3 の振りをする + PUSH0_32(flags); + return; + } + }else{ + EXCEPTION(GP_EXCEPTION, 0); + } +#else + EXCEPTION(GP_EXCEPTION, 0); +#endif +} + +void +POPF_Fw(void) +{ + UINT16 flags, mask; + + CPU_WORKCLOCK(3); + CPU_SET_PREV_ESP(); + if (!CPU_STAT_PM) { + /* Real Mode */ + POP0_16(flags); + mask = I_FLAG|IOPL_FLAG; + } else if (!CPU_STAT_VM86) { + /* Protected Mode */ + POP0_16(flags); + if (CPU_STAT_CPL == 0) { + mask = I_FLAG|IOPL_FLAG; + } else if (CPU_STAT_CPL <= CPU_STAT_IOPL) { + mask = I_FLAG; + } else { + mask = 0; + } + } else if (CPU_STAT_IOPL == CPU_IOPL3) { + /* Virtual-8086 Mode, IOPL == 3 */ + POP0_16(flags); + mask = I_FLAG; + } else { + EXCEPTION(GP_EXCEPTION, 0); + flags = 0; + mask = 0; + /* compiler happy */ + } + set_eflags(flags, mask); + CPU_CLEAR_PREV_ESP(); + IRQCHECKTERM(); +} + +void +POPFD_Fd(void) +{ + UINT32 flags, mask; + + CPU_WORKCLOCK(3); + CPU_SET_PREV_ESP(); + if (!CPU_STAT_PM) { + /* Real Mode */ + POP0_32(flags); + flags &= ~(RF_FLAG|VIF_FLAG|VIP_FLAG); + mask = I_FLAG|IOPL_FLAG|RF_FLAG|VIF_FLAG|VIP_FLAG; + } else if (!CPU_STAT_VM86) { + /* Protected Mode */ + POP0_32(flags); + flags &= ~RF_FLAG; + if (CPU_STAT_CPL == 0) { + flags &= ~(VIP_FLAG|VIF_FLAG); + mask = I_FLAG|IOPL_FLAG|RF_FLAG|VIF_FLAG|VIP_FLAG; + } else if (CPU_STAT_CPL <= CPU_STAT_IOPL) { + flags &= ~(VIP_FLAG|VIF_FLAG); + mask = I_FLAG|RF_FLAG|VIF_FLAG|VIP_FLAG; + } else { + mask = RF_FLAG; + } + } else if (CPU_STAT_IOPL == CPU_IOPL3) { + /* Virtual-8086 Mode, IOPL == 3 */ + POP0_32(flags); + mask = I_FLAG; + } else { + /* Virtual-8086 Mode, IOPL != 3 */ +#if defined(USE_VME) + if(CPU_CR4 & CPU_CR4_VME){ + if((CPU_EFLAG & VIP_FLAG) || (CPU_EFLAG & T_FLAG)){ + EXCEPTION(GP_EXCEPTION, 0); + flags = 0; + mask = 0; + }else{ + POP0_32(flags); + flags = (flags & ~VIF_FLAG) | ((flags & I_FLAG) << 10); // IF → VIFにコピー + mask = I_FLAG | IOPL_FLAG; // IF, IOPLは変更させない + } + }else{ + EXCEPTION(GP_EXCEPTION, 0); + flags = 0; + mask = 0; + } +#else + EXCEPTION(GP_EXCEPTION, 0); + flags = 0; + mask = 0; + /* compiler happy */ +#endif + } + set_eflags(flags, mask); + CPU_CLEAR_PREV_ESP(); + IRQCHECKTERM(); +} + +void +STI(void) +{ + + CPU_WORKCLOCK(2); + if (CPU_STAT_PM) { + if (!CPU_STAT_VM86) { + if (CPU_STAT_CPL > CPU_STAT_IOPL) { +#if defined(USE_VME) + if((CPU_CR4 & CPU_CR4_PVI) && CPU_STAT_CPL==3){ + if(CPU_EFLAG & VIP_FLAG){ + EXCEPTION(GP_EXCEPTION, 0); + }else{ + CPU_EFLAG |= VIF_FLAG; + return; + } + }else{ + EXCEPTION(GP_EXCEPTION, 0); + } +#else + EXCEPTION(GP_EXCEPTION, 0); +#endif + } + } else { + if (CPU_STAT_IOPL < 3) { +#if defined(USE_VME) + if(CPU_CR4 & CPU_CR4_VME){ + if(CPU_EFLAG & VIP_FLAG){ + EXCEPTION(GP_EXCEPTION, 0); + }else{ + CPU_EFLAG |= VIF_FLAG; + return; + } + }else{ + EXCEPTION(GP_EXCEPTION, 0); + } +#else + EXCEPTION(GP_EXCEPTION, 0); +#endif + } + } + } + CPU_FLAG |= I_FLAG; + CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG); + exec_1step(); + IRQCHECKTERM(); +} + +void +CLI(void) +{ + + CPU_WORKCLOCK(2); + if (CPU_STAT_PM) { + if (!CPU_STAT_VM86) { + if (CPU_STAT_CPL > CPU_STAT_IOPL) { +#if defined(USE_VME) + if((CPU_CR4 & CPU_CR4_PVI) && CPU_STAT_CPL==3){ + CPU_EFLAG &= ~VIF_FLAG; + return; + }else{ + EXCEPTION(GP_EXCEPTION, 0); + } +#else + EXCEPTION(GP_EXCEPTION, 0); +#endif + } + } else { + if (CPU_STAT_IOPL < 3) { +#if defined(USE_VME) + if(CPU_CR4 & CPU_CR4_VME){ + CPU_EFLAG &= ~VIF_FLAG; + return; + }else{ + EXCEPTION(GP_EXCEPTION, 0); + } +#else + EXCEPTION(GP_EXCEPTION, 0); +#endif + } + } + } + CPU_FLAG &= ~I_FLAG; + CPU_TRAP = 0; +} diff --git a/i386c/ia32/instructions/flag_ctrl.h b/i386c/ia32/instructions/flag_ctrl.h old mode 100755 new mode 100644 index b3fca2d4..8fc18555 --- a/i386c/ia32/instructions/flag_ctrl.h +++ b/i386c/ia32/instructions/flag_ctrl.h @@ -1,51 +1,51 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_FLAG_CTRL_H__ -#define IA32_CPU_INSTRUCTION_FLAG_CTRL_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -void STC(void); -void CLC(void); -void CMC(void); -void CLD(void); -void STD(void); -void LAHF(void); -void SAHF(void); -void PUSHF_Fw(void); -void PUSHFD_Fd(void); -void POPF_Fw(void); -void POPFD_Fd(void); -void STI(void); -void CLI(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_FLAG_CTRL_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_FLAG_CTRL_H__ +#define IA32_CPU_INSTRUCTION_FLAG_CTRL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void STC(void); +void CLC(void); +void CMC(void); +void CLD(void); +void STD(void); +void LAHF(void); +void SAHF(void); +void PUSHF_Fw(void); +void PUSHFD_Fd(void); +void POPF_Fw(void); +void POPFD_Fd(void); +void STI(void); +void CLI(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_FLAG_CTRL_H__ */ diff --git a/i386c/ia32/instructions/fpu.c b/i386c/ia32/instructions/fpu.c old mode 100755 new mode 100644 index e98f536e..c29f4f07 --- a/i386c/ia32/instructions/fpu.c +++ b/i386c/ia32/instructions/fpu.c @@ -1,433 +1,433 @@ -/* - * Copyright (c) 2012 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include -#include "ia32/ia32.mcr" -#include "ia32/inst_table.h" - -#include -#include "ia32/instructions/fpu/fpumem.h" - -#if defined(USE_FPU) && !defined(SUPPORT_FPU_DOSBOX) && !defined(SUPPORT_FPU_DOSBOX2) && !defined(SUPPORT_FPU_SOFTFLOAT) && !defined(SUPPORT_FPU_SOFTFLOAT3) -#error No FPU detected. Please define SUPPORT_FPU_DOSBOX, SUPPORT_FPU_DOSBOX2, SUPPORT_FPU_SOFTFLOAT or SUPPORT_FPU_SOFTFLOAT3. -#endif - -void CPUCALL -fpu_initialize(int initreg) -{ -#if defined(USE_FPU) - if(i386cpuid.cpu_feature & CPU_FEATURE_FPU){ - switch(i386cpuid.fpu_type){ -#if defined(SUPPORT_FPU_DOSBOX) - case FPU_TYPE_DOSBOX: - insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = DB_FPU_FXSAVERSTOR; - insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = DB_ESC0; - insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = DB_ESC1; - insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = DB_ESC2; - insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = DB_ESC3; - insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = DB_ESC4; - insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = DB_ESC5; - insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = DB_ESC6; - insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = DB_ESC7; - if (initreg) DB_FPU_FINIT(); - break; -#endif -#if defined(SUPPORT_FPU_DOSBOX2) - case FPU_TYPE_DOSBOX2: - insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = DB2_FPU_FXSAVERSTOR; - insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = DB2_ESC0; - insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = DB2_ESC1; - insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = DB2_ESC2; - insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = DB2_ESC3; - insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = DB2_ESC4; - insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = DB2_ESC5; - insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = DB2_ESC6; - insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = DB2_ESC7; - if (initreg) DB2_FPU_FINIT(); - break; -#endif -#if defined(SUPPORT_FPU_SOFTFLOAT) || defined(SUPPORT_FPU_SOFTFLOAT3) - case FPU_TYPE_SOFTFLOAT: - insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = SF_FPU_FXSAVERSTOR; - insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = SF_ESC0; - insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = SF_ESC1; - insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = SF_ESC2; - insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = SF_ESC3; - insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = SF_ESC4; - insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = SF_ESC5; - insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = SF_ESC6; - insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = SF_ESC7; - if (initreg) SF_FPU_FINIT(); - break; -#endif - default: -#if defined(SUPPORT_FPU_SOFTFLOAT) || defined(SUPPORT_FPU_SOFTFLOAT3) - insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = SF_FPU_FXSAVERSTOR; - insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = SF_ESC0; - insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = SF_ESC1; - insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = SF_ESC2; - insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = SF_ESC3; - insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = SF_ESC4; - insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = SF_ESC5; - insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = SF_ESC6; - insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = SF_ESC7; - if (initreg) SF_FPU_FINIT(); -#elif defined(SUPPORT_FPU_DOSBOX) - insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = DB_FPU_FXSAVERSTOR; - insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = DB_ESC0; - insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = DB_ESC1; - insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = DB_ESC2; - insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = DB_ESC3; - insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = DB_ESC4; - insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = DB_ESC5; - insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = DB_ESC6; - insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = DB_ESC7; - if (initreg) DB_FPU_FINIT(); -#elif defined(SUPPORT_FPU_DOSBOX2) - insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = DB2_FPU_FXSAVERSTOR; - insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = DB2_ESC0; - insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = DB2_ESC1; - insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = DB2_ESC2; - insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = DB2_ESC3; - insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = DB2_ESC4; - insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = DB2_ESC5; - insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = DB2_ESC6; - insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = DB2_ESC7; - if (initreg) DB2_FPU_FINIT(); -#else - insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = NOFPU_FPU_FXSAVERSTOR; - insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = NOFPU_ESC0; - insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = NOFPU_ESC1; - insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = NOFPU_ESC2; - insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = NOFPU_ESC3; - insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = NOFPU_ESC4; - insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = NOFPU_ESC5; - insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = NOFPU_ESC6; - insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = NOFPU_ESC7; - if (initreg) NOFPU_FPU_FINIT(); -#endif - break; - } - }else{ -#endif - insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = NOFPU_FPU_FXSAVERSTOR; - insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = NOFPU_ESC0; - insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = NOFPU_ESC1; - insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = NOFPU_ESC2; - insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = NOFPU_ESC3; - insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = NOFPU_ESC4; - insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = NOFPU_ESC5; - insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = NOFPU_ESC6; - insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = NOFPU_ESC7; - if (initreg) NOFPU_FPU_FINIT(); -#if defined(USE_FPU) - } -#endif -} - -void -fpu_statesave_load(void) -{ - int i; - - // FPU互換性維持用 -#if !defined(SUPPORT_FPU_SOFTFLOAT) && !defined(SUPPORT_FPU_SOFTFLOAT3) - if (i386cpuid.fpu_type == FPU_TYPE_SOFTFLOAT) { - // XXX: floatx80 -> doubleはsoftfloatなしでは処理できないので無視 - i386cpuid.fpu_type = FPU_TYPE_DOSBOX2; - } -#else - if (i386cpuid.fpu_type == FPU_TYPE_DOSBOX2 || i386cpuid.fpu_type == FPU_TYPE_DOSBOX) { -#if !defined(SUPPORT_FPU_DOSBOX2) && !defined(SUPPORT_FPU_DOSBOX) -#if defined(SUPPORT_FPU_SOFTFLOAT) - // double -> floatx80 - for (i = 0; i < 8; i++) { - FPU_STAT.reg[i].d = c_double_to_floatx80(FPU_STAT.reg[i].d64); - } - i386cpuid.fpu_type = FPU_TYPE_SOFTFLOAT; -#elif defined(SUPPORT_FPU_SOFTFLOAT3) - // double -> floatx80 - for (i = 0; i < 8; i++) { - sw_float64_t f = *(sw_float64_t*)(&(FPU_STAT.reg[i].d64)); - FPU_STAT.reg[i].d = f64_to_extF80(f); - } - i386cpuid.fpu_type = FPU_TYPE_SOFTFLOAT; -#endif -#elif !defined(SUPPORT_FPU_DOSBOX2) - if (i386cpuid.fpu_type == FPU_TYPE_DOSBOX2) { - i386cpuid.fpu_type = FPU_TYPE_DOSBOX; - } -#elif !defined(SUPPORT_FPU_DOSBOX) - if (i386cpuid.fpu_type == FPU_TYPE_DOSBOX) { - i386cpuid.fpu_type = FPU_TYPE_DOSBOX2; - } -#endif - } -#endif - - // フラグの復元 - if (i386cpuid.fpu_type == FPU_TYPE_SOFTFLOAT) { -#if defined(SUPPORT_FPU_SOFTFLOAT) - float_exception_flags = (FPU_STATUSWORD & 0x3f); - switch (FPU_STAT.round) { - case ROUND_Nearest: - float_rounding_mode = float_round_nearest_even; - break; - case ROUND_Down: - float_rounding_mode = float_round_down; - break; - case ROUND_Up: - float_rounding_mode = float_round_up; - break; - case ROUND_Chop: - float_rounding_mode = float_round_to_zero; - break; - default: - break; - } -#endif -#if defined(SUPPORT_FPU_SOFTFLOAT3) - const UINT16 statusword = FPU_STATUSWORD; - UINT8 result = 0; - if (statusword & (1 << 0)) result |= softfloat_flag_invalid; - if (statusword & (1 << 2)) result |= softfloat_flag_infinite; - if (statusword & (1 << 3)) result |= softfloat_flag_overflow; - if (statusword & (1 << 4)) result |= softfloat_flag_underflow; - if (statusword & (1 << 5)) result |= softfloat_flag_inexact; - softfloat_exceptionFlags = result; - switch (FPU_STAT.round) { - case ROUND_Nearest: - softfloat_roundingMode = softfloat_round_near_even; - break; - case ROUND_Down: - softfloat_roundingMode = softfloat_round_min; - break; - case ROUND_Up: - softfloat_roundingMode = softfloat_round_max; - break; - case ROUND_Chop: - softfloat_roundingMode = softfloat_round_minMag; - break; - default: - break; - } -#endif - } -} - -char * -fpu_reg2str(void) -{ - return NULL; -} - -/* - * FPU memory access function - */ -#if defined(USE_FPU) -UINT8 MEMCALL -fpu_memoryread_b(UINT32 address) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - return cpu_vmemoryread_b(seg, address); -} - -UINT16 MEMCALL -fpu_memoryread_w(UINT32 address) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - return cpu_vmemoryread_w(seg, address); -} - -UINT32 MEMCALL -fpu_memoryread_d(UINT32 address) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - return cpu_vmemoryread_d(seg, address); -} - -UINT64 MEMCALL -fpu_memoryread_q(UINT32 address) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - return cpu_vmemoryread_q(seg, address); -} - -REG80 MEMCALL -fpu_memoryread_f(UINT32 address) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - return cpu_vmemoryread_f(seg, address); -} - -float MEMCALL -fpu_memoryread_f32(UINT32 address) -{ - UINT16 seg; - union { - float f; - UINT32 l; - } val; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - val.l = cpu_vmemoryread_d(seg, address); - return val.f; -} - -double MEMCALL -fpu_memoryread_f64(UINT32 address) -{ - UINT16 seg; - union { - double f; - UINT64 q; - } val; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - val.q = cpu_vmemoryread_q(seg, address); - return val.f; -} - -void MEMCALL -fpu_memorywrite_b(UINT32 address, UINT8 value) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - cpu_vmemorywrite_b(seg, address, value); -} - -void MEMCALL -fpu_memorywrite_w(UINT32 address, UINT16 value) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - cpu_vmemorywrite_w(seg, address, value); -} - -void MEMCALL -fpu_memorywrite_d(UINT32 address, UINT32 value) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - cpu_vmemorywrite_d(seg, address, value); -} - -void MEMCALL -fpu_memorywrite_q(UINT32 address, UINT64 value) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - cpu_vmemorywrite_q(seg, address, value); -} - -void MEMCALL -fpu_memorywrite_f(UINT32 address, REG80 *value) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - cpu_vmemorywrite_f(seg, address, value); -} - -void MEMCALL -fpu_memorywrite_f32(UINT32 address, float value) -{ - UINT16 seg; - union { - float f; - UINT32 l; - } val; - - val.f = value; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - cpu_vmemorywrite_d(seg, address, val.l); -} - -void MEMCALL -fpu_memorywrite_f64(UINT32 address, double value) -{ - UINT16 seg; - union { - double f; - UINT64 q; - } val; - - val.f = value; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - cpu_vmemorywrite_q(seg, address, val.q); -} -#endif - -void -FPU_FWAIT(void) -{ -#if defined(USE_FPU) - // FPUなしなら何もしない - if(!(i386cpuid.cpu_feature & CPU_FEATURE_FPU)){ - return; - } - // タスクスイッチまたはMPでNM(デバイス使用不可例外)を発生させる - if ((CPU_CR0 & (CPU_CR0_MP|CPU_CR0_TS))==(CPU_CR0_MP|CPU_CR0_TS)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - // Check exception - if((FPU_STATUSWORD & ~FPU_CTRLWORD) & 0x3F){ - EXCEPTION(MF_EXCEPTION, 0); - } -#endif +/* + * Copyright (c) 2012 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include +#include "ia32/ia32.mcr" +#include "ia32/inst_table.h" + +#include +#include "ia32/instructions/fpu/fpumem.h" + +#if defined(USE_FPU) && !defined(SUPPORT_FPU_DOSBOX) && !defined(SUPPORT_FPU_DOSBOX2) && !defined(SUPPORT_FPU_SOFTFLOAT) && !defined(SUPPORT_FPU_SOFTFLOAT3) +#error No FPU detected. Please define SUPPORT_FPU_DOSBOX, SUPPORT_FPU_DOSBOX2, SUPPORT_FPU_SOFTFLOAT or SUPPORT_FPU_SOFTFLOAT3. +#endif + +void CPUCALL +fpu_initialize(int initreg) +{ +#if defined(USE_FPU) + if(i386cpuid.cpu_feature & CPU_FEATURE_FPU){ + switch(i386cpuid.fpu_type){ +#if defined(SUPPORT_FPU_DOSBOX) + case FPU_TYPE_DOSBOX: + insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = DB_FPU_FXSAVERSTOR; + insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = DB_ESC0; + insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = DB_ESC1; + insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = DB_ESC2; + insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = DB_ESC3; + insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = DB_ESC4; + insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = DB_ESC5; + insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = DB_ESC6; + insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = DB_ESC7; + if (initreg) DB_FPU_FINIT(); + break; +#endif +#if defined(SUPPORT_FPU_DOSBOX2) + case FPU_TYPE_DOSBOX2: + insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = DB2_FPU_FXSAVERSTOR; + insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = DB2_ESC0; + insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = DB2_ESC1; + insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = DB2_ESC2; + insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = DB2_ESC3; + insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = DB2_ESC4; + insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = DB2_ESC5; + insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = DB2_ESC6; + insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = DB2_ESC7; + if (initreg) DB2_FPU_FINIT(); + break; +#endif +#if defined(SUPPORT_FPU_SOFTFLOAT) || defined(SUPPORT_FPU_SOFTFLOAT3) + case FPU_TYPE_SOFTFLOAT: + insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = SF_FPU_FXSAVERSTOR; + insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = SF_ESC0; + insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = SF_ESC1; + insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = SF_ESC2; + insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = SF_ESC3; + insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = SF_ESC4; + insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = SF_ESC5; + insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = SF_ESC6; + insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = SF_ESC7; + if (initreg) SF_FPU_FINIT(); + break; +#endif + default: +#if defined(SUPPORT_FPU_SOFTFLOAT) || defined(SUPPORT_FPU_SOFTFLOAT3) + insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = SF_FPU_FXSAVERSTOR; + insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = SF_ESC0; + insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = SF_ESC1; + insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = SF_ESC2; + insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = SF_ESC3; + insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = SF_ESC4; + insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = SF_ESC5; + insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = SF_ESC6; + insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = SF_ESC7; + if (initreg) SF_FPU_FINIT(); +#elif defined(SUPPORT_FPU_DOSBOX) + insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = DB_FPU_FXSAVERSTOR; + insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = DB_ESC0; + insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = DB_ESC1; + insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = DB_ESC2; + insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = DB_ESC3; + insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = DB_ESC4; + insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = DB_ESC5; + insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = DB_ESC6; + insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = DB_ESC7; + if (initreg) DB_FPU_FINIT(); +#elif defined(SUPPORT_FPU_DOSBOX2) + insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = DB2_FPU_FXSAVERSTOR; + insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = DB2_ESC0; + insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = DB2_ESC1; + insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = DB2_ESC2; + insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = DB2_ESC3; + insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = DB2_ESC4; + insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = DB2_ESC5; + insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = DB2_ESC6; + insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = DB2_ESC7; + if (initreg) DB2_FPU_FINIT(); +#else + insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = NOFPU_FPU_FXSAVERSTOR; + insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = NOFPU_ESC0; + insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = NOFPU_ESC1; + insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = NOFPU_ESC2; + insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = NOFPU_ESC3; + insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = NOFPU_ESC4; + insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = NOFPU_ESC5; + insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = NOFPU_ESC6; + insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = NOFPU_ESC7; + if (initreg) NOFPU_FPU_FINIT(); +#endif + break; + } + }else{ +#endif + insttable_2byte[0][0xae] = insttable_2byte[1][0xae] = NOFPU_FPU_FXSAVERSTOR; + insttable_1byte[0][0xd8] = insttable_1byte[1][0xd8] = NOFPU_ESC0; + insttable_1byte[0][0xd9] = insttable_1byte[1][0xd9] = NOFPU_ESC1; + insttable_1byte[0][0xda] = insttable_1byte[1][0xda] = NOFPU_ESC2; + insttable_1byte[0][0xdb] = insttable_1byte[1][0xdb] = NOFPU_ESC3; + insttable_1byte[0][0xdc] = insttable_1byte[1][0xdc] = NOFPU_ESC4; + insttable_1byte[0][0xdd] = insttable_1byte[1][0xdd] = NOFPU_ESC5; + insttable_1byte[0][0xde] = insttable_1byte[1][0xde] = NOFPU_ESC6; + insttable_1byte[0][0xdf] = insttable_1byte[1][0xdf] = NOFPU_ESC7; + if (initreg) NOFPU_FPU_FINIT(); +#if defined(USE_FPU) + } +#endif +} + +void +fpu_statesave_load(void) +{ + int i; + + // FPU互換性維持用 +#if !defined(SUPPORT_FPU_SOFTFLOAT) && !defined(SUPPORT_FPU_SOFTFLOAT3) + if (i386cpuid.fpu_type == FPU_TYPE_SOFTFLOAT) { + // XXX: floatx80 -> doubleはsoftfloatなしでは処理できないので無視 + i386cpuid.fpu_type = FPU_TYPE_DOSBOX2; + } +#else + if (i386cpuid.fpu_type == FPU_TYPE_DOSBOX2 || i386cpuid.fpu_type == FPU_TYPE_DOSBOX) { +#if !defined(SUPPORT_FPU_DOSBOX2) && !defined(SUPPORT_FPU_DOSBOX) +#if defined(SUPPORT_FPU_SOFTFLOAT) + // double -> floatx80 + for (i = 0; i < 8; i++) { + FPU_STAT.reg[i].d = c_double_to_floatx80(FPU_STAT.reg[i].d64); + } + i386cpuid.fpu_type = FPU_TYPE_SOFTFLOAT; +#elif defined(SUPPORT_FPU_SOFTFLOAT3) + // double -> floatx80 + for (i = 0; i < 8; i++) { + sw_float64_t f = *(sw_float64_t*)(&(FPU_STAT.reg[i].d64)); + FPU_STAT.reg[i].d = f64_to_extF80(f); + } + i386cpuid.fpu_type = FPU_TYPE_SOFTFLOAT; +#endif +#elif !defined(SUPPORT_FPU_DOSBOX2) + if (i386cpuid.fpu_type == FPU_TYPE_DOSBOX2) { + i386cpuid.fpu_type = FPU_TYPE_DOSBOX; + } +#elif !defined(SUPPORT_FPU_DOSBOX) + if (i386cpuid.fpu_type == FPU_TYPE_DOSBOX) { + i386cpuid.fpu_type = FPU_TYPE_DOSBOX2; + } +#endif + } +#endif + + // フラグの復元 + if (i386cpuid.fpu_type == FPU_TYPE_SOFTFLOAT) { +#if defined(SUPPORT_FPU_SOFTFLOAT) + float_exception_flags = (FPU_STATUSWORD & 0x3f); + switch (FPU_STAT.round) { + case ROUND_Nearest: + float_rounding_mode = float_round_nearest_even; + break; + case ROUND_Down: + float_rounding_mode = float_round_down; + break; + case ROUND_Up: + float_rounding_mode = float_round_up; + break; + case ROUND_Chop: + float_rounding_mode = float_round_to_zero; + break; + default: + break; + } +#endif +#if defined(SUPPORT_FPU_SOFTFLOAT3) + const UINT16 statusword = FPU_STATUSWORD; + UINT8 result = 0; + if (statusword & (1 << 0)) result |= softfloat_flag_invalid; + if (statusword & (1 << 2)) result |= softfloat_flag_infinite; + if (statusword & (1 << 3)) result |= softfloat_flag_overflow; + if (statusword & (1 << 4)) result |= softfloat_flag_underflow; + if (statusword & (1 << 5)) result |= softfloat_flag_inexact; + softfloat_exceptionFlags = result; + switch (FPU_STAT.round) { + case ROUND_Nearest: + softfloat_roundingMode = softfloat_round_near_even; + break; + case ROUND_Down: + softfloat_roundingMode = softfloat_round_min; + break; + case ROUND_Up: + softfloat_roundingMode = softfloat_round_max; + break; + case ROUND_Chop: + softfloat_roundingMode = softfloat_round_minMag; + break; + default: + break; + } +#endif + } +} + +char * +fpu_reg2str(void) +{ + return NULL; +} + +/* + * FPU memory access function + */ +#if defined(USE_FPU) +UINT8 MEMCALL +fpu_memoryread_b(UINT32 address) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + return cpu_vmemoryread_b(seg, address); +} + +UINT16 MEMCALL +fpu_memoryread_w(UINT32 address) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + return cpu_vmemoryread_w(seg, address); +} + +UINT32 MEMCALL +fpu_memoryread_d(UINT32 address) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + return cpu_vmemoryread_d(seg, address); +} + +UINT64 MEMCALL +fpu_memoryread_q(UINT32 address) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + return cpu_vmemoryread_q(seg, address); +} + +REG80 MEMCALL +fpu_memoryread_f(UINT32 address) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + return cpu_vmemoryread_f(seg, address); +} + +float MEMCALL +fpu_memoryread_f32(UINT32 address) +{ + UINT16 seg; + union { + float f; + UINT32 l; + } val; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + val.l = cpu_vmemoryread_d(seg, address); + return val.f; +} + +double MEMCALL +fpu_memoryread_f64(UINT32 address) +{ + UINT16 seg; + union { + double f; + UINT64 q; + } val; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + val.q = cpu_vmemoryread_q(seg, address); + return val.f; +} + +void MEMCALL +fpu_memorywrite_b(UINT32 address, UINT8 value) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + cpu_vmemorywrite_b(seg, address, value); +} + +void MEMCALL +fpu_memorywrite_w(UINT32 address, UINT16 value) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + cpu_vmemorywrite_w(seg, address, value); +} + +void MEMCALL +fpu_memorywrite_d(UINT32 address, UINT32 value) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + cpu_vmemorywrite_d(seg, address, value); +} + +void MEMCALL +fpu_memorywrite_q(UINT32 address, UINT64 value) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + cpu_vmemorywrite_q(seg, address, value); +} + +void MEMCALL +fpu_memorywrite_f(UINT32 address, REG80 *value) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + cpu_vmemorywrite_f(seg, address, value); +} + +void MEMCALL +fpu_memorywrite_f32(UINT32 address, float value) +{ + UINT16 seg; + union { + float f; + UINT32 l; + } val; + + val.f = value; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + cpu_vmemorywrite_d(seg, address, val.l); +} + +void MEMCALL +fpu_memorywrite_f64(UINT32 address, double value) +{ + UINT16 seg; + union { + double f; + UINT64 q; + } val; + + val.f = value; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + cpu_vmemorywrite_q(seg, address, val.q); +} +#endif + +void +FPU_FWAIT(void) +{ +#if defined(USE_FPU) + // FPUなしなら何もしない + if(!(i386cpuid.cpu_feature & CPU_FEATURE_FPU)){ + return; + } + // タスクスイッチまたはMPでNM(デバイス使用不可例外)を発生させる + if ((CPU_CR0 & (CPU_CR0_MP|CPU_CR0_TS))==(CPU_CR0_MP|CPU_CR0_TS)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + // Check exception + if((FPU_STATUSWORD & ~FPU_CTRLWORD) & 0x3F){ + EXCEPTION(MF_EXCEPTION, 0); + } +#endif } \ No newline at end of file diff --git a/i386c/ia32/instructions/fpu/fp.h b/i386c/ia32/instructions/fpu/fp.h old mode 100755 new mode 100644 index 74d9590d..7bce6acc --- a/i386c/ia32/instructions/fpu/fp.h +++ b/i386c/ia32/instructions/fpu/fp.h @@ -1,94 +1,94 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_FPU_FP_H__ -#define IA32_CPU_INSTRUCTION_FPU_FP_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -void CPUCALL fpu_initialize(int initreg); - -void fpu_statesave_load(void); - -void FPU_FWAIT(void); - -#if defined(USE_FPU) -#if defined(SUPPORT_FPU_DOSBOX) -void DB_FPU_FINIT(void); -void DB_FPU_FXSAVERSTOR(void); -void DB_ESC0(void); -void DB_ESC1(void); -void DB_ESC2(void); -void DB_ESC3(void); -void DB_ESC4(void); -void DB_ESC5(void); -void DB_ESC6(void); -void DB_ESC7(void); -#endif -#if defined(SUPPORT_FPU_DOSBOX2) -void DB2_FPU_FINIT(void); -void DB2_FPU_FXSAVERSTOR(void); -void DB2_ESC0(void); -void DB2_ESC1(void); -void DB2_ESC2(void); -void DB2_ESC3(void); -void DB2_ESC4(void); -void DB2_ESC5(void); -void DB2_ESC6(void); -void DB2_ESC7(void); -#endif -#if defined(SUPPORT_FPU_SOFTFLOAT) || defined(SUPPORT_FPU_SOFTFLOAT3) -void SF_FPU_FINIT(void); -void SF_FPU_FXSAVERSTOR(void); -void SF_ESC0(void); -void SF_ESC1(void); -void SF_ESC2(void); -void SF_ESC3(void); -void SF_ESC4(void); -void SF_ESC5(void); -void SF_ESC6(void); -void SF_ESC7(void); -#endif -#endif - -// for i486SX -void NOFPU_FPU_FINIT(void); -void NOFPU_FPU_FXSAVERSTOR(void); -void NOFPU_ESC0(void); -void NOFPU_ESC1(void); -void NOFPU_ESC2(void); -void NOFPU_ESC3(void); -void NOFPU_ESC4(void); -void NOFPU_ESC5(void); -void NOFPU_ESC6(void); -void NOFPU_ESC7(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_FPU_FP_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_FPU_FP_H__ +#define IA32_CPU_INSTRUCTION_FPU_FP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void CPUCALL fpu_initialize(int initreg); + +void fpu_statesave_load(void); + +void FPU_FWAIT(void); + +#if defined(USE_FPU) +#if defined(SUPPORT_FPU_DOSBOX) +void DB_FPU_FINIT(void); +void DB_FPU_FXSAVERSTOR(void); +void DB_ESC0(void); +void DB_ESC1(void); +void DB_ESC2(void); +void DB_ESC3(void); +void DB_ESC4(void); +void DB_ESC5(void); +void DB_ESC6(void); +void DB_ESC7(void); +#endif +#if defined(SUPPORT_FPU_DOSBOX2) +void DB2_FPU_FINIT(void); +void DB2_FPU_FXSAVERSTOR(void); +void DB2_ESC0(void); +void DB2_ESC1(void); +void DB2_ESC2(void); +void DB2_ESC3(void); +void DB2_ESC4(void); +void DB2_ESC5(void); +void DB2_ESC6(void); +void DB2_ESC7(void); +#endif +#if defined(SUPPORT_FPU_SOFTFLOAT) || defined(SUPPORT_FPU_SOFTFLOAT3) +void SF_FPU_FINIT(void); +void SF_FPU_FXSAVERSTOR(void); +void SF_ESC0(void); +void SF_ESC1(void); +void SF_ESC2(void); +void SF_ESC3(void); +void SF_ESC4(void); +void SF_ESC5(void); +void SF_ESC6(void); +void SF_ESC7(void); +#endif +#endif + +// for i486SX +void NOFPU_FPU_FINIT(void); +void NOFPU_FPU_FXSAVERSTOR(void); +void NOFPU_ESC0(void); +void NOFPU_ESC1(void); +void NOFPU_ESC2(void); +void NOFPU_ESC3(void); +void NOFPU_ESC4(void); +void NOFPU_ESC5(void); +void NOFPU_ESC6(void); +void NOFPU_ESC7(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_FPU_FP_H__ */ diff --git a/i386c/ia32/instructions/fpu/fpdummy.c b/i386c/ia32/instructions/fpu/fpdummy.c old mode 100755 new mode 100644 index 4974e452..714cdd35 --- a/i386c/ia32/instructions/fpu/fpdummy.c +++ b/i386c/ia32/instructions/fpu/fpdummy.c @@ -1,161 +1,161 @@ -#include - -#include -#include "ia32/ia32.mcr" -#include "fp.h" - -void NOFPU_FPU_FINIT(void){ - // Nothing to do -} - -void NOFPU_FPU_FXSAVERSTOR(void){ - EXCEPTION(UD_EXCEPTION, 0); -} - -void -NOFPU_ESC0(void) -{ - UINT32 op, madr; - - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU d8 %.2x", op)); - if (op >= 0xc0) { - EXCEPTION(NM_EXCEPTION, 0); - } else { - madr = calc_ea_dst(op); - EXCEPTION(NM_EXCEPTION, 0); - } -} - -void -NOFPU_ESC1(void) -{ - UINT32 op, madr; - - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU d9 %.2x", op)); - if (op >= 0xc0) { - EXCEPTION(NM_EXCEPTION, 0); - } else { - madr = calc_ea_dst(op); - switch (op & 0x38) { - case 0x28: - TRACEOUT(("FLDCW")); - (void) cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - break; - - case 0x38: - TRACEOUT(("FSTCW")); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, 0xffff); - break; - - default: - EXCEPTION(NM_EXCEPTION, 0); - break; - } - } -} - -void -NOFPU_ESC2(void) -{ - UINT32 op, madr; - - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU da %.2x", op)); - if (op >= 0xc0) { - EXCEPTION(NM_EXCEPTION, 0); - } else { - madr = calc_ea_dst(op); - EXCEPTION(NM_EXCEPTION, 0); - } -} - -void -NOFPU_ESC3(void) -{ - UINT32 op, madr; - - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU db %.2x", op)); - if (op >= 0xc0) { - if (op != 0xe3) { - EXCEPTION(NM_EXCEPTION, 0); - } - /* FNINIT */ - (void)madr; - } else { - madr = calc_ea_dst(op); - EXCEPTION(NM_EXCEPTION, 0); - } -} - -void -NOFPU_ESC4(void) -{ - UINT32 op, madr; - - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU dc %.2x", op)); - if (op >= 0xc0) { - EXCEPTION(NM_EXCEPTION, 0); - } else { - madr = calc_ea_dst(op); - EXCEPTION(NM_EXCEPTION, 0); - } -} - -void -NOFPU_ESC5(void) -{ - UINT32 op, madr; - - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU dd %.2x", op)); - if (op >= 0xc0) { - EXCEPTION(NM_EXCEPTION, 0); - } else { - madr = calc_ea_dst(op); - if (((op >> 3) & 7) != 7) { - EXCEPTION(NM_EXCEPTION, 0); - } - /* FSTSW */ - TRACEOUT(("FSTSW")); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, 0xffff); - } -} - -void -NOFPU_ESC6(void) -{ - UINT32 op, madr; - - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU de %.2x", op)); - if (op >= 0xc0) { - EXCEPTION(NM_EXCEPTION, 0); - } else { - madr = calc_ea_dst(op); - EXCEPTION(NM_EXCEPTION, 0); - } -} - -void -NOFPU_ESC7(void) -{ - UINT32 op, madr; - - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU df %.2x", op)); - if (op >= 0xc0) { - if (op != 0xe0) { - EXCEPTION(NM_EXCEPTION, 0); - } - /* FSTSW AX */ - TRACEOUT(("FSTSW AX")); - CPU_AX = 0xffff; - } else { - madr = calc_ea_dst(op); - EXCEPTION(NM_EXCEPTION, 0); - } +#include + +#include +#include "ia32/ia32.mcr" +#include "fp.h" + +void NOFPU_FPU_FINIT(void){ + // Nothing to do +} + +void NOFPU_FPU_FXSAVERSTOR(void){ + EXCEPTION(UD_EXCEPTION, 0); +} + +void +NOFPU_ESC0(void) +{ + UINT32 op, madr; + + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU d8 %.2x", op)); + if (op >= 0xc0) { + EXCEPTION(NM_EXCEPTION, 0); + } else { + madr = calc_ea_dst(op); + EXCEPTION(NM_EXCEPTION, 0); + } +} + +void +NOFPU_ESC1(void) +{ + UINT32 op, madr; + + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU d9 %.2x", op)); + if (op >= 0xc0) { + EXCEPTION(NM_EXCEPTION, 0); + } else { + madr = calc_ea_dst(op); + switch (op & 0x38) { + case 0x28: + TRACEOUT(("FLDCW")); + (void) cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + break; + + case 0x38: + TRACEOUT(("FSTCW")); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, 0xffff); + break; + + default: + EXCEPTION(NM_EXCEPTION, 0); + break; + } + } +} + +void +NOFPU_ESC2(void) +{ + UINT32 op, madr; + + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU da %.2x", op)); + if (op >= 0xc0) { + EXCEPTION(NM_EXCEPTION, 0); + } else { + madr = calc_ea_dst(op); + EXCEPTION(NM_EXCEPTION, 0); + } +} + +void +NOFPU_ESC3(void) +{ + UINT32 op, madr; + + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU db %.2x", op)); + if (op >= 0xc0) { + if (op != 0xe3) { + EXCEPTION(NM_EXCEPTION, 0); + } + /* FNINIT */ + (void)madr; + } else { + madr = calc_ea_dst(op); + EXCEPTION(NM_EXCEPTION, 0); + } +} + +void +NOFPU_ESC4(void) +{ + UINT32 op, madr; + + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU dc %.2x", op)); + if (op >= 0xc0) { + EXCEPTION(NM_EXCEPTION, 0); + } else { + madr = calc_ea_dst(op); + EXCEPTION(NM_EXCEPTION, 0); + } +} + +void +NOFPU_ESC5(void) +{ + UINT32 op, madr; + + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU dd %.2x", op)); + if (op >= 0xc0) { + EXCEPTION(NM_EXCEPTION, 0); + } else { + madr = calc_ea_dst(op); + if (((op >> 3) & 7) != 7) { + EXCEPTION(NM_EXCEPTION, 0); + } + /* FSTSW */ + TRACEOUT(("FSTSW")); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, 0xffff); + } +} + +void +NOFPU_ESC6(void) +{ + UINT32 op, madr; + + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU de %.2x", op)); + if (op >= 0xc0) { + EXCEPTION(NM_EXCEPTION, 0); + } else { + madr = calc_ea_dst(op); + EXCEPTION(NM_EXCEPTION, 0); + } +} + +void +NOFPU_ESC7(void) +{ + UINT32 op, madr; + + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU df %.2x", op)); + if (op >= 0xc0) { + if (op != 0xe0) { + EXCEPTION(NM_EXCEPTION, 0); + } + /* FSTSW AX */ + TRACEOUT(("FSTSW AX")); + CPU_AX = 0xffff; + } else { + madr = calc_ea_dst(op); + EXCEPTION(NM_EXCEPTION, 0); + } } \ No newline at end of file diff --git a/i386c/ia32/instructions/fpu/fpemul.c b/i386c/ia32/instructions/fpu/fpemul.c old mode 100755 new mode 100644 index c9c95e2e..8ae9215b --- a/i386c/ia32/instructions/fpu/fpemul.c +++ b/i386c/ia32/instructions/fpu/fpemul.c @@ -1,1329 +1,1329 @@ -/* - * Copyright (c) 2012 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include - -#include -#include "ia32/ia32.mcr" - -#include - -/* -Short Real - 31: sign (符号) -30-23: exp-8 (指数部: exponet) -22-00: num-23 (小数部) - -Long Real - 63: sign -62-52: exp-11 -51-00: num-52 - -Temp Real - 79: sign -78-64: exp-15 - 63: 1(?) -62-00: num-63 - --- -指数部: -2 の 0 乗のとき 0111 1111 となる -1000 0001: +2 乗 -1000 0000: +1 乗 -0111 1111: 0 乗 -0111 1110: -1 乗 - -仮数部: -2 を基数として整数部が一桁になるように正規化した数の 2 進数表現となる。 -正規化によって仮数部の最上位ビットは常に 1 になるので実際に用意しておく -必要はなく、倍精度の 52 ビットであれば最上位の 1 を hidden bit にして -含めなければ、53 ビット分の情報が含まれることになる。 - -小数の二進数表現: -0.1000 1/2 = 0.5 -0.0100 1/(2*2) = 0.25 -0.0010 1/(2*2*2) = 0.125 -0.0001 1/(2*2*2*2) = 0.0625 -*/ - -#define PRECISION_NBIT 64 -#define EXP_OFFSET 0x3fff - -#define IS_VALID(f) (f)->valid -#define IS_ZERO(f) (f)->zero -#define IS_INF(f) (f)->inf -#define IS_NAN(f) (f)->nan -#define IS_DENORMAL(f) (f)->denorm - -#define SET_ZERO(f) \ -do \ -{ \ - (f)->zero = 1; \ - (f)->inf = 0; \ - (f)->nan = 0; \ - (f)->denorm = 0; \ -} while (/*CONSTCOND*/0) - -#define SET_INF(f) \ -do \ -{ \ - (f)->zero = 0; \ - (f)->inf = 1; \ - (f)->nan = 0; \ - (f)->denorm = 0; \ -} while (/*CONSTCOND*/0) - -#define SET_NAN(f) \ -do \ -{ \ - (f)->zero = 0; \ - (f)->inf = 0; \ - (f)->nan = 1; \ - (f)->denorm = 0; \ -} while (/*CONSTCOND*/0) - - -/* -制御命令: -FINIT, FCLEX, FLDCW, FSTCW, FSTSW, GSTENV, FLDENV, FSAVE, FRSTOR, FWAIT -*/ - -void F2XM1(void); -void FABS(void); -void FADD(void); -void FADDP(void); -void FIADD(void); -void FBLD(void); -void FBSTP(void); -void FCHS(void); -void FCLEX(void); -void FNCLEX(void); -void FCOM(void); -void FCOMP(void); -void FCOMPP(void); -void FCOMI(void); -void FCOMIP(void); -void FUCOMI(void); -void FUCOMIP(void); -void FCOS(void); -void FDECSTP(void); -void FDIV(void); -void FDIVP(void); -void FIDIV(void); -void FDIVR(void); -void FDIVRP(void); -void FIDIVR(void); -void FFREE(void); -void FICOM(void); -void FICOMP(void); -void FILD(void); -void FINCSTP(void); -void FIST(void); -void FISTP(void); -void FLD(void); -void FLDCW(void); -void FLDENV(void); -void FMUL(void); -void FMULP(void); -void FNINIT(void); -void FIMUL(void); -void FNOP(void); -void FPATAN(void); -void FPREM(void); -void FPREM1(void); -void FPTAN(void); -void FRNDINT(void); -void FRSTOR(void); -void FSAVE(void); -void FNSAVE(void); -void _FSCALE(void); -void FSIN(void); -void FSINCOS(void); -void FSQRT(void); -void FST(void); -void FSTP(void); -void FNSTCW(void); -void FSTENV(void); -void FNSTENV(void); -void FNSTSW(void); -void FSUB(void); -void FSUBP(void); -void FISUB(void); -void FSUBR(void); -void FSUBRP(void); -void FISUBR(void); -void FTST(void); -void FUCOM(void); -void FUCOMP(void); -void FUCOMPP(void); -void FXAM(void); -void FXCH(void); -void FXTRACT(void); -void FYL2X(void); -void FYL2XP1(void); - -/* FMOVcc */ -void FCMOVB(void); -void FCMOVE(void); -void FCMOVBE(void); -void FCMOVU(void); -void FCMOVNB(void); -void FCMOVNE(void); -void FCMOVNBE(void); -void FCMOVNU(void); - -/* Load constant */ -void FLD1(void); -void FLDL2T(void); -void FLDL2E(void); -void FLDPI(void); -void FLDLG2(void); -void FLDLN2(void); -void FLDZ(void); - - -static const FPU_PTR zero_ptr = { 0, 0, 0 }; - -static const FP_REG fp_const_0 = { 1, 0, 1, 0, 0, 0, 0, 0 }; -static const FP_REG fp_const_1 = { 1, 0, 0, 0, 0, 0, 0, 0 }; - -static const FP_REG snan = { - 1, 1, 0, 0, 1, 0, 0, QWORD_CONST(0x00) /* SNaN */ -}; -static const FP_REG qnan = { - 1, 1, 0, 0, 1, 0, 0, QWORD_CONST(0x01) /* QNaN */ -}; -static const FP_REG indefinite_qnan = { - 1, 1, 0, 0, 1, 0, 0, QWORD_CONST(0x11) /* indef QNaN */ -}; - -static const REG80 indefinite_bcd = { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff } -}; - -/* - * FPU exception - */ -enum { - IS_EXCEPTION, - IA_EXCEPTION, - Z_EXCEPTION, - D_EXCEPTION, - O_EXCEPTION, - U_EXCEPTION, - P_EXCEPTION, - FPU_EXCEPTION_NUM -}; - -static void CPUCALL -fpu_exception(int num, int async) -{ - UINT16 bit; - - switch (num) { - case IS_EXCEPTION: - FPU_STATUSWORD |= FP_SF_FLAG; - /*FALLTHROUGH*/ - case IA_EXCEPTION: - bit = FP_IE_FLAG; - break; - - case Z_EXCEPTION: - bit = FP_ZE_FLAG; - break; - - case D_EXCEPTION: - bit = FP_DE_FLAG; - break; - - case O_EXCEPTION: - bit = FP_OE_FLAG; - break; - - case U_EXCEPTION: - bit = FP_UE_FLAG; - break; - - case P_EXCEPTION: - bit = FP_PE_FLAG; - break; - - case FPU_EXCEPTION_NUM: - default: - ia32_panic("fpu_exception: unknown exception (%d)\n", num); - return; - } - - FPU_STATUSWORD |= bit; - - if (!(bit & FPU_CTRLWORD)) { - FPU_STATUSWORD |= FP_ES_FLAG|FP_B_FLAG; - if (CPU_CR0 & CPU_CR0_NE) { - /* native mode */ - if (!async) { - CPU_PREV_EIP = CPU_EIP; /* XXX */ - EXCEPTION(MF_EXCEPTION, 0); - } - } else { - /* MS-DOS compat. mode */ - /* XXX */ - } - } -} - -#define FPU_EXCEPTION(n,a) fpu_exception(n,a) - - -/* - * FPU memory access function - */ -static UINT16 MEMCALL -fpu_memoryread_w(UINT32 address) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - return cpu_vmemoryread_w(seg, address); -} - -static UINT32 MEMCALL -fpu_memoryread_d(UINT32 address) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - return cpu_vmemoryread_d(seg, address); -} - -static UINT64 MEMCALL -fpu_memoryread_q(UINT32 address) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - return cpu_vmemoryread_q(seg, address); -} - -static REG80 MEMCALL -fpu_memoryread_f(UINT32 address) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - return cpu_vmemoryread_f(seg, address); -} - -static void MEMCALL -fpu_memorywrite_w(UINT32 address, UINT16 value) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - cpu_vmemorywrite_w(seg, address, value); -} - -static void MEMCALL -fpu_memorywrite_d(UINT32 address, UINT32 value) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - cpu_vmemorywrite_d(seg, address, value); -} - -static void MEMCALL -fpu_memorywrite_q(UINT32 address, UINT64 value) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - cpu_vmemorywrite_q(seg, address, value); -} - -static void MEMCALL -fpu_memorywrite_f(UINT32 address, REG80 *value) -{ - UINT16 seg; - - FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; - FPU_DATAPTR_OFFSET = address; - cpu_vmemorywrite_f(seg, address, value); -} - -/* - * FPU memory load function - */ -static void MEMCALL -fp_load_integer(FP_REG *fp, int sign, UINT64 value) -{ - int exp; - - fp->valid = 1; - fp->sign = sign ? 1 : 0; - fp->zero = (value == 0); - fp->nan = 0; - fp->inf = 0; - fp->denorm = 0; - - if (!IS_ZERO(fp)) { - for (exp = 0; exp < 64; ++exp, value <<= 1) { - if (value & QWORD_CONST(0x8000000000000000)) { - break; - } - } - fp->num = value; - fp->exp = (UINT16)exp; - } -} - -static void MEMCALL -fp_load_word_integer(FP_REG *fp, UINT32 address) -{ - UINT64 n; - UINT16 v; - int sign; - - v = fpu_memoryread_w(address); - - sign = (v & 0x8000) ? 1 : 0; - n = sign ? -v : v; - - fp_load_integer(fp, sign, n); -} - -static void MEMCALL -fp_load_short_integer(FP_REG *fp, UINT32 address) -{ - UINT64 n; - UINT32 v; - int sign; - - v = fpu_memoryread_d(address); - - sign = (v & 0x80000000UL) ? 1 : 0; - n = sign ? -v : v; - - fp_load_integer(fp, sign, n); -} - -static void MEMCALL -fp_load_long_integer(FP_REG *fp, UINT32 address) -{ - UINT64 n; - UINT64 v; - int sign; - - v = fpu_memoryread_q(address); - - sign = (v & QWORD_CONST(0x8000000000000000)) ? 1 : 0; - n = sign ? -v : v; - - fp_load_integer(fp, sign, n); -} - -static void MEMCALL -fp_load_bcd_integer(FP_REG *fp, UINT32 address) -{ - REG80 v; - UINT64 n; - int sign; - int i, t; - - v = fpu_memoryread_f(address); - - n = 0; - for (i = 0; i < 4; ++i) { - t = v.b[i] & 0xf; - if (t > 9) { - goto indefinite; - } - n = (n * 10) + t; - - t = (v.b[i] >> 4) & 0xf; - if (t > 9) { - goto indefinite; - } - n = (n * 10) + t; - } - sign = v.b[9] & 0x80; - - fp_load_integer(fp, sign, n); - return; - - indefinite: - *fp = indefinite_qnan; - return; -} - -/* - * FPU memory strore function - */ -static void MEMCALL -fp_store_bcd(FP_REG *fp, UINT32 address) -{ - const REG80 *p; - REG80 v; - UINT64 n; - int valid; - int i; - - if (IS_ZERO(fp)) { - memset(&v, 0, sizeof(v)); - v.b[9] = fp->sign ? 0x80 : 0x00; - p = &v; - } else if (IS_NAN(fp) || IS_INF(fp)) { - FPU_EXCEPTION(IA_EXCEPTION, 0); - p = &indefinite_bcd; - } else if (IS_DENORMAL(fp)) { - memset(&v, 0, sizeof(v)); - /* XXX */ - p = &v; - } else { - if (fp->exp >= 0 && fp->exp < 59) { - n = fp->num >> (63 - fp->exp); - valid = 1; - } else if (fp->exp == 59) { - n = fp->num >> (63 - 59); - if (n < QWORD_CONST(1000000000000000000)) { - valid = 1; - } else { - valid = 0; - } - } else { - n = 0; - valid = 0; - } - - if (valid) { - for (i = 0; i < 9; ++i) { - v.b[i] = (n % 10); - n /= 10; - v.b[i] += (n % 10) << 4; - n /= 10; - } - v.b[9] = fp->sign ? 0x80 : 0x00; - p = &v; - } else { - FPU_EXCEPTION(IA_EXCEPTION, 0); - p = &indefinite_bcd; - } - } - - fpu_memorywrite_f(address, p); -} - -/* - * FPU misc. - */ -static UINT16 -fpu_get_tag(void) -{ - FP_REG *fp; - UINT16 tag; - UINT v; - int i; - - tag = 0; - for (i = 0; i < FPU_REG_NUM; ++i) { - fp = &FPU_REG(i); - if (!IS_VALID(fp)) { - v = 0x11; - } else if (IS_ZERO(fp)) { - v = 0x01; - } else if (IS_NAN(fp) || IS_INF(fp) || IS_DENORMAL(fp)) { - v = 0x10; - } else { - v = 0x11; - } - tag |= v << (i * 2); - } - return tag; -} - - -/* - * FPU interface - */ -void -fpu_init(void) -{ - int i; - - for (i = 0; i < FPU_REG_NUM; i++) { - memset(&FPU_STAT.reg[i], 0, sizeof(FP_REG)); - } - - FPU_CTRLWORD = 0x037f; - FPU_STATUSWORD = 0; - FPU_INSTPTR = zero_ptr; - FPU_DATAPTR = zero_ptr; - FPU_LASTINSTOP = 0; - - FPU_STAT_TOP = 0; - FPU_STAT_PC = FP_CTRL_PC_64; - FPU_STAT_RC = FP_CTRL_RC_NEAREST_EVEN; - -} - -char * -fpu_reg2str(void) -{ - static char buf[512]; - char tmp[128]; - -#if 0 - strcpy(buf, "st=\n"); - for (i = 0; i < FPU_REG_NUM; i++) { - snprintf(tmp, sizeof(tmp), "%02x", FPU_REG(i)); - strcat(buf, tmp); - } - strcat(buf, "\n"); - } -#endif - - snprintf(tmp, sizeof(tmp), - "ctrl=%04x status=%04x tag=%04x\n" - "inst=%04x:%08x data=%04x:%08x op=%03x\n", - FPU_CTRLWORD, FPU_STATUSWORD, fpu_get_tag(), - FPU_INSTPTR_SEG, FPU_INSTPTR_OFFSET, - FPU_DATAPTR_SEG, FPU_DATAPTR_OFFSET, - FPU_LASTINSTOP); - strcat(buf, tmp); - - return buf; -} - - -/* - * FPU instruction - */ -void -fpu_fwait(void) -{ - - /* XXX: check pending FPU exception */ -} - -void -ESC0(void) -{ - UINT32 op, madr; - UINT idx; - - if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - GET_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FADD */ - case 1: /* FMUL */ - case 2: /* FCOM */ - case 3: /* FCOMP */ - case 4: /* FSUB */ - case 5: /* FSUBR */ - case 6: /* FDIV */ - case 7: /* FDIVR */ - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FADD (単精度実数) */ - case 1: /* FMUL (単精度実数) */ - case 2: /* FCOM (単精度実数) */ - case 3: /* FCOMP (単精度実数) */ - case 4: /* FSUB (単精度実数) */ - case 5: /* FSUBR (単精度実数) */ - case 6: /* FDIV (単精度実数) */ - case 7: /* FDIVR (単精度実数) */ - break; - } - } -} - -void -ESC1(void) -{ - FP_REG *st0; - UINT32 op, madr; - UINT idx; - - if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - GET_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - switch (op & 0xf0) { - case 0xc0: - if (!(op & 0x08)) { - /* FLD ST(0), ST(i) */ - } else { - /* FXCH ST(0), ST(i) */ - } - break; - - case 0xd0: - if (op == 0xd0) { - /* FNOP */ - break; - } - EXCEPTION(UD_EXCEPTION, 0); - break; - - case 0xe0: - switch (op & 0x0f) { - case 0x0: /* FCHS */ - break; - - case 0x1: /* FABS */ - st0 = &FPU_ST(0); - FPU_STATUSWORD &= ~FP_C1_FLAG; - if (IS_VALID(st0)) { - if (!IS_NAN(st0)) { - st0->sign = 0; - } - } else { - FPU_EXCEPTION(IS_EXCEPTION, 0); - } - break; - - case 0x4: /* FTST */ - case 0x5: /* FXAM */ - case 0x8: /* FLD1 */ - case 0x9: /* FLDL2T */ - case 0xa: /* FLDL2E */ - case 0xb: /* FLDPI */ - case 0xc: /* FLDLG2 */ - case 0xd: /* FLDLN2 */ - case 0xe: /* FLDZ */ - break; - - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - break; - - case 0xf0: - switch (op & 0xf) { - case 0x0: /* F2XM1 */ - case 0x1: /* FYL2X */ - case 0x2: /* FPTAN */ - case 0x3: /* FPATAN */ - case 0x4: /* FXTRACT */ - case 0x5: /* FPREM1 */ - case 0x6: /* FDECSTP */ - case 0x7: /* FINCSTP */ - case 0x8: /* FPREM */ - case 0x9: /* FYL2XP1 */ - case 0xa: /* FSQRT */ - case 0xb: /* FSINCOS */ - case 0xc: /* FRNDINT */ - case 0xd: /* FSCALE */ - case 0xe: /* FSIN */ - case 0xf: /* FCOS */ - break; - } - break; - - default: - ia32_panic("ESC1: invalid opcode = %02x\n", op); - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FLD (単精度実数) */ - case 2: /* FST (単精度実数) */ - case 3: /* FSTP (単精度実数) */ - case 4: /* FLDENV */ - case 5: /* FLDCW */ - case 6: /* FSTENV */ - break; - - case 7: /* FSTCW */ - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, - FPU_CTRLWORD); - break; - - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } -} - -void -ESC2(void) -{ - UINT32 op, madr; - UINT idx; - - if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - GET_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FCMOVB */ - case 1: /* FCMOVE */ - case 2: /* FCMOVBE */ - case 3: /* FCMOVU */ - break; - - case 5: - if (op == 0xe9) { - /* FUCOMPP */ - break; - } - /*FALLTHROUGH*/ - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FIADD (DWORD) */ - case 1: /* FIMUL (DWORD) */ - case 2: /* FICOM (DWORD) */ - case 3: /* FICOMP (DWORD) */ - case 4: /* FISUB (DWORD) */ - case 5: /* FISUBR (DWORD) */ - case 6: /* FIDIV (DWORD) */ - case 7: /* FIDIVR (DWORD) */ - break; - } - } -} - -void -ESC3(void) -{ - UINT32 op, madr; - UINT idx; - - if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - GET_PCBYTE(op); - if (op == 0xe3) { - /* FNINIT */ - fpu_init(); - return; - } - idx = (op >> 3) & 7; - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FCMOVNB */ - case 1: /* FCMOVNE */ - case 2: /* FCMOVBE */ - case 3: /* FCMOVNU */ - case 5: /* FUCOMI */ - case 6: /* FCOMI */ - break; - - case 4: - if (op == 0xe2) { - /* FCLEX */ - break; - } - /*FALLTHROUGH*/ - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FILD (DWORD) */ - case 2: /* FIST (DWORD) */ - case 3: /* FISTP (DWORD) */ - case 5: /* FLD (拡張実数) */ - case 7: /* FSTP (拡張実数) */ - break; - - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } -} - -void -ESC4(void) -{ - UINT32 op, madr; - UINT idx; - - if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - GET_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - /* Fxxx ST(i), ST(0) */ - switch (idx) { - case 0: /* FADD */ - case 1: /* FMUL */ - case 4: /* FSUBR */ - case 5: /* FSUB */ - case 6: /* FDIVR */ - case 7: /* FDIV */ - break; - - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FADD (倍精度実数) */ - case 1: /* FMUL (倍精度実数) */ - case 2: /* FCOM (倍精度実数) */ - case 3: /* FCOMP (倍精度実数) */ - case 4: /* FSUB (倍精度実数) */ - case 5: /* FSUBR (倍精度実数) */ - case 6: /* FDIV (倍精度実数) */ - case 7: /* FDIVR (倍精度実数) */ - break; - } - } -} - -void -ESC5(void) -{ - UINT32 op, madr; - UINT idx; - - if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - GET_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - /* FUCOM ST(i), ST(0) */ - /* Fxxx ST(i) */ - switch (idx) { - case 0: /* FFREE */ - case 2: /* FST */ - case 3: /* FSTP */ - case 4: /* FUCOM */ - case 5: /* FUCOMP */ - break; - - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FLD (倍精度実数) */ - case 2: /* FST (倍精度実数) */ - case 3: /* FSTP (倍精度実数) */ - case 4: /* FRSTOR */ - case 6: /* FSAVE */ - break; - - case 7: /* FSTSW */ - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, - FPU_STATUSWORD); - break; - - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } -} - -void -ESC6(void) -{ - UINT32 op, madr; - UINT idx; - - if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - GET_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - /* Fxxx ST(i), ST(0) */ - switch (idx) { - case 0: /* FADDP */ - case 1: /* FMULP */ - case 4: /* FSUBRP */ - case 5: /* FSUBP */ - case 6: /* FDIVRP */ - case 7: /* FFIVP */ - break; - - case 3: - if (op == 0xd9) { - /* FCOMPP */ - break; - } - /*FALLTHROUGH*/ - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FIADD (WORD) */ - case 1: /* FIMUL (WORD) */ - case 2: /* FICOM (WORD) */ - case 3: /* FICOMP (WORD) */ - case 4: /* FISUB (WORD) */ - case 5: /* FISUBR (WORD) */ - case 6: /* FIDIV (WORD) */ - case 7: /* FIDIVR (WORD) */ - break; - } - } -} - -void -ESC7(void) -{ - FP_REG *st0; - UINT32 op, madr; - UINT idx; - int valid; - - if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - GET_PCBYTE(op); - idx = (op >> 3) & 7; - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 6: /* FCOMIP */ - case 7: /* FUCOMIP */ - break; - - case 5: - if (op == 0xe0) { - /* FSTSW AX */ - CPU_AX = FPU_STATUSWORD; - break; - } - /*FALLTHROUGH*/ - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FILD (WORD) */ - case 2: /* FIST (WORD) */ - case 3: /* FISTP (WORD) */ - break; - - case 4: /* FBLD (BCD) */ - st0 = &FPU_ST(-1); - valid = IS_VALID(st0); - if (valid) { - /* stack overflow */ - FPU_STATUSWORD |= FP_C1_FLAG; - FPU_EXCEPTION(IS_EXCEPTION, 0); - } - fp_load_bcd_integer(st0, madr); - if (!valid) { - FPU_STATUSWORD &= ~FP_C1_FLAG; - } - FPU_STAT_TOP_DEC(); - break; - - case 5: /* FILD (QWORD) */ - break; - - case 6: /* FBSTP (BCD) */ - st0 = &FPU_ST(0); - if (!IS_VALID(st0)) { - /* stack underflow */ - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_EXCEPTION(IS_EXCEPTION, 0); - } - fp_store_bcd(st0, madr); - st0->valid = 0; - FPU_STAT_TOP_INC(); - break; - - case 7: /* FISTP (QWORD) */ - break; - - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } -} - -//void -//ESC0(void) -//{ -// UINT32 op, madr; -// -// GET_PCBYTE(op); -// TRACEOUT(("use FPU d8 %.2x", op)); -// if (op >= 0xc0) { -// EXCEPTION(NM_EXCEPTION, 0); -// } else { -// madr = calc_ea_dst(op); -// EXCEPTION(NM_EXCEPTION, 0); -// } -//} -// -//void -//ESC1(void) -//{ -// UINT32 op, madr; -// -// GET_PCBYTE(op); -// TRACEOUT(("use FPU d9 %.2x", op)); -// if (op >= 0xc0) { -// EXCEPTION(NM_EXCEPTION, 0); -// } else { -// madr = calc_ea_dst(op); -// switch (op & 0x38) { -// case 0x28: -// TRACEOUT(("FLDCW")); -// (void) cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); -// break; -// -// case 0x38: -// TRACEOUT(("FSTCW")); -// cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, 0xffff); -// break; -// -// default: -// EXCEPTION(NM_EXCEPTION, 0); -// break; -// } -// } -//} -// -//void -//ESC2(void) -//{ -// UINT32 op, madr; -// -// GET_PCBYTE(op); -// TRACEOUT(("use FPU da %.2x", op)); -// if (op >= 0xc0) { -// EXCEPTION(NM_EXCEPTION, 0); -// } else { -// madr = calc_ea_dst(op); -// EXCEPTION(NM_EXCEPTION, 0); -// } -//} -// -//void -//ESC3(void) -//{ -// UINT32 op, madr; -// -// GET_PCBYTE(op); -// TRACEOUT(("use FPU db %.2x", op)); -// if (op >= 0xc0) { -// if (op != 0xe3) { -// EXCEPTION(NM_EXCEPTION, 0); -// } -// /* FNINIT */ -// (void)madr; -// } else { -// madr = calc_ea_dst(op); -// EXCEPTION(NM_EXCEPTION, 0); -// } -//} -// -//void -//ESC4(void) -//{ -// UINT32 op, madr; -// -// GET_PCBYTE(op); -// TRACEOUT(("use FPU dc %.2x", op)); -// if (op >= 0xc0) { -// EXCEPTION(NM_EXCEPTION, 0); -// } else { -// madr = calc_ea_dst(op); -// EXCEPTION(NM_EXCEPTION, 0); -// } -//} -// -//void -//ESC5(void) -//{ -// UINT32 op, madr; -// -// GET_PCBYTE(op); -// TRACEOUT(("use FPU dd %.2x", op)); -// if (op >= 0xc0) { -// EXCEPTION(NM_EXCEPTION, 0); -// } else { -// madr = calc_ea_dst(op); -// if (((op >> 3) & 7) != 7) { -// EXCEPTION(NM_EXCEPTION, 0); -// } -// /* FSTSW */ -// TRACEOUT(("FSTSW")); -// cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, 0xffff); -// } -//} -// -//void -//ESC6(void) -//{ -// UINT32 op, madr; -// -// GET_PCBYTE(op); -// TRACEOUT(("use FPU de %.2x", op)); -// if (op >= 0xc0) { -// EXCEPTION(NM_EXCEPTION, 0); -// } else { -// madr = calc_ea_dst(op); -// EXCEPTION(NM_EXCEPTION, 0); -// } -//} -// -//void -//ESC7(void) -//{ -// UINT32 op, madr; -// -// GET_PCBYTE(op); -// TRACEOUT(("use FPU df %.2x", op)); -// if (op >= 0xc0) { -// if (op != 0xe0) { -// EXCEPTION(NM_EXCEPTION, 0); -// } -// /* FSTSW AX */ -// TRACEOUT(("FSTSW AX")); -// CPU_AX = 0xffff; -// } else { -// madr = calc_ea_dst(op); -// EXCEPTION(NM_EXCEPTION, 0); -// } -//} - - -#if 0 -/* ----- */ - -/* - * 加減算 - */ -void -fp_add_sub(FP_REG *t, FP_REG *d, FP_REG *s) -{ - FP_REG *u, *v; - SINT32 diff_exp; - - /* チェック */ - if (IS_NAN(s) || IS_NAN(d)) { - SET_NAN(t); - return; - } - if (IS_INF(s) || IS_INF(d)) { - if (IS_INF(s) && IS_INF(d) && (s->sign != d->sign)) { - /* #IA 浮動小数点無効算術オペランド例外 */ - } else { - t->sign = IS_INF(d) ? s->sign : d->sign; - SET_INF(t); - } - return; - } - if (IS_ZERO(a) || IS_ZERO(d)) { - *t = IS_ZERO(d) ? *s : *d; - return; - } - if (IS_DENORM(s)) { - /* cause #D, s is DENORM */ - return; - } - if (IS_DENORM(d)) { - } - - /* 計算 */ - diff_exp = d->exp - s->exp; - if (diff_exp >= PRECISION_NBIT + 2) { - *t = *d; - u = d; - v = s; - } else if (diff_exp <= -(PRECISION_NBIT + 2)) { - *t = *s; - u = s; - v = d; - } else { - if (diff_exp == 0) { - u = d; - v = s; - /* XXX */ - } else if (diff_exp > 0) { - u = d; - v = s; - t->sign = u->sign; - } else if (diff_exp < 0) { - diff_exp = diff_exp * -1; - u = s; - v = d; - t->sign = u->sign; - } - } - - /* 正規化 */ -} -#endif +/* + * Copyright (c) 2012 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include + +#include +#include "ia32/ia32.mcr" + +#include + +/* +Short Real + 31: sign (符号) +30-23: exp-8 (指数部: exponet) +22-00: num-23 (小数部) + +Long Real + 63: sign +62-52: exp-11 +51-00: num-52 + +Temp Real + 79: sign +78-64: exp-15 + 63: 1(?) +62-00: num-63 + +-- +指数部: +2 の 0 乗のとき 0111 1111 となる +1000 0001: +2 乗 +1000 0000: +1 乗 +0111 1111: 0 乗 +0111 1110: -1 乗 + +仮数部: +2 を基数として整数部が一桁になるように正規化した数の 2 進数表現となる。 +正規化によって仮数部の最上位ビットは常に 1 になるので実際に用意しておく +必要はなく、倍精度の 52 ビットであれば最上位の 1 を hidden bit にして +含めなければ、53 ビット分の情報が含まれることになる。 + +小数の二進数表現: +0.1000 1/2 = 0.5 +0.0100 1/(2*2) = 0.25 +0.0010 1/(2*2*2) = 0.125 +0.0001 1/(2*2*2*2) = 0.0625 +*/ + +#define PRECISION_NBIT 64 +#define EXP_OFFSET 0x3fff + +#define IS_VALID(f) (f)->valid +#define IS_ZERO(f) (f)->zero +#define IS_INF(f) (f)->inf +#define IS_NAN(f) (f)->nan +#define IS_DENORMAL(f) (f)->denorm + +#define SET_ZERO(f) \ +do \ +{ \ + (f)->zero = 1; \ + (f)->inf = 0; \ + (f)->nan = 0; \ + (f)->denorm = 0; \ +} while (/*CONSTCOND*/0) + +#define SET_INF(f) \ +do \ +{ \ + (f)->zero = 0; \ + (f)->inf = 1; \ + (f)->nan = 0; \ + (f)->denorm = 0; \ +} while (/*CONSTCOND*/0) + +#define SET_NAN(f) \ +do \ +{ \ + (f)->zero = 0; \ + (f)->inf = 0; \ + (f)->nan = 1; \ + (f)->denorm = 0; \ +} while (/*CONSTCOND*/0) + + +/* +制御命令: +FINIT, FCLEX, FLDCW, FSTCW, FSTSW, GSTENV, FLDENV, FSAVE, FRSTOR, FWAIT +*/ + +void F2XM1(void); +void FABS(void); +void FADD(void); +void FADDP(void); +void FIADD(void); +void FBLD(void); +void FBSTP(void); +void FCHS(void); +void FCLEX(void); +void FNCLEX(void); +void FCOM(void); +void FCOMP(void); +void FCOMPP(void); +void FCOMI(void); +void FCOMIP(void); +void FUCOMI(void); +void FUCOMIP(void); +void FCOS(void); +void FDECSTP(void); +void FDIV(void); +void FDIVP(void); +void FIDIV(void); +void FDIVR(void); +void FDIVRP(void); +void FIDIVR(void); +void FFREE(void); +void FICOM(void); +void FICOMP(void); +void FILD(void); +void FINCSTP(void); +void FIST(void); +void FISTP(void); +void FLD(void); +void FLDCW(void); +void FLDENV(void); +void FMUL(void); +void FMULP(void); +void FNINIT(void); +void FIMUL(void); +void FNOP(void); +void FPATAN(void); +void FPREM(void); +void FPREM1(void); +void FPTAN(void); +void FRNDINT(void); +void FRSTOR(void); +void FSAVE(void); +void FNSAVE(void); +void _FSCALE(void); +void FSIN(void); +void FSINCOS(void); +void FSQRT(void); +void FST(void); +void FSTP(void); +void FNSTCW(void); +void FSTENV(void); +void FNSTENV(void); +void FNSTSW(void); +void FSUB(void); +void FSUBP(void); +void FISUB(void); +void FSUBR(void); +void FSUBRP(void); +void FISUBR(void); +void FTST(void); +void FUCOM(void); +void FUCOMP(void); +void FUCOMPP(void); +void FXAM(void); +void FXCH(void); +void FXTRACT(void); +void FYL2X(void); +void FYL2XP1(void); + +/* FMOVcc */ +void FCMOVB(void); +void FCMOVE(void); +void FCMOVBE(void); +void FCMOVU(void); +void FCMOVNB(void); +void FCMOVNE(void); +void FCMOVNBE(void); +void FCMOVNU(void); + +/* Load constant */ +void FLD1(void); +void FLDL2T(void); +void FLDL2E(void); +void FLDPI(void); +void FLDLG2(void); +void FLDLN2(void); +void FLDZ(void); + + +static const FPU_PTR zero_ptr = { 0, 0, 0 }; + +static const FP_REG fp_const_0 = { 1, 0, 1, 0, 0, 0, 0, 0 }; +static const FP_REG fp_const_1 = { 1, 0, 0, 0, 0, 0, 0, 0 }; + +static const FP_REG snan = { + 1, 1, 0, 0, 1, 0, 0, QWORD_CONST(0x00) /* SNaN */ +}; +static const FP_REG qnan = { + 1, 1, 0, 0, 1, 0, 0, QWORD_CONST(0x01) /* QNaN */ +}; +static const FP_REG indefinite_qnan = { + 1, 1, 0, 0, 1, 0, 0, QWORD_CONST(0x11) /* indef QNaN */ +}; + +static const REG80 indefinite_bcd = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff } +}; + +/* + * FPU exception + */ +enum { + IS_EXCEPTION, + IA_EXCEPTION, + Z_EXCEPTION, + D_EXCEPTION, + O_EXCEPTION, + U_EXCEPTION, + P_EXCEPTION, + FPU_EXCEPTION_NUM +}; + +static void CPUCALL +fpu_exception(int num, int async) +{ + UINT16 bit; + + switch (num) { + case IS_EXCEPTION: + FPU_STATUSWORD |= FP_SF_FLAG; + /*FALLTHROUGH*/ + case IA_EXCEPTION: + bit = FP_IE_FLAG; + break; + + case Z_EXCEPTION: + bit = FP_ZE_FLAG; + break; + + case D_EXCEPTION: + bit = FP_DE_FLAG; + break; + + case O_EXCEPTION: + bit = FP_OE_FLAG; + break; + + case U_EXCEPTION: + bit = FP_UE_FLAG; + break; + + case P_EXCEPTION: + bit = FP_PE_FLAG; + break; + + case FPU_EXCEPTION_NUM: + default: + ia32_panic("fpu_exception: unknown exception (%d)\n", num); + return; + } + + FPU_STATUSWORD |= bit; + + if (!(bit & FPU_CTRLWORD)) { + FPU_STATUSWORD |= FP_ES_FLAG|FP_B_FLAG; + if (CPU_CR0 & CPU_CR0_NE) { + /* native mode */ + if (!async) { + CPU_PREV_EIP = CPU_EIP; /* XXX */ + EXCEPTION(MF_EXCEPTION, 0); + } + } else { + /* MS-DOS compat. mode */ + /* XXX */ + } + } +} + +#define FPU_EXCEPTION(n,a) fpu_exception(n,a) + + +/* + * FPU memory access function + */ +static UINT16 MEMCALL +fpu_memoryread_w(UINT32 address) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + return cpu_vmemoryread_w(seg, address); +} + +static UINT32 MEMCALL +fpu_memoryread_d(UINT32 address) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + return cpu_vmemoryread_d(seg, address); +} + +static UINT64 MEMCALL +fpu_memoryread_q(UINT32 address) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + return cpu_vmemoryread_q(seg, address); +} + +static REG80 MEMCALL +fpu_memoryread_f(UINT32 address) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + return cpu_vmemoryread_f(seg, address); +} + +static void MEMCALL +fpu_memorywrite_w(UINT32 address, UINT16 value) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + cpu_vmemorywrite_w(seg, address, value); +} + +static void MEMCALL +fpu_memorywrite_d(UINT32 address, UINT32 value) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + cpu_vmemorywrite_d(seg, address, value); +} + +static void MEMCALL +fpu_memorywrite_q(UINT32 address, UINT64 value) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + cpu_vmemorywrite_q(seg, address, value); +} + +static void MEMCALL +fpu_memorywrite_f(UINT32 address, REG80 *value) +{ + UINT16 seg; + + FPU_DATAPTR_SEG = seg = CPU_INST_SEGREG_INDEX; + FPU_DATAPTR_OFFSET = address; + cpu_vmemorywrite_f(seg, address, value); +} + +/* + * FPU memory load function + */ +static void MEMCALL +fp_load_integer(FP_REG *fp, int sign, UINT64 value) +{ + int exp; + + fp->valid = 1; + fp->sign = sign ? 1 : 0; + fp->zero = (value == 0); + fp->nan = 0; + fp->inf = 0; + fp->denorm = 0; + + if (!IS_ZERO(fp)) { + for (exp = 0; exp < 64; ++exp, value <<= 1) { + if (value & QWORD_CONST(0x8000000000000000)) { + break; + } + } + fp->num = value; + fp->exp = (UINT16)exp; + } +} + +static void MEMCALL +fp_load_word_integer(FP_REG *fp, UINT32 address) +{ + UINT64 n; + UINT16 v; + int sign; + + v = fpu_memoryread_w(address); + + sign = (v & 0x8000) ? 1 : 0; + n = sign ? -v : v; + + fp_load_integer(fp, sign, n); +} + +static void MEMCALL +fp_load_short_integer(FP_REG *fp, UINT32 address) +{ + UINT64 n; + UINT32 v; + int sign; + + v = fpu_memoryread_d(address); + + sign = (v & 0x80000000UL) ? 1 : 0; + n = sign ? -v : v; + + fp_load_integer(fp, sign, n); +} + +static void MEMCALL +fp_load_long_integer(FP_REG *fp, UINT32 address) +{ + UINT64 n; + UINT64 v; + int sign; + + v = fpu_memoryread_q(address); + + sign = (v & QWORD_CONST(0x8000000000000000)) ? 1 : 0; + n = sign ? -v : v; + + fp_load_integer(fp, sign, n); +} + +static void MEMCALL +fp_load_bcd_integer(FP_REG *fp, UINT32 address) +{ + REG80 v; + UINT64 n; + int sign; + int i, t; + + v = fpu_memoryread_f(address); + + n = 0; + for (i = 0; i < 4; ++i) { + t = v.b[i] & 0xf; + if (t > 9) { + goto indefinite; + } + n = (n * 10) + t; + + t = (v.b[i] >> 4) & 0xf; + if (t > 9) { + goto indefinite; + } + n = (n * 10) + t; + } + sign = v.b[9] & 0x80; + + fp_load_integer(fp, sign, n); + return; + + indefinite: + *fp = indefinite_qnan; + return; +} + +/* + * FPU memory strore function + */ +static void MEMCALL +fp_store_bcd(FP_REG *fp, UINT32 address) +{ + const REG80 *p; + REG80 v; + UINT64 n; + int valid; + int i; + + if (IS_ZERO(fp)) { + memset(&v, 0, sizeof(v)); + v.b[9] = fp->sign ? 0x80 : 0x00; + p = &v; + } else if (IS_NAN(fp) || IS_INF(fp)) { + FPU_EXCEPTION(IA_EXCEPTION, 0); + p = &indefinite_bcd; + } else if (IS_DENORMAL(fp)) { + memset(&v, 0, sizeof(v)); + /* XXX */ + p = &v; + } else { + if (fp->exp >= 0 && fp->exp < 59) { + n = fp->num >> (63 - fp->exp); + valid = 1; + } else if (fp->exp == 59) { + n = fp->num >> (63 - 59); + if (n < QWORD_CONST(1000000000000000000)) { + valid = 1; + } else { + valid = 0; + } + } else { + n = 0; + valid = 0; + } + + if (valid) { + for (i = 0; i < 9; ++i) { + v.b[i] = (n % 10); + n /= 10; + v.b[i] += (n % 10) << 4; + n /= 10; + } + v.b[9] = fp->sign ? 0x80 : 0x00; + p = &v; + } else { + FPU_EXCEPTION(IA_EXCEPTION, 0); + p = &indefinite_bcd; + } + } + + fpu_memorywrite_f(address, p); +} + +/* + * FPU misc. + */ +static UINT16 +fpu_get_tag(void) +{ + FP_REG *fp; + UINT16 tag; + UINT v; + int i; + + tag = 0; + for (i = 0; i < FPU_REG_NUM; ++i) { + fp = &FPU_REG(i); + if (!IS_VALID(fp)) { + v = 0x11; + } else if (IS_ZERO(fp)) { + v = 0x01; + } else if (IS_NAN(fp) || IS_INF(fp) || IS_DENORMAL(fp)) { + v = 0x10; + } else { + v = 0x11; + } + tag |= v << (i * 2); + } + return tag; +} + + +/* + * FPU interface + */ +void +fpu_init(void) +{ + int i; + + for (i = 0; i < FPU_REG_NUM; i++) { + memset(&FPU_STAT.reg[i], 0, sizeof(FP_REG)); + } + + FPU_CTRLWORD = 0x037f; + FPU_STATUSWORD = 0; + FPU_INSTPTR = zero_ptr; + FPU_DATAPTR = zero_ptr; + FPU_LASTINSTOP = 0; + + FPU_STAT_TOP = 0; + FPU_STAT_PC = FP_CTRL_PC_64; + FPU_STAT_RC = FP_CTRL_RC_NEAREST_EVEN; + +} + +char * +fpu_reg2str(void) +{ + static char buf[512]; + char tmp[128]; + +#if 0 + strcpy(buf, "st=\n"); + for (i = 0; i < FPU_REG_NUM; i++) { + snprintf(tmp, sizeof(tmp), "%02x", FPU_REG(i)); + strcat(buf, tmp); + } + strcat(buf, "\n"); + } +#endif + + snprintf(tmp, sizeof(tmp), + "ctrl=%04x status=%04x tag=%04x\n" + "inst=%04x:%08x data=%04x:%08x op=%03x\n", + FPU_CTRLWORD, FPU_STATUSWORD, fpu_get_tag(), + FPU_INSTPTR_SEG, FPU_INSTPTR_OFFSET, + FPU_DATAPTR_SEG, FPU_DATAPTR_OFFSET, + FPU_LASTINSTOP); + strcat(buf, tmp); + + return buf; +} + + +/* + * FPU instruction + */ +void +fpu_fwait(void) +{ + + /* XXX: check pending FPU exception */ +} + +void +ESC0(void) +{ + UINT32 op, madr; + UINT idx; + + if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + GET_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FADD */ + case 1: /* FMUL */ + case 2: /* FCOM */ + case 3: /* FCOMP */ + case 4: /* FSUB */ + case 5: /* FSUBR */ + case 6: /* FDIV */ + case 7: /* FDIVR */ + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FADD (単精度実数) */ + case 1: /* FMUL (単精度実数) */ + case 2: /* FCOM (単精度実数) */ + case 3: /* FCOMP (単精度実数) */ + case 4: /* FSUB (単精度実数) */ + case 5: /* FSUBR (単精度実数) */ + case 6: /* FDIV (単精度実数) */ + case 7: /* FDIVR (単精度実数) */ + break; + } + } +} + +void +ESC1(void) +{ + FP_REG *st0; + UINT32 op, madr; + UINT idx; + + if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + GET_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + switch (op & 0xf0) { + case 0xc0: + if (!(op & 0x08)) { + /* FLD ST(0), ST(i) */ + } else { + /* FXCH ST(0), ST(i) */ + } + break; + + case 0xd0: + if (op == 0xd0) { + /* FNOP */ + break; + } + EXCEPTION(UD_EXCEPTION, 0); + break; + + case 0xe0: + switch (op & 0x0f) { + case 0x0: /* FCHS */ + break; + + case 0x1: /* FABS */ + st0 = &FPU_ST(0); + FPU_STATUSWORD &= ~FP_C1_FLAG; + if (IS_VALID(st0)) { + if (!IS_NAN(st0)) { + st0->sign = 0; + } + } else { + FPU_EXCEPTION(IS_EXCEPTION, 0); + } + break; + + case 0x4: /* FTST */ + case 0x5: /* FXAM */ + case 0x8: /* FLD1 */ + case 0x9: /* FLDL2T */ + case 0xa: /* FLDL2E */ + case 0xb: /* FLDPI */ + case 0xc: /* FLDLG2 */ + case 0xd: /* FLDLN2 */ + case 0xe: /* FLDZ */ + break; + + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + break; + + case 0xf0: + switch (op & 0xf) { + case 0x0: /* F2XM1 */ + case 0x1: /* FYL2X */ + case 0x2: /* FPTAN */ + case 0x3: /* FPATAN */ + case 0x4: /* FXTRACT */ + case 0x5: /* FPREM1 */ + case 0x6: /* FDECSTP */ + case 0x7: /* FINCSTP */ + case 0x8: /* FPREM */ + case 0x9: /* FYL2XP1 */ + case 0xa: /* FSQRT */ + case 0xb: /* FSINCOS */ + case 0xc: /* FRNDINT */ + case 0xd: /* FSCALE */ + case 0xe: /* FSIN */ + case 0xf: /* FCOS */ + break; + } + break; + + default: + ia32_panic("ESC1: invalid opcode = %02x\n", op); + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FLD (単精度実数) */ + case 2: /* FST (単精度実数) */ + case 3: /* FSTP (単精度実数) */ + case 4: /* FLDENV */ + case 5: /* FLDCW */ + case 6: /* FSTENV */ + break; + + case 7: /* FSTCW */ + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, + FPU_CTRLWORD); + break; + + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } +} + +void +ESC2(void) +{ + UINT32 op, madr; + UINT idx; + + if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + GET_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FCMOVB */ + case 1: /* FCMOVE */ + case 2: /* FCMOVBE */ + case 3: /* FCMOVU */ + break; + + case 5: + if (op == 0xe9) { + /* FUCOMPP */ + break; + } + /*FALLTHROUGH*/ + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FIADD (DWORD) */ + case 1: /* FIMUL (DWORD) */ + case 2: /* FICOM (DWORD) */ + case 3: /* FICOMP (DWORD) */ + case 4: /* FISUB (DWORD) */ + case 5: /* FISUBR (DWORD) */ + case 6: /* FIDIV (DWORD) */ + case 7: /* FIDIVR (DWORD) */ + break; + } + } +} + +void +ESC3(void) +{ + UINT32 op, madr; + UINT idx; + + if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + GET_PCBYTE(op); + if (op == 0xe3) { + /* FNINIT */ + fpu_init(); + return; + } + idx = (op >> 3) & 7; + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FCMOVNB */ + case 1: /* FCMOVNE */ + case 2: /* FCMOVBE */ + case 3: /* FCMOVNU */ + case 5: /* FUCOMI */ + case 6: /* FCOMI */ + break; + + case 4: + if (op == 0xe2) { + /* FCLEX */ + break; + } + /*FALLTHROUGH*/ + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FILD (DWORD) */ + case 2: /* FIST (DWORD) */ + case 3: /* FISTP (DWORD) */ + case 5: /* FLD (拡張実数) */ + case 7: /* FSTP (拡張実数) */ + break; + + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } +} + +void +ESC4(void) +{ + UINT32 op, madr; + UINT idx; + + if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + GET_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + /* Fxxx ST(i), ST(0) */ + switch (idx) { + case 0: /* FADD */ + case 1: /* FMUL */ + case 4: /* FSUBR */ + case 5: /* FSUB */ + case 6: /* FDIVR */ + case 7: /* FDIV */ + break; + + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FADD (倍精度実数) */ + case 1: /* FMUL (倍精度実数) */ + case 2: /* FCOM (倍精度実数) */ + case 3: /* FCOMP (倍精度実数) */ + case 4: /* FSUB (倍精度実数) */ + case 5: /* FSUBR (倍精度実数) */ + case 6: /* FDIV (倍精度実数) */ + case 7: /* FDIVR (倍精度実数) */ + break; + } + } +} + +void +ESC5(void) +{ + UINT32 op, madr; + UINT idx; + + if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + GET_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + /* FUCOM ST(i), ST(0) */ + /* Fxxx ST(i) */ + switch (idx) { + case 0: /* FFREE */ + case 2: /* FST */ + case 3: /* FSTP */ + case 4: /* FUCOM */ + case 5: /* FUCOMP */ + break; + + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FLD (倍精度実数) */ + case 2: /* FST (倍精度実数) */ + case 3: /* FSTP (倍精度実数) */ + case 4: /* FRSTOR */ + case 6: /* FSAVE */ + break; + + case 7: /* FSTSW */ + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, + FPU_STATUSWORD); + break; + + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } +} + +void +ESC6(void) +{ + UINT32 op, madr; + UINT idx; + + if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + GET_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + /* Fxxx ST(i), ST(0) */ + switch (idx) { + case 0: /* FADDP */ + case 1: /* FMULP */ + case 4: /* FSUBRP */ + case 5: /* FSUBP */ + case 6: /* FDIVRP */ + case 7: /* FFIVP */ + break; + + case 3: + if (op == 0xd9) { + /* FCOMPP */ + break; + } + /*FALLTHROUGH*/ + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FIADD (WORD) */ + case 1: /* FIMUL (WORD) */ + case 2: /* FICOM (WORD) */ + case 3: /* FICOMP (WORD) */ + case 4: /* FISUB (WORD) */ + case 5: /* FISUBR (WORD) */ + case 6: /* FIDIV (WORD) */ + case 7: /* FIDIVR (WORD) */ + break; + } + } +} + +void +ESC7(void) +{ + FP_REG *st0; + UINT32 op, madr; + UINT idx; + int valid; + + if (CPU_CR0 & (CPU_CR0_EM|CPU_CR0_TS)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + GET_PCBYTE(op); + idx = (op >> 3) & 7; + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 6: /* FCOMIP */ + case 7: /* FUCOMIP */ + break; + + case 5: + if (op == 0xe0) { + /* FSTSW AX */ + CPU_AX = FPU_STATUSWORD; + break; + } + /*FALLTHROUGH*/ + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FILD (WORD) */ + case 2: /* FIST (WORD) */ + case 3: /* FISTP (WORD) */ + break; + + case 4: /* FBLD (BCD) */ + st0 = &FPU_ST(-1); + valid = IS_VALID(st0); + if (valid) { + /* stack overflow */ + FPU_STATUSWORD |= FP_C1_FLAG; + FPU_EXCEPTION(IS_EXCEPTION, 0); + } + fp_load_bcd_integer(st0, madr); + if (!valid) { + FPU_STATUSWORD &= ~FP_C1_FLAG; + } + FPU_STAT_TOP_DEC(); + break; + + case 5: /* FILD (QWORD) */ + break; + + case 6: /* FBSTP (BCD) */ + st0 = &FPU_ST(0); + if (!IS_VALID(st0)) { + /* stack underflow */ + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_EXCEPTION(IS_EXCEPTION, 0); + } + fp_store_bcd(st0, madr); + st0->valid = 0; + FPU_STAT_TOP_INC(); + break; + + case 7: /* FISTP (QWORD) */ + break; + + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } +} + +//void +//ESC0(void) +//{ +// UINT32 op, madr; +// +// GET_PCBYTE(op); +// TRACEOUT(("use FPU d8 %.2x", op)); +// if (op >= 0xc0) { +// EXCEPTION(NM_EXCEPTION, 0); +// } else { +// madr = calc_ea_dst(op); +// EXCEPTION(NM_EXCEPTION, 0); +// } +//} +// +//void +//ESC1(void) +//{ +// UINT32 op, madr; +// +// GET_PCBYTE(op); +// TRACEOUT(("use FPU d9 %.2x", op)); +// if (op >= 0xc0) { +// EXCEPTION(NM_EXCEPTION, 0); +// } else { +// madr = calc_ea_dst(op); +// switch (op & 0x38) { +// case 0x28: +// TRACEOUT(("FLDCW")); +// (void) cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); +// break; +// +// case 0x38: +// TRACEOUT(("FSTCW")); +// cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, 0xffff); +// break; +// +// default: +// EXCEPTION(NM_EXCEPTION, 0); +// break; +// } +// } +//} +// +//void +//ESC2(void) +//{ +// UINT32 op, madr; +// +// GET_PCBYTE(op); +// TRACEOUT(("use FPU da %.2x", op)); +// if (op >= 0xc0) { +// EXCEPTION(NM_EXCEPTION, 0); +// } else { +// madr = calc_ea_dst(op); +// EXCEPTION(NM_EXCEPTION, 0); +// } +//} +// +//void +//ESC3(void) +//{ +// UINT32 op, madr; +// +// GET_PCBYTE(op); +// TRACEOUT(("use FPU db %.2x", op)); +// if (op >= 0xc0) { +// if (op != 0xe3) { +// EXCEPTION(NM_EXCEPTION, 0); +// } +// /* FNINIT */ +// (void)madr; +// } else { +// madr = calc_ea_dst(op); +// EXCEPTION(NM_EXCEPTION, 0); +// } +//} +// +//void +//ESC4(void) +//{ +// UINT32 op, madr; +// +// GET_PCBYTE(op); +// TRACEOUT(("use FPU dc %.2x", op)); +// if (op >= 0xc0) { +// EXCEPTION(NM_EXCEPTION, 0); +// } else { +// madr = calc_ea_dst(op); +// EXCEPTION(NM_EXCEPTION, 0); +// } +//} +// +//void +//ESC5(void) +//{ +// UINT32 op, madr; +// +// GET_PCBYTE(op); +// TRACEOUT(("use FPU dd %.2x", op)); +// if (op >= 0xc0) { +// EXCEPTION(NM_EXCEPTION, 0); +// } else { +// madr = calc_ea_dst(op); +// if (((op >> 3) & 7) != 7) { +// EXCEPTION(NM_EXCEPTION, 0); +// } +// /* FSTSW */ +// TRACEOUT(("FSTSW")); +// cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, 0xffff); +// } +//} +// +//void +//ESC6(void) +//{ +// UINT32 op, madr; +// +// GET_PCBYTE(op); +// TRACEOUT(("use FPU de %.2x", op)); +// if (op >= 0xc0) { +// EXCEPTION(NM_EXCEPTION, 0); +// } else { +// madr = calc_ea_dst(op); +// EXCEPTION(NM_EXCEPTION, 0); +// } +//} +// +//void +//ESC7(void) +//{ +// UINT32 op, madr; +// +// GET_PCBYTE(op); +// TRACEOUT(("use FPU df %.2x", op)); +// if (op >= 0xc0) { +// if (op != 0xe0) { +// EXCEPTION(NM_EXCEPTION, 0); +// } +// /* FSTSW AX */ +// TRACEOUT(("FSTSW AX")); +// CPU_AX = 0xffff; +// } else { +// madr = calc_ea_dst(op); +// EXCEPTION(NM_EXCEPTION, 0); +// } +//} + + +#if 0 +/* ----- */ + +/* + * 加減算 + */ +void +fp_add_sub(FP_REG *t, FP_REG *d, FP_REG *s) +{ + FP_REG *u, *v; + SINT32 diff_exp; + + /* チェック */ + if (IS_NAN(s) || IS_NAN(d)) { + SET_NAN(t); + return; + } + if (IS_INF(s) || IS_INF(d)) { + if (IS_INF(s) && IS_INF(d) && (s->sign != d->sign)) { + /* #IA 浮動小数点無効算術オペランド例外 */ + } else { + t->sign = IS_INF(d) ? s->sign : d->sign; + SET_INF(t); + } + return; + } + if (IS_ZERO(a) || IS_ZERO(d)) { + *t = IS_ZERO(d) ? *s : *d; + return; + } + if (IS_DENORM(s)) { + /* cause #D, s is DENORM */ + return; + } + if (IS_DENORM(d)) { + } + + /* 計算 */ + diff_exp = d->exp - s->exp; + if (diff_exp >= PRECISION_NBIT + 2) { + *t = *d; + u = d; + v = s; + } else if (diff_exp <= -(PRECISION_NBIT + 2)) { + *t = *s; + u = s; + v = d; + } else { + if (diff_exp == 0) { + u = d; + v = s; + /* XXX */ + } else if (diff_exp > 0) { + u = d; + v = s; + t->sign = u->sign; + } else if (diff_exp < 0) { + diff_exp = diff_exp * -1; + u = s; + v = d; + t->sign = u->sign; + } + } + + /* 正規化 */ +} +#endif diff --git a/i386c/ia32/instructions/fpu/fpemul_dosbox.c b/i386c/ia32/instructions/fpu/fpemul_dosbox.c old mode 100755 new mode 100644 index f94d7ed6..32a87fab --- a/i386c/ia32/instructions/fpu/fpemul_dosbox.c +++ b/i386c/ia32/instructions/fpu/fpemul_dosbox.c @@ -1,2006 +1,2006 @@ -/* - * Copyright (C) 2002-2015 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Copyright (c) 2012 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -/* - * modified by SimK - * 拡張倍精度浮動小数点ではなく倍精度浮動小数点で計算されるので実際のx87 FPUより精度が劣ります - */ - -#include - -#if defined(USE_FPU) && defined(SUPPORT_FPU_DOSBOX) - -#include -#include -#include -#include "ia32/ia32.mcr" - -#include -#include "ia32/instructions/fpu/fpumem.h" -#ifdef USE_SSE -#include "ia32/instructions/sse/sse.h" -#endif - -#if 1 -#undef TRACEOUT -#define TRACEOUT(s) (void)(s) -#endif /* 0 */ - -#define FPU_WORKCLOCK 6 - -#define PI 3.14159265358979323846 -#define L2E 1.4426950408889634 -#define L2T 3.3219280948873623 -#define LN2 0.69314718055994531 -#define LG2 0.3010299956639812 - -static void FPU_FINIT(void); - -static void -fpu_check_NM_EXCEPTION(){ - // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる - if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { - EXCEPTION(NM_EXCEPTION, 0); - } -} -static void -fpu_check_NM_EXCEPTION2(){ - // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる - if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { - EXCEPTION(NM_EXCEPTION, 0); - } -} - -static const FPU_PTR zero_ptr = { 0, 0, 0 }; - -/* - * FPU interface - */ - -static INLINE UINT FPU_GET_TOP(void) { - return (FPU_STATUSWORD & 0x3800)>>11; -} - -static INLINE void FPU_SET_TOP(UINT val){ - FPU_STATUSWORD &= ~0x3800; - FPU_STATUSWORD |= (val&7)<<11; -} - - -static INLINE void FPU_SET_C0(UINT C){ - FPU_STATUSWORD &= ~0x0100; - if(C) FPU_STATUSWORD |= 0x0100; -} - -static INLINE void FPU_SET_C1(UINT C){ - FPU_STATUSWORD &= ~0x0200; - if(C) FPU_STATUSWORD |= 0x0200; -} - -static INLINE void FPU_SET_C2(UINT C){ - FPU_STATUSWORD &= ~0x0400; - if(C) FPU_STATUSWORD |= 0x0400; -} - -static INLINE void FPU_SET_C3(UINT C){ - FPU_STATUSWORD &= ~0x4000; - if(C) FPU_STATUSWORD |= 0x4000; -} - -static INLINE void FPU_SET_D(UINT C){ - FPU_STATUSWORD &= ~0x0002; - if(C) FPU_STATUSWORD |= 0x0002; -} - -static INLINE void FPU_SetCW(UINT16 cword) -{ - // HACK: Bits 13-15 are not defined. Apparently, one program likes to test for - // Cyrix EMC87 by trying to set bit 15. We want the test program to see - // us as an Intel 287 when cputype == 286. - cword &= 0x7FFF; - FPU_CTRLWORD = cword; - FPU_STAT.round = (FP_RND)((cword >> 10) & 3); -} - -static void FPU_FLDCW(UINT32 addr) -{ - UINT16 temp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, addr); - FPU_SetCW(temp); -} - -static UINT16 FPU_GetTag(void) -{ - UINT i; - - UINT16 tag=0; - for(i=0;i<8;i++) - tag |= ( (FPU_STAT.tag[i]&3) <<(2*i)); - return tag; -} -static UINT8 FPU_GetTag8(void) -{ - UINT i; - - UINT8 tag=0; - for(i=0;i<8;i++) - tag |= ( (FPU_STAT.tag[i]==TAG_Empty ? 0 : 1) <<(i)); - return tag; -} - -static INLINE void FPU_SetTag(UINT16 tag) -{ - UINT i; - - for(i=0;i<8;i++){ - FPU_STAT.tag[i] = (FP_TAG)((tag >>(2*i))&3); - - } -} -static INLINE void FPU_SetTag8(UINT8 tag) -{ - UINT i; - - for(i=0;i<8;i++){ - FPU_STAT.tag[i] = (((tag>>i)&1) == 0 ? TAG_Empty : TAG_Valid); - } -} - -static void FPU_FCLEX(void){ - //FPU_STATUSWORD &= 0xff00; //should clear exceptions - FPU_STATUSWORD &= 0x7f00; //should clear exceptions? -} - -static void FPU_FNOP(void){ - return; -} - -static void FPU_PUSH(double in){ - FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; - //actually check if empty - FPU_STAT.tag[FPU_STAT_TOP] = TAG_Valid; - FPU_STAT.reg[FPU_STAT_TOP].d64 = in; -// LOG(LOG_FPU,LOG_ERROR)("Pushed at %d %g to the stack",newtop,in); - return; -} - -static void FPU_PREP_PUSH(void){ - FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; - FPU_STAT.tag[FPU_STAT_TOP] = TAG_Valid; -} - -static void FPU_FPOP(void){ - FPU_STAT.tag[FPU_STAT_TOP] = TAG_Empty; - //maybe set zero in it as well - FPU_STAT_TOP = ((FPU_STAT_TOP+1)&7); -// LOG(LOG_FPU,LOG_ERROR)("popped from %d %g off the stack",top,fpu.regs[top].d64); - return; -} - -static double FROUND(double in){ - switch(FPU_STAT.round){ - case ROUND_Nearest: - if (in-floor(in)>0.5) return (floor(in)+1); - else if (in-floor(in)<0.5) return (floor(in)); - else return ((((SINT64)(floor(in)))&1)!=0)?(floor(in)+1):(floor(in)); - break; - case ROUND_Down: - return (floor(in)); - break; - case ROUND_Up: - return (ceil(in)); - break; - case ROUND_Chop: - return in; //the cast afterwards will do it right maybe cast here - break; - default: - return in; - break; - } -} - -#define BIAS80 16383 -#define BIAS64 1023 - -static void FPU_FLD80(UINT32 addr, UINT reg) -{ - FP_REG result; - SINT64 exp64, exp64final; - SINT64 blah; - SINT64 mant64; - SINT64 sign; - - struct { - SINT16 begin; - FP_REG eind; - } test; - - test.eind.l.lower = fpu_memoryread_d(addr); - test.eind.l.upper = fpu_memoryread_d(addr+4); - test.begin = fpu_memoryread_w(addr+8); - - exp64 = (((test.begin&0x7fff) - BIAS80)); - blah = ((exp64 >0)?exp64:-exp64)&0x3ff; - exp64final = ((exp64 >0)?blah:-blah) +BIAS64; - - mant64 = (test.eind.ll >> 11) & QWORD_CONST(0xfffffffffffff); - sign = (test.begin&0x8000)?1:0; - result.ll = (sign <<63)|(exp64final << 52)| mant64; - - if(test.eind.l.lower == 0 && (UINT32)test.eind.l.upper == (UINT32)0x80000000UL && (test.begin&0x7fff) == 0x7fff) { - //Detect INF and -INF (score 3.11 when drawing a slur.) - result.d64 = sign?-HUGE_VAL:HUGE_VAL; - } - FPU_STAT.reg[reg].d64 = result.d64; - //return result.d64; - - //mant64= test.mant80/2***64 * 2 **53 -} - -static void FPU_ST80(UINT32 addr,UINT reg) -{ - SINT64 sign80; - SINT64 exp80, exp80final; - SINT64 mant80, mant80final; - - struct { - SINT16 begin; - FP_REG eind; - } test; - - sign80 = (FPU_STAT.reg[reg].ll&QWORD_CONST(0x8000000000000000))?1:0; - exp80 = FPU_STAT.reg[reg].ll&QWORD_CONST(0x7ff0000000000000); - exp80final = (exp80>>52); - mant80 = FPU_STAT.reg[reg].ll&QWORD_CONST(0x000fffffffffffff); - mant80final = (mant80 << 11); - if(FPU_STAT.reg[reg].d64 != 0){ //Zero is a special case - // Elvira wants the 8 and tcalc doesn't - mant80final |= QWORD_CONST(0x8000000000000000); - //Ca-cyber doesn't like this when result is zero. - exp80final += (BIAS80 - BIAS64); - } - test.begin = ((SINT16)(sign80)<<15)| (SINT16)(exp80final); - test.eind.ll = mant80final; - fpu_memorywrite_d(addr,test.eind.l.lower); - fpu_memorywrite_d(addr+4,test.eind.l.upper); - fpu_memorywrite_w(addr+8,test.begin); -} - - -static void FPU_FLD_F32(UINT32 addr,UINT store_to) { - union { - float f; - UINT32 l; - } blah; - - blah.l = fpu_memoryread_d(addr); - FPU_STAT.reg[store_to].d64 = (double)(blah.f); -} - -static void FPU_FLD_F64(UINT32 addr,UINT store_to) { - FPU_STAT.reg[store_to].l.lower = fpu_memoryread_d(addr); - FPU_STAT.reg[store_to].l.upper = fpu_memoryread_d(addr+4); -} - -static void FPU_FLD_F80(UINT32 addr) { - FPU_FLD80(addr, FPU_STAT_TOP); -} - -static void FPU_FLD_I16(UINT32 addr,UINT store_to) { - SINT16 blah; - - blah = fpu_memoryread_w(addr); - FPU_STAT.reg[store_to].d64 = (double)(blah); -} - -static void FPU_FLD_I32(UINT32 addr,UINT store_to) { - SINT32 blah; - - blah = fpu_memoryread_d(addr); - FPU_STAT.reg[store_to].d64 = (double)(blah); -} - -static void FPU_FLD_I64(UINT32 addr,UINT store_to) { - FP_REG blah; - - blah.l.lower = fpu_memoryread_d(addr); - blah.l.upper = fpu_memoryread_d(addr+4); - FPU_STAT.reg[store_to].d64 = (double)(blah.ll); -} - -static void FPU_FBLD(UINT32 addr,UINT store_to) -{ - UINT i; - double temp; - - UINT64 val = 0; - UINT in = 0; - UINT64 base = 1; - for(i = 0;i < 9;i++){ - in = fpu_memoryread_b(addr + i); - val += ( (in&0xf) * base); //in&0xf shouldn't be higher then 9 - base *= 10; - val += ((( in>>4)&0xf) * base); - base *= 10; - } - - //last number, only now convert to float in order to get - //the best signification - temp = (double)(val); - in = fpu_memoryread_b(addr + 9); - temp += ( (in&0xf) * base ); - if(in&0x80) temp *= -1.0; - FPU_STAT.reg[store_to].d64 = temp; -} - - -static INLINE void FPU_FLD_F32_EA(UINT32 addr) { - FPU_FLD_F32(addr,8); -} -static INLINE void FPU_FLD_F64_EA(UINT32 addr) { - FPU_FLD_F64(addr,8); -} -static INLINE void FPU_FLD_I32_EA(UINT32 addr) { - FPU_FLD_I32(addr,8); -} -static INLINE void FPU_FLD_I16_EA(UINT32 addr) { - FPU_FLD_I16(addr,8); -} - -static void FPU_FST_F32(UINT32 addr) { - union { - float f; - UINT32 l; - } blah; - - //should depend on rounding method - blah.f = (float)(FPU_STAT.reg[FPU_STAT_TOP].d64); - fpu_memorywrite_d(addr,blah.l); -} - -static void FPU_FST_F64(UINT32 addr) { - fpu_memorywrite_d(addr,FPU_STAT.reg[FPU_STAT_TOP].l.lower); - fpu_memorywrite_d(addr+4,FPU_STAT.reg[FPU_STAT_TOP].l.upper); -} - -static void FPU_FST_F80(UINT32 addr) { - FPU_ST80(addr,FPU_STAT_TOP); -} - -static void FPU_FST_I16(UINT32 addr) { - fpu_memorywrite_w(addr,(SINT16)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64))); -} - -static void FPU_FST_I32(UINT32 addr) { - fpu_memorywrite_d(addr,(SINT32)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64))); -} - -static void FPU_FST_I64(UINT32 addr) { - FP_REG blah; - - blah.ll = (SINT64)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64)); - fpu_memorywrite_d(addr,blah.l.lower); - fpu_memorywrite_d(addr+4,blah.l.upper); -} - -static void FPU_FBST(UINT32 addr) -{ - FP_REG val; - UINT p; - UINT i; - BOOL sign; - double temp; - - val = FPU_STAT.reg[FPU_STAT_TOP]; - sign = FALSE; - if(FPU_STAT.reg[FPU_STAT_TOP].ll & QWORD_CONST(0x8000000000000000)) { //sign - sign=TRUE; - val.d64=-val.d64; - } - //numbers from back to front - temp=val.d64; - for(i=0;i<9;i++){ - val.d64=temp; - temp = (double)((SINT64)(floor(val.d64/10.0))); - p = (UINT)(val.d64 - 10.0*temp); - val.d64=temp; - temp = (double)((SINT64)(floor(val.d64/10.0))); - p |= ((UINT)(val.d64 - 10.0*temp)<<4); - - fpu_memorywrite_b(addr+i,p); - } - val.d64=temp; - temp = (double)((SINT64)(floor(val.d64/10.0))); - p = (UINT)(val.d64 - 10.0*temp); - if(sign) - p|=0x80; - fpu_memorywrite_b(addr+9,p); -} - -#if defined(_WIN32) && !defined(__LIBRETRO__) -#define isinf(x) (!(_finite(x) || _isnan(x))) -#else -#define isinf(x) (!(_finite(x) || isnan(x))) -#endif -#define isdenormal(x) (_fpclass(x) == _FPCLASS_ND || _fpclass(x) == _FPCLASS_PD) - -static void FPU_FADD(UINT op1, UINT op2){ - //// HACK: Set the denormal flag according to whether the source or final result is a denormalized number. - //// This is vital if we don't want certain DOS programs to mis-detect our FPU emulation as an IIT clone chip when cputype == 286 - //BOOL was_not_normal; - - //was_not_normal = isdenormal(FPU_STAT.reg[op1].d64); - //FPU_STAT.reg[op1].d64 += FPU_STAT.reg[op2].d64; - //FPU_SET_D(was_not_normal || isdenormal(FPU_STAT.reg[op1].d64) || isdenormal(FPU_STAT.reg[op2].d64)); - FPU_STAT.reg[op1].d64 += FPU_STAT.reg[op2].d64; - //flags and such :) - return; -} - -static void FPU_FSIN(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = sin(FPU_STAT.reg[FPU_STAT_TOP].d64); - FPU_SET_C2(0); - //flags and such :) - return; -} - -static void FPU_FSINCOS(void){ - double temp; - - temp = FPU_STAT.reg[FPU_STAT_TOP].d64; - FPU_STAT.reg[FPU_STAT_TOP].d64 = sin(temp); - FPU_PUSH(cos(temp)); - FPU_SET_C2(0); - //flags and such :) - return; -} - -static void FPU_FCOS(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = cos(FPU_STAT.reg[FPU_STAT_TOP].d64); - FPU_SET_C2(0); - //flags and such :) - return; -} - -static void FPU_FSQRT(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = sqrt(FPU_STAT.reg[FPU_STAT_TOP].d64); - //flags and such :) - return; -} -static void FPU_FPATAN(void){ - FPU_STAT.reg[FPU_ST(1)].d64 = atan2(FPU_STAT.reg[FPU_ST(1)].d64,FPU_STAT.reg[FPU_STAT_TOP].d64); - FPU_FPOP(); - //flags and such :) - return; -} -static void FPU_FPTAN(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = tan(FPU_STAT.reg[FPU_STAT_TOP].d64); - FPU_PUSH(1.0); - FPU_SET_C2(0); - //flags and such :) - return; -} -static void FPU_FDIV(UINT st, UINT other){ - if(FPU_STAT.reg[other].d64==0){ - FPU_STATUSWORD |= FP_ZE_FLAG; - if(!(FPU_CTRLWORD & FP_ZE_FLAG)) - return; - } - FPU_STAT.reg[st].d64= FPU_STAT.reg[st].d64/FPU_STAT.reg[other].d64; - //flags and such :) - return; -} - -static void FPU_FDIVR(UINT st, UINT other){ - if(FPU_STAT.reg[st].d64==0){ - FPU_STATUSWORD |= FP_ZE_FLAG; - if(!(FPU_CTRLWORD & FP_ZE_FLAG)) - return; - } - FPU_STAT.reg[st].d64= FPU_STAT.reg[other].d64/FPU_STAT.reg[st].d64; - // flags and such :) - return; -} - -static void FPU_FMUL(UINT st, UINT other){ - FPU_STAT.reg[st].d64*=FPU_STAT.reg[other].d64; - //flags and such :) - return; -} - -static void FPU_FSUB(UINT st, UINT other){ - FPU_STAT.reg[st].d64 = FPU_STAT.reg[st].d64 - FPU_STAT.reg[other].d64; - //flags and such :) - return; -} - -static void FPU_FSUBR(UINT st, UINT other){ - FPU_STAT.reg[st].d64 = FPU_STAT.reg[other].d64 - FPU_STAT.reg[st].d64; - //flags and such :) - return; -} - -static void FPU_FXCH(UINT st, UINT other){ - FP_TAG tag; - FP_REG reg; - - tag = FPU_STAT.tag[other]; - reg = FPU_STAT.reg[other]; - FPU_STAT.tag[other] = FPU_STAT.tag[st]; - FPU_STAT.reg[other] = FPU_STAT.reg[st]; - FPU_STAT.tag[st] = tag; - FPU_STAT.reg[st] = reg; -} - -static void FPU_FST(UINT st, UINT other){ - FPU_STAT.tag[other] = FPU_STAT.tag[st]; - FPU_STAT.reg[other] = FPU_STAT.reg[st]; -} - -static void FPU_FCOM(UINT st, UINT other){ - if(((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || - ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero))){ - FPU_SET_C3(1); - FPU_SET_C2(1); - FPU_SET_C0(1); - return; - } - - if(FPU_STAT.reg[st].d64 == FPU_STAT.reg[other].d64){ - FPU_SET_C3(1); - FPU_SET_C2(0); - FPU_SET_C0(0); - return; - } - if(FPU_STAT.reg[st].d64 < FPU_STAT.reg[other].d64){ - FPU_SET_C3(0); - FPU_SET_C2(0); - FPU_SET_C0(1); - return; - } - // st > other - FPU_SET_C3(0); - FPU_SET_C2(0); - FPU_SET_C0(0); - return; -} -static void FPU_FCOMI(UINT st, UINT other){ - if(((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || - ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero))){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | P_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; - return; - } - - if(FPU_STAT.reg[st].d64 == FPU_STAT.reg[other].d64){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; - return; - } - if(FPU_STAT.reg[st].d64 < FPU_STAT.reg[other].d64){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; - return; - } - // st > other - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; - return; -} - -static void FPU_FUCOM(UINT st, UINT other){ - //does atm the same as fcom - FPU_FCOM(st,other); -} -static void FPU_FUCOMI(UINT st, UINT other){ - //does atm the same as fcomi - FPU_FCOMI(st,other); -} - -static void FPU_FCMOVB(UINT st, UINT other){ - if(CPU_FLAGL & C_FLAG){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVE(UINT st, UINT other){ - if(CPU_FLAGL & Z_FLAG){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVBE(UINT st, UINT other){ - if(CPU_FLAGL & (C_FLAG|Z_FLAG)){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVU(UINT st, UINT other){ - if(CPU_FLAGL & P_FLAG){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} - -static void FPU_FCMOVNB(UINT st, UINT other){ - if(!(CPU_FLAGL & C_FLAG)){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVNE(UINT st, UINT other){ - if(!(CPU_FLAGL & Z_FLAG)){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVNBE(UINT st, UINT other){ - if(!(CPU_FLAGL & (C_FLAG|Z_FLAG))){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVNU(UINT st, UINT other){ - if(!(CPU_FLAGL & P_FLAG)){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} - -static void FPU_FRNDINT(void){ - SINT64 temp; - - temp = (SINT64)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64)); - FPU_STAT.reg[FPU_STAT_TOP].d64=(double)(temp); -} - -static void FPU_FPREM(void){ - double valtop; - double valdiv; - SINT64 ressaved; - - valtop = FPU_STAT.reg[FPU_STAT_TOP].d64; - valdiv = FPU_STAT.reg[FPU_ST(1)].d64; - ressaved = (SINT64)( (valtop/valdiv) ); -// Some backups -// Real64 res=valtop - ressaved*valdiv; -// res= fmod(valtop,valdiv); - FPU_STAT.reg[FPU_STAT_TOP].d64 = valtop - ressaved*valdiv; - FPU_SET_C0((UINT)(ressaved&4)); - FPU_SET_C3((UINT)(ressaved&2)); - FPU_SET_C1((UINT)(ressaved&1)); - FPU_SET_C2(0); -} - -static void FPU_FPREM1(void){ - double valtop; - double valdiv, quot, quotf; - SINT64 ressaved; - - valtop = FPU_STAT.reg[FPU_STAT_TOP].d64; - valdiv = FPU_STAT.reg[FPU_ST(1)].d64; - quot = valtop/valdiv; - quotf = floor(quot); - - if (quot-quotf>0.5) ressaved = (SINT64)(quotf+1); - else if (quot-quotf<0.5) ressaved = (SINT64)(quotf); - else ressaved = (SINT64)(((((SINT64)(quotf))&1)!=0)?(quotf+1):(quotf)); - - FPU_STAT.reg[FPU_STAT_TOP].d64 = valtop - ressaved*valdiv; - FPU_SET_C0((UINT)(ressaved&4)); - FPU_SET_C3((UINT)(ressaved&2)); - FPU_SET_C1((UINT)(ressaved&1)); - FPU_SET_C2(0); -} - -static void FPU_FXAM(void){ - if(FPU_STAT.reg[FPU_STAT_TOP].ll & QWORD_CONST(0x8000000000000000)) //sign - { - FPU_SET_C1(1); - } - else - { - FPU_SET_C1(0); - } - if(FPU_STAT.tag[FPU_STAT_TOP] == TAG_Empty) - { - FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(1); - return; - } - if(FPU_STAT.reg[FPU_STAT_TOP].d64 == 0.0) //zero or normalized number. - { - FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0); - } - else - { - FPU_SET_C3(0);FPU_SET_C2(1);FPU_SET_C0(0); - } -} - -static void FPU_F2XM1(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = pow(2.0,FPU_STAT.reg[FPU_STAT_TOP].d64) - 1; - return; -} - -static void FPU_FYL2X(void){ - FPU_STAT.reg[FPU_ST(1)].d64*=log(FPU_STAT.reg[FPU_STAT_TOP].d64)/log((double)(2.0)); - FPU_FPOP(); - return; -} - -static void FPU_FYL2XP1(void){ - FPU_STAT.reg[FPU_ST(1)].d64*=log(FPU_STAT.reg[FPU_STAT_TOP].d64+1.0)/log((double)(2.0)); - FPU_FPOP(); - return; -} - -static void FPU_FSCALE(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 *= pow(2.0,(double)((SINT64)(FPU_STAT.reg[FPU_ST(1)].d64))); - return; //2^x where x is chopped. -} - -static void FPU_FSTENV(UINT32 addr) -{ - descriptor_t *sdp = &CPU_CS_DESC; - FPU_SET_TOP(FPU_STAT_TOP); - - switch ((CPU_CR0 & 1) | (SEG_IS_32BIT(sdp) ? 0x100 : 0x000)) - { - case 0x000: case 0x001: - fpu_memorywrite_w(addr+0,FPU_CTRLWORD); - fpu_memorywrite_w(addr+2,FPU_STATUSWORD); - fpu_memorywrite_w(addr+4,FPU_GetTag()); - fpu_memorywrite_w(addr+10,FPU_LASTINSTOP); - break; - - case 0x100: case 0x101: - fpu_memorywrite_d(addr+0,(UINT32)(FPU_CTRLWORD)); - fpu_memorywrite_d(addr+4,(UINT32)(FPU_STATUSWORD)); - fpu_memorywrite_d(addr+8,(UINT32)(FPU_GetTag())); - fpu_memorywrite_d(addr+20,FPU_LASTINSTOP); - break; - } -} - -static void FPU_FLDENV(UINT32 addr) -{ - descriptor_t *sdp = &CPU_CS_DESC; - - switch ((CPU_CR0 & 1) | (SEG_IS_32BIT(sdp) ? 0x100 : 0x000)) { - case 0x000: case 0x001: - FPU_SetCW(fpu_memoryread_w(addr+0)); - FPU_STATUSWORD = fpu_memoryread_w(addr+2); - FPU_SetTag(fpu_memoryread_w(addr+4)); - FPU_LASTINSTOP = fpu_memoryread_w(addr+10); - break; - - case 0x100: case 0x101: - FPU_SetCW((UINT16)fpu_memoryread_d(addr+0)); - FPU_STATUSWORD = (UINT16)fpu_memoryread_d(addr+4); - FPU_SetTag((UINT16)fpu_memoryread_d(addr+8)); - FPU_LASTINSTOP = (UINT16)fpu_memoryread_d(addr+20); - break; - } - FPU_STAT_TOP = FPU_GET_TOP(); -} - -static void FPU_FSAVE(UINT32 addr) -{ - UINT start; - UINT i; - - descriptor_t *sdp = &CPU_CS_DESC; - - FPU_FSTENV(addr); - start = ((SEG_IS_32BIT(sdp))?28:14); - for(i = 0;i < 8;i++){ - FPU_ST80(addr+start,FPU_ST(i)); - start += 10; - } - FPU_FINIT(); -} - -static void FPU_FRSTOR(UINT32 addr) -{ - UINT start; - UINT i; - - descriptor_t *sdp = &CPU_CS_DESC; - - FPU_FLDENV(addr); - start = ((SEG_IS_32BIT(sdp))?28:14); - for(i = 0;i < 8;i++){ - FPU_FLD80(addr+start, FPU_ST(i)); - start += 10; - } -} - -static void FPU_FXSAVE(UINT32 addr){ - UINT start; - UINT i; - - descriptor_t *sdp = &CPU_CS_DESC; - - //FPU_FSTENV(addr); - FPU_SET_TOP(FPU_STAT_TOP); - fpu_memorywrite_w(addr+0,FPU_CTRLWORD); - fpu_memorywrite_w(addr+2,FPU_STATUSWORD); - fpu_memorywrite_b(addr+4,FPU_GetTag8()); -#ifdef USE_SSE - fpu_memorywrite_d(addr+24,SSE_MXCSR); -#endif - start = 32; - for(i = 0;i < 8;i++){ - //FPU_ST80(addr+start,FPU_ST(i)); - fpu_memorywrite_d(addr+start+0,FPU_STAT.reg[FPU_ST(i)].l.lower); - fpu_memorywrite_d(addr+start+4,FPU_STAT.reg[FPU_ST(i)].l.upper); - fpu_memorywrite_d(addr+start+8,0x0000ffff); - fpu_memorywrite_d(addr+start+12,0x00000000); - start += 16; - } -#ifdef USE_SSE - start = 160; - for(i = 0;i < 8;i++){ - fpu_memorywrite_q(addr+start+0,SSE_XMMREG(i).ul64[0]); - fpu_memorywrite_q(addr+start+8,SSE_XMMREG(i).ul64[1]); - start += 16; - } -#endif -} -static void FPU_FXRSTOR(UINT32 addr){ - UINT start; - UINT i; - - descriptor_t *sdp = &CPU_CS_DESC; - - //FPU_FLDENV(addr); - FPU_SetCW(fpu_memoryread_w(addr+0)); - FPU_STATUSWORD = fpu_memoryread_w(addr+2); - FPU_SetTag8(fpu_memoryread_b(addr+4)); - FPU_STAT_TOP = FPU_GET_TOP(); -#ifdef USE_SSE - SSE_MXCSR = fpu_memoryread_d(addr+24); -#endif - start = 32; - for(i = 0;i < 8;i++){ - //FPU_STAT.reg[FPU_ST(i)].d64 = FPU_FLD80(addr+start); - FPU_STAT.reg[FPU_ST(i)].l.lower = fpu_memoryread_d(addr+start+0); - FPU_STAT.reg[FPU_ST(i)].l.upper = fpu_memoryread_d(addr+start+4); - start += 16; - } -#ifdef USE_SSE - start = 160; - for(i = 0;i < 8;i++){ - SSE_XMMREG(i).ul64[0] = fpu_memoryread_q(addr+start+0); - SSE_XMMREG(i).ul64[1] = fpu_memoryread_q(addr+start+8); - start += 16; - } -#endif -} - -void DB_FPU_FXSAVERSTOR(void){ - UINT32 op; - UINT idx, sub; - UINT32 maddr; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - switch(idx){ - case 0: // FXSAVE - fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し - maddr = calc_ea_dst(op); - FPU_FXSAVE(maddr); - break; - case 1: // FXRSTOR - fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し - maddr = calc_ea_dst(op); - FPU_FXRSTOR(maddr); - break; -#ifdef USE_SSE - case 2: // LDMXCSR - maddr = calc_ea_dst(op); - SSE_LDMXCSR(maddr); - break; - case 3: // STMXCSR - maddr = calc_ea_dst(op); - SSE_STMXCSR(maddr); - break; - case 4: // SFENCE - SSE_SFENCE(); - break; - case 5: // LFENCE - SSE_LFENCE(); - break; - case 6: // MFENCE - SSE_MFENCE(); - break; - case 7: // CLFLUSH; - SSE_CLFLUSH(op); - break; -#endif - default: - ia32_panic("invalid opcode = %02x\n", op); - break; - } -} - -static void FPU_FXTRACT(void) { - // function stores real bias in st and - // pushes the significant number onto the stack - // if double ever uses a different base please correct this function - FP_REG test; - SINT64 exp80, exp80final; - double mant; - - test = FPU_STAT.reg[FPU_STAT_TOP]; - exp80 = test.ll&QWORD_CONST(0x7ff0000000000000); - exp80final = (exp80>>52) - BIAS64; - mant = test.d64 / (pow(2.0,(double)(exp80final))); - FPU_STAT.reg[FPU_STAT_TOP].d64 = (double)(exp80final); - FPU_PUSH(mant); -} - -static void FPU_FCHS(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = -1.0*(FPU_STAT.reg[FPU_STAT_TOP].d64); -} - -static void FPU_FABS(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = fabs(FPU_STAT.reg[FPU_STAT_TOP].d64); -} - -static void FPU_FTST(void){ - FPU_STAT.reg[8].d64 = 0.0; - FPU_FCOM(FPU_STAT_TOP,8); -} - -static void FPU_FLD1(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = 1.0; -} - -static void FPU_FLDL2T(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = L2T; -} - -static void FPU_FLDL2E(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = L2E; -} - -static void FPU_FLDPI(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = PI; -} - -static void FPU_FLDLG2(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = LG2; -} - -static void FPU_FLDLN2(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = LN2; -} - -static void FPU_FLDZ(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = 0.0; - FPU_STAT.tag[FPU_STAT_TOP] = TAG_Zero; -} - - -static INLINE void FPU_FADD_EA(UINT op1){ - FPU_FADD(op1,8); -} -static INLINE void FPU_FMUL_EA(UINT op1){ - FPU_FMUL(op1,8); -} -static INLINE void FPU_FSUB_EA(UINT op1){ - FPU_FSUB(op1,8); -} -static INLINE void FPU_FSUBR_EA(UINT op1){ - FPU_FSUBR(op1,8); -} -static INLINE void FPU_FDIV_EA(UINT op1){ - FPU_FDIV(op1,8); -} -static INLINE void FPU_FDIVR_EA(UINT op1){ - FPU_FDIVR(op1,8); -} -static INLINE void FPU_FCOM_EA(UINT op1){ - FPU_FCOM(op1,8); -} - -/* - * FPU interface - */ -//int fpu_updateEmuEnv(void); -static void -FPU_FINIT(void) -{ - int i; - FPU_SetCW(0x37F); - FPU_STATUSWORD = 0; - FPU_STAT_TOP=FPU_GET_TOP(); - for(i=0;i<8;i++){ - FPU_STAT.tag[i] = TAG_Empty; - // レジスタの内容は消してはいけない ver0.86 rev40 - //FPU_STAT.reg[i].d64 = 0; - //FPU_STAT.reg[i].l.lower = 0; - //FPU_STAT.reg[i].l.upper = 0; - //FPU_STAT.reg[i].ll = 0; - } - FPU_STAT.tag[8] = TAG_Valid; // is only used by us -} -void DB_FPU_FINIT(void){ - int i; - FPU_FINIT(); - for(i=0;i<8;i++){ - FPU_STAT.tag[i] = TAG_Empty; - FPU_STAT.reg[i].l.ext = 0; - FPU_STAT.reg[i].l.lower = 0; - FPU_STAT.reg[i].l.upper = 0; - } -} - -/* - * FPU instruction - */ - -static void fpu_checkexception(){ - if((FPU_STATUSWORD & ~FPU_CTRLWORD) & 0x3F){ - EXCEPTION(MF_EXCEPTION, 0); - } -} - -static void EA_TREE(UINT op) -{ - UINT idx; - - idx = (op >> 3) & 7; - - switch (idx) { - case 0: /* FADD (単精度実数) */ - TRACEOUT(("FADD EA")); - FPU_FADD_EA(FPU_STAT_TOP); - break; - case 1: /* FMUL (単精度実数) */ - TRACEOUT(("FMUL EA")); - FPU_FMUL_EA(FPU_STAT_TOP); - break; - case 2: /* FCOM (単精度実数) */ - TRACEOUT(("FCOM EA")); - FPU_FCOM_EA(FPU_STAT_TOP); - break; - case 3: /* FCOMP (単精度実数) */ - TRACEOUT(("FCOMP EA")); - FPU_FCOM_EA(FPU_STAT_TOP); - FPU_FPOP(); - break; - case 4: /* FSUB (単精度実数) */ - TRACEOUT(("FSUB EA")); - FPU_FSUB_EA(FPU_STAT_TOP); - break; - case 5: /* FSUBR (単精度実数) */ - TRACEOUT(("FSUBR EA")); - FPU_FSUBR_EA(FPU_STAT_TOP); - break; - case 6: /* FDIV (単精度実数) */ - TRACEOUT(("FDIV EA")); - FPU_FDIV_EA(FPU_STAT_TOP); - break; - case 7: /* FDIVR (単精度実数) */ - TRACEOUT(("FDIVR EA")); - FPU_FDIVR_EA(FPU_STAT_TOP); - break; - default: - break; - } -} - -// d8 -void -DB_ESC0(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU d8 %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FADD */ - TRACEOUT(("FADD")); - FPU_FADD(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 1: /* FMUL */ - TRACEOUT(("FMUL")); - FPU_FMUL(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FCOM */ - TRACEOUT(("FCOM")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCOMP */ - TRACEOUT(("FCOMP")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - case 4: /* FSUB */ - TRACEOUT(("FSUB")); - FPU_FSUB(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 5: /* FSUBR */ - TRACEOUT(("FSUBR")); - FPU_FSUBR(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 6: /* FDIV */ - TRACEOUT(("FDIV")); - FPU_FDIV(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 7: /* FDIVR */ - TRACEOUT(("FDIVR")); - FPU_FDIVR(FPU_STAT_TOP,FPU_ST(sub)); - break; - } - } else { - madr = calc_ea_dst(op); - FPU_FLD_F32_EA(madr); - EA_TREE(op); - } -} - -// d9 -void -DB_ESC1(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU d9 %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - if(!(op < 0xc0 && idx>=4)){ - fpu_checkexception(); - } - if (op >= 0xc0) - { - switch (idx) { - case 0: /* FLD ST(0), ST(i) */ - { - UINT reg_from; - - TRACEOUT(("FLD STi")); - reg_from = FPU_ST(sub); - FPU_PREP_PUSH(); - FPU_FST(reg_from, FPU_STAT_TOP); - } - break; - - case 1: /* FXCH ST(0), ST(i) */ - TRACEOUT(("FXCH STi")); - FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); - break; - - case 2: /* FNOP */ - TRACEOUT(("FNOP")); - FPU_FNOP(); - break; - - case 3: /* FSTP STi */ - TRACEOUT(("FSTP STi")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - - case 4: - switch (sub) { - case 0x0: /* FCHS */ - TRACEOUT(("FCHS")); - FPU_FCHS(); - break; - - case 0x1: /* FABS */ - TRACEOUT(("FABS")); - FPU_FABS(); - break; - - case 0x2: /* UNKNOWN */ - case 0x3: /* ILLEGAL */ - break; - - case 0x4: /* FTST */ - TRACEOUT(("FTST")); - FPU_FTST(); - break; - - case 0x5: /* FXAM */ - TRACEOUT(("FXAM")); - FPU_FXAM(); - break; - - case 0x06: /* FTSTP (cyrix)*/ - case 0x07: /* UNKNOWN */ - break; - } - break; - - case 5: - switch (sub) { - case 0x0: /* FLD1 */ - TRACEOUT(("FLD1")); - FPU_FLD1(); - break; - - case 0x1: /* FLDL2T */ - TRACEOUT(("FLDL2T")); - FPU_FLDL2T(); - break; - - case 0x2: /* FLDL2E */ - TRACEOUT(("FLDL2E")); - FPU_FLDL2E(); - break; - - case 0x3: /* FLDPI */ - TRACEOUT(("FLDPI")); - FPU_FLDPI(); - break; - - case 0x4: /* FLDLG2 */ - TRACEOUT(("FLDLG2")); - FPU_FLDLG2(); - break; - - case 0x5: /* FLDLN2 */ - TRACEOUT(("FLDLN2")); - FPU_FLDLN2(); - break; - - case 0x6: /* FLDZ */ - TRACEOUT(("FLDZ")); - FPU_FLDZ(); - break; - - case 0x07: /* ILLEGAL */ - break; - } - break; - - case 6: - switch (sub) { - case 0x0: /* F2XM1 */ - TRACEOUT(("F2XM1")); - FPU_F2XM1(); - break; - - case 0x1: /* FYL2X */ - TRACEOUT(("FYL2X")); - FPU_FYL2X(); - break; - - case 0x2: /* FPTAN */ - TRACEOUT(("FPTAN")); - FPU_FPTAN(); - break; - - case 0x3: /* FPATAN */ - TRACEOUT(("FPATAN")); - FPU_FPATAN(); - break; - - case 0x4: /* FXTRACT */ - TRACEOUT(("FXTRACT")); - FPU_FXTRACT(); - break; - - case 0x5: /* FPREM1 */ - TRACEOUT(("FPREM1")); - FPU_FPREM1(); - break; - - case 0x6: /* FDECSTP */ - TRACEOUT(("FDECSTP")); - FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; - break; - - case 0x7: /* FINCSTP */ - TRACEOUT(("FINCSTP")); - FPU_STAT_TOP = (FPU_STAT_TOP + 1) & 7; - break; - } - break; - - case 7: - switch (sub) { - case 0x0: /* FPREM */ - TRACEOUT(("FPREM")); - FPU_FPREM(); - break; - - case 0x1: /* FYL2XP1 */ - TRACEOUT(("FYL2XP1")); - FPU_FYL2XP1(); - break; - - case 0x2: /* FSQRT */ - TRACEOUT(("FSQRT")); - FPU_FSQRT(); - break; - - case 0x3: /* FSINCOS */ - TRACEOUT(("FSINCOS")); - FPU_FSINCOS(); - break; - - case 0x4: /* FRNDINT */ - TRACEOUT(("FRNDINT")); - FPU_FRNDINT(); - break; - - case 0x5: /* FSCALE */ - TRACEOUT(("FSCALE")); - FPU_FSCALE(); - break; - - case 0x6: /* FSIN */ - TRACEOUT(("FSIN")); - FPU_FSIN(); - break; - - case 0x7: /* FCOS */ - TRACEOUT(("FCOS")); - FPU_FCOS(); - break; - } - break; - - default: - ia32_panic("ESC1: invalid opcode = %02x\n", op); - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FLD (単精度実数) */ - TRACEOUT(("FLD float")); - FPU_PREP_PUSH(); - FPU_FLD_F32(madr,FPU_STAT_TOP); - break; - - case 1: /* UNKNOWN */ - break; - - case 2: /* FST (単精度実数) */ - TRACEOUT(("FST float")); - FPU_FST_F32(madr); - break; - - case 3: /* FSTP (単精度実数) */ - TRACEOUT(("FSTP float")); - FPU_FST_F32(madr); - FPU_FPOP(); - break; - - case 4: /* FLDENV */ - TRACEOUT(("FLDENV")); - FPU_FLDENV(madr); - break; - - case 5: /* FLDCW */ - TRACEOUT(("FLDCW")); - FPU_FLDCW(madr); - break; - - case 6: /* FSTENV */ - TRACEOUT(("FSTENV")); - FPU_FSTENV(madr); - break; - - case 7: /* FSTCW */ - TRACEOUT(("FSTCW/FNSTCW")); - fpu_memorywrite_w(madr,FPU_CTRLWORD); - break; - - default: - break; - } - } -} - -// da -void -DB_ESC2(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU da %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FCMOVB */ - TRACEOUT(("ESC2: FCMOVB")); - FPU_FCMOVB(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 1: /* FCMOVE */ - TRACEOUT(("ESC2: FCMOVE")); - FPU_FCMOVE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FCMOVBE */ - TRACEOUT(("ESC2: FCMOVBE")); - FPU_FCMOVBE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCMOVU */ - TRACEOUT(("ESC2: FCMOVU")); - FPU_FCMOVU(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 5: - switch (sub) { - case 1: /* FUCOMPP */ - TRACEOUT(("FUCOMPP")); - FPU_FUCOM(FPU_STAT_TOP,FPU_ST(1)); - FPU_FPOP(); - FPU_FPOP(); - break; - - default: - break; - } - break; - - default: - break; - } - } else { - madr = calc_ea_dst(op); - FPU_FLD_I32_EA(madr); - EA_TREE(op); - } -} - -// db -void -DB_ESC3(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU db %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - if(!(op >= 0xc0 && idx==4)){ - fpu_checkexception(); - } - if (op >= 0xc0) - { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FCMOVNB */ - TRACEOUT(("ESC3: FCMOVNB")); - FPU_FCMOVNB(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 1: /* FCMOVNE */ - TRACEOUT(("ESC3: FCMOVNE")); - FPU_FCMOVNE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FCMOVNBE */ - TRACEOUT(("ESC3: FCMOVNBE")); - FPU_FCMOVNBE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCMOVNU */ - TRACEOUT(("ESC3: FCMOVNU")); - FPU_FCMOVNU(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 4: - switch (sub) { - case 0: /* FNENI */ - case 1: /* FNDIS */ - break; - - case 2: /* FCLEX */ - TRACEOUT(("FCLEX")); - FPU_FCLEX(); - break; - - case 3: /* FNINIT/FINIT */ - TRACEOUT(("FNINIT/FINIT")); - FPU_FINIT(); - break; - - case 4: /* FNSETPM */ - case 5: /* FRSTPM */ - FPU_FNOP(); - break; - - default: - break; - } - break; - case 5: /* FUCOMI */ - TRACEOUT(("ESC3: FUCOMI")); - FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 6: /* FCOMI */ - TRACEOUT(("ESC3: FCOMI")); - FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); - break; - default: - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FILD (DWORD) */ - TRACEOUT(("FILD")); - FPU_PREP_PUSH(); - FPU_FLD_I32(madr,FPU_STAT_TOP); - break; - - case 1: /* FISTTP (DWORD) */ - { - FP_RND oldrnd = FPU_STAT.round; - FPU_STAT.round = ROUND_Down; - FPU_FST_I32(madr); - FPU_STAT.round = oldrnd; - } - FPU_FPOP(); - break; - - case 2: /* FIST (DWORD) */ - TRACEOUT(("FIST")); - FPU_FST_I32(madr); - break; - - case 3: /* FISTP (DWORD) */ - TRACEOUT(("FISTP")); - FPU_FST_I32(madr); - FPU_FPOP(); - break; - - case 5: /* FLD (拡張実数) */ - TRACEOUT(("FLD 80 Bits Real")); - FPU_PREP_PUSH(); - FPU_FLD_F80(madr); - break; - - case 7: /* FSTP (拡張実数) */ - TRACEOUT(("FSTP 80 Bits Real")); - FPU_FST_F80(madr); - FPU_FPOP(); - break; - - default: - break; - } - } -} - -// dc -void -DB_ESC4(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU dc %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(i), ST(0) */ - switch (idx) { - case 0: /* FADD */ - TRACEOUT(("ESC4: FADD")); - FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); - break; - case 1: /* FMUL */ - TRACEOUT(("ESC4: FMUL")); - FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); - break; - case 2: /* FCOM */ - TRACEOUT(("ESC4: FCOM")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCOMP */ - TRACEOUT(("ESC4: FCOMP")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - case 4: /* FSUBR */ - TRACEOUT(("ESC4: FSUBR")); - FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); - break; - case 5: /* FSUB */ - TRACEOUT(("ESC4: FSUB")); - FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); - break; - case 6: /* FDIVR */ - TRACEOUT(("ESC4: FDIVR")); - FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); - break; - case 7: /* FDIV */ - TRACEOUT(("ESC4: FDIV")); - FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); - break; - default: - break; - } - } else { - madr = calc_ea_dst(op); - FPU_FLD_F64_EA(madr); - EA_TREE(op); - } -} - -// dd -void -DB_ESC5(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU dd %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - fpu_check_NM_EXCEPTION(); - //if(op < 0xc0 && (idx==6 || idx==4)){ - // _ADD_EIP(-1); // XXX: 無理やり戻す - // fpu_check_NM_EXCEPTION2(); - // _ADD_EIP(1); - //}else{ - // _ADD_EIP(-1); // XXX: 無理やり戻す - // fpu_check_NM_EXCEPTION(); - // _ADD_EIP(1); - //} - if(op >= 0xc0 || (idx!=4 && idx!=6 && idx!=7)){ - fpu_checkexception(); - } - if (op >= 0xc0) { - /* FUCOM ST(i), ST(0) */ - /* Fxxx ST(i) */ - switch (idx) { - case 0: /* FFREE */ - TRACEOUT(("FFREE")); - FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; - break; - case 1: /* FXCH */ - TRACEOUT(("FXCH")); - FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FST */ - TRACEOUT(("FST")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FSTP */ - TRACEOUT(("FSTP")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - case 4: /* FUCOM */ - TRACEOUT(("FUCOM")); - FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 5: /* FUCOMP */ - TRACEOUT(("FUCOMP")); - FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - - default: - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FLD (倍精度実数) */ - TRACEOUT(("FLD double real")); - FPU_PREP_PUSH(); - FPU_FLD_F64(madr,FPU_STAT_TOP); - break; - case 1: /* FISTTP (QWORD) */ - { - FP_RND oldrnd = FPU_STAT.round; - FPU_STAT.round = ROUND_Down; - FPU_FST_I64(madr); - FPU_STAT.round = oldrnd; - } - FPU_FPOP(); - break; - case 2: /* FST (倍精度実数) */ - TRACEOUT(("FST double real")); - FPU_FST_F64(madr); - break; - case 3: /* FSTP (倍精度実数) */ - TRACEOUT(("FSTP double real")); - FPU_FST_F64(madr); - FPU_FPOP(); - break; - case 4: /* FRSTOR */ - TRACEOUT(("FRSTOR")); - FPU_FRSTOR(madr); - break; - case 6: /* FSAVE */ - TRACEOUT(("FSAVE")); - FPU_FSAVE(madr); - break; - - case 7: /* FSTSW */ - FPU_SET_TOP(FPU_STAT_TOP); - //cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, FPU_CTRLWORD); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, FPU_STATUSWORD); - break; - - default: - break; - } - } -} - -// de -void -DB_ESC6(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU de %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(i), ST(0) */ - switch (idx) { - case 0: /* FADDP */ - TRACEOUT(("FADDP")); - FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); - break; - case 1: /* FMULP */ - TRACEOUT(("FMULP")); - FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); - break; - case 2: /* FCOMP5 */ - TRACEOUT(("FCOMP5")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCOMPP */ - TRACEOUT(("FCOMPP")); - if(sub != 1) { - return; - } - FPU_FCOM(FPU_STAT_TOP,FPU_ST(1)); - FPU_FPOP(); /* extra pop at the bottom*/ - break; - case 4: /* FSUBRP */ - TRACEOUT(("FSUBRP")); - FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); - break; - case 5: /* FSUBP */ - TRACEOUT(("FSUBP")); - FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); - break; - case 6: /* FDIVRP */ - TRACEOUT(("FDIVRP")); - FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); - if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ - return; // POPしないようにする - } - break; - case 7: /* FDIVP */ - TRACEOUT(("FDIVP")); - FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); - if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ - return; // POPしないようにする - } - break; - /*FALLTHROUGH*/ - default: - break; - } - FPU_FPOP(); - } else { - madr = calc_ea_dst(op); - FPU_FLD_I16_EA(madr); - EA_TREE(op); - } -} - -// df -void -DB_ESC7(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU df %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - if(!(op >= 0xc0 && idx==4 && sub==0)){ - fpu_checkexception(); - } - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FFREEP */ - TRACEOUT(("FFREEP")); - FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; - FPU_FPOP(); - break; - case 1: /* FXCH */ - TRACEOUT(("FXCH")); - FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); - break; - - case 2: - case 3: /* FSTP */ - TRACEOUT(("FSTP")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - - case 4: - switch (sub) - { - case 0: /* FSTSW AX */ - TRACEOUT(("FSTSW AX")); - FPU_SET_TOP(FPU_STAT_TOP); - CPU_AX = FPU_STATUSWORD; - break; - - default: - break; - } - break; - case 5: /* FUCOMIP */ - TRACEOUT(("ESC7: FUCOMIP")); - FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - case 6: /* FCOMIP */ - TRACEOUT(("ESC7: FCOMIP")); - FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - default: - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FILD (WORD) */ - TRACEOUT(("FILD SINT16")); - FPU_PREP_PUSH(); - FPU_FLD_I16(madr,FPU_STAT_TOP); - break; - case 1: /* FISTTP (WORD) */ - { - FP_RND oldrnd = FPU_STAT.round; - FPU_STAT.round = ROUND_Down; - FPU_FST_I16(madr); - FPU_STAT.round = oldrnd; - } - FPU_FPOP(); - break; - case 2: /* FIST (WORD) */ - TRACEOUT(("FIST SINT16")); - FPU_FST_I16(madr); - break; - case 3: /* FISTP (WORD) */ - TRACEOUT(("FISTP SINT16")); - FPU_FST_I16(madr); - FPU_FPOP(); - break; - - case 4: /* FBLD (BCD) */ - TRACEOUT(("FBLD packed BCD")); - FPU_PREP_PUSH(); - FPU_FBLD(madr,FPU_STAT_TOP); - break; - - case 5: /* FILD (QWORD) */ - TRACEOUT(("FILD SINT64")); - FPU_PREP_PUSH(); - FPU_FLD_I64(madr,FPU_STAT_TOP); - break; - - case 6: /* FBSTP (BCD) */ - TRACEOUT(("FBSTP packed BCD")); - FPU_FBST(madr); - FPU_FPOP(); - break; - - case 7: /* FISTP (QWORD) */ - TRACEOUT(("FISTP SINT64")); - FPU_FST_I64(madr); - FPU_FPOP(); - break; - - default: - break; - } - } -} -#endif +/* + * Copyright (C) 2002-2015 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Copyright (c) 2012 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +/* + * modified by SimK + * 拡張倍精度浮動小数点ではなく倍精度浮動小数点で計算されるので実際のx87 FPUより精度が劣ります + */ + +#include + +#if defined(USE_FPU) && defined(SUPPORT_FPU_DOSBOX) + +#include +#include +#include +#include "ia32/ia32.mcr" + +#include +#include "ia32/instructions/fpu/fpumem.h" +#ifdef USE_SSE +#include "ia32/instructions/sse/sse.h" +#endif + +#if 1 +#undef TRACEOUT +#define TRACEOUT(s) (void)(s) +#endif /* 0 */ + +#define FPU_WORKCLOCK 6 + +#define PI 3.14159265358979323846 +#define L2E 1.4426950408889634 +#define L2T 3.3219280948873623 +#define LN2 0.69314718055994531 +#define LG2 0.3010299956639812 + +static void FPU_FINIT(void); + +static void +fpu_check_NM_EXCEPTION(){ + // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる + if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { + EXCEPTION(NM_EXCEPTION, 0); + } +} +static void +fpu_check_NM_EXCEPTION2(){ + // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる + if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { + EXCEPTION(NM_EXCEPTION, 0); + } +} + +static const FPU_PTR zero_ptr = { 0, 0, 0 }; + +/* + * FPU interface + */ + +static INLINE UINT FPU_GET_TOP(void) { + return (FPU_STATUSWORD & 0x3800)>>11; +} + +static INLINE void FPU_SET_TOP(UINT val){ + FPU_STATUSWORD &= ~0x3800; + FPU_STATUSWORD |= (val&7)<<11; +} + + +static INLINE void FPU_SET_C0(UINT C){ + FPU_STATUSWORD &= ~0x0100; + if(C) FPU_STATUSWORD |= 0x0100; +} + +static INLINE void FPU_SET_C1(UINT C){ + FPU_STATUSWORD &= ~0x0200; + if(C) FPU_STATUSWORD |= 0x0200; +} + +static INLINE void FPU_SET_C2(UINT C){ + FPU_STATUSWORD &= ~0x0400; + if(C) FPU_STATUSWORD |= 0x0400; +} + +static INLINE void FPU_SET_C3(UINT C){ + FPU_STATUSWORD &= ~0x4000; + if(C) FPU_STATUSWORD |= 0x4000; +} + +static INLINE void FPU_SET_D(UINT C){ + FPU_STATUSWORD &= ~0x0002; + if(C) FPU_STATUSWORD |= 0x0002; +} + +static INLINE void FPU_SetCW(UINT16 cword) +{ + // HACK: Bits 13-15 are not defined. Apparently, one program likes to test for + // Cyrix EMC87 by trying to set bit 15. We want the test program to see + // us as an Intel 287 when cputype == 286. + cword &= 0x7FFF; + FPU_CTRLWORD = cword; + FPU_STAT.round = (FP_RND)((cword >> 10) & 3); +} + +static void FPU_FLDCW(UINT32 addr) +{ + UINT16 temp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, addr); + FPU_SetCW(temp); +} + +static UINT16 FPU_GetTag(void) +{ + UINT i; + + UINT16 tag=0; + for(i=0;i<8;i++) + tag |= ( (FPU_STAT.tag[i]&3) <<(2*i)); + return tag; +} +static UINT8 FPU_GetTag8(void) +{ + UINT i; + + UINT8 tag=0; + for(i=0;i<8;i++) + tag |= ( (FPU_STAT.tag[i]==TAG_Empty ? 0 : 1) <<(i)); + return tag; +} + +static INLINE void FPU_SetTag(UINT16 tag) +{ + UINT i; + + for(i=0;i<8;i++){ + FPU_STAT.tag[i] = (FP_TAG)((tag >>(2*i))&3); + + } +} +static INLINE void FPU_SetTag8(UINT8 tag) +{ + UINT i; + + for(i=0;i<8;i++){ + FPU_STAT.tag[i] = (((tag>>i)&1) == 0 ? TAG_Empty : TAG_Valid); + } +} + +static void FPU_FCLEX(void){ + //FPU_STATUSWORD &= 0xff00; //should clear exceptions + FPU_STATUSWORD &= 0x7f00; //should clear exceptions? +} + +static void FPU_FNOP(void){ + return; +} + +static void FPU_PUSH(double in){ + FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; + //actually check if empty + FPU_STAT.tag[FPU_STAT_TOP] = TAG_Valid; + FPU_STAT.reg[FPU_STAT_TOP].d64 = in; +// LOG(LOG_FPU,LOG_ERROR)("Pushed at %d %g to the stack",newtop,in); + return; +} + +static void FPU_PREP_PUSH(void){ + FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; + FPU_STAT.tag[FPU_STAT_TOP] = TAG_Valid; +} + +static void FPU_FPOP(void){ + FPU_STAT.tag[FPU_STAT_TOP] = TAG_Empty; + //maybe set zero in it as well + FPU_STAT_TOP = ((FPU_STAT_TOP+1)&7); +// LOG(LOG_FPU,LOG_ERROR)("popped from %d %g off the stack",top,fpu.regs[top].d64); + return; +} + +static double FROUND(double in){ + switch(FPU_STAT.round){ + case ROUND_Nearest: + if (in-floor(in)>0.5) return (floor(in)+1); + else if (in-floor(in)<0.5) return (floor(in)); + else return ((((SINT64)(floor(in)))&1)!=0)?(floor(in)+1):(floor(in)); + break; + case ROUND_Down: + return (floor(in)); + break; + case ROUND_Up: + return (ceil(in)); + break; + case ROUND_Chop: + return in; //the cast afterwards will do it right maybe cast here + break; + default: + return in; + break; + } +} + +#define BIAS80 16383 +#define BIAS64 1023 + +static void FPU_FLD80(UINT32 addr, UINT reg) +{ + FP_REG result; + SINT64 exp64, exp64final; + SINT64 blah; + SINT64 mant64; + SINT64 sign; + + struct { + SINT16 begin; + FP_REG eind; + } test; + + test.eind.l.lower = fpu_memoryread_d(addr); + test.eind.l.upper = fpu_memoryread_d(addr+4); + test.begin = fpu_memoryread_w(addr+8); + + exp64 = (((test.begin&0x7fff) - BIAS80)); + blah = ((exp64 >0)?exp64:-exp64)&0x3ff; + exp64final = ((exp64 >0)?blah:-blah) +BIAS64; + + mant64 = (test.eind.ll >> 11) & QWORD_CONST(0xfffffffffffff); + sign = (test.begin&0x8000)?1:0; + result.ll = (sign <<63)|(exp64final << 52)| mant64; + + if(test.eind.l.lower == 0 && (UINT32)test.eind.l.upper == (UINT32)0x80000000UL && (test.begin&0x7fff) == 0x7fff) { + //Detect INF and -INF (score 3.11 when drawing a slur.) + result.d64 = sign?-HUGE_VAL:HUGE_VAL; + } + FPU_STAT.reg[reg].d64 = result.d64; + //return result.d64; + + //mant64= test.mant80/2***64 * 2 **53 +} + +static void FPU_ST80(UINT32 addr,UINT reg) +{ + SINT64 sign80; + SINT64 exp80, exp80final; + SINT64 mant80, mant80final; + + struct { + SINT16 begin; + FP_REG eind; + } test; + + sign80 = (FPU_STAT.reg[reg].ll&QWORD_CONST(0x8000000000000000))?1:0; + exp80 = FPU_STAT.reg[reg].ll&QWORD_CONST(0x7ff0000000000000); + exp80final = (exp80>>52); + mant80 = FPU_STAT.reg[reg].ll&QWORD_CONST(0x000fffffffffffff); + mant80final = (mant80 << 11); + if(FPU_STAT.reg[reg].d64 != 0){ //Zero is a special case + // Elvira wants the 8 and tcalc doesn't + mant80final |= QWORD_CONST(0x8000000000000000); + //Ca-cyber doesn't like this when result is zero. + exp80final += (BIAS80 - BIAS64); + } + test.begin = ((SINT16)(sign80)<<15)| (SINT16)(exp80final); + test.eind.ll = mant80final; + fpu_memorywrite_d(addr,test.eind.l.lower); + fpu_memorywrite_d(addr+4,test.eind.l.upper); + fpu_memorywrite_w(addr+8,test.begin); +} + + +static void FPU_FLD_F32(UINT32 addr,UINT store_to) { + union { + float f; + UINT32 l; + } blah; + + blah.l = fpu_memoryread_d(addr); + FPU_STAT.reg[store_to].d64 = (double)(blah.f); +} + +static void FPU_FLD_F64(UINT32 addr,UINT store_to) { + FPU_STAT.reg[store_to].l.lower = fpu_memoryread_d(addr); + FPU_STAT.reg[store_to].l.upper = fpu_memoryread_d(addr+4); +} + +static void FPU_FLD_F80(UINT32 addr) { + FPU_FLD80(addr, FPU_STAT_TOP); +} + +static void FPU_FLD_I16(UINT32 addr,UINT store_to) { + SINT16 blah; + + blah = fpu_memoryread_w(addr); + FPU_STAT.reg[store_to].d64 = (double)(blah); +} + +static void FPU_FLD_I32(UINT32 addr,UINT store_to) { + SINT32 blah; + + blah = fpu_memoryread_d(addr); + FPU_STAT.reg[store_to].d64 = (double)(blah); +} + +static void FPU_FLD_I64(UINT32 addr,UINT store_to) { + FP_REG blah; + + blah.l.lower = fpu_memoryread_d(addr); + blah.l.upper = fpu_memoryread_d(addr+4); + FPU_STAT.reg[store_to].d64 = (double)(blah.ll); +} + +static void FPU_FBLD(UINT32 addr,UINT store_to) +{ + UINT i; + double temp; + + UINT64 val = 0; + UINT in = 0; + UINT64 base = 1; + for(i = 0;i < 9;i++){ + in = fpu_memoryread_b(addr + i); + val += ( (in&0xf) * base); //in&0xf shouldn't be higher then 9 + base *= 10; + val += ((( in>>4)&0xf) * base); + base *= 10; + } + + //last number, only now convert to float in order to get + //the best signification + temp = (double)(val); + in = fpu_memoryread_b(addr + 9); + temp += ( (in&0xf) * base ); + if(in&0x80) temp *= -1.0; + FPU_STAT.reg[store_to].d64 = temp; +} + + +static INLINE void FPU_FLD_F32_EA(UINT32 addr) { + FPU_FLD_F32(addr,8); +} +static INLINE void FPU_FLD_F64_EA(UINT32 addr) { + FPU_FLD_F64(addr,8); +} +static INLINE void FPU_FLD_I32_EA(UINT32 addr) { + FPU_FLD_I32(addr,8); +} +static INLINE void FPU_FLD_I16_EA(UINT32 addr) { + FPU_FLD_I16(addr,8); +} + +static void FPU_FST_F32(UINT32 addr) { + union { + float f; + UINT32 l; + } blah; + + //should depend on rounding method + blah.f = (float)(FPU_STAT.reg[FPU_STAT_TOP].d64); + fpu_memorywrite_d(addr,blah.l); +} + +static void FPU_FST_F64(UINT32 addr) { + fpu_memorywrite_d(addr,FPU_STAT.reg[FPU_STAT_TOP].l.lower); + fpu_memorywrite_d(addr+4,FPU_STAT.reg[FPU_STAT_TOP].l.upper); +} + +static void FPU_FST_F80(UINT32 addr) { + FPU_ST80(addr,FPU_STAT_TOP); +} + +static void FPU_FST_I16(UINT32 addr) { + fpu_memorywrite_w(addr,(SINT16)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64))); +} + +static void FPU_FST_I32(UINT32 addr) { + fpu_memorywrite_d(addr,(SINT32)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64))); +} + +static void FPU_FST_I64(UINT32 addr) { + FP_REG blah; + + blah.ll = (SINT64)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64)); + fpu_memorywrite_d(addr,blah.l.lower); + fpu_memorywrite_d(addr+4,blah.l.upper); +} + +static void FPU_FBST(UINT32 addr) +{ + FP_REG val; + UINT p; + UINT i; + BOOL sign; + double temp; + + val = FPU_STAT.reg[FPU_STAT_TOP]; + sign = FALSE; + if(FPU_STAT.reg[FPU_STAT_TOP].ll & QWORD_CONST(0x8000000000000000)) { //sign + sign=TRUE; + val.d64=-val.d64; + } + //numbers from back to front + temp=val.d64; + for(i=0;i<9;i++){ + val.d64=temp; + temp = (double)((SINT64)(floor(val.d64/10.0))); + p = (UINT)(val.d64 - 10.0*temp); + val.d64=temp; + temp = (double)((SINT64)(floor(val.d64/10.0))); + p |= ((UINT)(val.d64 - 10.0*temp)<<4); + + fpu_memorywrite_b(addr+i,p); + } + val.d64=temp; + temp = (double)((SINT64)(floor(val.d64/10.0))); + p = (UINT)(val.d64 - 10.0*temp); + if(sign) + p|=0x80; + fpu_memorywrite_b(addr+9,p); +} + +#if defined(_WIN32) && !defined(__LIBRETRO__) +#define isinf(x) (!(_finite(x) || _isnan(x))) +#else +#define isinf(x) (!(_finite(x) || isnan(x))) +#endif +#define isdenormal(x) (_fpclass(x) == _FPCLASS_ND || _fpclass(x) == _FPCLASS_PD) + +static void FPU_FADD(UINT op1, UINT op2){ + //// HACK: Set the denormal flag according to whether the source or final result is a denormalized number. + //// This is vital if we don't want certain DOS programs to mis-detect our FPU emulation as an IIT clone chip when cputype == 286 + //BOOL was_not_normal; + + //was_not_normal = isdenormal(FPU_STAT.reg[op1].d64); + //FPU_STAT.reg[op1].d64 += FPU_STAT.reg[op2].d64; + //FPU_SET_D(was_not_normal || isdenormal(FPU_STAT.reg[op1].d64) || isdenormal(FPU_STAT.reg[op2].d64)); + FPU_STAT.reg[op1].d64 += FPU_STAT.reg[op2].d64; + //flags and such :) + return; +} + +static void FPU_FSIN(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = sin(FPU_STAT.reg[FPU_STAT_TOP].d64); + FPU_SET_C2(0); + //flags and such :) + return; +} + +static void FPU_FSINCOS(void){ + double temp; + + temp = FPU_STAT.reg[FPU_STAT_TOP].d64; + FPU_STAT.reg[FPU_STAT_TOP].d64 = sin(temp); + FPU_PUSH(cos(temp)); + FPU_SET_C2(0); + //flags and such :) + return; +} + +static void FPU_FCOS(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = cos(FPU_STAT.reg[FPU_STAT_TOP].d64); + FPU_SET_C2(0); + //flags and such :) + return; +} + +static void FPU_FSQRT(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = sqrt(FPU_STAT.reg[FPU_STAT_TOP].d64); + //flags and such :) + return; +} +static void FPU_FPATAN(void){ + FPU_STAT.reg[FPU_ST(1)].d64 = atan2(FPU_STAT.reg[FPU_ST(1)].d64,FPU_STAT.reg[FPU_STAT_TOP].d64); + FPU_FPOP(); + //flags and such :) + return; +} +static void FPU_FPTAN(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = tan(FPU_STAT.reg[FPU_STAT_TOP].d64); + FPU_PUSH(1.0); + FPU_SET_C2(0); + //flags and such :) + return; +} +static void FPU_FDIV(UINT st, UINT other){ + if(FPU_STAT.reg[other].d64==0){ + FPU_STATUSWORD |= FP_ZE_FLAG; + if(!(FPU_CTRLWORD & FP_ZE_FLAG)) + return; + } + FPU_STAT.reg[st].d64= FPU_STAT.reg[st].d64/FPU_STAT.reg[other].d64; + //flags and such :) + return; +} + +static void FPU_FDIVR(UINT st, UINT other){ + if(FPU_STAT.reg[st].d64==0){ + FPU_STATUSWORD |= FP_ZE_FLAG; + if(!(FPU_CTRLWORD & FP_ZE_FLAG)) + return; + } + FPU_STAT.reg[st].d64= FPU_STAT.reg[other].d64/FPU_STAT.reg[st].d64; + // flags and such :) + return; +} + +static void FPU_FMUL(UINT st, UINT other){ + FPU_STAT.reg[st].d64*=FPU_STAT.reg[other].d64; + //flags and such :) + return; +} + +static void FPU_FSUB(UINT st, UINT other){ + FPU_STAT.reg[st].d64 = FPU_STAT.reg[st].d64 - FPU_STAT.reg[other].d64; + //flags and such :) + return; +} + +static void FPU_FSUBR(UINT st, UINT other){ + FPU_STAT.reg[st].d64 = FPU_STAT.reg[other].d64 - FPU_STAT.reg[st].d64; + //flags and such :) + return; +} + +static void FPU_FXCH(UINT st, UINT other){ + FP_TAG tag; + FP_REG reg; + + tag = FPU_STAT.tag[other]; + reg = FPU_STAT.reg[other]; + FPU_STAT.tag[other] = FPU_STAT.tag[st]; + FPU_STAT.reg[other] = FPU_STAT.reg[st]; + FPU_STAT.tag[st] = tag; + FPU_STAT.reg[st] = reg; +} + +static void FPU_FST(UINT st, UINT other){ + FPU_STAT.tag[other] = FPU_STAT.tag[st]; + FPU_STAT.reg[other] = FPU_STAT.reg[st]; +} + +static void FPU_FCOM(UINT st, UINT other){ + if(((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || + ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero))){ + FPU_SET_C3(1); + FPU_SET_C2(1); + FPU_SET_C0(1); + return; + } + + if(FPU_STAT.reg[st].d64 == FPU_STAT.reg[other].d64){ + FPU_SET_C3(1); + FPU_SET_C2(0); + FPU_SET_C0(0); + return; + } + if(FPU_STAT.reg[st].d64 < FPU_STAT.reg[other].d64){ + FPU_SET_C3(0); + FPU_SET_C2(0); + FPU_SET_C0(1); + return; + } + // st > other + FPU_SET_C3(0); + FPU_SET_C2(0); + FPU_SET_C0(0); + return; +} +static void FPU_FCOMI(UINT st, UINT other){ + if(((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || + ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero))){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | P_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; + return; + } + + if(FPU_STAT.reg[st].d64 == FPU_STAT.reg[other].d64){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; + return; + } + if(FPU_STAT.reg[st].d64 < FPU_STAT.reg[other].d64){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; + return; + } + // st > other + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; + return; +} + +static void FPU_FUCOM(UINT st, UINT other){ + //does atm the same as fcom + FPU_FCOM(st,other); +} +static void FPU_FUCOMI(UINT st, UINT other){ + //does atm the same as fcomi + FPU_FCOMI(st,other); +} + +static void FPU_FCMOVB(UINT st, UINT other){ + if(CPU_FLAGL & C_FLAG){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVE(UINT st, UINT other){ + if(CPU_FLAGL & Z_FLAG){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVBE(UINT st, UINT other){ + if(CPU_FLAGL & (C_FLAG|Z_FLAG)){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVU(UINT st, UINT other){ + if(CPU_FLAGL & P_FLAG){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} + +static void FPU_FCMOVNB(UINT st, UINT other){ + if(!(CPU_FLAGL & C_FLAG)){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVNE(UINT st, UINT other){ + if(!(CPU_FLAGL & Z_FLAG)){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVNBE(UINT st, UINT other){ + if(!(CPU_FLAGL & (C_FLAG|Z_FLAG))){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVNU(UINT st, UINT other){ + if(!(CPU_FLAGL & P_FLAG)){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} + +static void FPU_FRNDINT(void){ + SINT64 temp; + + temp = (SINT64)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64)); + FPU_STAT.reg[FPU_STAT_TOP].d64=(double)(temp); +} + +static void FPU_FPREM(void){ + double valtop; + double valdiv; + SINT64 ressaved; + + valtop = FPU_STAT.reg[FPU_STAT_TOP].d64; + valdiv = FPU_STAT.reg[FPU_ST(1)].d64; + ressaved = (SINT64)( (valtop/valdiv) ); +// Some backups +// Real64 res=valtop - ressaved*valdiv; +// res= fmod(valtop,valdiv); + FPU_STAT.reg[FPU_STAT_TOP].d64 = valtop - ressaved*valdiv; + FPU_SET_C0((UINT)(ressaved&4)); + FPU_SET_C3((UINT)(ressaved&2)); + FPU_SET_C1((UINT)(ressaved&1)); + FPU_SET_C2(0); +} + +static void FPU_FPREM1(void){ + double valtop; + double valdiv, quot, quotf; + SINT64 ressaved; + + valtop = FPU_STAT.reg[FPU_STAT_TOP].d64; + valdiv = FPU_STAT.reg[FPU_ST(1)].d64; + quot = valtop/valdiv; + quotf = floor(quot); + + if (quot-quotf>0.5) ressaved = (SINT64)(quotf+1); + else if (quot-quotf<0.5) ressaved = (SINT64)(quotf); + else ressaved = (SINT64)(((((SINT64)(quotf))&1)!=0)?(quotf+1):(quotf)); + + FPU_STAT.reg[FPU_STAT_TOP].d64 = valtop - ressaved*valdiv; + FPU_SET_C0((UINT)(ressaved&4)); + FPU_SET_C3((UINT)(ressaved&2)); + FPU_SET_C1((UINT)(ressaved&1)); + FPU_SET_C2(0); +} + +static void FPU_FXAM(void){ + if(FPU_STAT.reg[FPU_STAT_TOP].ll & QWORD_CONST(0x8000000000000000)) //sign + { + FPU_SET_C1(1); + } + else + { + FPU_SET_C1(0); + } + if(FPU_STAT.tag[FPU_STAT_TOP] == TAG_Empty) + { + FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(1); + return; + } + if(FPU_STAT.reg[FPU_STAT_TOP].d64 == 0.0) //zero or normalized number. + { + FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0); + } + else + { + FPU_SET_C3(0);FPU_SET_C2(1);FPU_SET_C0(0); + } +} + +static void FPU_F2XM1(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = pow(2.0,FPU_STAT.reg[FPU_STAT_TOP].d64) - 1; + return; +} + +static void FPU_FYL2X(void){ + FPU_STAT.reg[FPU_ST(1)].d64*=log(FPU_STAT.reg[FPU_STAT_TOP].d64)/log((double)(2.0)); + FPU_FPOP(); + return; +} + +static void FPU_FYL2XP1(void){ + FPU_STAT.reg[FPU_ST(1)].d64*=log(FPU_STAT.reg[FPU_STAT_TOP].d64+1.0)/log((double)(2.0)); + FPU_FPOP(); + return; +} + +static void FPU_FSCALE(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 *= pow(2.0,(double)((SINT64)(FPU_STAT.reg[FPU_ST(1)].d64))); + return; //2^x where x is chopped. +} + +static void FPU_FSTENV(UINT32 addr) +{ + descriptor_t *sdp = &CPU_CS_DESC; + FPU_SET_TOP(FPU_STAT_TOP); + + switch ((CPU_CR0 & 1) | (SEG_IS_32BIT(sdp) ? 0x100 : 0x000)) + { + case 0x000: case 0x001: + fpu_memorywrite_w(addr+0,FPU_CTRLWORD); + fpu_memorywrite_w(addr+2,FPU_STATUSWORD); + fpu_memorywrite_w(addr+4,FPU_GetTag()); + fpu_memorywrite_w(addr+10,FPU_LASTINSTOP); + break; + + case 0x100: case 0x101: + fpu_memorywrite_d(addr+0,(UINT32)(FPU_CTRLWORD)); + fpu_memorywrite_d(addr+4,(UINT32)(FPU_STATUSWORD)); + fpu_memorywrite_d(addr+8,(UINT32)(FPU_GetTag())); + fpu_memorywrite_d(addr+20,FPU_LASTINSTOP); + break; + } +} + +static void FPU_FLDENV(UINT32 addr) +{ + descriptor_t *sdp = &CPU_CS_DESC; + + switch ((CPU_CR0 & 1) | (SEG_IS_32BIT(sdp) ? 0x100 : 0x000)) { + case 0x000: case 0x001: + FPU_SetCW(fpu_memoryread_w(addr+0)); + FPU_STATUSWORD = fpu_memoryread_w(addr+2); + FPU_SetTag(fpu_memoryread_w(addr+4)); + FPU_LASTINSTOP = fpu_memoryread_w(addr+10); + break; + + case 0x100: case 0x101: + FPU_SetCW((UINT16)fpu_memoryread_d(addr+0)); + FPU_STATUSWORD = (UINT16)fpu_memoryread_d(addr+4); + FPU_SetTag((UINT16)fpu_memoryread_d(addr+8)); + FPU_LASTINSTOP = (UINT16)fpu_memoryread_d(addr+20); + break; + } + FPU_STAT_TOP = FPU_GET_TOP(); +} + +static void FPU_FSAVE(UINT32 addr) +{ + UINT start; + UINT i; + + descriptor_t *sdp = &CPU_CS_DESC; + + FPU_FSTENV(addr); + start = ((SEG_IS_32BIT(sdp))?28:14); + for(i = 0;i < 8;i++){ + FPU_ST80(addr+start,FPU_ST(i)); + start += 10; + } + FPU_FINIT(); +} + +static void FPU_FRSTOR(UINT32 addr) +{ + UINT start; + UINT i; + + descriptor_t *sdp = &CPU_CS_DESC; + + FPU_FLDENV(addr); + start = ((SEG_IS_32BIT(sdp))?28:14); + for(i = 0;i < 8;i++){ + FPU_FLD80(addr+start, FPU_ST(i)); + start += 10; + } +} + +static void FPU_FXSAVE(UINT32 addr){ + UINT start; + UINT i; + + descriptor_t *sdp = &CPU_CS_DESC; + + //FPU_FSTENV(addr); + FPU_SET_TOP(FPU_STAT_TOP); + fpu_memorywrite_w(addr+0,FPU_CTRLWORD); + fpu_memorywrite_w(addr+2,FPU_STATUSWORD); + fpu_memorywrite_b(addr+4,FPU_GetTag8()); +#ifdef USE_SSE + fpu_memorywrite_d(addr+24,SSE_MXCSR); +#endif + start = 32; + for(i = 0;i < 8;i++){ + //FPU_ST80(addr+start,FPU_ST(i)); + fpu_memorywrite_d(addr+start+0,FPU_STAT.reg[FPU_ST(i)].l.lower); + fpu_memorywrite_d(addr+start+4,FPU_STAT.reg[FPU_ST(i)].l.upper); + fpu_memorywrite_d(addr+start+8,0x0000ffff); + fpu_memorywrite_d(addr+start+12,0x00000000); + start += 16; + } +#ifdef USE_SSE + start = 160; + for(i = 0;i < 8;i++){ + fpu_memorywrite_q(addr+start+0,SSE_XMMREG(i).ul64[0]); + fpu_memorywrite_q(addr+start+8,SSE_XMMREG(i).ul64[1]); + start += 16; + } +#endif +} +static void FPU_FXRSTOR(UINT32 addr){ + UINT start; + UINT i; + + descriptor_t *sdp = &CPU_CS_DESC; + + //FPU_FLDENV(addr); + FPU_SetCW(fpu_memoryread_w(addr+0)); + FPU_STATUSWORD = fpu_memoryread_w(addr+2); + FPU_SetTag8(fpu_memoryread_b(addr+4)); + FPU_STAT_TOP = FPU_GET_TOP(); +#ifdef USE_SSE + SSE_MXCSR = fpu_memoryread_d(addr+24); +#endif + start = 32; + for(i = 0;i < 8;i++){ + //FPU_STAT.reg[FPU_ST(i)].d64 = FPU_FLD80(addr+start); + FPU_STAT.reg[FPU_ST(i)].l.lower = fpu_memoryread_d(addr+start+0); + FPU_STAT.reg[FPU_ST(i)].l.upper = fpu_memoryread_d(addr+start+4); + start += 16; + } +#ifdef USE_SSE + start = 160; + for(i = 0;i < 8;i++){ + SSE_XMMREG(i).ul64[0] = fpu_memoryread_q(addr+start+0); + SSE_XMMREG(i).ul64[1] = fpu_memoryread_q(addr+start+8); + start += 16; + } +#endif +} + +void DB_FPU_FXSAVERSTOR(void){ + UINT32 op; + UINT idx, sub; + UINT32 maddr; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + switch(idx){ + case 0: // FXSAVE + fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し + maddr = calc_ea_dst(op); + FPU_FXSAVE(maddr); + break; + case 1: // FXRSTOR + fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し + maddr = calc_ea_dst(op); + FPU_FXRSTOR(maddr); + break; +#ifdef USE_SSE + case 2: // LDMXCSR + maddr = calc_ea_dst(op); + SSE_LDMXCSR(maddr); + break; + case 3: // STMXCSR + maddr = calc_ea_dst(op); + SSE_STMXCSR(maddr); + break; + case 4: // SFENCE + SSE_SFENCE(); + break; + case 5: // LFENCE + SSE_LFENCE(); + break; + case 6: // MFENCE + SSE_MFENCE(); + break; + case 7: // CLFLUSH; + SSE_CLFLUSH(op); + break; +#endif + default: + ia32_panic("invalid opcode = %02x\n", op); + break; + } +} + +static void FPU_FXTRACT(void) { + // function stores real bias in st and + // pushes the significant number onto the stack + // if double ever uses a different base please correct this function + FP_REG test; + SINT64 exp80, exp80final; + double mant; + + test = FPU_STAT.reg[FPU_STAT_TOP]; + exp80 = test.ll&QWORD_CONST(0x7ff0000000000000); + exp80final = (exp80>>52) - BIAS64; + mant = test.d64 / (pow(2.0,(double)(exp80final))); + FPU_STAT.reg[FPU_STAT_TOP].d64 = (double)(exp80final); + FPU_PUSH(mant); +} + +static void FPU_FCHS(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = -1.0*(FPU_STAT.reg[FPU_STAT_TOP].d64); +} + +static void FPU_FABS(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = fabs(FPU_STAT.reg[FPU_STAT_TOP].d64); +} + +static void FPU_FTST(void){ + FPU_STAT.reg[8].d64 = 0.0; + FPU_FCOM(FPU_STAT_TOP,8); +} + +static void FPU_FLD1(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = 1.0; +} + +static void FPU_FLDL2T(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = L2T; +} + +static void FPU_FLDL2E(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = L2E; +} + +static void FPU_FLDPI(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = PI; +} + +static void FPU_FLDLG2(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = LG2; +} + +static void FPU_FLDLN2(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = LN2; +} + +static void FPU_FLDZ(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = 0.0; + FPU_STAT.tag[FPU_STAT_TOP] = TAG_Zero; +} + + +static INLINE void FPU_FADD_EA(UINT op1){ + FPU_FADD(op1,8); +} +static INLINE void FPU_FMUL_EA(UINT op1){ + FPU_FMUL(op1,8); +} +static INLINE void FPU_FSUB_EA(UINT op1){ + FPU_FSUB(op1,8); +} +static INLINE void FPU_FSUBR_EA(UINT op1){ + FPU_FSUBR(op1,8); +} +static INLINE void FPU_FDIV_EA(UINT op1){ + FPU_FDIV(op1,8); +} +static INLINE void FPU_FDIVR_EA(UINT op1){ + FPU_FDIVR(op1,8); +} +static INLINE void FPU_FCOM_EA(UINT op1){ + FPU_FCOM(op1,8); +} + +/* + * FPU interface + */ +//int fpu_updateEmuEnv(void); +static void +FPU_FINIT(void) +{ + int i; + FPU_SetCW(0x37F); + FPU_STATUSWORD = 0; + FPU_STAT_TOP=FPU_GET_TOP(); + for(i=0;i<8;i++){ + FPU_STAT.tag[i] = TAG_Empty; + // レジスタの内容は消してはいけない ver0.86 rev40 + //FPU_STAT.reg[i].d64 = 0; + //FPU_STAT.reg[i].l.lower = 0; + //FPU_STAT.reg[i].l.upper = 0; + //FPU_STAT.reg[i].ll = 0; + } + FPU_STAT.tag[8] = TAG_Valid; // is only used by us +} +void DB_FPU_FINIT(void){ + int i; + FPU_FINIT(); + for(i=0;i<8;i++){ + FPU_STAT.tag[i] = TAG_Empty; + FPU_STAT.reg[i].l.ext = 0; + FPU_STAT.reg[i].l.lower = 0; + FPU_STAT.reg[i].l.upper = 0; + } +} + +/* + * FPU instruction + */ + +static void fpu_checkexception(){ + if((FPU_STATUSWORD & ~FPU_CTRLWORD) & 0x3F){ + EXCEPTION(MF_EXCEPTION, 0); + } +} + +static void EA_TREE(UINT op) +{ + UINT idx; + + idx = (op >> 3) & 7; + + switch (idx) { + case 0: /* FADD (単精度実数) */ + TRACEOUT(("FADD EA")); + FPU_FADD_EA(FPU_STAT_TOP); + break; + case 1: /* FMUL (単精度実数) */ + TRACEOUT(("FMUL EA")); + FPU_FMUL_EA(FPU_STAT_TOP); + break; + case 2: /* FCOM (単精度実数) */ + TRACEOUT(("FCOM EA")); + FPU_FCOM_EA(FPU_STAT_TOP); + break; + case 3: /* FCOMP (単精度実数) */ + TRACEOUT(("FCOMP EA")); + FPU_FCOM_EA(FPU_STAT_TOP); + FPU_FPOP(); + break; + case 4: /* FSUB (単精度実数) */ + TRACEOUT(("FSUB EA")); + FPU_FSUB_EA(FPU_STAT_TOP); + break; + case 5: /* FSUBR (単精度実数) */ + TRACEOUT(("FSUBR EA")); + FPU_FSUBR_EA(FPU_STAT_TOP); + break; + case 6: /* FDIV (単精度実数) */ + TRACEOUT(("FDIV EA")); + FPU_FDIV_EA(FPU_STAT_TOP); + break; + case 7: /* FDIVR (単精度実数) */ + TRACEOUT(("FDIVR EA")); + FPU_FDIVR_EA(FPU_STAT_TOP); + break; + default: + break; + } +} + +// d8 +void +DB_ESC0(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU d8 %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FADD */ + TRACEOUT(("FADD")); + FPU_FADD(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 1: /* FMUL */ + TRACEOUT(("FMUL")); + FPU_FMUL(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FCOM */ + TRACEOUT(("FCOM")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCOMP */ + TRACEOUT(("FCOMP")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + case 4: /* FSUB */ + TRACEOUT(("FSUB")); + FPU_FSUB(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 5: /* FSUBR */ + TRACEOUT(("FSUBR")); + FPU_FSUBR(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 6: /* FDIV */ + TRACEOUT(("FDIV")); + FPU_FDIV(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 7: /* FDIVR */ + TRACEOUT(("FDIVR")); + FPU_FDIVR(FPU_STAT_TOP,FPU_ST(sub)); + break; + } + } else { + madr = calc_ea_dst(op); + FPU_FLD_F32_EA(madr); + EA_TREE(op); + } +} + +// d9 +void +DB_ESC1(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU d9 %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + if(!(op < 0xc0 && idx>=4)){ + fpu_checkexception(); + } + if (op >= 0xc0) + { + switch (idx) { + case 0: /* FLD ST(0), ST(i) */ + { + UINT reg_from; + + TRACEOUT(("FLD STi")); + reg_from = FPU_ST(sub); + FPU_PREP_PUSH(); + FPU_FST(reg_from, FPU_STAT_TOP); + } + break; + + case 1: /* FXCH ST(0), ST(i) */ + TRACEOUT(("FXCH STi")); + FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); + break; + + case 2: /* FNOP */ + TRACEOUT(("FNOP")); + FPU_FNOP(); + break; + + case 3: /* FSTP STi */ + TRACEOUT(("FSTP STi")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + + case 4: + switch (sub) { + case 0x0: /* FCHS */ + TRACEOUT(("FCHS")); + FPU_FCHS(); + break; + + case 0x1: /* FABS */ + TRACEOUT(("FABS")); + FPU_FABS(); + break; + + case 0x2: /* UNKNOWN */ + case 0x3: /* ILLEGAL */ + break; + + case 0x4: /* FTST */ + TRACEOUT(("FTST")); + FPU_FTST(); + break; + + case 0x5: /* FXAM */ + TRACEOUT(("FXAM")); + FPU_FXAM(); + break; + + case 0x06: /* FTSTP (cyrix)*/ + case 0x07: /* UNKNOWN */ + break; + } + break; + + case 5: + switch (sub) { + case 0x0: /* FLD1 */ + TRACEOUT(("FLD1")); + FPU_FLD1(); + break; + + case 0x1: /* FLDL2T */ + TRACEOUT(("FLDL2T")); + FPU_FLDL2T(); + break; + + case 0x2: /* FLDL2E */ + TRACEOUT(("FLDL2E")); + FPU_FLDL2E(); + break; + + case 0x3: /* FLDPI */ + TRACEOUT(("FLDPI")); + FPU_FLDPI(); + break; + + case 0x4: /* FLDLG2 */ + TRACEOUT(("FLDLG2")); + FPU_FLDLG2(); + break; + + case 0x5: /* FLDLN2 */ + TRACEOUT(("FLDLN2")); + FPU_FLDLN2(); + break; + + case 0x6: /* FLDZ */ + TRACEOUT(("FLDZ")); + FPU_FLDZ(); + break; + + case 0x07: /* ILLEGAL */ + break; + } + break; + + case 6: + switch (sub) { + case 0x0: /* F2XM1 */ + TRACEOUT(("F2XM1")); + FPU_F2XM1(); + break; + + case 0x1: /* FYL2X */ + TRACEOUT(("FYL2X")); + FPU_FYL2X(); + break; + + case 0x2: /* FPTAN */ + TRACEOUT(("FPTAN")); + FPU_FPTAN(); + break; + + case 0x3: /* FPATAN */ + TRACEOUT(("FPATAN")); + FPU_FPATAN(); + break; + + case 0x4: /* FXTRACT */ + TRACEOUT(("FXTRACT")); + FPU_FXTRACT(); + break; + + case 0x5: /* FPREM1 */ + TRACEOUT(("FPREM1")); + FPU_FPREM1(); + break; + + case 0x6: /* FDECSTP */ + TRACEOUT(("FDECSTP")); + FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; + break; + + case 0x7: /* FINCSTP */ + TRACEOUT(("FINCSTP")); + FPU_STAT_TOP = (FPU_STAT_TOP + 1) & 7; + break; + } + break; + + case 7: + switch (sub) { + case 0x0: /* FPREM */ + TRACEOUT(("FPREM")); + FPU_FPREM(); + break; + + case 0x1: /* FYL2XP1 */ + TRACEOUT(("FYL2XP1")); + FPU_FYL2XP1(); + break; + + case 0x2: /* FSQRT */ + TRACEOUT(("FSQRT")); + FPU_FSQRT(); + break; + + case 0x3: /* FSINCOS */ + TRACEOUT(("FSINCOS")); + FPU_FSINCOS(); + break; + + case 0x4: /* FRNDINT */ + TRACEOUT(("FRNDINT")); + FPU_FRNDINT(); + break; + + case 0x5: /* FSCALE */ + TRACEOUT(("FSCALE")); + FPU_FSCALE(); + break; + + case 0x6: /* FSIN */ + TRACEOUT(("FSIN")); + FPU_FSIN(); + break; + + case 0x7: /* FCOS */ + TRACEOUT(("FCOS")); + FPU_FCOS(); + break; + } + break; + + default: + ia32_panic("ESC1: invalid opcode = %02x\n", op); + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FLD (単精度実数) */ + TRACEOUT(("FLD float")); + FPU_PREP_PUSH(); + FPU_FLD_F32(madr,FPU_STAT_TOP); + break; + + case 1: /* UNKNOWN */ + break; + + case 2: /* FST (単精度実数) */ + TRACEOUT(("FST float")); + FPU_FST_F32(madr); + break; + + case 3: /* FSTP (単精度実数) */ + TRACEOUT(("FSTP float")); + FPU_FST_F32(madr); + FPU_FPOP(); + break; + + case 4: /* FLDENV */ + TRACEOUT(("FLDENV")); + FPU_FLDENV(madr); + break; + + case 5: /* FLDCW */ + TRACEOUT(("FLDCW")); + FPU_FLDCW(madr); + break; + + case 6: /* FSTENV */ + TRACEOUT(("FSTENV")); + FPU_FSTENV(madr); + break; + + case 7: /* FSTCW */ + TRACEOUT(("FSTCW/FNSTCW")); + fpu_memorywrite_w(madr,FPU_CTRLWORD); + break; + + default: + break; + } + } +} + +// da +void +DB_ESC2(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU da %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FCMOVB */ + TRACEOUT(("ESC2: FCMOVB")); + FPU_FCMOVB(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 1: /* FCMOVE */ + TRACEOUT(("ESC2: FCMOVE")); + FPU_FCMOVE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FCMOVBE */ + TRACEOUT(("ESC2: FCMOVBE")); + FPU_FCMOVBE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCMOVU */ + TRACEOUT(("ESC2: FCMOVU")); + FPU_FCMOVU(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 5: + switch (sub) { + case 1: /* FUCOMPP */ + TRACEOUT(("FUCOMPP")); + FPU_FUCOM(FPU_STAT_TOP,FPU_ST(1)); + FPU_FPOP(); + FPU_FPOP(); + break; + + default: + break; + } + break; + + default: + break; + } + } else { + madr = calc_ea_dst(op); + FPU_FLD_I32_EA(madr); + EA_TREE(op); + } +} + +// db +void +DB_ESC3(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU db %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + if(!(op >= 0xc0 && idx==4)){ + fpu_checkexception(); + } + if (op >= 0xc0) + { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FCMOVNB */ + TRACEOUT(("ESC3: FCMOVNB")); + FPU_FCMOVNB(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 1: /* FCMOVNE */ + TRACEOUT(("ESC3: FCMOVNE")); + FPU_FCMOVNE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FCMOVNBE */ + TRACEOUT(("ESC3: FCMOVNBE")); + FPU_FCMOVNBE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCMOVNU */ + TRACEOUT(("ESC3: FCMOVNU")); + FPU_FCMOVNU(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 4: + switch (sub) { + case 0: /* FNENI */ + case 1: /* FNDIS */ + break; + + case 2: /* FCLEX */ + TRACEOUT(("FCLEX")); + FPU_FCLEX(); + break; + + case 3: /* FNINIT/FINIT */ + TRACEOUT(("FNINIT/FINIT")); + FPU_FINIT(); + break; + + case 4: /* FNSETPM */ + case 5: /* FRSTPM */ + FPU_FNOP(); + break; + + default: + break; + } + break; + case 5: /* FUCOMI */ + TRACEOUT(("ESC3: FUCOMI")); + FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 6: /* FCOMI */ + TRACEOUT(("ESC3: FCOMI")); + FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); + break; + default: + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FILD (DWORD) */ + TRACEOUT(("FILD")); + FPU_PREP_PUSH(); + FPU_FLD_I32(madr,FPU_STAT_TOP); + break; + + case 1: /* FISTTP (DWORD) */ + { + FP_RND oldrnd = FPU_STAT.round; + FPU_STAT.round = ROUND_Down; + FPU_FST_I32(madr); + FPU_STAT.round = oldrnd; + } + FPU_FPOP(); + break; + + case 2: /* FIST (DWORD) */ + TRACEOUT(("FIST")); + FPU_FST_I32(madr); + break; + + case 3: /* FISTP (DWORD) */ + TRACEOUT(("FISTP")); + FPU_FST_I32(madr); + FPU_FPOP(); + break; + + case 5: /* FLD (拡張実数) */ + TRACEOUT(("FLD 80 Bits Real")); + FPU_PREP_PUSH(); + FPU_FLD_F80(madr); + break; + + case 7: /* FSTP (拡張実数) */ + TRACEOUT(("FSTP 80 Bits Real")); + FPU_FST_F80(madr); + FPU_FPOP(); + break; + + default: + break; + } + } +} + +// dc +void +DB_ESC4(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU dc %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(i), ST(0) */ + switch (idx) { + case 0: /* FADD */ + TRACEOUT(("ESC4: FADD")); + FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); + break; + case 1: /* FMUL */ + TRACEOUT(("ESC4: FMUL")); + FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); + break; + case 2: /* FCOM */ + TRACEOUT(("ESC4: FCOM")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCOMP */ + TRACEOUT(("ESC4: FCOMP")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + case 4: /* FSUBR */ + TRACEOUT(("ESC4: FSUBR")); + FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); + break; + case 5: /* FSUB */ + TRACEOUT(("ESC4: FSUB")); + FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); + break; + case 6: /* FDIVR */ + TRACEOUT(("ESC4: FDIVR")); + FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); + break; + case 7: /* FDIV */ + TRACEOUT(("ESC4: FDIV")); + FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); + break; + default: + break; + } + } else { + madr = calc_ea_dst(op); + FPU_FLD_F64_EA(madr); + EA_TREE(op); + } +} + +// dd +void +DB_ESC5(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU dd %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + fpu_check_NM_EXCEPTION(); + //if(op < 0xc0 && (idx==6 || idx==4)){ + // _ADD_EIP(-1); // XXX: 無理やり戻す + // fpu_check_NM_EXCEPTION2(); + // _ADD_EIP(1); + //}else{ + // _ADD_EIP(-1); // XXX: 無理やり戻す + // fpu_check_NM_EXCEPTION(); + // _ADD_EIP(1); + //} + if(op >= 0xc0 || (idx!=4 && idx!=6 && idx!=7)){ + fpu_checkexception(); + } + if (op >= 0xc0) { + /* FUCOM ST(i), ST(0) */ + /* Fxxx ST(i) */ + switch (idx) { + case 0: /* FFREE */ + TRACEOUT(("FFREE")); + FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; + break; + case 1: /* FXCH */ + TRACEOUT(("FXCH")); + FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FST */ + TRACEOUT(("FST")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FSTP */ + TRACEOUT(("FSTP")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + case 4: /* FUCOM */ + TRACEOUT(("FUCOM")); + FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 5: /* FUCOMP */ + TRACEOUT(("FUCOMP")); + FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + + default: + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FLD (倍精度実数) */ + TRACEOUT(("FLD double real")); + FPU_PREP_PUSH(); + FPU_FLD_F64(madr,FPU_STAT_TOP); + break; + case 1: /* FISTTP (QWORD) */ + { + FP_RND oldrnd = FPU_STAT.round; + FPU_STAT.round = ROUND_Down; + FPU_FST_I64(madr); + FPU_STAT.round = oldrnd; + } + FPU_FPOP(); + break; + case 2: /* FST (倍精度実数) */ + TRACEOUT(("FST double real")); + FPU_FST_F64(madr); + break; + case 3: /* FSTP (倍精度実数) */ + TRACEOUT(("FSTP double real")); + FPU_FST_F64(madr); + FPU_FPOP(); + break; + case 4: /* FRSTOR */ + TRACEOUT(("FRSTOR")); + FPU_FRSTOR(madr); + break; + case 6: /* FSAVE */ + TRACEOUT(("FSAVE")); + FPU_FSAVE(madr); + break; + + case 7: /* FSTSW */ + FPU_SET_TOP(FPU_STAT_TOP); + //cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, FPU_CTRLWORD); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, FPU_STATUSWORD); + break; + + default: + break; + } + } +} + +// de +void +DB_ESC6(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU de %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(i), ST(0) */ + switch (idx) { + case 0: /* FADDP */ + TRACEOUT(("FADDP")); + FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); + break; + case 1: /* FMULP */ + TRACEOUT(("FMULP")); + FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); + break; + case 2: /* FCOMP5 */ + TRACEOUT(("FCOMP5")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCOMPP */ + TRACEOUT(("FCOMPP")); + if(sub != 1) { + return; + } + FPU_FCOM(FPU_STAT_TOP,FPU_ST(1)); + FPU_FPOP(); /* extra pop at the bottom*/ + break; + case 4: /* FSUBRP */ + TRACEOUT(("FSUBRP")); + FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); + break; + case 5: /* FSUBP */ + TRACEOUT(("FSUBP")); + FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); + break; + case 6: /* FDIVRP */ + TRACEOUT(("FDIVRP")); + FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); + if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ + return; // POPしないようにする + } + break; + case 7: /* FDIVP */ + TRACEOUT(("FDIVP")); + FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); + if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ + return; // POPしないようにする + } + break; + /*FALLTHROUGH*/ + default: + break; + } + FPU_FPOP(); + } else { + madr = calc_ea_dst(op); + FPU_FLD_I16_EA(madr); + EA_TREE(op); + } +} + +// df +void +DB_ESC7(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU df %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + if(!(op >= 0xc0 && idx==4 && sub==0)){ + fpu_checkexception(); + } + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FFREEP */ + TRACEOUT(("FFREEP")); + FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; + FPU_FPOP(); + break; + case 1: /* FXCH */ + TRACEOUT(("FXCH")); + FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); + break; + + case 2: + case 3: /* FSTP */ + TRACEOUT(("FSTP")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + + case 4: + switch (sub) + { + case 0: /* FSTSW AX */ + TRACEOUT(("FSTSW AX")); + FPU_SET_TOP(FPU_STAT_TOP); + CPU_AX = FPU_STATUSWORD; + break; + + default: + break; + } + break; + case 5: /* FUCOMIP */ + TRACEOUT(("ESC7: FUCOMIP")); + FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + case 6: /* FCOMIP */ + TRACEOUT(("ESC7: FCOMIP")); + FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + default: + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FILD (WORD) */ + TRACEOUT(("FILD SINT16")); + FPU_PREP_PUSH(); + FPU_FLD_I16(madr,FPU_STAT_TOP); + break; + case 1: /* FISTTP (WORD) */ + { + FP_RND oldrnd = FPU_STAT.round; + FPU_STAT.round = ROUND_Down; + FPU_FST_I16(madr); + FPU_STAT.round = oldrnd; + } + FPU_FPOP(); + break; + case 2: /* FIST (WORD) */ + TRACEOUT(("FIST SINT16")); + FPU_FST_I16(madr); + break; + case 3: /* FISTP (WORD) */ + TRACEOUT(("FISTP SINT16")); + FPU_FST_I16(madr); + FPU_FPOP(); + break; + + case 4: /* FBLD (BCD) */ + TRACEOUT(("FBLD packed BCD")); + FPU_PREP_PUSH(); + FPU_FBLD(madr,FPU_STAT_TOP); + break; + + case 5: /* FILD (QWORD) */ + TRACEOUT(("FILD SINT64")); + FPU_PREP_PUSH(); + FPU_FLD_I64(madr,FPU_STAT_TOP); + break; + + case 6: /* FBSTP (BCD) */ + TRACEOUT(("FBSTP packed BCD")); + FPU_FBST(madr); + FPU_FPOP(); + break; + + case 7: /* FISTP (QWORD) */ + TRACEOUT(("FISTP SINT64")); + FPU_FST_I64(madr); + FPU_FPOP(); + break; + + default: + break; + } + } +} +#endif diff --git a/i386c/ia32/instructions/fpu/fpemul_dosbox2.c b/i386c/ia32/instructions/fpu/fpemul_dosbox2.c old mode 100755 new mode 100644 index acdb327b..f71f25a0 --- a/i386c/ia32/instructions/fpu/fpemul_dosbox2.c +++ b/i386c/ia32/instructions/fpu/fpemul_dosbox2.c @@ -1,2213 +1,2213 @@ -/* - * Copyright (C) 2002-2015 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Copyright (c) 2012 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -/* - * modified by SimK - * 整数値のロード・ストア限定で拡張倍精度浮動小数点相当の精度があります - */ - -#include - -#if defined(USE_FPU) && defined(SUPPORT_FPU_DOSBOX2) - -#include -#include -#include -#include "ia32/ia32.mcr" - -#include -#include "ia32/instructions/fpu/fpumem.h" -#ifdef USE_SSE -#include "ia32/instructions/sse/sse.h" -#endif - -#if 1 -#undef TRACEOUT -#define TRACEOUT(s) (void)(s) -#endif /* 0 */ - -#define FPU_WORKCLOCK 6 - -#define PI 3.14159265358979323846 -#define L2E 1.4426950408889634 -#define L2T 3.3219280948873623 -#define LN2 0.69314718055994531 -#define LG2 0.3010299956639812 - -static void FPU_FINIT(void); - -static void -fpu_check_NM_EXCEPTION(){ - // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる - if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { - EXCEPTION(NM_EXCEPTION, 0); - } -} -static void -fpu_check_NM_EXCEPTION2(){ - // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる - if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { - EXCEPTION(NM_EXCEPTION, 0); - } -} - -static const FPU_PTR zero_ptr = { 0, 0, 0 }; - -/* - * FPU interface - */ - -static INLINE UINT FPU_GET_TOP(void) { - return (FPU_STATUSWORD & 0x3800)>>11; -} - -static INLINE void FPU_SET_TOP(UINT val){ - FPU_STATUSWORD &= ~0x3800; - FPU_STATUSWORD |= (val&7)<<11; -} - - -static INLINE void FPU_SET_C0(UINT C){ - FPU_STATUSWORD &= ~0x0100; - if(C) FPU_STATUSWORD |= 0x0100; -} - -static INLINE void FPU_SET_C1(UINT C){ - FPU_STATUSWORD &= ~0x0200; - if(C) FPU_STATUSWORD |= 0x0200; -} - -static INLINE void FPU_SET_C2(UINT C){ - FPU_STATUSWORD &= ~0x0400; - if(C) FPU_STATUSWORD |= 0x0400; -} - -static INLINE void FPU_SET_C3(UINT C){ - FPU_STATUSWORD &= ~0x4000; - if(C) FPU_STATUSWORD |= 0x4000; -} - -static INLINE void FPU_SET_D(UINT C){ - FPU_STATUSWORD &= ~0x0002; - if(C) FPU_STATUSWORD |= 0x0002; -} - -static INLINE void FPU_SetCW(UINT16 cword) -{ - // HACK: Bits 13-15 are not defined. Apparently, one program likes to test for - // Cyrix EMC87 by trying to set bit 15. We want the test program to see - // us as an Intel 287 when cputype == 286. - cword &= 0x7FFF; - FPU_CTRLWORD = cword; - FPU_STAT.round = (FP_RND)((cword >> 10) & 3); -} - -static void FPU_FLDCW(UINT32 addr) -{ - UINT16 temp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, addr); - FPU_SetCW(temp); -} - -static UINT16 FPU_GetTag(void) -{ - UINT i; - - UINT16 tag=0; - for(i=0;i<8;i++) - tag |= ( (FPU_STAT.tag[i]&3) <<(2*i)); - return tag; -} -static UINT8 FPU_GetTag8(void) -{ - UINT i; - - UINT8 tag=0; - for(i=0;i<8;i++) - tag |= ( (FPU_STAT.tag[i]==TAG_Empty ? 0 : 1) <<(i)); - return tag; -} - -static INLINE void FPU_SetTag(UINT16 tag) -{ - UINT i; - - for(i=0;i<8;i++){ - FPU_STAT.tag[i] = (FP_TAG)((tag >>(2*i))&3); - - } -} -static INLINE void FPU_SetTag8(UINT8 tag) -{ - UINT i; - - for(i=0;i<8;i++){ - FPU_STAT.tag[i] = (((tag>>i)&1) == 0 ? TAG_Empty : TAG_Valid); - } -} - -static void FPU_FCLEX(void){ - //FPU_STATUSWORD &= 0xff00; //should clear exceptions - FPU_STATUSWORD &= 0x7f00; //should clear exceptions? -} - -static void FPU_FNOP(void){ - return; -} - -static void FPU_PUSH(double in){ - FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; - //actually check if empty - FPU_STAT.tag[FPU_STAT_TOP] = TAG_Valid; - FPU_STAT.reg[FPU_STAT_TOP].d64 = in; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; -// LOG(LOG_FPU,LOG_ERROR)("Pushed at %d %g to the stack",newtop,in); - return; -} - -static void FPU_PREP_PUSH(void){ - FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; - FPU_STAT.tag[FPU_STAT_TOP] = TAG_Valid; -} - -static void FPU_FPOP(void){ - FPU_STAT.tag[FPU_STAT_TOP] = TAG_Empty; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - //maybe set zero in it as well - FPU_STAT_TOP = ((FPU_STAT_TOP+1)&7); -// LOG(LOG_FPU,LOG_ERROR)("popped from %d %g off the stack",top,fpu.regs[top].d64); - return; -} - -static double FROUND(double in){ - switch(FPU_STAT.round){ - case ROUND_Nearest: - if (in-floor(in)>0.5) return (floor(in)+1); - else if (in-floor(in)<0.5) return (floor(in)); - else return ((((SINT64)(floor(in)))&1)!=0)?(floor(in)+1):(floor(in)); - break; - case ROUND_Down: - return (floor(in)); - break; - case ROUND_Up: - return (ceil(in)); - break; - case ROUND_Chop: - return in; //the cast afterwards will do it right maybe cast here - break; - default: - return in; - break; - } -} - -#define BIAS80 16383 -#define BIAS64 1023 - -static void FPU_FLD80(UINT32 addr, UINT reg) -{ - FP_REG result; - SINT64 exp64, exp64final; - SINT64 blah; - SINT64 mant64; - SINT64 sign; - - struct { - SINT16 begin; - FP_REG eind; - } test; - - test.eind.l.lower = fpu_memoryread_d(addr); - test.eind.l.upper = fpu_memoryread_d(addr+4); - test.begin = fpu_memoryread_w(addr+8); - - exp64 = (((test.begin&0x7fff) - BIAS80)); - blah = ((exp64 >0)?exp64:-exp64)&0x3ff; - exp64final = ((exp64 >0)?blah:-blah) +BIAS64; - - mant64 = (test.eind.ll >> 11) & QWORD_CONST(0xfffffffffffff); - sign = (test.begin&0x8000)?1:0; - result.ll = (sign <<63)|(exp64final << 52)| mant64; - - { - UINT64 tmp; - unsigned int shift; - shift = (unsigned int)(63-exp64); - // 1.xxxを64bit整数表現できるかチェック - if(exp64 >= 0 && // 1未満なったらアウト - exp64 <= 63 && // 値が64bit整数で表現できない場合もアウト(とりあえず符号無しで判定) - ((test.eind.ll >> shift) << shift)==test.eind.ll){ // 小数点以下の数がある場合もアウト - //tmp = ((((UINT64)test.eind.ll) >> 1) | QWORD_CONST(0x8000000000000000)) >> shift; - tmp = ((UINT64)test.eind.ll) >> shift; - if(sign==0 && tmp < QWORD_CONST(0x8000000000000000)){ // 符号付き(正)で表現できるか - FPU_STAT.int_reg[reg].ul64.m12 = tmp; - FPU_STAT.int_regvalid[reg] = 1; - }else if(sign==1 && tmp <= QWORD_CONST(0x8000000000000000)){ // 符号付き(負)で表現できるか - FPU_STAT.int_reg[reg].ul64.m12 = ((~tmp) + 1); - FPU_STAT.int_regvalid[reg] = 1; - }else{ - FPU_STAT.int_regvalid[reg] = 0; - } - }else if((test.begin&0x7fff) == 0 && test.eind.ll == 0){ // 0の場合 - FPU_STAT.int_reg[reg].ul64.m12 = 0; - FPU_STAT.int_regvalid[reg] = 1; - }else{ - FPU_STAT.int_regvalid[reg] = 0; - } - } - - if(test.eind.l.lower == 0 && (UINT32)test.eind.l.upper == (UINT32)0x80000000UL && (test.begin&0x7fff) == 0x7fff) { - //Detect INF and -INF (score 3.11 when drawing a slur.) - result.d64 = sign?-HUGE_VAL:HUGE_VAL; - } - FPU_STAT.reg[reg].d64 = result.d64; - //return result.d64; - - //mant64= test.mant80/2***64 * 2 **53 -} - -static void FPU_ST80(UINT32 addr,UINT reg) -{ - SINT64 sign80; - SINT64 exp80, exp80final; - SINT64 mant80, mant80final; - - struct { - SINT16 begin; - FP_REG eind; - } test; - - sign80 = (FPU_STAT.reg[reg].ll&QWORD_CONST(0x8000000000000000))?1:0; - exp80 = FPU_STAT.reg[reg].ll&QWORD_CONST(0x7ff0000000000000); - exp80final = (exp80>>52); - mant80 = FPU_STAT.reg[reg].ll&QWORD_CONST(0x000fffffffffffff); - mant80final = (mant80 << 11); - if(FPU_STAT.reg[reg].d64 != 0){ //Zero is a special case - // Elvira wants the 8 and tcalc doesn't - mant80final |= QWORD_CONST(0x8000000000000000); - //Ca-cyber doesn't like this when result is zero. - exp80final += (BIAS80 - BIAS64); - } - test.begin = ((SINT16)(sign80)<<15)| (SINT16)(exp80final); - test.eind.ll = mant80final; - if(FPU_STAT.int_regvalid[reg] && FPU_STAT.int_reg[reg].ul64.m12!=0){ - UINT64 tmp; - if((SINT64)FPU_STAT.int_reg[reg].ul64.m12 < 0){ - sign80 = 1; - tmp = (~(FPU_STAT.int_reg[reg].ul64.m12)) + 1; - }else{ - sign80 = 0; - tmp = FPU_STAT.int_reg[reg].ul64.m12; - } - exp80final = BIAS80 + 63; - while(!(tmp & QWORD_CONST(0x8000000000000000))){ - tmp = tmp << 1; - exp80final--; - } - test.begin = ((SINT16)(sign80)<<15)| (SINT16)(exp80final); - test.eind.ll = tmp; - } - fpu_memorywrite_d(addr,test.eind.l.lower); - fpu_memorywrite_d(addr+4,test.eind.l.upper); - fpu_memorywrite_w(addr+8,test.begin); -} - - -static void FPU_FLD_F32(UINT32 addr,UINT store_to) { - union { - float f; - UINT32 l; - } blah; - - blah.l = fpu_memoryread_d(addr); - FPU_STAT.reg[store_to].d64 = (double)(blah.f); - FPU_STAT.int_regvalid[store_to] = 0; -} - -static void FPU_FLD_F64(UINT32 addr,UINT store_to) { - FPU_STAT.reg[store_to].l.lower = fpu_memoryread_d(addr); - FPU_STAT.reg[store_to].l.upper = fpu_memoryread_d(addr+4); - FPU_STAT.int_regvalid[store_to] = 0; -} - -static void FPU_FLD_F80(UINT32 addr) { - FPU_FLD80(addr, FPU_STAT_TOP); -} - -static void FPU_FLD_I16(UINT32 addr,UINT store_to) { - SINT16 blah; - - blah = fpu_memoryread_w(addr); - FPU_STAT.reg[store_to].d64 = (double)(blah); - FPU_STAT.int_reg[store_to].ul64.m12 = (UINT64)((SINT64)blah); - FPU_STAT.int_regvalid[store_to] = 1; -} - -static void FPU_FLD_I32(UINT32 addr,UINT store_to) { - SINT32 blah; - - blah = fpu_memoryread_d(addr); - FPU_STAT.reg[store_to].d64 = (double)(blah); - FPU_STAT.int_reg[store_to].ul64.m12 = (UINT64)((SINT64)blah); - FPU_STAT.int_regvalid[store_to] = 1; -} - -static void FPU_FLD_I64(UINT32 addr,UINT store_to) { - FP_REG blah; - - blah.l.lower = fpu_memoryread_d(addr); - blah.l.upper = fpu_memoryread_d(addr+4); - FPU_STAT.reg[store_to].d64 = (double)(blah.ll); - FPU_STAT.int_reg[store_to].ul64.m12 = (UINT64)(blah.ll); - FPU_STAT.int_regvalid[store_to] = 1; -} - -static void FPU_FBLD(UINT32 addr,UINT store_to) -{ - UINT i; - double temp; - - UINT64 val = 0; - UINT in = 0; - UINT64 base = 1; - for(i = 0;i < 9;i++){ - in = fpu_memoryread_b(addr + i); - val += ( (in&0xf) * base); //in&0xf shouldn't be higher then 9 - base *= 10; - val += ((( in>>4)&0xf) * base); - base *= 10; - } - - //last number, only now convert to float in order to get - //the best signification - temp = (double)(val); - in = fpu_memoryread_b(addr + 9); - temp += ( (in&0xf) * base ); - if(in&0x80) temp *= -1.0; - FPU_STAT.reg[store_to].d64 = temp; -} - - -static INLINE void FPU_FLD_F32_EA(UINT32 addr) { - FPU_FLD_F32(addr,8); -} -static INLINE void FPU_FLD_F64_EA(UINT32 addr) { - FPU_FLD_F64(addr,8); -} -static INLINE void FPU_FLD_I32_EA(UINT32 addr) { - FPU_FLD_I32(addr,8); -} -static INLINE void FPU_FLD_I16_EA(UINT32 addr) { - FPU_FLD_I16(addr,8); -} - -static void FPU_FST_F32(UINT32 addr) { - union { - float f; - UINT32 l; - } blah; - - //should depend on rounding method - blah.f = (float)(FPU_STAT.reg[FPU_STAT_TOP].d64); - fpu_memorywrite_d(addr,blah.l); -} - -static void FPU_FST_F64(UINT32 addr) { - fpu_memorywrite_d(addr,FPU_STAT.reg[FPU_STAT_TOP].l.lower); - fpu_memorywrite_d(addr+4,FPU_STAT.reg[FPU_STAT_TOP].l.upper); -} - -static void FPU_FST_F80(UINT32 addr) { - FPU_ST80(addr,FPU_STAT_TOP); -} - -static void FPU_FST_I16(UINT32 addr) { - if(FPU_STAT.int_regvalid[FPU_STAT_TOP]){ - fpu_memorywrite_w(addr,(SINT16)((SINT64)(FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12))); - }else{ - fpu_memorywrite_w(addr,(SINT16)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64))); - } -} - -static void FPU_FST_I32(UINT32 addr) { - if(FPU_STAT.int_regvalid[FPU_STAT_TOP]){ - fpu_memorywrite_d(addr,(SINT32)((SINT64)(FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12))); - }else{ - fpu_memorywrite_d(addr,(SINT32)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64))); - } -} - -static void FPU_FST_I64(UINT32 addr) { - FP_REG blah; - - if(FPU_STAT.int_regvalid[FPU_STAT_TOP]){ - blah.ll = (SINT64)FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12; - fpu_memorywrite_d(addr,blah.l.lower); - fpu_memorywrite_d(addr+4,blah.l.upper); - }else{ - blah.ll = (SINT64)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64)); - fpu_memorywrite_d(addr,blah.l.lower); - fpu_memorywrite_d(addr+4,blah.l.upper); - } -} - -static void FPU_FBST(UINT32 addr) -{ - FP_REG val; - UINT p; - UINT i; - BOOL sign; - double temp; - - val = FPU_STAT.reg[FPU_STAT_TOP]; - sign = FALSE; - if(FPU_STAT.reg[FPU_STAT_TOP].ll & QWORD_CONST(0x8000000000000000)) { //sign - sign=TRUE; - val.d64=-val.d64; - } - //numbers from back to front - temp=val.d64; - for(i=0;i<9;i++){ - val.d64=temp; - temp = (double)((SINT64)(floor(val.d64/10.0))); - p = (UINT)(val.d64 - 10.0*temp); - val.d64=temp; - temp = (double)((SINT64)(floor(val.d64/10.0))); - p |= ((UINT)(val.d64 - 10.0*temp)<<4); - - fpu_memorywrite_b(addr+i,p); - } - val.d64=temp; - temp = (double)((SINT64)(floor(val.d64/10.0))); - p = (UINT)(val.d64 - 10.0*temp); - if(sign) - p|=0x80; - fpu_memorywrite_b(addr+9,p); -} - -#if defined(_WIN32) && !defined(__LIBRETRO__) -#define isinf(x) (!(_finite(x) || _isnan(x))) -#else -#define isinf(x) (!(_finite(x) || isnan(x))) -#endif -#define isdenormal(x) (_fpclass(x) == _FPCLASS_ND || _fpclass(x) == _FPCLASS_PD) - -static void FPU_FADD(UINT op1, UINT op2){ - //// HACK: Set the denormal flag according to whether the source or final result is a denormalized number. - //// This is vital if we don't want certain DOS programs to mis-detect our FPU emulation as an IIT clone chip when cputype == 286 - //BOOL was_not_normal; - - //was_not_normal = isdenormal(FPU_STAT.reg[op1].d64); - //FPU_STAT.reg[op1].d64 += FPU_STAT.reg[op2].d64; - //FPU_SET_D(was_not_normal || isdenormal(FPU_STAT.reg[op1].d64) || isdenormal(FPU_STAT.reg[op2].d64)); - FPU_STAT.reg[op1].d64 += FPU_STAT.reg[op2].d64; - //flags and such :) - //if(FPU_STAT.int_regvalid[op1] && FPU_STAT.int_regvalid[op2]){ - // SINT64 v1 = (SINT64)FPU_STAT.int_reg[op1].ul64.m12; - // SINT64 v2 = (SINT64)FPU_STAT.int_reg[op2].ul64.m12; - // SINT64 v12 = v1+v2; - // if((v1>=0 && v2<=0) || (v1<=0 && v2>=0)){ // 符号が異なればオーバーフローしない - // FPU_STAT.int_reg[op1].ul64.m12 = (UINT64)v12; - // }else if((v1>0 && v2>0) && v12 > 0){ // XXX: 正+正→正 多分処理系依存 - // FPU_STAT.int_reg[op1].ul64.m12 = (UINT64)v12; - // }else if((v1<0 && v2<0) && v12 < 0){ // XXX: 負+負→負 多分処理系依存 - // FPU_STAT.int_reg[op1].ul64.m12 = (UINT64)v12; - // }else{ - // FPU_STAT.int_regvalid[op1] = 0; - // } - //}else{ - FPU_STAT.int_regvalid[op1] = 0; - //} - return; -} - -static void FPU_FSIN(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = sin(FPU_STAT.reg[FPU_STAT_TOP].d64); - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - FPU_SET_C2(0); - //flags and such :) - return; -} - -static void FPU_FSINCOS(void){ - double temp; - - temp = FPU_STAT.reg[FPU_STAT_TOP].d64; - FPU_STAT.reg[FPU_STAT_TOP].d64 = sin(temp); - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - FPU_PUSH(cos(temp)); - FPU_SET_C2(0); - //flags and such :) - return; -} - -static void FPU_FCOS(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = cos(FPU_STAT.reg[FPU_STAT_TOP].d64); - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - FPU_SET_C2(0); - //flags and such :) - return; -} - -static void FPU_FSQRT(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = sqrt(FPU_STAT.reg[FPU_STAT_TOP].d64); - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - //flags and such :) - return; -} -static void FPU_FPATAN(void){ - FPU_STAT.reg[FPU_ST(1)].d64 = atan2(FPU_STAT.reg[FPU_ST(1)].d64,FPU_STAT.reg[FPU_STAT_TOP].d64); - FPU_STAT.int_regvalid[FPU_ST(1)] = 0; - FPU_FPOP(); - //flags and such :) - return; -} -static void FPU_FPTAN(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = tan(FPU_STAT.reg[FPU_STAT_TOP].d64); - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - FPU_PUSH(1.0); - FPU_SET_C2(0); - //flags and such :) - return; -} -static void FPU_FDIV(UINT st, UINT other){ - if(FPU_STAT.reg[other].d64==0){ - FPU_STATUSWORD |= FP_ZE_FLAG; - if(!(FPU_CTRLWORD & FP_ZE_FLAG)) - return; - } - FPU_STAT.reg[st].d64= FPU_STAT.reg[st].d64/FPU_STAT.reg[other].d64; - FPU_STAT.int_regvalid[st] = 0; - //flags and such :) - return; -} - -static void FPU_FDIVR(UINT st, UINT other){ - if(FPU_STAT.reg[st].d64==0){ - FPU_STATUSWORD |= FP_ZE_FLAG; - if(!(FPU_CTRLWORD & FP_ZE_FLAG)) - return; - } - FPU_STAT.reg[st].d64= FPU_STAT.reg[other].d64/FPU_STAT.reg[st].d64; - FPU_STAT.int_regvalid[st] = 0; - // flags and such :) - return; -} - -static void FPU_FMUL(UINT st, UINT other){ - FPU_STAT.reg[st].d64*=FPU_STAT.reg[other].d64; - FPU_STAT.int_regvalid[st] = 0; - //flags and such :) - return; -} - -static void FPU_FSUB(UINT st, UINT other){ - FPU_STAT.reg[st].d64 = FPU_STAT.reg[st].d64 - FPU_STAT.reg[other].d64; - //if(FPU_STAT.int_regvalid[st] && FPU_STAT.int_regvalid[other]){ - // SINT64 v1 = (SINT64)FPU_STAT.int_reg[st].ul64.m12; - // SINT64 v2 = (SINT64)FPU_STAT.int_reg[other].ul64.m12; - // SINT64 v12 = v1-v2; - // if((v1>=0 && v2>=0) || (v1<=0 && v2<=0)){ // 符号が異なればオーバーフローしない - // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; - // }else if((v1>0 && v2<0) && v12 > 0){ // XXX: 正+正→正 多分処理系依存 - // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; - // }else if((v1<0 && v2>0) && v12 < 0){ // XXX: 負+負→負 多分処理系依存 - // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; - // }else{ - // FPU_STAT.int_regvalid[st] = 0; - // } - //}else{ - FPU_STAT.int_regvalid[st] = 0; - //} - //flags and such :) - return; -} - -static void FPU_FSUBR(UINT st, UINT other){ - FPU_STAT.reg[st].d64 = FPU_STAT.reg[other].d64 - FPU_STAT.reg[st].d64; - //if(FPU_STAT.int_regvalid[st] && FPU_STAT.int_regvalid[other]){ - // SINT64 v1 = (SINT64)FPU_STAT.int_reg[other].ul64.m12; - // SINT64 v2 = (SINT64)FPU_STAT.int_reg[st].ul64.m12; - // SINT64 v12 = v1-v2; - // if((v1>=0 && v2>=0) || (v1<=0 && v2<=0)){ // 符号が異なればオーバーフローしない - // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; - // }else if((v1>0 && v2<0) && v12 > 0){ // 正+正→正 多分処理系依存 - // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; - // }else if((v1<0 && v2>0) && v12 < 0){ // 負+負→負 多分処理系依存 - // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; - // }else{ - // FPU_STAT.int_regvalid[st] = 0; - // } - //}else{ - FPU_STAT.int_regvalid[st] = 0; - //} - //flags and such :) - return; -} - -static void FPU_FXCH(UINT st, UINT other){ - FP_TAG tag; - FP_REG reg; - UINT8 regvalid; - FP_INT_REG intreg; - - tag = FPU_STAT.tag[other]; - reg = FPU_STAT.reg[other]; - FPU_STAT.tag[other] = FPU_STAT.tag[st]; - FPU_STAT.reg[other] = FPU_STAT.reg[st]; - FPU_STAT.tag[st] = tag; - FPU_STAT.reg[st] = reg; - regvalid = FPU_STAT.int_regvalid[other]; - intreg = FPU_STAT.int_reg[other]; - FPU_STAT.int_regvalid[other] = FPU_STAT.int_regvalid[st]; - FPU_STAT.int_reg[other] = FPU_STAT.int_reg[st]; - FPU_STAT.int_regvalid[st] = regvalid; - FPU_STAT.int_reg[st] = intreg; -} - -static void FPU_FST(UINT st, UINT other){ - FPU_STAT.tag[other] = FPU_STAT.tag[st]; - FPU_STAT.reg[other] = FPU_STAT.reg[st]; - FPU_STAT.int_regvalid[other] = FPU_STAT.int_regvalid[st]; - FPU_STAT.int_reg[other] = FPU_STAT.int_reg[st]; -} - -static void FPU_FCOM(UINT st, UINT other){ - if(((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || - ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero))){ - FPU_SET_C3(1); - FPU_SET_C2(1); - FPU_SET_C0(1); - return; - } - - if(FPU_STAT.reg[st].d64 == FPU_STAT.reg[other].d64){ - FPU_SET_C3(1); - FPU_SET_C2(0); - FPU_SET_C0(0); - return; - } - if(FPU_STAT.reg[st].d64 < FPU_STAT.reg[other].d64){ - FPU_SET_C3(0); - FPU_SET_C2(0); - FPU_SET_C0(1); - return; - } - // st > other - FPU_SET_C3(0); - FPU_SET_C2(0); - FPU_SET_C0(0); - return; -} -static void FPU_FCOMI(UINT st, UINT other){ - if(((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || - ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero))){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | P_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; - return; - } - - if(FPU_STAT.reg[st].d64 == FPU_STAT.reg[other].d64){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; - return; - } - if(FPU_STAT.reg[st].d64 < FPU_STAT.reg[other].d64){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; - return; - } - // st > other - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; - return; -} - -static void FPU_FUCOM(UINT st, UINT other){ - //does atm the same as fcom - FPU_FCOM(st,other); -} -static void FPU_FUCOMI(UINT st, UINT other){ - //does atm the same as fcomi - FPU_FCOMI(st,other); -} - -static void FPU_FCMOVB(UINT st, UINT other){ - if(CPU_FLAGL & C_FLAG){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; - FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; - } -} -static void FPU_FCMOVE(UINT st, UINT other){ - if(CPU_FLAGL & Z_FLAG){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; - FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; - } -} -static void FPU_FCMOVBE(UINT st, UINT other){ - if(CPU_FLAGL & (C_FLAG|Z_FLAG)){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; - FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; - } -} -static void FPU_FCMOVU(UINT st, UINT other){ - if(CPU_FLAGL & P_FLAG){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; - FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; - } -} - -static void FPU_FCMOVNB(UINT st, UINT other){ - if(!(CPU_FLAGL & C_FLAG)){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; - FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; - } -} -static void FPU_FCMOVNE(UINT st, UINT other){ - if(!(CPU_FLAGL & Z_FLAG)){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; - FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; - } -} -static void FPU_FCMOVNBE(UINT st, UINT other){ - if(!(CPU_FLAGL & (C_FLAG|Z_FLAG))){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; - FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; - } -} -static void FPU_FCMOVNU(UINT st, UINT other){ - if(!(CPU_FLAGL & P_FLAG)){ - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; - FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; - } -} - -static void FPU_FRNDINT(void){ - SINT64 temp; - - temp = (SINT64)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64)); - FPU_STAT.reg[FPU_STAT_TOP].d64=(double)(temp); - if(!FPU_STAT.int_regvalid[FPU_STAT_TOP]){ - FPU_STAT.int_reg[FPU_STAT_TOP].l64.m12 = temp; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 1; - }else{ - // 既に整数 - } -} - -static void FPU_FPREM(void){ - double valtop; - double valdiv; - SINT64 ressaved; - - valtop = FPU_STAT.reg[FPU_STAT_TOP].d64; - valdiv = FPU_STAT.reg[FPU_ST(1)].d64; - ressaved = (SINT64)( (valtop/valdiv) ); -// Some backups -// Real64 res=valtop - ressaved*valdiv; -// res= fmod(valtop,valdiv); - FPU_STAT.reg[FPU_STAT_TOP].d64 = valtop - ressaved*valdiv; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - FPU_SET_C0((UINT)(ressaved&4)); - FPU_SET_C3((UINT)(ressaved&2)); - FPU_SET_C1((UINT)(ressaved&1)); - FPU_SET_C2(0); -} - -static void FPU_FPREM1(void){ - double valtop; - double valdiv, quot, quotf; - SINT64 ressaved; - - valtop = FPU_STAT.reg[FPU_STAT_TOP].d64; - valdiv = FPU_STAT.reg[FPU_ST(1)].d64; - quot = valtop/valdiv; - quotf = floor(quot); - - if (quot-quotf>0.5) ressaved = (SINT64)(quotf+1); - else if (quot-quotf<0.5) ressaved = (SINT64)(quotf); - else ressaved = (SINT64)(((((SINT64)(quotf))&1)!=0)?(quotf+1):(quotf)); - - FPU_STAT.reg[FPU_STAT_TOP].d64 = valtop - ressaved*valdiv; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - FPU_SET_C0((UINT)(ressaved&4)); - FPU_SET_C3((UINT)(ressaved&2)); - FPU_SET_C1((UINT)(ressaved&1)); - FPU_SET_C2(0); -} - -static void FPU_FXAM(void){ - if(FPU_STAT.reg[FPU_STAT_TOP].ll & QWORD_CONST(0x8000000000000000)) //sign - { - FPU_SET_C1(1); - } - else - { - FPU_SET_C1(0); - } - if(FPU_STAT.tag[FPU_STAT_TOP] == TAG_Empty) - { - FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(1); - return; - } - if(FPU_STAT.reg[FPU_STAT_TOP].d64 == 0.0) //zero or normalized number. - { - FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0); - } - else - { - FPU_SET_C3(0);FPU_SET_C2(1);FPU_SET_C0(0); - } -} - -static void FPU_F2XM1(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = pow(2.0,FPU_STAT.reg[FPU_STAT_TOP].d64) - 1; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - return; -} - -static void FPU_FYL2X(void){ - FPU_STAT.reg[FPU_ST(1)].d64*=log(FPU_STAT.reg[FPU_STAT_TOP].d64)/log((double)(2.0)); - FPU_STAT.int_regvalid[FPU_ST(1)] = 0; - FPU_FPOP(); - return; -} - -static void FPU_FYL2XP1(void){ - FPU_STAT.reg[FPU_ST(1)].d64*=log(FPU_STAT.reg[FPU_STAT_TOP].d64+1.0)/log((double)(2.0)); - FPU_STAT.int_regvalid[FPU_ST(1)] = 0; - FPU_FPOP(); - return; -} - -static void FPU_FSCALE(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 *= pow(2.0,(double)((SINT64)(FPU_STAT.reg[FPU_ST(1)].d64))); - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - return; //2^x where x is chopped. -} - -static void FPU_FSTENV(UINT32 addr) -{ - descriptor_t *sdp = &CPU_CS_DESC; - FPU_SET_TOP(FPU_STAT_TOP); - - switch ((CPU_CR0 & 1) | (SEG_IS_32BIT(sdp) ? 0x100 : 0x000)) - { - case 0x000: case 0x001: - fpu_memorywrite_w(addr+0,FPU_CTRLWORD); - fpu_memorywrite_w(addr+2,FPU_STATUSWORD); - fpu_memorywrite_w(addr+4,FPU_GetTag()); - fpu_memorywrite_w(addr+10,FPU_LASTINSTOP); - break; - - case 0x100: case 0x101: - fpu_memorywrite_d(addr+0,(UINT32)(FPU_CTRLWORD)); - fpu_memorywrite_d(addr+4,(UINT32)(FPU_STATUSWORD)); - fpu_memorywrite_d(addr+8,(UINT32)(FPU_GetTag())); - fpu_memorywrite_d(addr+20,FPU_LASTINSTOP); - break; - } -} - -static void FPU_FLDENV(UINT32 addr) -{ - descriptor_t *sdp = &CPU_CS_DESC; - - switch ((CPU_CR0 & 1) | (SEG_IS_32BIT(sdp) ? 0x100 : 0x000)) { - case 0x000: case 0x001: - FPU_SetCW(fpu_memoryread_w(addr+0)); - FPU_STATUSWORD = fpu_memoryread_w(addr+2); - FPU_SetTag(fpu_memoryread_w(addr+4)); - FPU_LASTINSTOP = fpu_memoryread_w(addr+10); - break; - - case 0x100: case 0x101: - FPU_SetCW((UINT16)fpu_memoryread_d(addr+0)); - FPU_STATUSWORD = (UINT16)fpu_memoryread_d(addr+4); - FPU_SetTag((UINT16)fpu_memoryread_d(addr+8)); - FPU_LASTINSTOP = (UINT16)fpu_memoryread_d(addr+20); - break; - } - FPU_STAT_TOP = FPU_GET_TOP(); -} - -static void FPU_FSAVE(UINT32 addr) -{ - UINT start; - UINT i; - - descriptor_t *sdp = &CPU_CS_DESC; - - FPU_FSTENV(addr); - start = ((SEG_IS_32BIT(sdp))?28:14); - for(i = 0;i < 8;i++){ - FPU_ST80(addr+start,FPU_ST(i)); - start += 10; - } - FPU_FINIT(); -} - -static void FPU_FRSTOR(UINT32 addr) -{ - UINT start; - UINT i; - - descriptor_t *sdp = &CPU_CS_DESC; - - FPU_FLDENV(addr); - start = ((SEG_IS_32BIT(sdp))?28:14); - for(i = 0;i < 8;i++){ - FPU_FLD80(addr+start, FPU_ST(i)); - start += 10; - } -} - -static void FPU_FXSAVE(UINT32 addr){ - UINT start; - UINT i; - - descriptor_t *sdp = &CPU_CS_DESC; - - //FPU_FSTENV(addr); - FPU_SET_TOP(FPU_STAT_TOP); - fpu_memorywrite_w(addr+0,FPU_CTRLWORD); - fpu_memorywrite_w(addr+2,FPU_STATUSWORD); - fpu_memorywrite_b(addr+4,FPU_GetTag8()); -#ifdef USE_SSE - fpu_memorywrite_d(addr+24,SSE_MXCSR); -#endif - start = 32; - for(i = 0;i < 8;i++){ - //FPU_ST80(addr+start,FPU_ST(i)); - fpu_memorywrite_d(addr+start+0,FPU_STAT.reg[FPU_ST(i)].l.lower); - fpu_memorywrite_d(addr+start+4,FPU_STAT.reg[FPU_ST(i)].l.upper); - if(FPU_STAT.int_regvalid[FPU_ST(i)]){ - fpu_memorywrite_d(addr+start+8,FPU_STAT.int_reg[FPU_ST(i)].ul32.m1); - fpu_memorywrite_d(addr+start+12,FPU_STAT.int_reg[FPU_ST(i)].ul32.m2); - }else{ - fpu_memorywrite_d(addr+start+8,0x00000000); - fpu_memorywrite_d(addr+start+12,0x00000000); - } - start += 16; - } -#ifdef USE_SSE - start = 160; - for(i = 0;i < 8;i++){ - fpu_memorywrite_q(addr+start+0,SSE_XMMREG(i).ul64[0]); - fpu_memorywrite_q(addr+start+8,SSE_XMMREG(i).ul64[1]); - start += 16; - } -#endif -} -static void FPU_FXRSTOR(UINT32 addr){ - UINT start; - UINT i; - - descriptor_t *sdp = &CPU_CS_DESC; - - //FPU_FLDENV(addr); - FPU_SetCW(fpu_memoryread_w(addr+0)); - FPU_STATUSWORD = fpu_memoryread_w(addr+2); - FPU_SetTag8(fpu_memoryread_b(addr+4)); - FPU_STAT_TOP = FPU_GET_TOP(); -#ifdef USE_SSE - SSE_MXCSR = fpu_memoryread_d(addr+24); -#endif - start = 32; - for(i = 0;i < 8;i++){ - //FPU_STAT.reg[FPU_ST(i)].d64 = FPU_FLD80(addr+start); - FPU_STAT.reg[FPU_ST(i)].l.lower = fpu_memoryread_d(addr+start+0); - FPU_STAT.reg[FPU_ST(i)].l.upper = fpu_memoryread_d(addr+start+4); - FPU_STAT.int_reg[FPU_ST(i)].ul32.m1 = fpu_memoryread_d(addr+start+8); - FPU_STAT.int_reg[FPU_ST(i)].ul32.m2 = fpu_memoryread_d(addr+start+12); - if(FPU_STAT.int_reg[FPU_ST(i)].ul64.m12){ - FPU_STAT.int_regvalid[FPU_ST(i)] = 1; - }else{ - FPU_STAT.int_regvalid[FPU_ST(i)] = 0; - } - start += 16; - } -#ifdef USE_SSE - start = 160; - for(i = 0;i < 8;i++){ - SSE_XMMREG(i).ul64[0] = fpu_memoryread_q(addr+start+0); - SSE_XMMREG(i).ul64[1] = fpu_memoryread_q(addr+start+8); - start += 16; - } -#endif -} - -void DB2_FPU_FXSAVERSTOR(void){ - UINT32 op; - UINT idx, sub; - UINT32 maddr; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - switch(idx){ - case 0: // FXSAVE - fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し - maddr = calc_ea_dst(op); - FPU_FXSAVE(maddr); - break; - case 1: // FXRSTOR - fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し - maddr = calc_ea_dst(op); - FPU_FXRSTOR(maddr); - break; -#ifdef USE_SSE - case 2: // LDMXCSR - maddr = calc_ea_dst(op); - SSE_LDMXCSR(maddr); - break; - case 3: // STMXCSR - maddr = calc_ea_dst(op); - SSE_STMXCSR(maddr); - break; - case 4: // SFENCE - SSE_SFENCE(); - break; - case 5: // LFENCE - SSE_LFENCE(); - break; - case 6: // MFENCE - SSE_MFENCE(); - break; - case 7: // CLFLUSH; - SSE_CLFLUSH(op); - break; -#endif - default: - ia32_panic("invalid opcode = %02x\n", op); - break; - } -} - -static void FPU_FXTRACT(void) { - // function stores real bias in st and - // pushes the significant number onto the stack - // if double ever uses a different base please correct this function - FP_REG test; - SINT64 exp80, exp80final; - double mant; - - test = FPU_STAT.reg[FPU_STAT_TOP]; - exp80 = test.ll&QWORD_CONST(0x7ff0000000000000); - exp80final = (exp80>>52) - BIAS64; - mant = test.d64 / (pow(2.0,(double)(exp80final))); - FPU_STAT.reg[FPU_STAT_TOP].d64 = (double)(exp80final); - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - FPU_PUSH(mant); -} - -static void FPU_FCHS(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = -1.0*(FPU_STAT.reg[FPU_STAT_TOP].d64); - if(FPU_STAT.int_regvalid[FPU_STAT_TOP]){ - if(FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12 != QWORD_CONST(0x8000000000000000)){ - FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12 = (~FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12) + 1; // 符号反転 - }else{ - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - } - } -} - -static void FPU_FABS(void){ - FPU_STAT.reg[FPU_STAT_TOP].d64 = fabs(FPU_STAT.reg[FPU_STAT_TOP].d64); - if(FPU_STAT.int_regvalid[FPU_STAT_TOP]){ - if((QWORD_CONST(0x8000000000000000) & FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12)!=0 && - (FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12 != QWORD_CONST(0x8000000000000000))){ - FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12 = (~FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12) + 1; // 符号反転 - }else{ - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; - } - } -} - -static void FPU_FTST(void){ - FPU_STAT.reg[8].d64 = 0.0; - FPU_FCOM(FPU_STAT_TOP,8); -} - -static void FPU_FLD1(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = 1.0; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; -} - -static void FPU_FLDL2T(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = L2T; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; -} - -static void FPU_FLDL2E(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = L2E; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; -} - -static void FPU_FLDPI(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = PI; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; -} - -static void FPU_FLDLG2(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = LG2; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; -} - -static void FPU_FLDLN2(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = LN2; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; -} - -static void FPU_FLDZ(void){ - FPU_PREP_PUSH(); - FPU_STAT.reg[FPU_STAT_TOP].d64 = 0.0; - FPU_STAT.tag[FPU_STAT_TOP] = TAG_Zero; - FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12 = 0; - FPU_STAT.int_regvalid[FPU_STAT_TOP] = 1; -} - - -static INLINE void FPU_FADD_EA(UINT op1){ - FPU_FADD(op1,8); -} -static INLINE void FPU_FMUL_EA(UINT op1){ - FPU_FMUL(op1,8); -} -static INLINE void FPU_FSUB_EA(UINT op1){ - FPU_FSUB(op1,8); -} -static INLINE void FPU_FSUBR_EA(UINT op1){ - FPU_FSUBR(op1,8); -} -static INLINE void FPU_FDIV_EA(UINT op1){ - FPU_FDIV(op1,8); -} -static INLINE void FPU_FDIVR_EA(UINT op1){ - FPU_FDIVR(op1,8); -} -static INLINE void FPU_FCOM_EA(UINT op1){ - FPU_FCOM(op1,8); -} - -/* - * FPU interface - */ -//int fpu_updateEmuEnv(void); -static void -FPU_FINIT(void) -{ - int i; - FPU_SetCW(0x37F); - FPU_STATUSWORD = 0; - FPU_STAT_TOP=FPU_GET_TOP(); - for(i=0;i<8;i++){ - FPU_STAT.tag[i] = TAG_Empty; - FPU_STAT.int_regvalid[i] = 0; - // レジスタの内容は消してはいけない ver0.86 rev40 - //FPU_STAT.reg[i].d64 = 0; - //FPU_STAT.reg[i].l.lower = 0; - //FPU_STAT.reg[i].l.upper = 0; - //FPU_STAT.reg[i].ll = 0; - } - FPU_STAT.tag[8] = TAG_Valid; // is only used by us -} -void DB2_FPU_FINIT(void){ - int i; - FPU_FINIT(); - for(i=0;i<8;i++){ - FPU_STAT.tag[i] = TAG_Empty; - FPU_STAT.reg[i].l.ext = 0; - FPU_STAT.reg[i].l.lower = 0; - FPU_STAT.reg[i].l.upper = 0; - } -} - -//char * -//fpu_reg2str(void) -//{ -// return NULL; -//} - - -/* - * FPU instruction - */ - -static void fpu_checkexception(){ - if((FPU_STATUSWORD & ~FPU_CTRLWORD) & 0x3F){ - EXCEPTION(MF_EXCEPTION, 0); - } -} - -static void EA_TREE(UINT op) -{ - UINT idx; - - idx = (op >> 3) & 7; - - switch (idx) { - case 0: /* FADD (単精度実数) */ - TRACEOUT(("FADD EA")); - FPU_FADD_EA(FPU_STAT_TOP); - break; - case 1: /* FMUL (単精度実数) */ - TRACEOUT(("FMUL EA")); - FPU_FMUL_EA(FPU_STAT_TOP); - break; - case 2: /* FCOM (単精度実数) */ - TRACEOUT(("FCOM EA")); - FPU_FCOM_EA(FPU_STAT_TOP); - break; - case 3: /* FCOMP (単精度実数) */ - TRACEOUT(("FCOMP EA")); - FPU_FCOM_EA(FPU_STAT_TOP); - FPU_FPOP(); - break; - case 4: /* FSUB (単精度実数) */ - TRACEOUT(("FSUB EA")); - FPU_FSUB_EA(FPU_STAT_TOP); - break; - case 5: /* FSUBR (単精度実数) */ - TRACEOUT(("FSUBR EA")); - FPU_FSUBR_EA(FPU_STAT_TOP); - break; - case 6: /* FDIV (単精度実数) */ - TRACEOUT(("FDIV EA")); - FPU_FDIV_EA(FPU_STAT_TOP); - break; - case 7: /* FDIVR (単精度実数) */ - TRACEOUT(("FDIVR EA")); - FPU_FDIVR_EA(FPU_STAT_TOP); - break; - default: - break; - } -} - -// d8 -void -DB2_ESC0(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU d8 %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FADD */ - TRACEOUT(("FADD")); - FPU_FADD(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 1: /* FMUL */ - TRACEOUT(("FMUL")); - FPU_FMUL(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FCOM */ - TRACEOUT(("FCOM")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCOMP */ - TRACEOUT(("FCOMP")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - case 4: /* FSUB */ - TRACEOUT(("FSUB")); - FPU_FSUB(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 5: /* FSUBR */ - TRACEOUT(("FSUBR")); - FPU_FSUBR(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 6: /* FDIV */ - TRACEOUT(("FDIV")); - FPU_FDIV(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 7: /* FDIVR */ - TRACEOUT(("FDIVR")); - FPU_FDIVR(FPU_STAT_TOP,FPU_ST(sub)); - break; - } - } else { - madr = calc_ea_dst(op); - FPU_FLD_F32_EA(madr); - EA_TREE(op); - } -} - -// d9 -void -DB2_ESC1(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU d9 %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - if(!(op < 0xc0 && idx>=4)){ - fpu_checkexception(); - } - if (op >= 0xc0) - { - switch (idx) { - case 0: /* FLD ST(0), ST(i) */ - { - UINT reg_from; - - TRACEOUT(("FLD STi")); - reg_from = FPU_ST(sub); - FPU_PREP_PUSH(); - FPU_FST(reg_from, FPU_STAT_TOP); - } - break; - - case 1: /* FXCH ST(0), ST(i) */ - TRACEOUT(("FXCH STi")); - FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); - break; - - case 2: /* FNOP */ - TRACEOUT(("FNOP")); - FPU_FNOP(); - break; - - case 3: /* FSTP STi */ - TRACEOUT(("FSTP STi")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - - case 4: - switch (sub) { - case 0x0: /* FCHS */ - TRACEOUT(("FCHS")); - FPU_FCHS(); - break; - - case 0x1: /* FABS */ - TRACEOUT(("FABS")); - FPU_FABS(); - break; - - case 0x2: /* UNKNOWN */ - case 0x3: /* ILLEGAL */ - break; - - case 0x4: /* FTST */ - TRACEOUT(("FTST")); - FPU_FTST(); - break; - - case 0x5: /* FXAM */ - TRACEOUT(("FXAM")); - FPU_FXAM(); - break; - - case 0x06: /* FTSTP (cyrix)*/ - case 0x07: /* UNKNOWN */ - break; - } - break; - - case 5: - switch (sub) { - case 0x0: /* FLD1 */ - TRACEOUT(("FLD1")); - FPU_FLD1(); - break; - - case 0x1: /* FLDL2T */ - TRACEOUT(("FLDL2T")); - FPU_FLDL2T(); - break; - - case 0x2: /* FLDL2E */ - TRACEOUT(("FLDL2E")); - FPU_FLDL2E(); - break; - - case 0x3: /* FLDPI */ - TRACEOUT(("FLDPI")); - FPU_FLDPI(); - break; - - case 0x4: /* FLDLG2 */ - TRACEOUT(("FLDLG2")); - FPU_FLDLG2(); - break; - - case 0x5: /* FLDLN2 */ - TRACEOUT(("FLDLN2")); - FPU_FLDLN2(); - break; - - case 0x6: /* FLDZ */ - TRACEOUT(("FLDZ")); - FPU_FLDZ(); - break; - - case 0x07: /* ILLEGAL */ - break; - } - break; - - case 6: - switch (sub) { - case 0x0: /* F2XM1 */ - TRACEOUT(("F2XM1")); - FPU_F2XM1(); - break; - - case 0x1: /* FYL2X */ - TRACEOUT(("FYL2X")); - FPU_FYL2X(); - break; - - case 0x2: /* FPTAN */ - TRACEOUT(("FPTAN")); - FPU_FPTAN(); - break; - - case 0x3: /* FPATAN */ - TRACEOUT(("FPATAN")); - FPU_FPATAN(); - break; - - case 0x4: /* FXTRACT */ - TRACEOUT(("FXTRACT")); - FPU_FXTRACT(); - break; - - case 0x5: /* FPREM1 */ - TRACEOUT(("FPREM1")); - FPU_FPREM1(); - break; - - case 0x6: /* FDECSTP */ - TRACEOUT(("FDECSTP")); - FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; - break; - - case 0x7: /* FINCSTP */ - TRACEOUT(("FINCSTP")); - FPU_STAT_TOP = (FPU_STAT_TOP + 1) & 7; - break; - } - break; - - case 7: - switch (sub) { - case 0x0: /* FPREM */ - TRACEOUT(("FPREM")); - FPU_FPREM(); - break; - - case 0x1: /* FYL2XP1 */ - TRACEOUT(("FYL2XP1")); - FPU_FYL2XP1(); - break; - - case 0x2: /* FSQRT */ - TRACEOUT(("FSQRT")); - FPU_FSQRT(); - break; - - case 0x3: /* FSINCOS */ - TRACEOUT(("FSINCOS")); - FPU_FSINCOS(); - break; - - case 0x4: /* FRNDINT */ - TRACEOUT(("FRNDINT")); - FPU_FRNDINT(); - break; - - case 0x5: /* FSCALE */ - TRACEOUT(("FSCALE")); - FPU_FSCALE(); - break; - - case 0x6: /* FSIN */ - TRACEOUT(("FSIN")); - FPU_FSIN(); - break; - - case 0x7: /* FCOS */ - TRACEOUT(("FCOS")); - FPU_FCOS(); - break; - } - break; - - default: - ia32_panic("ESC1: invalid opcode = %02x\n", op); - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FLD (単精度実数) */ - TRACEOUT(("FLD float")); - FPU_PREP_PUSH(); - FPU_FLD_F32(madr,FPU_STAT_TOP); - break; - - case 1: /* UNKNOWN */ - break; - - case 2: /* FST (単精度実数) */ - TRACEOUT(("FST float")); - FPU_FST_F32(madr); - break; - - case 3: /* FSTP (単精度実数) */ - TRACEOUT(("FSTP float")); - FPU_FST_F32(madr); - FPU_FPOP(); - break; - - case 4: /* FLDENV */ - TRACEOUT(("FLDENV")); - FPU_FLDENV(madr); - break; - - case 5: /* FLDCW */ - TRACEOUT(("FLDCW")); - FPU_FLDCW(madr); - break; - - case 6: /* FSTENV */ - TRACEOUT(("FSTENV")); - FPU_FSTENV(madr); - break; - - case 7: /* FSTCW */ - TRACEOUT(("FSTCW/FNSTCW")); - fpu_memorywrite_w(madr,FPU_CTRLWORD); - break; - - default: - break; - } - } -} - -// da -void -DB2_ESC2(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU da %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FCMOVB */ - TRACEOUT(("ESC2: FCMOVB")); - FPU_FCMOVB(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 1: /* FCMOVE */ - TRACEOUT(("ESC2: FCMOVE")); - FPU_FCMOVE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FCMOVBE */ - TRACEOUT(("ESC2: FCMOVBE")); - FPU_FCMOVBE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCMOVU */ - TRACEOUT(("ESC2: FCMOVU")); - FPU_FCMOVU(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 5: - switch (sub) { - case 1: /* FUCOMPP */ - TRACEOUT(("FUCOMPP")); - FPU_FUCOM(FPU_STAT_TOP,FPU_ST(1)); - FPU_FPOP(); - FPU_FPOP(); - break; - - default: - break; - } - break; - - default: - break; - } - } else { - madr = calc_ea_dst(op); - FPU_FLD_I32_EA(madr); - EA_TREE(op); - } -} - -// db -void -DB2_ESC3(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU db %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - if(!(op >= 0xc0 && idx==4)){ - fpu_checkexception(); - } - if (op >= 0xc0) - { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FCMOVNB */ - TRACEOUT(("ESC3: FCMOVNB")); - FPU_FCMOVNB(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 1: /* FCMOVNE */ - TRACEOUT(("ESC3: FCMOVNE")); - FPU_FCMOVNE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FCMOVNBE */ - TRACEOUT(("ESC3: FCMOVNBE")); - FPU_FCMOVNBE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCMOVNU */ - TRACEOUT(("ESC3: FCMOVNU")); - FPU_FCMOVNU(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 4: - switch (sub) { - case 0: /* FNENI */ - case 1: /* FNDIS */ - break; - - case 2: /* FCLEX */ - TRACEOUT(("FCLEX")); - FPU_FCLEX(); - break; - - case 3: /* FNINIT/FINIT */ - TRACEOUT(("FNINIT/FINIT")); - FPU_FINIT(); - break; - - case 4: /* FNSETPM */ - case 5: /* FRSTPM */ - FPU_FNOP(); - break; - - default: - break; - } - break; - case 5: /* FUCOMI */ - TRACEOUT(("ESC3: FUCOMI")); - FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 6: /* FCOMI */ - TRACEOUT(("ESC3: FCOMI")); - FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); - break; - default: - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FILD (DWORD) */ - TRACEOUT(("FILD")); - FPU_PREP_PUSH(); - FPU_FLD_I32(madr,FPU_STAT_TOP); - break; - - case 1: /* FISTTP (DWORD) */ - { - FP_RND oldrnd = FPU_STAT.round; - FPU_STAT.round = ROUND_Down; - FPU_FST_I32(madr); - FPU_STAT.round = oldrnd; - } - FPU_FPOP(); - break; - - case 2: /* FIST (DWORD) */ - TRACEOUT(("FIST")); - FPU_FST_I32(madr); - break; - - case 3: /* FISTP (DWORD) */ - TRACEOUT(("FISTP")); - FPU_FST_I32(madr); - FPU_FPOP(); - break; - - case 5: /* FLD (拡張実数) */ - TRACEOUT(("FLD 80 Bits Real")); - FPU_PREP_PUSH(); - FPU_FLD_F80(madr); - break; - - case 7: /* FSTP (拡張実数) */ - TRACEOUT(("FSTP 80 Bits Real")); - FPU_FST_F80(madr); - FPU_FPOP(); - break; - - default: - break; - } - } -} - -// dc -void -DB2_ESC4(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU dc %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(i), ST(0) */ - switch (idx) { - case 0: /* FADD */ - TRACEOUT(("ESC4: FADD")); - FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); - break; - case 1: /* FMUL */ - TRACEOUT(("ESC4: FMUL")); - FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); - break; - case 2: /* FCOM */ - TRACEOUT(("ESC4: FCOM")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCOMP */ - TRACEOUT(("ESC4: FCOMP")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - case 4: /* FSUBR */ - TRACEOUT(("ESC4: FSUBR")); - FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); - break; - case 5: /* FSUB */ - TRACEOUT(("ESC4: FSUB")); - FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); - break; - case 6: /* FDIVR */ - TRACEOUT(("ESC4: FDIVR")); - FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); - break; - case 7: /* FDIV */ - TRACEOUT(("ESC4: FDIV")); - FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); - break; - default: - break; - } - } else { - madr = calc_ea_dst(op); - FPU_FLD_F64_EA(madr); - EA_TREE(op); - } -} - -// dd -void -DB2_ESC5(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU dd %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - fpu_check_NM_EXCEPTION(); - //if(op < 0xc0 && (idx==6 || idx==4)){ - // _ADD_EIP(-1); // XXX: 無理やり戻す - // fpu_check_NM_EXCEPTION2(); - // _ADD_EIP(1); - //}else{ - // _ADD_EIP(-1); // XXX: 無理やり戻す - // fpu_check_NM_EXCEPTION(); - // _ADD_EIP(1); - //} - if(op >= 0xc0 || (idx!=4 && idx!=6 && idx!=7)){ - fpu_checkexception(); - } - if (op >= 0xc0) { - /* FUCOM ST(i), ST(0) */ - /* Fxxx ST(i) */ - switch (idx) { - case 0: /* FFREE */ - TRACEOUT(("FFREE")); - FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; - break; - case 1: /* FXCH */ - TRACEOUT(("FXCH")); - FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FST */ - TRACEOUT(("FST")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FSTP */ - TRACEOUT(("FSTP")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - case 4: /* FUCOM */ - TRACEOUT(("FUCOM")); - FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 5: /* FUCOMP */ - TRACEOUT(("FUCOMP")); - FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - - default: - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FLD (倍精度実数) */ - TRACEOUT(("FLD double real")); - FPU_PREP_PUSH(); - FPU_FLD_F64(madr,FPU_STAT_TOP); - break; - case 1: /* FISTTP (QWORD) */ - { - FP_RND oldrnd = FPU_STAT.round; - FPU_STAT.round = ROUND_Down; - FPU_FST_I64(madr); - FPU_STAT.round = oldrnd; - } - FPU_FPOP(); - break; - case 2: /* FST (倍精度実数) */ - TRACEOUT(("FST double real")); - FPU_FST_F64(madr); - break; - case 3: /* FSTP (倍精度実数) */ - TRACEOUT(("FSTP double real")); - FPU_FST_F64(madr); - FPU_FPOP(); - break; - case 4: /* FRSTOR */ - TRACEOUT(("FRSTOR")); - FPU_FRSTOR(madr); - break; - case 6: /* FSAVE */ - TRACEOUT(("FSAVE")); - FPU_FSAVE(madr); - break; - - case 7: /* FSTSW */ - FPU_SET_TOP(FPU_STAT_TOP); - //cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, FPU_CTRLWORD); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, FPU_STATUSWORD); - break; - - default: - break; - } - } -} - -// de -void -DB2_ESC6(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU de %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(i), ST(0) */ - switch (idx) { - case 0: /* FADDP */ - TRACEOUT(("FADDP")); - FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); - break; - case 1: /* FMULP */ - TRACEOUT(("FMULP")); - FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); - break; - case 2: /* FCOMP5 */ - TRACEOUT(("FCOMP5")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCOMPP */ - TRACEOUT(("FCOMPP")); - if(sub != 1) { - return; - } - FPU_FCOM(FPU_STAT_TOP,FPU_ST(1)); - FPU_FPOP(); /* extra pop at the bottom*/ - break; - case 4: /* FSUBRP */ - TRACEOUT(("FSUBRP")); - FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); - break; - case 5: /* FSUBP */ - TRACEOUT(("FSUBP")); - FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); - break; - case 6: /* FDIVRP */ - TRACEOUT(("FDIVRP")); - FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); - if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ - return; // POPしないようにする - } - break; - case 7: /* FDIVP */ - TRACEOUT(("FDIVP")); - FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); - if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ - return; // POPしないようにする - } - break; - /*FALLTHROUGH*/ - default: - break; - } - FPU_FPOP(); - } else { - madr = calc_ea_dst(op); - FPU_FLD_I16_EA(madr); - EA_TREE(op); - } -} - -// df -void -DB2_ESC7(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU df %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - if(!(op >= 0xc0 && idx==4 && sub==0)){ - fpu_checkexception(); - } - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FFREEP */ - TRACEOUT(("FFREEP")); - FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; - FPU_FPOP(); - break; - case 1: /* FXCH */ - TRACEOUT(("FXCH")); - FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); - break; - - case 2: - case 3: /* FSTP */ - TRACEOUT(("FSTP")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - - case 4: - switch (sub) - { - case 0: /* FSTSW AX */ - TRACEOUT(("FSTSW AX")); - FPU_SET_TOP(FPU_STAT_TOP); - CPU_AX = FPU_STATUSWORD; - break; - - default: - break; - } - break; - case 5: /* FUCOMIP */ - TRACEOUT(("ESC7: FUCOMIP")); - FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - case 6: /* FCOMIP */ - TRACEOUT(("ESC7: FCOMIP")); - FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); - FPU_FPOP(); - break; - default: - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FILD (WORD) */ - TRACEOUT(("FILD SINT16")); - FPU_PREP_PUSH(); - FPU_FLD_I16(madr,FPU_STAT_TOP); - break; - case 1: /* FISTTP (WORD) */ - { - FP_RND oldrnd = FPU_STAT.round; - FPU_STAT.round = ROUND_Down; - FPU_FST_I16(madr); - FPU_STAT.round = oldrnd; - } - FPU_FPOP(); - break; - case 2: /* FIST (WORD) */ - TRACEOUT(("FIST SINT16")); - FPU_FST_I16(madr); - break; - case 3: /* FISTP (WORD) */ - TRACEOUT(("FISTP SINT16")); - FPU_FST_I16(madr); - FPU_FPOP(); - break; - - case 4: /* FBLD (BCD) */ - TRACEOUT(("FBLD packed BCD")); - FPU_PREP_PUSH(); - FPU_FBLD(madr,FPU_STAT_TOP); - break; - - case 5: /* FILD (QWORD) */ - TRACEOUT(("FILD SINT64")); - FPU_PREP_PUSH(); - FPU_FLD_I64(madr,FPU_STAT_TOP); - break; - - case 6: /* FBSTP (BCD) */ - TRACEOUT(("FBSTP packed BCD")); - FPU_FBST(madr); - FPU_FPOP(); - break; - - case 7: /* FISTP (QWORD) */ - TRACEOUT(("FISTP SINT64")); - FPU_FST_I64(madr); - FPU_FPOP(); - break; - - default: - break; - } - } -} -#endif +/* + * Copyright (C) 2002-2015 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Copyright (c) 2012 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +/* + * modified by SimK + * 整数値のロード・ストア限定で拡張倍精度浮動小数点相当の精度があります + */ + +#include + +#if defined(USE_FPU) && defined(SUPPORT_FPU_DOSBOX2) + +#include +#include +#include +#include "ia32/ia32.mcr" + +#include +#include "ia32/instructions/fpu/fpumem.h" +#ifdef USE_SSE +#include "ia32/instructions/sse/sse.h" +#endif + +#if 1 +#undef TRACEOUT +#define TRACEOUT(s) (void)(s) +#endif /* 0 */ + +#define FPU_WORKCLOCK 6 + +#define PI 3.14159265358979323846 +#define L2E 1.4426950408889634 +#define L2T 3.3219280948873623 +#define LN2 0.69314718055994531 +#define LG2 0.3010299956639812 + +static void FPU_FINIT(void); + +static void +fpu_check_NM_EXCEPTION(){ + // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる + if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { + EXCEPTION(NM_EXCEPTION, 0); + } +} +static void +fpu_check_NM_EXCEPTION2(){ + // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる + if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { + EXCEPTION(NM_EXCEPTION, 0); + } +} + +static const FPU_PTR zero_ptr = { 0, 0, 0 }; + +/* + * FPU interface + */ + +static INLINE UINT FPU_GET_TOP(void) { + return (FPU_STATUSWORD & 0x3800)>>11; +} + +static INLINE void FPU_SET_TOP(UINT val){ + FPU_STATUSWORD &= ~0x3800; + FPU_STATUSWORD |= (val&7)<<11; +} + + +static INLINE void FPU_SET_C0(UINT C){ + FPU_STATUSWORD &= ~0x0100; + if(C) FPU_STATUSWORD |= 0x0100; +} + +static INLINE void FPU_SET_C1(UINT C){ + FPU_STATUSWORD &= ~0x0200; + if(C) FPU_STATUSWORD |= 0x0200; +} + +static INLINE void FPU_SET_C2(UINT C){ + FPU_STATUSWORD &= ~0x0400; + if(C) FPU_STATUSWORD |= 0x0400; +} + +static INLINE void FPU_SET_C3(UINT C){ + FPU_STATUSWORD &= ~0x4000; + if(C) FPU_STATUSWORD |= 0x4000; +} + +static INLINE void FPU_SET_D(UINT C){ + FPU_STATUSWORD &= ~0x0002; + if(C) FPU_STATUSWORD |= 0x0002; +} + +static INLINE void FPU_SetCW(UINT16 cword) +{ + // HACK: Bits 13-15 are not defined. Apparently, one program likes to test for + // Cyrix EMC87 by trying to set bit 15. We want the test program to see + // us as an Intel 287 when cputype == 286. + cword &= 0x7FFF; + FPU_CTRLWORD = cword; + FPU_STAT.round = (FP_RND)((cword >> 10) & 3); +} + +static void FPU_FLDCW(UINT32 addr) +{ + UINT16 temp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, addr); + FPU_SetCW(temp); +} + +static UINT16 FPU_GetTag(void) +{ + UINT i; + + UINT16 tag=0; + for(i=0;i<8;i++) + tag |= ( (FPU_STAT.tag[i]&3) <<(2*i)); + return tag; +} +static UINT8 FPU_GetTag8(void) +{ + UINT i; + + UINT8 tag=0; + for(i=0;i<8;i++) + tag |= ( (FPU_STAT.tag[i]==TAG_Empty ? 0 : 1) <<(i)); + return tag; +} + +static INLINE void FPU_SetTag(UINT16 tag) +{ + UINT i; + + for(i=0;i<8;i++){ + FPU_STAT.tag[i] = (FP_TAG)((tag >>(2*i))&3); + + } +} +static INLINE void FPU_SetTag8(UINT8 tag) +{ + UINT i; + + for(i=0;i<8;i++){ + FPU_STAT.tag[i] = (((tag>>i)&1) == 0 ? TAG_Empty : TAG_Valid); + } +} + +static void FPU_FCLEX(void){ + //FPU_STATUSWORD &= 0xff00; //should clear exceptions + FPU_STATUSWORD &= 0x7f00; //should clear exceptions? +} + +static void FPU_FNOP(void){ + return; +} + +static void FPU_PUSH(double in){ + FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; + //actually check if empty + FPU_STAT.tag[FPU_STAT_TOP] = TAG_Valid; + FPU_STAT.reg[FPU_STAT_TOP].d64 = in; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; +// LOG(LOG_FPU,LOG_ERROR)("Pushed at %d %g to the stack",newtop,in); + return; +} + +static void FPU_PREP_PUSH(void){ + FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; + FPU_STAT.tag[FPU_STAT_TOP] = TAG_Valid; +} + +static void FPU_FPOP(void){ + FPU_STAT.tag[FPU_STAT_TOP] = TAG_Empty; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + //maybe set zero in it as well + FPU_STAT_TOP = ((FPU_STAT_TOP+1)&7); +// LOG(LOG_FPU,LOG_ERROR)("popped from %d %g off the stack",top,fpu.regs[top].d64); + return; +} + +static double FROUND(double in){ + switch(FPU_STAT.round){ + case ROUND_Nearest: + if (in-floor(in)>0.5) return (floor(in)+1); + else if (in-floor(in)<0.5) return (floor(in)); + else return ((((SINT64)(floor(in)))&1)!=0)?(floor(in)+1):(floor(in)); + break; + case ROUND_Down: + return (floor(in)); + break; + case ROUND_Up: + return (ceil(in)); + break; + case ROUND_Chop: + return in; //the cast afterwards will do it right maybe cast here + break; + default: + return in; + break; + } +} + +#define BIAS80 16383 +#define BIAS64 1023 + +static void FPU_FLD80(UINT32 addr, UINT reg) +{ + FP_REG result; + SINT64 exp64, exp64final; + SINT64 blah; + SINT64 mant64; + SINT64 sign; + + struct { + SINT16 begin; + FP_REG eind; + } test; + + test.eind.l.lower = fpu_memoryread_d(addr); + test.eind.l.upper = fpu_memoryread_d(addr+4); + test.begin = fpu_memoryread_w(addr+8); + + exp64 = (((test.begin&0x7fff) - BIAS80)); + blah = ((exp64 >0)?exp64:-exp64)&0x3ff; + exp64final = ((exp64 >0)?blah:-blah) +BIAS64; + + mant64 = (test.eind.ll >> 11) & QWORD_CONST(0xfffffffffffff); + sign = (test.begin&0x8000)?1:0; + result.ll = (sign <<63)|(exp64final << 52)| mant64; + + { + UINT64 tmp; + unsigned int shift; + shift = (unsigned int)(63-exp64); + // 1.xxxを64bit整数表現できるかチェック + if(exp64 >= 0 && // 1未満なったらアウト + exp64 <= 63 && // 値が64bit整数で表現できない場合もアウト(とりあえず符号無しで判定) + ((test.eind.ll >> shift) << shift)==test.eind.ll){ // 小数点以下の数がある場合もアウト + //tmp = ((((UINT64)test.eind.ll) >> 1) | QWORD_CONST(0x8000000000000000)) >> shift; + tmp = ((UINT64)test.eind.ll) >> shift; + if(sign==0 && tmp < QWORD_CONST(0x8000000000000000)){ // 符号付き(正)で表現できるか + FPU_STAT.int_reg[reg].ul64.m12 = tmp; + FPU_STAT.int_regvalid[reg] = 1; + }else if(sign==1 && tmp <= QWORD_CONST(0x8000000000000000)){ // 符号付き(負)で表現できるか + FPU_STAT.int_reg[reg].ul64.m12 = ((~tmp) + 1); + FPU_STAT.int_regvalid[reg] = 1; + }else{ + FPU_STAT.int_regvalid[reg] = 0; + } + }else if((test.begin&0x7fff) == 0 && test.eind.ll == 0){ // 0の場合 + FPU_STAT.int_reg[reg].ul64.m12 = 0; + FPU_STAT.int_regvalid[reg] = 1; + }else{ + FPU_STAT.int_regvalid[reg] = 0; + } + } + + if(test.eind.l.lower == 0 && (UINT32)test.eind.l.upper == (UINT32)0x80000000UL && (test.begin&0x7fff) == 0x7fff) { + //Detect INF and -INF (score 3.11 when drawing a slur.) + result.d64 = sign?-HUGE_VAL:HUGE_VAL; + } + FPU_STAT.reg[reg].d64 = result.d64; + //return result.d64; + + //mant64= test.mant80/2***64 * 2 **53 +} + +static void FPU_ST80(UINT32 addr,UINT reg) +{ + SINT64 sign80; + SINT64 exp80, exp80final; + SINT64 mant80, mant80final; + + struct { + SINT16 begin; + FP_REG eind; + } test; + + sign80 = (FPU_STAT.reg[reg].ll&QWORD_CONST(0x8000000000000000))?1:0; + exp80 = FPU_STAT.reg[reg].ll&QWORD_CONST(0x7ff0000000000000); + exp80final = (exp80>>52); + mant80 = FPU_STAT.reg[reg].ll&QWORD_CONST(0x000fffffffffffff); + mant80final = (mant80 << 11); + if(FPU_STAT.reg[reg].d64 != 0){ //Zero is a special case + // Elvira wants the 8 and tcalc doesn't + mant80final |= QWORD_CONST(0x8000000000000000); + //Ca-cyber doesn't like this when result is zero. + exp80final += (BIAS80 - BIAS64); + } + test.begin = ((SINT16)(sign80)<<15)| (SINT16)(exp80final); + test.eind.ll = mant80final; + if(FPU_STAT.int_regvalid[reg] && FPU_STAT.int_reg[reg].ul64.m12!=0){ + UINT64 tmp; + if((SINT64)FPU_STAT.int_reg[reg].ul64.m12 < 0){ + sign80 = 1; + tmp = (~(FPU_STAT.int_reg[reg].ul64.m12)) + 1; + }else{ + sign80 = 0; + tmp = FPU_STAT.int_reg[reg].ul64.m12; + } + exp80final = BIAS80 + 63; + while(!(tmp & QWORD_CONST(0x8000000000000000))){ + tmp = tmp << 1; + exp80final--; + } + test.begin = ((SINT16)(sign80)<<15)| (SINT16)(exp80final); + test.eind.ll = tmp; + } + fpu_memorywrite_d(addr,test.eind.l.lower); + fpu_memorywrite_d(addr+4,test.eind.l.upper); + fpu_memorywrite_w(addr+8,test.begin); +} + + +static void FPU_FLD_F32(UINT32 addr,UINT store_to) { + union { + float f; + UINT32 l; + } blah; + + blah.l = fpu_memoryread_d(addr); + FPU_STAT.reg[store_to].d64 = (double)(blah.f); + FPU_STAT.int_regvalid[store_to] = 0; +} + +static void FPU_FLD_F64(UINT32 addr,UINT store_to) { + FPU_STAT.reg[store_to].l.lower = fpu_memoryread_d(addr); + FPU_STAT.reg[store_to].l.upper = fpu_memoryread_d(addr+4); + FPU_STAT.int_regvalid[store_to] = 0; +} + +static void FPU_FLD_F80(UINT32 addr) { + FPU_FLD80(addr, FPU_STAT_TOP); +} + +static void FPU_FLD_I16(UINT32 addr,UINT store_to) { + SINT16 blah; + + blah = fpu_memoryread_w(addr); + FPU_STAT.reg[store_to].d64 = (double)(blah); + FPU_STAT.int_reg[store_to].ul64.m12 = (UINT64)((SINT64)blah); + FPU_STAT.int_regvalid[store_to] = 1; +} + +static void FPU_FLD_I32(UINT32 addr,UINT store_to) { + SINT32 blah; + + blah = fpu_memoryread_d(addr); + FPU_STAT.reg[store_to].d64 = (double)(blah); + FPU_STAT.int_reg[store_to].ul64.m12 = (UINT64)((SINT64)blah); + FPU_STAT.int_regvalid[store_to] = 1; +} + +static void FPU_FLD_I64(UINT32 addr,UINT store_to) { + FP_REG blah; + + blah.l.lower = fpu_memoryread_d(addr); + blah.l.upper = fpu_memoryread_d(addr+4); + FPU_STAT.reg[store_to].d64 = (double)(blah.ll); + FPU_STAT.int_reg[store_to].ul64.m12 = (UINT64)(blah.ll); + FPU_STAT.int_regvalid[store_to] = 1; +} + +static void FPU_FBLD(UINT32 addr,UINT store_to) +{ + UINT i; + double temp; + + UINT64 val = 0; + UINT in = 0; + UINT64 base = 1; + for(i = 0;i < 9;i++){ + in = fpu_memoryread_b(addr + i); + val += ( (in&0xf) * base); //in&0xf shouldn't be higher then 9 + base *= 10; + val += ((( in>>4)&0xf) * base); + base *= 10; + } + + //last number, only now convert to float in order to get + //the best signification + temp = (double)(val); + in = fpu_memoryread_b(addr + 9); + temp += ( (in&0xf) * base ); + if(in&0x80) temp *= -1.0; + FPU_STAT.reg[store_to].d64 = temp; +} + + +static INLINE void FPU_FLD_F32_EA(UINT32 addr) { + FPU_FLD_F32(addr,8); +} +static INLINE void FPU_FLD_F64_EA(UINT32 addr) { + FPU_FLD_F64(addr,8); +} +static INLINE void FPU_FLD_I32_EA(UINT32 addr) { + FPU_FLD_I32(addr,8); +} +static INLINE void FPU_FLD_I16_EA(UINT32 addr) { + FPU_FLD_I16(addr,8); +} + +static void FPU_FST_F32(UINT32 addr) { + union { + float f; + UINT32 l; + } blah; + + //should depend on rounding method + blah.f = (float)(FPU_STAT.reg[FPU_STAT_TOP].d64); + fpu_memorywrite_d(addr,blah.l); +} + +static void FPU_FST_F64(UINT32 addr) { + fpu_memorywrite_d(addr,FPU_STAT.reg[FPU_STAT_TOP].l.lower); + fpu_memorywrite_d(addr+4,FPU_STAT.reg[FPU_STAT_TOP].l.upper); +} + +static void FPU_FST_F80(UINT32 addr) { + FPU_ST80(addr,FPU_STAT_TOP); +} + +static void FPU_FST_I16(UINT32 addr) { + if(FPU_STAT.int_regvalid[FPU_STAT_TOP]){ + fpu_memorywrite_w(addr,(SINT16)((SINT64)(FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12))); + }else{ + fpu_memorywrite_w(addr,(SINT16)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64))); + } +} + +static void FPU_FST_I32(UINT32 addr) { + if(FPU_STAT.int_regvalid[FPU_STAT_TOP]){ + fpu_memorywrite_d(addr,(SINT32)((SINT64)(FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12))); + }else{ + fpu_memorywrite_d(addr,(SINT32)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64))); + } +} + +static void FPU_FST_I64(UINT32 addr) { + FP_REG blah; + + if(FPU_STAT.int_regvalid[FPU_STAT_TOP]){ + blah.ll = (SINT64)FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12; + fpu_memorywrite_d(addr,blah.l.lower); + fpu_memorywrite_d(addr+4,blah.l.upper); + }else{ + blah.ll = (SINT64)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64)); + fpu_memorywrite_d(addr,blah.l.lower); + fpu_memorywrite_d(addr+4,blah.l.upper); + } +} + +static void FPU_FBST(UINT32 addr) +{ + FP_REG val; + UINT p; + UINT i; + BOOL sign; + double temp; + + val = FPU_STAT.reg[FPU_STAT_TOP]; + sign = FALSE; + if(FPU_STAT.reg[FPU_STAT_TOP].ll & QWORD_CONST(0x8000000000000000)) { //sign + sign=TRUE; + val.d64=-val.d64; + } + //numbers from back to front + temp=val.d64; + for(i=0;i<9;i++){ + val.d64=temp; + temp = (double)((SINT64)(floor(val.d64/10.0))); + p = (UINT)(val.d64 - 10.0*temp); + val.d64=temp; + temp = (double)((SINT64)(floor(val.d64/10.0))); + p |= ((UINT)(val.d64 - 10.0*temp)<<4); + + fpu_memorywrite_b(addr+i,p); + } + val.d64=temp; + temp = (double)((SINT64)(floor(val.d64/10.0))); + p = (UINT)(val.d64 - 10.0*temp); + if(sign) + p|=0x80; + fpu_memorywrite_b(addr+9,p); +} + +#if defined(_WIN32) && !defined(__LIBRETRO__) +#define isinf(x) (!(_finite(x) || _isnan(x))) +#else +#define isinf(x) (!(_finite(x) || isnan(x))) +#endif +#define isdenormal(x) (_fpclass(x) == _FPCLASS_ND || _fpclass(x) == _FPCLASS_PD) + +static void FPU_FADD(UINT op1, UINT op2){ + //// HACK: Set the denormal flag according to whether the source or final result is a denormalized number. + //// This is vital if we don't want certain DOS programs to mis-detect our FPU emulation as an IIT clone chip when cputype == 286 + //BOOL was_not_normal; + + //was_not_normal = isdenormal(FPU_STAT.reg[op1].d64); + //FPU_STAT.reg[op1].d64 += FPU_STAT.reg[op2].d64; + //FPU_SET_D(was_not_normal || isdenormal(FPU_STAT.reg[op1].d64) || isdenormal(FPU_STAT.reg[op2].d64)); + FPU_STAT.reg[op1].d64 += FPU_STAT.reg[op2].d64; + //flags and such :) + //if(FPU_STAT.int_regvalid[op1] && FPU_STAT.int_regvalid[op2]){ + // SINT64 v1 = (SINT64)FPU_STAT.int_reg[op1].ul64.m12; + // SINT64 v2 = (SINT64)FPU_STAT.int_reg[op2].ul64.m12; + // SINT64 v12 = v1+v2; + // if((v1>=0 && v2<=0) || (v1<=0 && v2>=0)){ // 符号が異なればオーバーフローしない + // FPU_STAT.int_reg[op1].ul64.m12 = (UINT64)v12; + // }else if((v1>0 && v2>0) && v12 > 0){ // XXX: 正+正→正 多分処理系依存 + // FPU_STAT.int_reg[op1].ul64.m12 = (UINT64)v12; + // }else if((v1<0 && v2<0) && v12 < 0){ // XXX: 負+負→負 多分処理系依存 + // FPU_STAT.int_reg[op1].ul64.m12 = (UINT64)v12; + // }else{ + // FPU_STAT.int_regvalid[op1] = 0; + // } + //}else{ + FPU_STAT.int_regvalid[op1] = 0; + //} + return; +} + +static void FPU_FSIN(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = sin(FPU_STAT.reg[FPU_STAT_TOP].d64); + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + FPU_SET_C2(0); + //flags and such :) + return; +} + +static void FPU_FSINCOS(void){ + double temp; + + temp = FPU_STAT.reg[FPU_STAT_TOP].d64; + FPU_STAT.reg[FPU_STAT_TOP].d64 = sin(temp); + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + FPU_PUSH(cos(temp)); + FPU_SET_C2(0); + //flags and such :) + return; +} + +static void FPU_FCOS(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = cos(FPU_STAT.reg[FPU_STAT_TOP].d64); + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + FPU_SET_C2(0); + //flags and such :) + return; +} + +static void FPU_FSQRT(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = sqrt(FPU_STAT.reg[FPU_STAT_TOP].d64); + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + //flags and such :) + return; +} +static void FPU_FPATAN(void){ + FPU_STAT.reg[FPU_ST(1)].d64 = atan2(FPU_STAT.reg[FPU_ST(1)].d64,FPU_STAT.reg[FPU_STAT_TOP].d64); + FPU_STAT.int_regvalid[FPU_ST(1)] = 0; + FPU_FPOP(); + //flags and such :) + return; +} +static void FPU_FPTAN(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = tan(FPU_STAT.reg[FPU_STAT_TOP].d64); + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + FPU_PUSH(1.0); + FPU_SET_C2(0); + //flags and such :) + return; +} +static void FPU_FDIV(UINT st, UINT other){ + if(FPU_STAT.reg[other].d64==0){ + FPU_STATUSWORD |= FP_ZE_FLAG; + if(!(FPU_CTRLWORD & FP_ZE_FLAG)) + return; + } + FPU_STAT.reg[st].d64= FPU_STAT.reg[st].d64/FPU_STAT.reg[other].d64; + FPU_STAT.int_regvalid[st] = 0; + //flags and such :) + return; +} + +static void FPU_FDIVR(UINT st, UINT other){ + if(FPU_STAT.reg[st].d64==0){ + FPU_STATUSWORD |= FP_ZE_FLAG; + if(!(FPU_CTRLWORD & FP_ZE_FLAG)) + return; + } + FPU_STAT.reg[st].d64= FPU_STAT.reg[other].d64/FPU_STAT.reg[st].d64; + FPU_STAT.int_regvalid[st] = 0; + // flags and such :) + return; +} + +static void FPU_FMUL(UINT st, UINT other){ + FPU_STAT.reg[st].d64*=FPU_STAT.reg[other].d64; + FPU_STAT.int_regvalid[st] = 0; + //flags and such :) + return; +} + +static void FPU_FSUB(UINT st, UINT other){ + FPU_STAT.reg[st].d64 = FPU_STAT.reg[st].d64 - FPU_STAT.reg[other].d64; + //if(FPU_STAT.int_regvalid[st] && FPU_STAT.int_regvalid[other]){ + // SINT64 v1 = (SINT64)FPU_STAT.int_reg[st].ul64.m12; + // SINT64 v2 = (SINT64)FPU_STAT.int_reg[other].ul64.m12; + // SINT64 v12 = v1-v2; + // if((v1>=0 && v2>=0) || (v1<=0 && v2<=0)){ // 符号が異なればオーバーフローしない + // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; + // }else if((v1>0 && v2<0) && v12 > 0){ // XXX: 正+正→正 多分処理系依存 + // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; + // }else if((v1<0 && v2>0) && v12 < 0){ // XXX: 負+負→負 多分処理系依存 + // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; + // }else{ + // FPU_STAT.int_regvalid[st] = 0; + // } + //}else{ + FPU_STAT.int_regvalid[st] = 0; + //} + //flags and such :) + return; +} + +static void FPU_FSUBR(UINT st, UINT other){ + FPU_STAT.reg[st].d64 = FPU_STAT.reg[other].d64 - FPU_STAT.reg[st].d64; + //if(FPU_STAT.int_regvalid[st] && FPU_STAT.int_regvalid[other]){ + // SINT64 v1 = (SINT64)FPU_STAT.int_reg[other].ul64.m12; + // SINT64 v2 = (SINT64)FPU_STAT.int_reg[st].ul64.m12; + // SINT64 v12 = v1-v2; + // if((v1>=0 && v2>=0) || (v1<=0 && v2<=0)){ // 符号が異なればオーバーフローしない + // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; + // }else if((v1>0 && v2<0) && v12 > 0){ // 正+正→正 多分処理系依存 + // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; + // }else if((v1<0 && v2>0) && v12 < 0){ // 負+負→負 多分処理系依存 + // FPU_STAT.int_reg[st].ul64.m12 = (UINT64)v12; + // }else{ + // FPU_STAT.int_regvalid[st] = 0; + // } + //}else{ + FPU_STAT.int_regvalid[st] = 0; + //} + //flags and such :) + return; +} + +static void FPU_FXCH(UINT st, UINT other){ + FP_TAG tag; + FP_REG reg; + UINT8 regvalid; + FP_INT_REG intreg; + + tag = FPU_STAT.tag[other]; + reg = FPU_STAT.reg[other]; + FPU_STAT.tag[other] = FPU_STAT.tag[st]; + FPU_STAT.reg[other] = FPU_STAT.reg[st]; + FPU_STAT.tag[st] = tag; + FPU_STAT.reg[st] = reg; + regvalid = FPU_STAT.int_regvalid[other]; + intreg = FPU_STAT.int_reg[other]; + FPU_STAT.int_regvalid[other] = FPU_STAT.int_regvalid[st]; + FPU_STAT.int_reg[other] = FPU_STAT.int_reg[st]; + FPU_STAT.int_regvalid[st] = regvalid; + FPU_STAT.int_reg[st] = intreg; +} + +static void FPU_FST(UINT st, UINT other){ + FPU_STAT.tag[other] = FPU_STAT.tag[st]; + FPU_STAT.reg[other] = FPU_STAT.reg[st]; + FPU_STAT.int_regvalid[other] = FPU_STAT.int_regvalid[st]; + FPU_STAT.int_reg[other] = FPU_STAT.int_reg[st]; +} + +static void FPU_FCOM(UINT st, UINT other){ + if(((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || + ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero))){ + FPU_SET_C3(1); + FPU_SET_C2(1); + FPU_SET_C0(1); + return; + } + + if(FPU_STAT.reg[st].d64 == FPU_STAT.reg[other].d64){ + FPU_SET_C3(1); + FPU_SET_C2(0); + FPU_SET_C0(0); + return; + } + if(FPU_STAT.reg[st].d64 < FPU_STAT.reg[other].d64){ + FPU_SET_C3(0); + FPU_SET_C2(0); + FPU_SET_C0(1); + return; + } + // st > other + FPU_SET_C3(0); + FPU_SET_C2(0); + FPU_SET_C0(0); + return; +} +static void FPU_FCOMI(UINT st, UINT other){ + if(((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || + ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero))){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | P_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; + return; + } + + if(FPU_STAT.reg[st].d64 == FPU_STAT.reg[other].d64){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; + return; + } + if(FPU_STAT.reg[st].d64 < FPU_STAT.reg[other].d64){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; + return; + } + // st > other + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; + return; +} + +static void FPU_FUCOM(UINT st, UINT other){ + //does atm the same as fcom + FPU_FCOM(st,other); +} +static void FPU_FUCOMI(UINT st, UINT other){ + //does atm the same as fcomi + FPU_FCOMI(st,other); +} + +static void FPU_FCMOVB(UINT st, UINT other){ + if(CPU_FLAGL & C_FLAG){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; + FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; + } +} +static void FPU_FCMOVE(UINT st, UINT other){ + if(CPU_FLAGL & Z_FLAG){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; + FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; + } +} +static void FPU_FCMOVBE(UINT st, UINT other){ + if(CPU_FLAGL & (C_FLAG|Z_FLAG)){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; + FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; + } +} +static void FPU_FCMOVU(UINT st, UINT other){ + if(CPU_FLAGL & P_FLAG){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; + FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; + } +} + +static void FPU_FCMOVNB(UINT st, UINT other){ + if(!(CPU_FLAGL & C_FLAG)){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; + FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; + } +} +static void FPU_FCMOVNE(UINT st, UINT other){ + if(!(CPU_FLAGL & Z_FLAG)){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; + FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; + } +} +static void FPU_FCMOVNBE(UINT st, UINT other){ + if(!(CPU_FLAGL & (C_FLAG|Z_FLAG))){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; + FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; + } +} +static void FPU_FCMOVNU(UINT st, UINT other){ + if(!(CPU_FLAGL & P_FLAG)){ + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + FPU_STAT.int_regvalid[st] = FPU_STAT.int_regvalid[other]; + FPU_STAT.int_reg[st] = FPU_STAT.int_reg[other]; + } +} + +static void FPU_FRNDINT(void){ + SINT64 temp; + + temp = (SINT64)(FROUND(FPU_STAT.reg[FPU_STAT_TOP].d64)); + FPU_STAT.reg[FPU_STAT_TOP].d64=(double)(temp); + if(!FPU_STAT.int_regvalid[FPU_STAT_TOP]){ + FPU_STAT.int_reg[FPU_STAT_TOP].l64.m12 = temp; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 1; + }else{ + // 既に整数 + } +} + +static void FPU_FPREM(void){ + double valtop; + double valdiv; + SINT64 ressaved; + + valtop = FPU_STAT.reg[FPU_STAT_TOP].d64; + valdiv = FPU_STAT.reg[FPU_ST(1)].d64; + ressaved = (SINT64)( (valtop/valdiv) ); +// Some backups +// Real64 res=valtop - ressaved*valdiv; +// res= fmod(valtop,valdiv); + FPU_STAT.reg[FPU_STAT_TOP].d64 = valtop - ressaved*valdiv; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + FPU_SET_C0((UINT)(ressaved&4)); + FPU_SET_C3((UINT)(ressaved&2)); + FPU_SET_C1((UINT)(ressaved&1)); + FPU_SET_C2(0); +} + +static void FPU_FPREM1(void){ + double valtop; + double valdiv, quot, quotf; + SINT64 ressaved; + + valtop = FPU_STAT.reg[FPU_STAT_TOP].d64; + valdiv = FPU_STAT.reg[FPU_ST(1)].d64; + quot = valtop/valdiv; + quotf = floor(quot); + + if (quot-quotf>0.5) ressaved = (SINT64)(quotf+1); + else if (quot-quotf<0.5) ressaved = (SINT64)(quotf); + else ressaved = (SINT64)(((((SINT64)(quotf))&1)!=0)?(quotf+1):(quotf)); + + FPU_STAT.reg[FPU_STAT_TOP].d64 = valtop - ressaved*valdiv; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + FPU_SET_C0((UINT)(ressaved&4)); + FPU_SET_C3((UINT)(ressaved&2)); + FPU_SET_C1((UINT)(ressaved&1)); + FPU_SET_C2(0); +} + +static void FPU_FXAM(void){ + if(FPU_STAT.reg[FPU_STAT_TOP].ll & QWORD_CONST(0x8000000000000000)) //sign + { + FPU_SET_C1(1); + } + else + { + FPU_SET_C1(0); + } + if(FPU_STAT.tag[FPU_STAT_TOP] == TAG_Empty) + { + FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(1); + return; + } + if(FPU_STAT.reg[FPU_STAT_TOP].d64 == 0.0) //zero or normalized number. + { + FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0); + } + else + { + FPU_SET_C3(0);FPU_SET_C2(1);FPU_SET_C0(0); + } +} + +static void FPU_F2XM1(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = pow(2.0,FPU_STAT.reg[FPU_STAT_TOP].d64) - 1; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + return; +} + +static void FPU_FYL2X(void){ + FPU_STAT.reg[FPU_ST(1)].d64*=log(FPU_STAT.reg[FPU_STAT_TOP].d64)/log((double)(2.0)); + FPU_STAT.int_regvalid[FPU_ST(1)] = 0; + FPU_FPOP(); + return; +} + +static void FPU_FYL2XP1(void){ + FPU_STAT.reg[FPU_ST(1)].d64*=log(FPU_STAT.reg[FPU_STAT_TOP].d64+1.0)/log((double)(2.0)); + FPU_STAT.int_regvalid[FPU_ST(1)] = 0; + FPU_FPOP(); + return; +} + +static void FPU_FSCALE(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 *= pow(2.0,(double)((SINT64)(FPU_STAT.reg[FPU_ST(1)].d64))); + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + return; //2^x where x is chopped. +} + +static void FPU_FSTENV(UINT32 addr) +{ + descriptor_t *sdp = &CPU_CS_DESC; + FPU_SET_TOP(FPU_STAT_TOP); + + switch ((CPU_CR0 & 1) | (SEG_IS_32BIT(sdp) ? 0x100 : 0x000)) + { + case 0x000: case 0x001: + fpu_memorywrite_w(addr+0,FPU_CTRLWORD); + fpu_memorywrite_w(addr+2,FPU_STATUSWORD); + fpu_memorywrite_w(addr+4,FPU_GetTag()); + fpu_memorywrite_w(addr+10,FPU_LASTINSTOP); + break; + + case 0x100: case 0x101: + fpu_memorywrite_d(addr+0,(UINT32)(FPU_CTRLWORD)); + fpu_memorywrite_d(addr+4,(UINT32)(FPU_STATUSWORD)); + fpu_memorywrite_d(addr+8,(UINT32)(FPU_GetTag())); + fpu_memorywrite_d(addr+20,FPU_LASTINSTOP); + break; + } +} + +static void FPU_FLDENV(UINT32 addr) +{ + descriptor_t *sdp = &CPU_CS_DESC; + + switch ((CPU_CR0 & 1) | (SEG_IS_32BIT(sdp) ? 0x100 : 0x000)) { + case 0x000: case 0x001: + FPU_SetCW(fpu_memoryread_w(addr+0)); + FPU_STATUSWORD = fpu_memoryread_w(addr+2); + FPU_SetTag(fpu_memoryread_w(addr+4)); + FPU_LASTINSTOP = fpu_memoryread_w(addr+10); + break; + + case 0x100: case 0x101: + FPU_SetCW((UINT16)fpu_memoryread_d(addr+0)); + FPU_STATUSWORD = (UINT16)fpu_memoryread_d(addr+4); + FPU_SetTag((UINT16)fpu_memoryread_d(addr+8)); + FPU_LASTINSTOP = (UINT16)fpu_memoryread_d(addr+20); + break; + } + FPU_STAT_TOP = FPU_GET_TOP(); +} + +static void FPU_FSAVE(UINT32 addr) +{ + UINT start; + UINT i; + + descriptor_t *sdp = &CPU_CS_DESC; + + FPU_FSTENV(addr); + start = ((SEG_IS_32BIT(sdp))?28:14); + for(i = 0;i < 8;i++){ + FPU_ST80(addr+start,FPU_ST(i)); + start += 10; + } + FPU_FINIT(); +} + +static void FPU_FRSTOR(UINT32 addr) +{ + UINT start; + UINT i; + + descriptor_t *sdp = &CPU_CS_DESC; + + FPU_FLDENV(addr); + start = ((SEG_IS_32BIT(sdp))?28:14); + for(i = 0;i < 8;i++){ + FPU_FLD80(addr+start, FPU_ST(i)); + start += 10; + } +} + +static void FPU_FXSAVE(UINT32 addr){ + UINT start; + UINT i; + + descriptor_t *sdp = &CPU_CS_DESC; + + //FPU_FSTENV(addr); + FPU_SET_TOP(FPU_STAT_TOP); + fpu_memorywrite_w(addr+0,FPU_CTRLWORD); + fpu_memorywrite_w(addr+2,FPU_STATUSWORD); + fpu_memorywrite_b(addr+4,FPU_GetTag8()); +#ifdef USE_SSE + fpu_memorywrite_d(addr+24,SSE_MXCSR); +#endif + start = 32; + for(i = 0;i < 8;i++){ + //FPU_ST80(addr+start,FPU_ST(i)); + fpu_memorywrite_d(addr+start+0,FPU_STAT.reg[FPU_ST(i)].l.lower); + fpu_memorywrite_d(addr+start+4,FPU_STAT.reg[FPU_ST(i)].l.upper); + if(FPU_STAT.int_regvalid[FPU_ST(i)]){ + fpu_memorywrite_d(addr+start+8,FPU_STAT.int_reg[FPU_ST(i)].ul32.m1); + fpu_memorywrite_d(addr+start+12,FPU_STAT.int_reg[FPU_ST(i)].ul32.m2); + }else{ + fpu_memorywrite_d(addr+start+8,0x00000000); + fpu_memorywrite_d(addr+start+12,0x00000000); + } + start += 16; + } +#ifdef USE_SSE + start = 160; + for(i = 0;i < 8;i++){ + fpu_memorywrite_q(addr+start+0,SSE_XMMREG(i).ul64[0]); + fpu_memorywrite_q(addr+start+8,SSE_XMMREG(i).ul64[1]); + start += 16; + } +#endif +} +static void FPU_FXRSTOR(UINT32 addr){ + UINT start; + UINT i; + + descriptor_t *sdp = &CPU_CS_DESC; + + //FPU_FLDENV(addr); + FPU_SetCW(fpu_memoryread_w(addr+0)); + FPU_STATUSWORD = fpu_memoryread_w(addr+2); + FPU_SetTag8(fpu_memoryread_b(addr+4)); + FPU_STAT_TOP = FPU_GET_TOP(); +#ifdef USE_SSE + SSE_MXCSR = fpu_memoryread_d(addr+24); +#endif + start = 32; + for(i = 0;i < 8;i++){ + //FPU_STAT.reg[FPU_ST(i)].d64 = FPU_FLD80(addr+start); + FPU_STAT.reg[FPU_ST(i)].l.lower = fpu_memoryread_d(addr+start+0); + FPU_STAT.reg[FPU_ST(i)].l.upper = fpu_memoryread_d(addr+start+4); + FPU_STAT.int_reg[FPU_ST(i)].ul32.m1 = fpu_memoryread_d(addr+start+8); + FPU_STAT.int_reg[FPU_ST(i)].ul32.m2 = fpu_memoryread_d(addr+start+12); + if(FPU_STAT.int_reg[FPU_ST(i)].ul64.m12){ + FPU_STAT.int_regvalid[FPU_ST(i)] = 1; + }else{ + FPU_STAT.int_regvalid[FPU_ST(i)] = 0; + } + start += 16; + } +#ifdef USE_SSE + start = 160; + for(i = 0;i < 8;i++){ + SSE_XMMREG(i).ul64[0] = fpu_memoryread_q(addr+start+0); + SSE_XMMREG(i).ul64[1] = fpu_memoryread_q(addr+start+8); + start += 16; + } +#endif +} + +void DB2_FPU_FXSAVERSTOR(void){ + UINT32 op; + UINT idx, sub; + UINT32 maddr; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + switch(idx){ + case 0: // FXSAVE + fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し + maddr = calc_ea_dst(op); + FPU_FXSAVE(maddr); + break; + case 1: // FXRSTOR + fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し + maddr = calc_ea_dst(op); + FPU_FXRSTOR(maddr); + break; +#ifdef USE_SSE + case 2: // LDMXCSR + maddr = calc_ea_dst(op); + SSE_LDMXCSR(maddr); + break; + case 3: // STMXCSR + maddr = calc_ea_dst(op); + SSE_STMXCSR(maddr); + break; + case 4: // SFENCE + SSE_SFENCE(); + break; + case 5: // LFENCE + SSE_LFENCE(); + break; + case 6: // MFENCE + SSE_MFENCE(); + break; + case 7: // CLFLUSH; + SSE_CLFLUSH(op); + break; +#endif + default: + ia32_panic("invalid opcode = %02x\n", op); + break; + } +} + +static void FPU_FXTRACT(void) { + // function stores real bias in st and + // pushes the significant number onto the stack + // if double ever uses a different base please correct this function + FP_REG test; + SINT64 exp80, exp80final; + double mant; + + test = FPU_STAT.reg[FPU_STAT_TOP]; + exp80 = test.ll&QWORD_CONST(0x7ff0000000000000); + exp80final = (exp80>>52) - BIAS64; + mant = test.d64 / (pow(2.0,(double)(exp80final))); + FPU_STAT.reg[FPU_STAT_TOP].d64 = (double)(exp80final); + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + FPU_PUSH(mant); +} + +static void FPU_FCHS(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = -1.0*(FPU_STAT.reg[FPU_STAT_TOP].d64); + if(FPU_STAT.int_regvalid[FPU_STAT_TOP]){ + if(FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12 != QWORD_CONST(0x8000000000000000)){ + FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12 = (~FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12) + 1; // 符号反転 + }else{ + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + } + } +} + +static void FPU_FABS(void){ + FPU_STAT.reg[FPU_STAT_TOP].d64 = fabs(FPU_STAT.reg[FPU_STAT_TOP].d64); + if(FPU_STAT.int_regvalid[FPU_STAT_TOP]){ + if((QWORD_CONST(0x8000000000000000) & FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12)!=0 && + (FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12 != QWORD_CONST(0x8000000000000000))){ + FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12 = (~FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12) + 1; // 符号反転 + }else{ + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; + } + } +} + +static void FPU_FTST(void){ + FPU_STAT.reg[8].d64 = 0.0; + FPU_FCOM(FPU_STAT_TOP,8); +} + +static void FPU_FLD1(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = 1.0; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; +} + +static void FPU_FLDL2T(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = L2T; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; +} + +static void FPU_FLDL2E(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = L2E; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; +} + +static void FPU_FLDPI(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = PI; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; +} + +static void FPU_FLDLG2(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = LG2; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; +} + +static void FPU_FLDLN2(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = LN2; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 0; +} + +static void FPU_FLDZ(void){ + FPU_PREP_PUSH(); + FPU_STAT.reg[FPU_STAT_TOP].d64 = 0.0; + FPU_STAT.tag[FPU_STAT_TOP] = TAG_Zero; + FPU_STAT.int_reg[FPU_STAT_TOP].ul64.m12 = 0; + FPU_STAT.int_regvalid[FPU_STAT_TOP] = 1; +} + + +static INLINE void FPU_FADD_EA(UINT op1){ + FPU_FADD(op1,8); +} +static INLINE void FPU_FMUL_EA(UINT op1){ + FPU_FMUL(op1,8); +} +static INLINE void FPU_FSUB_EA(UINT op1){ + FPU_FSUB(op1,8); +} +static INLINE void FPU_FSUBR_EA(UINT op1){ + FPU_FSUBR(op1,8); +} +static INLINE void FPU_FDIV_EA(UINT op1){ + FPU_FDIV(op1,8); +} +static INLINE void FPU_FDIVR_EA(UINT op1){ + FPU_FDIVR(op1,8); +} +static INLINE void FPU_FCOM_EA(UINT op1){ + FPU_FCOM(op1,8); +} + +/* + * FPU interface + */ +//int fpu_updateEmuEnv(void); +static void +FPU_FINIT(void) +{ + int i; + FPU_SetCW(0x37F); + FPU_STATUSWORD = 0; + FPU_STAT_TOP=FPU_GET_TOP(); + for(i=0;i<8;i++){ + FPU_STAT.tag[i] = TAG_Empty; + FPU_STAT.int_regvalid[i] = 0; + // レジスタの内容は消してはいけない ver0.86 rev40 + //FPU_STAT.reg[i].d64 = 0; + //FPU_STAT.reg[i].l.lower = 0; + //FPU_STAT.reg[i].l.upper = 0; + //FPU_STAT.reg[i].ll = 0; + } + FPU_STAT.tag[8] = TAG_Valid; // is only used by us +} +void DB2_FPU_FINIT(void){ + int i; + FPU_FINIT(); + for(i=0;i<8;i++){ + FPU_STAT.tag[i] = TAG_Empty; + FPU_STAT.reg[i].l.ext = 0; + FPU_STAT.reg[i].l.lower = 0; + FPU_STAT.reg[i].l.upper = 0; + } +} + +//char * +//fpu_reg2str(void) +//{ +// return NULL; +//} + + +/* + * FPU instruction + */ + +static void fpu_checkexception(){ + if((FPU_STATUSWORD & ~FPU_CTRLWORD) & 0x3F){ + EXCEPTION(MF_EXCEPTION, 0); + } +} + +static void EA_TREE(UINT op) +{ + UINT idx; + + idx = (op >> 3) & 7; + + switch (idx) { + case 0: /* FADD (単精度実数) */ + TRACEOUT(("FADD EA")); + FPU_FADD_EA(FPU_STAT_TOP); + break; + case 1: /* FMUL (単精度実数) */ + TRACEOUT(("FMUL EA")); + FPU_FMUL_EA(FPU_STAT_TOP); + break; + case 2: /* FCOM (単精度実数) */ + TRACEOUT(("FCOM EA")); + FPU_FCOM_EA(FPU_STAT_TOP); + break; + case 3: /* FCOMP (単精度実数) */ + TRACEOUT(("FCOMP EA")); + FPU_FCOM_EA(FPU_STAT_TOP); + FPU_FPOP(); + break; + case 4: /* FSUB (単精度実数) */ + TRACEOUT(("FSUB EA")); + FPU_FSUB_EA(FPU_STAT_TOP); + break; + case 5: /* FSUBR (単精度実数) */ + TRACEOUT(("FSUBR EA")); + FPU_FSUBR_EA(FPU_STAT_TOP); + break; + case 6: /* FDIV (単精度実数) */ + TRACEOUT(("FDIV EA")); + FPU_FDIV_EA(FPU_STAT_TOP); + break; + case 7: /* FDIVR (単精度実数) */ + TRACEOUT(("FDIVR EA")); + FPU_FDIVR_EA(FPU_STAT_TOP); + break; + default: + break; + } +} + +// d8 +void +DB2_ESC0(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU d8 %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FADD */ + TRACEOUT(("FADD")); + FPU_FADD(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 1: /* FMUL */ + TRACEOUT(("FMUL")); + FPU_FMUL(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FCOM */ + TRACEOUT(("FCOM")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCOMP */ + TRACEOUT(("FCOMP")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + case 4: /* FSUB */ + TRACEOUT(("FSUB")); + FPU_FSUB(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 5: /* FSUBR */ + TRACEOUT(("FSUBR")); + FPU_FSUBR(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 6: /* FDIV */ + TRACEOUT(("FDIV")); + FPU_FDIV(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 7: /* FDIVR */ + TRACEOUT(("FDIVR")); + FPU_FDIVR(FPU_STAT_TOP,FPU_ST(sub)); + break; + } + } else { + madr = calc_ea_dst(op); + FPU_FLD_F32_EA(madr); + EA_TREE(op); + } +} + +// d9 +void +DB2_ESC1(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU d9 %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + if(!(op < 0xc0 && idx>=4)){ + fpu_checkexception(); + } + if (op >= 0xc0) + { + switch (idx) { + case 0: /* FLD ST(0), ST(i) */ + { + UINT reg_from; + + TRACEOUT(("FLD STi")); + reg_from = FPU_ST(sub); + FPU_PREP_PUSH(); + FPU_FST(reg_from, FPU_STAT_TOP); + } + break; + + case 1: /* FXCH ST(0), ST(i) */ + TRACEOUT(("FXCH STi")); + FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); + break; + + case 2: /* FNOP */ + TRACEOUT(("FNOP")); + FPU_FNOP(); + break; + + case 3: /* FSTP STi */ + TRACEOUT(("FSTP STi")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + + case 4: + switch (sub) { + case 0x0: /* FCHS */ + TRACEOUT(("FCHS")); + FPU_FCHS(); + break; + + case 0x1: /* FABS */ + TRACEOUT(("FABS")); + FPU_FABS(); + break; + + case 0x2: /* UNKNOWN */ + case 0x3: /* ILLEGAL */ + break; + + case 0x4: /* FTST */ + TRACEOUT(("FTST")); + FPU_FTST(); + break; + + case 0x5: /* FXAM */ + TRACEOUT(("FXAM")); + FPU_FXAM(); + break; + + case 0x06: /* FTSTP (cyrix)*/ + case 0x07: /* UNKNOWN */ + break; + } + break; + + case 5: + switch (sub) { + case 0x0: /* FLD1 */ + TRACEOUT(("FLD1")); + FPU_FLD1(); + break; + + case 0x1: /* FLDL2T */ + TRACEOUT(("FLDL2T")); + FPU_FLDL2T(); + break; + + case 0x2: /* FLDL2E */ + TRACEOUT(("FLDL2E")); + FPU_FLDL2E(); + break; + + case 0x3: /* FLDPI */ + TRACEOUT(("FLDPI")); + FPU_FLDPI(); + break; + + case 0x4: /* FLDLG2 */ + TRACEOUT(("FLDLG2")); + FPU_FLDLG2(); + break; + + case 0x5: /* FLDLN2 */ + TRACEOUT(("FLDLN2")); + FPU_FLDLN2(); + break; + + case 0x6: /* FLDZ */ + TRACEOUT(("FLDZ")); + FPU_FLDZ(); + break; + + case 0x07: /* ILLEGAL */ + break; + } + break; + + case 6: + switch (sub) { + case 0x0: /* F2XM1 */ + TRACEOUT(("F2XM1")); + FPU_F2XM1(); + break; + + case 0x1: /* FYL2X */ + TRACEOUT(("FYL2X")); + FPU_FYL2X(); + break; + + case 0x2: /* FPTAN */ + TRACEOUT(("FPTAN")); + FPU_FPTAN(); + break; + + case 0x3: /* FPATAN */ + TRACEOUT(("FPATAN")); + FPU_FPATAN(); + break; + + case 0x4: /* FXTRACT */ + TRACEOUT(("FXTRACT")); + FPU_FXTRACT(); + break; + + case 0x5: /* FPREM1 */ + TRACEOUT(("FPREM1")); + FPU_FPREM1(); + break; + + case 0x6: /* FDECSTP */ + TRACEOUT(("FDECSTP")); + FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; + break; + + case 0x7: /* FINCSTP */ + TRACEOUT(("FINCSTP")); + FPU_STAT_TOP = (FPU_STAT_TOP + 1) & 7; + break; + } + break; + + case 7: + switch (sub) { + case 0x0: /* FPREM */ + TRACEOUT(("FPREM")); + FPU_FPREM(); + break; + + case 0x1: /* FYL2XP1 */ + TRACEOUT(("FYL2XP1")); + FPU_FYL2XP1(); + break; + + case 0x2: /* FSQRT */ + TRACEOUT(("FSQRT")); + FPU_FSQRT(); + break; + + case 0x3: /* FSINCOS */ + TRACEOUT(("FSINCOS")); + FPU_FSINCOS(); + break; + + case 0x4: /* FRNDINT */ + TRACEOUT(("FRNDINT")); + FPU_FRNDINT(); + break; + + case 0x5: /* FSCALE */ + TRACEOUT(("FSCALE")); + FPU_FSCALE(); + break; + + case 0x6: /* FSIN */ + TRACEOUT(("FSIN")); + FPU_FSIN(); + break; + + case 0x7: /* FCOS */ + TRACEOUT(("FCOS")); + FPU_FCOS(); + break; + } + break; + + default: + ia32_panic("ESC1: invalid opcode = %02x\n", op); + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FLD (単精度実数) */ + TRACEOUT(("FLD float")); + FPU_PREP_PUSH(); + FPU_FLD_F32(madr,FPU_STAT_TOP); + break; + + case 1: /* UNKNOWN */ + break; + + case 2: /* FST (単精度実数) */ + TRACEOUT(("FST float")); + FPU_FST_F32(madr); + break; + + case 3: /* FSTP (単精度実数) */ + TRACEOUT(("FSTP float")); + FPU_FST_F32(madr); + FPU_FPOP(); + break; + + case 4: /* FLDENV */ + TRACEOUT(("FLDENV")); + FPU_FLDENV(madr); + break; + + case 5: /* FLDCW */ + TRACEOUT(("FLDCW")); + FPU_FLDCW(madr); + break; + + case 6: /* FSTENV */ + TRACEOUT(("FSTENV")); + FPU_FSTENV(madr); + break; + + case 7: /* FSTCW */ + TRACEOUT(("FSTCW/FNSTCW")); + fpu_memorywrite_w(madr,FPU_CTRLWORD); + break; + + default: + break; + } + } +} + +// da +void +DB2_ESC2(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU da %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FCMOVB */ + TRACEOUT(("ESC2: FCMOVB")); + FPU_FCMOVB(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 1: /* FCMOVE */ + TRACEOUT(("ESC2: FCMOVE")); + FPU_FCMOVE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FCMOVBE */ + TRACEOUT(("ESC2: FCMOVBE")); + FPU_FCMOVBE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCMOVU */ + TRACEOUT(("ESC2: FCMOVU")); + FPU_FCMOVU(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 5: + switch (sub) { + case 1: /* FUCOMPP */ + TRACEOUT(("FUCOMPP")); + FPU_FUCOM(FPU_STAT_TOP,FPU_ST(1)); + FPU_FPOP(); + FPU_FPOP(); + break; + + default: + break; + } + break; + + default: + break; + } + } else { + madr = calc_ea_dst(op); + FPU_FLD_I32_EA(madr); + EA_TREE(op); + } +} + +// db +void +DB2_ESC3(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU db %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + if(!(op >= 0xc0 && idx==4)){ + fpu_checkexception(); + } + if (op >= 0xc0) + { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FCMOVNB */ + TRACEOUT(("ESC3: FCMOVNB")); + FPU_FCMOVNB(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 1: /* FCMOVNE */ + TRACEOUT(("ESC3: FCMOVNE")); + FPU_FCMOVNE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FCMOVNBE */ + TRACEOUT(("ESC3: FCMOVNBE")); + FPU_FCMOVNBE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCMOVNU */ + TRACEOUT(("ESC3: FCMOVNU")); + FPU_FCMOVNU(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 4: + switch (sub) { + case 0: /* FNENI */ + case 1: /* FNDIS */ + break; + + case 2: /* FCLEX */ + TRACEOUT(("FCLEX")); + FPU_FCLEX(); + break; + + case 3: /* FNINIT/FINIT */ + TRACEOUT(("FNINIT/FINIT")); + FPU_FINIT(); + break; + + case 4: /* FNSETPM */ + case 5: /* FRSTPM */ + FPU_FNOP(); + break; + + default: + break; + } + break; + case 5: /* FUCOMI */ + TRACEOUT(("ESC3: FUCOMI")); + FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 6: /* FCOMI */ + TRACEOUT(("ESC3: FCOMI")); + FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); + break; + default: + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FILD (DWORD) */ + TRACEOUT(("FILD")); + FPU_PREP_PUSH(); + FPU_FLD_I32(madr,FPU_STAT_TOP); + break; + + case 1: /* FISTTP (DWORD) */ + { + FP_RND oldrnd = FPU_STAT.round; + FPU_STAT.round = ROUND_Down; + FPU_FST_I32(madr); + FPU_STAT.round = oldrnd; + } + FPU_FPOP(); + break; + + case 2: /* FIST (DWORD) */ + TRACEOUT(("FIST")); + FPU_FST_I32(madr); + break; + + case 3: /* FISTP (DWORD) */ + TRACEOUT(("FISTP")); + FPU_FST_I32(madr); + FPU_FPOP(); + break; + + case 5: /* FLD (拡張実数) */ + TRACEOUT(("FLD 80 Bits Real")); + FPU_PREP_PUSH(); + FPU_FLD_F80(madr); + break; + + case 7: /* FSTP (拡張実数) */ + TRACEOUT(("FSTP 80 Bits Real")); + FPU_FST_F80(madr); + FPU_FPOP(); + break; + + default: + break; + } + } +} + +// dc +void +DB2_ESC4(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU dc %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(i), ST(0) */ + switch (idx) { + case 0: /* FADD */ + TRACEOUT(("ESC4: FADD")); + FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); + break; + case 1: /* FMUL */ + TRACEOUT(("ESC4: FMUL")); + FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); + break; + case 2: /* FCOM */ + TRACEOUT(("ESC4: FCOM")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCOMP */ + TRACEOUT(("ESC4: FCOMP")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + case 4: /* FSUBR */ + TRACEOUT(("ESC4: FSUBR")); + FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); + break; + case 5: /* FSUB */ + TRACEOUT(("ESC4: FSUB")); + FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); + break; + case 6: /* FDIVR */ + TRACEOUT(("ESC4: FDIVR")); + FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); + break; + case 7: /* FDIV */ + TRACEOUT(("ESC4: FDIV")); + FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); + break; + default: + break; + } + } else { + madr = calc_ea_dst(op); + FPU_FLD_F64_EA(madr); + EA_TREE(op); + } +} + +// dd +void +DB2_ESC5(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU dd %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + fpu_check_NM_EXCEPTION(); + //if(op < 0xc0 && (idx==6 || idx==4)){ + // _ADD_EIP(-1); // XXX: 無理やり戻す + // fpu_check_NM_EXCEPTION2(); + // _ADD_EIP(1); + //}else{ + // _ADD_EIP(-1); // XXX: 無理やり戻す + // fpu_check_NM_EXCEPTION(); + // _ADD_EIP(1); + //} + if(op >= 0xc0 || (idx!=4 && idx!=6 && idx!=7)){ + fpu_checkexception(); + } + if (op >= 0xc0) { + /* FUCOM ST(i), ST(0) */ + /* Fxxx ST(i) */ + switch (idx) { + case 0: /* FFREE */ + TRACEOUT(("FFREE")); + FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; + break; + case 1: /* FXCH */ + TRACEOUT(("FXCH")); + FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FST */ + TRACEOUT(("FST")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FSTP */ + TRACEOUT(("FSTP")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + case 4: /* FUCOM */ + TRACEOUT(("FUCOM")); + FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 5: /* FUCOMP */ + TRACEOUT(("FUCOMP")); + FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + + default: + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FLD (倍精度実数) */ + TRACEOUT(("FLD double real")); + FPU_PREP_PUSH(); + FPU_FLD_F64(madr,FPU_STAT_TOP); + break; + case 1: /* FISTTP (QWORD) */ + { + FP_RND oldrnd = FPU_STAT.round; + FPU_STAT.round = ROUND_Down; + FPU_FST_I64(madr); + FPU_STAT.round = oldrnd; + } + FPU_FPOP(); + break; + case 2: /* FST (倍精度実数) */ + TRACEOUT(("FST double real")); + FPU_FST_F64(madr); + break; + case 3: /* FSTP (倍精度実数) */ + TRACEOUT(("FSTP double real")); + FPU_FST_F64(madr); + FPU_FPOP(); + break; + case 4: /* FRSTOR */ + TRACEOUT(("FRSTOR")); + FPU_FRSTOR(madr); + break; + case 6: /* FSAVE */ + TRACEOUT(("FSAVE")); + FPU_FSAVE(madr); + break; + + case 7: /* FSTSW */ + FPU_SET_TOP(FPU_STAT_TOP); + //cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, FPU_CTRLWORD); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, FPU_STATUSWORD); + break; + + default: + break; + } + } +} + +// de +void +DB2_ESC6(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU de %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(i), ST(0) */ + switch (idx) { + case 0: /* FADDP */ + TRACEOUT(("FADDP")); + FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); + break; + case 1: /* FMULP */ + TRACEOUT(("FMULP")); + FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); + break; + case 2: /* FCOMP5 */ + TRACEOUT(("FCOMP5")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCOMPP */ + TRACEOUT(("FCOMPP")); + if(sub != 1) { + return; + } + FPU_FCOM(FPU_STAT_TOP,FPU_ST(1)); + FPU_FPOP(); /* extra pop at the bottom*/ + break; + case 4: /* FSUBRP */ + TRACEOUT(("FSUBRP")); + FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); + break; + case 5: /* FSUBP */ + TRACEOUT(("FSUBP")); + FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); + break; + case 6: /* FDIVRP */ + TRACEOUT(("FDIVRP")); + FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); + if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ + return; // POPしないようにする + } + break; + case 7: /* FDIVP */ + TRACEOUT(("FDIVP")); + FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); + if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ + return; // POPしないようにする + } + break; + /*FALLTHROUGH*/ + default: + break; + } + FPU_FPOP(); + } else { + madr = calc_ea_dst(op); + FPU_FLD_I16_EA(madr); + EA_TREE(op); + } +} + +// df +void +DB2_ESC7(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU df %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + if(!(op >= 0xc0 && idx==4 && sub==0)){ + fpu_checkexception(); + } + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FFREEP */ + TRACEOUT(("FFREEP")); + FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; + FPU_FPOP(); + break; + case 1: /* FXCH */ + TRACEOUT(("FXCH")); + FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); + break; + + case 2: + case 3: /* FSTP */ + TRACEOUT(("FSTP")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + + case 4: + switch (sub) + { + case 0: /* FSTSW AX */ + TRACEOUT(("FSTSW AX")); + FPU_SET_TOP(FPU_STAT_TOP); + CPU_AX = FPU_STATUSWORD; + break; + + default: + break; + } + break; + case 5: /* FUCOMIP */ + TRACEOUT(("ESC7: FUCOMIP")); + FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + case 6: /* FCOMIP */ + TRACEOUT(("ESC7: FCOMIP")); + FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); + FPU_FPOP(); + break; + default: + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FILD (WORD) */ + TRACEOUT(("FILD SINT16")); + FPU_PREP_PUSH(); + FPU_FLD_I16(madr,FPU_STAT_TOP); + break; + case 1: /* FISTTP (WORD) */ + { + FP_RND oldrnd = FPU_STAT.round; + FPU_STAT.round = ROUND_Down; + FPU_FST_I16(madr); + FPU_STAT.round = oldrnd; + } + FPU_FPOP(); + break; + case 2: /* FIST (WORD) */ + TRACEOUT(("FIST SINT16")); + FPU_FST_I16(madr); + break; + case 3: /* FISTP (WORD) */ + TRACEOUT(("FISTP SINT16")); + FPU_FST_I16(madr); + FPU_FPOP(); + break; + + case 4: /* FBLD (BCD) */ + TRACEOUT(("FBLD packed BCD")); + FPU_PREP_PUSH(); + FPU_FBLD(madr,FPU_STAT_TOP); + break; + + case 5: /* FILD (QWORD) */ + TRACEOUT(("FILD SINT64")); + FPU_PREP_PUSH(); + FPU_FLD_I64(madr,FPU_STAT_TOP); + break; + + case 6: /* FBSTP (BCD) */ + TRACEOUT(("FBSTP packed BCD")); + FPU_FBST(madr); + FPU_FPOP(); + break; + + case 7: /* FISTP (QWORD) */ + TRACEOUT(("FISTP SINT64")); + FPU_FST_I64(madr); + FPU_FPOP(); + break; + + default: + break; + } + } +} +#endif diff --git a/i386c/ia32/instructions/fpu/fpemul_softfloat.c b/i386c/ia32/instructions/fpu/fpemul_softfloat.c old mode 100755 new mode 100644 index 2b70500d..d45f9668 --- a/i386c/ia32/instructions/fpu/fpemul_softfloat.c +++ b/i386c/ia32/instructions/fpu/fpemul_softfloat.c @@ -1,1851 +1,1851 @@ -/* - * Copyright (c) 2012 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -/* - * modified by SimK - */ - -#include "compiler.h" - -#if defined(USE_FPU) && defined(SUPPORT_FPU_SOFTFLOAT) - -#include -#include -#include "ia32/cpu.h" -#include "ia32/ia32.mcr" - -#include "ia32/instructions/fpu/fp.h" -#include "ia32/instructions/fpu/fpumem.h" -#ifdef USE_SSE -#include "ia32/instructions/sse/sse.h" -#endif - - // softfloat.hのインクルードはcpu.hにあります - - /* - Short Real - 31: sign (符号) - 30-23: exp-8 (指数部: exponet) - 22-00: num-23 (小数部) - - Long Real - 63: sign - 62-52: exp-11 - 51-00: num-52 - - Temp Real - 79: sign - 78-64: exp-15 - 63: 1(?) - 62-00: num-63 - - -- - 指数部: - 2 の 0 乗のとき 0111 1111 となる - 1000 0001: +2 乗 - 1000 0000: +1 乗 - 0111 1111: 0 乗 - 0111 1110: -1 乗 - - 仮数部: - 2 を基数として整数部が一桁になるように正規化した数の 2 進数表現となる。 - 正規化によって仮数部の最上位ビットは常に 1 になるので実際に用意しておく - 必要はなく、倍精度の 52 ビットであれば最上位の 1 を hidden bit にして - 含めなければ、53 ビット分の情報が含まれることになる。 - - 小数の二進数表現: - 0.1000 1/2 = 0.5 - 0.0100 1/(2*2) = 0.25 - 0.0010 1/(2*2*2) = 0.125 - 0.0001 1/(2*2*2*2) = 0.0625 - */ - -#if 1 -#undef TRACEOUT -#define TRACEOUT(s) (void)(s) -#endif /* 0 */ - -#define FPU_WORKCLOCK 6 - -#define PI 3.1415926535897932384626433832795 -#define L2E 1.4426950408889634073599246810019 -#define L2T 3.3219280948873623478703194294894 -#define LN2 0.6931471805599453094172321214582 -#define LG2 0.3010299956639811952137388947245 - -static INLINE void FPU_SetCW(UINT16 cword) -{ - FPU_CTRLWORD = cword & 0x7FFF; - FPU_STAT.round = (FP_RND)((cword >> 10) & 3); - switch (FPU_STAT.round) { - case ROUND_Nearest: - float_rounding_mode = float_round_nearest_even; - break; - case ROUND_Down: - float_rounding_mode = float_round_down; - break; - case ROUND_Up: - float_rounding_mode = float_round_up; - break; - case ROUND_Chop: - float_rounding_mode = float_round_to_zero; - break; - default: - break; - } -} - -/* - * FPU exception - */ - -static void -fpu_check_NM_EXCEPTION(){ - // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる - if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { - EXCEPTION(NM_EXCEPTION, 0); - } -} -static void -fpu_check_NM_EXCEPTION2(){ - // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる - if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { - EXCEPTION(NM_EXCEPTION, 0); - } -} - -static void fpu_checkexception() { - if ((FPU_STATUSWORD & ~FPU_CTRLWORD) & 0x3F) { - EXCEPTION(MF_EXCEPTION, 0); - } -} - - -/* - * FPU memory access function - */ - -static void FPU_FLD80(UINT32 addr, UINT reg) -{ - *((REG80*)FPU_STAT.reg[reg].b) = fpu_memoryread_f(addr); -} - -static void FPU_FLD_F32(UINT32 addr, UINT reg) { - FPU_STAT.reg[reg].d = c_float_to_floatx80(fpu_memoryread_f32(addr)); -} - -static void FPU_FLD_F64(UINT32 addr, UINT reg) { - FPU_STAT.reg[reg].d = c_double_to_floatx80(fpu_memoryread_f64(addr)); -} - -static void FPU_FLD_F80(UINT32 addr) { - FPU_FLD80(addr, FPU_STAT_TOP); -} - -static void FPU_FLD_I16(UINT32 addr, UINT reg) { - FPU_STAT.reg[reg].d = int32_to_floatx80((SINT32)((SINT16)fpu_memoryread_w(addr))); -} - -static void FPU_FLD_I32(UINT32 addr, UINT reg) { - FPU_STAT.reg[reg].d = int32_to_floatx80((SINT32)fpu_memoryread_d(addr)); -} - -static void FPU_FLD_I64(UINT32 addr, UINT reg) { - FPU_STAT.reg[reg].d = int64_to_floatx80((SINT64)fpu_memoryread_q(addr)); -} - -static void FPU_FBLD(UINT32 addr, UINT reg) -{ - int i; - int tmp; - - REG80 bcdbuf; - SINT64 val = 0; - UINT8 in = 0; - - // 80bitまとめて読み取り - bcdbuf = fpu_memoryread_f(addr); - - // 0〜8byte目の処理 BCD - for (i = 8; i >= 0; i--) { - in = bcdbuf.b[i]; - tmp = ((in >> 4) & 0xf) * 10 + (in & 0xf); - val = val * 100 + tmp; - } - - // 9byte目は符号のみ意味がある - if (bcdbuf.b[9] & 0x80) { - val = -val; - } - - FPU_STAT.reg[reg].d = int64_to_floatx80(val); -} - -static INLINE void FPU_FLD_F32_EA(UINT32 addr) { - FPU_FLD_F32(addr, 8); -} -static INLINE void FPU_FLD_F64_EA(UINT32 addr) { - FPU_FLD_F64(addr, 8); -} -static INLINE void FPU_FLD_I32_EA(UINT32 addr) { - FPU_FLD_I32(addr, 8); -} -static INLINE void FPU_FLD_I16_EA(UINT32 addr) { - FPU_FLD_I16(addr, 8); -} - - -static void FPU_ST80(UINT32 addr, UINT reg) -{ - fpu_memorywrite_f(addr, (REG80*)FPU_STAT.reg[reg].b); -} - -static void FPU_FST_F32(UINT32 addr) { - fpu_memorywrite_f32(addr, floatx80_to_c_float(FPU_STAT.reg[FPU_STAT_TOP].d)); -} - -static void FPU_FST_F64(UINT32 addr) { - fpu_memorywrite_f64(addr, floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d)); -} - -static void FPU_FST_F80(UINT32 addr) { - FPU_ST80(addr, FPU_STAT_TOP); -} - -static void FPU_FST_I16(UINT32 addr) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - fpu_memorywrite_w(addr, (UINT16)floatx80_to_int16_np2(FPU_STAT.reg[FPU_STAT_TOP].d)); - FPU_STATUSWORD |= float_exception_flags; -} - -static void FPU_FST_I32(UINT32 addr) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - fpu_memorywrite_d(addr, (UINT32)floatx80_to_int32_np2(FPU_STAT.reg[FPU_STAT_TOP].d)); - FPU_STATUSWORD |= float_exception_flags; -} - -static void FPU_FST_I64(UINT32 addr) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - fpu_memorywrite_q(addr, (UINT64)floatx80_to_int64_np2(FPU_STAT.reg[FPU_STAT_TOP].d)); - FPU_STATUSWORD |= float_exception_flags; -} - -static void FPU_FBST(UINT32 addr) -{ - SINT64 val; - REG80 bcdbuf = { 0 }; - UINT i; - - signed char oldrnd = float_rounding_mode; - float_rounding_mode = float_round_down; - - val = floatx80_to_int64(FPU_STAT.reg[FPU_STAT_TOP].d); - - // 9byte目は符号のみ意味がある - if (val < 0) - { - bcdbuf.b[9] = 0x80; - val = -val; - } - - // 0〜8byte目の処理 BCD - for (i = 0; i < 9; i++) { - bcdbuf.b[i] = (UINT8)(val % 10); - val /= 10; - bcdbuf.b[i] |= (UINT8)(val % 10) << 4; - val /= 10; - } - - // 80bitまとめて書き込み - fpu_memorywrite_f(addr, &bcdbuf); - - float_rounding_mode = oldrnd; - FPU_STATUSWORD |= float_exception_flags; -} - - -/* - * FPU interface - */ - -static void -FPU_FINIT(void) -{ - int i; - FPU_SetCW(0x37F); - FPU_STATUSWORD = 0; - FPU_STAT_TOP=FP_TOP_GET(); - for(i=0;i<8;i++){ - // Emptyセットしてもレジスタの内容は消してはいけない - FPU_STAT.tag[i] = TAG_Empty; - } - FPU_STAT.tag[8] = TAG_Valid; // dummy - FPU_STAT.mmxenable = 0; -} -void SF_FPU_FINIT(void){ - int i; - FPU_FINIT(); - for(i=0;i<8;i++){ - FPU_STAT.tag[i] = TAG_Empty; - FPU_STAT.reg[i].l.ext = 0; - FPU_STAT.reg[i].l.lower = 0; - FPU_STAT.reg[i].l.upper = 0; - } -} - -static void FPU_FLDCW(UINT32 addr) -{ - UINT16 temp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, addr); - FPU_SetCW(temp); -} - -static UINT16 FPU_GetTag(void) -{ - UINT i; - - UINT16 tag = 0; - for (i = 0; i < 8; i++) - tag |= ((FPU_STAT.tag[i] & 3) << (2 * i)); - return tag; -} -static UINT8 FPU_GetTag8(void) -{ - UINT i; - - UINT8 tag = 0; - for (i = 0; i < 8; i++) - tag |= ((FPU_STAT.tag[i] == TAG_Empty ? 0 : 1) << (i)); - return tag; -} - -static INLINE void FPU_SetTag(UINT16 tag) -{ - UINT i; - - for (i = 0; i < 8; i++) { - FPU_STAT.tag[i] = (FP_TAG)((tag >> (2 * i)) & 3); - - } -} -static INLINE void FPU_SetTag8(UINT8 tag) -{ - UINT i; - - for (i = 0; i < 8; i++) { - FPU_STAT.tag[i] = (((tag >> i) & 1) == 0 ? TAG_Empty : TAG_Valid); - } -} - -static void FPU_prepush(void) { - FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; - if(FPU_STAT.tag[FPU_STAT_TOP] == TAG_Valid){ - FPU_STATUSWORD |= FP_C1_FLAG | FP_SF_FLAG | FP_IE_FLAG; - }else{ - FPU_STATUSWORD &= ~FP_C1_FLAG; - } - FPU_STAT.tag[FPU_STAT_TOP] = TAG_Valid; -} -static void FPU_push(floatx80 in) { - FPU_prepush(); - FPU_STAT.reg[FPU_STAT_TOP].d = in; -} - -static void FPU_pop(void) { - if(FPU_STAT.tag[FPU_STAT_TOP] == TAG_Empty){ - FPU_STATUSWORD |= FP_SF_FLAG | FP_IE_FLAG; - } - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_STAT.tag[FPU_STAT_TOP] = TAG_Empty; - FPU_STAT.mmxenable = 0; - FPU_STAT_TOP = ((FPU_STAT_TOP + 1) & 7); -} - -/* - * FPU instruction - */ - - // レジスタ操作 -static void FPU_FST(UINT st, UINT other) { - FPU_STAT.tag[other] = FPU_STAT.tag[st]; - FPU_STAT.reg[other] = FPU_STAT.reg[st]; -} -static void FPU_FXCH(UINT st, UINT other) { - FP_TAG tag; - FP_REG reg; - - tag = FPU_STAT.tag[other]; - reg = FPU_STAT.reg[other]; - FPU_STAT.tag[other] = FPU_STAT.tag[st]; - FPU_STAT.reg[other] = FPU_STAT.reg[st]; - FPU_STAT.tag[st] = tag; - FPU_STAT.reg[st] = reg; -} -static void FPU_FLD1(void) { - FPU_prepush(); - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(1.0); -} -static void FPU_FLDL2T(void) { - FPU_prepush(); - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(L2T); -} -static void FPU_FLDL2E(void) { - FPU_prepush(); - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(L2E); -} -static void FPU_FLDPI(void) { - FPU_prepush(); - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(PI); -} -static void FPU_FLDLG2(void) { - FPU_prepush(); - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(LG2); -} -static void FPU_FLDLN2(void) { - FPU_prepush(); - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(LN2); -} -static void FPU_FLDZ(void) { - FPU_prepush(); - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(0.0); - FPU_STAT.tag[FPU_STAT_TOP] = TAG_Zero; - FPU_STAT.mmxenable = 0; -} - -// 四則演算 -static void FPU_FADD(UINT op1, UINT op2) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[op1].d = floatx80_add(FPU_STAT.reg[op1].d, FPU_STAT.reg[op2].d); - FPU_STATUSWORD |= float_exception_flags; - return; -} -static void FPU_FMUL(UINT st, UINT other) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[st].d = floatx80_mul(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d); - FPU_STATUSWORD |= float_exception_flags; - return; -} -static void FPU_FSUB(UINT st, UINT other) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[st].d = floatx80_sub(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d); - return; -} -static void FPU_FSUBR(UINT st, UINT other) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[st].d = floatx80_sub(FPU_STAT.reg[other].d, FPU_STAT.reg[st].d); - FPU_STATUSWORD |= float_exception_flags; - return; -} -static void FPU_FDIV(UINT st, UINT other) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[st].d = floatx80_div(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d); - FPU_STATUSWORD |= float_exception_flags; - return; -} -static void FPU_FDIVR(UINT st, UINT other) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[st].d = floatx80_div(FPU_STAT.reg[other].d, FPU_STAT.reg[st].d); - FPU_STATUSWORD |= float_exception_flags; - return; -} -static INLINE void FPU_FADD_EA(UINT op1) { - FPU_FADD(op1, 8); -} -static INLINE void FPU_FMUL_EA(UINT op1) { - FPU_FMUL(op1, 8); -} -static INLINE void FPU_FSUB_EA(UINT op1) { - FPU_FSUB(op1, 8); -} -static INLINE void FPU_FSUBR_EA(UINT op1) { - FPU_FSUBR(op1, 8); -} -static INLINE void FPU_FDIV_EA(UINT op1) { - FPU_FDIV(op1, 8); -} -static INLINE void FPU_FDIVR_EA(UINT op1) { - FPU_FDIVR(op1, 8); -} -static void FPU_FPREM(void) { - floatx80 val, div; - SINT64 qint; - - float_exception_flags = (FPU_STATUSWORD & 0x3f); - val = FPU_STAT.reg[FPU_STAT_TOP].d; - div = FPU_STAT.reg[FPU_ST(1)].d; - qint = floatx80_to_int64_round_to_zero(floatx80_div(val, div)); // int(被除数 / 除数) = 商 - - FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_sub(val, floatx80_mul(int64_to_floatx80(qint), div)); // 被除数 - 商 x 除数 = 剰余 - FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C1_FLAG | FP_C2_FLAG | FP_C3_FLAG); - if(qint & 4) FPU_STATUSWORD |= FP_C0_FLAG; // 商のbit2 - if(qint & 2) FPU_STATUSWORD |= FP_C3_FLAG; // 商のbit1 - if(qint & 1) FPU_STATUSWORD |= FP_C1_FLAG; // 商のbit0 - // C2クリアで完了扱い - FPU_STATUSWORD |= float_exception_flags; -} - -static void FPU_FPREM1(void) { - floatx80 val, div, q; - SINT64 qint; - signed char oldrnd = float_rounding_mode; - - // IEEE 754 剰余 商を最も近い整数値とする。余りが負値になることが有り得る - - float_exception_flags = (FPU_STATUSWORD & 0x3f); - val = FPU_STAT.reg[FPU_STAT_TOP].d; - div = FPU_STAT.reg[FPU_ST(1)].d; - q = floatx80_add(floatx80_div(val, div), c_double_to_floatx80(0.5)); // floor(値 + 0.5)で四捨五入 厳密には負値の境界で違うが微々たる差として気にしないことにする。 - float_rounding_mode = float_round_down; - qint = floatx80_to_int64(q); // 四捨五入(被除数 / 除数) = 最も整数に近い商 - - FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_sub(val, floatx80_mul(int64_to_floatx80(qint), div)); // 被除数 - 商 x 除数 = 剰余 - FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C1_FLAG | FP_C2_FLAG | FP_C3_FLAG); - if(qint & 4) FPU_STATUSWORD |= FP_C0_FLAG; // 商のbit2 - if(qint & 2) FPU_STATUSWORD |= FP_C3_FLAG; // 商のbit1 - if(qint & 1) FPU_STATUSWORD |= FP_C1_FLAG; // 商のbit0 - // C2クリアで完了扱い - float_rounding_mode = oldrnd; - FPU_STATUSWORD |= float_exception_flags; -} - -// 数学関数 -static void FPU_FSIN(void) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(sin(floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d))); - FPU_STATUSWORD &= ~FP_C2_FLAG; - FPU_STATUSWORD |= float_exception_flags; - return; -} -static void FPU_FCOS(void) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(cos(floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d))); - FPU_STATUSWORD &= ~FP_C2_FLAG; - FPU_STATUSWORD |= float_exception_flags; - return; -} -static void FPU_FSINCOS(void) { - double temp; - - float_exception_flags = (FPU_STATUSWORD & 0x3f); - temp = floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d); - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(sin(temp)); - FPU_push(c_double_to_floatx80(cos(temp))); - FPU_STATUSWORD &= ~FP_C2_FLAG; - FPU_STATUSWORD |= float_exception_flags; - return; -} -static void FPU_FPTAN(void) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(tan(floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d))); - FPU_push(c_double_to_floatx80(1.0)); - FPU_STATUSWORD &= ~FP_C2_FLAG; - FPU_STATUSWORD |= float_exception_flags; - return; -} -static void FPU_FPATAN(void) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[FPU_ST(1)].d = c_double_to_floatx80(atan2(floatx80_to_c_double(FPU_STAT.reg[FPU_ST(1)].d), floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d))); - FPU_pop(); - FPU_STATUSWORD |= float_exception_flags; - return; -} -static void FPU_FSQRT(void) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_sqrt(FPU_STAT.reg[FPU_STAT_TOP].d); - FPU_STATUSWORD |= float_exception_flags; - return; -} -static void FPU_FRNDINT(void) { - float_exception_flags = (FPU_STATUSWORD & 0x3f); - FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_round_to_int(FPU_STAT.reg[FPU_STAT_TOP].d); - FPU_STATUSWORD |= float_exception_flags; -} -static void FPU_F2XM1(void) { - FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(pow(2.0, floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d)) - 1); -} -static void FPU_FYL2X(void) { - FPU_STAT.reg[FPU_ST(1)].d = floatx80_mul(FPU_STAT.reg[FPU_ST(1)].d, c_double_to_floatx80(log(floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d)) / log(2.0))); - FPU_pop(); -} -static void FPU_FYL2XP1(void) { - FPU_STAT.reg[FPU_ST(1)].d = floatx80_mul(FPU_STAT.reg[FPU_ST(1)].d, c_double_to_floatx80(log(floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d) + 1.0) / log(2.0))); - FPU_pop(); -} -static void FPU_FSCALE(void) { - FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_mul(FPU_STAT.reg[FPU_STAT_TOP].d, c_double_to_floatx80(pow(2.0, floatx80_to_c_double(FPU_STAT.reg[FPU_ST(1)].d)))); -} -static void FPU_FCHS(void) { - FPU_STAT.reg[FPU_STAT_TOP].b[9] ^= 0x80; -} -static void FPU_FABS(void) { - FPU_STAT.reg[FPU_STAT_TOP].b[9] &= ~0x80; -} - -// 比較 -static void FPU_FCOM(UINT st, UINT other) { - FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C2_FLAG | FP_C3_FLAG); - if (((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || - ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero)) || - (floatx80_is_nan(FPU_STAT.reg[st].d) || floatx80_is_nan(FPU_STAT.reg[other].d))) { - FPU_STATUSWORD |= FP_C3_FLAG|FP_C2_FLAG|FP_C0_FLAG; - } - else if (floatx80_eq(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d)) { - FPU_STATUSWORD |= FP_C3_FLAG; - } - else if (floatx80_lt(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d)) { - FPU_STATUSWORD |= FP_C0_FLAG; - } -} -static void FPU_FCOMI(UINT st, UINT other) { - CPU_FLAGL &= ~(Z_FLAG|P_FLAG|C_FLAG); - if (((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || - ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero)) || - (floatx80_is_nan(FPU_STAT.reg[st].d) || floatx80_is_nan(FPU_STAT.reg[other].d))) { - CPU_FLAGL |= Z_FLAG|P_FLAG|C_FLAG; - } - else if (floatx80_eq(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d)) { - CPU_FLAGL |= Z_FLAG; - } - else if (floatx80_lt(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d)) { - CPU_FLAGL |= C_FLAG; - } -} -static void FPU_FUCOM(UINT st, UINT other) { - // 例外絡みの挙動が違うがほぼ同じとしてスルー - FPU_FCOM(st, other); -} -static void FPU_FUCOMI(UINT st, UINT other) { - // 例外絡みの挙動が違うがほぼ同じとしてスルー - FPU_FCOMI(st, other); -} -static INLINE void FPU_FCOM_EA(UINT op1) { - FPU_FCOM(op1, 8); -} -static void FPU_FTST(void) { - FPU_STAT.reg[8].d = c_double_to_floatx80(0.0); - FPU_FCOM(FPU_STAT_TOP, 8); -} - -// 条件付きコピー -static void FPU_FCMOVB(UINT st, UINT other) { - if (CPU_FLAGL & C_FLAG) { - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVE(UINT st, UINT other) { - if (CPU_FLAGL & Z_FLAG) { - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVBE(UINT st, UINT other) { - if (CPU_FLAGL & (C_FLAG | Z_FLAG)) { - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVU(UINT st, UINT other) { - if (CPU_FLAGL & P_FLAG) { - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVNB(UINT st, UINT other) { - if (!(CPU_FLAGL & C_FLAG)) { - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVNE(UINT st, UINT other) { - if (!(CPU_FLAGL & Z_FLAG)) { - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVNBE(UINT st, UINT other) { - if (!(CPU_FLAGL & (C_FLAG | Z_FLAG))) { - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} -static void FPU_FCMOVNU(UINT st, UINT other) { - if (!(CPU_FLAGL & P_FLAG)) { - FPU_STAT.tag[st] = FPU_STAT.tag[other]; - FPU_STAT.reg[st] = FPU_STAT.reg[other]; - } -} - -// 浮動小数点数操作 -static void FPU_FXAM(void) { - FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C1_FLAG | FP_C2_FLAG | FP_C3_FLAG); - if (FPU_STAT.reg[FPU_STAT_TOP].d.high & 0x8000) { - FPU_STATUSWORD |= FP_C1_FLAG; - } - - if (FPU_STAT.tag[FPU_STAT_TOP] == TAG_Empty) { - FPU_STATUSWORD |= FP_C3_FLAG; - FPU_STATUSWORD |= FP_C0_FLAG; - } - else if (floatx80_is_nan(FPU_STAT.reg[FPU_STAT_TOP].d)) { - FPU_STATUSWORD |= FP_C0_FLAG; - } - else if (floatx80_is_inf(FPU_STAT.reg[FPU_STAT_TOP].d)) { - FPU_STATUSWORD |= FP_C2_FLAG; - FPU_STATUSWORD |= FP_C0_FLAG; - } - else if (floatx80_eq(FPU_STAT.reg[FPU_STAT_TOP].d, c_double_to_floatx80(0.0))) { - FPU_STATUSWORD |= FP_C3_FLAG; - } - else { - FPU_STATUSWORD |= FP_C2_FLAG; - } -} - -static void FPU_FXTRACT(void) { - SINT32 expval; - floatx80 fracval; - - fracval = FPU_STAT.reg[FPU_STAT_TOP].d; - expval = (SINT32)((UINT16)fracval.high & 0x7FFF) - 0x3FFF; // 指数部分を抽出、バイアス分を引く - fracval.high = (SINT16)(((UINT16)fracval.high & 0x8000) | 0x3FFF); // 符号は残し、指数部分を0x3FFF(バイアス分=0)にして仮数だけにする - FPU_STAT.reg[FPU_STAT_TOP].d = int64_to_floatx80(expval); // 指数の書き込み - FPU_push(fracval); // 仮数のpush -} - -// 環境ロード・ストア -static void FPU_FSTENV(UINT32 addr) -{ - FP_TOP_SET(FPU_STAT_TOP); - - switch ((CPU_CR0 & 1) | (CPU_INST_OP32 ? 0x100 : 0x000)) - { - case 0x000: case 0x001: - fpu_memorywrite_w(addr + 0, FPU_CTRLWORD); - fpu_memorywrite_w(addr + 2, FPU_STATUSWORD); - fpu_memorywrite_w(addr + 4, FPU_GetTag()); - fpu_memorywrite_w(addr + 10, FPU_LASTINSTOP); - break; - - case 0x100: case 0x101: - fpu_memorywrite_d(addr + 0, (UINT32)(FPU_CTRLWORD)); - fpu_memorywrite_d(addr + 4, (UINT32)(FPU_STATUSWORD)); - fpu_memorywrite_d(addr + 8, (UINT32)(FPU_GetTag())); - fpu_memorywrite_d(addr + 20, FPU_LASTINSTOP); - break; - } -} -static void FPU_FLDENV(UINT32 addr) -{ - switch ((CPU_CR0 & 1) | (CPU_INST_OP32 ? 0x100 : 0x000)) { - case 0x000: case 0x001: - FPU_SetCW(fpu_memoryread_w(addr + 0)); - FPU_STATUSWORD = fpu_memoryread_w(addr + 2); - FPU_SetTag(fpu_memoryread_w(addr + 4)); - FPU_LASTINSTOP = fpu_memoryread_w(addr + 10); - break; - - case 0x100: case 0x101: - FPU_SetCW((UINT16)fpu_memoryread_d(addr + 0)); - FPU_STATUSWORD = (UINT16)fpu_memoryread_d(addr + 4); - FPU_SetTag((UINT16)fpu_memoryread_d(addr + 8)); - FPU_LASTINSTOP = (UINT16)fpu_memoryread_d(addr + 20); - break; - } - FPU_STAT_TOP = FP_TOP_GET(); -} -static void FPU_FSAVE(UINT32 addr) -{ - UINT start; - UINT i; - - FPU_FSTENV(addr); - start = ((CPU_INST_OP32) ? 28 : 14); - for (i = 0; i < 8; i++) { - FPU_ST80(addr + start, FPU_ST(i)); - start += 10; - } - FPU_FINIT(); -} -static void FPU_FRSTOR(UINT32 addr) -{ - UINT start; - UINT i; - - FPU_FLDENV(addr); - start = ((CPU_INST_OP32) ? 28 : 14); - for (i = 0; i < 8; i++) { - FPU_FLD80(addr + start, FPU_ST(i)); - start += 10; - } -} -static void FPU_FXSAVE(UINT32 addr) { - UINT start; - UINT i; - - FP_TOP_SET(FPU_STAT_TOP); - fpu_memorywrite_w(addr + 0, FPU_CTRLWORD); - fpu_memorywrite_w(addr + 2, FPU_STATUSWORD); - fpu_memorywrite_b(addr + 4, FPU_GetTag8()); -#ifdef USE_SSE - fpu_memorywrite_d(addr + 24, SSE_MXCSR); -#endif - start = 32; - for (i = 0; i < 8; i++) { - FPU_ST80(addr + start, FPU_ST(i)); - start += 16; - } -#ifdef USE_SSE - start = 160; - for (i = 0; i < 8; i++) { - fpu_memorywrite_q(addr + start + 0, SSE_XMMREG(i).ul64[0]); - fpu_memorywrite_q(addr + start + 8, SSE_XMMREG(i).ul64[1]); - start += 16; - } -#endif -} -static void FPU_FXRSTOR(UINT32 addr) { - UINT start; - UINT i; - - FPU_SetCW(fpu_memoryread_w(addr + 0)); - FPU_STATUSWORD = fpu_memoryread_w(addr + 2); - FPU_SetTag8(fpu_memoryread_b(addr + 4)); - FPU_STAT_TOP = FP_TOP_GET(); -#ifdef USE_SSE - SSE_MXCSR = fpu_memoryread_d(addr + 24); -#endif - start = 32; - for (i = 0; i < 8; i++) { - FPU_FLD80(addr + start, FPU_ST(i)); - start += 16; - } -#ifdef USE_SSE - start = 160; - for (i = 0; i < 8; i++) { - SSE_XMMREG(i).ul64[0] = fpu_memoryread_q(addr + start + 0); - SSE_XMMREG(i).ul64[1] = fpu_memoryread_q(addr + start + 8); - start += 16; - } -#endif -} -void SF_FPU_FXSAVERSTOR(void) { - UINT32 op; - UINT idx, sub; - UINT32 maddr; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - switch (idx) { - case 0: // FXSAVE - fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し - maddr = calc_ea_dst(op); - FPU_FXSAVE(maddr); - break; - case 1: // FXRSTOR - fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し - maddr = calc_ea_dst(op); - FPU_FXRSTOR(maddr); - break; -#ifdef USE_SSE - case 2: // LDMXCSR - maddr = calc_ea_dst(op); - SSE_LDMXCSR(maddr); - break; - case 3: // STMXCSR - maddr = calc_ea_dst(op); - SSE_STMXCSR(maddr); - break; - case 4: // SFENCE - SSE_SFENCE(); - break; - case 5: // LFENCE - SSE_LFENCE(); - break; - case 6: // MFENCE - SSE_MFENCE(); - break; - case 7: // CLFLUSH; - SSE_CLFLUSH(op); - break; -#endif - default: - ia32_panic("invalid opcode = %02x\n", op); - break; - } -} - -static void EA_TREE(UINT op) -{ - UINT idx; - - idx = (op >> 3) & 7; - - switch (idx) { - case 0: /* FADD (単精度実数) */ - TRACEOUT(("FADD EA")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FADD_EA(FPU_STAT_TOP); - break; - case 1: /* FMUL (単精度実数) */ - TRACEOUT(("FMUL EA")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FMUL_EA(FPU_STAT_TOP); - break; - case 2: /* FCOM (単精度実数) */ - TRACEOUT(("FCOM EA")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCOM_EA(FPU_STAT_TOP); - break; - case 3: /* FCOMP (単精度実数) */ - TRACEOUT(("FCOMP EA")); - FPU_FCOM_EA(FPU_STAT_TOP); - FPU_pop(); - break; - case 4: /* FSUB (単精度実数) */ - TRACEOUT(("FSUB EA")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FSUB_EA(FPU_STAT_TOP); - break; - case 5: /* FSUBR (単精度実数) */ - TRACEOUT(("FSUBR EA")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FSUBR_EA(FPU_STAT_TOP); - break; - case 6: /* FDIV (単精度実数) */ - TRACEOUT(("FDIV EA")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FDIV_EA(FPU_STAT_TOP); - break; - case 7: /* FDIVR (単精度実数) */ - TRACEOUT(("FDIVR EA")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FDIVR_EA(FPU_STAT_TOP); - break; - default: - break; - } -} - -// d8 -void -SF_ESC0(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU d8 %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FADD */ - TRACEOUT(("FADD")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FADD(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 1: /* FMUL */ - TRACEOUT(("FMUL")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FMUL(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FCOM */ - TRACEOUT(("FCOM")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCOMP */ - TRACEOUT(("FCOMP")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - FPU_pop(); - break; - case 4: /* FSUB */ - TRACEOUT(("FSUB")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FSUB(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 5: /* FSUBR */ - TRACEOUT(("FSUBR")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FSUBR(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 6: /* FDIV */ - TRACEOUT(("FDIV")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FDIV(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 7: /* FDIVR */ - TRACEOUT(("FDIVR")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FDIVR(FPU_STAT_TOP,FPU_ST(sub)); - break; - } - } else { - madr = calc_ea_dst(op); - FPU_FLD_F32_EA(madr); - EA_TREE(op); - } -} - -// d9 -void -SF_ESC1(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU d9 %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - if(!(op < 0xc0 && idx>=4)){ - fpu_checkexception(); - } - if (op >= 0xc0) - { - switch (idx) { - case 0: /* FLD ST(0), ST(i) */ - { - UINT reg_from; - - TRACEOUT(("FLD STi")); - reg_from = FPU_ST(sub); - FPU_prepush(); - FPU_FST(reg_from, FPU_STAT_TOP); - } - break; - - case 1: /* FXCH ST(0), ST(i) */ - TRACEOUT(("FXCH STi")); - FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); - break; - - case 2: /* FNOP */ - TRACEOUT(("FNOP")); - break; - - case 3: /* FSTP STi */ - TRACEOUT(("FSTP STi")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - FPU_pop(); - break; - - case 4: - switch (sub) { - case 0x0: /* FCHS */ - TRACEOUT(("FCHS")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCHS(); - break; - - case 0x1: /* FABS */ - TRACEOUT(("FABS")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FABS(); - break; - - case 0x2: /* UNKNOWN */ - case 0x3: /* ILLEGAL */ - break; - - case 0x4: /* FTST */ - TRACEOUT(("FTST")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FTST(); - break; - - case 0x5: /* FXAM */ - TRACEOUT(("FXAM")); - FPU_FXAM(); - break; - - case 0x06: /* FTSTP (cyrix)*/ - case 0x07: /* UNKNOWN */ - break; - } - break; - - case 5: - switch (sub) { - case 0x0: /* FLD1 */ - TRACEOUT(("FLD1")); - FPU_FLD1(); - break; - - case 0x1: /* FLDL2T */ - TRACEOUT(("FLDL2T")); - FPU_FLDL2T(); - break; - - case 0x2: /* FLDL2E */ - TRACEOUT(("FLDL2E")); - FPU_FLDL2E(); - break; - - case 0x3: /* FLDPI */ - TRACEOUT(("FLDPI")); - FPU_FLDPI(); - break; - - case 0x4: /* FLDLG2 */ - TRACEOUT(("FLDLG2")); - FPU_FLDLG2(); - break; - - case 0x5: /* FLDLN2 */ - TRACEOUT(("FLDLN2")); - FPU_FLDLN2(); - break; - - case 0x6: /* FLDZ */ - TRACEOUT(("FLDZ")); - FPU_FLDZ(); - break; - - case 0x07: /* ILLEGAL */ - break; - } - break; - - case 6: - switch (sub) { - case 0x0: /* F2XM1 */ - TRACEOUT(("F2XM1")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_F2XM1(); - break; - - case 0x1: /* FYL2X */ - TRACEOUT(("FYL2X")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FYL2X(); - break; - - case 0x2: /* FPTAN */ - TRACEOUT(("FPTAN")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FPTAN(); - break; - - case 0x3: /* FPATAN */ - TRACEOUT(("FPATAN")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FPATAN(); - break; - - case 0x4: /* FXTRACT */ - TRACEOUT(("FXTRACT")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FXTRACT(); - break; - - case 0x5: /* FPREM1 */ - TRACEOUT(("FPREM1")); - FPU_FPREM1(); - break; - - case 0x6: /* FDECSTP */ - TRACEOUT(("FDECSTP")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; - break; - - case 0x7: /* FINCSTP */ - TRACEOUT(("FINCSTP")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_STAT_TOP = (FPU_STAT_TOP + 1) & 7; - break; - } - break; - - case 7: - switch (sub) { - case 0x0: /* FPREM */ - TRACEOUT(("FPREM")); - FPU_FPREM(); - break; - - case 0x1: /* FYL2XP1 */ - TRACEOUT(("FYL2XP1")); - FPU_FYL2XP1(); - break; - - case 0x2: /* FSQRT */ - TRACEOUT(("FSQRT")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FSQRT(); - break; - - case 0x3: /* FSINCOS */ - TRACEOUT(("FSINCOS")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FSINCOS(); - break; - - case 0x4: /* FRNDINT */ - TRACEOUT(("FRNDINT")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FRNDINT(); - break; - - case 0x5: /* FSCALE */ - TRACEOUT(("FSCALE")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FSCALE(); - break; - - case 0x6: /* FSIN */ - TRACEOUT(("FSIN")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FSIN(); - break; - - case 0x7: /* FCOS */ - TRACEOUT(("FCOS")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCOS(); - break; - } - break; - - default: - ia32_panic("ESC1: invalid opcode = %02x\n", op); - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FLD (単精度実数) */ - TRACEOUT(("FLD float")); - FPU_prepush(); - FPU_FLD_F32(madr,FPU_STAT_TOP); - break; - - case 1: /* UNKNOWN */ - break; - - case 2: /* FST (単精度実数) */ - TRACEOUT(("FST float")); - FPU_FST_F32(madr); - FPU_STATUSWORD &= ~FP_C1_FLAG; - break; - - case 3: /* FSTP (単精度実数) */ - TRACEOUT(("FSTP float")); - FPU_FST_F32(madr); - FPU_pop(); - break; - - case 4: /* FLDENV */ - TRACEOUT(("FLDENV")); - FPU_FLDENV(madr); - break; - - case 5: /* FLDCW */ - TRACEOUT(("FLDCW")); - FPU_FLDCW(madr); - break; - - case 6: /* FSTENV */ - TRACEOUT(("FSTENV")); - FPU_FSTENV(madr); - break; - - case 7: /* FSTCW */ - TRACEOUT(("FSTCW/FNSTCW")); - fpu_memorywrite_w(madr,FPU_CTRLWORD); - break; - - default: - break; - } - } -} - -// da -void -SF_ESC2(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU da %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FCMOVB */ - TRACEOUT(("ESC2: FCMOVB")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCMOVB(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 1: /* FCMOVE */ - TRACEOUT(("ESC2: FCMOVE")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCMOVE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FCMOVBE */ - TRACEOUT(("ESC2: FCMOVBE")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCMOVBE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCMOVU */ - TRACEOUT(("ESC2: FCMOVU")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCMOVU(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 5: - switch (sub) { - case 1: /* FUCOMPP */ - TRACEOUT(("FUCOMPP")); - FPU_FUCOM(FPU_STAT_TOP,FPU_ST(1)); - FPU_pop(); - FPU_pop(); - break; - - default: - break; - } - break; - - default: - break; - } - } else { - madr = calc_ea_dst(op); - FPU_FLD_I32_EA(madr); - EA_TREE(op); - } -} - -// db -void -SF_ESC3(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU db %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - if(!(op >= 0xc0 && idx==4)){ - fpu_checkexception(); - } - if (op >= 0xc0) - { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FCMOVNB */ - TRACEOUT(("ESC3: FCMOVNB")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCMOVNB(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 1: /* FCMOVNE */ - TRACEOUT(("ESC3: FCMOVNE")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCMOVNE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FCMOVNBE */ - TRACEOUT(("ESC3: FCMOVNBE")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCMOVNBE(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCMOVNU */ - TRACEOUT(("ESC3: FCMOVNU")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCMOVNU(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 4: - switch (sub) { - case 0: /* FNENI */ - case 1: /* FNDIS */ - break; - - case 2: /* FCLEX */ - TRACEOUT(("FCLEX")); - FPU_STATUSWORD &= 0x7f00; - break; - - case 3: /* FNINIT/FINIT */ - TRACEOUT(("FNINIT/FINIT")); - FPU_FINIT(); - break; - - case 4: /* FNSETPM */ - case 5: /* FRSTPM */ - // nop - break; - - default: - break; - } - break; - case 5: /* FUCOMI */ - TRACEOUT(("ESC3: FUCOMI")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 6: /* FCOMI */ - TRACEOUT(("ESC3: FCOMI")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); - break; - default: - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FILD (DWORD) */ - TRACEOUT(("FILD")); - FPU_prepush(); - FPU_FLD_I32(madr,FPU_STAT_TOP); - break; - - case 1: /* FISTTP (DWORD) */ - { - signed char oldrnd = float_rounding_mode; - float_rounding_mode = float_round_down; - FPU_FST_I32(madr); - float_rounding_mode = oldrnd; - } - FPU_pop(); - break; - - case 2: /* FIST (DWORD) */ - TRACEOUT(("FIST")); - FPU_FST_I32(madr); - FPU_STATUSWORD &= ~FP_C1_FLAG; - break; - - case 3: /* FISTP (DWORD) */ - TRACEOUT(("FISTP")); - FPU_FST_I32(madr); - FPU_pop(); - break; - - case 5: /* FLD (拡張実数) */ - TRACEOUT(("FLD 80 Bits Real")); - FPU_prepush(); - FPU_FLD_F80(madr); - break; - - case 7: /* FSTP (拡張実数) */ - TRACEOUT(("FSTP 80 Bits Real")); - FPU_FST_F80(madr); - FPU_pop(); - break; - - default: - break; - } - } -} - -// dc -void -SF_ESC4(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU dc %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(i), ST(0) */ - switch (idx) { - case 0: /* FADD */ - TRACEOUT(("ESC4: FADD")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); - break; - case 1: /* FMUL */ - TRACEOUT(("ESC4: FMUL")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); - break; - case 2: /* FCOM */ - TRACEOUT(("ESC4: FCOM")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCOMP */ - TRACEOUT(("ESC4: FCOMP")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - FPU_pop(); - break; - case 4: /* FSUBR */ - TRACEOUT(("ESC4: FSUBR")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); - break; - case 5: /* FSUB */ - TRACEOUT(("ESC4: FSUB")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); - break; - case 6: /* FDIVR */ - TRACEOUT(("ESC4: FDIVR")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); - break; - case 7: /* FDIV */ - TRACEOUT(("ESC4: FDIV")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); - break; - default: - break; - } - } else { - madr = calc_ea_dst(op); - FPU_FLD_F64_EA(madr); - EA_TREE(op); - } -} - -// dd -void -SF_ESC5(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU dd %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - fpu_check_NM_EXCEPTION(); - if(op >= 0xc0 || (idx!=4 && idx!=6 && idx!=7)){ - fpu_checkexception(); - } - if (op >= 0xc0) { - /* FUCOM ST(i), ST(0) */ - /* Fxxx ST(i) */ - switch (idx) { - case 0: /* FFREE */ - TRACEOUT(("FFREE")); - FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; - FPU_STAT.mmxenable = 0; - break; - case 1: /* FXCH */ - TRACEOUT(("FXCH")); - FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 2: /* FST */ - TRACEOUT(("FST")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - FPU_STATUSWORD &= ~FP_C1_FLAG; - break; - case 3: /* FSTP */ - TRACEOUT(("FSTP")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - FPU_pop(); - break; - case 4: /* FUCOM */ - TRACEOUT(("FUCOM")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 5: /* FUCOMP */ - TRACEOUT(("FUCOMP")); - FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); - FPU_pop(); - break; - - default: - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FLD (倍精度実数) */ - TRACEOUT(("FLD double real")); - FPU_prepush(); - FPU_FLD_F64(madr,FPU_STAT_TOP); - break; - case 1: /* FISTTP (QWORD) */ - { - signed char oldrnd = float_rounding_mode; - float_rounding_mode = float_round_down; - FPU_FST_I64(madr); - float_rounding_mode = oldrnd; - } - FPU_pop(); - break; - case 2: /* FST (倍精度実数) */ - TRACEOUT(("FST double real")); - FPU_FST_F64(madr); - FPU_STATUSWORD &= ~FP_C1_FLAG; - break; - case 3: /* FSTP (倍精度実数) */ - TRACEOUT(("FSTP double real")); - FPU_FST_F64(madr); - FPU_pop(); - break; - case 4: /* FRSTOR */ - TRACEOUT(("FRSTOR")); - FPU_FRSTOR(madr); - break; - case 6: /* FSAVE */ - TRACEOUT(("FSAVE")); - FPU_FSAVE(madr); - break; - - case 7: /* FSTSW */ - FP_TOP_SET(FPU_STAT_TOP); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, FPU_STATUSWORD); - break; - - default: - break; - } - } -} - -// de -void -SF_ESC6(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU de %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - fpu_checkexception(); - if (op >= 0xc0) { - /* Fxxx ST(i), ST(0) */ - switch (idx) { - case 0: /* FADDP */ - TRACEOUT(("FADDP")); - FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); - break; - case 1: /* FMULP */ - TRACEOUT(("FMULP")); - FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); - break; - case 2: /* FCOMP5 */ - TRACEOUT(("FCOMP5")); - FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); - break; - case 3: /* FCOMPP */ - TRACEOUT(("FCOMPP")); - if(sub != 1) { - return; - } - FPU_FCOM(FPU_STAT_TOP,FPU_ST(1)); - FPU_pop(); // 下コードと合わせて2回pop - break; - case 4: /* FSUBRP */ - TRACEOUT(("FSUBRP")); - FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); - break; - case 5: /* FSUBP */ - TRACEOUT(("FSUBP")); - FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); - break; - case 6: /* FDIVRP */ - TRACEOUT(("FDIVRP")); - FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); - if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ - return; // POPしないようにする - } - break; - case 7: /* FDIVP */ - TRACEOUT(("FDIVP")); - FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); - if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ - return; // POPしないようにする - } - break; - /*FALLTHROUGH*/ - default: - break; - } - FPU_pop(); - } else { - madr = calc_ea_dst(op); - FPU_FLD_I16_EA(madr); - EA_TREE(op); - } -} - -// df -void -SF_ESC7(void) -{ - UINT32 op, madr; - UINT idx, sub; - - CPU_WORKCLOCK(FPU_WORKCLOCK); - GET_MODRM_PCBYTE(op); - TRACEOUT(("use FPU df %.2x", op)); - idx = (op >> 3) & 7; - sub = (op & 7); - - fpu_check_NM_EXCEPTION(); - if(!(op >= 0xc0 && idx==4 && sub==0)){ - fpu_checkexception(); - } - if (op >= 0xc0) { - /* Fxxx ST(0), ST(i) */ - switch (idx) { - case 0: /* FFREEP */ - TRACEOUT(("FFREEP")); - FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; - FPU_STAT.mmxenable = 0; - FPU_pop(); - break; - case 1: /* FXCH */ - TRACEOUT(("FXCH")); - FPU_STATUSWORD &= ~FP_C1_FLAG; - FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); - break; - - case 2: - case 3: /* FSTP */ - TRACEOUT(("FSTP")); - FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); - FPU_pop(); - break; - - case 4: - switch (sub) - { - case 0: /* FSTSW AX */ - TRACEOUT(("FSTSW AX")); - FP_TOP_SET(FPU_STAT_TOP); - CPU_AX = FPU_STATUSWORD; - break; - - default: - break; - } - break; - case 5: /* FUCOMIP */ - TRACEOUT(("ESC7: FUCOMIP")); - FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); - FPU_pop(); - break; - case 6: /* FCOMIP */ - TRACEOUT(("ESC7: FCOMIP")); - FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); - FPU_pop(); - break; - default: - break; - } - } else { - madr = calc_ea_dst(op); - switch (idx) { - case 0: /* FILD (WORD) */ - TRACEOUT(("FILD SINT16")); - FPU_prepush(); - FPU_FLD_I16(madr,FPU_STAT_TOP); - break; - case 1: /* FISTTP (WORD) */ - { - signed char oldrnd = float_rounding_mode; - float_rounding_mode = float_round_down; - FPU_FST_I16(madr); - float_rounding_mode = oldrnd; - } - FPU_pop(); - break; - case 2: /* FIST (WORD) */ - TRACEOUT(("FIST SINT16")); - FPU_FST_I16(madr); - FPU_STATUSWORD &= ~FP_C1_FLAG; - break; - case 3: /* FISTP (WORD) */ - TRACEOUT(("FISTP SINT16")); - FPU_FST_I16(madr); - FPU_pop(); - break; - - case 4: /* FBLD (BCD) */ - TRACEOUT(("FBLD packed BCD")); - FPU_prepush(); - FPU_FBLD(madr,FPU_STAT_TOP); - break; - - case 5: /* FILD (QWORD) */ - TRACEOUT(("FILD SINT64")); - FPU_prepush(); - FPU_FLD_I64(madr,FPU_STAT_TOP); - break; - - case 6: /* FBSTP (BCD) */ - TRACEOUT(("FBSTP packed BCD")); - FPU_FBST(madr); - FPU_pop(); - break; - - case 7: /* FISTP (QWORD) */ - TRACEOUT(("FISTP SINT64")); - FPU_FST_I64(madr); - FPU_pop(); - break; - - default: - break; - } - } -} -#endif +/* + * Copyright (c) 2012 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +/* + * modified by SimK + */ + +#include "compiler.h" + +#if defined(USE_FPU) && defined(SUPPORT_FPU_SOFTFLOAT) + +#include +#include +#include "ia32/cpu.h" +#include "ia32/ia32.mcr" + +#include "ia32/instructions/fpu/fp.h" +#include "ia32/instructions/fpu/fpumem.h" +#ifdef USE_SSE +#include "ia32/instructions/sse/sse.h" +#endif + + // softfloat.hのインクルードはcpu.hにあります + + /* + Short Real + 31: sign (符号) + 30-23: exp-8 (指数部: exponet) + 22-00: num-23 (小数部) + + Long Real + 63: sign + 62-52: exp-11 + 51-00: num-52 + + Temp Real + 79: sign + 78-64: exp-15 + 63: 1(?) + 62-00: num-63 + + -- + 指数部: + 2 の 0 乗のとき 0111 1111 となる + 1000 0001: +2 乗 + 1000 0000: +1 乗 + 0111 1111: 0 乗 + 0111 1110: -1 乗 + + 仮数部: + 2 を基数として整数部が一桁になるように正規化した数の 2 進数表現となる。 + 正規化によって仮数部の最上位ビットは常に 1 になるので実際に用意しておく + 必要はなく、倍精度の 52 ビットであれば最上位の 1 を hidden bit にして + 含めなければ、53 ビット分の情報が含まれることになる。 + + 小数の二進数表現: + 0.1000 1/2 = 0.5 + 0.0100 1/(2*2) = 0.25 + 0.0010 1/(2*2*2) = 0.125 + 0.0001 1/(2*2*2*2) = 0.0625 + */ + +#if 1 +#undef TRACEOUT +#define TRACEOUT(s) (void)(s) +#endif /* 0 */ + +#define FPU_WORKCLOCK 6 + +#define PI 3.1415926535897932384626433832795 +#define L2E 1.4426950408889634073599246810019 +#define L2T 3.3219280948873623478703194294894 +#define LN2 0.6931471805599453094172321214582 +#define LG2 0.3010299956639811952137388947245 + +static INLINE void FPU_SetCW(UINT16 cword) +{ + FPU_CTRLWORD = cword & 0x7FFF; + FPU_STAT.round = (FP_RND)((cword >> 10) & 3); + switch (FPU_STAT.round) { + case ROUND_Nearest: + float_rounding_mode = float_round_nearest_even; + break; + case ROUND_Down: + float_rounding_mode = float_round_down; + break; + case ROUND_Up: + float_rounding_mode = float_round_up; + break; + case ROUND_Chop: + float_rounding_mode = float_round_to_zero; + break; + default: + break; + } +} + +/* + * FPU exception + */ + +static void +fpu_check_NM_EXCEPTION(){ + // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる + if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { + EXCEPTION(NM_EXCEPTION, 0); + } +} +static void +fpu_check_NM_EXCEPTION2(){ + // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる + if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { + EXCEPTION(NM_EXCEPTION, 0); + } +} + +static void fpu_checkexception() { + if ((FPU_STATUSWORD & ~FPU_CTRLWORD) & 0x3F) { + EXCEPTION(MF_EXCEPTION, 0); + } +} + + +/* + * FPU memory access function + */ + +static void FPU_FLD80(UINT32 addr, UINT reg) +{ + *((REG80*)FPU_STAT.reg[reg].b) = fpu_memoryread_f(addr); +} + +static void FPU_FLD_F32(UINT32 addr, UINT reg) { + FPU_STAT.reg[reg].d = c_float_to_floatx80(fpu_memoryread_f32(addr)); +} + +static void FPU_FLD_F64(UINT32 addr, UINT reg) { + FPU_STAT.reg[reg].d = c_double_to_floatx80(fpu_memoryread_f64(addr)); +} + +static void FPU_FLD_F80(UINT32 addr) { + FPU_FLD80(addr, FPU_STAT_TOP); +} + +static void FPU_FLD_I16(UINT32 addr, UINT reg) { + FPU_STAT.reg[reg].d = int32_to_floatx80((SINT32)((SINT16)fpu_memoryread_w(addr))); +} + +static void FPU_FLD_I32(UINT32 addr, UINT reg) { + FPU_STAT.reg[reg].d = int32_to_floatx80((SINT32)fpu_memoryread_d(addr)); +} + +static void FPU_FLD_I64(UINT32 addr, UINT reg) { + FPU_STAT.reg[reg].d = int64_to_floatx80((SINT64)fpu_memoryread_q(addr)); +} + +static void FPU_FBLD(UINT32 addr, UINT reg) +{ + int i; + int tmp; + + REG80 bcdbuf; + SINT64 val = 0; + UINT8 in = 0; + + // 80bitまとめて読み取り + bcdbuf = fpu_memoryread_f(addr); + + // 0〜8byte目の処理 BCD + for (i = 8; i >= 0; i--) { + in = bcdbuf.b[i]; + tmp = ((in >> 4) & 0xf) * 10 + (in & 0xf); + val = val * 100 + tmp; + } + + // 9byte目は符号のみ意味がある + if (bcdbuf.b[9] & 0x80) { + val = -val; + } + + FPU_STAT.reg[reg].d = int64_to_floatx80(val); +} + +static INLINE void FPU_FLD_F32_EA(UINT32 addr) { + FPU_FLD_F32(addr, 8); +} +static INLINE void FPU_FLD_F64_EA(UINT32 addr) { + FPU_FLD_F64(addr, 8); +} +static INLINE void FPU_FLD_I32_EA(UINT32 addr) { + FPU_FLD_I32(addr, 8); +} +static INLINE void FPU_FLD_I16_EA(UINT32 addr) { + FPU_FLD_I16(addr, 8); +} + + +static void FPU_ST80(UINT32 addr, UINT reg) +{ + fpu_memorywrite_f(addr, (REG80*)FPU_STAT.reg[reg].b); +} + +static void FPU_FST_F32(UINT32 addr) { + fpu_memorywrite_f32(addr, floatx80_to_c_float(FPU_STAT.reg[FPU_STAT_TOP].d)); +} + +static void FPU_FST_F64(UINT32 addr) { + fpu_memorywrite_f64(addr, floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d)); +} + +static void FPU_FST_F80(UINT32 addr) { + FPU_ST80(addr, FPU_STAT_TOP); +} + +static void FPU_FST_I16(UINT32 addr) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + fpu_memorywrite_w(addr, (UINT16)floatx80_to_int16_np2(FPU_STAT.reg[FPU_STAT_TOP].d)); + FPU_STATUSWORD |= float_exception_flags; +} + +static void FPU_FST_I32(UINT32 addr) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + fpu_memorywrite_d(addr, (UINT32)floatx80_to_int32_np2(FPU_STAT.reg[FPU_STAT_TOP].d)); + FPU_STATUSWORD |= float_exception_flags; +} + +static void FPU_FST_I64(UINT32 addr) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + fpu_memorywrite_q(addr, (UINT64)floatx80_to_int64_np2(FPU_STAT.reg[FPU_STAT_TOP].d)); + FPU_STATUSWORD |= float_exception_flags; +} + +static void FPU_FBST(UINT32 addr) +{ + SINT64 val; + REG80 bcdbuf = { 0 }; + UINT i; + + signed char oldrnd = float_rounding_mode; + float_rounding_mode = float_round_down; + + val = floatx80_to_int64(FPU_STAT.reg[FPU_STAT_TOP].d); + + // 9byte目は符号のみ意味がある + if (val < 0) + { + bcdbuf.b[9] = 0x80; + val = -val; + } + + // 0〜8byte目の処理 BCD + for (i = 0; i < 9; i++) { + bcdbuf.b[i] = (UINT8)(val % 10); + val /= 10; + bcdbuf.b[i] |= (UINT8)(val % 10) << 4; + val /= 10; + } + + // 80bitまとめて書き込み + fpu_memorywrite_f(addr, &bcdbuf); + + float_rounding_mode = oldrnd; + FPU_STATUSWORD |= float_exception_flags; +} + + +/* + * FPU interface + */ + +static void +FPU_FINIT(void) +{ + int i; + FPU_SetCW(0x37F); + FPU_STATUSWORD = 0; + FPU_STAT_TOP=FP_TOP_GET(); + for(i=0;i<8;i++){ + // Emptyセットしてもレジスタの内容は消してはいけない + FPU_STAT.tag[i] = TAG_Empty; + } + FPU_STAT.tag[8] = TAG_Valid; // dummy + FPU_STAT.mmxenable = 0; +} +void SF_FPU_FINIT(void){ + int i; + FPU_FINIT(); + for(i=0;i<8;i++){ + FPU_STAT.tag[i] = TAG_Empty; + FPU_STAT.reg[i].l.ext = 0; + FPU_STAT.reg[i].l.lower = 0; + FPU_STAT.reg[i].l.upper = 0; + } +} + +static void FPU_FLDCW(UINT32 addr) +{ + UINT16 temp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, addr); + FPU_SetCW(temp); +} + +static UINT16 FPU_GetTag(void) +{ + UINT i; + + UINT16 tag = 0; + for (i = 0; i < 8; i++) + tag |= ((FPU_STAT.tag[i] & 3) << (2 * i)); + return tag; +} +static UINT8 FPU_GetTag8(void) +{ + UINT i; + + UINT8 tag = 0; + for (i = 0; i < 8; i++) + tag |= ((FPU_STAT.tag[i] == TAG_Empty ? 0 : 1) << (i)); + return tag; +} + +static INLINE void FPU_SetTag(UINT16 tag) +{ + UINT i; + + for (i = 0; i < 8; i++) { + FPU_STAT.tag[i] = (FP_TAG)((tag >> (2 * i)) & 3); + + } +} +static INLINE void FPU_SetTag8(UINT8 tag) +{ + UINT i; + + for (i = 0; i < 8; i++) { + FPU_STAT.tag[i] = (((tag >> i) & 1) == 0 ? TAG_Empty : TAG_Valid); + } +} + +static void FPU_prepush(void) { + FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; + if(FPU_STAT.tag[FPU_STAT_TOP] == TAG_Valid){ + FPU_STATUSWORD |= FP_C1_FLAG | FP_SF_FLAG | FP_IE_FLAG; + }else{ + FPU_STATUSWORD &= ~FP_C1_FLAG; + } + FPU_STAT.tag[FPU_STAT_TOP] = TAG_Valid; +} +static void FPU_push(floatx80 in) { + FPU_prepush(); + FPU_STAT.reg[FPU_STAT_TOP].d = in; +} + +static void FPU_pop(void) { + if(FPU_STAT.tag[FPU_STAT_TOP] == TAG_Empty){ + FPU_STATUSWORD |= FP_SF_FLAG | FP_IE_FLAG; + } + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_STAT.tag[FPU_STAT_TOP] = TAG_Empty; + FPU_STAT.mmxenable = 0; + FPU_STAT_TOP = ((FPU_STAT_TOP + 1) & 7); +} + +/* + * FPU instruction + */ + + // レジスタ操作 +static void FPU_FST(UINT st, UINT other) { + FPU_STAT.tag[other] = FPU_STAT.tag[st]; + FPU_STAT.reg[other] = FPU_STAT.reg[st]; +} +static void FPU_FXCH(UINT st, UINT other) { + FP_TAG tag; + FP_REG reg; + + tag = FPU_STAT.tag[other]; + reg = FPU_STAT.reg[other]; + FPU_STAT.tag[other] = FPU_STAT.tag[st]; + FPU_STAT.reg[other] = FPU_STAT.reg[st]; + FPU_STAT.tag[st] = tag; + FPU_STAT.reg[st] = reg; +} +static void FPU_FLD1(void) { + FPU_prepush(); + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(1.0); +} +static void FPU_FLDL2T(void) { + FPU_prepush(); + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(L2T); +} +static void FPU_FLDL2E(void) { + FPU_prepush(); + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(L2E); +} +static void FPU_FLDPI(void) { + FPU_prepush(); + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(PI); +} +static void FPU_FLDLG2(void) { + FPU_prepush(); + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(LG2); +} +static void FPU_FLDLN2(void) { + FPU_prepush(); + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(LN2); +} +static void FPU_FLDZ(void) { + FPU_prepush(); + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(0.0); + FPU_STAT.tag[FPU_STAT_TOP] = TAG_Zero; + FPU_STAT.mmxenable = 0; +} + +// 四則演算 +static void FPU_FADD(UINT op1, UINT op2) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[op1].d = floatx80_add(FPU_STAT.reg[op1].d, FPU_STAT.reg[op2].d); + FPU_STATUSWORD |= float_exception_flags; + return; +} +static void FPU_FMUL(UINT st, UINT other) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[st].d = floatx80_mul(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d); + FPU_STATUSWORD |= float_exception_flags; + return; +} +static void FPU_FSUB(UINT st, UINT other) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[st].d = floatx80_sub(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d); + return; +} +static void FPU_FSUBR(UINT st, UINT other) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[st].d = floatx80_sub(FPU_STAT.reg[other].d, FPU_STAT.reg[st].d); + FPU_STATUSWORD |= float_exception_flags; + return; +} +static void FPU_FDIV(UINT st, UINT other) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[st].d = floatx80_div(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d); + FPU_STATUSWORD |= float_exception_flags; + return; +} +static void FPU_FDIVR(UINT st, UINT other) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[st].d = floatx80_div(FPU_STAT.reg[other].d, FPU_STAT.reg[st].d); + FPU_STATUSWORD |= float_exception_flags; + return; +} +static INLINE void FPU_FADD_EA(UINT op1) { + FPU_FADD(op1, 8); +} +static INLINE void FPU_FMUL_EA(UINT op1) { + FPU_FMUL(op1, 8); +} +static INLINE void FPU_FSUB_EA(UINT op1) { + FPU_FSUB(op1, 8); +} +static INLINE void FPU_FSUBR_EA(UINT op1) { + FPU_FSUBR(op1, 8); +} +static INLINE void FPU_FDIV_EA(UINT op1) { + FPU_FDIV(op1, 8); +} +static INLINE void FPU_FDIVR_EA(UINT op1) { + FPU_FDIVR(op1, 8); +} +static void FPU_FPREM(void) { + floatx80 val, div; + SINT64 qint; + + float_exception_flags = (FPU_STATUSWORD & 0x3f); + val = FPU_STAT.reg[FPU_STAT_TOP].d; + div = FPU_STAT.reg[FPU_ST(1)].d; + qint = floatx80_to_int64_round_to_zero(floatx80_div(val, div)); // int(被除数 / 除数) = 商 + + FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_sub(val, floatx80_mul(int64_to_floatx80(qint), div)); // 被除数 - 商 x 除数 = 剰余 + FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C1_FLAG | FP_C2_FLAG | FP_C3_FLAG); + if(qint & 4) FPU_STATUSWORD |= FP_C0_FLAG; // 商のbit2 + if(qint & 2) FPU_STATUSWORD |= FP_C3_FLAG; // 商のbit1 + if(qint & 1) FPU_STATUSWORD |= FP_C1_FLAG; // 商のbit0 + // C2クリアで完了扱い + FPU_STATUSWORD |= float_exception_flags; +} + +static void FPU_FPREM1(void) { + floatx80 val, div, q; + SINT64 qint; + signed char oldrnd = float_rounding_mode; + + // IEEE 754 剰余 商を最も近い整数値とする。余りが負値になることが有り得る + + float_exception_flags = (FPU_STATUSWORD & 0x3f); + val = FPU_STAT.reg[FPU_STAT_TOP].d; + div = FPU_STAT.reg[FPU_ST(1)].d; + q = floatx80_add(floatx80_div(val, div), c_double_to_floatx80(0.5)); // floor(値 + 0.5)で四捨五入 厳密には負値の境界で違うが微々たる差として気にしないことにする。 + float_rounding_mode = float_round_down; + qint = floatx80_to_int64(q); // 四捨五入(被除数 / 除数) = 最も整数に近い商 + + FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_sub(val, floatx80_mul(int64_to_floatx80(qint), div)); // 被除数 - 商 x 除数 = 剰余 + FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C1_FLAG | FP_C2_FLAG | FP_C3_FLAG); + if(qint & 4) FPU_STATUSWORD |= FP_C0_FLAG; // 商のbit2 + if(qint & 2) FPU_STATUSWORD |= FP_C3_FLAG; // 商のbit1 + if(qint & 1) FPU_STATUSWORD |= FP_C1_FLAG; // 商のbit0 + // C2クリアで完了扱い + float_rounding_mode = oldrnd; + FPU_STATUSWORD |= float_exception_flags; +} + +// 数学関数 +static void FPU_FSIN(void) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(sin(floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d))); + FPU_STATUSWORD &= ~FP_C2_FLAG; + FPU_STATUSWORD |= float_exception_flags; + return; +} +static void FPU_FCOS(void) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(cos(floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d))); + FPU_STATUSWORD &= ~FP_C2_FLAG; + FPU_STATUSWORD |= float_exception_flags; + return; +} +static void FPU_FSINCOS(void) { + double temp; + + float_exception_flags = (FPU_STATUSWORD & 0x3f); + temp = floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d); + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(sin(temp)); + FPU_push(c_double_to_floatx80(cos(temp))); + FPU_STATUSWORD &= ~FP_C2_FLAG; + FPU_STATUSWORD |= float_exception_flags; + return; +} +static void FPU_FPTAN(void) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(tan(floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d))); + FPU_push(c_double_to_floatx80(1.0)); + FPU_STATUSWORD &= ~FP_C2_FLAG; + FPU_STATUSWORD |= float_exception_flags; + return; +} +static void FPU_FPATAN(void) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[FPU_ST(1)].d = c_double_to_floatx80(atan2(floatx80_to_c_double(FPU_STAT.reg[FPU_ST(1)].d), floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d))); + FPU_pop(); + FPU_STATUSWORD |= float_exception_flags; + return; +} +static void FPU_FSQRT(void) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_sqrt(FPU_STAT.reg[FPU_STAT_TOP].d); + FPU_STATUSWORD |= float_exception_flags; + return; +} +static void FPU_FRNDINT(void) { + float_exception_flags = (FPU_STATUSWORD & 0x3f); + FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_round_to_int(FPU_STAT.reg[FPU_STAT_TOP].d); + FPU_STATUSWORD |= float_exception_flags; +} +static void FPU_F2XM1(void) { + FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(pow(2.0, floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d)) - 1); +} +static void FPU_FYL2X(void) { + FPU_STAT.reg[FPU_ST(1)].d = floatx80_mul(FPU_STAT.reg[FPU_ST(1)].d, c_double_to_floatx80(log(floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d)) / log(2.0))); + FPU_pop(); +} +static void FPU_FYL2XP1(void) { + FPU_STAT.reg[FPU_ST(1)].d = floatx80_mul(FPU_STAT.reg[FPU_ST(1)].d, c_double_to_floatx80(log(floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d) + 1.0) / log(2.0))); + FPU_pop(); +} +static void FPU_FSCALE(void) { + FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_mul(FPU_STAT.reg[FPU_STAT_TOP].d, c_double_to_floatx80(pow(2.0, floatx80_to_c_double(FPU_STAT.reg[FPU_ST(1)].d)))); +} +static void FPU_FCHS(void) { + FPU_STAT.reg[FPU_STAT_TOP].b[9] ^= 0x80; +} +static void FPU_FABS(void) { + FPU_STAT.reg[FPU_STAT_TOP].b[9] &= ~0x80; +} + +// 比較 +static void FPU_FCOM(UINT st, UINT other) { + FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C2_FLAG | FP_C3_FLAG); + if (((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || + ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero)) || + (floatx80_is_nan(FPU_STAT.reg[st].d) || floatx80_is_nan(FPU_STAT.reg[other].d))) { + FPU_STATUSWORD |= FP_C3_FLAG|FP_C2_FLAG|FP_C0_FLAG; + } + else if (floatx80_eq(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d)) { + FPU_STATUSWORD |= FP_C3_FLAG; + } + else if (floatx80_lt(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d)) { + FPU_STATUSWORD |= FP_C0_FLAG; + } +} +static void FPU_FCOMI(UINT st, UINT other) { + CPU_FLAGL &= ~(Z_FLAG|P_FLAG|C_FLAG); + if (((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || + ((FPU_STAT.tag[other] != TAG_Valid) && (FPU_STAT.tag[other] != TAG_Zero)) || + (floatx80_is_nan(FPU_STAT.reg[st].d) || floatx80_is_nan(FPU_STAT.reg[other].d))) { + CPU_FLAGL |= Z_FLAG|P_FLAG|C_FLAG; + } + else if (floatx80_eq(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d)) { + CPU_FLAGL |= Z_FLAG; + } + else if (floatx80_lt(FPU_STAT.reg[st].d, FPU_STAT.reg[other].d)) { + CPU_FLAGL |= C_FLAG; + } +} +static void FPU_FUCOM(UINT st, UINT other) { + // 例外絡みの挙動が違うがほぼ同じとしてスルー + FPU_FCOM(st, other); +} +static void FPU_FUCOMI(UINT st, UINT other) { + // 例外絡みの挙動が違うがほぼ同じとしてスルー + FPU_FCOMI(st, other); +} +static INLINE void FPU_FCOM_EA(UINT op1) { + FPU_FCOM(op1, 8); +} +static void FPU_FTST(void) { + FPU_STAT.reg[8].d = c_double_to_floatx80(0.0); + FPU_FCOM(FPU_STAT_TOP, 8); +} + +// 条件付きコピー +static void FPU_FCMOVB(UINT st, UINT other) { + if (CPU_FLAGL & C_FLAG) { + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVE(UINT st, UINT other) { + if (CPU_FLAGL & Z_FLAG) { + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVBE(UINT st, UINT other) { + if (CPU_FLAGL & (C_FLAG | Z_FLAG)) { + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVU(UINT st, UINT other) { + if (CPU_FLAGL & P_FLAG) { + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVNB(UINT st, UINT other) { + if (!(CPU_FLAGL & C_FLAG)) { + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVNE(UINT st, UINT other) { + if (!(CPU_FLAGL & Z_FLAG)) { + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVNBE(UINT st, UINT other) { + if (!(CPU_FLAGL & (C_FLAG | Z_FLAG))) { + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} +static void FPU_FCMOVNU(UINT st, UINT other) { + if (!(CPU_FLAGL & P_FLAG)) { + FPU_STAT.tag[st] = FPU_STAT.tag[other]; + FPU_STAT.reg[st] = FPU_STAT.reg[other]; + } +} + +// 浮動小数点数操作 +static void FPU_FXAM(void) { + FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C1_FLAG | FP_C2_FLAG | FP_C3_FLAG); + if (FPU_STAT.reg[FPU_STAT_TOP].d.high & 0x8000) { + FPU_STATUSWORD |= FP_C1_FLAG; + } + + if (FPU_STAT.tag[FPU_STAT_TOP] == TAG_Empty) { + FPU_STATUSWORD |= FP_C3_FLAG; + FPU_STATUSWORD |= FP_C0_FLAG; + } + else if (floatx80_is_nan(FPU_STAT.reg[FPU_STAT_TOP].d)) { + FPU_STATUSWORD |= FP_C0_FLAG; + } + else if (floatx80_is_inf(FPU_STAT.reg[FPU_STAT_TOP].d)) { + FPU_STATUSWORD |= FP_C2_FLAG; + FPU_STATUSWORD |= FP_C0_FLAG; + } + else if (floatx80_eq(FPU_STAT.reg[FPU_STAT_TOP].d, c_double_to_floatx80(0.0))) { + FPU_STATUSWORD |= FP_C3_FLAG; + } + else { + FPU_STATUSWORD |= FP_C2_FLAG; + } +} + +static void FPU_FXTRACT(void) { + SINT32 expval; + floatx80 fracval; + + fracval = FPU_STAT.reg[FPU_STAT_TOP].d; + expval = (SINT32)((UINT16)fracval.high & 0x7FFF) - 0x3FFF; // 指数部分を抽出、バイアス分を引く + fracval.high = (SINT16)(((UINT16)fracval.high & 0x8000) | 0x3FFF); // 符号は残し、指数部分を0x3FFF(バイアス分=0)にして仮数だけにする + FPU_STAT.reg[FPU_STAT_TOP].d = int64_to_floatx80(expval); // 指数の書き込み + FPU_push(fracval); // 仮数のpush +} + +// 環境ロード・ストア +static void FPU_FSTENV(UINT32 addr) +{ + FP_TOP_SET(FPU_STAT_TOP); + + switch ((CPU_CR0 & 1) | (CPU_INST_OP32 ? 0x100 : 0x000)) + { + case 0x000: case 0x001: + fpu_memorywrite_w(addr + 0, FPU_CTRLWORD); + fpu_memorywrite_w(addr + 2, FPU_STATUSWORD); + fpu_memorywrite_w(addr + 4, FPU_GetTag()); + fpu_memorywrite_w(addr + 10, FPU_LASTINSTOP); + break; + + case 0x100: case 0x101: + fpu_memorywrite_d(addr + 0, (UINT32)(FPU_CTRLWORD)); + fpu_memorywrite_d(addr + 4, (UINT32)(FPU_STATUSWORD)); + fpu_memorywrite_d(addr + 8, (UINT32)(FPU_GetTag())); + fpu_memorywrite_d(addr + 20, FPU_LASTINSTOP); + break; + } +} +static void FPU_FLDENV(UINT32 addr) +{ + switch ((CPU_CR0 & 1) | (CPU_INST_OP32 ? 0x100 : 0x000)) { + case 0x000: case 0x001: + FPU_SetCW(fpu_memoryread_w(addr + 0)); + FPU_STATUSWORD = fpu_memoryread_w(addr + 2); + FPU_SetTag(fpu_memoryread_w(addr + 4)); + FPU_LASTINSTOP = fpu_memoryread_w(addr + 10); + break; + + case 0x100: case 0x101: + FPU_SetCW((UINT16)fpu_memoryread_d(addr + 0)); + FPU_STATUSWORD = (UINT16)fpu_memoryread_d(addr + 4); + FPU_SetTag((UINT16)fpu_memoryread_d(addr + 8)); + FPU_LASTINSTOP = (UINT16)fpu_memoryread_d(addr + 20); + break; + } + FPU_STAT_TOP = FP_TOP_GET(); +} +static void FPU_FSAVE(UINT32 addr) +{ + UINT start; + UINT i; + + FPU_FSTENV(addr); + start = ((CPU_INST_OP32) ? 28 : 14); + for (i = 0; i < 8; i++) { + FPU_ST80(addr + start, FPU_ST(i)); + start += 10; + } + FPU_FINIT(); +} +static void FPU_FRSTOR(UINT32 addr) +{ + UINT start; + UINT i; + + FPU_FLDENV(addr); + start = ((CPU_INST_OP32) ? 28 : 14); + for (i = 0; i < 8; i++) { + FPU_FLD80(addr + start, FPU_ST(i)); + start += 10; + } +} +static void FPU_FXSAVE(UINT32 addr) { + UINT start; + UINT i; + + FP_TOP_SET(FPU_STAT_TOP); + fpu_memorywrite_w(addr + 0, FPU_CTRLWORD); + fpu_memorywrite_w(addr + 2, FPU_STATUSWORD); + fpu_memorywrite_b(addr + 4, FPU_GetTag8()); +#ifdef USE_SSE + fpu_memorywrite_d(addr + 24, SSE_MXCSR); +#endif + start = 32; + for (i = 0; i < 8; i++) { + FPU_ST80(addr + start, FPU_ST(i)); + start += 16; + } +#ifdef USE_SSE + start = 160; + for (i = 0; i < 8; i++) { + fpu_memorywrite_q(addr + start + 0, SSE_XMMREG(i).ul64[0]); + fpu_memorywrite_q(addr + start + 8, SSE_XMMREG(i).ul64[1]); + start += 16; + } +#endif +} +static void FPU_FXRSTOR(UINT32 addr) { + UINT start; + UINT i; + + FPU_SetCW(fpu_memoryread_w(addr + 0)); + FPU_STATUSWORD = fpu_memoryread_w(addr + 2); + FPU_SetTag8(fpu_memoryread_b(addr + 4)); + FPU_STAT_TOP = FP_TOP_GET(); +#ifdef USE_SSE + SSE_MXCSR = fpu_memoryread_d(addr + 24); +#endif + start = 32; + for (i = 0; i < 8; i++) { + FPU_FLD80(addr + start, FPU_ST(i)); + start += 16; + } +#ifdef USE_SSE + start = 160; + for (i = 0; i < 8; i++) { + SSE_XMMREG(i).ul64[0] = fpu_memoryread_q(addr + start + 0); + SSE_XMMREG(i).ul64[1] = fpu_memoryread_q(addr + start + 8); + start += 16; + } +#endif +} +void SF_FPU_FXSAVERSTOR(void) { + UINT32 op; + UINT idx, sub; + UINT32 maddr; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + switch (idx) { + case 0: // FXSAVE + fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し + maddr = calc_ea_dst(op); + FPU_FXSAVE(maddr); + break; + case 1: // FXRSTOR + fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し + maddr = calc_ea_dst(op); + FPU_FXRSTOR(maddr); + break; +#ifdef USE_SSE + case 2: // LDMXCSR + maddr = calc_ea_dst(op); + SSE_LDMXCSR(maddr); + break; + case 3: // STMXCSR + maddr = calc_ea_dst(op); + SSE_STMXCSR(maddr); + break; + case 4: // SFENCE + SSE_SFENCE(); + break; + case 5: // LFENCE + SSE_LFENCE(); + break; + case 6: // MFENCE + SSE_MFENCE(); + break; + case 7: // CLFLUSH; + SSE_CLFLUSH(op); + break; +#endif + default: + ia32_panic("invalid opcode = %02x\n", op); + break; + } +} + +static void EA_TREE(UINT op) +{ + UINT idx; + + idx = (op >> 3) & 7; + + switch (idx) { + case 0: /* FADD (単精度実数) */ + TRACEOUT(("FADD EA")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FADD_EA(FPU_STAT_TOP); + break; + case 1: /* FMUL (単精度実数) */ + TRACEOUT(("FMUL EA")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FMUL_EA(FPU_STAT_TOP); + break; + case 2: /* FCOM (単精度実数) */ + TRACEOUT(("FCOM EA")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCOM_EA(FPU_STAT_TOP); + break; + case 3: /* FCOMP (単精度実数) */ + TRACEOUT(("FCOMP EA")); + FPU_FCOM_EA(FPU_STAT_TOP); + FPU_pop(); + break; + case 4: /* FSUB (単精度実数) */ + TRACEOUT(("FSUB EA")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FSUB_EA(FPU_STAT_TOP); + break; + case 5: /* FSUBR (単精度実数) */ + TRACEOUT(("FSUBR EA")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FSUBR_EA(FPU_STAT_TOP); + break; + case 6: /* FDIV (単精度実数) */ + TRACEOUT(("FDIV EA")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FDIV_EA(FPU_STAT_TOP); + break; + case 7: /* FDIVR (単精度実数) */ + TRACEOUT(("FDIVR EA")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FDIVR_EA(FPU_STAT_TOP); + break; + default: + break; + } +} + +// d8 +void +SF_ESC0(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU d8 %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FADD */ + TRACEOUT(("FADD")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FADD(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 1: /* FMUL */ + TRACEOUT(("FMUL")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FMUL(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FCOM */ + TRACEOUT(("FCOM")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCOMP */ + TRACEOUT(("FCOMP")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + FPU_pop(); + break; + case 4: /* FSUB */ + TRACEOUT(("FSUB")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FSUB(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 5: /* FSUBR */ + TRACEOUT(("FSUBR")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FSUBR(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 6: /* FDIV */ + TRACEOUT(("FDIV")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FDIV(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 7: /* FDIVR */ + TRACEOUT(("FDIVR")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FDIVR(FPU_STAT_TOP,FPU_ST(sub)); + break; + } + } else { + madr = calc_ea_dst(op); + FPU_FLD_F32_EA(madr); + EA_TREE(op); + } +} + +// d9 +void +SF_ESC1(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU d9 %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + if(!(op < 0xc0 && idx>=4)){ + fpu_checkexception(); + } + if (op >= 0xc0) + { + switch (idx) { + case 0: /* FLD ST(0), ST(i) */ + { + UINT reg_from; + + TRACEOUT(("FLD STi")); + reg_from = FPU_ST(sub); + FPU_prepush(); + FPU_FST(reg_from, FPU_STAT_TOP); + } + break; + + case 1: /* FXCH ST(0), ST(i) */ + TRACEOUT(("FXCH STi")); + FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); + break; + + case 2: /* FNOP */ + TRACEOUT(("FNOP")); + break; + + case 3: /* FSTP STi */ + TRACEOUT(("FSTP STi")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + FPU_pop(); + break; + + case 4: + switch (sub) { + case 0x0: /* FCHS */ + TRACEOUT(("FCHS")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCHS(); + break; + + case 0x1: /* FABS */ + TRACEOUT(("FABS")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FABS(); + break; + + case 0x2: /* UNKNOWN */ + case 0x3: /* ILLEGAL */ + break; + + case 0x4: /* FTST */ + TRACEOUT(("FTST")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FTST(); + break; + + case 0x5: /* FXAM */ + TRACEOUT(("FXAM")); + FPU_FXAM(); + break; + + case 0x06: /* FTSTP (cyrix)*/ + case 0x07: /* UNKNOWN */ + break; + } + break; + + case 5: + switch (sub) { + case 0x0: /* FLD1 */ + TRACEOUT(("FLD1")); + FPU_FLD1(); + break; + + case 0x1: /* FLDL2T */ + TRACEOUT(("FLDL2T")); + FPU_FLDL2T(); + break; + + case 0x2: /* FLDL2E */ + TRACEOUT(("FLDL2E")); + FPU_FLDL2E(); + break; + + case 0x3: /* FLDPI */ + TRACEOUT(("FLDPI")); + FPU_FLDPI(); + break; + + case 0x4: /* FLDLG2 */ + TRACEOUT(("FLDLG2")); + FPU_FLDLG2(); + break; + + case 0x5: /* FLDLN2 */ + TRACEOUT(("FLDLN2")); + FPU_FLDLN2(); + break; + + case 0x6: /* FLDZ */ + TRACEOUT(("FLDZ")); + FPU_FLDZ(); + break; + + case 0x07: /* ILLEGAL */ + break; + } + break; + + case 6: + switch (sub) { + case 0x0: /* F2XM1 */ + TRACEOUT(("F2XM1")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_F2XM1(); + break; + + case 0x1: /* FYL2X */ + TRACEOUT(("FYL2X")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FYL2X(); + break; + + case 0x2: /* FPTAN */ + TRACEOUT(("FPTAN")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FPTAN(); + break; + + case 0x3: /* FPATAN */ + TRACEOUT(("FPATAN")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FPATAN(); + break; + + case 0x4: /* FXTRACT */ + TRACEOUT(("FXTRACT")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FXTRACT(); + break; + + case 0x5: /* FPREM1 */ + TRACEOUT(("FPREM1")); + FPU_FPREM1(); + break; + + case 0x6: /* FDECSTP */ + TRACEOUT(("FDECSTP")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_STAT_TOP = (FPU_STAT_TOP - 1) & 7; + break; + + case 0x7: /* FINCSTP */ + TRACEOUT(("FINCSTP")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_STAT_TOP = (FPU_STAT_TOP + 1) & 7; + break; + } + break; + + case 7: + switch (sub) { + case 0x0: /* FPREM */ + TRACEOUT(("FPREM")); + FPU_FPREM(); + break; + + case 0x1: /* FYL2XP1 */ + TRACEOUT(("FYL2XP1")); + FPU_FYL2XP1(); + break; + + case 0x2: /* FSQRT */ + TRACEOUT(("FSQRT")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FSQRT(); + break; + + case 0x3: /* FSINCOS */ + TRACEOUT(("FSINCOS")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FSINCOS(); + break; + + case 0x4: /* FRNDINT */ + TRACEOUT(("FRNDINT")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FRNDINT(); + break; + + case 0x5: /* FSCALE */ + TRACEOUT(("FSCALE")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FSCALE(); + break; + + case 0x6: /* FSIN */ + TRACEOUT(("FSIN")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FSIN(); + break; + + case 0x7: /* FCOS */ + TRACEOUT(("FCOS")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCOS(); + break; + } + break; + + default: + ia32_panic("ESC1: invalid opcode = %02x\n", op); + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FLD (単精度実数) */ + TRACEOUT(("FLD float")); + FPU_prepush(); + FPU_FLD_F32(madr,FPU_STAT_TOP); + break; + + case 1: /* UNKNOWN */ + break; + + case 2: /* FST (単精度実数) */ + TRACEOUT(("FST float")); + FPU_FST_F32(madr); + FPU_STATUSWORD &= ~FP_C1_FLAG; + break; + + case 3: /* FSTP (単精度実数) */ + TRACEOUT(("FSTP float")); + FPU_FST_F32(madr); + FPU_pop(); + break; + + case 4: /* FLDENV */ + TRACEOUT(("FLDENV")); + FPU_FLDENV(madr); + break; + + case 5: /* FLDCW */ + TRACEOUT(("FLDCW")); + FPU_FLDCW(madr); + break; + + case 6: /* FSTENV */ + TRACEOUT(("FSTENV")); + FPU_FSTENV(madr); + break; + + case 7: /* FSTCW */ + TRACEOUT(("FSTCW/FNSTCW")); + fpu_memorywrite_w(madr,FPU_CTRLWORD); + break; + + default: + break; + } + } +} + +// da +void +SF_ESC2(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU da %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FCMOVB */ + TRACEOUT(("ESC2: FCMOVB")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCMOVB(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 1: /* FCMOVE */ + TRACEOUT(("ESC2: FCMOVE")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCMOVE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FCMOVBE */ + TRACEOUT(("ESC2: FCMOVBE")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCMOVBE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCMOVU */ + TRACEOUT(("ESC2: FCMOVU")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCMOVU(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 5: + switch (sub) { + case 1: /* FUCOMPP */ + TRACEOUT(("FUCOMPP")); + FPU_FUCOM(FPU_STAT_TOP,FPU_ST(1)); + FPU_pop(); + FPU_pop(); + break; + + default: + break; + } + break; + + default: + break; + } + } else { + madr = calc_ea_dst(op); + FPU_FLD_I32_EA(madr); + EA_TREE(op); + } +} + +// db +void +SF_ESC3(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU db %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + if(!(op >= 0xc0 && idx==4)){ + fpu_checkexception(); + } + if (op >= 0xc0) + { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FCMOVNB */ + TRACEOUT(("ESC3: FCMOVNB")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCMOVNB(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 1: /* FCMOVNE */ + TRACEOUT(("ESC3: FCMOVNE")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCMOVNE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FCMOVNBE */ + TRACEOUT(("ESC3: FCMOVNBE")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCMOVNBE(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCMOVNU */ + TRACEOUT(("ESC3: FCMOVNU")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCMOVNU(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 4: + switch (sub) { + case 0: /* FNENI */ + case 1: /* FNDIS */ + break; + + case 2: /* FCLEX */ + TRACEOUT(("FCLEX")); + FPU_STATUSWORD &= 0x7f00; + break; + + case 3: /* FNINIT/FINIT */ + TRACEOUT(("FNINIT/FINIT")); + FPU_FINIT(); + break; + + case 4: /* FNSETPM */ + case 5: /* FRSTPM */ + // nop + break; + + default: + break; + } + break; + case 5: /* FUCOMI */ + TRACEOUT(("ESC3: FUCOMI")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 6: /* FCOMI */ + TRACEOUT(("ESC3: FCOMI")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); + break; + default: + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FILD (DWORD) */ + TRACEOUT(("FILD")); + FPU_prepush(); + FPU_FLD_I32(madr,FPU_STAT_TOP); + break; + + case 1: /* FISTTP (DWORD) */ + { + signed char oldrnd = float_rounding_mode; + float_rounding_mode = float_round_down; + FPU_FST_I32(madr); + float_rounding_mode = oldrnd; + } + FPU_pop(); + break; + + case 2: /* FIST (DWORD) */ + TRACEOUT(("FIST")); + FPU_FST_I32(madr); + FPU_STATUSWORD &= ~FP_C1_FLAG; + break; + + case 3: /* FISTP (DWORD) */ + TRACEOUT(("FISTP")); + FPU_FST_I32(madr); + FPU_pop(); + break; + + case 5: /* FLD (拡張実数) */ + TRACEOUT(("FLD 80 Bits Real")); + FPU_prepush(); + FPU_FLD_F80(madr); + break; + + case 7: /* FSTP (拡張実数) */ + TRACEOUT(("FSTP 80 Bits Real")); + FPU_FST_F80(madr); + FPU_pop(); + break; + + default: + break; + } + } +} + +// dc +void +SF_ESC4(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU dc %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(i), ST(0) */ + switch (idx) { + case 0: /* FADD */ + TRACEOUT(("ESC4: FADD")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); + break; + case 1: /* FMUL */ + TRACEOUT(("ESC4: FMUL")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); + break; + case 2: /* FCOM */ + TRACEOUT(("ESC4: FCOM")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCOMP */ + TRACEOUT(("ESC4: FCOMP")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + FPU_pop(); + break; + case 4: /* FSUBR */ + TRACEOUT(("ESC4: FSUBR")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); + break; + case 5: /* FSUB */ + TRACEOUT(("ESC4: FSUB")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); + break; + case 6: /* FDIVR */ + TRACEOUT(("ESC4: FDIVR")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); + break; + case 7: /* FDIV */ + TRACEOUT(("ESC4: FDIV")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); + break; + default: + break; + } + } else { + madr = calc_ea_dst(op); + FPU_FLD_F64_EA(madr); + EA_TREE(op); + } +} + +// dd +void +SF_ESC5(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU dd %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + fpu_check_NM_EXCEPTION(); + if(op >= 0xc0 || (idx!=4 && idx!=6 && idx!=7)){ + fpu_checkexception(); + } + if (op >= 0xc0) { + /* FUCOM ST(i), ST(0) */ + /* Fxxx ST(i) */ + switch (idx) { + case 0: /* FFREE */ + TRACEOUT(("FFREE")); + FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; + FPU_STAT.mmxenable = 0; + break; + case 1: /* FXCH */ + TRACEOUT(("FXCH")); + FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 2: /* FST */ + TRACEOUT(("FST")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + FPU_STATUSWORD &= ~FP_C1_FLAG; + break; + case 3: /* FSTP */ + TRACEOUT(("FSTP")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + FPU_pop(); + break; + case 4: /* FUCOM */ + TRACEOUT(("FUCOM")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 5: /* FUCOMP */ + TRACEOUT(("FUCOMP")); + FPU_FUCOM(FPU_STAT_TOP,FPU_ST(sub)); + FPU_pop(); + break; + + default: + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FLD (倍精度実数) */ + TRACEOUT(("FLD double real")); + FPU_prepush(); + FPU_FLD_F64(madr,FPU_STAT_TOP); + break; + case 1: /* FISTTP (QWORD) */ + { + signed char oldrnd = float_rounding_mode; + float_rounding_mode = float_round_down; + FPU_FST_I64(madr); + float_rounding_mode = oldrnd; + } + FPU_pop(); + break; + case 2: /* FST (倍精度実数) */ + TRACEOUT(("FST double real")); + FPU_FST_F64(madr); + FPU_STATUSWORD &= ~FP_C1_FLAG; + break; + case 3: /* FSTP (倍精度実数) */ + TRACEOUT(("FSTP double real")); + FPU_FST_F64(madr); + FPU_pop(); + break; + case 4: /* FRSTOR */ + TRACEOUT(("FRSTOR")); + FPU_FRSTOR(madr); + break; + case 6: /* FSAVE */ + TRACEOUT(("FSAVE")); + FPU_FSAVE(madr); + break; + + case 7: /* FSTSW */ + FP_TOP_SET(FPU_STAT_TOP); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, FPU_STATUSWORD); + break; + + default: + break; + } + } +} + +// de +void +SF_ESC6(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU de %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + fpu_checkexception(); + if (op >= 0xc0) { + /* Fxxx ST(i), ST(0) */ + switch (idx) { + case 0: /* FADDP */ + TRACEOUT(("FADDP")); + FPU_FADD(FPU_ST(sub),FPU_STAT_TOP); + break; + case 1: /* FMULP */ + TRACEOUT(("FMULP")); + FPU_FMUL(FPU_ST(sub),FPU_STAT_TOP); + break; + case 2: /* FCOMP5 */ + TRACEOUT(("FCOMP5")); + FPU_FCOM(FPU_STAT_TOP,FPU_ST(sub)); + break; + case 3: /* FCOMPP */ + TRACEOUT(("FCOMPP")); + if(sub != 1) { + return; + } + FPU_FCOM(FPU_STAT_TOP,FPU_ST(1)); + FPU_pop(); // 下コードと合わせて2回pop + break; + case 4: /* FSUBRP */ + TRACEOUT(("FSUBRP")); + FPU_FSUBR(FPU_ST(sub),FPU_STAT_TOP); + break; + case 5: /* FSUBP */ + TRACEOUT(("FSUBP")); + FPU_FSUB(FPU_ST(sub),FPU_STAT_TOP); + break; + case 6: /* FDIVRP */ + TRACEOUT(("FDIVRP")); + FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); + if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ + return; // POPしないようにする + } + break; + case 7: /* FDIVP */ + TRACEOUT(("FDIVP")); + FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); + if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ + return; // POPしないようにする + } + break; + /*FALLTHROUGH*/ + default: + break; + } + FPU_pop(); + } else { + madr = calc_ea_dst(op); + FPU_FLD_I16_EA(madr); + EA_TREE(op); + } +} + +// df +void +SF_ESC7(void) +{ + UINT32 op, madr; + UINT idx, sub; + + CPU_WORKCLOCK(FPU_WORKCLOCK); + GET_MODRM_PCBYTE(op); + TRACEOUT(("use FPU df %.2x", op)); + idx = (op >> 3) & 7; + sub = (op & 7); + + fpu_check_NM_EXCEPTION(); + if(!(op >= 0xc0 && idx==4 && sub==0)){ + fpu_checkexception(); + } + if (op >= 0xc0) { + /* Fxxx ST(0), ST(i) */ + switch (idx) { + case 0: /* FFREEP */ + TRACEOUT(("FFREEP")); + FPU_STAT.tag[FPU_ST(sub)]=TAG_Empty; + FPU_STAT.mmxenable = 0; + FPU_pop(); + break; + case 1: /* FXCH */ + TRACEOUT(("FXCH")); + FPU_STATUSWORD &= ~FP_C1_FLAG; + FPU_FXCH(FPU_STAT_TOP,FPU_ST(sub)); + break; + + case 2: + case 3: /* FSTP */ + TRACEOUT(("FSTP")); + FPU_FST(FPU_STAT_TOP,FPU_ST(sub)); + FPU_pop(); + break; + + case 4: + switch (sub) + { + case 0: /* FSTSW AX */ + TRACEOUT(("FSTSW AX")); + FP_TOP_SET(FPU_STAT_TOP); + CPU_AX = FPU_STATUSWORD; + break; + + default: + break; + } + break; + case 5: /* FUCOMIP */ + TRACEOUT(("ESC7: FUCOMIP")); + FPU_FUCOMI(FPU_STAT_TOP,FPU_ST(sub)); + FPU_pop(); + break; + case 6: /* FCOMIP */ + TRACEOUT(("ESC7: FCOMIP")); + FPU_FCOMI(FPU_STAT_TOP,FPU_ST(sub)); + FPU_pop(); + break; + default: + break; + } + } else { + madr = calc_ea_dst(op); + switch (idx) { + case 0: /* FILD (WORD) */ + TRACEOUT(("FILD SINT16")); + FPU_prepush(); + FPU_FLD_I16(madr,FPU_STAT_TOP); + break; + case 1: /* FISTTP (WORD) */ + { + signed char oldrnd = float_rounding_mode; + float_rounding_mode = float_round_down; + FPU_FST_I16(madr); + float_rounding_mode = oldrnd; + } + FPU_pop(); + break; + case 2: /* FIST (WORD) */ + TRACEOUT(("FIST SINT16")); + FPU_FST_I16(madr); + FPU_STATUSWORD &= ~FP_C1_FLAG; + break; + case 3: /* FISTP (WORD) */ + TRACEOUT(("FISTP SINT16")); + FPU_FST_I16(madr); + FPU_pop(); + break; + + case 4: /* FBLD (BCD) */ + TRACEOUT(("FBLD packed BCD")); + FPU_prepush(); + FPU_FBLD(madr,FPU_STAT_TOP); + break; + + case 5: /* FILD (QWORD) */ + TRACEOUT(("FILD SINT64")); + FPU_prepush(); + FPU_FLD_I64(madr,FPU_STAT_TOP); + break; + + case 6: /* FBSTP (BCD) */ + TRACEOUT(("FBSTP packed BCD")); + FPU_FBST(madr); + FPU_pop(); + break; + + case 7: /* FISTP (QWORD) */ + TRACEOUT(("FISTP SINT64")); + FPU_FST_I64(madr); + FPU_pop(); + break; + + default: + break; + } + } +} +#endif diff --git a/i386c/ia32/instructions/fpu/fpemul_softfloat3.cpp b/i386c/ia32/instructions/fpu/fpemul_softfloat3.cpp index 4000a9b6..9539dea0 100644 --- a/i386c/ia32/instructions/fpu/fpemul_softfloat3.cpp +++ b/i386c/ia32/instructions/fpu/fpemul_softfloat3.cpp @@ -42,13 +42,13 @@ #include "ia32/instructions/sse/sse.h" #endif -// softfloat.h̃CN[hcpu.hɂ܂ +// softfloat.hのインクルードはcpu.hにあります /* Short Real - 31: sign () - 30-23: exp-8 (w: exponet) - 22-00: num-23 () + 31: sign (符号) + 30-23: exp-8 (指数部: exponet) + 22-00: num-23 (小数部) Long Real 63: sign @@ -62,20 +62,20 @@ 62-00: num-63 -- - w: - 2 0 ̂Ƃ 0111 1111 ƂȂ - 1000 0001: +2 - 1000 0000: +1 - 0111 1111: 0 - 0111 1110: -1 - - : - 2 ƂĐꌅɂȂ悤ɐK 2 i\ƂȂB - Kɂĉ̍ŏʃrbg͏ 1 ɂȂ̂ŎۂɗpӂĂ - Kv͂ȂA{x 52 rbgł΍ŏʂ 1 hidden bit ɂ - ܂߂Ȃ΁A53 rbg̏񂪊܂܂邱ƂɂȂB - - ̓i\: + 指数部: + 2 の 0 乗のとき 0111 1111 となる + 1000 0001: +2 乗 + 1000 0000: +1 乗 + 0111 1111: 0 乗 + 0111 1110: -1 乗 + + 仮数部: + 2 を基数として整数部が一桁になるように正規化した数の 2 進数表現となる。 + 正規化によって仮数部の最上位ビットは常に 1 になるので実際に用意しておく + 必要はなく、倍精度の 52 ビットであれば最上位の 1 を hidden bit にして + 含めなければ、53 ビット分の情報が含まれることになる。 + + 小数の二進数表現: 0.1000 1/2 = 0.5 0.0100 1/(2*2) = 0.25 0.0010 1/(2*2*2) = 0.125 @@ -234,14 +234,14 @@ static INLINE sw_extFloat80_t floatx80_sqrt(sw_extFloat80_t a) { static void fpu_check_NM_EXCEPTION(){ - // ^XNXCb`܂̓G~[VNM(foCXgps—O)𔭐 + // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { EXCEPTION(NM_EXCEPTION, 0); } } static void fpu_check_NM_EXCEPTION2(){ - // ^XNXCb`܂̓G~[VNM(foCXgps—O)𔭐 + // タスクスイッチまたはエミュレーション時にNM(デバイス使用不可例外)を発生させる if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { EXCEPTION(NM_EXCEPTION, 0); } @@ -296,17 +296,17 @@ static void FPU_FBLD(UINT32 addr, UINT reg) SINT64 val = 0; UINT8 in = 0; - // 80bit܂Ƃ߂ēǂݎ + // 80bitまとめて読み取り bcdbuf = fpu_memoryread_f(addr); - // 0`8byteڂ̏ BCD + // 0~8byte目の処理 BCD for (i = 8; i >= 0; i--) { in = bcdbuf.b[i]; tmp = ((in >> 4) & 0xf) * 10 + (in & 0xf); val = val * 100 + tmp; } - // 9byteڂ͕݈̂Ӗ + // 9byte目は符号のみ意味がある if (bcdbuf.b[9] & 0x80) { val = -val; } @@ -374,14 +374,14 @@ static void FPU_FBST(UINT32 addr) val = floatx80_to_int64(FPU_STAT.reg[FPU_STAT_TOP].d); - // 9byteڂ͕݈̂Ӗ + // 9byte目は符号のみ意味がある if (val < 0) { bcdbuf.b[9] = 0x80; val = -val; } - // 0`8byteڂ̏ BCD + // 0~8byte目の処理 BCD for (i = 0; i < 9; i++) { bcdbuf.b[i] = (UINT8)(val % 10); val /= 10; @@ -389,7 +389,7 @@ static void FPU_FBST(UINT32 addr) val /= 10; } - // 80bit܂Ƃ߂ď + // 80bitまとめて書き込み fpu_memorywrite_f(addr, &bcdbuf); softfloat_roundingMode = oldrnd; @@ -409,7 +409,7 @@ FPU_FINIT(void) FPU_STATUSWORD = 0; FPU_STAT_TOP=FP_TOP_GET(); for(i=0;i<8;i++){ - // EmptyZbgĂWX^̓e͏Ă͂Ȃ + // Emptyセットしてもレジスタの内容は消してはいけない FPU_STAT.tag[i] = TAG_Empty; } FPU_STAT.tag[8] = TAG_Valid; // dummy @@ -497,7 +497,7 @@ static void FPU_pop(void) { * FPU instruction */ - // WX^ + // レジスタ操作 static void FPU_FST(UINT st, UINT other) { FPU_STAT.tag[other] = FPU_STAT.tag[st]; FPU_STAT.reg[other] = FPU_STAT.reg[st]; @@ -544,7 +544,7 @@ static void FPU_FLDZ(void) { FPU_STAT.mmxenable = 0; } -// lZ +// 四則演算 static void FPU_FADD(UINT op1, UINT op2) { FPU_ConvertToSoftFloatFlags(); FPU_STAT.reg[op1].d = floatx80_add(FPU_STAT.reg[op1].d, FPU_STAT.reg[op2].d); @@ -605,14 +605,14 @@ static void FPU_FPREM(void) { FPU_ConvertToSoftFloatFlags(); val = FPU_STAT.reg[FPU_STAT_TOP].d; div = FPU_STAT.reg[FPU_ST(1)].d; - qint = floatx80_to_int64_round_to_zero(floatx80_div(val, div)); // int(폜 / ) = + qint = floatx80_to_int64_round_to_zero(floatx80_div(val, div)); // int(被除数 / 除数) = 商 - FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_sub(val, floatx80_mul(int64_to_floatx80(qint), div)); // 폜 - x = ] + FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_sub(val, floatx80_mul(int64_to_floatx80(qint), div)); // 被除数 - 商 x 除数 = 剰余 FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C1_FLAG | FP_C2_FLAG | FP_C3_FLAG); - if(qint & 4) FPU_STATUSWORD |= FP_C0_FLAG; // bit2 - if(qint & 2) FPU_STATUSWORD |= FP_C3_FLAG; // bit1 - if(qint & 1) FPU_STATUSWORD |= FP_C1_FLAG; // bit0 - // C2NAŊ + if(qint & 4) FPU_STATUSWORD |= FP_C0_FLAG; // 商のbit2 + if(qint & 2) FPU_STATUSWORD |= FP_C3_FLAG; // 商のbit1 + if(qint & 1) FPU_STATUSWORD |= FP_C1_FLAG; // 商のbit0 + // C2クリアで完了扱い FPU_ConvertFromSoftFloatFlags(); } @@ -621,26 +621,26 @@ static void FPU_FPREM1(void) { SINT64 qint; uint_fast8_t oldrnd = softfloat_roundingMode; - // IEEE 754 ]@ł߂lƂB]肪lɂȂ邱ƂL蓾 + // IEEE 754 剰余 商を最も近い整数値とする。余りが負値になることが有り得る FPU_ConvertToSoftFloatFlags(); val = FPU_STAT.reg[FPU_STAT_TOP].d; div = FPU_STAT.reg[FPU_ST(1)].d; - q = floatx80_add(floatx80_div(val, div), c_double_to_floatx80(0.5)); // floor(l + 0.5)Ŏľܓ ɂ͕l̋EňႤX鍷ƂċCɂȂƂɂB + q = floatx80_add(floatx80_div(val, div), c_double_to_floatx80(0.5)); // floor(値 + 0.5)で四捨五入 厳密には負値の境界で違うが微々たる差として気にしないことにする。 softfloat_roundingMode = softfloat_round_min; - qint = floatx80_to_int64(q); // ľܓ(폜 / ) = łɋ߂ + qint = floatx80_to_int64(q); // 四捨五入(被除数 / 除数) = 最も整数に近い商 - FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_sub(val, floatx80_mul(int64_to_floatx80(qint), div)); // 폜 - x = ] + FPU_STAT.reg[FPU_STAT_TOP].d = floatx80_sub(val, floatx80_mul(int64_to_floatx80(qint), div)); // 被除数 - 商 x 除数 = 剰余 FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C1_FLAG | FP_C2_FLAG | FP_C3_FLAG); - if(qint & 4) FPU_STATUSWORD |= FP_C0_FLAG; // bit2 - if(qint & 2) FPU_STATUSWORD |= FP_C3_FLAG; // bit1 - if(qint & 1) FPU_STATUSWORD |= FP_C1_FLAG; // bit0 - // C2NAŊ + if(qint & 4) FPU_STATUSWORD |= FP_C0_FLAG; // 商のbit2 + if(qint & 2) FPU_STATUSWORD |= FP_C3_FLAG; // 商のbit1 + if(qint & 1) FPU_STATUSWORD |= FP_C1_FLAG; // 商のbit0 + // C2クリアで完了扱い softfloat_roundingMode = oldrnd; FPU_ConvertFromSoftFloatFlags(); } -// w֐ +// 数学関数 static void FPU_FSIN(void) { FPU_ConvertToSoftFloatFlags(); FPU_STAT.reg[FPU_STAT_TOP].d = c_double_to_floatx80(sin(floatx80_to_c_double(FPU_STAT.reg[FPU_STAT_TOP].d))); @@ -713,7 +713,7 @@ static void FPU_FABS(void) { FPU_STAT.reg[FPU_STAT_TOP].b[9] &= ~0x80; } -// r +// 比較 static void FPU_FCOM(UINT st, UINT other) { FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C2_FLAG | FP_C3_FLAG); if (((FPU_STAT.tag[st] != TAG_Valid) && (FPU_STAT.tag[st] != TAG_Zero)) || @@ -743,11 +743,11 @@ static void FPU_FCOMI(UINT st, UINT other) { } } static void FPU_FUCOM(UINT st, UINT other) { - // Ő݂ႤقړƂăX[ + // 例外絡みの挙動が違うがほぼ同じとしてスルー FPU_FCOM(st, other); } static void FPU_FUCOMI(UINT st, UINT other) { - // Ő݂ႤقړƂăX[ + // 例外絡みの挙動が違うがほぼ同じとしてスルー FPU_FCOMI(st, other); } static INLINE void FPU_FCOM_EA(UINT op1) { @@ -758,7 +758,7 @@ static void FPU_FTST(void) { FPU_FCOM(FPU_STAT_TOP, 8); } -// tRs[ +// 条件付きコピー static void FPU_FCMOVB(UINT st, UINT other) { if (CPU_FLAGL & C_FLAG) { FPU_STAT.tag[st] = FPU_STAT.tag[other]; @@ -808,7 +808,7 @@ static void FPU_FCMOVNU(UINT st, UINT other) { } } -// _ +// 浮動小数点数操作 static void FPU_FXAM(void) { FPU_STATUSWORD &= ~(FP_C0_FLAG | FP_C1_FLAG | FP_C2_FLAG | FP_C3_FLAG); if (FPU_STAT.reg[FPU_STAT_TOP].d.signExp & 0x8000) { @@ -839,13 +839,13 @@ static void FPU_FXTRACT(void) { sw_extFloat80_t fracval; fracval = FPU_STAT.reg[FPU_STAT_TOP].d; - expval = (SINT32)((UINT16)fracval.signExp & 0x7FFF) - 0x3FFF; // w𒊏oAoCAX - fracval.signExp = (SINT16)(((UINT16)fracval.signExp & 0x8000) | 0x3FFF); // ͎cAw0x3FFFioCAX=0jɂĉɂ - FPU_STAT.reg[FPU_STAT_TOP].d = int64_to_floatx80(expval); // w̏ - FPU_push(fracval); // push + expval = (SINT32)((UINT16)fracval.signExp & 0x7FFF) - 0x3FFF; // 指数部分を抽出、バイアス分を引く + fracval.signExp = (SINT16)(((UINT16)fracval.signExp & 0x8000) | 0x3FFF); // 符号は残し、指数部分を0x3FFF(バイアス分=0)にして仮数だけにする + FPU_STAT.reg[FPU_STAT_TOP].d = int64_to_floatx80(expval); // 指数の書き込み + FPU_push(fracval); // 仮数のpush } -// ‹[hEXgA +// 環境ロード・ストア static void FPU_FSTENV(UINT32 addr) { FP_TOP_SET(FPU_STAT_TOP); @@ -973,12 +973,12 @@ void SF_FPU_FXSAVERSTOR(void) { switch (idx) { case 0: // FXSAVE - fpu_check_NM_EXCEPTION2(); // XXX: + fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し maddr = calc_ea_dst(op); FPU_FXSAVE(maddr); break; case 1: // FXRSTOR - fpu_check_NM_EXCEPTION2(); // XXX: + fpu_check_NM_EXCEPTION2(); // XXX: 根拠無し maddr = calc_ea_dst(op); FPU_FXRSTOR(maddr); break; @@ -1017,42 +1017,42 @@ static void EA_TREE(UINT op) idx = (op >> 3) & 7; switch (idx) { - case 0: /* FADD (Px) */ + case 0: /* FADD (単精度実数) */ TRACEOUT(("FADD EA")); FPU_STATUSWORD &= ~FP_C1_FLAG; FPU_FADD_EA(FPU_STAT_TOP); break; - case 1: /* FMUL (Px) */ + case 1: /* FMUL (単精度実数) */ TRACEOUT(("FMUL EA")); FPU_STATUSWORD &= ~FP_C1_FLAG; FPU_FMUL_EA(FPU_STAT_TOP); break; - case 2: /* FCOM (Px) */ + case 2: /* FCOM (単精度実数) */ TRACEOUT(("FCOM EA")); FPU_STATUSWORD &= ~FP_C1_FLAG; FPU_FCOM_EA(FPU_STAT_TOP); break; - case 3: /* FCOMP (Px) */ + case 3: /* FCOMP (単精度実数) */ TRACEOUT(("FCOMP EA")); FPU_FCOM_EA(FPU_STAT_TOP); FPU_pop(); break; - case 4: /* FSUB (Px) */ + case 4: /* FSUB (単精度実数) */ TRACEOUT(("FSUB EA")); FPU_STATUSWORD &= ~FP_C1_FLAG; FPU_FSUB_EA(FPU_STAT_TOP); break; - case 5: /* FSUBR (Px) */ + case 5: /* FSUBR (単精度実数) */ TRACEOUT(("FSUBR EA")); FPU_STATUSWORD &= ~FP_C1_FLAG; FPU_FSUBR_EA(FPU_STAT_TOP); break; - case 6: /* FDIV (Px) */ + case 6: /* FDIV (単精度実数) */ TRACEOUT(("FDIV EA")); FPU_STATUSWORD &= ~FP_C1_FLAG; FPU_FDIV_EA(FPU_STAT_TOP); break; - case 7: /* FDIVR (Px) */ + case 7: /* FDIVR (単精度実数) */ TRACEOUT(("FDIVR EA")); FPU_STATUSWORD &= ~FP_C1_FLAG; FPU_FDIVR_EA(FPU_STAT_TOP); @@ -1360,7 +1360,7 @@ SF_ESC1(void) } else { madr = calc_ea_dst(op); switch (idx) { - case 0: /* FLD (Px) */ + case 0: /* FLD (単精度実数) */ TRACEOUT(("FLD float")); FPU_prepush(); FPU_FLD_F32(madr,FPU_STAT_TOP); @@ -1369,13 +1369,13 @@ SF_ESC1(void) case 1: /* UNKNOWN */ break; - case 2: /* FST (Px) */ + case 2: /* FST (単精度実数) */ TRACEOUT(("FST float")); FPU_FST_F32(madr); FPU_STATUSWORD &= ~FP_C1_FLAG; break; - case 3: /* FSTP (Px) */ + case 3: /* FSTP (単精度実数) */ TRACEOUT(("FSTP float")); FPU_FST_F32(madr); FPU_pop(); @@ -1579,13 +1579,13 @@ SF_ESC3(void) FPU_pop(); break; - case 5: /* FLD (g) */ + case 5: /* FLD (拡張実数) */ TRACEOUT(("FLD 80 Bits Real")); FPU_prepush(); FPU_FLD_F80(madr); break; - case 7: /* FSTP (g) */ + case 7: /* FSTP (拡張実数) */ TRACEOUT(("FSTP 80 Bits Real")); FPU_FST_F80(madr); FPU_pop(); @@ -1721,7 +1721,7 @@ SF_ESC5(void) } else { madr = calc_ea_dst(op); switch (idx) { - case 0: /* FLD ({x) */ + case 0: /* FLD (倍精度実数) */ TRACEOUT(("FLD double real")); FPU_prepush(); FPU_FLD_F64(madr,FPU_STAT_TOP); @@ -1735,12 +1735,12 @@ SF_ESC5(void) } FPU_pop(); break; - case 2: /* FST ({x) */ + case 2: /* FST (倍精度実数) */ TRACEOUT(("FST double real")); FPU_FST_F64(madr); FPU_STATUSWORD &= ~FP_C1_FLAG; break; - case 3: /* FSTP ({x) */ + case 3: /* FSTP (倍精度実数) */ TRACEOUT(("FSTP double real")); FPU_FST_F64(madr); FPU_pop(); @@ -1801,7 +1801,7 @@ SF_ESC6(void) return; } FPU_FCOM(FPU_STAT_TOP,FPU_ST(1)); - FPU_pop(); // R[hƍ킹2pop + FPU_pop(); // 下コードと合わせて2回pop break; case 4: /* FSUBRP */ TRACEOUT(("FSUBRP")); @@ -1815,14 +1815,14 @@ SF_ESC6(void) TRACEOUT(("FDIVRP")); FPU_FDIVR(FPU_ST(sub),FPU_STAT_TOP); if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ - return; // POPȂ悤ɂ + return; // POPしないようにする } break; case 7: /* FDIVP */ TRACEOUT(("FDIVP")); FPU_FDIV(FPU_ST(sub),FPU_STAT_TOP); if((FPU_STATUSWORD & ~FPU_CTRLWORD) & FP_ZE_FLAG){ - return; // POPȂ悤ɂ + return; // POPしないようにする } break; /*FALLTHROUGH*/ diff --git a/i386c/ia32/instructions/fpu/fpumem.h b/i386c/ia32/instructions/fpu/fpumem.h old mode 100755 new mode 100644 index 371748f4..0d7778cd --- a/i386c/ia32/instructions/fpu/fpumem.h +++ b/i386c/ia32/instructions/fpu/fpumem.h @@ -1,82 +1,82 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_FPU_FPUMEM_H__ -#define IA32_CPU_INSTRUCTION_FPU_FPUMEM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * FPU memory access function - */ -UINT8 MEMCALL -fpu_memoryread_b(UINT32 address); - -UINT16 MEMCALL -fpu_memoryread_w(UINT32 address); - -UINT32 MEMCALL -fpu_memoryread_d(UINT32 address); - -UINT64 MEMCALL -fpu_memoryread_q(UINT32 address); - -REG80 MEMCALL -fpu_memoryread_f(UINT32 address); - -float MEMCALL -fpu_memoryread_f32(UINT32 address); - -double MEMCALL -fpu_memoryread_f64(UINT32 address); - -void MEMCALL -fpu_memorywrite_b(UINT32 address, UINT8 value); - -void MEMCALL -fpu_memorywrite_w(UINT32 address, UINT16 value); - -void MEMCALL -fpu_memorywrite_d(UINT32 address, UINT32 value); - -void MEMCALL -fpu_memorywrite_q(UINT32 address, UINT64 value); - -void MEMCALL -fpu_memorywrite_f(UINT32 address, REG80 *value); - -void MEMCALL -fpu_memorywrite_f32(UINT32 address, float value); - -void MEMCALL -fpu_memorywrite_f64(UINT32 address, double value); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_FPU_FP_H__ */ +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_FPU_FPUMEM_H__ +#define IA32_CPU_INSTRUCTION_FPU_FPUMEM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * FPU memory access function + */ +UINT8 MEMCALL +fpu_memoryread_b(UINT32 address); + +UINT16 MEMCALL +fpu_memoryread_w(UINT32 address); + +UINT32 MEMCALL +fpu_memoryread_d(UINT32 address); + +UINT64 MEMCALL +fpu_memoryread_q(UINT32 address); + +REG80 MEMCALL +fpu_memoryread_f(UINT32 address); + +float MEMCALL +fpu_memoryread_f32(UINT32 address); + +double MEMCALL +fpu_memoryread_f64(UINT32 address); + +void MEMCALL +fpu_memorywrite_b(UINT32 address, UINT8 value); + +void MEMCALL +fpu_memorywrite_w(UINT32 address, UINT16 value); + +void MEMCALL +fpu_memorywrite_d(UINT32 address, UINT32 value); + +void MEMCALL +fpu_memorywrite_q(UINT32 address, UINT64 value); + +void MEMCALL +fpu_memorywrite_f(UINT32 address, REG80 *value); + +void MEMCALL +fpu_memorywrite_f32(UINT32 address, float value); + +void MEMCALL +fpu_memorywrite_f64(UINT32 address, double value); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_FPU_FP_H__ */ diff --git a/i386c/ia32/instructions/fpu/softfloat/README.txt b/i386c/ia32/instructions/fpu/softfloat/README.txt index e56debf4..1d7c4908 100644 --- a/i386c/ia32/instructions/fpu/softfloat/README.txt +++ b/i386c/ia32/instructions/fpu/softfloat/README.txt @@ -1,83 +1,83 @@ - -Package Overview for Berkeley SoftFloat Release 2c - -John R. Hauser -2015 January 30 - - ----------------------------------------------------------------------------- -Overview - -Berkeley SoftFloat is a software implementation of binary floating-point -that conforms to the IEEE Standard for Floating-Point Arithmetic. -Release 2c updates an older version of SoftFloat that has for most purposes -been supplanted by Release 3 or later. For the latest version of SoftFloat, -see Web page `http://www.jhauser.us/arithmetic/SoftFloat.html'. - -SoftFloat is distributed in the form of C source code. For Release 2c, -compiling the SoftFloat sources generates two things: - --- A SoftFloat object file (typically `softfloat.o') containing the complete - set of IEC/IEEE floating-point routines. - --- A `timesoftfloat' program for evaluating the speed of the SoftFloat - routines. (The SoftFloat module is linked into this program.) - -This version of the SoftFloat package is documented in four text files: - - SoftFloat.txt Documentation for using the SoftFloat functions. - SoftFloat-source.txt Documentation for compiling SoftFloat. - SoftFloat-history.txt History of major changes to SoftFloat. - timesoftfloat.txt Documentation for using `timesoftfloat'. - -Other files in the package comprise the source code for SoftFloat. - -Please be aware that some work is involved in porting this software to other -targets. It is not just a matter of getting `make' to complete without -error messages. You should not attempt to compile this release of SoftFloat -without first reading both `SoftFloat.txt' and `SoftFloat-source.txt'. -Depending on your needs, you may find that newer versions of SoftFloat are -less work to port. - - ----------------------------------------------------------------------------- -Legal Notice - -SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made -possible in part by the International Computer Science Institute, located -at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding -was partially provided by the National Science Foundation under grant -MIP-9311980. The original version of this code was written as part of a -project to build a fixed-point vector processor in collaboration with the -University of California at Berkeley, overseen by Profs. Nelson Morgan and -John Wawrzynek. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort -has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT -TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO -PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR -OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN -HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, -OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF -THE SOFTWARE. - -The following are expressly permitted, even for commercial purposes: -(1) distribution of SoftFloat in whole or in part, as long as this and -other legal notices remain and are prominent, and provided also that, for a -partial distribution, prominent notice is given that it is a subset of the -original; and -(2) inclusion or use of SoftFloat in whole or in part in a derivative -work, provided that the use restrictions above are met and the minimal -documentation requirements stated in the source code are satisfied. - - ----------------------------------------------------------------------------- -Contact Information - -At the time of this writing, the most up-to-date information about SoftFloat -and the latest release can be found at the Web page `http://www.jhauser.us/ -arithmetic/SoftFloat.html'. - + +Package Overview for Berkeley SoftFloat Release 2c + +John R. Hauser +2015 January 30 + + +---------------------------------------------------------------------------- +Overview + +Berkeley SoftFloat is a software implementation of binary floating-point +that conforms to the IEEE Standard for Floating-Point Arithmetic. +Release 2c updates an older version of SoftFloat that has for most purposes +been supplanted by Release 3 or later. For the latest version of SoftFloat, +see Web page `http://www.jhauser.us/arithmetic/SoftFloat.html'. + +SoftFloat is distributed in the form of C source code. For Release 2c, +compiling the SoftFloat sources generates two things: + +-- A SoftFloat object file (typically `softfloat.o') containing the complete + set of IEC/IEEE floating-point routines. + +-- A `timesoftfloat' program for evaluating the speed of the SoftFloat + routines. (The SoftFloat module is linked into this program.) + +This version of the SoftFloat package is documented in four text files: + + SoftFloat.txt Documentation for using the SoftFloat functions. + SoftFloat-source.txt Documentation for compiling SoftFloat. + SoftFloat-history.txt History of major changes to SoftFloat. + timesoftfloat.txt Documentation for using `timesoftfloat'. + +Other files in the package comprise the source code for SoftFloat. + +Please be aware that some work is involved in porting this software to other +targets. It is not just a matter of getting `make' to complete without +error messages. You should not attempt to compile this release of SoftFloat +without first reading both `SoftFloat.txt' and `SoftFloat-source.txt'. +Depending on your needs, you may find that newer versions of SoftFloat are +less work to port. + + +---------------------------------------------------------------------------- +Legal Notice + +SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made +possible in part by the International Computer Science Institute, located +at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding +was partially provided by the National Science Foundation under grant +MIP-9311980. The original version of this code was written as part of a +project to build a fixed-point vector processor in collaboration with the +University of California at Berkeley, overseen by Profs. Nelson Morgan and +John Wawrzynek. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR +OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN +HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, +OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF +THE SOFTWARE. + +The following are expressly permitted, even for commercial purposes: +(1) distribution of SoftFloat in whole or in part, as long as this and +other legal notices remain and are prominent, and provided also that, for a +partial distribution, prominent notice is given that it is a subset of the +original; and +(2) inclusion or use of SoftFloat in whole or in part in a derivative +work, provided that the use restrictions above are met and the minimal +documentation requirements stated in the source code are satisfied. + + +---------------------------------------------------------------------------- +Contact Information + +At the time of this writing, the most up-to-date information about SoftFloat +and the latest release can be found at the Web page `http://www.jhauser.us/ +arithmetic/SoftFloat.html'. + diff --git a/i386c/ia32/instructions/fpu/softfloat/SoftFloat-history.txt b/i386c/ia32/instructions/fpu/softfloat/SoftFloat-history.txt index 4634fede..daabf0e6 100644 --- a/i386c/ia32/instructions/fpu/softfloat/SoftFloat-history.txt +++ b/i386c/ia32/instructions/fpu/softfloat/SoftFloat-history.txt @@ -1,65 +1,65 @@ - -History of Major Changes to Berkeley SoftFloat, up to Release 2c - -John R. Hauser -2015 January 31 - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Release 2c (2015 January) - --- Fixed mistakes affecting some 64-bit processors. - --- Further improved the documentation and the wording for the legal - restrictions on using SoftFloat. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Release 2b (2002 May) - --- Made minor updates to the documentation, including improved wording for - the legal restrictions on using SoftFloat. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Release 2a (1998 December) - --- Added functions to convert between 64-bit integers (int64) and all - supported floating-point formats. - --- Fixed a bug in all 64-bit-version square root functions except - `float32_sqrt' that caused the result sometimes to be off by 1 unit in - the last place (1 ulp) from what it should be. (Bug discovered by Paul - Donahue.) - --- Improved the Makefiles. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Release 2 (1997 June) - --- Created the 64-bit (bits64) version, adding the floatx80 and float128 - formats. - --- Changed the source directory structure, splitting the sources into a - `bits32' and a `bits64' version. Renamed `environment.h' to `milieu.h' - to avoid confusion with environment variables. - --- Fixed a small error that caused `float64_round_to_int' often to round the - wrong way in nearest/even mode when the operand was between 2^20 and 2^21 - and halfway between two integers. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Release 1a (1996 July) - --- Corrected a mistake that caused borderline underflow cases not to raise - the underflow flag when they should have. (Problem reported by Doug - Priest.) - --- Added the `float_detect_tininess' variable to control whether tininess is - detected before or after rounding. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Release 1 (1996 July) - --- Original release. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +History of Major Changes to Berkeley SoftFloat, up to Release 2c + +John R. Hauser +2015 January 31 + + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Release 2c (2015 January) + +-- Fixed mistakes affecting some 64-bit processors. + +-- Further improved the documentation and the wording for the legal + restrictions on using SoftFloat. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Release 2b (2002 May) + +-- Made minor updates to the documentation, including improved wording for + the legal restrictions on using SoftFloat. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Release 2a (1998 December) + +-- Added functions to convert between 64-bit integers (int64) and all + supported floating-point formats. + +-- Fixed a bug in all 64-bit-version square root functions except + `float32_sqrt' that caused the result sometimes to be off by 1 unit in + the last place (1 ulp) from what it should be. (Bug discovered by Paul + Donahue.) + +-- Improved the Makefiles. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Release 2 (1997 June) + +-- Created the 64-bit (bits64) version, adding the floatx80 and float128 + formats. + +-- Changed the source directory structure, splitting the sources into a + `bits32' and a `bits64' version. Renamed `environment.h' to `milieu.h' + to avoid confusion with environment variables. + +-- Fixed a small error that caused `float64_round_to_int' often to round the + wrong way in nearest/even mode when the operand was between 2^20 and 2^21 + and halfway between two integers. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Release 1a (1996 July) + +-- Corrected a mistake that caused borderline underflow cases not to raise + the underflow flag when they should have. (Problem reported by Doug + Priest.) + +-- Added the `float_detect_tininess' variable to control whether tininess is + detected before or after rounding. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Release 1 (1996 July) + +-- Original release. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/i386c/ia32/instructions/fpu/softfloat/SoftFloat-source.txt b/i386c/ia32/instructions/fpu/softfloat/SoftFloat-source.txt index 523d0706..ed14355a 100644 --- a/i386c/ia32/instructions/fpu/softfloat/SoftFloat-source.txt +++ b/i386c/ia32/instructions/fpu/softfloat/SoftFloat-source.txt @@ -1,400 +1,400 @@ - -Berkeley SoftFloat Release 2c Source Documentation - -John R. Hauser -2015 January 30 - - ----------------------------------------------------------------------------- -Introduction - -Berkeley SoftFloat is a software implementation of binary floating-point -that conforms to the IEEE Standard for Floating-Point Arithmetic. -Release 2c of SoftFloat can support four floating-point formats: 32-bit -single-precision, 64-bit double-precision, 80-bit double-extended-precision, -and 128-bit quadruple-precision. All operations required by the older 1985 -version of the IEEE Standard are implemented, except for conversions to and -from decimal. SoftFloat is distributed in the form of C source code, so a -C compiler is needed to compile the code. Support for the 80-bit double- -extended-precision and 128-bit quadruple-precision formats is dependent on -the C compiler implementing a 64-bit integer type. - -This document gives information needed for compiling and/or porting this -SoftFloat release. - -The source code for SoftFloat is intended to be relatively machine- -independent and should be compilable using most any ISO/ANSI C compiler. At -the time of this writing, SoftFloat has been successfully compiled with the -GNU C Compiler (`gcc') for several platforms. - - ----------------------------------------------------------------------------- -Limitations - -As supplied, SoftFloat requires an ISO/ANSI-style C compiler. No attempt -has been made to accomodate compilers that are not ISO-conformant. Older -"K&R-style" compilers are not adequate for compiling SoftFloat. All testing -I have done so far has been with the GNU C Compiler. Compilation with other -compilers should be possible but has not been tested by me. - -The SoftFloat sources assume that source code file names can be longer than -8 characters. In order to compile under an MS-DOS-type system, many of the -source files will need to be renamed, and the source and Makefiles edited -appropriately. Once compiled, the SoftFloat binary does not depend on the -existence of long file names. - -The underlying machine is assumed to be binary with a word size that is a -power of 2. Bytes are 8 bits. Arithmetic on signed integers must modularly -wrap around on overflows (as is already required for unsigned integers -in C). - -Support for the 80-bit double-extended-precision and 128-bit quadruple- -precision formats depends on the C compiler implementing a 64-bit integer -type. If the largest integer type supported by the C compiler is 32 bits, -SoftFloat is limited to the 32-bit single-precision and 64-bit double- -precision formats. - - ----------------------------------------------------------------------------- -Contents - - Introduction - Limitations - Contents - Legal Notice - SoftFloat Source Directory Structure - SoftFloat Source Files - processors/*.h - softfloat/bits*/*/softfloat.h - softfloat/bits*/*/milieu.h - softfloat/bits*/*/softfloat-specialize - softfloat/bits*/softfloat-macros - softfloat/bits*/softfloat.c - Steps to Creating a `softfloat.o' - Making `softfloat.o' a Library - Testing SoftFloat - Timing SoftFloat - Compiler Options and Efficiency - Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros' - Contact Information - - - ----------------------------------------------------------------------------- -Legal Notice - -SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made -possible in part by the International Computer Science Institute, located -at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding -was partially provided by the National Science Foundation under grant -MIP-9311980. The original version of this code was written as part of a -project to build a fixed-point vector processor in collaboration with the -University of California at Berkeley, overseen by Profs. Nelson Morgan and -John Wawrzynek. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort -has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT -TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO -PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR -OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN -HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, -OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF -THE SOFTWARE. - -The following are expressly permitted, even for commercial purposes: -(1) distribution of SoftFloat in whole or in part, as long as this and -other legal notices remain and are prominent, and provided also that, for a -partial distribution, prominent notice is given that it is a subset of the -original; and -(2) inclusion or use of SoftFloat in whole or in part in a derivative -work, provided that the use restrictions above are met and the minimal -documentation requirements stated in the source code are satisfied. - - ----------------------------------------------------------------------------- -SoftFloat Source Directory Structure - -Because SoftFloat is targeted to multiple platforms, its source code -is slightly scattered between target-specific and target-independent -directories and files. The directory structure is as follows: - - processors - softfloat - bits64 - templates - 386-Win32-GCC - SPARC-Solaris-GCC - bits32 - templates - 386-Win32-GCC - SPARC-Solaris-GCC - -The two topmost directories and their contents are: - - softfloat - Most of the source code needed for SoftFloat. - processors - Target-specific header files that are not specific to - SoftFloat. - -The `softfloat' directory is further split into two parts: - - bits64 - SoftFloat implementation using 64-bit integers. - bits32 - SoftFloat implementation using only 32-bit integers. - -Within these directories are subdirectories for each of the targeted -platforms. The SoftFloat source code is distributed with targets -`386-Win32-GCC' and `SPARC-Solaris-GCC' (and perhaps others) already -prepared for both the 32-bit and 64-bit implementations. Source files -that are not within these target-specific subdirectories are intended to be -target-independent. - -The naming convention used for the target-specific directories is -`--'. The names of the supplied -target directories should be interpreted as follows: - - : - 386 - Intel 386-compatible processor. - SPARC - SPARC processor (as used by Sun computers). - : - Win32 - Microsoft Win32 executable. - Solaris - Sun Solaris executable. - : - GCC - GNU C Compiler. - -You do not need to maintain this convention if you do not want to. - -Alongside the supplied target-specific directories is a `templates' -directory containing a set of "generic" target-specific source files. A -new target directory can be created by copying the `templates' directory and -editing the files inside. (Complete instructions for porting SoftFloat to -a new target are in the section _Steps to Creating a `softfloat.o'_.) Note -that the `templates' directory will not work as a target directory without -some editing. To avoid confusion, it would be wise to refrain from editing -the files inside `templates' directly. - - ----------------------------------------------------------------------------- -SoftFloat Source Files - -The purpose of each source file is described below. In the following, -the `*' symbol is used in place of the name of a specific target, such as -`386-Win32-GCC' or `SPARC-Solaris-GCC', or in place of some other text, as -in `bits*' for either `bits32' or `bits64'. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -processors/*.h - -The target-specific `processors' header file defines integer types -of various sizes, and also defines certain C preprocessor macros that -characterize the target. The two examples supplied are `386-GCC.h' and -`SPARC-GCC.h'. The naming convention used for processor header files is -`-.h'. - -If 64-bit integers are supported by the compiler, the macro name `BITS64' -should be defined here along with the corresponding 64-bit integer -types. In addition, the function-like macro `LIT64' must be defined for -constructing 64-bit integer literals (constants). The `LIT64' macro is used -consistently in the SoftFloat code to annotate 64-bit literals. - -If `BITS64' is not defined, only the 32-bit version of SoftFloat can be -compiled. If `BITS64' _is_ defined, either can be compiled. - -If an inlining attribute (such as an `inline' keyword) is provided by the -compiler, the macro `INLINE' should be defined to the appropriate keyword. -If not, `INLINE' can be set to the keyword `static'. The `INLINE' macro -appears in the SoftFloat source code before every function that should -be inlined by the compiler. SoftFloat depends on inlining to obtain -good speed. Even if inlining cannot be forced with a language keyword, -the compiler may still be able to perform inlining on its own as an -optimization. If a command-line option is needed to convince the compiler -to perform this optimization, this should be assured in the Makefile. (See -the section _Compiler Options and Efficiency_ below.) - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -softfloat/bits*/*/softfloat.h - -The target-specific `softfloat.h' header file defines the SoftFloat -interface as seen by clients. - -Unlike the actual function definitions in `softfloat.c', the declarations -in `softfloat.h' do not use any of the types defined by the `processors' -header file. This is done so that clients will not have to include the -`processors' header file in order to use SoftFloat. Nevertheless, the -target-specific declarations in `softfloat.h' must match what `softfloat.c' -expects. For example, if `int32' is defined as `int' in the `processors' -header file, then in `softfloat.h' the output of `float32_to_int32' should -be stated as `int', although in `softfloat.c' it is given in target- -independent form as `int32'. - -For the `bits64' implementation of SoftFloat, the macro names `FLOATX80' -and `FLOAT128' must be defined in order for the 80-bit double-extended- -precision and 128-bit quadruple-precision formats to be enabled in the -code. Conversely, either or both of these larger formats can be disabled by -simply removing the `#define' of the respective macro. When a format is not -enabled, none of the functions that either input or output the format are -defined, and no space is taken up in `softfloat.o' by such functions. There -is no provision for disabling the usual 32-bit single-precision and 64-bit -double-precision formats. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -softfloat/bits*/*/milieu.h - -The target-specific `milieu.h' header file provides declarations that are -needed to compile SoftFloat. In addition, deviations from ISO/ANSI C by -the compiler (such as names not properly declared in system header files) -are corrected in this header if possible. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -softfloat/bits*/*/softfloat-specialize - -This target-specific C source fragment defines: - --- whether tininess for underflow is detected before or after rounding by - default; --- what (if anything) special happens when exceptions are raised; --- how signaling NaNs are distinguished from quiet NaNs; --- the default generated quiet NaNs; and --- how NaNs are propagated from function inputs to output. - -These details are not decided by the IEEE Standard. This fragment is -included verbatim within `softfloat.c' when SoftFloat is compiled. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -softfloat/bits*/softfloat-macros - -This target-independent C source fragment defines a number of arithmetic -functions used as primitives within the `softfloat.c' source. Most of -the functions defined here are intended to be inlined for efficiency. -This fragment is included verbatim within `softfloat.c' when SoftFloat is -compiled. - -Target-specific variations on this file are possible. See the section -_Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros'_ -below. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -softfloat/bits*/softfloat.c - -The target-independent `softfloat.c' source file contains the body of the -SoftFloat implementation. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The inclusion of the files above within each other (using `#include') can be -shown graphically as follows: - - softfloat/bits*/softfloat.c - softfloat/bits*/*/milieu.h - processors/*.h - softfloat/bits*/*/softfloat.h - softfloat/bits*/*/softfloat-specialize - softfloat/bits*/softfloat-macros - -Note in particular that `softfloat.c' does not include the `processors' -header file directly. Rather, `softfloat.c' includes the target-specific -`milieu.h' header file, which in turn includes the appropriate processor -header file. - - ----------------------------------------------------------------------------- -Steps to Creating a `softfloat.o' - -Porting and/or compiling SoftFloat involves the following steps: - -1. If one does not already exist, create an appropriate `.h' file in the - `processors' directory. - -2. If `BITS64' is defined in the `processors' header file, choose whether - to compile the 32-bit or 64-bit implementation of SoftFloat. If - `BITS64' is not defined, your only choice is the 32-bit implementation. - The remaining steps occur within either the `bits32' or `bits64' - subdirectories. - -3. If one does not already exist, create an appropriate target-specific - subdirectory by copying the given `templates' directory. - -4. In the target-specific subdirectory, edit the files `softfloat-specialize' - and `softfloat.h' to define the desired exception handling functions - and mode control values. In the `softfloat.h' header file, ensure also - that all declarations give the proper target-specific type (such as - `int' or `long') corresponding to the target-independent type used in - `softfloat.c' (such as `int32'). None of the type names declared in the - `processors' header file should appear in `softfloat.h'. - -5. In the target-specific subdirectory, edit the files `milieu.h' and - `Makefile' to reflect the current environment. - -6. In the target-specific subdirectory, execute `make'. - -For the targets that are supplied, if the expected compiler is available -(usually `gcc'), it should only be necessary to execute `make' in the -target-specific subdirectory. - - ----------------------------------------------------------------------------- -Making `softfloat.o' a Library - -SoftFloat is not made into a software library by the supplied Makefile. -If desired, `softfloat.o' can easily be put into its own library (typically -`softfloat.a' or `libsoftfloat.a') using the usual system tool (in UNIX, -`ar'). - - ----------------------------------------------------------------------------- -Testing SoftFloat - -SoftFloat can be tested using the `testsoftfloat' program by the same -author. The `testsoftfloat' program is part of the TestFloat package -available at the Web page `http://www.jhauser.us/arithmetic/TestFloat.html'. - - ----------------------------------------------------------------------------- -Timing SoftFloat - -A program called `timesoftfloat' for timing the SoftFloat functions is -included with the SoftFloat source code. Compiling `timesoftfloat' should -pose no difficulties once `softfloat.o' exists. The supplied Makefile -will create a `timesoftfloat' executable by default after generating -`softfloat.o'. See `timesoftfloat.txt' for documentation about using -`timesoftfloat'. - - ----------------------------------------------------------------------------- -Compiler Options and Efficiency - -In order to get good speed with SoftFloat, it is important that the compiler -inline the routines that have been marked `INLINE' in the code. Even if -inlining cannot be forced by an appropriate definition of the `INLINE' -macro, the compiler may still be able to perform inlining on its own as -an optimization. In that case, the Makefile should be edited to give the -compiler whatever option is required to cause it to inline small functions. - - ----------------------------------------------------------------------------- -Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros' - -The `softfloat-macros' source fragment defines arithmetic functions used -as primitives by `softfloat.c'. This file has been written in a target- -independent form. For a given target, it may be possible to improve on -these functions using target-specific and/or non-ISO-C features (such -as `asm' statements). For example, one of the "macro" functions takes -two word-size integers and returns their full product in two words. -This operation can be done directly in hardware on many processors; but -because it is not available through standard C, the function defined in -`softfloat-macros' uses four multiplications to achieve the same result. - -To address these shortcomings, a customized version of `softfloat-macros' -can be created in any of the target-specific subdirectories. A simple -modification to the target's Makefile should be sufficient to ensure that -the custom version is used instead of the generic one. - - ----------------------------------------------------------------------------- -Contact Information - -At the time of this writing, the most up-to-date information about SoftFloat -and the latest release can be found at the Web page `http://www.jhauser.us/ -arithmetic/SoftFloat.html'. - + +Berkeley SoftFloat Release 2c Source Documentation + +John R. Hauser +2015 January 30 + + +---------------------------------------------------------------------------- +Introduction + +Berkeley SoftFloat is a software implementation of binary floating-point +that conforms to the IEEE Standard for Floating-Point Arithmetic. +Release 2c of SoftFloat can support four floating-point formats: 32-bit +single-precision, 64-bit double-precision, 80-bit double-extended-precision, +and 128-bit quadruple-precision. All operations required by the older 1985 +version of the IEEE Standard are implemented, except for conversions to and +from decimal. SoftFloat is distributed in the form of C source code, so a +C compiler is needed to compile the code. Support for the 80-bit double- +extended-precision and 128-bit quadruple-precision formats is dependent on +the C compiler implementing a 64-bit integer type. + +This document gives information needed for compiling and/or porting this +SoftFloat release. + +The source code for SoftFloat is intended to be relatively machine- +independent and should be compilable using most any ISO/ANSI C compiler. At +the time of this writing, SoftFloat has been successfully compiled with the +GNU C Compiler (`gcc') for several platforms. + + +---------------------------------------------------------------------------- +Limitations + +As supplied, SoftFloat requires an ISO/ANSI-style C compiler. No attempt +has been made to accomodate compilers that are not ISO-conformant. Older +"K&R-style" compilers are not adequate for compiling SoftFloat. All testing +I have done so far has been with the GNU C Compiler. Compilation with other +compilers should be possible but has not been tested by me. + +The SoftFloat sources assume that source code file names can be longer than +8 characters. In order to compile under an MS-DOS-type system, many of the +source files will need to be renamed, and the source and Makefiles edited +appropriately. Once compiled, the SoftFloat binary does not depend on the +existence of long file names. + +The underlying machine is assumed to be binary with a word size that is a +power of 2. Bytes are 8 bits. Arithmetic on signed integers must modularly +wrap around on overflows (as is already required for unsigned integers +in C). + +Support for the 80-bit double-extended-precision and 128-bit quadruple- +precision formats depends on the C compiler implementing a 64-bit integer +type. If the largest integer type supported by the C compiler is 32 bits, +SoftFloat is limited to the 32-bit single-precision and 64-bit double- +precision formats. + + +---------------------------------------------------------------------------- +Contents + + Introduction + Limitations + Contents + Legal Notice + SoftFloat Source Directory Structure + SoftFloat Source Files + processors/*.h + softfloat/bits*/*/softfloat.h + softfloat/bits*/*/milieu.h + softfloat/bits*/*/softfloat-specialize + softfloat/bits*/softfloat-macros + softfloat/bits*/softfloat.c + Steps to Creating a `softfloat.o' + Making `softfloat.o' a Library + Testing SoftFloat + Timing SoftFloat + Compiler Options and Efficiency + Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros' + Contact Information + + + +---------------------------------------------------------------------------- +Legal Notice + +SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made +possible in part by the International Computer Science Institute, located +at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding +was partially provided by the National Science Foundation under grant +MIP-9311980. The original version of this code was written as part of a +project to build a fixed-point vector processor in collaboration with the +University of California at Berkeley, overseen by Profs. Nelson Morgan and +John Wawrzynek. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR +OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN +HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, +OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF +THE SOFTWARE. + +The following are expressly permitted, even for commercial purposes: +(1) distribution of SoftFloat in whole or in part, as long as this and +other legal notices remain and are prominent, and provided also that, for a +partial distribution, prominent notice is given that it is a subset of the +original; and +(2) inclusion or use of SoftFloat in whole or in part in a derivative +work, provided that the use restrictions above are met and the minimal +documentation requirements stated in the source code are satisfied. + + +---------------------------------------------------------------------------- +SoftFloat Source Directory Structure + +Because SoftFloat is targeted to multiple platforms, its source code +is slightly scattered between target-specific and target-independent +directories and files. The directory structure is as follows: + + processors + softfloat + bits64 + templates + 386-Win32-GCC + SPARC-Solaris-GCC + bits32 + templates + 386-Win32-GCC + SPARC-Solaris-GCC + +The two topmost directories and their contents are: + + softfloat - Most of the source code needed for SoftFloat. + processors - Target-specific header files that are not specific to + SoftFloat. + +The `softfloat' directory is further split into two parts: + + bits64 - SoftFloat implementation using 64-bit integers. + bits32 - SoftFloat implementation using only 32-bit integers. + +Within these directories are subdirectories for each of the targeted +platforms. The SoftFloat source code is distributed with targets +`386-Win32-GCC' and `SPARC-Solaris-GCC' (and perhaps others) already +prepared for both the 32-bit and 64-bit implementations. Source files +that are not within these target-specific subdirectories are intended to be +target-independent. + +The naming convention used for the target-specific directories is +`--'. The names of the supplied +target directories should be interpreted as follows: + + : + 386 - Intel 386-compatible processor. + SPARC - SPARC processor (as used by Sun computers). + : + Win32 - Microsoft Win32 executable. + Solaris - Sun Solaris executable. + : + GCC - GNU C Compiler. + +You do not need to maintain this convention if you do not want to. + +Alongside the supplied target-specific directories is a `templates' +directory containing a set of "generic" target-specific source files. A +new target directory can be created by copying the `templates' directory and +editing the files inside. (Complete instructions for porting SoftFloat to +a new target are in the section _Steps to Creating a `softfloat.o'_.) Note +that the `templates' directory will not work as a target directory without +some editing. To avoid confusion, it would be wise to refrain from editing +the files inside `templates' directly. + + +---------------------------------------------------------------------------- +SoftFloat Source Files + +The purpose of each source file is described below. In the following, +the `*' symbol is used in place of the name of a specific target, such as +`386-Win32-GCC' or `SPARC-Solaris-GCC', or in place of some other text, as +in `bits*' for either `bits32' or `bits64'. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +processors/*.h + +The target-specific `processors' header file defines integer types +of various sizes, and also defines certain C preprocessor macros that +characterize the target. The two examples supplied are `386-GCC.h' and +`SPARC-GCC.h'. The naming convention used for processor header files is +`-.h'. + +If 64-bit integers are supported by the compiler, the macro name `BITS64' +should be defined here along with the corresponding 64-bit integer +types. In addition, the function-like macro `LIT64' must be defined for +constructing 64-bit integer literals (constants). The `LIT64' macro is used +consistently in the SoftFloat code to annotate 64-bit literals. + +If `BITS64' is not defined, only the 32-bit version of SoftFloat can be +compiled. If `BITS64' _is_ defined, either can be compiled. + +If an inlining attribute (such as an `inline' keyword) is provided by the +compiler, the macro `INLINE' should be defined to the appropriate keyword. +If not, `INLINE' can be set to the keyword `static'. The `INLINE' macro +appears in the SoftFloat source code before every function that should +be inlined by the compiler. SoftFloat depends on inlining to obtain +good speed. Even if inlining cannot be forced with a language keyword, +the compiler may still be able to perform inlining on its own as an +optimization. If a command-line option is needed to convince the compiler +to perform this optimization, this should be assured in the Makefile. (See +the section _Compiler Options and Efficiency_ below.) + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +softfloat/bits*/*/softfloat.h + +The target-specific `softfloat.h' header file defines the SoftFloat +interface as seen by clients. + +Unlike the actual function definitions in `softfloat.c', the declarations +in `softfloat.h' do not use any of the types defined by the `processors' +header file. This is done so that clients will not have to include the +`processors' header file in order to use SoftFloat. Nevertheless, the +target-specific declarations in `softfloat.h' must match what `softfloat.c' +expects. For example, if `int32' is defined as `int' in the `processors' +header file, then in `softfloat.h' the output of `float32_to_int32' should +be stated as `int', although in `softfloat.c' it is given in target- +independent form as `int32'. + +For the `bits64' implementation of SoftFloat, the macro names `FLOATX80' +and `FLOAT128' must be defined in order for the 80-bit double-extended- +precision and 128-bit quadruple-precision formats to be enabled in the +code. Conversely, either or both of these larger formats can be disabled by +simply removing the `#define' of the respective macro. When a format is not +enabled, none of the functions that either input or output the format are +defined, and no space is taken up in `softfloat.o' by such functions. There +is no provision for disabling the usual 32-bit single-precision and 64-bit +double-precision formats. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +softfloat/bits*/*/milieu.h + +The target-specific `milieu.h' header file provides declarations that are +needed to compile SoftFloat. In addition, deviations from ISO/ANSI C by +the compiler (such as names not properly declared in system header files) +are corrected in this header if possible. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +softfloat/bits*/*/softfloat-specialize + +This target-specific C source fragment defines: + +-- whether tininess for underflow is detected before or after rounding by + default; +-- what (if anything) special happens when exceptions are raised; +-- how signaling NaNs are distinguished from quiet NaNs; +-- the default generated quiet NaNs; and +-- how NaNs are propagated from function inputs to output. + +These details are not decided by the IEEE Standard. This fragment is +included verbatim within `softfloat.c' when SoftFloat is compiled. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +softfloat/bits*/softfloat-macros + +This target-independent C source fragment defines a number of arithmetic +functions used as primitives within the `softfloat.c' source. Most of +the functions defined here are intended to be inlined for efficiency. +This fragment is included verbatim within `softfloat.c' when SoftFloat is +compiled. + +Target-specific variations on this file are possible. See the section +_Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros'_ +below. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +softfloat/bits*/softfloat.c + +The target-independent `softfloat.c' source file contains the body of the +SoftFloat implementation. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +The inclusion of the files above within each other (using `#include') can be +shown graphically as follows: + + softfloat/bits*/softfloat.c + softfloat/bits*/*/milieu.h + processors/*.h + softfloat/bits*/*/softfloat.h + softfloat/bits*/*/softfloat-specialize + softfloat/bits*/softfloat-macros + +Note in particular that `softfloat.c' does not include the `processors' +header file directly. Rather, `softfloat.c' includes the target-specific +`milieu.h' header file, which in turn includes the appropriate processor +header file. + + +---------------------------------------------------------------------------- +Steps to Creating a `softfloat.o' + +Porting and/or compiling SoftFloat involves the following steps: + +1. If one does not already exist, create an appropriate `.h' file in the + `processors' directory. + +2. If `BITS64' is defined in the `processors' header file, choose whether + to compile the 32-bit or 64-bit implementation of SoftFloat. If + `BITS64' is not defined, your only choice is the 32-bit implementation. + The remaining steps occur within either the `bits32' or `bits64' + subdirectories. + +3. If one does not already exist, create an appropriate target-specific + subdirectory by copying the given `templates' directory. + +4. In the target-specific subdirectory, edit the files `softfloat-specialize' + and `softfloat.h' to define the desired exception handling functions + and mode control values. In the `softfloat.h' header file, ensure also + that all declarations give the proper target-specific type (such as + `int' or `long') corresponding to the target-independent type used in + `softfloat.c' (such as `int32'). None of the type names declared in the + `processors' header file should appear in `softfloat.h'. + +5. In the target-specific subdirectory, edit the files `milieu.h' and + `Makefile' to reflect the current environment. + +6. In the target-specific subdirectory, execute `make'. + +For the targets that are supplied, if the expected compiler is available +(usually `gcc'), it should only be necessary to execute `make' in the +target-specific subdirectory. + + +---------------------------------------------------------------------------- +Making `softfloat.o' a Library + +SoftFloat is not made into a software library by the supplied Makefile. +If desired, `softfloat.o' can easily be put into its own library (typically +`softfloat.a' or `libsoftfloat.a') using the usual system tool (in UNIX, +`ar'). + + +---------------------------------------------------------------------------- +Testing SoftFloat + +SoftFloat can be tested using the `testsoftfloat' program by the same +author. The `testsoftfloat' program is part of the TestFloat package +available at the Web page `http://www.jhauser.us/arithmetic/TestFloat.html'. + + +---------------------------------------------------------------------------- +Timing SoftFloat + +A program called `timesoftfloat' for timing the SoftFloat functions is +included with the SoftFloat source code. Compiling `timesoftfloat' should +pose no difficulties once `softfloat.o' exists. The supplied Makefile +will create a `timesoftfloat' executable by default after generating +`softfloat.o'. See `timesoftfloat.txt' for documentation about using +`timesoftfloat'. + + +---------------------------------------------------------------------------- +Compiler Options and Efficiency + +In order to get good speed with SoftFloat, it is important that the compiler +inline the routines that have been marked `INLINE' in the code. Even if +inlining cannot be forced by an appropriate definition of the `INLINE' +macro, the compiler may still be able to perform inlining on its own as +an optimization. In that case, the Makefile should be edited to give the +compiler whatever option is required to cause it to inline small functions. + + +---------------------------------------------------------------------------- +Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros' + +The `softfloat-macros' source fragment defines arithmetic functions used +as primitives by `softfloat.c'. This file has been written in a target- +independent form. For a given target, it may be possible to improve on +these functions using target-specific and/or non-ISO-C features (such +as `asm' statements). For example, one of the "macro" functions takes +two word-size integers and returns their full product in two words. +This operation can be done directly in hardware on many processors; but +because it is not available through standard C, the function defined in +`softfloat-macros' uses four multiplications to achieve the same result. + +To address these shortcomings, a customized version of `softfloat-macros' +can be created in any of the target-specific subdirectories. A simple +modification to the target's Makefile should be sufficient to ensure that +the custom version is used instead of the generic one. + + +---------------------------------------------------------------------------- +Contact Information + +At the time of this writing, the most up-to-date information about SoftFloat +and the latest release can be found at the Web page `http://www.jhauser.us/ +arithmetic/SoftFloat.html'. + diff --git a/i386c/ia32/instructions/fpu/softfloat/SoftFloat.txt b/i386c/ia32/instructions/fpu/softfloat/SoftFloat.txt index 0d553276..07923317 100644 --- a/i386c/ia32/instructions/fpu/softfloat/SoftFloat.txt +++ b/i386c/ia32/instructions/fpu/softfloat/SoftFloat.txt @@ -1,389 +1,389 @@ - -Berkeley SoftFloat Release 2c General Documentation - -John R. Hauser -2015 January 30 - - ----------------------------------------------------------------------------- -Introduction - -Berkeley SoftFloat is a software implementation of binary floating-point -that conforms to the IEEE Standard for Floating-Point Arithmetic. For -Release 2c of SoftFloat, as many as four formats are supported: 32-bit -single-precision, 64-bit double-precision, 80-bit double-extended-precision, -and 128-bit quadruple-precision. All operations required by the older 1985 -version of the IEEE Standard are implemented, except for conversions to and -from decimal. - -This document gives information about the types defined and the routines -implemented by this release of SoftFloat. It does not attempt to define or -explain the IEEE Floating-Point Standard. Details about the standard are -available elsewhere. - - ----------------------------------------------------------------------------- -Limitations - -SoftFloat is written in C and is designed to work with other C code. The -SoftFloat header files assume an ISO/ANSI-style C compiler. No attempt -has been made to accomodate compilers that are not ISO-conformant. In -particular, the distributed header files will not be acceptable to any -compiler that does not recognize function prototypes. - -Support for the 80-bit double-extended-precision and 128-bit quadruple- -precision formats depends on a C compiler that implements 64-bit integer -arithmetic. If the largest integer format supported by the C compiler is -32 bits, SoftFloat is limited to only 32-bit single-precision and 64-bit -double-precision. When that is the case, all references in this document -to 80-bit double-extended-precision, 128-bit quadruple-precision, and 64-bit -integers should be ignored. - - ----------------------------------------------------------------------------- -Contents - - Introduction - Limitations - Contents - Legal Notice - Types and Functions - Rounding Modes - Double-Extended-Precision Rounding Precision - Exceptions and Exception Flags - Function Details - Conversion Functions - Basic Arithmetic Functions - Remainder Functions - Round-to-Integer Functions - Comparison Functions - Signaling NaN Test Functions - Raise-Exception Function - Contact Information - - - ----------------------------------------------------------------------------- -Legal Notice - -SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made -possible in part by the International Computer Science Institute, located -at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding -was partially provided by the National Science Foundation under grant -MIP-9311980. The original version of this code was written as part of a -project to build a fixed-point vector processor in collaboration with the -University of California at Berkeley, overseen by Profs. Nelson Morgan and -John Wawrzynek. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort -has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT -TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO -PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR -OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN -HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, -OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF -THE SOFTWARE. - -The following are expressly permitted, even for commercial purposes: -(1) distribution of SoftFloat in whole or in part, as long as this and -other legal notices remain and are prominent, and provided also that, for a -partial distribution, prominent notice is given that it is a subset of the -original; and -(2) inclusion or use of SoftFloat in whole or in part in a derivative -work, provided that the use restrictions above are met and the minimal -documentation requirements stated in the source code are satisfied. - - ----------------------------------------------------------------------------- -Types and Functions - -When 64-bit integers are supported by the compiler, the `softfloat.h' header -file defines four types: `float32' (32-bit single-precision), `float64' -(64-bit double-precision), `floatx80' (80-bit double-extended-precision), -and `float128' (128-bit quadruple-precision). The `float32' and `float64' -types are defined in terms of 32-bit and 64-bit integer types, respectively, -while the `float128' type is defined as a structure of two 64-bit integers, -taking into account the byte order of the particular machine being used. -The `floatx80' type is defined as a structure containing one 16-bit and one -64-bit integer, with the machine's byte order again determining the order -within the structure. - -When 64-bit integers are _not_ supported by the compiler, the `softfloat.h' -header file defines only two types: `float32' and `float64'. Because -the ISO/ANSI C Standard guarantees at least one built-in integer type of -32 bits, the `float32' type is identified with an appropriate integer type. -The `float64' type is defined as a structure of two 32-bit integers, with -the machine's byte order determining the order of the fields. - -In either case, the types in `softfloat.h' are defined such that if a system -implements the usual C `float' and `double' types according to the IEEE -Standard, then the `float32' and `float64' types should be indistinguishable -in memory from the native `float' and `double' types. (On the other hand, -when `float32' or `float64' values are placed in processor registers by -the compiler, the type of registers used may differ from those used for the -native `float' and `double' types.) - -SoftFloat implements the following arithmetic operations: - --- Conversions among all the floating-point formats, and also between - integers (32-bit and 64-bit) and any of the floating-point formats. - --- The usual add, subtract, multiply, divide, and square root operations for - all floating-point formats. - --- For each format, the floating-point remainder operation defined by the - IEEE Standard. - --- For each floating-point format, a "round to integer" operation that - rounds to the nearest integer value in the same format. (The floating- - point formats can hold integer values, of course.) - --- Comparisons between two values in the same floating-point format. - -The only functions required by the 1985 IEEE Standard that are not provided -are conversions to and from decimal. - - ----------------------------------------------------------------------------- -Rounding Modes - -All four rounding modes prescribed by the 1985 IEEE Standard are implemented -for all operations that require rounding. The rounding mode is selected -by the global variable `float_rounding_mode'. This variable may be set -to one of the values `float_round_nearest_even', `float_round_to_zero', -`float_round_down', or `float_round_up'. The rounding mode is initialized -to nearest/even. - - ----------------------------------------------------------------------------- -Double-Extended-Precision Rounding Precision - -For 80-bit double-extended-precision (`floatx80') only, the rounding -precision of the basic arithmetic operations is controlled by the global -variable `floatx80_rounding_precision'. The operations affected are: - - floatx80_add floatx80_sub floatx80_mul floatx80_div floatx80_sqrt - -When `floatx80_rounding_precision' is set to its default value of 80, -these operations are rounded (as usual) to the full precision of the 80-bit -double-extended-precision format. Setting `floatx80_rounding_precision' to -32 or to 64 causes the operations listed to be rounded to reduced precision -equivalent to 32-bit single-precision (`float32') or to 64-bit double- -precision (`float64'), respectively. When rounding to reduced precision, -additional bits in the result significand beyond the rounding point are set -to zero. The consequences of setting `floatx80_rounding_precision' to a -value other than 32, 64, or 80 is not specified. Operations other than the -ones listed above are not affected by `floatx80_rounding_precision'. - - ----------------------------------------------------------------------------- -Exceptions and Exception Flags - -All five exception flags required by the IEEE Standard are implemented. -Each flag is stored as a separate bit in the global variable -`float_exception_flags'. The positions of the exception flag bits within -this variable are determined by the bit masks `float_flag_inexact', -`float_flag_underflow', `float_flag_overflow', `float_flag_divbyzero', and -`float_flag_invalid'. The exception flags variable is initialized to all 0, -meaning no exceptions. - -An individual exception flag can be cleared with the statement - - float_exception_flags &= ~ float_flag_; - -where `' is the appropriate name. To raise a floating-point -exception, the SoftFloat function `float_raise' should be used (see below). - -In the terminology of the IEEE Standard, SoftFloat can detect tininess -for underflow either before or after rounding. The choice is made by -the global variable `float_detect_tininess', which can be set to either -`float_tininess_before_rounding' or `float_tininess_after_rounding'. -Detecting tininess after rounding is better because it results in fewer -spurious underflow signals. The other option is provided for compatibility -with some systems. Like most systems, SoftFloat always detects loss of -accuracy for underflow as an inexact result. - - ----------------------------------------------------------------------------- -Function Details - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Conversion Functions - -All conversions among the floating-point formats are supported, as are all -conversions between a floating-point format and 32-bit and 64-bit signed -integers. The complete set of conversion functions is: - - int32_to_float32 int64_to_float32 - int32_to_float64 int64_to_float64 - int32_to_floatx80 int64_to_floatx80 - int32_to_float128 int64_to_float128 - - float32_to_int32 float32_to_int64 - float64_to_int32 float64_to_int64 - floatx80_to_int32 floatx80_to_int64 - float128_to_int32 float128_to_int64 - - float32_to_float64 float32_to_floatx80 float32_to_float128 - float64_to_float32 float64_to_floatx80 float64_to_float128 - floatx80_to_float32 floatx80_to_float64 floatx80_to_float128 - float128_to_float32 float128_to_float64 float128_to_floatx80 - -Each conversion function takes one operand of the appropriate type and -returns one result. Conversions from a smaller to a larger floating-point -format are always exact and so require no rounding. Conversions from 32-bit -integers to 64-bit double-precision and larger formats are also exact, and -likewise for conversions from 64-bit integers to 80-bit double-extended- -precision and 128-bit quadruple-precision. - -Conversions from floating-point to integer raise the invalid exception if -the source value cannot be rounded to a representable integer of the desired -size (32 or 64 bits). If the floating-point operand is a NaN, the largest -positive integer is returned. Otherwise, if the conversion overflows, the -largest integer with the same sign as the operand is returned. - -On conversions to integer, if the floating-point operand is not already -an integer value, the operand is rounded according to the current rounding -mode as specified by `float_rounding_mode'. Because C (and perhaps other -languages) require that conversions to integers be rounded toward zero, the -following functions are provided for improved speed and convenience: - - float32_to_int32_round_to_zero float32_to_int64_round_to_zero - float64_to_int32_round_to_zero float64_to_int64_round_to_zero - floatx80_to_int32_round_to_zero floatx80_to_int64_round_to_zero - float128_to_int32_round_to_zero float128_to_int64_round_to_zero - -These variant functions ignore `float_rounding_mode' and always round toward -zero. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Basic Arithmetic Functions - -The following basic arithmetic functions are provided: - - float32_add float32_sub float32_mul float32_div float32_sqrt - float64_add float64_sub float64_mul float64_div float64_sqrt - floatx80_add floatx80_sub floatx80_mul floatx80_div floatx80_sqrt - float128_add float128_sub float128_mul float128_div float128_sqrt - -Each function takes two operands, except for `sqrt' which takes only one. -The operands and result are all of the same type. - -Rounding of the 80-bit double-extended-precision (`floatx80') functions is -affected by the `floatx80_rounding_precision' variable, as explained above -in the section _Double-Extended-Precision Rounding Precision_. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Remainder Functions - -For each format, SoftFloat implements the remainder function according to -the IEEE Standard. The remainder functions are: - - float32_rem - float64_rem - floatx80_rem - float128_rem - -Each remainder function takes two operands. The operands and result are all -of the same type. Given operands x and y, the remainder functions return -the value x - n*y, where n is the integer closest to x/y. If x/y is exactly -halfway between two integers, n is the even integer closest to x/y. The -remainder functions are always exact and so require no rounding. - -Depending on the relative magnitudes of the operands, the remainder -functions can take considerably longer to execute than the other SoftFloat -functions. This is inherent in the remainder operation itself and is not a -flaw in the SoftFloat implementation. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Round-to-Integer Functions - -For each format, SoftFloat implements the round-to-integer function -specified by the IEEE Standard. The functions are: - - float32_round_to_int - float64_round_to_int - floatx80_round_to_int - float128_round_to_int - -Each function takes a single floating-point operand and returns a result of -the same type. (Note that the result is not an integer type.) The operand -is rounded to an exact integer according to the current rounding mode, and -the resulting integer value is returned in the same floating-point format. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Comparison Functions - -The following floating-point comparison functions are provided: - - float32_eq float32_le float32_lt - float64_eq float64_le float64_lt - floatx80_eq floatx80_le floatx80_lt - float128_eq float128_le float128_lt - -Each function takes two operands of the same type and returns a 1 or 0 -representing either _true_ or _false_. The abbreviation `eq' stands for -"equal" (=); `le' stands for "less than or equal" (<=); and `lt' stands for -"less than" (<). - -The usual greater-than (>), greater-than-or-equal (>=), and not-equal (!=) -functions are easily obtained using the functions provided. The not-equal -function is just the logical complement of the equal function. The greater- -than-or-equal function is identical to the less-than-or-equal function with -the operands reversed, and the greater-than function is identical to the -less-than function with the operands reversed. - -The IEEE Standard specifies that the less-than-or-equal and less-than -functions raise the invalid exception if either input is any kind of NaN. -The equal functions, on the other hand, are defined not to raise the invalid -exception on quiet NaNs. For completeness, SoftFloat provides the following -additional functions: - - float32_eq_signaling float32_le_quiet float32_lt_quiet - float64_eq_signaling float64_le_quiet float64_lt_quiet - floatx80_eq_signaling floatx80_le_quiet floatx80_lt_quiet - float128_eq_signaling float128_le_quiet float128_lt_quiet - -The `signaling' equal functions are identical to the standard functions -except that the invalid exception is raised for any NaN input. Likewise, -the `quiet' comparison functions are identical to their counterparts except -that the invalid exception is not raised for quiet NaNs. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Signaling NaN Test Functions - -The following functions test whether a floating-point value is a signaling -NaN: - - float32_is_signaling_nan - float64_is_signaling_nan - floatx80_is_signaling_nan - float128_is_signaling_nan - -The functions take one operand and return 1 if the operand is a signaling -NaN and 0 otherwise. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Raise-Exception Function - -SoftFloat provides a function for raising floating-point exceptions: - - float_raise - -The function takes a mask indicating the set of exceptions to raise. No -result is returned. In addition to setting the specified exception flags, -this function may cause a trap or abort appropriate for the current system. - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ----------------------------------------------------------------------------- -Contact Information - -At the time of this writing, the most up-to-date information about SoftFloat -and the latest release can be found at the Web page `http://www.jhauser.us/ -arithmetic/SoftFloat.html'. - + +Berkeley SoftFloat Release 2c General Documentation + +John R. Hauser +2015 January 30 + + +---------------------------------------------------------------------------- +Introduction + +Berkeley SoftFloat is a software implementation of binary floating-point +that conforms to the IEEE Standard for Floating-Point Arithmetic. For +Release 2c of SoftFloat, as many as four formats are supported: 32-bit +single-precision, 64-bit double-precision, 80-bit double-extended-precision, +and 128-bit quadruple-precision. All operations required by the older 1985 +version of the IEEE Standard are implemented, except for conversions to and +from decimal. + +This document gives information about the types defined and the routines +implemented by this release of SoftFloat. It does not attempt to define or +explain the IEEE Floating-Point Standard. Details about the standard are +available elsewhere. + + +---------------------------------------------------------------------------- +Limitations + +SoftFloat is written in C and is designed to work with other C code. The +SoftFloat header files assume an ISO/ANSI-style C compiler. No attempt +has been made to accomodate compilers that are not ISO-conformant. In +particular, the distributed header files will not be acceptable to any +compiler that does not recognize function prototypes. + +Support for the 80-bit double-extended-precision and 128-bit quadruple- +precision formats depends on a C compiler that implements 64-bit integer +arithmetic. If the largest integer format supported by the C compiler is +32 bits, SoftFloat is limited to only 32-bit single-precision and 64-bit +double-precision. When that is the case, all references in this document +to 80-bit double-extended-precision, 128-bit quadruple-precision, and 64-bit +integers should be ignored. + + +---------------------------------------------------------------------------- +Contents + + Introduction + Limitations + Contents + Legal Notice + Types and Functions + Rounding Modes + Double-Extended-Precision Rounding Precision + Exceptions and Exception Flags + Function Details + Conversion Functions + Basic Arithmetic Functions + Remainder Functions + Round-to-Integer Functions + Comparison Functions + Signaling NaN Test Functions + Raise-Exception Function + Contact Information + + + +---------------------------------------------------------------------------- +Legal Notice + +SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made +possible in part by the International Computer Science Institute, located +at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding +was partially provided by the National Science Foundation under grant +MIP-9311980. The original version of this code was written as part of a +project to build a fixed-point vector processor in collaboration with the +University of California at Berkeley, overseen by Profs. Nelson Morgan and +John Wawrzynek. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR +OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN +HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, +OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF +THE SOFTWARE. + +The following are expressly permitted, even for commercial purposes: +(1) distribution of SoftFloat in whole or in part, as long as this and +other legal notices remain and are prominent, and provided also that, for a +partial distribution, prominent notice is given that it is a subset of the +original; and +(2) inclusion or use of SoftFloat in whole or in part in a derivative +work, provided that the use restrictions above are met and the minimal +documentation requirements stated in the source code are satisfied. + + +---------------------------------------------------------------------------- +Types and Functions + +When 64-bit integers are supported by the compiler, the `softfloat.h' header +file defines four types: `float32' (32-bit single-precision), `float64' +(64-bit double-precision), `floatx80' (80-bit double-extended-precision), +and `float128' (128-bit quadruple-precision). The `float32' and `float64' +types are defined in terms of 32-bit and 64-bit integer types, respectively, +while the `float128' type is defined as a structure of two 64-bit integers, +taking into account the byte order of the particular machine being used. +The `floatx80' type is defined as a structure containing one 16-bit and one +64-bit integer, with the machine's byte order again determining the order +within the structure. + +When 64-bit integers are _not_ supported by the compiler, the `softfloat.h' +header file defines only two types: `float32' and `float64'. Because +the ISO/ANSI C Standard guarantees at least one built-in integer type of +32 bits, the `float32' type is identified with an appropriate integer type. +The `float64' type is defined as a structure of two 32-bit integers, with +the machine's byte order determining the order of the fields. + +In either case, the types in `softfloat.h' are defined such that if a system +implements the usual C `float' and `double' types according to the IEEE +Standard, then the `float32' and `float64' types should be indistinguishable +in memory from the native `float' and `double' types. (On the other hand, +when `float32' or `float64' values are placed in processor registers by +the compiler, the type of registers used may differ from those used for the +native `float' and `double' types.) + +SoftFloat implements the following arithmetic operations: + +-- Conversions among all the floating-point formats, and also between + integers (32-bit and 64-bit) and any of the floating-point formats. + +-- The usual add, subtract, multiply, divide, and square root operations for + all floating-point formats. + +-- For each format, the floating-point remainder operation defined by the + IEEE Standard. + +-- For each floating-point format, a "round to integer" operation that + rounds to the nearest integer value in the same format. (The floating- + point formats can hold integer values, of course.) + +-- Comparisons between two values in the same floating-point format. + +The only functions required by the 1985 IEEE Standard that are not provided +are conversions to and from decimal. + + +---------------------------------------------------------------------------- +Rounding Modes + +All four rounding modes prescribed by the 1985 IEEE Standard are implemented +for all operations that require rounding. The rounding mode is selected +by the global variable `float_rounding_mode'. This variable may be set +to one of the values `float_round_nearest_even', `float_round_to_zero', +`float_round_down', or `float_round_up'. The rounding mode is initialized +to nearest/even. + + +---------------------------------------------------------------------------- +Double-Extended-Precision Rounding Precision + +For 80-bit double-extended-precision (`floatx80') only, the rounding +precision of the basic arithmetic operations is controlled by the global +variable `floatx80_rounding_precision'. The operations affected are: + + floatx80_add floatx80_sub floatx80_mul floatx80_div floatx80_sqrt + +When `floatx80_rounding_precision' is set to its default value of 80, +these operations are rounded (as usual) to the full precision of the 80-bit +double-extended-precision format. Setting `floatx80_rounding_precision' to +32 or to 64 causes the operations listed to be rounded to reduced precision +equivalent to 32-bit single-precision (`float32') or to 64-bit double- +precision (`float64'), respectively. When rounding to reduced precision, +additional bits in the result significand beyond the rounding point are set +to zero. The consequences of setting `floatx80_rounding_precision' to a +value other than 32, 64, or 80 is not specified. Operations other than the +ones listed above are not affected by `floatx80_rounding_precision'. + + +---------------------------------------------------------------------------- +Exceptions and Exception Flags + +All five exception flags required by the IEEE Standard are implemented. +Each flag is stored as a separate bit in the global variable +`float_exception_flags'. The positions of the exception flag bits within +this variable are determined by the bit masks `float_flag_inexact', +`float_flag_underflow', `float_flag_overflow', `float_flag_divbyzero', and +`float_flag_invalid'. The exception flags variable is initialized to all 0, +meaning no exceptions. + +An individual exception flag can be cleared with the statement + + float_exception_flags &= ~ float_flag_; + +where `' is the appropriate name. To raise a floating-point +exception, the SoftFloat function `float_raise' should be used (see below). + +In the terminology of the IEEE Standard, SoftFloat can detect tininess +for underflow either before or after rounding. The choice is made by +the global variable `float_detect_tininess', which can be set to either +`float_tininess_before_rounding' or `float_tininess_after_rounding'. +Detecting tininess after rounding is better because it results in fewer +spurious underflow signals. The other option is provided for compatibility +with some systems. Like most systems, SoftFloat always detects loss of +accuracy for underflow as an inexact result. + + +---------------------------------------------------------------------------- +Function Details + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Conversion Functions + +All conversions among the floating-point formats are supported, as are all +conversions between a floating-point format and 32-bit and 64-bit signed +integers. The complete set of conversion functions is: + + int32_to_float32 int64_to_float32 + int32_to_float64 int64_to_float64 + int32_to_floatx80 int64_to_floatx80 + int32_to_float128 int64_to_float128 + + float32_to_int32 float32_to_int64 + float64_to_int32 float64_to_int64 + floatx80_to_int32 floatx80_to_int64 + float128_to_int32 float128_to_int64 + + float32_to_float64 float32_to_floatx80 float32_to_float128 + float64_to_float32 float64_to_floatx80 float64_to_float128 + floatx80_to_float32 floatx80_to_float64 floatx80_to_float128 + float128_to_float32 float128_to_float64 float128_to_floatx80 + +Each conversion function takes one operand of the appropriate type and +returns one result. Conversions from a smaller to a larger floating-point +format are always exact and so require no rounding. Conversions from 32-bit +integers to 64-bit double-precision and larger formats are also exact, and +likewise for conversions from 64-bit integers to 80-bit double-extended- +precision and 128-bit quadruple-precision. + +Conversions from floating-point to integer raise the invalid exception if +the source value cannot be rounded to a representable integer of the desired +size (32 or 64 bits). If the floating-point operand is a NaN, the largest +positive integer is returned. Otherwise, if the conversion overflows, the +largest integer with the same sign as the operand is returned. + +On conversions to integer, if the floating-point operand is not already +an integer value, the operand is rounded according to the current rounding +mode as specified by `float_rounding_mode'. Because C (and perhaps other +languages) require that conversions to integers be rounded toward zero, the +following functions are provided for improved speed and convenience: + + float32_to_int32_round_to_zero float32_to_int64_round_to_zero + float64_to_int32_round_to_zero float64_to_int64_round_to_zero + floatx80_to_int32_round_to_zero floatx80_to_int64_round_to_zero + float128_to_int32_round_to_zero float128_to_int64_round_to_zero + +These variant functions ignore `float_rounding_mode' and always round toward +zero. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Basic Arithmetic Functions + +The following basic arithmetic functions are provided: + + float32_add float32_sub float32_mul float32_div float32_sqrt + float64_add float64_sub float64_mul float64_div float64_sqrt + floatx80_add floatx80_sub floatx80_mul floatx80_div floatx80_sqrt + float128_add float128_sub float128_mul float128_div float128_sqrt + +Each function takes two operands, except for `sqrt' which takes only one. +The operands and result are all of the same type. + +Rounding of the 80-bit double-extended-precision (`floatx80') functions is +affected by the `floatx80_rounding_precision' variable, as explained above +in the section _Double-Extended-Precision Rounding Precision_. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Remainder Functions + +For each format, SoftFloat implements the remainder function according to +the IEEE Standard. The remainder functions are: + + float32_rem + float64_rem + floatx80_rem + float128_rem + +Each remainder function takes two operands. The operands and result are all +of the same type. Given operands x and y, the remainder functions return +the value x - n*y, where n is the integer closest to x/y. If x/y is exactly +halfway between two integers, n is the even integer closest to x/y. The +remainder functions are always exact and so require no rounding. + +Depending on the relative magnitudes of the operands, the remainder +functions can take considerably longer to execute than the other SoftFloat +functions. This is inherent in the remainder operation itself and is not a +flaw in the SoftFloat implementation. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Round-to-Integer Functions + +For each format, SoftFloat implements the round-to-integer function +specified by the IEEE Standard. The functions are: + + float32_round_to_int + float64_round_to_int + floatx80_round_to_int + float128_round_to_int + +Each function takes a single floating-point operand and returns a result of +the same type. (Note that the result is not an integer type.) The operand +is rounded to an exact integer according to the current rounding mode, and +the resulting integer value is returned in the same floating-point format. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Comparison Functions + +The following floating-point comparison functions are provided: + + float32_eq float32_le float32_lt + float64_eq float64_le float64_lt + floatx80_eq floatx80_le floatx80_lt + float128_eq float128_le float128_lt + +Each function takes two operands of the same type and returns a 1 or 0 +representing either _true_ or _false_. The abbreviation `eq' stands for +"equal" (=); `le' stands for "less than or equal" (<=); and `lt' stands for +"less than" (<). + +The usual greater-than (>), greater-than-or-equal (>=), and not-equal (!=) +functions are easily obtained using the functions provided. The not-equal +function is just the logical complement of the equal function. The greater- +than-or-equal function is identical to the less-than-or-equal function with +the operands reversed, and the greater-than function is identical to the +less-than function with the operands reversed. + +The IEEE Standard specifies that the less-than-or-equal and less-than +functions raise the invalid exception if either input is any kind of NaN. +The equal functions, on the other hand, are defined not to raise the invalid +exception on quiet NaNs. For completeness, SoftFloat provides the following +additional functions: + + float32_eq_signaling float32_le_quiet float32_lt_quiet + float64_eq_signaling float64_le_quiet float64_lt_quiet + floatx80_eq_signaling floatx80_le_quiet floatx80_lt_quiet + float128_eq_signaling float128_le_quiet float128_lt_quiet + +The `signaling' equal functions are identical to the standard functions +except that the invalid exception is raised for any NaN input. Likewise, +the `quiet' comparison functions are identical to their counterparts except +that the invalid exception is not raised for quiet NaNs. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Signaling NaN Test Functions + +The following functions test whether a floating-point value is a signaling +NaN: + + float32_is_signaling_nan + float64_is_signaling_nan + floatx80_is_signaling_nan + float128_is_signaling_nan + +The functions take one operand and return 1 if the operand is a signaling +NaN and 0 otherwise. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Raise-Exception Function + +SoftFloat provides a function for raising floating-point exceptions: + + float_raise + +The function takes a mask indicating the set of exceptions to raise. No +result is returned. In addition to setting the specified exception flags, +this function may cause a trap or abort appropriate for the current system. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +---------------------------------------------------------------------------- +Contact Information + +At the time of this writing, the most up-to-date information about SoftFloat +and the latest release can be found at the Web page `http://www.jhauser.us/ +arithmetic/SoftFloat.html'. + diff --git a/i386c/ia32/instructions/fpu/softfloat/softfloat-macros.h b/i386c/ia32/instructions/fpu/softfloat/softfloat-macros.h index 77622341..dc52a240 100644 --- a/i386c/ia32/instructions/fpu/softfloat/softfloat-macros.h +++ b/i386c/ia32/instructions/fpu/softfloat/softfloat-macros.h @@ -1,713 +1,713 @@ - -/*============================================================================ - -This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point -Arithmetic Package, Release 2c, by John R. Hauser. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER -PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR -THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY -INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE -(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER -PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR -INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE -SOFTWARE. - -Derivative works require also that (1) the source code for the derivative work -includes prominent notice that the work is derivative, and (2) the source code -includes prominent notice of these three paragraphs for those parts of this -code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are "jammed" into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 32, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr ) -{ - bits32 z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 32 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are "jammed" into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 64, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr ) -{ - bits64 z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 64 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 -| _plus_ the number of bits given in `count'. The shifted result is at most -| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The -| bits shifted off form a second 64-bit result as follows: The _last_ bit -| shifted off is the most-significant bit of the extra result, and the other -| 63 bits of the extra result are all zero if and only if _all_but_the_last_ -| bits shifted off were all zero. This extra result is stored in the location -| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0' and `a1' are considered to form -| a fixed-point value with binary point between `a0' and `a1'. This fixed- -| point value is shifted right by the number of bits given in `count', and -| the integer part of the result is returned at the location pointed to by -| `z0Ptr'. The fractional part of the result may be slightly corrupted as -| described above, and is returned at the location pointed to by `z1Ptr'.) -*----------------------------------------------------------------------------*/ - -INLINE void - shift64ExtraRightJamming( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else { - z1 = ( ( a0 | a1 ) != 0 ); - } - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' can be arbitrarily large; in particular, if `count' is greater -| than 128, the result will be 0. The result is broken into two 64-bit pieces -| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shift128Right( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ); - z0 = a0>>count; - } - else { - z1 = ( count < 128 ) ? ( a0>>( count & 63 ) ) : 0; - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. If any nonzero bits are shifted off, they -| are "jammed" into the least significant bit of the result by setting the -| least significant bit to 1. The value of `count' can be arbitrarily large; -| in particular, if `count' is greater than 128, the result will be either -| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or -| nonzero. The result is broken into two 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shift128RightJamming( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ) | ( ( a1<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else if ( count < 128 ) { - z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<>count ); - z0 = a0>>count; - } - else { - if ( count == 64 ) { - z2 = a1; - z1 = a0; - } - else { - a2 |= a1; - if ( count < 128 ) { - z2 = a0<>( count & 63 ); - } - else { - z2 = ( count == 128 ) ? a0 : ( a0 != 0 ); - z1 = 0; - } - } - z0 = 0; - } - z2 |= ( a2 != 0 ); - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' must be less than 64. The result is broken into two 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shortShift128Left( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - - *z1Ptr = a1<>( ( - count ) & 63 ) ); - -} - -/*---------------------------------------------------------------------------- -| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left -| by the number of bits given in `count'. Any bits shifted off are lost. -| The value of `count' must be less than 64. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shortShift192Left( - bits64 a0, - bits64 a1, - bits64 a2, - int16 count, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - int8 negCount; - - z2 = a2<>negCount; - z0 |= a1>>negCount; - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit -| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so -| any carry out is lost. The result is broken into two 64-bit pieces which -| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - add128( - bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z1; - - z1 = a1 + b1; - *z1Ptr = z1; - *z0Ptr = a0 + b0 + ( z1 < a1 ); - -} - -/*---------------------------------------------------------------------------- -| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the -| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is -| modulo 2^192, so any carry out is lost. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - add192( - bits64 a0, - bits64 a1, - bits64 a2, - bits64 b0, - bits64 b1, - bits64 b2, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - int8 carry0, carry1; - - z2 = a2 + b2; - carry1 = ( z2 < a2 ); - z1 = a1 + b1; - carry0 = ( z1 < a1 ); - z0 = a0 + b0; - z1 += carry1; - z0 += ( z1 < carry1 ); - z0 += carry0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the -| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo -| 2^128, so any borrow out (carry out) is lost. The result is broken into two -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and -| `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - sub128( - bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - - *z1Ptr = a1 - b1; - *z0Ptr = a0 - b0 - ( a1 < b1 ); - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' -| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. -| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The -| result is broken into three 64-bit pieces which are stored at the locations -| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - sub192( - bits64 a0, - bits64 a1, - bits64 a2, - bits64 b0, - bits64 b1, - bits64 b2, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - int8 borrow0, borrow1; - - z2 = a2 - b2; - borrow1 = ( a2 < b2 ); - z1 = a1 - b1; - borrow0 = ( a1 < b1 ); - z0 = a0 - b0; - z0 -= ( z1 < borrow1 ); - z1 -= borrow1; - z0 -= borrow0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken -| into two 64-bit pieces which are stored at the locations pointed to by -| `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits32 aHigh, aLow, bHigh, bLow; - bits64 z0, zMiddleA, zMiddleB, z1; - - aLow = a; - aHigh = a>>32; - bLow = b; - bHigh = b>>32; - z1 = ( (bits64) aLow ) * bLow; - zMiddleA = ( (bits64) aLow ) * bHigh; - zMiddleB = ( (bits64) aHigh ) * bLow; - z0 = ( (bits64) aHigh ) * bHigh; - zMiddleA += zMiddleB; - z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 ); - zMiddleA <<= 32; - z1 += zMiddleA; - z0 += ( z1 < zMiddleA ); - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by -| `b' to obtain a 192-bit product. The product is broken into three 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and -| `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - mul128By64To192( - bits64 a0, - bits64 a1, - bits64 b, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2, more1; - - mul64To128( a1, b, &z1, &z2 ); - mul64To128( a0, b, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the -| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit -| product. The product is broken into four 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - mul128To256( - bits64 a0, - bits64 a1, - bits64 b0, - bits64 b1, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr, - bits64 *z3Ptr - ) -{ - bits64 z0, z1, z2, z3; - bits64 more1, more2; - - mul64To128( a1, b1, &z2, &z3 ); - mul64To128( a1, b0, &z1, &more2 ); - add128( z1, more2, 0, z2, &z1, &z2 ); - mul64To128( a0, b0, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - mul64To128( a0, b1, &more1, &more2 ); - add128( more1, more2, 0, z2, &more1, &z2 ); - add128( z0, z1, 0, more1, &z0, &z1 ); - *z3Ptr = z3; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the 64-bit integer quotient obtained by dividing -| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The -| divisor `b' must be at least 2^63. If q is the exact quotient truncated -| toward zero, the approximation returned lies between q and q + 2 inclusive. -| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit -| unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b ) -{ - bits64 b0, b1; - bits64 rem0, rem1, term0, term1; - bits64 z; - - if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); - b0 = b>>32; - z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32; - mul64To128( b, z, &term0, &term1 ); - sub128( a0, a1, term0, term1, &rem0, &rem1 ); - while ( ( (sbits64) rem0 ) < 0 ) { - z -= LIT64( 0x100000000 ); - b1 = b<<32; - add128( rem0, rem1, b0, b1, &rem0, &rem1 ); - } - rem0 = ( rem0<<32 ) | ( rem1>>32 ); - z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the square root of the 32-bit significand given -| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of -| `aExp' (the least significant bit) is 1, the integer returned approximates -| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' -| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either -| case, the approximation returned lies strictly within +/-2 of the exact -| value. -*----------------------------------------------------------------------------*/ - -static bits32 estimateSqrt32( int16 aExp, bits32 a ) -{ - static const bits16 sqrtOddAdjustments[] = { - 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, - 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 - }; - static const bits16 sqrtEvenAdjustments[] = { - 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, - 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 - }; - int8 index; - bits32 z; - - index = ( a>>27 ) & 15; - if ( aExp & 1 ) { - z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; - z = ( ( a / z )<<14 ) + ( z<<15 ); - a >>= 1; - } - else { - z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; - z = a / z + z; - z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 ); - if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 ); - } - return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 32 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros32( bits32 a ) -{ - static const int8 countLeadingZerosHigh[] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - int8 shiftCount; - - shiftCount = 0; - if ( a < 0x10000 ) { - shiftCount += 16; - a <<= 16; - } - if ( a < 0x1000000 ) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZerosHigh[ a>>24 ]; - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 64 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros64( bits64 a ) -{ - int8 shiftCount; - - shiftCount = 0; - if ( a < ( (bits64) 1 )<<32 ) { - shiftCount += 32; - } - else { - a >>= 32; - } - shiftCount += countLeadingZeros32( a ); - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' -| is equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 == b0 ) && ( a1 == b1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, -| returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is -| not equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 != b0 ) || ( a1 != b1 ); - -} - + +/*============================================================================ + +This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point +Arithmetic Package, Release 2c, by John R. Hauser. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER +PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR +THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY +INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE +(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER +PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR +INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE +SOFTWARE. + +Derivative works require also that (1) the source code for the derivative work +includes prominent notice that the work is derivative, and (2) the source code +includes prominent notice of these three paragraphs for those parts of this +code that are retained. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +| Shifts `a' right by the number of bits given in `count'. If any nonzero +| bits are shifted off, they are "jammed" into the least significant bit of +| the result by setting the least significant bit to 1. The value of `count' +| can be arbitrarily large; in particular, if `count' is greater than 32, the +| result will be either 0 or 1, depending on whether `a' is zero or nonzero. +| The result is stored in the location pointed to by `zPtr'. +*----------------------------------------------------------------------------*/ + +INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr ) +{ + bits32 z; + + if ( count == 0 ) { + z = a; + } + else if ( count < 32 ) { + z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); + } + else { + z = ( a != 0 ); + } + *zPtr = z; + +} + +/*---------------------------------------------------------------------------- +| Shifts `a' right by the number of bits given in `count'. If any nonzero +| bits are shifted off, they are "jammed" into the least significant bit of +| the result by setting the least significant bit to 1. The value of `count' +| can be arbitrarily large; in particular, if `count' is greater than 64, the +| result will be either 0 or 1, depending on whether `a' is zero or nonzero. +| The result is stored in the location pointed to by `zPtr'. +*----------------------------------------------------------------------------*/ + +INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr ) +{ + bits64 z; + + if ( count == 0 ) { + z = a; + } + else if ( count < 64 ) { + z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); + } + else { + z = ( a != 0 ); + } + *zPtr = z; + +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 +| _plus_ the number of bits given in `count'. The shifted result is at most +| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The +| bits shifted off form a second 64-bit result as follows: The _last_ bit +| shifted off is the most-significant bit of the extra result, and the other +| 63 bits of the extra result are all zero if and only if _all_but_the_last_ +| bits shifted off were all zero. This extra result is stored in the location +| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. +| (This routine makes more sense if `a0' and `a1' are considered to form +| a fixed-point value with binary point between `a0' and `a1'. This fixed- +| point value is shifted right by the number of bits given in `count', and +| the integer part of the result is returned at the location pointed to by +| `z0Ptr'. The fractional part of the result may be slightly corrupted as +| described above, and is returned at the location pointed to by `z1Ptr'.) +*----------------------------------------------------------------------------*/ + +INLINE void + shift64ExtraRightJamming( + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits64 z0, z1; + int8 negCount = ( - count ) & 63; + + if ( count == 0 ) { + z1 = a1; + z0 = a0; + } + else if ( count < 64 ) { + z1 = ( a0<>count; + } + else { + if ( count == 64 ) { + z1 = a0 | ( a1 != 0 ); + } + else { + z1 = ( ( a0 | a1 ) != 0 ); + } + z0 = 0; + } + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' can be arbitrarily large; in particular, if `count' is greater +| than 128, the result will be 0. The result is broken into two 64-bit pieces +| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +INLINE void + shift128Right( + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits64 z0, z1; + int8 negCount = ( - count ) & 63; + + if ( count == 0 ) { + z1 = a1; + z0 = a0; + } + else if ( count < 64 ) { + z1 = ( a0<>count ); + z0 = a0>>count; + } + else { + z1 = ( count < 128 ) ? ( a0>>( count & 63 ) ) : 0; + z0 = 0; + } + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the +| number of bits given in `count'. If any nonzero bits are shifted off, they +| are "jammed" into the least significant bit of the result by setting the +| least significant bit to 1. The value of `count' can be arbitrarily large; +| in particular, if `count' is greater than 128, the result will be either +| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or +| nonzero. The result is broken into two 64-bit pieces which are stored at +| the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +INLINE void + shift128RightJamming( + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits64 z0, z1; + int8 negCount = ( - count ) & 63; + + if ( count == 0 ) { + z1 = a1; + z0 = a0; + } + else if ( count < 64 ) { + z1 = ( a0<>count ) | ( ( a1<>count; + } + else { + if ( count == 64 ) { + z1 = a0 | ( a1 != 0 ); + } + else if ( count < 128 ) { + z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<>count ); + z0 = a0>>count; + } + else { + if ( count == 64 ) { + z2 = a1; + z1 = a0; + } + else { + a2 |= a1; + if ( count < 128 ) { + z2 = a0<>( count & 63 ); + } + else { + z2 = ( count == 128 ) ? a0 : ( a0 != 0 ); + z1 = 0; + } + } + z0 = 0; + } + z2 |= ( a2 != 0 ); + } + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' must be less than 64. The result is broken into two 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +INLINE void + shortShift128Left( + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + + *z1Ptr = a1<>( ( - count ) & 63 ) ); + +} + +/*---------------------------------------------------------------------------- +| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left +| by the number of bits given in `count'. Any bits shifted off are lost. +| The value of `count' must be less than 64. The result is broken into three +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', +| `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ + +INLINE void + shortShift192Left( + bits64 a0, + bits64 a1, + bits64 a2, + int16 count, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr + ) +{ + bits64 z0, z1, z2; + int8 negCount; + + z2 = a2<>negCount; + z0 |= a1>>negCount; + } + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit +| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so +| any carry out is lost. The result is broken into two 64-bit pieces which +| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +INLINE void + add128( + bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits64 z1; + + z1 = a1 + b1; + *z1Ptr = z1; + *z0Ptr = a0 + b0 + ( z1 < a1 ); + +} + +/*---------------------------------------------------------------------------- +| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the +| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is +| modulo 2^192, so any carry out is lost. The result is broken into three +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', +| `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ + +INLINE void + add192( + bits64 a0, + bits64 a1, + bits64 a2, + bits64 b0, + bits64 b1, + bits64 b2, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr + ) +{ + bits64 z0, z1, z2; + int8 carry0, carry1; + + z2 = a2 + b2; + carry1 = ( z2 < a2 ); + z1 = a1 + b1; + carry0 = ( z1 < a1 ); + z0 = a0 + b0; + z1 += carry1; + z0 += ( z1 < carry1 ); + z0 += carry0; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the +| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo +| 2^128, so any borrow out (carry out) is lost. The result is broken into two +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and +| `z1Ptr'. +*----------------------------------------------------------------------------*/ + +INLINE void + sub128( + bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + + *z1Ptr = a1 - b1; + *z0Ptr = a0 - b0 - ( a1 < b1 ); + +} + +/*---------------------------------------------------------------------------- +| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' +| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. +| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The +| result is broken into three 64-bit pieces which are stored at the locations +| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ + +INLINE void + sub192( + bits64 a0, + bits64 a1, + bits64 a2, + bits64 b0, + bits64 b1, + bits64 b2, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr + ) +{ + bits64 z0, z1, z2; + int8 borrow0, borrow1; + + z2 = a2 - b2; + borrow1 = ( a2 < b2 ); + z1 = a1 - b1; + borrow0 = ( a1 < b1 ); + z0 = a0 - b0; + z0 -= ( z1 < borrow1 ); + z1 -= borrow1; + z0 -= borrow0; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken +| into two 64-bit pieces which are stored at the locations pointed to by +| `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits32 aHigh, aLow, bHigh, bLow; + bits64 z0, zMiddleA, zMiddleB, z1; + + aLow = a; + aHigh = a>>32; + bLow = b; + bHigh = b>>32; + z1 = ( (bits64) aLow ) * bLow; + zMiddleA = ( (bits64) aLow ) * bHigh; + zMiddleB = ( (bits64) aHigh ) * bLow; + z0 = ( (bits64) aHigh ) * bHigh; + zMiddleA += zMiddleB; + z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 ); + zMiddleA <<= 32; + z1 += zMiddleA; + z0 += ( z1 < zMiddleA ); + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by +| `b' to obtain a 192-bit product. The product is broken into three 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and +| `z2Ptr'. +*----------------------------------------------------------------------------*/ + +INLINE void + mul128By64To192( + bits64 a0, + bits64 a1, + bits64 b, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr + ) +{ + bits64 z0, z1, z2, more1; + + mul64To128( a1, b, &z1, &z2 ); + mul64To128( a0, b, &z0, &more1 ); + add128( z0, more1, 0, z1, &z0, &z1 ); + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the +| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit +| product. The product is broken into four 64-bit pieces which are stored at +| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. +*----------------------------------------------------------------------------*/ + +INLINE void + mul128To256( + bits64 a0, + bits64 a1, + bits64 b0, + bits64 b1, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr, + bits64 *z3Ptr + ) +{ + bits64 z0, z1, z2, z3; + bits64 more1, more2; + + mul64To128( a1, b1, &z2, &z3 ); + mul64To128( a1, b0, &z1, &more2 ); + add128( z1, more2, 0, z2, &z1, &z2 ); + mul64To128( a0, b0, &z0, &more1 ); + add128( z0, more1, 0, z1, &z0, &z1 ); + mul64To128( a0, b1, &more1, &more2 ); + add128( more1, more2, 0, z2, &more1, &z2 ); + add128( z0, z1, 0, more1, &z0, &z1 ); + *z3Ptr = z3; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Returns an approximation to the 64-bit integer quotient obtained by dividing +| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The +| divisor `b' must be at least 2^63. If q is the exact quotient truncated +| toward zero, the approximation returned lies between q and q + 2 inclusive. +| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit +| unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b ) +{ + bits64 b0, b1; + bits64 rem0, rem1, term0, term1; + bits64 z; + + if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); + b0 = b>>32; + z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32; + mul64To128( b, z, &term0, &term1 ); + sub128( a0, a1, term0, term1, &rem0, &rem1 ); + while ( ( (sbits64) rem0 ) < 0 ) { + z -= LIT64( 0x100000000 ); + b1 = b<<32; + add128( rem0, rem1, b0, b1, &rem0, &rem1 ); + } + rem0 = ( rem0<<32 ) | ( rem1>>32 ); + z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns an approximation to the square root of the 32-bit significand given +| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of +| `aExp' (the least significant bit) is 1, the integer returned approximates +| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' +| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either +| case, the approximation returned lies strictly within +/-2 of the exact +| value. +*----------------------------------------------------------------------------*/ + +static bits32 estimateSqrt32( int16 aExp, bits32 a ) +{ + static const bits16 sqrtOddAdjustments[] = { + 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, + 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 + }; + static const bits16 sqrtEvenAdjustments[] = { + 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, + 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 + }; + int8 index; + bits32 z; + + index = ( a>>27 ) & 15; + if ( aExp & 1 ) { + z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; + z = ( ( a / z )<<14 ) + ( z<<15 ); + a >>= 1; + } + else { + z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; + z = a / z + z; + z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 ); + if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 ); + } + return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| `a'. If `a' is zero, 32 is returned. +*----------------------------------------------------------------------------*/ + +static int8 countLeadingZeros32( bits32 a ) +{ + static const int8 countLeadingZerosHigh[] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + int8 shiftCount; + + shiftCount = 0; + if ( a < 0x10000 ) { + shiftCount += 16; + a <<= 16; + } + if ( a < 0x1000000 ) { + shiftCount += 8; + a <<= 8; + } + shiftCount += countLeadingZerosHigh[ a>>24 ]; + return shiftCount; + +} + +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| `a'. If `a' is zero, 64 is returned. +*----------------------------------------------------------------------------*/ + +static int8 countLeadingZeros64( bits64 a ) +{ + int8 shiftCount; + + shiftCount = 0; + if ( a < ( (bits64) 1 )<<32 ) { + shiftCount += 32; + } + else { + a >>= 32; + } + shiftCount += countLeadingZeros32( a ); + return shiftCount; + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' +| is equal to the 128-bit value formed by concatenating `b0' and `b1'. +| Otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 == b0 ) && ( a1 == b1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less +| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. +| Otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less +| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, +| returns 0. +*----------------------------------------------------------------------------*/ + +INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is +| not equal to the 128-bit value formed by concatenating `b0' and `b1'. +| Otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 != b0 ) || ( a1 != b1 ); + +} + diff --git a/i386c/ia32/instructions/fpu/softfloat/softfloat-specialize.h b/i386c/ia32/instructions/fpu/softfloat/softfloat-specialize.h index f9d8cbdf..d4590276 100644 --- a/i386c/ia32/instructions/fpu/softfloat/softfloat-specialize.h +++ b/i386c/ia32/instructions/fpu/softfloat/softfloat-specialize.h @@ -1,469 +1,469 @@ - -/*============================================================================ - -This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point -Arithmetic Package, Release 2c, by John R. Hauser. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER -PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR -THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY -INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE -(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER -PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR -INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE -SOFTWARE. - -Derivative works require also that (1) the source code for the derivative work -includes prominent notice that the work is derivative, and (2) the source code -includes prominent notice of these three paragraphs for those parts of this -code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Underflow tininess-detection mode, statically initialized to default value. -| (The declaration in `softfloat.h' must match the `int8' type here.) -*----------------------------------------------------------------------------*/ -int8 float_detect_tininess = float_tininess_after_rounding; - -/*---------------------------------------------------------------------------- -| Raises the exceptions specified by `flags'. Floating-point traps can be -| defined here if desired. It is currently not possible for such a trap -| to substitute a result value. If traps are not implemented, this routine -| should be simply `float_exception_flags |= flags;'. -*----------------------------------------------------------------------------*/ - -void float_raise( int8 flags ) -{ - - float_exception_flags |= flags; - -} - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ -typedef struct { - flag sign; - bits64 high, low; -} commonNaNT; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -#define float32_default_nan 0xFFC00000 - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float32_is_nan( float32 a ) -{ - - return ( 0xFF000000 < (bits32) ( a<<1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float32_is_signaling_nan( float32 a ) -{ - - return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float32ToCommonNaN( float32 a ) -{ - commonNaNT z; - - if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>31; - z.low = 0; - z.high = ( (bits64) a )<<41; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float32 commonNaNToFloat32( commonNaNT a ) -{ - - return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); - -} - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float32 propagateFloat32NaN( float32 a, float32 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float32_is_nan( a ); - aIsSignalingNaN = float32_is_signaling_nan( a ); - bIsNaN = float32_is_nan( b ); - bIsSignalingNaN = float32_is_signaling_nan( b ); - a |= 0x00400000; - b |= 0x00400000; - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsSignalingNaN ) { - if ( bIsSignalingNaN ) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if ( aIsNaN ) { - if ( bIsSignalingNaN | ! bIsNaN ) return a; - returnLargerSignificand: - if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b; - if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a; - return ( a < b ) ? a : b; - } - else { - return b; - } - -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -#define float64_default_nan LIT64( 0xFFF8000000000000 ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float64_is_nan( float64 a ) -{ - - return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float64_is_signaling_nan( float64 a ) -{ - - return - ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) - && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float64ToCommonNaN( float64 a ) -{ - commonNaNT z; - - if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>63; - z.low = 0; - z.high = a<<12; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float64 commonNaNToFloat64( commonNaNT a ) -{ - - return - ( ( (bits64) a.sign )<<63 ) - | LIT64( 0x7FF8000000000000 ) - | ( a.high>>12 ); - -} - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64NaN( float64 a, float64 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float64_is_nan( a ); - aIsSignalingNaN = float64_is_signaling_nan( a ); - bIsNaN = float64_is_nan( b ); - bIsSignalingNaN = float64_is_signaling_nan( b ); - a |= LIT64( 0x0008000000000000 ); - b |= LIT64( 0x0008000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsSignalingNaN ) { - if ( bIsSignalingNaN ) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if ( aIsNaN ) { - if ( bIsSignalingNaN | ! bIsNaN ) return a; - returnLargerSignificand: - if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b; - if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a; - return ( a < b ) ? a : b; - } - else { - return b; - } - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-extended-precision NaN. -| The `high' and `low' values hold the most- and least-significant bits, -| respectively. -*----------------------------------------------------------------------------*/ -#define floatx80_default_nan_high 0xFFFF -#define floatx80_default_nan_low LIT64( 0xC000000000000000 ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-extended-precision floating-point value `a' is a -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_nan( floatx80 a ) -{ - - return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-extended-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_signaling_nan( floatx80 a ) -{ - bits64 aLow; - - aLow = a.low & ~ LIT64( 0x4000000000000000 ); - return - ( ( a.high & 0x7FFF ) == 0x7FFF ) - && (bits64) ( aLow<<1 ) - && ( a.low == aLow ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-extended-precision floating-point value `a' is an -| infinity; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_inf( floatx80 a ) -{ - - return ( ( a.high & 0x7FFF ) == 0x7FFF ) && ( a.low == 0x8000000000000000LL ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-extended-precision floating- -| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the -| invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT floatx80ToCommonNaN( floatx80 a ) -{ - commonNaNT z; - - if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>15; - z.low = 0; - z.high = a.low<<1; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| extended-precision floating-point format. -*----------------------------------------------------------------------------*/ - -static floatx80 commonNaNToFloatx80( commonNaNT a ) -{ - floatx80 z; - - z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); - z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two double-extended-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = floatx80_is_nan( a ); - aIsSignalingNaN = floatx80_is_signaling_nan( a ); - bIsNaN = floatx80_is_nan( b ); - bIsSignalingNaN = floatx80_is_signaling_nan( b ); - a.low |= LIT64( 0xC000000000000000 ); - b.low |= LIT64( 0xC000000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsSignalingNaN ) { - if ( bIsSignalingNaN ) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if ( aIsNaN ) { - if ( bIsSignalingNaN | ! bIsNaN ) return a; - returnLargerSignificand: - if ( a.low < b.low ) return b; - if ( b.low < a.low ) return a; - return ( a.high < b.high ) ? a : b; - } - else { - return b; - } - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. The `high' and -| `low' values hold the most- and least-significant bits, respectively. -*----------------------------------------------------------------------------*/ -#define float128_default_nan_high LIT64( 0xFFFF800000000000 ) -#define float128_default_nan_low LIT64( 0x0000000000000000 ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_nan( float128 a ) -{ - - return - ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) - && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_signaling_nan( float128 a ) -{ - - return - ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) - && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float128ToCommonNaN( float128 a ) -{ - commonNaNT z; - - if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>63; - shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float128 commonNaNToFloat128( commonNaNT a ) -{ - float128 z; - - shift128Right( a.high, a.low, 16, &z.high, &z.low ); - z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float128 propagateFloat128NaN( float128 a, float128 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float128_is_nan( a ); - aIsSignalingNaN = float128_is_signaling_nan( a ); - bIsNaN = float128_is_nan( b ); - bIsSignalingNaN = float128_is_signaling_nan( b ); - a.high |= LIT64( 0x0000800000000000 ); - b.high |= LIT64( 0x0000800000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsSignalingNaN ) { - if ( bIsSignalingNaN ) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if ( aIsNaN ) { - if ( bIsSignalingNaN | ! bIsNaN ) return a; - returnLargerSignificand: - if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; - if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; - return ( a.high < b.high ) ? a : b; - } - else { - return b; - } - -} - -#endif - + +/*============================================================================ + +This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point +Arithmetic Package, Release 2c, by John R. Hauser. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER +PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR +THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY +INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE +(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER +PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR +INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE +SOFTWARE. + +Derivative works require also that (1) the source code for the derivative work +includes prominent notice that the work is derivative, and (2) the source code +includes prominent notice of these three paragraphs for those parts of this +code that are retained. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +| Underflow tininess-detection mode, statically initialized to default value. +| (The declaration in `softfloat.h' must match the `int8' type here.) +*----------------------------------------------------------------------------*/ +int8 float_detect_tininess = float_tininess_after_rounding; + +/*---------------------------------------------------------------------------- +| Raises the exceptions specified by `flags'. Floating-point traps can be +| defined here if desired. It is currently not possible for such a trap +| to substitute a result value. If traps are not implemented, this routine +| should be simply `float_exception_flags |= flags;'. +*----------------------------------------------------------------------------*/ + +void float_raise( int8 flags ) +{ + + float_exception_flags |= flags; + +} + +/*---------------------------------------------------------------------------- +| Internal canonical NaN format. +*----------------------------------------------------------------------------*/ +typedef struct { + flag sign; + bits64 high, low; +} commonNaNT; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated single-precision NaN. +*----------------------------------------------------------------------------*/ +#define float32_default_nan 0xFFC00000 + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a NaN; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float32_is_nan( float32 a ) +{ + + return ( 0xFF000000 < (bits32) ( a<<1 ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a signaling +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float32_is_signaling_nan( float32 a ) +{ + + return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT float32ToCommonNaN( float32 a ) +{ + commonNaNT z; + + if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a>>31; + z.low = 0; + z.high = ( (bits64) a )<<41; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the single- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static float32 commonNaNToFloat32( commonNaNT a ) +{ + + return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); + +} + +/*---------------------------------------------------------------------------- +| Takes two single-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static float32 propagateFloat32NaN( float32 a, float32 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float32_is_nan( a ); + aIsSignalingNaN = float32_is_signaling_nan( a ); + bIsNaN = float32_is_nan( b ); + bIsSignalingNaN = float32_is_signaling_nan( b ); + a |= 0x00400000; + b |= 0x00400000; + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsSignalingNaN ) { + if ( bIsSignalingNaN ) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if ( aIsNaN ) { + if ( bIsSignalingNaN | ! bIsNaN ) return a; + returnLargerSignificand: + if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b; + if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a; + return ( a < b ) ? a : b; + } + else { + return b; + } + +} + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-precision NaN. +*----------------------------------------------------------------------------*/ +#define float64_default_nan LIT64( 0xFFF8000000000000 ) + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is a NaN; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float64_is_nan( float64 a ) +{ + + return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is a signaling +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float64_is_signaling_nan( float64 a ) +{ + + return + ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) + && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT float64ToCommonNaN( float64 a ) +{ + commonNaNT z; + + if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a>>63; + z.low = 0; + z.high = a<<12; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the double- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static float64 commonNaNToFloat64( commonNaNT a ) +{ + + return + ( ( (bits64) a.sign )<<63 ) + | LIT64( 0x7FF8000000000000 ) + | ( a.high>>12 ); + +} + +/*---------------------------------------------------------------------------- +| Takes two double-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static float64 propagateFloat64NaN( float64 a, float64 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float64_is_nan( a ); + aIsSignalingNaN = float64_is_signaling_nan( a ); + bIsNaN = float64_is_nan( b ); + bIsSignalingNaN = float64_is_signaling_nan( b ); + a |= LIT64( 0x0008000000000000 ); + b |= LIT64( 0x0008000000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsSignalingNaN ) { + if ( bIsSignalingNaN ) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if ( aIsNaN ) { + if ( bIsSignalingNaN | ! bIsNaN ) return a; + returnLargerSignificand: + if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b; + if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a; + return ( a < b ) ? a : b; + } + else { + return b; + } + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-extended-precision NaN. +| The `high' and `low' values hold the most- and least-significant bits, +| respectively. +*----------------------------------------------------------------------------*/ +#define floatx80_default_nan_high 0xFFFF +#define floatx80_default_nan_low LIT64( 0xC000000000000000 ) + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-extended-precision floating-point value `a' is a +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag floatx80_is_nan( floatx80 a ) +{ + + return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-extended-precision floating-point value `a' is a +| signaling NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag floatx80_is_signaling_nan( floatx80 a ) +{ + bits64 aLow; + + aLow = a.low & ~ LIT64( 0x4000000000000000 ); + return + ( ( a.high & 0x7FFF ) == 0x7FFF ) + && (bits64) ( aLow<<1 ) + && ( a.low == aLow ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-extended-precision floating-point value `a' is an +| infinity; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag floatx80_is_inf( floatx80 a ) +{ + + return ( ( a.high & 0x7FFF ) == 0x7FFF ) && ( a.low == 0x8000000000000000LL ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-extended-precision floating- +| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT floatx80ToCommonNaN( floatx80 a ) +{ + commonNaNT z; + + if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a.high>>15; + z.low = 0; + z.high = a.low<<1; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the double- +| extended-precision floating-point format. +*----------------------------------------------------------------------------*/ + +static floatx80 commonNaNToFloatx80( commonNaNT a ) +{ + floatx80 z; + + z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); + z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes two double-extended-precision floating-point values `a' and `b', one +| of which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = floatx80_is_nan( a ); + aIsSignalingNaN = floatx80_is_signaling_nan( a ); + bIsNaN = floatx80_is_nan( b ); + bIsSignalingNaN = floatx80_is_signaling_nan( b ); + a.low |= LIT64( 0xC000000000000000 ); + b.low |= LIT64( 0xC000000000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsSignalingNaN ) { + if ( bIsSignalingNaN ) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if ( aIsNaN ) { + if ( bIsSignalingNaN | ! bIsNaN ) return a; + returnLargerSignificand: + if ( a.low < b.low ) return b; + if ( b.low < a.low ) return a; + return ( a.high < b.high ) ? a : b; + } + else { + return b; + } + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| The pattern for a default generated quadruple-precision NaN. The `high' and +| `low' values hold the most- and least-significant bits, respectively. +*----------------------------------------------------------------------------*/ +#define float128_default_nan_high LIT64( 0xFFFF800000000000 ) +#define float128_default_nan_low LIT64( 0x0000000000000000 ) + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float128_is_nan( float128 a ) +{ + + return + ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) + && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is a +| signaling NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float128_is_signaling_nan( float128 a ) +{ + + return + ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) + && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT float128ToCommonNaN( float128 a ) +{ + commonNaNT z; + + if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a.high>>63; + shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the quadruple- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static float128 commonNaNToFloat128( commonNaNT a ) +{ + float128 z; + + shift128Right( a.high, a.low, 16, &z.high, &z.low ); + z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes two quadruple-precision floating-point values `a' and `b', one of +| which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static float128 propagateFloat128NaN( float128 a, float128 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float128_is_nan( a ); + aIsSignalingNaN = float128_is_signaling_nan( a ); + bIsNaN = float128_is_nan( b ); + bIsSignalingNaN = float128_is_signaling_nan( b ); + a.high |= LIT64( 0x0000800000000000 ); + b.high |= LIT64( 0x0000800000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsSignalingNaN ) { + if ( bIsSignalingNaN ) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if ( aIsNaN ) { + if ( bIsSignalingNaN | ! bIsNaN ) return a; + returnLargerSignificand: + if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; + if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; + return ( a.high < b.high ) ? a : b; + } + else { + return b; + } + +} + +#endif + diff --git a/i386c/ia32/instructions/fpu/softfloat/softfloat.c b/i386c/ia32/instructions/fpu/softfloat/softfloat.c index 6f8f57a1..f2adb4ec 100644 --- a/i386c/ia32/instructions/fpu/softfloat/softfloat.c +++ b/i386c/ia32/instructions/fpu/softfloat/softfloat.c @@ -1,5437 +1,5437 @@ - -/*============================================================================ - -This C source file is part of the Berkeley SoftFloat IEEE Floating-Point -Arithmetic Package, Release 2c, by John R. Hauser. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER -PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR -THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY -INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE -(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER -PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR -INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE -SOFTWARE. - -Derivative works require also that (1) the source code for the derivative work -includes prominent notice that the work is derivative, and (2) the source code -includes prominent notice of these three paragraphs for those parts of this -code that are retained. - -=============================================================================*/ - -#include "compiler.h" - -#ifdef SUPPORT_FPU_SOFTFLOAT - -#include "softfloatdef.h" -//#include "milieu.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Floating-point rounding mode, double-extended-precision rounding precision, -| and exception flags. -*----------------------------------------------------------------------------*/ -int8 float_rounding_mode = float_round_nearest_even; -int8 float_exception_flags = 0; -#ifdef FLOATX80 -int8 floatx80_rounding_precision = 80; -#endif - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target if -| desired.) -*----------------------------------------------------------------------------*/ -#include "softfloat-macros.h" // rename softfloat-macros -> softfloat-macros.h - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize.h" // rename softfloat-specialize -> softfloat-specialize.h - -// for np2 FPU by SimK 2025/10/25 -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 16-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the largest -| negative integer is returned. -*----------------------------------------------------------------------------*/ - -static int16 roundAndPackInt16_np2(flag zSign, bits64 absZ) -{ - int8 roundingMode; - flag roundNearestEven; - int8 roundIncrement, roundBits; - int16 z; - - roundingMode = float_rounding_mode; - roundNearestEven = (roundingMode == float_round_nearest_even); - roundIncrement = 0x40; - if (!roundNearestEven) { - if (roundingMode == float_round_to_zero) { - roundIncrement = 0; - } - else { - roundIncrement = 0x7F; - if (zSign) { - if (roundingMode == float_round_up) roundIncrement = 0; - } - else { - if (roundingMode == float_round_down) roundIncrement = 0; - } - } - } - roundBits = absZ & 0x7F; - absZ = (absZ + roundIncrement) >> 7; - absZ &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); - z = absZ; - if (zSign) z = -z; - z = (sbits16)z; - if ((absZ >> 16) || (z && ((z < 0) ^ zSign))) { - float_raise(float_flag_invalid); - return (sbits16)0x8000; // for np2 by SimK 2025/10/25 - } - if (roundBits) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the largest -| negative integer is returned. -*----------------------------------------------------------------------------*/ - -static int32 roundAndPackInt32_np2(flag zSign, bits64 absZ) -{ - int8 roundingMode; - flag roundNearestEven; - int8 roundIncrement, roundBits; - int32 z; - - roundingMode = float_rounding_mode; - roundNearestEven = (roundingMode == float_round_nearest_even); - roundIncrement = 0x40; - if (!roundNearestEven) { - if (roundingMode == float_round_to_zero) { - roundIncrement = 0; - } - else { - roundIncrement = 0x7F; - if (zSign) { - if (roundingMode == float_round_up) roundIncrement = 0; - } - else { - if (roundingMode == float_round_down) roundIncrement = 0; - } - } - } - roundBits = absZ & 0x7F; - absZ = (absZ + roundIncrement) >> 7; - absZ &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); - z = absZ; - if (zSign) z = -z; - z = (sbits32)z; - if ((absZ >> 32) || (z && ((z < 0) ^ zSign))) { - float_raise(float_flag_invalid); - return 0x80000000; // for np2 by SimK 2025/10/25 - } - if (roundBits) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest negative integer is returned. -*----------------------------------------------------------------------------*/ - -static int64 roundAndPackInt64_np2(flag zSign, bits64 absZ0, bits64 absZ1) -{ - int8 roundingMode; - flag roundNearestEven, increment; - int64 z; - - roundingMode = float_rounding_mode; - roundNearestEven = (roundingMode == float_round_nearest_even); - increment = ((sbits64)absZ1 < 0); - if (!roundNearestEven) { - if (roundingMode == float_round_to_zero) { - increment = 0; - } - else { - if (zSign) { - increment = (roundingMode == float_round_down) && absZ1; - } - else { - increment = (roundingMode == float_round_up) && absZ1; - } - } - } - if (increment) { - ++absZ0; - if (absZ0 == 0) goto overflow; - absZ0 &= ~(((bits64)(absZ1 << 1) == 0) & roundNearestEven); - } - z = absZ0; - if (zSign) z = -z; - z = (sbits64)z; - if (z && ((z < 0) ^ zSign)) { - overflow: - float_raise(float_flag_invalid); - return LIT64(0x8000000000000000); // for np2 by SimK 2025/10/25 - } - if (absZ1) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the largest -| positive or negative integer is returned. -*----------------------------------------------------------------------------*/ - -static int32 roundAndPackInt32( flag zSign, bits64 absZ ) -{ - int8 roundingMode; - flag roundNearestEven; - int8 roundIncrement, roundBits; - int32 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - roundIncrement = 0x40; - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - roundIncrement = 0; - } - else { - roundIncrement = 0x7F; - if ( zSign ) { - if ( roundingMode == float_round_up ) roundIncrement = 0; - } - else { - if ( roundingMode == float_round_down ) roundIncrement = 0; - } - } - } - roundBits = absZ & 0x7F; - absZ = ( absZ + roundIncrement )>>7; - absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - z = absZ; - if ( zSign ) z = - z; - z = (sbits32) z; - if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { - float_raise( float_flag_invalid ); - return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( roundBits ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest positive or negative integer is -| returned. -*----------------------------------------------------------------------------*/ - -static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 ) -{ - int8 roundingMode; - flag roundNearestEven, increment; - int64 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - increment = ( (sbits64) absZ1 < 0 ); - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - increment = 0; - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && absZ1; - } - else { - increment = ( roundingMode == float_round_up ) && absZ1; - } - } - } - if ( increment ) { - ++absZ0; - if ( absZ0 == 0 ) goto overflow; - absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven ); - } - z = absZ0; - if ( zSign ) z = - z; - z = (sbits64) z; - if ( z && ( ( z < 0 ) ^ zSign ) ) { - overflow: - float_raise( float_flag_invalid ); - return - zSign ? (sbits64) LIT64( 0x8000000000000000 ) - : LIT64( 0x7FFFFFFFFFFFFFFF ); - } - if ( absZ1 ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE bits32 extractFloat32Frac( float32 a ) -{ - - return a & 0x007FFFFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE int16 extractFloat32Exp( float32 a ) -{ - - return ( a>>23 ) & 0xFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloat32Sign( float32 a ) -{ - - return a>>31; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( aSig ) - 8; - *zSigPtr = aSig<>7; - zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the "true" -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float32 - normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( zSig ) - 1; - return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<>52 ) & 0x7FF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloat64Sign( float64 a ) -{ - - return a>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal double-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( aSig ) - 11; - *zSigPtr = aSig<>10; - zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the "true" -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float64 - normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( zSig ) - 1; - return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<>15; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal double-extended-precision floating-point value -| represented by the denormalized significand `aSig'. The normalized exponent -| and significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( aSig ); - *zSigPtr = aSig<>48 ) & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloat128Sign( float128 a ) -{ - - return a.high>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat128Subnormal( - bits64 aSig0, - bits64 aSig1, - int32 *zExpPtr, - bits64 *zSig0Ptr, - bits64 *zSig1Ptr - ) -{ - int8 shiftCount; - - if ( aSig0 == 0 ) { - shiftCount = countLeadingZeros64( aSig1 ) - 15; - if ( shiftCount < 0 ) { - *zSig0Ptr = aSig1>>( - shiftCount ); - *zSig1Ptr = aSig1<<( shiftCount & 63 ); - } - else { - *zSig0Ptr = aSig1<>( - shiftCount ); - if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEEE Standard for Floating-Point Arithmetic--- -| which means in particular that the conversion is rounded according to the -| current rounding mode. If `a' is a NaN, the largest positive integer is -| returned. Otherwise, if the conversion overflows, the largest integer with -| the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64, aSigExtra; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = 0xBE - aExp; - if ( shiftCount < 0 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - if ( aExp ) aSig |= 0x00800000; - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra ); - return roundAndPackInt64( aSign, aSig64, aSigExtra ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEEE Standard for Floating-Point Arithmetic, -| except that the conversion is always rounded toward zero. If `a' is a NaN, -| the largest positive integer is returned. Otherwise, if the conversion -| overflows, the largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64_round_to_zero( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64; - int64 z; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = aExp - 0xBE; - if ( 0 <= shiftCount ) { - if ( a != 0xDF000000 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - else if ( aExp <= 0x7E ) { - if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - z = aSig64>>( - shiftCount ); - if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float32_to_float64( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) ); - return packFloat64( aSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-extended-precision floating-point format. The conversion -| is performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float32_to_floatx80( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - aSig |= 0x00800000; - return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float32_to_float128( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the single-precision floating-point value `a' to an integer, -| and returns the result as a single-precision floating-point value. The -| operation is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_round_to_int( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 lastBitMask, roundBitsMask; - int8 roundingMode; - float32 z; - - aExp = extractFloat32Exp( a ); - if ( 0x96 <= aExp ) { - if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { - return propagateFloat32NaN( a, a ); - } - return a; - } - if ( aExp <= 0x7E ) { - if ( (bits32) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat32Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { - return packFloat32( aSign, 0x7F, 0 ); - } - break; - case float_round_down: - return aSign ? 0xBF800000 : 0; - case float_round_up: - return aSign ? 0x80000000 : 0x3F800000; - } - return packFloat32( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x96 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the single-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. The -| addition is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 6; - bSig <<= 6; - if ( 0 < expDiff ) { - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x20000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x20000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); - zSig = 0x40000000 + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= 0x20000000; - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits32) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the single- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 7; - bSig <<= 7; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign ^ 1, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x40000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - bSig |= 0x40000000; - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x40000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - aSig |= 0x40000000; - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEEE Standard for -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_add( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return addFloat32Sigs( a, b, aSign ); - } - else { - return subFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEEE Standard for -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sub( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return subFloat32Sigs( a, b, aSign ); - } - else { - return addFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEEE Standard for -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_mul( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig; - bits64 zSig64; - bits32 zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x7F; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 ); - zSig = zSig64; - if ( 0 <= (sbits32) ( zSig<<1 ) ) { - zSig <<= 1; - --zExp; - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the single-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to the -| IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_div( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat32( zSign, 0xFF, 0 ); - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x7D; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = ( ( (bits64) aSig )<<32 ) / bSig; - if ( ( zSig & 0x3F ) == 0 ) { - zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 ); - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the single-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_rem( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, expDiff; - bits32 aSig, bSig; - bits32 q; - bits64 aSig64, bSig64, q64; - bits32 alternateASig; - sbits32 sigMean; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig |= 0x00800000; - bSig |= 0x00800000; - if ( expDiff < 32 ) { - aSig <<= 8; - bSig <<= 8; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - if ( 0 < expDiff ) { - q = ( ( (bits64) aSig )<<32 ) / bSig; - q >>= 32 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - } - else { - if ( bSig <= aSig ) aSig -= bSig; - aSig64 = ( (bits64) aSig )<<40; - bSig64 = ( (bits64) bSig )<<40; - expDiff -= 64; - while ( 0 < expDiff ) { - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - aSig64 = - ( ( bSig * q64 )<<38 ); - expDiff -= 62; - } - expDiff += 64; - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - q = q64>>( 64 - expDiff ); - bSig <<= 6; - aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits32) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits32) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the single-precision floating-point value `a'. -| The operation is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sqrt( float32 a ) -{ - flag aSign; - int16 aExp, zExp; - bits32 aSig, zSig; - bits64 rem, term; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, 0 ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; - aSig = ( aSig | 0x00800000 )<<8; - zSig = estimateSqrt32( aExp, aSig ) + 2; - if ( ( zSig & 0x7F ) <= 5 ) { - if ( zSig < 2 ) { - zSig = 0x7FFFFFFF; - goto roundAndPack; - } - aSig >>= aExp & 1; - term = ( (bits64) zSig ) * zSig; - rem = ( ( (bits64) aSig )<<32 ) - term; - while ( (sbits64) rem < 0 ) { - --zSig; - rem += ( ( (bits64) zSig )<<1 ) | 1; - } - zSig |= ( rem != 0 ); - } - shift32RightJamming( zSig, 1, &zSig ); - roundAndPack: - return roundAndPackFloat32( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq( float32 a, float32 b ) -{ - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq_signaling( float32 a, float32 b ) -{ - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; - int16 aExp, bExp; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEEE Standard for Floating-Point Arithmetic--- -| which means in particular that the conversion is rounded according to the -| current rounding mode. If `a' is a NaN, the largest positive integer is -| returned. Otherwise, if the conversion overflows, the largest integer with -| the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x42C - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEEE Standard for Floating-Point Arithmetic, -| except that the conversion is always rounded toward zero. If `a' is a NaN, -| the largest positive integer is returned. Otherwise, if the conversion -| overflows, the largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32_round_to_zero( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( 0x41E < aExp ) { - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - z = (sbits32) z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float64_to_float32( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - bits32 zSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) ); - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 22, &aSig ); - zSig = aSig; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x381; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the double-extended-precision floating-point format. The conversion -| is performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float64_to_floatx80( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - return - packFloatx80( - aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the quadruple-precision floating-point format. The conversion is -| performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float64_to_float128( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - shift128Right( aSig, 0, 4, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the double-precision floating-point value `a' to an integer, -| and returns the result as a double-precision floating-point value. The -| operation is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_round_to_int( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float64 z; - - aExp = extractFloat64Exp( a ); - if ( 0x433 <= aExp ) { - if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { - return propagateFloat64NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FF ) { - if ( (bits64) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat64Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { - return packFloat64( aSign, 0x3FF, 0 ); - } - break; - case float_round_down: - return aSign ? LIT64( 0xBFF0000000000000 ) : 0; - case float_round_up: - return - aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ); - } - return packFloat64( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x433 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. The -| addition is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 9; - bSig <<= 9; - if ( 0 < expDiff ) { - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); - zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= LIT64( 0x2000000000000000 ); - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits64) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 10; - bSig <<= 10; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign ^ 1, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - bSig |= LIT64( 0x4000000000000000 ); - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - aSig |= LIT64( 0x4000000000000000 ); - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEEE Standard for -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_add( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return addFloat64Sigs( a, b, aSign ); - } - else { - return subFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEEE Standard for -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sub( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return subFloat64Sigs( a, b, aSign ); - } - else { - return addFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEEE Standard for -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_mul( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FF; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - zSig0 |= ( zSig1 != 0 ); - if ( 0 <= (sbits64) ( zSig0<<1 ) ) { - zSig0 <<= 1; - --zExp; - } - return roundAndPackFloat64( zSign, zExp, zSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the double-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to the -| IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_div( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - bits64 rem0, rem1; - bits64 term0, term1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat64( zSign, 0x7FF, 0 ); - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FD; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = estimateDiv128To64( aSig, 0, bSig ); - if ( ( zSig & 0x1FF ) <= 2 ) { - mul64To128( bSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig |= ( rem1 != 0 ); - } - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the double-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_rem( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, expDiff; - bits64 aSig, bSig; - bits64 q, alternateASig; - sbits64 sigMean; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - aSig = - ( ( bSig>>2 ) * q ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits64) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits64) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the double-precision floating-point value `a'. -| The operation is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sqrt( float64 a ) -{ - flag aSign; - int16 aExp, zExp; - bits64 aSig, zSig, doubleZSig; - bits64 rem0, rem1, term0, term1; - float64 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, a ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; - aSig |= LIT64( 0x0010000000000000 ); - zSig = estimateSqrt32( aExp, aSig>>21 ); - aSig <<= 9 - ( aExp & 1 ); - zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 ); - if ( ( zSig & 0x1FF ) <= 5 ) { - doubleZSig = zSig<<1; - mul64To128( zSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - doubleZSig -= 2; - add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 ); - } - zSig |= ( ( rem0 | rem1 ) != 0 ); - } - return roundAndPackFloat64( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq( float64 a, float64 b ) -{ - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq_signaling( float64 a, float64 b ) -{ - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; - int16 aExp, bExp; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -#ifdef FLOATX80 - -// for np2 FPU by SimK 2025/10/25 -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-extended-precision floating- -| point value `a' to the 16-bit two's complement integer format. The -| conversion is performed according to the IEEE Standard for Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the conversion -| overflows, the largest negative integer is returned. -*----------------------------------------------------------------------------*/ - -int16 floatx80_to_int16_np2(floatx80 a) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - if ((aExp == 0x7FFF) && (bits64)(aSig << 1)) aSign = 0; - shiftCount = 0x4037 - aExp; - if (shiftCount <= 0) shiftCount = 1; - shift64RightJamming(aSig, shiftCount, &aSig); - return roundAndPackInt16_np2(aSign, aSig); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-extended-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEEE Standard for Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the conversion -| overflows, the largest negative integer is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32_np2(floatx80 a) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - if ((aExp == 0x7FFF) && (bits64)(aSig << 1)) aSign = 0; - shiftCount = 0x4037 - aExp; - if (shiftCount <= 0) shiftCount = 1; - shift64RightJamming(aSig, shiftCount, &aSig); - return roundAndPackInt32_np2(aSign, aSig); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-extended-precision floating- -| point value `a' to the 64-bit two's complement integer format. The -| conversion is performed according to the IEEE Standard for Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the conversion -| overflows, the largest negative integer is returned. -*----------------------------------------------------------------------------*/ - -int64 floatx80_to_int64_np2(floatx80 a) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig, aSigExtra; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - shiftCount = 0x403E - aExp; - if (shiftCount <= 0) { - if (shiftCount) { - float_raise(float_flag_invalid); - return (sbits64)LIT64(0x8000000000000000); - } - aSigExtra = 0; - } - else { - shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra); - } - return roundAndPackInt64_np2(aSign, aSig, aSigExtra); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-extended-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEEE Standard for Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - shiftCount = 0x4037 - aExp; - if ( shiftCount <= 0 ) shiftCount = 1; - shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-extended-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEEE Standard for Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32_round_to_zero( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - shiftCount = 0x403E - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - z = (sbits32) z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-extended-precision floating- -| point value `a' to the single-precision floating-point format. The -| conversion is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 floatx80_to_float32( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 33, &aSig ); - if ( aExp || aSig ) aExp -= 0x3F81; - return roundAndPackFloat32( aSign, aExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-extended-precision floating- -| point value `a' to the double-precision floating-point format. The -| conversion is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 floatx80_to_float64( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig, zSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shift64RightJamming( aSig, 1, &zSig ); - if ( aExp || aSig ) aExp -= 0x3C01; - return roundAndPackFloat64( aSign, aExp, zSig ); - -} - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-extended-precision floating- -| point value `a' to the quadruple-precision floating-point format. The -| conversion is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 floatx80_to_float128( floatx80 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat128( floatx80ToCommonNaN( a ) ); - } - shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the double-extended-precision floating-point value `a' to an integer, -| and returns the result as an double-extended-precision floating-point value. -| The operation is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_round_to_int( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - floatx80 z; - - aExp = extractFloatx80Exp( a ); - if ( 0x403E <= aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { - return propagateFloatx80NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FFF ) { - if ( ( aExp == 0 ) - && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { - return a; - } - float_exception_flags |= float_flag_inexact; - aSign = extractFloatx80Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) - ) { - return - packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - break; - case float_round_down: - return - aSign ? - packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) - : packFloatx80( 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloatx80( 1, 0, 0 ) - : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - return packFloatx80( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x403E - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.low += lastBitMask>>1; - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z.low += roundBitsMask; - } - } - z.low &= ~ roundBitsMask; - if ( z.low == 0 ) { - ++z.high; - z.low = LIT64( 0x8000000000000000 ); - } - if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-extended- -| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is -| negated before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - return a; - } - zSig1 = 0; - zSig0 = aSig + bSig; - if ( aExp == 0 ) { - normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); - goto roundAndPack; - } - zExp = aExp; - goto shiftRight1; - } - zSig0 = aSig + bSig; - if ( (sbits64) zSig0 < 0 ) goto roundAndPack; - shiftRight1: - shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= LIT64( 0x8000000000000000 ); - ++zExp; - roundAndPack: - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| extended-precision floating-point values `a' and `b'. If `zSign' is 1, -| the difference is negated before being returned. `zSign' is ignored if -| the result is a NaN. The subtraction is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - zSig1 = 0; - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - bBigger: - sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - aBigger: - sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - return - normalizeRoundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the double-extended-precision floating-point -| values `a' and `b'. The operation is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_add( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return addFloatx80Sigs( a, b, aSign ); - } - else { - return subFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the double-extended-precision floating- -| point values `a' and `b'. The operation is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sub( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return subFloatx80Sigs( a, b, aSign ); - } - else { - return addFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-extended-precision floating- -| point values `a' and `b'. The operation is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_mul( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) goto invalid; - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FFE; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - if ( 0 < (sbits64) zSig0 ) { - shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); - --zExp; - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the double-extended-precision floating-point -| value `a' by the corresponding value `b'. The operation is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_div( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - bits64 rem0, rem1, rem2, term0, term1, term2; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - goto invalid; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FFE; - rem1 = 0; - if ( bSig <= aSig ) { - shift128Right( aSig, 0, 1, &aSig, &rem1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig, rem1, bSig ); - mul64To128( bSig, zSig0, &term0, &term1 ); - sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, bSig ); - if ( (bits64) ( zSig1<<1 ) <= 8 ) { - mul64To128( bSig, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); - } - zSig1 |= ( ( rem1 | rem2 ) != 0 ); - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the double-extended-precision floating-point value -| `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_rem( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig; - bits64 q, term0, term1, alternateASig0, alternateASig1; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( (bits64) ( aSig0<<1 ) == 0 ) return a; - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - bSig |= LIT64( 0x8000000000000000 ); - zSign = aSign; - expDiff = aExp - bExp; - aSig1 = 0; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); - expDiff = 0; - } - q = ( bSig <= aSig0 ); - if ( q ) aSig0 -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - mul64To128( bSig, q, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); - while ( le128( term0, term1, aSig0, aSig1 ) ) { - ++q; - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - } - } - else { - term1 = 0; - term0 = bSig; - } - sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); - if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) - || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) - && ( q & 1 ) ) - ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - zSign = ! zSign; - } - return - normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the double-extended-precision floating-point -| value `a'. The operation is performed according to the IEEE Standard for -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sqrt( floatx80 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; - zSig0 = estimateSqrt32( aExp, aSig0>>32 ); - shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= doubleZSig0; - return - roundAndPackFloatx80( - floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-extended-precision floating-point value `a' is -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq( floatx80 a, floatx80 b ) -{ - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-extended-precision floating-point value `a' is -| less than or equal to the corresponding value `b', and 0 otherwise. The -| comparison is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-extended-precision floating-point value `a' is -| less than the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-extended-precision floating-point value `a' is equal -| to the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq_signaling( floatx80 a, floatx80 b ) -{ - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-extended-precision floating-point value `a' is less -| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs -| do not cause an exception. Otherwise, the comparison is performed according -| to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-extended-precision floating-point value `a' is less -| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause -| an exception. Otherwise, the comparison is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEEE Standard for Floating-Point Arithmetic--- -| which means in particular that the conversion is rounded according to the -| current rounding mode. If `a' is a NaN, the largest positive integer is -| returned. Otherwise, if the conversion overflows, the largest integer with -| the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); - aSig0 |= ( aSig1 != 0 ); - shiftCount = 0x4028 - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); - return roundAndPackInt32( aSign, aSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEEE Standard for Floating-Point Arithmetic, -| except that the conversion is always rounded toward zero. If `a' is a NaN, -| the largest positive integer is returned. Otherwise, if the conversion -| overflows, the largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32_round_to_zero( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1, savedASig; - int32 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - aSig0 |= ( aSig1 != 0 ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig0 ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig0 |= LIT64( 0x0001000000000000 ); - shiftCount = 0x402F - aExp; - savedASig = aSig0; - aSig0 >>= shiftCount; - z = aSig0; - if ( aSign ) z = - z; - z = (sbits32) z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig0<>( ( - shiftCount ) & 63 ) ); - if ( (bits64) ( aSig1<>( - shiftCount ); - if ( aSig1 - || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the single-precision floating-point format. The conversion is -| performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float128_to_float32( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - bits32 zSig; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat32( float128ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - aSig0 |= ( aSig1 != 0 ); - shift64RightJamming( aSig0, 18, &aSig0 ); - zSig = aSig0; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x3F81; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the double-precision floating-point format. The conversion is -| performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float128_to_float64( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat64( float128ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - aSig0 |= ( aSig1 != 0 ); - if ( aExp || aSig0 ) { - aSig0 |= LIT64( 0x4000000000000000 ); - aExp -= 0x3C01; - } - return roundAndPackFloat64( aSign, aExp, aSig0 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the double-extended-precision floating-point format. The -| conversion is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float128_to_floatx80( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloatx80( float128ToCommonNaN( a ) ); - } - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); - return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the quadruple-precision floating-point value `a' to an integer, -| and returns the result as a quadruple-precision floating-point value. The -| operation is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_round_to_int( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float128 z; - - aExp = extractFloat128Exp( a ); - if ( 0x402F <= aExp ) { - if ( 0x406F <= aExp ) { - if ( ( aExp == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) - ) { - return propagateFloat128NaN( a, a ); - } - return a; - } - lastBitMask = 1; - lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - if ( lastBitMask ) { - add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else { - if ( (sbits64) z.low < 0 ) { - ++z.high; - if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1; - } - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); - } - } - z.low &= ~ roundBitsMask; - } - else { - if ( aExp < 0x3FFF ) { - if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat128Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) - && ( extractFloat128Frac0( a ) - | extractFloat128Frac1( a ) ) - ) { - return packFloat128( aSign, 0x3FFF, 0, 0 ); - } - break; - case float_round_down: - return - aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) - : packFloat128( 0, 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloat128( 1, 0, 0, 0 ) - : packFloat128( 0, 0x3FFF, 0, 0 ); - } - return packFloat128( aSign, 0, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x402F - aExp; - roundBitsMask = lastBitMask - 1; - z.low = 0; - z.high = a.high; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.high += lastBitMask>>1; - if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { - z.high &= ~ lastBitMask; - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - z.high |= ( a.low != 0 ); - z.high += roundBitsMask; - } - } - z.high &= ~ roundBitsMask; - } - if ( ( z.low != a.low ) || ( z.high != a.high ) ) { - float_exception_flags |= float_flag_inexact; - } - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. The -| addition is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - int32 expDiff; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - return a; - } - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); - zSig2 = 0; - zSig0 |= LIT64( 0x0002000000000000 ); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= LIT64( 0x0001000000000000 ); - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - --zExp; - if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; - ++zExp; - shiftRight1: - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - roundAndPack: - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - int32 expDiff; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig0 < aSig0 ) goto aBigger; - if ( aSig0 < bSig0 ) goto bBigger; - if ( bSig1 < aSig1 ) goto aBigger; - if ( aSig1 < bSig1 ) goto bBigger; - return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - bSig0 |= LIT64( 0x4000000000000000 ); - bBigger: - sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); - aSig0 |= LIT64( 0x4000000000000000 ); - aBigger: - sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEEE Standard for -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_add( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return addFloat128Sigs( a, b, aSign ); - } - else { - return subFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sub( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return subFloat128Sigs( a, b, aSign ); - } - else { - return addFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_mul( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= LIT64( 0x0001000000000000 ); - shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); - mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); - add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zSig2 |= ( zSig3 != 0 ); - if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - ++zExp; - } - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_div( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - goto invalid; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0, 0, 0 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { - shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); - mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); - sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); - } - zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); - if ( ( zSig1 & 0x3FFF ) <= 4 ) { - mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); - sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the quadruple-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_rem( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; - bits64 allZero, alternateASig0, alternateASig1, sigMean1; - sbits64 sigMean0; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return a; - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - expDiff = aExp - bExp; - if ( expDiff < -1 ) return a; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), - aSig1, - 15 - ( expDiff < 0 ), - &aSig0, - &aSig1 - ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - q = le128( bSig0, bSig1, aSig0, aSig1 ); - if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero ); - shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero ); - sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 ); - expDiff -= 61; - } - if ( -64 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - q >>= - expDiff; - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - expDiff += 52; - if ( expDiff < 0 ) { - shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - } - else { - shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 ); - } - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 ); - } - else { - shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 ); - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - } - do { - alternateASig0 = aSig0; - alternateASig1 = aSig1; - ++q; - sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - } while ( 0 <= (sbits64) aSig0 ); - add128( - aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 ); - if ( ( sigMean0 < 0 ) - || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - } - zSign = ( (sbits64) aSig0 < 0 ); - if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 ); - return - normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the quadruple-precision floating-point value `a'. -| The operation is performed according to the IEEE Standard for Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sqrt( float128 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; - aSig0 |= LIT64( 0x0001000000000000 ); - zSig0 = estimateSqrt32( aExp, aSig0>>17 ); - shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & 0x1FFF ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq( float128 a, float128 b ) -{ - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq_signaling( float128 a, float128 b ) -{ - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEEE Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEEE -| Standard for Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif - -float float32_to_c_float(float32 a){ - return *((float*)(&a)); -} -double float64_to_c_double(float64 a){ - return *((double*)(&a)); -} -float32 c_float_to_float32(float a){ - return *((float32*)(&a)); -} -float64 c_double_to_float64(double a){ - return *((float64*)(&a)); -} - -#ifdef FLOATX80 -float floatx80_to_c_float(floatx80 a){ - return float32_to_c_float(floatx80_to_float32(a)); -} -double floatx80_to_c_double(floatx80 a){ - return float64_to_c_double(floatx80_to_float64(a)); -} -floatx80 c_float_to_floatx80(float a){ - return float32_to_floatx80(c_float_to_float32(a)); -} -floatx80 c_double_to_floatx80(double a){ - return float64_to_floatx80(c_double_to_float64(a)); -} -#endif - -#endif + +/*============================================================================ + +This C source file is part of the Berkeley SoftFloat IEEE Floating-Point +Arithmetic Package, Release 2c, by John R. Hauser. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER +PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR +THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY +INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE +(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER +PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR +INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE +SOFTWARE. + +Derivative works require also that (1) the source code for the derivative work +includes prominent notice that the work is derivative, and (2) the source code +includes prominent notice of these three paragraphs for those parts of this +code that are retained. + +=============================================================================*/ + +#include "compiler.h" + +#ifdef SUPPORT_FPU_SOFTFLOAT + +#include "softfloatdef.h" +//#include "milieu.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Floating-point rounding mode, double-extended-precision rounding precision, +| and exception flags. +*----------------------------------------------------------------------------*/ +int8 float_rounding_mode = float_round_nearest_even; +int8 float_exception_flags = 0; +#ifdef FLOATX80 +int8 floatx80_rounding_precision = 80; +#endif + +/*---------------------------------------------------------------------------- +| Primitive arithmetic functions, including multi-word arithmetic, and +| division and square root approximations. (Can be specialized to target if +| desired.) +*----------------------------------------------------------------------------*/ +#include "softfloat-macros.h" // rename softfloat-macros -> softfloat-macros.h + +/*---------------------------------------------------------------------------- +| Functions and definitions to determine: (1) whether tininess for underflow +| is detected before or after rounding by default, (2) what (if anything) +| happens when exceptions are raised, (3) how signaling NaNs are distinguished +| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs +| are propagated from function inputs to output. These details are target- +| specific. +*----------------------------------------------------------------------------*/ +#include "softfloat-specialize.h" // rename softfloat-specialize -> softfloat-specialize.h + +// for np2 FPU by SimK 2025/10/25 +/*---------------------------------------------------------------------------- +| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 +| and 7, and returns the properly rounded 16-bit integer corresponding to the +| input. If `zSign' is 1, the input is negated before being converted to an +| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input +| is simply rounded to an integer, with the inexact exception raised if the +| input cannot be represented exactly as an integer. However, if the fixed- +| point input is too large, the invalid exception is raised and the largest +| negative integer is returned. +*----------------------------------------------------------------------------*/ + +static int16 roundAndPackInt16_np2(flag zSign, bits64 absZ) +{ + int8 roundingMode; + flag roundNearestEven; + int8 roundIncrement, roundBits; + int16 z; + + roundingMode = float_rounding_mode; + roundNearestEven = (roundingMode == float_round_nearest_even); + roundIncrement = 0x40; + if (!roundNearestEven) { + if (roundingMode == float_round_to_zero) { + roundIncrement = 0; + } + else { + roundIncrement = 0x7F; + if (zSign) { + if (roundingMode == float_round_up) roundIncrement = 0; + } + else { + if (roundingMode == float_round_down) roundIncrement = 0; + } + } + } + roundBits = absZ & 0x7F; + absZ = (absZ + roundIncrement) >> 7; + absZ &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); + z = absZ; + if (zSign) z = -z; + z = (sbits16)z; + if ((absZ >> 16) || (z && ((z < 0) ^ zSign))) { + float_raise(float_flag_invalid); + return (sbits16)0x8000; // for np2 by SimK 2025/10/25 + } + if (roundBits) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 +| and 7, and returns the properly rounded 32-bit integer corresponding to the +| input. If `zSign' is 1, the input is negated before being converted to an +| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input +| is simply rounded to an integer, with the inexact exception raised if the +| input cannot be represented exactly as an integer. However, if the fixed- +| point input is too large, the invalid exception is raised and the largest +| negative integer is returned. +*----------------------------------------------------------------------------*/ + +static int32 roundAndPackInt32_np2(flag zSign, bits64 absZ) +{ + int8 roundingMode; + flag roundNearestEven; + int8 roundIncrement, roundBits; + int32 z; + + roundingMode = float_rounding_mode; + roundNearestEven = (roundingMode == float_round_nearest_even); + roundIncrement = 0x40; + if (!roundNearestEven) { + if (roundingMode == float_round_to_zero) { + roundIncrement = 0; + } + else { + roundIncrement = 0x7F; + if (zSign) { + if (roundingMode == float_round_up) roundIncrement = 0; + } + else { + if (roundingMode == float_round_down) roundIncrement = 0; + } + } + } + roundBits = absZ & 0x7F; + absZ = (absZ + roundIncrement) >> 7; + absZ &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); + z = absZ; + if (zSign) z = -z; + z = (sbits32)z; + if ((absZ >> 32) || (z && ((z < 0) ^ zSign))) { + float_raise(float_flag_invalid); + return 0x80000000; // for np2 by SimK 2025/10/25 + } + if (roundBits) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and +| `absZ1', with binary point between bits 63 and 64 (between the input words), +| and returns the properly rounded 64-bit integer corresponding to the input. +| If `zSign' is 1, the input is negated before being converted to an integer. +| Ordinarily, the fixed-point input is simply rounded to an integer, with +| the inexact exception raised if the input cannot be represented exactly as +| an integer. However, if the fixed-point input is too large, the invalid +| exception is raised and the largest negative integer is returned. +*----------------------------------------------------------------------------*/ + +static int64 roundAndPackInt64_np2(flag zSign, bits64 absZ0, bits64 absZ1) +{ + int8 roundingMode; + flag roundNearestEven, increment; + int64 z; + + roundingMode = float_rounding_mode; + roundNearestEven = (roundingMode == float_round_nearest_even); + increment = ((sbits64)absZ1 < 0); + if (!roundNearestEven) { + if (roundingMode == float_round_to_zero) { + increment = 0; + } + else { + if (zSign) { + increment = (roundingMode == float_round_down) && absZ1; + } + else { + increment = (roundingMode == float_round_up) && absZ1; + } + } + } + if (increment) { + ++absZ0; + if (absZ0 == 0) goto overflow; + absZ0 &= ~(((bits64)(absZ1 << 1) == 0) & roundNearestEven); + } + z = absZ0; + if (zSign) z = -z; + z = (sbits64)z; + if (z && ((z < 0) ^ zSign)) { + overflow: + float_raise(float_flag_invalid); + return LIT64(0x8000000000000000); // for np2 by SimK 2025/10/25 + } + if (absZ1) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 +| and 7, and returns the properly rounded 32-bit integer corresponding to the +| input. If `zSign' is 1, the input is negated before being converted to an +| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input +| is simply rounded to an integer, with the inexact exception raised if the +| input cannot be represented exactly as an integer. However, if the fixed- +| point input is too large, the invalid exception is raised and the largest +| positive or negative integer is returned. +*----------------------------------------------------------------------------*/ + +static int32 roundAndPackInt32( flag zSign, bits64 absZ ) +{ + int8 roundingMode; + flag roundNearestEven; + int8 roundIncrement, roundBits; + int32 z; + + roundingMode = float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); + roundIncrement = 0x40; + if ( ! roundNearestEven ) { + if ( roundingMode == float_round_to_zero ) { + roundIncrement = 0; + } + else { + roundIncrement = 0x7F; + if ( zSign ) { + if ( roundingMode == float_round_up ) roundIncrement = 0; + } + else { + if ( roundingMode == float_round_down ) roundIncrement = 0; + } + } + } + roundBits = absZ & 0x7F; + absZ = ( absZ + roundIncrement )>>7; + absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); + z = absZ; + if ( zSign ) z = - z; + z = (sbits32) z; + if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { + float_raise( float_flag_invalid ); + return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( roundBits ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and +| `absZ1', with binary point between bits 63 and 64 (between the input words), +| and returns the properly rounded 64-bit integer corresponding to the input. +| If `zSign' is 1, the input is negated before being converted to an integer. +| Ordinarily, the fixed-point input is simply rounded to an integer, with +| the inexact exception raised if the input cannot be represented exactly as +| an integer. However, if the fixed-point input is too large, the invalid +| exception is raised and the largest positive or negative integer is +| returned. +*----------------------------------------------------------------------------*/ + +static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 ) +{ + int8 roundingMode; + flag roundNearestEven, increment; + int64 z; + + roundingMode = float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); + increment = ( (sbits64) absZ1 < 0 ); + if ( ! roundNearestEven ) { + if ( roundingMode == float_round_to_zero ) { + increment = 0; + } + else { + if ( zSign ) { + increment = ( roundingMode == float_round_down ) && absZ1; + } + else { + increment = ( roundingMode == float_round_up ) && absZ1; + } + } + } + if ( increment ) { + ++absZ0; + if ( absZ0 == 0 ) goto overflow; + absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven ); + } + z = absZ0; + if ( zSign ) z = - z; + z = (sbits64) z; + if ( z && ( ( z < 0 ) ^ zSign ) ) { + overflow: + float_raise( float_flag_invalid ); + return + zSign ? (sbits64) LIT64( 0x8000000000000000 ) + : LIT64( 0x7FFFFFFFFFFFFFFF ); + } + if ( absZ1 ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the fraction bits of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +INLINE bits32 extractFloat32Frac( float32 a ) +{ + + return a & 0x007FFFFF; + +} + +/*---------------------------------------------------------------------------- +| Returns the exponent bits of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +INLINE int16 extractFloat32Exp( float32 a ) +{ + + return ( a>>23 ) & 0xFF; + +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +INLINE flag extractFloat32Sign( float32 a ) +{ + + return a>>31; + +} + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal single-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +static void + normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros32( aSig ) - 8; + *zSigPtr = aSig<>7; + zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); + if ( zSig == 0 ) zExp = 0; + return packFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper single-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat32' except that `zSig' does not have to be normalized. +| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the "true" +| floating-point exponent. +*----------------------------------------------------------------------------*/ + +static float32 + normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros32( zSig ) - 1; + return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<>52 ) & 0x7FF; + +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the double-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +INLINE flag extractFloat64Sign( float64 a ) +{ + + return a>>63; + +} + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal double-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +static void + normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros64( aSig ) - 11; + *zSigPtr = aSig<>10; + zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); + if ( zSig == 0 ) zExp = 0; + return packFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper double-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat64' except that `zSig' does not have to be normalized. +| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the "true" +| floating-point exponent. +*----------------------------------------------------------------------------*/ + +static float64 + normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros64( zSig ) - 1; + return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<>15; + +} + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal double-extended-precision floating-point value +| represented by the denormalized significand `aSig'. The normalized exponent +| and significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +static void + normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros64( aSig ); + *zSigPtr = aSig<>48 ) & 0x7FFF; + +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the quadruple-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +INLINE flag extractFloat128Sign( float128 a ) +{ + + return a.high>>63; + +} + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal quadruple-precision floating-point value +| represented by the denormalized significand formed by the concatenation of +| `aSig0' and `aSig1'. The normalized exponent is stored at the location +| pointed to by `zExpPtr'. The most significant 49 bits of the normalized +| significand are stored at the location pointed to by `zSig0Ptr', and the +| least significant 64 bits of the normalized significand are stored at the +| location pointed to by `zSig1Ptr'. +*----------------------------------------------------------------------------*/ + +static void + normalizeFloat128Subnormal( + bits64 aSig0, + bits64 aSig1, + int32 *zExpPtr, + bits64 *zSig0Ptr, + bits64 *zSig1Ptr + ) +{ + int8 shiftCount; + + if ( aSig0 == 0 ) { + shiftCount = countLeadingZeros64( aSig1 ) - 15; + if ( shiftCount < 0 ) { + *zSig0Ptr = aSig1>>( - shiftCount ); + *zSig1Ptr = aSig1<<( shiftCount & 63 ); + } + else { + *zSig0Ptr = aSig1<>( - shiftCount ); + if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 64-bit two's complement integer format. The conversion is +| performed according to the IEEE Standard for Floating-Point Arithmetic--- +| which means in particular that the conversion is rounded according to the +| current rounding mode. If `a' is a NaN, the largest positive integer is +| returned. Otherwise, if the conversion overflows, the largest integer with +| the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int64 float32_to_int64( float32 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits32 aSig; + bits64 aSig64, aSigExtra; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + shiftCount = 0xBE - aExp; + if ( shiftCount < 0 ) { + float_raise( float_flag_invalid ); + if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { + return LIT64( 0x7FFFFFFFFFFFFFFF ); + } + return (sbits64) LIT64( 0x8000000000000000 ); + } + if ( aExp ) aSig |= 0x00800000; + aSig64 = aSig; + aSig64 <<= 40; + shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra ); + return roundAndPackInt64( aSign, aSig64, aSigExtra ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 64-bit two's complement integer format. The conversion is +| performed according to the IEEE Standard for Floating-Point Arithmetic, +| except that the conversion is always rounded toward zero. If `a' is a NaN, +| the largest positive integer is returned. Otherwise, if the conversion +| overflows, the largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int64 float32_to_int64_round_to_zero( float32 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits32 aSig; + bits64 aSig64; + int64 z; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + shiftCount = aExp - 0xBE; + if ( 0 <= shiftCount ) { + if ( a != 0xDF000000 ) { + float_raise( float_flag_invalid ); + if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { + return LIT64( 0x7FFFFFFFFFFFFFFF ); + } + } + return (sbits64) LIT64( 0x8000000000000000 ); + } + else if ( aExp <= 0x7E ) { + if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; + return 0; + } + aSig64 = aSig | 0x00800000; + aSig64 <<= 40; + z = aSig64>>( - shiftCount ); + if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the double-precision floating-point format. The conversion is +| performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float32_to_float64( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 aSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) ); + return packFloat64( aSign, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + --aExp; + } + return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 ); + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the double-extended-precision floating-point format. The conversion +| is performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 float32_to_floatx80( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 aSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); + return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + aSig |= 0x00800000; + return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 ); + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the double-precision floating-point format. The conversion is +| performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float32_to_float128( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 aSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a ) ); + return packFloat128( aSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + --aExp; + } + return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the single-precision floating-point value `a' to an integer, +| and returns the result as a single-precision floating-point value. The +| operation is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_round_to_int( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 lastBitMask, roundBitsMask; + int8 roundingMode; + float32 z; + + aExp = extractFloat32Exp( a ); + if ( 0x96 <= aExp ) { + if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { + return propagateFloat32NaN( a, a ); + } + return a; + } + if ( aExp <= 0x7E ) { + if ( (bits32) ( a<<1 ) == 0 ) return a; + float_exception_flags |= float_flag_inexact; + aSign = extractFloat32Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { + return packFloat32( aSign, 0x7F, 0 ); + } + break; + case float_round_down: + return aSign ? 0xBF800000 : 0; + case float_round_up: + return aSign ? 0x80000000 : 0x3F800000; + } + return packFloat32( aSign, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x96 - aExp; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z += lastBitMask>>1; + if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) { + z += roundBitsMask; + } + } + z &= ~ roundBitsMask; + if ( z != a ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the single-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. The +| addition is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + expDiff = aExp - bExp; + aSig <<= 6; + bSig <<= 6; + if ( 0 < expDiff ) { + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= 0x20000000; + } + shift32RightJamming( bSig, expDiff, &bSig ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return packFloat32( zSign, 0xFF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= 0x20000000; + } + shift32RightJamming( aSig, - expDiff, &aSig ); + zExp = bExp; + } + else { + if ( aExp == 0xFF ) { + if ( aSig | bSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); + zSig = 0x40000000 + aSig + bSig; + zExp = aExp; + goto roundAndPack; + } + aSig |= 0x20000000; + zSig = ( aSig + bSig )<<1; + --zExp; + if ( (sbits32) zSig < 0 ) { + zSig = aSig + bSig; + ++zExp; + } + roundAndPack: + return roundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the single- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + expDiff = aExp - bExp; + aSig <<= 7; + bSig <<= 7; + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0xFF ) { + if ( aSig | bSig ) return propagateFloat32NaN( a, b ); + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + if ( bSig < aSig ) goto aBigger; + if ( aSig < bSig ) goto bBigger; + return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); + bExpBigger: + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return packFloat32( zSign ^ 1, 0xFF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= 0x40000000; + } + shift32RightJamming( aSig, - expDiff, &aSig ); + bSig |= 0x40000000; + bBigger: + zSig = bSig - aSig; + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= 0x40000000; + } + shift32RightJamming( bSig, expDiff, &bSig ); + aSig |= 0x40000000; + aBigger: + zSig = aSig - bSig; + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the single-precision floating-point values +| `a' and `b'. The operation is performed according to the IEEE Standard for +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_add( float32 a, float32 b ) +{ + flag aSign, bSign; + + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign == bSign ) { + return addFloat32Sigs( a, b, aSign ); + } + else { + return subFloat32Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the single-precision floating-point values +| `a' and `b'. The operation is performed according to the IEEE Standard for +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_sub( float32 a, float32 b ) +{ + flag aSign, bSign; + + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign == bSign ) { + return subFloat32Sigs( a, b, aSign ); + } + else { + return addFloat32Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the single-precision floating-point values +| `a' and `b'. The operation is performed according to the IEEE Standard for +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_mul( float32 a, float32 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits32 aSig, bSig; + bits64 zSig64; + bits32 zSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + bSign = extractFloat32Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0xFF ) { + if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { + return propagateFloat32NaN( a, b ); + } + if ( ( bExp | bSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + return packFloat32( zSign, 0xFF, 0 ); + } + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + return packFloat32( zSign, 0xFF, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); + normalizeFloat32Subnormal( bSig, &bExp, &bSig ); + } + zExp = aExp + bExp - 0x7F; + aSig = ( aSig | 0x00800000 )<<7; + bSig = ( bSig | 0x00800000 )<<8; + shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 ); + zSig = zSig64; + if ( 0 <= (sbits32) ( zSig<<1 ) ) { + zSig <<= 1; + --zExp; + } + return roundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the single-precision floating-point value `a' +| by the corresponding value `b'. The operation is performed according to the +| IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_div( float32 a, float32 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + bSign = extractFloat32Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, b ); + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + float_raise( float_flag_invalid ); + return float32_default_nan; + } + return packFloat32( zSign, 0xFF, 0 ); + } + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return packFloat32( zSign, 0, 0 ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + float_raise( float_flag_divbyzero ); + return packFloat32( zSign, 0xFF, 0 ); + } + normalizeFloat32Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + zExp = aExp - bExp + 0x7D; + aSig = ( aSig | 0x00800000 )<<7; + bSig = ( bSig | 0x00800000 )<<8; + if ( bSig <= ( aSig + aSig ) ) { + aSig >>= 1; + ++zExp; + } + zSig = ( ( (bits64) aSig )<<32 ) / bSig; + if ( ( zSig & 0x3F ) == 0 ) { + zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 ); + } + return roundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the single-precision floating-point value `a' +| with respect to the corresponding value `b'. The operation is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_rem( float32 a, float32 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, expDiff; + bits32 aSig, bSig; + bits32 q; + bits64 aSig64, bSig64, q64; + bits32 alternateASig; + sbits32 sigMean; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + bSign = extractFloat32Sign( b ); + if ( aExp == 0xFF ) { + if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { + return propagateFloat32NaN( a, b ); + } + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + normalizeFloat32Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return a; + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + expDiff = aExp - bExp; + aSig |= 0x00800000; + bSig |= 0x00800000; + if ( expDiff < 32 ) { + aSig <<= 8; + bSig <<= 8; + if ( expDiff < 0 ) { + if ( expDiff < -1 ) return a; + aSig >>= 1; + } + q = ( bSig <= aSig ); + if ( q ) aSig -= bSig; + if ( 0 < expDiff ) { + q = ( ( (bits64) aSig )<<32 ) / bSig; + q >>= 32 - expDiff; + bSig >>= 2; + aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; + } + else { + aSig >>= 2; + bSig >>= 2; + } + } + else { + if ( bSig <= aSig ) aSig -= bSig; + aSig64 = ( (bits64) aSig )<<40; + bSig64 = ( (bits64) bSig )<<40; + expDiff -= 64; + while ( 0 < expDiff ) { + q64 = estimateDiv128To64( aSig64, 0, bSig64 ); + q64 = ( 2 < q64 ) ? q64 - 2 : 0; + aSig64 = - ( ( bSig * q64 )<<38 ); + expDiff -= 62; + } + expDiff += 64; + q64 = estimateDiv128To64( aSig64, 0, bSig64 ); + q64 = ( 2 < q64 ) ? q64 - 2 : 0; + q = q64>>( 64 - expDiff ); + bSig <<= 6; + aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q; + } + do { + alternateASig = aSig; + ++q; + aSig -= bSig; + } while ( 0 <= (sbits32) aSig ); + sigMean = aSig + alternateASig; + if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { + aSig = alternateASig; + } + zSign = ( (sbits32) aSig < 0 ); + if ( zSign ) aSig = - aSig; + return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the single-precision floating-point value `a'. +| The operation is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_sqrt( float32 a ) +{ + flag aSign; + int16 aExp, zExp; + bits32 aSig, zSig; + bits64 rem, term; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, 0 ); + if ( ! aSign ) return a; + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( aSign ) { + if ( ( aExp | aSig ) == 0 ) return a; + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return 0; + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; + aSig = ( aSig | 0x00800000 )<<8; + zSig = estimateSqrt32( aExp, aSig ) + 2; + if ( ( zSig & 0x7F ) <= 5 ) { + if ( zSig < 2 ) { + zSig = 0x7FFFFFFF; + goto roundAndPack; + } + aSig >>= aExp & 1; + term = ( (bits64) zSig ) * zSig; + rem = ( ( (bits64) aSig )<<32 ) - term; + while ( (sbits64) rem < 0 ) { + --zSig; + rem += ( ( (bits64) zSig )<<1 ) | 1; + } + zSig |= ( rem != 0 ); + } + shift32RightJamming( zSig, 1, &zSig ); + roundAndPack: + return roundAndPackFloat32( 0, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_eq( float32 a, float32 b ) +{ + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than +| or equal to the corresponding value `b', and 0 otherwise. The comparison +| is performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_le( float32 a, float32 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_lt( float32 a, float32 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The invalid exception is +| raised if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_eq_signaling( float32 a, float32 b ) +{ + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than or +| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +| cause an exception. Otherwise, the comparison is performed according to the +| IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_le_quiet( float32 a, float32 b ) +{ + flag aSign, bSign; + int16 aExp, bExp; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +| exception. Otherwise, the comparison is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_lt_quiet( float32 a, float32 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the 32-bit two's complement integer format. The conversion is +| performed according to the IEEE Standard for Floating-Point Arithmetic--- +| which means in particular that the conversion is rounded according to the +| current rounding mode. If `a' is a NaN, the largest positive integer is +| returned. Otherwise, if the conversion overflows, the largest integer with +| the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 float64_to_int32( float64 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits64 aSig; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; + if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); + shiftCount = 0x42C - aExp; + if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); + return roundAndPackInt32( aSign, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the 32-bit two's complement integer format. The conversion is +| performed according to the IEEE Standard for Floating-Point Arithmetic, +| except that the conversion is always rounded toward zero. If `a' is a NaN, +| the largest positive integer is returned. Otherwise, if the conversion +| overflows, the largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 float64_to_int32_round_to_zero( float64 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits64 aSig, savedASig; + int32 z; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( 0x41E < aExp ) { + if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; + goto invalid; + } + else if ( aExp < 0x3FF ) { + if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; + return 0; + } + aSig |= LIT64( 0x0010000000000000 ); + shiftCount = 0x433 - aExp; + savedASig = aSig; + aSig >>= shiftCount; + z = aSig; + if ( aSign ) z = - z; + z = (sbits32) z; + if ( ( z < 0 ) ^ aSign ) { + invalid: + float_raise( float_flag_invalid ); + return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( ( aSig<>( - shiftCount ); + if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the single-precision floating-point format. The conversion is +| performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float64_to_float32( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig; + bits32 zSig; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) ); + return packFloat32( aSign, 0xFF, 0 ); + } + shift64RightJamming( aSig, 22, &aSig ); + zSig = aSig; + if ( aExp || zSig ) { + zSig |= 0x40000000; + aExp -= 0x381; + } + return roundAndPackFloat32( aSign, aExp, zSig ); + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the double-extended-precision floating-point format. The conversion +| is performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 float64_to_floatx80( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) ); + return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + return + packFloatx80( + aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the quadruple-precision floating-point format. The conversion is +| performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float64_to_float128( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig, zSig0, zSig1; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a ) ); + return packFloat128( aSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + --aExp; + } + shift128Right( aSig, 0, 4, &zSig0, &zSig1 ); + return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the double-precision floating-point value `a' to an integer, +| and returns the result as a double-precision floating-point value. The +| operation is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_round_to_int( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 lastBitMask, roundBitsMask; + int8 roundingMode; + float64 z; + + aExp = extractFloat64Exp( a ); + if ( 0x433 <= aExp ) { + if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { + return propagateFloat64NaN( a, a ); + } + return a; + } + if ( aExp < 0x3FF ) { + if ( (bits64) ( a<<1 ) == 0 ) return a; + float_exception_flags |= float_flag_inexact; + aSign = extractFloat64Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { + return packFloat64( aSign, 0x3FF, 0 ); + } + break; + case float_round_down: + return aSign ? LIT64( 0xBFF0000000000000 ) : 0; + case float_round_up: + return + aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ); + } + return packFloat64( aSign, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x433 - aExp; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z += lastBitMask>>1; + if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) { + z += roundBitsMask; + } + } + z &= ~ roundBitsMask; + if ( z != a ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the double-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. The +| addition is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + expDiff = aExp - bExp; + aSig <<= 9; + bSig <<= 9; + if ( 0 < expDiff ) { + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= LIT64( 0x2000000000000000 ); + } + shift64RightJamming( bSig, expDiff, &bSig ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= LIT64( 0x2000000000000000 ); + } + shift64RightJamming( aSig, - expDiff, &aSig ); + zExp = bExp; + } + else { + if ( aExp == 0x7FF ) { + if ( aSig | bSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); + zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; + zExp = aExp; + goto roundAndPack; + } + aSig |= LIT64( 0x2000000000000000 ); + zSig = ( aSig + bSig )<<1; + --zExp; + if ( (sbits64) zSig < 0 ) { + zSig = aSig + bSig; + ++zExp; + } + roundAndPack: + return roundAndPackFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the double- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + expDiff = aExp - bExp; + aSig <<= 10; + bSig <<= 10; + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0x7FF ) { + if ( aSig | bSig ) return propagateFloat64NaN( a, b ); + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + if ( bSig < aSig ) goto aBigger; + if ( aSig < bSig ) goto bBigger; + return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); + bExpBigger: + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return packFloat64( zSign ^ 1, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= LIT64( 0x4000000000000000 ); + } + shift64RightJamming( aSig, - expDiff, &aSig ); + bSig |= LIT64( 0x4000000000000000 ); + bBigger: + zSig = bSig - aSig; + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= LIT64( 0x4000000000000000 ); + } + shift64RightJamming( bSig, expDiff, &bSig ); + aSig |= LIT64( 0x4000000000000000 ); + aBigger: + zSig = aSig - bSig; + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the double-precision floating-point values +| `a' and `b'. The operation is performed according to the IEEE Standard for +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_add( float64 a, float64 b ) +{ + flag aSign, bSign; + + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign == bSign ) { + return addFloat64Sigs( a, b, aSign ); + } + else { + return subFloat64Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the double-precision floating-point values +| `a' and `b'. The operation is performed according to the IEEE Standard for +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_sub( float64 a, float64 b ) +{ + flag aSign, bSign; + + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign == bSign ) { + return subFloat64Sigs( a, b, aSign ); + } + else { + return addFloat64Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the double-precision floating-point values +| `a' and `b'. The operation is performed according to the IEEE Standard for +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_mul( float64 a, float64 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + bSign = extractFloat64Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FF ) { + if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { + return propagateFloat64NaN( a, b ); + } + if ( ( bExp | bSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); + normalizeFloat64Subnormal( bSig, &bExp, &bSig ); + } + zExp = aExp + bExp - 0x3FF; + aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; + bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; + mul64To128( aSig, bSig, &zSig0, &zSig1 ); + zSig0 |= ( zSig1 != 0 ); + if ( 0 <= (sbits64) ( zSig0<<1 ) ) { + zSig0 <<= 1; + --zExp; + } + return roundAndPackFloat64( zSign, zExp, zSig0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the double-precision floating-point value `a' +| by the corresponding value `b'. The operation is performed according to the +| IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_div( float64 a, float64 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + bits64 rem0, rem1; + bits64 term0, term1; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + bSign = extractFloat64Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, b ); + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + float_raise( float_flag_invalid ); + return float64_default_nan; + } + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return packFloat64( zSign, 0, 0 ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + float_raise( float_flag_divbyzero ); + return packFloat64( zSign, 0x7FF, 0 ); + } + normalizeFloat64Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + zExp = aExp - bExp + 0x3FD; + aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; + bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; + if ( bSig <= ( aSig + aSig ) ) { + aSig >>= 1; + ++zExp; + } + zSig = estimateDiv128To64( aSig, 0, bSig ); + if ( ( zSig & 0x1FF ) <= 2 ) { + mul64To128( bSig, zSig, &term0, &term1 ); + sub128( aSig, 0, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig; + add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); + } + zSig |= ( rem1 != 0 ); + } + return roundAndPackFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the double-precision floating-point value `a' +| with respect to the corresponding value `b'. The operation is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_rem( float64 a, float64 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, expDiff; + bits64 aSig, bSig; + bits64 q, alternateASig; + sbits64 sigMean; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + bSign = extractFloat64Sign( b ); + if ( aExp == 0x7FF ) { + if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { + return propagateFloat64NaN( a, b ); + } + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + normalizeFloat64Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return a; + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + expDiff = aExp - bExp; + aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; + bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; + if ( expDiff < 0 ) { + if ( expDiff < -1 ) return a; + aSig >>= 1; + } + q = ( bSig <= aSig ); + if ( q ) aSig -= bSig; + expDiff -= 64; + while ( 0 < expDiff ) { + q = estimateDiv128To64( aSig, 0, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + aSig = - ( ( bSig>>2 ) * q ); + expDiff -= 62; + } + expDiff += 64; + if ( 0 < expDiff ) { + q = estimateDiv128To64( aSig, 0, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + q >>= 64 - expDiff; + bSig >>= 2; + aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; + } + else { + aSig >>= 2; + bSig >>= 2; + } + do { + alternateASig = aSig; + ++q; + aSig -= bSig; + } while ( 0 <= (sbits64) aSig ); + sigMean = aSig + alternateASig; + if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { + aSig = alternateASig; + } + zSign = ( (sbits64) aSig < 0 ); + if ( zSign ) aSig = - aSig; + return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the double-precision floating-point value `a'. +| The operation is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_sqrt( float64 a ) +{ + flag aSign; + int16 aExp, zExp; + bits64 aSig, zSig, doubleZSig; + bits64 rem0, rem1, term0, term1; + float64 z; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, a ); + if ( ! aSign ) return a; + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( aSign ) { + if ( ( aExp | aSig ) == 0 ) return a; + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return 0; + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; + aSig |= LIT64( 0x0010000000000000 ); + zSig = estimateSqrt32( aExp, aSig>>21 ); + aSig <<= 9 - ( aExp & 1 ); + zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 ); + if ( ( zSig & 0x1FF ) <= 5 ) { + doubleZSig = zSig<<1; + mul64To128( zSig, zSig, &term0, &term1 ); + sub128( aSig, 0, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig; + doubleZSig -= 2; + add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 ); + } + zSig |= ( ( rem0 | rem1 ) != 0 ); + } + return roundAndPackFloat64( 0, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is equal to the +| corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_eq( float64 a, float64 b ) +{ + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than or +| equal to the corresponding value `b', and 0 otherwise. The comparison is +| performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_le( float64 a, float64 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_lt( float64 a, float64 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The invalid exception is +| raised if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_eq_signaling( float64 a, float64 b ) +{ + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than or +| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +| cause an exception. Otherwise, the comparison is performed according to the +| IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_le_quiet( float64 a, float64 b ) +{ + flag aSign, bSign; + int16 aExp, bExp; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +| exception. Otherwise, the comparison is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_lt_quiet( float64 a, float64 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +#ifdef FLOATX80 + +// for np2 FPU by SimK 2025/10/25 +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-extended-precision floating- +| point value `a' to the 16-bit two's complement integer format. The +| conversion is performed according to the IEEE Standard for Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN or the conversion +| overflows, the largest negative integer is returned. +*----------------------------------------------------------------------------*/ + +int16 floatx80_to_int16_np2(floatx80 a) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + if ((aExp == 0x7FFF) && (bits64)(aSig << 1)) aSign = 0; + shiftCount = 0x4037 - aExp; + if (shiftCount <= 0) shiftCount = 1; + shift64RightJamming(aSig, shiftCount, &aSig); + return roundAndPackInt16_np2(aSign, aSig); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-extended-precision floating- +| point value `a' to the 32-bit two's complement integer format. The +| conversion is performed according to the IEEE Standard for Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN or the conversion +| overflows, the largest negative integer is returned. +*----------------------------------------------------------------------------*/ + +int32 floatx80_to_int32_np2(floatx80 a) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + if ((aExp == 0x7FFF) && (bits64)(aSig << 1)) aSign = 0; + shiftCount = 0x4037 - aExp; + if (shiftCount <= 0) shiftCount = 1; + shift64RightJamming(aSig, shiftCount, &aSig); + return roundAndPackInt32_np2(aSign, aSig); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-extended-precision floating- +| point value `a' to the 64-bit two's complement integer format. The +| conversion is performed according to the IEEE Standard for Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN or the conversion +| overflows, the largest negative integer is returned. +*----------------------------------------------------------------------------*/ + +int64 floatx80_to_int64_np2(floatx80 a) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig, aSigExtra; + + aSig = extractFloatx80Frac(a); + aExp = extractFloatx80Exp(a); + aSign = extractFloatx80Sign(a); + shiftCount = 0x403E - aExp; + if (shiftCount <= 0) { + if (shiftCount) { + float_raise(float_flag_invalid); + return (sbits64)LIT64(0x8000000000000000); + } + aSigExtra = 0; + } + else { + shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra); + } + return roundAndPackInt64_np2(aSign, aSig, aSigExtra); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-extended-precision floating- +| point value `a' to the 32-bit two's complement integer format. The +| conversion is performed according to the IEEE Standard for Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN, the largest +| positive integer is returned. Otherwise, if the conversion overflows, the +| largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 floatx80_to_int32( floatx80 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; + shiftCount = 0x4037 - aExp; + if ( shiftCount <= 0 ) shiftCount = 1; + shift64RightJamming( aSig, shiftCount, &aSig ); + return roundAndPackInt32( aSign, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-extended-precision floating- +| point value `a' to the 32-bit two's complement integer format. The +| conversion is performed according to the IEEE Standard for Floating-Point +| Arithmetic, except that the conversion is always rounded toward zero. +| If `a' is a NaN, the largest positive integer is returned. Otherwise, if +| the conversion overflows, the largest integer with the same sign as `a' is +| returned. +*----------------------------------------------------------------------------*/ + +int32 floatx80_to_int32_round_to_zero( floatx80 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig, savedASig; + int32 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( 0x401E < aExp ) { + if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; + goto invalid; + } + else if ( aExp < 0x3FFF ) { + if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; + return 0; + } + shiftCount = 0x403E - aExp; + savedASig = aSig; + aSig >>= shiftCount; + z = aSig; + if ( aSign ) z = - z; + z = (sbits32) z; + if ( ( z < 0 ) ^ aSign ) { + invalid: + float_raise( float_flag_invalid ); + return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( ( aSig<>( - shiftCount ); + if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-extended-precision floating- +| point value `a' to the single-precision floating-point format. The +| conversion is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 floatx80_to_float32( floatx80 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) { + return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); + } + return packFloat32( aSign, 0xFF, 0 ); + } + shift64RightJamming( aSig, 33, &aSig ); + if ( aExp || aSig ) aExp -= 0x3F81; + return roundAndPackFloat32( aSign, aExp, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-extended-precision floating- +| point value `a' to the double-precision floating-point format. The +| conversion is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 floatx80_to_float64( floatx80 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig, zSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) { + return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); + } + return packFloat64( aSign, 0x7FF, 0 ); + } + shift64RightJamming( aSig, 1, &zSig ); + if ( aExp || aSig ) aExp -= 0x3C01; + return roundAndPackFloat64( aSign, aExp, zSig ); + +} + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-extended-precision floating- +| point value `a' to the quadruple-precision floating-point format. The +| conversion is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 floatx80_to_float128( floatx80 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig, zSig0, zSig1; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { + return commonNaNToFloat128( floatx80ToCommonNaN( a ) ); + } + shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); + return packFloat128( aSign, aExp, zSig0, zSig1 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the double-extended-precision floating-point value `a' to an integer, +| and returns the result as an double-extended-precision floating-point value. +| The operation is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_round_to_int( floatx80 a ) +{ + flag aSign; + int32 aExp; + bits64 lastBitMask, roundBitsMask; + int8 roundingMode; + floatx80 z; + + aExp = extractFloatx80Exp( a ); + if ( 0x403E <= aExp ) { + if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { + return propagateFloatx80NaN( a, a ); + } + return a; + } + if ( aExp < 0x3FFF ) { + if ( ( aExp == 0 ) + && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { + return a; + } + float_exception_flags |= float_flag_inexact; + aSign = extractFloatx80Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) + ) { + return + packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); + } + break; + case float_round_down: + return + aSign ? + packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) + : packFloatx80( 0, 0, 0 ); + case float_round_up: + return + aSign ? packFloatx80( 1, 0, 0 ) + : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); + } + return packFloatx80( aSign, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x403E - aExp; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z.low += lastBitMask>>1; + if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { + z.low += roundBitsMask; + } + } + z.low &= ~ roundBitsMask; + if ( z.low == 0 ) { + ++z.high; + z.low = LIT64( 0x8000000000000000 ); + } + if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the double-extended- +| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is +| negated before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + int32 expDiff; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + expDiff = aExp - bExp; + if ( 0 < expDiff ) { + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return a; + } + if ( bExp == 0 ) --expDiff; + shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) ++expDiff; + shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); + zExp = bExp; + } + else { + if ( aExp == 0x7FFF ) { + if ( (bits64) ( ( aSig | bSig )<<1 ) ) { + return propagateFloatx80NaN( a, b ); + } + return a; + } + zSig1 = 0; + zSig0 = aSig + bSig; + if ( aExp == 0 ) { + normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); + goto roundAndPack; + } + zExp = aExp; + goto shiftRight1; + } + zSig0 = aSig + bSig; + if ( (sbits64) zSig0 < 0 ) goto roundAndPack; + shiftRight1: + shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); + zSig0 |= LIT64( 0x8000000000000000 ); + ++zExp; + roundAndPack: + return + roundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the double- +| extended-precision floating-point values `a' and `b'. If `zSign' is 1, +| the difference is negated before being returned. `zSign' is ignored if +| the result is a NaN. The subtraction is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + int32 expDiff; + floatx80 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + expDiff = aExp - bExp; + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0x7FFF ) { + if ( (bits64) ( ( aSig | bSig )<<1 ) ) { + return propagateFloatx80NaN( a, b ); + } + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + zSig1 = 0; + if ( bSig < aSig ) goto aBigger; + if ( aSig < bSig ) goto bBigger; + return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); + bExpBigger: + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) ++expDiff; + shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); + bBigger: + sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return a; + } + if ( bExp == 0 ) --expDiff; + shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); + aBigger: + sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); + zExp = aExp; + normalizeRoundAndPack: + return + normalizeRoundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the double-extended-precision floating-point +| values `a' and `b'. The operation is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_add( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign == bSign ) { + return addFloatx80Sigs( a, b, aSign ); + } + else { + return subFloatx80Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the double-extended-precision floating- +| point values `a' and `b'. The operation is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_sub( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign == bSign ) { + return subFloatx80Sigs( a, b, aSign ); + } + else { + return addFloatx80Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the double-extended-precision floating- +| point values `a' and `b'. The operation is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_mul( floatx80 a, floatx80 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + floatx80 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + bSign = extractFloatx80Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) + || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { + return propagateFloatx80NaN( a, b ); + } + if ( ( bExp | bSig ) == 0 ) goto invalid; + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + if ( ( aExp | aSig ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); + normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); + normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); + } + zExp = aExp + bExp - 0x3FFE; + mul64To128( aSig, bSig, &zSig0, &zSig1 ); + if ( 0 < (sbits64) zSig0 ) { + shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); + --zExp; + } + return + roundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the double-extended-precision floating-point +| value `a' by the corresponding value `b'. The operation is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_div( floatx80 a, floatx80 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + bits64 rem0, rem1, rem2, term0, term1, term2; + floatx80 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + bSign = extractFloatx80Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + goto invalid; + } + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return packFloatx80( zSign, 0, 0 ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + if ( ( aExp | aSig ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + float_raise( float_flag_divbyzero ); + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); + normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); + } + zExp = aExp - bExp + 0x3FFE; + rem1 = 0; + if ( bSig <= aSig ) { + shift128Right( aSig, 0, 1, &aSig, &rem1 ); + ++zExp; + } + zSig0 = estimateDiv128To64( aSig, rem1, bSig ); + mul64To128( bSig, zSig0, &term0, &term1 ); + sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); + } + zSig1 = estimateDiv128To64( rem1, 0, bSig ); + if ( (bits64) ( zSig1<<1 ) <= 8 ) { + mul64To128( bSig, zSig1, &term1, &term2 ); + sub128( rem1, 0, term1, term2, &rem1, &rem2 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); + } + zSig1 |= ( ( rem1 | rem2 ) != 0 ); + } + return + roundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the double-extended-precision floating-point value +| `a' with respect to the corresponding value `b'. The operation is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_rem( floatx80 a, floatx80 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, expDiff; + bits64 aSig0, aSig1, bSig; + bits64 q, term0, term1, alternateASig0, alternateASig1; + floatx80 z; + + aSig0 = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + bSign = extractFloatx80Sign( b ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig0<<1 ) + || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { + return propagateFloatx80NaN( a, b ); + } + goto invalid; + } + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( (bits64) ( aSig0<<1 ) == 0 ) return a; + normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); + } + bSig |= LIT64( 0x8000000000000000 ); + zSign = aSign; + expDiff = aExp - bExp; + aSig1 = 0; + if ( expDiff < 0 ) { + if ( expDiff < -1 ) return a; + shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); + expDiff = 0; + } + q = ( bSig <= aSig0 ); + if ( q ) aSig0 -= bSig; + expDiff -= 64; + while ( 0 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + mul64To128( bSig, q, &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); + shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); + expDiff -= 62; + } + expDiff += 64; + if ( 0 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + q >>= 64 - expDiff; + mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); + shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); + while ( le128( term0, term1, aSig0, aSig1 ) ) { + ++q; + sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); + } + } + else { + term1 = 0; + term0 = bSig; + } + sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); + if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) + || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) + && ( q & 1 ) ) + ) { + aSig0 = alternateASig0; + aSig1 = alternateASig1; + zSign = ! zSign; + } + return + normalizeRoundAndPackFloatx80( + 80, zSign, bExp + expDiff, aSig0, aSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the double-extended-precision floating-point +| value `a'. The operation is performed according to the IEEE Standard for +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_sqrt( floatx80 a ) +{ + flag aSign; + int32 aExp, zExp; + bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0; + bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; + floatx80 z; + + aSig0 = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); + if ( ! aSign ) return a; + goto invalid; + } + if ( aSign ) { + if ( ( aExp | aSig0 ) == 0 ) return a; + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + if ( aExp == 0 ) { + if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); + normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); + } + zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; + zSig0 = estimateSqrt32( aExp, aSig0>>32 ); + shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); + zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); + doubleZSig0 = zSig0<<1; + mul64To128( zSig0, zSig0, &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + doubleZSig0 -= 2; + add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); + } + zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); + if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { + if ( zSig1 == 0 ) zSig1 = 1; + mul64To128( doubleZSig0, zSig1, &term1, &term2 ); + sub128( rem1, 0, term1, term2, &rem1, &rem2 ); + mul64To128( zSig1, zSig1, &term2, &term3 ); + sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + shortShift128Left( 0, zSig1, 1, &term2, &term3 ); + term3 |= 1; + term2 |= doubleZSig0; + add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); + } + zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); + } + shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); + zSig0 |= doubleZSig0; + return + roundAndPackFloatx80( + floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-extended-precision floating-point value `a' is +| equal to the corresponding value `b', and 0 otherwise. The comparison is +| performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_eq( floatx80 a, floatx80 b ) +{ + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + if ( floatx80_is_signaling_nan( a ) + || floatx80_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-extended-precision floating-point value `a' is +| less than or equal to the corresponding value `b', and 0 otherwise. The +| comparison is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_le( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-extended-precision floating-point value `a' is +| less than the corresponding value `b', and 0 otherwise. The comparison is +| performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_lt( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-extended-precision floating-point value `a' is equal +| to the corresponding value `b', and 0 otherwise. The invalid exception is +| raised if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_eq_signaling( floatx80 a, floatx80 b ) +{ + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-extended-precision floating-point value `a' is less +| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs +| do not cause an exception. Otherwise, the comparison is performed according +| to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_le_quiet( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + if ( floatx80_is_signaling_nan( a ) + || floatx80_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-extended-precision floating-point value `a' is less +| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause +| an exception. Otherwise, the comparison is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_lt_quiet( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + if ( floatx80_is_signaling_nan( a ) + || floatx80_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the 32-bit two's complement integer format. The conversion is +| performed according to the IEEE Standard for Floating-Point Arithmetic--- +| which means in particular that the conversion is rounded according to the +| current rounding mode. If `a' is a NaN, the largest positive integer is +| returned. Otherwise, if the conversion overflows, the largest integer with +| the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 float128_to_int32( float128 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig0, aSig1; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; + if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); + aSig0 |= ( aSig1 != 0 ); + shiftCount = 0x4028 - aExp; + if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); + return roundAndPackInt32( aSign, aSig0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the 32-bit two's complement integer format. The conversion +| is performed according to the IEEE Standard for Floating-Point Arithmetic, +| except that the conversion is always rounded toward zero. If `a' is a NaN, +| the largest positive integer is returned. Otherwise, if the conversion +| overflows, the largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 float128_to_int32_round_to_zero( float128 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig0, aSig1, savedASig; + int32 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + aSig0 |= ( aSig1 != 0 ); + if ( 0x401E < aExp ) { + if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; + goto invalid; + } + else if ( aExp < 0x3FFF ) { + if ( aExp || aSig0 ) float_exception_flags |= float_flag_inexact; + return 0; + } + aSig0 |= LIT64( 0x0001000000000000 ); + shiftCount = 0x402F - aExp; + savedASig = aSig0; + aSig0 >>= shiftCount; + z = aSig0; + if ( aSign ) z = - z; + z = (sbits32) z; + if ( ( z < 0 ) ^ aSign ) { + invalid: + float_raise( float_flag_invalid ); + return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( ( aSig0<>( ( - shiftCount ) & 63 ) ); + if ( (bits64) ( aSig1<>( - shiftCount ); + if ( aSig1 + || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { + float_exception_flags |= float_flag_inexact; + } + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the single-precision floating-point format. The conversion is +| performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float128_to_float32( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig0, aSig1; + bits32 zSig; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) { + return commonNaNToFloat32( float128ToCommonNaN( a ) ); + } + return packFloat32( aSign, 0xFF, 0 ); + } + aSig0 |= ( aSig1 != 0 ); + shift64RightJamming( aSig0, 18, &aSig0 ); + zSig = aSig0; + if ( aExp || zSig ) { + zSig |= 0x40000000; + aExp -= 0x3F81; + } + return roundAndPackFloat32( aSign, aExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the double-precision floating-point format. The conversion is +| performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float128_to_float64( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig0, aSig1; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) { + return commonNaNToFloat64( float128ToCommonNaN( a ) ); + } + return packFloat64( aSign, 0x7FF, 0 ); + } + shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); + aSig0 |= ( aSig1 != 0 ); + if ( aExp || aSig0 ) { + aSig0 |= LIT64( 0x4000000000000000 ); + aExp -= 0x3C01; + } + return roundAndPackFloat64( aSign, aExp, aSig0 ); + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the double-extended-precision floating-point format. The +| conversion is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 float128_to_floatx80( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig0, aSig1; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) { + return commonNaNToFloatx80( float128ToCommonNaN( a ) ); + } + return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + else { + aSig0 |= LIT64( 0x0001000000000000 ); + } + shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); + return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the quadruple-precision floating-point value `a' to an integer, +| and returns the result as a quadruple-precision floating-point value. The +| operation is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_round_to_int( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 lastBitMask, roundBitsMask; + int8 roundingMode; + float128 z; + + aExp = extractFloat128Exp( a ); + if ( 0x402F <= aExp ) { + if ( 0x406F <= aExp ) { + if ( ( aExp == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) + ) { + return propagateFloat128NaN( a, a ); + } + return a; + } + lastBitMask = 1; + lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + if ( lastBitMask ) { + add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); + if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; + } + else { + if ( (sbits64) z.low < 0 ) { + ++z.high; + if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1; + } + } + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat128Sign( z ) + ^ ( roundingMode == float_round_up ) ) { + add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); + } + } + z.low &= ~ roundBitsMask; + } + else { + if ( aExp < 0x3FFF ) { + if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a; + float_exception_flags |= float_flag_inexact; + aSign = extractFloat128Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x3FFE ) + && ( extractFloat128Frac0( a ) + | extractFloat128Frac1( a ) ) + ) { + return packFloat128( aSign, 0x3FFF, 0, 0 ); + } + break; + case float_round_down: + return + aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) + : packFloat128( 0, 0, 0, 0 ); + case float_round_up: + return + aSign ? packFloat128( 1, 0, 0, 0 ) + : packFloat128( 0, 0x3FFF, 0, 0 ); + } + return packFloat128( aSign, 0, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x402F - aExp; + roundBitsMask = lastBitMask - 1; + z.low = 0; + z.high = a.high; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z.high += lastBitMask>>1; + if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { + z.high &= ~ lastBitMask; + } + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat128Sign( z ) + ^ ( roundingMode == float_round_up ) ) { + z.high |= ( a.low != 0 ); + z.high += roundBitsMask; + } + } + z.high &= ~ roundBitsMask; + } + if ( ( z.low != a.low ) || ( z.high != a.high ) ) { + float_exception_flags |= float_flag_inexact; + } + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the quadruple-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. The +| addition is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +static float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; + int32 expDiff; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + expDiff = aExp - bExp; + if ( 0 < expDiff ) { + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig0 |= LIT64( 0x0001000000000000 ); + } + shift128ExtraRightJamming( + bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig0 |= LIT64( 0x0001000000000000 ); + } + shift128ExtraRightJamming( + aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); + zExp = bExp; + } + else { + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 | bSig0 | bSig1 ) { + return propagateFloat128NaN( a, b ); + } + return a; + } + add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); + if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); + zSig2 = 0; + zSig0 |= LIT64( 0x0002000000000000 ); + zExp = aExp; + goto shiftRight1; + } + aSig0 |= LIT64( 0x0001000000000000 ); + add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); + --zExp; + if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; + ++zExp; + shiftRight1: + shift128ExtraRightJamming( + zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); + roundAndPack: + return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the quadruple- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; + int32 expDiff; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + expDiff = aExp - bExp; + shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); + shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 | bSig0 | bSig1 ) { + return propagateFloat128NaN( a, b ); + } + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + if ( bSig0 < aSig0 ) goto aBigger; + if ( aSig0 < bSig0 ) goto bBigger; + if ( bSig1 < aSig1 ) goto aBigger; + if ( aSig1 < bSig1 ) goto bBigger; + return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); + bExpBigger: + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig0 |= LIT64( 0x4000000000000000 ); + } + shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); + bSig0 |= LIT64( 0x4000000000000000 ); + bBigger: + sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig0 |= LIT64( 0x4000000000000000 ); + } + shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); + aSig0 |= LIT64( 0x4000000000000000 ); + aBigger: + sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the quadruple-precision floating-point values +| `a' and `b'. The operation is performed according to the IEEE Standard for +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_add( float128 a, float128 b ) +{ + flag aSign, bSign; + + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign == bSign ) { + return addFloat128Sigs( a, b, aSign ); + } + else { + return subFloat128Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the quadruple-precision floating-point +| values `a' and `b'. The operation is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_sub( float128 a, float128 b ) +{ + flag aSign, bSign; + + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign == bSign ) { + return subFloat128Sigs( a, b, aSign ); + } + else { + return addFloat128Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the quadruple-precision floating-point +| values `a' and `b'. The operation is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_mul( float128 a, float128 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + bSign = extractFloat128Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( ( aSig0 | aSig1 ) + || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { + return propagateFloat128NaN( a, b ); + } + if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + if ( ( aExp | aSig0 | aSig1 ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + if ( bExp == 0 ) { + if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); + normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); + } + zExp = aExp + bExp - 0x4000; + aSig0 |= LIT64( 0x0001000000000000 ); + shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); + mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); + add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); + zSig2 |= ( zSig3 != 0 ); + if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { + shift128ExtraRightJamming( + zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); + ++zExp; + } + return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the quadruple-precision floating-point value +| `a' by the corresponding value `b'. The operation is performed according to +| the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_div( float128 a, float128 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; + bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + bSign = extractFloat128Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + goto invalid; + } + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return packFloat128( zSign, 0, 0, 0 ); + } + if ( bExp == 0 ) { + if ( ( bSig0 | bSig1 ) == 0 ) { + if ( ( aExp | aSig0 | aSig1 ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + float_raise( float_flag_divbyzero ); + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + zExp = aExp - bExp + 0x3FFD; + shortShift128Left( + aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); + shortShift128Left( + bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); + if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { + shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); + ++zExp; + } + zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); + mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); + sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); + } + zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); + if ( ( zSig1 & 0x3FFF ) <= 4 ) { + mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); + sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); + } + zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); + } + shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); + return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the quadruple-precision floating-point value `a' +| with respect to the corresponding value `b'. The operation is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_rem( float128 a, float128 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, expDiff; + bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; + bits64 allZero, alternateASig0, alternateASig1, sigMean1; + sbits64 sigMean0; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + bSign = extractFloat128Sign( b ); + if ( aExp == 0x7FFF ) { + if ( ( aSig0 | aSig1 ) + || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { + return propagateFloat128NaN( a, b ); + } + goto invalid; + } + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( ( bSig0 | bSig1 ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return a; + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + expDiff = aExp - bExp; + if ( expDiff < -1 ) return a; + shortShift128Left( + aSig0 | LIT64( 0x0001000000000000 ), + aSig1, + 15 - ( expDiff < 0 ), + &aSig0, + &aSig1 + ); + shortShift128Left( + bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); + q = le128( bSig0, bSig1, aSig0, aSig1 ); + if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); + expDiff -= 64; + while ( 0 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig0 ); + q = ( 4 < q ) ? q - 4 : 0; + mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); + shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero ); + shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero ); + sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 ); + expDiff -= 61; + } + if ( -64 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig0 ); + q = ( 4 < q ) ? q - 4 : 0; + q >>= - expDiff; + shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); + expDiff += 52; + if ( expDiff < 0 ) { + shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); + } + else { + shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 ); + } + mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); + sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 ); + } + else { + shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 ); + shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); + } + do { + alternateASig0 = aSig0; + alternateASig1 = aSig1; + ++q; + sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); + } while ( 0 <= (sbits64) aSig0 ); + add128( + aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 ); + if ( ( sigMean0 < 0 ) + || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { + aSig0 = alternateASig0; + aSig1 = alternateASig1; + } + zSign = ( (sbits64) aSig0 < 0 ); + if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 ); + return + normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the quadruple-precision floating-point value `a'. +| The operation is performed according to the IEEE Standard for Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_sqrt( float128 a ) +{ + flag aSign; + int32 aExp, zExp; + bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; + bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a ); + if ( ! aSign ) return a; + goto invalid; + } + if ( aSign ) { + if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; + aSig0 |= LIT64( 0x0001000000000000 ); + zSig0 = estimateSqrt32( aExp, aSig0>>17 ); + shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); + zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); + doubleZSig0 = zSig0<<1; + mul64To128( zSig0, zSig0, &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + doubleZSig0 -= 2; + add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); + } + zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); + if ( ( zSig1 & 0x1FFF ) <= 5 ) { + if ( zSig1 == 0 ) zSig1 = 1; + mul64To128( doubleZSig0, zSig1, &term1, &term2 ); + sub128( rem1, 0, term1, term2, &rem1, &rem2 ); + mul64To128( zSig1, zSig1, &term2, &term3 ); + sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + shortShift128Left( 0, zSig1, 1, &term2, &term3 ); + term3 |= 1; + term2 |= doubleZSig0; + add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); + } + zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); + } + shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); + return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_eq( float128 a, float128 b ) +{ + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + if ( float128_is_signaling_nan( a ) + || float128_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| or equal to the corresponding value `b', and 0 otherwise. The comparison is +| performed according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_le( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_lt( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The invalid exception is +| raised if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_eq_signaling( float128 a, float128 b ) +{ + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +| cause an exception. Otherwise, the comparison is performed according to the +| IEEE Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_le_quiet( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + if ( float128_is_signaling_nan( a ) + || float128_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +| exception. Otherwise, the comparison is performed according to the IEEE +| Standard for Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_lt_quiet( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + if ( float128_is_signaling_nan( a ) + || float128_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +#endif + +float float32_to_c_float(float32 a){ + return *((float*)(&a)); +} +double float64_to_c_double(float64 a){ + return *((double*)(&a)); +} +float32 c_float_to_float32(float a){ + return *((float32*)(&a)); +} +float64 c_double_to_float64(double a){ + return *((float64*)(&a)); +} + +#ifdef FLOATX80 +float floatx80_to_c_float(floatx80 a){ + return float32_to_c_float(floatx80_to_float32(a)); +} +double floatx80_to_c_double(floatx80 a){ + return float64_to_c_double(floatx80_to_float64(a)); +} +floatx80 c_float_to_floatx80(float a){ + return float32_to_floatx80(c_float_to_float32(a)); +} +floatx80 c_double_to_floatx80(double a){ + return float64_to_floatx80(c_double_to_float64(a)); +} +#endif + +#endif diff --git a/i386c/ia32/instructions/fpu/softfloat/softfloat.h b/i386c/ia32/instructions/fpu/softfloat/softfloat.h index c93b7a14..5eaaacf7 100644 --- a/i386c/ia32/instructions/fpu/softfloat/softfloat.h +++ b/i386c/ia32/instructions/fpu/softfloat/softfloat.h @@ -1,268 +1,268 @@ - -/*============================================================================ - -This C header file is part of the Berkeley SoftFloat IEEE Floating-Point -Arithmetic Package, Release 2c, by John R. Hauser. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER -PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR -THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY -INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE -(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER -PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR -INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE -SOFTWARE. - -Derivative works require also that (1) the source code for the derivative work -includes prominent notice that the work is derivative, and (2) the source code -includes prominent notice of these three paragraphs for those parts of this -code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| The macro `FLOATX80' must be defined to enable the double-extended-precision -| floating-point format `floatx80'. If this macro is not defined, the -| `floatx80' type will not be defined, and none of the functions that either -| input or output the `floatx80' type will be defined. The same applies to -| the `FLOAT128' macro and the quadruple-precision format `float128'. -*----------------------------------------------------------------------------*/ -#define FLOATX80 -//#define FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEEE floating-point types. -*----------------------------------------------------------------------------*/ -typedef unsigned int float32; -typedef unsigned long long float64; -#ifdef FLOATX80 -typedef struct { - unsigned long long low; - unsigned short high; -} floatx80; -#endif -#ifdef FLOAT128 -typedef struct { - unsigned long long low, high; -} float128; -#endif - -/*---------------------------------------------------------------------------- -| Software IEEE floating-point underflow tininess-detection mode. -*----------------------------------------------------------------------------*/ -extern signed char float_detect_tininess; -enum { - float_tininess_after_rounding = 0, - float_tininess_before_rounding = 1 -}; - -/*---------------------------------------------------------------------------- -| Software IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -extern signed char float_rounding_mode; -enum { - float_round_nearest_even = 0, - float_round_down = 1, - float_round_up = 2, - float_round_to_zero = 3 -}; - -/*---------------------------------------------------------------------------- -| Software IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ -extern signed char float_exception_flags; -enum { - float_flag_invalid = 1, - float_flag_divbyzero = 4, - float_flag_overflow = 8, - float_flag_underflow = 16, - float_flag_inexact = 32 -}; - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEEE floating-point exception -| flags. -*----------------------------------------------------------------------------*/ -void float_raise( signed char ); - -/*---------------------------------------------------------------------------- -| Software IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32( int ); -float64 int32_to_float64( int ); -#ifdef FLOATX80 -floatx80 int32_to_floatx80( int ); -#endif -#ifdef FLOAT128 -float128 int32_to_float128( int ); -#endif -float32 int64_to_float32( long long ); -float64 int64_to_float64( long long ); -#ifdef FLOATX80 -floatx80 int64_to_floatx80( long long ); -#endif -#ifdef FLOAT128 -float128 int64_to_float128( long long ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float32_to_int32( float32 ); -int float32_to_int32_round_to_zero( float32 ); -long long float32_to_int64( float32 ); -long long float32_to_int64_round_to_zero( float32 ); -float64 float32_to_float64( float32 ); -#ifdef FLOATX80 -floatx80 float32_to_floatx80( float32 ); -#endif -#ifdef FLOAT128 -float128 float32_to_float128( float32 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int( float32 ); -float32 float32_add( float32, float32 ); -float32 float32_sub( float32, float32 ); -float32 float32_mul( float32, float32 ); -float32 float32_div( float32, float32 ); -float32 float32_rem( float32, float32 ); -float32 float32_sqrt( float32 ); -char float32_eq( float32, float32 ); -char float32_le( float32, float32 ); -char float32_lt( float32, float32 ); -char float32_eq_signaling( float32, float32 ); -char float32_le_quiet( float32, float32 ); -char float32_lt_quiet( float32, float32 ); -char float32_is_signaling_nan( float32 ); - -/*---------------------------------------------------------------------------- -| Software IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float64_to_int32( float64 ); -int float64_to_int32_round_to_zero( float64 ); -long long float64_to_int64( float64 ); -long long float64_to_int64_round_to_zero( float64 ); -float32 float64_to_float32( float64 ); -#ifdef FLOATX80 -floatx80 float64_to_floatx80( float64 ); -#endif -#ifdef FLOAT128 -float128 float64_to_float128( float64 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -float64 float64_round_to_int( float64 ); -float64 float64_add( float64, float64 ); -float64 float64_sub( float64, float64 ); -float64 float64_mul( float64, float64 ); -float64 float64_div( float64, float64 ); -float64 float64_rem( float64, float64 ); -float64 float64_sqrt( float64 ); -char float64_eq( float64, float64 ); -char float64_le( float64, float64 ); -char float64_lt( float64, float64 ); -char float64_eq_signaling( float64, float64 ); -char float64_le_quiet( float64, float64 ); -char float64_lt_quiet( float64, float64 ); -char float64_is_signaling_nan( float64 ); - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEEE double-extended-precision conversion routines. -*----------------------------------------------------------------------------*/ -short floatx80_to_int16_np2( floatx80 ); // for np2 FPU by SimK -int floatx80_to_int32( floatx80 ); -int floatx80_to_int32_np2( floatx80 ); -int floatx80_to_int32_round_to_zero( floatx80 ); -long long floatx80_to_int64( floatx80 ); -long long floatx80_to_int64_np2( floatx80 ); -long long floatx80_to_int64_round_to_zero( floatx80 ); -float32 floatx80_to_float32( floatx80 ); -float64 floatx80_to_float64( floatx80 ); -#ifdef FLOAT128 -float128 floatx80_to_float128( floatx80 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEEE double-extended-precision rounding precision. Valid values -| are 32, 64, and 80. -*----------------------------------------------------------------------------*/ -extern signed char floatx80_rounding_precision; - -/*---------------------------------------------------------------------------- -| Software IEEE double-extended-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int( floatx80 ); -floatx80 floatx80_add( floatx80, floatx80 ); -floatx80 floatx80_sub( floatx80, floatx80 ); -floatx80 floatx80_mul( floatx80, floatx80 ); -floatx80 floatx80_div( floatx80, floatx80 ); -floatx80 floatx80_rem( floatx80, floatx80 ); -floatx80 floatx80_sqrt( floatx80 ); -char floatx80_eq( floatx80, floatx80 ); -char floatx80_le( floatx80, floatx80 ); -char floatx80_lt( floatx80, floatx80 ); -char floatx80_eq_signaling( floatx80, floatx80 ); -char floatx80_le_quiet( floatx80, floatx80 ); -char floatx80_lt_quiet( floatx80, floatx80 ); -char floatx80_is_nan( floatx80 a ); -char floatx80_is_signaling_nan( floatx80 ); -char floatx80_is_inf( floatx80 a ); - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEEE quadruple-precision conversion routines. -*----------------------------------------------------------------------------*/ -int float128_to_int32( float128 ); -int float128_to_int32_round_to_zero( float128 ); -long long float128_to_int64( float128 ); -long long float128_to_int64_round_to_zero( float128 ); -float32 float128_to_float32( float128 ); -float64 float128_to_float64( float128 ); -#ifdef FLOATX80 -floatx80 float128_to_floatx80( float128 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEEE quadruple-precision operations. -*----------------------------------------------------------------------------*/ -float128 float128_round_to_int( float128 ); -float128 float128_add( float128, float128 ); -float128 float128_sub( float128, float128 ); -float128 float128_mul( float128, float128 ); -float128 float128_div( float128, float128 ); -float128 float128_rem( float128, float128 ); -float128 float128_sqrt( float128 ); -char float128_eq( float128, float128 ); -char float128_le( float128, float128 ); -char float128_lt( float128, float128 ); -char float128_eq_signaling( float128, float128 ); -char float128_le_quiet( float128, float128 ); -char float128_lt_quiet( float128, float128 ); -char float128_is_signaling_nan( float128 ); - -#endif - -float float32_to_c_float(float32 a); -double float64_to_c_double(float64 a); -float32 c_float_to_float32(float a); -float64 c_double_to_float64(double a); - -#ifdef FLOATX80 -float floatx80_to_c_float(floatx80 a); -double floatx80_to_c_double(floatx80 a); -floatx80 c_float_to_floatx80(float a); -floatx80 c_double_to_floatx80(double a); + +/*============================================================================ + +This C header file is part of the Berkeley SoftFloat IEEE Floating-Point +Arithmetic Package, Release 2c, by John R. Hauser. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER +PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR +THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY +INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE +(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER +PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR +INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE +SOFTWARE. + +Derivative works require also that (1) the source code for the derivative work +includes prominent notice that the work is derivative, and (2) the source code +includes prominent notice of these three paragraphs for those parts of this +code that are retained. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +| The macro `FLOATX80' must be defined to enable the double-extended-precision +| floating-point format `floatx80'. If this macro is not defined, the +| `floatx80' type will not be defined, and none of the functions that either +| input or output the `floatx80' type will be defined. The same applies to +| the `FLOAT128' macro and the quadruple-precision format `float128'. +*----------------------------------------------------------------------------*/ +#define FLOATX80 +//#define FLOAT128 + +/*---------------------------------------------------------------------------- +| Software IEEE floating-point types. +*----------------------------------------------------------------------------*/ +typedef unsigned int float32; +typedef unsigned long long float64; +#ifdef FLOATX80 +typedef struct { + unsigned long long low; + unsigned short high; +} floatx80; +#endif +#ifdef FLOAT128 +typedef struct { + unsigned long long low, high; +} float128; +#endif + +/*---------------------------------------------------------------------------- +| Software IEEE floating-point underflow tininess-detection mode. +*----------------------------------------------------------------------------*/ +extern signed char float_detect_tininess; +enum { + float_tininess_after_rounding = 0, + float_tininess_before_rounding = 1 +}; + +/*---------------------------------------------------------------------------- +| Software IEEE floating-point rounding mode. +*----------------------------------------------------------------------------*/ +extern signed char float_rounding_mode; +enum { + float_round_nearest_even = 0, + float_round_down = 1, + float_round_up = 2, + float_round_to_zero = 3 +}; + +/*---------------------------------------------------------------------------- +| Software IEEE floating-point exception flags. +*----------------------------------------------------------------------------*/ +extern signed char float_exception_flags; +enum { + float_flag_invalid = 1, + float_flag_divbyzero = 4, + float_flag_overflow = 8, + float_flag_underflow = 16, + float_flag_inexact = 32 +}; + +/*---------------------------------------------------------------------------- +| Routine to raise any or all of the software IEEE floating-point exception +| flags. +*----------------------------------------------------------------------------*/ +void float_raise( signed char ); + +/*---------------------------------------------------------------------------- +| Software IEEE integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ +float32 int32_to_float32( int ); +float64 int32_to_float64( int ); +#ifdef FLOATX80 +floatx80 int32_to_floatx80( int ); +#endif +#ifdef FLOAT128 +float128 int32_to_float128( int ); +#endif +float32 int64_to_float32( long long ); +float64 int64_to_float64( long long ); +#ifdef FLOATX80 +floatx80 int64_to_floatx80( long long ); +#endif +#ifdef FLOAT128 +float128 int64_to_float128( long long ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEEE single-precision conversion routines. +*----------------------------------------------------------------------------*/ +int float32_to_int32( float32 ); +int float32_to_int32_round_to_zero( float32 ); +long long float32_to_int64( float32 ); +long long float32_to_int64_round_to_zero( float32 ); +float64 float32_to_float64( float32 ); +#ifdef FLOATX80 +floatx80 float32_to_floatx80( float32 ); +#endif +#ifdef FLOAT128 +float128 float32_to_float128( float32 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEEE single-precision operations. +*----------------------------------------------------------------------------*/ +float32 float32_round_to_int( float32 ); +float32 float32_add( float32, float32 ); +float32 float32_sub( float32, float32 ); +float32 float32_mul( float32, float32 ); +float32 float32_div( float32, float32 ); +float32 float32_rem( float32, float32 ); +float32 float32_sqrt( float32 ); +char float32_eq( float32, float32 ); +char float32_le( float32, float32 ); +char float32_lt( float32, float32 ); +char float32_eq_signaling( float32, float32 ); +char float32_le_quiet( float32, float32 ); +char float32_lt_quiet( float32, float32 ); +char float32_is_signaling_nan( float32 ); + +/*---------------------------------------------------------------------------- +| Software IEEE double-precision conversion routines. +*----------------------------------------------------------------------------*/ +int float64_to_int32( float64 ); +int float64_to_int32_round_to_zero( float64 ); +long long float64_to_int64( float64 ); +long long float64_to_int64_round_to_zero( float64 ); +float32 float64_to_float32( float64 ); +#ifdef FLOATX80 +floatx80 float64_to_floatx80( float64 ); +#endif +#ifdef FLOAT128 +float128 float64_to_float128( float64 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEEE double-precision operations. +*----------------------------------------------------------------------------*/ +float64 float64_round_to_int( float64 ); +float64 float64_add( float64, float64 ); +float64 float64_sub( float64, float64 ); +float64 float64_mul( float64, float64 ); +float64 float64_div( float64, float64 ); +float64 float64_rem( float64, float64 ); +float64 float64_sqrt( float64 ); +char float64_eq( float64, float64 ); +char float64_le( float64, float64 ); +char float64_lt( float64, float64 ); +char float64_eq_signaling( float64, float64 ); +char float64_le_quiet( float64, float64 ); +char float64_lt_quiet( float64, float64 ); +char float64_is_signaling_nan( float64 ); + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Software IEEE double-extended-precision conversion routines. +*----------------------------------------------------------------------------*/ +short floatx80_to_int16_np2( floatx80 ); // for np2 FPU by SimK +int floatx80_to_int32( floatx80 ); +int floatx80_to_int32_np2( floatx80 ); +int floatx80_to_int32_round_to_zero( floatx80 ); +long long floatx80_to_int64( floatx80 ); +long long floatx80_to_int64_np2( floatx80 ); +long long floatx80_to_int64_round_to_zero( floatx80 ); +float32 floatx80_to_float32( floatx80 ); +float64 floatx80_to_float64( floatx80 ); +#ifdef FLOAT128 +float128 floatx80_to_float128( floatx80 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEEE double-extended-precision rounding precision. Valid values +| are 32, 64, and 80. +*----------------------------------------------------------------------------*/ +extern signed char floatx80_rounding_precision; + +/*---------------------------------------------------------------------------- +| Software IEEE double-extended-precision operations. +*----------------------------------------------------------------------------*/ +floatx80 floatx80_round_to_int( floatx80 ); +floatx80 floatx80_add( floatx80, floatx80 ); +floatx80 floatx80_sub( floatx80, floatx80 ); +floatx80 floatx80_mul( floatx80, floatx80 ); +floatx80 floatx80_div( floatx80, floatx80 ); +floatx80 floatx80_rem( floatx80, floatx80 ); +floatx80 floatx80_sqrt( floatx80 ); +char floatx80_eq( floatx80, floatx80 ); +char floatx80_le( floatx80, floatx80 ); +char floatx80_lt( floatx80, floatx80 ); +char floatx80_eq_signaling( floatx80, floatx80 ); +char floatx80_le_quiet( floatx80, floatx80 ); +char floatx80_lt_quiet( floatx80, floatx80 ); +char floatx80_is_nan( floatx80 a ); +char floatx80_is_signaling_nan( floatx80 ); +char floatx80_is_inf( floatx80 a ); + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Software IEEE quadruple-precision conversion routines. +*----------------------------------------------------------------------------*/ +int float128_to_int32( float128 ); +int float128_to_int32_round_to_zero( float128 ); +long long float128_to_int64( float128 ); +long long float128_to_int64_round_to_zero( float128 ); +float32 float128_to_float32( float128 ); +float64 float128_to_float64( float128 ); +#ifdef FLOATX80 +floatx80 float128_to_floatx80( float128 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEEE quadruple-precision operations. +*----------------------------------------------------------------------------*/ +float128 float128_round_to_int( float128 ); +float128 float128_add( float128, float128 ); +float128 float128_sub( float128, float128 ); +float128 float128_mul( float128, float128 ); +float128 float128_div( float128, float128 ); +float128 float128_rem( float128, float128 ); +float128 float128_sqrt( float128 ); +char float128_eq( float128, float128 ); +char float128_le( float128, float128 ); +char float128_lt( float128, float128 ); +char float128_eq_signaling( float128, float128 ); +char float128_le_quiet( float128, float128 ); +char float128_lt_quiet( float128, float128 ); +char float128_is_signaling_nan( float128 ); + +#endif + +float float32_to_c_float(float32 a); +double float64_to_c_double(float64 a); +float32 c_float_to_float32(float a); +float64 c_double_to_float64(double a); + +#ifdef FLOATX80 +float floatx80_to_c_float(floatx80 a); +double floatx80_to_c_double(floatx80 a); +floatx80 c_float_to_floatx80(float a); +floatx80 c_double_to_floatx80(double a); #endif \ No newline at end of file diff --git a/i386c/ia32/instructions/fpu/softfloat/softfloatdef.h b/i386c/ia32/instructions/fpu/softfloat/softfloatdef.h index fea6dd61..5bc07c79 100644 --- a/i386c/ia32/instructions/fpu/softfloat/softfloatdef.h +++ b/i386c/ia32/instructions/fpu/softfloat/softfloatdef.h @@ -1,22 +1,22 @@ -#pragma once - -typedef char flag; -typedef unsigned char uint8; -typedef signed char int8; -typedef unsigned short int uint16; -typedef signed short int int16; -typedef unsigned int uint32; -typedef signed int int32; -typedef unsigned long long int uint64; -typedef signed long long int int64; - -typedef unsigned char bits8; -typedef signed char sbits8; -typedef unsigned short int bits16; -typedef signed short int sbits16; -typedef unsigned int bits32; -typedef signed int sbits32; -typedef unsigned long long int bits64; -typedef signed long long int sbits64; - -#define LIT64(a) (a) +#pragma once + +typedef char flag; +typedef unsigned char uint8; +typedef signed char int8; +typedef unsigned short int uint16; +typedef signed short int int16; +typedef unsigned int uint32; +typedef signed int int32; +typedef unsigned long long int uint64; +typedef signed long long int int64; + +typedef unsigned char bits8; +typedef signed char sbits8; +typedef unsigned short int bits16; +typedef signed short int sbits16; +typedef unsigned int bits32; +typedef signed int sbits32; +typedef unsigned long long int bits64; +typedef signed long long int sbits64; + +#define LIT64(a) (a) diff --git a/i386c/ia32/instructions/fpu/softfloat3/include/stdbool.h b/i386c/ia32/instructions/fpu/softfloat3/include/stdbool.h index 6c1710b2..10fffa94 100644 --- a/i386c/ia32/instructions/fpu/softfloat3/include/stdbool.h +++ b/i386c/ia32/instructions/fpu/softfloat3/include/stdbool.h @@ -1,4 +1,4 @@ -/* stdbool.hȂ‹p */ +/* stdbool.hがない環境用 */ #pragma once diff --git a/i386c/ia32/instructions/logic_arith.c b/i386c/ia32/instructions/logic_arith.c old mode 100755 new mode 100644 index 594a4c41..62b1aa84 --- a/i386c/ia32/instructions/logic_arith.c +++ b/i386c/ia32/instructions/logic_arith.c @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" -#include "arith.mcr" - -#include "logic_arith.h" - - -/* - * AND - */ -ARITH_INSTRUCTION_2(AND) - -/* - * OR - */ -ARITH_INSTRUCTION_2(OR) - -/* - * XOR - */ -ARITH_INSTRUCTION_2(XOR) - -/* - * NOT - */ -ARITH_INSTRUCTION_1(NOT) +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" +#include "arith.mcr" + +#include "logic_arith.h" + + +/* + * AND + */ +ARITH_INSTRUCTION_2(AND) + +/* + * OR + */ +ARITH_INSTRUCTION_2(OR) + +/* + * XOR + */ +ARITH_INSTRUCTION_2(XOR) + +/* + * NOT + */ +ARITH_INSTRUCTION_1(NOT) diff --git a/i386c/ia32/instructions/logic_arith.h b/i386c/ia32/instructions/logic_arith.h old mode 100755 new mode 100644 index 5e1821cd..a1ed14e5 --- a/i386c/ia32/instructions/logic_arith.h +++ b/i386c/ia32/instructions/logic_arith.h @@ -1,101 +1,101 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_LOGIC_ARITH_H__ -#define IA32_CPU_INSTRUCTION_LOGIC_ARITH_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * AND - */ -void AND_EbGb(void); -void AND_EwGw(void); -void AND_EdGd(void); -void AND_GbEb(void); -void AND_GwEw(void); -void AND_GdEd(void); -void AND_ALIb(void); -void AND_AXIw(void); -void AND_EAXId(void); -void CPUCALL AND_EbIb(UINT8 *, UINT32); -void CPUCALL AND_EwIx(UINT16 *, UINT32); -void CPUCALL AND_EdIx(UINT32 *, UINT32); -void CPUCALL AND_EbIb_ext(UINT32, UINT32); -void CPUCALL AND_EwIx_ext(UINT32, UINT32); -void CPUCALL AND_EdIx_ext(UINT32, UINT32); - -/* - * OR - */ -void OR_EbGb(void); -void OR_EwGw(void); -void OR_EdGd(void); -void OR_GbEb(void); -void OR_GwEw(void); -void OR_GdEd(void); -void OR_ALIb(void); -void OR_AXIw(void); -void OR_EAXId(void); -void CPUCALL OR_EbIb(UINT8 *, UINT32); -void CPUCALL OR_EwIx(UINT16 *, UINT32); -void CPUCALL OR_EdIx(UINT32 *, UINT32); -void CPUCALL OR_EbIb_ext(UINT32, UINT32); -void CPUCALL OR_EwIx_ext(UINT32, UINT32); -void CPUCALL OR_EdIx_ext(UINT32, UINT32); - -/* - * XOR - */ -void XOR_EbGb(void); -void XOR_EwGw(void); -void XOR_EdGd(void); -void XOR_GbEb(void); -void XOR_GwEw(void); -void XOR_GdEd(void); -void XOR_ALIb(void); -void XOR_AXIw(void); -void XOR_EAXId(void); -void CPUCALL XOR_EbIb(UINT8 *, UINT32); -void CPUCALL XOR_EwIx(UINT16 *, UINT32); -void CPUCALL XOR_EdIx(UINT32 *, UINT32); -void CPUCALL XOR_EbIb_ext(UINT32, UINT32); -void CPUCALL XOR_EwIx_ext(UINT32, UINT32); -void CPUCALL XOR_EdIx_ext(UINT32, UINT32); - -/* - * NOT - */ -void CPUCALL NOT_Eb(UINT32); -void CPUCALL NOT_Ew(UINT32); -void CPUCALL NOT_Ed(UINT32); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_LOGIC_ARITH_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_LOGIC_ARITH_H__ +#define IA32_CPU_INSTRUCTION_LOGIC_ARITH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * AND + */ +void AND_EbGb(void); +void AND_EwGw(void); +void AND_EdGd(void); +void AND_GbEb(void); +void AND_GwEw(void); +void AND_GdEd(void); +void AND_ALIb(void); +void AND_AXIw(void); +void AND_EAXId(void); +void CPUCALL AND_EbIb(UINT8 *, UINT32); +void CPUCALL AND_EwIx(UINT16 *, UINT32); +void CPUCALL AND_EdIx(UINT32 *, UINT32); +void CPUCALL AND_EbIb_ext(UINT32, UINT32); +void CPUCALL AND_EwIx_ext(UINT32, UINT32); +void CPUCALL AND_EdIx_ext(UINT32, UINT32); + +/* + * OR + */ +void OR_EbGb(void); +void OR_EwGw(void); +void OR_EdGd(void); +void OR_GbEb(void); +void OR_GwEw(void); +void OR_GdEd(void); +void OR_ALIb(void); +void OR_AXIw(void); +void OR_EAXId(void); +void CPUCALL OR_EbIb(UINT8 *, UINT32); +void CPUCALL OR_EwIx(UINT16 *, UINT32); +void CPUCALL OR_EdIx(UINT32 *, UINT32); +void CPUCALL OR_EbIb_ext(UINT32, UINT32); +void CPUCALL OR_EwIx_ext(UINT32, UINT32); +void CPUCALL OR_EdIx_ext(UINT32, UINT32); + +/* + * XOR + */ +void XOR_EbGb(void); +void XOR_EwGw(void); +void XOR_EdGd(void); +void XOR_GbEb(void); +void XOR_GwEw(void); +void XOR_GdEd(void); +void XOR_ALIb(void); +void XOR_AXIw(void); +void XOR_EAXId(void); +void CPUCALL XOR_EbIb(UINT8 *, UINT32); +void CPUCALL XOR_EwIx(UINT16 *, UINT32); +void CPUCALL XOR_EdIx(UINT32 *, UINT32); +void CPUCALL XOR_EbIb_ext(UINT32, UINT32); +void CPUCALL XOR_EwIx_ext(UINT32, UINT32); +void CPUCALL XOR_EdIx_ext(UINT32, UINT32); + +/* + * NOT + */ +void CPUCALL NOT_Eb(UINT32); +void CPUCALL NOT_Ew(UINT32); +void CPUCALL NOT_Ed(UINT32); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_LOGIC_ARITH_H__ */ diff --git a/i386c/ia32/instructions/misc_inst.c b/i386c/ia32/instructions/misc_inst.c old mode 100755 new mode 100644 index db3cf410..e499331a --- a/i386c/ia32/instructions/misc_inst.c +++ b/i386c/ia32/instructions/misc_inst.c @@ -1,401 +1,401 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" - -#include "misc_inst.h" -#include "ia32/inst_table.h" - -#include - -#ifdef USE_SSE2 -#include "ia32/instructions/sse2/sse2.h" -#endif - -#ifdef SUPPORT_IA32_HAXM -#include -#endif -void -LEA_GwM(void) -{ - UINT16 *out; - UINT32 op, dst; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG16_B53(op); - dst = calc_ea_dst(op); - *out = (UINT16)dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LEA_GdM(void) -{ - UINT32 *out; - UINT32 op, dst; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - CPU_WORKCLOCK(2); - out = CPU_REG32_B53(op); - dst = calc_ea_dst(op); - *out = dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -_NOP(void) -{ -#if defined(SUPPORT_IA32_HAXM) && defined(USE_CUSTOM_HOOKINST) - if(bioshookinfo.hookinst == 0x90) -#endif - ia32_bioscall(); -} - -void -UD2(void) -{ - - EXCEPTION(UD_EXCEPTION, 0); -} - -void -XLAT(void) -{ - - CPU_WORKCLOCK(5); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - CPU_AL = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_BX + CPU_AL); - } else { - CPU_AL = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_EBX + CPU_AL); - } -} - -void -_CPUID(void) -{ - switch (CPU_EAX) { - case 0: - CPU_EAX = 1; - CPU_EBX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+0))); - CPU_EDX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+4))); - CPU_ECX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+8))); - break; - - case 1: - CPU_EAX = (((i386cpuid.cpu_family >> 4) & 0xff) << 20) | (((i386cpuid.cpu_model >> 4) & 0xf) << 16) | - ((i386cpuid.cpu_family & 0xf) << 8) | ((i386cpuid.cpu_model & 0xf) << 4) | (i386cpuid.cpu_stepping & 0xf); - CPU_EBX = i386cpuid.cpu_brandid; - if (i386cpuid.cpu_feature & CPU_FEATURE_CLFSH) - { - CPU_EBX |= (8) << 8; // キャッシュラインサイズ - } - CPU_ECX = i386cpuid.cpu_feature_ecx & CPU_FEATURES_ECX_ALL; - CPU_EDX = i386cpuid.cpu_feature & CPU_FEATURES_ALL; - break; - - case 2: - if(i386cpuid.cpu_family >= 6){ - CPU_EAX = 0x1; - CPU_EBX = 0; - CPU_ECX = 0; - CPU_EDX = 0x43; // 512KB L2 Cache のふり - }else{ - CPU_EAX = 0; - CPU_EBX = 0; - CPU_ECX = 0; - CPU_EDX = 0; - } - break; - - case 0x80000000: - CPU_EAX = 0x80000004; - if(strncmp(i386cpuid.cpu_vendor, CPU_VENDOR_AMD, 12)==0){ // AMD判定 - CPU_EBX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+0))); - CPU_EDX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+4))); - CPU_ECX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+8))); - }else{ - CPU_EBX = 0; - CPU_ECX = 0; - CPU_EDX = 0; - } - break; - - case 0x80000001: - if (strncmp(i386cpuid.cpu_vendor, CPU_VENDOR_AMD, 12) == 0) - { // AMD判定 - if (i386cpuid.cpu_family >= 6 || (i386cpuid.cpu_family == 5 && i386cpuid.cpu_model >= 6)) - { - CPU_EAX = ((i386cpuid.cpu_family + 1) << 8) | (i386cpuid.cpu_model << 4) | i386cpuid.cpu_stepping; - } - else - { - CPU_EAX = (i386cpuid.cpu_family << 8) | (i386cpuid.cpu_model << 4) | i386cpuid.cpu_stepping; - } - }else{ - CPU_EAX = 0; - } - CPU_EBX = 0; - CPU_ECX = i386cpuid.cpu_feature_ex_ecx & CPU_FEATURES_EX_ECX_ALL; - CPU_EDX = i386cpuid.cpu_feature_ex & CPU_FEATURES_EX_ALL; - break; - - case 0x80000002: - case 0x80000003: - case 0x80000004: - { - UINT32 clkMHz; - char cpu_brandstringbuf[64] = {0}; - int stroffset = (CPU_EAX - 0x80000002) * 16; - clkMHz = pccore.realclock/1000/1000; - sprintf(cpu_brandstringbuf, "%s%u MHz", i386cpuid.cpu_brandstring, clkMHz); - CPU_EAX = LOADINTELDWORD(((UINT8*)(cpu_brandstringbuf + stroffset + 0))); - CPU_EBX = LOADINTELDWORD(((UINT8*)(cpu_brandstringbuf + stroffset + 4))); - CPU_ECX = LOADINTELDWORD(((UINT8*)(cpu_brandstringbuf + stroffset + 8))); - CPU_EDX = LOADINTELDWORD(((UINT8*)(cpu_brandstringbuf + stroffset + 12))); - } - - break; - } -} - -/* undoc 8086 */ -void -SALC(void) -{ - - CPU_WORKCLOCK(2); - CPU_AL = (CPU_FLAGL & C_FLAG) ? 0xff : 0; -} - -/* undoc 286 */ -void -LOADALL286(void) -{ - - ia32_panic("LOADALL286: not implemented yet."); -} - -/* undoc 386 */ -void -LOADALL(void) -{ - - ia32_panic("LOADALL: not implemented yet."); -} - -void -OpSize(void) -{ - - CPU_INST_OP32 = !CPU_STATSAVE.cpu_inst_default.op_32; -} - -void -AddrSize(void) -{ - - CPU_INST_AS32 = !CPU_STATSAVE.cpu_inst_default.as_32; -} - -void -_2byte_ESC16(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); -#ifdef USE_SSE - if(insttable_2byte660F_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32){ - (*insttable_2byte660F_32[op])(); - }else if(insttable_2byteF20F_32[op] && CPU_INST_REPUSE == 0xf2){ - (*insttable_2byteF20F_32[op])(); - }else if(insttable_2byteF30F_32[op] && CPU_INST_REPUSE == 0xf3){ - (*insttable_2byteF30F_32[op])(); - }else{ - (*insttable_2byte[0][op])(); - } -#else - (*insttable_2byte[0][op])(); -#endif -} - -void -_2byte_ESC32(void) -{ - UINT32 op; - - GET_MODRM_PCBYTE(op); -#ifdef USE_SSE - if(insttable_2byte660F_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32){ - (*insttable_2byte660F_32[op])(); - }else if(insttable_2byteF20F_32[op] && CPU_INST_REPUSE == 0xf2){ - (*insttable_2byteF20F_32[op])(); - }else if(insttable_2byteF30F_32[op] && CPU_INST_REPUSE == 0xf3){ - (*insttable_2byteF30F_32[op])(); - }else{ - (*insttable_2byte[1][op])(); - } -#else - (*insttable_2byte[1][op])(); -#endif -} - -void -_3byte_38ESC(void) -{ - UINT32 op; - -#ifdef USE_SSSE3 - if(!(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSSE3)){ - EXCEPTION(UD_EXCEPTION, 0); - } else { - GET_MODRM_PCBYTE(op); - if(insttable_3byte660F38_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32){ - (*insttable_3byte660F38_32[op])(); - return; - }else if(insttable_3byteF20F38_32[op] && CPU_INST_REPUSE == 0xf2){ - (*insttable_3byteF20F38_32[op])(); - return; - }else if(insttable_2byte0F38_32[op]){ - (*insttable_2byte0F38_32[op])(); - return; - }else{ - EXCEPTION(UD_EXCEPTION, 0); - } - } -#else - EXCEPTION(UD_EXCEPTION, 0); -#endif -} - -void -_3byte_38ESC_16(void) -{ - UINT32 op; - -#ifdef USE_SSSE3 - if(!(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSSE3)){ - EXCEPTION(UD_EXCEPTION, 0); - } else { - GET_MODRM_PCBYTE(op); - if(insttable_3byte660F38_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32){ - (*insttable_3byte660F38_32[op])(); - return; - }else if(insttable_3byteF20F38_16[op] && CPU_INST_REPUSE == 0xf2){ - (*insttable_3byteF20F38_16[op])(); - return; - }else if(insttable_2byte0F38_32[op]){ - (*insttable_2byte0F38_32[op])(); - return; - }else{ - EXCEPTION(UD_EXCEPTION, 0); - } - } -#else - EXCEPTION(UD_EXCEPTION, 0); -#endif -} - -void -_3byte_3AESC(void) -{ - UINT32 op; - -#ifdef USE_SSSE3 - if(!(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSSE3)){ - EXCEPTION(UD_EXCEPTION, 0); - } else { - GET_MODRM_PCBYTE(op); - if(insttable_3byte660F3A_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32){ - (*insttable_3byte660F3A_32[op])(); - return; - }else if(insttable_2byte0F3A_32[op]){ - (*insttable_2byte0F3A_32[op])(); - return; - }else{ - EXCEPTION(UD_EXCEPTION, 0); - } - } -#else - EXCEPTION(UD_EXCEPTION, 0); -#endif -} - -void -Prefix_ES(void) -{ - - CPU_INST_SEGUSE = 1; - CPU_INST_SEGREG_INDEX = CPU_ES_INDEX; -} - -void -Prefix_CS(void) -{ - - CPU_INST_SEGUSE = 1; - CPU_INST_SEGREG_INDEX = CPU_CS_INDEX; -} - -void -Prefix_SS(void) -{ - - CPU_INST_SEGUSE = 1; - CPU_INST_SEGREG_INDEX = CPU_SS_INDEX; -} - -void -Prefix_DS(void) -{ - - CPU_INST_SEGUSE = 1; - CPU_INST_SEGREG_INDEX = CPU_DS_INDEX; -} - -void -Prefix_FS(void) -{ - - CPU_INST_SEGUSE = 1; - CPU_INST_SEGREG_INDEX = CPU_FS_INDEX; -} - -void -Prefix_GS(void) -{ - - CPU_INST_SEGUSE = 1; - CPU_INST_SEGREG_INDEX = CPU_GS_INDEX; -} +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" + +#include "misc_inst.h" +#include "ia32/inst_table.h" + +#include + +#ifdef USE_SSE2 +#include "ia32/instructions/sse2/sse2.h" +#endif + +#ifdef SUPPORT_IA32_HAXM +#include +#endif +void +LEA_GwM(void) +{ + UINT16 *out; + UINT32 op, dst; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG16_B53(op); + dst = calc_ea_dst(op); + *out = (UINT16)dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LEA_GdM(void) +{ + UINT32 *out; + UINT32 op, dst; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + CPU_WORKCLOCK(2); + out = CPU_REG32_B53(op); + dst = calc_ea_dst(op); + *out = dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +_NOP(void) +{ +#if defined(SUPPORT_IA32_HAXM) && defined(USE_CUSTOM_HOOKINST) + if(bioshookinfo.hookinst == 0x90) +#endif + ia32_bioscall(); +} + +void +UD2(void) +{ + + EXCEPTION(UD_EXCEPTION, 0); +} + +void +XLAT(void) +{ + + CPU_WORKCLOCK(5); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + CPU_AL = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_BX + CPU_AL); + } else { + CPU_AL = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_EBX + CPU_AL); + } +} + +void +_CPUID(void) +{ + switch (CPU_EAX) { + case 0: + CPU_EAX = 1; + CPU_EBX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+0))); + CPU_EDX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+4))); + CPU_ECX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+8))); + break; + + case 1: + CPU_EAX = (((i386cpuid.cpu_family >> 4) & 0xff) << 20) | (((i386cpuid.cpu_model >> 4) & 0xf) << 16) | + ((i386cpuid.cpu_family & 0xf) << 8) | ((i386cpuid.cpu_model & 0xf) << 4) | (i386cpuid.cpu_stepping & 0xf); + CPU_EBX = i386cpuid.cpu_brandid; + if (i386cpuid.cpu_feature & CPU_FEATURE_CLFSH) + { + CPU_EBX |= (8) << 8; // キャッシュラインサイズ + } + CPU_ECX = i386cpuid.cpu_feature_ecx & CPU_FEATURES_ECX_ALL; + CPU_EDX = i386cpuid.cpu_feature & CPU_FEATURES_ALL; + break; + + case 2: + if(i386cpuid.cpu_family >= 6){ + CPU_EAX = 0x1; + CPU_EBX = 0; + CPU_ECX = 0; + CPU_EDX = 0x43; // 512KB L2 Cache のふり + }else{ + CPU_EAX = 0; + CPU_EBX = 0; + CPU_ECX = 0; + CPU_EDX = 0; + } + break; + + case 0x80000000: + CPU_EAX = 0x80000004; + if(strncmp(i386cpuid.cpu_vendor, CPU_VENDOR_AMD, 12)==0){ // AMD判定 + CPU_EBX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+0))); + CPU_EDX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+4))); + CPU_ECX = LOADINTELDWORD(((UINT8*)(i386cpuid.cpu_vendor+8))); + }else{ + CPU_EBX = 0; + CPU_ECX = 0; + CPU_EDX = 0; + } + break; + + case 0x80000001: + if (strncmp(i386cpuid.cpu_vendor, CPU_VENDOR_AMD, 12) == 0) + { // AMD判定 + if (i386cpuid.cpu_family >= 6 || (i386cpuid.cpu_family == 5 && i386cpuid.cpu_model >= 6)) + { + CPU_EAX = ((i386cpuid.cpu_family + 1) << 8) | (i386cpuid.cpu_model << 4) | i386cpuid.cpu_stepping; + } + else + { + CPU_EAX = (i386cpuid.cpu_family << 8) | (i386cpuid.cpu_model << 4) | i386cpuid.cpu_stepping; + } + }else{ + CPU_EAX = 0; + } + CPU_EBX = 0; + CPU_ECX = i386cpuid.cpu_feature_ex_ecx & CPU_FEATURES_EX_ECX_ALL; + CPU_EDX = i386cpuid.cpu_feature_ex & CPU_FEATURES_EX_ALL; + break; + + case 0x80000002: + case 0x80000003: + case 0x80000004: + { + UINT32 clkMHz; + char cpu_brandstringbuf[64] = {0}; + int stroffset = (CPU_EAX - 0x80000002) * 16; + clkMHz = pccore.realclock/1000/1000; + sprintf(cpu_brandstringbuf, "%s%u MHz", i386cpuid.cpu_brandstring, clkMHz); + CPU_EAX = LOADINTELDWORD(((UINT8*)(cpu_brandstringbuf + stroffset + 0))); + CPU_EBX = LOADINTELDWORD(((UINT8*)(cpu_brandstringbuf + stroffset + 4))); + CPU_ECX = LOADINTELDWORD(((UINT8*)(cpu_brandstringbuf + stroffset + 8))); + CPU_EDX = LOADINTELDWORD(((UINT8*)(cpu_brandstringbuf + stroffset + 12))); + } + + break; + } +} + +/* undoc 8086 */ +void +SALC(void) +{ + + CPU_WORKCLOCK(2); + CPU_AL = (CPU_FLAGL & C_FLAG) ? 0xff : 0; +} + +/* undoc 286 */ +void +LOADALL286(void) +{ + + ia32_panic("LOADALL286: not implemented yet."); +} + +/* undoc 386 */ +void +LOADALL(void) +{ + + ia32_panic("LOADALL: not implemented yet."); +} + +void +OpSize(void) +{ + + CPU_INST_OP32 = !CPU_STATSAVE.cpu_inst_default.op_32; +} + +void +AddrSize(void) +{ + + CPU_INST_AS32 = !CPU_STATSAVE.cpu_inst_default.as_32; +} + +void +_2byte_ESC16(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); +#ifdef USE_SSE + if(insttable_2byte660F_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32){ + (*insttable_2byte660F_32[op])(); + }else if(insttable_2byteF20F_32[op] && CPU_INST_REPUSE == 0xf2){ + (*insttable_2byteF20F_32[op])(); + }else if(insttable_2byteF30F_32[op] && CPU_INST_REPUSE == 0xf3){ + (*insttable_2byteF30F_32[op])(); + }else{ + (*insttable_2byte[0][op])(); + } +#else + (*insttable_2byte[0][op])(); +#endif +} + +void +_2byte_ESC32(void) +{ + UINT32 op; + + GET_MODRM_PCBYTE(op); +#ifdef USE_SSE + if(insttable_2byte660F_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32){ + (*insttable_2byte660F_32[op])(); + }else if(insttable_2byteF20F_32[op] && CPU_INST_REPUSE == 0xf2){ + (*insttable_2byteF20F_32[op])(); + }else if(insttable_2byteF30F_32[op] && CPU_INST_REPUSE == 0xf3){ + (*insttable_2byteF30F_32[op])(); + }else{ + (*insttable_2byte[1][op])(); + } +#else + (*insttable_2byte[1][op])(); +#endif +} + +void +_3byte_38ESC(void) +{ + UINT32 op; + +#ifdef USE_SSSE3 + if(!(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSSE3)){ + EXCEPTION(UD_EXCEPTION, 0); + } else { + GET_MODRM_PCBYTE(op); + if(insttable_3byte660F38_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32){ + (*insttable_3byte660F38_32[op])(); + return; + }else if(insttable_3byteF20F38_32[op] && CPU_INST_REPUSE == 0xf2){ + (*insttable_3byteF20F38_32[op])(); + return; + }else if(insttable_2byte0F38_32[op]){ + (*insttable_2byte0F38_32[op])(); + return; + }else{ + EXCEPTION(UD_EXCEPTION, 0); + } + } +#else + EXCEPTION(UD_EXCEPTION, 0); +#endif +} + +void +_3byte_38ESC_16(void) +{ + UINT32 op; + +#ifdef USE_SSSE3 + if(!(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSSE3)){ + EXCEPTION(UD_EXCEPTION, 0); + } else { + GET_MODRM_PCBYTE(op); + if(insttable_3byte660F38_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32){ + (*insttable_3byte660F38_32[op])(); + return; + }else if(insttable_3byteF20F38_16[op] && CPU_INST_REPUSE == 0xf2){ + (*insttable_3byteF20F38_16[op])(); + return; + }else if(insttable_2byte0F38_32[op]){ + (*insttable_2byte0F38_32[op])(); + return; + }else{ + EXCEPTION(UD_EXCEPTION, 0); + } + } +#else + EXCEPTION(UD_EXCEPTION, 0); +#endif +} + +void +_3byte_3AESC(void) +{ + UINT32 op; + +#ifdef USE_SSSE3 + if(!(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSSE3)){ + EXCEPTION(UD_EXCEPTION, 0); + } else { + GET_MODRM_PCBYTE(op); + if(insttable_3byte660F3A_32[op] && CPU_INST_OP32 == !CPU_STATSAVE.cpu_inst_default.op_32){ + (*insttable_3byte660F3A_32[op])(); + return; + }else if(insttable_2byte0F3A_32[op]){ + (*insttable_2byte0F3A_32[op])(); + return; + }else{ + EXCEPTION(UD_EXCEPTION, 0); + } + } +#else + EXCEPTION(UD_EXCEPTION, 0); +#endif +} + +void +Prefix_ES(void) +{ + + CPU_INST_SEGUSE = 1; + CPU_INST_SEGREG_INDEX = CPU_ES_INDEX; +} + +void +Prefix_CS(void) +{ + + CPU_INST_SEGUSE = 1; + CPU_INST_SEGREG_INDEX = CPU_CS_INDEX; +} + +void +Prefix_SS(void) +{ + + CPU_INST_SEGUSE = 1; + CPU_INST_SEGREG_INDEX = CPU_SS_INDEX; +} + +void +Prefix_DS(void) +{ + + CPU_INST_SEGUSE = 1; + CPU_INST_SEGREG_INDEX = CPU_DS_INDEX; +} + +void +Prefix_FS(void) +{ + + CPU_INST_SEGUSE = 1; + CPU_INST_SEGREG_INDEX = CPU_FS_INDEX; +} + +void +Prefix_GS(void) +{ + + CPU_INST_SEGUSE = 1; + CPU_INST_SEGREG_INDEX = CPU_GS_INDEX; +} diff --git a/i386c/ia32/instructions/misc_inst.h b/i386c/ia32/instructions/misc_inst.h old mode 100755 new mode 100644 index 080a7f94..b244f117 --- a/i386c/ia32/instructions/misc_inst.h +++ b/i386c/ia32/instructions/misc_inst.h @@ -1,66 +1,66 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_MISC_H__ -#define IA32_CPU_INSTRUCTION_MISC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -void LEA_GwM(void); -void LEA_GdM(void); -void _NOP(void); -void UD2(void); -void XLAT(void); -void _CPUID(void); - -void SALC(void); /* undoc 8086 */ -void LOADALL286(void); /* undoc 286 */ -void LOADALL(void); /* undoc 386 */ - -void OpSize(void); -void AddrSize(void); -void _2byte_ESC16(void); -void _2byte_ESC32(void); -void _3byte_38ESC(void); -void _3byte_38ESC_16(void); -void _3byte_3AESC(void); -void Prefix_ES(void); -void Prefix_CS(void); -void Prefix_SS(void); -void Prefix_DS(void); -void Prefix_FS(void); -void Prefix_GS(void); - -//void _2byte_Prefix660F_32(void); -//void _2byte_PrefixF20F_32(void); -//void _2byte_PrefixF30F_32(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_MISC_H__ */ +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_MISC_H__ +#define IA32_CPU_INSTRUCTION_MISC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void LEA_GwM(void); +void LEA_GdM(void); +void _NOP(void); +void UD2(void); +void XLAT(void); +void _CPUID(void); + +void SALC(void); /* undoc 8086 */ +void LOADALL286(void); /* undoc 286 */ +void LOADALL(void); /* undoc 386 */ + +void OpSize(void); +void AddrSize(void); +void _2byte_ESC16(void); +void _2byte_ESC32(void); +void _3byte_38ESC(void); +void _3byte_38ESC_16(void); +void _3byte_3AESC(void); +void Prefix_ES(void); +void Prefix_CS(void); +void Prefix_SS(void); +void Prefix_DS(void); +void Prefix_FS(void); +void Prefix_GS(void); + +//void _2byte_Prefix660F_32(void); +//void _2byte_PrefixF20F_32(void); +//void _2byte_PrefixF30F_32(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_MISC_H__ */ diff --git a/i386c/ia32/instructions/mmx/3dnow.c b/i386c/ia32/instructions/mmx/3dnow.c old mode 100755 new mode 100644 index 2f3a5269..299014c2 --- a/i386c/ia32/instructions/mmx/3dnow.c +++ b/i386c/ia32/instructions/mmx/3dnow.c @@ -1,864 +1,864 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include - -#include - -#include -#include "ia32/ia32.mcr" - -#include "ia32/instructions/mmx/3dnow.h" - -#if defined(USE_3DNOW) && defined(USE_MMX) && defined(USE_FPU) - -#define CPU_MMXWORKCLOCK(a) CPU_WORKCLOCK(2) - -// 3DNow! -void AMD3DNOW_PAVGUSB_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PAVGUSB_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PF2ID_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PF2ID_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFACC_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFACC_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFADD_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFADD_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFCMPEQ_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFCMPEQ_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFCMPGE_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFCMPGE_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFCMPGT_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFCMPGT_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFMAX_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFMAX_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFMIN_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFMIN_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFMUL_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFMUL_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFRCP_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFRCP_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFRCPIT1_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFRCPIT1_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFRCPIT2_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFRCPIT2_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFRSQIT1_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFRSQIT1_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFRSQRT_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFRSQRT_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFSUB_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFSUB_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFSUBR_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFSUBR_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PI2FD_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PI2FD_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PMULHRW_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PMULHRW_MEM(UINT8 reg1, UINT32 memaddr); - -// Enhanced 3DNow! -void AMD3DNOW_PF2IW_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PF2IW_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PI2FW_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PI2FW_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFNACC_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFNACC_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PFPNACC_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PFPNACC_MEM(UINT8 reg1, UINT32 memaddr); - -void AMD3DNOW_PSWAPD_REG(UINT8 reg1, UINT8 reg2); -void AMD3DNOW_PSWAPD_MEM(UINT8 reg1, UINT32 memaddr); - - -static INLINE void -AMD3DNOW_check_NM_EXCEPTION(){ - // 3DNow!なしならUD(無効オペコード例外)を発生させる - if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX) || !(i386cpuid.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ - EXCEPTION(UD_EXCEPTION, 0); - } - // エミュレーションならUD(無効オペコード例外)を発生させる - if(CPU_CR0 & CPU_CR0_EM){ - EXCEPTION(UD_EXCEPTION, 0); - } - // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる - if (CPU_CR0 & CPU_CR0_TS) { - EXCEPTION(NM_EXCEPTION, 0); - } -} - -static INLINE void -AMD3DNOW_setTag(void) -{ - int i; - - if(!FPU_STAT.mmxenable){ - FPU_STAT.mmxenable = 1; - //FPU_CTRLWORD = 0x27F; - for (i = 0; i < FPU_REG_NUM; i++) { - FPU_STAT.tag[i] = TAG_Valid; -#ifdef SUPPORT_FPU_DOSBOX2 - FPU_STAT.int_regvalid[i] = 0; -#endif - FPU_STAT.reg[i].ul.ext = 0xffff; - } - } - FPU_STAT_TOP = 0; - FPU_STATUSWORD &= ~0x3800; - FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; -} - -/* - * 3DNow! interface - */ -void -AMD3DNOW_FEMMS(void) -{ - int i; - - // MMXなしならUD(無効オペコード例外)を発生させる - if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX)){ - EXCEPTION(UD_EXCEPTION, 0); - } - // エミュレーションならUD(無効オペコード例外)を発生させる - if(CPU_CR0 & CPU_CR0_EM){ - EXCEPTION(UD_EXCEPTION, 0); - } - // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる - if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - CPU_WORKCLOCK(2); - for (i = 0; i < FPU_REG_NUM; i++) { - FPU_STAT.tag[i] = TAG_Empty; - } - FPU_STAT_TOP = 0; - FPU_STATUSWORD &= ~0x3800; - FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; - FPU_STAT.mmxenable = 0; -} - -void -AMD3DNOW_PREFETCH(void) -{ - UINT32 op; - UINT idx, sub; - - AMD3DNOW_check_NM_EXCEPTION(); - AMD3DNOW_setTag(); - CPU_MMXWORKCLOCK(a); - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - // Invalid Opcode - EXCEPTION(UD_EXCEPTION, 0); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - switch(idx){ - case 1: - // PREFETCHW - break; - case 0: - // PREFETCH - default: - // Reserved(=PREFETCH) - break; - } - // XXX: 何もしない - } -} - -void -AMD3DNOW_F0(void) -{ - UINT32 op; - UINT idx, sub; - UINT8 suffix; - UINT8 reg1; - - AMD3DNOW_check_NM_EXCEPTION(); - AMD3DNOW_setTag(); - CPU_MMXWORKCLOCK(a); - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - // mmreg1, mmreg2 - UINT8 reg2; - reg1 = idx; - reg2 = sub; - GET_MODRM_PCBYTE((suffix)); - switch(suffix){ - case AMD3DNOW_SUFFIX_PAVGUSB: - AMD3DNOW_PAVGUSB_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFADD: - AMD3DNOW_PFADD_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFSUB: - AMD3DNOW_PFSUB_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFSUBR: - AMD3DNOW_PFSUBR_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFACC: - AMD3DNOW_PFACC_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFCMPGE: - AMD3DNOW_PFCMPGE_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFCMPGT: - AMD3DNOW_PFCMPGT_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFCMPEQ: - AMD3DNOW_PFCMPEQ_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFMIN: - AMD3DNOW_PFMIN_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFMAX: - AMD3DNOW_PFMAX_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PI2FD: - AMD3DNOW_PI2FD_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PF2ID: - AMD3DNOW_PI2FD_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFRCP: - AMD3DNOW_PFRCP_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFRSQRT: - AMD3DNOW_PFRSQRT_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFMUL: - AMD3DNOW_PFMUL_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFRCPIT1: - AMD3DNOW_PFRCPIT1_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFRSQIT1: - AMD3DNOW_PFRSQIT1_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFRCPIT2: - AMD3DNOW_PFRCPIT2_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PMULHRW: - AMD3DNOW_PMULHRW_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PF2IW: - AMD3DNOW_PF2IW_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PI2FW: - AMD3DNOW_PI2FW_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFNACC: - AMD3DNOW_PFNACC_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PFPNACC: - AMD3DNOW_PFPNACC_REG(reg1, reg2); - break; - case AMD3DNOW_SUFFIX_PSWAPD: - AMD3DNOW_PSWAPD_REG(reg1, reg2); - break; - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } else { - // mmreg1, mem - UINT32 memaddr; - reg1 = idx; - memaddr = calc_ea_dst(op); - GET_MODRM_PCBYTE((suffix)); - switch(suffix){ - case AMD3DNOW_SUFFIX_PAVGUSB: - AMD3DNOW_PAVGUSB_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFADD: - AMD3DNOW_PFADD_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFSUB: - AMD3DNOW_PFSUB_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFSUBR: - AMD3DNOW_PFSUBR_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFACC: - AMD3DNOW_PFACC_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFCMPGE: - AMD3DNOW_PFCMPGE_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFCMPGT: - AMD3DNOW_PFCMPGT_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFCMPEQ: - AMD3DNOW_PFCMPEQ_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFMIN: - AMD3DNOW_PFMIN_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFMAX: - AMD3DNOW_PFMAX_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PI2FD: - AMD3DNOW_PI2FD_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PF2ID: - AMD3DNOW_PI2FD_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFRCP: - AMD3DNOW_PFRCP_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFRSQRT: - AMD3DNOW_PFRSQRT_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFMUL: - AMD3DNOW_PFMUL_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFRCPIT1: - AMD3DNOW_PFRCPIT1_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFRSQIT1: - AMD3DNOW_PFRSQIT1_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFRCPIT2: - AMD3DNOW_PFRCPIT2_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PMULHRW: - AMD3DNOW_PMULHRW_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PF2IW: - AMD3DNOW_PF2IW_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PI2FW: - AMD3DNOW_PI2FW_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFNACC: - AMD3DNOW_PFNACC_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PFPNACC: - AMD3DNOW_PFPNACC_MEM(reg1, memaddr); - break; - case AMD3DNOW_SUFFIX_PSWAPD: - AMD3DNOW_PSWAPD_MEM(reg1, memaddr); - break; - default: - EXCEPTION(UD_EXCEPTION, 0); - break; - } - } -} - -// PAVGUSB -void AMD3DNOW_PAVGUSB(UINT8 *data1, UINT8 *data2){ - int i; - for(i=0;i<8;i++){ - data1[i] = (UINT8)(((UINT16)(data1[i]) + (UINT16)(data2[i]) + 1) / 2); - } -} -void AMD3DNOW_PAVGUSB_REG(UINT8 reg1, UINT8 reg2){ - UINT8 *data1 = (UINT8*)(&(FPU_STAT.reg[reg1])); - UINT8 *data2 = (UINT8*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PAVGUSB(data1, data2); -} -void AMD3DNOW_PAVGUSB_MEM(UINT8 reg1, UINT32 memaddr){ - UINT8 *data1 = (UINT8*)(&(FPU_STAT.reg[reg1])); - UINT8 data2[8]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PAVGUSB(data1, data2); -} - -// PF2ID -void AMD3DNOW_PF2ID(SINT32 *data1, float *data2){ - int i; - for(i=0;i<2;i++){ - if (data2[i] >= (float)((SINT32)0x7fffffff)){ - data1[i] = (SINT32)0x7fffffff; - }else if(data2[i] <= (float)((SINT32)0x80000000)){ - data1[i] = (SINT32)0x80000000; - }else{ - data1[i] = (SINT32)data2[i]; - } - } -} -void AMD3DNOW_PF2ID_REG(UINT8 reg1, UINT8 reg2){ - SINT32 *data1 = (SINT32*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PF2ID(data1, data2); -} -void AMD3DNOW_PF2ID_MEM(UINT8 reg1, UINT32 memaddr){ - SINT32 *data1 = (SINT32*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PF2ID(data1, data2); -} - -// PFACC -void AMD3DNOW_PFACC(float *data1, float *data2){ - float temp[2]; - temp[0] = data2[0]; - temp[1] = data2[1]; - data1[0] = data1[0] + data1[1]; - data1[1] = temp[0] + temp[1]; -} -void AMD3DNOW_PFACC_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFACC(data1, data2); -} -void AMD3DNOW_PFACC_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFACC(data1, data2); -} - -// PFADD -void AMD3DNOW_PFADD(float *data1, float *data2){ - data1[0] = data1[0] + data2[0]; - data1[1] = data1[1] + data2[1]; -} -void AMD3DNOW_PFADD_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFADD(data1, data2); -} -void AMD3DNOW_PFADD_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFADD(data1, data2); -} - -// PFCMPEQ -void AMD3DNOW_PFCMPEQ(float *data1, float *data2){ - *((UINT32*)(data1+0)) = (data1[0] == data2[0] ? 0xffffffff : 0x00000000); - *((UINT32*)(data1+1)) = (data1[1] == data2[1] ? 0xffffffff : 0x00000000); -} -void AMD3DNOW_PFCMPEQ_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFCMPEQ(data1, data2); -} -void AMD3DNOW_PFCMPEQ_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFCMPEQ(data1, data2); -} - -// PFCMPGE -void AMD3DNOW_PFCMPGE(float *data1, float *data2){ - *((UINT32*)(data1+0)) = (data1[0] >= data2[0] ? 0xffffffff : 0x00000000); - *((UINT32*)(data1+1)) = (data1[1] >= data2[1] ? 0xffffffff : 0x00000000); -} -void AMD3DNOW_PFCMPGE_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFCMPGE(data1, data2); -} -void AMD3DNOW_PFCMPGE_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFCMPGE(data1, data2); -} - -// PFCMPGT -void AMD3DNOW_PFCMPGT(float *data1, float *data2){ - *((UINT32*)(data1+0)) = (data1[0] > data2[0] ? 0xffffffff : 0x00000000); - *((UINT32*)(data1+1)) = (data1[1] > data2[1] ? 0xffffffff : 0x00000000); -} -void AMD3DNOW_PFCMPGT_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFCMPGT(data1, data2); -} -void AMD3DNOW_PFCMPGT_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFCMPGT(data1, data2); -} - -// PFMAX -void AMD3DNOW_PFMAX(float *data1, float *data2){ - data1[0] = (data1[0] > data2[0] ? data1[0] : data2[0]); - data1[1] = (data1[1] > data2[1] ? data1[1] : data2[1]); -} -void AMD3DNOW_PFMAX_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFMAX(data1, data2); -} -void AMD3DNOW_PFMAX_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFMAX(data1, data2); -} - -// PFMIN -void AMD3DNOW_PFMIN(float *data1, float *data2){ - data1[0] = (data1[0] < data2[0] ? data1[0] : data2[0]); - data1[1] = (data1[1] < data2[1] ? data1[1] : data2[1]); -} -void AMD3DNOW_PFMIN_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFMIN(data1, data2); -} -void AMD3DNOW_PFMIN_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFMIN(data1, data2); -} - -// PFMUL -void AMD3DNOW_PFMUL(float *data1, float *data2){ - data1[0] = data1[0] * data2[0]; - data1[1] = data1[1] * data2[1]; -} -void AMD3DNOW_PFMUL_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFMUL(data1, data2); -} -void AMD3DNOW_PFMUL_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFMUL(data1, data2); -} - -// PFRCP -void AMD3DNOW_PFRCP(float *data1, float *data2){ - // XXX: ただのコピー - data1[0] = 1.0f / data2[0]; - data1[1] = 1.0f / data2[1]; -} -void AMD3DNOW_PFRCP_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFRCP(data1, data2); -} -void AMD3DNOW_PFRCP_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFRCP(data1, data2); -} - -// PFRCPIT1 -void AMD3DNOW_PFRCPIT1(float *data1, float *data2){ - // XXX: ただのコピーで代替 - data1[0] = data2[0]; - data1[1] = data2[1]; -} -void AMD3DNOW_PFRCPIT1_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFRCPIT1(data1, data2); -} -void AMD3DNOW_PFRCPIT1_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFRCPIT1(data1, data2); -} - -// PFRCPIT2 -void AMD3DNOW_PFRCPIT2(float *data1, float *data2){ - // XXX: ただのコピーで代替 - data1[0] = data2[0]; - data1[1] = data2[1]; -} -void AMD3DNOW_PFRCPIT2_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFRCPIT2(data1, data2); -} -void AMD3DNOW_PFRCPIT2_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFRCPIT2(data1, data2); -} - -// PFRSQIT1 -void AMD3DNOW_PFRSQIT1(float *data1, float *data2){ - // XXX: ただのコピーで代替 - data1[0] = data2[0]; - data1[1] = data2[1]; -} -void AMD3DNOW_PFRSQIT1_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFRSQIT1(data1, data2); -} -void AMD3DNOW_PFRSQIT1_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFRSQIT1(data1, data2); -} - -// PFRSQRT -void AMD3DNOW_PFRSQRT(float *data1, float *data2){ - data1[0] = (float)(1.0f / sqrt(data2[0])); - data1[1] = (float)(1.0f / sqrt(data2[1])); -} -void AMD3DNOW_PFRSQRT_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFRSQRT(data1, data2); -} -void AMD3DNOW_PFRSQRT_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFRSQRT(data1, data2); -} - -// PFSUB -void AMD3DNOW_PFSUB(float *data1, float *data2){ - data1[0] = data1[0] - data2[0]; - data1[1] = data1[1] - data2[1]; -} -void AMD3DNOW_PFSUB_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFSUB(data1, data2); -} -void AMD3DNOW_PFSUB_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFSUB(data1, data2); -} - -// PFSUBR -void AMD3DNOW_PFSUBR(float *data1, float *data2){ - data1[0] = data2[0] - data1[0]; - data1[1] = data2[1] - data1[1]; -} -void AMD3DNOW_PFSUBR_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFSUBR(data1, data2); -} -void AMD3DNOW_PFSUBR_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFSUBR(data1, data2); -} - -// PI2FD -void AMD3DNOW_PI2FD(float *data1, SINT32 *data2){ - data1[0] = (float)(data2[0]); - data1[1] = (float)(data2[1]); -} -void AMD3DNOW_PI2FD_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - SINT32 *data2 = (SINT32*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PI2FD(data1, data2); -} -void AMD3DNOW_PI2FD_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - SINT32 data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PI2FD(data1, data2); -} - -// PMULHRW -void AMD3DNOW_PMULHRW(SINT16 *data1, SINT16 *data2){ - int i; - for(i=0;i<4;i++){ - data1[i] = (UINT16)((((UINT32)data1[i] * (UINT32)data2[i] + 0x8000) >> 16) & 0xffff); - } -} -void AMD3DNOW_PMULHRW_REG(UINT8 reg1, UINT8 reg2){ - SINT16 *data1 = (SINT16*)(&(FPU_STAT.reg[reg1])); - SINT16 *data2 = (SINT16*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PMULHRW(data1, data2); -} -void AMD3DNOW_PMULHRW_MEM(UINT8 reg1, UINT32 memaddr){ - SINT16 *data1 = (SINT16*)(&(FPU_STAT.reg[reg1])); - SINT16 data2[4]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PMULHRW(data1, data2); -} - -/* - * Enhanced 3DNow! interface - */ -// PF2IW -void AMD3DNOW_PF2IW(SINT32 *data1, float *data2){ - int i; - for(i=0;i<2;i++){ - if (data2[i] >= (float)((SINT16)0x7fff)){ - data1[i] = (SINT16)0x7fff; - }else if(data2[i] <= (float)((SINT16)0x8000)){ - data1[i] = (SINT16)0x8000; - }else{ - data1[i] = (SINT16)data2[i]; - } - } -} -void AMD3DNOW_PF2IW_REG(UINT8 reg1, UINT8 reg2){ - SINT32 *data1 = (SINT32*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PF2IW(data1, data2); -} -void AMD3DNOW_PF2IW_MEM(UINT8 reg1, UINT32 memaddr){ - SINT32 *data1 = (SINT32*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PF2IW(data1, data2); -} - -// PI2FW -void AMD3DNOW_PI2FW(float *data1, SINT16 *data2){ - data1[0] = (float)(data2[0]); - data1[1] = (float)(data2[2]); -} -void AMD3DNOW_PI2FW_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - SINT16 *data2 = (SINT16*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PI2FW(data1, data2); -} -void AMD3DNOW_PI2FW_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - SINT16 data2[4]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PI2FW(data1, data2); -} - -// PFNACC -void AMD3DNOW_PFNACC(float *data1, float *data2){ - float temp[2]; - temp[0] = data2[0]; - temp[1] = data2[1]; - data1[0] = data1[0] - data1[1]; - data1[1] = temp[0] - temp[1]; -} -void AMD3DNOW_PFNACC_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFNACC(data1, data2); -} -void AMD3DNOW_PFNACC_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFNACC(data1, data2); -} - -// PFPNACC -void AMD3DNOW_PFPNACC(float *data1, float *data2){ - float temp[2]; - temp[0] = data2[0]; - temp[1] = data2[1]; - data1[0] = data1[0] - data1[1]; - data1[1] = temp[0] + temp[1]; -} -void AMD3DNOW_PFPNACC_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PFPNACC(data1, data2); -} -void AMD3DNOW_PFPNACC_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PFPNACC(data1, data2); -} - -// PSWAPD -void AMD3DNOW_PSWAPD(float *data1, float *data2){ - float temp[2]; - temp[0] = data2[0]; - temp[1] = data2[1]; - data1[0] = temp[1]; - data1[1] = temp[0]; -} -void AMD3DNOW_PSWAPD_REG(UINT8 reg1, UINT8 reg2){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float *data2 = (float*)(&(FPU_STAT.reg[reg2])); - AMD3DNOW_PSWAPD(data1, data2); -} -void AMD3DNOW_PSWAPD_MEM(UINT8 reg1, UINT32 memaddr){ - float *data1 = (float*)(&(FPU_STAT.reg[reg1])); - float data2[2]; - *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); - AMD3DNOW_PSWAPD(data1, data2); -} - -#else - -/* - * 3DNow! interface - */ -void AMD3DNOW_F0(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void AMD3DNOW_FEMMS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void AMD3DNOW_PREFETCH(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include + +#include + +#include +#include "ia32/ia32.mcr" + +#include "ia32/instructions/mmx/3dnow.h" + +#if defined(USE_3DNOW) && defined(USE_MMX) && defined(USE_FPU) + +#define CPU_MMXWORKCLOCK(a) CPU_WORKCLOCK(2) + +// 3DNow! +void AMD3DNOW_PAVGUSB_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PAVGUSB_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PF2ID_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PF2ID_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFACC_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFACC_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFADD_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFADD_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFCMPEQ_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFCMPEQ_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFCMPGE_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFCMPGE_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFCMPGT_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFCMPGT_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFMAX_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFMAX_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFMIN_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFMIN_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFMUL_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFMUL_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFRCP_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFRCP_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFRCPIT1_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFRCPIT1_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFRCPIT2_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFRCPIT2_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFRSQIT1_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFRSQIT1_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFRSQRT_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFRSQRT_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFSUB_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFSUB_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFSUBR_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFSUBR_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PI2FD_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PI2FD_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PMULHRW_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PMULHRW_MEM(UINT8 reg1, UINT32 memaddr); + +// Enhanced 3DNow! +void AMD3DNOW_PF2IW_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PF2IW_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PI2FW_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PI2FW_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFNACC_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFNACC_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PFPNACC_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PFPNACC_MEM(UINT8 reg1, UINT32 memaddr); + +void AMD3DNOW_PSWAPD_REG(UINT8 reg1, UINT8 reg2); +void AMD3DNOW_PSWAPD_MEM(UINT8 reg1, UINT32 memaddr); + + +static INLINE void +AMD3DNOW_check_NM_EXCEPTION(){ + // 3DNow!なしならUD(無効オペコード例外)を発生させる + if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX) || !(i386cpuid.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ + EXCEPTION(UD_EXCEPTION, 0); + } + // エミュレーションならUD(無効オペコード例外)を発生させる + if(CPU_CR0 & CPU_CR0_EM){ + EXCEPTION(UD_EXCEPTION, 0); + } + // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる + if (CPU_CR0 & CPU_CR0_TS) { + EXCEPTION(NM_EXCEPTION, 0); + } +} + +static INLINE void +AMD3DNOW_setTag(void) +{ + int i; + + if(!FPU_STAT.mmxenable){ + FPU_STAT.mmxenable = 1; + //FPU_CTRLWORD = 0x27F; + for (i = 0; i < FPU_REG_NUM; i++) { + FPU_STAT.tag[i] = TAG_Valid; +#ifdef SUPPORT_FPU_DOSBOX2 + FPU_STAT.int_regvalid[i] = 0; +#endif + FPU_STAT.reg[i].ul.ext = 0xffff; + } + } + FPU_STAT_TOP = 0; + FPU_STATUSWORD &= ~0x3800; + FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; +} + +/* + * 3DNow! interface + */ +void +AMD3DNOW_FEMMS(void) +{ + int i; + + // MMXなしならUD(無効オペコード例外)を発生させる + if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX)){ + EXCEPTION(UD_EXCEPTION, 0); + } + // エミュレーションならUD(無効オペコード例外)を発生させる + if(CPU_CR0 & CPU_CR0_EM){ + EXCEPTION(UD_EXCEPTION, 0); + } + // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる + if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + CPU_WORKCLOCK(2); + for (i = 0; i < FPU_REG_NUM; i++) { + FPU_STAT.tag[i] = TAG_Empty; + } + FPU_STAT_TOP = 0; + FPU_STATUSWORD &= ~0x3800; + FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; + FPU_STAT.mmxenable = 0; +} + +void +AMD3DNOW_PREFETCH(void) +{ + UINT32 op; + UINT idx, sub; + + AMD3DNOW_check_NM_EXCEPTION(); + AMD3DNOW_setTag(); + CPU_MMXWORKCLOCK(a); + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + // Invalid Opcode + EXCEPTION(UD_EXCEPTION, 0); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + switch(idx){ + case 1: + // PREFETCHW + break; + case 0: + // PREFETCH + default: + // Reserved(=PREFETCH) + break; + } + // XXX: 何もしない + } +} + +void +AMD3DNOW_F0(void) +{ + UINT32 op; + UINT idx, sub; + UINT8 suffix; + UINT8 reg1; + + AMD3DNOW_check_NM_EXCEPTION(); + AMD3DNOW_setTag(); + CPU_MMXWORKCLOCK(a); + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + // mmreg1, mmreg2 + UINT8 reg2; + reg1 = idx; + reg2 = sub; + GET_MODRM_PCBYTE((suffix)); + switch(suffix){ + case AMD3DNOW_SUFFIX_PAVGUSB: + AMD3DNOW_PAVGUSB_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFADD: + AMD3DNOW_PFADD_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFSUB: + AMD3DNOW_PFSUB_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFSUBR: + AMD3DNOW_PFSUBR_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFACC: + AMD3DNOW_PFACC_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFCMPGE: + AMD3DNOW_PFCMPGE_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFCMPGT: + AMD3DNOW_PFCMPGT_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFCMPEQ: + AMD3DNOW_PFCMPEQ_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFMIN: + AMD3DNOW_PFMIN_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFMAX: + AMD3DNOW_PFMAX_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PI2FD: + AMD3DNOW_PI2FD_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PF2ID: + AMD3DNOW_PI2FD_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFRCP: + AMD3DNOW_PFRCP_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFRSQRT: + AMD3DNOW_PFRSQRT_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFMUL: + AMD3DNOW_PFMUL_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFRCPIT1: + AMD3DNOW_PFRCPIT1_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFRSQIT1: + AMD3DNOW_PFRSQIT1_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFRCPIT2: + AMD3DNOW_PFRCPIT2_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PMULHRW: + AMD3DNOW_PMULHRW_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PF2IW: + AMD3DNOW_PF2IW_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PI2FW: + AMD3DNOW_PI2FW_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFNACC: + AMD3DNOW_PFNACC_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PFPNACC: + AMD3DNOW_PFPNACC_REG(reg1, reg2); + break; + case AMD3DNOW_SUFFIX_PSWAPD: + AMD3DNOW_PSWAPD_REG(reg1, reg2); + break; + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } else { + // mmreg1, mem + UINT32 memaddr; + reg1 = idx; + memaddr = calc_ea_dst(op); + GET_MODRM_PCBYTE((suffix)); + switch(suffix){ + case AMD3DNOW_SUFFIX_PAVGUSB: + AMD3DNOW_PAVGUSB_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFADD: + AMD3DNOW_PFADD_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFSUB: + AMD3DNOW_PFSUB_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFSUBR: + AMD3DNOW_PFSUBR_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFACC: + AMD3DNOW_PFACC_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFCMPGE: + AMD3DNOW_PFCMPGE_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFCMPGT: + AMD3DNOW_PFCMPGT_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFCMPEQ: + AMD3DNOW_PFCMPEQ_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFMIN: + AMD3DNOW_PFMIN_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFMAX: + AMD3DNOW_PFMAX_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PI2FD: + AMD3DNOW_PI2FD_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PF2ID: + AMD3DNOW_PI2FD_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFRCP: + AMD3DNOW_PFRCP_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFRSQRT: + AMD3DNOW_PFRSQRT_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFMUL: + AMD3DNOW_PFMUL_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFRCPIT1: + AMD3DNOW_PFRCPIT1_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFRSQIT1: + AMD3DNOW_PFRSQIT1_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFRCPIT2: + AMD3DNOW_PFRCPIT2_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PMULHRW: + AMD3DNOW_PMULHRW_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PF2IW: + AMD3DNOW_PF2IW_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PI2FW: + AMD3DNOW_PI2FW_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFNACC: + AMD3DNOW_PFNACC_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PFPNACC: + AMD3DNOW_PFPNACC_MEM(reg1, memaddr); + break; + case AMD3DNOW_SUFFIX_PSWAPD: + AMD3DNOW_PSWAPD_MEM(reg1, memaddr); + break; + default: + EXCEPTION(UD_EXCEPTION, 0); + break; + } + } +} + +// PAVGUSB +void AMD3DNOW_PAVGUSB(UINT8 *data1, UINT8 *data2){ + int i; + for(i=0;i<8;i++){ + data1[i] = (UINT8)(((UINT16)(data1[i]) + (UINT16)(data2[i]) + 1) / 2); + } +} +void AMD3DNOW_PAVGUSB_REG(UINT8 reg1, UINT8 reg2){ + UINT8 *data1 = (UINT8*)(&(FPU_STAT.reg[reg1])); + UINT8 *data2 = (UINT8*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PAVGUSB(data1, data2); +} +void AMD3DNOW_PAVGUSB_MEM(UINT8 reg1, UINT32 memaddr){ + UINT8 *data1 = (UINT8*)(&(FPU_STAT.reg[reg1])); + UINT8 data2[8]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PAVGUSB(data1, data2); +} + +// PF2ID +void AMD3DNOW_PF2ID(SINT32 *data1, float *data2){ + int i; + for(i=0;i<2;i++){ + if (data2[i] >= (float)((SINT32)0x7fffffff)){ + data1[i] = (SINT32)0x7fffffff; + }else if(data2[i] <= (float)((SINT32)0x80000000)){ + data1[i] = (SINT32)0x80000000; + }else{ + data1[i] = (SINT32)data2[i]; + } + } +} +void AMD3DNOW_PF2ID_REG(UINT8 reg1, UINT8 reg2){ + SINT32 *data1 = (SINT32*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PF2ID(data1, data2); +} +void AMD3DNOW_PF2ID_MEM(UINT8 reg1, UINT32 memaddr){ + SINT32 *data1 = (SINT32*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PF2ID(data1, data2); +} + +// PFACC +void AMD3DNOW_PFACC(float *data1, float *data2){ + float temp[2]; + temp[0] = data2[0]; + temp[1] = data2[1]; + data1[0] = data1[0] + data1[1]; + data1[1] = temp[0] + temp[1]; +} +void AMD3DNOW_PFACC_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFACC(data1, data2); +} +void AMD3DNOW_PFACC_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFACC(data1, data2); +} + +// PFADD +void AMD3DNOW_PFADD(float *data1, float *data2){ + data1[0] = data1[0] + data2[0]; + data1[1] = data1[1] + data2[1]; +} +void AMD3DNOW_PFADD_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFADD(data1, data2); +} +void AMD3DNOW_PFADD_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFADD(data1, data2); +} + +// PFCMPEQ +void AMD3DNOW_PFCMPEQ(float *data1, float *data2){ + *((UINT32*)(data1+0)) = (data1[0] == data2[0] ? 0xffffffff : 0x00000000); + *((UINT32*)(data1+1)) = (data1[1] == data2[1] ? 0xffffffff : 0x00000000); +} +void AMD3DNOW_PFCMPEQ_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFCMPEQ(data1, data2); +} +void AMD3DNOW_PFCMPEQ_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFCMPEQ(data1, data2); +} + +// PFCMPGE +void AMD3DNOW_PFCMPGE(float *data1, float *data2){ + *((UINT32*)(data1+0)) = (data1[0] >= data2[0] ? 0xffffffff : 0x00000000); + *((UINT32*)(data1+1)) = (data1[1] >= data2[1] ? 0xffffffff : 0x00000000); +} +void AMD3DNOW_PFCMPGE_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFCMPGE(data1, data2); +} +void AMD3DNOW_PFCMPGE_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFCMPGE(data1, data2); +} + +// PFCMPGT +void AMD3DNOW_PFCMPGT(float *data1, float *data2){ + *((UINT32*)(data1+0)) = (data1[0] > data2[0] ? 0xffffffff : 0x00000000); + *((UINT32*)(data1+1)) = (data1[1] > data2[1] ? 0xffffffff : 0x00000000); +} +void AMD3DNOW_PFCMPGT_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFCMPGT(data1, data2); +} +void AMD3DNOW_PFCMPGT_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFCMPGT(data1, data2); +} + +// PFMAX +void AMD3DNOW_PFMAX(float *data1, float *data2){ + data1[0] = (data1[0] > data2[0] ? data1[0] : data2[0]); + data1[1] = (data1[1] > data2[1] ? data1[1] : data2[1]); +} +void AMD3DNOW_PFMAX_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFMAX(data1, data2); +} +void AMD3DNOW_PFMAX_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFMAX(data1, data2); +} + +// PFMIN +void AMD3DNOW_PFMIN(float *data1, float *data2){ + data1[0] = (data1[0] < data2[0] ? data1[0] : data2[0]); + data1[1] = (data1[1] < data2[1] ? data1[1] : data2[1]); +} +void AMD3DNOW_PFMIN_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFMIN(data1, data2); +} +void AMD3DNOW_PFMIN_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFMIN(data1, data2); +} + +// PFMUL +void AMD3DNOW_PFMUL(float *data1, float *data2){ + data1[0] = data1[0] * data2[0]; + data1[1] = data1[1] * data2[1]; +} +void AMD3DNOW_PFMUL_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFMUL(data1, data2); +} +void AMD3DNOW_PFMUL_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFMUL(data1, data2); +} + +// PFRCP +void AMD3DNOW_PFRCP(float *data1, float *data2){ + // XXX: ただのコピー + data1[0] = 1.0f / data2[0]; + data1[1] = 1.0f / data2[1]; +} +void AMD3DNOW_PFRCP_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFRCP(data1, data2); +} +void AMD3DNOW_PFRCP_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFRCP(data1, data2); +} + +// PFRCPIT1 +void AMD3DNOW_PFRCPIT1(float *data1, float *data2){ + // XXX: ただのコピーで代替 + data1[0] = data2[0]; + data1[1] = data2[1]; +} +void AMD3DNOW_PFRCPIT1_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFRCPIT1(data1, data2); +} +void AMD3DNOW_PFRCPIT1_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFRCPIT1(data1, data2); +} + +// PFRCPIT2 +void AMD3DNOW_PFRCPIT2(float *data1, float *data2){ + // XXX: ただのコピーで代替 + data1[0] = data2[0]; + data1[1] = data2[1]; +} +void AMD3DNOW_PFRCPIT2_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFRCPIT2(data1, data2); +} +void AMD3DNOW_PFRCPIT2_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFRCPIT2(data1, data2); +} + +// PFRSQIT1 +void AMD3DNOW_PFRSQIT1(float *data1, float *data2){ + // XXX: ただのコピーで代替 + data1[0] = data2[0]; + data1[1] = data2[1]; +} +void AMD3DNOW_PFRSQIT1_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFRSQIT1(data1, data2); +} +void AMD3DNOW_PFRSQIT1_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFRSQIT1(data1, data2); +} + +// PFRSQRT +void AMD3DNOW_PFRSQRT(float *data1, float *data2){ + data1[0] = (float)(1.0f / sqrt(data2[0])); + data1[1] = (float)(1.0f / sqrt(data2[1])); +} +void AMD3DNOW_PFRSQRT_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFRSQRT(data1, data2); +} +void AMD3DNOW_PFRSQRT_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFRSQRT(data1, data2); +} + +// PFSUB +void AMD3DNOW_PFSUB(float *data1, float *data2){ + data1[0] = data1[0] - data2[0]; + data1[1] = data1[1] - data2[1]; +} +void AMD3DNOW_PFSUB_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFSUB(data1, data2); +} +void AMD3DNOW_PFSUB_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFSUB(data1, data2); +} + +// PFSUBR +void AMD3DNOW_PFSUBR(float *data1, float *data2){ + data1[0] = data2[0] - data1[0]; + data1[1] = data2[1] - data1[1]; +} +void AMD3DNOW_PFSUBR_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFSUBR(data1, data2); +} +void AMD3DNOW_PFSUBR_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFSUBR(data1, data2); +} + +// PI2FD +void AMD3DNOW_PI2FD(float *data1, SINT32 *data2){ + data1[0] = (float)(data2[0]); + data1[1] = (float)(data2[1]); +} +void AMD3DNOW_PI2FD_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + SINT32 *data2 = (SINT32*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PI2FD(data1, data2); +} +void AMD3DNOW_PI2FD_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + SINT32 data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PI2FD(data1, data2); +} + +// PMULHRW +void AMD3DNOW_PMULHRW(SINT16 *data1, SINT16 *data2){ + int i; + for(i=0;i<4;i++){ + data1[i] = (UINT16)((((UINT32)data1[i] * (UINT32)data2[i] + 0x8000) >> 16) & 0xffff); + } +} +void AMD3DNOW_PMULHRW_REG(UINT8 reg1, UINT8 reg2){ + SINT16 *data1 = (SINT16*)(&(FPU_STAT.reg[reg1])); + SINT16 *data2 = (SINT16*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PMULHRW(data1, data2); +} +void AMD3DNOW_PMULHRW_MEM(UINT8 reg1, UINT32 memaddr){ + SINT16 *data1 = (SINT16*)(&(FPU_STAT.reg[reg1])); + SINT16 data2[4]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PMULHRW(data1, data2); +} + +/* + * Enhanced 3DNow! interface + */ +// PF2IW +void AMD3DNOW_PF2IW(SINT32 *data1, float *data2){ + int i; + for(i=0;i<2;i++){ + if (data2[i] >= (float)((SINT16)0x7fff)){ + data1[i] = (SINT16)0x7fff; + }else if(data2[i] <= (float)((SINT16)0x8000)){ + data1[i] = (SINT16)0x8000; + }else{ + data1[i] = (SINT16)data2[i]; + } + } +} +void AMD3DNOW_PF2IW_REG(UINT8 reg1, UINT8 reg2){ + SINT32 *data1 = (SINT32*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PF2IW(data1, data2); +} +void AMD3DNOW_PF2IW_MEM(UINT8 reg1, UINT32 memaddr){ + SINT32 *data1 = (SINT32*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PF2IW(data1, data2); +} + +// PI2FW +void AMD3DNOW_PI2FW(float *data1, SINT16 *data2){ + data1[0] = (float)(data2[0]); + data1[1] = (float)(data2[2]); +} +void AMD3DNOW_PI2FW_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + SINT16 *data2 = (SINT16*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PI2FW(data1, data2); +} +void AMD3DNOW_PI2FW_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + SINT16 data2[4]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PI2FW(data1, data2); +} + +// PFNACC +void AMD3DNOW_PFNACC(float *data1, float *data2){ + float temp[2]; + temp[0] = data2[0]; + temp[1] = data2[1]; + data1[0] = data1[0] - data1[1]; + data1[1] = temp[0] - temp[1]; +} +void AMD3DNOW_PFNACC_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFNACC(data1, data2); +} +void AMD3DNOW_PFNACC_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFNACC(data1, data2); +} + +// PFPNACC +void AMD3DNOW_PFPNACC(float *data1, float *data2){ + float temp[2]; + temp[0] = data2[0]; + temp[1] = data2[1]; + data1[0] = data1[0] - data1[1]; + data1[1] = temp[0] + temp[1]; +} +void AMD3DNOW_PFPNACC_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PFPNACC(data1, data2); +} +void AMD3DNOW_PFPNACC_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PFPNACC(data1, data2); +} + +// PSWAPD +void AMD3DNOW_PSWAPD(float *data1, float *data2){ + float temp[2]; + temp[0] = data2[0]; + temp[1] = data2[1]; + data1[0] = temp[1]; + data1[1] = temp[0]; +} +void AMD3DNOW_PSWAPD_REG(UINT8 reg1, UINT8 reg2){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float *data2 = (float*)(&(FPU_STAT.reg[reg2])); + AMD3DNOW_PSWAPD(data1, data2); +} +void AMD3DNOW_PSWAPD_MEM(UINT8 reg1, UINT32 memaddr){ + float *data1 = (float*)(&(FPU_STAT.reg[reg1])); + float data2[2]; + *((UINT64*)data2) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, memaddr); + AMD3DNOW_PSWAPD(data1, data2); +} + +#else + +/* + * 3DNow! interface + */ +void AMD3DNOW_F0(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void AMD3DNOW_FEMMS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void AMD3DNOW_PREFETCH(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + #endif \ No newline at end of file diff --git a/i386c/ia32/instructions/mmx/3dnow.h b/i386c/ia32/instructions/mmx/3dnow.h old mode 100755 new mode 100644 index 9981d74e..ddcc868d --- a/i386c/ia32/instructions/mmx/3dnow.h +++ b/i386c/ia32/instructions/mmx/3dnow.h @@ -1,70 +1,70 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_MMX_AMD3DNOW_H__ -#define IA32_CPU_INSTRUCTION_MMX_AMD3DNOW_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -enum{ - AMD3DNOW_SUFFIX_PAVGUSB = 0xBF, - AMD3DNOW_SUFFIX_PFADD = 0x9E, - AMD3DNOW_SUFFIX_PFSUB = 0x9A, - AMD3DNOW_SUFFIX_PFSUBR = 0xAA, - AMD3DNOW_SUFFIX_PFACC = 0xAE, - AMD3DNOW_SUFFIX_PFCMPGE = 0x90, - AMD3DNOW_SUFFIX_PFCMPGT = 0xA0, - AMD3DNOW_SUFFIX_PFCMPEQ = 0xB0, - AMD3DNOW_SUFFIX_PFMIN = 0x94, - AMD3DNOW_SUFFIX_PFMAX = 0xA4, - AMD3DNOW_SUFFIX_PI2FD = 0x0D, - AMD3DNOW_SUFFIX_PF2ID = 0x1D, - AMD3DNOW_SUFFIX_PFRCP = 0x96, - AMD3DNOW_SUFFIX_PFRSQRT = 0x97, - AMD3DNOW_SUFFIX_PFMUL = 0xB4, - AMD3DNOW_SUFFIX_PFRCPIT1 = 0xA6, - AMD3DNOW_SUFFIX_PFRSQIT1 = 0xA7, - AMD3DNOW_SUFFIX_PFRCPIT2 = 0xB6, - AMD3DNOW_SUFFIX_PMULHRW = 0xB7, - AMD3DNOW_SUFFIX_PF2IW = 0x1C, - AMD3DNOW_SUFFIX_PI2FW = 0x0C, - AMD3DNOW_SUFFIX_PFNACC = 0x8A, - AMD3DNOW_SUFFIX_PFPNACC = 0x8E, - AMD3DNOW_SUFFIX_PSWAPD = 0xBB, -}; - -void AMD3DNOW_F0(void); - -void AMD3DNOW_FEMMS(void); - -void AMD3DNOW_PREFETCH(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_MMX_AMD3DNOW_H__ */ +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_MMX_AMD3DNOW_H__ +#define IA32_CPU_INSTRUCTION_MMX_AMD3DNOW_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +enum{ + AMD3DNOW_SUFFIX_PAVGUSB = 0xBF, + AMD3DNOW_SUFFIX_PFADD = 0x9E, + AMD3DNOW_SUFFIX_PFSUB = 0x9A, + AMD3DNOW_SUFFIX_PFSUBR = 0xAA, + AMD3DNOW_SUFFIX_PFACC = 0xAE, + AMD3DNOW_SUFFIX_PFCMPGE = 0x90, + AMD3DNOW_SUFFIX_PFCMPGT = 0xA0, + AMD3DNOW_SUFFIX_PFCMPEQ = 0xB0, + AMD3DNOW_SUFFIX_PFMIN = 0x94, + AMD3DNOW_SUFFIX_PFMAX = 0xA4, + AMD3DNOW_SUFFIX_PI2FD = 0x0D, + AMD3DNOW_SUFFIX_PF2ID = 0x1D, + AMD3DNOW_SUFFIX_PFRCP = 0x96, + AMD3DNOW_SUFFIX_PFRSQRT = 0x97, + AMD3DNOW_SUFFIX_PFMUL = 0xB4, + AMD3DNOW_SUFFIX_PFRCPIT1 = 0xA6, + AMD3DNOW_SUFFIX_PFRSQIT1 = 0xA7, + AMD3DNOW_SUFFIX_PFRCPIT2 = 0xB6, + AMD3DNOW_SUFFIX_PMULHRW = 0xB7, + AMD3DNOW_SUFFIX_PF2IW = 0x1C, + AMD3DNOW_SUFFIX_PI2FW = 0x0C, + AMD3DNOW_SUFFIX_PFNACC = 0x8A, + AMD3DNOW_SUFFIX_PFPNACC = 0x8E, + AMD3DNOW_SUFFIX_PSWAPD = 0xBB, +}; + +void AMD3DNOW_F0(void); + +void AMD3DNOW_FEMMS(void); + +void AMD3DNOW_PREFETCH(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_MMX_AMD3DNOW_H__ */ diff --git a/i386c/ia32/instructions/mmx/mmx.c b/i386c/ia32/instructions/mmx/mmx.c old mode 100755 new mode 100644 index 10b7b24e..ae53ac56 --- a/i386c/ia32/instructions/mmx/mmx.c +++ b/i386c/ia32/instructions/mmx/mmx.c @@ -1,2090 +1,2090 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include - -#include -#include "ia32/ia32.mcr" - -#include "ia32/instructions/mmx/mmx.h" - -#if defined(USE_MMX) && defined(USE_FPU) - -#define CPU_MMXWORKCLOCK CPU_WORKCLOCK(2) - -static INLINE void -MMX_check_NM_EXCEPTION(){ - // MMXなしならUD(無効オペコード例外)を発生させる - if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX)){ - EXCEPTION(UD_EXCEPTION, 0); - } - // エミュレーションならUD(無効オペコード例外)を発生させる - if(CPU_CR0 & CPU_CR0_EM){ - EXCEPTION(UD_EXCEPTION, 0); - } - // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる - if (CPU_CR0 & CPU_CR0_TS) { - EXCEPTION(NM_EXCEPTION, 0); - } -} - -static INLINE void -MMX_setTag(void) -{ - int i; - - if(!FPU_STAT.mmxenable){ - FPU_STAT.mmxenable = 1; - //FPU_CTRLWORD = 0x27F; - for (i = 0; i < FPU_REG_NUM; i++) { - FPU_STAT.tag[i] = TAG_Valid; -#ifdef SUPPORT_FPU_DOSBOX2 - FPU_STAT.int_regvalid[i] = 0; -#endif - FPU_STAT.reg[i].ul.ext = 0xffff; - } - } - FPU_STAT_TOP = 0; - FPU_STATUSWORD &= ~0x3800; - FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; -} - -/* - * MMX interface - */ -void -MMX_EMMS(void) -{ - int i; - - // MMXなしならUD(無効オペコード例外)を発生させる - if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX)){ - EXCEPTION(UD_EXCEPTION, 0); - } - // エミュレーションならUD(無効オペコード例外)を発生させる - if(CPU_CR0 & CPU_CR0_EM){ - EXCEPTION(UD_EXCEPTION, 0); - } - // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる - if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - CPU_WORKCLOCK(2); - for (i = 0; i < FPU_REG_NUM; i++) { - FPU_STAT.tag[i] = TAG_Empty; - } - FPU_STAT_TOP = 0; - FPU_STATUSWORD &= ~0x3800; - FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; - FPU_STAT.mmxenable = 0; -} - -// *********** MOV - -void MMX_MOVD_mm_rm32(void) -{ - UINT32 op, src; - UINT idx, sub; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - (src) = *(CPU_REG32_B20(op)); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - (src) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - } - FPU_STAT.reg[idx].ul.lower = src; - FPU_STAT.reg[idx].ul.upper = 0; -} -void MMX_MOVD_rm32_mm(void) -{ - UINT32 op, src, madr; - UINT idx, sub; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - src = FPU_STAT.reg[idx].ul.lower; - if (op >= 0xc0) { - *(CPU_REG32_B20(op)) = src; - } else { - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); - } -} - -void MMX_MOVQ_mm_mmm64(void) -{ - UINT32 op; - UINT idx, sub; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.reg[idx].ll = FPU_STAT.reg[sub].ll; - } else { - UINT32 madr; - madr = calc_ea_dst(op); - FPU_STAT.reg[idx].ll = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); - //FPU_STAT.reg[idx].ul.lower = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - //FPU_STAT.reg[idx].ul.upper = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr+4); - } -} -void MMX_MOVQ_mmm64_mm(void) -{ - UINT32 op; - UINT idx, sub; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.reg[sub].ll = FPU_STAT.reg[idx].ll; - } else { - UINT32 madr; - madr = calc_ea_dst(op); - cpu_vmemorywrite_q(CPU_INST_SEGREG_INDEX, madr, FPU_STAT.reg[idx].ll); - //cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, FPU_STAT.reg[idx].ul.lower); - //cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+4, FPU_STAT.reg[idx].ul.upper); - } -} - - -// *********** PACK - -void MMX_PACKSSWB(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT16 *srcreg1; - INT16 *srcreg2; - INT8 *dstreg; - INT8 dstregbuf[8]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); - srcreg2 = (INT16*)(&(FPU_STAT.reg[sub])); - dstreg = (INT8*)(&(FPU_STAT.reg[idx])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); - srcreg2 = srcregbuf.w; - dstreg = (INT8*)(&(FPU_STAT.reg[idx])); - } - for(i=0;i<4;i++){ - if(srcreg1[i] > 127){ - dstregbuf[i] = 127; - }else if(srcreg1[i] < -128){ - dstregbuf[i] = -128; - }else{ - dstregbuf[i] = (INT8)(srcreg1[i]); - } - } - for(i=0;i<4;i++){ - if(srcreg2[i] > 127){ - dstregbuf[i+4] = 127; - }else if(srcreg2[i] < -128){ - dstregbuf[i+4] = -128; - }else{ - dstregbuf[i+4] = (INT8)(srcreg2[i]); - } - } - for(i=0;i<8;i++){ - dstreg[i] = dstregbuf[i]; - } -} -void MMX_PACKSSDW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT32 *srcreg1; - INT32 *srcreg2; - INT16 *dstreg; - INT16 dstregbuf[4]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg1 = (INT32*)(&(FPU_STAT.reg[idx])); - srcreg2 = (INT32*)(&(FPU_STAT.reg[sub])); - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg1 = (INT32*)(&(FPU_STAT.reg[idx])); - srcreg2 = srcregbuf.d; - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - } - for(i=0;i<2;i++){ - if(srcreg1[i] > 32767){ - dstregbuf[i] = 32767; - }else if(srcreg1[i] < -32768){ - dstregbuf[i] = -32768; - }else{ - dstregbuf[i] = (INT16)(srcreg1[i]); - } - } - for(i=0;i<2;i++){ - if(srcreg2[i] > 32767){ - dstregbuf[i+2] = 32767; - }else if(srcreg2[i] < -32768){ - dstregbuf[i+2] = -32768; - }else{ - dstregbuf[i+2] = (INT16)(srcreg2[i]); - } - } - for(i=0;i<4;i++){ - dstreg[i] = dstregbuf[i]; - } -} - -void MMX_PACKUSWB(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT16 *srcreg1; - INT16 *srcreg2; - UINT8 *dstreg; - UINT8 dstregbuf[8]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); - srcreg2 = (INT16*)(&(FPU_STAT.reg[sub])); - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); - srcreg2 = srcregbuf.w; - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - } - for(i=0;i<4;i++){ - if(srcreg1[i] > 255){ - dstregbuf[i] = 255; - }else if(srcreg1[i] < 0){ - dstregbuf[i] = 0; - }else{ - dstregbuf[i] = (UINT8)(srcreg1[i]); - } - } - for(i=0;i<4;i++){ - if(srcreg2[i] > 255){ - dstregbuf[i+4] = 255; - }else if(srcreg2[i] < 0){ - dstregbuf[i+4] = 0; - }else{ - dstregbuf[i+4] = (UINT8)(srcreg2[i]); - } - } - for(i=0;i<8;i++){ - dstreg[i] = dstregbuf[i]; - } -} - -// *********** PADD - -void MMX_PADDB(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT8 *srcreg; - UINT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.b; - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - dstreg[i] += srcreg[i]; - } -} -void MMX_PADDW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT16 *srcreg; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstreg[i] += srcreg[i]; - } -} -void MMX_PADDD(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT32 *srcreg; - UINT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.d; - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - dstreg[i] += srcreg[i]; - } -} - -void MMX_PADDSB(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT8 *srcreg; - INT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.b; - } - dstreg = (INT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - INT16 cbuf = (INT16)dstreg[i] + (INT16)srcreg[i]; - if(cbuf > 127){ - dstreg[i] = 127; - }else if(cbuf < -128){ - dstreg[i] = -128; - }else{ - dstreg[i] = (INT8)cbuf; - } - } -} -void MMX_PADDSW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT16 *srcreg; - INT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - INT32 cbuf = (INT32)dstreg[i] + (INT32)srcreg[i]; - if(cbuf > 32767){ - dstreg[i] = 32767; - }else if(cbuf < -32768){ - dstreg[i] = -32768; - }else{ - dstreg[i] = (INT16)cbuf; - } - } -} - -void MMX_PADDUSB(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT8 *srcreg; - UINT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.b; - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - UINT16 cbuf = (UINT16)dstreg[i] + (UINT16)srcreg[i]; - if(cbuf > 255){ - dstreg[i] = 255; - }else{ - dstreg[i] = (UINT8)cbuf; - } - } -} -void MMX_PADDUSW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT16 *srcreg; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - UINT32 cbuf = (UINT32)dstreg[i] + (UINT32)srcreg[i]; - if(cbuf > 65535){ - dstreg[i] = 65535; - }else{ - dstreg[i] = (UINT16)cbuf; - } - } -} - -// *********** PAND/ANDN,OR,XOR - -void MMX_PAND(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT32 *srcreg; - UINT32 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.d; - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - dstreg[0] = dstreg[0] & srcreg[0]; - dstreg[1] = dstreg[1] & srcreg[1]; -} -void MMX_PANDN(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT32 *srcreg; - UINT32 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.d; - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - //dstreg[0] = ~(dstreg[0] & srcreg[0]); - //dstreg[1] = ~(dstreg[1] & srcreg[1]); - dstreg[0] = (~dstreg[0]) & srcreg[0]; - dstreg[1] = (~dstreg[1]) & srcreg[1]; -} -void MMX_POR(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT32 *srcreg; - UINT32 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.d; - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - dstreg[0] = dstreg[0] | srcreg[0]; - dstreg[1] = dstreg[1] | srcreg[1]; -} -void MMX_PXOR(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT32 *srcreg; - UINT32 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.d; - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - dstreg[0] = dstreg[0] ^ srcreg[0]; - dstreg[1] = dstreg[1] ^ srcreg[1]; -} - -// *********** PCMPEQ - -void MMX_PCMPEQB(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT8 *srcreg; - UINT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.b; - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - if(dstreg[i] == srcreg[i]){ - dstreg[i] = 0xff; - }else{ - dstreg[i] = 0; - } - } -} -void MMX_PCMPEQW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT16 *srcreg; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - if(dstreg[i] == srcreg[i]){ - dstreg[i] = 0xffff; - }else{ - dstreg[i] = 0; - } - } -} -void MMX_PCMPEQD(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT32 *srcreg; - UINT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.d; - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - if(dstreg[i] == srcreg[i]){ - dstreg[i] = 0xffffffff; - }else{ - dstreg[i] = 0; - } - } -} - -// *********** PCMPGT - -void MMX_PCMPGTB(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT8 *srcreg; - INT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.b; - } - dstreg = (INT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - if(dstreg[i] > srcreg[i]){ - dstreg[i] = 0xff; - }else{ - dstreg[i] = 0; - } - } -} -void MMX_PCMPGTW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT16 *srcreg; - INT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - if(dstreg[i] > srcreg[i]){ - dstreg[i] = 0xffff; - }else{ - dstreg[i] = 0; - } - } -} -void MMX_PCMPGTD(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT32 *srcreg; - INT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.d; - } - dstreg = (INT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - if(dstreg[i] > srcreg[i]){ - dstreg[i] = 0xffffffff; - }else{ - dstreg[i] = 0; - } - } -} - -// *********** PMADDWD -void MMX_PMADDWD(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT16 *srcreg; - INT16 *dstreg; - INT32 *dstreg32; - INT32 dstregbuf[2]; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - dstreg32 = (INT32*)(&(FPU_STAT.reg[idx])); - - dstregbuf[0] = (INT32)srcreg[0] * (INT32)dstreg[0] + (INT32)srcreg[1] * (INT32)dstreg[1]; - dstregbuf[1] = (INT32)srcreg[2] * (INT32)dstreg[2] + (INT32)srcreg[3] * (INT32)dstreg[3]; - dstreg32[0] = dstregbuf[0]; - dstreg32[1] = dstregbuf[1]; -} - -// *********** PMUL -void MMX_PMULHW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT16 *srcreg; - INT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstreg[i] = (INT16)((((INT32)srcreg[i] * (INT32)dstreg[i]) >> 16) & 0xffff); - } -} -void MMX_PMULLW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT16 *srcreg; - INT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstreg[i] = (INT16)((((INT32)srcreg[i] * (INT32)dstreg[i])) & 0xffff); - } -} - -// *********** PSLL -void MMX_PSLLW(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - //dstreg[i] = (dstreg[i] << shift); - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } -} -void MMX_PSLLD(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - //dstreg[i] = (dstreg[i] << shift); - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } -} -void MMX_PSLLQ(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT64 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT64*)(&(FPU_STAT.reg[idx])); - - //dstreg[0] = (dstreg[0] << shift); - dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) -} - -// *********** PSRA - -void MMX_PSRAW(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT16 *dstreg; - UINT16 signval; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - // 無理やり算術シフト(怪しい) - if(16 <= shift){ - signval = 0xffff; - }else{ - UINT32 rshift = 16 - shift; - signval = (0xffff >> rshift) << rshift; - } - for(i=0;i<4;i++){ - if(((INT16*)dstreg)[i] < 0){ - dstreg[i] = (dstreg[i] >> shift) | signval; - }else{ - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } -} -void MMX_PSRAD(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT32 *dstreg; - UINT32 signval; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - // 無理やり算術シフト(怪しい) - if(32 <= shift){ - signval = 0xffffffff; - }else{ - UINT32 rshift = 32 - shift; - signval = (0xffffffff >> rshift) << rshift; - } - for(i=0;i<2;i++){ - if(((INT32*)dstreg)[i] < 0){ - dstreg[i] = (dstreg[i] >> shift) | signval; - }else{ - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } -} - -// *********** PSRL -void MMX_PSRLW(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - //dstreg[i] = (dstreg[i] >> shift); - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } -} -void MMX_PSRLD(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - //dstreg[i] = (dstreg[i] >> shift); - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } -} -void MMX_PSRLQ(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT64 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: シフトしすぎ - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: シフトしすぎ - } - dstreg = (UINT64*)(&(FPU_STAT.reg[idx])); - - //dstreg[0] = (dstreg[0] >> shift); - dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) -} - -// *********** PSLL(imm8),PSRL(imm8),PSRA(imm8) -void MMX_PSxxW_imm8(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT16 *dstreg; - UINT16 signval; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - dstreg = (UINT16*)(&(FPU_STAT.reg[sub])); - GET_MODRM_PCBYTE((shift)); - - switch(idx){ - case 2: // PSRLW(imm8) - for(i=0;i<4;i++){ - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - break; - case 4: // PSRAW(imm8) - // 無理やり算術シフト(怪しい) - if(16 <= shift){ - signval = 0xffff; - }else{ - UINT32 rshift = 16 - shift; - signval = (0xffff >> rshift) << rshift; - } - for(i=0;i<4;i++){ - if(((INT16*)dstreg)[i] < 0){ - dstreg[i] = (dstreg[i] >> shift) | signval; - }else{ - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } - break; - case 6: // PSLLW(imm8) - for(i=0;i<4;i++){ - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } - break; - default: - break; - } -} -void MMX_PSxxD_imm8(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT32 *dstreg; - UINT32 signval; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - dstreg = (UINT32*)(&(FPU_STAT.reg[sub])); - GET_MODRM_PCBYTE((shift)); - - switch(idx){ - case 2: // PSRLD(imm8) - for(i=0;i<2;i++){ - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - break; - case 4: // PSRAD(imm8) - // 無理やり算術シフト(怪しい) - if(32 <= shift){ - signval = 0xffffffff; - }else{ - UINT32 rshift = 32 - shift; - signval = (0xffffffff >> rshift) << rshift; - } - for(i=0;i<2;i++){ - if(((INT32*)dstreg)[i] < 0){ - dstreg[i] = (dstreg[i] >> shift) | signval; - }else{ - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } - break; - case 6: // PSLLD(imm8) - for(i=0;i<2;i++){ - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } - break; - default: - break; - } -} -void MMX_PSxxQ_imm8(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT64 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - dstreg = (UINT64*)(&(FPU_STAT.reg[sub])); - GET_MODRM_PCBYTE((shift)); - - switch(idx){ - case 2: // PSRLQ(imm8) - dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - break; - case 4: // PSRAQ(imm8) - EXCEPTION(UD_EXCEPTION, 0); - break; - case 6: // PSLLQ(imm8) - dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - break; - default: - break; - } -} - -// *********** PSUB - -void MMX_PSUBB(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT8 *srcreg; - UINT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.b; - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - dstreg[i] -= srcreg[i]; - } -} -void MMX_PSUBW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT16 *srcreg; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstreg[i] -= srcreg[i]; - } -} -void MMX_PSUBD(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT32 *srcreg; - UINT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.d; - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - dstreg[i] -= srcreg[i]; - } -} - -void MMX_PSUBSB(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT8 *srcreg; - INT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.b; - } - dstreg = (INT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - INT16 cbuf = (INT16)dstreg[i] - (INT16)srcreg[i]; - if(cbuf > 127){ - dstreg[i] = 127; - }else if(cbuf < -128){ - dstreg[i] = -128; - }else{ - dstreg[i] = (INT8)cbuf; - } - } -} -void MMX_PSUBSW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - INT16 *srcreg; - INT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - INT32 cbuf = (INT32)dstreg[i] - (INT32)srcreg[i]; - if(cbuf > 32767){ - dstreg[i] = 32767; - }else if(cbuf < -32768){ - dstreg[i] = -32768; - }else{ - dstreg[i] = (INT16)cbuf; - } - } -} - -void MMX_PSUBUSB(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT8 *srcreg; - UINT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.b; - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - INT16 cbuf = (INT16)dstreg[i] - (INT16)srcreg[i]; - if(cbuf > 255){ - dstreg[i] = 255; - }else if(cbuf < 0){ - dstreg[i] = 0; - }else{ - dstreg[i] = (UINT8)cbuf; - } - } -} -void MMX_PSUBUSW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT16 *srcreg; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - INT32 cbuf = (INT32)dstreg[i] - (INT32)srcreg[i]; - if(cbuf > 65535){ - dstreg[i] = 65535; - }else if(cbuf < 0){ - dstreg[i] = 0; - }else{ - dstreg[i] = (UINT16)cbuf; - } - } -} - -// *********** PUNPCK - -void MMX_PUNPCKHBW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT8 *srcreg; - UINT8 *dstreg; - UINT8 dstregbuf[8]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.b; - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstregbuf[i*2] = dstreg[i+4]; - dstregbuf[i*2 + 1] = srcreg[i+4]; - } - for(i=0;i<8;i++){ - dstreg[i] = dstregbuf[i]; - } -} -void MMX_PUNPCKHWD(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT16 *srcreg; - UINT16 *dstreg; - UINT16 dstregbuf[4]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - dstregbuf[i*2] = dstreg[i+2]; - dstregbuf[i*2 + 1] = srcreg[i+2]; - } - for(i=0;i<4;i++){ - dstreg[i] = dstregbuf[i]; - } -} -void MMX_PUNPCKHDQ(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT32 *srcreg; - UINT32 *dstreg; - UINT32 dstregbuf[2]; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.d; - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - dstregbuf[0] = dstreg[1]; - dstregbuf[1] = srcreg[1]; - dstreg[0] = dstregbuf[0]; - dstreg[1] = dstregbuf[1]; -} -void MMX_PUNPCKLBW(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT8 *srcreg; - UINT8 *dstreg; - UINT8 dstregbuf[8]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.b; - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstregbuf[i*2] = dstreg[i]; - dstregbuf[i*2 + 1] = srcreg[i]; - } - for(i=0;i<8;i++){ - dstreg[i] = dstregbuf[i]; - } -} -void MMX_PUNPCKLWD(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT16 *srcreg; - UINT16 *dstreg; - UINT16 dstregbuf[4]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.w; - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - dstregbuf[i*2] = dstreg[i]; - dstregbuf[i*2 + 1] = srcreg[i]; - } - for(i=0;i<4;i++){ - dstreg[i] = dstregbuf[i]; - } -} -void MMX_PUNPCKLDQ(void) -{ - UINT32 op; - UINT idx, sub; - MMXREG srcregbuf; - UINT32 *srcreg; - UINT32 *dstreg; - UINT32 dstregbuf[2]; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg = srcregbuf.d; - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - dstregbuf[0] = dstreg[0]; - dstregbuf[1] = srcreg[0]; - dstreg[0] = dstregbuf[0]; - dstreg[1] = dstregbuf[1]; -} - -#else - -/* - * MMX interface - */ -void -MMX_EMMS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_MOVD_mm_rm32(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_MOVD_rm32_mm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_MOVQ_mm_mmm64(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_MOVQ_mmm64_mm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PACKSSWB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PACKSSDW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PACKUSWB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PADDB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PADDW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PADDD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PADDSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PADDSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PADDUSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PADDUSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PAND(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PANDN(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_POR(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PXOR(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PCMPEQB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PCMPEQW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PCMPEQD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PCMPGTB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PCMPGTW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PCMPGTD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PMADDWD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PMULHW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PMULLW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSLLW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSLLD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSLLQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSRAW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSRAD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSRLW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSRLD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSRLQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSxxW_imm8(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSxxD_imm8(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSxxQ_imm8(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSUBB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSUBW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSUBD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSUBSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSUBSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSUBUSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSUBUSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PUNPCKHBW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PUNPCKHWD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PUNPCKHDQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PUNPCKLBW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PUNPCKLWD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PUNPCKLDQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include + +#include +#include "ia32/ia32.mcr" + +#include "ia32/instructions/mmx/mmx.h" + +#if defined(USE_MMX) && defined(USE_FPU) + +#define CPU_MMXWORKCLOCK CPU_WORKCLOCK(2) + +static INLINE void +MMX_check_NM_EXCEPTION(){ + // MMXなしならUD(無効オペコード例外)を発生させる + if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX)){ + EXCEPTION(UD_EXCEPTION, 0); + } + // エミュレーションならUD(無効オペコード例外)を発生させる + if(CPU_CR0 & CPU_CR0_EM){ + EXCEPTION(UD_EXCEPTION, 0); + } + // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる + if (CPU_CR0 & CPU_CR0_TS) { + EXCEPTION(NM_EXCEPTION, 0); + } +} + +static INLINE void +MMX_setTag(void) +{ + int i; + + if(!FPU_STAT.mmxenable){ + FPU_STAT.mmxenable = 1; + //FPU_CTRLWORD = 0x27F; + for (i = 0; i < FPU_REG_NUM; i++) { + FPU_STAT.tag[i] = TAG_Valid; +#ifdef SUPPORT_FPU_DOSBOX2 + FPU_STAT.int_regvalid[i] = 0; +#endif + FPU_STAT.reg[i].ul.ext = 0xffff; + } + } + FPU_STAT_TOP = 0; + FPU_STATUSWORD &= ~0x3800; + FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; +} + +/* + * MMX interface + */ +void +MMX_EMMS(void) +{ + int i; + + // MMXなしならUD(無効オペコード例外)を発生させる + if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX)){ + EXCEPTION(UD_EXCEPTION, 0); + } + // エミュレーションならUD(無効オペコード例外)を発生させる + if(CPU_CR0 & CPU_CR0_EM){ + EXCEPTION(UD_EXCEPTION, 0); + } + // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる + if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + CPU_WORKCLOCK(2); + for (i = 0; i < FPU_REG_NUM; i++) { + FPU_STAT.tag[i] = TAG_Empty; + } + FPU_STAT_TOP = 0; + FPU_STATUSWORD &= ~0x3800; + FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; + FPU_STAT.mmxenable = 0; +} + +// *********** MOV + +void MMX_MOVD_mm_rm32(void) +{ + UINT32 op, src; + UINT idx, sub; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + (src) = *(CPU_REG32_B20(op)); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + (src) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + } + FPU_STAT.reg[idx].ul.lower = src; + FPU_STAT.reg[idx].ul.upper = 0; +} +void MMX_MOVD_rm32_mm(void) +{ + UINT32 op, src, madr; + UINT idx, sub; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + src = FPU_STAT.reg[idx].ul.lower; + if (op >= 0xc0) { + *(CPU_REG32_B20(op)) = src; + } else { + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); + } +} + +void MMX_MOVQ_mm_mmm64(void) +{ + UINT32 op; + UINT idx, sub; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.reg[idx].ll = FPU_STAT.reg[sub].ll; + } else { + UINT32 madr; + madr = calc_ea_dst(op); + FPU_STAT.reg[idx].ll = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); + //FPU_STAT.reg[idx].ul.lower = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + //FPU_STAT.reg[idx].ul.upper = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr+4); + } +} +void MMX_MOVQ_mmm64_mm(void) +{ + UINT32 op; + UINT idx, sub; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.reg[sub].ll = FPU_STAT.reg[idx].ll; + } else { + UINT32 madr; + madr = calc_ea_dst(op); + cpu_vmemorywrite_q(CPU_INST_SEGREG_INDEX, madr, FPU_STAT.reg[idx].ll); + //cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, FPU_STAT.reg[idx].ul.lower); + //cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+4, FPU_STAT.reg[idx].ul.upper); + } +} + + +// *********** PACK + +void MMX_PACKSSWB(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT16 *srcreg1; + INT16 *srcreg2; + INT8 *dstreg; + INT8 dstregbuf[8]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); + srcreg2 = (INT16*)(&(FPU_STAT.reg[sub])); + dstreg = (INT8*)(&(FPU_STAT.reg[idx])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); + srcreg2 = srcregbuf.w; + dstreg = (INT8*)(&(FPU_STAT.reg[idx])); + } + for(i=0;i<4;i++){ + if(srcreg1[i] > 127){ + dstregbuf[i] = 127; + }else if(srcreg1[i] < -128){ + dstregbuf[i] = -128; + }else{ + dstregbuf[i] = (INT8)(srcreg1[i]); + } + } + for(i=0;i<4;i++){ + if(srcreg2[i] > 127){ + dstregbuf[i+4] = 127; + }else if(srcreg2[i] < -128){ + dstregbuf[i+4] = -128; + }else{ + dstregbuf[i+4] = (INT8)(srcreg2[i]); + } + } + for(i=0;i<8;i++){ + dstreg[i] = dstregbuf[i]; + } +} +void MMX_PACKSSDW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT32 *srcreg1; + INT32 *srcreg2; + INT16 *dstreg; + INT16 dstregbuf[4]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg1 = (INT32*)(&(FPU_STAT.reg[idx])); + srcreg2 = (INT32*)(&(FPU_STAT.reg[sub])); + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg1 = (INT32*)(&(FPU_STAT.reg[idx])); + srcreg2 = srcregbuf.d; + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + } + for(i=0;i<2;i++){ + if(srcreg1[i] > 32767){ + dstregbuf[i] = 32767; + }else if(srcreg1[i] < -32768){ + dstregbuf[i] = -32768; + }else{ + dstregbuf[i] = (INT16)(srcreg1[i]); + } + } + for(i=0;i<2;i++){ + if(srcreg2[i] > 32767){ + dstregbuf[i+2] = 32767; + }else if(srcreg2[i] < -32768){ + dstregbuf[i+2] = -32768; + }else{ + dstregbuf[i+2] = (INT16)(srcreg2[i]); + } + } + for(i=0;i<4;i++){ + dstreg[i] = dstregbuf[i]; + } +} + +void MMX_PACKUSWB(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT16 *srcreg1; + INT16 *srcreg2; + UINT8 *dstreg; + UINT8 dstregbuf[8]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); + srcreg2 = (INT16*)(&(FPU_STAT.reg[sub])); + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); + srcreg2 = srcregbuf.w; + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + } + for(i=0;i<4;i++){ + if(srcreg1[i] > 255){ + dstregbuf[i] = 255; + }else if(srcreg1[i] < 0){ + dstregbuf[i] = 0; + }else{ + dstregbuf[i] = (UINT8)(srcreg1[i]); + } + } + for(i=0;i<4;i++){ + if(srcreg2[i] > 255){ + dstregbuf[i+4] = 255; + }else if(srcreg2[i] < 0){ + dstregbuf[i+4] = 0; + }else{ + dstregbuf[i+4] = (UINT8)(srcreg2[i]); + } + } + for(i=0;i<8;i++){ + dstreg[i] = dstregbuf[i]; + } +} + +// *********** PADD + +void MMX_PADDB(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT8 *srcreg; + UINT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.b; + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + dstreg[i] += srcreg[i]; + } +} +void MMX_PADDW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT16 *srcreg; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstreg[i] += srcreg[i]; + } +} +void MMX_PADDD(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT32 *srcreg; + UINT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.d; + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + dstreg[i] += srcreg[i]; + } +} + +void MMX_PADDSB(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT8 *srcreg; + INT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.b; + } + dstreg = (INT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + INT16 cbuf = (INT16)dstreg[i] + (INT16)srcreg[i]; + if(cbuf > 127){ + dstreg[i] = 127; + }else if(cbuf < -128){ + dstreg[i] = -128; + }else{ + dstreg[i] = (INT8)cbuf; + } + } +} +void MMX_PADDSW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT16 *srcreg; + INT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + INT32 cbuf = (INT32)dstreg[i] + (INT32)srcreg[i]; + if(cbuf > 32767){ + dstreg[i] = 32767; + }else if(cbuf < -32768){ + dstreg[i] = -32768; + }else{ + dstreg[i] = (INT16)cbuf; + } + } +} + +void MMX_PADDUSB(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT8 *srcreg; + UINT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.b; + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + UINT16 cbuf = (UINT16)dstreg[i] + (UINT16)srcreg[i]; + if(cbuf > 255){ + dstreg[i] = 255; + }else{ + dstreg[i] = (UINT8)cbuf; + } + } +} +void MMX_PADDUSW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT16 *srcreg; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + UINT32 cbuf = (UINT32)dstreg[i] + (UINT32)srcreg[i]; + if(cbuf > 65535){ + dstreg[i] = 65535; + }else{ + dstreg[i] = (UINT16)cbuf; + } + } +} + +// *********** PAND/ANDN,OR,XOR + +void MMX_PAND(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT32 *srcreg; + UINT32 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.d; + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + dstreg[0] = dstreg[0] & srcreg[0]; + dstreg[1] = dstreg[1] & srcreg[1]; +} +void MMX_PANDN(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT32 *srcreg; + UINT32 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.d; + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + //dstreg[0] = ~(dstreg[0] & srcreg[0]); + //dstreg[1] = ~(dstreg[1] & srcreg[1]); + dstreg[0] = (~dstreg[0]) & srcreg[0]; + dstreg[1] = (~dstreg[1]) & srcreg[1]; +} +void MMX_POR(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT32 *srcreg; + UINT32 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.d; + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + dstreg[0] = dstreg[0] | srcreg[0]; + dstreg[1] = dstreg[1] | srcreg[1]; +} +void MMX_PXOR(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT32 *srcreg; + UINT32 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.d; + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + dstreg[0] = dstreg[0] ^ srcreg[0]; + dstreg[1] = dstreg[1] ^ srcreg[1]; +} + +// *********** PCMPEQ + +void MMX_PCMPEQB(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT8 *srcreg; + UINT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.b; + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + if(dstreg[i] == srcreg[i]){ + dstreg[i] = 0xff; + }else{ + dstreg[i] = 0; + } + } +} +void MMX_PCMPEQW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT16 *srcreg; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + if(dstreg[i] == srcreg[i]){ + dstreg[i] = 0xffff; + }else{ + dstreg[i] = 0; + } + } +} +void MMX_PCMPEQD(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT32 *srcreg; + UINT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.d; + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + if(dstreg[i] == srcreg[i]){ + dstreg[i] = 0xffffffff; + }else{ + dstreg[i] = 0; + } + } +} + +// *********** PCMPGT + +void MMX_PCMPGTB(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT8 *srcreg; + INT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.b; + } + dstreg = (INT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + if(dstreg[i] > srcreg[i]){ + dstreg[i] = 0xff; + }else{ + dstreg[i] = 0; + } + } +} +void MMX_PCMPGTW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT16 *srcreg; + INT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + if(dstreg[i] > srcreg[i]){ + dstreg[i] = 0xffff; + }else{ + dstreg[i] = 0; + } + } +} +void MMX_PCMPGTD(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT32 *srcreg; + INT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.d; + } + dstreg = (INT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + if(dstreg[i] > srcreg[i]){ + dstreg[i] = 0xffffffff; + }else{ + dstreg[i] = 0; + } + } +} + +// *********** PMADDWD +void MMX_PMADDWD(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT16 *srcreg; + INT16 *dstreg; + INT32 *dstreg32; + INT32 dstregbuf[2]; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + dstreg32 = (INT32*)(&(FPU_STAT.reg[idx])); + + dstregbuf[0] = (INT32)srcreg[0] * (INT32)dstreg[0] + (INT32)srcreg[1] * (INT32)dstreg[1]; + dstregbuf[1] = (INT32)srcreg[2] * (INT32)dstreg[2] + (INT32)srcreg[3] * (INT32)dstreg[3]; + dstreg32[0] = dstregbuf[0]; + dstreg32[1] = dstregbuf[1]; +} + +// *********** PMUL +void MMX_PMULHW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT16 *srcreg; + INT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstreg[i] = (INT16)((((INT32)srcreg[i] * (INT32)dstreg[i]) >> 16) & 0xffff); + } +} +void MMX_PMULLW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT16 *srcreg; + INT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstreg[i] = (INT16)((((INT32)srcreg[i] * (INT32)dstreg[i])) & 0xffff); + } +} + +// *********** PSLL +void MMX_PSLLW(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + //dstreg[i] = (dstreg[i] << shift); + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } +} +void MMX_PSLLD(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + //dstreg[i] = (dstreg[i] << shift); + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } +} +void MMX_PSLLQ(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT64 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT64*)(&(FPU_STAT.reg[idx])); + + //dstreg[0] = (dstreg[0] << shift); + dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) +} + +// *********** PSRA + +void MMX_PSRAW(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT16 *dstreg; + UINT16 signval; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + // 無理やり算術シフト(怪しい) + if(16 <= shift){ + signval = 0xffff; + }else{ + UINT32 rshift = 16 - shift; + signval = (0xffff >> rshift) << rshift; + } + for(i=0;i<4;i++){ + if(((INT16*)dstreg)[i] < 0){ + dstreg[i] = (dstreg[i] >> shift) | signval; + }else{ + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } +} +void MMX_PSRAD(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT32 *dstreg; + UINT32 signval; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + // 無理やり算術シフト(怪しい) + if(32 <= shift){ + signval = 0xffffffff; + }else{ + UINT32 rshift = 32 - shift; + signval = (0xffffffff >> rshift) << rshift; + } + for(i=0;i<2;i++){ + if(((INT32*)dstreg)[i] < 0){ + dstreg[i] = (dstreg[i] >> shift) | signval; + }else{ + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } +} + +// *********** PSRL +void MMX_PSRLW(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + //dstreg[i] = (dstreg[i] >> shift); + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } +} +void MMX_PSRLD(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + //dstreg[i] = (dstreg[i] >> shift); + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } +} +void MMX_PSRLQ(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT64 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: シフトしすぎ + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: シフトしすぎ + } + dstreg = (UINT64*)(&(FPU_STAT.reg[idx])); + + //dstreg[0] = (dstreg[0] >> shift); + dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) +} + +// *********** PSLL(imm8),PSRL(imm8),PSRA(imm8) +void MMX_PSxxW_imm8(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT16 *dstreg; + UINT16 signval; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + dstreg = (UINT16*)(&(FPU_STAT.reg[sub])); + GET_MODRM_PCBYTE((shift)); + + switch(idx){ + case 2: // PSRLW(imm8) + for(i=0;i<4;i++){ + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + break; + case 4: // PSRAW(imm8) + // 無理やり算術シフト(怪しい) + if(16 <= shift){ + signval = 0xffff; + }else{ + UINT32 rshift = 16 - shift; + signval = (0xffff >> rshift) << rshift; + } + for(i=0;i<4;i++){ + if(((INT16*)dstreg)[i] < 0){ + dstreg[i] = (dstreg[i] >> shift) | signval; + }else{ + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } + break; + case 6: // PSLLW(imm8) + for(i=0;i<4;i++){ + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } + break; + default: + break; + } +} +void MMX_PSxxD_imm8(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT32 *dstreg; + UINT32 signval; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + dstreg = (UINT32*)(&(FPU_STAT.reg[sub])); + GET_MODRM_PCBYTE((shift)); + + switch(idx){ + case 2: // PSRLD(imm8) + for(i=0;i<2;i++){ + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + break; + case 4: // PSRAD(imm8) + // 無理やり算術シフト(怪しい) + if(32 <= shift){ + signval = 0xffffffff; + }else{ + UINT32 rshift = 32 - shift; + signval = (0xffffffff >> rshift) << rshift; + } + for(i=0;i<2;i++){ + if(((INT32*)dstreg)[i] < 0){ + dstreg[i] = (dstreg[i] >> shift) | signval; + }else{ + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } + break; + case 6: // PSLLD(imm8) + for(i=0;i<2;i++){ + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } + break; + default: + break; + } +} +void MMX_PSxxQ_imm8(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT64 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + dstreg = (UINT64*)(&(FPU_STAT.reg[sub])); + GET_MODRM_PCBYTE((shift)); + + switch(idx){ + case 2: // PSRLQ(imm8) + dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + break; + case 4: // PSRAQ(imm8) + EXCEPTION(UD_EXCEPTION, 0); + break; + case 6: // PSLLQ(imm8) + dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + break; + default: + break; + } +} + +// *********** PSUB + +void MMX_PSUBB(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT8 *srcreg; + UINT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.b; + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + dstreg[i] -= srcreg[i]; + } +} +void MMX_PSUBW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT16 *srcreg; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstreg[i] -= srcreg[i]; + } +} +void MMX_PSUBD(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT32 *srcreg; + UINT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.d; + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + dstreg[i] -= srcreg[i]; + } +} + +void MMX_PSUBSB(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT8 *srcreg; + INT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.b; + } + dstreg = (INT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + INT16 cbuf = (INT16)dstreg[i] - (INT16)srcreg[i]; + if(cbuf > 127){ + dstreg[i] = 127; + }else if(cbuf < -128){ + dstreg[i] = -128; + }else{ + dstreg[i] = (INT8)cbuf; + } + } +} +void MMX_PSUBSW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + INT16 *srcreg; + INT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + INT32 cbuf = (INT32)dstreg[i] - (INT32)srcreg[i]; + if(cbuf > 32767){ + dstreg[i] = 32767; + }else if(cbuf < -32768){ + dstreg[i] = -32768; + }else{ + dstreg[i] = (INT16)cbuf; + } + } +} + +void MMX_PSUBUSB(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT8 *srcreg; + UINT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.b; + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + INT16 cbuf = (INT16)dstreg[i] - (INT16)srcreg[i]; + if(cbuf > 255){ + dstreg[i] = 255; + }else if(cbuf < 0){ + dstreg[i] = 0; + }else{ + dstreg[i] = (UINT8)cbuf; + } + } +} +void MMX_PSUBUSW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT16 *srcreg; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + INT32 cbuf = (INT32)dstreg[i] - (INT32)srcreg[i]; + if(cbuf > 65535){ + dstreg[i] = 65535; + }else if(cbuf < 0){ + dstreg[i] = 0; + }else{ + dstreg[i] = (UINT16)cbuf; + } + } +} + +// *********** PUNPCK + +void MMX_PUNPCKHBW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT8 *srcreg; + UINT8 *dstreg; + UINT8 dstregbuf[8]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.b; + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstregbuf[i*2] = dstreg[i+4]; + dstregbuf[i*2 + 1] = srcreg[i+4]; + } + for(i=0;i<8;i++){ + dstreg[i] = dstregbuf[i]; + } +} +void MMX_PUNPCKHWD(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT16 *srcreg; + UINT16 *dstreg; + UINT16 dstregbuf[4]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + dstregbuf[i*2] = dstreg[i+2]; + dstregbuf[i*2 + 1] = srcreg[i+2]; + } + for(i=0;i<4;i++){ + dstreg[i] = dstregbuf[i]; + } +} +void MMX_PUNPCKHDQ(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT32 *srcreg; + UINT32 *dstreg; + UINT32 dstregbuf[2]; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.d; + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + dstregbuf[0] = dstreg[1]; + dstregbuf[1] = srcreg[1]; + dstreg[0] = dstregbuf[0]; + dstreg[1] = dstregbuf[1]; +} +void MMX_PUNPCKLBW(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT8 *srcreg; + UINT8 *dstreg; + UINT8 dstregbuf[8]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.b; + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstregbuf[i*2] = dstreg[i]; + dstregbuf[i*2 + 1] = srcreg[i]; + } + for(i=0;i<8;i++){ + dstreg[i] = dstregbuf[i]; + } +} +void MMX_PUNPCKLWD(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT16 *srcreg; + UINT16 *dstreg; + UINT16 dstregbuf[4]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.w; + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + dstregbuf[i*2] = dstreg[i]; + dstregbuf[i*2 + 1] = srcreg[i]; + } + for(i=0;i<4;i++){ + dstreg[i] = dstregbuf[i]; + } +} +void MMX_PUNPCKLDQ(void) +{ + UINT32 op; + UINT idx, sub; + MMXREG srcregbuf; + UINT32 *srcreg; + UINT32 *dstreg; + UINT32 dstregbuf[2]; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcregbuf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcregbuf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg = srcregbuf.d; + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + dstregbuf[0] = dstreg[0]; + dstregbuf[1] = srcreg[0]; + dstreg[0] = dstregbuf[0]; + dstreg[1] = dstregbuf[1]; +} + +#else + +/* + * MMX interface + */ +void +MMX_EMMS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_MOVD_mm_rm32(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_MOVD_rm32_mm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_MOVQ_mm_mmm64(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_MOVQ_mmm64_mm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PACKSSWB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PACKSSDW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PACKUSWB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PADDB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PADDW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PADDD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PADDSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PADDSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PADDUSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PADDUSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PAND(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PANDN(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_POR(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PXOR(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PCMPEQB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PCMPEQW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PCMPEQD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PCMPGTB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PCMPGTW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PCMPGTD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PMADDWD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PMULHW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PMULLW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSLLW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSLLD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSLLQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSRAW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSRAD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSRLW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSRLD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSRLQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSxxW_imm8(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSxxD_imm8(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSxxQ_imm8(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSUBB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSUBW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSUBD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSUBSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSUBSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSUBUSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSUBUSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PUNPCKHBW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PUNPCKHWD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PUNPCKHDQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PUNPCKLBW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PUNPCKLWD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PUNPCKLDQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} #endif \ No newline at end of file diff --git a/i386c/ia32/instructions/mmx/mmx.h b/i386c/ia32/instructions/mmx/mmx.h old mode 100755 new mode 100644 index 337b20eb..ae448c20 --- a/i386c/ia32/instructions/mmx/mmx.h +++ b/i386c/ia32/instructions/mmx/mmx.h @@ -1,117 +1,117 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_MMX_MMX_H__ -#define IA32_CPU_INSTRUCTION_MMX_MMX_H__ - -typedef union { - UINT8 b[8]; - UINT16 w[4]; - UINT32 d[2]; - UINT64 q[1]; -} MMXREG; - -#ifdef __cplusplus -extern "C" { -#endif - -void MMX_EMMS(void); - -void MMX_MOVD_mm_rm32(void); -void MMX_MOVD_rm32_mm(void); - -void MMX_MOVQ_mm_mmm64(void); -void MMX_MOVQ_mmm64_mm(void); - -void MMX_PACKSSWB(void); -void MMX_PACKSSDW(void); - -void MMX_PACKUSWB(void); - -void MMX_PADDB(void); -void MMX_PADDW(void); -void MMX_PADDD(void); - -void MMX_PADDSB(void); -void MMX_PADDSW(void); - -void MMX_PADDUSB(void); -void MMX_PADDUSW(void); - -void MMX_PAND(void); -void MMX_PANDN(void); -void MMX_POR(void); -void MMX_PXOR(void); - -void MMX_PCMPEQB(void); -void MMX_PCMPEQW(void); -void MMX_PCMPEQD(void); - -void MMX_PCMPGTB(void); -void MMX_PCMPGTW(void); -void MMX_PCMPGTD(void); - -void MMX_PMADDWD(void); - -void MMX_PMULHW(void); -void MMX_PMULLW(void); - -void MMX_PSLLW(void); -void MMX_PSLLD(void); -void MMX_PSLLQ(void); - -void MMX_PSRAW(void); -void MMX_PSRAD(void); - -void MMX_PSRLW(void); -void MMX_PSRLD(void); -void MMX_PSRLQ(void); - -void MMX_PSxxW_imm8(void); -void MMX_PSxxD_imm8(void); -void MMX_PSxxQ_imm8(void); - -void MMX_PSUBB(void); -void MMX_PSUBW(void); -void MMX_PSUBD(void); - -void MMX_PSUBSB(void); -void MMX_PSUBSW(void); - -void MMX_PSUBUSB(void); -void MMX_PSUBUSW(void); - -void MMX_PUNPCKHBW(void); -void MMX_PUNPCKHWD(void); -void MMX_PUNPCKHDQ(void); -void MMX_PUNPCKLBW(void); -void MMX_PUNPCKLWD(void); -void MMX_PUNPCKLDQ(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_MMX_MMX_H__ */ +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_MMX_MMX_H__ +#define IA32_CPU_INSTRUCTION_MMX_MMX_H__ + +typedef union { + UINT8 b[8]; + UINT16 w[4]; + UINT32 d[2]; + UINT64 q[1]; +} MMXREG; + +#ifdef __cplusplus +extern "C" { +#endif + +void MMX_EMMS(void); + +void MMX_MOVD_mm_rm32(void); +void MMX_MOVD_rm32_mm(void); + +void MMX_MOVQ_mm_mmm64(void); +void MMX_MOVQ_mmm64_mm(void); + +void MMX_PACKSSWB(void); +void MMX_PACKSSDW(void); + +void MMX_PACKUSWB(void); + +void MMX_PADDB(void); +void MMX_PADDW(void); +void MMX_PADDD(void); + +void MMX_PADDSB(void); +void MMX_PADDSW(void); + +void MMX_PADDUSB(void); +void MMX_PADDUSW(void); + +void MMX_PAND(void); +void MMX_PANDN(void); +void MMX_POR(void); +void MMX_PXOR(void); + +void MMX_PCMPEQB(void); +void MMX_PCMPEQW(void); +void MMX_PCMPEQD(void); + +void MMX_PCMPGTB(void); +void MMX_PCMPGTW(void); +void MMX_PCMPGTD(void); + +void MMX_PMADDWD(void); + +void MMX_PMULHW(void); +void MMX_PMULLW(void); + +void MMX_PSLLW(void); +void MMX_PSLLD(void); +void MMX_PSLLQ(void); + +void MMX_PSRAW(void); +void MMX_PSRAD(void); + +void MMX_PSRLW(void); +void MMX_PSRLD(void); +void MMX_PSRLQ(void); + +void MMX_PSxxW_imm8(void); +void MMX_PSxxD_imm8(void); +void MMX_PSxxQ_imm8(void); + +void MMX_PSUBB(void); +void MMX_PSUBW(void); +void MMX_PSUBD(void); + +void MMX_PSUBSB(void); +void MMX_PSUBSW(void); + +void MMX_PSUBUSB(void); +void MMX_PSUBUSW(void); + +void MMX_PUNPCKHBW(void); +void MMX_PUNPCKHWD(void); +void MMX_PUNPCKHDQ(void); +void MMX_PUNPCKLBW(void); +void MMX_PUNPCKLWD(void); +void MMX_PUNPCKLDQ(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_MMX_MMX_H__ */ diff --git a/i386c/ia32/instructions/mmx/mmx2.txt b/i386c/ia32/instructions/mmx/mmx2.txt old mode 100755 new mode 100644 index 0df91de6..b624df9d --- a/i386c/ia32/instructions/mmx/mmx2.txt +++ b/i386c/ia32/instructions/mmx/mmx2.txt @@ -1,2091 +1,2091 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include - -#include -#include "ia32/ia32.mcr" - -#include "ia32/instructions/mmx/mmx.h" - -#if defined(USE_MMX) && defined(USE_FPU) - -#define CPU_MMXWORKCLOCK CPU_WORKCLOCK(6) - -static INLINE void -MMX_check_NM_EXCEPTION(){ - // MMXなしならUD(無効オペコード例外)を発生させる - if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX)){ - EXCEPTION(UD_EXCEPTION, 0); - } - // エミュレーションならUD(無効オペコード例外)を発生させる - if(CPU_CR0 & CPU_CR0_EM){ - EXCEPTION(UD_EXCEPTION, 0); - } - // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる - if (CPU_CR0 & CPU_CR0_TS) { - EXCEPTION(NM_EXCEPTION, 0); - } -} - -static INLINE void -MMX_setTag(void) -{ - int i; - - if(!FPU_STAT.mmxenable){ - FPU_STAT.mmxenable = 1; - //FPU_CTRLWORD = 0x27F; - for (i = 0; i < FPU_REG_NUM; i++) { - FPU_STAT.tag[i] = TAG_Valid; -#ifdef SUPPORT_FPU_DOSBOX2 - FPU_STAT.int_regvalid[i] = 0; -#endif - FPU_STAT.reg[i].ul.ext = 0xffff; - } - } - FPU_STAT_TOP = 0; - FPU_STATUSWORD &= ~0x3800; - FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; -} - -/* - * MMX interface - */ -void -MMX_EMMS(void) -{ - int i; - - // MMXなしならUD(無効オペコード例外)を発生させる - if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX)){ - EXCEPTION(UD_EXCEPTION, 0); - } - // エミュレーションならUD(無効オペコード例外)を発生させる - if(CPU_CR0 & CPU_CR0_EM){ - EXCEPTION(UD_EXCEPTION, 0); - } - // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる - if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { - EXCEPTION(NM_EXCEPTION, 0); - } - - CPU_WORKCLOCK(2); - for (i = 0; i < FPU_REG_NUM; i++) { - FPU_STAT.tag[i] = TAG_Empty; - } - FPU_STAT_TOP = 0; - FPU_STATUSWORD &= ~0x3800; - FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; - FPU_STAT.mmxenable = 0; -} - -// *********** MOV - -void MMX_MOVD_mm_rm32(void) -{ - UINT32 op, src; - UINT idx, sub; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - (src) = *(reg32_b20[(op)]); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - (src) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - } - FPU_STAT.reg[idx].ul.lower = src; - FPU_STAT.reg[idx].ul.upper = 0; -} -void MMX_MOVD_rm32_mm(void) -{ - UINT32 op, src, madr; - UINT idx, sub; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - src = FPU_STAT.reg[idx].ul.lower; - if (op >= 0xc0) { - *(reg32_b20[op]) = src; - } else { - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); - } -} - -void MMX_MOVQ_mm_mmm64(void) -{ - UINT32 op; - UINT idx, sub; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.reg[idx].ll = FPU_STAT.reg[sub].ll; - } else { - UINT32 madr; - madr = calc_ea_dst(op); - FPU_STAT.reg[idx].ll = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); - //FPU_STAT.reg[idx].ul.lower = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - //FPU_STAT.reg[idx].ul.upper = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr+4); - } -} -void MMX_MOVQ_mmm64_mm(void) -{ - UINT32 op; - UINT idx, sub; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.reg[sub].ll = FPU_STAT.reg[idx].ll; - } else { - UINT32 madr; - madr = calc_ea_dst(op); - cpu_vmemorywrite_q(CPU_INST_SEGREG_INDEX, madr, FPU_STAT.reg[idx].ll); - //cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, FPU_STAT.reg[idx].ul.lower); - //cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+4, FPU_STAT.reg[idx].ul.upper); - } -} - - -// *********** PACK - -void MMX_PACKSSWB(void) -{ - UINT32 op; - UINT idx, sub; - INT16 srcreg2buf[4]; - INT16 *srcreg1; - INT16 *srcreg2; - INT8 *dstreg; - INT8 dstregbuf[8]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); - srcreg2 = (INT16*)(&(FPU_STAT.reg[sub])); - dstreg = (INT8*)(&(FPU_STAT.reg[idx])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcreg2buf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcreg2buf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); - srcreg2 = (INT16*)(&srcreg2buf); - dstreg = (INT8*)(&(FPU_STAT.reg[idx])); - } - for(i=0;i<4;i++){ - if(srcreg1[i] > 127){ - dstregbuf[i] = 127; - }else if(srcreg1[i] < -128){ - dstregbuf[i] = -128; - }else{ - dstregbuf[i] = (INT8)(srcreg1[i]); - } - } - for(i=0;i<4;i++){ - if(srcreg2[i] > 127){ - dstregbuf[i+4] = 127; - }else if(srcreg2[i] < -128){ - dstregbuf[i+4] = -128; - }else{ - dstregbuf[i+4] = (INT8)(srcreg2[i]); - } - } - for(i=0;i<8;i++){ - dstreg[i] = dstregbuf[i]; - } -} -void MMX_PACKSSDW(void) -{ - UINT32 op; - UINT idx, sub; - INT32 srcreg2buf[2]; - INT32 *srcreg1; - INT32 *srcreg2; - INT16 *dstreg; - INT16 dstregbuf[4]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg1 = (INT32*)(&(FPU_STAT.reg[idx])); - srcreg2 = (INT32*)(&(FPU_STAT.reg[sub])); - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcreg2buf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcreg2buf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg1 = (INT32*)(&(FPU_STAT.reg[idx])); - srcreg2 = (INT32*)(&srcreg2buf); - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - } - for(i=0;i<2;i++){ - if(srcreg1[i] > 32767){ - dstregbuf[i] = 32767; - }else if(srcreg1[i] < -32768){ - dstregbuf[i] = -32768; - }else{ - dstregbuf[i] = (INT16)(srcreg1[i]); - } - } - for(i=0;i<2;i++){ - if(srcreg2[i] > 32767){ - dstregbuf[i+2] = 32767; - }else if(srcreg2[i] < -32768){ - dstregbuf[i+2] = -32768; - }else{ - dstregbuf[i+2] = (INT16)(srcreg2[i]); - } - } - for(i=0;i<4;i++){ - dstreg[i] = dstregbuf[i]; - } -} - -void MMX_PACKUSWB(void) -{ - UINT32 op; - UINT idx, sub; - INT16 srcreg2buf[4]; - INT16 *srcreg1; - INT16 *srcreg2; - UINT8 *dstreg; - UINT8 dstregbuf[8]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); - srcreg2 = (INT16*)(&(FPU_STAT.reg[sub])); - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcreg2buf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcreg2buf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); - srcreg2 = (INT16*)(&srcreg2buf); - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - } - for(i=0;i<4;i++){ - if(srcreg1[i] > 255){ - dstregbuf[i] = 255; - }else if(srcreg1[i] < 0){ - dstregbuf[i] = 0; - }else{ - dstregbuf[i] = (UINT8)(srcreg1[i]); - } - } - for(i=0;i<4;i++){ - if(srcreg2[i] > 255){ - dstregbuf[i+4] = 255; - }else if(srcreg2[i] < 0){ - dstregbuf[i+4] = 0; - }else{ - dstregbuf[i+4] = (UINT8)(srcreg2[i]); - } - } - for(i=0;i<8;i++){ - dstreg[i] = dstregbuf[i]; - } -} - -// *********** PADD - -void MMX_PADDB(void) -{ - UINT32 op; - UINT idx, sub; - UINT8 srcregbuf[8]; - UINT8 *srcreg; - UINT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT8*)(srcregbuf); - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - dstreg[i] += srcreg[i]; - } -} -void MMX_PADDW(void) -{ - UINT32 op; - UINT idx, sub; - UINT16 srcregbuf[4]; - UINT16 *srcreg; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT16*)(srcregbuf); - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstreg[i] += srcreg[i]; - } -} -void MMX_PADDD(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 srcregbuf[2]; - UINT32 *srcreg; - UINT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT32*)(srcregbuf); - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - dstreg[i] += srcreg[i]; - } -} - -void MMX_PADDSB(void) -{ - UINT32 op; - UINT idx, sub; - INT8 srcregbuf[8]; - INT8 *srcreg; - INT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (INT8*)(srcregbuf); - } - dstreg = (INT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - INT16 cbuf = (INT16)dstreg[i] + (INT16)srcreg[i]; - if(cbuf > 127){ - dstreg[i] = 127; - }else if(cbuf < -128){ - dstreg[i] = -128; - }else{ - dstreg[i] = (INT8)cbuf; - } - } -} -void MMX_PADDSW(void) -{ - UINT32 op; - UINT idx, sub; - INT16 srcregbuf[4]; - INT16 *srcreg; - INT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (INT16*)(srcregbuf); - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - INT32 cbuf = (INT32)dstreg[i] + (INT32)srcreg[i]; - if(cbuf > 32767){ - dstreg[i] = 32767; - }else if(cbuf < -32768){ - dstreg[i] = -32768; - }else{ - dstreg[i] = (INT16)cbuf; - } - } -} - -void MMX_PADDUSB(void) -{ - UINT32 op; - UINT idx, sub; - UINT8 srcregbuf[8]; - UINT8 *srcreg; - UINT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT8*)(srcregbuf); - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - UINT16 cbuf = (UINT16)dstreg[i] + (UINT16)srcreg[i]; - if(cbuf > 255){ - dstreg[i] = 255; - }else{ - dstreg[i] = (UINT8)cbuf; - } - } -} -void MMX_PADDUSW(void) -{ - UINT32 op; - UINT idx, sub; - UINT16 srcregbuf[4]; - UINT16 *srcreg; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT16*)(srcregbuf); - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - UINT32 cbuf = (UINT32)dstreg[i] + (UINT32)srcreg[i]; - if(cbuf > 65535){ - dstreg[i] = 65535; - }else{ - dstreg[i] = (UINT16)cbuf; - } - } -} - -// *********** PAND/ANDN,OR,XOR - -void MMX_PAND(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 srcregbuf[2]; - UINT32 *srcreg; - UINT32 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT32*)(srcregbuf); - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - dstreg[0] = dstreg[0] & srcreg[0]; - dstreg[1] = dstreg[1] & srcreg[1]; -} -void MMX_PANDN(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 srcregbuf[2]; - UINT32 *srcreg; - UINT32 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT32*)(srcregbuf); - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - //dstreg[0] = ~(dstreg[0] & srcreg[0]); - //dstreg[1] = ~(dstreg[1] & srcreg[1]); - dstreg[0] = (~dstreg[0]) & srcreg[0]; - dstreg[1] = (~dstreg[1]) & srcreg[1]; -} -void MMX_POR(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 srcregbuf[2]; - UINT32 *srcreg; - UINT32 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT32*)(srcregbuf); - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - dstreg[0] = dstreg[0] | srcreg[0]; - dstreg[1] = dstreg[1] | srcreg[1]; -} -void MMX_PXOR(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 srcregbuf[2]; - UINT32 *srcreg; - UINT32 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT32*)(srcregbuf); - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - dstreg[0] = dstreg[0] ^ srcreg[0]; - dstreg[1] = dstreg[1] ^ srcreg[1]; -} - -// *********** PCMPEQ - -void MMX_PCMPEQB(void) -{ - UINT32 op; - UINT idx, sub; - UINT8 srcregbuf[8]; - UINT8 *srcreg; - UINT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT8*)(srcregbuf); - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - if(dstreg[i] == srcreg[i]){ - dstreg[i] = 0xff; - }else{ - dstreg[i] = 0; - } - } -} -void MMX_PCMPEQW(void) -{ - UINT32 op; - UINT idx, sub; - UINT16 srcregbuf[4]; - UINT16 *srcreg; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT16*)(srcregbuf); - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - if(dstreg[i] == srcreg[i]){ - dstreg[i] = 0xffff; - }else{ - dstreg[i] = 0; - } - } -} -void MMX_PCMPEQD(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 srcregbuf[2]; - UINT32 *srcreg; - UINT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT32*)(srcregbuf); - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - if(dstreg[i] == srcreg[i]){ - dstreg[i] = 0xffffffff; - }else{ - dstreg[i] = 0; - } - } -} - -// *********** PCMPGT - -void MMX_PCMPGTB(void) -{ - UINT32 op; - UINT idx, sub; - INT8 srcregbuf[8]; - INT8 *srcreg; - INT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (INT8*)(srcregbuf); - } - dstreg = (INT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - if(dstreg[i] > srcreg[i]){ - dstreg[i] = 0xff; - }else{ - dstreg[i] = 0; - } - } -} -void MMX_PCMPGTW(void) -{ - UINT32 op; - UINT idx, sub; - INT16 srcregbuf[4]; - INT16 *srcreg; - INT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (INT16*)(srcregbuf); - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - if(dstreg[i] > srcreg[i]){ - dstreg[i] = 0xffff; - }else{ - dstreg[i] = 0; - } - } -} -void MMX_PCMPGTD(void) -{ - UINT32 op; - UINT idx, sub; - INT32 srcregbuf[2]; - INT32 *srcreg; - INT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (INT32*)(srcregbuf); - } - dstreg = (INT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - if(dstreg[i] > srcreg[i]){ - dstreg[i] = 0xffffffff; - }else{ - dstreg[i] = 0; - } - } -} - -// *********** PMADDWD -void MMX_PMADDWD(void) -{ - UINT32 op; - UINT idx, sub; - INT16 srcregbuf[4]; - INT16 *srcreg; - INT16 *dstreg; - INT32 *dstreg32; - INT32 dstregbuf[2]; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (INT16*)(srcregbuf); - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - dstreg32 = (INT32*)(&(FPU_STAT.reg[idx])); - - dstregbuf[0] = (INT32)srcreg[0] * (INT32)dstreg[0] + (INT32)srcreg[1] * (INT32)dstreg[1]; - dstregbuf[1] = (INT32)srcreg[2] * (INT32)dstreg[2] + (INT32)srcreg[3] * (INT32)dstreg[3]; - dstreg32[0] = dstregbuf[0]; - dstreg32[1] = dstregbuf[1]; -} - -// *********** PMUL -void MMX_PMULHW(void) -{ - UINT32 op; - UINT idx, sub; - INT16 srcregbuf[4]; - INT16 *srcreg; - INT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (INT16*)(srcregbuf); - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstreg[i] = (INT16)((((INT32)srcreg[i] * (INT32)dstreg[i]) >> 16) & 0xffff); - } -} -void MMX_PMULLW(void) -{ - UINT32 op; - UINT idx, sub; - INT16 srcregbuf[4]; - INT16 *srcreg; - INT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (INT16*)(srcregbuf); - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstreg[i] = (INT16)((((INT32)srcreg[i] * (INT32)dstreg[i])) & 0xffff); - } -} - -// *********** PSLL -void MMX_PSLLW(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - //dstreg[i] = (dstreg[i] << shift); - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } -} -void MMX_PSLLD(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - //dstreg[i] = (dstreg[i] << shift); - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } -} -void MMX_PSLLQ(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT64 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT64*)(&(FPU_STAT.reg[idx])); - - //dstreg[0] = (dstreg[0] << shift); - dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) -} - -// *********** PSRA - -void MMX_PSRAW(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT16 *dstreg; - UINT16 signval; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - // 無理やり算術シフト(怪しい) - if(16 <= shift){ - signval = 0xffff; - }else{ - UINT32 rshift = 16 - shift; - signval = (0xffff >> rshift) << rshift; - } - for(i=0;i<4;i++){ - if(((INT16*)dstreg)[i] < 0){ - dstreg[i] = (dstreg[i] >> shift) | signval; - }else{ - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } -} -void MMX_PSRAD(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT32 *dstreg; - UINT32 signval; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - // 無理やり算術シフト(怪しい) - if(32 <= shift){ - signval = 0xffffffff; - }else{ - UINT32 rshift = 32 - shift; - signval = (0xffffffff >> rshift) << rshift; - } - for(i=0;i<2;i++){ - if(((INT32*)dstreg)[i] < 0){ - dstreg[i] = (dstreg[i] >> shift) | signval; - }else{ - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } -} - -// *********** PSRL -void MMX_PSRLW(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - //dstreg[i] = (dstreg[i] >> shift); - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } -} -void MMX_PSRLD(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - //dstreg[i] = (dstreg[i] >> shift); - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } -} -void MMX_PSRLQ(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT64 *dstreg; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - shift = FPU_STAT.reg[sub].ul.lower; - if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: シフトしすぎ - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: シフトしすぎ - } - dstreg = (UINT64*)(&(FPU_STAT.reg[idx])); - - //dstreg[0] = (dstreg[0] >> shift); - dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) -} - -// *********** PSLL(imm8),PSRL(imm8),PSRA(imm8) -void MMX_PSxxW_imm8(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT16 *dstreg; - UINT16 signval; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - dstreg = (UINT16*)(&(FPU_STAT.reg[sub])); - GET_PCBYTE((shift)); - - switch(idx){ - case 2: // PSRLW(imm8) - for(i=0;i<4;i++){ - dstreg[i] = (shift >= 16 ? 0 : (dstreg[0] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - break; - case 4: // PSRAW(imm8) - // 無理やり算術シフト(怪しい) - if(16 <= shift){ - signval = 0xffff; - }else{ - UINT32 rshift = 16 - shift; - signval = (0xffff >> rshift) << rshift; - } - for(i=0;i<4;i++){ - if(((INT16*)dstreg)[i] < 0){ - dstreg[i] = (dstreg[i] >> shift) | signval; - }else{ - dstreg[i] = (shift >= 16 ? 0 : (dstreg[0] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } - break; - case 6: // PSLLW(imm8) - for(i=0;i<4;i++){ - dstreg[i] = (shift >= 16 ? 0 : (dstreg[0] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } - break; - default: - break; - } -} -void MMX_PSxxD_imm8(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT32 *dstreg; - UINT32 signval; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - dstreg = (UINT32*)(&(FPU_STAT.reg[sub])); - GET_PCBYTE((shift)); - - switch(idx){ - case 2: // PSRLD(imm8) - for(i=0;i<2;i++){ - dstreg[i] = (shift >= 32 ? 0 : (dstreg[0] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - break; - case 4: // PSRAD(imm8) - // 無理やり算術シフト(怪しい) - if(32 <= shift){ - signval = 0xffffffff; - }else{ - UINT32 rshift = 32 - shift; - signval = (0xffffffff >> rshift) << rshift; - } - for(i=0;i<2;i++){ - if(((INT32*)dstreg)[i] < 0){ - dstreg[i] = (dstreg[i] >> shift) | signval; - }else{ - dstreg[i] = (shift >= 32 ? 0 : (dstreg[0] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } - break; - case 6: // PSLLD(imm8) - for(i=0;i<2;i++){ - dstreg[i] = (shift >= 32 ? 0 : (dstreg[0] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } - break; - default: - break; - } -} -void MMX_PSxxQ_imm8(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT64 *dstreg; - UINT32 signval; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - dstreg = (UINT64*)(&(FPU_STAT.reg[sub])); - GET_PCBYTE((shift)); - - switch(idx){ - case 2: // PSRLQ(imm8) - dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - break; - case 4: // PSRAQ(imm8) - EXCEPTION(UD_EXCEPTION, 0); - break; - case 6: // PSLLQ(imm8) - dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - break; - default: - break; - } -} - -// *********** PSUB - -void MMX_PSUBB(void) -{ - UINT32 op; - UINT idx, sub; - UINT8 srcregbuf[8]; - UINT8 *srcreg; - UINT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT8*)(srcregbuf); - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - dstreg[i] -= srcreg[i]; - } -} -void MMX_PSUBW(void) -{ - UINT32 op; - UINT idx, sub; - UINT16 srcregbuf[4]; - UINT16 *srcreg; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT16*)(srcregbuf); - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstreg[i] -= srcreg[i]; - } -} -void MMX_PSUBD(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 srcregbuf[2]; - UINT32 *srcreg; - UINT32 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT32*)(srcregbuf); - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - dstreg[i] -= srcreg[i]; - } -} - -void MMX_PSUBSB(void) -{ - UINT32 op; - UINT idx, sub; - INT8 srcregbuf[8]; - INT8 *srcreg; - INT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (INT8*)(srcregbuf); - } - dstreg = (INT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - INT16 cbuf = (INT16)dstreg[i] - (INT16)srcreg[i]; - if(cbuf > 127){ - dstreg[i] = 127; - }else if(cbuf < -128){ - dstreg[i] = -128; - }else{ - dstreg[i] = (INT8)cbuf; - } - } -} -void MMX_PSUBSW(void) -{ - UINT32 op; - UINT idx, sub; - INT16 srcregbuf[4]; - INT16 *srcreg; - INT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (INT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (INT16*)(srcregbuf); - } - dstreg = (INT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - INT32 cbuf = (INT32)dstreg[i] - (INT32)srcreg[i]; - if(cbuf > 32767){ - dstreg[i] = 32767; - }else if(cbuf < -32768){ - dstreg[i] = -32768; - }else{ - dstreg[i] = (INT16)cbuf; - } - } -} - -void MMX_PSUBUSB(void) -{ - UINT32 op; - UINT idx, sub; - UINT8 srcregbuf[8]; - UINT8 *srcreg; - UINT8 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT8*)(srcregbuf); - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<8;i++){ - INT16 cbuf = (INT16)dstreg[i] - (INT16)srcreg[i]; - if(cbuf > 255){ - dstreg[i] = 255; - }else if(cbuf < 0){ - dstreg[i] = 0; - }else{ - dstreg[i] = (UINT8)cbuf; - } - } -} -void MMX_PSUBUSW(void) -{ - UINT32 op; - UINT idx, sub; - UINT16 srcregbuf[4]; - UINT16 *srcreg; - UINT16 *dstreg; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT16*)(srcregbuf); - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - INT32 cbuf = (INT32)dstreg[i] - (INT32)srcreg[i]; - if(cbuf > 65535){ - dstreg[i] = 65535; - }else if(cbuf < 0){ - dstreg[i] = 0; - }else{ - dstreg[i] = (UINT16)cbuf; - } - } -} - -// *********** PUNPCK - -void MMX_PUNPCKHBW(void) -{ - UINT32 op; - UINT idx, sub; - UINT8 srcregbuf[8]; - UINT8 *srcreg; - UINT8 *dstreg; - UINT8 dstregbuf[8]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT8*)(srcregbuf); - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstregbuf[i*2] = dstreg[i+4]; - dstregbuf[i*2 + 1] = srcreg[i+4]; - } - for(i=0;i<8;i++){ - dstreg[i] = dstregbuf[i]; - } -} -void MMX_PUNPCKHWD(void) -{ - UINT32 op; - UINT idx, sub; - UINT16 srcregbuf[4]; - UINT16 *srcreg; - UINT16 *dstreg; - UINT16 dstregbuf[4]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT16*)(srcregbuf); - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - dstregbuf[i*2] = dstreg[i+2]; - dstregbuf[i*2 + 1] = srcreg[i+2]; - } - for(i=0;i<4;i++){ - dstreg[i] = dstregbuf[i]; - } -} -void MMX_PUNPCKHDQ(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 srcregbuf[2]; - UINT32 *srcreg; - UINT32 *dstreg; - UINT32 dstregbuf[2]; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT32*)(srcregbuf); - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - dstregbuf[0] = dstreg[1]; - dstregbuf[1] = srcreg[1]; - dstreg[0] = dstregbuf[0]; - dstreg[1] = dstregbuf[1]; -} -void MMX_PUNPCKLBW(void) -{ - UINT32 op; - UINT idx, sub; - UINT8 srcregbuf[8]; - UINT8 *srcreg; - UINT8 *dstreg; - UINT8 dstregbuf[8]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT8*)(srcregbuf); - } - dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<4;i++){ - dstregbuf[i*2] = dstreg[i]; - dstregbuf[i*2 + 1] = srcreg[i]; - } - for(i=0;i<8;i++){ - dstreg[i] = dstregbuf[i]; - } -} -void MMX_PUNPCKLWD(void) -{ - UINT32 op; - UINT idx, sub; - UINT16 srcregbuf[4]; - UINT16 *srcreg; - UINT16 *dstreg; - UINT16 dstregbuf[4]; - int i; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT16*)(srcregbuf); - } - dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); - - for(i=0;i<2;i++){ - dstregbuf[i*2] = dstreg[i]; - dstregbuf[i*2 + 1] = srcreg[i]; - } - for(i=0;i<4;i++){ - dstreg[i] = dstregbuf[i]; - } -} -void MMX_PUNPCKLDQ(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 srcregbuf[2]; - UINT32 *srcreg; - UINT32 *dstreg; - UINT32 dstregbuf[2]; - - MMX_check_NM_EXCEPTION(); - MMX_setTag(); - CPU_MMXWORKCLOCK; - GET_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - srcreg = (UINT32*)(srcregbuf); - } - dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); - - dstregbuf[0] = dstreg[0]; - dstregbuf[1] = srcreg[0]; - dstreg[0] = dstregbuf[0]; - dstreg[1] = dstregbuf[1]; -} - -#else - -/* - * MMX interface - */ -void -MMX_EMMS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_MOVD_mm_rm32(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_MOVD_rm32_mm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_MOVQ_mm_mmm64(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_MOVQ_mmm64_mm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PACKSSWB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PACKSSDW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PACKUSWB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PADDB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PADDW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PADDD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PADDSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PADDSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PADDUSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PADDUSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PAND(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PANDN(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_POR(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PXOR(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PCMPEQB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PCMPEQW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PCMPEQD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PCMPGTB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PCMPGTW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PCMPGTD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PMADDWD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PMULHW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PMULLW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSLLW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSLLD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSLLQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSRAW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSRAD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSRLW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSRLD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSRLQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSxxW_imm8(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSxxD_imm8(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSxxQ_imm8(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSUBB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSUBW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSUBD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSUBSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSUBSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PSUBUSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PSUBUSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void MMX_PUNPCKHBW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PUNPCKHWD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PUNPCKHDQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PUNPCKLBW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PUNPCKLWD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void MMX_PUNPCKLDQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include + +#include +#include "ia32/ia32.mcr" + +#include "ia32/instructions/mmx/mmx.h" + +#if defined(USE_MMX) && defined(USE_FPU) + +#define CPU_MMXWORKCLOCK CPU_WORKCLOCK(6) + +static INLINE void +MMX_check_NM_EXCEPTION(){ + // MMXなしならUD(無効オペコード例外)を発生させる + if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX)){ + EXCEPTION(UD_EXCEPTION, 0); + } + // エミュレーションならUD(無効オペコード例外)を発生させる + if(CPU_CR0 & CPU_CR0_EM){ + EXCEPTION(UD_EXCEPTION, 0); + } + // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる + if (CPU_CR0 & CPU_CR0_TS) { + EXCEPTION(NM_EXCEPTION, 0); + } +} + +static INLINE void +MMX_setTag(void) +{ + int i; + + if(!FPU_STAT.mmxenable){ + FPU_STAT.mmxenable = 1; + //FPU_CTRLWORD = 0x27F; + for (i = 0; i < FPU_REG_NUM; i++) { + FPU_STAT.tag[i] = TAG_Valid; +#ifdef SUPPORT_FPU_DOSBOX2 + FPU_STAT.int_regvalid[i] = 0; +#endif + FPU_STAT.reg[i].ul.ext = 0xffff; + } + } + FPU_STAT_TOP = 0; + FPU_STATUSWORD &= ~0x3800; + FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; +} + +/* + * MMX interface + */ +void +MMX_EMMS(void) +{ + int i; + + // MMXなしならUD(無効オペコード例外)を発生させる + if(!(i386cpuid.cpu_feature & CPU_FEATURE_MMX)){ + EXCEPTION(UD_EXCEPTION, 0); + } + // エミュレーションならUD(無効オペコード例外)を発生させる + if(CPU_CR0 & CPU_CR0_EM){ + EXCEPTION(UD_EXCEPTION, 0); + } + // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる + if ((CPU_CR0 & (CPU_CR0_TS)) || (CPU_CR0 & CPU_CR0_EM)) { + EXCEPTION(NM_EXCEPTION, 0); + } + + CPU_WORKCLOCK(2); + for (i = 0; i < FPU_REG_NUM; i++) { + FPU_STAT.tag[i] = TAG_Empty; + } + FPU_STAT_TOP = 0; + FPU_STATUSWORD &= ~0x3800; + FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; + FPU_STAT.mmxenable = 0; +} + +// *********** MOV + +void MMX_MOVD_mm_rm32(void) +{ + UINT32 op, src; + UINT idx, sub; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + (src) = *(reg32_b20[(op)]); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + (src) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + } + FPU_STAT.reg[idx].ul.lower = src; + FPU_STAT.reg[idx].ul.upper = 0; +} +void MMX_MOVD_rm32_mm(void) +{ + UINT32 op, src, madr; + UINT idx, sub; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + src = FPU_STAT.reg[idx].ul.lower; + if (op >= 0xc0) { + *(reg32_b20[op]) = src; + } else { + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); + } +} + +void MMX_MOVQ_mm_mmm64(void) +{ + UINT32 op; + UINT idx, sub; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.reg[idx].ll = FPU_STAT.reg[sub].ll; + } else { + UINT32 madr; + madr = calc_ea_dst(op); + FPU_STAT.reg[idx].ll = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); + //FPU_STAT.reg[idx].ul.lower = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + //FPU_STAT.reg[idx].ul.upper = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr+4); + } +} +void MMX_MOVQ_mmm64_mm(void) +{ + UINT32 op; + UINT idx, sub; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.reg[sub].ll = FPU_STAT.reg[idx].ll; + } else { + UINT32 madr; + madr = calc_ea_dst(op); + cpu_vmemorywrite_q(CPU_INST_SEGREG_INDEX, madr, FPU_STAT.reg[idx].ll); + //cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, FPU_STAT.reg[idx].ul.lower); + //cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+4, FPU_STAT.reg[idx].ul.upper); + } +} + + +// *********** PACK + +void MMX_PACKSSWB(void) +{ + UINT32 op; + UINT idx, sub; + INT16 srcreg2buf[4]; + INT16 *srcreg1; + INT16 *srcreg2; + INT8 *dstreg; + INT8 dstregbuf[8]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); + srcreg2 = (INT16*)(&(FPU_STAT.reg[sub])); + dstreg = (INT8*)(&(FPU_STAT.reg[idx])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcreg2buf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcreg2buf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); + srcreg2 = (INT16*)(&srcreg2buf); + dstreg = (INT8*)(&(FPU_STAT.reg[idx])); + } + for(i=0;i<4;i++){ + if(srcreg1[i] > 127){ + dstregbuf[i] = 127; + }else if(srcreg1[i] < -128){ + dstregbuf[i] = -128; + }else{ + dstregbuf[i] = (INT8)(srcreg1[i]); + } + } + for(i=0;i<4;i++){ + if(srcreg2[i] > 127){ + dstregbuf[i+4] = 127; + }else if(srcreg2[i] < -128){ + dstregbuf[i+4] = -128; + }else{ + dstregbuf[i+4] = (INT8)(srcreg2[i]); + } + } + for(i=0;i<8;i++){ + dstreg[i] = dstregbuf[i]; + } +} +void MMX_PACKSSDW(void) +{ + UINT32 op; + UINT idx, sub; + INT32 srcreg2buf[2]; + INT32 *srcreg1; + INT32 *srcreg2; + INT16 *dstreg; + INT16 dstregbuf[4]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg1 = (INT32*)(&(FPU_STAT.reg[idx])); + srcreg2 = (INT32*)(&(FPU_STAT.reg[sub])); + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcreg2buf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcreg2buf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg1 = (INT32*)(&(FPU_STAT.reg[idx])); + srcreg2 = (INT32*)(&srcreg2buf); + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + } + for(i=0;i<2;i++){ + if(srcreg1[i] > 32767){ + dstregbuf[i] = 32767; + }else if(srcreg1[i] < -32768){ + dstregbuf[i] = -32768; + }else{ + dstregbuf[i] = (INT16)(srcreg1[i]); + } + } + for(i=0;i<2;i++){ + if(srcreg2[i] > 32767){ + dstregbuf[i+2] = 32767; + }else if(srcreg2[i] < -32768){ + dstregbuf[i+2] = -32768; + }else{ + dstregbuf[i+2] = (INT16)(srcreg2[i]); + } + } + for(i=0;i<4;i++){ + dstreg[i] = dstregbuf[i]; + } +} + +void MMX_PACKUSWB(void) +{ + UINT32 op; + UINT idx, sub; + INT16 srcreg2buf[4]; + INT16 *srcreg1; + INT16 *srcreg2; + UINT8 *dstreg; + UINT8 dstregbuf[8]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); + srcreg2 = (INT16*)(&(FPU_STAT.reg[sub])); + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcreg2buf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcreg2buf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg1 = (INT16*)(&(FPU_STAT.reg[idx])); + srcreg2 = (INT16*)(&srcreg2buf); + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + } + for(i=0;i<4;i++){ + if(srcreg1[i] > 255){ + dstregbuf[i] = 255; + }else if(srcreg1[i] < 0){ + dstregbuf[i] = 0; + }else{ + dstregbuf[i] = (UINT8)(srcreg1[i]); + } + } + for(i=0;i<4;i++){ + if(srcreg2[i] > 255){ + dstregbuf[i+4] = 255; + }else if(srcreg2[i] < 0){ + dstregbuf[i+4] = 0; + }else{ + dstregbuf[i+4] = (UINT8)(srcreg2[i]); + } + } + for(i=0;i<8;i++){ + dstreg[i] = dstregbuf[i]; + } +} + +// *********** PADD + +void MMX_PADDB(void) +{ + UINT32 op; + UINT idx, sub; + UINT8 srcregbuf[8]; + UINT8 *srcreg; + UINT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT8*)(srcregbuf); + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + dstreg[i] += srcreg[i]; + } +} +void MMX_PADDW(void) +{ + UINT32 op; + UINT idx, sub; + UINT16 srcregbuf[4]; + UINT16 *srcreg; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT16*)(srcregbuf); + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstreg[i] += srcreg[i]; + } +} +void MMX_PADDD(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 srcregbuf[2]; + UINT32 *srcreg; + UINT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT32*)(srcregbuf); + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + dstreg[i] += srcreg[i]; + } +} + +void MMX_PADDSB(void) +{ + UINT32 op; + UINT idx, sub; + INT8 srcregbuf[8]; + INT8 *srcreg; + INT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (INT8*)(srcregbuf); + } + dstreg = (INT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + INT16 cbuf = (INT16)dstreg[i] + (INT16)srcreg[i]; + if(cbuf > 127){ + dstreg[i] = 127; + }else if(cbuf < -128){ + dstreg[i] = -128; + }else{ + dstreg[i] = (INT8)cbuf; + } + } +} +void MMX_PADDSW(void) +{ + UINT32 op; + UINT idx, sub; + INT16 srcregbuf[4]; + INT16 *srcreg; + INT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (INT16*)(srcregbuf); + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + INT32 cbuf = (INT32)dstreg[i] + (INT32)srcreg[i]; + if(cbuf > 32767){ + dstreg[i] = 32767; + }else if(cbuf < -32768){ + dstreg[i] = -32768; + }else{ + dstreg[i] = (INT16)cbuf; + } + } +} + +void MMX_PADDUSB(void) +{ + UINT32 op; + UINT idx, sub; + UINT8 srcregbuf[8]; + UINT8 *srcreg; + UINT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT8*)(srcregbuf); + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + UINT16 cbuf = (UINT16)dstreg[i] + (UINT16)srcreg[i]; + if(cbuf > 255){ + dstreg[i] = 255; + }else{ + dstreg[i] = (UINT8)cbuf; + } + } +} +void MMX_PADDUSW(void) +{ + UINT32 op; + UINT idx, sub; + UINT16 srcregbuf[4]; + UINT16 *srcreg; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT16*)(srcregbuf); + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + UINT32 cbuf = (UINT32)dstreg[i] + (UINT32)srcreg[i]; + if(cbuf > 65535){ + dstreg[i] = 65535; + }else{ + dstreg[i] = (UINT16)cbuf; + } + } +} + +// *********** PAND/ANDN,OR,XOR + +void MMX_PAND(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 srcregbuf[2]; + UINT32 *srcreg; + UINT32 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT32*)(srcregbuf); + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + dstreg[0] = dstreg[0] & srcreg[0]; + dstreg[1] = dstreg[1] & srcreg[1]; +} +void MMX_PANDN(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 srcregbuf[2]; + UINT32 *srcreg; + UINT32 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT32*)(srcregbuf); + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + //dstreg[0] = ~(dstreg[0] & srcreg[0]); + //dstreg[1] = ~(dstreg[1] & srcreg[1]); + dstreg[0] = (~dstreg[0]) & srcreg[0]; + dstreg[1] = (~dstreg[1]) & srcreg[1]; +} +void MMX_POR(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 srcregbuf[2]; + UINT32 *srcreg; + UINT32 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT32*)(srcregbuf); + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + dstreg[0] = dstreg[0] | srcreg[0]; + dstreg[1] = dstreg[1] | srcreg[1]; +} +void MMX_PXOR(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 srcregbuf[2]; + UINT32 *srcreg; + UINT32 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT32*)(srcregbuf); + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + dstreg[0] = dstreg[0] ^ srcreg[0]; + dstreg[1] = dstreg[1] ^ srcreg[1]; +} + +// *********** PCMPEQ + +void MMX_PCMPEQB(void) +{ + UINT32 op; + UINT idx, sub; + UINT8 srcregbuf[8]; + UINT8 *srcreg; + UINT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT8*)(srcregbuf); + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + if(dstreg[i] == srcreg[i]){ + dstreg[i] = 0xff; + }else{ + dstreg[i] = 0; + } + } +} +void MMX_PCMPEQW(void) +{ + UINT32 op; + UINT idx, sub; + UINT16 srcregbuf[4]; + UINT16 *srcreg; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT16*)(srcregbuf); + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + if(dstreg[i] == srcreg[i]){ + dstreg[i] = 0xffff; + }else{ + dstreg[i] = 0; + } + } +} +void MMX_PCMPEQD(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 srcregbuf[2]; + UINT32 *srcreg; + UINT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT32*)(srcregbuf); + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + if(dstreg[i] == srcreg[i]){ + dstreg[i] = 0xffffffff; + }else{ + dstreg[i] = 0; + } + } +} + +// *********** PCMPGT + +void MMX_PCMPGTB(void) +{ + UINT32 op; + UINT idx, sub; + INT8 srcregbuf[8]; + INT8 *srcreg; + INT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (INT8*)(srcregbuf); + } + dstreg = (INT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + if(dstreg[i] > srcreg[i]){ + dstreg[i] = 0xff; + }else{ + dstreg[i] = 0; + } + } +} +void MMX_PCMPGTW(void) +{ + UINT32 op; + UINT idx, sub; + INT16 srcregbuf[4]; + INT16 *srcreg; + INT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (INT16*)(srcregbuf); + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + if(dstreg[i] > srcreg[i]){ + dstreg[i] = 0xffff; + }else{ + dstreg[i] = 0; + } + } +} +void MMX_PCMPGTD(void) +{ + UINT32 op; + UINT idx, sub; + INT32 srcregbuf[2]; + INT32 *srcreg; + INT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (INT32*)(srcregbuf); + } + dstreg = (INT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + if(dstreg[i] > srcreg[i]){ + dstreg[i] = 0xffffffff; + }else{ + dstreg[i] = 0; + } + } +} + +// *********** PMADDWD +void MMX_PMADDWD(void) +{ + UINT32 op; + UINT idx, sub; + INT16 srcregbuf[4]; + INT16 *srcreg; + INT16 *dstreg; + INT32 *dstreg32; + INT32 dstregbuf[2]; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (INT16*)(srcregbuf); + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + dstreg32 = (INT32*)(&(FPU_STAT.reg[idx])); + + dstregbuf[0] = (INT32)srcreg[0] * (INT32)dstreg[0] + (INT32)srcreg[1] * (INT32)dstreg[1]; + dstregbuf[1] = (INT32)srcreg[2] * (INT32)dstreg[2] + (INT32)srcreg[3] * (INT32)dstreg[3]; + dstreg32[0] = dstregbuf[0]; + dstreg32[1] = dstregbuf[1]; +} + +// *********** PMUL +void MMX_PMULHW(void) +{ + UINT32 op; + UINT idx, sub; + INT16 srcregbuf[4]; + INT16 *srcreg; + INT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (INT16*)(srcregbuf); + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstreg[i] = (INT16)((((INT32)srcreg[i] * (INT32)dstreg[i]) >> 16) & 0xffff); + } +} +void MMX_PMULLW(void) +{ + UINT32 op; + UINT idx, sub; + INT16 srcregbuf[4]; + INT16 *srcreg; + INT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (INT16*)(srcregbuf); + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstreg[i] = (INT16)((((INT32)srcreg[i] * (INT32)dstreg[i])) & 0xffff); + } +} + +// *********** PSLL +void MMX_PSLLW(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + //dstreg[i] = (dstreg[i] << shift); + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } +} +void MMX_PSLLD(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + //dstreg[i] = (dstreg[i] << shift); + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } +} +void MMX_PSLLQ(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT64 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT64*)(&(FPU_STAT.reg[idx])); + + //dstreg[0] = (dstreg[0] << shift); + dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) +} + +// *********** PSRA + +void MMX_PSRAW(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT16 *dstreg; + UINT16 signval; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + // 無理やり算術シフト(怪しい) + if(16 <= shift){ + signval = 0xffff; + }else{ + UINT32 rshift = 16 - shift; + signval = (0xffff >> rshift) << rshift; + } + for(i=0;i<4;i++){ + if(((INT16*)dstreg)[i] < 0){ + dstreg[i] = (dstreg[i] >> shift) | signval; + }else{ + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } +} +void MMX_PSRAD(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT32 *dstreg; + UINT32 signval; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + // 無理やり算術シフト(怪しい) + if(32 <= shift){ + signval = 0xffffffff; + }else{ + UINT32 rshift = 32 - shift; + signval = (0xffffffff >> rshift) << rshift; + } + for(i=0;i<2;i++){ + if(((INT32*)dstreg)[i] < 0){ + dstreg[i] = (dstreg[i] >> shift) | signval; + }else{ + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } +} + +// *********** PSRL +void MMX_PSRLW(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + //dstreg[i] = (dstreg[i] >> shift); + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } +} +void MMX_PSRLD(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + //dstreg[i] = (dstreg[i] >> shift); + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } +} +void MMX_PSRLQ(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT64 *dstreg; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + shift = FPU_STAT.reg[sub].ul.lower; + if(FPU_STAT.reg[sub].ul.upper) shift = 0xffffffff; // XXX: シフトしすぎ + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + shift = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + if(cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4)) shift = 0xffffffff; // XXX: シフトしすぎ + } + dstreg = (UINT64*)(&(FPU_STAT.reg[idx])); + + //dstreg[0] = (dstreg[0] >> shift); + dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) +} + +// *********** PSLL(imm8),PSRL(imm8),PSRA(imm8) +void MMX_PSxxW_imm8(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT16 *dstreg; + UINT16 signval; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + dstreg = (UINT16*)(&(FPU_STAT.reg[sub])); + GET_PCBYTE((shift)); + + switch(idx){ + case 2: // PSRLW(imm8) + for(i=0;i<4;i++){ + dstreg[i] = (shift >= 16 ? 0 : (dstreg[0] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + break; + case 4: // PSRAW(imm8) + // 無理やり算術シフト(怪しい) + if(16 <= shift){ + signval = 0xffff; + }else{ + UINT32 rshift = 16 - shift; + signval = (0xffff >> rshift) << rshift; + } + for(i=0;i<4;i++){ + if(((INT16*)dstreg)[i] < 0){ + dstreg[i] = (dstreg[i] >> shift) | signval; + }else{ + dstreg[i] = (shift >= 16 ? 0 : (dstreg[0] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } + break; + case 6: // PSLLW(imm8) + for(i=0;i<4;i++){ + dstreg[i] = (shift >= 16 ? 0 : (dstreg[0] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } + break; + default: + break; + } +} +void MMX_PSxxD_imm8(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT32 *dstreg; + UINT32 signval; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + dstreg = (UINT32*)(&(FPU_STAT.reg[sub])); + GET_PCBYTE((shift)); + + switch(idx){ + case 2: // PSRLD(imm8) + for(i=0;i<2;i++){ + dstreg[i] = (shift >= 32 ? 0 : (dstreg[0] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + break; + case 4: // PSRAD(imm8) + // 無理やり算術シフト(怪しい) + if(32 <= shift){ + signval = 0xffffffff; + }else{ + UINT32 rshift = 32 - shift; + signval = (0xffffffff >> rshift) << rshift; + } + for(i=0;i<2;i++){ + if(((INT32*)dstreg)[i] < 0){ + dstreg[i] = (dstreg[i] >> shift) | signval; + }else{ + dstreg[i] = (shift >= 32 ? 0 : (dstreg[0] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } + break; + case 6: // PSLLD(imm8) + for(i=0;i<2;i++){ + dstreg[i] = (shift >= 32 ? 0 : (dstreg[0] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } + break; + default: + break; + } +} +void MMX_PSxxQ_imm8(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT64 *dstreg; + UINT32 signval; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + dstreg = (UINT64*)(&(FPU_STAT.reg[sub])); + GET_PCBYTE((shift)); + + switch(idx){ + case 2: // PSRLQ(imm8) + dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + break; + case 4: // PSRAQ(imm8) + EXCEPTION(UD_EXCEPTION, 0); + break; + case 6: // PSLLQ(imm8) + dstreg[0] = (shift >= 64 ? 0 : (dstreg[0] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + break; + default: + break; + } +} + +// *********** PSUB + +void MMX_PSUBB(void) +{ + UINT32 op; + UINT idx, sub; + UINT8 srcregbuf[8]; + UINT8 *srcreg; + UINT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT8*)(srcregbuf); + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + dstreg[i] -= srcreg[i]; + } +} +void MMX_PSUBW(void) +{ + UINT32 op; + UINT idx, sub; + UINT16 srcregbuf[4]; + UINT16 *srcreg; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT16*)(srcregbuf); + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstreg[i] -= srcreg[i]; + } +} +void MMX_PSUBD(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 srcregbuf[2]; + UINT32 *srcreg; + UINT32 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT32*)(srcregbuf); + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + dstreg[i] -= srcreg[i]; + } +} + +void MMX_PSUBSB(void) +{ + UINT32 op; + UINT idx, sub; + INT8 srcregbuf[8]; + INT8 *srcreg; + INT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (INT8*)(srcregbuf); + } + dstreg = (INT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + INT16 cbuf = (INT16)dstreg[i] - (INT16)srcreg[i]; + if(cbuf > 127){ + dstreg[i] = 127; + }else if(cbuf < -128){ + dstreg[i] = -128; + }else{ + dstreg[i] = (INT8)cbuf; + } + } +} +void MMX_PSUBSW(void) +{ + UINT32 op; + UINT idx, sub; + INT16 srcregbuf[4]; + INT16 *srcreg; + INT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (INT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (INT16*)(srcregbuf); + } + dstreg = (INT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + INT32 cbuf = (INT32)dstreg[i] - (INT32)srcreg[i]; + if(cbuf > 32767){ + dstreg[i] = 32767; + }else if(cbuf < -32768){ + dstreg[i] = -32768; + }else{ + dstreg[i] = (INT16)cbuf; + } + } +} + +void MMX_PSUBUSB(void) +{ + UINT32 op; + UINT idx, sub; + UINT8 srcregbuf[8]; + UINT8 *srcreg; + UINT8 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT8*)(srcregbuf); + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<8;i++){ + INT16 cbuf = (INT16)dstreg[i] - (INT16)srcreg[i]; + if(cbuf > 255){ + dstreg[i] = 255; + }else if(cbuf < 0){ + dstreg[i] = 0; + }else{ + dstreg[i] = (UINT8)cbuf; + } + } +} +void MMX_PSUBUSW(void) +{ + UINT32 op; + UINT idx, sub; + UINT16 srcregbuf[4]; + UINT16 *srcreg; + UINT16 *dstreg; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT16*)(srcregbuf); + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + INT32 cbuf = (INT32)dstreg[i] - (INT32)srcreg[i]; + if(cbuf > 65535){ + dstreg[i] = 65535; + }else if(cbuf < 0){ + dstreg[i] = 0; + }else{ + dstreg[i] = (UINT16)cbuf; + } + } +} + +// *********** PUNPCK + +void MMX_PUNPCKHBW(void) +{ + UINT32 op; + UINT idx, sub; + UINT8 srcregbuf[8]; + UINT8 *srcreg; + UINT8 *dstreg; + UINT8 dstregbuf[8]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT8*)(srcregbuf); + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstregbuf[i*2] = dstreg[i+4]; + dstregbuf[i*2 + 1] = srcreg[i+4]; + } + for(i=0;i<8;i++){ + dstreg[i] = dstregbuf[i]; + } +} +void MMX_PUNPCKHWD(void) +{ + UINT32 op; + UINT idx, sub; + UINT16 srcregbuf[4]; + UINT16 *srcreg; + UINT16 *dstreg; + UINT16 dstregbuf[4]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT16*)(srcregbuf); + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + dstregbuf[i*2] = dstreg[i+2]; + dstregbuf[i*2 + 1] = srcreg[i+2]; + } + for(i=0;i<4;i++){ + dstreg[i] = dstregbuf[i]; + } +} +void MMX_PUNPCKHDQ(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 srcregbuf[2]; + UINT32 *srcreg; + UINT32 *dstreg; + UINT32 dstregbuf[2]; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT32*)(srcregbuf); + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + dstregbuf[0] = dstreg[1]; + dstregbuf[1] = srcreg[1]; + dstreg[0] = dstregbuf[0]; + dstreg[1] = dstregbuf[1]; +} +void MMX_PUNPCKLBW(void) +{ + UINT32 op; + UINT idx, sub; + UINT8 srcregbuf[8]; + UINT8 *srcreg; + UINT8 *dstreg; + UINT8 dstregbuf[8]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT8*)(srcregbuf); + } + dstreg = (UINT8*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<4;i++){ + dstregbuf[i*2] = dstreg[i]; + dstregbuf[i*2 + 1] = srcreg[i]; + } + for(i=0;i<8;i++){ + dstreg[i] = dstregbuf[i]; + } +} +void MMX_PUNPCKLWD(void) +{ + UINT32 op; + UINT idx, sub; + UINT16 srcregbuf[4]; + UINT16 *srcreg; + UINT16 *dstreg; + UINT16 dstregbuf[4]; + int i; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT16*)(srcregbuf); + } + dstreg = (UINT16*)(&(FPU_STAT.reg[idx])); + + for(i=0;i<2;i++){ + dstregbuf[i*2] = dstreg[i]; + dstregbuf[i*2 + 1] = srcreg[i]; + } + for(i=0;i<4;i++){ + dstreg[i] = dstregbuf[i]; + } +} +void MMX_PUNPCKLDQ(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 srcregbuf[2]; + UINT32 *srcreg; + UINT32 *dstreg; + UINT32 dstregbuf[2]; + + MMX_check_NM_EXCEPTION(); + MMX_setTag(); + CPU_MMXWORKCLOCK; + GET_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg = (UINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(srcregbuf+0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + *((UINT32*)(srcregbuf+1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + srcreg = (UINT32*)(srcregbuf); + } + dstreg = (UINT32*)(&(FPU_STAT.reg[idx])); + + dstregbuf[0] = dstreg[0]; + dstregbuf[1] = srcreg[0]; + dstreg[0] = dstregbuf[0]; + dstreg[1] = dstregbuf[1]; +} + +#else + +/* + * MMX interface + */ +void +MMX_EMMS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_MOVD_mm_rm32(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_MOVD_rm32_mm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_MOVQ_mm_mmm64(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_MOVQ_mmm64_mm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PACKSSWB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PACKSSDW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PACKUSWB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PADDB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PADDW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PADDD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PADDSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PADDSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PADDUSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PADDUSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PAND(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PANDN(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_POR(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PXOR(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PCMPEQB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PCMPEQW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PCMPEQD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PCMPGTB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PCMPGTW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PCMPGTD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PMADDWD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PMULHW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PMULLW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSLLW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSLLD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSLLQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSRAW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSRAD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSRLW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSRLD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSRLQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSxxW_imm8(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSxxD_imm8(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSxxQ_imm8(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSUBB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSUBW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSUBD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSUBSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSUBSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PSUBUSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PSUBUSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void MMX_PUNPCKHBW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PUNPCKHWD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PUNPCKHDQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PUNPCKLBW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PUNPCKLWD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void MMX_PUNPCKLDQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} #endif \ No newline at end of file diff --git a/i386c/ia32/instructions/seg_reg.c b/i386c/ia32/instructions/seg_reg.c old mode 100755 new mode 100644 index a19a4e85..1f076c75 --- a/i386c/ia32/instructions/seg_reg.c +++ b/i386c/ia32/instructions/seg_reg.c @@ -1,231 +1,231 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" - -#include "seg_reg.h" - - -void -LES_GwMp(void) -{ - UINT16 *out; - UINT32 op, dst, madr; - UINT16 sreg; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - out = CPU_REG16_B53(op); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); - LOAD_SEGREG(CPU_ES_INDEX, sreg); - *out = (UINT16)dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LES_GdMp(void) -{ - UINT32 *out; - UINT32 op, dst, madr; - UINT16 sreg; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - out = CPU_REG32_B53(op); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); - LOAD_SEGREG(CPU_ES_INDEX, sreg); - *out = dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LSS_GwMp(void) -{ - UINT16 *out; - UINT32 op, dst, madr; - UINT16 sreg; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - out = CPU_REG16_B53(op); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); - LOAD_SEGREG(CPU_SS_INDEX, sreg); - *out = (UINT16)dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LSS_GdMp(void) -{ - UINT32 *out; - UINT32 op, dst, madr; - UINT16 sreg; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - out = CPU_REG32_B53(op); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); - LOAD_SEGREG(CPU_SS_INDEX, sreg); - *out = dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LDS_GwMp(void) -{ - UINT16 *out; - UINT32 op, dst, madr; - UINT16 sreg; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - out = CPU_REG16_B53(op); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); - LOAD_SEGREG(CPU_DS_INDEX, sreg); - *out = (UINT16)dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LDS_GdMp(void) -{ - UINT32 *out; - UINT32 op, dst, madr; - UINT16 sreg; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - out = CPU_REG32_B53(op); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); - LOAD_SEGREG(CPU_DS_INDEX, sreg); - *out = dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LFS_GwMp(void) -{ - UINT16 *out; - UINT32 op, dst, madr; - UINT16 sreg; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - out = CPU_REG16_B53(op); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); - LOAD_SEGREG(CPU_FS_INDEX, sreg); - *out = (UINT16)dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LFS_GdMp(void) -{ - UINT32 *out; - UINT32 op, dst, madr; - UINT16 sreg; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - out = CPU_REG32_B53(op); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); - LOAD_SEGREG(CPU_FS_INDEX, sreg); - *out = dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LGS_GwMp(void) -{ - UINT16 *out; - UINT32 op, dst, madr; - UINT16 sreg; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - out = CPU_REG16_B53(op); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); - LOAD_SEGREG(CPU_GS_INDEX, sreg); - *out = (UINT16)dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LGS_GdMp(void) -{ - UINT32 *out; - UINT32 op, dst, madr; - UINT16 sreg; - - GET_MODRM_PCBYTE(op); - if (op < 0xc0) { - out = CPU_REG32_B53(op); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); - sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); - LOAD_SEGREG(CPU_GS_INDEX, sreg); - *out = dst; - return; - } - EXCEPTION(UD_EXCEPTION, 0); +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" + +#include "seg_reg.h" + + +void +LES_GwMp(void) +{ + UINT16 *out; + UINT32 op, dst, madr; + UINT16 sreg; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + out = CPU_REG16_B53(op); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); + LOAD_SEGREG(CPU_ES_INDEX, sreg); + *out = (UINT16)dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LES_GdMp(void) +{ + UINT32 *out; + UINT32 op, dst, madr; + UINT16 sreg; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + out = CPU_REG32_B53(op); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); + LOAD_SEGREG(CPU_ES_INDEX, sreg); + *out = dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LSS_GwMp(void) +{ + UINT16 *out; + UINT32 op, dst, madr; + UINT16 sreg; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + out = CPU_REG16_B53(op); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); + LOAD_SEGREG(CPU_SS_INDEX, sreg); + *out = (UINT16)dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LSS_GdMp(void) +{ + UINT32 *out; + UINT32 op, dst, madr; + UINT16 sreg; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + out = CPU_REG32_B53(op); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); + LOAD_SEGREG(CPU_SS_INDEX, sreg); + *out = dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LDS_GwMp(void) +{ + UINT16 *out; + UINT32 op, dst, madr; + UINT16 sreg; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + out = CPU_REG16_B53(op); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); + LOAD_SEGREG(CPU_DS_INDEX, sreg); + *out = (UINT16)dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LDS_GdMp(void) +{ + UINT32 *out; + UINT32 op, dst, madr; + UINT16 sreg; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + out = CPU_REG32_B53(op); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); + LOAD_SEGREG(CPU_DS_INDEX, sreg); + *out = dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LFS_GwMp(void) +{ + UINT16 *out; + UINT32 op, dst, madr; + UINT16 sreg; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + out = CPU_REG16_B53(op); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); + LOAD_SEGREG(CPU_FS_INDEX, sreg); + *out = (UINT16)dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LFS_GdMp(void) +{ + UINT32 *out; + UINT32 op, dst, madr; + UINT16 sreg; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + out = CPU_REG32_B53(op); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); + LOAD_SEGREG(CPU_FS_INDEX, sreg); + *out = dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LGS_GwMp(void) +{ + UINT16 *out; + UINT32 op, dst, madr; + UINT16 sreg; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + out = CPU_REG16_B53(op); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 2); + LOAD_SEGREG(CPU_GS_INDEX, sreg); + *out = (UINT16)dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LGS_GdMp(void) +{ + UINT32 *out; + UINT32 op, dst, madr; + UINT16 sreg; + + GET_MODRM_PCBYTE(op); + if (op < 0xc0) { + out = CPU_REG32_B53(op); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr); + sreg = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr + 4); + LOAD_SEGREG(CPU_GS_INDEX, sreg); + *out = dst; + return; + } + EXCEPTION(UD_EXCEPTION, 0); } \ No newline at end of file diff --git a/i386c/ia32/instructions/seg_reg.h b/i386c/ia32/instructions/seg_reg.h old mode 100755 new mode 100644 index 61a9b324..6c5b85a3 --- a/i386c/ia32/instructions/seg_reg.h +++ b/i386c/ia32/instructions/seg_reg.h @@ -1,48 +1,48 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_SEG_REG_H__ -#define IA32_CPU_INSTRUCTION_SEG_REG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -void LES_GwMp(void); -void LES_GdMp(void); -void LSS_GwMp(void); -void LSS_GdMp(void); -void LDS_GwMp(void); -void LDS_GdMp(void); -void LFS_GwMp(void); -void LFS_GdMp(void); -void LGS_GwMp(void); -void LGS_GdMp(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_SEG_REG_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_SEG_REG_H__ +#define IA32_CPU_INSTRUCTION_SEG_REG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void LES_GwMp(void); +void LES_GdMp(void); +void LSS_GwMp(void); +void LSS_GdMp(void); +void LDS_GwMp(void); +void LDS_GdMp(void); +void LFS_GwMp(void); +void LFS_GdMp(void); +void LGS_GwMp(void); +void LGS_GdMp(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_SEG_REG_H__ */ diff --git a/i386c/ia32/instructions/shift_rotate.c b/i386c/ia32/instructions/shift_rotate.c old mode 100755 new mode 100644 index 4702ceda..d3d2f21c --- a/i386c/ia32/instructions/shift_rotate.c +++ b/i386c/ia32/instructions/shift_rotate.c @@ -1,50 +1,50 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" - -#include "shift_rotate.h" -#include "shift_rotate.mcr" - - -/* - * shift - */ -SHIFT_ROTATE_INSTRUCTION(SAR) -SHIFT_ROTATE_INSTRUCTION(SHR) -SHIFT_ROTATE_INSTRUCTION(SHL) -SHxD_INSTRUCTION(SHRD) -SHxD_INSTRUCTION(SHLD) - - -/* - * rotate - */ -SHIFT_ROTATE_INSTRUCTION(ROR) -SHIFT_ROTATE_INSTRUCTION(ROL) -SHIFT_ROTATE_INSTRUCTION(RCR) -SHIFT_ROTATE_INSTRUCTION(RCL) +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" + +#include "shift_rotate.h" +#include "shift_rotate.mcr" + + +/* + * shift + */ +SHIFT_ROTATE_INSTRUCTION(SAR) +SHIFT_ROTATE_INSTRUCTION(SHR) +SHIFT_ROTATE_INSTRUCTION(SHL) +SHxD_INSTRUCTION(SHRD) +SHxD_INSTRUCTION(SHLD) + + +/* + * rotate + */ +SHIFT_ROTATE_INSTRUCTION(ROR) +SHIFT_ROTATE_INSTRUCTION(ROL) +SHIFT_ROTATE_INSTRUCTION(RCR) +SHIFT_ROTATE_INSTRUCTION(RCL) diff --git a/i386c/ia32/instructions/shift_rotate.h b/i386c/ia32/instructions/shift_rotate.h old mode 100755 new mode 100644 index c5603b3c..715e599e --- a/i386c/ia32/instructions/shift_rotate.h +++ b/i386c/ia32/instructions/shift_rotate.h @@ -1,165 +1,165 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_SHIFT_ROTATE_H__ -#define IA32_CPU_INSTRUCTION_SHIFT_ROTATE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * SAR - */ -void CPUCALL SAR_Eb(UINT8 *); -void CPUCALL SAR_Ew(UINT16 *); -void CPUCALL SAR_Ed(UINT32 *); -void CPUCALL SAR_Eb_ext(UINT32); -void CPUCALL SAR_Ew_ext(UINT32); -void CPUCALL SAR_Ed_ext(UINT32); -void CPUCALL SAR_EbCL(UINT8 *, UINT32); -void CPUCALL SAR_EbCL_ext(UINT32, UINT32); -void CPUCALL SAR_EwCL(UINT16 *, UINT32); -void CPUCALL SAR_EwCL_ext(UINT32, UINT32); -void CPUCALL SAR_EdCL(UINT32 *, UINT32); -void CPUCALL SAR_EdCL_ext(UINT32, UINT32); - -/* - * SHR - */ -void CPUCALL SHR_Eb(UINT8 *); -void CPUCALL SHR_Ew(UINT16 *); -void CPUCALL SHR_Ed(UINT32 *); -void CPUCALL SHR_Eb_ext(UINT32); -void CPUCALL SHR_Ew_ext(UINT32); -void CPUCALL SHR_Ed_ext(UINT32); -void CPUCALL SHR_EbCL(UINT8 *, UINT32); -void CPUCALL SHR_EbCL_ext(UINT32, UINT32); -void CPUCALL SHR_EwCL(UINT16 *, UINT32); -void CPUCALL SHR_EwCL_ext(UINT32, UINT32); -void CPUCALL SHR_EdCL(UINT32 *, UINT32); -void CPUCALL SHR_EdCL_ext(UINT32, UINT32); - -/* - * SHL - */ -void CPUCALL SHL_Eb(UINT8 *); -void CPUCALL SHL_Ew(UINT16 *); -void CPUCALL SHL_Ed(UINT32 *); -void CPUCALL SHL_Eb_ext(UINT32); -void CPUCALL SHL_Ew_ext(UINT32); -void CPUCALL SHL_Ed_ext(UINT32); -void CPUCALL SHL_EbCL(UINT8 *, UINT32); -void CPUCALL SHL_EbCL_ext(UINT32, UINT32); -void CPUCALL SHL_EwCL(UINT16 *, UINT32); -void CPUCALL SHL_EwCL_ext(UINT32, UINT32); -void CPUCALL SHL_EdCL(UINT32 *, UINT32); -void CPUCALL SHL_EdCL_ext(UINT32, UINT32); - -/* - * SHRD - */ -void SHRD_EwGwIb(void); -void SHRD_EdGdIb(void); -void SHRD_EwGwCL(void); -void SHRD_EdGdCL(void); - -/* - * SHLD - */ -void SHLD_EwGwIb(void); -void SHLD_EdGdIb(void); -void SHLD_EwGwCL(void); -void SHLD_EdGdCL(void); - -/* - * ROR - */ -void CPUCALL ROR_Eb(UINT8 *); -void CPUCALL ROR_Ew(UINT16 *); -void CPUCALL ROR_Ed(UINT32 *); -void CPUCALL ROR_Eb_ext(UINT32); -void CPUCALL ROR_Ew_ext(UINT32); -void CPUCALL ROR_Ed_ext(UINT32); -void CPUCALL ROR_EbCL(UINT8 *, UINT32); -void CPUCALL ROR_EbCL_ext(UINT32, UINT32); -void CPUCALL ROR_EwCL(UINT16 *, UINT32); -void CPUCALL ROR_EwCL_ext(UINT32, UINT32); -void CPUCALL ROR_EdCL(UINT32 *, UINT32); -void CPUCALL ROR_EdCL_ext(UINT32, UINT32); - -/* - * ROL - */ -void CPUCALL ROL_Eb(UINT8 *); -void CPUCALL ROL_Ew(UINT16 *); -void CPUCALL ROL_Ed(UINT32 *); -void CPUCALL ROL_Eb_ext(UINT32); -void CPUCALL ROL_Ew_ext(UINT32); -void CPUCALL ROL_Ed_ext(UINT32); -void CPUCALL ROL_EbCL(UINT8 *, UINT32); -void CPUCALL ROL_EbCL_ext(UINT32, UINT32); -void CPUCALL ROL_EwCL(UINT16 *, UINT32); -void CPUCALL ROL_EwCL_ext(UINT32, UINT32); -void CPUCALL ROL_EdCL(UINT32 *, UINT32); -void CPUCALL ROL_EdCL_ext(UINT32, UINT32); - -/* - * RCR - */ -void CPUCALL RCR_Eb(UINT8 *); -void CPUCALL RCR_Ew(UINT16 *); -void CPUCALL RCR_Ed(UINT32 *); -void CPUCALL RCR_Eb_ext(UINT32); -void CPUCALL RCR_Ew_ext(UINT32); -void CPUCALL RCR_Ed_ext(UINT32); -void CPUCALL RCR_EbCL(UINT8 *, UINT32); -void CPUCALL RCR_EbCL_ext(UINT32, UINT32); -void CPUCALL RCR_EwCL(UINT16 *, UINT32); -void CPUCALL RCR_EwCL_ext(UINT32, UINT32); -void CPUCALL RCR_EdCL(UINT32 *, UINT32); -void CPUCALL RCR_EdCL_ext(UINT32, UINT32); - -/* - * RCL - */ -void CPUCALL RCL_Eb(UINT8 *); -void CPUCALL RCL_Ew(UINT16 *); -void CPUCALL RCL_Ed(UINT32 *); -void CPUCALL RCL_Eb_ext(UINT32); -void CPUCALL RCL_Ew_ext(UINT32); -void CPUCALL RCL_Ed_ext(UINT32); -void CPUCALL RCL_EbCL(UINT8 *, UINT32); -void CPUCALL RCL_EbCL_ext(UINT32, UINT32); -void CPUCALL RCL_EwCL(UINT16 *, UINT32); -void CPUCALL RCL_EwCL_ext(UINT32, UINT32); -void CPUCALL RCL_EdCL(UINT32 *, UINT32); -void CPUCALL RCL_EdCL_ext(UINT32, UINT32); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_SHIFT_ROTATE_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_SHIFT_ROTATE_H__ +#define IA32_CPU_INSTRUCTION_SHIFT_ROTATE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SAR + */ +void CPUCALL SAR_Eb(UINT8 *); +void CPUCALL SAR_Ew(UINT16 *); +void CPUCALL SAR_Ed(UINT32 *); +void CPUCALL SAR_Eb_ext(UINT32); +void CPUCALL SAR_Ew_ext(UINT32); +void CPUCALL SAR_Ed_ext(UINT32); +void CPUCALL SAR_EbCL(UINT8 *, UINT32); +void CPUCALL SAR_EbCL_ext(UINT32, UINT32); +void CPUCALL SAR_EwCL(UINT16 *, UINT32); +void CPUCALL SAR_EwCL_ext(UINT32, UINT32); +void CPUCALL SAR_EdCL(UINT32 *, UINT32); +void CPUCALL SAR_EdCL_ext(UINT32, UINT32); + +/* + * SHR + */ +void CPUCALL SHR_Eb(UINT8 *); +void CPUCALL SHR_Ew(UINT16 *); +void CPUCALL SHR_Ed(UINT32 *); +void CPUCALL SHR_Eb_ext(UINT32); +void CPUCALL SHR_Ew_ext(UINT32); +void CPUCALL SHR_Ed_ext(UINT32); +void CPUCALL SHR_EbCL(UINT8 *, UINT32); +void CPUCALL SHR_EbCL_ext(UINT32, UINT32); +void CPUCALL SHR_EwCL(UINT16 *, UINT32); +void CPUCALL SHR_EwCL_ext(UINT32, UINT32); +void CPUCALL SHR_EdCL(UINT32 *, UINT32); +void CPUCALL SHR_EdCL_ext(UINT32, UINT32); + +/* + * SHL + */ +void CPUCALL SHL_Eb(UINT8 *); +void CPUCALL SHL_Ew(UINT16 *); +void CPUCALL SHL_Ed(UINT32 *); +void CPUCALL SHL_Eb_ext(UINT32); +void CPUCALL SHL_Ew_ext(UINT32); +void CPUCALL SHL_Ed_ext(UINT32); +void CPUCALL SHL_EbCL(UINT8 *, UINT32); +void CPUCALL SHL_EbCL_ext(UINT32, UINT32); +void CPUCALL SHL_EwCL(UINT16 *, UINT32); +void CPUCALL SHL_EwCL_ext(UINT32, UINT32); +void CPUCALL SHL_EdCL(UINT32 *, UINT32); +void CPUCALL SHL_EdCL_ext(UINT32, UINT32); + +/* + * SHRD + */ +void SHRD_EwGwIb(void); +void SHRD_EdGdIb(void); +void SHRD_EwGwCL(void); +void SHRD_EdGdCL(void); + +/* + * SHLD + */ +void SHLD_EwGwIb(void); +void SHLD_EdGdIb(void); +void SHLD_EwGwCL(void); +void SHLD_EdGdCL(void); + +/* + * ROR + */ +void CPUCALL ROR_Eb(UINT8 *); +void CPUCALL ROR_Ew(UINT16 *); +void CPUCALL ROR_Ed(UINT32 *); +void CPUCALL ROR_Eb_ext(UINT32); +void CPUCALL ROR_Ew_ext(UINT32); +void CPUCALL ROR_Ed_ext(UINT32); +void CPUCALL ROR_EbCL(UINT8 *, UINT32); +void CPUCALL ROR_EbCL_ext(UINT32, UINT32); +void CPUCALL ROR_EwCL(UINT16 *, UINT32); +void CPUCALL ROR_EwCL_ext(UINT32, UINT32); +void CPUCALL ROR_EdCL(UINT32 *, UINT32); +void CPUCALL ROR_EdCL_ext(UINT32, UINT32); + +/* + * ROL + */ +void CPUCALL ROL_Eb(UINT8 *); +void CPUCALL ROL_Ew(UINT16 *); +void CPUCALL ROL_Ed(UINT32 *); +void CPUCALL ROL_Eb_ext(UINT32); +void CPUCALL ROL_Ew_ext(UINT32); +void CPUCALL ROL_Ed_ext(UINT32); +void CPUCALL ROL_EbCL(UINT8 *, UINT32); +void CPUCALL ROL_EbCL_ext(UINT32, UINT32); +void CPUCALL ROL_EwCL(UINT16 *, UINT32); +void CPUCALL ROL_EwCL_ext(UINT32, UINT32); +void CPUCALL ROL_EdCL(UINT32 *, UINT32); +void CPUCALL ROL_EdCL_ext(UINT32, UINT32); + +/* + * RCR + */ +void CPUCALL RCR_Eb(UINT8 *); +void CPUCALL RCR_Ew(UINT16 *); +void CPUCALL RCR_Ed(UINT32 *); +void CPUCALL RCR_Eb_ext(UINT32); +void CPUCALL RCR_Ew_ext(UINT32); +void CPUCALL RCR_Ed_ext(UINT32); +void CPUCALL RCR_EbCL(UINT8 *, UINT32); +void CPUCALL RCR_EbCL_ext(UINT32, UINT32); +void CPUCALL RCR_EwCL(UINT16 *, UINT32); +void CPUCALL RCR_EwCL_ext(UINT32, UINT32); +void CPUCALL RCR_EdCL(UINT32 *, UINT32); +void CPUCALL RCR_EdCL_ext(UINT32, UINT32); + +/* + * RCL + */ +void CPUCALL RCL_Eb(UINT8 *); +void CPUCALL RCL_Ew(UINT16 *); +void CPUCALL RCL_Ed(UINT32 *); +void CPUCALL RCL_Eb_ext(UINT32); +void CPUCALL RCL_Ew_ext(UINT32); +void CPUCALL RCL_Ed_ext(UINT32); +void CPUCALL RCL_EbCL(UINT8 *, UINT32); +void CPUCALL RCL_EbCL_ext(UINT32, UINT32); +void CPUCALL RCL_EwCL(UINT16 *, UINT32); +void CPUCALL RCL_EwCL_ext(UINT32, UINT32); +void CPUCALL RCL_EdCL(UINT32 *, UINT32); +void CPUCALL RCL_EdCL_ext(UINT32, UINT32); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_SHIFT_ROTATE_H__ */ diff --git a/i386c/ia32/instructions/shift_rotate.mcr b/i386c/ia32/instructions/shift_rotate.mcr old mode 100755 new mode 100644 index 41410125..46150aef --- a/i386c/ia32/instructions/shift_rotate.mcr +++ b/i386c/ia32/instructions/shift_rotate.mcr @@ -1,1109 +1,1109 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_SHIFT_ROTATE_MCR__ -#define IA32_CPU_SHIFT_ROTATE_MCR__ - -/* - * shift/rorate instruction macro - */ -#define SHIFT_ROTATE_INSTRUCTION(inst) \ -static UINT32 CPUCALL \ -inst##1(UINT32 src, void *arg) \ -{ \ - UINT32 dst; \ - BYTE_##inst##1(dst, src); \ - return dst; \ -} \ -static UINT32 CPUCALL \ -inst##2(UINT32 src, void *arg) \ -{ \ - UINT32 dst; \ - WORD_##inst##1(dst, src); \ - return dst; \ -} \ -static UINT32 CPUCALL \ -inst##4(UINT32 src, void *arg) \ -{ \ - UINT32 dst; \ - DWORD_##inst##1(dst, src); \ - return dst; \ -} \ -static UINT32 CPUCALL \ -inst##CL1(UINT32 src, void *arg) \ -{ \ - UINT32 cl = PTR_TO_UINT32(arg); \ - UINT32 dst; \ - BYTE_##inst##CL(dst, src, cl); \ - return dst; \ -} \ -static UINT32 CPUCALL \ -inst##CL2(UINT32 src, void *arg) \ -{ \ - UINT32 cl = PTR_TO_UINT32(arg); \ - UINT32 dst; \ - WORD_##inst##CL(dst, src, cl); \ - return dst; \ -} \ -static UINT32 CPUCALL \ -inst##CL4(UINT32 src, void *arg) \ -{ \ - UINT32 cl = PTR_TO_UINT32(arg); \ - UINT32 dst; \ - DWORD_##inst##CL(dst, src, cl); \ - return dst; \ -} \ -\ -void CPUCALL \ -inst##_Eb(UINT8 *out) \ -{ \ - UINT32 src, dst; \ -\ - src = *out; \ - BYTE_##inst##1(dst, src); \ - *out = (UINT8)dst; \ -} \ -\ -void CPUCALL \ -inst##_Eb_ext(UINT32 madr) \ -{ \ -\ - cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, 0); \ -} \ -\ -void CPUCALL \ -inst##_Ew(UINT16 *out) \ -{ \ - UINT32 src, dst; \ -\ - src = *out; \ - WORD_##inst##1(dst, src); \ - *out = (UINT16)dst; \ -} \ -\ -void CPUCALL \ -inst##_Ew_ext(UINT32 madr) \ -{ \ -\ - cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, 0); \ -} \ -\ -void CPUCALL \ -inst##_Ed(UINT32 *out) \ -{ \ - UINT32 src, dst; \ -\ - src = *out; \ - DWORD_##inst##1(dst, src); \ - *out = dst; \ -} \ -\ -void CPUCALL \ -inst##_Ed_ext(UINT32 madr) \ -{ \ -\ - cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, 0); \ -} \ -\ -/* ExCL, ExIb */ \ -void CPUCALL \ -inst##_EbCL(UINT8 *out, UINT32 cl) \ -{ \ - UINT32 src, dst; \ -\ - src = *out; \ - BYTE_##inst##CL(dst, src, cl); \ - *out = (UINT8)dst; \ -} \ -\ -void CPUCALL \ -inst##_EbCL_ext(UINT32 madr, UINT32 cl) \ -{ \ -\ - cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##CL1, UINT32_TO_PTR(cl)); \ -} \ -\ -void CPUCALL \ -inst##_EwCL(UINT16 *out, UINT32 cl) \ -{ \ - UINT32 src, dst; \ -\ - src = *out; \ - WORD_##inst##CL(dst, src, cl); \ - *out = (UINT16)dst; \ -} \ -\ -void CPUCALL \ -inst##_EwCL_ext(UINT32 madr, UINT32 cl) \ -{ \ -\ - cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##CL2, UINT32_TO_PTR(cl)); \ -} \ -\ -void CPUCALL \ -inst##_EdCL(UINT32 *out, UINT32 cl) \ -{ \ - UINT32 src, dst; \ -\ - src = *out; \ - DWORD_##inst##CL(dst, src, cl); \ - *out = dst; \ -} \ -\ -void CPUCALL \ -inst##_EdCL_ext(UINT32 madr, UINT32 cl) \ -{ \ -\ - cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##CL4, UINT32_TO_PTR(cl)); \ -} - -/* - * shift double-words instructions - */ -struct SHxD_arg { - UINT32 src; - UINT32 cl; -}; - -#define SHxD_INSTRUCTION(inst) \ -static UINT32 CPUCALL \ -inst##2(UINT32 dst, void *arg) \ -{ \ - struct SHxD_arg *p = (struct SHxD_arg *)arg; \ - UINT32 src = p->src; \ - UINT32 cl = p->cl; \ - WORD_##inst(dst, src, cl); \ - return dst; \ -} \ -static UINT32 CPUCALL \ -inst##4(UINT32 dst, void *arg) \ -{ \ - struct SHxD_arg *p = (struct SHxD_arg *)arg; \ - UINT32 src = p->src; \ - UINT32 cl = p->cl; \ - DWORD_##inst(dst, src, cl); \ - return dst; \ -} \ -\ -void \ -inst##_EwGwIb(void) \ -{ \ - struct SHxD_arg arg; \ - UINT16 *out; \ - UINT32 op, dst, madr; \ -\ - PREPART_EA_REG16(op, arg.src); \ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(3); \ - GET_PCBYTE(arg.cl); \ - out = CPU_REG16_B20(op); \ - dst = *out; \ - WORD_##inst(dst, arg.src, arg.cl); \ - *out = (UINT16)dst; \ - } else { \ - CPU_WORKCLOCK(7); \ - madr = calc_ea_dst(op); \ - GET_PCBYTE(arg.cl); \ - cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, &arg); \ - } \ -} \ -\ -void \ -inst##_EdGdIb(void) \ -{ \ - struct SHxD_arg arg; \ - UINT32 *out; \ - UINT32 op, dst, madr; \ -\ - PREPART_EA_REG32(op, arg.src); \ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(3); \ - GET_PCBYTE(arg.cl); \ - out = CPU_REG32_B20(op); \ - dst = *out; \ - DWORD_##inst(dst, arg.src, arg.cl); \ - *out = dst; \ - } else { \ - CPU_WORKCLOCK(7); \ - madr = calc_ea_dst(op); \ - GET_PCBYTE(arg.cl); \ - cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, &arg); \ - } \ -} \ -\ -void \ -inst##_EwGwCL(void) \ -{ \ - struct SHxD_arg arg; \ - UINT16 *out; \ - UINT32 op, dst, madr; \ -\ - PREPART_EA_REG16(op, arg.src); \ - arg.cl = CPU_CL; \ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(3); \ - out = CPU_REG16_B20(op); \ - dst = *out; \ - WORD_##inst(dst, arg.src, arg.cl); \ - *out = (UINT16)dst; \ - } else { \ - CPU_WORKCLOCK(7); \ - madr = calc_ea_dst(op); \ - cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, (void *)&arg); \ - } \ -} \ -\ -void \ -inst##_EdGdCL(void) \ -{ \ - struct SHxD_arg arg; \ - UINT32 *out; \ - UINT32 op, dst, madr; \ -\ - PREPART_EA_REG32(op, arg.src); \ - arg.cl = CPU_CL; \ - if (op >= 0xc0) { \ - CPU_WORKCLOCK(3); \ - out = CPU_REG32_B20(op); \ - dst = *out; \ - DWORD_##inst(dst, arg.src, arg.cl); \ - *out = dst; \ - } else { \ - CPU_WORKCLOCK(7); \ - madr = calc_ea_dst(op); \ - cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, (void *)&arg); \ - } \ -} - - -/* Pentium!!! - シフトカウント != 1の場合はOVは不変らすい */ - -/* - * SAR - */ -#define _BYTE_SAR1(d, s) \ -do { \ - (d) = (UINT8)(((SINT8)(s)) >> 1); \ - CPU_OV = 0; \ - CPU_FLAGL = (UINT8)(szpcflag[(UINT8)(d)] | A_FLAG | ((s) & 1)); \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_SAR1(d, s) \ -do { \ - (d) = (UINT16)(((SINT16)(s)) >> 1); \ - CPU_OV = 0; \ - CPU_FLAGL = (UINT8)(szpflag_w[(UINT16)(d)] | A_FLAG | ((s) & 1)); \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_SAR1(d, s) \ -do { \ - (d) = (UINT32)(((SINT32)(s)) >> 1); \ - CPU_OV = 0; \ - CPU_FLAGL = (UINT8)(A_FLAG | ((s) & 1)); /* C_FLAG */ \ - if ((d) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } else if ((d) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= (szpcflag[(UINT8)(d)] & P_FLAG); \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_SARCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - (c)--; \ - if ((c)) { \ - (s) = ((SINT8)(s)) >> (c); \ - } else { \ - CPU_OV = 0; \ - } \ - CPU_FLAGL = (UINT8)((s) & 1); /* C_FLAG */ \ - (s) = (UINT8)(((SINT8)(s)) >> 1); \ - CPU_FLAGL |= (szpcflag[(UINT8)(s)] | A_FLAG); \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_SARCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - (c)--; \ - if ((c)) { \ - (s) = ((SINT16)(s)) >> (c); \ - } else { \ - CPU_OV = 0; \ - } \ - CPU_FLAGL = (UINT8)((s) & 1); /* C_FLAG */ \ - (s) = (UINT16)(((SINT16)(s)) >> 1); \ - CPU_FLAGL |= szpflag_w[(UINT16)(s)]; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_SARCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - (c)--; \ - if ((c)) { \ - (s) = ((SINT32)(s)) >> (c); \ - } else { \ - CPU_OV = 0; \ - } \ - CPU_FLAGL = (UINT8)((s) & 1); /* C_FLAG */ \ - (s) = (UINT32)(((SINT32)(s)) >> 1); \ - if ((s) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } else if ((s) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= (szpcflag[(UINT8)(s)] & P_FLAG); \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -/* - * SHR - */ -#define _BYTE_SHR1(d, s) \ -do { \ - (d) = (s) >> 1; \ - CPU_OV = (s) & 0x80; \ - CPU_FLAGL = (UINT8)(szpcflag[(UINT8)(d)] | A_FLAG | ((s) & 1)); \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_SHR1(d, s) \ -do { \ - (d) = (s) >> 1; \ - CPU_OV = (s) & 0x8000; \ - CPU_FLAGL = (UINT8)(szpflag_w[(UINT16)(d)] | A_FLAG | ((s) & 1)); \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_SHR1(d, s) \ -do { \ - (d) = (s) >> 1; \ - CPU_OV = (s) & 0x80000000; \ - CPU_FLAGL = (UINT8)(A_FLAG | ((s) & 1)); \ - if ((d) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } \ - CPU_FLAGL |= (szpcflag[(UINT8)(d)] & P_FLAG); \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_SHRCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - (c)--; \ - if ((c)) { \ - (s) >>= (c); \ - } else { \ - CPU_OV = (s) & 0x80; \ - } \ - CPU_FLAGL = (UINT8)((s) & 1); \ - (s) >>= 1; \ - CPU_FLAGL |= (szpcflag[(UINT8)(s)] | A_FLAG); \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_SHRCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - (c)--; \ - if ((c)) { \ - (s) >>= (c); \ - } else { \ - CPU_OV = (s) & 0x8000; \ - } \ - CPU_FLAGL = (UINT8)((s) & 1); \ - (s) >>= 1; \ - CPU_FLAGL |= szpflag_w[(UINT16)(s)]; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_SHRCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - (c)--; \ - if ((c)) { \ - (s) >>= (c); \ - } else { \ - CPU_OV = (s) & 0x80000000; \ - } \ - CPU_FLAGL = (UINT8)((s) & 1); \ - (s) >>= 1; \ - if ((s) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } \ - CPU_FLAGL |= (szpcflag[(UINT8)(s)] & P_FLAG); \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -/* - * SHL - */ -#define _BYTE_SHL1(d, s) \ -do { \ - (d) = (s) << 1; \ - CPU_OV = ((s) ^ (d)) & 0x80; \ - CPU_FLAGL = (UINT8)(szpcflag[(d) & 0x1ff] | A_FLAG); \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_SHL1(d, s) \ -do { \ - (d) = (s) << 1; \ - CPU_OV = ((s) ^ (d)) & 0x8000; \ - CPU_FLAGL = (UINT8)(szpflag_w[(UINT16)(d)] | A_FLAG | ((d) >> 16)); \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_SHL1(d, s) \ -do { \ - (d) = (s) << 1; \ - CPU_OV = ((s) ^ (d)) & 0x80000000; \ - CPU_FLAGL = (UINT8)(A_FLAG | (szpcflag[(UINT8)(d)] & P_FLAG)); \ - if ((s) & 0x80000000) { \ - CPU_FLAGL |= C_FLAG; \ - } \ - if ((d) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } else if ((d) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_SHLCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - if ((c) == 1) { \ - CPU_OV = ((s) + 0x40) & 0x80; \ - } \ - (s) <<= (c); \ - (s) &= 0x1ff; \ - CPU_FLAGL = (UINT8)(szpcflag[(s) & 0x1ff] | A_FLAG); \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_SHLCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - if ((c) == 1) { \ - CPU_OV = ((s) + 0x4000) & 0x8000; \ - } \ - (s) <<= (c); \ - (s) &= 0x1ffff; \ - CPU_FLAGL = (UINT8)(szpflag_w[(UINT16)(s)] | A_FLAG); \ - CPU_FLAGL |= (UINT8)((s) >> 16); /* C_FLAG */ \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_SHLCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - (c)--; \ - if ((c)) { \ - (s) <<= (c); \ - } else { \ - CPU_OV = ((s) + 0x40000000) & 0x80000000; \ - } \ - CPU_FLAGL = A_FLAG; \ - if ((s) & 0x80000000) { \ - CPU_FLAGL |= C_FLAG; \ - } \ - (s) <<= 1; \ - if ((s) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } else if ((s) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= (szpcflag[(UINT8)(s)] & P_FLAG); \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -/* - * SHRD - */ -#define _WORD_SHRD(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if (((c)) && ((c) < 16)) { \ - CPU_OV = 0; \ - if ((c) == 1) { \ - CPU_OV = (((d) >> 15) ^ (s)) & 1; \ - } \ - CPU_FLAGL = (UINT8)(((d) >> ((c) - 1)) & 1); /*C_FLAG*/ \ - (d) |= (s) << 16; \ - (d) >>= (c); \ - (d) &= 0xffff; \ - CPU_FLAGL |= szpflag_w[(UINT16)(d)] | A_FLAG; \ - } else if ((c) > 15) { \ - CPU_OV = 0; \ - if ((c) == 17) { \ - CPU_OV = (((s) >> 15) ^ (s)) & 1; \ - } \ - if ((c) == 16) { \ - CPU_FLAGL = (UINT8)(((d) >> 15) & 1); /*C_FLAG*/ \ - } else { \ - CPU_FLAGL = (UINT8)(((s) >> ((c) - 17)) & 1); /*C_FLAG*/ \ - } \ - (d) = ((d) << 16) | (s); \ - (d) >>= (c) - 16; \ - (d) &= 0xffff; \ - CPU_FLAGL |= szpflag_w[(UINT16)(d)] | A_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_SHRD(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - CPU_OV = 0; \ - if ((c) == 1) { \ - CPU_OV = (((d) >> 31) ^ (s)) & 1; \ - } \ - CPU_FLAGL = (UINT8)(((d) >> ((c) - 1)) & 1); /* C_FLAG */ \ - (d) >>= (c); \ - (d) |= (s) << (32 - (c)); \ - if ((d) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } else if ((d) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= (szpcflag[(UINT8)(d)] & P_FLAG); \ - } \ -} while (/*CONSTCOND*/ 0) - -/* - * SHLD - */ -#define _WORD_SHLD(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if (((c)) && ((c) < 16)) { \ - CPU_OV = 0; \ - if ((c) == 1) { \ - CPU_OV = ((d) ^ ((d) << 1)) & 0x8000; \ - } \ - CPU_FLAGL = (UINT8)(((d) >> (16 - (c))) & 1); /*C_FLAG*/\ - (d) = ((d) << 16) | (s); \ - (d) <<= (c); \ - (d) >>= 16; \ - CPU_FLAGL |= szpflag_w[(d)] | A_FLAG; \ - } else if ((c) > 15) { \ - CPU_OV = 0; \ - if ((c) == 17) { \ - CPU_OV = ((s) ^ ((s) << 1)) & 0x8000; \ - } \ - if ((c) == 16) { \ - CPU_FLAGL = (UINT8)((d) & 1); /*C_FLAG*/\ - } else { \ - CPU_FLAGL = (UINT8)(((s) >> (32 - (c))) & 1); /*C_FLAG*/\ - } \ - (d) |= (s) << 16; \ - (d) <<= (c) - 16; \ - (d) >>= 16; \ - CPU_FLAGL |= szpflag_w[(d)] | A_FLAG; \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_SHLD(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - CPU_OV = 0; \ - if ((c) == 1) { \ - CPU_OV = ((d) ^ ((d) << 1)) & 0x80000000; \ - } \ - CPU_FLAGL = (UINT8)(((d) >> (32 - (c))) & 1); /* C_FLAG */ \ - (d) <<= (c); \ - (d) |= ((s) >> (32 - (c))); \ - if ((d) == 0) { \ - CPU_FLAGL |= Z_FLAG; \ - } else if ((d) & 0x80000000) { \ - CPU_FLAGL |= S_FLAG; \ - } \ - CPU_FLAGL |= (szpcflag[(UINT8)(d)] & P_FLAG); \ - } \ -} while (/*CONSTCOND*/ 0) - -/* - * ROR - */ -#define _BYTE_ROR1(d, s) \ -do { \ - UINT32 tmp = (s) & 1; \ - (d) = (tmp << 7) + ((s) >> 1); \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= tmp; \ - CPU_OV = ((s) ^ (d)) & 0x80; \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_ROR1(d, s) \ -do { \ - UINT32 tmp = (s) & 1; \ - (d) = (tmp << 15) + ((s) >> 1); \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= tmp; \ - CPU_OV = ((s) ^ (d)) & 0x8000; \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_ROR1(d, s) \ -do { \ - UINT32 tmp = (s) & 1; \ - (d) = (tmp << 31) + ((s) >> 1); \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= tmp; \ - CPU_OV = ((s) ^ (d)) & 0x80000000; \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_RORCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - (c) = ((c) - 1) & 7; \ - if ((c)) { \ - (s) = ((s) >> (c)) | ((s) << (8 - (c))); \ - (s) &= 0xff; \ - } \ - _BYTE_ROR1(d, s); \ - } else { \ - (d) = (s); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_RORCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - UINT32 tmp; \ - (c)--; \ - if ((c)) { \ - (c) &= 0x0f; \ - (s) = ((s) >> (c)) | ((s) << (16 - (c))); \ - (s) &= 0xffff; \ - CPU_OV = 0; \ - } else { \ - CPU_OV = ((s) >> 15) ^ ((s) & 1); \ - } \ - tmp = (s) & 1; \ - (s) = (tmp << 15) + ((s) >> 1); \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= tmp; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_RORCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - UINT32 tmp; \ - (c)--; \ - if ((c)) { \ - (s) = ((s) >> (c)) | ((s) << (32 - (c))); \ - CPU_OV = 0; \ - } else { \ - CPU_OV = ((s) >> 31) ^ ((s) & 1); \ - } \ - tmp = (s) & 1; \ - (s) = (tmp << 31) + ((s) >> 1); \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= tmp; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -/* - * ROL - */ -#define _BYTE_ROL1(d, s) \ -do { \ - UINT32 tmp = (s) >> 7; /* C_FLAG */ \ - (d) = ((s) << 1) + tmp; \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= tmp; \ - CPU_OV = ((s) ^ (d)) & 0x80; \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_ROL1(d, s) \ -do { \ - UINT32 tmp = (s) >> 15; /* C_FLAG */ \ - (d) = ((s) << 1) + tmp; \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= tmp; \ - CPU_OV = ((s) ^ (d)) & 0x8000; \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_ROL1(d, s) \ -do { \ - UINT32 tmp = (s) >> 31; /* C_FLAG */ \ - (d) = ((s) << 1) + tmp; \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= tmp; \ - CPU_OV = ((s) ^ (d)) & 0x80000000; \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_ROLCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - (c) = ((c) - 1) & 7; \ - if ((c)) { \ - (s) = ((s) << (c)) | ((s) >> (8 - (c))); \ - (s) &= 0xff; \ - } \ - _BYTE_ROL1(d, s); \ - } else { \ - (d) = (s); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_ROLCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - UINT32 tmp; \ - (c)--; \ - if ((c)) { \ - (c) &= 0x0f; \ - (s) = ((s) << (c)) | ((s) >> (16 - (c))); \ - (s) &= 0xffff; \ - CPU_OV = 0; \ - } else { \ - CPU_OV = ((s) + 0x4000) & 0x8000; \ - } \ - tmp = (s) >> 15; \ - (s) = ((s) << 1) + tmp; \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= tmp; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_ROLCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - UINT32 tmp; \ - (c)--; \ - if ((c)) { \ - (s) = ((s) << (c)) | ((s) >> (32 - (c))); \ - CPU_OV = 0; \ - } else { \ - CPU_OV = ((s) + 0x40000000) & 0x80000000; \ - } \ - tmp = (s) >> 31; \ - (s) = ((s) << 1) + tmp; \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= tmp; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -/* - * RCR - */ -#define _BYTE_RCR1(d, s) \ -do { \ - (d) = ((CPU_FLAGL & C_FLAG) << 7) + ((s) >> 1); \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= (s) & 1; \ - CPU_OV = ((s) ^ (d)) & 0x80; \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_RCR1(d, s) \ -do { \ - (d) = ((CPU_FLAGL & C_FLAG) << 15) + ((s) >> 1); \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= (s) & 1; \ - CPU_OV = ((s) ^ (d)) & 0x8000; \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_RCR1(d, s) \ -do { \ - (d) = ((CPU_FLAGL & C_FLAG) << 31) + ((s) >> 1); \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= (s) & 1; \ - CPU_OV = ((s) ^ (d)) & 0x80000000; \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_RCRCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - UINT32 tmp = CPU_FLAGL & C_FLAG; \ - CPU_FLAGL &= ~C_FLAG; \ - while ((c)--) { \ - (s) |= (tmp << 8); \ - tmp = (s) & 1; \ - (s) >>= 1; \ - } \ - CPU_OV = ((s) ^ ((s) >> 1)) & 0x40; \ - CPU_FLAGL |= tmp; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_RCRCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - UINT32 tmp = CPU_FLAGL & C_FLAG; \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_OV = 0; \ - if ((c) == 1) { \ - CPU_OV = ((s) >> 15) ^ tmp; \ - } \ - while ((c)--) { \ - (s) |= (tmp << 16); \ - tmp = (s) & 1; \ - (s) >>= 1; \ - } \ - CPU_FLAGL |= tmp; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_RCRCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - UINT32 tmp = CPU_FLAGL & C_FLAG; \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_OV = 0; \ - if ((c) == 1) { \ - CPU_OV = ((s) >> 31) ^ tmp; \ - } \ - while ((c)--) { \ - UINT32 tmp2 = (s) & 1; \ - (s) = (tmp << 31) | ((s) >> 1); \ - tmp = tmp2; \ - } \ - CPU_FLAGL |= tmp; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -/* - * RCL - */ -#define _BYTE_RCL1(d, s) \ -do { \ - (d) = ((s) << 1) | (CPU_FLAGL & C_FLAG); \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= (s) >> 7; /* C_FLAG */ \ - CPU_OV = ((s) ^ (d)) & 0x80; \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_RCL1(d, s) \ -do { \ - (d) = ((s) << 1) | (CPU_FLAGL & C_FLAG); \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= (s) >> 15; /* C_FLAG */ \ - CPU_OV = ((s) ^ (d)) & 0x8000; \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_RCL1(d, s) \ -do { \ - (d) = ((s) << 1) | (CPU_FLAGL & C_FLAG); \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_FLAGL |= (s) >> 31; /* C_FLAG */ \ - CPU_OV = ((s) ^ (d)) & 0x80000000; \ -} while (/*CONSTCOND*/ 0) - -#define _BYTE_RCLCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - UINT32 tmp = CPU_FLAGL & C_FLAG; \ - CPU_FLAGL &= ~C_FLAG; \ - while ((c)--) { \ - (s) = (((s) << 1) | tmp) & 0x1ff; \ - tmp = (s) >> 8; \ - } \ - CPU_OV = ((s) ^ ((s) >> 1)) & 0x80; \ - CPU_FLAGL |= tmp; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _WORD_RCLCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - UINT32 tmp = CPU_FLAGL & C_FLAG; \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_OV = 0; \ - if ((c) == 1) { \ - CPU_OV = ((s) + 0x4000) & 0x8000; \ - } \ - while ((c)--) { \ - (s) = (((s) << 1) | tmp) & 0x1ffff; \ - tmp = (s) >> 16; \ - } \ - CPU_FLAGL |= tmp; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#define _DWORD_RCLCL(d, s, c) \ -do { \ - (c) &= 0x1f; \ - if ((c)) { \ - UINT32 tmp = CPU_FLAGL & C_FLAG; \ - CPU_FLAGL &= ~C_FLAG; \ - CPU_OV = 0; \ - if ((c) == 1) { \ - CPU_OV = ((s) + 0x40000000) & 0x80000000; \ - } \ - while ((c)--) { \ - UINT32 tmp2 = (s) & 0x80000000; \ - (s) = ((s) << 1) | (tmp & 1); \ - tmp = tmp2 >> 31; \ - } \ - CPU_FLAGL |= tmp; \ - } \ - (d) = (s); \ -} while (/*CONSTCOND*/ 0) - -#if defined(IA32_CROSS_CHECK) && defined(GCC_CPU_ARCH_IA32) - -#include "shift_rotatexc.mcr" - -#define BYTE_SAR1(d, s) XC_BYTE_SAR1(d, s) -#define WORD_SAR1(d, s) XC_WORD_SAR1(d, s) -#define DWORD_SAR1(d, s) XC_DWORD_SAR1(d, s) -#define BYTE_SARCL(d, s, c) XC_BYTE_SARCL(d, s, c) -#define WORD_SARCL(d, s, c) XC_WORD_SARCL(d, s, c) -#define DWORD_SARCL(d, s, c) XC_DWORD_SARCL(d, s, c) -#define BYTE_SHR1(d, s) XC_BYTE_SHR1(d, s) -#define WORD_SHR1(d, s) XC_WORD_SHR1(d, s) -#define DWORD_SHR1(d, s) XC_DWORD_SHR1(d, s) -#define BYTE_SHRCL(d, s, c) XC_BYTE_SHRCL(d, s, c) -#define WORD_SHRCL(d, s, c) XC_WORD_SHRCL(d, s, c) -#define DWORD_SHRCL(d, s, c) XC_DWORD_SHRCL(d, s, c) -#define BYTE_SHL1(d, s) XC_BYTE_SHL1(d, s) -#define WORD_SHL1(d, s) XC_WORD_SHL1(d, s) -#define DWORD_SHL1(d, s) XC_DWORD_SHL1(d, s) -#define BYTE_SHLCL(d, s, c) XC_BYTE_SHLCL(d, s, c) -#define WORD_SHLCL(d, s, c) XC_WORD_SHLCL(d, s, c) -#define DWORD_SHLCL(d, s, c) XC_DWORD_SHLCL(d, s, c) -#define WORD_SHRD(d, s, c) XC_WORD_SHRD(d, s, c) -#define DWORD_SHRD(d, s, c) XC_DWORD_SHRD(d, s, c) -#define WORD_SHLD(d, s, c) XC_WORD_SHLD(d, s, c) -#define DWORD_SHLD(d, s, c) XC_DWORD_SHLD(d, s, c) -#define BYTE_ROR1(d, s) XC_BYTE_ROR1(d, s) -#define WORD_ROR1(d, s) XC_WORD_ROR1(d, s) -#define DWORD_ROR1(d, s) XC_DWORD_ROR1(d, s) -#define BYTE_RORCL(d, s, c) XC_BYTE_RORCL(d, s, c) -#define WORD_RORCL(d, s, c) XC_WORD_RORCL(d, s, c) -#define DWORD_RORCL(d, s, c) XC_DWORD_RORCL(d, s, c) -#define BYTE_ROL1(d, s) XC_BYTE_ROL1(d, s) -#define WORD_ROL1(d, s) XC_WORD_ROL1(d, s) -#define DWORD_ROL1(d, s) XC_DWORD_ROL1(d, s) -#define BYTE_ROLCL(d, s, c) XC_BYTE_ROLCL(d, s, c) -#define WORD_ROLCL(d, s, c) XC_WORD_ROLCL(d, s, c) -#define DWORD_ROLCL(d, s, c) XC_DWORD_ROLCL(d, s, c) -#define BYTE_RCR1(d, s) XC_BYTE_RCR1(d, s) -#define WORD_RCR1(d, s) XC_WORD_RCR1(d, s) -#define DWORD_RCR1(d, s) XC_DWORD_RCR1(d, s) -#define BYTE_RCRCL(d, s, c) XC_BYTE_RCRCL(d, s, c) -#define WORD_RCRCL(d, s, c) XC_WORD_RCRCL(d, s, c) -#define DWORD_RCRCL(d, s, c) XC_DWORD_RCRCL(d, s, c) -#define BYTE_RCL1(d, s) XC_BYTE_RCL1(d, s) -#define WORD_RCL1(d, s) XC_WORD_RCL1(d, s) -#define DWORD_RCL1(d, s) XC_DWORD_RCL1(d, s) -#define BYTE_RCLCL(d, s, c) XC_BYTE_RCLCL(d, s, c) -#define WORD_RCLCL(d, s, c) XC_WORD_RCLCL(d, s, c) -#define DWORD_RCLCL(d, s, c) XC_DWORD_RCLCL(d, s, c) - -#elif defined(IA32_CROSS_CHECK) && defined(_MSC_VER) - -#include "shift_rotatexc_msc.mcr" - -#else /* !(IA32_CROSS_CHECK && GCC_CPU_ARCH_IA32 */ - -#define BYTE_SAR1(d, s) _BYTE_SAR1(d, s) -#define WORD_SAR1(d, s) _WORD_SAR1(d, s) -#define DWORD_SAR1(d, s) _DWORD_SAR1(d, s) -#define BYTE_SARCL(d, s, c) _BYTE_SARCL(d, s, c) -#define WORD_SARCL(d, s, c) _WORD_SARCL(d, s, c) -#define DWORD_SARCL(d, s, c) _DWORD_SARCL(d, s, c) -#define BYTE_SHR1(d, s) _BYTE_SHR1(d, s) -#define WORD_SHR1(d, s) _WORD_SHR1(d, s) -#define DWORD_SHR1(d, s) _DWORD_SHR1(d, s) -#define BYTE_SHRCL(d, s, c) _BYTE_SHRCL(d, s, c) -#define WORD_SHRCL(d, s, c) _WORD_SHRCL(d, s, c) -#define DWORD_SHRCL(d, s, c) _DWORD_SHRCL(d, s, c) -#define BYTE_SHL1(d, s) _BYTE_SHL1(d, s) -#define WORD_SHL1(d, s) _WORD_SHL1(d, s) -#define DWORD_SHL1(d, s) _DWORD_SHL1(d, s) -#define BYTE_SHLCL(d, s, c) _BYTE_SHLCL(d, s, c) -#define WORD_SHLCL(d, s, c) _WORD_SHLCL(d, s, c) -#define DWORD_SHLCL(d, s, c) _DWORD_SHLCL(d, s, c) -#define WORD_SHRD(d, s, c) _WORD_SHRD(d, s, c) -#define DWORD_SHRD(d, s, c) _DWORD_SHRD(d, s, c) -#define WORD_SHLD(d, s, c) _WORD_SHLD(d, s, c) -#define DWORD_SHLD(d, s, c) _DWORD_SHLD(d, s, c) -#define BYTE_ROR1(d, s) _BYTE_ROR1(d, s) -#define WORD_ROR1(d, s) _WORD_ROR1(d, s) -#define DWORD_ROR1(d, s) _DWORD_ROR1(d, s) -#define BYTE_RORCL(d, s, c) _BYTE_RORCL(d, s, c) -#define WORD_RORCL(d, s, c) _WORD_RORCL(d, s, c) -#define DWORD_RORCL(d, s, c) _DWORD_RORCL(d, s, c) -#define BYTE_ROL1(d, s) _BYTE_ROL1(d, s) -#define WORD_ROL1(d, s) _WORD_ROL1(d, s) -#define DWORD_ROL1(d, s) _DWORD_ROL1(d, s) -#define BYTE_ROLCL(d, s, c) _BYTE_ROLCL(d, s, c) -#define WORD_ROLCL(d, s, c) _WORD_ROLCL(d, s, c) -#define DWORD_ROLCL(d, s, c) _DWORD_ROLCL(d, s, c) -#define BYTE_RCR1(d, s) _BYTE_RCR1(d, s) -#define WORD_RCR1(d, s) _WORD_RCR1(d, s) -#define DWORD_RCR1(d, s) _DWORD_RCR1(d, s) -#define BYTE_RCRCL(d, s, c) _BYTE_RCRCL(d, s, c) -#define WORD_RCRCL(d, s, c) _WORD_RCRCL(d, s, c) -#define DWORD_RCRCL(d, s, c) _DWORD_RCRCL(d, s, c) -#define BYTE_RCL1(d, s) _BYTE_RCL1(d, s) -#define WORD_RCL1(d, s) _WORD_RCL1(d, s) -#define DWORD_RCL1(d, s) _DWORD_RCL1(d, s) -#define BYTE_RCLCL(d, s, c) _BYTE_RCLCL(d, s, c) -#define WORD_RCLCL(d, s, c) _WORD_RCLCL(d, s, c) -#define DWORD_RCLCL(d, s, c) _DWORD_RCLCL(d, s, c) - -#endif /* IA32_CROSS_CHECK && GCC_CPU_ARCH_IA32 */ - -#endif /* IA32_CPU_SHIFT_ROTATE_MCR__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_SHIFT_ROTATE_MCR__ +#define IA32_CPU_SHIFT_ROTATE_MCR__ + +/* + * shift/rorate instruction macro + */ +#define SHIFT_ROTATE_INSTRUCTION(inst) \ +static UINT32 CPUCALL \ +inst##1(UINT32 src, void *arg) \ +{ \ + UINT32 dst; \ + BYTE_##inst##1(dst, src); \ + return dst; \ +} \ +static UINT32 CPUCALL \ +inst##2(UINT32 src, void *arg) \ +{ \ + UINT32 dst; \ + WORD_##inst##1(dst, src); \ + return dst; \ +} \ +static UINT32 CPUCALL \ +inst##4(UINT32 src, void *arg) \ +{ \ + UINT32 dst; \ + DWORD_##inst##1(dst, src); \ + return dst; \ +} \ +static UINT32 CPUCALL \ +inst##CL1(UINT32 src, void *arg) \ +{ \ + UINT32 cl = PTR_TO_UINT32(arg); \ + UINT32 dst; \ + BYTE_##inst##CL(dst, src, cl); \ + return dst; \ +} \ +static UINT32 CPUCALL \ +inst##CL2(UINT32 src, void *arg) \ +{ \ + UINT32 cl = PTR_TO_UINT32(arg); \ + UINT32 dst; \ + WORD_##inst##CL(dst, src, cl); \ + return dst; \ +} \ +static UINT32 CPUCALL \ +inst##CL4(UINT32 src, void *arg) \ +{ \ + UINT32 cl = PTR_TO_UINT32(arg); \ + UINT32 dst; \ + DWORD_##inst##CL(dst, src, cl); \ + return dst; \ +} \ +\ +void CPUCALL \ +inst##_Eb(UINT8 *out) \ +{ \ + UINT32 src, dst; \ +\ + src = *out; \ + BYTE_##inst##1(dst, src); \ + *out = (UINT8)dst; \ +} \ +\ +void CPUCALL \ +inst##_Eb_ext(UINT32 madr) \ +{ \ +\ + cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##1, 0); \ +} \ +\ +void CPUCALL \ +inst##_Ew(UINT16 *out) \ +{ \ + UINT32 src, dst; \ +\ + src = *out; \ + WORD_##inst##1(dst, src); \ + *out = (UINT16)dst; \ +} \ +\ +void CPUCALL \ +inst##_Ew_ext(UINT32 madr) \ +{ \ +\ + cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, 0); \ +} \ +\ +void CPUCALL \ +inst##_Ed(UINT32 *out) \ +{ \ + UINT32 src, dst; \ +\ + src = *out; \ + DWORD_##inst##1(dst, src); \ + *out = dst; \ +} \ +\ +void CPUCALL \ +inst##_Ed_ext(UINT32 madr) \ +{ \ +\ + cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, 0); \ +} \ +\ +/* ExCL, ExIb */ \ +void CPUCALL \ +inst##_EbCL(UINT8 *out, UINT32 cl) \ +{ \ + UINT32 src, dst; \ +\ + src = *out; \ + BYTE_##inst##CL(dst, src, cl); \ + *out = (UINT8)dst; \ +} \ +\ +void CPUCALL \ +inst##_EbCL_ext(UINT32 madr, UINT32 cl) \ +{ \ +\ + cpu_vmemory_RMW_b(CPU_INST_SEGREG_INDEX, madr, inst##CL1, UINT32_TO_PTR(cl)); \ +} \ +\ +void CPUCALL \ +inst##_EwCL(UINT16 *out, UINT32 cl) \ +{ \ + UINT32 src, dst; \ +\ + src = *out; \ + WORD_##inst##CL(dst, src, cl); \ + *out = (UINT16)dst; \ +} \ +\ +void CPUCALL \ +inst##_EwCL_ext(UINT32 madr, UINT32 cl) \ +{ \ +\ + cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##CL2, UINT32_TO_PTR(cl)); \ +} \ +\ +void CPUCALL \ +inst##_EdCL(UINT32 *out, UINT32 cl) \ +{ \ + UINT32 src, dst; \ +\ + src = *out; \ + DWORD_##inst##CL(dst, src, cl); \ + *out = dst; \ +} \ +\ +void CPUCALL \ +inst##_EdCL_ext(UINT32 madr, UINT32 cl) \ +{ \ +\ + cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##CL4, UINT32_TO_PTR(cl)); \ +} + +/* + * shift double-words instructions + */ +struct SHxD_arg { + UINT32 src; + UINT32 cl; +}; + +#define SHxD_INSTRUCTION(inst) \ +static UINT32 CPUCALL \ +inst##2(UINT32 dst, void *arg) \ +{ \ + struct SHxD_arg *p = (struct SHxD_arg *)arg; \ + UINT32 src = p->src; \ + UINT32 cl = p->cl; \ + WORD_##inst(dst, src, cl); \ + return dst; \ +} \ +static UINT32 CPUCALL \ +inst##4(UINT32 dst, void *arg) \ +{ \ + struct SHxD_arg *p = (struct SHxD_arg *)arg; \ + UINT32 src = p->src; \ + UINT32 cl = p->cl; \ + DWORD_##inst(dst, src, cl); \ + return dst; \ +} \ +\ +void \ +inst##_EwGwIb(void) \ +{ \ + struct SHxD_arg arg; \ + UINT16 *out; \ + UINT32 op, dst, madr; \ +\ + PREPART_EA_REG16(op, arg.src); \ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(3); \ + GET_PCBYTE(arg.cl); \ + out = CPU_REG16_B20(op); \ + dst = *out; \ + WORD_##inst(dst, arg.src, arg.cl); \ + *out = (UINT16)dst; \ + } else { \ + CPU_WORKCLOCK(7); \ + madr = calc_ea_dst(op); \ + GET_PCBYTE(arg.cl); \ + cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, &arg); \ + } \ +} \ +\ +void \ +inst##_EdGdIb(void) \ +{ \ + struct SHxD_arg arg; \ + UINT32 *out; \ + UINT32 op, dst, madr; \ +\ + PREPART_EA_REG32(op, arg.src); \ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(3); \ + GET_PCBYTE(arg.cl); \ + out = CPU_REG32_B20(op); \ + dst = *out; \ + DWORD_##inst(dst, arg.src, arg.cl); \ + *out = dst; \ + } else { \ + CPU_WORKCLOCK(7); \ + madr = calc_ea_dst(op); \ + GET_PCBYTE(arg.cl); \ + cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, &arg); \ + } \ +} \ +\ +void \ +inst##_EwGwCL(void) \ +{ \ + struct SHxD_arg arg; \ + UINT16 *out; \ + UINT32 op, dst, madr; \ +\ + PREPART_EA_REG16(op, arg.src); \ + arg.cl = CPU_CL; \ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(3); \ + out = CPU_REG16_B20(op); \ + dst = *out; \ + WORD_##inst(dst, arg.src, arg.cl); \ + *out = (UINT16)dst; \ + } else { \ + CPU_WORKCLOCK(7); \ + madr = calc_ea_dst(op); \ + cpu_vmemory_RMW_w(CPU_INST_SEGREG_INDEX, madr, inst##2, (void *)&arg); \ + } \ +} \ +\ +void \ +inst##_EdGdCL(void) \ +{ \ + struct SHxD_arg arg; \ + UINT32 *out; \ + UINT32 op, dst, madr; \ +\ + PREPART_EA_REG32(op, arg.src); \ + arg.cl = CPU_CL; \ + if (op >= 0xc0) { \ + CPU_WORKCLOCK(3); \ + out = CPU_REG32_B20(op); \ + dst = *out; \ + DWORD_##inst(dst, arg.src, arg.cl); \ + *out = dst; \ + } else { \ + CPU_WORKCLOCK(7); \ + madr = calc_ea_dst(op); \ + cpu_vmemory_RMW_d(CPU_INST_SEGREG_INDEX, madr, inst##4, (void *)&arg); \ + } \ +} + + +/* Pentium!!! - シフトカウント != 1の場合はOVは不変らすい */ + +/* + * SAR + */ +#define _BYTE_SAR1(d, s) \ +do { \ + (d) = (UINT8)(((SINT8)(s)) >> 1); \ + CPU_OV = 0; \ + CPU_FLAGL = (UINT8)(szpcflag[(UINT8)(d)] | A_FLAG | ((s) & 1)); \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_SAR1(d, s) \ +do { \ + (d) = (UINT16)(((SINT16)(s)) >> 1); \ + CPU_OV = 0; \ + CPU_FLAGL = (UINT8)(szpflag_w[(UINT16)(d)] | A_FLAG | ((s) & 1)); \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_SAR1(d, s) \ +do { \ + (d) = (UINT32)(((SINT32)(s)) >> 1); \ + CPU_OV = 0; \ + CPU_FLAGL = (UINT8)(A_FLAG | ((s) & 1)); /* C_FLAG */ \ + if ((d) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } else if ((d) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= (szpcflag[(UINT8)(d)] & P_FLAG); \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_SARCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + (c)--; \ + if ((c)) { \ + (s) = ((SINT8)(s)) >> (c); \ + } else { \ + CPU_OV = 0; \ + } \ + CPU_FLAGL = (UINT8)((s) & 1); /* C_FLAG */ \ + (s) = (UINT8)(((SINT8)(s)) >> 1); \ + CPU_FLAGL |= (szpcflag[(UINT8)(s)] | A_FLAG); \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_SARCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + (c)--; \ + if ((c)) { \ + (s) = ((SINT16)(s)) >> (c); \ + } else { \ + CPU_OV = 0; \ + } \ + CPU_FLAGL = (UINT8)((s) & 1); /* C_FLAG */ \ + (s) = (UINT16)(((SINT16)(s)) >> 1); \ + CPU_FLAGL |= szpflag_w[(UINT16)(s)]; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_SARCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + (c)--; \ + if ((c)) { \ + (s) = ((SINT32)(s)) >> (c); \ + } else { \ + CPU_OV = 0; \ + } \ + CPU_FLAGL = (UINT8)((s) & 1); /* C_FLAG */ \ + (s) = (UINT32)(((SINT32)(s)) >> 1); \ + if ((s) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } else if ((s) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= (szpcflag[(UINT8)(s)] & P_FLAG); \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +/* + * SHR + */ +#define _BYTE_SHR1(d, s) \ +do { \ + (d) = (s) >> 1; \ + CPU_OV = (s) & 0x80; \ + CPU_FLAGL = (UINT8)(szpcflag[(UINT8)(d)] | A_FLAG | ((s) & 1)); \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_SHR1(d, s) \ +do { \ + (d) = (s) >> 1; \ + CPU_OV = (s) & 0x8000; \ + CPU_FLAGL = (UINT8)(szpflag_w[(UINT16)(d)] | A_FLAG | ((s) & 1)); \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_SHR1(d, s) \ +do { \ + (d) = (s) >> 1; \ + CPU_OV = (s) & 0x80000000; \ + CPU_FLAGL = (UINT8)(A_FLAG | ((s) & 1)); \ + if ((d) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } \ + CPU_FLAGL |= (szpcflag[(UINT8)(d)] & P_FLAG); \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_SHRCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + (c)--; \ + if ((c)) { \ + (s) >>= (c); \ + } else { \ + CPU_OV = (s) & 0x80; \ + } \ + CPU_FLAGL = (UINT8)((s) & 1); \ + (s) >>= 1; \ + CPU_FLAGL |= (szpcflag[(UINT8)(s)] | A_FLAG); \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_SHRCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + (c)--; \ + if ((c)) { \ + (s) >>= (c); \ + } else { \ + CPU_OV = (s) & 0x8000; \ + } \ + CPU_FLAGL = (UINT8)((s) & 1); \ + (s) >>= 1; \ + CPU_FLAGL |= szpflag_w[(UINT16)(s)]; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_SHRCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + (c)--; \ + if ((c)) { \ + (s) >>= (c); \ + } else { \ + CPU_OV = (s) & 0x80000000; \ + } \ + CPU_FLAGL = (UINT8)((s) & 1); \ + (s) >>= 1; \ + if ((s) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } \ + CPU_FLAGL |= (szpcflag[(UINT8)(s)] & P_FLAG); \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +/* + * SHL + */ +#define _BYTE_SHL1(d, s) \ +do { \ + (d) = (s) << 1; \ + CPU_OV = ((s) ^ (d)) & 0x80; \ + CPU_FLAGL = (UINT8)(szpcflag[(d) & 0x1ff] | A_FLAG); \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_SHL1(d, s) \ +do { \ + (d) = (s) << 1; \ + CPU_OV = ((s) ^ (d)) & 0x8000; \ + CPU_FLAGL = (UINT8)(szpflag_w[(UINT16)(d)] | A_FLAG | ((d) >> 16)); \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_SHL1(d, s) \ +do { \ + (d) = (s) << 1; \ + CPU_OV = ((s) ^ (d)) & 0x80000000; \ + CPU_FLAGL = (UINT8)(A_FLAG | (szpcflag[(UINT8)(d)] & P_FLAG)); \ + if ((s) & 0x80000000) { \ + CPU_FLAGL |= C_FLAG; \ + } \ + if ((d) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } else if ((d) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_SHLCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + if ((c) == 1) { \ + CPU_OV = ((s) + 0x40) & 0x80; \ + } \ + (s) <<= (c); \ + (s) &= 0x1ff; \ + CPU_FLAGL = (UINT8)(szpcflag[(s) & 0x1ff] | A_FLAG); \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_SHLCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + if ((c) == 1) { \ + CPU_OV = ((s) + 0x4000) & 0x8000; \ + } \ + (s) <<= (c); \ + (s) &= 0x1ffff; \ + CPU_FLAGL = (UINT8)(szpflag_w[(UINT16)(s)] | A_FLAG); \ + CPU_FLAGL |= (UINT8)((s) >> 16); /* C_FLAG */ \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_SHLCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + (c)--; \ + if ((c)) { \ + (s) <<= (c); \ + } else { \ + CPU_OV = ((s) + 0x40000000) & 0x80000000; \ + } \ + CPU_FLAGL = A_FLAG; \ + if ((s) & 0x80000000) { \ + CPU_FLAGL |= C_FLAG; \ + } \ + (s) <<= 1; \ + if ((s) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } else if ((s) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= (szpcflag[(UINT8)(s)] & P_FLAG); \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +/* + * SHRD + */ +#define _WORD_SHRD(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if (((c)) && ((c) < 16)) { \ + CPU_OV = 0; \ + if ((c) == 1) { \ + CPU_OV = (((d) >> 15) ^ (s)) & 1; \ + } \ + CPU_FLAGL = (UINT8)(((d) >> ((c) - 1)) & 1); /*C_FLAG*/ \ + (d) |= (s) << 16; \ + (d) >>= (c); \ + (d) &= 0xffff; \ + CPU_FLAGL |= szpflag_w[(UINT16)(d)] | A_FLAG; \ + } else if ((c) > 15) { \ + CPU_OV = 0; \ + if ((c) == 17) { \ + CPU_OV = (((s) >> 15) ^ (s)) & 1; \ + } \ + if ((c) == 16) { \ + CPU_FLAGL = (UINT8)(((d) >> 15) & 1); /*C_FLAG*/ \ + } else { \ + CPU_FLAGL = (UINT8)(((s) >> ((c) - 17)) & 1); /*C_FLAG*/ \ + } \ + (d) = ((d) << 16) | (s); \ + (d) >>= (c) - 16; \ + (d) &= 0xffff; \ + CPU_FLAGL |= szpflag_w[(UINT16)(d)] | A_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_SHRD(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + CPU_OV = 0; \ + if ((c) == 1) { \ + CPU_OV = (((d) >> 31) ^ (s)) & 1; \ + } \ + CPU_FLAGL = (UINT8)(((d) >> ((c) - 1)) & 1); /* C_FLAG */ \ + (d) >>= (c); \ + (d) |= (s) << (32 - (c)); \ + if ((d) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } else if ((d) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= (szpcflag[(UINT8)(d)] & P_FLAG); \ + } \ +} while (/*CONSTCOND*/ 0) + +/* + * SHLD + */ +#define _WORD_SHLD(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if (((c)) && ((c) < 16)) { \ + CPU_OV = 0; \ + if ((c) == 1) { \ + CPU_OV = ((d) ^ ((d) << 1)) & 0x8000; \ + } \ + CPU_FLAGL = (UINT8)(((d) >> (16 - (c))) & 1); /*C_FLAG*/\ + (d) = ((d) << 16) | (s); \ + (d) <<= (c); \ + (d) >>= 16; \ + CPU_FLAGL |= szpflag_w[(d)] | A_FLAG; \ + } else if ((c) > 15) { \ + CPU_OV = 0; \ + if ((c) == 17) { \ + CPU_OV = ((s) ^ ((s) << 1)) & 0x8000; \ + } \ + if ((c) == 16) { \ + CPU_FLAGL = (UINT8)((d) & 1); /*C_FLAG*/\ + } else { \ + CPU_FLAGL = (UINT8)(((s) >> (32 - (c))) & 1); /*C_FLAG*/\ + } \ + (d) |= (s) << 16; \ + (d) <<= (c) - 16; \ + (d) >>= 16; \ + CPU_FLAGL |= szpflag_w[(d)] | A_FLAG; \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_SHLD(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + CPU_OV = 0; \ + if ((c) == 1) { \ + CPU_OV = ((d) ^ ((d) << 1)) & 0x80000000; \ + } \ + CPU_FLAGL = (UINT8)(((d) >> (32 - (c))) & 1); /* C_FLAG */ \ + (d) <<= (c); \ + (d) |= ((s) >> (32 - (c))); \ + if ((d) == 0) { \ + CPU_FLAGL |= Z_FLAG; \ + } else if ((d) & 0x80000000) { \ + CPU_FLAGL |= S_FLAG; \ + } \ + CPU_FLAGL |= (szpcflag[(UINT8)(d)] & P_FLAG); \ + } \ +} while (/*CONSTCOND*/ 0) + +/* + * ROR + */ +#define _BYTE_ROR1(d, s) \ +do { \ + UINT32 tmp = (s) & 1; \ + (d) = (tmp << 7) + ((s) >> 1); \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= tmp; \ + CPU_OV = ((s) ^ (d)) & 0x80; \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_ROR1(d, s) \ +do { \ + UINT32 tmp = (s) & 1; \ + (d) = (tmp << 15) + ((s) >> 1); \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= tmp; \ + CPU_OV = ((s) ^ (d)) & 0x8000; \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_ROR1(d, s) \ +do { \ + UINT32 tmp = (s) & 1; \ + (d) = (tmp << 31) + ((s) >> 1); \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= tmp; \ + CPU_OV = ((s) ^ (d)) & 0x80000000; \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_RORCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + (c) = ((c) - 1) & 7; \ + if ((c)) { \ + (s) = ((s) >> (c)) | ((s) << (8 - (c))); \ + (s) &= 0xff; \ + } \ + _BYTE_ROR1(d, s); \ + } else { \ + (d) = (s); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_RORCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + UINT32 tmp; \ + (c)--; \ + if ((c)) { \ + (c) &= 0x0f; \ + (s) = ((s) >> (c)) | ((s) << (16 - (c))); \ + (s) &= 0xffff; \ + CPU_OV = 0; \ + } else { \ + CPU_OV = ((s) >> 15) ^ ((s) & 1); \ + } \ + tmp = (s) & 1; \ + (s) = (tmp << 15) + ((s) >> 1); \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= tmp; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_RORCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + UINT32 tmp; \ + (c)--; \ + if ((c)) { \ + (s) = ((s) >> (c)) | ((s) << (32 - (c))); \ + CPU_OV = 0; \ + } else { \ + CPU_OV = ((s) >> 31) ^ ((s) & 1); \ + } \ + tmp = (s) & 1; \ + (s) = (tmp << 31) + ((s) >> 1); \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= tmp; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +/* + * ROL + */ +#define _BYTE_ROL1(d, s) \ +do { \ + UINT32 tmp = (s) >> 7; /* C_FLAG */ \ + (d) = ((s) << 1) + tmp; \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= tmp; \ + CPU_OV = ((s) ^ (d)) & 0x80; \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_ROL1(d, s) \ +do { \ + UINT32 tmp = (s) >> 15; /* C_FLAG */ \ + (d) = ((s) << 1) + tmp; \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= tmp; \ + CPU_OV = ((s) ^ (d)) & 0x8000; \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_ROL1(d, s) \ +do { \ + UINT32 tmp = (s) >> 31; /* C_FLAG */ \ + (d) = ((s) << 1) + tmp; \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= tmp; \ + CPU_OV = ((s) ^ (d)) & 0x80000000; \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_ROLCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + (c) = ((c) - 1) & 7; \ + if ((c)) { \ + (s) = ((s) << (c)) | ((s) >> (8 - (c))); \ + (s) &= 0xff; \ + } \ + _BYTE_ROL1(d, s); \ + } else { \ + (d) = (s); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_ROLCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + UINT32 tmp; \ + (c)--; \ + if ((c)) { \ + (c) &= 0x0f; \ + (s) = ((s) << (c)) | ((s) >> (16 - (c))); \ + (s) &= 0xffff; \ + CPU_OV = 0; \ + } else { \ + CPU_OV = ((s) + 0x4000) & 0x8000; \ + } \ + tmp = (s) >> 15; \ + (s) = ((s) << 1) + tmp; \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= tmp; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_ROLCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + UINT32 tmp; \ + (c)--; \ + if ((c)) { \ + (s) = ((s) << (c)) | ((s) >> (32 - (c))); \ + CPU_OV = 0; \ + } else { \ + CPU_OV = ((s) + 0x40000000) & 0x80000000; \ + } \ + tmp = (s) >> 31; \ + (s) = ((s) << 1) + tmp; \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= tmp; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +/* + * RCR + */ +#define _BYTE_RCR1(d, s) \ +do { \ + (d) = ((CPU_FLAGL & C_FLAG) << 7) + ((s) >> 1); \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= (s) & 1; \ + CPU_OV = ((s) ^ (d)) & 0x80; \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_RCR1(d, s) \ +do { \ + (d) = ((CPU_FLAGL & C_FLAG) << 15) + ((s) >> 1); \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= (s) & 1; \ + CPU_OV = ((s) ^ (d)) & 0x8000; \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_RCR1(d, s) \ +do { \ + (d) = ((CPU_FLAGL & C_FLAG) << 31) + ((s) >> 1); \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= (s) & 1; \ + CPU_OV = ((s) ^ (d)) & 0x80000000; \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_RCRCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + UINT32 tmp = CPU_FLAGL & C_FLAG; \ + CPU_FLAGL &= ~C_FLAG; \ + while ((c)--) { \ + (s) |= (tmp << 8); \ + tmp = (s) & 1; \ + (s) >>= 1; \ + } \ + CPU_OV = ((s) ^ ((s) >> 1)) & 0x40; \ + CPU_FLAGL |= tmp; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_RCRCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + UINT32 tmp = CPU_FLAGL & C_FLAG; \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_OV = 0; \ + if ((c) == 1) { \ + CPU_OV = ((s) >> 15) ^ tmp; \ + } \ + while ((c)--) { \ + (s) |= (tmp << 16); \ + tmp = (s) & 1; \ + (s) >>= 1; \ + } \ + CPU_FLAGL |= tmp; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_RCRCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + UINT32 tmp = CPU_FLAGL & C_FLAG; \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_OV = 0; \ + if ((c) == 1) { \ + CPU_OV = ((s) >> 31) ^ tmp; \ + } \ + while ((c)--) { \ + UINT32 tmp2 = (s) & 1; \ + (s) = (tmp << 31) | ((s) >> 1); \ + tmp = tmp2; \ + } \ + CPU_FLAGL |= tmp; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +/* + * RCL + */ +#define _BYTE_RCL1(d, s) \ +do { \ + (d) = ((s) << 1) | (CPU_FLAGL & C_FLAG); \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= (s) >> 7; /* C_FLAG */ \ + CPU_OV = ((s) ^ (d)) & 0x80; \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_RCL1(d, s) \ +do { \ + (d) = ((s) << 1) | (CPU_FLAGL & C_FLAG); \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= (s) >> 15; /* C_FLAG */ \ + CPU_OV = ((s) ^ (d)) & 0x8000; \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_RCL1(d, s) \ +do { \ + (d) = ((s) << 1) | (CPU_FLAGL & C_FLAG); \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_FLAGL |= (s) >> 31; /* C_FLAG */ \ + CPU_OV = ((s) ^ (d)) & 0x80000000; \ +} while (/*CONSTCOND*/ 0) + +#define _BYTE_RCLCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + UINT32 tmp = CPU_FLAGL & C_FLAG; \ + CPU_FLAGL &= ~C_FLAG; \ + while ((c)--) { \ + (s) = (((s) << 1) | tmp) & 0x1ff; \ + tmp = (s) >> 8; \ + } \ + CPU_OV = ((s) ^ ((s) >> 1)) & 0x80; \ + CPU_FLAGL |= tmp; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _WORD_RCLCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + UINT32 tmp = CPU_FLAGL & C_FLAG; \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_OV = 0; \ + if ((c) == 1) { \ + CPU_OV = ((s) + 0x4000) & 0x8000; \ + } \ + while ((c)--) { \ + (s) = (((s) << 1) | tmp) & 0x1ffff; \ + tmp = (s) >> 16; \ + } \ + CPU_FLAGL |= tmp; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#define _DWORD_RCLCL(d, s, c) \ +do { \ + (c) &= 0x1f; \ + if ((c)) { \ + UINT32 tmp = CPU_FLAGL & C_FLAG; \ + CPU_FLAGL &= ~C_FLAG; \ + CPU_OV = 0; \ + if ((c) == 1) { \ + CPU_OV = ((s) + 0x40000000) & 0x80000000; \ + } \ + while ((c)--) { \ + UINT32 tmp2 = (s) & 0x80000000; \ + (s) = ((s) << 1) | (tmp & 1); \ + tmp = tmp2 >> 31; \ + } \ + CPU_FLAGL |= tmp; \ + } \ + (d) = (s); \ +} while (/*CONSTCOND*/ 0) + +#if defined(IA32_CROSS_CHECK) && defined(GCC_CPU_ARCH_IA32) + +#include "shift_rotatexc.mcr" + +#define BYTE_SAR1(d, s) XC_BYTE_SAR1(d, s) +#define WORD_SAR1(d, s) XC_WORD_SAR1(d, s) +#define DWORD_SAR1(d, s) XC_DWORD_SAR1(d, s) +#define BYTE_SARCL(d, s, c) XC_BYTE_SARCL(d, s, c) +#define WORD_SARCL(d, s, c) XC_WORD_SARCL(d, s, c) +#define DWORD_SARCL(d, s, c) XC_DWORD_SARCL(d, s, c) +#define BYTE_SHR1(d, s) XC_BYTE_SHR1(d, s) +#define WORD_SHR1(d, s) XC_WORD_SHR1(d, s) +#define DWORD_SHR1(d, s) XC_DWORD_SHR1(d, s) +#define BYTE_SHRCL(d, s, c) XC_BYTE_SHRCL(d, s, c) +#define WORD_SHRCL(d, s, c) XC_WORD_SHRCL(d, s, c) +#define DWORD_SHRCL(d, s, c) XC_DWORD_SHRCL(d, s, c) +#define BYTE_SHL1(d, s) XC_BYTE_SHL1(d, s) +#define WORD_SHL1(d, s) XC_WORD_SHL1(d, s) +#define DWORD_SHL1(d, s) XC_DWORD_SHL1(d, s) +#define BYTE_SHLCL(d, s, c) XC_BYTE_SHLCL(d, s, c) +#define WORD_SHLCL(d, s, c) XC_WORD_SHLCL(d, s, c) +#define DWORD_SHLCL(d, s, c) XC_DWORD_SHLCL(d, s, c) +#define WORD_SHRD(d, s, c) XC_WORD_SHRD(d, s, c) +#define DWORD_SHRD(d, s, c) XC_DWORD_SHRD(d, s, c) +#define WORD_SHLD(d, s, c) XC_WORD_SHLD(d, s, c) +#define DWORD_SHLD(d, s, c) XC_DWORD_SHLD(d, s, c) +#define BYTE_ROR1(d, s) XC_BYTE_ROR1(d, s) +#define WORD_ROR1(d, s) XC_WORD_ROR1(d, s) +#define DWORD_ROR1(d, s) XC_DWORD_ROR1(d, s) +#define BYTE_RORCL(d, s, c) XC_BYTE_RORCL(d, s, c) +#define WORD_RORCL(d, s, c) XC_WORD_RORCL(d, s, c) +#define DWORD_RORCL(d, s, c) XC_DWORD_RORCL(d, s, c) +#define BYTE_ROL1(d, s) XC_BYTE_ROL1(d, s) +#define WORD_ROL1(d, s) XC_WORD_ROL1(d, s) +#define DWORD_ROL1(d, s) XC_DWORD_ROL1(d, s) +#define BYTE_ROLCL(d, s, c) XC_BYTE_ROLCL(d, s, c) +#define WORD_ROLCL(d, s, c) XC_WORD_ROLCL(d, s, c) +#define DWORD_ROLCL(d, s, c) XC_DWORD_ROLCL(d, s, c) +#define BYTE_RCR1(d, s) XC_BYTE_RCR1(d, s) +#define WORD_RCR1(d, s) XC_WORD_RCR1(d, s) +#define DWORD_RCR1(d, s) XC_DWORD_RCR1(d, s) +#define BYTE_RCRCL(d, s, c) XC_BYTE_RCRCL(d, s, c) +#define WORD_RCRCL(d, s, c) XC_WORD_RCRCL(d, s, c) +#define DWORD_RCRCL(d, s, c) XC_DWORD_RCRCL(d, s, c) +#define BYTE_RCL1(d, s) XC_BYTE_RCL1(d, s) +#define WORD_RCL1(d, s) XC_WORD_RCL1(d, s) +#define DWORD_RCL1(d, s) XC_DWORD_RCL1(d, s) +#define BYTE_RCLCL(d, s, c) XC_BYTE_RCLCL(d, s, c) +#define WORD_RCLCL(d, s, c) XC_WORD_RCLCL(d, s, c) +#define DWORD_RCLCL(d, s, c) XC_DWORD_RCLCL(d, s, c) + +#elif defined(IA32_CROSS_CHECK) && defined(_MSC_VER) + +#include "shift_rotatexc_msc.mcr" + +#else /* !(IA32_CROSS_CHECK && GCC_CPU_ARCH_IA32 */ + +#define BYTE_SAR1(d, s) _BYTE_SAR1(d, s) +#define WORD_SAR1(d, s) _WORD_SAR1(d, s) +#define DWORD_SAR1(d, s) _DWORD_SAR1(d, s) +#define BYTE_SARCL(d, s, c) _BYTE_SARCL(d, s, c) +#define WORD_SARCL(d, s, c) _WORD_SARCL(d, s, c) +#define DWORD_SARCL(d, s, c) _DWORD_SARCL(d, s, c) +#define BYTE_SHR1(d, s) _BYTE_SHR1(d, s) +#define WORD_SHR1(d, s) _WORD_SHR1(d, s) +#define DWORD_SHR1(d, s) _DWORD_SHR1(d, s) +#define BYTE_SHRCL(d, s, c) _BYTE_SHRCL(d, s, c) +#define WORD_SHRCL(d, s, c) _WORD_SHRCL(d, s, c) +#define DWORD_SHRCL(d, s, c) _DWORD_SHRCL(d, s, c) +#define BYTE_SHL1(d, s) _BYTE_SHL1(d, s) +#define WORD_SHL1(d, s) _WORD_SHL1(d, s) +#define DWORD_SHL1(d, s) _DWORD_SHL1(d, s) +#define BYTE_SHLCL(d, s, c) _BYTE_SHLCL(d, s, c) +#define WORD_SHLCL(d, s, c) _WORD_SHLCL(d, s, c) +#define DWORD_SHLCL(d, s, c) _DWORD_SHLCL(d, s, c) +#define WORD_SHRD(d, s, c) _WORD_SHRD(d, s, c) +#define DWORD_SHRD(d, s, c) _DWORD_SHRD(d, s, c) +#define WORD_SHLD(d, s, c) _WORD_SHLD(d, s, c) +#define DWORD_SHLD(d, s, c) _DWORD_SHLD(d, s, c) +#define BYTE_ROR1(d, s) _BYTE_ROR1(d, s) +#define WORD_ROR1(d, s) _WORD_ROR1(d, s) +#define DWORD_ROR1(d, s) _DWORD_ROR1(d, s) +#define BYTE_RORCL(d, s, c) _BYTE_RORCL(d, s, c) +#define WORD_RORCL(d, s, c) _WORD_RORCL(d, s, c) +#define DWORD_RORCL(d, s, c) _DWORD_RORCL(d, s, c) +#define BYTE_ROL1(d, s) _BYTE_ROL1(d, s) +#define WORD_ROL1(d, s) _WORD_ROL1(d, s) +#define DWORD_ROL1(d, s) _DWORD_ROL1(d, s) +#define BYTE_ROLCL(d, s, c) _BYTE_ROLCL(d, s, c) +#define WORD_ROLCL(d, s, c) _WORD_ROLCL(d, s, c) +#define DWORD_ROLCL(d, s, c) _DWORD_ROLCL(d, s, c) +#define BYTE_RCR1(d, s) _BYTE_RCR1(d, s) +#define WORD_RCR1(d, s) _WORD_RCR1(d, s) +#define DWORD_RCR1(d, s) _DWORD_RCR1(d, s) +#define BYTE_RCRCL(d, s, c) _BYTE_RCRCL(d, s, c) +#define WORD_RCRCL(d, s, c) _WORD_RCRCL(d, s, c) +#define DWORD_RCRCL(d, s, c) _DWORD_RCRCL(d, s, c) +#define BYTE_RCL1(d, s) _BYTE_RCL1(d, s) +#define WORD_RCL1(d, s) _WORD_RCL1(d, s) +#define DWORD_RCL1(d, s) _DWORD_RCL1(d, s) +#define BYTE_RCLCL(d, s, c) _BYTE_RCLCL(d, s, c) +#define WORD_RCLCL(d, s, c) _WORD_RCLCL(d, s, c) +#define DWORD_RCLCL(d, s, c) _DWORD_RCLCL(d, s, c) + +#endif /* IA32_CROSS_CHECK && GCC_CPU_ARCH_IA32 */ + +#endif /* IA32_CPU_SHIFT_ROTATE_MCR__ */ diff --git a/i386c/ia32/instructions/shift_rotatexc.mcr b/i386c/ia32/instructions/shift_rotatexc.mcr old mode 100755 new mode 100644 index 013e624a..70a2ff81 --- a/i386c/ia32/instructions/shift_rotatexc.mcr +++ b/i386c/ia32/instructions/shift_rotatexc.mcr @@ -1,2143 +1,2143 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_SHIFT_ROTATEXC_H__ -#define IA32_CPU_INSTRUCTION_SHIFT_ROTATEXC_H__ - -#define XC_BYTE_SAR1(d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_SAR1((d), (s)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "sarb $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_SAR1: __s = %02x", __s); \ - ia32_warning("XC_BYTE_SAR1: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_SAR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_BYTE_SAR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_SAR1(d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_SAR1((d), (s)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "sarw $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_SAR1: __s = %04x", __s); \ - ia32_warning("XC_WORD_SAR1: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_SAR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_WORD_SAR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_SAR1(d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_SAR1((d), (s)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "sarl $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_SAR1: __s = %08x", __s); \ - ia32_warning("XC_DWORD_SAR1: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_SAR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_DWORD_SAR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_SARCL(d, s, c) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_SARCL((d), (s), (c)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "sarb %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_BYTE_SARCL: __s = %02x", __s); \ - ia32_warning("XC_BYTE_SARCL: __c = %02x", __c); \ - ia32_warning("XC_BYTE_SARCL: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_SARCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_BYTE_SARCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_SARCL(d, s, c) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_SARCL((d), (s), (c)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "sarw %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_WORD_SARCL: __s = %04x", __s); \ - ia32_warning("XC_WORD_SARCL: __c = %02x", __c); \ - ia32_warning("XC_WORD_SARCL: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_SARCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_WORD_SARCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_SARCL(d, s, c) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_SARCL((d), (s), (c)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "sarl %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_DWORD_SARCL: __s = %08x", __s); \ - ia32_warning("XC_DWORD_SARCL: __c = %02x", __c); \ - ia32_warning("XC_DWORD_SARCL: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_SARCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_DWORD_SARCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_SHR1(d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_SHR1((d), (s)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "shrb $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_SHR1: __s = %02x", __s); \ - ia32_warning("XC_BYTE_SHR1: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_SHR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_BYTE_SHR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_SHR1(d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_SHR1((d), (s)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "shrw $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_SHR1: __s = %04x", __s); \ - ia32_warning("XC_WORD_SHR1: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_SHR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_WORD_SHR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_SHR1(d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_SHR1((d), (s)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "shrl $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_SHR1: __s = %08x", __s); \ - ia32_warning("XC_DWORD_SHR1: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_SHR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_DWORD_SHR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_SHRCL(d, s, c) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_SHRCL((d), (s), (c)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "shrb %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_BYTE_SHRCL: __s = %02x", __s); \ - ia32_warning("XC_BYTE_SHRCL: __c = %02x", __c); \ - ia32_warning("XC_BYTE_SHRCL: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_SHRCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_BYTE_SHRCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_SHRCL(d, s, c) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_SHRCL((d), (s), (c)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "shrw %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_WORD_SHRCL: __s = %04x", __s); \ - ia32_warning("XC_WORD_SHRCL: __c = %02x", __c); \ - ia32_warning("XC_WORD_SHRCL: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_SHRCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_WORD_SHRCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_SHRCL(d, s, c) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_SHRCL((d), (s), (c)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "shrl %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_DWORD_SHRCL: __s = %08x", __s); \ - ia32_warning("XC_DWORD_SHRCL: __c = %02x", __c); \ - ia32_warning("XC_DWORD_SHRCL: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_SHRCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_DWORD_SHRCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_SHL1(d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_SHL1((d), (s)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "shlb $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_SHL1: __s = %02x", __s); \ - ia32_warning("XC_BYTE_SHL1: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_SHL1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_BYTE_SHL1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/0) - -#define XC_WORD_SHL1(d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_SHL1((d), (s)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "shlw $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_SHL1: __s = %04x", __s); \ - ia32_warning("XC_WORD_SHL1: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_SHL1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_WORD_SHL1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_SHL1(d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_SHL1((d), (s)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "shll $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_SHL1: __s = %08x", __s); \ - ia32_warning("XC_DWORD_SHL1: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_SHL1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_DWORD_SHL1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_SHLCL(d, s, c) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_SHLCL((d), (s), (c)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "shlb %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_BYTE_SHLCL: __s = %02x", __s); \ - ia32_warning("XC_BYTE_SHLCL: __c = %02x", __c); \ - ia32_warning("XC_BYTE_SHLCL: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_SHLCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_BYTE_SHLCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_SHLCL(d, s, c) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_SHLCL((d), (s), (c)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "shlw %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_WORD_SHLCL: __s = %04x", __s); \ - ia32_warning("XC_WORD_SHLCL: __c = %02x", __c); \ - ia32_warning("XC_WORD_SHLCL: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_SHLCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_WORD_SHLCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_SHLCL(d, s, c) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_SHLCL((d), (s), (c)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "shll %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_DWORD_SHLCL: __s = %08x", __s); \ - ia32_warning("XC_DWORD_SHLCL: __c = %02x", __c); \ - ia32_warning("XC_DWORD_SHLCL: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_SHLCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_DWORD_SHLCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_SHRD(d, s, c) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __d = (d) & 0xffff; \ - UINT16 __r = __d; \ - UINT16 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_SHRD((d), (s), (c)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "pushl %%edx\n\t" \ - "movb %5, %%cl\n\t" \ - "movw %4, %%dx\n\t" \ - "shrdw %%cl, %%dx, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%edx\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s), "m" (__c) \ - : "eax", "ecx", "edx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_WORD_SHRD: __s = %04x, __d = %04x", \ - __s, __d); \ - ia32_warning("XC_WORD_SHRD: __c = %02x", __c); \ - ia32_warning("XC_WORD_SHRD: __R = %04x, __r = %04x",\ - __R, __r); \ - ia32_warning("XC_WORD_SHRD: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_WORD_SHRD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert((__c != 1) || (!CPU_OV == !__o)); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_SHRD(d, s, c) \ -do { \ - UINT32 __s = (s); \ - UINT32 __d = (d); \ - UINT32 __r = __d; \ - UINT32 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_SHRD((d), (s), (c)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "pushl %%edx\n\t" \ - "movb %5, %%cl\n\t" \ - "movl %4, %%edx\n\t" \ - "shrdl %%cl, %%edx, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%edx\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s), "m" (__c) \ - : "eax", "ecx", "edx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_DWORD_SHRD: __s = %08x, __d = %08x", \ - __s, __d); \ - ia32_warning("XC_DWORD_SHRD: __c = %02x", __c); \ - ia32_warning("XC_DWORD_SHRD: __R = %08x, __r = %08x",\ - __R, __r); \ - ia32_warning("XC_DWORD_SHRD: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_DWORD_SHRD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert((__c != 1) || (!CPU_OV == !__o)); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_SHLD(d, s, c) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __d = (d) & 0xffff; \ - UINT16 __r = __d; \ - UINT16 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_SHLD((d), (s), (c)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "pushl %%edx\n\t" \ - "movb %5, %%cl\n\t" \ - "movw %4, %%dx\n\t" \ - "shldw %%cl, %%dx, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%edx\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s), "m" (__c) \ - : "eax", "ecx", "edx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_WORD_SHLD: __s = %04x, __d = %04x", \ - __s, __d); \ - ia32_warning("XC_WORD_SHLD: __c = %02x", __c); \ - ia32_warning("XC_WORD_SHLD: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_SHLD: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_WORD_SHLD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert((__c != 1) || (!CPU_OV == !__o)); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_SHLD(d, s, c) \ -do { \ - UINT32 __s = (s); \ - UINT32 __d = (d); \ - UINT32 __r = __d; \ - UINT32 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_SHLD((d), (s), (c)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "pushl %%edx\n\t" \ - "movb %5, %%cl\n\t" \ - "movl %4, %%edx\n\t" \ - "shldl %%cl, %%edx, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%edx\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__s), "m" (__c) \ - : "eax", "ecx", "edx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_DWORD_SHLD: __s = %08x, __d = %08x", \ - __s, __d); \ - ia32_warning("XC_DWORD_SHLD: __c = %02x", __c); \ - ia32_warning("XC_DWORD_SHLD: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_SHLD: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, SZPC_FLAG); \ - ia32_warning("XC_DWORD_SHLD: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ - assert((__c != 1) || (!CPU_OV == !__o)); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_ROR1(d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_ROR1((d), (s)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "rorb $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_ROR1: __s = %02x", __s); \ - ia32_warning("XC_BYTE_ROR1: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_ROR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_BYTE_ROR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_ROR1(d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_ROR1((d), (s)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "rorw $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_ROR1: __s = %04x", __s); \ - ia32_warning("XC_WORD_ROR1: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_ROR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_WORD_ROR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_ROR1(d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_ROR1((d), (s)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "rorl $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_ROR1: __s = %08x", __s); \ - ia32_warning("XC_DWORD_ROR1: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_ROR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_DWORD_ROR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_RORCL(d, s, c) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_RORCL((d), (s), (c)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "rorb %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_BYTE_RORCL: __s = %02x", __s); \ - ia32_warning("XC_BYTE_RORCL: __c = %02x", __c); \ - ia32_warning("XC_BYTE_RORCL: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_RORCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_BYTE_RORCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_RORCL(d, s, c) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_RORCL((d), (s), (c)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "rorw %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_WORD_RORCL: __s = %04x", __s); \ - ia32_warning("XC_WORD_RORCL: __c = %02x", __c); \ - ia32_warning("XC_WORD_RORCL: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_RORCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_WORD_RORCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_RORCL(d, s, c) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_RORCL((d), (s), (c)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "rorl %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_DWORD_RORCL: __s = %08x", __s); \ - ia32_warning("XC_DWORD_RORCL: __c = %02x", __c); \ - ia32_warning("XC_DWORD_RORCL: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_RORCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_DWORD_RORCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_ROL1(d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_ROL1((d), (s)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "rolb $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_ROL1: __s = %02x", __s); \ - ia32_warning("XC_BYTE_ROL1: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_ROL1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_BYTE_ROL1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_ROL1(d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_ROL1((d), (s)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "rolw $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_ROL1: __s = %04x", __s); \ - ia32_warning("XC_WORD_ROL1: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_ROL1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_WORD_ROL1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_ROL1(d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_ROL1((d), (s)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "roll $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_ROL1: __s = %08x", __s); \ - ia32_warning("XC_DWORD_ROL1: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_ROL1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_DWORD_ROL1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_ROLCL(d, s, c) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _BYTE_ROLCL((d), (s), (c)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "rolb %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_BYTE_ROLCL: __s = %02x", __s); \ - ia32_warning("XC_BYTE_ROLCL: __c = %02x", __c); \ - ia32_warning("XC_BYTE_ROLCL: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_ROLCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_BYTE_ROLCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_ROLCL(d, s, c) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _WORD_ROLCL((d), (s), (c)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "rolw %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_WORD_ROLCL: __s = %04x", __s); \ - ia32_warning("XC_WORD_ROLCL: __c = %02x", __c); \ - ia32_warning("XC_WORD_ROLCL: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_ROLCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_WORD_ROLCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_ROLCL(d, s, c) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - \ - _DWORD_ROLCL((d), (s), (c)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "roll %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_DWORD_ROLCL: __s = %08x", __s); \ - ia32_warning("XC_DWORD_ROLCL: __c = %02x", __c); \ - ia32_warning("XC_DWORD_ROLCL: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_ROLCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_DWORD_ROLCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_RCR1(d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _BYTE_RCR1((d), (s)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "movzbl %4, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rcrb $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_RCR1: __s = %02x", __s); \ - ia32_warning("XC_BYTE_RCR1: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_RCR1: __xc_flagl = %02x", __xc_flagl); \ - ia32_warning("XC_BYTE_RCR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_BYTE_RCR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_RCR1(d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _WORD_RCR1((d), (s)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "movzbl %4, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rcrw $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_RCR1: __s = %04x", __s); \ - ia32_warning("XC_WORD_RCR1: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_RCR1: __xc_flagl = %02x", __xc_flagl); \ - ia32_warning("XC_WORD_RCR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_WORD_RCR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_RCR1(d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _DWORD_RCR1((d), (s)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "movzbl %4, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rcrl $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_RCR1: __s = %08x", __s); \ - ia32_warning("XC_DWORD_RCR1: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_RCR1: __xc_flagl = %02x", __xc_flagl); \ - ia32_warning("XC_DWORD_RCR1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_DWORD_RCR1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_RCRCL(d, s, c) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _BYTE_RCRCL((d), (s), (c)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rcrb %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c), "m" (__xc_flagl) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_BYTE_RCRCL: __s = %02x", __s); \ - ia32_warning("XC_BYTE_RCRCL: __c = %02x", __c); \ - ia32_warning("XC_BYTE_RCRCL: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_RCRCL: __xc_flagl = %02x", \ - __xc_flagl); \ - ia32_warning("XC_BYTE_RCRCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_BYTE_RCRCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_RCRCL(d, s, c) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _WORD_RCRCL((d), (s), (c)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rcrw %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c), "m" (__xc_flagl) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_WORD_RCRCL: __s = %04x", __s); \ - ia32_warning("XC_WORD_RCRCL: __c = %02x", __c); \ - ia32_warning("XC_WORD_RCRCL: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_RCRCL: __xc_flagl = %02x", \ - __xc_flagl); \ - ia32_warning("XC_WORD_RCRCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_WORD_RCRCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_RCRCL(d, s, c) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _DWORD_RCRCL((d), (s), (c)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rcrl %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c), "m" (__xc_flagl) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_DWORD_RCRCL: __s = %08x", __s); \ - ia32_warning("XC_DWORD_RCRCL: __c = %02x", __c); \ - ia32_warning("XC_DWORD_RCRCL: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_RCRCL: __xc_flagl = %02x", \ - __xc_flagl); \ - ia32_warning("XC_DWORD_RCRCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_DWORD_RCRCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_RCL1(d, s) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _BYTE_RCL1((d), (s)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "movzbl %4, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rclb $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_BYTE_RCL1: __s = %02x", __s); \ - ia32_warning("XC_BYTE_RCL1: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_RCL1: __xc_flagl = %02x", __xc_flagl); \ - ia32_warning("XC_BYTE_RCL1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_BYTE_RCL1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_RCL1(d, s) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _WORD_RCL1((d), (s)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "movzbl %4, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rclw $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_WORD_RCL1: __s = %04x", __s); \ - ia32_warning("XC_WORD_RCL1: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_RCL1: __xc_flagl = %02x", __xc_flagl); \ - ia32_warning("XC_WORD_RCL1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_WORD_RCL1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_RCL1(d, s) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _DWORD_RCL1((d), (s)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "movzbl %4, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rcll $1, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__xc_flagl) \ - : "eax"); \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - (!CPU_OV != !__o)) { \ - ia32_warning("XC_DWORD_RCL1: __s = %08x", __s); \ - ia32_warning("XC_DWORD_RCL1: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_RCL1: __xc_flagl = %02x", __xc_flagl); \ - ia32_warning("XC_DWORD_RCL1: CPU_FLAGL = %02x, __f = %02x, " \ - "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_DWORD_RCL1: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_BYTE_RCLCL(d, s, c) \ -do { \ - UINT8 __s = (s) & 0xff; \ - UINT8 __r = __s; \ - UINT8 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _BYTE_RCLCL((d), (s), (c)); \ - __R = (d) & 0xff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rclb %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c), "m" (__xc_flagl) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_BYTE_RCLCL: __s = %02x", __s); \ - ia32_warning("XC_BYTE_RCLCL: __c = %02x", __c); \ - ia32_warning("XC_BYTE_RCLCL: __R = %02x, __r = %02x", \ - __R, __r); \ - ia32_warning("XC_BYTE_RCLCL: __xc_flagl = %02x", \ - __xc_flagl); \ - ia32_warning("XC_BYTE_RCLCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_BYTE_RCLCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_WORD_RCLCL(d, s, c) \ -do { \ - UINT16 __s = (s) & 0xffff; \ - UINT16 __r = __s; \ - UINT16 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _WORD_RCLCL((d), (s), (c)); \ - __R = (d) & 0xffff; \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rclw %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c), "m" (__xc_flagl) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_WORD_RCLCL: __s = %04x", __s); \ - ia32_warning("XC_WORD_RCLCL: __c = %02x", __c); \ - ia32_warning("XC_WORD_RCLCL: __R = %04x, __r = %04x", \ - __R, __r); \ - ia32_warning("XC_WORD_RCLCL: __xc_flagl = %02x", \ - __xc_flagl); \ - ia32_warning("XC_WORD_RCLCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_WORD_RCLCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#define XC_DWORD_RCLCL(d, s, c) \ -do { \ - UINT32 __s = (s); \ - UINT32 __r = __s; \ - UINT32 __R; \ - UINT8 __c = (c) & 0xff; \ - UINT8 __f; \ - UINT8 __o; \ - UINT8 __xc_flagl = CPU_FLAGL; \ - \ - _DWORD_RCLCL((d), (s), (c)); \ - __R = (d); \ - \ - __asm__ __volatile__ ( \ - "pushf\n\t" \ - "pushl %%eax\n\t" \ - "pushl %%ecx\n\t" \ - "movb %4, %%cl\n\t" \ - "movzbl %5, %%eax\n\t" \ - "bt $0, %%eax\n\t" \ - "rcll %%cl, %0\n\t" \ - "lahf\n\t" \ - "movb %%ah, %1\n\t" \ - "seto %%ah\n\t" \ - "movb %%ah, %2\n\t" \ - "popl %%ecx\n\t" \ - "popl %%eax\n\t" \ - "popf\n\t" \ - : "=m" (__r), "=m" (__f), "=m" (__o) \ - : "0" (__r), "m" (__c), "m" (__xc_flagl) \ - : "eax", "ecx"); \ - if (__c != 0) { \ - if ((__R != __r) || \ - (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ - ((__c == 1) && (!CPU_OV != !__o))) { \ - ia32_warning("XC_DWORD_RCLCL: __s = %08x", __s); \ - ia32_warning("XC_DWORD_RCLCL: __c = %02x", __c); \ - ia32_warning("XC_DWORD_RCLCL: __R = %08x, __r = %08x", \ - __R, __r); \ - ia32_warning("XC_DWORD_RCLCL: __xc_flagl = %02x", \ - __xc_flagl); \ - ia32_warning("XC_DWORD_RCLCL: CPU_FLAGL = %02x, " \ - "__f = %02x, mask = %02x", \ - CPU_FLAGL, __f, C_FLAG); \ - ia32_warning("XC_DWORD_RCLCL: CPU_OV = %s, __o = %s", \ - CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ - assert(__R == __r); \ - assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ - assert(!CPU_OV == !__o); \ - } \ - } \ -} while (/*CONSTCOND*/ 0) - -#endif /* IA32_CPU_INSTRUCTION_SHIFT_ROTATEXC_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_SHIFT_ROTATEXC_H__ +#define IA32_CPU_INSTRUCTION_SHIFT_ROTATEXC_H__ + +#define XC_BYTE_SAR1(d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_SAR1((d), (s)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "sarb $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_SAR1: __s = %02x", __s); \ + ia32_warning("XC_BYTE_SAR1: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_SAR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_BYTE_SAR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_SAR1(d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_SAR1((d), (s)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "sarw $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_SAR1: __s = %04x", __s); \ + ia32_warning("XC_WORD_SAR1: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_SAR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_WORD_SAR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_SAR1(d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_SAR1((d), (s)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "sarl $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_SAR1: __s = %08x", __s); \ + ia32_warning("XC_DWORD_SAR1: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_SAR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_DWORD_SAR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_SARCL(d, s, c) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_SARCL((d), (s), (c)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "sarb %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_BYTE_SARCL: __s = %02x", __s); \ + ia32_warning("XC_BYTE_SARCL: __c = %02x", __c); \ + ia32_warning("XC_BYTE_SARCL: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_SARCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_BYTE_SARCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_SARCL(d, s, c) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_SARCL((d), (s), (c)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "sarw %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_WORD_SARCL: __s = %04x", __s); \ + ia32_warning("XC_WORD_SARCL: __c = %02x", __c); \ + ia32_warning("XC_WORD_SARCL: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_SARCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_WORD_SARCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_SARCL(d, s, c) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_SARCL((d), (s), (c)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "sarl %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_DWORD_SARCL: __s = %08x", __s); \ + ia32_warning("XC_DWORD_SARCL: __c = %02x", __c); \ + ia32_warning("XC_DWORD_SARCL: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_SARCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_DWORD_SARCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_SHR1(d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_SHR1((d), (s)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "shrb $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_SHR1: __s = %02x", __s); \ + ia32_warning("XC_BYTE_SHR1: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_SHR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_BYTE_SHR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_SHR1(d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_SHR1((d), (s)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "shrw $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_SHR1: __s = %04x", __s); \ + ia32_warning("XC_WORD_SHR1: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_SHR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_WORD_SHR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_SHR1(d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_SHR1((d), (s)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "shrl $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_SHR1: __s = %08x", __s); \ + ia32_warning("XC_DWORD_SHR1: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_SHR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_DWORD_SHR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_SHRCL(d, s, c) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_SHRCL((d), (s), (c)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "shrb %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_BYTE_SHRCL: __s = %02x", __s); \ + ia32_warning("XC_BYTE_SHRCL: __c = %02x", __c); \ + ia32_warning("XC_BYTE_SHRCL: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_SHRCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_BYTE_SHRCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_SHRCL(d, s, c) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_SHRCL((d), (s), (c)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "shrw %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_WORD_SHRCL: __s = %04x", __s); \ + ia32_warning("XC_WORD_SHRCL: __c = %02x", __c); \ + ia32_warning("XC_WORD_SHRCL: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_SHRCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_WORD_SHRCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_SHRCL(d, s, c) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_SHRCL((d), (s), (c)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "shrl %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_DWORD_SHRCL: __s = %08x", __s); \ + ia32_warning("XC_DWORD_SHRCL: __c = %02x", __c); \ + ia32_warning("XC_DWORD_SHRCL: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_SHRCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_DWORD_SHRCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_SHL1(d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_SHL1((d), (s)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "shlb $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_SHL1: __s = %02x", __s); \ + ia32_warning("XC_BYTE_SHL1: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_SHL1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_BYTE_SHL1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/0) + +#define XC_WORD_SHL1(d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_SHL1((d), (s)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "shlw $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_SHL1: __s = %04x", __s); \ + ia32_warning("XC_WORD_SHL1: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_SHL1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_WORD_SHL1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_SHL1(d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_SHL1((d), (s)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "shll $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_SHL1: __s = %08x", __s); \ + ia32_warning("XC_DWORD_SHL1: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_SHL1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_DWORD_SHL1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_SHLCL(d, s, c) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_SHLCL((d), (s), (c)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "shlb %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_BYTE_SHLCL: __s = %02x", __s); \ + ia32_warning("XC_BYTE_SHLCL: __c = %02x", __c); \ + ia32_warning("XC_BYTE_SHLCL: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_SHLCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_BYTE_SHLCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_SHLCL(d, s, c) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_SHLCL((d), (s), (c)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "shlw %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_WORD_SHLCL: __s = %04x", __s); \ + ia32_warning("XC_WORD_SHLCL: __c = %02x", __c); \ + ia32_warning("XC_WORD_SHLCL: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_SHLCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_WORD_SHLCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_SHLCL(d, s, c) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_SHLCL((d), (s), (c)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "shll %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_DWORD_SHLCL: __s = %08x", __s); \ + ia32_warning("XC_DWORD_SHLCL: __c = %02x", __c); \ + ia32_warning("XC_DWORD_SHLCL: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_SHLCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_DWORD_SHLCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_SHRD(d, s, c) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __d = (d) & 0xffff; \ + UINT16 __r = __d; \ + UINT16 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_SHRD((d), (s), (c)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "pushl %%edx\n\t" \ + "movb %5, %%cl\n\t" \ + "movw %4, %%dx\n\t" \ + "shrdw %%cl, %%dx, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%edx\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s), "m" (__c) \ + : "eax", "ecx", "edx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_WORD_SHRD: __s = %04x, __d = %04x", \ + __s, __d); \ + ia32_warning("XC_WORD_SHRD: __c = %02x", __c); \ + ia32_warning("XC_WORD_SHRD: __R = %04x, __r = %04x",\ + __R, __r); \ + ia32_warning("XC_WORD_SHRD: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_WORD_SHRD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert((__c != 1) || (!CPU_OV == !__o)); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_SHRD(d, s, c) \ +do { \ + UINT32 __s = (s); \ + UINT32 __d = (d); \ + UINT32 __r = __d; \ + UINT32 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_SHRD((d), (s), (c)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "pushl %%edx\n\t" \ + "movb %5, %%cl\n\t" \ + "movl %4, %%edx\n\t" \ + "shrdl %%cl, %%edx, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%edx\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s), "m" (__c) \ + : "eax", "ecx", "edx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_DWORD_SHRD: __s = %08x, __d = %08x", \ + __s, __d); \ + ia32_warning("XC_DWORD_SHRD: __c = %02x", __c); \ + ia32_warning("XC_DWORD_SHRD: __R = %08x, __r = %08x",\ + __R, __r); \ + ia32_warning("XC_DWORD_SHRD: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_DWORD_SHRD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert((__c != 1) || (!CPU_OV == !__o)); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_SHLD(d, s, c) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __d = (d) & 0xffff; \ + UINT16 __r = __d; \ + UINT16 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_SHLD((d), (s), (c)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "pushl %%edx\n\t" \ + "movb %5, %%cl\n\t" \ + "movw %4, %%dx\n\t" \ + "shldw %%cl, %%dx, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%edx\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s), "m" (__c) \ + : "eax", "ecx", "edx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_WORD_SHLD: __s = %04x, __d = %04x", \ + __s, __d); \ + ia32_warning("XC_WORD_SHLD: __c = %02x", __c); \ + ia32_warning("XC_WORD_SHLD: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_SHLD: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_WORD_SHLD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert((__c != 1) || (!CPU_OV == !__o)); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_SHLD(d, s, c) \ +do { \ + UINT32 __s = (s); \ + UINT32 __d = (d); \ + UINT32 __r = __d; \ + UINT32 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_SHLD((d), (s), (c)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "pushl %%edx\n\t" \ + "movb %5, %%cl\n\t" \ + "movl %4, %%edx\n\t" \ + "shldl %%cl, %%edx, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%edx\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__s), "m" (__c) \ + : "eax", "ecx", "edx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & SZPC_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_DWORD_SHLD: __s = %08x, __d = %08x", \ + __s, __d); \ + ia32_warning("XC_DWORD_SHLD: __c = %02x", __c); \ + ia32_warning("XC_DWORD_SHLD: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_SHLD: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, SZPC_FLAG); \ + ia32_warning("XC_DWORD_SHLD: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & SZPC_FLAG) == 0); \ + assert((__c != 1) || (!CPU_OV == !__o)); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_ROR1(d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_ROR1((d), (s)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "rorb $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_ROR1: __s = %02x", __s); \ + ia32_warning("XC_BYTE_ROR1: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_ROR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_BYTE_ROR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_ROR1(d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_ROR1((d), (s)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "rorw $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_ROR1: __s = %04x", __s); \ + ia32_warning("XC_WORD_ROR1: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_ROR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_WORD_ROR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_ROR1(d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_ROR1((d), (s)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "rorl $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_ROR1: __s = %08x", __s); \ + ia32_warning("XC_DWORD_ROR1: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_ROR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_DWORD_ROR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_RORCL(d, s, c) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_RORCL((d), (s), (c)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "rorb %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_BYTE_RORCL: __s = %02x", __s); \ + ia32_warning("XC_BYTE_RORCL: __c = %02x", __c); \ + ia32_warning("XC_BYTE_RORCL: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_RORCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_BYTE_RORCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_RORCL(d, s, c) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_RORCL((d), (s), (c)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "rorw %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_WORD_RORCL: __s = %04x", __s); \ + ia32_warning("XC_WORD_RORCL: __c = %02x", __c); \ + ia32_warning("XC_WORD_RORCL: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_RORCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_WORD_RORCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_RORCL(d, s, c) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_RORCL((d), (s), (c)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "rorl %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_DWORD_RORCL: __s = %08x", __s); \ + ia32_warning("XC_DWORD_RORCL: __c = %02x", __c); \ + ia32_warning("XC_DWORD_RORCL: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_RORCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_DWORD_RORCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_ROL1(d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_ROL1((d), (s)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "rolb $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_ROL1: __s = %02x", __s); \ + ia32_warning("XC_BYTE_ROL1: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_ROL1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_BYTE_ROL1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_ROL1(d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_ROL1((d), (s)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "rolw $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_ROL1: __s = %04x", __s); \ + ia32_warning("XC_WORD_ROL1: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_ROL1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_WORD_ROL1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_ROL1(d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_ROL1((d), (s)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "roll $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_ROL1: __s = %08x", __s); \ + ia32_warning("XC_DWORD_ROL1: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_ROL1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_DWORD_ROL1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_ROLCL(d, s, c) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _BYTE_ROLCL((d), (s), (c)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "rolb %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_BYTE_ROLCL: __s = %02x", __s); \ + ia32_warning("XC_BYTE_ROLCL: __c = %02x", __c); \ + ia32_warning("XC_BYTE_ROLCL: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_ROLCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_BYTE_ROLCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_ROLCL(d, s, c) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _WORD_ROLCL((d), (s), (c)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "rolw %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_WORD_ROLCL: __s = %04x", __s); \ + ia32_warning("XC_WORD_ROLCL: __c = %02x", __c); \ + ia32_warning("XC_WORD_ROLCL: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_ROLCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_WORD_ROLCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_ROLCL(d, s, c) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + \ + _DWORD_ROLCL((d), (s), (c)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "roll %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_DWORD_ROLCL: __s = %08x", __s); \ + ia32_warning("XC_DWORD_ROLCL: __c = %02x", __c); \ + ia32_warning("XC_DWORD_ROLCL: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_ROLCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_DWORD_ROLCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_RCR1(d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _BYTE_RCR1((d), (s)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "movzbl %4, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rcrb $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_RCR1: __s = %02x", __s); \ + ia32_warning("XC_BYTE_RCR1: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_RCR1: __xc_flagl = %02x", __xc_flagl); \ + ia32_warning("XC_BYTE_RCR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_BYTE_RCR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_RCR1(d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _WORD_RCR1((d), (s)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "movzbl %4, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rcrw $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_RCR1: __s = %04x", __s); \ + ia32_warning("XC_WORD_RCR1: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_RCR1: __xc_flagl = %02x", __xc_flagl); \ + ia32_warning("XC_WORD_RCR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_WORD_RCR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_RCR1(d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _DWORD_RCR1((d), (s)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "movzbl %4, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rcrl $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_RCR1: __s = %08x", __s); \ + ia32_warning("XC_DWORD_RCR1: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_RCR1: __xc_flagl = %02x", __xc_flagl); \ + ia32_warning("XC_DWORD_RCR1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_DWORD_RCR1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_RCRCL(d, s, c) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _BYTE_RCRCL((d), (s), (c)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rcrb %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c), "m" (__xc_flagl) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_BYTE_RCRCL: __s = %02x", __s); \ + ia32_warning("XC_BYTE_RCRCL: __c = %02x", __c); \ + ia32_warning("XC_BYTE_RCRCL: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_RCRCL: __xc_flagl = %02x", \ + __xc_flagl); \ + ia32_warning("XC_BYTE_RCRCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_BYTE_RCRCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_RCRCL(d, s, c) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _WORD_RCRCL((d), (s), (c)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rcrw %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c), "m" (__xc_flagl) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_WORD_RCRCL: __s = %04x", __s); \ + ia32_warning("XC_WORD_RCRCL: __c = %02x", __c); \ + ia32_warning("XC_WORD_RCRCL: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_RCRCL: __xc_flagl = %02x", \ + __xc_flagl); \ + ia32_warning("XC_WORD_RCRCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_WORD_RCRCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_RCRCL(d, s, c) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _DWORD_RCRCL((d), (s), (c)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rcrl %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c), "m" (__xc_flagl) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_DWORD_RCRCL: __s = %08x", __s); \ + ia32_warning("XC_DWORD_RCRCL: __c = %02x", __c); \ + ia32_warning("XC_DWORD_RCRCL: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_RCRCL: __xc_flagl = %02x", \ + __xc_flagl); \ + ia32_warning("XC_DWORD_RCRCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_DWORD_RCRCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_RCL1(d, s) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _BYTE_RCL1((d), (s)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "movzbl %4, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rclb $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_BYTE_RCL1: __s = %02x", __s); \ + ia32_warning("XC_BYTE_RCL1: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_RCL1: __xc_flagl = %02x", __xc_flagl); \ + ia32_warning("XC_BYTE_RCL1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_BYTE_RCL1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_RCL1(d, s) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _WORD_RCL1((d), (s)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "movzbl %4, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rclw $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_WORD_RCL1: __s = %04x", __s); \ + ia32_warning("XC_WORD_RCL1: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_RCL1: __xc_flagl = %02x", __xc_flagl); \ + ia32_warning("XC_WORD_RCL1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_WORD_RCL1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_RCL1(d, s) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _DWORD_RCL1((d), (s)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "movzbl %4, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rcll $1, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__xc_flagl) \ + : "eax"); \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + (!CPU_OV != !__o)) { \ + ia32_warning("XC_DWORD_RCL1: __s = %08x", __s); \ + ia32_warning("XC_DWORD_RCL1: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_RCL1: __xc_flagl = %02x", __xc_flagl); \ + ia32_warning("XC_DWORD_RCL1: CPU_FLAGL = %02x, __f = %02x, " \ + "mask = %02x", CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_DWORD_RCL1: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_BYTE_RCLCL(d, s, c) \ +do { \ + UINT8 __s = (s) & 0xff; \ + UINT8 __r = __s; \ + UINT8 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _BYTE_RCLCL((d), (s), (c)); \ + __R = (d) & 0xff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rclb %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c), "m" (__xc_flagl) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_BYTE_RCLCL: __s = %02x", __s); \ + ia32_warning("XC_BYTE_RCLCL: __c = %02x", __c); \ + ia32_warning("XC_BYTE_RCLCL: __R = %02x, __r = %02x", \ + __R, __r); \ + ia32_warning("XC_BYTE_RCLCL: __xc_flagl = %02x", \ + __xc_flagl); \ + ia32_warning("XC_BYTE_RCLCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_BYTE_RCLCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_WORD_RCLCL(d, s, c) \ +do { \ + UINT16 __s = (s) & 0xffff; \ + UINT16 __r = __s; \ + UINT16 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _WORD_RCLCL((d), (s), (c)); \ + __R = (d) & 0xffff; \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rclw %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c), "m" (__xc_flagl) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_WORD_RCLCL: __s = %04x", __s); \ + ia32_warning("XC_WORD_RCLCL: __c = %02x", __c); \ + ia32_warning("XC_WORD_RCLCL: __R = %04x, __r = %04x", \ + __R, __r); \ + ia32_warning("XC_WORD_RCLCL: __xc_flagl = %02x", \ + __xc_flagl); \ + ia32_warning("XC_WORD_RCLCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_WORD_RCLCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#define XC_DWORD_RCLCL(d, s, c) \ +do { \ + UINT32 __s = (s); \ + UINT32 __r = __s; \ + UINT32 __R; \ + UINT8 __c = (c) & 0xff; \ + UINT8 __f; \ + UINT8 __o; \ + UINT8 __xc_flagl = CPU_FLAGL; \ + \ + _DWORD_RCLCL((d), (s), (c)); \ + __R = (d); \ + \ + __asm__ __volatile__ ( \ + "pushf\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%ecx\n\t" \ + "movb %4, %%cl\n\t" \ + "movzbl %5, %%eax\n\t" \ + "bt $0, %%eax\n\t" \ + "rcll %%cl, %0\n\t" \ + "lahf\n\t" \ + "movb %%ah, %1\n\t" \ + "seto %%ah\n\t" \ + "movb %%ah, %2\n\t" \ + "popl %%ecx\n\t" \ + "popl %%eax\n\t" \ + "popf\n\t" \ + : "=m" (__r), "=m" (__f), "=m" (__o) \ + : "0" (__r), "m" (__c), "m" (__xc_flagl) \ + : "eax", "ecx"); \ + if (__c != 0) { \ + if ((__R != __r) || \ + (((__f ^ CPU_FLAGL) & C_FLAG) != 0) || \ + ((__c == 1) && (!CPU_OV != !__o))) { \ + ia32_warning("XC_DWORD_RCLCL: __s = %08x", __s); \ + ia32_warning("XC_DWORD_RCLCL: __c = %02x", __c); \ + ia32_warning("XC_DWORD_RCLCL: __R = %08x, __r = %08x", \ + __R, __r); \ + ia32_warning("XC_DWORD_RCLCL: __xc_flagl = %02x", \ + __xc_flagl); \ + ia32_warning("XC_DWORD_RCLCL: CPU_FLAGL = %02x, " \ + "__f = %02x, mask = %02x", \ + CPU_FLAGL, __f, C_FLAG); \ + ia32_warning("XC_DWORD_RCLCL: CPU_OV = %s, __o = %s", \ + CPU_OV ? "OV" : "NV", __o ? "OV" : "NV"); \ + assert(__R == __r); \ + assert(((__f ^ CPU_FLAGL) & C_FLAG) == 0); \ + assert(!CPU_OV == !__o); \ + } \ + } \ +} while (/*CONSTCOND*/ 0) + +#endif /* IA32_CPU_INSTRUCTION_SHIFT_ROTATEXC_H__ */ diff --git a/i386c/ia32/instructions/shift_rotatexc_msc.mcr b/i386c/ia32/instructions/shift_rotatexc_msc.mcr old mode 100755 new mode 100644 index 8dc802d9..82b8bdb9 --- a/i386c/ia32/instructions/shift_rotatexc_msc.mcr +++ b/i386c/ia32/instructions/shift_rotatexc_msc.mcr @@ -1,638 +1,638 @@ - -// Crosscheck for VC++ - -#define SETFLAGS \ - __asm { cmp CPU_OV, 0 } \ - __asm { setne al } \ - __asm { add al, 7fh } \ - __asm { mov ah, CPU_FLAGL } \ - __asm { sahf } - - - -#define BYTE_SAR1(d, s) { \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { sar _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_SAR1(d, s); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sarb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_SAR1(d, s) { \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { sar _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_SAR1(d, s); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sarw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_SAR1(d, s) { \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { sar _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_SAR1(d, s); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sard1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define BYTE_SARCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { sar _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_SARCL(d, s, c); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sarb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_SARCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { sar _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_SARCL(d, s, c); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sarw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_SARCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { sar _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_SARCL(d, s, c); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sard(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_SHL1(d, s) { \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { shl _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_SHL1(d, s); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shlb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_SHL1(d, s) { \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { shl _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_SHL1(d, s); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shlw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_SHL1(d, s) { \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { shl _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_SHL1(d, s); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shld1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define BYTE_SHLCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { shl _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_SHLCL(d, s, c); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shlb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_SHLCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { shl _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_SHLCL(d, s, c); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shlw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_SHLCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { shl _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_SHLCL(d, s, c); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shld(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_SHR1(d, s) { \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { shr _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_SHR1(d, s); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_SHR1(d, s) { \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { shr _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_SHR1(d, s); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_SHR1(d, s) { \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { shr _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_SHR1(d, s); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrd1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define BYTE_SHRCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { shr _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_SHRCL(d, s, c); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_SHRCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { shr _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_SHRCL(d, s, c); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_SHRCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { shr _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_SHRCL(d, s, c); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrd(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define WORD_SHLD(d, s, c) { \ - UINT8 _c = (c); \ - UINT16 _s = (s); \ - UINT16 _d = (d); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { mov ax, _s } \ - __asm { shld _d, ax, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_SHLD(d, s, c); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shldw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_SHLD(d, s, c) { \ - UINT8 _c = (c); \ - UINT32 _s = (s); \ - UINT32 _d = (d); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { mov eax, _s } \ - __asm { shld _d, eax, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_SHLD(d, s, c); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shldd r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define WORD_SHRD(d, s, c) { \ - UINT8 _c = (c); \ - UINT16 _s = (s); \ - UINT16 _d = (d); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { mov ax, _s } \ - __asm { shrd _d, ax, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_SHRD(d, s, c); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrdw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_SHRD(d, s, c) { \ - UINT8 _c = (c); \ - UINT32 _s = (s); \ - UINT32 _d = (d); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { mov eax, _s } \ - __asm { shrd _d, eax, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_SHRD(d, s, c); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrdd r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_RCL1(d, s) { \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { rcl _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_RCL1(d, s); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rclb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_RCL1(d, s) { \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { rcl _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_RCL1(d, s); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rclw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_RCL1(d, s) { \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { rcl _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_RCL1(d, s); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcld1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define BYTE_RCLCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { rcl _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_RCLCL(d, s, c); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rclb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_RCLCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { rcl _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_RCLCL(d, s, c); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rclw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_RCLCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { rcl _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_RCLCL(d, s, c); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcld(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_RCR1(d, s) { \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { rcr _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_RCR1(d, s); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_RCR1(d, s) { \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { rcr _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_RCR1(d, s); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_RCR1(d, s) { \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { rcr _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_RCR1(d, s); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrd1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define BYTE_RCRCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { rcr _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_RCRCL(d, s, c); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_RCRCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { rcr _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_RCRCL(d, s, c); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_RCRCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { rcr _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_RCRCL(d, s, c); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrd(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_ROL1(d, s) { \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { rol _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_ROL1(d, s); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rolb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_ROL1(d, s) { \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { rol _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_ROL1(d, s); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rolw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_ROL1(d, s) { \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { rol _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_ROL1(d, s); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rold1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define BYTE_ROLCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { rol _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_ROLCL(d, s, c); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rolb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_ROLCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { rol _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_ROLCL(d, s, c); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rolw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_ROLCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { rol _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_ROLCL(d, s, c); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rold(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - - - -#define BYTE_ROR1(d, s) { \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { ror _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_ROR1(d, s); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rorb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_ROR1(d, s) { \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { ror _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_ROR1(d, s); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rorw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_ROR1(d, s) { \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { ror _d, 1 } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_ROR1(d, s); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rord1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define BYTE_RORCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT8 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { ror _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _BYTE_RORCL(d, s, c); \ - if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rorb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define WORD_RORCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT16 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { ror _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _WORD_RORCL(d, s, c); \ - if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rorw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - -#define DWORD_RORCL(d, s, c) { \ - UINT8 _c = (c); \ - UINT32 _d = (s); \ - UINT8 _f, _ov; \ - SETFLAGS \ - __asm { mov cl, _c } \ - __asm { ror _d, cl } \ - __asm { seto _ov } \ - __asm { lahf } \ - __asm { mov _f, ah } \ - _DWORD_RORCL(d, s, c); \ - if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rord(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ -} - + +// Crosscheck for VC++ + +#define SETFLAGS \ + __asm { cmp CPU_OV, 0 } \ + __asm { setne al } \ + __asm { add al, 7fh } \ + __asm { mov ah, CPU_FLAGL } \ + __asm { sahf } + + + +#define BYTE_SAR1(d, s) { \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { sar _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_SAR1(d, s); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sarb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_SAR1(d, s) { \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { sar _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_SAR1(d, s); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sarw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_SAR1(d, s) { \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { sar _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_SAR1(d, s); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sard1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define BYTE_SARCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { sar _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_SARCL(d, s, c); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sarb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_SARCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { sar _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_SARCL(d, s, c); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sarw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_SARCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { sar _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_SARCL(d, s, c); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("sard(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_SHL1(d, s) { \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { shl _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_SHL1(d, s); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shlb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_SHL1(d, s) { \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { shl _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_SHL1(d, s); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shlw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_SHL1(d, s) { \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { shl _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_SHL1(d, s); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shld1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define BYTE_SHLCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { shl _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_SHLCL(d, s, c); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shlb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_SHLCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { shl _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_SHLCL(d, s, c); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shlw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_SHLCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { shl _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_SHLCL(d, s, c); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shld(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_SHR1(d, s) { \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { shr _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_SHR1(d, s); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_SHR1(d, s) { \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { shr _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_SHR1(d, s); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_SHR1(d, s) { \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { shr _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_SHR1(d, s); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrd1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define BYTE_SHRCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { shr _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_SHRCL(d, s, c); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_SHRCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { shr _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_SHRCL(d, s, c); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_SHRCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { shr _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_SHRCL(d, s, c); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrd(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define WORD_SHLD(d, s, c) { \ + UINT8 _c = (c); \ + UINT16 _s = (s); \ + UINT16 _d = (d); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { mov ax, _s } \ + __asm { shld _d, ax, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_SHLD(d, s, c); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shldw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_SHLD(d, s, c) { \ + UINT8 _c = (c); \ + UINT32 _s = (s); \ + UINT32 _d = (d); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { mov eax, _s } \ + __asm { shld _d, eax, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_SHLD(d, s, c); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shldd r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define WORD_SHRD(d, s, c) { \ + UINT8 _c = (c); \ + UINT16 _s = (s); \ + UINT16 _d = (d); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { mov ax, _s } \ + __asm { shrd _d, ax, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_SHRD(d, s, c); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrdw r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_SHRD(d, s, c) { \ + UINT8 _c = (c); \ + UINT32 _s = (s); \ + UINT32 _d = (d); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { mov eax, _s } \ + __asm { shrd _d, eax, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_SHRD(d, s, c); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("shrdd r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_RCL1(d, s) { \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { rcl _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_RCL1(d, s); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rclb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_RCL1(d, s) { \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { rcl _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_RCL1(d, s); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rclw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_RCL1(d, s) { \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { rcl _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_RCL1(d, s); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcld1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define BYTE_RCLCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { rcl _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_RCLCL(d, s, c); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rclb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_RCLCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { rcl _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_RCLCL(d, s, c); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rclw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_RCLCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { rcl _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_RCLCL(d, s, c); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcld(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_RCR1(d, s) { \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { rcr _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_RCR1(d, s); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_RCR1(d, s) { \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { rcr _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_RCR1(d, s); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_RCR1(d, s) { \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { rcr _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_RCR1(d, s); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrd1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define BYTE_RCRCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { rcr _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_RCRCL(d, s, c); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_RCRCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { rcr _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_RCRCL(d, s, c); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_RCRCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { rcr _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_RCRCL(d, s, c); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rcrd(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_ROL1(d, s) { \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { rol _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_ROL1(d, s); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rolb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_ROL1(d, s) { \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { rol _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_ROL1(d, s); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rolw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_ROL1(d, s) { \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { rol _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_ROL1(d, s); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rold1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define BYTE_ROLCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { rol _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_ROLCL(d, s, c); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rolb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_ROLCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { rol _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_ROLCL(d, s, c); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rolw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_ROLCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { rol _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_ROLCL(d, s, c); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rold(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + + + +#define BYTE_ROR1(d, s) { \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { ror _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_ROR1(d, s); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rorb1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_ROR1(d, s) { \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { ror _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_ROR1(d, s); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rorw1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_ROR1(d, s) { \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { ror _d, 1 } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_ROR1(d, s); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rord1 r=%x:%x f=%x:%x o=%d %d", _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define BYTE_RORCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT8 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { ror _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _BYTE_RORCL(d, s, c); \ + if ((_d != (UINT8)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rorb(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define WORD_RORCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT16 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { ror _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _WORD_RORCL(d, s, c); \ + if ((_d != (UINT16)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rorw(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + +#define DWORD_RORCL(d, s, c) { \ + UINT8 _c = (c); \ + UINT32 _d = (s); \ + UINT8 _f, _ov; \ + SETFLAGS \ + __asm { mov cl, _c } \ + __asm { ror _d, cl } \ + __asm { seto _ov } \ + __asm { lahf } \ + __asm { mov _f, ah } \ + _DWORD_RORCL(d, s, c); \ + if ((_d != (UINT32)(d)) || ((_f ^ CPU_FLAGL) & SZPC_FLAG) || ((!_ov) != (!CPU_OV))) TRACEOUT(("rord(%x) r=%x:%x f=%x:%x o=%d %d", _c, _d, d, _f, CPU_FLAGL, _ov, CPU_OV)); \ +} + diff --git a/i386c/ia32/instructions/sse/sse.c b/i386c/ia32/instructions/sse/sse.c old mode 100755 new mode 100644 index ffefd290..90f8c16e --- a/i386c/ia32/instructions/sse/sse.c +++ b/i386c/ia32/instructions/sse/sse.c @@ -1,1770 +1,1770 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include - -#include -#include - -#if defined(_WIN32) && !defined(__LIBRETRO__) -#define isnan(x) (_isnan(x)) -#endif - -#include -#include "ia32/ia32.mcr" - -#include "ia32/instructions/sse/sse.h" - -#if defined(USE_SSE) && defined(USE_FPU) - -#define CPU_SSEWORKCLOCK CPU_WORKCLOCK(2) - -static INLINE void -SSE_check_NM_EXCEPTION(){ - // SSEなしならUD(無効オペコード例外)を発生させる - if(!(i386cpuid.cpu_feature & CPU_FEATURE_SSE) && !(i386cpuid.cpu_feature_ex & CPU_FEATURE_EX_E3DNOW)){ // XXX: SSE命令にEnhanced 3DNow!命令が一部あるので例外的に認める - EXCEPTION(UD_EXCEPTION, 0); - } - // エミュレーションならUD(無効オペコード例外)を発生させる - if(CPU_CR0 & CPU_CR0_EM){ - EXCEPTION(UD_EXCEPTION, 0); - } - // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる - if (CPU_CR0 & CPU_CR0_TS) { - EXCEPTION(NM_EXCEPTION, 0); - } -} - -static INLINE void -SSE_setTag(void) -{ -// int i; -// -// if(!FPU_STAT.mmxenable){ -// FPU_STAT.mmxenable = 1; -// //FPU_CTRLWORD = 0x27F; -// for (i = 0; i < FPU_REG_NUM; i++) { -// FPU_STAT.tag[i] = TAG_Valid; -//#ifdef SUPPORT_FPU_DOSBOX2 -// FPU_STAT.int_regvalid[i] = 0; -//#endif -// FPU_STAT.reg[i].ul.ext = 0xffff; -// } -// } -// FPU_STAT_TOP = 0; -// FPU_STATUSWORD &= ~0x3800; -// FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; -} - -// mmx.cのものと同じ -static INLINE void -MMX_setTag(void) -{ - int i; - - if(!FPU_STAT.mmxenable){ - FPU_STAT.mmxenable = 1; - //FPU_CTRLWORD = 0x27F; - for (i = 0; i < FPU_REG_NUM; i++) { - FPU_STAT.tag[i] = TAG_Valid; -#ifdef SUPPORT_FPU_DOSBOX2 - FPU_STAT.int_regvalid[i] = 0; -#endif - FPU_STAT.reg[i].ul.ext = 0xffff; - } - } - FPU_STAT_TOP = 0; - FPU_STATUSWORD &= ~0x3800; - FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; -} - -float SSE_ROUND(float val){ - float floorval; - int rndbit = (SSE_MXCSR >> 13) & 0x3; - switch(rndbit){ - case 0: - floorval = (float)floor(val); - if (val - floorval > 0.5f){ - return (floorval + 1); // 切り上げ - }else if (val - floorval < 0.5f){ - return (floorval); // 切り捨て - }else{ - if(floor(floorval / 2) == floorval/2){ - return (floorval); // 偶数 - }else{ - return (floorval+1); // 奇数 - } - } - break; - case 1: - return (float)floor(val); - case 2: - return (float)ceil(val); - case 3: - if(val < 0){ - return (float)ceil(val); // ゼロ方向への切り捨て - }else{ - return (float)floor(val); // ゼロ方向への切り捨て - } - break; - default: - return val; - } -} - -/* - * SSE interface - */ - -// コードが長くなるのでやや強引に共通化 -// xmm/m128 -> xmm -static INLINE void SSE_PART_GETDATA1DATA2_P(float **data1, float **data2, float *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *((UINT32*)(data2buf+ 1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); - *((UINT32*)(data2buf+ 2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 8); - *((UINT32*)(data2buf+ 3)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+12); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_P_UINT32(UINT32 **data1, UINT32 **data2, UINT32 *data2buf){ - SSE_PART_GETDATA1DATA2_P((float**)data1, (float**)data2, (float*)data2buf); -} -static INLINE void SSE_PART_GETDATA1DATA2_S(float **data1, float **data2, float *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_S_UINT32(UINT32 **data1, UINT32 **data2, UINT32 *data2buf){ - SSE_PART_GETDATA1DATA2_S((float**)data1, (float**)data2, (float*)data2buf); -} - -// mm/m64 -> xmm -static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2XMM(float **data1, SINT32 **data2, SINT32 *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - MMX_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (SINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *((UINT32*)(data2buf+ 1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_S_MMX2XMM(float **data1, SINT32 **data2, SINT32 *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - MMX_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (SINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *data2 = data2buf; - } -} -// xmm/m64 -> mm -static INLINE void SSE_PART_GETDATA1DATA2_P_XMM2MMX(SINT32 **data1, float **data2, float *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - MMX_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (SINT32*)(&(FPU_STAT.reg[idx])); - if ((op) >= 0xc0) { - *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *((UINT32*)(data2buf+ 1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_S_XMM2MMX(SINT32 **data1, float **data2, float *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - MMX_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (SINT32*)(&(FPU_STAT.reg[idx])); - if ((op) >= 0xc0) { - *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *data2 = data2buf; - } -} - -// reg/m32 -> xmm -static INLINE void SSE_PART_GETDATA1DATA2_S_REG2XMM(float **data1, SINT32 **data2, SINT32 *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (SINT32*)CPU_REG32_B20(op); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_S_XMM2REG(SINT32 **data1, float **data2, float *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (SINT32*)CPU_REG32_B53(op); - if ((op) >= 0xc0) { - *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *data2 = data2buf; - } -} - -// mm/m64 -> mm -static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB(SINT8 **data1, SINT8 **data2, SINT8 *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - MMX_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (SINT8*)(&(FPU_STAT.reg[idx])); - if ((op) >= 0xc0) { - *data2 = (SINT8*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *((UINT32*)(data2buf+ 4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(UINT8 **data1, UINT8 **data2, UINT8 *data2buf){ - SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB((SINT8**)data1, (SINT8**)data2, (SINT8*)data2buf); -} -static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_SW(SINT16 **data1, SINT16 **data2, SINT16 *data2buf){ - SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB((SINT8**)data1, (SINT8**)data2, (SINT8*)data2buf); -} -static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_UW(UINT16 **data1, UINT16 **data2, UINT16 *data2buf){ - SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB((SINT8**)data1, (SINT8**)data2, (SINT8*)data2buf); -} -static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_SD(SINT32 **data1, SINT32 **data2, SINT32 *data2buf){ - SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB((SINT8**)data1, (SINT8**)data2, (SINT8*)data2buf); -} -static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_UD(UINT32 **data1, UINT32 **data2, UINT32 *data2buf){ - SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB((SINT8**)data1, (SINT8**)data2, (SINT8*)data2buf); -} - - -// 実際の命令群 - -void SSE_ADDPS(void) -{ - float data2buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = data1[i] + data2[i]; - } -} -void SSE_ADDSS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); - data1[0] = data1[0] + data2[0]; -} -void SSE_ANDNPS(void) -{ - UINT32 data2buf[4]; - UINT32 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_UINT32(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = ((~(data1[i])) & (data2[i])); - } -} -void SSE_ANDPS(void) -{ - UINT32 data2buf[4]; - UINT32 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_UINT32(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = ((data1[i]) & (data2[i])); - } -} -void SSE_CMPPS(void) -{ - UINT32 idx; - float data2buf[4]; - float *data1, *data2; - UINT32 *data1ui32; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - - data1ui32 = (UINT32*)data1; - - GET_MODRM_PCBYTE((idx)); - switch(idx){ - case 0: // CMPEQPS - for(i=0;i<4;i++){ - data1ui32[i] = (data1[i] == data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 1: // CMPLTPS - for(i=0;i<4;i++){ - data1ui32[i] = (data1[i] < data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 2: // CMPLEPS - for(i=0;i<4;i++){ - data1ui32[i] = (data1[i] <= data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 3: // CMPUNORDPS - for(i=0;i<4;i++){ - data1ui32[i] = (isnan(data1[i]) || isnan(data2[i]) ? 0xffffffff : 0x00000000); - } - break; - case 4: // CMPNEQPS - for(i=0;i<4;i++){ - data1ui32[i] = (data1[i] != data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 5: // CMPNLTPS - for(i=0;i<4;i++){ - data1ui32[i] = (data1[i] >= data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 6: // CMPNLEPS - for(i=0;i<4;i++){ - data1ui32[i] = (data1[i] > data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 7: // CMPORDPS - for(i=0;i<4;i++){ - data1ui32[i] = (!isnan(data1[i]) && !isnan(data2[i]) ? 0xffffffff : 0x00000000); - } - break; - } -} -void SSE_CMPSS(void) -{ - UINT32 idx; - float data2buf[4]; - float *data1, *data2; - UINT32 *data1ui32; - - SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); - - data1ui32 = (UINT32*)data1; - - GET_MODRM_PCBYTE((idx)); - switch(idx){ - case 0: // CMPEQSS - data1ui32[0] = (data1[0] == data2[0] ? 0xffffffff : 0x00000000); - break; - case 1: // CMPLTSS - data1ui32[0] = (data1[0] < data2[0] ? 0xffffffff : 0x00000000); - break; - case 2: // CMPLESS - data1ui32[0] = (data1[0] <= data2[0] ? 0xffffffff : 0x00000000); - break; - case 3: // CMPUNORDSS - data1ui32[0] = (isnan(data1[0]) || isnan(data2[0]) ? 0xffffffff : 0x00000000); - break; - case 4: // CMPNEQSS - data1ui32[0] = (data1[0] != data2[0] ? 0xffffffff : 0x00000000); - break; - case 5: // CMPNLTSS - data1ui32[0] = (data1[0] >= data2[0] ? 0xffffffff : 0x00000000); - break; - case 6: // CMPNLESS - data1ui32[0] = (data1[0] > data2[0] ? 0xffffffff : 0x00000000); - break; - case 7: // CMPORDSS - data1ui32[0] = (!isnan(data1[0]) && !isnan(data2[0]) ? 0xffffffff : 0x00000000); - break; - } -} -void SSE_COMISS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); - - if(isnan(data1[0]) || isnan(data2[0])){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | P_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; - }else if(data1[0] > data2[0]){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; - }else if(data1[0] < data2[0]){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; - }else{ // equal - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; - } -} -void SSE_CVTPI2PS(void) -{ - SINT32 data2buf[2]; - float *data1; - SINT32 *data2; - - SSE_PART_GETDATA1DATA2_P_MMX2XMM(&data1, &data2, data2buf); - - data1[0] = (float)data2[0]; - data1[1] = (float)data2[1]; -} -void SSE_CVTPS2PI(void) -{ - float data2buf[2]; - SINT32 *data1; - float *data2; - - SSE_PART_GETDATA1DATA2_P_XMM2MMX(&data1, &data2, data2buf); - - data1[0] = (SINT32)SSE_ROUND(data2[0]); - data1[1] = (SINT32)SSE_ROUND(data2[1]); -} -void SSE_CVTSI2SS(void) -{ - SINT32 data2buf[2]; - float *data1; - SINT32 *data2; - - SSE_PART_GETDATA1DATA2_S_REG2XMM(&data1, &data2, data2buf); - - data1[0] = (float)data2[0]; -} -void SSE_CVTSS2SI(void) -{ - float data2buf[2]; - SINT32 *data1; - float *data2; - - SSE_PART_GETDATA1DATA2_S_XMM2REG(&data1, &data2, data2buf); - - data1[0] = (SINT32)SSE_ROUND(data2[0]); -} -void SSE_CVTTPS2PI(void) -{ - float data2buf[2]; - SINT32 *data1; - float *data2; - - SSE_PART_GETDATA1DATA2_P_XMM2MMX(&data1, &data2, data2buf); - - data1[0] = (SINT32)(data2[0]); - data1[1] = (SINT32)(data2[1]); -} -void SSE_CVTTSS2SI(void) -{ - float data2buf[2]; - SINT32 *data1; - float *data2; - - SSE_PART_GETDATA1DATA2_S_XMM2REG(&data1, &data2, data2buf); - - data1[0] = (SINT32)(data2[0]); -} -void SSE_DIVPS(void) -{ - float data2buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = data1[i] / data2[i]; - } -} -void SSE_DIVSS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); - data1[0] = data1[0] / data2[0]; -} -void SSE_LDMXCSR(UINT32 maddr) -{ - SSE_MXCSR = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); -} -void SSE_MAXPS(void) -{ - float data2buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - if(isnan(data1[i]) || isnan(data2[i])){ - data1[i] = data2[i]; - }else{ - data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); - } - } -} -void SSE_MAXSS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); - if(isnan(data1[0]) || isnan(data2[0])){ - data1[0] = data2[0]; - }else{ - data1[0] = (data1[0] > data2[0] ? data1[0] : data2[0]); - } -} -void SSE_MINPS(void) -{ - float data2buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - if(isnan(data1[i]) || isnan(data2[i])){ - data1[i] = data2[i]; - }else{ - data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); - } - } -} -void SSE_MINSS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); - if(isnan(data1[0]) || isnan(data2[0])){ - data1[0] = data2[0]; - }else{ - data1[0] = (data1[0] < data2[0] ? data1[0] : data2[0]); - } -} -void SSE_MOVAPSmem2xmm(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG data2buf; - float *data1, *data2; - int i; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); - data2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 8); - data2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+12); - data2 = data2buf.f32; - } - for(i=0;i<4;i++){ - data1[i] = data2[i]; - } -} -void SSE_MOVAPSxmm2mem(void) -{ - UINT32 op; - UINT idx, sub; - float *data1, *data2; - int i; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - for(i=0;i<4;i++){ - data2[i] = data1[i]; - } - } else { - UINT32 madr; - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 0))); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 4, *((UINT32*)(data1+ 1))); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 8, *((UINT32*)(data1+ 2))); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+12, *((UINT32*)(data1+ 3))); - } -} -void SSE_MOVHLPS(float *data1, float *data2) -{ - data1[0] = data2[2]; - data1[1] = data2[3]; -} -void SSE_MOVHPSmem2xmm(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG data2buf; - float *data1, *data2; - int i; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - SSE_MOVLHPS(data1, data2); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - data2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - data2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); - data2 = data2buf.f32; - for(i=2;i<4;i++){ - data1[i] = data2[i]; - } - } -} -void SSE_MOVHPSxmm2mem(void) -{ - UINT32 op; - UINT idx, sub; - float *data1; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - EXCEPTION(UD_EXCEPTION, 0); - } else { - UINT32 madr; - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 2))); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 4, *((UINT32*)(data1+ 3))); - } -} -void SSE_MOVLHPS(float *data1, float *data2) -{ - data1[2] = data2[0]; - data1[3] = data2[1]; -} -void SSE_MOVLPSmem2xmm(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG data2buf; - float *data1, *data2; - int i; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - SSE_MOVHLPS(data1, data2); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); - data2 = data2buf.f32; - for(i=0;i<2;i++){ - data1[i] = data2[i]; - } - } -} -void SSE_MOVLPSxmm2mem(void) -{ - UINT32 op; - UINT idx, sub; - float *data1; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - EXCEPTION(UD_EXCEPTION, 0); - } else { - UINT32 madr; - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 0))); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 4, *((UINT32*)(data1+ 1))); - } -} -void SSE_MOVMSKPS(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 *data1; - UINT32 *data2; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = CPU_REG32_B53(op); - if ((op) >= 0xc0) { - data2 = (UINT32*)(&(FPU_STAT.xmm_reg[sub])); - } else { - EXCEPTION(UD_EXCEPTION, 0); - } - *data1 = ((data2[0] >> 31) & 0x1)| - ((data2[1] >> 30) & 0x2)| - ((data2[2] >> 29) & 0x4)| - ((data2[3] >> 28) & 0x8); -} -void SSE_MOVSSmem2xmm(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG data2buf; - float *data1, *data2; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - data2 = data2buf.f32; - } - data1[0] = data2[0]; - *(UINT32*)(data1+1) = *(UINT32*)(data1+2) = *(UINT32*)(data1+3) = 0; -} -void SSE_MOVSSxmm2mem(void) -{ - UINT32 op; - UINT idx, sub; - float *data1, *data2; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - data2[0] = data1[0]; - } else { - UINT32 madr; - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 0))); - } -} -void SSE_MOVUPSmem2xmm(void) -{ - SSE_MOVAPSmem2xmm(); // エミュレーションではアライメント制限がないのでMOVAPSと同じ -} -void SSE_MOVUPSxmm2mem(void) -{ - SSE_MOVAPSxmm2mem(); // エミュレーションではアライメント制限がないのでMOVAPSと同じ -} -void SSE_MULPS(void) -{ - float data2buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = data1[i] * data2[i]; - } -} -void SSE_MULSS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); - data1[0] = data1[0] * data2[0]; -} -void SSE_ORPS(void) -{ - UINT32 data2buf[4]; - UINT32 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_UINT32(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = ((data1[i]) | (data2[i])); - } -} -void SSE_RCPPS(void) -{ - float data2buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = 1.0f / data2[i]; - } -} -void SSE_RCPSS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); - data1[0] = 1.0f / data2[0]; -} -void SSE_RSQRTPS(void) -{ - float data2buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = (float)(1.0f / sqrt(data2[i])); - } -} -void SSE_RSQRTSS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); - data1[0] = (float)(1.0f / sqrt(data2[0])); -} -void SSE_SHUFPS(void) -{ - UINT32 imm8; - float data2buf[4]; - float data1buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - - GET_MODRM_PCBYTE((imm8)); - - for(i=0;i<2;i++){ - data1buf[i] = data1[imm8 & 0x3]; - imm8 = (imm8 >> 2); - } - for(i=2;i<4;i++){ - data1buf[i] = data2[imm8 & 0x3]; - imm8 = (imm8 >> 2); - } - for(i=0;i<4;i++){ - data1[i] = data1buf[i]; - } -} -void SSE_SQRTPS(void) -{ - float data2buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = (float)sqrt(data2[i]); - } -} -void SSE_SQRTSS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); - data1[0] = (float)sqrt(data2[0]); -} -void SSE_STMXCSR(UINT32 maddr) -{ - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, maddr, SSE_MXCSR); -} -void SSE_SUBPS(void) -{ - float data2buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = data1[i] - data2[i]; - } -} -void SSE_SUBSS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); - data1[0] = data1[0] - data2[0]; -} -void SSE_UCOMISS(void) -{ - SSE_COMISS(); // XXX: とりあえず例外は考えないのでCOMISSと同じ -} -void SSE_UNPCKHPS(void) -{ - float data1buf[4]; - float data2buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1buf[i] = data1[i]; - } - data1[0] = data1buf[2]; - data1[1] = data2[2]; - data1[2] = data1buf[3]; - data1[3] = data2[3]; -} -void SSE_UNPCKLPS(void) -{ - float data1buf[4]; - float data2buf[4]; - float *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1buf[i] = data1[i]; - } - data1[0] = data1buf[0]; - data1[1] = data2[0]; - data1[2] = data1buf[1]; - data1[3] = data2[1]; -} -void SSE_XORPS(void) -{ - UINT32 data2buf[4]; - UINT32 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_UINT32(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = ((data1[i]) ^ (data2[i])); - } -} - -void SSE_PAVGB(void) -{ - UINT8 data2buf[8]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(&data1, &data2, data2buf); - for(i=0;i<8;i++){ - data1[i] = (UINT8)(((UINT16)data1[i] + (UINT16)data2[i] + 1) / 2); - } -} -void SSE_PAVGW(void) -{ - UINT16 data2buf[4]; - UINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_MMX2MMX_UW(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = (UINT16)(((UINT32)data1[i] + (UINT32)data2[i] + 1) / 2); - } -} -void SSE_PEXTRW(void) -{ - UINT32 imm8; - UINT32 op; - UINT idx, sub; - UINT32 *data1; - UINT16 *data2; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (UINT32*)CPU_REG32_B53(op); - if ((op) >= 0xc0) { - data2 = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - EXCEPTION(UD_EXCEPTION, 0); - } - GET_MODRM_PCBYTE((imm8)); - *data1 = (UINT32)data2[imm8 & 0x3]; -} -void SSE_PINSRW(void) -{ - UINT32 imm8; - UINT32 op; - UINT idx, sub; - UINT16 *data1; - UINT16 data2; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (UINT16*)(&(FPU_STAT.reg[idx])); - if ((op) >= 0xc0) { - data2 = (UINT16)((*CPU_REG32_B20(op)) & 0xffff); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - data2 = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, maddr+ 0); - } - GET_MODRM_PCBYTE((imm8)); - data1[imm8 & 0x3] = data2; -} -void SSE_PMAXSW(void) -{ - SINT16 data2buf[4]; - SINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_MMX2MMX_SW(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); - } -} -void SSE_PMAXUB(void) -{ - UINT8 data2buf[8]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(&data1, &data2, data2buf); - for(i=0;i<8;i++){ - data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); - } -} -void SSE_PMINSW(void) -{ - SINT16 data2buf[4]; - SINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_MMX2MMX_SW(&data1, &data2, data2buf); - for(i=0;i<4;i++){ - data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); - } -} -void SSE_PMINUB(void) -{ - UINT8 data2buf[8]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(&data1, &data2, data2buf); - for(i=0;i<8;i++){ - data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); - } -} -void SSE_PMOVMSKB(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 *data1; - UINT8 *data2; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (UINT32*)CPU_REG32_B53(op); - if ((op) >= 0xc0) { - data2 = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - EXCEPTION(UD_EXCEPTION, 0); - } - *data1 = ((data2[0] >> 7) & 0x1 )| - ((data2[1] >> 6) & 0x2 )| - ((data2[2] >> 5) & 0x4 )| - ((data2[3] >> 4) & 0x8 )| - ((data2[4] >> 3) & 0x10)| - ((data2[5] >> 2) & 0x20)| - ((data2[6] >> 1) & 0x40)| - ((data2[7] >> 0) & 0x80); -} -void SSE_PMULHUW(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG data2buf; - UINT16 *data1, *data2; - int i; - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (UINT16*)(&(FPU_STAT.reg[idx])); - if ((op) >= 0xc0) { - data2 = (UINT16*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); - data2 = data2buf.w; - } - for(i=0;i<4;i++){ - data1[i] = (UINT16)((((UINT32)data2[i] * (UINT32)data1[i]) >> 16) & 0xffff); - } -} -void SSE_PSADBW(void) -{ - SINT16 temp1; - UINT16 temp; - UINT8 data2buf[8]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(&data1, &data2, data2buf); - temp = 0; - for(i=0;i<8;i++){ - temp1 = (SINT16)data2[i] - (SINT16)data1[i]; - temp += (UINT16)(temp1 < 0 ? -temp1 : temp1); - } - *((UINT16*)data2 + 0) = temp; - *((UINT16*)data2 + 1) = 0; - *((UINT16*)data2 + 2) = 0; - *((UINT16*)data2 + 3) = 0; -} -void SSE_PSHUFW(void) -{ - UINT32 imm8; - UINT16 data2buf[4]; - UINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_MMX2MMX_UW(&data1, &data2, data2buf); - GET_MODRM_PCBYTE((imm8)); - for(i=0;i<4;i++){ - data1[i] = data2[imm8 & 0x3]; - imm8 = imm8 >> 2; - } -} - -void SSE_MASKMOVQ(void) -{ - UINT8 data2buf[8]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(&data1, &data2, data2buf); - for(i=0;i<8;i++){ - if (!CPU_INST_AS32) { - if(data2[i] & 0x80){ - cpu_vmemorywrite(CPU_DS_INDEX, CPU_DI, data1[i]); - } - CPU_DI += 1; - } else { - if(data2[i] & 0x80){ - cpu_vmemorywrite(CPU_DS_INDEX, CPU_EDI, data1[i]); - } - CPU_EDI += 1; - } - } - // 戻す - if (!CPU_INST_AS32) { - CPU_DI -= 8; - } else { - CPU_EDI -= 8; - } -} -void SSE_MOVNTPS(void) -{ - UINT32 op; - UINT idx, sub; - float *data1; - - // 00001111:00101011 mod xmmreg r/m - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - // XXX: ここはどう扱う? - EXCEPTION(UD_EXCEPTION, 0); - //data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - //for(i=0;i<4;i++){ - // data2[i] = data1[i]; - //} - } else { - UINT32 madr; - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 0))); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 4, *((UINT32*)(data1+ 1))); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 8, *((UINT32*)(data1+ 2))); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+12, *((UINT32*)(data1+ 3))); - } -} -void SSE_MOVNTQ(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 *data1; - - // 00001111:00101011 mod xmmreg r/m - - SSE_check_NM_EXCEPTION(); - SSE_setTag(); - MMX_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (UINT32*)(&(FPU_STAT.reg[idx])); - if ((op) >= 0xc0) { - // XXX: ここはどう扱う? - EXCEPTION(UD_EXCEPTION, 0); - //data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - //for(i=0;i<4;i++){ - // data2[i] = data1[i]; - //} - } else { - UINT32 madr; - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 0))); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 4, *((UINT32*)(data1+ 1))); - } -} -void SSE_PREFETCHTx(void) -{ - UINT32 op; - UINT idx, sub; - - //SSE_check_NM_EXCEPTION(); - //SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - // XXX: ここはどう扱う? - //EXCEPTION(UD_EXCEPTION, 0); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - switch(idx){ - case 3: - // PREFETCH2 - break; - case 2: - // PREFETCH1 - break; - case 1: - // PREFETCH0 - break; - case 0: - // PREFETCHNTA - break; - default: - //EXCEPTION(UD_EXCEPTION, 0); - break; - } - // XXX: 何もしない - } -} -void SSE_NOPPREFETCH(void) -{ - UINT32 op; - UINT idx, sub; - - //SSE_check_NM_EXCEPTION(); - //SSE_setTag(); - CPU_SSEWORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - // XXX: ここはどう扱う? - //EXCEPTION(UD_EXCEPTION, 0); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - // XXX: 何もしない - } -} -void SSE_SFENCE(void) -{ - // Nothing to do -} -void SSE_LFENCE(void) -{ - // Nothing to do -} -void SSE_MFENCE(void) -{ - // Nothing to do -} -void SSE_CLFLUSH(UINT32 op) -{ - UINT idx, sub; - - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - // XXX: ここはどう扱う? - //EXCEPTION(UD_EXCEPTION, 0); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - // XXX: 何もしない - } -} - - -#else - -/* - * SSE interface - */ - -void SSE_ADDPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_ADDSS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_ANDNPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_ANDPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_CMPPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_CMPSS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_COMISS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_CVTPI2PS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_CVTPS2PI(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_CVTSI2SS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_CVTSS2SI(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_CVTTPS2PI(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_CVTTSS2SI(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_DIVPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_DIVSS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_LDMXCSR(UINT32 maddr) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MAXPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MAXSS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MINPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MINSS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVAPSmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVAPSxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVHLPS(float *data1, float *data2) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVHPSmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVHPSxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVLHPS(float *data1, float *data2) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVLPSmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVLPSxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVMSKPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVSSmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVSSxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVUPSmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVUPSxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MULPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MULSS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_ORPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_RCPPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_RCPSS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_RSQRTPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_RSQRTSS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_SHUFPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_SQRTPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_SQRTSS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_STMXCSR(UINT32 maddr) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_SUBPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_SUBSS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_UCOMISS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_UNPCKHPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_UNPCKLPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_XORPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void SSE_PAVGB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PAVGW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PEXTRW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PINSRW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PMAXSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PMAXUB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PMINSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PMINUB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PMOVMSKB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PMULHUW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PSADBW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PSHUFW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void SSE_MASKMOVQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVNTPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MOVNTQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_PREFETCHTx(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_NOPPREFETCH(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_SFENCE(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_LFENCE(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_MFENCE(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE_CLFLUSH(UINT32 op) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - - +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include + +#include +#include + +#if defined(_WIN32) && !defined(__LIBRETRO__) +#define isnan(x) (_isnan(x)) +#endif + +#include +#include "ia32/ia32.mcr" + +#include "ia32/instructions/sse/sse.h" + +#if defined(USE_SSE) && defined(USE_FPU) + +#define CPU_SSEWORKCLOCK CPU_WORKCLOCK(2) + +static INLINE void +SSE_check_NM_EXCEPTION(){ + // SSEなしならUD(無効オペコード例外)を発生させる + if(!(i386cpuid.cpu_feature & CPU_FEATURE_SSE) && !(i386cpuid.cpu_feature_ex & CPU_FEATURE_EX_E3DNOW)){ // XXX: SSE命令にEnhanced 3DNow!命令が一部あるので例外的に認める + EXCEPTION(UD_EXCEPTION, 0); + } + // エミュレーションならUD(無効オペコード例外)を発生させる + if(CPU_CR0 & CPU_CR0_EM){ + EXCEPTION(UD_EXCEPTION, 0); + } + // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる + if (CPU_CR0 & CPU_CR0_TS) { + EXCEPTION(NM_EXCEPTION, 0); + } +} + +static INLINE void +SSE_setTag(void) +{ +// int i; +// +// if(!FPU_STAT.mmxenable){ +// FPU_STAT.mmxenable = 1; +// //FPU_CTRLWORD = 0x27F; +// for (i = 0; i < FPU_REG_NUM; i++) { +// FPU_STAT.tag[i] = TAG_Valid; +//#ifdef SUPPORT_FPU_DOSBOX2 +// FPU_STAT.int_regvalid[i] = 0; +//#endif +// FPU_STAT.reg[i].ul.ext = 0xffff; +// } +// } +// FPU_STAT_TOP = 0; +// FPU_STATUSWORD &= ~0x3800; +// FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; +} + +// mmx.cのものと同じ +static INLINE void +MMX_setTag(void) +{ + int i; + + if(!FPU_STAT.mmxenable){ + FPU_STAT.mmxenable = 1; + //FPU_CTRLWORD = 0x27F; + for (i = 0; i < FPU_REG_NUM; i++) { + FPU_STAT.tag[i] = TAG_Valid; +#ifdef SUPPORT_FPU_DOSBOX2 + FPU_STAT.int_regvalid[i] = 0; +#endif + FPU_STAT.reg[i].ul.ext = 0xffff; + } + } + FPU_STAT_TOP = 0; + FPU_STATUSWORD &= ~0x3800; + FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; +} + +float SSE_ROUND(float val){ + float floorval; + int rndbit = (SSE_MXCSR >> 13) & 0x3; + switch(rndbit){ + case 0: + floorval = (float)floor(val); + if (val - floorval > 0.5f){ + return (floorval + 1); // 切り上げ + }else if (val - floorval < 0.5f){ + return (floorval); // 切り捨て + }else{ + if(floor(floorval / 2) == floorval/2){ + return (floorval); // 偶数 + }else{ + return (floorval+1); // 奇数 + } + } + break; + case 1: + return (float)floor(val); + case 2: + return (float)ceil(val); + case 3: + if(val < 0){ + return (float)ceil(val); // ゼロ方向への切り捨て + }else{ + return (float)floor(val); // ゼロ方向への切り捨て + } + break; + default: + return val; + } +} + +/* + * SSE interface + */ + +// コードが長くなるのでやや強引に共通化 +// xmm/m128 -> xmm +static INLINE void SSE_PART_GETDATA1DATA2_P(float **data1, float **data2, float *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *((UINT32*)(data2buf+ 1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); + *((UINT32*)(data2buf+ 2)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 8); + *((UINT32*)(data2buf+ 3)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+12); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_P_UINT32(UINT32 **data1, UINT32 **data2, UINT32 *data2buf){ + SSE_PART_GETDATA1DATA2_P((float**)data1, (float**)data2, (float*)data2buf); +} +static INLINE void SSE_PART_GETDATA1DATA2_S(float **data1, float **data2, float *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_S_UINT32(UINT32 **data1, UINT32 **data2, UINT32 *data2buf){ + SSE_PART_GETDATA1DATA2_S((float**)data1, (float**)data2, (float*)data2buf); +} + +// mm/m64 -> xmm +static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2XMM(float **data1, SINT32 **data2, SINT32 *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + MMX_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (SINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *((UINT32*)(data2buf+ 1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_S_MMX2XMM(float **data1, SINT32 **data2, SINT32 *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + MMX_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (SINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *data2 = data2buf; + } +} +// xmm/m64 -> mm +static INLINE void SSE_PART_GETDATA1DATA2_P_XMM2MMX(SINT32 **data1, float **data2, float *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + MMX_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (SINT32*)(&(FPU_STAT.reg[idx])); + if ((op) >= 0xc0) { + *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *((UINT32*)(data2buf+ 1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_S_XMM2MMX(SINT32 **data1, float **data2, float *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + MMX_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (SINT32*)(&(FPU_STAT.reg[idx])); + if ((op) >= 0xc0) { + *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *data2 = data2buf; + } +} + +// reg/m32 -> xmm +static INLINE void SSE_PART_GETDATA1DATA2_S_REG2XMM(float **data1, SINT32 **data2, SINT32 *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (SINT32*)CPU_REG32_B20(op); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_S_XMM2REG(SINT32 **data1, float **data2, float *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (SINT32*)CPU_REG32_B53(op); + if ((op) >= 0xc0) { + *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *data2 = data2buf; + } +} + +// mm/m64 -> mm +static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB(SINT8 **data1, SINT8 **data2, SINT8 *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + MMX_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (SINT8*)(&(FPU_STAT.reg[idx])); + if ((op) >= 0xc0) { + *data2 = (SINT8*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *((UINT32*)(data2buf+ 4)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(UINT8 **data1, UINT8 **data2, UINT8 *data2buf){ + SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB((SINT8**)data1, (SINT8**)data2, (SINT8*)data2buf); +} +static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_SW(SINT16 **data1, SINT16 **data2, SINT16 *data2buf){ + SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB((SINT8**)data1, (SINT8**)data2, (SINT8*)data2buf); +} +static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_UW(UINT16 **data1, UINT16 **data2, UINT16 *data2buf){ + SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB((SINT8**)data1, (SINT8**)data2, (SINT8*)data2buf); +} +static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_SD(SINT32 **data1, SINT32 **data2, SINT32 *data2buf){ + SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB((SINT8**)data1, (SINT8**)data2, (SINT8*)data2buf); +} +static INLINE void SSE_PART_GETDATA1DATA2_P_MMX2MMX_UD(UINT32 **data1, UINT32 **data2, UINT32 *data2buf){ + SSE_PART_GETDATA1DATA2_P_MMX2MMX_SB((SINT8**)data1, (SINT8**)data2, (SINT8*)data2buf); +} + + +// 実際の命令群 + +void SSE_ADDPS(void) +{ + float data2buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = data1[i] + data2[i]; + } +} +void SSE_ADDSS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); + data1[0] = data1[0] + data2[0]; +} +void SSE_ANDNPS(void) +{ + UINT32 data2buf[4]; + UINT32 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_UINT32(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = ((~(data1[i])) & (data2[i])); + } +} +void SSE_ANDPS(void) +{ + UINT32 data2buf[4]; + UINT32 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_UINT32(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = ((data1[i]) & (data2[i])); + } +} +void SSE_CMPPS(void) +{ + UINT32 idx; + float data2buf[4]; + float *data1, *data2; + UINT32 *data1ui32; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + + data1ui32 = (UINT32*)data1; + + GET_MODRM_PCBYTE((idx)); + switch(idx){ + case 0: // CMPEQPS + for(i=0;i<4;i++){ + data1ui32[i] = (data1[i] == data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 1: // CMPLTPS + for(i=0;i<4;i++){ + data1ui32[i] = (data1[i] < data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 2: // CMPLEPS + for(i=0;i<4;i++){ + data1ui32[i] = (data1[i] <= data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 3: // CMPUNORDPS + for(i=0;i<4;i++){ + data1ui32[i] = (isnan(data1[i]) || isnan(data2[i]) ? 0xffffffff : 0x00000000); + } + break; + case 4: // CMPNEQPS + for(i=0;i<4;i++){ + data1ui32[i] = (data1[i] != data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 5: // CMPNLTPS + for(i=0;i<4;i++){ + data1ui32[i] = (data1[i] >= data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 6: // CMPNLEPS + for(i=0;i<4;i++){ + data1ui32[i] = (data1[i] > data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 7: // CMPORDPS + for(i=0;i<4;i++){ + data1ui32[i] = (!isnan(data1[i]) && !isnan(data2[i]) ? 0xffffffff : 0x00000000); + } + break; + } +} +void SSE_CMPSS(void) +{ + UINT32 idx; + float data2buf[4]; + float *data1, *data2; + UINT32 *data1ui32; + + SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); + + data1ui32 = (UINT32*)data1; + + GET_MODRM_PCBYTE((idx)); + switch(idx){ + case 0: // CMPEQSS + data1ui32[0] = (data1[0] == data2[0] ? 0xffffffff : 0x00000000); + break; + case 1: // CMPLTSS + data1ui32[0] = (data1[0] < data2[0] ? 0xffffffff : 0x00000000); + break; + case 2: // CMPLESS + data1ui32[0] = (data1[0] <= data2[0] ? 0xffffffff : 0x00000000); + break; + case 3: // CMPUNORDSS + data1ui32[0] = (isnan(data1[0]) || isnan(data2[0]) ? 0xffffffff : 0x00000000); + break; + case 4: // CMPNEQSS + data1ui32[0] = (data1[0] != data2[0] ? 0xffffffff : 0x00000000); + break; + case 5: // CMPNLTSS + data1ui32[0] = (data1[0] >= data2[0] ? 0xffffffff : 0x00000000); + break; + case 6: // CMPNLESS + data1ui32[0] = (data1[0] > data2[0] ? 0xffffffff : 0x00000000); + break; + case 7: // CMPORDSS + data1ui32[0] = (!isnan(data1[0]) && !isnan(data2[0]) ? 0xffffffff : 0x00000000); + break; + } +} +void SSE_COMISS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); + + if(isnan(data1[0]) || isnan(data2[0])){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | P_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; + }else if(data1[0] > data2[0]){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; + }else if(data1[0] < data2[0]){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; + }else{ // equal + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; + } +} +void SSE_CVTPI2PS(void) +{ + SINT32 data2buf[2]; + float *data1; + SINT32 *data2; + + SSE_PART_GETDATA1DATA2_P_MMX2XMM(&data1, &data2, data2buf); + + data1[0] = (float)data2[0]; + data1[1] = (float)data2[1]; +} +void SSE_CVTPS2PI(void) +{ + float data2buf[2]; + SINT32 *data1; + float *data2; + + SSE_PART_GETDATA1DATA2_P_XMM2MMX(&data1, &data2, data2buf); + + data1[0] = (SINT32)SSE_ROUND(data2[0]); + data1[1] = (SINT32)SSE_ROUND(data2[1]); +} +void SSE_CVTSI2SS(void) +{ + SINT32 data2buf[2]; + float *data1; + SINT32 *data2; + + SSE_PART_GETDATA1DATA2_S_REG2XMM(&data1, &data2, data2buf); + + data1[0] = (float)data2[0]; +} +void SSE_CVTSS2SI(void) +{ + float data2buf[2]; + SINT32 *data1; + float *data2; + + SSE_PART_GETDATA1DATA2_S_XMM2REG(&data1, &data2, data2buf); + + data1[0] = (SINT32)SSE_ROUND(data2[0]); +} +void SSE_CVTTPS2PI(void) +{ + float data2buf[2]; + SINT32 *data1; + float *data2; + + SSE_PART_GETDATA1DATA2_P_XMM2MMX(&data1, &data2, data2buf); + + data1[0] = (SINT32)(data2[0]); + data1[1] = (SINT32)(data2[1]); +} +void SSE_CVTTSS2SI(void) +{ + float data2buf[2]; + SINT32 *data1; + float *data2; + + SSE_PART_GETDATA1DATA2_S_XMM2REG(&data1, &data2, data2buf); + + data1[0] = (SINT32)(data2[0]); +} +void SSE_DIVPS(void) +{ + float data2buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = data1[i] / data2[i]; + } +} +void SSE_DIVSS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); + data1[0] = data1[0] / data2[0]; +} +void SSE_LDMXCSR(UINT32 maddr) +{ + SSE_MXCSR = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); +} +void SSE_MAXPS(void) +{ + float data2buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + if(isnan(data1[i]) || isnan(data2[i])){ + data1[i] = data2[i]; + }else{ + data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); + } + } +} +void SSE_MAXSS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); + if(isnan(data1[0]) || isnan(data2[0])){ + data1[0] = data2[0]; + }else{ + data1[0] = (data1[0] > data2[0] ? data1[0] : data2[0]); + } +} +void SSE_MINPS(void) +{ + float data2buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + if(isnan(data1[i]) || isnan(data2[i])){ + data1[i] = data2[i]; + }else{ + data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); + } + } +} +void SSE_MINSS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); + if(isnan(data1[0]) || isnan(data2[0])){ + data1[0] = data2[0]; + }else{ + data1[0] = (data1[0] < data2[0] ? data1[0] : data2[0]); + } +} +void SSE_MOVAPSmem2xmm(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG data2buf; + float *data1, *data2; + int i; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); + data2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 8); + data2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+12); + data2 = data2buf.f32; + } + for(i=0;i<4;i++){ + data1[i] = data2[i]; + } +} +void SSE_MOVAPSxmm2mem(void) +{ + UINT32 op; + UINT idx, sub; + float *data1, *data2; + int i; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + for(i=0;i<4;i++){ + data2[i] = data1[i]; + } + } else { + UINT32 madr; + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 0))); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 4, *((UINT32*)(data1+ 1))); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 8, *((UINT32*)(data1+ 2))); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+12, *((UINT32*)(data1+ 3))); + } +} +void SSE_MOVHLPS(float *data1, float *data2) +{ + data1[0] = data2[2]; + data1[1] = data2[3]; +} +void SSE_MOVHPSmem2xmm(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG data2buf; + float *data1, *data2; + int i; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + SSE_MOVLHPS(data1, data2); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + data2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + data2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); + data2 = data2buf.f32; + for(i=2;i<4;i++){ + data1[i] = data2[i]; + } + } +} +void SSE_MOVHPSxmm2mem(void) +{ + UINT32 op; + UINT idx, sub; + float *data1; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + EXCEPTION(UD_EXCEPTION, 0); + } else { + UINT32 madr; + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 2))); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 4, *((UINT32*)(data1+ 3))); + } +} +void SSE_MOVLHPS(float *data1, float *data2) +{ + data1[2] = data2[0]; + data1[3] = data2[1]; +} +void SSE_MOVLPSmem2xmm(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG data2buf; + float *data1, *data2; + int i; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + SSE_MOVHLPS(data1, data2); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); + data2 = data2buf.f32; + for(i=0;i<2;i++){ + data1[i] = data2[i]; + } + } +} +void SSE_MOVLPSxmm2mem(void) +{ + UINT32 op; + UINT idx, sub; + float *data1; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + EXCEPTION(UD_EXCEPTION, 0); + } else { + UINT32 madr; + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 0))); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 4, *((UINT32*)(data1+ 1))); + } +} +void SSE_MOVMSKPS(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 *data1; + UINT32 *data2; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = CPU_REG32_B53(op); + if ((op) >= 0xc0) { + data2 = (UINT32*)(&(FPU_STAT.xmm_reg[sub])); + } else { + EXCEPTION(UD_EXCEPTION, 0); + } + *data1 = ((data2[0] >> 31) & 0x1)| + ((data2[1] >> 30) & 0x2)| + ((data2[2] >> 29) & 0x4)| + ((data2[3] >> 28) & 0x8); +} +void SSE_MOVSSmem2xmm(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG data2buf; + float *data1, *data2; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + data2 = data2buf.f32; + } + data1[0] = data2[0]; + *(UINT32*)(data1+1) = *(UINT32*)(data1+2) = *(UINT32*)(data1+3) = 0; +} +void SSE_MOVSSxmm2mem(void) +{ + UINT32 op; + UINT idx, sub; + float *data1, *data2; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + data2[0] = data1[0]; + } else { + UINT32 madr; + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 0))); + } +} +void SSE_MOVUPSmem2xmm(void) +{ + SSE_MOVAPSmem2xmm(); // エミュレーションではアライメント制限がないのでMOVAPSと同じ +} +void SSE_MOVUPSxmm2mem(void) +{ + SSE_MOVAPSxmm2mem(); // エミュレーションではアライメント制限がないのでMOVAPSと同じ +} +void SSE_MULPS(void) +{ + float data2buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = data1[i] * data2[i]; + } +} +void SSE_MULSS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); + data1[0] = data1[0] * data2[0]; +} +void SSE_ORPS(void) +{ + UINT32 data2buf[4]; + UINT32 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_UINT32(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = ((data1[i]) | (data2[i])); + } +} +void SSE_RCPPS(void) +{ + float data2buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = 1.0f / data2[i]; + } +} +void SSE_RCPSS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); + data1[0] = 1.0f / data2[0]; +} +void SSE_RSQRTPS(void) +{ + float data2buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = (float)(1.0f / sqrt(data2[i])); + } +} +void SSE_RSQRTSS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); + data1[0] = (float)(1.0f / sqrt(data2[0])); +} +void SSE_SHUFPS(void) +{ + UINT32 imm8; + float data2buf[4]; + float data1buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + + GET_MODRM_PCBYTE((imm8)); + + for(i=0;i<2;i++){ + data1buf[i] = data1[imm8 & 0x3]; + imm8 = (imm8 >> 2); + } + for(i=2;i<4;i++){ + data1buf[i] = data2[imm8 & 0x3]; + imm8 = (imm8 >> 2); + } + for(i=0;i<4;i++){ + data1[i] = data1buf[i]; + } +} +void SSE_SQRTPS(void) +{ + float data2buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = (float)sqrt(data2[i]); + } +} +void SSE_SQRTSS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); + data1[0] = (float)sqrt(data2[0]); +} +void SSE_STMXCSR(UINT32 maddr) +{ + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, maddr, SSE_MXCSR); +} +void SSE_SUBPS(void) +{ + float data2buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = data1[i] - data2[i]; + } +} +void SSE_SUBSS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_S(&data1, &data2, data2buf); + data1[0] = data1[0] - data2[0]; +} +void SSE_UCOMISS(void) +{ + SSE_COMISS(); // XXX: とりあえず例外は考えないのでCOMISSと同じ +} +void SSE_UNPCKHPS(void) +{ + float data1buf[4]; + float data2buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1buf[i] = data1[i]; + } + data1[0] = data1buf[2]; + data1[1] = data2[2]; + data1[2] = data1buf[3]; + data1[3] = data2[3]; +} +void SSE_UNPCKLPS(void) +{ + float data1buf[4]; + float data2buf[4]; + float *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1buf[i] = data1[i]; + } + data1[0] = data1buf[0]; + data1[1] = data2[0]; + data1[2] = data1buf[1]; + data1[3] = data2[1]; +} +void SSE_XORPS(void) +{ + UINT32 data2buf[4]; + UINT32 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_UINT32(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = ((data1[i]) ^ (data2[i])); + } +} + +void SSE_PAVGB(void) +{ + UINT8 data2buf[8]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(&data1, &data2, data2buf); + for(i=0;i<8;i++){ + data1[i] = (UINT8)(((UINT16)data1[i] + (UINT16)data2[i] + 1) / 2); + } +} +void SSE_PAVGW(void) +{ + UINT16 data2buf[4]; + UINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_MMX2MMX_UW(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = (UINT16)(((UINT32)data1[i] + (UINT32)data2[i] + 1) / 2); + } +} +void SSE_PEXTRW(void) +{ + UINT32 imm8; + UINT32 op; + UINT idx, sub; + UINT32 *data1; + UINT16 *data2; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (UINT32*)CPU_REG32_B53(op); + if ((op) >= 0xc0) { + data2 = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + EXCEPTION(UD_EXCEPTION, 0); + } + GET_MODRM_PCBYTE((imm8)); + *data1 = (UINT32)data2[imm8 & 0x3]; +} +void SSE_PINSRW(void) +{ + UINT32 imm8; + UINT32 op; + UINT idx, sub; + UINT16 *data1; + UINT16 data2; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (UINT16*)(&(FPU_STAT.reg[idx])); + if ((op) >= 0xc0) { + data2 = (UINT16)((*CPU_REG32_B20(op)) & 0xffff); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + data2 = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, maddr+ 0); + } + GET_MODRM_PCBYTE((imm8)); + data1[imm8 & 0x3] = data2; +} +void SSE_PMAXSW(void) +{ + SINT16 data2buf[4]; + SINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_MMX2MMX_SW(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); + } +} +void SSE_PMAXUB(void) +{ + UINT8 data2buf[8]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(&data1, &data2, data2buf); + for(i=0;i<8;i++){ + data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); + } +} +void SSE_PMINSW(void) +{ + SINT16 data2buf[4]; + SINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_MMX2MMX_SW(&data1, &data2, data2buf); + for(i=0;i<4;i++){ + data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); + } +} +void SSE_PMINUB(void) +{ + UINT8 data2buf[8]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(&data1, &data2, data2buf); + for(i=0;i<8;i++){ + data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); + } +} +void SSE_PMOVMSKB(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 *data1; + UINT8 *data2; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (UINT32*)CPU_REG32_B53(op); + if ((op) >= 0xc0) { + data2 = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + EXCEPTION(UD_EXCEPTION, 0); + } + *data1 = ((data2[0] >> 7) & 0x1 )| + ((data2[1] >> 6) & 0x2 )| + ((data2[2] >> 5) & 0x4 )| + ((data2[3] >> 4) & 0x8 )| + ((data2[4] >> 3) & 0x10)| + ((data2[5] >> 2) & 0x20)| + ((data2[6] >> 1) & 0x40)| + ((data2[7] >> 0) & 0x80); +} +void SSE_PMULHUW(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG data2buf; + UINT16 *data1, *data2; + int i; + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (UINT16*)(&(FPU_STAT.reg[idx])); + if ((op) >= 0xc0) { + data2 = (UINT16*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+4); + data2 = data2buf.w; + } + for(i=0;i<4;i++){ + data1[i] = (UINT16)((((UINT32)data2[i] * (UINT32)data1[i]) >> 16) & 0xffff); + } +} +void SSE_PSADBW(void) +{ + SINT16 temp1; + UINT16 temp; + UINT8 data2buf[8]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(&data1, &data2, data2buf); + temp = 0; + for(i=0;i<8;i++){ + temp1 = (SINT16)data2[i] - (SINT16)data1[i]; + temp += (UINT16)(temp1 < 0 ? -temp1 : temp1); + } + *((UINT16*)data2 + 0) = temp; + *((UINT16*)data2 + 1) = 0; + *((UINT16*)data2 + 2) = 0; + *((UINT16*)data2 + 3) = 0; +} +void SSE_PSHUFW(void) +{ + UINT32 imm8; + UINT16 data2buf[4]; + UINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_MMX2MMX_UW(&data1, &data2, data2buf); + GET_MODRM_PCBYTE((imm8)); + for(i=0;i<4;i++){ + data1[i] = data2[imm8 & 0x3]; + imm8 = imm8 >> 2; + } +} + +void SSE_MASKMOVQ(void) +{ + UINT8 data2buf[8]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_P_MMX2MMX_UB(&data1, &data2, data2buf); + for(i=0;i<8;i++){ + if (!CPU_INST_AS32) { + if(data2[i] & 0x80){ + cpu_vmemorywrite(CPU_DS_INDEX, CPU_DI, data1[i]); + } + CPU_DI += 1; + } else { + if(data2[i] & 0x80){ + cpu_vmemorywrite(CPU_DS_INDEX, CPU_EDI, data1[i]); + } + CPU_EDI += 1; + } + } + // 戻す + if (!CPU_INST_AS32) { + CPU_DI -= 8; + } else { + CPU_EDI -= 8; + } +} +void SSE_MOVNTPS(void) +{ + UINT32 op; + UINT idx, sub; + float *data1; + + // 00001111:00101011 mod xmmreg r/m + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (float*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + // XXX: ここはどう扱う? + EXCEPTION(UD_EXCEPTION, 0); + //data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + //for(i=0;i<4;i++){ + // data2[i] = data1[i]; + //} + } else { + UINT32 madr; + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 0))); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 4, *((UINT32*)(data1+ 1))); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 8, *((UINT32*)(data1+ 2))); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+12, *((UINT32*)(data1+ 3))); + } +} +void SSE_MOVNTQ(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 *data1; + + // 00001111:00101011 mod xmmreg r/m + + SSE_check_NM_EXCEPTION(); + SSE_setTag(); + MMX_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (UINT32*)(&(FPU_STAT.reg[idx])); + if ((op) >= 0xc0) { + // XXX: ここはどう扱う? + EXCEPTION(UD_EXCEPTION, 0); + //data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + //for(i=0;i<4;i++){ + // data2[i] = data1[i]; + //} + } else { + UINT32 madr; + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT32*)(data1+ 0))); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr+ 4, *((UINT32*)(data1+ 1))); + } +} +void SSE_PREFETCHTx(void) +{ + UINT32 op; + UINT idx, sub; + + //SSE_check_NM_EXCEPTION(); + //SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + // XXX: ここはどう扱う? + //EXCEPTION(UD_EXCEPTION, 0); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + switch(idx){ + case 3: + // PREFETCH2 + break; + case 2: + // PREFETCH1 + break; + case 1: + // PREFETCH0 + break; + case 0: + // PREFETCHNTA + break; + default: + //EXCEPTION(UD_EXCEPTION, 0); + break; + } + // XXX: 何もしない + } +} +void SSE_NOPPREFETCH(void) +{ + UINT32 op; + UINT idx, sub; + + //SSE_check_NM_EXCEPTION(); + //SSE_setTag(); + CPU_SSEWORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + // XXX: ここはどう扱う? + //EXCEPTION(UD_EXCEPTION, 0); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + // XXX: 何もしない + } +} +void SSE_SFENCE(void) +{ + // Nothing to do +} +void SSE_LFENCE(void) +{ + // Nothing to do +} +void SSE_MFENCE(void) +{ + // Nothing to do +} +void SSE_CLFLUSH(UINT32 op) +{ + UINT idx, sub; + + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + // XXX: ここはどう扱う? + //EXCEPTION(UD_EXCEPTION, 0); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + // XXX: 何もしない + } +} + + +#else + +/* + * SSE interface + */ + +void SSE_ADDPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_ADDSS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_ANDNPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_ANDPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_CMPPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_CMPSS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_COMISS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_CVTPI2PS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_CVTPS2PI(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_CVTSI2SS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_CVTSS2SI(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_CVTTPS2PI(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_CVTTSS2SI(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_DIVPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_DIVSS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_LDMXCSR(UINT32 maddr) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MAXPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MAXSS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MINPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MINSS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVAPSmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVAPSxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVHLPS(float *data1, float *data2) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVHPSmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVHPSxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVLHPS(float *data1, float *data2) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVLPSmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVLPSxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVMSKPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVSSmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVSSxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVUPSmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVUPSxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MULPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MULSS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_ORPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_RCPPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_RCPSS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_RSQRTPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_RSQRTSS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_SHUFPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_SQRTPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_SQRTSS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_STMXCSR(UINT32 maddr) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_SUBPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_SUBSS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_UCOMISS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_UNPCKHPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_UNPCKLPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_XORPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void SSE_PAVGB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PAVGW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PEXTRW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PINSRW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PMAXSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PMAXUB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PMINSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PMINUB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PMOVMSKB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PMULHUW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PSADBW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PSHUFW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void SSE_MASKMOVQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVNTPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MOVNTQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_PREFETCHTx(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_NOPPREFETCH(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_SFENCE(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_LFENCE(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_MFENCE(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE_CLFLUSH(UINT32 op) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + + #endif \ No newline at end of file diff --git a/i386c/ia32/instructions/sse/sse.h b/i386c/ia32/instructions/sse/sse.h old mode 100755 new mode 100644 index 53bd3c17..ed3104df --- a/i386c/ia32/instructions/sse/sse.h +++ b/i386c/ia32/instructions/sse/sse.h @@ -1,123 +1,123 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_SSE_SSE_H__ -#define IA32_CPU_INSTRUCTION_SSE_SSE_H__ - -typedef union { - UINT8 b[16]; - UINT16 w[8]; - UINT32 d[4]; - UINT64 q[2]; - float f32[4]; - double f64[2]; -} SSEREG; - -#ifdef __cplusplus -extern "C" { -#endif - -float SSE_ROUND(float val); - -void SSE_ADDPS(void); -void SSE_ADDSS(void); -void SSE_ANDNPS(void); -void SSE_ANDPS(void); -void SSE_CMPPS(void); -void SSE_CMPSS(void); -void SSE_COMISS(void); -void SSE_CVTPI2PS(void); -void SSE_CVTPS2PI(void); -void SSE_CVTSI2SS(void); -void SSE_CVTSS2SI(void); -void SSE_CVTTPS2PI(void); -void SSE_CVTTSS2SI(void); -void SSE_DIVPS(void); -void SSE_DIVSS(void); -void SSE_LDMXCSR(UINT32 maddr); -void SSE_MAXPS(void); -void SSE_MAXSS(void); -void SSE_MINPS(void); -void SSE_MINSS(void); -void SSE_MOVAPSmem2xmm(void); -void SSE_MOVAPSxmm2mem(void); -void SSE_MOVHLPS(float *data1, float *data2); -void SSE_MOVHPSmem2xmm(void); -void SSE_MOVHPSxmm2mem(void); -void SSE_MOVLHPS(float *data1, float *data2); -void SSE_MOVLPSmem2xmm(void); -void SSE_MOVLPSxmm2mem(void); -void SSE_MOVMSKPS(void); -void SSE_MOVSSmem2xmm(void); -void SSE_MOVSSxmm2mem(void); -void SSE_MOVUPSmem2xmm(void); -void SSE_MOVUPSxmm2mem(void); -void SSE_MULPS(void); -void SSE_MULSS(void); -void SSE_ORPS(void); -void SSE_RCPPS(void); -void SSE_RCPSS(void); -void SSE_RSQRTPS(void); -void SSE_RSQRTSS(void); -void SSE_SHUFPS(void); -void SSE_SQRTPS(void); -void SSE_SQRTSS(void); -void SSE_STMXCSR(UINT32 maddr); -void SSE_SUBPS(void); -void SSE_SUBSS(void); -void SSE_UCOMISS(void); -void SSE_UNPCKHPS(void); -void SSE_UNPCKLPS(void); -void SSE_XORPS(void); - -void SSE_PAVGB(void); -void SSE_PAVGW(void); -void SSE_PEXTRW(void); -void SSE_PINSRW(void); -void SSE_PMAXSW(void); -void SSE_PMAXUB(void); -void SSE_PMINSW(void); -void SSE_PMINUB(void); -void SSE_PMOVMSKB(void); -void SSE_PMULHUW(void); -void SSE_PSADBW(void); -void SSE_PSHUFW(void); - -void SSE_MASKMOVQ(void); -void SSE_MOVNTPS(void); -void SSE_MOVNTQ(void); -void SSE_PREFETCHTx(void); -void SSE_NOPPREFETCH(void); -//void SSE_PREFETCHNTA(void); // -> SSE_PREFETCHTx -void SSE_SFENCE(void); -void SSE_LFENCE(void); -void SSE_MFENCE(void); -void SSE_CLFLUSH(UINT32 op); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_SSE_SSE_H__ */ +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_SSE_SSE_H__ +#define IA32_CPU_INSTRUCTION_SSE_SSE_H__ + +typedef union { + UINT8 b[16]; + UINT16 w[8]; + UINT32 d[4]; + UINT64 q[2]; + float f32[4]; + double f64[2]; +} SSEREG; + +#ifdef __cplusplus +extern "C" { +#endif + +float SSE_ROUND(float val); + +void SSE_ADDPS(void); +void SSE_ADDSS(void); +void SSE_ANDNPS(void); +void SSE_ANDPS(void); +void SSE_CMPPS(void); +void SSE_CMPSS(void); +void SSE_COMISS(void); +void SSE_CVTPI2PS(void); +void SSE_CVTPS2PI(void); +void SSE_CVTSI2SS(void); +void SSE_CVTSS2SI(void); +void SSE_CVTTPS2PI(void); +void SSE_CVTTSS2SI(void); +void SSE_DIVPS(void); +void SSE_DIVSS(void); +void SSE_LDMXCSR(UINT32 maddr); +void SSE_MAXPS(void); +void SSE_MAXSS(void); +void SSE_MINPS(void); +void SSE_MINSS(void); +void SSE_MOVAPSmem2xmm(void); +void SSE_MOVAPSxmm2mem(void); +void SSE_MOVHLPS(float *data1, float *data2); +void SSE_MOVHPSmem2xmm(void); +void SSE_MOVHPSxmm2mem(void); +void SSE_MOVLHPS(float *data1, float *data2); +void SSE_MOVLPSmem2xmm(void); +void SSE_MOVLPSxmm2mem(void); +void SSE_MOVMSKPS(void); +void SSE_MOVSSmem2xmm(void); +void SSE_MOVSSxmm2mem(void); +void SSE_MOVUPSmem2xmm(void); +void SSE_MOVUPSxmm2mem(void); +void SSE_MULPS(void); +void SSE_MULSS(void); +void SSE_ORPS(void); +void SSE_RCPPS(void); +void SSE_RCPSS(void); +void SSE_RSQRTPS(void); +void SSE_RSQRTSS(void); +void SSE_SHUFPS(void); +void SSE_SQRTPS(void); +void SSE_SQRTSS(void); +void SSE_STMXCSR(UINT32 maddr); +void SSE_SUBPS(void); +void SSE_SUBSS(void); +void SSE_UCOMISS(void); +void SSE_UNPCKHPS(void); +void SSE_UNPCKLPS(void); +void SSE_XORPS(void); + +void SSE_PAVGB(void); +void SSE_PAVGW(void); +void SSE_PEXTRW(void); +void SSE_PINSRW(void); +void SSE_PMAXSW(void); +void SSE_PMAXUB(void); +void SSE_PMINSW(void); +void SSE_PMINUB(void); +void SSE_PMOVMSKB(void); +void SSE_PMULHUW(void); +void SSE_PSADBW(void); +void SSE_PSHUFW(void); + +void SSE_MASKMOVQ(void); +void SSE_MOVNTPS(void); +void SSE_MOVNTQ(void); +void SSE_PREFETCHTx(void); +void SSE_NOPPREFETCH(void); +//void SSE_PREFETCHNTA(void); // -> SSE_PREFETCHTx +void SSE_SFENCE(void); +void SSE_LFENCE(void); +void SSE_MFENCE(void); +void SSE_CLFLUSH(UINT32 op); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_SSE_SSE_H__ */ diff --git a/i386c/ia32/instructions/sse2/sse2.c b/i386c/ia32/instructions/sse2/sse2.c index 5f1d40fe..8a06d625 100644 --- a/i386c/ia32/instructions/sse2/sse2.c +++ b/i386c/ia32/instructions/sse2/sse2.c @@ -1,3494 +1,3494 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include - -#if 0 -#undef TRACEOUT -#define USE_TRACEOUT_VS -//#define MEM_BDA_TRACEOUT -//#define MEM_D8_TRACEOUT -#ifdef USE_TRACEOUT_VS -static void trace_fmt_ex(const char *fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "\n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#else -#define TRACEOUT(s) (void)(s) -#endif -#endif /* 1 */ - -#include -#include - -#if defined(_WIN32) && !defined(__LIBRETRO__) -#define isnan(x) (_isnan(x)) -#endif - -#include -#include "ia32/ia32.mcr" - -#include "ia32/instructions/sse/sse.h" -#include "ia32/instructions/sse2/sse2.h" - -#if defined(USE_SSE2) && defined(USE_SSE) && defined(USE_FPU) - -#define CPU_SSE2WORKCLOCK CPU_WORKCLOCK(2) - -static INLINE void -SSE2_check_NM_EXCEPTION(){ - // SSE2なしならUD(無効オペコード例外)を発生させる - if(!(i386cpuid.cpu_feature & CPU_FEATURE_SSE2)){ - EXCEPTION(UD_EXCEPTION, 0); - } - // エミュレーションならUD(無効オペコード例外)を発生させる - if(CPU_CR0 & CPU_CR0_EM){ - EXCEPTION(UD_EXCEPTION, 0); - } - // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる - if (CPU_CR0 & CPU_CR0_TS) { - EXCEPTION(NM_EXCEPTION, 0); - } -} - -static INLINE void -SSE2_setTag(void) -{ -} - -// mmx.cのものと同じ -static INLINE void -MMX_setTag(void) -{ - int i; - - if(!FPU_STAT.mmxenable){ - FPU_STAT.mmxenable = 1; - //FPU_CTRLWORD = 0x27F; - for (i = 0; i < FPU_REG_NUM; i++) { - FPU_STAT.tag[i] = TAG_Valid; -#ifdef SUPPORT_FPU_DOSBOX2 - FPU_STAT.int_regvalid[i] = 0; -#endif - FPU_STAT.reg[i].ul.ext = 0xffff; - } - } - FPU_STAT_TOP = 0; - FPU_STATUSWORD &= ~0x3800; - FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; -} - -float SSE2_ROUND_FLOAT(float val){ - return SSE_ROUND(val); -} -double SSE2_ROUND_DOUBLE(double val){ - double floorval; - int rndbit = (SSE_MXCSR >> 13) & 0x3; - switch(rndbit){ - case 0: - floorval = floor(val); - if (val - floorval > 0.5){ - return (floorval + 1); // 切り上げ - }else if (val - floorval < 0.5){ - return (floorval); // 切り捨て - }else{ - if(floor(floorval / 2) == floorval/2){ - return (floorval); // 偶数 - }else{ - return (floorval+1); // 奇数 - } - } - break; - case 1: - return floor(val); - case 2: - return ceil(val); - case 3: - if(val < 0){ - return ceil(val); // ゼロ方向への切り捨て - }else{ - return floor(val); // ゼロ方向への切り捨て - } - break; - default: - return val; - } -} - -/* - * SSE2 interface - */ - -// コードが長くなるのでやや強引に共通化 -// xmm/m128 -> xmm -static INLINE void SSE_PART_GETDATA1DATA2_PD(double **data1, double **data2, double *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); - *((UINT64*)(data2buf+ 1)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 8); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_P_UINT32(UINT32 **data1, UINT32 **data2, UINT32 *data2buf){ - SSE_PART_GETDATA1DATA2_PD((double**)data1, (double**)data2, (double*)data2buf); -} -static INLINE void SSE_PART_GETDATA1DATA2_PD_UINT64(UINT64 **data1, UINT64 **data2, UINT64 *data2buf){ - SSE_PART_GETDATA1DATA2_PD((double**)data1, (double**)data2, (double*)data2buf); -} -static INLINE void SSE_PART_GETDATA1DATA2_SD(double **data1, double **data2, double *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_S_UINT32(UINT32 **data1, UINT32 **data2, UINT32 *data2buf){ - SSE_PART_GETDATA1DATA2_SD((double**)data1, (double**)data2, (double*)data2buf); -} -static INLINE void SSE_PART_GETDATA1DATA2_SD_UINT64(UINT64 **data1, UINT64 **data2, UINT64 *data2buf){ - SSE_PART_GETDATA1DATA2_SD((double**)data1, (double**)data2, (double*)data2buf); -} -// xmm/m64 -> xmm -static INLINE void SSE_PART_GETDATA1DATA2_PDm64(double **data1, float **data2, float *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *((UINT32*)(data2buf+ 1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_SDm64(double **data1, float **data2, float *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *data2 = data2buf; - } -} - -// mm/m128 -> xmm -static INLINE void SSE_PART_GETDATA1DATA2_PD_MMX2XMM(double **data1, SINT32 **data2, SINT32 *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - MMX_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (SINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *((UINT32*)(data2buf+ 1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_SD_MMX2XMM(double **data1, SINT32 **data2, SINT32 *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - MMX_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (SINT32*)(&(FPU_STAT.reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *data2 = data2buf; - } -} -// xmm/m128 -> mm -static INLINE void SSE_PART_GETDATA1DATA2_PD_XMM2MMX(SINT32 **data1, double **data2, double *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - MMX_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (SINT32*)(&(FPU_STAT.reg[idx])); - if ((op) >= 0xc0) { - *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); - *((UINT64*)(data2buf+ 1)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 8); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_SD_XMM2MMX(SINT32 **data1, double **data2, double *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - MMX_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (SINT32*)(&(FPU_STAT.reg[idx])); - if ((op) >= 0xc0) { - *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); - *data2 = data2buf; - } -} - -// reg/m32 -> xmm -static INLINE void SSE_PART_GETDATA1DATA2_SD_REG2XMM(double **data1, SINT32 **data2, SINT32 *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (SINT32*)CPU_REG32_B20(op); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); - *data2 = data2buf; - } -} -static INLINE void SSE_PART_GETDATA1DATA2_SD_XMM2REG(SINT32 **data1, double **data2, double *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (SINT32*)CPU_REG32_B53(op); - if ((op) >= 0xc0) { - *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); - *data2 = data2buf; - } -} - -void SSE2_ADDPD(void) -{ - double data2buf[2]; - double *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - data1[i] = data1[i] + data2[i]; - } - TRACEOUT(("SSE2_ADDPD")); -} -void SSE2_ADDSD(void) -{ - double data2buf[2]; - double *data1, *data2; - - SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); - data1[0] = data1[0] + data2[0]; - TRACEOUT(("SSE2_ADDSD")); -} -void SSE2_ANDNPD(void) -{ - SSE_ANDNPS(); - TRACEOUT(("SSE2_ANDNPD")); -} -void SSE2_ANDPD(void) -{ - SSE_ANDPS(); - TRACEOUT(("SSE2_ANDPD")); -} -void SSE2_CMPPD(void) -{ - UINT32 idx; - double data2buf[2]; - double *data1, *data2; - UINT32 *data1ui32; - int i; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - - data1ui32 = (UINT32*)data1; - - GET_MODRM_PCBYTE((idx)); - switch(idx){ - case 0: // CMPEQPS - for(i=0;i<2;i++){ - data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] == data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 1: // CMPLTPS - for(i=0;i<2;i++){ - data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] < data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 2: // CMPLEPS - for(i=0;i<2;i++){ - data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] <= data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 3: // CMPUNORDPS - for(i=0;i<2;i++){ - data1ui32[i*2+0] = data1ui32[i*2+1] = (isnan(data1[i]) || isnan(data2[i]) ? 0xffffffff : 0x00000000); - } - break; - case 4: // CMPNEQPS - for(i=0;i<2;i++){ - data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] != data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 5: // CMPNLTPS - for(i=0;i<2;i++){ - data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] >= data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 6: // CMPNLEPS - for(i=0;i<2;i++){ - data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] > data2[i] ? 0xffffffff : 0x00000000); - } - break; - case 7: // CMPORDPS - for(i=0;i<2;i++){ - data1ui32[i*2+0] = data1ui32[i*2+1] = (!isnan(data1[i]) && !isnan(data2[i]) ? 0xffffffff : 0x00000000); - } - break; - } - TRACEOUT(("SSE2_CMPPD")); -} -void SSE2_CMPSD(void) -{ - UINT32 idx; - double data2buf[2]; - double *data1, *data2; - UINT32 *data1ui32; - - SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); - - data1ui32 = (UINT32*)data1; - - GET_MODRM_PCBYTE((idx)); - switch(idx){ - case 0: // CMPEQSS - data1ui32[0] = data1ui32[1] = (data1[0] == data2[0] ? 0xffffffff : 0x00000000); - break; - case 1: // CMPLTSS - data1ui32[0] = data1ui32[1] = (data1[0] < data2[0] ? 0xffffffff : 0x00000000); - break; - case 2: // CMPLESS - data1ui32[0] = data1ui32[1] = (data1[0] <= data2[0] ? 0xffffffff : 0x00000000); - break; - case 3: // CMPUNORDSS - data1ui32[0] = data1ui32[1] = (isnan(data1[0]) || isnan(data2[0]) ? 0xffffffff : 0x00000000); - break; - case 4: // CMPNEQSS - data1ui32[0] = data1ui32[1] = (data1[0] != data2[0] ? 0xffffffff : 0x00000000); - break; - case 5: // CMPNLTSS - data1ui32[0] = data1ui32[1] = (data1[0] >= data2[0] ? 0xffffffff : 0x00000000); - break; - case 6: // CMPNLESS - data1ui32[0] = data1ui32[1] = (data1[0] > data2[0] ? 0xffffffff : 0x00000000); - break; - case 7: // CMPORDSS - data1ui32[0] = data1ui32[1] = (!isnan(data1[0]) && !isnan(data2[0]) ? 0xffffffff : 0x00000000); - break; - } - TRACEOUT(("SSE2_CMPSD")); -} -void SSE2_COMISD(void) -{ - double data2buf[2]; - double *data1, *data2; - - SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); - - if(isnan(data1[0]) || isnan(data2[0])){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | P_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; - }else if(data1[0] > data2[0]){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; - }else if(data1[0] < data2[0]){ - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; - }else{ // equal - CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; - CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; - CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; - } - TRACEOUT(("SSE2_COMISD")); -} -void SSE2_CVTPI2PD(void) -{ - SINT32 data2buf[2]; - double *data1; - SINT32 *data2; - - SSE_PART_GETDATA1DATA2_PD_MMX2XMM(&data1, &data2, data2buf); - - data1[0] = (double)data2[0]; - data1[1] = (double)data2[1]; - TRACEOUT(("SSE2_CVTPI2PD")); -} -void SSE2_CVTPD2PI(void) -{ - double data2buf[2]; - SINT32 *data1; - double *data2; - - SSE_PART_GETDATA1DATA2_PD_XMM2MMX(&data1, &data2, data2buf); - - data1[0] = (SINT32)SSE2_ROUND_DOUBLE(data2[0]); - data1[1] = (SINT32)SSE2_ROUND_DOUBLE(data2[1]); - TRACEOUT(("SSE2_CVTPD2PI")); -} -void SSE2_CVTSI2SD(void) -{ - SINT32 data2buf[2]; - double *data1; - SINT32 *data2; - - SSE_PART_GETDATA1DATA2_SD_REG2XMM(&data1, &data2, data2buf); - - data1[0] = (double)data2[0]; - TRACEOUT(("SSE2_CVTSI2SD")); -} -void SSE2_CVTSD2SI(void) -{ - double data2buf[2]; - SINT32 *data1; - double *data2; - - SSE_PART_GETDATA1DATA2_SD_XMM2REG(&data1, &data2, data2buf); - - data1[0] = (SINT32)SSE2_ROUND_DOUBLE(data2[0]); - TRACEOUT(("SSE2_CVTSD2SI")); -} -void SSE2_CVTTPD2PI(void) -{ - double data2buf[2]; - SINT32 *data1; - double *data2; - - SSE_PART_GETDATA1DATA2_PD_XMM2MMX(&data1, &data2, data2buf); - - data1[0] = (SINT32)(data2[0]); - data1[1] = (SINT32)(data2[1]); - TRACEOUT(("SSE2_CVTTPD2PI")); -} -void SSE2_CVTTSD2SI(void) -{ - double data2buf[2]; - SINT32 *data1; - double *data2; - - SSE_PART_GETDATA1DATA2_SD_XMM2REG(&data1, &data2, data2buf); - - data1[0] = (SINT32)(data2[0]); - TRACEOUT(("SSE2_CVTTSD2SI")); -} -void SSE2_CVTPD2PS(void) -{ - double data2buf[2]; - float *data1; - double *data2; - - SSE_PART_GETDATA1DATA2_PD((double**)(&data1), &data2, data2buf); - - data1[0] = (float)(data2[0]); - data1[1] = (float)(data2[1]); - data1[2] = data1[3] = 0; - TRACEOUT(("SSE2_CVTPD2PS")); -} -void SSE2_CVTPS2PD(void) -{ - float data2buf[2]; - double *data1; - float *data2; - - SSE_PART_GETDATA1DATA2_PDm64(&data1, &data2, data2buf); - - data1[0] = (double)(data2[0]); - data1[1] = (double)(data2[1]); - TRACEOUT(("SSE2_CVTPS2PD")); -} -void SSE2_CVTSD2SS(void) -{ - double data2buf[2]; - float *data1; - double *data2; - - SSE_PART_GETDATA1DATA2_SD((double**)(&data1), &data2, data2buf); - - data1[0] = (float)(data2[0]); - TRACEOUT(("SSE2_CVTSD2SS")); -} -void SSE2_CVTSS2SD(void) -{ - float data2buf[2]; - double *data1; - float *data2; - - SSE_PART_GETDATA1DATA2_SDm64(&data1, &data2, data2buf); - - data1[0] = (double)(data2[0]); - TRACEOUT(("SSE2_CVTSS2SD")); -} -void SSE2_CVTPD2DQ(void) -{ - double data2buf[2]; - SINT32 *data1; - double *data2; - - SSE_PART_GETDATA1DATA2_PD((double**)(&data1), &data2, data2buf); - - data1[0] = (SINT32)SSE2_ROUND_DOUBLE(data2[0]); - data1[1] = (SINT32)SSE2_ROUND_DOUBLE(data2[1]); - data1[2] = data1[3] = 0; - TRACEOUT(("SSE2_CVTPD2DQ")); -} -void SSE2_CVTTPD2DQ(void) -{ - double data2buf[2]; - SINT32 *data1; - double *data2; - - SSE_PART_GETDATA1DATA2_PD((double**)(&data1), &data2, data2buf); - - data1[0] = (SINT32)(data2[0]); - data1[1] = (SINT32)(data2[1]); - data1[2] = data1[3] = 0; - TRACEOUT(("SSE2_CVTTPD2DQ")); -} -void SSE2_CVTDQ2PD(void) -{ - SINT32 data2buf[2]; - double *data1; - SINT32 *data2; - - SSE_PART_GETDATA1DATA2_PDm64(&data1, (float**)(&data2), (float*)data2buf); - - data1[0] = (double)(data2[0]); - data1[1] = (double)(data2[1]); - TRACEOUT(("SSE2_CVTDQ2PD")); -} -void SSE2_CVTPS2DQ(void) -{ - float data2buf[4]; - SINT32 *data1; - float *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); - - for(i=0;i<4;i++){ - data1[i] = (SINT32)SSE2_ROUND_FLOAT(data2[i]); - } - TRACEOUT(("SSE2_CVTPS2DQ")); -} -void SSE2_CVTTPS2DQ(void) -{ - float data2buf[4]; - SINT32 *data1; - float *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); - - for(i=0;i<4;i++){ - data1[i] = (SINT32)(data2[i]); - } - TRACEOUT(("SSE2_CVTTPS2DQ")); -} -void SSE2_CVTDQ2PS(void) -{ - SINT32 data2buf[4]; - float *data1; - SINT32 *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); - - for(i=0;i<4;i++){ - data1[i] = (float)(data2[i]); - } - TRACEOUT(("SSE2_CVTDQ2PS")); -} -void SSE2_DIVPD(void) -{ - double data2buf[2]; - double *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - data1[i] = data1[i] / data2[i]; - } - TRACEOUT(("SSE2_DIVPD")); -} -void SSE2_DIVSD(void) -{ - double data2buf[2]; - double *data1, *data2; - - SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); - data1[0] = data1[0] / data2[0]; - TRACEOUT(("SSE2_DIVSD")); -} -void SSE2_MAXPD(void) -{ - double data2buf[2]; - double *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - if(isnan(data1[i]) || isnan(data2[i])){ - data1[i] = data2[i]; - }else{ - data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); - } - } - TRACEOUT(("SSE2_MAXPD")); -} -void SSE2_MAXSD(void) -{ - double data2buf[2]; - double *data1, *data2; - - SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); - if(isnan(data1[0]) || isnan(data2[0])){ - data1[0] = data2[0]; - }else{ - data1[0] = (data1[0] > data2[0] ? data1[0] : data2[0]); - } - TRACEOUT(("SSE2_MAXSD")); -} -void SSE2_MINPD(void) -{ - double data2buf[2]; - double *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - if(isnan(data1[i]) || isnan(data2[i])){ - data1[i] = data2[i]; - }else{ - data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); - } - } - TRACEOUT(("SSE2_MINPD")); -} -void SSE2_MINSD(void) -{ - double data2buf[2]; - double *data1, *data2; - - SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); - if(isnan(data1[0]) || isnan(data2[0])){ - data1[0] = data2[0]; - }else{ - data1[0] = (data1[0] < data2[0] ? data1[0] : data2[0]); - } - TRACEOUT(("SSE2_MINSD")); -} -void SSE2_MOVAPDmem2xmm(void) -{ - SSE_MOVAPSmem2xmm(); - TRACEOUT(("SSE2_MOVAPDmem2xmm")); -} -void SSE2_MOVAPDxmm2mem(void) -{ - SSE_MOVAPSxmm2mem(); - TRACEOUT(("SSE2_MOVAPDxmm2mem")); -} -void SSE2_MOVHPDmem2xmm(void) -{ - SSE_MOVHPSmem2xmm(); - TRACEOUT(("SSE2_MOVHPDmem2xmm")); -} -void SSE2_MOVHPDxmm2mem(void) -{ - SSE_MOVHPSxmm2mem(); - TRACEOUT(("SSE2_MOVHPDxmm2mem")); -} -void SSE2_MOVLPDmem2xmm(void) -{ - SSE_MOVLPSmem2xmm(); - TRACEOUT(("SSE2_MOVLPDmem2xmm")); -} -void SSE2_MOVLPDxmm2mem(void) -{ - SSE_MOVLPSxmm2mem(); - TRACEOUT(("SSE2_MOVLPDxmm2mem")); -} -void SSE2_MOVMSKPD(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 *data1; - UINT32 *data2; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = CPU_REG32_B53(op); - if ((op) >= 0xc0) { - data2 = (UINT32*)(&(FPU_STAT.xmm_reg[sub])); - } else { - EXCEPTION(UD_EXCEPTION, 0); - } - *data1 = ((data2[1] >> 31) & 0x1)| - ((data2[3] >> 30) & 0x2); - TRACEOUT(("SSE2_MOVMSKPD")); -} -void SSE2_MOVSDmem2xmm(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG data2buf; - double *data1, *data2; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - data2buf.q[0] = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); - data2 = data2buf.f64; - *(UINT64*)(data1+1) = 0; - } - data1[0] = data2[0]; - TRACEOUT(("SSE2_MOVSDmem2xmm")); -} -void SSE2_MOVSDxmm2mem(void) -{ - UINT32 op; - UINT idx, sub; - double *data1, *data2; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); - data2[0] = data1[0]; - } else { - UINT32 madr; - madr = calc_ea_dst(op); - cpu_vmemorywrite_q(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT64*)(data1+ 0))); - } - TRACEOUT(("SSE2_MOVSDxmm2mem")); -} -void SSE2_MOVUPDmem2xmm(void) -{ - SSE2_MOVAPDmem2xmm(); // エミュレーションではアライメント制限がないのでMOVAPDと同じ - TRACEOUT(("SSE2_MOVUPDmem2xmm")); -} -void SSE2_MOVUPDxmm2mem(void) -{ - SSE2_MOVAPDxmm2mem(); // エミュレーションではアライメント制限がないのでMOVAPDと同じ - TRACEOUT(("SSE2_MOVUPDxmm2mem")); -} -void SSE2_MULPD(void) -{ - double data2buf[2]; - double *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - data1[i] = data1[i] * data2[i]; - } - TRACEOUT(("SSE2_MULPD")); -} -void SSE2_MULSD(void) -{ - double data2buf[2]; - double *data1, *data2; - - SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); - data1[0] = data1[0] * data2[0]; - TRACEOUT(("SSE2_MULSD")); -} -void SSE2_ORPD(void) -{ - SSE_ORPS(); - TRACEOUT(("SSE2_ORPD")); -} -void SSE2_SHUFPD(void) -{ - UINT32 imm8; - double data2buf[2]; - double data1buf[2]; - double *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - - GET_MODRM_PCBYTE((imm8)); - - for(i=0;i<2;i++){ - data1buf[i] = data1[i]; - } - data1[0] = data1buf[imm8 & 0x1]; - imm8 = (imm8 >> 1); - data1[1] = data2[imm8 & 0x1]; - TRACEOUT(("SSE2_SHUFPD")); -} -void SSE2_SQRTPD(void) -{ - double data2buf[2]; - double *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - data1[i] = sqrt(data2[i]); - } - TRACEOUT(("SSE2_SQRTPD")); -} -void SSE2_SQRTSD(void) -{ - double data2buf[2]; - double *data1, *data2; - - SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); - data1[0] = sqrt(data2[0]); - TRACEOUT(("SSE2_SQRTSD")); -} -//void SSE2_STMXCSR(UINT32 maddr) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_SUBPD(void) -{ - double data2buf[2]; - double *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - data1[i] = data1[i] - data2[i]; - } - TRACEOUT(("SSE2_SUBPD")); -} -void SSE2_SUBSD(void) -{ - double data2buf[2]; - double *data1, *data2; - - SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); - data1[0] = data1[0] - data2[0]; - TRACEOUT(("SSE2_SUBSD")); -} -void SSE2_UCOMISD(void) -{ - SSE_COMISS(); // XXX: とりあえず例外は考えないのでCOMISSと同じ - TRACEOUT(("SSE2_UCOMISD")); -} -void SSE2_UNPCKHPD(void) -{ - double data1buf[2]; - double data2buf[2]; - double *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - data1buf[i] = data1[i]; - } - data1[0] = data1buf[1]; - data1[1] = data2[1]; - TRACEOUT(("SSE2_UNPCKHPD")); -} -void SSE2_UNPCKLPD(void) -{ - double data1buf[2]; - double data2buf[2]; - double *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - data1buf[i] = data1[i]; - } - data1[0] = data1buf[0]; - data1[1] = data2[0]; - TRACEOUT(("SSE2_UNPCKLPD")); -} -void SSE2_XORPD(void) -{ - SSE_XORPS(); - TRACEOUT(("SSE2_XORPD")); -} - -void SSE2_MOVDrm2xmm(void) -{ - UINT32 op, src; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - (src) = *(CPU_REG32_B20(op)); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - (src) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - } - FPU_STAT.xmm_reg[idx].ul32[0] = src; - FPU_STAT.xmm_reg[idx].ul32[1] = FPU_STAT.xmm_reg[idx].ul32[2] = FPU_STAT.xmm_reg[idx].ul32[3] = 0; - TRACEOUT(("SSE2_MOVDrm2xmm")); -} -void SSE2_MOVDxmm2rm(void) -{ - UINT32 op, src, madr; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - src = FPU_STAT.xmm_reg[idx].ul32[0]; - if (op >= 0xc0) { - *(CPU_REG32_B20(op)) = src; - } else { - madr = calc_ea_dst(op); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); - } - TRACEOUT(("SSE2_MOVDxmm2rm")); -} -void SSE2_MOVDQAmem2xmm(void) -{ - SSE_MOVAPSmem2xmm(); - TRACEOUT(("SSE2_MOVDQAmem2xmm")); -} -void SSE2_MOVDQAxmm2mem(void) -{ - SSE_MOVAPSxmm2mem(); - TRACEOUT(("SSE2_MOVDQAxmm2mem")); -} -void SSE2_MOVDQUmem2xmm(void) -{ - SSE2_MOVDQAmem2xmm(); // エミュレーションではアライメント制限がないのでMOVDQAと同じ - TRACEOUT(("SSE2_MOVDQUmem2xmm")); -} -void SSE2_MOVDQUxmm2mem(void) -{ - SSE2_MOVDQAxmm2mem(); // エミュレーションではアライメント制限がないのでMOVDQAと同じ - TRACEOUT(("SSE2_MOVDQUxmm2mem")); -} -void SSE2_MOVQ2DQ(void) -{ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - MMX_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.xmm_reg[idx].ul64[0] = FPU_STAT.reg[sub].ll; // idxとsubが逆かも。要検証 - FPU_STAT.xmm_reg[idx].ul64[1] = 0; - } else { - EXCEPTION(UD_EXCEPTION, 0); - } - TRACEOUT(("SSE2_MOVQ2DQ")); -} -void SSE2_MOVDQ2Q(void) -{ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - MMX_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.reg[idx].ll = FPU_STAT.xmm_reg[sub].ul64[0]; // idxとsubが逆かも。要検証 - } else { - EXCEPTION(UD_EXCEPTION, 0); - } - TRACEOUT(("SSE2_MOVDQ2Q")); -} -void SSE2_MOVQmem2xmm(void) -{ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.xmm_reg[idx].ul64[0] = FPU_STAT.xmm_reg[sub].ul64[0]; - } else { - UINT32 madr; - madr = calc_ea_dst(op); - FPU_STAT.xmm_reg[idx].ul64[0] = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); - FPU_STAT.xmm_reg[idx].ul64[1] = 0; - } - TRACEOUT(("SSE2_MOVQmem2xmm")); -} -void SSE2_MOVQxmm2mem(void) -{ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.xmm_reg[sub].ul64[0] = FPU_STAT.xmm_reg[idx].ul64[0]; - } else { - UINT32 madr; - madr = calc_ea_dst(op); - cpu_vmemorywrite_q(CPU_INST_SEGREG_INDEX, madr, FPU_STAT.xmm_reg[idx].ul64[0]); - } - TRACEOUT(("SSE2_MOVQxmm2mem")); -} -void SSE2_PACKSSDW(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG srcreg2buf; - INT32 *srcreg1; - INT32 *srcreg2; - INT16 *dstreg; - INT16 dstregbuf[8]; - int i; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg1 = (INT32*)(&(FPU_STAT.xmm_reg[idx])); - srcreg2 = (INT32*)(&(FPU_STAT.xmm_reg[sub])); - dstreg = (INT16*)(&(FPU_STAT.xmm_reg[idx])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcreg2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcreg2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); - srcreg2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); - srcreg1 = (INT32*)(&(FPU_STAT.xmm_reg[idx])); - srcreg2 = srcreg2buf.d; - dstreg = (INT16*)(&(FPU_STAT.xmm_reg[idx])); - } - for(i=0;i<4;i++){ - if(srcreg1[i] > 32767){ - dstregbuf[i] = 32767; - }else if(srcreg1[i] < -32768){ - dstregbuf[i] = -32768; - }else{ - dstregbuf[i] = (INT16)(srcreg1[i]); - } - } - for(i=0;i<4;i++){ - if(srcreg2[i] > 32767){ - dstregbuf[i+4] = 32767; - }else if(srcreg2[i] < -32768){ - dstregbuf[i+4] = -32768; - }else{ - dstregbuf[i+4] = (INT16)(srcreg2[i]); - } - } - for(i=0;i<8;i++){ - dstreg[i] = dstregbuf[i]; - } - TRACEOUT(("SSE2_PACKSSDW")); -} -void SSE2_PACKSSWB(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG srcreg2buf; - INT16 *srcreg1; - INT16 *srcreg2; - INT8 *dstreg; - INT8 dstregbuf[16]; - int i; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg1 = (INT16*)(&(FPU_STAT.xmm_reg[idx])); - srcreg2 = (INT16*)(&(FPU_STAT.xmm_reg[sub])); - dstreg = (INT8*)(&(FPU_STAT.xmm_reg[idx])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcreg2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcreg2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); - srcreg2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); - srcreg1 = (INT16*)(&(FPU_STAT.xmm_reg[idx])); - srcreg2 = srcreg2buf.w; - dstreg = (INT8*)(&(FPU_STAT.xmm_reg[idx])); - } - for(i=0;i<8;i++){ - if(srcreg1[i] > 127){ - dstregbuf[i] = 127; - }else if(srcreg1[i] < -128){ - dstregbuf[i] = -128; - }else{ - dstregbuf[i] = (INT8)(srcreg1[i]); - } - } - for(i=0;i<8;i++){ - if(srcreg2[i] > 127){ - dstregbuf[i+8] = 127; - }else if(srcreg2[i] < -128){ - dstregbuf[i+8] = -128; - }else{ - dstregbuf[i+8] = (INT8)(srcreg2[i]); - } - } - for(i=0;i<16;i++){ - dstreg[i] = dstregbuf[i]; - } - TRACEOUT(("SSE2_PACKSSWB")); -} -void SSE2_PACKUSWB(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG srcreg2buf; - INT16 *srcreg1; - INT16 *srcreg2; - UINT8 *dstreg; - UINT8 dstregbuf[16]; - int i; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - srcreg1 = (INT16*)(&(FPU_STAT.xmm_reg[idx])); - srcreg2 = (INT16*)(&(FPU_STAT.xmm_reg[sub])); - dstreg = (UINT8*)(&(FPU_STAT.xmm_reg[idx])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - srcreg2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - srcreg2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - srcreg2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); - srcreg2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); - srcreg1 = (INT16*)(&(FPU_STAT.xmm_reg[idx])); - srcreg2 = srcreg2buf.w; - dstreg = (UINT8*)(&(FPU_STAT.xmm_reg[idx])); - } - for(i=0;i<8;i++){ - if(srcreg1[i] > 255){ - dstregbuf[i] = 255; - }else if(srcreg1[i] < 0){ - dstregbuf[i] = 0; - }else{ - dstregbuf[i] = (UINT8)(srcreg1[i]); - } - } - for(i=0;i<8;i++){ - if(srcreg2[i] > 255){ - dstregbuf[i+8] = 255; - }else if(srcreg2[i] < 0){ - dstregbuf[i+8] = 0; - }else{ - dstregbuf[i+8] = (UINT8)(srcreg2[i]); - } - } - for(i=0;i<16;i++){ - dstreg[i] = dstregbuf[i]; - } - TRACEOUT(("SSE2_PACKUSWB")); -} -void SSE2_PADDQmm(void) -{ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - MMX_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.reg[idx].ll += FPU_STAT.reg[sub].ll; - } else { - UINT32 madr; - madr = calc_ea_dst(op); - FPU_STAT.reg[idx].ll += (SINT64)cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); - } - TRACEOUT(("SSE2_PADDQmm")); -} -void SSE2_PADDQxmm(void) -{ - UINT64 data2buf[2]; - UINT64 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - data1[i] = data1[i] + data2[i]; - } - TRACEOUT(("SSE2_PADDQxmm")); -} -void SSE2_PADDB(void) -{ - UINT8 data2buf[16]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - data1[i] = data1[i] + data2[i]; - } - TRACEOUT(("SSE2_PADDB")); -} -void SSE2_PADDW(void) -{ - UINT16 data2buf[8]; - UINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<8;i++){ - data1[i] = data1[i] + data2[i]; - } - TRACEOUT(("SSE2_PADDW")); -} -void SSE2_PADDD(void) -{ - UINT32 data2buf[4]; - UINT32 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<4;i++){ - data1[i] = data1[i] + data2[i]; - } - TRACEOUT(("SSE2_PADDD")); -} -//void SSE2_PADDQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PADDSB(void) -{ - SINT8 data2buf[16]; - SINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - SINT16 cbuf = (SINT16)data1[i] + (SINT16)data2[i]; - if(cbuf > 127){ - data1[i] = 127; - }else if(cbuf < -128){ - data1[i] = -128; - }else{ - data1[i] = (SINT8)cbuf; - } - } - TRACEOUT(("SSE2_PADDSB")); -} -void SSE2_PADDSW(void) -{ - SINT16 data2buf[8]; - SINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<8;i++){ - SINT32 cbuf = (SINT32)data1[i] + (SINT32)data2[i]; - if(cbuf > 32767){ - data1[i] = 32767; - }else if(cbuf < -32768){ - data1[i] = -32768; - }else{ - data1[i] = (SINT16)cbuf; - } - } - TRACEOUT(("SSE2_PADDSW")); -} -//void SSE2_PADDSD(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PADDSQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PADDUSB(void) -{ - UINT8 data2buf[16]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - UINT16 cbuf = (UINT16)data1[i] + (UINT16)data2[i]; - if(cbuf > 255){ - data1[i] = 255; - }else{ - data1[i] = (UINT8)cbuf; - } - } - TRACEOUT(("SSE2_PADDUSB")); -} -void SSE2_PADDUSW(void) -{ - UINT16 data2buf[8]; - UINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<8;i++){ - UINT32 cbuf = (UINT32)data1[i] + (UINT32)data2[i]; - if(cbuf > 65535){ - data1[i] = 65535; - }else{ - data1[i] = (UINT16)cbuf; - } - } - TRACEOUT(("SSE2_PADDUSW")); -} -//void SSE2_PADDUSD(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PADDUSQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PAND(void) -{ - SSE_ANDPS(); - TRACEOUT(("SSE2_PAND")); -} -void SSE2_PANDN(void) -{ - SSE_ANDNPS(); - TRACEOUT(("SSE2_PANDN")); -} -void SSE2_PAVGB(void) -{ - UINT8 data2buf[16]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - data1[i] = (UINT8)(((UINT16)data1[i] + (UINT16)data2[i] + 1) / 2); - } - TRACEOUT(("SSE2_PAVGB")); -} -void SSE2_PAVGW(void) -{ - UINT16 data2buf[8]; - UINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<8;i++){ - data1[i] = (UINT16)(((UINT32)data1[i] + (UINT32)data2[i] + 1) / 2); - } - TRACEOUT(("SSE2_PAVGW")); -} -void SSE2_PCMPEQB(void) -{ - UINT8 data2buf[16]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - data1[i] = (data1[i] == data2[i] ? 0xff : 0x00); - } - TRACEOUT(("SSE2_PCMPEQB")); -} -void SSE2_PCMPEQW(void) -{ - UINT16 data2buf[8]; - UINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<8;i++){ - data1[i] = (data1[i] == data2[i] ? 0xffff : 0x00); - } - TRACEOUT(("SSE2_PCMPEQW")); -} -void SSE2_PCMPEQD(void) -{ - UINT32 data2buf[4]; - UINT32 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<4;i++){ - data1[i] = (data1[i] == data2[i] ? 0xffffffff : 0x00); - } - TRACEOUT(("SSE2_PCMPEQD")); -} -//void SSE2_PCMPEQQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PCMPGTB(void) -{ - SINT8 data2buf[16]; - SINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - data1[i] = (data1[i] > data2[i] ? 0xff : 0x00); - } - TRACEOUT(("SSE2_PCMPGTB")); -} -void SSE2_PCMPGTW(void) -{ - SINT16 data2buf[8]; - SINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<8;i++){ - data1[i] = (data1[i] > data2[i] ? 0xffff : 0x00); - } - TRACEOUT(("SSE2_PCMPGTW")); -} -void SSE2_PCMPGTD(void) -{ - SINT32 data2buf[4]; - SINT32 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<4;i++){ - data1[i] = (data1[i] > data2[i] ? 0xffffffff : 0x00); - } - TRACEOUT(("SSE2_PCMPGTD")); -} -//void SSE2_PCMPGTQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PEXTRW(void) -{ - UINT32 imm8; - UINT32 op; - UINT idx, sub; - UINT32 *data1; - UINT16 *data2; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (UINT32*)CPU_REG32_B53(op); - if ((op) >= 0xc0) { - data2 = (UINT16*)(&(FPU_STAT.xmm_reg[sub])); - } else { - EXCEPTION(UD_EXCEPTION, 0); - } - GET_MODRM_PCBYTE((imm8)); - *data1 = (UINT32)data2[imm8 & 0x7]; - TRACEOUT(("SSE2_PEXTRW")); -} -void SSE2_PINSRW(void) -{ - UINT32 imm8; - UINT32 op; - UINT idx, sub; - UINT16 *data1; - UINT16 data2; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (UINT16*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (UINT16)((*CPU_REG32_B20(op)) & 0xffff); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - data2 = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, maddr+ 0); - } - GET_MODRM_PCBYTE((imm8)); - data1[imm8 & 0x7] = data2; - TRACEOUT(("SSE2_PINSRW")); -} -void SSE2_PMADD(void) -{ - SINT16 data2buf[8]; - SINT16 *data1, *data2; - SINT32 data1dbuf[4]; - SINT32 *data1d; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - data1d = (SINT32*)data1; - - data1dbuf[0] = (INT32)data2[0] * (INT32)data1[0] + (INT32)data2[1] * (INT32)data1[1]; - data1dbuf[1] = (INT32)data2[2] * (INT32)data1[2] + (INT32)data2[3] * (INT32)data1[3]; - data1dbuf[2] = (INT32)data2[4] * (INT32)data1[4] + (INT32)data2[5] * (INT32)data1[5]; - data1dbuf[3] = (INT32)data2[6] * (INT32)data1[6] + (INT32)data2[7] * (INT32)data1[7]; - data1d[0] = data1dbuf[0]; - data1d[1] = data1dbuf[1]; - data1d[2] = data1dbuf[2]; - data1d[3] = data1dbuf[3]; - TRACEOUT(("SSE2_PMADD")); -} -void SSE2_PMAXSW(void) -{ - SINT16 data2buf[8]; - SINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<8;i++){ - data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); - } - TRACEOUT(("SSE2_PMAXSW")); -} -void SSE2_PMAXUB(void) -{ - UINT8 data2buf[16]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); - } - TRACEOUT(("SSE2_PMAXUB")); -} -void SSE2_PMINSW(void) -{ - SINT16 data2buf[8]; - SINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<8;i++){ - data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); - } - TRACEOUT(("SSE2_PMINSW")); -} -void SSE2_PMINUB(void) -{ - UINT8 data2buf[16]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); - } - TRACEOUT(("SSE2_PMINUB")); -} -void SSE2_PMOVMSKB(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 *data1; - UINT8 *data2; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (UINT32*)CPU_REG32_B53(op); - if ((op) >= 0xc0) { - data2 = (UINT8*)(&(FPU_STAT.reg[sub])); - } else { - EXCEPTION(UD_EXCEPTION, 0); - } - *data1 = ((UINT32)(data2[0] >> 7) & 0x1 )| - ((UINT32)(data2[1] >> 6) & 0x2 )| - ((UINT32)(data2[2] >> 5) & 0x4 )| - ((UINT32)(data2[3] >> 4) & 0x8 )| - ((UINT32)(data2[4] >> 3) & 0x10)| - ((UINT32)(data2[5] >> 2) & 0x20)| - ((UINT32)(data2[6] >> 1) & 0x40)| - ((UINT32)(data2[7] >> 0) & 0x80)| - (((UINT32)(data2[8] >> 7) & 0x1 ) << 8)| - (((UINT32)(data2[9] >> 6) & 0x2 ) << 8)| - (((UINT32)(data2[10]>> 5) & 0x4 ) << 8)| - (((UINT32)(data2[11]>> 4) & 0x8 ) << 8)| - (((UINT32)(data2[12]>> 3) & 0x10) << 8)| - (((UINT32)(data2[13]>> 2) & 0x20) << 8)| - (((UINT32)(data2[14]>> 1) & 0x40) << 8)| - (((UINT32)(data2[15]>> 0) & 0x80) << 8); - TRACEOUT(("SSE2_PMOVMSKB")); -} -void SSE2_PMULHUW(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG data2buf; - UINT16 *data1, *data2; - int i; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (UINT16*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (UINT16*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - data2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); - data2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); - data2 = data2buf.w; - } - for(i=0;i<8;i++){ - data1[i] = (UINT16)((((UINT32)data2[i] * (UINT32)data1[i]) >> 16) & 0xffff); - } - TRACEOUT(("SSE2_PMULHUW")); -} -void SSE2_PMULHW(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG data2buf; - SINT16 *data1, *data2; - int i; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (SINT16*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (SINT16*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - data2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); - data2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); - data2 = data2buf.w; - } - for(i=0;i<8;i++){ - data1[i] = (SINT16)((((SINT32)data2[i] * (SINT32)data1[i]) >> 16) & 0xffff); - } - TRACEOUT(("SSE2_PMULHW")); -} -void SSE2_PMULLW(void) -{ - UINT32 op; - UINT idx, sub; - SSEREG data2buf; - SINT16 *data1, *data2; - int i; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = (SINT16*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - data2 = (SINT16*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); - data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); - data2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); - data2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); - data2 = data2buf.w; - } - for(i=0;i<8;i++){ - data1[i] = (SINT16)((((SINT32)data2[i] * (SINT32)data1[i])) & 0xffff); - } - TRACEOUT(("SSE2_PMULLW")); -} -void SSE2_PMULUDQmm(void) -{ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - MMX_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.reg[idx].ll = ((UINT64)FPU_STAT.reg[idx].l.lower * (UINT64)FPU_STAT.reg[sub].l.lower); - } else { - UINT32 madr; - madr = calc_ea_dst(op); - FPU_STAT.reg[idx].ll = ((UINT64)FPU_STAT.reg[idx].l.lower * (cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr) & 0xffffffff)); - } - TRACEOUT(("SSE2_PMULUDQmm")); -} -void SSE2_PMULUDQxmm(void) -{ - UINT64 data2buf[2]; - UINT64 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - data1[i] = (data1[i] & 0xffffffff) * (data2[i] & 0xffffffff); - } - TRACEOUT(("SSE2_PMULUDQxmm")); -} -void SSE2_POR(void) -{ - SSE_ORPS(); - TRACEOUT(("SSE2_POR")); -} -void SSE2_PSADBW(void) -{ - SINT16 temp1; - UINT16 temp; - UINT8 data2buf[16]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - - temp = 0; - for(i=0;i<8;i++){ - temp1 = (SINT16)data2[i] - (SINT16)data1[i]; - temp += (UINT16)(temp1 < 0 ? -temp1 : temp1); - } - *((UINT16*)data2 + 0) = temp; - *((UINT16*)data2 + 1) = 0; - *((UINT16*)data2 + 2) = 0; - *((UINT16*)data2 + 3) = 0; - - temp = 0; - for(i=8;i<16;i++){ - temp1 = (SINT16)data2[i] - (SINT16)data1[i]; - temp += (UINT16)(temp1 < 0 ? -temp1 : temp1); - } - *((UINT16*)data2 + 4) = temp; - *((UINT16*)data2 + 5) = 0; - *((UINT16*)data2 + 6) = 0; - *((UINT16*)data2 + 7) = 0; - TRACEOUT(("SSE2_PSADBW")); -} -void SSE2_PSHUFLW(void) -{ - UINT32 imm8; - UINT16 data2buf[8]; - UINT16 *data1, *data2; - UINT16 dstbuf[8]; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - GET_MODRM_PCBYTE((imm8)); - for(i=0;i<4;i++){ - dstbuf[i] = data2[imm8 & 0x3]; - imm8 = imm8 >> 2; - } - for(i=0;i<4;i++){ - data1[i] = dstbuf[i]; - } - for(i=4;i<8;i++){ - data1[i] = data2[i]; - } - TRACEOUT(("SSE2_PSHUFLW")); -} -void SSE2_PSHUFHW(void) -{ - UINT32 imm8; - UINT16 data2buf[8]; - UINT16 *data1, *data2; - UINT16 dstbuf[8]; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - GET_MODRM_PCBYTE((imm8)); - for(i=0;i<4;i++){ - data1[i] = data2[i]; - } - for(i=4;i<8;i++){ - dstbuf[i] = data2[4 + (imm8 & 0x3)]; - imm8 = imm8 >> 2; - } - for(i=4;i<8;i++){ - data1[i] = dstbuf[i]; - } - TRACEOUT(("SSE2_PSHUFHW")); -} -void SSE2_PSHUFD(void) -{ - UINT32 imm8; - UINT32 data2buf[4]; - UINT32 *data1, *data2; - UINT32 dstbuf[4]; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - GET_MODRM_PCBYTE((imm8)); - for(i=0;i<4;i++){ - dstbuf[i] = data2[imm8 & 0x3]; - imm8 = imm8 >> 2; - } - for(i=0;i<4;i++){ - data1[i] = dstbuf[i]; - } - TRACEOUT(("SSE2_PSHUFD")); -} -//void SSE2_PSLLDQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSLLB(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSLLW(void) -{ - UINT32 data2buf[4]; - UINT16 *data1; - UINT32 *data2; - UINT32 shift; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - shift = data2[0]; - if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - - for(i=0;i<8;i++){ - data1[i] = (shift >= 16 ? 0 : (data1[i] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } - TRACEOUT(("SSE2_PSLLW")); -} -void SSE2_PSLLD(void) -{ - UINT32 data2buf[4]; - UINT32 *data1; - UINT32 *data2; - UINT32 shift; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - shift = data2[0]; - if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - - for(i=0;i<4;i++){ - data1[i] = (shift >= 32 ? 0 : (data1[i] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } - TRACEOUT(("SSE2_PSLLD")); -} -void SSE2_PSLLQ(void) -{ - UINT32 data2buf[4]; - UINT64 *data1; - UINT32 *data2; - UINT32 shift; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - shift = data2[0]; - if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - - for(i=0;i<2;i++){ - data1[i] = (shift >= 64 ? 0 : (data1[i] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } - TRACEOUT(("SSE2_PSLLQ")); -} -//void SSE2_PSLLBimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSLLWimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSLLDimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSLLQimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSRAB(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSRAW(void) -{ - UINT32 data2buf[4]; - UINT16 *data1; - UINT32 *data2; - UINT32 shift; - UINT16 signval; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - shift = data2[0]; - if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - - // 無理やり算術シフト(怪しい) - if(16 <= shift){ - signval = 0xffff; - }else{ - UINT32 rshift = 16 - shift; - signval = (0xffff >> rshift) << rshift; - } - for(i=0;i<8;i++){ - if(((INT16*)data1)[i] < 0){ - data1[i] = (data1[i] >> shift) | signval; - }else{ - data1[i] = (shift >= 16 ? 0 : (data1[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } - TRACEOUT(("SSE2_PSRAW")); -} -void SSE2_PSRAD(void) -{ - UINT32 data2buf[4]; - UINT32 *data1; - UINT32 *data2; - UINT32 shift; - UINT32 signval; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - shift = data2[0]; - if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - - // 無理やり算術シフト(怪しい) - if(32 <= shift){ - signval = 0xffffffff; - }else{ - UINT32 rshift = 32 - shift; - signval = (0xffffffff >> rshift) << rshift; - } - for(i=0;i<2;i++){ - if(((INT32*)data1)[i] < 0){ - data1[i] = (data1[i] >> shift) | signval; - }else{ - data1[i] = (shift >= 32 ? 0 : (data1[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } - TRACEOUT(("SSE2_PSRAD")); -} -//void SSE2_PSRAQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSRABimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSRAWimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSRADimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSRAQimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSRLDQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSRLB(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSRLW(void) -{ - UINT32 data2buf[4]; - UINT16 *data1; - UINT32 *data2; - UINT32 shift; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - shift = data2[0]; - if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - - for(i=0;i<8;i++){ - data1[i] = (shift >= 16 ? 0 : (data1[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - TRACEOUT(("SSE2_PSRLW")); -} -void SSE2_PSRLD(void) -{ - UINT32 data2buf[4]; - UINT32 *data1; - UINT32 *data2; - UINT32 shift; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - shift = data2[0]; - if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - - for(i=0;i<4;i++){ - data1[i] = (shift >= 32 ? 0 : (data1[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - TRACEOUT(("SSE2_PSRLD")); -} -void SSE2_PSRLQ(void) -{ - UINT32 data2buf[4]; - UINT64 *data1; - UINT32 *data2; - UINT32 shift; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - shift = data2[0]; - if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく - - for(i=0;i<2;i++){ - data1[i] = (shift >= 64 ? 0 : (data1[i] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - TRACEOUT(("SSE2_PSRLQ")); -} -//void SSE2_PSRLBimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSRLWimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSRLDimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSRLQimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSxxWimm(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT16 *dstreg; - UINT16 signval; - int i; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - dstreg = (UINT16*)(&(FPU_STAT.xmm_reg[sub])); - GET_MODRM_PCBYTE((shift)); - - switch(idx){ - case 2: // PSRLW(imm8) - for(i=0;i<8;i++){ - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - break; - case 4: // PSRAW(imm8) - // 無理やり算術シフト(怪しい) - if(16 <= shift){ - signval = 0xffff; - }else{ - UINT32 rshift = 16 - shift; - signval = (0xffff >> rshift) << rshift; - } - for(i=0;i<8;i++){ - if(((INT16*)dstreg)[i] < 0){ - dstreg[i] = (dstreg[i] >> shift) | signval; - }else{ - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } - break; - case 6: // PSLLW(imm8) - for(i=0;i<8;i++){ - dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } - break; - default: - break; - } - TRACEOUT(("SSE2_PSxxWimm")); -} -void SSE2_PSxxDimm(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT32 *dstreg; - UINT32 signval; - int i; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - dstreg = (UINT32*)(&(FPU_STAT.xmm_reg[sub])); - GET_MODRM_PCBYTE((shift)); - - switch(idx){ - case 2: // PSRLD(imm8) - for(i=0;i<4;i++){ - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - break; - case 4: // PSRAD(imm8) - // 無理やり算術シフト(怪しい) - if(32 <= shift){ - signval = 0xffffffff; - }else{ - UINT32 rshift = 32 - shift; - signval = (0xffffffff >> rshift) << rshift; - } - for(i=0;i<4;i++){ - if(((INT32*)dstreg)[i] < 0){ - dstreg[i] = (dstreg[i] >> shift) | signval; - }else{ - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - } - break; - case 6: // PSLLD(imm8) - for(i=0;i<4;i++){ - dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } - break; - default: - break; - } - TRACEOUT(("SSE2_PSxxDimm")); -} -void SSE2_PSxxQimm(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 shift; - UINT64 *dstreg; - int i; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - dstreg = (UINT64*)(&(FPU_STAT.xmm_reg[sub])); - GET_MODRM_PCBYTE((shift)); - - switch(idx){ - case 2: // PSRLQ(imm8) - for(i=0;i<2;i++){ - dstreg[i] = (shift >= 64 ? 0 : (dstreg[i] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) - } - break; - case 3: // PSRLDQ - // 無理やり128bit右シフト 怪しいので要検証 - shift *= 8; // シフト量はバイト数で指定 - if(shift == 0){ - // シフト無しなら何もしない - }else if(shift >= 128){ - // シフトが128以上の時 - dstreg[0] = dstreg[1] = 0; - }else if(shift >= 64){ - // シフトが64以上の時 - dstreg[0] = dstreg[1] >> (shift - 64); - dstreg[1] = 0; - }else{ - // シフトが64より小さい時 - dstreg[0] = (dstreg[0] >> shift) | (dstreg[1] << (64-shift)); // 下位QWORD右シフト&上から降りてきたビットをOR - dstreg[1] = (dstreg[1] >> shift); - } - break; - case 4: // PSRAQ(imm8) - EXCEPTION(UD_EXCEPTION, 0); - break; - case 6: // PSLLQ(imm8) - for(i=0;i<2;i++){ - dstreg[i] = (shift >= 64 ? 0 : (dstreg[i] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) - } - break; - case 7: // PSLLDQ - // 無理やり128bit左シフト 怪しいので要検証 - shift *= 8; // シフト量はバイト数で指定 - if(shift == 0){ - // シフト無しなら何もしない - }else if(shift >= 128){ - // シフトが128以上の時 - dstreg[0] = dstreg[1] = 0; - }else if(shift >= 64){ - // シフトが64以上の時 - dstreg[1] = dstreg[0] << (shift - 64); - dstreg[0] = 0; - }else{ - // シフトが64より小さい時 - dstreg[1] = (dstreg[1] << shift) | (dstreg[0] >> (64-shift)); // 上位QWORD左シフト&下から上がってきたビットをOR - dstreg[0] = (dstreg[0] << shift); - } - break; - default: - break; - } - TRACEOUT(("SSE2_PSxxQimm")); -} -void SSE2_PSUBQmm(void) -{ - UINT32 op; - UINT idx, sub; - - SSE2_check_NM_EXCEPTION(); - SSE2_setTag(); - MMX_setTag(); - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.reg[idx].ll -= FPU_STAT.reg[sub].ll; - } else { - UINT32 madr; - madr = calc_ea_dst(op); - FPU_STAT.reg[idx].ll -= (SINT64)cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); - } - TRACEOUT(("SSE2_PSUBQmm")); -} -void SSE2_PSUBQxmm(void) -{ - UINT64 data2buf[2]; - UINT64 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64(&data1, &data2, data2buf); - for(i=0;i<2;i++){ - data1[i] = data1[i] - data2[i]; - } - TRACEOUT(("SSE2_PSUBQxmm")); -} -void SSE2_PSUBB(void) -{ - UINT8 data2buf[16]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - data1[i] = data1[i] - data2[i]; - } - TRACEOUT(("SSE2_PSUBB")); -} -void SSE2_PSUBW(void) -{ - UINT16 data2buf[8]; - UINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<8;i++){ - data1[i] = data1[i] - data2[i]; - } - TRACEOUT(("SSE2_PSUBW")); -} -void SSE2_PSUBD(void) -{ - UINT32 data2buf[4]; - UINT32 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<4;i++){ - data1[i] = data1[i] - data2[i]; - } - TRACEOUT(("SSE2_PSUBD")); -} -//void SSE2_PSUBQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSUBSB(void) -{ - SINT8 data2buf[16]; - SINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - SINT16 cbuf = (SINT16)data1[i] - (SINT16)data2[i]; - if(cbuf > 127){ - data1[i] = 127; - }else if(cbuf < -128){ - data1[i] = -128; - }else{ - data1[i] = (SINT8)cbuf; - } - } - TRACEOUT(("SSE2_PSUBSB")); -} -void SSE2_PSUBSW(void) -{ - SINT16 data2buf[8]; - SINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<8;i++){ - SINT32 cbuf = (SINT32)data1[i] - (SINT32)data2[i]; - if(cbuf > 32767){ - data1[i] = 32767; - }else if(cbuf < -32768){ - data1[i] = -32768; - }else{ - data1[i] = (SINT16)cbuf; - } - } - TRACEOUT(("SSE2_PSUBSW")); -} -//void SSE2_PSUBSD(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSUBSQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSUBUSB(void) -{ - UINT8 data2buf[16]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - SINT16 cbuf = (SINT16)data1[i] - (SINT16)data2[i]; - if(cbuf > 255){ - data1[i] = 255; - }else if(cbuf < 0){ - data1[i] = 0; - }else{ - data1[i] = (UINT8)cbuf; - } - } - TRACEOUT(("SSE2_PSUBUSB")); -} -void SSE2_PSUBUSW(void) -{ - UINT16 data2buf[8]; - UINT16 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<8;i++){ - SINT32 cbuf = (SINT32)data1[i] - (SINT32)data2[i]; - if(cbuf > 65535){ - data1[i] = 65535; - }else if(cbuf < 0){ - data1[i] = 0; - }else{ - data1[i] = (UINT16)cbuf; - } - } - TRACEOUT(("SSE2_PSUBUSW")); -} -//void SSE2_PSUBUSD(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSUBUSQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PUNPCKHBW(void) -{ - UINT8 data2buf[16]; - UINT8 *data1; - UINT8 *data2; - UINT8 dstregbuf[16]; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - - for(i=0;i<8;i++){ - dstregbuf[i*2] = data1[i+8]; - dstregbuf[i*2 + 1] = data2[i+8]; - } - for(i=0;i<16;i++){ - data1[i] = dstregbuf[i]; - } - TRACEOUT(("SSE2_PUNPCKHBW")); -} -void SSE2_PUNPCKHWD(void) -{ - UINT16 data2buf[8]; - UINT16 *data1; - UINT16 *data2; - UINT16 dstregbuf[8]; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - - for(i=0;i<4;i++){ - dstregbuf[i*2] = data1[i+4]; - dstregbuf[i*2 + 1] = data2[i+4]; - } - for(i=0;i<8;i++){ - data1[i] = dstregbuf[i]; - } - TRACEOUT(("SSE2_PUNPCKHWD")); -} -void SSE2_PUNPCKHDQ(void) -{ - UINT32 data2buf[4]; - UINT32 *data1; - UINT32 *data2; - UINT32 dstregbuf[4]; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - - for(i=0;i<2;i++){ - dstregbuf[i*2] = data1[i+2]; - dstregbuf[i*2 + 1] = data2[i+2]; - } - for(i=0;i<4;i++){ - data1[i] = dstregbuf[i]; - } - TRACEOUT(("SSE2_PUNPCKHDQ")); -} -void SSE2_PUNPCKHQDQ(void) -{ - UINT64 data2buf[2]; - UINT64 *data1; - UINT64 *data2; - UINT64 dstregbuf[2]; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - - dstregbuf[0] = data1[1]; - dstregbuf[1] = data2[1]; - data1[0] = dstregbuf[0]; - data1[1] = dstregbuf[1]; - TRACEOUT(("SSE2_PUNPCKHQDQ")); -} -void SSE2_PUNPCKLBW(void) -{ - UINT8 data2buf[16]; - UINT8 *data1; - UINT8 *data2; - UINT8 dstregbuf[16]; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - - for(i=0;i<8;i++){ - dstregbuf[i*2] = data1[i]; - dstregbuf[i*2 + 1] = data2[i]; - } - for(i=0;i<16;i++){ - data1[i] = dstregbuf[i]; - } - TRACEOUT(("SSE2_PUNPCKLBW")); -} -void SSE2_PUNPCKLWD(void) -{ - UINT16 data2buf[8]; - UINT16 *data1; - UINT16 *data2; - UINT16 dstregbuf[8]; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - - for(i=0;i<4;i++){ - dstregbuf[i*2] = data1[i]; - dstregbuf[i*2 + 1] = data2[i]; - } - for(i=0;i<8;i++){ - data1[i] = dstregbuf[i]; - } - TRACEOUT(("SSE2_PUNPCKLWD")); -} -void SSE2_PUNPCKLDQ(void) -{ - UINT32 data2buf[4]; - UINT32 *data1; - UINT32 *data2; - UINT32 dstregbuf[4]; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - - for(i=0;i<2;i++){ - dstregbuf[i*2] = data1[i]; - dstregbuf[i*2 + 1] = data2[i]; - } - for(i=0;i<4;i++){ - data1[i] = dstregbuf[i]; - } - TRACEOUT(("SSE2_PUNPCKLDQ")); -} -void SSE2_PUNPCKLQDQ(void) -{ - UINT64 data2buf[2]; - UINT64 *data1; - UINT64 *data2; - UINT64 dstregbuf[2]; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - - dstregbuf[0] = data1[0]; - dstregbuf[1] = data2[0]; - data1[0] = dstregbuf[0]; - data1[1] = dstregbuf[1]; - TRACEOUT(("SSE2_PUNPCKLQDQ")); -} -void SSE2_PXOR(void) -{ - SSE_XORPS(); - TRACEOUT(("SSE2_PXOR")); -} - -void SSE2_MASKMOVDQU(void) -{ - UINT8 data2buf[16]; - UINT8 *data1, *data2; - int i; - - SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); - for(i=0;i<16;i++){ - if (!CPU_INST_AS32) { - if(data2[i] & 0x80){ - cpu_vmemorywrite(CPU_DS_INDEX, CPU_DI, data1[i]); - } - CPU_DI += 1; - } else { - if(data2[i] & 0x80){ - cpu_vmemorywrite(CPU_DS_INDEX, CPU_EDI, data1[i]); - } - CPU_EDI += 1; - } - } - // 戻す - if (!CPU_INST_AS32) { - CPU_DI -= 16; - } else { - CPU_EDI -= 16; - } - TRACEOUT(("SSE2_MASKMOVDQU")); -} -//void SSE2_CLFLUSH(UINT32 op) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_MOVNTPD(void) -{ - SSE_MOVNTPS(); - TRACEOUT(("SSE2_MOVNTPD")); -} -void SSE2_MOVNTDQ(void) -{ - SSE_MOVNTPS(); - TRACEOUT(("SSE2_MOVNTDQ")); -} -void SSE2_MOVNTI(void) -{ - UINT32 op; - UINT idx, sub; - UINT32 *data1; - - // SSE2なしならUD(無効オペコード例外)を発生させる - if (!(i386cpuid.cpu_feature & CPU_FEATURE_SSE2)) - { - EXCEPTION(UD_EXCEPTION, 0); - } - CPU_SSE2WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - data1 = CPU_REG32_B53(op); // これ合ってる? - if ((op) >= 0xc0) { - EXCEPTION(UD_EXCEPTION, 0); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, maddr, *data1); - } - TRACEOUT(("SSE2_MOVNTI")); -} -void SSE2_PAUSE(void) -{ - // Nothing to do - TRACEOUT(("SSE2_PAUSE")); -} -//void SSE2_LFENCE(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_MFENCE(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} - -#else - -/* - * SSE2 interface - */ - -void SSE2_ADDPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_ADDSD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_ANDNPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_ANDPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CMPPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CMPSD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_COMISD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTPI2PD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTPD2PI(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTSI2SD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTSD2SI(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTTPD2PI(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTTSD2SI(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTPD2PS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTPS2PD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTSD2SS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTSS2SD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTPD2DQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTTPD2DQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTDQ2PD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTPS2DQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTTPS2DQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_CVTDQ2PS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_DIVPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_DIVSD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MAXPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MAXSD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MINPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MINSD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVAPDmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVAPDxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVHPDmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVHPDxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVLPDmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVLPDxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVMSKPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVSDmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVSDxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVUPDmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVUPDxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MULPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MULSD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_ORPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_SHUFPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_SQRTPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_SQRTSD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_STMXCSR(UINT32 maddr) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_SUBPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_SUBSD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_UCOMISD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_UNPCKHPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_UNPCKLPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_XORPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void SSE2_MOVDrm2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVDxmm2rm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVDQAmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVDQAxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVDQUmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVDQUxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVQ2DQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVDQ2Q(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVQmem2xmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVQxmm2mem(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PACKSSDW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PACKSSWB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PACKUSWB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PADDQmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PADDQxmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PADDB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PADDW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PADDD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PADDQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PADDSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PADDSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PADDSD(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PADDSQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PADDUSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PADDUSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PADDUSD(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PADDUSQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PAND(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PANDN(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PAVGB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PAVGW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PCMPEQB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PCMPEQW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PCMPEQD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PCMPEQQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PCMPGTB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PCMPGTW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PCMPGTD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PCMPGTQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PEXTRW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PINSRW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PMADD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PMAXSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PMAXUB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PMINSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PMINUB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PMOVMSKB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PMULHUW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PMULHW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PMULLW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PMULUDQmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PMULUDQxmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_POR(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSADBW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSHUFLW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSHUFHW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSHUFD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSLLDQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PSLLB(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSLLW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSLLD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSLLQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PSLLBimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSLLWimm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSLLDimm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSLLQimm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PSRAB(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSRAW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSRAD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSRAQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PSRABimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSRAWimm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSRADimm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSRAQimm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSRLDQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PSRLB(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSRLW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSRLD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSRLQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PSRLBimm(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSRLWimm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSRLDimm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSRLQimm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSUBQmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSUBQxmm(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSUBB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSUBW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSUBD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PSUBQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSUBSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSUBSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PSUBSD(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSUBSQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PSUBUSB(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PSUBUSW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_PSUBUSD(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_PSUBUSQ(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_PUNPCKHBW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PUNPCKHWD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PUNPCKHDQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PUNPCKHQDQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PUNPCKLBW(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PUNPCKLWD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PUNPCKLDQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PUNPCKLQDQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PXOR(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void SSE2_MASKMOVDQU(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_CLFLUSH(UINT32 op) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE2_MOVNTPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVNTDQ(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_MOVNTI(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE2_PAUSE(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -//void SSE2_LFENCE(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -//void SSE2_MFENCE(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} - - +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include + +#if 0 +#undef TRACEOUT +#define USE_TRACEOUT_VS +//#define MEM_BDA_TRACEOUT +//#define MEM_D8_TRACEOUT +#ifdef USE_TRACEOUT_VS +static void trace_fmt_ex(const char *fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "\n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#else +#define TRACEOUT(s) (void)(s) +#endif +#endif /* 1 */ + +#include +#include + +#if defined(_WIN32) && !defined(__LIBRETRO__) +#define isnan(x) (_isnan(x)) +#endif + +#include +#include "ia32/ia32.mcr" + +#include "ia32/instructions/sse/sse.h" +#include "ia32/instructions/sse2/sse2.h" + +#if defined(USE_SSE2) && defined(USE_SSE) && defined(USE_FPU) + +#define CPU_SSE2WORKCLOCK CPU_WORKCLOCK(2) + +static INLINE void +SSE2_check_NM_EXCEPTION(){ + // SSE2なしならUD(無効オペコード例外)を発生させる + if(!(i386cpuid.cpu_feature & CPU_FEATURE_SSE2)){ + EXCEPTION(UD_EXCEPTION, 0); + } + // エミュレーションならUD(無効オペコード例外)を発生させる + if(CPU_CR0 & CPU_CR0_EM){ + EXCEPTION(UD_EXCEPTION, 0); + } + // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる + if (CPU_CR0 & CPU_CR0_TS) { + EXCEPTION(NM_EXCEPTION, 0); + } +} + +static INLINE void +SSE2_setTag(void) +{ +} + +// mmx.cのものと同じ +static INLINE void +MMX_setTag(void) +{ + int i; + + if(!FPU_STAT.mmxenable){ + FPU_STAT.mmxenable = 1; + //FPU_CTRLWORD = 0x27F; + for (i = 0; i < FPU_REG_NUM; i++) { + FPU_STAT.tag[i] = TAG_Valid; +#ifdef SUPPORT_FPU_DOSBOX2 + FPU_STAT.int_regvalid[i] = 0; +#endif + FPU_STAT.reg[i].ul.ext = 0xffff; + } + } + FPU_STAT_TOP = 0; + FPU_STATUSWORD &= ~0x3800; + FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; +} + +float SSE2_ROUND_FLOAT(float val){ + return SSE_ROUND(val); +} +double SSE2_ROUND_DOUBLE(double val){ + double floorval; + int rndbit = (SSE_MXCSR >> 13) & 0x3; + switch(rndbit){ + case 0: + floorval = floor(val); + if (val - floorval > 0.5){ + return (floorval + 1); // 切り上げ + }else if (val - floorval < 0.5){ + return (floorval); // 切り捨て + }else{ + if(floor(floorval / 2) == floorval/2){ + return (floorval); // 偶数 + }else{ + return (floorval+1); // 奇数 + } + } + break; + case 1: + return floor(val); + case 2: + return ceil(val); + case 3: + if(val < 0){ + return ceil(val); // ゼロ方向への切り捨て + }else{ + return floor(val); // ゼロ方向への切り捨て + } + break; + default: + return val; + } +} + +/* + * SSE2 interface + */ + +// コードが長くなるのでやや強引に共通化 +// xmm/m128 -> xmm +static INLINE void SSE_PART_GETDATA1DATA2_PD(double **data1, double **data2, double *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); + *((UINT64*)(data2buf+ 1)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 8); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_P_UINT32(UINT32 **data1, UINT32 **data2, UINT32 *data2buf){ + SSE_PART_GETDATA1DATA2_PD((double**)data1, (double**)data2, (double*)data2buf); +} +static INLINE void SSE_PART_GETDATA1DATA2_PD_UINT64(UINT64 **data1, UINT64 **data2, UINT64 *data2buf){ + SSE_PART_GETDATA1DATA2_PD((double**)data1, (double**)data2, (double*)data2buf); +} +static INLINE void SSE_PART_GETDATA1DATA2_SD(double **data1, double **data2, double *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_S_UINT32(UINT32 **data1, UINT32 **data2, UINT32 *data2buf){ + SSE_PART_GETDATA1DATA2_SD((double**)data1, (double**)data2, (double*)data2buf); +} +static INLINE void SSE_PART_GETDATA1DATA2_SD_UINT64(UINT64 **data1, UINT64 **data2, UINT64 *data2buf){ + SSE_PART_GETDATA1DATA2_SD((double**)data1, (double**)data2, (double*)data2buf); +} +// xmm/m64 -> xmm +static INLINE void SSE_PART_GETDATA1DATA2_PDm64(double **data1, float **data2, float *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *((UINT32*)(data2buf+ 1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_SDm64(double **data1, float **data2, float *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (float*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *data2 = data2buf; + } +} + +// mm/m128 -> xmm +static INLINE void SSE_PART_GETDATA1DATA2_PD_MMX2XMM(double **data1, SINT32 **data2, SINT32 *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + MMX_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (SINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *((UINT32*)(data2buf+ 1)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 4); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_SD_MMX2XMM(double **data1, SINT32 **data2, SINT32 *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + MMX_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (SINT32*)(&(FPU_STAT.reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *data2 = data2buf; + } +} +// xmm/m128 -> mm +static INLINE void SSE_PART_GETDATA1DATA2_PD_XMM2MMX(SINT32 **data1, double **data2, double *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + MMX_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (SINT32*)(&(FPU_STAT.reg[idx])); + if ((op) >= 0xc0) { + *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); + *((UINT64*)(data2buf+ 1)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 8); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_SD_XMM2MMX(SINT32 **data1, double **data2, double *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + MMX_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (SINT32*)(&(FPU_STAT.reg[idx])); + if ((op) >= 0xc0) { + *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); + *data2 = data2buf; + } +} + +// reg/m32 -> xmm +static INLINE void SSE_PART_GETDATA1DATA2_SD_REG2XMM(double **data1, SINT32 **data2, SINT32 *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (SINT32*)CPU_REG32_B20(op); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT32*)(data2buf+ 0)) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr+ 0); + *data2 = data2buf; + } +} +static INLINE void SSE_PART_GETDATA1DATA2_SD_XMM2REG(SINT32 **data1, double **data2, double *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (SINT32*)CPU_REG32_B53(op); + if ((op) >= 0xc0) { + *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); + *data2 = data2buf; + } +} + +void SSE2_ADDPD(void) +{ + double data2buf[2]; + double *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + data1[i] = data1[i] + data2[i]; + } + TRACEOUT(("SSE2_ADDPD")); +} +void SSE2_ADDSD(void) +{ + double data2buf[2]; + double *data1, *data2; + + SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); + data1[0] = data1[0] + data2[0]; + TRACEOUT(("SSE2_ADDSD")); +} +void SSE2_ANDNPD(void) +{ + SSE_ANDNPS(); + TRACEOUT(("SSE2_ANDNPD")); +} +void SSE2_ANDPD(void) +{ + SSE_ANDPS(); + TRACEOUT(("SSE2_ANDPD")); +} +void SSE2_CMPPD(void) +{ + UINT32 idx; + double data2buf[2]; + double *data1, *data2; + UINT32 *data1ui32; + int i; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + + data1ui32 = (UINT32*)data1; + + GET_MODRM_PCBYTE((idx)); + switch(idx){ + case 0: // CMPEQPS + for(i=0;i<2;i++){ + data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] == data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 1: // CMPLTPS + for(i=0;i<2;i++){ + data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] < data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 2: // CMPLEPS + for(i=0;i<2;i++){ + data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] <= data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 3: // CMPUNORDPS + for(i=0;i<2;i++){ + data1ui32[i*2+0] = data1ui32[i*2+1] = (isnan(data1[i]) || isnan(data2[i]) ? 0xffffffff : 0x00000000); + } + break; + case 4: // CMPNEQPS + for(i=0;i<2;i++){ + data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] != data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 5: // CMPNLTPS + for(i=0;i<2;i++){ + data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] >= data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 6: // CMPNLEPS + for(i=0;i<2;i++){ + data1ui32[i*2+0] = data1ui32[i*2+1] = (data1[i] > data2[i] ? 0xffffffff : 0x00000000); + } + break; + case 7: // CMPORDPS + for(i=0;i<2;i++){ + data1ui32[i*2+0] = data1ui32[i*2+1] = (!isnan(data1[i]) && !isnan(data2[i]) ? 0xffffffff : 0x00000000); + } + break; + } + TRACEOUT(("SSE2_CMPPD")); +} +void SSE2_CMPSD(void) +{ + UINT32 idx; + double data2buf[2]; + double *data1, *data2; + UINT32 *data1ui32; + + SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); + + data1ui32 = (UINT32*)data1; + + GET_MODRM_PCBYTE((idx)); + switch(idx){ + case 0: // CMPEQSS + data1ui32[0] = data1ui32[1] = (data1[0] == data2[0] ? 0xffffffff : 0x00000000); + break; + case 1: // CMPLTSS + data1ui32[0] = data1ui32[1] = (data1[0] < data2[0] ? 0xffffffff : 0x00000000); + break; + case 2: // CMPLESS + data1ui32[0] = data1ui32[1] = (data1[0] <= data2[0] ? 0xffffffff : 0x00000000); + break; + case 3: // CMPUNORDSS + data1ui32[0] = data1ui32[1] = (isnan(data1[0]) || isnan(data2[0]) ? 0xffffffff : 0x00000000); + break; + case 4: // CMPNEQSS + data1ui32[0] = data1ui32[1] = (data1[0] != data2[0] ? 0xffffffff : 0x00000000); + break; + case 5: // CMPNLTSS + data1ui32[0] = data1ui32[1] = (data1[0] >= data2[0] ? 0xffffffff : 0x00000000); + break; + case 6: // CMPNLESS + data1ui32[0] = data1ui32[1] = (data1[0] > data2[0] ? 0xffffffff : 0x00000000); + break; + case 7: // CMPORDSS + data1ui32[0] = data1ui32[1] = (!isnan(data1[0]) && !isnan(data2[0]) ? 0xffffffff : 0x00000000); + break; + } + TRACEOUT(("SSE2_CMPSD")); +} +void SSE2_COMISD(void) +{ + double data2buf[2]; + double *data1, *data2; + + SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); + + if(isnan(data1[0]) || isnan(data2[0])){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | P_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; + }else if(data1[0] > data2[0]){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; + }else if(data1[0] < data2[0]){ + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | C_FLAG; + }else{ // equal + CPU_FLAGL = (CPU_FLAGL & ~Z_FLAG) | Z_FLAG; + CPU_FLAGL = (CPU_FLAGL & ~P_FLAG) | 0; + CPU_FLAGL = (CPU_FLAGL & ~C_FLAG) | 0; + } + TRACEOUT(("SSE2_COMISD")); +} +void SSE2_CVTPI2PD(void) +{ + SINT32 data2buf[2]; + double *data1; + SINT32 *data2; + + SSE_PART_GETDATA1DATA2_PD_MMX2XMM(&data1, &data2, data2buf); + + data1[0] = (double)data2[0]; + data1[1] = (double)data2[1]; + TRACEOUT(("SSE2_CVTPI2PD")); +} +void SSE2_CVTPD2PI(void) +{ + double data2buf[2]; + SINT32 *data1; + double *data2; + + SSE_PART_GETDATA1DATA2_PD_XMM2MMX(&data1, &data2, data2buf); + + data1[0] = (SINT32)SSE2_ROUND_DOUBLE(data2[0]); + data1[1] = (SINT32)SSE2_ROUND_DOUBLE(data2[1]); + TRACEOUT(("SSE2_CVTPD2PI")); +} +void SSE2_CVTSI2SD(void) +{ + SINT32 data2buf[2]; + double *data1; + SINT32 *data2; + + SSE_PART_GETDATA1DATA2_SD_REG2XMM(&data1, &data2, data2buf); + + data1[0] = (double)data2[0]; + TRACEOUT(("SSE2_CVTSI2SD")); +} +void SSE2_CVTSD2SI(void) +{ + double data2buf[2]; + SINT32 *data1; + double *data2; + + SSE_PART_GETDATA1DATA2_SD_XMM2REG(&data1, &data2, data2buf); + + data1[0] = (SINT32)SSE2_ROUND_DOUBLE(data2[0]); + TRACEOUT(("SSE2_CVTSD2SI")); +} +void SSE2_CVTTPD2PI(void) +{ + double data2buf[2]; + SINT32 *data1; + double *data2; + + SSE_PART_GETDATA1DATA2_PD_XMM2MMX(&data1, &data2, data2buf); + + data1[0] = (SINT32)(data2[0]); + data1[1] = (SINT32)(data2[1]); + TRACEOUT(("SSE2_CVTTPD2PI")); +} +void SSE2_CVTTSD2SI(void) +{ + double data2buf[2]; + SINT32 *data1; + double *data2; + + SSE_PART_GETDATA1DATA2_SD_XMM2REG(&data1, &data2, data2buf); + + data1[0] = (SINT32)(data2[0]); + TRACEOUT(("SSE2_CVTTSD2SI")); +} +void SSE2_CVTPD2PS(void) +{ + double data2buf[2]; + float *data1; + double *data2; + + SSE_PART_GETDATA1DATA2_PD((double**)(&data1), &data2, data2buf); + + data1[0] = (float)(data2[0]); + data1[1] = (float)(data2[1]); + data1[2] = data1[3] = 0; + TRACEOUT(("SSE2_CVTPD2PS")); +} +void SSE2_CVTPS2PD(void) +{ + float data2buf[2]; + double *data1; + float *data2; + + SSE_PART_GETDATA1DATA2_PDm64(&data1, &data2, data2buf); + + data1[0] = (double)(data2[0]); + data1[1] = (double)(data2[1]); + TRACEOUT(("SSE2_CVTPS2PD")); +} +void SSE2_CVTSD2SS(void) +{ + double data2buf[2]; + float *data1; + double *data2; + + SSE_PART_GETDATA1DATA2_SD((double**)(&data1), &data2, data2buf); + + data1[0] = (float)(data2[0]); + TRACEOUT(("SSE2_CVTSD2SS")); +} +void SSE2_CVTSS2SD(void) +{ + float data2buf[2]; + double *data1; + float *data2; + + SSE_PART_GETDATA1DATA2_SDm64(&data1, &data2, data2buf); + + data1[0] = (double)(data2[0]); + TRACEOUT(("SSE2_CVTSS2SD")); +} +void SSE2_CVTPD2DQ(void) +{ + double data2buf[2]; + SINT32 *data1; + double *data2; + + SSE_PART_GETDATA1DATA2_PD((double**)(&data1), &data2, data2buf); + + data1[0] = (SINT32)SSE2_ROUND_DOUBLE(data2[0]); + data1[1] = (SINT32)SSE2_ROUND_DOUBLE(data2[1]); + data1[2] = data1[3] = 0; + TRACEOUT(("SSE2_CVTPD2DQ")); +} +void SSE2_CVTTPD2DQ(void) +{ + double data2buf[2]; + SINT32 *data1; + double *data2; + + SSE_PART_GETDATA1DATA2_PD((double**)(&data1), &data2, data2buf); + + data1[0] = (SINT32)(data2[0]); + data1[1] = (SINT32)(data2[1]); + data1[2] = data1[3] = 0; + TRACEOUT(("SSE2_CVTTPD2DQ")); +} +void SSE2_CVTDQ2PD(void) +{ + SINT32 data2buf[2]; + double *data1; + SINT32 *data2; + + SSE_PART_GETDATA1DATA2_PDm64(&data1, (float**)(&data2), (float*)data2buf); + + data1[0] = (double)(data2[0]); + data1[1] = (double)(data2[1]); + TRACEOUT(("SSE2_CVTDQ2PD")); +} +void SSE2_CVTPS2DQ(void) +{ + float data2buf[4]; + SINT32 *data1; + float *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); + + for(i=0;i<4;i++){ + data1[i] = (SINT32)SSE2_ROUND_FLOAT(data2[i]); + } + TRACEOUT(("SSE2_CVTPS2DQ")); +} +void SSE2_CVTTPS2DQ(void) +{ + float data2buf[4]; + SINT32 *data1; + float *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); + + for(i=0;i<4;i++){ + data1[i] = (SINT32)(data2[i]); + } + TRACEOUT(("SSE2_CVTTPS2DQ")); +} +void SSE2_CVTDQ2PS(void) +{ + SINT32 data2buf[4]; + float *data1; + SINT32 *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); + + for(i=0;i<4;i++){ + data1[i] = (float)(data2[i]); + } + TRACEOUT(("SSE2_CVTDQ2PS")); +} +void SSE2_DIVPD(void) +{ + double data2buf[2]; + double *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + data1[i] = data1[i] / data2[i]; + } + TRACEOUT(("SSE2_DIVPD")); +} +void SSE2_DIVSD(void) +{ + double data2buf[2]; + double *data1, *data2; + + SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); + data1[0] = data1[0] / data2[0]; + TRACEOUT(("SSE2_DIVSD")); +} +void SSE2_MAXPD(void) +{ + double data2buf[2]; + double *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + if(isnan(data1[i]) || isnan(data2[i])){ + data1[i] = data2[i]; + }else{ + data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); + } + } + TRACEOUT(("SSE2_MAXPD")); +} +void SSE2_MAXSD(void) +{ + double data2buf[2]; + double *data1, *data2; + + SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); + if(isnan(data1[0]) || isnan(data2[0])){ + data1[0] = data2[0]; + }else{ + data1[0] = (data1[0] > data2[0] ? data1[0] : data2[0]); + } + TRACEOUT(("SSE2_MAXSD")); +} +void SSE2_MINPD(void) +{ + double data2buf[2]; + double *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + if(isnan(data1[i]) || isnan(data2[i])){ + data1[i] = data2[i]; + }else{ + data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); + } + } + TRACEOUT(("SSE2_MINPD")); +} +void SSE2_MINSD(void) +{ + double data2buf[2]; + double *data1, *data2; + + SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); + if(isnan(data1[0]) || isnan(data2[0])){ + data1[0] = data2[0]; + }else{ + data1[0] = (data1[0] < data2[0] ? data1[0] : data2[0]); + } + TRACEOUT(("SSE2_MINSD")); +} +void SSE2_MOVAPDmem2xmm(void) +{ + SSE_MOVAPSmem2xmm(); + TRACEOUT(("SSE2_MOVAPDmem2xmm")); +} +void SSE2_MOVAPDxmm2mem(void) +{ + SSE_MOVAPSxmm2mem(); + TRACEOUT(("SSE2_MOVAPDxmm2mem")); +} +void SSE2_MOVHPDmem2xmm(void) +{ + SSE_MOVHPSmem2xmm(); + TRACEOUT(("SSE2_MOVHPDmem2xmm")); +} +void SSE2_MOVHPDxmm2mem(void) +{ + SSE_MOVHPSxmm2mem(); + TRACEOUT(("SSE2_MOVHPDxmm2mem")); +} +void SSE2_MOVLPDmem2xmm(void) +{ + SSE_MOVLPSmem2xmm(); + TRACEOUT(("SSE2_MOVLPDmem2xmm")); +} +void SSE2_MOVLPDxmm2mem(void) +{ + SSE_MOVLPSxmm2mem(); + TRACEOUT(("SSE2_MOVLPDxmm2mem")); +} +void SSE2_MOVMSKPD(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 *data1; + UINT32 *data2; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = CPU_REG32_B53(op); + if ((op) >= 0xc0) { + data2 = (UINT32*)(&(FPU_STAT.xmm_reg[sub])); + } else { + EXCEPTION(UD_EXCEPTION, 0); + } + *data1 = ((data2[1] >> 31) & 0x1)| + ((data2[3] >> 30) & 0x2); + TRACEOUT(("SSE2_MOVMSKPD")); +} +void SSE2_MOVSDmem2xmm(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG data2buf; + double *data1, *data2; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + data2buf.q[0] = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); + data2 = data2buf.f64; + *(UINT64*)(data1+1) = 0; + } + data1[0] = data2[0]; + TRACEOUT(("SSE2_MOVSDmem2xmm")); +} +void SSE2_MOVSDxmm2mem(void) +{ + UINT32 op; + UINT idx, sub; + double *data1, *data2; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); + data2[0] = data1[0]; + } else { + UINT32 madr; + madr = calc_ea_dst(op); + cpu_vmemorywrite_q(CPU_INST_SEGREG_INDEX, madr+ 0, *((UINT64*)(data1+ 0))); + } + TRACEOUT(("SSE2_MOVSDxmm2mem")); +} +void SSE2_MOVUPDmem2xmm(void) +{ + SSE2_MOVAPDmem2xmm(); // エミュレーションではアライメント制限がないのでMOVAPDと同じ + TRACEOUT(("SSE2_MOVUPDmem2xmm")); +} +void SSE2_MOVUPDxmm2mem(void) +{ + SSE2_MOVAPDxmm2mem(); // エミュレーションではアライメント制限がないのでMOVAPDと同じ + TRACEOUT(("SSE2_MOVUPDxmm2mem")); +} +void SSE2_MULPD(void) +{ + double data2buf[2]; + double *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + data1[i] = data1[i] * data2[i]; + } + TRACEOUT(("SSE2_MULPD")); +} +void SSE2_MULSD(void) +{ + double data2buf[2]; + double *data1, *data2; + + SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); + data1[0] = data1[0] * data2[0]; + TRACEOUT(("SSE2_MULSD")); +} +void SSE2_ORPD(void) +{ + SSE_ORPS(); + TRACEOUT(("SSE2_ORPD")); +} +void SSE2_SHUFPD(void) +{ + UINT32 imm8; + double data2buf[2]; + double data1buf[2]; + double *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + + GET_MODRM_PCBYTE((imm8)); + + for(i=0;i<2;i++){ + data1buf[i] = data1[i]; + } + data1[0] = data1buf[imm8 & 0x1]; + imm8 = (imm8 >> 1); + data1[1] = data2[imm8 & 0x1]; + TRACEOUT(("SSE2_SHUFPD")); +} +void SSE2_SQRTPD(void) +{ + double data2buf[2]; + double *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + data1[i] = sqrt(data2[i]); + } + TRACEOUT(("SSE2_SQRTPD")); +} +void SSE2_SQRTSD(void) +{ + double data2buf[2]; + double *data1, *data2; + + SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); + data1[0] = sqrt(data2[0]); + TRACEOUT(("SSE2_SQRTSD")); +} +//void SSE2_STMXCSR(UINT32 maddr) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_SUBPD(void) +{ + double data2buf[2]; + double *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + data1[i] = data1[i] - data2[i]; + } + TRACEOUT(("SSE2_SUBPD")); +} +void SSE2_SUBSD(void) +{ + double data2buf[2]; + double *data1, *data2; + + SSE_PART_GETDATA1DATA2_SD(&data1, &data2, data2buf); + data1[0] = data1[0] - data2[0]; + TRACEOUT(("SSE2_SUBSD")); +} +void SSE2_UCOMISD(void) +{ + SSE_COMISS(); // XXX: とりあえず例外は考えないのでCOMISSと同じ + TRACEOUT(("SSE2_UCOMISD")); +} +void SSE2_UNPCKHPD(void) +{ + double data1buf[2]; + double data2buf[2]; + double *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + data1buf[i] = data1[i]; + } + data1[0] = data1buf[1]; + data1[1] = data2[1]; + TRACEOUT(("SSE2_UNPCKHPD")); +} +void SSE2_UNPCKLPD(void) +{ + double data1buf[2]; + double data2buf[2]; + double *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + data1buf[i] = data1[i]; + } + data1[0] = data1buf[0]; + data1[1] = data2[0]; + TRACEOUT(("SSE2_UNPCKLPD")); +} +void SSE2_XORPD(void) +{ + SSE_XORPS(); + TRACEOUT(("SSE2_XORPD")); +} + +void SSE2_MOVDrm2xmm(void) +{ + UINT32 op, src; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + (src) = *(CPU_REG32_B20(op)); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + (src) = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + } + FPU_STAT.xmm_reg[idx].ul32[0] = src; + FPU_STAT.xmm_reg[idx].ul32[1] = FPU_STAT.xmm_reg[idx].ul32[2] = FPU_STAT.xmm_reg[idx].ul32[3] = 0; + TRACEOUT(("SSE2_MOVDrm2xmm")); +} +void SSE2_MOVDxmm2rm(void) +{ + UINT32 op, src, madr; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + src = FPU_STAT.xmm_reg[idx].ul32[0]; + if (op >= 0xc0) { + *(CPU_REG32_B20(op)) = src; + } else { + madr = calc_ea_dst(op); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr, src); + } + TRACEOUT(("SSE2_MOVDxmm2rm")); +} +void SSE2_MOVDQAmem2xmm(void) +{ + SSE_MOVAPSmem2xmm(); + TRACEOUT(("SSE2_MOVDQAmem2xmm")); +} +void SSE2_MOVDQAxmm2mem(void) +{ + SSE_MOVAPSxmm2mem(); + TRACEOUT(("SSE2_MOVDQAxmm2mem")); +} +void SSE2_MOVDQUmem2xmm(void) +{ + SSE2_MOVDQAmem2xmm(); // エミュレーションではアライメント制限がないのでMOVDQAと同じ + TRACEOUT(("SSE2_MOVDQUmem2xmm")); +} +void SSE2_MOVDQUxmm2mem(void) +{ + SSE2_MOVDQAxmm2mem(); // エミュレーションではアライメント制限がないのでMOVDQAと同じ + TRACEOUT(("SSE2_MOVDQUxmm2mem")); +} +void SSE2_MOVQ2DQ(void) +{ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + MMX_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.xmm_reg[idx].ul64[0] = FPU_STAT.reg[sub].ll; // idxとsubが逆かも。要検証 + FPU_STAT.xmm_reg[idx].ul64[1] = 0; + } else { + EXCEPTION(UD_EXCEPTION, 0); + } + TRACEOUT(("SSE2_MOVQ2DQ")); +} +void SSE2_MOVDQ2Q(void) +{ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + MMX_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.reg[idx].ll = FPU_STAT.xmm_reg[sub].ul64[0]; // idxとsubが逆かも。要検証 + } else { + EXCEPTION(UD_EXCEPTION, 0); + } + TRACEOUT(("SSE2_MOVDQ2Q")); +} +void SSE2_MOVQmem2xmm(void) +{ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.xmm_reg[idx].ul64[0] = FPU_STAT.xmm_reg[sub].ul64[0]; + } else { + UINT32 madr; + madr = calc_ea_dst(op); + FPU_STAT.xmm_reg[idx].ul64[0] = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); + FPU_STAT.xmm_reg[idx].ul64[1] = 0; + } + TRACEOUT(("SSE2_MOVQmem2xmm")); +} +void SSE2_MOVQxmm2mem(void) +{ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.xmm_reg[sub].ul64[0] = FPU_STAT.xmm_reg[idx].ul64[0]; + } else { + UINT32 madr; + madr = calc_ea_dst(op); + cpu_vmemorywrite_q(CPU_INST_SEGREG_INDEX, madr, FPU_STAT.xmm_reg[idx].ul64[0]); + } + TRACEOUT(("SSE2_MOVQxmm2mem")); +} +void SSE2_PACKSSDW(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG srcreg2buf; + INT32 *srcreg1; + INT32 *srcreg2; + INT16 *dstreg; + INT16 dstregbuf[8]; + int i; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg1 = (INT32*)(&(FPU_STAT.xmm_reg[idx])); + srcreg2 = (INT32*)(&(FPU_STAT.xmm_reg[sub])); + dstreg = (INT16*)(&(FPU_STAT.xmm_reg[idx])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcreg2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcreg2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); + srcreg2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); + srcreg1 = (INT32*)(&(FPU_STAT.xmm_reg[idx])); + srcreg2 = srcreg2buf.d; + dstreg = (INT16*)(&(FPU_STAT.xmm_reg[idx])); + } + for(i=0;i<4;i++){ + if(srcreg1[i] > 32767){ + dstregbuf[i] = 32767; + }else if(srcreg1[i] < -32768){ + dstregbuf[i] = -32768; + }else{ + dstregbuf[i] = (INT16)(srcreg1[i]); + } + } + for(i=0;i<4;i++){ + if(srcreg2[i] > 32767){ + dstregbuf[i+4] = 32767; + }else if(srcreg2[i] < -32768){ + dstregbuf[i+4] = -32768; + }else{ + dstregbuf[i+4] = (INT16)(srcreg2[i]); + } + } + for(i=0;i<8;i++){ + dstreg[i] = dstregbuf[i]; + } + TRACEOUT(("SSE2_PACKSSDW")); +} +void SSE2_PACKSSWB(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG srcreg2buf; + INT16 *srcreg1; + INT16 *srcreg2; + INT8 *dstreg; + INT8 dstregbuf[16]; + int i; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg1 = (INT16*)(&(FPU_STAT.xmm_reg[idx])); + srcreg2 = (INT16*)(&(FPU_STAT.xmm_reg[sub])); + dstreg = (INT8*)(&(FPU_STAT.xmm_reg[idx])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcreg2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcreg2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); + srcreg2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); + srcreg1 = (INT16*)(&(FPU_STAT.xmm_reg[idx])); + srcreg2 = srcreg2buf.w; + dstreg = (INT8*)(&(FPU_STAT.xmm_reg[idx])); + } + for(i=0;i<8;i++){ + if(srcreg1[i] > 127){ + dstregbuf[i] = 127; + }else if(srcreg1[i] < -128){ + dstregbuf[i] = -128; + }else{ + dstregbuf[i] = (INT8)(srcreg1[i]); + } + } + for(i=0;i<8;i++){ + if(srcreg2[i] > 127){ + dstregbuf[i+8] = 127; + }else if(srcreg2[i] < -128){ + dstregbuf[i+8] = -128; + }else{ + dstregbuf[i+8] = (INT8)(srcreg2[i]); + } + } + for(i=0;i<16;i++){ + dstreg[i] = dstregbuf[i]; + } + TRACEOUT(("SSE2_PACKSSWB")); +} +void SSE2_PACKUSWB(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG srcreg2buf; + INT16 *srcreg1; + INT16 *srcreg2; + UINT8 *dstreg; + UINT8 dstregbuf[16]; + int i; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + srcreg1 = (INT16*)(&(FPU_STAT.xmm_reg[idx])); + srcreg2 = (INT16*)(&(FPU_STAT.xmm_reg[sub])); + dstreg = (UINT8*)(&(FPU_STAT.xmm_reg[idx])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + srcreg2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + srcreg2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + srcreg2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); + srcreg2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); + srcreg1 = (INT16*)(&(FPU_STAT.xmm_reg[idx])); + srcreg2 = srcreg2buf.w; + dstreg = (UINT8*)(&(FPU_STAT.xmm_reg[idx])); + } + for(i=0;i<8;i++){ + if(srcreg1[i] > 255){ + dstregbuf[i] = 255; + }else if(srcreg1[i] < 0){ + dstregbuf[i] = 0; + }else{ + dstregbuf[i] = (UINT8)(srcreg1[i]); + } + } + for(i=0;i<8;i++){ + if(srcreg2[i] > 255){ + dstregbuf[i+8] = 255; + }else if(srcreg2[i] < 0){ + dstregbuf[i+8] = 0; + }else{ + dstregbuf[i+8] = (UINT8)(srcreg2[i]); + } + } + for(i=0;i<16;i++){ + dstreg[i] = dstregbuf[i]; + } + TRACEOUT(("SSE2_PACKUSWB")); +} +void SSE2_PADDQmm(void) +{ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + MMX_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.reg[idx].ll += FPU_STAT.reg[sub].ll; + } else { + UINT32 madr; + madr = calc_ea_dst(op); + FPU_STAT.reg[idx].ll += (SINT64)cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); + } + TRACEOUT(("SSE2_PADDQmm")); +} +void SSE2_PADDQxmm(void) +{ + UINT64 data2buf[2]; + UINT64 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + data1[i] = data1[i] + data2[i]; + } + TRACEOUT(("SSE2_PADDQxmm")); +} +void SSE2_PADDB(void) +{ + UINT8 data2buf[16]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + data1[i] = data1[i] + data2[i]; + } + TRACEOUT(("SSE2_PADDB")); +} +void SSE2_PADDW(void) +{ + UINT16 data2buf[8]; + UINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<8;i++){ + data1[i] = data1[i] + data2[i]; + } + TRACEOUT(("SSE2_PADDW")); +} +void SSE2_PADDD(void) +{ + UINT32 data2buf[4]; + UINT32 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<4;i++){ + data1[i] = data1[i] + data2[i]; + } + TRACEOUT(("SSE2_PADDD")); +} +//void SSE2_PADDQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PADDSB(void) +{ + SINT8 data2buf[16]; + SINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + SINT16 cbuf = (SINT16)data1[i] + (SINT16)data2[i]; + if(cbuf > 127){ + data1[i] = 127; + }else if(cbuf < -128){ + data1[i] = -128; + }else{ + data1[i] = (SINT8)cbuf; + } + } + TRACEOUT(("SSE2_PADDSB")); +} +void SSE2_PADDSW(void) +{ + SINT16 data2buf[8]; + SINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<8;i++){ + SINT32 cbuf = (SINT32)data1[i] + (SINT32)data2[i]; + if(cbuf > 32767){ + data1[i] = 32767; + }else if(cbuf < -32768){ + data1[i] = -32768; + }else{ + data1[i] = (SINT16)cbuf; + } + } + TRACEOUT(("SSE2_PADDSW")); +} +//void SSE2_PADDSD(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PADDSQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PADDUSB(void) +{ + UINT8 data2buf[16]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + UINT16 cbuf = (UINT16)data1[i] + (UINT16)data2[i]; + if(cbuf > 255){ + data1[i] = 255; + }else{ + data1[i] = (UINT8)cbuf; + } + } + TRACEOUT(("SSE2_PADDUSB")); +} +void SSE2_PADDUSW(void) +{ + UINT16 data2buf[8]; + UINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<8;i++){ + UINT32 cbuf = (UINT32)data1[i] + (UINT32)data2[i]; + if(cbuf > 65535){ + data1[i] = 65535; + }else{ + data1[i] = (UINT16)cbuf; + } + } + TRACEOUT(("SSE2_PADDUSW")); +} +//void SSE2_PADDUSD(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PADDUSQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PAND(void) +{ + SSE_ANDPS(); + TRACEOUT(("SSE2_PAND")); +} +void SSE2_PANDN(void) +{ + SSE_ANDNPS(); + TRACEOUT(("SSE2_PANDN")); +} +void SSE2_PAVGB(void) +{ + UINT8 data2buf[16]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + data1[i] = (UINT8)(((UINT16)data1[i] + (UINT16)data2[i] + 1) / 2); + } + TRACEOUT(("SSE2_PAVGB")); +} +void SSE2_PAVGW(void) +{ + UINT16 data2buf[8]; + UINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<8;i++){ + data1[i] = (UINT16)(((UINT32)data1[i] + (UINT32)data2[i] + 1) / 2); + } + TRACEOUT(("SSE2_PAVGW")); +} +void SSE2_PCMPEQB(void) +{ + UINT8 data2buf[16]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + data1[i] = (data1[i] == data2[i] ? 0xff : 0x00); + } + TRACEOUT(("SSE2_PCMPEQB")); +} +void SSE2_PCMPEQW(void) +{ + UINT16 data2buf[8]; + UINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<8;i++){ + data1[i] = (data1[i] == data2[i] ? 0xffff : 0x00); + } + TRACEOUT(("SSE2_PCMPEQW")); +} +void SSE2_PCMPEQD(void) +{ + UINT32 data2buf[4]; + UINT32 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<4;i++){ + data1[i] = (data1[i] == data2[i] ? 0xffffffff : 0x00); + } + TRACEOUT(("SSE2_PCMPEQD")); +} +//void SSE2_PCMPEQQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PCMPGTB(void) +{ + SINT8 data2buf[16]; + SINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + data1[i] = (data1[i] > data2[i] ? 0xff : 0x00); + } + TRACEOUT(("SSE2_PCMPGTB")); +} +void SSE2_PCMPGTW(void) +{ + SINT16 data2buf[8]; + SINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<8;i++){ + data1[i] = (data1[i] > data2[i] ? 0xffff : 0x00); + } + TRACEOUT(("SSE2_PCMPGTW")); +} +void SSE2_PCMPGTD(void) +{ + SINT32 data2buf[4]; + SINT32 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<4;i++){ + data1[i] = (data1[i] > data2[i] ? 0xffffffff : 0x00); + } + TRACEOUT(("SSE2_PCMPGTD")); +} +//void SSE2_PCMPGTQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PEXTRW(void) +{ + UINT32 imm8; + UINT32 op; + UINT idx, sub; + UINT32 *data1; + UINT16 *data2; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (UINT32*)CPU_REG32_B53(op); + if ((op) >= 0xc0) { + data2 = (UINT16*)(&(FPU_STAT.xmm_reg[sub])); + } else { + EXCEPTION(UD_EXCEPTION, 0); + } + GET_MODRM_PCBYTE((imm8)); + *data1 = (UINT32)data2[imm8 & 0x7]; + TRACEOUT(("SSE2_PEXTRW")); +} +void SSE2_PINSRW(void) +{ + UINT32 imm8; + UINT32 op; + UINT idx, sub; + UINT16 *data1; + UINT16 data2; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (UINT16*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (UINT16)((*CPU_REG32_B20(op)) & 0xffff); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + data2 = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, maddr+ 0); + } + GET_MODRM_PCBYTE((imm8)); + data1[imm8 & 0x7] = data2; + TRACEOUT(("SSE2_PINSRW")); +} +void SSE2_PMADD(void) +{ + SINT16 data2buf[8]; + SINT16 *data1, *data2; + SINT32 data1dbuf[4]; + SINT32 *data1d; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + data1d = (SINT32*)data1; + + data1dbuf[0] = (INT32)data2[0] * (INT32)data1[0] + (INT32)data2[1] * (INT32)data1[1]; + data1dbuf[1] = (INT32)data2[2] * (INT32)data1[2] + (INT32)data2[3] * (INT32)data1[3]; + data1dbuf[2] = (INT32)data2[4] * (INT32)data1[4] + (INT32)data2[5] * (INT32)data1[5]; + data1dbuf[3] = (INT32)data2[6] * (INT32)data1[6] + (INT32)data2[7] * (INT32)data1[7]; + data1d[0] = data1dbuf[0]; + data1d[1] = data1dbuf[1]; + data1d[2] = data1dbuf[2]; + data1d[3] = data1dbuf[3]; + TRACEOUT(("SSE2_PMADD")); +} +void SSE2_PMAXSW(void) +{ + SINT16 data2buf[8]; + SINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<8;i++){ + data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); + } + TRACEOUT(("SSE2_PMAXSW")); +} +void SSE2_PMAXUB(void) +{ + UINT8 data2buf[16]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + data1[i] = (data1[i] > data2[i] ? data1[i] : data2[i]); + } + TRACEOUT(("SSE2_PMAXUB")); +} +void SSE2_PMINSW(void) +{ + SINT16 data2buf[8]; + SINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<8;i++){ + data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); + } + TRACEOUT(("SSE2_PMINSW")); +} +void SSE2_PMINUB(void) +{ + UINT8 data2buf[16]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + data1[i] = (data1[i] < data2[i] ? data1[i] : data2[i]); + } + TRACEOUT(("SSE2_PMINUB")); +} +void SSE2_PMOVMSKB(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 *data1; + UINT8 *data2; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (UINT32*)CPU_REG32_B53(op); + if ((op) >= 0xc0) { + data2 = (UINT8*)(&(FPU_STAT.reg[sub])); + } else { + EXCEPTION(UD_EXCEPTION, 0); + } + *data1 = ((UINT32)(data2[0] >> 7) & 0x1 )| + ((UINT32)(data2[1] >> 6) & 0x2 )| + ((UINT32)(data2[2] >> 5) & 0x4 )| + ((UINT32)(data2[3] >> 4) & 0x8 )| + ((UINT32)(data2[4] >> 3) & 0x10)| + ((UINT32)(data2[5] >> 2) & 0x20)| + ((UINT32)(data2[6] >> 1) & 0x40)| + ((UINT32)(data2[7] >> 0) & 0x80)| + (((UINT32)(data2[8] >> 7) & 0x1 ) << 8)| + (((UINT32)(data2[9] >> 6) & 0x2 ) << 8)| + (((UINT32)(data2[10]>> 5) & 0x4 ) << 8)| + (((UINT32)(data2[11]>> 4) & 0x8 ) << 8)| + (((UINT32)(data2[12]>> 3) & 0x10) << 8)| + (((UINT32)(data2[13]>> 2) & 0x20) << 8)| + (((UINT32)(data2[14]>> 1) & 0x40) << 8)| + (((UINT32)(data2[15]>> 0) & 0x80) << 8); + TRACEOUT(("SSE2_PMOVMSKB")); +} +void SSE2_PMULHUW(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG data2buf; + UINT16 *data1, *data2; + int i; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (UINT16*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (UINT16*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + data2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); + data2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); + data2 = data2buf.w; + } + for(i=0;i<8;i++){ + data1[i] = (UINT16)((((UINT32)data2[i] * (UINT32)data1[i]) >> 16) & 0xffff); + } + TRACEOUT(("SSE2_PMULHUW")); +} +void SSE2_PMULHW(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG data2buf; + SINT16 *data1, *data2; + int i; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (SINT16*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (SINT16*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + data2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); + data2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); + data2 = data2buf.w; + } + for(i=0;i<8;i++){ + data1[i] = (SINT16)((((SINT32)data2[i] * (SINT32)data1[i]) >> 16) & 0xffff); + } + TRACEOUT(("SSE2_PMULHW")); +} +void SSE2_PMULLW(void) +{ + UINT32 op; + UINT idx, sub; + SSEREG data2buf; + SINT16 *data1, *data2; + int i; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = (SINT16*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + data2 = (SINT16*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + data2buf.d[0] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr); + data2buf.d[1] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 4); + data2buf.d[2] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 8); + data2buf.d[3] = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, maddr + 12); + data2 = data2buf.w; + } + for(i=0;i<8;i++){ + data1[i] = (SINT16)((((SINT32)data2[i] * (SINT32)data1[i])) & 0xffff); + } + TRACEOUT(("SSE2_PMULLW")); +} +void SSE2_PMULUDQmm(void) +{ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + MMX_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.reg[idx].ll = ((UINT64)FPU_STAT.reg[idx].l.lower * (UINT64)FPU_STAT.reg[sub].l.lower); + } else { + UINT32 madr; + madr = calc_ea_dst(op); + FPU_STAT.reg[idx].ll = ((UINT64)FPU_STAT.reg[idx].l.lower * (cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr) & 0xffffffff)); + } + TRACEOUT(("SSE2_PMULUDQmm")); +} +void SSE2_PMULUDQxmm(void) +{ + UINT64 data2buf[2]; + UINT64 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + data1[i] = (data1[i] & 0xffffffff) * (data2[i] & 0xffffffff); + } + TRACEOUT(("SSE2_PMULUDQxmm")); +} +void SSE2_POR(void) +{ + SSE_ORPS(); + TRACEOUT(("SSE2_POR")); +} +void SSE2_PSADBW(void) +{ + SINT16 temp1; + UINT16 temp; + UINT8 data2buf[16]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + + temp = 0; + for(i=0;i<8;i++){ + temp1 = (SINT16)data2[i] - (SINT16)data1[i]; + temp += (UINT16)(temp1 < 0 ? -temp1 : temp1); + } + *((UINT16*)data2 + 0) = temp; + *((UINT16*)data2 + 1) = 0; + *((UINT16*)data2 + 2) = 0; + *((UINT16*)data2 + 3) = 0; + + temp = 0; + for(i=8;i<16;i++){ + temp1 = (SINT16)data2[i] - (SINT16)data1[i]; + temp += (UINT16)(temp1 < 0 ? -temp1 : temp1); + } + *((UINT16*)data2 + 4) = temp; + *((UINT16*)data2 + 5) = 0; + *((UINT16*)data2 + 6) = 0; + *((UINT16*)data2 + 7) = 0; + TRACEOUT(("SSE2_PSADBW")); +} +void SSE2_PSHUFLW(void) +{ + UINT32 imm8; + UINT16 data2buf[8]; + UINT16 *data1, *data2; + UINT16 dstbuf[8]; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + GET_MODRM_PCBYTE((imm8)); + for(i=0;i<4;i++){ + dstbuf[i] = data2[imm8 & 0x3]; + imm8 = imm8 >> 2; + } + for(i=0;i<4;i++){ + data1[i] = dstbuf[i]; + } + for(i=4;i<8;i++){ + data1[i] = data2[i]; + } + TRACEOUT(("SSE2_PSHUFLW")); +} +void SSE2_PSHUFHW(void) +{ + UINT32 imm8; + UINT16 data2buf[8]; + UINT16 *data1, *data2; + UINT16 dstbuf[8]; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + GET_MODRM_PCBYTE((imm8)); + for(i=0;i<4;i++){ + data1[i] = data2[i]; + } + for(i=4;i<8;i++){ + dstbuf[i] = data2[4 + (imm8 & 0x3)]; + imm8 = imm8 >> 2; + } + for(i=4;i<8;i++){ + data1[i] = dstbuf[i]; + } + TRACEOUT(("SSE2_PSHUFHW")); +} +void SSE2_PSHUFD(void) +{ + UINT32 imm8; + UINT32 data2buf[4]; + UINT32 *data1, *data2; + UINT32 dstbuf[4]; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + GET_MODRM_PCBYTE((imm8)); + for(i=0;i<4;i++){ + dstbuf[i] = data2[imm8 & 0x3]; + imm8 = imm8 >> 2; + } + for(i=0;i<4;i++){ + data1[i] = dstbuf[i]; + } + TRACEOUT(("SSE2_PSHUFD")); +} +//void SSE2_PSLLDQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSLLB(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSLLW(void) +{ + UINT32 data2buf[4]; + UINT16 *data1; + UINT32 *data2; + UINT32 shift; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + shift = data2[0]; + if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + + for(i=0;i<8;i++){ + data1[i] = (shift >= 16 ? 0 : (data1[i] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } + TRACEOUT(("SSE2_PSLLW")); +} +void SSE2_PSLLD(void) +{ + UINT32 data2buf[4]; + UINT32 *data1; + UINT32 *data2; + UINT32 shift; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + shift = data2[0]; + if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + + for(i=0;i<4;i++){ + data1[i] = (shift >= 32 ? 0 : (data1[i] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } + TRACEOUT(("SSE2_PSLLD")); +} +void SSE2_PSLLQ(void) +{ + UINT32 data2buf[4]; + UINT64 *data1; + UINT32 *data2; + UINT32 shift; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + shift = data2[0]; + if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + + for(i=0;i<2;i++){ + data1[i] = (shift >= 64 ? 0 : (data1[i] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } + TRACEOUT(("SSE2_PSLLQ")); +} +//void SSE2_PSLLBimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSLLWimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSLLDimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSLLQimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSRAB(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSRAW(void) +{ + UINT32 data2buf[4]; + UINT16 *data1; + UINT32 *data2; + UINT32 shift; + UINT16 signval; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + shift = data2[0]; + if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + + // 無理やり算術シフト(怪しい) + if(16 <= shift){ + signval = 0xffff; + }else{ + UINT32 rshift = 16 - shift; + signval = (0xffff >> rshift) << rshift; + } + for(i=0;i<8;i++){ + if(((INT16*)data1)[i] < 0){ + data1[i] = (data1[i] >> shift) | signval; + }else{ + data1[i] = (shift >= 16 ? 0 : (data1[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } + TRACEOUT(("SSE2_PSRAW")); +} +void SSE2_PSRAD(void) +{ + UINT32 data2buf[4]; + UINT32 *data1; + UINT32 *data2; + UINT32 shift; + UINT32 signval; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + shift = data2[0]; + if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + + // 無理やり算術シフト(怪しい) + if(32 <= shift){ + signval = 0xffffffff; + }else{ + UINT32 rshift = 32 - shift; + signval = (0xffffffff >> rshift) << rshift; + } + for(i=0;i<2;i++){ + if(((INT32*)data1)[i] < 0){ + data1[i] = (data1[i] >> shift) | signval; + }else{ + data1[i] = (shift >= 32 ? 0 : (data1[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } + TRACEOUT(("SSE2_PSRAD")); +} +//void SSE2_PSRAQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSRABimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSRAWimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSRADimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSRAQimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSRLDQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSRLB(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSRLW(void) +{ + UINT32 data2buf[4]; + UINT16 *data1; + UINT32 *data2; + UINT32 shift; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + shift = data2[0]; + if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + + for(i=0;i<8;i++){ + data1[i] = (shift >= 16 ? 0 : (data1[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + TRACEOUT(("SSE2_PSRLW")); +} +void SSE2_PSRLD(void) +{ + UINT32 data2buf[4]; + UINT32 *data1; + UINT32 *data2; + UINT32 shift; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + shift = data2[0]; + if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + + for(i=0;i<4;i++){ + data1[i] = (shift >= 32 ? 0 : (data1[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + TRACEOUT(("SSE2_PSRLD")); +} +void SSE2_PSRLQ(void) +{ + UINT32 data2buf[4]; + UINT64 *data1; + UINT32 *data2; + UINT32 shift; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + shift = data2[0]; + if(data2[1] || data2[2] || data2[3]) shift = 0xffffffff; // XXX: とりあえずレジスタ内容が消えるくらい大きなシフト量にしておく + + for(i=0;i<2;i++){ + data1[i] = (shift >= 64 ? 0 : (data1[i] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + TRACEOUT(("SSE2_PSRLQ")); +} +//void SSE2_PSRLBimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSRLWimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSRLDimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSRLQimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSxxWimm(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT16 *dstreg; + UINT16 signval; + int i; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + dstreg = (UINT16*)(&(FPU_STAT.xmm_reg[sub])); + GET_MODRM_PCBYTE((shift)); + + switch(idx){ + case 2: // PSRLW(imm8) + for(i=0;i<8;i++){ + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + break; + case 4: // PSRAW(imm8) + // 無理やり算術シフト(怪しい) + if(16 <= shift){ + signval = 0xffff; + }else{ + UINT32 rshift = 16 - shift; + signval = (0xffff >> rshift) << rshift; + } + for(i=0;i<8;i++){ + if(((INT16*)dstreg)[i] < 0){ + dstreg[i] = (dstreg[i] >> shift) | signval; + }else{ + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } + break; + case 6: // PSLLW(imm8) + for(i=0;i<8;i++){ + dstreg[i] = (shift >= 16 ? 0 : (dstreg[i] << (UINT16)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } + break; + default: + break; + } + TRACEOUT(("SSE2_PSxxWimm")); +} +void SSE2_PSxxDimm(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT32 *dstreg; + UINT32 signval; + int i; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + dstreg = (UINT32*)(&(FPU_STAT.xmm_reg[sub])); + GET_MODRM_PCBYTE((shift)); + + switch(idx){ + case 2: // PSRLD(imm8) + for(i=0;i<4;i++){ + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT32)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + break; + case 4: // PSRAD(imm8) + // 無理やり算術シフト(怪しい) + if(32 <= shift){ + signval = 0xffffffff; + }else{ + UINT32 rshift = 32 - shift; + signval = (0xffffffff >> rshift) << rshift; + } + for(i=0;i<4;i++){ + if(((INT32*)dstreg)[i] < 0){ + dstreg[i] = (dstreg[i] >> shift) | signval; + }else{ + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] >> (UINT16)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + } + break; + case 6: // PSLLD(imm8) + for(i=0;i<4;i++){ + dstreg[i] = (shift >= 32 ? 0 : (dstreg[i] << (UINT32)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } + break; + default: + break; + } + TRACEOUT(("SSE2_PSxxDimm")); +} +void SSE2_PSxxQimm(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 shift; + UINT64 *dstreg; + int i; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + dstreg = (UINT64*)(&(FPU_STAT.xmm_reg[sub])); + GET_MODRM_PCBYTE((shift)); + + switch(idx){ + case 2: // PSRLQ(imm8) + for(i=0;i<2;i++){ + dstreg[i] = (shift >= 64 ? 0 : (dstreg[i] >> (UINT64)shift)); // XXX: LSBが取り残されるのでごまかし(環境依存?) + } + break; + case 3: // PSRLDQ + // 無理やり128bit右シフト 怪しいので要検証 + shift *= 8; // シフト量はバイト数で指定 + if(shift == 0){ + // シフト無しなら何もしない + }else if(shift >= 128){ + // シフトが128以上の時 + dstreg[0] = dstreg[1] = 0; + }else if(shift >= 64){ + // シフトが64以上の時 + dstreg[0] = dstreg[1] >> (shift - 64); + dstreg[1] = 0; + }else{ + // シフトが64より小さい時 + dstreg[0] = (dstreg[0] >> shift) | (dstreg[1] << (64-shift)); // 下位QWORD右シフト&上から降りてきたビットをOR + dstreg[1] = (dstreg[1] >> shift); + } + break; + case 4: // PSRAQ(imm8) + EXCEPTION(UD_EXCEPTION, 0); + break; + case 6: // PSLLQ(imm8) + for(i=0;i<2;i++){ + dstreg[i] = (shift >= 64 ? 0 : (dstreg[i] << (UINT64)shift)); // XXX: MSBが取り残されるのでごまかし(環境依存?) + } + break; + case 7: // PSLLDQ + // 無理やり128bit左シフト 怪しいので要検証 + shift *= 8; // シフト量はバイト数で指定 + if(shift == 0){ + // シフト無しなら何もしない + }else if(shift >= 128){ + // シフトが128以上の時 + dstreg[0] = dstreg[1] = 0; + }else if(shift >= 64){ + // シフトが64以上の時 + dstreg[1] = dstreg[0] << (shift - 64); + dstreg[0] = 0; + }else{ + // シフトが64より小さい時 + dstreg[1] = (dstreg[1] << shift) | (dstreg[0] >> (64-shift)); // 上位QWORD左シフト&下から上がってきたビットをOR + dstreg[0] = (dstreg[0] << shift); + } + break; + default: + break; + } + TRACEOUT(("SSE2_PSxxQimm")); +} +void SSE2_PSUBQmm(void) +{ + UINT32 op; + UINT idx, sub; + + SSE2_check_NM_EXCEPTION(); + SSE2_setTag(); + MMX_setTag(); + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.reg[idx].ll -= FPU_STAT.reg[sub].ll; + } else { + UINT32 madr; + madr = calc_ea_dst(op); + FPU_STAT.reg[idx].ll -= (SINT64)cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); + } + TRACEOUT(("SSE2_PSUBQmm")); +} +void SSE2_PSUBQxmm(void) +{ + UINT64 data2buf[2]; + UINT64 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64(&data1, &data2, data2buf); + for(i=0;i<2;i++){ + data1[i] = data1[i] - data2[i]; + } + TRACEOUT(("SSE2_PSUBQxmm")); +} +void SSE2_PSUBB(void) +{ + UINT8 data2buf[16]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + data1[i] = data1[i] - data2[i]; + } + TRACEOUT(("SSE2_PSUBB")); +} +void SSE2_PSUBW(void) +{ + UINT16 data2buf[8]; + UINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<8;i++){ + data1[i] = data1[i] - data2[i]; + } + TRACEOUT(("SSE2_PSUBW")); +} +void SSE2_PSUBD(void) +{ + UINT32 data2buf[4]; + UINT32 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<4;i++){ + data1[i] = data1[i] - data2[i]; + } + TRACEOUT(("SSE2_PSUBD")); +} +//void SSE2_PSUBQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSUBSB(void) +{ + SINT8 data2buf[16]; + SINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + SINT16 cbuf = (SINT16)data1[i] - (SINT16)data2[i]; + if(cbuf > 127){ + data1[i] = 127; + }else if(cbuf < -128){ + data1[i] = -128; + }else{ + data1[i] = (SINT8)cbuf; + } + } + TRACEOUT(("SSE2_PSUBSB")); +} +void SSE2_PSUBSW(void) +{ + SINT16 data2buf[8]; + SINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<8;i++){ + SINT32 cbuf = (SINT32)data1[i] - (SINT32)data2[i]; + if(cbuf > 32767){ + data1[i] = 32767; + }else if(cbuf < -32768){ + data1[i] = -32768; + }else{ + data1[i] = (SINT16)cbuf; + } + } + TRACEOUT(("SSE2_PSUBSW")); +} +//void SSE2_PSUBSD(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSUBSQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSUBUSB(void) +{ + UINT8 data2buf[16]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + SINT16 cbuf = (SINT16)data1[i] - (SINT16)data2[i]; + if(cbuf > 255){ + data1[i] = 255; + }else if(cbuf < 0){ + data1[i] = 0; + }else{ + data1[i] = (UINT8)cbuf; + } + } + TRACEOUT(("SSE2_PSUBUSB")); +} +void SSE2_PSUBUSW(void) +{ + UINT16 data2buf[8]; + UINT16 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<8;i++){ + SINT32 cbuf = (SINT32)data1[i] - (SINT32)data2[i]; + if(cbuf > 65535){ + data1[i] = 65535; + }else if(cbuf < 0){ + data1[i] = 0; + }else{ + data1[i] = (UINT16)cbuf; + } + } + TRACEOUT(("SSE2_PSUBUSW")); +} +//void SSE2_PSUBUSD(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSUBUSQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PUNPCKHBW(void) +{ + UINT8 data2buf[16]; + UINT8 *data1; + UINT8 *data2; + UINT8 dstregbuf[16]; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + + for(i=0;i<8;i++){ + dstregbuf[i*2] = data1[i+8]; + dstregbuf[i*2 + 1] = data2[i+8]; + } + for(i=0;i<16;i++){ + data1[i] = dstregbuf[i]; + } + TRACEOUT(("SSE2_PUNPCKHBW")); +} +void SSE2_PUNPCKHWD(void) +{ + UINT16 data2buf[8]; + UINT16 *data1; + UINT16 *data2; + UINT16 dstregbuf[8]; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + + for(i=0;i<4;i++){ + dstregbuf[i*2] = data1[i+4]; + dstregbuf[i*2 + 1] = data2[i+4]; + } + for(i=0;i<8;i++){ + data1[i] = dstregbuf[i]; + } + TRACEOUT(("SSE2_PUNPCKHWD")); +} +void SSE2_PUNPCKHDQ(void) +{ + UINT32 data2buf[4]; + UINT32 *data1; + UINT32 *data2; + UINT32 dstregbuf[4]; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + + for(i=0;i<2;i++){ + dstregbuf[i*2] = data1[i+2]; + dstregbuf[i*2 + 1] = data2[i+2]; + } + for(i=0;i<4;i++){ + data1[i] = dstregbuf[i]; + } + TRACEOUT(("SSE2_PUNPCKHDQ")); +} +void SSE2_PUNPCKHQDQ(void) +{ + UINT64 data2buf[2]; + UINT64 *data1; + UINT64 *data2; + UINT64 dstregbuf[2]; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + + dstregbuf[0] = data1[1]; + dstregbuf[1] = data2[1]; + data1[0] = dstregbuf[0]; + data1[1] = dstregbuf[1]; + TRACEOUT(("SSE2_PUNPCKHQDQ")); +} +void SSE2_PUNPCKLBW(void) +{ + UINT8 data2buf[16]; + UINT8 *data1; + UINT8 *data2; + UINT8 dstregbuf[16]; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + + for(i=0;i<8;i++){ + dstregbuf[i*2] = data1[i]; + dstregbuf[i*2 + 1] = data2[i]; + } + for(i=0;i<16;i++){ + data1[i] = dstregbuf[i]; + } + TRACEOUT(("SSE2_PUNPCKLBW")); +} +void SSE2_PUNPCKLWD(void) +{ + UINT16 data2buf[8]; + UINT16 *data1; + UINT16 *data2; + UINT16 dstregbuf[8]; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + + for(i=0;i<4;i++){ + dstregbuf[i*2] = data1[i]; + dstregbuf[i*2 + 1] = data2[i]; + } + for(i=0;i<8;i++){ + data1[i] = dstregbuf[i]; + } + TRACEOUT(("SSE2_PUNPCKLWD")); +} +void SSE2_PUNPCKLDQ(void) +{ + UINT32 data2buf[4]; + UINT32 *data1; + UINT32 *data2; + UINT32 dstregbuf[4]; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + + for(i=0;i<2;i++){ + dstregbuf[i*2] = data1[i]; + dstregbuf[i*2 + 1] = data2[i]; + } + for(i=0;i<4;i++){ + data1[i] = dstregbuf[i]; + } + TRACEOUT(("SSE2_PUNPCKLDQ")); +} +void SSE2_PUNPCKLQDQ(void) +{ + UINT64 data2buf[2]; + UINT64 *data1; + UINT64 *data2; + UINT64 dstregbuf[2]; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + + dstregbuf[0] = data1[0]; + dstregbuf[1] = data2[0]; + data1[0] = dstregbuf[0]; + data1[1] = dstregbuf[1]; + TRACEOUT(("SSE2_PUNPCKLQDQ")); +} +void SSE2_PXOR(void) +{ + SSE_XORPS(); + TRACEOUT(("SSE2_PXOR")); +} + +void SSE2_MASKMOVDQU(void) +{ + UINT8 data2buf[16]; + UINT8 *data1, *data2; + int i; + + SSE_PART_GETDATA1DATA2_PD_UINT64((UINT64**)(&data1), (UINT64**)(&data2), (UINT64*)data2buf); + for(i=0;i<16;i++){ + if (!CPU_INST_AS32) { + if(data2[i] & 0x80){ + cpu_vmemorywrite(CPU_DS_INDEX, CPU_DI, data1[i]); + } + CPU_DI += 1; + } else { + if(data2[i] & 0x80){ + cpu_vmemorywrite(CPU_DS_INDEX, CPU_EDI, data1[i]); + } + CPU_EDI += 1; + } + } + // 戻す + if (!CPU_INST_AS32) { + CPU_DI -= 16; + } else { + CPU_EDI -= 16; + } + TRACEOUT(("SSE2_MASKMOVDQU")); +} +//void SSE2_CLFLUSH(UINT32 op) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_MOVNTPD(void) +{ + SSE_MOVNTPS(); + TRACEOUT(("SSE2_MOVNTPD")); +} +void SSE2_MOVNTDQ(void) +{ + SSE_MOVNTPS(); + TRACEOUT(("SSE2_MOVNTDQ")); +} +void SSE2_MOVNTI(void) +{ + UINT32 op; + UINT idx, sub; + UINT32 *data1; + + // SSE2なしならUD(無効オペコード例外)を発生させる + if (!(i386cpuid.cpu_feature & CPU_FEATURE_SSE2)) + { + EXCEPTION(UD_EXCEPTION, 0); + } + CPU_SSE2WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + data1 = CPU_REG32_B53(op); // これ合ってる? + if ((op) >= 0xc0) { + EXCEPTION(UD_EXCEPTION, 0); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, maddr, *data1); + } + TRACEOUT(("SSE2_MOVNTI")); +} +void SSE2_PAUSE(void) +{ + // Nothing to do + TRACEOUT(("SSE2_PAUSE")); +} +//void SSE2_LFENCE(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_MFENCE(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} + +#else + +/* + * SSE2 interface + */ + +void SSE2_ADDPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_ADDSD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_ANDNPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_ANDPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CMPPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CMPSD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_COMISD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTPI2PD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTPD2PI(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTSI2SD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTSD2SI(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTTPD2PI(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTTSD2SI(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTPD2PS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTPS2PD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTSD2SS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTSS2SD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTPD2DQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTTPD2DQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTDQ2PD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTPS2DQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTTPS2DQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_CVTDQ2PS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_DIVPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_DIVSD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MAXPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MAXSD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MINPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MINSD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVAPDmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVAPDxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVHPDmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVHPDxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVLPDmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVLPDxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVMSKPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVSDmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVSDxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVUPDmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVUPDxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MULPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MULSD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_ORPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_SHUFPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_SQRTPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_SQRTSD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_STMXCSR(UINT32 maddr) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_SUBPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_SUBSD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_UCOMISD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_UNPCKHPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_UNPCKLPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_XORPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void SSE2_MOVDrm2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVDxmm2rm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVDQAmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVDQAxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVDQUmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVDQUxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVQ2DQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVDQ2Q(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVQmem2xmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVQxmm2mem(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PACKSSDW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PACKSSWB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PACKUSWB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PADDQmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PADDQxmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PADDB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PADDW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PADDD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PADDQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PADDSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PADDSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PADDSD(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PADDSQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PADDUSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PADDUSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PADDUSD(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PADDUSQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PAND(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PANDN(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PAVGB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PAVGW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PCMPEQB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PCMPEQW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PCMPEQD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PCMPEQQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PCMPGTB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PCMPGTW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PCMPGTD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PCMPGTQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PEXTRW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PINSRW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PMADD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PMAXSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PMAXUB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PMINSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PMINUB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PMOVMSKB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PMULHUW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PMULHW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PMULLW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PMULUDQmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PMULUDQxmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_POR(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSADBW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSHUFLW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSHUFHW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSHUFD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSLLDQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PSLLB(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSLLW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSLLD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSLLQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PSLLBimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSLLWimm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSLLDimm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSLLQimm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PSRAB(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSRAW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSRAD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSRAQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PSRABimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSRAWimm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSRADimm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSRAQimm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSRLDQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PSRLB(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSRLW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSRLD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSRLQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PSRLBimm(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSRLWimm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSRLDimm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSRLQimm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSUBQmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSUBQxmm(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSUBB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSUBW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSUBD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PSUBQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSUBSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSUBSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PSUBSD(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSUBSQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PSUBUSB(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PSUBUSW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_PSUBUSD(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_PSUBUSQ(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_PUNPCKHBW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PUNPCKHWD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PUNPCKHDQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PUNPCKHQDQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PUNPCKLBW(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PUNPCKLWD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PUNPCKLDQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PUNPCKLQDQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PXOR(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void SSE2_MASKMOVDQU(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_CLFLUSH(UINT32 op) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE2_MOVNTPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVNTDQ(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_MOVNTI(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE2_PAUSE(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +//void SSE2_LFENCE(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +//void SSE2_MFENCE(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} + + #endif \ No newline at end of file diff --git a/i386c/ia32/instructions/sse2/sse2.h b/i386c/ia32/instructions/sse2/sse2.h old mode 100755 new mode 100644 index 453f6eca..e48fe14c --- a/i386c/ia32/instructions/sse2/sse2.h +++ b/i386c/ia32/instructions/sse2/sse2.h @@ -1,213 +1,213 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_SSE2_SSE2_H__ -#define IA32_CPU_INSTRUCTION_SSE2_SSE2_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -float SSE2_ROUND_FLOAT(float val); -double SSE2_ROUND_DOUBLE(double val); - -void SSE2_ADDPD(void); -void SSE2_ADDSD(void); -void SSE2_ANDNPD(void); -void SSE2_ANDPD(void); -void SSE2_CMPPD(void); -void SSE2_CMPSD(void); -void SSE2_COMISD(void); -void SSE2_CVTPI2PD(void); -void SSE2_CVTPD2PI(void); -void SSE2_CVTSI2SD(void); -void SSE2_CVTSD2SI(void); -void SSE2_CVTTPD2PI(void); -void SSE2_CVTTSD2SI(void); -void SSE2_CVTPD2PS(void); -void SSE2_CVTPS2PD(void); -void SSE2_CVTSD2SS(void); -void SSE2_CVTSS2SD(void); -void SSE2_CVTPD2DQ(void); -void SSE2_CVTTPD2DQ(void); -void SSE2_CVTDQ2PD(void); -void SSE2_CVTPS2DQ(void); -void SSE2_CVTTPS2DQ(void); -void SSE2_CVTDQ2PS(void); -void SSE2_DIVPD(void); -void SSE2_DIVSD(void); -void SSE2_MAXPD(void); -void SSE2_MAXSD(void); -void SSE2_MINPD(void); -void SSE2_MINSD(void); -void SSE2_MOVAPDmem2xmm(void); -void SSE2_MOVAPDxmm2mem(void); -void SSE2_MOVHPDmem2xmm(void); -void SSE2_MOVHPDxmm2mem(void); -void SSE2_MOVLPDmem2xmm(void); -void SSE2_MOVLPDxmm2mem(void); -void SSE2_MOVMSKPD(void); -void SSE2_MOVSDmem2xmm(void); -void SSE2_MOVSDxmm2mem(void); -void SSE2_MOVUPDmem2xmm(void); -void SSE2_MOVUPDxmm2mem(void); -void SSE2_MULPD(void); -void SSE2_MULSD(void); -void SSE2_ORPD(void); -void SSE2_SHUFPD(void); -void SSE2_SQRTPD(void); -void SSE2_SQRTSD(void); -//void SSE2_STMXCSR(UINT32 maddr); // -> SSE_STMXCSRと同じ -void SSE2_SUBPD(void); -void SSE2_SUBSD(void); -void SSE2_UCOMISD(void); -void SSE2_UNPCKHPD(void); -void SSE2_UNPCKLPD(void); -void SSE2_XORPD(void); - -void SSE2_MOVDrm2xmm(void); -void SSE2_MOVDxmm2rm(void); -void SSE2_MOVDQAmem2xmm(void); -void SSE2_MOVDQAxmm2mem(void); -void SSE2_MOVDQUmem2xmm(void); -void SSE2_MOVDQUxmm2mem(void); -void SSE2_MOVQ2DQ(void); -void SSE2_MOVDQ2Q(void); -void SSE2_MOVQmem2xmm(void); -void SSE2_MOVQxmm2mem(void); -void SSE2_PACKSSDW(void); -void SSE2_PACKSSWB(void); -void SSE2_PACKUSWB(void); -void SSE2_PADDQmm(void); -void SSE2_PADDQxmm(void); -void SSE2_PADDB(void); -void SSE2_PADDW(void); -void SSE2_PADDD(void); -//void SSE2_PADDQ(void); -void SSE2_PADDSB(void); -void SSE2_PADDSW(void); -//void SSE2_PADDSD(void); -//void SSE2_PADDSQ(void); -void SSE2_PADDUSB(void); -void SSE2_PADDUSW(void); -//void SSE2_PADDUSD(void); -//void SSE2_PADDUSQ(void); -void SSE2_PAND(void); -void SSE2_PANDN(void); -void SSE2_PAVGB(void); -void SSE2_PAVGW(void); -void SSE2_PCMPEQB(void); -void SSE2_PCMPEQW(void); -void SSE2_PCMPEQD(void); -//void SSE2_PCMPEQQ(void); -void SSE2_PCMPGTB(void); -void SSE2_PCMPGTW(void); -void SSE2_PCMPGTD(void); -//void SSE2_PCMPGTQ(void); -void SSE2_PEXTRW(void); -void SSE2_PINSRW(void); -void SSE2_PMADD(void); -void SSE2_PMAXSW(void); -void SSE2_PMAXUB(void); -void SSE2_PMINSW(void); -void SSE2_PMINUB(void); -void SSE2_PMOVMSKB(void); -void SSE2_PMULHUW(void); -void SSE2_PMULHW(void); -void SSE2_PMULLW(void); -void SSE2_PMULUDQmm(void); -void SSE2_PMULUDQxmm(void); -void SSE2_POR(void); -void SSE2_PSADBW(void); -void SSE2_PSHUFLW(void); -void SSE2_PSHUFHW(void); -void SSE2_PSHUFD(void); -//void SSE2_PSLLDQ(void); -//void SSE2_PSLLB(void); -void SSE2_PSLLW(void); -void SSE2_PSLLD(void); -void SSE2_PSLLQ(void); -//void SSE2_PSLLBimm(void); -//void SSE2_PSLLWimm(void); -//void SSE2_PSLLDimm(void); -//void SSE2_PSLLQimm(void); -//void SSE2_PSRAB(void); -void SSE2_PSRAW(void); -void SSE2_PSRAD(void); -//void SSE2_PSRAQ(void); -//void SSE2_PSRABimm(void); -//void SSE2_PSRAWimm(void); -//void SSE2_PSRADimm(void); -//void SSE2_PSRAQimm(void); -//void SSE2_PSRLDQ(void); -//void SSE2_PSRLB(void); -void SSE2_PSRLW(void); -void SSE2_PSRLD(void); -void SSE2_PSRLQ(void); -//void SSE2_PSRLBimm(void); -//void SSE2_PSRLWimm(void); -//void SSE2_PSRLDimm(void); -//void SSE2_PSRLQimm(void); -void SSE2_PSxxWimm(void); -void SSE2_PSxxDimm(void); -void SSE2_PSxxQimm(void); -void SSE2_PSUBQmm(void); -void SSE2_PSUBQxmm(void); -void SSE2_PSUBB(void); -void SSE2_PSUBW(void); -void SSE2_PSUBD(void); -//void SSE2_PSUBQ(void); -void SSE2_PSUBSB(void); -void SSE2_PSUBSW(void); -//void SSE2_PSUBSD(void); -//void SSE2_PSUBSQ(void); -void SSE2_PSUBUSB(void); -void SSE2_PSUBUSW(void); -//void SSE2_PSUBUSD(void); -//void SSE2_PSUBUSQ(void); -void SSE2_PUNPCKHBW(void); -void SSE2_PUNPCKHWD(void); -void SSE2_PUNPCKHDQ(void); -void SSE2_PUNPCKHQDQ(void); -void SSE2_PUNPCKLBW(void); -void SSE2_PUNPCKLWD(void); -void SSE2_PUNPCKLDQ(void); -void SSE2_PUNPCKLQDQ(void); -void SSE2_PXOR(void); - -void SSE2_MASKMOVDQU(void); -//void SSE2_CLFLUSH(UINT32 op); // --> SSE_CLFLUSH(UINT32 op)へ -void SSE2_MOVNTPD(void); -void SSE2_MOVNTDQ(void); -void SSE2_MOVNTI(void); -void SSE2_PAUSE(void); -//void SSE2_LFENCE(void); // --> SSE_LFENCE(void)へ -//void SSE2_MFENCE(void); // --> SSE_MFENCE(void)へ - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_SSE2_SSE2_H__ */ +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_SSE2_SSE2_H__ +#define IA32_CPU_INSTRUCTION_SSE2_SSE2_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +float SSE2_ROUND_FLOAT(float val); +double SSE2_ROUND_DOUBLE(double val); + +void SSE2_ADDPD(void); +void SSE2_ADDSD(void); +void SSE2_ANDNPD(void); +void SSE2_ANDPD(void); +void SSE2_CMPPD(void); +void SSE2_CMPSD(void); +void SSE2_COMISD(void); +void SSE2_CVTPI2PD(void); +void SSE2_CVTPD2PI(void); +void SSE2_CVTSI2SD(void); +void SSE2_CVTSD2SI(void); +void SSE2_CVTTPD2PI(void); +void SSE2_CVTTSD2SI(void); +void SSE2_CVTPD2PS(void); +void SSE2_CVTPS2PD(void); +void SSE2_CVTSD2SS(void); +void SSE2_CVTSS2SD(void); +void SSE2_CVTPD2DQ(void); +void SSE2_CVTTPD2DQ(void); +void SSE2_CVTDQ2PD(void); +void SSE2_CVTPS2DQ(void); +void SSE2_CVTTPS2DQ(void); +void SSE2_CVTDQ2PS(void); +void SSE2_DIVPD(void); +void SSE2_DIVSD(void); +void SSE2_MAXPD(void); +void SSE2_MAXSD(void); +void SSE2_MINPD(void); +void SSE2_MINSD(void); +void SSE2_MOVAPDmem2xmm(void); +void SSE2_MOVAPDxmm2mem(void); +void SSE2_MOVHPDmem2xmm(void); +void SSE2_MOVHPDxmm2mem(void); +void SSE2_MOVLPDmem2xmm(void); +void SSE2_MOVLPDxmm2mem(void); +void SSE2_MOVMSKPD(void); +void SSE2_MOVSDmem2xmm(void); +void SSE2_MOVSDxmm2mem(void); +void SSE2_MOVUPDmem2xmm(void); +void SSE2_MOVUPDxmm2mem(void); +void SSE2_MULPD(void); +void SSE2_MULSD(void); +void SSE2_ORPD(void); +void SSE2_SHUFPD(void); +void SSE2_SQRTPD(void); +void SSE2_SQRTSD(void); +//void SSE2_STMXCSR(UINT32 maddr); // -> SSE_STMXCSRと同じ +void SSE2_SUBPD(void); +void SSE2_SUBSD(void); +void SSE2_UCOMISD(void); +void SSE2_UNPCKHPD(void); +void SSE2_UNPCKLPD(void); +void SSE2_XORPD(void); + +void SSE2_MOVDrm2xmm(void); +void SSE2_MOVDxmm2rm(void); +void SSE2_MOVDQAmem2xmm(void); +void SSE2_MOVDQAxmm2mem(void); +void SSE2_MOVDQUmem2xmm(void); +void SSE2_MOVDQUxmm2mem(void); +void SSE2_MOVQ2DQ(void); +void SSE2_MOVDQ2Q(void); +void SSE2_MOVQmem2xmm(void); +void SSE2_MOVQxmm2mem(void); +void SSE2_PACKSSDW(void); +void SSE2_PACKSSWB(void); +void SSE2_PACKUSWB(void); +void SSE2_PADDQmm(void); +void SSE2_PADDQxmm(void); +void SSE2_PADDB(void); +void SSE2_PADDW(void); +void SSE2_PADDD(void); +//void SSE2_PADDQ(void); +void SSE2_PADDSB(void); +void SSE2_PADDSW(void); +//void SSE2_PADDSD(void); +//void SSE2_PADDSQ(void); +void SSE2_PADDUSB(void); +void SSE2_PADDUSW(void); +//void SSE2_PADDUSD(void); +//void SSE2_PADDUSQ(void); +void SSE2_PAND(void); +void SSE2_PANDN(void); +void SSE2_PAVGB(void); +void SSE2_PAVGW(void); +void SSE2_PCMPEQB(void); +void SSE2_PCMPEQW(void); +void SSE2_PCMPEQD(void); +//void SSE2_PCMPEQQ(void); +void SSE2_PCMPGTB(void); +void SSE2_PCMPGTW(void); +void SSE2_PCMPGTD(void); +//void SSE2_PCMPGTQ(void); +void SSE2_PEXTRW(void); +void SSE2_PINSRW(void); +void SSE2_PMADD(void); +void SSE2_PMAXSW(void); +void SSE2_PMAXUB(void); +void SSE2_PMINSW(void); +void SSE2_PMINUB(void); +void SSE2_PMOVMSKB(void); +void SSE2_PMULHUW(void); +void SSE2_PMULHW(void); +void SSE2_PMULLW(void); +void SSE2_PMULUDQmm(void); +void SSE2_PMULUDQxmm(void); +void SSE2_POR(void); +void SSE2_PSADBW(void); +void SSE2_PSHUFLW(void); +void SSE2_PSHUFHW(void); +void SSE2_PSHUFD(void); +//void SSE2_PSLLDQ(void); +//void SSE2_PSLLB(void); +void SSE2_PSLLW(void); +void SSE2_PSLLD(void); +void SSE2_PSLLQ(void); +//void SSE2_PSLLBimm(void); +//void SSE2_PSLLWimm(void); +//void SSE2_PSLLDimm(void); +//void SSE2_PSLLQimm(void); +//void SSE2_PSRAB(void); +void SSE2_PSRAW(void); +void SSE2_PSRAD(void); +//void SSE2_PSRAQ(void); +//void SSE2_PSRABimm(void); +//void SSE2_PSRAWimm(void); +//void SSE2_PSRADimm(void); +//void SSE2_PSRAQimm(void); +//void SSE2_PSRLDQ(void); +//void SSE2_PSRLB(void); +void SSE2_PSRLW(void); +void SSE2_PSRLD(void); +void SSE2_PSRLQ(void); +//void SSE2_PSRLBimm(void); +//void SSE2_PSRLWimm(void); +//void SSE2_PSRLDimm(void); +//void SSE2_PSRLQimm(void); +void SSE2_PSxxWimm(void); +void SSE2_PSxxDimm(void); +void SSE2_PSxxQimm(void); +void SSE2_PSUBQmm(void); +void SSE2_PSUBQxmm(void); +void SSE2_PSUBB(void); +void SSE2_PSUBW(void); +void SSE2_PSUBD(void); +//void SSE2_PSUBQ(void); +void SSE2_PSUBSB(void); +void SSE2_PSUBSW(void); +//void SSE2_PSUBSD(void); +//void SSE2_PSUBSQ(void); +void SSE2_PSUBUSB(void); +void SSE2_PSUBUSW(void); +//void SSE2_PSUBUSD(void); +//void SSE2_PSUBUSQ(void); +void SSE2_PUNPCKHBW(void); +void SSE2_PUNPCKHWD(void); +void SSE2_PUNPCKHDQ(void); +void SSE2_PUNPCKHQDQ(void); +void SSE2_PUNPCKLBW(void); +void SSE2_PUNPCKLWD(void); +void SSE2_PUNPCKLDQ(void); +void SSE2_PUNPCKLQDQ(void); +void SSE2_PXOR(void); + +void SSE2_MASKMOVDQU(void); +//void SSE2_CLFLUSH(UINT32 op); // --> SSE_CLFLUSH(UINT32 op)へ +void SSE2_MOVNTPD(void); +void SSE2_MOVNTDQ(void); +void SSE2_MOVNTI(void); +void SSE2_PAUSE(void); +//void SSE2_LFENCE(void); // --> SSE_LFENCE(void)へ +//void SSE2_MFENCE(void); // --> SSE_MFENCE(void)へ + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_SSE2_SSE2_H__ */ diff --git a/i386c/ia32/instructions/sse3/sse3.c b/i386c/ia32/instructions/sse3/sse3.c old mode 100755 new mode 100644 index 67bbda8a..4c11f46c --- a/i386c/ia32/instructions/sse3/sse3.c +++ b/i386c/ia32/instructions/sse3/sse3.c @@ -1,299 +1,299 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include - -#include -#include - -#if defined(_WIN32) && !defined(__LIBRETRO__) -#define isnan(x) (_isnan(x)) -#endif - -#include -#include "ia32/ia32.mcr" - -#include "ia32/instructions/sse/sse.h" -#include "ia32/instructions/sse2/sse2.h" -#include "ia32/instructions/sse3/sse3.h" - -#if defined(USE_SSE3) && defined(USE_SSE2) && defined(USE_SSE) && defined(USE_FPU) - -#define CPU_SSE3WORKCLOCK CPU_WORKCLOCK(2) - -static INLINE void -SSE3_check_NM_EXCEPTION(){ - // SSE3なしならUD(無効オペコード例外)を発生させる - if(!(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSE3)){ - EXCEPTION(UD_EXCEPTION, 0); - } - // エミュレーションならUD(無効オペコード例外)を発生させる - if(CPU_CR0 & CPU_CR0_EM){ - EXCEPTION(UD_EXCEPTION, 0); - } - // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる - if (CPU_CR0 & CPU_CR0_TS) { - EXCEPTION(NM_EXCEPTION, 0); - } -} - -static INLINE void -SSE3_setTag(void) -{ -} - -// mmx.cのものと同じ -static INLINE void -MMX_setTag(void) -{ - int i; - - if(!FPU_STAT.mmxenable){ - FPU_STAT.mmxenable = 1; - //FPU_CTRLWORD = 0x27F; - for (i = 0; i < FPU_REG_NUM; i++) { - FPU_STAT.tag[i] = TAG_Valid; -#ifdef SUPPORT_FPU_DOSBOX2 - FPU_STAT.int_regvalid[i] = 0; -#endif - FPU_STAT.reg[i].ul.ext = 0xffff; - } - } - FPU_STAT_TOP = 0; - FPU_STATUSWORD &= ~0x3800; - FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; -} - -/* - * SSE3 interface - */ - -// コードが長くなるのでやや強引に共通化 -// xmm/m128 -> xmm -static INLINE void SSE_PART_GETDATA1DATA2_PD(double **data1, double **data2, double *data2buf){ - UINT32 op; - UINT idx, sub; - - SSE3_check_NM_EXCEPTION(); - SSE3_setTag(); - CPU_SSE3WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); - if ((op) >= 0xc0) { - *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); - } else { - UINT32 maddr; - maddr = calc_ea_dst((op)); - *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); - *((UINT64*)(data2buf+ 1)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 8); - *data2 = data2buf; - } -} - -void SSE3_ADDSUBPD(void) -{ - double data2buf[2]; - double *data1, *data2; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - data1[0] = data1[0] - data2[0]; - data1[1] = data1[1] + data2[1]; -} -void SSE3_ADDSUBPS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); - data1[0] = data1[0] - data2[0]; - data1[1] = data1[1] + data2[1]; - data1[2] = data1[2] - data2[2]; - data1[3] = data1[3] + data2[3]; -} -void SSE3_HADDPD(void) -{ - double data2buf[2]; - double *data1, *data2; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - data1[0] = data1[0] + data1[1]; - data1[1] = data2[0] + data2[1]; -} -void SSE3_HADDPS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); - data1[0] = data1[0] + data1[1]; - data1[1] = data1[2] + data1[3]; - data1[2] = data2[0] + data2[1]; - data1[3] = data2[2] + data2[3]; -} -void SSE3_HSUBPD(void) -{ - double data2buf[2]; - double *data1, *data2; - - SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); - data1[0] = data1[0] - data1[1]; - data1[1] = data2[0] - data2[1]; -} -void SSE3_HSUBPS(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); - data1[0] = data1[0] - data1[1]; - data1[1] = data1[2] - data1[3]; - data1[2] = data2[0] - data2[1]; - data1[3] = data2[2] - data2[3]; -} - -void SSE3_MONITOR(void) -{ - EXCEPTION(UD_EXCEPTION, 0); // 未実装 -} -void SSE3_MWAIT(void) -{ - EXCEPTION(UD_EXCEPTION, 0); // 未実装 -} - -//void SSE3_FISTTP(void) -//{ -// EXCEPTION(UD_EXCEPTION, 0); -//} -void SSE3_LDDQU(void) -{ - SSE2_MOVDQAmem2xmm(); // 微妙に違うけどいいかな・・・ -} -void SSE3_MOVDDUP(void) -{ - UINT32 op; - UINT idx, sub; - - SSE3_check_NM_EXCEPTION(); - SSE3_setTag(); - CPU_SSE3WORKCLOCK; - GET_MODRM_PCBYTE((op)); - idx = (op >> 3) & 7; - sub = (op & 7); - if ((op) >= 0xc0) { - FPU_STAT.xmm_reg[idx].ul64[0] = FPU_STAT.xmm_reg[sub].ul64[0]; - } else { - UINT32 madr; - madr = calc_ea_dst(op); - FPU_STAT.xmm_reg[idx].ul64[0] = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); - } - FPU_STAT.xmm_reg[idx].ul64[1] = FPU_STAT.xmm_reg[idx].ul64[0]; -} -void SSE3_MOVSHDUP(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); - data1[0] = data2[1]; - data1[1] = data2[1]; - data1[2] = data2[3]; - data1[3] = data2[3]; -} -void SSE3_MOVSLDUP(void) -{ - float data2buf[4]; - float *data1, *data2; - - SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); - data1[0] = data2[0]; - data1[1] = data2[0]; - data1[2] = data2[2]; - data1[3] = data2[2]; -} - -#else - -/* - * SSE3 interface - */ - -void SSE3_ADDSUBPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE3_ADDSUBPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE3_HADDPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE3_HADDPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE3_HSUBPD(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE3_HSUBPS(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void SSE3_MONITOR(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE3_MWAIT(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -void SSE3_FISTTP(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE3_LDDQU(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE3_MOVDDUP(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE3_MOVSHDUP(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} -void SSE3_MOVSLDUP(void) -{ - EXCEPTION(UD_EXCEPTION, 0); -} - -#endif +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include + +#include +#include + +#if defined(_WIN32) && !defined(__LIBRETRO__) +#define isnan(x) (_isnan(x)) +#endif + +#include +#include "ia32/ia32.mcr" + +#include "ia32/instructions/sse/sse.h" +#include "ia32/instructions/sse2/sse2.h" +#include "ia32/instructions/sse3/sse3.h" + +#if defined(USE_SSE3) && defined(USE_SSE2) && defined(USE_SSE) && defined(USE_FPU) + +#define CPU_SSE3WORKCLOCK CPU_WORKCLOCK(2) + +static INLINE void +SSE3_check_NM_EXCEPTION(){ + // SSE3なしならUD(無効オペコード例外)を発生させる + if(!(i386cpuid.cpu_feature_ecx & CPU_FEATURE_ECX_SSE3)){ + EXCEPTION(UD_EXCEPTION, 0); + } + // エミュレーションならUD(無効オペコード例外)を発生させる + if(CPU_CR0 & CPU_CR0_EM){ + EXCEPTION(UD_EXCEPTION, 0); + } + // タスクスイッチ時にNM(デバイス使用不可例外)を発生させる + if (CPU_CR0 & CPU_CR0_TS) { + EXCEPTION(NM_EXCEPTION, 0); + } +} + +static INLINE void +SSE3_setTag(void) +{ +} + +// mmx.cのものと同じ +static INLINE void +MMX_setTag(void) +{ + int i; + + if(!FPU_STAT.mmxenable){ + FPU_STAT.mmxenable = 1; + //FPU_CTRLWORD = 0x27F; + for (i = 0; i < FPU_REG_NUM; i++) { + FPU_STAT.tag[i] = TAG_Valid; +#ifdef SUPPORT_FPU_DOSBOX2 + FPU_STAT.int_regvalid[i] = 0; +#endif + FPU_STAT.reg[i].ul.ext = 0xffff; + } + } + FPU_STAT_TOP = 0; + FPU_STATUSWORD &= ~0x3800; + FPU_STATUSWORD |= (FPU_STAT_TOP&7)<<11; +} + +/* + * SSE3 interface + */ + +// コードが長くなるのでやや強引に共通化 +// xmm/m128 -> xmm +static INLINE void SSE_PART_GETDATA1DATA2_PD(double **data1, double **data2, double *data2buf){ + UINT32 op; + UINT idx, sub; + + SSE3_check_NM_EXCEPTION(); + SSE3_setTag(); + CPU_SSE3WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + *data1 = (double*)(&(FPU_STAT.xmm_reg[idx])); + if ((op) >= 0xc0) { + *data2 = (double*)(&(FPU_STAT.xmm_reg[sub])); + } else { + UINT32 maddr; + maddr = calc_ea_dst((op)); + *((UINT64*)(data2buf+ 0)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 0); + *((UINT64*)(data2buf+ 1)) = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, maddr+ 8); + *data2 = data2buf; + } +} + +void SSE3_ADDSUBPD(void) +{ + double data2buf[2]; + double *data1, *data2; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + data1[0] = data1[0] - data2[0]; + data1[1] = data1[1] + data2[1]; +} +void SSE3_ADDSUBPS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); + data1[0] = data1[0] - data2[0]; + data1[1] = data1[1] + data2[1]; + data1[2] = data1[2] - data2[2]; + data1[3] = data1[3] + data2[3]; +} +void SSE3_HADDPD(void) +{ + double data2buf[2]; + double *data1, *data2; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + data1[0] = data1[0] + data1[1]; + data1[1] = data2[0] + data2[1]; +} +void SSE3_HADDPS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); + data1[0] = data1[0] + data1[1]; + data1[1] = data1[2] + data1[3]; + data1[2] = data2[0] + data2[1]; + data1[3] = data2[2] + data2[3]; +} +void SSE3_HSUBPD(void) +{ + double data2buf[2]; + double *data1, *data2; + + SSE_PART_GETDATA1DATA2_PD(&data1, &data2, data2buf); + data1[0] = data1[0] - data1[1]; + data1[1] = data2[0] - data2[1]; +} +void SSE3_HSUBPS(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); + data1[0] = data1[0] - data1[1]; + data1[1] = data1[2] - data1[3]; + data1[2] = data2[0] - data2[1]; + data1[3] = data2[2] - data2[3]; +} + +void SSE3_MONITOR(void) +{ + EXCEPTION(UD_EXCEPTION, 0); // 未実装 +} +void SSE3_MWAIT(void) +{ + EXCEPTION(UD_EXCEPTION, 0); // 未実装 +} + +//void SSE3_FISTTP(void) +//{ +// EXCEPTION(UD_EXCEPTION, 0); +//} +void SSE3_LDDQU(void) +{ + SSE2_MOVDQAmem2xmm(); // 微妙に違うけどいいかな・・・ +} +void SSE3_MOVDDUP(void) +{ + UINT32 op; + UINT idx, sub; + + SSE3_check_NM_EXCEPTION(); + SSE3_setTag(); + CPU_SSE3WORKCLOCK; + GET_MODRM_PCBYTE((op)); + idx = (op >> 3) & 7; + sub = (op & 7); + if ((op) >= 0xc0) { + FPU_STAT.xmm_reg[idx].ul64[0] = FPU_STAT.xmm_reg[sub].ul64[0]; + } else { + UINT32 madr; + madr = calc_ea_dst(op); + FPU_STAT.xmm_reg[idx].ul64[0] = cpu_vmemoryread_q(CPU_INST_SEGREG_INDEX, madr); + } + FPU_STAT.xmm_reg[idx].ul64[1] = FPU_STAT.xmm_reg[idx].ul64[0]; +} +void SSE3_MOVSHDUP(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); + data1[0] = data2[1]; + data1[1] = data2[1]; + data1[2] = data2[3]; + data1[3] = data2[3]; +} +void SSE3_MOVSLDUP(void) +{ + float data2buf[4]; + float *data1, *data2; + + SSE_PART_GETDATA1DATA2_PD((double**)(&data1), (double**)(&data2), (double*)data2buf); + data1[0] = data2[0]; + data1[1] = data2[0]; + data1[2] = data2[2]; + data1[3] = data2[2]; +} + +#else + +/* + * SSE3 interface + */ + +void SSE3_ADDSUBPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE3_ADDSUBPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE3_HADDPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE3_HADDPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE3_HSUBPD(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE3_HSUBPS(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void SSE3_MONITOR(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE3_MWAIT(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +void SSE3_FISTTP(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE3_LDDQU(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE3_MOVDDUP(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE3_MOVSHDUP(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} +void SSE3_MOVSLDUP(void) +{ + EXCEPTION(UD_EXCEPTION, 0); +} + +#endif diff --git a/i386c/ia32/instructions/sse3/sse3.h b/i386c/ia32/instructions/sse3/sse3.h old mode 100755 new mode 100644 index 6eb1fe98..b82ac1dc --- a/i386c/ia32/instructions/sse3/sse3.h +++ b/i386c/ia32/instructions/sse3/sse3.h @@ -1,53 +1,53 @@ -/* - * Copyright (c) 2018 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_SSE3_SSE3_H__ -#define IA32_CPU_INSTRUCTION_SSE3_SSE3_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -void SSE3_ADDSUBPD(void); -void SSE3_ADDSUBPS(void); -void SSE3_HADDPD(void); -void SSE3_HADDPS(void); -void SSE3_HSUBPD(void); -void SSE3_HSUBPS(void); - -void SSE3_MONITOR(void); -void SSE3_MWAIT(void); - -//void SSE3_FISTTP(void); // -> FPU命令 ESC7 -void SSE3_LDDQU(void); -void SSE3_MOVDDUP(void); -void SSE3_MOVSHDUP(void); -void SSE3_MOVSLDUP(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_SSE3_SSE3_H__ */ +/* + * Copyright (c) 2018 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_SSE3_SSE3_H__ +#define IA32_CPU_INSTRUCTION_SSE3_SSE3_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void SSE3_ADDSUBPD(void); +void SSE3_ADDSUBPS(void); +void SSE3_HADDPD(void); +void SSE3_HADDPS(void); +void SSE3_HSUBPD(void); +void SSE3_HSUBPS(void); + +void SSE3_MONITOR(void); +void SSE3_MWAIT(void); + +//void SSE3_FISTTP(void); // -> FPU命令 ESC7 +void SSE3_LDDQU(void); +void SSE3_MOVDDUP(void); +void SSE3_MOVSHDUP(void); +void SSE3_MOVSLDUP(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_SSE3_SSE3_H__ */ diff --git a/i386c/ia32/instructions/string_inst.c b/i386c/ia32/instructions/string_inst.c old mode 100755 new mode 100644 index df1367a8..dab2e4f5 --- a/i386c/ia32/instructions/string_inst.c +++ b/i386c/ia32/instructions/string_inst.c @@ -1,1291 +1,1291 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" - -#include "string_inst.h" - -#ifdef USE_SSE -#include "misc_inst.h" -#endif - - -/* movs */ -void -MOVSB_XbYb(void) -{ - UINT8 tmp; - - CPU_WORKCLOCK(5); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI); - cpu_vmemorywrite(CPU_ES_INDEX, CPU_DI, tmp); - CPU_SI += STRING_DIR; - CPU_DI += STRING_DIR; - } else { - tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI); - cpu_vmemorywrite(CPU_ES_INDEX, CPU_EDI, tmp); - CPU_ESI += STRING_DIR; - CPU_EDI += STRING_DIR; - } -} - -void -MOVSW_XwYw(void) -{ - UINT16 tmp; - - CPU_WORKCLOCK(5); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI); - cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_DI, tmp); - CPU_SI += STRING_DIRx2; - CPU_DI += STRING_DIRx2; - } else { - tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI); - cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_EDI, tmp); - CPU_ESI += STRING_DIRx2; - CPU_EDI += STRING_DIRx2; - } -} - -void -MOVSD_XdYd(void) -{ - UINT32 tmp; - - CPU_WORKCLOCK(5); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI); - cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_DI, tmp); - CPU_SI += STRING_DIRx4; - CPU_DI += STRING_DIRx4; - } else { - tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI); - cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_EDI, tmp); - CPU_ESI += STRING_DIRx4; - CPU_EDI += STRING_DIRx4; - } -} - -#define MOVSB_XbYb_rep16_part \ - do { \ - CPU_WORKCLOCK(5);\ - tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI); \ - cpu_vmemorywrite(CPU_ES_INDEX, CPU_DI, tmp); \ - CPU_SI += STRING_DIR; \ - CPU_DI += STRING_DIR; \ - } while (0) - -#define MOVSW_XwYw_rep16_part \ - do { \ - CPU_WORKCLOCK(5);\ - tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI); \ - cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_DI, tmp); \ - CPU_SI += STRING_DIRx2; \ - CPU_DI += STRING_DIRx2; \ - } while (0) - -#define MOVSD_XdYd_rep16_part \ - do { \ - CPU_WORKCLOCK(5);\ - tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI); \ - cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_DI, tmp); \ - CPU_SI += STRING_DIRx4; \ - CPU_DI += STRING_DIRx4; \ - } while (0) - -#define MOVSB_XbYb_rep32_part \ - do { \ - CPU_WORKCLOCK(5);\ - tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI); \ - cpu_vmemorywrite(CPU_ES_INDEX, CPU_EDI, tmp); \ - CPU_ESI += STRING_DIR; \ - CPU_EDI += STRING_DIR; \ - } while (0) - -#define MOVSW_XwYw_rep32_part \ - do { \ - CPU_WORKCLOCK(5);\ - tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI); \ - cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_EDI, tmp); \ - CPU_ESI += STRING_DIRx2; \ - CPU_EDI += STRING_DIRx2; \ - } while (0) - -#define MOVSD_XdYd_rep32_part \ - do { \ - CPU_WORKCLOCK(5);\ - tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI); \ - cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_EDI, tmp); \ - CPU_ESI += STRING_DIRx4; \ - CPU_EDI += STRING_DIRx4; \ - } while (0) - -void -MOVSB_XbYb_rep(int reptype) -{ - UINT8 tmp; - /* rep */ - CPU_INST_SEGREG_INDEX = DS_FIX; - if(!CPU_INST_AS32){ - switch(reptype){ - case 0: /* rep */ - for (;;) { - MOVSB_XbYb_rep16_part; - if (--CPU_CX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - MOVSB_XbYb_rep16_part; - if (--CPU_CX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - MOVSB_XbYb_rep16_part; - if (--CPU_CX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - }else{ - switch(reptype){ - case 0: /* rep */ - for (;;) { - MOVSB_XbYb_rep32_part; - if (--CPU_ECX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - MOVSB_XbYb_rep32_part; - if (--CPU_ECX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - MOVSB_XbYb_rep32_part; - if (--CPU_ECX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - } -} - -void -MOVSW_XwYw_rep(int reptype) -{ - UINT16 tmp; - /* rep */ - CPU_INST_SEGREG_INDEX = DS_FIX; - if(!CPU_INST_AS32){ - switch(reptype){ - case 0: /* rep */ - for (;;) { - MOVSW_XwYw_rep16_part; - if (--CPU_CX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - MOVSW_XwYw_rep16_part; - if (--CPU_CX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - MOVSW_XwYw_rep16_part; - if (--CPU_CX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - }else{ - switch(reptype){ - case 0: /* rep */ - for (;;) { - MOVSW_XwYw_rep32_part; - if (--CPU_ECX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - MOVSW_XwYw_rep32_part; - if (--CPU_ECX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - MOVSW_XwYw_rep32_part; - if (--CPU_ECX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - } -} - -void -MOVSD_XdYd_rep(int reptype) -{ - UINT32 tmp; - /* rep */ - CPU_INST_SEGREG_INDEX = DS_FIX; - if(!CPU_INST_AS32){ - switch(reptype){ - case 0: /* rep */ - for (;;) { - MOVSD_XdYd_rep16_part; - if (--CPU_CX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - MOVSD_XdYd_rep16_part; - if (--CPU_CX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - MOVSD_XdYd_rep16_part; - if (--CPU_CX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - }else{ - switch(reptype){ - case 0: /* rep */ - for (;;) { - MOVSD_XdYd_rep32_part; - if (--CPU_ECX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - MOVSD_XdYd_rep32_part; - if (--CPU_ECX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - MOVSD_XdYd_rep32_part; - if (--CPU_ECX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - } -} - - -/* cmps */ -void -CMPSB_XbYb(void) -{ - UINT32 src, dst, res; - - CPU_WORKCLOCK(8); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI); - src = cpu_vmemoryread(CPU_ES_INDEX, CPU_DI); - BYTE_SUB(res, dst, src); - CPU_SI += STRING_DIR; - CPU_DI += STRING_DIR; - } else { - dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI); - src = cpu_vmemoryread(CPU_ES_INDEX, CPU_EDI); - BYTE_SUB(res, dst, src); - CPU_ESI += STRING_DIR; - CPU_EDI += STRING_DIR; - } -} - -void -CMPSW_XwYw(void) -{ - UINT32 src, dst, res; - - CPU_WORKCLOCK(8); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI); - src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_DI); - WORD_SUB(res, dst, src); - CPU_SI += STRING_DIRx2; - CPU_DI += STRING_DIRx2; - } else { - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI); - src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_EDI); - WORD_SUB(res, dst, src); - CPU_ESI += STRING_DIRx2; - CPU_EDI += STRING_DIRx2; - } -} - -void -CMPSD_XdYd(void) -{ - UINT32 src, dst, res; - - CPU_WORKCLOCK(8); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI); - src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_DI); - DWORD_SUB(res, dst, src); - CPU_SI += STRING_DIRx4; - CPU_DI += STRING_DIRx4; - } else { - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI); - src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_EDI); - DWORD_SUB(res, dst, src); - CPU_ESI += STRING_DIRx4; - CPU_EDI += STRING_DIRx4; - } -} - -#define CMPSB_XbYb_rep16_part \ - do { \ - CPU_WORKCLOCK(8);\ - dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI);\ - src = cpu_vmemoryread(CPU_ES_INDEX, CPU_DI);\ - BYTE_SUB(res, dst, src);\ - CPU_SI += STRING_DIR;\ - CPU_DI += STRING_DIR;\ - } while (0) - -#define CMPSW_XwYw_rep16_part \ - do { \ - CPU_WORKCLOCK(8);\ - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI);\ - src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_DI);\ - WORD_SUB(res, dst, src);\ - CPU_SI += STRING_DIRx2;\ - CPU_DI += STRING_DIRx2;\ - } while (0) - -#define CMPSD_XdYd_rep16_part \ - do { \ - CPU_WORKCLOCK(8);\ - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI);\ - src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_DI);\ - DWORD_SUB(res, dst, src);\ - CPU_SI += STRING_DIRx4;\ - CPU_DI += STRING_DIRx4;\ - } while (0) - -#define CMPSB_XbYb_rep32_part \ - do { \ - CPU_WORKCLOCK(8);\ - dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI);\ - src = cpu_vmemoryread(CPU_ES_INDEX, CPU_EDI);\ - BYTE_SUB(res, dst, src);\ - CPU_ESI += STRING_DIR;\ - CPU_EDI += STRING_DIR;\ - } while (0) - -#define CMPSW_XwYw_rep32_part \ - do { \ - CPU_WORKCLOCK(8);\ - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI);\ - src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_EDI);\ - WORD_SUB(res, dst, src);\ - CPU_ESI += STRING_DIRx2;\ - CPU_EDI += STRING_DIRx2;\ - } while (0) - -#define CMPSD_XdYd_rep32_part \ - do { \ - CPU_WORKCLOCK(8);\ - dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI);\ - src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_EDI);\ - DWORD_SUB(res, dst, src);\ - CPU_ESI += STRING_DIRx4;\ - CPU_EDI += STRING_DIRx4;\ - } while (0) -void -CMPSB_XbYb_rep(int reptype) -{ - UINT32 src, dst, res; - - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - switch(reptype){ - case 0: /* rep */ - for (;;) { - CMPSB_XbYb_rep16_part; - if (--CPU_CX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - CMPSB_XbYb_rep16_part; - if (--CPU_CX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - CMPSB_XbYb_rep16_part; - if (--CPU_CX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - }else{ - switch(reptype){ - case 0: /* rep */ - for (;;) { - CMPSB_XbYb_rep32_part; - if (--CPU_ECX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - CMPSB_XbYb_rep32_part; - if (--CPU_ECX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - CMPSB_XbYb_rep32_part; - if (--CPU_ECX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - } -} - -void -CMPSW_XwYw_rep(int reptype) -{ - UINT32 src, dst, res; - - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - switch(reptype){ - case 0: /* rep */ - for (;;) { - CMPSW_XwYw_rep16_part; - if (--CPU_CX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - CMPSW_XwYw_rep16_part; - if (--CPU_CX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - CMPSW_XwYw_rep16_part; - if (--CPU_CX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - }else{ - switch(reptype){ - case 0: /* rep */ - for (;;) { - CMPSW_XwYw_rep32_part; - if (--CPU_ECX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - CMPSW_XwYw_rep32_part; - if (--CPU_ECX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - CMPSW_XwYw_rep32_part; - if (--CPU_ECX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - } -} - -void -CMPSD_XdYd_rep(int reptype) -{ - UINT32 src, dst, res; - - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - switch(reptype){ - case 0: /* rep */ - for (;;) { - CMPSD_XdYd_rep16_part; - if (--CPU_CX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - CMPSD_XdYd_rep16_part; - if (--CPU_CX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - CMPSD_XdYd_rep16_part; - if (--CPU_CX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - }else{ - switch(reptype){ - case 0: /* rep */ - for (;;) { - CMPSD_XdYd_rep32_part; - if (--CPU_ECX == 0) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 1: /* repe */ - for (;;) { - CMPSD_XdYd_rep32_part; - if (--CPU_ECX == 0 || CC_NZ) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - case 2: /* repne */ - for (;;) { - CMPSD_XdYd_rep32_part; - if (--CPU_ECX == 0 || CC_Z) { - #if defined(DEBUG) - cpu_debug_rep_cont = 0; - #endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - break; - } - } -} - - -/* scas */ -void -SCASB_ALXb(void) -{ - UINT32 src, dst, res; - - CPU_WORKCLOCK(7); - dst = CPU_AL; - if (!CPU_INST_AS32) { - src = cpu_vmemoryread(CPU_ES_INDEX, CPU_DI); - BYTE_SUB(res, dst, src); - CPU_DI += STRING_DIR; - } else { - src = cpu_vmemoryread(CPU_ES_INDEX, CPU_EDI); - BYTE_SUB(res, dst, src); - CPU_EDI += STRING_DIR; - } -} - -void -SCASW_AXXw(void) -{ - UINT32 src, dst, res; - - CPU_WORKCLOCK(7); - dst = CPU_AX; - if (!CPU_INST_AS32) { - src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_DI); - WORD_SUB(res, dst, src); - CPU_DI += STRING_DIRx2; - } else { - src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_EDI); - WORD_SUB(res, dst, src); - CPU_EDI += STRING_DIRx2; - } -} - -void -SCASD_EAXXd(void) -{ - UINT32 src, dst, res; - - CPU_WORKCLOCK(7); - dst = CPU_EAX; - if (!CPU_INST_AS32) { - src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_DI); - DWORD_SUB(res, dst, src); - CPU_DI += STRING_DIRx4; - } else { - src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_EDI); - DWORD_SUB(res, dst, src); - CPU_EDI += STRING_DIRx4; - } -} - - -/* lods */ -void -LODSB_ALXb(void) -{ - - CPU_WORKCLOCK(5); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - CPU_AL = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI); - CPU_SI += STRING_DIR; - } else { - CPU_AL = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI); - CPU_ESI += STRING_DIR; - } -} - -void -LODSW_AXXw(void) -{ - - CPU_WORKCLOCK(5); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - CPU_AX = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI); - CPU_SI += STRING_DIRx2; - } else { - CPU_AX = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI); - CPU_ESI += STRING_DIRx2; - } -} - -void -LODSD_EAXXd(void) -{ - - CPU_WORKCLOCK(5); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - CPU_EAX = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI); - CPU_SI += STRING_DIRx4; - } else { - CPU_EAX = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI); - CPU_ESI += STRING_DIRx4; - } -} - - -/* stos */ -void -STOSB_YbAL(void) -{ - - CPU_WORKCLOCK(3); - if (!CPU_INST_AS32) { - cpu_vmemorywrite(CPU_ES_INDEX, CPU_DI, CPU_AL); - CPU_DI += STRING_DIR; - } else { - cpu_vmemorywrite(CPU_ES_INDEX, CPU_EDI, CPU_AL); - CPU_EDI += STRING_DIR; - } -} - -void -STOSW_YwAX(void) -{ - - CPU_WORKCLOCK(3); - if (!CPU_INST_AS32) { - cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_DI, CPU_AX); - CPU_DI += STRING_DIRx2; - } else { - cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_EDI, CPU_AX); - CPU_EDI += STRING_DIRx2; - } -} - -void -STOSD_YdEAX(void) -{ - - CPU_WORKCLOCK(3); - if (!CPU_INST_AS32) { - cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_DI, CPU_EAX); - CPU_DI += STRING_DIRx4; - } else { - cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_EDI, CPU_EAX); - CPU_EDI += STRING_DIRx4; - } -} - -// repのみ -void -STOSB_YbAL_rep(int reptype) -{ - if (!CPU_INST_AS32) { - for (;;) { - CPU_WORKCLOCK(3); - cpu_vmemorywrite(CPU_ES_INDEX, CPU_DI, CPU_AL); - CPU_DI += STRING_DIR; - if (--CPU_CX == 0) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } else { - for (;;) { - CPU_WORKCLOCK(3); - cpu_vmemorywrite(CPU_ES_INDEX, CPU_EDI, CPU_AL); - CPU_EDI += STRING_DIR; - if (--CPU_ECX == 0) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } -} - -void -STOSW_YwAX_rep(int reptype) -{ - - if (!CPU_INST_AS32) { - for (;;) { - CPU_WORKCLOCK(3); - cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_DI, CPU_AX); - CPU_DI += STRING_DIRx2; - if (--CPU_CX == 0) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } else { - for (;;) { - CPU_WORKCLOCK(3); - cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_EDI, CPU_AX); - CPU_EDI += STRING_DIRx2; - if (--CPU_ECX == 0) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } -} - -void -STOSD_YdEAX_rep(int reptype) -{ - - if (!CPU_INST_AS32) { - for (;;) { - CPU_WORKCLOCK(3); - cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_DI, CPU_EAX); - CPU_DI += STRING_DIRx4; - if (--CPU_CX == 0) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } else { - for (;;) { - CPU_WORKCLOCK(3); - cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_EDI, CPU_EAX); - CPU_EDI += STRING_DIRx4; - if (--CPU_ECX == 0) { -#if defined(DEBUG) - cpu_debug_rep_cont = 0; -#endif - break; - } - if (CPU_REMCLOCK <= 0) { - CPU_EIP = CPU_PREV_EIP; - break; - } - } - } -} - - -/* repeat */ -void -_REPNE(void) -{ - CPU_INST_REPUSE = 0xf2; -} - -void -_REPE(void) -{ - CPU_INST_REPUSE = 0xf3; -} - - -/* ins */ -void -INSB_YbDX(void) -{ - UINT8 data; - - CPU_WORKCLOCK(12); - data = cpu_in(CPU_DX); - if (!CPU_INST_AS32) { - cpu_vmemorywrite(CPU_ES_INDEX, CPU_DI, data); - CPU_DI += STRING_DIR; - } else { - cpu_vmemorywrite(CPU_ES_INDEX, CPU_EDI, data); - CPU_EDI += STRING_DIR; - } -} - -void -INSW_YwDX(void) -{ - UINT16 data; - - CPU_WORKCLOCK(12); - data = cpu_in_w(CPU_DX); - if (!CPU_INST_AS32) { - cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_DI, data); - CPU_DI += STRING_DIRx2; - } else { - cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_EDI, data); - CPU_EDI += STRING_DIRx2; - } -} - -void -INSD_YdDX(void) -{ - UINT32 data; - - CPU_WORKCLOCK(12); - data = cpu_in_d(CPU_DX); - if (!CPU_INST_AS32) { - cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_DI, data); - CPU_DI += STRING_DIRx4; - } else { - cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_EDI, data); - CPU_EDI += STRING_DIRx4; - } -} - - -/* outs */ -void -OUTSB_DXXb(void) -{ - UINT8 data; - - CPU_WORKCLOCK(14); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - data = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI); - cpu_out(CPU_DX, data); - CPU_SI += STRING_DIR; - } else { - data = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI); - cpu_out(CPU_DX, data); - CPU_ESI += STRING_DIR; - } -} - -void -OUTSW_DXXw(void) -{ - UINT16 data; - - CPU_WORKCLOCK(14); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - data = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI); - cpu_out_w(CPU_DX, data); - CPU_SI += STRING_DIRx2; - } else { - data = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI); - cpu_out_w(CPU_DX, data); - CPU_ESI += STRING_DIRx2; - } -} - -void -OUTSD_DXXd(void) -{ - UINT32 data; - - CPU_WORKCLOCK(14); - CPU_INST_SEGREG_INDEX = DS_FIX; - if (!CPU_INST_AS32) { - data = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI); - cpu_out_d(CPU_DX, data); - CPU_SI += STRING_DIRx4; - } else { - data = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI); - cpu_out_d(CPU_DX, data); - CPU_ESI += STRING_DIRx4; - } -} +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" + +#include "string_inst.h" + +#ifdef USE_SSE +#include "misc_inst.h" +#endif + + +/* movs */ +void +MOVSB_XbYb(void) +{ + UINT8 tmp; + + CPU_WORKCLOCK(5); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI); + cpu_vmemorywrite(CPU_ES_INDEX, CPU_DI, tmp); + CPU_SI += STRING_DIR; + CPU_DI += STRING_DIR; + } else { + tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI); + cpu_vmemorywrite(CPU_ES_INDEX, CPU_EDI, tmp); + CPU_ESI += STRING_DIR; + CPU_EDI += STRING_DIR; + } +} + +void +MOVSW_XwYw(void) +{ + UINT16 tmp; + + CPU_WORKCLOCK(5); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI); + cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_DI, tmp); + CPU_SI += STRING_DIRx2; + CPU_DI += STRING_DIRx2; + } else { + tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI); + cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_EDI, tmp); + CPU_ESI += STRING_DIRx2; + CPU_EDI += STRING_DIRx2; + } +} + +void +MOVSD_XdYd(void) +{ + UINT32 tmp; + + CPU_WORKCLOCK(5); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI); + cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_DI, tmp); + CPU_SI += STRING_DIRx4; + CPU_DI += STRING_DIRx4; + } else { + tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI); + cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_EDI, tmp); + CPU_ESI += STRING_DIRx4; + CPU_EDI += STRING_DIRx4; + } +} + +#define MOVSB_XbYb_rep16_part \ + do { \ + CPU_WORKCLOCK(5);\ + tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI); \ + cpu_vmemorywrite(CPU_ES_INDEX, CPU_DI, tmp); \ + CPU_SI += STRING_DIR; \ + CPU_DI += STRING_DIR; \ + } while (0) + +#define MOVSW_XwYw_rep16_part \ + do { \ + CPU_WORKCLOCK(5);\ + tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI); \ + cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_DI, tmp); \ + CPU_SI += STRING_DIRx2; \ + CPU_DI += STRING_DIRx2; \ + } while (0) + +#define MOVSD_XdYd_rep16_part \ + do { \ + CPU_WORKCLOCK(5);\ + tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI); \ + cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_DI, tmp); \ + CPU_SI += STRING_DIRx4; \ + CPU_DI += STRING_DIRx4; \ + } while (0) + +#define MOVSB_XbYb_rep32_part \ + do { \ + CPU_WORKCLOCK(5);\ + tmp = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI); \ + cpu_vmemorywrite(CPU_ES_INDEX, CPU_EDI, tmp); \ + CPU_ESI += STRING_DIR; \ + CPU_EDI += STRING_DIR; \ + } while (0) + +#define MOVSW_XwYw_rep32_part \ + do { \ + CPU_WORKCLOCK(5);\ + tmp = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI); \ + cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_EDI, tmp); \ + CPU_ESI += STRING_DIRx2; \ + CPU_EDI += STRING_DIRx2; \ + } while (0) + +#define MOVSD_XdYd_rep32_part \ + do { \ + CPU_WORKCLOCK(5);\ + tmp = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI); \ + cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_EDI, tmp); \ + CPU_ESI += STRING_DIRx4; \ + CPU_EDI += STRING_DIRx4; \ + } while (0) + +void +MOVSB_XbYb_rep(int reptype) +{ + UINT8 tmp; + /* rep */ + CPU_INST_SEGREG_INDEX = DS_FIX; + if(!CPU_INST_AS32){ + switch(reptype){ + case 0: /* rep */ + for (;;) { + MOVSB_XbYb_rep16_part; + if (--CPU_CX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + MOVSB_XbYb_rep16_part; + if (--CPU_CX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + MOVSB_XbYb_rep16_part; + if (--CPU_CX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + }else{ + switch(reptype){ + case 0: /* rep */ + for (;;) { + MOVSB_XbYb_rep32_part; + if (--CPU_ECX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + MOVSB_XbYb_rep32_part; + if (--CPU_ECX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + MOVSB_XbYb_rep32_part; + if (--CPU_ECX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + } +} + +void +MOVSW_XwYw_rep(int reptype) +{ + UINT16 tmp; + /* rep */ + CPU_INST_SEGREG_INDEX = DS_FIX; + if(!CPU_INST_AS32){ + switch(reptype){ + case 0: /* rep */ + for (;;) { + MOVSW_XwYw_rep16_part; + if (--CPU_CX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + MOVSW_XwYw_rep16_part; + if (--CPU_CX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + MOVSW_XwYw_rep16_part; + if (--CPU_CX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + }else{ + switch(reptype){ + case 0: /* rep */ + for (;;) { + MOVSW_XwYw_rep32_part; + if (--CPU_ECX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + MOVSW_XwYw_rep32_part; + if (--CPU_ECX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + MOVSW_XwYw_rep32_part; + if (--CPU_ECX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + } +} + +void +MOVSD_XdYd_rep(int reptype) +{ + UINT32 tmp; + /* rep */ + CPU_INST_SEGREG_INDEX = DS_FIX; + if(!CPU_INST_AS32){ + switch(reptype){ + case 0: /* rep */ + for (;;) { + MOVSD_XdYd_rep16_part; + if (--CPU_CX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + MOVSD_XdYd_rep16_part; + if (--CPU_CX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + MOVSD_XdYd_rep16_part; + if (--CPU_CX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + }else{ + switch(reptype){ + case 0: /* rep */ + for (;;) { + MOVSD_XdYd_rep32_part; + if (--CPU_ECX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + MOVSD_XdYd_rep32_part; + if (--CPU_ECX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + MOVSD_XdYd_rep32_part; + if (--CPU_ECX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + } +} + + +/* cmps */ +void +CMPSB_XbYb(void) +{ + UINT32 src, dst, res; + + CPU_WORKCLOCK(8); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI); + src = cpu_vmemoryread(CPU_ES_INDEX, CPU_DI); + BYTE_SUB(res, dst, src); + CPU_SI += STRING_DIR; + CPU_DI += STRING_DIR; + } else { + dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI); + src = cpu_vmemoryread(CPU_ES_INDEX, CPU_EDI); + BYTE_SUB(res, dst, src); + CPU_ESI += STRING_DIR; + CPU_EDI += STRING_DIR; + } +} + +void +CMPSW_XwYw(void) +{ + UINT32 src, dst, res; + + CPU_WORKCLOCK(8); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI); + src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_DI); + WORD_SUB(res, dst, src); + CPU_SI += STRING_DIRx2; + CPU_DI += STRING_DIRx2; + } else { + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI); + src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_EDI); + WORD_SUB(res, dst, src); + CPU_ESI += STRING_DIRx2; + CPU_EDI += STRING_DIRx2; + } +} + +void +CMPSD_XdYd(void) +{ + UINT32 src, dst, res; + + CPU_WORKCLOCK(8); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI); + src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_DI); + DWORD_SUB(res, dst, src); + CPU_SI += STRING_DIRx4; + CPU_DI += STRING_DIRx4; + } else { + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI); + src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_EDI); + DWORD_SUB(res, dst, src); + CPU_ESI += STRING_DIRx4; + CPU_EDI += STRING_DIRx4; + } +} + +#define CMPSB_XbYb_rep16_part \ + do { \ + CPU_WORKCLOCK(8);\ + dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI);\ + src = cpu_vmemoryread(CPU_ES_INDEX, CPU_DI);\ + BYTE_SUB(res, dst, src);\ + CPU_SI += STRING_DIR;\ + CPU_DI += STRING_DIR;\ + } while (0) + +#define CMPSW_XwYw_rep16_part \ + do { \ + CPU_WORKCLOCK(8);\ + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI);\ + src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_DI);\ + WORD_SUB(res, dst, src);\ + CPU_SI += STRING_DIRx2;\ + CPU_DI += STRING_DIRx2;\ + } while (0) + +#define CMPSD_XdYd_rep16_part \ + do { \ + CPU_WORKCLOCK(8);\ + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI);\ + src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_DI);\ + DWORD_SUB(res, dst, src);\ + CPU_SI += STRING_DIRx4;\ + CPU_DI += STRING_DIRx4;\ + } while (0) + +#define CMPSB_XbYb_rep32_part \ + do { \ + CPU_WORKCLOCK(8);\ + dst = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI);\ + src = cpu_vmemoryread(CPU_ES_INDEX, CPU_EDI);\ + BYTE_SUB(res, dst, src);\ + CPU_ESI += STRING_DIR;\ + CPU_EDI += STRING_DIR;\ + } while (0) + +#define CMPSW_XwYw_rep32_part \ + do { \ + CPU_WORKCLOCK(8);\ + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI);\ + src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_EDI);\ + WORD_SUB(res, dst, src);\ + CPU_ESI += STRING_DIRx2;\ + CPU_EDI += STRING_DIRx2;\ + } while (0) + +#define CMPSD_XdYd_rep32_part \ + do { \ + CPU_WORKCLOCK(8);\ + dst = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI);\ + src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_EDI);\ + DWORD_SUB(res, dst, src);\ + CPU_ESI += STRING_DIRx4;\ + CPU_EDI += STRING_DIRx4;\ + } while (0) +void +CMPSB_XbYb_rep(int reptype) +{ + UINT32 src, dst, res; + + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + switch(reptype){ + case 0: /* rep */ + for (;;) { + CMPSB_XbYb_rep16_part; + if (--CPU_CX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + CMPSB_XbYb_rep16_part; + if (--CPU_CX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + CMPSB_XbYb_rep16_part; + if (--CPU_CX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + }else{ + switch(reptype){ + case 0: /* rep */ + for (;;) { + CMPSB_XbYb_rep32_part; + if (--CPU_ECX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + CMPSB_XbYb_rep32_part; + if (--CPU_ECX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + CMPSB_XbYb_rep32_part; + if (--CPU_ECX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + } +} + +void +CMPSW_XwYw_rep(int reptype) +{ + UINT32 src, dst, res; + + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + switch(reptype){ + case 0: /* rep */ + for (;;) { + CMPSW_XwYw_rep16_part; + if (--CPU_CX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + CMPSW_XwYw_rep16_part; + if (--CPU_CX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + CMPSW_XwYw_rep16_part; + if (--CPU_CX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + }else{ + switch(reptype){ + case 0: /* rep */ + for (;;) { + CMPSW_XwYw_rep32_part; + if (--CPU_ECX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + CMPSW_XwYw_rep32_part; + if (--CPU_ECX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + CMPSW_XwYw_rep32_part; + if (--CPU_ECX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + } +} + +void +CMPSD_XdYd_rep(int reptype) +{ + UINT32 src, dst, res; + + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + switch(reptype){ + case 0: /* rep */ + for (;;) { + CMPSD_XdYd_rep16_part; + if (--CPU_CX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + CMPSD_XdYd_rep16_part; + if (--CPU_CX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + CMPSD_XdYd_rep16_part; + if (--CPU_CX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + }else{ + switch(reptype){ + case 0: /* rep */ + for (;;) { + CMPSD_XdYd_rep32_part; + if (--CPU_ECX == 0) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 1: /* repe */ + for (;;) { + CMPSD_XdYd_rep32_part; + if (--CPU_ECX == 0 || CC_NZ) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + case 2: /* repne */ + for (;;) { + CMPSD_XdYd_rep32_part; + if (--CPU_ECX == 0 || CC_Z) { + #if defined(DEBUG) + cpu_debug_rep_cont = 0; + #endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + break; + } + } +} + + +/* scas */ +void +SCASB_ALXb(void) +{ + UINT32 src, dst, res; + + CPU_WORKCLOCK(7); + dst = CPU_AL; + if (!CPU_INST_AS32) { + src = cpu_vmemoryread(CPU_ES_INDEX, CPU_DI); + BYTE_SUB(res, dst, src); + CPU_DI += STRING_DIR; + } else { + src = cpu_vmemoryread(CPU_ES_INDEX, CPU_EDI); + BYTE_SUB(res, dst, src); + CPU_EDI += STRING_DIR; + } +} + +void +SCASW_AXXw(void) +{ + UINT32 src, dst, res; + + CPU_WORKCLOCK(7); + dst = CPU_AX; + if (!CPU_INST_AS32) { + src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_DI); + WORD_SUB(res, dst, src); + CPU_DI += STRING_DIRx2; + } else { + src = cpu_vmemoryread_w(CPU_ES_INDEX, CPU_EDI); + WORD_SUB(res, dst, src); + CPU_EDI += STRING_DIRx2; + } +} + +void +SCASD_EAXXd(void) +{ + UINT32 src, dst, res; + + CPU_WORKCLOCK(7); + dst = CPU_EAX; + if (!CPU_INST_AS32) { + src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_DI); + DWORD_SUB(res, dst, src); + CPU_DI += STRING_DIRx4; + } else { + src = cpu_vmemoryread_d(CPU_ES_INDEX, CPU_EDI); + DWORD_SUB(res, dst, src); + CPU_EDI += STRING_DIRx4; + } +} + + +/* lods */ +void +LODSB_ALXb(void) +{ + + CPU_WORKCLOCK(5); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + CPU_AL = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI); + CPU_SI += STRING_DIR; + } else { + CPU_AL = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI); + CPU_ESI += STRING_DIR; + } +} + +void +LODSW_AXXw(void) +{ + + CPU_WORKCLOCK(5); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + CPU_AX = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI); + CPU_SI += STRING_DIRx2; + } else { + CPU_AX = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI); + CPU_ESI += STRING_DIRx2; + } +} + +void +LODSD_EAXXd(void) +{ + + CPU_WORKCLOCK(5); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + CPU_EAX = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI); + CPU_SI += STRING_DIRx4; + } else { + CPU_EAX = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI); + CPU_ESI += STRING_DIRx4; + } +} + + +/* stos */ +void +STOSB_YbAL(void) +{ + + CPU_WORKCLOCK(3); + if (!CPU_INST_AS32) { + cpu_vmemorywrite(CPU_ES_INDEX, CPU_DI, CPU_AL); + CPU_DI += STRING_DIR; + } else { + cpu_vmemorywrite(CPU_ES_INDEX, CPU_EDI, CPU_AL); + CPU_EDI += STRING_DIR; + } +} + +void +STOSW_YwAX(void) +{ + + CPU_WORKCLOCK(3); + if (!CPU_INST_AS32) { + cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_DI, CPU_AX); + CPU_DI += STRING_DIRx2; + } else { + cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_EDI, CPU_AX); + CPU_EDI += STRING_DIRx2; + } +} + +void +STOSD_YdEAX(void) +{ + + CPU_WORKCLOCK(3); + if (!CPU_INST_AS32) { + cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_DI, CPU_EAX); + CPU_DI += STRING_DIRx4; + } else { + cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_EDI, CPU_EAX); + CPU_EDI += STRING_DIRx4; + } +} + +// repのみ +void +STOSB_YbAL_rep(int reptype) +{ + if (!CPU_INST_AS32) { + for (;;) { + CPU_WORKCLOCK(3); + cpu_vmemorywrite(CPU_ES_INDEX, CPU_DI, CPU_AL); + CPU_DI += STRING_DIR; + if (--CPU_CX == 0) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } else { + for (;;) { + CPU_WORKCLOCK(3); + cpu_vmemorywrite(CPU_ES_INDEX, CPU_EDI, CPU_AL); + CPU_EDI += STRING_DIR; + if (--CPU_ECX == 0) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } +} + +void +STOSW_YwAX_rep(int reptype) +{ + + if (!CPU_INST_AS32) { + for (;;) { + CPU_WORKCLOCK(3); + cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_DI, CPU_AX); + CPU_DI += STRING_DIRx2; + if (--CPU_CX == 0) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } else { + for (;;) { + CPU_WORKCLOCK(3); + cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_EDI, CPU_AX); + CPU_EDI += STRING_DIRx2; + if (--CPU_ECX == 0) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } +} + +void +STOSD_YdEAX_rep(int reptype) +{ + + if (!CPU_INST_AS32) { + for (;;) { + CPU_WORKCLOCK(3); + cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_DI, CPU_EAX); + CPU_DI += STRING_DIRx4; + if (--CPU_CX == 0) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } else { + for (;;) { + CPU_WORKCLOCK(3); + cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_EDI, CPU_EAX); + CPU_EDI += STRING_DIRx4; + if (--CPU_ECX == 0) { +#if defined(DEBUG) + cpu_debug_rep_cont = 0; +#endif + break; + } + if (CPU_REMCLOCK <= 0) { + CPU_EIP = CPU_PREV_EIP; + break; + } + } + } +} + + +/* repeat */ +void +_REPNE(void) +{ + CPU_INST_REPUSE = 0xf2; +} + +void +_REPE(void) +{ + CPU_INST_REPUSE = 0xf3; +} + + +/* ins */ +void +INSB_YbDX(void) +{ + UINT8 data; + + CPU_WORKCLOCK(12); + data = cpu_in(CPU_DX); + if (!CPU_INST_AS32) { + cpu_vmemorywrite(CPU_ES_INDEX, CPU_DI, data); + CPU_DI += STRING_DIR; + } else { + cpu_vmemorywrite(CPU_ES_INDEX, CPU_EDI, data); + CPU_EDI += STRING_DIR; + } +} + +void +INSW_YwDX(void) +{ + UINT16 data; + + CPU_WORKCLOCK(12); + data = cpu_in_w(CPU_DX); + if (!CPU_INST_AS32) { + cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_DI, data); + CPU_DI += STRING_DIRx2; + } else { + cpu_vmemorywrite_w(CPU_ES_INDEX, CPU_EDI, data); + CPU_EDI += STRING_DIRx2; + } +} + +void +INSD_YdDX(void) +{ + UINT32 data; + + CPU_WORKCLOCK(12); + data = cpu_in_d(CPU_DX); + if (!CPU_INST_AS32) { + cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_DI, data); + CPU_DI += STRING_DIRx4; + } else { + cpu_vmemorywrite_d(CPU_ES_INDEX, CPU_EDI, data); + CPU_EDI += STRING_DIRx4; + } +} + + +/* outs */ +void +OUTSB_DXXb(void) +{ + UINT8 data; + + CPU_WORKCLOCK(14); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + data = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_SI); + cpu_out(CPU_DX, data); + CPU_SI += STRING_DIR; + } else { + data = cpu_vmemoryread(CPU_INST_SEGREG_INDEX, CPU_ESI); + cpu_out(CPU_DX, data); + CPU_ESI += STRING_DIR; + } +} + +void +OUTSW_DXXw(void) +{ + UINT16 data; + + CPU_WORKCLOCK(14); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + data = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_SI); + cpu_out_w(CPU_DX, data); + CPU_SI += STRING_DIRx2; + } else { + data = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, CPU_ESI); + cpu_out_w(CPU_DX, data); + CPU_ESI += STRING_DIRx2; + } +} + +void +OUTSD_DXXd(void) +{ + UINT32 data; + + CPU_WORKCLOCK(14); + CPU_INST_SEGREG_INDEX = DS_FIX; + if (!CPU_INST_AS32) { + data = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_SI); + cpu_out_d(CPU_DX, data); + CPU_SI += STRING_DIRx4; + } else { + data = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, CPU_ESI); + cpu_out_d(CPU_DX, data); + CPU_ESI += STRING_DIRx4; + } +} diff --git a/i386c/ia32/instructions/string_inst.h b/i386c/ia32/instructions/string_inst.h old mode 100755 new mode 100644 index 297d460e..18fa7a13 --- a/i386c/ia32/instructions/string_inst.h +++ b/i386c/ia32/instructions/string_inst.h @@ -1,89 +1,89 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_STRING_H__ -#define IA32_CPU_INSTRUCTION_STRING_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#define STRING_DIR ((CPU_FLAG & D_FLAG) ? -1 : 1) -#define STRING_DIRx2 ((CPU_FLAG & D_FLAG) ? -2 : 2) -#define STRING_DIRx4 ((CPU_FLAG & D_FLAG) ? -4 : 4) - -/* movs */ -void MOVSB_XbYb(void); -void MOVSW_XwYw(void); -void MOVSD_XdYd(void); -void MOVSB_XbYb_rep(int reptype); -void MOVSW_XwYw_rep(int reptype); -void MOVSD_XdYd_rep(int reptype); - -/* cmps */ -void CMPSB_XbYb(void); -void CMPSW_XwYw(void); -void CMPSD_XdYd(void); -void CMPSB_XbYb_rep(int reptype); -void CMPSW_XwYw_rep(int reptype); -void CMPSD_XdYd_rep(int reptype); - -/* scas */ -void SCASB_ALXb(void); -void SCASW_AXXw(void); -void SCASD_EAXXd(void); - -/* lods */ -void LODSB_ALXb(void); -void LODSW_AXXw(void); -void LODSD_EAXXd(void); - -/* stos */ -void STOSB_YbAL(void); -void STOSW_YwAX(void); -void STOSD_YdEAX(void); -void STOSB_YbAL_rep(int reptype); -void STOSW_YwAX_rep(int reptype); -void STOSD_YdEAX_rep(int reptype); - -/* repeat */ -void _REPNE(void); -void _REPE(void); - -/* ins */ -void INSB_YbDX(void); -void INSW_YwDX(void); -void INSD_YdDX(void); - -/* outs */ -void OUTSB_DXXb(void); -void OUTSW_DXXw(void); -void OUTSD_DXXd(void); - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_STRING_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_STRING_H__ +#define IA32_CPU_INSTRUCTION_STRING_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define STRING_DIR ((CPU_FLAG & D_FLAG) ? -1 : 1) +#define STRING_DIRx2 ((CPU_FLAG & D_FLAG) ? -2 : 2) +#define STRING_DIRx4 ((CPU_FLAG & D_FLAG) ? -4 : 4) + +/* movs */ +void MOVSB_XbYb(void); +void MOVSW_XwYw(void); +void MOVSD_XdYd(void); +void MOVSB_XbYb_rep(int reptype); +void MOVSW_XwYw_rep(int reptype); +void MOVSD_XdYd_rep(int reptype); + +/* cmps */ +void CMPSB_XbYb(void); +void CMPSW_XwYw(void); +void CMPSD_XdYd(void); +void CMPSB_XbYb_rep(int reptype); +void CMPSW_XwYw_rep(int reptype); +void CMPSD_XdYd_rep(int reptype); + +/* scas */ +void SCASB_ALXb(void); +void SCASW_AXXw(void); +void SCASD_EAXXd(void); + +/* lods */ +void LODSB_ALXb(void); +void LODSW_AXXw(void); +void LODSD_EAXXd(void); + +/* stos */ +void STOSB_YbAL(void); +void STOSW_YwAX(void); +void STOSD_YdEAX(void); +void STOSB_YbAL_rep(int reptype); +void STOSW_YwAX_rep(int reptype); +void STOSD_YdEAX_rep(int reptype); + +/* repeat */ +void _REPNE(void); +void _REPE(void); + +/* ins */ +void INSB_YbDX(void); +void INSW_YwDX(void); +void INSD_YdDX(void); + +/* outs */ +void OUTSB_DXXb(void); +void OUTSW_DXXw(void); +void OUTSD_DXXd(void); + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_STRING_H__ */ diff --git a/i386c/ia32/instructions/system_inst.c b/i386c/ia32/instructions/system_inst.c old mode 100755 new mode 100644 index 2760bbf5..162c61c0 --- a/i386c/ia32/instructions/system_inst.c +++ b/i386c/ia32/instructions/system_inst.c @@ -1,1299 +1,1299 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include "ia32/ia32.mcr" -#include - -#include "system_inst.h" - -#if defined(USE_CUSTOM_HOOKINST) -#include -#endif - - -void CPUCALL -LGDT_Ms(UINT32 op) -{ - UINT32 madr; - UINT32 base; - UINT16 limit; - - if (op < 0xc0) { - if (!CPU_STAT_PM || (CPU_STAT_CPL == 0 && !CPU_STAT_VM86)) { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - limit = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - base = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 2); - if (!CPU_INST_OP32) { - base &= 0x00ffffff; - } - -#if defined(MORE_DEBUG) - gdtr_dump(base, limit); -#endif - - CPU_GDTR_BASE = base; - CPU_GDTR_LIMIT = limit; - return; - } - VERBOSE(("LGDT: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -SGDT_Ms(UINT32 op) -{ - UINT32 madr; - UINT32 base; - UINT16 limit; - - if (op < 0xc0) { - CPU_WORKCLOCK(11); - limit = CPU_GDTR_LIMIT; - base = CPU_GDTR_BASE; - - // SGDTではi386以降常時32bitでStoreされるらしい。 - // 新しめのIntel SDMの擬似コードではそのように書かれている - //if (!CPU_INST_OP32) { - // base &= 0x00ffffff; - //} - - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, limit); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 2, base); - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -LLDT_Ew(UINT32 op) -{ - UINT32 madr; - UINT16 src; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - if (CPU_STAT_CPL == 0) { - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - src = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - load_ldtr(src, GP_EXCEPTION); - return; - } - VERBOSE(("LLDT: CPL(%d) != 0", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - VERBOSE(("LLDT: real-mode or VM86")); - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -SLDT_Ew(UINT32 op) -{ - UINT32 madr; - UINT16 ldtr; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - ldtr = CPU_LDTR; - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - if (CPU_INST_OP32) { - *(CPU_REG32_B20(op)) = ldtr; - } else { - *(CPU_REG16_B20(op)) = ldtr; - } - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, ldtr); - } - return; - } - VERBOSE(("SLDT: real-mode or VM86")); - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -LTR_Ew(UINT32 op) -{ - UINT32 madr; - UINT16 src; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - if (CPU_STAT_CPL == 0) { - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - src = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - load_tr(src); - return; - } - VERBOSE(("LTR: CPL(%d) != 0", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - VERBOSE(("LTR: real-mode or VM86")); - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -STR_Ew(UINT32 op) -{ - UINT32 madr; - UINT16 tr; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - tr = CPU_TR; - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - if (CPU_INST_OP32) { - *(CPU_REG32_B20(op)) = tr; - } else { - *(CPU_REG16_B20(op)) = tr; - } - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, tr); - } - return; - } - VERBOSE(("STR: real-mode or VM86")); - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -LIDT_Ms(UINT32 op) -{ - UINT32 madr; - UINT32 base; - UINT16 limit; - - if (op < 0xc0) { - if (!CPU_STAT_PM || (CPU_STAT_CPL == 0 && !CPU_STAT_VM86)) { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - limit = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - base = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 2); - if (!CPU_INST_OP32) { - base &= 0x00ffffff; - } - -#if defined(MORE_DEBUG) - idtr_dump(base, limit); -#endif - - CPU_IDTR_BASE = base; - CPU_IDTR_LIMIT = limit; - return; - } - VERBOSE(("LIDT: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -SIDT_Ms(UINT32 op) -{ - UINT32 madr; - UINT32 base; - UINT16 limit; - - if (op < 0xc0) { - CPU_WORKCLOCK(11); - limit = CPU_IDTR_LIMIT; - base = CPU_IDTR_BASE; - if (!CPU_INST_OP32) { - base &= 0x00ffffff; - } - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, limit); - cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 2, base); - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -MOV_CdRd(void) -{ - UINT32 op, src; - UINT32 reg; - int idx; - - CPU_WORKCLOCK(11); - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { - VERBOSE(("MOV_CdRd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - - src = *(CPU_REG32_B20(op)); - idx = (op >> 3) & 7; - - switch (idx) { - case 0: /* CR0 */ - /* - * 0 = PE (protect enable) - * 1 = MP (monitor coprocesser) - * 2 = EM (emulation) - * 3 = TS (task switch) - * 4 = ET (extend type, FPU present = 1) - * 5 = NE (numeric error) - * 16 = WP (write protect) - * 18 = AM (alignment mask) - * 29 = NW (not write-through) - * 30 = CD (cache diable) - * 31 = PG (pageing) - */ - - /* 下巻 p.182 割り込み 13 - 一般保護例外 */ - if ((src & (CPU_CR0_PE|CPU_CR0_PG)) == (UINT32)CPU_CR0_PG) { - EXCEPTION(GP_EXCEPTION, 0); - } - if ((src & (CPU_CR0_NW|CPU_CR0_CD)) == CPU_CR0_NW) { - EXCEPTION(GP_EXCEPTION, 0); - } - - reg = CPU_CR0; - src &= CPU_CR0_ALL; -#if defined(USE_FPU) - if(i386cpuid.cpu_feature & CPU_FEATURE_FPU){ - src |= CPU_CR0_ET; /* FPU present */ - //src &= ~CPU_CR0_EM; - }else{ - src |= CPU_CR0_EM | CPU_CR0_NE; - src &= ~(CPU_CR0_MP | CPU_CR0_ET); - } -#else - src |= CPU_CR0_EM | CPU_CR0_NE; - src &= ~(CPU_CR0_MP | CPU_CR0_ET); -#endif - CPU_CR0 = src; - VERBOSE(("MOV_CdRd: %04x:%08x: cr0: 0x%08x <- 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR0, reg32_str[op & 7])); - - if ((reg ^ CPU_CR0) & (CPU_CR0_PE|CPU_CR0_PG)) { - tlb_flush_all(); - } - if ((reg ^ CPU_CR0) & CPU_CR0_PE) { - if (CPU_CR0 & CPU_CR0_PE) { - change_pm(1); - } - } - if ((reg ^ CPU_CR0) & CPU_CR0_PG) { - if (CPU_CR0 & CPU_CR0_PG) { - change_pg(1); - } else { - change_pg(0); - } - } - if ((reg ^ CPU_CR0) & CPU_CR0_PE) { - if (!(CPU_CR0 & CPU_CR0_PE)) { - change_pm(0); - } - } - - CPU_STAT_WP = (CPU_CR0 & CPU_CR0_WP) ? 0x10 : 0; - break; - - case 2: /* CR2 */ - reg = CPU_CR2; - CPU_CR2 = src; /* page fault linear address */ - VERBOSE(("MOV_CdRd: %04x:%08x: cr2: 0x%08x <- 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR2, reg32_str[op & 7])); - break; - - case 3: /* CR3 */ - /* - * 31-12 = page directory base - * 4 = PCD (page level cache diable) - * 3 = PWT (page level write throgh) - */ - reg = CPU_CR3; - set_cr3(src); - VERBOSE(("MOV_CdRd: %04x:%08x: cr3: 0x%08x <- 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR3, reg32_str[op & 7])); - break; - - case 4: /* CR4 */ - /* - * 10 = OSXMMEXCPT (support non masking exception by OS) - * 9 = OSFXSR (support FXSAVE, FXRSTOR by OS) - * 8 = PCE (performance monitoring counter enable) - * 7 = PGE (page global enable) - * 6 = MCE (machine check enable) - * 5 = PAE (physical address extention) - * 4 = PSE (page size extention) - * 3 = DE (debug extention) - * 2 = TSD (time stamp diable) - * 1 = PVI (protected mode virtual interrupt) - * 0 = VME (VM8086 mode extention) - */ - reg = CPU_CR4_PCE; /* allow bit */ - if (i386cpuid.cpu_feature & CPU_FEATURE_PGE) { - reg |= CPU_CR4_PGE; - } - if (i386cpuid.cpu_feature & CPU_FEATURE_VME) { - reg |= CPU_CR4_PVI | CPU_CR4_VME; - } - if (i386cpuid.cpu_feature & CPU_FEATURE_FXSR) { - reg |= CPU_CR4_OSFXSR; - } - if (i386cpuid.cpu_feature & CPU_FEATURE_SSE) { - reg |= CPU_CR4_OSXMMEXCPT; - } - if (src & ~reg) { - //if (src & 0xfffffc00) { - if (src & 0xfffff800) { - EXCEPTION(GP_EXCEPTION, 0); - } - if ((src & ~reg) != CPU_CR4_DE) { // XXX: debug extentionは警告しない - ia32_warning("MOV_CdRd: CR4 <- 0x%08x", src); - } - } - - reg = CPU_CR4; - CPU_CR4 = src; - VERBOSE(("MOV_CdRd: %04x:%08x: cr4: 0x%08x <- 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR4, reg32_str[op & 7])); - - if ((reg ^ CPU_CR4) & (CPU_CR4_PSE|CPU_CR4_PGE|CPU_CR4_PAE|CPU_CR4_PVI|CPU_CR4_VME|CPU_CR4_OSFXSR|CPU_CR4_OSXMMEXCPT)) { - tlb_flush_all(); - } - break; - - default: - ia32_panic("MOV_CdRd: CR reg index (%d)", idx); - /*NOTREACHED*/ - break; - } - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -MOV_RdCd(void) -{ - UINT32 *out; - UINT32 op; - int idx; - - CPU_WORKCLOCK(11); - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { - VERBOSE(("MOV_RdCd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - - out = CPU_REG32_B20(op); - idx = (op >> 3) & 7; - - switch (idx) { - case 0: - *out = CPU_CR0; - break; - - case 2: - *out = CPU_CR2; - break; - - case 3: - *out = CPU_CR3; - break; - - case 4: - *out = CPU_CR4; - break; - - default: - ia32_panic("MOV_RdCd: CR reg index (%d)", idx); - /*NOTREACHED*/ - break; - } - VERBOSE(("MOV_RdCd: %04x:%08x: cr%d: 0x%08x -> %s", CPU_CS, CPU_PREV_EIP, idx, *out, reg32_str[op & 7])); - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -LMSW_Ew(UINT32 op) -{ - UINT32 src, madr; - UINT32 cr0; - - if (!CPU_STAT_PM || CPU_STAT_CPL == 0) { - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - src = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - - cr0 = CPU_CR0; - CPU_CR0 &= ~0xe; /* can't switch back from protected mode */ - CPU_CR0 |= (src & 0xf); /* TS, EM, MP, PE */ - if (!(cr0 & CPU_CR0_PE) && (src & CPU_CR0_PE)) { - change_pm(1); /* switch to protected mode */ - } - return; - } - VERBOSE(("LMSW: CPL(%d) != 0", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); -} - -void CPUCALL -SMSW_Ew(UINT32 op) -{ - UINT32 madr; - - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - if (CPU_INST_OP32) { - *(CPU_REG32_B20(op)) = (UINT16)CPU_CR0; - } else { - *(CPU_REG16_B20(op)) = (UINT16)CPU_CR0; - } - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)CPU_CR0); - } -} - -void -CLTS(void) -{ - - CPU_WORKCLOCK(5); - if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL != 0))) { - VERBOSE(("CLTS: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - CPU_CR0 &= ~CPU_CR0_TS; -} - -void -ARPL_EwGw(void) -{ - UINT32 op, madr; - UINT src, dst; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - PREPART_EA_REG16(op, src); - if (op >= 0xc0) { - CPU_WORKCLOCK(2); - dst = *(CPU_REG16_B20(op)); - if ((dst & 3) < (src & 3)) { - CPU_FLAGL |= Z_FLAG; - dst &= ~3; - dst |= (src & 3); - *(CPU_REG16_B20(op)) = (UINT16)dst; - } else { - CPU_FLAGL &= ~Z_FLAG; - } - } else { - CPU_WORKCLOCK(3); - madr = calc_ea_dst(op); - dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - if ((dst & 3) < (src & 3)) { - CPU_FLAGL |= Z_FLAG; - dst &= ~3; - dst |= (src & 3); - cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)dst); - } else { - CPU_FLAGL &= ~Z_FLAG; - } - } - return; - } - VERBOSE(("ARPL: real-mode or VM86")); - EXCEPTION(UD_EXCEPTION, 0); -} - -/* - * DPL - */ -void -LAR_GwEw(void) -{ - selector_t sel; - UINT16 *out; - UINT32 op; - UINT32 h; - int rv; - UINT16 selector; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - PREPART_REG16_EA(op, selector, out, 5, 11); - - rv = parse_selector(&sel, selector); - if (rv < 0) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - - if (!SEG_IS_SYSTEM(&sel.desc)) { - /* code or data segment */ - if ((SEG_IS_DATA(&sel.desc) - || !SEG_IS_CONFORMING_CODE(&sel.desc))) { - /* data or non-conforming code segment */ - if ((sel.desc.dpl < CPU_STAT_CPL) - || (sel.desc.dpl < sel.rpl)) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - } - } else { - /* system segment */ - switch (sel.desc.type) { - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_LDT: - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - case CPU_SYSDESC_TYPE_CALL_16: - case CPU_SYSDESC_TYPE_TASK: - case CPU_SYSDESC_TYPE_TSS_32: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - case CPU_SYSDESC_TYPE_CALL_32: - break; - - default: - CPU_FLAGL &= ~Z_FLAG; - return; - } - } - - h = cpu_kmemoryread_d(sel.addr + 4); - *out = (UINT16)(h & 0xff00); - CPU_FLAGL |= Z_FLAG; - return; - } - VERBOSE(("LAR: real-mode or VM86")); - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LAR_GdEw(void) -{ - selector_t sel; - UINT32 *out; - UINT32 op; - UINT32 h; - int rv; - UINT32 selector; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - PREPART_REG32_EA(op, selector, out, 5, 11); - - rv = parse_selector(&sel, (UINT16)selector); - if (rv < 0) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - - if (!SEG_IS_SYSTEM(&sel.desc)) { - /* code or data segment */ - if ((SEG_IS_DATA(&sel.desc) - || !SEG_IS_CONFORMING_CODE(&sel.desc))) { - /* data or non-conforming code segment */ - if ((sel.desc.dpl < CPU_STAT_CPL) - || (sel.desc.dpl < sel.rpl)) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - } - } else { - /* system segment */ - switch (sel.desc.type) { - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_LDT: - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - case CPU_SYSDESC_TYPE_CALL_16: - case CPU_SYSDESC_TYPE_TASK: - case CPU_SYSDESC_TYPE_TSS_32: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - case CPU_SYSDESC_TYPE_CALL_32: - break; - - default: - CPU_FLAGL &= ~Z_FLAG; - return; - } - } - - h = cpu_kmemoryread_d(sel.addr + 4); - *out = h & 0x00ffff00; /* 0x00fxff00, x? */ - CPU_FLAGL |= Z_FLAG; - return; - } - VERBOSE(("LAR: real-mode or VM86")); - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LSL_GwEw(void) -{ - selector_t sel; - UINT16 *out; - UINT32 op; - int rv; - UINT16 selector; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - PREPART_REG16_EA(op, selector, out, 5, 11); - - rv = parse_selector(&sel, selector); - if (rv < 0) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - - if (!SEG_IS_SYSTEM(&sel.desc)) { - /* code or data segment */ - if ((SEG_IS_DATA(&sel.desc) - || !SEG_IS_CONFORMING_CODE(&sel.desc))) { - /* data or non-conforming code segment */ - if ((sel.desc.dpl < CPU_STAT_CPL) - || (sel.desc.dpl < sel.rpl)) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - } - } else { - /* system segment */ - switch (sel.desc.type) { - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_LDT: - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - case CPU_SYSDESC_TYPE_TSS_32: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - break; - - default: - CPU_FLAGL &= ~Z_FLAG; - return; - } - } - - *out = (UINT16)sel.desc.u.seg.limit; - CPU_FLAGL |= Z_FLAG; - return; - } - VERBOSE(("LSL: real-mode or VM86")); - EXCEPTION(UD_EXCEPTION, 0); -} - -void -LSL_GdEw(void) -{ - selector_t sel; - UINT32 *out; - UINT32 op; - int rv; - UINT32 selector; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - PREPART_REG32_EA(op, selector, out, 5, 11); - - rv = parse_selector(&sel, (UINT16)selector); - if (rv < 0) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - - if (!SEG_IS_SYSTEM(&sel.desc)) { - /* code or data segment */ - if ((SEG_IS_DATA(&sel.desc) - || !SEG_IS_CONFORMING_CODE(&sel.desc))) { - /* data or non-conforming code segment */ - if ((sel.desc.dpl < CPU_STAT_CPL) - || (sel.desc.dpl < sel.rpl)) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - } - } else { - /* system segment */ - switch (sel.desc.type) { - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_LDT: - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - case CPU_SYSDESC_TYPE_TSS_32: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - break; - - default: - CPU_FLAGL &= ~Z_FLAG; - return; - } - } - - *out = sel.desc.u.seg.limit; - CPU_FLAGL |= Z_FLAG; - return; - } - VERBOSE(("LSL: real-mode or VM86")); - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -VERR_Ew(UINT32 op) -{ - selector_t sel; - UINT32 madr; - int rv; - UINT16 selector; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - selector = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - selector = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - - rv = parse_selector(&sel, selector); - if (rv < 0) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - - /* system segment */ - if (SEG_IS_SYSTEM(&sel.desc)) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - - /* data or non-conforming code segment */ - if ((SEG_IS_DATA(&sel.desc) - || !SEG_IS_CONFORMING_CODE(&sel.desc))) { - if ((sel.desc.dpl < CPU_STAT_CPL) - || (sel.desc.dpl < sel.rpl)) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - } - /* code segment is not readable */ - if (SEG_IS_CODE(&sel.desc) - && !SEG_IS_READABLE_CODE(&sel.desc)) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - - CPU_FLAGL |= Z_FLAG; - return; - } - VERBOSE(("VERR: real-mode or VM86")); - EXCEPTION(UD_EXCEPTION, 0); -} - -void CPUCALL -VERW_Ew(UINT32 op) -{ - selector_t sel; - UINT32 madr; - int rv; - UINT16 selector; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - if (op >= 0xc0) { - CPU_WORKCLOCK(5); - selector = *(CPU_REG16_B20(op)); - } else { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - selector = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); - } - - rv = parse_selector(&sel, selector); - if (rv < 0) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - - /* system segment || code segment */ - if (SEG_IS_SYSTEM(&sel.desc) || SEG_IS_CODE(&sel.desc)) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - /* data segment is not writable */ - if (!SEG_IS_WRITABLE_DATA(&sel.desc)) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - /* privilege level */ - if ((CPU_STAT_CPL > sel.desc.dpl) || (sel.rpl > sel.desc.dpl)) { - CPU_FLAGL &= ~Z_FLAG; - return; - } - - CPU_FLAGL |= Z_FLAG; - return; - } - VERBOSE(("VERW: real-mode or VM86")); - EXCEPTION(UD_EXCEPTION, 0); -} - -void -MOV_DdRd(void) -{ - UINT32 src; - UINT op; - int idx; - - CPU_WORKCLOCK(11); - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { - VERBOSE(("MOV_DdRd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - - if (CPU_DR7 & CPU_DR7_GD) { - CPU_DR6 |= CPU_DR6_BD; - CPU_DR7 &= ~CPU_DR7_GD; - EXCEPTION(DB_EXCEPTION, 0); - } - - src = *(CPU_REG32_B20(op)); - idx = (op >> 3) & 7; - - CPU_DR(idx) = src; - switch (idx) { - case 0: - case 1: - case 2: - case 3: - CPU_DR(idx) = src; - break; - - case 6: - CPU_DR6 = src; - break; - - case 7: - CPU_DR7 = src; - CPU_STAT_BP = 0; - break; - - default: - ia32_panic("MOV_DdRd: DR reg index (%d)", idx); - /*NOTREACHED*/ - break; - } - - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -MOV_RdDd(void) -{ - UINT32 *out; - UINT op; - int idx; - - CPU_WORKCLOCK(11); - GET_MODRM_PCBYTE(op); - if (op >= 0xc0) { - if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { - VERBOSE(("MOV_RdDd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - - if (CPU_DR7 & CPU_DR7_GD) { - CPU_DR6 |= CPU_DR6_BD; - CPU_DR7 &= ~CPU_DR7_GD; - EXCEPTION(DB_EXCEPTION, 0); - } - - out = CPU_REG32_B20(op); - idx = (op >> 3) & 7; - - switch (idx) { - case 0: - case 1: - case 2: - case 3: - *out = CPU_DR(idx); - break; - - case 4: - case 6: - *out = (CPU_DR6 & 0x0000f00f) | 0xffff0ff0; - break; - - case 7: - *out = CPU_DR7; - break; - - default: - ia32_panic("MOV_RdDd: DR reg index (%d)", idx); - /*NOTREACHED*/ - break; - } - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -INVD(void) -{ - - CPU_WORKCLOCK(11); - if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { - VERBOSE(("INVD: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } -} - -void -WBINVD(void) -{ - - CPU_WORKCLOCK(11); - if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { - VERBOSE(("WBINVD: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } -} - -void CPUCALL -INVLPG(UINT32 op) -{ - descriptor_t *sdp; - UINT32 madr; - int idx; - - if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { - VERBOSE(("INVLPG: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - - if (op < 0xc0) { - CPU_WORKCLOCK(11); - madr = calc_ea_dst(op); - - idx = CPU_INST_SEGREG_INDEX; - sdp = &CPU_STAT_SREG(idx); - if (!SEG_IS_VALID(sdp)) { - EXCEPTION(GP_EXCEPTION, 0); - } - switch (sdp->type) { - case 4: case 5: case 6: case 7: - if (madr <= sdp->u.seg.limit) { - EXCEPTION((idx == CPU_SS_INDEX) ? - SS_EXCEPTION: GP_EXCEPTION, 0); - } - break; - - default: - if (madr > sdp->u.seg.limit) { - EXCEPTION((idx == CPU_SS_INDEX) ? - SS_EXCEPTION: GP_EXCEPTION, 0); - } - break; - } - tlb_flush_page(sdp->u.seg.segbase + madr); - return; - } - EXCEPTION(UD_EXCEPTION, 0); -} - -void -_LOCK(void) -{ - - /* Nothing to do */ -} - -void -HLT(void) -{ -#if defined(USE_CUSTOM_HOOKINST) - if (bioshookinfo.hookinst == 0xF4) - { - if (!CPU_STAT_PM || CPU_STAT_VM86) - { - UINT32 adrs; - adrs = CPU_PREV_EIP + (CPU_CS << 4); - if ((adrs >= 0xf8000) && (adrs < 0x100000)) - { - ia32_bioscall(); - return; - } - } - } -#endif - - if (CPU_STAT_PM && CPU_STAT_CPL != 0) { - VERBOSE(("HLT: CPL(%d) != 0", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - - VERBOSE(("HLT: do HLT.")); - CPU_HALT(); - CPU_EIP = CPU_PREV_EIP; - CPU_STAT_HLT = 1; -} - -void -RSM(void) -{ - - ia32_panic("RSM: not implemented yet!"); -} - -void -RDMSR(void) -{ - int idx; - - if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { - VERBOSE(("RDMSR: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - - idx = CPU_ECX; - switch (idx) { - case 0x174: - CPU_EDX = (UINT32)((i386msr.reg.ia32_sysenter_cs >> 32) & 0xffffffff); - CPU_EAX = (UINT32)((i386msr.reg.ia32_sysenter_cs ) & 0xffffffff); - break; - case 0x175: - CPU_EDX = (UINT32)((i386msr.reg.ia32_sysenter_esp >> 32) & 0xffffffff); - CPU_EAX = (UINT32)((i386msr.reg.ia32_sysenter_esp ) & 0xffffffff); - break; - case 0x176: - CPU_EDX = (UINT32)((i386msr.reg.ia32_sysenter_eip >> 32) & 0xffffffff); - CPU_EAX = (UINT32)((i386msr.reg.ia32_sysenter_eip ) & 0xffffffff); - break; - case 0x10: - RDTSC(); - break; - case 0x2c: - CPU_EDX = 0x00000000; - CPU_EAX = 0xfee00800; - break; - //case 0x1b: - // CPU_EDX = 0x00000000; - // CPU_EAX = 0x00000010; - // break; - default: - CPU_EDX = CPU_EAX = 0; - //EXCEPTION(GP_EXCEPTION, 0); // XXX: とりあえず通す - break; - } -} - -void -WRMSR(void) -{ - int idx; - - if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { - VERBOSE(("WRMSR: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - - idx = CPU_ECX; - switch (idx) { - case 0x174: - i386msr.reg.ia32_sysenter_cs = ((UINT64)CPU_EDX << 32) | ((UINT64)CPU_EAX); - break; - case 0x175: - i386msr.reg.ia32_sysenter_esp = ((UINT64)CPU_EDX << 32) | ((UINT64)CPU_EAX); - break; - case 0x176: - i386msr.reg.ia32_sysenter_eip = ((UINT64)CPU_EDX << 32) | ((UINT64)CPU_EAX); - break; - /* MTRR への書き込み時 tlb_flush_all(); */ - default: - //EXCEPTION(GP_EXCEPTION, 0); // XXX: とりあえず通す - break; - } -} - -#if defined(SUPPORT_GAMEPORT) -int gameport_tsccounter = 0; -#endif -void -RDTSC(void) -{ -#if defined(SUPPORT_IA32_HAXM)&&defined(_WIN32) - LARGE_INTEGER li = {0}; - LARGE_INTEGER qpf; - QueryPerformanceCounter(&li); - if (QueryPerformanceFrequency(&qpf)) { - li.QuadPart = li.QuadPart * pccore.realclock / qpf.QuadPart; - } - CPU_EDX = li.HighPart; - CPU_EAX = li.LowPart; -#else - if(np2cfg.consttsc){ - // CPUクロックに依存しないカウンタ値にする - UINT64 tsc_tmp; - if(CPU_REMCLOCK != -1){ - tsc_tmp = CPU_MSR_TSC - CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple; - }else{ - tsc_tmp = CPU_MSR_TSC; - } - CPU_EDX = ((tsc_tmp >> 32) & 0xffffffff); - CPU_EAX = (tsc_tmp & 0xffffffff); - }else{ - // CPUクロックに依存するカウンタ値にする - static UINT64 tsc_last = 0; - static UINT64 tsc_cur = 0; - UINT64 tsc_tmp; - if(CPU_REMCLOCK != -1){ - tsc_tmp = CPU_MSR_TSC - CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple; - }else{ - tsc_tmp = CPU_MSR_TSC; - } - tsc_cur += (tsc_tmp - tsc_last) * pccore.multiple / pccore.maxmultiple; - tsc_last = tsc_tmp; - CPU_EDX = ((tsc_cur >> 32) & 0xffffffff); - CPU_EAX = (tsc_cur & 0xffffffff); - } -#if defined(SUPPORT_GAMEPORT) - if(gameport_tsccounter < INT_MAX) gameport_tsccounter++; -#endif -#endif -// ia32_panic("RDTSC: not implemented yet!"); -} - -void -RDPMC(void) -{ - int idx; - - if(!(CPU_CR4 & CPU_CR4_PCE)){ - if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { - VERBOSE(("RDPMC: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - } - - idx = CPU_ECX; - switch (idx) { - default: - CPU_EDX = CPU_EAX = 0; - } -} - -void -MOV_TdRd(void) -{ - - ia32_panic("MOV_TdRd: not implemented yet!"); -} - -void -MOV_RdTd(void) -{ - - ia32_panic("MOV_RdTd: not implemented yet!"); -} - -// 中途半端&ノーチェック注意 -void -SYSENTER(void) -{ - // SEPなしならUD(無効オペコード例外)を発生させる - if(!(i386cpuid.cpu_feature & CPU_FEATURE_SEP)){ - EXCEPTION(UD_EXCEPTION, 0); - } - // プロテクトモードチェック - if (!CPU_STAT_PM) { - EXCEPTION(GP_EXCEPTION, 0); - } - // MSRレジスタチェック - if (i386msr.reg.ia32_sysenter_cs == 0) { - EXCEPTION(GP_EXCEPTION, 0); - } - - CPU_EFLAG = CPU_EFLAG & ~(VM_FLAG|I_FLAG|RF_FLAG); - CPU_CS = (UINT32)i386msr.reg.ia32_sysenter_cs; - - CPU_SS = CPU_CS + 8; - - CPU_ESP = (UINT32)i386msr.reg.ia32_sysenter_esp; - CPU_EIP = (UINT32)i386msr.reg.ia32_sysenter_eip; - - CPU_STAT_CPL = 0; - CPU_STAT_USER_MODE = (CPU_STAT_CPL == 3) ? CPU_MODE_USER : CPU_MODE_SUPERVISER; -} - -// 中途半端&ノーチェック注意 -void -SYSEXIT(void) -{ - // SEPなしならUD(無効オペコード例外)を発生させる - if(!(i386cpuid.cpu_feature & CPU_FEATURE_SEP)){ - EXCEPTION(UD_EXCEPTION, 0); - } - // プロテクトモードチェック - if (!CPU_STAT_PM) { - EXCEPTION(GP_EXCEPTION, 0); - } - // MSRレジスタチェック - if (i386msr.reg.ia32_sysenter_cs == 0) { - EXCEPTION(GP_EXCEPTION, 0); - } - // 特権レベルチェック - if (CPU_STAT_CPL != 0) { - VERBOSE(("SYSENTER: CPL(%d) != 0", CPU_STAT_CPL)); - EXCEPTION(GP_EXCEPTION, 0); - } - - CPU_CS = (UINT32)i386msr.reg.ia32_sysenter_cs + 16; - - CPU_SS = (UINT32)i386msr.reg.ia32_sysenter_cs + 24; - - CPU_ESP = CPU_ECX; - CPU_EIP = CPU_EDX; - - CPU_STAT_CPL = 3; - CPU_STAT_USER_MODE = (CPU_STAT_CPL == 3) ? CPU_MODE_USER : CPU_MODE_SUPERVISER; +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include "ia32/ia32.mcr" +#include + +#include "system_inst.h" + +#if defined(USE_CUSTOM_HOOKINST) +#include +#endif + + +void CPUCALL +LGDT_Ms(UINT32 op) +{ + UINT32 madr; + UINT32 base; + UINT16 limit; + + if (op < 0xc0) { + if (!CPU_STAT_PM || (CPU_STAT_CPL == 0 && !CPU_STAT_VM86)) { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + limit = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + base = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 2); + if (!CPU_INST_OP32) { + base &= 0x00ffffff; + } + +#if defined(MORE_DEBUG) + gdtr_dump(base, limit); +#endif + + CPU_GDTR_BASE = base; + CPU_GDTR_LIMIT = limit; + return; + } + VERBOSE(("LGDT: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +SGDT_Ms(UINT32 op) +{ + UINT32 madr; + UINT32 base; + UINT16 limit; + + if (op < 0xc0) { + CPU_WORKCLOCK(11); + limit = CPU_GDTR_LIMIT; + base = CPU_GDTR_BASE; + + // SGDTではi386以降常時32bitでStoreされるらしい。 + // 新しめのIntel SDMの擬似コードではそのように書かれている + //if (!CPU_INST_OP32) { + // base &= 0x00ffffff; + //} + + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, limit); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 2, base); + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +LLDT_Ew(UINT32 op) +{ + UINT32 madr; + UINT16 src; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + if (CPU_STAT_CPL == 0) { + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + src = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + load_ldtr(src, GP_EXCEPTION); + return; + } + VERBOSE(("LLDT: CPL(%d) != 0", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + VERBOSE(("LLDT: real-mode or VM86")); + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +SLDT_Ew(UINT32 op) +{ + UINT32 madr; + UINT16 ldtr; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + ldtr = CPU_LDTR; + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + if (CPU_INST_OP32) { + *(CPU_REG32_B20(op)) = ldtr; + } else { + *(CPU_REG16_B20(op)) = ldtr; + } + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, ldtr); + } + return; + } + VERBOSE(("SLDT: real-mode or VM86")); + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +LTR_Ew(UINT32 op) +{ + UINT32 madr; + UINT16 src; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + if (CPU_STAT_CPL == 0) { + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + src = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + load_tr(src); + return; + } + VERBOSE(("LTR: CPL(%d) != 0", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + VERBOSE(("LTR: real-mode or VM86")); + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +STR_Ew(UINT32 op) +{ + UINT32 madr; + UINT16 tr; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + tr = CPU_TR; + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + if (CPU_INST_OP32) { + *(CPU_REG32_B20(op)) = tr; + } else { + *(CPU_REG16_B20(op)) = tr; + } + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, tr); + } + return; + } + VERBOSE(("STR: real-mode or VM86")); + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +LIDT_Ms(UINT32 op) +{ + UINT32 madr; + UINT32 base; + UINT16 limit; + + if (op < 0xc0) { + if (!CPU_STAT_PM || (CPU_STAT_CPL == 0 && !CPU_STAT_VM86)) { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + limit = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + base = cpu_vmemoryread_d(CPU_INST_SEGREG_INDEX, madr + 2); + if (!CPU_INST_OP32) { + base &= 0x00ffffff; + } + +#if defined(MORE_DEBUG) + idtr_dump(base, limit); +#endif + + CPU_IDTR_BASE = base; + CPU_IDTR_LIMIT = limit; + return; + } + VERBOSE(("LIDT: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +SIDT_Ms(UINT32 op) +{ + UINT32 madr; + UINT32 base; + UINT16 limit; + + if (op < 0xc0) { + CPU_WORKCLOCK(11); + limit = CPU_IDTR_LIMIT; + base = CPU_IDTR_BASE; + if (!CPU_INST_OP32) { + base &= 0x00ffffff; + } + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, limit); + cpu_vmemorywrite_d(CPU_INST_SEGREG_INDEX, madr + 2, base); + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +MOV_CdRd(void) +{ + UINT32 op, src; + UINT32 reg; + int idx; + + CPU_WORKCLOCK(11); + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("MOV_CdRd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + + src = *(CPU_REG32_B20(op)); + idx = (op >> 3) & 7; + + switch (idx) { + case 0: /* CR0 */ + /* + * 0 = PE (protect enable) + * 1 = MP (monitor coprocesser) + * 2 = EM (emulation) + * 3 = TS (task switch) + * 4 = ET (extend type, FPU present = 1) + * 5 = NE (numeric error) + * 16 = WP (write protect) + * 18 = AM (alignment mask) + * 29 = NW (not write-through) + * 30 = CD (cache diable) + * 31 = PG (pageing) + */ + + /* 下巻 p.182 割り込み 13 - 一般保護例外 */ + if ((src & (CPU_CR0_PE|CPU_CR0_PG)) == (UINT32)CPU_CR0_PG) { + EXCEPTION(GP_EXCEPTION, 0); + } + if ((src & (CPU_CR0_NW|CPU_CR0_CD)) == CPU_CR0_NW) { + EXCEPTION(GP_EXCEPTION, 0); + } + + reg = CPU_CR0; + src &= CPU_CR0_ALL; +#if defined(USE_FPU) + if(i386cpuid.cpu_feature & CPU_FEATURE_FPU){ + src |= CPU_CR0_ET; /* FPU present */ + //src &= ~CPU_CR0_EM; + }else{ + src |= CPU_CR0_EM | CPU_CR0_NE; + src &= ~(CPU_CR0_MP | CPU_CR0_ET); + } +#else + src |= CPU_CR0_EM | CPU_CR0_NE; + src &= ~(CPU_CR0_MP | CPU_CR0_ET); +#endif + CPU_CR0 = src; + VERBOSE(("MOV_CdRd: %04x:%08x: cr0: 0x%08x <- 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR0, reg32_str[op & 7])); + + if ((reg ^ CPU_CR0) & (CPU_CR0_PE|CPU_CR0_PG)) { + tlb_flush_all(); + } + if ((reg ^ CPU_CR0) & CPU_CR0_PE) { + if (CPU_CR0 & CPU_CR0_PE) { + change_pm(1); + } + } + if ((reg ^ CPU_CR0) & CPU_CR0_PG) { + if (CPU_CR0 & CPU_CR0_PG) { + change_pg(1); + } else { + change_pg(0); + } + } + if ((reg ^ CPU_CR0) & CPU_CR0_PE) { + if (!(CPU_CR0 & CPU_CR0_PE)) { + change_pm(0); + } + } + + CPU_STAT_WP = (CPU_CR0 & CPU_CR0_WP) ? 0x10 : 0; + break; + + case 2: /* CR2 */ + reg = CPU_CR2; + CPU_CR2 = src; /* page fault linear address */ + VERBOSE(("MOV_CdRd: %04x:%08x: cr2: 0x%08x <- 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR2, reg32_str[op & 7])); + break; + + case 3: /* CR3 */ + /* + * 31-12 = page directory base + * 4 = PCD (page level cache diable) + * 3 = PWT (page level write throgh) + */ + reg = CPU_CR3; + set_cr3(src); + VERBOSE(("MOV_CdRd: %04x:%08x: cr3: 0x%08x <- 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR3, reg32_str[op & 7])); + break; + + case 4: /* CR4 */ + /* + * 10 = OSXMMEXCPT (support non masking exception by OS) + * 9 = OSFXSR (support FXSAVE, FXRSTOR by OS) + * 8 = PCE (performance monitoring counter enable) + * 7 = PGE (page global enable) + * 6 = MCE (machine check enable) + * 5 = PAE (physical address extention) + * 4 = PSE (page size extention) + * 3 = DE (debug extention) + * 2 = TSD (time stamp diable) + * 1 = PVI (protected mode virtual interrupt) + * 0 = VME (VM8086 mode extention) + */ + reg = CPU_CR4_PCE; /* allow bit */ + if (i386cpuid.cpu_feature & CPU_FEATURE_PGE) { + reg |= CPU_CR4_PGE; + } + if (i386cpuid.cpu_feature & CPU_FEATURE_VME) { + reg |= CPU_CR4_PVI | CPU_CR4_VME; + } + if (i386cpuid.cpu_feature & CPU_FEATURE_FXSR) { + reg |= CPU_CR4_OSFXSR; + } + if (i386cpuid.cpu_feature & CPU_FEATURE_SSE) { + reg |= CPU_CR4_OSXMMEXCPT; + } + if (src & ~reg) { + //if (src & 0xfffffc00) { + if (src & 0xfffff800) { + EXCEPTION(GP_EXCEPTION, 0); + } + if ((src & ~reg) != CPU_CR4_DE) { // XXX: debug extentionは警告しない + ia32_warning("MOV_CdRd: CR4 <- 0x%08x", src); + } + } + + reg = CPU_CR4; + CPU_CR4 = src; + VERBOSE(("MOV_CdRd: %04x:%08x: cr4: 0x%08x <- 0x%08x(%s)", CPU_CS, CPU_PREV_EIP, reg, CPU_CR4, reg32_str[op & 7])); + + if ((reg ^ CPU_CR4) & (CPU_CR4_PSE|CPU_CR4_PGE|CPU_CR4_PAE|CPU_CR4_PVI|CPU_CR4_VME|CPU_CR4_OSFXSR|CPU_CR4_OSXMMEXCPT)) { + tlb_flush_all(); + } + break; + + default: + ia32_panic("MOV_CdRd: CR reg index (%d)", idx); + /*NOTREACHED*/ + break; + } + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +MOV_RdCd(void) +{ + UINT32 *out; + UINT32 op; + int idx; + + CPU_WORKCLOCK(11); + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("MOV_RdCd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + + out = CPU_REG32_B20(op); + idx = (op >> 3) & 7; + + switch (idx) { + case 0: + *out = CPU_CR0; + break; + + case 2: + *out = CPU_CR2; + break; + + case 3: + *out = CPU_CR3; + break; + + case 4: + *out = CPU_CR4; + break; + + default: + ia32_panic("MOV_RdCd: CR reg index (%d)", idx); + /*NOTREACHED*/ + break; + } + VERBOSE(("MOV_RdCd: %04x:%08x: cr%d: 0x%08x -> %s", CPU_CS, CPU_PREV_EIP, idx, *out, reg32_str[op & 7])); + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +LMSW_Ew(UINT32 op) +{ + UINT32 src, madr; + UINT32 cr0; + + if (!CPU_STAT_PM || CPU_STAT_CPL == 0) { + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + src = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + src = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + + cr0 = CPU_CR0; + CPU_CR0 &= ~0xe; /* can't switch back from protected mode */ + CPU_CR0 |= (src & 0xf); /* TS, EM, MP, PE */ + if (!(cr0 & CPU_CR0_PE) && (src & CPU_CR0_PE)) { + change_pm(1); /* switch to protected mode */ + } + return; + } + VERBOSE(("LMSW: CPL(%d) != 0", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); +} + +void CPUCALL +SMSW_Ew(UINT32 op) +{ + UINT32 madr; + + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + if (CPU_INST_OP32) { + *(CPU_REG32_B20(op)) = (UINT16)CPU_CR0; + } else { + *(CPU_REG16_B20(op)) = (UINT16)CPU_CR0; + } + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)CPU_CR0); + } +} + +void +CLTS(void) +{ + + CPU_WORKCLOCK(5); + if (CPU_STAT_PM && (CPU_STAT_VM86 || (CPU_STAT_CPL != 0))) { + VERBOSE(("CLTS: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + CPU_CR0 &= ~CPU_CR0_TS; +} + +void +ARPL_EwGw(void) +{ + UINT32 op, madr; + UINT src, dst; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + PREPART_EA_REG16(op, src); + if (op >= 0xc0) { + CPU_WORKCLOCK(2); + dst = *(CPU_REG16_B20(op)); + if ((dst & 3) < (src & 3)) { + CPU_FLAGL |= Z_FLAG; + dst &= ~3; + dst |= (src & 3); + *(CPU_REG16_B20(op)) = (UINT16)dst; + } else { + CPU_FLAGL &= ~Z_FLAG; + } + } else { + CPU_WORKCLOCK(3); + madr = calc_ea_dst(op); + dst = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + if ((dst & 3) < (src & 3)) { + CPU_FLAGL |= Z_FLAG; + dst &= ~3; + dst |= (src & 3); + cpu_vmemorywrite_w(CPU_INST_SEGREG_INDEX, madr, (UINT16)dst); + } else { + CPU_FLAGL &= ~Z_FLAG; + } + } + return; + } + VERBOSE(("ARPL: real-mode or VM86")); + EXCEPTION(UD_EXCEPTION, 0); +} + +/* + * DPL + */ +void +LAR_GwEw(void) +{ + selector_t sel; + UINT16 *out; + UINT32 op; + UINT32 h; + int rv; + UINT16 selector; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + PREPART_REG16_EA(op, selector, out, 5, 11); + + rv = parse_selector(&sel, selector); + if (rv < 0) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + + if (!SEG_IS_SYSTEM(&sel.desc)) { + /* code or data segment */ + if ((SEG_IS_DATA(&sel.desc) + || !SEG_IS_CONFORMING_CODE(&sel.desc))) { + /* data or non-conforming code segment */ + if ((sel.desc.dpl < CPU_STAT_CPL) + || (sel.desc.dpl < sel.rpl)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + } + } else { + /* system segment */ + switch (sel.desc.type) { + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_LDT: + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + case CPU_SYSDESC_TYPE_CALL_16: + case CPU_SYSDESC_TYPE_TASK: + case CPU_SYSDESC_TYPE_TSS_32: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + case CPU_SYSDESC_TYPE_CALL_32: + break; + + default: + CPU_FLAGL &= ~Z_FLAG; + return; + } + } + + h = cpu_kmemoryread_d(sel.addr + 4); + *out = (UINT16)(h & 0xff00); + CPU_FLAGL |= Z_FLAG; + return; + } + VERBOSE(("LAR: real-mode or VM86")); + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LAR_GdEw(void) +{ + selector_t sel; + UINT32 *out; + UINT32 op; + UINT32 h; + int rv; + UINT32 selector; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + PREPART_REG32_EA(op, selector, out, 5, 11); + + rv = parse_selector(&sel, (UINT16)selector); + if (rv < 0) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + + if (!SEG_IS_SYSTEM(&sel.desc)) { + /* code or data segment */ + if ((SEG_IS_DATA(&sel.desc) + || !SEG_IS_CONFORMING_CODE(&sel.desc))) { + /* data or non-conforming code segment */ + if ((sel.desc.dpl < CPU_STAT_CPL) + || (sel.desc.dpl < sel.rpl)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + } + } else { + /* system segment */ + switch (sel.desc.type) { + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_LDT: + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + case CPU_SYSDESC_TYPE_CALL_16: + case CPU_SYSDESC_TYPE_TASK: + case CPU_SYSDESC_TYPE_TSS_32: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + case CPU_SYSDESC_TYPE_CALL_32: + break; + + default: + CPU_FLAGL &= ~Z_FLAG; + return; + } + } + + h = cpu_kmemoryread_d(sel.addr + 4); + *out = h & 0x00ffff00; /* 0x00fxff00, x? */ + CPU_FLAGL |= Z_FLAG; + return; + } + VERBOSE(("LAR: real-mode or VM86")); + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LSL_GwEw(void) +{ + selector_t sel; + UINT16 *out; + UINT32 op; + int rv; + UINT16 selector; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + PREPART_REG16_EA(op, selector, out, 5, 11); + + rv = parse_selector(&sel, selector); + if (rv < 0) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + + if (!SEG_IS_SYSTEM(&sel.desc)) { + /* code or data segment */ + if ((SEG_IS_DATA(&sel.desc) + || !SEG_IS_CONFORMING_CODE(&sel.desc))) { + /* data or non-conforming code segment */ + if ((sel.desc.dpl < CPU_STAT_CPL) + || (sel.desc.dpl < sel.rpl)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + } + } else { + /* system segment */ + switch (sel.desc.type) { + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_LDT: + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + case CPU_SYSDESC_TYPE_TSS_32: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + break; + + default: + CPU_FLAGL &= ~Z_FLAG; + return; + } + } + + *out = (UINT16)sel.desc.u.seg.limit; + CPU_FLAGL |= Z_FLAG; + return; + } + VERBOSE(("LSL: real-mode or VM86")); + EXCEPTION(UD_EXCEPTION, 0); +} + +void +LSL_GdEw(void) +{ + selector_t sel; + UINT32 *out; + UINT32 op; + int rv; + UINT32 selector; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + PREPART_REG32_EA(op, selector, out, 5, 11); + + rv = parse_selector(&sel, (UINT16)selector); + if (rv < 0) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + + if (!SEG_IS_SYSTEM(&sel.desc)) { + /* code or data segment */ + if ((SEG_IS_DATA(&sel.desc) + || !SEG_IS_CONFORMING_CODE(&sel.desc))) { + /* data or non-conforming code segment */ + if ((sel.desc.dpl < CPU_STAT_CPL) + || (sel.desc.dpl < sel.rpl)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + } + } else { + /* system segment */ + switch (sel.desc.type) { + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_LDT: + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + case CPU_SYSDESC_TYPE_TSS_32: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + break; + + default: + CPU_FLAGL &= ~Z_FLAG; + return; + } + } + + *out = sel.desc.u.seg.limit; + CPU_FLAGL |= Z_FLAG; + return; + } + VERBOSE(("LSL: real-mode or VM86")); + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +VERR_Ew(UINT32 op) +{ + selector_t sel; + UINT32 madr; + int rv; + UINT16 selector; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + selector = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + selector = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + + rv = parse_selector(&sel, selector); + if (rv < 0) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + + /* system segment */ + if (SEG_IS_SYSTEM(&sel.desc)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + + /* data or non-conforming code segment */ + if ((SEG_IS_DATA(&sel.desc) + || !SEG_IS_CONFORMING_CODE(&sel.desc))) { + if ((sel.desc.dpl < CPU_STAT_CPL) + || (sel.desc.dpl < sel.rpl)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + } + /* code segment is not readable */ + if (SEG_IS_CODE(&sel.desc) + && !SEG_IS_READABLE_CODE(&sel.desc)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + + CPU_FLAGL |= Z_FLAG; + return; + } + VERBOSE(("VERR: real-mode or VM86")); + EXCEPTION(UD_EXCEPTION, 0); +} + +void CPUCALL +VERW_Ew(UINT32 op) +{ + selector_t sel; + UINT32 madr; + int rv; + UINT16 selector; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + if (op >= 0xc0) { + CPU_WORKCLOCK(5); + selector = *(CPU_REG16_B20(op)); + } else { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + selector = cpu_vmemoryread_w(CPU_INST_SEGREG_INDEX, madr); + } + + rv = parse_selector(&sel, selector); + if (rv < 0) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + + /* system segment || code segment */ + if (SEG_IS_SYSTEM(&sel.desc) || SEG_IS_CODE(&sel.desc)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + /* data segment is not writable */ + if (!SEG_IS_WRITABLE_DATA(&sel.desc)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + /* privilege level */ + if ((CPU_STAT_CPL > sel.desc.dpl) || (sel.rpl > sel.desc.dpl)) { + CPU_FLAGL &= ~Z_FLAG; + return; + } + + CPU_FLAGL |= Z_FLAG; + return; + } + VERBOSE(("VERW: real-mode or VM86")); + EXCEPTION(UD_EXCEPTION, 0); +} + +void +MOV_DdRd(void) +{ + UINT32 src; + UINT op; + int idx; + + CPU_WORKCLOCK(11); + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("MOV_DdRd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + + if (CPU_DR7 & CPU_DR7_GD) { + CPU_DR6 |= CPU_DR6_BD; + CPU_DR7 &= ~CPU_DR7_GD; + EXCEPTION(DB_EXCEPTION, 0); + } + + src = *(CPU_REG32_B20(op)); + idx = (op >> 3) & 7; + + CPU_DR(idx) = src; + switch (idx) { + case 0: + case 1: + case 2: + case 3: + CPU_DR(idx) = src; + break; + + case 6: + CPU_DR6 = src; + break; + + case 7: + CPU_DR7 = src; + CPU_STAT_BP = 0; + break; + + default: + ia32_panic("MOV_DdRd: DR reg index (%d)", idx); + /*NOTREACHED*/ + break; + } + + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +MOV_RdDd(void) +{ + UINT32 *out; + UINT op; + int idx; + + CPU_WORKCLOCK(11); + GET_MODRM_PCBYTE(op); + if (op >= 0xc0) { + if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("MOV_RdDd: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + + if (CPU_DR7 & CPU_DR7_GD) { + CPU_DR6 |= CPU_DR6_BD; + CPU_DR7 &= ~CPU_DR7_GD; + EXCEPTION(DB_EXCEPTION, 0); + } + + out = CPU_REG32_B20(op); + idx = (op >> 3) & 7; + + switch (idx) { + case 0: + case 1: + case 2: + case 3: + *out = CPU_DR(idx); + break; + + case 4: + case 6: + *out = (CPU_DR6 & 0x0000f00f) | 0xffff0ff0; + break; + + case 7: + *out = CPU_DR7; + break; + + default: + ia32_panic("MOV_RdDd: DR reg index (%d)", idx); + /*NOTREACHED*/ + break; + } + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +INVD(void) +{ + + CPU_WORKCLOCK(11); + if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("INVD: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } +} + +void +WBINVD(void) +{ + + CPU_WORKCLOCK(11); + if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("WBINVD: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } +} + +void CPUCALL +INVLPG(UINT32 op) +{ + descriptor_t *sdp; + UINT32 madr; + int idx; + + if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("INVLPG: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + + if (op < 0xc0) { + CPU_WORKCLOCK(11); + madr = calc_ea_dst(op); + + idx = CPU_INST_SEGREG_INDEX; + sdp = &CPU_STAT_SREG(idx); + if (!SEG_IS_VALID(sdp)) { + EXCEPTION(GP_EXCEPTION, 0); + } + switch (sdp->type) { + case 4: case 5: case 6: case 7: + if (madr <= sdp->u.seg.limit) { + EXCEPTION((idx == CPU_SS_INDEX) ? + SS_EXCEPTION: GP_EXCEPTION, 0); + } + break; + + default: + if (madr > sdp->u.seg.limit) { + EXCEPTION((idx == CPU_SS_INDEX) ? + SS_EXCEPTION: GP_EXCEPTION, 0); + } + break; + } + tlb_flush_page(sdp->u.seg.segbase + madr); + return; + } + EXCEPTION(UD_EXCEPTION, 0); +} + +void +_LOCK(void) +{ + + /* Nothing to do */ +} + +void +HLT(void) +{ +#if defined(USE_CUSTOM_HOOKINST) + if (bioshookinfo.hookinst == 0xF4) + { + if (!CPU_STAT_PM || CPU_STAT_VM86) + { + UINT32 adrs; + adrs = CPU_PREV_EIP + (CPU_CS << 4); + if ((adrs >= 0xf8000) && (adrs < 0x100000)) + { + ia32_bioscall(); + return; + } + } + } +#endif + + if (CPU_STAT_PM && CPU_STAT_CPL != 0) { + VERBOSE(("HLT: CPL(%d) != 0", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + + VERBOSE(("HLT: do HLT.")); + CPU_HALT(); + CPU_EIP = CPU_PREV_EIP; + CPU_STAT_HLT = 1; +} + +void +RSM(void) +{ + + ia32_panic("RSM: not implemented yet!"); +} + +void +RDMSR(void) +{ + int idx; + + if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("RDMSR: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + + idx = CPU_ECX; + switch (idx) { + case 0x174: + CPU_EDX = (UINT32)((i386msr.reg.ia32_sysenter_cs >> 32) & 0xffffffff); + CPU_EAX = (UINT32)((i386msr.reg.ia32_sysenter_cs ) & 0xffffffff); + break; + case 0x175: + CPU_EDX = (UINT32)((i386msr.reg.ia32_sysenter_esp >> 32) & 0xffffffff); + CPU_EAX = (UINT32)((i386msr.reg.ia32_sysenter_esp ) & 0xffffffff); + break; + case 0x176: + CPU_EDX = (UINT32)((i386msr.reg.ia32_sysenter_eip >> 32) & 0xffffffff); + CPU_EAX = (UINT32)((i386msr.reg.ia32_sysenter_eip ) & 0xffffffff); + break; + case 0x10: + RDTSC(); + break; + case 0x2c: + CPU_EDX = 0x00000000; + CPU_EAX = 0xfee00800; + break; + //case 0x1b: + // CPU_EDX = 0x00000000; + // CPU_EAX = 0x00000010; + // break; + default: + CPU_EDX = CPU_EAX = 0; + //EXCEPTION(GP_EXCEPTION, 0); // XXX: とりあえず通す + break; + } +} + +void +WRMSR(void) +{ + int idx; + + if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("WRMSR: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + + idx = CPU_ECX; + switch (idx) { + case 0x174: + i386msr.reg.ia32_sysenter_cs = ((UINT64)CPU_EDX << 32) | ((UINT64)CPU_EAX); + break; + case 0x175: + i386msr.reg.ia32_sysenter_esp = ((UINT64)CPU_EDX << 32) | ((UINT64)CPU_EAX); + break; + case 0x176: + i386msr.reg.ia32_sysenter_eip = ((UINT64)CPU_EDX << 32) | ((UINT64)CPU_EAX); + break; + /* MTRR への書き込み時 tlb_flush_all(); */ + default: + //EXCEPTION(GP_EXCEPTION, 0); // XXX: とりあえず通す + break; + } +} + +#if defined(SUPPORT_GAMEPORT) +int gameport_tsccounter = 0; +#endif +void +RDTSC(void) +{ +#if defined(SUPPORT_IA32_HAXM)&&defined(_WIN32) + LARGE_INTEGER li = {0}; + LARGE_INTEGER qpf; + QueryPerformanceCounter(&li); + if (QueryPerformanceFrequency(&qpf)) { + li.QuadPart = li.QuadPart * pccore.realclock / qpf.QuadPart; + } + CPU_EDX = li.HighPart; + CPU_EAX = li.LowPart; +#else + if(np2cfg.consttsc){ + // CPUクロックに依存しないカウンタ値にする + UINT64 tsc_tmp; + if(CPU_REMCLOCK != -1){ + tsc_tmp = CPU_MSR_TSC - CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple; + }else{ + tsc_tmp = CPU_MSR_TSC; + } + CPU_EDX = ((tsc_tmp >> 32) & 0xffffffff); + CPU_EAX = (tsc_tmp & 0xffffffff); + }else{ + // CPUクロックに依存するカウンタ値にする + static UINT64 tsc_last = 0; + static UINT64 tsc_cur = 0; + UINT64 tsc_tmp; + if(CPU_REMCLOCK != -1){ + tsc_tmp = CPU_MSR_TSC - CPU_REMCLOCK * pccore.maxmultiple / pccore.multiple; + }else{ + tsc_tmp = CPU_MSR_TSC; + } + tsc_cur += (tsc_tmp - tsc_last) * pccore.multiple / pccore.maxmultiple; + tsc_last = tsc_tmp; + CPU_EDX = ((tsc_cur >> 32) & 0xffffffff); + CPU_EAX = (tsc_cur & 0xffffffff); + } +#if defined(SUPPORT_GAMEPORT) + if(gameport_tsccounter < INT_MAX) gameport_tsccounter++; +#endif +#endif +// ia32_panic("RDTSC: not implemented yet!"); +} + +void +RDPMC(void) +{ + int idx; + + if(!(CPU_CR4 & CPU_CR4_PCE)){ + if (CPU_STAT_PM && (CPU_STAT_VM86 || CPU_STAT_CPL != 0)) { + VERBOSE(("RDPMC: VM86(%s) or CPL(%d) != 0", CPU_STAT_VM86 ? "true" : "false", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + } + + idx = CPU_ECX; + switch (idx) { + default: + CPU_EDX = CPU_EAX = 0; + } +} + +void +MOV_TdRd(void) +{ + + ia32_panic("MOV_TdRd: not implemented yet!"); +} + +void +MOV_RdTd(void) +{ + + ia32_panic("MOV_RdTd: not implemented yet!"); +} + +// 中途半端&ノーチェック注意 +void +SYSENTER(void) +{ + // SEPなしならUD(無効オペコード例外)を発生させる + if(!(i386cpuid.cpu_feature & CPU_FEATURE_SEP)){ + EXCEPTION(UD_EXCEPTION, 0); + } + // プロテクトモードチェック + if (!CPU_STAT_PM) { + EXCEPTION(GP_EXCEPTION, 0); + } + // MSRレジスタチェック + if (i386msr.reg.ia32_sysenter_cs == 0) { + EXCEPTION(GP_EXCEPTION, 0); + } + + CPU_EFLAG = CPU_EFLAG & ~(VM_FLAG|I_FLAG|RF_FLAG); + CPU_CS = (UINT32)i386msr.reg.ia32_sysenter_cs; + + CPU_SS = CPU_CS + 8; + + CPU_ESP = (UINT32)i386msr.reg.ia32_sysenter_esp; + CPU_EIP = (UINT32)i386msr.reg.ia32_sysenter_eip; + + CPU_STAT_CPL = 0; + CPU_STAT_USER_MODE = (CPU_STAT_CPL == 3) ? CPU_MODE_USER : CPU_MODE_SUPERVISER; +} + +// 中途半端&ノーチェック注意 +void +SYSEXIT(void) +{ + // SEPなしならUD(無効オペコード例外)を発生させる + if(!(i386cpuid.cpu_feature & CPU_FEATURE_SEP)){ + EXCEPTION(UD_EXCEPTION, 0); + } + // プロテクトモードチェック + if (!CPU_STAT_PM) { + EXCEPTION(GP_EXCEPTION, 0); + } + // MSRレジスタチェック + if (i386msr.reg.ia32_sysenter_cs == 0) { + EXCEPTION(GP_EXCEPTION, 0); + } + // 特権レベルチェック + if (CPU_STAT_CPL != 0) { + VERBOSE(("SYSENTER: CPL(%d) != 0", CPU_STAT_CPL)); + EXCEPTION(GP_EXCEPTION, 0); + } + + CPU_CS = (UINT32)i386msr.reg.ia32_sysenter_cs + 16; + + CPU_SS = (UINT32)i386msr.reg.ia32_sysenter_cs + 24; + + CPU_ESP = CPU_ECX; + CPU_EIP = CPU_EDX; + + CPU_STAT_CPL = 3; + CPU_STAT_USER_MODE = (CPU_STAT_CPL == 3) ? CPU_MODE_USER : CPU_MODE_SUPERVISER; } \ No newline at end of file diff --git a/i386c/ia32/instructions/system_inst.h b/i386c/ia32/instructions/system_inst.h old mode 100755 new mode 100644 index 1e40578d..e0534d2a --- a/i386c/ia32/instructions/system_inst.h +++ b/i386c/ia32/instructions/system_inst.h @@ -1,105 +1,105 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INSTRUCTION_SYSTEM_H__ -#define IA32_CPU_INSTRUCTION_SYSTEM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Load/Store system register */ -void CPUCALL LGDT_Ms(UINT32); -void CPUCALL SGDT_Ms(UINT32); -void CPUCALL LLDT_Ew(UINT32); -void CPUCALL SLDT_Ew(UINT32); -void CPUCALL LTR_Ew(UINT32); -void CPUCALL STR_Ew(UINT32); -void CPUCALL LIDT_Ms(UINT32); -void CPUCALL SIDT_Ms(UINT32); - -/* ctrl reg */ -void MOV_CdRd(void); -void MOV_RdCd(void); - -/* msw */ -void CPUCALL LMSW_Ew(UINT32); -void CPUCALL SMSW_Ew(UINT32); - -/* */ -void CLTS(void); -void ARPL_EwGw(void); - -/* dpl */ -void LAR_GwEw(void); -void LAR_GdEw(void); -void LSL_GwEw(void); -void LSL_GdEw(void); - -/* */ -void CPUCALL VERR_Ew(UINT32); -void CPUCALL VERW_Ew(UINT32); - -/* dbg reg */ -void MOV_DdRd(void); -void MOV_RdDd(void); - -/* cache */ -void INVD(void); -void WBINVD(void); - -/* */ -void CPUCALL INVLPG(UINT32); - -/* */ -void _LOCK(void); -void HLT(void); - -/* ctrl reg */ -void RSM(void); - -/* msr */ -void RDMSR(void); -void WRMSR(void); - -/* ctrl reg */ -void RDTSC(void); - -void RDPMC(void); - -/* test reg */ -void MOV_TdRd(void); -void MOV_RdTd(void); - -/* fast system call */ -void SYSENTER(void); -void SYSEXIT(void); - - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_INSTRUCTION_SYSTEM_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INSTRUCTION_SYSTEM_H__ +#define IA32_CPU_INSTRUCTION_SYSTEM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Load/Store system register */ +void CPUCALL LGDT_Ms(UINT32); +void CPUCALL SGDT_Ms(UINT32); +void CPUCALL LLDT_Ew(UINT32); +void CPUCALL SLDT_Ew(UINT32); +void CPUCALL LTR_Ew(UINT32); +void CPUCALL STR_Ew(UINT32); +void CPUCALL LIDT_Ms(UINT32); +void CPUCALL SIDT_Ms(UINT32); + +/* ctrl reg */ +void MOV_CdRd(void); +void MOV_RdCd(void); + +/* msw */ +void CPUCALL LMSW_Ew(UINT32); +void CPUCALL SMSW_Ew(UINT32); + +/* */ +void CLTS(void); +void ARPL_EwGw(void); + +/* dpl */ +void LAR_GwEw(void); +void LAR_GdEw(void); +void LSL_GwEw(void); +void LSL_GdEw(void); + +/* */ +void CPUCALL VERR_Ew(UINT32); +void CPUCALL VERW_Ew(UINT32); + +/* dbg reg */ +void MOV_DdRd(void); +void MOV_RdDd(void); + +/* cache */ +void INVD(void); +void WBINVD(void); + +/* */ +void CPUCALL INVLPG(UINT32); + +/* */ +void _LOCK(void); +void HLT(void); + +/* ctrl reg */ +void RSM(void); + +/* msr */ +void RDMSR(void); +void WRMSR(void); + +/* ctrl reg */ +void RDTSC(void); + +void RDPMC(void); + +/* test reg */ +void MOV_TdRd(void); +void MOV_RdTd(void); + +/* fast system call */ +void SYSENTER(void); +void SYSEXIT(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_INSTRUCTION_SYSTEM_H__ */ diff --git a/i386c/ia32/interface.c b/i386c/ia32/interface.c old mode 100755 new mode 100644 index fdbabc49..60a2bcec --- a/i386c/ia32/interface.c +++ b/i386c/ia32/interface.c @@ -1,337 +1,337 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" -#include "ia32.mcr" - -#include -#include -#include -#include - -#include - -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif - -void -ia32_initreg(void) -{ - int i; - - CPU_STATSAVE.cpu_inst_default.seg_base = (UINT32)-1; - - CPU_EDX = (CPU_FAMILY << 8) | (CPU_MODEL << 4) | CPU_STEPPING; - CPU_EFLAG = 2; - CPU_CR0 = CPU_CR0_CD | CPU_CR0_NW; -#if defined(USE_FPU) - if(i386cpuid.cpu_feature & CPU_FEATURE_FPU){ - CPU_CR0 |= CPU_CR0_ET; /* FPU present */ - CPU_CR0 &= ~CPU_CR0_EM; - }else{ - CPU_CR0 |= CPU_CR0_EM | CPU_CR0_NE; - CPU_CR0 &= ~(CPU_CR0_MP | CPU_CR0_ET); - } -#else - CPU_CR0 |= CPU_CR0_EM | CPU_CR0_NE; - CPU_CR0 &= ~(CPU_CR0_MP | CPU_CR0_ET); -#endif - CPU_MXCSR = 0x1f80; - -#if defined(USE_TSC) - CPU_MSR_TSC = 0; -#endif - - CPU_GDTR_BASE = 0x0; - CPU_GDTR_LIMIT = 0xffff; - CPU_IDTR_BASE = 0x0; - CPU_IDTR_LIMIT = 0xffff; - CPU_LDTR_BASE = 0x0; - CPU_LDTR_LIMIT = 0xffff; - CPU_TR_BASE = 0x0; - CPU_TR_LIMIT = 0xffff; - - CPU_STATSAVE.cpu_regs.dr[6] = 0xffff1ff0; - - for (i = 0; i < CPU_SEGREG_NUM; ++i) { - segdesc_init(i, 0, &CPU_STAT_SREG(i)); - } - LOAD_SEGREG(CPU_CS_INDEX, 0xf000); - CPU_STAT_CS_BASE = 0xffff0000; - CPU_EIP = 0xfff0; - CPU_ADRSMASK = 0x000fffff; - - tlb_init(); - fpu_initialize(1); - -#if defined(USE_CPU_EIPMASK) - CPU_EIPMASK = CPU_STATSAVE.cpu_inst_default.op_32 ? 0xffffffff : 0xffff; -#endif - -#if defined(USE_CPU_MODRMPREFETCH) - opCache = 0; -#endif -} - -void -ia32reset(void) -{ - memset(&i386core.s, 0, sizeof(i386core.s)); - ia32_initreg(); -#if defined(SUPPORT_IA32_HAXM) - i386hax_resetVMCPU(); - i386haxfunc_vcpu_getREGs(&np2haxstat.state); - i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); - if (!np2hax.emumode) - { - np2haxstat.update_regs = np2haxstat.update_fpu = 0; - // HAXMレジスタ→猫レジスタにコピー - ia32hax_copyregHAXtoNP2(); - } -#endif -} - -void -ia32shut(void) -{ - memset(&i386core.s, 0, offsetof(I386STAT, cpu_type)); - ia32_initreg(); -#if defined(SUPPORT_IA32_HAXM) - i386hax_resetVMCPU(); - i386haxfunc_vcpu_getREGs(&np2haxstat.state); - i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); - if (!np2hax.emumode) - { - np2haxstat.update_regs = np2haxstat.update_fpu = 0; - // HAXMレジスタ→猫レジスタにコピー - ia32hax_copyregHAXtoNP2(); - } -#endif -} - -void -ia32a20enable(BOOL enable) -{ - - CPU_ADRSMASK = (enable)?0xffffffff:0x00ffffff; -} - -//#pragma optimize("", off) -void -ia32(void) -{ - switch (sigsetjmp(exec_1step_jmpbuf, 1)) { - case 0: - break; - - case 1: - VERBOSE(("ia32: return from exception")); - break; - - case 2: - VERBOSE(("ia32: return from panic")); - return; - - default: - VERBOSE(("ia32: return from unknown cause")); - break; - } - if (!CPU_TRAP && !dmac.working) { - exec_allstep(); - }else if (!CPU_TRAP) { - do { - exec_1step(); - dmax86(); - } while (CPU_REMCLOCK > 0); - }else{ - do { - exec_1step(); - if (CPU_TRAP) { - CPU_DR6 |= CPU_DR6_BS; - INTERRUPT(1, INTR_TYPE_EXCEPTION); - } - dmax86(); - } while (CPU_REMCLOCK > 0); - } - -} - -void -ia32_step(void) -{ - switch (sigsetjmp(exec_1step_jmpbuf, 1)) { - case 0: - break; - - case 1: - VERBOSE(("ia32: return from exception")); - break; - - case 2: - VERBOSE(("ia32: return from panic")); - return; - - default: - VERBOSE(("ia32: return from unknown cause")); - break; - } - - do { - exec_1step(); - if (CPU_TRAP) { - CPU_DR6 |= CPU_DR6_BS; - INTERRUPT(1, INTR_TYPE_EXCEPTION); - } - if (dmac.working) { - dmax86(); - } - } while (CPU_REMCLOCK > 0); -} -//#pragma optimize("", on) -void CPUCALL -ia32_interrupt(int vect, int soft) -{ - -// TRACEOUT(("int (%x, %x) PE=%d VM=%d", vect, soft, CPU_STAT_PM, CPU_STAT_VM86)); -#if defined(SUPPORT_IA32_HAXM) - if(np2hax.enable && !np2hax.emumode && np2hax.hVCPUDevice){ - np2haxcore.hltflag = 0; - if(!soft){ - HAX_TUNNEL *tunnel; - tunnel = (HAX_TUNNEL*)np2hax.tunnel.va; - if(np2haxstat.irq_reqidx_end - np2haxstat.irq_reqidx_cur < 250){ - np2haxstat.irq_req[np2haxstat.irq_reqidx_end] = vect; - np2haxstat.irq_reqidx_end++; - } - //i386haxfunc_vcpu_interrupt(vect); - } - }else -#endif - { - if (!soft) { - INTERRUPT(vect, INTR_TYPE_EXTINTR); - } else { - if (CPU_STAT_PM && CPU_STAT_VM86 && CPU_STAT_IOPL < CPU_IOPL3) { - VERBOSE(("ia32_interrupt: VM86 && IOPL < 3 && INTn")); - EXCEPTION(GP_EXCEPTION, 0); - } - INTERRUPT(vect, INTR_TYPE_SOFTINTR); - } - } -} - - -/* - * error function - */ -void -ia32_panic(const char *str, ...) -{ - extern char *cpu_reg2str(void); - char buf[2048]; - va_list ap; - - va_start(ap, str); - vsnprintf(buf, sizeof(buf), str, ap); - va_end(ap); - strcat(buf, "\n"); - strcat(buf, cpu_reg2str()); - VERBOSE(("%s", buf)); - - msgbox("ia32_panic", buf); - -#if defined(IA32_REBOOT_ON_PANIC) - VERBOSE(("ia32_panic: reboot")); - pccore_reset(); - pcstat.screendispflag = 0; - siglongjmp(exec_1step_jmpbuf, 2); -#else - __ASSERT(0); - exit(1); -#endif -} - -void -ia32_warning(const char *str, ...) -{ - char buf[1024]; - va_list ap; - va_start(ap, str); - vsnprintf(buf, sizeof(buf), str, ap); - va_end(ap); - strcat(buf, "\n"); - - msgbox("ia32_warning", buf); -} - -void -ia32_printf(const char *str, ...) -{ - char buf[1024]; - va_list ap; - va_start(ap, str); - vsnprintf(buf, sizeof(buf), str, ap); - va_end(ap); - strcat(buf, "\n"); - - msgbox("ia32_printf", buf); -} - - -/* - * bios call interface - */ -void -ia32_bioscall(void) -{ - UINT32 adrs; - - if (!CPU_STAT_PM || CPU_STAT_VM86) { -#if 1 - adrs = CPU_PREV_EIP + (CPU_CS << 4); -#else - adrs = CPU_PREV_EIP + CPU_STAT_CS_BASE; -#endif - if ((adrs >= 0xf8000) && (adrs < 0x100000)) { - if (biosfunc(adrs)) { - /* Nothing to do */ - } - LOAD_SEGREG(CPU_ES_INDEX, CPU_ES); - LOAD_SEGREG(CPU_CS_INDEX, CPU_CS); - LOAD_SEGREG(CPU_SS_INDEX, CPU_SS); - LOAD_SEGREG(CPU_DS_INDEX, CPU_DS); - } - }else{ -#ifdef SUPPORT_PCI - adrs = CPU_EIP; - if (bios32func(adrs)) { - /* Nothing to do */ - } -#endif - } -} +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" +#include "ia32.mcr" + +#include +#include +#include +#include + +#include + +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif + +void +ia32_initreg(void) +{ + int i; + + CPU_STATSAVE.cpu_inst_default.seg_base = (UINT32)-1; + + CPU_EDX = (CPU_FAMILY << 8) | (CPU_MODEL << 4) | CPU_STEPPING; + CPU_EFLAG = 2; + CPU_CR0 = CPU_CR0_CD | CPU_CR0_NW; +#if defined(USE_FPU) + if(i386cpuid.cpu_feature & CPU_FEATURE_FPU){ + CPU_CR0 |= CPU_CR0_ET; /* FPU present */ + CPU_CR0 &= ~CPU_CR0_EM; + }else{ + CPU_CR0 |= CPU_CR0_EM | CPU_CR0_NE; + CPU_CR0 &= ~(CPU_CR0_MP | CPU_CR0_ET); + } +#else + CPU_CR0 |= CPU_CR0_EM | CPU_CR0_NE; + CPU_CR0 &= ~(CPU_CR0_MP | CPU_CR0_ET); +#endif + CPU_MXCSR = 0x1f80; + +#if defined(USE_TSC) + CPU_MSR_TSC = 0; +#endif + + CPU_GDTR_BASE = 0x0; + CPU_GDTR_LIMIT = 0xffff; + CPU_IDTR_BASE = 0x0; + CPU_IDTR_LIMIT = 0xffff; + CPU_LDTR_BASE = 0x0; + CPU_LDTR_LIMIT = 0xffff; + CPU_TR_BASE = 0x0; + CPU_TR_LIMIT = 0xffff; + + CPU_STATSAVE.cpu_regs.dr[6] = 0xffff1ff0; + + for (i = 0; i < CPU_SEGREG_NUM; ++i) { + segdesc_init(i, 0, &CPU_STAT_SREG(i)); + } + LOAD_SEGREG(CPU_CS_INDEX, 0xf000); + CPU_STAT_CS_BASE = 0xffff0000; + CPU_EIP = 0xfff0; + CPU_ADRSMASK = 0x000fffff; + + tlb_init(); + fpu_initialize(1); + +#if defined(USE_CPU_EIPMASK) + CPU_EIPMASK = CPU_STATSAVE.cpu_inst_default.op_32 ? 0xffffffff : 0xffff; +#endif + +#if defined(USE_CPU_MODRMPREFETCH) + opCache = 0; +#endif +} + +void +ia32reset(void) +{ + memset(&i386core.s, 0, sizeof(i386core.s)); + ia32_initreg(); +#if defined(SUPPORT_IA32_HAXM) + i386hax_resetVMCPU(); + i386haxfunc_vcpu_getREGs(&np2haxstat.state); + i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); + if (!np2hax.emumode) + { + np2haxstat.update_regs = np2haxstat.update_fpu = 0; + // HAXMレジスタ→猫レジスタにコピー + ia32hax_copyregHAXtoNP2(); + } +#endif +} + +void +ia32shut(void) +{ + memset(&i386core.s, 0, offsetof(I386STAT, cpu_type)); + ia32_initreg(); +#if defined(SUPPORT_IA32_HAXM) + i386hax_resetVMCPU(); + i386haxfunc_vcpu_getREGs(&np2haxstat.state); + i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); + if (!np2hax.emumode) + { + np2haxstat.update_regs = np2haxstat.update_fpu = 0; + // HAXMレジスタ→猫レジスタにコピー + ia32hax_copyregHAXtoNP2(); + } +#endif +} + +void +ia32a20enable(BOOL enable) +{ + + CPU_ADRSMASK = (enable)?0xffffffff:0x00ffffff; +} + +//#pragma optimize("", off) +void +ia32(void) +{ + switch (sigsetjmp(exec_1step_jmpbuf, 1)) { + case 0: + break; + + case 1: + VERBOSE(("ia32: return from exception")); + break; + + case 2: + VERBOSE(("ia32: return from panic")); + return; + + default: + VERBOSE(("ia32: return from unknown cause")); + break; + } + if (!CPU_TRAP && !dmac.working) { + exec_allstep(); + }else if (!CPU_TRAP) { + do { + exec_1step(); + dmax86(); + } while (CPU_REMCLOCK > 0); + }else{ + do { + exec_1step(); + if (CPU_TRAP) { + CPU_DR6 |= CPU_DR6_BS; + INTERRUPT(1, INTR_TYPE_EXCEPTION); + } + dmax86(); + } while (CPU_REMCLOCK > 0); + } + +} + +void +ia32_step(void) +{ + switch (sigsetjmp(exec_1step_jmpbuf, 1)) { + case 0: + break; + + case 1: + VERBOSE(("ia32: return from exception")); + break; + + case 2: + VERBOSE(("ia32: return from panic")); + return; + + default: + VERBOSE(("ia32: return from unknown cause")); + break; + } + + do { + exec_1step(); + if (CPU_TRAP) { + CPU_DR6 |= CPU_DR6_BS; + INTERRUPT(1, INTR_TYPE_EXCEPTION); + } + if (dmac.working) { + dmax86(); + } + } while (CPU_REMCLOCK > 0); +} +//#pragma optimize("", on) +void CPUCALL +ia32_interrupt(int vect, int soft) +{ + +// TRACEOUT(("int (%x, %x) PE=%d VM=%d", vect, soft, CPU_STAT_PM, CPU_STAT_VM86)); +#if defined(SUPPORT_IA32_HAXM) + if(np2hax.enable && !np2hax.emumode && np2hax.hVCPUDevice){ + np2haxcore.hltflag = 0; + if(!soft){ + HAX_TUNNEL *tunnel; + tunnel = (HAX_TUNNEL*)np2hax.tunnel.va; + if(np2haxstat.irq_reqidx_end - np2haxstat.irq_reqidx_cur < 250){ + np2haxstat.irq_req[np2haxstat.irq_reqidx_end] = vect; + np2haxstat.irq_reqidx_end++; + } + //i386haxfunc_vcpu_interrupt(vect); + } + }else +#endif + { + if (!soft) { + INTERRUPT(vect, INTR_TYPE_EXTINTR); + } else { + if (CPU_STAT_PM && CPU_STAT_VM86 && CPU_STAT_IOPL < CPU_IOPL3) { + VERBOSE(("ia32_interrupt: VM86 && IOPL < 3 && INTn")); + EXCEPTION(GP_EXCEPTION, 0); + } + INTERRUPT(vect, INTR_TYPE_SOFTINTR); + } + } +} + + +/* + * error function + */ +void +ia32_panic(const char *str, ...) +{ + extern char *cpu_reg2str(void); + char buf[2048]; + va_list ap; + + va_start(ap, str); + vsnprintf(buf, sizeof(buf), str, ap); + va_end(ap); + strcat(buf, "\n"); + strcat(buf, cpu_reg2str()); + VERBOSE(("%s", buf)); + + msgbox("ia32_panic", buf); + +#if defined(IA32_REBOOT_ON_PANIC) + VERBOSE(("ia32_panic: reboot")); + pccore_reset(); + pcstat.screendispflag = 0; + siglongjmp(exec_1step_jmpbuf, 2); +#else + __ASSERT(0); + exit(1); +#endif +} + +void +ia32_warning(const char *str, ...) +{ + char buf[1024]; + va_list ap; + va_start(ap, str); + vsnprintf(buf, sizeof(buf), str, ap); + va_end(ap); + strcat(buf, "\n"); + + msgbox("ia32_warning", buf); +} + +void +ia32_printf(const char *str, ...) +{ + char buf[1024]; + va_list ap; + va_start(ap, str); + vsnprintf(buf, sizeof(buf), str, ap); + va_end(ap); + strcat(buf, "\n"); + + msgbox("ia32_printf", buf); +} + + +/* + * bios call interface + */ +void +ia32_bioscall(void) +{ + UINT32 adrs; + + if (!CPU_STAT_PM || CPU_STAT_VM86) { +#if 1 + adrs = CPU_PREV_EIP + (CPU_CS << 4); +#else + adrs = CPU_PREV_EIP + CPU_STAT_CS_BASE; +#endif + if ((adrs >= 0xf8000) && (adrs < 0x100000)) { + if (biosfunc(adrs)) { + /* Nothing to do */ + } + LOAD_SEGREG(CPU_ES_INDEX, CPU_ES); + LOAD_SEGREG(CPU_CS_INDEX, CPU_CS); + LOAD_SEGREG(CPU_SS_INDEX, CPU_SS); + LOAD_SEGREG(CPU_DS_INDEX, CPU_DS); + } + }else{ +#ifdef SUPPORT_PCI + adrs = CPU_EIP; + if (bios32func(adrs)) { + /* Nothing to do */ + } +#endif + } +} diff --git a/i386c/ia32/interface.h b/i386c/ia32/interface.h old mode 100755 new mode 100644 index 63394192..0789f99a --- a/i386c/ia32/interface.h +++ b/i386c/ia32/interface.h @@ -1,98 +1,98 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_INTERFACE_H__ -#define IA32_CPU_INTERFACE_H__ - -#ifndef CPUCALL -#define CPUCALL -#endif - -#ifndef STATIC_INLINE -#if defined(__GNUC__) -#define STATIC_INLINE static INLINE __attribute__((unused)) -#else -#define STATIC_INLINE static INLINE -#endif -#endif - -#if !defined(QWORD_CONST) -#define QWORD_CONST(v) v ## ULL -#define SQWORD_CONST(v) v ## LL -#endif - -#define CPU_isEI (CPU_FLAG & I_FLAG) -#define CPU_isDI (!CPU_isEI) -#define CPU_A20EN(en) CPU_ADRSMASK = (en)?0xffffffff:0x000fffff; - -#define CPU_INITIALIZE() i386c_initialize() -#define CPU_DEINITIALIZE() -#define CPU_RESET() ia32reset() -#define CPU_CLEARPREFETCH() -#define CPU_INTERRUPT(vect, soft) ia32_interrupt(vect, soft) -#define CPU_EXEC() ia32() -#define CPU_EXECV30() ia32() -#define CPU_SHUT() ia32shut() -#define CPU_SETEXTSIZE(size) ia32_setextsize((UINT32)(size) << 20) -#define CPU_SETEMM(frame, addr) ia32_setemm(frame, addr) - -#define cpu_memorywrite(a,v) memp_write8(a,v) -#define cpu_memorywrite_b(a,v) memp_write8(a,v) -#define cpu_memorywrite_w(a,v) memp_write16(a,v) -#define cpu_memorywrite_d(a,v) memp_write32(a,v) -#define cpu_memoryread(a) memp_read8(a) -#define cpu_memoryread_b(a) memp_read8(a) -#define cpu_memoryread_w(a) memp_read16(a) -#define cpu_memoryread_d(a) memp_read32(a) -#define cpu_memoryread_codefetch(a) memp_read8_codefetch(a) -#define cpu_memoryread_b_codefetch(a) memp_read8_codefetch(a) -#define cpu_memoryread_w_codefetch(a) memp_read16_codefetch(a) -#define cpu_memoryread_d_codefetch(a) memp_read32_codefetch(a) -#ifdef USE_FASTPAGING -#define cpu_memoryread_paging(a) memp_read8_paging(a) -#define cpu_memoryread_b_paging(a) memp_read8_paging(a) -#define cpu_memoryread_w_paging(a) memp_read16_paging(a) -#define cpu_memoryread_d_paging(a) memp_read32_paging(a) -#define cpu_memorywrite_paging(a,v) memp_write8_paging(a,v) -#define cpu_memorywrite_b_paging(a,v) memp_write8_paging(a,v) -#define cpu_memorywrite_w_paging(a,v) memp_write16_paging(a,v) -#define cpu_memorywrite_d_paging(a,v) memp_write32_paging(a,v) -#else -#define cpu_memoryread_paging(a) memp_read8_codefetch(a) -#define cpu_memoryread_b_paging(a) memp_read8_codefetch(a) -#define cpu_memoryread_w_paging(a) memp_read16_codefetch(a) -#define cpu_memoryread_d_paging(a) memp_read32_codefetch(a) -#define cpu_memorywrite_paging(a,v) memp_write8(a,v) -#define cpu_memorywrite_b_paging(a,v) memp_write8(a,v) -#define cpu_memorywrite_w_paging(a,v) memp_write16(a,v) -#define cpu_memorywrite_d_paging(a,v) memp_write32(a,v) -#endif - -#define cpu_memoryread_region(a,p,l) memp_reads(a,p,l) -#define cpu_memorywrite_region(a,p,l) memp_writes(a,p,l) - -void i386c_initialize(void); - -#endif /* IA32_CPU_INTERFACE_H__ */ +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_INTERFACE_H__ +#define IA32_CPU_INTERFACE_H__ + +#ifndef CPUCALL +#define CPUCALL +#endif + +#ifndef STATIC_INLINE +#if defined(__GNUC__) +#define STATIC_INLINE static INLINE __attribute__((unused)) +#else +#define STATIC_INLINE static INLINE +#endif +#endif + +#if !defined(QWORD_CONST) +#define QWORD_CONST(v) v ## ULL +#define SQWORD_CONST(v) v ## LL +#endif + +#define CPU_isEI (CPU_FLAG & I_FLAG) +#define CPU_isDI (!CPU_isEI) +#define CPU_A20EN(en) CPU_ADRSMASK = (en)?0xffffffff:0x000fffff; + +#define CPU_INITIALIZE() i386c_initialize() +#define CPU_DEINITIALIZE() +#define CPU_RESET() ia32reset() +#define CPU_CLEARPREFETCH() +#define CPU_INTERRUPT(vect, soft) ia32_interrupt(vect, soft) +#define CPU_EXEC() ia32() +#define CPU_EXECV30() ia32() +#define CPU_SHUT() ia32shut() +#define CPU_SETEXTSIZE(size) ia32_setextsize((UINT32)(size) << 20) +#define CPU_SETEMM(frame, addr) ia32_setemm(frame, addr) + +#define cpu_memorywrite(a,v) memp_write8(a,v) +#define cpu_memorywrite_b(a,v) memp_write8(a,v) +#define cpu_memorywrite_w(a,v) memp_write16(a,v) +#define cpu_memorywrite_d(a,v) memp_write32(a,v) +#define cpu_memoryread(a) memp_read8(a) +#define cpu_memoryread_b(a) memp_read8(a) +#define cpu_memoryread_w(a) memp_read16(a) +#define cpu_memoryread_d(a) memp_read32(a) +#define cpu_memoryread_codefetch(a) memp_read8_codefetch(a) +#define cpu_memoryread_b_codefetch(a) memp_read8_codefetch(a) +#define cpu_memoryread_w_codefetch(a) memp_read16_codefetch(a) +#define cpu_memoryread_d_codefetch(a) memp_read32_codefetch(a) +#ifdef USE_FASTPAGING +#define cpu_memoryread_paging(a) memp_read8_paging(a) +#define cpu_memoryread_b_paging(a) memp_read8_paging(a) +#define cpu_memoryread_w_paging(a) memp_read16_paging(a) +#define cpu_memoryread_d_paging(a) memp_read32_paging(a) +#define cpu_memorywrite_paging(a,v) memp_write8_paging(a,v) +#define cpu_memorywrite_b_paging(a,v) memp_write8_paging(a,v) +#define cpu_memorywrite_w_paging(a,v) memp_write16_paging(a,v) +#define cpu_memorywrite_d_paging(a,v) memp_write32_paging(a,v) +#else +#define cpu_memoryread_paging(a) memp_read8_codefetch(a) +#define cpu_memoryread_b_paging(a) memp_read8_codefetch(a) +#define cpu_memoryread_w_paging(a) memp_read16_codefetch(a) +#define cpu_memoryread_d_paging(a) memp_read32_codefetch(a) +#define cpu_memorywrite_paging(a,v) memp_write8(a,v) +#define cpu_memorywrite_b_paging(a,v) memp_write8(a,v) +#define cpu_memorywrite_w_paging(a,v) memp_write16(a,v) +#define cpu_memorywrite_d_paging(a,v) memp_write32(a,v) +#endif + +#define cpu_memoryread_region(a,p,l) memp_reads(a,p,l) +#define cpu_memorywrite_region(a,p,l) memp_writes(a,p,l) + +void i386c_initialize(void); + +#endif /* IA32_CPU_INTERFACE_H__ */ diff --git a/i386c/ia32/paging.c b/i386c/ia32/paging.c old mode 100755 new mode 100644 index b15ee296..8b32a27c --- a/i386c/ia32/paging.c +++ b/i386c/ia32/paging.c @@ -1,935 +1,935 @@ -/* - * Copyright (c) 2003-2004 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" -#include "ia32.mcr" - -/* - * ページフォルト例外 - * - * 4-31: 予約済み - * 3: RSVD: 0 = フォルトの原因は予約ビット違反ではなかった. - * 1 = ページ・フォルトの原因は,違反とマークされた PTE または - * PDE の予約ビット位置のうち一つで,1 が検出されたことである. - * 2: U/S: 0 = フォルトの原因となったアクセスはプロセッサがスーパバイザ・ - * モードで実行中に行われた. - * 1 = フォルトの原因となったアクセスはプロセッサがユーザ・モードで - * 実行中に行われた. - * 1: W/R: 0 = フォルトの原因となったアクセスが読み取りであった. - * 1 = フォルトの原因となったアクセスが書き込みであった. - * 0: P: 0 = フォルトの原因が不在ページであった. - * 1 = フォルトの原因がページ・レベル保護違反であった. - */ - -/* - * 下巻 4.12. ページ保護とセグメント保護の組み合わせ - * 「表 4-2. ページ・ディレクトリとページ・テーブルの保護の組み合わせ」 - * - * +------------+------------+------------+ - * | PDE | PTE | merge | - * +-----+------+-----+------+-----+------+ - * | pri | type | pri | type | pri | type | - * +-----+------+-----+------+-----+------+ - * | u | ro | u | ro | u | ro | - * | u | ro | u | rw | u | ro | - * | u | rw | u | ro | u | ro | - * | u | rw | u | rw | u | rw | - * | u | ro | s | ro | s | rw/p | - * | u | ro | s | rw | s | rw/p | - * | u | rw | s | ro | s | rw/p | - * | u | rw | s | rw | s | rw | - * | s | ro | u | ro | s | rw/p | - * | s | ro | u | rw | s | rw/p | - * | s | rw | u | ro | s | rw/p | - * | s | rw | u | rw | s | rw | - * | s | ro | s | ro | s | rw/p | - * | s | ro | s | rw | s | rw/p | - * | s | rw | s | ro | s | rw/p | - * | s | rw | s | rw | s | rw | - * +-----+------+-----+------+-----+------+ - * - * ※ rw/p : CR0 の WP ビットが ON の場合には ro - */ - -/* - * メモリアクセス/PxE(上記参照)/CPL/CR0 とページアクセス権の関係 - * - * +-----+-----+-----+-----+-----+---+ - * | CR0 | CPL | PxE | PxE | ope | | - * | W/P | u/s | u/s | r/w | r/w | | - * +-----+-----+-----+-----+-----+---+ - * | n/a | s | s | n/a | r | o | - * | n/a | s | u | n/a | r | o | - * | n/a | u | s | n/a | r | x | - * | n/a | u | u | n/a | r | o | - * +-----+-----+-----+-----+-----+---+ - * | n | s | s | r | w | o | - * | n | s | u | r | w | o | - * | n | u | s | r | w | x | - * | n | u | u | r | w | x | - * +-----+-----+-----+-----+-----+---+ - * | p | s | s | r | w | x | - * | p | s | u | r | w | x | - * | p | u | s | r | w | x | - * | p | u | u | r | w | x | - * +-----+-----+-----+-----+-----+---+ - * | n | s | s | w | w | o | - * | n | s | u | w | w | o | - * | n | u | s | w | w | x | - * | n | u | u | w | w | o | - * +-----+-----+-----+-----+-----+---+ - * | p | s | s | w | w | o | - * | p | s | u | w | w | x | - * | p | u | s | w | w | x | - * | p | u | u | w | w | o | - * +-----+-----------+-----+-----+---+ - */ -#if !defined(USE_PAGE_ACCESS_TABLE) -#define page_access 0xd0ddd0ff -#else /* USE_PAGE_ACCESS_TABLE */ -static const UINT8 page_access_bit[32] = { - 1, /* CR0: n, CPL: s, PTE: s, PTE: r, ope: r */ - 1, /* CR0: n, CPL: s, PTE: s, PTE: r, ope: w */ - 1, /* CR0: n, CPL: s, PTE: s, PTE: w, ope: r */ - 1, /* CR0: n, CPL: s, PTE: s, PTE: w, ope: w */ - - 1, /* CR0: n, CPL: s, PTE: u, PTE: r, ope: r */ - 1, /* CR0: n, CPL: s, PTE: u, PTE: r, ope: w */ - 1, /* CR0: n, CPL: s, PTE: u, PTE: w, ope: r */ - 1, /* CR0: n, CPL: s, PTE: u, PTE: w, ope: w */ - - 0, /* CR0: n, CPL: u, PTE: s, PTE: r, ope: r */ - 0, /* CR0: n, CPL: u, PTE: s, PTE: r, ope: w */ - 0, /* CR0: n, CPL: u, PTE: s, PTE: w, ope: r */ - 0, /* CR0: n, CPL: u, PTE: s, PTE: w, ope: w */ - - 1, /* CR0: n, CPL: u, PTE: u, PTE: r, ope: r */ - 0, /* CR0: n, CPL: u, PTE: u, PTE: r, ope: w */ - 1, /* CR0: n, CPL: u, PTE: u, PTE: w, ope: r */ - 1, /* CR0: n, CPL: u, PTE: u, PTE: w, ope: w */ - - 1, /* CR0: p, CPL: s, PTE: s, PTE: r, ope: r */ - 0, /* CR0: p, CPL: s, PTE: s, PTE: r, ope: w */ - 1, /* CR0: p, CPL: s, PTE: s, PTE: w, ope: r */ - 1, /* CR0: p, CPL: s, PTE: s, PTE: w, ope: w */ - - 1, /* CR0: p, CPL: s, PTE: u, PTE: r, ope: r */ - 0, /* CR0: p, CPL: s, PTE: u, PTE: r, ope: w */ - 1, /* CR0: p, CPL: s, PTE: u, PTE: w, ope: r */ - 1, /* CR0: p, CPL: s, PTE: u, PTE: w, ope: w */ - - 0, /* CR0: p, CPL: u, PTE: s, PTE: r, ope: r */ - 0, /* CR0: p, CPL: u, PTE: s, PTE: r, ope: w */ - 0, /* CR0: p, CPL: u, PTE: s, PTE: w, ope: r */ - 0, /* CR0: p, CPL: u, PTE: s, PTE: w, ope: w */ - - 1, /* CR0: p, CPL: u, PTE: u, PTE: r, ope: r */ - 0, /* CR0: p, CPL: u, PTE: u, PTE: r, ope: w */ - 1, /* CR0: p, CPL: u, PTE: u, PTE: w, ope: r */ - 1, /* CR0: p, CPL: u, PTE: u, PTE: w, ope: w */ -}; -#endif /* !USE_PAGE_ACCESS_TABLE */ - -/* - *-- - * 32bit 物理アドレス 4k ページ - * - * リニア・アドレス - * 31 22 21 12 11 0 - * +------------------------+----------------------+--------------------------+ - * | ページ・ディレクトリ | ページ・テーブル | オフセット | - * +------------------------+----------------------+--------------------------+ - * | | | - * +-----------+ +-----------+ +----------+ - * | | | - * | ページ・ディレクトリ | ページ・テーブル ページ | - * | +--------------------+ | +-------------------+ +------------------+ | - * | | | | | | | | | - * | | | | +-------------------+ | | | - * | | | +>| page table entry |-+ | | | - * | +--------------------+ +-------------------+ | | | | - * +>|page directory entry|-+ | | | +------------------+ | - * +--------------------+ | | | | | physical address |<+ - * | | | | | | +------------------+ - * | | | | | | | | - * +>+--------------------+ +>+-------------------+ +>+------------------+ - * | - * +- CR3(物理アドレス) - */ -/* TLB */ -struct tlb_entry { - UINT32 tag; /* linear address */ -#define TLB_ENTRY_TAG_VALID (1 << 0) -/* pde & pte & CPU_PTE_WRITABLE (1 << 1) */ -/* pde & pte & CPU_PTE_USER_MODE (1 << 2) */ -#define TLB_ENTRY_TAG_DIRTY CPU_PTE_DIRTY /* (1 << 6) */ -#define TLB_ENTRY_TAG_GLOBAL CPU_PTE_GLOBAL_PAGE /* (1 << 8) */ -#define TLB_ENTRY_TAG_MAX_SHIFT 12 - UINT32 paddr; /* physical address */ -}; -static void MEMCALL tlb_update(UINT32 laddr, UINT entry, int ucrw); - -/* paging */ -static UINT32 MEMCALL paging(UINT32 laddr, int ucrw); - -/* - * linear memory access - */ -/* RMW */ -UINT8 MEMCALL -cpu_memory_access_la_RMW_b(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) -{ - const int ucrw = CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE; - UINT32 paddr; - UINT32 result; - UINT8 value; - - paddr = paging(laddr, ucrw); - value = cpu_memoryread(paddr); - result = (*func)(value, arg); - cpu_memorywrite(paddr, (UINT8)result); - return value; -} - -UINT16 MEMCALL -cpu_memory_access_la_RMW_w(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) -{ - const int ucrw = CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE; - UINT32 paddr[2]; - UINT32 result; - UINT16 value; - - paddr[0] = paging(laddr, ucrw); - if ((laddr + 1) & CPU_PAGE_MASK) { - value = cpu_memoryread_w(paddr[0]); - result = (*func)(value, arg); - cpu_memorywrite_w(paddr[0], (UINT16)result); - return value; - } - - paddr[1] = paging(laddr + 1, ucrw); - value = cpu_memoryread_b(paddr[0]); - value += (UINT16)cpu_memoryread_b(paddr[1]) << 8; - result = (*func)(value, arg); - cpu_memorywrite(paddr[0], (UINT8)result); - cpu_memorywrite(paddr[1], (UINT8)(result >> 8)); - return value; -} - -UINT32 MEMCALL -cpu_memory_access_la_RMW_d(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) -{ - const int ucrw = CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE; - UINT32 paddr[2]; - UINT32 result; - UINT32 value; - int remain; - - paddr[0] = paging(laddr, ucrw); - remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); - if (remain >= 4) { - value = cpu_memoryread_d(paddr[0]); - result = (*func)(value, arg); - cpu_memorywrite_d(paddr[0], result); - return value; - } - - paddr[1] = paging(laddr + remain, ucrw); - switch (remain) { - case 3: - value = cpu_memoryread(paddr[0]); - value += (UINT32)cpu_memoryread_w(paddr[0] + 1) << 8; - value += (UINT32)cpu_memoryread(paddr[1]) << 24; - result = (*func)(value, arg); - cpu_memorywrite(paddr[0], (UINT8)result); - cpu_memorywrite_w(paddr[0] + 1, (UINT16)(result >> 8)); - cpu_memorywrite(paddr[1], (UINT8)(result >> 24)); - break; - - case 2: - value = cpu_memoryread_w(paddr[0]); - value += (UINT32)cpu_memoryread_w(paddr[1]) << 16; - result = (*func)(value, arg); - cpu_memorywrite_w(paddr[0], (UINT16)result); - cpu_memorywrite_w(paddr[1], (UINT16)(result >> 16)); - break; - - case 1: - value = cpu_memoryread(paddr[0]); - value += (UINT32)cpu_memoryread_w(paddr[1]) << 8; - value += (UINT32)cpu_memoryread(paddr[1] + 2) << 24; - result = (*func)(value, arg); - cpu_memorywrite(paddr[0], (UINT8)result); - cpu_memorywrite_w(paddr[1], (UINT16)(result >> 8)); - cpu_memorywrite(paddr[1] + 2, (UINT8)(result >> 24)); - break; - - default: - ia32_panic("cpu_memory_access_la_RMW_d: out of range (remain=%d)\n", remain); - value = 0; /* XXX compiler happy */ - break; - } - return value; -} - -/* read */ -UINT8 MEMCALL -cpu_linear_memory_read_b(UINT32 laddr, int ucrw) -{ - return cpu_memoryread(paging(laddr, ucrw)); -} -PF_UINT8 MEMCALL -cpu_linear_memory_read_b_codefetch(UINT32 laddr, int ucrw) -{ - return cpu_memoryread_codefetch(paging(laddr, ucrw)); -} - -UINT16 MEMCALL -cpu_linear_memory_read_w(UINT32 laddr, int ucrw) -{ - UINT32 paddr[2]; - UINT16 value; - - paddr[0] = paging(laddr, ucrw); - if ((laddr + 1) & CPU_PAGE_MASK) - return cpu_memoryread_w(paddr[0]); - - paddr[1] = paging(laddr + 1, ucrw); - value = cpu_memoryread_b(paddr[0]); - value |= (UINT16)cpu_memoryread_b(paddr[1]) << 8; - return value; -} -PF_UINT16 MEMCALL -cpu_linear_memory_read_w_codefetch(UINT32 laddr, int ucrw) -{ - UINT32 paddr[2]; - PF_UINT16 value; - - paddr[0] = paging(laddr, ucrw); - if ((laddr + 1) & CPU_PAGE_MASK) - return cpu_memoryread_w_codefetch(paddr[0]); - - paddr[1] = paging(laddr + 1, ucrw); - value = cpu_memoryread_b_codefetch(paddr[0]); - value |= (PF_UINT16)cpu_memoryread_b_codefetch(paddr[1]) << 8; - return value; -} - - -UINT32 MEMCALL -cpu_linear_memory_read_d(UINT32 laddr, int ucrw) -{ - UINT32 paddr[2]; - UINT32 value; - UINT remain; - - paddr[0] = paging(laddr, ucrw); - remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); - if (remain >= sizeof(value)) - return cpu_memoryread_d(paddr[0]); - - paddr[1] = paging(laddr + remain, ucrw); - switch (remain) { - case 3: - value = cpu_memoryread(paddr[0]); - value |= (UINT32)cpu_memoryread_w(paddr[0] + 1) << 8; - value |= (UINT32)cpu_memoryread(paddr[1]) << 24; - break; - - case 2: - value = cpu_memoryread_w(paddr[0]); - value |= (UINT32)cpu_memoryread_w(paddr[1]) << 16; - break; - - case 1: - value = cpu_memoryread(paddr[0]); - value |= (UINT32)cpu_memoryread_w(paddr[1]) << 8; - value |= (UINT32)cpu_memoryread(paddr[1] + 2) << 24; - break; - - default: - ia32_panic("cpu_linear_memory_read_d: out of range (remain=%d)\n", remain); - value = 0; /* XXX compiler happy */ - break; - } - return value; -} -PF_UINT32 MEMCALL -cpu_linear_memory_read_d_codefetch(UINT32 laddr, int ucrw) -{ - UINT32 paddr[2]; - UINT32 value; - UINT remain; - - paddr[0] = paging(laddr, ucrw); - remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); - if (remain >= sizeof(value)) - return cpu_memoryread_d_codefetch(paddr[0]); - - paddr[1] = paging(laddr + remain, ucrw); - switch (remain) { - case 3: - value = cpu_memoryread_codefetch(paddr[0]); - value |= (UINT32)cpu_memoryread_w_codefetch(paddr[0] + 1) << 8; - value |= (UINT32)cpu_memoryread_codefetch(paddr[1]) << 24; - break; - - case 2: - value = cpu_memoryread_w_codefetch(paddr[0]); - value |= (UINT32)cpu_memoryread_w_codefetch(paddr[1]) << 16; - break; - - case 1: - value = cpu_memoryread_codefetch(paddr[0]); - value |= (UINT32)cpu_memoryread_w_codefetch(paddr[1]) << 8; - value |= (UINT32)cpu_memoryread_codefetch(paddr[1] + 2) << 24; - break; - - default: - ia32_panic("cpu_linear_memory_read_d: out of range (remain=%d)\n", remain); - value = 0; /* XXX compiler happy */ - break; - } - return value; -} - -UINT64 MEMCALL -cpu_linear_memory_read_q(UINT32 laddr, int ucrw) -{ - UINT32 paddr[2]; - UINT64 value; - UINT remain; - - paddr[0] = paging(laddr, ucrw); - remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); - if (remain >= sizeof(value)) - return cpu_memoryread_q(paddr[0]); - - paddr[1] = paging(laddr + remain, ucrw); - switch (remain) { - case 7: - value = cpu_memoryread(paddr[0]); - value += (UINT64)cpu_memoryread_w(paddr[0] + 1) << 8; - value += (UINT64)cpu_memoryread_d(paddr[0] + 3) << 24; - value += (UINT64)cpu_memoryread(paddr[1]) << 56; - break; - - case 6: - value = cpu_memoryread_w(paddr[0]); - value += (UINT64)cpu_memoryread_d(paddr[0] + 2) << 16; - value += (UINT64)cpu_memoryread_w(paddr[1]) << 48; - break; - - case 5: - value = cpu_memoryread(paddr[0]); - value += (UINT64)cpu_memoryread_d(paddr[0] + 1) << 8; - value += (UINT64)cpu_memoryread_w(paddr[1]) << 40; - value += (UINT64)cpu_memoryread(paddr[1] + 2) << 56; - break; - - case 4: - value = cpu_memoryread_d(paddr[0]); - value += (UINT64)cpu_memoryread_d(paddr[1]) << 32; - break; - - case 3: - value = cpu_memoryread(paddr[0]); - value += (UINT64)cpu_memoryread_w(paddr[0] + 1) << 8; - value += (UINT64)cpu_memoryread_d(paddr[1]) << 24; - value += (UINT64)cpu_memoryread(paddr[1] + 4) << 56; - break; - - case 2: - value = cpu_memoryread_w(paddr[0]); - value += (UINT64)cpu_memoryread_d(paddr[1]) << 16; - value += (UINT64)cpu_memoryread_w(paddr[1] + 4) << 48; - break; - - case 1: - value = cpu_memoryread(paddr[0]); - value += (UINT64)cpu_memoryread_d(paddr[1]) << 8; - value += (UINT64)cpu_memoryread_w(paddr[1] + 4) << 40; - value += (UINT64)cpu_memoryread(paddr[1] + 6) << 56; - break; - - default: - ia32_panic("cpu_linear_memory_read_q: out of range (remain=%d)\n", remain); - value = 0; /* XXX compiler happy */ - break; - } - return value; -} - -REG80 MEMCALL -cpu_linear_memory_read_f(UINT32 laddr, int ucrw) -{ - UINT32 paddr[2]; - REG80 value; - UINT remain; - UINT i, j; - - paddr[0] = paging(laddr, ucrw); - remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); - if (remain >= sizeof(value)) - return cpu_memoryread_f(paddr[0]); - - paddr[1] = paging(laddr + remain, ucrw); - for (i = 0; i < remain; ++i) { - value.b[i] = cpu_memoryread(paddr[0] + i); - } - for (j = 0; i < 10; ++i, ++j) { - value.b[i] = cpu_memoryread(paddr[1] + j); - } - return value; -} - -/* write */ -void MEMCALL -cpu_linear_memory_write_b(UINT32 laddr, UINT8 value, int ucrw) -{ - - cpu_memorywrite(paging(laddr, ucrw), value); -} - -void MEMCALL -cpu_linear_memory_write_w(UINT32 laddr, UINT16 value, int ucrw) -{ - UINT32 paddr[2]; - - paddr[0] = paging(laddr, ucrw); - if ((laddr + 1) & CPU_PAGE_MASK) { - cpu_memorywrite_w(paddr[0], value); - return; - } - - paddr[1] = paging(laddr + 1, ucrw); - cpu_memorywrite(paddr[0], (UINT8)value); - cpu_memorywrite(paddr[1], (UINT8)(value >> 8)); -} - -void MEMCALL -cpu_linear_memory_write_d(UINT32 laddr, UINT32 value, int ucrw) -{ - UINT32 paddr[2]; - UINT remain; - - paddr[0] = paging(laddr, ucrw); - remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); - if (remain >= sizeof(value)) { - cpu_memorywrite_d(paddr[0], value); - return; - } - - paddr[1] = paging(laddr + remain, ucrw); - switch (remain) { - case 3: - cpu_memorywrite(paddr[0], (UINT8)value); - cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); - cpu_memorywrite(paddr[1], (UINT8)(value >> 24)); - break; - - case 2: - cpu_memorywrite_w(paddr[0], (UINT16)value); - cpu_memorywrite_w(paddr[1], (UINT16)(value >> 16)); - break; - - case 1: - cpu_memorywrite(paddr[0], (UINT8)value); - cpu_memorywrite_w(paddr[1], (UINT16)(value >> 8)); - cpu_memorywrite(paddr[1] + 2, (UINT8)(value >> 24)); - break; - - default: - ia32_panic("cpu_linear_memory_write_d: out of range (remain=%d)\n", remain); - break; - } -} - -void MEMCALL -cpu_linear_memory_write_q(UINT32 laddr, UINT64 value, int ucrw) -{ - UINT32 paddr[2]; - UINT remain; - - paddr[0] = paging(laddr, ucrw); - remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); - if (remain >= sizeof(value)) { - cpu_memorywrite_q(paddr[0], value); - return; - } - - paddr[1] = paging(laddr + remain, ucrw); - switch (remain) { - case 7: - cpu_memorywrite(paddr[0], (UINT8)value); - cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); - cpu_memorywrite_d(paddr[0] + 3, (UINT32)(value >> 24)); - cpu_memorywrite(paddr[1], (UINT8)(value >> 56)); - break; - - case 6: - cpu_memorywrite_w(paddr[0], (UINT16)value); - cpu_memorywrite_d(paddr[0] + 2, (UINT32)(value >> 16)); - cpu_memorywrite_w(paddr[1], (UINT16)(value >> 48)); - break; - - case 5: - cpu_memorywrite(paddr[0], (UINT8)value); - cpu_memorywrite_d(paddr[0] + 1, (UINT32)(value >> 8)); - cpu_memorywrite_w(paddr[1], (UINT16)(value >> 40)); - cpu_memorywrite(paddr[1] + 2, (UINT8)(value >> 56)); - break; - - case 4: - cpu_memorywrite_d(paddr[0], (UINT32)value); - cpu_memorywrite_d(paddr[1], (UINT32)(value >> 32)); - break; - - case 3: - cpu_memorywrite(paddr[0], (UINT8)value); - cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); - cpu_memorywrite_d(paddr[1], (UINT32)(value >> 24)); - cpu_memorywrite(paddr[1] + 4, (UINT8)(value >> 56)); - break; - - case 2: - cpu_memorywrite_w(paddr[0], (UINT16)value); - cpu_memorywrite_d(paddr[1], (UINT32)(value >> 16)); - cpu_memorywrite_w(paddr[1] + 4, (UINT16)(value >> 48)); - break; - - case 1: - cpu_memorywrite(paddr[0], (UINT8)value); - cpu_memorywrite_d(paddr[1], (UINT32)(value >> 8)); - cpu_memorywrite_w(paddr[1] + 4, (UINT16)(value >> 40)); - cpu_memorywrite(paddr[1] + 6, (UINT8)(value >> 56)); - break; - - default: - ia32_panic("cpu_linear_memory_write_q: out of range (remain=%d)\n", remain); - break; - } -} - -void MEMCALL -cpu_linear_memory_write_f(UINT32 laddr, const REG80 *value, int ucrw) -{ - UINT32 paddr[2]; - UINT remain; - UINT i, j; - - paddr[0] = paging(laddr, ucrw); - remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); - if (remain >= sizeof(value)) { - cpu_memorywrite_f(paddr[0], value); - return; - } - - paddr[1] = paging(laddr + remain, ucrw); - for (i = 0; i < remain; ++i) { - cpu_memorywrite(paddr[0] + i, value->b[i]); - } - for (j = 0; i < 10; ++i, ++j) { - cpu_memorywrite(paddr[1] + j, value->b[i]); - } -} - -/* - * linear address memory access function - */ -void MEMCALL -cpu_memory_access_la_region(UINT32 laddr, UINT length, int ucrw, UINT8 *data) -{ - UINT32 paddr; - UINT remain; /* page remain */ - UINT r; - - while (length > 0) { - remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); - if (!CPU_STAT_PAGING) { - paddr = laddr; - } else { - paddr = paging(laddr, ucrw); - } - - r = (remain > length) ? length : remain; - if (!(ucrw & CPU_PAGE_WRITE)) { - cpu_memoryread_region(paddr, data, r); - } else { - cpu_memorywrite_region(paddr, data, r); - } - - laddr += r; - data += r; - length -= r; - } -} - -UINT32 MEMCALL -laddr2paddr(UINT32 laddr, int ucrw) -{ - - return paging(laddr, ucrw); -} - -/* - * paging - */ -static UINT32 MEMCALL -paging(UINT32 laddr, int ucrw) -{ - struct tlb_entry *ep; - UINT32 paddr; /* physical address */ - UINT32 pde_addr; /* page directory entry address */ - UINT32 pde; /* page directory entry */ - UINT32 pte_addr; /* page table entry address */ - UINT32 pte; /* page table entry */ - UINT bit; - UINT err; - -#if !defined(SUPPORT_IA32_HAXM) // HAXMはエミュレーションTLBを使わない - ep = tlb_lookup(laddr, ucrw); - if (ep != NULL) - return ep->paddr + (laddr & CPU_PAGE_MASK); -#endif - - pde_addr = CPU_STAT_PDE_BASE + ((laddr >> 20) & 0xffc); - pde = cpu_memoryread_d_paging(pde_addr); - if (!(pde & CPU_PDE_PRESENT)) { - VERBOSE(("paging: PTE page is not present")); - VERBOSE(("paging: CPU_CR3 = 0x%08x", CPU_CR3)); - VERBOSE(("paging: laddr = 0x%08x, pde_addr = 0x%08x, pde = 0x%08x", laddr, pde_addr, pde)); - err = 0; - goto pf_exception; - } - if (!(pde & CPU_PDE_ACCESS)) { - pde |= CPU_PDE_ACCESS; - cpu_memorywrite_d_paging(pde_addr, pde); - } - -#if defined(SUPPORT_IA32_HAXM) // HAXMは4MBページのことがある - if ((CPU_CR4 & CPU_CR4_PSE) && (pde & CPU_PDE_PAGE_SIZE)) { - /* 4MB page size */ - paddr = (pde & CPU_PDE_4M_BASEADDR_MASK) | (laddr & 0x003fffff); - - bit = ucrw & (CPU_PAGE_WRITE | CPU_PAGE_USER_MODE); - bit |= (pde & (CPU_PTE_WRITABLE | CPU_PTE_USER_MODE)); - bit |= CPU_STAT_WP; - } - else -#endif - { - /* 4KB page size */ - pte_addr = (pde & CPU_PDE_BASEADDR_MASK) + ((laddr >> 10) & 0xffc); - pte = cpu_memoryread_d_paging(pte_addr); - if (!(pte & CPU_PTE_PRESENT)) { - VERBOSE(("paging: page is not present")); - VERBOSE(("paging: laddr = 0x%08x, pde_addr = 0x%08x, pde = 0x%08x", laddr, pde_addr, pde)); - VERBOSE(("paging: pte_addr = 0x%08x, pte = 0x%08x", pte_addr, pte)); - err = 0; - goto pf_exception; - } - if (!(pte & CPU_PTE_ACCESS)) { - pte |= CPU_PTE_ACCESS; - cpu_memorywrite_d_paging(pte_addr, pte); - } - - /* make physical address */ - paddr = (pte & CPU_PTE_BASEADDR_MASK) + (laddr & CPU_PAGE_MASK); - - bit = ucrw & (CPU_PAGE_WRITE | CPU_PAGE_USER_MODE); - bit |= (pde & pte & (CPU_PTE_WRITABLE | CPU_PTE_USER_MODE)); - bit |= CPU_STAT_WP; - -#if !defined(USE_PAGE_ACCESS_TABLE) - if (!(page_access & (1 << bit))) -#else - if (!(page_access_bit[bit])) -#endif - { - VERBOSE(("paging: page access violation.")); - VERBOSE(("paging: laddr = 0x%08x, pde_addr = 0x%08x, pde = 0x%08x", laddr, pde_addr, pde)); - VERBOSE(("paging: pte_addr = 0x%08x, pte = 0x%08x", pte_addr, pte)); - VERBOSE(("paging: paddr = 0x%08x, bit = 0x%08x", paddr, bit)); - err = 1; - goto pf_exception; - } - - if ((ucrw & CPU_PAGE_WRITE) && !(pte & CPU_PTE_DIRTY)) { - pte |= CPU_PTE_DIRTY; - cpu_memorywrite_d_paging(pte_addr, pte); - } - - tlb_update(laddr, pte, (bit & (CPU_PTE_WRITABLE | CPU_PTE_USER_MODE)) + ((ucrw & CPU_PAGE_CODE) ? 1 : 0)); - } - - return paddr; - -pf_exception: - CPU_CR2 = laddr; - err |= (ucrw & CPU_PAGE_WRITE) << 1; - err |= (ucrw & CPU_PAGE_USER_MODE) >> 1; - EXCEPTION(PF_EXCEPTION, err); - return 0; /* compiler happy */ -} - -/* - * TLB - */ -#define TLB_TAG_SHIFT TLB_ENTRY_TAG_MAX_SHIFT -#define TLB_TAG_MASK (~((1 << TLB_TAG_SHIFT) - 1)) -#define TLB_GET_TAG_ADDR(ep) ((ep)->tag & TLB_TAG_MASK) -#define TLB_SET_TAG_ADDR(ep, addr) \ -do { \ - (ep)->tag &= ~TLB_TAG_MASK; \ - (ep)->tag |= (addr) & TLB_TAG_MASK; \ -} while (/*CONSTCOND(*/ 0) - -#define TLB_IS_VALID(ep) ((ep)->tag & TLB_ENTRY_TAG_VALID) -#define TLB_SET_VALID(ep) ((ep)->tag = TLB_ENTRY_TAG_VALID) -#define TLB_SET_INVALID(ep) ((ep)->tag = 0) - -#define TLB_IS_WRITABLE(ep) ((ep)->tag & CPU_PTE_WRITABLE) -#define TLB_IS_USERMODE(ep) ((ep)->tag & CPU_PTE_USER_MODE) -#define TLB_IS_DIRTY(ep) ((ep)->tag & TLB_ENTRY_TAG_DIRTY) -#if (CPU_FEATURES_ALL & CPU_FEATURE_PGE) == CPU_FEATURE_PGE -#define TLB_IS_GLOBAL(ep) ((ep)->tag & TLB_ENTRY_TAG_GLOBAL) -#else -#define TLB_IS_GLOBAL(ep) 0 -#endif - -#define TLB_SET_TAG_FLAGS(ep, entry, bit) \ -do { \ - (ep)->tag |= (entry) & (CPU_PTE_GLOBAL_PAGE|CPU_PTE_DIRTY); \ - (ep)->tag |= (bit) & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE); \ -} while (/*CONSTCOND*/ 0) - -#define NTLB 2 /* 0: DTLB, 1: ITLB */ -#define NENTRY (1 << 6) -#define TLB_ENTRY_SHIFT 12 -#define TLB_ENTRY_MASK (NENTRY - 1) - -typedef struct { - struct tlb_entry entry[NENTRY]; -} tlb_t; -static tlb_t tlb[NTLB]; - -void -tlb_init(void) -{ - memset(tlb, 0, sizeof(tlb)); -} - -void MEMCALL -tlb_flush() -{ - struct tlb_entry *ep; - int i; - int n; - - for (n = 0; n < NTLB; n++) { - for (i = 0; i < NENTRY ; i++) { - ep = &tlb[n].entry[i]; - if (TLB_IS_VALID(ep) && !TLB_IS_GLOBAL(ep)) { - TLB_SET_INVALID(ep); - } - } - } -} - -void MEMCALL -tlb_flush_all() -{ - tlb_init(); -} - -void MEMCALL -tlb_flush_page(UINT32 laddr) -{ - struct tlb_entry *ep; - int idx; - int n; - - idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; - - for (n = 0; n < NTLB; n++) { - ep = &tlb[n].entry[idx]; - if (TLB_IS_VALID(ep)) { - if ((laddr & TLB_TAG_MASK) == TLB_GET_TAG_ADDR(ep)) { - TLB_SET_INVALID(ep); - } - } - } -} - -struct tlb_entry * MEMCALL -tlb_lookup(UINT32 laddr, int ucrw) -{ - struct tlb_entry *ep; - UINT bit; - int idx; - int n; - - n = (ucrw & CPU_PAGE_CODE) ? 1 : 0; - idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; - ep = &tlb[n].entry[idx]; - - if (TLB_IS_VALID(ep)) { - if ((laddr & TLB_TAG_MASK) == TLB_GET_TAG_ADDR(ep)) { - bit = ucrw & (CPU_PAGE_WRITE|CPU_PAGE_USER_MODE); - bit |= ep->tag & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE); - bit |= CPU_STAT_WP; -#if !defined(USE_PAGE_ACCESS_TABLE) - if ((page_access & (1 << bit))) -#else - if (page_access_bit[bit]) -#endif - { - if (!(ucrw & CPU_PAGE_WRITE) || TLB_IS_DIRTY(ep)) { - return ep; - } - } - } - } - return NULL; -} - -static void MEMCALL -tlb_update(UINT32 laddr, UINT entry, int bit) -{ - struct tlb_entry *ep; - int idx; - int n; - - n = bit & 1; - idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; - ep = &tlb[n].entry[idx]; - - TLB_SET_VALID(ep); - TLB_SET_TAG_ADDR(ep, laddr); - TLB_SET_TAG_FLAGS(ep, entry, bit); - ep->paddr = entry & CPU_PTE_BASEADDR_MASK; -} +/* + * Copyright (c) 2003-2004 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" +#include "ia32.mcr" + +/* + * ページフォルト例外 + * + * 4-31: 予約済み + * 3: RSVD: 0 = フォルトの原因は予約ビット違反ではなかった. + * 1 = ページ・フォルトの原因は,違反とマークされた PTE または + * PDE の予約ビット位置のうち一つで,1 が検出されたことである. + * 2: U/S: 0 = フォルトの原因となったアクセスはプロセッサがスーパバイザ・ + * モードで実行中に行われた. + * 1 = フォルトの原因となったアクセスはプロセッサがユーザ・モードで + * 実行中に行われた. + * 1: W/R: 0 = フォルトの原因となったアクセスが読み取りであった. + * 1 = フォルトの原因となったアクセスが書き込みであった. + * 0: P: 0 = フォルトの原因が不在ページであった. + * 1 = フォルトの原因がページ・レベル保護違反であった. + */ + +/* + * 下巻 4.12. ページ保護とセグメント保護の組み合わせ + * 「表 4-2. ページ・ディレクトリとページ・テーブルの保護の組み合わせ」 + * + * +------------+------------+------------+ + * | PDE | PTE | merge | + * +-----+------+-----+------+-----+------+ + * | pri | type | pri | type | pri | type | + * +-----+------+-----+------+-----+------+ + * | u | ro | u | ro | u | ro | + * | u | ro | u | rw | u | ro | + * | u | rw | u | ro | u | ro | + * | u | rw | u | rw | u | rw | + * | u | ro | s | ro | s | rw/p | + * | u | ro | s | rw | s | rw/p | + * | u | rw | s | ro | s | rw/p | + * | u | rw | s | rw | s | rw | + * | s | ro | u | ro | s | rw/p | + * | s | ro | u | rw | s | rw/p | + * | s | rw | u | ro | s | rw/p | + * | s | rw | u | rw | s | rw | + * | s | ro | s | ro | s | rw/p | + * | s | ro | s | rw | s | rw/p | + * | s | rw | s | ro | s | rw/p | + * | s | rw | s | rw | s | rw | + * +-----+------+-----+------+-----+------+ + * + * ※ rw/p : CR0 の WP ビットが ON の場合には ro + */ + +/* + * メモリアクセス/PxE(上記参照)/CPL/CR0 とページアクセス権の関係 + * + * +-----+-----+-----+-----+-----+---+ + * | CR0 | CPL | PxE | PxE | ope | | + * | W/P | u/s | u/s | r/w | r/w | | + * +-----+-----+-----+-----+-----+---+ + * | n/a | s | s | n/a | r | o | + * | n/a | s | u | n/a | r | o | + * | n/a | u | s | n/a | r | x | + * | n/a | u | u | n/a | r | o | + * +-----+-----+-----+-----+-----+---+ + * | n | s | s | r | w | o | + * | n | s | u | r | w | o | + * | n | u | s | r | w | x | + * | n | u | u | r | w | x | + * +-----+-----+-----+-----+-----+---+ + * | p | s | s | r | w | x | + * | p | s | u | r | w | x | + * | p | u | s | r | w | x | + * | p | u | u | r | w | x | + * +-----+-----+-----+-----+-----+---+ + * | n | s | s | w | w | o | + * | n | s | u | w | w | o | + * | n | u | s | w | w | x | + * | n | u | u | w | w | o | + * +-----+-----+-----+-----+-----+---+ + * | p | s | s | w | w | o | + * | p | s | u | w | w | x | + * | p | u | s | w | w | x | + * | p | u | u | w | w | o | + * +-----+-----------+-----+-----+---+ + */ +#if !defined(USE_PAGE_ACCESS_TABLE) +#define page_access 0xd0ddd0ff +#else /* USE_PAGE_ACCESS_TABLE */ +static const UINT8 page_access_bit[32] = { + 1, /* CR0: n, CPL: s, PTE: s, PTE: r, ope: r */ + 1, /* CR0: n, CPL: s, PTE: s, PTE: r, ope: w */ + 1, /* CR0: n, CPL: s, PTE: s, PTE: w, ope: r */ + 1, /* CR0: n, CPL: s, PTE: s, PTE: w, ope: w */ + + 1, /* CR0: n, CPL: s, PTE: u, PTE: r, ope: r */ + 1, /* CR0: n, CPL: s, PTE: u, PTE: r, ope: w */ + 1, /* CR0: n, CPL: s, PTE: u, PTE: w, ope: r */ + 1, /* CR0: n, CPL: s, PTE: u, PTE: w, ope: w */ + + 0, /* CR0: n, CPL: u, PTE: s, PTE: r, ope: r */ + 0, /* CR0: n, CPL: u, PTE: s, PTE: r, ope: w */ + 0, /* CR0: n, CPL: u, PTE: s, PTE: w, ope: r */ + 0, /* CR0: n, CPL: u, PTE: s, PTE: w, ope: w */ + + 1, /* CR0: n, CPL: u, PTE: u, PTE: r, ope: r */ + 0, /* CR0: n, CPL: u, PTE: u, PTE: r, ope: w */ + 1, /* CR0: n, CPL: u, PTE: u, PTE: w, ope: r */ + 1, /* CR0: n, CPL: u, PTE: u, PTE: w, ope: w */ + + 1, /* CR0: p, CPL: s, PTE: s, PTE: r, ope: r */ + 0, /* CR0: p, CPL: s, PTE: s, PTE: r, ope: w */ + 1, /* CR0: p, CPL: s, PTE: s, PTE: w, ope: r */ + 1, /* CR0: p, CPL: s, PTE: s, PTE: w, ope: w */ + + 1, /* CR0: p, CPL: s, PTE: u, PTE: r, ope: r */ + 0, /* CR0: p, CPL: s, PTE: u, PTE: r, ope: w */ + 1, /* CR0: p, CPL: s, PTE: u, PTE: w, ope: r */ + 1, /* CR0: p, CPL: s, PTE: u, PTE: w, ope: w */ + + 0, /* CR0: p, CPL: u, PTE: s, PTE: r, ope: r */ + 0, /* CR0: p, CPL: u, PTE: s, PTE: r, ope: w */ + 0, /* CR0: p, CPL: u, PTE: s, PTE: w, ope: r */ + 0, /* CR0: p, CPL: u, PTE: s, PTE: w, ope: w */ + + 1, /* CR0: p, CPL: u, PTE: u, PTE: r, ope: r */ + 0, /* CR0: p, CPL: u, PTE: u, PTE: r, ope: w */ + 1, /* CR0: p, CPL: u, PTE: u, PTE: w, ope: r */ + 1, /* CR0: p, CPL: u, PTE: u, PTE: w, ope: w */ +}; +#endif /* !USE_PAGE_ACCESS_TABLE */ + +/* + *-- + * 32bit 物理アドレス 4k ページ + * + * リニア・アドレス + * 31 22 21 12 11 0 + * +------------------------+----------------------+--------------------------+ + * | ページ・ディレクトリ | ページ・テーブル | オフセット | + * +------------------------+----------------------+--------------------------+ + * | | | + * +-----------+ +-----------+ +----------+ + * | | | + * | ページ・ディレクトリ | ページ・テーブル ページ | + * | +--------------------+ | +-------------------+ +------------------+ | + * | | | | | | | | | + * | | | | +-------------------+ | | | + * | | | +>| page table entry |-+ | | | + * | +--------------------+ +-------------------+ | | | | + * +>|page directory entry|-+ | | | +------------------+ | + * +--------------------+ | | | | | physical address |<+ + * | | | | | | +------------------+ + * | | | | | | | | + * +>+--------------------+ +>+-------------------+ +>+------------------+ + * | + * +- CR3(物理アドレス) + */ +/* TLB */ +struct tlb_entry { + UINT32 tag; /* linear address */ +#define TLB_ENTRY_TAG_VALID (1 << 0) +/* pde & pte & CPU_PTE_WRITABLE (1 << 1) */ +/* pde & pte & CPU_PTE_USER_MODE (1 << 2) */ +#define TLB_ENTRY_TAG_DIRTY CPU_PTE_DIRTY /* (1 << 6) */ +#define TLB_ENTRY_TAG_GLOBAL CPU_PTE_GLOBAL_PAGE /* (1 << 8) */ +#define TLB_ENTRY_TAG_MAX_SHIFT 12 + UINT32 paddr; /* physical address */ +}; +static void MEMCALL tlb_update(UINT32 laddr, UINT entry, int ucrw); + +/* paging */ +static UINT32 MEMCALL paging(UINT32 laddr, int ucrw); + +/* + * linear memory access + */ +/* RMW */ +UINT8 MEMCALL +cpu_memory_access_la_RMW_b(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) +{ + const int ucrw = CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE; + UINT32 paddr; + UINT32 result; + UINT8 value; + + paddr = paging(laddr, ucrw); + value = cpu_memoryread(paddr); + result = (*func)(value, arg); + cpu_memorywrite(paddr, (UINT8)result); + return value; +} + +UINT16 MEMCALL +cpu_memory_access_la_RMW_w(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) +{ + const int ucrw = CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE; + UINT32 paddr[2]; + UINT32 result; + UINT16 value; + + paddr[0] = paging(laddr, ucrw); + if ((laddr + 1) & CPU_PAGE_MASK) { + value = cpu_memoryread_w(paddr[0]); + result = (*func)(value, arg); + cpu_memorywrite_w(paddr[0], (UINT16)result); + return value; + } + + paddr[1] = paging(laddr + 1, ucrw); + value = cpu_memoryread_b(paddr[0]); + value += (UINT16)cpu_memoryread_b(paddr[1]) << 8; + result = (*func)(value, arg); + cpu_memorywrite(paddr[0], (UINT8)result); + cpu_memorywrite(paddr[1], (UINT8)(result >> 8)); + return value; +} + +UINT32 MEMCALL +cpu_memory_access_la_RMW_d(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) +{ + const int ucrw = CPU_PAGE_WRITE_DATA | CPU_STAT_USER_MODE; + UINT32 paddr[2]; + UINT32 result; + UINT32 value; + int remain; + + paddr[0] = paging(laddr, ucrw); + remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); + if (remain >= 4) { + value = cpu_memoryread_d(paddr[0]); + result = (*func)(value, arg); + cpu_memorywrite_d(paddr[0], result); + return value; + } + + paddr[1] = paging(laddr + remain, ucrw); + switch (remain) { + case 3: + value = cpu_memoryread(paddr[0]); + value += (UINT32)cpu_memoryread_w(paddr[0] + 1) << 8; + value += (UINT32)cpu_memoryread(paddr[1]) << 24; + result = (*func)(value, arg); + cpu_memorywrite(paddr[0], (UINT8)result); + cpu_memorywrite_w(paddr[0] + 1, (UINT16)(result >> 8)); + cpu_memorywrite(paddr[1], (UINT8)(result >> 24)); + break; + + case 2: + value = cpu_memoryread_w(paddr[0]); + value += (UINT32)cpu_memoryread_w(paddr[1]) << 16; + result = (*func)(value, arg); + cpu_memorywrite_w(paddr[0], (UINT16)result); + cpu_memorywrite_w(paddr[1], (UINT16)(result >> 16)); + break; + + case 1: + value = cpu_memoryread(paddr[0]); + value += (UINT32)cpu_memoryread_w(paddr[1]) << 8; + value += (UINT32)cpu_memoryread(paddr[1] + 2) << 24; + result = (*func)(value, arg); + cpu_memorywrite(paddr[0], (UINT8)result); + cpu_memorywrite_w(paddr[1], (UINT16)(result >> 8)); + cpu_memorywrite(paddr[1] + 2, (UINT8)(result >> 24)); + break; + + default: + ia32_panic("cpu_memory_access_la_RMW_d: out of range (remain=%d)\n", remain); + value = 0; /* XXX compiler happy */ + break; + } + return value; +} + +/* read */ +UINT8 MEMCALL +cpu_linear_memory_read_b(UINT32 laddr, int ucrw) +{ + return cpu_memoryread(paging(laddr, ucrw)); +} +PF_UINT8 MEMCALL +cpu_linear_memory_read_b_codefetch(UINT32 laddr, int ucrw) +{ + return cpu_memoryread_codefetch(paging(laddr, ucrw)); +} + +UINT16 MEMCALL +cpu_linear_memory_read_w(UINT32 laddr, int ucrw) +{ + UINT32 paddr[2]; + UINT16 value; + + paddr[0] = paging(laddr, ucrw); + if ((laddr + 1) & CPU_PAGE_MASK) + return cpu_memoryread_w(paddr[0]); + + paddr[1] = paging(laddr + 1, ucrw); + value = cpu_memoryread_b(paddr[0]); + value |= (UINT16)cpu_memoryread_b(paddr[1]) << 8; + return value; +} +PF_UINT16 MEMCALL +cpu_linear_memory_read_w_codefetch(UINT32 laddr, int ucrw) +{ + UINT32 paddr[2]; + PF_UINT16 value; + + paddr[0] = paging(laddr, ucrw); + if ((laddr + 1) & CPU_PAGE_MASK) + return cpu_memoryread_w_codefetch(paddr[0]); + + paddr[1] = paging(laddr + 1, ucrw); + value = cpu_memoryread_b_codefetch(paddr[0]); + value |= (PF_UINT16)cpu_memoryread_b_codefetch(paddr[1]) << 8; + return value; +} + + +UINT32 MEMCALL +cpu_linear_memory_read_d(UINT32 laddr, int ucrw) +{ + UINT32 paddr[2]; + UINT32 value; + UINT remain; + + paddr[0] = paging(laddr, ucrw); + remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); + if (remain >= sizeof(value)) + return cpu_memoryread_d(paddr[0]); + + paddr[1] = paging(laddr + remain, ucrw); + switch (remain) { + case 3: + value = cpu_memoryread(paddr[0]); + value |= (UINT32)cpu_memoryread_w(paddr[0] + 1) << 8; + value |= (UINT32)cpu_memoryread(paddr[1]) << 24; + break; + + case 2: + value = cpu_memoryread_w(paddr[0]); + value |= (UINT32)cpu_memoryread_w(paddr[1]) << 16; + break; + + case 1: + value = cpu_memoryread(paddr[0]); + value |= (UINT32)cpu_memoryread_w(paddr[1]) << 8; + value |= (UINT32)cpu_memoryread(paddr[1] + 2) << 24; + break; + + default: + ia32_panic("cpu_linear_memory_read_d: out of range (remain=%d)\n", remain); + value = 0; /* XXX compiler happy */ + break; + } + return value; +} +PF_UINT32 MEMCALL +cpu_linear_memory_read_d_codefetch(UINT32 laddr, int ucrw) +{ + UINT32 paddr[2]; + UINT32 value; + UINT remain; + + paddr[0] = paging(laddr, ucrw); + remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); + if (remain >= sizeof(value)) + return cpu_memoryread_d_codefetch(paddr[0]); + + paddr[1] = paging(laddr + remain, ucrw); + switch (remain) { + case 3: + value = cpu_memoryread_codefetch(paddr[0]); + value |= (UINT32)cpu_memoryread_w_codefetch(paddr[0] + 1) << 8; + value |= (UINT32)cpu_memoryread_codefetch(paddr[1]) << 24; + break; + + case 2: + value = cpu_memoryread_w_codefetch(paddr[0]); + value |= (UINT32)cpu_memoryread_w_codefetch(paddr[1]) << 16; + break; + + case 1: + value = cpu_memoryread_codefetch(paddr[0]); + value |= (UINT32)cpu_memoryread_w_codefetch(paddr[1]) << 8; + value |= (UINT32)cpu_memoryread_codefetch(paddr[1] + 2) << 24; + break; + + default: + ia32_panic("cpu_linear_memory_read_d: out of range (remain=%d)\n", remain); + value = 0; /* XXX compiler happy */ + break; + } + return value; +} + +UINT64 MEMCALL +cpu_linear_memory_read_q(UINT32 laddr, int ucrw) +{ + UINT32 paddr[2]; + UINT64 value; + UINT remain; + + paddr[0] = paging(laddr, ucrw); + remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); + if (remain >= sizeof(value)) + return cpu_memoryread_q(paddr[0]); + + paddr[1] = paging(laddr + remain, ucrw); + switch (remain) { + case 7: + value = cpu_memoryread(paddr[0]); + value += (UINT64)cpu_memoryread_w(paddr[0] + 1) << 8; + value += (UINT64)cpu_memoryread_d(paddr[0] + 3) << 24; + value += (UINT64)cpu_memoryread(paddr[1]) << 56; + break; + + case 6: + value = cpu_memoryread_w(paddr[0]); + value += (UINT64)cpu_memoryread_d(paddr[0] + 2) << 16; + value += (UINT64)cpu_memoryread_w(paddr[1]) << 48; + break; + + case 5: + value = cpu_memoryread(paddr[0]); + value += (UINT64)cpu_memoryread_d(paddr[0] + 1) << 8; + value += (UINT64)cpu_memoryread_w(paddr[1]) << 40; + value += (UINT64)cpu_memoryread(paddr[1] + 2) << 56; + break; + + case 4: + value = cpu_memoryread_d(paddr[0]); + value += (UINT64)cpu_memoryread_d(paddr[1]) << 32; + break; + + case 3: + value = cpu_memoryread(paddr[0]); + value += (UINT64)cpu_memoryread_w(paddr[0] + 1) << 8; + value += (UINT64)cpu_memoryread_d(paddr[1]) << 24; + value += (UINT64)cpu_memoryread(paddr[1] + 4) << 56; + break; + + case 2: + value = cpu_memoryread_w(paddr[0]); + value += (UINT64)cpu_memoryread_d(paddr[1]) << 16; + value += (UINT64)cpu_memoryread_w(paddr[1] + 4) << 48; + break; + + case 1: + value = cpu_memoryread(paddr[0]); + value += (UINT64)cpu_memoryread_d(paddr[1]) << 8; + value += (UINT64)cpu_memoryread_w(paddr[1] + 4) << 40; + value += (UINT64)cpu_memoryread(paddr[1] + 6) << 56; + break; + + default: + ia32_panic("cpu_linear_memory_read_q: out of range (remain=%d)\n", remain); + value = 0; /* XXX compiler happy */ + break; + } + return value; +} + +REG80 MEMCALL +cpu_linear_memory_read_f(UINT32 laddr, int ucrw) +{ + UINT32 paddr[2]; + REG80 value; + UINT remain; + UINT i, j; + + paddr[0] = paging(laddr, ucrw); + remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); + if (remain >= sizeof(value)) + return cpu_memoryread_f(paddr[0]); + + paddr[1] = paging(laddr + remain, ucrw); + for (i = 0; i < remain; ++i) { + value.b[i] = cpu_memoryread(paddr[0] + i); + } + for (j = 0; i < 10; ++i, ++j) { + value.b[i] = cpu_memoryread(paddr[1] + j); + } + return value; +} + +/* write */ +void MEMCALL +cpu_linear_memory_write_b(UINT32 laddr, UINT8 value, int ucrw) +{ + + cpu_memorywrite(paging(laddr, ucrw), value); +} + +void MEMCALL +cpu_linear_memory_write_w(UINT32 laddr, UINT16 value, int ucrw) +{ + UINT32 paddr[2]; + + paddr[0] = paging(laddr, ucrw); + if ((laddr + 1) & CPU_PAGE_MASK) { + cpu_memorywrite_w(paddr[0], value); + return; + } + + paddr[1] = paging(laddr + 1, ucrw); + cpu_memorywrite(paddr[0], (UINT8)value); + cpu_memorywrite(paddr[1], (UINT8)(value >> 8)); +} + +void MEMCALL +cpu_linear_memory_write_d(UINT32 laddr, UINT32 value, int ucrw) +{ + UINT32 paddr[2]; + UINT remain; + + paddr[0] = paging(laddr, ucrw); + remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); + if (remain >= sizeof(value)) { + cpu_memorywrite_d(paddr[0], value); + return; + } + + paddr[1] = paging(laddr + remain, ucrw); + switch (remain) { + case 3: + cpu_memorywrite(paddr[0], (UINT8)value); + cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); + cpu_memorywrite(paddr[1], (UINT8)(value >> 24)); + break; + + case 2: + cpu_memorywrite_w(paddr[0], (UINT16)value); + cpu_memorywrite_w(paddr[1], (UINT16)(value >> 16)); + break; + + case 1: + cpu_memorywrite(paddr[0], (UINT8)value); + cpu_memorywrite_w(paddr[1], (UINT16)(value >> 8)); + cpu_memorywrite(paddr[1] + 2, (UINT8)(value >> 24)); + break; + + default: + ia32_panic("cpu_linear_memory_write_d: out of range (remain=%d)\n", remain); + break; + } +} + +void MEMCALL +cpu_linear_memory_write_q(UINT32 laddr, UINT64 value, int ucrw) +{ + UINT32 paddr[2]; + UINT remain; + + paddr[0] = paging(laddr, ucrw); + remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); + if (remain >= sizeof(value)) { + cpu_memorywrite_q(paddr[0], value); + return; + } + + paddr[1] = paging(laddr + remain, ucrw); + switch (remain) { + case 7: + cpu_memorywrite(paddr[0], (UINT8)value); + cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); + cpu_memorywrite_d(paddr[0] + 3, (UINT32)(value >> 24)); + cpu_memorywrite(paddr[1], (UINT8)(value >> 56)); + break; + + case 6: + cpu_memorywrite_w(paddr[0], (UINT16)value); + cpu_memorywrite_d(paddr[0] + 2, (UINT32)(value >> 16)); + cpu_memorywrite_w(paddr[1], (UINT16)(value >> 48)); + break; + + case 5: + cpu_memorywrite(paddr[0], (UINT8)value); + cpu_memorywrite_d(paddr[0] + 1, (UINT32)(value >> 8)); + cpu_memorywrite_w(paddr[1], (UINT16)(value >> 40)); + cpu_memorywrite(paddr[1] + 2, (UINT8)(value >> 56)); + break; + + case 4: + cpu_memorywrite_d(paddr[0], (UINT32)value); + cpu_memorywrite_d(paddr[1], (UINT32)(value >> 32)); + break; + + case 3: + cpu_memorywrite(paddr[0], (UINT8)value); + cpu_memorywrite_w(paddr[0] + 1, (UINT16)(value >> 8)); + cpu_memorywrite_d(paddr[1], (UINT32)(value >> 24)); + cpu_memorywrite(paddr[1] + 4, (UINT8)(value >> 56)); + break; + + case 2: + cpu_memorywrite_w(paddr[0], (UINT16)value); + cpu_memorywrite_d(paddr[1], (UINT32)(value >> 16)); + cpu_memorywrite_w(paddr[1] + 4, (UINT16)(value >> 48)); + break; + + case 1: + cpu_memorywrite(paddr[0], (UINT8)value); + cpu_memorywrite_d(paddr[1], (UINT32)(value >> 8)); + cpu_memorywrite_w(paddr[1] + 4, (UINT16)(value >> 40)); + cpu_memorywrite(paddr[1] + 6, (UINT8)(value >> 56)); + break; + + default: + ia32_panic("cpu_linear_memory_write_q: out of range (remain=%d)\n", remain); + break; + } +} + +void MEMCALL +cpu_linear_memory_write_f(UINT32 laddr, const REG80 *value, int ucrw) +{ + UINT32 paddr[2]; + UINT remain; + UINT i, j; + + paddr[0] = paging(laddr, ucrw); + remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); + if (remain >= sizeof(value)) { + cpu_memorywrite_f(paddr[0], value); + return; + } + + paddr[1] = paging(laddr + remain, ucrw); + for (i = 0; i < remain; ++i) { + cpu_memorywrite(paddr[0] + i, value->b[i]); + } + for (j = 0; i < 10; ++i, ++j) { + cpu_memorywrite(paddr[1] + j, value->b[i]); + } +} + +/* + * linear address memory access function + */ +void MEMCALL +cpu_memory_access_la_region(UINT32 laddr, UINT length, int ucrw, UINT8 *data) +{ + UINT32 paddr; + UINT remain; /* page remain */ + UINT r; + + while (length > 0) { + remain = CPU_PAGE_SIZE - (laddr & CPU_PAGE_MASK); + if (!CPU_STAT_PAGING) { + paddr = laddr; + } else { + paddr = paging(laddr, ucrw); + } + + r = (remain > length) ? length : remain; + if (!(ucrw & CPU_PAGE_WRITE)) { + cpu_memoryread_region(paddr, data, r); + } else { + cpu_memorywrite_region(paddr, data, r); + } + + laddr += r; + data += r; + length -= r; + } +} + +UINT32 MEMCALL +laddr2paddr(UINT32 laddr, int ucrw) +{ + + return paging(laddr, ucrw); +} + +/* + * paging + */ +static UINT32 MEMCALL +paging(UINT32 laddr, int ucrw) +{ + struct tlb_entry *ep; + UINT32 paddr; /* physical address */ + UINT32 pde_addr; /* page directory entry address */ + UINT32 pde; /* page directory entry */ + UINT32 pte_addr; /* page table entry address */ + UINT32 pte; /* page table entry */ + UINT bit; + UINT err; + +#if !defined(SUPPORT_IA32_HAXM) // HAXMはエミュレーションTLBを使わない + ep = tlb_lookup(laddr, ucrw); + if (ep != NULL) + return ep->paddr + (laddr & CPU_PAGE_MASK); +#endif + + pde_addr = CPU_STAT_PDE_BASE + ((laddr >> 20) & 0xffc); + pde = cpu_memoryread_d_paging(pde_addr); + if (!(pde & CPU_PDE_PRESENT)) { + VERBOSE(("paging: PTE page is not present")); + VERBOSE(("paging: CPU_CR3 = 0x%08x", CPU_CR3)); + VERBOSE(("paging: laddr = 0x%08x, pde_addr = 0x%08x, pde = 0x%08x", laddr, pde_addr, pde)); + err = 0; + goto pf_exception; + } + if (!(pde & CPU_PDE_ACCESS)) { + pde |= CPU_PDE_ACCESS; + cpu_memorywrite_d_paging(pde_addr, pde); + } + +#if defined(SUPPORT_IA32_HAXM) // HAXMは4MBページのことがある + if ((CPU_CR4 & CPU_CR4_PSE) && (pde & CPU_PDE_PAGE_SIZE)) { + /* 4MB page size */ + paddr = (pde & CPU_PDE_4M_BASEADDR_MASK) | (laddr & 0x003fffff); + + bit = ucrw & (CPU_PAGE_WRITE | CPU_PAGE_USER_MODE); + bit |= (pde & (CPU_PTE_WRITABLE | CPU_PTE_USER_MODE)); + bit |= CPU_STAT_WP; + } + else +#endif + { + /* 4KB page size */ + pte_addr = (pde & CPU_PDE_BASEADDR_MASK) + ((laddr >> 10) & 0xffc); + pte = cpu_memoryread_d_paging(pte_addr); + if (!(pte & CPU_PTE_PRESENT)) { + VERBOSE(("paging: page is not present")); + VERBOSE(("paging: laddr = 0x%08x, pde_addr = 0x%08x, pde = 0x%08x", laddr, pde_addr, pde)); + VERBOSE(("paging: pte_addr = 0x%08x, pte = 0x%08x", pte_addr, pte)); + err = 0; + goto pf_exception; + } + if (!(pte & CPU_PTE_ACCESS)) { + pte |= CPU_PTE_ACCESS; + cpu_memorywrite_d_paging(pte_addr, pte); + } + + /* make physical address */ + paddr = (pte & CPU_PTE_BASEADDR_MASK) + (laddr & CPU_PAGE_MASK); + + bit = ucrw & (CPU_PAGE_WRITE | CPU_PAGE_USER_MODE); + bit |= (pde & pte & (CPU_PTE_WRITABLE | CPU_PTE_USER_MODE)); + bit |= CPU_STAT_WP; + +#if !defined(USE_PAGE_ACCESS_TABLE) + if (!(page_access & (1 << bit))) +#else + if (!(page_access_bit[bit])) +#endif + { + VERBOSE(("paging: page access violation.")); + VERBOSE(("paging: laddr = 0x%08x, pde_addr = 0x%08x, pde = 0x%08x", laddr, pde_addr, pde)); + VERBOSE(("paging: pte_addr = 0x%08x, pte = 0x%08x", pte_addr, pte)); + VERBOSE(("paging: paddr = 0x%08x, bit = 0x%08x", paddr, bit)); + err = 1; + goto pf_exception; + } + + if ((ucrw & CPU_PAGE_WRITE) && !(pte & CPU_PTE_DIRTY)) { + pte |= CPU_PTE_DIRTY; + cpu_memorywrite_d_paging(pte_addr, pte); + } + + tlb_update(laddr, pte, (bit & (CPU_PTE_WRITABLE | CPU_PTE_USER_MODE)) + ((ucrw & CPU_PAGE_CODE) ? 1 : 0)); + } + + return paddr; + +pf_exception: + CPU_CR2 = laddr; + err |= (ucrw & CPU_PAGE_WRITE) << 1; + err |= (ucrw & CPU_PAGE_USER_MODE) >> 1; + EXCEPTION(PF_EXCEPTION, err); + return 0; /* compiler happy */ +} + +/* + * TLB + */ +#define TLB_TAG_SHIFT TLB_ENTRY_TAG_MAX_SHIFT +#define TLB_TAG_MASK (~((1 << TLB_TAG_SHIFT) - 1)) +#define TLB_GET_TAG_ADDR(ep) ((ep)->tag & TLB_TAG_MASK) +#define TLB_SET_TAG_ADDR(ep, addr) \ +do { \ + (ep)->tag &= ~TLB_TAG_MASK; \ + (ep)->tag |= (addr) & TLB_TAG_MASK; \ +} while (/*CONSTCOND(*/ 0) + +#define TLB_IS_VALID(ep) ((ep)->tag & TLB_ENTRY_TAG_VALID) +#define TLB_SET_VALID(ep) ((ep)->tag = TLB_ENTRY_TAG_VALID) +#define TLB_SET_INVALID(ep) ((ep)->tag = 0) + +#define TLB_IS_WRITABLE(ep) ((ep)->tag & CPU_PTE_WRITABLE) +#define TLB_IS_USERMODE(ep) ((ep)->tag & CPU_PTE_USER_MODE) +#define TLB_IS_DIRTY(ep) ((ep)->tag & TLB_ENTRY_TAG_DIRTY) +#if (CPU_FEATURES_ALL & CPU_FEATURE_PGE) == CPU_FEATURE_PGE +#define TLB_IS_GLOBAL(ep) ((ep)->tag & TLB_ENTRY_TAG_GLOBAL) +#else +#define TLB_IS_GLOBAL(ep) 0 +#endif + +#define TLB_SET_TAG_FLAGS(ep, entry, bit) \ +do { \ + (ep)->tag |= (entry) & (CPU_PTE_GLOBAL_PAGE|CPU_PTE_DIRTY); \ + (ep)->tag |= (bit) & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE); \ +} while (/*CONSTCOND*/ 0) + +#define NTLB 2 /* 0: DTLB, 1: ITLB */ +#define NENTRY (1 << 6) +#define TLB_ENTRY_SHIFT 12 +#define TLB_ENTRY_MASK (NENTRY - 1) + +typedef struct { + struct tlb_entry entry[NENTRY]; +} tlb_t; +static tlb_t tlb[NTLB]; + +void +tlb_init(void) +{ + memset(tlb, 0, sizeof(tlb)); +} + +void MEMCALL +tlb_flush() +{ + struct tlb_entry *ep; + int i; + int n; + + for (n = 0; n < NTLB; n++) { + for (i = 0; i < NENTRY ; i++) { + ep = &tlb[n].entry[i]; + if (TLB_IS_VALID(ep) && !TLB_IS_GLOBAL(ep)) { + TLB_SET_INVALID(ep); + } + } + } +} + +void MEMCALL +tlb_flush_all() +{ + tlb_init(); +} + +void MEMCALL +tlb_flush_page(UINT32 laddr) +{ + struct tlb_entry *ep; + int idx; + int n; + + idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; + + for (n = 0; n < NTLB; n++) { + ep = &tlb[n].entry[idx]; + if (TLB_IS_VALID(ep)) { + if ((laddr & TLB_TAG_MASK) == TLB_GET_TAG_ADDR(ep)) { + TLB_SET_INVALID(ep); + } + } + } +} + +struct tlb_entry * MEMCALL +tlb_lookup(UINT32 laddr, int ucrw) +{ + struct tlb_entry *ep; + UINT bit; + int idx; + int n; + + n = (ucrw & CPU_PAGE_CODE) ? 1 : 0; + idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; + ep = &tlb[n].entry[idx]; + + if (TLB_IS_VALID(ep)) { + if ((laddr & TLB_TAG_MASK) == TLB_GET_TAG_ADDR(ep)) { + bit = ucrw & (CPU_PAGE_WRITE|CPU_PAGE_USER_MODE); + bit |= ep->tag & (CPU_PTE_WRITABLE|CPU_PTE_USER_MODE); + bit |= CPU_STAT_WP; +#if !defined(USE_PAGE_ACCESS_TABLE) + if ((page_access & (1 << bit))) +#else + if (page_access_bit[bit]) +#endif + { + if (!(ucrw & CPU_PAGE_WRITE) || TLB_IS_DIRTY(ep)) { + return ep; + } + } + } + } + return NULL; +} + +static void MEMCALL +tlb_update(UINT32 laddr, UINT entry, int bit) +{ + struct tlb_entry *ep; + int idx; + int n; + + n = bit & 1; + idx = (laddr >> TLB_ENTRY_SHIFT) & TLB_ENTRY_MASK; + ep = &tlb[n].entry[idx]; + + TLB_SET_VALID(ep); + TLB_SET_TAG_ADDR(ep, laddr); + TLB_SET_TAG_FLAGS(ep, entry, bit); + ep->paddr = entry & CPU_PTE_BASEADDR_MASK; +} diff --git a/i386c/ia32/paging.h b/i386c/ia32/paging.h old mode 100755 new mode 100644 index 770cc831..ad469f39 --- a/i386c/ia32/paging.h +++ b/i386c/ia32/paging.h @@ -1,377 +1,377 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_PAGING_H__ -#define IA32_CPU_PAGING_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * ページ・ディレクトリ・エントリ (4K バイトページ使用時) - * - * 31 12 11 9 8 7 6 5 4 3 2 1 0 - * +----------------------------------------+------+-+--+-+-+---+---+---+---+-+ - * | ページ・テーブルのベース・アドレス |使用可|G|PS|-|A|PCD|PWT|U/S|R/W|P| - * +----------------------------------------+------+-+--+-+-+---+---+---+---+-+ - * | | | | | | | | | | - * 9-11: システム・プログラマが使用可能 --------+ | | | | | | | | | - * 8: グローバル・ページ(無視される) ------------+ | | | | | | | | - * 7: ページ・サイズ (0 = 4k バイトページ) ---------+ | | | | | | | - * 6: 予約 (-) ---------------------------------------+ | | | | | | - * 5: アクセス -----------------------------------------+ | | | | | - * 4: キャッシュ無効 --------------------------------------+ | | | | - * 3: ライトスルー --------------------------------------------+ | | | - * 2: ユーザ/スーパバイザ (0 = スーパバイザ) ---------------------+ | | - * 1: 読み取り/書き込み (0 = 読み取りのみ) ---------------------------+ | - * 0: ページ存在 ---------------------------------------------------------+ - */ -#define CPU_PDE_BASEADDR_MASK 0xfffff000 -#define CPU_PDE_GLOBAL_PAGE (1 << 8) -#define CPU_PDE_PAGE_SIZE (1 << 7) -#define CPU_PDE_DIRTY (1 << 6) -#define CPU_PDE_ACCESS (1 << 5) -#define CPU_PDE_CACHE_DISABLE (1 << 4) -#define CPU_PDE_WRITE_THROUGH (1 << 3) -#define CPU_PDE_USER_MODE (1 << 2) -#define CPU_PDE_WRITABLE (1 << 1) -#define CPU_PDE_PRESENT (1 << 0) - -/* - * ページ・ディレクトリ・エントリ (4M バイトページ使用時) - * - * 31 22 21 12 11 9 8 7 6 5 4 3 2 1 0 - * +----------------------------+-----------+------+-+--+-+-+---+---+---+---+-+ - * |ページテーブルの物理アドレス| 予約済み |使用可|G|PS|D|A|PCD|PWT|U/S|R/W|P| - * +----------------------------+-----------+------+-+--+-+-+---+---+---+---+-+ - * | | | | | | | | | | - * 9-11: システム・プログラマが使用可能 --------+ | | | | | | | | | - * 8: グローバル・ページ ------------------------+ | | | | | | | | - * 7: ページ・サイズ (1 = 4M バイトページ) ---------+ | | | | | | | - * 6: ダーティ ---------------------------------------+ | | | | | | - * 5: アクセス -----------------------------------------+ | | | | | - * 4: キャッシュ無効 --------------------------------------+ | | | | - * 3: ライトスルー --------------------------------------------+ | | | - * 2: ユーザ/スーパバイザ (0 = スーパバイザ) ---------------------+ | | - * 1: 読み取り/書き込み (0 = 読み取りのみ) ---------------------------+ | - * 0: ページ存在 ---------------------------------------------------------+ - */ -#define CPU_PDE_4M_BASEADDR_MASK 0xffc00000 -#define CPU_PDE_4M_GLOBAL_PAGE (1 << 8) -#define CPU_PDE_4M_PAGE_SIZE (1 << 7) -#define CPU_PDE_4M_DIRTY (1 << 6) -#define CPU_PDE_4M_ACCESS (1 << 5) -#define CPU_PDE_4M_CACHE_DISABLE (1 << 4) -#define CPU_PDE_4M_WRITE_THROUGH (1 << 3) -#define CPU_PDE_4M_USER_MODE (1 << 2) -#define CPU_PDE_4M_WRITABLE (1 << 1) -#define CPU_PDE_4M_PRESENT (1 << 0) - -/* - * ページ・テーブル・エントリ (4k バイト・ページ) - * - * 31 12 11 9 8 7 6 5 4 3 2 1 0 - * +----------------------------------------+------+-+-+-+-+---+---+---+---+-+ - * | ページのベース・アドレス |使用可|G|-|D|A|PCD|PWT|U/S|R/W|P| - * +----------------------------------------+------+-+-+-+-+---+---+---+---+-+ - * | | | | | | | | | | - * 9-11: システム・プログラマが使用可能 -------+ | | | | | | | | | - * 8: グローバル・ページ -----------------------+ | | | | | | | | - * 7: 予約 (-) -----------------------------------+ | | | | | | | - * 6: ダーティ -------------------------------------+ | | | | | | - * 5: アクセス ---------------------------------------+ | | | | | - * 4: キャッシュ無効 ------------------------------------+ | | | | - * 3: ライトスルー ------------------------------------------+ | | | - * 2: ユーザ/スーパバイザ (0 = スーパバイザ) -------------------+ | | - * 1: 読み取り/書き込み (0 = 読み取りのみ) -------------------------+ | - * 0: ページ存在 -------------------------------------------------------+ - */ -#define CPU_PTE_BASEADDR_MASK 0xfffff000 -#define CPU_PTE_GLOBAL_PAGE (1 << 8) -#define CPU_PTE_PAGE_SIZE (1 << 7) -#define CPU_PTE_DIRTY (1 << 6) -#define CPU_PTE_ACCESS (1 << 5) -#define CPU_PTE_CACHE_DISABLE (1 << 4) -#define CPU_PTE_WRITE_THROUGH (1 << 3) -#define CPU_PTE_USER_MODE (1 << 2) -#define CPU_PTE_WRITABLE (1 << 1) -#define CPU_PTE_PRESENT (1 << 0) - -#define CPU_PAGE_SIZE 0x1000 -#define CPU_PAGE_MASK (CPU_PAGE_SIZE - 1) - -/* ucrw */ -#define CPU_PAGE_WRITE (1 << 0) -#define CPU_PAGE_CODE (1 << 1) -#define CPU_PAGE_DATA (1 << 2) -#define CPU_PAGE_USER_MODE (1 << 3) /* == CPU_MODE_USER */ -#define CPU_PAGE_READ_CODE (CPU_PAGE_CODE) -#define CPU_PAGE_READ_DATA (CPU_PAGE_DATA) -#define CPU_PAGE_WRITE_DATA (CPU_PAGE_WRITE|CPU_PAGE_DATA) - -UINT8 MEMCALL cpu_memory_access_la_RMW_b(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); -UINT16 MEMCALL cpu_memory_access_la_RMW_w(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); -UINT32 MEMCALL cpu_memory_access_la_RMW_d(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); -UINT8 MEMCALL cpu_linear_memory_read_b(UINT32 laddr, int ucrw); -UINT16 MEMCALL cpu_linear_memory_read_w(UINT32 laddr, int ucrw); -UINT32 MEMCALL cpu_linear_memory_read_d(UINT32 laddr, int ucrw); -UINT64 MEMCALL cpu_linear_memory_read_q(UINT32 laddr, int ucrw); -PF_UINT8 MEMCALL cpu_linear_memory_read_b_codefetch(UINT32 laddr, int ucrw); -PF_UINT16 MEMCALL cpu_linear_memory_read_w_codefetch(UINT32 laddr, int ucrw); -PF_UINT32 MEMCALL cpu_linear_memory_read_d_codefetch(UINT32 laddr, int ucrw); -REG80 MEMCALL cpu_linear_memory_read_f(UINT32 laddr, int ucrw); -void MEMCALL cpu_linear_memory_write_b(UINT32 laddr, UINT8 value, int ucrw); -void MEMCALL cpu_linear_memory_write_w(UINT32 laddr, UINT16 value, int ucrw); -void MEMCALL cpu_linear_memory_write_d(UINT32 laddr, UINT32 value, int ucrw); -void MEMCALL cpu_linear_memory_write_q(UINT32 laddr, UINT64 value, int ucrw); -void MEMCALL cpu_linear_memory_write_f(UINT32 laddr, const REG80 *value, int ucrw); - -/* - * linear address memory access function with TLB - */ -/* RMW */ -STATIC_INLINE UINT8 MEMCALL -cpu_lmemory_RMW_b(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) -{ - UINT32 result; - UINT8 value; - - if (!CPU_STAT_PAGING) { - value = cpu_memoryread_b(laddr); - result = (*func)(value, arg); - cpu_memorywrite_b(laddr, (UINT8)result); - return value; - } - return cpu_memory_access_la_RMW_b(laddr, func, arg); -} - -STATIC_INLINE UINT16 MEMCALL -cpu_lmemory_RMW_w(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) -{ - UINT32 result; - UINT16 value; - - if (!CPU_STAT_PAGING) { - value = cpu_memoryread_w(laddr); - result = (*func)(value, arg); - cpu_memorywrite_w(laddr, (UINT16)result); - return value; - } - return cpu_memory_access_la_RMW_w(laddr, func, arg); -} - -STATIC_INLINE UINT32 MEMCALL -cpu_lmemory_RMW_d(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) -{ - UINT32 result; - UINT32 value; - - if (!CPU_STAT_PAGING) { - value = cpu_memoryread_d(laddr); - result = (*func)(value, arg); - cpu_memorywrite_d(laddr, result); - return value; - } - return cpu_memory_access_la_RMW_d(laddr, func, arg); -} - -/* read */ -STATIC_INLINE UINT8 MEMCALL -cpu_lmemoryread_b(UINT32 laddr, int ucrw) -{ - - if (!CPU_STAT_PAGING) - return cpu_memoryread_b(laddr); - return cpu_linear_memory_read_b(laddr, ucrw); -} -STATIC_INLINE PF_UINT8 MEMCALL -cpu_lmemoryread_b_codefetch(UINT32 laddr, int ucrw) -{ - - if (!CPU_STAT_PAGING) - return cpu_memoryread_b_codefetch(laddr); - return cpu_linear_memory_read_b_codefetch(laddr, ucrw); -} -#define cpu_lmemoryread(a,ucrw) cpu_lmemoryread_b((a),(ucrw)) -#define cpu_lmemoryread_codefetch(a,ucrw) cpu_lmemoryread_b_codefetch((a),(ucrw)) - -STATIC_INLINE UINT16 MEMCALL -cpu_lmemoryread_w(UINT32 laddr, int ucrw) -{ - - if (!CPU_STAT_PAGING) - return cpu_memoryread_w(laddr); - return cpu_linear_memory_read_w(laddr, ucrw); -} -STATIC_INLINE PF_UINT16 MEMCALL -cpu_lmemoryread_w_codefetch(UINT32 laddr, int ucrw) -{ - - if (!CPU_STAT_PAGING) - return cpu_memoryread_w_codefetch(laddr); - return cpu_linear_memory_read_w_codefetch(laddr, ucrw); -} - - -STATIC_INLINE UINT32 MEMCALL -cpu_lmemoryread_d(UINT32 laddr, int ucrw) -{ - - if (!CPU_STAT_PAGING) - return cpu_memoryread_d(laddr); - return cpu_linear_memory_read_d(laddr, ucrw); -} -STATIC_INLINE PF_UINT32 MEMCALL -cpu_lmemoryread_d_codefetch(UINT32 laddr, int ucrw) -{ - - if (!CPU_STAT_PAGING) - return cpu_memoryread_d_codefetch(laddr); - return cpu_linear_memory_read_d_codefetch(laddr, ucrw); -} - -STATIC_INLINE UINT64 -cpu_lmemoryread_q(UINT32 laddr, int ucrw) -{ - - if (!CPU_STAT_PAGING) - return cpu_memoryread_q(laddr); - return cpu_linear_memory_read_q(laddr, ucrw); -} - -STATIC_INLINE REG80 -cpu_lmemoryread_f(UINT32 laddr, int ucrw) -{ - - if (!CPU_STAT_PAGING) - return cpu_memoryread_f(laddr); - return cpu_linear_memory_read_f(laddr, ucrw); -} - -/* write */ -STATIC_INLINE void MEMCALL -cpu_lmemorywrite_b(UINT32 laddr, UINT8 value, int ucrw) -{ - - if (!CPU_STAT_PAGING) { - cpu_memorywrite_b(laddr, value); - return; - } - cpu_linear_memory_write_b(laddr, value, ucrw); -} -#define cpu_lmemorywrite(a,v,ucrw) cpu_lmemorywrite_b((a),(v),(ucrw)) - -STATIC_INLINE void MEMCALL -cpu_lmemorywrite_w(UINT32 laddr, UINT16 value, int ucrw) -{ - - if (!CPU_STAT_PAGING) { - cpu_memorywrite_w(laddr, value); - return; - } - cpu_linear_memory_write_w(laddr, value, ucrw); -} - -STATIC_INLINE void MEMCALL -cpu_lmemorywrite_d(UINT32 laddr, UINT32 value, int ucrw) -{ - - if (!CPU_STAT_PAGING) { - cpu_memorywrite_d(laddr, value); - return; - } - cpu_linear_memory_write_d(laddr, value, ucrw); -} - -STATIC_INLINE void MEMCALL -cpu_lmemorywrite_q(UINT32 laddr, UINT64 value, int ucrw) -{ - - if (!CPU_STAT_PAGING) { - cpu_memorywrite_q(laddr, value); - return; - } - cpu_linear_memory_write_q(laddr, value, ucrw); -} - -STATIC_INLINE void MEMCALL -cpu_lmemorywrite_f(UINT32 laddr, const REG80 *value, int ucrw) -{ - - if (!CPU_STAT_PAGING) { - cpu_memorywrite_f(laddr, value); - return; - } - cpu_linear_memory_write_f(laddr, value, ucrw); -} - - -/* - * linear address memory access with superviser mode - */ -#define cpu_kmemoryread(a) \ - cpu_lmemoryread((a),CPU_PAGE_READ_DATA|CPU_MODE_SUPERVISER) -#define cpu_kmemoryread_w(a) \ - cpu_lmemoryread_w((a),CPU_PAGE_READ_DATA|CPU_MODE_SUPERVISER) -#define cpu_kmemoryread_d(a) \ - cpu_lmemoryread_d((a),CPU_PAGE_READ_DATA|CPU_MODE_SUPERVISER) -#define cpu_kmemorywrite(a,v) \ - cpu_lmemorywrite((a),(v),CPU_PAGE_WRITE_DATA|CPU_MODE_SUPERVISER) -#define cpu_kmemorywrite_w(a,v) \ - cpu_lmemorywrite_w((a),(v),CPU_PAGE_WRITE_DATA|CPU_MODE_SUPERVISER) -#define cpu_kmemorywrite_d(a,v) \ - cpu_lmemorywrite_d((a),(v),CPU_PAGE_WRITE_DATA|CPU_MODE_SUPERVISER) - -/* - * linear address memory access function - */ -void MEMCALL cpu_memory_access_la_region(UINT32 address, UINT length, int ucrw, UINT8 *data); -UINT32 MEMCALL laddr2paddr(UINT32 laddr, int ucrw); - -STATIC_INLINE UINT32 MEMCALL -laddr_to_paddr(UINT32 laddr, int ucrw) -{ - - if (!CPU_STAT_PAGING) - return laddr; - return laddr2paddr(laddr, ucrw); -} - -/* - * TLB function - */ -struct tlb_entry; -void tlb_init(void); -void MEMCALL tlb_flush(); -void MEMCALL tlb_flush_all(); -void MEMCALL tlb_flush_page(UINT32 laddr); -struct tlb_entry *MEMCALL tlb_lookup(UINT32 laddr, int ucrw); - -#ifdef __cplusplus -} -#endif - -#endif /* !IA32_CPU_PAGING_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_PAGING_H__ +#define IA32_CPU_PAGING_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ページ・ディレクトリ・エントリ (4K バイトページ使用時) + * + * 31 12 11 9 8 7 6 5 4 3 2 1 0 + * +----------------------------------------+------+-+--+-+-+---+---+---+---+-+ + * | ページ・テーブルのベース・アドレス |使用可|G|PS|-|A|PCD|PWT|U/S|R/W|P| + * +----------------------------------------+------+-+--+-+-+---+---+---+---+-+ + * | | | | | | | | | | + * 9-11: システム・プログラマが使用可能 --------+ | | | | | | | | | + * 8: グローバル・ページ(無視される) ------------+ | | | | | | | | + * 7: ページ・サイズ (0 = 4k バイトページ) ---------+ | | | | | | | + * 6: 予約 (-) ---------------------------------------+ | | | | | | + * 5: アクセス -----------------------------------------+ | | | | | + * 4: キャッシュ無効 --------------------------------------+ | | | | + * 3: ライトスルー --------------------------------------------+ | | | + * 2: ユーザ/スーパバイザ (0 = スーパバイザ) ---------------------+ | | + * 1: 読み取り/書き込み (0 = 読み取りのみ) ---------------------------+ | + * 0: ページ存在 ---------------------------------------------------------+ + */ +#define CPU_PDE_BASEADDR_MASK 0xfffff000 +#define CPU_PDE_GLOBAL_PAGE (1 << 8) +#define CPU_PDE_PAGE_SIZE (1 << 7) +#define CPU_PDE_DIRTY (1 << 6) +#define CPU_PDE_ACCESS (1 << 5) +#define CPU_PDE_CACHE_DISABLE (1 << 4) +#define CPU_PDE_WRITE_THROUGH (1 << 3) +#define CPU_PDE_USER_MODE (1 << 2) +#define CPU_PDE_WRITABLE (1 << 1) +#define CPU_PDE_PRESENT (1 << 0) + +/* + * ページ・ディレクトリ・エントリ (4M バイトページ使用時) + * + * 31 22 21 12 11 9 8 7 6 5 4 3 2 1 0 + * +----------------------------+-----------+------+-+--+-+-+---+---+---+---+-+ + * |ページテーブルの物理アドレス| 予約済み |使用可|G|PS|D|A|PCD|PWT|U/S|R/W|P| + * +----------------------------+-----------+------+-+--+-+-+---+---+---+---+-+ + * | | | | | | | | | | + * 9-11: システム・プログラマが使用可能 --------+ | | | | | | | | | + * 8: グローバル・ページ ------------------------+ | | | | | | | | + * 7: ページ・サイズ (1 = 4M バイトページ) ---------+ | | | | | | | + * 6: ダーティ ---------------------------------------+ | | | | | | + * 5: アクセス -----------------------------------------+ | | | | | + * 4: キャッシュ無効 --------------------------------------+ | | | | + * 3: ライトスルー --------------------------------------------+ | | | + * 2: ユーザ/スーパバイザ (0 = スーパバイザ) ---------------------+ | | + * 1: 読み取り/書き込み (0 = 読み取りのみ) ---------------------------+ | + * 0: ページ存在 ---------------------------------------------------------+ + */ +#define CPU_PDE_4M_BASEADDR_MASK 0xffc00000 +#define CPU_PDE_4M_GLOBAL_PAGE (1 << 8) +#define CPU_PDE_4M_PAGE_SIZE (1 << 7) +#define CPU_PDE_4M_DIRTY (1 << 6) +#define CPU_PDE_4M_ACCESS (1 << 5) +#define CPU_PDE_4M_CACHE_DISABLE (1 << 4) +#define CPU_PDE_4M_WRITE_THROUGH (1 << 3) +#define CPU_PDE_4M_USER_MODE (1 << 2) +#define CPU_PDE_4M_WRITABLE (1 << 1) +#define CPU_PDE_4M_PRESENT (1 << 0) + +/* + * ページ・テーブル・エントリ (4k バイト・ページ) + * + * 31 12 11 9 8 7 6 5 4 3 2 1 0 + * +----------------------------------------+------+-+-+-+-+---+---+---+---+-+ + * | ページのベース・アドレス |使用可|G|-|D|A|PCD|PWT|U/S|R/W|P| + * +----------------------------------------+------+-+-+-+-+---+---+---+---+-+ + * | | | | | | | | | | + * 9-11: システム・プログラマが使用可能 -------+ | | | | | | | | | + * 8: グローバル・ページ -----------------------+ | | | | | | | | + * 7: 予約 (-) -----------------------------------+ | | | | | | | + * 6: ダーティ -------------------------------------+ | | | | | | + * 5: アクセス ---------------------------------------+ | | | | | + * 4: キャッシュ無効 ------------------------------------+ | | | | + * 3: ライトスルー ------------------------------------------+ | | | + * 2: ユーザ/スーパバイザ (0 = スーパバイザ) -------------------+ | | + * 1: 読み取り/書き込み (0 = 読み取りのみ) -------------------------+ | + * 0: ページ存在 -------------------------------------------------------+ + */ +#define CPU_PTE_BASEADDR_MASK 0xfffff000 +#define CPU_PTE_GLOBAL_PAGE (1 << 8) +#define CPU_PTE_PAGE_SIZE (1 << 7) +#define CPU_PTE_DIRTY (1 << 6) +#define CPU_PTE_ACCESS (1 << 5) +#define CPU_PTE_CACHE_DISABLE (1 << 4) +#define CPU_PTE_WRITE_THROUGH (1 << 3) +#define CPU_PTE_USER_MODE (1 << 2) +#define CPU_PTE_WRITABLE (1 << 1) +#define CPU_PTE_PRESENT (1 << 0) + +#define CPU_PAGE_SIZE 0x1000 +#define CPU_PAGE_MASK (CPU_PAGE_SIZE - 1) + +/* ucrw */ +#define CPU_PAGE_WRITE (1 << 0) +#define CPU_PAGE_CODE (1 << 1) +#define CPU_PAGE_DATA (1 << 2) +#define CPU_PAGE_USER_MODE (1 << 3) /* == CPU_MODE_USER */ +#define CPU_PAGE_READ_CODE (CPU_PAGE_CODE) +#define CPU_PAGE_READ_DATA (CPU_PAGE_DATA) +#define CPU_PAGE_WRITE_DATA (CPU_PAGE_WRITE|CPU_PAGE_DATA) + +UINT8 MEMCALL cpu_memory_access_la_RMW_b(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); +UINT16 MEMCALL cpu_memory_access_la_RMW_w(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); +UINT32 MEMCALL cpu_memory_access_la_RMW_d(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg); +UINT8 MEMCALL cpu_linear_memory_read_b(UINT32 laddr, int ucrw); +UINT16 MEMCALL cpu_linear_memory_read_w(UINT32 laddr, int ucrw); +UINT32 MEMCALL cpu_linear_memory_read_d(UINT32 laddr, int ucrw); +UINT64 MEMCALL cpu_linear_memory_read_q(UINT32 laddr, int ucrw); +PF_UINT8 MEMCALL cpu_linear_memory_read_b_codefetch(UINT32 laddr, int ucrw); +PF_UINT16 MEMCALL cpu_linear_memory_read_w_codefetch(UINT32 laddr, int ucrw); +PF_UINT32 MEMCALL cpu_linear_memory_read_d_codefetch(UINT32 laddr, int ucrw); +REG80 MEMCALL cpu_linear_memory_read_f(UINT32 laddr, int ucrw); +void MEMCALL cpu_linear_memory_write_b(UINT32 laddr, UINT8 value, int ucrw); +void MEMCALL cpu_linear_memory_write_w(UINT32 laddr, UINT16 value, int ucrw); +void MEMCALL cpu_linear_memory_write_d(UINT32 laddr, UINT32 value, int ucrw); +void MEMCALL cpu_linear_memory_write_q(UINT32 laddr, UINT64 value, int ucrw); +void MEMCALL cpu_linear_memory_write_f(UINT32 laddr, const REG80 *value, int ucrw); + +/* + * linear address memory access function with TLB + */ +/* RMW */ +STATIC_INLINE UINT8 MEMCALL +cpu_lmemory_RMW_b(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) +{ + UINT32 result; + UINT8 value; + + if (!CPU_STAT_PAGING) { + value = cpu_memoryread_b(laddr); + result = (*func)(value, arg); + cpu_memorywrite_b(laddr, (UINT8)result); + return value; + } + return cpu_memory_access_la_RMW_b(laddr, func, arg); +} + +STATIC_INLINE UINT16 MEMCALL +cpu_lmemory_RMW_w(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) +{ + UINT32 result; + UINT16 value; + + if (!CPU_STAT_PAGING) { + value = cpu_memoryread_w(laddr); + result = (*func)(value, arg); + cpu_memorywrite_w(laddr, (UINT16)result); + return value; + } + return cpu_memory_access_la_RMW_w(laddr, func, arg); +} + +STATIC_INLINE UINT32 MEMCALL +cpu_lmemory_RMW_d(UINT32 laddr, UINT32 (CPUCALL *func)(UINT32, void *), void *arg) +{ + UINT32 result; + UINT32 value; + + if (!CPU_STAT_PAGING) { + value = cpu_memoryread_d(laddr); + result = (*func)(value, arg); + cpu_memorywrite_d(laddr, result); + return value; + } + return cpu_memory_access_la_RMW_d(laddr, func, arg); +} + +/* read */ +STATIC_INLINE UINT8 MEMCALL +cpu_lmemoryread_b(UINT32 laddr, int ucrw) +{ + + if (!CPU_STAT_PAGING) + return cpu_memoryread_b(laddr); + return cpu_linear_memory_read_b(laddr, ucrw); +} +STATIC_INLINE PF_UINT8 MEMCALL +cpu_lmemoryread_b_codefetch(UINT32 laddr, int ucrw) +{ + + if (!CPU_STAT_PAGING) + return cpu_memoryread_b_codefetch(laddr); + return cpu_linear_memory_read_b_codefetch(laddr, ucrw); +} +#define cpu_lmemoryread(a,ucrw) cpu_lmemoryread_b((a),(ucrw)) +#define cpu_lmemoryread_codefetch(a,ucrw) cpu_lmemoryread_b_codefetch((a),(ucrw)) + +STATIC_INLINE UINT16 MEMCALL +cpu_lmemoryread_w(UINT32 laddr, int ucrw) +{ + + if (!CPU_STAT_PAGING) + return cpu_memoryread_w(laddr); + return cpu_linear_memory_read_w(laddr, ucrw); +} +STATIC_INLINE PF_UINT16 MEMCALL +cpu_lmemoryread_w_codefetch(UINT32 laddr, int ucrw) +{ + + if (!CPU_STAT_PAGING) + return cpu_memoryread_w_codefetch(laddr); + return cpu_linear_memory_read_w_codefetch(laddr, ucrw); +} + + +STATIC_INLINE UINT32 MEMCALL +cpu_lmemoryread_d(UINT32 laddr, int ucrw) +{ + + if (!CPU_STAT_PAGING) + return cpu_memoryread_d(laddr); + return cpu_linear_memory_read_d(laddr, ucrw); +} +STATIC_INLINE PF_UINT32 MEMCALL +cpu_lmemoryread_d_codefetch(UINT32 laddr, int ucrw) +{ + + if (!CPU_STAT_PAGING) + return cpu_memoryread_d_codefetch(laddr); + return cpu_linear_memory_read_d_codefetch(laddr, ucrw); +} + +STATIC_INLINE UINT64 +cpu_lmemoryread_q(UINT32 laddr, int ucrw) +{ + + if (!CPU_STAT_PAGING) + return cpu_memoryread_q(laddr); + return cpu_linear_memory_read_q(laddr, ucrw); +} + +STATIC_INLINE REG80 +cpu_lmemoryread_f(UINT32 laddr, int ucrw) +{ + + if (!CPU_STAT_PAGING) + return cpu_memoryread_f(laddr); + return cpu_linear_memory_read_f(laddr, ucrw); +} + +/* write */ +STATIC_INLINE void MEMCALL +cpu_lmemorywrite_b(UINT32 laddr, UINT8 value, int ucrw) +{ + + if (!CPU_STAT_PAGING) { + cpu_memorywrite_b(laddr, value); + return; + } + cpu_linear_memory_write_b(laddr, value, ucrw); +} +#define cpu_lmemorywrite(a,v,ucrw) cpu_lmemorywrite_b((a),(v),(ucrw)) + +STATIC_INLINE void MEMCALL +cpu_lmemorywrite_w(UINT32 laddr, UINT16 value, int ucrw) +{ + + if (!CPU_STAT_PAGING) { + cpu_memorywrite_w(laddr, value); + return; + } + cpu_linear_memory_write_w(laddr, value, ucrw); +} + +STATIC_INLINE void MEMCALL +cpu_lmemorywrite_d(UINT32 laddr, UINT32 value, int ucrw) +{ + + if (!CPU_STAT_PAGING) { + cpu_memorywrite_d(laddr, value); + return; + } + cpu_linear_memory_write_d(laddr, value, ucrw); +} + +STATIC_INLINE void MEMCALL +cpu_lmemorywrite_q(UINT32 laddr, UINT64 value, int ucrw) +{ + + if (!CPU_STAT_PAGING) { + cpu_memorywrite_q(laddr, value); + return; + } + cpu_linear_memory_write_q(laddr, value, ucrw); +} + +STATIC_INLINE void MEMCALL +cpu_lmemorywrite_f(UINT32 laddr, const REG80 *value, int ucrw) +{ + + if (!CPU_STAT_PAGING) { + cpu_memorywrite_f(laddr, value); + return; + } + cpu_linear_memory_write_f(laddr, value, ucrw); +} + + +/* + * linear address memory access with superviser mode + */ +#define cpu_kmemoryread(a) \ + cpu_lmemoryread((a),CPU_PAGE_READ_DATA|CPU_MODE_SUPERVISER) +#define cpu_kmemoryread_w(a) \ + cpu_lmemoryread_w((a),CPU_PAGE_READ_DATA|CPU_MODE_SUPERVISER) +#define cpu_kmemoryread_d(a) \ + cpu_lmemoryread_d((a),CPU_PAGE_READ_DATA|CPU_MODE_SUPERVISER) +#define cpu_kmemorywrite(a,v) \ + cpu_lmemorywrite((a),(v),CPU_PAGE_WRITE_DATA|CPU_MODE_SUPERVISER) +#define cpu_kmemorywrite_w(a,v) \ + cpu_lmemorywrite_w((a),(v),CPU_PAGE_WRITE_DATA|CPU_MODE_SUPERVISER) +#define cpu_kmemorywrite_d(a,v) \ + cpu_lmemorywrite_d((a),(v),CPU_PAGE_WRITE_DATA|CPU_MODE_SUPERVISER) + +/* + * linear address memory access function + */ +void MEMCALL cpu_memory_access_la_region(UINT32 address, UINT length, int ucrw, UINT8 *data); +UINT32 MEMCALL laddr2paddr(UINT32 laddr, int ucrw); + +STATIC_INLINE UINT32 MEMCALL +laddr_to_paddr(UINT32 laddr, int ucrw) +{ + + if (!CPU_STAT_PAGING) + return laddr; + return laddr2paddr(laddr, ucrw); +} + +/* + * TLB function + */ +struct tlb_entry; +void tlb_init(void); +void MEMCALL tlb_flush(); +void MEMCALL tlb_flush_all(); +void MEMCALL tlb_flush_page(UINT32 laddr); +struct tlb_entry *MEMCALL tlb_lookup(UINT32 laddr, int ucrw); + +#ifdef __cplusplus +} +#endif + +#endif /* !IA32_CPU_PAGING_H__ */ diff --git a/i386c/ia32/resolve.c b/i386c/ia32/resolve.c old mode 100755 new mode 100644 index ace5fea3..58e4c2ee --- a/i386c/ia32/resolve.c +++ b/i386c/ia32/resolve.c @@ -1,627 +1,627 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" -#include "ia32.mcr" - - -UINT32 (*calc_ea_dst_tbl[0x100])(void); -UINT32 (*calc_ea32_dst_tbl[0x100])(void); - - -/* - * common - */ -static UINT32 -ea_nop(void) -{ - - ia32_panic("ea_nop"); - return 0; -} - - -/* - * 16bit - */ - -/* - * ea_dest - */ -static UINT32 -ea_bx_si(void) -{ - - CPU_INST_SEGREG_INDEX = DS_FIX; - return (CPU_BX + CPU_SI); -} - -static UINT32 -ea_bx_si_disp8(void) -{ - UINT32 adrs; - - GET_PCBYTES(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return (adrs + CPU_BX + CPU_SI); -} - -static UINT32 -ea_bx_si_disp16(void) -{ - UINT32 adrs; - - GET_PCWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return (adrs + CPU_BX + CPU_SI); -} - -static UINT32 -ea_bx_di(void) -{ - - CPU_INST_SEGREG_INDEX = DS_FIX; - return (CPU_BX + CPU_DI); -} - -static UINT32 -ea_bx_di_disp8(void) -{ - UINT32 adrs; - - GET_PCBYTES(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return (adrs + CPU_BX + CPU_DI); -} - -static UINT32 -ea_bx_di_disp16(void) -{ - UINT32 adrs; - - GET_PCWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return (adrs + CPU_BX + CPU_DI); -} - -static UINT32 -ea_bp_si(void) -{ - - CPU_INST_SEGREG_INDEX = SS_FIX; - return (CPU_BP + CPU_SI); -} - -static UINT32 -ea_bp_si_disp8(void) -{ - UINT32 adrs; - - GET_PCBYTES(adrs); - CPU_INST_SEGREG_INDEX = SS_FIX; - return (adrs + CPU_BP + CPU_SI); -} - -static UINT32 -ea_bp_si_disp16(void) -{ - UINT32 adrs; - - GET_PCWORD(adrs); - CPU_INST_SEGREG_INDEX = SS_FIX; - return (adrs + CPU_BP + CPU_SI); -} - -static UINT32 -ea_bp_di(void) -{ - - CPU_INST_SEGREG_INDEX = SS_FIX; - return (CPU_BP + CPU_DI); -} - -static UINT32 -ea_bp_di_disp8(void) -{ - UINT32 adrs; - - GET_PCBYTES(adrs); - CPU_INST_SEGREG_INDEX = SS_FIX; - return (adrs + CPU_BP + CPU_DI); -} - -static UINT32 -ea_bp_di_disp16(void) -{ - UINT32 adrs; - - GET_PCWORD(adrs); - CPU_INST_SEGREG_INDEX = SS_FIX; - return (adrs + CPU_BP + CPU_DI); -} - -static UINT32 -ea_si(void) -{ - - CPU_INST_SEGREG_INDEX = DS_FIX; - return CPU_SI; -} - -static UINT32 -ea_si_disp8(void) -{ - UINT32 adrs; - - GET_PCBYTES(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return (adrs + CPU_SI); -} - -static UINT32 -ea_si_disp16(void) -{ - UINT32 adrs; - - GET_PCWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return (adrs + CPU_SI); -} - -static UINT32 -ea_di(void) -{ - - CPU_INST_SEGREG_INDEX = DS_FIX; - return CPU_DI; -} - -static UINT32 -ea_di_disp8(void) -{ - UINT32 adrs; - - GET_PCBYTES(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return (adrs + CPU_DI); -} - -static UINT32 -ea_di_disp16(void) -{ - UINT32 adrs; - - GET_PCWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return (adrs + CPU_DI); -} - -static UINT32 -ea_disp16(void) -{ - UINT32 adrs; - - GET_PCWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs; -} - -static UINT32 -ea_bp_disp8(void) -{ - UINT32 adrs; - - GET_PCBYTES(adrs); - CPU_INST_SEGREG_INDEX = SS_FIX; - return (adrs + CPU_BP); -} - -static UINT32 -ea_bp_disp16(void) -{ - UINT32 adrs; - - GET_PCWORD(adrs); - CPU_INST_SEGREG_INDEX = SS_FIX; - return (adrs + CPU_BP); -} - -static UINT32 -ea_bx(void) -{ - - CPU_INST_SEGREG_INDEX = DS_FIX; - return CPU_BX; -} - -static UINT32 -ea_bx_disp8(void) -{ - UINT32 adrs; - - GET_PCBYTES(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return (adrs + CPU_BX); -} - -static UINT32 -ea_bx_disp16(void) -{ - UINT32 adrs; - - GET_PCWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return (adrs + CPU_BX); -} - -static UINT32 (*c_ea_dst_tbl[])(void) = { - ea_bx_si, ea_bx_di, - ea_bp_si, ea_bp_di, - ea_si, ea_di, - ea_disp16, ea_bx, - ea_bx_si_disp8, ea_bx_di_disp8, - ea_bp_si_disp8, ea_bp_di_disp8, - ea_si_disp8, ea_di_disp8, - ea_bp_disp8, ea_bx_disp8, - ea_bx_si_disp16, ea_bx_di_disp16, - ea_bp_si_disp16, ea_bp_di_disp16, - ea_si_disp16, ea_di_disp16, - ea_bp_disp16, ea_bx_disp16, -}; - - -/* - * 32bit - */ -/* - * ea_dest 32 - */ -static UINT32 -ea32_eax(void) -{ - - CPU_INST_SEGREG_INDEX = DS_FIX; - return CPU_EAX; -} - -static UINT32 -ea32_ecx(void) -{ - - CPU_INST_SEGREG_INDEX = DS_FIX; - return CPU_ECX; -} - -static UINT32 -ea32_edx(void) -{ - - CPU_INST_SEGREG_INDEX = DS_FIX; - return CPU_EDX; -} - -static UINT32 -ea32_ebx(void) -{ - - CPU_INST_SEGREG_INDEX = DS_FIX; - return CPU_EBX; -} - -static UINT32 -ea32_sib(void) -{ - UINT32 dst; - UINT32 op; - UINT32 base, idx, scale; - - GET_PCBYTE(op); - base = op & 7; - idx = (op >> 3) & 7; - scale = (op >> 6) & 3; - - switch (base) { - case 0: case 1: case 2: case 3: case 6: case 7: - CPU_INST_SEGREG_INDEX = DS_FIX; - dst = CPU_REGS_DWORD(base); - break; - - case 4: - CPU_INST_SEGREG_INDEX = SS_FIX; - dst = CPU_ESP; - break; - - case 5: - CPU_INST_SEGREG_INDEX = DS_FIX; - GET_PCDWORD(dst); - break; - - default: - dst = 0; /* compiler happy */ - ia32_panic("ea32_sib: invalid base = %d", base); - break; - } - if (idx != 4) - dst += CPU_REGS_DWORD(idx) << scale; - return dst; -} - -static UINT32 -ea32_disp32(void) -{ - UINT32 adrs; - - GET_PCDWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs; -} - -static UINT32 -ea32_esi(void) -{ - - CPU_INST_SEGREG_INDEX = DS_FIX; - return CPU_ESI; -} - -static UINT32 -ea32_edi(void) -{ - - CPU_INST_SEGREG_INDEX = DS_FIX; - return CPU_EDI; -} - -static UINT32 -ea32_eax_disp8(void) -{ - SINT32 adrs; - - GET_PCBYTESD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_EAX; -} - -static UINT32 -ea32_ecx_disp8(void) -{ - SINT32 adrs; - - GET_PCBYTESD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_ECX; -} - -static UINT32 -ea32_edx_disp8(void) -{ - SINT32 adrs; - - GET_PCBYTESD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_EDX; -} - -static UINT32 -ea32_ebx_disp8(void) -{ - SINT32 adrs; - - GET_PCBYTESD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_EBX; -} - -static UINT32 -ea32_sib_disp8(void) -{ - SINT32 adrs; - UINT32 op; - UINT32 base, idx, scale; - - GET_PCBYTE(op); - base = op & 7; - idx = (op >> 3) & 7; - scale = (op >> 6) & 3; - - GET_PCBYTESD(adrs); - - switch (base) { - case 0: case 1: case 2: case 3: case 6: case 7: - CPU_INST_SEGREG_INDEX = DS_FIX; - break; - - case 4: case 5: - CPU_INST_SEGREG_INDEX = SS_FIX; - break; - } - if (idx != 4) - adrs += CPU_REGS_DWORD(idx) << scale; - return CPU_REGS_DWORD(base) + adrs; -} - -static UINT32 -ea32_ebp_disp8(void) -{ - SINT32 adrs; - - GET_PCBYTESD(adrs); - CPU_INST_SEGREG_INDEX = SS_FIX; - return adrs + CPU_EBP; -} - -static UINT32 -ea32_esi_disp8(void) -{ - SINT32 adrs; - - GET_PCBYTESD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_ESI; -} - -static UINT32 -ea32_edi_disp8(void) -{ - SINT32 adrs; - - GET_PCBYTESD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_EDI; -} - -static UINT32 -ea32_eax_disp32(void) -{ - UINT32 adrs; - - GET_PCDWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_EAX; -} - -static UINT32 -ea32_ecx_disp32(void) -{ - UINT32 adrs; - - GET_PCDWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_ECX; -} - -static UINT32 -ea32_edx_disp32(void) -{ - UINT32 adrs; - - GET_PCDWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_EDX; -} - -static UINT32 -ea32_ebx_disp32(void) -{ - UINT32 adrs; - - GET_PCDWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_EBX; -} - -static UINT32 -ea32_sib_disp32(void) -{ - UINT32 adrs; - UINT32 op; - UINT32 base, idx, scale; - - GET_PCBYTE(op); - base = op & 7; - idx = (op >> 3) & 7; - scale = (op >> 6) & 3; - - GET_PCDWORD(adrs); - - switch (base) { - case 0: case 1: case 2: case 3: case 6: case 7: - CPU_INST_SEGREG_INDEX = DS_FIX; - break; - - case 4: case 5: - CPU_INST_SEGREG_INDEX = SS_FIX; - break; - } - if (idx != 4) - adrs += CPU_REGS_DWORD(idx) << scale; - return CPU_REGS_DWORD(base) + adrs; -} - -static UINT32 -ea32_ebp_disp32(void) -{ - UINT32 adrs; - - GET_PCDWORD(adrs); - CPU_INST_SEGREG_INDEX = SS_FIX; - return adrs + CPU_EBP; -} - -static UINT32 -ea32_esi_disp32(void) -{ - UINT32 adrs; - - GET_PCDWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_ESI; -} - -static UINT32 -ea32_edi_disp32(void) -{ - UINT32 adrs; - - GET_PCDWORD(adrs); - CPU_INST_SEGREG_INDEX = DS_FIX; - return adrs + CPU_EDI; -} - -static UINT32 (*c_ea32_dst_tbl[])(void) = { - ea32_eax, ea32_ecx, - ea32_edx, ea32_ebx, - ea32_sib, ea32_disp32, - ea32_esi, ea32_edi, - ea32_eax_disp8, ea32_ecx_disp8, - ea32_edx_disp8, ea32_ebx_disp8, - ea32_sib_disp8, ea32_ebp_disp8, - ea32_esi_disp8, ea32_edi_disp8, - ea32_eax_disp32, ea32_ecx_disp32, - ea32_edx_disp32, ea32_ebx_disp32, - ea32_sib_disp32, ea32_ebp_disp32, - ea32_esi_disp32, ea32_edi_disp32, -}; - - -/* - * init table - */ -void -resolve_init(void) -{ - int i, pos; - - for (i = 0; i < 0xc0; ++i) { - pos = ((i >> 3) & 0x18) + (i & 0x07); - calc_ea_dst_tbl[i] = c_ea_dst_tbl[pos]; - calc_ea32_dst_tbl[i] = c_ea32_dst_tbl[pos]; - } - for (; i < 0x100; ++i) { - calc_ea_dst_tbl[i] = ea_nop; - calc_ea32_dst_tbl[i] = ea_nop; - } -} +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" +#include "ia32.mcr" + + +UINT32 (*calc_ea_dst_tbl[0x100])(void); +UINT32 (*calc_ea32_dst_tbl[0x100])(void); + + +/* + * common + */ +static UINT32 +ea_nop(void) +{ + + ia32_panic("ea_nop"); + return 0; +} + + +/* + * 16bit + */ + +/* + * ea_dest + */ +static UINT32 +ea_bx_si(void) +{ + + CPU_INST_SEGREG_INDEX = DS_FIX; + return (CPU_BX + CPU_SI); +} + +static UINT32 +ea_bx_si_disp8(void) +{ + UINT32 adrs; + + GET_PCBYTES(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return (adrs + CPU_BX + CPU_SI); +} + +static UINT32 +ea_bx_si_disp16(void) +{ + UINT32 adrs; + + GET_PCWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return (adrs + CPU_BX + CPU_SI); +} + +static UINT32 +ea_bx_di(void) +{ + + CPU_INST_SEGREG_INDEX = DS_FIX; + return (CPU_BX + CPU_DI); +} + +static UINT32 +ea_bx_di_disp8(void) +{ + UINT32 adrs; + + GET_PCBYTES(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return (adrs + CPU_BX + CPU_DI); +} + +static UINT32 +ea_bx_di_disp16(void) +{ + UINT32 adrs; + + GET_PCWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return (adrs + CPU_BX + CPU_DI); +} + +static UINT32 +ea_bp_si(void) +{ + + CPU_INST_SEGREG_INDEX = SS_FIX; + return (CPU_BP + CPU_SI); +} + +static UINT32 +ea_bp_si_disp8(void) +{ + UINT32 adrs; + + GET_PCBYTES(adrs); + CPU_INST_SEGREG_INDEX = SS_FIX; + return (adrs + CPU_BP + CPU_SI); +} + +static UINT32 +ea_bp_si_disp16(void) +{ + UINT32 adrs; + + GET_PCWORD(adrs); + CPU_INST_SEGREG_INDEX = SS_FIX; + return (adrs + CPU_BP + CPU_SI); +} + +static UINT32 +ea_bp_di(void) +{ + + CPU_INST_SEGREG_INDEX = SS_FIX; + return (CPU_BP + CPU_DI); +} + +static UINT32 +ea_bp_di_disp8(void) +{ + UINT32 adrs; + + GET_PCBYTES(adrs); + CPU_INST_SEGREG_INDEX = SS_FIX; + return (adrs + CPU_BP + CPU_DI); +} + +static UINT32 +ea_bp_di_disp16(void) +{ + UINT32 adrs; + + GET_PCWORD(adrs); + CPU_INST_SEGREG_INDEX = SS_FIX; + return (adrs + CPU_BP + CPU_DI); +} + +static UINT32 +ea_si(void) +{ + + CPU_INST_SEGREG_INDEX = DS_FIX; + return CPU_SI; +} + +static UINT32 +ea_si_disp8(void) +{ + UINT32 adrs; + + GET_PCBYTES(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return (adrs + CPU_SI); +} + +static UINT32 +ea_si_disp16(void) +{ + UINT32 adrs; + + GET_PCWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return (adrs + CPU_SI); +} + +static UINT32 +ea_di(void) +{ + + CPU_INST_SEGREG_INDEX = DS_FIX; + return CPU_DI; +} + +static UINT32 +ea_di_disp8(void) +{ + UINT32 adrs; + + GET_PCBYTES(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return (adrs + CPU_DI); +} + +static UINT32 +ea_di_disp16(void) +{ + UINT32 adrs; + + GET_PCWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return (adrs + CPU_DI); +} + +static UINT32 +ea_disp16(void) +{ + UINT32 adrs; + + GET_PCWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs; +} + +static UINT32 +ea_bp_disp8(void) +{ + UINT32 adrs; + + GET_PCBYTES(adrs); + CPU_INST_SEGREG_INDEX = SS_FIX; + return (adrs + CPU_BP); +} + +static UINT32 +ea_bp_disp16(void) +{ + UINT32 adrs; + + GET_PCWORD(adrs); + CPU_INST_SEGREG_INDEX = SS_FIX; + return (adrs + CPU_BP); +} + +static UINT32 +ea_bx(void) +{ + + CPU_INST_SEGREG_INDEX = DS_FIX; + return CPU_BX; +} + +static UINT32 +ea_bx_disp8(void) +{ + UINT32 adrs; + + GET_PCBYTES(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return (adrs + CPU_BX); +} + +static UINT32 +ea_bx_disp16(void) +{ + UINT32 adrs; + + GET_PCWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return (adrs + CPU_BX); +} + +static UINT32 (*c_ea_dst_tbl[])(void) = { + ea_bx_si, ea_bx_di, + ea_bp_si, ea_bp_di, + ea_si, ea_di, + ea_disp16, ea_bx, + ea_bx_si_disp8, ea_bx_di_disp8, + ea_bp_si_disp8, ea_bp_di_disp8, + ea_si_disp8, ea_di_disp8, + ea_bp_disp8, ea_bx_disp8, + ea_bx_si_disp16, ea_bx_di_disp16, + ea_bp_si_disp16, ea_bp_di_disp16, + ea_si_disp16, ea_di_disp16, + ea_bp_disp16, ea_bx_disp16, +}; + + +/* + * 32bit + */ +/* + * ea_dest 32 + */ +static UINT32 +ea32_eax(void) +{ + + CPU_INST_SEGREG_INDEX = DS_FIX; + return CPU_EAX; +} + +static UINT32 +ea32_ecx(void) +{ + + CPU_INST_SEGREG_INDEX = DS_FIX; + return CPU_ECX; +} + +static UINT32 +ea32_edx(void) +{ + + CPU_INST_SEGREG_INDEX = DS_FIX; + return CPU_EDX; +} + +static UINT32 +ea32_ebx(void) +{ + + CPU_INST_SEGREG_INDEX = DS_FIX; + return CPU_EBX; +} + +static UINT32 +ea32_sib(void) +{ + UINT32 dst; + UINT32 op; + UINT32 base, idx, scale; + + GET_PCBYTE(op); + base = op & 7; + idx = (op >> 3) & 7; + scale = (op >> 6) & 3; + + switch (base) { + case 0: case 1: case 2: case 3: case 6: case 7: + CPU_INST_SEGREG_INDEX = DS_FIX; + dst = CPU_REGS_DWORD(base); + break; + + case 4: + CPU_INST_SEGREG_INDEX = SS_FIX; + dst = CPU_ESP; + break; + + case 5: + CPU_INST_SEGREG_INDEX = DS_FIX; + GET_PCDWORD(dst); + break; + + default: + dst = 0; /* compiler happy */ + ia32_panic("ea32_sib: invalid base = %d", base); + break; + } + if (idx != 4) + dst += CPU_REGS_DWORD(idx) << scale; + return dst; +} + +static UINT32 +ea32_disp32(void) +{ + UINT32 adrs; + + GET_PCDWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs; +} + +static UINT32 +ea32_esi(void) +{ + + CPU_INST_SEGREG_INDEX = DS_FIX; + return CPU_ESI; +} + +static UINT32 +ea32_edi(void) +{ + + CPU_INST_SEGREG_INDEX = DS_FIX; + return CPU_EDI; +} + +static UINT32 +ea32_eax_disp8(void) +{ + SINT32 adrs; + + GET_PCBYTESD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_EAX; +} + +static UINT32 +ea32_ecx_disp8(void) +{ + SINT32 adrs; + + GET_PCBYTESD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_ECX; +} + +static UINT32 +ea32_edx_disp8(void) +{ + SINT32 adrs; + + GET_PCBYTESD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_EDX; +} + +static UINT32 +ea32_ebx_disp8(void) +{ + SINT32 adrs; + + GET_PCBYTESD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_EBX; +} + +static UINT32 +ea32_sib_disp8(void) +{ + SINT32 adrs; + UINT32 op; + UINT32 base, idx, scale; + + GET_PCBYTE(op); + base = op & 7; + idx = (op >> 3) & 7; + scale = (op >> 6) & 3; + + GET_PCBYTESD(adrs); + + switch (base) { + case 0: case 1: case 2: case 3: case 6: case 7: + CPU_INST_SEGREG_INDEX = DS_FIX; + break; + + case 4: case 5: + CPU_INST_SEGREG_INDEX = SS_FIX; + break; + } + if (idx != 4) + adrs += CPU_REGS_DWORD(idx) << scale; + return CPU_REGS_DWORD(base) + adrs; +} + +static UINT32 +ea32_ebp_disp8(void) +{ + SINT32 adrs; + + GET_PCBYTESD(adrs); + CPU_INST_SEGREG_INDEX = SS_FIX; + return adrs + CPU_EBP; +} + +static UINT32 +ea32_esi_disp8(void) +{ + SINT32 adrs; + + GET_PCBYTESD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_ESI; +} + +static UINT32 +ea32_edi_disp8(void) +{ + SINT32 adrs; + + GET_PCBYTESD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_EDI; +} + +static UINT32 +ea32_eax_disp32(void) +{ + UINT32 adrs; + + GET_PCDWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_EAX; +} + +static UINT32 +ea32_ecx_disp32(void) +{ + UINT32 adrs; + + GET_PCDWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_ECX; +} + +static UINT32 +ea32_edx_disp32(void) +{ + UINT32 adrs; + + GET_PCDWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_EDX; +} + +static UINT32 +ea32_ebx_disp32(void) +{ + UINT32 adrs; + + GET_PCDWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_EBX; +} + +static UINT32 +ea32_sib_disp32(void) +{ + UINT32 adrs; + UINT32 op; + UINT32 base, idx, scale; + + GET_PCBYTE(op); + base = op & 7; + idx = (op >> 3) & 7; + scale = (op >> 6) & 3; + + GET_PCDWORD(adrs); + + switch (base) { + case 0: case 1: case 2: case 3: case 6: case 7: + CPU_INST_SEGREG_INDEX = DS_FIX; + break; + + case 4: case 5: + CPU_INST_SEGREG_INDEX = SS_FIX; + break; + } + if (idx != 4) + adrs += CPU_REGS_DWORD(idx) << scale; + return CPU_REGS_DWORD(base) + adrs; +} + +static UINT32 +ea32_ebp_disp32(void) +{ + UINT32 adrs; + + GET_PCDWORD(adrs); + CPU_INST_SEGREG_INDEX = SS_FIX; + return adrs + CPU_EBP; +} + +static UINT32 +ea32_esi_disp32(void) +{ + UINT32 adrs; + + GET_PCDWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_ESI; +} + +static UINT32 +ea32_edi_disp32(void) +{ + UINT32 adrs; + + GET_PCDWORD(adrs); + CPU_INST_SEGREG_INDEX = DS_FIX; + return adrs + CPU_EDI; +} + +static UINT32 (*c_ea32_dst_tbl[])(void) = { + ea32_eax, ea32_ecx, + ea32_edx, ea32_ebx, + ea32_sib, ea32_disp32, + ea32_esi, ea32_edi, + ea32_eax_disp8, ea32_ecx_disp8, + ea32_edx_disp8, ea32_ebx_disp8, + ea32_sib_disp8, ea32_ebp_disp8, + ea32_esi_disp8, ea32_edi_disp8, + ea32_eax_disp32, ea32_ecx_disp32, + ea32_edx_disp32, ea32_ebx_disp32, + ea32_sib_disp32, ea32_ebp_disp32, + ea32_esi_disp32, ea32_edi_disp32, +}; + + +/* + * init table + */ +void +resolve_init(void) +{ + int i, pos; + + for (i = 0; i < 0xc0; ++i) { + pos = ((i >> 3) & 0x18) + (i & 0x07); + calc_ea_dst_tbl[i] = c_ea_dst_tbl[pos]; + calc_ea32_dst_tbl[i] = c_ea32_dst_tbl[pos]; + } + for (; i < 0x100; ++i) { + calc_ea_dst_tbl[i] = ea_nop; + calc_ea32_dst_tbl[i] = ea_nop; + } +} diff --git a/i386c/ia32/resolve.h b/i386c/ia32/resolve.h old mode 100755 new mode 100644 index fe9e9e6d..46154059 --- a/i386c/ia32/resolve.h +++ b/i386c/ia32/resolve.h @@ -1,52 +1,52 @@ -/* - * Copyright (c) 2002-2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_RESOLVE_H__ -#define IA32_CPU_RESOLVE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -void resolve_init(void); - -STATIC_INLINE UINT32 CPUCALL -calc_ea_dst(UINT32 op) -{ - extern UINT32 (*calc_ea_dst_tbl[0x100])(void); - extern UINT32 (*calc_ea32_dst_tbl[0x100])(void); - - __ASSERT(op < 0x100); - - if (!CPU_INST_AS32) - return ((*calc_ea_dst_tbl[op])() & 0xffff); - return (*calc_ea32_dst_tbl[op])(); -} - -#ifdef __cplusplus -} -#endif - -#endif /* IA32_CPU_RESOLVE_H__ */ +/* + * Copyright (c) 2002-2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_RESOLVE_H__ +#define IA32_CPU_RESOLVE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void resolve_init(void); + +STATIC_INLINE UINT32 CPUCALL +calc_ea_dst(UINT32 op) +{ + extern UINT32 (*calc_ea_dst_tbl[0x100])(void); + extern UINT32 (*calc_ea32_dst_tbl[0x100])(void); + + __ASSERT(op < 0x100); + + if (!CPU_INST_AS32) + return ((*calc_ea_dst_tbl[op])() & 0xffff); + return (*calc_ea32_dst_tbl[op])(); +} + +#ifdef __cplusplus +} +#endif + +#endif /* IA32_CPU_RESOLVE_H__ */ diff --git a/i386c/ia32/segments.c b/i386c/ia32/segments.c old mode 100755 new mode 100644 index 3ad5189a..a6e2a125 --- a/i386c/ia32/segments.c +++ b/i386c/ia32/segments.c @@ -1,416 +1,416 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" -#include "ia32.mcr" - -static void CPUCALL segdesc_set_default(int, UINT16, descriptor_t *); - -void CPUCALL -load_segreg(int idx, UINT16 selector, UINT16 *sregp, descriptor_t *sdp, int exc) -{ - selector_t sel; - int rv; - - __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); - __ASSERT((sregp != NULL)); - __ASSERT((sdp != NULL)); - - if (!CPU_STAT_PM || CPU_STAT_VM86) { - /* real-mode or vm86 mode */ - *sregp = selector; - segdesc_set_default(idx, selector, &sel.desc); - *sdp = sel.desc; - return; - } - - VERBOSE(("load_segreg: EIP = %04x:%08x, idx = %d, selector = %04x, sregp = %p, dp = %p, exc = %d", CPU_CS, CPU_PREV_EIP, idx, selector, sregp, sdp, exc)); - - /* - * protected mode - */ - if (idx == CPU_CS_INDEX) { - ia32_panic("load_segreg: CS"); - } - - rv = parse_selector(&sel, selector); - if (rv < 0) { - if ((rv != -2) || (idx == CPU_SS_INDEX)) { - EXCEPTION(exc, sel.idx); - } - /* null selector */ - *sregp = sel.selector; - memset(sdp, 0, sizeof(*sdp)); - return; - } - - switch (idx) { - case CPU_SS_INDEX: - if ((CPU_STAT_CPL != sel.rpl) - || (CPU_STAT_CPL != sel.desc.dpl) - || SEG_IS_SYSTEM(&sel.desc) - || SEG_IS_CODE(&sel.desc) - || !SEG_IS_WRITABLE_DATA(&sel.desc)) { - EXCEPTION(exc, sel.idx); - } - - /* not present */ - rv = selector_is_not_present(&sel); - if (rv < 0) { - EXCEPTION(SS_EXCEPTION, sel.idx); - } - - load_ss(sel.selector, &sel.desc, CPU_STAT_CPL); - break; - - case CPU_ES_INDEX: - case CPU_DS_INDEX: - case CPU_FS_INDEX: - case CPU_GS_INDEX: - if (SEG_IS_SYSTEM(&sel.desc) - || (SEG_IS_CODE(&sel.desc) && !SEG_IS_READABLE_CODE(&sel.desc))) { - EXCEPTION(exc, sel.idx); - } - if (SEG_IS_DATA(&sel.desc) - || !SEG_IS_CONFORMING_CODE(&sel.desc)) { - /* check privilege level */ - if ((sel.rpl > sel.desc.dpl) - || (CPU_STAT_CPL > sel.desc.dpl)) { - EXCEPTION(exc, sel.idx); - } - } - - /* not present */ - rv = selector_is_not_present(&sel); - if (rv < 0) { - EXCEPTION(NP_EXCEPTION, sel.idx); - } - - *sregp = sel.selector; - *sdp = sel.desc; - break; - - default: - ia32_panic("load_segreg(): segment register index is invalid"); - break; - } -} - -/* - * load SS register - */ -void CPUCALL -load_ss(UINT16 selector, const descriptor_t *sdp, int cpl) -{ - - CPU_STAT_SS32 = sdp->d; - CPU_SS = (UINT16)((selector & ~3) | (cpl & 3)); - CPU_SS_DESC = *sdp; -} - -/* - * load CS register - */ -void CPUCALL -load_cs(UINT16 selector, const descriptor_t *sdp, int new_cpl) -{ - int cpl = new_cpl & 3; - - CPU_INST_OP32 = CPU_INST_AS32 = - CPU_STATSAVE.cpu_inst_default.op_32 = - CPU_STATSAVE.cpu_inst_default.as_32 = sdp->d; -#if defined(USE_CPU_EIPMASK) - CPU_EIPMASK = CPU_STATSAVE.cpu_inst_default.op_32 ? 0xffffffff : 0xffff; -#endif - CPU_CS = (UINT16)((selector & ~3) | cpl); - CPU_CS_DESC = *sdp; - set_cpl(cpl); -} - -/* - * load LDT register - */ -void CPUCALL -load_ldtr(UINT16 selector, int exc) -{ - selector_t sel; - int rv; - - memset(&sel, 0, sizeof(sel)); - - rv = parse_selector(&sel, selector); - if (rv < 0 || sel.ldt) { - if (rv == -2) { - /* null segment */ - VERBOSE(("load_ldtr: null segment")); - CPU_LDTR = 0; - memset(&CPU_LDTR_DESC, 0, sizeof(CPU_LDTR_DESC)); - return; - } - EXCEPTION(exc, sel.selector); - } - - /* check descriptor type */ - if (!SEG_IS_SYSTEM(&sel.desc) - || (sel.desc.type != CPU_SYSDESC_TYPE_LDT)) { - EXCEPTION(exc, sel.selector); - } - - /* not present */ - rv = selector_is_not_present(&sel); - if (rv < 0) { - EXCEPTION((exc == TS_EXCEPTION) ? TS_EXCEPTION : NP_EXCEPTION, sel.selector); - } - -#if defined(MORE_DEBUG) - ldtr_dump(sel.desc.u.seg.segbase, sel.desc.u.seg.limit); -#endif - - CPU_LDTR = sel.selector; - CPU_LDTR_DESC = sel.desc; -} - -void CPUCALL -load_descriptor(descriptor_t *sdp, UINT32 addr) -{ - UINT32 l, h; - - __ASSERT(sdp != NULL); - - VERBOSE(("load_descriptor: address = 0x%08x", addr)); - - l = cpu_kmemoryread_d(addr); - h = cpu_kmemoryread_d(addr + 4); - VERBOSE(("descriptor value = 0x%08x%08x", h, l)); - - memset(sdp, 0, sizeof(*sdp)); - sdp->flag = 0; - - sdp->p = (h & CPU_DESC_H_P) ? 1 : 0; - sdp->type = (UINT8)((h & CPU_DESC_H_TYPE) >> CPU_DESC_H_TYPE_SHIFT); - sdp->dpl = (UINT8)((h & CPU_DESC_H_DPL) >> CPU_DESC_H_DPL_SHIFT); - sdp->s = (h & CPU_DESC_H_S) ? 1 : 0; - - if (!SEG_IS_SYSTEM(sdp)) { - /* code/data */ - sdp->valid = 1; - sdp->d = (h & CPU_SEGDESC_H_D) ? 1 : 0; - - sdp->u.seg.c = (h & CPU_SEGDESC_H_D_C) ? 1 : 0; - sdp->u.seg.g = (h & CPU_SEGDESC_H_G) ? 1 : 0; - sdp->u.seg.wr = (sdp->type & CPU_SEGDESC_TYPE_WR) ? 1 : 0; - sdp->u.seg.ec = (sdp->type & CPU_SEGDESC_TYPE_EC) ? 1 : 0; - - sdp->u.seg.segbase = (l >> 16) & 0xffff; - sdp->u.seg.segbase |= (h & 0xff) << 16; - sdp->u.seg.segbase |= h & 0xff000000; - sdp->u.seg.limit = (h & 0xf0000) | (l & 0xffff); - if (sdp->u.seg.g) { - sdp->u.seg.limit <<= 12; - if (SEG_IS_CODE(sdp) || !SEG_IS_EXPANDDOWN_DATA(sdp)) { - /* expand-up segment */ - sdp->u.seg.limit |= 0xfff; - } - } - } else { - /* system */ - switch (sdp->type) { - case CPU_SYSDESC_TYPE_LDT: /* LDT */ - sdp->valid = 1; - sdp->u.seg.g = (h & CPU_SEGDESC_H_G) ? 1 : 0; - - sdp->u.seg.segbase = h & 0xff000000; - sdp->u.seg.segbase |= (h & 0xff) << 16; - sdp->u.seg.segbase |= l >> 16; - sdp->u.seg.limit = h & 0xf0000; - sdp->u.seg.limit |= l & 0xffff; - if (sdp->u.seg.g) { - sdp->u.seg.limit <<= 12; - sdp->u.seg.limit |= 0xfff; - } - break; - - case CPU_SYSDESC_TYPE_TASK: /* task gate */ - sdp->valid = 1; - sdp->u.gate.selector = (UINT16)(l >> 16); - break; - - case CPU_SYSDESC_TYPE_TSS_16: /* 286 TSS */ - case CPU_SYSDESC_TYPE_TSS_BUSY_16: /* 286 TSS Busy */ - case CPU_SYSDESC_TYPE_TSS_32: /* 386 TSS */ - case CPU_SYSDESC_TYPE_TSS_BUSY_32: /* 386 TSS Busy */ - sdp->valid = 1; - sdp->d = (h & CPU_GATEDESC_H_D) ? 1 : 0; - sdp->u.seg.g = (h & CPU_SEGDESC_H_G) ? 1 : 0; - - sdp->u.seg.segbase = h & 0xff000000; - sdp->u.seg.segbase |= (h & 0xff) << 16; - sdp->u.seg.segbase |= l >> 16; - sdp->u.seg.limit = h & 0xf0000; - sdp->u.seg.limit |= l & 0xffff; - if (sdp->u.seg.g) { - sdp->u.seg.limit <<= 12; - sdp->u.seg.limit |= 0xfff; - } - break; - - case CPU_SYSDESC_TYPE_CALL_16: /* 286 call gate */ - case CPU_SYSDESC_TYPE_INTR_16: /* 286 interrupt gate */ - case CPU_SYSDESC_TYPE_TRAP_16: /* 286 trap gate */ - case CPU_SYSDESC_TYPE_CALL_32: /* 386 call gate */ - case CPU_SYSDESC_TYPE_INTR_32: /* 386 interrupt gate */ - case CPU_SYSDESC_TYPE_TRAP_32: /* 386 trap gate */ - if ((h & 0x0000000e0) == 0) { - sdp->valid = 1; - sdp->d = (h & CPU_GATEDESC_H_D) ? 1 : 0; - sdp->u.gate.selector = (UINT16)(l >> 16); - sdp->u.gate.offset = h & 0xffff0000; - sdp->u.gate.offset |= l & 0xffff; - sdp->u.gate.count = (UINT8)(h & 0x1f); - } else { - sdp->valid = 0; - VERBOSE(("load_descriptor: gate is invalid")); - } - break; - - case 0: case 8: case 10: case 13: /* reserved */ - default: - sdp->valid = 0; - break; - } - } -#if defined(DEBUG) - segdesc_dump(sdp); -#endif -} - -int CPUCALL -parse_selector(selector_t *ssp, UINT16 selector) -{ - UINT32 base; - UINT limit; - UINT idx; - - ssp->selector = selector; - ssp->idx = selector & ~3; - ssp->rpl = selector & 3; - ssp->ldt = (UINT8)(selector & CPU_SEGMENT_TABLE_IND); - - VERBOSE(("parse_selector: selector = %04x, index = %d, RPL = %d, %cDT", ssp->selector, ssp->idx >> 3, ssp->rpl, ssp->ldt ? 'L' : 'G')); - - /* descriptor table */ - idx = selector & CPU_SEGMENT_SELECTOR_INDEX_MASK; - if (ssp->ldt) { - /* LDT */ - if (!SEG_IS_VALID(&CPU_LDTR_DESC)) { - VERBOSE(("parse_selector: LDT is invalid")); - return -1; - } - base = CPU_LDTR_BASE; - limit = CPU_LDTR_LIMIT; - } else { - /* check null segment */ - if (idx == 0) { - VERBOSE(("parse_selector: null segment")); - return -2; - } - base = CPU_GDTR_BASE; - limit = CPU_GDTR_LIMIT; - } - if (idx + 7 > limit) { - VERBOSE(("parse_selector: segment limit check failed: 0x%08x > 0x%08x", idx + 7, limit)); - return -3; - } - - /* load descriptor */ - ssp->addr = base + idx; - load_descriptor(&ssp->desc, ssp->addr); - if (!SEG_IS_VALID(&ssp->desc)) { - VERBOSE(("parse_selector: segment descriptor is invalid")); - return -4; - } - - return 0; -} - -int CPUCALL -selector_is_not_present(const selector_t *ssp) -{ - UINT32 h; - - /* not present */ - if (!SEG_IS_PRESENT(&ssp->desc)) { - VERBOSE(("selector_is_not_present: not present")); - return -1; - } - - /* set access bit if code/data segment descriptor */ - if (!SEG_IS_SYSTEM(&ssp->desc)) { - h = cpu_kmemoryread_d(ssp->addr + 4); - if (!(h & CPU_SEGDESC_H_A)) { - h |= CPU_SEGDESC_H_A; - cpu_kmemorywrite_d(ssp->addr + 4, h); - } - } - - return 0; -} - -void CPUCALL -segdesc_init(int idx, UINT16 sreg, descriptor_t *sdp) -{ - - __ASSERT(((unsigned int)idx < CPU_SEGREG_NUM)); - __ASSERT((sdp != NULL)); - - CPU_REGS_SREG(idx) = sreg; - segdesc_set_default(idx, sreg, sdp); -} - -static void CPUCALL -segdesc_set_default(int idx, UINT16 selector, descriptor_t *sdp) -{ - - __ASSERT(((unsigned int)idx < CPU_SEGREG_NUM)); - __ASSERT((sdp != NULL)); - - sdp->u.seg.segbase = (UINT32)selector << 4; - sdp->u.seg.limit = 0xffff; - sdp->u.seg.c = (idx == CPU_CS_INDEX) ? 1 : 0; /* code or data */ - sdp->u.seg.g = 0; /* non 4k factor scale */ - sdp->u.seg.wr = 1; /* execute/read(CS) or read/write(others) */ - sdp->u.seg.ec = 0; /* nonconforming(CS) or expand-up(others) */ - sdp->valid = 1; /* valid */ - sdp->p = 1; /* present */ - sdp->type = (CPU_SEGDESC_TYPE_WR << CPU_DESC_H_TYPE_SHIFT) - | ((idx == CPU_CS_INDEX) ? CPU_SEGDESC_H_D_C : 0); - /* readable code/writable data segment */ - sdp->dpl = CPU_STAT_VM86 ? 3 : 0; /* descriptor privilege level */ - sdp->rpl = CPU_STAT_VM86 ? 3 : 0; /* request privilege level */ - sdp->s = 1; /* code/data */ - sdp->d = 0; /* 16bit */ - sdp->flag = CPU_DESC_FLAG_READABLE|CPU_DESC_FLAG_WRITABLE; -} +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" +#include "ia32.mcr" + +static void CPUCALL segdesc_set_default(int, UINT16, descriptor_t *); + +void CPUCALL +load_segreg(int idx, UINT16 selector, UINT16 *sregp, descriptor_t *sdp, int exc) +{ + selector_t sel; + int rv; + + __ASSERT((unsigned int)idx < CPU_SEGREG_NUM); + __ASSERT((sregp != NULL)); + __ASSERT((sdp != NULL)); + + if (!CPU_STAT_PM || CPU_STAT_VM86) { + /* real-mode or vm86 mode */ + *sregp = selector; + segdesc_set_default(idx, selector, &sel.desc); + *sdp = sel.desc; + return; + } + + VERBOSE(("load_segreg: EIP = %04x:%08x, idx = %d, selector = %04x, sregp = %p, dp = %p, exc = %d", CPU_CS, CPU_PREV_EIP, idx, selector, sregp, sdp, exc)); + + /* + * protected mode + */ + if (idx == CPU_CS_INDEX) { + ia32_panic("load_segreg: CS"); + } + + rv = parse_selector(&sel, selector); + if (rv < 0) { + if ((rv != -2) || (idx == CPU_SS_INDEX)) { + EXCEPTION(exc, sel.idx); + } + /* null selector */ + *sregp = sel.selector; + memset(sdp, 0, sizeof(*sdp)); + return; + } + + switch (idx) { + case CPU_SS_INDEX: + if ((CPU_STAT_CPL != sel.rpl) + || (CPU_STAT_CPL != sel.desc.dpl) + || SEG_IS_SYSTEM(&sel.desc) + || SEG_IS_CODE(&sel.desc) + || !SEG_IS_WRITABLE_DATA(&sel.desc)) { + EXCEPTION(exc, sel.idx); + } + + /* not present */ + rv = selector_is_not_present(&sel); + if (rv < 0) { + EXCEPTION(SS_EXCEPTION, sel.idx); + } + + load_ss(sel.selector, &sel.desc, CPU_STAT_CPL); + break; + + case CPU_ES_INDEX: + case CPU_DS_INDEX: + case CPU_FS_INDEX: + case CPU_GS_INDEX: + if (SEG_IS_SYSTEM(&sel.desc) + || (SEG_IS_CODE(&sel.desc) && !SEG_IS_READABLE_CODE(&sel.desc))) { + EXCEPTION(exc, sel.idx); + } + if (SEG_IS_DATA(&sel.desc) + || !SEG_IS_CONFORMING_CODE(&sel.desc)) { + /* check privilege level */ + if ((sel.rpl > sel.desc.dpl) + || (CPU_STAT_CPL > sel.desc.dpl)) { + EXCEPTION(exc, sel.idx); + } + } + + /* not present */ + rv = selector_is_not_present(&sel); + if (rv < 0) { + EXCEPTION(NP_EXCEPTION, sel.idx); + } + + *sregp = sel.selector; + *sdp = sel.desc; + break; + + default: + ia32_panic("load_segreg(): segment register index is invalid"); + break; + } +} + +/* + * load SS register + */ +void CPUCALL +load_ss(UINT16 selector, const descriptor_t *sdp, int cpl) +{ + + CPU_STAT_SS32 = sdp->d; + CPU_SS = (UINT16)((selector & ~3) | (cpl & 3)); + CPU_SS_DESC = *sdp; +} + +/* + * load CS register + */ +void CPUCALL +load_cs(UINT16 selector, const descriptor_t *sdp, int new_cpl) +{ + int cpl = new_cpl & 3; + + CPU_INST_OP32 = CPU_INST_AS32 = + CPU_STATSAVE.cpu_inst_default.op_32 = + CPU_STATSAVE.cpu_inst_default.as_32 = sdp->d; +#if defined(USE_CPU_EIPMASK) + CPU_EIPMASK = CPU_STATSAVE.cpu_inst_default.op_32 ? 0xffffffff : 0xffff; +#endif + CPU_CS = (UINT16)((selector & ~3) | cpl); + CPU_CS_DESC = *sdp; + set_cpl(cpl); +} + +/* + * load LDT register + */ +void CPUCALL +load_ldtr(UINT16 selector, int exc) +{ + selector_t sel; + int rv; + + memset(&sel, 0, sizeof(sel)); + + rv = parse_selector(&sel, selector); + if (rv < 0 || sel.ldt) { + if (rv == -2) { + /* null segment */ + VERBOSE(("load_ldtr: null segment")); + CPU_LDTR = 0; + memset(&CPU_LDTR_DESC, 0, sizeof(CPU_LDTR_DESC)); + return; + } + EXCEPTION(exc, sel.selector); + } + + /* check descriptor type */ + if (!SEG_IS_SYSTEM(&sel.desc) + || (sel.desc.type != CPU_SYSDESC_TYPE_LDT)) { + EXCEPTION(exc, sel.selector); + } + + /* not present */ + rv = selector_is_not_present(&sel); + if (rv < 0) { + EXCEPTION((exc == TS_EXCEPTION) ? TS_EXCEPTION : NP_EXCEPTION, sel.selector); + } + +#if defined(MORE_DEBUG) + ldtr_dump(sel.desc.u.seg.segbase, sel.desc.u.seg.limit); +#endif + + CPU_LDTR = sel.selector; + CPU_LDTR_DESC = sel.desc; +} + +void CPUCALL +load_descriptor(descriptor_t *sdp, UINT32 addr) +{ + UINT32 l, h; + + __ASSERT(sdp != NULL); + + VERBOSE(("load_descriptor: address = 0x%08x", addr)); + + l = cpu_kmemoryread_d(addr); + h = cpu_kmemoryread_d(addr + 4); + VERBOSE(("descriptor value = 0x%08x%08x", h, l)); + + memset(sdp, 0, sizeof(*sdp)); + sdp->flag = 0; + + sdp->p = (h & CPU_DESC_H_P) ? 1 : 0; + sdp->type = (UINT8)((h & CPU_DESC_H_TYPE) >> CPU_DESC_H_TYPE_SHIFT); + sdp->dpl = (UINT8)((h & CPU_DESC_H_DPL) >> CPU_DESC_H_DPL_SHIFT); + sdp->s = (h & CPU_DESC_H_S) ? 1 : 0; + + if (!SEG_IS_SYSTEM(sdp)) { + /* code/data */ + sdp->valid = 1; + sdp->d = (h & CPU_SEGDESC_H_D) ? 1 : 0; + + sdp->u.seg.c = (h & CPU_SEGDESC_H_D_C) ? 1 : 0; + sdp->u.seg.g = (h & CPU_SEGDESC_H_G) ? 1 : 0; + sdp->u.seg.wr = (sdp->type & CPU_SEGDESC_TYPE_WR) ? 1 : 0; + sdp->u.seg.ec = (sdp->type & CPU_SEGDESC_TYPE_EC) ? 1 : 0; + + sdp->u.seg.segbase = (l >> 16) & 0xffff; + sdp->u.seg.segbase |= (h & 0xff) << 16; + sdp->u.seg.segbase |= h & 0xff000000; + sdp->u.seg.limit = (h & 0xf0000) | (l & 0xffff); + if (sdp->u.seg.g) { + sdp->u.seg.limit <<= 12; + if (SEG_IS_CODE(sdp) || !SEG_IS_EXPANDDOWN_DATA(sdp)) { + /* expand-up segment */ + sdp->u.seg.limit |= 0xfff; + } + } + } else { + /* system */ + switch (sdp->type) { + case CPU_SYSDESC_TYPE_LDT: /* LDT */ + sdp->valid = 1; + sdp->u.seg.g = (h & CPU_SEGDESC_H_G) ? 1 : 0; + + sdp->u.seg.segbase = h & 0xff000000; + sdp->u.seg.segbase |= (h & 0xff) << 16; + sdp->u.seg.segbase |= l >> 16; + sdp->u.seg.limit = h & 0xf0000; + sdp->u.seg.limit |= l & 0xffff; + if (sdp->u.seg.g) { + sdp->u.seg.limit <<= 12; + sdp->u.seg.limit |= 0xfff; + } + break; + + case CPU_SYSDESC_TYPE_TASK: /* task gate */ + sdp->valid = 1; + sdp->u.gate.selector = (UINT16)(l >> 16); + break; + + case CPU_SYSDESC_TYPE_TSS_16: /* 286 TSS */ + case CPU_SYSDESC_TYPE_TSS_BUSY_16: /* 286 TSS Busy */ + case CPU_SYSDESC_TYPE_TSS_32: /* 386 TSS */ + case CPU_SYSDESC_TYPE_TSS_BUSY_32: /* 386 TSS Busy */ + sdp->valid = 1; + sdp->d = (h & CPU_GATEDESC_H_D) ? 1 : 0; + sdp->u.seg.g = (h & CPU_SEGDESC_H_G) ? 1 : 0; + + sdp->u.seg.segbase = h & 0xff000000; + sdp->u.seg.segbase |= (h & 0xff) << 16; + sdp->u.seg.segbase |= l >> 16; + sdp->u.seg.limit = h & 0xf0000; + sdp->u.seg.limit |= l & 0xffff; + if (sdp->u.seg.g) { + sdp->u.seg.limit <<= 12; + sdp->u.seg.limit |= 0xfff; + } + break; + + case CPU_SYSDESC_TYPE_CALL_16: /* 286 call gate */ + case CPU_SYSDESC_TYPE_INTR_16: /* 286 interrupt gate */ + case CPU_SYSDESC_TYPE_TRAP_16: /* 286 trap gate */ + case CPU_SYSDESC_TYPE_CALL_32: /* 386 call gate */ + case CPU_SYSDESC_TYPE_INTR_32: /* 386 interrupt gate */ + case CPU_SYSDESC_TYPE_TRAP_32: /* 386 trap gate */ + if ((h & 0x0000000e0) == 0) { + sdp->valid = 1; + sdp->d = (h & CPU_GATEDESC_H_D) ? 1 : 0; + sdp->u.gate.selector = (UINT16)(l >> 16); + sdp->u.gate.offset = h & 0xffff0000; + sdp->u.gate.offset |= l & 0xffff; + sdp->u.gate.count = (UINT8)(h & 0x1f); + } else { + sdp->valid = 0; + VERBOSE(("load_descriptor: gate is invalid")); + } + break; + + case 0: case 8: case 10: case 13: /* reserved */ + default: + sdp->valid = 0; + break; + } + } +#if defined(DEBUG) + segdesc_dump(sdp); +#endif +} + +int CPUCALL +parse_selector(selector_t *ssp, UINT16 selector) +{ + UINT32 base; + UINT limit; + UINT idx; + + ssp->selector = selector; + ssp->idx = selector & ~3; + ssp->rpl = selector & 3; + ssp->ldt = (UINT8)(selector & CPU_SEGMENT_TABLE_IND); + + VERBOSE(("parse_selector: selector = %04x, index = %d, RPL = %d, %cDT", ssp->selector, ssp->idx >> 3, ssp->rpl, ssp->ldt ? 'L' : 'G')); + + /* descriptor table */ + idx = selector & CPU_SEGMENT_SELECTOR_INDEX_MASK; + if (ssp->ldt) { + /* LDT */ + if (!SEG_IS_VALID(&CPU_LDTR_DESC)) { + VERBOSE(("parse_selector: LDT is invalid")); + return -1; + } + base = CPU_LDTR_BASE; + limit = CPU_LDTR_LIMIT; + } else { + /* check null segment */ + if (idx == 0) { + VERBOSE(("parse_selector: null segment")); + return -2; + } + base = CPU_GDTR_BASE; + limit = CPU_GDTR_LIMIT; + } + if (idx + 7 > limit) { + VERBOSE(("parse_selector: segment limit check failed: 0x%08x > 0x%08x", idx + 7, limit)); + return -3; + } + + /* load descriptor */ + ssp->addr = base + idx; + load_descriptor(&ssp->desc, ssp->addr); + if (!SEG_IS_VALID(&ssp->desc)) { + VERBOSE(("parse_selector: segment descriptor is invalid")); + return -4; + } + + return 0; +} + +int CPUCALL +selector_is_not_present(const selector_t *ssp) +{ + UINT32 h; + + /* not present */ + if (!SEG_IS_PRESENT(&ssp->desc)) { + VERBOSE(("selector_is_not_present: not present")); + return -1; + } + + /* set access bit if code/data segment descriptor */ + if (!SEG_IS_SYSTEM(&ssp->desc)) { + h = cpu_kmemoryread_d(ssp->addr + 4); + if (!(h & CPU_SEGDESC_H_A)) { + h |= CPU_SEGDESC_H_A; + cpu_kmemorywrite_d(ssp->addr + 4, h); + } + } + + return 0; +} + +void CPUCALL +segdesc_init(int idx, UINT16 sreg, descriptor_t *sdp) +{ + + __ASSERT(((unsigned int)idx < CPU_SEGREG_NUM)); + __ASSERT((sdp != NULL)); + + CPU_REGS_SREG(idx) = sreg; + segdesc_set_default(idx, sreg, sdp); +} + +static void CPUCALL +segdesc_set_default(int idx, UINT16 selector, descriptor_t *sdp) +{ + + __ASSERT(((unsigned int)idx < CPU_SEGREG_NUM)); + __ASSERT((sdp != NULL)); + + sdp->u.seg.segbase = (UINT32)selector << 4; + sdp->u.seg.limit = 0xffff; + sdp->u.seg.c = (idx == CPU_CS_INDEX) ? 1 : 0; /* code or data */ + sdp->u.seg.g = 0; /* non 4k factor scale */ + sdp->u.seg.wr = 1; /* execute/read(CS) or read/write(others) */ + sdp->u.seg.ec = 0; /* nonconforming(CS) or expand-up(others) */ + sdp->valid = 1; /* valid */ + sdp->p = 1; /* present */ + sdp->type = (CPU_SEGDESC_TYPE_WR << CPU_DESC_H_TYPE_SHIFT) + | ((idx == CPU_CS_INDEX) ? CPU_SEGDESC_H_D_C : 0); + /* readable code/writable data segment */ + sdp->dpl = CPU_STAT_VM86 ? 3 : 0; /* descriptor privilege level */ + sdp->rpl = CPU_STAT_VM86 ? 3 : 0; /* request privilege level */ + sdp->s = 1; /* code/data */ + sdp->d = 0; /* 16bit */ + sdp->flag = CPU_DESC_FLAG_READABLE|CPU_DESC_FLAG_WRITABLE; +} diff --git a/i386c/ia32/segments.h b/i386c/ia32/segments.h old mode 100755 new mode 100644 index bc9a60e5..947e451a --- a/i386c/ia32/segments.h +++ b/i386c/ia32/segments.h @@ -1,191 +1,191 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_SEGMENTS_H__ -#define IA32_CPU_SEGMENTS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * segment descriptor - */ -typedef struct { - union { - struct { - UINT32 segbase; - UINT32 d_pad; - UINT32 limit; - - UINT8 c; /* 0 = data, 1 = code */ - UINT8 g; /* 4k base */ - UINT8 wr; /* readable/writable */ - UINT8 ec; /* expand down/conforming */ - } seg; - - struct { - UINT16 selector; - UINT16 w_pad; - UINT32 offset; - - UINT8 count; /* parameter count:call gate */ - - UINT8 b_pad[7]; - } gate; - } u; - - UINT8 valid; /* descriptor valid flag */ - UINT8 p; /* avail flag */ - - UINT8 type; /* descriptor type */ - UINT8 dpl; /* DPL */ - UINT8 rpl; /* RPL */ - UINT8 s; /* 0 = system, 1 = code/data */ - UINT8 d; /* 0 = 16bit, 1 = 32bit */ - - UINT8 flag; -#define CPU_DESC_FLAG_READABLE (1 << 0) -#define CPU_DESC_FLAG_WRITABLE (1 << 1) -#define CPU_DESC_FLAG_WHOLEADR (1 << 2) -} descriptor_t; - -#define SEG_IS_VALID(sdp) ((sdp)->valid) -#define SEG_IS_PRESENT(sdp) ((sdp)->p) -#define SEG_IS_32BIT(sdp) ((sdp)->d) -#define SEG_IS_SYSTEM(sdp) (!(sdp)->s) -#define SEG_IS_CODE(sdp) ((sdp)->s && (sdp)->u.seg.c) -#define SEG_IS_DATA(sdp) ((sdp)->s && !(sdp)->u.seg.c) -#define SEG_IS_READABLE_CODE(sdp) ((sdp)->u.seg.wr) -#define SEG_IS_WRITABLE_DATA(sdp) ((sdp)->u.seg.wr) -#define SEG_IS_CONFORMING_CODE(sdp) ((sdp)->u.seg.ec) -#define SEG_IS_EXPANDDOWN_DATA(sdp) ((sdp)->u.seg.ec) - -/* - * segment descriptor - * - * 31 24 23 22 21 20 19 16 15 14 13 12 11 8 7 0 - * +----------------+--+--+--+--+-------+--+-----+--+-------+---------------+ - * | Base 31..16 | G|DB| 0| A|limit_h| P| DPL | S| type | Base 23:16 | 4 - * +----------------+--+--+--+--+-------+--+-----+--+-------+---------------+ - * 31 16 15 0 - * +------------------------------------+-----------------------------------+ - * | Base 15..00 | limit 15..0 | 0 - * +------------------------------------+-----------------------------------+ - */ - -/* descriptor common */ -#define CPU_DESC_H_TYPE_SHIFT 8 -#define CPU_DESC_H_TYPE (0xf << CPU_DESC_H_TYPE_SHIFT) -#define CPU_DESC_H_S ( 1 << 12) /* 0 = system, 1 = code/data */ -#define CPU_DESC_H_DPL_SHIFT 13 -#define CPU_DESC_H_DPL ( 3 << CPU_DESC_H_DPL_SHIFT) -#define CPU_DESC_H_P ( 1 << 15) /* exist */ - -/* for segment descriptor */ -#define CPU_SEGDESC_H_A ( 1 << 8) -#define CPU_SEGDESC_H_D_C ( 1 << 11) /* 0 = data, 1 = code */ -#define CPU_SEGDESC_H_D ( 1 << 22) -#define CPU_SEGDESC_H_G ( 1 << 23) - -/* for gate descriptor */ -#define CPU_GATEDESC_H_D ( 1 << 11) - -/* for tss descriptor */ -#define CPU_TSS_H_BUSY ( 1 << 9) - -/* - * descriptor type - */ -#define CPU_SEGDESC_TYPE_A 0x01 -#define CPU_SEGDESC_TYPE_WR 0x02 -#define CPU_SEGDESC_TYPE_EC 0x04 - -#define CPU_SYSDESC_TYPE_TSS_16 0x01 -#define CPU_SYSDESC_TYPE_LDT 0x02 -#define CPU_SYSDESC_TYPE_TSS_BUSY_16 0x03 -#define CPU_SYSDESC_TYPE_CALL_16 0x04 /* call gate */ -#define CPU_SYSDESC_TYPE_TASK 0x05 /* task gate */ -#define CPU_SYSDESC_TYPE_INTR_16 0x06 /* hardware interrupt */ -#define CPU_SYSDESC_TYPE_TRAP_16 0x07 /* software interrupt */ -#define CPU_SYSDESC_TYPE_TSS_32 0x09 -#define CPU_SYSDESC_TYPE_TSS_BUSY_32 0x0b -#define CPU_SYSDESC_TYPE_CALL_32 0x0c /* call gate */ -#define CPU_SYSDESC_TYPE_INTR_32 0x0e /* hardware interrupt */ -#define CPU_SYSDESC_TYPE_TRAP_32 0x0f /* software interrupt */ - -#define CPU_SYSDESC_TYPE_TSS 0x01 -/* CPU_SYSDESC_TYPE_LDT 0x02 */ -#define CPU_SYSDESC_TYPE_TSS_BUSY 0x03 -#define CPU_SYSDESC_TYPE_CALL 0x04 -/* CPU_SYSDESC_TYPE_TASK 0x05 */ -#define CPU_SYSDESC_TYPE_INTR 0x06 -#define CPU_SYSDESC_TYPE_TRAP 0x07 -#define CPU_SYSDESC_TYPE_MASKBIT 0x07 -#define CPU_SYSDESC_TYPE_32BIT 0x08 - -#define CPU_SYSDESC_TYPE_TSS_BUSY_IND 0x02 - - -void CPUCALL segdesc_init(int idx, UINT16 sreg, descriptor_t *sdp); -void CPUCALL load_descriptor(descriptor_t *sdp, UINT32 addr); - -void CPUCALL load_segreg(int idx, UINT16 selector, UINT16 *sregp, descriptor_t *sdp, int exc); -#define LOAD_SEGREG1(idx, selector, e) \ - load_segreg(idx, selector, &CPU_REGS_SREG(idx), &CPU_STAT_SREG(idx), e) -#define LOAD_SEGREG(idx, selector) \ - LOAD_SEGREG1((idx), (selector), GP_EXCEPTION) -void CPUCALL load_ss(UINT16 selector, const descriptor_t *sdp, int cpl); -void CPUCALL load_cs(UINT16 selector, const descriptor_t *sdp, int cpl); -void CPUCALL load_ldtr(UINT16 selector, int exc); - - -/* - * segment selector - */ -#define CPU_SEGMENT_SELECTOR_INDEX_MASK (~7) -#define CPU_SEGMENT_SELECTOR_RPL_MASK (3) -#define CPU_SEGMENT_TABLE_IND (1 << 2) /* 0 = GDT, 1 = LDT */ - -typedef struct { - UINT16 selector; - UINT16 idx; - UINT16 rpl; - UINT8 ldt; - UINT8 pad; - - UINT32 addr; /* descriptor linear address */ - - descriptor_t desc; -} selector_t; - -int CPUCALL parse_selector(selector_t *ssp, UINT16 selector); -int CPUCALL selector_is_not_present(const selector_t *ssp); - -#ifdef __cplusplus -} -#endif - -#endif /* !IA32_CPU_SEGMENTS_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_SEGMENTS_H__ +#define IA32_CPU_SEGMENTS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * segment descriptor + */ +typedef struct { + union { + struct { + UINT32 segbase; + UINT32 d_pad; + UINT32 limit; + + UINT8 c; /* 0 = data, 1 = code */ + UINT8 g; /* 4k base */ + UINT8 wr; /* readable/writable */ + UINT8 ec; /* expand down/conforming */ + } seg; + + struct { + UINT16 selector; + UINT16 w_pad; + UINT32 offset; + + UINT8 count; /* parameter count:call gate */ + + UINT8 b_pad[7]; + } gate; + } u; + + UINT8 valid; /* descriptor valid flag */ + UINT8 p; /* avail flag */ + + UINT8 type; /* descriptor type */ + UINT8 dpl; /* DPL */ + UINT8 rpl; /* RPL */ + UINT8 s; /* 0 = system, 1 = code/data */ + UINT8 d; /* 0 = 16bit, 1 = 32bit */ + + UINT8 flag; +#define CPU_DESC_FLAG_READABLE (1 << 0) +#define CPU_DESC_FLAG_WRITABLE (1 << 1) +#define CPU_DESC_FLAG_WHOLEADR (1 << 2) +} descriptor_t; + +#define SEG_IS_VALID(sdp) ((sdp)->valid) +#define SEG_IS_PRESENT(sdp) ((sdp)->p) +#define SEG_IS_32BIT(sdp) ((sdp)->d) +#define SEG_IS_SYSTEM(sdp) (!(sdp)->s) +#define SEG_IS_CODE(sdp) ((sdp)->s && (sdp)->u.seg.c) +#define SEG_IS_DATA(sdp) ((sdp)->s && !(sdp)->u.seg.c) +#define SEG_IS_READABLE_CODE(sdp) ((sdp)->u.seg.wr) +#define SEG_IS_WRITABLE_DATA(sdp) ((sdp)->u.seg.wr) +#define SEG_IS_CONFORMING_CODE(sdp) ((sdp)->u.seg.ec) +#define SEG_IS_EXPANDDOWN_DATA(sdp) ((sdp)->u.seg.ec) + +/* + * segment descriptor + * + * 31 24 23 22 21 20 19 16 15 14 13 12 11 8 7 0 + * +----------------+--+--+--+--+-------+--+-----+--+-------+---------------+ + * | Base 31..16 | G|DB| 0| A|limit_h| P| DPL | S| type | Base 23:16 | 4 + * +----------------+--+--+--+--+-------+--+-----+--+-------+---------------+ + * 31 16 15 0 + * +------------------------------------+-----------------------------------+ + * | Base 15..00 | limit 15..0 | 0 + * +------------------------------------+-----------------------------------+ + */ + +/* descriptor common */ +#define CPU_DESC_H_TYPE_SHIFT 8 +#define CPU_DESC_H_TYPE (0xf << CPU_DESC_H_TYPE_SHIFT) +#define CPU_DESC_H_S ( 1 << 12) /* 0 = system, 1 = code/data */ +#define CPU_DESC_H_DPL_SHIFT 13 +#define CPU_DESC_H_DPL ( 3 << CPU_DESC_H_DPL_SHIFT) +#define CPU_DESC_H_P ( 1 << 15) /* exist */ + +/* for segment descriptor */ +#define CPU_SEGDESC_H_A ( 1 << 8) +#define CPU_SEGDESC_H_D_C ( 1 << 11) /* 0 = data, 1 = code */ +#define CPU_SEGDESC_H_D ( 1 << 22) +#define CPU_SEGDESC_H_G ( 1 << 23) + +/* for gate descriptor */ +#define CPU_GATEDESC_H_D ( 1 << 11) + +/* for tss descriptor */ +#define CPU_TSS_H_BUSY ( 1 << 9) + +/* + * descriptor type + */ +#define CPU_SEGDESC_TYPE_A 0x01 +#define CPU_SEGDESC_TYPE_WR 0x02 +#define CPU_SEGDESC_TYPE_EC 0x04 + +#define CPU_SYSDESC_TYPE_TSS_16 0x01 +#define CPU_SYSDESC_TYPE_LDT 0x02 +#define CPU_SYSDESC_TYPE_TSS_BUSY_16 0x03 +#define CPU_SYSDESC_TYPE_CALL_16 0x04 /* call gate */ +#define CPU_SYSDESC_TYPE_TASK 0x05 /* task gate */ +#define CPU_SYSDESC_TYPE_INTR_16 0x06 /* hardware interrupt */ +#define CPU_SYSDESC_TYPE_TRAP_16 0x07 /* software interrupt */ +#define CPU_SYSDESC_TYPE_TSS_32 0x09 +#define CPU_SYSDESC_TYPE_TSS_BUSY_32 0x0b +#define CPU_SYSDESC_TYPE_CALL_32 0x0c /* call gate */ +#define CPU_SYSDESC_TYPE_INTR_32 0x0e /* hardware interrupt */ +#define CPU_SYSDESC_TYPE_TRAP_32 0x0f /* software interrupt */ + +#define CPU_SYSDESC_TYPE_TSS 0x01 +/* CPU_SYSDESC_TYPE_LDT 0x02 */ +#define CPU_SYSDESC_TYPE_TSS_BUSY 0x03 +#define CPU_SYSDESC_TYPE_CALL 0x04 +/* CPU_SYSDESC_TYPE_TASK 0x05 */ +#define CPU_SYSDESC_TYPE_INTR 0x06 +#define CPU_SYSDESC_TYPE_TRAP 0x07 +#define CPU_SYSDESC_TYPE_MASKBIT 0x07 +#define CPU_SYSDESC_TYPE_32BIT 0x08 + +#define CPU_SYSDESC_TYPE_TSS_BUSY_IND 0x02 + + +void CPUCALL segdesc_init(int idx, UINT16 sreg, descriptor_t *sdp); +void CPUCALL load_descriptor(descriptor_t *sdp, UINT32 addr); + +void CPUCALL load_segreg(int idx, UINT16 selector, UINT16 *sregp, descriptor_t *sdp, int exc); +#define LOAD_SEGREG1(idx, selector, e) \ + load_segreg(idx, selector, &CPU_REGS_SREG(idx), &CPU_STAT_SREG(idx), e) +#define LOAD_SEGREG(idx, selector) \ + LOAD_SEGREG1((idx), (selector), GP_EXCEPTION) +void CPUCALL load_ss(UINT16 selector, const descriptor_t *sdp, int cpl); +void CPUCALL load_cs(UINT16 selector, const descriptor_t *sdp, int cpl); +void CPUCALL load_ldtr(UINT16 selector, int exc); + + +/* + * segment selector + */ +#define CPU_SEGMENT_SELECTOR_INDEX_MASK (~7) +#define CPU_SEGMENT_SELECTOR_RPL_MASK (3) +#define CPU_SEGMENT_TABLE_IND (1 << 2) /* 0 = GDT, 1 = LDT */ + +typedef struct { + UINT16 selector; + UINT16 idx; + UINT16 rpl; + UINT8 ldt; + UINT8 pad; + + UINT32 addr; /* descriptor linear address */ + + descriptor_t desc; +} selector_t; + +int CPUCALL parse_selector(selector_t *ssp, UINT16 selector); +int CPUCALL selector_is_not_present(const selector_t *ssp); + +#ifdef __cplusplus +} +#endif + +#endif /* !IA32_CPU_SEGMENTS_H__ */ diff --git a/i386c/ia32/task.c b/i386c/ia32/task.c old mode 100755 new mode 100644 index a2727c05..c377dc69 --- a/i386c/ia32/task.c +++ b/i386c/ia32/task.c @@ -1,546 +1,546 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "cpu.h" -#include "ia32.mcr" - -#define TSS_16_SIZE 44 -#define TSS_16_LIMIT (TSS_16_SIZE - 1) -#define TSS_32_SIZE 104 -#define TSS_32_LIMIT (TSS_32_SIZE - 1) - -static void CPUCALL -set_task_busy(UINT16 selector) -{ - UINT32 addr; - UINT32 h; - - addr = CPU_GDTR_BASE + (selector & CPU_SEGMENT_SELECTOR_INDEX_MASK); - h = cpu_kmemoryread_d(addr + 4); - if (!(h & CPU_TSS_H_BUSY)) { - h |= CPU_TSS_H_BUSY; - cpu_kmemorywrite_d(addr + 4, h); - } else { - ia32_panic("set_task_busy: already busy(%04x:%08x)", - selector, h); - } -} - -static void CPUCALL -set_task_free(UINT16 selector) -{ - UINT32 addr; - UINT32 h; - - addr = CPU_GDTR_BASE + (selector & CPU_SEGMENT_SELECTOR_INDEX_MASK); - h = cpu_kmemoryread_d(addr + 4); - if (h & CPU_TSS_H_BUSY) { - h &= ~CPU_TSS_H_BUSY; - cpu_kmemorywrite_d(addr + 4, h); - } else { - ia32_panic("set_task_free: already free(%04x:%08x)", - selector, h); - } -} - -void CPUCALL -load_tr(UINT16 selector) -{ - selector_t task_sel; - int rv; - UINT16 iobase; - - rv = parse_selector(&task_sel, selector); - if (rv < 0 || task_sel.ldt || !SEG_IS_SYSTEM(&task_sel.desc)) { - EXCEPTION(GP_EXCEPTION, task_sel.idx); - } - - /* check descriptor type & stack room size */ - switch (task_sel.desc.type) { - case CPU_SYSDESC_TYPE_TSS_16: - if (task_sel.desc.u.seg.limit < TSS_16_LIMIT) { - EXCEPTION(TS_EXCEPTION, task_sel.idx); - } - iobase = 0; - break; - - case CPU_SYSDESC_TYPE_TSS_32: - if (task_sel.desc.u.seg.limit < TSS_32_LIMIT) { - EXCEPTION(TS_EXCEPTION, task_sel.idx); - } - iobase = cpu_kmemoryread_w(task_sel.desc.u.seg.segbase + 102); - break; - - default: - EXCEPTION(GP_EXCEPTION, task_sel.idx); - return; - } - - /* not present */ - rv = selector_is_not_present(&task_sel); - if (rv < 0) { - EXCEPTION(NP_EXCEPTION, task_sel.idx); - } - -#if defined(MORE_DEBUG) - tr_dump(task_sel.selector, task_sel.desc.u.seg.segbase, task_sel.desc.u.seg.limit); -#endif - - set_task_busy(task_sel.selector); - CPU_TR = task_sel.selector; - CPU_TR_DESC = task_sel.desc; - CPU_TR_DESC.type |= CPU_SYSDESC_TYPE_TSS_BUSY_IND; - - /* I/O deny bitmap */ - CPU_STAT_IOLIMIT = 0; - if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_32) { - if (iobase < CPU_TR_LIMIT) { - CPU_STAT_IOLIMIT = (UINT16)(CPU_TR_LIMIT - iobase); - CPU_STAT_IOADDR = CPU_TR_BASE + iobase; - VERBOSE(("load_tr: enable ioport control: iobase=0x%04x, base=0x%08x, limit=0x%08x", iobase, CPU_STAT_IOADDR, CPU_STAT_IOLIMIT)); - } - } - if (CPU_STAT_IOLIMIT == 0) { - VERBOSE(("load_tr: disable ioport control.")); - } -} - -void CPUCALL -get_stack_pointer_from_tss(UINT pl, UINT16 *new_ss, UINT32 *new_esp) -{ - UINT32 tss_stack_addr; - - VERBOSE(("get_stack_pointer_from_tss: pl = %d", pl)); - VERBOSE(("get_stack_pointer_from_tss: CPU_TR type = %d, base = 0x%08x, limit = 0x%08x", CPU_TR_DESC.type, CPU_TR_BASE, CPU_TR_LIMIT)); - - __ASSERT(pl < 3); - - if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_32) { - tss_stack_addr = pl * 8 + 4; - if (tss_stack_addr + 7 > CPU_TR_LIMIT) { - EXCEPTION(TS_EXCEPTION, CPU_TR & ~3); - } - tss_stack_addr += CPU_TR_BASE; - *new_esp = cpu_kmemoryread_d(tss_stack_addr); - *new_ss = cpu_kmemoryread_w(tss_stack_addr + 4); - } else if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_16) { - tss_stack_addr = pl * 4 + 2; - if (tss_stack_addr + 3 > CPU_TR_LIMIT) { - EXCEPTION(TS_EXCEPTION, CPU_TR & ~3); - } - tss_stack_addr += CPU_TR_BASE; - *new_esp = cpu_kmemoryread_w(tss_stack_addr); - *new_ss = cpu_kmemoryread_w(tss_stack_addr + 2); - } else { - ia32_panic("get_stack_pointer_from_tss: task register is invalid (%d)\n", CPU_TR_DESC.type); - } - VERBOSE(("get_stack_pointer_from_tss: new stack pointer = %04x:%08x", - *new_ss, *new_esp)); -} - -UINT16 -get_backlink_selector_from_tss(void) -{ - UINT16 backlink; - - if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_32) { - if (4 > CPU_TR_LIMIT) { - EXCEPTION(TS_EXCEPTION, CPU_TR & ~3); - } - } else if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_16) { - if (2 > CPU_TR_LIMIT) { - EXCEPTION(TS_EXCEPTION, CPU_TR & ~3); - } - } else { - ia32_panic("get_backlink_selector_from_tss: task register has invalid type (%d)\n", CPU_TR_DESC.type); - } - - backlink = cpu_kmemoryread_w(CPU_TR_BASE); - VERBOSE(("get_backlink_selector_from_tss: backlink selector = 0x%04x", - backlink)); - return backlink; -} - -void CPUCALL -task_switch(selector_t *task_sel, task_switch_type_t type) -{ - UINT32 regs[CPU_REG_NUM]; - UINT32 eip; - UINT32 new_flags; - UINT32 cr3 = 0; - UINT16 sreg[CPU_SEGREG_NUM]; - UINT16 ldtr; - UINT16 iobase; - UINT16 t; - - selector_t cs_sel, ss_sel; - int rv; - - UINT32 cur_base, cur_paddr; /* current task state */ - UINT32 task_base, task_paddr; /* new task state */ - UINT32 old_flags = REAL_EFLAGREG; - BOOL task16; - UINT i; - - VERBOSE(("task_switch: start")); - - switch (task_sel->desc.type) { - case CPU_SYSDESC_TYPE_TSS_32: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - if (task_sel->desc.u.seg.limit < TSS_32_LIMIT) { - EXCEPTION(TS_EXCEPTION, task_sel->idx); - } - task16 = 0; - break; - - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - if (task_sel->desc.u.seg.limit < TSS_16_LIMIT) { - EXCEPTION(TS_EXCEPTION, task_sel->idx); - } - task16 = 1; - break; - - default: - ia32_panic("task_switch: descriptor type is invalid."); - task16 = 0; /* compiler happy */ - break; - } - - cur_base = CPU_TR_BASE; - cur_paddr = laddr_to_paddr(cur_base, CPU_PAGE_WRITE_DATA|CPU_MODE_SUPERVISER); - task_base = task_sel->desc.u.seg.segbase; - task_paddr = laddr_to_paddr(task_base, CPU_PAGE_WRITE_DATA|CPU_MODE_SUPERVISER); - VERBOSE(("task_switch: current task (%04x) = 0x%08x:%08x (p0x%08x)", - CPU_TR, cur_base, CPU_TR_LIMIT, cur_paddr)); - VERBOSE(("task_switch: new task (%04x) = 0x%08x:%08x (p0x%08x)", - task_sel->selector, task_base, task_sel->desc.u.seg.limit, - task_paddr)); - VERBOSE(("task_switch: %dbit task switch", task16 ? 16 : 32)); - -#if defined(MORE_DEBUG) - VERBOSE(("task_switch: new task")); - for (i = 0; i < task_sel->desc.u.seg.limit; i += 4) { - VERBOSE(("task_switch: 0x%08x: %08x", task_base + i, - cpu_memoryread_d(task_paddr + i))); - } -#endif - - /* load task state */ - if (!task16) { - if (CPU_STAT_PAGING) { - cr3 = cpu_memoryread_d(task_paddr + 28); - } - eip = cpu_memoryread_d(task_paddr + 32); - new_flags = cpu_memoryread_d(task_paddr + 36); - for (i = 0; i < CPU_REG_NUM; i++) { - regs[i] = cpu_memoryread_d(task_paddr + 40 + i * 4); - } - for (i = 0; i < CPU_SEGREG_NUM; i++) { - sreg[i] = cpu_memoryread_w(task_paddr + 72 + i * 4); - } - ldtr = cpu_memoryread_w(task_paddr + 96); - t = cpu_memoryread_w(task_paddr + 100); - if (t & 1) { - CPU_STAT_BP_EVENT |= CPU_STAT_BP_EVENT_TASK; - } - iobase = cpu_memoryread_w(task_paddr + 102); - } else { - eip = cpu_memoryread_w(task_paddr + 14); - new_flags = cpu_memoryread_w(task_paddr + 16); - for (i = 0; i < CPU_REG_NUM; i++) { - regs[i] = cpu_memoryread_w(task_paddr + 18 + i * 2); - } - for (i = 0; i < CPU_SEGREG286_NUM; i++) { - sreg[i] = cpu_memoryread_w(task_paddr + 34 + i * 2); - } - for (; i < CPU_SEGREG_NUM; i++) { - sreg[i] = 0; - } - ldtr = cpu_memoryread_w(task_paddr + 42); - iobase = 0; - t = 0; - } - -#if defined(DEBUG) - VERBOSE(("task_switch: current task")); - if (!task16) { - VERBOSE(("task_switch: CR3 = 0x%08x", CPU_CR3)); - } - VERBOSE(("task_switch: eip = 0x%08x", CPU_EIP)); - VERBOSE(("task_switch: eflags = 0x%08x", old_flags)); - for (i = 0; i < CPU_REG_NUM; i++) { - VERBOSE(("task_switch: %s = 0x%08x", reg32_str[i], - CPU_REGS_DWORD(i))); - } - for (i = 0; i < CPU_SEGREG_NUM; i++) { - VERBOSE(("task_switch: %s = 0x%04x", sreg_str[i], - CPU_REGS_SREG(i))); - } - VERBOSE(("task_switch: ldtr = 0x%04x", CPU_LDTR)); - - VERBOSE(("task_switch: new task")); - if (!task16) { - VERBOSE(("task_switch: CR3 = 0x%08x", cr3)); - } - VERBOSE(("task_switch: eip = 0x%08x", eip)); - VERBOSE(("task_switch: eflags = 0x%08x", new_flags)); - for (i = 0; i < CPU_REG_NUM; i++) { - VERBOSE(("task_switch: %s = 0x%08x", reg32_str[i], regs[i])); - } - for (i = 0; i < CPU_SEGREG_NUM; i++) { - VERBOSE(("task_switch: %s = 0x%04x", sreg_str[i], sreg[i])); - } - VERBOSE(("task_switch: ldtr = 0x%04x", ldtr)); - if (!task16) { - VERBOSE(("task_switch: t = 0x%04x", t)); - VERBOSE(("task_switch: iobase = 0x%04x", iobase)); - } -#endif - - /* if IRET or JMP, clear busy flag in this task: need */ - /* if IRET, clear NT_FLAG in current EFLAG: need */ - switch (type) { - case TASK_SWITCH_IRET: - /* clear NT_FLAG */ - old_flags &= ~NT_FLAG; - /*FALLTHROUGH*/ - case TASK_SWITCH_JMP: - /* clear busy flags in current task */ - set_task_free(CPU_TR); - break; - - case TASK_SWITCH_CALL: - case TASK_SWITCH_INTR: - /* Nothing to do */ - break; - - default: - ia32_panic("task_switch: task switch type is invalid"); - break; - } - - /* store current task state in current TSS */ - if (!task16) { - cpu_memorywrite_d(cur_paddr + 32, CPU_EIP); - cpu_memorywrite_d(cur_paddr + 36, old_flags); - for (i = 0; i < CPU_REG_NUM; i++) { - cpu_memorywrite_d(cur_paddr + 40 + i * 4, - CPU_REGS_DWORD(i)); - } - for (i = 0; i < CPU_SEGREG_NUM; i++) { - cpu_memorywrite_w(cur_paddr + 72 + i * 4, - CPU_REGS_SREG(i)); - } - } else { - cpu_memorywrite_w(cur_paddr + 14, CPU_IP); - cpu_memorywrite_w(cur_paddr + 16, (UINT16)old_flags); - for (i = 0; i < CPU_REG_NUM; i++) { - cpu_memorywrite_w(cur_paddr + 18 + i * 2, - CPU_REGS_WORD(i)); - } - for (i = 0; i < CPU_SEGREG286_NUM; i++) { - cpu_memorywrite_w(cur_paddr + 34 + i * 2, - CPU_REGS_SREG(i)); - } - } - - /* set back link selector */ - switch (type) { - case TASK_SWITCH_CALL: - case TASK_SWITCH_INTR: - /* set back link selector */ - cpu_memorywrite_w(task_paddr, CPU_TR); - break; - - case TASK_SWITCH_IRET: - case TASK_SWITCH_JMP: - /* Nothing to do */ - break; - - default: - ia32_panic("task_switch: task switch type is invalid"); - break; - } - -#if defined(MORE_DEBUG) - VERBOSE(("task_switch: current task")); - for (i = 0; i < CPU_TR_LIMIT; i += 4) { - VERBOSE(("task_switch: 0x%08x: %08x", cur_base + i, - cpu_memoryread_d(cur_paddr + i))); - } -#endif - - /* Now task switching! */ - - /* if CALL, INTR, set EFLAGS image NT_FLAG */ - /* if CALL, INTR, JMP set busy flag */ - switch (type) { - case TASK_SWITCH_CALL: - case TASK_SWITCH_INTR: - /* set back link selector */ - new_flags |= NT_FLAG; - /*FALLTHROUGH*/ - case TASK_SWITCH_JMP: - set_task_busy(task_sel->selector); - break; - - case TASK_SWITCH_IRET: - /* check busy flag is active */ - if (SEG_IS_VALID(&task_sel->desc)) { - UINT32 h; - h = cpu_kmemoryread_d(task_sel->addr + 4); - if ((h & CPU_TSS_H_BUSY) == 0) { - ia32_panic("task_switch: new task is not busy"); - } - } - break; - - default: - ia32_panic("task_switch: task switch type is invalid"); - break; - } - - /* load task selector to CPU_TR */ - CPU_TR = task_sel->selector; - CPU_TR_DESC = task_sel->desc; - CPU_TR_DESC.type |= CPU_SYSDESC_TYPE_TSS_BUSY_IND; - - /* set CR0 image CPU_CR0_TS */ - CPU_CR0 |= CPU_CR0_TS; - - /* - * load task state (CR3, EIP, GPR, segregs, LDTR, EFLAGS) - */ - - /* set new CR3 */ - if (!task16 && CPU_STAT_PAGING) { - set_cr3(cr3); - } - - /* set new EIP, GPR, segregs */ - CPU_EIP = eip; - for (i = 0; i < CPU_REG_NUM; i++) { - CPU_REGS_DWORD(i) = regs[i]; - } - for (i = 0; i < CPU_SEGREG_NUM; i++) { - segdesc_init(i, sreg[i], &CPU_STAT_SREG(i)); - /* invalidate segreg descriptor */ - CPU_STAT_SREG(i).valid = 0; - } - - CPU_CLEAR_PREV_ESP(); - - /* load new LDTR */ - CPU_LDTR_DESC.valid = 0; - load_ldtr(ldtr, TS_EXCEPTION); - - /* I/O deny bitmap */ - CPU_STAT_IOLIMIT = 0; - if (!task16 && iobase != 0 && iobase < CPU_TR_DESC.u.seg.limit) { - CPU_STAT_IOLIMIT = (UINT16)(CPU_TR_DESC.u.seg.limit - iobase); - CPU_STAT_IOADDR = task_base + iobase; - } - VERBOSE(("task_switch: ioaddr = %08x, limit = %08x", CPU_STAT_IOADDR, - CPU_STAT_IOLIMIT)); - - /* set new EFLAGS */ - set_eflags(new_flags, I_FLAG|IOPL_FLAG|RF_FLAG|VM_FLAG|VIF_FLAG|VIP_FLAG); - - /* set new segment register */ - if (!CPU_STAT_VM86) { - /* load CS */ - rv = parse_selector(&cs_sel, sreg[CPU_CS_INDEX]); - if (rv < 0) { - VERBOSE(("task_switch: load CS failure (sel = 0x%04x, rv = %d)", sreg[CPU_CS_INDEX], rv)); - EXCEPTION(TS_EXCEPTION, cs_sel.idx); - } - - /* CS must be code segment */ - if (SEG_IS_SYSTEM(&cs_sel.desc) || SEG_IS_DATA(&cs_sel.desc)) { - EXCEPTION(TS_EXCEPTION, cs_sel.idx); - } - - /* check privilege level */ - if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc)) { - /* non-confirming code segment */ - if (cs_sel.desc.dpl != cs_sel.rpl) { - EXCEPTION(TS_EXCEPTION, cs_sel.idx); - } - } else { - /* conforming code segment */ - if (cs_sel.desc.dpl > cs_sel.rpl) { - EXCEPTION(TS_EXCEPTION, cs_sel.idx); - } - } - - /* code segment is not present */ - rv = selector_is_not_present(&cs_sel); - if (rv < 0) { - EXCEPTION(NP_EXCEPTION, cs_sel.idx); - } - - /* load SS */ - rv = parse_selector(&ss_sel, sreg[CPU_SS_INDEX]); - if (rv < 0) { - VERBOSE(("task_switch: load SS failure (sel = 0x%04x, rv = %d)", sreg[CPU_SS_INDEX], rv)); - EXCEPTION(TS_EXCEPTION, ss_sel.idx); - } - - /* SS must be writable data segment */ - if (SEG_IS_SYSTEM(&ss_sel.desc) - || SEG_IS_CODE(&ss_sel.desc) - || !SEG_IS_WRITABLE_DATA(&ss_sel.desc)) { - EXCEPTION(TS_EXCEPTION, ss_sel.idx); - } - - /* check privilege level */ - if ((ss_sel.desc.dpl != cs_sel.rpl) - || (ss_sel.desc.dpl != ss_sel.rpl)) { - EXCEPTION(TS_EXCEPTION, ss_sel.idx); - } - - /* stack segment is not present */ - rv = selector_is_not_present(&ss_sel); - if (rv < 0) { - EXCEPTION(SS_EXCEPTION, ss_sel.idx); - } - - /* Now loading SS register */ - load_ss(ss_sel.selector, &ss_sel.desc, cs_sel.rpl); - - /* load ES, DS, FS, GS segment register */ - LOAD_SEGREG1(CPU_ES_INDEX, sreg[CPU_ES_INDEX], TS_EXCEPTION); - LOAD_SEGREG1(CPU_DS_INDEX, sreg[CPU_DS_INDEX], TS_EXCEPTION); - LOAD_SEGREG1(CPU_FS_INDEX, sreg[CPU_FS_INDEX], TS_EXCEPTION); - LOAD_SEGREG1(CPU_GS_INDEX, sreg[CPU_GS_INDEX], TS_EXCEPTION); - - /* Now loading CS register */ - load_cs(cs_sel.selector, &cs_sel.desc, cs_sel.rpl); - } - - VERBOSE(("task_switch: done.")); -} +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "cpu.h" +#include "ia32.mcr" + +#define TSS_16_SIZE 44 +#define TSS_16_LIMIT (TSS_16_SIZE - 1) +#define TSS_32_SIZE 104 +#define TSS_32_LIMIT (TSS_32_SIZE - 1) + +static void CPUCALL +set_task_busy(UINT16 selector) +{ + UINT32 addr; + UINT32 h; + + addr = CPU_GDTR_BASE + (selector & CPU_SEGMENT_SELECTOR_INDEX_MASK); + h = cpu_kmemoryread_d(addr + 4); + if (!(h & CPU_TSS_H_BUSY)) { + h |= CPU_TSS_H_BUSY; + cpu_kmemorywrite_d(addr + 4, h); + } else { + ia32_panic("set_task_busy: already busy(%04x:%08x)", + selector, h); + } +} + +static void CPUCALL +set_task_free(UINT16 selector) +{ + UINT32 addr; + UINT32 h; + + addr = CPU_GDTR_BASE + (selector & CPU_SEGMENT_SELECTOR_INDEX_MASK); + h = cpu_kmemoryread_d(addr + 4); + if (h & CPU_TSS_H_BUSY) { + h &= ~CPU_TSS_H_BUSY; + cpu_kmemorywrite_d(addr + 4, h); + } else { + ia32_panic("set_task_free: already free(%04x:%08x)", + selector, h); + } +} + +void CPUCALL +load_tr(UINT16 selector) +{ + selector_t task_sel; + int rv; + UINT16 iobase; + + rv = parse_selector(&task_sel, selector); + if (rv < 0 || task_sel.ldt || !SEG_IS_SYSTEM(&task_sel.desc)) { + EXCEPTION(GP_EXCEPTION, task_sel.idx); + } + + /* check descriptor type & stack room size */ + switch (task_sel.desc.type) { + case CPU_SYSDESC_TYPE_TSS_16: + if (task_sel.desc.u.seg.limit < TSS_16_LIMIT) { + EXCEPTION(TS_EXCEPTION, task_sel.idx); + } + iobase = 0; + break; + + case CPU_SYSDESC_TYPE_TSS_32: + if (task_sel.desc.u.seg.limit < TSS_32_LIMIT) { + EXCEPTION(TS_EXCEPTION, task_sel.idx); + } + iobase = cpu_kmemoryread_w(task_sel.desc.u.seg.segbase + 102); + break; + + default: + EXCEPTION(GP_EXCEPTION, task_sel.idx); + return; + } + + /* not present */ + rv = selector_is_not_present(&task_sel); + if (rv < 0) { + EXCEPTION(NP_EXCEPTION, task_sel.idx); + } + +#if defined(MORE_DEBUG) + tr_dump(task_sel.selector, task_sel.desc.u.seg.segbase, task_sel.desc.u.seg.limit); +#endif + + set_task_busy(task_sel.selector); + CPU_TR = task_sel.selector; + CPU_TR_DESC = task_sel.desc; + CPU_TR_DESC.type |= CPU_SYSDESC_TYPE_TSS_BUSY_IND; + + /* I/O deny bitmap */ + CPU_STAT_IOLIMIT = 0; + if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_32) { + if (iobase < CPU_TR_LIMIT) { + CPU_STAT_IOLIMIT = (UINT16)(CPU_TR_LIMIT - iobase); + CPU_STAT_IOADDR = CPU_TR_BASE + iobase; + VERBOSE(("load_tr: enable ioport control: iobase=0x%04x, base=0x%08x, limit=0x%08x", iobase, CPU_STAT_IOADDR, CPU_STAT_IOLIMIT)); + } + } + if (CPU_STAT_IOLIMIT == 0) { + VERBOSE(("load_tr: disable ioport control.")); + } +} + +void CPUCALL +get_stack_pointer_from_tss(UINT pl, UINT16 *new_ss, UINT32 *new_esp) +{ + UINT32 tss_stack_addr; + + VERBOSE(("get_stack_pointer_from_tss: pl = %d", pl)); + VERBOSE(("get_stack_pointer_from_tss: CPU_TR type = %d, base = 0x%08x, limit = 0x%08x", CPU_TR_DESC.type, CPU_TR_BASE, CPU_TR_LIMIT)); + + __ASSERT(pl < 3); + + if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_32) { + tss_stack_addr = pl * 8 + 4; + if (tss_stack_addr + 7 > CPU_TR_LIMIT) { + EXCEPTION(TS_EXCEPTION, CPU_TR & ~3); + } + tss_stack_addr += CPU_TR_BASE; + *new_esp = cpu_kmemoryread_d(tss_stack_addr); + *new_ss = cpu_kmemoryread_w(tss_stack_addr + 4); + } else if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_16) { + tss_stack_addr = pl * 4 + 2; + if (tss_stack_addr + 3 > CPU_TR_LIMIT) { + EXCEPTION(TS_EXCEPTION, CPU_TR & ~3); + } + tss_stack_addr += CPU_TR_BASE; + *new_esp = cpu_kmemoryread_w(tss_stack_addr); + *new_ss = cpu_kmemoryread_w(tss_stack_addr + 2); + } else { + ia32_panic("get_stack_pointer_from_tss: task register is invalid (%d)\n", CPU_TR_DESC.type); + } + VERBOSE(("get_stack_pointer_from_tss: new stack pointer = %04x:%08x", + *new_ss, *new_esp)); +} + +UINT16 +get_backlink_selector_from_tss(void) +{ + UINT16 backlink; + + if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_32) { + if (4 > CPU_TR_LIMIT) { + EXCEPTION(TS_EXCEPTION, CPU_TR & ~3); + } + } else if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_16) { + if (2 > CPU_TR_LIMIT) { + EXCEPTION(TS_EXCEPTION, CPU_TR & ~3); + } + } else { + ia32_panic("get_backlink_selector_from_tss: task register has invalid type (%d)\n", CPU_TR_DESC.type); + } + + backlink = cpu_kmemoryread_w(CPU_TR_BASE); + VERBOSE(("get_backlink_selector_from_tss: backlink selector = 0x%04x", + backlink)); + return backlink; +} + +void CPUCALL +task_switch(selector_t *task_sel, task_switch_type_t type) +{ + UINT32 regs[CPU_REG_NUM]; + UINT32 eip; + UINT32 new_flags; + UINT32 cr3 = 0; + UINT16 sreg[CPU_SEGREG_NUM]; + UINT16 ldtr; + UINT16 iobase; + UINT16 t; + + selector_t cs_sel, ss_sel; + int rv; + + UINT32 cur_base, cur_paddr; /* current task state */ + UINT32 task_base, task_paddr; /* new task state */ + UINT32 old_flags = REAL_EFLAGREG; + BOOL task16; + UINT i; + + VERBOSE(("task_switch: start")); + + switch (task_sel->desc.type) { + case CPU_SYSDESC_TYPE_TSS_32: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + if (task_sel->desc.u.seg.limit < TSS_32_LIMIT) { + EXCEPTION(TS_EXCEPTION, task_sel->idx); + } + task16 = 0; + break; + + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + if (task_sel->desc.u.seg.limit < TSS_16_LIMIT) { + EXCEPTION(TS_EXCEPTION, task_sel->idx); + } + task16 = 1; + break; + + default: + ia32_panic("task_switch: descriptor type is invalid."); + task16 = 0; /* compiler happy */ + break; + } + + cur_base = CPU_TR_BASE; + cur_paddr = laddr_to_paddr(cur_base, CPU_PAGE_WRITE_DATA|CPU_MODE_SUPERVISER); + task_base = task_sel->desc.u.seg.segbase; + task_paddr = laddr_to_paddr(task_base, CPU_PAGE_WRITE_DATA|CPU_MODE_SUPERVISER); + VERBOSE(("task_switch: current task (%04x) = 0x%08x:%08x (p0x%08x)", + CPU_TR, cur_base, CPU_TR_LIMIT, cur_paddr)); + VERBOSE(("task_switch: new task (%04x) = 0x%08x:%08x (p0x%08x)", + task_sel->selector, task_base, task_sel->desc.u.seg.limit, + task_paddr)); + VERBOSE(("task_switch: %dbit task switch", task16 ? 16 : 32)); + +#if defined(MORE_DEBUG) + VERBOSE(("task_switch: new task")); + for (i = 0; i < task_sel->desc.u.seg.limit; i += 4) { + VERBOSE(("task_switch: 0x%08x: %08x", task_base + i, + cpu_memoryread_d(task_paddr + i))); + } +#endif + + /* load task state */ + if (!task16) { + if (CPU_STAT_PAGING) { + cr3 = cpu_memoryread_d(task_paddr + 28); + } + eip = cpu_memoryread_d(task_paddr + 32); + new_flags = cpu_memoryread_d(task_paddr + 36); + for (i = 0; i < CPU_REG_NUM; i++) { + regs[i] = cpu_memoryread_d(task_paddr + 40 + i * 4); + } + for (i = 0; i < CPU_SEGREG_NUM; i++) { + sreg[i] = cpu_memoryread_w(task_paddr + 72 + i * 4); + } + ldtr = cpu_memoryread_w(task_paddr + 96); + t = cpu_memoryread_w(task_paddr + 100); + if (t & 1) { + CPU_STAT_BP_EVENT |= CPU_STAT_BP_EVENT_TASK; + } + iobase = cpu_memoryread_w(task_paddr + 102); + } else { + eip = cpu_memoryread_w(task_paddr + 14); + new_flags = cpu_memoryread_w(task_paddr + 16); + for (i = 0; i < CPU_REG_NUM; i++) { + regs[i] = cpu_memoryread_w(task_paddr + 18 + i * 2); + } + for (i = 0; i < CPU_SEGREG286_NUM; i++) { + sreg[i] = cpu_memoryread_w(task_paddr + 34 + i * 2); + } + for (; i < CPU_SEGREG_NUM; i++) { + sreg[i] = 0; + } + ldtr = cpu_memoryread_w(task_paddr + 42); + iobase = 0; + t = 0; + } + +#if defined(DEBUG) + VERBOSE(("task_switch: current task")); + if (!task16) { + VERBOSE(("task_switch: CR3 = 0x%08x", CPU_CR3)); + } + VERBOSE(("task_switch: eip = 0x%08x", CPU_EIP)); + VERBOSE(("task_switch: eflags = 0x%08x", old_flags)); + for (i = 0; i < CPU_REG_NUM; i++) { + VERBOSE(("task_switch: %s = 0x%08x", reg32_str[i], + CPU_REGS_DWORD(i))); + } + for (i = 0; i < CPU_SEGREG_NUM; i++) { + VERBOSE(("task_switch: %s = 0x%04x", sreg_str[i], + CPU_REGS_SREG(i))); + } + VERBOSE(("task_switch: ldtr = 0x%04x", CPU_LDTR)); + + VERBOSE(("task_switch: new task")); + if (!task16) { + VERBOSE(("task_switch: CR3 = 0x%08x", cr3)); + } + VERBOSE(("task_switch: eip = 0x%08x", eip)); + VERBOSE(("task_switch: eflags = 0x%08x", new_flags)); + for (i = 0; i < CPU_REG_NUM; i++) { + VERBOSE(("task_switch: %s = 0x%08x", reg32_str[i], regs[i])); + } + for (i = 0; i < CPU_SEGREG_NUM; i++) { + VERBOSE(("task_switch: %s = 0x%04x", sreg_str[i], sreg[i])); + } + VERBOSE(("task_switch: ldtr = 0x%04x", ldtr)); + if (!task16) { + VERBOSE(("task_switch: t = 0x%04x", t)); + VERBOSE(("task_switch: iobase = 0x%04x", iobase)); + } +#endif + + /* if IRET or JMP, clear busy flag in this task: need */ + /* if IRET, clear NT_FLAG in current EFLAG: need */ + switch (type) { + case TASK_SWITCH_IRET: + /* clear NT_FLAG */ + old_flags &= ~NT_FLAG; + /*FALLTHROUGH*/ + case TASK_SWITCH_JMP: + /* clear busy flags in current task */ + set_task_free(CPU_TR); + break; + + case TASK_SWITCH_CALL: + case TASK_SWITCH_INTR: + /* Nothing to do */ + break; + + default: + ia32_panic("task_switch: task switch type is invalid"); + break; + } + + /* store current task state in current TSS */ + if (!task16) { + cpu_memorywrite_d(cur_paddr + 32, CPU_EIP); + cpu_memorywrite_d(cur_paddr + 36, old_flags); + for (i = 0; i < CPU_REG_NUM; i++) { + cpu_memorywrite_d(cur_paddr + 40 + i * 4, + CPU_REGS_DWORD(i)); + } + for (i = 0; i < CPU_SEGREG_NUM; i++) { + cpu_memorywrite_w(cur_paddr + 72 + i * 4, + CPU_REGS_SREG(i)); + } + } else { + cpu_memorywrite_w(cur_paddr + 14, CPU_IP); + cpu_memorywrite_w(cur_paddr + 16, (UINT16)old_flags); + for (i = 0; i < CPU_REG_NUM; i++) { + cpu_memorywrite_w(cur_paddr + 18 + i * 2, + CPU_REGS_WORD(i)); + } + for (i = 0; i < CPU_SEGREG286_NUM; i++) { + cpu_memorywrite_w(cur_paddr + 34 + i * 2, + CPU_REGS_SREG(i)); + } + } + + /* set back link selector */ + switch (type) { + case TASK_SWITCH_CALL: + case TASK_SWITCH_INTR: + /* set back link selector */ + cpu_memorywrite_w(task_paddr, CPU_TR); + break; + + case TASK_SWITCH_IRET: + case TASK_SWITCH_JMP: + /* Nothing to do */ + break; + + default: + ia32_panic("task_switch: task switch type is invalid"); + break; + } + +#if defined(MORE_DEBUG) + VERBOSE(("task_switch: current task")); + for (i = 0; i < CPU_TR_LIMIT; i += 4) { + VERBOSE(("task_switch: 0x%08x: %08x", cur_base + i, + cpu_memoryread_d(cur_paddr + i))); + } +#endif + + /* Now task switching! */ + + /* if CALL, INTR, set EFLAGS image NT_FLAG */ + /* if CALL, INTR, JMP set busy flag */ + switch (type) { + case TASK_SWITCH_CALL: + case TASK_SWITCH_INTR: + /* set back link selector */ + new_flags |= NT_FLAG; + /*FALLTHROUGH*/ + case TASK_SWITCH_JMP: + set_task_busy(task_sel->selector); + break; + + case TASK_SWITCH_IRET: + /* check busy flag is active */ + if (SEG_IS_VALID(&task_sel->desc)) { + UINT32 h; + h = cpu_kmemoryread_d(task_sel->addr + 4); + if ((h & CPU_TSS_H_BUSY) == 0) { + ia32_panic("task_switch: new task is not busy"); + } + } + break; + + default: + ia32_panic("task_switch: task switch type is invalid"); + break; + } + + /* load task selector to CPU_TR */ + CPU_TR = task_sel->selector; + CPU_TR_DESC = task_sel->desc; + CPU_TR_DESC.type |= CPU_SYSDESC_TYPE_TSS_BUSY_IND; + + /* set CR0 image CPU_CR0_TS */ + CPU_CR0 |= CPU_CR0_TS; + + /* + * load task state (CR3, EIP, GPR, segregs, LDTR, EFLAGS) + */ + + /* set new CR3 */ + if (!task16 && CPU_STAT_PAGING) { + set_cr3(cr3); + } + + /* set new EIP, GPR, segregs */ + CPU_EIP = eip; + for (i = 0; i < CPU_REG_NUM; i++) { + CPU_REGS_DWORD(i) = regs[i]; + } + for (i = 0; i < CPU_SEGREG_NUM; i++) { + segdesc_init(i, sreg[i], &CPU_STAT_SREG(i)); + /* invalidate segreg descriptor */ + CPU_STAT_SREG(i).valid = 0; + } + + CPU_CLEAR_PREV_ESP(); + + /* load new LDTR */ + CPU_LDTR_DESC.valid = 0; + load_ldtr(ldtr, TS_EXCEPTION); + + /* I/O deny bitmap */ + CPU_STAT_IOLIMIT = 0; + if (!task16 && iobase != 0 && iobase < CPU_TR_DESC.u.seg.limit) { + CPU_STAT_IOLIMIT = (UINT16)(CPU_TR_DESC.u.seg.limit - iobase); + CPU_STAT_IOADDR = task_base + iobase; + } + VERBOSE(("task_switch: ioaddr = %08x, limit = %08x", CPU_STAT_IOADDR, + CPU_STAT_IOLIMIT)); + + /* set new EFLAGS */ + set_eflags(new_flags, I_FLAG|IOPL_FLAG|RF_FLAG|VM_FLAG|VIF_FLAG|VIP_FLAG); + + /* set new segment register */ + if (!CPU_STAT_VM86) { + /* load CS */ + rv = parse_selector(&cs_sel, sreg[CPU_CS_INDEX]); + if (rv < 0) { + VERBOSE(("task_switch: load CS failure (sel = 0x%04x, rv = %d)", sreg[CPU_CS_INDEX], rv)); + EXCEPTION(TS_EXCEPTION, cs_sel.idx); + } + + /* CS must be code segment */ + if (SEG_IS_SYSTEM(&cs_sel.desc) || SEG_IS_DATA(&cs_sel.desc)) { + EXCEPTION(TS_EXCEPTION, cs_sel.idx); + } + + /* check privilege level */ + if (!SEG_IS_CONFORMING_CODE(&cs_sel.desc)) { + /* non-confirming code segment */ + if (cs_sel.desc.dpl != cs_sel.rpl) { + EXCEPTION(TS_EXCEPTION, cs_sel.idx); + } + } else { + /* conforming code segment */ + if (cs_sel.desc.dpl > cs_sel.rpl) { + EXCEPTION(TS_EXCEPTION, cs_sel.idx); + } + } + + /* code segment is not present */ + rv = selector_is_not_present(&cs_sel); + if (rv < 0) { + EXCEPTION(NP_EXCEPTION, cs_sel.idx); + } + + /* load SS */ + rv = parse_selector(&ss_sel, sreg[CPU_SS_INDEX]); + if (rv < 0) { + VERBOSE(("task_switch: load SS failure (sel = 0x%04x, rv = %d)", sreg[CPU_SS_INDEX], rv)); + EXCEPTION(TS_EXCEPTION, ss_sel.idx); + } + + /* SS must be writable data segment */ + if (SEG_IS_SYSTEM(&ss_sel.desc) + || SEG_IS_CODE(&ss_sel.desc) + || !SEG_IS_WRITABLE_DATA(&ss_sel.desc)) { + EXCEPTION(TS_EXCEPTION, ss_sel.idx); + } + + /* check privilege level */ + if ((ss_sel.desc.dpl != cs_sel.rpl) + || (ss_sel.desc.dpl != ss_sel.rpl)) { + EXCEPTION(TS_EXCEPTION, ss_sel.idx); + } + + /* stack segment is not present */ + rv = selector_is_not_present(&ss_sel); + if (rv < 0) { + EXCEPTION(SS_EXCEPTION, ss_sel.idx); + } + + /* Now loading SS register */ + load_ss(ss_sel.selector, &ss_sel.desc, cs_sel.rpl); + + /* load ES, DS, FS, GS segment register */ + LOAD_SEGREG1(CPU_ES_INDEX, sreg[CPU_ES_INDEX], TS_EXCEPTION); + LOAD_SEGREG1(CPU_DS_INDEX, sreg[CPU_DS_INDEX], TS_EXCEPTION); + LOAD_SEGREG1(CPU_FS_INDEX, sreg[CPU_FS_INDEX], TS_EXCEPTION); + LOAD_SEGREG1(CPU_GS_INDEX, sreg[CPU_GS_INDEX], TS_EXCEPTION); + + /* Now loading CS register */ + load_cs(cs_sel.selector, &cs_sel.desc, cs_sel.rpl); + } + + VERBOSE(("task_switch: done.")); +} diff --git a/i386c/ia32/task.h b/i386c/ia32/task.h old mode 100755 new mode 100644 index 4f09224c..749859d0 --- a/i386c/ia32/task.h +++ b/i386c/ia32/task.h @@ -1,51 +1,51 @@ -/* - * Copyright (c) 2003 NONAKA Kimihiro - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#ifndef IA32_CPU_TASK_H__ -#define IA32_CPU_TASK_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -void CPUCALL load_tr(UINT16 selector); -void CPUCALL get_stack_pointer_from_tss(UINT pl, UINT16 *new_ss, UINT32 *new_esp); -UINT16 get_backlink_selector_from_tss(void); - -/* task_switch type */ -typedef enum { - TASK_SWITCH_JMP, - TASK_SWITCH_CALL, - TASK_SWITCH_IRET, - TASK_SWITCH_INTR -} task_switch_type_t; - -void CPUCALL task_switch(selector_t *selector, task_switch_type_t type); - -#ifdef __cplusplus -} -#endif - -#endif /* !IA32_CPU_TASK_H__ */ +/* + * Copyright (c) 2003 NONAKA Kimihiro + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#ifndef IA32_CPU_TASK_H__ +#define IA32_CPU_TASK_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void CPUCALL load_tr(UINT16 selector); +void CPUCALL get_stack_pointer_from_tss(UINT pl, UINT16 *new_ss, UINT32 *new_esp); +UINT16 get_backlink_selector_from_tss(void); + +/* task_switch type */ +typedef enum { + TASK_SWITCH_JMP, + TASK_SWITCH_CALL, + TASK_SWITCH_IRET, + TASK_SWITCH_INTR +} task_switch_type_t; + +void CPUCALL task_switch(selector_t *selector, task_switch_type_t type); + +#ifdef __cplusplus +} +#endif + +#endif /* !IA32_CPU_TASK_H__ */ diff --git a/i386hax/haxcore.c b/i386hax/haxcore.c index 02d53c52..be8d1aa3 100644 --- a/i386hax/haxcore.c +++ b/i386hax/haxcore.c @@ -1,1589 +1,1589 @@ -/* - * Copyright (c) 2019 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(SUPPORT_IA32_HAXM) - -#if 0 -#undef TRACEOUT -//#define USE_TRACEOUT_VS -#ifdef USE_TRACEOUT_VS -static void trace_fmt_ex(const char *fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#else -#define TRACEOUT(s) (void)(s) -#endif -#endif /* 1 */ -#include "haxfunc.h" -#include "haxcore.h" - -#if defined(_WINDOWS) -#include -#endif - -NP2_HAX np2hax = {0}; -NP2_HAX_STAT np2haxstat = {0}; -NP2_HAX_CORE np2haxcore = {0}; - -static void make_vm_str(OEMCHAR* buf, UINT32 vm_id){ - _stprintf(buf, OEMTEXT("¥¥¥¥.¥¥hax_vm%02d"), vm_id); -} -static void make_vcpu_str(OEMCHAR* buf, UINT32 vm_id, UINT32 vcpu_id){ - _stprintf(buf, OEMTEXT("¥¥¥¥.¥¥hax_vm%02d_vcpu%02d"), vm_id, vcpu_id); -} - -// HAXMが使えそうかチェック -UINT8 i386hax_check(void) { - -#if defined(_WIN32) - HAX_MODULE_VERSION haxver = {0}; - HAX_CAPINFO haxcap = {0}; - - // HAXMカーネルモードドライバを開く - np2hax.hDevice = CreateFile(OEMTEXT("¥¥¥¥.¥¥HAX"), - GENERIC_READ|GENERIC_WRITE, 0, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if (np2hax.hDevice == INVALID_HANDLE_VALUE) { - TRACEOUT(("HAXM: Failed to initialize the HAX device.")); - msgbox("HAXM check", "Failed to initialize the HAX device."); - np2hax.available = 0; - np2hax.hDevice = NULL; - return FAILURE; - } - - // HAXMバージョンを取得 - if(i386haxfunc_getversion(&haxver)==SUCCESS){ - char buf[256] = {0}; - TRACEOUT(("HAXM: HAX getversion: compatible version %d, current version %d", haxver.compat_version, haxver.current_version)); - //sprintf(buf, "HAXM: HAX getversion: compatible version %d, current version %d", haxver.compat_version, haxver.current_version); - //msgbox("HAXM check", buf); - //msgbox("HAXM init", "HAX getversion succeeded."); - }else{ - TRACEOUT(("HAXM: HAX getversion failed.")); - msgbox("HAXM check", "HAX getversion failed."); - goto initfailure; - } - - // HAXMで使える機能を調査 - if(i386haxfunc_getcapability(&haxcap)==SUCCESS){ - char buf[256] = {0}; - TRACEOUT(("HAXM: HAX getcapability: wstatus 0x%.4x, winfo 0x%.4x, win_refcount %d, mem_quota %d", haxcap.wstatus, haxcap.winfo, haxcap.win_refcount, haxcap.mem_quota)); - //sprintf(buf, "HAXM: HAX getcapability: wstatus 0x%.4x, winfo 0x%.4x, win_refcount %d, mem_quota %d", haxcap.wstatus, haxcap.winfo, haxcap.win_refcount, haxcap.mem_quota); - //msgbox("HAXM check", buf); - if(!(haxcap.wstatus & HAX_CAP_WORKSTATUS_MASK)){ - if(haxcap.winfo & HAX_CAP_FAILREASON_VT){ - msgbox("HAXM check", "Error: Intel VT-x is not supported by the host CPU."); - }else{ - msgbox("HAXM check", "Error: Intel Execute Disable Bit is not supported by the host CPU."); - } - goto initfailure; - } - if(!(haxcap.winfo & HAX_CAP_FASTMMIO)){ - msgbox("HAXM check", "Error: Fast MMIO is not supported. Please update HAXM."); - goto initfailure; - } - if(!(haxcap.winfo & HAX_CAP_DEBUG)){ - msgbox("HAXM check", "Error: Debugging function is not supported. Please update HAXM."); - goto initfailure; - } - //msgbox("HAXM init", "HAX getversion succeeded."); - }else{ - TRACEOUT(("HAXM: HAX getcapability failed.")); - msgbox("HAXM check", "HAX getcapability failed."); - goto initfailure; - } - - CloseHandle(np2hax.hDevice); - np2hax.hDevice = NULL; - - TRACEOUT(("HAXM: HAX available.")); - //msgbox("HAXM check", "HAX available."); - - np2hax.available = 1; - - return SUCCESS; - -initfailure: - CloseHandle(np2hax.hDevice); - np2hax.available = 0; - np2hax.enable = 0; - np2hax.hDevice = NULL; - return FAILURE; -#else - return 1; -#endif -} - -void i386hax_initialize(void) { - -#if defined(_WIN32) - if(!np2hax.available) return; - if(!np2hax.enable) return; - - i386hax_deinitialize(); - - // HAXMカーネルモードドライバを開く - np2hax.hDevice = CreateFile(OEMTEXT("¥¥¥¥.¥¥HAX"), - GENERIC_READ|GENERIC_WRITE, 0, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if (np2hax.hDevice == INVALID_HANDLE_VALUE) { - TRACEOUT(("HAXM: Failed to initialize the HAX device.")); - return; - } - - TRACEOUT(("HAXM: HAX initialized.")); - //msgbox("HAXM init", "HAX initialized."); - - return; - -error1: - CloseHandle(np2hax.hDevice); - np2hax.hDevice = NULL; - return; -#endif -} - -void i386hax_createVM(void) { - -#if defined(_WIN32) - OEMCHAR vm_str[64] = {0}; - OEMCHAR vcpu_str[64] = {0}; - HAX_DEBUG hax_dbg = {0}; - HAX_QEMU_VERSION hax_qemu_ver = {0}; - - if(!np2hax.available) return; - if(!np2hax.enable) return; - if(!np2hax.hDevice) return; - - i386hax_disposeVM(); - - // HAXM仮想マシンを作成 - if(i386haxfunc_createVM(&np2hax.vm_id)==FAILURE){ - TRACEOUT(("HAXM: HAX create VM failed.")); - msgbox("HAXM VM", "HAX create VM failed."); - return; - } - - make_vm_str(vm_str, np2hax.vm_id); - - // HAXM仮想マシンを開く - np2hax.hVMDevice = CreateFile(vm_str, - GENERIC_READ|GENERIC_WRITE, 0, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if (np2hax.hVMDevice == INVALID_HANDLE_VALUE) { - TRACEOUT(("HAXM: Failed to initialize the HAX VM device.")); - return; - } - - // あまり意味なし? - //hax_qemu_ver.cur_version = 0x0; - //if(i386haxfunc_notifyQEMUversion(&hax_qemu_ver)==FAILURE){ - // TRACEOUT(("HAXM: HAX notify QEMU version failed.")); - // msgbox("HAXM VM", "HAX notify QEMU version failed."); - // goto error2; - //} - - // 仮想CPUを作成 - if(i386haxfunc_VCPUcreate(0)==FAILURE){ - TRACEOUT(("HAXM: HAX create VCPU failed.")); - msgbox("HAXM VM", "HAX create VCPU failed."); - goto error2; - } - - make_vcpu_str(vcpu_str, np2hax.vm_id, 0); - - // 仮想CPUを開く - np2hax.hVCPUDevice = CreateFile(vcpu_str, - GENERIC_READ|GENERIC_WRITE, 0, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - if (np2hax.hVCPUDevice == INVALID_HANDLE_VALUE) { - TRACEOUT(("HAXM: Failed to initialize the HAX VCPU device.")); - goto error2; - } - - // 仮想CPUとデータをやりとりするのための場所を確保 - if(i386haxfunc_vcpu_setup_tunnel(&np2hax.tunnel)==FAILURE){ - TRACEOUT(("HAXM: HAX VCPU setup tunnel failed.")); - msgbox("HAXM VM", "HAX VCPU setup tunnel failed."); - goto error2; - } - - //// デバッグ機能を有効にする(HAX_DEBUG_USE_SW_BPは仮想マシンがINT3 CChを呼ぶと無条件で仮想マシンモニタに移行できる) - //np2hax.bioshookenable = 1; - //hax_dbg.control = HAX_DEBUG_ENABLE|HAX_DEBUG_USE_SW_BP;//|HAX_DEBUG_USE_HW_BP|HAX_DEBUG_STEP; - //if(i386haxfunc_vcpu_debug(&hax_dbg)==FAILURE){ - // TRACEOUT(("HAXM: HAX VCPU debug setting failed.")); - // msgbox("HAXM VM", "HAX VCPU debug setting failed."); - // goto error2; - //} - np2hax.bioshookenable = 0; // もう使用しなくなった np21w ver0.86 rev95 - - TRACEOUT(("HAXM: HAX VM initialized.")); - //msgbox("HAXM VM", "HAX VM initialized."); - - memset(&np2haxcore, 0, sizeof(np2haxcore)); - - // デフォルトのレジスタ設定を覚えておく - i386haxfunc_vcpu_getREGs(&np2haxstat.state); - i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); - memcpy(&np2haxstat.default_state, &np2haxstat.state, sizeof(np2haxstat.state)); - memcpy(&np2haxstat.default_fpustate, &np2haxstat.fpustate, sizeof(np2haxstat.fpustate)); - - np2hax.emumode = 0; - - return; - -error3: - CloseHandle(np2hax.hVCPUDevice); - np2hax.hVCPUDevice = NULL; -error2: - CloseHandle(np2hax.hVMDevice); - np2hax.hVMDevice = NULL; -error1: - return; -#endif -} - -void i386hax_resetVMMem(void) { - - // メモリ周りの初期設定 - np2haxcore.lastA20en = (CPU_ADRSMASK != 0x000fffff); - i386hax_vm_sethmemory(np2haxcore.lastA20en); - np2haxcore.lastITFbank = CPU_ITFBANK; - i386hax_vm_setitfmemory(np2haxcore.lastITFbank); - np2haxcore.lastVGA256linear = (vramop.mio2[0x2]==0x1); - i386hax_vm_setvga256linearmemory(); - np2haxcore.lastVRAMMMIO = 1; - - i386hax_vm_setmemoryarea(mem+0xA5000, 0xA5000, 0x3000); - //i386hax_vm_setmemoryarea(mem+0xA8000, 0xA8000, 0x8000); - //i386hax_vm_setmemoryarea(mem+0xB0000, 0xB0000, 0x10000); - //i386hax_vm_setmemoryarea(mem+0xC0000, 0xC0000, 0x10000); - i386hax_vm_setmemoryarea(mem+0xD0000, 0xD0000, 0x10000); - //i386hax_vm_setmemoryarea(mem+0xE0000, 0xE0000, 0x8000); - i386hax_vm_setmemoryarea(mem+0xE8000, 0xE8000, 0x8000); - i386hax_vm_setmemoryarea(mem+0xF0000, 0xF0000, 0x8000); - i386hax_vm_setmemoryarea(mem+0xF8000, 0xF8000, 0x8000); - - //i386hax_vm_setmemoryarea(mem+0xA5000, 0xA5000, 0x3000); - //i386hax_vm_setmemoryarea(mem+0xA8000, 0xA8000, 0x8000); - //i386hax_vm_setmemoryarea(mem+0xB0000, 0xB0000, 0x10000); - //i386hax_vm_setmemoryarea(mem+0xC0000, 0xC0000, 0x10000); - //i386hax_vm_setmemoryarea(mem+0xD0000, 0xD0000, 0x10000); - //i386hax_vm_setmemoryarea(mem+0xE0000, 0xE0000, 0x8000); - //i386hax_vm_setmemoryarea(mem+0xE8000, 0xE8000, 0x8000); - //i386hax_vm_setmemoryarea(mem+0xF0000, 0xF0000, 0x8000); -} - -void i386hax_resetVMCPU(void) { - - // CPU周りの初期設定 - np2haxstat.irq_reqidx_cur = np2haxstat.irq_reqidx_end = 0; - - memcpy(&np2haxstat.state, &np2haxstat.default_state, sizeof(np2haxstat.state)); - memcpy(&np2haxstat.fpustate, &np2haxstat.default_fpustate, sizeof(np2haxstat.fpustate)); - - np2haxstat.update_regs = np2haxstat.update_fpu = 1; - np2haxstat.update_segment_regs = 1; - - np2haxcore.clockpersec = GetTickCounter_ClockPerSec(); - np2haxcore.lastclock = GetTickCounter_Clock(); - np2haxcore.clockcount = GetTickCounter_Clock(); -} - -/* - * bios call interface (HAXM) - */ -static int -ia32hax_bioscall(void) -{ - UINT32 adrs; - int ret = 0; - - if (!CPU_STAT_PM || CPU_STAT_VM86) { -#if 1 - adrs = CPU_PREV_EIP + (CPU_CS << 4); -#else - adrs = CPU_PREV_EIP + CPU_STAT_CS_BASE; -#endif - if ((adrs >= 0xf8000) && (adrs < 0x100000)) { - if (biosfunc(adrs)) { - /* Nothing to do */ - } - LOAD_SEGREG(CPU_ES_INDEX, CPU_ES); - LOAD_SEGREG(CPU_CS_INDEX, CPU_CS); - LOAD_SEGREG(CPU_SS_INDEX, CPU_SS); - LOAD_SEGREG(CPU_DS_INDEX, CPU_DS); - ret = 1; - } - } - return ret; -} - -#define TSS_16_SIZE 44 -#define TSS_16_LIMIT (TSS_16_SIZE - 1) -#define TSS_32_SIZE 104 -#define TSS_32_LIMIT (TSS_32_SIZE - 1) - -static void CPUCALL -ia32hax_setHAXtoNP2IOADDR() -{ - UINT16 iobase; - - if (CPU_STAT_PM && !CPU_STAT_VM86) { - /* check descriptor type & stack room size */ - switch (CPU_TR_DESC.type) { - case CPU_SYSDESC_TYPE_TSS_16: - case CPU_SYSDESC_TYPE_TSS_BUSY_16: - if (CPU_TR_DESC.u.seg.limit < TSS_16_LIMIT) { - return; - } - iobase = 0; - break; - - case CPU_SYSDESC_TYPE_TSS_32: - case CPU_SYSDESC_TYPE_TSS_BUSY_32: - if (CPU_TR_DESC.u.seg.limit < TSS_32_LIMIT) { - return; - } - iobase = cpu_kmemoryread_w(CPU_TR_DESC.u.seg.segbase + 102); - //return; - break; - - default: - return; - } - - /* I/O deny bitmap */ - CPU_STAT_IOLIMIT = 0; - if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_32) { - if (iobase < CPU_TR_LIMIT) { - CPU_STAT_IOLIMIT = (UINT16)(CPU_TR_LIMIT - iobase); - CPU_STAT_IOADDR = CPU_TR_BASE + iobase; - } - } - } -} - -// HAXレジスタ → NP2 IA-32 レジスタ -void -ia32hax_copyregHAXtoNP2(void) -{ - CPU_EAX = np2haxstat.state._eax; - CPU_EBX = np2haxstat.state._ebx; - CPU_ECX = np2haxstat.state._ecx; - CPU_EDX = np2haxstat.state._edx; - - CPU_ESI = np2haxstat.state._esi; - CPU_EDI = np2haxstat.state._edi; - - CPU_CS = np2haxstat.state._cs.selector; - CPU_DS = np2haxstat.state._ds.selector; - CPU_ES = np2haxstat.state._es.selector; - CPU_SS = np2haxstat.state._ss.selector; - CPU_FS = np2haxstat.state._fs.selector; - CPU_GS = np2haxstat.state._gs.selector; - CS_BASE = np2haxstat.state._cs.base; - DS_BASE = np2haxstat.state._ds.base; - ES_BASE = np2haxstat.state._es.base; - SS_BASE = np2haxstat.state._ss.base; - FS_BASE = np2haxstat.state._fs.base; - GS_BASE = np2haxstat.state._gs.base; - - CPU_CS_DESC.u.seg.limit = np2haxstat.state._cs.limit; - CPU_CS_DESC.flag = np2haxstat.state._cs.type; - CPU_CS_DESC.s = np2haxstat.state._cs.desc; - CPU_CS_DESC.dpl = np2haxstat.state._cs.dpl; - CPU_CS_DESC.rpl = np2haxstat.state._cs.selector & 0x3; - CPU_CS_DESC.p = np2haxstat.state._cs.available; - CPU_CS_DESC.valid = np2haxstat.state._cs.present; - CPU_CS_DESC.d = np2haxstat.state._cs.operand_size; - CPU_CS_DESC.u.seg.g = np2haxstat.state._cs.granularity; - - CPU_DS_DESC.u.seg.limit = np2haxstat.state._ds.limit; - CPU_DS_DESC.flag = np2haxstat.state._ds.type; - CPU_DS_DESC.s = np2haxstat.state._ds.desc; - CPU_DS_DESC.dpl = np2haxstat.state._ds.dpl; - CPU_DS_DESC.rpl = np2haxstat.state._ds.selector & 0x3; - CPU_DS_DESC.p = np2haxstat.state._ds.available; - CPU_DS_DESC.valid = np2haxstat.state._ds.present; - CPU_DS_DESC.d = np2haxstat.state._ds.operand_size; - CPU_DS_DESC.u.seg.g = np2haxstat.state._ds.granularity; - - CPU_ES_DESC.u.seg.limit = np2haxstat.state._es.limit; - CPU_ES_DESC.flag = np2haxstat.state._es.type; - CPU_ES_DESC.s = np2haxstat.state._es.desc; - CPU_ES_DESC.dpl = np2haxstat.state._es.dpl; - CPU_ES_DESC.rpl = np2haxstat.state._es.selector & 0x3; - CPU_ES_DESC.p = np2haxstat.state._es.available; - CPU_ES_DESC.valid = np2haxstat.state._es.present; - CPU_ES_DESC.d = np2haxstat.state._es.operand_size; - CPU_ES_DESC.u.seg.g = np2haxstat.state._es.granularity; - - CPU_SS_DESC.u.seg.limit = np2haxstat.state._ss.limit; - CPU_SS_DESC.flag = np2haxstat.state._ss.type; - CPU_SS_DESC.s = np2haxstat.state._ss.desc; - CPU_SS_DESC.dpl = np2haxstat.state._ss.dpl; - CPU_SS_DESC.rpl = np2haxstat.state._ss.selector & 0x3; - CPU_SS_DESC.p = np2haxstat.state._ss.available; - CPU_SS_DESC.valid = np2haxstat.state._ss.present; - CPU_SS_DESC.d = np2haxstat.state._ss.operand_size; - CPU_SS_DESC.u.seg.g = np2haxstat.state._ss.granularity; - - CPU_FS_DESC.u.seg.limit = np2haxstat.state._fs.limit; - CPU_FS_DESC.flag = np2haxstat.state._fs.type; - CPU_FS_DESC.s = np2haxstat.state._fs.desc; - CPU_FS_DESC.dpl = np2haxstat.state._fs.dpl; - CPU_FS_DESC.rpl = np2haxstat.state._fs.selector & 0x3; - CPU_FS_DESC.p = np2haxstat.state._fs.available; - CPU_FS_DESC.valid = np2haxstat.state._fs.present; - CPU_FS_DESC.d = np2haxstat.state._fs.operand_size; - CPU_FS_DESC.u.seg.g = np2haxstat.state._fs.granularity; - - CPU_GS_DESC.u.seg.limit = np2haxstat.state._gs.limit; - CPU_GS_DESC.flag = np2haxstat.state._gs.type; - CPU_GS_DESC.s = np2haxstat.state._gs.desc; - CPU_GS_DESC.dpl = np2haxstat.state._gs.dpl; - CPU_GS_DESC.rpl = np2haxstat.state._gs.selector & 0x3; - CPU_GS_DESC.p = np2haxstat.state._gs.available; - CPU_GS_DESC.valid = np2haxstat.state._gs.present; - CPU_GS_DESC.d = np2haxstat.state._gs.operand_size; - CPU_GS_DESC.u.seg.g = np2haxstat.state._gs.granularity; - - CPU_EBP = np2haxstat.state._ebp; - CPU_ESP = np2haxstat.state._esp; - CPU_EIP = np2haxstat.state._eip; - CPU_PREV_EIP = np2haxstat.state._eip; // XXX: あんまり良くない - - CPU_EFLAG = np2haxstat.state._eflags; - - CPU_CR0 = np2haxstat.state._cr0; - //CPU_CR1 = np2haxstat.state._cr1; - CPU_CR2 = np2haxstat.state._cr2; - CPU_CR3 = np2haxstat.state._cr3; - CPU_CR4 = np2haxstat.state._cr4; - - CPU_GDTR_BASE = np2haxstat.state._gdt.base; - CPU_GDTR_LIMIT = np2haxstat.state._gdt.limit; - CPU_IDTR_BASE = np2haxstat.state._idt.base; - CPU_IDTR_LIMIT = np2haxstat.state._idt.limit; - CPU_LDTR = np2haxstat.state._ldt.selector; - CPU_LDTR_BASE = np2haxstat.state._ldt.base; - CPU_LDTR_LIMIT = np2haxstat.state._ldt.limit; - CPU_LDTR_DESC.flag = np2haxstat.state._ldt.type; - CPU_LDTR_DESC.s = np2haxstat.state._ldt.desc; - CPU_LDTR_DESC.dpl = np2haxstat.state._ldt.dpl; - CPU_LDTR_DESC.p = np2haxstat.state._ldt.available; - CPU_LDTR_DESC.valid = np2haxstat.state._ldt.present; - CPU_LDTR_DESC.d = np2haxstat.state._ldt.operand_size; - CPU_LDTR_DESC.u.seg.g = np2haxstat.state._ldt.granularity; - CPU_TR = np2haxstat.state._tr.selector; - CPU_TR_BASE = np2haxstat.state._tr.base; - CPU_TR_LIMIT = np2haxstat.state._tr.limit; - CPU_TR_DESC.flag = np2haxstat.state._tr.type; - CPU_TR_DESC.s = np2haxstat.state._tr.desc; - CPU_TR_DESC.dpl = np2haxstat.state._tr.dpl; - CPU_TR_DESC.p = np2haxstat.state._tr.available; - CPU_TR_DESC.valid = np2haxstat.state._tr.present; - CPU_TR_DESC.d = np2haxstat.state._tr.operand_size; - CPU_TR_DESC.u.seg.segbase = np2haxstat.state._tr.base; - CPU_TR_DESC.u.seg.limit = np2haxstat.state._tr.limit; - CPU_TR_DESC.u.seg.c = 0; - CPU_TR_DESC.u.seg.g = np2haxstat.state._tr.granularity; - - CPU_DR(0) = np2haxstat.state._dr0; - CPU_DR(1) = np2haxstat.state._dr1; - CPU_DR(2) = np2haxstat.state._dr2; - CPU_DR(3) = np2haxstat.state._dr3; - //CPU_DR(4) = np2haxstat.state._dr4; - //CPU_DR(5) = np2haxstat.state._dr5; - CPU_DR(6) = np2haxstat.state._dr6; - CPU_DR(7) = np2haxstat.state._dr7; - - CPU_STAT_PM = (np2haxstat.state._cr0 & 0x1) != 0; - CPU_STAT_PAGING = (CPU_CR0 & CPU_CR0_PG) != 0; - CPU_STAT_VM86 = (np2haxstat.state._eflags & VM_FLAG) != 0; - CPU_STAT_WP = (CPU_CR0 & CPU_CR0_WP) ? 0x10 : 0; - CPU_STAT_CPL = (UINT8)CPU_CS_DESC.rpl; - CPU_STAT_USER_MODE = (CPU_CS_DESC.rpl == 3) ? CPU_MODE_USER : CPU_MODE_SUPERVISER; - CPU_STAT_PDE_BASE = CPU_CR3 & CPU_CR3_PD_MASK; - //CPU_STAT_PDE_BASE = np2haxstat.state._pde; - - CPU_OV = CPU_FLAG & O_FLAG; - CPU_TRAP = (CPU_FLAG & (I_FLAG | T_FLAG)) == (I_FLAG | T_FLAG); - CPU_INST_OP32 = CPU_INST_AS32 = - CPU_STATSAVE.cpu_inst_default.op_32 = - CPU_STATSAVE.cpu_inst_default.as_32 = CPU_CS_DESC.d; -#if defined(USE_CPU_EIPMASK) - CPU_EIPMASK = CPU_STATSAVE.cpu_inst_default.op_32 ? 0xffffffff : 0xffff; -#endif - CPU_STAT_SS32 = CPU_SS_DESC.d; - - ia32hax_setHAXtoNP2IOADDR(); - -} -// NP2 IA-32 レジスタ → HAXレジスタ -void -ia32hax_copyregNP2toHAX(void) -{ - np2haxstat.state._eax = CPU_EAX; - np2haxstat.state._ebx = CPU_EBX; - np2haxstat.state._ecx = CPU_ECX; - np2haxstat.state._edx = CPU_EDX; - - np2haxstat.state._esi = CPU_ESI; - np2haxstat.state._edi = CPU_EDI; - - if (1 || np2haxstat.update_segment_regs) - { - np2haxstat.state._cs.selector = CPU_CS; - np2haxstat.state._ds.selector = CPU_DS; - np2haxstat.state._es.selector = CPU_ES; - np2haxstat.state._ss.selector = CPU_SS; - np2haxstat.state._fs.selector = CPU_FS; - np2haxstat.state._gs.selector = CPU_GS; - np2haxstat.state._cs.base = CS_BASE; - np2haxstat.state._ds.base = DS_BASE; - np2haxstat.state._es.base = ES_BASE; - np2haxstat.state._ss.base = SS_BASE; - np2haxstat.state._fs.base = FS_BASE; - np2haxstat.state._gs.base = GS_BASE; - - np2haxstat.state._cs.base = CPU_CS_DESC.u.seg.segbase; - np2haxstat.state._cs.limit = CPU_CS_DESC.u.seg.limit; - np2haxstat.state._cs.type = CPU_CS_DESC.flag; - np2haxstat.state._cs.desc = CPU_CS_DESC.s; - np2haxstat.state._cs.dpl = CPU_CS_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._cs.selector = (np2haxstat.state._cs.selector & ‾0x3) | CPU_CS_DESC.rpl; - np2haxstat.state._cs.present = CPU_CS_DESC.valid; - np2haxstat.state._cs.available = CPU_CS_DESC.p; - np2haxstat.state._cs.operand_size = CPU_CS_DESC.d; - np2haxstat.state._cs.granularity = CPU_CS_DESC.u.seg.g; - - np2haxstat.state._ds.base = CPU_DS_DESC.u.seg.segbase; - np2haxstat.state._ds.limit = CPU_DS_DESC.u.seg.limit; - np2haxstat.state._ds.type = CPU_DS_DESC.flag; - np2haxstat.state._ds.desc = CPU_DS_DESC.s; - np2haxstat.state._ds.dpl = CPU_DS_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._ds.selector = (np2haxstat.state._ds.selector & ‾0x3) | CPU_CS_DESC.rpl; - np2haxstat.state._ds.present = CPU_DS_DESC.valid; - np2haxstat.state._ds.available = CPU_DS_DESC.p; - np2haxstat.state._ds.operand_size = CPU_DS_DESC.d; - np2haxstat.state._ds.granularity = CPU_DS_DESC.u.seg.g; - - np2haxstat.state._es.base = CPU_ES_DESC.u.seg.segbase; - np2haxstat.state._es.limit = CPU_ES_DESC.u.seg.limit; - np2haxstat.state._es.type = CPU_ES_DESC.flag; - np2haxstat.state._es.desc = CPU_ES_DESC.s; - np2haxstat.state._es.dpl = CPU_ES_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._es.selector = (np2haxstat.state._es.selector & ‾0x3) | CPU_CS_DESC.rpl; - np2haxstat.state._es.present = CPU_ES_DESC.valid; - np2haxstat.state._es.available = CPU_ES_DESC.p; - np2haxstat.state._es.operand_size = CPU_ES_DESC.d; - np2haxstat.state._es.granularity = CPU_ES_DESC.u.seg.g; - - np2haxstat.state._ss.base = CPU_SS_DESC.u.seg.segbase; - np2haxstat.state._ss.limit = CPU_SS_DESC.u.seg.limit; - np2haxstat.state._ss.type = CPU_SS_DESC.flag; - np2haxstat.state._ss.desc = CPU_SS_DESC.s; - np2haxstat.state._ss.dpl = CPU_SS_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._ss.selector = (np2haxstat.state._ss.selector & ‾0x3) | CPU_CS_DESC.rpl; - np2haxstat.state._ss.present = CPU_SS_DESC.valid; - np2haxstat.state._ss.available = CPU_SS_DESC.p; - np2haxstat.state._ss.operand_size = CPU_SS_DESC.d; - np2haxstat.state._ss.granularity = CPU_SS_DESC.u.seg.g; - - np2haxstat.state._fs.base = CPU_FS_DESC.u.seg.segbase; - np2haxstat.state._fs.limit = CPU_FS_DESC.u.seg.limit; - np2haxstat.state._fs.type = CPU_FS_DESC.flag; - np2haxstat.state._fs.desc = CPU_FS_DESC.s; - np2haxstat.state._fs.dpl = CPU_FS_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._fs.selector = (np2haxstat.state._fs.selector & ‾0x3) | CPU_CS_DESC.rpl; - np2haxstat.state._fs.present = CPU_FS_DESC.valid; - np2haxstat.state._fs.available = CPU_FS_DESC.p; - np2haxstat.state._fs.operand_size = CPU_FS_DESC.d; - np2haxstat.state._fs.granularity = CPU_FS_DESC.u.seg.g; - - np2haxstat.state._gs.base = CPU_GS_DESC.u.seg.segbase; - np2haxstat.state._gs.limit = CPU_GS_DESC.u.seg.limit; - np2haxstat.state._gs.type = CPU_GS_DESC.flag; - np2haxstat.state._gs.desc = CPU_GS_DESC.s; - np2haxstat.state._gs.dpl = CPU_GS_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._gs.selector = (np2haxstat.state._gs.selector & ‾0x3) | CPU_CS_DESC.rpl; - np2haxstat.state._gs.present = CPU_GS_DESC.valid; - np2haxstat.state._gs.available = CPU_GS_DESC.p; - np2haxstat.state._gs.operand_size = CPU_GS_DESC.d; - np2haxstat.state._gs.granularity = CPU_GS_DESC.u.seg.g; - - np2haxstat.update_segment_regs = 0; - } - - np2haxstat.state._ebp = CPU_EBP; - np2haxstat.state._esp = CPU_ESP; - np2haxstat.state._eip = CPU_EIP; - - np2haxstat.state._eflags = CPU_EFLAG; - - np2haxstat.state._cr0 = CPU_CR0; - //np2haxstat.state._cr1 = CPU_CR1; - np2haxstat.state._cr2 = CPU_CR2; - np2haxstat.state._cr3 = CPU_CR3; - np2haxstat.state._cr4 = CPU_CR4; - - np2haxstat.state._gdt.base = CPU_GDTR_BASE; - np2haxstat.state._gdt.limit = CPU_GDTR_LIMIT; - np2haxstat.state._idt.base = CPU_IDTR_BASE; - np2haxstat.state._idt.limit = CPU_IDTR_LIMIT; - np2haxstat.state._ldt.selector = CPU_LDTR; - np2haxstat.state._ldt.base = CPU_LDTR_BASE; - np2haxstat.state._ldt.limit = CPU_LDTR_LIMIT; - np2haxstat.state._ldt.type = CPU_LDTR_DESC.flag; - np2haxstat.state._ldt.desc = CPU_LDTR_DESC.s; - np2haxstat.state._ldt.dpl = CPU_LDTR_DESC.dpl; - //np2haxstat.state._ldt.present = CPU_LDTR_DESC.valid; - np2haxstat.state._ldt.available = CPU_LDTR_DESC.p; - np2haxstat.state._ldt.operand_size = CPU_LDTR_DESC.d; - np2haxstat.state._ldt.granularity = CPU_LDTR_DESC.u.seg.g; - np2haxstat.state._tr.selector = CPU_TR; - np2haxstat.state._tr.base = CPU_TR_BASE; - np2haxstat.state._tr.limit = CPU_TR_LIMIT; - np2haxstat.state._tr.type = CPU_TR_DESC.flag; - np2haxstat.state._tr.desc = CPU_TR_DESC.s; - np2haxstat.state._tr.dpl = CPU_TR_DESC.dpl; - //np2haxstat.state._tr.present = CPU_TR_DESC.valid; - np2haxstat.state._tr.available = CPU_TR_DESC.p; - np2haxstat.state._tr.operand_size = CPU_TR_DESC.d; - np2haxstat.state._tr.granularity = CPU_TR_DESC.u.seg.g; - - //np2haxstat.state._tr.base = CPU_TR_DESC.u.seg.segbase; - //np2haxstat.state._tr.limit = CPU_TR_DESC.u.seg.limit; - - np2haxstat.state._dr0 = CPU_DR(0); - np2haxstat.state._dr1 = CPU_DR(1); - np2haxstat.state._dr2 = CPU_DR(2); - np2haxstat.state._dr3 = CPU_DR(3); - //np2haxstat.state._dr4 = CPU_DR(4); - //np2haxstat.state._dr5 = CPU_DR(5); - np2haxstat.state._dr6 = CPU_DR(6); - np2haxstat.state._dr7 = CPU_DR(7); - - np2haxstat.state._pde = CPU_STAT_PDE_BASE; -} - -// 仮想マシン実行 -void i386hax_vm_exec_part(void) { - HAX_TUNNEL *tunnel; - UINT8 *iobuf; - UINT32 exitstatus; - UINT32 addr; - SINT32 oldremclock; -#define PMCOUNTER_THRESHOLD 200000 - static UINT32 pmcounter = 0; - static int restoreCounter = 0; - - np2haxcore.running = 1; - - if(np2hax.emumode){ - OEMCHAR vm_str[64] = {0}; - OEMCHAR vcpu_str[64] = {0}; - NP2_HAX_CORE tmphax; - - if(restoreCounter > 0){ - restoreCounter--; - if (!(CPU_TYPE & CPUTYPE_V30)) { - CPU_EXEC(); - } - else { - CPU_EXECV30(); - } - np2haxstat.update_regs = 1; - np2haxstat.update_fpu = 1; - - np2haxcore.running = 0; - return; - } - - memcpy(&tmphax, &np2haxcore, sizeof(np2haxcore)); - - i386hax_createVM(); - - memcpy(&np2haxcore, &tmphax, sizeof(np2haxcore)); - - i386hax_resetVMCPU(); - - memcpy(&np2haxstat.state, &np2haxstat.default_state, sizeof(np2haxstat.state)); - memcpy(&np2haxstat.fpustate, &np2haxstat.default_fpustate, sizeof(np2haxstat.fpustate)); - - // HAXレジスタを更新 - ia32hax_copyregNP2toHAX(); - i386haxfunc_vcpu_setREGs(&np2haxstat.state); - i386haxfunc_vcpu_setFPU(&np2haxstat.fpustate); - //i386hax_disposeVM(); - // - //// HAXM仮想マシンを開く - //make_vm_str(vm_str, np2hax.vm_id); - //np2hax.hVMDevice = CreateFile(vm_str, - // GENERIC_READ|GENERIC_WRITE, 0, NULL, - // CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - //if (np2hax.hVMDevice == INVALID_HANDLE_VALUE) { - // TRACEOUT(("HAXM: Failed to initialize the HAX VM device.")); - // return; - //} - - //// 仮想CPUを開く - //make_vcpu_str(vcpu_str, np2hax.vm_id, 0); - //np2hax.hVCPUDevice = CreateFile(vcpu_str, - // GENERIC_READ|GENERIC_WRITE, 0, NULL, - // CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - //if (np2hax.hVCPUDevice == INVALID_HANDLE_VALUE) { - // TRACEOUT(("HAXM: Failed to initialize the HAX VCPU device.")); - //} - - // 仮想CPUとデータをやりとりするのための場所を確保 - if(i386haxfunc_vcpu_setup_tunnel(&np2hax.tunnel)==FAILURE){ - TRACEOUT(("HAXM: HAX VCPU setup tunnel failed.")); - } - i386hax_vm_allocmemory(); - if(np2hax.hVMDevice){ - i386hax_vm_setmemory(); - i386hax_vm_setbankmemory(); - i386hax_vm_setextmemory(); - i386haxfunc_vcpu_setREGs(&np2haxstat.state); - i386haxfunc_vcpu_setFPU(&np2haxstat.fpustate); - { - HAX_MSR_DATA msrstate_set = {0}; - i386haxfunc_vcpu_setMSRs(&np2haxstat.msrstate, &msrstate_set); - } - i386hax_vm_sethmemory(CPU_ADRSMASK != 0x000fffff); - i386hax_vm_setitfmemory(CPU_ITFBANK); - i386hax_vm_setvga256linearmemory(); - - i386hax_vm_setmemoryarea(mem+0xA5000, 0xA5000, 0x3000); - //i386hax_vm_setmemoryarea(mem+0xA8000, 0xA8000, 0x8000); - //i386hax_vm_setmemoryarea(mem+0xB0000, 0xB0000, 0x10000); - //i386hax_vm_setmemoryarea(mem+0xC0000, 0xC0000, 0x10000); - i386hax_vm_setmemoryarea(mem+0xD0000, 0xD0000, 0x10000); - //i386hax_vm_setmemoryarea(mem+0xE0000, 0xE0000, 0x8000); - i386hax_vm_setmemoryarea(mem+0xE8000, 0xE8000, 0x8000); - i386hax_vm_setmemoryarea(mem+0xF0000, 0xF0000, 0x8000); - - np2hax.emumode = 0; - } - } - - // XXX: 変なアドレスにぶっ飛ぶのを回避 - switch (sigsetjmp(exec_1step_jmpbuf, 1)) - { - case 0: - break; - - case 1: - VERBOSE(("ia32: return from exception")); - break; - - case 2: - VERBOSE(("ia32: return from panic")); - return; - - default: - VERBOSE(("ia32: return from unknown cause")); - break; - } - - // HAXMとのデータやりとり用 - tunnel = (HAX_TUNNEL*)np2hax.tunnel.va; - iobuf = (UINT8*)np2hax.tunnel.io_va; - - // 猫レジスタをHAXレジスタにコピー - ia32hax_copyregNP2toHAX(); - - // 必要ならHAXレジスタを更新 - if(np2haxstat.update_regs) i386haxfunc_vcpu_setREGs(&np2haxstat.state); - if(np2haxstat.update_fpu) i386haxfunc_vcpu_setFPU(&np2haxstat.fpustate); - - np2haxcore.hltflag = 0; - -coutinue_cpu: - // メモリ絡みの構成が変わっていたら変える - if(np2haxcore.lastA20en != (CPU_ADRSMASK != 0x000fffff)){ - i386hax_vm_sethmemory(CPU_ADRSMASK != 0x000fffff); - np2haxcore.lastA20en = (CPU_ADRSMASK != 0x000fffff); - } - if(np2haxcore.lastITFbank != CPU_ITFBANK){ - i386hax_vm_sethmemory(CPU_ADRSMASK != 0x000fffff); - i386hax_vm_setitfmemory(CPU_ITFBANK); - np2haxcore.lastITFbank = CPU_ITFBANK; - } - if(np2haxcore.lastVGA256linear != (vramop.mio2[0x2]==0x1 && (gdc.analog & (1 << GDCANALOG_256))!=0)){ - i386hax_vm_setvga256linearmemory(); - np2haxcore.lastVGA256linear = (vramop.mio2[0x2]==0x1 && (gdc.analog & (1 << GDCANALOG_256))!=0); - } - - // 割り込みを処理 - if(np2haxstat.irq_reqidx_cur != np2haxstat.irq_reqidx_end){ - if (tunnel->ready_for_interrupt_injection) { // 割り込み準備OK? - i386haxfunc_vcpu_interrupt(np2haxstat.irq_req[np2haxstat.irq_reqidx_cur]); - np2haxstat.irq_reqidx_cur++; - } - } - if(np2haxstat.irq_reqidx_cur != np2haxstat.irq_reqidx_end){ // 割り込みが必要ならrequest_interrupt_windowを1にする - tunnel->request_interrupt_window = 1; - }else{ - tunnel->request_interrupt_window = 0; - } - - // リセット可能フラグをクリア - np2haxcore.ready_for_reset = 0; - -coutinue_cpu_imm: - // HAXM CPU実行 - if(np2hax.emumode){ - tunnel->_exit_status = HAX_EXIT_STATECHANGE; - }else{ - i386haxfunc_vcpu_run(); - } - - // 実行停止理由を取得 - exitstatus = tunnel->_exit_status; - - // CPU実行再開のための処理(高速処理が要るもの) - switch (exitstatus) { - case HAX_EXIT_IO: // I/Oポートへのアクセス - //printf("HAX_EXIT_IO¥n"); - oldremclock = CPU_REMCLOCK; - switch(tunnel->io._direction){ // 入力 or 出力 - case HAX_IO_OUT: // 出力 - if(tunnel->io._df==0){ // 連続でデータを出力する場合の方向? - int i; - UINT8 *bufptr = iobuf; - for(i=0;iio._count;i++){ - if(tunnel->io._size==1){ // 1byte - iocore_out8(tunnel->io._port, *bufptr); - }else if(tunnel->io._size==2){ // 2yte - iocore_out16(tunnel->io._port, LOADINTELWORD(bufptr)); - }else{ // tunnel->io._size==4 // それ以外(実質4byte) - iocore_out32(tunnel->io._port, LOADINTELDWORD(bufptr)); - } - bufptr += tunnel->io._size; - } - }else{ - int i; - UINT8 *bufptr = iobuf; - bufptr += tunnel->io._size * (tunnel->io._count-1); - for(i=tunnel->io._count-1;i>=0;i--){ - if(tunnel->io._size==1){ // 1byte - iocore_out8(tunnel->io._port, *bufptr); - }else if(tunnel->io._size==2){ // 2yte - iocore_out16(tunnel->io._port, LOADINTELWORD(bufptr)); - }else{ // tunnel->io._size==4 // それ以外(実質4byte) - iocore_out32(tunnel->io._port, LOADINTELDWORD(bufptr)); - } - bufptr -= tunnel->io._size; - } - } - break; - case HAX_IO_IN: // 入力 - if(tunnel->io._df==0){ // 連続でデータを入力する場合の方向? - int i; - UINT8 *bufptr = iobuf; - for(i=0;iio._count;i++){ - if(tunnel->io._size==1){ - *bufptr = iocore_inp8(tunnel->io._port); // 1byte - }else if(tunnel->io._size==2){ - STOREINTELWORD(bufptr, iocore_inp16(tunnel->io._port)); // 2yte - }else{ // tunnel->io._size==4 - STOREINTELDWORD(bufptr, iocore_inp32(tunnel->io._port)); // それ以外(実質4byte) - } - bufptr += tunnel->io._size; - } - }else{ - int i; - UINT8 *bufptr = iobuf; - bufptr += tunnel->io._size * (tunnel->io._count-1); - for(i=tunnel->io._count-1;i>=0;i--){ - if(tunnel->io._size==1){ - *bufptr = iocore_inp8(tunnel->io._port); // 1byte - }else if(tunnel->io._size==2){ - STOREINTELWORD(bufptr, iocore_inp16(tunnel->io._port)); // 2yte - }else{ // tunnel->io._size==4 - STOREINTELDWORD(bufptr, iocore_inp32(tunnel->io._port)); // それ以外(実質4byte) - } - bufptr -= tunnel->io._size; - } - } - break; - } - if(tunnel->io._port==0x1480 || tunnel->io._port == 0x04d2){ - // ゲームポート読み取りは即座に返す - goto coutinue_cpu_imm; - } - if(CPU_REMCLOCK==-1){ - break; - } - //CPU_REMCLOCK = oldremclock; - - // 高速化のために一部のI/Oポートの処理を簡略化 - //if(tunnel->io._port != 0x90 && tunnel->io._port != 0x92 && tunnel->io._port != 0x94 && - // tunnel->io._port != 0xc8 && tunnel->io._port != 0xca && tunnel->io._port != 0xcc && tunnel->io._port != 0xbe && tunnel->io._port != 0x4be) { - // (0x430 <= tunnel->io._port && tunnel->io._port <= 0x64e && !(g_nevent.item[NEVENT_SASIIO].flag & NEVENT_ENABLE)) || - // (0x7FD9 <= tunnel->io._port && tunnel->io._port <= 0x7FDF)){ - if(tunnel->io._port==0x640){ - // 厳しめにする - if (np2haxcore.hurryup) { - np2haxcore.hurryup = 0; - break; - } - } - { - SINT32 diff; - np2haxcore.clockcount = GetTickCounter_Clock(); - diff = (np2haxcore.clockcount.QuadPart - np2haxcore.lastclock.QuadPart) * pccore.realclock / np2haxcore.clockpersec.QuadPart; - if(CPU_REMCLOCK > 0){ - CPU_REMCLOCK -= diff; - } - np2haxcore.lastclock.QuadPart = np2haxcore.clockcount.QuadPart; - } - - // 時間切れなら抜ける - if (CPU_REMCLOCK <= 0) { - break; - } - if (CPU_REMCLOCK > 0 && timing_getcount_baseclock()!=0) { - CPU_REMCLOCK = 0; - break; - } - i386haxfunc_vcpu_getREGs(&np2haxstat.state); - i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); - np2haxstat.update_regs = np2haxstat.update_fpu = 0; - - ia32hax_copyregHAXtoNP2(); - pic_irq(); - - goto coutinue_cpu; - //} - break; - case HAX_EXIT_FAST_MMIO: // メモリマップドI/Oへのアクセス - //printf("HAX_EXIT_FAST_MMIO¥n"); - { - HAX_FASTMMIO *mmio = (HAX_FASTMMIO*)np2hax.tunnel.io_va; - - switch(mmio->direction){ // データREAD/WRITEの判定 - case 0: // データREAD - if(mmio->size==1){ - mmio->value = memp_read8((UINT32)mmio->gpa); - }else if(mmio->size==2){ - mmio->value = memp_read16((UINT32)mmio->gpa); - }else{ // mmio->size==4 - mmio->value = memp_read32((UINT32)mmio->gpa); - } - break; - case 1: // データWRITE - if(mmio->size==1){ - memp_write8((UINT32)mmio->gpa, (UINT8)mmio->value); - }else if(mmio->size==2){ - memp_write16((UINT32)mmio->gpa, (UINT16)mmio->value); - }else{ // mmio->size==4 - memp_write32((UINT32)mmio->gpa, (UINT32)mmio->value); - } - break; - default: // データREAD→データWRITE - if(mmio->size==1){ - memp_write8((UINT32)mmio->gpa2, memp_read8((UINT32)mmio->gpa)); - }else if(mmio->size==2){ - memp_write16((UINT32)mmio->gpa2, memp_read16((UINT32)mmio->gpa)); - }else{ // mmio->size==4 - memp_write32((UINT32)mmio->gpa2, memp_read32((UINT32)mmio->gpa)); - } - break; - } - } - { - SINT32 diff; - np2haxcore.clockcount = GetTickCounter_Clock(); - diff = (np2haxcore.clockcount.QuadPart - np2haxcore.lastclock.QuadPart) * pccore.realclock / np2haxcore.clockpersec.QuadPart; - if(CPU_REMCLOCK > 0){ - CPU_REMCLOCK -= diff; - } - np2haxcore.lastclock.QuadPart = np2haxcore.clockcount.QuadPart; - } - - // 時間切れなら抜ける - if (CPU_REMCLOCK <= 0) { - break; - } - if (CPU_REMCLOCK > 0 && timing_getcount_baseclock()!=0) { - CPU_REMCLOCK = 0; - break; - } - i386haxfunc_vcpu_getREGs(&np2haxstat.state); - i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); - np2haxstat.update_regs = np2haxstat.update_fpu = 0; - - ia32hax_copyregHAXtoNP2(); - pic_irq(); - goto coutinue_cpu; - break; - } - - // HAXMレジスタを読み取り - i386haxfunc_vcpu_getREGs(&np2haxstat.state); - i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); - np2haxstat.update_regs = np2haxstat.update_fpu = 0; - - // HAXMレジスタ→猫レジスタにコピー - ia32hax_copyregHAXtoNP2(); - - // CPU実行再開のための処理(処理速度はどうでもいい物) - switch (exitstatus) { - case HAX_EXIT_MMIO: // メモリマップドI/Oへのアクセス(旧式・もう呼ばれないと思う) - //printf("HAX_EXIT_MMIO¥n"); - break; - case HAX_EXIT_REALMODE: // 事前設定をするとリアルモードの時に呼ばれるらしい - //printf("HAX_EXIT_REALMODE¥n"); - break; - case HAX_EXIT_INTERRUPT: // 割り込み・・・? - //printf("HAX_EXIT_INTERRUPT¥n"); - // リセット可能フラグを立てる - np2haxcore.ready_for_reset = 1; - break; - case HAX_EXIT_UNKNOWN: // 謎 - //printf("HAX_EXIT_UNKNOWN¥n"); - //if(!CPU_RESETREQ){ - // np2hax.emumode = 1; - // CPU_REMCLOCK = 0; - // if (!(CPU_TYPE & CPUTYPE_V30)) { - // CPU_EXEC(); - // } - // else { - // CPU_EXECV30(); - // } - // np2haxstat.update_regs = 1; - // np2haxstat.update_fpu = 1; - //} - break; - case HAX_EXIT_HLT: // HLT命令が実行されたとき - np2haxcore.hltflag = 1; - //printf("HAX_EXIT_HLT¥n"); - // リセット可能フラグを立てる - np2haxcore.ready_for_reset = 1; - // リアルモード or 仮想86 - if (!CPU_STAT_PM || CPU_STAT_VM86) - { - CPU_PREV_EIP = CPU_EIP - 1; // HLTの次の命令に移ってしまっているので・・・ - addr = CPU_PREV_EIP + (CPU_CS << 4); - // BIOSコール - if (memp_read8(addr) == bioshookinfo.hookinst) - { - if (ia32hax_bioscall()) - { - np2haxstat.update_regs = 1; - np2haxstat.update_segment_regs = 1; - // カウンタリセット - pmcounter = 0; - np2haxcore.hltflag = 0; // すぐに再開 - } - } - } - break; - case HAX_EXIT_STATECHANGE: // CPU状態が変わったとき・・・と言いつつ、事実上CPUが実行不能(panic)になったときしか呼ばれない - //printf("HAX_EXIT_STATECHANGE¥n"); - // リセット可能フラグを立てる - np2haxcore.ready_for_reset = 1; - //if(!CPU_RESETREQ){ - // np2hax.emumode = 1; - // //CPU_REMCLOCK = 0; - // if (!(CPU_TYPE & CPUTYPE_V30)) { - // CPU_EXEC(); - // } - // else { - // CPU_EXECV30(); - // } - // np2haxstat.update_regs = 1; - // np2haxstat.update_fpu = 1; - // restoreCounter = 100000; - //} - //{ - // int i; - // UINT32 memdumpa[0x100]; - // UINT8 memdump[0x100]; - // UINT32 baseaddr; - // addr = CPU_EIP + (CPU_CS << 4); - // baseaddr = addr & ‾0xff; - // for(i=0;i<0x100;i++){ - // memdumpa[i] = baseaddr + i; - // memdump[i] = memp_read8(memdumpa[i]); - // } - // //msgbox("HAXM_ia32_panic", "HAXM CPU panic"); - // //pcstat.hardwarereset = TRUE; - // return; - //} - break; - case HAX_EXIT_PAUSED: // 一時停止? - //printf("HAX_EXIT_PAUSED¥n"); - // リセット可能フラグを立てる - np2haxcore.ready_for_reset = 1; - break; - case HAX_EXIT_PAGEFAULT: // ページフォールト? - //printf("HAX_EXIT_PAGEFAULT¥n"); - break; - case HAX_EXIT_DEBUG: // デバッグ命令(INT3 CCh)が呼ばれたとき - //printf("HAX_EXIT_DEBUG¥n"); - // リセット可能フラグを立てる - np2haxcore.ready_for_reset = 1; - break; - default: - break; - } - - np2haxcore.running = 0; -} -void i386hax_vm_exec(void) { - static int skipcounter = 0; - static SINT32 remain_clk = 0; - SINT32 remclktmp = CPU_REMCLOCK; - int timing; - int i; - if(pcstat.hardwarereset){ - CPU_REMCLOCK = 0; - return; - } - if(!np2haxcore.hltflag || !CPU_isEI || np2haxstat.irq_reqidx_cur != np2haxstat.irq_reqidx_end){ - CPU_REMCLOCK += remain_clk; - np2haxcore.lastclock = GetTickCounter_Clock(); - while(CPU_REMCLOCK > 0){ - int remclkdiff = 0; - i386hax_vm_exec_part(); - np2haxcore.clockcount = GetTickCounter_Clock(); - if(CPU_REMCLOCK > 0){ - remclkdiff = (np2haxcore.clockcount.QuadPart - np2haxcore.lastclock.QuadPart) * pccore.realclock / np2haxcore.clockpersec.QuadPart; - CPU_REMCLOCK -= remclkdiff; - } - np2haxcore.lastclock = np2haxcore.clockcount; - if(dmac.working) { - for(i=0;i<(remclkdiff+3)/4;i++){ - dmax86(); // XXX: 本当は1命令実行ごとに呼ぶのが正しいけど出来ないのでまとめて呼ぶ・・・ - } - } - if(CPU_RESETREQ) break; - if(pcstat.hardwarereset) break; - if (CPU_REMCLOCK > 0 && (timing = timing_getcount_baseclock())!=0) { - CPU_REMCLOCK = 0; - break; - } - if(np2haxcore.hltflag){ - CPU_REMCLOCK = 0; - remain_clk = 0; - break; - } - } - if(CPU_REMCLOCK <= 0){ - remain_clk = CPU_REMCLOCK; - }else{ - remain_clk = 0; - } - if (CPU_REMCLOCK < -(SINT32)(CPU_BASECLOCK*3)) { - np2haxcore.hurryup = 1; - } - CPU_REMCLOCK = 0; - }else{ - if(dmac.working) { - for(i=0;i<(CPU_REMCLOCK+3)/4;i++){ - dmax86(); - } - } - CPU_REMCLOCK = 0; - remain_clk = 0; - } -} - -void i386hax_disposeVM(void) { - -#if defined(_WIN32) - if(!np2hax.hDevice) return; - if(!np2hax.hVCPUDevice) return; - if(!np2hax.hVMDevice) return; - - // 仮想マシンを閉じる - CloseHandle(np2hax.hVCPUDevice); - np2hax.hVCPUDevice = NULL; - CloseHandle(np2hax.hVMDevice); - np2hax.hVMDevice = NULL; - - TRACEOUT(("HAXM: HAX VM disposed.")); - //msgbox("HAXM deinit", "HAX VM disposed."); -#endif -} - -void i386hax_deinitialize(void) { - -#if defined(_WIN32) - if(!np2hax.hDevice) return; - - i386hax_disposeVM(); - - // HAXMを閉じる - CloseHandle(np2hax.hDevice); - np2hax.hDevice = NULL; - - TRACEOUT(("HAXM: HAX deinitialized.")); - //msgbox("HAXM deinit", "HAX deinitialized."); - -#endif -} - -// HAXM仮想マシンで使用するホストのメモリ領域を登録(登録済みメモリのみ仮想マシンに割り当て可能) -void i386hax_vm_allocmemory(void) { - -#if defined(_WIN32) - HAX_ALLOC_RAM_INFO info = {0}; - - if(!np2hax.hVMDevice) return; - - info.size = 0x200000; - info.va = (UINT64)mem; - if(i386haxfunc_allocRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM alloc memory failed.")); - msgbox("HAXM VM", "HAX VM alloc memory failed."); - np2hax.enable = 0; - i386hax_disposeVM(); - return; - } - - info.size = CPU_EXTMEMSIZE + 4096; - info.va = (UINT64)CPU_EXTMEM; - if(i386haxfunc_allocRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM alloc memory failed.")); - msgbox("HAXM VM", "HAX VM alloc memory failed."); - np2hax.enable = 0; - i386hax_disposeVM(); - return; - } - - info.size = sizeof(vramex_base); - info.va = (UINT64)vramex; - if(i386haxfunc_allocRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM alloc memory failed.")); - msgbox("HAXM VM", "HAX VM alloc memory failed."); - np2hax.enable = 0; - i386hax_disposeVM(); - return; - } - - TRACEOUT(("HAXM: HAX VM alloc memory.")); - //msgbox("HAXM VM", "HAX VM alloc memory."); -#endif -} -void i386hax_vm_allocmemoryex(UINT8 *vramptr, UINT32 size) { - -#if defined(_WIN32) - HAX_ALLOC_RAM_INFO info = {0}; - - if(!np2hax.hVMDevice) return; - - info.size = size; - info.va = (UINT64)vramptr; - if(i386haxfunc_allocRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM alloc memory failed.")); - msgbox("HAXM VM", "HAX VM alloc memory failed."); - return; - } - - TRACEOUT(("HAXM: HAX VM alloc memory.")); - //msgbox("HAXM VM", "HAX VM alloc memory."); -#endif -} - -// HAXM仮想マシンのゲスト物理アドレス(Guest Physical Address; GPA)にホストの仮想アドレス(Host Virtual Address; HVA)を割り当て -void i386hax_vm_setmemory(void) { - -#if defined(_WIN32) - HAX_SET_RAM_INFO info = {0}; - - if(!np2hax.enable) return; - if(!np2hax.hVMDevice) return; - - info.pa_start = 0; - info.size = 0xA0000; - info.flags = 0; - info.va = (UINT64)mem; - if(i386haxfunc_setRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM set memory failed.")); - msgbox("HAXM VM", "HAX VM set memory failed."); - np2hax.enable = 0; - return; - } - - //info.pa_start = 0xFFF00000; - //info.size = 0xF8000; - //info.flags = 0; - //info.va = (UINT64)mem; - //if(i386haxfunc_setRAM(&info)==FAILURE){ - // TRACEOUT(("HAXM: HAX VM set memory failed.")); - // msgbox("HAXM VM", "HAX VM set memory failed."); - // np2hax.enable = 0; - // return; - //} - - TRACEOUT(("HAXM: HAX VM set memory.")); - //msgbox("HAXM VM", "HAX VM set memory."); -#endif -} -void i386hax_vm_setbankmemory() { - -} -void i386hax_vm_setitfmemory(UINT8 isitfbank) { - -#if defined(_WIN32) - HAX_SET_RAM_INFO info = {0}; - - if(!np2hax.hVMDevice) - if(!np2hax.enable) return; - - info.pa_start = 0xF8000; - info.size = 0x8000; - info.flags = HAX_RAM_INFO_INVALID; - if(i386haxfunc_setRAM(&info)==FAILURE){ - } - if(isitfbank){ - info.flags = HAX_RAM_INFO_ROM; - info.va = (UINT64)(mem + ITF_ADRS); - }else{ - info.flags = HAX_RAM_INFO_ROM; - info.va = (UINT64)(mem + info.pa_start); - } - if(i386haxfunc_setRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM set ITF bank memory failed.")); - msgbox("HAXM VM", "HAX VM set ITF bank memory failed."); - np2hax.enable = 0; - return; - } - - info.pa_start = 0xFFFF8000; - info.size = 0x8000; - info.flags = HAX_RAM_INFO_INVALID; - if(i386haxfunc_setRAM(&info)==FAILURE){ - } - if(isitfbank){ - info.flags = HAX_RAM_INFO_ROM; - info.va = (UINT64)(mem + ITF_ADRS); - }else{ - info.flags = HAX_RAM_INFO_ROM; - info.va = (UINT64)(mem + 0xF8000); - } - if(i386haxfunc_setRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM set ITF bank memory failed.")); - msgbox("HAXM VM", "HAX VM set ITF bank memory failed."); - np2hax.enable = 0; - return; - } - - if(isitfbank){ - TRACEOUT(("HAXM: HAX VM set ITF bank memory. (ITF)")); - //msgbox("HAXM VM", "HAX VM set ITF bank memory. (ITF)"); - }else{ - TRACEOUT(("HAXM: HAX VM set ITF bank memory. (OFF)")); - //msgbox("HAXM VM", "HAX VM set ITF bank memory. (OFF)"); - } -#endif -} -void i386hax_vm_sethmemory(UINT8 a20en) { - -#if defined(_WIN32) - HAX_SET_RAM_INFO info = {0}; - - if(!np2hax.enable) return; - if(!np2hax.hVMDevice) return; - - info.pa_start = 0x100000; - info.size = 0x10000; - info.flags = HAX_RAM_INFO_INVALID; - if(i386haxfunc_setRAM(&info)==FAILURE){ - } - - if(a20en){ - info.flags = 0; - info.va = (UINT64)(mem + info.pa_start); - }else{ - info.flags = 0; - info.va = (UINT64)(mem); - } - if(i386haxfunc_setRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM set high memory failed.")); - msgbox("HAXM VM", "HAX VM set high memory failed."); - np2hax.enable = 0; - return; - } - - if(a20en){ - TRACEOUT(("HAXM: HAX VM set high memory. (A20 ON)")); - //msgbox("HAXM VM", "HAX VM set high memory. (A20 ON)"); - }else{ - TRACEOUT(("HAXM: HAX VM set high memory. (A20 OFF)")); - //msgbox("HAXM VM", "HAX VM set ITF bank memory. (A20 OFF)"); - } -#endif -} -void i386hax_vm_setextmemory(void) { - -#if defined(_WIN32) - HAX_SET_RAM_INFO info = {0}; - - if(!np2hax.enable) return; - if(!np2hax.hVMDevice) return; - - info.pa_start = 0x110000; - info.size = CPU_EXTLIMIT16 - 0x110000; - info.flags = 0; - info.va = (UINT64)(CPU_EXTMEMBASE + info.pa_start); - if(i386haxfunc_setRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM set ext16 memory failed.")); - msgbox("HAXM VM", "HAX VM set ext16 memory failed."); - np2hax.enable = 0; - return; - } - - if(CPU_EXTLIMIT > 0x01000000){ - info.pa_start = 0x01000000; - info.size = CPU_EXTLIMIT - 0x01000000; - info.flags = 0; - info.va = (UINT64)(CPU_EXTMEMBASE + info.pa_start); - if(i386haxfunc_setRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM set ext memory failed.")); - msgbox("HAXM VM", "HAX VM set ext memory failed."); - np2hax.enable = 0; - return; - } - } - - TRACEOUT(("HAXM: HAX VM set ext memory.")); - //msgbox("HAXM VM", "HAX VM set ext memory."); -#endif -} - -void i386hax_vm_setvga256linearmemory(void) { - -#if defined(_WIN32) - HAX_SET_RAM_INFO info = {0}; - - if(!np2hax.enable) return; - if(!np2hax.hVMDevice) return; - - info.pa_start = 0xF00000; - info.size = 0x80000; - info.flags = HAX_RAM_INFO_INVALID; - i386haxfunc_setRAM(&info); - if(vramop.mio2[0x2]==0x1 && (gdc.analog & (1 << GDCANALOG_256))!=0){ - info.flags = 0; - info.va = (UINT64)vramex; - if(i386haxfunc_setRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM set vga256 linear memory failed.")); - msgbox("HAXM VM", "HAX VM set vga256 linear memory failed."); - return; - } - - TRACEOUT(("HAXM: HAX VM set vga256 linear memory.")); - } - - info.pa_start = 0xfff00000; - info.size = 0x80000; - info.flags = HAX_RAM_INFO_INVALID; - info.va = NULL; - i386haxfunc_setRAM(&info); - info.flags = 0; - info.va = (UINT64)vramex; - if(i386haxfunc_setRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM set vga256 0xfff00000 linear memory failed.")); - msgbox("HAXM VM", "HAX VM set vga256 0xfff00000 linear memory failed."); - return; - } - //msgbox("HAXM VM", "HAX VM set ext memory."); -#endif -} - -void i386hax_vm_setmemoryarea(UINT8 *vramptr, UINT32 addr, UINT32 size) { - -#if defined(_WIN32) - HAX_SET_RAM_INFO info = {0}; - - if(!np2hax.enable) return; - if(!np2hax.hVMDevice) return; - - info.pa_start = addr; - info.size = size; - info.flags = HAX_RAM_INFO_INVALID; - i386haxfunc_setRAM(&info); - if(vramptr){ - info.flags = 0; - info.va = (UINT64)vramptr; - if(i386haxfunc_setRAM(&info)==FAILURE){ - TRACEOUT(("HAXM: HAX VM set memory area failed.")); - //msgbox("HAXM VM", "HAX VM set memory area failed."); - return; - } - - TRACEOUT(("HAXM: HAX VM set memory area.")); - } -#endif -} -void i386hax_vm_removememoryarea(UINT8 *vramptr, UINT32 addr, UINT32 size) { - -#if defined(_WIN32) - HAX_SET_RAM_INFO info = {0}; - - if(!np2hax.enable) return; - if(!np2hax.hVMDevice) return; - - info.pa_start = addr; - info.size = size; - info.flags = HAX_RAM_INFO_INVALID; - i386haxfunc_setRAM(&info); -#endif -} - +/* + * Copyright (c) 2019 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(SUPPORT_IA32_HAXM) + +#if 0 +#undef TRACEOUT +//#define USE_TRACEOUT_VS +#ifdef USE_TRACEOUT_VS +static void trace_fmt_ex(const char *fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "¥n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#else +#define TRACEOUT(s) (void)(s) +#endif +#endif /* 1 */ +#include "haxfunc.h" +#include "haxcore.h" + +#if defined(_WINDOWS) +#include +#endif + +NP2_HAX np2hax = {0}; +NP2_HAX_STAT np2haxstat = {0}; +NP2_HAX_CORE np2haxcore = {0}; + +static void make_vm_str(OEMCHAR* buf, UINT32 vm_id){ + _stprintf(buf, OEMTEXT("¥¥¥¥.¥¥hax_vm%02d"), vm_id); +} +static void make_vcpu_str(OEMCHAR* buf, UINT32 vm_id, UINT32 vcpu_id){ + _stprintf(buf, OEMTEXT("¥¥¥¥.¥¥hax_vm%02d_vcpu%02d"), vm_id, vcpu_id); +} + +// HAXMが使えそうかチェック +UINT8 i386hax_check(void) { + +#if defined(_WIN32) + HAX_MODULE_VERSION haxver = {0}; + HAX_CAPINFO haxcap = {0}; + + // HAXMカーネルモードドライバを開く + np2hax.hDevice = CreateFile(OEMTEXT("¥¥¥¥.¥¥HAX"), + GENERIC_READ|GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (np2hax.hDevice == INVALID_HANDLE_VALUE) { + TRACEOUT(("HAXM: Failed to initialize the HAX device.")); + msgbox("HAXM check", "Failed to initialize the HAX device."); + np2hax.available = 0; + np2hax.hDevice = NULL; + return FAILURE; + } + + // HAXMバージョンを取得 + if(i386haxfunc_getversion(&haxver)==SUCCESS){ + char buf[256] = {0}; + TRACEOUT(("HAXM: HAX getversion: compatible version %d, current version %d", haxver.compat_version, haxver.current_version)); + //sprintf(buf, "HAXM: HAX getversion: compatible version %d, current version %d", haxver.compat_version, haxver.current_version); + //msgbox("HAXM check", buf); + //msgbox("HAXM init", "HAX getversion succeeded."); + }else{ + TRACEOUT(("HAXM: HAX getversion failed.")); + msgbox("HAXM check", "HAX getversion failed."); + goto initfailure; + } + + // HAXMで使える機能を調査 + if(i386haxfunc_getcapability(&haxcap)==SUCCESS){ + char buf[256] = {0}; + TRACEOUT(("HAXM: HAX getcapability: wstatus 0x%.4x, winfo 0x%.4x, win_refcount %d, mem_quota %d", haxcap.wstatus, haxcap.winfo, haxcap.win_refcount, haxcap.mem_quota)); + //sprintf(buf, "HAXM: HAX getcapability: wstatus 0x%.4x, winfo 0x%.4x, win_refcount %d, mem_quota %d", haxcap.wstatus, haxcap.winfo, haxcap.win_refcount, haxcap.mem_quota); + //msgbox("HAXM check", buf); + if(!(haxcap.wstatus & HAX_CAP_WORKSTATUS_MASK)){ + if(haxcap.winfo & HAX_CAP_FAILREASON_VT){ + msgbox("HAXM check", "Error: Intel VT-x is not supported by the host CPU."); + }else{ + msgbox("HAXM check", "Error: Intel Execute Disable Bit is not supported by the host CPU."); + } + goto initfailure; + } + if(!(haxcap.winfo & HAX_CAP_FASTMMIO)){ + msgbox("HAXM check", "Error: Fast MMIO is not supported. Please update HAXM."); + goto initfailure; + } + if(!(haxcap.winfo & HAX_CAP_DEBUG)){ + msgbox("HAXM check", "Error: Debugging function is not supported. Please update HAXM."); + goto initfailure; + } + //msgbox("HAXM init", "HAX getversion succeeded."); + }else{ + TRACEOUT(("HAXM: HAX getcapability failed.")); + msgbox("HAXM check", "HAX getcapability failed."); + goto initfailure; + } + + CloseHandle(np2hax.hDevice); + np2hax.hDevice = NULL; + + TRACEOUT(("HAXM: HAX available.")); + //msgbox("HAXM check", "HAX available."); + + np2hax.available = 1; + + return SUCCESS; + +initfailure: + CloseHandle(np2hax.hDevice); + np2hax.available = 0; + np2hax.enable = 0; + np2hax.hDevice = NULL; + return FAILURE; +#else + return 1; +#endif +} + +void i386hax_initialize(void) { + +#if defined(_WIN32) + if(!np2hax.available) return; + if(!np2hax.enable) return; + + i386hax_deinitialize(); + + // HAXMカーネルモードドライバを開く + np2hax.hDevice = CreateFile(OEMTEXT("¥¥¥¥.¥¥HAX"), + GENERIC_READ|GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (np2hax.hDevice == INVALID_HANDLE_VALUE) { + TRACEOUT(("HAXM: Failed to initialize the HAX device.")); + return; + } + + TRACEOUT(("HAXM: HAX initialized.")); + //msgbox("HAXM init", "HAX initialized."); + + return; + +error1: + CloseHandle(np2hax.hDevice); + np2hax.hDevice = NULL; + return; +#endif +} + +void i386hax_createVM(void) { + +#if defined(_WIN32) + OEMCHAR vm_str[64] = {0}; + OEMCHAR vcpu_str[64] = {0}; + HAX_DEBUG hax_dbg = {0}; + HAX_QEMU_VERSION hax_qemu_ver = {0}; + + if(!np2hax.available) return; + if(!np2hax.enable) return; + if(!np2hax.hDevice) return; + + i386hax_disposeVM(); + + // HAXM仮想マシンを作成 + if(i386haxfunc_createVM(&np2hax.vm_id)==FAILURE){ + TRACEOUT(("HAXM: HAX create VM failed.")); + msgbox("HAXM VM", "HAX create VM failed."); + return; + } + + make_vm_str(vm_str, np2hax.vm_id); + + // HAXM仮想マシンを開く + np2hax.hVMDevice = CreateFile(vm_str, + GENERIC_READ|GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (np2hax.hVMDevice == INVALID_HANDLE_VALUE) { + TRACEOUT(("HAXM: Failed to initialize the HAX VM device.")); + return; + } + + // あまり意味なし? + //hax_qemu_ver.cur_version = 0x0; + //if(i386haxfunc_notifyQEMUversion(&hax_qemu_ver)==FAILURE){ + // TRACEOUT(("HAXM: HAX notify QEMU version failed.")); + // msgbox("HAXM VM", "HAX notify QEMU version failed."); + // goto error2; + //} + + // 仮想CPUを作成 + if(i386haxfunc_VCPUcreate(0)==FAILURE){ + TRACEOUT(("HAXM: HAX create VCPU failed.")); + msgbox("HAXM VM", "HAX create VCPU failed."); + goto error2; + } + + make_vcpu_str(vcpu_str, np2hax.vm_id, 0); + + // 仮想CPUを開く + np2hax.hVCPUDevice = CreateFile(vcpu_str, + GENERIC_READ|GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (np2hax.hVCPUDevice == INVALID_HANDLE_VALUE) { + TRACEOUT(("HAXM: Failed to initialize the HAX VCPU device.")); + goto error2; + } + + // 仮想CPUとデータをやりとりするのための場所を確保 + if(i386haxfunc_vcpu_setup_tunnel(&np2hax.tunnel)==FAILURE){ + TRACEOUT(("HAXM: HAX VCPU setup tunnel failed.")); + msgbox("HAXM VM", "HAX VCPU setup tunnel failed."); + goto error2; + } + + //// デバッグ機能を有効にする(HAX_DEBUG_USE_SW_BPは仮想マシンがINT3 CChを呼ぶと無条件で仮想マシンモニタに移行できる) + //np2hax.bioshookenable = 1; + //hax_dbg.control = HAX_DEBUG_ENABLE|HAX_DEBUG_USE_SW_BP;//|HAX_DEBUG_USE_HW_BP|HAX_DEBUG_STEP; + //if(i386haxfunc_vcpu_debug(&hax_dbg)==FAILURE){ + // TRACEOUT(("HAXM: HAX VCPU debug setting failed.")); + // msgbox("HAXM VM", "HAX VCPU debug setting failed."); + // goto error2; + //} + np2hax.bioshookenable = 0; // もう使用しなくなった np21w ver0.86 rev95 + + TRACEOUT(("HAXM: HAX VM initialized.")); + //msgbox("HAXM VM", "HAX VM initialized."); + + memset(&np2haxcore, 0, sizeof(np2haxcore)); + + // デフォルトのレジスタ設定を覚えておく + i386haxfunc_vcpu_getREGs(&np2haxstat.state); + i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); + memcpy(&np2haxstat.default_state, &np2haxstat.state, sizeof(np2haxstat.state)); + memcpy(&np2haxstat.default_fpustate, &np2haxstat.fpustate, sizeof(np2haxstat.fpustate)); + + np2hax.emumode = 0; + + return; + +error3: + CloseHandle(np2hax.hVCPUDevice); + np2hax.hVCPUDevice = NULL; +error2: + CloseHandle(np2hax.hVMDevice); + np2hax.hVMDevice = NULL; +error1: + return; +#endif +} + +void i386hax_resetVMMem(void) { + + // メモリ周りの初期設定 + np2haxcore.lastA20en = (CPU_ADRSMASK != 0x000fffff); + i386hax_vm_sethmemory(np2haxcore.lastA20en); + np2haxcore.lastITFbank = CPU_ITFBANK; + i386hax_vm_setitfmemory(np2haxcore.lastITFbank); + np2haxcore.lastVGA256linear = (vramop.mio2[0x2]==0x1); + i386hax_vm_setvga256linearmemory(); + np2haxcore.lastVRAMMMIO = 1; + + i386hax_vm_setmemoryarea(mem+0xA5000, 0xA5000, 0x3000); + //i386hax_vm_setmemoryarea(mem+0xA8000, 0xA8000, 0x8000); + //i386hax_vm_setmemoryarea(mem+0xB0000, 0xB0000, 0x10000); + //i386hax_vm_setmemoryarea(mem+0xC0000, 0xC0000, 0x10000); + i386hax_vm_setmemoryarea(mem+0xD0000, 0xD0000, 0x10000); + //i386hax_vm_setmemoryarea(mem+0xE0000, 0xE0000, 0x8000); + i386hax_vm_setmemoryarea(mem+0xE8000, 0xE8000, 0x8000); + i386hax_vm_setmemoryarea(mem+0xF0000, 0xF0000, 0x8000); + i386hax_vm_setmemoryarea(mem+0xF8000, 0xF8000, 0x8000); + + //i386hax_vm_setmemoryarea(mem+0xA5000, 0xA5000, 0x3000); + //i386hax_vm_setmemoryarea(mem+0xA8000, 0xA8000, 0x8000); + //i386hax_vm_setmemoryarea(mem+0xB0000, 0xB0000, 0x10000); + //i386hax_vm_setmemoryarea(mem+0xC0000, 0xC0000, 0x10000); + //i386hax_vm_setmemoryarea(mem+0xD0000, 0xD0000, 0x10000); + //i386hax_vm_setmemoryarea(mem+0xE0000, 0xE0000, 0x8000); + //i386hax_vm_setmemoryarea(mem+0xE8000, 0xE8000, 0x8000); + //i386hax_vm_setmemoryarea(mem+0xF0000, 0xF0000, 0x8000); +} + +void i386hax_resetVMCPU(void) { + + // CPU周りの初期設定 + np2haxstat.irq_reqidx_cur = np2haxstat.irq_reqidx_end = 0; + + memcpy(&np2haxstat.state, &np2haxstat.default_state, sizeof(np2haxstat.state)); + memcpy(&np2haxstat.fpustate, &np2haxstat.default_fpustate, sizeof(np2haxstat.fpustate)); + + np2haxstat.update_regs = np2haxstat.update_fpu = 1; + np2haxstat.update_segment_regs = 1; + + np2haxcore.clockpersec = GetTickCounter_ClockPerSec(); + np2haxcore.lastclock = GetTickCounter_Clock(); + np2haxcore.clockcount = GetTickCounter_Clock(); +} + +/* + * bios call interface (HAXM) + */ +static int +ia32hax_bioscall(void) +{ + UINT32 adrs; + int ret = 0; + + if (!CPU_STAT_PM || CPU_STAT_VM86) { +#if 1 + adrs = CPU_PREV_EIP + (CPU_CS << 4); +#else + adrs = CPU_PREV_EIP + CPU_STAT_CS_BASE; +#endif + if ((adrs >= 0xf8000) && (adrs < 0x100000)) { + if (biosfunc(adrs)) { + /* Nothing to do */ + } + LOAD_SEGREG(CPU_ES_INDEX, CPU_ES); + LOAD_SEGREG(CPU_CS_INDEX, CPU_CS); + LOAD_SEGREG(CPU_SS_INDEX, CPU_SS); + LOAD_SEGREG(CPU_DS_INDEX, CPU_DS); + ret = 1; + } + } + return ret; +} + +#define TSS_16_SIZE 44 +#define TSS_16_LIMIT (TSS_16_SIZE - 1) +#define TSS_32_SIZE 104 +#define TSS_32_LIMIT (TSS_32_SIZE - 1) + +static void CPUCALL +ia32hax_setHAXtoNP2IOADDR() +{ + UINT16 iobase; + + if (CPU_STAT_PM && !CPU_STAT_VM86) { + /* check descriptor type & stack room size */ + switch (CPU_TR_DESC.type) { + case CPU_SYSDESC_TYPE_TSS_16: + case CPU_SYSDESC_TYPE_TSS_BUSY_16: + if (CPU_TR_DESC.u.seg.limit < TSS_16_LIMIT) { + return; + } + iobase = 0; + break; + + case CPU_SYSDESC_TYPE_TSS_32: + case CPU_SYSDESC_TYPE_TSS_BUSY_32: + if (CPU_TR_DESC.u.seg.limit < TSS_32_LIMIT) { + return; + } + iobase = cpu_kmemoryread_w(CPU_TR_DESC.u.seg.segbase + 102); + //return; + break; + + default: + return; + } + + /* I/O deny bitmap */ + CPU_STAT_IOLIMIT = 0; + if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_32) { + if (iobase < CPU_TR_LIMIT) { + CPU_STAT_IOLIMIT = (UINT16)(CPU_TR_LIMIT - iobase); + CPU_STAT_IOADDR = CPU_TR_BASE + iobase; + } + } + } +} + +// HAXレジスタ → NP2 IA-32 レジスタ +void +ia32hax_copyregHAXtoNP2(void) +{ + CPU_EAX = np2haxstat.state._eax; + CPU_EBX = np2haxstat.state._ebx; + CPU_ECX = np2haxstat.state._ecx; + CPU_EDX = np2haxstat.state._edx; + + CPU_ESI = np2haxstat.state._esi; + CPU_EDI = np2haxstat.state._edi; + + CPU_CS = np2haxstat.state._cs.selector; + CPU_DS = np2haxstat.state._ds.selector; + CPU_ES = np2haxstat.state._es.selector; + CPU_SS = np2haxstat.state._ss.selector; + CPU_FS = np2haxstat.state._fs.selector; + CPU_GS = np2haxstat.state._gs.selector; + CS_BASE = np2haxstat.state._cs.base; + DS_BASE = np2haxstat.state._ds.base; + ES_BASE = np2haxstat.state._es.base; + SS_BASE = np2haxstat.state._ss.base; + FS_BASE = np2haxstat.state._fs.base; + GS_BASE = np2haxstat.state._gs.base; + + CPU_CS_DESC.u.seg.limit = np2haxstat.state._cs.limit; + CPU_CS_DESC.flag = np2haxstat.state._cs.type; + CPU_CS_DESC.s = np2haxstat.state._cs.desc; + CPU_CS_DESC.dpl = np2haxstat.state._cs.dpl; + CPU_CS_DESC.rpl = np2haxstat.state._cs.selector & 0x3; + CPU_CS_DESC.p = np2haxstat.state._cs.available; + CPU_CS_DESC.valid = np2haxstat.state._cs.present; + CPU_CS_DESC.d = np2haxstat.state._cs.operand_size; + CPU_CS_DESC.u.seg.g = np2haxstat.state._cs.granularity; + + CPU_DS_DESC.u.seg.limit = np2haxstat.state._ds.limit; + CPU_DS_DESC.flag = np2haxstat.state._ds.type; + CPU_DS_DESC.s = np2haxstat.state._ds.desc; + CPU_DS_DESC.dpl = np2haxstat.state._ds.dpl; + CPU_DS_DESC.rpl = np2haxstat.state._ds.selector & 0x3; + CPU_DS_DESC.p = np2haxstat.state._ds.available; + CPU_DS_DESC.valid = np2haxstat.state._ds.present; + CPU_DS_DESC.d = np2haxstat.state._ds.operand_size; + CPU_DS_DESC.u.seg.g = np2haxstat.state._ds.granularity; + + CPU_ES_DESC.u.seg.limit = np2haxstat.state._es.limit; + CPU_ES_DESC.flag = np2haxstat.state._es.type; + CPU_ES_DESC.s = np2haxstat.state._es.desc; + CPU_ES_DESC.dpl = np2haxstat.state._es.dpl; + CPU_ES_DESC.rpl = np2haxstat.state._es.selector & 0x3; + CPU_ES_DESC.p = np2haxstat.state._es.available; + CPU_ES_DESC.valid = np2haxstat.state._es.present; + CPU_ES_DESC.d = np2haxstat.state._es.operand_size; + CPU_ES_DESC.u.seg.g = np2haxstat.state._es.granularity; + + CPU_SS_DESC.u.seg.limit = np2haxstat.state._ss.limit; + CPU_SS_DESC.flag = np2haxstat.state._ss.type; + CPU_SS_DESC.s = np2haxstat.state._ss.desc; + CPU_SS_DESC.dpl = np2haxstat.state._ss.dpl; + CPU_SS_DESC.rpl = np2haxstat.state._ss.selector & 0x3; + CPU_SS_DESC.p = np2haxstat.state._ss.available; + CPU_SS_DESC.valid = np2haxstat.state._ss.present; + CPU_SS_DESC.d = np2haxstat.state._ss.operand_size; + CPU_SS_DESC.u.seg.g = np2haxstat.state._ss.granularity; + + CPU_FS_DESC.u.seg.limit = np2haxstat.state._fs.limit; + CPU_FS_DESC.flag = np2haxstat.state._fs.type; + CPU_FS_DESC.s = np2haxstat.state._fs.desc; + CPU_FS_DESC.dpl = np2haxstat.state._fs.dpl; + CPU_FS_DESC.rpl = np2haxstat.state._fs.selector & 0x3; + CPU_FS_DESC.p = np2haxstat.state._fs.available; + CPU_FS_DESC.valid = np2haxstat.state._fs.present; + CPU_FS_DESC.d = np2haxstat.state._fs.operand_size; + CPU_FS_DESC.u.seg.g = np2haxstat.state._fs.granularity; + + CPU_GS_DESC.u.seg.limit = np2haxstat.state._gs.limit; + CPU_GS_DESC.flag = np2haxstat.state._gs.type; + CPU_GS_DESC.s = np2haxstat.state._gs.desc; + CPU_GS_DESC.dpl = np2haxstat.state._gs.dpl; + CPU_GS_DESC.rpl = np2haxstat.state._gs.selector & 0x3; + CPU_GS_DESC.p = np2haxstat.state._gs.available; + CPU_GS_DESC.valid = np2haxstat.state._gs.present; + CPU_GS_DESC.d = np2haxstat.state._gs.operand_size; + CPU_GS_DESC.u.seg.g = np2haxstat.state._gs.granularity; + + CPU_EBP = np2haxstat.state._ebp; + CPU_ESP = np2haxstat.state._esp; + CPU_EIP = np2haxstat.state._eip; + CPU_PREV_EIP = np2haxstat.state._eip; // XXX: あんまり良くない + + CPU_EFLAG = np2haxstat.state._eflags; + + CPU_CR0 = np2haxstat.state._cr0; + //CPU_CR1 = np2haxstat.state._cr1; + CPU_CR2 = np2haxstat.state._cr2; + CPU_CR3 = np2haxstat.state._cr3; + CPU_CR4 = np2haxstat.state._cr4; + + CPU_GDTR_BASE = np2haxstat.state._gdt.base; + CPU_GDTR_LIMIT = np2haxstat.state._gdt.limit; + CPU_IDTR_BASE = np2haxstat.state._idt.base; + CPU_IDTR_LIMIT = np2haxstat.state._idt.limit; + CPU_LDTR = np2haxstat.state._ldt.selector; + CPU_LDTR_BASE = np2haxstat.state._ldt.base; + CPU_LDTR_LIMIT = np2haxstat.state._ldt.limit; + CPU_LDTR_DESC.flag = np2haxstat.state._ldt.type; + CPU_LDTR_DESC.s = np2haxstat.state._ldt.desc; + CPU_LDTR_DESC.dpl = np2haxstat.state._ldt.dpl; + CPU_LDTR_DESC.p = np2haxstat.state._ldt.available; + CPU_LDTR_DESC.valid = np2haxstat.state._ldt.present; + CPU_LDTR_DESC.d = np2haxstat.state._ldt.operand_size; + CPU_LDTR_DESC.u.seg.g = np2haxstat.state._ldt.granularity; + CPU_TR = np2haxstat.state._tr.selector; + CPU_TR_BASE = np2haxstat.state._tr.base; + CPU_TR_LIMIT = np2haxstat.state._tr.limit; + CPU_TR_DESC.flag = np2haxstat.state._tr.type; + CPU_TR_DESC.s = np2haxstat.state._tr.desc; + CPU_TR_DESC.dpl = np2haxstat.state._tr.dpl; + CPU_TR_DESC.p = np2haxstat.state._tr.available; + CPU_TR_DESC.valid = np2haxstat.state._tr.present; + CPU_TR_DESC.d = np2haxstat.state._tr.operand_size; + CPU_TR_DESC.u.seg.segbase = np2haxstat.state._tr.base; + CPU_TR_DESC.u.seg.limit = np2haxstat.state._tr.limit; + CPU_TR_DESC.u.seg.c = 0; + CPU_TR_DESC.u.seg.g = np2haxstat.state._tr.granularity; + + CPU_DR(0) = np2haxstat.state._dr0; + CPU_DR(1) = np2haxstat.state._dr1; + CPU_DR(2) = np2haxstat.state._dr2; + CPU_DR(3) = np2haxstat.state._dr3; + //CPU_DR(4) = np2haxstat.state._dr4; + //CPU_DR(5) = np2haxstat.state._dr5; + CPU_DR(6) = np2haxstat.state._dr6; + CPU_DR(7) = np2haxstat.state._dr7; + + CPU_STAT_PM = (np2haxstat.state._cr0 & 0x1) != 0; + CPU_STAT_PAGING = (CPU_CR0 & CPU_CR0_PG) != 0; + CPU_STAT_VM86 = (np2haxstat.state._eflags & VM_FLAG) != 0; + CPU_STAT_WP = (CPU_CR0 & CPU_CR0_WP) ? 0x10 : 0; + CPU_STAT_CPL = (UINT8)CPU_CS_DESC.rpl; + CPU_STAT_USER_MODE = (CPU_CS_DESC.rpl == 3) ? CPU_MODE_USER : CPU_MODE_SUPERVISER; + CPU_STAT_PDE_BASE = CPU_CR3 & CPU_CR3_PD_MASK; + //CPU_STAT_PDE_BASE = np2haxstat.state._pde; + + CPU_OV = CPU_FLAG & O_FLAG; + CPU_TRAP = (CPU_FLAG & (I_FLAG | T_FLAG)) == (I_FLAG | T_FLAG); + CPU_INST_OP32 = CPU_INST_AS32 = + CPU_STATSAVE.cpu_inst_default.op_32 = + CPU_STATSAVE.cpu_inst_default.as_32 = CPU_CS_DESC.d; +#if defined(USE_CPU_EIPMASK) + CPU_EIPMASK = CPU_STATSAVE.cpu_inst_default.op_32 ? 0xffffffff : 0xffff; +#endif + CPU_STAT_SS32 = CPU_SS_DESC.d; + + ia32hax_setHAXtoNP2IOADDR(); + +} +// NP2 IA-32 レジスタ → HAXレジスタ +void +ia32hax_copyregNP2toHAX(void) +{ + np2haxstat.state._eax = CPU_EAX; + np2haxstat.state._ebx = CPU_EBX; + np2haxstat.state._ecx = CPU_ECX; + np2haxstat.state._edx = CPU_EDX; + + np2haxstat.state._esi = CPU_ESI; + np2haxstat.state._edi = CPU_EDI; + + if (1 || np2haxstat.update_segment_regs) + { + np2haxstat.state._cs.selector = CPU_CS; + np2haxstat.state._ds.selector = CPU_DS; + np2haxstat.state._es.selector = CPU_ES; + np2haxstat.state._ss.selector = CPU_SS; + np2haxstat.state._fs.selector = CPU_FS; + np2haxstat.state._gs.selector = CPU_GS; + np2haxstat.state._cs.base = CS_BASE; + np2haxstat.state._ds.base = DS_BASE; + np2haxstat.state._es.base = ES_BASE; + np2haxstat.state._ss.base = SS_BASE; + np2haxstat.state._fs.base = FS_BASE; + np2haxstat.state._gs.base = GS_BASE; + + np2haxstat.state._cs.base = CPU_CS_DESC.u.seg.segbase; + np2haxstat.state._cs.limit = CPU_CS_DESC.u.seg.limit; + np2haxstat.state._cs.type = CPU_CS_DESC.flag; + np2haxstat.state._cs.desc = CPU_CS_DESC.s; + np2haxstat.state._cs.dpl = CPU_CS_DESC.dpl; + //if(wacounter > 10)np2haxstat.state._cs.selector = (np2haxstat.state._cs.selector & ‾0x3) | CPU_CS_DESC.rpl; + np2haxstat.state._cs.present = CPU_CS_DESC.valid; + np2haxstat.state._cs.available = CPU_CS_DESC.p; + np2haxstat.state._cs.operand_size = CPU_CS_DESC.d; + np2haxstat.state._cs.granularity = CPU_CS_DESC.u.seg.g; + + np2haxstat.state._ds.base = CPU_DS_DESC.u.seg.segbase; + np2haxstat.state._ds.limit = CPU_DS_DESC.u.seg.limit; + np2haxstat.state._ds.type = CPU_DS_DESC.flag; + np2haxstat.state._ds.desc = CPU_DS_DESC.s; + np2haxstat.state._ds.dpl = CPU_DS_DESC.dpl; + //if(wacounter > 10)np2haxstat.state._ds.selector = (np2haxstat.state._ds.selector & ‾0x3) | CPU_CS_DESC.rpl; + np2haxstat.state._ds.present = CPU_DS_DESC.valid; + np2haxstat.state._ds.available = CPU_DS_DESC.p; + np2haxstat.state._ds.operand_size = CPU_DS_DESC.d; + np2haxstat.state._ds.granularity = CPU_DS_DESC.u.seg.g; + + np2haxstat.state._es.base = CPU_ES_DESC.u.seg.segbase; + np2haxstat.state._es.limit = CPU_ES_DESC.u.seg.limit; + np2haxstat.state._es.type = CPU_ES_DESC.flag; + np2haxstat.state._es.desc = CPU_ES_DESC.s; + np2haxstat.state._es.dpl = CPU_ES_DESC.dpl; + //if(wacounter > 10)np2haxstat.state._es.selector = (np2haxstat.state._es.selector & ‾0x3) | CPU_CS_DESC.rpl; + np2haxstat.state._es.present = CPU_ES_DESC.valid; + np2haxstat.state._es.available = CPU_ES_DESC.p; + np2haxstat.state._es.operand_size = CPU_ES_DESC.d; + np2haxstat.state._es.granularity = CPU_ES_DESC.u.seg.g; + + np2haxstat.state._ss.base = CPU_SS_DESC.u.seg.segbase; + np2haxstat.state._ss.limit = CPU_SS_DESC.u.seg.limit; + np2haxstat.state._ss.type = CPU_SS_DESC.flag; + np2haxstat.state._ss.desc = CPU_SS_DESC.s; + np2haxstat.state._ss.dpl = CPU_SS_DESC.dpl; + //if(wacounter > 10)np2haxstat.state._ss.selector = (np2haxstat.state._ss.selector & ‾0x3) | CPU_CS_DESC.rpl; + np2haxstat.state._ss.present = CPU_SS_DESC.valid; + np2haxstat.state._ss.available = CPU_SS_DESC.p; + np2haxstat.state._ss.operand_size = CPU_SS_DESC.d; + np2haxstat.state._ss.granularity = CPU_SS_DESC.u.seg.g; + + np2haxstat.state._fs.base = CPU_FS_DESC.u.seg.segbase; + np2haxstat.state._fs.limit = CPU_FS_DESC.u.seg.limit; + np2haxstat.state._fs.type = CPU_FS_DESC.flag; + np2haxstat.state._fs.desc = CPU_FS_DESC.s; + np2haxstat.state._fs.dpl = CPU_FS_DESC.dpl; + //if(wacounter > 10)np2haxstat.state._fs.selector = (np2haxstat.state._fs.selector & ‾0x3) | CPU_CS_DESC.rpl; + np2haxstat.state._fs.present = CPU_FS_DESC.valid; + np2haxstat.state._fs.available = CPU_FS_DESC.p; + np2haxstat.state._fs.operand_size = CPU_FS_DESC.d; + np2haxstat.state._fs.granularity = CPU_FS_DESC.u.seg.g; + + np2haxstat.state._gs.base = CPU_GS_DESC.u.seg.segbase; + np2haxstat.state._gs.limit = CPU_GS_DESC.u.seg.limit; + np2haxstat.state._gs.type = CPU_GS_DESC.flag; + np2haxstat.state._gs.desc = CPU_GS_DESC.s; + np2haxstat.state._gs.dpl = CPU_GS_DESC.dpl; + //if(wacounter > 10)np2haxstat.state._gs.selector = (np2haxstat.state._gs.selector & ‾0x3) | CPU_CS_DESC.rpl; + np2haxstat.state._gs.present = CPU_GS_DESC.valid; + np2haxstat.state._gs.available = CPU_GS_DESC.p; + np2haxstat.state._gs.operand_size = CPU_GS_DESC.d; + np2haxstat.state._gs.granularity = CPU_GS_DESC.u.seg.g; + + np2haxstat.update_segment_regs = 0; + } + + np2haxstat.state._ebp = CPU_EBP; + np2haxstat.state._esp = CPU_ESP; + np2haxstat.state._eip = CPU_EIP; + + np2haxstat.state._eflags = CPU_EFLAG; + + np2haxstat.state._cr0 = CPU_CR0; + //np2haxstat.state._cr1 = CPU_CR1; + np2haxstat.state._cr2 = CPU_CR2; + np2haxstat.state._cr3 = CPU_CR3; + np2haxstat.state._cr4 = CPU_CR4; + + np2haxstat.state._gdt.base = CPU_GDTR_BASE; + np2haxstat.state._gdt.limit = CPU_GDTR_LIMIT; + np2haxstat.state._idt.base = CPU_IDTR_BASE; + np2haxstat.state._idt.limit = CPU_IDTR_LIMIT; + np2haxstat.state._ldt.selector = CPU_LDTR; + np2haxstat.state._ldt.base = CPU_LDTR_BASE; + np2haxstat.state._ldt.limit = CPU_LDTR_LIMIT; + np2haxstat.state._ldt.type = CPU_LDTR_DESC.flag; + np2haxstat.state._ldt.desc = CPU_LDTR_DESC.s; + np2haxstat.state._ldt.dpl = CPU_LDTR_DESC.dpl; + //np2haxstat.state._ldt.present = CPU_LDTR_DESC.valid; + np2haxstat.state._ldt.available = CPU_LDTR_DESC.p; + np2haxstat.state._ldt.operand_size = CPU_LDTR_DESC.d; + np2haxstat.state._ldt.granularity = CPU_LDTR_DESC.u.seg.g; + np2haxstat.state._tr.selector = CPU_TR; + np2haxstat.state._tr.base = CPU_TR_BASE; + np2haxstat.state._tr.limit = CPU_TR_LIMIT; + np2haxstat.state._tr.type = CPU_TR_DESC.flag; + np2haxstat.state._tr.desc = CPU_TR_DESC.s; + np2haxstat.state._tr.dpl = CPU_TR_DESC.dpl; + //np2haxstat.state._tr.present = CPU_TR_DESC.valid; + np2haxstat.state._tr.available = CPU_TR_DESC.p; + np2haxstat.state._tr.operand_size = CPU_TR_DESC.d; + np2haxstat.state._tr.granularity = CPU_TR_DESC.u.seg.g; + + //np2haxstat.state._tr.base = CPU_TR_DESC.u.seg.segbase; + //np2haxstat.state._tr.limit = CPU_TR_DESC.u.seg.limit; + + np2haxstat.state._dr0 = CPU_DR(0); + np2haxstat.state._dr1 = CPU_DR(1); + np2haxstat.state._dr2 = CPU_DR(2); + np2haxstat.state._dr3 = CPU_DR(3); + //np2haxstat.state._dr4 = CPU_DR(4); + //np2haxstat.state._dr5 = CPU_DR(5); + np2haxstat.state._dr6 = CPU_DR(6); + np2haxstat.state._dr7 = CPU_DR(7); + + np2haxstat.state._pde = CPU_STAT_PDE_BASE; +} + +// 仮想マシン実行 +void i386hax_vm_exec_part(void) { + HAX_TUNNEL *tunnel; + UINT8 *iobuf; + UINT32 exitstatus; + UINT32 addr; + SINT32 oldremclock; +#define PMCOUNTER_THRESHOLD 200000 + static UINT32 pmcounter = 0; + static int restoreCounter = 0; + + np2haxcore.running = 1; + + if(np2hax.emumode){ + OEMCHAR vm_str[64] = {0}; + OEMCHAR vcpu_str[64] = {0}; + NP2_HAX_CORE tmphax; + + if(restoreCounter > 0){ + restoreCounter--; + if (!(CPU_TYPE & CPUTYPE_V30)) { + CPU_EXEC(); + } + else { + CPU_EXECV30(); + } + np2haxstat.update_regs = 1; + np2haxstat.update_fpu = 1; + + np2haxcore.running = 0; + return; + } + + memcpy(&tmphax, &np2haxcore, sizeof(np2haxcore)); + + i386hax_createVM(); + + memcpy(&np2haxcore, &tmphax, sizeof(np2haxcore)); + + i386hax_resetVMCPU(); + + memcpy(&np2haxstat.state, &np2haxstat.default_state, sizeof(np2haxstat.state)); + memcpy(&np2haxstat.fpustate, &np2haxstat.default_fpustate, sizeof(np2haxstat.fpustate)); + + // HAXレジスタを更新 + ia32hax_copyregNP2toHAX(); + i386haxfunc_vcpu_setREGs(&np2haxstat.state); + i386haxfunc_vcpu_setFPU(&np2haxstat.fpustate); + //i386hax_disposeVM(); + // + //// HAXM仮想マシンを開く + //make_vm_str(vm_str, np2hax.vm_id); + //np2hax.hVMDevice = CreateFile(vm_str, + // GENERIC_READ|GENERIC_WRITE, 0, NULL, + // CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + //if (np2hax.hVMDevice == INVALID_HANDLE_VALUE) { + // TRACEOUT(("HAXM: Failed to initialize the HAX VM device.")); + // return; + //} + + //// 仮想CPUを開く + //make_vcpu_str(vcpu_str, np2hax.vm_id, 0); + //np2hax.hVCPUDevice = CreateFile(vcpu_str, + // GENERIC_READ|GENERIC_WRITE, 0, NULL, + // CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + //if (np2hax.hVCPUDevice == INVALID_HANDLE_VALUE) { + // TRACEOUT(("HAXM: Failed to initialize the HAX VCPU device.")); + //} + + // 仮想CPUとデータをやりとりするのための場所を確保 + if(i386haxfunc_vcpu_setup_tunnel(&np2hax.tunnel)==FAILURE){ + TRACEOUT(("HAXM: HAX VCPU setup tunnel failed.")); + } + i386hax_vm_allocmemory(); + if(np2hax.hVMDevice){ + i386hax_vm_setmemory(); + i386hax_vm_setbankmemory(); + i386hax_vm_setextmemory(); + i386haxfunc_vcpu_setREGs(&np2haxstat.state); + i386haxfunc_vcpu_setFPU(&np2haxstat.fpustate); + { + HAX_MSR_DATA msrstate_set = {0}; + i386haxfunc_vcpu_setMSRs(&np2haxstat.msrstate, &msrstate_set); + } + i386hax_vm_sethmemory(CPU_ADRSMASK != 0x000fffff); + i386hax_vm_setitfmemory(CPU_ITFBANK); + i386hax_vm_setvga256linearmemory(); + + i386hax_vm_setmemoryarea(mem+0xA5000, 0xA5000, 0x3000); + //i386hax_vm_setmemoryarea(mem+0xA8000, 0xA8000, 0x8000); + //i386hax_vm_setmemoryarea(mem+0xB0000, 0xB0000, 0x10000); + //i386hax_vm_setmemoryarea(mem+0xC0000, 0xC0000, 0x10000); + i386hax_vm_setmemoryarea(mem+0xD0000, 0xD0000, 0x10000); + //i386hax_vm_setmemoryarea(mem+0xE0000, 0xE0000, 0x8000); + i386hax_vm_setmemoryarea(mem+0xE8000, 0xE8000, 0x8000); + i386hax_vm_setmemoryarea(mem+0xF0000, 0xF0000, 0x8000); + + np2hax.emumode = 0; + } + } + + // XXX: 変なアドレスにぶっ飛ぶのを回避 + switch (sigsetjmp(exec_1step_jmpbuf, 1)) + { + case 0: + break; + + case 1: + VERBOSE(("ia32: return from exception")); + break; + + case 2: + VERBOSE(("ia32: return from panic")); + return; + + default: + VERBOSE(("ia32: return from unknown cause")); + break; + } + + // HAXMとのデータやりとり用 + tunnel = (HAX_TUNNEL*)np2hax.tunnel.va; + iobuf = (UINT8*)np2hax.tunnel.io_va; + + // 猫レジスタをHAXレジスタにコピー + ia32hax_copyregNP2toHAX(); + + // 必要ならHAXレジスタを更新 + if(np2haxstat.update_regs) i386haxfunc_vcpu_setREGs(&np2haxstat.state); + if(np2haxstat.update_fpu) i386haxfunc_vcpu_setFPU(&np2haxstat.fpustate); + + np2haxcore.hltflag = 0; + +coutinue_cpu: + // メモリ絡みの構成が変わっていたら変える + if(np2haxcore.lastA20en != (CPU_ADRSMASK != 0x000fffff)){ + i386hax_vm_sethmemory(CPU_ADRSMASK != 0x000fffff); + np2haxcore.lastA20en = (CPU_ADRSMASK != 0x000fffff); + } + if(np2haxcore.lastITFbank != CPU_ITFBANK){ + i386hax_vm_sethmemory(CPU_ADRSMASK != 0x000fffff); + i386hax_vm_setitfmemory(CPU_ITFBANK); + np2haxcore.lastITFbank = CPU_ITFBANK; + } + if(np2haxcore.lastVGA256linear != (vramop.mio2[0x2]==0x1 && (gdc.analog & (1 << GDCANALOG_256))!=0)){ + i386hax_vm_setvga256linearmemory(); + np2haxcore.lastVGA256linear = (vramop.mio2[0x2]==0x1 && (gdc.analog & (1 << GDCANALOG_256))!=0); + } + + // 割り込みを処理 + if(np2haxstat.irq_reqidx_cur != np2haxstat.irq_reqidx_end){ + if (tunnel->ready_for_interrupt_injection) { // 割り込み準備OK? + i386haxfunc_vcpu_interrupt(np2haxstat.irq_req[np2haxstat.irq_reqidx_cur]); + np2haxstat.irq_reqidx_cur++; + } + } + if(np2haxstat.irq_reqidx_cur != np2haxstat.irq_reqidx_end){ // 割り込みが必要ならrequest_interrupt_windowを1にする + tunnel->request_interrupt_window = 1; + }else{ + tunnel->request_interrupt_window = 0; + } + + // リセット可能フラグをクリア + np2haxcore.ready_for_reset = 0; + +coutinue_cpu_imm: + // HAXM CPU実行 + if(np2hax.emumode){ + tunnel->_exit_status = HAX_EXIT_STATECHANGE; + }else{ + i386haxfunc_vcpu_run(); + } + + // 実行停止理由を取得 + exitstatus = tunnel->_exit_status; + + // CPU実行再開のための処理(高速処理が要るもの) + switch (exitstatus) { + case HAX_EXIT_IO: // I/Oポートへのアクセス + //printf("HAX_EXIT_IO¥n"); + oldremclock = CPU_REMCLOCK; + switch(tunnel->io._direction){ // 入力 or 出力 + case HAX_IO_OUT: // 出力 + if(tunnel->io._df==0){ // 連続でデータを出力する場合の方向? + int i; + UINT8 *bufptr = iobuf; + for(i=0;iio._count;i++){ + if(tunnel->io._size==1){ // 1byte + iocore_out8(tunnel->io._port, *bufptr); + }else if(tunnel->io._size==2){ // 2yte + iocore_out16(tunnel->io._port, LOADINTELWORD(bufptr)); + }else{ // tunnel->io._size==4 // それ以外(実質4byte) + iocore_out32(tunnel->io._port, LOADINTELDWORD(bufptr)); + } + bufptr += tunnel->io._size; + } + }else{ + int i; + UINT8 *bufptr = iobuf; + bufptr += tunnel->io._size * (tunnel->io._count-1); + for(i=tunnel->io._count-1;i>=0;i--){ + if(tunnel->io._size==1){ // 1byte + iocore_out8(tunnel->io._port, *bufptr); + }else if(tunnel->io._size==2){ // 2yte + iocore_out16(tunnel->io._port, LOADINTELWORD(bufptr)); + }else{ // tunnel->io._size==4 // それ以外(実質4byte) + iocore_out32(tunnel->io._port, LOADINTELDWORD(bufptr)); + } + bufptr -= tunnel->io._size; + } + } + break; + case HAX_IO_IN: // 入力 + if(tunnel->io._df==0){ // 連続でデータを入力する場合の方向? + int i; + UINT8 *bufptr = iobuf; + for(i=0;iio._count;i++){ + if(tunnel->io._size==1){ + *bufptr = iocore_inp8(tunnel->io._port); // 1byte + }else if(tunnel->io._size==2){ + STOREINTELWORD(bufptr, iocore_inp16(tunnel->io._port)); // 2yte + }else{ // tunnel->io._size==4 + STOREINTELDWORD(bufptr, iocore_inp32(tunnel->io._port)); // それ以外(実質4byte) + } + bufptr += tunnel->io._size; + } + }else{ + int i; + UINT8 *bufptr = iobuf; + bufptr += tunnel->io._size * (tunnel->io._count-1); + for(i=tunnel->io._count-1;i>=0;i--){ + if(tunnel->io._size==1){ + *bufptr = iocore_inp8(tunnel->io._port); // 1byte + }else if(tunnel->io._size==2){ + STOREINTELWORD(bufptr, iocore_inp16(tunnel->io._port)); // 2yte + }else{ // tunnel->io._size==4 + STOREINTELDWORD(bufptr, iocore_inp32(tunnel->io._port)); // それ以外(実質4byte) + } + bufptr -= tunnel->io._size; + } + } + break; + } + if(tunnel->io._port==0x1480 || tunnel->io._port == 0x04d2){ + // ゲームポート読み取りは即座に返す + goto coutinue_cpu_imm; + } + if(CPU_REMCLOCK==-1){ + break; + } + //CPU_REMCLOCK = oldremclock; + + // 高速化のために一部のI/Oポートの処理を簡略化 + //if(tunnel->io._port != 0x90 && tunnel->io._port != 0x92 && tunnel->io._port != 0x94 && + // tunnel->io._port != 0xc8 && tunnel->io._port != 0xca && tunnel->io._port != 0xcc && tunnel->io._port != 0xbe && tunnel->io._port != 0x4be) { + // (0x430 <= tunnel->io._port && tunnel->io._port <= 0x64e && !(g_nevent.item[NEVENT_SASIIO].flag & NEVENT_ENABLE)) || + // (0x7FD9 <= tunnel->io._port && tunnel->io._port <= 0x7FDF)){ + if(tunnel->io._port==0x640){ + // 厳しめにする + if (np2haxcore.hurryup) { + np2haxcore.hurryup = 0; + break; + } + } + { + SINT32 diff; + np2haxcore.clockcount = GetTickCounter_Clock(); + diff = (np2haxcore.clockcount.QuadPart - np2haxcore.lastclock.QuadPart) * pccore.realclock / np2haxcore.clockpersec.QuadPart; + if(CPU_REMCLOCK > 0){ + CPU_REMCLOCK -= diff; + } + np2haxcore.lastclock.QuadPart = np2haxcore.clockcount.QuadPart; + } + + // 時間切れなら抜ける + if (CPU_REMCLOCK <= 0) { + break; + } + if (CPU_REMCLOCK > 0 && timing_getcount_baseclock()!=0) { + CPU_REMCLOCK = 0; + break; + } + i386haxfunc_vcpu_getREGs(&np2haxstat.state); + i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); + np2haxstat.update_regs = np2haxstat.update_fpu = 0; + + ia32hax_copyregHAXtoNP2(); + pic_irq(); + + goto coutinue_cpu; + //} + break; + case HAX_EXIT_FAST_MMIO: // メモリマップドI/Oへのアクセス + //printf("HAX_EXIT_FAST_MMIO¥n"); + { + HAX_FASTMMIO *mmio = (HAX_FASTMMIO*)np2hax.tunnel.io_va; + + switch(mmio->direction){ // データREAD/WRITEの判定 + case 0: // データREAD + if(mmio->size==1){ + mmio->value = memp_read8((UINT32)mmio->gpa); + }else if(mmio->size==2){ + mmio->value = memp_read16((UINT32)mmio->gpa); + }else{ // mmio->size==4 + mmio->value = memp_read32((UINT32)mmio->gpa); + } + break; + case 1: // データWRITE + if(mmio->size==1){ + memp_write8((UINT32)mmio->gpa, (UINT8)mmio->value); + }else if(mmio->size==2){ + memp_write16((UINT32)mmio->gpa, (UINT16)mmio->value); + }else{ // mmio->size==4 + memp_write32((UINT32)mmio->gpa, (UINT32)mmio->value); + } + break; + default: // データREAD→データWRITE + if(mmio->size==1){ + memp_write8((UINT32)mmio->gpa2, memp_read8((UINT32)mmio->gpa)); + }else if(mmio->size==2){ + memp_write16((UINT32)mmio->gpa2, memp_read16((UINT32)mmio->gpa)); + }else{ // mmio->size==4 + memp_write32((UINT32)mmio->gpa2, memp_read32((UINT32)mmio->gpa)); + } + break; + } + } + { + SINT32 diff; + np2haxcore.clockcount = GetTickCounter_Clock(); + diff = (np2haxcore.clockcount.QuadPart - np2haxcore.lastclock.QuadPart) * pccore.realclock / np2haxcore.clockpersec.QuadPart; + if(CPU_REMCLOCK > 0){ + CPU_REMCLOCK -= diff; + } + np2haxcore.lastclock.QuadPart = np2haxcore.clockcount.QuadPart; + } + + // 時間切れなら抜ける + if (CPU_REMCLOCK <= 0) { + break; + } + if (CPU_REMCLOCK > 0 && timing_getcount_baseclock()!=0) { + CPU_REMCLOCK = 0; + break; + } + i386haxfunc_vcpu_getREGs(&np2haxstat.state); + i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); + np2haxstat.update_regs = np2haxstat.update_fpu = 0; + + ia32hax_copyregHAXtoNP2(); + pic_irq(); + goto coutinue_cpu; + break; + } + + // HAXMレジスタを読み取り + i386haxfunc_vcpu_getREGs(&np2haxstat.state); + i386haxfunc_vcpu_getFPU(&np2haxstat.fpustate); + np2haxstat.update_regs = np2haxstat.update_fpu = 0; + + // HAXMレジスタ→猫レジスタにコピー + ia32hax_copyregHAXtoNP2(); + + // CPU実行再開のための処理(処理速度はどうでもいい物) + switch (exitstatus) { + case HAX_EXIT_MMIO: // メモリマップドI/Oへのアクセス(旧式・もう呼ばれないと思う) + //printf("HAX_EXIT_MMIO¥n"); + break; + case HAX_EXIT_REALMODE: // 事前設定をするとリアルモードの時に呼ばれるらしい + //printf("HAX_EXIT_REALMODE¥n"); + break; + case HAX_EXIT_INTERRUPT: // 割り込み・・・? + //printf("HAX_EXIT_INTERRUPT¥n"); + // リセット可能フラグを立てる + np2haxcore.ready_for_reset = 1; + break; + case HAX_EXIT_UNKNOWN: // 謎 + //printf("HAX_EXIT_UNKNOWN¥n"); + //if(!CPU_RESETREQ){ + // np2hax.emumode = 1; + // CPU_REMCLOCK = 0; + // if (!(CPU_TYPE & CPUTYPE_V30)) { + // CPU_EXEC(); + // } + // else { + // CPU_EXECV30(); + // } + // np2haxstat.update_regs = 1; + // np2haxstat.update_fpu = 1; + //} + break; + case HAX_EXIT_HLT: // HLT命令が実行されたとき + np2haxcore.hltflag = 1; + //printf("HAX_EXIT_HLT¥n"); + // リセット可能フラグを立てる + np2haxcore.ready_for_reset = 1; + // リアルモード or 仮想86 + if (!CPU_STAT_PM || CPU_STAT_VM86) + { + CPU_PREV_EIP = CPU_EIP - 1; // HLTの次の命令に移ってしまっているので・・・ + addr = CPU_PREV_EIP + (CPU_CS << 4); + // BIOSコール + if (memp_read8(addr) == bioshookinfo.hookinst) + { + if (ia32hax_bioscall()) + { + np2haxstat.update_regs = 1; + np2haxstat.update_segment_regs = 1; + // カウンタリセット + pmcounter = 0; + np2haxcore.hltflag = 0; // すぐに再開 + } + } + } + break; + case HAX_EXIT_STATECHANGE: // CPU状態が変わったとき・・・と言いつつ、事実上CPUが実行不能(panic)になったときしか呼ばれない + //printf("HAX_EXIT_STATECHANGE¥n"); + // リセット可能フラグを立てる + np2haxcore.ready_for_reset = 1; + //if(!CPU_RESETREQ){ + // np2hax.emumode = 1; + // //CPU_REMCLOCK = 0; + // if (!(CPU_TYPE & CPUTYPE_V30)) { + // CPU_EXEC(); + // } + // else { + // CPU_EXECV30(); + // } + // np2haxstat.update_regs = 1; + // np2haxstat.update_fpu = 1; + // restoreCounter = 100000; + //} + //{ + // int i; + // UINT32 memdumpa[0x100]; + // UINT8 memdump[0x100]; + // UINT32 baseaddr; + // addr = CPU_EIP + (CPU_CS << 4); + // baseaddr = addr & ‾0xff; + // for(i=0;i<0x100;i++){ + // memdumpa[i] = baseaddr + i; + // memdump[i] = memp_read8(memdumpa[i]); + // } + // //msgbox("HAXM_ia32_panic", "HAXM CPU panic"); + // //pcstat.hardwarereset = TRUE; + // return; + //} + break; + case HAX_EXIT_PAUSED: // 一時停止? + //printf("HAX_EXIT_PAUSED¥n"); + // リセット可能フラグを立てる + np2haxcore.ready_for_reset = 1; + break; + case HAX_EXIT_PAGEFAULT: // ページフォールト? + //printf("HAX_EXIT_PAGEFAULT¥n"); + break; + case HAX_EXIT_DEBUG: // デバッグ命令(INT3 CCh)が呼ばれたとき + //printf("HAX_EXIT_DEBUG¥n"); + // リセット可能フラグを立てる + np2haxcore.ready_for_reset = 1; + break; + default: + break; + } + + np2haxcore.running = 0; +} +void i386hax_vm_exec(void) { + static int skipcounter = 0; + static SINT32 remain_clk = 0; + SINT32 remclktmp = CPU_REMCLOCK; + int timing; + int i; + if(pcstat.hardwarereset){ + CPU_REMCLOCK = 0; + return; + } + if(!np2haxcore.hltflag || !CPU_isEI || np2haxstat.irq_reqidx_cur != np2haxstat.irq_reqidx_end){ + CPU_REMCLOCK += remain_clk; + np2haxcore.lastclock = GetTickCounter_Clock(); + while(CPU_REMCLOCK > 0){ + int remclkdiff = 0; + i386hax_vm_exec_part(); + np2haxcore.clockcount = GetTickCounter_Clock(); + if(CPU_REMCLOCK > 0){ + remclkdiff = (np2haxcore.clockcount.QuadPart - np2haxcore.lastclock.QuadPart) * pccore.realclock / np2haxcore.clockpersec.QuadPart; + CPU_REMCLOCK -= remclkdiff; + } + np2haxcore.lastclock = np2haxcore.clockcount; + if(dmac.working) { + for(i=0;i<(remclkdiff+3)/4;i++){ + dmax86(); // XXX: 本当は1命令実行ごとに呼ぶのが正しいけど出来ないのでまとめて呼ぶ・・・ + } + } + if(CPU_RESETREQ) break; + if(pcstat.hardwarereset) break; + if (CPU_REMCLOCK > 0 && (timing = timing_getcount_baseclock())!=0) { + CPU_REMCLOCK = 0; + break; + } + if(np2haxcore.hltflag){ + CPU_REMCLOCK = 0; + remain_clk = 0; + break; + } + } + if(CPU_REMCLOCK <= 0){ + remain_clk = CPU_REMCLOCK; + }else{ + remain_clk = 0; + } + if (CPU_REMCLOCK < -(SINT32)(CPU_BASECLOCK*3)) { + np2haxcore.hurryup = 1; + } + CPU_REMCLOCK = 0; + }else{ + if(dmac.working) { + for(i=0;i<(CPU_REMCLOCK+3)/4;i++){ + dmax86(); + } + } + CPU_REMCLOCK = 0; + remain_clk = 0; + } +} + +void i386hax_disposeVM(void) { + +#if defined(_WIN32) + if(!np2hax.hDevice) return; + if(!np2hax.hVCPUDevice) return; + if(!np2hax.hVMDevice) return; + + // 仮想マシンを閉じる + CloseHandle(np2hax.hVCPUDevice); + np2hax.hVCPUDevice = NULL; + CloseHandle(np2hax.hVMDevice); + np2hax.hVMDevice = NULL; + + TRACEOUT(("HAXM: HAX VM disposed.")); + //msgbox("HAXM deinit", "HAX VM disposed."); +#endif +} + +void i386hax_deinitialize(void) { + +#if defined(_WIN32) + if(!np2hax.hDevice) return; + + i386hax_disposeVM(); + + // HAXMを閉じる + CloseHandle(np2hax.hDevice); + np2hax.hDevice = NULL; + + TRACEOUT(("HAXM: HAX deinitialized.")); + //msgbox("HAXM deinit", "HAX deinitialized."); + +#endif +} + +// HAXM仮想マシンで使用するホストのメモリ領域を登録(登録済みメモリのみ仮想マシンに割り当て可能) +void i386hax_vm_allocmemory(void) { + +#if defined(_WIN32) + HAX_ALLOC_RAM_INFO info = {0}; + + if(!np2hax.hVMDevice) return; + + info.size = 0x200000; + info.va = (UINT64)mem; + if(i386haxfunc_allocRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM alloc memory failed.")); + msgbox("HAXM VM", "HAX VM alloc memory failed."); + np2hax.enable = 0; + i386hax_disposeVM(); + return; + } + + info.size = CPU_EXTMEMSIZE + 4096; + info.va = (UINT64)CPU_EXTMEM; + if(i386haxfunc_allocRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM alloc memory failed.")); + msgbox("HAXM VM", "HAX VM alloc memory failed."); + np2hax.enable = 0; + i386hax_disposeVM(); + return; + } + + info.size = sizeof(vramex_base); + info.va = (UINT64)vramex; + if(i386haxfunc_allocRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM alloc memory failed.")); + msgbox("HAXM VM", "HAX VM alloc memory failed."); + np2hax.enable = 0; + i386hax_disposeVM(); + return; + } + + TRACEOUT(("HAXM: HAX VM alloc memory.")); + //msgbox("HAXM VM", "HAX VM alloc memory."); +#endif +} +void i386hax_vm_allocmemoryex(UINT8 *vramptr, UINT32 size) { + +#if defined(_WIN32) + HAX_ALLOC_RAM_INFO info = {0}; + + if(!np2hax.hVMDevice) return; + + info.size = size; + info.va = (UINT64)vramptr; + if(i386haxfunc_allocRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM alloc memory failed.")); + msgbox("HAXM VM", "HAX VM alloc memory failed."); + return; + } + + TRACEOUT(("HAXM: HAX VM alloc memory.")); + //msgbox("HAXM VM", "HAX VM alloc memory."); +#endif +} + +// HAXM仮想マシンのゲスト物理アドレス(Guest Physical Address; GPA)にホストの仮想アドレス(Host Virtual Address; HVA)を割り当て +void i386hax_vm_setmemory(void) { + +#if defined(_WIN32) + HAX_SET_RAM_INFO info = {0}; + + if(!np2hax.enable) return; + if(!np2hax.hVMDevice) return; + + info.pa_start = 0; + info.size = 0xA0000; + info.flags = 0; + info.va = (UINT64)mem; + if(i386haxfunc_setRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM set memory failed.")); + msgbox("HAXM VM", "HAX VM set memory failed."); + np2hax.enable = 0; + return; + } + + //info.pa_start = 0xFFF00000; + //info.size = 0xF8000; + //info.flags = 0; + //info.va = (UINT64)mem; + //if(i386haxfunc_setRAM(&info)==FAILURE){ + // TRACEOUT(("HAXM: HAX VM set memory failed.")); + // msgbox("HAXM VM", "HAX VM set memory failed."); + // np2hax.enable = 0; + // return; + //} + + TRACEOUT(("HAXM: HAX VM set memory.")); + //msgbox("HAXM VM", "HAX VM set memory."); +#endif +} +void i386hax_vm_setbankmemory() { + +} +void i386hax_vm_setitfmemory(UINT8 isitfbank) { + +#if defined(_WIN32) + HAX_SET_RAM_INFO info = {0}; + + if(!np2hax.hVMDevice) + if(!np2hax.enable) return; + + info.pa_start = 0xF8000; + info.size = 0x8000; + info.flags = HAX_RAM_INFO_INVALID; + if(i386haxfunc_setRAM(&info)==FAILURE){ + } + if(isitfbank){ + info.flags = HAX_RAM_INFO_ROM; + info.va = (UINT64)(mem + ITF_ADRS); + }else{ + info.flags = HAX_RAM_INFO_ROM; + info.va = (UINT64)(mem + info.pa_start); + } + if(i386haxfunc_setRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM set ITF bank memory failed.")); + msgbox("HAXM VM", "HAX VM set ITF bank memory failed."); + np2hax.enable = 0; + return; + } + + info.pa_start = 0xFFFF8000; + info.size = 0x8000; + info.flags = HAX_RAM_INFO_INVALID; + if(i386haxfunc_setRAM(&info)==FAILURE){ + } + if(isitfbank){ + info.flags = HAX_RAM_INFO_ROM; + info.va = (UINT64)(mem + ITF_ADRS); + }else{ + info.flags = HAX_RAM_INFO_ROM; + info.va = (UINT64)(mem + 0xF8000); + } + if(i386haxfunc_setRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM set ITF bank memory failed.")); + msgbox("HAXM VM", "HAX VM set ITF bank memory failed."); + np2hax.enable = 0; + return; + } + + if(isitfbank){ + TRACEOUT(("HAXM: HAX VM set ITF bank memory. (ITF)")); + //msgbox("HAXM VM", "HAX VM set ITF bank memory. (ITF)"); + }else{ + TRACEOUT(("HAXM: HAX VM set ITF bank memory. (OFF)")); + //msgbox("HAXM VM", "HAX VM set ITF bank memory. (OFF)"); + } +#endif +} +void i386hax_vm_sethmemory(UINT8 a20en) { + +#if defined(_WIN32) + HAX_SET_RAM_INFO info = {0}; + + if(!np2hax.enable) return; + if(!np2hax.hVMDevice) return; + + info.pa_start = 0x100000; + info.size = 0x10000; + info.flags = HAX_RAM_INFO_INVALID; + if(i386haxfunc_setRAM(&info)==FAILURE){ + } + + if(a20en){ + info.flags = 0; + info.va = (UINT64)(mem + info.pa_start); + }else{ + info.flags = 0; + info.va = (UINT64)(mem); + } + if(i386haxfunc_setRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM set high memory failed.")); + msgbox("HAXM VM", "HAX VM set high memory failed."); + np2hax.enable = 0; + return; + } + + if(a20en){ + TRACEOUT(("HAXM: HAX VM set high memory. (A20 ON)")); + //msgbox("HAXM VM", "HAX VM set high memory. (A20 ON)"); + }else{ + TRACEOUT(("HAXM: HAX VM set high memory. (A20 OFF)")); + //msgbox("HAXM VM", "HAX VM set ITF bank memory. (A20 OFF)"); + } +#endif +} +void i386hax_vm_setextmemory(void) { + +#if defined(_WIN32) + HAX_SET_RAM_INFO info = {0}; + + if(!np2hax.enable) return; + if(!np2hax.hVMDevice) return; + + info.pa_start = 0x110000; + info.size = CPU_EXTLIMIT16 - 0x110000; + info.flags = 0; + info.va = (UINT64)(CPU_EXTMEMBASE + info.pa_start); + if(i386haxfunc_setRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM set ext16 memory failed.")); + msgbox("HAXM VM", "HAX VM set ext16 memory failed."); + np2hax.enable = 0; + return; + } + + if(CPU_EXTLIMIT > 0x01000000){ + info.pa_start = 0x01000000; + info.size = CPU_EXTLIMIT - 0x01000000; + info.flags = 0; + info.va = (UINT64)(CPU_EXTMEMBASE + info.pa_start); + if(i386haxfunc_setRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM set ext memory failed.")); + msgbox("HAXM VM", "HAX VM set ext memory failed."); + np2hax.enable = 0; + return; + } + } + + TRACEOUT(("HAXM: HAX VM set ext memory.")); + //msgbox("HAXM VM", "HAX VM set ext memory."); +#endif +} + +void i386hax_vm_setvga256linearmemory(void) { + +#if defined(_WIN32) + HAX_SET_RAM_INFO info = {0}; + + if(!np2hax.enable) return; + if(!np2hax.hVMDevice) return; + + info.pa_start = 0xF00000; + info.size = 0x80000; + info.flags = HAX_RAM_INFO_INVALID; + i386haxfunc_setRAM(&info); + if(vramop.mio2[0x2]==0x1 && (gdc.analog & (1 << GDCANALOG_256))!=0){ + info.flags = 0; + info.va = (UINT64)vramex; + if(i386haxfunc_setRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM set vga256 linear memory failed.")); + msgbox("HAXM VM", "HAX VM set vga256 linear memory failed."); + return; + } + + TRACEOUT(("HAXM: HAX VM set vga256 linear memory.")); + } + + info.pa_start = 0xfff00000; + info.size = 0x80000; + info.flags = HAX_RAM_INFO_INVALID; + info.va = NULL; + i386haxfunc_setRAM(&info); + info.flags = 0; + info.va = (UINT64)vramex; + if(i386haxfunc_setRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM set vga256 0xfff00000 linear memory failed.")); + msgbox("HAXM VM", "HAX VM set vga256 0xfff00000 linear memory failed."); + return; + } + //msgbox("HAXM VM", "HAX VM set ext memory."); +#endif +} + +void i386hax_vm_setmemoryarea(UINT8 *vramptr, UINT32 addr, UINT32 size) { + +#if defined(_WIN32) + HAX_SET_RAM_INFO info = {0}; + + if(!np2hax.enable) return; + if(!np2hax.hVMDevice) return; + + info.pa_start = addr; + info.size = size; + info.flags = HAX_RAM_INFO_INVALID; + i386haxfunc_setRAM(&info); + if(vramptr){ + info.flags = 0; + info.va = (UINT64)vramptr; + if(i386haxfunc_setRAM(&info)==FAILURE){ + TRACEOUT(("HAXM: HAX VM set memory area failed.")); + //msgbox("HAXM VM", "HAX VM set memory area failed."); + return; + } + + TRACEOUT(("HAXM: HAX VM set memory area.")); + } +#endif +} +void i386hax_vm_removememoryarea(UINT8 *vramptr, UINT32 addr, UINT32 size) { + +#if defined(_WIN32) + HAX_SET_RAM_INFO info = {0}; + + if(!np2hax.enable) return; + if(!np2hax.hVMDevice) return; + + info.pa_start = addr; + info.size = size; + info.flags = HAX_RAM_INFO_INVALID; + i386haxfunc_setRAM(&info); +#endif +} + #endif \ No newline at end of file diff --git a/i386hax/haxcore.h b/i386hax/haxcore.h index 8dc322a4..7f6282d2 100644 --- a/i386hax/haxcore.h +++ b/i386hax/haxcore.h @@ -1,114 +1,114 @@ - -#ifndef NP2_I386HAX_HAXCORE_H__ -#define NP2_I386HAX_HAXCORE_H__ - -#if defined(SUPPORT_IA32_HAXM) - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#if !defined(_WINDOWS) -typedef uint8_t BYTE; -typedef uint32_t DWORD; -typedef int32_t LONG; -typedef int64_t LONGLONG; - -typedef int HANDLE; -#endif - -typedef struct _NP2_HAX { - UINT8 available; // HAXMgp - UINT8 enable; // HAXML - UINT8 emumode; // LCPUő֏ - HANDLE hDevice; // HAXMfoCX̃nh - HANDLE hVMDevice; // HAXMz}VfoCX̃nh - HANDLE hVCPUDevice; // HAXMzCPUfoCX̃nh - UINT32 vm_id; // HAXMz}VID - HAX_TUNNEL_INFO tunnel; // HAXMz}VƂ̃f[^Ƃptunnel - - UINT8 bioshookenable; // fobOWX^ɂG~[VBIOStbNL -} NP2_HAX; -typedef struct { - HAX_VCPU_STATE state; // HAXMzCPŨWX^ - HAX_FX_LAYOUT fpustate; // HAXMzCPUFPUWX^ - HAX_MSR_DATA msrstate; // HAXMzCPUMSR - HAX_VCPU_STATE default_state; // HAXMzCPŨWX^iftHglj - HAX_FX_LAYOUT default_fpustate; // HAXMzCPUFPUWX^iftHglj - HAX_MSR_DATA default_msrstate; // HAXMzCPUMSRiftHglj - UINT8 update_regs; // vWX^XV - UINT8 update_segment_regs; // vZOgWX^XV - UINT8 update_fpu; // vFPUWX^XV - - UINT8 irq_req[256]; // 荞ݑҋ@obt@BC̊荞݃xN^i[ - UINT8 irq_reqidx_cur; // 荞ݑҋ@obt@̓ǂݎʒu - UINT8 irq_reqidx_end; // 荞ݑҋ@obt@݈̏ʒu -} NP2_HAX_STAT; -typedef struct { - UINT8 running; // HAXM CPUstO - - // ^C~Opiperformance countergpj - int64_t lastclock; // ÕNbN - int64_t clockpersec; // 1bNbN - int64_t clockcount; // ݂̃NbN - - UINT8 I_ratio; - - UINT32 lastA20en; // OA20CL - UINT32 lastITFbank; // OITFoNgpĂ - UINT32 lastVGA256linear; // O256F[h̃jAAhXgpĂ - UINT32 lastVRAMMMIO; // VRAM̃AhXMMIO[h - - UINT8 hurryup; // ^C~OxĂ̂ŋ}ׂ - - UINT8 hltflag; // HLT߂Œ~tO - - UINT8 allocwabmem; // WAB vramptro^ς݂Ȃ1 - - UINT8 ready_for_reset; -} NP2_HAX_CORE; - -#define NP2HAX_I_RATIO_MAX 1024 - -extern NP2_HAX np2hax; -extern NP2_HAX_STAT np2haxstat; -extern NP2_HAX_CORE np2haxcore; - -#ifdef __cplusplus -} -#endif - -UINT8 i386hax_check(void); // HAXMgp”\`FbN -void i386hax_initialize(void); // HAXM -void i386hax_createVM(void); // HAXMz}V쐬 -void i386hax_resetVMMem(void); // HAXMz}VZbgij -void i386hax_resetVMCPU(void); // HAXMz}VZbgiCPUj -void i386hax_disposeVM(void); // HAXMz}Vj -void i386hax_deinitialize(void); // HAXM - -void i386hax_vm_exec(void); // HAXMzCPU̎s - -void i386hax_vm_allocmemory(void); // ̈o^i{̈j -void i386hax_vm_allocmemoryex(UINT8 *vramptr, UINT32 size); // ̈o^iėpj - -// QXgAhX(Guest Physical Address; GPA)ɃzXg̉zAhX(Host Virtual Address; HVA)蓖 -void i386hax_vm_setmemory(void); // 00000h`BFFFFh܂ -void i386hax_vm_setbankmemory(void); // A0000h`F7FFFh܂ -void i386hax_vm_setitfmemory(UINT8 isitfbank); // F8000h`FFFFFh܂ -void i386hax_vm_sethmemory(UINT8 a20en); // 100000h`10FFFFh܂ -void i386hax_vm_setextmemory(void); // 110000hȍ~ -void i386hax_vm_setvga256linearmemory(void); // 0xF00000`0xF80000 -//void i386hax_vm_setwabmemory(UINT8 *vramptr, UINT32 addr, UINT32 size); - -// ėp ̈抄蓖 -void i386hax_vm_setmemoryarea(UINT8 *vramptr, UINT32 addr, UINT32 size); -void i386hax_vm_removememoryarea(UINT8 *vramptr, UINT32 addr, UINT32 size); - -void ia32hax_copyregHAXtoNP2(void); -void ia32hax_copyregNP2toHAX(void); - -#endif - -#endif /* !NP2_I386HAX_HAXCORE_H__ */ + +#ifndef NP2_I386HAX_HAXCORE_H__ +#define NP2_I386HAX_HAXCORE_H__ + +#if defined(SUPPORT_IA32_HAXM) + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#if !defined(_WINDOWS) +typedef uint8_t BYTE; +typedef uint32_t DWORD; +typedef int32_t LONG; +typedef int64_t LONGLONG; + +typedef int HANDLE; +#endif + +typedef struct _NP2_HAX { + UINT8 available; // HAXM使用可 + UINT8 enable; // HAXM有効 + UINT8 emumode; // 猫CPUで代替処理中 + HANDLE hDevice; // HAXMデバイスのハンドル + HANDLE hVMDevice; // HAXM仮想マシンデバイスのハンドル + HANDLE hVCPUDevice; // HAXM仮想CPUデバイスのハンドル + UINT32 vm_id; // HAXM仮想マシンID + HAX_TUNNEL_INFO tunnel; // HAXM仮想マシンとのデータやりとり用tunnel + + UINT8 bioshookenable; // デバッグレジスタによるエミュレーションBIOSフック有効 +} NP2_HAX; +typedef struct { + HAX_VCPU_STATE state; // HAXM仮想CPUのレジスタ + HAX_FX_LAYOUT fpustate; // HAXM仮想CPUのFPUレジスタ + HAX_MSR_DATA msrstate; // HAXM仮想CPUのMSR + HAX_VCPU_STATE default_state; // HAXM仮想CPUのレジスタ(デフォルト値) + HAX_FX_LAYOUT default_fpustate; // HAXM仮想CPUのFPUレジスタ(デフォルト値) + HAX_MSR_DATA default_msrstate; // HAXM仮想CPUのMSR(デフォルト値) + UINT8 update_regs; // 要レジスタ更新 + UINT8 update_segment_regs; // 要セグメントレジスタ更新 + UINT8 update_fpu; // 要FPUレジスタ更新 + + UINT8 irq_req[256]; // 割り込み待機バッファ。大気中の割り込みベクタが格納される + UINT8 irq_reqidx_cur; // 割り込み待機バッファの読み取り位置 + UINT8 irq_reqidx_end; // 割り込み待機バッファの書き込み位置 +} NP2_HAX_STAT; +typedef struct { + UINT8 running; // HAXM CPU実行中フラグ + + // タイミング調整用(performance counter使用) + int64_t lastclock; // 前回のクロック + int64_t clockpersec; // 1秒あたりクロック数 + int64_t clockcount; // 現在のクロック + + UINT8 I_ratio; + + UINT32 lastA20en; // 前回A20ラインが有効だったか + UINT32 lastITFbank; // 前回ITFバンクを使用していたか + UINT32 lastVGA256linear; // 前回256色モードのリニアアドレスを使用していたか + UINT32 lastVRAMMMIO; // VRAMのメモリアドレスがMMIOモードか + + UINT8 hurryup; // タイミングが遅れているので急ぐべし + + UINT8 hltflag; // HLT命令で停止中フラグ + + UINT8 allocwabmem; // WAB vramptr登録済みなら1 + + UINT8 ready_for_reset; +} NP2_HAX_CORE; + +#define NP2HAX_I_RATIO_MAX 1024 + +extern NP2_HAX np2hax; +extern NP2_HAX_STAT np2haxstat; +extern NP2_HAX_CORE np2haxcore; + +#ifdef __cplusplus +} +#endif + +UINT8 i386hax_check(void); // HAXM使用可能チェック +void i386hax_initialize(void); // HAXM初期化 +void i386hax_createVM(void); // HAXM仮想マシン作成 +void i386hax_resetVMMem(void); // HAXM仮想マシンリセット(メモリ周り) +void i386hax_resetVMCPU(void); // HAXM仮想マシンリセット(CPU周り) +void i386hax_disposeVM(void); // HAXM仮想マシン破棄 +void i386hax_deinitialize(void); // HAXM解放 + +void i386hax_vm_exec(void); // HAXM仮想CPUの実行 + +void i386hax_vm_allocmemory(void); // メモリ領域を登録(基本領域) +void i386hax_vm_allocmemoryex(UINT8 *vramptr, UINT32 size); // メモリ領域を登録(汎用) + +// ゲスト物理アドレス(Guest Physical Address; GPA)にホストの仮想アドレス(Host Virtual Address; HVA)を割り当て +void i386hax_vm_setmemory(void); // 00000h~BFFFFhまで +void i386hax_vm_setbankmemory(void); // A0000h~F7FFFhまで +void i386hax_vm_setitfmemory(UINT8 isitfbank); // F8000h~FFFFFhまで +void i386hax_vm_sethmemory(UINT8 a20en); // 100000h~10FFFFhまで +void i386hax_vm_setextmemory(void); // 110000h以降 +void i386hax_vm_setvga256linearmemory(void); // 0xF00000~0xF80000 +//void i386hax_vm_setwabmemory(UINT8 *vramptr, UINT32 addr, UINT32 size); + +// 汎用 メモリ領域割り当て +void i386hax_vm_setmemoryarea(UINT8 *vramptr, UINT32 addr, UINT32 size); +void i386hax_vm_removememoryarea(UINT8 *vramptr, UINT32 addr, UINT32 size); + +void ia32hax_copyregHAXtoNP2(void); +void ia32hax_copyregNP2toHAX(void); + +#endif + +#endif /* !NP2_I386HAX_HAXCORE_H__ */ diff --git a/i386hax/haxfunc.c b/i386hax/haxfunc.c index b336fbb0..8dcf09c9 100644 --- a/i386hax/haxfunc.c +++ b/i386hax/haxfunc.c @@ -1,520 +1,520 @@ -/* - * Copyright (c) 2019 SimK - * 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. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -#include -#include "haxfunc.h" -#include "haxcore.h" - -#if defined(SUPPORT_IA32_HAXM) - -// HAXM IOCTL -UINT8 i386haxfunc_getversion(HAX_MODULE_VERSION *version) { - - int ret = 0; - DWORD dwSize; - - if(!np2hax.hDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hDevice, HAX_IOCTL_VERSION, - NULL, 0, - version, sizeof(HAX_MODULE_VERSION), &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hDevice, HAX_IOCTL_VERSION, version); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_getcapability(HAX_CAPINFO *cap) { - int ret = 0; - DWORD dwSize; - - if(!np2hax.hDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hDevice, HAX_IOCTL_CAPABILITY, - NULL, 0, - cap, sizeof(HAX_CAPINFO), &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hDevice, HAX_IOCTL_CAPABILITY, cap); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_setmemlimit(HAX_SET_MEMLIMIT *memlimit) { - int ret = 0; - DWORD dwSize; - - if(!np2hax.hDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hDevice, HAX_IOCTL_SET_MEMLIMIT, - memlimit, sizeof(HAX_SET_MEMLIMIT), - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hDevice, HAX_IOCTL_SET_MEMLIMIT, memlimit); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_createVM(UINT32 *vm_id) { - int ret = 0; - DWORD dwSize; - - if(!np2hax.hDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hDevice, HAX_IOCTL_CREATE_VM, - NULL, 0, - vm_id, sizeof(UINT32), &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hDevice, HAX_IOCTL_CREATE_VM, vm_id); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} - -// HAXM VM IOCTL -UINT8 i386haxfunc_notifyQEMUversion(HAX_QEMU_VERSION *hax_qemu_ver) { - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVMDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVMDevice, HAX_VM_IOCTL_NOTIFY_QEMU_VERSION, - hax_qemu_ver, sizeof(HAX_QEMU_VERSION), - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVMDevice, HAX_VM_IOCTL_NOTIFY_QEMU_VERSION, hax_qemu_ver); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} - -UINT8 i386haxfunc_VCPUcreate(UINT32 vcpu_id) { - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVMDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVMDevice, HAX_VM_IOCTL_VCPU_CREATE, - &vcpu_id, sizeof(UINT32), - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVMDevice, HAX_VM_IOCTL_VCPU_CREATE, &vcpu_id); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} - -UINT8 i386haxfunc_allocRAM(HAX_ALLOC_RAM_INFO *allocraminfo) { - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVMDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVMDevice, HAX_VM_IOCTL_ALLOC_RAM, - allocraminfo, sizeof(HAX_ALLOC_RAM_INFO), - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVMDevice, HAX_VM_IOCTL_ALLOC_RAM, allocraminfo); - if (ret == -1) { -#endif -#if defined(_WINDOWS) - ret = GetLastError(); -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_addRAMblock(HAX_RAMBLOCK_INFO *ramblkinfo) { - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVMDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVMDevice, HAX_VM_IOCTL_ADD_RAMBLOCK, - ramblkinfo, sizeof(HAX_RAMBLOCK_INFO), - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVMDevice, HAX_VM_IOCTL_ADD_RAMBLOCK, ramblkinfo); - if (ret == -1) { -#endif -#if defined(_WINDOWS) - ret = GetLastError(); -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_setRAM(HAX_SET_RAM_INFO *setraminfo) { - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVMDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVMDevice, HAX_VM_IOCTL_SET_RAM, - setraminfo, sizeof(HAX_SET_RAM_INFO), - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVMDevice, HAX_VM_IOCTL_SET_RAM, setraminfo); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} - -// HAXM VCPU IOCTL -UINT8 i386haxfunc_vcpu_run(){ - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_RUN, - NULL, 0, - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_RUN, NULL); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_vcpu_setup_tunnel(HAX_TUNNEL_INFO *info){ - int ret = 0; - DWORD dwSize; - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SETUP_TUNNEL, - NULL, 0, - info, sizeof(HAX_TUNNEL_INFO), &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SETUP_TUNNEL, info); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_vcpu_setMSRs(HAX_MSR_DATA *inbuf, HAX_MSR_DATA *outbuf){ - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SET_MSRS, - inbuf, sizeof(HAX_MSR_DATA), - outbuf, sizeof(HAX_MSR_DATA), &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SET_MSRS, inbuf); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_vcpu_getMSRs(HAX_MSR_DATA *outbuf){ - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_GET_MSRS, - NULL, 0, - outbuf, sizeof(HAX_MSR_DATA), &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_GET_MSRS, outbuf); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_vcpu_setFPU(HAX_FX_LAYOUT *inbuf){ - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SET_FPU, - inbuf, sizeof(HAX_FX_LAYOUT), - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SET_FPU, inbuf); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_vcpu_getFPU(HAX_FX_LAYOUT *outbuf){ - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_GET_FPU, - NULL, 0, - outbuf, sizeof(HAX_FX_LAYOUT), &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_GET_FPU, outbuf); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_vcpu_setREGs(HAX_VCPU_STATE *inbuf){ - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_SET_REGS, - inbuf, sizeof(HAX_VCPU_STATE), - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_SET_REGS, inbuf); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_vcpu_getREGs(HAX_VCPU_STATE *outbuf){ - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_GET_REGS, - NULL, 0, - outbuf, sizeof(HAX_VCPU_STATE), &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_GET_REGS, outbuf); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_vcpu_interrupt(UINT32 vector){ - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_INTERRUPT, - &vector, sizeof(UINT32), - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_INTERRUPT, &vector); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_vcpu_kickoff(){ - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_KICKOFF, - NULL, 0, - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { - return FAILURE; - } -#endif - - return SUCCESS; -} -UINT8 i386haxfunc_vcpu_debug(HAX_DEBUG *inbuf){ - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - -#if defined(_WINDOWS) - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_IOCTL_VCPU_DEBUG, - inbuf, sizeof(HAX_DEBUG), - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { -#else - ret = ioctl(np2hax.hVCPUDevice, HAX_IOCTL_VCPU_DEBUG, inbuf); - if (ret == -1) { -#endif - return FAILURE; - } - - return SUCCESS; -} -UINT8 i386haxfunc_vcpu_setCPUID(HAX_CPUID *inbuf){ - int ret = 0; - DWORD dwSize; - - if(!np2hax.hVCPUDevice){ - return FAILURE; - } - - ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SET_CPUID, - inbuf, sizeof(HAX_CPUID) - sizeof(HAX_CPUID_ENTRY) * (HAX_MAX_CPUID_ENTRIES - inbuf->total), - NULL, 0, &dwSize, - (LPOVERLAPPED)NULL); - if (!ret) { - return FAILURE; - } - - return SUCCESS; -} -#endif +/* + * Copyright (c) 2019 SimK + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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. + */ + +#include +#include "haxfunc.h" +#include "haxcore.h" + +#if defined(SUPPORT_IA32_HAXM) + +// HAXM IOCTL +UINT8 i386haxfunc_getversion(HAX_MODULE_VERSION *version) { + + int ret = 0; + DWORD dwSize; + + if(!np2hax.hDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hDevice, HAX_IOCTL_VERSION, + NULL, 0, + version, sizeof(HAX_MODULE_VERSION), &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hDevice, HAX_IOCTL_VERSION, version); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_getcapability(HAX_CAPINFO *cap) { + int ret = 0; + DWORD dwSize; + + if(!np2hax.hDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hDevice, HAX_IOCTL_CAPABILITY, + NULL, 0, + cap, sizeof(HAX_CAPINFO), &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hDevice, HAX_IOCTL_CAPABILITY, cap); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_setmemlimit(HAX_SET_MEMLIMIT *memlimit) { + int ret = 0; + DWORD dwSize; + + if(!np2hax.hDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hDevice, HAX_IOCTL_SET_MEMLIMIT, + memlimit, sizeof(HAX_SET_MEMLIMIT), + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hDevice, HAX_IOCTL_SET_MEMLIMIT, memlimit); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_createVM(UINT32 *vm_id) { + int ret = 0; + DWORD dwSize; + + if(!np2hax.hDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hDevice, HAX_IOCTL_CREATE_VM, + NULL, 0, + vm_id, sizeof(UINT32), &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hDevice, HAX_IOCTL_CREATE_VM, vm_id); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} + +// HAXM VM IOCTL +UINT8 i386haxfunc_notifyQEMUversion(HAX_QEMU_VERSION *hax_qemu_ver) { + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVMDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVMDevice, HAX_VM_IOCTL_NOTIFY_QEMU_VERSION, + hax_qemu_ver, sizeof(HAX_QEMU_VERSION), + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVMDevice, HAX_VM_IOCTL_NOTIFY_QEMU_VERSION, hax_qemu_ver); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} + +UINT8 i386haxfunc_VCPUcreate(UINT32 vcpu_id) { + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVMDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVMDevice, HAX_VM_IOCTL_VCPU_CREATE, + &vcpu_id, sizeof(UINT32), + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVMDevice, HAX_VM_IOCTL_VCPU_CREATE, &vcpu_id); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} + +UINT8 i386haxfunc_allocRAM(HAX_ALLOC_RAM_INFO *allocraminfo) { + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVMDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVMDevice, HAX_VM_IOCTL_ALLOC_RAM, + allocraminfo, sizeof(HAX_ALLOC_RAM_INFO), + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVMDevice, HAX_VM_IOCTL_ALLOC_RAM, allocraminfo); + if (ret == -1) { +#endif +#if defined(_WINDOWS) + ret = GetLastError(); +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_addRAMblock(HAX_RAMBLOCK_INFO *ramblkinfo) { + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVMDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVMDevice, HAX_VM_IOCTL_ADD_RAMBLOCK, + ramblkinfo, sizeof(HAX_RAMBLOCK_INFO), + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVMDevice, HAX_VM_IOCTL_ADD_RAMBLOCK, ramblkinfo); + if (ret == -1) { +#endif +#if defined(_WINDOWS) + ret = GetLastError(); +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_setRAM(HAX_SET_RAM_INFO *setraminfo) { + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVMDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVMDevice, HAX_VM_IOCTL_SET_RAM, + setraminfo, sizeof(HAX_SET_RAM_INFO), + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVMDevice, HAX_VM_IOCTL_SET_RAM, setraminfo); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} + +// HAXM VCPU IOCTL +UINT8 i386haxfunc_vcpu_run(){ + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_RUN, + NULL, 0, + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_RUN, NULL); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_vcpu_setup_tunnel(HAX_TUNNEL_INFO *info){ + int ret = 0; + DWORD dwSize; + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SETUP_TUNNEL, + NULL, 0, + info, sizeof(HAX_TUNNEL_INFO), &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SETUP_TUNNEL, info); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_vcpu_setMSRs(HAX_MSR_DATA *inbuf, HAX_MSR_DATA *outbuf){ + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SET_MSRS, + inbuf, sizeof(HAX_MSR_DATA), + outbuf, sizeof(HAX_MSR_DATA), &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SET_MSRS, inbuf); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_vcpu_getMSRs(HAX_MSR_DATA *outbuf){ + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_GET_MSRS, + NULL, 0, + outbuf, sizeof(HAX_MSR_DATA), &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_GET_MSRS, outbuf); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_vcpu_setFPU(HAX_FX_LAYOUT *inbuf){ + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SET_FPU, + inbuf, sizeof(HAX_FX_LAYOUT), + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SET_FPU, inbuf); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_vcpu_getFPU(HAX_FX_LAYOUT *outbuf){ + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_GET_FPU, + NULL, 0, + outbuf, sizeof(HAX_FX_LAYOUT), &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_GET_FPU, outbuf); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_vcpu_setREGs(HAX_VCPU_STATE *inbuf){ + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_SET_REGS, + inbuf, sizeof(HAX_VCPU_STATE), + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_SET_REGS, inbuf); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_vcpu_getREGs(HAX_VCPU_STATE *outbuf){ + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_GET_REGS, + NULL, 0, + outbuf, sizeof(HAX_VCPU_STATE), &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_GET_REGS, outbuf); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_vcpu_interrupt(UINT32 vector){ + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_INTERRUPT, + &vector, sizeof(UINT32), + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_INTERRUPT, &vector); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_vcpu_kickoff(){ + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_KICKOFF, + NULL, 0, + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { + return FAILURE; + } +#endif + + return SUCCESS; +} +UINT8 i386haxfunc_vcpu_debug(HAX_DEBUG *inbuf){ + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + +#if defined(_WINDOWS) + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_IOCTL_VCPU_DEBUG, + inbuf, sizeof(HAX_DEBUG), + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { +#else + ret = ioctl(np2hax.hVCPUDevice, HAX_IOCTL_VCPU_DEBUG, inbuf); + if (ret == -1) { +#endif + return FAILURE; + } + + return SUCCESS; +} +UINT8 i386haxfunc_vcpu_setCPUID(HAX_CPUID *inbuf){ + int ret = 0; + DWORD dwSize; + + if(!np2hax.hVCPUDevice){ + return FAILURE; + } + + ret = DeviceIoControl(np2hax.hVCPUDevice, HAX_VCPU_IOCTL_SET_CPUID, + inbuf, sizeof(HAX_CPUID) - sizeof(HAX_CPUID_ENTRY) * (HAX_MAX_CPUID_ENTRIES - inbuf->total), + NULL, 0, &dwSize, + (LPOVERLAPPED)NULL); + if (!ret) { + return FAILURE; + } + + return SUCCESS; +} +#endif diff --git a/i386hax/haxfunc.h b/i386hax/haxfunc.h index 06e63a7f..5601c93c 100644 --- a/i386hax/haxfunc.h +++ b/i386hax/haxfunc.h @@ -1,529 +1,529 @@ - -#ifndef NP2_I386HAX_HAXFUNC_H__ -#define NP2_I386HAX_HAXFUNC_H__ - -#if defined(SUPPORT_IA32_HAXM) - -#if !defined(_WINDOWS) -#include -#endif - -#define HAX_DEVICE_TYPE 0x4000 - -#if defined(_WINDOWS) -#define HAX_IOCTL_VERSION CTL_CODE(HAX_DEVICE_TYPE, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_IOCTL_CAPABILITY CTL_CODE(HAX_DEVICE_TYPE, 0x910, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_IOCTL_SET_MEMLIMIT CTL_CODE(HAX_DEVICE_TYPE, 0x911, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_IOCTL_CREATE_VM CTL_CODE(HAX_DEVICE_TYPE, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define HAX_VM_IOCTL_VCPU_CREATE CTL_CODE(HAX_DEVICE_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_ALLOC_RAM CTL_CODE(HAX_DEVICE_TYPE, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_SET_RAM CTL_CODE(HAX_DEVICE_TYPE, 0x904, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_VCPU_DESTROY CTL_CODE(HAX_DEVICE_TYPE, 0x905, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_ADD_RAMBLOCK CTL_CODE(HAX_DEVICE_TYPE, 0x913, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_SET_RAM2 CTL_CODE(HAX_DEVICE_TYPE, 0x914, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VM_IOCTL_PROTECT_RAM CTL_CODE(HAX_DEVICE_TYPE, 0x915, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define HAX_VCPU_IOCTL_RUN CTL_CODE(HAX_DEVICE_TYPE, 0x906, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_IOCTL_SET_MSRS CTL_CODE(HAX_DEVICE_TYPE, 0x907, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_IOCTL_GET_MSRS CTL_CODE(HAX_DEVICE_TYPE, 0x908, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define HAX_VCPU_IOCTL_SET_FPU CTL_CODE(HAX_DEVICE_TYPE, 0x909, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_IOCTL_GET_FPU CTL_CODE(HAX_DEVICE_TYPE, 0x90a, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define HAX_VCPU_IOCTL_SETUP_TUNNEL CTL_CODE(HAX_DEVICE_TYPE, 0x90b, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_IOCTL_INTERRUPT CTL_CODE(HAX_DEVICE_TYPE, 0x90c, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_SET_REGS CTL_CODE(HAX_DEVICE_TYPE, 0x90d, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_GET_REGS CTL_CODE(HAX_DEVICE_TYPE, 0x90e, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define HAX_VCPU_IOCTL_KICKOFF CTL_CODE(HAX_DEVICE_TYPE, 0x90f, METHOD_BUFFERED, FILE_ANY_ACCESS) - -/* API version 2.0 */ -#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION \ - CTL_CODE(HAX_DEVICE_TYPE, 0x910, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define HAX_IOCTL_VCPU_DEBUG \ - CTL_CODE(HAX_DEVICE_TYPE, 0x916, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define HAX_VCPU_IOCTL_SET_CPUID \ - CTL_CODE(HAX_DEVICE_TYPE, 0x917, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#else -/* The mac specific interface to qemu because of mac's - * special handling like hax tunnel allocation etc */ -/* HAX model level ioctl */ -#define HAX_IOCTL_VERSION _IOWR(0, 0x20, struct hax_module_version) -#define HAX_IOCTL_CREATE_VM _IOWR(0, 0x21, uint32_t) -#define HAX_IOCTL_DESTROY_VM _IOW(0, 0x22, uint32_t) -#define HAX_IOCTL_CAPABILITY _IOR(0, 0x23, struct hax_capabilityinfo) -#define HAX_IOCTL_SET_MEMLIMIT _IOWR(0, 0x24, struct hax_set_memlimit) - -// Only for backward compatibility with old Qemu. -#define HAX_VM_IOCTL_VCPU_CREATE_ORIG _IOR(0, 0x80, int) - -#define HAX_VM_IOCTL_VCPU_CREATE _IOWR(0, 0x80, uint32_t) -#define HAX_VM_IOCTL_ALLOC_RAM _IOWR(0, 0x81, struct hax_alloc_ram_info) -#define HAX_VM_IOCTL_SET_RAM _IOWR(0, 0x82, struct hax_set_ram_info) -#define HAX_VM_IOCTL_VCPU_DESTROY _IOR(0, 0x83, uint32_t) -#define HAX_VM_IOCTL_ADD_RAMBLOCK _IOW(0, 0x85, struct hax_ramblock_info) -#define HAX_VM_IOCTL_SET_RAM2 _IOWR(0, 0x86, struct hax_set_ram_info2) -#define HAX_VM_IOCTL_PROTECT_RAM _IOWR(0, 0x87, struct hax_protect_ram_info) - -#define HAX_VCPU_IOCTL_RUN _IO(0, 0xc0) -#define HAX_VCPU_IOCTL_SET_MSRS _IOWR(0, 0xc1, struct hax_msr_data) -#define HAX_VCPU_IOCTL_GET_MSRS _IOWR(0, 0xc2, struct hax_msr_data) - -#define HAX_VCPU_IOCTL_SET_FPU _IOW(0, 0xc3, struct fx_layout) -#define HAX_VCPU_IOCTL_GET_FPU _IOR(0, 0xc4, struct fx_layout) - -#define HAX_VCPU_IOCTL_SETUP_TUNNEL _IOWR(0, 0xc5, struct hax_tunnel_info) -#define HAX_VCPU_IOCTL_INTERRUPT _IOWR(0, 0xc6, uint32_t) -#define HAX_VCPU_SET_REGS _IOWR(0, 0xc7, struct vcpu_state_t) -#define HAX_VCPU_GET_REGS _IOWR(0, 0xc8, struct vcpu_state_t) - -/* API 2.0 */ -#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION _IOW(0, 0x84, struct hax_qemu_version) - -#define HAX_IOCTL_VCPU_DEBUG _IOW(0, 0xc9, struct hax_debug_t) - -#define HAX_KERNEL64_CS 0x80 -#define HAX_KERNEL32_CS 0x08 - -#define is_compatible() 0 -#endif - -// hax_capabilityinfo wstatus用 -#define HAX_CAP_STATUS_WORKING (1 << 0) -#define HAX_CAP_MEMQUOTA (1 << 1) -#define HAX_CAP_WORKSTATUS_MASK 0x01 - -// hax_capabilityinfo winfo用(HAXM使用不可な場合) -#define HAX_CAP_FAILREASON_VT (1 << 0) -#define HAX_CAP_FAILREASON_NX (1 << 1) - -// hax_capabilityinfo winfo用(HAXM使用可能な場合) -#define HAX_CAP_EPT (1 << 0) -#define HAX_CAP_FASTMMIO (1 << 1) -#define HAX_CAP_UG (1 << 2) -#define HAX_CAP_64BIT_RAMBLOCK (1 << 3) -#define HAX_CAP_64BIT_SETRAM (1 << 4) -#define HAX_CAP_TUNNEL_PAGE (1 << 5) -#define HAX_CAP_DEBUG (1 << 7) - -#define HAX_MAX_VCPUS 16 - -#define HAX_RAM_INFO_ROM 0x01 -#define HAX_RAM_INFO_INVALID 0x80 - -#ifdef __cplusplus -extern "C" { -#endif - -#pragma pack(1) -typedef struct hax_module_version { - UINT32 compat_version; // 互換性のあるバージョン? - UINT32 current_version; // 現在のバージョン? -} HAX_MODULE_VERSION; - -typedef struct hax_capabilityinfo { - UINT16 wstatus; // 使用可否のフラグなど - UINT16 winfo; // wstatusで使用可の場合:HAXMで使用できる機能のフラグ、使用不可の場合:使用不可の理由フラグ - UINT32 win_refcount; // 謎 - UINT64 mem_quota; // 仮想マシン(VM)で使用可能なメモリの上限? -} HAX_CAPINFO; - -typedef struct hax_set_memlimit { - UINT8 enable_memlimit; // メモリ制限有効? - UINT8 pad[7]; // 無視 - UINT64 memory_limit; // メモリ制限サイズ? -} HAX_SET_MEMLIMIT; - -typedef struct hax_alloc_ram_info { - UINT32 size; // 登録するメモリのサイズ - UINT32 pad; // 無視 - UINT64 va; // 登録したいホストのメモリアドレス。4KB境界でないと駄目。vaはVirtual Addressの略? -} HAX_ALLOC_RAM_INFO; - -typedef struct hax_ramblock_info { - UINT64 start_va; // 登録したいホストのメモリアドレス。4KB境界でないと駄目。vaはVirtual Addressの略? - UINT64 size; // 登録するメモリのサイズ - UINT32 reserved; // 無視 -} HAX_RAMBLOCK_INFO; - -typedef struct hax_set_ram_info { - UINT64 pa_start; // 割当先のゲスト物理アドレス(Guest Physical Address; GPA)。既に登録されている場合は上書き。4KB境界でないと駄目 - UINT32 size; // 割当するサイズ - UINT8 flags; // 0:通常のRAM、HAX_RAM_INFO_ROM:ROM領域、HAX_RAM_INFO_INVALID:割り当て解除(vaは0にする) - UINT8 pad[3]; // 無視 - UINT64 va; // 割当したいホストのメモリアドレス(Host Virtual Address; HVA)。先にi386haxfunc_allocRAMで登録しておかないと駄目。4KB境界でないと駄目 -} HAX_SET_RAM_INFO; - -typedef struct hax_tunnel_info { - UINT64 va; // struct hax_tunnelのアドレス(キャストして使う) - UINT64 io_va; // データやりとり用。exit_statusによって内容が変わる - UINT16 size; // struct hax_tunnelのサイズ - UINT16 pad[3]; // 無視 -} HAX_TUNNEL_INFO; - -typedef struct hax_qemu_version { - UINT32 cur_version; // 実行中のQEMUバージョン? - UINT32 least_version; // 最低限必要なQEMU APIバージョン? -} HAX_QEMU_VERSION; - -#define HAX_IO_OUT 0 -#define HAX_IO_IN 1 - -// VM実行中断の原因 -enum exit_status { - HAX_EXIT_IO = 1, // I/Oポートアクセス - HAX_EXIT_MMIO, // メモリマップドIOアクセス(最近はFAST_MMIOが使われている。廃止?) - HAX_EXIT_REALMODE, // リアルモードの場合 - HAX_EXIT_INTERRUPT, // 割り込み発生? - HAX_EXIT_UNKNOWN, // 原因不明 - HAX_EXIT_HLT, // HLT命令が実行された - HAX_EXIT_STATECHANGE, // シャットダウンやCPUパニックなどでリセット以外の選択肢が無いとき - HAX_EXIT_PAUSED, // 一時停止? - HAX_EXIT_FAST_MMIO, // メモリマップドIOアクセス(HAX_EXIT_MMIOを高速にしたものらしい)tunnelのio_vaはhax_fastmmio構造体のアドレス - HAX_EXIT_PAGEFAULT, // ページフォールト発生? - HAX_EXIT_DEBUG // デバッグ -}; -enum run_flag { - HAX_EXIT = 0, - HAX_RESUME = 1 -}; - -typedef struct hax_tunnel { - UINT32 _exit_reason; // ??? - UINT32 pad0; // 無視 - UINT32 _exit_status; // HAX_EXIT_なんたら - UINT32 user_event_pending; // ??? - int ready_for_interrupt_injection; // i386haxfunc_vcpu_interruptで割り込みを受け入れる準備が出来た - int request_interrupt_window; // 割り込みしたいので準備して下さいフラグ(必要なときに自分で1に設定する) - - union { - struct { - // tunnel.io_vaはポートへの出力データ、あるいはポートからの入力データの書き込み先メモリアドレス - UINT8 _direction; // 入力か出力かの判定。HAX_IO_OUTまたはHAX_IO_IN - UINT8 _df; // _countが2以上の場合、メモリを読み取る順番。0はインクリメント、1はデクリメント(I/Oポート番号はそのまま) - UINT16 _size; // ポートアクセス時のサイズ(バイト数) - UINT16 _port; // 出力先ポート - UINT16 _count; // 連続出力するデータ数 - /* Followed owned by HAXM, QEMU should not touch them */ - /* bit 1 is 1 means string io */ - UINT8 _flags; // ??? - UINT8 _pad0; // 無視 - UINT16 _pad1; // 無視 - UINT32 _pad2; // 無視 - UINT64 _vaddr; // ホスト仮想アドレス? - } io; - struct { - UINT64 gla; // ゲストリニアアドレスの略?もう使われていないようなので分からない - } mmio; - struct { - UINT64 gpa; // ゲスト物理アドレス? -#define HAX_PAGEFAULT_ACC_R (1 << 0) -#define HAX_PAGEFAULT_ACC_W (1 << 1) -#define HAX_PAGEFAULT_ACC_X (1 << 2) -#define HAX_PAGEFAULT_PERM_R (1 << 4) -#define HAX_PAGEFAULT_PERM_W (1 << 5) -#define HAX_PAGEFAULT_PERM_X (1 << 6) - UINT32 flags; - UINT32 reserved1; - UINT64 reserved2; - } pagefault; - struct { - UINT64 dummy; - } state; - struct { - UINT64 rip; - UINT64 dr6; - UINT64 dr7; - } debug; - }; - UINT64 apic_base; -} HAX_TUNNEL; -typedef struct hax_fastmmio { - UINT64 gpa; // ゲスト物理アドレス - union { - UINT64 value; // 書き込み時は出力する値、読み取り時は値の格納先変数 - UINT64 gpa2; /* since API v4 */ - }; - UINT8 size; // データバイト数(1, 2, 4 byteのいずれか) - UINT8 direction; // READ=0、WRITE=1、READ&WRITE=2 (I/Oポートの時と何故か逆なので注意。参考: I/OポートではREAD=1, WRITE=0) - UINT16 reg_index; /* obsolete */ - UINT32 pad0; // 無視 - UINT64 _cr0; // CR0レジスタ? - UINT64 _cr2; // CR2レジスタ? - UINT64 _cr3; // CR3レジスタ? - UINT64 _cr4; // CR4レジスタ? -} HAX_FASTMMIO; - - -#define HAX_MAX_MSR_ARRAY 0x20 -typedef struct vmx_msr { - UINT64 entry; - UINT64 value; -} VMX_MSR; -typedef struct hax_msr_data { - UINT16 nr_msr; - UINT16 done; - UINT16 pad[2]; - VMX_MSR entries[HAX_MAX_MSR_ARRAY]; -} HAX_MSR_DATA; -#pragma pack() - -#pragma pack(16) -typedef struct fx_layout { - UINT16 fcw; - UINT16 fsw; - UINT8 ftw; - UINT8 res1; - UINT16 fop; - union { - struct { - UINT32 fip; - UINT16 fcs; - UINT16 res2; - }; - UINT64 fpu_ip; - }; - union { - struct { - UINT32 fdp; - UINT16 fds; - UINT16 res3; - }; - UINT64 fpu_dp; - }; - UINT32 mxcsr; - UINT32 mxcsr_mask; - UINT8 st_mm[8][16]; - UINT8 mmx_1[8][16]; - UINT8 mmx_2[8][16]; - UINT8 pad[96]; -} HAX_FX_LAYOUT; -#pragma pack() - -#pragma pack(1) - -typedef union interruptibility_state_t { - UINT32 raw; - struct { - UINT32 sti_blocking : 1; - UINT32 movss_blocking : 1; - UINT32 smi_blocking : 1; - UINT32 nmi_blocking : 1; - UINT32 reserved : 28; - }; - UINT64 pad; -} INTERRUPTIBILITY_STATE; - -// Segment descriptor -typedef struct segment_desc_t { - UINT16 selector; - UINT16 _dummy; - UINT32 limit; - UINT64 base; - union { - struct { - UINT32 type : 4; - UINT32 desc : 1; - UINT32 dpl : 2; - UINT32 present : 1; - UINT32 : 4; - UINT32 available : 1; - UINT32 long_mode : 1; - UINT32 operand_size : 1; - UINT32 granularity : 1; - UINT32 null : 1; - UINT32 : 15; - }; - UINT32 ar; - }; - UINT32 ipad; -} SEGMENT_DESC; - -// CPUレジスタ -typedef struct vcpu_state_t { - union { - UINT64 _regs[16]; - struct { - union { - struct { - UINT8 _al, - _ah; - }; - UINT16 _ax; - UINT32 _eax; - UINT64 _rax; - }; - union { - struct { - UINT8 _cl, - _ch; - }; - UINT16 _cx; - UINT32 _ecx; - UINT64 _rcx; - }; - union { - struct { - UINT8 _dl, - _dh; - }; - UINT16 _dx; - UINT32 _edx; - UINT64 _rdx; - }; - union { - struct { - UINT8 _bl, - _bh; - }; - UINT16 _bx; - UINT32 _ebx; - UINT64 _rbx; - }; - union { - UINT16 _sp; - UINT32 _esp; - UINT64 _rsp; - }; - union { - UINT16 _bp; - UINT32 _ebp; - UINT64 _rbp; - }; - union { - UINT16 _si; - UINT32 _esi; - UINT64 _rsi; - }; - union { - UINT16 _di; - UINT32 _edi; - UINT64 _rdi; - }; - - UINT64 _r8; - UINT64 _r9; - UINT64 _r10; - UINT64 _r11; - UINT64 _r12; - UINT64 _r13; - UINT64 _r14; - UINT64 _r15; - }; - }; - - union { - UINT32 _eip; - UINT64 _rip; - }; - - union { - UINT32 _eflags; - UINT64 _rflags; - }; - - SEGMENT_DESC _cs; - SEGMENT_DESC _ss; - SEGMENT_DESC _ds; - SEGMENT_DESC _es; - SEGMENT_DESC _fs; - SEGMENT_DESC _gs; - SEGMENT_DESC _ldt; - SEGMENT_DESC _tr; - - SEGMENT_DESC _gdt; - SEGMENT_DESC _idt; - - UINT64 _cr0; - UINT64 _cr2; - UINT64 _cr3; - UINT64 _cr4; - - UINT64 _dr0; - UINT64 _dr1; - UINT64 _dr2; - UINT64 _dr3; - UINT64 _dr6; - UINT64 _dr7; - UINT64 _pde; - - UINT32 _efer; - - UINT32 _sysenter_cs; - UINT64 _sysenter_eip; - UINT64 _sysenter_esp; - - UINT32 _activity_state; - UINT32 pad; - INTERRUPTIBILITY_STATE _interruptibility_state; -} HAX_VCPU_STATE; - -// No access (R/W/X) is allowed -#define HAX_RAM_PERM_NONE 0x0 -// All accesses (R/W/X) are allowed -#define HAX_RAM_PERM_RWX 0x7 -#define HAX_RAM_PERM_MASK 0x7 -typedef struct hax_protect_ram_info { - UINT64 pa_start; - UINT64 size; - UINT32 flags; - UINT32 reserved; -} HAX_PROTECT_RAM_INFO; - -#define HAX_DEBUG_ENABLE (1 << 0) -#define HAX_DEBUG_STEP (1 << 1) -#define HAX_DEBUG_USE_SW_BP (1 << 2) -#define HAX_DEBUG_USE_HW_BP (1 << 3) - -typedef struct hax_debug_t { - UINT32 control; - UINT32 reserved; - UINT64 dr[8]; -} HAX_DEBUG; - -#pragma pack() - -#define HAX_MAX_VCPU 0x10 -#define MAX_VM_ID 0x40 -#define MAX_VCPU_ID 0x40 - -#ifdef __cplusplus -} -#endif - -/*** - HAXM IOCTL用関数群 - ***/ - -// HAXM IOCTL -UINT8 i386haxfunc_getversion(HAX_MODULE_VERSION *version); // HAXMのバージョンを取得する -UINT8 i386haxfunc_getcapability(HAX_CAPINFO *cap); // HAXMで使用可能な機能を取得する -UINT8 i386haxfunc_setmemlimit(HAX_SET_MEMLIMIT *memlimit); // HAXMのメモリ容量制限をセットする(最近の版では意味なし?) -UINT8 i386haxfunc_createVM(UINT32 *vm_id); // HAXMの仮想マシンを作成して仮想マシンIDを返す - -// HAXM VM IOCTL -UINT8 i386haxfunc_notifyQEMUversion(HAX_QEMU_VERSION *hax_qemu_ver); // QEMUバージョンの通知(Fast MMIOの挙動が変わる?通知しなくても問題はなさそう) -UINT8 i386haxfunc_VCPUcreate(UINT32 vcpu_id); // HAXM仮想マシンに指定したIDの仮想CPUを作成する(CPU IDは0~15で指定) -UINT8 i386haxfunc_allocRAM(HAX_ALLOC_RAM_INFO *allocraminfo); // HAXM仮想マシンで使用するホストのメモリ範囲を登録 -UINT8 i386haxfunc_addRAMblock(HAX_RAMBLOCK_INFO *ramblkinfo); // HAXM仮想マシンで使用するホストのメモリ範囲を登録 -UINT8 i386haxfunc_setRAM(HAX_SET_RAM_INFO *setraminfo); // HAXM仮想マシンの物理アドレスにホストのメモリを割り当て(メモリは事前にi386haxfunc_allocRAMで登録が必要)。未割り当てのアドレスはMMIO扱いになる。 - -// HAXM VCPU IOCTL -UINT8 i386haxfunc_vcpu_run(); // 仮想マシン実行開始。I/Oポートアクセス・割り込み発生等で実行継続できなくなったら実行中断する -UINT8 i386haxfunc_vcpu_setup_tunnel(HAX_TUNNEL_INFO *info); // 仮想マシンとデータをやりとりするためのメモリ領域(tunnel)を確保 -UINT8 i386haxfunc_vcpu_setMSRs(HAX_MSR_DATA *inbuf, HAX_MSR_DATA *outbuf); // モデル固有レジスタ(Model Specific Register; MSR)を設定 -UINT8 i386haxfunc_vcpu_getMSRs(HAX_MSR_DATA *outbuf); // モデル固有レジスタを取得 -UINT8 i386haxfunc_vcpu_setFPU(HAX_FX_LAYOUT *inbuf); // FPUレジスタを設定 -UINT8 i386haxfunc_vcpu_getFPU(HAX_FX_LAYOUT *outbuf); // FPUレジスタを取得 -UINT8 i386haxfunc_vcpu_setREGs(HAX_VCPU_STATE *inbuf); // レジスタを設定 -UINT8 i386haxfunc_vcpu_getREGs(HAX_VCPU_STATE *outbuf); // レジスタを取得 -UINT8 i386haxfunc_vcpu_interrupt(UINT32 vector); // 指定したベクタの割り込みを発生させる -UINT8 i386haxfunc_vcpu_kickoff(); // 謎 -UINT8 i386haxfunc_vcpu_debug(HAX_DEBUG *inbuf); // デバッグの有効/無効やデバッグ方法を設定する - -#endif - -#endif /* !NP2_I386HAX_HAXFUNC_H__ */ + +#ifndef NP2_I386HAX_HAXFUNC_H__ +#define NP2_I386HAX_HAXFUNC_H__ + +#if defined(SUPPORT_IA32_HAXM) + +#if !defined(_WINDOWS) +#include +#endif + +#define HAX_DEVICE_TYPE 0x4000 + +#if defined(_WINDOWS) +#define HAX_IOCTL_VERSION CTL_CODE(HAX_DEVICE_TYPE, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_IOCTL_CAPABILITY CTL_CODE(HAX_DEVICE_TYPE, 0x910, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_IOCTL_SET_MEMLIMIT CTL_CODE(HAX_DEVICE_TYPE, 0x911, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_IOCTL_CREATE_VM CTL_CODE(HAX_DEVICE_TYPE, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define HAX_VM_IOCTL_VCPU_CREATE CTL_CODE(HAX_DEVICE_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VM_IOCTL_ALLOC_RAM CTL_CODE(HAX_DEVICE_TYPE, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VM_IOCTL_SET_RAM CTL_CODE(HAX_DEVICE_TYPE, 0x904, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VM_IOCTL_VCPU_DESTROY CTL_CODE(HAX_DEVICE_TYPE, 0x905, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VM_IOCTL_ADD_RAMBLOCK CTL_CODE(HAX_DEVICE_TYPE, 0x913, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VM_IOCTL_SET_RAM2 CTL_CODE(HAX_DEVICE_TYPE, 0x914, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VM_IOCTL_PROTECT_RAM CTL_CODE(HAX_DEVICE_TYPE, 0x915, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define HAX_VCPU_IOCTL_RUN CTL_CODE(HAX_DEVICE_TYPE, 0x906, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VCPU_IOCTL_SET_MSRS CTL_CODE(HAX_DEVICE_TYPE, 0x907, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VCPU_IOCTL_GET_MSRS CTL_CODE(HAX_DEVICE_TYPE, 0x908, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define HAX_VCPU_IOCTL_SET_FPU CTL_CODE(HAX_DEVICE_TYPE, 0x909, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VCPU_IOCTL_GET_FPU CTL_CODE(HAX_DEVICE_TYPE, 0x90a, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define HAX_VCPU_IOCTL_SETUP_TUNNEL CTL_CODE(HAX_DEVICE_TYPE, 0x90b, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VCPU_IOCTL_INTERRUPT CTL_CODE(HAX_DEVICE_TYPE, 0x90c, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VCPU_SET_REGS CTL_CODE(HAX_DEVICE_TYPE, 0x90d, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VCPU_GET_REGS CTL_CODE(HAX_DEVICE_TYPE, 0x90e, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define HAX_VCPU_IOCTL_KICKOFF CTL_CODE(HAX_DEVICE_TYPE, 0x90f, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/* API version 2.0 */ +#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION \ + CTL_CODE(HAX_DEVICE_TYPE, 0x910, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define HAX_IOCTL_VCPU_DEBUG \ + CTL_CODE(HAX_DEVICE_TYPE, 0x916, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define HAX_VCPU_IOCTL_SET_CPUID \ + CTL_CODE(HAX_DEVICE_TYPE, 0x917, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#else +/* The mac specific interface to qemu because of mac's + * special handling like hax tunnel allocation etc */ +/* HAX model level ioctl */ +#define HAX_IOCTL_VERSION _IOWR(0, 0x20, struct hax_module_version) +#define HAX_IOCTL_CREATE_VM _IOWR(0, 0x21, uint32_t) +#define HAX_IOCTL_DESTROY_VM _IOW(0, 0x22, uint32_t) +#define HAX_IOCTL_CAPABILITY _IOR(0, 0x23, struct hax_capabilityinfo) +#define HAX_IOCTL_SET_MEMLIMIT _IOWR(0, 0x24, struct hax_set_memlimit) + +// Only for backward compatibility with old Qemu. +#define HAX_VM_IOCTL_VCPU_CREATE_ORIG _IOR(0, 0x80, int) + +#define HAX_VM_IOCTL_VCPU_CREATE _IOWR(0, 0x80, uint32_t) +#define HAX_VM_IOCTL_ALLOC_RAM _IOWR(0, 0x81, struct hax_alloc_ram_info) +#define HAX_VM_IOCTL_SET_RAM _IOWR(0, 0x82, struct hax_set_ram_info) +#define HAX_VM_IOCTL_VCPU_DESTROY _IOR(0, 0x83, uint32_t) +#define HAX_VM_IOCTL_ADD_RAMBLOCK _IOW(0, 0x85, struct hax_ramblock_info) +#define HAX_VM_IOCTL_SET_RAM2 _IOWR(0, 0x86, struct hax_set_ram_info2) +#define HAX_VM_IOCTL_PROTECT_RAM _IOWR(0, 0x87, struct hax_protect_ram_info) + +#define HAX_VCPU_IOCTL_RUN _IO(0, 0xc0) +#define HAX_VCPU_IOCTL_SET_MSRS _IOWR(0, 0xc1, struct hax_msr_data) +#define HAX_VCPU_IOCTL_GET_MSRS _IOWR(0, 0xc2, struct hax_msr_data) + +#define HAX_VCPU_IOCTL_SET_FPU _IOW(0, 0xc3, struct fx_layout) +#define HAX_VCPU_IOCTL_GET_FPU _IOR(0, 0xc4, struct fx_layout) + +#define HAX_VCPU_IOCTL_SETUP_TUNNEL _IOWR(0, 0xc5, struct hax_tunnel_info) +#define HAX_VCPU_IOCTL_INTERRUPT _IOWR(0, 0xc6, uint32_t) +#define HAX_VCPU_SET_REGS _IOWR(0, 0xc7, struct vcpu_state_t) +#define HAX_VCPU_GET_REGS _IOWR(0, 0xc8, struct vcpu_state_t) + +/* API 2.0 */ +#define HAX_VM_IOCTL_NOTIFY_QEMU_VERSION _IOW(0, 0x84, struct hax_qemu_version) + +#define HAX_IOCTL_VCPU_DEBUG _IOW(0, 0xc9, struct hax_debug_t) + +#define HAX_KERNEL64_CS 0x80 +#define HAX_KERNEL32_CS 0x08 + +#define is_compatible() 0 +#endif + +// hax_capabilityinfo wstatus用 +#define HAX_CAP_STATUS_WORKING (1 << 0) +#define HAX_CAP_MEMQUOTA (1 << 1) +#define HAX_CAP_WORKSTATUS_MASK 0x01 + +// hax_capabilityinfo winfo用(HAXM使用不可な場合) +#define HAX_CAP_FAILREASON_VT (1 << 0) +#define HAX_CAP_FAILREASON_NX (1 << 1) + +// hax_capabilityinfo winfo用(HAXM使用可能な場合) +#define HAX_CAP_EPT (1 << 0) +#define HAX_CAP_FASTMMIO (1 << 1) +#define HAX_CAP_UG (1 << 2) +#define HAX_CAP_64BIT_RAMBLOCK (1 << 3) +#define HAX_CAP_64BIT_SETRAM (1 << 4) +#define HAX_CAP_TUNNEL_PAGE (1 << 5) +#define HAX_CAP_DEBUG (1 << 7) + +#define HAX_MAX_VCPUS 16 + +#define HAX_RAM_INFO_ROM 0x01 +#define HAX_RAM_INFO_INVALID 0x80 + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack(1) +typedef struct hax_module_version { + UINT32 compat_version; // 互換性のあるバージョン? + UINT32 current_version; // 現在のバージョン? +} HAX_MODULE_VERSION; + +typedef struct hax_capabilityinfo { + UINT16 wstatus; // 使用可否のフラグなど + UINT16 winfo; // wstatusで使用可の場合:HAXMで使用できる機能のフラグ、使用不可の場合:使用不可の理由フラグ + UINT32 win_refcount; // 謎 + UINT64 mem_quota; // 仮想マシン(VM)で使用可能なメモリの上限? +} HAX_CAPINFO; + +typedef struct hax_set_memlimit { + UINT8 enable_memlimit; // メモリ制限有効? + UINT8 pad[7]; // 無視 + UINT64 memory_limit; // メモリ制限サイズ? +} HAX_SET_MEMLIMIT; + +typedef struct hax_alloc_ram_info { + UINT32 size; // 登録するメモリのサイズ + UINT32 pad; // 無視 + UINT64 va; // 登録したいホストのメモリアドレス。4KB境界でないと駄目。vaはVirtual Addressの略? +} HAX_ALLOC_RAM_INFO; + +typedef struct hax_ramblock_info { + UINT64 start_va; // 登録したいホストのメモリアドレス。4KB境界でないと駄目。vaはVirtual Addressの略? + UINT64 size; // 登録するメモリのサイズ + UINT32 reserved; // 無視 +} HAX_RAMBLOCK_INFO; + +typedef struct hax_set_ram_info { + UINT64 pa_start; // 割当先のゲスト物理アドレス(Guest Physical Address; GPA)。既に登録されている場合は上書き。4KB境界でないと駄目 + UINT32 size; // 割当するサイズ + UINT8 flags; // 0:通常のRAM、HAX_RAM_INFO_ROM:ROM領域、HAX_RAM_INFO_INVALID:割り当て解除(vaは0にする) + UINT8 pad[3]; // 無視 + UINT64 va; // 割当したいホストのメモリアドレス(Host Virtual Address; HVA)。先にi386haxfunc_allocRAMで登録しておかないと駄目。4KB境界でないと駄目 +} HAX_SET_RAM_INFO; + +typedef struct hax_tunnel_info { + UINT64 va; // struct hax_tunnelのアドレス(キャストして使う) + UINT64 io_va; // データやりとり用。exit_statusによって内容が変わる + UINT16 size; // struct hax_tunnelのサイズ + UINT16 pad[3]; // 無視 +} HAX_TUNNEL_INFO; + +typedef struct hax_qemu_version { + UINT32 cur_version; // 実行中のQEMUバージョン? + UINT32 least_version; // 最低限必要なQEMU APIバージョン? +} HAX_QEMU_VERSION; + +#define HAX_IO_OUT 0 +#define HAX_IO_IN 1 + +// VM実行中断の原因 +enum exit_status { + HAX_EXIT_IO = 1, // I/Oポートアクセス + HAX_EXIT_MMIO, // メモリマップドIOアクセス(最近はFAST_MMIOが使われている。廃止?) + HAX_EXIT_REALMODE, // リアルモードの場合 + HAX_EXIT_INTERRUPT, // 割り込み発生? + HAX_EXIT_UNKNOWN, // 原因不明 + HAX_EXIT_HLT, // HLT命令が実行された + HAX_EXIT_STATECHANGE, // シャットダウンやCPUパニックなどでリセット以外の選択肢が無いとき + HAX_EXIT_PAUSED, // 一時停止? + HAX_EXIT_FAST_MMIO, // メモリマップドIOアクセス(HAX_EXIT_MMIOを高速にしたものらしい)tunnelのio_vaはhax_fastmmio構造体のアドレス + HAX_EXIT_PAGEFAULT, // ページフォールト発生? + HAX_EXIT_DEBUG // デバッグ +}; +enum run_flag { + HAX_EXIT = 0, + HAX_RESUME = 1 +}; + +typedef struct hax_tunnel { + UINT32 _exit_reason; // ??? + UINT32 pad0; // 無視 + UINT32 _exit_status; // HAX_EXIT_なんたら + UINT32 user_event_pending; // ??? + int ready_for_interrupt_injection; // i386haxfunc_vcpu_interruptで割り込みを受け入れる準備が出来た + int request_interrupt_window; // 割り込みしたいので準備して下さいフラグ(必要なときに自分で1に設定する) + + union { + struct { + // tunnel.io_vaはポートへの出力データ、あるいはポートからの入力データの書き込み先メモリアドレス + UINT8 _direction; // 入力か出力かの判定。HAX_IO_OUTまたはHAX_IO_IN + UINT8 _df; // _countが2以上の場合、メモリを読み取る順番。0はインクリメント、1はデクリメント(I/Oポート番号はそのまま) + UINT16 _size; // ポートアクセス時のサイズ(バイト数) + UINT16 _port; // 出力先ポート + UINT16 _count; // 連続出力するデータ数 + /* Followed owned by HAXM, QEMU should not touch them */ + /* bit 1 is 1 means string io */ + UINT8 _flags; // ??? + UINT8 _pad0; // 無視 + UINT16 _pad1; // 無視 + UINT32 _pad2; // 無視 + UINT64 _vaddr; // ホスト仮想アドレス? + } io; + struct { + UINT64 gla; // ゲストリニアアドレスの略?もう使われていないようなので分からない + } mmio; + struct { + UINT64 gpa; // ゲスト物理アドレス? +#define HAX_PAGEFAULT_ACC_R (1 << 0) +#define HAX_PAGEFAULT_ACC_W (1 << 1) +#define HAX_PAGEFAULT_ACC_X (1 << 2) +#define HAX_PAGEFAULT_PERM_R (1 << 4) +#define HAX_PAGEFAULT_PERM_W (1 << 5) +#define HAX_PAGEFAULT_PERM_X (1 << 6) + UINT32 flags; + UINT32 reserved1; + UINT64 reserved2; + } pagefault; + struct { + UINT64 dummy; + } state; + struct { + UINT64 rip; + UINT64 dr6; + UINT64 dr7; + } debug; + }; + UINT64 apic_base; +} HAX_TUNNEL; +typedef struct hax_fastmmio { + UINT64 gpa; // ゲスト物理アドレス + union { + UINT64 value; // 書き込み時は出力する値、読み取り時は値の格納先変数 + UINT64 gpa2; /* since API v4 */ + }; + UINT8 size; // データバイト数(1, 2, 4 byteのいずれか) + UINT8 direction; // READ=0、WRITE=1、READ&WRITE=2 (I/Oポートの時と何故か逆なので注意。参考: I/OポートではREAD=1, WRITE=0) + UINT16 reg_index; /* obsolete */ + UINT32 pad0; // 無視 + UINT64 _cr0; // CR0レジスタ? + UINT64 _cr2; // CR2レジスタ? + UINT64 _cr3; // CR3レジスタ? + UINT64 _cr4; // CR4レジスタ? +} HAX_FASTMMIO; + + +#define HAX_MAX_MSR_ARRAY 0x20 +typedef struct vmx_msr { + UINT64 entry; + UINT64 value; +} VMX_MSR; +typedef struct hax_msr_data { + UINT16 nr_msr; + UINT16 done; + UINT16 pad[2]; + VMX_MSR entries[HAX_MAX_MSR_ARRAY]; +} HAX_MSR_DATA; +#pragma pack() + +#pragma pack(16) +typedef struct fx_layout { + UINT16 fcw; + UINT16 fsw; + UINT8 ftw; + UINT8 res1; + UINT16 fop; + union { + struct { + UINT32 fip; + UINT16 fcs; + UINT16 res2; + }; + UINT64 fpu_ip; + }; + union { + struct { + UINT32 fdp; + UINT16 fds; + UINT16 res3; + }; + UINT64 fpu_dp; + }; + UINT32 mxcsr; + UINT32 mxcsr_mask; + UINT8 st_mm[8][16]; + UINT8 mmx_1[8][16]; + UINT8 mmx_2[8][16]; + UINT8 pad[96]; +} HAX_FX_LAYOUT; +#pragma pack() + +#pragma pack(1) + +typedef union interruptibility_state_t { + UINT32 raw; + struct { + UINT32 sti_blocking : 1; + UINT32 movss_blocking : 1; + UINT32 smi_blocking : 1; + UINT32 nmi_blocking : 1; + UINT32 reserved : 28; + }; + UINT64 pad; +} INTERRUPTIBILITY_STATE; + +// Segment descriptor +typedef struct segment_desc_t { + UINT16 selector; + UINT16 _dummy; + UINT32 limit; + UINT64 base; + union { + struct { + UINT32 type : 4; + UINT32 desc : 1; + UINT32 dpl : 2; + UINT32 present : 1; + UINT32 : 4; + UINT32 available : 1; + UINT32 long_mode : 1; + UINT32 operand_size : 1; + UINT32 granularity : 1; + UINT32 null : 1; + UINT32 : 15; + }; + UINT32 ar; + }; + UINT32 ipad; +} SEGMENT_DESC; + +// CPUレジスタ +typedef struct vcpu_state_t { + union { + UINT64 _regs[16]; + struct { + union { + struct { + UINT8 _al, + _ah; + }; + UINT16 _ax; + UINT32 _eax; + UINT64 _rax; + }; + union { + struct { + UINT8 _cl, + _ch; + }; + UINT16 _cx; + UINT32 _ecx; + UINT64 _rcx; + }; + union { + struct { + UINT8 _dl, + _dh; + }; + UINT16 _dx; + UINT32 _edx; + UINT64 _rdx; + }; + union { + struct { + UINT8 _bl, + _bh; + }; + UINT16 _bx; + UINT32 _ebx; + UINT64 _rbx; + }; + union { + UINT16 _sp; + UINT32 _esp; + UINT64 _rsp; + }; + union { + UINT16 _bp; + UINT32 _ebp; + UINT64 _rbp; + }; + union { + UINT16 _si; + UINT32 _esi; + UINT64 _rsi; + }; + union { + UINT16 _di; + UINT32 _edi; + UINT64 _rdi; + }; + + UINT64 _r8; + UINT64 _r9; + UINT64 _r10; + UINT64 _r11; + UINT64 _r12; + UINT64 _r13; + UINT64 _r14; + UINT64 _r15; + }; + }; + + union { + UINT32 _eip; + UINT64 _rip; + }; + + union { + UINT32 _eflags; + UINT64 _rflags; + }; + + SEGMENT_DESC _cs; + SEGMENT_DESC _ss; + SEGMENT_DESC _ds; + SEGMENT_DESC _es; + SEGMENT_DESC _fs; + SEGMENT_DESC _gs; + SEGMENT_DESC _ldt; + SEGMENT_DESC _tr; + + SEGMENT_DESC _gdt; + SEGMENT_DESC _idt; + + UINT64 _cr0; + UINT64 _cr2; + UINT64 _cr3; + UINT64 _cr4; + + UINT64 _dr0; + UINT64 _dr1; + UINT64 _dr2; + UINT64 _dr3; + UINT64 _dr6; + UINT64 _dr7; + UINT64 _pde; + + UINT32 _efer; + + UINT32 _sysenter_cs; + UINT64 _sysenter_eip; + UINT64 _sysenter_esp; + + UINT32 _activity_state; + UINT32 pad; + INTERRUPTIBILITY_STATE _interruptibility_state; +} HAX_VCPU_STATE; + +// No access (R/W/X) is allowed +#define HAX_RAM_PERM_NONE 0x0 +// All accesses (R/W/X) are allowed +#define HAX_RAM_PERM_RWX 0x7 +#define HAX_RAM_PERM_MASK 0x7 +typedef struct hax_protect_ram_info { + UINT64 pa_start; + UINT64 size; + UINT32 flags; + UINT32 reserved; +} HAX_PROTECT_RAM_INFO; + +#define HAX_DEBUG_ENABLE (1 << 0) +#define HAX_DEBUG_STEP (1 << 1) +#define HAX_DEBUG_USE_SW_BP (1 << 2) +#define HAX_DEBUG_USE_HW_BP (1 << 3) + +typedef struct hax_debug_t { + UINT32 control; + UINT32 reserved; + UINT64 dr[8]; +} HAX_DEBUG; + +#pragma pack() + +#define HAX_MAX_VCPU 0x10 +#define MAX_VM_ID 0x40 +#define MAX_VCPU_ID 0x40 + +#ifdef __cplusplus +} +#endif + +/*** + HAXM IOCTL用関数群 + ***/ + +// HAXM IOCTL +UINT8 i386haxfunc_getversion(HAX_MODULE_VERSION *version); // HAXMのバージョンを取得する +UINT8 i386haxfunc_getcapability(HAX_CAPINFO *cap); // HAXMで使用可能な機能を取得する +UINT8 i386haxfunc_setmemlimit(HAX_SET_MEMLIMIT *memlimit); // HAXMのメモリ容量制限をセットする(最近の版では意味なし?) +UINT8 i386haxfunc_createVM(UINT32 *vm_id); // HAXMの仮想マシンを作成して仮想マシンIDを返す + +// HAXM VM IOCTL +UINT8 i386haxfunc_notifyQEMUversion(HAX_QEMU_VERSION *hax_qemu_ver); // QEMUバージョンの通知(Fast MMIOの挙動が変わる?通知しなくても問題はなさそう) +UINT8 i386haxfunc_VCPUcreate(UINT32 vcpu_id); // HAXM仮想マシンに指定したIDの仮想CPUを作成する(CPU IDは0~15で指定) +UINT8 i386haxfunc_allocRAM(HAX_ALLOC_RAM_INFO *allocraminfo); // HAXM仮想マシンで使用するホストのメモリ範囲を登録 +UINT8 i386haxfunc_addRAMblock(HAX_RAMBLOCK_INFO *ramblkinfo); // HAXM仮想マシンで使用するホストのメモリ範囲を登録 +UINT8 i386haxfunc_setRAM(HAX_SET_RAM_INFO *setraminfo); // HAXM仮想マシンの物理アドレスにホストのメモリを割り当て(メモリは事前にi386haxfunc_allocRAMで登録が必要)。未割り当てのアドレスはMMIO扱いになる。 + +// HAXM VCPU IOCTL +UINT8 i386haxfunc_vcpu_run(); // 仮想マシン実行開始。I/Oポートアクセス・割り込み発生等で実行継続できなくなったら実行中断する +UINT8 i386haxfunc_vcpu_setup_tunnel(HAX_TUNNEL_INFO *info); // 仮想マシンとデータをやりとりするためのメモリ領域(tunnel)を確保 +UINT8 i386haxfunc_vcpu_setMSRs(HAX_MSR_DATA *inbuf, HAX_MSR_DATA *outbuf); // モデル固有レジスタ(Model Specific Register; MSR)を設定 +UINT8 i386haxfunc_vcpu_getMSRs(HAX_MSR_DATA *outbuf); // モデル固有レジスタを取得 +UINT8 i386haxfunc_vcpu_setFPU(HAX_FX_LAYOUT *inbuf); // FPUレジスタを設定 +UINT8 i386haxfunc_vcpu_getFPU(HAX_FX_LAYOUT *outbuf); // FPUレジスタを取得 +UINT8 i386haxfunc_vcpu_setREGs(HAX_VCPU_STATE *inbuf); // レジスタを設定 +UINT8 i386haxfunc_vcpu_getREGs(HAX_VCPU_STATE *outbuf); // レジスタを取得 +UINT8 i386haxfunc_vcpu_interrupt(UINT32 vector); // 指定したベクタの割り込みを発生させる +UINT8 i386haxfunc_vcpu_kickoff(); // 謎 +UINT8 i386haxfunc_vcpu_debug(HAX_DEBUG *inbuf); // デバッグの有効/無効やデバッグ方法を設定する + +#endif + +#endif /* !NP2_I386HAX_HAXFUNC_H__ */ diff --git a/io/artic.c b/io/artic.c old mode 100755 new mode 100644 index 978e846d..ca3bc8c9 --- a/io/artic.c +++ b/io/artic.c @@ -1,108 +1,108 @@ -#include -#include -#include -#include - - -void artic_callback(void) { - - SINT32 mul; - SINT32 leng; - - mul = pccore.multiple; - if (pccore.cpumode & CPUMODE_8MHZ) { - mul *= 13; - } - else { - mul *= 16; - } - leng = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - leng *= 2; - leng -= artic.lastclk2; - if (leng > 0) { - leng /= mul; - artic.counter += leng; - artic.lastclk2 += leng * mul; - } -} - -static UINT32 artic_getcnt(void) { - - SINT32 mul; - SINT32 leng; - - mul = pccore.multiple; - if (pccore.cpumode & CPUMODE_8MHZ) { - mul *= 13; - } - else { - mul *= 16; - } - leng = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - leng *= 2; - leng -= artic.lastclk2; - if (leng > 0) { - leng /= mul; - return(artic.counter + leng); - } - return(artic.counter); -} - - -// ---- I/O - -static void IOOUTCALL artic_o5f(UINT port, REG8 dat) { - - (void)port; - (void)dat; - CPU_REMCLOCK -= 20; -} - -static REG8 IOINPCALL artic_i5c(UINT port) { - - (void)port; - return((UINT8)artic_getcnt()); -} - -static REG8 IOINPCALL artic_i5d(UINT port) { - - (void)port; - return((UINT8)(artic_getcnt() >> 8)); -} - -static REG8 IOINPCALL artic_i5f(UINT port) { - - (void)port; - return((UINT8)(artic_getcnt() >> 16)); -} - - -// ---- I/F - -void artic_reset(const NP2CFG *pConfig) { - - ZeroMemory(&artic, sizeof(artic)); - - (void)pConfig; -} - -void artic_bind(void) { - - iocore_attachout(0x005f, artic_o5f); - iocore_attachinp(0x005c, artic_i5c); - iocore_attachinp(0x005d, artic_i5d); - iocore_attachinp(0x005e, artic_i5d); - iocore_attachinp(0x005f, artic_i5f); -} - -REG16 IOINPCALL artic_r16(UINT port) { - - UINT32 cnt; - - cnt = artic_getcnt(); - if (port & 2) { - cnt >>= 8; - } - return((UINT16)cnt); -} - +#include +#include +#include +#include + + +void artic_callback(void) { + + SINT32 mul; + SINT32 leng; + + mul = pccore.multiple; + if (pccore.cpumode & CPUMODE_8MHZ) { + mul *= 13; + } + else { + mul *= 16; + } + leng = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + leng *= 2; + leng -= artic.lastclk2; + if (leng > 0) { + leng /= mul; + artic.counter += leng; + artic.lastclk2 += leng * mul; + } +} + +static UINT32 artic_getcnt(void) { + + SINT32 mul; + SINT32 leng; + + mul = pccore.multiple; + if (pccore.cpumode & CPUMODE_8MHZ) { + mul *= 13; + } + else { + mul *= 16; + } + leng = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + leng *= 2; + leng -= artic.lastclk2; + if (leng > 0) { + leng /= mul; + return(artic.counter + leng); + } + return(artic.counter); +} + + +// ---- I/O + +static void IOOUTCALL artic_o5f(UINT port, REG8 dat) { + + (void)port; + (void)dat; + CPU_REMCLOCK -= 20; +} + +static REG8 IOINPCALL artic_i5c(UINT port) { + + (void)port; + return((UINT8)artic_getcnt()); +} + +static REG8 IOINPCALL artic_i5d(UINT port) { + + (void)port; + return((UINT8)(artic_getcnt() >> 8)); +} + +static REG8 IOINPCALL artic_i5f(UINT port) { + + (void)port; + return((UINT8)(artic_getcnt() >> 16)); +} + + +// ---- I/F + +void artic_reset(const NP2CFG *pConfig) { + + ZeroMemory(&artic, sizeof(artic)); + + (void)pConfig; +} + +void artic_bind(void) { + + iocore_attachout(0x005f, artic_o5f); + iocore_attachinp(0x005c, artic_i5c); + iocore_attachinp(0x005d, artic_i5d); + iocore_attachinp(0x005e, artic_i5d); + iocore_attachinp(0x005f, artic_i5f); +} + +REG16 IOINPCALL artic_r16(UINT port) { + + UINT32 cnt; + + cnt = artic_getcnt(); + if (port & 2) { + cnt >>= 8; + } + return((UINT16)cnt); +} + diff --git a/io/artic.h b/io/artic.h old mode 100755 new mode 100644 index 6143c80c..34613ba8 --- a/io/artic.h +++ b/io/artic.h @@ -1,21 +1,21 @@ - -typedef struct { - SINT32 lastclk2; - SINT32 counter; -} _ARTIC, *ARTIC; - - -#ifdef __cplusplus -extern "C" { -#endif - -void artic_callback(void); - -void artic_reset(const NP2CFG *pConfig); -void artic_bind(void); -REG16 IOINPCALL artic_r16(UINT port); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + SINT32 lastclk2; + SINT32 counter; +} _ARTIC, *ARTIC; + + +#ifdef __cplusplus +extern "C" { +#endif + +void artic_callback(void); + +void artic_reset(const NP2CFG *pConfig); +void artic_bind(void); +REG16 IOINPCALL artic_r16(UINT port); + +#ifdef __cplusplus +} +#endif + diff --git a/io/cgrom.c b/io/cgrom.c old mode 100755 new mode 100644 index f13e2b6b..d65abaa3 --- a/io/cgrom.c +++ b/io/cgrom.c @@ -1,227 +1,227 @@ -#include -#include -#include -#include -#include -#if defined(SUPPORT_TEXTHOOK) -#include -#endif - - -static void cgwindowset(CGROM cr) { - - UINT low; - UINT high; - int code; - - cgwindow.writable &= ~1; - low = 0x7fff0; - if (grcg.chip >= 2) { - if (!(cr->code & 0xff00)) { - high = 0x80000 + (cr->code << 4); - if (!(gdc.mode1 & 8)) { - high += 0x2000; - } - } - else { - code = cr->code & 0x007f; - high = (cr->code & 0x7f7f) << 4; - if ((code >= 0x56) && (code < 0x58)) { - cgwindow.writable |= 1; - high += cr->lr; - } - else if ((code >= 0x09) && (code < 0x0c)) { // ver0.78 - if (cr->lr) { - high = low; - } - } - else if (((code >= 0x0c) && (code < 0x10)) || - ((code >= 0x58) && (code < 0x60))) { - high += cr->lr; - } - else { - low = high; - high += 0x800; - } - } - } - else { - high = low; - } - cgwindow.low = low; - cgwindow.high = high; -} - - -// ---- I/O - -// write charactor code low -static void IOOUTCALL cgrom_oa1(UINT port, REG8 dat) { - - CGROM cr; - -// TRACEOUT(("%.4x:%.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); - hf_codeul |= 0x1; - hf_count = 0; - cr = &cgrom; - cr->code = (dat << 8) | (cr->code & 0xff); -//#if defined(SUPPORT_TEXTHOOK) -// if(np2cfg.usetexthook){ -// UINT16 SJis; -// UINT8 th[3]; -// UINT16 thw[2]; -// thw[1]='¥0'; -// SJis = font_Jis2Sjis(((cr->code + 0x20) << 8) | (cr->code >> 8)); -// if(SJis){ -// th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '¥0'; -// codecnv_sjistoucs2(thw, 1, (const char*)th, 2); -// font_outhooktest((wchar_t*)thw); -// } -// } -//#endif - cgwindowset(cr); - (void)port; -} - -// write charactor code high -static void IOOUTCALL cgrom_oa3(UINT port, REG8 dat) { - - CGROM cr; - -// TRACEOUT(("%.4x:%.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); - hf_codeul |= 0x2; - hf_count = 0; - cr = &cgrom; - cr->code = (cr->code & 0xff00) | dat; -#if defined(SUPPORT_TEXTHOOK) - if(np2cfg.usetexthook){ - UINT16 SJis; - UINT8 th[3]; - UINT16 thw[2]; - thw[1]='¥0'; - SJis = font_Jis2Sjis(((cr->code + 0x20) << 8) | (cr->code >> 8)); - if(SJis){ - th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '¥0'; - codecnv_sjistoucs2(thw, 1, (const char*)th, 2); - font_outhooktest((wchar_t*)thw); - } - } -#endif - cgwindowset(cr); - (void)port; -} - -// write charactor line -static void IOOUTCALL cgrom_oa5(UINT port, REG8 dat) { - - CGROM cr; - - cr = &cgrom; - cr->line = dat & 0x1f; - cr->lr = ((~dat) & 0x20) << 6; -#if defined(SUPPORT_TEXTHOOK) - if(dat == 0 && np2cfg.usetexthook){ - UINT16 SJis; - UINT8 th[3]; - UINT16 thw[2]; - thw[1]='¥0'; - SJis = font_Jis2Sjis(((cr->code + 0x20) << 8) | (cr->code >> 8)); - if(SJis){ - th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '¥0'; - codecnv_sjistoucs2(thw, 1, (const char*)th, 2); - font_outhooktest((wchar_t*)thw); - } - } -#endif - cgwindowset(cr); - (void)port; -} - -// CG write pattern -static void IOOUTCALL cgrom_oa9(UINT port, REG8 dat) { - - CGROM cr; - - cr = &cgrom; - if ((cr->code & 0x007e) == 0x0056) { - fontrom[((cr->code & 0x7f7f) << 4) + - cr->lr + (cr->line & 0x0f)] = (UINT8)dat; - cgwindow.writable |= 0x80; - } - (void)port; -} - -static REG8 IOINPCALL cgrom_ia9(UINT port) { - - CGROM cr; -const UINT8 *ptr; - int type; - - cr = &cgrom; - ptr = fontrom; - type = cr->code & 0x00ff; - if ((type >= 0x09) && (type < 0x0c)) { // ver0.78 - if (!cr->lr) { - if(hf_codeul && hf_count == 0) { - hook_fontrom((cr->code & 0x7f7f) << 4); - hf_codeul = 0; - hf_count++; - } - ptr += (cr->code & 0x7f7f) << 4; - return(ptr[cr->line & 0x0f]); - } - } - else if (cr->code & 0xff00) { - if(hf_codeul && hf_count == 0) { - hook_fontrom((cr->code & 0x7f7f) << 4); - hf_codeul = 0; - hf_count++; - } - ptr += (cr->code & 0x7f7f) << 4; - ptr += cr->lr; - return(ptr[cr->line & 0x0f]); - } - else if (!(cr->line & 0x10)) { // 半角 - if(hf_codeul && hf_count == 0) { - hook_fontrom(0x80000 + (cr->code << 4)); - hf_codeul = 0; - hf_count++; - } - ptr += 0x80000; - ptr += cr->code << 4; - return(ptr[cr->line]); - } - (void)port; - return(0); -} - - -// ---- I/F - -static const IOOUT cgromoa1[8] = { - cgrom_oa1, cgrom_oa3, cgrom_oa5, NULL, - cgrom_oa9, NULL, NULL, NULL}; - -static const IOINP cgromia1[8] = { - NULL, NULL, NULL, NULL, - cgrom_ia9, NULL, NULL, NULL}; - -void cgrom_reset(const NP2CFG *pConfig) { - - CGWINDOW cgw; - - cgw = &cgwindow; - ZeroMemory(cgw, sizeof(cgrom)); - cgw->low = 0x7fff0; - cgw->high = 0x7fff0; - cgw->writable = 0; - - (void)pConfig; -} - -void cgrom_bind(void) { - - iocore_attachsysoutex(0x00a1, 0x0cf1, cgromoa1, 8); - iocore_attachsysinpex(0x00a1, 0x0cf1, cgromia1, 8); -} - +#include +#include +#include +#include +#include +#if defined(SUPPORT_TEXTHOOK) +#include +#endif + + +static void cgwindowset(CGROM cr) { + + UINT low; + UINT high; + int code; + + cgwindow.writable &= ~1; + low = 0x7fff0; + if (grcg.chip >= 2) { + if (!(cr->code & 0xff00)) { + high = 0x80000 + (cr->code << 4); + if (!(gdc.mode1 & 8)) { + high += 0x2000; + } + } + else { + code = cr->code & 0x007f; + high = (cr->code & 0x7f7f) << 4; + if ((code >= 0x56) && (code < 0x58)) { + cgwindow.writable |= 1; + high += cr->lr; + } + else if ((code >= 0x09) && (code < 0x0c)) { // ver0.78 + if (cr->lr) { + high = low; + } + } + else if (((code >= 0x0c) && (code < 0x10)) || + ((code >= 0x58) && (code < 0x60))) { + high += cr->lr; + } + else { + low = high; + high += 0x800; + } + } + } + else { + high = low; + } + cgwindow.low = low; + cgwindow.high = high; +} + + +// ---- I/O + +// write charactor code low +static void IOOUTCALL cgrom_oa1(UINT port, REG8 dat) { + + CGROM cr; + +// TRACEOUT(("%.4x:%.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); + hf_codeul |= 0x1; + hf_count = 0; + cr = &cgrom; + cr->code = (dat << 8) | (cr->code & 0xff); +//#if defined(SUPPORT_TEXTHOOK) +// if(np2cfg.usetexthook){ +// UINT16 SJis; +// UINT8 th[3]; +// UINT16 thw[2]; +// thw[1]='¥0'; +// SJis = font_Jis2Sjis(((cr->code + 0x20) << 8) | (cr->code >> 8)); +// if(SJis){ +// th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '¥0'; +// codecnv_sjistoucs2(thw, 1, (const char*)th, 2); +// font_outhooktest((wchar_t*)thw); +// } +// } +//#endif + cgwindowset(cr); + (void)port; +} + +// write charactor code high +static void IOOUTCALL cgrom_oa3(UINT port, REG8 dat) { + + CGROM cr; + +// TRACEOUT(("%.4x:%.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); + hf_codeul |= 0x2; + hf_count = 0; + cr = &cgrom; + cr->code = (cr->code & 0xff00) | dat; +#if defined(SUPPORT_TEXTHOOK) + if(np2cfg.usetexthook){ + UINT16 SJis; + UINT8 th[3]; + UINT16 thw[2]; + thw[1]='¥0'; + SJis = font_Jis2Sjis(((cr->code + 0x20) << 8) | (cr->code >> 8)); + if(SJis){ + th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '¥0'; + codecnv_sjistoucs2(thw, 1, (const char*)th, 2); + font_outhooktest((wchar_t*)thw); + } + } +#endif + cgwindowset(cr); + (void)port; +} + +// write charactor line +static void IOOUTCALL cgrom_oa5(UINT port, REG8 dat) { + + CGROM cr; + + cr = &cgrom; + cr->line = dat & 0x1f; + cr->lr = ((~dat) & 0x20) << 6; +#if defined(SUPPORT_TEXTHOOK) + if(dat == 0 && np2cfg.usetexthook){ + UINT16 SJis; + UINT8 th[3]; + UINT16 thw[2]; + thw[1]='¥0'; + SJis = font_Jis2Sjis(((cr->code + 0x20) << 8) | (cr->code >> 8)); + if(SJis){ + th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '¥0'; + codecnv_sjistoucs2(thw, 1, (const char*)th, 2); + font_outhooktest((wchar_t*)thw); + } + } +#endif + cgwindowset(cr); + (void)port; +} + +// CG write pattern +static void IOOUTCALL cgrom_oa9(UINT port, REG8 dat) { + + CGROM cr; + + cr = &cgrom; + if ((cr->code & 0x007e) == 0x0056) { + fontrom[((cr->code & 0x7f7f) << 4) + + cr->lr + (cr->line & 0x0f)] = (UINT8)dat; + cgwindow.writable |= 0x80; + } + (void)port; +} + +static REG8 IOINPCALL cgrom_ia9(UINT port) { + + CGROM cr; +const UINT8 *ptr; + int type; + + cr = &cgrom; + ptr = fontrom; + type = cr->code & 0x00ff; + if ((type >= 0x09) && (type < 0x0c)) { // ver0.78 + if (!cr->lr) { + if(hf_codeul && hf_count == 0) { + hook_fontrom((cr->code & 0x7f7f) << 4); + hf_codeul = 0; + hf_count++; + } + ptr += (cr->code & 0x7f7f) << 4; + return(ptr[cr->line & 0x0f]); + } + } + else if (cr->code & 0xff00) { + if(hf_codeul && hf_count == 0) { + hook_fontrom((cr->code & 0x7f7f) << 4); + hf_codeul = 0; + hf_count++; + } + ptr += (cr->code & 0x7f7f) << 4; + ptr += cr->lr; + return(ptr[cr->line & 0x0f]); + } + else if (!(cr->line & 0x10)) { // 半角 + if(hf_codeul && hf_count == 0) { + hook_fontrom(0x80000 + (cr->code << 4)); + hf_codeul = 0; + hf_count++; + } + ptr += 0x80000; + ptr += cr->code << 4; + return(ptr[cr->line]); + } + (void)port; + return(0); +} + + +// ---- I/F + +static const IOOUT cgromoa1[8] = { + cgrom_oa1, cgrom_oa3, cgrom_oa5, NULL, + cgrom_oa9, NULL, NULL, NULL}; + +static const IOINP cgromia1[8] = { + NULL, NULL, NULL, NULL, + cgrom_ia9, NULL, NULL, NULL}; + +void cgrom_reset(const NP2CFG *pConfig) { + + CGWINDOW cgw; + + cgw = &cgwindow; + ZeroMemory(cgw, sizeof(cgrom)); + cgw->low = 0x7fff0; + cgw->high = 0x7fff0; + cgw->writable = 0; + + (void)pConfig; +} + +void cgrom_bind(void) { + + iocore_attachsysoutex(0x00a1, 0x0cf1, cgromoa1, 8); + iocore_attachsysinpex(0x00a1, 0x0cf1, cgromia1, 8); +} + diff --git a/io/cgrom.h b/io/cgrom.h old mode 100755 new mode 100644 index 38f9abd1..300ea37e --- a/io/cgrom.h +++ b/io/cgrom.h @@ -1,25 +1,25 @@ - -typedef struct { - UINT code; - UINT lr; - UINT line; -} _CGROM, *CGROM; - -typedef struct { - UINT32 low; - UINT32 high; - UINT8 writable; -} _CGWINDOW, *CGWINDOW; - - -#ifdef __cplusplus -extern "C" { -#endif - -void cgrom_reset(const NP2CFG *pConfig); -void cgrom_bind(void); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + UINT code; + UINT lr; + UINT line; +} _CGROM, *CGROM; + +typedef struct { + UINT32 low; + UINT32 high; + UINT8 writable; +} _CGWINDOW, *CGWINDOW; + + +#ifdef __cplusplus +extern "C" { +#endif + +void cgrom_reset(const NP2CFG *pConfig); +void cgrom_bind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/cpuio.c b/io/cpuio.c old mode 100755 new mode 100644 index 1963482c..1df70105 --- a/io/cpuio.c +++ b/io/cpuio.c @@ -1,140 +1,140 @@ -#include -#include -#include -#include - -//#ifdef SUPPORT_IDEIO -//#include -//int ide_f0portread = 0; -//#endif - -// ---- I/O - -static void IOOUTCALL cpuio_of0(UINT port, REG8 dat) { - -#if defined(TRACE) - if (CPU_MSW & 1) { - TRACEOUT(("80286 ProtectMode Disable")); - } -#endif - epsonio.cpumode = (CPU_MSW & 1)?'P':'R'; - CPU_A20EN(FALSE); - CPU_RESETREQ = 1; - nevent_forceexit(); - (void)port; - (void)dat; -} - -static void IOINPCALL cpuio_of1(UINT port, REG8 dat) { - -//#ifdef SUPPORT_IDEIO -// ide_f0portread = 1; -//#endif - (void)port; - (void)dat; -} - -static void IOOUTCALL cpuio_of2(UINT port, REG8 dat) { - - CPU_A20EN(TRUE); - (void)port; - (void)dat; -} - -static REG8 IOINPCALL cpuio_if0(UINT port) { - - UINT8 ret; - - if (!(pccore.sound & 0x80)) { - ret = 0x00; - } - else { // for AMD-98 - ret = 0x18; // 0x14? - } -//#ifdef SUPPORT_IDEIO -// ret |= 0x20; -// if(ide_f0portread){ -// if(sxsi_getdevtype(0)!=SXSIDEV_NC){ -// ret &= ~0x20; -// } -// ide_f0portread--; -// }else{ -// if(sxsi_getdevtype(2)!=SXSIDEV_NC){ -// ret &= ~0x20; -// } -// } -//#endif - (void)port; - return(ret); -} - -static REG8 IOINPCALL cpuio_if2(UINT port) { - - REG8 ret; - - ret = 0xff; - ret -= (REG8)((CPU_ADRSMASK >> 20) & 1); - (void)port; - return(ret); -} - - -#if defined(CPUCORE_IA32) -static void IOOUTCALL cpuio_of6(UINT port, REG8 dat) { - - switch(dat) { - case 0x02: - CPU_A20EN(TRUE); - break; - - case 0x03: - CPU_A20EN(FALSE); - break; - } - (void)port; -} - -static REG8 IOINPCALL cpuio_if6(UINT port) { - - REG8 ret; - - ret = 0x00; - if (!(CPU_ADRSMASK & (1 << 20))) { - ret |= 0x01; - } - if (nmiio.enable) { - ret |= 0x02; - } - (void)port; - return(ret); -} -#endif - - -// ---- I/F - -#if !defined(CPUCORE_IA32) -static const IOOUT cpuioof0[8] = { - cpuio_of0, cpuio_of2, NULL, NULL, - NULL, NULL, NULL, NULL}; - -static const IOINP cpuioif0[8] = { - cpuio_if0, cpuio_if2, NULL, NULL, - NULL, NULL, NULL, NULL}; -#else -static const IOOUT cpuioof0[8] = { - cpuio_of0, cpuio_of2, NULL, cpuio_of6, - NULL, NULL, NULL, NULL}; - -static const IOINP cpuioif0[8] = { - cpuio_if0, cpuio_if2, NULL, cpuio_if6, - NULL, NULL, NULL, NULL}; -#endif - -void cpuio_bind(void) { - - iocore_attachsysoutex(0x00f0, 0x0cf1, cpuioof0, 8); - iocore_attachsysinpex(0x00f0, 0x0cf1, cpuioif0, 8); - //iocore_attachout(0x00f1, cpuio_of1); -} - +#include +#include +#include +#include + +//#ifdef SUPPORT_IDEIO +//#include +//int ide_f0portread = 0; +//#endif + +// ---- I/O + +static void IOOUTCALL cpuio_of0(UINT port, REG8 dat) { + +#if defined(TRACE) + if (CPU_MSW & 1) { + TRACEOUT(("80286 ProtectMode Disable")); + } +#endif + epsonio.cpumode = (CPU_MSW & 1)?'P':'R'; + CPU_A20EN(FALSE); + CPU_RESETREQ = 1; + nevent_forceexit(); + (void)port; + (void)dat; +} + +static void IOINPCALL cpuio_of1(UINT port, REG8 dat) { + +//#ifdef SUPPORT_IDEIO +// ide_f0portread = 1; +//#endif + (void)port; + (void)dat; +} + +static void IOOUTCALL cpuio_of2(UINT port, REG8 dat) { + + CPU_A20EN(TRUE); + (void)port; + (void)dat; +} + +static REG8 IOINPCALL cpuio_if0(UINT port) { + + UINT8 ret; + + if (!(pccore.sound & 0x80)) { + ret = 0x00; + } + else { // for AMD-98 + ret = 0x18; // 0x14? + } +//#ifdef SUPPORT_IDEIO +// ret |= 0x20; +// if(ide_f0portread){ +// if(sxsi_getdevtype(0)!=SXSIDEV_NC){ +// ret &= ~0x20; +// } +// ide_f0portread--; +// }else{ +// if(sxsi_getdevtype(2)!=SXSIDEV_NC){ +// ret &= ~0x20; +// } +// } +//#endif + (void)port; + return(ret); +} + +static REG8 IOINPCALL cpuio_if2(UINT port) { + + REG8 ret; + + ret = 0xff; + ret -= (REG8)((CPU_ADRSMASK >> 20) & 1); + (void)port; + return(ret); +} + + +#if defined(CPUCORE_IA32) +static void IOOUTCALL cpuio_of6(UINT port, REG8 dat) { + + switch(dat) { + case 0x02: + CPU_A20EN(TRUE); + break; + + case 0x03: + CPU_A20EN(FALSE); + break; + } + (void)port; +} + +static REG8 IOINPCALL cpuio_if6(UINT port) { + + REG8 ret; + + ret = 0x00; + if (!(CPU_ADRSMASK & (1 << 20))) { + ret |= 0x01; + } + if (nmiio.enable) { + ret |= 0x02; + } + (void)port; + return(ret); +} +#endif + + +// ---- I/F + +#if !defined(CPUCORE_IA32) +static const IOOUT cpuioof0[8] = { + cpuio_of0, cpuio_of2, NULL, NULL, + NULL, NULL, NULL, NULL}; + +static const IOINP cpuioif0[8] = { + cpuio_if0, cpuio_if2, NULL, NULL, + NULL, NULL, NULL, NULL}; +#else +static const IOOUT cpuioof0[8] = { + cpuio_of0, cpuio_of2, NULL, cpuio_of6, + NULL, NULL, NULL, NULL}; + +static const IOINP cpuioif0[8] = { + cpuio_if0, cpuio_if2, NULL, cpuio_if6, + NULL, NULL, NULL, NULL}; +#endif + +void cpuio_bind(void) { + + iocore_attachsysoutex(0x00f0, 0x0cf1, cpuioof0, 8); + iocore_attachsysinpex(0x00f0, 0x0cf1, cpuioif0, 8); + //iocore_attachout(0x00f1, cpuio_of1); +} + diff --git a/io/cpuio.h b/io/cpuio.h old mode 100755 new mode 100644 index f912eb92..ed361357 --- a/io/cpuio.h +++ b/io/cpuio.h @@ -1,11 +1,11 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void cpuio_bind(void); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void cpuio_bind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/crtc.c b/io/crtc.c old mode 100755 new mode 100644 index b18420c1..56b81ce8 --- a/io/crtc.c +++ b/io/crtc.c @@ -1,105 +1,105 @@ -#include -#include "cpumem.h" -#include -#include -#include - - -// ---- I/O - -static void IOOUTCALL crtc_o70(UINT port, REG8 dat) { - - port = (port & 0x0e) >> 1; - dat &= 0x1f; - if (crtc.b[port] != dat) { - crtc.b[port] = (UINT8)dat; - gdcs.textdisp |= GDCSCRN_ALLDRAW; - } -} - -static void IOOUTCALL crtc_o7c(UINT port, REG8 dat) { - - if (grcg.chip) { - grcg.modereg = (UINT8)dat; - grcg.counter = 0; - vramop.operate &= ~(3 << VOPBIT_GRCG); - vramop.operate |= ((dat & 0xc0) >> (6 - VOPBIT_GRCG)); - if (grcg.chip >= 2) { - grcg.gdcwithgrcg = (dat >> 4) & 0x0c; - } - MEMM_VRAM(vramop.operate); - } - (void)port; -} - -static void IOOUTCALL crtc_o7e(UINT port, REG8 dat) { - - int cnt; - - cnt = grcg.counter; - grcg.tile[cnt].b[0] = (UINT8)dat; - grcg.tile[cnt].b[1] = (UINT8)dat; - grcg.counter = (cnt + 1) & 3; - (void)port; -} - -static REG8 IOINPCALL crtc_i7c(UINT port) { - - (void)port; - return(grcg.modereg); -} - - -// ---- I/F - -static const IOOUT crtco70[8] = { - crtc_o70, crtc_o70, crtc_o70, crtc_o70, - crtc_o70, crtc_o70, crtc_o7c, crtc_o7e}; - -static const IOINP crtci70[8] = { - NULL, NULL, NULL, NULL, - NULL, NULL, crtc_i7c, NULL}; - - -void crtc_biosreset(void) { - - if (!(pccore.dipsw[0] & 0x01)) { - crtc.reg.pl = 0; - crtc.reg.bl = 0x0f; - crtc.reg.cl = 0x10; - crtc.reg.ssl = 0; - } - else { - crtc.reg.pl = 0; - crtc.reg.bl = 0x07; - crtc.reg.cl = 0x08; - crtc.reg.ssl = 0; - } - gdcs.textdisp |= GDCSCRN_ALLDRAW; - - grcg.modereg = 0; - grcg.counter = 0; - vramop.operate &= ~(3 << VOPBIT_GRCG); - grcg.gdcwithgrcg = 0; - ZeroMemory(grcg.tile, sizeof(grcg.tile)); - MEMM_VRAM(vramop.operate); -} - -void crtc_reset(const NP2CFG *pConfig) { - - ZeroMemory(&grcg, sizeof(grcg)); - ZeroMemory(&crtc, sizeof(crtc)); -#if defined(SUPPORT_PC9821) - grcg.chip = 3; // PC-9821は EGC必須 -#else - grcg.chip = pConfig->grcg & 3; // GRCG動作のコピー -#endif - crtc_biosreset(); -} - -void crtc_bind(void) { - - iocore_attachsysoutex(0x0070, 0x0cf1, crtco70, 8); - iocore_attachsysinpex(0x0070, 0x0cf1, crtci70, 8); -} - +#include +#include "cpumem.h" +#include +#include +#include + + +// ---- I/O + +static void IOOUTCALL crtc_o70(UINT port, REG8 dat) { + + port = (port & 0x0e) >> 1; + dat &= 0x1f; + if (crtc.b[port] != dat) { + crtc.b[port] = (UINT8)dat; + gdcs.textdisp |= GDCSCRN_ALLDRAW; + } +} + +static void IOOUTCALL crtc_o7c(UINT port, REG8 dat) { + + if (grcg.chip) { + grcg.modereg = (UINT8)dat; + grcg.counter = 0; + vramop.operate &= ~(3 << VOPBIT_GRCG); + vramop.operate |= ((dat & 0xc0) >> (6 - VOPBIT_GRCG)); + if (grcg.chip >= 2) { + grcg.gdcwithgrcg = (dat >> 4) & 0x0c; + } + MEMM_VRAM(vramop.operate); + } + (void)port; +} + +static void IOOUTCALL crtc_o7e(UINT port, REG8 dat) { + + int cnt; + + cnt = grcg.counter; + grcg.tile[cnt].b[0] = (UINT8)dat; + grcg.tile[cnt].b[1] = (UINT8)dat; + grcg.counter = (cnt + 1) & 3; + (void)port; +} + +static REG8 IOINPCALL crtc_i7c(UINT port) { + + (void)port; + return(grcg.modereg); +} + + +// ---- I/F + +static const IOOUT crtco70[8] = { + crtc_o70, crtc_o70, crtc_o70, crtc_o70, + crtc_o70, crtc_o70, crtc_o7c, crtc_o7e}; + +static const IOINP crtci70[8] = { + NULL, NULL, NULL, NULL, + NULL, NULL, crtc_i7c, NULL}; + + +void crtc_biosreset(void) { + + if (!(pccore.dipsw[0] & 0x01)) { + crtc.reg.pl = 0; + crtc.reg.bl = 0x0f; + crtc.reg.cl = 0x10; + crtc.reg.ssl = 0; + } + else { + crtc.reg.pl = 0; + crtc.reg.bl = 0x07; + crtc.reg.cl = 0x08; + crtc.reg.ssl = 0; + } + gdcs.textdisp |= GDCSCRN_ALLDRAW; + + grcg.modereg = 0; + grcg.counter = 0; + vramop.operate &= ~(3 << VOPBIT_GRCG); + grcg.gdcwithgrcg = 0; + ZeroMemory(grcg.tile, sizeof(grcg.tile)); + MEMM_VRAM(vramop.operate); +} + +void crtc_reset(const NP2CFG *pConfig) { + + ZeroMemory(&grcg, sizeof(grcg)); + ZeroMemory(&crtc, sizeof(crtc)); +#if defined(SUPPORT_PC9821) + grcg.chip = 3; // PC-9821は EGC必須 +#else + grcg.chip = pConfig->grcg & 3; // GRCG動作のコピー +#endif + crtc_biosreset(); +} + +void crtc_bind(void) { + + iocore_attachsysoutex(0x0070, 0x0cf1, crtco70, 8); + iocore_attachsysinpex(0x0070, 0x0cf1, crtci70, 8); +} + diff --git a/io/crtc.h b/io/crtc.h old mode 100755 new mode 100644 index c24f048b..e9070b06 --- a/io/crtc.h +++ b/io/crtc.h @@ -1,42 +1,42 @@ - -typedef union { - struct { - UINT8 pl; - UINT8 bl; - UINT8 cl; - UINT8 ssl; - UINT8 sur; - UINT8 sdr; - } reg; - UINT8 b[6]; -} _CRTC, *CRTC; - -typedef union { - UINT8 b[2]; - UINT16 w; -} PAIR16; - -typedef struct { - UINT32 counter; - UINT16 mode; - UINT8 modereg; - UINT8 padding; - PAIR16 tile[4]; - UINT32 gdcwithgrcg; - UINT8 chip; -} _GRCG, *GRCG; - - -#ifdef __cplusplus -extern "C" { -#endif - -void crtc_reset(const NP2CFG *pConfig); -void crtc_bind(void); - -void crtc_biosreset(void); - -#ifdef __cplusplus -} -#endif - + +typedef union { + struct { + UINT8 pl; + UINT8 bl; + UINT8 cl; + UINT8 ssl; + UINT8 sur; + UINT8 sdr; + } reg; + UINT8 b[6]; +} _CRTC, *CRTC; + +typedef union { + UINT8 b[2]; + UINT16 w; +} PAIR16; + +typedef struct { + UINT32 counter; + UINT16 mode; + UINT8 modereg; + UINT8 padding; + PAIR16 tile[4]; + UINT32 gdcwithgrcg; + UINT8 chip; +} _GRCG, *GRCG; + + +#ifdef __cplusplus +extern "C" { +#endif + +void crtc_reset(const NP2CFG *pConfig); +void crtc_bind(void); + +void crtc_biosreset(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/dipsw.c b/io/dipsw.c old mode 100755 new mode 100644 index ab01d723..c3799a5f --- a/io/dipsw.c +++ b/io/dipsw.c @@ -1,115 +1,115 @@ -#include -#include -#include -#include -#include -#include -#include - - -void IOOUTCALL dipsw_w8(UINT port, REG8 value) { - - UINT8 set; - - switch(port & 0x0f00) { - case 0x0400: - if (!(iflags[value] & 0x04)) { - set = value & 0xfc; - if ((pccore.dipsw[0] ^ set) & 0xfc) { - pccore.dipsw[0] &= ~(0xfc); - pccore.dipsw[0] |= set; - } - } - break; - - case 0x0500: - if (!(iflags[value] & 0x04)) { - set = value & 0xef; - if ((pccore.dipsw[1] ^ set) & 0xef) { - pccore.dipsw[1] &= ~(0xef); - pccore.dipsw[1] |= set; - } - } - break; - - case 0x0600: - if (!(iflags[value] & 0x04)) { - set = value & 0x7f; - if ((pccore.dipsw[2] ^ set) & 0x7f) { - pccore.dipsw[2] &= ~(0x7f); - pccore.dipsw[2] |= set; - } - } - break; - - case 0x0700: - if (!(iflags[value] & 0x04)) { - set = (value & 0x20) >> 1; - if ((pccore.dipsw[1] ^ set) & 0x10) { - pccore.dipsw[1] ^= 0x10; - } - set = (value >> 2) & 0x03; - if (np2cfg.BEEP_VOL != set) { - np2cfg.BEEP_VOL = set; - beep_setvol(set); - sysmng_update(SYS_UPDATECFG); - } - } - break; - - case 0x0e00: - if (!(iflags[value] & 0x04)) { - set = (value & 0x10) << 3; - if ((pccore.dipsw[2] ^ set) & 0x80) { - pccore.dipsw[2] ^= 0x80; - } - } - break; - } -} - -REG8 IOINPCALL dipsw_r8(UINT port) { - - REG8 ret; - - ret = 0xff; - switch(port & 0x0f00) { - case 0x0400: - ret = pccore.dipsw[0] & 0xfc; - if (iflags[ret] & 0x04) { - ret |= 0x01; - } - break; - - case 0x0500: - ret = pccore.dipsw[1] & 0xef; - if (iflags[ret] & 0x04) { - ret |= 0x10; - } - break; - - case 0x0600: - ret = pccore.dipsw[2] & 0x7f; - if (iflags[ret] & 0x04) { - ret |= 0x80; - } - break; - - case 0x0700: - ret = ((pccore.dipsw[1] & 0x10) << 1) | - ((np2cfg.BEEP_VOL & 0x03) << 2); - if (iflags[ret] & 0x04) { - ret |= 0x80; - } - break; - - case 0x0e00: - ret = (pccore.dipsw[2] & 0x80) >> 3; - if (iflags[ret] & 0x04) { - ret |= 0x80; - } - break; - } - return(ret); -} - +#include +#include +#include +#include +#include +#include +#include + + +void IOOUTCALL dipsw_w8(UINT port, REG8 value) { + + UINT8 set; + + switch(port & 0x0f00) { + case 0x0400: + if (!(iflags[value] & 0x04)) { + set = value & 0xfc; + if ((pccore.dipsw[0] ^ set) & 0xfc) { + pccore.dipsw[0] &= ~(0xfc); + pccore.dipsw[0] |= set; + } + } + break; + + case 0x0500: + if (!(iflags[value] & 0x04)) { + set = value & 0xef; + if ((pccore.dipsw[1] ^ set) & 0xef) { + pccore.dipsw[1] &= ~(0xef); + pccore.dipsw[1] |= set; + } + } + break; + + case 0x0600: + if (!(iflags[value] & 0x04)) { + set = value & 0x7f; + if ((pccore.dipsw[2] ^ set) & 0x7f) { + pccore.dipsw[2] &= ~(0x7f); + pccore.dipsw[2] |= set; + } + } + break; + + case 0x0700: + if (!(iflags[value] & 0x04)) { + set = (value & 0x20) >> 1; + if ((pccore.dipsw[1] ^ set) & 0x10) { + pccore.dipsw[1] ^= 0x10; + } + set = (value >> 2) & 0x03; + if (np2cfg.BEEP_VOL != set) { + np2cfg.BEEP_VOL = set; + beep_setvol(set); + sysmng_update(SYS_UPDATECFG); + } + } + break; + + case 0x0e00: + if (!(iflags[value] & 0x04)) { + set = (value & 0x10) << 3; + if ((pccore.dipsw[2] ^ set) & 0x80) { + pccore.dipsw[2] ^= 0x80; + } + } + break; + } +} + +REG8 IOINPCALL dipsw_r8(UINT port) { + + REG8 ret; + + ret = 0xff; + switch(port & 0x0f00) { + case 0x0400: + ret = pccore.dipsw[0] & 0xfc; + if (iflags[ret] & 0x04) { + ret |= 0x01; + } + break; + + case 0x0500: + ret = pccore.dipsw[1] & 0xef; + if (iflags[ret] & 0x04) { + ret |= 0x10; + } + break; + + case 0x0600: + ret = pccore.dipsw[2] & 0x7f; + if (iflags[ret] & 0x04) { + ret |= 0x80; + } + break; + + case 0x0700: + ret = ((pccore.dipsw[1] & 0x10) << 1) | + ((np2cfg.BEEP_VOL & 0x03) << 2); + if (iflags[ret] & 0x04) { + ret |= 0x80; + } + break; + + case 0x0e00: + ret = (pccore.dipsw[2] & 0x80) >> 3; + if (iflags[ret] & 0x04) { + ret |= 0x80; + } + break; + } + return(ret); +} + diff --git a/io/dipsw.h b/io/dipsw.h old mode 100755 new mode 100644 index 5276a206..689a2e71 --- a/io/dipsw.h +++ b/io/dipsw.h @@ -1,12 +1,12 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void IOOUTCALL dipsw_w8(UINT port, REG8 value); -REG8 IOINPCALL dipsw_r8(UINT port); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void IOOUTCALL dipsw_w8(UINT port, REG8 value); +REG8 IOINPCALL dipsw_r8(UINT port); + +#ifdef __cplusplus +} +#endif + diff --git a/io/egc.c b/io/egc.c old mode 100755 new mode 100644 index e15dda77..a395a80b --- a/io/egc.c +++ b/io/egc.c @@ -1,191 +1,191 @@ -#include -#include -#include -#include -#include -#include - - -// エンディアン修正しる。 - -static const UINT16 maskword[16][4] = { - {0x0000,0x0000,0x0000,0x0000}, {0xffff,0x0000,0x0000,0x0000}, - {0x0000,0xffff,0x0000,0x0000}, {0xffff,0xffff,0x0000,0x0000}, - {0x0000,0x0000,0xffff,0x0000}, {0xffff,0x0000,0xffff,0x0000}, - {0x0000,0xffff,0xffff,0x0000}, {0xffff,0xffff,0xffff,0x0000}, - {0x0000,0x0000,0x0000,0xffff}, {0xffff,0x0000,0x0000,0xffff}, - {0x0000,0xffff,0x0000,0xffff}, {0xffff,0xffff,0x0000,0xffff}, - {0x0000,0x0000,0xffff,0xffff}, {0xffff,0x0000,0xffff,0xffff}, - {0x0000,0xffff,0xffff,0xffff}, {0xffff,0xffff,0xffff,0xffff}}; - - -static void IOOUTCALL egc_o4a0(UINT port, REG8 value) { - - if (!(vramop.operate & (1 << VOPBIT_EGC))) { - return; - } - -// TRACEOUT(port, value); - switch(port & 0x000f) { - case 0x00: - egc.access &= 0xff00; - egc.access |= value; - break; - case 0x01: - egc.access &= 0x00ff; - egc.access |= value << 8; - break; - - case 0x02: - egc.fgbg &= 0xff00; - egc.fgbg |= value; - break; - case 0x03: - egc.fgbg &= 0x00ff; - egc.fgbg |= value << 8; - break; - - case 0x04: - egc.ope &= 0xff00; - egc.ope |= value; - break; - case 0x05: - egc.ope &= 0x00ff; - egc.ope |= value << 8; - break; - - case 0x06: - egc.fg &= 0xff00; - egc.fg |= value; - egc.fgc.d[0] = *(UINT32 *)(maskword[value & 15] + 0); - egc.fgc.d[1] = *(UINT32 *)(maskword[value & 15] + 2); - break; - case 0x07: - egc.fg &= 0x00ff; - egc.fg |= value << 8; - break; - - case 0x08: - if (!(egc.fgbg & 0x6000)) { - egc.mask._b[0] = value; - } - break; - case 0x09: - if (!(egc.fgbg & 0x6000)) { - egc.mask._b[1] = value; - } - break; - - case 0x0a: - egc.bg &= 0xff00; - egc.bg |= value; - egc.bgc.d[0] = *(UINT32 *)(maskword[value & 15] + 0); - egc.bgc.d[1] = *(UINT32 *)(maskword[value & 15] + 2); - break; - case 0x0b: - egc.bg &= 0x00ff; - egc.bg |= value << 8; - break; - - case 0x0c: - egc.sft &= 0xff00; - egc.sft |= value; - egcshift(); - egc.srcmask.w = 0xffff; - break; - case 0x0d: - egc.sft &= 0x00ff; - egc.sft |= value << 8; - egcshift(); - egc.srcmask.w = 0xffff; - break; - - case 0x0e: - egc.leng &= 0xff00; - egc.leng |= value; - egcshift(); - egc.srcmask.w = 0xffff; - break; - case 0x0f: - egc.leng &= 0x00ff; - egc.leng |= value << 8; - egcshift(); - egc.srcmask.w = 0xffff; - break; - } -} - -void egc_reset(const NP2CFG *pConfig) { - - ZeroMemory(&egc, sizeof(egc)); - egc.access = 0xfff0; - egc.fgbg = 0x00ff; - egc.mask.w = 0xffff; - egc.leng = 0x000f; - egcshift(); - egc.srcmask.w = 0xffff; - - (void)pConfig; -} - -void egc_bind(void) { - - UINT i; - - for (i=0; i<16; i++) { - iocore_attachout(0x04a0 + i, egc_o4a0); - } -} - -void IOOUTCALL egc_w16(UINT port, REG16 value) { - - if (!(vramop.operate & (1 << VOPBIT_EGC))) { - return; - } - -// TRACEOUTW(port, value); - switch(port & 0x000f) { - case 0x00: - egc.access = value; - break; - - case 0x02: - egc.fgbg = value; - break; - - case 0x04: - egc.ope = value; - break; - - case 0x06: - egc.fg = value; - egc.fgc.d[0] = *(UINT32 *)(maskword[value & 15] + 0); - egc.fgc.d[1] = *(UINT32 *)(maskword[value & 15] + 2); - break; - - case 0x08: - if (!(egc.fgbg & 0x6000)) { - egc.mask.w = value; - } - break; - - case 0x0a: - egc.bg = value; - egc.bgc.d[0] = *(UINT32 *)(maskword[value & 15] + 0); - egc.bgc.d[1] = *(UINT32 *)(maskword[value & 15] + 2); - break; - - case 0x0c: - egc.sft = value; - egcshift(); - egc.srcmask.w = 0xffff; - break; - - case 0x0e: - egc.leng = value; - egcshift(); - egc.srcmask.w = 0xffff; - break; - } -} - +#include +#include +#include +#include +#include +#include + + +// エンディアン修正しる。 + +static const UINT16 maskword[16][4] = { + {0x0000,0x0000,0x0000,0x0000}, {0xffff,0x0000,0x0000,0x0000}, + {0x0000,0xffff,0x0000,0x0000}, {0xffff,0xffff,0x0000,0x0000}, + {0x0000,0x0000,0xffff,0x0000}, {0xffff,0x0000,0xffff,0x0000}, + {0x0000,0xffff,0xffff,0x0000}, {0xffff,0xffff,0xffff,0x0000}, + {0x0000,0x0000,0x0000,0xffff}, {0xffff,0x0000,0x0000,0xffff}, + {0x0000,0xffff,0x0000,0xffff}, {0xffff,0xffff,0x0000,0xffff}, + {0x0000,0x0000,0xffff,0xffff}, {0xffff,0x0000,0xffff,0xffff}, + {0x0000,0xffff,0xffff,0xffff}, {0xffff,0xffff,0xffff,0xffff}}; + + +static void IOOUTCALL egc_o4a0(UINT port, REG8 value) { + + if (!(vramop.operate & (1 << VOPBIT_EGC))) { + return; + } + +// TRACEOUT(port, value); + switch(port & 0x000f) { + case 0x00: + egc.access &= 0xff00; + egc.access |= value; + break; + case 0x01: + egc.access &= 0x00ff; + egc.access |= value << 8; + break; + + case 0x02: + egc.fgbg &= 0xff00; + egc.fgbg |= value; + break; + case 0x03: + egc.fgbg &= 0x00ff; + egc.fgbg |= value << 8; + break; + + case 0x04: + egc.ope &= 0xff00; + egc.ope |= value; + break; + case 0x05: + egc.ope &= 0x00ff; + egc.ope |= value << 8; + break; + + case 0x06: + egc.fg &= 0xff00; + egc.fg |= value; + egc.fgc.d[0] = *(UINT32 *)(maskword[value & 15] + 0); + egc.fgc.d[1] = *(UINT32 *)(maskword[value & 15] + 2); + break; + case 0x07: + egc.fg &= 0x00ff; + egc.fg |= value << 8; + break; + + case 0x08: + if (!(egc.fgbg & 0x6000)) { + egc.mask._b[0] = value; + } + break; + case 0x09: + if (!(egc.fgbg & 0x6000)) { + egc.mask._b[1] = value; + } + break; + + case 0x0a: + egc.bg &= 0xff00; + egc.bg |= value; + egc.bgc.d[0] = *(UINT32 *)(maskword[value & 15] + 0); + egc.bgc.d[1] = *(UINT32 *)(maskword[value & 15] + 2); + break; + case 0x0b: + egc.bg &= 0x00ff; + egc.bg |= value << 8; + break; + + case 0x0c: + egc.sft &= 0xff00; + egc.sft |= value; + egcshift(); + egc.srcmask.w = 0xffff; + break; + case 0x0d: + egc.sft &= 0x00ff; + egc.sft |= value << 8; + egcshift(); + egc.srcmask.w = 0xffff; + break; + + case 0x0e: + egc.leng &= 0xff00; + egc.leng |= value; + egcshift(); + egc.srcmask.w = 0xffff; + break; + case 0x0f: + egc.leng &= 0x00ff; + egc.leng |= value << 8; + egcshift(); + egc.srcmask.w = 0xffff; + break; + } +} + +void egc_reset(const NP2CFG *pConfig) { + + ZeroMemory(&egc, sizeof(egc)); + egc.access = 0xfff0; + egc.fgbg = 0x00ff; + egc.mask.w = 0xffff; + egc.leng = 0x000f; + egcshift(); + egc.srcmask.w = 0xffff; + + (void)pConfig; +} + +void egc_bind(void) { + + UINT i; + + for (i=0; i<16; i++) { + iocore_attachout(0x04a0 + i, egc_o4a0); + } +} + +void IOOUTCALL egc_w16(UINT port, REG16 value) { + + if (!(vramop.operate & (1 << VOPBIT_EGC))) { + return; + } + +// TRACEOUTW(port, value); + switch(port & 0x000f) { + case 0x00: + egc.access = value; + break; + + case 0x02: + egc.fgbg = value; + break; + + case 0x04: + egc.ope = value; + break; + + case 0x06: + egc.fg = value; + egc.fgc.d[0] = *(UINT32 *)(maskword[value & 15] + 0); + egc.fgc.d[1] = *(UINT32 *)(maskword[value & 15] + 2); + break; + + case 0x08: + if (!(egc.fgbg & 0x6000)) { + egc.mask.w = value; + } + break; + + case 0x0a: + egc.bg = value; + egc.bgc.d[0] = *(UINT32 *)(maskword[value & 15] + 0); + egc.bgc.d[1] = *(UINT32 *)(maskword[value & 15] + 2); + break; + + case 0x0c: + egc.sft = value; + egcshift(); + egc.srcmask.w = 0xffff; + break; + + case 0x0e: + egc.leng = value; + egcshift(); + egc.srcmask.w = 0xffff; + break; + } +} + diff --git a/io/egc.h b/io/egc.h old mode 100755 new mode 100644 index 4eb6566f..77780c78 --- a/io/egc.h +++ b/io/egc.h @@ -1,57 +1,57 @@ - -typedef union { - UINT8 _b[2]; - UINT16 w; -} EGCWORD; - -typedef union { - UINT8 _b[4][2]; - UINT16 w[4]; - UINT32 d[2]; - UINT64 q; -} EGCQUAD; - -typedef struct { - UINT16 access; - UINT16 fgbg; - UINT16 ope; - UINT16 fg; - EGCWORD mask; - UINT16 bg; - UINT16 sft; - UINT16 leng; - EGCQUAD lastvram; - EGCQUAD patreg; - EGCQUAD fgc; - EGCQUAD bgc; - - int func; - UINT remain; - UINT stack; - UINT8 *inptr; - UINT8 *outptr; - EGCWORD mask2; - EGCWORD srcmask; - UINT8 srcbit; - UINT8 dstbit; - UINT8 sft8bitl; - UINT8 sft8bitr; - - UINT padding_b[4]; - UINT8 buf[4096/8 + 4*4]; - UINT padding_a[4]; -} _EGC, *EGC; - - -#ifdef __cplusplus -extern "C" { -#endif - -void egc_reset(const NP2CFG *pConfig); -void egc_bind(void); -void IOOUTCALL egc_w16(UINT port, REG16 value); - -#ifdef __cplusplus -} -#endif - + +typedef union { + UINT8 _b[2]; + UINT16 w; +} EGCWORD; + +typedef union { + UINT8 _b[4][2]; + UINT16 w[4]; + UINT32 d[2]; + UINT64 q; +} EGCQUAD; + +typedef struct { + UINT16 access; + UINT16 fgbg; + UINT16 ope; + UINT16 fg; + EGCWORD mask; + UINT16 bg; + UINT16 sft; + UINT16 leng; + EGCQUAD lastvram; + EGCQUAD patreg; + EGCQUAD fgc; + EGCQUAD bgc; + + int func; + UINT remain; + UINT stack; + UINT8 *inptr; + UINT8 *outptr; + EGCWORD mask2; + EGCWORD srcmask; + UINT8 srcbit; + UINT8 dstbit; + UINT8 sft8bitl; + UINT8 sft8bitr; + + UINT padding_b[4]; + UINT8 buf[4096/8 + 4*4]; + UINT padding_a[4]; +} _EGC, *EGC; + + +#ifdef __cplusplus +extern "C" { +#endif + +void egc_reset(const NP2CFG *pConfig); +void egc_bind(void); +void IOOUTCALL egc_w16(UINT port, REG16 value); + +#ifdef __cplusplus +} +#endif + diff --git a/io/emsio.c b/io/emsio.c old mode 100755 new mode 100644 index 4aab3500..c1d40fe3 --- a/io/emsio.c +++ b/io/emsio.c @@ -1,77 +1,77 @@ -#include -#include -#include -#include - - -// ---- I/O - -static void IOOUTCALL emsio_o08e1(UINT port, REG8 dat) { - - UINT pos; - UINT32 addr; - - pos = (port >> 1) & 3; - if (!emsio.target) { - addr = 0xc0000 + (pos << 14); - emsio.addr[pos] = addr; - CPU_SETEMM(pos, addr); - } - else if (emsio.target <= emsio.maxmem) { - dat &= 0xfc; - addr = (emsio.target << 20) + (dat << 12); - emsio.addr[pos] = addr; - CPU_SETEMM(pos, addr); - } -} - -static void IOOUTCALL emsio_o08e9(UINT port, REG8 dat) { - - emsio.target = (UINT8)(dat & 0x0f); - (void)port; -} - -static REG8 IOINPCALL emsio_i08e9(UINT port) { - - if ((emsio.target) && (emsio.target <= emsio.maxmem)) { - return(0); - } - else { - return(0xff); - } - (void)port; -} - -// ---- I/F - -void emsio_reset(const NP2CFG *pConfig) { - - ZeroMemory(&emsio, sizeof(emsio)); -#if 1 || !defined(CPUCORE_IA32) - emsio.maxmem = (pccore.extmem > 255 ? 255 : pccore.extmem); // XXX: 256MB以上のときどうなる? -#endif - emsio.addr[0] = 0xc0000; - emsio.addr[1] = 0xc4000; - emsio.addr[2] = 0xc8000; - emsio.addr[3] = 0xcc000; - - (void)pConfig; -} - -void emsio_bind(void) { - - UINT i; - - for (i=0; i<4; i++) { - CPU_SETEMM(i, emsio.addr[i]); - } - if (emsio.maxmem) { - iocore_attachout(0x08e1, emsio_o08e1); - iocore_attachout(0x08e3, emsio_o08e1); - iocore_attachout(0x08e5, emsio_o08e1); - iocore_attachout(0x08e7, emsio_o08e1); - iocore_attachout(0x08e9, emsio_o08e9); - iocore_attachinp(0x08e9, emsio_i08e9); - } -} - +#include +#include +#include +#include + + +// ---- I/O + +static void IOOUTCALL emsio_o08e1(UINT port, REG8 dat) { + + UINT pos; + UINT32 addr; + + pos = (port >> 1) & 3; + if (!emsio.target) { + addr = 0xc0000 + (pos << 14); + emsio.addr[pos] = addr; + CPU_SETEMM(pos, addr); + } + else if (emsio.target <= emsio.maxmem) { + dat &= 0xfc; + addr = (emsio.target << 20) + (dat << 12); + emsio.addr[pos] = addr; + CPU_SETEMM(pos, addr); + } +} + +static void IOOUTCALL emsio_o08e9(UINT port, REG8 dat) { + + emsio.target = (UINT8)(dat & 0x0f); + (void)port; +} + +static REG8 IOINPCALL emsio_i08e9(UINT port) { + + if ((emsio.target) && (emsio.target <= emsio.maxmem)) { + return(0); + } + else { + return(0xff); + } + (void)port; +} + +// ---- I/F + +void emsio_reset(const NP2CFG *pConfig) { + + ZeroMemory(&emsio, sizeof(emsio)); +#if 1 || !defined(CPUCORE_IA32) + emsio.maxmem = (pccore.extmem > 255 ? 255 : pccore.extmem); // XXX: 256MB以上のときどうなる? +#endif + emsio.addr[0] = 0xc0000; + emsio.addr[1] = 0xc4000; + emsio.addr[2] = 0xc8000; + emsio.addr[3] = 0xcc000; + + (void)pConfig; +} + +void emsio_bind(void) { + + UINT i; + + for (i=0; i<4; i++) { + CPU_SETEMM(i, emsio.addr[i]); + } + if (emsio.maxmem) { + iocore_attachout(0x08e1, emsio_o08e1); + iocore_attachout(0x08e3, emsio_o08e1); + iocore_attachout(0x08e5, emsio_o08e1); + iocore_attachout(0x08e7, emsio_o08e1); + iocore_attachout(0x08e9, emsio_o08e9); + iocore_attachinp(0x08e9, emsio_i08e9); + } +} + diff --git a/io/emsio.h b/io/emsio.h old mode 100755 new mode 100644 index 2b077a9d..4b4ab9a3 --- a/io/emsio.h +++ b/io/emsio.h @@ -1,20 +1,20 @@ - -typedef struct { - UINT8 maxmem; // LARGE_MEM //UINT8 UINT16 maxmem; - UINT8 target; - UINT16 padding; - UINT32 addr[4]; -} _EMSIO, *EMSIO; - - -#ifdef __cplusplus -extern "C" { -#endif - -void emsio_reset(const NP2CFG *pConfig); -void emsio_bind(void); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + UINT8 maxmem; // LARGE_MEM //UINT8 UINT16 maxmem; + UINT8 target; + UINT16 padding; + UINT32 addr[4]; +} _EMSIO, *EMSIO; + + +#ifdef __cplusplus +extern "C" { +#endif + +void emsio_reset(const NP2CFG *pConfig); +void emsio_bind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/epsonio.c b/io/epsonio.c old mode 100755 new mode 100644 index 009307e0..f7746322 --- a/io/epsonio.c +++ b/io/epsonio.c @@ -1,129 +1,129 @@ -#include -#include -#include -#include - - -// EPSON専用ポート 0c00〜 - -static void bankselect(void) { - - if (epsonio.bankioen & 0x02) { - CPU_ITFBANK = 1; - TRACEOUT(("EPSON ITF - Enable")); - } - else { - CPU_ITFBANK = 0; - TRACEOUT(("EPSON ITF - Disable")); - } -} - -// ---- I/O - -static void IOOUTCALL epsonio_o043d(UINT port, REG8 dat) { - - switch(dat) { - case 0x00: - if (epsonio.bankioen & 0x01) { - epsonio.bankioen &= ~0x02; - bankselect(); - } - break; - - case 0x02: - if (epsonio.bankioen & 0x01) { - epsonio.bankioen |= 0x02; - bankselect(); - } - break; - - case 0x10: - CPU_ITFBANK = 1; - break; - - case 0x12: - CPU_ITFBANK = 0; - break; - } - (void)port; -} - -static void IOOUTCALL epsonio_o043f(UINT port, REG8 dat) { - - switch(dat) { - case 0x40: - epsonio.bankioen &= ~0x01; - break; - - case 0x42: - epsonio.bankioen |= 0x01; - break; - } - (void)port; -} - -static void IOOUTCALL epsonio_oc07(UINT port, REG8 dat) { - - TRACEOUT(("EPSON ROM MODE - %.2x", dat)); - - switch(dat) { - case 0x2a: // 0010|1010 - case 0x2b: - CopyMemory(mem + 0x1e8000, mem + 0x1c8000, 0x18000); - break; - - case 0x2c: // 0010|1100 - case 0x2d: - CopyMemory(mem + 0x1e8000, mem + 0x0e8000, 0x10000); - CopyMemory(mem + 0x1f8000, mem + 0x1c0000, 0x08000); - break; - - case 0xa6: // 1010|0110 - CopyMemory(mem + 0x1c8000, mem + 0x0e8000, 0x10000); - CopyMemory(mem + 0x1d8000, mem + 0x1c0000, 0x08000); - CopyMemory(mem + 0x1e8000, mem + 0x0e8000, 0x10000); - CopyMemory(mem + 0x1f8000, mem + 0x1c0000, 0x08000); - break; - - case 0xe6: // 1110|0110 - CopyMemory(mem + 0x1d8000, mem + 0x1c0000, 0x08000); - CopyMemory(mem + 0x1f8000, mem + 0x1c0000, 0x08000); - break; - } - (void)port; -} - -static REG8 IOINPCALL epsonio_ic03(UINT port) { - - (void)port; - return(epsonio.cpumode); -} - -static REG8 IOINPCALL epsonio_ic13(UINT port) { - - (void)port; - return(0x00); -} - - -// ---- I/F - -void epsonio_reset(const NP2CFG *pConfig) { - - epsonio.cpumode = 'R'; - - (void)pConfig; -} - -void epsonio_bind(void) { - - if (pccore.model & PCMODEL_EPSON) { - iocore_attachout(0x043d, epsonio_o043d); - iocore_attachout(0x043f, epsonio_o043f); - iocore_attachout(0x0c07, epsonio_oc07); - iocore_attachinp(0x0c03, epsonio_ic03); - iocore_attachinp(0x0c13, epsonio_ic13); - iocore_attachinp(0x0c14, epsonio_ic13); - } -} - +#include +#include +#include +#include + + +// EPSON専用ポート 0c00〜 + +static void bankselect(void) { + + if (epsonio.bankioen & 0x02) { + CPU_ITFBANK = 1; + TRACEOUT(("EPSON ITF - Enable")); + } + else { + CPU_ITFBANK = 0; + TRACEOUT(("EPSON ITF - Disable")); + } +} + +// ---- I/O + +static void IOOUTCALL epsonio_o043d(UINT port, REG8 dat) { + + switch(dat) { + case 0x00: + if (epsonio.bankioen & 0x01) { + epsonio.bankioen &= ~0x02; + bankselect(); + } + break; + + case 0x02: + if (epsonio.bankioen & 0x01) { + epsonio.bankioen |= 0x02; + bankselect(); + } + break; + + case 0x10: + CPU_ITFBANK = 1; + break; + + case 0x12: + CPU_ITFBANK = 0; + break; + } + (void)port; +} + +static void IOOUTCALL epsonio_o043f(UINT port, REG8 dat) { + + switch(dat) { + case 0x40: + epsonio.bankioen &= ~0x01; + break; + + case 0x42: + epsonio.bankioen |= 0x01; + break; + } + (void)port; +} + +static void IOOUTCALL epsonio_oc07(UINT port, REG8 dat) { + + TRACEOUT(("EPSON ROM MODE - %.2x", dat)); + + switch(dat) { + case 0x2a: // 0010|1010 + case 0x2b: + CopyMemory(mem + 0x1e8000, mem + 0x1c8000, 0x18000); + break; + + case 0x2c: // 0010|1100 + case 0x2d: + CopyMemory(mem + 0x1e8000, mem + 0x0e8000, 0x10000); + CopyMemory(mem + 0x1f8000, mem + 0x1c0000, 0x08000); + break; + + case 0xa6: // 1010|0110 + CopyMemory(mem + 0x1c8000, mem + 0x0e8000, 0x10000); + CopyMemory(mem + 0x1d8000, mem + 0x1c0000, 0x08000); + CopyMemory(mem + 0x1e8000, mem + 0x0e8000, 0x10000); + CopyMemory(mem + 0x1f8000, mem + 0x1c0000, 0x08000); + break; + + case 0xe6: // 1110|0110 + CopyMemory(mem + 0x1d8000, mem + 0x1c0000, 0x08000); + CopyMemory(mem + 0x1f8000, mem + 0x1c0000, 0x08000); + break; + } + (void)port; +} + +static REG8 IOINPCALL epsonio_ic03(UINT port) { + + (void)port; + return(epsonio.cpumode); +} + +static REG8 IOINPCALL epsonio_ic13(UINT port) { + + (void)port; + return(0x00); +} + + +// ---- I/F + +void epsonio_reset(const NP2CFG *pConfig) { + + epsonio.cpumode = 'R'; + + (void)pConfig; +} + +void epsonio_bind(void) { + + if (pccore.model & PCMODEL_EPSON) { + iocore_attachout(0x043d, epsonio_o043d); + iocore_attachout(0x043f, epsonio_o043f); + iocore_attachout(0x0c07, epsonio_oc07); + iocore_attachinp(0x0c03, epsonio_ic03); + iocore_attachinp(0x0c13, epsonio_ic13); + iocore_attachinp(0x0c14, epsonio_ic13); + } +} + diff --git a/io/epsonio.h b/io/epsonio.h old mode 100755 new mode 100644 index 9897951a..a7dfdfe1 --- a/io/epsonio.h +++ b/io/epsonio.h @@ -1,18 +1,18 @@ - -typedef struct { - UINT8 cpumode; - UINT8 bankioen; -} _EPSONIO; - - -#ifdef __cplusplus -extern "C" { -#endif - -void epsonio_reset(const NP2CFG *pConfig); -void epsonio_bind(void); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + UINT8 cpumode; + UINT8 bankioen; +} _EPSONIO; + + +#ifdef __cplusplus +extern "C" { +#endif + +void epsonio_reset(const NP2CFG *pConfig); +void epsonio_bind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/fdc.c b/io/fdc.c old mode 100755 new mode 100644 index 6d932f96..6fa4b066 --- a/io/fdc.c +++ b/io/fdc.c @@ -1,1176 +1,1176 @@ -// -// FDC μPD765A -// - -#include -#include -#include -#include -#include -#if defined(SUPPORT_SWSEEKSND) -#include -#include -#endif -#include - -#if 1 -#undef TRACEOUT -#define TRACEOUT(s) (void)(s) -#endif /* 0 */ - -static int fdc_lasttreg[4] = {0}; // 暫定:Win用 Seek後にはtregをfdc.Cで更新 本当はfdc構造体の中に入れるべき - -extern void fddmtrsnd_play(UINT num, BOOL play); - -enum { - FDC_DMACH2HD = 2, - FDC_DMACH2DD = 3 -}; - -static const UINT8 FDCCMD_TABLE[32] = { - 0, 0, 8, 2, 1, 8, 8, 1, 0, 8, 1, 0, 8, 5, 0, 2, - 0, 8, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0}; - - -#define FDC_FORCEREADY (1) -#define FDC_DELAYERROR7 - -#define FDC_INT_DELAY 6 /*!< Delay 100ms */ -#define FDC_SEEKSOUND_TIMEOUT 60 /*!< Timeout 1000ms */ - -static int fdc_seeksndtimeout[4] = {0}; - -void fdc_intwait(NEVENTITEM item) { - - if (item->flag & NEVENT_SETEVENT) { - fdc.intreq = TRUE; - if (fdc.chgreg & 1) { - pic_setirq(0x0b); - } - else { - pic_setirq(0x0a); - } - } -} - -void fdc_interrupt(void) { - - nevent_set(NEVENT_FDCINT, 512, fdc_intwait, NEVENT_ABSOLUTE); -} - -static void fdc_interruptreset(void) { - - fdc.intreq = FALSE; -} - -static BOOL fdc_isfdcinterrupt(void) { - - return(fdc.intreq); -} - -REG8 DMACCALL fdc_dmafunc(REG8 func) { - -// TRACEOUT(("fdc_dmafunc = %d", func)); - switch(func) { - case DMAEXT_START: - return(1); - - case DMAEXT_END: // TC - fdc.tc = 1; - break; - } - return(0); -} - -static void fdc_dmaready(REG8 enable) { - - if (fdc.chgreg & 1) { - dmac.dmach[FDC_DMACH2HD].ready = enable; - } - else { - dmac.dmach[FDC_DMACH2DD].ready = enable; - } -} - - -// ---------------------------------------------------------------------- - -void fdcsend_error7(void) { - - fdc.tc = 0; - fdc.event = FDCEVENT_BUFSEND; - fdc.bufp = 0; - fdc.bufcnt = 7; - fdc.buf[0] = (UINT8)(fdc.stat[fdc.us] >> 0); - fdc.buf[1] = (UINT8)(fdc.stat[fdc.us] >> 8); - fdc.buf[2] = (UINT8)(fdc.stat[fdc.us] >> 16); - fdc.buf[3] = fdc.C; - fdc.buf[4] = fdc.H; - fdc.buf[5] = fdc.R; - fdc.buf[6] = fdc.N; - fdc.status &= 0x0f; - fdc.status |= (1 << fdc.us); - fdc.status |= FDCSTAT_RQM | FDCSTAT_CB | FDCSTAT_DIO; - fdc.stat[fdc.us] = 0; // ver0.29 - fdc_dmaready(0); - dmac_check(); - fdc_interrupt(); -} - -void fdcsend_success7(void) { - - fdc.tc = 0; - fdc.event = FDCEVENT_BUFSEND; - fdc.bufp = 0; - fdc.bufcnt = 7; -#ifdef SUPPORT_KAI_IMAGES - if (fdd_fdcresult() == FALSE) { - fdc.buf[0] = (fdc.hd << 2) | fdc.us; - fdc.buf[1] = 0; - fdc.buf[2] = 0; - } - else { - // FDイメージファイルがFDCリザルトコードを持っている場合は - // (fdc.statに設定しているはずなので)そちらを設定 - fdc.buf[0] = (fdc.hd << 2) | fdc.us | (UINT8)(fdc.stat[fdc.us] >> 0); - fdc.buf[1] = (UINT8)(fdc.stat[fdc.us] >> 8); - fdc.buf[2] = (UINT8)(fdc.stat[fdc.us] >> 16); - } -#else - fdc.buf[0] = (fdc.hd << 2) | fdc.us; - fdc.buf[1] = 0; - fdc.buf[2] = 0; -#endif - fdc.buf[3] = fdc.C; - fdc.buf[4] = fdc.H; - fdc.buf[5] = fdc.R; - fdc.buf[6] = fdc.N; - fdc.status &= 0x0f; - fdc.status |= (1 << fdc.us); - fdc.status |= FDCSTAT_RQM | FDCSTAT_CB | FDCSTAT_DIO; - fdc.stat[fdc.us] = 0; // ver0.29 - fdc_dmaready(0); - dmac_check(); - fdc_interrupt(); -} - -#if 0 -// FDCのタイムアウト まぁ本当はこんなんじゃダメだけど… ver0.29 -void fdctimeoutproc(NEVENTITEM item) { - - if (item->flag & NEVENT_SETEVENT) { - fdc.stat[fdc.us] = FDCRLT_IC0 | FDCRLT_EN | (fdc.hd << 2) | fdc.us; - fdcsend_error7(); - } -} - -static void fdc_timeoutset(void) { - - nevent_setbyms(NEVENT_FDCTIMEOUT, 166, fdctimeoutproc, NEVENT_ABSOLUTE); -} -#endif - - - -static BOOL FDC_DriveCheck(BOOL protectcheck) { - -// if (!fddfile[fdc.us].fname[0]) { - if (!fdd_diskready(fdc.us)) { - fdc.stat[fdc.us] = FDCRLT_IC0 | FDCRLT_NR | (fdc.hd << 2) | fdc.us; - fdcsend_error7(); - return(FALSE); - } -// else if ((protectcheck) && (fddfile[fdc.us].protect)) { - else if ((protectcheck) && fdd_diskprotect(fdc.us)) { - fdc.stat[fdc.us] = FDCRLT_IC0 | FDCRLT_NW | (fdc.hd << 2) | fdc.us; - fdcsend_error7(); - return(FALSE); - } - return(TRUE); -} - -// ---------------------------------------------------------------------- - -static void get_mtmfsk(void) { - - fdc.mt = (fdc.cmd >> 7) & 1; - fdc.mf = fdc.cmd & 0x40; // ver0.29 - fdc.sk = (fdc.cmd >> 5) & 1; -} - -static void get_hdus(void) { - - fdc.hd = (fdc.cmds[0] >> 2) & 1; - fdc.us = fdc.cmds[0] & 3; -} - -static void get_chrn(void) { - - fdc.C = fdc.cmds[1]; - fdc.H = fdc.cmds[2]; - fdc.R = fdc.cmds[3]; - fdc.N = fdc.cmds[4]; -} - -static void get_eotgsldtl(void) { - - fdc.eot = fdc.cmds[5]; - fdc.gpl = fdc.cmds[6]; - fdc.dtl = fdc.cmds[7]; -} - -// -------------------------------------------------------------------------- - -static void FDC_Invalid(void) { // cmd: xx - - fdc.event = FDCEVENT_BUFSEND; - fdc.bufcnt = 1; - fdc.bufp = 0; - fdc.buf[0] = 0x80; - fdc.status &= 0x0f; - fdc.status |= FDCSTAT_RQM | FDCSTAT_CB | FDCSTAT_DIO; -} - -#ifdef SUPPORT_KAI_IMAGES -static void FDC_ReadDiagnostic(void) { // cmd: 02 - - switch(fdc.event) { - case FDCEVENT_CMDRECV: - get_hdus(); - get_chrn(); - get_eotgsldtl(); - fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; - - if (FDC_DriveCheck(FALSE)) { - fdc.event = FDCEVENT_BUFSEND; -// fdc.bufcnt = makedianosedata(); - fdc.bufp = 0; - } - break; - - default: - fdc.event = FDCEVENT_NEUTRAL; - break; - } -} -#endif - -static void FDC_Specify(void) { // cmd: 03 - - switch(fdc.event) { - case FDCEVENT_CMDRECV: - fdc.srt = fdc.cmds[0] >> 4; - fdc.hut = fdc.cmds[0] & 0x0f; - fdc.hlt = fdc.cmds[1] >> 1; - fdc.nd = fdc.cmds[1] & 1; - fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; - break; - } - fdc.event = FDCEVENT_NEUTRAL; - fdc.status &= 0x0f; - fdc.status |= FDCSTAT_RQM; -} - -static void FDC_SenseDeviceStatus(void) { // cmd: 04 - - switch (fdc.event) { - case FDCEVENT_CMDRECV: - get_hdus(); - fdc.buf[0] = (fdc.hd << 2) | fdc.us; - fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; - if (fdc.equip & (1 << fdc.us)) { - fdc.buf[0] |= 0x08; - if (!fdc.treg[fdc.us]) { - fdc.buf[0] |= 0x10; - } - if (fdd_diskready(fdc.us) || (fdc.ctrlreg & 0x40)) {/* 170107 念のため */ - fdc.buf[0] |= 0x20; - } - if (fddfile[fdc.us].protect) { - fdc.buf[0] |= 0x40; - } - } - else { - fdc.buf[0] |= 0x80; - } -// TRACEOUT(("FDC_SenseDeviceStatus %.2x", fdc.buf[0])); - fdc.event = FDCEVENT_BUFSEND; - fdc.bufcnt = 1; - fdc.bufp = 0; - fdc.status &= 0x0f; - fdc.status |= (1 << fdc.us); - fdc.status |= FDCSTAT_RQM | FDCSTAT_CB | FDCSTAT_DIO; - break; - - default: - fdc.event = FDCEVENT_NEUTRAL; - fdc.status &= 0x0f; - fdc.status |= FDCSTAT_RQM; - break; - } -} - -static BRESULT writesector(void) { - - fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; - if (!FDC_DriveCheck(TRUE)) { - return(FAILURE); - } - if (fdd_write()) { - fdc.stat[fdc.us] = fdc.us | (fdc.hd << 2) | FDCRLT_IC0 | FDCRLT_ND; - fdcsend_error7(); - return(FAILURE); - } - fdc.event = FDCEVENT_BUFRECV; - fdc.bufcnt = 128 << fdc.N; - fdc.bufp = 0; -// fdc.status = FDCSTAT_RQM | FDCSTAT_NDM | FDCSTAT_CB; -#if defined(SUPPORT_SWSEEKSND) - if(np2cfg.MOTOR) fddmtrsnd_play(1, TRUE); -#else - if(np2cfg.MOTOR) { - if(fdc_seeksndtimeout[fdc.us]!=0){ - soundmng_pcmplay(SOUND_PCMSEEK, FALSE); - }else{ - soundmng_pcmstop(SOUND_PCMSEEK1); - soundmng_pcmplay(SOUND_PCMSEEK1, FALSE); - } - } -#endif - fdc_seeksndtimeout[fdc.us] = FDC_SEEKSOUND_TIMEOUT; - fdc_dmaready(1); - dmac_check(); - return(SUCCESS); -} - -static void FDC_WriteData(void) { // cmd: 05 - // cmd: 09 - switch(fdc.event) { - case FDCEVENT_CMDRECV: - get_hdus(); - get_chrn(); - get_eotgsldtl(); - fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; - if(fdc_lasttreg[fdc.us] != fdc.treg[fdc.us]){ - fdc.treg[fdc.us] = fdc.C; /* 170101 ST modified to work on Windows 9x/2000 */ - } - if (FDC_DriveCheck(TRUE)) { - fdc.event = FDCEVENT_BUFRECV; - fdc.bufcnt = 128 << fdc.N; - fdc.bufp = 0; -#if 1 // ver0.27 ?? - fdc.status &= 0x0f; - fdc.status |= (1 << fdc.us); - fdc.status |= FDCSTAT_RQM | FDCSTAT_CB; - if (fdc.nd) { - fdc.status |= FDCSTAT_NDM; - } -#else - fdc.status = FDCSTAT_RQM | FDCSTAT_NDM | FDCSTAT_CB; -#endif - fdc_dmaready(1); - dmac_check(); - } - break; - - case FDCEVENT_BUFRECV: - if (writesector()) { - return; - } - /* 170101 ST modified to work on Windows 9x/2000 form ... */ - //if (fdc.tc) { - // fdcsend_success7(); - // return; - //} - if ((fdc.tc) || (fdc.R++ == fdc.eot)) { - fdc.R = 1; - if (fdc.mt) { - fdc.hd ^= 1; - fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; - fdc.H ^= 1; - if (fdc.tc || !fdc.H) { - fdc.C++; - fdcsend_success7(); - break; - } - } - else { - fdc.C++; - fdcsend_success7(); - } - //fdc.stat[fdc.us] = fdc.us | (fdc.hd << 2) | - // FDCRLT_IC0 | FDCRLT_EN; - //fdcsend_error7(); - break; - } - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - break; - - default: - fdc.event = FDCEVENT_NEUTRAL; - fdc.status &= 0x0f; - fdc.status |= FDCSTAT_RQM; - break; - } -} - -static void readsector(void) { - - fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; - if (!FDC_DriveCheck(FALSE)) { - return; - } - if (fdd_read()) { - fdc.stat[fdc.us] = fdc.us | (fdc.hd << 2) | FDCRLT_IC0 | FDCRLT_ND; - fdcsend_error7(); - return; - } -#if defined(SUPPORT_SWSEEKSND) - if(np2cfg.MOTOR) fddmtrsnd_play(1, TRUE); -#else - if(np2cfg.MOTOR) { - if(fdc_seeksndtimeout[fdc.us]!=0){ - soundmng_pcmplay(SOUND_PCMSEEK, FALSE); - }else{ - soundmng_pcmstop(SOUND_PCMSEEK1); - soundmng_pcmplay(SOUND_PCMSEEK1, FALSE); - } - } -#endif - fdc_seeksndtimeout[fdc.us] = FDC_SEEKSOUND_TIMEOUT; - - fdc.event = FDCEVENT_BUFSEND2; - fdc.bufp = 0; -#if 0 // ver0.27 ?? - fdc.status = FDCSTAT_NDM | FDCSTAT_CB; - if (!(fdc.ctrlreg & 0x10)) { - fdc.status |= FDCSTAT_RQM | FDCSTAT_DIO; - } -#else - fdc.status &= 0x0f; - fdc.status |= (1 << fdc.us); - fdc.status |= FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB; - if (fdc.nd) { - fdc.status |= FDCSTAT_NDM; - } -#endif - fdc_dmaready(1); - dmac_check(); -} - -static void FDC_ReadData(void) { // cmd: 06 - // cmd: 0c - switch(fdc.event) { - case FDCEVENT_CMDRECV: - get_hdus(); - get_chrn(); - get_eotgsldtl(); - if(fdc_lasttreg[fdc.us] != fdc.treg[fdc.us]){ - fdc.treg[fdc.us] = fdc.C; /* 170101 ST modified to work on Windows 9x/2000 */ - } - readsector(); - break; - - case FDCEVENT_NEXTDATA: - fdc.bufcnt = 0; - if (fdc.R++ == fdc.eot) { - /* 170101 ST modified to work on Windows 9x/2000 form ... */ - fdc.R = 1; - if (fdc.mt) { - fdc.hd ^= 1; - fdc.H ^= 1; - if (fdc.H) { - readsector(); - break; - } - } - fdc.C++; - fdcsend_success7(); - //fdc.stat[fdc.us] = fdc.us | (fdc.hd << 2) | - // FDCRLT_IC0 | FDCRLT_EN; - //fdcsend_error7(); - break; - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - } - readsector(); - break; - -#ifdef FDC_DELAYERROR7 - case FDCEVENT_BUSY: - break; -#endif - - default: - fdc.event = FDCEVENT_NEUTRAL; - fdc.status &= 0x0f; - fdc.status |= FDCSTAT_RQM; - break; - } -} - -static void FDC_Recalibrate(void) { // cmd: 07 - - switch(fdc.event) { - case FDCEVENT_CMDRECV: - get_hdus(); -// fdc.ncn = 0; -// fdc.R = 1; /* 170107 for Windows95 */ -// fdc.crcn = fdc.R; /* 170107 for Windows95 */ - fdc.int_stat[fdc.us] = /* (fdc.hd << 2) | */ fdc.us; - fdc.int_stat[fdc.us] |= FDCRLT_SE; - if (!(fdc.equip & (1 << fdc.us))) { - fdc.int_stat[fdc.us] |= FDCRLT_IC0; - if (!(fdc.ctrlreg & 0x40)) { - // 強制ReadyでなければNR - fdc.int_stat[fdc.us] |= FDCRLT_NR; - } - else { - // 強制ReadyならばNRは立たないがECが立つ(sector0が見つからないので) - fdc.int_stat[fdc.us] |= FDCRLT_EC; - } - } - else if (!fdd_diskready(fdc.us)) { - // Win95, 98用 - fdc.ncn = 0; - fdc.R = 1; /* 170107 for Windows95 */ - fdc.crcn = fdc.R; /* 170107 for Windows95 */ - if (fdc.ctrlreg & 0x40) { - fdc.treg[fdc.us] = fdc.ncn; - }else{ - fdc.int_stat[fdc.us] |= FDCRLT_NR; - } - } - else { - fdc.ncn = 0; - fdc.treg[fdc.us] = fdc.ncn; - fdc.R = 1; /* 170107 for Windows95 */ - fdc.crcn = fdc.R; /* 170107 for Windows95 */ - /* 170107 for Windows95 form ... */ -// if (fdd_seek()) { -// fdc.stat[fdc.us] |= FDCRLT_IC0; - if (fdd_diskready(fdc.us)) { -#if defined(SUPPORT_SWSEEKSND) - if(np2cfg.MOTOR) fddmtrsnd_play(1, TRUE); -#else - if(np2cfg.MOTOR) soundmng_pcmplay(SOUND_PCMSEEK1, FALSE); -#endif - } -// } - /* 170107 for Windows95 ... to */ - } - fdc.int_timer[fdc.us] = FDC_INT_DELAY; - fdc.status &= 0x0f; - fdc.status |= (1 << fdc.us); - -// fdc_interrupt(); - break; -// default: -// fdc_interrupt(); -// break; - } - fdc.event = FDCEVENT_NEUTRAL; - fdc.status |= FDCSTAT_RQM; - fdc.status &= ~FDCSTAT_CB; -} - -static void FDC_SenceintStatus(void) { // cmd: 08 - - int i; - - fdc.event = FDCEVENT_BUFSEND; - fdc.bufp = 0; - fdc.bufcnt = 0; - fdc.status &= 0x0f; - fdc.status |= FDCSTAT_RQM | FDCSTAT_CB | FDCSTAT_DIO; - - -// if (fdc_isfdcinterrupt()) { -// i = 0; - if (fdc.stat[fdc.us]) { - fdc.buf[0] = (UINT8)fdc.stat[fdc.us]; - fdc.buf[1] = fdc.treg[fdc.us]; - fdc.bufcnt = 2; - fdc.stat[fdc.us] = 0; -// TRACEOUT(("fdc stat - %d [%.2x]", fdc.us, fdc.buf[0])); - } - else { - for (i=0; i<4; i++) { - if (fdc.stat[i]) { - fdc.buf[0] = (UINT8)fdc.stat[i]; - fdc.buf[1] = fdc.treg[i]; - fdc.bufcnt = 2; - fdc.stat[i] = 0; -// TRACEOUT(("fdc stat - %d [%.2x]", i, fdc.buf[0])); - break; - } - } - } -// for (; i<4; i++) { -// if (fdc.stat[i]) { -// break; -// } -// } -// if (i >= 4) { -// fdc_interruptreset(); -// } -// -// } - if (!fdc.bufcnt) { - fdc.buf[0] = FDCRLT_IC1; - fdc.bufcnt = 1; - } - /* 170101 ST modified to work on Windows 9x/2000 form ... */ - else if ((fdc.ctrlreg & 0x08) == 0) { - //fdc.buf[0] |= 0x08; - //fdc.bufcnt = 1; - fdc.ctrlreg |= 0x08; // アクセスされたらモータ回す・・・ np21w ver0.86 rev39 - } - /* 170101 ST modified to work on Windows 9x/2000 ... to */ -} - -static void FDC_ReadID(void) { // cmd: 0a - - switch(fdc.event) { - case FDCEVENT_CMDRECV: - fdc.mf = fdc.cmd & 0x40; - get_hdus(); - if (fdd_readid() == SUCCESS) { - fdcsend_success7(); - //fdc.status = 0x80; // TEST -#if defined(SUPPORT_SWSEEKSND) - if(np2cfg.MOTOR) fddmtrsnd_play(1, TRUE); -#else - if(np2cfg.MOTOR) soundmng_pcmplay(SOUND_PCMSEEK1, FALSE); -#endif - } - else { - fdc.stat[fdc.us] = fdc.us | (fdc.hd << 2) | -// FDCRLT_IC0 | FDCRLT_MA; - FDCRLT_IC0 | FDCRLT_ND; - - fdcsend_error7(); - } - break; - } -} - -static void FDC_WriteID(void) { // cmd: 0d - - switch(fdc.event) { - case FDCEVENT_CMDRECV: -// TRACE_("FDC_WriteID FDCEVENT_CMDRECV", 0); - get_hdus(); - fdc.N = fdc.cmds[1]; - fdc.sc = fdc.cmds[2]; - fdc.gpl = fdc.cmds[3]; - fdc.d = fdc.cmds[4]; - if (FDC_DriveCheck(TRUE)) { -// TRACE_("FDC_WriteID FDC_DriveCheck", 0); - if (fdd_formatinit()) { -// TRACE_("FDC_WriteID fdd_formatinit", 0); - fdcsend_error7(); - break; - } - /* 170107 modified to work on Windows 9x/2000 form ... */ - if (!fdd_isformating()) { - fdc.crcn = 1; - fdcsend_success7(); - break; - } - /* 170107 modified to work on Windows 9x/2000 ... to */ -// TRACE_("FDC_WriteID FDCEVENT_BUFRECV", 0); - fdc.event = FDCEVENT_BUFRECV; - fdc.bufcnt = 4; - fdc.bufp = 0; -#if 1 // ver0.27 ?? - fdc.status &= 0x0f; - fdc.status |= (1 << fdc.us); - fdc.status |= FDCSTAT_RQM | FDCSTAT_CB; - if (fdc.nd) { - fdc.status |= FDCSTAT_NDM; - } -#else - fdc.status = FDCSTAT_RQM | FDCSTAT_NDM | FDCSTAT_CB; -#endif - fdc_dmaready(1); - dmac_check(); - } - break; - - case FDCEVENT_BUFRECV: - if (fdd_formating(fdc.buf)) { - fdcsend_error7(); - break; - } - if ((fdc.tc) || (!fdd_isformating())) { - fdcsend_success7(); - return; - } - fdc.event = FDCEVENT_BUFRECV; - fdc.bufcnt = 4; - fdc.bufp = 0; -#if 1 // ver0.27 ?? - fdc.status &= 0x0f; - fdc.status |= (1 << fdc.us); - fdc.status |= FDCSTAT_RQM | FDCSTAT_CB; - if (fdc.nd) { - fdc.status |= FDCSTAT_NDM; - } -#else - fdc.status = FDCSTAT_RQM | FDCSTAT_NDM | FDCSTAT_CB; -#endif - break; - - default: - fdc.event = FDCEVENT_NEUTRAL; - fdc.status = FDCSTAT_RQM; - break; - } -} - -static void FDC_Seek(void) { // cmd: 0f - - switch(fdc.event) { - case FDCEVENT_CMDRECV: - get_hdus(); -// fdc.ncn = fdc.cmds[1]; -// fdc.treg[fdc.us] = fdc.ncn; -// fdc.R = 1; -// fdc.crcn = fdc.R; /* 170107 for Windows95 */ - /* 170101 ST modified to work on Windows 9x/2000 */ - fdc.int_stat[fdc.us] = /*(fdc.hd << 2) |*/ fdc.us; - fdc.int_stat[fdc.us] |= FDCRLT_SE; - if (!fdd_diskready(fdc.us)) { - fdc.int_stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_NR; - } - else { - UINT8 sdiff = fdc.cmds[1] - fdc.ncn; - fdc.ncn = fdc.cmds[1]; - fdc.treg[fdc.us] = fdc.ncn; - fdc.R = 1; - fdc.crcn = fdc.R; /* 170107 for Windows95 */ - /* 170107 for Windows95 form ... */ - //if (fdd_seek()) { - // fdc.stat[fdc.us] |= FDCRLT_IC0; -#if defined(SUPPORT_SWSEEKSND) - if(np2cfg.MOTOR) fddmtrsnd_play(1, TRUE); -#else - if(np2cfg.MOTOR) { - if(fdc_seeksndtimeout[fdc.us]!=0 && sdiff==1){ - soundmng_pcmplay(SOUND_PCMSEEK, FALSE); - }else{ - soundmng_pcmstop(SOUND_PCMSEEK1); - soundmng_pcmplay(SOUND_PCMSEEK1, FALSE); - } - } -#endif - fdc_seeksndtimeout[fdc.us] = FDC_SEEKSOUND_TIMEOUT; - //} - fdc_lasttreg[fdc.us] = fdc.treg[fdc.us]; - /* 170107 for Windows95 ... to */ - } - fdc.int_timer[fdc.us] = FDC_INT_DELAY; - fdc.status &= 0x0f; - fdc.status |= (1 << fdc.us); -// fdc_interrupt(); - break; - } - fdc.event = FDCEVENT_NEUTRAL; - fdc.status |= FDCSTAT_RQM; - fdc.status &= ~FDCSTAT_CB; -} - -#ifdef SUPPORT_KAI_IMAGES -static void FDC_ScanEqual(void) { // cmd: 11, 19, 1d - - switch(fdc.event) { - case FDCEVENT_CMDRECV: - get_hdus(); - get_chrn(); - fdc.eot = fdc.cmds[5]; - fdc.gpl = fdc.cmds[6]; - fdc.stp = fdc.cmds[7]; - break; - } -} -#endif - -// -------------------------------------------------------------------------- - -typedef void (*FDCOPE)(void); - -static const FDCOPE FDC_Ope[0x20] = { - FDC_Invalid, - FDC_Invalid, - FDC_ReadData, // FDC_ReadDiagnostic, - FDC_Specify, - FDC_SenseDeviceStatus, - FDC_WriteData, - FDC_ReadData, - FDC_Recalibrate, - FDC_SenceintStatus, - FDC_WriteData, - FDC_ReadID, - FDC_Invalid, - FDC_ReadData, - FDC_WriteID, - FDC_Invalid, - FDC_Seek, - FDC_Invalid, // 10 -#ifdef SUPPORT_KAI_IMAGES - FDC_ScanEqual, -#else - FDC_Invalid, // FDC_ScanEqual, -#endif - FDC_Invalid, - FDC_Invalid, - FDC_Invalid, - FDC_Invalid, - FDC_Invalid, - FDC_Invalid, - FDC_Invalid, -#ifdef SUPPORT_KAI_IMAGES - FDC_ScanEqual, -#else - FDC_Invalid, // FDC_ScanEqual, -#endif - FDC_Invalid, - FDC_Invalid, - FDC_Invalid, -#ifdef SUPPORT_KAI_IMAGES - FDC_ScanEqual, -#else - FDC_Invalid, // FDC_ScanEqual, -#endif - FDC_Invalid, - FDC_Invalid}; - - -// -------------------------------------------------------------------------- - -static void fdcstatusreset(void) { - - fdc.event = FDCEVENT_NEUTRAL; - fdc.status = FDCSTAT_RQM; -} - -void DMACCALL fdc_datawrite(REG8 data) { - -// if ((fdc.status & (FDCSTAT_RQM | FDCSTAT_DIO)) == FDCSTAT_RQM) { - switch(fdc.event) { - case FDCEVENT_BUFRECV: -// TRACE_("write", fdc.bufp); - fdc.buf[fdc.bufp++] = data; - if ((!(--fdc.bufcnt)) || (fdc.tc)) { - fdc.status &= ~FDCSTAT_RQM; - FDC_Ope[fdc.cmd & 0x1f](); - } - break; - - case FDCEVENT_CMDRECV: - fdc.cmds[fdc.cmdp++] = data; - if (!(--fdc.cmdcnt)) { - fdc.status &= ~FDCSTAT_RQM; - FDC_Ope[fdc.cmd & 0x1f](); - } - break; - - default: - fdc.cmd = data; - get_mtmfsk(); - fdc.status |= FDCSTAT_CB; // コマンド受けたらCBをセット - if (FDCCMD_TABLE[data & 0x1f]) { - fdc.event = FDCEVENT_CMDRECV; - fdc.cmdp = 0; - fdc.cmdcnt = FDCCMD_TABLE[data & 0x1f]; - fdc.status |= FDCSTAT_RQM; - } - else { - fdc.status &= ~FDCSTAT_RQM; - FDC_Ope[fdc.cmd & 0x1f](); - } - break; - } -// } -} - -REG8 DMACCALL fdc_dataread(void) { - - int i; - -// if ((fdc.status & (FDCSTAT_RQM | FDCSTAT_DIO)) -// == (FDCSTAT_RQM | FDCSTAT_DIO)) { - switch(fdc.event) { - case FDCEVENT_BUFSEND: - fdc.lastdata = fdc.buf[fdc.bufp++]; - if (!(--fdc.bufcnt)) { - fdc.event = FDCEVENT_NEUTRAL; - fdc.status &= ~(1 << fdc.us); - fdc.status &= ~(FDCSTAT_DIO | FDCSTAT_CB); - fdc.status |= FDCSTAT_RQM; - } - // 割り込みクリア処理 - for (i = 0; i < 4; i++) { - if (fdc.stat[i]) { - break; - } - } - if (i >= 4) { - fdc_interruptreset(); - } - break; - - case FDCEVENT_BUFSEND2: - if (fdc.bufcnt) { - fdc.lastdata = fdc.buf[fdc.bufp++]; - fdc.bufcnt--; - } - if (fdc.tc) { - if (!fdc.bufcnt) { // ver0.26 - fdc.R++; - if ((fdc.cmd & 0x80) && fdd_seeksector()) { - fdc.C += fdc.hd; - fdc.H = fdc.hd ^ 1; - fdc.R = 1; - } - } - /* 170101 ST modified to work on Windows 9x/2000 */ - fdc.R = 1; - fdcsend_success7(); - } - if (!fdc.bufcnt) { - fdc.event = FDCEVENT_NEXTDATA; - fdc.status &= ~(FDCSTAT_RQM | FDCSTAT_NDM); - FDC_Ope[fdc.cmd & 0x1f](); - } - break; - } -// } - return(fdc.lastdata); -} - -/* SEEKとRECALIBRATEの割り込み通知処理 */ -void fdc_intdelay(void) { - - int i; - - for (i = 0; i < 4; i++) { - if (fdc.int_timer[i]) { - fdc.int_timer[i]--; - if (!fdc.int_timer[i]) { - fdc.stat[i] = fdc.int_stat[i]; - fdc_interrupt(); - } - } - if(fdc_seeksndtimeout[i] > 0) fdc_seeksndtimeout[i]--; - } -} - -// ---- I/O - -static void IOOUTCALL fdc_o92(UINT port, REG8 dat) { - - TRACEOUT(("fdc out %.2x %.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); - - if (((port >> 4) ^ fdc.chgreg) & 1) { - return; - } -// /* 170101 ST modified to work on Windows 9x/2000 form ... */ -// if (fdc.status & FDCSTAT_DIO) { -// fdc.status &= ~FDCSTAT_DIO; -// fdc.status |= FDCSTAT_RQM; -// } -// /* 170101 ST modified to work on Windows 9x/2000 ... to */ - - if ((fdc.status & (FDCSTAT_RQM | FDCSTAT_DIO)) == FDCSTAT_RQM) { - fdc_datawrite(dat); - } -} - -static void IOOUTCALL fdc_o94(UINT port, REG8 dat) { - - UINT8 i; - - TRACEOUT(("fdc out %.2x %.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); - - if (((port >> 4) ^ fdc.chgreg) & 1) { - return; - } - if ((fdc.ctrlreg ^ dat) & 0x10) { - fdcstatusreset(); - fdc_dmaready(0); - dmac_check(); - } - /* 170101 ST modified to work on Windows 9x/2000 form ... */ - if ((fdc.ctrlreg ^ dat) & 0x80) { - if (dat & 0x80) { - fdcstatusreset(); - - if(dat & 0x08){ // XXX: Workaround for OSASK - // FDCリセット後 1,024ms以内にINTがアクティブになる - for (i = 0; i < 4; i++) { - fdc.int_stat[i] = fdc.stat[i]; - fdc.int_timer[i] = FDC_INT_DELAY; - } - } - } - } - if (fdc.chgreg & 4) { - if ((fdc.ctrlreg ^ dat) & 0x08) { - if (dat & 0x08) { - for (i = 0; i < 4; i++) { - if (fdd_diskready(i)) { - fdc.int_stat[i] = FDCRLT_AI | i; - fdc.int_timer[i] = FDC_INT_DELAY; - fdc.status |= (1 << i); - } - } - } - } - } - /* 170101 ST modified to work on Windows 9x/2000 ... to */ - fdc.ctrlreg = dat; -} - -static REG8 IOINPCALL fdc_i90(UINT port) { - - TRACEOUT(("fdc in %.2x %.2x [%.4x:%.4x]", port, fdc.status, - CPU_CS, CPU_IP)); - - if (((port >> 4) ^ fdc.chgreg) & 1) { - return(0xff); - } - return(fdc.status); -} - -static REG8 IOINPCALL fdc_i92(UINT port) { - - REG8 ret; - - if (((port >> 4) ^ fdc.chgreg) & 1) { - return(0xff); - } - if ((fdc.status & (FDCSTAT_RQM | FDCSTAT_DIO)) - == (FDCSTAT_RQM | FDCSTAT_DIO)) { - ret = fdc_dataread(); - } - else { - ret = fdc.lastdata; - } - TRACEOUT(("fdc in %.2x %.2x [%.4x:%.4x]", port, ret, CPU_CS, CPU_IP)); - return(ret); -} - -static REG8 IOINPCALL fdc_i94(UINT port) { - - REG8 ret; - - if (((port >> 4) ^ fdc.chgreg) & 1) { - return(0xff); - } - - ret = 0x40; - if (!(port & 0x10)) /* CC */ - { - ret |= 0x20; /* DMA */ - ret |= 0x10; /* readyを立てるるる */ - } - - if (pccore.dipsw[0] & 8) - { - ret |= 0x04; /* 内蔵優先 */ - } - else - { - ret |= 0x08; /* 外付け優先 */ - } - TRACEOUT(("fdc in %.2x %.2x [%.4x:%.4x]", port, ret, - CPU_CS, CPU_IP)); - - return ret; -} - - -static void IOOUTCALL fdc_obe(UINT port, REG8 dat) { - - TRACEOUT(("fdc out %.2x %.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); - - fdc.chgreg = dat; - if (fdc.chgreg & 2) { - CTRL_FDMEDIA = DISKTYPE_2HD; - } - else { - CTRL_FDMEDIA = DISKTYPE_2DD; - } - (void)port; -} - -static REG8 IOINPCALL fdc_ibe(UINT port) { - - (void)port; - TRACEOUT(("fdc in %.2x %.2x [%.4x:%.4x]", port, ((fdc.chgreg & 3) | 8), - CPU_CS, CPU_IP)); - - return((fdc.chgreg & 3) | 8 | 0xf0); -} - -static void IOOUTCALL fdc_o4be(UINT port, REG8 dat) { - - TRACEOUT(("fdc out %.2x %.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); - - fdc.reg144 = dat; - if (dat & 0x10) { - fdc.rpm[(dat >> 5) & 3] = dat & 1; - } - (void)port; -} - -static REG8 IOINPCALL fdc_i4be(UINT port) { - - (void)port; - TRACEOUT(("fdc in %.2x %.2x [%.4x:%.4x]", port, (fdc.rpm[(fdc.reg144 >> 5) & 3] | 0xf0), - CPU_CS, CPU_IP)); - return(fdc.rpm[(fdc.reg144 >> 5) & 3] | 0xfe); -} - - -// ---- I/F - -static const IOOUT fdco90[4] = { - NULL, fdc_o92, fdc_o94, NULL}; -static const IOINP fdci90[4] = { - fdc_i90, fdc_i92, fdc_i94, NULL}; -static const IOOUT fdcobe[1] = {fdc_obe}; -static const IOINP fdcibe[1] = {fdc_ibe}; - -void fdc_reset(const NP2CFG *pConfig) { - - ZeroMemory(&fdc, sizeof(fdc)); - fdc.equip = pConfig->fddequip; -#if defined(SUPPORT_PC9821) - fdc.support144 = 1; -#else - fdc.support144 = pConfig->usefd144; -#endif - fdcstatusreset(); - dmac_attach(DMADEV_2HD, FDC_DMACH2HD); - dmac_attach(DMADEV_2DD, FDC_DMACH2DD); - CTRL_FDMEDIA = DISKTYPE_2HD; - fdc.chgreg = 3; -} - -void fdc_bind(void) { - - iocore_attachcmnoutex(0x0090, 0x00f9, fdco90, 4); - iocore_attachcmninpex(0x0090, 0x00f9, fdci90, 4); - iocore_attachcmnoutex(0x00c8, 0x00f9, fdco90, 4); - iocore_attachcmninpex(0x00c8, 0x00f9, fdci90, 4); - - if (fdc.support144) { - iocore_attachout(0x04be, fdc_o4be); - iocore_attachinp(0x04be, fdc_i4be); - } - iocore_attachsysoutex(0x00be, 0x0cff, fdcobe, 1); - iocore_attachsysinpex(0x00be, 0x0cff, fdcibe, 1); -} - +// +// FDC μPD765A +// + +#include +#include +#include +#include +#include +#if defined(SUPPORT_SWSEEKSND) +#include +#include +#endif +#include + +#if 1 +#undef TRACEOUT +#define TRACEOUT(s) (void)(s) +#endif /* 0 */ + +static int fdc_lasttreg[4] = {0}; // 暫定:Win用 Seek後にはtregをfdc.Cで更新 本当はfdc構造体の中に入れるべき + +extern void fddmtrsnd_play(UINT num, BOOL play); + +enum { + FDC_DMACH2HD = 2, + FDC_DMACH2DD = 3 +}; + +static const UINT8 FDCCMD_TABLE[32] = { + 0, 0, 8, 2, 1, 8, 8, 1, 0, 8, 1, 0, 8, 5, 0, 2, + 0, 8, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0}; + + +#define FDC_FORCEREADY (1) +#define FDC_DELAYERROR7 + +#define FDC_INT_DELAY 6 /*!< Delay 100ms */ +#define FDC_SEEKSOUND_TIMEOUT 60 /*!< Timeout 1000ms */ + +static int fdc_seeksndtimeout[4] = {0}; + +void fdc_intwait(NEVENTITEM item) { + + if (item->flag & NEVENT_SETEVENT) { + fdc.intreq = TRUE; + if (fdc.chgreg & 1) { + pic_setirq(0x0b); + } + else { + pic_setirq(0x0a); + } + } +} + +void fdc_interrupt(void) { + + nevent_set(NEVENT_FDCINT, 512, fdc_intwait, NEVENT_ABSOLUTE); +} + +static void fdc_interruptreset(void) { + + fdc.intreq = FALSE; +} + +static BOOL fdc_isfdcinterrupt(void) { + + return(fdc.intreq); +} + +REG8 DMACCALL fdc_dmafunc(REG8 func) { + +// TRACEOUT(("fdc_dmafunc = %d", func)); + switch(func) { + case DMAEXT_START: + return(1); + + case DMAEXT_END: // TC + fdc.tc = 1; + break; + } + return(0); +} + +static void fdc_dmaready(REG8 enable) { + + if (fdc.chgreg & 1) { + dmac.dmach[FDC_DMACH2HD].ready = enable; + } + else { + dmac.dmach[FDC_DMACH2DD].ready = enable; + } +} + + +// ---------------------------------------------------------------------- + +void fdcsend_error7(void) { + + fdc.tc = 0; + fdc.event = FDCEVENT_BUFSEND; + fdc.bufp = 0; + fdc.bufcnt = 7; + fdc.buf[0] = (UINT8)(fdc.stat[fdc.us] >> 0); + fdc.buf[1] = (UINT8)(fdc.stat[fdc.us] >> 8); + fdc.buf[2] = (UINT8)(fdc.stat[fdc.us] >> 16); + fdc.buf[3] = fdc.C; + fdc.buf[4] = fdc.H; + fdc.buf[5] = fdc.R; + fdc.buf[6] = fdc.N; + fdc.status &= 0x0f; + fdc.status |= (1 << fdc.us); + fdc.status |= FDCSTAT_RQM | FDCSTAT_CB | FDCSTAT_DIO; + fdc.stat[fdc.us] = 0; // ver0.29 + fdc_dmaready(0); + dmac_check(); + fdc_interrupt(); +} + +void fdcsend_success7(void) { + + fdc.tc = 0; + fdc.event = FDCEVENT_BUFSEND; + fdc.bufp = 0; + fdc.bufcnt = 7; +#ifdef SUPPORT_KAI_IMAGES + if (fdd_fdcresult() == FALSE) { + fdc.buf[0] = (fdc.hd << 2) | fdc.us; + fdc.buf[1] = 0; + fdc.buf[2] = 0; + } + else { + // FDイメージファイルがFDCリザルトコードを持っている場合は + // (fdc.statに設定しているはずなので)そちらを設定 + fdc.buf[0] = (fdc.hd << 2) | fdc.us | (UINT8)(fdc.stat[fdc.us] >> 0); + fdc.buf[1] = (UINT8)(fdc.stat[fdc.us] >> 8); + fdc.buf[2] = (UINT8)(fdc.stat[fdc.us] >> 16); + } +#else + fdc.buf[0] = (fdc.hd << 2) | fdc.us; + fdc.buf[1] = 0; + fdc.buf[2] = 0; +#endif + fdc.buf[3] = fdc.C; + fdc.buf[4] = fdc.H; + fdc.buf[5] = fdc.R; + fdc.buf[6] = fdc.N; + fdc.status &= 0x0f; + fdc.status |= (1 << fdc.us); + fdc.status |= FDCSTAT_RQM | FDCSTAT_CB | FDCSTAT_DIO; + fdc.stat[fdc.us] = 0; // ver0.29 + fdc_dmaready(0); + dmac_check(); + fdc_interrupt(); +} + +#if 0 +// FDCのタイムアウト まぁ本当はこんなんじゃダメだけど… ver0.29 +void fdctimeoutproc(NEVENTITEM item) { + + if (item->flag & NEVENT_SETEVENT) { + fdc.stat[fdc.us] = FDCRLT_IC0 | FDCRLT_EN | (fdc.hd << 2) | fdc.us; + fdcsend_error7(); + } +} + +static void fdc_timeoutset(void) { + + nevent_setbyms(NEVENT_FDCTIMEOUT, 166, fdctimeoutproc, NEVENT_ABSOLUTE); +} +#endif + + + +static BOOL FDC_DriveCheck(BOOL protectcheck) { + +// if (!fddfile[fdc.us].fname[0]) { + if (!fdd_diskready(fdc.us)) { + fdc.stat[fdc.us] = FDCRLT_IC0 | FDCRLT_NR | (fdc.hd << 2) | fdc.us; + fdcsend_error7(); + return(FALSE); + } +// else if ((protectcheck) && (fddfile[fdc.us].protect)) { + else if ((protectcheck) && fdd_diskprotect(fdc.us)) { + fdc.stat[fdc.us] = FDCRLT_IC0 | FDCRLT_NW | (fdc.hd << 2) | fdc.us; + fdcsend_error7(); + return(FALSE); + } + return(TRUE); +} + +// ---------------------------------------------------------------------- + +static void get_mtmfsk(void) { + + fdc.mt = (fdc.cmd >> 7) & 1; + fdc.mf = fdc.cmd & 0x40; // ver0.29 + fdc.sk = (fdc.cmd >> 5) & 1; +} + +static void get_hdus(void) { + + fdc.hd = (fdc.cmds[0] >> 2) & 1; + fdc.us = fdc.cmds[0] & 3; +} + +static void get_chrn(void) { + + fdc.C = fdc.cmds[1]; + fdc.H = fdc.cmds[2]; + fdc.R = fdc.cmds[3]; + fdc.N = fdc.cmds[4]; +} + +static void get_eotgsldtl(void) { + + fdc.eot = fdc.cmds[5]; + fdc.gpl = fdc.cmds[6]; + fdc.dtl = fdc.cmds[7]; +} + +// -------------------------------------------------------------------------- + +static void FDC_Invalid(void) { // cmd: xx + + fdc.event = FDCEVENT_BUFSEND; + fdc.bufcnt = 1; + fdc.bufp = 0; + fdc.buf[0] = 0x80; + fdc.status &= 0x0f; + fdc.status |= FDCSTAT_RQM | FDCSTAT_CB | FDCSTAT_DIO; +} + +#ifdef SUPPORT_KAI_IMAGES +static void FDC_ReadDiagnostic(void) { // cmd: 02 + + switch(fdc.event) { + case FDCEVENT_CMDRECV: + get_hdus(); + get_chrn(); + get_eotgsldtl(); + fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; + + if (FDC_DriveCheck(FALSE)) { + fdc.event = FDCEVENT_BUFSEND; +// fdc.bufcnt = makedianosedata(); + fdc.bufp = 0; + } + break; + + default: + fdc.event = FDCEVENT_NEUTRAL; + break; + } +} +#endif + +static void FDC_Specify(void) { // cmd: 03 + + switch(fdc.event) { + case FDCEVENT_CMDRECV: + fdc.srt = fdc.cmds[0] >> 4; + fdc.hut = fdc.cmds[0] & 0x0f; + fdc.hlt = fdc.cmds[1] >> 1; + fdc.nd = fdc.cmds[1] & 1; + fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; + break; + } + fdc.event = FDCEVENT_NEUTRAL; + fdc.status &= 0x0f; + fdc.status |= FDCSTAT_RQM; +} + +static void FDC_SenseDeviceStatus(void) { // cmd: 04 + + switch (fdc.event) { + case FDCEVENT_CMDRECV: + get_hdus(); + fdc.buf[0] = (fdc.hd << 2) | fdc.us; + fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; + if (fdc.equip & (1 << fdc.us)) { + fdc.buf[0] |= 0x08; + if (!fdc.treg[fdc.us]) { + fdc.buf[0] |= 0x10; + } + if (fdd_diskready(fdc.us) || (fdc.ctrlreg & 0x40)) {/* 170107 念のため */ + fdc.buf[0] |= 0x20; + } + if (fddfile[fdc.us].protect) { + fdc.buf[0] |= 0x40; + } + } + else { + fdc.buf[0] |= 0x80; + } +// TRACEOUT(("FDC_SenseDeviceStatus %.2x", fdc.buf[0])); + fdc.event = FDCEVENT_BUFSEND; + fdc.bufcnt = 1; + fdc.bufp = 0; + fdc.status &= 0x0f; + fdc.status |= (1 << fdc.us); + fdc.status |= FDCSTAT_RQM | FDCSTAT_CB | FDCSTAT_DIO; + break; + + default: + fdc.event = FDCEVENT_NEUTRAL; + fdc.status &= 0x0f; + fdc.status |= FDCSTAT_RQM; + break; + } +} + +static BRESULT writesector(void) { + + fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; + if (!FDC_DriveCheck(TRUE)) { + return(FAILURE); + } + if (fdd_write()) { + fdc.stat[fdc.us] = fdc.us | (fdc.hd << 2) | FDCRLT_IC0 | FDCRLT_ND; + fdcsend_error7(); + return(FAILURE); + } + fdc.event = FDCEVENT_BUFRECV; + fdc.bufcnt = 128 << fdc.N; + fdc.bufp = 0; +// fdc.status = FDCSTAT_RQM | FDCSTAT_NDM | FDCSTAT_CB; +#if defined(SUPPORT_SWSEEKSND) + if(np2cfg.MOTOR) fddmtrsnd_play(1, TRUE); +#else + if(np2cfg.MOTOR) { + if(fdc_seeksndtimeout[fdc.us]!=0){ + soundmng_pcmplay(SOUND_PCMSEEK, FALSE); + }else{ + soundmng_pcmstop(SOUND_PCMSEEK1); + soundmng_pcmplay(SOUND_PCMSEEK1, FALSE); + } + } +#endif + fdc_seeksndtimeout[fdc.us] = FDC_SEEKSOUND_TIMEOUT; + fdc_dmaready(1); + dmac_check(); + return(SUCCESS); +} + +static void FDC_WriteData(void) { // cmd: 05 + // cmd: 09 + switch(fdc.event) { + case FDCEVENT_CMDRECV: + get_hdus(); + get_chrn(); + get_eotgsldtl(); + fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; + if(fdc_lasttreg[fdc.us] != fdc.treg[fdc.us]){ + fdc.treg[fdc.us] = fdc.C; /* 170101 ST modified to work on Windows 9x/2000 */ + } + if (FDC_DriveCheck(TRUE)) { + fdc.event = FDCEVENT_BUFRECV; + fdc.bufcnt = 128 << fdc.N; + fdc.bufp = 0; +#if 1 // ver0.27 ?? + fdc.status &= 0x0f; + fdc.status |= (1 << fdc.us); + fdc.status |= FDCSTAT_RQM | FDCSTAT_CB; + if (fdc.nd) { + fdc.status |= FDCSTAT_NDM; + } +#else + fdc.status = FDCSTAT_RQM | FDCSTAT_NDM | FDCSTAT_CB; +#endif + fdc_dmaready(1); + dmac_check(); + } + break; + + case FDCEVENT_BUFRECV: + if (writesector()) { + return; + } + /* 170101 ST modified to work on Windows 9x/2000 form ... */ + //if (fdc.tc) { + // fdcsend_success7(); + // return; + //} + if ((fdc.tc) || (fdc.R++ == fdc.eot)) { + fdc.R = 1; + if (fdc.mt) { + fdc.hd ^= 1; + fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; + fdc.H ^= 1; + if (fdc.tc || !fdc.H) { + fdc.C++; + fdcsend_success7(); + break; + } + } + else { + fdc.C++; + fdcsend_success7(); + } + //fdc.stat[fdc.us] = fdc.us | (fdc.hd << 2) | + // FDCRLT_IC0 | FDCRLT_EN; + //fdcsend_error7(); + break; + } + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + break; + + default: + fdc.event = FDCEVENT_NEUTRAL; + fdc.status &= 0x0f; + fdc.status |= FDCSTAT_RQM; + break; + } +} + +static void readsector(void) { + + fdc.stat[fdc.us] = (fdc.hd << 2) | fdc.us; + if (!FDC_DriveCheck(FALSE)) { + return; + } + if (fdd_read()) { + fdc.stat[fdc.us] = fdc.us | (fdc.hd << 2) | FDCRLT_IC0 | FDCRLT_ND; + fdcsend_error7(); + return; + } +#if defined(SUPPORT_SWSEEKSND) + if(np2cfg.MOTOR) fddmtrsnd_play(1, TRUE); +#else + if(np2cfg.MOTOR) { + if(fdc_seeksndtimeout[fdc.us]!=0){ + soundmng_pcmplay(SOUND_PCMSEEK, FALSE); + }else{ + soundmng_pcmstop(SOUND_PCMSEEK1); + soundmng_pcmplay(SOUND_PCMSEEK1, FALSE); + } + } +#endif + fdc_seeksndtimeout[fdc.us] = FDC_SEEKSOUND_TIMEOUT; + + fdc.event = FDCEVENT_BUFSEND2; + fdc.bufp = 0; +#if 0 // ver0.27 ?? + fdc.status = FDCSTAT_NDM | FDCSTAT_CB; + if (!(fdc.ctrlreg & 0x10)) { + fdc.status |= FDCSTAT_RQM | FDCSTAT_DIO; + } +#else + fdc.status &= 0x0f; + fdc.status |= (1 << fdc.us); + fdc.status |= FDCSTAT_RQM | FDCSTAT_DIO | FDCSTAT_CB; + if (fdc.nd) { + fdc.status |= FDCSTAT_NDM; + } +#endif + fdc_dmaready(1); + dmac_check(); +} + +static void FDC_ReadData(void) { // cmd: 06 + // cmd: 0c + switch(fdc.event) { + case FDCEVENT_CMDRECV: + get_hdus(); + get_chrn(); + get_eotgsldtl(); + if(fdc_lasttreg[fdc.us] != fdc.treg[fdc.us]){ + fdc.treg[fdc.us] = fdc.C; /* 170101 ST modified to work on Windows 9x/2000 */ + } + readsector(); + break; + + case FDCEVENT_NEXTDATA: + fdc.bufcnt = 0; + if (fdc.R++ == fdc.eot) { + /* 170101 ST modified to work on Windows 9x/2000 form ... */ + fdc.R = 1; + if (fdc.mt) { + fdc.hd ^= 1; + fdc.H ^= 1; + if (fdc.H) { + readsector(); + break; + } + } + fdc.C++; + fdcsend_success7(); + //fdc.stat[fdc.us] = fdc.us | (fdc.hd << 2) | + // FDCRLT_IC0 | FDCRLT_EN; + //fdcsend_error7(); + break; + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + } + readsector(); + break; + +#ifdef FDC_DELAYERROR7 + case FDCEVENT_BUSY: + break; +#endif + + default: + fdc.event = FDCEVENT_NEUTRAL; + fdc.status &= 0x0f; + fdc.status |= FDCSTAT_RQM; + break; + } +} + +static void FDC_Recalibrate(void) { // cmd: 07 + + switch(fdc.event) { + case FDCEVENT_CMDRECV: + get_hdus(); +// fdc.ncn = 0; +// fdc.R = 1; /* 170107 for Windows95 */ +// fdc.crcn = fdc.R; /* 170107 for Windows95 */ + fdc.int_stat[fdc.us] = /* (fdc.hd << 2) | */ fdc.us; + fdc.int_stat[fdc.us] |= FDCRLT_SE; + if (!(fdc.equip & (1 << fdc.us))) { + fdc.int_stat[fdc.us] |= FDCRLT_IC0; + if (!(fdc.ctrlreg & 0x40)) { + // 強制ReadyでなければNR + fdc.int_stat[fdc.us] |= FDCRLT_NR; + } + else { + // 強制ReadyならばNRは立たないがECが立つ(sector0が見つからないので) + fdc.int_stat[fdc.us] |= FDCRLT_EC; + } + } + else if (!fdd_diskready(fdc.us)) { + // Win95, 98用 + fdc.ncn = 0; + fdc.R = 1; /* 170107 for Windows95 */ + fdc.crcn = fdc.R; /* 170107 for Windows95 */ + if (fdc.ctrlreg & 0x40) { + fdc.treg[fdc.us] = fdc.ncn; + }else{ + fdc.int_stat[fdc.us] |= FDCRLT_NR; + } + } + else { + fdc.ncn = 0; + fdc.treg[fdc.us] = fdc.ncn; + fdc.R = 1; /* 170107 for Windows95 */ + fdc.crcn = fdc.R; /* 170107 for Windows95 */ + /* 170107 for Windows95 form ... */ +// if (fdd_seek()) { +// fdc.stat[fdc.us] |= FDCRLT_IC0; + if (fdd_diskready(fdc.us)) { +#if defined(SUPPORT_SWSEEKSND) + if(np2cfg.MOTOR) fddmtrsnd_play(1, TRUE); +#else + if(np2cfg.MOTOR) soundmng_pcmplay(SOUND_PCMSEEK1, FALSE); +#endif + } +// } + /* 170107 for Windows95 ... to */ + } + fdc.int_timer[fdc.us] = FDC_INT_DELAY; + fdc.status &= 0x0f; + fdc.status |= (1 << fdc.us); + +// fdc_interrupt(); + break; +// default: +// fdc_interrupt(); +// break; + } + fdc.event = FDCEVENT_NEUTRAL; + fdc.status |= FDCSTAT_RQM; + fdc.status &= ~FDCSTAT_CB; +} + +static void FDC_SenceintStatus(void) { // cmd: 08 + + int i; + + fdc.event = FDCEVENT_BUFSEND; + fdc.bufp = 0; + fdc.bufcnt = 0; + fdc.status &= 0x0f; + fdc.status |= FDCSTAT_RQM | FDCSTAT_CB | FDCSTAT_DIO; + + +// if (fdc_isfdcinterrupt()) { +// i = 0; + if (fdc.stat[fdc.us]) { + fdc.buf[0] = (UINT8)fdc.stat[fdc.us]; + fdc.buf[1] = fdc.treg[fdc.us]; + fdc.bufcnt = 2; + fdc.stat[fdc.us] = 0; +// TRACEOUT(("fdc stat - %d [%.2x]", fdc.us, fdc.buf[0])); + } + else { + for (i=0; i<4; i++) { + if (fdc.stat[i]) { + fdc.buf[0] = (UINT8)fdc.stat[i]; + fdc.buf[1] = fdc.treg[i]; + fdc.bufcnt = 2; + fdc.stat[i] = 0; +// TRACEOUT(("fdc stat - %d [%.2x]", i, fdc.buf[0])); + break; + } + } + } +// for (; i<4; i++) { +// if (fdc.stat[i]) { +// break; +// } +// } +// if (i >= 4) { +// fdc_interruptreset(); +// } +// +// } + if (!fdc.bufcnt) { + fdc.buf[0] = FDCRLT_IC1; + fdc.bufcnt = 1; + } + /* 170101 ST modified to work on Windows 9x/2000 form ... */ + else if ((fdc.ctrlreg & 0x08) == 0) { + //fdc.buf[0] |= 0x08; + //fdc.bufcnt = 1; + fdc.ctrlreg |= 0x08; // アクセスされたらモータ回す・・・ np21w ver0.86 rev39 + } + /* 170101 ST modified to work on Windows 9x/2000 ... to */ +} + +static void FDC_ReadID(void) { // cmd: 0a + + switch(fdc.event) { + case FDCEVENT_CMDRECV: + fdc.mf = fdc.cmd & 0x40; + get_hdus(); + if (fdd_readid() == SUCCESS) { + fdcsend_success7(); + //fdc.status = 0x80; // TEST +#if defined(SUPPORT_SWSEEKSND) + if(np2cfg.MOTOR) fddmtrsnd_play(1, TRUE); +#else + if(np2cfg.MOTOR) soundmng_pcmplay(SOUND_PCMSEEK1, FALSE); +#endif + } + else { + fdc.stat[fdc.us] = fdc.us | (fdc.hd << 2) | +// FDCRLT_IC0 | FDCRLT_MA; + FDCRLT_IC0 | FDCRLT_ND; + + fdcsend_error7(); + } + break; + } +} + +static void FDC_WriteID(void) { // cmd: 0d + + switch(fdc.event) { + case FDCEVENT_CMDRECV: +// TRACE_("FDC_WriteID FDCEVENT_CMDRECV", 0); + get_hdus(); + fdc.N = fdc.cmds[1]; + fdc.sc = fdc.cmds[2]; + fdc.gpl = fdc.cmds[3]; + fdc.d = fdc.cmds[4]; + if (FDC_DriveCheck(TRUE)) { +// TRACE_("FDC_WriteID FDC_DriveCheck", 0); + if (fdd_formatinit()) { +// TRACE_("FDC_WriteID fdd_formatinit", 0); + fdcsend_error7(); + break; + } + /* 170107 modified to work on Windows 9x/2000 form ... */ + if (!fdd_isformating()) { + fdc.crcn = 1; + fdcsend_success7(); + break; + } + /* 170107 modified to work on Windows 9x/2000 ... to */ +// TRACE_("FDC_WriteID FDCEVENT_BUFRECV", 0); + fdc.event = FDCEVENT_BUFRECV; + fdc.bufcnt = 4; + fdc.bufp = 0; +#if 1 // ver0.27 ?? + fdc.status &= 0x0f; + fdc.status |= (1 << fdc.us); + fdc.status |= FDCSTAT_RQM | FDCSTAT_CB; + if (fdc.nd) { + fdc.status |= FDCSTAT_NDM; + } +#else + fdc.status = FDCSTAT_RQM | FDCSTAT_NDM | FDCSTAT_CB; +#endif + fdc_dmaready(1); + dmac_check(); + } + break; + + case FDCEVENT_BUFRECV: + if (fdd_formating(fdc.buf)) { + fdcsend_error7(); + break; + } + if ((fdc.tc) || (!fdd_isformating())) { + fdcsend_success7(); + return; + } + fdc.event = FDCEVENT_BUFRECV; + fdc.bufcnt = 4; + fdc.bufp = 0; +#if 1 // ver0.27 ?? + fdc.status &= 0x0f; + fdc.status |= (1 << fdc.us); + fdc.status |= FDCSTAT_RQM | FDCSTAT_CB; + if (fdc.nd) { + fdc.status |= FDCSTAT_NDM; + } +#else + fdc.status = FDCSTAT_RQM | FDCSTAT_NDM | FDCSTAT_CB; +#endif + break; + + default: + fdc.event = FDCEVENT_NEUTRAL; + fdc.status = FDCSTAT_RQM; + break; + } +} + +static void FDC_Seek(void) { // cmd: 0f + + switch(fdc.event) { + case FDCEVENT_CMDRECV: + get_hdus(); +// fdc.ncn = fdc.cmds[1]; +// fdc.treg[fdc.us] = fdc.ncn; +// fdc.R = 1; +// fdc.crcn = fdc.R; /* 170107 for Windows95 */ + /* 170101 ST modified to work on Windows 9x/2000 */ + fdc.int_stat[fdc.us] = /*(fdc.hd << 2) |*/ fdc.us; + fdc.int_stat[fdc.us] |= FDCRLT_SE; + if (!fdd_diskready(fdc.us)) { + fdc.int_stat[fdc.us] |= FDCRLT_IC0 | FDCRLT_NR; + } + else { + UINT8 sdiff = fdc.cmds[1] - fdc.ncn; + fdc.ncn = fdc.cmds[1]; + fdc.treg[fdc.us] = fdc.ncn; + fdc.R = 1; + fdc.crcn = fdc.R; /* 170107 for Windows95 */ + /* 170107 for Windows95 form ... */ + //if (fdd_seek()) { + // fdc.stat[fdc.us] |= FDCRLT_IC0; +#if defined(SUPPORT_SWSEEKSND) + if(np2cfg.MOTOR) fddmtrsnd_play(1, TRUE); +#else + if(np2cfg.MOTOR) { + if(fdc_seeksndtimeout[fdc.us]!=0 && sdiff==1){ + soundmng_pcmplay(SOUND_PCMSEEK, FALSE); + }else{ + soundmng_pcmstop(SOUND_PCMSEEK1); + soundmng_pcmplay(SOUND_PCMSEEK1, FALSE); + } + } +#endif + fdc_seeksndtimeout[fdc.us] = FDC_SEEKSOUND_TIMEOUT; + //} + fdc_lasttreg[fdc.us] = fdc.treg[fdc.us]; + /* 170107 for Windows95 ... to */ + } + fdc.int_timer[fdc.us] = FDC_INT_DELAY; + fdc.status &= 0x0f; + fdc.status |= (1 << fdc.us); +// fdc_interrupt(); + break; + } + fdc.event = FDCEVENT_NEUTRAL; + fdc.status |= FDCSTAT_RQM; + fdc.status &= ~FDCSTAT_CB; +} + +#ifdef SUPPORT_KAI_IMAGES +static void FDC_ScanEqual(void) { // cmd: 11, 19, 1d + + switch(fdc.event) { + case FDCEVENT_CMDRECV: + get_hdus(); + get_chrn(); + fdc.eot = fdc.cmds[5]; + fdc.gpl = fdc.cmds[6]; + fdc.stp = fdc.cmds[7]; + break; + } +} +#endif + +// -------------------------------------------------------------------------- + +typedef void (*FDCOPE)(void); + +static const FDCOPE FDC_Ope[0x20] = { + FDC_Invalid, + FDC_Invalid, + FDC_ReadData, // FDC_ReadDiagnostic, + FDC_Specify, + FDC_SenseDeviceStatus, + FDC_WriteData, + FDC_ReadData, + FDC_Recalibrate, + FDC_SenceintStatus, + FDC_WriteData, + FDC_ReadID, + FDC_Invalid, + FDC_ReadData, + FDC_WriteID, + FDC_Invalid, + FDC_Seek, + FDC_Invalid, // 10 +#ifdef SUPPORT_KAI_IMAGES + FDC_ScanEqual, +#else + FDC_Invalid, // FDC_ScanEqual, +#endif + FDC_Invalid, + FDC_Invalid, + FDC_Invalid, + FDC_Invalid, + FDC_Invalid, + FDC_Invalid, + FDC_Invalid, +#ifdef SUPPORT_KAI_IMAGES + FDC_ScanEqual, +#else + FDC_Invalid, // FDC_ScanEqual, +#endif + FDC_Invalid, + FDC_Invalid, + FDC_Invalid, +#ifdef SUPPORT_KAI_IMAGES + FDC_ScanEqual, +#else + FDC_Invalid, // FDC_ScanEqual, +#endif + FDC_Invalid, + FDC_Invalid}; + + +// -------------------------------------------------------------------------- + +static void fdcstatusreset(void) { + + fdc.event = FDCEVENT_NEUTRAL; + fdc.status = FDCSTAT_RQM; +} + +void DMACCALL fdc_datawrite(REG8 data) { + +// if ((fdc.status & (FDCSTAT_RQM | FDCSTAT_DIO)) == FDCSTAT_RQM) { + switch(fdc.event) { + case FDCEVENT_BUFRECV: +// TRACE_("write", fdc.bufp); + fdc.buf[fdc.bufp++] = data; + if ((!(--fdc.bufcnt)) || (fdc.tc)) { + fdc.status &= ~FDCSTAT_RQM; + FDC_Ope[fdc.cmd & 0x1f](); + } + break; + + case FDCEVENT_CMDRECV: + fdc.cmds[fdc.cmdp++] = data; + if (!(--fdc.cmdcnt)) { + fdc.status &= ~FDCSTAT_RQM; + FDC_Ope[fdc.cmd & 0x1f](); + } + break; + + default: + fdc.cmd = data; + get_mtmfsk(); + fdc.status |= FDCSTAT_CB; // コマンド受けたらCBをセット + if (FDCCMD_TABLE[data & 0x1f]) { + fdc.event = FDCEVENT_CMDRECV; + fdc.cmdp = 0; + fdc.cmdcnt = FDCCMD_TABLE[data & 0x1f]; + fdc.status |= FDCSTAT_RQM; + } + else { + fdc.status &= ~FDCSTAT_RQM; + FDC_Ope[fdc.cmd & 0x1f](); + } + break; + } +// } +} + +REG8 DMACCALL fdc_dataread(void) { + + int i; + +// if ((fdc.status & (FDCSTAT_RQM | FDCSTAT_DIO)) +// == (FDCSTAT_RQM | FDCSTAT_DIO)) { + switch(fdc.event) { + case FDCEVENT_BUFSEND: + fdc.lastdata = fdc.buf[fdc.bufp++]; + if (!(--fdc.bufcnt)) { + fdc.event = FDCEVENT_NEUTRAL; + fdc.status &= ~(1 << fdc.us); + fdc.status &= ~(FDCSTAT_DIO | FDCSTAT_CB); + fdc.status |= FDCSTAT_RQM; + } + // 割り込みクリア処理 + for (i = 0; i < 4; i++) { + if (fdc.stat[i]) { + break; + } + } + if (i >= 4) { + fdc_interruptreset(); + } + break; + + case FDCEVENT_BUFSEND2: + if (fdc.bufcnt) { + fdc.lastdata = fdc.buf[fdc.bufp++]; + fdc.bufcnt--; + } + if (fdc.tc) { + if (!fdc.bufcnt) { // ver0.26 + fdc.R++; + if ((fdc.cmd & 0x80) && fdd_seeksector()) { + fdc.C += fdc.hd; + fdc.H = fdc.hd ^ 1; + fdc.R = 1; + } + } + /* 170101 ST modified to work on Windows 9x/2000 */ + fdc.R = 1; + fdcsend_success7(); + } + if (!fdc.bufcnt) { + fdc.event = FDCEVENT_NEXTDATA; + fdc.status &= ~(FDCSTAT_RQM | FDCSTAT_NDM); + FDC_Ope[fdc.cmd & 0x1f](); + } + break; + } +// } + return(fdc.lastdata); +} + +/* SEEKとRECALIBRATEの割り込み通知処理 */ +void fdc_intdelay(void) { + + int i; + + for (i = 0; i < 4; i++) { + if (fdc.int_timer[i]) { + fdc.int_timer[i]--; + if (!fdc.int_timer[i]) { + fdc.stat[i] = fdc.int_stat[i]; + fdc_interrupt(); + } + } + if(fdc_seeksndtimeout[i] > 0) fdc_seeksndtimeout[i]--; + } +} + +// ---- I/O + +static void IOOUTCALL fdc_o92(UINT port, REG8 dat) { + + TRACEOUT(("fdc out %.2x %.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); + + if (((port >> 4) ^ fdc.chgreg) & 1) { + return; + } +// /* 170101 ST modified to work on Windows 9x/2000 form ... */ +// if (fdc.status & FDCSTAT_DIO) { +// fdc.status &= ~FDCSTAT_DIO; +// fdc.status |= FDCSTAT_RQM; +// } +// /* 170101 ST modified to work on Windows 9x/2000 ... to */ + + if ((fdc.status & (FDCSTAT_RQM | FDCSTAT_DIO)) == FDCSTAT_RQM) { + fdc_datawrite(dat); + } +} + +static void IOOUTCALL fdc_o94(UINT port, REG8 dat) { + + UINT8 i; + + TRACEOUT(("fdc out %.2x %.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); + + if (((port >> 4) ^ fdc.chgreg) & 1) { + return; + } + if ((fdc.ctrlreg ^ dat) & 0x10) { + fdcstatusreset(); + fdc_dmaready(0); + dmac_check(); + } + /* 170101 ST modified to work on Windows 9x/2000 form ... */ + if ((fdc.ctrlreg ^ dat) & 0x80) { + if (dat & 0x80) { + fdcstatusreset(); + + if(dat & 0x08){ // XXX: Workaround for OSASK + // FDCリセット後 1,024ms以内にINTがアクティブになる + for (i = 0; i < 4; i++) { + fdc.int_stat[i] = fdc.stat[i]; + fdc.int_timer[i] = FDC_INT_DELAY; + } + } + } + } + if (fdc.chgreg & 4) { + if ((fdc.ctrlreg ^ dat) & 0x08) { + if (dat & 0x08) { + for (i = 0; i < 4; i++) { + if (fdd_diskready(i)) { + fdc.int_stat[i] = FDCRLT_AI | i; + fdc.int_timer[i] = FDC_INT_DELAY; + fdc.status |= (1 << i); + } + } + } + } + } + /* 170101 ST modified to work on Windows 9x/2000 ... to */ + fdc.ctrlreg = dat; +} + +static REG8 IOINPCALL fdc_i90(UINT port) { + + TRACEOUT(("fdc in %.2x %.2x [%.4x:%.4x]", port, fdc.status, + CPU_CS, CPU_IP)); + + if (((port >> 4) ^ fdc.chgreg) & 1) { + return(0xff); + } + return(fdc.status); +} + +static REG8 IOINPCALL fdc_i92(UINT port) { + + REG8 ret; + + if (((port >> 4) ^ fdc.chgreg) & 1) { + return(0xff); + } + if ((fdc.status & (FDCSTAT_RQM | FDCSTAT_DIO)) + == (FDCSTAT_RQM | FDCSTAT_DIO)) { + ret = fdc_dataread(); + } + else { + ret = fdc.lastdata; + } + TRACEOUT(("fdc in %.2x %.2x [%.4x:%.4x]", port, ret, CPU_CS, CPU_IP)); + return(ret); +} + +static REG8 IOINPCALL fdc_i94(UINT port) { + + REG8 ret; + + if (((port >> 4) ^ fdc.chgreg) & 1) { + return(0xff); + } + + ret = 0x40; + if (!(port & 0x10)) /* CC */ + { + ret |= 0x20; /* DMA */ + ret |= 0x10; /* readyを立てるるる */ + } + + if (pccore.dipsw[0] & 8) + { + ret |= 0x04; /* 内蔵優先 */ + } + else + { + ret |= 0x08; /* 外付け優先 */ + } + TRACEOUT(("fdc in %.2x %.2x [%.4x:%.4x]", port, ret, + CPU_CS, CPU_IP)); + + return ret; +} + + +static void IOOUTCALL fdc_obe(UINT port, REG8 dat) { + + TRACEOUT(("fdc out %.2x %.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); + + fdc.chgreg = dat; + if (fdc.chgreg & 2) { + CTRL_FDMEDIA = DISKTYPE_2HD; + } + else { + CTRL_FDMEDIA = DISKTYPE_2DD; + } + (void)port; +} + +static REG8 IOINPCALL fdc_ibe(UINT port) { + + (void)port; + TRACEOUT(("fdc in %.2x %.2x [%.4x:%.4x]", port, ((fdc.chgreg & 3) | 8), + CPU_CS, CPU_IP)); + + return((fdc.chgreg & 3) | 8 | 0xf0); +} + +static void IOOUTCALL fdc_o4be(UINT port, REG8 dat) { + + TRACEOUT(("fdc out %.2x %.2x [%.4x:%.4x]", port, dat, CPU_CS, CPU_IP)); + + fdc.reg144 = dat; + if (dat & 0x10) { + fdc.rpm[(dat >> 5) & 3] = dat & 1; + } + (void)port; +} + +static REG8 IOINPCALL fdc_i4be(UINT port) { + + (void)port; + TRACEOUT(("fdc in %.2x %.2x [%.4x:%.4x]", port, (fdc.rpm[(fdc.reg144 >> 5) & 3] | 0xf0), + CPU_CS, CPU_IP)); + return(fdc.rpm[(fdc.reg144 >> 5) & 3] | 0xfe); +} + + +// ---- I/F + +static const IOOUT fdco90[4] = { + NULL, fdc_o92, fdc_o94, NULL}; +static const IOINP fdci90[4] = { + fdc_i90, fdc_i92, fdc_i94, NULL}; +static const IOOUT fdcobe[1] = {fdc_obe}; +static const IOINP fdcibe[1] = {fdc_ibe}; + +void fdc_reset(const NP2CFG *pConfig) { + + ZeroMemory(&fdc, sizeof(fdc)); + fdc.equip = pConfig->fddequip; +#if defined(SUPPORT_PC9821) + fdc.support144 = 1; +#else + fdc.support144 = pConfig->usefd144; +#endif + fdcstatusreset(); + dmac_attach(DMADEV_2HD, FDC_DMACH2HD); + dmac_attach(DMADEV_2DD, FDC_DMACH2DD); + CTRL_FDMEDIA = DISKTYPE_2HD; + fdc.chgreg = 3; +} + +void fdc_bind(void) { + + iocore_attachcmnoutex(0x0090, 0x00f9, fdco90, 4); + iocore_attachcmninpex(0x0090, 0x00f9, fdci90, 4); + iocore_attachcmnoutex(0x00c8, 0x00f9, fdco90, 4); + iocore_attachcmninpex(0x00c8, 0x00f9, fdci90, 4); + + if (fdc.support144) { + iocore_attachout(0x04be, fdc_o4be); + iocore_attachinp(0x04be, fdc_i4be); + } + iocore_attachsysoutex(0x00be, 0x0cff, fdcobe, 1); + iocore_attachsysinpex(0x00be, 0x0cff, fdcibe, 1); +} + diff --git a/io/fdc.h b/io/fdc.h old mode 100755 new mode 100644 index d78ce249..dc2c5727 --- a/io/fdc.h +++ b/io/fdc.h @@ -1,138 +1,138 @@ - -enum { - FDCEVENT_NEUTRAL, - FDCEVENT_CMDRECV, - FDCEVENT_DATSEND, - FDCEVENT_BUFRECV, - FDCEVENT_BUFSEND, - FDCEVENT_BUFSEND2, - FDCEVENT_NEXTDATA, - FDCEVENT_BUSY -}; - -enum { - LENGTH_GAP0 = 80, - LENGTH_SYNC = 12, - LENGTH_IM = 4, - LENGTH_GAP1 = 50, - LENGTH_IAM = 4, - LENGTH_ID = 4, - LENGTH_CRC = 2, - LENGTH_GAP2 = 22, - LENGTH_DAM = 4, - - LENGTH_PRIAMP = LENGTH_GAP0 + LENGTH_SYNC + LENGTH_IM + LENGTH_GAP1, - LENGTH_SECTOR = LENGTH_SYNC + LENGTH_IAM + LENGTH_ID + LENGTH_CRC + - LENGTH_GAP2 + LENGTH_SYNC + LENGTH_DAM + LENGTH_CRC, - - LENGTH_TRACK = 10600 // normal: (+-2%) -}; - -// real sector size = LENGTH_SECTOR + (128 << n) + gap3 - -enum { - FDCRLT_NR = 0x000008, - FDCRLT_EC = 0x000010, - FDCRLT_SE = 0x000020, - FDCRLT_IC0 = 0x000040, - FDCRLT_IC1 = 0x000080, - - FDCRLT_MA = 0x000100, - FDCRLT_NW = 0x000200, - FDCRLT_ND = 0x000400, - FDCRLT_OR = 0x001000, - FDCRLT_DE = 0x002000, - FDCRLT_EN = 0x008000, - - FDCRLT_MD = 0x010000, - FDCRLT_BC = 0x020000, - FDCRLT_SN = 0x040000, - FDCRLT_SH = 0x080000, - FDCRLT_NC = 0x100000, - FDCRLT_DD = 0x200000, - FDCRLT_CM = 0x400000, - - FDCRLT_NT = 0x00000000, // type miss ? - FDCRLT_AT = 0x00000040, - FDCRLT_IC = 0x00000080, - FDCRLT_AI = 0x000000c0, - - FDCSTAT_CB = 0x10, - FDCSTAT_NDM = 0x20, - FDCSTAT_DIO = 0x40, - FDCSTAT_RQM = 0x80 -}; - -typedef struct { - UINT8 equip; - UINT8 support144; - UINT8 ctrlfd; - UINT8 padding; - - UINT8 us, hd; - UINT8 mt, mf, sk; - UINT8 eot, gpl, dtl; - UINT8 C, H, R, N; - UINT8 srt, hut, hlt, nd; - UINT8 stp, ncn, sc, d; - - UINT8 status; - UINT8 intreq; - UINT8 lastdata; - UINT8 tc; - - UINT8 crcn; - UINT8 ctrlreg; - UINT8 chgreg; - UINT8 reg144; - - UINT32 stat[4]; - UINT8 treg[4]; - UINT8 rpm[4]; - - int event; - int cmdp; - int cmdcnt; - int datp; - int datcnt; - int bufp; - int bufcnt; - - UINT8 cmd; - UINT8 cmds[15]; - UINT8 data[16]; - - UINT8 buf[0x8000]; - - // SEEKとRECALIBRATEの通知割り込み用 - UINT8 int_timer[4]; - UINT8 int_stat[4]; -} _FDC, *FDC; - - -#ifdef __cplusplus -extern "C" { -#endif - -#define CTRL_FDMEDIA fdc.ctrlfd - -void fdc_intwait(NEVENTITEM item); - -void fdc_interrupt(void); - -void DMACCALL fdc_datawrite(REG8 data); -REG8 DMACCALL fdc_dataread(void); -REG8 DMACCALL fdc_dmafunc(REG8 func); - -void fdcsend_error7(void); -void fdcsend_success7(void); - -void fdc_reset(const NP2CFG *pConfig); -void fdc_bind(void); - -void fdc_intdelay(void); - -#ifdef __cplusplus -} -#endif - + +enum { + FDCEVENT_NEUTRAL, + FDCEVENT_CMDRECV, + FDCEVENT_DATSEND, + FDCEVENT_BUFRECV, + FDCEVENT_BUFSEND, + FDCEVENT_BUFSEND2, + FDCEVENT_NEXTDATA, + FDCEVENT_BUSY +}; + +enum { + LENGTH_GAP0 = 80, + LENGTH_SYNC = 12, + LENGTH_IM = 4, + LENGTH_GAP1 = 50, + LENGTH_IAM = 4, + LENGTH_ID = 4, + LENGTH_CRC = 2, + LENGTH_GAP2 = 22, + LENGTH_DAM = 4, + + LENGTH_PRIAMP = LENGTH_GAP0 + LENGTH_SYNC + LENGTH_IM + LENGTH_GAP1, + LENGTH_SECTOR = LENGTH_SYNC + LENGTH_IAM + LENGTH_ID + LENGTH_CRC + + LENGTH_GAP2 + LENGTH_SYNC + LENGTH_DAM + LENGTH_CRC, + + LENGTH_TRACK = 10600 // normal: (+-2%) +}; + +// real sector size = LENGTH_SECTOR + (128 << n) + gap3 + +enum { + FDCRLT_NR = 0x000008, + FDCRLT_EC = 0x000010, + FDCRLT_SE = 0x000020, + FDCRLT_IC0 = 0x000040, + FDCRLT_IC1 = 0x000080, + + FDCRLT_MA = 0x000100, + FDCRLT_NW = 0x000200, + FDCRLT_ND = 0x000400, + FDCRLT_OR = 0x001000, + FDCRLT_DE = 0x002000, + FDCRLT_EN = 0x008000, + + FDCRLT_MD = 0x010000, + FDCRLT_BC = 0x020000, + FDCRLT_SN = 0x040000, + FDCRLT_SH = 0x080000, + FDCRLT_NC = 0x100000, + FDCRLT_DD = 0x200000, + FDCRLT_CM = 0x400000, + + FDCRLT_NT = 0x00000000, // type miss ? + FDCRLT_AT = 0x00000040, + FDCRLT_IC = 0x00000080, + FDCRLT_AI = 0x000000c0, + + FDCSTAT_CB = 0x10, + FDCSTAT_NDM = 0x20, + FDCSTAT_DIO = 0x40, + FDCSTAT_RQM = 0x80 +}; + +typedef struct { + UINT8 equip; + UINT8 support144; + UINT8 ctrlfd; + UINT8 padding; + + UINT8 us, hd; + UINT8 mt, mf, sk; + UINT8 eot, gpl, dtl; + UINT8 C, H, R, N; + UINT8 srt, hut, hlt, nd; + UINT8 stp, ncn, sc, d; + + UINT8 status; + UINT8 intreq; + UINT8 lastdata; + UINT8 tc; + + UINT8 crcn; + UINT8 ctrlreg; + UINT8 chgreg; + UINT8 reg144; + + UINT32 stat[4]; + UINT8 treg[4]; + UINT8 rpm[4]; + + int event; + int cmdp; + int cmdcnt; + int datp; + int datcnt; + int bufp; + int bufcnt; + + UINT8 cmd; + UINT8 cmds[15]; + UINT8 data[16]; + + UINT8 buf[0x8000]; + + // SEEKとRECALIBRATEの通知割り込み用 + UINT8 int_timer[4]; + UINT8 int_stat[4]; +} _FDC, *FDC; + + +#ifdef __cplusplus +extern "C" { +#endif + +#define CTRL_FDMEDIA fdc.ctrlfd + +void fdc_intwait(NEVENTITEM item); + +void fdc_interrupt(void); + +void DMACCALL fdc_datawrite(REG8 data); +REG8 DMACCALL fdc_dataread(void); +REG8 DMACCALL fdc_dmafunc(REG8 func); + +void fdcsend_error7(void); +void fdcsend_success7(void); + +void fdc_reset(const NP2CFG *pConfig); +void fdc_bind(void); + +void fdc_intdelay(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/fdd320.c b/io/fdd320.c old mode 100755 new mode 100644 index ef1e5dcb..bfacc199 --- a/io/fdd320.c +++ b/io/fdd320.c @@ -1,39 +1,39 @@ -#include -#include -#include - - -// こっちで処理するか シリンダ倍移動で誤魔化すか悩ましいところ - - UINT8 fdd320_stat; - - -static REG8 IOINPCALL fdd320_i51(UINT port) { - - (void)port; - return(0x00); -} - -static REG8 IOINPCALL fdd320_i55(UINT port) { - - fdd320_stat ^= 0xff; - (void)port; - return(fdd320_stat); -} - - -// ---- - -static const IOINP fdd320i51[4] = { - fdd320_i51, NULL, fdd320_i55, NULL}; - -void fdd320_reset(const NP2CFG *pConfig) { - - fdd320_stat = 0xff; -} - -void fdd320_bind(void) { - - iocore_attachcmninpex(0x0051, 0x00f9, fdd320i51, 4); -} - +#include +#include +#include + + +// こっちで処理するか シリンダ倍移動で誤魔化すか悩ましいところ + + UINT8 fdd320_stat; + + +static REG8 IOINPCALL fdd320_i51(UINT port) { + + (void)port; + return(0x00); +} + +static REG8 IOINPCALL fdd320_i55(UINT port) { + + fdd320_stat ^= 0xff; + (void)port; + return(fdd320_stat); +} + + +// ---- + +static const IOINP fdd320i51[4] = { + fdd320_i51, NULL, fdd320_i55, NULL}; + +void fdd320_reset(const NP2CFG *pConfig) { + + fdd320_stat = 0xff; +} + +void fdd320_bind(void) { + + iocore_attachcmninpex(0x0051, 0x00f9, fdd320i51, 4); +} + diff --git a/io/fdd320.h b/io/fdd320.h old mode 100755 new mode 100644 index 6b7ba4d8..4b115ea3 --- a/io/fdd320.h +++ b/io/fdd320.h @@ -1,12 +1,12 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void fdd320_reset(const NP2CFG *pConfig); -void fdd320_bind(void); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void fdd320_reset(const NP2CFG *pConfig); +void fdd320_bind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/gdc.c b/io/gdc.c old mode 100755 new mode 100644 index 736b820e..9a824e40 --- a/io/gdc.c +++ b/io/gdc.c @@ -1,1193 +1,1193 @@ -#include -#include -#include -#include -#include -#include "gdc_cmd.tbl" -#include -#include -#include -#include -#if defined(BIOS_IO_EMULATION) -#include -#endif -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif - -#if !defined(CPUCORE_IA32) -#define SEARCH_SYNC -#endif -#define TURE_SYNC - -typedef struct { - UINT32 clock; - UINT minx; - UINT maxx; - UINT miny; - UINT maxy; -} GDCCLK; - -// 31kHzの時の動作クロックが不明… -static const GDCCLK gdcclk[] = { - {14318180 / 8, 112 - 8, 112 + 8, 200, 300}, - {21052600 / 8, 106 - 6, 106 + 6, 400, 575}, - {25260000 / 8, 100 - 8, 100 + 8, 400, 575}}; - - -typedef struct { - UINT8 master[8]; - UINT8 slave[8]; -} GDCSYNC; - -static const UINT8 defsyncm15[8] = {0x10,0x4e,0x07,0x25,0x0d,0x0f,0xc8,0x94}; -static const UINT8 defsyncs15[8] = {0x06,0x26,0x03,0x11,0x86,0x0f,0xc8,0x94}; - -static const UINT8 defsyncm24[8] = {0x10,0x4e,0x07,0x25,0x07,0x07,0x90,0x65}; -static const UINT8 defsyncs24[8] = {0x06,0x26,0x03,0x11,0x83,0x07,0x90,0x65}; - -#if 0 -static const UINT8 defsyncm31[8] = {0x10,0x4e,0x47,0x0c,0x07,0x0d,0x90,0x89}; -static const UINT8 defsyncs31[8] = {0x06,0x26,0x41,0x0c,0x83,0x0d,0x90,0x89}; -#endif /* 0 */ - - -static const UINT8 defdegpal[4] = {0x04,0x15,0x26,0x37}; -static const UINT16 defanapal[16] = { - 0x000,0x007,0x070,0x077,0x700,0x707,0x770,0x777, - 0x444,0x00f,0x0f0,0x0ff,0xf00,0xf0f,0xff0,0xfff}; - - -void gdc_setdegitalpal(int color, REG8 value) { - - if (color & 4) { - color &= 3; - value &= 0x0f; - if ((gdc.degpal[color] ^ value) & 0x07) { - gdcs.palchange = GDCSCRN_REDRAW; - } - gdc.degpal[color] &= 0xf0; - gdc.degpal[color] |= value; - } - else { - color &= 3; - value <<= 4; - if ((gdc.degpal[color] ^ value) & 0x70) { - gdcs.palchange = GDCSCRN_REDRAW; - } - gdc.degpal[color] &= 0x0f; - gdc.degpal[color] |= value; - } -} - -void gdc_setdegpalpack(int color, REG8 value) { - - if ((gdc.degpal[color] ^ value) & 0x77) { - gdcs.palchange = GDCSCRN_REDRAW; - } - gdc.degpal[color] = (UINT8)value; -} - -void gdc_setanalogpal(int color, int rgb, REG8 value) { - - UINT8 *ptr; - PAL1EVENT *event; - - ptr = ((UINT8 *)(gdc.anapal + color)) + rgb; - if (((*ptr) ^ value) & 0x0f) { - gdcs.palchange = GDCSCRN_REDRAW; - if (palevent.events < PALEVENTMAX) { - if (!gdc.vsync) { - event = palevent.event + palevent.events; - event->clock = g_nevent.item[NEVENT_FLAMES].clock - - (CPU_BASECLOCK - CPU_REMCLOCK); - event->color = (UINT16)((color * sizeof(RGB32)) + rgb); - event->value = (UINT8)value; - palevent.events++; - } - else { - palevent.vsyncpal = 1; - } - } - } - *ptr = value; -} - -void gdc_setanalogpalall(const UINT16 *paltbl) { - - UINT c; - UINT pal; - - for (c=0; c<16; c++) { - pal = *paltbl++; -#if defined(SUPPORT_PC9821) - gdc.anareg[(c * 3) + 0] = (pal >> 8) & 15; - gdc.anareg[(c * 3) + 1] = (pal >> 4) & 15; - gdc.anareg[(c * 3) + 2] = (pal >> 0) & 15; -#endif - gdc_setanalogpal(c, offsetof(RGB32, p.g), (REG8)((pal >> 8) & 15)); - gdc_setanalogpal(c, offsetof(RGB32, p.r), (REG8)((pal >> 4) & 15)); - gdc_setanalogpal(c, offsetof(RGB32, p.b), (REG8)((pal >> 0) & 15)); - } -} - - -void gdc_paletteinit(void) { - - int c; - - CopyMemory(gdc.degpal, defdegpal, 4); - for (c=0; c<8; c++) { - gdc.anapal[c+0].p.b = ((c&1)?0x0f:0); - gdc.anapal[c+8].p.b = ((c&1)?0x0a:0); - gdc.anapal[c+0].p.r = ((c&2)?0x0f:0); - gdc.anapal[c+8].p.r = ((c&2)?0x0a:0); - gdc.anapal[c+0].p.g = ((c&4)?0x0f:0); - gdc.anapal[c+8].p.g = ((c&4)?0x0a:0); - } - gdc.anapal[8].p.b = 0x07; - gdc.anapal[8].p.r = 0x07; - gdc.anapal[8].p.g = 0x07; - gdcs.palchange = GDCSCRN_REDRAW; -} - -#if defined(SUPPORT_PC9821) -void gdc_analogext(BOOL extend) { - -#if defined(SUPPORT_CRT31KHZ) - if (extend) { - gdc.analog |= (1 << GDCANALOG_256); - vramop.operate |= (1 << VOPBIT_VGA); -#if defined(SUPPORT_IA32_HAXM) - i386hax_vm_setmemoryarea(vramex + ((vramop.mio1[0] & 15) << 15), 0xA8000, 0x8000); - i386hax_vm_setmemoryarea(vramex + ((vramop.mio1[2] & 15) << 15), 0xB0000, 0x8000); -#endif - } - else { - gdc.analog &= ~(1 << (GDCANALOG_256)); - vramop.operate &= ~(1 << VOPBIT_VGA); -#if defined(SUPPORT_IA32_HAXM) - i386hax_vm_removememoryarea(vramex + ((vramop.mio1[0] & 15) << 15), 0xA8000, 0x8000); - i386hax_vm_removememoryarea(vramex + ((vramop.mio1[2] & 15) << 15), 0xB0000, 0x8000); -#endif - } - gdcs.palchange = GDCSCRN_REDRAW; - gdcs.grphdisp |= GDCSCRN_EXT | GDCSCRN_ALLDRAW2; - MEMM_VRAM(vramop.operate); -#endif -} -#endif - - -// -------------------------------------------------------------------------- - -void gdc_vectreset(GDCDATA item) { - - item->para[GDC_VECTW+1] = 0x00; - item->para[GDC_VECTW+2] = 0x00; - item->para[GDC_VECTW+3] = 0x08; - item->para[GDC_VECTW+4] = 0x00; - item->para[GDC_VECTW+5] = 0x08; - item->para[GDC_VECTW+6] = 0x00; - item->para[GDC_VECTW+7] = 0xff; - item->para[GDC_VECTW+8] = 0xff; - item->para[GDC_VECTW+9] = 0xff; - item->para[GDC_VECTW+10] = 0xff; -} - -static void vectdraw(void) { - - UINT32 csrw; -const GDCVECT *vect; - REG16 textw; - REG8 ope; - - csrw = LOADINTELDWORD(gdc.s.para + GDC_CSRW); - vect = (GDCVECT *)(gdc.s.para + GDC_VECTW); - textw = LOADINTELWORD(gdc.s.para + GDC_TEXTW); - ope = gdc.s.para[GDC_WRITE]; - - if (!(vect->ope & 0x78)) { - gdcsub_vectp(csrw, vect, textw, ope); // Single Dot Writing? - } - if (vect->ope & 0x08) { - gdcsub_vectl(csrw, vect, textw, ope); - } - if (vect->ope & 0x10) { // undocumented - gdcsub_vectt(csrw, vect, textw, ope); - } - if (vect->ope & 0x20) { - gdcsub_vectc(csrw, vect, textw, ope); - } - if (vect->ope & 0x40) { - gdcsub_vectr(csrw, vect, textw, ope); - } - gdc_vectreset(&gdc.s); -} - -static void textdraw(void) { - - UINT32 csrw; -const GDCVECT *vect; - REG16 textw; - REG8 ope; - - csrw = LOADINTELDWORD(gdc.s.para + GDC_CSRW); - vect = (GDCVECT *)(gdc.s.para + GDC_VECTW); - textw = gdc.s.para[GDC_TEXTW + 7]; - textw = (textw << 8) + textw; - ope = gdc.s.para[GDC_WRITE]; - - if (!(vect->ope & 0x78)) { - gdcsub_vectp(csrw, vect, textw, ope); // Single Dot Writing? - } - if (vect->ope & 0x08) { // undocumented - gdcsub_vectl(csrw, vect, textw, ope); - } - if (vect->ope & 0x10) { - gdcsub_text(csrw, vect, gdc.s.para + GDC_TEXTW, ope); - } - if (vect->ope & 0x20) { // undocumented - gdcsub_vectc(csrw, vect, textw, ope); - } - if (vect->ope & 0x40) { // undocumented - gdcsub_vectr(csrw, vect, textw, ope); - } - gdc_vectreset(&gdc.s); -} - -void gdc_work(int id) { - - GDCDATA item; - UINT8 *dispflag; - UINT i; - UINT8 data; - - item = (id == GDCWORK_MASTER)?&gdc.m:&gdc.s; - dispflag = (id == GDCWORK_MASTER)?&gdcs.textdisp:&gdcs.grphdisp; - - for (i=0; icnt; i++) { - data = (UINT8)item->fifo[i]; - if (item->fifo[i] & 0xff00) { - item->cmd = data; - item->paracb = 0; - if ((data & 0x60) == 0x20) { - item->para[GDC_WRITE] = data; - switch(data & 0x18) { - case 0x00: - item->rcv = 2; - item->paracb = 1; - break; - - case 0x10: - case 0x18: - item->rcv = 1; - item->paracb = 1; - break; - - default: - item->rcv = 0; - break; - } - item->ptr = GDC_CODE; - item->snd = 0; - continue; - } - switch(data) { - case CMD_START_: - case CMD_START: - case CMD_SYNC_ON: - (*dispflag) |= GDCSCRN_ENABLE | GDCSCRN_ALLDRAW2; - pcstat.screenupdate |= 2; - break; - - case CMD_STOP_: - case CMD_STOP: - case CMD_SYNC_OFF: - (*dispflag) &= (~GDCSCRN_ENABLE); -// (*dispflag) |= GDCSCRN_ALLDRAW2; - pcstat.screenupdate |= 2; - break; - - case CMD_VECTE: - if (id != GDCWORK_MASTER) { - vectdraw(); - } - break; - - case CMD_TEXTE: - if (id != GDCWORK_MASTER) { - textdraw(); - } - break; - } - item->ptr = gdc_cmd[data].pos; - item->rcv = gdc_cmd[data].outdatas; - item->snd = gdc_cmd[data].indatas; - if (item->snd) { - switch(item->ptr) { - case GDC_CSRR: - item->para[GDC_CSRR+0] = item->para[GDC_CSRW+0]; - item->para[GDC_CSRR+1] = item->para[GDC_CSRW+1]; - item->para[GDC_CSRR+2] = item->para[GDC_CSRW+2] & 3; - item->para[GDC_CSRR+3] = 0; - item->para[GDC_CSRR+4] = 0; - break; - } - } - } - else if (item->rcv) { - if (item->para[item->ptr] != data) { - item->para[item->ptr] = data; - (*dispflag) |= gdc_dirtyflag[id][item->ptr]; - } - (item->ptr)++; - (item->rcv)--; - if ((!(item->rcv)) && (id == GDCWORK_SLAVE) && - (((item->cmd) & 0xe4) == 0x20)) { - gdcsub_write(); - item->paracb = 0; - } - } - } - item->cnt = 0; -} - -// BIOSとかで弄った時にリセット -void gdc_forceready(int id) { - - GDCDATA item; - item = (id == GDCWORK_MASTER)?&gdc.m:&gdc.s; - if (item->cnt) { - gdc_work(id); - } - item->rcv = 0; - item->snd = 0; -} - - -void gdc_updateclock(void) { - - UINT tmp; - UINT cr; - UINT hfbs; - UINT vfbs; - UINT lf; - UINT x; - UINT y; - UINT cnt; -const GDCCLK *clk; - UINT32 hclock; - - cr = gdc.m.para[GDC_SYNC + 1] + 2; - tmp = LOADINTELWORD(gdc.m.para + GDC_SYNC + 2); - hfbs = tmp & 0x1f; // HS - hfbs += tmp >> 10; // HFP - vfbs = (tmp >> 5) & 0x1f; // VS - hfbs += gdc.m.para[GDC_SYNC + 4] & 0x3f; // HFP - vfbs += gdc.m.para[GDC_SYNC + 5] & 0x3f; // VFP - tmp = LOADINTELWORD(gdc.m.para + GDC_SYNC + 6); - lf = ((tmp - 1) & 0x3ff) + 1; - vfbs += tmp >> 10; // VBP - - hfbs += 3; - x = cr + hfbs; - if (!vfbs) { - vfbs = 1; - } - y = lf + vfbs; -// TRACEOUT(("h %d:%d / v %d:%d", cr, x, lf, y)); - -#if defined(SUPPORT_CRT31KHZ) - if (gdc.display & (1 << GDCDISP_31)) { - clk = gdcclk + 2; - } - else -#endif - if (!(gdc.crt15khz & 2)) { // 24.83±300Hz - clk = gdcclk + 1; - } - else { // 15.98±300Hz - clk = gdcclk; - } - - if (x < clk->minx) { - cr = (clk->minx * cr) / x; - x = clk->minx; - } - else if (x > clk->maxx) { - cr = (clk->maxx * cr) / x; - x = clk->maxx; - } - if (y < clk->miny) { - lf = (clk->miny * lf) / y; - y = clk->miny; - } - else if (y > clk->maxy) { - lf = (clk->maxy * lf) / y; - y = clk->maxy; - } - hclock = clk->clock / x; - gdc.hclock = hclock; - gdc.vclock = hclock * 10 / y; - cnt = (pccore.baseclock * y) / hclock; - cnt *= pccore.multiple; - gdc.rasterclock = cnt / y; - gdc.hsyncclock = (gdc.rasterclock * cr) / x; - gdc.dispclock = gdc.rasterclock * lf; - gdc.vsyncclock = cnt - gdc.dispclock; - timing_setrate(y, hclock); -} - -void gdc_restorekacmode(void) { - - UINT8 bit; - - bit = (((!np2cfg.uPD72020) && (gdc.mode1 & 0x20))?0x00:0xff); - if (gdc.bitac != bit) { - gdc.bitac = bit; - gdcs.textdisp |= GDCSCRN_ALLDRAW2; - } -} - - -// ---- I/O master - -static void IOOUTCALL gdc_o60(UINT port, REG8 dat) { - - if (gdc.m.cnt < GDCCMD_MAX) { - gdc.m.fifo[gdc.m.cnt++] = dat; - } - (void)port; -} - -static void IOOUTCALL gdc_o62(UINT port, REG8 dat) { - - if (gdc.m.cnt < GDCCMD_MAX) { - gdc.m.fifo[gdc.m.cnt++] = 0x100 | dat; - } - gdc_work(GDCWORK_MASTER); - (void)port; -} - -static void IOOUTCALL gdc_o64(UINT port, REG8 dat) { - - gdc.vsyncint = 1; - (void)port; - (void)dat; -} - -static void IOOUTCALL gdc_o68(UINT port, REG8 dat) { - - REG8 bit; - - if (!(dat & 0xf0)) { - bit = 1 << ((dat >> 1) & 7); - if (dat & 1) { - gdc.mode1 |= bit; - } - else { - gdc.mode1 &= ~bit; - } - if (bit & (0x01 | 0x04 | 0x10)) { - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - } - else if (bit == 0x02) { - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - gdcs.palchange = GDCSCRN_REDRAW; - } - else if (bit == 0x08) { - gdcs.textdisp |= GDCSCRN_ALLDRAW2; - } - else if (bit == 0x20) { - gdc_restorekacmode(); - } - else if (bit == 0x80) { - pcstat.screenupdate |= 2; - } - gdcs.msw_accessable = gdc.mode1 & 0x40; - } - (void)port; -} - -static void IOOUTCALL gdc_o6a(UINT port, REG8 dat) { - - REG8 bit; - - if (!(dat & 0xf8)) { - bit = (dat >> 1) & 3; - dat &= 1; - if (!(((gdc.mode2 >> bit) ^ dat) & 1)) { - return; - } - gdc.mode2 ^= (1 << bit); - switch(bit) { - case 0: - if (gdc.display & (1 << GDCDISP_ANALOG)) { - gdc.analog &= ~(1 << GDCANALOG_16); - gdc.analog |= (dat << GDCANALOG_16); - gdcs.palchange = GDCSCRN_REDRAW; - vramop.operate &= ~(1 << VOPBIT_ANALOG); - vramop.operate |= dat << VOPBIT_ANALOG; - MEMM_VRAM(vramop.operate); - } - break; - - case 2: - if ((gdc.mode2 & 0x08) && (grcg.chip == 3)) { - vramop.operate &= ~(1 << VOPBIT_EGC); - vramop.operate |= dat << VOPBIT_EGC; - MEMM_VRAM(vramop.operate); - } - break; - } - gdcs.mode2 = gdc.mode2; - } - else { - switch(dat) { -#if defined(SUPPORT_PC9821) -#if defined(SUPPORT_CRT31KHZ) - case 0x20: - if (gdc.mode2 & 0x08) { - gdc_analogext(FALSE); - } - break; - - case 0x21: - if (gdc.mode2 & 0x08) { - gdc_analogext(TRUE); - } - break; - case 0x68: - gdc.analog &= ~(1 << GDCANALOG_256E); - break; - - case 0x69: - gdc.analog |= (1 << GDCANALOG_256E); - break; -#endif -#endif - case 0x40: - case 0x80: // EPSON? - gdc.display &= ~(1 << GDCDISP_PLAZMA); - gdcs.textdisp |= GDCSCRN_EXT; - break; - - case 0x41: - case 0x81: // EPSON? - gdc.display |= (1 << GDCDISP_PLAZMA); - gdcs.textdisp |= GDCSCRN_EXT; - break; - - case 0x82: - gdc.clock &= ~1; - gdcs.grphdisp |= GDCSCRN_EXT; - break; - - case 0x83: - gdc.clock |= 1; - gdcs.grphdisp |= GDCSCRN_EXT; - break; - - case 0x84: - gdc.clock &= ~2; - gdcs.grphdisp |= GDCSCRN_EXT; - break; - - case 0x85: - gdc.clock |= 2; - gdcs.grphdisp |= GDCSCRN_EXT; - break; - } - } - (void)port; -} - -static void IOOUTCALL gdc_o6e(UINT port, REG8 dat) { - - switch(dat) { - case 0: - gdc.crt15khz &= ~1; - gdcs.textdisp |= GDCSCRN_ALLDRAW2; - break; - - case 1: - gdc.crt15khz |= 1; - gdcs.textdisp |= GDCSCRN_ALLDRAW2; - break; - } - (void)port; -} - -static REG8 IOINPCALL gdc_i60(UINT port) { - - REG8 ret; - SINT32 remain; - - ret = 0x80 | gdc.vsync; // | m_drawing; - remain = nevent_getremain(NEVENT_FLAMES); - if (remain >= 0) { - if ((remain % gdc.rasterclock) < gdc.hsyncclock) { - ret |= 0x40; - } - } - if (gdc.m.snd) { - ret |= 0x01; - } - if (gdc.m.cnt >= GDCCMD_MAX) { - ret |= 0x02; - } - if (!gdc.m.cnt) { - ret |= 0x04; - } - else { - gdc_work(GDCWORK_MASTER); - } -#ifdef SEARCH_SYNC // ToDo: フェッチキューを参照するように… - if ((CPU_INPADRS) && (CPU_REMCLOCK >= 5)) { - UINT32 addr; - UINT16 jadr; - UINT16 memv; - addr = CPU_INPADRS; - jadr = 0xfa74; - memv = MEML_READ16(addr); - while((memv == 0x00eb) || (memv == 0x5fe6)) { - jadr -= 0x200; - addr += 2; - memv = MEML_READ16(addr); - } - if ((memv == 0x20a8) || (memv == 0x2024)) { - memv = MEML_READ16(addr + 2); - if (memv == jadr) { // je - if (!gdc.vsync) { - CPU_REMCLOCK = -1; - } - } - else if (memv == (jadr + 1)) { // jne - if (gdc.vsync) { - CPU_REMCLOCK = -1; - } - } - } - } -#endif -#ifdef TURE_SYNC // クロックイベントの誤差修正 - if (g_nevent.item[NEVENT_FLAMES].clock < (CPU_BASECLOCK - CPU_REMCLOCK)) { - ret ^= 0x20; - } -#endif - (void)port; - return(ret); -} - -static REG8 IOINPCALL gdc_i62(UINT port) { - - if (gdc.m.snd) { - gdc.m.snd--; - return(gdc.m.para[gdc.m.ptr++]); - } - (void)port; - return(0xff); -} - -static REG8 IOINPCALL gdc_i68(UINT port) { - - (void)port; - return(gdc.mode1); -} - -static REG8 IOINPCALL gdc_i6a(UINT port) { - - (void)port; - return(gdc.mode2); -} - - -// ---- I/O slave - -static void IOOUTCALL gdc_oa0(UINT port, REG8 dat) { - - if (gdc.s.cnt < GDCCMD_MAX) { - gdc.s.fifo[gdc.s.cnt++] = dat; - } -// TRACEOUT(("GDC-B %.2x [%.4x:%.4x]", dat, CPU_CS, CPU_IP)); - if (gdc.s.paracb) { - gdc_work(GDCWORK_SLAVE); - } - (void)port; -} - -static void IOOUTCALL gdc_oa2(UINT port, REG8 dat) { - - if (gdc.s.cnt < GDCCMD_MAX) { - gdc.s.fifo[gdc.s.cnt++] = 0x100 | dat; - } -// TRACEOUT(("GDC-A %.2x", dat)); - gdc_work(GDCWORK_SLAVE); - (void)port; -} - -static void IOOUTCALL gdc_oa4(UINT port, REG8 dat) { - - if ((gdcs.disp ^ dat) & 1) { - gdcs.disp = dat & 1; - pcstat.screenupdate |= 2; - } - (void)port; -} - -static void IOOUTCALL gdc_oa6(UINT port, REG8 dat) { - - dat = dat & 1; - if (gdcs.access != dat) { - gdcs.access = (UINT8)dat; - vramop.operate &= ~(1 << VOPBIT_ACCESS); - vramop.operate |= dat << VOPBIT_ACCESS; - MEMM_VRAM(vramop.operate); - } - (void)port; -} - -static REG8 IOINPCALL gdc_ia0(UINT port) { - - REG8 ret; - SINT32 remain; - - ret = 0x80 | gdc.vsync | gdc.s_drawing; - remain = nevent_getremain(NEVENT_FLAMES); - if (remain >= 0) { - if ((remain % gdc.rasterclock) < (gdc.hsyncclock)) { - ret |= 0x40; - } - } - if (gdc.s.snd) { - ret |= 0x01; - } - if (gdc.s.cnt >= GDCCMD_MAX) { - ret |= 0x02; - } - if (!gdc.s.cnt) { - ret |= 0x04; - } - else { - gdc_work(GDCWORK_SLAVE); - } -#ifdef SEARCH_SYNC - if ((CPU_INPADRS) && (CPU_REMCLOCK >= 5)) { - UINT32 addr; - UINT16 jadr; - UINT16 memv; - addr = CPU_INPADRS; - jadr = 0xfa74; - memv = MEML_READ16(addr); - while((memv == 0x00eb) || (memv == 0x5fe6)) { - jadr -= 0x200; - addr += 2; - memv = MEML_READ16(addr); - } - if ((memv == 0x20a8) || (memv == 0x2024)) { - memv = MEML_READ16(addr + 2); - if (memv == jadr) { // je - if (!gdc.vsync) { - CPU_REMCLOCK = -1; - } - } - else if (memv == (jadr + 1)) { // jne - if (gdc.vsync) { - CPU_REMCLOCK = -1; - } - } - } - } -#endif -#ifdef TURE_SYNC // クロックイベントの誤差修正 - if (g_nevent.item[NEVENT_FLAMES].clock < (CPU_BASECLOCK - CPU_REMCLOCK)) { - ret ^= 0x20; - } -#endif - (void)port; - return(ret); -} - -static REG8 IOINPCALL gdc_ia2(UINT port) { - - if (gdc.s.snd) { - gdc.s.snd--; - return(gdc.s.para[gdc.s.ptr++]); - } - (void)port; - return(0xff); -} - -static REG8 IOINPCALL gdc_ia4(UINT port) { - - (void)port; - return(gdcs.disp); -} - -static REG8 IOINPCALL gdc_ia6(UINT port) { - - (void)port; - return(gdcs.access); -} - - -// ---- I/O palette - -static void IOOUTCALL gdc_oa8(UINT port, REG8 dat) { - - if (gdc.analog & ((1 << GDCANALOG_256) + (1 << GDCANALOG_16))) { - gdc.palnum = dat; - } - else { - gdc_setdegpalpack(3, dat); - } - (void)port; -} - -static void IOOUTCALL gdc_oaa(UINT port, REG8 dat) { - -#if defined(SUPPORT_PC9821) - if (gdc.analog & (1 << GDCANALOG_256)) { - gdcs.palchange = GDCSCRN_REDRAW; - gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 0] = dat; - } - else -#endif - if (gdc.analog & (1 << GDCANALOG_16)) { -#if defined(SUPPORT_PC9821) - gdc.anareg[(gdc.palnum * 3) + 0] = dat; -#endif - gdc_setanalogpal(gdc.palnum & 15, offsetof(RGB32, p.g), dat); - } - else { - gdc_setdegpalpack(1, dat); - } - (void)port; -} - -static void IOOUTCALL gdc_oac(UINT port, REG8 dat) { - -#if defined(SUPPORT_PC9821) - if (gdc.analog & (1 << GDCANALOG_256)) { - gdcs.palchange = GDCSCRN_REDRAW; - gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 1] = dat; - } - else -#endif - if (gdc.analog & (1 << GDCANALOG_16)) { -#if defined(SUPPORT_PC9821) - gdc.anareg[(gdc.palnum * 3) + 1] = dat; -#endif - gdc_setanalogpal(gdc.palnum & 15, offsetof(RGB32, p.r), dat); - } - else { - gdc_setdegpalpack(2, dat); - } - (void)port; -} - -static void IOOUTCALL gdc_oae(UINT port, REG8 dat) { - -#if defined(SUPPORT_PC9821) - if (gdc.analog & (1 << GDCANALOG_256)) { - gdcs.palchange = GDCSCRN_REDRAW; - gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 2] = dat; - } - else -#endif - if (gdc.analog & (1 << GDCANALOG_16)) { -#if defined(SUPPORT_PC9821) - gdc.anareg[(gdc.palnum * 3) + 2] = dat; -#endif - gdc_setanalogpal(gdc.palnum & 15, offsetof(RGB32, p.b), dat); - } - else { - gdc_setdegpalpack(0, dat); - } - (void)port; -} - -#if defined(SUPPORT_PC9821) -static REG8 IOINPCALL gdc_ia8(UINT port) { - - if (gdc.analog & ((1 << GDCANALOG_256) + (1 << GDCANALOG_16))) { - return(gdc.palnum); - } - (void)port; - return(gdc.degpal[3]); -} - -static REG8 IOINPCALL gdc_iaa(UINT port) { - - if (gdc.analog & (1 << GDCANALOG_256)) { - return(gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 0]); - } - if (gdc.analog & (1 << GDCANALOG_16)) { - return(gdc.anareg[(gdc.palnum * 3) + 0]); - } - (void)port; - return(gdc.degpal[1]); -} - -static REG8 IOINPCALL gdc_iac(UINT port) { - - if (gdc.analog & (1 << GDCANALOG_256)) { - return(gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 1]); - } - if (gdc.analog & (1 << GDCANALOG_16)) { - return(gdc.anareg[(gdc.palnum * 3) + 1]); - } - (void)port; - return(gdc.degpal[2]); -} - -static REG8 IOINPCALL gdc_iae(UINT port) { - - if (gdc.analog & (1 << GDCANALOG_256)) { - return(gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 2]); - } - if (gdc.analog & (1 << GDCANALOG_16)) { - return(gdc.anareg[(gdc.palnum * 3) + 2]); - } - (void)port; - return(gdc.degpal[0]); -} -#endif - - -// ---- extend - -#if defined(SUPPORT_PC9821) -static void IOOUTCALL gdc_o9a0(UINT port, REG8 dat) { - - gdc.ff2 = dat; - (void)port; -} - -static REG8 IOINPCALL gdc_i9a0(UINT port) { - - REG8 ret; - - ret = 0; - switch(gdc.ff2) { - case 0x00: - ret = 0xff; - break; - - case 0x01: - ret = (gdc.mode1 >> 1) & 1; - break; - - case 0x02: - ret = (gdc.mode1 >> 4) & 1; - break; - - case 0x03: - ret = (gdc.mode1 >> 7) & 1; - break; - - case 0x04: - ret = (gdc.mode2 >> 0) & 1; - break; - - case 0x05: - ret = (gdc.display >> GDCDISP_PLAZMA) & 1; - break; - - case 0x07: - ret = (gdc.mode2 >> 2) & 1; - break; - - case 0x08: - ret = (gdc.mode2 >> 3) & 1; - break; - - case 0x09: - ret = (gdc.clock >> 0) & 1; - break; - - case 0x0a: - ret = (gdc.analog >> GDCANALOG_256) & 1; - break; - - case 0x0b: - ret = 1; - break; - - case 0x0d: - ret = (gdc.analog >> GDCANALOG_256E) & 1; - break; - } - ret |= (gdc.clock & 2); - (void)port; - return(ret); -} -#endif - -#if defined(SUPPORT_CRT31KHZ) -static void IOOUTCALL gdc_o9a8(UINT port, REG8 dat) { - - if ((gdc.display ^ (dat << GDCDISP_31)) & (1 << GDCDISP_31)) { - gdc.display ^= (1 << GDCDISP_31); - gdcs.textdisp |= GDCSCRN_EXT; - } - (void)port; -} - -static REG8 IOINPCALL gdc_i9a8(UINT port) { - - (void)port; - return((gdc.display >> GDCDISP_31) & 1); -} -#endif - - -// ---- I/F - -static const IOOUT gdco60[8] = { - gdc_o60, gdc_o62, gdc_o64, NULL, - gdc_o68, gdc_o6a, NULL, gdc_o6e}; - -static const IOOUT gdcoa0[8] = { - gdc_oa0, gdc_oa2, gdc_oa4, gdc_oa6, - gdc_oa8, gdc_oaa, gdc_oac, gdc_oae}; - -static const IOINP gdci60[8] = { - gdc_i60, gdc_i62, NULL, NULL, - gdc_i68, gdc_i6a, NULL, NULL}; - -#if defined(SUPPORT_PC9821) -static const IOINP gdcia0[8] = { - gdc_ia0, gdc_ia2, gdc_ia4, gdc_ia6, - gdc_ia8, gdc_iaa, gdc_iac, gdc_iae}; -#else -static const IOINP gdcia0[8] = { - gdc_ia0, gdc_ia2, gdc_ia4, gdc_ia6, - NULL, NULL, NULL, NULL}; -#endif - - -void gdc_biosreset(void) { - -#if defined(SUPPORT_PC9821) - UINT i; - UINT j; - UINT8 tmp; - UINT8 *pal; -#endif - - if (!(pccore.dipsw[0] & 0x01)) { - gdc.mode1 = 0x98; - gdc.m.para[GDC_CSRFORM + 0] = 0x0f; - gdc.m.para[GDC_CSRFORM + 1] = 0xc0; - gdc.m.para[GDC_CSRFORM + 2] = 0x7b; - CopyMemory(gdc.m.para + GDC_SYNC, defsyncm24, 8); - gdc.s.para[GDC_CSRFORM + 0] = 1; - CopyMemory(gdc.s.para + GDC_SYNC, defsyncs24, 8); - } - else { - gdc.crt15khz = 3; - gdc.mode1 = 0x80; - gdc.m.para[GDC_CSRFORM + 0] = 0x07; - gdc.m.para[GDC_CSRFORM + 1] = 0xc0; - gdc.m.para[GDC_CSRFORM + 2] = 0x3b; - CopyMemory(gdc.m.para + GDC_SYNC, defsyncm15, 8); - CopyMemory(gdc.s.para + GDC_SYNC, defsyncs15, 8); - } - if (pccore.dipsw[0] & 0x80) { - gdc.s.para[GDC_SYNC] = 0x16; - } - gdc_vectreset(&gdc.m); - gdc_vectreset(&gdc.s); - - gdc.clock = 0; - gdc.m.para[GDC_PITCH] = 80; - gdc.s.para[GDC_PITCH] = 40; - - gdc.bitac = 0xff; - - // vram bank - gdcs.disp = 0; - gdcs.access = 0; - gdc.analog &= ~(1 << GDCANALOG_16); - gdcs.palchange = GDCSCRN_REDRAW; - - gdc.mode2 &= ~(1 << 0); - gdc.mode2 &= ~(1 << 2); - gdc.mode2 &= ~(1 << 3); - gdcs.mode2 = gdc.mode2; - - vramop.operate &= ~(1 << VOPBIT_ACCESS); - vramop.operate &= ~(1 << VOPBIT_EGC); - vramop.operate &= ~(1 << VOPBIT_ANALOG); -#if defined(SUPPORT_PC9821) - gdc.analog &= ~(1 << (GDCANALOG_256)); - vramop.operate &= ~(1 << VOPBIT_VGA); -#endif - MEMM_VRAM(vramop.operate); - - // palette - CopyMemory(gdc.degpal, defdegpal, 4); - if (gdc.display & (1 << GDCDISP_ANALOG)) { - gdc_setanalogpalall(defanapal); - } -#if defined(SUPPORT_PC9821) - pal = gdc.anareg + (16 * 3); - for (i=0; i<256; i+=8) { - tmp = (UINT8)((i)?(i - 4):0); - pal[0] = tmp; - pal[1] = tmp; - pal[2] = tmp; - pal += 4; - for (j=1; j<8; j++) { - pal[0] = (UINT8)((i + 7) * ((j >> 2) & 1)); - pal[1] = (UINT8)((i + 7) * ((j >> 1) & 1)); - pal[2] = (UINT8)((i + 7) * ((j >> 0) & 1)); - pal += 4; - } - } -#endif - gdcs.textdisp = GDCSCRN_ALLDRAW2 | GDCSCRN_EXT; - gdcs.grphdisp = GDCSCRN_ALLDRAW2 | GDCSCRN_EXT; - gdcs.palchange = GDCSCRN_REDRAW; - pcstat.screenupdate |= 2; -} - -void gdc_reset(const NP2CFG *pConfig) { - - ZeroMemory(&gdc, sizeof(gdc)); - ZeroMemory(&gdcs, sizeof(gdcs)); - -#if !defined(SUPPORT_PC9821) - if (pConfig->color16 & 1) -#endif - { - gdc.display |= (1 << GDCDISP_ANALOG); - } - if (!(pccore.dipsw[0] & 0x04)) { // dipsw1-3 on - gdc.display |= (1 << GDCDISP_PLAZMA2); - } - gdc_biosreset(); - - (void)pConfig; -} - -void gdc_bind(void) { - - gdc_updateclock(); -#if defined(SUPPORT_PC9821) - iocore_attachout(0x09a0, gdc_o9a0); - iocore_attachinp(0x09a0, gdc_i9a0); -#endif -#if defined(SUPPORT_CRT31KHZ) - iocore_attachout(0x09a8, gdc_o9a8); - iocore_attachinp(0x09a8, gdc_i9a8); -#endif - iocore_attachsysoutex(0x0060, 0x0cf1, gdco60, 8); - iocore_attachsysinpex(0x0060, 0x0cf1, gdci60, 8); - iocore_attachsysoutex(0x00a0, 0x0cf1, gdcoa0, 8); - iocore_attachsysinpex(0x00a0, 0x0cf1, gdcia0, 8); -} - +#include +#include +#include +#include +#include +#include "gdc_cmd.tbl" +#include +#include +#include +#include +#if defined(BIOS_IO_EMULATION) +#include +#endif +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif + +#if !defined(CPUCORE_IA32) +#define SEARCH_SYNC +#endif +#define TURE_SYNC + +typedef struct { + UINT32 clock; + UINT minx; + UINT maxx; + UINT miny; + UINT maxy; +} GDCCLK; + +// 31kHzの時の動作クロックが不明… +static const GDCCLK gdcclk[] = { + {14318180 / 8, 112 - 8, 112 + 8, 200, 300}, + {21052600 / 8, 106 - 6, 106 + 6, 400, 575}, + {25260000 / 8, 100 - 8, 100 + 8, 400, 575}}; + + +typedef struct { + UINT8 master[8]; + UINT8 slave[8]; +} GDCSYNC; + +static const UINT8 defsyncm15[8] = {0x10,0x4e,0x07,0x25,0x0d,0x0f,0xc8,0x94}; +static const UINT8 defsyncs15[8] = {0x06,0x26,0x03,0x11,0x86,0x0f,0xc8,0x94}; + +static const UINT8 defsyncm24[8] = {0x10,0x4e,0x07,0x25,0x07,0x07,0x90,0x65}; +static const UINT8 defsyncs24[8] = {0x06,0x26,0x03,0x11,0x83,0x07,0x90,0x65}; + +#if 0 +static const UINT8 defsyncm31[8] = {0x10,0x4e,0x47,0x0c,0x07,0x0d,0x90,0x89}; +static const UINT8 defsyncs31[8] = {0x06,0x26,0x41,0x0c,0x83,0x0d,0x90,0x89}; +#endif /* 0 */ + + +static const UINT8 defdegpal[4] = {0x04,0x15,0x26,0x37}; +static const UINT16 defanapal[16] = { + 0x000,0x007,0x070,0x077,0x700,0x707,0x770,0x777, + 0x444,0x00f,0x0f0,0x0ff,0xf00,0xf0f,0xff0,0xfff}; + + +void gdc_setdegitalpal(int color, REG8 value) { + + if (color & 4) { + color &= 3; + value &= 0x0f; + if ((gdc.degpal[color] ^ value) & 0x07) { + gdcs.palchange = GDCSCRN_REDRAW; + } + gdc.degpal[color] &= 0xf0; + gdc.degpal[color] |= value; + } + else { + color &= 3; + value <<= 4; + if ((gdc.degpal[color] ^ value) & 0x70) { + gdcs.palchange = GDCSCRN_REDRAW; + } + gdc.degpal[color] &= 0x0f; + gdc.degpal[color] |= value; + } +} + +void gdc_setdegpalpack(int color, REG8 value) { + + if ((gdc.degpal[color] ^ value) & 0x77) { + gdcs.palchange = GDCSCRN_REDRAW; + } + gdc.degpal[color] = (UINT8)value; +} + +void gdc_setanalogpal(int color, int rgb, REG8 value) { + + UINT8 *ptr; + PAL1EVENT *event; + + ptr = ((UINT8 *)(gdc.anapal + color)) + rgb; + if (((*ptr) ^ value) & 0x0f) { + gdcs.palchange = GDCSCRN_REDRAW; + if (palevent.events < PALEVENTMAX) { + if (!gdc.vsync) { + event = palevent.event + palevent.events; + event->clock = g_nevent.item[NEVENT_FLAMES].clock - + (CPU_BASECLOCK - CPU_REMCLOCK); + event->color = (UINT16)((color * sizeof(RGB32)) + rgb); + event->value = (UINT8)value; + palevent.events++; + } + else { + palevent.vsyncpal = 1; + } + } + } + *ptr = value; +} + +void gdc_setanalogpalall(const UINT16 *paltbl) { + + UINT c; + UINT pal; + + for (c=0; c<16; c++) { + pal = *paltbl++; +#if defined(SUPPORT_PC9821) + gdc.anareg[(c * 3) + 0] = (pal >> 8) & 15; + gdc.anareg[(c * 3) + 1] = (pal >> 4) & 15; + gdc.anareg[(c * 3) + 2] = (pal >> 0) & 15; +#endif + gdc_setanalogpal(c, offsetof(RGB32, p.g), (REG8)((pal >> 8) & 15)); + gdc_setanalogpal(c, offsetof(RGB32, p.r), (REG8)((pal >> 4) & 15)); + gdc_setanalogpal(c, offsetof(RGB32, p.b), (REG8)((pal >> 0) & 15)); + } +} + + +void gdc_paletteinit(void) { + + int c; + + CopyMemory(gdc.degpal, defdegpal, 4); + for (c=0; c<8; c++) { + gdc.anapal[c+0].p.b = ((c&1)?0x0f:0); + gdc.anapal[c+8].p.b = ((c&1)?0x0a:0); + gdc.anapal[c+0].p.r = ((c&2)?0x0f:0); + gdc.anapal[c+8].p.r = ((c&2)?0x0a:0); + gdc.anapal[c+0].p.g = ((c&4)?0x0f:0); + gdc.anapal[c+8].p.g = ((c&4)?0x0a:0); + } + gdc.anapal[8].p.b = 0x07; + gdc.anapal[8].p.r = 0x07; + gdc.anapal[8].p.g = 0x07; + gdcs.palchange = GDCSCRN_REDRAW; +} + +#if defined(SUPPORT_PC9821) +void gdc_analogext(BOOL extend) { + +#if defined(SUPPORT_CRT31KHZ) + if (extend) { + gdc.analog |= (1 << GDCANALOG_256); + vramop.operate |= (1 << VOPBIT_VGA); +#if defined(SUPPORT_IA32_HAXM) + i386hax_vm_setmemoryarea(vramex + ((vramop.mio1[0] & 15) << 15), 0xA8000, 0x8000); + i386hax_vm_setmemoryarea(vramex + ((vramop.mio1[2] & 15) << 15), 0xB0000, 0x8000); +#endif + } + else { + gdc.analog &= ~(1 << (GDCANALOG_256)); + vramop.operate &= ~(1 << VOPBIT_VGA); +#if defined(SUPPORT_IA32_HAXM) + i386hax_vm_removememoryarea(vramex + ((vramop.mio1[0] & 15) << 15), 0xA8000, 0x8000); + i386hax_vm_removememoryarea(vramex + ((vramop.mio1[2] & 15) << 15), 0xB0000, 0x8000); +#endif + } + gdcs.palchange = GDCSCRN_REDRAW; + gdcs.grphdisp |= GDCSCRN_EXT | GDCSCRN_ALLDRAW2; + MEMM_VRAM(vramop.operate); +#endif +} +#endif + + +// -------------------------------------------------------------------------- + +void gdc_vectreset(GDCDATA item) { + + item->para[GDC_VECTW+1] = 0x00; + item->para[GDC_VECTW+2] = 0x00; + item->para[GDC_VECTW+3] = 0x08; + item->para[GDC_VECTW+4] = 0x00; + item->para[GDC_VECTW+5] = 0x08; + item->para[GDC_VECTW+6] = 0x00; + item->para[GDC_VECTW+7] = 0xff; + item->para[GDC_VECTW+8] = 0xff; + item->para[GDC_VECTW+9] = 0xff; + item->para[GDC_VECTW+10] = 0xff; +} + +static void vectdraw(void) { + + UINT32 csrw; +const GDCVECT *vect; + REG16 textw; + REG8 ope; + + csrw = LOADINTELDWORD(gdc.s.para + GDC_CSRW); + vect = (GDCVECT *)(gdc.s.para + GDC_VECTW); + textw = LOADINTELWORD(gdc.s.para + GDC_TEXTW); + ope = gdc.s.para[GDC_WRITE]; + + if (!(vect->ope & 0x78)) { + gdcsub_vectp(csrw, vect, textw, ope); // Single Dot Writing? + } + if (vect->ope & 0x08) { + gdcsub_vectl(csrw, vect, textw, ope); + } + if (vect->ope & 0x10) { // undocumented + gdcsub_vectt(csrw, vect, textw, ope); + } + if (vect->ope & 0x20) { + gdcsub_vectc(csrw, vect, textw, ope); + } + if (vect->ope & 0x40) { + gdcsub_vectr(csrw, vect, textw, ope); + } + gdc_vectreset(&gdc.s); +} + +static void textdraw(void) { + + UINT32 csrw; +const GDCVECT *vect; + REG16 textw; + REG8 ope; + + csrw = LOADINTELDWORD(gdc.s.para + GDC_CSRW); + vect = (GDCVECT *)(gdc.s.para + GDC_VECTW); + textw = gdc.s.para[GDC_TEXTW + 7]; + textw = (textw << 8) + textw; + ope = gdc.s.para[GDC_WRITE]; + + if (!(vect->ope & 0x78)) { + gdcsub_vectp(csrw, vect, textw, ope); // Single Dot Writing? + } + if (vect->ope & 0x08) { // undocumented + gdcsub_vectl(csrw, vect, textw, ope); + } + if (vect->ope & 0x10) { + gdcsub_text(csrw, vect, gdc.s.para + GDC_TEXTW, ope); + } + if (vect->ope & 0x20) { // undocumented + gdcsub_vectc(csrw, vect, textw, ope); + } + if (vect->ope & 0x40) { // undocumented + gdcsub_vectr(csrw, vect, textw, ope); + } + gdc_vectreset(&gdc.s); +} + +void gdc_work(int id) { + + GDCDATA item; + UINT8 *dispflag; + UINT i; + UINT8 data; + + item = (id == GDCWORK_MASTER)?&gdc.m:&gdc.s; + dispflag = (id == GDCWORK_MASTER)?&gdcs.textdisp:&gdcs.grphdisp; + + for (i=0; icnt; i++) { + data = (UINT8)item->fifo[i]; + if (item->fifo[i] & 0xff00) { + item->cmd = data; + item->paracb = 0; + if ((data & 0x60) == 0x20) { + item->para[GDC_WRITE] = data; + switch(data & 0x18) { + case 0x00: + item->rcv = 2; + item->paracb = 1; + break; + + case 0x10: + case 0x18: + item->rcv = 1; + item->paracb = 1; + break; + + default: + item->rcv = 0; + break; + } + item->ptr = GDC_CODE; + item->snd = 0; + continue; + } + switch(data) { + case CMD_START_: + case CMD_START: + case CMD_SYNC_ON: + (*dispflag) |= GDCSCRN_ENABLE | GDCSCRN_ALLDRAW2; + pcstat.screenupdate |= 2; + break; + + case CMD_STOP_: + case CMD_STOP: + case CMD_SYNC_OFF: + (*dispflag) &= (~GDCSCRN_ENABLE); +// (*dispflag) |= GDCSCRN_ALLDRAW2; + pcstat.screenupdate |= 2; + break; + + case CMD_VECTE: + if (id != GDCWORK_MASTER) { + vectdraw(); + } + break; + + case CMD_TEXTE: + if (id != GDCWORK_MASTER) { + textdraw(); + } + break; + } + item->ptr = gdc_cmd[data].pos; + item->rcv = gdc_cmd[data].outdatas; + item->snd = gdc_cmd[data].indatas; + if (item->snd) { + switch(item->ptr) { + case GDC_CSRR: + item->para[GDC_CSRR+0] = item->para[GDC_CSRW+0]; + item->para[GDC_CSRR+1] = item->para[GDC_CSRW+1]; + item->para[GDC_CSRR+2] = item->para[GDC_CSRW+2] & 3; + item->para[GDC_CSRR+3] = 0; + item->para[GDC_CSRR+4] = 0; + break; + } + } + } + else if (item->rcv) { + if (item->para[item->ptr] != data) { + item->para[item->ptr] = data; + (*dispflag) |= gdc_dirtyflag[id][item->ptr]; + } + (item->ptr)++; + (item->rcv)--; + if ((!(item->rcv)) && (id == GDCWORK_SLAVE) && + (((item->cmd) & 0xe4) == 0x20)) { + gdcsub_write(); + item->paracb = 0; + } + } + } + item->cnt = 0; +} + +// BIOSとかで弄った時にリセット +void gdc_forceready(int id) { + + GDCDATA item; + item = (id == GDCWORK_MASTER)?&gdc.m:&gdc.s; + if (item->cnt) { + gdc_work(id); + } + item->rcv = 0; + item->snd = 0; +} + + +void gdc_updateclock(void) { + + UINT tmp; + UINT cr; + UINT hfbs; + UINT vfbs; + UINT lf; + UINT x; + UINT y; + UINT cnt; +const GDCCLK *clk; + UINT32 hclock; + + cr = gdc.m.para[GDC_SYNC + 1] + 2; + tmp = LOADINTELWORD(gdc.m.para + GDC_SYNC + 2); + hfbs = tmp & 0x1f; // HS + hfbs += tmp >> 10; // HFP + vfbs = (tmp >> 5) & 0x1f; // VS + hfbs += gdc.m.para[GDC_SYNC + 4] & 0x3f; // HFP + vfbs += gdc.m.para[GDC_SYNC + 5] & 0x3f; // VFP + tmp = LOADINTELWORD(gdc.m.para + GDC_SYNC + 6); + lf = ((tmp - 1) & 0x3ff) + 1; + vfbs += tmp >> 10; // VBP + + hfbs += 3; + x = cr + hfbs; + if (!vfbs) { + vfbs = 1; + } + y = lf + vfbs; +// TRACEOUT(("h %d:%d / v %d:%d", cr, x, lf, y)); + +#if defined(SUPPORT_CRT31KHZ) + if (gdc.display & (1 << GDCDISP_31)) { + clk = gdcclk + 2; + } + else +#endif + if (!(gdc.crt15khz & 2)) { // 24.83±300Hz + clk = gdcclk + 1; + } + else { // 15.98±300Hz + clk = gdcclk; + } + + if (x < clk->minx) { + cr = (clk->minx * cr) / x; + x = clk->minx; + } + else if (x > clk->maxx) { + cr = (clk->maxx * cr) / x; + x = clk->maxx; + } + if (y < clk->miny) { + lf = (clk->miny * lf) / y; + y = clk->miny; + } + else if (y > clk->maxy) { + lf = (clk->maxy * lf) / y; + y = clk->maxy; + } + hclock = clk->clock / x; + gdc.hclock = hclock; + gdc.vclock = hclock * 10 / y; + cnt = (pccore.baseclock * y) / hclock; + cnt *= pccore.multiple; + gdc.rasterclock = cnt / y; + gdc.hsyncclock = (gdc.rasterclock * cr) / x; + gdc.dispclock = gdc.rasterclock * lf; + gdc.vsyncclock = cnt - gdc.dispclock; + timing_setrate(y, hclock); +} + +void gdc_restorekacmode(void) { + + UINT8 bit; + + bit = (((!np2cfg.uPD72020) && (gdc.mode1 & 0x20))?0x00:0xff); + if (gdc.bitac != bit) { + gdc.bitac = bit; + gdcs.textdisp |= GDCSCRN_ALLDRAW2; + } +} + + +// ---- I/O master + +static void IOOUTCALL gdc_o60(UINT port, REG8 dat) { + + if (gdc.m.cnt < GDCCMD_MAX) { + gdc.m.fifo[gdc.m.cnt++] = dat; + } + (void)port; +} + +static void IOOUTCALL gdc_o62(UINT port, REG8 dat) { + + if (gdc.m.cnt < GDCCMD_MAX) { + gdc.m.fifo[gdc.m.cnt++] = 0x100 | dat; + } + gdc_work(GDCWORK_MASTER); + (void)port; +} + +static void IOOUTCALL gdc_o64(UINT port, REG8 dat) { + + gdc.vsyncint = 1; + (void)port; + (void)dat; +} + +static void IOOUTCALL gdc_o68(UINT port, REG8 dat) { + + REG8 bit; + + if (!(dat & 0xf0)) { + bit = 1 << ((dat >> 1) & 7); + if (dat & 1) { + gdc.mode1 |= bit; + } + else { + gdc.mode1 &= ~bit; + } + if (bit & (0x01 | 0x04 | 0x10)) { + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + } + else if (bit == 0x02) { + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + gdcs.palchange = GDCSCRN_REDRAW; + } + else if (bit == 0x08) { + gdcs.textdisp |= GDCSCRN_ALLDRAW2; + } + else if (bit == 0x20) { + gdc_restorekacmode(); + } + else if (bit == 0x80) { + pcstat.screenupdate |= 2; + } + gdcs.msw_accessable = gdc.mode1 & 0x40; + } + (void)port; +} + +static void IOOUTCALL gdc_o6a(UINT port, REG8 dat) { + + REG8 bit; + + if (!(dat & 0xf8)) { + bit = (dat >> 1) & 3; + dat &= 1; + if (!(((gdc.mode2 >> bit) ^ dat) & 1)) { + return; + } + gdc.mode2 ^= (1 << bit); + switch(bit) { + case 0: + if (gdc.display & (1 << GDCDISP_ANALOG)) { + gdc.analog &= ~(1 << GDCANALOG_16); + gdc.analog |= (dat << GDCANALOG_16); + gdcs.palchange = GDCSCRN_REDRAW; + vramop.operate &= ~(1 << VOPBIT_ANALOG); + vramop.operate |= dat << VOPBIT_ANALOG; + MEMM_VRAM(vramop.operate); + } + break; + + case 2: + if ((gdc.mode2 & 0x08) && (grcg.chip == 3)) { + vramop.operate &= ~(1 << VOPBIT_EGC); + vramop.operate |= dat << VOPBIT_EGC; + MEMM_VRAM(vramop.operate); + } + break; + } + gdcs.mode2 = gdc.mode2; + } + else { + switch(dat) { +#if defined(SUPPORT_PC9821) +#if defined(SUPPORT_CRT31KHZ) + case 0x20: + if (gdc.mode2 & 0x08) { + gdc_analogext(FALSE); + } + break; + + case 0x21: + if (gdc.mode2 & 0x08) { + gdc_analogext(TRUE); + } + break; + case 0x68: + gdc.analog &= ~(1 << GDCANALOG_256E); + break; + + case 0x69: + gdc.analog |= (1 << GDCANALOG_256E); + break; +#endif +#endif + case 0x40: + case 0x80: // EPSON? + gdc.display &= ~(1 << GDCDISP_PLAZMA); + gdcs.textdisp |= GDCSCRN_EXT; + break; + + case 0x41: + case 0x81: // EPSON? + gdc.display |= (1 << GDCDISP_PLAZMA); + gdcs.textdisp |= GDCSCRN_EXT; + break; + + case 0x82: + gdc.clock &= ~1; + gdcs.grphdisp |= GDCSCRN_EXT; + break; + + case 0x83: + gdc.clock |= 1; + gdcs.grphdisp |= GDCSCRN_EXT; + break; + + case 0x84: + gdc.clock &= ~2; + gdcs.grphdisp |= GDCSCRN_EXT; + break; + + case 0x85: + gdc.clock |= 2; + gdcs.grphdisp |= GDCSCRN_EXT; + break; + } + } + (void)port; +} + +static void IOOUTCALL gdc_o6e(UINT port, REG8 dat) { + + switch(dat) { + case 0: + gdc.crt15khz &= ~1; + gdcs.textdisp |= GDCSCRN_ALLDRAW2; + break; + + case 1: + gdc.crt15khz |= 1; + gdcs.textdisp |= GDCSCRN_ALLDRAW2; + break; + } + (void)port; +} + +static REG8 IOINPCALL gdc_i60(UINT port) { + + REG8 ret; + SINT32 remain; + + ret = 0x80 | gdc.vsync; // | m_drawing; + remain = nevent_getremain(NEVENT_FLAMES); + if (remain >= 0) { + if ((remain % gdc.rasterclock) < gdc.hsyncclock) { + ret |= 0x40; + } + } + if (gdc.m.snd) { + ret |= 0x01; + } + if (gdc.m.cnt >= GDCCMD_MAX) { + ret |= 0x02; + } + if (!gdc.m.cnt) { + ret |= 0x04; + } + else { + gdc_work(GDCWORK_MASTER); + } +#ifdef SEARCH_SYNC // ToDo: フェッチキューを参照するように… + if ((CPU_INPADRS) && (CPU_REMCLOCK >= 5)) { + UINT32 addr; + UINT16 jadr; + UINT16 memv; + addr = CPU_INPADRS; + jadr = 0xfa74; + memv = MEML_READ16(addr); + while((memv == 0x00eb) || (memv == 0x5fe6)) { + jadr -= 0x200; + addr += 2; + memv = MEML_READ16(addr); + } + if ((memv == 0x20a8) || (memv == 0x2024)) { + memv = MEML_READ16(addr + 2); + if (memv == jadr) { // je + if (!gdc.vsync) { + CPU_REMCLOCK = -1; + } + } + else if (memv == (jadr + 1)) { // jne + if (gdc.vsync) { + CPU_REMCLOCK = -1; + } + } + } + } +#endif +#ifdef TURE_SYNC // クロックイベントの誤差修正 + if (g_nevent.item[NEVENT_FLAMES].clock < (CPU_BASECLOCK - CPU_REMCLOCK)) { + ret ^= 0x20; + } +#endif + (void)port; + return(ret); +} + +static REG8 IOINPCALL gdc_i62(UINT port) { + + if (gdc.m.snd) { + gdc.m.snd--; + return(gdc.m.para[gdc.m.ptr++]); + } + (void)port; + return(0xff); +} + +static REG8 IOINPCALL gdc_i68(UINT port) { + + (void)port; + return(gdc.mode1); +} + +static REG8 IOINPCALL gdc_i6a(UINT port) { + + (void)port; + return(gdc.mode2); +} + + +// ---- I/O slave + +static void IOOUTCALL gdc_oa0(UINT port, REG8 dat) { + + if (gdc.s.cnt < GDCCMD_MAX) { + gdc.s.fifo[gdc.s.cnt++] = dat; + } +// TRACEOUT(("GDC-B %.2x [%.4x:%.4x]", dat, CPU_CS, CPU_IP)); + if (gdc.s.paracb) { + gdc_work(GDCWORK_SLAVE); + } + (void)port; +} + +static void IOOUTCALL gdc_oa2(UINT port, REG8 dat) { + + if (gdc.s.cnt < GDCCMD_MAX) { + gdc.s.fifo[gdc.s.cnt++] = 0x100 | dat; + } +// TRACEOUT(("GDC-A %.2x", dat)); + gdc_work(GDCWORK_SLAVE); + (void)port; +} + +static void IOOUTCALL gdc_oa4(UINT port, REG8 dat) { + + if ((gdcs.disp ^ dat) & 1) { + gdcs.disp = dat & 1; + pcstat.screenupdate |= 2; + } + (void)port; +} + +static void IOOUTCALL gdc_oa6(UINT port, REG8 dat) { + + dat = dat & 1; + if (gdcs.access != dat) { + gdcs.access = (UINT8)dat; + vramop.operate &= ~(1 << VOPBIT_ACCESS); + vramop.operate |= dat << VOPBIT_ACCESS; + MEMM_VRAM(vramop.operate); + } + (void)port; +} + +static REG8 IOINPCALL gdc_ia0(UINT port) { + + REG8 ret; + SINT32 remain; + + ret = 0x80 | gdc.vsync | gdc.s_drawing; + remain = nevent_getremain(NEVENT_FLAMES); + if (remain >= 0) { + if ((remain % gdc.rasterclock) < (gdc.hsyncclock)) { + ret |= 0x40; + } + } + if (gdc.s.snd) { + ret |= 0x01; + } + if (gdc.s.cnt >= GDCCMD_MAX) { + ret |= 0x02; + } + if (!gdc.s.cnt) { + ret |= 0x04; + } + else { + gdc_work(GDCWORK_SLAVE); + } +#ifdef SEARCH_SYNC + if ((CPU_INPADRS) && (CPU_REMCLOCK >= 5)) { + UINT32 addr; + UINT16 jadr; + UINT16 memv; + addr = CPU_INPADRS; + jadr = 0xfa74; + memv = MEML_READ16(addr); + while((memv == 0x00eb) || (memv == 0x5fe6)) { + jadr -= 0x200; + addr += 2; + memv = MEML_READ16(addr); + } + if ((memv == 0x20a8) || (memv == 0x2024)) { + memv = MEML_READ16(addr + 2); + if (memv == jadr) { // je + if (!gdc.vsync) { + CPU_REMCLOCK = -1; + } + } + else if (memv == (jadr + 1)) { // jne + if (gdc.vsync) { + CPU_REMCLOCK = -1; + } + } + } + } +#endif +#ifdef TURE_SYNC // クロックイベントの誤差修正 + if (g_nevent.item[NEVENT_FLAMES].clock < (CPU_BASECLOCK - CPU_REMCLOCK)) { + ret ^= 0x20; + } +#endif + (void)port; + return(ret); +} + +static REG8 IOINPCALL gdc_ia2(UINT port) { + + if (gdc.s.snd) { + gdc.s.snd--; + return(gdc.s.para[gdc.s.ptr++]); + } + (void)port; + return(0xff); +} + +static REG8 IOINPCALL gdc_ia4(UINT port) { + + (void)port; + return(gdcs.disp); +} + +static REG8 IOINPCALL gdc_ia6(UINT port) { + + (void)port; + return(gdcs.access); +} + + +// ---- I/O palette + +static void IOOUTCALL gdc_oa8(UINT port, REG8 dat) { + + if (gdc.analog & ((1 << GDCANALOG_256) + (1 << GDCANALOG_16))) { + gdc.palnum = dat; + } + else { + gdc_setdegpalpack(3, dat); + } + (void)port; +} + +static void IOOUTCALL gdc_oaa(UINT port, REG8 dat) { + +#if defined(SUPPORT_PC9821) + if (gdc.analog & (1 << GDCANALOG_256)) { + gdcs.palchange = GDCSCRN_REDRAW; + gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 0] = dat; + } + else +#endif + if (gdc.analog & (1 << GDCANALOG_16)) { +#if defined(SUPPORT_PC9821) + gdc.anareg[(gdc.palnum * 3) + 0] = dat; +#endif + gdc_setanalogpal(gdc.palnum & 15, offsetof(RGB32, p.g), dat); + } + else { + gdc_setdegpalpack(1, dat); + } + (void)port; +} + +static void IOOUTCALL gdc_oac(UINT port, REG8 dat) { + +#if defined(SUPPORT_PC9821) + if (gdc.analog & (1 << GDCANALOG_256)) { + gdcs.palchange = GDCSCRN_REDRAW; + gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 1] = dat; + } + else +#endif + if (gdc.analog & (1 << GDCANALOG_16)) { +#if defined(SUPPORT_PC9821) + gdc.anareg[(gdc.palnum * 3) + 1] = dat; +#endif + gdc_setanalogpal(gdc.palnum & 15, offsetof(RGB32, p.r), dat); + } + else { + gdc_setdegpalpack(2, dat); + } + (void)port; +} + +static void IOOUTCALL gdc_oae(UINT port, REG8 dat) { + +#if defined(SUPPORT_PC9821) + if (gdc.analog & (1 << GDCANALOG_256)) { + gdcs.palchange = GDCSCRN_REDRAW; + gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 2] = dat; + } + else +#endif + if (gdc.analog & (1 << GDCANALOG_16)) { +#if defined(SUPPORT_PC9821) + gdc.anareg[(gdc.palnum * 3) + 2] = dat; +#endif + gdc_setanalogpal(gdc.palnum & 15, offsetof(RGB32, p.b), dat); + } + else { + gdc_setdegpalpack(0, dat); + } + (void)port; +} + +#if defined(SUPPORT_PC9821) +static REG8 IOINPCALL gdc_ia8(UINT port) { + + if (gdc.analog & ((1 << GDCANALOG_256) + (1 << GDCANALOG_16))) { + return(gdc.palnum); + } + (void)port; + return(gdc.degpal[3]); +} + +static REG8 IOINPCALL gdc_iaa(UINT port) { + + if (gdc.analog & (1 << GDCANALOG_256)) { + return(gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 0]); + } + if (gdc.analog & (1 << GDCANALOG_16)) { + return(gdc.anareg[(gdc.palnum * 3) + 0]); + } + (void)port; + return(gdc.degpal[1]); +} + +static REG8 IOINPCALL gdc_iac(UINT port) { + + if (gdc.analog & (1 << GDCANALOG_256)) { + return(gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 1]); + } + if (gdc.analog & (1 << GDCANALOG_16)) { + return(gdc.anareg[(gdc.palnum * 3) + 1]); + } + (void)port; + return(gdc.degpal[2]); +} + +static REG8 IOINPCALL gdc_iae(UINT port) { + + if (gdc.analog & (1 << GDCANALOG_256)) { + return(gdc.anareg[(16 * 3) + (gdc.palnum * 4) + 2]); + } + if (gdc.analog & (1 << GDCANALOG_16)) { + return(gdc.anareg[(gdc.palnum * 3) + 2]); + } + (void)port; + return(gdc.degpal[0]); +} +#endif + + +// ---- extend + +#if defined(SUPPORT_PC9821) +static void IOOUTCALL gdc_o9a0(UINT port, REG8 dat) { + + gdc.ff2 = dat; + (void)port; +} + +static REG8 IOINPCALL gdc_i9a0(UINT port) { + + REG8 ret; + + ret = 0; + switch(gdc.ff2) { + case 0x00: + ret = 0xff; + break; + + case 0x01: + ret = (gdc.mode1 >> 1) & 1; + break; + + case 0x02: + ret = (gdc.mode1 >> 4) & 1; + break; + + case 0x03: + ret = (gdc.mode1 >> 7) & 1; + break; + + case 0x04: + ret = (gdc.mode2 >> 0) & 1; + break; + + case 0x05: + ret = (gdc.display >> GDCDISP_PLAZMA) & 1; + break; + + case 0x07: + ret = (gdc.mode2 >> 2) & 1; + break; + + case 0x08: + ret = (gdc.mode2 >> 3) & 1; + break; + + case 0x09: + ret = (gdc.clock >> 0) & 1; + break; + + case 0x0a: + ret = (gdc.analog >> GDCANALOG_256) & 1; + break; + + case 0x0b: + ret = 1; + break; + + case 0x0d: + ret = (gdc.analog >> GDCANALOG_256E) & 1; + break; + } + ret |= (gdc.clock & 2); + (void)port; + return(ret); +} +#endif + +#if defined(SUPPORT_CRT31KHZ) +static void IOOUTCALL gdc_o9a8(UINT port, REG8 dat) { + + if ((gdc.display ^ (dat << GDCDISP_31)) & (1 << GDCDISP_31)) { + gdc.display ^= (1 << GDCDISP_31); + gdcs.textdisp |= GDCSCRN_EXT; + } + (void)port; +} + +static REG8 IOINPCALL gdc_i9a8(UINT port) { + + (void)port; + return((gdc.display >> GDCDISP_31) & 1); +} +#endif + + +// ---- I/F + +static const IOOUT gdco60[8] = { + gdc_o60, gdc_o62, gdc_o64, NULL, + gdc_o68, gdc_o6a, NULL, gdc_o6e}; + +static const IOOUT gdcoa0[8] = { + gdc_oa0, gdc_oa2, gdc_oa4, gdc_oa6, + gdc_oa8, gdc_oaa, gdc_oac, gdc_oae}; + +static const IOINP gdci60[8] = { + gdc_i60, gdc_i62, NULL, NULL, + gdc_i68, gdc_i6a, NULL, NULL}; + +#if defined(SUPPORT_PC9821) +static const IOINP gdcia0[8] = { + gdc_ia0, gdc_ia2, gdc_ia4, gdc_ia6, + gdc_ia8, gdc_iaa, gdc_iac, gdc_iae}; +#else +static const IOINP gdcia0[8] = { + gdc_ia0, gdc_ia2, gdc_ia4, gdc_ia6, + NULL, NULL, NULL, NULL}; +#endif + + +void gdc_biosreset(void) { + +#if defined(SUPPORT_PC9821) + UINT i; + UINT j; + UINT8 tmp; + UINT8 *pal; +#endif + + if (!(pccore.dipsw[0] & 0x01)) { + gdc.mode1 = 0x98; + gdc.m.para[GDC_CSRFORM + 0] = 0x0f; + gdc.m.para[GDC_CSRFORM + 1] = 0xc0; + gdc.m.para[GDC_CSRFORM + 2] = 0x7b; + CopyMemory(gdc.m.para + GDC_SYNC, defsyncm24, 8); + gdc.s.para[GDC_CSRFORM + 0] = 1; + CopyMemory(gdc.s.para + GDC_SYNC, defsyncs24, 8); + } + else { + gdc.crt15khz = 3; + gdc.mode1 = 0x80; + gdc.m.para[GDC_CSRFORM + 0] = 0x07; + gdc.m.para[GDC_CSRFORM + 1] = 0xc0; + gdc.m.para[GDC_CSRFORM + 2] = 0x3b; + CopyMemory(gdc.m.para + GDC_SYNC, defsyncm15, 8); + CopyMemory(gdc.s.para + GDC_SYNC, defsyncs15, 8); + } + if (pccore.dipsw[0] & 0x80) { + gdc.s.para[GDC_SYNC] = 0x16; + } + gdc_vectreset(&gdc.m); + gdc_vectreset(&gdc.s); + + gdc.clock = 0; + gdc.m.para[GDC_PITCH] = 80; + gdc.s.para[GDC_PITCH] = 40; + + gdc.bitac = 0xff; + + // vram bank + gdcs.disp = 0; + gdcs.access = 0; + gdc.analog &= ~(1 << GDCANALOG_16); + gdcs.palchange = GDCSCRN_REDRAW; + + gdc.mode2 &= ~(1 << 0); + gdc.mode2 &= ~(1 << 2); + gdc.mode2 &= ~(1 << 3); + gdcs.mode2 = gdc.mode2; + + vramop.operate &= ~(1 << VOPBIT_ACCESS); + vramop.operate &= ~(1 << VOPBIT_EGC); + vramop.operate &= ~(1 << VOPBIT_ANALOG); +#if defined(SUPPORT_PC9821) + gdc.analog &= ~(1 << (GDCANALOG_256)); + vramop.operate &= ~(1 << VOPBIT_VGA); +#endif + MEMM_VRAM(vramop.operate); + + // palette + CopyMemory(gdc.degpal, defdegpal, 4); + if (gdc.display & (1 << GDCDISP_ANALOG)) { + gdc_setanalogpalall(defanapal); + } +#if defined(SUPPORT_PC9821) + pal = gdc.anareg + (16 * 3); + for (i=0; i<256; i+=8) { + tmp = (UINT8)((i)?(i - 4):0); + pal[0] = tmp; + pal[1] = tmp; + pal[2] = tmp; + pal += 4; + for (j=1; j<8; j++) { + pal[0] = (UINT8)((i + 7) * ((j >> 2) & 1)); + pal[1] = (UINT8)((i + 7) * ((j >> 1) & 1)); + pal[2] = (UINT8)((i + 7) * ((j >> 0) & 1)); + pal += 4; + } + } +#endif + gdcs.textdisp = GDCSCRN_ALLDRAW2 | GDCSCRN_EXT; + gdcs.grphdisp = GDCSCRN_ALLDRAW2 | GDCSCRN_EXT; + gdcs.palchange = GDCSCRN_REDRAW; + pcstat.screenupdate |= 2; +} + +void gdc_reset(const NP2CFG *pConfig) { + + ZeroMemory(&gdc, sizeof(gdc)); + ZeroMemory(&gdcs, sizeof(gdcs)); + +#if !defined(SUPPORT_PC9821) + if (pConfig->color16 & 1) +#endif + { + gdc.display |= (1 << GDCDISP_ANALOG); + } + if (!(pccore.dipsw[0] & 0x04)) { // dipsw1-3 on + gdc.display |= (1 << GDCDISP_PLAZMA2); + } + gdc_biosreset(); + + (void)pConfig; +} + +void gdc_bind(void) { + + gdc_updateclock(); +#if defined(SUPPORT_PC9821) + iocore_attachout(0x09a0, gdc_o9a0); + iocore_attachinp(0x09a0, gdc_i9a0); +#endif +#if defined(SUPPORT_CRT31KHZ) + iocore_attachout(0x09a8, gdc_o9a8); + iocore_attachinp(0x09a8, gdc_i9a8); +#endif + iocore_attachsysoutex(0x0060, 0x0cf1, gdco60, 8); + iocore_attachsysinpex(0x0060, 0x0cf1, gdci60, 8); + iocore_attachsysoutex(0x00a0, 0x0cf1, gdcoa0, 8); + iocore_attachsysinpex(0x00a0, 0x0cf1, gdcia0, 8); +} + diff --git a/io/gdc_cmd.h b/io/gdc_cmd.h old mode 100755 new mode 100644 index 706ef131..bfbf740a --- a/io/gdc_cmd.h +++ b/io/gdc_cmd.h @@ -1,47 +1,47 @@ - -enum { - CMD_RESET = 0x00, - CMD_SYNC_ON = 0x0f, - CMD_SYNC_OFF = 0x0e, - CMD_MASTER = 0x6f, - CMD_SLAVE = 0x6e, - - CMD_START_ = 0x6b, - CMD_START = 0x0d, - CMD_STOP_ = 0x05, - CMD_STOP = 0x0c, - - CMD_ZOOM = 0x06, - CMD_SCROLL = 0x70, - CMD_CSRW = 0x49, - CMD_CSRFORM = 0x4b, - CMD_PITCH = 0x47, - CMD_LPEN = 0xc0, - CMD_VECTW = 0x4c, - CMD_VECTE = 0x6c, - CMD_TEXTW = 0x78, - CMD_TEXTE = 0x68, - CMD_CSRR = 0xe0, - CMD_MASK = 0x4a, - - CMD_WRITE = 0x20, - CMD_READ = 0xa0 -}; - -enum { - GDC_SYNC = 0, // 0 - GDC_ZOOM = (GDC_SYNC+8), // 8 - GDC_CSRFORM = (GDC_ZOOM+1), // 9 - GDC_SCROLL = (GDC_CSRFORM+3), // 12 - GDC_TEXTW = (GDC_SCROLL+8), // 20 - GDC_PITCH = (GDC_TEXTW+8), // 28 - GDC_LPEN = (GDC_PITCH+1), // 29 - GDC_VECTW = (GDC_LPEN+3), // 32 - GDC_CSRW = (GDC_VECTW+11), // 43 - GDC_MASK = (GDC_CSRW+3), // 46 - GDC_CSRR = (GDC_MASK+2), // 48 - GDC_WRITE = (GDC_CSRR+5), // 53 - GDC_CODE = (GDC_WRITE+1), // 54 - GDC_TERMDATA = (GDC_CODE+2) -}; - + +enum { + CMD_RESET = 0x00, + CMD_SYNC_ON = 0x0f, + CMD_SYNC_OFF = 0x0e, + CMD_MASTER = 0x6f, + CMD_SLAVE = 0x6e, + + CMD_START_ = 0x6b, + CMD_START = 0x0d, + CMD_STOP_ = 0x05, + CMD_STOP = 0x0c, + + CMD_ZOOM = 0x06, + CMD_SCROLL = 0x70, + CMD_CSRW = 0x49, + CMD_CSRFORM = 0x4b, + CMD_PITCH = 0x47, + CMD_LPEN = 0xc0, + CMD_VECTW = 0x4c, + CMD_VECTE = 0x6c, + CMD_TEXTW = 0x78, + CMD_TEXTE = 0x68, + CMD_CSRR = 0xe0, + CMD_MASK = 0x4a, + + CMD_WRITE = 0x20, + CMD_READ = 0xa0 +}; + +enum { + GDC_SYNC = 0, // 0 + GDC_ZOOM = (GDC_SYNC+8), // 8 + GDC_CSRFORM = (GDC_ZOOM+1), // 9 + GDC_SCROLL = (GDC_CSRFORM+3), // 12 + GDC_TEXTW = (GDC_SCROLL+8), // 20 + GDC_PITCH = (GDC_TEXTW+8), // 28 + GDC_LPEN = (GDC_PITCH+1), // 29 + GDC_VECTW = (GDC_LPEN+3), // 32 + GDC_CSRW = (GDC_VECTW+11), // 43 + GDC_MASK = (GDC_CSRW+3), // 46 + GDC_CSRR = (GDC_MASK+2), // 48 + GDC_WRITE = (GDC_CSRR+5), // 53 + GDC_CODE = (GDC_WRITE+1), // 54 + GDC_TERMDATA = (GDC_CODE+2) +}; + diff --git a/io/gdc_pset.c b/io/gdc_pset.c old mode 100755 new mode 100644 index fbc9cbb7..9250b9e4 --- a/io/gdc_pset.c +++ b/io/gdc_pset.c @@ -1,174 +1,174 @@ -#include -#include -#include -#include -#include -#include -#include "gdc_pset.h" -#include - - -static void MEMCALL _nop(GDCPSET pset, UINT addr, UINT bit) { - - (void)pset; - (void)addr; - (void)bit; -} - -static void MEMCALL _replace0(GDCPSET pset, UINT addr, UINT bit) { - - vramupdate[addr] |= pset->update.b[0]; - pset->base.ptr[addr] &= ~(0x80 >> bit); -} - -static void MEMCALL _replace1(GDCPSET pset, UINT addr, UINT bit) { - - vramupdate[addr] |= pset->update.b[0]; - pset->base.ptr[addr] |= (0x80 >> bit); -} - -static void MEMCALL _complemnt(GDCPSET pset, UINT addr, UINT bit) { - - vramupdate[addr] |= pset->update.b[0]; - pset->base.ptr[addr] ^= (0x80 >> bit); -} - -static void MEMCALL _clear(GDCPSET pset, UINT addr, UINT bit) { - - vramupdate[addr] |= pset->update.b[0]; - pset->base.ptr[addr] &= ~(0x80 >> bit); -} - -static void MEMCALL _set(GDCPSET pset, UINT addr, UINT bit) { - - vramupdate[addr] |= pset->update.b[0]; - pset->base.ptr[addr] |= (0x80 >> bit); -} - - -// ---- grcg - -static void MEMCALL withtdw(GDCPSET pset, UINT addr, UINT bit) { - - UINT8 *ptr; - - addr &= ~1; - *(UINT16 *)(vramupdate + addr) |= pset->update.w; - ptr = pset->base.ptr + addr; - *(UINT16 *)(ptr + VRAM_B) = grcg.tile[0].w; - *(UINT16 *)(ptr + VRAM_R) = grcg.tile[1].w; - *(UINT16 *)(ptr + VRAM_G) = grcg.tile[2].w; - *(UINT16 *)(ptr + VRAM_E) = grcg.tile[3].w; - (void)bit; -} - -static void MEMCALL withrmw(GDCPSET pset, UINT addr, UINT bit) { - - UINT8 *ptr; - UINT8 data; - UINT8 mask; - - vramupdate[addr] |= pset->update.b[0]; - ptr = pset->base.ptr + addr; - data = (0x80 >> bit); - mask = ~data; - ptr[VRAM_B] &= mask; - ptr[VRAM_B] |= data & grcg.tile[0].b[0]; - ptr[VRAM_R] &= mask; - ptr[VRAM_R] |= data & grcg.tile[1].b[0]; - ptr[VRAM_G] &= mask; - ptr[VRAM_G] |= data & grcg.tile[2].b[0]; - ptr[VRAM_E] &= mask; - ptr[VRAM_E] |= data & grcg.tile[3].b[0]; -} - - -// ---- egc - -static void MEMCALL withegc(GDCPSET pset, UINT addr, UINT bit) { - - REG16 data; - - data = (0x80 >> bit); - if (addr & 1) { - addr &= ~1; - data <<= 8; - } - egc_writeword(pset->base.addr + addr, data); -} - - -static const GDCPFN psettbl[4][2] = { - {_replace0, _replace1}, - {_nop, _complemnt}, - {_nop, _clear}, - {_nop, _set}}; - - -// ---- - -void MEMCALL gdcpset_prepare(GDCPSET pset, UINT32 csrw, REG16 pat, REG8 op) { - - UINT8 *base; - UINT8 update; - - if (vramop.operate & (1 << VOPBIT_EGC)) { - pset->func[0] = _nop; - pset->func[1] = withegc; - pset->base.addr = gdcplaneseg[(csrw >> 14) & 3]; - } - else { - base = mem; - if (!gdcs.access) { - update = 1; - } - else { - base += VRAM_STEP; - update = 2; - } - op &= 3; - if (!(grcg.gdcwithgrcg & 0x8)) { - pset->func[0] = psettbl[op][0]; - pset->func[1] = psettbl[op][1]; - pset->base.ptr = base + gdcplaneseg[(csrw >> 14) & 3]; - } - else { - pset->func[0] = _nop; - pset->func[1] = (grcg.gdcwithgrcg & 0x4)?withrmw:withtdw; - pset->base.ptr = base; - } - gdcs.grphdisp |= update; - pset->update.b[0] = update; - pset->update.b[1] = update; - } - pset->pattern = pat; - pset->x = (UINT16)((((csrw & 0x3fff) % 40) << 4) + ((csrw >> 20) & 0x0f)); - pset->y = (UINT16)((csrw & 0x3fff) / 40); - pset->dots = 0; -} - -void MEMCALL gdcpset(GDCPSET pset, REG16 x, REG16 y) { - - UINT dot; - - dot = pset->pattern & 1; - pset->pattern = (pset->pattern >> 1) + (dot << 15); - pset->dots++; - x = LOW16(x); - y = LOW16(y); - if (y > 409) { - return; - } - else if (y == 409) { - if (x >= 384) { - return; - } - } - else { - if (x >= 640) { - return; - } - } - (*pset->func[dot])(pset, (y * 80) + (x >> 3), x & 7); -} - +#include +#include +#include +#include +#include +#include +#include "gdc_pset.h" +#include + + +static void MEMCALL _nop(GDCPSET pset, UINT addr, UINT bit) { + + (void)pset; + (void)addr; + (void)bit; +} + +static void MEMCALL _replace0(GDCPSET pset, UINT addr, UINT bit) { + + vramupdate[addr] |= pset->update.b[0]; + pset->base.ptr[addr] &= ~(0x80 >> bit); +} + +static void MEMCALL _replace1(GDCPSET pset, UINT addr, UINT bit) { + + vramupdate[addr] |= pset->update.b[0]; + pset->base.ptr[addr] |= (0x80 >> bit); +} + +static void MEMCALL _complemnt(GDCPSET pset, UINT addr, UINT bit) { + + vramupdate[addr] |= pset->update.b[0]; + pset->base.ptr[addr] ^= (0x80 >> bit); +} + +static void MEMCALL _clear(GDCPSET pset, UINT addr, UINT bit) { + + vramupdate[addr] |= pset->update.b[0]; + pset->base.ptr[addr] &= ~(0x80 >> bit); +} + +static void MEMCALL _set(GDCPSET pset, UINT addr, UINT bit) { + + vramupdate[addr] |= pset->update.b[0]; + pset->base.ptr[addr] |= (0x80 >> bit); +} + + +// ---- grcg + +static void MEMCALL withtdw(GDCPSET pset, UINT addr, UINT bit) { + + UINT8 *ptr; + + addr &= ~1; + *(UINT16 *)(vramupdate + addr) |= pset->update.w; + ptr = pset->base.ptr + addr; + *(UINT16 *)(ptr + VRAM_B) = grcg.tile[0].w; + *(UINT16 *)(ptr + VRAM_R) = grcg.tile[1].w; + *(UINT16 *)(ptr + VRAM_G) = grcg.tile[2].w; + *(UINT16 *)(ptr + VRAM_E) = grcg.tile[3].w; + (void)bit; +} + +static void MEMCALL withrmw(GDCPSET pset, UINT addr, UINT bit) { + + UINT8 *ptr; + UINT8 data; + UINT8 mask; + + vramupdate[addr] |= pset->update.b[0]; + ptr = pset->base.ptr + addr; + data = (0x80 >> bit); + mask = ~data; + ptr[VRAM_B] &= mask; + ptr[VRAM_B] |= data & grcg.tile[0].b[0]; + ptr[VRAM_R] &= mask; + ptr[VRAM_R] |= data & grcg.tile[1].b[0]; + ptr[VRAM_G] &= mask; + ptr[VRAM_G] |= data & grcg.tile[2].b[0]; + ptr[VRAM_E] &= mask; + ptr[VRAM_E] |= data & grcg.tile[3].b[0]; +} + + +// ---- egc + +static void MEMCALL withegc(GDCPSET pset, UINT addr, UINT bit) { + + REG16 data; + + data = (0x80 >> bit); + if (addr & 1) { + addr &= ~1; + data <<= 8; + } + egc_writeword(pset->base.addr + addr, data); +} + + +static const GDCPFN psettbl[4][2] = { + {_replace0, _replace1}, + {_nop, _complemnt}, + {_nop, _clear}, + {_nop, _set}}; + + +// ---- + +void MEMCALL gdcpset_prepare(GDCPSET pset, UINT32 csrw, REG16 pat, REG8 op) { + + UINT8 *base; + UINT8 update; + + if (vramop.operate & (1 << VOPBIT_EGC)) { + pset->func[0] = _nop; + pset->func[1] = withegc; + pset->base.addr = gdcplaneseg[(csrw >> 14) & 3]; + } + else { + base = mem; + if (!gdcs.access) { + update = 1; + } + else { + base += VRAM_STEP; + update = 2; + } + op &= 3; + if (!(grcg.gdcwithgrcg & 0x8)) { + pset->func[0] = psettbl[op][0]; + pset->func[1] = psettbl[op][1]; + pset->base.ptr = base + gdcplaneseg[(csrw >> 14) & 3]; + } + else { + pset->func[0] = _nop; + pset->func[1] = (grcg.gdcwithgrcg & 0x4)?withrmw:withtdw; + pset->base.ptr = base; + } + gdcs.grphdisp |= update; + pset->update.b[0] = update; + pset->update.b[1] = update; + } + pset->pattern = pat; + pset->x = (UINT16)((((csrw & 0x3fff) % 40) << 4) + ((csrw >> 20) & 0x0f)); + pset->y = (UINT16)((csrw & 0x3fff) / 40); + pset->dots = 0; +} + +void MEMCALL gdcpset(GDCPSET pset, REG16 x, REG16 y) { + + UINT dot; + + dot = pset->pattern & 1; + pset->pattern = (pset->pattern >> 1) + (dot << 15); + pset->dots++; + x = LOW16(x); + y = LOW16(y); + if (y > 409) { + return; + } + else if (y == 409) { + if (x >= 384) { + return; + } + } + else { + if (x >= 640) { + return; + } + } + (*pset->func[dot])(pset, (y * 80) + (x >> 3), x & 7); +} + diff --git a/io/gdc_pset.h b/io/gdc_pset.h old mode 100755 new mode 100644 index 3540b768..44b4828e --- a/io/gdc_pset.h +++ b/io/gdc_pset.h @@ -1,32 +1,32 @@ - -struct _gdcpset; -typedef struct _gdcpset _GDCPSET; -typedef struct _gdcpset *GDCPSET; - -typedef void (MEMCALL * GDCPFN)(GDCPSET pen, UINT addr, UINT bit); - -struct _gdcpset { - GDCPFN func[2]; - union { - UINT8 *ptr; // raw access / grcg - UINT32 addr; // egc - } base; - UINT16 pattern; - PAIR16 update; - UINT16 x; - UINT16 y; - UINT dots; -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -void MEMCALL gdcpset_prepare(GDCPSET pset, UINT32 csrw, REG16 pat, REG8 op); -void MEMCALL gdcpset(GDCPSET pset, REG16 x, REG16 y); - -#ifdef __cplusplus -} -#endif - + +struct _gdcpset; +typedef struct _gdcpset _GDCPSET; +typedef struct _gdcpset *GDCPSET; + +typedef void (MEMCALL * GDCPFN)(GDCPSET pen, UINT addr, UINT bit); + +struct _gdcpset { + GDCPFN func[2]; + union { + UINT8 *ptr; // raw access / grcg + UINT32 addr; // egc + } base; + UINT16 pattern; + PAIR16 update; + UINT16 x; + UINT16 y; + UINT dots; +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +void MEMCALL gdcpset_prepare(GDCPSET pset, UINT32 csrw, REG16 pat, REG8 op); +void MEMCALL gdcpset(GDCPSET pset, REG16 x, REG16 y); + +#ifdef __cplusplus +} +#endif + diff --git a/io/gdc_sub.c b/io/gdc_sub.c old mode 100755 new mode 100644 index 2d2b44a8..d4fa1394 --- a/io/gdc_sub.c +++ b/io/gdc_sub.c @@ -1,683 +1,683 @@ -#include -#if !defined(DISABLE_MATH_H) -#include -#endif -#include -#include -#include -#include -#include "gdc_pset.h" -#include - - -enum { - RT_MULBIT = 15, - RT_TABLEBIT = 12, - RT_TABLEMAX = (1 << RT_TABLEBIT) -}; - -static UINT16 gdc_rt[RT_TABLEMAX+1]; - -typedef struct { - SINT16 x; - SINT16 y; - SINT16 x2; - SINT16 y2; -} VECTDIR; - -const UINT32 gdcplaneseg[4] = {VRAM_E, VRAM_B, VRAM_R, VRAM_G}; - -static const VECTDIR vectdir[16] = { - { 0, 1, 1, 0}, { 1, 1, 1,-1}, - { 1, 0, 0,-1}, { 1,-1,-1,-1}, - { 0,-1,-1, 0}, {-1,-1,-1, 1}, - {-1, 0, 0, 1}, {-1, 1, 1, 1}, - - { 0, 1, 1, 1}, { 1, 1, 1, 0}, // SL - { 1, 0, 1,-1}, { 1,-1, 0,-1}, - { 0,-1,-1,-1}, {-1,-1,-1, 0}, - {-1, 0,-1, 1}, {-1, 1, 0, 1}}; - - -#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) -const UINT8 gdcbitreverse[0x100] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff}; -#else -REG8 gdcbitreverse(REG8 data) { - - REG8 ret; - UINT cnt; - - ret = 0; - cnt = 8; - do { - ret = (ret * 2) + (data & 1); - data >>= 1; - } while(--cnt); - return(ret); -} -#endif - - -void gdcsub_initialize(void) { - -#if !defined(DISABLE_MATH_H) - int i; - - for (i=0; i<=RT_TABLEMAX; i++) { - gdc_rt[i] = (UINT16)((double)(1 << RT_MULBIT) * - (1 - sqrt(1 - pow((0.70710678118654 * i) / RT_TABLEMAX, 2)))); - } -#endif -} - -void gdcslavewait(NEVENTITEM item) { - - if (item->flag & NEVENT_SETEVENT) { - gdc.s_drawing = 0; // clear DRAWING - } -} - -void gdcsub_setslavewait(UINT32 wait) { - - SINT32 clk; - - clk = nevent_getremain(NEVENT_GDCSLAVE); - if (clk < 0) { - clk = 0; - } - gdc.s_drawing = 8; // GDC DRAWING! - nevent_set(NEVENT_GDCSLAVE, clk + wait, gdcslavewait, NEVENT_ABSOLUTE); -} - -static void calc_gdcslavewait(UINT dots) { - - SINT32 clk; - - clk = dots; - if (pccore.cpumode & CPUMODE_8MHZ) { - clk *= 22464; - } - else { - clk *= 27648; - } - clk *= pccore.multiple; - clk /= 15625; - clk += 30 * pccore.multiple; - gdcsub_setslavewait(clk); -} - -void gdcsub_setvectl(GDCVECT *vect, int xx1, int yy1, int xx2, int yy2) { - - UINT ope; - int dy; - int dx; - int tmp; - - ope = 0; - dy = yy2 - yy1; - if (dy < 0) { - dy = 0 - dy; - } - dx = xx2 - xx1; - if (dx == 0) { - if (yy1 <= yy2) { - ope = 7; - } - else { - ope = 3; - } - } - else { - if (dx > 0) { - if (yy1 >= yy2) { - ope += 2; - } - } - else { - dx = 0 - dx; - ope += 4; - if (yy1 <= yy2) { - ope += 2; - } - } - if (ope & 2) { - if (dx <= dy) { - ope += 1; - } - } - else { - if (dx >= dy) { - ope += 1; - } - } - } - if (!((ope + 1) & 2)) { - tmp = dx; - dx = dy; - dy = tmp; - } - vect->ope = (UINT8)(ope + 0x08); - STOREINTELWORD(vect->DC, (UINT16)dx); - dy = dy * 2; - STOREINTELWORD(vect->D1, (UINT16)dy); - dy -= dx; - STOREINTELWORD(vect->D, (UINT16)dy); - dy -= dx; - STOREINTELWORD(vect->D2, (UINT16)dy); -} - - -// ---- - -void gdcsub_vect0(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { - - (void)csrw; - (void)vect; - (void)pat; - (void)ope; -} - -void gdcsub_vectp(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { - - _GDCPSET pset; - - gdcpset_prepare(&pset, csrw, pat, ope); - gdcpset(&pset, pset.x, pset.y); - calc_gdcslavewait(pset.dots); -} - -void gdcsub_vectl(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { - - _GDCPSET pset; - UINT dc; - REG16 x; - REG16 y; - UINT i; - UINT16 step; - UINT d1; - - gdcpset_prepare(&pset, csrw, pat, ope); - dc = (LOADINTELWORD(vect->DC)) & 0x3fff; - if (dc == 0) { - gdcpset(&pset, pset.x, pset.y); - } - else { - x = pset.x; - y = pset.y; - d1 = LOADINTELWORD(vect->D1); - switch(vect->ope & 7) { - case 0: - for (i=0; i<=dc; i++) { - step = (UINT16)((((d1 * i) / dc) + 1) >> 1); - gdcpset(&pset, (REG16)(x + step), y++); - } - break; - - case 1: - for (i=0; i<=dc; i++) { - step = (UINT16)((((d1 * i) / dc) + 1) >> 1); - gdcpset(&pset, x++, (REG16)(y + step)); - } - break; - - case 2: - for (i=0; i<=dc; i++) { - step = (UINT16)((((d1 * i) / dc) + 1) >> 1); - gdcpset(&pset, x++, (REG16)(y - step)); - } - break; - - case 3: - for (i=0; i<=dc; i++) { - step = (UINT16)((((d1 * i) / dc) + 1) >> 1); - gdcpset(&pset, (REG16)(x + step), y--); - } - break; - - case 4: - for (i=0; i<=dc; i++) { - step = (UINT16)((((d1 * i) / dc) + 1) >> 1); - gdcpset(&pset, (REG16)(x - step), y--); - } - break; - - case 5: - for (i=0; i<=dc; i++) { - step = (UINT16)((((d1 * i) / dc) + 1) >> 1); - gdcpset(&pset, x--, (REG16)(y - step)); - } - break; - - case 6: - for (i=0; i<=dc; i++) { - step = (UINT16)((((d1 * i) / dc) + 1) >> 1); - gdcpset(&pset, x--, (REG16)(y + step)); - } - break; - - case 7: - for (i=0; i<=dc; i++) { - step = (UINT16)((((d1 * i) / dc) + 1) >> 1); - gdcpset(&pset, (REG16)(x - step), y++); - } - break; - } - } - calc_gdcslavewait(pset.dots); -} - -void gdcsub_vectt(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { - - _GDCPSET pset; - UINT8 multiple; - UINT sx; -const VECTDIR *dir; - UINT8 muly; - REG16 cx; - REG16 cy; - UINT xrem; - UINT8 mulx; - - if (vect->ope & 0x80) { // SL - pat = (REG16)((GDCPATREVERSE(pat) << 8) + GDCPATREVERSE(pat >> 8)); - } - gdcpset_prepare(&pset, csrw, 0xffff, ope); - multiple = (gdc.s.para[GDC_ZOOM] & 15) + 1; - - sx = LOADINTELWORD(vect->D); - sx = ((sx - 1) & 0x3fff) + 1; - if (sx >= 768) { - sx = 768; - } - dir = vectdir + ((vect->ope) & 7); - - muly = multiple; - while(muly--) { - cx = pset.x; - cy = pset.y; - xrem = sx; - while(xrem--) { - mulx = multiple; - if (pat & 1) { - pat >>= 1; - pat |= 0x8000; - while(mulx--) { - gdcpset(&pset, cx, cy); - cx += dir->x; - cy += dir->y; - } - } - else { - pat >>= 1; - while(mulx--) { - cx += dir->x; - cy += dir->y; - } - } - } - pset.x += dir->x2; - pset.y += dir->y2; - } - calc_gdcslavewait(pset.dots); -} - -void gdcsub_vectc(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { - - _GDCPSET pset; - UINT r; - UINT m; - UINT i; - UINT t; - UINT x; - UINT y; - UINT s; - - gdcpset_prepare(&pset, csrw, pat, ope); - r = (LOADINTELWORD(vect->D)) & 0x3fff; - m = (r * 10000 + 14141) / 14142; - if (!m) { - gdcpset(&pset, pset.x, pset.y); - } - else { - i = (LOADINTELWORD(vect->DM)) & 0x3fff; - t = (LOADINTELWORD(vect->DC)) & 0x3fff; - x = pset.x; - y = pset.y; - if (t > m) { - t = m; - } - switch((vect->ope) & 7) { - case 0: - for (; i<=t; i++) { - s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); - s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; - gdcpset(&pset, (REG16)(x + s), (REG16)(y + i)); - } - break; - - case 1: - for (; i<=t; i++) { - s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); - s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; - gdcpset(&pset, (REG16)(x + i), (REG16)(y + s)); - } - break; - - case 2: - for (; i<=t; i++) { - s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); - s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; - gdcpset(&pset, (REG16)(x + i), (REG16)(y - s)); - } - break; - - case 3: - for (; i<=t; i++) { - s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); - s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; - gdcpset(&pset, (REG16)(x + s), (REG16)(y - i)); - } - break; - - case 4: - for (; i<=t; i++) { - s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); - s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; - gdcpset(&pset, (REG16)(x - s), (REG16)(y - i)); - } - break; - - case 5: - for (; i<=t; i++) { - s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); - s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; - gdcpset(&pset, (REG16)(x - i), (REG16)(y - s)); - } - break; - - case 6: - for (; i<=t; i++) { - s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); - s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; - gdcpset(&pset, (REG16)(x - i), (REG16)(y + s)); - } - break; - - case 7: - for (; i<=t; i++) { - s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); - s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; - gdcpset(&pset, (REG16)(x - s), (REG16)(y + i)); - } - break; - } - } - calc_gdcslavewait(pset.dots); -} - -void gdcsub_vectr(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { - - _GDCPSET pset; - UINT d; - UINT d2; - REG16 x; - REG16 y; - UINT i; -const VECTDIR *dir; - - gdcpset_prepare(&pset, csrw, pat, ope); - d = (LOADINTELWORD(vect->D)) & 0x3fff; - d2 = (LOADINTELWORD(vect->D2)) & 0x3fff; - x = pset.x; - y = pset.y; - dir = vectdir + ((vect->ope) & 7); - for (i=0; ix; - y += dir->y; - } - for (i=0; ix2; - y += dir->y2; - } - for (i=0; ix; - y -= dir->y; - } - for (i=0; ix2; - y -= dir->y2; - } - calc_gdcslavewait(pset.dots); -} - -void gdcsub_text(UINT32 csrw, const GDCVECT *vect, const UINT8 *pat, - REG8 ope) { - - _GDCPSET pset; - UINT8 multiple; - UINT sx; - UINT sy; -const VECTDIR *dir; - UINT patnum; - UINT8 muly; - REG16 cx; - REG16 cy; - UINT xrem; - UINT8 bit; - UINT8 mulx; - - gdcpset_prepare(&pset, csrw, 0xffff, ope); - multiple = (gdc.s.para[GDC_ZOOM] & 15) + 1; -#if 1 - sy = LOADINTELWORD(vect->DC); - sy = (sy & 0x3fff) + 1; - sx = LOADINTELWORD(vect->D); - sx = ((sx - 1) & 0x3fff) + 1; - - // てきとーにリミット - if (sx >= 768) { - sx = 768; - } - if (sy >= 768) { - sy = 768; - } -#else - sx = 8; - sy = 8; -#endif - dir = vectdir + (((vect->ope & 0x80) >> 4) + ((vect->ope) & 7)); - patnum = 0; - - while(sy--) { - muly = multiple; - patnum--; - while(muly--) { - cx = pset.x; - cy = pset.y; - bit = pat[patnum & 7]; - xrem = sx; - while(xrem--) { - mulx = multiple; - if (bit & 1) { - bit >>= 1; - bit |= 0x80; - while(mulx--) { - gdcpset(&pset, cx, cy); - cx += dir->x; - cy += dir->y; - } - } - else { - bit >>= 1; - while(mulx--) { - cx += dir->x; - cy += dir->y; - } - } - } - pset.x += dir->x2; - pset.y += dir->y2; - } - } - calc_gdcslavewait(pset.dots); -} - - -// ---- - -void gdcsub_write(void) { - - UINT16 mask; - UINT16 data; - UINT32 adrs; - UINT leng; - UINT8 *ptr; - UINT16 updatebit; - -#if 0 - TRACEOUT(("gdcsub_write")); - if (grcg.gdcwithgrcg & 0x8) { - MessageBox(NULL, "!!! grcg working", "?", MB_OK); - } -#endif - - mask = LOADINTELWORD(gdc.s.para + GDC_MASK); -#if defined(BYTESEX_LITTLE) - switch(gdc.s.cmd & 0x18) { - case 0x00: - data = LOADINTELWORD(gdc.s.para + GDC_CODE); - break; - - case 0x10: - mask &= 0x00ff; - data = gdc.s.para[GDC_CODE]; - break; - - case 0x18: - mask &= 0xff00; - data = gdc.s.para[GDC_CODE] << 8; - break; - - default: - return; - } -#else - switch(gdc.s.cmd & 0x18) { - case 0x00: - data = (gdc.s.para[GDC_CODE] << 8) + gdc.s.para[GDC_CODE + 1]; - break; - - case 0x10: - mask &= 0xff00; - data = gdc.s.para[GDC_CODE] << 8; - break; - - case 0x18: - mask &= 0x00ff; - data = gdc.s.para[GDC_CODE]; - break; - - default: - return; - } -#endif -#if 0 // これって uPD7220でも有効? - if (data != 0xffff) { - data = 0; - } -#endif - - adrs = LOADINTELDWORD(gdc.s.para + GDC_CSRW); - leng = LOADINTELWORD(gdc.s.para + GDC_VECTW + 1); - leng++; - ptr = mem; - if (!gdcs.access) { - updatebit = 0x0101; - } - else { - ptr += VRAM_STEP; - updatebit = 0x0202; - } - gdcs.grphdisp |= (UINT8)updatebit; - - ptr += gdcplaneseg[(adrs >> 14) & 3]; - adrs = (adrs & 0x3fff) << 1; - calc_gdcslavewait(leng); - - switch(gdc.s.cmd & 0x03) { - case 0x00: // replace - data &= mask; - mask = ~mask; - do { - *(UINT16 *)(ptr + adrs) &= mask; - *(UINT16 *)(ptr + adrs) |= data; - *(UINT16 *)(vramupdate + adrs) |= updatebit; - adrs = (adrs + 2) & 0x7ffe; - } while(--leng); - break; - - case 0x01: // complement - data &= mask; - do { - *(UINT16 *)(ptr + adrs) ^= data; - *(UINT16 *)(vramupdate + adrs) |= updatebit; - adrs = (adrs + 2) & 0x7ffe; - } while(--leng); - break; - - case 0x02: // clear - data &= mask; - do { - *(UINT16 *)(ptr + adrs) &= data; - *(UINT16 *)(vramupdate + adrs) |= updatebit; - adrs = (adrs + 2) & 0x7ffe; - } while(--leng); - break; - - case 0x03: // set - data &= mask; - do { - *(UINT16 *)(ptr + adrs) |= data; - *(UINT16 *)(vramupdate + adrs) |= updatebit; - adrs = (adrs + 2) & 0x7ffe; - } while(--leng); - break; - } -} - +#include +#if !defined(DISABLE_MATH_H) +#include +#endif +#include +#include +#include +#include +#include "gdc_pset.h" +#include + + +enum { + RT_MULBIT = 15, + RT_TABLEBIT = 12, + RT_TABLEMAX = (1 << RT_TABLEBIT) +}; + +static UINT16 gdc_rt[RT_TABLEMAX+1]; + +typedef struct { + SINT16 x; + SINT16 y; + SINT16 x2; + SINT16 y2; +} VECTDIR; + +const UINT32 gdcplaneseg[4] = {VRAM_E, VRAM_B, VRAM_R, VRAM_G}; + +static const VECTDIR vectdir[16] = { + { 0, 1, 1, 0}, { 1, 1, 1,-1}, + { 1, 0, 0,-1}, { 1,-1,-1,-1}, + { 0,-1,-1, 0}, {-1,-1,-1, 1}, + {-1, 0, 0, 1}, {-1, 1, 1, 1}, + + { 0, 1, 1, 1}, { 1, 1, 1, 0}, // SL + { 1, 0, 1,-1}, { 1,-1, 0,-1}, + { 0,-1,-1,-1}, {-1,-1,-1, 0}, + {-1, 0,-1, 1}, {-1, 1, 0, 1}}; + + +#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) +const UINT8 gdcbitreverse[0x100] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff}; +#else +REG8 gdcbitreverse(REG8 data) { + + REG8 ret; + UINT cnt; + + ret = 0; + cnt = 8; + do { + ret = (ret * 2) + (data & 1); + data >>= 1; + } while(--cnt); + return(ret); +} +#endif + + +void gdcsub_initialize(void) { + +#if !defined(DISABLE_MATH_H) + int i; + + for (i=0; i<=RT_TABLEMAX; i++) { + gdc_rt[i] = (UINT16)((double)(1 << RT_MULBIT) * + (1 - sqrt(1 - pow((0.70710678118654 * i) / RT_TABLEMAX, 2)))); + } +#endif +} + +void gdcslavewait(NEVENTITEM item) { + + if (item->flag & NEVENT_SETEVENT) { + gdc.s_drawing = 0; // clear DRAWING + } +} + +void gdcsub_setslavewait(UINT32 wait) { + + SINT32 clk; + + clk = nevent_getremain(NEVENT_GDCSLAVE); + if (clk < 0) { + clk = 0; + } + gdc.s_drawing = 8; // GDC DRAWING! + nevent_set(NEVENT_GDCSLAVE, clk + wait, gdcslavewait, NEVENT_ABSOLUTE); +} + +static void calc_gdcslavewait(UINT dots) { + + SINT32 clk; + + clk = dots; + if (pccore.cpumode & CPUMODE_8MHZ) { + clk *= 22464; + } + else { + clk *= 27648; + } + clk *= pccore.multiple; + clk /= 15625; + clk += 30 * pccore.multiple; + gdcsub_setslavewait(clk); +} + +void gdcsub_setvectl(GDCVECT *vect, int xx1, int yy1, int xx2, int yy2) { + + UINT ope; + int dy; + int dx; + int tmp; + + ope = 0; + dy = yy2 - yy1; + if (dy < 0) { + dy = 0 - dy; + } + dx = xx2 - xx1; + if (dx == 0) { + if (yy1 <= yy2) { + ope = 7; + } + else { + ope = 3; + } + } + else { + if (dx > 0) { + if (yy1 >= yy2) { + ope += 2; + } + } + else { + dx = 0 - dx; + ope += 4; + if (yy1 <= yy2) { + ope += 2; + } + } + if (ope & 2) { + if (dx <= dy) { + ope += 1; + } + } + else { + if (dx >= dy) { + ope += 1; + } + } + } + if (!((ope + 1) & 2)) { + tmp = dx; + dx = dy; + dy = tmp; + } + vect->ope = (UINT8)(ope + 0x08); + STOREINTELWORD(vect->DC, (UINT16)dx); + dy = dy * 2; + STOREINTELWORD(vect->D1, (UINT16)dy); + dy -= dx; + STOREINTELWORD(vect->D, (UINT16)dy); + dy -= dx; + STOREINTELWORD(vect->D2, (UINT16)dy); +} + + +// ---- + +void gdcsub_vect0(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { + + (void)csrw; + (void)vect; + (void)pat; + (void)ope; +} + +void gdcsub_vectp(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { + + _GDCPSET pset; + + gdcpset_prepare(&pset, csrw, pat, ope); + gdcpset(&pset, pset.x, pset.y); + calc_gdcslavewait(pset.dots); +} + +void gdcsub_vectl(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { + + _GDCPSET pset; + UINT dc; + REG16 x; + REG16 y; + UINT i; + UINT16 step; + UINT d1; + + gdcpset_prepare(&pset, csrw, pat, ope); + dc = (LOADINTELWORD(vect->DC)) & 0x3fff; + if (dc == 0) { + gdcpset(&pset, pset.x, pset.y); + } + else { + x = pset.x; + y = pset.y; + d1 = LOADINTELWORD(vect->D1); + switch(vect->ope & 7) { + case 0: + for (i=0; i<=dc; i++) { + step = (UINT16)((((d1 * i) / dc) + 1) >> 1); + gdcpset(&pset, (REG16)(x + step), y++); + } + break; + + case 1: + for (i=0; i<=dc; i++) { + step = (UINT16)((((d1 * i) / dc) + 1) >> 1); + gdcpset(&pset, x++, (REG16)(y + step)); + } + break; + + case 2: + for (i=0; i<=dc; i++) { + step = (UINT16)((((d1 * i) / dc) + 1) >> 1); + gdcpset(&pset, x++, (REG16)(y - step)); + } + break; + + case 3: + for (i=0; i<=dc; i++) { + step = (UINT16)((((d1 * i) / dc) + 1) >> 1); + gdcpset(&pset, (REG16)(x + step), y--); + } + break; + + case 4: + for (i=0; i<=dc; i++) { + step = (UINT16)((((d1 * i) / dc) + 1) >> 1); + gdcpset(&pset, (REG16)(x - step), y--); + } + break; + + case 5: + for (i=0; i<=dc; i++) { + step = (UINT16)((((d1 * i) / dc) + 1) >> 1); + gdcpset(&pset, x--, (REG16)(y - step)); + } + break; + + case 6: + for (i=0; i<=dc; i++) { + step = (UINT16)((((d1 * i) / dc) + 1) >> 1); + gdcpset(&pset, x--, (REG16)(y + step)); + } + break; + + case 7: + for (i=0; i<=dc; i++) { + step = (UINT16)((((d1 * i) / dc) + 1) >> 1); + gdcpset(&pset, (REG16)(x - step), y++); + } + break; + } + } + calc_gdcslavewait(pset.dots); +} + +void gdcsub_vectt(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { + + _GDCPSET pset; + UINT8 multiple; + UINT sx; +const VECTDIR *dir; + UINT8 muly; + REG16 cx; + REG16 cy; + UINT xrem; + UINT8 mulx; + + if (vect->ope & 0x80) { // SL + pat = (REG16)((GDCPATREVERSE(pat) << 8) + GDCPATREVERSE(pat >> 8)); + } + gdcpset_prepare(&pset, csrw, 0xffff, ope); + multiple = (gdc.s.para[GDC_ZOOM] & 15) + 1; + + sx = LOADINTELWORD(vect->D); + sx = ((sx - 1) & 0x3fff) + 1; + if (sx >= 768) { + sx = 768; + } + dir = vectdir + ((vect->ope) & 7); + + muly = multiple; + while(muly--) { + cx = pset.x; + cy = pset.y; + xrem = sx; + while(xrem--) { + mulx = multiple; + if (pat & 1) { + pat >>= 1; + pat |= 0x8000; + while(mulx--) { + gdcpset(&pset, cx, cy); + cx += dir->x; + cy += dir->y; + } + } + else { + pat >>= 1; + while(mulx--) { + cx += dir->x; + cy += dir->y; + } + } + } + pset.x += dir->x2; + pset.y += dir->y2; + } + calc_gdcslavewait(pset.dots); +} + +void gdcsub_vectc(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { + + _GDCPSET pset; + UINT r; + UINT m; + UINT i; + UINT t; + UINT x; + UINT y; + UINT s; + + gdcpset_prepare(&pset, csrw, pat, ope); + r = (LOADINTELWORD(vect->D)) & 0x3fff; + m = (r * 10000 + 14141) / 14142; + if (!m) { + gdcpset(&pset, pset.x, pset.y); + } + else { + i = (LOADINTELWORD(vect->DM)) & 0x3fff; + t = (LOADINTELWORD(vect->DC)) & 0x3fff; + x = pset.x; + y = pset.y; + if (t > m) { + t = m; + } + switch((vect->ope) & 7) { + case 0: + for (; i<=t; i++) { + s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); + s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; + gdcpset(&pset, (REG16)(x + s), (REG16)(y + i)); + } + break; + + case 1: + for (; i<=t; i++) { + s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); + s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; + gdcpset(&pset, (REG16)(x + i), (REG16)(y + s)); + } + break; + + case 2: + for (; i<=t; i++) { + s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); + s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; + gdcpset(&pset, (REG16)(x + i), (REG16)(y - s)); + } + break; + + case 3: + for (; i<=t; i++) { + s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); + s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; + gdcpset(&pset, (REG16)(x + s), (REG16)(y - i)); + } + break; + + case 4: + for (; i<=t; i++) { + s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); + s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; + gdcpset(&pset, (REG16)(x - s), (REG16)(y - i)); + } + break; + + case 5: + for (; i<=t; i++) { + s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); + s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; + gdcpset(&pset, (REG16)(x - i), (REG16)(y - s)); + } + break; + + case 6: + for (; i<=t; i++) { + s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); + s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; + gdcpset(&pset, (REG16)(x - i), (REG16)(y + s)); + } + break; + + case 7: + for (; i<=t; i++) { + s = (gdc_rt[(i << RT_TABLEBIT) / m] * r); + s = (s + (1 << (RT_MULBIT - 1))) >> RT_MULBIT; + gdcpset(&pset, (REG16)(x - s), (REG16)(y + i)); + } + break; + } + } + calc_gdcslavewait(pset.dots); +} + +void gdcsub_vectr(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope) { + + _GDCPSET pset; + UINT d; + UINT d2; + REG16 x; + REG16 y; + UINT i; +const VECTDIR *dir; + + gdcpset_prepare(&pset, csrw, pat, ope); + d = (LOADINTELWORD(vect->D)) & 0x3fff; + d2 = (LOADINTELWORD(vect->D2)) & 0x3fff; + x = pset.x; + y = pset.y; + dir = vectdir + ((vect->ope) & 7); + for (i=0; ix; + y += dir->y; + } + for (i=0; ix2; + y += dir->y2; + } + for (i=0; ix; + y -= dir->y; + } + for (i=0; ix2; + y -= dir->y2; + } + calc_gdcslavewait(pset.dots); +} + +void gdcsub_text(UINT32 csrw, const GDCVECT *vect, const UINT8 *pat, + REG8 ope) { + + _GDCPSET pset; + UINT8 multiple; + UINT sx; + UINT sy; +const VECTDIR *dir; + UINT patnum; + UINT8 muly; + REG16 cx; + REG16 cy; + UINT xrem; + UINT8 bit; + UINT8 mulx; + + gdcpset_prepare(&pset, csrw, 0xffff, ope); + multiple = (gdc.s.para[GDC_ZOOM] & 15) + 1; +#if 1 + sy = LOADINTELWORD(vect->DC); + sy = (sy & 0x3fff) + 1; + sx = LOADINTELWORD(vect->D); + sx = ((sx - 1) & 0x3fff) + 1; + + // てきとーにリミット + if (sx >= 768) { + sx = 768; + } + if (sy >= 768) { + sy = 768; + } +#else + sx = 8; + sy = 8; +#endif + dir = vectdir + (((vect->ope & 0x80) >> 4) + ((vect->ope) & 7)); + patnum = 0; + + while(sy--) { + muly = multiple; + patnum--; + while(muly--) { + cx = pset.x; + cy = pset.y; + bit = pat[patnum & 7]; + xrem = sx; + while(xrem--) { + mulx = multiple; + if (bit & 1) { + bit >>= 1; + bit |= 0x80; + while(mulx--) { + gdcpset(&pset, cx, cy); + cx += dir->x; + cy += dir->y; + } + } + else { + bit >>= 1; + while(mulx--) { + cx += dir->x; + cy += dir->y; + } + } + } + pset.x += dir->x2; + pset.y += dir->y2; + } + } + calc_gdcslavewait(pset.dots); +} + + +// ---- + +void gdcsub_write(void) { + + UINT16 mask; + UINT16 data; + UINT32 adrs; + UINT leng; + UINT8 *ptr; + UINT16 updatebit; + +#if 0 + TRACEOUT(("gdcsub_write")); + if (grcg.gdcwithgrcg & 0x8) { + MessageBox(NULL, "!!! grcg working", "?", MB_OK); + } +#endif + + mask = LOADINTELWORD(gdc.s.para + GDC_MASK); +#if defined(BYTESEX_LITTLE) + switch(gdc.s.cmd & 0x18) { + case 0x00: + data = LOADINTELWORD(gdc.s.para + GDC_CODE); + break; + + case 0x10: + mask &= 0x00ff; + data = gdc.s.para[GDC_CODE]; + break; + + case 0x18: + mask &= 0xff00; + data = gdc.s.para[GDC_CODE] << 8; + break; + + default: + return; + } +#else + switch(gdc.s.cmd & 0x18) { + case 0x00: + data = (gdc.s.para[GDC_CODE] << 8) + gdc.s.para[GDC_CODE + 1]; + break; + + case 0x10: + mask &= 0xff00; + data = gdc.s.para[GDC_CODE] << 8; + break; + + case 0x18: + mask &= 0x00ff; + data = gdc.s.para[GDC_CODE]; + break; + + default: + return; + } +#endif +#if 0 // これって uPD7220でも有効? + if (data != 0xffff) { + data = 0; + } +#endif + + adrs = LOADINTELDWORD(gdc.s.para + GDC_CSRW); + leng = LOADINTELWORD(gdc.s.para + GDC_VECTW + 1); + leng++; + ptr = mem; + if (!gdcs.access) { + updatebit = 0x0101; + } + else { + ptr += VRAM_STEP; + updatebit = 0x0202; + } + gdcs.grphdisp |= (UINT8)updatebit; + + ptr += gdcplaneseg[(adrs >> 14) & 3]; + adrs = (adrs & 0x3fff) << 1; + calc_gdcslavewait(leng); + + switch(gdc.s.cmd & 0x03) { + case 0x00: // replace + data &= mask; + mask = ~mask; + do { + *(UINT16 *)(ptr + adrs) &= mask; + *(UINT16 *)(ptr + adrs) |= data; + *(UINT16 *)(vramupdate + adrs) |= updatebit; + adrs = (adrs + 2) & 0x7ffe; + } while(--leng); + break; + + case 0x01: // complement + data &= mask; + do { + *(UINT16 *)(ptr + adrs) ^= data; + *(UINT16 *)(vramupdate + adrs) |= updatebit; + adrs = (adrs + 2) & 0x7ffe; + } while(--leng); + break; + + case 0x02: // clear + data &= mask; + do { + *(UINT16 *)(ptr + adrs) &= data; + *(UINT16 *)(vramupdate + adrs) |= updatebit; + adrs = (adrs + 2) & 0x7ffe; + } while(--leng); + break; + + case 0x03: // set + data &= mask; + do { + *(UINT16 *)(ptr + adrs) |= data; + *(UINT16 *)(vramupdate + adrs) |= updatebit; + adrs = (adrs + 2) & 0x7ffe; + } while(--leng); + break; + } +} + diff --git a/io/gdc_sub.h b/io/gdc_sub.h old mode 100755 new mode 100644 index 55db3bd4..d7a5bf8f --- a/io/gdc_sub.h +++ b/io/gdc_sub.h @@ -1,55 +1,55 @@ - -enum { - GDCOPE_REPLACE = 0, - GDCOPE_COMPLEMENT = 1, - GDCOPE_CLEAR = 2, - GDCOPE_SET = 3 -}; - -typedef struct { - UINT8 ope; - UINT8 DC[2]; - UINT8 D[2]; - UINT8 D2[2]; - UINT8 D1[2]; - UINT8 DM[2]; -} GDCVECT; - -extern const UINT32 gdcplaneseg[4]; - -typedef void (*GDCSUBFN)(UINT32 csrw, const GDCVECT *vect, - REG16 pat, REG8 ope); - - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) -extern const UINT8 gdcbitreverse[0x100]; -#define GDCPATREVERSE(d) gdcbitreverse[(d) & 0xff] -#else -REG8 gdcbitreverse(REG8 data); -#define GDCPATREVERSE(d) gdcbitreverse((REG8)(d)) -#endif - -void gdcslavewait(NEVENTITEM item); - -void gdcsub_initialize(void); -void gdcsub_setslavewait(UINT32 clock); -void gdcsub_setvectl(GDCVECT *vect, int x1, int y1, int x2, int y2); - -void gdcsub_vect0(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); -void gdcsub_vectp(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); -void gdcsub_vectl(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); -void gdcsub_vectt(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); -void gdcsub_vectc(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); -void gdcsub_vectr(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); - -void gdcsub_text(UINT32 csrw, const GDCVECT *vect, const UINT8 *pat, REG8 ope); -void gdcsub_write(void); - -#ifdef __cplusplus -} -#endif - + +enum { + GDCOPE_REPLACE = 0, + GDCOPE_COMPLEMENT = 1, + GDCOPE_CLEAR = 2, + GDCOPE_SET = 3 +}; + +typedef struct { + UINT8 ope; + UINT8 DC[2]; + UINT8 D[2]; + UINT8 D2[2]; + UINT8 D1[2]; + UINT8 DM[2]; +} GDCVECT; + +extern const UINT32 gdcplaneseg[4]; + +typedef void (*GDCSUBFN)(UINT32 csrw, const GDCVECT *vect, + REG16 pat, REG8 ope); + + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MEMOPTIMIZE) || (MEMOPTIMIZE < 2) +extern const UINT8 gdcbitreverse[0x100]; +#define GDCPATREVERSE(d) gdcbitreverse[(d) & 0xff] +#else +REG8 gdcbitreverse(REG8 data); +#define GDCPATREVERSE(d) gdcbitreverse((REG8)(d)) +#endif + +void gdcslavewait(NEVENTITEM item); + +void gdcsub_initialize(void); +void gdcsub_setslavewait(UINT32 clock); +void gdcsub_setvectl(GDCVECT *vect, int x1, int y1, int x2, int y2); + +void gdcsub_vect0(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); +void gdcsub_vectp(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); +void gdcsub_vectl(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); +void gdcsub_vectt(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); +void gdcsub_vectc(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); +void gdcsub_vectr(UINT32 csrw, const GDCVECT *vect, REG16 pat, REG8 ope); + +void gdcsub_text(UINT32 csrw, const GDCVECT *vect, const UINT8 *pat, REG8 ope); +void gdcsub_write(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/iocore.c b/io/iocore.c old mode 100755 new mode 100644 index e992ff3a..d00ee91b --- a/io/iocore.c +++ b/io/iocore.c @@ -1,845 +1,845 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "iocore16.tbl" -#ifdef SUPPORT_LGY98 -#include -#endif -#ifdef SUPPORT_WAB -#include -#endif -#ifdef SUPPORT_CL_GD5430 -#include -#endif -#ifdef SUPPORT_SMPU98 -#include -#include -#endif -#if defined(SUPPORT_HOSTDRVNT) -#include -#endif - - - _ARTIC artic; - _CGROM cgrom; - _CGWINDOW cgwindow; - _CRTC crtc; - _DMAC dmac; - _EGC egc; - _EPSONIO epsonio; - _EMSIO emsio; - _FDC fdc; - _GDC gdc; - _GDCS gdcs; - _GRCG grcg; - _KEYBRD keybrd; - _MOUSEIF mouseif; - _NECIO necio; - _NMIIO nmiio; - _NP2SYSP np2sysp; - _PIC pic; - _PIT pit; - _RS232C rs232c; -#if defined(SUPPORT_RS232C_FIFO) - _RS232CFIFO rs232cfifo; -#endif - _SYSPORT sysport; - _UPD4990 uPD4990; -#ifdef SUPPORT_HRTIMER - _UPD4990HRT uPD4990HRT; -#endif - -#if defined(SUPPORT_PC9821) - _PCIDEV pcidev; -#endif -#if defined(SUPPORT_PEGC) - _PEGC pegc; -#endif - - -// ---- - -enum { - IOFUNC_SYS = 0x01, - IOFUNC_SND = 0x02, - IOFUNC_EXT = 0x04 -}; - -typedef struct { - IOOUT ioout[256]; - IOINP ioinp[256]; - UINT type; - UINT port; -} _IOFUNC, *IOFUNC; - -typedef struct { - IOFUNC base[256]; - UINT busclock; - LISTARRAY iotbl; -} _IOCORE, *IOCORE; - -static _IOCORE iocore; -static UINT8 ioterminate[0x100]; - -//extern UINT lgy98_baseaddr; -//extern UINT ne2000_baseaddr; - -// ---- - -static void IOOUTCALL defout8(UINT port, REG8 dat) { - -#if !defined(DISABLE_SOUND) - if(cs4231.enable){ - UINT tmp; - - tmp = port - cs4231.port[0]; - if (tmp < 8) { - cs4231io0_w8(port, dat); - return; - } - tmp = port - cs4231.port[5]; - if (tmp < 2) { - cs4231io5_w8(port, dat); - return; - } - } -#endif - if ((port & 0xf0ff) == 0x801e) { - dipsw_w8(port, dat); - return; - } - //TRACEOUT(("defout8 - %x %x %.4x %.4x", port, dat, CPU_CS, CPU_IP)); -} - -static REG8 IOINPCALL definp8(UINT port) { - -#if !defined(DISABLE_SOUND) - if(cs4231.enable){ - UINT tmp; - - tmp = port - cs4231.port[0]; - if (tmp < 8) { - return(cs4231io0_r8(port)); - } - tmp = port - cs4231.port[5]; - if (tmp < 2) { - return(cs4231io5_r8(port)); - } - } -#endif - if ((port & 0xf0ff) == 0x801e) { - return(dipsw_r8(port)); - } - //TRACEOUT(("definp8 - %x %.4x %.4x", port, CPU_CS, CPU_IP)); - return(0xff); -} - - -static void attachout(IOFUNC iof, UINT port, IOOUT func) { - - if (func) { - iof->ioout[port] = func; - } -} -static void detachout(IOFUNC iof, UINT port) { - - iof->ioout[port] = &defout8; -} - -static void attachinp(IOFUNC iof, UINT port, IOINP func) { - - if (func) { - iof->ioinp[port] = func; - } -} -static void detachinp(IOFUNC iof, UINT port) { - - iof->ioinp[port] = &definp8; -} - - -// ---- out - -typedef struct { - UINT port; - UINT mask; -const IOOUT *func; - UINT funcs; -} _ATTOUT, *ATTOUT; - -static void attachoutex(IOFUNC iof, ATTOUT attout) { - - UINT port; - UINT mask; - UINT num; - UINT i; - - port = attout->port & 0xff; - mask = attout->mask & 0xff; - num = 0; - for (i=0; i<0x100; i++) { - if ((i & mask) == port) { - attachout(iof, i, attout->func[num]); - num = (num + 1) & (attout->funcs - 1); - } - } -} - -static BOOL attachcmnout(void *iotbl, void *attout) { - - attachoutex((IOFUNC)iotbl, (ATTOUT)attout); - return(FALSE); -} - -void iocore_attachcmnoutex(UINT port, UINT mask, - const IOOUT *func, UINT funcs) { - - _ATTOUT ao; - - ao.port = port; - ao.mask = mask; - ao.func = func; - ao.funcs = funcs; - listarray_enum(iocore.iotbl, attachcmnout, &ao); -} - -static BOOL attachsysout(void *iotbl, void *attout) { - - if ((((IOFUNC)iotbl)->type) & IOFUNC_SYS) { - attachoutex((IOFUNC)iotbl, (ATTOUT)attout); - } - return(FALSE); -} - -void iocore_attachsysoutex(UINT port, UINT mask, - const IOOUT *func, UINT funcs) { - - _ATTOUT ao; - - ao.port = port; - ao.mask = mask; - ao.func = func; - ao.funcs = funcs; - listarray_enum(iocore.iotbl, attachsysout, &ao); -} - - -// ---- inp - -typedef struct { - UINT port; - UINT mask; -const IOINP *func; - UINT funcs; -} _ATTINP, *ATTINP; - -static void attachinpex(IOFUNC iof, ATTINP attinp) { - - UINT port; - UINT mask; - UINT num; - UINT i; - - port = attinp->port & 0xff; - mask = attinp->mask & 0xff; - num = 0; - for (i=0; i<0x100; i++) { - if ((i & mask) == port) { - attachinp(iof, i, attinp->func[num]); - num = (num + 1) & (attinp->funcs - 1); - } - } -} - -static BOOL attachcmninp(void *iotbl, void *attinp) { - - attachinpex((IOFUNC)iotbl, (ATTINP)attinp); - return(FALSE); -} - -void iocore_attachcmninpex(UINT port, UINT mask, - const IOINP *func, UINT funcs) { - - _ATTINP ai; - - ai.port = port; - ai.mask = mask; - ai.func = func; - ai.funcs = funcs; - listarray_enum(iocore.iotbl, attachcmninp, &ai); -} - -static BOOL attachsysinp(void *iotbl, void *attinp) { - - if ((((IOFUNC)iotbl)->type) & IOFUNC_SYS) { - attachinpex((IOFUNC)iotbl, (ATTINP)attinp); - } - return(FALSE); -} - -void iocore_attachsysinpex(UINT port, UINT mask, - const IOINP *func, UINT funcs) { - - _ATTINP ai; - - ai.port = port; - ai.mask = mask; - ai.func = func; - ai.funcs = funcs; - listarray_enum(iocore.iotbl, attachsysinp, &ai); -} - -// ---- - -static BRESULT makesndiofunc(UINT port) { - - IOFUNC tbl[2]; - UINT num; - IOFUNC iof; - UINT type; - IOFUNC set; - - ZeroMemory(tbl, sizeof(tbl)); - num = (port >> 8) & 15; - do { - iof = iocore.base[num]; - type = iof->type; - if (!(type & (IOFUNC_SND | IOFUNC_EXT))) { - set = tbl[type & IOFUNC_SYS]; - if (set == NULL) { - set = (IOFUNC)listarray_append(iocore.iotbl, iof); - if (set == NULL) { - return(FAILURE); - } - set->type |= IOFUNC_SND; - set->port = port & 0x0f00; - } - iocore.base[num] = set; - } - num += 0x10; - } while(num < 0x100); - return(SUCCESS); -} - -BRESULT iocore_attachsndout(UINT port, IOOUT func) { - - BRESULT r; - UINT num; - - r = makesndiofunc(port); - if (r == SUCCESS) { - num = (port >> 8) & 15; - do { - attachout(iocore.base[num], port & 0xff, func); - num += 0x10; - } while(num < 0x100); - } - return(r); -} -BRESULT iocore_detachsndout(UINT port) { - - BRESULT r; - UINT num; - - r = makesndiofunc(port); - if (r == SUCCESS) { - num = (port >> 8) & 15; - do { - detachout(iocore.base[num], port & 0xff); - num += 0x10; - } while(num < 0x100); - } - return(r); -} - -BRESULT iocore_attachsndinp(UINT port, IOINP func) { - - BRESULT r; - UINT num; - - r = makesndiofunc(port); - if (r == SUCCESS) { - num = (port >> 8) & 15; - do { - attachinp(iocore.base[num], port & 0xff, func); - num += 0x10; - } while(num < 0x100); - } - return(r); -} -BRESULT iocore_detachsndinp(UINT port) { - - BRESULT r; - UINT num; - - r = makesndiofunc(port); - if (r == SUCCESS) { - num = (port >> 8) & 15; - do { - detachinp(iocore.base[num], port & 0xff); - num += 0x10; - } while(num < 0x100); - } - return(r); -} - - -// ---- - -static IOFUNC getextiofunc(UINT port) { - - IOFUNC iof; - - iof = iocore.base[(port >> 8) & 0xff]; - if (!(iof->type & IOFUNC_EXT)) { - iof = (IOFUNC)listarray_append(iocore.iotbl, iof); - if (iof != NULL) { - iocore.base[(port >> 8) & 0xff] = iof; - iof->type |= IOFUNC_EXT; - iof->port = port & 0xff00; - } - } - return(iof); -} - -BRESULT iocore_attachout(UINT port, IOOUT func) { - - IOFUNC iof; - - iof = getextiofunc(port); - if (iof) { - attachout(iof, port & 0xff, func); - return(SUCCESS); - } - else { - return(FAILURE); - } -} -BRESULT iocore_detachout(UINT port) { - - IOFUNC iof; - - iof = getextiofunc(port); - if (iof) { - detachout(iof, port & 0xff); - return(SUCCESS); - } - else { - return(FAILURE); - } -} - -BRESULT iocore_attachinp(UINT port, IOINP func) { - - IOFUNC iof; - - iof = getextiofunc(port); - if (iof) { - attachinp(iof, port & 0xff, func); - return(SUCCESS); - } - else { - return(FAILURE); - } -} -BRESULT iocore_detachinp(UINT port) { - - IOFUNC iof; - - iof = getextiofunc(port); - if (iof) { - detachinp(iof, port & 0xff); - return(SUCCESS); - } - else { - return(FAILURE); - } -} - - -// ---- - -void iocore_create(void) { - - UINT i; -const UINT8 *p; - UINT r; - - ZeroMemory(&iocore, sizeof(iocore)); - ZeroMemory(ioterminate, sizeof(ioterminate)); - for (i=0; iiotbl); - ioc->iotbl = NULL; -} - -BRESULT iocore_build(void) { - - IOCORE ioc; - IOFUNC cmn; - IOFUNC sys; - int i; - LISTARRAY iotbl; - - ioc = &iocore; - listarray_destroy(ioc->iotbl); - iotbl = listarray_new(sizeof(_IOFUNC), 32); - ioc->iotbl = iotbl; - if (iotbl == NULL) { - goto icbld_err; - } - cmn = (IOFUNC)listarray_append(iotbl, NULL); - if (cmn == NULL) { - goto icbld_err; - } - for (i=0; i<256; i++) { - cmn->ioout[i] = defout8; - cmn->ioinp[i] = definp8; - } - sys = (IOFUNC)listarray_append(iotbl, cmn); - if (sys == NULL) { - goto icbld_err; - } - sys->type = IOFUNC_SYS; - for (i=0; i<256; i++) { -#ifdef SUPPORT_PC9821 - if (!(i & (0x0c|(np2cfg.sysiomsk >> 8)))) { // PC-9821用 追加マスク(0x0c -> 0xff) np21w ver0.86 rev37 -#else - if (!(i & 0x0c)) { -#endif - ioc->base[i] = sys; - } - else { - ioc->base[i] = cmn; - } - } - return(SUCCESS); - -icbld_err: - return(FAILURE); -} - - -// ---- - -static const FNIORESET resetfn[] = -{ - // PC-9801 System... - cgrom_reset, crtc_reset, - dmac_reset, gdc_reset, fdc_reset, - keyboard_reset, nmiio_reset, pic_reset, - printif_reset, rs232c_reset, systemport_reset, - uPD4990_reset, fdd320_reset, - - // sys+extend - itimer_reset, mouseif_reset, - - // extend - artic_reset, egc_reset, np2sysp_reset, - necio_reset, epsonio_reset, emsio_reset, -#if defined(SUPPORT_PC9821) - pcidev_reset, -#endif -}; - -static const FNIOBIND bindfn[] = -{ - // PC-9801 System... - cgrom_bind, cpuio_bind, crtc_bind, - dmac_bind, gdc_bind, fdc_bind, - keyboard_bind, nmiio_bind, pic_bind, - printif_bind, rs232c_bind, systemport_bind, - uPD4990_bind, fdd320_bind, - - // sys+extend - itimer_bind, mouseif_bind, - - // extend - artic_bind, egc_bind, np2sysp_bind, - necio_bind, epsonio_bind, emsio_bind, -#if defined(SUPPORT_PC9821) - pcidev_bind, -#endif -#if defined(SUPPORT_HOSTDRVNT) - hostdrvNT_bind, -#endif -}; - - -void iocore_cbreset(const FNIORESET *pfn, UINT uCount, const NP2CFG *pConfig) -{ - while(uCount--) - { - (*pfn)(pConfig); - pfn++; - } -} - -void iocore_cbbind(const FNIOBIND *pfn, UINT uCount) -{ - while(uCount--) - { - (*pfn)(); - pfn++; - } -} - -void iocore_reset(const NP2CFG *pConfig) -{ - iocore_cbreset(resetfn, NELEMENTS(resetfn), pConfig); -} - -void iocore_bind(void) -{ - iocore.busclock = pccore.multiple; - iocore_cbbind(bindfn, NELEMENTS(bindfn)); -} - -void IOOUTCALL iocore_out8(UINT port, REG8 dat) { - - IOFUNC iof; - -// TRACEOUT(("iocore_out8(%.2x, %.2x)", port, dat)); - CPU_REMCLOCK -= iocore.busclock; - iof = iocore.base[(port >> 8) & 0xff]; - iof->ioout[port & 0xff](port, dat); -} - -REG8 IOINPCALL iocore_inp8(UINT port) { - - IOFUNC iof; - REG8 ret; - - CPU_REMCLOCK -= iocore.busclock; - iof = iocore.base[(port >> 8) & 0xff]; - ret = iof->ioinp[port & 0xff](port); -// TRACEOUT(("iocore_inp8(%.2x) -> %.2x", port, ret)); - return(ret); -} - -void IOOUTCALL iocore_out16(UINT port, REG16 dat) { - - IOFUNC iof; - -// TRACEOUT(("iocore_out16(%.4x, %.4x)", port, dat)); - CPU_REMCLOCK -= iocore.busclock; -#if defined(SUPPORT_PC9821)&&defined(SUPPORT_PCI) - if (0x0cfc <= port && port <= 0x0cff) { - pcidev_w16_0xcfc(port, dat); - return; - } -#endif -#if defined(SUPPORT_IDEIO) - if (port == 0x0640) { - ideio_w16(port, dat); - return; - } -#endif -#if defined(SUPPORT_LGY98) - if (lgy98cfg.enabled && port == lgy98cfg.baseaddr + 0x200) { - lgy98_ob200_16(port, dat); - return; - } -#endif -#if defined(SUPPORT_SMPU98) - if (smpu98.enable && smpu98.port <= port && port <= smpu98.port + 0xf) { - if(smpu98_io16outfunc[port - smpu98.port]){ - (*smpu98_io16outfunc[port - smpu98.port])(port, dat); - return; - } - } -#endif -#if defined(SUPPORT_CL_GD5430) - if(np2clvga.enabled && cirrusvga_opaque){ - if((np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - if(pc98_cirrus_isWABport(port)){ - cirrusvga_ioport_write_wrap16(port, (UINT16)dat); - return; - } - }else if(np2clvga.gd54xxtype <= 0xff){ - if(port == 0xc44){ - if(dat == 0xffff){ - pc98_cirrus_vga_setVRAMWindowAddr3(0); - }else{ - pc98_cirrus_vga_setVRAMWindowAddr3(((UINT32)dat) << 16); - } - return; - } - } - } -#endif - if ((port & 0xfff1) == 0x04a0) { - egc_w16(port, dat); - return; - } - if (!(port & 0x0c00)) { - switch(ioterminate[port & 0xff]) { - case TERM_WORD: - return; - - case TERM_ACTIVE: - case TERM_PLUS: - case TERM_MINUS: - case TERM_EXT08: - iof = iocore.base[(port >> 8) & 0xff]; - iof->ioout[port & 0xff](port, (UINT8)dat); - return; - } - } - iof = iocore.base[(port >> 8) & 0xff]; - iof->ioout[port & 0xff](port, (UINT8)dat); - port++; - iof = iocore.base[(port >> 8) & 0xff]; - iof->ioout[port & 0xff](port, (UINT8)(dat >> 8)); -} - -REG16 IOINPCALL iocore_inp16(UINT port) { - - IOFUNC iof; - REG8 ret; - - CPU_REMCLOCK -= iocore.busclock; -#if defined(SUPPORT_PC9821)&&defined(SUPPORT_PCI) - if (0x0cfc <= port && port <= 0x0cff) { - return(pcidev_r16_0xcfc(port)); - } -#endif -#if defined(SUPPORT_IDEIO) - if (port == 0x0640) { - return(ideio_r16(port)); - } -#endif -#if defined(SUPPORT_LGY98) - if (lgy98cfg.enabled && port == lgy98cfg.baseaddr + 0x200) { - return(lgy98_ib200_16(port)); - } -#endif -#if defined(SUPPORT_SMPU98) - if (smpu98.enable && smpu98.port <= port && port <= smpu98.port + 0xf) { - if(smpu98_io16inpfunc[port - smpu98.port]){ - return (*smpu98_io16inpfunc[port - smpu98.port])(port); - } - } -#endif -#if defined(SUPPORT_CL_GD5430) - if(np2clvga.enabled && cirrusvga_opaque){ - if((np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - if(pc98_cirrus_isWABport(port)){ - return(cirrusvga_ioport_read_wrap16(port)); - } - }else if(np2clvga.gd54xxtype <= 0xff){ - if(port == 0xc44){ - return(np2clvga.VRAMWindowAddr3 >> 16); - } - } - } -#endif - if ((port & 0xfffc) == 0x005c) { - return(artic_r16(port)); - } - iof = iocore.base[(port >> 8) & 0xff]; - if (!(port & 0x0c00)) { - switch(ioterminate[port & 0xff]) { - case TERM_WORD: - return(WORD_TERMINATE); - - case TERM_ACTIVE: - ret = iof->ioinp[port & 0xff](port); - return((CPU_AX & 0xff00) + ret); - - case TERM_PLUS: - ret = iof->ioinp[port & 0xff](port); - return(0xff00 + ret); - - case TERM_MINUS: - return(iof->ioinp[port & 0xff](port)); - - case TERM_EXT08: - ret = iof->ioinp[port & 0xff](port); - return(0x0800 + ret); - } - } - ret = iof->ioinp[port & 0xff](port); - port++; - iof = iocore.base[(port >> 8) & 0xff]; - return((UINT16)((iof->ioinp[port & 0xff](port) << 8) + ret)); -} - -void IOOUTCALL iocore_out32(UINT port, UINT32 dat) { - - CPU_REMCLOCK -= iocore.busclock; -#if defined(SUPPORT_PC9821) - if ((port & 0xfffb) == 0x0cf8) { - pcidev_w32(port, dat); - return; - } -#endif -#if defined(SUPPORT_CL_GD5430) - if(np2clvga.enabled && cirrusvga_opaque){ - if((np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - if(pc98_cirrus_isWABport(port)){ - cirrusvga_ioport_write_wrap32(port, (UINT32)dat); - return; - } - } - } -#endif -//#if defined(SUPPORT_IDEIO) -// if (port == 0x0640) { -// ideio_w16(port, (UINT16)dat); -// ideio_w16(port, (UINT16)(dat >> 16)); -// return; -// } -//#endif - iocore_out16(port, (UINT16)dat); - iocore_out16(port+2, (UINT16)(dat >> 16)); -} - -UINT32 IOINPCALL iocore_inp32(UINT port) { - - UINT32 ret; - - CPU_REMCLOCK -= iocore.busclock; -#if defined(SUPPORT_PC9821) - if ((port & 0xfffb) == 0x0cf8) { - return(pcidev_r32(port)); - } -#endif -#if defined(SUPPORT_CL_GD5430) - if(np2clvga.enabled && cirrusvga_opaque){ - if((np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - if(pc98_cirrus_isWABport(port)){ - return(cirrusvga_ioport_read_wrap32(port)); - } - } - } -#endif -//#if defined(SUPPORT_IDEIO) -// if (port == 0x0640) { -// ret = ideio_r16(port); -// ret |= ideio_r16(port) << 16; -// return ret; -// } -//#endif - ret = iocore_inp16(port); - return(ret + (iocore_inp16(port+2) << 16)); -} - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "iocore16.tbl" +#ifdef SUPPORT_LGY98 +#include +#endif +#ifdef SUPPORT_WAB +#include +#endif +#ifdef SUPPORT_CL_GD5430 +#include +#endif +#ifdef SUPPORT_SMPU98 +#include +#include +#endif +#if defined(SUPPORT_HOSTDRVNT) +#include +#endif + + + _ARTIC artic; + _CGROM cgrom; + _CGWINDOW cgwindow; + _CRTC crtc; + _DMAC dmac; + _EGC egc; + _EPSONIO epsonio; + _EMSIO emsio; + _FDC fdc; + _GDC gdc; + _GDCS gdcs; + _GRCG grcg; + _KEYBRD keybrd; + _MOUSEIF mouseif; + _NECIO necio; + _NMIIO nmiio; + _NP2SYSP np2sysp; + _PIC pic; + _PIT pit; + _RS232C rs232c; +#if defined(SUPPORT_RS232C_FIFO) + _RS232CFIFO rs232cfifo; +#endif + _SYSPORT sysport; + _UPD4990 uPD4990; +#ifdef SUPPORT_HRTIMER + _UPD4990HRT uPD4990HRT; +#endif + +#if defined(SUPPORT_PC9821) + _PCIDEV pcidev; +#endif +#if defined(SUPPORT_PEGC) + _PEGC pegc; +#endif + + +// ---- + +enum { + IOFUNC_SYS = 0x01, + IOFUNC_SND = 0x02, + IOFUNC_EXT = 0x04 +}; + +typedef struct { + IOOUT ioout[256]; + IOINP ioinp[256]; + UINT type; + UINT port; +} _IOFUNC, *IOFUNC; + +typedef struct { + IOFUNC base[256]; + UINT busclock; + LISTARRAY iotbl; +} _IOCORE, *IOCORE; + +static _IOCORE iocore; +static UINT8 ioterminate[0x100]; + +//extern UINT lgy98_baseaddr; +//extern UINT ne2000_baseaddr; + +// ---- + +static void IOOUTCALL defout8(UINT port, REG8 dat) { + +#if !defined(DISABLE_SOUND) + if(cs4231.enable){ + UINT tmp; + + tmp = port - cs4231.port[0]; + if (tmp < 8) { + cs4231io0_w8(port, dat); + return; + } + tmp = port - cs4231.port[5]; + if (tmp < 2) { + cs4231io5_w8(port, dat); + return; + } + } +#endif + if ((port & 0xf0ff) == 0x801e) { + dipsw_w8(port, dat); + return; + } + //TRACEOUT(("defout8 - %x %x %.4x %.4x", port, dat, CPU_CS, CPU_IP)); +} + +static REG8 IOINPCALL definp8(UINT port) { + +#if !defined(DISABLE_SOUND) + if(cs4231.enable){ + UINT tmp; + + tmp = port - cs4231.port[0]; + if (tmp < 8) { + return(cs4231io0_r8(port)); + } + tmp = port - cs4231.port[5]; + if (tmp < 2) { + return(cs4231io5_r8(port)); + } + } +#endif + if ((port & 0xf0ff) == 0x801e) { + return(dipsw_r8(port)); + } + //TRACEOUT(("definp8 - %x %.4x %.4x", port, CPU_CS, CPU_IP)); + return(0xff); +} + + +static void attachout(IOFUNC iof, UINT port, IOOUT func) { + + if (func) { + iof->ioout[port] = func; + } +} +static void detachout(IOFUNC iof, UINT port) { + + iof->ioout[port] = &defout8; +} + +static void attachinp(IOFUNC iof, UINT port, IOINP func) { + + if (func) { + iof->ioinp[port] = func; + } +} +static void detachinp(IOFUNC iof, UINT port) { + + iof->ioinp[port] = &definp8; +} + + +// ---- out + +typedef struct { + UINT port; + UINT mask; +const IOOUT *func; + UINT funcs; +} _ATTOUT, *ATTOUT; + +static void attachoutex(IOFUNC iof, ATTOUT attout) { + + UINT port; + UINT mask; + UINT num; + UINT i; + + port = attout->port & 0xff; + mask = attout->mask & 0xff; + num = 0; + for (i=0; i<0x100; i++) { + if ((i & mask) == port) { + attachout(iof, i, attout->func[num]); + num = (num + 1) & (attout->funcs - 1); + } + } +} + +static BOOL attachcmnout(void *iotbl, void *attout) { + + attachoutex((IOFUNC)iotbl, (ATTOUT)attout); + return(FALSE); +} + +void iocore_attachcmnoutex(UINT port, UINT mask, + const IOOUT *func, UINT funcs) { + + _ATTOUT ao; + + ao.port = port; + ao.mask = mask; + ao.func = func; + ao.funcs = funcs; + listarray_enum(iocore.iotbl, attachcmnout, &ao); +} + +static BOOL attachsysout(void *iotbl, void *attout) { + + if ((((IOFUNC)iotbl)->type) & IOFUNC_SYS) { + attachoutex((IOFUNC)iotbl, (ATTOUT)attout); + } + return(FALSE); +} + +void iocore_attachsysoutex(UINT port, UINT mask, + const IOOUT *func, UINT funcs) { + + _ATTOUT ao; + + ao.port = port; + ao.mask = mask; + ao.func = func; + ao.funcs = funcs; + listarray_enum(iocore.iotbl, attachsysout, &ao); +} + + +// ---- inp + +typedef struct { + UINT port; + UINT mask; +const IOINP *func; + UINT funcs; +} _ATTINP, *ATTINP; + +static void attachinpex(IOFUNC iof, ATTINP attinp) { + + UINT port; + UINT mask; + UINT num; + UINT i; + + port = attinp->port & 0xff; + mask = attinp->mask & 0xff; + num = 0; + for (i=0; i<0x100; i++) { + if ((i & mask) == port) { + attachinp(iof, i, attinp->func[num]); + num = (num + 1) & (attinp->funcs - 1); + } + } +} + +static BOOL attachcmninp(void *iotbl, void *attinp) { + + attachinpex((IOFUNC)iotbl, (ATTINP)attinp); + return(FALSE); +} + +void iocore_attachcmninpex(UINT port, UINT mask, + const IOINP *func, UINT funcs) { + + _ATTINP ai; + + ai.port = port; + ai.mask = mask; + ai.func = func; + ai.funcs = funcs; + listarray_enum(iocore.iotbl, attachcmninp, &ai); +} + +static BOOL attachsysinp(void *iotbl, void *attinp) { + + if ((((IOFUNC)iotbl)->type) & IOFUNC_SYS) { + attachinpex((IOFUNC)iotbl, (ATTINP)attinp); + } + return(FALSE); +} + +void iocore_attachsysinpex(UINT port, UINT mask, + const IOINP *func, UINT funcs) { + + _ATTINP ai; + + ai.port = port; + ai.mask = mask; + ai.func = func; + ai.funcs = funcs; + listarray_enum(iocore.iotbl, attachsysinp, &ai); +} + +// ---- + +static BRESULT makesndiofunc(UINT port) { + + IOFUNC tbl[2]; + UINT num; + IOFUNC iof; + UINT type; + IOFUNC set; + + ZeroMemory(tbl, sizeof(tbl)); + num = (port >> 8) & 15; + do { + iof = iocore.base[num]; + type = iof->type; + if (!(type & (IOFUNC_SND | IOFUNC_EXT))) { + set = tbl[type & IOFUNC_SYS]; + if (set == NULL) { + set = (IOFUNC)listarray_append(iocore.iotbl, iof); + if (set == NULL) { + return(FAILURE); + } + set->type |= IOFUNC_SND; + set->port = port & 0x0f00; + } + iocore.base[num] = set; + } + num += 0x10; + } while(num < 0x100); + return(SUCCESS); +} + +BRESULT iocore_attachsndout(UINT port, IOOUT func) { + + BRESULT r; + UINT num; + + r = makesndiofunc(port); + if (r == SUCCESS) { + num = (port >> 8) & 15; + do { + attachout(iocore.base[num], port & 0xff, func); + num += 0x10; + } while(num < 0x100); + } + return(r); +} +BRESULT iocore_detachsndout(UINT port) { + + BRESULT r; + UINT num; + + r = makesndiofunc(port); + if (r == SUCCESS) { + num = (port >> 8) & 15; + do { + detachout(iocore.base[num], port & 0xff); + num += 0x10; + } while(num < 0x100); + } + return(r); +} + +BRESULT iocore_attachsndinp(UINT port, IOINP func) { + + BRESULT r; + UINT num; + + r = makesndiofunc(port); + if (r == SUCCESS) { + num = (port >> 8) & 15; + do { + attachinp(iocore.base[num], port & 0xff, func); + num += 0x10; + } while(num < 0x100); + } + return(r); +} +BRESULT iocore_detachsndinp(UINT port) { + + BRESULT r; + UINT num; + + r = makesndiofunc(port); + if (r == SUCCESS) { + num = (port >> 8) & 15; + do { + detachinp(iocore.base[num], port & 0xff); + num += 0x10; + } while(num < 0x100); + } + return(r); +} + + +// ---- + +static IOFUNC getextiofunc(UINT port) { + + IOFUNC iof; + + iof = iocore.base[(port >> 8) & 0xff]; + if (!(iof->type & IOFUNC_EXT)) { + iof = (IOFUNC)listarray_append(iocore.iotbl, iof); + if (iof != NULL) { + iocore.base[(port >> 8) & 0xff] = iof; + iof->type |= IOFUNC_EXT; + iof->port = port & 0xff00; + } + } + return(iof); +} + +BRESULT iocore_attachout(UINT port, IOOUT func) { + + IOFUNC iof; + + iof = getextiofunc(port); + if (iof) { + attachout(iof, port & 0xff, func); + return(SUCCESS); + } + else { + return(FAILURE); + } +} +BRESULT iocore_detachout(UINT port) { + + IOFUNC iof; + + iof = getextiofunc(port); + if (iof) { + detachout(iof, port & 0xff); + return(SUCCESS); + } + else { + return(FAILURE); + } +} + +BRESULT iocore_attachinp(UINT port, IOINP func) { + + IOFUNC iof; + + iof = getextiofunc(port); + if (iof) { + attachinp(iof, port & 0xff, func); + return(SUCCESS); + } + else { + return(FAILURE); + } +} +BRESULT iocore_detachinp(UINT port) { + + IOFUNC iof; + + iof = getextiofunc(port); + if (iof) { + detachinp(iof, port & 0xff); + return(SUCCESS); + } + else { + return(FAILURE); + } +} + + +// ---- + +void iocore_create(void) { + + UINT i; +const UINT8 *p; + UINT r; + + ZeroMemory(&iocore, sizeof(iocore)); + ZeroMemory(ioterminate, sizeof(ioterminate)); + for (i=0; iiotbl); + ioc->iotbl = NULL; +} + +BRESULT iocore_build(void) { + + IOCORE ioc; + IOFUNC cmn; + IOFUNC sys; + int i; + LISTARRAY iotbl; + + ioc = &iocore; + listarray_destroy(ioc->iotbl); + iotbl = listarray_new(sizeof(_IOFUNC), 32); + ioc->iotbl = iotbl; + if (iotbl == NULL) { + goto icbld_err; + } + cmn = (IOFUNC)listarray_append(iotbl, NULL); + if (cmn == NULL) { + goto icbld_err; + } + for (i=0; i<256; i++) { + cmn->ioout[i] = defout8; + cmn->ioinp[i] = definp8; + } + sys = (IOFUNC)listarray_append(iotbl, cmn); + if (sys == NULL) { + goto icbld_err; + } + sys->type = IOFUNC_SYS; + for (i=0; i<256; i++) { +#ifdef SUPPORT_PC9821 + if (!(i & (0x0c|(np2cfg.sysiomsk >> 8)))) { // PC-9821用 追加マスク(0x0c -> 0xff) np21w ver0.86 rev37 +#else + if (!(i & 0x0c)) { +#endif + ioc->base[i] = sys; + } + else { + ioc->base[i] = cmn; + } + } + return(SUCCESS); + +icbld_err: + return(FAILURE); +} + + +// ---- + +static const FNIORESET resetfn[] = +{ + // PC-9801 System... + cgrom_reset, crtc_reset, + dmac_reset, gdc_reset, fdc_reset, + keyboard_reset, nmiio_reset, pic_reset, + printif_reset, rs232c_reset, systemport_reset, + uPD4990_reset, fdd320_reset, + + // sys+extend + itimer_reset, mouseif_reset, + + // extend + artic_reset, egc_reset, np2sysp_reset, + necio_reset, epsonio_reset, emsio_reset, +#if defined(SUPPORT_PC9821) + pcidev_reset, +#endif +}; + +static const FNIOBIND bindfn[] = +{ + // PC-9801 System... + cgrom_bind, cpuio_bind, crtc_bind, + dmac_bind, gdc_bind, fdc_bind, + keyboard_bind, nmiio_bind, pic_bind, + printif_bind, rs232c_bind, systemport_bind, + uPD4990_bind, fdd320_bind, + + // sys+extend + itimer_bind, mouseif_bind, + + // extend + artic_bind, egc_bind, np2sysp_bind, + necio_bind, epsonio_bind, emsio_bind, +#if defined(SUPPORT_PC9821) + pcidev_bind, +#endif +#if defined(SUPPORT_HOSTDRVNT) + hostdrvNT_bind, +#endif +}; + + +void iocore_cbreset(const FNIORESET *pfn, UINT uCount, const NP2CFG *pConfig) +{ + while(uCount--) + { + (*pfn)(pConfig); + pfn++; + } +} + +void iocore_cbbind(const FNIOBIND *pfn, UINT uCount) +{ + while(uCount--) + { + (*pfn)(); + pfn++; + } +} + +void iocore_reset(const NP2CFG *pConfig) +{ + iocore_cbreset(resetfn, NELEMENTS(resetfn), pConfig); +} + +void iocore_bind(void) +{ + iocore.busclock = pccore.multiple; + iocore_cbbind(bindfn, NELEMENTS(bindfn)); +} + +void IOOUTCALL iocore_out8(UINT port, REG8 dat) { + + IOFUNC iof; + +// TRACEOUT(("iocore_out8(%.2x, %.2x)", port, dat)); + CPU_REMCLOCK -= iocore.busclock; + iof = iocore.base[(port >> 8) & 0xff]; + iof->ioout[port & 0xff](port, dat); +} + +REG8 IOINPCALL iocore_inp8(UINT port) { + + IOFUNC iof; + REG8 ret; + + CPU_REMCLOCK -= iocore.busclock; + iof = iocore.base[(port >> 8) & 0xff]; + ret = iof->ioinp[port & 0xff](port); +// TRACEOUT(("iocore_inp8(%.2x) -> %.2x", port, ret)); + return(ret); +} + +void IOOUTCALL iocore_out16(UINT port, REG16 dat) { + + IOFUNC iof; + +// TRACEOUT(("iocore_out16(%.4x, %.4x)", port, dat)); + CPU_REMCLOCK -= iocore.busclock; +#if defined(SUPPORT_PC9821)&&defined(SUPPORT_PCI) + if (0x0cfc <= port && port <= 0x0cff) { + pcidev_w16_0xcfc(port, dat); + return; + } +#endif +#if defined(SUPPORT_IDEIO) + if (port == 0x0640) { + ideio_w16(port, dat); + return; + } +#endif +#if defined(SUPPORT_LGY98) + if (lgy98cfg.enabled && port == lgy98cfg.baseaddr + 0x200) { + lgy98_ob200_16(port, dat); + return; + } +#endif +#if defined(SUPPORT_SMPU98) + if (smpu98.enable && smpu98.port <= port && port <= smpu98.port + 0xf) { + if(smpu98_io16outfunc[port - smpu98.port]){ + (*smpu98_io16outfunc[port - smpu98.port])(port, dat); + return; + } + } +#endif +#if defined(SUPPORT_CL_GD5430) + if(np2clvga.enabled && cirrusvga_opaque){ + if((np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + if(pc98_cirrus_isWABport(port)){ + cirrusvga_ioport_write_wrap16(port, (UINT16)dat); + return; + } + }else if(np2clvga.gd54xxtype <= 0xff){ + if(port == 0xc44){ + if(dat == 0xffff){ + pc98_cirrus_vga_setVRAMWindowAddr3(0); + }else{ + pc98_cirrus_vga_setVRAMWindowAddr3(((UINT32)dat) << 16); + } + return; + } + } + } +#endif + if ((port & 0xfff1) == 0x04a0) { + egc_w16(port, dat); + return; + } + if (!(port & 0x0c00)) { + switch(ioterminate[port & 0xff]) { + case TERM_WORD: + return; + + case TERM_ACTIVE: + case TERM_PLUS: + case TERM_MINUS: + case TERM_EXT08: + iof = iocore.base[(port >> 8) & 0xff]; + iof->ioout[port & 0xff](port, (UINT8)dat); + return; + } + } + iof = iocore.base[(port >> 8) & 0xff]; + iof->ioout[port & 0xff](port, (UINT8)dat); + port++; + iof = iocore.base[(port >> 8) & 0xff]; + iof->ioout[port & 0xff](port, (UINT8)(dat >> 8)); +} + +REG16 IOINPCALL iocore_inp16(UINT port) { + + IOFUNC iof; + REG8 ret; + + CPU_REMCLOCK -= iocore.busclock; +#if defined(SUPPORT_PC9821)&&defined(SUPPORT_PCI) + if (0x0cfc <= port && port <= 0x0cff) { + return(pcidev_r16_0xcfc(port)); + } +#endif +#if defined(SUPPORT_IDEIO) + if (port == 0x0640) { + return(ideio_r16(port)); + } +#endif +#if defined(SUPPORT_LGY98) + if (lgy98cfg.enabled && port == lgy98cfg.baseaddr + 0x200) { + return(lgy98_ib200_16(port)); + } +#endif +#if defined(SUPPORT_SMPU98) + if (smpu98.enable && smpu98.port <= port && port <= smpu98.port + 0xf) { + if(smpu98_io16inpfunc[port - smpu98.port]){ + return (*smpu98_io16inpfunc[port - smpu98.port])(port); + } + } +#endif +#if defined(SUPPORT_CL_GD5430) + if(np2clvga.enabled && cirrusvga_opaque){ + if((np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + if(pc98_cirrus_isWABport(port)){ + return(cirrusvga_ioport_read_wrap16(port)); + } + }else if(np2clvga.gd54xxtype <= 0xff){ + if(port == 0xc44){ + return(np2clvga.VRAMWindowAddr3 >> 16); + } + } + } +#endif + if ((port & 0xfffc) == 0x005c) { + return(artic_r16(port)); + } + iof = iocore.base[(port >> 8) & 0xff]; + if (!(port & 0x0c00)) { + switch(ioterminate[port & 0xff]) { + case TERM_WORD: + return(WORD_TERMINATE); + + case TERM_ACTIVE: + ret = iof->ioinp[port & 0xff](port); + return((CPU_AX & 0xff00) + ret); + + case TERM_PLUS: + ret = iof->ioinp[port & 0xff](port); + return(0xff00 + ret); + + case TERM_MINUS: + return(iof->ioinp[port & 0xff](port)); + + case TERM_EXT08: + ret = iof->ioinp[port & 0xff](port); + return(0x0800 + ret); + } + } + ret = iof->ioinp[port & 0xff](port); + port++; + iof = iocore.base[(port >> 8) & 0xff]; + return((UINT16)((iof->ioinp[port & 0xff](port) << 8) + ret)); +} + +void IOOUTCALL iocore_out32(UINT port, UINT32 dat) { + + CPU_REMCLOCK -= iocore.busclock; +#if defined(SUPPORT_PC9821) + if ((port & 0xfffb) == 0x0cf8) { + pcidev_w32(port, dat); + return; + } +#endif +#if defined(SUPPORT_CL_GD5430) + if(np2clvga.enabled && cirrusvga_opaque){ + if((np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + if(pc98_cirrus_isWABport(port)){ + cirrusvga_ioport_write_wrap32(port, (UINT32)dat); + return; + } + } + } +#endif +//#if defined(SUPPORT_IDEIO) +// if (port == 0x0640) { +// ideio_w16(port, (UINT16)dat); +// ideio_w16(port, (UINT16)(dat >> 16)); +// return; +// } +//#endif + iocore_out16(port, (UINT16)dat); + iocore_out16(port+2, (UINT16)(dat >> 16)); +} + +UINT32 IOINPCALL iocore_inp32(UINT port) { + + UINT32 ret; + + CPU_REMCLOCK -= iocore.busclock; +#if defined(SUPPORT_PC9821) + if ((port & 0xfffb) == 0x0cf8) { + return(pcidev_r32(port)); + } +#endif +#if defined(SUPPORT_CL_GD5430) + if(np2clvga.enabled && cirrusvga_opaque){ + if((np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + if(pc98_cirrus_isWABport(port)){ + return(cirrusvga_ioport_read_wrap32(port)); + } + } + } +#endif +//#if defined(SUPPORT_IDEIO) +// if (port == 0x0640) { +// ret = ideio_r16(port); +// ret |= ideio_r16(port) << 16; +// return ret; +// } +//#endif + ret = iocore_inp16(port); + return(ret + (iocore_inp16(port+2) << 16)); +} + diff --git a/io/iocore.h b/io/iocore.h old mode 100755 new mode 100644 index 38d1d560..ab434ace --- a/io/iocore.h +++ b/io/iocore.h @@ -1,134 +1,134 @@ -#ifndef NP2_IOCORE_H -#define NP2_IOCORE_H - -typedef void (*FNIORESET)(const NP2CFG *pConfig); -typedef void (*FNIOBIND)(void); -typedef void (IOOUTCALL *IOOUT)(UINT port, UINT val); -typedef UINT (IOINPCALL *IOINP)(UINT port); - -#include "lsidef.h" - -#include "artic.h" -#include "cgrom.h" -#include "cpuio.h" -#include "crtc.h" -#include "dipsw.h" -#include -#include "egc.h" -#include "epsonio.h" -#include "emsio.h" -#include "fdc.h" -#include "fdd320.h" -#include "gdc.h" -#include "gdc_cmd.h" -#include "mouseif.h" -#include "necio.h" -#include "nmiio.h" -#include "np2sysp.h" -#include "pic.h" -#include "pit.h" -#include "printif.h" -#include -#include "sysport.h" -#include - -#if defined(SUPPORT_PC9821) -#include "pcidev.h" -#endif -#if defined(SUPPORT_PEGC) -#include "pegc.h" -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -extern _ARTIC artic; -extern _CGROM cgrom; -extern _CGWINDOW cgwindow; -extern _CRTC crtc; -extern _DMAC dmac; -extern _EGC egc; -extern _EPSONIO epsonio; -extern _EMSIO emsio; -extern _FDC fdc; -extern _GDC gdc; -extern _GDCS gdcs; -extern _GRCG grcg; -extern _KEYBRD keybrd; -extern _MOUSEIF mouseif; -extern _NECIO necio; -extern _NMIIO nmiio; -extern _NP2SYSP np2sysp; -extern _PIC pic; -extern _PIT pit; -extern _RS232C rs232c; -#if defined(SUPPORT_RS232C_FIFO) -extern _RS232CFIFO rs232cfifo; -#endif -extern _SYSPORT sysport; -extern _UPD4990 uPD4990; -#ifdef SUPPORT_HRTIMER -extern _UPD4990HRT uPD4990HRT; -#endif - -#if defined(SUPPORT_PC9821) -extern _PCIDEV pcidev; -#endif -#if defined(SUPPORT_PEGC) -extern _PEGC pegc; -#endif - - -// I/O - 8bit decode -void iocore_attachcmnout(UINT port, IOOUT func); -void iocore_attachcmninp(UINT port, IOINP func); -void iocore_attachcmnoutex(UINT port, UINT mask, - const IOOUT *func, UINT funcs); -void iocore_attachcmninpex(UINT port, UINT mask, - const IOINP *func, UINT funcs); - -// システムI/O - 10bit decode -void iocore_attachsysout(UINT port, IOOUT func); -void iocore_attachsysinp(UINT port, IOINP func); -void iocore_attachsysoutex(UINT port, UINT mask, - const IOOUT *func, UINT funcs); -void iocore_attachsysinpex(UINT port, UINT mask, - const IOINP *func, UINT funcs); - -// サウンドI/O - 12bit decode -BRESULT iocore_attachsndout(UINT port, IOOUT func); -BRESULT iocore_detachsndout(UINT port); -BRESULT iocore_attachsndinp(UINT port, IOINP func); -BRESULT iocore_detachsndinp(UINT port); - -// 拡張I/O - 16bit decode -BRESULT iocore_attachout(UINT port, IOOUT func); -BRESULT iocore_detachout(UINT port); -BRESULT iocore_attachinp(UINT port, IOINP func); -BRESULT iocore_detachinp(UINT port); - -void iocore_create(void); -void iocore_destroy(void); -BRESULT iocore_build(void); - -void iocore_cbreset(const FNIORESET *pfn, UINT uCount, const NP2CFG *pConfig); -void iocore_cbbind(const FNIOBIND *pfn, UINT uCount); -void iocore_reset(const NP2CFG *pConfig); -void iocore_bind(void); - -void IOOUTCALL iocore_out8(UINT port, REG8 dat); -REG8 IOINPCALL iocore_inp8(UINT port); - -void IOOUTCALL iocore_out16(UINT port, REG16 dat); -REG16 IOINPCALL iocore_inp16(UINT port); - -void IOOUTCALL iocore_out32(UINT port, UINT32 dat); -UINT32 IOINPCALL iocore_inp32(UINT port); - -#ifdef __cplusplus -} -#endif - -#endif /* NP2_IOCORE_H */ +#ifndef NP2_IOCORE_H +#define NP2_IOCORE_H + +typedef void (*FNIORESET)(const NP2CFG *pConfig); +typedef void (*FNIOBIND)(void); +typedef void (IOOUTCALL *IOOUT)(UINT port, UINT val); +typedef UINT (IOINPCALL *IOINP)(UINT port); + +#include "lsidef.h" + +#include "artic.h" +#include "cgrom.h" +#include "cpuio.h" +#include "crtc.h" +#include "dipsw.h" +#include +#include "egc.h" +#include "epsonio.h" +#include "emsio.h" +#include "fdc.h" +#include "fdd320.h" +#include "gdc.h" +#include "gdc_cmd.h" +#include "mouseif.h" +#include "necio.h" +#include "nmiio.h" +#include "np2sysp.h" +#include "pic.h" +#include "pit.h" +#include "printif.h" +#include +#include "sysport.h" +#include + +#if defined(SUPPORT_PC9821) +#include "pcidev.h" +#endif +#if defined(SUPPORT_PEGC) +#include "pegc.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _ARTIC artic; +extern _CGROM cgrom; +extern _CGWINDOW cgwindow; +extern _CRTC crtc; +extern _DMAC dmac; +extern _EGC egc; +extern _EPSONIO epsonio; +extern _EMSIO emsio; +extern _FDC fdc; +extern _GDC gdc; +extern _GDCS gdcs; +extern _GRCG grcg; +extern _KEYBRD keybrd; +extern _MOUSEIF mouseif; +extern _NECIO necio; +extern _NMIIO nmiio; +extern _NP2SYSP np2sysp; +extern _PIC pic; +extern _PIT pit; +extern _RS232C rs232c; +#if defined(SUPPORT_RS232C_FIFO) +extern _RS232CFIFO rs232cfifo; +#endif +extern _SYSPORT sysport; +extern _UPD4990 uPD4990; +#ifdef SUPPORT_HRTIMER +extern _UPD4990HRT uPD4990HRT; +#endif + +#if defined(SUPPORT_PC9821) +extern _PCIDEV pcidev; +#endif +#if defined(SUPPORT_PEGC) +extern _PEGC pegc; +#endif + + +// I/O - 8bit decode +void iocore_attachcmnout(UINT port, IOOUT func); +void iocore_attachcmninp(UINT port, IOINP func); +void iocore_attachcmnoutex(UINT port, UINT mask, + const IOOUT *func, UINT funcs); +void iocore_attachcmninpex(UINT port, UINT mask, + const IOINP *func, UINT funcs); + +// システムI/O - 10bit decode +void iocore_attachsysout(UINT port, IOOUT func); +void iocore_attachsysinp(UINT port, IOINP func); +void iocore_attachsysoutex(UINT port, UINT mask, + const IOOUT *func, UINT funcs); +void iocore_attachsysinpex(UINT port, UINT mask, + const IOINP *func, UINT funcs); + +// サウンドI/O - 12bit decode +BRESULT iocore_attachsndout(UINT port, IOOUT func); +BRESULT iocore_detachsndout(UINT port); +BRESULT iocore_attachsndinp(UINT port, IOINP func); +BRESULT iocore_detachsndinp(UINT port); + +// 拡張I/O - 16bit decode +BRESULT iocore_attachout(UINT port, IOOUT func); +BRESULT iocore_detachout(UINT port); +BRESULT iocore_attachinp(UINT port, IOINP func); +BRESULT iocore_detachinp(UINT port); + +void iocore_create(void); +void iocore_destroy(void); +BRESULT iocore_build(void); + +void iocore_cbreset(const FNIORESET *pfn, UINT uCount, const NP2CFG *pConfig); +void iocore_cbbind(const FNIOBIND *pfn, UINT uCount); +void iocore_reset(const NP2CFG *pConfig); +void iocore_bind(void); + +void IOOUTCALL iocore_out8(UINT port, REG8 dat); +REG8 IOINPCALL iocore_inp8(UINT port); + +void IOOUTCALL iocore_out16(UINT port, REG16 dat); +REG16 IOINPCALL iocore_inp16(UINT port); + +void IOOUTCALL iocore_out32(UINT port, UINT32 dat); +UINT32 IOINPCALL iocore_inp32(UINT port); + +#ifdef __cplusplus +} +#endif + +#endif /* NP2_IOCORE_H */ diff --git a/io/lsidef.h b/io/lsidef.h old mode 100755 new mode 100644 index c061359d..144fd8bf --- a/io/lsidef.h +++ b/io/lsidef.h @@ -1,18 +1,18 @@ - -typedef struct { - UINT8 porta; - UINT8 portb; - UINT8 portc; - UINT8 mode; -} uPD8255; - -enum { - uPD8255_PORTCL = 0x01, - uPD8255_PORTB = 0x02, - uPD8255_GROUPB = 0x04, - uPD8255_PORTCH = 0x08, - uPD8255_PORTA = 0x10, - uPD8255_GROUPA = 0x60, - uPD8255_CTRL = 0x80 -}; - + +typedef struct { + UINT8 porta; + UINT8 portb; + UINT8 portc; + UINT8 mode; +} uPD8255; + +enum { + uPD8255_PORTCL = 0x01, + uPD8255_PORTB = 0x02, + uPD8255_GROUPB = 0x04, + uPD8255_PORTCH = 0x08, + uPD8255_PORTA = 0x10, + uPD8255_GROUPA = 0x60, + uPD8255_CTRL = 0x80 +}; + diff --git a/io/mouseif.c b/io/mouseif.c old mode 100755 new mode 100644 index 2362d9a7..6ac74a1e --- a/io/mouseif.c +++ b/io/mouseif.c @@ -1,337 +1,337 @@ -#include -#include -#include -#include -#include -#include - - -// マウス ver0.28 -// 一部のゲームでマウスデータを切り捨てるので正常な動かなくなる事がある -// それを救う為に 均等に移動データが伝わるようにしなければならない - -static int mouseif_limitcounter = 0; -static int mouseif_test = 0; - -void mouseif_sync(void) { - - // 前回の分を補正 - mouseif.x += mouseif.rx; - mouseif.y += mouseif.ry; - - // 今回の移動量を取得 - mouseif.b = mousemng_getstat(&mouseif.sx, &mouseif.sy, 1); - if (np2cfg.KEY_MODE == 3) { - mouseif.b &= keystat_getmouse(&mouseif.sx, &mouseif.sy); - } - mouseif.rx = mouseif.sx; - mouseif.ry = mouseif.sy; - -#if defined(VAEG_FIX) - mouseif.lastc = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; -#else - mouseif.lastc = CPU_CLOCK + CPU_BASECLOCK + CPU_REMCLOCK; -#endif - - // XXX: 何故かマウスイベントが消えることがあるので復活させる・・・ np21w ver.0.86 rev.79 - if (!(mouseif.upd8255.portc & 0x10)) { - if (!nevent_iswork(NEVENT_MOUSE)) { - nevent_set(NEVENT_MOUSE, mouseif.intrclock << mouseif.timing, - mouseint, NEVENT_ABSOLUTE); - } - } -} - -static void calc_mousexy(void) { - -#if defined(VAEG_EXT) - static UINT32 rapidlastc; -#endif - - UINT32 clk; - SINT32 diff; - -#if defined(VAEG_FIX) - clk = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; -#else - clk = CPU_CLOCK + CPU_BASECLOCK + CPU_REMCLOCK; -#endif - diff = clk - mouseif.lastc; - if (diff >= 2000) { - SINT32 dx; - SINT32 dy; -#if !defined(VAEG_EXT) - mouseif.rapid ^= 0xa0; -#endif - diff /= 1000; - dx = mouseif.sx; - if (dx > 0) { - dx = dx * diff / mouseif.moveclock; - if (dx > mouseif.rx) { - dx = mouseif.rx; - } - } - else if (dx < 0) { - dx *= -1; - dx = dx * diff / mouseif.moveclock; - dx *= -1; - if (dx < mouseif.rx) { - dx = mouseif.rx; - } - } - mouseif.x += dx; - mouseif.rx -= dx; - - dy = mouseif.sy; - if (dy > 0) { - dy = dy * diff / mouseif.moveclock; - if (dy > mouseif.ry) { - dy = mouseif.ry; - } - } - else if (dy < 0) { - dy *= -1; - dy = dy * diff / mouseif.moveclock; - dy *= -1; - if (dy < mouseif.ry) { - dy = mouseif.ry; - } - } - mouseif.y += dy; - mouseif.ry -= dy; - mouseif.lastc += diff * 1000; - } - -#if defined(VAEG_EXT) - diff = clock - rapidlastc; - if (diff > 200000 || diff < 0) { - mouseif.rapid ^= 0xa0; - rapidlastc = clock; - } -#endif -} - -void mouseint(NEVENTITEM item) { - - if (item->flag & NEVENT_SETEVENT) { - if (!(mouseif.upd8255.portc & 0x10)) { - pic_setirq(0x0d); - nevent_set(NEVENT_MOUSE, mouseif.intrclock << mouseif.timing, - mouseint, NEVENT_RELATIVE); - } - } -} - -static void setportc(REG8 value) { - - if ((value & 0x80) && (!(mouseif.upd8255.portc & 0x80))) { - calc_mousexy(); - mouseif.latch_x = mouseif.x; - mouseif.x = 0; - mouseif.latch_y = mouseif.y; - mouseif.y = 0; - mouseif_limitcounter = 4; // XXX: カウンタがオーバーフローしてマウスカーソルが暴走するのを回避。ただし、オーバーフロー前提の物があるのでオーバーフローしっぱなしならそのままの値を渡す。 - if (mouseif.latch_x > 127) { - mouseif.latch_x = 127; - } - else if (mouseif.latch_x < -128) { - mouseif.latch_x = -128; - } - if (mouseif.latch_y > 127) { - mouseif.latch_y = 127; - } - else if (mouseif.latch_y < -128) { - mouseif.latch_y = -128; - } - } - if ((value ^ mouseif.upd8255.portc) & 0x10) { - if (!(value & 0x10)) { - if (!nevent_iswork(NEVENT_MOUSE)) { - // 割り込みを入れとく → 割り込みはやめとく ver0.86 rev51 - //pic_setirq(0x0d); - nevent_set(NEVENT_MOUSE, mouseif.intrclock << mouseif.timing, - mouseint, NEVENT_ABSOLUTE); - } - } - } - mouseif.upd8255.portc = (UINT8)value; -} - - -// ---- I/O - -static void IOOUTCALL mouseif_o7fd9(UINT port, REG8 dat) { - - mouseif.upd8255.porta = dat; - (void)port; -} - -static void IOOUTCALL mouseif_o7fdb(UINT port, REG8 dat) { - - mouseif.upd8255.portb = dat; - (void)port; -} - -static void IOOUTCALL mouseif_o7fdd(UINT port, REG8 dat) { - - setportc(dat); - (void)port; -} - -static void IOOUTCALL mouseif_o7fdf(UINT port, REG8 dat) { - - REG8 portc; - UINT sft; - - portc = 0; - if (dat & uPD8255_CTRL) { - mouseif.upd8255.mode = (UINT8)dat; -#if 0 - pic_resetirq(0x0d); - nevent_set(NEVENT_MOUSE, mouseif.intrclock << mouseif.timing, - mouseint, NEVENT_ABSOLUTE); -#endif - } - else { - sft = (dat >> 1) & 7; - portc = mouseif.upd8255.portc; - portc &= (~(1 << sft)); - portc |= (dat & 1) << sft; - } - setportc(portc); - (void)port; -} - -static REG8 IOINPCALL mouseif_i7fd9(UINT port) { - - SINT16 x; - SINT16 y; - REG8 ret; - REG8 portc; - - if (mouseif.upd8255.mode & uPD8255_PORTA) { - calc_mousexy(); - ret = mouseif.b; - if (np2cfg.MOUSERAPID) { - ret |= mouseif.rapid; - } - ret &= 0xf0; -#if 1 - ret |= 0x40; // for shizuku -#else - ret |= 0x50; -#endif - portc = mouseif.upd8255.portc; - if (portc & 0x80) { - x = mouseif.latch_x; - y = mouseif.latch_y; - } - else { - x = mouseif.x; - y = mouseif.y; - } - if (portc & 0x40) { - x = y; - } - if (mouseif_limitcounter > 0) { - if (np2cfg.slowmous) { - if (x < -16) - x = -16; - if (x > +15) - x = +15; - } - else { - if (x < -128) - x = -128; - if (x > +127) - x = +127; - } - mouseif_limitcounter--; - } - if (!(portc & 0x20)) { - ret |= x & 0x0f; - } - else { - ret |= (x >> 4) & 0x0f; - } - return(ret); - } - else { - return(mouseif.upd8255.porta); - } - (void)port; -} - -static REG8 IOINPCALL mouseif_i7fdb(UINT port) { - - if (mouseif.upd8255.mode & uPD8255_PORTB) { - return(0x40); - } - else { - return(mouseif.upd8255.portb); - } - (void)port; -} - -static REG8 IOINPCALL mouseif_i7fdd(UINT port) { - - REG8 mode; - REG8 ret; - - mode = mouseif.upd8255.mode; - ret = mouseif.upd8255.portc; - if (mode & uPD8255_PORTCH) { - ret &= 0x1f; - } - if (mode & uPD8255_PORTCL) { - ret &= 0xf0; - ret |= 0x08; - ret |= (pccore.dipsw[2] >> 5) & 0x04; - ret |= ((~pccore.dipsw[0]) >> 4) & 0x03; - } - (void)port; - return(ret); -} - -static void IOOUTCALL mouseif_obfdb(UINT port, REG8 dat) { - - mouseif.timing = dat & 3; - (void)port; -} - - -// ---- I/F - -void mouseif_reset(const NP2CFG *pConfig) { - - ZeroMemory(&mouseif, sizeof(mouseif)); - mouseif.upd8255.porta = 0x00; - mouseif.upd8255.portb = 0x00; - mouseif.upd8255.portc = 0xf0; // ver0.82 - mouseif.upd8255.mode = 0x93; - mouseif_changeclock(); - mouseif.latch_x = -1; - mouseif.latch_y = -1; - - //mouseif.timing = 2; - (void)pConfig; -} - -void mouseif_bind(void) { - - iocore_attachout(0x7fd9, mouseif_o7fd9); - iocore_attachout(0x7fdb, mouseif_o7fdb); - iocore_attachout(0x7fdd, mouseif_o7fdd); - iocore_attachout(0x7fdf, mouseif_o7fdf); - iocore_attachinp(0x7fd9, mouseif_i7fd9); - iocore_attachinp(0x7fdb, mouseif_i7fdb); - iocore_attachinp(0x7fdd, mouseif_i7fdd); - iocore_attachout(0xbfdb, mouseif_obfdb); -} - -void mouseif_changeclock(void) { - - mouseif.intrclock = pccore.realclock / 120; - mouseif.moveclock = pccore.realclock / 56400; -} - +#include +#include +#include +#include +#include +#include + + +// マウス ver0.28 +// 一部のゲームでマウスデータを切り捨てるので正常な動かなくなる事がある +// それを救う為に 均等に移動データが伝わるようにしなければならない + +static int mouseif_limitcounter = 0; +static int mouseif_test = 0; + +void mouseif_sync(void) { + + // 前回の分を補正 + mouseif.x += mouseif.rx; + mouseif.y += mouseif.ry; + + // 今回の移動量を取得 + mouseif.b = mousemng_getstat(&mouseif.sx, &mouseif.sy, 1); + if (np2cfg.KEY_MODE == 3) { + mouseif.b &= keystat_getmouse(&mouseif.sx, &mouseif.sy); + } + mouseif.rx = mouseif.sx; + mouseif.ry = mouseif.sy; + +#if defined(VAEG_FIX) + mouseif.lastc = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; +#else + mouseif.lastc = CPU_CLOCK + CPU_BASECLOCK + CPU_REMCLOCK; +#endif + + // XXX: 何故かマウスイベントが消えることがあるので復活させる・・・ np21w ver.0.86 rev.79 + if (!(mouseif.upd8255.portc & 0x10)) { + if (!nevent_iswork(NEVENT_MOUSE)) { + nevent_set(NEVENT_MOUSE, mouseif.intrclock << mouseif.timing, + mouseint, NEVENT_ABSOLUTE); + } + } +} + +static void calc_mousexy(void) { + +#if defined(VAEG_EXT) + static UINT32 rapidlastc; +#endif + + UINT32 clk; + SINT32 diff; + +#if defined(VAEG_FIX) + clk = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; +#else + clk = CPU_CLOCK + CPU_BASECLOCK + CPU_REMCLOCK; +#endif + diff = clk - mouseif.lastc; + if (diff >= 2000) { + SINT32 dx; + SINT32 dy; +#if !defined(VAEG_EXT) + mouseif.rapid ^= 0xa0; +#endif + diff /= 1000; + dx = mouseif.sx; + if (dx > 0) { + dx = dx * diff / mouseif.moveclock; + if (dx > mouseif.rx) { + dx = mouseif.rx; + } + } + else if (dx < 0) { + dx *= -1; + dx = dx * diff / mouseif.moveclock; + dx *= -1; + if (dx < mouseif.rx) { + dx = mouseif.rx; + } + } + mouseif.x += dx; + mouseif.rx -= dx; + + dy = mouseif.sy; + if (dy > 0) { + dy = dy * diff / mouseif.moveclock; + if (dy > mouseif.ry) { + dy = mouseif.ry; + } + } + else if (dy < 0) { + dy *= -1; + dy = dy * diff / mouseif.moveclock; + dy *= -1; + if (dy < mouseif.ry) { + dy = mouseif.ry; + } + } + mouseif.y += dy; + mouseif.ry -= dy; + mouseif.lastc += diff * 1000; + } + +#if defined(VAEG_EXT) + diff = clock - rapidlastc; + if (diff > 200000 || diff < 0) { + mouseif.rapid ^= 0xa0; + rapidlastc = clock; + } +#endif +} + +void mouseint(NEVENTITEM item) { + + if (item->flag & NEVENT_SETEVENT) { + if (!(mouseif.upd8255.portc & 0x10)) { + pic_setirq(0x0d); + nevent_set(NEVENT_MOUSE, mouseif.intrclock << mouseif.timing, + mouseint, NEVENT_RELATIVE); + } + } +} + +static void setportc(REG8 value) { + + if ((value & 0x80) && (!(mouseif.upd8255.portc & 0x80))) { + calc_mousexy(); + mouseif.latch_x = mouseif.x; + mouseif.x = 0; + mouseif.latch_y = mouseif.y; + mouseif.y = 0; + mouseif_limitcounter = 4; // XXX: カウンタがオーバーフローしてマウスカーソルが暴走するのを回避。ただし、オーバーフロー前提の物があるのでオーバーフローしっぱなしならそのままの値を渡す。 + if (mouseif.latch_x > 127) { + mouseif.latch_x = 127; + } + else if (mouseif.latch_x < -128) { + mouseif.latch_x = -128; + } + if (mouseif.latch_y > 127) { + mouseif.latch_y = 127; + } + else if (mouseif.latch_y < -128) { + mouseif.latch_y = -128; + } + } + if ((value ^ mouseif.upd8255.portc) & 0x10) { + if (!(value & 0x10)) { + if (!nevent_iswork(NEVENT_MOUSE)) { + // 割り込みを入れとく → 割り込みはやめとく ver0.86 rev51 + //pic_setirq(0x0d); + nevent_set(NEVENT_MOUSE, mouseif.intrclock << mouseif.timing, + mouseint, NEVENT_ABSOLUTE); + } + } + } + mouseif.upd8255.portc = (UINT8)value; +} + + +// ---- I/O + +static void IOOUTCALL mouseif_o7fd9(UINT port, REG8 dat) { + + mouseif.upd8255.porta = dat; + (void)port; +} + +static void IOOUTCALL mouseif_o7fdb(UINT port, REG8 dat) { + + mouseif.upd8255.portb = dat; + (void)port; +} + +static void IOOUTCALL mouseif_o7fdd(UINT port, REG8 dat) { + + setportc(dat); + (void)port; +} + +static void IOOUTCALL mouseif_o7fdf(UINT port, REG8 dat) { + + REG8 portc; + UINT sft; + + portc = 0; + if (dat & uPD8255_CTRL) { + mouseif.upd8255.mode = (UINT8)dat; +#if 0 + pic_resetirq(0x0d); + nevent_set(NEVENT_MOUSE, mouseif.intrclock << mouseif.timing, + mouseint, NEVENT_ABSOLUTE); +#endif + } + else { + sft = (dat >> 1) & 7; + portc = mouseif.upd8255.portc; + portc &= (~(1 << sft)); + portc |= (dat & 1) << sft; + } + setportc(portc); + (void)port; +} + +static REG8 IOINPCALL mouseif_i7fd9(UINT port) { + + SINT16 x; + SINT16 y; + REG8 ret; + REG8 portc; + + if (mouseif.upd8255.mode & uPD8255_PORTA) { + calc_mousexy(); + ret = mouseif.b; + if (np2cfg.MOUSERAPID) { + ret |= mouseif.rapid; + } + ret &= 0xf0; +#if 1 + ret |= 0x40; // for shizuku +#else + ret |= 0x50; +#endif + portc = mouseif.upd8255.portc; + if (portc & 0x80) { + x = mouseif.latch_x; + y = mouseif.latch_y; + } + else { + x = mouseif.x; + y = mouseif.y; + } + if (portc & 0x40) { + x = y; + } + if (mouseif_limitcounter > 0) { + if (np2cfg.slowmous) { + if (x < -16) + x = -16; + if (x > +15) + x = +15; + } + else { + if (x < -128) + x = -128; + if (x > +127) + x = +127; + } + mouseif_limitcounter--; + } + if (!(portc & 0x20)) { + ret |= x & 0x0f; + } + else { + ret |= (x >> 4) & 0x0f; + } + return(ret); + } + else { + return(mouseif.upd8255.porta); + } + (void)port; +} + +static REG8 IOINPCALL mouseif_i7fdb(UINT port) { + + if (mouseif.upd8255.mode & uPD8255_PORTB) { + return(0x40); + } + else { + return(mouseif.upd8255.portb); + } + (void)port; +} + +static REG8 IOINPCALL mouseif_i7fdd(UINT port) { + + REG8 mode; + REG8 ret; + + mode = mouseif.upd8255.mode; + ret = mouseif.upd8255.portc; + if (mode & uPD8255_PORTCH) { + ret &= 0x1f; + } + if (mode & uPD8255_PORTCL) { + ret &= 0xf0; + ret |= 0x08; + ret |= (pccore.dipsw[2] >> 5) & 0x04; + ret |= ((~pccore.dipsw[0]) >> 4) & 0x03; + } + (void)port; + return(ret); +} + +static void IOOUTCALL mouseif_obfdb(UINT port, REG8 dat) { + + mouseif.timing = dat & 3; + (void)port; +} + + +// ---- I/F + +void mouseif_reset(const NP2CFG *pConfig) { + + ZeroMemory(&mouseif, sizeof(mouseif)); + mouseif.upd8255.porta = 0x00; + mouseif.upd8255.portb = 0x00; + mouseif.upd8255.portc = 0xf0; // ver0.82 + mouseif.upd8255.mode = 0x93; + mouseif_changeclock(); + mouseif.latch_x = -1; + mouseif.latch_y = -1; + + //mouseif.timing = 2; + (void)pConfig; +} + +void mouseif_bind(void) { + + iocore_attachout(0x7fd9, mouseif_o7fd9); + iocore_attachout(0x7fdb, mouseif_o7fdb); + iocore_attachout(0x7fdd, mouseif_o7fdd); + iocore_attachout(0x7fdf, mouseif_o7fdf); + iocore_attachinp(0x7fd9, mouseif_i7fd9); + iocore_attachinp(0x7fdb, mouseif_i7fdb); + iocore_attachinp(0x7fdd, mouseif_i7fdd); + iocore_attachout(0xbfdb, mouseif_obfdb); +} + +void mouseif_changeclock(void) { + + mouseif.intrclock = pccore.realclock / 120; + mouseif.moveclock = pccore.realclock / 56400; +} + diff --git a/io/mouseif.h b/io/mouseif.h old mode 100755 new mode 100644 index 6f77c4c9..f94e8564 --- a/io/mouseif.h +++ b/io/mouseif.h @@ -1,34 +1,34 @@ - -typedef struct { - uPD8255 upd8255; - UINT32 lastc; - UINT32 intrclock; - UINT32 moveclock; - SINT16 x; - SINT16 y; - SINT16 rx; - SINT16 ry; - SINT16 sx; - SINT16 sy; - SINT16 latch_x; - SINT16 latch_y; - UINT8 timing; - UINT8 rapid; - UINT8 b; -} _MOUSEIF, *MOUSEIF; - - -#ifdef __cplusplus -extern "C" { -#endif - -void mouseif_reset(const NP2CFG *pConfig); -void mouseif_bind(void); -void mouseif_sync(void); -void mouseint(NEVENTITEM item); -void mouseif_changeclock(void); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + uPD8255 upd8255; + UINT32 lastc; + UINT32 intrclock; + UINT32 moveclock; + SINT16 x; + SINT16 y; + SINT16 rx; + SINT16 ry; + SINT16 sx; + SINT16 sy; + SINT16 latch_x; + SINT16 latch_y; + UINT8 timing; + UINT8 rapid; + UINT8 b; +} _MOUSEIF, *MOUSEIF; + + +#ifdef __cplusplus +extern "C" { +#endif + +void mouseif_reset(const NP2CFG *pConfig); +void mouseif_bind(void); +void mouseif_sync(void); +void mouseint(NEVENTITEM item); +void mouseif_changeclock(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/necio.c b/io/necio.c old mode 100755 new mode 100644 index 486bab0f..491f4d52 --- a/io/necio.c +++ b/io/necio.c @@ -1,59 +1,59 @@ -#include -#include -#include -#include - - -// ---- I/O - -static void IOOUTCALL necio_o0439(UINT port, REG8 dat) { - - necio.port0439 = dat; - (void)port; -} - -static void IOOUTCALL necio_o043b(UINT port, REG8 dat) { - - necio.port043b = dat & 0x04; - (void)port; -} -static REG8 IOOUTCALL necio_i043b(UINT port) { - - return(necio.port043b); -} - -static void IOOUTCALL necio_o043d(UINT port, REG8 dat) { - - switch(dat) { - case 0x10: - CPU_ITFBANK = 1; - break; - - case 0x12: - CPU_ITFBANK = 0; - break; - } - (void)port; -} - - -// ---- I/F - -void necio_reset(const NP2CFG *pConfig) { - - necio.port0439 = 0xff; - - (void)pConfig; -} - -void necio_bind(void) { - - iocore_attachout(0x0439, necio_o0439); - - if (!(pccore.model & PCMODEL_EPSON)) { - iocore_attachout(0x043b, necio_o043b); - iocore_attachinp(0x043b, necio_i043b); - iocore_attachout(0x043d, necio_o043d); - } -} - +#include +#include +#include +#include + + +// ---- I/O + +static void IOOUTCALL necio_o0439(UINT port, REG8 dat) { + + necio.port0439 = dat; + (void)port; +} + +static void IOOUTCALL necio_o043b(UINT port, REG8 dat) { + + necio.port043b = dat & 0x04; + (void)port; +} +static REG8 IOOUTCALL necio_i043b(UINT port) { + + return(necio.port043b); +} + +static void IOOUTCALL necio_o043d(UINT port, REG8 dat) { + + switch(dat) { + case 0x10: + CPU_ITFBANK = 1; + break; + + case 0x12: + CPU_ITFBANK = 0; + break; + } + (void)port; +} + + +// ---- I/F + +void necio_reset(const NP2CFG *pConfig) { + + necio.port0439 = 0xff; + + (void)pConfig; +} + +void necio_bind(void) { + + iocore_attachout(0x0439, necio_o0439); + + if (!(pccore.model & PCMODEL_EPSON)) { + iocore_attachout(0x043b, necio_o043b); + iocore_attachinp(0x043b, necio_i043b); + iocore_attachout(0x043d, necio_o043d); + } +} + diff --git a/io/necio.h b/io/necio.h old mode 100755 new mode 100644 index f5e230cd..e989d4ca --- a/io/necio.h +++ b/io/necio.h @@ -1,17 +1,17 @@ - -typedef struct { - UINT8 port0439; - UINT8 port043b; -} _NECIO, *NECIO; - -#ifdef __cplusplus -extern "C" { -#endif - -void necio_reset(const NP2CFG *pConfig); -void necio_bind(void); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + UINT8 port0439; + UINT8 port043b; +} _NECIO, *NECIO; + +#ifdef __cplusplus +extern "C" { +#endif + +void necio_reset(const NP2CFG *pConfig); +void necio_bind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/nmiio.c b/io/nmiio.c old mode 100755 new mode 100644 index 8f9f8c3c..a72d34d0 --- a/io/nmiio.c +++ b/io/nmiio.c @@ -1,40 +1,40 @@ -#include -#include -#include - - -// ---- I/O - -static void IOOUTCALL nmiio_o50(UINT port, REG8 dat) { - - nmiio.enable = 0; - (void)port; - (void)dat; -} - -static void IOOUTCALL nmiio_o52(UINT port, REG8 dat) { - - nmiio.enable = 1; - (void)port; - (void)dat; -} - - -// ---- I/F - -static const IOOUT nmiioo50[2] = { - nmiio_o50, nmiio_o52}; - -void nmiio_reset(const NP2CFG *pConfig) { - - ZeroMemory(&nmiio, sizeof(nmiio)); - - (void)pConfig; -} - -void nmiio_bind(void) { - - iocore_attachsysoutex(0x0050, 0x0cf1, nmiioo50, 2); -// iocore_attachinp(0x98f0, nmiio_i98f0); -} - +#include +#include +#include + + +// ---- I/O + +static void IOOUTCALL nmiio_o50(UINT port, REG8 dat) { + + nmiio.enable = 0; + (void)port; + (void)dat; +} + +static void IOOUTCALL nmiio_o52(UINT port, REG8 dat) { + + nmiio.enable = 1; + (void)port; + (void)dat; +} + + +// ---- I/F + +static const IOOUT nmiioo50[2] = { + nmiio_o50, nmiio_o52}; + +void nmiio_reset(const NP2CFG *pConfig) { + + ZeroMemory(&nmiio, sizeof(nmiio)); + + (void)pConfig; +} + +void nmiio_bind(void) { + + iocore_attachsysoutex(0x0050, 0x0cf1, nmiioo50, 2); +// iocore_attachinp(0x98f0, nmiio_i98f0); +} + diff --git a/io/nmiio.h b/io/nmiio.h old mode 100755 new mode 100644 index fbfad04c..95bd4315 --- a/io/nmiio.h +++ b/io/nmiio.h @@ -1,17 +1,17 @@ - -typedef struct { - int enable; -} _NMIIO, *NMIIO; - - -#ifdef __cplusplus -extern "C" { -#endif - -void nmiio_reset(const NP2CFG *pConfig); -void nmiio_bind(void); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + int enable; +} _NMIIO, *NMIIO; + + +#ifdef __cplusplus +extern "C" { +#endif + +void nmiio_reset(const NP2CFG *pConfig); +void nmiio_bind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/np2sysp.c b/io/np2sysp.c index 8a5bb256..2b9507e5 100644 --- a/io/np2sysp.c +++ b/io/np2sysp.c @@ -1,927 +1,927 @@ -#include -#include -#if defined(OSLANG_UCS2) -#include "oemtext.h" -#endif -#include "taskmng.h" -#include -#include -#include -#include -#if defined(SUPPORT_HOSTDRV) -#include -#endif -#include -#include -#include -#include -#include -#if defined(SUPPORT_SMPU98) -#include -#endif -#if defined(SUPPORT_IDEIO) -#include -#endif -#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) -#include -#include -#endif -#include "np2.h" -#if defined(SUPPORT_HRTIMER) -#include -#endif -#if defined(SUPPORT_LGY98) -#include -#include -#endif -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif -#include "dosio.h" -#include "mousemng.h" - -//#include - -// 性能上最適化で優先しない方がいいコードなのでわざと別セグメントに置く -#pragma code_seg(".MISCCODE") - -#if 0 -#undef TRACEOUT -static void trace_fmt_ex(const char* fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -static void trace_fmt_exw(const WCHAR* fmt, ...) -{ - WCHAR stmp[2048]; - va_list ap; - va_start(ap, fmt); - vswprintf(stmp, 2048, fmt, ap); - wcscat(stmp, L"¥n"); - va_end(ap); - OutputDebugStringW(stmp); -} -#define TRACEOUTW(s) trace_fmt_exw s -#else -#define TRACEOUTW(s) (void)0 -#endif /* 1 */ - - -#define NP2SYSP_VER "C" -// #define NP2SYSP_CREDIT "" // 要るなら・・・ - -// NP2依存ポート -// port:07edh np2 value comm -// port:07efh np2 string comm - -// 基本的に STRINGでやり取りする -// ポート 7efh に 'NP2' と出力で "NP2"が返ってきたら NP2である - -// verA -// out->str: 'ver' in->str: ver番号 A〜 -// out->str: 'poweroff' NP2を終了 - -// verB -// out->str: 'cpu' in->str: CPU型番 -// out->str: 'clock' in->str: 動作クロック数 - - -// ---- - -typedef struct { -const char *key; - void (*func)(const void *arg1, long arg2); -const void *arg1; - long arg2; -} SYSPCMD; - -static const OEMCHAR str_80286[] = OEMTEXT("80286"); -static const OEMCHAR str_v30[] = OEMTEXT("V30"); -#if defined(CPUCORE_IA32) -static const OEMCHAR str_pentium[] = OEMTEXT("PENTIUM"); -#endif /* 0 */ -static const OEMCHAR str_mhz[] = OEMTEXT("%uMHz"); - -// np21/w dynamic config -#define NP21W_SWITCH_DUMMY 0 -#define NP21W_SWITCH_GD54XXTYPE 1 -#define NP21W_SWITCH_SOUNDBOARD 2 -#define NP21W_SWITCH_SYNCCLOCK 3 -#define NP21W_SWITCH_PCIENABLE 4 -#define NP21W_SWITCH_ASYNCCPU 5 -#define NP21W_SWITCH_DISABLESOUNDROM 6 -#define NP21W_SWITCH_SETIDEWAIT_R 7 -#define NP21W_SWITCH_SETIDEWAIT_W 8 -#define NP21W_SWITCH_AUTOHIDECURSOR 9 -#define NP21W_SWITCH_SETDEVICEIRQ 10 - -#define NP21W_SWITCH_SETDEVICEIRQ_SUPPORTED 0 -#define NP21W_SWITCH_SETDEVICEIRQ_SND_26 1 -#define NP21W_SWITCH_SETDEVICEIRQ_SND_86 2 -#define NP21W_SWITCH_SETDEVICEIRQ_SND_118 3 -#define NP21W_SWITCH_SETDEVICEIRQ_SND_MATEX 4 -#define NP21W_SWITCH_SETDEVICEIRQ_SND_SB16 5 -#define NP21W_SWITCH_SETDEVICEIRQ_SND_SPB 6 -#define NP21W_SWITCH_SETDEVICEIRQ_MIDI_MPU 7 -#define NP21W_SWITCH_SETDEVICEIRQ_MIDI_SMPU 8 -#define NP21W_SWITCH_SETDEVICEIRQ_NET_LGY98 9 -#define NP21W_SWITCH_SETDEVICEIRQ_SND_SO 10 - - -static void setoutstr(const OEMCHAR *str) { - -#if defined(OSLANG_UCS2) - oemtext_oemtosjis(np2sysp.outstr, sizeof(np2sysp.outstr), str, -1); -#else - milstr_ncpy(np2sysp.outstr, str, sizeof(np2sysp.outstr)); -#endif - np2sysp.outpos = 0; -} - -void np2sysp_outstr(const void *arg1, long arg2) { - - setoutstr((OEMCHAR *)arg1); - (void)arg2; -} - -static void np2sysp_poweroff(const void *arg1, long arg2) { - - taskmng_exit(); - (void)arg1; - (void)arg2; -} - -static void np2sysp_cpu(const void *arg1, long arg2) { - - // CPUを返す -#if !defined(CPUCORE_IA32) // 80286 or V30 - if (!(CPU_TYPE & CPUTYPE_V30)) { - setoutstr(str_80286); - } - else { - setoutstr(str_v30); - } -#else - // 386機以降の場合 V30モードはエミュレーションだから固定(?) - setoutstr(str_pentium); -#endif - (void)arg1; - (void)arg2; -} - -static void np2sysp_clock(const void *arg1, long arg2) { - - OEMCHAR str[16]; - - OEMSPRINTF(str, str_mhz, (pccore.realclock + 500000) / 1000000); - setoutstr(str); - (void)arg1; - (void)arg2; -} - -static void np2sysp_multiple(const void *arg1, long arg2) { - - OEMCHAR str[16]; - - OEMSPRINTF(str, str_u, pccore.multiple); - setoutstr(str); - (void)arg1; - (void)arg2; -} - -static void np2sysp_hwreset(const void *arg1, long arg2) { - - pcstat.hardwarereset = TRUE; - (void)arg1; - (void)arg2; -} - -static void np2sysp_changeclock(const void *arg1, long arg2) { - - OEMCHAR str[16]; - - OEMSPRINTF(str, str_mhz, (pccore.realclock + 500000) / 1000000); - setoutstr(str); - (void)arg1; - (void)arg2; -} - -// np21/w extensions -static void np2sysp_cngclkmul(const void *arg1, long arg2) { - - OEMCHAR str[16]; - UINT8 oldclockmul = pccore.maxmultiple; - UINT8 oldclockmult = pccore.multiple; - UINT8 newclockmul = (np2sysp.outval >> 24); - - if(newclockmul > 0 && pccore.multiple != newclockmul) { - np2sysp.outval = (oldclockmul << 24) + (np2sysp.outval >> 8); - - pccore.multiple = newclockmul; - pccore.maxmultiple = newclockmul; - pccore.realclock = pccore.baseclock * pccore.multiple; - pcm86_changeclock(oldclockmult); - nevent_changeclock(oldclockmult, pccore.multiple); - - sound_changeclock(); - beep_changeclock(); - mpu98ii_changeclock(); -#if defined(SUPPORT_SMPU98) - smpu98_changeclock(); -#endif - keyboard_changeclock(); - mouseif_changeclock(); - gdc_updateclock(); - } - - OEMSPRINTF(str, OEMTEXT("%u"), pccore.maxmultiple); - setoutstr(str); - (void)arg1; - (void)arg2; -} - -static void np2sysp_getconfig(const void *arg1, long arg2) { - - OEMCHAR str[16]; - UINT8 configid = (np2sysp.outval >> 24) & 0xff; - UINT8 configvalue = 0; - UINT16 configvalue16 = 0; - - switch(configid){ - case NP21W_SWITCH_SOUNDBOARD: - configvalue = g_nSoundID; - break; - case NP21W_SWITCH_GD54XXTYPE: -#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) - configvalue16 = np2clvga.gd54xxtype; -#endif - OEMSPRINTF(str, OEMTEXT("%u"), configvalue16); - setoutstr(str); - return; - case NP21W_SWITCH_PCIENABLE: -#if defined(SUPPORT_PCI) - configvalue = pcidev.enable ? 1 : 0; -#endif - return; - case NP21W_SWITCH_ASYNCCPU: -#if defined(SUPPORT_ASYNC_CPU) - configvalue = np2cfg.asynccpu ? 1 : 0; -#endif /* defined(SUPPORT_ASYNC_CPU) */ - break; - case NP21W_SWITCH_DISABLESOUNDROM: - configvalue = 0; // 常時0 - break; -#if defined(SUPPORT_IDEIO) - case NP21W_SWITCH_SETIDEWAIT_R: - configvalue = (UINT8)(ideio.rwait >> 8); - break; - case NP21W_SWITCH_SETIDEWAIT_W: - configvalue = (UINT8)(ideio.wwait >> 8); - break; -#endif - case NP21W_SWITCH_AUTOHIDECURSOR: -#if defined(NP2_WIN) - configvalue = mousemng_getautohidecursor(); -#endif - break; - case NP21W_SWITCH_SETDEVICEIRQ: - { - UINT8 targetvalue = (np2sysp.outval >> 16) & 0xff; - int opna_idx; - if (g_nSoundID == SOUNDID_PC_9801_86_WSS || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_WAVESTAR || g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16) { - opna_idx = 1; - } - else { - opna_idx = 0; - } - configvalue = 0xfe; // デバイスがない場合は0xfeを返す - switch (targetvalue) { - case NP21W_SWITCH_SETDEVICEIRQ_SUPPORTED: - configvalue = 98; // サポート確認用 常時98を返す - break; - case NP21W_SWITCH_SETDEVICEIRQ_SND_26: - if (g_nSoundID == SOUNDID_PC_9801_26K) { - configvalue = g_opna[0].s.irq; - } - else if (g_nSoundID == SOUNDID_PC_9801_86_26K) { - configvalue = g_opna[1].s.irq; - } - break; - case NP21W_SWITCH_SETDEVICEIRQ_SND_86: - if (g_nSoundID == SOUNDID_PC_9801_86 || - g_nSoundID == SOUNDID_PC_9801_86_26K || - g_nSoundID == SOUNDID_PC_9801_86_118 || - g_nSoundID == SOUNDID_PC_9801_86_118_SB16 || - g_nSoundID == SOUNDID_PC_9801_86_ADPCM || - g_nSoundID == SOUNDID_PC_9801_86_SB16 || - g_nSoundID == SOUNDID_PC_9801_86_WSS || - g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || - g_nSoundID == SOUNDID_86_SPEAKBOARD) { - configvalue = g_pcm86.irq; - } - break; - case NP21W_SWITCH_SETDEVICEIRQ_SND_118: - if (g_nSoundID == SOUNDID_PC_9801_118 || - g_nSoundID == SOUNDID_PC_9801_118_SB16 || - g_nSoundID == SOUNDID_PC_9801_86_118 || - g_nSoundID == SOUNDID_PC_9801_86_118_SB16) { - configvalue = cs4231.dmairq; - } - break; - case NP21W_SWITCH_SETDEVICEIRQ_SND_MATEX: - if (g_nSoundID == SOUNDID_MATE_X_PCM || - g_nSoundID == SOUNDID_WSS_SB16 || - g_nSoundID == SOUNDID_PC_9801_86_WSS || - g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16) { - configvalue = cs4231.dmairq; - } - break; -#if defined(SUPPORT_SOUND_SB16) - case NP21W_SWITCH_SETDEVICEIRQ_SND_SB16: - if (g_nSoundID == SOUNDID_SB16 || - g_nSoundID == SOUNDID_WSS_SB16 || - g_nSoundID == SOUNDID_PC_9801_86_SB16 || - g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || - g_nSoundID == SOUNDID_PC_9801_118_SB16 || - g_nSoundID == SOUNDID_PC_9801_86_118_SB16) { - configvalue = g_sb16.dmairq; - } - break; -#endif - case NP21W_SWITCH_SETDEVICEIRQ_SND_SPB: - if (g_nSoundID == SOUNDID_SPEAKBOARD || g_nSoundID == SOUNDID_SPARKBOARD) { - configvalue = g_opna[0].s.irq; - } - else if (g_nSoundID == SOUNDID_86_SPEAKBOARD) { - configvalue = g_opna[1].s.irq; - } - break; - case NP21W_SWITCH_SETDEVICEIRQ_MIDI_MPU: - if (mpu98.enable) { - configvalue = mpu98.irqnum; - } - break; -#if defined(SUPPORT_SMPU98) - case NP21W_SWITCH_SETDEVICEIRQ_MIDI_SMPU: - if (smpu98.enable) { - configvalue = smpu98.irqnum; - } - break; -#endif -#if defined(SUPPORT_LGY98) - case NP21W_SWITCH_SETDEVICEIRQ_NET_LGY98: - if (lgy98cfg.enabled) { - configvalue = lgy98cfg.irq; - } - break; -#endif - case NP21W_SWITCH_SETDEVICEIRQ_SND_SO: - if (g_nSoundID == SOUNDID_SOUNDORCHESTRA || g_nSoundID == SOUNDID_SOUNDORCHESTRAV) { - configvalue = g_opna[0].s.irq; - } - break; - default: - configvalue = 0xfd; // 番号自体無効なら0xfdを返す - break; - } - break; - } - case NP21W_SWITCH_DUMMY: - default: - break; - } - - OEMSPRINTF(str, OEMTEXT("%u"), configvalue); - setoutstr(str); - (void)arg1; - (void)arg2; -} -static void np2sysp_cngconfig(const void *arg1, long arg2) { - - OEMCHAR str[16]; - UINT8 configid = (np2sysp.outval >> 24) & 0xff; - UINT8 configvalue = (np2sysp.outval >> 16) & 0xff; - UINT16 configvalue16 = 0; - - switch(configid){ - case NP21W_SWITCH_SYNCCLOCK: -#if defined(SUPPORT_HRTIMER) - if(configvalue == 1){ - _SYSTIME hrtimertime; - UINT32 hrtimertimeuint; - - timemng_gettime(&hrtimertime); - hrtimertimeuint = (((UINT32)hrtimertime.hour*60 + (UINT32)hrtimertime.minute)*60 + (UINT32)hrtimertime.second)*32 + ((UINT32)hrtimertime.milli*32)/1000; - hrtimertimeuint |= 0x400000; // こうしないとWin98の時計が1日ずれる? - STOREINTELDWORD(mem+0x04F1, hrtimertimeuint); // XXX: 04F4にも書いちゃってるけど差し当たっては問題なさそうなので・・・ - } -#endif /* defined(SUPPORT_HRTIMER) */ - break; - case NP21W_SWITCH_SOUNDBOARD: - if(configvalue != (UINT8)g_nSoundID){ - sound_reset(); - fmboard_unbind(); - if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16){ - iocore_detachout(cs4231.port[10]); - iocore_detachinp(cs4231.port[10]); - iocore_detachout(cs4231.port[10]+1); - iocore_detachinp(cs4231.port[10]+1); - } - soundrom_reset(); - fmboard_reset(&np2cfg, (SOUNDID)configvalue); - fmboard_bind(); - if (((pccore.model & PCMODELMASK) >= PCMODEL_VX) && - (pccore.sound & 0x7e)) { - if(g_nSoundID == SOUNDID_MATE_X_PCM || ((g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16) && np2cfg.snd118irqf == np2cfg.snd118irqp) || g_nSoundID == SOUNDID_PC_9801_86_WSS || g_nSoundID == SOUNDID_WAVESTAR || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ - iocore_out8(0x188, 0x27); - iocore_out8(0x18a, 0x30); - if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_WAVESTAR || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ - iocore_out8(cs4231.port[4], 0x27); - iocore_out8(cs4231.port[4]+2, 0x30); - } - }else{ - iocore_out8(0x188, 0x27); - iocore_out8(0x18a, 0x3f); - } - } - if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ - iocore_attachout(cs4231.port[10], mpu98ii_o0); - iocore_attachinp(cs4231.port[10], mpu98ii_i0); - iocore_attachout(cs4231.port[10]+1, mpu98ii_o2); - iocore_attachinp(cs4231.port[10]+1, mpu98ii_i2); - switch(np2cfg.snd118irqm){ - case 10: - mpu98.irqnum = 10; - break; - } - } -#if defined(SUPPORT_IDEIO) - ideio_bindCDDA(); -#endif /* defined(SUPPORT_IDEIO) */ - } - break; - case NP21W_SWITCH_GD54XXTYPE: -#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) - pc98_cirrus_vga_unbind(); - configvalue16 = (np2sysp.outval >> 8) & 0xffff; - if(configvalue16 != 0){ - np2clvga.gd54xxtype = configvalue16; - }else{ - np2clvga.gd54xxtype = np2clvga.defgd54xxtype; - } - pc98_cirrus_vga_bind(); - np2clvga.VRAMWindowAddr2 = 0; - np2clvga.VRAMWindowAddr3 = 0; - pc98_cirrus_vga_initVRAMWindowAddr(); - np2clvga.mmioenable = 0; - np2wab.paletteChanged = 1; - pc98_cirrus_vga_resetresolution(); -#endif - OEMSPRINTF(str, OEMTEXT("%u"), configvalue16); - setoutstr(str); - return; - case NP21W_SWITCH_PCIENABLE: -#if defined(SUPPORT_PCI) - if(configvalue==0){ - pcidev.enable = configvalue; - }else{ - if(!pcidev.enable){ - int oldusepci = np2cfg.usepci; - np2cfg.usepci = 1; - pcidev_reset(&np2cfg); - pcidev_bind(); -#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) - // 作り直し - pc98_cirrus_vga_unbind(); - pc98_cirrus_vga_bind(); - np2clvga.VRAMWindowAddr2 = 0; - np2clvga.VRAMWindowAddr3 = 0; - pc98_cirrus_vga_initVRAMWindowAddr(); - np2clvga.mmioenable = 0; - np2wab.paletteChanged = 1; - pc98_cirrus_vga_resetresolution(); -#endif - np2cfg.usepci = oldusepci; - } - } - configvalue = pcidev.enable; -#endif - return; - case NP21W_SWITCH_ASYNCCPU: -#if defined(SUPPORT_ASYNC_CPU) - np2cfg.asynccpu = configvalue ? 1 : 0; - configvalue = np2cfg.asynccpu ? 1 : 0; -#endif /* defined(SUPPORT_ASYNC_CPU) */ - break; - case NP21W_SWITCH_DISABLESOUNDROM: - if(configvalue == 1){ - soundrom_reset(); // サウンドROMを消す - } - break; -#if defined(SUPPORT_IDEIO) - case NP21W_SWITCH_SETIDEWAIT_R: - ideio.rwait = configvalue << 8; - break; - case NP21W_SWITCH_SETIDEWAIT_W: - ideio.wwait = configvalue << 8; - break; -#endif - case NP21W_SWITCH_AUTOHIDECURSOR: -#if defined(NP2_WIN) - mousemng_setautohidecursor(configvalue); -#endif - break; - case NP21W_SWITCH_SETDEVICEIRQ: - { - // デバイスのIRQLを設定 デバイスで有効なIRQのみ設定可能 ただし事実上の無効化のためにIRQ14には設定できるようにする - UINT8 retvalue = 0xfe; // デバイスがない場合は0xfeを返す - UINT8 irqvalue = (np2sysp.outval >> 8) & 0xff; - int opna_idx; - if (g_nSoundID == SOUNDID_PC_9801_86_WSS || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_WAVESTAR || g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16) { - opna_idx = 1; - } - else { - opna_idx = 0; - } - switch (configvalue) { - case NP21W_SWITCH_SETDEVICEIRQ_SUPPORTED: - retvalue = 98; // サポート確認用 常時98を返す - break; - case NP21W_SWITCH_SETDEVICEIRQ_SND_26: - if (irqvalue == 0x03 || irqvalue == 0x0d || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { - if (g_nSoundID == SOUNDID_PC_9801_26K) { - g_opna[0].s.irq = irqvalue; - retvalue = irqvalue; // 受付されたらその値を返す - } - else if (g_nSoundID == SOUNDID_PC_9801_86_26K) { - g_opna[1].s.irq = irqvalue; - retvalue = irqvalue; // 受付されたらその値を返す - } - } - break; - case NP21W_SWITCH_SETDEVICEIRQ_SND_86: - if (irqvalue == 0x03 || irqvalue == 0x0d || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { - g_opna[0].s.irq = irqvalue; - g_pcm86.irq = irqvalue; - retvalue = irqvalue; // 受付されたらその値を返す - } - break; - case NP21W_SWITCH_SETDEVICEIRQ_SND_118: - if (irqvalue == 0x03 || irqvalue == 0x06 || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { - g_opna[opna_idx].s.irq = irqvalue; - cs4231.dmairq = irqvalue; - retvalue = irqvalue; // 受付されたらその値を返す - } - break; - case NP21W_SWITCH_SETDEVICEIRQ_SND_MATEX: - if (irqvalue == 0x03 || irqvalue == 0x06 || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { - cs4231.dmairq = irqvalue; - retvalue = irqvalue; // 受付されたらその値を返す - } - break; -#if defined(SUPPORT_SOUND_SB16) - case NP21W_SWITCH_SETDEVICEIRQ_SND_SB16: - if (irqvalue == 3 || irqvalue == 5 || irqvalue == 10 || irqvalue == 12 || irqvalue == 0xff) { - g_sb16.dmairq = 3; - g_sb16.dsp_info.dmairq = ct1741_get_dma_irq(); - retvalue = irqvalue; // 受付されたらその値を返す - } - break; -#endif - case NP21W_SWITCH_SETDEVICEIRQ_SND_SPB: - if (irqvalue == 0x03 || irqvalue == 0x0d || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { - g_opna[0].s.irq = irqvalue; - g_pcm86.irq = irqvalue; - retvalue = irqvalue; // 受付されたらその値を返す - } - break; - case NP21W_SWITCH_SETDEVICEIRQ_MIDI_MPU: - if (irqvalue == 3 || irqvalue == 5 || irqvalue == 6 || irqvalue == 12 || irqvalue == 0xff) { - mpu98.irqnum = irqvalue; - retvalue = irqvalue; // 受付されたらその値を返す - } - break; -#if defined(SUPPORT_SMPU98) - case NP21W_SWITCH_SETDEVICEIRQ_MIDI_SMPU: - if (irqvalue == 3 || irqvalue == 5 || irqvalue == 6 || irqvalue == 12 || irqvalue == 0xff) { - smpu98.irqnum = irqvalue; - retvalue = irqvalue; // 受付されたらその値を返す - } - break; -#endif -#if defined(SUPPORT_LGY98) - case NP21W_SWITCH_SETDEVICEIRQ_NET_LGY98: - if (irqvalue == 3 || irqvalue == 5 || irqvalue == 6 || irqvalue == 12 || irqvalue == 0xff) { - lgy98cfg.irq = irqvalue; - lgy98.irq = irqvalue; - retvalue = irqvalue; // 受付されたらその値を返す - } - break; -#endif - case NP21W_SWITCH_SETDEVICEIRQ_SND_SO: - if (irqvalue == 0x03 || irqvalue == 0x0d || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { - if (g_nSoundID == SOUNDID_SOUNDORCHESTRA || g_nSoundID == SOUNDID_SOUNDORCHESTRAV) { - g_opna[0].s.irq = irqvalue; - retvalue = irqvalue; // 受付されたらその値を返す - } - } - break; - default: - retvalue = 0xfd; // 番号自体無効なら0xfdを返す - break; - } - configvalue = retvalue; - break; - } - case NP21W_SWITCH_DUMMY: - default: - break; - } - - OEMSPRINTF(str, OEMTEXT("%u"), configvalue); - setoutstr(str); - (void)arg1; - (void)arg2; -} -static void np2sysp_getmpos(const void* arg1, long arg2) -{ - OEMCHAR str[16] = { 0 }; - int mouseX, mouseY; - UINT8 mode = (np2sysp.outval >> 24) & 0xff; // 今は未使用 - - if (mode == 0 || mode == 1 || mode == 2 || mode == 3) - { -#if defined(NP2_WIN) - if (mousemng_getabspos(&mouseX, &mouseY)) -#else - if (0) -#endif - { - if (mouseX < 0) mouseX = 0; - if (mouseX > 65535) mouseX = 65535; - if (mouseY < 0) mouseY = 0; - if (mouseY > 65535) mouseY = 65535; - - if (mode == 1) - { - // Win3.1向け 強制レジスタ書き換えモード - CPU_DI |= 0x8000; // 絶対座標モード 本当はAXレジスタだが触れないのでDIで - CPU_BX = mouseX; // X座標 - CPU_CX = mouseY; // Y座標 - OEMSPRINTF(str, OEMTEXT("OK")); - } - else if (mode == 2) - { - // 一般向け 強制レジスタ書き換えモード - CPU_BX = mouseX; // X座標 - CPU_CX = mouseY; // Y座標 - CPU_FLAG |= C_FLAG; // 成功ならC_FLAGを立てる - OEMSPRINTF(str, OEMTEXT("OK")); - } - else if (mode == 3) - { - // 一般向け 強制レジスタ書き換えモード ボタンも取得 - SINT16 x, y; - UINT8 btn = mousemng_getstat(&x, &y, 0); - CPU_BX = mouseX; // X座標 - CPU_CX = mouseY; // Y座標 - CPU_DI = btn; // ボタンの状態 - CPU_FLAG |= C_FLAG; // 成功ならC_FLAGを立てる - OEMSPRINTF(str, OEMTEXT("OK")); - } - else - { - OEMSPRINTF(str, OEMTEXT("%d,%d"), mouseX, mouseY); - } - setoutstr(str); - } - else - { - if (mode == 2 || mode == 3) - { - // 一般向け 強制レジスタ書き換えモード - CPU_FLAG &= ~C_FLAG; // 失敗ならC_FLAGを消す - } - setoutstr(str); // 空文字列(エラー) - } - } - else if (mode == 4 || mode == 5) - { - // 一般向け 強制レジスタ書き換えモード 相対座標とボタンの取得 - SINT16 x, y; - UINT8 btn = mousemng_getstat(&x, &y, mode == 5 ? 1 : 0); // モード5は取得した座標をクリアする - CPU_BX = x; // X座標 - CPU_CX = y; // Y座標 - CPU_DI = btn; // ボタンの状態 - CPU_FLAG |= C_FLAG; // 成功ならC_FLAGを立てる - OEMSPRINTF(str, OEMTEXT("OK")); - } - else - { - setoutstr(str); // 空文字列(エラー) - } - (void)arg1; - (void)arg2; -} - - -// ---- - -static const char cmd_np2[] = "NP2"; -static const OEMCHAR rep_np2[] = OEMTEXT("NP2"); - -static const char cmd_ver[] = "ver"; -static const char cmd_poweroff[] = "poweroff"; -static const char cmd_credit[] = "credit"; -static const char cmd_cpu[] = "cpu"; -static const char cmd_clock[] = "clock"; -static const char cmd_multiple[] = "multiple"; -static const char cmd_hwreset[] = "hardwarereset"; -#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) -static const char cmd_sasibios[] = "sasibios"; -#endif -#if defined(SUPPORT_SCSI) -static const char cmd_scsibios[] = "scsibios"; -static const char cmd_scsidev[] = "scsi_dev"; -#endif -#if defined(SUPPORT_HOSTDRV) -static const char cmd_hdrvcheck[] = "check_hostdrv"; -static const char cmd_hdrvopen[] = "open_hostdrv"; -static const char cmd_hdrvclose[] = "close_hostdrv"; -static const char cmd_hdrvintr[] = "intr_hostdrv"; -static const char cmd_hdrvsetn[] = "setn_hostdrv"; // Set new protocol np21w ver0.86 rev95 -static const OEMCHAR rep_hdrvcheck[] = OEMTEXT("0.74"); -#endif - -// np21/w extensions -static const char cmd_cngclkmul[] = "changeclockmul"; // np21w ver0.86 rev44 -static const char cmd_cngconfig[] = "changeconfig"; // np21w ver0.86 rev44 -static const char cmd_getconfig[] = "getconfig"; // np21w ver0.86 rev44 -static const char cmd_getmpos[] = "getmpos"; // np21w ver0.86 rev94 - -#if defined(NP2SYSP_VER) -static const OEMCHAR str_syspver[] = OEMTEXT(NP2SYSP_VER); -#else -#define str_syspver str_null -#endif - -#if defined(NP2SYSP_CREDIT) -static const OEMCHAR str_syspcredit[] = OEMTEXT(NP2SYSP_CREDIT); -#else -#define str_syspcredit str_null -#endif - - -static const SYSPCMD np2spcmd[] = { - {cmd_np2, np2sysp_outstr, rep_np2, 0}, - {cmd_ver, np2sysp_outstr, str_syspver, 0}, - -// version:A - {cmd_poweroff, np2sysp_poweroff, NULL, 0}, - -// version:B - {cmd_credit, np2sysp_outstr, str_syspcredit, 0}, - {cmd_cpu, np2sysp_cpu, NULL, 0}, - {cmd_clock, np2sysp_clock, NULL, 0}, - {cmd_multiple, np2sysp_multiple, NULL, 0}, - -// version:C - {cmd_hwreset, np2sysp_hwreset, NULL, 0}, - -// extension -#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) - {cmd_sasibios, np2sysp_sasi, NULL, 0}, -#endif -#if defined(SUPPORT_SCSI) - {cmd_scsibios, np2sysp_scsi, NULL, 0}, - {cmd_scsidev, np2sysp_scsidev, NULL, 0}, -#endif - -#if defined(SUPPORT_HOSTDRV) - {cmd_hdrvcheck, np2sysp_outstr, rep_hdrvcheck, 0}, - {cmd_hdrvopen, hostdrv_mount, NULL, 0}, - {cmd_hdrvclose, hostdrv_unmount, NULL, 0}, - {cmd_hdrvintr, hostdrv_intr, NULL, 0}, - {cmd_hdrvsetn, hostdrv_setn, NULL, 0}, -#endif - {cmd_cngclkmul, np2sysp_cngclkmul, NULL, 0}, - {cmd_getconfig, np2sysp_getconfig, NULL, 0}, - {cmd_cngconfig, np2sysp_cngconfig, NULL, 0}, - {cmd_getmpos, np2sysp_getmpos, NULL, 0}, -}; - - -static BRESULT np2syspcmp(const char *p) { - - int len; - int pos; - - len = (int)STRLEN(p); - if (!len) { - return(FAILURE); - } - pos = np2sysp.strpos; - while(len--) { - if (p[len] != np2sysp.substr[pos]) { - return(FAILURE); - } - pos--; - pos &= NP2SYSP_MASK; - } - return(SUCCESS); -} - -static void IOOUTCALL np2sysp_o7ed(UINT port, REG8 dat) { - - np2sysp.outval = (dat << 24) | (np2sysp.outval >> 8); - (void)port; -} - -static void IOOUTCALL np2sysp_o7ef(UINT port, REG8 dat) { - -const SYSPCMD *cmd; -const SYSPCMD *cmdterm; - - np2sysp.substr[np2sysp.strpos] = (char)dat; - cmd = np2spcmd; - cmdterm = cmd + NELEMENTS(np2spcmd); - while(cmd < cmdterm) { - if (!np2syspcmp(cmd->key)) { - cmd->func(cmd->arg1, cmd->arg2); - break; - } - cmd++; - } - np2sysp.strpos++; - np2sysp.strpos &= NP2SYSP_MASK; - (void)port; -} - -static REG8 IOINPCALL np2sysp_i7ed(UINT port) { - - REG8 ret; - - ret = (REG8)(np2sysp.inpval & 0xff); - np2sysp.inpval = (ret << 24) | (np2sysp.inpval >> 8); - (void)port; - return(ret); -} - -static REG8 IOINPCALL np2sysp_i7ef(UINT port) { - - REG8 ret; - - ret = (UINT8)np2sysp.outstr[np2sysp.outpos]; - if (ret) { - np2sysp.outpos++; - np2sysp.outpos &= NP2SYSP_MASK; - } - (void)port; - return(ret); -} - -#if defined(NP2APPDEV) -static void IOOUTCALL np2sysp_o0e9(UINT port, REG8 dat) { - - APPDEVOUT(dat); - (void)port; -} - -static REG8 IOINPCALL np2sysp_i0e9(UINT port) { - - return((UINT8)port); -} -#endif - - -// ---- I/F - -void np2sysp_reset(const NP2CFG *pConfig) { - - ZeroMemory(&np2sysp, sizeof(np2sysp)); - - (void)pConfig; -} - -void np2sysp_bind(void) { - - iocore_attachout(0x07ed, np2sysp_o7ed); - iocore_attachout(0x07ef, np2sysp_o7ef); - iocore_attachinp(0x07ed, np2sysp_i7ed); - iocore_attachinp(0x07ef, np2sysp_i7ef); - -#if defined(NP2APPDEV) - iocore_attachout(0x00e9, np2sysp_o0e9); - iocore_attachinp(0x00e9, np2sysp_i0e9); -#endif -} - -#pragma code_seg() +#include +#include +#if defined(OSLANG_UCS2) +#include "oemtext.h" +#endif +#include "taskmng.h" +#include +#include +#include +#include +#if defined(SUPPORT_HOSTDRV) +#include +#endif +#include +#include +#include +#include +#include +#if defined(SUPPORT_SMPU98) +#include +#endif +#if defined(SUPPORT_IDEIO) +#include +#endif +#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) +#include +#include +#endif +#include "np2.h" +#if defined(SUPPORT_HRTIMER) +#include +#endif +#if defined(SUPPORT_LGY98) +#include +#include +#endif +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif +#include "dosio.h" +#include "mousemng.h" + +//#include + +// 性能上最適化で優先しない方がいいコードなのでわざと別セグメントに置く +#pragma code_seg(".MISCCODE") + +#if 0 +#undef TRACEOUT +static void trace_fmt_ex(const char* fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "¥n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +static void trace_fmt_exw(const WCHAR* fmt, ...) +{ + WCHAR stmp[2048]; + va_list ap; + va_start(ap, fmt); + vswprintf(stmp, 2048, fmt, ap); + wcscat(stmp, L"¥n"); + va_end(ap); + OutputDebugStringW(stmp); +} +#define TRACEOUTW(s) trace_fmt_exw s +#else +#define TRACEOUTW(s) (void)0 +#endif /* 1 */ + + +#define NP2SYSP_VER "C" +// #define NP2SYSP_CREDIT "" // 要るなら・・・ + +// NP2依存ポート +// port:07edh np2 value comm +// port:07efh np2 string comm + +// 基本的に STRINGでやり取りする +// ポート 7efh に 'NP2' と出力で "NP2"が返ってきたら NP2である + +// verA +// out->str: 'ver' in->str: ver番号 A〜 +// out->str: 'poweroff' NP2を終了 + +// verB +// out->str: 'cpu' in->str: CPU型番 +// out->str: 'clock' in->str: 動作クロック数 + + +// ---- + +typedef struct { +const char *key; + void (*func)(const void *arg1, long arg2); +const void *arg1; + long arg2; +} SYSPCMD; + +static const OEMCHAR str_80286[] = OEMTEXT("80286"); +static const OEMCHAR str_v30[] = OEMTEXT("V30"); +#if defined(CPUCORE_IA32) +static const OEMCHAR str_pentium[] = OEMTEXT("PENTIUM"); +#endif /* 0 */ +static const OEMCHAR str_mhz[] = OEMTEXT("%uMHz"); + +// np21/w dynamic config +#define NP21W_SWITCH_DUMMY 0 +#define NP21W_SWITCH_GD54XXTYPE 1 +#define NP21W_SWITCH_SOUNDBOARD 2 +#define NP21W_SWITCH_SYNCCLOCK 3 +#define NP21W_SWITCH_PCIENABLE 4 +#define NP21W_SWITCH_ASYNCCPU 5 +#define NP21W_SWITCH_DISABLESOUNDROM 6 +#define NP21W_SWITCH_SETIDEWAIT_R 7 +#define NP21W_SWITCH_SETIDEWAIT_W 8 +#define NP21W_SWITCH_AUTOHIDECURSOR 9 +#define NP21W_SWITCH_SETDEVICEIRQ 10 + +#define NP21W_SWITCH_SETDEVICEIRQ_SUPPORTED 0 +#define NP21W_SWITCH_SETDEVICEIRQ_SND_26 1 +#define NP21W_SWITCH_SETDEVICEIRQ_SND_86 2 +#define NP21W_SWITCH_SETDEVICEIRQ_SND_118 3 +#define NP21W_SWITCH_SETDEVICEIRQ_SND_MATEX 4 +#define NP21W_SWITCH_SETDEVICEIRQ_SND_SB16 5 +#define NP21W_SWITCH_SETDEVICEIRQ_SND_SPB 6 +#define NP21W_SWITCH_SETDEVICEIRQ_MIDI_MPU 7 +#define NP21W_SWITCH_SETDEVICEIRQ_MIDI_SMPU 8 +#define NP21W_SWITCH_SETDEVICEIRQ_NET_LGY98 9 +#define NP21W_SWITCH_SETDEVICEIRQ_SND_SO 10 + + +static void setoutstr(const OEMCHAR *str) { + +#if defined(OSLANG_UCS2) + oemtext_oemtosjis(np2sysp.outstr, sizeof(np2sysp.outstr), str, -1); +#else + milstr_ncpy(np2sysp.outstr, str, sizeof(np2sysp.outstr)); +#endif + np2sysp.outpos = 0; +} + +void np2sysp_outstr(const void *arg1, long arg2) { + + setoutstr((OEMCHAR *)arg1); + (void)arg2; +} + +static void np2sysp_poweroff(const void *arg1, long arg2) { + + taskmng_exit(); + (void)arg1; + (void)arg2; +} + +static void np2sysp_cpu(const void *arg1, long arg2) { + + // CPUを返す +#if !defined(CPUCORE_IA32) // 80286 or V30 + if (!(CPU_TYPE & CPUTYPE_V30)) { + setoutstr(str_80286); + } + else { + setoutstr(str_v30); + } +#else + // 386機以降の場合 V30モードはエミュレーションだから固定(?) + setoutstr(str_pentium); +#endif + (void)arg1; + (void)arg2; +} + +static void np2sysp_clock(const void *arg1, long arg2) { + + OEMCHAR str[16]; + + OEMSPRINTF(str, str_mhz, (pccore.realclock + 500000) / 1000000); + setoutstr(str); + (void)arg1; + (void)arg2; +} + +static void np2sysp_multiple(const void *arg1, long arg2) { + + OEMCHAR str[16]; + + OEMSPRINTF(str, str_u, pccore.multiple); + setoutstr(str); + (void)arg1; + (void)arg2; +} + +static void np2sysp_hwreset(const void *arg1, long arg2) { + + pcstat.hardwarereset = TRUE; + (void)arg1; + (void)arg2; +} + +static void np2sysp_changeclock(const void *arg1, long arg2) { + + OEMCHAR str[16]; + + OEMSPRINTF(str, str_mhz, (pccore.realclock + 500000) / 1000000); + setoutstr(str); + (void)arg1; + (void)arg2; +} + +// np21/w extensions +static void np2sysp_cngclkmul(const void *arg1, long arg2) { + + OEMCHAR str[16]; + UINT8 oldclockmul = pccore.maxmultiple; + UINT8 oldclockmult = pccore.multiple; + UINT8 newclockmul = (np2sysp.outval >> 24); + + if(newclockmul > 0 && pccore.multiple != newclockmul) { + np2sysp.outval = (oldclockmul << 24) + (np2sysp.outval >> 8); + + pccore.multiple = newclockmul; + pccore.maxmultiple = newclockmul; + pccore.realclock = pccore.baseclock * pccore.multiple; + pcm86_changeclock(oldclockmult); + nevent_changeclock(oldclockmult, pccore.multiple); + + sound_changeclock(); + beep_changeclock(); + mpu98ii_changeclock(); +#if defined(SUPPORT_SMPU98) + smpu98_changeclock(); +#endif + keyboard_changeclock(); + mouseif_changeclock(); + gdc_updateclock(); + } + + OEMSPRINTF(str, OEMTEXT("%u"), pccore.maxmultiple); + setoutstr(str); + (void)arg1; + (void)arg2; +} + +static void np2sysp_getconfig(const void *arg1, long arg2) { + + OEMCHAR str[16]; + UINT8 configid = (np2sysp.outval >> 24) & 0xff; + UINT8 configvalue = 0; + UINT16 configvalue16 = 0; + + switch(configid){ + case NP21W_SWITCH_SOUNDBOARD: + configvalue = g_nSoundID; + break; + case NP21W_SWITCH_GD54XXTYPE: +#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) + configvalue16 = np2clvga.gd54xxtype; +#endif + OEMSPRINTF(str, OEMTEXT("%u"), configvalue16); + setoutstr(str); + return; + case NP21W_SWITCH_PCIENABLE: +#if defined(SUPPORT_PCI) + configvalue = pcidev.enable ? 1 : 0; +#endif + return; + case NP21W_SWITCH_ASYNCCPU: +#if defined(SUPPORT_ASYNC_CPU) + configvalue = np2cfg.asynccpu ? 1 : 0; +#endif /* defined(SUPPORT_ASYNC_CPU) */ + break; + case NP21W_SWITCH_DISABLESOUNDROM: + configvalue = 0; // 常時0 + break; +#if defined(SUPPORT_IDEIO) + case NP21W_SWITCH_SETIDEWAIT_R: + configvalue = (UINT8)(ideio.rwait >> 8); + break; + case NP21W_SWITCH_SETIDEWAIT_W: + configvalue = (UINT8)(ideio.wwait >> 8); + break; +#endif + case NP21W_SWITCH_AUTOHIDECURSOR: +#if defined(NP2_WIN) + configvalue = mousemng_getautohidecursor(); +#endif + break; + case NP21W_SWITCH_SETDEVICEIRQ: + { + UINT8 targetvalue = (np2sysp.outval >> 16) & 0xff; + int opna_idx; + if (g_nSoundID == SOUNDID_PC_9801_86_WSS || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_WAVESTAR || g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16) { + opna_idx = 1; + } + else { + opna_idx = 0; + } + configvalue = 0xfe; // デバイスがない場合は0xfeを返す + switch (targetvalue) { + case NP21W_SWITCH_SETDEVICEIRQ_SUPPORTED: + configvalue = 98; // サポート確認用 常時98を返す + break; + case NP21W_SWITCH_SETDEVICEIRQ_SND_26: + if (g_nSoundID == SOUNDID_PC_9801_26K) { + configvalue = g_opna[0].s.irq; + } + else if (g_nSoundID == SOUNDID_PC_9801_86_26K) { + configvalue = g_opna[1].s.irq; + } + break; + case NP21W_SWITCH_SETDEVICEIRQ_SND_86: + if (g_nSoundID == SOUNDID_PC_9801_86 || + g_nSoundID == SOUNDID_PC_9801_86_26K || + g_nSoundID == SOUNDID_PC_9801_86_118 || + g_nSoundID == SOUNDID_PC_9801_86_118_SB16 || + g_nSoundID == SOUNDID_PC_9801_86_ADPCM || + g_nSoundID == SOUNDID_PC_9801_86_SB16 || + g_nSoundID == SOUNDID_PC_9801_86_WSS || + g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || + g_nSoundID == SOUNDID_86_SPEAKBOARD) { + configvalue = g_pcm86.irq; + } + break; + case NP21W_SWITCH_SETDEVICEIRQ_SND_118: + if (g_nSoundID == SOUNDID_PC_9801_118 || + g_nSoundID == SOUNDID_PC_9801_118_SB16 || + g_nSoundID == SOUNDID_PC_9801_86_118 || + g_nSoundID == SOUNDID_PC_9801_86_118_SB16) { + configvalue = cs4231.dmairq; + } + break; + case NP21W_SWITCH_SETDEVICEIRQ_SND_MATEX: + if (g_nSoundID == SOUNDID_MATE_X_PCM || + g_nSoundID == SOUNDID_WSS_SB16 || + g_nSoundID == SOUNDID_PC_9801_86_WSS || + g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16) { + configvalue = cs4231.dmairq; + } + break; +#if defined(SUPPORT_SOUND_SB16) + case NP21W_SWITCH_SETDEVICEIRQ_SND_SB16: + if (g_nSoundID == SOUNDID_SB16 || + g_nSoundID == SOUNDID_WSS_SB16 || + g_nSoundID == SOUNDID_PC_9801_86_SB16 || + g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || + g_nSoundID == SOUNDID_PC_9801_118_SB16 || + g_nSoundID == SOUNDID_PC_9801_86_118_SB16) { + configvalue = g_sb16.dmairq; + } + break; +#endif + case NP21W_SWITCH_SETDEVICEIRQ_SND_SPB: + if (g_nSoundID == SOUNDID_SPEAKBOARD || g_nSoundID == SOUNDID_SPARKBOARD) { + configvalue = g_opna[0].s.irq; + } + else if (g_nSoundID == SOUNDID_86_SPEAKBOARD) { + configvalue = g_opna[1].s.irq; + } + break; + case NP21W_SWITCH_SETDEVICEIRQ_MIDI_MPU: + if (mpu98.enable) { + configvalue = mpu98.irqnum; + } + break; +#if defined(SUPPORT_SMPU98) + case NP21W_SWITCH_SETDEVICEIRQ_MIDI_SMPU: + if (smpu98.enable) { + configvalue = smpu98.irqnum; + } + break; +#endif +#if defined(SUPPORT_LGY98) + case NP21W_SWITCH_SETDEVICEIRQ_NET_LGY98: + if (lgy98cfg.enabled) { + configvalue = lgy98cfg.irq; + } + break; +#endif + case NP21W_SWITCH_SETDEVICEIRQ_SND_SO: + if (g_nSoundID == SOUNDID_SOUNDORCHESTRA || g_nSoundID == SOUNDID_SOUNDORCHESTRAV) { + configvalue = g_opna[0].s.irq; + } + break; + default: + configvalue = 0xfd; // 番号自体無効なら0xfdを返す + break; + } + break; + } + case NP21W_SWITCH_DUMMY: + default: + break; + } + + OEMSPRINTF(str, OEMTEXT("%u"), configvalue); + setoutstr(str); + (void)arg1; + (void)arg2; +} +static void np2sysp_cngconfig(const void *arg1, long arg2) { + + OEMCHAR str[16]; + UINT8 configid = (np2sysp.outval >> 24) & 0xff; + UINT8 configvalue = (np2sysp.outval >> 16) & 0xff; + UINT16 configvalue16 = 0; + + switch(configid){ + case NP21W_SWITCH_SYNCCLOCK: +#if defined(SUPPORT_HRTIMER) + if(configvalue == 1){ + _SYSTIME hrtimertime; + UINT32 hrtimertimeuint; + + timemng_gettime(&hrtimertime); + hrtimertimeuint = (((UINT32)hrtimertime.hour*60 + (UINT32)hrtimertime.minute)*60 + (UINT32)hrtimertime.second)*32 + ((UINT32)hrtimertime.milli*32)/1000; + hrtimertimeuint |= 0x400000; // こうしないとWin98の時計が1日ずれる? + STOREINTELDWORD(mem+0x04F1, hrtimertimeuint); // XXX: 04F4にも書いちゃってるけど差し当たっては問題なさそうなので・・・ + } +#endif /* defined(SUPPORT_HRTIMER) */ + break; + case NP21W_SWITCH_SOUNDBOARD: + if(configvalue != (UINT8)g_nSoundID){ + sound_reset(); + fmboard_unbind(); + if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16){ + iocore_detachout(cs4231.port[10]); + iocore_detachinp(cs4231.port[10]); + iocore_detachout(cs4231.port[10]+1); + iocore_detachinp(cs4231.port[10]+1); + } + soundrom_reset(); + fmboard_reset(&np2cfg, (SOUNDID)configvalue); + fmboard_bind(); + if (((pccore.model & PCMODELMASK) >= PCMODEL_VX) && + (pccore.sound & 0x7e)) { + if(g_nSoundID == SOUNDID_MATE_X_PCM || ((g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16) && np2cfg.snd118irqf == np2cfg.snd118irqp) || g_nSoundID == SOUNDID_PC_9801_86_WSS || g_nSoundID == SOUNDID_WAVESTAR || g_nSoundID==SOUNDID_PC_9801_86_WSS_SB16){ + iocore_out8(0x188, 0x27); + iocore_out8(0x18a, 0x30); + if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID==SOUNDID_WAVESTAR || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ + iocore_out8(cs4231.port[4], 0x27); + iocore_out8(cs4231.port[4]+2, 0x30); + } + }else{ + iocore_out8(0x188, 0x27); + iocore_out8(0x18a, 0x3f); + } + } + if(g_nSoundID == SOUNDID_PC_9801_118 || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_PC_9801_118_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16){ + iocore_attachout(cs4231.port[10], mpu98ii_o0); + iocore_attachinp(cs4231.port[10], mpu98ii_i0); + iocore_attachout(cs4231.port[10]+1, mpu98ii_o2); + iocore_attachinp(cs4231.port[10]+1, mpu98ii_i2); + switch(np2cfg.snd118irqm){ + case 10: + mpu98.irqnum = 10; + break; + } + } +#if defined(SUPPORT_IDEIO) + ideio_bindCDDA(); +#endif /* defined(SUPPORT_IDEIO) */ + } + break; + case NP21W_SWITCH_GD54XXTYPE: +#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) + pc98_cirrus_vga_unbind(); + configvalue16 = (np2sysp.outval >> 8) & 0xffff; + if(configvalue16 != 0){ + np2clvga.gd54xxtype = configvalue16; + }else{ + np2clvga.gd54xxtype = np2clvga.defgd54xxtype; + } + pc98_cirrus_vga_bind(); + np2clvga.VRAMWindowAddr2 = 0; + np2clvga.VRAMWindowAddr3 = 0; + pc98_cirrus_vga_initVRAMWindowAddr(); + np2clvga.mmioenable = 0; + np2wab.paletteChanged = 1; + pc98_cirrus_vga_resetresolution(); +#endif + OEMSPRINTF(str, OEMTEXT("%u"), configvalue16); + setoutstr(str); + return; + case NP21W_SWITCH_PCIENABLE: +#if defined(SUPPORT_PCI) + if(configvalue==0){ + pcidev.enable = configvalue; + }else{ + if(!pcidev.enable){ + int oldusepci = np2cfg.usepci; + np2cfg.usepci = 1; + pcidev_reset(&np2cfg); + pcidev_bind(); +#if defined(SUPPORT_WAB) && defined(SUPPORT_CL_GD5430) + // 作り直し + pc98_cirrus_vga_unbind(); + pc98_cirrus_vga_bind(); + np2clvga.VRAMWindowAddr2 = 0; + np2clvga.VRAMWindowAddr3 = 0; + pc98_cirrus_vga_initVRAMWindowAddr(); + np2clvga.mmioenable = 0; + np2wab.paletteChanged = 1; + pc98_cirrus_vga_resetresolution(); +#endif + np2cfg.usepci = oldusepci; + } + } + configvalue = pcidev.enable; +#endif + return; + case NP21W_SWITCH_ASYNCCPU: +#if defined(SUPPORT_ASYNC_CPU) + np2cfg.asynccpu = configvalue ? 1 : 0; + configvalue = np2cfg.asynccpu ? 1 : 0; +#endif /* defined(SUPPORT_ASYNC_CPU) */ + break; + case NP21W_SWITCH_DISABLESOUNDROM: + if(configvalue == 1){ + soundrom_reset(); // サウンドROMを消す + } + break; +#if defined(SUPPORT_IDEIO) + case NP21W_SWITCH_SETIDEWAIT_R: + ideio.rwait = configvalue << 8; + break; + case NP21W_SWITCH_SETIDEWAIT_W: + ideio.wwait = configvalue << 8; + break; +#endif + case NP21W_SWITCH_AUTOHIDECURSOR: +#if defined(NP2_WIN) + mousemng_setautohidecursor(configvalue); +#endif + break; + case NP21W_SWITCH_SETDEVICEIRQ: + { + // デバイスのIRQLを設定 デバイスで有効なIRQのみ設定可能 ただし事実上の無効化のためにIRQ14には設定できるようにする + UINT8 retvalue = 0xfe; // デバイスがない場合は0xfeを返す + UINT8 irqvalue = (np2sysp.outval >> 8) & 0xff; + int opna_idx; + if (g_nSoundID == SOUNDID_PC_9801_86_WSS || g_nSoundID == SOUNDID_PC_9801_86_118 || g_nSoundID == SOUNDID_WAVESTAR || g_nSoundID == SOUNDID_PC_9801_86_WSS_SB16 || g_nSoundID == SOUNDID_PC_9801_86_118_SB16) { + opna_idx = 1; + } + else { + opna_idx = 0; + } + switch (configvalue) { + case NP21W_SWITCH_SETDEVICEIRQ_SUPPORTED: + retvalue = 98; // サポート確認用 常時98を返す + break; + case NP21W_SWITCH_SETDEVICEIRQ_SND_26: + if (irqvalue == 0x03 || irqvalue == 0x0d || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { + if (g_nSoundID == SOUNDID_PC_9801_26K) { + g_opna[0].s.irq = irqvalue; + retvalue = irqvalue; // 受付されたらその値を返す + } + else if (g_nSoundID == SOUNDID_PC_9801_86_26K) { + g_opna[1].s.irq = irqvalue; + retvalue = irqvalue; // 受付されたらその値を返す + } + } + break; + case NP21W_SWITCH_SETDEVICEIRQ_SND_86: + if (irqvalue == 0x03 || irqvalue == 0x0d || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { + g_opna[0].s.irq = irqvalue; + g_pcm86.irq = irqvalue; + retvalue = irqvalue; // 受付されたらその値を返す + } + break; + case NP21W_SWITCH_SETDEVICEIRQ_SND_118: + if (irqvalue == 0x03 || irqvalue == 0x06 || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { + g_opna[opna_idx].s.irq = irqvalue; + cs4231.dmairq = irqvalue; + retvalue = irqvalue; // 受付されたらその値を返す + } + break; + case NP21W_SWITCH_SETDEVICEIRQ_SND_MATEX: + if (irqvalue == 0x03 || irqvalue == 0x06 || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { + cs4231.dmairq = irqvalue; + retvalue = irqvalue; // 受付されたらその値を返す + } + break; +#if defined(SUPPORT_SOUND_SB16) + case NP21W_SWITCH_SETDEVICEIRQ_SND_SB16: + if (irqvalue == 3 || irqvalue == 5 || irqvalue == 10 || irqvalue == 12 || irqvalue == 0xff) { + g_sb16.dmairq = 3; + g_sb16.dsp_info.dmairq = ct1741_get_dma_irq(); + retvalue = irqvalue; // 受付されたらその値を返す + } + break; +#endif + case NP21W_SWITCH_SETDEVICEIRQ_SND_SPB: + if (irqvalue == 0x03 || irqvalue == 0x0d || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { + g_opna[0].s.irq = irqvalue; + g_pcm86.irq = irqvalue; + retvalue = irqvalue; // 受付されたらその値を返す + } + break; + case NP21W_SWITCH_SETDEVICEIRQ_MIDI_MPU: + if (irqvalue == 3 || irqvalue == 5 || irqvalue == 6 || irqvalue == 12 || irqvalue == 0xff) { + mpu98.irqnum = irqvalue; + retvalue = irqvalue; // 受付されたらその値を返す + } + break; +#if defined(SUPPORT_SMPU98) + case NP21W_SWITCH_SETDEVICEIRQ_MIDI_SMPU: + if (irqvalue == 3 || irqvalue == 5 || irqvalue == 6 || irqvalue == 12 || irqvalue == 0xff) { + smpu98.irqnum = irqvalue; + retvalue = irqvalue; // 受付されたらその値を返す + } + break; +#endif +#if defined(SUPPORT_LGY98) + case NP21W_SWITCH_SETDEVICEIRQ_NET_LGY98: + if (irqvalue == 3 || irqvalue == 5 || irqvalue == 6 || irqvalue == 12 || irqvalue == 0xff) { + lgy98cfg.irq = irqvalue; + lgy98.irq = irqvalue; + retvalue = irqvalue; // 受付されたらその値を返す + } + break; +#endif + case NP21W_SWITCH_SETDEVICEIRQ_SND_SO: + if (irqvalue == 0x03 || irqvalue == 0x0d || irqvalue == 0x0a || irqvalue == 0x0c || irqvalue == 0xff) { + if (g_nSoundID == SOUNDID_SOUNDORCHESTRA || g_nSoundID == SOUNDID_SOUNDORCHESTRAV) { + g_opna[0].s.irq = irqvalue; + retvalue = irqvalue; // 受付されたらその値を返す + } + } + break; + default: + retvalue = 0xfd; // 番号自体無効なら0xfdを返す + break; + } + configvalue = retvalue; + break; + } + case NP21W_SWITCH_DUMMY: + default: + break; + } + + OEMSPRINTF(str, OEMTEXT("%u"), configvalue); + setoutstr(str); + (void)arg1; + (void)arg2; +} +static void np2sysp_getmpos(const void* arg1, long arg2) +{ + OEMCHAR str[16] = { 0 }; + int mouseX, mouseY; + UINT8 mode = (np2sysp.outval >> 24) & 0xff; // 今は未使用 + + if (mode == 0 || mode == 1 || mode == 2 || mode == 3) + { +#if defined(NP2_WIN) + if (mousemng_getabspos(&mouseX, &mouseY)) +#else + if (0) +#endif + { + if (mouseX < 0) mouseX = 0; + if (mouseX > 65535) mouseX = 65535; + if (mouseY < 0) mouseY = 0; + if (mouseY > 65535) mouseY = 65535; + + if (mode == 1) + { + // Win3.1向け 強制レジスタ書き換えモード + CPU_DI |= 0x8000; // 絶対座標モード 本当はAXレジスタだが触れないのでDIで + CPU_BX = mouseX; // X座標 + CPU_CX = mouseY; // Y座標 + OEMSPRINTF(str, OEMTEXT("OK")); + } + else if (mode == 2) + { + // 一般向け 強制レジスタ書き換えモード + CPU_BX = mouseX; // X座標 + CPU_CX = mouseY; // Y座標 + CPU_FLAG |= C_FLAG; // 成功ならC_FLAGを立てる + OEMSPRINTF(str, OEMTEXT("OK")); + } + else if (mode == 3) + { + // 一般向け 強制レジスタ書き換えモード ボタンも取得 + SINT16 x, y; + UINT8 btn = mousemng_getstat(&x, &y, 0); + CPU_BX = mouseX; // X座標 + CPU_CX = mouseY; // Y座標 + CPU_DI = btn; // ボタンの状態 + CPU_FLAG |= C_FLAG; // 成功ならC_FLAGを立てる + OEMSPRINTF(str, OEMTEXT("OK")); + } + else + { + OEMSPRINTF(str, OEMTEXT("%d,%d"), mouseX, mouseY); + } + setoutstr(str); + } + else + { + if (mode == 2 || mode == 3) + { + // 一般向け 強制レジスタ書き換えモード + CPU_FLAG &= ~C_FLAG; // 失敗ならC_FLAGを消す + } + setoutstr(str); // 空文字列(エラー) + } + } + else if (mode == 4 || mode == 5) + { + // 一般向け 強制レジスタ書き換えモード 相対座標とボタンの取得 + SINT16 x, y; + UINT8 btn = mousemng_getstat(&x, &y, mode == 5 ? 1 : 0); // モード5は取得した座標をクリアする + CPU_BX = x; // X座標 + CPU_CX = y; // Y座標 + CPU_DI = btn; // ボタンの状態 + CPU_FLAG |= C_FLAG; // 成功ならC_FLAGを立てる + OEMSPRINTF(str, OEMTEXT("OK")); + } + else + { + setoutstr(str); // 空文字列(エラー) + } + (void)arg1; + (void)arg2; +} + + +// ---- + +static const char cmd_np2[] = "NP2"; +static const OEMCHAR rep_np2[] = OEMTEXT("NP2"); + +static const char cmd_ver[] = "ver"; +static const char cmd_poweroff[] = "poweroff"; +static const char cmd_credit[] = "credit"; +static const char cmd_cpu[] = "cpu"; +static const char cmd_clock[] = "clock"; +static const char cmd_multiple[] = "multiple"; +static const char cmd_hwreset[] = "hardwarereset"; +#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) +static const char cmd_sasibios[] = "sasibios"; +#endif +#if defined(SUPPORT_SCSI) +static const char cmd_scsibios[] = "scsibios"; +static const char cmd_scsidev[] = "scsi_dev"; +#endif +#if defined(SUPPORT_HOSTDRV) +static const char cmd_hdrvcheck[] = "check_hostdrv"; +static const char cmd_hdrvopen[] = "open_hostdrv"; +static const char cmd_hdrvclose[] = "close_hostdrv"; +static const char cmd_hdrvintr[] = "intr_hostdrv"; +static const char cmd_hdrvsetn[] = "setn_hostdrv"; // Set new protocol np21w ver0.86 rev95 +static const OEMCHAR rep_hdrvcheck[] = OEMTEXT("0.74"); +#endif + +// np21/w extensions +static const char cmd_cngclkmul[] = "changeclockmul"; // np21w ver0.86 rev44 +static const char cmd_cngconfig[] = "changeconfig"; // np21w ver0.86 rev44 +static const char cmd_getconfig[] = "getconfig"; // np21w ver0.86 rev44 +static const char cmd_getmpos[] = "getmpos"; // np21w ver0.86 rev94 + +#if defined(NP2SYSP_VER) +static const OEMCHAR str_syspver[] = OEMTEXT(NP2SYSP_VER); +#else +#define str_syspver str_null +#endif + +#if defined(NP2SYSP_CREDIT) +static const OEMCHAR str_syspcredit[] = OEMTEXT(NP2SYSP_CREDIT); +#else +#define str_syspcredit str_null +#endif + + +static const SYSPCMD np2spcmd[] = { + {cmd_np2, np2sysp_outstr, rep_np2, 0}, + {cmd_ver, np2sysp_outstr, str_syspver, 0}, + +// version:A + {cmd_poweroff, np2sysp_poweroff, NULL, 0}, + +// version:B + {cmd_credit, np2sysp_outstr, str_syspcredit, 0}, + {cmd_cpu, np2sysp_cpu, NULL, 0}, + {cmd_clock, np2sysp_clock, NULL, 0}, + {cmd_multiple, np2sysp_multiple, NULL, 0}, + +// version:C + {cmd_hwreset, np2sysp_hwreset, NULL, 0}, + +// extension +#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) + {cmd_sasibios, np2sysp_sasi, NULL, 0}, +#endif +#if defined(SUPPORT_SCSI) + {cmd_scsibios, np2sysp_scsi, NULL, 0}, + {cmd_scsidev, np2sysp_scsidev, NULL, 0}, +#endif + +#if defined(SUPPORT_HOSTDRV) + {cmd_hdrvcheck, np2sysp_outstr, rep_hdrvcheck, 0}, + {cmd_hdrvopen, hostdrv_mount, NULL, 0}, + {cmd_hdrvclose, hostdrv_unmount, NULL, 0}, + {cmd_hdrvintr, hostdrv_intr, NULL, 0}, + {cmd_hdrvsetn, hostdrv_setn, NULL, 0}, +#endif + {cmd_cngclkmul, np2sysp_cngclkmul, NULL, 0}, + {cmd_getconfig, np2sysp_getconfig, NULL, 0}, + {cmd_cngconfig, np2sysp_cngconfig, NULL, 0}, + {cmd_getmpos, np2sysp_getmpos, NULL, 0}, +}; + + +static BRESULT np2syspcmp(const char *p) { + + int len; + int pos; + + len = (int)STRLEN(p); + if (!len) { + return(FAILURE); + } + pos = np2sysp.strpos; + while(len--) { + if (p[len] != np2sysp.substr[pos]) { + return(FAILURE); + } + pos--; + pos &= NP2SYSP_MASK; + } + return(SUCCESS); +} + +static void IOOUTCALL np2sysp_o7ed(UINT port, REG8 dat) { + + np2sysp.outval = (dat << 24) | (np2sysp.outval >> 8); + (void)port; +} + +static void IOOUTCALL np2sysp_o7ef(UINT port, REG8 dat) { + +const SYSPCMD *cmd; +const SYSPCMD *cmdterm; + + np2sysp.substr[np2sysp.strpos] = (char)dat; + cmd = np2spcmd; + cmdterm = cmd + NELEMENTS(np2spcmd); + while(cmd < cmdterm) { + if (!np2syspcmp(cmd->key)) { + cmd->func(cmd->arg1, cmd->arg2); + break; + } + cmd++; + } + np2sysp.strpos++; + np2sysp.strpos &= NP2SYSP_MASK; + (void)port; +} + +static REG8 IOINPCALL np2sysp_i7ed(UINT port) { + + REG8 ret; + + ret = (REG8)(np2sysp.inpval & 0xff); + np2sysp.inpval = (ret << 24) | (np2sysp.inpval >> 8); + (void)port; + return(ret); +} + +static REG8 IOINPCALL np2sysp_i7ef(UINT port) { + + REG8 ret; + + ret = (UINT8)np2sysp.outstr[np2sysp.outpos]; + if (ret) { + np2sysp.outpos++; + np2sysp.outpos &= NP2SYSP_MASK; + } + (void)port; + return(ret); +} + +#if defined(NP2APPDEV) +static void IOOUTCALL np2sysp_o0e9(UINT port, REG8 dat) { + + APPDEVOUT(dat); + (void)port; +} + +static REG8 IOINPCALL np2sysp_i0e9(UINT port) { + + return((UINT8)port); +} +#endif + + +// ---- I/F + +void np2sysp_reset(const NP2CFG *pConfig) { + + ZeroMemory(&np2sysp, sizeof(np2sysp)); + + (void)pConfig; +} + +void np2sysp_bind(void) { + + iocore_attachout(0x07ed, np2sysp_o7ed); + iocore_attachout(0x07ef, np2sysp_o7ef); + iocore_attachinp(0x07ed, np2sysp_i7ed); + iocore_attachinp(0x07ef, np2sysp_i7ef); + +#if defined(NP2APPDEV) + iocore_attachout(0x00e9, np2sysp_o0e9); + iocore_attachinp(0x00e9, np2sysp_i0e9); +#endif +} + +#pragma code_seg() diff --git a/io/np2sysp.h b/io/np2sysp.h old mode 100755 new mode 100644 index 6a9e5501..6328fa5f --- a/io/np2sysp.h +++ b/io/np2sysp.h @@ -1,28 +1,28 @@ - -#define NP2SYSP_BIT 4 -#define NP2SYSP_LEN (1 << NP2SYSP_BIT) -#define NP2SYSP_MASK (NP2SYSP_LEN - 1) - -typedef struct { - char substr[NP2SYSP_LEN]; - char outstr[NP2SYSP_LEN]; - int strpos; - int outpos; - UINT32 outval; - UINT32 inpval; -} _NP2SYSP, *NP2SYSP; - - -#ifdef __cplusplus -extern "C" { -#endif - -void np2sysp_outstr(const void *arg1, long arg2); - -void np2sysp_reset(const NP2CFG *pConfig); -void np2sysp_bind(void); - -#ifdef __cplusplus -} -#endif - + +#define NP2SYSP_BIT 4 +#define NP2SYSP_LEN (1 << NP2SYSP_BIT) +#define NP2SYSP_MASK (NP2SYSP_LEN - 1) + +typedef struct { + char substr[NP2SYSP_LEN]; + char outstr[NP2SYSP_LEN]; + int strpos; + int outpos; + UINT32 outval; + UINT32 inpval; +} _NP2SYSP, *NP2SYSP; + + +#ifdef __cplusplus +extern "C" { +#endif + +void np2sysp_outstr(const void *arg1, long arg2); + +void np2sysp_reset(const NP2CFG *pConfig); +void np2sysp_bind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/pci/98graphbridge.c b/io/pci/98graphbridge.c old mode 100755 new mode 100644 index 24b9a8e9..56624879 --- a/io/pci/98graphbridge.c +++ b/io/pci/98graphbridge.c @@ -1,83 +1,83 @@ - -// PC-9821 PCI-CBusブリッジ - -#include - -#if defined(SUPPORT_PC9821) - -#include -#include -#include - -#if defined(SUPPORT_PCI) - -#include "98graphbridge.h" - -#define GETCFGREG_B(reg, ofs) PCI_GETCFGREG_B(reg, ofs) -#define GETCFGREG_W(reg, ofs) PCI_GETCFGREG_W(reg, ofs) -#define GETCFGREG_D(reg, ofs) PCI_GETCFGREG_D(reg, ofs) - -#define SETCFGREG_B(reg, ofs, value) PCI_SETCFGREG_B(reg, ofs, value) -#define SETCFGREG_W(reg, ofs, value) PCI_SETCFGREG_W(reg, ofs, value) -#define SETCFGREG_D(reg, ofs, value) PCI_SETCFGREG_D(reg, ofs, value) - -#define SETCFGREG_B_MASK(reg, ofs, value, mask) PCI_SETCFGREG_B_MASK(reg, ofs, value, mask) -#define SETCFGREG_W_MASK(reg, ofs, value, mask) PCI_SETCFGREG_W_MASK(reg, ofs, value, mask) -#define SETCFGREG_D_MASK(reg, ofs, value, mask) PCI_SETCFGREG_D_MASK(reg, ofs, value, mask) - -int pcidev_98graphbridge_deviceid = 7; - -void pcidev_98graphbridge_cfgreg_w(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value){ - -} - -void pcidev_98graphbridge_reset(const NP2CFG *pConfig) { - - (void)pConfig; -} - -void pcidev_98graphbridge_bind(void) { - - int devid = pcidev_98graphbridge_deviceid; - - // 98グラフィックバスブリッジ - ZeroMemory(pcidev.devices+devid, sizeof(_PCIDEVICE)); - pcidev.devices[devid].enable = 1; - pcidev.devices[devid].skipirqtbl = 1; - pcidev.devices[devid].regwfn = &pcidev_98graphbridge_cfgreg_w; - pcidev.devices[devid].header.vendorID = 0x1033; - pcidev.devices[devid].header.deviceID = 0x0009; - pcidev.devices[devid].header.command = 0x0003;//0x0006;//0x0003; - pcidev.devices[devid].header.status = 0x0280;//0x0000;//0x0280; - pcidev.devices[devid].header.revisionID = 0x01; - pcidev.devices[devid].header.classcode[0] = 0x00; // レジスタレベルプログラミングインタフェース - pcidev.devices[devid].header.classcode[1] = 0x80; // サブクラスコード - pcidev.devices[devid].header.classcode[2] = 0x03; // ベースクラスコード - pcidev.devices[devid].header.cachelinesize = 0; - pcidev.devices[devid].header.latencytimer = 0x0; - pcidev.devices[devid].header.headertype = 0; - pcidev.devices[devid].header.BIST = 0x00; - pcidev.devices[devid].header.interruptline = 0x00; - pcidev.devices[devid].header.interruptpin = 0x00; - - // ROM領域設定 - pcidev.devices[devid].headerrom.vendorID = 0xffff; - pcidev.devices[devid].headerrom.deviceID = 0xffff; - pcidev.devices[devid].headerrom.status = 0xffff; - pcidev.devices[devid].headerrom.revisionID = 0xff; - pcidev.devices[devid].headerrom.classcode[0] = 0xff; - pcidev.devices[devid].headerrom.classcode[1] = 0xff; - pcidev.devices[devid].headerrom.classcode[2] = 0xff; - pcidev.devices[devid].headerrom.baseaddrregs[0] = 0xffffffff; - pcidev.devices[devid].headerrom.baseaddrregs[1] = 0xffffffff; - pcidev.devices[devid].headerrom.baseaddrregs[2] = 0xffffffff; - pcidev.devices[devid].headerrom.baseaddrregs[3] = 0xffffffff; - pcidev.devices[devid].headerrom.baseaddrregs[4] = 0xffffffff; - pcidev.devices[devid].headerrom.baseaddrregs[5] = 0xffffffff; - pcidev.devices[devid].headerrom.expROMbaseaddr = 0xffffffff; - memset(&(pcidev.devices[devid].headerrom), 0xff, sizeof(_PCICSH)); -} - -#endif -#endif - + +// PC-9821 PCI-CBusブリッジ + +#include + +#if defined(SUPPORT_PC9821) + +#include +#include +#include + +#if defined(SUPPORT_PCI) + +#include "98graphbridge.h" + +#define GETCFGREG_B(reg, ofs) PCI_GETCFGREG_B(reg, ofs) +#define GETCFGREG_W(reg, ofs) PCI_GETCFGREG_W(reg, ofs) +#define GETCFGREG_D(reg, ofs) PCI_GETCFGREG_D(reg, ofs) + +#define SETCFGREG_B(reg, ofs, value) PCI_SETCFGREG_B(reg, ofs, value) +#define SETCFGREG_W(reg, ofs, value) PCI_SETCFGREG_W(reg, ofs, value) +#define SETCFGREG_D(reg, ofs, value) PCI_SETCFGREG_D(reg, ofs, value) + +#define SETCFGREG_B_MASK(reg, ofs, value, mask) PCI_SETCFGREG_B_MASK(reg, ofs, value, mask) +#define SETCFGREG_W_MASK(reg, ofs, value, mask) PCI_SETCFGREG_W_MASK(reg, ofs, value, mask) +#define SETCFGREG_D_MASK(reg, ofs, value, mask) PCI_SETCFGREG_D_MASK(reg, ofs, value, mask) + +int pcidev_98graphbridge_deviceid = 7; + +void pcidev_98graphbridge_cfgreg_w(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value){ + +} + +void pcidev_98graphbridge_reset(const NP2CFG *pConfig) { + + (void)pConfig; +} + +void pcidev_98graphbridge_bind(void) { + + int devid = pcidev_98graphbridge_deviceid; + + // 98グラフィックバスブリッジ + ZeroMemory(pcidev.devices+devid, sizeof(_PCIDEVICE)); + pcidev.devices[devid].enable = 1; + pcidev.devices[devid].skipirqtbl = 1; + pcidev.devices[devid].regwfn = &pcidev_98graphbridge_cfgreg_w; + pcidev.devices[devid].header.vendorID = 0x1033; + pcidev.devices[devid].header.deviceID = 0x0009; + pcidev.devices[devid].header.command = 0x0003;//0x0006;//0x0003; + pcidev.devices[devid].header.status = 0x0280;//0x0000;//0x0280; + pcidev.devices[devid].header.revisionID = 0x01; + pcidev.devices[devid].header.classcode[0] = 0x00; // レジスタレベルプログラミングインタフェース + pcidev.devices[devid].header.classcode[1] = 0x80; // サブクラスコード + pcidev.devices[devid].header.classcode[2] = 0x03; // ベースクラスコード + pcidev.devices[devid].header.cachelinesize = 0; + pcidev.devices[devid].header.latencytimer = 0x0; + pcidev.devices[devid].header.headertype = 0; + pcidev.devices[devid].header.BIST = 0x00; + pcidev.devices[devid].header.interruptline = 0x00; + pcidev.devices[devid].header.interruptpin = 0x00; + + // ROM領域設定 + pcidev.devices[devid].headerrom.vendorID = 0xffff; + pcidev.devices[devid].headerrom.deviceID = 0xffff; + pcidev.devices[devid].headerrom.status = 0xffff; + pcidev.devices[devid].headerrom.revisionID = 0xff; + pcidev.devices[devid].headerrom.classcode[0] = 0xff; + pcidev.devices[devid].headerrom.classcode[1] = 0xff; + pcidev.devices[devid].headerrom.classcode[2] = 0xff; + pcidev.devices[devid].headerrom.baseaddrregs[0] = 0xffffffff; + pcidev.devices[devid].headerrom.baseaddrregs[1] = 0xffffffff; + pcidev.devices[devid].headerrom.baseaddrregs[2] = 0xffffffff; + pcidev.devices[devid].headerrom.baseaddrregs[3] = 0xffffffff; + pcidev.devices[devid].headerrom.baseaddrregs[4] = 0xffffffff; + pcidev.devices[devid].headerrom.baseaddrregs[5] = 0xffffffff; + pcidev.devices[devid].headerrom.expROMbaseaddr = 0xffffffff; + memset(&(pcidev.devices[devid].headerrom), 0xff, sizeof(_PCICSH)); +} + +#endif +#endif + diff --git a/io/pci/98graphbridge.h b/io/pci/98graphbridge.h old mode 100755 new mode 100644 index 9eb92ef8..17382001 --- a/io/pci/98graphbridge.h +++ b/io/pci/98graphbridge.h @@ -1,22 +1,22 @@ - -// PC-9821 PCI-CBusブリッジ - -#if defined(SUPPORT_PC9821) -#if defined(SUPPORT_PCI) - -#ifdef __cplusplus -extern "C" { -#endif - -extern int pcidev_98graphbridge_deviceid; - -void pcidev_98graphbridge_reset(const NP2CFG *pConfig); -void pcidev_98graphbridge_bind(void); - -#ifdef __cplusplus -} -#endif - -#endif -#endif - + +// PC-9821 PCI-CBusブリッジ + +#if defined(SUPPORT_PC9821) +#if defined(SUPPORT_PCI) + +#ifdef __cplusplus +extern "C" { +#endif + +extern int pcidev_98graphbridge_deviceid; + +void pcidev_98graphbridge_reset(const NP2CFG *pConfig); +void pcidev_98graphbridge_bind(void); + +#ifdef __cplusplus +} +#endif + +#endif +#endif + diff --git a/io/pci/cbusbridge.c b/io/pci/cbusbridge.c old mode 100755 new mode 100644 index 8d9bfeae..8d16f7fc --- a/io/pci/cbusbridge.c +++ b/io/pci/cbusbridge.c @@ -1,199 +1,199 @@ - -// PC-9821 PCI-CBusブリッジ - -#include - -#if defined(SUPPORT_PC9821) - -#include -#include -#include - -#if defined(SUPPORT_PCI) - -#include "cbusbridge.h" - -#define GETCFGREG_B(reg, ofs) PCI_GETCFGREG_B(reg, ofs) -#define GETCFGREG_W(reg, ofs) PCI_GETCFGREG_W(reg, ofs) -#define GETCFGREG_D(reg, ofs) PCI_GETCFGREG_D(reg, ofs) - -#define SETCFGREG_B(reg, ofs, value) PCI_SETCFGREG_B(reg, ofs, value) -#define SETCFGREG_W(reg, ofs, value) PCI_SETCFGREG_W(reg, ofs, value) -#define SETCFGREG_D(reg, ofs, value) PCI_SETCFGREG_D(reg, ofs, value) - -#define SETCFGREG_B_MASK(reg, ofs, value, mask) PCI_SETCFGREG_B_MASK(reg, ofs, value, mask) -#define SETCFGREG_W_MASK(reg, ofs, value, mask) PCI_SETCFGREG_W_MASK(reg, ofs, value, mask) -#define SETCFGREG_D_MASK(reg, ofs, value, mask) PCI_SETCFGREG_D_MASK(reg, ofs, value, mask) - -int pcidev_cbusbridge_deviceid = 6; - -void pcidev_cbusbridge_cfgreg_w(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value){ - -} - -void pcidev_cbusbridge_reset(const NP2CFG *pConfig) { - - (void)pConfig; -} - -void pcidev_cbusbridge_bind(void) { - int devid = pcidev_cbusbridge_deviceid; - - // PCI-Cバスブリッジ - ZeroMemory(pcidev.devices+devid, sizeof(_PCIDEVICE)); - pcidev.devices[devid].enable = 1; - pcidev.devices[devid].skipirqtbl = 1; - pcidev.devices[devid].regwfn = &pcidev_cbusbridge_cfgreg_w; - pcidev.devices[devid].header.vendorID = 0x1033; - pcidev.devices[devid].header.deviceID = 0x0001; - pcidev.devices[devid].header.command = 0x010f;//0x010f;//0x0107; - pcidev.devices[devid].header.status = 0x0200;//0x0200;//0x0400; - pcidev.devices[devid].header.revisionID = 0x01;//0x03; - pcidev.devices[devid].header.classcode[0] = 0x00; // レジスタレベルプログラミングインタフェース - pcidev.devices[devid].header.classcode[1] = 0x80; // サブクラスコード - pcidev.devices[devid].header.classcode[2] = 0x06; // ベースクラスコード - pcidev.devices[devid].header.cachelinesize = 0; - pcidev.devices[devid].header.latencytimer = 0x0; - pcidev.devices[devid].header.headertype = 0; - pcidev.devices[devid].header.BIST = 0x00; - pcidev.devices[devid].header.interruptline = 0x00; - pcidev.devices[devid].header.interruptpin = 0x01; - pcidev.devices[devid].cfgreg8[0x40] = 0x10; - pcidev.devices[devid].cfgreg8[0x41] = 0x00; - pcidev.devices[devid].cfgreg8[0x42] = 0xEF; - pcidev.devices[devid].cfgreg8[0x43] = 0x00; - pcidev.devices[devid].cfgreg8[0x44] = 0xFA; - pcidev.devices[devid].cfgreg8[0x45] = 0xff; - pcidev.devices[devid].cfgreg8[0x46] = 0xfb; - pcidev.devices[devid].cfgreg8[0x47] = 0xff; - pcidev.devices[devid].cfgreg8[0x48] = 0xFE; - pcidev.devices[devid].cfgreg8[0x49] = 0xFF; - pcidev.devices[devid].cfgreg8[0x4A] = 0xFE; - pcidev.devices[devid].cfgreg8[0x4B] = 0xFF; - pcidev.devices[devid].cfgreg8[0x4C] = 0xFF; - pcidev.devices[devid].cfgreg8[0x4D] = 0xFF; - pcidev.devices[devid].cfgreg8[0x4E] = 0x00; - pcidev.devices[devid].cfgreg8[0x4F] = 0x00; - //pcidev.devices[devid].cfgreg8[0x40] = 0x00; - //pcidev.devices[devid].cfgreg8[0x41] = 0x10; - //pcidev.devices[devid].cfgreg8[0x42] = 0x00; - //pcidev.devices[devid].cfgreg8[0x43] = 0xff; - //pcidev.devices[devid].cfgreg8[0x44] = 0x00; - //pcidev.devices[devid].cfgreg8[0x45] = 0xff; - //pcidev.devices[devid].cfgreg8[0x46] = 0xff; - //pcidev.devices[devid].cfgreg8[0x47] = 0xff; - //pcidev.devices[devid].cfgreg8[0x48] = 0x3f; - //pcidev.devices[devid].cfgreg8[0x4C] = 0x3e; - //pcidev.devices[devid].cfgreg8[0x4E] = 0x03; - pcidev.devices[devid].cfgreg8[0x50] = 0; - pcidev.devices[devid].cfgreg8[0x51] = 1; - pcidev.devices[devid].cfgreg8[0x52] = 2; - pcidev.devices[devid].cfgreg8[0x59] = 9; - pcidev.devices[devid].cfgreg8[0x5a] = 10; - pcidev.devices[devid].cfgreg8[0x5b] = 11; - pcidev.devices[devid].cfgreg8[0x5d] = 13; - //SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x50, 0x00EF0010); - //SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x54, 0xFFFBFFFA); - //SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x58, 0xFFFEFFFE); - //SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x5C, 0x0000FFFF); - pcidev.devices[devid].cfgreg8[0x60] = 0x03;//0x80;//0x03; - pcidev.devices[devid].cfgreg8[0x61] = 0x05;//0x80;//0x05; - pcidev.devices[devid].cfgreg8[0x62] = 0x06;//0x80;//0x06; - pcidev.devices[devid].cfgreg8[0x63] = 0x0c;//0x80;//0x0c; - - //// PCI-Cバスブリッジ(違うバージョン) - //ZeroMemory(pcidev.devices+devid, sizeof(_PCIDEVICE)); - //pcidev.devices[devid].enable = 1; - //pcidev.devices[devid].regwfn = &pcidev_cbusbridge_cfgreg_w; - //pcidev.devices[devid].header.vendorID = 0x1033; - //pcidev.devices[devid].header.deviceID = 0x0001; - //pcidev.devices[devid].header.command = 0x010f;//0x0107; - //pcidev.devices[devid].header.status = 0x0200;//0x0400; - //pcidev.devices[devid].header.revisionID = 0x00;//0x03; - //pcidev.devices[devid].header.classcode[0] = 0x00; // レジスタレベルプログラミングインタフェース - //pcidev.devices[devid].header.classcode[1] = 0x80; // サブクラスコード - //pcidev.devices[devid].header.classcode[2] = 0x06; // ベースクラスコード - //pcidev.devices[devid].header.cachelinesize = 0; - //pcidev.devices[devid].header.latencytimer = 0x0; - //pcidev.devices[devid].header.headertype = 0; - //pcidev.devices[devid].header.BIST = 0x00; - //pcidev.devices[devid].header.interruptline = 0x00; - //pcidev.devices[devid].header.interruptpin = 0x00; - //pcidev.devices[devid].cfgreg8[0x40] = 0x10; - //pcidev.devices[devid].cfgreg8[0x41] = 0x00; - //pcidev.devices[devid].cfgreg8[0x42] = 0xEF; - //pcidev.devices[devid].cfgreg8[0x43] = 0x00; - //pcidev.devices[devid].cfgreg8[0x44] = 0xFA; - //pcidev.devices[devid].cfgreg8[0x45] = 0xff; - //pcidev.devices[devid].cfgreg8[0x46] = 0xfb; - //pcidev.devices[devid].cfgreg8[0x47] = 0xff; - //pcidev.devices[devid].cfgreg8[0x48] = 0xFE; - //pcidev.devices[devid].cfgreg8[0x49] = 0xFF; - //pcidev.devices[devid].cfgreg8[0x4A] = 0xFE; - //pcidev.devices[devid].cfgreg8[0x4B] = 0xFF; - //pcidev.devices[devid].cfgreg8[0x4C] = 0xFF; - //pcidev.devices[devid].cfgreg8[0x4D] = 0xFF; - //pcidev.devices[devid].cfgreg8[0x4E] = 0x00; - //pcidev.devices[devid].cfgreg8[0x4F] = 0x00; - //pcidev.devices[devid].cfgreg8[0x50] = 0x00; - //pcidev.devices[devid].cfgreg8[0x51] = 0x01; - //pcidev.devices[devid].cfgreg8[0x52] = 0x02; - //pcidev.devices[devid].cfgreg8[0x53] = 0x0F; - //pcidev.devices[devid].cfgreg8[0x54] = 0x04; - //pcidev.devices[devid].cfgreg8[0x55] = 0x05; - //pcidev.devices[devid].cfgreg8[0x56] = 0x86; - //pcidev.devices[devid].cfgreg8[0x57] = 0x07; - //pcidev.devices[devid].cfgreg8[0x58] = 0x08; - //pcidev.devices[devid].cfgreg8[0x59] = 0x09; - //pcidev.devices[devid].cfgreg8[0x5A] = 0x0A; - //pcidev.devices[devid].cfgreg8[0x5B] = 0x0B; - //pcidev.devices[devid].cfgreg8[0x5C] = 0x8C; - //pcidev.devices[devid].cfgreg8[0x5D] = 0x0D; - //pcidev.devices[devid].cfgreg8[0x5E] = 0x0E; - //pcidev.devices[devid].cfgreg8[0x5F] = 0x8F; - ////pcidev.devices[devid].cfgreg8[0x59] = 9; - ////pcidev.devices[devid].cfgreg8[0x5a] = 10; - ////pcidev.devices[devid].cfgreg8[0x5b] = 11; - ////pcidev.devices[devid].cfgreg8[0x5d] = 13; - ////SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x50, 0x00EF0010); - ////SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x54, 0xFFFBFFFA); - ////SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x58, 0xFFFEFFFE); - ////SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x5C, 0x0000FFFF); - ////pcidev.devices[devid].cfgreg8[0x60] = 0x03;//0x80;//0x03; - ////pcidev.devices[devid].cfgreg8[0x61] = 0x05;//0x80;//0x05; - ////pcidev.devices[devid].cfgreg8[0x62] = 0x06;//0x80;//0x06; - ////pcidev.devices[devid].cfgreg8[0x63] = 0x80;//0x0c;//0x80;//0x0c; - //pcidev.devices[devid].cfgreg8[0x60] = 0x0A;//0x80;//0x03; - //pcidev.devices[devid].cfgreg8[0x61] = 0x0A;//0x80;//0x05; - //pcidev.devices[devid].cfgreg8[0x62] = 0x0A;//0x80;//0x06; - //pcidev.devices[devid].cfgreg8[0x63] = 0x0A;//0x0c;//0x80;//0x0c; - //pcidev.devices[devid].cfgreg8[0x64] = 0x10; - //pcidev.devices[devid].cfgreg8[0x65] = 0x3F; - //pcidev.devices[devid].cfgreg8[0x66] = 0x07; - //pcidev.devices[devid].cfgreg8[0x67] = 0x18; - //pcidev.devices[devid].cfgreg8[0x68] = 0x32; - //pcidev.devices[devid].cfgreg8[0x69] = 0x01; - //pcidev.devices[devid].cfgreg8[0x6A] = 0x00; - //pcidev.devices[devid].cfgreg8[0x6B] = 0x0D; - - // ROM領域設定 - pcidev.devices[devid].headerrom.vendorID = 0xffff; - pcidev.devices[devid].headerrom.deviceID = 0xffff; - pcidev.devices[devid].headerrom.status = 0xffff; - pcidev.devices[devid].headerrom.revisionID = 0xff; - pcidev.devices[devid].headerrom.classcode[0] = 0xff; - pcidev.devices[devid].headerrom.classcode[1] = 0xff; - pcidev.devices[devid].headerrom.classcode[2] = 0xff; - pcidev.devices[devid].headerrom.baseaddrregs[0] = 0xffffffff; - pcidev.devices[devid].headerrom.baseaddrregs[1] = 0xffffffff; - pcidev.devices[devid].headerrom.baseaddrregs[2] = 0xffffffff; - pcidev.devices[devid].headerrom.baseaddrregs[3] = 0xffffffff; - pcidev.devices[devid].headerrom.baseaddrregs[4] = 0xffffffff; - pcidev.devices[devid].headerrom.baseaddrregs[5] = 0xffffffff; - pcidev.devices[devid].headerrom.expROMbaseaddr = 0xffffffff; - memset(&(pcidev.devices[devid].headerrom), 0xff, sizeof(_PCICSH)); -} - -#endif -#endif - + +// PC-9821 PCI-CBusブリッジ + +#include + +#if defined(SUPPORT_PC9821) + +#include +#include +#include + +#if defined(SUPPORT_PCI) + +#include "cbusbridge.h" + +#define GETCFGREG_B(reg, ofs) PCI_GETCFGREG_B(reg, ofs) +#define GETCFGREG_W(reg, ofs) PCI_GETCFGREG_W(reg, ofs) +#define GETCFGREG_D(reg, ofs) PCI_GETCFGREG_D(reg, ofs) + +#define SETCFGREG_B(reg, ofs, value) PCI_SETCFGREG_B(reg, ofs, value) +#define SETCFGREG_W(reg, ofs, value) PCI_SETCFGREG_W(reg, ofs, value) +#define SETCFGREG_D(reg, ofs, value) PCI_SETCFGREG_D(reg, ofs, value) + +#define SETCFGREG_B_MASK(reg, ofs, value, mask) PCI_SETCFGREG_B_MASK(reg, ofs, value, mask) +#define SETCFGREG_W_MASK(reg, ofs, value, mask) PCI_SETCFGREG_W_MASK(reg, ofs, value, mask) +#define SETCFGREG_D_MASK(reg, ofs, value, mask) PCI_SETCFGREG_D_MASK(reg, ofs, value, mask) + +int pcidev_cbusbridge_deviceid = 6; + +void pcidev_cbusbridge_cfgreg_w(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value){ + +} + +void pcidev_cbusbridge_reset(const NP2CFG *pConfig) { + + (void)pConfig; +} + +void pcidev_cbusbridge_bind(void) { + int devid = pcidev_cbusbridge_deviceid; + + // PCI-Cバスブリッジ + ZeroMemory(pcidev.devices+devid, sizeof(_PCIDEVICE)); + pcidev.devices[devid].enable = 1; + pcidev.devices[devid].skipirqtbl = 1; + pcidev.devices[devid].regwfn = &pcidev_cbusbridge_cfgreg_w; + pcidev.devices[devid].header.vendorID = 0x1033; + pcidev.devices[devid].header.deviceID = 0x0001; + pcidev.devices[devid].header.command = 0x010f;//0x010f;//0x0107; + pcidev.devices[devid].header.status = 0x0200;//0x0200;//0x0400; + pcidev.devices[devid].header.revisionID = 0x01;//0x03; + pcidev.devices[devid].header.classcode[0] = 0x00; // レジスタレベルプログラミングインタフェース + pcidev.devices[devid].header.classcode[1] = 0x80; // サブクラスコード + pcidev.devices[devid].header.classcode[2] = 0x06; // ベースクラスコード + pcidev.devices[devid].header.cachelinesize = 0; + pcidev.devices[devid].header.latencytimer = 0x0; + pcidev.devices[devid].header.headertype = 0; + pcidev.devices[devid].header.BIST = 0x00; + pcidev.devices[devid].header.interruptline = 0x00; + pcidev.devices[devid].header.interruptpin = 0x01; + pcidev.devices[devid].cfgreg8[0x40] = 0x10; + pcidev.devices[devid].cfgreg8[0x41] = 0x00; + pcidev.devices[devid].cfgreg8[0x42] = 0xEF; + pcidev.devices[devid].cfgreg8[0x43] = 0x00; + pcidev.devices[devid].cfgreg8[0x44] = 0xFA; + pcidev.devices[devid].cfgreg8[0x45] = 0xff; + pcidev.devices[devid].cfgreg8[0x46] = 0xfb; + pcidev.devices[devid].cfgreg8[0x47] = 0xff; + pcidev.devices[devid].cfgreg8[0x48] = 0xFE; + pcidev.devices[devid].cfgreg8[0x49] = 0xFF; + pcidev.devices[devid].cfgreg8[0x4A] = 0xFE; + pcidev.devices[devid].cfgreg8[0x4B] = 0xFF; + pcidev.devices[devid].cfgreg8[0x4C] = 0xFF; + pcidev.devices[devid].cfgreg8[0x4D] = 0xFF; + pcidev.devices[devid].cfgreg8[0x4E] = 0x00; + pcidev.devices[devid].cfgreg8[0x4F] = 0x00; + //pcidev.devices[devid].cfgreg8[0x40] = 0x00; + //pcidev.devices[devid].cfgreg8[0x41] = 0x10; + //pcidev.devices[devid].cfgreg8[0x42] = 0x00; + //pcidev.devices[devid].cfgreg8[0x43] = 0xff; + //pcidev.devices[devid].cfgreg8[0x44] = 0x00; + //pcidev.devices[devid].cfgreg8[0x45] = 0xff; + //pcidev.devices[devid].cfgreg8[0x46] = 0xff; + //pcidev.devices[devid].cfgreg8[0x47] = 0xff; + //pcidev.devices[devid].cfgreg8[0x48] = 0x3f; + //pcidev.devices[devid].cfgreg8[0x4C] = 0x3e; + //pcidev.devices[devid].cfgreg8[0x4E] = 0x03; + pcidev.devices[devid].cfgreg8[0x50] = 0; + pcidev.devices[devid].cfgreg8[0x51] = 1; + pcidev.devices[devid].cfgreg8[0x52] = 2; + pcidev.devices[devid].cfgreg8[0x59] = 9; + pcidev.devices[devid].cfgreg8[0x5a] = 10; + pcidev.devices[devid].cfgreg8[0x5b] = 11; + pcidev.devices[devid].cfgreg8[0x5d] = 13; + //SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x50, 0x00EF0010); + //SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x54, 0xFFFBFFFA); + //SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x58, 0xFFFEFFFE); + //SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x5C, 0x0000FFFF); + pcidev.devices[devid].cfgreg8[0x60] = 0x03;//0x80;//0x03; + pcidev.devices[devid].cfgreg8[0x61] = 0x05;//0x80;//0x05; + pcidev.devices[devid].cfgreg8[0x62] = 0x06;//0x80;//0x06; + pcidev.devices[devid].cfgreg8[0x63] = 0x0c;//0x80;//0x0c; + + //// PCI-Cバスブリッジ(違うバージョン) + //ZeroMemory(pcidev.devices+devid, sizeof(_PCIDEVICE)); + //pcidev.devices[devid].enable = 1; + //pcidev.devices[devid].regwfn = &pcidev_cbusbridge_cfgreg_w; + //pcidev.devices[devid].header.vendorID = 0x1033; + //pcidev.devices[devid].header.deviceID = 0x0001; + //pcidev.devices[devid].header.command = 0x010f;//0x0107; + //pcidev.devices[devid].header.status = 0x0200;//0x0400; + //pcidev.devices[devid].header.revisionID = 0x00;//0x03; + //pcidev.devices[devid].header.classcode[0] = 0x00; // レジスタレベルプログラミングインタフェース + //pcidev.devices[devid].header.classcode[1] = 0x80; // サブクラスコード + //pcidev.devices[devid].header.classcode[2] = 0x06; // ベースクラスコード + //pcidev.devices[devid].header.cachelinesize = 0; + //pcidev.devices[devid].header.latencytimer = 0x0; + //pcidev.devices[devid].header.headertype = 0; + //pcidev.devices[devid].header.BIST = 0x00; + //pcidev.devices[devid].header.interruptline = 0x00; + //pcidev.devices[devid].header.interruptpin = 0x00; + //pcidev.devices[devid].cfgreg8[0x40] = 0x10; + //pcidev.devices[devid].cfgreg8[0x41] = 0x00; + //pcidev.devices[devid].cfgreg8[0x42] = 0xEF; + //pcidev.devices[devid].cfgreg8[0x43] = 0x00; + //pcidev.devices[devid].cfgreg8[0x44] = 0xFA; + //pcidev.devices[devid].cfgreg8[0x45] = 0xff; + //pcidev.devices[devid].cfgreg8[0x46] = 0xfb; + //pcidev.devices[devid].cfgreg8[0x47] = 0xff; + //pcidev.devices[devid].cfgreg8[0x48] = 0xFE; + //pcidev.devices[devid].cfgreg8[0x49] = 0xFF; + //pcidev.devices[devid].cfgreg8[0x4A] = 0xFE; + //pcidev.devices[devid].cfgreg8[0x4B] = 0xFF; + //pcidev.devices[devid].cfgreg8[0x4C] = 0xFF; + //pcidev.devices[devid].cfgreg8[0x4D] = 0xFF; + //pcidev.devices[devid].cfgreg8[0x4E] = 0x00; + //pcidev.devices[devid].cfgreg8[0x4F] = 0x00; + //pcidev.devices[devid].cfgreg8[0x50] = 0x00; + //pcidev.devices[devid].cfgreg8[0x51] = 0x01; + //pcidev.devices[devid].cfgreg8[0x52] = 0x02; + //pcidev.devices[devid].cfgreg8[0x53] = 0x0F; + //pcidev.devices[devid].cfgreg8[0x54] = 0x04; + //pcidev.devices[devid].cfgreg8[0x55] = 0x05; + //pcidev.devices[devid].cfgreg8[0x56] = 0x86; + //pcidev.devices[devid].cfgreg8[0x57] = 0x07; + //pcidev.devices[devid].cfgreg8[0x58] = 0x08; + //pcidev.devices[devid].cfgreg8[0x59] = 0x09; + //pcidev.devices[devid].cfgreg8[0x5A] = 0x0A; + //pcidev.devices[devid].cfgreg8[0x5B] = 0x0B; + //pcidev.devices[devid].cfgreg8[0x5C] = 0x8C; + //pcidev.devices[devid].cfgreg8[0x5D] = 0x0D; + //pcidev.devices[devid].cfgreg8[0x5E] = 0x0E; + //pcidev.devices[devid].cfgreg8[0x5F] = 0x8F; + ////pcidev.devices[devid].cfgreg8[0x59] = 9; + ////pcidev.devices[devid].cfgreg8[0x5a] = 10; + ////pcidev.devices[devid].cfgreg8[0x5b] = 11; + ////pcidev.devices[devid].cfgreg8[0x5d] = 13; + ////SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x50, 0x00EF0010); + ////SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x54, 0xFFFBFFFA); + ////SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x58, 0xFFFEFFFE); + ////SETCFGREG_D(pcidev.devices[devid].cfgreg8, 0x5C, 0x0000FFFF); + ////pcidev.devices[devid].cfgreg8[0x60] = 0x03;//0x80;//0x03; + ////pcidev.devices[devid].cfgreg8[0x61] = 0x05;//0x80;//0x05; + ////pcidev.devices[devid].cfgreg8[0x62] = 0x06;//0x80;//0x06; + ////pcidev.devices[devid].cfgreg8[0x63] = 0x80;//0x0c;//0x80;//0x0c; + //pcidev.devices[devid].cfgreg8[0x60] = 0x0A;//0x80;//0x03; + //pcidev.devices[devid].cfgreg8[0x61] = 0x0A;//0x80;//0x05; + //pcidev.devices[devid].cfgreg8[0x62] = 0x0A;//0x80;//0x06; + //pcidev.devices[devid].cfgreg8[0x63] = 0x0A;//0x0c;//0x80;//0x0c; + //pcidev.devices[devid].cfgreg8[0x64] = 0x10; + //pcidev.devices[devid].cfgreg8[0x65] = 0x3F; + //pcidev.devices[devid].cfgreg8[0x66] = 0x07; + //pcidev.devices[devid].cfgreg8[0x67] = 0x18; + //pcidev.devices[devid].cfgreg8[0x68] = 0x32; + //pcidev.devices[devid].cfgreg8[0x69] = 0x01; + //pcidev.devices[devid].cfgreg8[0x6A] = 0x00; + //pcidev.devices[devid].cfgreg8[0x6B] = 0x0D; + + // ROM領域設定 + pcidev.devices[devid].headerrom.vendorID = 0xffff; + pcidev.devices[devid].headerrom.deviceID = 0xffff; + pcidev.devices[devid].headerrom.status = 0xffff; + pcidev.devices[devid].headerrom.revisionID = 0xff; + pcidev.devices[devid].headerrom.classcode[0] = 0xff; + pcidev.devices[devid].headerrom.classcode[1] = 0xff; + pcidev.devices[devid].headerrom.classcode[2] = 0xff; + pcidev.devices[devid].headerrom.baseaddrregs[0] = 0xffffffff; + pcidev.devices[devid].headerrom.baseaddrregs[1] = 0xffffffff; + pcidev.devices[devid].headerrom.baseaddrregs[2] = 0xffffffff; + pcidev.devices[devid].headerrom.baseaddrregs[3] = 0xffffffff; + pcidev.devices[devid].headerrom.baseaddrregs[4] = 0xffffffff; + pcidev.devices[devid].headerrom.baseaddrregs[5] = 0xffffffff; + pcidev.devices[devid].headerrom.expROMbaseaddr = 0xffffffff; + memset(&(pcidev.devices[devid].headerrom), 0xff, sizeof(_PCICSH)); +} + +#endif +#endif + diff --git a/io/pci/cbusbridge.h b/io/pci/cbusbridge.h old mode 100755 new mode 100644 index ff1ca032..63343db5 --- a/io/pci/cbusbridge.h +++ b/io/pci/cbusbridge.h @@ -1,22 +1,22 @@ - -// PC-9821 PCI-CBusブリッジ - -#if defined(SUPPORT_PC9821) -#if defined(SUPPORT_PCI) - -#ifdef __cplusplus -extern "C" { -#endif - -extern int pcidev_cbusbridge_deviceid; - -void pcidev_cbusbridge_reset(const NP2CFG *pConfig); -void pcidev_cbusbridge_bind(void); - -#ifdef __cplusplus -} -#endif - -#endif -#endif - + +// PC-9821 PCI-CBusブリッジ + +#if defined(SUPPORT_PC9821) +#if defined(SUPPORT_PCI) + +#ifdef __cplusplus +extern "C" { +#endif + +extern int pcidev_cbusbridge_deviceid; + +void pcidev_cbusbridge_reset(const NP2CFG *pConfig); +void pcidev_cbusbridge_bind(void); + +#ifdef __cplusplus +} +#endif + +#endif +#endif + diff --git a/io/pcidev.c b/io/pcidev.c old mode 100755 new mode 100644 index 5086f0f3..fe5d720d --- a/io/pcidev.c +++ b/io/pcidev.c @@ -1,789 +1,789 @@ - -// PC-9821 PCIバス - -// 現状はConfiguration Mechanism #1対応でバス番号0のみ。bios1a.cにエミュレーションPCI BIOSがあります。 - -#include - -#if defined(SUPPORT_PC9821) - -#include -#include -#include - -#if defined(SUPPORT_PCI) - -#include -#include "pci/cbusbridge.h" -#include "pci/98graphbridge.h" -#include - -#define GETCFGREG_B(reg, ofs) PCI_GETCFGREG_B(reg, ofs) -#define GETCFGREG_W(reg, ofs) PCI_GETCFGREG_W(reg, ofs) -#define GETCFGREG_D(reg, ofs) PCI_GETCFGREG_D(reg, ofs) - -#define SETCFGREG_B(reg, ofs, value) PCI_SETCFGREG_B(reg, ofs, value) -#define SETCFGREG_W(reg, ofs, value) PCI_SETCFGREG_W(reg, ofs, value) -#define SETCFGREG_D(reg, ofs, value) PCI_SETCFGREG_D(reg, ofs, value) - -#define SETCFGREG_B_MASK(reg, ofs, value, mask) PCI_SETCFGREG_B_MASK(reg, ofs, value, mask) -#define SETCFGREG_W_MASK(reg, ofs, value, mask) PCI_SETCFGREG_W_MASK(reg, ofs, value, mask) -#define SETCFGREG_D_MASK(reg, ofs, value, mask) PCI_SETCFGREG_D_MASK(reg, ofs, value, mask) - -int pcidev_pcmc_deviceid = 0; - -//UINT8 PCI_INTLINE2IRQTBL[] = { -//// INTA INTB INTC INTD -// 0, 1, 2, 3, // slot #0 -// 1, 2, 3, 0, // slot #1 -// 2, 3, 0, 1, // slot #2 -// 3, 2, 1, 0, // slot #3 -//}; - -// これはなんだろう? -static void setRAM_D000(UINT8 dat){ - //UINT8 dat = *((UINT8*)(pcidev.devices[0].cfgreg8 + 0x64)); - UINT32 work; - work = CPU_RAM_D000 & 0x03ff; - if (dat & 0x10) { - work |= 0x0400; - } - if (dat & 0x20) { - work |= 0x0800; - } - if (dat & 0x80) { - work |= 0xf000; - } - CPU_RAM_D000 = (UINT16)work; -} - - -void pcidev_pcmc_cfgreg_w(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value){ - -} - -static void IOOUTCALL pci_o0cf8(UINT port, REG8 dat) { - - pcidev.reg_cse = dat & 0xfe; -} -static void IOOUTCALL pci_o0cf9(UINT port, REG8 dat) { - - pcidev.reg_trc = dat; -} -static void IOOUTCALL pci_o0cfa(UINT port, REG8 dat) { - - pcidev.reg_fwd = dat; -} -static void IOOUTCALL pci_o0cfb(UINT port, REG8 dat) { - - pcidev.reg_cms = dat; -} - -static REG8 IOINPCALL pci_i0cf8(UINT port) { - - return pcidev.reg_cse; -} -static REG8 IOINPCALL pci_i0cf9(UINT port) { - - return pcidev.reg_trc; -} -static REG8 IOINPCALL pci_i0cfa(UINT port) { - - return pcidev.reg_fwd; -} -static REG8 IOINPCALL pci_i0cfb(UINT port) { - - return pcidev.reg_cms; -} - -void IOOUTCALL pcidev_w8_0xcfc(UINT port, UINT8 value) { - - if (pcidev.reg32_caddr & 0x80000000) { - //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ - // Configuration Mechanism #1 Type0,1 - UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; - UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - UINT8 cfgregOffset = ((pcidev.reg32_caddr >> 0) & 0xff) + (port-0xcfc); - if(!pcidev.enable && idselSelect!=0) return; - if(busNumber==0){ - if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ - UINT32 mask = GETCFGREG_B(pcidev.devices[idselSelect].cfgreg8rom, cfgregOffset); - SETCFGREG_B_MASK(pcidev.devices[idselSelect].cfgreg8, cfgregOffset, value, mask); - if(pcidev.devices[idselSelect].regwfn){ - (*pcidev.devices[idselSelect].regwfn)(idselSelect, funcNumber, cfgregOffset, 1, value); - } - } - } - if(idselSelect==0 && cfgregOffset==0x64) setRAM_D000(value); - //}else{ - // // Configuration Mechanism #1 Type1 - // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; - // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; - //} - } -} -void IOOUTCALL pcidev_w16_0xcfc(UINT port, UINT16 value) { - - if (pcidev.reg32_caddr & 0x80000000) { - //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ - // Configuration Mechanism #1 Type0,1 - UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; - UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - UINT8 cfgregOffset = ((pcidev.reg32_caddr >> 0) & 0xff) + (port-0xcfc); - if(!pcidev.enable && idselSelect!=0) return; - if(busNumber==0){ - if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ - UINT32 mask = GETCFGREG_W(pcidev.devices[idselSelect].cfgreg8rom, cfgregOffset); - SETCFGREG_W_MASK(pcidev.devices[idselSelect].cfgreg8, cfgregOffset, value, mask); - if(pcidev.devices[idselSelect].regwfn){ - (*pcidev.devices[idselSelect].regwfn)(idselSelect, funcNumber, cfgregOffset, 2, value); - } - } - } - if(idselSelect==0 && cfgregOffset==0x64){ - //setRAM_D000((value >> 0) & 0xff); - setRAM_D000((value >> 8) & 0xff); - } - //}else{ - // // Configuration Mechanism #1 Type1 - // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; - // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; - //} - } -} -void IOOUTCALL pcidev_w32(UINT port, UINT32 value) { - - if(port==0xcf8){ - pcidev.reg32_caddr = value; - }else{ - if (pcidev.reg32_caddr & 0x80000000) { - //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ - // Configuration Mechanism #1 Type0,1 - UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; - UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; - if(!pcidev.enable && idselSelect!=0) return; - if(busNumber==0){ - if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ - UINT32 mask = GETCFGREG_D(pcidev.devices[idselSelect].cfgreg8rom, cfgregOffset); - SETCFGREG_D_MASK(pcidev.devices[idselSelect].cfgreg8, cfgregOffset, value, mask); - if(pcidev.devices[idselSelect].regwfn){ - (*pcidev.devices[idselSelect].regwfn)(idselSelect, funcNumber, cfgregOffset, 4, value); - } - } - } - if(idselSelect==0 && cfgregOffset==0x64){ - //setRAM_D000((value >> 0) & 0xff); - //setRAM_D000((value >> 8) & 0xff); - //setRAM_D000((value >> 16) & 0xff); - setRAM_D000((value >> 24) & 0xff); - } - //}else{ - // // Configuration Mechanism #1 Type1 - // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; - // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; - //} - } - } -} - -UINT8 IOOUTCALL pcidev_r8_0xcfc(UINT port) { - - //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ - // Configuration Mechanism #1 Type0,1 - UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; - UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - UINT8 cfgregOffset = ((pcidev.reg32_caddr >> 0) & 0xff) + (port-0xcfc); - if(!pcidev.enable && idselSelect!=0) return 0xff; - if(busNumber==0){ - if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ - return GETCFGREG_B(pcidev.devices[idselSelect].cfgreg8, cfgregOffset); - } - } - //}else{ - // // Configuration Mechanism #1 Type1 - // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; - // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; - //} - return 0xff; -} -UINT16 IOOUTCALL pcidev_r16_0xcfc(UINT port) { - - //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ - // Configuration Mechanism #1 Type0,1 - UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; - UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - UINT8 cfgregOffset = ((pcidev.reg32_caddr >> 0) & 0xff) + (port-0xcfc); - if(!pcidev.enable && idselSelect!=0) return 0xffff; - if(busNumber==0){ - if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ - return GETCFGREG_W(pcidev.devices[idselSelect].cfgreg8, cfgregOffset); - } - } - //}else{ - // // Configuration Mechanism #1 Type1 - // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; - // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; - //} - return 0xffff; -} -UINT32 IOOUTCALL pcidev_r32(UINT port) { - - if(port==0xcf8){ - return pcidev.reg32_caddr; - }else{ - //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ - // Configuration Mechanism #1 Type0,1 - UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; - UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; - if(!pcidev.enable && idselSelect!=0) return 0xffffffff; - if(busNumber==0){ - if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ - return GETCFGREG_D(pcidev.devices[idselSelect].cfgreg8, cfgregOffset); - } - } - //}else{ - // // Configuration Mechanism #1 Type1 - // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; - // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; - // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; - // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; - //} - } - return 0xffffffff; -} - -static void IOOUTCALL pci_o063c(UINT port, REG8 dat) { - - //// とりあえずバンク切り替えらしきが出来るように・・・(手抜きなので頻繁に切り替えられると困る) - switch(dat & 0x3) { - case 0x1: - if((pcidev.membankd8 & 0x3) != 0x01){ - memcpy(pcidev.biosromtmp, mem + 0x0d8000, 0x8000); - memcpy(mem + 0x0d8000, pcidev.biosrom, 0x8000); - } - break; - - case 0x2: - case 0x3: - case 0x0: - default: - if((pcidev.membankd8 & 0x3) == 0x01){ - memcpy(pcidev.biosrom, mem + 0x0d8000, 0x8000); - memcpy(mem + 0x0d8000, pcidev.biosromtmp, 0x8000); - } - break; - } - pcidev.membankd8 = dat; - (void)port; -} -static REG8 IOINPCALL pci_i063c(UINT port) { - - return pcidev.membankd8; -} - -// 謎のI/Oポート -static void IOOUTCALL pci_o18f0(UINT port, REG8 dat) { - - pcidev.unkreg_bank1 = dat; - pcidev.unkreg_bank2 = 0; - (void)port; -} -static REG8 IOINPCALL pci_i18f0(UINT port) { - - return pcidev.unkreg_bank1; -} -static void IOOUTCALL pci_o18f2(UINT port, REG8 dat) { - - pcidev.unkreg[(pcidev.unkreg_bank2++) & 3][pcidev.unkreg_bank1] = dat; - (void)port; -} -static REG8 IOINPCALL pci_i18f2(UINT port) { - - return pcidev.unkreg[(pcidev.unkreg_bank2++) & 3][pcidev.unkreg_bank1]; -} - -// Cバス PnP関連 -static UINT8 pnp_addr = 0; -static UINT8 pnp_data[0x100] = {0}; -static REG8 IOINPCALL pnp_iReg(UINT port) { - - return 0xff; -} -static void IOOUTCALL pnp_o259(UINT port, REG8 dat) { - - pnp_addr = dat; - (void)port; -} -static REG8 IOINPCALL pnp_i259(UINT port) { - - return pnp_addr; -} -static void IOOUTCALL pnp_oA59(UINT port, REG8 dat) { - - if(pnp_addr==0){ - iocore_detachinp((pnp_data[pnp_addr] << 2) | 0x3); - iocore_attachinp((dat << 2) | 0x3, pnp_iReg); - mem[0x5B7] = dat; - } - pnp_data[pnp_addr] = dat; - (void)port; -} -static REG8 IOINPCALL pnp_iA59(UINT port) { - - if(pnp_addr==0){ - pnp_data[pnp_addr] = mem[0x5B7]; - } - return pnp_data[pnp_addr]; -} - -void pcidev_basereset() { - OEMCHAR path[MAX_PATH]; - FILEH fh; - OEMCHAR tmpbiosname[16]; - - // 実機PCI BIOSがあれば配置 - _tcscpy(pcidev.biosname, OEMTEXT("")); - _tcscpy(tmpbiosname, OEMTEXT("pci.rom")); - getbiospath(path, tmpbiosname, NELEMENTS(path)); - fh = file_open_rb(path); - if (fh == FILEH_INVALID) { - _tcscpy(tmpbiosname, OEMTEXT("bank0.bin")); - getbiospath(path, tmpbiosname, NELEMENTS(path)); - fh = file_open_rb(path); - } - if (fh != FILEH_INVALID) { - // PCI BIOS - if (file_read(fh, pcidev.biosrom, 0x8000) == 0x8000) { - TRACEOUT(("load pci.rom")); - _tcscpy(pcidev.biosname, tmpbiosname); - }else{ - TRACEOUT(("use simulate pci.rom")); - } - file_close(fh); - }else{ - TRACEOUT(("use simulate pci.rom")); - } - - // レジスタ初期化 - pcidev.reg_cse = 0; - pcidev.reg_trc = 0; - pcidev.reg_fwd = 0; - pcidev.reg_cms = 0x80; // Configuration Mechanism #1 Enable -} - -void pcidev_reset(const NP2CFG *pConfig) { - - int i; - int devid = pcidev_pcmc_deviceid; - - ZeroMemory(&pcidev, sizeof(pcidev)); - - pcidev.enable = np2cfg.usepci; - pcidev.usebios32 = np2cfg.pci_bios32; - - pcidev.membankd8 = 0xFE; // IDE bank にしておく - - pcidev_basereset(); - - memset(pcidev.devices, 0xff, sizeof(_PCIDEVICE)*PCI_DEVICES_MAX); - - for(i=0;i> 2); // READ_DATA port address 0000 00xx xxxx xx11b - //mem[0x5B7] = pnp_data[0]; // READ_DATA port address - //mem[0x5B8] = 0x00; // No C-Bus PnP boards - //iocore_attachinp((pnp_data[pnp_addr] << 2) | 0x3, pnp_iReg); - //iocore_attachout(0x259, pnp_o259); - //iocore_attachout(0xA59, pnp_oA59); - //iocore_attachinp(0x259, pnp_i259); - //iocore_attachinp(0xA59, pnp_iA59); - - if(pcidev.enable){ - // 関数アドレス入れ直し(ステートセーブ用) - pcidev.devices[pcidev_pcmc_deviceid].regwfn = &pcidev_pcmc_cfgreg_w; - - // PCI PC-9821標準デバイスbind - pcidev_cbusbridge_bind(); - pcidev_98graphbridge_bind(); - - if(pcidev.usebios32){ - if(pcidev.bios32entrypoint==0){ - // BIOS32 Entry Pointが位置未確定ならBIOS32 Entry Pointを置く - // XXX: 多分この辺なら空いてるだろーということで・・・ - pcidev.bios32entrypoint = 0x000fffe0; - emptyflag = 1; - // 2byte分空いてるかチェック(0だからといって空いてるとは限らないけど・・・) - for(j=0;j<2;j++){ - if(mem[pcidev.bios32entrypoint+j] != 0x00){ - emptyflag = 0; - } - } - if(emptyflag){ - // 猫BIOSで乗っ取るためにNOPを置いてすぐにRET - mem[pcidev.bios32entrypoint] = 0x90; - mem[pcidev.bios32entrypoint+1] = 0xCB; - }else{ - pcidev.bios32entrypoint = 0; - } - } - } - // BIOS32 Service Directoryとルーティングテーブルを生成 - pcidev_updateBIOS32data(); - pcidev_updateRoutingTable(); - } -} -void pcidev_updateRoutingTable(){ - UINT16 i; - UINT16 allpciirq = (1<<12)|(1<<6)|(1<<5)|(1<<3); - - ZeroMemory(pcidev.biosdata.data, sizeof(pcidev.biosdata.data)); - - // PCI IRQ ルーティングテーブルを生成する - pcidev.biosdata.datacount = 0; - pcidev.allirqbitmap = 0; - for(i=1;i> 0)); - pcidevset10(addr + 1, (UINT8)(value >> 8)); - pcidevset10(addr + 2, (UINT8)(value >> 16)); - pcidevset10(addr + 3, (UINT8)(value >> 24)); - } - } -} - -UINT32 IOOUTCALL pcidev_r32(UINT port) { - - UINT32 ret; - UINT32 addr; - - ret = (UINT32)-1; - if (!(port & 4)) { - ret = pcidev.base; - } - else { - if (pcidev.base & 0x80000000) { - addr = pcidev.base & 0x00fffffc; - ret = pcidevget10(addr + 0); - ret |= (pcidevget10(addr + 1) << 8); - ret |= (pcidevget10(addr + 2) << 16); - ret |= (pcidevget10(addr + 3) << 24); - } - } - return(ret); -} - -void pcidev_reset(const NP2CFG *pConfig) { - - ZeroMemory(&pcidev, sizeof(pcidev)); - - (void)pConfig; -} - -void pcidev_bind(void) { - - UINT i; - - for (i=0x0cfc; i<0x0d00; i++) { - iocore_attachout(i, pci_o04); - iocore_attachinp(i, pci_i04); - } -} -#endif -#endif - + +// PC-9821 PCIバス + +// 現状はConfiguration Mechanism #1対応でバス番号0のみ。bios1a.cにエミュレーションPCI BIOSがあります。 + +#include + +#if defined(SUPPORT_PC9821) + +#include +#include +#include + +#if defined(SUPPORT_PCI) + +#include +#include "pci/cbusbridge.h" +#include "pci/98graphbridge.h" +#include + +#define GETCFGREG_B(reg, ofs) PCI_GETCFGREG_B(reg, ofs) +#define GETCFGREG_W(reg, ofs) PCI_GETCFGREG_W(reg, ofs) +#define GETCFGREG_D(reg, ofs) PCI_GETCFGREG_D(reg, ofs) + +#define SETCFGREG_B(reg, ofs, value) PCI_SETCFGREG_B(reg, ofs, value) +#define SETCFGREG_W(reg, ofs, value) PCI_SETCFGREG_W(reg, ofs, value) +#define SETCFGREG_D(reg, ofs, value) PCI_SETCFGREG_D(reg, ofs, value) + +#define SETCFGREG_B_MASK(reg, ofs, value, mask) PCI_SETCFGREG_B_MASK(reg, ofs, value, mask) +#define SETCFGREG_W_MASK(reg, ofs, value, mask) PCI_SETCFGREG_W_MASK(reg, ofs, value, mask) +#define SETCFGREG_D_MASK(reg, ofs, value, mask) PCI_SETCFGREG_D_MASK(reg, ofs, value, mask) + +int pcidev_pcmc_deviceid = 0; + +//UINT8 PCI_INTLINE2IRQTBL[] = { +//// INTA INTB INTC INTD +// 0, 1, 2, 3, // slot #0 +// 1, 2, 3, 0, // slot #1 +// 2, 3, 0, 1, // slot #2 +// 3, 2, 1, 0, // slot #3 +//}; + +// これはなんだろう? +static void setRAM_D000(UINT8 dat){ + //UINT8 dat = *((UINT8*)(pcidev.devices[0].cfgreg8 + 0x64)); + UINT32 work; + work = CPU_RAM_D000 & 0x03ff; + if (dat & 0x10) { + work |= 0x0400; + } + if (dat & 0x20) { + work |= 0x0800; + } + if (dat & 0x80) { + work |= 0xf000; + } + CPU_RAM_D000 = (UINT16)work; +} + + +void pcidev_pcmc_cfgreg_w(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value){ + +} + +static void IOOUTCALL pci_o0cf8(UINT port, REG8 dat) { + + pcidev.reg_cse = dat & 0xfe; +} +static void IOOUTCALL pci_o0cf9(UINT port, REG8 dat) { + + pcidev.reg_trc = dat; +} +static void IOOUTCALL pci_o0cfa(UINT port, REG8 dat) { + + pcidev.reg_fwd = dat; +} +static void IOOUTCALL pci_o0cfb(UINT port, REG8 dat) { + + pcidev.reg_cms = dat; +} + +static REG8 IOINPCALL pci_i0cf8(UINT port) { + + return pcidev.reg_cse; +} +static REG8 IOINPCALL pci_i0cf9(UINT port) { + + return pcidev.reg_trc; +} +static REG8 IOINPCALL pci_i0cfa(UINT port) { + + return pcidev.reg_fwd; +} +static REG8 IOINPCALL pci_i0cfb(UINT port) { + + return pcidev.reg_cms; +} + +void IOOUTCALL pcidev_w8_0xcfc(UINT port, UINT8 value) { + + if (pcidev.reg32_caddr & 0x80000000) { + //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ + // Configuration Mechanism #1 Type0,1 + UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; + UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + UINT8 cfgregOffset = ((pcidev.reg32_caddr >> 0) & 0xff) + (port-0xcfc); + if(!pcidev.enable && idselSelect!=0) return; + if(busNumber==0){ + if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ + UINT32 mask = GETCFGREG_B(pcidev.devices[idselSelect].cfgreg8rom, cfgregOffset); + SETCFGREG_B_MASK(pcidev.devices[idselSelect].cfgreg8, cfgregOffset, value, mask); + if(pcidev.devices[idselSelect].regwfn){ + (*pcidev.devices[idselSelect].regwfn)(idselSelect, funcNumber, cfgregOffset, 1, value); + } + } + } + if(idselSelect==0 && cfgregOffset==0x64) setRAM_D000(value); + //}else{ + // // Configuration Mechanism #1 Type1 + // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; + // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; + //} + } +} +void IOOUTCALL pcidev_w16_0xcfc(UINT port, UINT16 value) { + + if (pcidev.reg32_caddr & 0x80000000) { + //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ + // Configuration Mechanism #1 Type0,1 + UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; + UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + UINT8 cfgregOffset = ((pcidev.reg32_caddr >> 0) & 0xff) + (port-0xcfc); + if(!pcidev.enable && idselSelect!=0) return; + if(busNumber==0){ + if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ + UINT32 mask = GETCFGREG_W(pcidev.devices[idselSelect].cfgreg8rom, cfgregOffset); + SETCFGREG_W_MASK(pcidev.devices[idselSelect].cfgreg8, cfgregOffset, value, mask); + if(pcidev.devices[idselSelect].regwfn){ + (*pcidev.devices[idselSelect].regwfn)(idselSelect, funcNumber, cfgregOffset, 2, value); + } + } + } + if(idselSelect==0 && cfgregOffset==0x64){ + //setRAM_D000((value >> 0) & 0xff); + setRAM_D000((value >> 8) & 0xff); + } + //}else{ + // // Configuration Mechanism #1 Type1 + // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; + // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; + //} + } +} +void IOOUTCALL pcidev_w32(UINT port, UINT32 value) { + + if(port==0xcf8){ + pcidev.reg32_caddr = value; + }else{ + if (pcidev.reg32_caddr & 0x80000000) { + //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ + // Configuration Mechanism #1 Type0,1 + UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; + UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; + if(!pcidev.enable && idselSelect!=0) return; + if(busNumber==0){ + if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ + UINT32 mask = GETCFGREG_D(pcidev.devices[idselSelect].cfgreg8rom, cfgregOffset); + SETCFGREG_D_MASK(pcidev.devices[idselSelect].cfgreg8, cfgregOffset, value, mask); + if(pcidev.devices[idselSelect].regwfn){ + (*pcidev.devices[idselSelect].regwfn)(idselSelect, funcNumber, cfgregOffset, 4, value); + } + } + } + if(idselSelect==0 && cfgregOffset==0x64){ + //setRAM_D000((value >> 0) & 0xff); + //setRAM_D000((value >> 8) & 0xff); + //setRAM_D000((value >> 16) & 0xff); + setRAM_D000((value >> 24) & 0xff); + } + //}else{ + // // Configuration Mechanism #1 Type1 + // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; + // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; + //} + } + } +} + +UINT8 IOOUTCALL pcidev_r8_0xcfc(UINT port) { + + //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ + // Configuration Mechanism #1 Type0,1 + UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; + UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + UINT8 cfgregOffset = ((pcidev.reg32_caddr >> 0) & 0xff) + (port-0xcfc); + if(!pcidev.enable && idselSelect!=0) return 0xff; + if(busNumber==0){ + if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ + return GETCFGREG_B(pcidev.devices[idselSelect].cfgreg8, cfgregOffset); + } + } + //}else{ + // // Configuration Mechanism #1 Type1 + // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; + // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; + //} + return 0xff; +} +UINT16 IOOUTCALL pcidev_r16_0xcfc(UINT port) { + + //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ + // Configuration Mechanism #1 Type0,1 + UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; + UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + UINT8 cfgregOffset = ((pcidev.reg32_caddr >> 0) & 0xff) + (port-0xcfc); + if(!pcidev.enable && idselSelect!=0) return 0xffff; + if(busNumber==0){ + if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ + return GETCFGREG_W(pcidev.devices[idselSelect].cfgreg8, cfgregOffset); + } + } + //}else{ + // // Configuration Mechanism #1 Type1 + // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; + // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; + //} + return 0xffff; +} +UINT32 IOOUTCALL pcidev_r32(UINT port) { + + if(port==0xcf8){ + return pcidev.reg32_caddr; + }else{ + //if((pcidev.reg32_caddr & 0x00ff0000) == 0){ + // Configuration Mechanism #1 Type0,1 + UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + UINT8 idselSelect = (pcidev.reg32_caddr >> 11) & 0x1f; + UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; + if(!pcidev.enable && idselSelect!=0) return 0xffffffff; + if(busNumber==0){ + if(pcidev.devices[idselSelect].enable/* && funcNumber==0*/){ + return GETCFGREG_D(pcidev.devices[idselSelect].cfgreg8, cfgregOffset); + } + } + //}else{ + // // Configuration Mechanism #1 Type1 + // UINT8 busNumber = (pcidev.reg32_caddr >> 16) & 0xff; + // UINT8 devNumber = (pcidev.reg32_caddr >> 11) & 0x1f; + // UINT8 funcNumber = (pcidev.reg32_caddr >> 8) & 0x7; + // UINT8 cfgregOffset = (pcidev.reg32_caddr >> 0) & 0xff; + //} + } + return 0xffffffff; +} + +static void IOOUTCALL pci_o063c(UINT port, REG8 dat) { + + //// とりあえずバンク切り替えらしきが出来るように・・・(手抜きなので頻繁に切り替えられると困る) + switch(dat & 0x3) { + case 0x1: + if((pcidev.membankd8 & 0x3) != 0x01){ + memcpy(pcidev.biosromtmp, mem + 0x0d8000, 0x8000); + memcpy(mem + 0x0d8000, pcidev.biosrom, 0x8000); + } + break; + + case 0x2: + case 0x3: + case 0x0: + default: + if((pcidev.membankd8 & 0x3) == 0x01){ + memcpy(pcidev.biosrom, mem + 0x0d8000, 0x8000); + memcpy(mem + 0x0d8000, pcidev.biosromtmp, 0x8000); + } + break; + } + pcidev.membankd8 = dat; + (void)port; +} +static REG8 IOINPCALL pci_i063c(UINT port) { + + return pcidev.membankd8; +} + +// 謎のI/Oポート +static void IOOUTCALL pci_o18f0(UINT port, REG8 dat) { + + pcidev.unkreg_bank1 = dat; + pcidev.unkreg_bank2 = 0; + (void)port; +} +static REG8 IOINPCALL pci_i18f0(UINT port) { + + return pcidev.unkreg_bank1; +} +static void IOOUTCALL pci_o18f2(UINT port, REG8 dat) { + + pcidev.unkreg[(pcidev.unkreg_bank2++) & 3][pcidev.unkreg_bank1] = dat; + (void)port; +} +static REG8 IOINPCALL pci_i18f2(UINT port) { + + return pcidev.unkreg[(pcidev.unkreg_bank2++) & 3][pcidev.unkreg_bank1]; +} + +// Cバス PnP関連 +static UINT8 pnp_addr = 0; +static UINT8 pnp_data[0x100] = {0}; +static REG8 IOINPCALL pnp_iReg(UINT port) { + + return 0xff; +} +static void IOOUTCALL pnp_o259(UINT port, REG8 dat) { + + pnp_addr = dat; + (void)port; +} +static REG8 IOINPCALL pnp_i259(UINT port) { + + return pnp_addr; +} +static void IOOUTCALL pnp_oA59(UINT port, REG8 dat) { + + if(pnp_addr==0){ + iocore_detachinp((pnp_data[pnp_addr] << 2) | 0x3); + iocore_attachinp((dat << 2) | 0x3, pnp_iReg); + mem[0x5B7] = dat; + } + pnp_data[pnp_addr] = dat; + (void)port; +} +static REG8 IOINPCALL pnp_iA59(UINT port) { + + if(pnp_addr==0){ + pnp_data[pnp_addr] = mem[0x5B7]; + } + return pnp_data[pnp_addr]; +} + +void pcidev_basereset() { + OEMCHAR path[MAX_PATH]; + FILEH fh; + OEMCHAR tmpbiosname[16]; + + // 実機PCI BIOSがあれば配置 + _tcscpy(pcidev.biosname, OEMTEXT("")); + _tcscpy(tmpbiosname, OEMTEXT("pci.rom")); + getbiospath(path, tmpbiosname, NELEMENTS(path)); + fh = file_open_rb(path); + if (fh == FILEH_INVALID) { + _tcscpy(tmpbiosname, OEMTEXT("bank0.bin")); + getbiospath(path, tmpbiosname, NELEMENTS(path)); + fh = file_open_rb(path); + } + if (fh != FILEH_INVALID) { + // PCI BIOS + if (file_read(fh, pcidev.biosrom, 0x8000) == 0x8000) { + TRACEOUT(("load pci.rom")); + _tcscpy(pcidev.biosname, tmpbiosname); + }else{ + TRACEOUT(("use simulate pci.rom")); + } + file_close(fh); + }else{ + TRACEOUT(("use simulate pci.rom")); + } + + // レジスタ初期化 + pcidev.reg_cse = 0; + pcidev.reg_trc = 0; + pcidev.reg_fwd = 0; + pcidev.reg_cms = 0x80; // Configuration Mechanism #1 Enable +} + +void pcidev_reset(const NP2CFG *pConfig) { + + int i; + int devid = pcidev_pcmc_deviceid; + + ZeroMemory(&pcidev, sizeof(pcidev)); + + pcidev.enable = np2cfg.usepci; + pcidev.usebios32 = np2cfg.pci_bios32; + + pcidev.membankd8 = 0xFE; // IDE bank にしておく + + pcidev_basereset(); + + memset(pcidev.devices, 0xff, sizeof(_PCIDEVICE)*PCI_DEVICES_MAX); + + for(i=0;i> 2); // READ_DATA port address 0000 00xx xxxx xx11b + //mem[0x5B7] = pnp_data[0]; // READ_DATA port address + //mem[0x5B8] = 0x00; // No C-Bus PnP boards + //iocore_attachinp((pnp_data[pnp_addr] << 2) | 0x3, pnp_iReg); + //iocore_attachout(0x259, pnp_o259); + //iocore_attachout(0xA59, pnp_oA59); + //iocore_attachinp(0x259, pnp_i259); + //iocore_attachinp(0xA59, pnp_iA59); + + if(pcidev.enable){ + // 関数アドレス入れ直し(ステートセーブ用) + pcidev.devices[pcidev_pcmc_deviceid].regwfn = &pcidev_pcmc_cfgreg_w; + + // PCI PC-9821標準デバイスbind + pcidev_cbusbridge_bind(); + pcidev_98graphbridge_bind(); + + if(pcidev.usebios32){ + if(pcidev.bios32entrypoint==0){ + // BIOS32 Entry Pointが位置未確定ならBIOS32 Entry Pointを置く + // XXX: 多分この辺なら空いてるだろーということで・・・ + pcidev.bios32entrypoint = 0x000fffe0; + emptyflag = 1; + // 2byte分空いてるかチェック(0だからといって空いてるとは限らないけど・・・) + for(j=0;j<2;j++){ + if(mem[pcidev.bios32entrypoint+j] != 0x00){ + emptyflag = 0; + } + } + if(emptyflag){ + // 猫BIOSで乗っ取るためにNOPを置いてすぐにRET + mem[pcidev.bios32entrypoint] = 0x90; + mem[pcidev.bios32entrypoint+1] = 0xCB; + }else{ + pcidev.bios32entrypoint = 0; + } + } + } + // BIOS32 Service Directoryとルーティングテーブルを生成 + pcidev_updateBIOS32data(); + pcidev_updateRoutingTable(); + } +} +void pcidev_updateRoutingTable(){ + UINT16 i; + UINT16 allpciirq = (1<<12)|(1<<6)|(1<<5)|(1<<3); + + ZeroMemory(pcidev.biosdata.data, sizeof(pcidev.biosdata.data)); + + // PCI IRQ ルーティングテーブルを生成する + pcidev.biosdata.datacount = 0; + pcidev.allirqbitmap = 0; + for(i=1;i> 0)); + pcidevset10(addr + 1, (UINT8)(value >> 8)); + pcidevset10(addr + 2, (UINT8)(value >> 16)); + pcidevset10(addr + 3, (UINT8)(value >> 24)); + } + } +} + +UINT32 IOOUTCALL pcidev_r32(UINT port) { + + UINT32 ret; + UINT32 addr; + + ret = (UINT32)-1; + if (!(port & 4)) { + ret = pcidev.base; + } + else { + if (pcidev.base & 0x80000000) { + addr = pcidev.base & 0x00fffffc; + ret = pcidevget10(addr + 0); + ret |= (pcidevget10(addr + 1) << 8); + ret |= (pcidevget10(addr + 2) << 16); + ret |= (pcidevget10(addr + 3) << 24); + } + } + return(ret); +} + +void pcidev_reset(const NP2CFG *pConfig) { + + ZeroMemory(&pcidev, sizeof(pcidev)); + + (void)pConfig; +} + +void pcidev_bind(void) { + + UINT i; + + for (i=0x0cfc; i<0x0d00; i++) { + iocore_attachout(i, pci_o04); + iocore_attachinp(i, pci_i04); + } +} +#endif +#endif + diff --git a/io/pcidev.h b/io/pcidev.h old mode 100755 new mode 100644 index 8fab701d..3df0d56a --- a/io/pcidev.h +++ b/io/pcidev.h @@ -1,175 +1,175 @@ - -// PC-9821 PCIバス - -#if defined(SUPPORT_PC9821) - -#if defined(SUPPORT_PCI) - -#define PCI_DEVICES_MAX 32 - -#define PCI_PCMC_82434LX 0 -#define PCI_PCMC_82441FX 1 -#define PCI_PCMC_WILDCAT 2 - -#define PCI_GETCFGREG_B(reg, ofs) (*((UINT8*)((reg) + (ofs)))) -#define PCI_GETCFGREG_W(reg, ofs) (*((UINT16*)((reg) + (ofs)))) -#define PCI_GETCFGREG_D(reg, ofs) (*((UINT32*)((reg) + (ofs)))) - -#define PCI_SETCFGREG_B(reg, ofs, value) (PCI_GETCFGREG_B(reg, ofs) = value) -#define PCI_SETCFGREG_W(reg, ofs, value) (PCI_GETCFGREG_W(reg, ofs) = value) -#define PCI_SETCFGREG_D(reg, ofs, value) (PCI_GETCFGREG_D(reg, ofs) = value) - -#define PCI_SETCFGREG_B_MASK(reg, ofs, value, mask) (PCI_GETCFGREG_B(reg, ofs) = (PCI_GETCFGREG_B(reg, ofs) & mask) | (value & ~mask)) -#define PCI_SETCFGREG_W_MASK(reg, ofs, value, mask) (PCI_GETCFGREG_W(reg, ofs) = (PCI_GETCFGREG_W(reg, ofs) & mask) | (value & ~mask)) -#define PCI_SETCFGREG_D_MASK(reg, ofs, value, mask) (PCI_GETCFGREG_D(reg, ofs) = (PCI_GETCFGREG_D(reg, ofs) & mask) | (value & ~mask)) - -// コンフィギュレーションレジスタ変更時に呼ばれる。 -typedef void (*PCIREGWCB)(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value); - -#pragma pack(1) -// PCI IRQ ルーティングテーブル エントリ -typedef struct { - UINT8 busnumber; - UINT8 devicenumber; - UINT8 link4intA; - UINT16 irqmap4intA; - UINT8 link4intB; - UINT16 irqmap4intB; - UINT8 link4intC; - UINT16 irqmap4intC; - UINT8 link4intD; - UINT16 irqmap4intD; - UINT8 slot; - UINT8 reserved; -} _PCIPNP_IRQTBL_ENTRY, *PCIPNP_IRQTBL_ENTRY; -#pragma pack() - -// PCI IRQ ルーティングテーブル -typedef struct { - UINT16 datacount; - union{ - _PCIPNP_IRQTBL_ENTRY data[PCI_DEVICES_MAX]; - UINT8 data8[PCI_DEVICES_MAX * sizeof(_PCIPNP_IRQTBL_ENTRY)]; - }; -} _PCIPNP_IRQTBL, *PCIPNP_IRQTBL; - -// Configuration Space Header -typedef struct { - UINT16 vendorID; - UINT16 deviceID; - UINT16 command; - UINT16 status; - UINT8 revisionID; - UINT8 classcode[3]; - UINT8 cachelinesize; - UINT8 latencytimer; - UINT8 headertype; - UINT8 BIST; - UINT32 baseaddrregs[6]; - UINT32 cardbusCISptr; - UINT16 subsysventorID; - UINT16 subsysID; - UINT32 expROMbaseaddr; - UINT16 capsptr; - UINT8 reserved1[3]; - UINT32 reserved2; - UINT8 interruptline; - UINT8 interruptpin; - UINT8 min_gnt; - UINT8 max_lat; -} _PCICSH, *PCICSH; - -// PCIデバイス -typedef struct { - UINT8 enable; - PCIREGWCB regwfn; - UINT8 slot; // PCIスロット番号(オンボードは0) - UINT8 skipirqtbl; // 0でない場合はルーティングテーブルに登録しない - union{ - UINT8 cfgreg8[0x100]; - _PCICSH header; // Type 00h Configuration Space Header - }; - // ビットを立てたところはリードオンリ - union{ - UINT8 cfgreg8rom[0x100]; - _PCICSH headerrom; // Type 00h Configuration Space Header - }; -} _PCIDEVICE, *PCIDEVICE; - -// PCI -typedef struct { - UINT8 enable; - - UINT8 reg_cse; // CONFIGURATION SPACE ENABLE REGISTER - UINT8 reg_trc; // TURBO-RESET CONTROL REGISTER - UINT8 reg_fwd; // FORWARD REGISTER - UINT8 reg_cms; // Configuration Mechanism Select - - UINT32 reg32_caddr; // CONFIGURATION ADDRESS REGISTER - - _PCIDEVICE devices[PCI_DEVICES_MAX]; // PCIデバイス - - UINT8 membankd0; - UINT8 membankd8; - - UINT8 biosrom[0x8000]; - UINT8 biosromtmp[0x8000]; - OEMCHAR biosname[16]; - - UINT8 usebios32; - UINT32 bios32svcdir; - UINT32 bios32entrypoint; - _PCIPNP_IRQTBL biosdata; - UINT16 allirqbitmap; - - UINT8 unkreg[4][256]; - UINT8 unkreg_bank1; - UINT8 unkreg_bank2; -} _PCIDEV, *PCIDEV; - -#ifdef __cplusplus -extern "C" { -#endif - -void IOOUTCALL pcidev_w8_0xcfc(UINT port, UINT8 value); -void IOOUTCALL pcidev_w16_0xcfc(UINT port, UINT16 value); -void IOOUTCALL pcidev_w32(UINT port, UINT32 value); -UINT8 IOOUTCALL pcidev_r8_0xcfc(UINT port); -UINT16 IOOUTCALL pcidev_r16_0xcfc(UINT port); -UINT32 IOOUTCALL pcidev_r32(UINT port); - -void pcidev_basereset(); -void pcidev_reset(const NP2CFG *pConfig); -void pcidev_bind(void); -void pcidev_updateRoutingTable(); -void pcidev_updateBIOS32data(); - -#ifdef __cplusplus -} -#endif - -#else -typedef struct { - UINT32 base; - - UINT8 membankd0; -} _PCIDEV, *PCIDEV; - -#ifdef __cplusplus -extern "C" { -#endif - -void IOOUTCALL pcidev_w32(UINT port, UINT32 value); -UINT32 IOOUTCALL pcidev_r32(UINT port); - -void pcidev_reset(const NP2CFG *pConfig); -void pcidev_bind(void); - -#ifdef __cplusplus -} -#endif - -#endif - -#endif - + +// PC-9821 PCIバス + +#if defined(SUPPORT_PC9821) + +#if defined(SUPPORT_PCI) + +#define PCI_DEVICES_MAX 32 + +#define PCI_PCMC_82434LX 0 +#define PCI_PCMC_82441FX 1 +#define PCI_PCMC_WILDCAT 2 + +#define PCI_GETCFGREG_B(reg, ofs) (*((UINT8*)((reg) + (ofs)))) +#define PCI_GETCFGREG_W(reg, ofs) (*((UINT16*)((reg) + (ofs)))) +#define PCI_GETCFGREG_D(reg, ofs) (*((UINT32*)((reg) + (ofs)))) + +#define PCI_SETCFGREG_B(reg, ofs, value) (PCI_GETCFGREG_B(reg, ofs) = value) +#define PCI_SETCFGREG_W(reg, ofs, value) (PCI_GETCFGREG_W(reg, ofs) = value) +#define PCI_SETCFGREG_D(reg, ofs, value) (PCI_GETCFGREG_D(reg, ofs) = value) + +#define PCI_SETCFGREG_B_MASK(reg, ofs, value, mask) (PCI_GETCFGREG_B(reg, ofs) = (PCI_GETCFGREG_B(reg, ofs) & mask) | (value & ~mask)) +#define PCI_SETCFGREG_W_MASK(reg, ofs, value, mask) (PCI_GETCFGREG_W(reg, ofs) = (PCI_GETCFGREG_W(reg, ofs) & mask) | (value & ~mask)) +#define PCI_SETCFGREG_D_MASK(reg, ofs, value, mask) (PCI_GETCFGREG_D(reg, ofs) = (PCI_GETCFGREG_D(reg, ofs) & mask) | (value & ~mask)) + +// コンフィギュレーションレジスタ変更時に呼ばれる。 +typedef void (*PCIREGWCB)(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value); + +#pragma pack(1) +// PCI IRQ ルーティングテーブル エントリ +typedef struct { + UINT8 busnumber; + UINT8 devicenumber; + UINT8 link4intA; + UINT16 irqmap4intA; + UINT8 link4intB; + UINT16 irqmap4intB; + UINT8 link4intC; + UINT16 irqmap4intC; + UINT8 link4intD; + UINT16 irqmap4intD; + UINT8 slot; + UINT8 reserved; +} _PCIPNP_IRQTBL_ENTRY, *PCIPNP_IRQTBL_ENTRY; +#pragma pack() + +// PCI IRQ ルーティングテーブル +typedef struct { + UINT16 datacount; + union{ + _PCIPNP_IRQTBL_ENTRY data[PCI_DEVICES_MAX]; + UINT8 data8[PCI_DEVICES_MAX * sizeof(_PCIPNP_IRQTBL_ENTRY)]; + }; +} _PCIPNP_IRQTBL, *PCIPNP_IRQTBL; + +// Configuration Space Header +typedef struct { + UINT16 vendorID; + UINT16 deviceID; + UINT16 command; + UINT16 status; + UINT8 revisionID; + UINT8 classcode[3]; + UINT8 cachelinesize; + UINT8 latencytimer; + UINT8 headertype; + UINT8 BIST; + UINT32 baseaddrregs[6]; + UINT32 cardbusCISptr; + UINT16 subsysventorID; + UINT16 subsysID; + UINT32 expROMbaseaddr; + UINT16 capsptr; + UINT8 reserved1[3]; + UINT32 reserved2; + UINT8 interruptline; + UINT8 interruptpin; + UINT8 min_gnt; + UINT8 max_lat; +} _PCICSH, *PCICSH; + +// PCIデバイス +typedef struct { + UINT8 enable; + PCIREGWCB regwfn; + UINT8 slot; // PCIスロット番号(オンボードは0) + UINT8 skipirqtbl; // 0でない場合はルーティングテーブルに登録しない + union{ + UINT8 cfgreg8[0x100]; + _PCICSH header; // Type 00h Configuration Space Header + }; + // ビットを立てたところはリードオンリ + union{ + UINT8 cfgreg8rom[0x100]; + _PCICSH headerrom; // Type 00h Configuration Space Header + }; +} _PCIDEVICE, *PCIDEVICE; + +// PCI +typedef struct { + UINT8 enable; + + UINT8 reg_cse; // CONFIGURATION SPACE ENABLE REGISTER + UINT8 reg_trc; // TURBO-RESET CONTROL REGISTER + UINT8 reg_fwd; // FORWARD REGISTER + UINT8 reg_cms; // Configuration Mechanism Select + + UINT32 reg32_caddr; // CONFIGURATION ADDRESS REGISTER + + _PCIDEVICE devices[PCI_DEVICES_MAX]; // PCIデバイス + + UINT8 membankd0; + UINT8 membankd8; + + UINT8 biosrom[0x8000]; + UINT8 biosromtmp[0x8000]; + OEMCHAR biosname[16]; + + UINT8 usebios32; + UINT32 bios32svcdir; + UINT32 bios32entrypoint; + _PCIPNP_IRQTBL biosdata; + UINT16 allirqbitmap; + + UINT8 unkreg[4][256]; + UINT8 unkreg_bank1; + UINT8 unkreg_bank2; +} _PCIDEV, *PCIDEV; + +#ifdef __cplusplus +extern "C" { +#endif + +void IOOUTCALL pcidev_w8_0xcfc(UINT port, UINT8 value); +void IOOUTCALL pcidev_w16_0xcfc(UINT port, UINT16 value); +void IOOUTCALL pcidev_w32(UINT port, UINT32 value); +UINT8 IOOUTCALL pcidev_r8_0xcfc(UINT port); +UINT16 IOOUTCALL pcidev_r16_0xcfc(UINT port); +UINT32 IOOUTCALL pcidev_r32(UINT port); + +void pcidev_basereset(); +void pcidev_reset(const NP2CFG *pConfig); +void pcidev_bind(void); +void pcidev_updateRoutingTable(); +void pcidev_updateBIOS32data(); + +#ifdef __cplusplus +} +#endif + +#else +typedef struct { + UINT32 base; + + UINT8 membankd0; +} _PCIDEV, *PCIDEV; + +#ifdef __cplusplus +extern "C" { +#endif + +void IOOUTCALL pcidev_w32(UINT port, UINT32 value); +UINT32 IOOUTCALL pcidev_r32(UINT port); + +void pcidev_reset(const NP2CFG *pConfig); +void pcidev_bind(void); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + diff --git a/io/pegc.c b/io/pegc.c old mode 100755 new mode 100644 index ce4aea67..6c474135 --- a/io/pegc.c +++ b/io/pegc.c @@ -1,385 +1,385 @@ -#include -#include -#include -#include -#include -#include - -// PEGC プレーンモード -// 関連: vram.c, vram.h, memvga.c, memvga.h - -// 詳しくもないのに作ったのでかなりいい加減です。Better than nothing. -// シフタを設定すると読み取りアドレスまで一緒にずれるという致命的な設計ミスをしています。 -// 改良するのであれば全部捨てて作り直した方が良いかもしれません - -#ifdef SUPPORT_PEGC - -// -REG16 MEMCALL pegc_memvgaplane_rd16(UINT32 address){ - - int i,j; - UINT16 ret = 0; - //UINT8 bit; - - UINT32 addr; // 画素単位の読み込み元アドレス - - //UINT8 src, dst, pat1, pat2; // ソースデータ、ディスティネーションデータ、パターンデータ1&2 - UINT8 ropcode = 0; // ラスタオペレーション設定 E0108h bit0〜bit7 - UINT8 ropmethod = 0; // 論理演算の方法を指定(パターンレジスタまたはカラーパレット) E0108h bit11,10 - UINT8 ropupdmode = 0; // 1ならラスタオペレーションを使用 E0108h bit12 - UINT8 planemask = 0; // プレーン書き込み禁止(0=許可, 1=禁止) E0104h - UINT32 pixelmask = 0; // ビット(画素)への書き込み禁止(0=禁止, 1=許可) E010Ch - UINT32 blocklength = 0; // ブロック転送ビット長(転送サイズ-1) E0110h - UINT32 srcbitshift = 0; // リード時のビットシフト数 E0112h - UINT32 dstbitshift = 0; // ライト時のビットシフト数 E0112h - UINT8 shiftdir = 1; // シフト方向(0:inc, 1:dec)E0108h bit9 - UINT8 srccpu = 1; // 直前に読み取ったVRAMデータではなくCPUデータを使用するか E0108h bit8 - - // PEGCレジスタ読みだし - ropcode = LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0xff; - ropmethod = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 10) & 0x3; - ropupdmode = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 12) & 0x1; - planemask = vramop.mio2[PEGC_REG_PLANE_ACCESS]; - pixelmask = LOADINTELDWORD(vramop.mio2 + PEGC_REG_MASK); - blocklength = LOADINTELDWORD(vramop.mio2 + PEGC_REG_LENGTH) & 0x0fff; - srcbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT)) & 0x1f; - dstbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT) >> 8) & 0x1f; - srcbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT)) & 0x1f; - shiftdir = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 9) & 0x1; - srccpu = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 8) & 0x1; - - // 画素単位のアドレス計算 - addr = (address - 0xa8000) * 8; - addr += srcbitshift; - if(!shiftdir){ - if(pegc.remain == blocklength + 1){ - }else{ - addr -= dstbitshift; - } - }else{ - if(pegc.remain == blocklength + 1){ - }else{ - addr -= dstbitshift; - } - } - addr &= 0x80000-1; // 安全のため - - pegc.lastdatalen = 0; - if(!srccpu){ - if(!shiftdir){ - for(i=0;i<16;i++){ - UINT32 addrtmp = (addr + i) & (0x80000-1); // 読み取り位置 - UINT32 pixmaskpos = (1 << ((15-i+8)&0xf)); // 現在の画素に対応するpixelmaskのビット位置 - UINT8 data = vramex[addrtmp]; - - // compare data - if((data ^ vramop.mio2[PEGC_REG_PALETTE1]) & ~planemask){ - ret |= (1<> 13) & 0x1){ - for(j=7;j>=0;j--){ - UINT16 regdata = LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4); - regdata = (regdata & ~(1 << i)) | (((data >> j) & 0x1) << i); - STOREINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4, regdata); - } - } - } - }else{ - for(i=0;i<16;i++){ - UINT32 addrtmp = (addr - i) & (0x80000-1); // 読み取り位置 - UINT32 pixmaskpos = (1 << ((i/8)*8 + (7-(i&0x7)))); // 現在の画素に対応するvalueやpixelmaskのビット位置 - UINT8 data = vramex[addrtmp]; - - // compare data - if((data ^ vramop.mio2[PEGC_REG_PALETTE1]) & ~planemask){ - ret |= (1<=0;j--){ - UINT16 regdata = LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4); - regdata = (regdata & ~(1 << i)) | (((data >> j) & 0x1) << i); - STOREINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4, regdata); - } - } - } - } - } - if(pegc.lastdatalen < 32) pegc.lastdatalen += 16; - return ret; -} -void MEMCALL pegc_memvgaplane_wr16(UINT32 address, REG16 value){ - - static int firstSkip = 0; - - int i,j; - UINT8 bit; - - UINT32 addr; // 画素単位の書き込み先アドレス - - UINT8 src, dst, pat1 = 0, pat2 = 0; // ソースデータ、ディスティネーションデータ、パターンデータ1&2 - UINT8 ropcode = 0; // ラスタオペレーション設定 E0108h bit0〜bit7 - UINT8 ropmethod = 0; // 論理演算の方法を指定(パターンレジスタまたはカラーパレット) E0108h bit11,10 - UINT8 ropupdmode = 0; // 1ならラスタオペレーションを使用 E0108h bit12 - UINT8 planemask = 0; // プレーン書き込み禁止(0=許可, 1=禁止) E0104h - UINT32 pixelmask = 0; // ビット(画素)への書き込み禁止(0=禁止, 1=許可) E010Ch - UINT32 blocklength = 0; // ブロック転送ビット長(転送サイズ-1) E0110h - UINT32 srcbitshift = 0; // リード時のビットシフト数 E0112h - UINT32 dstbitshift = 0; // ライト時のビットシフト数 E0112h - UINT8 shiftdir = 1; // シフト方向(0:inc, 1:dec)E0108h bit9 - UINT8 srccpu = 1; // 直前に読み取ったVRAMデータではなくCPUデータを使用するか E0108h bit8 - int datalen = 16; - int exshiftmode; - - // PEGCレジスタ読みだし - ropcode = LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0xff; - ropmethod = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 10) & 0x3; - ropupdmode = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 12) & 0x1; - planemask = vramop.mio2[PEGC_REG_PLANE_ACCESS]; - pixelmask = LOADINTELDWORD(vramop.mio2 + PEGC_REG_MASK); - blocklength = LOADINTELDWORD(vramop.mio2 + PEGC_REG_LENGTH) & 0x0fff; - srcbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT)) & 0x1f; - dstbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT) >> 8) & 0x1f; - shiftdir = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 9) & 0x1; - srccpu = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 8) & 0x1; - - if(pegc.remain == 0){ - // データ数戻す? - pegc.remain = blocklength + 1; - pegc.lastdatalen = 0; - }else{ - firstSkip = 0; - } - if(firstSkip){ - firstSkip = 0; - return; - } - - exshiftmode = (!srccpu || ((blocklength + 1) & 0xf)!=0); // WORKAROUND - - // 画素単位のアドレス計算 - addr = (address - 0xa8000) * 8; - if(exshiftmode){ - if(pegc.remain == blocklength + 1){ - addr += dstbitshift; - datalen -= dstbitshift; - } - }else{ - // WORKAROUND - addr += dstbitshift; - } - addr &= 0x80000-1; // 安全のため - - // ??? - bit = (addr & 0x40000)?2:1; - - if(!shiftdir){ - // とりあえずインクリメンタル - // メモ (なんかおかしい) - // +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ - // i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | - // +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ - // value → bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 bitF bitE bitD bitC bitB bitA bit9 bit8 - // pixelmask→ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 bitF bitE bitD bitC bitB bitA bit9 bit8 planemask SRC,DST,PAT - // ↓ ↓ - // plane0 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit0 bit0 - // plane1 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit1 bit1 - // plane2 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit2 bit2 - // plane3 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit3 bit3 - // plane4 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit4 bit4 - // plane5 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit5 bit5 - // plane6 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit6 bit6 - // plane7 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit7 bit7 - - for(i=0;i 32){ - if(pixelmask & pixmaskpos){ // 書き込み禁止チェック - // SRCの設定 - if(srccpu){ - // CPUデータを使う - src = (value & pixmaskpos) ? 0xff : 0x00; - }else{ - // 直前に読み取ったVRAMデータを使う - src = pegc.lastdata[i]; - } - - // DSTの設定 現在のVRAMデータ取得 - dst = vramex[addrtmp]; - - if(ropupdmode){ - // ROP使用 - vramex[addrtmp] = (vramex[addrtmp] & planemask); // 書き換えされる予定のビットを0にしておく - - // PATの設定 - if(ropmethod==0){ - // パターンレジスタを使用 - int col = 0; - for(j=7;j>=0;j--){ - col |= (LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4) >> i) & 0x1; - col <<= 1; - } - pat1 = pat2 = col; - }else if(ropmethod==1){ - // パレット2を使用 - pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE2]; - }else if(ropmethod==2){ - // パレット1を使用 - pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE1]; - }else if(ropmethod==3){ - // パレット1と2を使用 - pat1 = vramop.mio2[PEGC_REG_PALETTE1]; - pat2 = vramop.mio2[PEGC_REG_PALETTE2]; - } - // ROP実行 - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<7)) vramex[addrtmp] |= (src & dst & pat1) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<6)) vramex[addrtmp] |= (src & dst & ~pat1) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<5)) vramex[addrtmp] |= (src & ~dst & pat1) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<4)) vramex[addrtmp] |= (src & ~dst & ~pat1) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<3)) vramex[addrtmp] |= (~src & dst & pat2) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<2)) vramex[addrtmp] |= (~src & dst & ~pat2) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<1)) vramex[addrtmp] |= (~src & ~dst & pat2) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<0)) vramex[addrtmp] |= (~src & ~dst & ~pat2) & (~planemask); - }else{ - // SRCの0に対してplanemask&DST, 1に対して~planemask|DST - vramex[addrtmp] = 0; - for(j=0;j<8;j++){ - if(src & (1<> 3)] |= bit; - } - pegc.remain--; - // 転送サイズチェック - if(pegc.remain == 0){ - goto endloop; // 抜ける - } - } - }else{ - for(i=0;i=0;j--){ - col |= (LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4) >> i) & 0x1; - col <<= 1; - } - pat1 = pat2 = col; - }else if(ropmethod==1){ - // パレット2を使用 - pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE2]; - }else if(ropmethod==2){ - // パレット1を使用 - pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE1]; - }else if(ropmethod==3){ - // パレット1と2を使用 - pat1 = vramop.mio2[PEGC_REG_PALETTE1]; - pat2 = vramop.mio2[PEGC_REG_PALETTE2]; - } - // ROP実行 - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<7)) vramex[addrtmp] |= (src & dst & pat1) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<6)) vramex[addrtmp] |= (src & dst & ~pat1) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<5)) vramex[addrtmp] |= (src & ~dst & pat1) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<4)) vramex[addrtmp] |= (src & ~dst & ~pat1) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<3)) vramex[addrtmp] |= (~src & dst & pat2) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<2)) vramex[addrtmp] |= (~src & dst & ~pat2) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<1)) vramex[addrtmp] |= (~src & ~dst & pat2) & (~planemask); - if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<0)) vramex[addrtmp] |= (~src & ~dst & ~pat2) & (~planemask); - }else{ - // SRCの0に対してplanemask&DST, 1に対して~planemask|DST - vramex[addrtmp] = 0; - for(j=0;j<8;j++){ - if(src & (1<> 3)] |= bit; - } - - pegc.remain--; - // 転送サイズチェック - if(pegc.remain == 0){ - goto endloop; // 抜ける - } - } - } -endloop: - gdcs.grphdisp |= bit; - - if(pegc.remain == 0){ - if(exshiftmode){ - // nothing to do - }else{ - // WORKAROUND - if(dstbitshift){ - firstSkip = 1; - } - } - } - if(pegc.lastdatalen > 16) { - pegc.lastdatalen -= 16; - }else{ - pegc.lastdatalen = 0; - } -} -UINT32 MEMCALL pegc_memvgaplane_rd32(UINT32 address){ - // TODO: 作る - return 0; -} -void MEMCALL pegc_memvgaplane_wr32(UINT32 address, UINT32 value){ - // TODO: 作る -} - -void pegc_reset(const NP2CFG *pConfig) { - - ZeroMemory(&pegc, sizeof(pegc)); - - pegc.enable = np2cfg.usepegcplane; - - (void)pConfig; -} - -void pegc_bind(void) { - -} - -#endif +#include +#include +#include +#include +#include +#include + +// PEGC プレーンモード +// 関連: vram.c, vram.h, memvga.c, memvga.h + +// 詳しくもないのに作ったのでかなりいい加減です。Better than nothing. +// シフタを設定すると読み取りアドレスまで一緒にずれるという致命的な設計ミスをしています。 +// 改良するのであれば全部捨てて作り直した方が良いかもしれません + +#ifdef SUPPORT_PEGC + +// +REG16 MEMCALL pegc_memvgaplane_rd16(UINT32 address){ + + int i,j; + UINT16 ret = 0; + //UINT8 bit; + + UINT32 addr; // 画素単位の読み込み元アドレス + + //UINT8 src, dst, pat1, pat2; // ソースデータ、ディスティネーションデータ、パターンデータ1&2 + UINT8 ropcode = 0; // ラスタオペレーション設定 E0108h bit0〜bit7 + UINT8 ropmethod = 0; // 論理演算の方法を指定(パターンレジスタまたはカラーパレット) E0108h bit11,10 + UINT8 ropupdmode = 0; // 1ならラスタオペレーションを使用 E0108h bit12 + UINT8 planemask = 0; // プレーン書き込み禁止(0=許可, 1=禁止) E0104h + UINT32 pixelmask = 0; // ビット(画素)への書き込み禁止(0=禁止, 1=許可) E010Ch + UINT32 blocklength = 0; // ブロック転送ビット長(転送サイズ-1) E0110h + UINT32 srcbitshift = 0; // リード時のビットシフト数 E0112h + UINT32 dstbitshift = 0; // ライト時のビットシフト数 E0112h + UINT8 shiftdir = 1; // シフト方向(0:inc, 1:dec)E0108h bit9 + UINT8 srccpu = 1; // 直前に読み取ったVRAMデータではなくCPUデータを使用するか E0108h bit8 + + // PEGCレジスタ読みだし + ropcode = LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0xff; + ropmethod = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 10) & 0x3; + ropupdmode = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 12) & 0x1; + planemask = vramop.mio2[PEGC_REG_PLANE_ACCESS]; + pixelmask = LOADINTELDWORD(vramop.mio2 + PEGC_REG_MASK); + blocklength = LOADINTELDWORD(vramop.mio2 + PEGC_REG_LENGTH) & 0x0fff; + srcbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT)) & 0x1f; + dstbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT) >> 8) & 0x1f; + srcbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT)) & 0x1f; + shiftdir = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 9) & 0x1; + srccpu = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 8) & 0x1; + + // 画素単位のアドレス計算 + addr = (address - 0xa8000) * 8; + addr += srcbitshift; + if(!shiftdir){ + if(pegc.remain == blocklength + 1){ + }else{ + addr -= dstbitshift; + } + }else{ + if(pegc.remain == blocklength + 1){ + }else{ + addr -= dstbitshift; + } + } + addr &= 0x80000-1; // 安全のため + + pegc.lastdatalen = 0; + if(!srccpu){ + if(!shiftdir){ + for(i=0;i<16;i++){ + UINT32 addrtmp = (addr + i) & (0x80000-1); // 読み取り位置 + UINT32 pixmaskpos = (1 << ((15-i+8)&0xf)); // 現在の画素に対応するpixelmaskのビット位置 + UINT8 data = vramex[addrtmp]; + + // compare data + if((data ^ vramop.mio2[PEGC_REG_PALETTE1]) & ~planemask){ + ret |= (1<> 13) & 0x1){ + for(j=7;j>=0;j--){ + UINT16 regdata = LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4); + regdata = (regdata & ~(1 << i)) | (((data >> j) & 0x1) << i); + STOREINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4, regdata); + } + } + } + }else{ + for(i=0;i<16;i++){ + UINT32 addrtmp = (addr - i) & (0x80000-1); // 読み取り位置 + UINT32 pixmaskpos = (1 << ((i/8)*8 + (7-(i&0x7)))); // 現在の画素に対応するvalueやpixelmaskのビット位置 + UINT8 data = vramex[addrtmp]; + + // compare data + if((data ^ vramop.mio2[PEGC_REG_PALETTE1]) & ~planemask){ + ret |= (1<=0;j--){ + UINT16 regdata = LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4); + regdata = (regdata & ~(1 << i)) | (((data >> j) & 0x1) << i); + STOREINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4, regdata); + } + } + } + } + } + if(pegc.lastdatalen < 32) pegc.lastdatalen += 16; + return ret; +} +void MEMCALL pegc_memvgaplane_wr16(UINT32 address, REG16 value){ + + static int firstSkip = 0; + + int i,j; + UINT8 bit; + + UINT32 addr; // 画素単位の書き込み先アドレス + + UINT8 src, dst, pat1 = 0, pat2 = 0; // ソースデータ、ディスティネーションデータ、パターンデータ1&2 + UINT8 ropcode = 0; // ラスタオペレーション設定 E0108h bit0〜bit7 + UINT8 ropmethod = 0; // 論理演算の方法を指定(パターンレジスタまたはカラーパレット) E0108h bit11,10 + UINT8 ropupdmode = 0; // 1ならラスタオペレーションを使用 E0108h bit12 + UINT8 planemask = 0; // プレーン書き込み禁止(0=許可, 1=禁止) E0104h + UINT32 pixelmask = 0; // ビット(画素)への書き込み禁止(0=禁止, 1=許可) E010Ch + UINT32 blocklength = 0; // ブロック転送ビット長(転送サイズ-1) E0110h + UINT32 srcbitshift = 0; // リード時のビットシフト数 E0112h + UINT32 dstbitshift = 0; // ライト時のビットシフト数 E0112h + UINT8 shiftdir = 1; // シフト方向(0:inc, 1:dec)E0108h bit9 + UINT8 srccpu = 1; // 直前に読み取ったVRAMデータではなくCPUデータを使用するか E0108h bit8 + int datalen = 16; + int exshiftmode; + + // PEGCレジスタ読みだし + ropcode = LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0xff; + ropmethod = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 10) & 0x3; + ropupdmode = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 12) & 0x1; + planemask = vramop.mio2[PEGC_REG_PLANE_ACCESS]; + pixelmask = LOADINTELDWORD(vramop.mio2 + PEGC_REG_MASK); + blocklength = LOADINTELDWORD(vramop.mio2 + PEGC_REG_LENGTH) & 0x0fff; + srcbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT)) & 0x1f; + dstbitshift = (LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT) >> 8) & 0x1f; + shiftdir = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 9) & 0x1; + srccpu = (LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) >> 8) & 0x1; + + if(pegc.remain == 0){ + // データ数戻す? + pegc.remain = blocklength + 1; + pegc.lastdatalen = 0; + }else{ + firstSkip = 0; + } + if(firstSkip){ + firstSkip = 0; + return; + } + + exshiftmode = (!srccpu || ((blocklength + 1) & 0xf)!=0); // WORKAROUND + + // 画素単位のアドレス計算 + addr = (address - 0xa8000) * 8; + if(exshiftmode){ + if(pegc.remain == blocklength + 1){ + addr += dstbitshift; + datalen -= dstbitshift; + } + }else{ + // WORKAROUND + addr += dstbitshift; + } + addr &= 0x80000-1; // 安全のため + + // ??? + bit = (addr & 0x40000)?2:1; + + if(!shiftdir){ + // とりあえずインクリメンタル + // メモ (なんかおかしい) + // +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + // i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | + // +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + // value → bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 bitF bitE bitD bitC bitB bitA bit9 bit8 + // pixelmask→ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 bitF bitE bitD bitC bitB bitA bit9 bit8 planemask SRC,DST,PAT + // ↓ ↓ + // plane0 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit0 bit0 + // plane1 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit1 bit1 + // plane2 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit2 bit2 + // plane3 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit3 bit3 + // plane4 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit4 bit4 + // plane5 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit5 bit5 + // plane6 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit6 bit6 + // plane7 vramex[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] bit7 bit7 + + for(i=0;i 32){ + if(pixelmask & pixmaskpos){ // 書き込み禁止チェック + // SRCの設定 + if(srccpu){ + // CPUデータを使う + src = (value & pixmaskpos) ? 0xff : 0x00; + }else{ + // 直前に読み取ったVRAMデータを使う + src = pegc.lastdata[i]; + } + + // DSTの設定 現在のVRAMデータ取得 + dst = vramex[addrtmp]; + + if(ropupdmode){ + // ROP使用 + vramex[addrtmp] = (vramex[addrtmp] & planemask); // 書き換えされる予定のビットを0にしておく + + // PATの設定 + if(ropmethod==0){ + // パターンレジスタを使用 + int col = 0; + for(j=7;j>=0;j--){ + col |= (LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4) >> i) & 0x1; + col <<= 1; + } + pat1 = pat2 = col; + }else if(ropmethod==1){ + // パレット2を使用 + pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE2]; + }else if(ropmethod==2){ + // パレット1を使用 + pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE1]; + }else if(ropmethod==3){ + // パレット1と2を使用 + pat1 = vramop.mio2[PEGC_REG_PALETTE1]; + pat2 = vramop.mio2[PEGC_REG_PALETTE2]; + } + // ROP実行 + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<7)) vramex[addrtmp] |= (src & dst & pat1) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<6)) vramex[addrtmp] |= (src & dst & ~pat1) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<5)) vramex[addrtmp] |= (src & ~dst & pat1) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<4)) vramex[addrtmp] |= (src & ~dst & ~pat1) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<3)) vramex[addrtmp] |= (~src & dst & pat2) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<2)) vramex[addrtmp] |= (~src & dst & ~pat2) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<1)) vramex[addrtmp] |= (~src & ~dst & pat2) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<0)) vramex[addrtmp] |= (~src & ~dst & ~pat2) & (~planemask); + }else{ + // SRCの0に対してplanemask&DST, 1に対して~planemask|DST + vramex[addrtmp] = 0; + for(j=0;j<8;j++){ + if(src & (1<> 3)] |= bit; + } + pegc.remain--; + // 転送サイズチェック + if(pegc.remain == 0){ + goto endloop; // 抜ける + } + } + }else{ + for(i=0;i=0;j--){ + col |= (LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + j*4) >> i) & 0x1; + col <<= 1; + } + pat1 = pat2 = col; + }else if(ropmethod==1){ + // パレット2を使用 + pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE2]; + }else if(ropmethod==2){ + // パレット1を使用 + pat1 = pat2 = vramop.mio2[PEGC_REG_PALETTE1]; + }else if(ropmethod==3){ + // パレット1と2を使用 + pat1 = vramop.mio2[PEGC_REG_PALETTE1]; + pat2 = vramop.mio2[PEGC_REG_PALETTE2]; + } + // ROP実行 + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<7)) vramex[addrtmp] |= (src & dst & pat1) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<6)) vramex[addrtmp] |= (src & dst & ~pat1) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<5)) vramex[addrtmp] |= (src & ~dst & pat1) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<4)) vramex[addrtmp] |= (src & ~dst & ~pat1) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<3)) vramex[addrtmp] |= (~src & dst & pat2) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<2)) vramex[addrtmp] |= (~src & dst & ~pat2) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<1)) vramex[addrtmp] |= (~src & ~dst & pat2) & (~planemask); + if(vramop.mio2[PEGC_REG_PLANE_ROP] & (1<<0)) vramex[addrtmp] |= (~src & ~dst & ~pat2) & (~planemask); + }else{ + // SRCの0に対してplanemask&DST, 1に対して~planemask|DST + vramex[addrtmp] = 0; + for(j=0;j<8;j++){ + if(src & (1<> 3)] |= bit; + } + + pegc.remain--; + // 転送サイズチェック + if(pegc.remain == 0){ + goto endloop; // 抜ける + } + } + } +endloop: + gdcs.grphdisp |= bit; + + if(pegc.remain == 0){ + if(exshiftmode){ + // nothing to do + }else{ + // WORKAROUND + if(dstbitshift){ + firstSkip = 1; + } + } + } + if(pegc.lastdatalen > 16) { + pegc.lastdatalen -= 16; + }else{ + pegc.lastdatalen = 0; + } +} +UINT32 MEMCALL pegc_memvgaplane_rd32(UINT32 address){ + // TODO: 作る + return 0; +} +void MEMCALL pegc_memvgaplane_wr32(UINT32 address, UINT32 value){ + // TODO: 作る +} + +void pegc_reset(const NP2CFG *pConfig) { + + ZeroMemory(&pegc, sizeof(pegc)); + + pegc.enable = np2cfg.usepegcplane; + + (void)pConfig; +} + +void pegc_bind(void) { + +} + +#endif diff --git a/io/pegc.h b/io/pegc.h index 3fe06da3..7f350f81 100644 --- a/io/pegc.h +++ b/io/pegc.h @@ -1,48 +1,48 @@ -#pragma once - -#ifdef SUPPORT_PEGC - -#define PEGC_REG_PPM_BANK_A8 0x000 // mio1 E0004h -#define PEGC_REG_PPM_BANK_B0 0x002 // mio1 E0006h -#define PEGC_REG_MODE 0x000 // mio2 E0100h -#define PEGC_REG_VRAM_ENABLE 0x002 // mio2 E0102h -#define PEGC_REG_PLANE_ACCESS 0x004 // mio2 E0104h - // mio2 E0106h -#define PEGC_REG_PLANE_ROP 0x008 // mio2 E0108h -#define PEGC_REG_DATASELECT 0x00A // mio2 E010Ah -#define PEGC_REG_MASK 0x00C // mio2 E010Ch - // mio2 E010Eh -#define PEGC_REG_LENGTH 0x010 // mio2 E0110h -#define PEGC_REG_SHIFT 0x012 // mio2 E0112h -#define PEGC_REG_PALETTE1 0x014 // mio2 E0114h - // mio2 E0116h -#define PEGC_REG_PALETTE2 0x018 // mio2 E0118h -#define PEGC_REG_PATTERN 0x020 // mio2 E0120h - -typedef struct { - UINT8 enable; // PEGCプレーンモード使用可能 - - UINT8 lastdata[64]; // PEGCプレーンモード 最後にVRAMから読み取ったデータ - SINT32 lastdatalen; // PEGCプレーンモード 読み取り済みデータ長さ - UINT32 remain; // PEGCプレーンモード 転送データ残り? -} _PEGC, *PEGC; - - -#ifdef __cplusplus -extern "C" { -#endif - -REG16 MEMCALL pegc_memvgaplane_rd16(UINT32 address); -void MEMCALL pegc_memvgaplane_wr16(UINT32 address, REG16 value); -UINT32 MEMCALL pegc_memvgaplane_rd32(UINT32 address); -void MEMCALL pegc_memvgaplane_wr32(UINT32 address, UINT32 value); - -void pegc_reset(const NP2CFG *pConfig); -void pegc_bind(void); - -#ifdef __cplusplus -} -#endif - - +#pragma once + +#ifdef SUPPORT_PEGC + +#define PEGC_REG_PPM_BANK_A8 0x000 // mio1 E0004h +#define PEGC_REG_PPM_BANK_B0 0x002 // mio1 E0006h +#define PEGC_REG_MODE 0x000 // mio2 E0100h +#define PEGC_REG_VRAM_ENABLE 0x002 // mio2 E0102h +#define PEGC_REG_PLANE_ACCESS 0x004 // mio2 E0104h + // mio2 E0106h +#define PEGC_REG_PLANE_ROP 0x008 // mio2 E0108h +#define PEGC_REG_DATASELECT 0x00A // mio2 E010Ah +#define PEGC_REG_MASK 0x00C // mio2 E010Ch + // mio2 E010Eh +#define PEGC_REG_LENGTH 0x010 // mio2 E0110h +#define PEGC_REG_SHIFT 0x012 // mio2 E0112h +#define PEGC_REG_PALETTE1 0x014 // mio2 E0114h + // mio2 E0116h +#define PEGC_REG_PALETTE2 0x018 // mio2 E0118h +#define PEGC_REG_PATTERN 0x020 // mio2 E0120h + +typedef struct { + UINT8 enable; // PEGCプレーンモード使用可能 + + UINT8 lastdata[64]; // PEGCプレーンモード 最後にVRAMから読み取ったデータ + SINT32 lastdatalen; // PEGCプレーンモード 読み取り済みデータ長さ + UINT32 remain; // PEGCプレーンモード 転送データ残り? +} _PEGC, *PEGC; + + +#ifdef __cplusplus +extern "C" { +#endif + +REG16 MEMCALL pegc_memvgaplane_rd16(UINT32 address); +void MEMCALL pegc_memvgaplane_wr16(UINT32 address, REG16 value); +UINT32 MEMCALL pegc_memvgaplane_rd32(UINT32 address); +void MEMCALL pegc_memvgaplane_wr32(UINT32 address, UINT32 value); + +void pegc_reset(const NP2CFG *pConfig); +void pegc_bind(void); + +#ifdef __cplusplus +} +#endif + + #endif \ No newline at end of file diff --git a/io/pic.c b/io/pic.c old mode 100755 new mode 100644 index 8c791304..858c0825 --- a/io/pic.c +++ b/io/pic.c @@ -1,452 +1,452 @@ -#include -#include -#include -#include - -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif - -enum { - PIC_OCW2_L = 0x07, - PIC_OCW2_EOI = 0x20, - PIC_OCW2_SL = 0x40, - PIC_OCW2_R = 0x80, - - PIC_OCW3_RIS = 0x01, - PIC_OCW3_RR = 0x02, - PIC_OCW3_P = 0x04, - PIC_OCW3_SMM = 0x20, - PIC_OCW3_ESMM = 0x40 -}; - -#if defined(NP2_WIN) -static int pic_cs_initialized = 0; -static CRITICAL_SECTION pic_cs; -#else - // TODO: 非Windows用コードを書く -#endif - -static void pic_enter_criticalsection(void){ -#if defined(NP2_WIN) - if(!pic_cs_initialized) return; - EnterCriticalSection(&pic_cs); -#else - // TODO: 非Windows用コードを書く -#endif -} -static void pic_leave_criticalsection(void){ -#if defined(NP2_WIN) - if(!pic_cs_initialized) return; - LeaveCriticalSection(&pic_cs); -#else - // TODO: 非Windows用コードを書く -#endif -} - -static const _PICITEM def_master = { - {0x11, 0x08, 0x80, 0x1d}, - 0x7d, 0, 0, 0, 0, 0}; - -static const _PICITEM def_slave = { - {0x11, 0x10, 0x07, 0x09}, - 0x71, 0, 0, 0, 0, 0}; - - -// ---- - -#if 0 // スレーブがおかしい… -void pic_irq(void) { - - PIC p; - REG8 mir; - REG8 sir; - REG8 dat; - REG8 num; - REG8 bit; - REG8 slave; - - // 割込み許可? - if (!CPU_isEI) { - return; - } - p = &pic; - - mir = p->pi[0].irr & (~p->pi[0].imr); - sir = p->pi[1].irr & (~p->pi[1].imr); - if ((mir == 0) && (sir == 0)) { - return; - } - - slave = 1 << (p->pi[1].icw[2] & 7); - dat = mir; - if (sir) { - dat |= slave & (~p->pi[0].imr); - } - if (!(p->pi[0].ocw3 & PIC_OCW3_SMM)) { - dat |= p->pi[0].isr; - } - num = p->pi[0].pry; - bit = 1 << num; - while(!(dat & bit)) { - num = (num + 1) & 7; - bit = 1 << num; - } - if (p->pi[0].icw[2] & bit) { // スレーヴ - dat = sir; - if (!(p->pi[1].ocw3 & PIC_OCW3_SMM)) { - dat |= p->pi[1].isr; - } - num = p->pi[1].pry; - bit = 1 << num; - while(!(dat & bit)) { - num = (num + 1) & 7; - bit = 1 << num; - } - if (!(p->pi[1].isr & bit)) { - p->pi[0].isr |= slave; - p->pi[0].irr &= ~slave; - p->pi[1].isr |= bit; - p->pi[1].irr &= ~bit; - TRACEOUT(("hardware-int %.2x", (p->pi[1].icw[1] & 0xf8) | num)); - CPU_INTERRUPT((REG8)((p->pi[1].icw[1] & 0xf8) | num), 0); - } - } - else if (!(p->pi[0].isr & bit)) { // マスター - p->pi[0].isr |= bit; - p->pi[0].irr &= ~bit; - if (num == 0) { - nevent_reset(NEVENT_PICMASK); - } - TRACEOUT(("hardware-int %.2x [%.4x:%.4x]", (p->pi[0].icw[1] & 0xf8) | num, CPU_CS, CPU_IP)); - CPU_INTERRUPT((REG8)((p->pi[0].icw[1] & 0xf8) | num), 0); - } -} -#else -void pic_irq(void) { // ver0.78 - - PIC p; - REG8 mir; - REG8 sir; - REG8 num; - REG8 bit; - REG8 slave; - UINT8 intrtmp; - - // 割込み許可? -#if defined(SUPPORT_IA32_HAXM) - if (!np2hax.emumode && np2hax.enable && CPU_STAT_PM) { - // workaround - //if (!(np2haxstat.state._eflags & I_FLAG)) { - // return; - //} - }else -#endif - if (!CPU_isEI) { - return; - } - p = &pic; - - pic_enter_criticalsection(); - sir = p->pi[1].irr & (~p->pi[1].imr); - slave = 1 << (p->pi[1].icw[2] & 7); - mir = p->pi[0].irr; - if (sir) { - mir |= slave; - } - mir &= (~p->pi[0].imr); - if (mir == 0) { - pic_leave_criticalsection(); - return; - } - if (!(p->pi[0].ocw3 & PIC_OCW3_SMM)) { - mir |= p->pi[0].isr; - } - num = p->pi[0].pry; - bit = 1 << num; - while(!(mir & bit)) { - num = (num + 1) & 7; - bit = 1 << num; - } - if (p->pi[0].icw[2] & bit) { // スレーヴ - if (sir == 0) { - pic_leave_criticalsection(); - return; - } - if (!(p->pi[1].ocw3 & PIC_OCW3_SMM)) { - sir |= p->pi[1].isr; - } - num = p->pi[1].pry; - bit = 1 << num; - while(!(sir & bit)) { - num = (num + 1) & 7; - bit = 1 << num; - } - if (!(p->pi[1].isr & bit)) { - p->pi[0].isr |= slave; - p->pi[0].irr &= ~slave; - p->pi[1].isr |= bit; - p->pi[1].irr &= ~bit; -// TRACEOUT(("hardware-int %.2x", (p->pi[1].icw[1] & 0xf8) | num)); - intrtmp = (p->pi[1].icw[1] & 0xf8) | num; - pic_leave_criticalsection(); - CPU_INTERRUPT((REG8)intrtmp, 0); - }else{ - pic_leave_criticalsection(); - } - } - else if (!(p->pi[0].isr & bit)) { // マスター - p->pi[0].isr |= bit; - p->pi[0].irr &= ~bit; - if (num == 0) { - nevent_reset(NEVENT_PICMASK); - } -// TRACEOUT(("hardware-int %.2x [%.4x:%.4x]", (p->pi[0].icw[1] & 0xf8) | num, CPU_CS, CPU_IP)); - intrtmp = (p->pi[0].icw[1] & 0xf8) | num; - pic_leave_criticalsection(); - CPU_INTERRUPT((REG8)intrtmp, 0); - }else{ - pic_leave_criticalsection(); - } -} -#endif - - -// 簡易モード(SYSTEM TIMERだけ) -void picmask(NEVENTITEM item) { - - PICITEM pi; - - pic_enter_criticalsection(); - if (item->flag & NEVENT_SETEVENT) { - pi = &pic.pi[0]; - pi->irr &= ~(pi->imr & PIC_SYSTEMTIMER); - } - pic_leave_criticalsection(); -} - -void pic_setirq(REG8 irq) { - - PICITEM pi; - REG8 bit; - - pic_enter_criticalsection(); - pi = pic.pi; - bit = 1 << (irq & 7); - if (!(irq & 8)) { - pi[0].irr |= bit; - if (pi[0].imr & bit) { - if (bit & PIC_SYSTEMTIMER) { - if ((pit.ch[0].ctrl & 0x0c) == 0x04) { - SINT32 cnt; // ver0.29 - if (pit.ch[0].value > 8) { - cnt = pccore.multiple * pit.ch[0].value; - cnt >>= 2; - } - else { - cnt = pccore.multiple << (16 - 2); - } - nevent_set(NEVENT_PICMASK, cnt, picmask, NEVENT_ABSOLUTE); - } - } - } - if (pi[0].isr & bit) { - if (bit & PIC_CRTV) { - pi[0].irr &= ~PIC_CRTV; - gdc.vsyncint = 1; - } - } - } - else { - pi[1].irr |= bit; - } - pic_leave_criticalsection(); -} - -void pic_resetirq(REG8 irq) { - - PICITEM pi; - - pic_enter_criticalsection(); - pi = pic.pi + ((irq >> 3) & 1); - pi->irr &= ~(1 << (irq & 7)); - pic_leave_criticalsection(); -} - - -// ---- I/O - -static void IOOUTCALL pic_o00(UINT port, REG8 dat) { - - PICITEM picp; - REG8 level; - UINT8 ocw3; - - pic_enter_criticalsection(); -// TRACEOUT(("pic %x %x", port, dat)); - picp = &pic.pi[(port >> 3) & 1]; - picp->writeicw = 0; - switch(dat & 0x18) { - case 0x00: // ocw2 - if (dat & PIC_OCW2_SL) { - level = dat & PIC_OCW2_L; - } - else { - if (!picp->isr) { - break; - } - level = picp->pry; - while(!(picp->isr & (1 << level))) { - level = (level + 1) & 7; - } - } - if (dat & PIC_OCW2_R) { - picp->pry = (level + 1) & 7; - } - if (dat & PIC_OCW2_EOI) { - picp->isr &= ~(1 << level); - } - nevent_forceexit(); // mainloop exit - break; - - case 0x08: // ocw3 - ocw3 = picp->ocw3; - if (!(dat & PIC_OCW3_RR)) { - dat &= PIC_OCW3_RIS; - dat |= (ocw3 & PIC_OCW3_RIS); - } - if (!(dat & PIC_OCW3_ESMM)) { - dat &= ~PIC_OCW3_SMM; - dat |= (ocw3 & PIC_OCW3_SMM); - } - picp->ocw3 = dat; - break; - - default: - picp->icw[0] = dat; - picp->imr = 0; - picp->irr = 0; - picp->ocw3 = 0; -#if 0 - picp->levels = 0; - picp->isr = 0; -#endif - picp->pry = 0; - picp->writeicw = 1; - break; - } - pic_leave_criticalsection(); -} - -static void IOOUTCALL pic_o02(UINT port, REG8 dat) { - - PICITEM picp; - - pic_enter_criticalsection(); -// TRACEOUT(("pic %x %x", port, dat)); - picp = &pic.pi[(port >> 3) & 1]; - if (!picp->writeicw) { -#if 1 - UINT8 set; - set = picp->imr & (~dat); - // リセットされたビットは割り込みある? - if ((CPU_isDI) || (!(picp->irr & set))) { - picp->imr = dat; - pic_leave_criticalsection(); - return; - } -#endif - picp->imr = dat; - } - else { - picp->icw[picp->writeicw] = dat; - picp->writeicw++; - if (picp->writeicw >= (3 + (picp->icw[0] & 1))) { - picp->writeicw = 0; - } - } - pic_leave_criticalsection(); - nevent_forceexit(); -} - -static REG8 IOINPCALL pic_i00(UINT port) { - - PICITEM picp; - - picp = &pic.pi[(port >> 3) & 1]; - if (!(picp->ocw3 & PIC_OCW3_RIS)) { - return(picp->irr); // read irr - } - else { - return(picp->isr); // read isr - } -} - -static REG8 IOINPCALL pic_i02(UINT port) { - - PICITEM picp; - - picp = &pic.pi[(port >> 3) & 1]; - return(picp->imr); -} - - -// ---- I/F - -#if !defined(SUPPORT_PC9821) -static const IOOUT pico00[2] = { - pic_o00, pic_o02}; - -static const IOINP pici00[2] = { - pic_i00, pic_i02}; -#else -static const IOOUT pico00[4] = { - pic_o00, pic_o02, NULL, NULL}; - -static const IOINP pici00[4] = { - pic_i00, pic_i02, NULL, NULL}; -#endif - -void pic_initialize(void) { -#if defined(NP2_WIN) - if(!pic_cs_initialized){ - memset(&pic_cs, 0, sizeof(pic_cs)); - InitializeCriticalSection(&pic_cs); - pic_cs_initialized = 1; - } -#else - // TODO: 非Windows用コードを書く -#endif -} - -void pic_deinitialize(void) { -#if defined(NP2_WIN) - if(pic_cs_initialized){ - DeleteCriticalSection(&pic_cs); - pic_cs_initialized = 0; - } -#else - // TODO: 非Windows用コードを書く -#endif -} - -void pic_reset(const NP2CFG *pConfig) { - - pic.pi[0] = def_master; - pic.pi[1] = def_slave; - - (void)pConfig; -} - -void pic_bind(void) { - -#if !defined(SUPPORT_PC9821) - iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 2); - iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 2); -#else - iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 4); - iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 4); -#endif -} - +#include +#include +#include +#include + +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif + +enum { + PIC_OCW2_L = 0x07, + PIC_OCW2_EOI = 0x20, + PIC_OCW2_SL = 0x40, + PIC_OCW2_R = 0x80, + + PIC_OCW3_RIS = 0x01, + PIC_OCW3_RR = 0x02, + PIC_OCW3_P = 0x04, + PIC_OCW3_SMM = 0x20, + PIC_OCW3_ESMM = 0x40 +}; + +#if defined(NP2_WIN) +static int pic_cs_initialized = 0; +static CRITICAL_SECTION pic_cs; +#else + // TODO: 非Windows用コードを書く +#endif + +static void pic_enter_criticalsection(void){ +#if defined(NP2_WIN) + if(!pic_cs_initialized) return; + EnterCriticalSection(&pic_cs); +#else + // TODO: 非Windows用コードを書く +#endif +} +static void pic_leave_criticalsection(void){ +#if defined(NP2_WIN) + if(!pic_cs_initialized) return; + LeaveCriticalSection(&pic_cs); +#else + // TODO: 非Windows用コードを書く +#endif +} + +static const _PICITEM def_master = { + {0x11, 0x08, 0x80, 0x1d}, + 0x7d, 0, 0, 0, 0, 0}; + +static const _PICITEM def_slave = { + {0x11, 0x10, 0x07, 0x09}, + 0x71, 0, 0, 0, 0, 0}; + + +// ---- + +#if 0 // スレーブがおかしい… +void pic_irq(void) { + + PIC p; + REG8 mir; + REG8 sir; + REG8 dat; + REG8 num; + REG8 bit; + REG8 slave; + + // 割込み許可? + if (!CPU_isEI) { + return; + } + p = &pic; + + mir = p->pi[0].irr & (~p->pi[0].imr); + sir = p->pi[1].irr & (~p->pi[1].imr); + if ((mir == 0) && (sir == 0)) { + return; + } + + slave = 1 << (p->pi[1].icw[2] & 7); + dat = mir; + if (sir) { + dat |= slave & (~p->pi[0].imr); + } + if (!(p->pi[0].ocw3 & PIC_OCW3_SMM)) { + dat |= p->pi[0].isr; + } + num = p->pi[0].pry; + bit = 1 << num; + while(!(dat & bit)) { + num = (num + 1) & 7; + bit = 1 << num; + } + if (p->pi[0].icw[2] & bit) { // スレーヴ + dat = sir; + if (!(p->pi[1].ocw3 & PIC_OCW3_SMM)) { + dat |= p->pi[1].isr; + } + num = p->pi[1].pry; + bit = 1 << num; + while(!(dat & bit)) { + num = (num + 1) & 7; + bit = 1 << num; + } + if (!(p->pi[1].isr & bit)) { + p->pi[0].isr |= slave; + p->pi[0].irr &= ~slave; + p->pi[1].isr |= bit; + p->pi[1].irr &= ~bit; + TRACEOUT(("hardware-int %.2x", (p->pi[1].icw[1] & 0xf8) | num)); + CPU_INTERRUPT((REG8)((p->pi[1].icw[1] & 0xf8) | num), 0); + } + } + else if (!(p->pi[0].isr & bit)) { // マスター + p->pi[0].isr |= bit; + p->pi[0].irr &= ~bit; + if (num == 0) { + nevent_reset(NEVENT_PICMASK); + } + TRACEOUT(("hardware-int %.2x [%.4x:%.4x]", (p->pi[0].icw[1] & 0xf8) | num, CPU_CS, CPU_IP)); + CPU_INTERRUPT((REG8)((p->pi[0].icw[1] & 0xf8) | num), 0); + } +} +#else +void pic_irq(void) { // ver0.78 + + PIC p; + REG8 mir; + REG8 sir; + REG8 num; + REG8 bit; + REG8 slave; + UINT8 intrtmp; + + // 割込み許可? +#if defined(SUPPORT_IA32_HAXM) + if (!np2hax.emumode && np2hax.enable && CPU_STAT_PM) { + // workaround + //if (!(np2haxstat.state._eflags & I_FLAG)) { + // return; + //} + }else +#endif + if (!CPU_isEI) { + return; + } + p = &pic; + + pic_enter_criticalsection(); + sir = p->pi[1].irr & (~p->pi[1].imr); + slave = 1 << (p->pi[1].icw[2] & 7); + mir = p->pi[0].irr; + if (sir) { + mir |= slave; + } + mir &= (~p->pi[0].imr); + if (mir == 0) { + pic_leave_criticalsection(); + return; + } + if (!(p->pi[0].ocw3 & PIC_OCW3_SMM)) { + mir |= p->pi[0].isr; + } + num = p->pi[0].pry; + bit = 1 << num; + while(!(mir & bit)) { + num = (num + 1) & 7; + bit = 1 << num; + } + if (p->pi[0].icw[2] & bit) { // スレーヴ + if (sir == 0) { + pic_leave_criticalsection(); + return; + } + if (!(p->pi[1].ocw3 & PIC_OCW3_SMM)) { + sir |= p->pi[1].isr; + } + num = p->pi[1].pry; + bit = 1 << num; + while(!(sir & bit)) { + num = (num + 1) & 7; + bit = 1 << num; + } + if (!(p->pi[1].isr & bit)) { + p->pi[0].isr |= slave; + p->pi[0].irr &= ~slave; + p->pi[1].isr |= bit; + p->pi[1].irr &= ~bit; +// TRACEOUT(("hardware-int %.2x", (p->pi[1].icw[1] & 0xf8) | num)); + intrtmp = (p->pi[1].icw[1] & 0xf8) | num; + pic_leave_criticalsection(); + CPU_INTERRUPT((REG8)intrtmp, 0); + }else{ + pic_leave_criticalsection(); + } + } + else if (!(p->pi[0].isr & bit)) { // マスター + p->pi[0].isr |= bit; + p->pi[0].irr &= ~bit; + if (num == 0) { + nevent_reset(NEVENT_PICMASK); + } +// TRACEOUT(("hardware-int %.2x [%.4x:%.4x]", (p->pi[0].icw[1] & 0xf8) | num, CPU_CS, CPU_IP)); + intrtmp = (p->pi[0].icw[1] & 0xf8) | num; + pic_leave_criticalsection(); + CPU_INTERRUPT((REG8)intrtmp, 0); + }else{ + pic_leave_criticalsection(); + } +} +#endif + + +// 簡易モード(SYSTEM TIMERだけ) +void picmask(NEVENTITEM item) { + + PICITEM pi; + + pic_enter_criticalsection(); + if (item->flag & NEVENT_SETEVENT) { + pi = &pic.pi[0]; + pi->irr &= ~(pi->imr & PIC_SYSTEMTIMER); + } + pic_leave_criticalsection(); +} + +void pic_setirq(REG8 irq) { + + PICITEM pi; + REG8 bit; + + pic_enter_criticalsection(); + pi = pic.pi; + bit = 1 << (irq & 7); + if (!(irq & 8)) { + pi[0].irr |= bit; + if (pi[0].imr & bit) { + if (bit & PIC_SYSTEMTIMER) { + if ((pit.ch[0].ctrl & 0x0c) == 0x04) { + SINT32 cnt; // ver0.29 + if (pit.ch[0].value > 8) { + cnt = pccore.multiple * pit.ch[0].value; + cnt >>= 2; + } + else { + cnt = pccore.multiple << (16 - 2); + } + nevent_set(NEVENT_PICMASK, cnt, picmask, NEVENT_ABSOLUTE); + } + } + } + if (pi[0].isr & bit) { + if (bit & PIC_CRTV) { + pi[0].irr &= ~PIC_CRTV; + gdc.vsyncint = 1; + } + } + } + else { + pi[1].irr |= bit; + } + pic_leave_criticalsection(); +} + +void pic_resetirq(REG8 irq) { + + PICITEM pi; + + pic_enter_criticalsection(); + pi = pic.pi + ((irq >> 3) & 1); + pi->irr &= ~(1 << (irq & 7)); + pic_leave_criticalsection(); +} + + +// ---- I/O + +static void IOOUTCALL pic_o00(UINT port, REG8 dat) { + + PICITEM picp; + REG8 level; + UINT8 ocw3; + + pic_enter_criticalsection(); +// TRACEOUT(("pic %x %x", port, dat)); + picp = &pic.pi[(port >> 3) & 1]; + picp->writeicw = 0; + switch(dat & 0x18) { + case 0x00: // ocw2 + if (dat & PIC_OCW2_SL) { + level = dat & PIC_OCW2_L; + } + else { + if (!picp->isr) { + break; + } + level = picp->pry; + while(!(picp->isr & (1 << level))) { + level = (level + 1) & 7; + } + } + if (dat & PIC_OCW2_R) { + picp->pry = (level + 1) & 7; + } + if (dat & PIC_OCW2_EOI) { + picp->isr &= ~(1 << level); + } + nevent_forceexit(); // mainloop exit + break; + + case 0x08: // ocw3 + ocw3 = picp->ocw3; + if (!(dat & PIC_OCW3_RR)) { + dat &= PIC_OCW3_RIS; + dat |= (ocw3 & PIC_OCW3_RIS); + } + if (!(dat & PIC_OCW3_ESMM)) { + dat &= ~PIC_OCW3_SMM; + dat |= (ocw3 & PIC_OCW3_SMM); + } + picp->ocw3 = dat; + break; + + default: + picp->icw[0] = dat; + picp->imr = 0; + picp->irr = 0; + picp->ocw3 = 0; +#if 0 + picp->levels = 0; + picp->isr = 0; +#endif + picp->pry = 0; + picp->writeicw = 1; + break; + } + pic_leave_criticalsection(); +} + +static void IOOUTCALL pic_o02(UINT port, REG8 dat) { + + PICITEM picp; + + pic_enter_criticalsection(); +// TRACEOUT(("pic %x %x", port, dat)); + picp = &pic.pi[(port >> 3) & 1]; + if (!picp->writeicw) { +#if 1 + UINT8 set; + set = picp->imr & (~dat); + // リセットされたビットは割り込みある? + if ((CPU_isDI) || (!(picp->irr & set))) { + picp->imr = dat; + pic_leave_criticalsection(); + return; + } +#endif + picp->imr = dat; + } + else { + picp->icw[picp->writeicw] = dat; + picp->writeicw++; + if (picp->writeicw >= (3 + (picp->icw[0] & 1))) { + picp->writeicw = 0; + } + } + pic_leave_criticalsection(); + nevent_forceexit(); +} + +static REG8 IOINPCALL pic_i00(UINT port) { + + PICITEM picp; + + picp = &pic.pi[(port >> 3) & 1]; + if (!(picp->ocw3 & PIC_OCW3_RIS)) { + return(picp->irr); // read irr + } + else { + return(picp->isr); // read isr + } +} + +static REG8 IOINPCALL pic_i02(UINT port) { + + PICITEM picp; + + picp = &pic.pi[(port >> 3) & 1]; + return(picp->imr); +} + + +// ---- I/F + +#if !defined(SUPPORT_PC9821) +static const IOOUT pico00[2] = { + pic_o00, pic_o02}; + +static const IOINP pici00[2] = { + pic_i00, pic_i02}; +#else +static const IOOUT pico00[4] = { + pic_o00, pic_o02, NULL, NULL}; + +static const IOINP pici00[4] = { + pic_i00, pic_i02, NULL, NULL}; +#endif + +void pic_initialize(void) { +#if defined(NP2_WIN) + if(!pic_cs_initialized){ + memset(&pic_cs, 0, sizeof(pic_cs)); + InitializeCriticalSection(&pic_cs); + pic_cs_initialized = 1; + } +#else + // TODO: 非Windows用コードを書く +#endif +} + +void pic_deinitialize(void) { +#if defined(NP2_WIN) + if(pic_cs_initialized){ + DeleteCriticalSection(&pic_cs); + pic_cs_initialized = 0; + } +#else + // TODO: 非Windows用コードを書く +#endif +} + +void pic_reset(const NP2CFG *pConfig) { + + pic.pi[0] = def_master; + pic.pi[1] = def_slave; + + (void)pConfig; +} + +void pic_bind(void) { + +#if !defined(SUPPORT_PC9821) + iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 2); + iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 2); +#else + iocore_attachsysoutex(0x0000, 0x0cf1, pico00, 4); + iocore_attachsysinpex(0x0000, 0x0cf1, pici00, 4); +#endif +} + diff --git a/io/pic.h b/io/pic.h old mode 100755 new mode 100644 index d03626aa..a1b7aee5 --- a/io/pic.h +++ b/io/pic.h @@ -1,70 +1,70 @@ - -typedef struct { - UINT8 icw[4]; - - UINT8 imr; // ocw1 - UINT8 isr; - UINT8 irr; - UINT8 ocw3; - - UINT8 pry; - UINT8 writeicw; - UINT8 padding[2]; -} _PICITEM, *PICITEM; - - -typedef struct { - _PICITEM pi[2]; -} _PIC, *PIC; - -enum { - PIC_SYSTEMTIMER = 0x01, - PIC_KEYBOARD = 0x02, - PIC_CRTV = 0x04, - PIC_INT0 = 0x08, - PIC_RS232C = 0x10, - PIC_INT1 = 0x20, - PIC_INT2 = 0x40, - PIC_SLAVE = 0x80, - - PIC_PRINTER = 0x01, - PIC_INT3 = 0x02, - PIC_INT41 = 0x04, - PIC_INT42 = 0x08, - PIC_INT5 = 0x10, - PIC_INT6 = 0x20, - PIC_NDP = 0x40, - - IRQ_INT0 = 0x03, - IRQ_INT1 = 0x05, - IRQ_INT2 = 0x06, - IRQ_INT3 = 0x09, - IRQ_INT41 = 0x0a, - IRQ_INT42 = 0x0b, - IRQ_INT5 = 0x0c, - IRQ_INT6 = 0x0d -}; - -#define PICEXISTINTR ((pic.pi[0].irr & (~pic.pi[0].imr)) || \ - (pic.pi[1].irr & (~pic.pi[1].imr))) - - -#ifdef __cplusplus -extern "C" { -#endif - -void pic_irq(void); -void pic_setirq(REG8 irq); -void pic_resetirq(REG8 irq); - -void picmask(NEVENTITEM item); - -void pic_initialize(void); -void pic_deinitialize(void); -void pic_reset(const NP2CFG *pConfig); -void pic_bind(void); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + UINT8 icw[4]; + + UINT8 imr; // ocw1 + UINT8 isr; + UINT8 irr; + UINT8 ocw3; + + UINT8 pry; + UINT8 writeicw; + UINT8 padding[2]; +} _PICITEM, *PICITEM; + + +typedef struct { + _PICITEM pi[2]; +} _PIC, *PIC; + +enum { + PIC_SYSTEMTIMER = 0x01, + PIC_KEYBOARD = 0x02, + PIC_CRTV = 0x04, + PIC_INT0 = 0x08, + PIC_RS232C = 0x10, + PIC_INT1 = 0x20, + PIC_INT2 = 0x40, + PIC_SLAVE = 0x80, + + PIC_PRINTER = 0x01, + PIC_INT3 = 0x02, + PIC_INT41 = 0x04, + PIC_INT42 = 0x08, + PIC_INT5 = 0x10, + PIC_INT6 = 0x20, + PIC_NDP = 0x40, + + IRQ_INT0 = 0x03, + IRQ_INT1 = 0x05, + IRQ_INT2 = 0x06, + IRQ_INT3 = 0x09, + IRQ_INT41 = 0x0a, + IRQ_INT42 = 0x0b, + IRQ_INT5 = 0x0c, + IRQ_INT6 = 0x0d +}; + +#define PICEXISTINTR ((pic.pi[0].irr & (~pic.pi[0].imr)) || \ + (pic.pi[1].irr & (~pic.pi[1].imr))) + + +#ifdef __cplusplus +extern "C" { +#endif + +void pic_irq(void); +void pic_setirq(REG8 irq); +void pic_resetirq(REG8 irq); + +void picmask(NEVENTITEM item); + +void pic_initialize(void); +void pic_deinitialize(void); +void pic_reset(const NP2CFG *pConfig); +void pic_bind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/pit.c b/io/pit.c old mode 100755 new mode 100644 index fa179978..3e32d4f2 --- a/io/pit.c +++ b/io/pit.c @@ -1,547 +1,547 @@ -// -// μPD8253C タイマLSI -// - -#include -#include -#include -#include -#include -#include -#include -#include - -extern COMMNG cm_rs232c; - -#define BEEPCOUNTEREX // BEEPアイドル時のカウンタをα倍に -#if defined(CPUCORE_IA32) -#define uPD71054 -#endif - - -// --- Interval timer - -static void setsystimerevent(UINT32 cnt, NEVENTPOSITION absolute) { - - PITCH pitch; - pitch = pit.ch + 0; - if (cnt > 8) { // 根拠なし - cnt *= pccore.multiple; - } - else { - cnt = pccore.multiple << 16; - } - nevent_set(NEVENT_ITIMER, cnt, systimer, absolute); -} - -void systimer(NEVENTITEM item) { - - PITCH pitch; - - if (item->flag & NEVENT_SETEVENT) { - pitch = pit.ch + 0; - if (pitch->flag & PIT_FLAG_I) { - pitch->flag &= ~PIT_FLAG_I; - pic_setirq(0); - } - if ((pitch->ctrl & 0x0c) == 0x04) { - // レートジェネレータ - pitch->flag |= PIT_FLAG_I; - setsystimerevent(pitch->value, NEVENT_RELATIVE); - } - else { - setsystimerevent(0, NEVENT_RELATIVE); - } - } -} - - -// --- Beep - -#if defined(BEEPCOUNTEREX) -static void setbeepeventex(UINT32 cnt, NEVENTPOSITION absolute) { - - if (cnt > 2) { - cnt *= pccore.multiple; - } - else { - cnt = pccore.multiple << 16; - } - while(cnt < 0x100000) { - cnt <<= 1; - } - nevent_set(NEVENT_BEEP, (SINT32)cnt, beeponeshot, absolute); -} -#endif - -static void setbeepevent(UINT32 cnt, NEVENTPOSITION absolute) { - - if (cnt > 2) { - cnt *= pccore.multiple; - } - else { - cnt = pccore.multiple << 16; - } - nevent_set(NEVENT_BEEP, cnt, beeponeshot, absolute); -} - -void beeponeshot(NEVENTITEM item) { - - PITCH pitch; - - if (item->flag & NEVENT_SETEVENT) { - pitch = pit.ch + 1; - if (!(pitch->ctrl & 0x0c)) { - beep_lheventset(0); - } -#if defined(uPD71054) - if ((pitch->ctrl & 0x06) == 0x02) -#else - if (pitch->ctrl & 0x02) -#endif - { -#if defined(BEEPCOUNTEREX) - setbeepeventex(pitch->value, NEVENT_RELATIVE); -#else - setbeepevent(pitch->value, NEVENT_RELATIVE); -#endif - } - } -} - - -// --- RS-232C - -static void setrs232cevent(UINT32 cnt, NEVENTPOSITION absolute) { - - if (cnt > 1) { - cnt *= pccore.multiple; - } - else { - cnt = pccore.multiple << 16; - } - cnt *= rs232c.mul; - nevent_set(NEVENT_RS232C, cnt, rs232ctimer, absolute); -} - -void rs232ctimer(NEVENTITEM item) { - - PITCH pitch; - - if (item->flag & NEVENT_SETEVENT) { - pitch = pit.ch + 2; - if (pitch->flag & PIT_FLAG_I) { - //pitch->flag &= ‾PIT_FLAG_I; - rs232c_callback(); - } -#if defined(SUPPORT_RS232C_FIFO) - if (rs232cfifo.vfast & 0x80) { - // V FASTモード - int speedtbl[16] = { - 0, 115200, 57600, 38400, - 28800, 0, 19200, 0, - 14400, 0, 0, 0, - 9600, 0, 0, 0, - }; - int speed; - speed = speedtbl[rs232cfifo.vfast & 0xf]; - if(speed != 0){ - nevent_set(NEVENT_RS232C, pccore.realclock * 8 / speed, rs232ctimer, NEVENT_RELATIVE); - }else{ - nevent_set(NEVENT_RS232C, pccore.realclock * 8 / 9600, rs232ctimer, NEVENT_RELATIVE); - } - }else -#endif - if ((pitch->ctrl & 0x0c) == 0x04) { - // レートジェネレータ - setrs232cevent(pitch->value, NEVENT_RELATIVE); - } - else { - setrs232cevent(0, NEVENT_RELATIVE); - } - } -} - - -// --------------------------------------------------------------------------- - -static UINT getcount(const _PITCH *pitch) { - - SINT32 clk; - - switch(pitch->ch) { - case 0: - clk = nevent_getremain(NEVENT_ITIMER); - break; - - case 1: - switch(pitch->ctrl & 0x06) { -#ifdef uPD71054 // ? -// case 0x00: -#endif - case 0x04: - return(pitch->value); -#ifdef uPD71054 - case 0x06: - return(pitch->value & (~1)); -#endif - } - clk = nevent_getremain(NEVENT_BEEP); -#if defined(BEEPCOUNTEREX) - if (clk >= 0) { - clk /= pccore.multiple; - if (pitch->value > 2) { - clk %= pitch->value; - } - else { - clk = LOW16(clk); - } - return(clk); - } -#else - break; -#endif - - case 2: - clk = nevent_getremain(NEVENT_RS232C); - break; - -#if !defined(DISABLE_SOUND) - case 3: - return(board14_pitcount()); -#endif - - default: - clk = 0; - break; - } - if (clk > 0) { - return(clk / pccore.multiple); - } - return(0); -} - -static void latchcmd(PITCH pitch, REG8 ctrl) { - - UINT8 flag; - - flag = pitch->flag; - if (!(ctrl & PIT_LATCH_S)) { - flag |= PIT_FLAG_S; - pitch->stat = pitch->ctrl; - } - if (!(ctrl & PIT_LATCH_C)) { - flag |= PIT_FLAG_C; - flag &= ~PIT_FLAG_L; - pitch->latch = getcount(pitch); - } - pitch->flag = flag; -} - - -// ---- - -void pit_setflag(PITCH pitch, REG8 value) { - - if (value & PIT_CTRL_RL) { - pitch->ctrl = (UINT8)((value & 0x3f) | PIT_STAT_CMD); - pitch->flag &= ~(PIT_FLAG_R | PIT_FLAG_W | PIT_FLAG_L | - PIT_FLAG_S | PIT_FLAG_C); - } - else { // latch - latchcmd(pitch, ~PIT_LATCH_C); - } -} - -// RS-232C通信速度設定 関連: serial.c rs232c_vfast_setrs232cspeed -void pit_setrs232cspeed(UINT16 value) { - if (cm_rs232c) { -#if defined(SUPPORT_RS232C_FIFO) - if(!(rs232cfifo.vfast & 0x80)) // V FASTモードでは通信速度変更しない -#endif - { - if(value > 0){ - if ((pccore.dipsw[0] & 0x30)==0x30) { // とりあえず調歩同期だけ - int newvalue; - int mul[] = {1, 1, 16, 64}; - if (pccore.cpumode & CPUMODE_8MHZ) { - newvalue = 9600 * 208 / mul[rs232c.rawmode & 0x3] / value; - }else{ - newvalue = 9600 * 256 / mul[rs232c.rawmode & 0x3] / value; - } - if(newvalue <= 38400){ // XXX: 大きすぎるのは無視 - cm_rs232c->msg(cm_rs232c, COMMSG_CHANGESPEED, (INTPTR)&newvalue); - } - } - } - } - cm_rs232c->msg(cm_rs232c, COMMSG_CHANGEMODE, (INTPTR)&rs232c.rawmode); - } -} - -BOOL pit_setcount(PITCH pitch, REG8 value) { - - UINT8 flag; - - switch(pitch->ctrl & PIT_CTRL_RL) { - case PIT_RL_L: // access low - pitch->value = value; - break; - - case PIT_RL_H: // access high - pitch->value = value << 8; - break; - - case PIT_RL_ALL: // access word - flag = pitch->flag; - pitch->flag = flag ^ PIT_FLAG_W; - if (!(flag & PIT_FLAG_W)) { - pitch->value &= 0xff00; - pitch->value += value; - return(TRUE); - } - pitch->value &= 0x00ff; - pitch->value += value << 8; - break; - } - pitch->ctrl &= ~PIT_STAT_CMD; - if (((pitch->ctrl & 0x06) == 0x02) && (pitch->flag & PIT_FLAG_I)) { - return(TRUE); - } - return(FALSE); -} - -REG8 pit_getstat(PITCH pitch) { - - UINT8 flag; - UINT8 rl; - UINT16 w; - REG8 ret; - - flag = pitch->flag; -#if defined(uPD71054) - if (flag & PIT_FLAG_S) { - flag &= ~PIT_FLAG_S; - ret = pitch->stat; - } - else -#endif - { - rl = pitch->ctrl & PIT_CTRL_RL; - if (flag & (PIT_FLAG_C | PIT_FLAG_L)) { - flag &= ~PIT_FLAG_C; - if (rl == PIT_RL_ALL) { - flag ^= PIT_FLAG_L; - } - w = pitch->latch; - } - else { - w = getcount(pitch); - } - switch(rl) { - case PIT_RL_L: // access low - ret = (UINT8)w; - break; - - case PIT_RL_H: - ret = (UINT8)(w >> 8); - break; - - case PIT_RL_ALL: - default: - if (!(flag & PIT_FLAG_R)) { - ret = (UINT8)w; - } - else { - ret = (UINT8)(w >> 8); - } - flag ^= PIT_FLAG_R; - break; - } - } - pitch->flag = flag; - return(ret); -} - - -// ---- I/O - -// system timer -static void IOOUTCALL pit_o71(UINT port, REG8 dat) { - - PITCH pitch; - - pitch = pit.ch + 0; - if (pit_setcount(pitch, dat)) { - return; - } - pic.pi[0].irr &= (~1); - pitch->flag |= PIT_FLAG_I; - setsystimerevent(pitch->value, NEVENT_ABSOLUTE); - (void)port; -} - -static int beep_mode_bit = 0; -static int beep_mode_bit_c = 0; - -// beep -static void IOOUTCALL pit_o73(UINT port, REG8 dat) { - - PITCH pitch; - - if(g_beep.mode == 0) { - switch(beep_mode_bit) { - case 0: - beep_data[g_beep.beep_data_load_loc] = dat; - break; - case 1: - beep_data[g_beep.beep_data_load_loc] = dat << 8; - break; - case 2: - if(beep_mode_bit_c == 0) - beep_data[g_beep.beep_data_load_loc] = dat; - else - beep_data[g_beep.beep_data_load_loc] += dat << 8; - break; - } - beep_time[g_beep.beep_data_load_loc] = CPU_CLOCK; - if(!(beep_mode_bit == 2 && beep_mode_bit_c == 0)) { - g_beep.beep_data_load_loc++; - if(g_beep.beep_data_load_loc >= BEEPDATACOUNT) - g_beep.beep_data_load_loc = 0; - g_beep.beep_laskclk = CPU_CLOCK; - } - beep_mode_bit_c ^= 1; - } - - pitch = pit.ch + 1; - if (pit_setcount(pitch, dat)) { - return; - } - setbeepevent(pitch->value, NEVENT_ABSOLUTE); - beep_lheventset(1); // ver0.79 - if (pitch->ctrl & 0x0c) { - beep_hzset(pitch->value); - } -} - -// rs-232c -static void IOOUTCALL pit_o75(UINT port, REG8 dat) { - - PITCH pitch; - UINT16 oldvalue; - - pitch = pit.ch + 2; - oldvalue = pitch->value; - if (pit_setcount(pitch, dat)) { - if(pitch->value != oldvalue){ - pit_setrs232cspeed(pitch->value); - } - return; - } - if(pitch->value != oldvalue){ - pit_setrs232cspeed(pitch->value); - } - pitch->flag |= PIT_FLAG_I; - rs232c_open(); - setrs232cevent(pitch->value, NEVENT_ABSOLUTE); - (void)port; -} - -// ctrl -static void IOOUTCALL pit_o77(UINT port, REG8 dat) { - - UINT chnum; - PITCH pitch; - - if((dat & 0xC0) == 0x40) { - if(CPU_CLOCK - g_beep.beep_laskclk >= 20000000) { - g_beep.beep_data_load_loc = 0; - g_beep.beep_data_curr_loc = 0; - } - beep_mode_bit = ((dat >> 4) & 3) - 1; - beep_mode_bit_c = 0; - } - - chnum = (dat >> 6) & 3; - if (chnum != 3) { - pitch = pit.ch + chnum; - pit_setflag(pitch, dat); - if (chnum == 0) { // 書込みで itimerのirrがリセットされる… - pic.pi[0].irr &= (~1); - if (dat & 0x30) { // 一応ラッチ時は割り込みをセットしない - pitch->flag |= PIT_FLAG_I; - } - } - if (chnum == 1) { - beep_modeset(); - } - } -#if defined(uPD71054) - else { - TRACEOUT(("multiple latch commands - %x", dat)); - for (chnum=0; chnum<3; chnum++) { - if (dat & (2 << chnum)) { - latchcmd(pit.ch + chnum, dat); - } - } - } -#endif - (void)port; -} - -static REG8 IOINPCALL pit_i71(UINT port) { - - return(pit_getstat(pit.ch + ((port >> 1) & 3))); -} - - -// ---- I/F - -static const IOOUT pito71[4] = { - pit_o71, pit_o73, pit_o75, pit_o77}; - -static const IOINP piti71[4] = { - pit_i71, pit_i71, pit_i71, NULL}; - -void itimer_reset(const NP2CFG *pConfig) { - - UINT16 beepcnt; - - ZeroMemory(&pit, sizeof(pit)); - beepcnt = (pccore.cpumode & CPUMODE_8MHZ)?998:1229; - pit.ch[0].ctrl = 0x30; - pit.ch[0].ch = 0; - pit.ch[0].flag = PIT_FLAG_I; - pit.ch[0].ctrl = 0x56 & 0x3f; - pit.ch[1].ch = 1; - pit.ch[1].value = beepcnt; - pit.ch[2].ctrl = 0xb6 & 0x3f; - pit.ch[2].ch = 2; -#if !defined(DISABLE_SOUND) - pit.ch[3].ctrl = 0x36; - pit.ch[3].ch = 3; - pit.ch[4].ctrl = 0x36; - pit.ch[4].ch = 4; -#endif - setsystimerevent(0, NEVENT_ABSOLUTE); - beep_lheventset(1); // ver0.79 - beep_hzset(beepcnt); -// setrs232cevent(0, NEVENT_ABSOLUTE); - - (void)pConfig; -} - -void itimer_bind(void) { - - iocore_attachsysoutex(0x0071, 0x0cf1, pito71, 4); - iocore_attachsysinpex(0x0071, 0x0cf1, piti71, 4); - iocore_attachout(0x3fd9, pit_o71); - iocore_attachout(0x3fdb, pit_o73); - iocore_attachout(0x3fdd, pit_o75); - iocore_attachout(0x3fdf, pit_o77); - iocore_attachinp(0x3fd9, pit_i71); - iocore_attachinp(0x3fdb, pit_i71); - iocore_attachinp(0x3fdd, pit_i71); -} - +// +// μPD8253C タイマLSI +// + +#include +#include +#include +#include +#include +#include +#include +#include + +extern COMMNG cm_rs232c; + +#define BEEPCOUNTEREX // BEEPアイドル時のカウンタをα倍に +#if defined(CPUCORE_IA32) +#define uPD71054 +#endif + + +// --- Interval timer + +static void setsystimerevent(UINT32 cnt, NEVENTPOSITION absolute) { + + PITCH pitch; + pitch = pit.ch + 0; + if (cnt > 8) { // 根拠なし + cnt *= pccore.multiple; + } + else { + cnt = pccore.multiple << 16; + } + nevent_set(NEVENT_ITIMER, cnt, systimer, absolute); +} + +void systimer(NEVENTITEM item) { + + PITCH pitch; + + if (item->flag & NEVENT_SETEVENT) { + pitch = pit.ch + 0; + if (pitch->flag & PIT_FLAG_I) { + pitch->flag &= ~PIT_FLAG_I; + pic_setirq(0); + } + if ((pitch->ctrl & 0x0c) == 0x04) { + // レートジェネレータ + pitch->flag |= PIT_FLAG_I; + setsystimerevent(pitch->value, NEVENT_RELATIVE); + } + else { + setsystimerevent(0, NEVENT_RELATIVE); + } + } +} + + +// --- Beep + +#if defined(BEEPCOUNTEREX) +static void setbeepeventex(UINT32 cnt, NEVENTPOSITION absolute) { + + if (cnt > 2) { + cnt *= pccore.multiple; + } + else { + cnt = pccore.multiple << 16; + } + while(cnt < 0x100000) { + cnt <<= 1; + } + nevent_set(NEVENT_BEEP, (SINT32)cnt, beeponeshot, absolute); +} +#endif + +static void setbeepevent(UINT32 cnt, NEVENTPOSITION absolute) { + + if (cnt > 2) { + cnt *= pccore.multiple; + } + else { + cnt = pccore.multiple << 16; + } + nevent_set(NEVENT_BEEP, cnt, beeponeshot, absolute); +} + +void beeponeshot(NEVENTITEM item) { + + PITCH pitch; + + if (item->flag & NEVENT_SETEVENT) { + pitch = pit.ch + 1; + if (!(pitch->ctrl & 0x0c)) { + beep_lheventset(0); + } +#if defined(uPD71054) + if ((pitch->ctrl & 0x06) == 0x02) +#else + if (pitch->ctrl & 0x02) +#endif + { +#if defined(BEEPCOUNTEREX) + setbeepeventex(pitch->value, NEVENT_RELATIVE); +#else + setbeepevent(pitch->value, NEVENT_RELATIVE); +#endif + } + } +} + + +// --- RS-232C + +static void setrs232cevent(UINT32 cnt, NEVENTPOSITION absolute) { + + if (cnt > 1) { + cnt *= pccore.multiple; + } + else { + cnt = pccore.multiple << 16; + } + cnt *= rs232c.mul; + nevent_set(NEVENT_RS232C, cnt, rs232ctimer, absolute); +} + +void rs232ctimer(NEVENTITEM item) { + + PITCH pitch; + + if (item->flag & NEVENT_SETEVENT) { + pitch = pit.ch + 2; + if (pitch->flag & PIT_FLAG_I) { + //pitch->flag &= ‾PIT_FLAG_I; + rs232c_callback(); + } +#if defined(SUPPORT_RS232C_FIFO) + if (rs232cfifo.vfast & 0x80) { + // V FASTモード + int speedtbl[16] = { + 0, 115200, 57600, 38400, + 28800, 0, 19200, 0, + 14400, 0, 0, 0, + 9600, 0, 0, 0, + }; + int speed; + speed = speedtbl[rs232cfifo.vfast & 0xf]; + if(speed != 0){ + nevent_set(NEVENT_RS232C, pccore.realclock * 8 / speed, rs232ctimer, NEVENT_RELATIVE); + }else{ + nevent_set(NEVENT_RS232C, pccore.realclock * 8 / 9600, rs232ctimer, NEVENT_RELATIVE); + } + }else +#endif + if ((pitch->ctrl & 0x0c) == 0x04) { + // レートジェネレータ + setrs232cevent(pitch->value, NEVENT_RELATIVE); + } + else { + setrs232cevent(0, NEVENT_RELATIVE); + } + } +} + + +// --------------------------------------------------------------------------- + +static UINT getcount(const _PITCH *pitch) { + + SINT32 clk; + + switch(pitch->ch) { + case 0: + clk = nevent_getremain(NEVENT_ITIMER); + break; + + case 1: + switch(pitch->ctrl & 0x06) { +#ifdef uPD71054 // ? +// case 0x00: +#endif + case 0x04: + return(pitch->value); +#ifdef uPD71054 + case 0x06: + return(pitch->value & (~1)); +#endif + } + clk = nevent_getremain(NEVENT_BEEP); +#if defined(BEEPCOUNTEREX) + if (clk >= 0) { + clk /= pccore.multiple; + if (pitch->value > 2) { + clk %= pitch->value; + } + else { + clk = LOW16(clk); + } + return(clk); + } +#else + break; +#endif + + case 2: + clk = nevent_getremain(NEVENT_RS232C); + break; + +#if !defined(DISABLE_SOUND) + case 3: + return(board14_pitcount()); +#endif + + default: + clk = 0; + break; + } + if (clk > 0) { + return(clk / pccore.multiple); + } + return(0); +} + +static void latchcmd(PITCH pitch, REG8 ctrl) { + + UINT8 flag; + + flag = pitch->flag; + if (!(ctrl & PIT_LATCH_S)) { + flag |= PIT_FLAG_S; + pitch->stat = pitch->ctrl; + } + if (!(ctrl & PIT_LATCH_C)) { + flag |= PIT_FLAG_C; + flag &= ~PIT_FLAG_L; + pitch->latch = getcount(pitch); + } + pitch->flag = flag; +} + + +// ---- + +void pit_setflag(PITCH pitch, REG8 value) { + + if (value & PIT_CTRL_RL) { + pitch->ctrl = (UINT8)((value & 0x3f) | PIT_STAT_CMD); + pitch->flag &= ~(PIT_FLAG_R | PIT_FLAG_W | PIT_FLAG_L | + PIT_FLAG_S | PIT_FLAG_C); + } + else { // latch + latchcmd(pitch, ~PIT_LATCH_C); + } +} + +// RS-232C通信速度設定 関連: serial.c rs232c_vfast_setrs232cspeed +void pit_setrs232cspeed(UINT16 value) { + if (cm_rs232c) { +#if defined(SUPPORT_RS232C_FIFO) + if(!(rs232cfifo.vfast & 0x80)) // V FASTモードでは通信速度変更しない +#endif + { + if(value > 0){ + if ((pccore.dipsw[0] & 0x30)==0x30) { // とりあえず調歩同期だけ + int newvalue; + int mul[] = {1, 1, 16, 64}; + if (pccore.cpumode & CPUMODE_8MHZ) { + newvalue = 9600 * 208 / mul[rs232c.rawmode & 0x3] / value; + }else{ + newvalue = 9600 * 256 / mul[rs232c.rawmode & 0x3] / value; + } + if(newvalue <= 38400){ // XXX: 大きすぎるのは無視 + cm_rs232c->msg(cm_rs232c, COMMSG_CHANGESPEED, (INTPTR)&newvalue); + } + } + } + } + cm_rs232c->msg(cm_rs232c, COMMSG_CHANGEMODE, (INTPTR)&rs232c.rawmode); + } +} + +BOOL pit_setcount(PITCH pitch, REG8 value) { + + UINT8 flag; + + switch(pitch->ctrl & PIT_CTRL_RL) { + case PIT_RL_L: // access low + pitch->value = value; + break; + + case PIT_RL_H: // access high + pitch->value = value << 8; + break; + + case PIT_RL_ALL: // access word + flag = pitch->flag; + pitch->flag = flag ^ PIT_FLAG_W; + if (!(flag & PIT_FLAG_W)) { + pitch->value &= 0xff00; + pitch->value += value; + return(TRUE); + } + pitch->value &= 0x00ff; + pitch->value += value << 8; + break; + } + pitch->ctrl &= ~PIT_STAT_CMD; + if (((pitch->ctrl & 0x06) == 0x02) && (pitch->flag & PIT_FLAG_I)) { + return(TRUE); + } + return(FALSE); +} + +REG8 pit_getstat(PITCH pitch) { + + UINT8 flag; + UINT8 rl; + UINT16 w; + REG8 ret; + + flag = pitch->flag; +#if defined(uPD71054) + if (flag & PIT_FLAG_S) { + flag &= ~PIT_FLAG_S; + ret = pitch->stat; + } + else +#endif + { + rl = pitch->ctrl & PIT_CTRL_RL; + if (flag & (PIT_FLAG_C | PIT_FLAG_L)) { + flag &= ~PIT_FLAG_C; + if (rl == PIT_RL_ALL) { + flag ^= PIT_FLAG_L; + } + w = pitch->latch; + } + else { + w = getcount(pitch); + } + switch(rl) { + case PIT_RL_L: // access low + ret = (UINT8)w; + break; + + case PIT_RL_H: + ret = (UINT8)(w >> 8); + break; + + case PIT_RL_ALL: + default: + if (!(flag & PIT_FLAG_R)) { + ret = (UINT8)w; + } + else { + ret = (UINT8)(w >> 8); + } + flag ^= PIT_FLAG_R; + break; + } + } + pitch->flag = flag; + return(ret); +} + + +// ---- I/O + +// system timer +static void IOOUTCALL pit_o71(UINT port, REG8 dat) { + + PITCH pitch; + + pitch = pit.ch + 0; + if (pit_setcount(pitch, dat)) { + return; + } + pic.pi[0].irr &= (~1); + pitch->flag |= PIT_FLAG_I; + setsystimerevent(pitch->value, NEVENT_ABSOLUTE); + (void)port; +} + +static int beep_mode_bit = 0; +static int beep_mode_bit_c = 0; + +// beep +static void IOOUTCALL pit_o73(UINT port, REG8 dat) { + + PITCH pitch; + + if(g_beep.mode == 0) { + switch(beep_mode_bit) { + case 0: + beep_data[g_beep.beep_data_load_loc] = dat; + break; + case 1: + beep_data[g_beep.beep_data_load_loc] = dat << 8; + break; + case 2: + if(beep_mode_bit_c == 0) + beep_data[g_beep.beep_data_load_loc] = dat; + else + beep_data[g_beep.beep_data_load_loc] += dat << 8; + break; + } + beep_time[g_beep.beep_data_load_loc] = CPU_CLOCK; + if(!(beep_mode_bit == 2 && beep_mode_bit_c == 0)) { + g_beep.beep_data_load_loc++; + if(g_beep.beep_data_load_loc >= BEEPDATACOUNT) + g_beep.beep_data_load_loc = 0; + g_beep.beep_laskclk = CPU_CLOCK; + } + beep_mode_bit_c ^= 1; + } + + pitch = pit.ch + 1; + if (pit_setcount(pitch, dat)) { + return; + } + setbeepevent(pitch->value, NEVENT_ABSOLUTE); + beep_lheventset(1); // ver0.79 + if (pitch->ctrl & 0x0c) { + beep_hzset(pitch->value); + } +} + +// rs-232c +static void IOOUTCALL pit_o75(UINT port, REG8 dat) { + + PITCH pitch; + UINT16 oldvalue; + + pitch = pit.ch + 2; + oldvalue = pitch->value; + if (pit_setcount(pitch, dat)) { + if(pitch->value != oldvalue){ + pit_setrs232cspeed(pitch->value); + } + return; + } + if(pitch->value != oldvalue){ + pit_setrs232cspeed(pitch->value); + } + pitch->flag |= PIT_FLAG_I; + rs232c_open(); + setrs232cevent(pitch->value, NEVENT_ABSOLUTE); + (void)port; +} + +// ctrl +static void IOOUTCALL pit_o77(UINT port, REG8 dat) { + + UINT chnum; + PITCH pitch; + + if((dat & 0xC0) == 0x40) { + if(CPU_CLOCK - g_beep.beep_laskclk >= 20000000) { + g_beep.beep_data_load_loc = 0; + g_beep.beep_data_curr_loc = 0; + } + beep_mode_bit = ((dat >> 4) & 3) - 1; + beep_mode_bit_c = 0; + } + + chnum = (dat >> 6) & 3; + if (chnum != 3) { + pitch = pit.ch + chnum; + pit_setflag(pitch, dat); + if (chnum == 0) { // 書込みで itimerのirrがリセットされる… + pic.pi[0].irr &= (~1); + if (dat & 0x30) { // 一応ラッチ時は割り込みをセットしない + pitch->flag |= PIT_FLAG_I; + } + } + if (chnum == 1) { + beep_modeset(); + } + } +#if defined(uPD71054) + else { + TRACEOUT(("multiple latch commands - %x", dat)); + for (chnum=0; chnum<3; chnum++) { + if (dat & (2 << chnum)) { + latchcmd(pit.ch + chnum, dat); + } + } + } +#endif + (void)port; +} + +static REG8 IOINPCALL pit_i71(UINT port) { + + return(pit_getstat(pit.ch + ((port >> 1) & 3))); +} + + +// ---- I/F + +static const IOOUT pito71[4] = { + pit_o71, pit_o73, pit_o75, pit_o77}; + +static const IOINP piti71[4] = { + pit_i71, pit_i71, pit_i71, NULL}; + +void itimer_reset(const NP2CFG *pConfig) { + + UINT16 beepcnt; + + ZeroMemory(&pit, sizeof(pit)); + beepcnt = (pccore.cpumode & CPUMODE_8MHZ)?998:1229; + pit.ch[0].ctrl = 0x30; + pit.ch[0].ch = 0; + pit.ch[0].flag = PIT_FLAG_I; + pit.ch[0].ctrl = 0x56 & 0x3f; + pit.ch[1].ch = 1; + pit.ch[1].value = beepcnt; + pit.ch[2].ctrl = 0xb6 & 0x3f; + pit.ch[2].ch = 2; +#if !defined(DISABLE_SOUND) + pit.ch[3].ctrl = 0x36; + pit.ch[3].ch = 3; + pit.ch[4].ctrl = 0x36; + pit.ch[4].ch = 4; +#endif + setsystimerevent(0, NEVENT_ABSOLUTE); + beep_lheventset(1); // ver0.79 + beep_hzset(beepcnt); +// setrs232cevent(0, NEVENT_ABSOLUTE); + + (void)pConfig; +} + +void itimer_bind(void) { + + iocore_attachsysoutex(0x0071, 0x0cf1, pito71, 4); + iocore_attachsysinpex(0x0071, 0x0cf1, piti71, 4); + iocore_attachout(0x3fd9, pit_o71); + iocore_attachout(0x3fdb, pit_o73); + iocore_attachout(0x3fdd, pit_o75); + iocore_attachout(0x3fdf, pit_o77); + iocore_attachinp(0x3fd9, pit_i71); + iocore_attachinp(0x3fdb, pit_i71); + iocore_attachinp(0x3fdd, pit_i71); +} + diff --git a/io/pit.h b/io/pit.h old mode 100755 new mode 100644 index adc6ea28..0b9ee7ab --- a/io/pit.h +++ b/io/pit.h @@ -1,67 +1,67 @@ - -typedef struct { - UINT8 ctrl; - UINT8 ch; - UINT8 flag; - UINT8 stat; - UINT16 value; - UINT16 latch; -} _PITCH, *PITCH; - -#if !defined(DISABLE_SOUND) -typedef struct { - _PITCH ch[5]; -} _PIT, *PIT; -#else -typedef struct { - _PITCH ch[3]; -} _PIT, *PIT; -#endif - -enum { - PIT_CTRL_BCD = 0x01, - PIT_CTRL_MODE = 0x0e, - PIT_CTRL_RL = 0x30, - PIT_CTRL_SC = 0xc0, - - PIT_RL_L = 0x10, - PIT_RL_H = 0x20, - PIT_RL_ALL = 0x30, - - PIT_STAT_CMD = 0x40, - PIT_STAT_INT = 0x80, - - PIT_FLAG_R = 0x01, - PIT_FLAG_W = 0x02, - PIT_FLAG_L = 0x04, - PIT_FLAG_S = 0x08, - PIT_FLAG_C = 0x10, - PIT_FLAG_I = 0x20, - - PIT_LATCH_S = 0x10, - PIT_LATCH_C = 0x20 -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -void systimer(NEVENTITEM item); -void beeponeshot(NEVENTITEM item); -void rs232ctimer(NEVENTITEM item); - -void pit_setflag(PITCH pitch, REG8 value); -BOOL pit_setcount(PITCH pitch, REG8 value); -UINT pit_getcount(PITCH pitch); -REG8 pit_getstat(PITCH pitch); - -void pit_setrs232cspeed(UINT16 value); - -void itimer_reset(const NP2CFG *pConfig); -void itimer_bind(void); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + UINT8 ctrl; + UINT8 ch; + UINT8 flag; + UINT8 stat; + UINT16 value; + UINT16 latch; +} _PITCH, *PITCH; + +#if !defined(DISABLE_SOUND) +typedef struct { + _PITCH ch[5]; +} _PIT, *PIT; +#else +typedef struct { + _PITCH ch[3]; +} _PIT, *PIT; +#endif + +enum { + PIT_CTRL_BCD = 0x01, + PIT_CTRL_MODE = 0x0e, + PIT_CTRL_RL = 0x30, + PIT_CTRL_SC = 0xc0, + + PIT_RL_L = 0x10, + PIT_RL_H = 0x20, + PIT_RL_ALL = 0x30, + + PIT_STAT_CMD = 0x40, + PIT_STAT_INT = 0x80, + + PIT_FLAG_R = 0x01, + PIT_FLAG_W = 0x02, + PIT_FLAG_L = 0x04, + PIT_FLAG_S = 0x08, + PIT_FLAG_C = 0x10, + PIT_FLAG_I = 0x20, + + PIT_LATCH_S = 0x10, + PIT_LATCH_C = 0x20 +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +void systimer(NEVENTITEM item); +void beeponeshot(NEVENTITEM item); +void rs232ctimer(NEVENTITEM item); + +void pit_setflag(PITCH pitch, REG8 value); +BOOL pit_setcount(PITCH pitch, REG8 value); +UINT pit_getcount(PITCH pitch); +REG8 pit_getstat(PITCH pitch); + +void pit_setrs232cspeed(UINT16 value); + +void itimer_reset(const NP2CFG *pConfig); +void itimer_bind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/printif.c b/io/printif.c old mode 100755 new mode 100644 index e5db8d32..fc0bd62d --- a/io/printif.c +++ b/io/printif.c @@ -1,83 +1,83 @@ -#include -#include -#include -#include -#include - - - COMMNG cm_prt; - - -// ---- I/O - -static void IOOUTCALL prt_o40(UINT port, REG8 dat) { - - COMMNG prt; - - prt = cm_prt; - if (prt == NULL) { - prt = commng_create(COMCREATE_PRINTER, FALSE); - cm_prt = prt; - } - prt->write(prt, (UINT8)dat); -// TRACEOUT(("prt - %.2x", dat)); - (void)port; -} - -static REG8 IOINPCALL prt_i42(UINT port) { - - REG8 ret; - - ret = 0x84; - if (pccore.cpumode & CPUMODE_8MHZ) { - ret |= 0x20; - } - if (pccore.dipsw[0] & 4) { - ret |= 0x10; - } - if (pccore.dipsw[0] & 0x80) { - ret |= 0x08; - } - if (!(pccore.model & PCMODEL_EPSON)) { - if (CPU_TYPE & CPUTYPE_V30) { - ret |= 0x02; - } - } - else { - if (pccore.dipsw[2] & 0x80) { - ret |= 0x02; - } - } - (void)port; - return(ret); -} - - -// ---- I/F - -static const IOOUT prto40[4] = { - prt_o40, NULL, NULL, NULL}; - -static const IOINP prti40[4] = { - NULL, prt_i42, NULL, NULL}; - -void printif_reset(const NP2CFG *pConfig) { - - commng_destroy(cm_prt); - cm_prt = NULL; - - (void)pConfig; -} - -void printif_bind(void) { - - iocore_attachsysoutex(0x0040, 0x0cf1, prto40, 4); - iocore_attachsysinpex(0x0040, 0x0cf1, prti40, 4); -} - -void printif_finalize(void) { - - commng_destroy(cm_prt); - cm_prt = NULL; -} - +#include +#include +#include +#include +#include + + + COMMNG cm_prt; + + +// ---- I/O + +static void IOOUTCALL prt_o40(UINT port, REG8 dat) { + + COMMNG prt; + + prt = cm_prt; + if (prt == NULL) { + prt = commng_create(COMCREATE_PRINTER, FALSE); + cm_prt = prt; + } + prt->write(prt, (UINT8)dat); +// TRACEOUT(("prt - %.2x", dat)); + (void)port; +} + +static REG8 IOINPCALL prt_i42(UINT port) { + + REG8 ret; + + ret = 0x84; + if (pccore.cpumode & CPUMODE_8MHZ) { + ret |= 0x20; + } + if (pccore.dipsw[0] & 4) { + ret |= 0x10; + } + if (pccore.dipsw[0] & 0x80) { + ret |= 0x08; + } + if (!(pccore.model & PCMODEL_EPSON)) { + if (CPU_TYPE & CPUTYPE_V30) { + ret |= 0x02; + } + } + else { + if (pccore.dipsw[2] & 0x80) { + ret |= 0x02; + } + } + (void)port; + return(ret); +} + + +// ---- I/F + +static const IOOUT prto40[4] = { + prt_o40, NULL, NULL, NULL}; + +static const IOINP prti40[4] = { + NULL, prt_i42, NULL, NULL}; + +void printif_reset(const NP2CFG *pConfig) { + + commng_destroy(cm_prt); + cm_prt = NULL; + + (void)pConfig; +} + +void printif_bind(void) { + + iocore_attachsysoutex(0x0040, 0x0cf1, prto40, 4); + iocore_attachsysinpex(0x0040, 0x0cf1, prti40, 4); +} + +void printif_finalize(void) { + + commng_destroy(cm_prt); + cm_prt = NULL; +} + diff --git a/io/printif.h b/io/printif.h old mode 100755 new mode 100644 index efab69a4..7241f332 --- a/io/printif.h +++ b/io/printif.h @@ -1,13 +1,13 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void printif_reset(const NP2CFG *pConfig); -void printif_bind(void); -void printif_finalize(void); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void printif_reset(const NP2CFG *pConfig); +void printif_bind(void); +void printif_finalize(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/serial.c b/io/serial.c index 1e0ba7f2..7b2d2cd3 100644 --- a/io/serial.c +++ b/io/serial.c @@ -1,950 +1,950 @@ -/** - * @file serial.c - * @brief Keyboard & RS-232C Interface - * - * 関連:pit.c, sysport.c - */ - -#include -#include -#include -#include -#include -#include - - -// ---- Keyboard - -void keyboard_callback(NEVENTITEM item) { - - if (item->flag & NEVENT_SETEVENT) { - if ((keybrd.ctrls) || (keybrd.buffers)) { - if (!(keybrd.status & 2)) { - keybrd.status |= 2; - if (keybrd.ctrls) { - keybrd.ctrls--; - keybrd.data = keybrd.ctr[keybrd.ctrpos]; - keybrd.ctrpos = (keybrd.ctrpos + 1) & KB_CTRMASK; - } - else if (keybrd.buffers) { - keybrd.buffers--; - keybrd.data = keybrd.buf[keybrd.bufpos]; - keybrd.bufpos = (keybrd.bufpos + 1) & KB_BUFMASK; - } -// TRACEOUT(("recv -> %02x", keybrd.data)); - } - pic_setirq(1); - nevent_set(NEVENT_KEYBOARD, keybrd.xferclock, - keyboard_callback, NEVENT_RELATIVE); - } - } -} - -static void IOOUTCALL keyboard_o41(UINT port, REG8 dat) { - - if (keybrd.cmd & 1) { -// TRACEOUT(("send -> %02x", dat)); - keystat_ctrlsend(dat); - } - else { - keybrd.mode = dat; - } - (void)port; -} - -static void IOOUTCALL keyboard_o43(UINT port, REG8 dat) { - -// TRACEOUT(("out43 -> %02x %.4x:%.8x", dat, CPU_CS, CPU_EIP)); - if ((!(dat & 0x08)) && (keybrd.cmd & 0x08)) { - keyboard_resetsignal(); - } - if (dat & 0x10) { - keybrd.status &= ~(0x38); - } - keybrd.cmd = dat; - (void)port; -} - -static REG8 IOINPCALL keyboard_i41(UINT port) { - - (void)port; - keybrd.status &= ~2; - pic_resetirq(1); -// TRACEOUT(("in41 -> %02x %.4x:%.8x", keybrd.data, CPU_CS, CPU_EIP)); - return(keybrd.data); -} - -static REG8 IOINPCALL keyboard_i43(UINT port) { - - (void)port; -// TRACEOUT(("in43 -> %02x %.4x:%.8x", keybrd.status, CPU_CS, CPU_EIP)); - return(keybrd.status | 0x85); -} - - -// ---- - -static const IOOUT keybrdo41[2] = { - keyboard_o41, keyboard_o43}; - -static const IOINP keybrdi41[2] = { - keyboard_i41, keyboard_i43}; - - -void keyboard_reset(const NP2CFG *pConfig) { - - ZeroMemory(&keybrd, sizeof(keybrd)); - keybrd.data = 0xff; - keybrd.mode = 0x5e; - - (void)pConfig; -} - -void keyboard_bind(void) { - - keystat_ctrlreset(); - keyboard_changeclock(); - iocore_attachsysoutex(0x0041, 0x0cf1, keybrdo41, 2); - iocore_attachsysinpex(0x0041, 0x0cf1, keybrdi41, 2); -} - -void keyboard_resetsignal(void) { - - nevent_reset(NEVENT_KEYBOARD); - keybrd.cmd = 0; - keybrd.status = 0; - keybrd.ctrls = 0; - keybrd.buffers = 0; - keystat_ctrlreset(); - keystat_resendstat(); -} - -void keyboard_ctrl(REG8 data) { - - if ((data == 0xfa) || (data == 0xfc)) { - keybrd.ctrls = 0; - } - if (keybrd.ctrls < KB_CTR) { - keybrd.ctr[(keybrd.ctrpos + keybrd.ctrls) & KB_CTRMASK] = data; - keybrd.ctrls++; - if (!nevent_iswork(NEVENT_KEYBOARD)) { - nevent_set(NEVENT_KEYBOARD, keybrd.xferclock, - keyboard_callback, NEVENT_ABSOLUTE); - } - } -} - -void keyboard_send(REG8 data) { - - if (keybrd.buffers < KB_BUF) { - keybrd.buf[(keybrd.bufpos + keybrd.buffers) & KB_BUFMASK] = data; - keybrd.buffers++; - if (!nevent_iswork(NEVENT_KEYBOARD)) { - nevent_set(NEVENT_KEYBOARD, keybrd.xferclock, - keyboard_callback, NEVENT_ABSOLUTE); - } - } - else { - keybrd.status |= 0x10; - } -} - -void keyboard_changeclock(void) { - - keybrd.xferclock = pccore.realclock / 1920; -} - - - -// ---- RS-232C - - COMMNG cm_rs232c = NULL; - -// RS-232C 受信バッファサイズ -#define RS232C_BUFFER (1 << 6) -#define RS232C_BUFFER_MASK (RS232C_BUFFER - 1) -// RS-232C 受信バッファにあるデータが(RS232C_BUFFER_CLRC×8÷ボーレート)秒間読み取られなければ捨てる(根拠なしで感覚的に指定) -#define RS232C_BUFFER_CLRC 16 - -static UINT8 rs232c_buf[RS232C_BUFFER]; // RS-232C 受信リングバッファ 本来は存在すべきでないがWindows経由の通信はリアルタイムにならない以上仕方なし(値に根拠なし) -static UINT8 rs232c_buf_rpos = 0; // RS-232C 受信リングバッファ 読み取り位置 -static UINT8 rs232c_buf_wpos = 0; // RS-232C 受信リングバッファ 書き込み位置 -static int rs232c_removecounter = 0; // データ破棄チェック用カウンタ - -// RS-232C FIFO送信バッファサイズ -#define RS232C_FIFO_WRITEBUFFER 256 -#define RS232C_FIFO_WRITEBUFFER_MASK (RS232C_FIFO_WRITEBUFFER - 1) -static UINT8 rs232c_fifo_writebuf[RS232C_FIFO_WRITEBUFFER]; // RS-232C FIFO送信リングバッファ -static int rs232c_fifo_writebuf_rpos = 0; // RS-232C FIFO送信リングバッファ 読み取り位置 -static int rs232c_fifo_writebuf_wpos = 0; // RS-232C FIFO送信リングバッファ 書き込み位置 - -// RS-232C 送信リトライ -static void rs232c_writeretry() { - - int ret; -//#if defined(SUPPORT_RS232C_FIFO) -// // FIFOモードの時 -// if(rs232cfifo.port138 & 0x1){ -// if(rs232c_fifo_writebuf_wpos == rs232c_fifo_writebuf_rpos) return; // バッファ空なら何もしない -// }else -//#endif -// { - if((rs232c.result & 0x4) != 0) { - return; // TxEMPを見て既に送信完了しているか確認(完了なら送信不要) - } - //} - if (cm_rs232c) { - cm_rs232c->writeretry(cm_rs232c); // 送信リトライ - ret = cm_rs232c->lastwritesuccess(cm_rs232c); // 送信成功かチェック - if(ret==0){ - return; // 失敗していたら次に持ち越し - } -#if defined(SUPPORT_RS232C_FIFO) - // FIFOモードの時 - if(rs232cfifo.port138 & 0x1){ - int fifowbufused; - - // バッファ読み取り位置を進める - rs232c_fifo_writebuf_rpos = (rs232c_fifo_writebuf_rpos+1) & RS232C_FIFO_WRITEBUFFER_MASK; - - fifowbufused = (rs232c_fifo_writebuf_wpos - rs232c_fifo_writebuf_rpos) & RS232C_FIFO_WRITEBUFFER_MASK; - if(fifowbufused > RS232C_FIFO_WRITEBUFFER * 3 / 4){ - rs232c.result &= ~0x1; // バッファフルならTxRDYを下ろす - }else{ - rs232c.result |= 0x1; // バッファ空きならTxRDYを立てる - } - if(!(rs232c.result & 0x5)){ - // バッファフルなら割り込みは止めておく - }else{ - if (sysport.c & 6) { // TxEMP, TxRDYで割り込み? - rs232c.send = 0; -#if defined(SUPPORT_RS232C_FIFO) - rs232cfifo.irqflag = 1; -#endif - pic_setirq(4); // 割り込み - } - } - // バッファに溜まっているデータを書けるだけ書く - while(fifowbufused = ((rs232c_fifo_writebuf_wpos - rs232c_fifo_writebuf_rpos) & RS232C_FIFO_WRITEBUFFER_MASK)){ - if(fifowbufused > RS232C_FIFO_WRITEBUFFER * 3 / 4){ - rs232c.result &= ~0x1; // バッファフルならTxRDYを下ろす - }else{ - rs232c.result |= 0x1; // バッファ空きならTxRDYを立てる - } - cm_rs232c->write(cm_rs232c, (UINT8)rs232c_fifo_writebuf[rs232c_fifo_writebuf_rpos]); - ret = cm_rs232c->lastwritesuccess(cm_rs232c); - if(!ret){ - return; // まだ書き込めないので待つ - }else{ - // バッファ読み取り位置を進める - rs232c_fifo_writebuf_rpos = (rs232c_fifo_writebuf_rpos+1) & RS232C_FIFO_WRITEBUFFER_MASK; - } - } - rs232c.result |= 0x5; // バッファ空きならTxEMP,TxRDYを立てる - cm_rs232c->endblocktranster(cm_rs232c); // ブロック転送モード解除 - }else -#endif - { - rs232c.result |= 0x5; // 送信成功したらTxEMP, TxRDYを立てる - } - if (sysport.c & 6) { // TxEMP, TxRDYで割り込み? - rs232c.send = 0; -#if defined(SUPPORT_RS232C_FIFO) - rs232cfifo.irqflag = 1; -#endif - pic_setirq(4); // 割り込み - } - else { - rs232c.send = 1; // 送信済みフラグを立てる(TxRE, TxEEビットが立つと割り込み発生) - } - } -} - -// RS-232C 初期化 np2起動時に1回だけ呼ばれる -void rs232c_construct(void) { - - if(cm_rs232c){ - commng_destroy(cm_rs232c); - } - cm_rs232c = NULL; -} - -// RS-232C 初期化 np2終了時に1回だけ呼ばれる -void rs232c_destruct(void) { - - commng_destroy(cm_rs232c); - cm_rs232c = NULL; -} - -// RS-232C ポートオープン 実際にアクセスされるまでポートオープンされない仕様 -void rs232c_open(void) { - - if (cm_rs232c == NULL) { - cm_rs232c = commng_create(COMCREATE_SERIAL, FALSE); -#if defined(VAEG_FIX) - cm_rs232c->msg(cm_rs232c, COMMSG_SETRSFLAG, rs232c.cmd & 0x22); /* RTS, DTR */ -#endif - } -} - -// RS-232C 通信用コールバック ボーレート÷8 回/秒で呼ばれる(例: 2400bpsなら2400/8 = 300回/秒) -void rs232c_callback(void) { - - BOOL intr = FALSE; // 割り込みフラグ - BOOL fifomode = FALSE; // FIFOモードフラグ - int bufused; // 受信リングバッファ使用量 - BOOL bufremoved = FALSE; - - // 開いていなければRS-232Cポートオープン - rs232c_open(); - - // 送信に失敗していたらリトライ - rs232c_writeretry(); - - // 受信リングバッファの使用状況を取得 - bufused = (rs232c_buf_wpos - rs232c_buf_rpos) & RS232C_BUFFER_MASK; - if(bufused==0){ - rs232c_removecounter = 0; // バッファが空なら古いデータ削除カウンタをリセット - } - - // 受信可(uPD8251 Recieve Enable)をチェック - if(!(rs232c.cmd & 0x04) && bufused==0) { - // 受信禁止で受信バッファが空ならなら受信処理をしない - }else{ - // 受信可能あるいは受信バッファに残りがあれば処理する -#if defined(SUPPORT_RS232C_FIFO) - // FIFOモードチェック - fifomode = (rs232cfifo.port138 & 0x1); - if(fifomode){ - rs232c_removecounter = 0; // FIFOモードでは古いデータを消さない - if(bufused == RS232C_BUFFER-1){ - if(!rs232cfifo.irqflag){ - // 割り込みが消えていたら割り込み原因をセットして割り込み - rs232cfifo.irqflag = 2; - pic_setirq(4); - } - return; // バッファがいっぱいなら待機 - } - if(rs232cfifo.irqflag){ - return; // 割り込み原因フラグが立っていれば待機 - } - } -#endif - - // 古いデータ削除カウンタをインクリメント - rs232c_removecounter = (rs232c_removecounter + 1) % RS232C_BUFFER_CLRC; - if (bufused > 0 && rs232c_removecounter==0 || bufused == RS232C_BUFFER-1){ - rs232c_buf_rpos = (rs232c_buf_rpos+1) & RS232C_BUFFER_MASK; // カウンタが1周したら一番古いものを捨てる - bufremoved = TRUE; - } - // 受信可(uPD8251 Recieve Enable)の時、ポートから次のデータ読み取り - if ((rs232c.cmd & 0x04) && (cm_rs232c) && (cm_rs232c->read(cm_rs232c, &rs232c_buf[rs232c_buf_wpos]))) { - rs232c_buf_wpos = (rs232c_buf_wpos+1) & RS232C_BUFFER_MASK; // 読み取れたらバッファ書き込み位置を進める - } - // バッファにデータがあればI/Oポート読み取りデータにセットして割り込み - if (rs232c_buf_rpos != rs232c_buf_wpos) { - rs232c.data = rs232c_buf[rs232c_buf_rpos]; // データを1つ取り出し - if(!(rs232c.result & 2) || bufremoved) { // RxRDYが既に立っていれば何もしない → 一部ソフト不具合発生のためバッファが破棄されたときのみ再割り込み - rs232c.result |= 2; // RxRDYを立てる -#if defined(SUPPORT_RS232C_FIFO) - if(fifomode){ - // FIFOモードの時割り込み原因をセット - rs232cfifo.irqflag = 2; - //OutputDebugString(_T("READ INT!\n")); - intr = TRUE; - }else -#endif - if (sysport.c & 1) { - // FIFOモードでないとき、RxREビット(RxRDY割り込み有効)が立っていたら割り込み - intr = TRUE; - } - } - } - } - - // 送信済みフラグが立っているとき、TxRE, TxEEビット(TxRDY, TxEMP割り込み有効)が立っていたら割り込み - if (sysport.c & 6) { - if (rs232c.send) { - rs232c.send = 0; // 送信済みフラグ解除 -#if defined(SUPPORT_RS232C_FIFO) - // FIFOモードの時割り込み原因をセット - rs232cfifo.irqflag = 1; -#endif - intr = TRUE; - } - } - - // WORKAROUND: TxEMP割り込み有効の時、バッファが空ならひたすら割り込み続ける(Win3.1が送信時に永久に割り込み待ちになるのを回避) -//#if defined(SUPPORT_RS232C_FIFO) -// if(!fifomode) -//#endif - if (sysport.c & 2) { - if (!rs232c.send) { - intr = TRUE; - } - } - - // 割り込みフラグが立っていれば割り込み - if (intr) { - pic_setirq(4); - } -} - -// ステータス取得 -// bit 7: ~CI (RI, RING) -// bit 6: ~CS (CTS) -// bit 5: ~CD (DCD, RLSD) -// bit 4: reserved -// bit 3: reserved -// bit 2: reserved -// bit 1: reserved -// bit 0: ~DSR (DR) -UINT8 rs232c_stat(void) { - - rs232c_open(); - if (cm_rs232c == NULL) { - cm_rs232c = commng_create(COMCREATE_SERIAL, FALSE); - return(cm_rs232c->getstat(cm_rs232c)); - } - return 0; -} - -// エラー状態取得 (bit0: パリティ, bit1: オーバーラン, bit2: フレーミング, bit3: ブレーク信号) -UINT8 rs232c_geterror(void) { - - if (cm_rs232c) { - UINT8 errorcode = 0; - cm_rs232c->msg(cm_rs232c, COMMSG_GETERROR, (INT_PTR)(&errorcode)); - return errorcode; - } - return 0; -} - -// エラー消去 -void rs232c_clearerror(void) { - - if (cm_rs232c) { - cm_rs232c->msg(cm_rs232c, COMMSG_CLRERROR, 0); - } -} - -// MIDI panic -void rs232c_midipanic(void) { - - if (cm_rs232c) { - cm_rs232c->msg(cm_rs232c, COMMSG_MIDIRESET, 0); - } -} - - -// ---- - -// I/O 30h データレジスタ Write -static void IOOUTCALL rs232c_o30(UINT port, REG8 dat) { - - static int lastfail = 0; - int ret; - BOOL fifomode = FALSE; // FIFOモードフラグ - -#if defined(SUPPORT_RS232C_FIFO) - // FIFOモードでないとき130hは無効 - fifomode = (rs232cfifo.port138 & 0x1); - if(!fifomode && port==0x130){ - lastfail = 0; - return; - } -#endif - if(!(rs232c.cmd & 0x01)) return; // 送信禁止なら抜ける - if (cm_rs232c) { - rs232c_writeretry(); -#if !defined(__LIBRETRO__) -#if defined(SUPPORT_RS232C_FIFO) - // FIFOモードの時 - if(fifomode){ - int fifowbufused; - - // バッファに入れる - fifowbufused = (rs232c_fifo_writebuf_wpos - rs232c_fifo_writebuf_rpos) & RS232C_FIFO_WRITEBUFFER_MASK; - if(fifowbufused == RS232C_FIFO_WRITEBUFFER-1){ - rs232c_fifo_writebuf_rpos = (rs232c_fifo_writebuf_rpos+1) & RS232C_FIFO_WRITEBUFFER_MASK; // カウンタが1周したら一番古いものを捨てる - } - rs232c.result &= ~0x4; // TxEMPを消す - if(fifowbufused > RS232C_FIFO_WRITEBUFFER * 3 / 4){ - rs232c.result &= ~0x1; // バッファフルならTxRDYを下ろす - }else{ - rs232c.result |= 0x1; // バッファ空きならTxRDY立てる - } - rs232c_fifo_writebuf[rs232c_fifo_writebuf_wpos] = dat; - rs232c_fifo_writebuf_wpos = (rs232c_fifo_writebuf_wpos+1) & RS232C_FIFO_WRITEBUFFER_MASK; // バッファ書き込み位置を進める - // バッファに溜まっているデータを書けるだけ書く - while(fifowbufused = ((rs232c_fifo_writebuf_wpos - rs232c_fifo_writebuf_rpos) & RS232C_FIFO_WRITEBUFFER_MASK)){ - if(fifowbufused > RS232C_FIFO_WRITEBUFFER * 3 / 4){ - rs232c.result &= ~0x1; // バッファフルならTxRDYを下ろす - }else{ - rs232c.result |= 0x1; // バッファ空きならTxRDY立てる - } - cm_rs232c->write(cm_rs232c, (UINT8)rs232c_fifo_writebuf[rs232c_fifo_writebuf_rpos]); - ret = cm_rs232c->lastwritesuccess(cm_rs232c); - if(!ret){ - if(fifowbufused > RS232C_FIFO_WRITEBUFFER / 2){ - cm_rs232c->beginblocktranster(cm_rs232c); // バッファが半分以上埋まっていたらブロック転送モードに変更 - } - if(!(rs232c.result & 0x5)){ - // バッファフルなら割り込みは止めておく - }else{ - // 1byteでも書けていたら割り込み - if (sysport.c & 6) { // TxEMP, TxRDYで割り込み? - rs232c.send = 0; -#if defined(SUPPORT_RS232C_FIFO) - rs232cfifo.irqflag = 1; -#endif - pic_setirq(4); // 割り込み - } - lastfail = 1; - } - return; // まだ書き込めないので待つ - }else{ - // バッファ読み取り位置を進める - rs232c_fifo_writebuf_rpos = (rs232c_fifo_writebuf_rpos+1) & RS232C_FIFO_WRITEBUFFER_MASK; - } - } - rs232c.result |= 0x5; // バッファ空ならTxEMP,TxRDYを立てる - cm_rs232c->endblocktranster(cm_rs232c); // ブロック転送モード解除 - }else -#endif - { - cm_rs232c->write(cm_rs232c, (UINT8)dat); - ret = cm_rs232c->lastwritesuccess(cm_rs232c); - rs232c.result &= ~0x5; // 送信中はTxEMP, TxRDYを下ろす - if(!ret){ - lastfail = 1; - return; // まだ書き込めないので待つ - } - rs232c.result |= 0x5; // 送信成功したらTxEMP, TxRDYを立てる - } -#endif - } - if (lastfail && (sysport.c & 6)) { - // 前回失敗していたら即割り込み - rs232c.send = 0; -#if defined(SUPPORT_RS232C_FIFO) - rs232cfifo.irqflag = 1; -#endif - pic_setirq(4); - } - else { - rs232c.send = 1; // 割り込みがボーレートよりも高速にならないようにする - } - lastfail = 0; - (void)port; -} - -// I/O 32h モードセット,コマンドワード Write -static void IOOUTCALL rs232c_o32(UINT port, REG8 dat) { - - if (!(dat & 0xfd)) { - rs232c.dummyinst++; - } - else { - if ((rs232c.dummyinst >= 3) && (dat == 0x40)) { - rs232c.pos = 0; - } - rs232c.dummyinst = 0; - } - switch(rs232c.pos) { - case 0x00: // reset - rs232c_clearerror(); - rs232c.pos++; - break; - - case 0x01: // mode - rs232c.rawmode = dat; - if (!(dat & 0x03)) { - rs232c.mul = 10 * 16; - } - else { - rs232c.mul = ((dat >> 1) & 6) + 10; - if (dat & 0x10) { - rs232c.mul += 2; - } - switch(dat & 0xc0) { - case 0x80: - rs232c.mul += 3; - break; - case 0xc0: - rs232c.mul += 4; - break; - default: - rs232c.mul += 2; - break; - } - switch(dat & 0x03) { - case 0x01: - rs232c.mul >>= 1; - break; - case 0x03: - rs232c.mul *= 32; - break; - default: - rs232c.mul *= 8; - break; - } - } - pit_setrs232cspeed((pit.ch + 2)->value); - rs232c.pos++; - break; - - case 0x02: // cmd - //sysport.c &= ~7; - //sysport.c |= (dat & 7); - //rs232c.pos++; - if(dat & 0x40){ - // reset - rs232c.pos = 1; - rs232c_clearerror(); - } - if(dat & 0x10){ - rs232c_clearerror(); - } - if(!(rs232c.cmd & 0x04) && (dat & 0x04)){ - if (cm_rs232c) { - cm_rs232c->msg(cm_rs232c, COMMSG_PURGE, (INTPTR)&rs232c.cmd); - } - } - rs232c.cmd = dat; - if (cm_rs232c) { - cm_rs232c->msg(cm_rs232c, COMMSG_SETCOMMAND, (INTPTR)&rs232c.cmd); - } - break; - } - (void)port; -} - -// I/O 30h データレジスタ Read -static REG8 IOINPCALL rs232c_i30(UINT port) { - - UINT8 ret = rs232c.data; - -#if defined(SUPPORT_RS232C_FIFO) - // FIFOモードでないとき130hは無効 - if(!(rs232cfifo.port138 & 0x1) && port==0x130){ - return 0xff; - } -#endif - - rs232c_writeretry(); - -#if defined(SUPPORT_RS232C_FIFO) - if(port==0x130){ - if (rs232c_buf_rpos == rs232c_buf_wpos) { - // 無理矢理読む - if ((cm_rs232c) && (cm_rs232c->read(cm_rs232c, &rs232c_buf[rs232c_buf_wpos]))) { - rs232c_buf_wpos = (rs232c_buf_wpos+1) & RS232C_BUFFER_MASK; - rs232c.data = rs232c_buf[rs232c_buf_rpos]; // データを1つ取り出し - } - } - } -#endif - if (rs232c_buf_rpos != rs232c_buf_wpos) { - rs232c_buf_rpos = (rs232c_buf_rpos+1) & RS232C_BUFFER_MASK; // バッファ読み取り位置を1進める - rs232c.data = rs232c_buf[rs232c_buf_rpos]; // データを1つ取り出し - } -#if defined(SUPPORT_RS232C_FIFO) - if(port==0x130){ - if (rs232c_buf_rpos != rs232c_buf_wpos) { // 受信すべきデータがあるか確認 - int bufused; // 受信リングバッファ使用量 - // 受信リングバッファの使用状況を取得 - bufused = (rs232c_buf_wpos - rs232c_buf_rpos) & RS232C_BUFFER_MASK; - - rs232c.data = rs232c_buf[rs232c_buf_rpos]; // 次のデータを取り出し - - if(bufused > RS232C_BUFFER * 3 / 4){ - // バッファ残りが少ないので急いで割り込み - //if (sysport.c & 1) { - rs232cfifo.irqflag = 2; - pic_setirq(4); - //} - } - //OutputDebugString(_T("READ!\n")); - }else{ - rs232c.result &= ~0x2; - rs232cfifo.irqflag = 3; - pic_setirq(4); - //rs232c.data = 0xff; - //pic_resetirq(4); - //OutputDebugString(_T("READ END!\n")); - } - }else -#endif - { - int bufused; // 受信リングバッファ使用量 - // 受信リングバッファの使用状況を取得 - bufused = (rs232c_buf_wpos - rs232c_buf_rpos) & RS232C_BUFFER_MASK; - if(bufused > RS232C_BUFFER * 3 / 4){ - // バッファ残りが少ないので急いで割り込み - if (sysport.c & 1) { - // FIFOモードでないとき、RxREビット(RxRDY割り込み有効)が立っていたら割り込み - pic_setirq(4); - } - }else{ - // 余裕があるので次のCallbackのタイミングで割り込み - rs232c.result &= ~0x2; // RxRDYを消す - } - } - rs232c_removecounter = 0; - return(ret); -} - -// I/O 32h ステータス Read -static REG8 IOINPCALL rs232c_i32(UINT port) { - - UINT8 ret; - - rs232c_writeretry(); - - ret = rs232c.result; - ret |= (rs232c_geterror() & 7) << 3; - if (!(rs232c_stat() & 0x01)) { - return(ret | 0x80); - } - else { - (void)port; - return(ret | 0x00); - } -} - -/* - * I/O 132h FIFO ラインステータス - * bit 3~7について UNDOCUMENTED 9801/9821 Vol.2に記載の内容は誤り - * - * bit 7: 不明 - * bit 6: ブレイク信号受信 - * bit 5: フレーミングエラー - * bit 4: オーバーランエラー - * bit 3: パリティエラー - * bit 2: RxRDY - * bit 1: TxRDY - * bit 0: TxEMP - */ -static REG8 IOINPCALL rs232c_i132(UINT port) { - - UINT8 ret; - UINT8 err; // エラー状態(bit0: パリティ, bit1: オーバーラン, bit2: フレーミング, bit3: ブレーク信号) - - rs232c_writeretry(); - - ret = rs232c.result; // bit0: TxRDY, bit1: RxRDY, bit2: TxEMP - err = rs232c_geterror(); - ret = ((ret >> 2) & 0x1) | ((ret << 1) & 0x6) | ((err << 3) & 0x78); - - if (!(rs232c_stat() & 0x01)) { - return(ret | 0x80); - } - else { - (void)port; - return(ret | 0x00); - } -} - -// I/O 134h モデムステータスレジスタ -#if defined(SUPPORT_RS232C_FIFO) -static REG8 IOINPCALL rs232c_i134(UINT port) { - - REG8 ret = 0; - static UINT8 lastret = 0; - UINT8 stat = rs232c_stat(); - - /* stat - * bit 7: ~CI (RI, RING) - * bit 6: ~CS (CTS) - * bit 5: ~CD (DCD, RLSD) - * bit 0: ~DSR (DR) - */ - if(~stat & 0x20){ - ret |= 0x80; // CD - } - if(~stat & 0x80){ - ret |= 0x40; // CI - } - if(~stat & 0x01){ - ret |= 0x20; // DR - } - if(~stat & 0x40){ - ret |= 0x10; // CS - } - ret |= ((lastret >> 4) ^ ret) & 0xf; // diff - lastret = ret; - (void)port; - return(ret); -} - -// I/O 136h FIFO割り込み参照レジスタ -static REG8 IOINPCALL rs232c_i136(UINT port) { - - rs232cfifo.port136 ^= 0x40; - - if(rs232cfifo.irqflag){ - rs232cfifo.port136 &= ~0xf; - if(rs232cfifo.irqflag == 3){ - rs232cfifo.port136 |= 0x6; - //rs232cfifo.irqflag = 0; - //OutputDebugString(_T("CHECK READ END INT!\n")); - }else if(rs232cfifo.irqflag == 2){ - rs232cfifo.port136 |= 0x4; - //OutputDebugString(_T("CHECK READ INT!\n")); - }else if(rs232cfifo.irqflag == 1){ - rs232cfifo.port136 |= 0x2; - //rs232cfifo.irqflag = 0; - //OutputDebugString(_T("CHECK WRITE INT!\n")); - } - rs232cfifo.irqflag &= ~0x7; - pic_resetirq(4); - }else{ - rs232cfifo.port136 |= 0x1; - pic_resetirq(4); - //OutputDebugString(_T("NULL INT!\n")); - } - - return(rs232cfifo.port136); -} - -// I/O 138h FIFOコントロールレジスタ -static void IOOUTCALL rs232c_o138(UINT port, REG8 dat) { - - if(dat & 0x2){ - //int i; - //// 受信FIFOリセット - //rs232c_buf_rpos = rs232c_buf_wpos; - //if(rs232cfifo.irqflag==2) rs232cfifo.irqflag = 0; - //if(cm_rs232c){ - // for(i=0;i<256;i++){ - // cm_rs232c->read(cm_rs232c, &rs232c_buf[rs232c_buf_wpos]); - // } - //} - //pic_resetirq(4); - } - rs232cfifo.port138 = dat; - (void)port; -} -static REG8 IOINPCALL rs232c_i138(UINT port) { - - UINT8 ret = rs232cfifo.port138; - - return(ret); -} - -// V-FASTモード通信速度設定 関連: pit.c pit_setrs232cspeed -void rs232c_vfast_setrs232cspeed(UINT8 value) { - if(value == 0) return; - if(!(rs232cfifo.vfast & 0x80)) return; // V FASTモードでない場合はなにもしない - if (cm_rs232c) { - int speedtbl[16] = { - 0, 115200, 57600, 38400, - 28800, 0, 19200, 0, - 14400, 0, 0, 0, - 9600, 0, 0, 0, - }; // V-FAST通信速度テーブル - int newspeed; - newspeed = speedtbl[rs232cfifo.vfast & 0xf]; - if(newspeed != 0){ - // 通信速度変更 - cm_rs232c->msg(cm_rs232c, COMMSG_CHANGESPEED, (INTPTR)&newspeed); - }else{ - // V-FAST通信速度テーブルにないとき、通常の速度設定にする - PITCH pitch; - pitch = pit.ch + 2; - pit_setrs232cspeed(pitch->value); - } - } -} - -// V-FASTモードレジスタ -static void IOOUTCALL rs232c_o13a(UINT port, REG8 dat) { - - if((rs232cfifo.vfast & 0x80) && !(dat & 0x80)){ - PITCH pitch; - // V FASTモード解除 - rs232cfifo.vfast = dat; - pitch = pit.ch + 2; - pit_setrs232cspeed(pitch->value); - }else{ - // V FASTモードセット - rs232cfifo.vfast = dat; - rs232c_vfast_setrs232cspeed(rs232cfifo.vfast); - } - rs232cfifo.irqflag &= ~0x7; - (void)port; -} -static REG8 IOINPCALL rs232c_i13a(UINT port) { - - UINT8 ret = rs232cfifo.vfast; - return(ret); -} -#endif - - - -// ---- - -static const IOOUT rs232co30[2] = { - rs232c_o30, rs232c_o32}; - -static const IOINP rs232ci30[2] = { - rs232c_i30, rs232c_i32}; - -void rs232c_reset(const NP2CFG *pConfig) { - - commng_destroy(cm_rs232c); - cm_rs232c = NULL; - rs232c.result = 0x05; - rs232c.data = 0xff; - rs232c.send = 1; - rs232c.pos = 0; - rs232c.cmd = 0x27; // デフォルトで送受信許可 -#if defined(VAEG_FIX) - rs232c.cmd = 0; -#endif - rs232c.cmdvalid = 1; // ステートセーブ互換性維持用 - rs232c.reserved = 0; - rs232c.dummyinst = 0; - rs232c.mul = 10 * 16; - rs232c.rawmode = 0; - -#if defined(SUPPORT_RS232C_FIFO) - ZeroMemory(&rs232cfifo, sizeof(rs232cfifo)); -#endif - - if (cm_rs232c == NULL) { - cm_rs232c = commng_create(COMCREATE_SERIAL, TRUE); - } - - (void)pConfig; -} - -void rs232c_bind(void) { - - iocore_attachsysoutex(0x0030, 0x0cf1, rs232co30, 2); - iocore_attachsysinpex(0x0030, 0x0cf1, rs232ci30, 2); - -#if defined(SUPPORT_RS232C_FIFO) - iocore_attachout(0x130, rs232c_o30); - iocore_attachinp(0x130, rs232c_i30); - iocore_attachout(0x132, rs232c_o32); - iocore_attachinp(0x132, rs232c_i132); - //iocore_attachout(0x134, rs232c_o134); - iocore_attachinp(0x134, rs232c_i134); - //iocore_attachout(0x136, rs232c_o136); - iocore_attachinp(0x136, rs232c_i136); - iocore_attachout(0x138, rs232c_o138); - iocore_attachinp(0x138, rs232c_i138); - iocore_attachout(0x13a, rs232c_o13a); - iocore_attachinp(0x13a, rs232c_i13a); -#endif - - // ステートセーブ互換性維持用 - if(!rs232c.cmdvalid){ - rs232c.cmd = 0x27; // デフォルトで送受信許可 - rs232c.cmdvalid = 1; - } -} - +/** + * @file serial.c + * @brief Keyboard & RS-232C Interface + * + * 関連:pit.c, sysport.c + */ + +#include +#include +#include +#include +#include +#include + + +// ---- Keyboard + +void keyboard_callback(NEVENTITEM item) { + + if (item->flag & NEVENT_SETEVENT) { + if ((keybrd.ctrls) || (keybrd.buffers)) { + if (!(keybrd.status & 2)) { + keybrd.status |= 2; + if (keybrd.ctrls) { + keybrd.ctrls--; + keybrd.data = keybrd.ctr[keybrd.ctrpos]; + keybrd.ctrpos = (keybrd.ctrpos + 1) & KB_CTRMASK; + } + else if (keybrd.buffers) { + keybrd.buffers--; + keybrd.data = keybrd.buf[keybrd.bufpos]; + keybrd.bufpos = (keybrd.bufpos + 1) & KB_BUFMASK; + } +// TRACEOUT(("recv -> %02x", keybrd.data)); + } + pic_setirq(1); + nevent_set(NEVENT_KEYBOARD, keybrd.xferclock, + keyboard_callback, NEVENT_RELATIVE); + } + } +} + +static void IOOUTCALL keyboard_o41(UINT port, REG8 dat) { + + if (keybrd.cmd & 1) { +// TRACEOUT(("send -> %02x", dat)); + keystat_ctrlsend(dat); + } + else { + keybrd.mode = dat; + } + (void)port; +} + +static void IOOUTCALL keyboard_o43(UINT port, REG8 dat) { + +// TRACEOUT(("out43 -> %02x %.4x:%.8x", dat, CPU_CS, CPU_EIP)); + if ((!(dat & 0x08)) && (keybrd.cmd & 0x08)) { + keyboard_resetsignal(); + } + if (dat & 0x10) { + keybrd.status &= ~(0x38); + } + keybrd.cmd = dat; + (void)port; +} + +static REG8 IOINPCALL keyboard_i41(UINT port) { + + (void)port; + keybrd.status &= ~2; + pic_resetirq(1); +// TRACEOUT(("in41 -> %02x %.4x:%.8x", keybrd.data, CPU_CS, CPU_EIP)); + return(keybrd.data); +} + +static REG8 IOINPCALL keyboard_i43(UINT port) { + + (void)port; +// TRACEOUT(("in43 -> %02x %.4x:%.8x", keybrd.status, CPU_CS, CPU_EIP)); + return(keybrd.status | 0x85); +} + + +// ---- + +static const IOOUT keybrdo41[2] = { + keyboard_o41, keyboard_o43}; + +static const IOINP keybrdi41[2] = { + keyboard_i41, keyboard_i43}; + + +void keyboard_reset(const NP2CFG *pConfig) { + + ZeroMemory(&keybrd, sizeof(keybrd)); + keybrd.data = 0xff; + keybrd.mode = 0x5e; + + (void)pConfig; +} + +void keyboard_bind(void) { + + keystat_ctrlreset(); + keyboard_changeclock(); + iocore_attachsysoutex(0x0041, 0x0cf1, keybrdo41, 2); + iocore_attachsysinpex(0x0041, 0x0cf1, keybrdi41, 2); +} + +void keyboard_resetsignal(void) { + + nevent_reset(NEVENT_KEYBOARD); + keybrd.cmd = 0; + keybrd.status = 0; + keybrd.ctrls = 0; + keybrd.buffers = 0; + keystat_ctrlreset(); + keystat_resendstat(); +} + +void keyboard_ctrl(REG8 data) { + + if ((data == 0xfa) || (data == 0xfc)) { + keybrd.ctrls = 0; + } + if (keybrd.ctrls < KB_CTR) { + keybrd.ctr[(keybrd.ctrpos + keybrd.ctrls) & KB_CTRMASK] = data; + keybrd.ctrls++; + if (!nevent_iswork(NEVENT_KEYBOARD)) { + nevent_set(NEVENT_KEYBOARD, keybrd.xferclock, + keyboard_callback, NEVENT_ABSOLUTE); + } + } +} + +void keyboard_send(REG8 data) { + + if (keybrd.buffers < KB_BUF) { + keybrd.buf[(keybrd.bufpos + keybrd.buffers) & KB_BUFMASK] = data; + keybrd.buffers++; + if (!nevent_iswork(NEVENT_KEYBOARD)) { + nevent_set(NEVENT_KEYBOARD, keybrd.xferclock, + keyboard_callback, NEVENT_ABSOLUTE); + } + } + else { + keybrd.status |= 0x10; + } +} + +void keyboard_changeclock(void) { + + keybrd.xferclock = pccore.realclock / 1920; +} + + + +// ---- RS-232C + + COMMNG cm_rs232c = NULL; + +// RS-232C 受信バッファサイズ +#define RS232C_BUFFER (1 << 6) +#define RS232C_BUFFER_MASK (RS232C_BUFFER - 1) +// RS-232C 受信バッファにあるデータが(RS232C_BUFFER_CLRC×8÷ボーレート)秒間読み取られなければ捨てる(根拠なしで感覚的に指定) +#define RS232C_BUFFER_CLRC 16 + +static UINT8 rs232c_buf[RS232C_BUFFER]; // RS-232C 受信リングバッファ 本来は存在すべきでないがWindows経由の通信はリアルタイムにならない以上仕方なし(値に根拠なし) +static UINT8 rs232c_buf_rpos = 0; // RS-232C 受信リングバッファ 読み取り位置 +static UINT8 rs232c_buf_wpos = 0; // RS-232C 受信リングバッファ 書き込み位置 +static int rs232c_removecounter = 0; // データ破棄チェック用カウンタ + +// RS-232C FIFO送信バッファサイズ +#define RS232C_FIFO_WRITEBUFFER 256 +#define RS232C_FIFO_WRITEBUFFER_MASK (RS232C_FIFO_WRITEBUFFER - 1) +static UINT8 rs232c_fifo_writebuf[RS232C_FIFO_WRITEBUFFER]; // RS-232C FIFO送信リングバッファ +static int rs232c_fifo_writebuf_rpos = 0; // RS-232C FIFO送信リングバッファ 読み取り位置 +static int rs232c_fifo_writebuf_wpos = 0; // RS-232C FIFO送信リングバッファ 書き込み位置 + +// RS-232C 送信リトライ +static void rs232c_writeretry() { + + int ret; +//#if defined(SUPPORT_RS232C_FIFO) +// // FIFOモードの時 +// if(rs232cfifo.port138 & 0x1){ +// if(rs232c_fifo_writebuf_wpos == rs232c_fifo_writebuf_rpos) return; // バッファ空なら何もしない +// }else +//#endif +// { + if((rs232c.result & 0x4) != 0) { + return; // TxEMPを見て既に送信完了しているか確認(完了なら送信不要) + } + //} + if (cm_rs232c) { + cm_rs232c->writeretry(cm_rs232c); // 送信リトライ + ret = cm_rs232c->lastwritesuccess(cm_rs232c); // 送信成功かチェック + if(ret==0){ + return; // 失敗していたら次に持ち越し + } +#if defined(SUPPORT_RS232C_FIFO) + // FIFOモードの時 + if(rs232cfifo.port138 & 0x1){ + int fifowbufused; + + // バッファ読み取り位置を進める + rs232c_fifo_writebuf_rpos = (rs232c_fifo_writebuf_rpos+1) & RS232C_FIFO_WRITEBUFFER_MASK; + + fifowbufused = (rs232c_fifo_writebuf_wpos - rs232c_fifo_writebuf_rpos) & RS232C_FIFO_WRITEBUFFER_MASK; + if(fifowbufused > RS232C_FIFO_WRITEBUFFER * 3 / 4){ + rs232c.result &= ~0x1; // バッファフルならTxRDYを下ろす + }else{ + rs232c.result |= 0x1; // バッファ空きならTxRDYを立てる + } + if(!(rs232c.result & 0x5)){ + // バッファフルなら割り込みは止めておく + }else{ + if (sysport.c & 6) { // TxEMP, TxRDYで割り込み? + rs232c.send = 0; +#if defined(SUPPORT_RS232C_FIFO) + rs232cfifo.irqflag = 1; +#endif + pic_setirq(4); // 割り込み + } + } + // バッファに溜まっているデータを書けるだけ書く + while(fifowbufused = ((rs232c_fifo_writebuf_wpos - rs232c_fifo_writebuf_rpos) & RS232C_FIFO_WRITEBUFFER_MASK)){ + if(fifowbufused > RS232C_FIFO_WRITEBUFFER * 3 / 4){ + rs232c.result &= ~0x1; // バッファフルならTxRDYを下ろす + }else{ + rs232c.result |= 0x1; // バッファ空きならTxRDYを立てる + } + cm_rs232c->write(cm_rs232c, (UINT8)rs232c_fifo_writebuf[rs232c_fifo_writebuf_rpos]); + ret = cm_rs232c->lastwritesuccess(cm_rs232c); + if(!ret){ + return; // まだ書き込めないので待つ + }else{ + // バッファ読み取り位置を進める + rs232c_fifo_writebuf_rpos = (rs232c_fifo_writebuf_rpos+1) & RS232C_FIFO_WRITEBUFFER_MASK; + } + } + rs232c.result |= 0x5; // バッファ空きならTxEMP,TxRDYを立てる + cm_rs232c->endblocktranster(cm_rs232c); // ブロック転送モード解除 + }else +#endif + { + rs232c.result |= 0x5; // 送信成功したらTxEMP, TxRDYを立てる + } + if (sysport.c & 6) { // TxEMP, TxRDYで割り込み? + rs232c.send = 0; +#if defined(SUPPORT_RS232C_FIFO) + rs232cfifo.irqflag = 1; +#endif + pic_setirq(4); // 割り込み + } + else { + rs232c.send = 1; // 送信済みフラグを立てる(TxRE, TxEEビットが立つと割り込み発生) + } + } +} + +// RS-232C 初期化 np2起動時に1回だけ呼ばれる +void rs232c_construct(void) { + + if(cm_rs232c){ + commng_destroy(cm_rs232c); + } + cm_rs232c = NULL; +} + +// RS-232C 初期化 np2終了時に1回だけ呼ばれる +void rs232c_destruct(void) { + + commng_destroy(cm_rs232c); + cm_rs232c = NULL; +} + +// RS-232C ポートオープン 実際にアクセスされるまでポートオープンされない仕様 +void rs232c_open(void) { + + if (cm_rs232c == NULL) { + cm_rs232c = commng_create(COMCREATE_SERIAL, FALSE); +#if defined(VAEG_FIX) + cm_rs232c->msg(cm_rs232c, COMMSG_SETRSFLAG, rs232c.cmd & 0x22); /* RTS, DTR */ +#endif + } +} + +// RS-232C 通信用コールバック ボーレート÷8 回/秒で呼ばれる(例: 2400bpsなら2400/8 = 300回/秒) +void rs232c_callback(void) { + + BOOL intr = FALSE; // 割り込みフラグ + BOOL fifomode = FALSE; // FIFOモードフラグ + int bufused; // 受信リングバッファ使用量 + BOOL bufremoved = FALSE; + + // 開いていなければRS-232Cポートオープン + rs232c_open(); + + // 送信に失敗していたらリトライ + rs232c_writeretry(); + + // 受信リングバッファの使用状況を取得 + bufused = (rs232c_buf_wpos - rs232c_buf_rpos) & RS232C_BUFFER_MASK; + if(bufused==0){ + rs232c_removecounter = 0; // バッファが空なら古いデータ削除カウンタをリセット + } + + // 受信可(uPD8251 Recieve Enable)をチェック + if(!(rs232c.cmd & 0x04) && bufused==0) { + // 受信禁止で受信バッファが空ならなら受信処理をしない + }else{ + // 受信可能あるいは受信バッファに残りがあれば処理する +#if defined(SUPPORT_RS232C_FIFO) + // FIFOモードチェック + fifomode = (rs232cfifo.port138 & 0x1); + if(fifomode){ + rs232c_removecounter = 0; // FIFOモードでは古いデータを消さない + if(bufused == RS232C_BUFFER-1){ + if(!rs232cfifo.irqflag){ + // 割り込みが消えていたら割り込み原因をセットして割り込み + rs232cfifo.irqflag = 2; + pic_setirq(4); + } + return; // バッファがいっぱいなら待機 + } + if(rs232cfifo.irqflag){ + return; // 割り込み原因フラグが立っていれば待機 + } + } +#endif + + // 古いデータ削除カウンタをインクリメント + rs232c_removecounter = (rs232c_removecounter + 1) % RS232C_BUFFER_CLRC; + if (bufused > 0 && rs232c_removecounter==0 || bufused == RS232C_BUFFER-1){ + rs232c_buf_rpos = (rs232c_buf_rpos+1) & RS232C_BUFFER_MASK; // カウンタが1周したら一番古いものを捨てる + bufremoved = TRUE; + } + // 受信可(uPD8251 Recieve Enable)の時、ポートから次のデータ読み取り + if ((rs232c.cmd & 0x04) && (cm_rs232c) && (cm_rs232c->read(cm_rs232c, &rs232c_buf[rs232c_buf_wpos]))) { + rs232c_buf_wpos = (rs232c_buf_wpos+1) & RS232C_BUFFER_MASK; // 読み取れたらバッファ書き込み位置を進める + } + // バッファにデータがあればI/Oポート読み取りデータにセットして割り込み + if (rs232c_buf_rpos != rs232c_buf_wpos) { + rs232c.data = rs232c_buf[rs232c_buf_rpos]; // データを1つ取り出し + if(!(rs232c.result & 2) || bufremoved) { // RxRDYが既に立っていれば何もしない → 一部ソフト不具合発生のためバッファが破棄されたときのみ再割り込み + rs232c.result |= 2; // RxRDYを立てる +#if defined(SUPPORT_RS232C_FIFO) + if(fifomode){ + // FIFOモードの時割り込み原因をセット + rs232cfifo.irqflag = 2; + //OutputDebugString(_T("READ INT!\n")); + intr = TRUE; + }else +#endif + if (sysport.c & 1) { + // FIFOモードでないとき、RxREビット(RxRDY割り込み有効)が立っていたら割り込み + intr = TRUE; + } + } + } + } + + // 送信済みフラグが立っているとき、TxRE, TxEEビット(TxRDY, TxEMP割り込み有効)が立っていたら割り込み + if (sysport.c & 6) { + if (rs232c.send) { + rs232c.send = 0; // 送信済みフラグ解除 +#if defined(SUPPORT_RS232C_FIFO) + // FIFOモードの時割り込み原因をセット + rs232cfifo.irqflag = 1; +#endif + intr = TRUE; + } + } + + // WORKAROUND: TxEMP割り込み有効の時、バッファが空ならひたすら割り込み続ける(Win3.1が送信時に永久に割り込み待ちになるのを回避) +//#if defined(SUPPORT_RS232C_FIFO) +// if(!fifomode) +//#endif + if (sysport.c & 2) { + if (!rs232c.send) { + intr = TRUE; + } + } + + // 割り込みフラグが立っていれば割り込み + if (intr) { + pic_setirq(4); + } +} + +// ステータス取得 +// bit 7: ~CI (RI, RING) +// bit 6: ~CS (CTS) +// bit 5: ~CD (DCD, RLSD) +// bit 4: reserved +// bit 3: reserved +// bit 2: reserved +// bit 1: reserved +// bit 0: ~DSR (DR) +UINT8 rs232c_stat(void) { + + rs232c_open(); + if (cm_rs232c == NULL) { + cm_rs232c = commng_create(COMCREATE_SERIAL, FALSE); + return(cm_rs232c->getstat(cm_rs232c)); + } + return 0; +} + +// エラー状態取得 (bit0: パリティ, bit1: オーバーラン, bit2: フレーミング, bit3: ブレーク信号) +UINT8 rs232c_geterror(void) { + + if (cm_rs232c) { + UINT8 errorcode = 0; + cm_rs232c->msg(cm_rs232c, COMMSG_GETERROR, (INT_PTR)(&errorcode)); + return errorcode; + } + return 0; +} + +// エラー消去 +void rs232c_clearerror(void) { + + if (cm_rs232c) { + cm_rs232c->msg(cm_rs232c, COMMSG_CLRERROR, 0); + } +} + +// MIDI panic +void rs232c_midipanic(void) { + + if (cm_rs232c) { + cm_rs232c->msg(cm_rs232c, COMMSG_MIDIRESET, 0); + } +} + + +// ---- + +// I/O 30h データレジスタ Write +static void IOOUTCALL rs232c_o30(UINT port, REG8 dat) { + + static int lastfail = 0; + int ret; + BOOL fifomode = FALSE; // FIFOモードフラグ + +#if defined(SUPPORT_RS232C_FIFO) + // FIFOモードでないとき130hは無効 + fifomode = (rs232cfifo.port138 & 0x1); + if(!fifomode && port==0x130){ + lastfail = 0; + return; + } +#endif + if(!(rs232c.cmd & 0x01)) return; // 送信禁止なら抜ける + if (cm_rs232c) { + rs232c_writeretry(); +#if !defined(__LIBRETRO__) +#if defined(SUPPORT_RS232C_FIFO) + // FIFOモードの時 + if(fifomode){ + int fifowbufused; + + // バッファに入れる + fifowbufused = (rs232c_fifo_writebuf_wpos - rs232c_fifo_writebuf_rpos) & RS232C_FIFO_WRITEBUFFER_MASK; + if(fifowbufused == RS232C_FIFO_WRITEBUFFER-1){ + rs232c_fifo_writebuf_rpos = (rs232c_fifo_writebuf_rpos+1) & RS232C_FIFO_WRITEBUFFER_MASK; // カウンタが1周したら一番古いものを捨てる + } + rs232c.result &= ~0x4; // TxEMPを消す + if(fifowbufused > RS232C_FIFO_WRITEBUFFER * 3 / 4){ + rs232c.result &= ~0x1; // バッファフルならTxRDYを下ろす + }else{ + rs232c.result |= 0x1; // バッファ空きならTxRDY立てる + } + rs232c_fifo_writebuf[rs232c_fifo_writebuf_wpos] = dat; + rs232c_fifo_writebuf_wpos = (rs232c_fifo_writebuf_wpos+1) & RS232C_FIFO_WRITEBUFFER_MASK; // バッファ書き込み位置を進める + // バッファに溜まっているデータを書けるだけ書く + while(fifowbufused = ((rs232c_fifo_writebuf_wpos - rs232c_fifo_writebuf_rpos) & RS232C_FIFO_WRITEBUFFER_MASK)){ + if(fifowbufused > RS232C_FIFO_WRITEBUFFER * 3 / 4){ + rs232c.result &= ~0x1; // バッファフルならTxRDYを下ろす + }else{ + rs232c.result |= 0x1; // バッファ空きならTxRDY立てる + } + cm_rs232c->write(cm_rs232c, (UINT8)rs232c_fifo_writebuf[rs232c_fifo_writebuf_rpos]); + ret = cm_rs232c->lastwritesuccess(cm_rs232c); + if(!ret){ + if(fifowbufused > RS232C_FIFO_WRITEBUFFER / 2){ + cm_rs232c->beginblocktranster(cm_rs232c); // バッファが半分以上埋まっていたらブロック転送モードに変更 + } + if(!(rs232c.result & 0x5)){ + // バッファフルなら割り込みは止めておく + }else{ + // 1byteでも書けていたら割り込み + if (sysport.c & 6) { // TxEMP, TxRDYで割り込み? + rs232c.send = 0; +#if defined(SUPPORT_RS232C_FIFO) + rs232cfifo.irqflag = 1; +#endif + pic_setirq(4); // 割り込み + } + lastfail = 1; + } + return; // まだ書き込めないので待つ + }else{ + // バッファ読み取り位置を進める + rs232c_fifo_writebuf_rpos = (rs232c_fifo_writebuf_rpos+1) & RS232C_FIFO_WRITEBUFFER_MASK; + } + } + rs232c.result |= 0x5; // バッファ空ならTxEMP,TxRDYを立てる + cm_rs232c->endblocktranster(cm_rs232c); // ブロック転送モード解除 + }else +#endif + { + cm_rs232c->write(cm_rs232c, (UINT8)dat); + ret = cm_rs232c->lastwritesuccess(cm_rs232c); + rs232c.result &= ~0x5; // 送信中はTxEMP, TxRDYを下ろす + if(!ret){ + lastfail = 1; + return; // まだ書き込めないので待つ + } + rs232c.result |= 0x5; // 送信成功したらTxEMP, TxRDYを立てる + } +#endif + } + if (lastfail && (sysport.c & 6)) { + // 前回失敗していたら即割り込み + rs232c.send = 0; +#if defined(SUPPORT_RS232C_FIFO) + rs232cfifo.irqflag = 1; +#endif + pic_setirq(4); + } + else { + rs232c.send = 1; // 割り込みがボーレートよりも高速にならないようにする + } + lastfail = 0; + (void)port; +} + +// I/O 32h モードセット,コマンドワード Write +static void IOOUTCALL rs232c_o32(UINT port, REG8 dat) { + + if (!(dat & 0xfd)) { + rs232c.dummyinst++; + } + else { + if ((rs232c.dummyinst >= 3) && (dat == 0x40)) { + rs232c.pos = 0; + } + rs232c.dummyinst = 0; + } + switch(rs232c.pos) { + case 0x00: // reset + rs232c_clearerror(); + rs232c.pos++; + break; + + case 0x01: // mode + rs232c.rawmode = dat; + if (!(dat & 0x03)) { + rs232c.mul = 10 * 16; + } + else { + rs232c.mul = ((dat >> 1) & 6) + 10; + if (dat & 0x10) { + rs232c.mul += 2; + } + switch(dat & 0xc0) { + case 0x80: + rs232c.mul += 3; + break; + case 0xc0: + rs232c.mul += 4; + break; + default: + rs232c.mul += 2; + break; + } + switch(dat & 0x03) { + case 0x01: + rs232c.mul >>= 1; + break; + case 0x03: + rs232c.mul *= 32; + break; + default: + rs232c.mul *= 8; + break; + } + } + pit_setrs232cspeed((pit.ch + 2)->value); + rs232c.pos++; + break; + + case 0x02: // cmd + //sysport.c &= ~7; + //sysport.c |= (dat & 7); + //rs232c.pos++; + if(dat & 0x40){ + // reset + rs232c.pos = 1; + rs232c_clearerror(); + } + if(dat & 0x10){ + rs232c_clearerror(); + } + if(!(rs232c.cmd & 0x04) && (dat & 0x04)){ + if (cm_rs232c) { + cm_rs232c->msg(cm_rs232c, COMMSG_PURGE, (INTPTR)&rs232c.cmd); + } + } + rs232c.cmd = dat; + if (cm_rs232c) { + cm_rs232c->msg(cm_rs232c, COMMSG_SETCOMMAND, (INTPTR)&rs232c.cmd); + } + break; + } + (void)port; +} + +// I/O 30h データレジスタ Read +static REG8 IOINPCALL rs232c_i30(UINT port) { + + UINT8 ret = rs232c.data; + +#if defined(SUPPORT_RS232C_FIFO) + // FIFOモードでないとき130hは無効 + if(!(rs232cfifo.port138 & 0x1) && port==0x130){ + return 0xff; + } +#endif + + rs232c_writeretry(); + +#if defined(SUPPORT_RS232C_FIFO) + if(port==0x130){ + if (rs232c_buf_rpos == rs232c_buf_wpos) { + // 無理矢理読む + if ((cm_rs232c) && (cm_rs232c->read(cm_rs232c, &rs232c_buf[rs232c_buf_wpos]))) { + rs232c_buf_wpos = (rs232c_buf_wpos+1) & RS232C_BUFFER_MASK; + rs232c.data = rs232c_buf[rs232c_buf_rpos]; // データを1つ取り出し + } + } + } +#endif + if (rs232c_buf_rpos != rs232c_buf_wpos) { + rs232c_buf_rpos = (rs232c_buf_rpos+1) & RS232C_BUFFER_MASK; // バッファ読み取り位置を1進める + rs232c.data = rs232c_buf[rs232c_buf_rpos]; // データを1つ取り出し + } +#if defined(SUPPORT_RS232C_FIFO) + if(port==0x130){ + if (rs232c_buf_rpos != rs232c_buf_wpos) { // 受信すべきデータがあるか確認 + int bufused; // 受信リングバッファ使用量 + // 受信リングバッファの使用状況を取得 + bufused = (rs232c_buf_wpos - rs232c_buf_rpos) & RS232C_BUFFER_MASK; + + rs232c.data = rs232c_buf[rs232c_buf_rpos]; // 次のデータを取り出し + + if(bufused > RS232C_BUFFER * 3 / 4){ + // バッファ残りが少ないので急いで割り込み + //if (sysport.c & 1) { + rs232cfifo.irqflag = 2; + pic_setirq(4); + //} + } + //OutputDebugString(_T("READ!\n")); + }else{ + rs232c.result &= ~0x2; + rs232cfifo.irqflag = 3; + pic_setirq(4); + //rs232c.data = 0xff; + //pic_resetirq(4); + //OutputDebugString(_T("READ END!\n")); + } + }else +#endif + { + int bufused; // 受信リングバッファ使用量 + // 受信リングバッファの使用状況を取得 + bufused = (rs232c_buf_wpos - rs232c_buf_rpos) & RS232C_BUFFER_MASK; + if(bufused > RS232C_BUFFER * 3 / 4){ + // バッファ残りが少ないので急いで割り込み + if (sysport.c & 1) { + // FIFOモードでないとき、RxREビット(RxRDY割り込み有効)が立っていたら割り込み + pic_setirq(4); + } + }else{ + // 余裕があるので次のCallbackのタイミングで割り込み + rs232c.result &= ~0x2; // RxRDYを消す + } + } + rs232c_removecounter = 0; + return(ret); +} + +// I/O 32h ステータス Read +static REG8 IOINPCALL rs232c_i32(UINT port) { + + UINT8 ret; + + rs232c_writeretry(); + + ret = rs232c.result; + ret |= (rs232c_geterror() & 7) << 3; + if (!(rs232c_stat() & 0x01)) { + return(ret | 0x80); + } + else { + (void)port; + return(ret | 0x00); + } +} + +/* + * I/O 132h FIFO ラインステータス + * bit 3~7について UNDOCUMENTED 9801/9821 Vol.2に記載の内容は誤り + * + * bit 7: 不明 + * bit 6: ブレイク信号受信 + * bit 5: フレーミングエラー + * bit 4: オーバーランエラー + * bit 3: パリティエラー + * bit 2: RxRDY + * bit 1: TxRDY + * bit 0: TxEMP + */ +static REG8 IOINPCALL rs232c_i132(UINT port) { + + UINT8 ret; + UINT8 err; // エラー状態(bit0: パリティ, bit1: オーバーラン, bit2: フレーミング, bit3: ブレーク信号) + + rs232c_writeretry(); + + ret = rs232c.result; // bit0: TxRDY, bit1: RxRDY, bit2: TxEMP + err = rs232c_geterror(); + ret = ((ret >> 2) & 0x1) | ((ret << 1) & 0x6) | ((err << 3) & 0x78); + + if (!(rs232c_stat() & 0x01)) { + return(ret | 0x80); + } + else { + (void)port; + return(ret | 0x00); + } +} + +// I/O 134h モデムステータスレジスタ +#if defined(SUPPORT_RS232C_FIFO) +static REG8 IOINPCALL rs232c_i134(UINT port) { + + REG8 ret = 0; + static UINT8 lastret = 0; + UINT8 stat = rs232c_stat(); + + /* stat + * bit 7: ~CI (RI, RING) + * bit 6: ~CS (CTS) + * bit 5: ~CD (DCD, RLSD) + * bit 0: ~DSR (DR) + */ + if(~stat & 0x20){ + ret |= 0x80; // CD + } + if(~stat & 0x80){ + ret |= 0x40; // CI + } + if(~stat & 0x01){ + ret |= 0x20; // DR + } + if(~stat & 0x40){ + ret |= 0x10; // CS + } + ret |= ((lastret >> 4) ^ ret) & 0xf; // diff + lastret = ret; + (void)port; + return(ret); +} + +// I/O 136h FIFO割り込み参照レジスタ +static REG8 IOINPCALL rs232c_i136(UINT port) { + + rs232cfifo.port136 ^= 0x40; + + if(rs232cfifo.irqflag){ + rs232cfifo.port136 &= ~0xf; + if(rs232cfifo.irqflag == 3){ + rs232cfifo.port136 |= 0x6; + //rs232cfifo.irqflag = 0; + //OutputDebugString(_T("CHECK READ END INT!\n")); + }else if(rs232cfifo.irqflag == 2){ + rs232cfifo.port136 |= 0x4; + //OutputDebugString(_T("CHECK READ INT!\n")); + }else if(rs232cfifo.irqflag == 1){ + rs232cfifo.port136 |= 0x2; + //rs232cfifo.irqflag = 0; + //OutputDebugString(_T("CHECK WRITE INT!\n")); + } + rs232cfifo.irqflag &= ~0x7; + pic_resetirq(4); + }else{ + rs232cfifo.port136 |= 0x1; + pic_resetirq(4); + //OutputDebugString(_T("NULL INT!\n")); + } + + return(rs232cfifo.port136); +} + +// I/O 138h FIFOコントロールレジスタ +static void IOOUTCALL rs232c_o138(UINT port, REG8 dat) { + + if(dat & 0x2){ + //int i; + //// 受信FIFOリセット + //rs232c_buf_rpos = rs232c_buf_wpos; + //if(rs232cfifo.irqflag==2) rs232cfifo.irqflag = 0; + //if(cm_rs232c){ + // for(i=0;i<256;i++){ + // cm_rs232c->read(cm_rs232c, &rs232c_buf[rs232c_buf_wpos]); + // } + //} + //pic_resetirq(4); + } + rs232cfifo.port138 = dat; + (void)port; +} +static REG8 IOINPCALL rs232c_i138(UINT port) { + + UINT8 ret = rs232cfifo.port138; + + return(ret); +} + +// V-FASTモード通信速度設定 関連: pit.c pit_setrs232cspeed +void rs232c_vfast_setrs232cspeed(UINT8 value) { + if(value == 0) return; + if(!(rs232cfifo.vfast & 0x80)) return; // V FASTモードでない場合はなにもしない + if (cm_rs232c) { + int speedtbl[16] = { + 0, 115200, 57600, 38400, + 28800, 0, 19200, 0, + 14400, 0, 0, 0, + 9600, 0, 0, 0, + }; // V-FAST通信速度テーブル + int newspeed; + newspeed = speedtbl[rs232cfifo.vfast & 0xf]; + if(newspeed != 0){ + // 通信速度変更 + cm_rs232c->msg(cm_rs232c, COMMSG_CHANGESPEED, (INTPTR)&newspeed); + }else{ + // V-FAST通信速度テーブルにないとき、通常の速度設定にする + PITCH pitch; + pitch = pit.ch + 2; + pit_setrs232cspeed(pitch->value); + } + } +} + +// V-FASTモードレジスタ +static void IOOUTCALL rs232c_o13a(UINT port, REG8 dat) { + + if((rs232cfifo.vfast & 0x80) && !(dat & 0x80)){ + PITCH pitch; + // V FASTモード解除 + rs232cfifo.vfast = dat; + pitch = pit.ch + 2; + pit_setrs232cspeed(pitch->value); + }else{ + // V FASTモードセット + rs232cfifo.vfast = dat; + rs232c_vfast_setrs232cspeed(rs232cfifo.vfast); + } + rs232cfifo.irqflag &= ~0x7; + (void)port; +} +static REG8 IOINPCALL rs232c_i13a(UINT port) { + + UINT8 ret = rs232cfifo.vfast; + return(ret); +} +#endif + + + +// ---- + +static const IOOUT rs232co30[2] = { + rs232c_o30, rs232c_o32}; + +static const IOINP rs232ci30[2] = { + rs232c_i30, rs232c_i32}; + +void rs232c_reset(const NP2CFG *pConfig) { + + commng_destroy(cm_rs232c); + cm_rs232c = NULL; + rs232c.result = 0x05; + rs232c.data = 0xff; + rs232c.send = 1; + rs232c.pos = 0; + rs232c.cmd = 0x27; // デフォルトで送受信許可 +#if defined(VAEG_FIX) + rs232c.cmd = 0; +#endif + rs232c.cmdvalid = 1; // ステートセーブ互換性維持用 + rs232c.reserved = 0; + rs232c.dummyinst = 0; + rs232c.mul = 10 * 16; + rs232c.rawmode = 0; + +#if defined(SUPPORT_RS232C_FIFO) + ZeroMemory(&rs232cfifo, sizeof(rs232cfifo)); +#endif + + if (cm_rs232c == NULL) { + cm_rs232c = commng_create(COMCREATE_SERIAL, TRUE); + } + + (void)pConfig; +} + +void rs232c_bind(void) { + + iocore_attachsysoutex(0x0030, 0x0cf1, rs232co30, 2); + iocore_attachsysinpex(0x0030, 0x0cf1, rs232ci30, 2); + +#if defined(SUPPORT_RS232C_FIFO) + iocore_attachout(0x130, rs232c_o30); + iocore_attachinp(0x130, rs232c_i30); + iocore_attachout(0x132, rs232c_o32); + iocore_attachinp(0x132, rs232c_i132); + //iocore_attachout(0x134, rs232c_o134); + iocore_attachinp(0x134, rs232c_i134); + //iocore_attachout(0x136, rs232c_o136); + iocore_attachinp(0x136, rs232c_i136); + iocore_attachout(0x138, rs232c_o138); + iocore_attachinp(0x138, rs232c_i138); + iocore_attachout(0x13a, rs232c_o13a); + iocore_attachinp(0x13a, rs232c_i13a); +#endif + + // ステートセーブ互換性維持用 + if(!rs232c.cmdvalid){ + rs232c.cmd = 0x27; // デフォルトで送受信許可 + rs232c.cmdvalid = 1; + } +} + diff --git a/io/serial.h b/io/serial.h old mode 100755 new mode 100644 index 7d6a403f..17e9b5f0 --- a/io/serial.h +++ b/io/serial.h @@ -1,88 +1,88 @@ -#ifndef _SERIAL_H_ -#define _SERIAL_H_ - -enum { - KB_CTR = (1 << 3), - KB_CTRMASK = (KB_CTR - 1), - - KB_BUF = (1 << 7), - KB_BUFMASK = (KB_BUF - 1) -}; - -typedef struct { - UINT32 xferclock; - UINT8 data; - UINT8 cmd; - UINT8 mode; - UINT8 status; - UINT ctrls; - UINT ctrpos; - UINT buffers; - UINT bufpos; - UINT8 ctr[KB_CTR]; - UINT8 buf[KB_BUF]; -} _KEYBRD, *KEYBRD; - -typedef struct { - UINT8 result; - UINT8 data; - UINT8 send; - UINT8 pad; - UINT8 pos; - UINT8 cmd; - UINT8 cmdvalid; - UINT8 reserved; - UINT dummyinst; - UINT mul; - UINT8 rawmode; -} _RS232C, *RS232C; - -#if defined(SUPPORT_RS232C_FIFO) -typedef struct { - UINT8 irqflag; // FIFOモード 割り込みの原因 0:なし, 1:送信可能になった, 2:受信すべきデータがある - UINT8 port136; - UINT8 port138; - UINT8 vfast; -} _RS232CFIFO, *RS232CFIFO; -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - -void keyboard_callback(NEVENTITEM item); - -void keyboard_reset(const NP2CFG *pConfig); -void keyboard_bind(void); -void keyboard_resetsignal(void); -void keyboard_ctrl(REG8 data); -void keyboard_send(REG8 data); -void keyboard_changeclock(); - - - -void rs232c_construct(void); -void rs232c_destruct(void); - -void rs232c_reset(const NP2CFG *pConfig); -void rs232c_bind(void); -void rs232c_open(void); -void rs232c_callback(void); - -UINT8 rs232c_stat(void); -UINT8 rs232c_geterror(void); -void rs232c_clearerror(void); -void rs232c_midipanic(void); - -#if defined(SUPPORT_RS232C_FIFO) -void rs232c_vfast_setrs232cspeed(UINT8 value); -#endif - -#ifdef __cplusplus -} -#endif - -#endif // _SERIAL_H_ - +#ifndef _SERIAL_H_ +#define _SERIAL_H_ + +enum { + KB_CTR = (1 << 3), + KB_CTRMASK = (KB_CTR - 1), + + KB_BUF = (1 << 7), + KB_BUFMASK = (KB_BUF - 1) +}; + +typedef struct { + UINT32 xferclock; + UINT8 data; + UINT8 cmd; + UINT8 mode; + UINT8 status; + UINT ctrls; + UINT ctrpos; + UINT buffers; + UINT bufpos; + UINT8 ctr[KB_CTR]; + UINT8 buf[KB_BUF]; +} _KEYBRD, *KEYBRD; + +typedef struct { + UINT8 result; + UINT8 data; + UINT8 send; + UINT8 pad; + UINT8 pos; + UINT8 cmd; + UINT8 cmdvalid; + UINT8 reserved; + UINT dummyinst; + UINT mul; + UINT8 rawmode; +} _RS232C, *RS232C; + +#if defined(SUPPORT_RS232C_FIFO) +typedef struct { + UINT8 irqflag; // FIFOモード 割り込みの原因 0:なし, 1:送信可能になった, 2:受信すべきデータがある + UINT8 port136; + UINT8 port138; + UINT8 vfast; +} _RS232CFIFO, *RS232CFIFO; +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + +void keyboard_callback(NEVENTITEM item); + +void keyboard_reset(const NP2CFG *pConfig); +void keyboard_bind(void); +void keyboard_resetsignal(void); +void keyboard_ctrl(REG8 data); +void keyboard_send(REG8 data); +void keyboard_changeclock(); + + + +void rs232c_construct(void); +void rs232c_destruct(void); + +void rs232c_reset(const NP2CFG *pConfig); +void rs232c_bind(void); +void rs232c_open(void); +void rs232c_callback(void); + +UINT8 rs232c_stat(void); +UINT8 rs232c_geterror(void); +void rs232c_clearerror(void); +void rs232c_midipanic(void); + +#if defined(SUPPORT_RS232C_FIFO) +void rs232c_vfast_setrs232cspeed(UINT8 value); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // _SERIAL_H_ + diff --git a/io/sysport.c b/io/sysport.c old mode 100755 new mode 100644 index 28b8829d..fe2d15e3 --- a/io/sysport.c +++ b/io/sysport.c @@ -1,109 +1,109 @@ -#include -#include -#include -#include -#include - - -// ---- I/O - -static void IOOUTCALL sysp_o35(UINT port, REG8 dat) { - - //int intreq = 0; - if ((sysport.c ^ dat) & 0x04) { // ver0.29 - rs232c.send = 1; - } - //if((sysport.c & 1) && !(dat & 1)){ - // if(rs232c.result & 2){ - // intreq = 1; - // } - //} - //if((sysport.c & 2) && !(dat & 2)){ - // if(rs232c.result & 4){ - // intreq = 1; - // } - //} - //if((sysport.c & 4) && !(dat & 4)){ - // if(rs232c.result & 1){ - // intreq = 1; - // } - //} - //if(intreq){ - // pic_setirq(4); - //} - sysport.c = dat; - beep_oneventset(); - (void)port; -} - -static void IOOUTCALL sysp_o37(UINT port, REG8 dat) { - - REG8 bit; - - if (!(dat & 0xf0)) { - bit = 1 << (dat >> 1); - if (dat & 1) { - sysport.c |= bit; - } - else { - sysport.c &= ~bit; - } - if (bit == 0x04) { // ver0.29 - rs232c.send = 1; - if(rs232c.result & 2){ - pic_setirq(4); - } - } - else if (bit == 0x08) { - beep_oneventset(); - } - } - (void)port; -} - -static REG8 IOINPCALL sysp_i31(UINT port) { - - (void)port; - return(pccore.dipsw[1]); -} - -static REG8 IOINPCALL sysp_i33(UINT port) { - - REG8 ret; - - ret = ((~pccore.dipsw[0]) & 1) << 3; - ret |= rs232c_stat() & 0xe0; - ret |= uPD4990.cdat; - (void)port; - return(ret); -} - -static REG8 IOINPCALL sysp_i35(UINT port) { - - (void)port; - return(sysport.c); -} - - -// ---- I/F - -static const IOOUT syspo31[4] = { - NULL, NULL, sysp_o35, sysp_o37}; - -static const IOINP syspi31[4] = { - sysp_i31, sysp_i33, sysp_i35, NULL}; - -void systemport_reset(const NP2CFG *pConfig) { - - sysport.c = 0xf9; - beep_oneventset(); - - (void)pConfig; -} - -void systemport_bind(void) { - - iocore_attachsysoutex(0x0031, 0xcf1, syspo31, 4); - iocore_attachsysinpex(0x0031, 0xcf1, syspi31, 4); -} - +#include +#include +#include +#include +#include + + +// ---- I/O + +static void IOOUTCALL sysp_o35(UINT port, REG8 dat) { + + //int intreq = 0; + if ((sysport.c ^ dat) & 0x04) { // ver0.29 + rs232c.send = 1; + } + //if((sysport.c & 1) && !(dat & 1)){ + // if(rs232c.result & 2){ + // intreq = 1; + // } + //} + //if((sysport.c & 2) && !(dat & 2)){ + // if(rs232c.result & 4){ + // intreq = 1; + // } + //} + //if((sysport.c & 4) && !(dat & 4)){ + // if(rs232c.result & 1){ + // intreq = 1; + // } + //} + //if(intreq){ + // pic_setirq(4); + //} + sysport.c = dat; + beep_oneventset(); + (void)port; +} + +static void IOOUTCALL sysp_o37(UINT port, REG8 dat) { + + REG8 bit; + + if (!(dat & 0xf0)) { + bit = 1 << (dat >> 1); + if (dat & 1) { + sysport.c |= bit; + } + else { + sysport.c &= ~bit; + } + if (bit == 0x04) { // ver0.29 + rs232c.send = 1; + if(rs232c.result & 2){ + pic_setirq(4); + } + } + else if (bit == 0x08) { + beep_oneventset(); + } + } + (void)port; +} + +static REG8 IOINPCALL sysp_i31(UINT port) { + + (void)port; + return(pccore.dipsw[1]); +} + +static REG8 IOINPCALL sysp_i33(UINT port) { + + REG8 ret; + + ret = ((~pccore.dipsw[0]) & 1) << 3; + ret |= rs232c_stat() & 0xe0; + ret |= uPD4990.cdat; + (void)port; + return(ret); +} + +static REG8 IOINPCALL sysp_i35(UINT port) { + + (void)port; + return(sysport.c); +} + + +// ---- I/F + +static const IOOUT syspo31[4] = { + NULL, NULL, sysp_o35, sysp_o37}; + +static const IOINP syspi31[4] = { + sysp_i31, sysp_i33, sysp_i35, NULL}; + +void systemport_reset(const NP2CFG *pConfig) { + + sysport.c = 0xf9; + beep_oneventset(); + + (void)pConfig; +} + +void systemport_bind(void) { + + iocore_attachsysoutex(0x0031, 0xcf1, syspo31, 4); + iocore_attachsysinpex(0x0031, 0xcf1, syspi31, 4); +} + diff --git a/io/sysport.h b/io/sysport.h old mode 100755 new mode 100644 index 37caf6f4..c93b0fd2 --- a/io/sysport.h +++ b/io/sysport.h @@ -1,17 +1,17 @@ - -typedef struct { - UINT8 c; -} _SYSPORT, *SYSPORT; - - -#ifdef __cplusplus -extern "C" { -#endif - -void systemport_reset(const NP2CFG *pConfig); -void systemport_bind(void); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + UINT8 c; +} _SYSPORT, *SYSPORT; + + +#ifdef __cplusplus +extern "C" { +#endif + +void systemport_reset(const NP2CFG *pConfig); +void systemport_bind(void); + +#ifdef __cplusplus +} +#endif + diff --git a/io/upd4990.c b/io/upd4990.c old mode 100755 new mode 100644 index c8f48f07..3d310e24 --- a/io/upd4990.c +++ b/io/upd4990.c @@ -1,239 +1,239 @@ -#include -#include -#include -#include -#include -#if defined(SUPPORT_HRTIMER) -#include -#include "cpumem.h" -#endif /* SUPPORT_HRTIMER */ - - -// ---- I/O - -static void IOOUTCALL upd4990_o20(UINT port, REG8 dat) { - - REG8 mod; - REG8 cmd; - - mod = dat ^ uPD4990.last; - uPD4990.last = (UINT8)dat; - - if (dat & 0x08) { // STB - if (mod & 0x08) { - cmd = uPD4990.parallel; - if (cmd == 7) { - cmd = uPD4990.serial & 0x0f; - } - switch(cmd) { - case 0x00: // register hold - uPD4990.regsft = 0; - break; - - case 0x01: // register shift - uPD4990.regsft = 1; - uPD4990.pos = (UPD4990_REGLEN * 8) - 1; - uPD4990.cdat = uPD4990.reg[UPD4990_REGLEN - 1] & 1; - break; - - case 0x02: // time set / counter hold - uPD4990.regsft = 0; - break; - - case 0x03: // time read - uPD4990.regsft = 0; - ZeroMemory(uPD4990.reg, sizeof(uPD4990.reg)); - calendar_get(uPD4990.reg + UPD4990_REGLEN - 6); - uPD4990.cdat = uPD4990.reg[UPD4990_REGLEN - 1] & 1; - // uPD4990 Happy!! :) - uPD4990.reg[UPD4990_REGLEN - 7] = 0x01; - break; -#if 0 - case 0x04: // TP=64Hz - case 0x05: // TP=256Hz - case 0x06: // TP=2048Hz - case 0x07: // TP=4096Hz - case 0x08: // TP=1sec interrupt - case 0x09: // TP=10sec interrupt - case 0x0a: // TP=30sec interrupt - case 0x0b: // TP=60sec interrupt - case 0x0c: // interrupt reset - case 0x0d: // interrupt start - case 0x0e: // interrupt stop - case 0x0f: // test.. - break; -#endif - } - } - } - else if (dat & 0x10) { // CLK - if (mod & 0x10) { - if (uPD4990.parallel == 7) { - uPD4990.serial >>= 1; - } - if ((uPD4990.regsft) && (uPD4990.pos)) { - uPD4990.pos--; - } - uPD4990.cdat = (uPD4990.reg[uPD4990.pos / 8] >> - ((~uPD4990.pos) & 7)) & 1; - } - } - else { // DATA - uPD4990.parallel = dat & 7; - if (uPD4990.parallel == 7) { - uPD4990.serial &= 0x0f; - uPD4990.serial |= (dat >> 1) & 0x10; - } - if (dat & 0x20) { - uPD4990.reg[uPD4990.pos / 8] |= (0x80 >> (uPD4990.pos & 7)); - } - else { - uPD4990.reg[uPD4990.pos / 8] &= ~(0x80 >> (uPD4990.pos & 7)); - } - } - (void)port; -} - -#ifdef SUPPORT_HRTIMER - -static void upd4990_hrtimer_setinterval(int absolute); - -void upd4990_hrtimer_proc(NEVENTITEM item) { - static UINT32 divcounter = 0; - static UINT32 divcounter32 = 0; - divcounter++; - if(divcounter >= 64 / uPD4990HRT.hrtimerdiv){ // 64 -> hrtimerdiv - pic_setirq(15); - divcounter = 0; - } - if(uPD4990HRT.hrtimerclock32){ - divcounter32++; - if(divcounter32 >= 2){ // 64 -> 32 - UINT32 hrtimertimeuint; - - hrtimertimeuint = LOADINTELDWORD(mem+0x04F1); - hrtimertimeuint++; - if((hrtimertimeuint & 0x3fffff) >= 24*60*60*32){ - hrtimertimeuint = ((hrtimertimeuint & ~0x3fffff) + 0x400000) & 0xffffff; // 日付変わった - } - STOREINTELDWORD(mem+0x04F1, hrtimertimeuint); // XXX: 04F4にも書いちゃってるけど差し当たっては問題なさそうなので・・・ - divcounter32 = 0; - } - } - upd4990_hrtimer_setinterval(0); -} -static void upd4990_hrtimer_setinterval(int absolute) { - if(uPD4990HRT.hrtimerclock > 0){ - nevent_set(NEVENT_HRTIMER, pccore.baseclock * pccore.multiple / 64, upd4990_hrtimer_proc, absolute ? NEVENT_ABSOLUTE : NEVENT_RELATIVE); - } -} - -static void upd4990_hrtimer_start(void) { - uPD4990HRT.hrtimerclock32 = pccore.baseclock / 32; - uPD4990HRT.clockcounter = 0; - uPD4990HRT.clockcounter32 = 0; -} -void upd4990_hrtimer_count(void) { - //if(uPD4990HRT.hrtimerclock){ - // uPD4990HRT.clockcounter += CPU_BASECLOCK; - // if(uPD4990HRT.clockcounter > uPD4990HRT.hrtimerclock*pccore.multiple){ - // uPD4990HRT.clockcounter -= uPD4990HRT.hrtimerclock*pccore.multiple; - - // pic_setirq(15); - // } - //} - //if(uPD4990HRT.hrtimerclock32){ - // uPD4990HRT.clockcounter32 += CPU_BASECLOCK; - // if(uPD4990HRT.clockcounter32 > uPD4990HRT.hrtimerclock32*pccore.multiple){ - // UINT32 hrtimertimeuint; - // uPD4990HRT.clockcounter32 -= uPD4990HRT.hrtimerclock32*pccore.multiple; - // - // hrtimertimeuint = LOADINTELDWORD(mem+0x04F1); - // hrtimertimeuint++; - // if((hrtimertimeuint & 0x3fffff) >= 24*60*60*32){ - // hrtimertimeuint = ((hrtimertimeuint & ‾0x3fffff) + 0x400000) & 0xffffff; // 日付変わった - // } - // STOREINTELDWORD(mem+0x04F1, hrtimertimeuint); // XXX: 04F4にも書いちゃってるけど差し当たっては問題なさそうなので・・・ - // } - //} -} - -int io22value = 0; -static void IOOUTCALL upd4990_o22(UINT port, REG8 dat) { - io22value = dat; - (void)port; -} -static REG8 IOOUTCALL upd4990_i22(UINT port) { - return io22value; -} - -static void IOOUTCALL upd4990_o128(UINT port, REG8 dat) { - REG8 dattmp = dat & 0x3; - switch(dattmp){ - case 0: - uPD4990HRT.hrtimerdiv = 64; - uPD4990HRT.hrtimerclock = pccore.baseclock/uPD4990HRT.hrtimerdiv; - break; - case 1: - uPD4990HRT.hrtimerdiv = 32; - uPD4990HRT.hrtimerclock = pccore.baseclock/uPD4990HRT.hrtimerdiv; - break; - case 2: - uPD4990HRT.hrtimerdiv = 0; - uPD4990HRT.hrtimerclock = 0;//pccore.realclock/uPD4990HRT.hrtimerdiv; - break; - case 3: - uPD4990HRT.hrtimerdiv = 16; - uPD4990HRT.hrtimerclock = pccore.baseclock/uPD4990HRT.hrtimerdiv; - break; - } - (void)port; -} - -static REG8 IOOUTCALL upd4990_i128(UINT port) { - pic_resetirq(15); - switch(uPD4990HRT.hrtimerdiv){ - case 64: - return(0x80); - case 32: - return(0x81); - case 0: - return(0x82); - case 16: - return(0x83); - } - return(0x81); -} -#endif - - -// ---- I/F - -static const IOOUT updo20[1] = {upd4990_o20}; - -void uPD4990_reset(const NP2CFG *pConfig) { - - ZeroMemory(&uPD4990, sizeof(uPD4990)); - -#if defined(SUPPORT_HRTIMER) - upd4990_hrtimer_start(); -#endif - - (void)pConfig; -} - -void uPD4990_bind(void) { - - iocore_attachsysoutex(0x0020, 0x0cf1, updo20, 1); -#ifdef SUPPORT_HRTIMER - iocore_attachout(0x0022, upd4990_o22); - iocore_attachinp(0x0022, upd4990_i22); - iocore_attachout(0x0128, upd4990_o128); - iocore_attachinp(0x0128, upd4990_i128); - - uPD4990HRT.hrtimerdiv = 32; - uPD4990HRT.hrtimerclock = pccore.baseclock/uPD4990HRT.hrtimerdiv; - upd4990_hrtimer_setinterval(1); -#endif -} - +#include +#include +#include +#include +#include +#if defined(SUPPORT_HRTIMER) +#include +#include "cpumem.h" +#endif /* SUPPORT_HRTIMER */ + + +// ---- I/O + +static void IOOUTCALL upd4990_o20(UINT port, REG8 dat) { + + REG8 mod; + REG8 cmd; + + mod = dat ^ uPD4990.last; + uPD4990.last = (UINT8)dat; + + if (dat & 0x08) { // STB + if (mod & 0x08) { + cmd = uPD4990.parallel; + if (cmd == 7) { + cmd = uPD4990.serial & 0x0f; + } + switch(cmd) { + case 0x00: // register hold + uPD4990.regsft = 0; + break; + + case 0x01: // register shift + uPD4990.regsft = 1; + uPD4990.pos = (UPD4990_REGLEN * 8) - 1; + uPD4990.cdat = uPD4990.reg[UPD4990_REGLEN - 1] & 1; + break; + + case 0x02: // time set / counter hold + uPD4990.regsft = 0; + break; + + case 0x03: // time read + uPD4990.regsft = 0; + ZeroMemory(uPD4990.reg, sizeof(uPD4990.reg)); + calendar_get(uPD4990.reg + UPD4990_REGLEN - 6); + uPD4990.cdat = uPD4990.reg[UPD4990_REGLEN - 1] & 1; + // uPD4990 Happy!! :) + uPD4990.reg[UPD4990_REGLEN - 7] = 0x01; + break; +#if 0 + case 0x04: // TP=64Hz + case 0x05: // TP=256Hz + case 0x06: // TP=2048Hz + case 0x07: // TP=4096Hz + case 0x08: // TP=1sec interrupt + case 0x09: // TP=10sec interrupt + case 0x0a: // TP=30sec interrupt + case 0x0b: // TP=60sec interrupt + case 0x0c: // interrupt reset + case 0x0d: // interrupt start + case 0x0e: // interrupt stop + case 0x0f: // test.. + break; +#endif + } + } + } + else if (dat & 0x10) { // CLK + if (mod & 0x10) { + if (uPD4990.parallel == 7) { + uPD4990.serial >>= 1; + } + if ((uPD4990.regsft) && (uPD4990.pos)) { + uPD4990.pos--; + } + uPD4990.cdat = (uPD4990.reg[uPD4990.pos / 8] >> + ((~uPD4990.pos) & 7)) & 1; + } + } + else { // DATA + uPD4990.parallel = dat & 7; + if (uPD4990.parallel == 7) { + uPD4990.serial &= 0x0f; + uPD4990.serial |= (dat >> 1) & 0x10; + } + if (dat & 0x20) { + uPD4990.reg[uPD4990.pos / 8] |= (0x80 >> (uPD4990.pos & 7)); + } + else { + uPD4990.reg[uPD4990.pos / 8] &= ~(0x80 >> (uPD4990.pos & 7)); + } + } + (void)port; +} + +#ifdef SUPPORT_HRTIMER + +static void upd4990_hrtimer_setinterval(int absolute); + +void upd4990_hrtimer_proc(NEVENTITEM item) { + static UINT32 divcounter = 0; + static UINT32 divcounter32 = 0; + divcounter++; + if(divcounter >= 64 / uPD4990HRT.hrtimerdiv){ // 64 -> hrtimerdiv + pic_setirq(15); + divcounter = 0; + } + if(uPD4990HRT.hrtimerclock32){ + divcounter32++; + if(divcounter32 >= 2){ // 64 -> 32 + UINT32 hrtimertimeuint; + + hrtimertimeuint = LOADINTELDWORD(mem+0x04F1); + hrtimertimeuint++; + if((hrtimertimeuint & 0x3fffff) >= 24*60*60*32){ + hrtimertimeuint = ((hrtimertimeuint & ~0x3fffff) + 0x400000) & 0xffffff; // 日付変わった + } + STOREINTELDWORD(mem+0x04F1, hrtimertimeuint); // XXX: 04F4にも書いちゃってるけど差し当たっては問題なさそうなので・・・ + divcounter32 = 0; + } + } + upd4990_hrtimer_setinterval(0); +} +static void upd4990_hrtimer_setinterval(int absolute) { + if(uPD4990HRT.hrtimerclock > 0){ + nevent_set(NEVENT_HRTIMER, pccore.baseclock * pccore.multiple / 64, upd4990_hrtimer_proc, absolute ? NEVENT_ABSOLUTE : NEVENT_RELATIVE); + } +} + +static void upd4990_hrtimer_start(void) { + uPD4990HRT.hrtimerclock32 = pccore.baseclock / 32; + uPD4990HRT.clockcounter = 0; + uPD4990HRT.clockcounter32 = 0; +} +void upd4990_hrtimer_count(void) { + //if(uPD4990HRT.hrtimerclock){ + // uPD4990HRT.clockcounter += CPU_BASECLOCK; + // if(uPD4990HRT.clockcounter > uPD4990HRT.hrtimerclock*pccore.multiple){ + // uPD4990HRT.clockcounter -= uPD4990HRT.hrtimerclock*pccore.multiple; + + // pic_setirq(15); + // } + //} + //if(uPD4990HRT.hrtimerclock32){ + // uPD4990HRT.clockcounter32 += CPU_BASECLOCK; + // if(uPD4990HRT.clockcounter32 > uPD4990HRT.hrtimerclock32*pccore.multiple){ + // UINT32 hrtimertimeuint; + // uPD4990HRT.clockcounter32 -= uPD4990HRT.hrtimerclock32*pccore.multiple; + // + // hrtimertimeuint = LOADINTELDWORD(mem+0x04F1); + // hrtimertimeuint++; + // if((hrtimertimeuint & 0x3fffff) >= 24*60*60*32){ + // hrtimertimeuint = ((hrtimertimeuint & ‾0x3fffff) + 0x400000) & 0xffffff; // 日付変わった + // } + // STOREINTELDWORD(mem+0x04F1, hrtimertimeuint); // XXX: 04F4にも書いちゃってるけど差し当たっては問題なさそうなので・・・ + // } + //} +} + +int io22value = 0; +static void IOOUTCALL upd4990_o22(UINT port, REG8 dat) { + io22value = dat; + (void)port; +} +static REG8 IOOUTCALL upd4990_i22(UINT port) { + return io22value; +} + +static void IOOUTCALL upd4990_o128(UINT port, REG8 dat) { + REG8 dattmp = dat & 0x3; + switch(dattmp){ + case 0: + uPD4990HRT.hrtimerdiv = 64; + uPD4990HRT.hrtimerclock = pccore.baseclock/uPD4990HRT.hrtimerdiv; + break; + case 1: + uPD4990HRT.hrtimerdiv = 32; + uPD4990HRT.hrtimerclock = pccore.baseclock/uPD4990HRT.hrtimerdiv; + break; + case 2: + uPD4990HRT.hrtimerdiv = 0; + uPD4990HRT.hrtimerclock = 0;//pccore.realclock/uPD4990HRT.hrtimerdiv; + break; + case 3: + uPD4990HRT.hrtimerdiv = 16; + uPD4990HRT.hrtimerclock = pccore.baseclock/uPD4990HRT.hrtimerdiv; + break; + } + (void)port; +} + +static REG8 IOOUTCALL upd4990_i128(UINT port) { + pic_resetirq(15); + switch(uPD4990HRT.hrtimerdiv){ + case 64: + return(0x80); + case 32: + return(0x81); + case 0: + return(0x82); + case 16: + return(0x83); + } + return(0x81); +} +#endif + + +// ---- I/F + +static const IOOUT updo20[1] = {upd4990_o20}; + +void uPD4990_reset(const NP2CFG *pConfig) { + + ZeroMemory(&uPD4990, sizeof(uPD4990)); + +#if defined(SUPPORT_HRTIMER) + upd4990_hrtimer_start(); +#endif + + (void)pConfig; +} + +void uPD4990_bind(void) { + + iocore_attachsysoutex(0x0020, 0x0cf1, updo20, 1); +#ifdef SUPPORT_HRTIMER + iocore_attachout(0x0022, upd4990_o22); + iocore_attachinp(0x0022, upd4990_i22); + iocore_attachout(0x0128, upd4990_o128); + iocore_attachinp(0x0128, upd4990_i128); + + uPD4990HRT.hrtimerdiv = 32; + uPD4990HRT.hrtimerclock = pccore.baseclock/uPD4990HRT.hrtimerdiv; + upd4990_hrtimer_setinterval(1); +#endif +} + diff --git a/keystat.c b/keystat.c old mode 100755 new mode 100644 index deb1f309..530f0558 --- a/keystat.c +++ b/keystat.c @@ -1,720 +1,720 @@ -#include -#include -#include -#include -#include -#include -#include "keystat.tbl" -#include - - -// Keyrepeat -#define KEYREPEAT_BUF_MAX 16 -#define KEYREPEAT_DELAY np2cfg.keyrepeat_delay -#define KEYREPEAT_INTERVAL np2cfg.keyrepeat_interval - -static UINT8 keyrepeat_buf[KEYREPEAT_BUF_MAX]; -static int keyrepeat_index = 0; -static BOOL keyrepeat_delay_flag = FALSE; -static UINT32 keyrepeat_delay = 0; -static UINT32 keyrepeat_interval = 0; - -static void keystat_send(REG8 data); -#define KEYBOARD_SEND(d) np2cfg.keyrepeat_enable ? keystat_send(d):keyboard_send(d) - - - NKEYTBL nkeytbl; - KEYCTRL keyctrl; - KEYSTAT keystat; - - -void keystat_initialize(void) { - - OEMCHAR path[MAX_PATH]; - - ZeroMemory(&keyctrl, sizeof(keyctrl)); - keyctrl.keyrep = 0x21; - keyctrl.capsref = NKEYREF_NC; - keyctrl.kanaref = NKEYREF_NC; -#if defined(SUPPORT_PC9801_119) - keyctrl.kbdtype = 1; // KEYBOARD MODE WIN95 -#endif - - ZeroMemory(&keystat, sizeof(keystat)); - FillMemory(keystat.ref, sizeof(keystat.ref), NKEYREF_NC); - keystat_tblreset(); - getbiospath(path, OEMTEXT("key.txt"), NELEMENTS(path)); - keystat_tblload(path); -} - -void keystat_tblreset(void) { - - UINT i; - - ZeroMemory(&nkeytbl, sizeof(nkeytbl)); - for (i=0; i<0x80; i++) { - nkeytbl.key[i].keys = 1; - nkeytbl.key[i].key[0] = (UINT8)i; - } - for (i=0; i<0x10; i++) { - nkeytbl.key[i+0x80].keys = 1; - nkeytbl.key[i+0x80].key[0] = (UINT8)(i + 0xf0); - } -} - -void keystat_tblset(REG8 ref, const UINT8 *key, UINT cnt) { - - NKEYM *nkey; - - if ((ref >= NKEY_USER) && (ref < (NKEY_USER + NKEY_USERKEYS))) { - nkey = (NKEYM *)(nkeytbl.user + (ref - NKEY_USER)); - cnt = MIN(cnt, 15); - } - else if (ref < NKEY_SYSTEM) { - nkey = (NKEYM *)(nkeytbl.key + ref); - cnt = MIN(cnt, 3); - } - else { - return; - } - nkey->keys = (UINT8)cnt; - if (cnt) { - CopyMemory(nkey->key, key, cnt); - } -} - - -// ---- config... - -static const OEMCHAR str_userkey1[] = OEMTEXT("userkey1"); -static const OEMCHAR str_userkey2[] = OEMTEXT("userkey2"); - -static REG8 searchkeynum(const OEMCHAR *str, BOOL user) { - -const KEYNAME *n; -const KEYNAME *nterm; - - n = s_keyname; - nterm = s_keyname + NELEMENTS(s_keyname); - while(n < nterm) { - if (!milstr_cmp(n->str, str)) { - return(n->num); - } - n++; - } - if (user) { - if (!milstr_cmp(str_userkey1, str)) { - return(NKEY_USER + 0); - } - if (!milstr_cmp(str_userkey2, str)) { - return(NKEY_USER + 1); - } - } - return(0xff); -} - -void keystat_tblload(const OEMCHAR *filename) { - - TEXTFILEH tfh; - OEMCHAR work[256]; - OEMCHAR *p; - OEMCHAR *q; - OEMCHAR *r; - UINT8 ref; - UINT8 key[15]; - UINT cnt; - - tfh = textfile_open(filename, 0x800); - if (tfh == NULL) { - goto kstbl_err; - } - while(textfile_read(tfh, work, NELEMENTS(work)) == SUCCESS) { - p = milstr_nextword(work); - q = milstr_chr(p, '\t'); - if (q == NULL) { - q = milstr_chr(p, '='); - } - if (q == NULL) { - continue; - } - *q++ = '\0'; - r = milstr_chr(p, ' '); - if (r != NULL) { - *r = '\0'; - } - ref = searchkeynum(p, TRUE); - if (ref == 0xff) { - continue; - } - cnt = 0; - while((q) && (cnt < 16)) { - p = milstr_nextword(q); - q = milstr_chr(p, ' '); - if (q != NULL) { - *q++ = '\0'; - } - key[cnt] = searchkeynum(p, FALSE); - if (key[cnt] != 0xff) { - cnt++; - } - } - keystat_tblset(ref, key, cnt); - } - textfile_close(tfh); - -kstbl_err: - return; -} - - -// ---- - -static REG8 getledstat(void) { - - REG8 ret; - - ret = 0; - if (keyctrl.kanaref != NKEYREF_NC) { - ret |= 8; - } - if (keyctrl.capsref != NKEYREF_NC) { - ret |= 4; - } - return(ret); -} - -static void reloadled(void) { - - keyctrl.kanaref = keystat.ref[0x72]; - keyctrl.capsref = keystat.ref[0x71]; -#if defined(SUPPORT_SOFTKBD) - softkbd_led(getledstat()); -#endif -} - -void keystat_ctrlreset(void) { - - keyctrl.reqparam = 0; - keystat.ref[0x72] = keyctrl.kanaref; - keystat.ref[0x71] = keyctrl.capsref; -#if defined(SUPPORT_SOFTKBD) - softkbd_led(getledstat()); -#endif -} - -void keystat_ctrlsend(REG8 dat) { - - if (!keyctrl.reqparam) { - keyctrl.mode = dat; - switch(dat) { -#if defined(SUPPORT_PC9801_119) - case 0x95: -#endif - case 0x9c: - case 0x9d: - keyctrl.reqparam = 1; - keyboard_ctrl(0xfa); - break; - -#if defined(SUPPORT_PC9801_119) - case 0x96: - keyboard_ctrl(0xfa); - keyboard_ctrl(0xa0); - keyboard_ctrl(0x83); - break; -#endif - - case 0x9f: - keyboard_ctrl(0xfa); - keyboard_ctrl(0xa0); - keyboard_ctrl(0x80); - break; - - default: - keyboard_ctrl(0xfc); - break; - } - } - else { - switch(keyctrl.mode) { -#if defined(SUPPORT_PC9801_119) - case 0x95: - keyctrl.kbdtype = dat; - keyboard_ctrl(0xfa); - break; -#endif - case 0x9c: - keyctrl.keyrep = dat; - keyboard_ctrl(0xfa); - break; - - case 0x9d: - if (dat == 0x60) { - keyboard_ctrl(0xfa); - keyboard_ctrl((REG8)(0x70 + getledstat())); - } - else if ((dat & 0xf0) == 0x70) { - keyboard_ctrl(0xfa); - keystat.ref[0x72] = (dat & 8)?NKEYREF_uPD8255:NKEYREF_NC; - keystat.ref[0x71] = (dat & 4)?NKEYREF_uPD8255:NKEYREF_NC; - reloadled(); - } - break; - } - keyctrl.reqparam = 0; - } -} - - -// ---- - -void keystat_down(const UINT8 *key, REG8 keys, REG8 ref) { - - UINT8 keydata; - UINT8 keycode; - REG8 data; - - while(keys--) { - keydata = *key++; - keycode = (keydata & 0x7f); - if (keycode <= 0x70) { -#if 1 // 05/02/04 - if (keystat.ref[keycode] != NKEYREF_NC) { - // 0x70 = STOP AUTO REPEAT - if (keyctrl.keyrep != 0x70 && !(kbexflag[keycode] & KBEX_NONREP)) { - KEYBOARD_SEND((REG8)(keycode + 0x80)); - keystat.ref[keycode] = NKEYREF_NC; - } - } - if (keystat.ref[keycode] == NKEYREF_NC) { - KEYBOARD_SEND(keycode); - } -#else - if ((keystat.ref[keycode] == NKEYREF_NC) || - (!(kbexflag[keycode] & KBEX_NONREP))) { - KEYBOARD_SEND(keycode); - } -#endif - keystat.ref[keycode] = ref; - } - else { -#if defined(SUPPORT_PC9801_119) - if (keyctrl.kbdtype < 2) // KEYBOARD MODE SHIFT SEPARATE DISABLE -#endif - { - if (keycode == 0x7d) - { - keycode = 0x70; - } - } -#if defined(SUPPORT_PC9801_119) - if (keyctrl.kbdtype < 3) // KEYBOARD MODE WINKEYS DISABLE -#endif - { - if (keycode >= 0x75) - { - continue; - } - } - if ((np2cfg.XSHIFT) && - (((keycode == 0x70) && (np2cfg.XSHIFT & 1)) || - ((keycode == 0x74) && (np2cfg.XSHIFT & 2)) || - ((keycode == 0x73) && (np2cfg.XSHIFT & 4)))) { - keydata |= 0x80; - } - if (!(keydata & 0x80)) { // シフト - if (keystat.ref[keycode] == NKEYREF_NC) { - keystat.ref[keycode] = ref; - KEYBOARD_SEND(keycode); - } - } - else { // シフトメカニカル処理 - if (keystat.ref[keycode] == NKEYREF_NC) { - keystat.ref[keycode] = ref; - data = keycode; - } - else { - keystat.ref[keycode] = NKEYREF_NC; - data = (REG8)(keycode + 0x80); - } - KEYBOARD_SEND(data); - } - if ((keycode == 0x71) || (keycode == 0x72)) { - reloadled(); - } - } - } -} - -void keystat_up(const UINT8 *key, REG8 keys, REG8 ref) { - - UINT8 keydata; - UINT8 keycode; - - while(keys--) { - keydata = *key++; - keycode = (keydata & 0x7f); - if (keycode <= 0x70) { - if (keystat.ref[keycode] == ref) { - keystat.ref[keycode] = NKEYREF_NC; - KEYBOARD_SEND((REG8)(keycode + 0x80)); - } - } - else { -#if defined(SUPPORT_PC9801_119) - if (keyctrl.kbdtype < 2) // KEYBOARD MODE SHIFT SEPARATE DISABLE -#endif - { - if (keycode == 0x7d) - { - keycode = 0x70; - } - } -#if defined(SUPPORT_PC9801_119) - if (keyctrl.kbdtype < 3) // KEYBOARD MODE WINKEYS DISABLE -#endif - { - if (keycode >= 0x75) - { - continue; - } - } - if ((np2cfg.XSHIFT) && - (((keycode == 0x70) && (np2cfg.XSHIFT & 1)) || - ((keycode == 0x74) && (np2cfg.XSHIFT & 2)) || - ((keycode == 0x73) && (np2cfg.XSHIFT & 4)))) { - keydata |= 0x80; - } - if (!(keydata & 0x80)) { // シフト - if (keystat.ref[keycode] != NKEYREF_NC) { - keystat.ref[keycode] = NKEYREF_NC; - KEYBOARD_SEND((REG8)(keycode + 0x80)); - if ((keycode == 0x71) || (keycode == 0x72)) { - reloadled(); - } - } - } - } - } -} - -void keystat_resendstat(void) { - - REG8 i; - - for (i=0; i<0x80; i++) { - if (keystat.ref[i] != NKEYREF_NC) { - keyboard_send(i); - } - } - keyrepeat_delay_flag = FALSE; - keyrepeat_index = 0; -} - - -// ---- - -void keystat_keydown(REG8 ref) { - - UINT8 shift; -const NKEYM *nkey; - - if ((ref >= NKEY_USER) && (ref < (NKEY_USER + NKEY_USERKEYS))) { - nkey = (NKEYM *)(nkeytbl.user + (ref - NKEY_USER)); - keystat_down(nkey->key, nkey->keys, NKEYREF_USER); - } - else if (ref < NKEY_SYSTEM) { - if (np2cfg.KEY_MODE) { - shift = kbexflag[ref]; - if (shift & KBEX_JOYKEY) { - keystat.extkey |= (1 << (shift & 7)); - return; - } - } - nkey = (NKEYM *)(nkeytbl.key + ref); - keystat_down(nkey->key, nkey->keys, ref); - } -} - -void keystat_keyup(REG8 ref) { - - UINT8 shift; -const NKEYM *nkey; - - if ((ref >= NKEY_USER) && (ref < (NKEY_USER + NKEY_USERKEYS))) { - nkey = (NKEYM *)(nkeytbl.user + (ref - NKEY_USER)); - keystat_up(nkey->key, nkey->keys, NKEYREF_USER); - } - else if (ref < NKEY_SYSTEM) { - if (np2cfg.KEY_MODE) { - shift = kbexflag[ref]; - if (shift & KBEX_JOYKEY) { - keystat.extkey &= ~(1 << (shift & 7)); - return; - } - } - nkey = (NKEYM *)(nkeytbl.key + ref); - keystat_up(nkey->key, nkey->keys, ref); - } -} - -void keystat_releaseref(REG8 ref) { - - REG8 i; - - for (i=0; i<0x80; i++) { - if (keystat.ref[i] == ref) { - keystat.ref[i] = NKEYREF_NC; - KEYBOARD_SEND((REG8)(i + 0x80)); - } - } -} - -void keystat_resetjoykey(void) { - - REG8 i; - - keystat.extkey = 0; - for (i=0; i<0x80; i++) { - if (kbexflag[i] & KBEX_JOYKEY) { - keystat_releaseref(i); - } - } -} - - -void keystat_releasekey(REG8 key) { - - key &= 0x7f; - if ((key != 0x71) && (key != 0x72)) { - if (keystat.ref[key] != NKEYREF_NC) { - keystat.ref[key] = NKEYREF_NC; - KEYBOARD_SEND((REG8)(key + 0x80)); - } - } -} - -void keystat_allrelease(void) { - - REG8 i; - - for (i=0; i<0x80; i++) { - keystat_releasekey(i); - } -} - - -REG8 keystat_getjoy(void) { - - return(~keystat.extkey); -} - -REG8 keystat_getmouse(SINT16 *x, SINT16 *y) { - - REG8 btn; - UINT8 acc; - SINT16 tmp; - REG8 ret; - - btn = ~keystat.extkey; - acc = btn | keystat.mouselast; - keystat.mouselast = (UINT8)btn; - tmp = 0; - if (!(btn & 1)) { - tmp -= mousedelta[keystat.d_up]; - } - if (!(acc & 1)) { - if (keystat.d_up < MOUSESTEPMAX) { - keystat.d_up++; - } - } - else { - keystat.d_up = 0; - } - if (!(btn & 2)) { - tmp += mousedelta[keystat.d_dn]; - } - if (!(acc & 2)) { - if (keystat.d_dn < MOUSESTEPMAX) { - keystat.d_dn++; - } - } - else { - keystat.d_dn = 0; - } - *y += tmp; - - tmp = 0; - if (!(btn & 4)) { - tmp -= mousedelta[keystat.d_lt]; - } - if (!(acc & 4)) { - if (keystat.d_lt < MOUSESTEPMAX) { - keystat.d_lt++; - } - } - else { - keystat.d_lt = 0; - } - if (!(btn & 8)) { - tmp += mousedelta[keystat.d_rt]; - } - if (!(acc & 8)) { - if (keystat.d_rt < MOUSESTEPMAX) { - keystat.d_rt++; - } - } - else { - keystat.d_rt = 0; - } - *x += tmp; - - ret = 0x5f; - ret += (btn & 0x10) << 3; - ret += (btn & 0x20); - return(ret); -} - - -// ---- - -// キーコード変更 - -static REG8 cnvnewcode(REG8 oldcode) { - - switch(oldcode) { - case 0x71: // 通常caps - return(0x81); - - case 0x72: // 通常カナ - return(0x82); - - case 0x79: // メカニカルロックcaps - return(0x71); - - case 0x7a: // メカニカルロックkana - return(0x72); - - case 0x76: - return(0x90); // NKEY_USER + 0 - - case 0x77: - return(0x91); // NKEY_USER + 1 - - default: - return(oldcode); - } -} - -void keystat_senddata(REG8 data) { - - REG8 keycode; - - keycode = cnvnewcode((REG8)(data & 0x7f)); - if (!(data & 0x80)) { - keystat_keydown(keycode); - } - else { - keystat_keyup(keycode); - } -} -void keystat_senddataraw(REG8 data) { - - REG8 keycode; - - keycode = (REG8)(data & 0x7f); - if (!(data & 0x80)) { - keystat_keydown(keycode); - } - else { - keystat_keyup(keycode); - } -} - -void keystat_forcerelease(REG8 data) { - - REG8 keycode; - - keycode = cnvnewcode((REG8)(data & 0x7f)); - keystat_releasekey(keycode); -} - -// Keyrepeat -static void keystat_send(REG8 data) { - UINT8 keycode = data & 0x7f; - int i; - - if(kbexflag[keycode] & KBEX_NONREP) { // none repeat key - keyboard_send(data); - return; - } - if(!(data & 0x80)) { // key down - if(keyrepeat_index >= KEYREPEAT_BUF_MAX) { // keyreat buf full - // Nothing - return; - } - // If the keycode is stored in the repeat buffer, return - for(i = 0; i < keyrepeat_index; i++) { - if(keyrepeat_buf[i] == keycode) { - return; - } - } - // Add the keycode to keyrepeat buffer - keyrepeat_buf[keyrepeat_index] = keycode; - keyrepeat_index++; - // Delay flag ON - keyrepeat_delay_flag = TRUE; - keyrepeat_delay = GETTICK(); - // Send keycode(make) - keyboard_send(data); - } else { // key up - // Remove keycode from the keyrepeat buffer - if(keyrepeat_index) { - for(i = keyrepeat_index - 1; i >= 0; i--) { - if(keyrepeat_buf[i] == keycode) { - // Remove keycode from the keyrepeat buffer - if(i == keyrepeat_index - 1) { - keyrepeat_delay_flag = TRUE; - keyrepeat_delay = GETTICK(); - } - for(; i < keyrepeat_index - 1; i++) { - keyrepeat_buf[i] = keyrepeat_buf[i+1]; - } - keyrepeat_index--; - break; - } - } - } - // Send keycode(break) - keyboard_send(data); - } -} - -// keyrepeat interval processing -void keyrepeat_proc() { - // If the keyrepeat buffer is empty, return - if(!keyrepeat_index) { - return; - } - if(keyrepeat_delay_flag) { // If Delay flag is ON, - UINT32 dt = GETTICK() - keyrepeat_delay; - // If it hasn't been (delay time - repeat time) yet, return - if(dt < KEYREPEAT_DELAY - KEYREPEAT_INTERVAL) { - return; - } - // Delay flag OFF - keyrepeat_delay_flag = FALSE; - keyrepeat_delay = 0; - keyrepeat_interval = GETTICK(); - } else { // If Delay flag is OFF, - UINT32 dt = GETTICK() - keyrepeat_interval; - // If is has been repeat time, - if(dt >= KEYREPEAT_INTERVAL) { - UINT8 keycode = keyrepeat_buf[keyrepeat_index-1]; - keyrepeat_interval = GETTICK(); - keyboard_send(keycode | 0x80); - keyboard_send(keycode); - } - - } -} +#include +#include +#include +#include +#include +#include +#include "keystat.tbl" +#include + + +// Keyrepeat +#define KEYREPEAT_BUF_MAX 16 +#define KEYREPEAT_DELAY np2cfg.keyrepeat_delay +#define KEYREPEAT_INTERVAL np2cfg.keyrepeat_interval + +static UINT8 keyrepeat_buf[KEYREPEAT_BUF_MAX]; +static int keyrepeat_index = 0; +static BOOL keyrepeat_delay_flag = FALSE; +static UINT32 keyrepeat_delay = 0; +static UINT32 keyrepeat_interval = 0; + +static void keystat_send(REG8 data); +#define KEYBOARD_SEND(d) np2cfg.keyrepeat_enable ? keystat_send(d):keyboard_send(d) + + + NKEYTBL nkeytbl; + KEYCTRL keyctrl; + KEYSTAT keystat; + + +void keystat_initialize(void) { + + OEMCHAR path[MAX_PATH]; + + ZeroMemory(&keyctrl, sizeof(keyctrl)); + keyctrl.keyrep = 0x21; + keyctrl.capsref = NKEYREF_NC; + keyctrl.kanaref = NKEYREF_NC; +#if defined(SUPPORT_PC9801_119) + keyctrl.kbdtype = 1; // KEYBOARD MODE WIN95 +#endif + + ZeroMemory(&keystat, sizeof(keystat)); + FillMemory(keystat.ref, sizeof(keystat.ref), NKEYREF_NC); + keystat_tblreset(); + getbiospath(path, OEMTEXT("key.txt"), NELEMENTS(path)); + keystat_tblload(path); +} + +void keystat_tblreset(void) { + + UINT i; + + ZeroMemory(&nkeytbl, sizeof(nkeytbl)); + for (i=0; i<0x80; i++) { + nkeytbl.key[i].keys = 1; + nkeytbl.key[i].key[0] = (UINT8)i; + } + for (i=0; i<0x10; i++) { + nkeytbl.key[i+0x80].keys = 1; + nkeytbl.key[i+0x80].key[0] = (UINT8)(i + 0xf0); + } +} + +void keystat_tblset(REG8 ref, const UINT8 *key, UINT cnt) { + + NKEYM *nkey; + + if ((ref >= NKEY_USER) && (ref < (NKEY_USER + NKEY_USERKEYS))) { + nkey = (NKEYM *)(nkeytbl.user + (ref - NKEY_USER)); + cnt = MIN(cnt, 15); + } + else if (ref < NKEY_SYSTEM) { + nkey = (NKEYM *)(nkeytbl.key + ref); + cnt = MIN(cnt, 3); + } + else { + return; + } + nkey->keys = (UINT8)cnt; + if (cnt) { + CopyMemory(nkey->key, key, cnt); + } +} + + +// ---- config... + +static const OEMCHAR str_userkey1[] = OEMTEXT("userkey1"); +static const OEMCHAR str_userkey2[] = OEMTEXT("userkey2"); + +static REG8 searchkeynum(const OEMCHAR *str, BOOL user) { + +const KEYNAME *n; +const KEYNAME *nterm; + + n = s_keyname; + nterm = s_keyname + NELEMENTS(s_keyname); + while(n < nterm) { + if (!milstr_cmp(n->str, str)) { + return(n->num); + } + n++; + } + if (user) { + if (!milstr_cmp(str_userkey1, str)) { + return(NKEY_USER + 0); + } + if (!milstr_cmp(str_userkey2, str)) { + return(NKEY_USER + 1); + } + } + return(0xff); +} + +void keystat_tblload(const OEMCHAR *filename) { + + TEXTFILEH tfh; + OEMCHAR work[256]; + OEMCHAR *p; + OEMCHAR *q; + OEMCHAR *r; + UINT8 ref; + UINT8 key[15]; + UINT cnt; + + tfh = textfile_open(filename, 0x800); + if (tfh == NULL) { + goto kstbl_err; + } + while(textfile_read(tfh, work, NELEMENTS(work)) == SUCCESS) { + p = milstr_nextword(work); + q = milstr_chr(p, '\t'); + if (q == NULL) { + q = milstr_chr(p, '='); + } + if (q == NULL) { + continue; + } + *q++ = '\0'; + r = milstr_chr(p, ' '); + if (r != NULL) { + *r = '\0'; + } + ref = searchkeynum(p, TRUE); + if (ref == 0xff) { + continue; + } + cnt = 0; + while((q) && (cnt < 16)) { + p = milstr_nextword(q); + q = milstr_chr(p, ' '); + if (q != NULL) { + *q++ = '\0'; + } + key[cnt] = searchkeynum(p, FALSE); + if (key[cnt] != 0xff) { + cnt++; + } + } + keystat_tblset(ref, key, cnt); + } + textfile_close(tfh); + +kstbl_err: + return; +} + + +// ---- + +static REG8 getledstat(void) { + + REG8 ret; + + ret = 0; + if (keyctrl.kanaref != NKEYREF_NC) { + ret |= 8; + } + if (keyctrl.capsref != NKEYREF_NC) { + ret |= 4; + } + return(ret); +} + +static void reloadled(void) { + + keyctrl.kanaref = keystat.ref[0x72]; + keyctrl.capsref = keystat.ref[0x71]; +#if defined(SUPPORT_SOFTKBD) + softkbd_led(getledstat()); +#endif +} + +void keystat_ctrlreset(void) { + + keyctrl.reqparam = 0; + keystat.ref[0x72] = keyctrl.kanaref; + keystat.ref[0x71] = keyctrl.capsref; +#if defined(SUPPORT_SOFTKBD) + softkbd_led(getledstat()); +#endif +} + +void keystat_ctrlsend(REG8 dat) { + + if (!keyctrl.reqparam) { + keyctrl.mode = dat; + switch(dat) { +#if defined(SUPPORT_PC9801_119) + case 0x95: +#endif + case 0x9c: + case 0x9d: + keyctrl.reqparam = 1; + keyboard_ctrl(0xfa); + break; + +#if defined(SUPPORT_PC9801_119) + case 0x96: + keyboard_ctrl(0xfa); + keyboard_ctrl(0xa0); + keyboard_ctrl(0x83); + break; +#endif + + case 0x9f: + keyboard_ctrl(0xfa); + keyboard_ctrl(0xa0); + keyboard_ctrl(0x80); + break; + + default: + keyboard_ctrl(0xfc); + break; + } + } + else { + switch(keyctrl.mode) { +#if defined(SUPPORT_PC9801_119) + case 0x95: + keyctrl.kbdtype = dat; + keyboard_ctrl(0xfa); + break; +#endif + case 0x9c: + keyctrl.keyrep = dat; + keyboard_ctrl(0xfa); + break; + + case 0x9d: + if (dat == 0x60) { + keyboard_ctrl(0xfa); + keyboard_ctrl((REG8)(0x70 + getledstat())); + } + else if ((dat & 0xf0) == 0x70) { + keyboard_ctrl(0xfa); + keystat.ref[0x72] = (dat & 8)?NKEYREF_uPD8255:NKEYREF_NC; + keystat.ref[0x71] = (dat & 4)?NKEYREF_uPD8255:NKEYREF_NC; + reloadled(); + } + break; + } + keyctrl.reqparam = 0; + } +} + + +// ---- + +void keystat_down(const UINT8 *key, REG8 keys, REG8 ref) { + + UINT8 keydata; + UINT8 keycode; + REG8 data; + + while(keys--) { + keydata = *key++; + keycode = (keydata & 0x7f); + if (keycode <= 0x70) { +#if 1 // 05/02/04 + if (keystat.ref[keycode] != NKEYREF_NC) { + // 0x70 = STOP AUTO REPEAT + if (keyctrl.keyrep != 0x70 && !(kbexflag[keycode] & KBEX_NONREP)) { + KEYBOARD_SEND((REG8)(keycode + 0x80)); + keystat.ref[keycode] = NKEYREF_NC; + } + } + if (keystat.ref[keycode] == NKEYREF_NC) { + KEYBOARD_SEND(keycode); + } +#else + if ((keystat.ref[keycode] == NKEYREF_NC) || + (!(kbexflag[keycode] & KBEX_NONREP))) { + KEYBOARD_SEND(keycode); + } +#endif + keystat.ref[keycode] = ref; + } + else { +#if defined(SUPPORT_PC9801_119) + if (keyctrl.kbdtype < 2) // KEYBOARD MODE SHIFT SEPARATE DISABLE +#endif + { + if (keycode == 0x7d) + { + keycode = 0x70; + } + } +#if defined(SUPPORT_PC9801_119) + if (keyctrl.kbdtype < 3) // KEYBOARD MODE WINKEYS DISABLE +#endif + { + if (keycode >= 0x75) + { + continue; + } + } + if ((np2cfg.XSHIFT) && + (((keycode == 0x70) && (np2cfg.XSHIFT & 1)) || + ((keycode == 0x74) && (np2cfg.XSHIFT & 2)) || + ((keycode == 0x73) && (np2cfg.XSHIFT & 4)))) { + keydata |= 0x80; + } + if (!(keydata & 0x80)) { // シフト + if (keystat.ref[keycode] == NKEYREF_NC) { + keystat.ref[keycode] = ref; + KEYBOARD_SEND(keycode); + } + } + else { // シフトメカニカル処理 + if (keystat.ref[keycode] == NKEYREF_NC) { + keystat.ref[keycode] = ref; + data = keycode; + } + else { + keystat.ref[keycode] = NKEYREF_NC; + data = (REG8)(keycode + 0x80); + } + KEYBOARD_SEND(data); + } + if ((keycode == 0x71) || (keycode == 0x72)) { + reloadled(); + } + } + } +} + +void keystat_up(const UINT8 *key, REG8 keys, REG8 ref) { + + UINT8 keydata; + UINT8 keycode; + + while(keys--) { + keydata = *key++; + keycode = (keydata & 0x7f); + if (keycode <= 0x70) { + if (keystat.ref[keycode] == ref) { + keystat.ref[keycode] = NKEYREF_NC; + KEYBOARD_SEND((REG8)(keycode + 0x80)); + } + } + else { +#if defined(SUPPORT_PC9801_119) + if (keyctrl.kbdtype < 2) // KEYBOARD MODE SHIFT SEPARATE DISABLE +#endif + { + if (keycode == 0x7d) + { + keycode = 0x70; + } + } +#if defined(SUPPORT_PC9801_119) + if (keyctrl.kbdtype < 3) // KEYBOARD MODE WINKEYS DISABLE +#endif + { + if (keycode >= 0x75) + { + continue; + } + } + if ((np2cfg.XSHIFT) && + (((keycode == 0x70) && (np2cfg.XSHIFT & 1)) || + ((keycode == 0x74) && (np2cfg.XSHIFT & 2)) || + ((keycode == 0x73) && (np2cfg.XSHIFT & 4)))) { + keydata |= 0x80; + } + if (!(keydata & 0x80)) { // シフト + if (keystat.ref[keycode] != NKEYREF_NC) { + keystat.ref[keycode] = NKEYREF_NC; + KEYBOARD_SEND((REG8)(keycode + 0x80)); + if ((keycode == 0x71) || (keycode == 0x72)) { + reloadled(); + } + } + } + } + } +} + +void keystat_resendstat(void) { + + REG8 i; + + for (i=0; i<0x80; i++) { + if (keystat.ref[i] != NKEYREF_NC) { + keyboard_send(i); + } + } + keyrepeat_delay_flag = FALSE; + keyrepeat_index = 0; +} + + +// ---- + +void keystat_keydown(REG8 ref) { + + UINT8 shift; +const NKEYM *nkey; + + if ((ref >= NKEY_USER) && (ref < (NKEY_USER + NKEY_USERKEYS))) { + nkey = (NKEYM *)(nkeytbl.user + (ref - NKEY_USER)); + keystat_down(nkey->key, nkey->keys, NKEYREF_USER); + } + else if (ref < NKEY_SYSTEM) { + if (np2cfg.KEY_MODE) { + shift = kbexflag[ref]; + if (shift & KBEX_JOYKEY) { + keystat.extkey |= (1 << (shift & 7)); + return; + } + } + nkey = (NKEYM *)(nkeytbl.key + ref); + keystat_down(nkey->key, nkey->keys, ref); + } +} + +void keystat_keyup(REG8 ref) { + + UINT8 shift; +const NKEYM *nkey; + + if ((ref >= NKEY_USER) && (ref < (NKEY_USER + NKEY_USERKEYS))) { + nkey = (NKEYM *)(nkeytbl.user + (ref - NKEY_USER)); + keystat_up(nkey->key, nkey->keys, NKEYREF_USER); + } + else if (ref < NKEY_SYSTEM) { + if (np2cfg.KEY_MODE) { + shift = kbexflag[ref]; + if (shift & KBEX_JOYKEY) { + keystat.extkey &= ~(1 << (shift & 7)); + return; + } + } + nkey = (NKEYM *)(nkeytbl.key + ref); + keystat_up(nkey->key, nkey->keys, ref); + } +} + +void keystat_releaseref(REG8 ref) { + + REG8 i; + + for (i=0; i<0x80; i++) { + if (keystat.ref[i] == ref) { + keystat.ref[i] = NKEYREF_NC; + KEYBOARD_SEND((REG8)(i + 0x80)); + } + } +} + +void keystat_resetjoykey(void) { + + REG8 i; + + keystat.extkey = 0; + for (i=0; i<0x80; i++) { + if (kbexflag[i] & KBEX_JOYKEY) { + keystat_releaseref(i); + } + } +} + + +void keystat_releasekey(REG8 key) { + + key &= 0x7f; + if ((key != 0x71) && (key != 0x72)) { + if (keystat.ref[key] != NKEYREF_NC) { + keystat.ref[key] = NKEYREF_NC; + KEYBOARD_SEND((REG8)(key + 0x80)); + } + } +} + +void keystat_allrelease(void) { + + REG8 i; + + for (i=0; i<0x80; i++) { + keystat_releasekey(i); + } +} + + +REG8 keystat_getjoy(void) { + + return(~keystat.extkey); +} + +REG8 keystat_getmouse(SINT16 *x, SINT16 *y) { + + REG8 btn; + UINT8 acc; + SINT16 tmp; + REG8 ret; + + btn = ~keystat.extkey; + acc = btn | keystat.mouselast; + keystat.mouselast = (UINT8)btn; + tmp = 0; + if (!(btn & 1)) { + tmp -= mousedelta[keystat.d_up]; + } + if (!(acc & 1)) { + if (keystat.d_up < MOUSESTEPMAX) { + keystat.d_up++; + } + } + else { + keystat.d_up = 0; + } + if (!(btn & 2)) { + tmp += mousedelta[keystat.d_dn]; + } + if (!(acc & 2)) { + if (keystat.d_dn < MOUSESTEPMAX) { + keystat.d_dn++; + } + } + else { + keystat.d_dn = 0; + } + *y += tmp; + + tmp = 0; + if (!(btn & 4)) { + tmp -= mousedelta[keystat.d_lt]; + } + if (!(acc & 4)) { + if (keystat.d_lt < MOUSESTEPMAX) { + keystat.d_lt++; + } + } + else { + keystat.d_lt = 0; + } + if (!(btn & 8)) { + tmp += mousedelta[keystat.d_rt]; + } + if (!(acc & 8)) { + if (keystat.d_rt < MOUSESTEPMAX) { + keystat.d_rt++; + } + } + else { + keystat.d_rt = 0; + } + *x += tmp; + + ret = 0x5f; + ret += (btn & 0x10) << 3; + ret += (btn & 0x20); + return(ret); +} + + +// ---- + +// キーコード変更 + +static REG8 cnvnewcode(REG8 oldcode) { + + switch(oldcode) { + case 0x71: // 通常caps + return(0x81); + + case 0x72: // 通常カナ + return(0x82); + + case 0x79: // メカニカルロックcaps + return(0x71); + + case 0x7a: // メカニカルロックkana + return(0x72); + + case 0x76: + return(0x90); // NKEY_USER + 0 + + case 0x77: + return(0x91); // NKEY_USER + 1 + + default: + return(oldcode); + } +} + +void keystat_senddata(REG8 data) { + + REG8 keycode; + + keycode = cnvnewcode((REG8)(data & 0x7f)); + if (!(data & 0x80)) { + keystat_keydown(keycode); + } + else { + keystat_keyup(keycode); + } +} +void keystat_senddataraw(REG8 data) { + + REG8 keycode; + + keycode = (REG8)(data & 0x7f); + if (!(data & 0x80)) { + keystat_keydown(keycode); + } + else { + keystat_keyup(keycode); + } +} + +void keystat_forcerelease(REG8 data) { + + REG8 keycode; + + keycode = cnvnewcode((REG8)(data & 0x7f)); + keystat_releasekey(keycode); +} + +// Keyrepeat +static void keystat_send(REG8 data) { + UINT8 keycode = data & 0x7f; + int i; + + if(kbexflag[keycode] & KBEX_NONREP) { // none repeat key + keyboard_send(data); + return; + } + if(!(data & 0x80)) { // key down + if(keyrepeat_index >= KEYREPEAT_BUF_MAX) { // keyreat buf full + // Nothing + return; + } + // If the keycode is stored in the repeat buffer, return + for(i = 0; i < keyrepeat_index; i++) { + if(keyrepeat_buf[i] == keycode) { + return; + } + } + // Add the keycode to keyrepeat buffer + keyrepeat_buf[keyrepeat_index] = keycode; + keyrepeat_index++; + // Delay flag ON + keyrepeat_delay_flag = TRUE; + keyrepeat_delay = GETTICK(); + // Send keycode(make) + keyboard_send(data); + } else { // key up + // Remove keycode from the keyrepeat buffer + if(keyrepeat_index) { + for(i = keyrepeat_index - 1; i >= 0; i--) { + if(keyrepeat_buf[i] == keycode) { + // Remove keycode from the keyrepeat buffer + if(i == keyrepeat_index - 1) { + keyrepeat_delay_flag = TRUE; + keyrepeat_delay = GETTICK(); + } + for(; i < keyrepeat_index - 1; i++) { + keyrepeat_buf[i] = keyrepeat_buf[i+1]; + } + keyrepeat_index--; + break; + } + } + } + // Send keycode(break) + keyboard_send(data); + } +} + +// keyrepeat interval processing +void keyrepeat_proc() { + // If the keyrepeat buffer is empty, return + if(!keyrepeat_index) { + return; + } + if(keyrepeat_delay_flag) { // If Delay flag is ON, + UINT32 dt = GETTICK() - keyrepeat_delay; + // If it hasn't been (delay time - repeat time) yet, return + if(dt < KEYREPEAT_DELAY - KEYREPEAT_INTERVAL) { + return; + } + // Delay flag OFF + keyrepeat_delay_flag = FALSE; + keyrepeat_delay = 0; + keyrepeat_interval = GETTICK(); + } else { // If Delay flag is OFF, + UINT32 dt = GETTICK() - keyrepeat_interval; + // If is has been repeat time, + if(dt >= KEYREPEAT_INTERVAL) { + UINT8 keycode = keyrepeat_buf[keyrepeat_index-1]; + keyrepeat_interval = GETTICK(); + keyboard_send(keycode | 0x80); + keyboard_send(keycode); + } + + } +} diff --git a/lio/gcircle.c b/lio/gcircle.c old mode 100755 new mode 100644 index c73322ba..bfc4d380 --- a/lio/gcircle.c +++ b/lio/gcircle.c @@ -1,92 +1,92 @@ -#include -#include -#include "lio.h" - -typedef struct { - UINT8 cx[2]; - UINT8 cy[2]; - UINT8 rx[2]; - UINT8 ry[2]; - UINT8 pal; - UINT8 flag; - UINT8 sx[2]; - UINT8 sy[2]; - UINT8 ex[2]; - UINT8 ey[2]; - UINT8 pat; - UINT8 off[2]; - UINT8 seg[2]; -} GCIRCLE; - - -// ---- GCIRCLE - -static void draw4(const _GLIO *lio, SINT16 x, SINT16 y, - SINT16 d1, SINT16 d2, REG8 pal) { - - SINT16 x1; - SINT16 x2; - SINT16 y1; - SINT16 y2; - - x1 = x - d1; - x2 = x + d1; - y1 = y - d2; - y2 = y + d2; - lio_pset(lio, x1, y1, pal); - lio_pset(lio, x1, y2, pal); - lio_pset(lio, x2, y1, pal); - lio_pset(lio, x2, y2, pal); -} - -REG8 lio_gcircle(GLIO lio) { - - GCIRCLE dat; - SINT16 cx; - SINT16 cy; - SINT16 rx; - SINT16 ry; - REG8 pal; - SINT16 d1; - SINT16 d2; - SINT16 d3; - - lio_updatedraw(lio); - MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); - - // チェック - if (dat.flag & 0x7f) { - TRACEOUT(("LIO GCIRCLE not support flags: %.2x", dat.flag)); - } - cx = (SINT16)LOADINTELWORD(dat.cx); - cy = (SINT16)LOADINTELWORD(dat.cy); - rx = (SINT16)LOADINTELWORD(dat.rx); - ry = (SINT16)LOADINTELWORD(dat.ry); - pal = dat.pal; - if (pal == 0xff) { - pal = lio->work.fgcolor; - } - - if (rx != ry) { - TRACEOUT(("LIO GCIRCLE not support ellipse")); - return(LIO_SUCCESS); - } - - // 単純な円の描画 - d1 = 0; - d2 = ry; - d3 = 0 - ry; - while(d1 <= d2) { - draw4(lio, cx, cy, d1, d2, pal); - draw4(lio, cx, cy, d2, d1, pal); - lio->wait += 8 * (10 + 10 + 10); - d1++; - d3 += (d1 * 2) - 1; - if (d3 >= 0) { - d2--; - d3 -= d2 * 2; - } - } - return(LIO_SUCCESS); -} - +#include +#include +#include "lio.h" + +typedef struct { + UINT8 cx[2]; + UINT8 cy[2]; + UINT8 rx[2]; + UINT8 ry[2]; + UINT8 pal; + UINT8 flag; + UINT8 sx[2]; + UINT8 sy[2]; + UINT8 ex[2]; + UINT8 ey[2]; + UINT8 pat; + UINT8 off[2]; + UINT8 seg[2]; +} GCIRCLE; + + +// ---- GCIRCLE + +static void draw4(const _GLIO *lio, SINT16 x, SINT16 y, + SINT16 d1, SINT16 d2, REG8 pal) { + + SINT16 x1; + SINT16 x2; + SINT16 y1; + SINT16 y2; + + x1 = x - d1; + x2 = x + d1; + y1 = y - d2; + y2 = y + d2; + lio_pset(lio, x1, y1, pal); + lio_pset(lio, x1, y2, pal); + lio_pset(lio, x2, y1, pal); + lio_pset(lio, x2, y2, pal); +} + +REG8 lio_gcircle(GLIO lio) { + + GCIRCLE dat; + SINT16 cx; + SINT16 cy; + SINT16 rx; + SINT16 ry; + REG8 pal; + SINT16 d1; + SINT16 d2; + SINT16 d3; + + lio_updatedraw(lio); + MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); + + // チェック + if (dat.flag & 0x7f) { + TRACEOUT(("LIO GCIRCLE not support flags: %.2x", dat.flag)); + } + cx = (SINT16)LOADINTELWORD(dat.cx); + cy = (SINT16)LOADINTELWORD(dat.cy); + rx = (SINT16)LOADINTELWORD(dat.rx); + ry = (SINT16)LOADINTELWORD(dat.ry); + pal = dat.pal; + if (pal == 0xff) { + pal = lio->work.fgcolor; + } + + if (rx != ry) { + TRACEOUT(("LIO GCIRCLE not support ellipse")); + return(LIO_SUCCESS); + } + + // 単純な円の描画 + d1 = 0; + d2 = ry; + d3 = 0 - ry; + while(d1 <= d2) { + draw4(lio, cx, cy, d1, d2, pal); + draw4(lio, cx, cy, d2, d1, pal); + lio->wait += 8 * (10 + 10 + 10); + d1++; + d3 += (d1 * 2) - 1; + if (d3 >= 0) { + d2--; + d3 -= d2 * 2; + } + } + return(LIO_SUCCESS); +} + diff --git a/lio/gline.c b/lio/gline.c old mode 100755 new mode 100644 index ce3fd48d..53061548 --- a/lio/gline.c +++ b/lio/gline.c @@ -1,363 +1,363 @@ -#include -#include -#include -#include -#include -#include "lio.h" - - -typedef struct { - UINT8 x1[2]; - UINT8 y1[2]; - UINT8 x2[2]; - UINT8 y2[2]; - UINT8 pal; - UINT8 type; - UINT8 sw; - UINT8 style[2]; - UINT8 patleng; - UINT8 off[2]; - UINT8 seg[2]; -} GLINE; - -typedef struct { - int x1; - int y1; - int x2; - int y2; - UINT8 pal; -} LINEPT; - - -static void gline(const _GLIO *lio, const LINEPT *lp, UINT16 pat) { - - int x1; - int y1; - int x2; - int y2; - int swap; - int tmp; - int width; - int height; - int d1; - int d2; - UINT32 csrw; - GDCVECT vect; - - x1 = lp->x1; - y1 = lp->y1; - x2 = lp->x2; - y2 = lp->y2; - - // びゅーぽいんと - swap = 0; - if (x1 > x2) { - tmp = x1; - x1 = x2; - x2 = tmp; - tmp = y1; - y1 = y2; - y2 = tmp; - swap = 1; - } - if ((x1 > lio->draw.x2) || (x2 < lio->draw.x1)) { - return; - } - width = x2 - x1; - height = y2 - y1; - d1 = lio->draw.x1 - x1; - d2 = x2 - lio->draw.x2; - if (d1 > 0) { - x1 = lio->draw.x1; - y1 += (((height * d1 * 2) / width) + 1) >> 1; - } - if (d2 > 0) { - x2 = lio->draw.x2; - y2 -= (((height * d2 * 2) / width) + 1) >> 1; - } - if (swap) { - tmp = x1; - x1 = x2; - x2 = tmp; - tmp = y1; - y1 = y2; - y2 = tmp; - } - - swap = 0; - if (y1 > y2) { - tmp = x1; - x1 = x2; - x2 = tmp; - tmp = y1; - y1 = y2; - y2 = tmp; - } - if ((y1 > lio->draw.y2) || (y2 < lio->draw.y1)) { - return; - } - width = x2 - x1; - height = y2 - y1; - d1 = lio->draw.y1 - y1; - d2 = y2 - lio->draw.y2; - if (d1 > 0) { - y1 = lio->draw.y1; - x1 += (((width * d1 * 2) / height) + 1) >> 1; - } - if (d2 > 0) { - y2 = lio->draw.y2; - x2 -= (((width * d2 * 2) / height) + 1) >> 1; - } - if (swap) { - tmp = x1; - x1 = x2; - x2 = tmp; - tmp = y1; - y1 = y2; - y2 = tmp; - } - - // 進んだ距離計算 - d1 = x1 - lp->x1; - if (d1 < 0) { - d1 = 0 - d1; - } - d2 = y1 - lp->y1; - if (d2 < 0) { - d2 = 0 - d2; - } - d1 = MAX(d1, d2) & 15; - pat = (UINT16)((pat >> d1) | (pat << (16 - d1))); - - csrw = (y1 * 40) + (x1 >> 4) + ((x1 & 0xf) << 20); - if (lio->draw.flag & LIODRAW_UPPER) { - csrw += 16000 >> 1; - } - gdcsub_setvectl(&vect, x1, y1, x2, y2); - if (!(lio->draw.flag & LIODRAW_MONO)) { - gdcsub_vectl(csrw + 0x4000, &vect, pat, - (REG8)((lp->pal & 1)?GDCOPE_SET:GDCOPE_CLEAR)); - gdcsub_vectl(csrw + 0x8000, &vect, pat, - (REG8)((lp->pal & 2)?GDCOPE_SET:GDCOPE_CLEAR)); - gdcsub_vectl(csrw + 0xc000, &vect, pat, - (REG8)((lp->pal & 4)?GDCOPE_SET:GDCOPE_CLEAR)); - if (lio->draw.flag & LIODRAW_4BPP) { - gdcsub_vectl(csrw, &vect, pat, - (REG8)((lp->pal & 8)?GDCOPE_SET:GDCOPE_CLEAR)); - } - } - else { - csrw += ((lio->draw.flag + 1) & LIODRAW_PMASK) << 12; - gdcsub_vectl(csrw, &vect, pat, - (REG8)((lp->pal)?GDCOPE_SET:GDCOPE_CLEAR)); - } -} - -static void glineb(const _GLIO *lio, const LINEPT *lp, UINT16 pat) { - - LINEPT lpt; - - lpt = *lp; - lpt.y2 = lp->y1; - gline(lio, &lpt, pat); - lpt.y2 = lp->y2; - - lpt.x2 = lp->x1; - gline(lio, &lpt, pat); - lpt.x2 = lp->x2; - - lpt.x1 = lp->x2; - gline(lio, &lpt, pat); - lpt.x1 = lp->x1; - - lpt.y1 = lp->y2; - gline(lio, &lpt, pat); - lpt.y1 = lp->y1; -} - - -// ---- - -static void gbox(const _GLIO *lio, const LINEPT *lp, UINT8 *tile, UINT leng) { - - int x1; - int y1; - int x2; - int y2; - int tmp; - UINT32 csrw; - GDCVECT vect; - UINT planes; - UINT adrs[4]; - UINT8 ope[4]; - UINT16 pat; - UINT8 *tterm; - UINT r; - - x1 = lp->x1; - y1 = lp->y1; - x2 = lp->x2; - y2 = lp->y2; - - if (x1 > x2) { - tmp = x1; - x1 = x2; - x2 = tmp; - } - if (y1 > y2) { - tmp = y1; - y1 = y2; - y2 = tmp; - } - if ((x1 > lio->draw.x2) || (x2 < lio->draw.x1) || - (y1 > lio->draw.y2) || (y2 < lio->draw.y1)) { - return; - } - x1 = MAX(x1, lio->draw.x1); - y1 = MAX(y1, lio->draw.y1); - x2 = MIN(x2, lio->draw.x2); - y2 = MIN(y2, lio->draw.y2); - - csrw = 0; - if (lio->draw.flag & LIODRAW_UPPER) { - csrw += 16000 >> 1; - } - if (!(lio->draw.flag & LIODRAW_MONO)) { - planes = (lio->draw.flag & LIODRAW_4BPP)?4:3; - adrs[0] = csrw + 0x4000; - adrs[1] = csrw + 0x8000; - adrs[2] = csrw + 0xc000; - adrs[3] = csrw + 0x0000; - ope[0] = (lp->pal & 1)?GDCOPE_SET:GDCOPE_CLEAR; - ope[1] = (lp->pal & 2)?GDCOPE_SET:GDCOPE_CLEAR; - ope[2] = (lp->pal & 4)?GDCOPE_SET:GDCOPE_CLEAR; - ope[3] = (lp->pal & 8)?GDCOPE_SET:GDCOPE_CLEAR; - } - else { - planes = 1; - adrs[0] = csrw + (((lio->draw.flag + 1) & LIODRAW_PMASK) << 12); - ope[0] = (lp->pal)?GDCOPE_SET:GDCOPE_CLEAR; - } - - if (leng == 0) { - tile = NULL; - tterm = NULL; - } - else { - tterm = tile + leng; - tmp = (x1 - lio->draw.x1) & 7; - do { - r = GDCPATREVERSE(*tile); - *tile = (UINT8)((r << tmp) | (r >> (8 - tmp))); - } while(++tile < tterm); - tile -= leng; - tmp = (y1 - lio->draw.y1) * planes; - tile += tmp % leng; - } - - pat = 0xffff; - while(y1 <= y2) { - gdcsub_setvectl(&vect, x1, y1, x2, y1); - csrw = (y1 * 40) + (x1 >> 4) + ((x1 & 0xf) << 20); - r = 0; - do { - if (tile) { - pat = (*tile << 8) | *tile; - if (++tile >= tterm) { - tile -= leng; - } - } - gdcsub_vectl(csrw + adrs[r], &vect, pat, ope[r]); - } while(++r < planes); - y1++; - } -} - - -// ---- CLS - -REG8 lio_gcls(GLIO lio) { - - LINEPT lp; - - lio_updatedraw(lio); - lp.x1 = lio->draw.x1; - lp.y1 = lio->draw.y1; - lp.x2 = lio->draw.x2; - lp.y2 = lio->draw.y2; - lp.pal = lio->work.bgcolor; - gbox(lio, &lp, NULL, 0); - return(LIO_SUCCESS); -} - - -// ---- - -REG8 lio_gline(GLIO lio) { - - GLINE dat; - LINEPT lp; - UINT16 pat; - UINT leng; -// UINT lengmin; - UINT8 tile[256]; - - lio_updatedraw(lio); - MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); - lp.x1 = (SINT16)LOADINTELWORD(dat.x1); - lp.y1 = (SINT16)LOADINTELWORD(dat.y1); - lp.x2 = (SINT16)LOADINTELWORD(dat.x2); - lp.y2 = (SINT16)LOADINTELWORD(dat.y2); - - TRACEOUT(("lio_gline %d,%d-%d,%d [%d]", lp.x1, lp.y1, lp.x2, lp.y2, dat.type)); - - if (dat.pal == 0xff) { - dat.pal = lio->work.fgcolor; - } - if (dat.pal >= lio->draw.palmax) { - goto gline_err; - } - pat = 0xffff; - if (dat.type < 2) { - if (dat.sw) { - pat = (GDCPATREVERSE(dat.style[0]) << 8) + - GDCPATREVERSE(dat.style[1]); - } - lp.pal = dat.pal; - if (dat.type == 0) { - gline(lio, &lp, pat); - } - else { - glineb(lio, &lp, pat); - } - } - else if (dat.type == 2) { - leng = 0; - if (dat.sw == 2) { - leng = dat.patleng; - if (leng == 0) { - goto gline_err; - } - MEMR_READS(LOADINTELWORD(dat.seg), LOADINTELWORD(dat.off), - tile, leng); - } - if (dat.sw != 1) { - lp.pal = dat.pal; - gbox(lio, &lp, tile, leng); - } - else { - lp.pal = dat.style[0]; - gbox(lio, &lp, tile, leng); - lp.pal = dat.pal; - glineb(lio, &lp, 0xffff); - } - } - else { - goto gline_err; - } - return(LIO_SUCCESS); - -gline_err: - return(LIO_ILLEGALFUNC); -} - +#include +#include +#include +#include +#include +#include "lio.h" + + +typedef struct { + UINT8 x1[2]; + UINT8 y1[2]; + UINT8 x2[2]; + UINT8 y2[2]; + UINT8 pal; + UINT8 type; + UINT8 sw; + UINT8 style[2]; + UINT8 patleng; + UINT8 off[2]; + UINT8 seg[2]; +} GLINE; + +typedef struct { + int x1; + int y1; + int x2; + int y2; + UINT8 pal; +} LINEPT; + + +static void gline(const _GLIO *lio, const LINEPT *lp, UINT16 pat) { + + int x1; + int y1; + int x2; + int y2; + int swap; + int tmp; + int width; + int height; + int d1; + int d2; + UINT32 csrw; + GDCVECT vect; + + x1 = lp->x1; + y1 = lp->y1; + x2 = lp->x2; + y2 = lp->y2; + + // びゅーぽいんと + swap = 0; + if (x1 > x2) { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + swap = 1; + } + if ((x1 > lio->draw.x2) || (x2 < lio->draw.x1)) { + return; + } + width = x2 - x1; + height = y2 - y1; + d1 = lio->draw.x1 - x1; + d2 = x2 - lio->draw.x2; + if (d1 > 0) { + x1 = lio->draw.x1; + y1 += (((height * d1 * 2) / width) + 1) >> 1; + } + if (d2 > 0) { + x2 = lio->draw.x2; + y2 -= (((height * d2 * 2) / width) + 1) >> 1; + } + if (swap) { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + } + + swap = 0; + if (y1 > y2) { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + } + if ((y1 > lio->draw.y2) || (y2 < lio->draw.y1)) { + return; + } + width = x2 - x1; + height = y2 - y1; + d1 = lio->draw.y1 - y1; + d2 = y2 - lio->draw.y2; + if (d1 > 0) { + y1 = lio->draw.y1; + x1 += (((width * d1 * 2) / height) + 1) >> 1; + } + if (d2 > 0) { + y2 = lio->draw.y2; + x2 -= (((width * d2 * 2) / height) + 1) >> 1; + } + if (swap) { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + } + + // 進んだ距離計算 + d1 = x1 - lp->x1; + if (d1 < 0) { + d1 = 0 - d1; + } + d2 = y1 - lp->y1; + if (d2 < 0) { + d2 = 0 - d2; + } + d1 = MAX(d1, d2) & 15; + pat = (UINT16)((pat >> d1) | (pat << (16 - d1))); + + csrw = (y1 * 40) + (x1 >> 4) + ((x1 & 0xf) << 20); + if (lio->draw.flag & LIODRAW_UPPER) { + csrw += 16000 >> 1; + } + gdcsub_setvectl(&vect, x1, y1, x2, y2); + if (!(lio->draw.flag & LIODRAW_MONO)) { + gdcsub_vectl(csrw + 0x4000, &vect, pat, + (REG8)((lp->pal & 1)?GDCOPE_SET:GDCOPE_CLEAR)); + gdcsub_vectl(csrw + 0x8000, &vect, pat, + (REG8)((lp->pal & 2)?GDCOPE_SET:GDCOPE_CLEAR)); + gdcsub_vectl(csrw + 0xc000, &vect, pat, + (REG8)((lp->pal & 4)?GDCOPE_SET:GDCOPE_CLEAR)); + if (lio->draw.flag & LIODRAW_4BPP) { + gdcsub_vectl(csrw, &vect, pat, + (REG8)((lp->pal & 8)?GDCOPE_SET:GDCOPE_CLEAR)); + } + } + else { + csrw += ((lio->draw.flag + 1) & LIODRAW_PMASK) << 12; + gdcsub_vectl(csrw, &vect, pat, + (REG8)((lp->pal)?GDCOPE_SET:GDCOPE_CLEAR)); + } +} + +static void glineb(const _GLIO *lio, const LINEPT *lp, UINT16 pat) { + + LINEPT lpt; + + lpt = *lp; + lpt.y2 = lp->y1; + gline(lio, &lpt, pat); + lpt.y2 = lp->y2; + + lpt.x2 = lp->x1; + gline(lio, &lpt, pat); + lpt.x2 = lp->x2; + + lpt.x1 = lp->x2; + gline(lio, &lpt, pat); + lpt.x1 = lp->x1; + + lpt.y1 = lp->y2; + gline(lio, &lpt, pat); + lpt.y1 = lp->y1; +} + + +// ---- + +static void gbox(const _GLIO *lio, const LINEPT *lp, UINT8 *tile, UINT leng) { + + int x1; + int y1; + int x2; + int y2; + int tmp; + UINT32 csrw; + GDCVECT vect; + UINT planes; + UINT adrs[4]; + UINT8 ope[4]; + UINT16 pat; + UINT8 *tterm; + UINT r; + + x1 = lp->x1; + y1 = lp->y1; + x2 = lp->x2; + y2 = lp->y2; + + if (x1 > x2) { + tmp = x1; + x1 = x2; + x2 = tmp; + } + if (y1 > y2) { + tmp = y1; + y1 = y2; + y2 = tmp; + } + if ((x1 > lio->draw.x2) || (x2 < lio->draw.x1) || + (y1 > lio->draw.y2) || (y2 < lio->draw.y1)) { + return; + } + x1 = MAX(x1, lio->draw.x1); + y1 = MAX(y1, lio->draw.y1); + x2 = MIN(x2, lio->draw.x2); + y2 = MIN(y2, lio->draw.y2); + + csrw = 0; + if (lio->draw.flag & LIODRAW_UPPER) { + csrw += 16000 >> 1; + } + if (!(lio->draw.flag & LIODRAW_MONO)) { + planes = (lio->draw.flag & LIODRAW_4BPP)?4:3; + adrs[0] = csrw + 0x4000; + adrs[1] = csrw + 0x8000; + adrs[2] = csrw + 0xc000; + adrs[3] = csrw + 0x0000; + ope[0] = (lp->pal & 1)?GDCOPE_SET:GDCOPE_CLEAR; + ope[1] = (lp->pal & 2)?GDCOPE_SET:GDCOPE_CLEAR; + ope[2] = (lp->pal & 4)?GDCOPE_SET:GDCOPE_CLEAR; + ope[3] = (lp->pal & 8)?GDCOPE_SET:GDCOPE_CLEAR; + } + else { + planes = 1; + adrs[0] = csrw + (((lio->draw.flag + 1) & LIODRAW_PMASK) << 12); + ope[0] = (lp->pal)?GDCOPE_SET:GDCOPE_CLEAR; + } + + if (leng == 0) { + tile = NULL; + tterm = NULL; + } + else { + tterm = tile + leng; + tmp = (x1 - lio->draw.x1) & 7; + do { + r = GDCPATREVERSE(*tile); + *tile = (UINT8)((r << tmp) | (r >> (8 - tmp))); + } while(++tile < tterm); + tile -= leng; + tmp = (y1 - lio->draw.y1) * planes; + tile += tmp % leng; + } + + pat = 0xffff; + while(y1 <= y2) { + gdcsub_setvectl(&vect, x1, y1, x2, y1); + csrw = (y1 * 40) + (x1 >> 4) + ((x1 & 0xf) << 20); + r = 0; + do { + if (tile) { + pat = (*tile << 8) | *tile; + if (++tile >= tterm) { + tile -= leng; + } + } + gdcsub_vectl(csrw + adrs[r], &vect, pat, ope[r]); + } while(++r < planes); + y1++; + } +} + + +// ---- CLS + +REG8 lio_gcls(GLIO lio) { + + LINEPT lp; + + lio_updatedraw(lio); + lp.x1 = lio->draw.x1; + lp.y1 = lio->draw.y1; + lp.x2 = lio->draw.x2; + lp.y2 = lio->draw.y2; + lp.pal = lio->work.bgcolor; + gbox(lio, &lp, NULL, 0); + return(LIO_SUCCESS); +} + + +// ---- + +REG8 lio_gline(GLIO lio) { + + GLINE dat; + LINEPT lp; + UINT16 pat; + UINT leng; +// UINT lengmin; + UINT8 tile[256]; + + lio_updatedraw(lio); + MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); + lp.x1 = (SINT16)LOADINTELWORD(dat.x1); + lp.y1 = (SINT16)LOADINTELWORD(dat.y1); + lp.x2 = (SINT16)LOADINTELWORD(dat.x2); + lp.y2 = (SINT16)LOADINTELWORD(dat.y2); + + TRACEOUT(("lio_gline %d,%d-%d,%d [%d]", lp.x1, lp.y1, lp.x2, lp.y2, dat.type)); + + if (dat.pal == 0xff) { + dat.pal = lio->work.fgcolor; + } + if (dat.pal >= lio->draw.palmax) { + goto gline_err; + } + pat = 0xffff; + if (dat.type < 2) { + if (dat.sw) { + pat = (GDCPATREVERSE(dat.style[0]) << 8) + + GDCPATREVERSE(dat.style[1]); + } + lp.pal = dat.pal; + if (dat.type == 0) { + gline(lio, &lp, pat); + } + else { + glineb(lio, &lp, pat); + } + } + else if (dat.type == 2) { + leng = 0; + if (dat.sw == 2) { + leng = dat.patleng; + if (leng == 0) { + goto gline_err; + } + MEMR_READS(LOADINTELWORD(dat.seg), LOADINTELWORD(dat.off), + tile, leng); + } + if (dat.sw != 1) { + lp.pal = dat.pal; + gbox(lio, &lp, tile, leng); + } + else { + lp.pal = dat.style[0]; + gbox(lio, &lp, tile, leng); + lp.pal = dat.pal; + glineb(lio, &lp, 0xffff); + } + } + else { + goto gline_err; + } + return(LIO_SUCCESS); + +gline_err: + return(LIO_ILLEGALFUNC); +} + diff --git a/lio/gpset.c b/lio/gpset.c old mode 100755 new mode 100644 index faee5699..740e6f54 --- a/lio/gpset.c +++ b/lio/gpset.c @@ -1,90 +1,90 @@ -#include -#include -#include "lio.h" - - -typedef struct { - UINT8 x[2]; - UINT8 y[2]; - UINT8 pal; -} GPSET; - -typedef struct { - UINT8 x[2]; - UINT8 y[2]; -} GPOINT2; - - -// ---- PSET - -REG8 lio_gpset(GLIO lio) { - - GPSET dat; - SINT16 x; - SINT16 y; - - lio_updatedraw(lio); - MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); - x = (SINT16)LOADINTELWORD(dat.x); - y = (SINT16)LOADINTELWORD(dat.y); - if (dat.pal == 0xff) { - if (CPU_AH == 1) { - dat.pal = lio->work.fgcolor; - } - else { - dat.pal = lio->work.bgcolor; - } - } - lio_pset(lio, x, y, dat.pal); - return(LIO_SUCCESS); -} - - -// ---- GPOINT2 - -REG8 lio_gpoint2(GLIO lio) { - - GPOINT2 dat; - SINT16 x; - SINT16 y; - REG8 ret; - UINT32 addr; - UINT sft; - UINT pl; -const UINT8 *ptr; - - lio_updatedraw(lio); - MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); - x = (SINT16)LOADINTELWORD(dat.x); - y = (SINT16)LOADINTELWORD(dat.y); - if ((lio->draw.x1 > x) || (lio->draw.x2 < x) || - (lio->draw.y1 > y) || (lio->draw.y2 < y)) { - ret = 0xff; - } - else { - ret = 0; - addr = (x >> 3) + (y * 80); - if (lio->draw.flag & LIODRAW_UPPER) { - addr += 16000; - } - addr += lio->draw.base; - sft = (~x) & 7; - if (!(lio->draw.flag & LIODRAW_MONO)) { - for (pl=0; pl<3; pl++) { - ptr = mem + addr + lioplaneadrs[pl]; - ret += (((*ptr) >> sft) & 1) << pl; - } - if (lio->draw.flag & LIODRAW_4BPP) { - ptr = mem + addr + lioplaneadrs[3]; - ret += (((*ptr) >> sft) & 1) << 3; - } - } - else { - ptr = mem + addr + lioplaneadrs[lio->draw.flag & LIODRAW_PMASK]; - ret = ((*ptr) >> sft) & 1; - } - } - CPU_AL = ret; - return(LIO_SUCCESS); -} - +#include +#include +#include "lio.h" + + +typedef struct { + UINT8 x[2]; + UINT8 y[2]; + UINT8 pal; +} GPSET; + +typedef struct { + UINT8 x[2]; + UINT8 y[2]; +} GPOINT2; + + +// ---- PSET + +REG8 lio_gpset(GLIO lio) { + + GPSET dat; + SINT16 x; + SINT16 y; + + lio_updatedraw(lio); + MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); + x = (SINT16)LOADINTELWORD(dat.x); + y = (SINT16)LOADINTELWORD(dat.y); + if (dat.pal == 0xff) { + if (CPU_AH == 1) { + dat.pal = lio->work.fgcolor; + } + else { + dat.pal = lio->work.bgcolor; + } + } + lio_pset(lio, x, y, dat.pal); + return(LIO_SUCCESS); +} + + +// ---- GPOINT2 + +REG8 lio_gpoint2(GLIO lio) { + + GPOINT2 dat; + SINT16 x; + SINT16 y; + REG8 ret; + UINT32 addr; + UINT sft; + UINT pl; +const UINT8 *ptr; + + lio_updatedraw(lio); + MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); + x = (SINT16)LOADINTELWORD(dat.x); + y = (SINT16)LOADINTELWORD(dat.y); + if ((lio->draw.x1 > x) || (lio->draw.x2 < x) || + (lio->draw.y1 > y) || (lio->draw.y2 < y)) { + ret = 0xff; + } + else { + ret = 0; + addr = (x >> 3) + (y * 80); + if (lio->draw.flag & LIODRAW_UPPER) { + addr += 16000; + } + addr += lio->draw.base; + sft = (~x) & 7; + if (!(lio->draw.flag & LIODRAW_MONO)) { + for (pl=0; pl<3; pl++) { + ptr = mem + addr + lioplaneadrs[pl]; + ret += (((*ptr) >> sft) & 1) << pl; + } + if (lio->draw.flag & LIODRAW_4BPP) { + ptr = mem + addr + lioplaneadrs[3]; + ret += (((*ptr) >> sft) & 1) << 3; + } + } + else { + ptr = mem + addr + lioplaneadrs[lio->draw.flag & LIODRAW_PMASK]; + ret = ((*ptr) >> sft) & 1; + } + } + CPU_AL = ret; + return(LIO_SUCCESS); +} + diff --git a/lio/gput1.c b/lio/gput1.c old mode 100755 new mode 100644 index bd078a3b..18c78941 --- a/lio/gput1.c +++ b/lio/gput1.c @@ -1,654 +1,654 @@ -#include -#include -#include -#include -#include -#include "lio.h" -#include - - -typedef struct { - UINT8 x1[2]; - UINT8 y1[2]; - UINT8 x2[2]; - UINT8 y2[2]; - UINT8 off[2]; - UINT8 seg[2]; - UINT8 leng[2]; -} GGET; - -typedef struct { - UINT8 x[2]; - UINT8 y[2]; - UINT8 off[2]; - UINT8 seg[2]; - UINT8 leng[2]; - UINT8 mode; - UINT8 colorsw; - UINT8 fg; - UINT8 bg; -} GPUT1; - -typedef struct { - UINT8 x[2]; - UINT8 y[2]; - UINT8 chr[2]; - UINT8 mode; - UINT8 colorsw; - UINT8 fg; - UINT8 bg; -} GPUT2; - -typedef struct { - SINT16 x; - SINT16 y; - UINT16 width; - UINT16 height; - UINT16 off; - UINT16 seg; - UINT8 mode; - UINT8 sw; - UINT8 fg; - UINT8 bg; -} LIOPUT; - -typedef struct { - UINT8 *baseptr; - UINT addr; - UINT sft; - UINT width; - UINT8 mask; -} GETCNTX; - -typedef struct { - UINT8 *baseptr; - UINT addr; - UINT sft; - UINT width; - UINT8 maskl; - UINT8 maskr; - UINT8 masklr; - UINT8 mask; - UINT8 pat[84]; -} PUTCNTX; - - -static void getvram(const GETCNTX *gt, UINT8 *dst) { - - UINT8 *baseptr; - UINT addr; - UINT width; - UINT dat; - UINT sft; - - baseptr = gt->baseptr; - addr = gt->addr; - width = gt->width; - sft = 8 - gt->sft; - dat = baseptr[LOW15(addr)]; - addr++; - while(width > 8) { - width -= 8; - dat = (dat << 8) + baseptr[LOW15(addr)]; - addr++; - *dst = (UINT8)(dat >> sft); - dst++; - } - dat = (dat << 8) + baseptr[LOW15(addr)]; - *dst = (UINT8)((dat >> sft) & gt->mask); -} - -static void setdirty(UINT addr, UINT width, UINT height, REG8 bit) { - - UINT r; - - gdcs.grphdisp |= bit; - width = (width + 7) >> 3; - while(height--) { - r = 0; - while(r < width) { - vramupdate[LOW15(addr + r)] |= bit; - r++; - } - addr += 80; - } -} - -static void putor(const PUTCNTX *pt) { - - UINT8 *baseptr; - UINT addr; -const UINT8 *src; - UINT width; - UINT dat; - - baseptr = pt->baseptr; - addr = pt->addr; - src = pt->pat; - width = pt->width; - dat = *src++; - if ((pt->sft + width) < 8) { - baseptr[LOW15(addr)] |= (UINT8)((dat >> pt->sft) & pt->masklr); - } - else { - baseptr[LOW15(addr)] |= (UINT8)(dat >> pt->sft) & pt->maskl; - addr++; - width -= (8 - pt->sft); - while(width > 8) { - width -= 8; - dat = (dat << 8) + (*src); - src++; - baseptr[LOW15(addr)] |= (UINT8)(dat >> pt->sft); - addr++; - } - if (width) { - dat = (dat << 8) + (*src); - baseptr[LOW15(addr)] |= (UINT8)(dat >> pt->sft) & pt->maskr; - } - } -} - -static void putorn(const PUTCNTX *pt) { - - UINT8 *baseptr; - UINT addr; -const UINT8 *src; - UINT width; - UINT dat; - - baseptr = pt->baseptr; - addr = pt->addr; - src = pt->pat; - width = pt->width; - dat = *src++; - if ((pt->sft + width) < 8) { - baseptr[LOW15(addr)] |= (UINT8)(((~dat) >> pt->sft) & pt->masklr); - } - else { - baseptr[LOW15(addr)] |= (UINT8)(((~dat) >> pt->sft) & pt->maskl); - addr++; - width -= (8 - pt->sft); - while(width > 8) { - width -= 8; - dat = (dat << 8) + (*src); - src++; - baseptr[LOW15(addr)] |= (UINT8)((~dat) >> pt->sft); - addr++; - } - if (width) { - dat = (dat << 8) + (*src); - baseptr[LOW15(addr)] |= (UINT8)(((~dat) >> pt->sft) & pt->maskr); - } - } -} - -static void putand(const PUTCNTX *pt) { - - UINT8 *baseptr; - UINT addr; -const UINT8 *src; - UINT width; - UINT dat; - - baseptr = pt->baseptr; - addr = pt->addr; - src = pt->pat; - width = pt->width; - dat = *src++; - if ((pt->sft + width) < 8) { - baseptr[LOW15(addr)] &= (UINT8)((dat >> pt->sft) | (~pt->masklr)); - } - else { - baseptr[LOW15(addr)] &= (UINT8)((dat >> pt->sft) | (~pt->maskl)); - addr++; - width -= (8 - pt->sft); - while(width > 8) { - width -= 8; - dat = (dat << 8) + (*src); - src++; - baseptr[LOW15(addr)] &= (UINT8)(dat >> pt->sft); - addr++; - } - if (width) { - dat = (dat << 8) + (*src); - baseptr[LOW15(addr)] &= (UINT8)((dat >> pt->sft) | (~pt->maskr)); - } - } -} - -static void putandn(const PUTCNTX *pt) { - - UINT8 *baseptr; - UINT addr; -const UINT8 *src; - UINT width; - UINT dat; - - baseptr = pt->baseptr; - addr = pt->addr; - src = pt->pat; - width = pt->width; - dat = *src++; - if ((pt->sft + width) < 8) { - baseptr[LOW15(addr)] &= (UINT8)(~((dat >> pt->sft) & pt->masklr)); - } - else { - baseptr[LOW15(addr)] &= (UINT8)(~((dat >> pt->sft) & pt->maskl)); - addr++; - width -= (8 - pt->sft); - while(width > 8) { - width -= 8; - dat = (dat << 8) + (*src); - src++; - baseptr[LOW15(addr)] &= (UINT8)((~dat) >> pt->sft); - addr++; - } - if (width) { - dat = (dat << 8) + (*src); - baseptr[LOW15(addr)] &= (UINT8)(~((dat >> pt->sft) & pt->maskr)); - } - } -} - -static void putxor(const PUTCNTX *pt) { - - UINT8 *baseptr; - UINT addr; -const UINT8 *src; - UINT width; - UINT dat; - - baseptr = pt->baseptr; - addr = pt->addr; - src = pt->pat; - width = pt->width; - dat = *src++; - if ((pt->sft + width) < 8) { - baseptr[LOW15(addr)] ^= (UINT8)((dat >> pt->sft) & pt->masklr); - } - else { - baseptr[LOW15(addr)] ^= (UINT8)(dat >> pt->sft) & pt->maskl; - addr++; - width -= (8 - pt->sft); - while(width > 8) { - width -= 8; - dat = (dat << 8) + (*src); - src++; - baseptr[LOW15(addr)] ^= (UINT8)(dat >> pt->sft); - addr++; - } - if (width) { - dat = (dat << 8) + (*src); - baseptr[LOW15(addr)] ^= (UINT8)(dat >> pt->sft) & pt->maskr; - } - } -} - -static void putxorn(const PUTCNTX *pt) { - - UINT8 *baseptr; - UINT addr; -const UINT8 *src; - UINT width; - UINT dat; - - baseptr = pt->baseptr; - addr = pt->addr; - src = pt->pat; - width = pt->width; - dat = *src++; - if ((pt->sft + width) < 8) { - baseptr[LOW15(addr)] ^= (UINT8)(((~dat) >> pt->sft) & pt->masklr); - } - else { - baseptr[LOW15(addr)] ^= (UINT8)(((~dat) >> pt->sft) & pt->maskl); - addr++; - width -= (8 - pt->sft); - while(width > 8) { - width -= 8; - dat = (dat << 8) + (*src); - src++; - baseptr[LOW15(addr)] ^= (UINT8)((~dat) >> pt->sft); - addr++; - } - if (width) { - dat = (dat << 8) + (*src); - baseptr[LOW15(addr)] ^= (UINT8)(((~dat) >> pt->sft) & pt->maskr); - } - } -} - - -// ---- - -static REG8 putsub(GLIO lio, const LIOPUT *lput) { - - UINT addr; - PUTCNTX pt; - UINT datacnt; - UINT off; - UINT height; - UINT flag; - UINT pl; - UINT writecnt; - - if ((lput->x < lio->draw.x1) || - (lput->y < lio->draw.y1) || - ((lput->x + lput->width - 1) > lio->draw.x2) || - ((lput->y + lput->height - 1) > lio->draw.y2)) { - return(LIO_ILLEGALFUNC); - } - if ((lput->width <= 0) || (lput->height <= 0)) { - return(LIO_SUCCESS); - } - - addr = (lput->x >> 3) + (lput->y * 80); - if (lio->draw.flag & LIODRAW_UPPER) { - addr += 16000; - } - setdirty(addr, (lput->x & 7) + lput->width, lput->height, lio->draw.sbit); - - pt.addr = addr; - pt.sft = lput->x & 7; - pt.width = lput->width; - pt.maskl = (UINT8)(0xff >> pt.sft); - pt.maskr = (UINT8)((~0x7f) >> ((pt.width + pt.sft - 1) & 7)); - pt.masklr = (UINT8)(pt.maskl >> pt.sft); - - datacnt = (lput->width + 7) >> 3; - off = lput->off; - - flag = (lio->draw.flag & LIODRAW_4BPP)?0x0f:0x07; - flag |= (lput->fg & 15) << 4; - flag |= (lput->bg & 15) << 8; - - // さて表示。 - writecnt = 0; - height = lput->height; - do { - flag <<= 4; - for (pl=0; pl<4; pl++) { - flag >>= 1; - if (flag & 8) { - pt.baseptr = mem + lio->draw.base + lioplaneadrs[pl]; - MEMR_READS(lput->seg, off, pt.pat, datacnt); - if (lput->sw) { - off += datacnt; - } - switch(lput->mode) { - case 0: // PSET - if (flag & (8 << 4)) { - putor(&pt); - } - else { - putandn(&pt); - } - if (flag & (8 << 8)) { - putorn(&pt); - } - else { - putand(&pt); - } - writecnt += 2; - break; - - case 1: // NOT - if (!(flag & (8 << 4))) { - putor(&pt); - } - else { - putandn(&pt); - } - if (!(flag & (8 << 8))) { - putorn(&pt); - } - else { - putand(&pt); - } - writecnt += 2; - break; - - case 2: // OR - if (flag & (8 << 4)) { - putor(&pt); - writecnt++; - } - if (flag & (8 << 8)) { - putorn(&pt); - writecnt++; - } - break; - - case 3: // AND - if (!(flag & (8 << 4))) { - putandn(&pt); - writecnt++; - } - if (!(flag & (8 << 8))) { - putand(&pt); - writecnt++; - } - break; - - case 4: // XOR - if (flag & (8 << 4)) { - putxor(&pt); - writecnt++; - } - if (flag & (8 << 8)) { - putxorn(&pt); - writecnt++; - } - break; - } - } - } - pt.addr += 80; - if (!lput->sw) { - off += datacnt; - } - } while(--height); - lio->wait += writecnt * datacnt * (10 + 10 + 10); - return(LIO_SUCCESS); -} - - -// ---- GGET - -REG8 lio_gget(GLIO lio) { - - GGET dat; - SINT32 x; - SINT32 y; - int x2; - int y2; - UINT off; - UINT seg; - UINT32 leng; - UINT32 size; - UINT datacnt; - UINT mask; - GETCNTX gt; - UINT8 pat[84]; - UINT pl; - - lio_updatedraw(lio); - MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); - x = (SINT16)LOADINTELWORD(dat.x1); - y = (SINT16)LOADINTELWORD(dat.y1); - x2 = (SINT16)LOADINTELWORD(dat.x2); - y2 = (SINT16)LOADINTELWORD(dat.y2); - if ((x < lio->draw.x1) || (y < lio->draw.y1) || - (x2 > lio->draw.x2) || (y2 > lio->draw.y2)) { - return(LIO_ILLEGALFUNC); - } - x2 = x2 - x + 1; - y2 = y2 - y + 1; - if ((x2 <= 0) || (y2 <= 0)) { - return(LIO_ILLEGALFUNC); - } - off = LOADINTELWORD(dat.off); - seg = (SINT16)LOADINTELWORD(dat.seg); - - datacnt = (x2 + 7) >> 3; - size = datacnt * y2; - leng = LOADINTELWORD(dat.leng); - if (!(lio->draw.flag & LIODRAW_MONO)) { - if (lio->draw.flag & LIODRAW_4BPP) { - size *= 4; - mask = 0x0f; - } - else { - size *= 3; - mask = 0x07; - } - } - else { - mask = 1 << (lio->draw.flag & LIODRAW_PMASK); - } - if (leng < (size + 4)) { - return(LIO_ILLEGALFUNC); - } - MEMR_WRITE16(seg, off, (REG16)x2); - MEMR_WRITE16(seg, off+2, (REG16)y2); - off += 4; - gt.addr = (x >> 3) + (y * 80); - if (lio->draw.flag & LIODRAW_UPPER) { - gt.addr += 16000; - } - gt.sft = x & 7; - gt.width = x2; - gt.mask = (UINT8)((~0x7f) >> ((x2 - 1) & 7)); - do { - mask <<= 4; - for (pl=0; pl<4; pl++) { - mask >>= 1; - if (mask & 8) { - gt.baseptr = mem + lio->draw.base + lioplaneadrs[pl]; - getvram(>, pat); - MEMR_WRITES(seg, off, pat, datacnt); - off += datacnt; - } - } - gt.addr += 80; - } while(--y2); - lio->wait = size * 12; - return(LIO_SUCCESS); -} - - -// ---- GPUT1 - -REG8 lio_gput1(GLIO lio) { - - GPUT1 dat; - LIOPUT lput; - UINT leng; - UINT size; - - lio_updatedraw(lio); - MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); - lput.x = (SINT16)LOADINTELWORD(dat.x); - lput.y = (SINT16)LOADINTELWORD(dat.y); - lput.off = (UINT16)(LOADINTELWORD(dat.off) + 4); - lput.seg = LOADINTELWORD(dat.seg); - lput.mode = dat.mode; - leng = LOADINTELWORD(dat.leng); - lput.width = MEMR_READ16(lput.seg, lput.off - 4); - lput.height = MEMR_READ16(lput.seg, lput.off - 2); - size = ((lput.width + 7) >> 3) * lput.height; - if (leng < (size + 4)) { - return(LIO_ILLEGALFUNC); - } - if (leng < ((size * 3) + 4)) { - lput.sw = 0; - if (dat.colorsw) { - lput.fg = dat.fg; - lput.bg = dat.bg; - } - else { - lput.fg = lio->work.fgcolor; - lput.bg = lio->work.bgcolor; - } - } - else { - if (dat.colorsw) { - lput.sw = 0; - lput.fg = dat.fg; - lput.bg = dat.bg; - } - else { - lput.sw = 1; - lput.fg = 0x0f; - lput.bg = 0; - } - } - return(putsub(lio, &lput)); -} - - -// ---- GPUT2 - -REG8 lio_gput2(GLIO lio) { - - GPUT2 dat; - LIOPUT lput; - UINT16 jis; - int pat; - REG16 size; - - lio_updatedraw(lio); - MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); - lput.x = (SINT16)LOADINTELWORD(dat.x); - lput.y = (SINT16)LOADINTELWORD(dat.y); - lput.off = 0x104e; - lput.seg = CPU_DS; - jis = LOADINTELWORD(dat.chr); - pat = 0; - if (jis < 0x200) { - if (jis < 0x80) { - if (jis == 0x7c) { - pat = 1; - } - else if (jis == 0x7e) { - pat = 2; - } - else { - jis += 0x2900; - } - } - else if (jis < 0x100) { - if ((jis - 0x20) & 0x40) { - pat = (jis & 0x3f) + 3; - } - else { - jis += 0x2980; - } - } - else { - jis &= 0xff; - } - } - if (!pat) { - size = bios0x18_14(lput.seg, 0x104c, jis); - } - else { - MEMR_WRITES(lput.seg, lput.off, mem + (LIO_SEGMENT << 4) + - LIO_FONT + ((pat - 1) << 4), 0x10); - size = 0x0102; - } - lput.width = (size & 0xff00) >> (8 - 3); - lput.height = (size & 0xff) << 3; - lput.mode = dat.mode; - lput.sw = 0; - if (dat.colorsw) { - lput.fg = dat.fg; - lput.bg = dat.bg; - } - else { - lput.fg = lio->work.fgcolor; - lput.bg = lio->work.bgcolor; - } - return(putsub(lio, &lput)); -} - +#include +#include +#include +#include +#include +#include "lio.h" +#include + + +typedef struct { + UINT8 x1[2]; + UINT8 y1[2]; + UINT8 x2[2]; + UINT8 y2[2]; + UINT8 off[2]; + UINT8 seg[2]; + UINT8 leng[2]; +} GGET; + +typedef struct { + UINT8 x[2]; + UINT8 y[2]; + UINT8 off[2]; + UINT8 seg[2]; + UINT8 leng[2]; + UINT8 mode; + UINT8 colorsw; + UINT8 fg; + UINT8 bg; +} GPUT1; + +typedef struct { + UINT8 x[2]; + UINT8 y[2]; + UINT8 chr[2]; + UINT8 mode; + UINT8 colorsw; + UINT8 fg; + UINT8 bg; +} GPUT2; + +typedef struct { + SINT16 x; + SINT16 y; + UINT16 width; + UINT16 height; + UINT16 off; + UINT16 seg; + UINT8 mode; + UINT8 sw; + UINT8 fg; + UINT8 bg; +} LIOPUT; + +typedef struct { + UINT8 *baseptr; + UINT addr; + UINT sft; + UINT width; + UINT8 mask; +} GETCNTX; + +typedef struct { + UINT8 *baseptr; + UINT addr; + UINT sft; + UINT width; + UINT8 maskl; + UINT8 maskr; + UINT8 masklr; + UINT8 mask; + UINT8 pat[84]; +} PUTCNTX; + + +static void getvram(const GETCNTX *gt, UINT8 *dst) { + + UINT8 *baseptr; + UINT addr; + UINT width; + UINT dat; + UINT sft; + + baseptr = gt->baseptr; + addr = gt->addr; + width = gt->width; + sft = 8 - gt->sft; + dat = baseptr[LOW15(addr)]; + addr++; + while(width > 8) { + width -= 8; + dat = (dat << 8) + baseptr[LOW15(addr)]; + addr++; + *dst = (UINT8)(dat >> sft); + dst++; + } + dat = (dat << 8) + baseptr[LOW15(addr)]; + *dst = (UINT8)((dat >> sft) & gt->mask); +} + +static void setdirty(UINT addr, UINT width, UINT height, REG8 bit) { + + UINT r; + + gdcs.grphdisp |= bit; + width = (width + 7) >> 3; + while(height--) { + r = 0; + while(r < width) { + vramupdate[LOW15(addr + r)] |= bit; + r++; + } + addr += 80; + } +} + +static void putor(const PUTCNTX *pt) { + + UINT8 *baseptr; + UINT addr; +const UINT8 *src; + UINT width; + UINT dat; + + baseptr = pt->baseptr; + addr = pt->addr; + src = pt->pat; + width = pt->width; + dat = *src++; + if ((pt->sft + width) < 8) { + baseptr[LOW15(addr)] |= (UINT8)((dat >> pt->sft) & pt->masklr); + } + else { + baseptr[LOW15(addr)] |= (UINT8)(dat >> pt->sft) & pt->maskl; + addr++; + width -= (8 - pt->sft); + while(width > 8) { + width -= 8; + dat = (dat << 8) + (*src); + src++; + baseptr[LOW15(addr)] |= (UINT8)(dat >> pt->sft); + addr++; + } + if (width) { + dat = (dat << 8) + (*src); + baseptr[LOW15(addr)] |= (UINT8)(dat >> pt->sft) & pt->maskr; + } + } +} + +static void putorn(const PUTCNTX *pt) { + + UINT8 *baseptr; + UINT addr; +const UINT8 *src; + UINT width; + UINT dat; + + baseptr = pt->baseptr; + addr = pt->addr; + src = pt->pat; + width = pt->width; + dat = *src++; + if ((pt->sft + width) < 8) { + baseptr[LOW15(addr)] |= (UINT8)(((~dat) >> pt->sft) & pt->masklr); + } + else { + baseptr[LOW15(addr)] |= (UINT8)(((~dat) >> pt->sft) & pt->maskl); + addr++; + width -= (8 - pt->sft); + while(width > 8) { + width -= 8; + dat = (dat << 8) + (*src); + src++; + baseptr[LOW15(addr)] |= (UINT8)((~dat) >> pt->sft); + addr++; + } + if (width) { + dat = (dat << 8) + (*src); + baseptr[LOW15(addr)] |= (UINT8)(((~dat) >> pt->sft) & pt->maskr); + } + } +} + +static void putand(const PUTCNTX *pt) { + + UINT8 *baseptr; + UINT addr; +const UINT8 *src; + UINT width; + UINT dat; + + baseptr = pt->baseptr; + addr = pt->addr; + src = pt->pat; + width = pt->width; + dat = *src++; + if ((pt->sft + width) < 8) { + baseptr[LOW15(addr)] &= (UINT8)((dat >> pt->sft) | (~pt->masklr)); + } + else { + baseptr[LOW15(addr)] &= (UINT8)((dat >> pt->sft) | (~pt->maskl)); + addr++; + width -= (8 - pt->sft); + while(width > 8) { + width -= 8; + dat = (dat << 8) + (*src); + src++; + baseptr[LOW15(addr)] &= (UINT8)(dat >> pt->sft); + addr++; + } + if (width) { + dat = (dat << 8) + (*src); + baseptr[LOW15(addr)] &= (UINT8)((dat >> pt->sft) | (~pt->maskr)); + } + } +} + +static void putandn(const PUTCNTX *pt) { + + UINT8 *baseptr; + UINT addr; +const UINT8 *src; + UINT width; + UINT dat; + + baseptr = pt->baseptr; + addr = pt->addr; + src = pt->pat; + width = pt->width; + dat = *src++; + if ((pt->sft + width) < 8) { + baseptr[LOW15(addr)] &= (UINT8)(~((dat >> pt->sft) & pt->masklr)); + } + else { + baseptr[LOW15(addr)] &= (UINT8)(~((dat >> pt->sft) & pt->maskl)); + addr++; + width -= (8 - pt->sft); + while(width > 8) { + width -= 8; + dat = (dat << 8) + (*src); + src++; + baseptr[LOW15(addr)] &= (UINT8)((~dat) >> pt->sft); + addr++; + } + if (width) { + dat = (dat << 8) + (*src); + baseptr[LOW15(addr)] &= (UINT8)(~((dat >> pt->sft) & pt->maskr)); + } + } +} + +static void putxor(const PUTCNTX *pt) { + + UINT8 *baseptr; + UINT addr; +const UINT8 *src; + UINT width; + UINT dat; + + baseptr = pt->baseptr; + addr = pt->addr; + src = pt->pat; + width = pt->width; + dat = *src++; + if ((pt->sft + width) < 8) { + baseptr[LOW15(addr)] ^= (UINT8)((dat >> pt->sft) & pt->masklr); + } + else { + baseptr[LOW15(addr)] ^= (UINT8)(dat >> pt->sft) & pt->maskl; + addr++; + width -= (8 - pt->sft); + while(width > 8) { + width -= 8; + dat = (dat << 8) + (*src); + src++; + baseptr[LOW15(addr)] ^= (UINT8)(dat >> pt->sft); + addr++; + } + if (width) { + dat = (dat << 8) + (*src); + baseptr[LOW15(addr)] ^= (UINT8)(dat >> pt->sft) & pt->maskr; + } + } +} + +static void putxorn(const PUTCNTX *pt) { + + UINT8 *baseptr; + UINT addr; +const UINT8 *src; + UINT width; + UINT dat; + + baseptr = pt->baseptr; + addr = pt->addr; + src = pt->pat; + width = pt->width; + dat = *src++; + if ((pt->sft + width) < 8) { + baseptr[LOW15(addr)] ^= (UINT8)(((~dat) >> pt->sft) & pt->masklr); + } + else { + baseptr[LOW15(addr)] ^= (UINT8)(((~dat) >> pt->sft) & pt->maskl); + addr++; + width -= (8 - pt->sft); + while(width > 8) { + width -= 8; + dat = (dat << 8) + (*src); + src++; + baseptr[LOW15(addr)] ^= (UINT8)((~dat) >> pt->sft); + addr++; + } + if (width) { + dat = (dat << 8) + (*src); + baseptr[LOW15(addr)] ^= (UINT8)(((~dat) >> pt->sft) & pt->maskr); + } + } +} + + +// ---- + +static REG8 putsub(GLIO lio, const LIOPUT *lput) { + + UINT addr; + PUTCNTX pt; + UINT datacnt; + UINT off; + UINT height; + UINT flag; + UINT pl; + UINT writecnt; + + if ((lput->x < lio->draw.x1) || + (lput->y < lio->draw.y1) || + ((lput->x + lput->width - 1) > lio->draw.x2) || + ((lput->y + lput->height - 1) > lio->draw.y2)) { + return(LIO_ILLEGALFUNC); + } + if ((lput->width <= 0) || (lput->height <= 0)) { + return(LIO_SUCCESS); + } + + addr = (lput->x >> 3) + (lput->y * 80); + if (lio->draw.flag & LIODRAW_UPPER) { + addr += 16000; + } + setdirty(addr, (lput->x & 7) + lput->width, lput->height, lio->draw.sbit); + + pt.addr = addr; + pt.sft = lput->x & 7; + pt.width = lput->width; + pt.maskl = (UINT8)(0xff >> pt.sft); + pt.maskr = (UINT8)((~0x7f) >> ((pt.width + pt.sft - 1) & 7)); + pt.masklr = (UINT8)(pt.maskl >> pt.sft); + + datacnt = (lput->width + 7) >> 3; + off = lput->off; + + flag = (lio->draw.flag & LIODRAW_4BPP)?0x0f:0x07; + flag |= (lput->fg & 15) << 4; + flag |= (lput->bg & 15) << 8; + + // さて表示。 + writecnt = 0; + height = lput->height; + do { + flag <<= 4; + for (pl=0; pl<4; pl++) { + flag >>= 1; + if (flag & 8) { + pt.baseptr = mem + lio->draw.base + lioplaneadrs[pl]; + MEMR_READS(lput->seg, off, pt.pat, datacnt); + if (lput->sw) { + off += datacnt; + } + switch(lput->mode) { + case 0: // PSET + if (flag & (8 << 4)) { + putor(&pt); + } + else { + putandn(&pt); + } + if (flag & (8 << 8)) { + putorn(&pt); + } + else { + putand(&pt); + } + writecnt += 2; + break; + + case 1: // NOT + if (!(flag & (8 << 4))) { + putor(&pt); + } + else { + putandn(&pt); + } + if (!(flag & (8 << 8))) { + putorn(&pt); + } + else { + putand(&pt); + } + writecnt += 2; + break; + + case 2: // OR + if (flag & (8 << 4)) { + putor(&pt); + writecnt++; + } + if (flag & (8 << 8)) { + putorn(&pt); + writecnt++; + } + break; + + case 3: // AND + if (!(flag & (8 << 4))) { + putandn(&pt); + writecnt++; + } + if (!(flag & (8 << 8))) { + putand(&pt); + writecnt++; + } + break; + + case 4: // XOR + if (flag & (8 << 4)) { + putxor(&pt); + writecnt++; + } + if (flag & (8 << 8)) { + putxorn(&pt); + writecnt++; + } + break; + } + } + } + pt.addr += 80; + if (!lput->sw) { + off += datacnt; + } + } while(--height); + lio->wait += writecnt * datacnt * (10 + 10 + 10); + return(LIO_SUCCESS); +} + + +// ---- GGET + +REG8 lio_gget(GLIO lio) { + + GGET dat; + SINT32 x; + SINT32 y; + int x2; + int y2; + UINT off; + UINT seg; + UINT32 leng; + UINT32 size; + UINT datacnt; + UINT mask; + GETCNTX gt; + UINT8 pat[84]; + UINT pl; + + lio_updatedraw(lio); + MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); + x = (SINT16)LOADINTELWORD(dat.x1); + y = (SINT16)LOADINTELWORD(dat.y1); + x2 = (SINT16)LOADINTELWORD(dat.x2); + y2 = (SINT16)LOADINTELWORD(dat.y2); + if ((x < lio->draw.x1) || (y < lio->draw.y1) || + (x2 > lio->draw.x2) || (y2 > lio->draw.y2)) { + return(LIO_ILLEGALFUNC); + } + x2 = x2 - x + 1; + y2 = y2 - y + 1; + if ((x2 <= 0) || (y2 <= 0)) { + return(LIO_ILLEGALFUNC); + } + off = LOADINTELWORD(dat.off); + seg = (SINT16)LOADINTELWORD(dat.seg); + + datacnt = (x2 + 7) >> 3; + size = datacnt * y2; + leng = LOADINTELWORD(dat.leng); + if (!(lio->draw.flag & LIODRAW_MONO)) { + if (lio->draw.flag & LIODRAW_4BPP) { + size *= 4; + mask = 0x0f; + } + else { + size *= 3; + mask = 0x07; + } + } + else { + mask = 1 << (lio->draw.flag & LIODRAW_PMASK); + } + if (leng < (size + 4)) { + return(LIO_ILLEGALFUNC); + } + MEMR_WRITE16(seg, off, (REG16)x2); + MEMR_WRITE16(seg, off+2, (REG16)y2); + off += 4; + gt.addr = (x >> 3) + (y * 80); + if (lio->draw.flag & LIODRAW_UPPER) { + gt.addr += 16000; + } + gt.sft = x & 7; + gt.width = x2; + gt.mask = (UINT8)((~0x7f) >> ((x2 - 1) & 7)); + do { + mask <<= 4; + for (pl=0; pl<4; pl++) { + mask >>= 1; + if (mask & 8) { + gt.baseptr = mem + lio->draw.base + lioplaneadrs[pl]; + getvram(>, pat); + MEMR_WRITES(seg, off, pat, datacnt); + off += datacnt; + } + } + gt.addr += 80; + } while(--y2); + lio->wait = size * 12; + return(LIO_SUCCESS); +} + + +// ---- GPUT1 + +REG8 lio_gput1(GLIO lio) { + + GPUT1 dat; + LIOPUT lput; + UINT leng; + UINT size; + + lio_updatedraw(lio); + MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); + lput.x = (SINT16)LOADINTELWORD(dat.x); + lput.y = (SINT16)LOADINTELWORD(dat.y); + lput.off = (UINT16)(LOADINTELWORD(dat.off) + 4); + lput.seg = LOADINTELWORD(dat.seg); + lput.mode = dat.mode; + leng = LOADINTELWORD(dat.leng); + lput.width = MEMR_READ16(lput.seg, lput.off - 4); + lput.height = MEMR_READ16(lput.seg, lput.off - 2); + size = ((lput.width + 7) >> 3) * lput.height; + if (leng < (size + 4)) { + return(LIO_ILLEGALFUNC); + } + if (leng < ((size * 3) + 4)) { + lput.sw = 0; + if (dat.colorsw) { + lput.fg = dat.fg; + lput.bg = dat.bg; + } + else { + lput.fg = lio->work.fgcolor; + lput.bg = lio->work.bgcolor; + } + } + else { + if (dat.colorsw) { + lput.sw = 0; + lput.fg = dat.fg; + lput.bg = dat.bg; + } + else { + lput.sw = 1; + lput.fg = 0x0f; + lput.bg = 0; + } + } + return(putsub(lio, &lput)); +} + + +// ---- GPUT2 + +REG8 lio_gput2(GLIO lio) { + + GPUT2 dat; + LIOPUT lput; + UINT16 jis; + int pat; + REG16 size; + + lio_updatedraw(lio); + MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); + lput.x = (SINT16)LOADINTELWORD(dat.x); + lput.y = (SINT16)LOADINTELWORD(dat.y); + lput.off = 0x104e; + lput.seg = CPU_DS; + jis = LOADINTELWORD(dat.chr); + pat = 0; + if (jis < 0x200) { + if (jis < 0x80) { + if (jis == 0x7c) { + pat = 1; + } + else if (jis == 0x7e) { + pat = 2; + } + else { + jis += 0x2900; + } + } + else if (jis < 0x100) { + if ((jis - 0x20) & 0x40) { + pat = (jis & 0x3f) + 3; + } + else { + jis += 0x2980; + } + } + else { + jis &= 0xff; + } + } + if (!pat) { + size = bios0x18_14(lput.seg, 0x104c, jis); + } + else { + MEMR_WRITES(lput.seg, lput.off, mem + (LIO_SEGMENT << 4) + + LIO_FONT + ((pat - 1) << 4), 0x10); + size = 0x0102; + } + lput.width = (size & 0xff00) >> (8 - 3); + lput.height = (size & 0xff) << 3; + lput.mode = dat.mode; + lput.sw = 0; + if (dat.colorsw) { + lput.fg = dat.fg; + lput.bg = dat.bg; + } + else { + lput.fg = lio->work.fgcolor; + lput.bg = lio->work.bgcolor; + } + return(putsub(lio, &lput)); +} + diff --git a/lio/gscreen.c b/lio/gscreen.c old mode 100755 new mode 100644 index c65d4dfd..c6737129 --- a/lio/gscreen.c +++ b/lio/gscreen.c @@ -1,311 +1,311 @@ -#include -#include -#include -#include -#include -#include -#include "lio.h" -#include - - -typedef struct { - UINT8 mode; - UINT8 sw; - UINT8 act; - UINT8 disp; -} GSCREEN; - -typedef struct { - UINT8 x1[2]; - UINT8 y1[2]; - UINT8 x2[2]; - UINT8 y2[2]; - UINT8 vdraw_bg; - UINT8 vdraw_ln; -} GVIEW; - -typedef struct { - UINT8 dummy; - UINT8 bgcolor; - UINT8 bdcolor; - UINT8 fgcolor; - UINT8 palmode; -} GCOLOR1; - -typedef struct { - UINT8 pal; - UINT8 color1; - UINT8 color2; -} GCOLOR2; - - -// ---- INIT - -REG8 lio_ginit(GLIO lio) { - - UINT i; - - vramop.operate &= ~(1 << VOPBIT_ACCESS); - MEMM_VRAM(vramop.operate); - bios0x18_42(0x80); - bios0x18_40(); - iocore_out8(0x006a, 0); - gdc_paletteinit(); - - ZeroMemory(&lio->work, sizeof(lio->work)); -// lio->work.scrnmode = 0; -// lio->work.pos = 0; - lio->work.plane = 1; -// lio->work.bgcolor = 0; - lio->work.fgcolor = 7; - for (i=0; i<8; i++) { - lio->work.color[i] = (UINT8)i; - } -// STOREINTELWORD(lio->work.viewx1, 0); -// STOREINTELWORD(lio->work.viewy1, 0); - STOREINTELWORD(lio->work.viewx2, 639); - STOREINTELWORD(lio->work.viewy2, 399); - lio->palmode = 0; - MEMR_WRITES(CPU_DS, 0x0620, &lio->work, sizeof(lio->work)); - MEMR_WRITE8(CPU_DS, 0x0a08, lio->palmode); - return(LIO_SUCCESS); -} - - -// ---- SCREEN - -REG8 lio_gscreen(GLIO lio) { - - GSCREEN dat; - UINT colorbit; - UINT8 scrnmode; - UINT8 mono; - UINT8 act; - UINT8 pos; - UINT8 disp; - UINT8 plane; - UINT8 planemax; - UINT8 mode; - - if (lio->palmode != 2) { - colorbit = 3; - } - else { - colorbit = 4; - } - MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); - scrnmode = dat.mode; - if (scrnmode == 0xff) { - scrnmode = lio->work.scrnmode; - } - else { - if ((dat.mode >= 2) && (!(mem[MEMB_PRXCRT] & 0x40))) { - goto gscreen_err5; - } - } - if (scrnmode >= 4) { - goto gscreen_err5; - } - if (dat.sw != 0xff) { - if (!(dat.sw & 2)) { - bios0x18_40(); - } - else { - bios0x18_41(); - } - } - - mono = ((scrnmode + 1) >> 1) & 1; - act = dat.act; - if (act == 0xff) { - if (scrnmode != lio->work.scrnmode) { - lio->work.pos = 0; - lio->work.access = 0; - } - } - else { - switch(scrnmode) { - case 0: - pos = act & 1; - act >>= 1; - break; - - case 1: - pos = act % (colorbit * 2); - act = act / (colorbit * 2); - break; - - case 2: - pos = act % colorbit; - act = act / colorbit; - break; - - case 3: - default: - pos = 0; - break; - } - if (act >= 2) { - goto gscreen_err5; - } - lio->work.pos = pos; - lio->work.access = act; - } - disp = dat.disp; - if (disp == 0xff) { - if (scrnmode != lio->work.scrnmode) { - lio->work.plane = 1; - lio->work.disp = 0; - } - } - else { - plane = disp & ((2 << colorbit) - 1); - disp >>= (colorbit + 1); - if (disp >= 2) { - goto gscreen_err5; - } - lio->work.disp = disp; - planemax = 1; - if (mono) { - planemax <<= colorbit; - } - if (!(scrnmode & 2)) { - planemax <<= 1; - } - if ((plane > planemax) && - (plane != (1 << colorbit))) { - goto gscreen_err5; - } - lio->work.plane = plane; - lio->work.disp = disp; - } - - lio->work.scrnmode = scrnmode; - pos = lio->work.pos; - switch(scrnmode) { - case 0: - mode = (pos)?0x40:0x80; - break; - - case 1: - mode = (pos >= colorbit)?0x60:0xa0; - break; - - case 2: - mode = 0xe0; - break; - - case 3: - default: - mode = 0xc0; - break; - } - mode |= disp << 4; - bios0x18_42(mode); - iocore_out8(0x00a6, lio->work.access); - MEMR_WRITES(CPU_DS, 0x0620, &lio->work, sizeof(lio->work)); - return(LIO_SUCCESS); - -gscreen_err5: - TRACEOUT(("screen error! %d %d %d %d", - dat.mode, dat.sw, dat.act, dat.disp)); - return(LIO_ILLEGALFUNC); -} - - -// ---- VIEW - -REG8 lio_gview(GLIO lio) { - - GVIEW dat; - int x1; - int y1; - int x2; - int y2; - - MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); - x1 = (SINT16)LOADINTELWORD(dat.x1); - y1 = (SINT16)LOADINTELWORD(dat.y1); - x2 = (SINT16)LOADINTELWORD(dat.x2); - y2 = (SINT16)LOADINTELWORD(dat.y2); - if ((x1 >= x2) || (y1 >= y2)) { - return(LIO_ILLEGALFUNC); - } - STOREINTELWORD(lio->work.viewx1, (UINT16)x1); - STOREINTELWORD(lio->work.viewy1, (UINT16)y1); - STOREINTELWORD(lio->work.viewx2, (UINT16)x2); - STOREINTELWORD(lio->work.viewy2, (UINT16)y2); - MEMR_WRITES(CPU_DS, 0x0620, &lio->work, sizeof(lio->work)); - return(LIO_SUCCESS); -} - - -// ---- COLOR1 - -REG8 lio_gcolor1(GLIO lio) { - - GCOLOR1 dat; - - MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); - if (dat.bgcolor != 0xff) { - lio->work.bgcolor = dat.bgcolor; - } - if (dat.fgcolor == 0xff) { - lio->work.fgcolor = dat.fgcolor; - } - if (dat.palmode != 0xff) { - if (!(mem[MEMB_PRXCRT] & 1)) { // 8color lio - dat.palmode = 0; - } - else { - if (!(mem[MEMB_PRXCRT] & 4)) { // have e-plane? - goto gcolor1_err5; - } - if (!dat.palmode) { - iocore_out8(0x006a, 0); - } - else { - iocore_out8(0x006a, 1); - } - } - lio->palmode = dat.palmode; - } - MEMR_WRITES(CPU_DS, 0x0620, &lio->work, sizeof(lio->work)); - MEMR_WRITE8(CPU_DS, 0x0a08, lio->palmode); - return(LIO_SUCCESS); - -gcolor1_err5: - return(LIO_ILLEGALFUNC); -} - - -// ---- COLOR2 - -REG8 lio_gcolor2(GLIO lio) { - - GCOLOR2 dat; - - MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); - if (dat.pal >= ((lio->palmode == 2)?16:8)) { - goto gcolor2_err5; - } - if (!lio->palmode) { - dat.color1 &= 7; - lio->work.color[dat.pal] = dat.color1; - gdc_setdegitalpal(dat.pal, dat.color1); - } - else { - gdc_setanalogpal(dat.pal, offsetof(RGB32, p.b), - (UINT8)(dat.color1 & 0x0f)); - gdc_setanalogpal(dat.pal, offsetof(RGB32, p.r), - (UINT8)(dat.color1 >> 4)); - gdc_setanalogpal(dat.pal, offsetof(RGB32, p.g), - (UINT8)(dat.color2 & 0x0f)); - } - MEMR_WRITES(CPU_DS, 0x0620, &lio->work, sizeof(lio->work)); - return(LIO_SUCCESS); - -gcolor2_err5: - return(LIO_ILLEGALFUNC); -} - +#include +#include +#include +#include +#include +#include +#include "lio.h" +#include + + +typedef struct { + UINT8 mode; + UINT8 sw; + UINT8 act; + UINT8 disp; +} GSCREEN; + +typedef struct { + UINT8 x1[2]; + UINT8 y1[2]; + UINT8 x2[2]; + UINT8 y2[2]; + UINT8 vdraw_bg; + UINT8 vdraw_ln; +} GVIEW; + +typedef struct { + UINT8 dummy; + UINT8 bgcolor; + UINT8 bdcolor; + UINT8 fgcolor; + UINT8 palmode; +} GCOLOR1; + +typedef struct { + UINT8 pal; + UINT8 color1; + UINT8 color2; +} GCOLOR2; + + +// ---- INIT + +REG8 lio_ginit(GLIO lio) { + + UINT i; + + vramop.operate &= ~(1 << VOPBIT_ACCESS); + MEMM_VRAM(vramop.operate); + bios0x18_42(0x80); + bios0x18_40(); + iocore_out8(0x006a, 0); + gdc_paletteinit(); + + ZeroMemory(&lio->work, sizeof(lio->work)); +// lio->work.scrnmode = 0; +// lio->work.pos = 0; + lio->work.plane = 1; +// lio->work.bgcolor = 0; + lio->work.fgcolor = 7; + for (i=0; i<8; i++) { + lio->work.color[i] = (UINT8)i; + } +// STOREINTELWORD(lio->work.viewx1, 0); +// STOREINTELWORD(lio->work.viewy1, 0); + STOREINTELWORD(lio->work.viewx2, 639); + STOREINTELWORD(lio->work.viewy2, 399); + lio->palmode = 0; + MEMR_WRITES(CPU_DS, 0x0620, &lio->work, sizeof(lio->work)); + MEMR_WRITE8(CPU_DS, 0x0a08, lio->palmode); + return(LIO_SUCCESS); +} + + +// ---- SCREEN + +REG8 lio_gscreen(GLIO lio) { + + GSCREEN dat; + UINT colorbit; + UINT8 scrnmode; + UINT8 mono; + UINT8 act; + UINT8 pos; + UINT8 disp; + UINT8 plane; + UINT8 planemax; + UINT8 mode; + + if (lio->palmode != 2) { + colorbit = 3; + } + else { + colorbit = 4; + } + MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); + scrnmode = dat.mode; + if (scrnmode == 0xff) { + scrnmode = lio->work.scrnmode; + } + else { + if ((dat.mode >= 2) && (!(mem[MEMB_PRXCRT] & 0x40))) { + goto gscreen_err5; + } + } + if (scrnmode >= 4) { + goto gscreen_err5; + } + if (dat.sw != 0xff) { + if (!(dat.sw & 2)) { + bios0x18_40(); + } + else { + bios0x18_41(); + } + } + + mono = ((scrnmode + 1) >> 1) & 1; + act = dat.act; + if (act == 0xff) { + if (scrnmode != lio->work.scrnmode) { + lio->work.pos = 0; + lio->work.access = 0; + } + } + else { + switch(scrnmode) { + case 0: + pos = act & 1; + act >>= 1; + break; + + case 1: + pos = act % (colorbit * 2); + act = act / (colorbit * 2); + break; + + case 2: + pos = act % colorbit; + act = act / colorbit; + break; + + case 3: + default: + pos = 0; + break; + } + if (act >= 2) { + goto gscreen_err5; + } + lio->work.pos = pos; + lio->work.access = act; + } + disp = dat.disp; + if (disp == 0xff) { + if (scrnmode != lio->work.scrnmode) { + lio->work.plane = 1; + lio->work.disp = 0; + } + } + else { + plane = disp & ((2 << colorbit) - 1); + disp >>= (colorbit + 1); + if (disp >= 2) { + goto gscreen_err5; + } + lio->work.disp = disp; + planemax = 1; + if (mono) { + planemax <<= colorbit; + } + if (!(scrnmode & 2)) { + planemax <<= 1; + } + if ((plane > planemax) && + (plane != (1 << colorbit))) { + goto gscreen_err5; + } + lio->work.plane = plane; + lio->work.disp = disp; + } + + lio->work.scrnmode = scrnmode; + pos = lio->work.pos; + switch(scrnmode) { + case 0: + mode = (pos)?0x40:0x80; + break; + + case 1: + mode = (pos >= colorbit)?0x60:0xa0; + break; + + case 2: + mode = 0xe0; + break; + + case 3: + default: + mode = 0xc0; + break; + } + mode |= disp << 4; + bios0x18_42(mode); + iocore_out8(0x00a6, lio->work.access); + MEMR_WRITES(CPU_DS, 0x0620, &lio->work, sizeof(lio->work)); + return(LIO_SUCCESS); + +gscreen_err5: + TRACEOUT(("screen error! %d %d %d %d", + dat.mode, dat.sw, dat.act, dat.disp)); + return(LIO_ILLEGALFUNC); +} + + +// ---- VIEW + +REG8 lio_gview(GLIO lio) { + + GVIEW dat; + int x1; + int y1; + int x2; + int y2; + + MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); + x1 = (SINT16)LOADINTELWORD(dat.x1); + y1 = (SINT16)LOADINTELWORD(dat.y1); + x2 = (SINT16)LOADINTELWORD(dat.x2); + y2 = (SINT16)LOADINTELWORD(dat.y2); + if ((x1 >= x2) || (y1 >= y2)) { + return(LIO_ILLEGALFUNC); + } + STOREINTELWORD(lio->work.viewx1, (UINT16)x1); + STOREINTELWORD(lio->work.viewy1, (UINT16)y1); + STOREINTELWORD(lio->work.viewx2, (UINT16)x2); + STOREINTELWORD(lio->work.viewy2, (UINT16)y2); + MEMR_WRITES(CPU_DS, 0x0620, &lio->work, sizeof(lio->work)); + return(LIO_SUCCESS); +} + + +// ---- COLOR1 + +REG8 lio_gcolor1(GLIO lio) { + + GCOLOR1 dat; + + MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); + if (dat.bgcolor != 0xff) { + lio->work.bgcolor = dat.bgcolor; + } + if (dat.fgcolor == 0xff) { + lio->work.fgcolor = dat.fgcolor; + } + if (dat.palmode != 0xff) { + if (!(mem[MEMB_PRXCRT] & 1)) { // 8color lio + dat.palmode = 0; + } + else { + if (!(mem[MEMB_PRXCRT] & 4)) { // have e-plane? + goto gcolor1_err5; + } + if (!dat.palmode) { + iocore_out8(0x006a, 0); + } + else { + iocore_out8(0x006a, 1); + } + } + lio->palmode = dat.palmode; + } + MEMR_WRITES(CPU_DS, 0x0620, &lio->work, sizeof(lio->work)); + MEMR_WRITE8(CPU_DS, 0x0a08, lio->palmode); + return(LIO_SUCCESS); + +gcolor1_err5: + return(LIO_ILLEGALFUNC); +} + + +// ---- COLOR2 + +REG8 lio_gcolor2(GLIO lio) { + + GCOLOR2 dat; + + MEMR_READS(CPU_DS, CPU_BX, &dat, sizeof(dat)); + if (dat.pal >= ((lio->palmode == 2)?16:8)) { + goto gcolor2_err5; + } + if (!lio->palmode) { + dat.color1 &= 7; + lio->work.color[dat.pal] = dat.color1; + gdc_setdegitalpal(dat.pal, dat.color1); + } + else { + gdc_setanalogpal(dat.pal, offsetof(RGB32, p.b), + (UINT8)(dat.color1 & 0x0f)); + gdc_setanalogpal(dat.pal, offsetof(RGB32, p.r), + (UINT8)(dat.color1 >> 4)); + gdc_setanalogpal(dat.pal, offsetof(RGB32, p.g), + (UINT8)(dat.color2 & 0x0f)); + } + MEMR_WRITES(CPU_DS, 0x0620, &lio->work, sizeof(lio->work)); + return(LIO_SUCCESS); + +gcolor2_err5: + return(LIO_ILLEGALFUNC); +} + diff --git a/lio/lio.c b/lio/lio.c old mode 100755 new mode 100644 index 04a348bb..b0e0ca47 --- a/lio/lio.c +++ b/lio/lio.c @@ -1,288 +1,288 @@ -/** - * @file lio.c - * @brief Implementation of LIO - */ - -#include -#include "lio.h" -#include -#include -#include -#include -#include -#include -#include -#include "lio.res" - -void lio_initialize(void) { - - CopyMemory(mem + (LIO_SEGMENT << 4), liorom, sizeof(liorom)); -} - -void bios_lio(REG8 cmd) { - - _GLIO lio; - UINT8 ret; - -// TRACEOUT(("lio command %.2x", cmd)); - MEMR_READS(CPU_DS, 0x0620, &lio.work, sizeof(lio.work)); - lio.palmode = MEMR_READ8(CPU_DS, 0x0a08); - lio.wait = 0; - switch(cmd) { - case 0x00: // a0: GINIT - ret = lio_ginit(&lio); - break; - - case 0x01: // a1: GSCREEN - ret = lio_gscreen(&lio); - break; - - case 0x02: // a2: GVIEW - ret = lio_gview(&lio); - break; - - case 0x03: // a3: GCOLOR1 - ret = lio_gcolor1(&lio); - break; - - case 0x04: // a4: GCOLOR2 - ret = lio_gcolor2(&lio); - break; - - case 0x05: // a5: GCLS - ret = lio_gcls(&lio); - break; - - case 0x06: // a6: GPSET - ret = lio_gpset(&lio); - break; - - case 0x07: // a7: GLINE - ret = lio_gline(&lio); - break; - - case 0x08: // a8: GCIRCLE - ret = lio_gcircle(&lio); - break; - -// case 0x09: // a9: GPAINT1 -// break; - -// case 0x0a: // aa: GPAINT2 -// break; - - case 0x0b: // ab: GGET - ret = lio_gget(&lio); - break; - - case 0x0c: // ac: GPUT1 - ret = lio_gput1(&lio); - break; - - case 0x0d: // ad: GPUT2 - ret = lio_gput2(&lio); - break; - -// case 0x0e: // ae: GROLL -// break; - - case 0x0f: // af: GPOINT2 - ret = lio_gpoint2(&lio); - break; - -// case 0x10: // ce: GCOPY -// break; - - default: - ret = LIO_SUCCESS; - break; - } - CPU_AH = ret; - if (lio.wait) { - gdcsub_setslavewait(lio.wait); - } -} - - -// ---- - -const UINT32 lioplaneadrs[4] = {VRAM_B, VRAM_R, VRAM_G, VRAM_E}; - -void lio_updatedraw(GLIO lio) { - - UINT8 flag; - UINT8 colorbit; - SINT16 maxline; - SINT16 tmp; - - flag = 0; - colorbit = 3; - maxline = 399; - if (lio->palmode == 2) { - flag |= LIODRAW_4BPP; - colorbit = 4; - } - switch(lio->work.scrnmode) { - case 0: - if (lio->work.pos & 1) { - flag |= LIODRAW_UPPER; - } - maxline = 199; - break; - - case 1: - flag |= lio->work.pos % colorbit; - flag |= LIODRAW_MONO; - if (lio->work.pos >= colorbit) { - flag |= LIODRAW_UPPER; - } - maxline = 199; - break; - - case 2: - flag |= lio->work.pos % colorbit; - flag |= LIODRAW_MONO; - break; - } - lio->draw.flag = flag; - lio->draw.palmax = 1 << colorbit; - - tmp = (SINT16)LOADINTELWORD(lio->work.viewx1); - lio->draw.x1 = MAX(tmp, 0); - tmp = (SINT16)LOADINTELWORD(lio->work.viewy1); - lio->draw.y1 = MAX(tmp, 0); - tmp = (SINT16)LOADINTELWORD(lio->work.viewx2); - lio->draw.x2 = MIN(tmp, 639); - tmp = (SINT16)LOADINTELWORD(lio->work.viewy2); - lio->draw.y2 = MIN(tmp, maxline); - if (!gdcs.access) { - lio->draw.base = 0; - lio->draw.bank = 0; - lio->draw.sbit = 0x01; - } - else { - lio->draw.base = VRAM_STEP; - lio->draw.bank = 1; - lio->draw.sbit = 0x02; - } -} - - -// ---- - -static void pixed8(const _GLIO *lio, UINT addr, REG8 bit, REG8 pal) { - - UINT8 *ptr; - - addr = LOW15(addr); - vramupdate[addr] |= lio->draw.sbit; - ptr = mem + lio->draw.base + addr; - if (!(lio->draw.flag & LIODRAW_MONO)) { - if (pal & 1) { - ptr[VRAM_B] |= bit; - } - else { - ptr[VRAM_B] &= ~bit; - } - if (pal & 2) { - ptr[VRAM_R] |= bit; - } - else { - ptr[VRAM_R] &= ~bit; - } - if (pal & 4) { - ptr[VRAM_G] |= bit; - } - else { - ptr[VRAM_G] &= ~bit; - } - if (lio->draw.flag & LIODRAW_4BPP) { - if (pal & 8) { - ptr[VRAM_E] |= bit; - } - else { - ptr[VRAM_E] &= ~bit; - } - } - } - else { - ptr += lioplaneadrs[lio->draw.flag & LIODRAW_PMASK]; - if (pal) { - *ptr |= bit; - } - else { - *ptr &= ~bit; - } - } -} - -void lio_pset(const _GLIO *lio, SINT16 x, SINT16 y, REG8 pal) { - - UINT addr; - UINT8 bit; - - if ((lio->draw.x1 > x) || (lio->draw.x2 < x) || - (lio->draw.y1 > y) || (lio->draw.y2 < y)) { - return; - } - addr = (y * 80) + (x >> 3); - bit = 0x80 >> (x & 7); - if (lio->draw.flag & LIODRAW_UPPER) { - addr += 16000; - } - gdcs.grphdisp |= lio->draw.sbit; - pixed8(lio, addr, bit, pal); -} - -#if 0 -void lio_line(const _GLIO *lio, SINT16 x1, SINT16 x2, SINT16 y, REG8 pal) { - - UINT addr; - UINT8 bit, dbit; - SINT16 width; - - if ((lio->draw.y1 > y) || (lio->draw.y2 < y)) { - return; - } - if (lio->draw.x1 > x1) { - x1 = lio->draw.x1; - } - if (lio->draw.x2 < x2) { - x2 = lio->draw.x2; - } - width = x2 - x1 + 1; - if (width <= 0) { - return; - } - addr = (y * 80) + (x1 >> 3); - bit = 0x80 >> (x1 & 7); - if (lio->draw.flag & LIODRAW_UPPER) { - addr += 16000; - } - gdcs.grphdisp |= lio->draw.sbit; - dbit = 0; - while((bit) && (width)) { - dbit |= bit; - bit >>= 1; - width--; - } - pixed8(lio, addr, dbit, pal); - addr++; - while(width >= 8) { - width -= 8; - pixed8(lio, addr, 0xff, pal); - addr++; - } - dbit = 0; - bit = 0x80; - while((bit) && (width)) { - dbit |= bit; - bit >>= 1; - width--; - } - if (dbit) { - pixed8(lio, addr, dbit, pal); - } -} -#endif - +/** + * @file lio.c + * @brief Implementation of LIO + */ + +#include +#include "lio.h" +#include +#include +#include +#include +#include +#include +#include +#include "lio.res" + +void lio_initialize(void) { + + CopyMemory(mem + (LIO_SEGMENT << 4), liorom, sizeof(liorom)); +} + +void bios_lio(REG8 cmd) { + + _GLIO lio; + UINT8 ret; + +// TRACEOUT(("lio command %.2x", cmd)); + MEMR_READS(CPU_DS, 0x0620, &lio.work, sizeof(lio.work)); + lio.palmode = MEMR_READ8(CPU_DS, 0x0a08); + lio.wait = 0; + switch(cmd) { + case 0x00: // a0: GINIT + ret = lio_ginit(&lio); + break; + + case 0x01: // a1: GSCREEN + ret = lio_gscreen(&lio); + break; + + case 0x02: // a2: GVIEW + ret = lio_gview(&lio); + break; + + case 0x03: // a3: GCOLOR1 + ret = lio_gcolor1(&lio); + break; + + case 0x04: // a4: GCOLOR2 + ret = lio_gcolor2(&lio); + break; + + case 0x05: // a5: GCLS + ret = lio_gcls(&lio); + break; + + case 0x06: // a6: GPSET + ret = lio_gpset(&lio); + break; + + case 0x07: // a7: GLINE + ret = lio_gline(&lio); + break; + + case 0x08: // a8: GCIRCLE + ret = lio_gcircle(&lio); + break; + +// case 0x09: // a9: GPAINT1 +// break; + +// case 0x0a: // aa: GPAINT2 +// break; + + case 0x0b: // ab: GGET + ret = lio_gget(&lio); + break; + + case 0x0c: // ac: GPUT1 + ret = lio_gput1(&lio); + break; + + case 0x0d: // ad: GPUT2 + ret = lio_gput2(&lio); + break; + +// case 0x0e: // ae: GROLL +// break; + + case 0x0f: // af: GPOINT2 + ret = lio_gpoint2(&lio); + break; + +// case 0x10: // ce: GCOPY +// break; + + default: + ret = LIO_SUCCESS; + break; + } + CPU_AH = ret; + if (lio.wait) { + gdcsub_setslavewait(lio.wait); + } +} + + +// ---- + +const UINT32 lioplaneadrs[4] = {VRAM_B, VRAM_R, VRAM_G, VRAM_E}; + +void lio_updatedraw(GLIO lio) { + + UINT8 flag; + UINT8 colorbit; + SINT16 maxline; + SINT16 tmp; + + flag = 0; + colorbit = 3; + maxline = 399; + if (lio->palmode == 2) { + flag |= LIODRAW_4BPP; + colorbit = 4; + } + switch(lio->work.scrnmode) { + case 0: + if (lio->work.pos & 1) { + flag |= LIODRAW_UPPER; + } + maxline = 199; + break; + + case 1: + flag |= lio->work.pos % colorbit; + flag |= LIODRAW_MONO; + if (lio->work.pos >= colorbit) { + flag |= LIODRAW_UPPER; + } + maxline = 199; + break; + + case 2: + flag |= lio->work.pos % colorbit; + flag |= LIODRAW_MONO; + break; + } + lio->draw.flag = flag; + lio->draw.palmax = 1 << colorbit; + + tmp = (SINT16)LOADINTELWORD(lio->work.viewx1); + lio->draw.x1 = MAX(tmp, 0); + tmp = (SINT16)LOADINTELWORD(lio->work.viewy1); + lio->draw.y1 = MAX(tmp, 0); + tmp = (SINT16)LOADINTELWORD(lio->work.viewx2); + lio->draw.x2 = MIN(tmp, 639); + tmp = (SINT16)LOADINTELWORD(lio->work.viewy2); + lio->draw.y2 = MIN(tmp, maxline); + if (!gdcs.access) { + lio->draw.base = 0; + lio->draw.bank = 0; + lio->draw.sbit = 0x01; + } + else { + lio->draw.base = VRAM_STEP; + lio->draw.bank = 1; + lio->draw.sbit = 0x02; + } +} + + +// ---- + +static void pixed8(const _GLIO *lio, UINT addr, REG8 bit, REG8 pal) { + + UINT8 *ptr; + + addr = LOW15(addr); + vramupdate[addr] |= lio->draw.sbit; + ptr = mem + lio->draw.base + addr; + if (!(lio->draw.flag & LIODRAW_MONO)) { + if (pal & 1) { + ptr[VRAM_B] |= bit; + } + else { + ptr[VRAM_B] &= ~bit; + } + if (pal & 2) { + ptr[VRAM_R] |= bit; + } + else { + ptr[VRAM_R] &= ~bit; + } + if (pal & 4) { + ptr[VRAM_G] |= bit; + } + else { + ptr[VRAM_G] &= ~bit; + } + if (lio->draw.flag & LIODRAW_4BPP) { + if (pal & 8) { + ptr[VRAM_E] |= bit; + } + else { + ptr[VRAM_E] &= ~bit; + } + } + } + else { + ptr += lioplaneadrs[lio->draw.flag & LIODRAW_PMASK]; + if (pal) { + *ptr |= bit; + } + else { + *ptr &= ~bit; + } + } +} + +void lio_pset(const _GLIO *lio, SINT16 x, SINT16 y, REG8 pal) { + + UINT addr; + UINT8 bit; + + if ((lio->draw.x1 > x) || (lio->draw.x2 < x) || + (lio->draw.y1 > y) || (lio->draw.y2 < y)) { + return; + } + addr = (y * 80) + (x >> 3); + bit = 0x80 >> (x & 7); + if (lio->draw.flag & LIODRAW_UPPER) { + addr += 16000; + } + gdcs.grphdisp |= lio->draw.sbit; + pixed8(lio, addr, bit, pal); +} + +#if 0 +void lio_line(const _GLIO *lio, SINT16 x1, SINT16 x2, SINT16 y, REG8 pal) { + + UINT addr; + UINT8 bit, dbit; + SINT16 width; + + if ((lio->draw.y1 > y) || (lio->draw.y2 < y)) { + return; + } + if (lio->draw.x1 > x1) { + x1 = lio->draw.x1; + } + if (lio->draw.x2 < x2) { + x2 = lio->draw.x2; + } + width = x2 - x1 + 1; + if (width <= 0) { + return; + } + addr = (y * 80) + (x1 >> 3); + bit = 0x80 >> (x1 & 7); + if (lio->draw.flag & LIODRAW_UPPER) { + addr += 16000; + } + gdcs.grphdisp |= lio->draw.sbit; + dbit = 0; + while((bit) && (width)) { + dbit |= bit; + bit >>= 1; + width--; + } + pixed8(lio, addr, dbit, pal); + addr++; + while(width >= 8) { + width -= 8; + pixed8(lio, addr, 0xff, pal); + addr++; + } + dbit = 0; + bit = 0x80; + while((bit) && (width)) { + dbit |= bit; + bit >>= 1; + width--; + } + if (dbit) { + pixed8(lio, addr, dbit, pal); + } +} +#endif + diff --git a/lio/lio.h b/lio/lio.h old mode 100755 new mode 100644 index 381f521d..b39c5760 --- a/lio/lio.h +++ b/lio/lio.h @@ -1,99 +1,99 @@ -/** - * @file lio.h - * @brief Interface of LIO - */ - -#pragma once - -enum { - LIO_SEGMENT = 0xf990, - LIO_FONT = 0x00a0 -}; - -enum { - LIO_SUCCESS = 0, - LIO_ILLEGALFUNC = 5, - LIO_OUTOFMEMORY = 7 -}; - -enum { - LIODRAW_PMASK = 0x03, - LIODRAW_MONO = 0x04, - LIODRAW_UPPER = 0x20, - LIODRAW_4BPP = 0x40 -}; - -typedef struct { - UINT8 scrnmode; - UINT8 pos; - UINT8 plane; - UINT8 fgcolor; - UINT8 bgcolor; - UINT8 padding; - UINT8 color[8]; - UINT8 viewx1[2]; - UINT8 viewy1[2]; - UINT8 viewx2[2]; - UINT8 viewy2[2]; - UINT8 disp; - UINT8 access; -} LIOWORK; - -typedef struct { - SINT16 x1; - SINT16 y1; - SINT16 x2; - SINT16 y2; - UINT32 base; - UINT8 flag; - UINT8 palmax; - UINT8 bank; - UINT8 sbit; -} LIODRAW; - - -typedef struct { - LIOWORK work; - UINT8 palmode; - - // ---- work - UINT32 wait; - LIODRAW draw; -} _GLIO, *GLIO; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern const UINT32 lioplaneadrs[4]; - -void lio_initialize(void); -void bios_lio(REG8 cmd); - -void lio_updatedraw(GLIO lio); -void lio_pset(const _GLIO *lio, SINT16 x, SINT16 y, REG8 pal); -void lio_line(const _GLIO *lio, SINT16 x1, SINT16 x2, SINT16 y, REG8 pal); - -REG8 lio_ginit(GLIO lio); -REG8 lio_gscreen(GLIO lio); -REG8 lio_gview(GLIO lio); -REG8 lio_gcolor1(GLIO lio); -REG8 lio_gcolor2(GLIO lio); -REG8 lio_gcls(GLIO lio); -REG8 lio_gpset(GLIO lio); -REG8 lio_gline(GLIO lio); -REG8 lio_gcircle(GLIO lio); -REG8 lio_gpaint1(GLIO lio); -REG8 lio_gpaint2(GLIO lio); -REG8 lio_gget(GLIO lio); -REG8 lio_gput1(GLIO lio); -REG8 lio_gput2(GLIO lio); -REG8 lio_groll(GLIO lio); -REG8 lio_gpoint2(GLIO lio); -REG8 lio_gcopy(GLIO lio); - -#ifdef __cplusplus -} -#endif - +/** + * @file lio.h + * @brief Interface of LIO + */ + +#pragma once + +enum { + LIO_SEGMENT = 0xf990, + LIO_FONT = 0x00a0 +}; + +enum { + LIO_SUCCESS = 0, + LIO_ILLEGALFUNC = 5, + LIO_OUTOFMEMORY = 7 +}; + +enum { + LIODRAW_PMASK = 0x03, + LIODRAW_MONO = 0x04, + LIODRAW_UPPER = 0x20, + LIODRAW_4BPP = 0x40 +}; + +typedef struct { + UINT8 scrnmode; + UINT8 pos; + UINT8 plane; + UINT8 fgcolor; + UINT8 bgcolor; + UINT8 padding; + UINT8 color[8]; + UINT8 viewx1[2]; + UINT8 viewy1[2]; + UINT8 viewx2[2]; + UINT8 viewy2[2]; + UINT8 disp; + UINT8 access; +} LIOWORK; + +typedef struct { + SINT16 x1; + SINT16 y1; + SINT16 x2; + SINT16 y2; + UINT32 base; + UINT8 flag; + UINT8 palmax; + UINT8 bank; + UINT8 sbit; +} LIODRAW; + + +typedef struct { + LIOWORK work; + UINT8 palmode; + + // ---- work + UINT32 wait; + LIODRAW draw; +} _GLIO, *GLIO; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern const UINT32 lioplaneadrs[4]; + +void lio_initialize(void); +void bios_lio(REG8 cmd); + +void lio_updatedraw(GLIO lio); +void lio_pset(const _GLIO *lio, SINT16 x, SINT16 y, REG8 pal); +void lio_line(const _GLIO *lio, SINT16 x1, SINT16 x2, SINT16 y, REG8 pal); + +REG8 lio_ginit(GLIO lio); +REG8 lio_gscreen(GLIO lio); +REG8 lio_gview(GLIO lio); +REG8 lio_gcolor1(GLIO lio); +REG8 lio_gcolor2(GLIO lio); +REG8 lio_gcls(GLIO lio); +REG8 lio_gpset(GLIO lio); +REG8 lio_gline(GLIO lio); +REG8 lio_gcircle(GLIO lio); +REG8 lio_gpaint1(GLIO lio); +REG8 lio_gpaint2(GLIO lio); +REG8 lio_gget(GLIO lio); +REG8 lio_gput1(GLIO lio); +REG8 lio_gput2(GLIO lio); +REG8 lio_groll(GLIO lio); +REG8 lio_gpoint2(GLIO lio); +REG8 lio_gcopy(GLIO lio); + +#ifdef __cplusplus +} +#endif + diff --git a/mem/dmav30.c b/mem/dmav30.c old mode 100755 new mode 100644 index b06d1110..ea1d7d16 --- a/mem/dmav30.c +++ b/mem/dmav30.c @@ -1,46 +1,46 @@ -#include -#include -#include -#include -#include - - -void dmav30(void) { - - DMACH ch; - REG8 bit; - - if (dmac.working) { - ch = dmac.dmach; - bit = 1; - do { - if (dmac.working & bit) { - // DMA working ! - if (!ch->leng.w) { - dmac.stat |= bit; - dmac.working &= ~bit; - ch->proc.extproc(DMAEXT_END); - } - ch->leng.w--; - - switch(ch->mode & 0x0c) { - case 0x00: // verifty - ch->proc.inproc(); - break; - - case 0x04: // port->mem - MEMP_WRITE8(ch->adrs.d, ch->proc.inproc()); - break; - - default: - ch->proc.outproc(MEMP_READ8(ch->adrs.d)); - break; - } - ch->adrs.w[DMA16_LOW] += ((ch->mode & 0x20)?-1:1); - } - ch++; - bit <<= 1; - } while(bit & 0x0f); - } -} - +#include +#include +#include +#include +#include + + +void dmav30(void) { + + DMACH ch; + REG8 bit; + + if (dmac.working) { + ch = dmac.dmach; + bit = 1; + do { + if (dmac.working & bit) { + // DMA working ! + if (!ch->leng.w) { + dmac.stat |= bit; + dmac.working &= ~bit; + ch->proc.extproc(DMAEXT_END); + } + ch->leng.w--; + + switch(ch->mode & 0x0c) { + case 0x00: // verifty + ch->proc.inproc(); + break; + + case 0x04: // port->mem + MEMP_WRITE8(ch->adrs.d, ch->proc.inproc()); + break; + + default: + ch->proc.outproc(MEMP_READ8(ch->adrs.d)); + break; + } + ch->adrs.w[DMA16_LOW] += ((ch->mode & 0x20)?-1:1); + } + ch++; + bit <<= 1; + } while(bit & 0x0f); + } +} + diff --git a/mem/dmav30.h b/mem/dmav30.h old mode 100755 new mode 100644 index 5b4457c9..b845dbbd --- a/mem/dmav30.h +++ b/mem/dmav30.h @@ -1,11 +1,11 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void dmav30(void); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void dmav30(void); + +#ifdef __cplusplus +} +#endif + diff --git a/mem/dmax86.c b/mem/dmax86.c old mode 100755 new mode 100644 index f8eaf81e..6bec6d5a --- a/mem/dmax86.c +++ b/mem/dmax86.c @@ -1,46 +1,46 @@ -#include -#include -#include -#include -#include - - -void dmax86(void) { - - DMACH ch; - REG8 bit; - - if (dmac.working) { - ch = dmac.dmach; - bit = 1; - do { - if (dmac.working & bit) { - // DMA working ! - if (!ch->leng.w) { - dmac.stat |= bit; - dmac.working &= ~bit; - ch->proc.extproc(DMAEXT_END); - } - ch->leng.w--; - - switch(ch->mode & 0x0c) { - case 0x00: // verifty - ch->proc.inproc(); - break; - - case 0x04: // port->mem - MEMP_WRITE8(ch->adrs.d, ch->proc.inproc()); - break; - - default: - ch->proc.outproc(MEMP_READ8(ch->adrs.d)); - break; - } - ch->adrs.d += ((ch->mode & 0x20)?-1:1); - } - ch++; - bit <<= 1; - } while(bit & 0x0f); - } -} - +#include +#include +#include +#include +#include + + +void dmax86(void) { + + DMACH ch; + REG8 bit; + + if (dmac.working) { + ch = dmac.dmach; + bit = 1; + do { + if (dmac.working & bit) { + // DMA working ! + if (!ch->leng.w) { + dmac.stat |= bit; + dmac.working &= ~bit; + ch->proc.extproc(DMAEXT_END); + } + ch->leng.w--; + + switch(ch->mode & 0x0c) { + case 0x00: // verifty + ch->proc.inproc(); + break; + + case 0x04: // port->mem + MEMP_WRITE8(ch->adrs.d, ch->proc.inproc()); + break; + + default: + ch->proc.outproc(MEMP_READ8(ch->adrs.d)); + break; + } + ch->adrs.d += ((ch->mode & 0x20)?-1:1); + } + ch++; + bit <<= 1; + } while(bit & 0x0f); + } +} + diff --git a/mem/dmax86.h b/mem/dmax86.h old mode 100755 new mode 100644 index 730729d8..60402a13 --- a/mem/dmax86.h +++ b/mem/dmax86.h @@ -1,11 +1,11 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void dmax86(void); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void dmax86(void); + +#ifdef __cplusplus +} +#endif + diff --git a/mem/memegc.c b/mem/memegc.c old mode 100755 new mode 100644 index 882331ac..f918514f --- a/mem/memegc.c +++ b/mem/memegc.c @@ -1,1424 +1,1424 @@ -#include -#include -#include -#include -#include -#include - - -enum { - EGCADDR_L = 0, - EGCADDR_H = 1 -}; -#define EGCADDR(a) (a) - - - -static EGCQUAD egc_src; -static EGCQUAD egc_data; - -static const UINT planead[4] = {VRAM_B, VRAM_R, VRAM_G, VRAM_E}; - - -static const UINT8 bytemask_u0[64] = // dir:right by startbit + (len-1)*8 - {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, - 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, - 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x07, 0x03, 0x01, - 0xf0, 0x78, 0x3c, 0x1e, 0x0f, 0x07, 0x03, 0x01, - 0xf8, 0x7c, 0x3e, 0x1f, 0x0f, 0x07, 0x03, 0x01, - 0xfc, 0x7e, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, - 0xfe, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, - 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; - -static const UINT8 bytemask_u1[8] = // dir:right by length - {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; - -static const UINT8 bytemask_d0[64] = // dir:left by startbit + (len-1)*8 - {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, - 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, - 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xc0, 0x80, - 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0xe0, 0xc0, 0x80, - 0x1f, 0x3e, 0x7c, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, - 0x3f, 0x7e, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, - 0x7f, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, - 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; - -static const UINT8 bytemask_d1[8] = // dir:left by length - {0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; - - -void egcshift(void) { - - UINT8 src8, dst8; - - egc.remain = LOW12(egc.leng) + 1; - egc.func = (egc.sft >> 12) & 1; - if (!egc.func) { - egc.inptr = egc.buf; - egc.outptr = egc.buf; - } - else { - egc.inptr = egc.buf + 4096/8 + 3; - egc.outptr = egc.buf + 4096/8 + 3; - } - egc.srcbit = egc.sft & 0x0f; - egc.dstbit = (egc.sft >> 4) & 0x0f; - - src8 = egc.srcbit & 0x07; - dst8 = egc.dstbit & 0x07; - if (src8 < dst8) { - -// dir:inc -// ****---4 -------8 -------- -// ******-- -4------ --8----- -- -// 1st -> data[0] >> (dst - src) -// 2nd -> (data[0] << (8 - (dst - src))) | (data[1] >> (dst - src)) - -// dir:dec -// -------- 8------- 6-----** -// --- -----8-- -----6-- ---***** -// 1st -> data[0] << (dst - src) -// 2nd -> (data[0] >> (8 - (dst - src))) | (data[1] << (dst - src)) - - egc.func += 2; - egc.sft8bitr = dst8 - src8; - egc.sft8bitl = 8 - egc.sft8bitr; - } - else if (src8 > dst8) { - -// dir:inc -// ****---4 -------8 -------- -// **---4-- -----8-- ------ -// 1st -> (data[0] << (src - dst)) | (data[1] >> (8 - (src - dst)) -// 2nd -> (data[0] << (src - dst)) | (data[1] >> (8 - (src - dst)) - -// dir:dec -// -------- 8------- 3--***** -// ----- ---8---- ---3--** -// 1st -> (data[0] >> (dst - src)) | (data[-1] << (8 - (src - dst)) -// 2nd -> (data[0] >> (dst - src)) | (data[-1] << (8 - (src - dst)) - - egc.func += 4; - egc.sft8bitl = src8 - dst8; - egc.sft8bitr = 8 - egc.sft8bitl; - } - egc.stack = 0; -} - - -static void MEMCALL egcsftb_upn_sub(UINT ext) { - - if (egc.dstbit >= 8) { - egc.dstbit -= 8; - egc.srcmask._b[ext] = 0; - return; - } - if (egc.dstbit) { - if ((egc.dstbit + egc.remain) >= 8) { - egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + (7*8)]; - egc.remain -= (8 - egc.dstbit); - egc.dstbit = 0; - } - else { - egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + - (egc.remain - 1) * 8]; - egc.remain = 0; - egc.dstbit = 0; - } - } - else { - if (egc.remain >= 8) { - egc.remain -= 8; - } - else { - egc.srcmask._b[ext] = bytemask_u1[egc.remain - 1]; - egc.remain = 0; - } - } - egc_src._b[0][ext] = egc.outptr[0]; - egc_src._b[1][ext] = egc.outptr[4]; - egc_src._b[2][ext] = egc.outptr[8]; - egc_src._b[3][ext] = egc.outptr[12]; - egc.outptr++; -} - -static void MEMCALL egcsftb_dnn_sub(UINT ext) { - - if (egc.dstbit >= 8) { - egc.dstbit -= 8; - egc.srcmask._b[ext] = 0; - return; - } - if (egc.dstbit) { - if ((egc.dstbit + egc.remain) >= 8) { - egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + (7*8)]; - egc.remain -= (8 - egc.dstbit); - egc.dstbit = 0; - } - else { - egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + - (egc.remain - 1) * 8]; - egc.remain = 0; - egc.dstbit = 0; - } - } - else { - if (egc.remain >= 8) { - egc.remain -= 8; - } - else { - egc.srcmask._b[ext] = bytemask_d1[egc.remain - 1]; - egc.remain = 0; - } - } - egc_src._b[0][ext] = egc.outptr[0]; - egc_src._b[1][ext] = egc.outptr[4]; - egc_src._b[2][ext] = egc.outptr[8]; - egc_src._b[3][ext] = egc.outptr[12]; - egc.outptr--; -} - - -// ****---4 -------8 -------- -// ******-- -4------ --8----- -- -// 1st -> data[0] >> (dst - src) -// 2nd -> (data[0] << (8 - (dst - src))) | (data[1] >> (dst - src)) - -static void MEMCALL egcsftb_upr_sub(UINT ext) { - - if (egc.dstbit >= 8) { - egc.dstbit -= 8; - egc.srcmask._b[ext] = 0; - return; - } - if (egc.dstbit) { - if ((egc.dstbit + egc.remain) >= 8) { - egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + (7*8)]; - egc.remain -= (8 - egc.dstbit); - } - else { - egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + - (egc.remain - 1) * 8]; - egc.remain = 0; - } - egc.dstbit = 0; - egc_src._b[0][ext] = (egc.outptr[0] >> egc.sft8bitr); - egc_src._b[1][ext] = (egc.outptr[4] >> egc.sft8bitr); - egc_src._b[2][ext] = (egc.outptr[8] >> egc.sft8bitr); - egc_src._b[3][ext] = (egc.outptr[12] >> egc.sft8bitr); - } - else { - if (egc.remain >= 8) { - egc.remain -= 8; - } - else { - egc.srcmask._b[ext] = bytemask_u1[egc.remain - 1]; - egc.remain = 0; - } - egc_src._b[0][ext] = (egc.outptr[0] << egc.sft8bitl) | - (egc.outptr[1] >> egc.sft8bitr); - egc_src._b[1][ext] = (egc.outptr[4] << egc.sft8bitl) | - (egc.outptr[5] >> egc.sft8bitr); - egc_src._b[2][ext] = (egc.outptr[8] << egc.sft8bitl) | - (egc.outptr[9] >> egc.sft8bitr); - egc_src._b[3][ext] = (egc.outptr[12] << egc.sft8bitl) | - (egc.outptr[13] >> egc.sft8bitr); - egc.outptr++; - } -} - - -// -------- 8------- 6-----** -// --- -----8-- -----6-- ---***** -// 1st -> data[0] << (dst - src) -// 2nd -> (data[0] >> (8 - (dst - src))) | (data[-1] << (dst - src)) - -static void MEMCALL egcsftb_dnr_sub(UINT ext) { - - if (egc.dstbit >= 8) { - egc.dstbit -= 8; - egc.srcmask._b[ext] = 0; - return; - } - if (egc.dstbit) { - if ((egc.dstbit + egc.remain) >= 8) { - egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + (7*8)]; - egc.remain -= (8 - egc.dstbit); - } - else { - egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + - (egc.remain - 1) * 8]; - egc.remain = 0; - } - egc.dstbit = 0; - egc_src._b[0][ext] = (egc.outptr[0] << egc.sft8bitr); - egc_src._b[1][ext] = (egc.outptr[4] << egc.sft8bitr); - egc_src._b[2][ext] = (egc.outptr[8] << egc.sft8bitr); - egc_src._b[3][ext] = (egc.outptr[12] << egc.sft8bitr); - } - else { - if (egc.remain >= 8) { - egc.remain -= 8; - } - else { - egc.srcmask._b[ext] = bytemask_d1[egc.remain - 1]; - egc.remain = 0; - } - egc.outptr--; - egc_src._b[0][ext] = (egc.outptr[1] >> egc.sft8bitl) | - (egc.outptr[0] << egc.sft8bitr); - egc_src._b[1][ext] = (egc.outptr[5] >> egc.sft8bitl) | - (egc.outptr[4] << egc.sft8bitr); - egc_src._b[2][ext] = (egc.outptr[9] >> egc.sft8bitl) | - (egc.outptr[8] << egc.sft8bitr); - egc_src._b[3][ext] = (egc.outptr[13] >> egc.sft8bitl) | - (egc.outptr[12] << egc.sft8bitr); - } -} - - -// ****---4 -------8 -------- -// **---4-- -----8-- ------ -// 1st -> (data[0] << (src - dst)) | (data[1] >> (8 - (src - dst)) -// 2nd -> (data[0] << (src - dst)) | (data[1] >> (8 - (src - dst)) - -static void MEMCALL egcsftb_upl_sub(UINT ext) { - - if (egc.dstbit >= 8) { - egc.dstbit -= 8; - egc.srcmask._b[ext] = 0; - return; - } - if (egc.dstbit) { - if ((egc.dstbit + egc.remain) >= 8) { - egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + (7*8)]; - egc.remain -= (8 - egc.dstbit); - egc.dstbit = 0; - } - else { - egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + - (egc.remain - 1) * 8]; - egc.remain = 0; - egc.dstbit = 0; - } - } - else { - if (egc.remain >= 8) { - egc.remain -= 8; - } - else { - egc.srcmask._b[ext] = bytemask_u1[egc.remain - 1]; - egc.remain = 0; - } - } - egc_src._b[0][ext] = (egc.outptr[0] << egc.sft8bitl) | - (egc.outptr[1] >> egc.sft8bitr); - egc_src._b[1][ext] = (egc.outptr[4] << egc.sft8bitl) | - (egc.outptr[5] >> egc.sft8bitr); - egc_src._b[2][ext] = (egc.outptr[8] << egc.sft8bitl) | - (egc.outptr[9] >> egc.sft8bitr); - egc_src._b[3][ext] = (egc.outptr[12] << egc.sft8bitl) | - (egc.outptr[13] >> egc.sft8bitr); - egc.outptr++; -} - - -// -------- 8------- 3--***** -// ----- ---8---- ---3--** -// 1st -> (data[0] >> (dst - src)) | (data[-1] << (8 - (src - dst)) -// 2nd -> (data[0] >> (dst - src)) | (data[-1] << (8 - (src - dst)) - -static void MEMCALL egcsftb_dnl_sub(UINT ext) { - - if (egc.dstbit >= 8) { - egc.dstbit -= 8; - egc.srcmask._b[ext] = 0; - return; - } - if (egc.dstbit) { - if ((egc.dstbit + egc.remain) >= 8) { - egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + (7*8)]; - egc.remain -= (8 - egc.dstbit); - egc.dstbit = 0; - } - else { - egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + - (egc.remain - 1) * 8]; - egc.remain = 0; - egc.dstbit = 0; - } - } - else { - if (egc.remain >= 8) { - egc.remain -= 8; - } - else { - egc.srcmask._b[ext] = bytemask_d1[egc.remain - 1]; - egc.remain = 0; - } - } - egc.outptr--; - egc_src._b[0][ext] = (egc.outptr[1] >> egc.sft8bitl) | - (egc.outptr[0] << egc.sft8bitr); - egc_src._b[1][ext] = (egc.outptr[5] >> egc.sft8bitl) | - (egc.outptr[4] << egc.sft8bitr); - egc_src._b[2][ext] = (egc.outptr[9] >> egc.sft8bitl) | - (egc.outptr[8] << egc.sft8bitr); - egc_src._b[3][ext] = (egc.outptr[13] >> egc.sft8bitl) | - (egc.outptr[12] << egc.sft8bitr); -} - - -static void MEMCALL egcsftb_upn0(UINT ext) { - - if (egc.stack < (UINT)(8 - egc.dstbit)) { - egc.srcmask._b[ext] = 0; - return; - } - egc.stack -= (8 - egc.dstbit); - egcsftb_upn_sub(ext); - if (!egc.remain) { - egcshift(); - } -} - -static void MEMCALL egcsftw_upn0(void) { - - if (egc.stack < (UINT)(16 - egc.dstbit)) { - egc.srcmask.w = 0; - return; - } - egc.stack -= (16 - egc.dstbit); - egcsftb_upn_sub(EGCADDR_L); - if (egc.remain) { - egcsftb_upn_sub(EGCADDR_H); - if (egc.remain) { - return; - } - } - else { - egc.srcmask._b[EGCADDR_H] = 0; - } - egcshift(); -} - -static void MEMCALL egcsftb_dnn0(UINT ext) { - - if (egc.stack < (UINT)(8 - egc.dstbit)) { - egc.srcmask._b[ext] = 0; - return; - } - egc.stack -= (8 - egc.dstbit); - egcsftb_dnn_sub(ext); - if (!egc.remain) { - egcshift(); - } -} - -static void MEMCALL egcsftw_dnn0(void) { - - if (egc.stack < (UINT)(16 - egc.dstbit)) { - egc.srcmask.w = 0; - return; - } - egc.stack -= (16 - egc.dstbit); - egcsftb_dnn_sub(EGCADDR_H); - if (egc.remain) { - egcsftb_dnn_sub(EGCADDR_L); - if (egc.remain) { - return; - } - } - else { - egc.srcmask._b[EGCADDR_L] = 0; - } - egcshift(); -} - - -static void MEMCALL egcsftb_upr0(UINT ext) { // dir:up srcbit < dstbit - - if (egc.stack < (UINT)(8 - egc.dstbit)) { - egc.srcmask._b[ext] = 0; - return; - } - egc.stack -= (8 - egc.dstbit); - egcsftb_upr_sub(ext); - if (!egc.remain) { - egcshift(); - } -} - -static void MEMCALL egcsftw_upr0(void) { // dir:up srcbit < dstbit - - if (egc.stack < (UINT)(16 - egc.dstbit)) { - egc.srcmask.w = 0; - return; - } - egc.stack -= (16 - egc.dstbit); - egcsftb_upr_sub(EGCADDR_L); - if (egc.remain) { - egcsftb_upr_sub(EGCADDR_H); - if (egc.remain) { - return; - } - } - else { - egc.srcmask._b[EGCADDR_H] = 0; - } - egcshift(); -} - -static void MEMCALL egcsftb_dnr0(UINT ext) { // dir:up srcbit < dstbit - - if (egc.stack < (UINT)(8 - egc.dstbit)) { - egc.srcmask._b[ext] = 0; - return; - } - egc.stack -= (8 - egc.dstbit); - egcsftb_dnr_sub(ext); - if (!egc.remain) { - egcshift(); - } -} - -static void MEMCALL egcsftw_dnr0(void) { // dir:up srcbit < dstbit - - if (egc.stack < (UINT)(16 - egc.dstbit)) { - egc.srcmask.w = 0; - return; - } - egc.stack -= (16 - egc.dstbit); - egcsftb_dnr_sub(EGCADDR_H); - if (egc.remain) { - egcsftb_dnr_sub(EGCADDR_L); - if (egc.remain) { - return; - } - } - else { - egc.srcmask._b[EGCADDR_L] = 0; - } - egcshift(); -} - - -static void MEMCALL egcsftb_upl0(UINT ext) { // dir:up srcbit > dstbit - - if (egc.stack < (UINT)(8 - egc.dstbit)) { - egc.srcmask._b[ext] = 0; - return; - } - egc.stack -= (8 - egc.dstbit); - egcsftb_upl_sub(ext); - if (!egc.remain) { - egcshift(); - } -} - -static void MEMCALL egcsftw_upl0(void) { // dir:up srcbit > dstbit - - if (egc.stack < (UINT)(16 - egc.dstbit)) { - egc.srcmask.w = 0; - return; - } - egc.stack -= (16 - egc.dstbit); - egcsftb_upl_sub(EGCADDR_L); - if (egc.remain) { - egcsftb_upl_sub(EGCADDR_H); - if (egc.remain) { - return; - } - } - else { - egc.srcmask._b[EGCADDR_H] = 0; - } - egcshift(); -} - -static void MEMCALL egcsftb_dnl0(UINT ext) { // dir:up srcbit > dstbit - - if (egc.stack < (UINT)(8 - egc.dstbit)) { - egc.srcmask._b[ext] = 0; - return; - } - egc.stack -= (8 - egc.dstbit); - egcsftb_dnl_sub(ext); - if (!egc.remain) { - egcshift(); - } -} - -static void MEMCALL egcsftw_dnl0(void) { // dir:up srcbit > dstbit - - if (egc.stack < (UINT)(16 - egc.dstbit)) { - egc.srcmask.w = 0; - return; - } - egc.stack -= (16 - egc.dstbit); - egcsftb_dnl_sub(EGCADDR_H); - if (egc.remain) { - egcsftb_dnl_sub(EGCADDR_L); - if (egc.remain) { - return; - } - } - else { - egc.srcmask._b[EGCADDR_L] = 0; - } - egcshift(); -} - - -typedef void (MEMCALL * EGCSFTB)(UINT ext); -typedef void (MEMCALL * EGCSFTW)(void); - -static const EGCSFTB egcsftb[6] = { - egcsftb_upn0, egcsftb_dnn0, - egcsftb_upr0, egcsftb_dnr0, - egcsftb_upl0, egcsftb_dnl0}; - -static const EGCSFTW egcsftw[6] = { - egcsftw_upn0, egcsftw_dnn0, - egcsftw_upr0, egcsftw_dnr0, - egcsftw_upl0, egcsftw_dnl0}; - - - -// --------------------------------------------------------------------------- - -static void MEMCALL shiftinput_byte(UINT ext) { - - if (egc.stack <= 16) { - if (egc.srcbit >= 8) { - egc.srcbit -= 8; - } - else { - egc.stack += (8 - egc.srcbit); - egc.srcbit = 0; - } - if (!(egc.sft & 0x1000)) { - egc.inptr++; - } - else { - egc.inptr--; - } - } - egc.srcmask._b[ext] = 0xff; - (*egcsftb[egc.func])(ext); -} - -static void MEMCALL shiftinput_incw(void) { - - if (egc.stack <= 16) { - egc.inptr += 2; - if (egc.srcbit >= 8) { - egc.outptr++; - } - egc.stack += (16 - egc.srcbit); - egc.srcbit = 0; - } - egc.srcmask.w = 0xffff; - (*egcsftw[egc.func])(); -} - -static void MEMCALL shiftinput_decw(void) { - - if (egc.stack <= 16) { - egc.inptr -= 2; - if (egc.srcbit >= 8) { - egc.outptr--; - } - egc.stack += (16 - egc.srcbit); - egc.srcbit = 0; - } - egc.srcmask.w = 0xffff; - (*egcsftw[egc.func])(); -} - -#define EGCOPE_SHIFTB \ - do { \ - if (egc.ope & 0x400) { \ - egc.inptr[ 0] = (UINT8)value; \ - egc.inptr[ 4] = (UINT8)value; \ - egc.inptr[ 8] = (UINT8)value; \ - egc.inptr[12] = (UINT8)value; \ - shiftinput_byte(EGCADDR(ad & 1)); \ - } \ - } while(0) - -#define EGCOPE_SHIFTW \ - do { \ - if (egc.ope & 0x400) { \ - if (!(egc.sft & 0x1000)) { \ - egc.inptr[ 0] = (UINT8)value; \ - egc.inptr[ 1] = (UINT8)(value >> 8); \ - egc.inptr[ 4] = (UINT8)value; \ - egc.inptr[ 5] = (UINT8)(value >> 8); \ - egc.inptr[ 8] = (UINT8)value; \ - egc.inptr[ 9] = (UINT8)(value >> 8); \ - egc.inptr[12] = (UINT8)value; \ - egc.inptr[13] = (UINT8)(value >> 8); \ - shiftinput_incw(); \ - } \ - else { \ - egc.inptr[-1] = (UINT8)value; \ - egc.inptr[ 0] = (UINT8)(value >> 8); \ - egc.inptr[ 3] = (UINT8)value; \ - egc.inptr[ 4] = (UINT8)(value >> 8); \ - egc.inptr[ 7] = (UINT8)value; \ - egc.inptr[ 8] = (UINT8)(value >> 8); \ - egc.inptr[11] = (UINT8)value; \ - egc.inptr[12] = (UINT8)(value >> 8); \ - shiftinput_decw(); \ - } \ - } \ - } while(0) - -#define EGCOPE_SHIFTW2 \ - do { \ - if (!(egc.sft & 0x1000)) { \ - egc.inptr[ 0] = (UINT8)value; \ - egc.inptr[ 1] = (UINT8)(value >> 8); \ - egc.inptr[ 4] = (UINT8)value; \ - egc.inptr[ 5] = (UINT8)(value >> 8); \ - egc.inptr[ 8] = (UINT8)value; \ - egc.inptr[ 9] = (UINT8)(value >> 8); \ - egc.inptr[12] = (UINT8)value; \ - egc.inptr[13] = (UINT8)(value >> 8); \ - shiftinput_incw(); \ - } \ - else { \ - egc.inptr[-1] = (UINT8)value; \ - egc.inptr[ 0] = (UINT8)(value >> 8); \ - egc.inptr[ 3] = (UINT8)value; \ - egc.inptr[ 4] = (UINT8)(value >> 8); \ - egc.inptr[ 7] = (UINT8)value; \ - egc.inptr[ 8] = (UINT8)(value >> 8); \ - egc.inptr[11] = (UINT8)value; \ - egc.inptr[12] = (UINT8)(value >> 8); \ - shiftinput_decw(); \ - } \ - } while(0) - -// ---- - -static const UINT8 data_00[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -static const UINT8 data_ff[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; - -static const EGCQUAD * MEMCALL ope_00(REG8 ope, UINT32 ad) { - - (void)ope; - (void)ad; - return((EGCQUAD *)data_00); -} - -static const EGCQUAD * MEMCALL ope_0f(REG8 ope, UINT32 ad) { - - egc_data.d[0] = ~egc_src.d[0]; - egc_data.d[1] = ~egc_src.d[1]; - - (void)ope; - (void)ad; - return(&egc_data); -} - -static const EGCQUAD * MEMCALL ope_c0(REG8 ope, UINT32 ad) { - - EGCQUAD dst; - - dst.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); - dst.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); - dst.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); - dst.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); - egc_data.d[0] = (egc_src.d[0] & dst.d[0]); - egc_data.d[1] = (egc_src.d[1] & dst.d[1]); - - (void)ope; - (void)ad; - return(&egc_data); -} - -static const EGCQUAD * MEMCALL ope_f0(REG8 ope, UINT32 ad) { - - (void)ope; - (void)ad; - return(&egc_src); -} - -static const EGCQUAD * MEMCALL ope_fc(REG8 ope, UINT32 ad) { - - EGCQUAD dst; - - dst.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); - dst.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); - dst.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); - dst.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); - egc_data.d[0] = egc_src.d[0]; - egc_data.d[0] |= ((~egc_src.d[0]) & dst.d[0]); - egc_data.d[1] = egc_src.d[1]; - egc_data.d[1] |= ((~egc_src.d[1]) & dst.d[1]); - - (void)ope; - (void)ad; - return(&egc_data); -} - -static const EGCQUAD * MEMCALL ope_ff(REG8 ope, UINT32 ad) { - - (void)ope; - (void)ad; - return((EGCQUAD *)data_ff); -} - -static const EGCQUAD * MEMCALL ope_nd(REG8 ope, UINT32 ad) { - - EGCQUAD pat; - - switch(egc.fgbg & 0x6000) { - case 0x2000: - pat.d[0] = egc.bgc.d[0]; - pat.d[1] = egc.bgc.d[1]; - break; - - case 0x4000: - pat.d[0] = egc.fgc.d[0]; - pat.d[1] = egc.fgc.d[1]; - break; - - case 0x6000: - pat.d[0] = egc.fgc.d[0]; - pat.d[1] = egc.bgc.d[1]; - break; - - - default: - if ((egc.ope & 0x0300) == 0x0100) { - pat.d[0] = egc_src.d[0]; - pat.d[1] = egc_src.d[1]; - } - else { - pat.d[0] = egc.patreg.d[0]; - pat.d[1] = egc.patreg.d[1]; - } - break; - } - - egc_data.d[0] = 0; - egc_data.d[1] = 0; - if (ope & 0x80) { - egc_data.d[0] |= (pat.d[0] & egc_src.d[0]); - egc_data.d[1] |= (pat.d[1] & egc_src.d[1]); - } - if (ope & 0x40) { - egc_data.d[0] |= ((~pat.d[0]) & egc_src.d[0]); - egc_data.d[1] |= ((~pat.d[1]) & egc_src.d[1]); - } - if (ope & 0x08) { - egc_data.d[0] |= (pat.d[0] & (~egc_src.d[0])); - egc_data.d[1] |= (pat.d[1] & (~egc_src.d[1])); - } - if (ope & 0x04) { - egc_data.d[0] |= ((~pat.d[0]) & (~egc_src.d[0])); - egc_data.d[1] |= ((~pat.d[1]) & (~egc_src.d[1])); - } - (void)ad; - return(&egc_data); -} - -static const EGCQUAD * MEMCALL ope_np(REG8 ope, UINT32 ad) { - - EGCQUAD dst; - - dst.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); - dst.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); - dst.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); - dst.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); - - egc_data.d[0] = 0; - egc_data.d[1] = 0; - if (ope & 0x80) { - egc_data.d[0] |= (egc_src.d[0] & dst.d[0]); - egc_data.d[1] |= (egc_src.d[1] & dst.d[1]); - } - if (ope & 0x20) { - egc_data.d[0] |= (egc_src.d[0] & (~dst.d[0])); - egc_data.d[1] |= (egc_src.d[1] & (~dst.d[1])); - } - if (ope & 0x08) { - egc_data.d[0] |= ((~egc_src.d[0]) & dst.d[0]); - egc_data.d[1] |= ((~egc_src.d[1]) & dst.d[1]); - } - if (ope & 0x02) { - egc_data.d[0] |= ((~egc_src.d[0]) & (~dst.d[0])); - egc_data.d[1] |= ((~egc_src.d[1]) & (~dst.d[1])); - } - return(&egc_data); -} - -static const EGCQUAD * MEMCALL ope_xx(REG8 ope, UINT32 ad) { - - EGCQUAD pat; - EGCQUAD dst; - - switch(egc.fgbg & 0x6000) { - case 0x2000: - pat.d[0] = egc.bgc.d[0]; - pat.d[1] = egc.bgc.d[1]; - break; - - case 0x4000: - pat.d[0] = egc.fgc.d[0]; - pat.d[1] = egc.fgc.d[1]; - break; - - case 0x6000: - pat.d[0] = egc.fgc.d[0]; - pat.d[1] = egc.bgc.d[1]; - break; - - default: - if ((egc.ope & 0x0300) == 0x0100) { - pat.d[0] = egc_src.d[0]; - pat.d[1] = egc_src.d[1]; - } - else { - pat.d[0] = egc.patreg.d[0]; - pat.d[1] = egc.patreg.d[1]; - } - break; - } - dst.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); - dst.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); - dst.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); - dst.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); - - egc_data.d[0] = 0; - egc_data.d[1] = 0; - if (ope & 0x80) { - egc_data.d[0] |= (pat.d[0] & egc_src.d[0] & dst.d[0]); - egc_data.d[1] |= (pat.d[1] & egc_src.d[1] & dst.d[1]); - } - if (ope & 0x40) { - egc_data.d[0] |= ((~pat.d[0]) & egc_src.d[0] & dst.d[0]); - egc_data.d[1] |= ((~pat.d[1]) & egc_src.d[1] & dst.d[1]); - } - if (ope & 0x20) { - egc_data.d[0] |= (pat.d[0] & egc_src.d[0] & (~dst.d[0])); - egc_data.d[1] |= (pat.d[1] & egc_src.d[1] & (~dst.d[1])); - } - if (ope & 0x10) { - egc_data.d[0] |= ((~pat.d[0]) & egc_src.d[0] & (~dst.d[0])); - egc_data.d[1] |= ((~pat.d[1]) & egc_src.d[1] & (~dst.d[1])); - } - if (ope & 0x08) { - egc_data.d[0] |= (pat.d[0] & (~egc_src.d[0]) & dst.d[0]); - egc_data.d[1] |= (pat.d[1] & (~egc_src.d[1]) & dst.d[1]); - } - if (ope & 0x04) { - egc_data.d[0] |= ((~pat.d[0]) & (~egc_src.d[0]) & dst.d[0]); - egc_data.d[1] |= ((~pat.d[1]) & (~egc_src.d[1]) & dst.d[1]); - } - if (ope & 0x02) { - egc_data.d[0] |= (pat.d[0] & (~egc_src.d[0]) & (~dst.d[0])); - egc_data.d[1] |= (pat.d[1] & (~egc_src.d[1]) & (~dst.d[1])); - } - if (ope & 0x01) { - egc_data.d[0] |= ((~pat.d[0]) & (~egc_src.d[0]) & (~dst.d[0])); - egc_data.d[1] |= ((~pat.d[1]) & (~egc_src.d[1]) & (~dst.d[1])); - } - return(&egc_data); -} - -typedef const EGCQUAD * (MEMCALL * OPEFN)(REG8 ope, UINT32 ad); - -static const OPEFN opefn[256] = { - ope_00, ope_xx, ope_xx, ope_np, - ope_xx, ope_nd, ope_xx, ope_xx, - ope_xx, ope_xx, ope_nd, ope_xx, - ope_np, ope_xx, ope_xx, ope_0f, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_np, ope_xx, ope_xx, ope_np, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_np, ope_xx, ope_xx, ope_np, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_nd, ope_xx, ope_xx, ope_xx, - ope_xx, ope_nd, ope_xx, ope_xx, - ope_xx, ope_xx, ope_nd, ope_xx, - ope_xx, ope_xx, ope_xx, ope_nd, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_nd, ope_xx, ope_xx, ope_xx, - ope_xx, ope_nd, ope_xx, ope_xx, - ope_xx, ope_xx, ope_nd, ope_xx, - ope_xx, ope_xx, ope_xx, ope_nd, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_c0, ope_xx, ope_xx, ope_np, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_np, ope_xx, ope_xx, ope_np, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_xx, ope_xx, ope_xx, ope_xx, - ope_f0, ope_xx, ope_xx, ope_np, - ope_xx, ope_nd, ope_xx, ope_xx, - ope_xx, ope_xx, ope_nd, ope_xx, - ope_fc, ope_xx, ope_xx, ope_ff}; - - -// ---- - -static const EGCQUAD * MEMCALL egc_opeb(UINT32 ad, REG8 value) { - - UINT tmp; - - egc.mask2.w = egc.mask.w; - switch(egc.ope & 0x1800) { - case 0x0800: - EGCOPE_SHIFTB; - egc.mask2.w &= egc.srcmask.w; - tmp = egc.ope & 0xff; - return((*opefn[tmp])((REG8)tmp, ad & (~1))); - - case 0x1000: - switch(egc.fgbg & 0x6000) { - case 0x2000: - return(&egc.bgc); - - case 0x4000: - return(&egc.fgc); - - default: - EGCOPE_SHIFTB; - egc.mask2.w &= egc.srcmask.w; - return(&egc_src); - } - break; - - default: - tmp = value & 0xff; - tmp = tmp | (tmp << 8); - egc_data.w[0] = (UINT16)tmp; - egc_data.w[1] = (UINT16)tmp; - egc_data.w[2] = (UINT16)tmp; - egc_data.w[3] = (UINT16)tmp; - return(&egc_data); - } -} - -static const EGCQUAD * MEMCALL egc_opew(UINT32 ad, REG16 value) { - - UINT tmp; - - egc.mask2.w = egc.mask.w; - switch(egc.ope & 0x1800) { - case 0x0800: - EGCOPE_SHIFTW; - egc.mask2.w &= egc.srcmask.w; - tmp = egc.ope & 0xff; - return((*opefn[tmp])((REG8)tmp, ad)); - - case 0x1000: - EGCOPE_SHIFTW2; - egc.mask2.w &= egc.srcmask.w; - switch(egc.fgbg & 0x6000) { - case 0x2000: - return(&egc.bgc); - case 0x4000: - return(&egc.fgc); - default: - return(&egc.patreg); - } - break; - - default: -#if defined(BYTESEX_BIG) - value = ((value >> 8) & 0xff) | ((value & 0xff) << 8); -#endif - egc_data.w[0] = (UINT16)value; - egc_data.w[1] = (UINT16)value; - egc_data.w[2] = (UINT16)value; - egc_data.w[3] = (UINT16)value; - EGCOPE_SHIFTW2; - egc.mask2.w &= egc.srcmask.w; - return(&egc_data); - } -} - - -// ---- - -REG8 MEMCALL egc_readbyte(UINT32 addr) { - - UINT32 ad; - UINT ext; - - if (gdcs.access) { - addr += VRAM_STEP; - } - ad = VRAMADDRMASKEX(addr); - ext = EGCADDR(addr & 1); - egc.lastvram._b[0][ext] = mem[ad + VRAM_B]; - egc.lastvram._b[1][ext] = mem[ad + VRAM_R]; - egc.lastvram._b[2][ext] = mem[ad + VRAM_G]; - egc.lastvram._b[3][ext] = mem[ad + VRAM_E]; - - // shift input - if (!(egc.ope & 0x400)) { - egc.inptr[0] = egc.lastvram._b[0][ext]; - egc.inptr[4] = egc.lastvram._b[1][ext]; - egc.inptr[8] = egc.lastvram._b[2][ext]; - egc.inptr[12] = egc.lastvram._b[3][ext]; - shiftinput_byte(ext); - } - - if ((egc.ope & 0x0300) == 0x0100) { - egc.patreg._b[0][ext] = mem[ad + VRAM_B]; - egc.patreg._b[1][ext] = mem[ad + VRAM_R]; - egc.patreg._b[2][ext] = mem[ad + VRAM_G]; - egc.patreg._b[3][ext] = mem[ad + VRAM_E]; - } - if (!(egc.ope & 0x2000)) { - int pl = (egc.fgbg >> 8) & 3; - if (!(egc.ope & 0x400)) { - return(egc_src._b[pl][ext]); - } - else { - return(mem[ad + planead[pl]]); - } - } - return(mem[addr]); -} - - -void MEMCALL egc_writebyte(UINT32 addr, REG8 value) { - - UINT ext; -const EGCQUAD *data; - addr = LOW15(addr); - ext = EGCADDR(addr & 1); - if (!gdcs.access) { - gdcs.grphdisp |= 1; - vramupdate[addr] |= 0x01; - } - else { - gdcs.grphdisp |= 2; - vramupdate[addr] |= 0x02; - addr += VRAM_STEP; - } - if ((egc.ope & 0x0300) == 0x0200) { - egc.patreg._b[0][ext] = mem[addr + VRAM_B]; - egc.patreg._b[1][ext] = mem[addr + VRAM_R]; - egc.patreg._b[2][ext] = mem[addr + VRAM_G]; - egc.patreg._b[3][ext] = mem[addr + VRAM_E]; - } - - data = egc_opeb(addr, value); - if (egc.mask2._b[ext]) { - if (!(egc.access & 1)) { - mem[addr + VRAM_B] &= ~egc.mask2._b[ext]; - mem[addr + VRAM_B] |= data->_b[0][ext] & egc.mask2._b[ext]; - } - if (!(egc.access & 2)) { - mem[addr + VRAM_R] &= ~egc.mask2._b[ext]; - mem[addr + VRAM_R] |= data->_b[1][ext] & egc.mask2._b[ext]; - } - if (!(egc.access & 4)) { - mem[addr + VRAM_G] &= ~egc.mask2._b[ext]; - mem[addr + VRAM_G] |= data->_b[2][ext] & egc.mask2._b[ext]; - } - if (!(egc.access & 8)) { - mem[addr + VRAM_E] &= ~egc.mask2._b[ext]; - mem[addr + VRAM_E] |= data->_b[3][ext] & egc.mask2._b[ext]; - } - } -} - -REG16 MEMCALL egc_readword(UINT32 addr) { -/* - UINT32 ad; - int pl; - - __ASSERT(!(addr & 1)); - if (gdcs.access) { - addr += VRAM_STEP; - } - ad = VRAMADDRMASKEX(addr); - egc.lastvram.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); - egc.lastvram.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); - egc.lastvram.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); - egc.lastvram.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); - - // shift input - pl = (egc.fgbg >> 8) & 3; - if (!(egc.ope & 0x400)) { - if (!(egc.sft & 0x1000)) { - if(!(egc.ope & 0x2000)){ - egc.inptr[ 4*pl+0] = egc.lastvram._b[pl][EGCADDR_L]; - egc.inptr[ 4*pl+1] = egc.lastvram._b[pl][EGCADDR_L]; - }else{ - egc.inptr[ 0] = egc.lastvram._b[0][EGCADDR_L]; - egc.inptr[ 1] = egc.lastvram._b[0][EGCADDR_H]; - egc.inptr[ 4] = egc.lastvram._b[1][EGCADDR_L]; - egc.inptr[ 5] = egc.lastvram._b[1][EGCADDR_H]; - egc.inptr[ 8] = egc.lastvram._b[2][EGCADDR_L]; - egc.inptr[ 9] = egc.lastvram._b[2][EGCADDR_H]; - egc.inptr[12] = egc.lastvram._b[3][EGCADDR_L]; - egc.inptr[13] = egc.lastvram._b[3][EGCADDR_H]; - - shiftinput_incw(); - } - }else { - egc.inptr[-1] = egc.lastvram._b[0][EGCADDR_L]; - egc.inptr[ 0] = egc.lastvram._b[0][EGCADDR_H]; - egc.inptr[ 3] = egc.lastvram._b[1][EGCADDR_L]; - egc.inptr[ 4] = egc.lastvram._b[1][EGCADDR_H]; - egc.inptr[ 7] = egc.lastvram._b[2][EGCADDR_L]; - egc.inptr[ 8] = egc.lastvram._b[2][EGCADDR_H]; - egc.inptr[11] = egc.lastvram._b[3][EGCADDR_L]; - egc.inptr[12] = egc.lastvram._b[3][EGCADDR_H]; - shiftinput_decw(); - } - } - - if ((egc.ope & 0x0300) == 0x0100) { - egc.patreg.d[0] = egc.lastvram.d[0]; - egc.patreg.d[1] = egc.lastvram.d[1]; - } - if (!(egc.ope & 0x2000)) { - -// if (!(egc.ope & 0x400)) { -// return(LOADINTELWORD(egc_src._b[pl])); -// } -// else { - UINT temp0,temp1,temp2,temp_1,temp_2; - UINT16 tempx; - UINT32 temp; - if(ad > 3)temp_2 =mem[ad -3 + planead[pl]]; - if(ad > 2)temp_1 =mem[ad -2 + planead[pl]]; - if(ad > 1)temp0 = mem[ad -1 + planead[pl]]; - temp1 = mem[ad -0 + planead[pl]]; - temp2 = mem[ad +1 + planead[pl]]; - if( ((egc.sft & 0xf0)>>4) < (egc.sft & 0xf)){//sftcopy1? - temp = (temp_2 << 24)|(temp_1<<16)|(temp0 <<8)|(temp1); - temp = (temp << (egc.sft & 0x0f) ) >> ((egc.sft & 0xf0)>>4); - temp = temp >> 8; - tempx = (temp & 0xff00)>>8; - tempx |= (temp & 0xff)<<8; - return tempx; - }else{ //sftcopy - temp = (temp0 <<16)|(temp1 <<8)|temp2; - temp = (temp << (egc.sft & 0x0f) ) >> ((egc.sft & 0xf0)>>4); - tempx = (temp & 0xff00)>>8; - tempx |= (temp & 0xff)<<8; - return tempx; - } -// } - } - { - int fg1,fg2,fg4,fg8; - UINT16 temp3; - if(!(egc.access & 1))fg1 = (egc.fg&1)|(egc.fg&1)<<1|(egc.fg&1)<<2|(egc.fg&1)<<3|(egc.fg&1)<<4|(egc.fg&1)<<5|(egc.fg&1)<<6|(egc.fg&1)<<7; - if(!(egc.access & 1))fg2 = (egc.fg&2)|(egc.fg&2)<<1|(egc.fg&2)<<2|(egc.fg&2)<<3|(egc.fg&2)<<4|(egc.fg&2)<<5|(egc.fg&2)<<6|(egc.fg&2)<<7; - if(!(egc.access & 1))fg4 = (egc.fg&4)|(egc.fg&4)<<1|(egc.fg&4)<<2|(egc.fg&4)<<3|(egc.fg&4)<<4|(egc.fg&4)<<5|(egc.fg&4)<<6|(egc.fg&4)<<7; - if(!(egc.access & 1))fg8 = (egc.fg&8)|(egc.fg&8)<<1|(egc.fg&8)<<2|(egc.fg&8)<<3|(egc.fg&8)<<4|(egc.fg&8)<<5|(egc.fg&8)<<6|(egc.fg&8)<<7; - temp3 = *(UINT16 *)(&mem[ad + VRAM_B]) ^ fg1; - temp3 |= *(UINT16 *)(&mem[ad + VRAM_R]) ^ fg2; - temp3 |= *(UINT16 *)(&mem[ad + VRAM_G]) ^ fg4; - temp3 |= *(UINT16 *)(&mem[ad + VRAM_E]) ^ fg8; - return (~temp3); - } -// return(LOADINTELWORD(mem + addr));*/ - - - UINT32 ad; - - __ASSERT(!(addr & 1)); - if (gdcs.access) { - addr += VRAM_STEP; - } - ad = VRAMADDRMASKEX(addr); - egc.lastvram.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); - egc.lastvram.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); - egc.lastvram.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); - egc.lastvram.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); - - // shift input - if (!(egc.ope & 0x400)) { - if (!(egc.sft & 0x1000)) { - egc.inptr[ 0] = egc.lastvram._b[0][EGCADDR_L]; - egc.inptr[ 1] = egc.lastvram._b[0][EGCADDR_H]; - egc.inptr[ 4] = egc.lastvram._b[1][EGCADDR_L]; - egc.inptr[ 5] = egc.lastvram._b[1][EGCADDR_H]; - egc.inptr[ 8] = egc.lastvram._b[2][EGCADDR_L]; - egc.inptr[ 9] = egc.lastvram._b[2][EGCADDR_H]; - egc.inptr[12] = egc.lastvram._b[3][EGCADDR_L]; - egc.inptr[13] = egc.lastvram._b[3][EGCADDR_H]; - shiftinput_incw(); - } - else { - egc.inptr[-1] = egc.lastvram._b[0][EGCADDR_L]; - egc.inptr[ 0] = egc.lastvram._b[0][EGCADDR_H]; - egc.inptr[ 3] = egc.lastvram._b[1][EGCADDR_L]; - egc.inptr[ 4] = egc.lastvram._b[1][EGCADDR_H]; - egc.inptr[ 7] = egc.lastvram._b[2][EGCADDR_L]; - egc.inptr[ 8] = egc.lastvram._b[2][EGCADDR_H]; - egc.inptr[11] = egc.lastvram._b[3][EGCADDR_L]; - egc.inptr[12] = egc.lastvram._b[3][EGCADDR_H]; - shiftinput_decw(); - } - } - - if ((egc.ope & 0x0300) == 0x0100) { - egc.patreg.d[0] = egc.lastvram.d[0]; - egc.patreg.d[1] = egc.lastvram.d[1]; - } - if (!(egc.ope & 0x2000)) { - int pl = (egc.fgbg >> 8) & 3; - if (!(egc.ope & 0x400)) { - return(LOADINTELWORD(egc_src._b[pl])); - } - else { - return(LOADINTELWORD(mem + ad + planead[pl])); - } - } - return(LOADINTELWORD(mem + addr)); - -} - -void MEMCALL egc_writeword(UINT32 addr, REG16 value) { - -const EGCQUAD *data; - - __ASSERT(!(addr & 1)); - addr = LOW15(addr); - if (!gdcs.access) { - gdcs.grphdisp |= 1; - *(UINT16 *)(vramupdate + addr) |= 0x0101; - } - else { - gdcs.grphdisp |= 2; - *(UINT16 *)(vramupdate + addr) |= 0x0202; - addr += VRAM_STEP; - } - if ((egc.ope & 0x0300) == 0x0200) { - egc.patreg.w[0] = *(UINT16 *)(&mem[addr + VRAM_B]); - egc.patreg.w[1] = *(UINT16 *)(&mem[addr + VRAM_R]); - egc.patreg.w[2] = *(UINT16 *)(&mem[addr + VRAM_G]); - egc.patreg.w[3] = *(UINT16 *)(&mem[addr + VRAM_E]); - } - data = egc_opew(addr, value); - if (egc.mask2.w) { - if (!(egc.access & 1)) { - *(UINT16 *)(&mem[addr + VRAM_B]) &= ~egc.mask2.w; - *(UINT16 *)(&mem[addr + VRAM_B]) |= data->w[0] & egc.mask2.w; - } - if (!(egc.access & 2)) { - *(UINT16 *)(&mem[addr + VRAM_R]) &= ~egc.mask2.w; - *(UINT16 *)(&mem[addr + VRAM_R]) |= data->w[1] & egc.mask2.w; - } - if (!(egc.access & 4)) { - *(UINT16 *)(&mem[addr + VRAM_G]) &= ~egc.mask2.w; - *(UINT16 *)(&mem[addr + VRAM_G]) |= data->w[2] & egc.mask2.w; - } - if (!(egc.access & 8)) { - *(UINT16 *)(&mem[addr + VRAM_E]) &= ~egc.mask2.w; - *(UINT16 *)(&mem[addr + VRAM_E]) |= data->w[3] & egc.mask2.w; - } - } -} - - -// ---- - -REG8 MEMCALL memegc_rd8(UINT32 addr) { - - CPU_REMCLOCK -= MEMWAIT_GRCG; - return(egc_readbyte(addr)); -} - -void MEMCALL memegc_wr8(UINT32 addr, REG8 value) { - - CPU_REMCLOCK -= MEMWAIT_GRCG; - egc_writebyte(addr, value); -} - -REG16 MEMCALL memegc_rd16(UINT32 addr) { - - CPU_REMCLOCK -= MEMWAIT_GRCG; - if (!(addr & 1)) { - return(egc_readword(addr)); - } - else if (!(egc.sft & 0x1000)) { - REG16 ret; - ret = egc_readbyte(addr); - ret |= egc_readbyte(addr+1) << 8; - return(ret); - } - else { - REG16 ret; - ret = egc_readbyte(addr+1) << 8; - ret |= egc_readbyte(addr); - return(ret); - } -} - -void MEMCALL memegc_wr16(UINT32 addr, REG16 value) { - - CPU_REMCLOCK -= MEMWAIT_GRCG; - if (!(addr & 1)) { - egc_writeword(addr, value); - } - else if (!(egc.sft & 0x1000)) { - egc_writebyte(addr, (REG8)value); - egc_writebyte(addr+1, (REG8)(value >> 8)); - } - else { - egc_writebyte(addr+1, (REG8)(value >> 8)); - egc_writebyte(addr, (REG8)value); - } -} - -UINT32 MEMCALL memegc_rd32(UINT32 address){ - UINT32 r = (UINT32)memegc_rd16(address); - r |= (UINT32)memegc_rd16(address+2) << 16; - return r; -} - -void MEMCALL memegc_wr32(UINT32 address, UINT32 value){ - memegc_wr16(address, (REG16)value); - memegc_wr16(address+2, (REG16)(value >> 16)); -} +#include +#include +#include +#include +#include +#include + + +enum { + EGCADDR_L = 0, + EGCADDR_H = 1 +}; +#define EGCADDR(a) (a) + + + +static EGCQUAD egc_src; +static EGCQUAD egc_data; + +static const UINT planead[4] = {VRAM_B, VRAM_R, VRAM_G, VRAM_E}; + + +static const UINT8 bytemask_u0[64] = // dir:right by startbit + (len-1)*8 + {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, + 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, + 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x07, 0x03, 0x01, + 0xf0, 0x78, 0x3c, 0x1e, 0x0f, 0x07, 0x03, 0x01, + 0xf8, 0x7c, 0x3e, 0x1f, 0x0f, 0x07, 0x03, 0x01, + 0xfc, 0x7e, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, + 0xfe, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, + 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; + +static const UINT8 bytemask_u1[8] = // dir:right by length + {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; + +static const UINT8 bytemask_d0[64] = // dir:left by startbit + (len-1)*8 + {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, + 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xc0, 0x80, + 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0xe0, 0xc0, 0x80, + 0x1f, 0x3e, 0x7c, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, + 0x3f, 0x7e, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, + 0x7f, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, + 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80}; + +static const UINT8 bytemask_d1[8] = // dir:left by length + {0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; + + +void egcshift(void) { + + UINT8 src8, dst8; + + egc.remain = LOW12(egc.leng) + 1; + egc.func = (egc.sft >> 12) & 1; + if (!egc.func) { + egc.inptr = egc.buf; + egc.outptr = egc.buf; + } + else { + egc.inptr = egc.buf + 4096/8 + 3; + egc.outptr = egc.buf + 4096/8 + 3; + } + egc.srcbit = egc.sft & 0x0f; + egc.dstbit = (egc.sft >> 4) & 0x0f; + + src8 = egc.srcbit & 0x07; + dst8 = egc.dstbit & 0x07; + if (src8 < dst8) { + +// dir:inc +// ****---4 -------8 -------- +// ******-- -4------ --8----- -- +// 1st -> data[0] >> (dst - src) +// 2nd -> (data[0] << (8 - (dst - src))) | (data[1] >> (dst - src)) + +// dir:dec +// -------- 8------- 6-----** +// --- -----8-- -----6-- ---***** +// 1st -> data[0] << (dst - src) +// 2nd -> (data[0] >> (8 - (dst - src))) | (data[1] << (dst - src)) + + egc.func += 2; + egc.sft8bitr = dst8 - src8; + egc.sft8bitl = 8 - egc.sft8bitr; + } + else if (src8 > dst8) { + +// dir:inc +// ****---4 -------8 -------- +// **---4-- -----8-- ------ +// 1st -> (data[0] << (src - dst)) | (data[1] >> (8 - (src - dst)) +// 2nd -> (data[0] << (src - dst)) | (data[1] >> (8 - (src - dst)) + +// dir:dec +// -------- 8------- 3--***** +// ----- ---8---- ---3--** +// 1st -> (data[0] >> (dst - src)) | (data[-1] << (8 - (src - dst)) +// 2nd -> (data[0] >> (dst - src)) | (data[-1] << (8 - (src - dst)) + + egc.func += 4; + egc.sft8bitl = src8 - dst8; + egc.sft8bitr = 8 - egc.sft8bitl; + } + egc.stack = 0; +} + + +static void MEMCALL egcsftb_upn_sub(UINT ext) { + + if (egc.dstbit >= 8) { + egc.dstbit -= 8; + egc.srcmask._b[ext] = 0; + return; + } + if (egc.dstbit) { + if ((egc.dstbit + egc.remain) >= 8) { + egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + (7*8)]; + egc.remain -= (8 - egc.dstbit); + egc.dstbit = 0; + } + else { + egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + + (egc.remain - 1) * 8]; + egc.remain = 0; + egc.dstbit = 0; + } + } + else { + if (egc.remain >= 8) { + egc.remain -= 8; + } + else { + egc.srcmask._b[ext] = bytemask_u1[egc.remain - 1]; + egc.remain = 0; + } + } + egc_src._b[0][ext] = egc.outptr[0]; + egc_src._b[1][ext] = egc.outptr[4]; + egc_src._b[2][ext] = egc.outptr[8]; + egc_src._b[3][ext] = egc.outptr[12]; + egc.outptr++; +} + +static void MEMCALL egcsftb_dnn_sub(UINT ext) { + + if (egc.dstbit >= 8) { + egc.dstbit -= 8; + egc.srcmask._b[ext] = 0; + return; + } + if (egc.dstbit) { + if ((egc.dstbit + egc.remain) >= 8) { + egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + (7*8)]; + egc.remain -= (8 - egc.dstbit); + egc.dstbit = 0; + } + else { + egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + + (egc.remain - 1) * 8]; + egc.remain = 0; + egc.dstbit = 0; + } + } + else { + if (egc.remain >= 8) { + egc.remain -= 8; + } + else { + egc.srcmask._b[ext] = bytemask_d1[egc.remain - 1]; + egc.remain = 0; + } + } + egc_src._b[0][ext] = egc.outptr[0]; + egc_src._b[1][ext] = egc.outptr[4]; + egc_src._b[2][ext] = egc.outptr[8]; + egc_src._b[3][ext] = egc.outptr[12]; + egc.outptr--; +} + + +// ****---4 -------8 -------- +// ******-- -4------ --8----- -- +// 1st -> data[0] >> (dst - src) +// 2nd -> (data[0] << (8 - (dst - src))) | (data[1] >> (dst - src)) + +static void MEMCALL egcsftb_upr_sub(UINT ext) { + + if (egc.dstbit >= 8) { + egc.dstbit -= 8; + egc.srcmask._b[ext] = 0; + return; + } + if (egc.dstbit) { + if ((egc.dstbit + egc.remain) >= 8) { + egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + (7*8)]; + egc.remain -= (8 - egc.dstbit); + } + else { + egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + + (egc.remain - 1) * 8]; + egc.remain = 0; + } + egc.dstbit = 0; + egc_src._b[0][ext] = (egc.outptr[0] >> egc.sft8bitr); + egc_src._b[1][ext] = (egc.outptr[4] >> egc.sft8bitr); + egc_src._b[2][ext] = (egc.outptr[8] >> egc.sft8bitr); + egc_src._b[3][ext] = (egc.outptr[12] >> egc.sft8bitr); + } + else { + if (egc.remain >= 8) { + egc.remain -= 8; + } + else { + egc.srcmask._b[ext] = bytemask_u1[egc.remain - 1]; + egc.remain = 0; + } + egc_src._b[0][ext] = (egc.outptr[0] << egc.sft8bitl) | + (egc.outptr[1] >> egc.sft8bitr); + egc_src._b[1][ext] = (egc.outptr[4] << egc.sft8bitl) | + (egc.outptr[5] >> egc.sft8bitr); + egc_src._b[2][ext] = (egc.outptr[8] << egc.sft8bitl) | + (egc.outptr[9] >> egc.sft8bitr); + egc_src._b[3][ext] = (egc.outptr[12] << egc.sft8bitl) | + (egc.outptr[13] >> egc.sft8bitr); + egc.outptr++; + } +} + + +// -------- 8------- 6-----** +// --- -----8-- -----6-- ---***** +// 1st -> data[0] << (dst - src) +// 2nd -> (data[0] >> (8 - (dst - src))) | (data[-1] << (dst - src)) + +static void MEMCALL egcsftb_dnr_sub(UINT ext) { + + if (egc.dstbit >= 8) { + egc.dstbit -= 8; + egc.srcmask._b[ext] = 0; + return; + } + if (egc.dstbit) { + if ((egc.dstbit + egc.remain) >= 8) { + egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + (7*8)]; + egc.remain -= (8 - egc.dstbit); + } + else { + egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + + (egc.remain - 1) * 8]; + egc.remain = 0; + } + egc.dstbit = 0; + egc_src._b[0][ext] = (egc.outptr[0] << egc.sft8bitr); + egc_src._b[1][ext] = (egc.outptr[4] << egc.sft8bitr); + egc_src._b[2][ext] = (egc.outptr[8] << egc.sft8bitr); + egc_src._b[3][ext] = (egc.outptr[12] << egc.sft8bitr); + } + else { + if (egc.remain >= 8) { + egc.remain -= 8; + } + else { + egc.srcmask._b[ext] = bytemask_d1[egc.remain - 1]; + egc.remain = 0; + } + egc.outptr--; + egc_src._b[0][ext] = (egc.outptr[1] >> egc.sft8bitl) | + (egc.outptr[0] << egc.sft8bitr); + egc_src._b[1][ext] = (egc.outptr[5] >> egc.sft8bitl) | + (egc.outptr[4] << egc.sft8bitr); + egc_src._b[2][ext] = (egc.outptr[9] >> egc.sft8bitl) | + (egc.outptr[8] << egc.sft8bitr); + egc_src._b[3][ext] = (egc.outptr[13] >> egc.sft8bitl) | + (egc.outptr[12] << egc.sft8bitr); + } +} + + +// ****---4 -------8 -------- +// **---4-- -----8-- ------ +// 1st -> (data[0] << (src - dst)) | (data[1] >> (8 - (src - dst)) +// 2nd -> (data[0] << (src - dst)) | (data[1] >> (8 - (src - dst)) + +static void MEMCALL egcsftb_upl_sub(UINT ext) { + + if (egc.dstbit >= 8) { + egc.dstbit -= 8; + egc.srcmask._b[ext] = 0; + return; + } + if (egc.dstbit) { + if ((egc.dstbit + egc.remain) >= 8) { + egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + (7*8)]; + egc.remain -= (8 - egc.dstbit); + egc.dstbit = 0; + } + else { + egc.srcmask._b[ext] = bytemask_u0[egc.dstbit + + (egc.remain - 1) * 8]; + egc.remain = 0; + egc.dstbit = 0; + } + } + else { + if (egc.remain >= 8) { + egc.remain -= 8; + } + else { + egc.srcmask._b[ext] = bytemask_u1[egc.remain - 1]; + egc.remain = 0; + } + } + egc_src._b[0][ext] = (egc.outptr[0] << egc.sft8bitl) | + (egc.outptr[1] >> egc.sft8bitr); + egc_src._b[1][ext] = (egc.outptr[4] << egc.sft8bitl) | + (egc.outptr[5] >> egc.sft8bitr); + egc_src._b[2][ext] = (egc.outptr[8] << egc.sft8bitl) | + (egc.outptr[9] >> egc.sft8bitr); + egc_src._b[3][ext] = (egc.outptr[12] << egc.sft8bitl) | + (egc.outptr[13] >> egc.sft8bitr); + egc.outptr++; +} + + +// -------- 8------- 3--***** +// ----- ---8---- ---3--** +// 1st -> (data[0] >> (dst - src)) | (data[-1] << (8 - (src - dst)) +// 2nd -> (data[0] >> (dst - src)) | (data[-1] << (8 - (src - dst)) + +static void MEMCALL egcsftb_dnl_sub(UINT ext) { + + if (egc.dstbit >= 8) { + egc.dstbit -= 8; + egc.srcmask._b[ext] = 0; + return; + } + if (egc.dstbit) { + if ((egc.dstbit + egc.remain) >= 8) { + egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + (7*8)]; + egc.remain -= (8 - egc.dstbit); + egc.dstbit = 0; + } + else { + egc.srcmask._b[ext] = bytemask_d0[egc.dstbit + + (egc.remain - 1) * 8]; + egc.remain = 0; + egc.dstbit = 0; + } + } + else { + if (egc.remain >= 8) { + egc.remain -= 8; + } + else { + egc.srcmask._b[ext] = bytemask_d1[egc.remain - 1]; + egc.remain = 0; + } + } + egc.outptr--; + egc_src._b[0][ext] = (egc.outptr[1] >> egc.sft8bitl) | + (egc.outptr[0] << egc.sft8bitr); + egc_src._b[1][ext] = (egc.outptr[5] >> egc.sft8bitl) | + (egc.outptr[4] << egc.sft8bitr); + egc_src._b[2][ext] = (egc.outptr[9] >> egc.sft8bitl) | + (egc.outptr[8] << egc.sft8bitr); + egc_src._b[3][ext] = (egc.outptr[13] >> egc.sft8bitl) | + (egc.outptr[12] << egc.sft8bitr); +} + + +static void MEMCALL egcsftb_upn0(UINT ext) { + + if (egc.stack < (UINT)(8 - egc.dstbit)) { + egc.srcmask._b[ext] = 0; + return; + } + egc.stack -= (8 - egc.dstbit); + egcsftb_upn_sub(ext); + if (!egc.remain) { + egcshift(); + } +} + +static void MEMCALL egcsftw_upn0(void) { + + if (egc.stack < (UINT)(16 - egc.dstbit)) { + egc.srcmask.w = 0; + return; + } + egc.stack -= (16 - egc.dstbit); + egcsftb_upn_sub(EGCADDR_L); + if (egc.remain) { + egcsftb_upn_sub(EGCADDR_H); + if (egc.remain) { + return; + } + } + else { + egc.srcmask._b[EGCADDR_H] = 0; + } + egcshift(); +} + +static void MEMCALL egcsftb_dnn0(UINT ext) { + + if (egc.stack < (UINT)(8 - egc.dstbit)) { + egc.srcmask._b[ext] = 0; + return; + } + egc.stack -= (8 - egc.dstbit); + egcsftb_dnn_sub(ext); + if (!egc.remain) { + egcshift(); + } +} + +static void MEMCALL egcsftw_dnn0(void) { + + if (egc.stack < (UINT)(16 - egc.dstbit)) { + egc.srcmask.w = 0; + return; + } + egc.stack -= (16 - egc.dstbit); + egcsftb_dnn_sub(EGCADDR_H); + if (egc.remain) { + egcsftb_dnn_sub(EGCADDR_L); + if (egc.remain) { + return; + } + } + else { + egc.srcmask._b[EGCADDR_L] = 0; + } + egcshift(); +} + + +static void MEMCALL egcsftb_upr0(UINT ext) { // dir:up srcbit < dstbit + + if (egc.stack < (UINT)(8 - egc.dstbit)) { + egc.srcmask._b[ext] = 0; + return; + } + egc.stack -= (8 - egc.dstbit); + egcsftb_upr_sub(ext); + if (!egc.remain) { + egcshift(); + } +} + +static void MEMCALL egcsftw_upr0(void) { // dir:up srcbit < dstbit + + if (egc.stack < (UINT)(16 - egc.dstbit)) { + egc.srcmask.w = 0; + return; + } + egc.stack -= (16 - egc.dstbit); + egcsftb_upr_sub(EGCADDR_L); + if (egc.remain) { + egcsftb_upr_sub(EGCADDR_H); + if (egc.remain) { + return; + } + } + else { + egc.srcmask._b[EGCADDR_H] = 0; + } + egcshift(); +} + +static void MEMCALL egcsftb_dnr0(UINT ext) { // dir:up srcbit < dstbit + + if (egc.stack < (UINT)(8 - egc.dstbit)) { + egc.srcmask._b[ext] = 0; + return; + } + egc.stack -= (8 - egc.dstbit); + egcsftb_dnr_sub(ext); + if (!egc.remain) { + egcshift(); + } +} + +static void MEMCALL egcsftw_dnr0(void) { // dir:up srcbit < dstbit + + if (egc.stack < (UINT)(16 - egc.dstbit)) { + egc.srcmask.w = 0; + return; + } + egc.stack -= (16 - egc.dstbit); + egcsftb_dnr_sub(EGCADDR_H); + if (egc.remain) { + egcsftb_dnr_sub(EGCADDR_L); + if (egc.remain) { + return; + } + } + else { + egc.srcmask._b[EGCADDR_L] = 0; + } + egcshift(); +} + + +static void MEMCALL egcsftb_upl0(UINT ext) { // dir:up srcbit > dstbit + + if (egc.stack < (UINT)(8 - egc.dstbit)) { + egc.srcmask._b[ext] = 0; + return; + } + egc.stack -= (8 - egc.dstbit); + egcsftb_upl_sub(ext); + if (!egc.remain) { + egcshift(); + } +} + +static void MEMCALL egcsftw_upl0(void) { // dir:up srcbit > dstbit + + if (egc.stack < (UINT)(16 - egc.dstbit)) { + egc.srcmask.w = 0; + return; + } + egc.stack -= (16 - egc.dstbit); + egcsftb_upl_sub(EGCADDR_L); + if (egc.remain) { + egcsftb_upl_sub(EGCADDR_H); + if (egc.remain) { + return; + } + } + else { + egc.srcmask._b[EGCADDR_H] = 0; + } + egcshift(); +} + +static void MEMCALL egcsftb_dnl0(UINT ext) { // dir:up srcbit > dstbit + + if (egc.stack < (UINT)(8 - egc.dstbit)) { + egc.srcmask._b[ext] = 0; + return; + } + egc.stack -= (8 - egc.dstbit); + egcsftb_dnl_sub(ext); + if (!egc.remain) { + egcshift(); + } +} + +static void MEMCALL egcsftw_dnl0(void) { // dir:up srcbit > dstbit + + if (egc.stack < (UINT)(16 - egc.dstbit)) { + egc.srcmask.w = 0; + return; + } + egc.stack -= (16 - egc.dstbit); + egcsftb_dnl_sub(EGCADDR_H); + if (egc.remain) { + egcsftb_dnl_sub(EGCADDR_L); + if (egc.remain) { + return; + } + } + else { + egc.srcmask._b[EGCADDR_L] = 0; + } + egcshift(); +} + + +typedef void (MEMCALL * EGCSFTB)(UINT ext); +typedef void (MEMCALL * EGCSFTW)(void); + +static const EGCSFTB egcsftb[6] = { + egcsftb_upn0, egcsftb_dnn0, + egcsftb_upr0, egcsftb_dnr0, + egcsftb_upl0, egcsftb_dnl0}; + +static const EGCSFTW egcsftw[6] = { + egcsftw_upn0, egcsftw_dnn0, + egcsftw_upr0, egcsftw_dnr0, + egcsftw_upl0, egcsftw_dnl0}; + + + +// --------------------------------------------------------------------------- + +static void MEMCALL shiftinput_byte(UINT ext) { + + if (egc.stack <= 16) { + if (egc.srcbit >= 8) { + egc.srcbit -= 8; + } + else { + egc.stack += (8 - egc.srcbit); + egc.srcbit = 0; + } + if (!(egc.sft & 0x1000)) { + egc.inptr++; + } + else { + egc.inptr--; + } + } + egc.srcmask._b[ext] = 0xff; + (*egcsftb[egc.func])(ext); +} + +static void MEMCALL shiftinput_incw(void) { + + if (egc.stack <= 16) { + egc.inptr += 2; + if (egc.srcbit >= 8) { + egc.outptr++; + } + egc.stack += (16 - egc.srcbit); + egc.srcbit = 0; + } + egc.srcmask.w = 0xffff; + (*egcsftw[egc.func])(); +} + +static void MEMCALL shiftinput_decw(void) { + + if (egc.stack <= 16) { + egc.inptr -= 2; + if (egc.srcbit >= 8) { + egc.outptr--; + } + egc.stack += (16 - egc.srcbit); + egc.srcbit = 0; + } + egc.srcmask.w = 0xffff; + (*egcsftw[egc.func])(); +} + +#define EGCOPE_SHIFTB \ + do { \ + if (egc.ope & 0x400) { \ + egc.inptr[ 0] = (UINT8)value; \ + egc.inptr[ 4] = (UINT8)value; \ + egc.inptr[ 8] = (UINT8)value; \ + egc.inptr[12] = (UINT8)value; \ + shiftinput_byte(EGCADDR(ad & 1)); \ + } \ + } while(0) + +#define EGCOPE_SHIFTW \ + do { \ + if (egc.ope & 0x400) { \ + if (!(egc.sft & 0x1000)) { \ + egc.inptr[ 0] = (UINT8)value; \ + egc.inptr[ 1] = (UINT8)(value >> 8); \ + egc.inptr[ 4] = (UINT8)value; \ + egc.inptr[ 5] = (UINT8)(value >> 8); \ + egc.inptr[ 8] = (UINT8)value; \ + egc.inptr[ 9] = (UINT8)(value >> 8); \ + egc.inptr[12] = (UINT8)value; \ + egc.inptr[13] = (UINT8)(value >> 8); \ + shiftinput_incw(); \ + } \ + else { \ + egc.inptr[-1] = (UINT8)value; \ + egc.inptr[ 0] = (UINT8)(value >> 8); \ + egc.inptr[ 3] = (UINT8)value; \ + egc.inptr[ 4] = (UINT8)(value >> 8); \ + egc.inptr[ 7] = (UINT8)value; \ + egc.inptr[ 8] = (UINT8)(value >> 8); \ + egc.inptr[11] = (UINT8)value; \ + egc.inptr[12] = (UINT8)(value >> 8); \ + shiftinput_decw(); \ + } \ + } \ + } while(0) + +#define EGCOPE_SHIFTW2 \ + do { \ + if (!(egc.sft & 0x1000)) { \ + egc.inptr[ 0] = (UINT8)value; \ + egc.inptr[ 1] = (UINT8)(value >> 8); \ + egc.inptr[ 4] = (UINT8)value; \ + egc.inptr[ 5] = (UINT8)(value >> 8); \ + egc.inptr[ 8] = (UINT8)value; \ + egc.inptr[ 9] = (UINT8)(value >> 8); \ + egc.inptr[12] = (UINT8)value; \ + egc.inptr[13] = (UINT8)(value >> 8); \ + shiftinput_incw(); \ + } \ + else { \ + egc.inptr[-1] = (UINT8)value; \ + egc.inptr[ 0] = (UINT8)(value >> 8); \ + egc.inptr[ 3] = (UINT8)value; \ + egc.inptr[ 4] = (UINT8)(value >> 8); \ + egc.inptr[ 7] = (UINT8)value; \ + egc.inptr[ 8] = (UINT8)(value >> 8); \ + egc.inptr[11] = (UINT8)value; \ + egc.inptr[12] = (UINT8)(value >> 8); \ + shiftinput_decw(); \ + } \ + } while(0) + +// ---- + +static const UINT8 data_00[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; +static const UINT8 data_ff[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; + +static const EGCQUAD * MEMCALL ope_00(REG8 ope, UINT32 ad) { + + (void)ope; + (void)ad; + return((EGCQUAD *)data_00); +} + +static const EGCQUAD * MEMCALL ope_0f(REG8 ope, UINT32 ad) { + + egc_data.d[0] = ~egc_src.d[0]; + egc_data.d[1] = ~egc_src.d[1]; + + (void)ope; + (void)ad; + return(&egc_data); +} + +static const EGCQUAD * MEMCALL ope_c0(REG8 ope, UINT32 ad) { + + EGCQUAD dst; + + dst.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); + dst.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); + dst.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); + dst.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); + egc_data.d[0] = (egc_src.d[0] & dst.d[0]); + egc_data.d[1] = (egc_src.d[1] & dst.d[1]); + + (void)ope; + (void)ad; + return(&egc_data); +} + +static const EGCQUAD * MEMCALL ope_f0(REG8 ope, UINT32 ad) { + + (void)ope; + (void)ad; + return(&egc_src); +} + +static const EGCQUAD * MEMCALL ope_fc(REG8 ope, UINT32 ad) { + + EGCQUAD dst; + + dst.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); + dst.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); + dst.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); + dst.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); + egc_data.d[0] = egc_src.d[0]; + egc_data.d[0] |= ((~egc_src.d[0]) & dst.d[0]); + egc_data.d[1] = egc_src.d[1]; + egc_data.d[1] |= ((~egc_src.d[1]) & dst.d[1]); + + (void)ope; + (void)ad; + return(&egc_data); +} + +static const EGCQUAD * MEMCALL ope_ff(REG8 ope, UINT32 ad) { + + (void)ope; + (void)ad; + return((EGCQUAD *)data_ff); +} + +static const EGCQUAD * MEMCALL ope_nd(REG8 ope, UINT32 ad) { + + EGCQUAD pat; + + switch(egc.fgbg & 0x6000) { + case 0x2000: + pat.d[0] = egc.bgc.d[0]; + pat.d[1] = egc.bgc.d[1]; + break; + + case 0x4000: + pat.d[0] = egc.fgc.d[0]; + pat.d[1] = egc.fgc.d[1]; + break; + + case 0x6000: + pat.d[0] = egc.fgc.d[0]; + pat.d[1] = egc.bgc.d[1]; + break; + + + default: + if ((egc.ope & 0x0300) == 0x0100) { + pat.d[0] = egc_src.d[0]; + pat.d[1] = egc_src.d[1]; + } + else { + pat.d[0] = egc.patreg.d[0]; + pat.d[1] = egc.patreg.d[1]; + } + break; + } + + egc_data.d[0] = 0; + egc_data.d[1] = 0; + if (ope & 0x80) { + egc_data.d[0] |= (pat.d[0] & egc_src.d[0]); + egc_data.d[1] |= (pat.d[1] & egc_src.d[1]); + } + if (ope & 0x40) { + egc_data.d[0] |= ((~pat.d[0]) & egc_src.d[0]); + egc_data.d[1] |= ((~pat.d[1]) & egc_src.d[1]); + } + if (ope & 0x08) { + egc_data.d[0] |= (pat.d[0] & (~egc_src.d[0])); + egc_data.d[1] |= (pat.d[1] & (~egc_src.d[1])); + } + if (ope & 0x04) { + egc_data.d[0] |= ((~pat.d[0]) & (~egc_src.d[0])); + egc_data.d[1] |= ((~pat.d[1]) & (~egc_src.d[1])); + } + (void)ad; + return(&egc_data); +} + +static const EGCQUAD * MEMCALL ope_np(REG8 ope, UINT32 ad) { + + EGCQUAD dst; + + dst.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); + dst.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); + dst.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); + dst.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); + + egc_data.d[0] = 0; + egc_data.d[1] = 0; + if (ope & 0x80) { + egc_data.d[0] |= (egc_src.d[0] & dst.d[0]); + egc_data.d[1] |= (egc_src.d[1] & dst.d[1]); + } + if (ope & 0x20) { + egc_data.d[0] |= (egc_src.d[0] & (~dst.d[0])); + egc_data.d[1] |= (egc_src.d[1] & (~dst.d[1])); + } + if (ope & 0x08) { + egc_data.d[0] |= ((~egc_src.d[0]) & dst.d[0]); + egc_data.d[1] |= ((~egc_src.d[1]) & dst.d[1]); + } + if (ope & 0x02) { + egc_data.d[0] |= ((~egc_src.d[0]) & (~dst.d[0])); + egc_data.d[1] |= ((~egc_src.d[1]) & (~dst.d[1])); + } + return(&egc_data); +} + +static const EGCQUAD * MEMCALL ope_xx(REG8 ope, UINT32 ad) { + + EGCQUAD pat; + EGCQUAD dst; + + switch(egc.fgbg & 0x6000) { + case 0x2000: + pat.d[0] = egc.bgc.d[0]; + pat.d[1] = egc.bgc.d[1]; + break; + + case 0x4000: + pat.d[0] = egc.fgc.d[0]; + pat.d[1] = egc.fgc.d[1]; + break; + + case 0x6000: + pat.d[0] = egc.fgc.d[0]; + pat.d[1] = egc.bgc.d[1]; + break; + + default: + if ((egc.ope & 0x0300) == 0x0100) { + pat.d[0] = egc_src.d[0]; + pat.d[1] = egc_src.d[1]; + } + else { + pat.d[0] = egc.patreg.d[0]; + pat.d[1] = egc.patreg.d[1]; + } + break; + } + dst.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); + dst.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); + dst.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); + dst.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); + + egc_data.d[0] = 0; + egc_data.d[1] = 0; + if (ope & 0x80) { + egc_data.d[0] |= (pat.d[0] & egc_src.d[0] & dst.d[0]); + egc_data.d[1] |= (pat.d[1] & egc_src.d[1] & dst.d[1]); + } + if (ope & 0x40) { + egc_data.d[0] |= ((~pat.d[0]) & egc_src.d[0] & dst.d[0]); + egc_data.d[1] |= ((~pat.d[1]) & egc_src.d[1] & dst.d[1]); + } + if (ope & 0x20) { + egc_data.d[0] |= (pat.d[0] & egc_src.d[0] & (~dst.d[0])); + egc_data.d[1] |= (pat.d[1] & egc_src.d[1] & (~dst.d[1])); + } + if (ope & 0x10) { + egc_data.d[0] |= ((~pat.d[0]) & egc_src.d[0] & (~dst.d[0])); + egc_data.d[1] |= ((~pat.d[1]) & egc_src.d[1] & (~dst.d[1])); + } + if (ope & 0x08) { + egc_data.d[0] |= (pat.d[0] & (~egc_src.d[0]) & dst.d[0]); + egc_data.d[1] |= (pat.d[1] & (~egc_src.d[1]) & dst.d[1]); + } + if (ope & 0x04) { + egc_data.d[0] |= ((~pat.d[0]) & (~egc_src.d[0]) & dst.d[0]); + egc_data.d[1] |= ((~pat.d[1]) & (~egc_src.d[1]) & dst.d[1]); + } + if (ope & 0x02) { + egc_data.d[0] |= (pat.d[0] & (~egc_src.d[0]) & (~dst.d[0])); + egc_data.d[1] |= (pat.d[1] & (~egc_src.d[1]) & (~dst.d[1])); + } + if (ope & 0x01) { + egc_data.d[0] |= ((~pat.d[0]) & (~egc_src.d[0]) & (~dst.d[0])); + egc_data.d[1] |= ((~pat.d[1]) & (~egc_src.d[1]) & (~dst.d[1])); + } + return(&egc_data); +} + +typedef const EGCQUAD * (MEMCALL * OPEFN)(REG8 ope, UINT32 ad); + +static const OPEFN opefn[256] = { + ope_00, ope_xx, ope_xx, ope_np, + ope_xx, ope_nd, ope_xx, ope_xx, + ope_xx, ope_xx, ope_nd, ope_xx, + ope_np, ope_xx, ope_xx, ope_0f, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_np, ope_xx, ope_xx, ope_np, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_np, ope_xx, ope_xx, ope_np, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_nd, ope_xx, ope_xx, ope_xx, + ope_xx, ope_nd, ope_xx, ope_xx, + ope_xx, ope_xx, ope_nd, ope_xx, + ope_xx, ope_xx, ope_xx, ope_nd, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_nd, ope_xx, ope_xx, ope_xx, + ope_xx, ope_nd, ope_xx, ope_xx, + ope_xx, ope_xx, ope_nd, ope_xx, + ope_xx, ope_xx, ope_xx, ope_nd, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_c0, ope_xx, ope_xx, ope_np, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_np, ope_xx, ope_xx, ope_np, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_xx, ope_xx, ope_xx, ope_xx, + ope_f0, ope_xx, ope_xx, ope_np, + ope_xx, ope_nd, ope_xx, ope_xx, + ope_xx, ope_xx, ope_nd, ope_xx, + ope_fc, ope_xx, ope_xx, ope_ff}; + + +// ---- + +static const EGCQUAD * MEMCALL egc_opeb(UINT32 ad, REG8 value) { + + UINT tmp; + + egc.mask2.w = egc.mask.w; + switch(egc.ope & 0x1800) { + case 0x0800: + EGCOPE_SHIFTB; + egc.mask2.w &= egc.srcmask.w; + tmp = egc.ope & 0xff; + return((*opefn[tmp])((REG8)tmp, ad & (~1))); + + case 0x1000: + switch(egc.fgbg & 0x6000) { + case 0x2000: + return(&egc.bgc); + + case 0x4000: + return(&egc.fgc); + + default: + EGCOPE_SHIFTB; + egc.mask2.w &= egc.srcmask.w; + return(&egc_src); + } + break; + + default: + tmp = value & 0xff; + tmp = tmp | (tmp << 8); + egc_data.w[0] = (UINT16)tmp; + egc_data.w[1] = (UINT16)tmp; + egc_data.w[2] = (UINT16)tmp; + egc_data.w[3] = (UINT16)tmp; + return(&egc_data); + } +} + +static const EGCQUAD * MEMCALL egc_opew(UINT32 ad, REG16 value) { + + UINT tmp; + + egc.mask2.w = egc.mask.w; + switch(egc.ope & 0x1800) { + case 0x0800: + EGCOPE_SHIFTW; + egc.mask2.w &= egc.srcmask.w; + tmp = egc.ope & 0xff; + return((*opefn[tmp])((REG8)tmp, ad)); + + case 0x1000: + EGCOPE_SHIFTW2; + egc.mask2.w &= egc.srcmask.w; + switch(egc.fgbg & 0x6000) { + case 0x2000: + return(&egc.bgc); + case 0x4000: + return(&egc.fgc); + default: + return(&egc.patreg); + } + break; + + default: +#if defined(BYTESEX_BIG) + value = ((value >> 8) & 0xff) | ((value & 0xff) << 8); +#endif + egc_data.w[0] = (UINT16)value; + egc_data.w[1] = (UINT16)value; + egc_data.w[2] = (UINT16)value; + egc_data.w[3] = (UINT16)value; + EGCOPE_SHIFTW2; + egc.mask2.w &= egc.srcmask.w; + return(&egc_data); + } +} + + +// ---- + +REG8 MEMCALL egc_readbyte(UINT32 addr) { + + UINT32 ad; + UINT ext; + + if (gdcs.access) { + addr += VRAM_STEP; + } + ad = VRAMADDRMASKEX(addr); + ext = EGCADDR(addr & 1); + egc.lastvram._b[0][ext] = mem[ad + VRAM_B]; + egc.lastvram._b[1][ext] = mem[ad + VRAM_R]; + egc.lastvram._b[2][ext] = mem[ad + VRAM_G]; + egc.lastvram._b[3][ext] = mem[ad + VRAM_E]; + + // shift input + if (!(egc.ope & 0x400)) { + egc.inptr[0] = egc.lastvram._b[0][ext]; + egc.inptr[4] = egc.lastvram._b[1][ext]; + egc.inptr[8] = egc.lastvram._b[2][ext]; + egc.inptr[12] = egc.lastvram._b[3][ext]; + shiftinput_byte(ext); + } + + if ((egc.ope & 0x0300) == 0x0100) { + egc.patreg._b[0][ext] = mem[ad + VRAM_B]; + egc.patreg._b[1][ext] = mem[ad + VRAM_R]; + egc.patreg._b[2][ext] = mem[ad + VRAM_G]; + egc.patreg._b[3][ext] = mem[ad + VRAM_E]; + } + if (!(egc.ope & 0x2000)) { + int pl = (egc.fgbg >> 8) & 3; + if (!(egc.ope & 0x400)) { + return(egc_src._b[pl][ext]); + } + else { + return(mem[ad + planead[pl]]); + } + } + return(mem[addr]); +} + + +void MEMCALL egc_writebyte(UINT32 addr, REG8 value) { + + UINT ext; +const EGCQUAD *data; + addr = LOW15(addr); + ext = EGCADDR(addr & 1); + if (!gdcs.access) { + gdcs.grphdisp |= 1; + vramupdate[addr] |= 0x01; + } + else { + gdcs.grphdisp |= 2; + vramupdate[addr] |= 0x02; + addr += VRAM_STEP; + } + if ((egc.ope & 0x0300) == 0x0200) { + egc.patreg._b[0][ext] = mem[addr + VRAM_B]; + egc.patreg._b[1][ext] = mem[addr + VRAM_R]; + egc.patreg._b[2][ext] = mem[addr + VRAM_G]; + egc.patreg._b[3][ext] = mem[addr + VRAM_E]; + } + + data = egc_opeb(addr, value); + if (egc.mask2._b[ext]) { + if (!(egc.access & 1)) { + mem[addr + VRAM_B] &= ~egc.mask2._b[ext]; + mem[addr + VRAM_B] |= data->_b[0][ext] & egc.mask2._b[ext]; + } + if (!(egc.access & 2)) { + mem[addr + VRAM_R] &= ~egc.mask2._b[ext]; + mem[addr + VRAM_R] |= data->_b[1][ext] & egc.mask2._b[ext]; + } + if (!(egc.access & 4)) { + mem[addr + VRAM_G] &= ~egc.mask2._b[ext]; + mem[addr + VRAM_G] |= data->_b[2][ext] & egc.mask2._b[ext]; + } + if (!(egc.access & 8)) { + mem[addr + VRAM_E] &= ~egc.mask2._b[ext]; + mem[addr + VRAM_E] |= data->_b[3][ext] & egc.mask2._b[ext]; + } + } +} + +REG16 MEMCALL egc_readword(UINT32 addr) { +/* + UINT32 ad; + int pl; + + __ASSERT(!(addr & 1)); + if (gdcs.access) { + addr += VRAM_STEP; + } + ad = VRAMADDRMASKEX(addr); + egc.lastvram.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); + egc.lastvram.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); + egc.lastvram.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); + egc.lastvram.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); + + // shift input + pl = (egc.fgbg >> 8) & 3; + if (!(egc.ope & 0x400)) { + if (!(egc.sft & 0x1000)) { + if(!(egc.ope & 0x2000)){ + egc.inptr[ 4*pl+0] = egc.lastvram._b[pl][EGCADDR_L]; + egc.inptr[ 4*pl+1] = egc.lastvram._b[pl][EGCADDR_L]; + }else{ + egc.inptr[ 0] = egc.lastvram._b[0][EGCADDR_L]; + egc.inptr[ 1] = egc.lastvram._b[0][EGCADDR_H]; + egc.inptr[ 4] = egc.lastvram._b[1][EGCADDR_L]; + egc.inptr[ 5] = egc.lastvram._b[1][EGCADDR_H]; + egc.inptr[ 8] = egc.lastvram._b[2][EGCADDR_L]; + egc.inptr[ 9] = egc.lastvram._b[2][EGCADDR_H]; + egc.inptr[12] = egc.lastvram._b[3][EGCADDR_L]; + egc.inptr[13] = egc.lastvram._b[3][EGCADDR_H]; + + shiftinput_incw(); + } + }else { + egc.inptr[-1] = egc.lastvram._b[0][EGCADDR_L]; + egc.inptr[ 0] = egc.lastvram._b[0][EGCADDR_H]; + egc.inptr[ 3] = egc.lastvram._b[1][EGCADDR_L]; + egc.inptr[ 4] = egc.lastvram._b[1][EGCADDR_H]; + egc.inptr[ 7] = egc.lastvram._b[2][EGCADDR_L]; + egc.inptr[ 8] = egc.lastvram._b[2][EGCADDR_H]; + egc.inptr[11] = egc.lastvram._b[3][EGCADDR_L]; + egc.inptr[12] = egc.lastvram._b[3][EGCADDR_H]; + shiftinput_decw(); + } + } + + if ((egc.ope & 0x0300) == 0x0100) { + egc.patreg.d[0] = egc.lastvram.d[0]; + egc.patreg.d[1] = egc.lastvram.d[1]; + } + if (!(egc.ope & 0x2000)) { + +// if (!(egc.ope & 0x400)) { +// return(LOADINTELWORD(egc_src._b[pl])); +// } +// else { + UINT temp0,temp1,temp2,temp_1,temp_2; + UINT16 tempx; + UINT32 temp; + if(ad > 3)temp_2 =mem[ad -3 + planead[pl]]; + if(ad > 2)temp_1 =mem[ad -2 + planead[pl]]; + if(ad > 1)temp0 = mem[ad -1 + planead[pl]]; + temp1 = mem[ad -0 + planead[pl]]; + temp2 = mem[ad +1 + planead[pl]]; + if( ((egc.sft & 0xf0)>>4) < (egc.sft & 0xf)){//sftcopy1? + temp = (temp_2 << 24)|(temp_1<<16)|(temp0 <<8)|(temp1); + temp = (temp << (egc.sft & 0x0f) ) >> ((egc.sft & 0xf0)>>4); + temp = temp >> 8; + tempx = (temp & 0xff00)>>8; + tempx |= (temp & 0xff)<<8; + return tempx; + }else{ //sftcopy + temp = (temp0 <<16)|(temp1 <<8)|temp2; + temp = (temp << (egc.sft & 0x0f) ) >> ((egc.sft & 0xf0)>>4); + tempx = (temp & 0xff00)>>8; + tempx |= (temp & 0xff)<<8; + return tempx; + } +// } + } + { + int fg1,fg2,fg4,fg8; + UINT16 temp3; + if(!(egc.access & 1))fg1 = (egc.fg&1)|(egc.fg&1)<<1|(egc.fg&1)<<2|(egc.fg&1)<<3|(egc.fg&1)<<4|(egc.fg&1)<<5|(egc.fg&1)<<6|(egc.fg&1)<<7; + if(!(egc.access & 1))fg2 = (egc.fg&2)|(egc.fg&2)<<1|(egc.fg&2)<<2|(egc.fg&2)<<3|(egc.fg&2)<<4|(egc.fg&2)<<5|(egc.fg&2)<<6|(egc.fg&2)<<7; + if(!(egc.access & 1))fg4 = (egc.fg&4)|(egc.fg&4)<<1|(egc.fg&4)<<2|(egc.fg&4)<<3|(egc.fg&4)<<4|(egc.fg&4)<<5|(egc.fg&4)<<6|(egc.fg&4)<<7; + if(!(egc.access & 1))fg8 = (egc.fg&8)|(egc.fg&8)<<1|(egc.fg&8)<<2|(egc.fg&8)<<3|(egc.fg&8)<<4|(egc.fg&8)<<5|(egc.fg&8)<<6|(egc.fg&8)<<7; + temp3 = *(UINT16 *)(&mem[ad + VRAM_B]) ^ fg1; + temp3 |= *(UINT16 *)(&mem[ad + VRAM_R]) ^ fg2; + temp3 |= *(UINT16 *)(&mem[ad + VRAM_G]) ^ fg4; + temp3 |= *(UINT16 *)(&mem[ad + VRAM_E]) ^ fg8; + return (~temp3); + } +// return(LOADINTELWORD(mem + addr));*/ + + + UINT32 ad; + + __ASSERT(!(addr & 1)); + if (gdcs.access) { + addr += VRAM_STEP; + } + ad = VRAMADDRMASKEX(addr); + egc.lastvram.w[0] = *(UINT16 *)(&mem[ad + VRAM_B]); + egc.lastvram.w[1] = *(UINT16 *)(&mem[ad + VRAM_R]); + egc.lastvram.w[2] = *(UINT16 *)(&mem[ad + VRAM_G]); + egc.lastvram.w[3] = *(UINT16 *)(&mem[ad + VRAM_E]); + + // shift input + if (!(egc.ope & 0x400)) { + if (!(egc.sft & 0x1000)) { + egc.inptr[ 0] = egc.lastvram._b[0][EGCADDR_L]; + egc.inptr[ 1] = egc.lastvram._b[0][EGCADDR_H]; + egc.inptr[ 4] = egc.lastvram._b[1][EGCADDR_L]; + egc.inptr[ 5] = egc.lastvram._b[1][EGCADDR_H]; + egc.inptr[ 8] = egc.lastvram._b[2][EGCADDR_L]; + egc.inptr[ 9] = egc.lastvram._b[2][EGCADDR_H]; + egc.inptr[12] = egc.lastvram._b[3][EGCADDR_L]; + egc.inptr[13] = egc.lastvram._b[3][EGCADDR_H]; + shiftinput_incw(); + } + else { + egc.inptr[-1] = egc.lastvram._b[0][EGCADDR_L]; + egc.inptr[ 0] = egc.lastvram._b[0][EGCADDR_H]; + egc.inptr[ 3] = egc.lastvram._b[1][EGCADDR_L]; + egc.inptr[ 4] = egc.lastvram._b[1][EGCADDR_H]; + egc.inptr[ 7] = egc.lastvram._b[2][EGCADDR_L]; + egc.inptr[ 8] = egc.lastvram._b[2][EGCADDR_H]; + egc.inptr[11] = egc.lastvram._b[3][EGCADDR_L]; + egc.inptr[12] = egc.lastvram._b[3][EGCADDR_H]; + shiftinput_decw(); + } + } + + if ((egc.ope & 0x0300) == 0x0100) { + egc.patreg.d[0] = egc.lastvram.d[0]; + egc.patreg.d[1] = egc.lastvram.d[1]; + } + if (!(egc.ope & 0x2000)) { + int pl = (egc.fgbg >> 8) & 3; + if (!(egc.ope & 0x400)) { + return(LOADINTELWORD(egc_src._b[pl])); + } + else { + return(LOADINTELWORD(mem + ad + planead[pl])); + } + } + return(LOADINTELWORD(mem + addr)); + +} + +void MEMCALL egc_writeword(UINT32 addr, REG16 value) { + +const EGCQUAD *data; + + __ASSERT(!(addr & 1)); + addr = LOW15(addr); + if (!gdcs.access) { + gdcs.grphdisp |= 1; + *(UINT16 *)(vramupdate + addr) |= 0x0101; + } + else { + gdcs.grphdisp |= 2; + *(UINT16 *)(vramupdate + addr) |= 0x0202; + addr += VRAM_STEP; + } + if ((egc.ope & 0x0300) == 0x0200) { + egc.patreg.w[0] = *(UINT16 *)(&mem[addr + VRAM_B]); + egc.patreg.w[1] = *(UINT16 *)(&mem[addr + VRAM_R]); + egc.patreg.w[2] = *(UINT16 *)(&mem[addr + VRAM_G]); + egc.patreg.w[3] = *(UINT16 *)(&mem[addr + VRAM_E]); + } + data = egc_opew(addr, value); + if (egc.mask2.w) { + if (!(egc.access & 1)) { + *(UINT16 *)(&mem[addr + VRAM_B]) &= ~egc.mask2.w; + *(UINT16 *)(&mem[addr + VRAM_B]) |= data->w[0] & egc.mask2.w; + } + if (!(egc.access & 2)) { + *(UINT16 *)(&mem[addr + VRAM_R]) &= ~egc.mask2.w; + *(UINT16 *)(&mem[addr + VRAM_R]) |= data->w[1] & egc.mask2.w; + } + if (!(egc.access & 4)) { + *(UINT16 *)(&mem[addr + VRAM_G]) &= ~egc.mask2.w; + *(UINT16 *)(&mem[addr + VRAM_G]) |= data->w[2] & egc.mask2.w; + } + if (!(egc.access & 8)) { + *(UINT16 *)(&mem[addr + VRAM_E]) &= ~egc.mask2.w; + *(UINT16 *)(&mem[addr + VRAM_E]) |= data->w[3] & egc.mask2.w; + } + } +} + + +// ---- + +REG8 MEMCALL memegc_rd8(UINT32 addr) { + + CPU_REMCLOCK -= MEMWAIT_GRCG; + return(egc_readbyte(addr)); +} + +void MEMCALL memegc_wr8(UINT32 addr, REG8 value) { + + CPU_REMCLOCK -= MEMWAIT_GRCG; + egc_writebyte(addr, value); +} + +REG16 MEMCALL memegc_rd16(UINT32 addr) { + + CPU_REMCLOCK -= MEMWAIT_GRCG; + if (!(addr & 1)) { + return(egc_readword(addr)); + } + else if (!(egc.sft & 0x1000)) { + REG16 ret; + ret = egc_readbyte(addr); + ret |= egc_readbyte(addr+1) << 8; + return(ret); + } + else { + REG16 ret; + ret = egc_readbyte(addr+1) << 8; + ret |= egc_readbyte(addr); + return(ret); + } +} + +void MEMCALL memegc_wr16(UINT32 addr, REG16 value) { + + CPU_REMCLOCK -= MEMWAIT_GRCG; + if (!(addr & 1)) { + egc_writeword(addr, value); + } + else if (!(egc.sft & 0x1000)) { + egc_writebyte(addr, (REG8)value); + egc_writebyte(addr+1, (REG8)(value >> 8)); + } + else { + egc_writebyte(addr+1, (REG8)(value >> 8)); + egc_writebyte(addr, (REG8)value); + } +} + +UINT32 MEMCALL memegc_rd32(UINT32 address){ + UINT32 r = (UINT32)memegc_rd16(address); + r |= (UINT32)memegc_rd16(address+2) << 16; + return r; +} + +void MEMCALL memegc_wr32(UINT32 address, UINT32 value){ + memegc_wr16(address, (REG16)value); + memegc_wr16(address+2, (REG16)(value >> 16)); +} diff --git a/mem/memegc.h b/mem/memegc.h old mode 100755 new mode 100644 index c3caad13..b20ae1d7 --- a/mem/memegc.h +++ b/mem/memegc.h @@ -1,23 +1,23 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void egcshift(void); - -REG8 MEMCALL egc_readbyte(UINT32 addr); -void MEMCALL egc_writebyte(UINT32 addr, REG8 value); -REG16 MEMCALL egc_readword(UINT32 addr); -void MEMCALL egc_writeword(UINT32 addr, REG16 value); - -REG8 MEMCALL memegc_rd8(UINT32 addr); -void MEMCALL memegc_wr8(UINT32 addr, REG8 value); -REG16 MEMCALL memegc_rd16(UINT32 addr); -void MEMCALL memegc_wr16(UINT32 addr, REG16 value); -UINT32 MEMCALL memegc_rd32(UINT32 address); -void MEMCALL memegc_wr32(UINT32 address, UINT32 value); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void egcshift(void); + +REG8 MEMCALL egc_readbyte(UINT32 addr); +void MEMCALL egc_writebyte(UINT32 addr, REG8 value); +REG16 MEMCALL egc_readword(UINT32 addr); +void MEMCALL egc_writeword(UINT32 addr, REG16 value); + +REG8 MEMCALL memegc_rd8(UINT32 addr); +void MEMCALL memegc_wr8(UINT32 addr, REG8 value); +REG16 MEMCALL memegc_rd16(UINT32 addr); +void MEMCALL memegc_wr16(UINT32 addr, REG16 value); +UINT32 MEMCALL memegc_rd32(UINT32 address); +void MEMCALL memegc_wr32(UINT32 address, UINT32 value); + +#ifdef __cplusplus +} +#endif + diff --git a/mem/memems.c b/mem/memems.c old mode 100755 new mode 100644 index 3f0df0ae..e6e6b738 --- a/mem/memems.c +++ b/mem/memems.c @@ -1,58 +1,58 @@ -#include -#include -#include -#include -#include - - -REG8 MEMCALL memems_rd8(UINT32 address) { - - return(CPU_EMSPTR[(address >> 14) & 3][LOW14(address)]); -} - -REG16 MEMCALL memems_rd16(UINT32 address) { - -const UINT8 *ptr; - REG16 ret; - - if ((address & 0x3fff) != 0x3fff) { - ptr = CPU_EMSPTR[(address >> 14) & 3] + LOW14(address); - return(LOADINTELWORD(ptr)); - } - else { - ret = CPU_EMSPTR[(address >> 14) & 3][0x3fff]; - ret += CPU_EMSPTR[((address + 1) >> 14) & 3][0] << 8; - return(ret); - } -} - -UINT32 MEMCALL memems_rd32(UINT32 address){ - UINT32 r = (UINT32)memems_rd16(address); - r |= (UINT32)memems_rd16(address+2) << 16; - return r; -} - -void MEMCALL memems_wr8(UINT32 address, REG8 value) { - - CPU_EMSPTR[(address >> 14) & 3][LOW14(address)] = (UINT8)value; -} - -void MEMCALL memems_wr16(UINT32 address, REG16 value) { - - UINT8 *ptr; - - if ((address & 0x3fff) != 0x3fff) { - ptr = CPU_EMSPTR[(address >> 14) & 3] + LOW14(address); - STOREINTELWORD(ptr, value); - } - else { - CPU_EMSPTR[(address >> 14) & 3][0x3fff] = (UINT8)value; - CPU_EMSPTR[((address + 1) >> 14) & 3][0] = (UINT8)(value >> 8); - } -} - -void MEMCALL memems_wr32(UINT32 address, UINT32 value){ - memems_wr16(address, (REG16)value); - memems_wr16(address+2, (REG16)(value >> 16)); -} - +#include +#include +#include +#include +#include + + +REG8 MEMCALL memems_rd8(UINT32 address) { + + return(CPU_EMSPTR[(address >> 14) & 3][LOW14(address)]); +} + +REG16 MEMCALL memems_rd16(UINT32 address) { + +const UINT8 *ptr; + REG16 ret; + + if ((address & 0x3fff) != 0x3fff) { + ptr = CPU_EMSPTR[(address >> 14) & 3] + LOW14(address); + return(LOADINTELWORD(ptr)); + } + else { + ret = CPU_EMSPTR[(address >> 14) & 3][0x3fff]; + ret += CPU_EMSPTR[((address + 1) >> 14) & 3][0] << 8; + return(ret); + } +} + +UINT32 MEMCALL memems_rd32(UINT32 address){ + UINT32 r = (UINT32)memems_rd16(address); + r |= (UINT32)memems_rd16(address+2) << 16; + return r; +} + +void MEMCALL memems_wr8(UINT32 address, REG8 value) { + + CPU_EMSPTR[(address >> 14) & 3][LOW14(address)] = (UINT8)value; +} + +void MEMCALL memems_wr16(UINT32 address, REG16 value) { + + UINT8 *ptr; + + if ((address & 0x3fff) != 0x3fff) { + ptr = CPU_EMSPTR[(address >> 14) & 3] + LOW14(address); + STOREINTELWORD(ptr, value); + } + else { + CPU_EMSPTR[(address >> 14) & 3][0x3fff] = (UINT8)value; + CPU_EMSPTR[((address + 1) >> 14) & 3][0] = (UINT8)(value >> 8); + } +} + +void MEMCALL memems_wr32(UINT32 address, UINT32 value){ + memems_wr16(address, (REG16)value); + memems_wr16(address+2, (REG16)(value >> 16)); +} + diff --git a/mem/memems.h b/mem/memems.h old mode 100755 new mode 100644 index ebd87097..00eb1231 --- a/mem/memems.h +++ b/mem/memems.h @@ -1,16 +1,16 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -REG8 MEMCALL memems_rd8(UINT32 address); -REG16 MEMCALL memems_rd16(UINT32 address); -UINT32 MEMCALL memems_rd32(UINT32 address); -void MEMCALL memems_wr8(UINT32 address, REG8 value); -void MEMCALL memems_wr16(UINT32 address, REG16 value); -void MEMCALL memems_wr32(UINT32 address, UINT32 value); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +REG8 MEMCALL memems_rd8(UINT32 address); +REG16 MEMCALL memems_rd16(UINT32 address); +UINT32 MEMCALL memems_rd32(UINT32 address); +void MEMCALL memems_wr8(UINT32 address, REG8 value); +void MEMCALL memems_wr16(UINT32 address, REG16 value); +void MEMCALL memems_wr32(UINT32 address, UINT32 value); + +#ifdef __cplusplus +} +#endif + diff --git a/mem/memepp.c b/mem/memepp.c old mode 100755 new mode 100644 index 99be3008..00015e40 --- a/mem/memepp.c +++ b/mem/memepp.c @@ -1,89 +1,89 @@ -#include -#include -#include -#include -#include - - -// ---- EPP-ROM - -void MEMCALL memd000_wr8(UINT32 address, REG8 value) { - - if (CPU_RAM_D000 & (1 << ((address >> 12) & 15))) { - mem[address] = (UINT8)value; - } -} - -void MEMCALL memd000_wr16(UINT32 address, REG16 value) { - - UINT8 *ptr; - UINT16 bit; - - ptr = mem + address; - bit = 1 << ((address >> 12) & 15); - if ((address + 1) & 0xfff) { - if (CPU_RAM_D000 & bit) { - STOREINTELWORD(ptr, value); - } - } - else { - if (CPU_RAM_D000 & bit) { - ptr[0] = (UINT8)value; - } - if (CPU_RAM_D000 & (bit << 1)) { - ptr[1] = (UINT8)(value >> 8); - } - } -} - -void MEMCALL memd000_wr32(UINT32 address, UINT32 value){ - memd000_wr16(address, (REG16)value); - memd000_wr16(address+2, (REG16)(value >> 16)); -} - - -// ---- ITF - -REG8 MEMCALL memf800_rd8(UINT32 address) { - - if (CPU_ITFBANK) { - address += VRAM_STEP; - } - return(mem[address]); -} - -REG16 MEMCALL memf800_rd16(UINT32 address) { - - if (CPU_ITFBANK) { - address += VRAM_STEP; - } - return(LOADINTELWORD(mem + address)); -} - -UINT32 MEMCALL memf800_rd32(UINT32 address){ - UINT32 r = (UINT32)memf800_rd16(address); - r |= (UINT32)memf800_rd16(address+2) << 16; - return r; -} - - -// ---- EPSON ROM - -void MEMCALL memepson_wr8(UINT32 address, REG8 value) { - - mem[address + 0x1c8000 - 0xe8000] = (UINT8)value; -} - -void MEMCALL memepson_wr16(UINT32 address, REG16 value) { - - UINT8 *ptr; - - ptr = mem + (address + 0x1c8000 - 0xe8000); - STOREINTELWORD(ptr, value); -} - -void MEMCALL memepson_wr32(UINT32 address, UINT32 value){ - memepson_wr16(address, (REG16)value); - memepson_wr16(address+2, (REG16)(value >> 16)); -} - +#include +#include +#include +#include +#include + + +// ---- EPP-ROM + +void MEMCALL memd000_wr8(UINT32 address, REG8 value) { + + if (CPU_RAM_D000 & (1 << ((address >> 12) & 15))) { + mem[address] = (UINT8)value; + } +} + +void MEMCALL memd000_wr16(UINT32 address, REG16 value) { + + UINT8 *ptr; + UINT16 bit; + + ptr = mem + address; + bit = 1 << ((address >> 12) & 15); + if ((address + 1) & 0xfff) { + if (CPU_RAM_D000 & bit) { + STOREINTELWORD(ptr, value); + } + } + else { + if (CPU_RAM_D000 & bit) { + ptr[0] = (UINT8)value; + } + if (CPU_RAM_D000 & (bit << 1)) { + ptr[1] = (UINT8)(value >> 8); + } + } +} + +void MEMCALL memd000_wr32(UINT32 address, UINT32 value){ + memd000_wr16(address, (REG16)value); + memd000_wr16(address+2, (REG16)(value >> 16)); +} + + +// ---- ITF + +REG8 MEMCALL memf800_rd8(UINT32 address) { + + if (CPU_ITFBANK) { + address += VRAM_STEP; + } + return(mem[address]); +} + +REG16 MEMCALL memf800_rd16(UINT32 address) { + + if (CPU_ITFBANK) { + address += VRAM_STEP; + } + return(LOADINTELWORD(mem + address)); +} + +UINT32 MEMCALL memf800_rd32(UINT32 address){ + UINT32 r = (UINT32)memf800_rd16(address); + r |= (UINT32)memf800_rd16(address+2) << 16; + return r; +} + + +// ---- EPSON ROM + +void MEMCALL memepson_wr8(UINT32 address, REG8 value) { + + mem[address + 0x1c8000 - 0xe8000] = (UINT8)value; +} + +void MEMCALL memepson_wr16(UINT32 address, REG16 value) { + + UINT8 *ptr; + + ptr = mem + (address + 0x1c8000 - 0xe8000); + STOREINTELWORD(ptr, value); +} + +void MEMCALL memepson_wr32(UINT32 address, UINT32 value){ + memepson_wr16(address, (REG16)value); + memepson_wr16(address+2, (REG16)(value >> 16)); +} + diff --git a/mem/memepp.h b/mem/memepp.h old mode 100755 new mode 100644 index 764b5b1c..44072e1b --- a/mem/memepp.h +++ b/mem/memepp.h @@ -1,21 +1,21 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void MEMCALL memd000_wr8(UINT32 address, REG8 value); -void MEMCALL memd000_wr16(UINT32 address, REG16 value); -void MEMCALL memd000_wr32(UINT32 address, UINT32 value); - -REG8 MEMCALL memf800_rd8(UINT32 address); -REG16 MEMCALL memf800_rd16(UINT32 address); -UINT32 MEMCALL memf800_rd32(UINT32 address); - -void MEMCALL memepson_wr8(UINT32 address, REG8 value); -void MEMCALL memepson_wr16(UINT32 address, REG16 value); -void MEMCALL memepson_wr32(UINT32 address, UINT32 value); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void MEMCALL memd000_wr8(UINT32 address, REG8 value); +void MEMCALL memd000_wr16(UINT32 address, REG16 value); +void MEMCALL memd000_wr32(UINT32 address, UINT32 value); + +REG8 MEMCALL memf800_rd8(UINT32 address); +REG16 MEMCALL memf800_rd16(UINT32 address); +UINT32 MEMCALL memf800_rd32(UINT32 address); + +void MEMCALL memepson_wr8(UINT32 address, REG8 value); +void MEMCALL memepson_wr16(UINT32 address, REG16 value); +void MEMCALL memepson_wr32(UINT32 address, UINT32 value); + +#ifdef __cplusplus +} +#endif + diff --git a/mem/memtram.c b/mem/memtram.c old mode 100755 new mode 100644 index 03f3ef6f..a9bf901e --- a/mem/memtram.c +++ b/mem/memtram.c @@ -1,180 +1,180 @@ -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_TEXTHOOK) -#include -#endif - - -REG8 MEMCALL memtram_rd8(UINT32 address) { - - CPU_REMCLOCK -= MEMWAIT_TRAM; - if (address < 0xa4000) { - return(mem[address]); - } - else if (address < 0xa5000) { - if(hf_codeul) { - hook_fontrom(cgwindow.low); - hf_codeul = 0; - } - if (address & 1) { - return(fontrom[cgwindow.high + ((address >> 1) & 0x0f)]); - } - else { - return(fontrom[cgwindow.low + ((address >> 1) & 0x0f)]); - } - } - return(mem[address]); -} - -REG16 MEMCALL memtram_rd16(UINT32 address) { - - CPU_REMCLOCK -= MEMWAIT_TRAM; - if(hf_codeul) { - hook_fontrom(cgwindow.low); - hf_codeul = 0; - } - if (address < (0xa4000 - 1)) { - return(LOADINTELWORD(mem + address)); - } - else if (address == 0xa3fff) { - return(mem[address] + (fontrom[cgwindow.low] << 8)); - } - else if (address < 0xa4fff) { - if (address & 1) { - REG16 ret; - ret = fontrom[cgwindow.high + ((address >> 1) & 0x0f)]; - ret += fontrom[cgwindow.low + (((address + 1) >> 1) & 0x0f)] << 8; - return(ret); - } - else { - REG16 ret; - ret = fontrom[cgwindow.low + ((address >> 1) & 0x0f)]; - ret += fontrom[cgwindow.high + ((address >> 1) & 0x0f)] << 8; - return(ret); - } - } - else if (address == 0xa4fff) { - return((mem[0xa5000] << 8) | fontrom[cgwindow.high + 15]); - } - return(LOADINTELWORD(mem + address)); -} - -UINT32 MEMCALL memtram_rd32(UINT32 address){ - UINT32 r = (UINT32)memtram_rd16(address); - r |= (UINT32)memtram_rd16(address+2) << 16; - return r; -} - -void MEMCALL memtram_wr8(UINT32 address, REG8 value) { - - - CPU_REMCLOCK -= MEMWAIT_TRAM; - if (address < 0xa2000) { - mem[address] = (UINT8)value; - tramupdate[LOW12(address >> 1)] |= 1; - gdcs.textdisp |= 1; - } - else if (address < 0xa3fe0) { - if (!(address & 1)) { - mem[address] = (UINT8)value; - tramupdate[LOW12(address >> 1)] |= 3; - gdcs.textdisp |= 1; - } - } - else if (address < 0xa4000) { - if (!(address & 1)) { - if ((!(address & 2)) || (gdcs.msw_accessable)) { - mem[address] = (UINT8)value; - tramupdate[LOW12(address >> 1)] |= 3; - gdcs.textdisp |= 1; - } - } - } - else if (address < 0xa5000) { - if ((address & 1) && (cgwindow.writable & 1)) { - cgwindow.writable |= 0x80; - fontrom[cgwindow.high + ((address >> 1) & 0x0f)] = (UINT8)value; - } - } -} - -void MEMCALL memtram_wr16(UINT32 address, REG16 value) { - -#if defined(SUPPORT_TEXTHOOK) - if(np2cfg.usetexthook){ - UINT16 SJis; - UINT8 th[3]; - UINT16 thw[2]; - thw[1]='\0'; - if (address & 2){ - SJis=font_Jis2Sjis(((value + 0x20) << 8) | (value >> 8)); - if(SJis){ - th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '\0'; - codecnv_sjistoucs2(thw, 1, (const char*)th, 2); - font_outhooktest((wchar_t*)thw); - } - }else if (!(address & 3)){ - SJis=font_Jis2Sjis2(((value + 0x20) << 8) | (value >> 8)); - if(SJis){ - th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '\0'; - codecnv_sjistoucs2(thw, 1, (const char*)th, 2); - font_outhooktest((wchar_t*)thw); - } - } - } -#endif - - CPU_REMCLOCK -= MEMWAIT_TRAM; - if (address < 0xa1fff) { - STOREINTELWORD(mem + address, value); - tramupdate[LOW12(address >> 1)] |= 1; - tramupdate[LOW12((address + 1) >> 1)] |= 1; - gdcs.textdisp |= 1; - } - else if (address == 0xa1fff) { - STOREINTELWORD(mem + address, value); - tramupdate[0] |= 3; - tramupdate[0xfff] |= 1; - gdcs.textdisp |= 1; - } - else if (address < 0xa3fe0) { - if (address & 1) { - address++; - value >>= 8; - } - mem[address] = (UINT8)value; - tramupdate[LOW12(address >> 1)] |= 3; - gdcs.textdisp |= 3; - } - else if (address < 0xa3fff) { - if (address & 1) { - address++; - value >>= 8; - } - if ((!(address & 2)) || (gdcs.msw_accessable)) { - mem[address] = (UINT8)value; - tramupdate[LOW12(address >> 1)] |= 3; - gdcs.textdisp |= 3; - } - } - else if (address < 0xa5000) { - if (!(address & 1)) { - value >>= 8; - } - if (cgwindow.writable & 1) { - cgwindow.writable |= 0x80; - fontrom[cgwindow.high + ((address >> 1) & 0x0f)] = (UINT8)value; - } - } -} - -void MEMCALL memtram_wr32(UINT32 address, UINT32 value){ - memtram_wr16(address, (REG16)value); - memtram_wr16(address+2, (REG16)(value >> 16)); -} - +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_TEXTHOOK) +#include +#endif + + +REG8 MEMCALL memtram_rd8(UINT32 address) { + + CPU_REMCLOCK -= MEMWAIT_TRAM; + if (address < 0xa4000) { + return(mem[address]); + } + else if (address < 0xa5000) { + if(hf_codeul) { + hook_fontrom(cgwindow.low); + hf_codeul = 0; + } + if (address & 1) { + return(fontrom[cgwindow.high + ((address >> 1) & 0x0f)]); + } + else { + return(fontrom[cgwindow.low + ((address >> 1) & 0x0f)]); + } + } + return(mem[address]); +} + +REG16 MEMCALL memtram_rd16(UINT32 address) { + + CPU_REMCLOCK -= MEMWAIT_TRAM; + if(hf_codeul) { + hook_fontrom(cgwindow.low); + hf_codeul = 0; + } + if (address < (0xa4000 - 1)) { + return(LOADINTELWORD(mem + address)); + } + else if (address == 0xa3fff) { + return(mem[address] + (fontrom[cgwindow.low] << 8)); + } + else if (address < 0xa4fff) { + if (address & 1) { + REG16 ret; + ret = fontrom[cgwindow.high + ((address >> 1) & 0x0f)]; + ret += fontrom[cgwindow.low + (((address + 1) >> 1) & 0x0f)] << 8; + return(ret); + } + else { + REG16 ret; + ret = fontrom[cgwindow.low + ((address >> 1) & 0x0f)]; + ret += fontrom[cgwindow.high + ((address >> 1) & 0x0f)] << 8; + return(ret); + } + } + else if (address == 0xa4fff) { + return((mem[0xa5000] << 8) | fontrom[cgwindow.high + 15]); + } + return(LOADINTELWORD(mem + address)); +} + +UINT32 MEMCALL memtram_rd32(UINT32 address){ + UINT32 r = (UINT32)memtram_rd16(address); + r |= (UINT32)memtram_rd16(address+2) << 16; + return r; +} + +void MEMCALL memtram_wr8(UINT32 address, REG8 value) { + + + CPU_REMCLOCK -= MEMWAIT_TRAM; + if (address < 0xa2000) { + mem[address] = (UINT8)value; + tramupdate[LOW12(address >> 1)] |= 1; + gdcs.textdisp |= 1; + } + else if (address < 0xa3fe0) { + if (!(address & 1)) { + mem[address] = (UINT8)value; + tramupdate[LOW12(address >> 1)] |= 3; + gdcs.textdisp |= 1; + } + } + else if (address < 0xa4000) { + if (!(address & 1)) { + if ((!(address & 2)) || (gdcs.msw_accessable)) { + mem[address] = (UINT8)value; + tramupdate[LOW12(address >> 1)] |= 3; + gdcs.textdisp |= 1; + } + } + } + else if (address < 0xa5000) { + if ((address & 1) && (cgwindow.writable & 1)) { + cgwindow.writable |= 0x80; + fontrom[cgwindow.high + ((address >> 1) & 0x0f)] = (UINT8)value; + } + } +} + +void MEMCALL memtram_wr16(UINT32 address, REG16 value) { + +#if defined(SUPPORT_TEXTHOOK) + if(np2cfg.usetexthook){ + UINT16 SJis; + UINT8 th[3]; + UINT16 thw[2]; + thw[1]='\0'; + if (address & 2){ + SJis=font_Jis2Sjis(((value + 0x20) << 8) | (value >> 8)); + if(SJis){ + th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '\0'; + codecnv_sjistoucs2(thw, 1, (const char*)th, 2); + font_outhooktest((wchar_t*)thw); + } + }else if (!(address & 3)){ + SJis=font_Jis2Sjis2(((value + 0x20) << 8) | (value >> 8)); + if(SJis){ + th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '\0'; + codecnv_sjistoucs2(thw, 1, (const char*)th, 2); + font_outhooktest((wchar_t*)thw); + } + } + } +#endif + + CPU_REMCLOCK -= MEMWAIT_TRAM; + if (address < 0xa1fff) { + STOREINTELWORD(mem + address, value); + tramupdate[LOW12(address >> 1)] |= 1; + tramupdate[LOW12((address + 1) >> 1)] |= 1; + gdcs.textdisp |= 1; + } + else if (address == 0xa1fff) { + STOREINTELWORD(mem + address, value); + tramupdate[0] |= 3; + tramupdate[0xfff] |= 1; + gdcs.textdisp |= 1; + } + else if (address < 0xa3fe0) { + if (address & 1) { + address++; + value >>= 8; + } + mem[address] = (UINT8)value; + tramupdate[LOW12(address >> 1)] |= 3; + gdcs.textdisp |= 3; + } + else if (address < 0xa3fff) { + if (address & 1) { + address++; + value >>= 8; + } + if ((!(address & 2)) || (gdcs.msw_accessable)) { + mem[address] = (UINT8)value; + tramupdate[LOW12(address >> 1)] |= 3; + gdcs.textdisp |= 3; + } + } + else if (address < 0xa5000) { + if (!(address & 1)) { + value >>= 8; + } + if (cgwindow.writable & 1) { + cgwindow.writable |= 0x80; + fontrom[cgwindow.high + ((address >> 1) & 0x0f)] = (UINT8)value; + } + } +} + +void MEMCALL memtram_wr32(UINT32 address, UINT32 value){ + memtram_wr16(address, (REG16)value); + memtram_wr16(address+2, (REG16)(value >> 16)); +} + diff --git a/mem/memtram.h b/mem/memtram.h old mode 100755 new mode 100644 index 7823e5d8..792a3edf --- a/mem/memtram.h +++ b/mem/memtram.h @@ -1,16 +1,16 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -REG8 MEMCALL memtram_rd8(UINT32 address); -REG16 MEMCALL memtram_rd16(UINT32 address); -UINT32 MEMCALL memtram_rd32(UINT32 address); -void MEMCALL memtram_wr8(UINT32 address, REG8 value); -void MEMCALL memtram_wr16(UINT32 address, REG16 value); -void MEMCALL memtram_wr32(UINT32 address, UINT32 value); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +REG8 MEMCALL memtram_rd8(UINT32 address); +REG16 MEMCALL memtram_rd16(UINT32 address); +UINT32 MEMCALL memtram_rd32(UINT32 address); +void MEMCALL memtram_wr8(UINT32 address, REG8 value); +void MEMCALL memtram_wr16(UINT32 address, REG16 value); +void MEMCALL memtram_wr32(UINT32 address, UINT32 value); + +#ifdef __cplusplus +} +#endif + diff --git a/mem/memvga.c b/mem/memvga.c old mode 100755 new mode 100644 index 8ba30757..1015e896 --- a/mem/memvga.c +++ b/mem/memvga.c @@ -1,671 +1,671 @@ -#include - -// PEGC 256 color mode - -// 詳しくもないのに作ったのでかなりいい加減です。 -// 改良するのであれば全部捨てて作り直した方が良いかもしれません - -#if defined(SUPPORT_PC9821) - -#include -#include -#include -#include -#include -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif - - -// ---- macros - -#define VGARD8(p, a) { \ - UINT32 addr; \ - addr = (vramop.mio1[(p) * 2] & 15) << 15; \ - addr += (a); \ - addr -= (0xa8000 + ((p) * 0x8000)); \ - return(vramex[addr]); \ -} - -#define VGAWR8(p, a, v) { \ - UINT32 addr; \ - UINT8 bit; \ - addr = (vramop.mio1[(p) * 2] & 15) << 15; \ - addr += (a); \ - addr -= (0xa8000 + ((p) * 0x8000)); \ - vramex[addr] = (v); \ - bit = (addr & 0x40000)?2:1; \ - vramupdate[LOW15(addr >> 3)] |= bit; \ - gdcs.grphdisp |= bit; \ -} - -#define VGARD16(p, a) { \ - UINT32 addr; \ - addr = (vramop.mio1[(p) * 2] & 15) << 15; \ - addr += (a); \ - addr -= (0xa8000 + ((p) * 0x8000)); \ - return(LOADINTELWORD(vramex + addr)); \ -} - -#define VGAWR16(p, a, v) { \ - UINT32 addr; \ - UINT8 bit; \ - addr = (vramop.mio1[(p) * 2] & 15) << 15; \ - addr += (a); \ - addr -= (0xa8000 + ((p) * 0x8000)); \ - STOREINTELWORD(vramex + addr, (v)); \ - bit = (addr & 0x40000)?2:1; \ - vramupdate[LOW15((addr + 0) >> 3)] |= bit; \ - vramupdate[LOW15((addr + 1) >> 3)] |= bit; \ - gdcs.grphdisp |= bit; \ -} - -// ---- flat (PEGC 0F00000h-00F80000h Memory Access ?) - -REG8 MEMCALL memvgaf_rd8(UINT32 address) { - - if(!(vramop.mio2[PEGC_REG_VRAM_ENABLE] & 0x1)){ - return 0xff; - } - return(vramex[address & 0x7ffff]); -} - -void MEMCALL memvgaf_wr8(UINT32 address, REG8 value) { - - UINT8 bit; - - if(!(vramop.mio2[PEGC_REG_VRAM_ENABLE] & 0x1)){ - return; - } - address = address & 0x7ffff; - vramex[address] = value; - bit = (address & 0x40000)?2:1; - vramupdate[LOW15(address >> 3)] |= bit; - gdcs.grphdisp |= bit; -} - -REG16 MEMCALL memvgaf_rd16(UINT32 address) { - - if(!(vramop.mio2[PEGC_REG_VRAM_ENABLE] & 0x1)){ - return 0xffff; - } - address = address & 0x7ffff; - return(LOADINTELWORD(vramex + address)); -} - -void MEMCALL memvgaf_wr16(UINT32 address, REG16 value) { - - UINT8 bit; - - if(!(vramop.mio2[PEGC_REG_VRAM_ENABLE] & 0x1)){ - return; - } - address = address & 0x7ffff; - STOREINTELWORD(vramex + address, value); - bit = (address & 0x40000)?2:1; - vramupdate[LOW15((address + 0) >> 3)] |= bit; - vramupdate[LOW15((address + 1) >> 3)] |= bit; - gdcs.grphdisp |= bit; -} - -UINT32 MEMCALL memvgaf_rd32(UINT32 address){ - UINT32 r = (UINT32)memvgaf_rd16(address); - r |= (UINT32)memvgaf_rd16(address+2) << 16; - return r; -} -void MEMCALL memvgaf_wr32(UINT32 address, UINT32 value){ - memvgaf_wr16(address, (REG16)value); - memvgaf_wr16(address+2, (REG16)(value >> 16)); -} - - -// ---- 8086 bank memory (PEGC memvga0:A8000h-AFFFFh, memvga1:B0000h-B7FFFh Bank(Packed-pixel Mode) or Plane Access(Plane Mode)) - -REG8 MEMCALL memvga0_rd8(UINT32 address){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - return 0; - }else -#endif - { - // Packed-pixel Mode - VGARD8(0, address) - } -} -REG8 MEMCALL memvga1_rd8(UINT32 address){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - return 0; - }else -#endif - { - // Packed-pixel Mode - VGARD8(1, address) - } -} -void MEMCALL memvga0_wr8(UINT32 address, REG8 value){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - // Nothing to do - }else -#endif - { - // Packed-pixel Mode - VGAWR8(0, address, value) - } -} -void MEMCALL memvga1_wr8(UINT32 address, REG8 value){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - // Nothing to do - }else -#endif - { - // Packed-pixel Mode - VGAWR8(1, address, value) - } -} - -REG16 MEMCALL memvga0_rd16(UINT32 address){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - return pegc_memvgaplane_rd16(address); - }else -#endif - { - // Packed-pixel Mode - VGARD16(0, address) - } -} -REG16 MEMCALL memvga1_rd16(UINT32 address){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - return pegc_memvgaplane_rd16(address); - }else -#endif - { - // Packed-pixel Mode - VGARD16(1, address) - } -} - -void MEMCALL memvga0_wr16(UINT32 address, REG16 value){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - pegc_memvgaplane_wr16(address, value); - }else -#endif - { - // Packed-pixel Mode - VGAWR16(0, address, value) - } -} -void MEMCALL memvga1_wr16(UINT32 address, REG16 value){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - pegc_memvgaplane_wr16(address, value); - }else -#endif - { - // Packed-pixel Mode - VGAWR16(1, address, value) - } -} - -UINT32 MEMCALL memvga0_rd32(UINT32 address){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - return pegc_memvgaplane_rd32(address); - }else -#endif - { - // Packed-pixel Mode - return (UINT32)memvga0_rd16(address)|(memvga0_rd16(address+2)<<16); - } -} -UINT32 MEMCALL memvga1_rd32(UINT32 address){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - return pegc_memvgaplane_rd32(address); - }else -#endif - { - // Packed-pixel Mode - return (UINT32)memvga1_rd16(address)|(memvga1_rd16(address+2)<<16); - } -} -void MEMCALL memvga0_wr32(UINT32 address, UINT32 value){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - pegc_memvgaplane_wr32(address, value); - }else -#endif - { - // Packed-pixel Mode - memvga0_wr16(address, (REG16)value); - memvga0_wr16(address+2, (REG16)(value >> 16)); - } -} -void MEMCALL memvga1_wr32(UINT32 address, UINT32 value){ -#ifdef SUPPORT_PEGC - if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ - // Plane Mode - pegc_memvgaplane_wr32(address, value); - }else -#endif - { - // Packed-pixel Mode - memvga1_wr16(address, (REG16)value); - memvga1_wr16(address+2, (REG16)(value >> 16)); - } -} - - -// ---- 8086 bank I/O (PEGC E0000h-E7FFFh MMIO) - -REG8 MEMCALL memvgaio_rd8(UINT32 address) { - - UINT pos; - - if(address > 0xe0000 + 0x0100){ - REG8 ret; - pos = address - 0xe0000 - 0x0100; - - if(PEGC_REG_PATTERN <= pos){ - ret = 0; - // vramop.mio2[PEGC_REG_PATTERN + ofs] PATTERN DATA (16bit) - // pix15 pix14 ... pix1 pix0 - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane0 |<--- ofs = 01h --->|<--- ofs = 00h --->| - // (bit0) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane1 |<--- ofs = 05h --->|<--- ofs = 04h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane2 |<--- ofs = 09h --->|<--- ofs = 08h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane3 |<--- ofs = 0Dh --->|<--- ofs = 0Ch --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane4 |<--- ofs = 11h --->|<--- ofs = 10h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane5 |<--- ofs = 15h --->|<--- ofs = 14h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane6 |<--- ofs = 19h --->|<--- ofs = 18h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane7 |<--- ofs = 1Dh --->|<--- ofs = 1Ch --->| - // (bit7) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ - // 1 palette x 16 pixels - // bit8 〜 bit0 - // pix0 <-- E0120h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit0) - // pix1 <-- E0124h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit1) - // pix2 <-- E0128h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit2) - // pix3 <-- E012Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit3) - // pix4 <-- E0130h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit4) - // pix5 <-- E0134h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit5) - // pix6 <-- E0138h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit6) - // pix7 <-- E013Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit7) - // pix8 <-- E0140h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit8) - // pix9 <-- E0144h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit9) - // pix10<-- E0148h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit10) - // pix11<-- E014Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit11) - // pix12<-- E0150h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit12) - // pix13<-- E0154h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit13) - // pix14<-- E0158h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit14) - // pix15<-- E015Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit15) - if((pos & 0x3)==0 && pos < 0x60){ - int i; - int bit = pos / 4; - for(i=7;i>=0;i--){ - ret |= (vramop.mio2[PEGC_REG_PATTERN + (7-i)*4] >> bit) & 0x1; - ret <<= 1; - } - } - }else{ - // 16 pixels x 8 planes - // pix15 〜 pix0 - // bit0 <-- E0120h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x00] - // bit1 <-- E0124h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x04] - // bit2 <-- E0128h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x08] - // bit3 <-- E012Ch(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x0C] - // bit4 <-- E0130h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x10] - // bit5 <-- E0134h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x14] - // bit6 <-- E0138h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x18] - // bit7 <-- E013Ch(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C] - if((pos & 0x3)==0 && pos < 0x40){ - ret = vramop.mio2[pos]; - } - } - return ret; - } - } - - address -= 0xe0000; - pos = address - 0x0004; - if (pos < 4) { - return(vramop.mio1[pos]); - } - pos = address - 0x0100; - if (pos < 0x20) { - return(vramop.mio2[pos]); - } - return(0x00); -} - -void MEMCALL memvgaio_wr8(UINT32 address, REG8 value) { - - UINT pos; - - if(address > 0xe0000 + 0x0100){ - pos = address - 0xe0000 - 0x0100; - - if(PEGC_REG_PATTERN <= pos){ - if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ - // 1 palette x 16 pixels - if((pos & 0x3)==0 && pos < 0x60){ - int i; - int bit = (pos - PEGC_REG_PATTERN) / 4; - for(i=0;i<8;i++){ - UINT16 tmp = LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + (7-i)*4); - tmp = (tmp & ~(1 << bit)) | ((value & 1) << bit); - STOREINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + (7-i)*4, tmp); - value >>= 1; - } - } - }else{ - // 16 pixels x 8 planes - if((pos & 0x3)==0 && pos < 0x40){ - vramop.mio2[pos] = value; - } - } - return; - } - } - - ////if(address == 0xE0110 || address == 0xE0108){ - // pegc.remain = 0; - // //pegc.lastdatalen = 0; - // pegc.lastdatalen = -(SINT32)((LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT)) & 0x1f); - ////} - address -= 0xe0000; - pos = address - 0x0004; - if (pos < 4) { - vramop.mio1[pos] = value; -#if defined(SUPPORT_IA32_HAXM) - i386hax_vm_setmemoryarea(vramex + ((vramop.mio1[0] & 15) << 15), 0xA8000, 0x8000); - i386hax_vm_setmemoryarea(vramex + ((vramop.mio1[2] & 15) << 15), 0xB0000, 0x8000); -#endif - return; - } - pos = address - 0x0100; - if (pos < 0x20) { - if(pos == PEGC_REG_MODE){ -#ifdef SUPPORT_PEGC - if(pegc.enable){ - value &= 0x1; - } -#endif - else{ - value = 0x0; - } - } - vramop.mio2[pos] = value; - //if(pos == PEGC_REG_LENGTH){ - pegc.remain = (LOADINTELDWORD(vramop.mio2 + PEGC_REG_LENGTH) & 0x0fff) + 1; - pegc.lastdatalen = 0; - //}else{ - // //STOREINTELDWORD(vramop.mio2 + PEGC_REG_LENGTH, 16-1); - //} - return; - } -} - -REG16 MEMCALL memvgaio_rd16(UINT32 address) { - - REG16 ret; - - if(address > 0xe0000 + 0x0100){ - UINT pos; - pos = address - 0xe0000 - 0x0100; - - if(PEGC_REG_PATTERN <= pos){ - ret = 0; - // vramop.mio2[PEGC_REG_PATTERN + ofs] PATTERN DATA (16bit) - // pix15 pix14 ... pix1 pix0 - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane0 |<--- ofs = 01h --->|<--- ofs = 00h --->| - // (bit0) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane1 |<--- ofs = 05h --->|<--- ofs = 04h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane2 |<--- ofs = 09h --->|<--- ofs = 08h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane3 |<--- ofs = 0Dh --->|<--- ofs = 0Ch --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane4 |<--- ofs = 11h --->|<--- ofs = 10h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane5 |<--- ofs = 15h --->|<--- ofs = 14h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane6 |<--- ofs = 19h --->|<--- ofs = 18h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane7 |<--- ofs = 1Dh --->|<--- ofs = 1Ch --->| - // (bit7) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ - // 1 palette x 16 pixels - // bit8 〜 bit0 - // pix0 <-- E0120h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit0) - // pix1 <-- E0124h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit1) - // pix2 <-- E0128h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit2) - // pix3 <-- E012Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit3) - // pix4 <-- E0130h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit4) - // pix5 <-- E0134h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit5) - // pix6 <-- E0138h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit6) - // pix7 <-- E013Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit7) - // pix8 <-- E0140h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit8) - // pix9 <-- E0144h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit9) - // pix10<-- E0148h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit10) - // pix11<-- E014Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit11) - // pix12<-- E0150h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit12) - // pix13<-- E0154h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit13) - // pix14<-- E0158h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit14) - // pix15<-- E015Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit15) - if((pos & 0x3)==0 && pos < 0x60){ - int i; - int bit = (pos - PEGC_REG_PATTERN) / 4; - for(i=7;i>=0;i--){ - ret |= (LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + (7-i)*4) >> bit) & 0x1; - ret <<= 1; - } - } - }else{ - // 16 pixels x 8 planes - // pix15 〜 pix0 - // bit0 <-- E0120h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x00] - // bit1 <-- E0124h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x04] - // bit2 <-- E0128h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x08] - // bit3 <-- E012Ch(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x0C] - // bit4 <-- E0130h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x10] - // bit5 <-- E0134h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x14] - // bit6 <-- E0138h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x18] - // bit7 <-- E013Ch(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C] - if((pos & 0x3)==0 && pos < 0x40){ - ret = LOADINTELWORD(vramop.mio2 + pos); - } - } - return ret; - } - } - - ret = memvgaio_rd8(address); - ret |= memvgaio_rd8(address + 1) << 8; - return(ret); -} - -void MEMCALL memvgaio_wr16(UINT32 address, REG16 value) { - - if(address > 0xe0000 + 0x0100){ - UINT pos; - pos = address - 0xe0000 - 0x0100; - - if(PEGC_REG_PATTERN <= pos){ - if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ - // 1 palette x 16 pixels - if((pos & 0x3)==0 && pos < 0x60){ - int i; - int bit = pos / 4; - for(i=0;i<16;i++){ - UINT16 tmp = LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + (7-i)*4); - tmp = (tmp & ~(1 << bit)) | ((value & 1) << bit); - STOREINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + (7-i)*4, tmp); - value >>= 1; - } - } - }else{ - // 16 pixels x 8 planes - if((pos & 0x3)==0 && pos < 0x40){ - STOREINTELWORD(vramop.mio2 + pos, value); - } - } - return; - } - } - - memvgaio_wr8(address + 0, (REG8)value); - memvgaio_wr8(address + 1, (REG8)(value >> 8)); - -} - -UINT32 MEMCALL memvgaio_rd32(UINT32 address){ - - UINT32 ret; - UINT pos; - - pos = address - 0xe0000 - 0x0100; - - if(address > 0xe0000 + 0x0100 && PEGC_REG_PATTERN <= pos){ - ret = 0; - // vramop.mio2[PEGC_REG_PATTERN + ofs] PATTERN DATA (32bit) - // pix31 pix30 ... pix1 pix0 - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane0 |<--- ofs = 03h --->|<--- ofs = 02h --->|<--- ofs = 01h --->|<--- ofs = 00h --->| - // (bit0) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane1 |<--- ofs = 07h --->|<--- ofs = 06h --->|<--- ofs = 05h --->|<--- ofs = 04h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane2 |<--- ofs = 0Bh --->|<--- ofs = 0Ah --->|<--- ofs = 09h --->|<--- ofs = 08h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane3 |<--- ofs = 0Fh --->|<--- ofs = 0Eh --->|<--- ofs = 0Dh --->|<--- ofs = 0Ch --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane4 |<--- ofs = 13h --->|<--- ofs = 12h --->|<--- ofs = 11h --->|<--- ofs = 10h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane5 |<--- ofs = 17h --->|<--- ofs = 16h --->|<--- ofs = 15h --->|<--- ofs = 14h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane6 |<--- ofs = 1Bh --->|<--- ofs = 1Ah --->|<--- ofs = 19h --->|<--- ofs = 18h --->| - // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - // plane7 |<--- ofs = 1Fh --->|<--- ofs = 1Eh --->|<--- ofs = 1Dh --->|<--- ofs = 1Ch --->| - // (bit7) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ - // 1 palette x 32 pixels - // bit8 〜 bit0 - // pix0 <-- E0120h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit0) - // pix1 <-- E0124h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit1) - // pix2 <-- E0128h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit2) - // pix3 <-- E012Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit3) - // pix4 <-- E0130h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit4) - // pix5 <-- E0134h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit5) - // pix6 <-- E0138h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit6) - // pix7 <-- E013Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit7) - // pix8 <-- E0140h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit8) - // pix9 <-- E0144h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit9) - // pix10<-- E0148h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit10) - // pix11<-- E014Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit11) - // pix12<-- E0150h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit12) - // pix13<-- E0154h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit13) - // pix14<-- E0158h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit14) - // pix15<-- E015Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit15) - // pix16<-- E0160h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit16) - // pix17<-- E0164h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit17) - // pix18<-- E0168h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit18) - // pix19<-- E016Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit19) - // pix20<-- E0170h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit20) - // pix21<-- E0174h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit21) - // pix22<-- E0178h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit22) - // pix23<-- E017Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit23) - // pix24<-- E0180h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit24) - // pix25<-- E0184h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit25) - // pix26<-- E0188h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit26) - // pix27<-- E018Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit27) - // pix28<-- E0190h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit28) - // pix29<-- E0194h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit29) - // pix30<-- E0198h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit30) - // pix31<-- E019Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit31) - if((pos & 0x3)==0 && pos < 0x100){ - int i; - int bit = pos / 4; - for(i=7;i>=0;i--){ - ret |= (LOADINTELDWORD(vramop.mio2 + PEGC_REG_PATTERN + i*4) >> bit) & 0x1; - ret <<= 1; - } - } - }else{ - // 32 pixels x 8 planes - // pix31 〜 pix0 - // bit0 <-- E0120h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x00] - // bit1 <-- E0124h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x04] - // bit2 <-- E0128h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x08] - // bit3 <-- E012Ch(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x0C] - // bit4 <-- E0130h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x10] - // bit5 <-- E0134h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x14] - // bit6 <-- E0138h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x18] - // bit7 <-- E013Ch(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C] - if((pos & 0x3)==0 && pos < 0x40){ - ret = LOADINTELDWORD(vramop.mio2 + pos); - } - } - return ret; - } - - return (UINT32)memvgaio_rd16(address)|(memvgaio_rd16(address+2)<<16); -} -void MEMCALL memvgaio_wr32(UINT32 address, UINT32 value){ - - UINT pos; - - pos = address - 0xe0000 - 0x0100; - - if(address > 0xe0000 + 0x0100 && PEGC_REG_PATTERN <= pos){ - if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ - // 1 palette x 32 pixels - if((pos & 0x3)==0 && pos < 0x100){ - int i; - int bit = pos / 4; - for(i=0;i<7;i++){ - UINT32 tmp = LOADINTELDWORD(vramop.mio2 + PEGC_REG_PATTERN + i*4); - tmp = (tmp & ~(1 << bit)) | ((value & 1) << bit); - STOREINTELDWORD(vramop.mio2 + PEGC_REG_PATTERN + i*4, tmp); - value >>= 1; - } - } - }else{ - // 32 pixels x 8 planes - if((pos & 0x3)==0 && pos < 0x40){ - STOREINTELDWORD(vramop.mio2 + pos, value); - } - } - return; - } - - memvgaio_wr16(address, (REG16)value); - memvgaio_wr16(address+2, (REG16)(value >> 16)); -} - -#endif - +#include + +// PEGC 256 color mode + +// 詳しくもないのに作ったのでかなりいい加減です。 +// 改良するのであれば全部捨てて作り直した方が良いかもしれません + +#if defined(SUPPORT_PC9821) + +#include +#include +#include +#include +#include +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif + + +// ---- macros + +#define VGARD8(p, a) { \ + UINT32 addr; \ + addr = (vramop.mio1[(p) * 2] & 15) << 15; \ + addr += (a); \ + addr -= (0xa8000 + ((p) * 0x8000)); \ + return(vramex[addr]); \ +} + +#define VGAWR8(p, a, v) { \ + UINT32 addr; \ + UINT8 bit; \ + addr = (vramop.mio1[(p) * 2] & 15) << 15; \ + addr += (a); \ + addr -= (0xa8000 + ((p) * 0x8000)); \ + vramex[addr] = (v); \ + bit = (addr & 0x40000)?2:1; \ + vramupdate[LOW15(addr >> 3)] |= bit; \ + gdcs.grphdisp |= bit; \ +} + +#define VGARD16(p, a) { \ + UINT32 addr; \ + addr = (vramop.mio1[(p) * 2] & 15) << 15; \ + addr += (a); \ + addr -= (0xa8000 + ((p) * 0x8000)); \ + return(LOADINTELWORD(vramex + addr)); \ +} + +#define VGAWR16(p, a, v) { \ + UINT32 addr; \ + UINT8 bit; \ + addr = (vramop.mio1[(p) * 2] & 15) << 15; \ + addr += (a); \ + addr -= (0xa8000 + ((p) * 0x8000)); \ + STOREINTELWORD(vramex + addr, (v)); \ + bit = (addr & 0x40000)?2:1; \ + vramupdate[LOW15((addr + 0) >> 3)] |= bit; \ + vramupdate[LOW15((addr + 1) >> 3)] |= bit; \ + gdcs.grphdisp |= bit; \ +} + +// ---- flat (PEGC 0F00000h-00F80000h Memory Access ?) + +REG8 MEMCALL memvgaf_rd8(UINT32 address) { + + if(!(vramop.mio2[PEGC_REG_VRAM_ENABLE] & 0x1)){ + return 0xff; + } + return(vramex[address & 0x7ffff]); +} + +void MEMCALL memvgaf_wr8(UINT32 address, REG8 value) { + + UINT8 bit; + + if(!(vramop.mio2[PEGC_REG_VRAM_ENABLE] & 0x1)){ + return; + } + address = address & 0x7ffff; + vramex[address] = value; + bit = (address & 0x40000)?2:1; + vramupdate[LOW15(address >> 3)] |= bit; + gdcs.grphdisp |= bit; +} + +REG16 MEMCALL memvgaf_rd16(UINT32 address) { + + if(!(vramop.mio2[PEGC_REG_VRAM_ENABLE] & 0x1)){ + return 0xffff; + } + address = address & 0x7ffff; + return(LOADINTELWORD(vramex + address)); +} + +void MEMCALL memvgaf_wr16(UINT32 address, REG16 value) { + + UINT8 bit; + + if(!(vramop.mio2[PEGC_REG_VRAM_ENABLE] & 0x1)){ + return; + } + address = address & 0x7ffff; + STOREINTELWORD(vramex + address, value); + bit = (address & 0x40000)?2:1; + vramupdate[LOW15((address + 0) >> 3)] |= bit; + vramupdate[LOW15((address + 1) >> 3)] |= bit; + gdcs.grphdisp |= bit; +} + +UINT32 MEMCALL memvgaf_rd32(UINT32 address){ + UINT32 r = (UINT32)memvgaf_rd16(address); + r |= (UINT32)memvgaf_rd16(address+2) << 16; + return r; +} +void MEMCALL memvgaf_wr32(UINT32 address, UINT32 value){ + memvgaf_wr16(address, (REG16)value); + memvgaf_wr16(address+2, (REG16)(value >> 16)); +} + + +// ---- 8086 bank memory (PEGC memvga0:A8000h-AFFFFh, memvga1:B0000h-B7FFFh Bank(Packed-pixel Mode) or Plane Access(Plane Mode)) + +REG8 MEMCALL memvga0_rd8(UINT32 address){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + return 0; + }else +#endif + { + // Packed-pixel Mode + VGARD8(0, address) + } +} +REG8 MEMCALL memvga1_rd8(UINT32 address){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + return 0; + }else +#endif + { + // Packed-pixel Mode + VGARD8(1, address) + } +} +void MEMCALL memvga0_wr8(UINT32 address, REG8 value){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + // Nothing to do + }else +#endif + { + // Packed-pixel Mode + VGAWR8(0, address, value) + } +} +void MEMCALL memvga1_wr8(UINT32 address, REG8 value){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + // Nothing to do + }else +#endif + { + // Packed-pixel Mode + VGAWR8(1, address, value) + } +} + +REG16 MEMCALL memvga0_rd16(UINT32 address){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + return pegc_memvgaplane_rd16(address); + }else +#endif + { + // Packed-pixel Mode + VGARD16(0, address) + } +} +REG16 MEMCALL memvga1_rd16(UINT32 address){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + return pegc_memvgaplane_rd16(address); + }else +#endif + { + // Packed-pixel Mode + VGARD16(1, address) + } +} + +void MEMCALL memvga0_wr16(UINT32 address, REG16 value){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + pegc_memvgaplane_wr16(address, value); + }else +#endif + { + // Packed-pixel Mode + VGAWR16(0, address, value) + } +} +void MEMCALL memvga1_wr16(UINT32 address, REG16 value){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + pegc_memvgaplane_wr16(address, value); + }else +#endif + { + // Packed-pixel Mode + VGAWR16(1, address, value) + } +} + +UINT32 MEMCALL memvga0_rd32(UINT32 address){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + return pegc_memvgaplane_rd32(address); + }else +#endif + { + // Packed-pixel Mode + return (UINT32)memvga0_rd16(address)|(memvga0_rd16(address+2)<<16); + } +} +UINT32 MEMCALL memvga1_rd32(UINT32 address){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + return pegc_memvgaplane_rd32(address); + }else +#endif + { + // Packed-pixel Mode + return (UINT32)memvga1_rd16(address)|(memvga1_rd16(address+2)<<16); + } +} +void MEMCALL memvga0_wr32(UINT32 address, UINT32 value){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + pegc_memvgaplane_wr32(address, value); + }else +#endif + { + // Packed-pixel Mode + memvga0_wr16(address, (REG16)value); + memvga0_wr16(address+2, (REG16)(value >> 16)); + } +} +void MEMCALL memvga1_wr32(UINT32 address, UINT32 value){ +#ifdef SUPPORT_PEGC + if(pegc.enable && (vramop.mio2[PEGC_REG_MODE] & 0x1)){ + // Plane Mode + pegc_memvgaplane_wr32(address, value); + }else +#endif + { + // Packed-pixel Mode + memvga1_wr16(address, (REG16)value); + memvga1_wr16(address+2, (REG16)(value >> 16)); + } +} + + +// ---- 8086 bank I/O (PEGC E0000h-E7FFFh MMIO) + +REG8 MEMCALL memvgaio_rd8(UINT32 address) { + + UINT pos; + + if(address > 0xe0000 + 0x0100){ + REG8 ret; + pos = address - 0xe0000 - 0x0100; + + if(PEGC_REG_PATTERN <= pos){ + ret = 0; + // vramop.mio2[PEGC_REG_PATTERN + ofs] PATTERN DATA (16bit) + // pix15 pix14 ... pix1 pix0 + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane0 |<--- ofs = 01h --->|<--- ofs = 00h --->| + // (bit0) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane1 |<--- ofs = 05h --->|<--- ofs = 04h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane2 |<--- ofs = 09h --->|<--- ofs = 08h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane3 |<--- ofs = 0Dh --->|<--- ofs = 0Ch --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane4 |<--- ofs = 11h --->|<--- ofs = 10h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane5 |<--- ofs = 15h --->|<--- ofs = 14h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane6 |<--- ofs = 19h --->|<--- ofs = 18h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane7 |<--- ofs = 1Dh --->|<--- ofs = 1Ch --->| + // (bit7) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ + // 1 palette x 16 pixels + // bit8 〜 bit0 + // pix0 <-- E0120h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit0) + // pix1 <-- E0124h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit1) + // pix2 <-- E0128h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit2) + // pix3 <-- E012Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit3) + // pix4 <-- E0130h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit4) + // pix5 <-- E0134h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit5) + // pix6 <-- E0138h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit6) + // pix7 <-- E013Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit7) + // pix8 <-- E0140h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit8) + // pix9 <-- E0144h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit9) + // pix10<-- E0148h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit10) + // pix11<-- E014Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit11) + // pix12<-- E0150h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit12) + // pix13<-- E0154h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit13) + // pix14<-- E0158h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit14) + // pix15<-- E015Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit15) + if((pos & 0x3)==0 && pos < 0x60){ + int i; + int bit = pos / 4; + for(i=7;i>=0;i--){ + ret |= (vramop.mio2[PEGC_REG_PATTERN + (7-i)*4] >> bit) & 0x1; + ret <<= 1; + } + } + }else{ + // 16 pixels x 8 planes + // pix15 〜 pix0 + // bit0 <-- E0120h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x00] + // bit1 <-- E0124h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x04] + // bit2 <-- E0128h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x08] + // bit3 <-- E012Ch(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x0C] + // bit4 <-- E0130h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x10] + // bit5 <-- E0134h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x14] + // bit6 <-- E0138h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x18] + // bit7 <-- E013Ch(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C] + if((pos & 0x3)==0 && pos < 0x40){ + ret = vramop.mio2[pos]; + } + } + return ret; + } + } + + address -= 0xe0000; + pos = address - 0x0004; + if (pos < 4) { + return(vramop.mio1[pos]); + } + pos = address - 0x0100; + if (pos < 0x20) { + return(vramop.mio2[pos]); + } + return(0x00); +} + +void MEMCALL memvgaio_wr8(UINT32 address, REG8 value) { + + UINT pos; + + if(address > 0xe0000 + 0x0100){ + pos = address - 0xe0000 - 0x0100; + + if(PEGC_REG_PATTERN <= pos){ + if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ + // 1 palette x 16 pixels + if((pos & 0x3)==0 && pos < 0x60){ + int i; + int bit = (pos - PEGC_REG_PATTERN) / 4; + for(i=0;i<8;i++){ + UINT16 tmp = LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + (7-i)*4); + tmp = (tmp & ~(1 << bit)) | ((value & 1) << bit); + STOREINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + (7-i)*4, tmp); + value >>= 1; + } + } + }else{ + // 16 pixels x 8 planes + if((pos & 0x3)==0 && pos < 0x40){ + vramop.mio2[pos] = value; + } + } + return; + } + } + + ////if(address == 0xE0110 || address == 0xE0108){ + // pegc.remain = 0; + // //pegc.lastdatalen = 0; + // pegc.lastdatalen = -(SINT32)((LOADINTELWORD(vramop.mio2+PEGC_REG_SHIFT)) & 0x1f); + ////} + address -= 0xe0000; + pos = address - 0x0004; + if (pos < 4) { + vramop.mio1[pos] = value; +#if defined(SUPPORT_IA32_HAXM) + i386hax_vm_setmemoryarea(vramex + ((vramop.mio1[0] & 15) << 15), 0xA8000, 0x8000); + i386hax_vm_setmemoryarea(vramex + ((vramop.mio1[2] & 15) << 15), 0xB0000, 0x8000); +#endif + return; + } + pos = address - 0x0100; + if (pos < 0x20) { + if(pos == PEGC_REG_MODE){ +#ifdef SUPPORT_PEGC + if(pegc.enable){ + value &= 0x1; + } +#endif + else{ + value = 0x0; + } + } + vramop.mio2[pos] = value; + //if(pos == PEGC_REG_LENGTH){ + pegc.remain = (LOADINTELDWORD(vramop.mio2 + PEGC_REG_LENGTH) & 0x0fff) + 1; + pegc.lastdatalen = 0; + //}else{ + // //STOREINTELDWORD(vramop.mio2 + PEGC_REG_LENGTH, 16-1); + //} + return; + } +} + +REG16 MEMCALL memvgaio_rd16(UINT32 address) { + + REG16 ret; + + if(address > 0xe0000 + 0x0100){ + UINT pos; + pos = address - 0xe0000 - 0x0100; + + if(PEGC_REG_PATTERN <= pos){ + ret = 0; + // vramop.mio2[PEGC_REG_PATTERN + ofs] PATTERN DATA (16bit) + // pix15 pix14 ... pix1 pix0 + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane0 |<--- ofs = 01h --->|<--- ofs = 00h --->| + // (bit0) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane1 |<--- ofs = 05h --->|<--- ofs = 04h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane2 |<--- ofs = 09h --->|<--- ofs = 08h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane3 |<--- ofs = 0Dh --->|<--- ofs = 0Ch --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane4 |<--- ofs = 11h --->|<--- ofs = 10h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane5 |<--- ofs = 15h --->|<--- ofs = 14h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane6 |<--- ofs = 19h --->|<--- ofs = 18h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane7 |<--- ofs = 1Dh --->|<--- ofs = 1Ch --->| + // (bit7) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ + // 1 palette x 16 pixels + // bit8 〜 bit0 + // pix0 <-- E0120h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit0) + // pix1 <-- E0124h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit1) + // pix2 <-- E0128h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit2) + // pix3 <-- E012Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit3) + // pix4 <-- E0130h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit4) + // pix5 <-- E0134h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit5) + // pix6 <-- E0138h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit6) + // pix7 <-- E013Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit7) + // pix8 <-- E0140h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit8) + // pix9 <-- E0144h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit9) + // pix10<-- E0148h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit10) + // pix11<-- E014Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit11) + // pix12<-- E0150h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit12) + // pix13<-- E0154h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit13) + // pix14<-- E0158h(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit14) + // pix15<-- E015Ch(8bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit15) + if((pos & 0x3)==0 && pos < 0x60){ + int i; + int bit = (pos - PEGC_REG_PATTERN) / 4; + for(i=7;i>=0;i--){ + ret |= (LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + (7-i)*4) >> bit) & 0x1; + ret <<= 1; + } + } + }else{ + // 16 pixels x 8 planes + // pix15 〜 pix0 + // bit0 <-- E0120h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x00] + // bit1 <-- E0124h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x04] + // bit2 <-- E0128h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x08] + // bit3 <-- E012Ch(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x0C] + // bit4 <-- E0130h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x10] + // bit5 <-- E0134h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x14] + // bit6 <-- E0138h(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x18] + // bit7 <-- E013Ch(16bit) --> LOADINTELWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C] + if((pos & 0x3)==0 && pos < 0x40){ + ret = LOADINTELWORD(vramop.mio2 + pos); + } + } + return ret; + } + } + + ret = memvgaio_rd8(address); + ret |= memvgaio_rd8(address + 1) << 8; + return(ret); +} + +void MEMCALL memvgaio_wr16(UINT32 address, REG16 value) { + + if(address > 0xe0000 + 0x0100){ + UINT pos; + pos = address - 0xe0000 - 0x0100; + + if(PEGC_REG_PATTERN <= pos){ + if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ + // 1 palette x 16 pixels + if((pos & 0x3)==0 && pos < 0x60){ + int i; + int bit = pos / 4; + for(i=0;i<16;i++){ + UINT16 tmp = LOADINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + (7-i)*4); + tmp = (tmp & ~(1 << bit)) | ((value & 1) << bit); + STOREINTELWORD(vramop.mio2 + PEGC_REG_PATTERN + (7-i)*4, tmp); + value >>= 1; + } + } + }else{ + // 16 pixels x 8 planes + if((pos & 0x3)==0 && pos < 0x40){ + STOREINTELWORD(vramop.mio2 + pos, value); + } + } + return; + } + } + + memvgaio_wr8(address + 0, (REG8)value); + memvgaio_wr8(address + 1, (REG8)(value >> 8)); + +} + +UINT32 MEMCALL memvgaio_rd32(UINT32 address){ + + UINT32 ret; + UINT pos; + + pos = address - 0xe0000 - 0x0100; + + if(address > 0xe0000 + 0x0100 && PEGC_REG_PATTERN <= pos){ + ret = 0; + // vramop.mio2[PEGC_REG_PATTERN + ofs] PATTERN DATA (32bit) + // pix31 pix30 ... pix1 pix0 + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane0 |<--- ofs = 03h --->|<--- ofs = 02h --->|<--- ofs = 01h --->|<--- ofs = 00h --->| + // (bit0) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane1 |<--- ofs = 07h --->|<--- ofs = 06h --->|<--- ofs = 05h --->|<--- ofs = 04h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane2 |<--- ofs = 0Bh --->|<--- ofs = 0Ah --->|<--- ofs = 09h --->|<--- ofs = 08h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane3 |<--- ofs = 0Fh --->|<--- ofs = 0Eh --->|<--- ofs = 0Dh --->|<--- ofs = 0Ch --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane4 |<--- ofs = 13h --->|<--- ofs = 12h --->|<--- ofs = 11h --->|<--- ofs = 10h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane5 |<--- ofs = 17h --->|<--- ofs = 16h --->|<--- ofs = 15h --->|<--- ofs = 14h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane6 |<--- ofs = 1Bh --->|<--- ofs = 1Ah --->|<--- ofs = 19h --->|<--- ofs = 18h --->| + // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + // plane7 |<--- ofs = 1Fh --->|<--- ofs = 1Eh --->|<--- ofs = 1Dh --->|<--- ofs = 1Ch --->| + // (bit7) +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ + // 1 palette x 32 pixels + // bit8 〜 bit0 + // pix0 <-- E0120h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit0) + // pix1 <-- E0124h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit1) + // pix2 <-- E0128h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit2) + // pix3 <-- E012Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit3) + // pix4 <-- E0130h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit4) + // pix5 <-- E0134h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit5) + // pix6 <-- E0138h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit6) + // pix7 <-- E013Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit7) + // pix8 <-- E0140h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit8) + // pix9 <-- E0144h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit9) + // pix10<-- E0148h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit10) + // pix11<-- E014Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit11) + // pix12<-- E0150h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit12) + // pix13<-- E0154h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit13) + // pix14<-- E0158h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit14) + // pix15<-- E015Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit15) + // pix16<-- E0160h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit16) + // pix17<-- E0164h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit17) + // pix18<-- E0168h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit18) + // pix19<-- E016Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit19) + // pix20<-- E0170h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit20) + // pix21<-- E0174h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit21) + // pix22<-- E0178h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit22) + // pix23<-- E017Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit23) + // pix24<-- E0180h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit24) + // pix25<-- E0184h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit25) + // pix26<-- E0188h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit26) + // pix27<-- E018Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit27) + // pix28<-- E0190h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit28) + // pix29<-- E0194h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit29) + // pix30<-- E0198h(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit30) + // pix31<-- E019Ch(8bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C], vramop.mio2[PEGC_REG_PATTERN + 0x18], ... , vramop.mio2[PEGC_REG_PATTERN + 0x00] (bit31) + if((pos & 0x3)==0 && pos < 0x100){ + int i; + int bit = pos / 4; + for(i=7;i>=0;i--){ + ret |= (LOADINTELDWORD(vramop.mio2 + PEGC_REG_PATTERN + i*4) >> bit) & 0x1; + ret <<= 1; + } + } + }else{ + // 32 pixels x 8 planes + // pix31 〜 pix0 + // bit0 <-- E0120h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x00] + // bit1 <-- E0124h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x04] + // bit2 <-- E0128h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x08] + // bit3 <-- E012Ch(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x0C] + // bit4 <-- E0130h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x10] + // bit5 <-- E0134h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x14] + // bit6 <-- E0138h(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x18] + // bit7 <-- E013Ch(32bit) --> LOADINTELDWORD vramop.mio2[PEGC_REG_PATTERN + 0x1C] + if((pos & 0x3)==0 && pos < 0x40){ + ret = LOADINTELDWORD(vramop.mio2 + pos); + } + } + return ret; + } + + return (UINT32)memvgaio_rd16(address)|(memvgaio_rd16(address+2)<<16); +} +void MEMCALL memvgaio_wr32(UINT32 address, UINT32 value){ + + UINT pos; + + pos = address - 0xe0000 - 0x0100; + + if(address > 0xe0000 + 0x0100 && PEGC_REG_PATTERN <= pos){ + if(LOADINTELWORD(vramop.mio2+PEGC_REG_PLANE_ROP) & 0x8000){ + // 1 palette x 32 pixels + if((pos & 0x3)==0 && pos < 0x100){ + int i; + int bit = pos / 4; + for(i=0;i<7;i++){ + UINT32 tmp = LOADINTELDWORD(vramop.mio2 + PEGC_REG_PATTERN + i*4); + tmp = (tmp & ~(1 << bit)) | ((value & 1) << bit); + STOREINTELDWORD(vramop.mio2 + PEGC_REG_PATTERN + i*4, tmp); + value >>= 1; + } + } + }else{ + // 32 pixels x 8 planes + if((pos & 0x3)==0 && pos < 0x40){ + STOREINTELDWORD(vramop.mio2 + pos, value); + } + } + return; + } + + memvgaio_wr16(address, (REG16)value); + memvgaio_wr16(address+2, (REG16)(value >> 16)); +} + +#endif + diff --git a/mem/memvga.h b/mem/memvga.h old mode 100755 new mode 100644 index ccb3f425..e82f9145 --- a/mem/memvga.h +++ b/mem/memvga.h @@ -1,43 +1,43 @@ - -#if defined(SUPPORT_PC9821) - -#ifdef __cplusplus -extern "C" { -#endif - -// PEGC 0F00000h-00F80000h Memory Access ? -REG8 MEMCALL memvgaf_rd8(UINT32 address); -void MEMCALL memvgaf_wr8(UINT32 address, REG8 value); -REG16 MEMCALL memvgaf_rd16(UINT32 address); -void MEMCALL memvgaf_wr16(UINT32 address, REG16 value); -UINT32 MEMCALL memvgaf_rd32(UINT32 address); -void MEMCALL memvgaf_wr32(UINT32 address, UINT32 value); - -// PEGC memvga0:A8000h-AFFFFh, memvga1:B0000h-B7FFFh Bank(Packed-pixel Mode) or Plane Access(Plane Mode) -REG8 MEMCALL memvga0_rd8(UINT32 address); -REG8 MEMCALL memvga1_rd8(UINT32 address); -void MEMCALL memvga0_wr8(UINT32 address, REG8 value); -void MEMCALL memvga1_wr8(UINT32 address, REG8 value); -REG16 MEMCALL memvga0_rd16(UINT32 address); -REG16 MEMCALL memvga1_rd16(UINT32 address); -void MEMCALL memvga0_wr16(UINT32 address, REG16 value); -void MEMCALL memvga1_wr16(UINT32 address, REG16 value); -UINT32 MEMCALL memvga0_rd32(UINT32 address); -UINT32 MEMCALL memvga1_rd32(UINT32 address); -void MEMCALL memvga0_wr32(UINT32 address, UINT32 value); -void MEMCALL memvga1_wr32(UINT32 address, UINT32 value); - -// PEGC E0000h-E7FFFh MMIO -REG8 MEMCALL memvgaio_rd8(UINT32 address); -void MEMCALL memvgaio_wr8(UINT32 address, REG8 value); -REG16 MEMCALL memvgaio_rd16(UINT32 address); -void MEMCALL memvgaio_wr16(UINT32 address, REG16 value); -UINT32 MEMCALL memvgaio_rd32(UINT32 address); -void MEMCALL memvgaio_wr32(UINT32 address, UINT32 value); - -#ifdef __cplusplus -} -#endif - -#endif - + +#if defined(SUPPORT_PC9821) + +#ifdef __cplusplus +extern "C" { +#endif + +// PEGC 0F00000h-00F80000h Memory Access ? +REG8 MEMCALL memvgaf_rd8(UINT32 address); +void MEMCALL memvgaf_wr8(UINT32 address, REG8 value); +REG16 MEMCALL memvgaf_rd16(UINT32 address); +void MEMCALL memvgaf_wr16(UINT32 address, REG16 value); +UINT32 MEMCALL memvgaf_rd32(UINT32 address); +void MEMCALL memvgaf_wr32(UINT32 address, UINT32 value); + +// PEGC memvga0:A8000h-AFFFFh, memvga1:B0000h-B7FFFh Bank(Packed-pixel Mode) or Plane Access(Plane Mode) +REG8 MEMCALL memvga0_rd8(UINT32 address); +REG8 MEMCALL memvga1_rd8(UINT32 address); +void MEMCALL memvga0_wr8(UINT32 address, REG8 value); +void MEMCALL memvga1_wr8(UINT32 address, REG8 value); +REG16 MEMCALL memvga0_rd16(UINT32 address); +REG16 MEMCALL memvga1_rd16(UINT32 address); +void MEMCALL memvga0_wr16(UINT32 address, REG16 value); +void MEMCALL memvga1_wr16(UINT32 address, REG16 value); +UINT32 MEMCALL memvga0_rd32(UINT32 address); +UINT32 MEMCALL memvga1_rd32(UINT32 address); +void MEMCALL memvga0_wr32(UINT32 address, UINT32 value); +void MEMCALL memvga1_wr32(UINT32 address, UINT32 value); + +// PEGC E0000h-E7FFFh MMIO +REG8 MEMCALL memvgaio_rd8(UINT32 address); +void MEMCALL memvgaio_wr8(UINT32 address, REG8 value); +REG16 MEMCALL memvgaio_rd16(UINT32 address); +void MEMCALL memvgaio_wr16(UINT32 address, REG16 value); +UINT32 MEMCALL memvgaio_rd32(UINT32 address); +void MEMCALL memvgaio_wr32(UINT32 address, UINT32 value); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/mem/memvram.c b/mem/memvram.c old mode 100755 new mode 100644 index 48d98de5..77aee18d --- a/mem/memvram.c +++ b/mem/memvram.c @@ -1,284 +1,284 @@ -#include -#include -#include -#include -#include -#include - - -// ---- macros - -#define VRAMRD8(p, a) { \ - CPU_REMCLOCK -= MEMWAIT_VRAM; \ - return(mem[(a) + ((p) * VRAM_STEP)]); \ -} - -#define VRAMRD16(p, a) { \ - CPU_REMCLOCK -= MEMWAIT_VRAM; \ - return(LOADINTELWORD(mem + (a) + ((p) * VRAM_STEP))); \ -} - -#define VRAMWR8(p, a, v) { \ - CPU_REMCLOCK -= MEMWAIT_VRAM; \ - mem[(a) + ((p) * VRAM_STEP)] = (UINT8)(v); \ - vramupdate[LOW15(a)] |= (1 << (p)); \ - gdcs.grphdisp |= (1 << (p)); \ -} - -#define VRAMWR16(p, a, v) { \ - CPU_REMCLOCK -= MEMWAIT_VRAM; \ - STOREINTELWORD(mem + (a) + ((p) * VRAM_STEP), (v)); \ - vramupdate[LOW15(a)] |= (1 << (p)); \ - vramupdate[LOW15((a) + 1)] |= (1 << (p)); \ - gdcs.grphdisp |= (1 << (p)); \ -} - - -#define RMWWR8(p, a, v) { \ - REG8 mask; \ - UINT8 *vram; \ - CPU_REMCLOCK -= MEMWAIT_GRCG; \ - mask = ~value; \ - (a) = LOW15((a)); \ - vramupdate[(a)] |= (1 << (p)); \ - gdcs.grphdisp |= (1 << (p)); \ - vram = mem + (a) + ((p) * VRAM_STEP); \ - if (!(grcg.modereg & 1)) { \ - vram[VRAM_B] &= mask; \ - vram[VRAM_B] |= ((v) & grcg.tile[0].b[0]); \ - } \ - if (!(grcg.modereg & 2)) { \ - vram[VRAM_R] &= mask; \ - vram[VRAM_R] |= ((v) & grcg.tile[1].b[0]); \ - } \ - if (!(grcg.modereg & 4)) { \ - vram[VRAM_G] &= mask; \ - vram[VRAM_G] |= ((v) & grcg.tile[2].b[0]); \ - } \ - if (!(grcg.modereg & 8)) { \ - vram[VRAM_E] &= mask; \ - vram[VRAM_E] |= ((v) & grcg.tile[3].b[0]); \ - } \ -} - -#define RMWWR16(p, a, v) { \ - UINT8 *vram; \ - CPU_REMCLOCK -= MEMWAIT_GRCG; \ - (a) = LOW15((a)); \ - vramupdate[(a) + 0] |= (1 << (p)); \ - vramupdate[(a) + 1] |= (1 << (p)); \ - gdcs.grphdisp |= (1 << (p)); \ - vram = mem + (a) + ((p) * VRAM_STEP); \ - if (!(grcg.modereg & 1)) { \ - UINT8 tmp; \ - tmp = (UINT8)(v); \ - vram[VRAM_B + 0] &= (~tmp); \ - vram[VRAM_B + 0] |= (tmp & grcg.tile[0].b[0]); \ - tmp = (UINT8)((v) >> 8); \ - vram[VRAM_B + 1] &= (~tmp); \ - vram[VRAM_B + 1] |= (tmp & grcg.tile[0].b[0]); \ - } \ - if (!(grcg.modereg & 2)) { \ - UINT8 tmp; \ - tmp = (UINT8)(v); \ - vram[VRAM_R + 0] &= (~tmp); \ - vram[VRAM_R + 0] |= (tmp & grcg.tile[1].b[0]); \ - tmp = (UINT8)((v) >> 8); \ - vram[VRAM_R + 1] &= (~tmp); \ - vram[VRAM_R + 1] |= (tmp & grcg.tile[1].b[0]); \ - } \ - if (!(grcg.modereg & 4)) { \ - UINT8 tmp; \ - tmp = (UINT8)(v); \ - vram[VRAM_G + 0] &= (~tmp); \ - vram[VRAM_G + 0] |= (tmp & grcg.tile[2].b[0]); \ - tmp = (UINT8)((v) >> 8); \ - vram[VRAM_G + 1] &= (~tmp); \ - vram[VRAM_G + 1] |= (tmp & grcg.tile[2].b[0]); \ - } \ - if (!(grcg.modereg & 8)) { \ - UINT8 tmp; \ - tmp = (UINT8)(v); \ - vram[VRAM_E + 0] &= (~tmp); \ - vram[VRAM_E + 0] |= (tmp & grcg.tile[3].b[0]); \ - tmp = (UINT8)((v) >> 8); \ - vram[VRAM_E + 1] &= (~tmp); \ - vram[VRAM_E + 1] |= (tmp & grcg.tile[3].b[0]); \ - } \ -} - - -#define TDWWR8(p, a, v) { \ - UINT8 *vram; \ - CPU_REMCLOCK -= MEMWAIT_GRCG; \ - (a) = LOW15(a); \ - vramupdate[(a)] |= (1 << (p)); \ - gdcs.grphdisp |= (1 << (p)); \ - vram = mem + (a) + ((p) * VRAM_STEP); \ - if (!(grcg.modereg & 1)) { \ - vram[VRAM_B] = grcg.tile[0].b[0]; \ - } \ - if (!(grcg.modereg & 2)) { \ - vram[VRAM_R] = grcg.tile[1].b[0]; \ - } \ - if (!(grcg.modereg & 4)) { \ - vram[VRAM_G] = grcg.tile[2].b[0]; \ - } \ - if (!(grcg.modereg & 8)) { \ - vram[VRAM_E] = grcg.tile[3].b[0]; \ - } \ - (void)(v); \ -} - -#define TDWWR16(p, a, v) { \ - UINT8 *vram; \ - CPU_REMCLOCK -= MEMWAIT_GRCG; \ - (a) = LOW15(a); \ - vramupdate[(a) + 0] |= (1 << (p)); \ - vramupdate[(a) + 1] |= (1 << (p)); \ - gdcs.grphdisp |= (1 << (p)); \ - vram = mem + (a) + ((p) * VRAM_STEP); \ - if (!(grcg.modereg & 1)) { \ - vram[VRAM_B + 0] = grcg.tile[0].b[0]; \ - vram[VRAM_B + 1] = grcg.tile[0].b[0]; \ - } \ - if (!(grcg.modereg & 2)) { \ - vram[VRAM_R + 0] = grcg.tile[1].b[0]; \ - vram[VRAM_R + 1] = grcg.tile[1].b[0]; \ - } \ - if (!(grcg.modereg & 4)) { \ - vram[VRAM_G + 0] = grcg.tile[2].b[0]; \ - vram[VRAM_G + 1] = grcg.tile[2].b[0]; \ - } \ - if (!(grcg.modereg & 8)) { \ - vram[VRAM_E + 0] = grcg.tile[3].b[0]; \ - vram[VRAM_E + 1] = grcg.tile[3].b[0]; \ - } \ - (void)(v); \ -} - - -#define TCRRD8(p, a) { \ -const UINT8 *vram; \ - REG8 ret; \ - CPU_REMCLOCK -= MEMWAIT_GRCG; \ - vram = mem + LOW15(a) + ((p) * VRAM_STEP); \ - ret = 0; \ - if (!(grcg.modereg & 1)) { \ - ret |= vram[VRAM_B] ^ grcg.tile[0].b[0]; \ - } \ - if (!(grcg.modereg & 2)) { \ - ret |= vram[VRAM_R] ^ grcg.tile[1].b[0]; \ - } \ - if (!(grcg.modereg & 4)) { \ - ret |= vram[VRAM_G] ^ grcg.tile[2].b[0]; \ - } \ - if (!(grcg.modereg & 8)) { \ - ret |= vram[VRAM_E] ^ grcg.tile[3].b[0]; \ - } \ - return(ret ^ 0xff); \ -} - -#define TCRRD16(p, a) { \ -const UINT8 *vram; \ - REG16 ret; \ - CPU_REMCLOCK -= MEMWAIT_GRCG; \ - ret = 0; \ - vram = mem + LOW15(a) + ((p) * VRAM_STEP); \ - if (!(grcg.modereg & 1)) { \ - ret |= LOADINTELWORD(vram + VRAM_B) ^ grcg.tile[0].w; \ - } \ - if (!(grcg.modereg & 2)) { \ - ret |= LOADINTELWORD(vram + VRAM_R) ^ grcg.tile[1].w; \ - } \ - if (!(grcg.modereg & 4)) { \ - ret |= LOADINTELWORD(vram + VRAM_G) ^ grcg.tile[2].w; \ - } \ - if (!(grcg.modereg & 8)) { \ - ret |= LOADINTELWORD(vram + VRAM_E) ^ grcg.tile[3].w; \ - } \ - return((UINT16)(~ret)); \ -} - - - - - -// ---- functions - -REG8 MEMCALL memvram0_rd8(UINT32 address) VRAMRD8(0, address) -REG8 MEMCALL memvram1_rd8(UINT32 address) VRAMRD8(1, address) -REG16 MEMCALL memvram0_rd16(UINT32 address) VRAMRD16(0, address) -REG16 MEMCALL memvram1_rd16(UINT32 address) VRAMRD16(1, address) -UINT32 MEMCALL memvram0_rd32(UINT32 address){ - return (UINT32)memvram0_rd16(address)|(memvram0_rd16(address+2)<<16); -} -UINT32 MEMCALL memvram1_rd32(UINT32 address){ - return (UINT32)memvram1_rd16(address)|(memvram1_rd16(address+2)<<16); -} -void MEMCALL memvram0_wr8(UINT32 address, REG8 value) - VRAMWR8(0, address, value) -void MEMCALL memvram1_wr8(UINT32 address, REG8 value) - VRAMWR8(1, address, value) -void MEMCALL memvram0_wr16(UINT32 address, REG16 value) - VRAMWR16(0, address, value) -void MEMCALL memvram1_wr16(UINT32 address, REG16 value) - VRAMWR16(1, address, value) -void MEMCALL memvram0_wr32(UINT32 address, UINT32 value){ - memvram0_wr16(address, (REG16)value); - memvram0_wr16(address+2, (REG16)(value >> 16)); -} -void MEMCALL memvram1_wr32(UINT32 address, UINT32 value){ - memvram1_wr16(address, (REG16)value); - memvram1_wr16(address+2, (REG16)(value >> 16)); -} - -REG8 MEMCALL memtcr0_rd8(UINT32 address) TCRRD8(0, address) -REG8 MEMCALL memtcr1_rd8(UINT32 address) TCRRD8(1, address) -REG16 MEMCALL memtcr0_rd16(UINT32 address) TCRRD16(0, address) -REG16 MEMCALL memtcr1_rd16(UINT32 address) TCRRD16(1, address) -UINT32 MEMCALL memtcr0_rd32(UINT32 address){ - UINT32 r = (UINT32)memtcr0_rd16(address); - r |= (UINT32)memtcr0_rd16(address+2) << 16; - return r; -} -UINT32 MEMCALL memtcr1_rd32(UINT32 address){ - UINT32 r = (UINT32)memtcr1_rd16(address); - r |= (UINT32)memtcr1_rd16(address+2) << 16; - return r; -} - -void MEMCALL memrmw0_wr8(UINT32 address, REG8 value) - RMWWR8(0, address, value) -void MEMCALL memrmw1_wr8(UINT32 address, REG8 value) - RMWWR8(1, address, value) -void MEMCALL memrmw0_wr16(UINT32 address, REG16 value) - RMWWR16(0, address, value) -void MEMCALL memrmw1_wr16(UINT32 address, REG16 value) - RMWWR16(1, address, value) -void MEMCALL memrmw0_wr32(UINT32 address, UINT32 value){ - memrmw0_wr16(address, (REG16)value); - memrmw0_wr16(address+2, (REG16)(value >> 16)); -} -void MEMCALL memrmw1_wr32(UINT32 address, UINT32 value){ - memrmw1_wr16(address, (REG16)value); - memrmw1_wr16(address+2, (REG16)(value >> 16)); -} - -void MEMCALL memtdw0_wr8(UINT32 address, REG8 value) - TDWWR8(0, address, value) -void MEMCALL memtdw1_wr8(UINT32 address, REG8 value) - TDWWR8(1, address, value) -void MEMCALL memtdw0_wr16(UINT32 address, REG16 value) - TDWWR16(0, address, value) -void MEMCALL memtdw1_wr16(UINT32 address, REG16 value) - TDWWR16(1, address, value) -void MEMCALL memtdw0_wr32(UINT32 address, UINT32 value){ - memtdw0_wr16(address, (REG16)value); - memtdw0_wr16(address+2, (REG16)(value >> 16)); -} -void MEMCALL memtdw1_wr32(UINT32 address, UINT32 value){ - memtdw1_wr16(address, (REG16)value); - memtdw1_wr16(address+2, (REG16)(value >> 16)); -} - +#include +#include +#include +#include +#include +#include + + +// ---- macros + +#define VRAMRD8(p, a) { \ + CPU_REMCLOCK -= MEMWAIT_VRAM; \ + return(mem[(a) + ((p) * VRAM_STEP)]); \ +} + +#define VRAMRD16(p, a) { \ + CPU_REMCLOCK -= MEMWAIT_VRAM; \ + return(LOADINTELWORD(mem + (a) + ((p) * VRAM_STEP))); \ +} + +#define VRAMWR8(p, a, v) { \ + CPU_REMCLOCK -= MEMWAIT_VRAM; \ + mem[(a) + ((p) * VRAM_STEP)] = (UINT8)(v); \ + vramupdate[LOW15(a)] |= (1 << (p)); \ + gdcs.grphdisp |= (1 << (p)); \ +} + +#define VRAMWR16(p, a, v) { \ + CPU_REMCLOCK -= MEMWAIT_VRAM; \ + STOREINTELWORD(mem + (a) + ((p) * VRAM_STEP), (v)); \ + vramupdate[LOW15(a)] |= (1 << (p)); \ + vramupdate[LOW15((a) + 1)] |= (1 << (p)); \ + gdcs.grphdisp |= (1 << (p)); \ +} + + +#define RMWWR8(p, a, v) { \ + REG8 mask; \ + UINT8 *vram; \ + CPU_REMCLOCK -= MEMWAIT_GRCG; \ + mask = ~value; \ + (a) = LOW15((a)); \ + vramupdate[(a)] |= (1 << (p)); \ + gdcs.grphdisp |= (1 << (p)); \ + vram = mem + (a) + ((p) * VRAM_STEP); \ + if (!(grcg.modereg & 1)) { \ + vram[VRAM_B] &= mask; \ + vram[VRAM_B] |= ((v) & grcg.tile[0].b[0]); \ + } \ + if (!(grcg.modereg & 2)) { \ + vram[VRAM_R] &= mask; \ + vram[VRAM_R] |= ((v) & grcg.tile[1].b[0]); \ + } \ + if (!(grcg.modereg & 4)) { \ + vram[VRAM_G] &= mask; \ + vram[VRAM_G] |= ((v) & grcg.tile[2].b[0]); \ + } \ + if (!(grcg.modereg & 8)) { \ + vram[VRAM_E] &= mask; \ + vram[VRAM_E] |= ((v) & grcg.tile[3].b[0]); \ + } \ +} + +#define RMWWR16(p, a, v) { \ + UINT8 *vram; \ + CPU_REMCLOCK -= MEMWAIT_GRCG; \ + (a) = LOW15((a)); \ + vramupdate[(a) + 0] |= (1 << (p)); \ + vramupdate[(a) + 1] |= (1 << (p)); \ + gdcs.grphdisp |= (1 << (p)); \ + vram = mem + (a) + ((p) * VRAM_STEP); \ + if (!(grcg.modereg & 1)) { \ + UINT8 tmp; \ + tmp = (UINT8)(v); \ + vram[VRAM_B + 0] &= (~tmp); \ + vram[VRAM_B + 0] |= (tmp & grcg.tile[0].b[0]); \ + tmp = (UINT8)((v) >> 8); \ + vram[VRAM_B + 1] &= (~tmp); \ + vram[VRAM_B + 1] |= (tmp & grcg.tile[0].b[0]); \ + } \ + if (!(grcg.modereg & 2)) { \ + UINT8 tmp; \ + tmp = (UINT8)(v); \ + vram[VRAM_R + 0] &= (~tmp); \ + vram[VRAM_R + 0] |= (tmp & grcg.tile[1].b[0]); \ + tmp = (UINT8)((v) >> 8); \ + vram[VRAM_R + 1] &= (~tmp); \ + vram[VRAM_R + 1] |= (tmp & grcg.tile[1].b[0]); \ + } \ + if (!(grcg.modereg & 4)) { \ + UINT8 tmp; \ + tmp = (UINT8)(v); \ + vram[VRAM_G + 0] &= (~tmp); \ + vram[VRAM_G + 0] |= (tmp & grcg.tile[2].b[0]); \ + tmp = (UINT8)((v) >> 8); \ + vram[VRAM_G + 1] &= (~tmp); \ + vram[VRAM_G + 1] |= (tmp & grcg.tile[2].b[0]); \ + } \ + if (!(grcg.modereg & 8)) { \ + UINT8 tmp; \ + tmp = (UINT8)(v); \ + vram[VRAM_E + 0] &= (~tmp); \ + vram[VRAM_E + 0] |= (tmp & grcg.tile[3].b[0]); \ + tmp = (UINT8)((v) >> 8); \ + vram[VRAM_E + 1] &= (~tmp); \ + vram[VRAM_E + 1] |= (tmp & grcg.tile[3].b[0]); \ + } \ +} + + +#define TDWWR8(p, a, v) { \ + UINT8 *vram; \ + CPU_REMCLOCK -= MEMWAIT_GRCG; \ + (a) = LOW15(a); \ + vramupdate[(a)] |= (1 << (p)); \ + gdcs.grphdisp |= (1 << (p)); \ + vram = mem + (a) + ((p) * VRAM_STEP); \ + if (!(grcg.modereg & 1)) { \ + vram[VRAM_B] = grcg.tile[0].b[0]; \ + } \ + if (!(grcg.modereg & 2)) { \ + vram[VRAM_R] = grcg.tile[1].b[0]; \ + } \ + if (!(grcg.modereg & 4)) { \ + vram[VRAM_G] = grcg.tile[2].b[0]; \ + } \ + if (!(grcg.modereg & 8)) { \ + vram[VRAM_E] = grcg.tile[3].b[0]; \ + } \ + (void)(v); \ +} + +#define TDWWR16(p, a, v) { \ + UINT8 *vram; \ + CPU_REMCLOCK -= MEMWAIT_GRCG; \ + (a) = LOW15(a); \ + vramupdate[(a) + 0] |= (1 << (p)); \ + vramupdate[(a) + 1] |= (1 << (p)); \ + gdcs.grphdisp |= (1 << (p)); \ + vram = mem + (a) + ((p) * VRAM_STEP); \ + if (!(grcg.modereg & 1)) { \ + vram[VRAM_B + 0] = grcg.tile[0].b[0]; \ + vram[VRAM_B + 1] = grcg.tile[0].b[0]; \ + } \ + if (!(grcg.modereg & 2)) { \ + vram[VRAM_R + 0] = grcg.tile[1].b[0]; \ + vram[VRAM_R + 1] = grcg.tile[1].b[0]; \ + } \ + if (!(grcg.modereg & 4)) { \ + vram[VRAM_G + 0] = grcg.tile[2].b[0]; \ + vram[VRAM_G + 1] = grcg.tile[2].b[0]; \ + } \ + if (!(grcg.modereg & 8)) { \ + vram[VRAM_E + 0] = grcg.tile[3].b[0]; \ + vram[VRAM_E + 1] = grcg.tile[3].b[0]; \ + } \ + (void)(v); \ +} + + +#define TCRRD8(p, a) { \ +const UINT8 *vram; \ + REG8 ret; \ + CPU_REMCLOCK -= MEMWAIT_GRCG; \ + vram = mem + LOW15(a) + ((p) * VRAM_STEP); \ + ret = 0; \ + if (!(grcg.modereg & 1)) { \ + ret |= vram[VRAM_B] ^ grcg.tile[0].b[0]; \ + } \ + if (!(grcg.modereg & 2)) { \ + ret |= vram[VRAM_R] ^ grcg.tile[1].b[0]; \ + } \ + if (!(grcg.modereg & 4)) { \ + ret |= vram[VRAM_G] ^ grcg.tile[2].b[0]; \ + } \ + if (!(grcg.modereg & 8)) { \ + ret |= vram[VRAM_E] ^ grcg.tile[3].b[0]; \ + } \ + return(ret ^ 0xff); \ +} + +#define TCRRD16(p, a) { \ +const UINT8 *vram; \ + REG16 ret; \ + CPU_REMCLOCK -= MEMWAIT_GRCG; \ + ret = 0; \ + vram = mem + LOW15(a) + ((p) * VRAM_STEP); \ + if (!(grcg.modereg & 1)) { \ + ret |= LOADINTELWORD(vram + VRAM_B) ^ grcg.tile[0].w; \ + } \ + if (!(grcg.modereg & 2)) { \ + ret |= LOADINTELWORD(vram + VRAM_R) ^ grcg.tile[1].w; \ + } \ + if (!(grcg.modereg & 4)) { \ + ret |= LOADINTELWORD(vram + VRAM_G) ^ grcg.tile[2].w; \ + } \ + if (!(grcg.modereg & 8)) { \ + ret |= LOADINTELWORD(vram + VRAM_E) ^ grcg.tile[3].w; \ + } \ + return((UINT16)(~ret)); \ +} + + + + + +// ---- functions + +REG8 MEMCALL memvram0_rd8(UINT32 address) VRAMRD8(0, address) +REG8 MEMCALL memvram1_rd8(UINT32 address) VRAMRD8(1, address) +REG16 MEMCALL memvram0_rd16(UINT32 address) VRAMRD16(0, address) +REG16 MEMCALL memvram1_rd16(UINT32 address) VRAMRD16(1, address) +UINT32 MEMCALL memvram0_rd32(UINT32 address){ + return (UINT32)memvram0_rd16(address)|(memvram0_rd16(address+2)<<16); +} +UINT32 MEMCALL memvram1_rd32(UINT32 address){ + return (UINT32)memvram1_rd16(address)|(memvram1_rd16(address+2)<<16); +} +void MEMCALL memvram0_wr8(UINT32 address, REG8 value) + VRAMWR8(0, address, value) +void MEMCALL memvram1_wr8(UINT32 address, REG8 value) + VRAMWR8(1, address, value) +void MEMCALL memvram0_wr16(UINT32 address, REG16 value) + VRAMWR16(0, address, value) +void MEMCALL memvram1_wr16(UINT32 address, REG16 value) + VRAMWR16(1, address, value) +void MEMCALL memvram0_wr32(UINT32 address, UINT32 value){ + memvram0_wr16(address, (REG16)value); + memvram0_wr16(address+2, (REG16)(value >> 16)); +} +void MEMCALL memvram1_wr32(UINT32 address, UINT32 value){ + memvram1_wr16(address, (REG16)value); + memvram1_wr16(address+2, (REG16)(value >> 16)); +} + +REG8 MEMCALL memtcr0_rd8(UINT32 address) TCRRD8(0, address) +REG8 MEMCALL memtcr1_rd8(UINT32 address) TCRRD8(1, address) +REG16 MEMCALL memtcr0_rd16(UINT32 address) TCRRD16(0, address) +REG16 MEMCALL memtcr1_rd16(UINT32 address) TCRRD16(1, address) +UINT32 MEMCALL memtcr0_rd32(UINT32 address){ + UINT32 r = (UINT32)memtcr0_rd16(address); + r |= (UINT32)memtcr0_rd16(address+2) << 16; + return r; +} +UINT32 MEMCALL memtcr1_rd32(UINT32 address){ + UINT32 r = (UINT32)memtcr1_rd16(address); + r |= (UINT32)memtcr1_rd16(address+2) << 16; + return r; +} + +void MEMCALL memrmw0_wr8(UINT32 address, REG8 value) + RMWWR8(0, address, value) +void MEMCALL memrmw1_wr8(UINT32 address, REG8 value) + RMWWR8(1, address, value) +void MEMCALL memrmw0_wr16(UINT32 address, REG16 value) + RMWWR16(0, address, value) +void MEMCALL memrmw1_wr16(UINT32 address, REG16 value) + RMWWR16(1, address, value) +void MEMCALL memrmw0_wr32(UINT32 address, UINT32 value){ + memrmw0_wr16(address, (REG16)value); + memrmw0_wr16(address+2, (REG16)(value >> 16)); +} +void MEMCALL memrmw1_wr32(UINT32 address, UINT32 value){ + memrmw1_wr16(address, (REG16)value); + memrmw1_wr16(address+2, (REG16)(value >> 16)); +} + +void MEMCALL memtdw0_wr8(UINT32 address, REG8 value) + TDWWR8(0, address, value) +void MEMCALL memtdw1_wr8(UINT32 address, REG8 value) + TDWWR8(1, address, value) +void MEMCALL memtdw0_wr16(UINT32 address, REG16 value) + TDWWR16(0, address, value) +void MEMCALL memtdw1_wr16(UINT32 address, REG16 value) + TDWWR16(1, address, value) +void MEMCALL memtdw0_wr32(UINT32 address, UINT32 value){ + memtdw0_wr16(address, (REG16)value); + memtdw0_wr16(address+2, (REG16)(value >> 16)); +} +void MEMCALL memtdw1_wr32(UINT32 address, UINT32 value){ + memtdw1_wr16(address, (REG16)value); + memtdw1_wr16(address+2, (REG16)(value >> 16)); +} + diff --git a/mem/memvram.h b/mem/memvram.h old mode 100755 new mode 100644 index 748ea902..f9c7b0c8 --- a/mem/memvram.h +++ b/mem/memvram.h @@ -1,43 +1,43 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -REG8 MEMCALL memvram0_rd8(UINT32 address); -REG8 MEMCALL memvram1_rd8(UINT32 address); -REG16 MEMCALL memvram0_rd16(UINT32 address); -REG16 MEMCALL memvram1_rd16(UINT32 address); -UINT32 MEMCALL memvram0_rd32(UINT32 address); -UINT32 MEMCALL memvram1_rd32(UINT32 address); -void MEMCALL memvram0_wr8(UINT32 address, REG8 value); -void MEMCALL memvram1_wr8(UINT32 address, REG8 value); -void MEMCALL memvram0_wr16(UINT32 address, REG16 value); -void MEMCALL memvram1_wr16(UINT32 address, REG16 value); -void MEMCALL memvram0_wr32(UINT32 address, UINT32 value); -void MEMCALL memvram1_wr32(UINT32 address, UINT32 value); - -REG8 MEMCALL memtcr0_rd8(UINT32 address); -REG8 MEMCALL memtcr1_rd8(UINT32 address); -REG16 MEMCALL memtcr0_rd16(UINT32 address); -REG16 MEMCALL memtcr1_rd16(UINT32 address); -UINT32 MEMCALL memtcr0_rd32(UINT32 address); -UINT32 MEMCALL memtcr1_rd32(UINT32 address); - -void MEMCALL memrmw0_wr8(UINT32 address, REG8 value); -void MEMCALL memrmw1_wr8(UINT32 address, REG8 value); -void MEMCALL memrmw0_wr16(UINT32 address, REG16 value); -void MEMCALL memrmw1_wr16(UINT32 address, REG16 value); -void MEMCALL memrmw0_wr32(UINT32 address, UINT32 value); -void MEMCALL memrmw1_wr32(UINT32 address, UINT32 value); - -void MEMCALL memtdw0_wr8(UINT32 address, REG8 value); -void MEMCALL memtdw1_wr8(UINT32 address, REG8 value); -void MEMCALL memtdw0_wr16(UINT32 address, REG16 value); -void MEMCALL memtdw1_wr16(UINT32 address, REG16 value); -void MEMCALL memtdw0_wr32(UINT32 address, UINT32 value); -void MEMCALL memtdw1_wr32(UINT32 address, UINT32 value); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +REG8 MEMCALL memvram0_rd8(UINT32 address); +REG8 MEMCALL memvram1_rd8(UINT32 address); +REG16 MEMCALL memvram0_rd16(UINT32 address); +REG16 MEMCALL memvram1_rd16(UINT32 address); +UINT32 MEMCALL memvram0_rd32(UINT32 address); +UINT32 MEMCALL memvram1_rd32(UINT32 address); +void MEMCALL memvram0_wr8(UINT32 address, REG8 value); +void MEMCALL memvram1_wr8(UINT32 address, REG8 value); +void MEMCALL memvram0_wr16(UINT32 address, REG16 value); +void MEMCALL memvram1_wr16(UINT32 address, REG16 value); +void MEMCALL memvram0_wr32(UINT32 address, UINT32 value); +void MEMCALL memvram1_wr32(UINT32 address, UINT32 value); + +REG8 MEMCALL memtcr0_rd8(UINT32 address); +REG8 MEMCALL memtcr1_rd8(UINT32 address); +REG16 MEMCALL memtcr0_rd16(UINT32 address); +REG16 MEMCALL memtcr1_rd16(UINT32 address); +UINT32 MEMCALL memtcr0_rd32(UINT32 address); +UINT32 MEMCALL memtcr1_rd32(UINT32 address); + +void MEMCALL memrmw0_wr8(UINT32 address, REG8 value); +void MEMCALL memrmw1_wr8(UINT32 address, REG8 value); +void MEMCALL memrmw0_wr16(UINT32 address, REG16 value); +void MEMCALL memrmw1_wr16(UINT32 address, REG16 value); +void MEMCALL memrmw0_wr32(UINT32 address, UINT32 value); +void MEMCALL memrmw1_wr32(UINT32 address, UINT32 value); + +void MEMCALL memtdw0_wr8(UINT32 address, REG8 value); +void MEMCALL memtdw1_wr8(UINT32 address, REG8 value); +void MEMCALL memtdw0_wr16(UINT32 address, REG16 value); +void MEMCALL memtdw1_wr16(UINT32 address, REG16 value); +void MEMCALL memtdw0_wr32(UINT32 address, UINT32 value); +void MEMCALL memtdw1_wr32(UINT32 address, UINT32 value); + +#ifdef __cplusplus +} +#endif + diff --git a/misc/test_codecnv.c b/misc/test_codecnv.c old mode 100755 new mode 100644 index 931d8c9e..4de462c1 --- a/misc/test_codecnv.c +++ b/misc/test_codecnv.c @@ -1,102 +1,102 @@ -/* === codecnv test === (c) 2020 AZO */ -// Windows(MSVC): -// cl test_codecnv.c -DCODECNV_TEST ../codecnv/sjisucs2.c ../codecnv/ucs2sjis.c ../codecnv/ucs2ucs4.c ../codecnv/ucs2utf8.c ../codecnv/ucs4ucs2.c ../codecnv/ucs4utf8.c ../codecnv/utf8ucs2.c ../codecnv/utf8ucs4.c -I../ -I../common -utf-8 -Wall -// Windows(MSYS/MinGW): -// gcc test_codecnv.c -DCODECNV_TEST ../codecnv/sjisucs2.c ../codecnv/ucs2sjis.c ../codecnv/ucs2ucs4.c ../codecnv/ucs2utf8.c ../codecnv/ucs4ucs2.c ../codecnv/ucs4utf8.c ../codecnv/utf8ucs2.c ../codecnv/utf8ucs4.c -I../ -I../codecnv -Wall -Wextra -o test_codecnv -// Linux: -// gcc test_codecnv.c -DCODECNV_TEST ../codecnv/sjisucs2.c ../codecnv/ucs2sjis.c ../codecnv/ucs2ucs4.c ../codecnv/ucs2utf8.c ../codecnv/ucs4ucs2.c ../codecnv/ucs4utf8.c ../codecnv/utf8ucs2.c ../codecnv/utf8ucs4.c -I../ -I../codecnv -Wall -Wextra -o test_codecnv - -#include "compiler_base.h" -#include - -#define COUNT_BUFFER 256 - -char strU8String[COUNT_BUFFER]; -char strSJString[COUNT_BUFFER]; -UINT16 su16String[COUNT_BUFFER]; -UINT32 su32String[COUNT_BUFFER]; - -int main(int iArgc, char* strArgv[]) { - int i; - int iLen; - UINT uiCount; - - // test000 - printf("=== test000\n"); - strcpy(strU8String, "0123ABCコンニチハこんにちは今日は"); - iLen = strlen(strU8String); - printf("UTF-8 length: %d\n", iLen); - printf("UTF-8 string: %s\n", strU8String); - printf("UTF-8 code: "); - for(i = 0; i < iLen; i++) { - printf(" %02X", ((UINT8*)strU8String)[i]); - } - printf("\n"); - - // test001 : UTF-8 to UTF-32 - printf("=== test001 : UTF-8 to UTF-32\n"); - uiCount = codecnv_utf8toucs4(su32String, COUNT_BUFFER, strU8String, -1); - iLen = codecnv_ucs4len(su32String); - printf("UTF-32 count: %d\n", uiCount); - printf("UTF-32 length: %d\n", iLen); - printf("UTF-32 code: "); - for(i = 0; i < iLen; i++) { - printf(" %08X", su32String[i]); - } - printf("\n"); - - // test002 : UTF-32 to UTF-16 - printf("=== test002 : UTF-32 to UTF-16\n"); - uiCount = codecnv_ucs4toucs2(su16String, COUNT_BUFFER, su32String, -1); - iLen = codecnv_ucs2len(su16String); - printf("UTF-16 count: %d\n", uiCount); - printf("UTF-16 length: %d\n", iLen); - printf("UTF-16 code: "); - for(i = 0; i < iLen; i++) { - printf(" %04X", su16String[i]); - } - printf("\n"); - - // test003 : UTF-32 to UTF-8 - printf("=== test003 : UTF-32 to UTF-8\n"); - uiCount = codecnv_ucs4toutf8(strU8String, COUNT_BUFFER, su32String, -1); - iLen = strlen(strU8String); - printf("UTF-8 count: %d\n", uiCount); - printf("UTF-8 length: %d\n", iLen); - printf("UTF-8 string: %s\n", strU8String); - printf("UTF-8 code: "); - for(i = 0; i < iLen; i++) { - printf(" %02X", ((UINT8*)strU8String)[i]); - } - printf("\n"); - - // test004 : UTF-8 to UTF-16 - printf("=== test004 : UTF-8 to UTF-16\n"); - uiCount = codecnv_utf8toucs2(su16String, COUNT_BUFFER, strU8String, -1); - iLen = codecnv_ucs2len(su16String); - printf("UTF-16 count: %d\n", uiCount); - printf("UTF-16 length: %d\n", iLen); - printf("UTF-16 code: "); - for(i = 0; i < iLen; i++) { - printf(" %04X", su16String[i]); - } - printf("\n"); - - // test005 : UTF-16 to UTF-8 - printf("=== test005 : UTF-16 to UTF-8\n"); - uiCount = codecnv_ucs2toutf8(strU8String, COUNT_BUFFER, su16String, -1); - iLen = strlen(strU8String); - printf("UTF-8 count: %d\n", uiCount); - printf("UTF-8 length: %d\n", iLen); - printf("UTF-8 string: %s\n", strU8String); - printf("UTF-8 code: "); - for(i = 0; i < iLen; i++) { - printf(" %02X", ((UINT8*)strU8String)[i]); - } - printf("\n"); - - - - return 0; -} - +/* === codecnv test === (c) 2020 AZO */ +// Windows(MSVC): +// cl test_codecnv.c -DCODECNV_TEST ../codecnv/sjisucs2.c ../codecnv/ucs2sjis.c ../codecnv/ucs2ucs4.c ../codecnv/ucs2utf8.c ../codecnv/ucs4ucs2.c ../codecnv/ucs4utf8.c ../codecnv/utf8ucs2.c ../codecnv/utf8ucs4.c -I../ -I../common -utf-8 -Wall +// Windows(MSYS/MinGW): +// gcc test_codecnv.c -DCODECNV_TEST ../codecnv/sjisucs2.c ../codecnv/ucs2sjis.c ../codecnv/ucs2ucs4.c ../codecnv/ucs2utf8.c ../codecnv/ucs4ucs2.c ../codecnv/ucs4utf8.c ../codecnv/utf8ucs2.c ../codecnv/utf8ucs4.c -I../ -I../codecnv -Wall -Wextra -o test_codecnv +// Linux: +// gcc test_codecnv.c -DCODECNV_TEST ../codecnv/sjisucs2.c ../codecnv/ucs2sjis.c ../codecnv/ucs2ucs4.c ../codecnv/ucs2utf8.c ../codecnv/ucs4ucs2.c ../codecnv/ucs4utf8.c ../codecnv/utf8ucs2.c ../codecnv/utf8ucs4.c -I../ -I../codecnv -Wall -Wextra -o test_codecnv + +#include "compiler_base.h" +#include + +#define COUNT_BUFFER 256 + +char strU8String[COUNT_BUFFER]; +char strSJString[COUNT_BUFFER]; +UINT16 su16String[COUNT_BUFFER]; +UINT32 su32String[COUNT_BUFFER]; + +int main(int iArgc, char* strArgv[]) { + int i; + int iLen; + UINT uiCount; + + // test000 + printf("=== test000\n"); + strcpy(strU8String, "0123ABCコンニチハこんにちは今日は"); + iLen = strlen(strU8String); + printf("UTF-8 length: %d\n", iLen); + printf("UTF-8 string: %s\n", strU8String); + printf("UTF-8 code: "); + for(i = 0; i < iLen; i++) { + printf(" %02X", ((UINT8*)strU8String)[i]); + } + printf("\n"); + + // test001 : UTF-8 to UTF-32 + printf("=== test001 : UTF-8 to UTF-32\n"); + uiCount = codecnv_utf8toucs4(su32String, COUNT_BUFFER, strU8String, -1); + iLen = codecnv_ucs4len(su32String); + printf("UTF-32 count: %d\n", uiCount); + printf("UTF-32 length: %d\n", iLen); + printf("UTF-32 code: "); + for(i = 0; i < iLen; i++) { + printf(" %08X", su32String[i]); + } + printf("\n"); + + // test002 : UTF-32 to UTF-16 + printf("=== test002 : UTF-32 to UTF-16\n"); + uiCount = codecnv_ucs4toucs2(su16String, COUNT_BUFFER, su32String, -1); + iLen = codecnv_ucs2len(su16String); + printf("UTF-16 count: %d\n", uiCount); + printf("UTF-16 length: %d\n", iLen); + printf("UTF-16 code: "); + for(i = 0; i < iLen; i++) { + printf(" %04X", su16String[i]); + } + printf("\n"); + + // test003 : UTF-32 to UTF-8 + printf("=== test003 : UTF-32 to UTF-8\n"); + uiCount = codecnv_ucs4toutf8(strU8String, COUNT_BUFFER, su32String, -1); + iLen = strlen(strU8String); + printf("UTF-8 count: %d\n", uiCount); + printf("UTF-8 length: %d\n", iLen); + printf("UTF-8 string: %s\n", strU8String); + printf("UTF-8 code: "); + for(i = 0; i < iLen; i++) { + printf(" %02X", ((UINT8*)strU8String)[i]); + } + printf("\n"); + + // test004 : UTF-8 to UTF-16 + printf("=== test004 : UTF-8 to UTF-16\n"); + uiCount = codecnv_utf8toucs2(su16String, COUNT_BUFFER, strU8String, -1); + iLen = codecnv_ucs2len(su16String); + printf("UTF-16 count: %d\n", uiCount); + printf("UTF-16 length: %d\n", iLen); + printf("UTF-16 code: "); + for(i = 0; i < iLen; i++) { + printf(" %04X", su16String[i]); + } + printf("\n"); + + // test005 : UTF-16 to UTF-8 + printf("=== test005 : UTF-16 to UTF-8\n"); + uiCount = codecnv_ucs2toutf8(strU8String, COUNT_BUFFER, su16String, -1); + iLen = strlen(strU8String); + printf("UTF-8 count: %d\n", uiCount); + printf("UTF-8 length: %d\n", iLen); + printf("UTF-8 string: %s\n", strU8String); + printf("UTF-8 code: "); + for(i = 0; i < iLen; i++) { + printf(" %02X", ((UINT8*)strU8String)[i]); + } + printf("\n"); + + + + return 0; +} + diff --git a/misc/test_milstr.c b/misc/test_milstr.c old mode 100755 new mode 100644 index a74375e5..b2d3a881 --- a/misc/test_milstr.c +++ b/misc/test_milstr.c @@ -1,79 +1,79 @@ -/* === milstr test === (c) 2020 AZO */ -// Windows(MSVC): -// cl test_milstr.c -DMILSTR_TEST ../common/milstr.c -I../ -I../common -utf-8 -Wall -// Windows(MSYS/MinGW): -// gcc test_milstr.c -DMILSTR_TEST ../common/milstr.c -I../ -I../common -Wall -Wextra -o test_milstr -// Linux: -// gcc test_milstr.c -DMILSTR_TEST ../common/milstr.c -I../ -I../common -Wall -Wextra -o test_milstr - -/* -・UTF-8で統一したい。(でも未来ではまた変わってるんだろうな) - ソース、スクリプト、Webなどのテキスト世界ではUTF-8が定着しつつある。 -・milstrで全てを吸収・解決したい。 -・ワイド文字(wchar_t)の存在も忘れちゃいけない。 -・文字列取り扱いのセキュリティ対応 - -このプログラムで動作をチェックしつつ、compiler.hに設定していけばいいかなと。 -※このプログラムは、MILSTR_TEST で compiler.h を無効にしている。 - -コンピュータの成り立ちから連綿と続く未解決な「文字」紛争、バベルの塔の再建。 -(欧米が先行し、他地域の文化・文字を理解するのに時間がかかる) - -バイト文字。文字はUTF-8(8-32bit)。既存char・main()がそのまま使える。 -ワイド文字。文字はWindowsで16bit(UTF-16)、他は32bit(UTF-32)。既存char・main()は使えない。 -milstrは前者を軸にして、後者をサポートする。 - -バイト文字→難易度HARD・自由度○・移植性○・セキュリティ△ -ワイド文字→難易度EASY・自由度△・移植性✕・セキュリティ○ -アセンブリはVERY HARDですかそうですかw - -char(文字)型=1Byteという掟は変わらないが、int8_tで代用出来るはず。 -※BYTEやuint8_tでの代用が望ましいが、 - Unicodeの「次Byteに続く」フラグがbit7なので、正負で分けちゃう人もきっと多い。 - if((uint8_t)c & 0x80) より if(c < 0) の方がCPU処理は速い、はず。 - -VC++のCString、std::stringクラスはTCHAR.Hのラッパーで、 -_UNICODE・UNICODEなし:バイト文字 -_UNICODE・UNICODEあり:ワイド文字 - -文字列で注意しなければならないのが、バッファオーバーラン。 -多少重くなっても、バッファサイズ(0以上)は必ず考慮する。 -処理内でポインタ戻りをする時も厳重注意。バッファアンダーラン。 -OK: strnlen strncpy snprintf -ダメ: strlen strcpy sprintf - -OEM?mil?何なんでしょう。 -NPCHAR、NPTEXTにしたいニャン。(NP3が出るかもしれないからね) - -C/C++20のワイド文字でchar8_t・char16_t・char32_tが登場予定。 - -・廃止予定 -OEMCHAR : charのみ -OEMTEXT : 標準文字列のみ - -milank、mileucはお役御免、かな。milsjisもそのうち・・・。 -ANK=Alphabet Numeric Katakana=1Byte。 -*/ - -#include - -#define COUNT_BUFFER 256 - -char strString1[COUNT_BUFFER]; -char strString2[COUNT_BUFFER]; - -int main(int iArgc, char* strArgv[]) { - // test000 : OEMSTRCPY, OEMPRINTFSTR - OEMPRINTFSTR("* test000 : OEMSTRCPY(OEMSTRNCPY), OEMPRINTFSTR(OEMPRINTF)" OEMNEWLINE); - OEMSTRCPY(strString1, "000output" OEMNEWLINE); - OEMPRINTFSTR(strString1); - OEMSTRCPY(strString1, "000アウトプット" OEMNEWLINE); - OEMPRINTFSTR(strString1); - OEMSTRCPY(strString1, "000アウトプット" OEMNEWLINE); - OEMPRINTFSTR(strString1); - OEMSTRCPY(strString1, "000出力" OEMNEWLINE); - OEMPRINTFSTR(strString1); - - return 0; -} - +/* === milstr test === (c) 2020 AZO */ +// Windows(MSVC): +// cl test_milstr.c -DMILSTR_TEST ../common/milstr.c -I../ -I../common -utf-8 -Wall +// Windows(MSYS/MinGW): +// gcc test_milstr.c -DMILSTR_TEST ../common/milstr.c -I../ -I../common -Wall -Wextra -o test_milstr +// Linux: +// gcc test_milstr.c -DMILSTR_TEST ../common/milstr.c -I../ -I../common -Wall -Wextra -o test_milstr + +/* +・UTF-8で統一したい。(でも未来ではまた変わってるんだろうな) + ソース、スクリプト、Webなどのテキスト世界ではUTF-8が定着しつつある。 +・milstrで全てを吸収・解決したい。 +・ワイド文字(wchar_t)の存在も忘れちゃいけない。 +・文字列取り扱いのセキュリティ対応 + +このプログラムで動作をチェックしつつ、compiler.hに設定していけばいいかなと。 +※このプログラムは、MILSTR_TEST で compiler.h を無効にしている。 + +コンピュータの成り立ちから連綿と続く未解決な「文字」紛争、バベルの塔の再建。 +(欧米が先行し、他地域の文化・文字を理解するのに時間がかかる) + +バイト文字。文字はUTF-8(8-32bit)。既存char・main()がそのまま使える。 +ワイド文字。文字はWindowsで16bit(UTF-16)、他は32bit(UTF-32)。既存char・main()は使えない。 +milstrは前者を軸にして、後者をサポートする。 + +バイト文字→難易度HARD・自由度○・移植性○・セキュリティ△ +ワイド文字→難易度EASY・自由度△・移植性✕・セキュリティ○ +アセンブリはVERY HARDですかそうですかw + +char(文字)型=1Byteという掟は変わらないが、int8_tで代用出来るはず。 +※BYTEやuint8_tでの代用が望ましいが、 + Unicodeの「次Byteに続く」フラグがbit7なので、正負で分けちゃう人もきっと多い。 + if((uint8_t)c & 0x80) より if(c < 0) の方がCPU処理は速い、はず。 + +VC++のCString、std::stringクラスはTCHAR.Hのラッパーで、 +_UNICODE・UNICODEなし:バイト文字 +_UNICODE・UNICODEあり:ワイド文字 + +文字列で注意しなければならないのが、バッファオーバーラン。 +多少重くなっても、バッファサイズ(0以上)は必ず考慮する。 +処理内でポインタ戻りをする時も厳重注意。バッファアンダーラン。 +OK: strnlen strncpy snprintf +ダメ: strlen strcpy sprintf + +OEM?mil?何なんでしょう。 +NPCHAR、NPTEXTにしたいニャン。(NP3が出るかもしれないからね) + +C/C++20のワイド文字でchar8_t・char16_t・char32_tが登場予定。 + +・廃止予定 +OEMCHAR : charのみ +OEMTEXT : 標準文字列のみ + +milank、mileucはお役御免、かな。milsjisもそのうち・・・。 +ANK=Alphabet Numeric Katakana=1Byte。 +*/ + +#include + +#define COUNT_BUFFER 256 + +char strString1[COUNT_BUFFER]; +char strString2[COUNT_BUFFER]; + +int main(int iArgc, char* strArgv[]) { + // test000 : OEMSTRCPY, OEMPRINTFSTR + OEMPRINTFSTR("* test000 : OEMSTRCPY(OEMSTRNCPY), OEMPRINTFSTR(OEMPRINTF)" OEMNEWLINE); + OEMSTRCPY(strString1, "000output" OEMNEWLINE); + OEMPRINTFSTR(strString1); + OEMSTRCPY(strString1, "000アウトプット" OEMNEWLINE); + OEMPRINTFSTR(strString1); + OEMSTRCPY(strString1, "000アウトプット" OEMNEWLINE); + OEMPRINTFSTR(strString1); + OEMSTRCPY(strString1, "000出力" OEMNEWLINE); + OEMPRINTFSTR(strString1); + + return 0; +} + diff --git a/network/lgy98.c b/network/lgy98.c old mode 100755 new mode 100644 index dc979c65..a07e3a3b --- a/network/lgy98.c +++ b/network/lgy98.c @@ -1,1125 +1,1125 @@ -/* - * QEMU NE2000 emulation - * - * Copyright (c) 2003-2004 Fabrice Bellard - * - * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* - * 注意:このファイルのオリジナルはQEMUのne2000.cですが、大幅な改変が行われています。 - */ - -#include - -#if defined(SUPPORT_LGY98) - -#include -#include -#include -#include -#include -#include -#include - -#if defined(_MSC_VER) -#define strdup _strdup -#endif - -// XXX: -#ifndef _countof -#define _countof(a) (sizeof(a) / sizeof((a)[0])) -#endif - -#define MAX_ETH_FRAME_SIZE 1514 - -#define E8390_CMD 0x00 /* The command register (for all pages) */ -/* Page 0 register offsets. */ -#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */ -#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */ -#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */ -#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */ -#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */ -#define EN0_TSR 0x04 /* Transmit status reg RD */ -#define EN0_TPSR 0x04 /* Transmit starting page WR */ -#define EN0_NCR 0x05 /* Number of collision reg RD */ -#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */ -#define EN0_FIFO 0x06 /* FIFO RD */ -#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */ -#define EN0_ISR 0x07 /* Interrupt status reg RD WR */ -#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */ -#define EN0_RSARLO 0x08 /* Remote start address reg 0 */ -#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */ -#define EN0_RSARHI 0x09 /* Remote start address reg 1 */ -#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */ -#define EN0_RTL8029ID0 0x0a /* Realtek ID byte #1 RD */ -#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */ -#define EN0_RTL8029ID1 0x0b /* Realtek ID byte #2 RD */ -#define EN0_RSR 0x0c /* rx status reg RD */ -#define EN0_RXCR 0x0c /* RX configuration reg WR */ -#define EN0_TXCR 0x0d /* TX configuration reg WR */ -#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */ -#define EN0_DCFG 0x0e /* Data configuration reg WR */ -#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */ -#define EN0_IMR 0x0f /* Interrupt mask reg WR */ -#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */ - -#define EN1_PHYS 0x11 -#define EN1_CURPAG 0x17 -#define EN1_MULT 0x18 - -#define EN2_STARTPG 0x21 /* Starting page of ring bfr RD */ -#define EN2_STOPPG 0x22 /* Ending page +1 of ring bfr RD */ - -#define EN3_CONFIG0 0x33 -#define EN3_CONFIG1 0x34 -#define EN3_CONFIG2 0x35 -#define EN3_CONFIG3 0x36 - -/* Register accessed at EN_CMD, the 8390 base addr. */ -#define E8390_STOP 0x01 /* Stop and reset the chip */ -#define E8390_START 0x02 /* Start the chip, clear reset */ -#define E8390_TRANS 0x04 /* Transmit a frame */ -#define E8390_RREAD 0x08 /* Remote read */ -#define E8390_RWRITE 0x10 /* Remote write */ -#define E8390_NODMA 0x20 /* Remote DMA */ -#define E8390_PAGE0 0x00 /* Select page chip registers */ -#define E8390_PAGE1 0x40 /* using the two high-order bits */ -#define E8390_PAGE2 0x80 /* Page 3 is invalid. */ - -/* Bits in EN0_ISR - Interrupt status register */ -#define ENISR_RX 0x01 /* Receiver, no error */ -#define ENISR_TX 0x02 /* Transmitter, no error */ -#define ENISR_RX_ERR 0x04 /* Receiver, with error */ -#define ENISR_TX_ERR 0x08 /* Transmitter, with error */ -#define ENISR_OVER 0x10 /* Receiver overwrote the ring */ -#define ENISR_COUNTERS 0x20 /* Counters need emptying */ -#define ENISR_RDC 0x40 /* remote dma complete */ -#define ENISR_RESET 0x80 /* Reset completed */ -#define ENISR_ALL 0x3f /* Interrupts we will enable */ - -/* Bits in received packet status byte and EN0_RSR*/ -#define ENRSR_RXOK 0x01 /* Received a good packet */ -#define ENRSR_CRC 0x02 /* CRC error */ -#define ENRSR_FAE 0x04 /* frame alignment error */ -#define ENRSR_FO 0x08 /* FIFO overrun */ -#define ENRSR_MPA 0x10 /* missed pkt */ -#define ENRSR_PHY 0x20 /* physical/multicast address */ -#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ -#define ENRSR_DEF 0x80 /* deferring */ - -/* Transmitted packet status, EN0_TSR. */ -#define ENTSR_PTX 0x01 /* Packet transmitted without error */ -#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */ -#define ENTSR_COL 0x04 /* The transmit collided at least once. */ -#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */ -#define ENTSR_CRS 0x10 /* The carrier sense was lost. */ -#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */ -#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */ -#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */ - - - LGY98 lgy98 = {0}; - LGY98CFG lgy98cfg = {0}; - - VLANClientState *lgy98vc = NULL; - - -//UINT lgy98_baseaddr = 0x10D0; -//UINT ne2000_baseaddr = 0x0200; - -static void ne2000_reset(LGY98 *s) -{ - int i; - - s->isr = ENISR_RESET; - memcpy(s->mem, s->macaddr, 6); - s->mem[14] = 0x57; - s->mem[15] = 0x57; - - /* duplicate prom data */ - for(i = 15;i >= 0; i--) { - s->mem[2 * i] = s->mem[i]; - s->mem[2 * i + 1] = s->mem[i]; - } -} - -static void ne2000_update_irq(LGY98 *s) -{ - static int irqflag = 0; - static unsigned long irqtime = 0; // WORKAROUND 短期間で割り込みし続けると暴走する問題を回避 - int isr; - isr = (s->isr & s->imr) & 0x7f; - //qemu_set_irq(s->irq, (isr != 0)); - if(isr != 0){ - if(irqflag && GETTICK()-irqtime > 2){ - irqflag = 0; // 2ms経過したら再割り込みOKとする - } - if(!irqflag) { - pic_setirq(s->irq); - irqtime = GETTICK(); - } - irqflag = 1; - }else{ - pic_resetirq(s->irq); - irqflag = 0; - } -} - -static void ne2000_mem_writeb(LGY98 *s, UINT32 addr, UINT32 val) -{ - if (addr < 32 || - (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { - s->mem[addr] = val; - } -} - -static void ne2000_mem_writew(LGY98 *s, UINT32 addr, UINT32 val) -{ - addr &= ~1; /* XXX: check exact behaviour if not even */ - if (addr < 32 || - (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { - //*(UINT16 *)(s->mem + addr) = cpu_to_le16(val); - STOREINTELWORD(s->mem + addr, val); - } -} - -static void ne2000_mem_writel(LGY98 *s, UINT32 addr, UINT32 val) -{ - addr &= ~1; /* XXX: check exact behaviour if not even */ - if (addr < 32 || - (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { - //cpu_to_le32wu((UINT32 *)(s->mem + addr), val); - STOREINTELDWORD(s->mem + addr, val); - } -} - -static UINT32 ne2000_mem_readb(LGY98 *s, UINT32 addr) -{ - if (addr < 32 || - (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { - return s->mem[addr]; - } else { - return 0xff; - } -} - -static UINT32 ne2000_mem_readw(LGY98 *s, UINT32 addr) -{ - UINT16 ret = 0xffff; - addr &= ~1; /* XXX: check exact behaviour if not even */ - if (addr < 32 || - (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { - //return le16_to_cpu(*(UINT16 *)(s->mem + addr)); - ret = LOADINTELWORD(s->mem + addr); - } - return (UINT32)ret; -} - -static UINT32 ne2000_mem_readl(LGY98 *s, UINT32 addr) -{ - UINT32 ret = 0xffffffff; - addr &= ~1; /* XXX: check exact behaviour if not even */ - if (addr < 32 || - (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { - //return le32_to_cpupu((UINT32 *)(s->mem + addr)); - ret = LOADINTELDWORD(s->mem + addr); - } - return ret; -} - -static void ne2000_dma_update(LGY98 *s, int len) -{ - s->rsar += len; - /* wrap */ - /* XXX: check what to do if rsar > stop */ - if (s->rsar == s->stop) - s->rsar = s->start; - - if (s->rcnt <= len) { - s->rcnt = 0; - /* signal end of transfer */ - s->isr |= ENISR_RDC; - s->cmd |= E8390_NODMA; /* コマンドレジスタにDMA完了ビットを立てる */ - ne2000_update_irq(s); - // TRACEOUT(("LGY-98: DMA_IRQ")); - } else { - s->rcnt -= len; - } -} - -void ne2000_send_packet(VLANClientState *vc1, const UINT8 *buf, int size) -{ - VLANState *vlan = vc1->vlan; - LGY98 *s = (LGY98*)vc1->opaque; - //VLANClientState *vc; - - if (vc1->link_down) - return; - -#ifdef DEBUG_NET - printf("vlan %d send:\n", vlan->id); - hex_dump(stdout, buf, size); -#endif - np2net.send_packet((UINT8*)buf, size); -} - - -#define MIN_BUF_SIZE 60 - -static void pc98_ne2000_cleanup(VLANClientState *vc) -{ - LGY98 *s = (LGY98*)vc->opaque; - - //unregister_savevm("ne2000", s); - - //isa_unassign_ioport(s->isa_io_base, 16); - //isa_unassign_ioport(s->isa_io_base + 0x200, 2); - //isa_unassign_ioport(s->isa_io_base + 0x300, 16); - //isa_unassign_ioport(s->isa_io_base + 0x18, 1); - - //qemu_free(s); -} - -static int ne2000_buffer_full(LGY98 *s) -{ - int avail, index, boundary; - - index = s->curpag << 8; - boundary = s->boundary << 8; - if (index < boundary) - avail = boundary - index; - else - avail = (s->stop - s->start) - (index - boundary); - if (avail < (MAX_ETH_FRAME_SIZE + 4)) - return 1; - return 0; -} - -static int ne2000_can_receive(void *opaque) -{ - LGY98 *s = (LGY98*)opaque; - - if (s->cmd & E8390_STOP) - return 1; - return !ne2000_buffer_full(s); -} - -/* From FreeBSD */ -static int compute_mcast_idx(const UINT8 *ep) -{ - UINT32 crc; - int carry, i, j; - UINT8 b; - - crc = 0xffffffff; - for (i = 0; i < 6; i++) { - b = *ep++; - for (j = 0; j < 8; j++) { - carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); - crc <<= 1; - b >>= 1; - if (carry) - crc = ((crc ^ 0x04c11db6) | carry); - } - } - return (crc >> 26); -} - -static void ne2000_receive(void *opaque, const UINT8 *buf, int size) -{ - LGY98 *s = &lgy98; - UINT8 *p; - unsigned int total_len, next, avail, len, index, mcast_idx; - UINT8 buf1[60]; - static const UINT8 broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - -#if defined(DEBUG_NE2000) - printf("NE2000: received len=%d\n", size); -#endif - - if (s->cmd & E8390_STOP || ne2000_buffer_full(s)) - return; - if (size >= s->stop - s->start - 0x100) - return; // 巨大パケットは捨てる - - - /* XXX: check this */ - if (s->rxcr & 0x10) { - /* promiscuous: receive all */ - } else { - if (!memcmp(buf, broadcast_macaddr, 6)) { - /* broadcast address */ - if (!(s->rxcr & 0x04)) - return; - } else if (buf[0] & 0x01) { - /* multicast */ - if (!(s->rxcr & 0x08)) - return; - mcast_idx = compute_mcast_idx(buf); - if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) - return; - } else if (s->mem[0] == buf[0] && - s->mem[2] == buf[1] && - s->mem[4] == buf[2] && - s->mem[6] == buf[3] && - s->mem[8] == buf[4] && - s->mem[10] == buf[5]) { - /* match */ - } else { - return; - } - } - - - /* if too small buffer, then expand it */ - if (size < MIN_BUF_SIZE) { - memcpy(buf1, buf, size); - memset(buf1 + size, 0, MIN_BUF_SIZE - size); - buf = buf1; - size = MIN_BUF_SIZE; - } - - index = s->curpag << 8; - /* 4 bytes for header */ - total_len = size + 4; - /* address for next packet (4 bytes for CRC) */ - next = index + ((total_len + 4 + 255) & ~0xff); - if (next >= s->stop) - next -= (s->stop - s->start); - /* prepare packet header */ - p = s->mem + index; - s->rsr = ENRSR_RXOK; /* receive status */ - /* XXX: check this */ - if (buf[0] & 0x01) - s->rsr |= ENRSR_PHY; - p[0] = s->rsr; - p[1] = next >> 8; - p[2] = total_len; - p[3] = total_len >> 8; - index += 4; - - /* write packet data */ - while (size > 0) { - if (index <= s->stop) - avail = s->stop - index; - else - avail = 0; - len = size; - if (len > avail) - len = avail; - memcpy(s->mem + index, buf, len); - buf += len; - index += len; - if (index == s->stop) - index = s->start; - size -= len; - } - s->curpag = next >> 8; - - /* now we can signal we have received something */ - s->isr |= ENISR_RX; - ne2000_update_irq(s); - //TRACEOUT(("LGY-98: RCV_IRQ")); -} - - - - -// ************************** I/O PORT ************** - -static void IOOUTCALL lgy98_ob000(UINT addr, REG8 dat) { - int offset, page, index; - UINT32 val = dat; - LGY98 *s = &lgy98; - - //TRACEOUT(("LGY-98: out %04X d=%02X", addr, dat)); - addr &= 0xf; - if (addr == E8390_CMD) { - /* control register */ - s->cmd = dat; - if (!(dat & E8390_STOP)) { /* START bit makes no sense on RTL8029... */ - s->isr &= ~ENISR_RESET; - /* test specific case: zero length transfer */ - if ((dat & (E8390_RREAD | E8390_RWRITE)) && - s->rcnt == 0) { - s->isr |= ENISR_RDC; - ne2000_update_irq(s); - //TRACEOUT(("LGY-98: RRW_IRQ")); - } - if (dat & E8390_TRANS) { - index = (lgy98.tpsr << 8); - /* XXX: next 2 lines are a hack to make netware 3.11 work */ - if (index >= NE2000_PMEM_END) - index -= NE2000_PMEM_SIZE; - /* fail safe: check range on the transmitted length */ - if (index + s->tcnt <= NE2000_PMEM_END) { - ne2000_send_packet(lgy98vc, s->mem + index, s->tcnt); - } - /* signal end of transfer */ - s->tsr = ENTSR_PTX; - s->isr |= ENISR_TX; - s->cmd &= ~E8390_TRANS; - //TRACEOUT(("LGY-98: SEND_IRQ")); - ne2000_update_irq(s); - } - } - } else { - page = s->cmd >> 6; - offset = addr | (page << 4); - switch(offset) { - case EN0_STARTPG: - s->start = val << 8; - break; - case EN0_STOPPG: - s->stop = val << 8; - break; - case EN0_BOUNDARY: - s->boundary = val; - break; - case EN0_IMR: - s->imr = val; - //TRACEOUT(("LGY-98: IMR_IRQ")); - //pic_resetirq(s->irq); - ne2000_update_irq(s); - break; - case EN0_TPSR: - s->tpsr = val; - break; - case EN0_TCNTLO: - s->tcnt = (s->tcnt & 0xff00) | val; - break; - case EN0_TCNTHI: - s->tcnt = (s->tcnt & 0x00ff) | (val << 8); - break; - case EN0_RSARLO: - s->rsar = (s->rsar & 0xff00) | val; - break; - case EN0_RSARHI: - s->rsar = (s->rsar & 0x00ff) | (val << 8); - break; - case EN0_RCNTLO: - s->rcnt = (s->rcnt & 0xff00) | val; - break; - case EN0_RCNTHI: - s->rcnt = (s->rcnt & 0x00ff) | (val << 8); - break; - case EN0_RXCR: - s->rxcr = val; - break; - case EN0_DCFG: - s->dcfg = val; - break; - case EN0_ISR: - s->isr &= ~(val & 0x7f); - //TRACEOUT(("LGY-98: ISR_IRQ")); - //pic_resetirq(s->irq); - ne2000_update_irq(s); - break; - case EN1_PHYS: - case EN1_PHYS + 1: - case EN1_PHYS + 2: - case EN1_PHYS + 3: - case EN1_PHYS + 4: - case EN1_PHYS + 5: - s->phys[offset - EN1_PHYS] = val; - break; - case EN1_CURPAG: - s->curpag = val; - break; - case EN1_MULT: - case EN1_MULT + 1: - case EN1_MULT + 2: - case EN1_MULT + 3: - case EN1_MULT + 4: - case EN1_MULT + 5: - case EN1_MULT + 6: - case EN1_MULT + 7: - s->mult[offset - EN1_MULT] = val; - break; - } - } - (void)addr; - (void)dat; -} -static REG8 IOINPCALL lgy98_ib000(UINT addr) { - int ret = 0; - int offset, page; - LGY98 *s = &lgy98; - - //pic_resetirq(s->irq); - //TRACEOUT(("LGY-98: inp %04X", addr)); - addr = (addr & 0xf); - if (addr == E8390_CMD) { - ret = s->cmd; - } else { - page = s->cmd >> 6; - offset = addr | (page << 4); - switch(offset) { - case EN0_TSR: - ret = s->tsr; - break; - case EN0_BOUNDARY: - ret = s->boundary; - break; - case EN0_ISR: - ret = s->isr; - break; - case EN0_RSARLO: - ret = s->rsar & 0x00ff; - break; - case EN0_RSARHI: - ret = s->rsar >> 8; - break; - case EN1_PHYS: - case EN1_PHYS + 1: - case EN1_PHYS + 2: - case EN1_PHYS + 3: - case EN1_PHYS + 4: - case EN1_PHYS + 5: - ret = s->phys[offset - EN1_PHYS]; - break; - case EN1_CURPAG: - ret = s->curpag; - break; - case EN1_MULT: - case EN1_MULT + 1: - case EN1_MULT + 2: - case EN1_MULT + 3: - case EN1_MULT + 4: - case EN1_MULT + 5: - case EN1_MULT + 6: - case EN1_MULT + 7: - ret = s->mult[offset - EN1_MULT]; - break; - case EN0_RSR: - ret = s->rsr; - break; - case EN2_STARTPG: - ret = s->start >> 8; - break; - case EN2_STOPPG: - ret = s->stop >> 8; - break; - case EN0_RTL8029ID0: - ret = 0x29; - break; - case EN0_RTL8029ID1: - ret = 0x43; - break; - case EN3_CONFIG0: - ret = 0; /* 10baseT media */ - break; - case EN3_CONFIG2: - ret = 0x40; /* 10baseT active */ - break; - case EN3_CONFIG3: - ret = 0x40; /* Full duplex */ - break; - default: - ret = 0x00; - break; - } - } - return (REG8)ret; -} -void IOOUTCALL lgy98_ob200_8(UINT addr, REG8 dat) { - UINT32 val = dat; - LGY98 *s = &lgy98; - - //pic_resetirq(s->irq); - if (s->rcnt == 0) - return; - if(s->dcfg & 0x01){ - ne2000_mem_writew(s, s->rsar, val); - ne2000_dma_update(s, 2); - return; - }else{ - //if (s->dcfg & 0x01) { - // /* 16 bit access */ - // ne2000_mem_writew(s, s->rsar, val); - // ne2000_dma_update(s, 2); - //} else { - /* 8 bit access */ - //TRACEOUT(("LGY-98: 8 bit write")); - ne2000_mem_writeb(s, s->rsar, val); - ne2000_dma_update(s, 1); - //} - } - (void)addr; - (void)dat; -} -REG8 IOINPCALL lgy98_ib200_8(UINT addr) { - int ret = 0; - LGY98 *s = &lgy98; - - //pic_resetirq(s->irq); - if(s->dcfg & 0x01){ - ret = ne2000_mem_readw(s, s->rsar); - ne2000_dma_update(s, 2); - return (REG8)ret; - }else{ - //TRACEOUT(("LGY-98: 8 bit read")); - /* 8 bit access */ - ret = ne2000_mem_readb(s, s->rsar); - ne2000_dma_update(s, 1); -#ifdef DEBUG_NE2000 - printf("NE2000: asic read val=0x%04x\n", ret); -#endif - return (REG8)ret; - } -} -void IOOUTCALL lgy98_ob200_16(UINT addr, REG16 dat) { - UINT32 val = dat; - LGY98 *s = &lgy98; - - //pic_resetirq(s->irq); - if (s->rcnt == 0) - return; - if(s->dcfg & 0x01){ - /* 16 bit access */ - //TRACEOUT(("LGY-98: 16 bit write")); - ne2000_mem_writew(s, s->rsar, val); - ne2000_dma_update(s, 2); - }else{ - ne2000_mem_writeb(s, s->rsar, val); - ne2000_dma_update(s, 1); - } - (void)addr; - (void)dat; -} -REG16 IOINPCALL lgy98_ib200_16(UINT addr) { - int ret = 0; - LGY98 *s = &lgy98; - - //pic_resetirq(s->irq); - if(s->dcfg & 0x01){ - /* 16 bit access */ - //TRACEOUT(("LGY-98: 16 bit read")); - ret = ne2000_mem_readw(s, s->rsar); - ne2000_dma_update(s, 2); -#ifdef DEBUG_NE2000 - printf("NE2000: asic read val=0x%04x\n", ret); -#endif - }else{ - ret = ne2000_mem_readb(s, s->rsar); - ne2000_dma_update(s, 1); - } - return (REG16)ret; -} - -// XXX: 実機から拾った謎のシーケンス -REG8 lgy98seq_base[] = {0xA,0x4,0xC,0x6,0xE,0x6,0xE,0x4}; // シーケンス共通部分? -REG8 lgy98seq_mbase = 0; // シーケンス一致数(共通部分) -REG8 lgy98seq_mbuf[64] = {0}; // シーケンス一致数 -REG8 lgy98seq_list[64][7] = { // シーケンスリスト - {0,0,0,0,0,0,1}, {0,0,0,0,0,1,3}, {0,0,0,0,1,2,1}, {0,0,0,0,1,3,3}, - {0,0,0,1,2,0,1}, {0,0,0,1,2,1,3}, {0,0,0,1,3,2,1}, {0,0,0,1,3,3,3}, - {0,0,1,2,0,0,1}, {0,0,1,2,0,1,3}, {0,0,1,2,1,2,1}, {0,0,1,2,1,3,3}, - {0,0,1,3,2,0,1}, {0,0,1,3,2,1,3}, {0,0,1,3,3,2,1}, {0,0,1,3,3,3,3}, - {0,1,2,0,0,0,1}, {0,1,2,0,0,1,3}, {0,1,2,0,1,2,1}, {0,1,2,0,1,3,3}, - {0,1,2,1,2,0,1}, {0,1,2,1,2,1,3}, {0,1,2,1,3,2,1}, {0,1,2,1,3,3,3}, - {0,1,3,2,0,0,1}, {0,1,3,2,0,1,3}, {0,1,3,2,1,2,1}, {0,1,3,2,1,3,3}, - {0,1,3,3,2,0,1}, {0,1,3,3,2,1,3}, {0,1,3,3,3,2,1}, {0,1,3,3,3,3,3}, - {1,2,0,0,0,0,1}, {1,2,0,0,0,1,3}, {1,2,0,0,1,2,1}, {1,2,0,0,1,3,3}, - {1,2,0,1,2,0,1}, {1,2,0,1,2,1,3}, {1,2,0,1,3,2,1}, {1,2,0,1,3,3,3}, - {1,2,1,2,0,0,1}, {1,2,1,2,0,1,3}, {1,2,1,2,1,2,1}, {1,2,1,2,1,3,3}, - {1,2,1,3,2,0,1}, {1,2,1,3,2,1,3}, {1,2,1,3,3,2,1}, {1,2,1,3,3,3,3}, - {1,3,2,0,0,0,1}, {1,3,2,0,0,1,3}, {1,3,2,0,1,2,1}, {1,3,2,0,1,3,3}, - {1,3,2,1,2,0,1}, {1,3,2,1,2,1,3}, {1,3,2,1,3,2,1}, {1,3,2,1,3,3,3}, - {1,3,3,2,0,0,1}, {1,3,3,2,0,1,3}, {1,3,3,2,1,2,1}, {1,3,3,2,1,3,3}, - {1,3,3,3,2,0,1}, {1,3,3,3,2,1,3}, {1,3,3,3,3,2,1}, {1,3,3,3,3,3,3}, -}; -// IRQ -> 7出現INDEX -/* 7出現位置メモ -17 -> INT0(IRQ3) -16 -> INT1(IRQ5) -15 -> INT2(IRQ6) 指定不可 -14 -> INT3(IRQ9) 指定不可 -13 -> INT4(IRQ10,11) 指定不可 -12 -> INT5(IRQ12) -11 -> INT6(IRQ13) 指定不可 -*/ -// IRQ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -REG8 lgy98_IRQ2IDX[] = { 0, 0, 0, 16, 0, 15, 14, 0, 0, 0, 0, 0, 11, 0, 0, 0}; -#define LGY98_MAKERETCODE(a) ((a) ? 0x07 : 0x06) -REG8 lgy98seq_retseq[17] = {0}; // 戻り値 -REG8 lgy98seq_retlist[64][17] = { // 戻り値リスト(ROM内容??) - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -}; -REG8 lgy98_code2num(REG8 code1,REG8 code2){ - switch ((code1<<8)|code2) { - case 0x0C04: - return 0; - case 0x0C06: - return 1; - case 0x0E04: - return 2; - case 0x0E06: - return 3; - } - return 0xff; -} -int lgy98seq_retidx = -1; // 戻り値リスト番号 -int lgy98seq_retpos = 0; // 戻り値リストの読み取り位置 - -void lgy98_setromdata(){ - // INT設定 - memset(lgy98seq_retlist[6], 0, _countof(lgy98seq_retlist[0])); - lgy98seq_retlist[6][lgy98_IRQ2IDX[lgy98.irq]] = 1; -} -void lgy98_setretseq(int index){ - // 戻り値設定 - lgy98seq_retidx = index; - lgy98seq_retpos = 0; - memcpy(lgy98seq_retseq, &(lgy98seq_retlist[lgy98seq_retidx]), _countof(lgy98seq_retseq)); -} - -static void IOOUTCALL lgy98_ob300_16(UINT port, REG8 dat) { - static REG8 codebuf[128] = {0}; - static REG8 codebufpos = 0; - LGY98 *s = &lgy98; - TRACEOUT(("LGY-98: out %04X d=%02X", port, dat)); - switch (port & 0x0f) { - case 0x0d: - if(lgy98seq_mbase < _countof(lgy98seq_base)){ - if(dat == lgy98seq_base[lgy98seq_mbase]){ - lgy98seq_mbase++; - if(lgy98seq_mbase ==_countof(lgy98seq_base)){ - int i; - for(i=0;i<_countof(lgy98seq_mbuf);i++){ - lgy98seq_mbuf[i] = 0; // 一致数カウンタ初期化 - } - codebufpos = 0; - } - }else if(dat == lgy98seq_base[0]){ - lgy98seq_mbase = 1; - }else{ - lgy98seq_mbase = 0; - } - }else{ - int mflag = 0; - int i; - if(codebufpos==0){ - codebuf[codebufpos] = dat; - codebufpos++; - }else{ - REG8 code; - codebuf[codebufpos] = dat; - code = lgy98_code2num(codebuf[0], codebuf[1]); - for(i=0;i<_countof(lgy98seq_mbuf);i++){ - if(code == lgy98seq_list[i][lgy98seq_mbuf[i]]){ - lgy98seq_mbuf[i]++; - if(lgy98seq_mbuf[i] ==_countof(lgy98seq_list[0])){ - mflag = 0; - lgy98_setretseq(i); - break; - }else{ - mflag = 1; - } - }else{ - lgy98seq_mbuf[i] = 0; - } - } - if(!mflag){ - // 完全一致または一致無し - if(dat == lgy98seq_base[0]){ - lgy98seq_mbase = 1; - }else{ - lgy98seq_mbase = 0; - } - } - codebufpos = 0; - } - } - break; - } - (void)port; - (void)dat; -} -static REG8 IOINPCALL lgy98_ib300_16(UINT port) { - REG8 ret = 0xff; - //TRACEOUT(("%d A=INP(&H%04X)", lognum, port)); - //lognum++; - //TRACEOUT(("%d PRINT #1 A", lognum)); - //lognum++; - //TRACEOUT(("%d PRINT #1", lognum)); - //lognum++; - //pic_resetirq(lgy98.irq); - switch (port & 0x0f) { - case 0x0a: - lgy98seq_mbase = 0; - lgy98seq_retidx = -1; - ret = 0x00; - break; - case 0x0b: - lgy98seq_mbase = 0; - lgy98seq_retidx = -1; - ret = 0x40; - break; - case 0x0c: - lgy98seq_mbase = 0; - lgy98seq_retidx = -1; - ret = 0x26; - break; - case 0x0d: - if(lgy98seq_retidx >= 0){ - ret = LGY98_MAKERETCODE(lgy98seq_retseq[lgy98seq_retpos]); - lgy98seq_retpos++; - if(lgy98seq_retpos == _countof(lgy98seq_retseq)){ - lgy98seq_retidx = -1; - } - }else{ - ret = 0x0b; - } - break; - } - TRACEOUT(("LGY-98: inp %04X ret=%X", port, ret)); - return ret; -} -static void IOOUTCALL lgy98_ob018(UINT port, REG8 dat) { - TRACEOUT(("LGY-98: out %04X d=%02X", port, dat)); - //pic_resetirq(lgy98.irq); - /* Nothing to do */ - (void)port; - (void)dat; -} -static REG8 IOINPCALL lgy98_ib018(UINT port) { - REG8 ret = 0x00; - LGY98 *s = &lgy98; - TRACEOUT(("LGY-98: inp %04X reset", port)); - //pic_resetirq(s->irq); - ne2000_reset(s); - return ret; -} - -static VLANState np2net_vlan = {0}; -/* find or alloc a new VLAN */ -VLANState *np2net_find_vlan(int id) -{ - np2net_vlan.id = id; - np2net_vlan.next = NULL; - np2net_vlan.first_client = NULL; - return &np2net_vlan; -} - -VLANClientState *np2net_new_vlan_client(VLANState *vlan, - const char *model, - const char *name, - IOReadHandler *fd_read, - IOCanRWHandler *fd_can_read, - NetCleanup *cleanup, - void *opaque) -{ - VLANClientState *vc, **pvc; - vc = (VLANClientState*)calloc(1, sizeof(VLANClientState)); - vc->model = strdup(model); - //if (name) - vc->name = strdup(name); - //else - // vc->name = assign_name(vc, model); - vc->fd_read = fd_read; - vc->fd_can_read = fd_can_read; - vc->cleanup = cleanup; - vc->opaque = opaque; - vc->vlan = vlan; - - vc->next = NULL; - pvc = &vlan->first_client; - while (*pvc != NULL) - pvc = &(*pvc)->next; - *pvc = vc; - return vc; -} - -// パケット受信時に呼ばれる(デフォルト処理) -static void np2net_lgy98_default_recieve_packet(const UINT8 *buf, int size) -{ - // 何もしない -} - -// パケット受信時に呼ばれる -static void lgy98_recieve_packet(const UINT8 *buf, int size) -{ - if(lgy98vc){ - lgy98vc->fd_read(&lgy98, buf, size); - } -} - -void lgy98_reset(const NP2CFG *pConfig){ - UINT base = 0x10D0; - REG8 irq = 5; - - lgy98cfg.enabled = np2cfg.uselgy98; - - // 初期化 - memset(&lgy98, 0, sizeof(lgy98)); - - // MACアドレス - memcpy(lgy98.macaddr, np2cfg.lgy98mac, 6); - - np2net.recieve_packet = np2net_lgy98_default_recieve_packet; - - if(np2cfg.lgy98io) base = np2cfg.lgy98io; - if(np2cfg.lgy98irq) irq = np2cfg.lgy98irq; - - lgy98cfg.baseaddr = base; - lgy98cfg.irq = irq; - - lgy98.base = base; - lgy98.irq = irq; -} -void lgy98_bind(void){ - int i; - VLANState *vlan; - UINT base = 0x10D0; - REG8 irq = 5; - //NICInfo *nd; - - if(!lgy98cfg.enabled) return; - - - vlan = np2net_find_vlan(0); - - base = lgy98.base; - irq = lgy98.irq; - - TRACEOUT(("LGY-98: I/O:%04X, IRQ:%d, TAP:%s", base, irq, np2cfg.np2nettap)); - - // - //if(np2net_reset(np2cfg.lgy98tap)){ - // TRACEOUT(("LGY-98: reset falied")); - // return; - //} - - //np2net_check_nic_model(nd, "ne2k_isa"); - // - //lgy98.base = base; - //lgy98.irq = irq; - //memcpy(lgy98.macaddr, macaddr, 6); - // - for(i=0;i<16;i++){ - iocore_attachout(base + i, lgy98_ob000); - iocore_attachinp(base + i, lgy98_ib000); - } - - iocore_attachout(base + 0x200, lgy98_ob200_8); - iocore_attachinp(base + 0x200, lgy98_ib200_8); - //iocore_attachout(base + 0x200, lgy98_ob200_16); // in iocore.c iocore_out16() - //iocore_attachinp(base + 0x200, lgy98_ib200_16); // in iocore.c iocore_inp16() - - for(i=0;i<16;i++){ - iocore_attachout(base + 0x300 + i, lgy98_ob300_16); - iocore_attachinp(base + 0x300 + i, lgy98_ib300_16); - } - - iocore_attachout(base + 0x018, lgy98_ob018); - iocore_attachinp(base + 0x018, lgy98_ib018); - - ne2000_reset(&lgy98); - - if(!lgy98vc){ - lgy98vc = np2net_new_vlan_client(vlan, "ne2k_isa", "ne2k_isa.1", - ne2000_receive, ne2000_can_receive, - pc98_ne2000_cleanup, &lgy98); - } - - np2net.recieve_packet = lgy98_recieve_packet; - - lgy98seq_mbase = 0; - lgy98seq_retidx = -1; - - lgy98_setromdata(); -} -void lgy98_shutdown(void){ - - // メモリ解放 - if(lgy98vc){ - free(lgy98vc->model); - free(lgy98vc->name); - free(lgy98vc); - lgy98vc = NULL; - } - -} - -#endif /* SUPPORT_LGY98 */ +/* + * QEMU NE2000 emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * 注意:このファイルのオリジナルはQEMUのne2000.cですが、大幅な改変が行われています。 + */ + +#include + +#if defined(SUPPORT_LGY98) + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) +#define strdup _strdup +#endif + +// XXX: +#ifndef _countof +#define _countof(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#define MAX_ETH_FRAME_SIZE 1514 + +#define E8390_CMD 0x00 /* The command register (for all pages) */ +/* Page 0 register offsets. */ +#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */ +#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */ +#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */ +#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */ +#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */ +#define EN0_TSR 0x04 /* Transmit status reg RD */ +#define EN0_TPSR 0x04 /* Transmit starting page WR */ +#define EN0_NCR 0x05 /* Number of collision reg RD */ +#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */ +#define EN0_FIFO 0x06 /* FIFO RD */ +#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */ +#define EN0_ISR 0x07 /* Interrupt status reg RD WR */ +#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */ +#define EN0_RSARLO 0x08 /* Remote start address reg 0 */ +#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */ +#define EN0_RSARHI 0x09 /* Remote start address reg 1 */ +#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */ +#define EN0_RTL8029ID0 0x0a /* Realtek ID byte #1 RD */ +#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */ +#define EN0_RTL8029ID1 0x0b /* Realtek ID byte #2 RD */ +#define EN0_RSR 0x0c /* rx status reg RD */ +#define EN0_RXCR 0x0c /* RX configuration reg WR */ +#define EN0_TXCR 0x0d /* TX configuration reg WR */ +#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */ +#define EN0_DCFG 0x0e /* Data configuration reg WR */ +#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */ +#define EN0_IMR 0x0f /* Interrupt mask reg WR */ +#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */ + +#define EN1_PHYS 0x11 +#define EN1_CURPAG 0x17 +#define EN1_MULT 0x18 + +#define EN2_STARTPG 0x21 /* Starting page of ring bfr RD */ +#define EN2_STOPPG 0x22 /* Ending page +1 of ring bfr RD */ + +#define EN3_CONFIG0 0x33 +#define EN3_CONFIG1 0x34 +#define EN3_CONFIG2 0x35 +#define EN3_CONFIG3 0x36 + +/* Register accessed at EN_CMD, the 8390 base addr. */ +#define E8390_STOP 0x01 /* Stop and reset the chip */ +#define E8390_START 0x02 /* Start the chip, clear reset */ +#define E8390_TRANS 0x04 /* Transmit a frame */ +#define E8390_RREAD 0x08 /* Remote read */ +#define E8390_RWRITE 0x10 /* Remote write */ +#define E8390_NODMA 0x20 /* Remote DMA */ +#define E8390_PAGE0 0x00 /* Select page chip registers */ +#define E8390_PAGE1 0x40 /* using the two high-order bits */ +#define E8390_PAGE2 0x80 /* Page 3 is invalid. */ + +/* Bits in EN0_ISR - Interrupt status register */ +#define ENISR_RX 0x01 /* Receiver, no error */ +#define ENISR_TX 0x02 /* Transmitter, no error */ +#define ENISR_RX_ERR 0x04 /* Receiver, with error */ +#define ENISR_TX_ERR 0x08 /* Transmitter, with error */ +#define ENISR_OVER 0x10 /* Receiver overwrote the ring */ +#define ENISR_COUNTERS 0x20 /* Counters need emptying */ +#define ENISR_RDC 0x40 /* remote dma complete */ +#define ENISR_RESET 0x80 /* Reset completed */ +#define ENISR_ALL 0x3f /* Interrupts we will enable */ + +/* Bits in received packet status byte and EN0_RSR*/ +#define ENRSR_RXOK 0x01 /* Received a good packet */ +#define ENRSR_CRC 0x02 /* CRC error */ +#define ENRSR_FAE 0x04 /* frame alignment error */ +#define ENRSR_FO 0x08 /* FIFO overrun */ +#define ENRSR_MPA 0x10 /* missed pkt */ +#define ENRSR_PHY 0x20 /* physical/multicast address */ +#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ +#define ENRSR_DEF 0x80 /* deferring */ + +/* Transmitted packet status, EN0_TSR. */ +#define ENTSR_PTX 0x01 /* Packet transmitted without error */ +#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */ +#define ENTSR_COL 0x04 /* The transmit collided at least once. */ +#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */ +#define ENTSR_CRS 0x10 /* The carrier sense was lost. */ +#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */ +#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */ +#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */ + + + LGY98 lgy98 = {0}; + LGY98CFG lgy98cfg = {0}; + + VLANClientState *lgy98vc = NULL; + + +//UINT lgy98_baseaddr = 0x10D0; +//UINT ne2000_baseaddr = 0x0200; + +static void ne2000_reset(LGY98 *s) +{ + int i; + + s->isr = ENISR_RESET; + memcpy(s->mem, s->macaddr, 6); + s->mem[14] = 0x57; + s->mem[15] = 0x57; + + /* duplicate prom data */ + for(i = 15;i >= 0; i--) { + s->mem[2 * i] = s->mem[i]; + s->mem[2 * i + 1] = s->mem[i]; + } +} + +static void ne2000_update_irq(LGY98 *s) +{ + static int irqflag = 0; + static unsigned long irqtime = 0; // WORKAROUND 短期間で割り込みし続けると暴走する問題を回避 + int isr; + isr = (s->isr & s->imr) & 0x7f; + //qemu_set_irq(s->irq, (isr != 0)); + if(isr != 0){ + if(irqflag && GETTICK()-irqtime > 2){ + irqflag = 0; // 2ms経過したら再割り込みOKとする + } + if(!irqflag) { + pic_setirq(s->irq); + irqtime = GETTICK(); + } + irqflag = 1; + }else{ + pic_resetirq(s->irq); + irqflag = 0; + } +} + +static void ne2000_mem_writeb(LGY98 *s, UINT32 addr, UINT32 val) +{ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + s->mem[addr] = val; + } +} + +static void ne2000_mem_writew(LGY98 *s, UINT32 addr, UINT32 val) +{ + addr &= ~1; /* XXX: check exact behaviour if not even */ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + //*(UINT16 *)(s->mem + addr) = cpu_to_le16(val); + STOREINTELWORD(s->mem + addr, val); + } +} + +static void ne2000_mem_writel(LGY98 *s, UINT32 addr, UINT32 val) +{ + addr &= ~1; /* XXX: check exact behaviour if not even */ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + //cpu_to_le32wu((UINT32 *)(s->mem + addr), val); + STOREINTELDWORD(s->mem + addr, val); + } +} + +static UINT32 ne2000_mem_readb(LGY98 *s, UINT32 addr) +{ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + return s->mem[addr]; + } else { + return 0xff; + } +} + +static UINT32 ne2000_mem_readw(LGY98 *s, UINT32 addr) +{ + UINT16 ret = 0xffff; + addr &= ~1; /* XXX: check exact behaviour if not even */ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + //return le16_to_cpu(*(UINT16 *)(s->mem + addr)); + ret = LOADINTELWORD(s->mem + addr); + } + return (UINT32)ret; +} + +static UINT32 ne2000_mem_readl(LGY98 *s, UINT32 addr) +{ + UINT32 ret = 0xffffffff; + addr &= ~1; /* XXX: check exact behaviour if not even */ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + //return le32_to_cpupu((UINT32 *)(s->mem + addr)); + ret = LOADINTELDWORD(s->mem + addr); + } + return ret; +} + +static void ne2000_dma_update(LGY98 *s, int len) +{ + s->rsar += len; + /* wrap */ + /* XXX: check what to do if rsar > stop */ + if (s->rsar == s->stop) + s->rsar = s->start; + + if (s->rcnt <= len) { + s->rcnt = 0; + /* signal end of transfer */ + s->isr |= ENISR_RDC; + s->cmd |= E8390_NODMA; /* コマンドレジスタにDMA完了ビットを立てる */ + ne2000_update_irq(s); + // TRACEOUT(("LGY-98: DMA_IRQ")); + } else { + s->rcnt -= len; + } +} + +void ne2000_send_packet(VLANClientState *vc1, const UINT8 *buf, int size) +{ + VLANState *vlan = vc1->vlan; + LGY98 *s = (LGY98*)vc1->opaque; + //VLANClientState *vc; + + if (vc1->link_down) + return; + +#ifdef DEBUG_NET + printf("vlan %d send:\n", vlan->id); + hex_dump(stdout, buf, size); +#endif + np2net.send_packet((UINT8*)buf, size); +} + + +#define MIN_BUF_SIZE 60 + +static void pc98_ne2000_cleanup(VLANClientState *vc) +{ + LGY98 *s = (LGY98*)vc->opaque; + + //unregister_savevm("ne2000", s); + + //isa_unassign_ioport(s->isa_io_base, 16); + //isa_unassign_ioport(s->isa_io_base + 0x200, 2); + //isa_unassign_ioport(s->isa_io_base + 0x300, 16); + //isa_unassign_ioport(s->isa_io_base + 0x18, 1); + + //qemu_free(s); +} + +static int ne2000_buffer_full(LGY98 *s) +{ + int avail, index, boundary; + + index = s->curpag << 8; + boundary = s->boundary << 8; + if (index < boundary) + avail = boundary - index; + else + avail = (s->stop - s->start) - (index - boundary); + if (avail < (MAX_ETH_FRAME_SIZE + 4)) + return 1; + return 0; +} + +static int ne2000_can_receive(void *opaque) +{ + LGY98 *s = (LGY98*)opaque; + + if (s->cmd & E8390_STOP) + return 1; + return !ne2000_buffer_full(s); +} + +/* From FreeBSD */ +static int compute_mcast_idx(const UINT8 *ep) +{ + UINT32 crc; + int carry, i, j; + UINT8 b; + + crc = 0xffffffff; + for (i = 0; i < 6; i++) { + b = *ep++; + for (j = 0; j < 8; j++) { + carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); + crc <<= 1; + b >>= 1; + if (carry) + crc = ((crc ^ 0x04c11db6) | carry); + } + } + return (crc >> 26); +} + +static void ne2000_receive(void *opaque, const UINT8 *buf, int size) +{ + LGY98 *s = &lgy98; + UINT8 *p; + unsigned int total_len, next, avail, len, index, mcast_idx; + UINT8 buf1[60]; + static const UINT8 broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + +#if defined(DEBUG_NE2000) + printf("NE2000: received len=%d\n", size); +#endif + + if (s->cmd & E8390_STOP || ne2000_buffer_full(s)) + return; + if (size >= s->stop - s->start - 0x100) + return; // 巨大パケットは捨てる + + + /* XXX: check this */ + if (s->rxcr & 0x10) { + /* promiscuous: receive all */ + } else { + if (!memcmp(buf, broadcast_macaddr, 6)) { + /* broadcast address */ + if (!(s->rxcr & 0x04)) + return; + } else if (buf[0] & 0x01) { + /* multicast */ + if (!(s->rxcr & 0x08)) + return; + mcast_idx = compute_mcast_idx(buf); + if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) + return; + } else if (s->mem[0] == buf[0] && + s->mem[2] == buf[1] && + s->mem[4] == buf[2] && + s->mem[6] == buf[3] && + s->mem[8] == buf[4] && + s->mem[10] == buf[5]) { + /* match */ + } else { + return; + } + } + + + /* if too small buffer, then expand it */ + if (size < MIN_BUF_SIZE) { + memcpy(buf1, buf, size); + memset(buf1 + size, 0, MIN_BUF_SIZE - size); + buf = buf1; + size = MIN_BUF_SIZE; + } + + index = s->curpag << 8; + /* 4 bytes for header */ + total_len = size + 4; + /* address for next packet (4 bytes for CRC) */ + next = index + ((total_len + 4 + 255) & ~0xff); + if (next >= s->stop) + next -= (s->stop - s->start); + /* prepare packet header */ + p = s->mem + index; + s->rsr = ENRSR_RXOK; /* receive status */ + /* XXX: check this */ + if (buf[0] & 0x01) + s->rsr |= ENRSR_PHY; + p[0] = s->rsr; + p[1] = next >> 8; + p[2] = total_len; + p[3] = total_len >> 8; + index += 4; + + /* write packet data */ + while (size > 0) { + if (index <= s->stop) + avail = s->stop - index; + else + avail = 0; + len = size; + if (len > avail) + len = avail; + memcpy(s->mem + index, buf, len); + buf += len; + index += len; + if (index == s->stop) + index = s->start; + size -= len; + } + s->curpag = next >> 8; + + /* now we can signal we have received something */ + s->isr |= ENISR_RX; + ne2000_update_irq(s); + //TRACEOUT(("LGY-98: RCV_IRQ")); +} + + + + +// ************************** I/O PORT ************** + +static void IOOUTCALL lgy98_ob000(UINT addr, REG8 dat) { + int offset, page, index; + UINT32 val = dat; + LGY98 *s = &lgy98; + + //TRACEOUT(("LGY-98: out %04X d=%02X", addr, dat)); + addr &= 0xf; + if (addr == E8390_CMD) { + /* control register */ + s->cmd = dat; + if (!(dat & E8390_STOP)) { /* START bit makes no sense on RTL8029... */ + s->isr &= ~ENISR_RESET; + /* test specific case: zero length transfer */ + if ((dat & (E8390_RREAD | E8390_RWRITE)) && + s->rcnt == 0) { + s->isr |= ENISR_RDC; + ne2000_update_irq(s); + //TRACEOUT(("LGY-98: RRW_IRQ")); + } + if (dat & E8390_TRANS) { + index = (lgy98.tpsr << 8); + /* XXX: next 2 lines are a hack to make netware 3.11 work */ + if (index >= NE2000_PMEM_END) + index -= NE2000_PMEM_SIZE; + /* fail safe: check range on the transmitted length */ + if (index + s->tcnt <= NE2000_PMEM_END) { + ne2000_send_packet(lgy98vc, s->mem + index, s->tcnt); + } + /* signal end of transfer */ + s->tsr = ENTSR_PTX; + s->isr |= ENISR_TX; + s->cmd &= ~E8390_TRANS; + //TRACEOUT(("LGY-98: SEND_IRQ")); + ne2000_update_irq(s); + } + } + } else { + page = s->cmd >> 6; + offset = addr | (page << 4); + switch(offset) { + case EN0_STARTPG: + s->start = val << 8; + break; + case EN0_STOPPG: + s->stop = val << 8; + break; + case EN0_BOUNDARY: + s->boundary = val; + break; + case EN0_IMR: + s->imr = val; + //TRACEOUT(("LGY-98: IMR_IRQ")); + //pic_resetirq(s->irq); + ne2000_update_irq(s); + break; + case EN0_TPSR: + s->tpsr = val; + break; + case EN0_TCNTLO: + s->tcnt = (s->tcnt & 0xff00) | val; + break; + case EN0_TCNTHI: + s->tcnt = (s->tcnt & 0x00ff) | (val << 8); + break; + case EN0_RSARLO: + s->rsar = (s->rsar & 0xff00) | val; + break; + case EN0_RSARHI: + s->rsar = (s->rsar & 0x00ff) | (val << 8); + break; + case EN0_RCNTLO: + s->rcnt = (s->rcnt & 0xff00) | val; + break; + case EN0_RCNTHI: + s->rcnt = (s->rcnt & 0x00ff) | (val << 8); + break; + case EN0_RXCR: + s->rxcr = val; + break; + case EN0_DCFG: + s->dcfg = val; + break; + case EN0_ISR: + s->isr &= ~(val & 0x7f); + //TRACEOUT(("LGY-98: ISR_IRQ")); + //pic_resetirq(s->irq); + ne2000_update_irq(s); + break; + case EN1_PHYS: + case EN1_PHYS + 1: + case EN1_PHYS + 2: + case EN1_PHYS + 3: + case EN1_PHYS + 4: + case EN1_PHYS + 5: + s->phys[offset - EN1_PHYS] = val; + break; + case EN1_CURPAG: + s->curpag = val; + break; + case EN1_MULT: + case EN1_MULT + 1: + case EN1_MULT + 2: + case EN1_MULT + 3: + case EN1_MULT + 4: + case EN1_MULT + 5: + case EN1_MULT + 6: + case EN1_MULT + 7: + s->mult[offset - EN1_MULT] = val; + break; + } + } + (void)addr; + (void)dat; +} +static REG8 IOINPCALL lgy98_ib000(UINT addr) { + int ret = 0; + int offset, page; + LGY98 *s = &lgy98; + + //pic_resetirq(s->irq); + //TRACEOUT(("LGY-98: inp %04X", addr)); + addr = (addr & 0xf); + if (addr == E8390_CMD) { + ret = s->cmd; + } else { + page = s->cmd >> 6; + offset = addr | (page << 4); + switch(offset) { + case EN0_TSR: + ret = s->tsr; + break; + case EN0_BOUNDARY: + ret = s->boundary; + break; + case EN0_ISR: + ret = s->isr; + break; + case EN0_RSARLO: + ret = s->rsar & 0x00ff; + break; + case EN0_RSARHI: + ret = s->rsar >> 8; + break; + case EN1_PHYS: + case EN1_PHYS + 1: + case EN1_PHYS + 2: + case EN1_PHYS + 3: + case EN1_PHYS + 4: + case EN1_PHYS + 5: + ret = s->phys[offset - EN1_PHYS]; + break; + case EN1_CURPAG: + ret = s->curpag; + break; + case EN1_MULT: + case EN1_MULT + 1: + case EN1_MULT + 2: + case EN1_MULT + 3: + case EN1_MULT + 4: + case EN1_MULT + 5: + case EN1_MULT + 6: + case EN1_MULT + 7: + ret = s->mult[offset - EN1_MULT]; + break; + case EN0_RSR: + ret = s->rsr; + break; + case EN2_STARTPG: + ret = s->start >> 8; + break; + case EN2_STOPPG: + ret = s->stop >> 8; + break; + case EN0_RTL8029ID0: + ret = 0x29; + break; + case EN0_RTL8029ID1: + ret = 0x43; + break; + case EN3_CONFIG0: + ret = 0; /* 10baseT media */ + break; + case EN3_CONFIG2: + ret = 0x40; /* 10baseT active */ + break; + case EN3_CONFIG3: + ret = 0x40; /* Full duplex */ + break; + default: + ret = 0x00; + break; + } + } + return (REG8)ret; +} +void IOOUTCALL lgy98_ob200_8(UINT addr, REG8 dat) { + UINT32 val = dat; + LGY98 *s = &lgy98; + + //pic_resetirq(s->irq); + if (s->rcnt == 0) + return; + if(s->dcfg & 0x01){ + ne2000_mem_writew(s, s->rsar, val); + ne2000_dma_update(s, 2); + return; + }else{ + //if (s->dcfg & 0x01) { + // /* 16 bit access */ + // ne2000_mem_writew(s, s->rsar, val); + // ne2000_dma_update(s, 2); + //} else { + /* 8 bit access */ + //TRACEOUT(("LGY-98: 8 bit write")); + ne2000_mem_writeb(s, s->rsar, val); + ne2000_dma_update(s, 1); + //} + } + (void)addr; + (void)dat; +} +REG8 IOINPCALL lgy98_ib200_8(UINT addr) { + int ret = 0; + LGY98 *s = &lgy98; + + //pic_resetirq(s->irq); + if(s->dcfg & 0x01){ + ret = ne2000_mem_readw(s, s->rsar); + ne2000_dma_update(s, 2); + return (REG8)ret; + }else{ + //TRACEOUT(("LGY-98: 8 bit read")); + /* 8 bit access */ + ret = ne2000_mem_readb(s, s->rsar); + ne2000_dma_update(s, 1); +#ifdef DEBUG_NE2000 + printf("NE2000: asic read val=0x%04x\n", ret); +#endif + return (REG8)ret; + } +} +void IOOUTCALL lgy98_ob200_16(UINT addr, REG16 dat) { + UINT32 val = dat; + LGY98 *s = &lgy98; + + //pic_resetirq(s->irq); + if (s->rcnt == 0) + return; + if(s->dcfg & 0x01){ + /* 16 bit access */ + //TRACEOUT(("LGY-98: 16 bit write")); + ne2000_mem_writew(s, s->rsar, val); + ne2000_dma_update(s, 2); + }else{ + ne2000_mem_writeb(s, s->rsar, val); + ne2000_dma_update(s, 1); + } + (void)addr; + (void)dat; +} +REG16 IOINPCALL lgy98_ib200_16(UINT addr) { + int ret = 0; + LGY98 *s = &lgy98; + + //pic_resetirq(s->irq); + if(s->dcfg & 0x01){ + /* 16 bit access */ + //TRACEOUT(("LGY-98: 16 bit read")); + ret = ne2000_mem_readw(s, s->rsar); + ne2000_dma_update(s, 2); +#ifdef DEBUG_NE2000 + printf("NE2000: asic read val=0x%04x\n", ret); +#endif + }else{ + ret = ne2000_mem_readb(s, s->rsar); + ne2000_dma_update(s, 1); + } + return (REG16)ret; +} + +// XXX: 実機から拾った謎のシーケンス +REG8 lgy98seq_base[] = {0xA,0x4,0xC,0x6,0xE,0x6,0xE,0x4}; // シーケンス共通部分? +REG8 lgy98seq_mbase = 0; // シーケンス一致数(共通部分) +REG8 lgy98seq_mbuf[64] = {0}; // シーケンス一致数 +REG8 lgy98seq_list[64][7] = { // シーケンスリスト + {0,0,0,0,0,0,1}, {0,0,0,0,0,1,3}, {0,0,0,0,1,2,1}, {0,0,0,0,1,3,3}, + {0,0,0,1,2,0,1}, {0,0,0,1,2,1,3}, {0,0,0,1,3,2,1}, {0,0,0,1,3,3,3}, + {0,0,1,2,0,0,1}, {0,0,1,2,0,1,3}, {0,0,1,2,1,2,1}, {0,0,1,2,1,3,3}, + {0,0,1,3,2,0,1}, {0,0,1,3,2,1,3}, {0,0,1,3,3,2,1}, {0,0,1,3,3,3,3}, + {0,1,2,0,0,0,1}, {0,1,2,0,0,1,3}, {0,1,2,0,1,2,1}, {0,1,2,0,1,3,3}, + {0,1,2,1,2,0,1}, {0,1,2,1,2,1,3}, {0,1,2,1,3,2,1}, {0,1,2,1,3,3,3}, + {0,1,3,2,0,0,1}, {0,1,3,2,0,1,3}, {0,1,3,2,1,2,1}, {0,1,3,2,1,3,3}, + {0,1,3,3,2,0,1}, {0,1,3,3,2,1,3}, {0,1,3,3,3,2,1}, {0,1,3,3,3,3,3}, + {1,2,0,0,0,0,1}, {1,2,0,0,0,1,3}, {1,2,0,0,1,2,1}, {1,2,0,0,1,3,3}, + {1,2,0,1,2,0,1}, {1,2,0,1,2,1,3}, {1,2,0,1,3,2,1}, {1,2,0,1,3,3,3}, + {1,2,1,2,0,0,1}, {1,2,1,2,0,1,3}, {1,2,1,2,1,2,1}, {1,2,1,2,1,3,3}, + {1,2,1,3,2,0,1}, {1,2,1,3,2,1,3}, {1,2,1,3,3,2,1}, {1,2,1,3,3,3,3}, + {1,3,2,0,0,0,1}, {1,3,2,0,0,1,3}, {1,3,2,0,1,2,1}, {1,3,2,0,1,3,3}, + {1,3,2,1,2,0,1}, {1,3,2,1,2,1,3}, {1,3,2,1,3,2,1}, {1,3,2,1,3,3,3}, + {1,3,3,2,0,0,1}, {1,3,3,2,0,1,3}, {1,3,3,2,1,2,1}, {1,3,3,2,1,3,3}, + {1,3,3,3,2,0,1}, {1,3,3,3,2,1,3}, {1,3,3,3,3,2,1}, {1,3,3,3,3,3,3}, +}; +// IRQ -> 7出現INDEX +/* 7出現位置メモ +17 -> INT0(IRQ3) +16 -> INT1(IRQ5) +15 -> INT2(IRQ6) 指定不可 +14 -> INT3(IRQ9) 指定不可 +13 -> INT4(IRQ10,11) 指定不可 +12 -> INT5(IRQ12) +11 -> INT6(IRQ13) 指定不可 +*/ +// IRQ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +REG8 lgy98_IRQ2IDX[] = { 0, 0, 0, 16, 0, 15, 14, 0, 0, 0, 0, 0, 11, 0, 0, 0}; +#define LGY98_MAKERETCODE(a) ((a) ? 0x07 : 0x06) +REG8 lgy98seq_retseq[17] = {0}; // 戻り値 +REG8 lgy98seq_retlist[64][17] = { // 戻り値リスト(ROM内容??) + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +}; +REG8 lgy98_code2num(REG8 code1,REG8 code2){ + switch ((code1<<8)|code2) { + case 0x0C04: + return 0; + case 0x0C06: + return 1; + case 0x0E04: + return 2; + case 0x0E06: + return 3; + } + return 0xff; +} +int lgy98seq_retidx = -1; // 戻り値リスト番号 +int lgy98seq_retpos = 0; // 戻り値リストの読み取り位置 + +void lgy98_setromdata(){ + // INT設定 + memset(lgy98seq_retlist[6], 0, _countof(lgy98seq_retlist[0])); + lgy98seq_retlist[6][lgy98_IRQ2IDX[lgy98.irq]] = 1; +} +void lgy98_setretseq(int index){ + // 戻り値設定 + lgy98seq_retidx = index; + lgy98seq_retpos = 0; + memcpy(lgy98seq_retseq, &(lgy98seq_retlist[lgy98seq_retidx]), _countof(lgy98seq_retseq)); +} + +static void IOOUTCALL lgy98_ob300_16(UINT port, REG8 dat) { + static REG8 codebuf[128] = {0}; + static REG8 codebufpos = 0; + LGY98 *s = &lgy98; + TRACEOUT(("LGY-98: out %04X d=%02X", port, dat)); + switch (port & 0x0f) { + case 0x0d: + if(lgy98seq_mbase < _countof(lgy98seq_base)){ + if(dat == lgy98seq_base[lgy98seq_mbase]){ + lgy98seq_mbase++; + if(lgy98seq_mbase ==_countof(lgy98seq_base)){ + int i; + for(i=0;i<_countof(lgy98seq_mbuf);i++){ + lgy98seq_mbuf[i] = 0; // 一致数カウンタ初期化 + } + codebufpos = 0; + } + }else if(dat == lgy98seq_base[0]){ + lgy98seq_mbase = 1; + }else{ + lgy98seq_mbase = 0; + } + }else{ + int mflag = 0; + int i; + if(codebufpos==0){ + codebuf[codebufpos] = dat; + codebufpos++; + }else{ + REG8 code; + codebuf[codebufpos] = dat; + code = lgy98_code2num(codebuf[0], codebuf[1]); + for(i=0;i<_countof(lgy98seq_mbuf);i++){ + if(code == lgy98seq_list[i][lgy98seq_mbuf[i]]){ + lgy98seq_mbuf[i]++; + if(lgy98seq_mbuf[i] ==_countof(lgy98seq_list[0])){ + mflag = 0; + lgy98_setretseq(i); + break; + }else{ + mflag = 1; + } + }else{ + lgy98seq_mbuf[i] = 0; + } + } + if(!mflag){ + // 完全一致または一致無し + if(dat == lgy98seq_base[0]){ + lgy98seq_mbase = 1; + }else{ + lgy98seq_mbase = 0; + } + } + codebufpos = 0; + } + } + break; + } + (void)port; + (void)dat; +} +static REG8 IOINPCALL lgy98_ib300_16(UINT port) { + REG8 ret = 0xff; + //TRACEOUT(("%d A=INP(&H%04X)", lognum, port)); + //lognum++; + //TRACEOUT(("%d PRINT #1 A", lognum)); + //lognum++; + //TRACEOUT(("%d PRINT #1", lognum)); + //lognum++; + //pic_resetirq(lgy98.irq); + switch (port & 0x0f) { + case 0x0a: + lgy98seq_mbase = 0; + lgy98seq_retidx = -1; + ret = 0x00; + break; + case 0x0b: + lgy98seq_mbase = 0; + lgy98seq_retidx = -1; + ret = 0x40; + break; + case 0x0c: + lgy98seq_mbase = 0; + lgy98seq_retidx = -1; + ret = 0x26; + break; + case 0x0d: + if(lgy98seq_retidx >= 0){ + ret = LGY98_MAKERETCODE(lgy98seq_retseq[lgy98seq_retpos]); + lgy98seq_retpos++; + if(lgy98seq_retpos == _countof(lgy98seq_retseq)){ + lgy98seq_retidx = -1; + } + }else{ + ret = 0x0b; + } + break; + } + TRACEOUT(("LGY-98: inp %04X ret=%X", port, ret)); + return ret; +} +static void IOOUTCALL lgy98_ob018(UINT port, REG8 dat) { + TRACEOUT(("LGY-98: out %04X d=%02X", port, dat)); + //pic_resetirq(lgy98.irq); + /* Nothing to do */ + (void)port; + (void)dat; +} +static REG8 IOINPCALL lgy98_ib018(UINT port) { + REG8 ret = 0x00; + LGY98 *s = &lgy98; + TRACEOUT(("LGY-98: inp %04X reset", port)); + //pic_resetirq(s->irq); + ne2000_reset(s); + return ret; +} + +static VLANState np2net_vlan = {0}; +/* find or alloc a new VLAN */ +VLANState *np2net_find_vlan(int id) +{ + np2net_vlan.id = id; + np2net_vlan.next = NULL; + np2net_vlan.first_client = NULL; + return &np2net_vlan; +} + +VLANClientState *np2net_new_vlan_client(VLANState *vlan, + const char *model, + const char *name, + IOReadHandler *fd_read, + IOCanRWHandler *fd_can_read, + NetCleanup *cleanup, + void *opaque) +{ + VLANClientState *vc, **pvc; + vc = (VLANClientState*)calloc(1, sizeof(VLANClientState)); + vc->model = strdup(model); + //if (name) + vc->name = strdup(name); + //else + // vc->name = assign_name(vc, model); + vc->fd_read = fd_read; + vc->fd_can_read = fd_can_read; + vc->cleanup = cleanup; + vc->opaque = opaque; + vc->vlan = vlan; + + vc->next = NULL; + pvc = &vlan->first_client; + while (*pvc != NULL) + pvc = &(*pvc)->next; + *pvc = vc; + return vc; +} + +// パケット受信時に呼ばれる(デフォルト処理) +static void np2net_lgy98_default_recieve_packet(const UINT8 *buf, int size) +{ + // 何もしない +} + +// パケット受信時に呼ばれる +static void lgy98_recieve_packet(const UINT8 *buf, int size) +{ + if(lgy98vc){ + lgy98vc->fd_read(&lgy98, buf, size); + } +} + +void lgy98_reset(const NP2CFG *pConfig){ + UINT base = 0x10D0; + REG8 irq = 5; + + lgy98cfg.enabled = np2cfg.uselgy98; + + // 初期化 + memset(&lgy98, 0, sizeof(lgy98)); + + // MACアドレス + memcpy(lgy98.macaddr, np2cfg.lgy98mac, 6); + + np2net.recieve_packet = np2net_lgy98_default_recieve_packet; + + if(np2cfg.lgy98io) base = np2cfg.lgy98io; + if(np2cfg.lgy98irq) irq = np2cfg.lgy98irq; + + lgy98cfg.baseaddr = base; + lgy98cfg.irq = irq; + + lgy98.base = base; + lgy98.irq = irq; +} +void lgy98_bind(void){ + int i; + VLANState *vlan; + UINT base = 0x10D0; + REG8 irq = 5; + //NICInfo *nd; + + if(!lgy98cfg.enabled) return; + + + vlan = np2net_find_vlan(0); + + base = lgy98.base; + irq = lgy98.irq; + + TRACEOUT(("LGY-98: I/O:%04X, IRQ:%d, TAP:%s", base, irq, np2cfg.np2nettap)); + + // + //if(np2net_reset(np2cfg.lgy98tap)){ + // TRACEOUT(("LGY-98: reset falied")); + // return; + //} + + //np2net_check_nic_model(nd, "ne2k_isa"); + // + //lgy98.base = base; + //lgy98.irq = irq; + //memcpy(lgy98.macaddr, macaddr, 6); + // + for(i=0;i<16;i++){ + iocore_attachout(base + i, lgy98_ob000); + iocore_attachinp(base + i, lgy98_ib000); + } + + iocore_attachout(base + 0x200, lgy98_ob200_8); + iocore_attachinp(base + 0x200, lgy98_ib200_8); + //iocore_attachout(base + 0x200, lgy98_ob200_16); // in iocore.c iocore_out16() + //iocore_attachinp(base + 0x200, lgy98_ib200_16); // in iocore.c iocore_inp16() + + for(i=0;i<16;i++){ + iocore_attachout(base + 0x300 + i, lgy98_ob300_16); + iocore_attachinp(base + 0x300 + i, lgy98_ib300_16); + } + + iocore_attachout(base + 0x018, lgy98_ob018); + iocore_attachinp(base + 0x018, lgy98_ib018); + + ne2000_reset(&lgy98); + + if(!lgy98vc){ + lgy98vc = np2net_new_vlan_client(vlan, "ne2k_isa", "ne2k_isa.1", + ne2000_receive, ne2000_can_receive, + pc98_ne2000_cleanup, &lgy98); + } + + np2net.recieve_packet = lgy98_recieve_packet; + + lgy98seq_mbase = 0; + lgy98seq_retidx = -1; + + lgy98_setromdata(); +} +void lgy98_shutdown(void){ + + // メモリ解放 + if(lgy98vc){ + free(lgy98vc->model); + free(lgy98vc->name); + free(lgy98vc); + lgy98vc = NULL; + } + +} + +#endif /* SUPPORT_LGY98 */ diff --git a/network/lgy98.h b/network/lgy98.h old mode 100755 new mode 100644 index d86e2fdc..13cdc68d --- a/network/lgy98.h +++ b/network/lgy98.h @@ -1,57 +1,57 @@ -/* - * QEMU NE2000 emulation - * - * Copyright (c) 2003-2004 Fabrice Bellard - * - * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma once - -#if defined(SUPPORT_LGY98) - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - UINT8 enabled; - UINT baseaddr; - UINT8 irq; -} LGY98CFG; - -extern LGY98CFG lgy98cfg; - -//void IOOUTCALL ideio_w16(UINT port, REG16 value); -//REG16 IOINPCALL ideio_r16(UINT port); - -void IOOUTCALL lgy98_ob200_8(UINT addr, REG8 value); -REG8 IOOUTCALL lgy98_ib200_8(UINT addr); -void IOOUTCALL lgy98_ob200_16(UINT addr, REG16 value); -REG16 IOOUTCALL lgy98_ib200_16(UINT addr); - -void lgy98_reset(const NP2CFG *pConfig); -void lgy98_bind(void); -void lgy98_shutdown(void); - -#ifdef __cplusplus -} -#endif - -#endif /* SUPPORT_LGY98 */ +/* + * QEMU NE2000 emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#if defined(SUPPORT_LGY98) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + UINT8 enabled; + UINT baseaddr; + UINT8 irq; +} LGY98CFG; + +extern LGY98CFG lgy98cfg; + +//void IOOUTCALL ideio_w16(UINT port, REG16 value); +//REG16 IOINPCALL ideio_r16(UINT port); + +void IOOUTCALL lgy98_ob200_8(UINT addr, REG8 value); +REG8 IOOUTCALL lgy98_ib200_8(UINT addr); +void IOOUTCALL lgy98_ob200_16(UINT addr, REG16 value); +REG16 IOOUTCALL lgy98_ib200_16(UINT addr); + +void lgy98_reset(const NP2CFG *pConfig); +void lgy98_bind(void); +void lgy98_shutdown(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SUPPORT_LGY98 */ diff --git a/network/lgy98dev.h b/network/lgy98dev.h old mode 100755 new mode 100644 index 9f6f24e5..385f00e7 --- a/network/lgy98dev.h +++ b/network/lgy98dev.h @@ -1,111 +1,111 @@ -/* - * QEMU NE2000 emulation - * - * Copyright (c) 2003-2004 Fabrice Bellard - * - * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#define NE2000_PMEM_SIZE (32*1024) -#define NE2000_PMEM_START (16*1024) -#define NE2000_PMEM_END (NE2000_PMEM_SIZE+NE2000_PMEM_START) -#define NE2000_MEM_SIZE NE2000_PMEM_END - -typedef void IOReadHandler(void *opaque, const UINT8 *buf, int size); -typedef int IOCanRWHandler(void *opaque); -//typedef ssize_t (IOReadvHandler)(void *, const struct iovec *, int); -typedef void (NetCleanup) (struct tagVLANClientState *); -typedef void (LinkStatusChanged)(struct tagVLANClientState *); - -struct tagVLANState { - int id; - struct tagVLANClientState *first_client; - struct tagVLANState *next; - unsigned int nb_guest_devs, nb_host_devs; -}; - -struct tagVLANClientState{ - IOReadHandler *fd_read; - //LGY98_IOReadvHandler *fd_readv; - /* Packets may still be sent if this returns zero. It's used to - rate-limit the slirp code. */ - IOCanRWHandler *fd_can_read; - NetCleanup *cleanup; - LinkStatusChanged *link_status_changed; - int link_down; - void *opaque; - struct tagVLANClientState *next; - struct tagVLANState *vlan; - char *model; - char *name; - char info_str[256]; -}; - -typedef struct tagVLANState VLANState; -typedef struct tagVLANClientState VLANClientState; - -typedef struct { - UINT16 base; - //REG8 macaddr[6]; - REG8 irq; - - REG8 cmd; - UINT32 start; - UINT32 stop; - REG8 boundary; - REG8 tsr; // - REG8 tpsr; // - UINT16 tcnt; // - UINT16 rcnt; // - UINT32 rsar; // - REG8 rsr; - REG8 rxcr; - REG8 isr; - REG8 dcfg; - REG8 imr; - REG8 phys[6]; /* mac address */ - REG8 curpag; - REG8 mult[8]; /* multicast mask array */ - //qemu_irq irq; - int isa_io_base; - //PCIDevice *pci_dev; - REG8 macaddr[6]; - REG8 mem[NE2000_MEM_SIZE]; - /* - REG8 cmd; - REG8 isr; - REG8 tpsr; - UINT16 rcnt; - UINT16 tcnt; - - VLANClientState *vc;*/ -} LGY98; - -extern LGY98 lgy98; - -#ifdef __cplusplus -} -#endif - +/* + * QEMU NE2000 emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define NE2000_PMEM_SIZE (32*1024) +#define NE2000_PMEM_START (16*1024) +#define NE2000_PMEM_END (NE2000_PMEM_SIZE+NE2000_PMEM_START) +#define NE2000_MEM_SIZE NE2000_PMEM_END + +typedef void IOReadHandler(void *opaque, const UINT8 *buf, int size); +typedef int IOCanRWHandler(void *opaque); +//typedef ssize_t (IOReadvHandler)(void *, const struct iovec *, int); +typedef void (NetCleanup) (struct tagVLANClientState *); +typedef void (LinkStatusChanged)(struct tagVLANClientState *); + +struct tagVLANState { + int id; + struct tagVLANClientState *first_client; + struct tagVLANState *next; + unsigned int nb_guest_devs, nb_host_devs; +}; + +struct tagVLANClientState{ + IOReadHandler *fd_read; + //LGY98_IOReadvHandler *fd_readv; + /* Packets may still be sent if this returns zero. It's used to + rate-limit the slirp code. */ + IOCanRWHandler *fd_can_read; + NetCleanup *cleanup; + LinkStatusChanged *link_status_changed; + int link_down; + void *opaque; + struct tagVLANClientState *next; + struct tagVLANState *vlan; + char *model; + char *name; + char info_str[256]; +}; + +typedef struct tagVLANState VLANState; +typedef struct tagVLANClientState VLANClientState; + +typedef struct { + UINT16 base; + //REG8 macaddr[6]; + REG8 irq; + + REG8 cmd; + UINT32 start; + UINT32 stop; + REG8 boundary; + REG8 tsr; // + REG8 tpsr; // + UINT16 tcnt; // + UINT16 rcnt; // + UINT32 rsar; // + REG8 rsr; + REG8 rxcr; + REG8 isr; + REG8 dcfg; + REG8 imr; + REG8 phys[6]; /* mac address */ + REG8 curpag; + REG8 mult[8]; /* multicast mask array */ + //qemu_irq irq; + int isa_io_base; + //PCIDevice *pci_dev; + REG8 macaddr[6]; + REG8 mem[NE2000_MEM_SIZE]; + /* + REG8 cmd; + REG8 isr; + REG8 tpsr; + UINT16 rcnt; + UINT16 tcnt; + + VLANClientState *vc;*/ +} LGY98; + +extern LGY98 lgy98; + +#ifdef __cplusplus +} +#endif + diff --git a/network/net.c b/network/net.c old mode 100755 new mode 100644 index c6733f41..d34fed19 --- a/network/net.c +++ b/network/net.c @@ -1,707 +1,707 @@ -/** - * @file net.c - * @brief Virtual LAN Interface - * - * @author $Author: SimK $ - */ - -#include -#if defined(NP2_WIN) -#include -#else -#include -#endif -#include - -//#define TRACEOUT(a) printf(a);printf("\n"); -#define TRACEOUT(a) - -#if defined(SUPPORT_NET) - -#include -#include -#ifdef SUPPORT_LGY98 -#include -#endif - -#if defined(NP2_WIN) -#include -#include -#include - -#define stricmp _stricmp - -#pragma warning(disable: 4996) -#pragma comment(lib, "Advapi32.lib") - -#define DEVICE_PATH_FMT _T("\\\\.\\Global\\%s.tap") - -#define TAP_CONTROL_CODE(request,method) \ - CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) - -#define TAP_IOCTL_SET_MEDIA_STATUS \ - TAP_CONTROL_CODE (6, METHOD_BUFFERED) - -#else - -// for Linux -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -unsigned GetTickCount(); - -/* -unsigned GetTickCount() -{ - struct timeval tv; - if(gettimeofday(&tv, NULL) != 0) - return 0; - - return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); -} -*/ - -#if defined(__APPLE__) -#include -#include -#include -#else -#include -#include -#include /* struct ethhdr */ -#endif - -#endif // defined(NP2_WIN) - -#define NET_BUFLEN (16*1024) // バッファ1つの長さ(XXX: パケットサイズの最大値にしないと無駄。もっと言えば可変長で大きな1つのバッファに入れるべき?) -#define NET_ARYLEN (128) // バッファの数 - - NP2NET np2net; - -static OEMCHAR np2net_tapName[MAX_PATH]; // TAPデバイス名 - -static int np2net_hThreadexit = 0; // スレッド終了フラグ - -#if defined(NP2_WIN) -static char *GetNetWorkDeviceGuid(const char *, char *, DWORD); // TAPデバイス名からGUIDを取得する - -static HANDLE np2net_hTap = INVALID_HANDLE_VALUE; // TAPデバイスの読み書きハンドル -static HANDLE np2net_hThreadR = NULL; // Read用スレッド -static HANDLE np2net_hThreadW = NULL; // Write用スレッド -static HANDLE np2net_thread_eventhandle = INVALID_HANDLE_VALUE; // 送受信要求用 -#else - -// for Linux -static int np2net_hTap = -1; // TAPデバイスの読み書きハンドル -static int np2net_hThreadE = 0; // Thread Running Flag -static pthread_t np2net_hThreadR = NULL; // Read用スレッド -static pthread_t np2net_hThreadW = NULL; // Write用スレッド -static pthread_t np2net_thread_eventhandle = 0; // 送受信要求用 -#endif // defined(NP2_WIN) - -static UINT8 np2net_membuf[NET_ARYLEN][NET_BUFLEN]; // 送信用バッファ -static int np2net_membuflen[NET_ARYLEN]; // 送信用バッファにあるデータの長さ -static int np2net_membuf_readpos = 0; // バッファ読み取り位置 -static int np2net_membuf_writepos = 0; // バッファ書き込み位置 - -static int np2net_pmm = 0; // CPU負荷低減モード(通信は若干遅くなると思われる) -static int np2net_highspeedmode = 0; // 高速送受信モード -static UINT32 np2net_highspeeddatacount = 0; // 送受信データ数カウンタ - -#if defined(NP2_WIN) -static BOOL np2net_cs_initialized = 0; // np2net クリティカルセクション 初期化済みフラグ -static CRITICAL_SECTION np2net_cs = {0}; // np2net クリティカルセクション -static void np2net_cs_Initialize(){ - if(!np2net_cs_initialized){ - InitializeCriticalSection(&np2net_cs); - np2net_thread_eventhandle = CreateEvent(NULL, FALSE, FALSE, NULL); - np2net_cs_initialized = TRUE; - } -} -static void np2net_cs_Finalize(){ - if(np2net_cs_initialized){ - DeleteCriticalSection(&np2net_cs); - CloseHandle(np2net_thread_eventhandle); - np2net_cs_initialized = FALSE; - } -} -void np2net_cs_EnterCriticalSection(){ - if(np2net_cs_initialized){ - EnterCriticalSection(&np2net_cs); - } -} -void np2net_cs_LeaveCriticalSection(){ - if(np2net_cs_initialized){ - LeaveCriticalSection(&np2net_cs); - } -} -#endif // defined(NP2_WIN) - -#if defined(NP2_WIN) -// パケットデータを TAP へ書き出す -static int doWriteTap(HANDLE hTap, const UCHAR *pSendBuf, DWORD len, OVERLAPPED *ovl) -{ - DWORD dwWriteLen; - - np2net_cs_EnterCriticalSection(); - if (!WriteFile(hTap, pSendBuf, len, &dwWriteLen, ovl)) { - DWORD err = GetLastError(); - np2net_cs_LeaveCriticalSection(); - if (err == ERROR_IO_PENDING) { - DWORD beginTime = GETTICK(); - int cancel = 0; - // 完了待ち - while(1){ - if (WaitForSingleObject(ovl->hEvent, 1000) == WAIT_OBJECT_0){ - BOOL result; - np2net_cs_EnterCriticalSection(); - result = GetOverlappedResult(np2net_hTap, ovl, &dwWriteLen, FALSE); - err = GetLastError(); - np2net_cs_LeaveCriticalSection(); - if(cancel){ - dwWriteLen = len; // 書けたことにする - } - if(result) break; - if (err != ERROR_IO_INCOMPLETE) { - break; - } - } - if(!cancel && GETTICK() - beginTime > 3000){ - //CancelIoEx(np2net_hTap, ovl); // 秒単位で終わらないのはおかしいのでキャンセル - cancel = 1; - } - if(np2net_hThreadexit){ - break; - } - //if(((np2net_membuf_writepos - np2net_membuf_readpos) & (NET_ARYLEN - 1)) < NET_ARYLEN/4){ - Sleep(0); - //}else{ - // Sleep(1); - //} - } - if(dwWriteLen==0){ - return 1; - } - } else { - TRACEOUT(("LGY-98: WriteFile err=0x%08X¥n", err)); - return -1; - } - }else{ - np2net_cs_LeaveCriticalSection(); - } - //TRACEOUT(("LGY-98: send %u bytes¥n", dwWriteLen)); - return 0; -} -#else - -// for Linux -// パケットデータを TAP へ書き出す -static int doWriteTap(int hTap, const UINT8 *pSendBuf, UINT32 len) -{ - #define ETHERDATALEN_MIN 46 - UINT32 dwWriteLen; - - if ((dwWriteLen = write(hTap, pSendBuf, len)) == -1) { - TRACEOUT(("LGY-98: WriteFile err")); - return -1; - } - //TRACEOUT(("LGY-98: send %u bytes\n", dwWriteLen)); - return 0; -} - -#endif // defined(NP2_WIN) - -// パケットデータをバッファに送る(実際の送信はnp2net_ThreadFuncW内で行われる) -static int sendDataToBuffer(const UINT8 *pSendBuf, UINT32 len){ - if(len > NET_BUFLEN){ - TRACEOUT(("LGY-98: too large packet!! %d bytes", len)); - return 1; - } - if(np2net_membuf_readpos==(np2net_membuf_writepos+1)%NET_ARYLEN){ - np2net_highspeedmode = 1; - TRACEOUT(("LGY-98: buffer full")); - while(np2net_membuf_readpos==(np2net_membuf_writepos+1)%NET_ARYLEN){ - //Sleep(0); // バッファがいっぱいなので待つ - return 1; // バッファがいっぱいなので捨てる - } - } - if(NET_BUFLEN < len){ - return 1; // 巨大パケット(?)は捨てる - } - memcpy(np2net_membuf[np2net_membuf_writepos], pSendBuf, len); - np2net_membuflen[np2net_membuf_writepos] = len; - np2net_membuf_writepos = (np2net_membuf_writepos+1)%NET_ARYLEN; -#if defined(NP2_WIN) - SetEvent(np2net_thread_eventhandle); -#endif - return 0; -} - -// パケット送信時に呼ばれる(デフォルト処理) -static void np2net_default_send_packet(const UINT8 *buf, int size) -{ - sendDataToBuffer(buf, size); -} -// パケット受信時に呼ばれる(デフォルト処理) -static void np2net_default_recieve_packet(const UINT8 *buf, int size) -{ - // 何もしない -} - -#if defined(NP2_WIN) -// 非同期で通信してみる(Write) -static unsigned int __stdcall np2net_ThreadFuncW(LPVOID vdParam) { - HANDLE hEvent = NULL; - OVERLAPPED ovl; - - // OVERLAPPED非同期書き込み準備 - memset(&ovl, 0, sizeof(OVERLAPPED)); - ovl.hEvent = hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if (hEvent == NULL) return 0; - ovl.Offset = 0; - ovl.OffsetHigh = 0; - - while (WaitForSingleObject(np2net_thread_eventhandle, INFINITE) == WAIT_OBJECT_0) - { - if (np2net_hThreadexit) break; - while (np2net_membuf_readpos != np2net_membuf_writepos) - { - if (np2net_hThreadexit) break; - doWriteTap(np2net_hTap, (UCHAR*)(np2net_membuf[np2net_membuf_readpos]), np2net_membuflen[np2net_membuf_readpos], &ovl); - np2net_membuf_readpos = (np2net_membuf_readpos + 1) % NET_ARYLEN; - } - } - CloseHandle(hEvent); - hEvent = NULL; - return 0; -} -// 非同期で通信してみる(Read) -static unsigned int __stdcall np2net_ThreadFuncR(LPVOID vdParam) { - HANDLE hEvent = NULL; - DWORD dwLen; - OVERLAPPED ovl; - int nodatacount = 0; - int sleepcount = 0; - int timediff = 0; - CHAR* np2net_Buf = (CHAR*)malloc(NET_BUFLEN); - if (!np2net_Buf) { - return 0; - } - - // OVERLAPPED非同期読み取り準備 - memset(&ovl, 0, sizeof(OVERLAPPED)); - ovl.hEvent = hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if (hEvent == NULL) { - free(np2net_Buf); - return 0; - } - ovl.Offset = 0; - ovl.OffsetHigh = 0; - - while (!np2net_hThreadexit) { - np2net_cs_EnterCriticalSection(); - if (!ReadFile(np2net_hTap, np2net_Buf, NET_BUFLEN, &dwLen, &ovl)) { - DWORD err = GetLastError(); - np2net_cs_LeaveCriticalSection(); - if (err == ERROR_IO_PENDING) { - // 読み取り待ち - while(1){ - if (WaitForSingleObject(ovl.hEvent, 1000) == WAIT_OBJECT_0){ - BOOL result; - np2net_cs_EnterCriticalSection(); - result = GetOverlappedResult(np2net_hTap, &ovl, &dwLen, FALSE); - err = GetLastError(); - np2net_cs_LeaveCriticalSection(); - if(result) break; - if (err != ERROR_IO_INCOMPLETE) { - break; - } - } - if(np2net_hThreadexit){ - break; - } - Sleep(0); - } - if(dwLen>0){ - //TRACEOUT(("LGY-98: recieve %u bytes¥n", dwLen)); - np2net.recieve_packet((UINT8*)np2net_Buf, dwLen); // 受信できたので通知する - } - } else { - // 読み取りエラー - printf("TAP-Win32: ReadFile err=0x%08X\n", err); - //CloseHandle(hTap); - //return -1; - Sleep(1); - } - } else { - np2net_cs_LeaveCriticalSection(); - // 読み取り成功 - if(dwLen>0){ - //TRACEOUT(("LGY-98: recieve %u bytes\n", dwLen)); - np2net.recieve_packet((UINT8*)np2net_Buf, dwLen); // 受信できたので通知する - }else{ - Sleep(1); - } - } - } - CloseHandle(hEvent); - hEvent = NULL; - free(np2net_Buf); - return 0; -} -#else - -// for Linux -// 非同期で通信してみる(Write) -static void* np2net_ThreadFuncW(void *thdata) { - while (!np2net_hThreadexit) { - if(np2net.recieve_packet != np2net_default_recieve_packet){ - if(np2net_membuf_readpos!=np2net_membuf_writepos){ - doWriteTap(np2net_hTap, np2net_membuf[np2net_membuf_readpos], np2net_membuflen[np2net_membuf_readpos]); - np2net_membuf_readpos = (np2net_membuf_readpos+1)%NET_ARYLEN; - }else{ - sched_yield(); - } - }else{ - sleep(1000); - } - } - return (void*) NULL; -} -// 非同期で通信してみる(Read) -static void* np2net_ThreadFuncR(void *thdata) { - UINT32 dwLen; - UINT8 np2net_Buf[NET_BUFLEN]; - - while (!np2net_hThreadexit) { - if ((dwLen = read(np2net_hTap, np2net_Buf, NET_BUFLEN)) < 0) { - // 読み取りエラー - printf("TAP-Win32: ReadFile err"); - sched_yield(); - } else { - // 読み取り成功 - if(dwLen>0){ - //TRACEOUT(("LGY-98: recieve %u bytes\n", dwLen)); - np2net.recieve_packet((UINT8*)np2net_Buf, dwLen); // 受信できたので通知する - np2net_highspeeddatacount += dwLen; - }else{ - sched_yield(); - } - } - } - return (void*) NULL; -} - -#endif // defined(NP2_WIN) - -// TAPデバイスを閉じる -static void np2net_closeTAP(){ -#if defined(NP2_WIN) - ULONG status = FALSE; - DWORD dwLen; - if (np2net_hTap != INVALID_HANDLE_VALUE) { - if(np2net_hThreadR){ - np2net_hThreadexit = 1; - SetEvent(np2net_thread_eventhandle); - if(WaitForSingleObject(np2net_hThreadR, 10000) == WAIT_TIMEOUT){ - TerminateThread(np2net_hThreadR, 0); - } - if(WaitForSingleObject(np2net_hThreadW, 10000) == WAIT_TIMEOUT){ - TerminateThread(np2net_hThreadW, 0); - } - np2net_membuf_readpos = np2net_membuf_writepos; - np2net_hThreadexit = 0; - CloseHandle(np2net_hThreadR); - CloseHandle(np2net_hThreadW); - np2net_hThreadR = NULL; - np2net_hThreadW = NULL; - } - - // TAP デバイスを非アクティブに - status = FALSE; - if (!DeviceIoControl(np2net_hTap,TAP_IOCTL_SET_MEDIA_STATUS, - &status, sizeof(status), &status, sizeof(status), - &dwLen, NULL)) { - TRACEOUT(("LGY-98: TAP_IOCTL_SET_MEDIA_STATUS err")); - } - - CloseHandle(np2net_hTap); - TRACEOUT(("LGY-98: TAP is closed")); - np2net_hTap = INVALID_HANDLE_VALUE; - } -#else - if (np2net_hTap >= 0) { - if(np2net_hThreadE){ - np2net_hThreadexit = 1; - pthread_join(np2net_hThreadR , NULL); - pthread_join(np2net_hThreadW , NULL); - np2net_membuf_readpos = np2net_membuf_writepos; - np2net_hThreadexit = 0; - np2net_hThreadR = NULL; - np2net_hThreadW = NULL; - np2net_hThreadE = 0; - } - close(np2net_hTap); - np2net_hTap = -1; - TRACEOUT(("LGY-98: TAP is closed")); - } -#endif // defined(NP2_WIN) -} -// TAPデバイスを開く -static int np2net_openTAP(const char* tapname){ -#if defined(NP2_WIN) - unsigned int dwID; - DWORD dwLen; - ULONG status = TRUE; - char Buf[2048]; - char DevicePath[256]; - char TAPname[MAX_PATH] = "TAP1"; - wchar_t wDevicePath[256]; - - if(*tapname){ - strcpy(TAPname, tapname); - } - - np2net_closeTAP(); - - // 指定された表示名から TAP の GUID を得る - if (!GetNetWorkDeviceGuid(TAPname, Buf, 2048)) { - TRACEOUT(("LGY-98: [%s] GUID is not found\n", TAPname)); - return 1; - } - TRACEOUT(("LGY-98: [%s] GUID = %s\n", TAPname, Buf)); - sprintf(DevicePath, DEVICE_PATH_FMT, Buf); - - // TAP デバイスを開く - codecnv_utf8toucs2(wDevicePath, MAX_PATH, DevicePath, -1); - np2net_hTap = CreateFileW(wDevicePath, GENERIC_READ | GENERIC_WRITE, - 0, 0, OPEN_EXISTING, - FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); - - if (np2net_hTap == INVALID_HANDLE_VALUE) { - DWORD err = GetLastError(); - TRACEOUT(("LGY-98: Failed to open [%s] error:%d", DevicePath, err)); - return 2; - } - - TRACEOUT(("LGY-98: TAP is opened")); - - // TAP デバイスをアクティブに - status = TRUE; - if (!DeviceIoControl(np2net_hTap,TAP_IOCTL_SET_MEDIA_STATUS, - &status, sizeof(status), &status, sizeof(status), - &dwLen, NULL)) { - TRACEOUT(("LGY-98: TAP_IOCTL_SET_MEDIA_STATUS err")); - np2net_closeTAP(); - return 3; - } - - np2net_hThreadR = (HANDLE)_beginthreadex(NULL , 0 , np2net_ThreadFuncR , NULL , 0 , &dwID); - np2net_hThreadW = (HANDLE)_beginthreadex(NULL , 0 , np2net_ThreadFuncW , NULL , 0 , &dwID); -#else - struct ifreq ifr; -#if defined(__APPLE__) - np2net_hTap = open("/dev/tap0", O_RDWR); -#else - np2net_hTap = open("/dev/net/tun", O_RDWR); -#endif - if(np2net_hTap < 0){ -#if defined(__APPLE__) - TRACEOUT(("LGY-98: Failed to open [%s]", "/dev/tap0")); -#else - TRACEOUT(("LGY-98: Failed to open [%s]", "/dev/net/tun")); -#endif - return 2; - } - memset(&ifr, 0, sizeof(ifr)); - -#if defined(__APPLE__) - strcpy(ifr.ifr_name, "tap%d"); -#else - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - strcpy(ifr.ifr_name, "tap%d"); - - if (ioctl(np2net_hTap, TUNSETIFF, (void *)&ifr) < 0) { - TRACEOUT(("LGY-98: TUNSETIFF err")); - np2net_closeTAP(); - return 3; - } -#endif - if(pthread_create(&np2net_hThreadR , NULL , np2net_ThreadFuncR , NULL) != 0){ - TRACEOUT(("LGY-98: thread_create(READ) err")); - np2net_closeTAP(); - return 3; - } - if(pthread_create(&np2net_hThreadW , NULL , np2net_ThreadFuncW , NULL) != 0){ - TRACEOUT(("LGY-98: thread_create(WRITE) err")); - np2net_closeTAP(); - return 3; - } - - TRACEOUT(("LGY-98: TAP is opened")); -#endif // defined(NP2_WIN) - return 0; -} - -// NP2起動時の処理 -void np2net_init(void) -{ -#if defined(NP2_WIN) - np2net_cs_Initialize(); -#endif // defined(NP2_WIN) - - memset(np2net_tapName, 0, sizeof(np2net_tapName)); - np2net.send_packet = np2net_default_send_packet; - np2net.recieve_packet = np2net_default_recieve_packet; -} -// リセット時に呼ばれる? -void np2net_reset(const NP2CFG *pConfig){ - strcpy(np2net_tapName, pConfig->np2nettap); - if(pConfig->uselgy98){ // XXX: 使われていないならTAPデバイスはオープンしない - np2net_openTAP(np2net_tapName); - } -} -// リセット時に呼ばれる?(np2net_resetより後・iocore_attach〜が使える) -void np2net_bind(void){ -} -// NP2終了時の処理 -void np2net_shutdown(void) -{ - np2net_hThreadexit = 1; -#if defined(NP2_WIN) - SetEvent(np2net_thread_eventhandle); -#endif - np2net_closeTAP(); - -#ifdef SUPPORT_LGY98 - lgy98_shutdown(); -#endif -#if defined(NP2_WIN) - np2net_cs_Finalize(); -#endif - -} - -#if defined(NP2_WIN) -// 参考文献: http://dsas.blog.klab.org/archives/51012690.html - -// ネットワークデバイス表示名からデバイス GUID 文字列を検索 -static char *GetNetWorkDeviceGuid(const char *pDisplayName, char *pszBuf, DWORD cbBuf) -{ - const wchar_t *SUBKEY = L"SYSTEM\\CurrentControlSet\\Control\\Network"; - -#define BUFSZ 256 - // HKLM\SYSTEM\\CurrentControlSet\\Control\\Network\{id1]\{id2}\Connection\Name が - // ネットワークデバイス名(ユニーク)の格納されたエントリであり、 - // {id2} がこのデバイスの GUID である - - HKEY hKey1, hKey2, hKey3; - LONG nResult; - DWORD dwIdx1, dwIdx2; - char szData[64]; - wchar_t *pKeyName1, *pKeyName2, *pKeyName3, *pKeyName4; - - DWORD dwSize, dwType = REG_SZ; - BOOL bDone = FALSE; - FILETIME ft; - - hKey1 = hKey2 = hKey3 = NULL; - pKeyName1 = pKeyName2 = pKeyName3 = pKeyName4 = NULL; - - // 主キーのオープン - nResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, SUBKEY, 0, KEY_READ, &hKey1); - if (nResult != ERROR_SUCCESS) { - return NULL; - } - pKeyName1 = (wchar_t*)malloc(sizeof(wchar_t)*BUFSZ); - pKeyName2 = (wchar_t*)malloc(sizeof(wchar_t)*BUFSZ); - pKeyName3 = (wchar_t*)malloc(sizeof(wchar_t)*BUFSZ); - pKeyName4 = (wchar_t*)malloc(sizeof(wchar_t)*BUFSZ); - - dwIdx1 = 0; - while (bDone != TRUE) { // {id1} を列挙するループ - - dwSize = BUFSZ; - nResult = RegEnumKeyExW(hKey1, dwIdx1++, pKeyName1, - &dwSize, NULL, NULL, NULL, &ft); - if (nResult == ERROR_NO_MORE_ITEMS) { - break; - } - - // SUBKEY\{id1} キーをオープン - swprintf(pKeyName2, BUFSZ, L"%ls\\%ls", SUBKEY, pKeyName1); - nResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, pKeyName2, - 0, KEY_READ, &hKey2); - if (nResult != ERROR_SUCCESS) { - continue; - } - dwIdx2 = 0; - while (1) { // {id2} を列挙するループ - dwSize = BUFSZ; - nResult = RegEnumKeyExW(hKey2, dwIdx2++, pKeyName3, - &dwSize, NULL, NULL, NULL, &ft); - if (nResult == ERROR_NO_MORE_ITEMS) { - break; - } - - if (nResult != ERROR_SUCCESS) { - continue; - } - - // SUBKEY\{id1}\{id2]\Connection キーをオープン - swprintf(pKeyName4, BUFSZ, L"%ls\\%ls\\%ls", - pKeyName2, pKeyName3, L"Connection"); - nResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - pKeyName4, 0, KEY_READ, &hKey3); - if (nResult != ERROR_SUCCESS) { - continue; - } - - // SUBKEY\{id1}\{id2]\Connection\Name 値を取得 - dwSize = sizeof(szData); - nResult = RegQueryValueExW(hKey3, L"Name", - 0, &dwType, (LPBYTE)szData, &dwSize); - - if (nResult == ERROR_SUCCESS) { - if (stricmp(szData, pDisplayName) == 0) { - codecnv_ucs2toutf8(pszBuf, MAX_PATH, pKeyName3, -1); - bDone = TRUE; - break; - } - } - RegCloseKey(hKey3); - hKey3 = NULL; - } - RegCloseKey(hKey2); - hKey2 = NULL; - } - - if (hKey1) { RegCloseKey(hKey1); } - if (hKey2) { RegCloseKey(hKey2); } - if (hKey3) { RegCloseKey(hKey3); } - - if (pKeyName1) { free(pKeyName1); } - if (pKeyName2) { free(pKeyName2); } - if (pKeyName3) { free(pKeyName3); } - if (pKeyName4) { free(pKeyName4); } - - // GUID を発見できず - if (bDone != TRUE) { - return NULL; - } - return pszBuf; -} -#endif // defined(NP2_WIN) - -#endif /* SUPPORT_NET */ +/** + * @file net.c + * @brief Virtual LAN Interface + * + * @author $Author: SimK $ + */ + +#include +#if defined(NP2_WIN) +#include +#else +#include +#endif +#include + +//#define TRACEOUT(a) printf(a);printf("\n"); +#define TRACEOUT(a) + +#if defined(SUPPORT_NET) + +#include +#include +#ifdef SUPPORT_LGY98 +#include +#endif + +#if defined(NP2_WIN) +#include +#include +#include + +#define stricmp _stricmp + +#pragma warning(disable: 4996) +#pragma comment(lib, "Advapi32.lib") + +#define DEVICE_PATH_FMT _T("\\\\.\\Global\\%s.tap") + +#define TAP_CONTROL_CODE(request,method) \ + CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) + +#define TAP_IOCTL_SET_MEDIA_STATUS \ + TAP_CONTROL_CODE (6, METHOD_BUFFERED) + +#else + +// for Linux +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +unsigned GetTickCount(); + +/* +unsigned GetTickCount() +{ + struct timeval tv; + if(gettimeofday(&tv, NULL) != 0) + return 0; + + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); +} +*/ + +#if defined(__APPLE__) +#include +#include +#include +#else +#include +#include +#include /* struct ethhdr */ +#endif + +#endif // defined(NP2_WIN) + +#define NET_BUFLEN (16*1024) // バッファ1つの長さ(XXX: パケットサイズの最大値にしないと無駄。もっと言えば可変長で大きな1つのバッファに入れるべき?) +#define NET_ARYLEN (128) // バッファの数 + + NP2NET np2net; + +static OEMCHAR np2net_tapName[MAX_PATH]; // TAPデバイス名 + +static int np2net_hThreadexit = 0; // スレッド終了フラグ + +#if defined(NP2_WIN) +static char *GetNetWorkDeviceGuid(const char *, char *, DWORD); // TAPデバイス名からGUIDを取得する + +static HANDLE np2net_hTap = INVALID_HANDLE_VALUE; // TAPデバイスの読み書きハンドル +static HANDLE np2net_hThreadR = NULL; // Read用スレッド +static HANDLE np2net_hThreadW = NULL; // Write用スレッド +static HANDLE np2net_thread_eventhandle = INVALID_HANDLE_VALUE; // 送受信要求用 +#else + +// for Linux +static int np2net_hTap = -1; // TAPデバイスの読み書きハンドル +static int np2net_hThreadE = 0; // Thread Running Flag +static pthread_t np2net_hThreadR = NULL; // Read用スレッド +static pthread_t np2net_hThreadW = NULL; // Write用スレッド +static pthread_t np2net_thread_eventhandle = 0; // 送受信要求用 +#endif // defined(NP2_WIN) + +static UINT8 np2net_membuf[NET_ARYLEN][NET_BUFLEN]; // 送信用バッファ +static int np2net_membuflen[NET_ARYLEN]; // 送信用バッファにあるデータの長さ +static int np2net_membuf_readpos = 0; // バッファ読み取り位置 +static int np2net_membuf_writepos = 0; // バッファ書き込み位置 + +static int np2net_pmm = 0; // CPU負荷低減モード(通信は若干遅くなると思われる) +static int np2net_highspeedmode = 0; // 高速送受信モード +static UINT32 np2net_highspeeddatacount = 0; // 送受信データ数カウンタ + +#if defined(NP2_WIN) +static BOOL np2net_cs_initialized = 0; // np2net クリティカルセクション 初期化済みフラグ +static CRITICAL_SECTION np2net_cs = {0}; // np2net クリティカルセクション +static void np2net_cs_Initialize(){ + if(!np2net_cs_initialized){ + InitializeCriticalSection(&np2net_cs); + np2net_thread_eventhandle = CreateEvent(NULL, FALSE, FALSE, NULL); + np2net_cs_initialized = TRUE; + } +} +static void np2net_cs_Finalize(){ + if(np2net_cs_initialized){ + DeleteCriticalSection(&np2net_cs); + CloseHandle(np2net_thread_eventhandle); + np2net_cs_initialized = FALSE; + } +} +void np2net_cs_EnterCriticalSection(){ + if(np2net_cs_initialized){ + EnterCriticalSection(&np2net_cs); + } +} +void np2net_cs_LeaveCriticalSection(){ + if(np2net_cs_initialized){ + LeaveCriticalSection(&np2net_cs); + } +} +#endif // defined(NP2_WIN) + +#if defined(NP2_WIN) +// パケットデータを TAP へ書き出す +static int doWriteTap(HANDLE hTap, const UCHAR *pSendBuf, DWORD len, OVERLAPPED *ovl) +{ + DWORD dwWriteLen; + + np2net_cs_EnterCriticalSection(); + if (!WriteFile(hTap, pSendBuf, len, &dwWriteLen, ovl)) { + DWORD err = GetLastError(); + np2net_cs_LeaveCriticalSection(); + if (err == ERROR_IO_PENDING) { + DWORD beginTime = GETTICK(); + int cancel = 0; + // 完了待ち + while(1){ + if (WaitForSingleObject(ovl->hEvent, 1000) == WAIT_OBJECT_0){ + BOOL result; + np2net_cs_EnterCriticalSection(); + result = GetOverlappedResult(np2net_hTap, ovl, &dwWriteLen, FALSE); + err = GetLastError(); + np2net_cs_LeaveCriticalSection(); + if(cancel){ + dwWriteLen = len; // 書けたことにする + } + if(result) break; + if (err != ERROR_IO_INCOMPLETE) { + break; + } + } + if(!cancel && GETTICK() - beginTime > 3000){ + //CancelIoEx(np2net_hTap, ovl); // 秒単位で終わらないのはおかしいのでキャンセル + cancel = 1; + } + if(np2net_hThreadexit){ + break; + } + //if(((np2net_membuf_writepos - np2net_membuf_readpos) & (NET_ARYLEN - 1)) < NET_ARYLEN/4){ + Sleep(0); + //}else{ + // Sleep(1); + //} + } + if(dwWriteLen==0){ + return 1; + } + } else { + TRACEOUT(("LGY-98: WriteFile err=0x%08X¥n", err)); + return -1; + } + }else{ + np2net_cs_LeaveCriticalSection(); + } + //TRACEOUT(("LGY-98: send %u bytes¥n", dwWriteLen)); + return 0; +} +#else + +// for Linux +// パケットデータを TAP へ書き出す +static int doWriteTap(int hTap, const UINT8 *pSendBuf, UINT32 len) +{ + #define ETHERDATALEN_MIN 46 + UINT32 dwWriteLen; + + if ((dwWriteLen = write(hTap, pSendBuf, len)) == -1) { + TRACEOUT(("LGY-98: WriteFile err")); + return -1; + } + //TRACEOUT(("LGY-98: send %u bytes\n", dwWriteLen)); + return 0; +} + +#endif // defined(NP2_WIN) + +// パケットデータをバッファに送る(実際の送信はnp2net_ThreadFuncW内で行われる) +static int sendDataToBuffer(const UINT8 *pSendBuf, UINT32 len){ + if(len > NET_BUFLEN){ + TRACEOUT(("LGY-98: too large packet!! %d bytes", len)); + return 1; + } + if(np2net_membuf_readpos==(np2net_membuf_writepos+1)%NET_ARYLEN){ + np2net_highspeedmode = 1; + TRACEOUT(("LGY-98: buffer full")); + while(np2net_membuf_readpos==(np2net_membuf_writepos+1)%NET_ARYLEN){ + //Sleep(0); // バッファがいっぱいなので待つ + return 1; // バッファがいっぱいなので捨てる + } + } + if(NET_BUFLEN < len){ + return 1; // 巨大パケット(?)は捨てる + } + memcpy(np2net_membuf[np2net_membuf_writepos], pSendBuf, len); + np2net_membuflen[np2net_membuf_writepos] = len; + np2net_membuf_writepos = (np2net_membuf_writepos+1)%NET_ARYLEN; +#if defined(NP2_WIN) + SetEvent(np2net_thread_eventhandle); +#endif + return 0; +} + +// パケット送信時に呼ばれる(デフォルト処理) +static void np2net_default_send_packet(const UINT8 *buf, int size) +{ + sendDataToBuffer(buf, size); +} +// パケット受信時に呼ばれる(デフォルト処理) +static void np2net_default_recieve_packet(const UINT8 *buf, int size) +{ + // 何もしない +} + +#if defined(NP2_WIN) +// 非同期で通信してみる(Write) +static unsigned int __stdcall np2net_ThreadFuncW(LPVOID vdParam) { + HANDLE hEvent = NULL; + OVERLAPPED ovl; + + // OVERLAPPED非同期書き込み準備 + memset(&ovl, 0, sizeof(OVERLAPPED)); + ovl.hEvent = hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (hEvent == NULL) return 0; + ovl.Offset = 0; + ovl.OffsetHigh = 0; + + while (WaitForSingleObject(np2net_thread_eventhandle, INFINITE) == WAIT_OBJECT_0) + { + if (np2net_hThreadexit) break; + while (np2net_membuf_readpos != np2net_membuf_writepos) + { + if (np2net_hThreadexit) break; + doWriteTap(np2net_hTap, (UCHAR*)(np2net_membuf[np2net_membuf_readpos]), np2net_membuflen[np2net_membuf_readpos], &ovl); + np2net_membuf_readpos = (np2net_membuf_readpos + 1) % NET_ARYLEN; + } + } + CloseHandle(hEvent); + hEvent = NULL; + return 0; +} +// 非同期で通信してみる(Read) +static unsigned int __stdcall np2net_ThreadFuncR(LPVOID vdParam) { + HANDLE hEvent = NULL; + DWORD dwLen; + OVERLAPPED ovl; + int nodatacount = 0; + int sleepcount = 0; + int timediff = 0; + CHAR* np2net_Buf = (CHAR*)malloc(NET_BUFLEN); + if (!np2net_Buf) { + return 0; + } + + // OVERLAPPED非同期読み取り準備 + memset(&ovl, 0, sizeof(OVERLAPPED)); + ovl.hEvent = hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (hEvent == NULL) { + free(np2net_Buf); + return 0; + } + ovl.Offset = 0; + ovl.OffsetHigh = 0; + + while (!np2net_hThreadexit) { + np2net_cs_EnterCriticalSection(); + if (!ReadFile(np2net_hTap, np2net_Buf, NET_BUFLEN, &dwLen, &ovl)) { + DWORD err = GetLastError(); + np2net_cs_LeaveCriticalSection(); + if (err == ERROR_IO_PENDING) { + // 読み取り待ち + while(1){ + if (WaitForSingleObject(ovl.hEvent, 1000) == WAIT_OBJECT_0){ + BOOL result; + np2net_cs_EnterCriticalSection(); + result = GetOverlappedResult(np2net_hTap, &ovl, &dwLen, FALSE); + err = GetLastError(); + np2net_cs_LeaveCriticalSection(); + if(result) break; + if (err != ERROR_IO_INCOMPLETE) { + break; + } + } + if(np2net_hThreadexit){ + break; + } + Sleep(0); + } + if(dwLen>0){ + //TRACEOUT(("LGY-98: recieve %u bytes¥n", dwLen)); + np2net.recieve_packet((UINT8*)np2net_Buf, dwLen); // 受信できたので通知する + } + } else { + // 読み取りエラー + printf("TAP-Win32: ReadFile err=0x%08X\n", err); + //CloseHandle(hTap); + //return -1; + Sleep(1); + } + } else { + np2net_cs_LeaveCriticalSection(); + // 読み取り成功 + if(dwLen>0){ + //TRACEOUT(("LGY-98: recieve %u bytes\n", dwLen)); + np2net.recieve_packet((UINT8*)np2net_Buf, dwLen); // 受信できたので通知する + }else{ + Sleep(1); + } + } + } + CloseHandle(hEvent); + hEvent = NULL; + free(np2net_Buf); + return 0; +} +#else + +// for Linux +// 非同期で通信してみる(Write) +static void* np2net_ThreadFuncW(void *thdata) { + while (!np2net_hThreadexit) { + if(np2net.recieve_packet != np2net_default_recieve_packet){ + if(np2net_membuf_readpos!=np2net_membuf_writepos){ + doWriteTap(np2net_hTap, np2net_membuf[np2net_membuf_readpos], np2net_membuflen[np2net_membuf_readpos]); + np2net_membuf_readpos = (np2net_membuf_readpos+1)%NET_ARYLEN; + }else{ + sched_yield(); + } + }else{ + sleep(1000); + } + } + return (void*) NULL; +} +// 非同期で通信してみる(Read) +static void* np2net_ThreadFuncR(void *thdata) { + UINT32 dwLen; + UINT8 np2net_Buf[NET_BUFLEN]; + + while (!np2net_hThreadexit) { + if ((dwLen = read(np2net_hTap, np2net_Buf, NET_BUFLEN)) < 0) { + // 読み取りエラー + printf("TAP-Win32: ReadFile err"); + sched_yield(); + } else { + // 読み取り成功 + if(dwLen>0){ + //TRACEOUT(("LGY-98: recieve %u bytes\n", dwLen)); + np2net.recieve_packet((UINT8*)np2net_Buf, dwLen); // 受信できたので通知する + np2net_highspeeddatacount += dwLen; + }else{ + sched_yield(); + } + } + } + return (void*) NULL; +} + +#endif // defined(NP2_WIN) + +// TAPデバイスを閉じる +static void np2net_closeTAP(){ +#if defined(NP2_WIN) + ULONG status = FALSE; + DWORD dwLen; + if (np2net_hTap != INVALID_HANDLE_VALUE) { + if(np2net_hThreadR){ + np2net_hThreadexit = 1; + SetEvent(np2net_thread_eventhandle); + if(WaitForSingleObject(np2net_hThreadR, 10000) == WAIT_TIMEOUT){ + TerminateThread(np2net_hThreadR, 0); + } + if(WaitForSingleObject(np2net_hThreadW, 10000) == WAIT_TIMEOUT){ + TerminateThread(np2net_hThreadW, 0); + } + np2net_membuf_readpos = np2net_membuf_writepos; + np2net_hThreadexit = 0; + CloseHandle(np2net_hThreadR); + CloseHandle(np2net_hThreadW); + np2net_hThreadR = NULL; + np2net_hThreadW = NULL; + } + + // TAP デバイスを非アクティブに + status = FALSE; + if (!DeviceIoControl(np2net_hTap,TAP_IOCTL_SET_MEDIA_STATUS, + &status, sizeof(status), &status, sizeof(status), + &dwLen, NULL)) { + TRACEOUT(("LGY-98: TAP_IOCTL_SET_MEDIA_STATUS err")); + } + + CloseHandle(np2net_hTap); + TRACEOUT(("LGY-98: TAP is closed")); + np2net_hTap = INVALID_HANDLE_VALUE; + } +#else + if (np2net_hTap >= 0) { + if(np2net_hThreadE){ + np2net_hThreadexit = 1; + pthread_join(np2net_hThreadR , NULL); + pthread_join(np2net_hThreadW , NULL); + np2net_membuf_readpos = np2net_membuf_writepos; + np2net_hThreadexit = 0; + np2net_hThreadR = NULL; + np2net_hThreadW = NULL; + np2net_hThreadE = 0; + } + close(np2net_hTap); + np2net_hTap = -1; + TRACEOUT(("LGY-98: TAP is closed")); + } +#endif // defined(NP2_WIN) +} +// TAPデバイスを開く +static int np2net_openTAP(const char* tapname){ +#if defined(NP2_WIN) + unsigned int dwID; + DWORD dwLen; + ULONG status = TRUE; + char Buf[2048]; + char DevicePath[256]; + char TAPname[MAX_PATH] = "TAP1"; + wchar_t wDevicePath[256]; + + if(*tapname){ + strcpy(TAPname, tapname); + } + + np2net_closeTAP(); + + // 指定された表示名から TAP の GUID を得る + if (!GetNetWorkDeviceGuid(TAPname, Buf, 2048)) { + TRACEOUT(("LGY-98: [%s] GUID is not found\n", TAPname)); + return 1; + } + TRACEOUT(("LGY-98: [%s] GUID = %s\n", TAPname, Buf)); + sprintf(DevicePath, DEVICE_PATH_FMT, Buf); + + // TAP デバイスを開く + codecnv_utf8toucs2(wDevicePath, MAX_PATH, DevicePath, -1); + np2net_hTap = CreateFileW(wDevicePath, GENERIC_READ | GENERIC_WRITE, + 0, 0, OPEN_EXISTING, + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0); + + if (np2net_hTap == INVALID_HANDLE_VALUE) { + DWORD err = GetLastError(); + TRACEOUT(("LGY-98: Failed to open [%s] error:%d", DevicePath, err)); + return 2; + } + + TRACEOUT(("LGY-98: TAP is opened")); + + // TAP デバイスをアクティブに + status = TRUE; + if (!DeviceIoControl(np2net_hTap,TAP_IOCTL_SET_MEDIA_STATUS, + &status, sizeof(status), &status, sizeof(status), + &dwLen, NULL)) { + TRACEOUT(("LGY-98: TAP_IOCTL_SET_MEDIA_STATUS err")); + np2net_closeTAP(); + return 3; + } + + np2net_hThreadR = (HANDLE)_beginthreadex(NULL , 0 , np2net_ThreadFuncR , NULL , 0 , &dwID); + np2net_hThreadW = (HANDLE)_beginthreadex(NULL , 0 , np2net_ThreadFuncW , NULL , 0 , &dwID); +#else + struct ifreq ifr; +#if defined(__APPLE__) + np2net_hTap = open("/dev/tap0", O_RDWR); +#else + np2net_hTap = open("/dev/net/tun", O_RDWR); +#endif + if(np2net_hTap < 0){ +#if defined(__APPLE__) + TRACEOUT(("LGY-98: Failed to open [%s]", "/dev/tap0")); +#else + TRACEOUT(("LGY-98: Failed to open [%s]", "/dev/net/tun")); +#endif + return 2; + } + memset(&ifr, 0, sizeof(ifr)); + +#if defined(__APPLE__) + strcpy(ifr.ifr_name, "tap%d"); +#else + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + strcpy(ifr.ifr_name, "tap%d"); + + if (ioctl(np2net_hTap, TUNSETIFF, (void *)&ifr) < 0) { + TRACEOUT(("LGY-98: TUNSETIFF err")); + np2net_closeTAP(); + return 3; + } +#endif + if(pthread_create(&np2net_hThreadR , NULL , np2net_ThreadFuncR , NULL) != 0){ + TRACEOUT(("LGY-98: thread_create(READ) err")); + np2net_closeTAP(); + return 3; + } + if(pthread_create(&np2net_hThreadW , NULL , np2net_ThreadFuncW , NULL) != 0){ + TRACEOUT(("LGY-98: thread_create(WRITE) err")); + np2net_closeTAP(); + return 3; + } + + TRACEOUT(("LGY-98: TAP is opened")); +#endif // defined(NP2_WIN) + return 0; +} + +// NP2起動時の処理 +void np2net_init(void) +{ +#if defined(NP2_WIN) + np2net_cs_Initialize(); +#endif // defined(NP2_WIN) + + memset(np2net_tapName, 0, sizeof(np2net_tapName)); + np2net.send_packet = np2net_default_send_packet; + np2net.recieve_packet = np2net_default_recieve_packet; +} +// リセット時に呼ばれる? +void np2net_reset(const NP2CFG *pConfig){ + strcpy(np2net_tapName, pConfig->np2nettap); + if(pConfig->uselgy98){ // XXX: 使われていないならTAPデバイスはオープンしない + np2net_openTAP(np2net_tapName); + } +} +// リセット時に呼ばれる?(np2net_resetより後・iocore_attach〜が使える) +void np2net_bind(void){ +} +// NP2終了時の処理 +void np2net_shutdown(void) +{ + np2net_hThreadexit = 1; +#if defined(NP2_WIN) + SetEvent(np2net_thread_eventhandle); +#endif + np2net_closeTAP(); + +#ifdef SUPPORT_LGY98 + lgy98_shutdown(); +#endif +#if defined(NP2_WIN) + np2net_cs_Finalize(); +#endif + +} + +#if defined(NP2_WIN) +// 参考文献: http://dsas.blog.klab.org/archives/51012690.html + +// ネットワークデバイス表示名からデバイス GUID 文字列を検索 +static char *GetNetWorkDeviceGuid(const char *pDisplayName, char *pszBuf, DWORD cbBuf) +{ + const wchar_t *SUBKEY = L"SYSTEM\\CurrentControlSet\\Control\\Network"; + +#define BUFSZ 256 + // HKLM\SYSTEM\\CurrentControlSet\\Control\\Network\{id1]\{id2}\Connection\Name が + // ネットワークデバイス名(ユニーク)の格納されたエントリであり、 + // {id2} がこのデバイスの GUID である + + HKEY hKey1, hKey2, hKey3; + LONG nResult; + DWORD dwIdx1, dwIdx2; + char szData[64]; + wchar_t *pKeyName1, *pKeyName2, *pKeyName3, *pKeyName4; + + DWORD dwSize, dwType = REG_SZ; + BOOL bDone = FALSE; + FILETIME ft; + + hKey1 = hKey2 = hKey3 = NULL; + pKeyName1 = pKeyName2 = pKeyName3 = pKeyName4 = NULL; + + // 主キーのオープン + nResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, SUBKEY, 0, KEY_READ, &hKey1); + if (nResult != ERROR_SUCCESS) { + return NULL; + } + pKeyName1 = (wchar_t*)malloc(sizeof(wchar_t)*BUFSZ); + pKeyName2 = (wchar_t*)malloc(sizeof(wchar_t)*BUFSZ); + pKeyName3 = (wchar_t*)malloc(sizeof(wchar_t)*BUFSZ); + pKeyName4 = (wchar_t*)malloc(sizeof(wchar_t)*BUFSZ); + + dwIdx1 = 0; + while (bDone != TRUE) { // {id1} を列挙するループ + + dwSize = BUFSZ; + nResult = RegEnumKeyExW(hKey1, dwIdx1++, pKeyName1, + &dwSize, NULL, NULL, NULL, &ft); + if (nResult == ERROR_NO_MORE_ITEMS) { + break; + } + + // SUBKEY\{id1} キーをオープン + swprintf(pKeyName2, BUFSZ, L"%ls\\%ls", SUBKEY, pKeyName1); + nResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, pKeyName2, + 0, KEY_READ, &hKey2); + if (nResult != ERROR_SUCCESS) { + continue; + } + dwIdx2 = 0; + while (1) { // {id2} を列挙するループ + dwSize = BUFSZ; + nResult = RegEnumKeyExW(hKey2, dwIdx2++, pKeyName3, + &dwSize, NULL, NULL, NULL, &ft); + if (nResult == ERROR_NO_MORE_ITEMS) { + break; + } + + if (nResult != ERROR_SUCCESS) { + continue; + } + + // SUBKEY\{id1}\{id2]\Connection キーをオープン + swprintf(pKeyName4, BUFSZ, L"%ls\\%ls\\%ls", + pKeyName2, pKeyName3, L"Connection"); + nResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + pKeyName4, 0, KEY_READ, &hKey3); + if (nResult != ERROR_SUCCESS) { + continue; + } + + // SUBKEY\{id1}\{id2]\Connection\Name 値を取得 + dwSize = sizeof(szData); + nResult = RegQueryValueExW(hKey3, L"Name", + 0, &dwType, (LPBYTE)szData, &dwSize); + + if (nResult == ERROR_SUCCESS) { + if (stricmp(szData, pDisplayName) == 0) { + codecnv_ucs2toutf8(pszBuf, MAX_PATH, pKeyName3, -1); + bDone = TRUE; + break; + } + } + RegCloseKey(hKey3); + hKey3 = NULL; + } + RegCloseKey(hKey2); + hKey2 = NULL; + } + + if (hKey1) { RegCloseKey(hKey1); } + if (hKey2) { RegCloseKey(hKey2); } + if (hKey3) { RegCloseKey(hKey3); } + + if (pKeyName1) { free(pKeyName1); } + if (pKeyName2) { free(pKeyName2); } + if (pKeyName3) { free(pKeyName3); } + if (pKeyName4) { free(pKeyName4); } + + // GUID を発見できず + if (bDone != TRUE) { + return NULL; + } + return pszBuf; +} +#endif // defined(NP2_WIN) + +#endif /* SUPPORT_NET */ diff --git a/network/net.h b/network/net.h old mode 100755 new mode 100644 index 862464ec..e708546c --- a/network/net.h +++ b/network/net.h @@ -1,28 +1,28 @@ -/** - * @file net.h - * @brief Virtual LAN Interface - * - * @author $Author: SimK $ - */ - -typedef void NP2NET_PacketHandler(const UINT8 *buf, int size); - -// send_packetはデータをLANに送信したいときに外から呼ばれます。データを送信する関数を作ってセットしてやってください。 -// recieve_packetはLANからデータを受信したときに呼んでください。この関数はリセット時にデバイスがセットしに来るので作る必要はありません。 -// 現在はTAPデバイスのみのサポートですが、send_packetとrecieve_packetに相当する物を作ってやればTAP以外でもOKなはず -typedef struct { - NP2NET_PacketHandler *send_packet; - NP2NET_PacketHandler *recieve_packet; -} NP2NET; - -#ifdef __cplusplus -extern "C" void np2net_init(void); -extern "C" void np2net_shutdown(void); -#else -extern void np2net_init(void); -extern void np2net_shutdown(void); -#endif -void np2net_reset(const NP2CFG *pConfig); -void np2net_bind(void); - +/** + * @file net.h + * @brief Virtual LAN Interface + * + * @author $Author: SimK $ + */ + +typedef void NP2NET_PacketHandler(const UINT8 *buf, int size); + +// send_packetはデータをLANに送信したいときに外から呼ばれます。データを送信する関数を作ってセットしてやってください。 +// recieve_packetはLANからデータを受信したときに呼んでください。この関数はリセット時にデバイスがセットしに来るので作る必要はありません。 +// 現在はTAPデバイスのみのサポートですが、send_packetとrecieve_packetに相当する物を作ってやればTAP以外でもOKなはず +typedef struct { + NP2NET_PacketHandler *send_packet; + NP2NET_PacketHandler *recieve_packet; +} NP2NET; + +#ifdef __cplusplus +extern "C" void np2net_init(void); +extern "C" void np2net_shutdown(void); +#else +extern void np2net_init(void); +extern void np2net_shutdown(void); +#endif +void np2net_reset(const NP2CFG *pConfig); +void np2net_bind(void); + extern NP2NET np2net; \ No newline at end of file diff --git a/network/readme.txt b/network/readme.txt old mode 100755 new mode 100644 index 86b0896b..6a0abbb5 --- a/network/readme.txt +++ b/network/readme.txt @@ -1,8 +1,8 @@ -Neko Project 21/WのLGY-98をxnp2に移植してみたものです。 -必要最小限のソースコード(Windows依存コードの修正部分)のみの提供となりますので、別でダウンロードしたxnp2を適当に変更してやってください - -1,np21w Win版を参考に付属ソース以外の場所も変更が必要です(SUPPORT_NETまたはSUPPORT_LGY98で囲まれているところ) -2,LinuxのTAPを使うためにはroot権限が要るかも -3,xnp21を起動するとtap0みたいなものが作成されますが、何処にもつながっていないのでホスト側でブリッジに繋ぐなりしてやらないとダメっぽい - +Neko Project 21/WのLGY-98をxnp2に移植してみたものです。 +必要最小限のソースコード(Windows依存コードの修正部分)のみの提供となりますので、別でダウンロードしたxnp2を適当に変更してやってください + +1,np21w Win版を参考に付属ソース以外の場所も変更が必要です(SUPPORT_NETまたはSUPPORT_LGY98で囲まれているところ) +2,LinuxのTAPを使うためにはroot権限が要るかも +3,xnp21を起動するとtap0みたいなものが作成されますが、何処にもつながっていないのでホスト側でブリッジに繋ぐなりしてやらないとダメっぽい + 他にもあった気がしますが忘れました・・・ \ No newline at end of file diff --git a/nevent.c b/nevent.c old mode 100755 new mode 100644 index 46056a23..78b7c329 --- a/nevent.c +++ b/nevent.c @@ -1,461 +1,461 @@ -/** - * @file nevent.c - * @brief Implementation of the event - */ - -#include -#include -#include -#include - - _NEVENT g_nevent; -#if 0 -#undef TRACEOUT -#define TRACEOUT(s) (void)(s) -static void trace_fmt_ex(const char* fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#endif /* 1 */ - - _NEVENT g_nevent; - -#if defined(SUPPORT_MULTITHREAD) -static int nevent_cs_initialized = 0; -static CRITICAL_SECTION nevent_cs; - -static BOOL nevent_tryenter_criticalsection(void){ - if(!nevent_cs_initialized) return TRUE; - return TryEnterCriticalSection(&nevent_cs); -} -static void nevent_enter_criticalsection(void){ - if(!nevent_cs_initialized) return; - EnterCriticalSection(&nevent_cs); -} -static void nevent_leave_criticalsection(void){ - if(!nevent_cs_initialized) return; - LeaveCriticalSection(&nevent_cs); -} - -void nevent_initialize(void) -{ - /* クリティカルセクション準備 */ - if(!nevent_cs_initialized){ - memset(&nevent_cs, 0, sizeof(nevent_cs)); - InitializeCriticalSection(&nevent_cs); - nevent_cs_initialized = 1; - } -} -void nevent_shutdown(void) -{ - /* クリティカルセクション破棄 */ - if(nevent_cs_initialized){ - memset(&nevent_cs, 0, sizeof(nevent_cs)); - DeleteCriticalSection(&nevent_cs); - nevent_cs_initialized = 0; - } -} -#endif - -void nevent_allreset(void) -{ - /* すべてをリセット */ - memset(&g_nevent, 0, sizeof(g_nevent)); -} - -void nevent_get1stevent(void) -{ -#if defined(SUPPORT_MULTITHREAD) - nevent_enter_criticalsection(); -#endif - /* 最短のイベントのクロック数をセット */ - if (g_nevent.readyevents) - { - CPU_BASECLOCK = g_nevent.item[g_nevent.level[0]].clock; - } - else - { - /* イベントがない場合のクロック数をセット */ - CPU_BASECLOCK = NEVENT_MAXCLOCK; - } - - /* カウンタへセット */ - CPU_REMCLOCK = CPU_BASECLOCK; - -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif -} - -static void nevent_execute(void) -{ - UINT nEvents; - UINT i; - NEVENTID id; - NEVENTITEM item; - -#if defined(SUPPORT_MULTITHREAD) - nevent_enter_criticalsection(); -#endif - nEvents = 0; - for (i = 0; i < g_nevent.waitevents; i++) - { - id = g_nevent.waitevent[i]; - item = &g_nevent.item[id]; - - /* コールバックの実行 */ - if (item->proc != NULL) - { - item->proc(item); - - /* 次回に持ち越しのイベントのチェック */ - if (item->flag & NEVENT_WAIT) - { - g_nevent.waitevent[nEvents++] = id; - } - } - else { - item->flag &= ~(NEVENT_WAIT); - } - item->flag &= ~(NEVENT_SETEVENT); - } - g_nevent.waitevents = nEvents; -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif -} - -void nevent_progress(void) -{ - UINT nEvents; - SINT32 nextbase; - UINT i; - NEVENTID id; - NEVENTITEM item; - UINT8 fevtchk = 0; - -#if defined(SUPPORT_MULTITHREAD) - nevent_enter_criticalsection(); -#endif - CPU_CLOCK += CPU_BASECLOCK; - nEvents = 0; - nextbase = NEVENT_MAXCLOCK; - for (i = 0; i < g_nevent.readyevents; i++) - { - id = g_nevent.level[i]; - item = &g_nevent.item[id]; - item->clock -= CPU_BASECLOCK; - if (item->clock > 0) - { - /* イベント待ち中 */ - g_nevent.level[nEvents++] = id; - if (nextbase >= item->clock) - { - nextbase = item->clock; - } - } - else - { - /* イベント発生 */ - if (!(item->flag & (NEVENT_SETEVENT | NEVENT_WAIT))) - { - g_nevent.waitevent[g_nevent.waitevents++] = id; - } - item->flag |= NEVENT_SETEVENT; - item->flag &= ~(NEVENT_ENABLE); -// TRACEOUT(("event = %x", id)); -#if defined(SUPPORT_ASYNC_CPU) - pccore_asynccpustat.screendisp = (id == NEVENT_FLAMES && g_nevent.item[NEVENT_FLAMES].proc == screendisp); -#endif - } - fevtchk |= (id==NEVENT_FLAMES ? 1 : 0); - } - g_nevent.readyevents = nEvents; - CPU_BASECLOCK = nextbase; - CPU_REMCLOCK += nextbase; - nevent_execute(); - - // NEVENT_FLAMESが消える問題に暫定対処 - if(!fevtchk){ - //printf("NEVENT_FLAMES is missing!!¥n"); - pcstat.screendispflag = 0; - } -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif -// TRACEOUT(("nextbase = %d (%d)", nextbase, CPU_REMCLOCK)); -} - -void nevent_changeclock(UINT32 oldclock, UINT32 newclock) -{ - UINT i; - NEVENTID id; - NEVENTITEM item; - SINT32 baseClock; - SINT32 remClock; - -#if defined(SUPPORT_MULTITHREAD) - nevent_enter_criticalsection(); -#endif - - if (oldclock > 0) - { - if (g_nevent.readyevents) - { - // イベントのクロック数を修正 - for (i = 0; i < g_nevent.readyevents; i++) - { - id = g_nevent.level[i]; - item = &g_nevent.item[id]; - if (item->clock > 0) - { - SINT64 newClock = ((SINT64)item->clock * newclock + oldclock / 2) / oldclock; - if (item->clock > 0 && newClock <= 0) newClock = 1; - if (newClock > INT_MAX) newClock = INT_MAX; - item->clock = (SINT32)newClock; - } - } - - // 自動調整のクロック変更のタイミングは CPU_BASECLOCK==CPU_REMCLOCK のタイミングになるように調整済み - if (CPU_BASECLOCK == CPU_REMCLOCK) { - CPU_BASECLOCK = g_nevent.item[g_nevent.level[0]].clock; - CPU_REMCLOCK = CPU_BASECLOCK;/* カウンタへセット */ - } - else { - // I/O経由の場合はずれている場合あり。この場合はスケール - CPU_BASECLOCK = ((SINT64)CPU_BASECLOCK * newclock + oldclock / 2) / oldclock; - CPU_REMCLOCK = ((SINT64)CPU_REMCLOCK * newclock + oldclock / 2) / oldclock; - } - } - } -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif - -} - -void nevent_reset(NEVENTID id) -{ - UINT i; - -#if defined(SUPPORT_MULTITHREAD) - nevent_enter_criticalsection(); -#endif - /* 現在進行してるイベントを検索 */ - for (i = 0; i < g_nevent.readyevents; i++) - { - if (g_nevent.level[i] == id) - { - break; - } - } - /* イベントは存在した? */ - if (i < g_nevent.readyevents) - { - /* 存在していたら削る */ - g_nevent.readyevents--; - for (; i < g_nevent.readyevents; i++) - { - g_nevent.level[i] = g_nevent.level[i + 1]; - } - } -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif -} - -void nevent_waitreset(NEVENTID id) -{ - UINT i; - -#if defined(SUPPORT_MULTITHREAD) - nevent_enter_criticalsection(); -#endif - /* 現在進行してるイベントを検索 */ - for (i = 0; i < g_nevent.waitevents; i++) - { - if (g_nevent.waitevent[i] == id) - { - break; - } - } - /* イベントは存在した? */ - if (i < g_nevent.waitevents) - { - /* 存在していたら削る */ - g_nevent.waitevents--; - for (; i < g_nevent.waitevents; i++) - { - g_nevent.waitevent[i] = g_nevent.waitevent[i + 1]; - } - } -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif -} - -void nevent_set(NEVENTID id, SINT32 eventclock, NEVENTCB proc, NEVENTPOSITION absolute) -{ - SINT32 clk; - NEVENTITEM item; - UINT eventId; - UINT i; - -#if defined(SUPPORT_MULTITHREAD) - nevent_enter_criticalsection(); -#endif -// TRACEOUT(("event %d - %xclocks", id, eventclock)); - - clk = CPU_BASECLOCK - CPU_REMCLOCK; - item = &g_nevent.item[id]; - item->proc = proc; - item->flag = 0; - if (absolute) - { - item->clock = eventclock + clk; - } - else - { - item->clock += eventclock; - } -#if 0 - if (item->clock < clk) - { - item->clock = clk; - } -#endif - /* イベントの削除 */ - nevent_reset(id); - - /* イベントの挿入位置の検索 */ - for (eventId = 0; eventId < g_nevent.readyevents; eventId++) - { - if (item->clock < g_nevent.item[g_nevent.level[eventId]].clock) - { - break; - } - } - - /* イベントの挿入 */ - for (i = g_nevent.readyevents; i > eventId; i--) - { - g_nevent.level[i] = g_nevent.level[i - 1]; - } - g_nevent.level[eventId] = id; - g_nevent.readyevents++; - - /* もし最短イベントだったら... */ - if (eventId == 0) - { - clk = CPU_BASECLOCK - item->clock; - CPU_BASECLOCK -= clk; - CPU_REMCLOCK -= clk; -// TRACEOUT(("reset nextbase -%d (%d)", clock, CPU_REMCLOCK)); - } -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif -} - -void nevent_setbyms(NEVENTID id, SINT32 ms, NEVENTCB proc, NEVENTPOSITION absolute) -{ - UINT64 waittime = (UINT64)(pccore.realclock / 1000) * ms; - if (waittime > INT_MAX - pccore.realclock) - { - nevent_set(id, INT_MAX - pccore.realclock, proc, absolute); - } - else - { - nevent_set(id, (SINT32)waittime, proc, absolute); - } -} - -BOOL nevent_iswork(NEVENTID id) -{ - UINT i; - -#if defined(SUPPORT_MULTITHREAD) - nevent_enter_criticalsection(); -#endif - /* 現在進行してるイベントを検索 */ - for (i = 0; i < g_nevent.readyevents; i++) - { - if (g_nevent.level[i] == id) - { -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif - return TRUE; - } - } -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif - return FALSE; -} - -void nevent_forceexecute(NEVENTID id) -{ - NEVENTITEM item; - -#if defined(SUPPORT_MULTITHREAD) - nevent_enter_criticalsection(); -#endif - item = &g_nevent.item[id]; - - /* コールバックの実行 */ - if (item->proc != NULL) - { - item->proc(item); - } -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif -} - -SINT32 nevent_getremain(NEVENTID id) -{ - UINT i; - -#if defined(SUPPORT_MULTITHREAD) - nevent_enter_criticalsection(); -#endif - /* 現在進行してるイベントを検索 */ - for (i = 0; i < g_nevent.readyevents; i++) - { - if (g_nevent.level[i] == id) - { - SINT32 result = (g_nevent.item[id].clock - (CPU_BASECLOCK - CPU_REMCLOCK)); -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif - return result; - } - } -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif - return -1; -} - -void nevent_forceexit(void) -{ -#if defined(SUPPORT_MULTITHREAD) - nevent_enter_criticalsection(); -#endif - if (CPU_REMCLOCK > 0) - { - CPU_BASECLOCK -= CPU_REMCLOCK; - CPU_REMCLOCK = 0; - } -#if defined(SUPPORT_MULTITHREAD) - nevent_leave_criticalsection(); -#endif -} +/** + * @file nevent.c + * @brief Implementation of the event + */ + +#include +#include +#include +#include + + _NEVENT g_nevent; +#if 0 +#undef TRACEOUT +#define TRACEOUT(s) (void)(s) +static void trace_fmt_ex(const char* fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "¥n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#endif /* 1 */ + + _NEVENT g_nevent; + +#if defined(SUPPORT_MULTITHREAD) +static int nevent_cs_initialized = 0; +static CRITICAL_SECTION nevent_cs; + +static BOOL nevent_tryenter_criticalsection(void){ + if(!nevent_cs_initialized) return TRUE; + return TryEnterCriticalSection(&nevent_cs); +} +static void nevent_enter_criticalsection(void){ + if(!nevent_cs_initialized) return; + EnterCriticalSection(&nevent_cs); +} +static void nevent_leave_criticalsection(void){ + if(!nevent_cs_initialized) return; + LeaveCriticalSection(&nevent_cs); +} + +void nevent_initialize(void) +{ + /* クリティカルセクション準備 */ + if(!nevent_cs_initialized){ + memset(&nevent_cs, 0, sizeof(nevent_cs)); + InitializeCriticalSection(&nevent_cs); + nevent_cs_initialized = 1; + } +} +void nevent_shutdown(void) +{ + /* クリティカルセクション破棄 */ + if(nevent_cs_initialized){ + memset(&nevent_cs, 0, sizeof(nevent_cs)); + DeleteCriticalSection(&nevent_cs); + nevent_cs_initialized = 0; + } +} +#endif + +void nevent_allreset(void) +{ + /* すべてをリセット */ + memset(&g_nevent, 0, sizeof(g_nevent)); +} + +void nevent_get1stevent(void) +{ +#if defined(SUPPORT_MULTITHREAD) + nevent_enter_criticalsection(); +#endif + /* 最短のイベントのクロック数をセット */ + if (g_nevent.readyevents) + { + CPU_BASECLOCK = g_nevent.item[g_nevent.level[0]].clock; + } + else + { + /* イベントがない場合のクロック数をセット */ + CPU_BASECLOCK = NEVENT_MAXCLOCK; + } + + /* カウンタへセット */ + CPU_REMCLOCK = CPU_BASECLOCK; + +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif +} + +static void nevent_execute(void) +{ + UINT nEvents; + UINT i; + NEVENTID id; + NEVENTITEM item; + +#if defined(SUPPORT_MULTITHREAD) + nevent_enter_criticalsection(); +#endif + nEvents = 0; + for (i = 0; i < g_nevent.waitevents; i++) + { + id = g_nevent.waitevent[i]; + item = &g_nevent.item[id]; + + /* コールバックの実行 */ + if (item->proc != NULL) + { + item->proc(item); + + /* 次回に持ち越しのイベントのチェック */ + if (item->flag & NEVENT_WAIT) + { + g_nevent.waitevent[nEvents++] = id; + } + } + else { + item->flag &= ~(NEVENT_WAIT); + } + item->flag &= ~(NEVENT_SETEVENT); + } + g_nevent.waitevents = nEvents; +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif +} + +void nevent_progress(void) +{ + UINT nEvents; + SINT32 nextbase; + UINT i; + NEVENTID id; + NEVENTITEM item; + UINT8 fevtchk = 0; + +#if defined(SUPPORT_MULTITHREAD) + nevent_enter_criticalsection(); +#endif + CPU_CLOCK += CPU_BASECLOCK; + nEvents = 0; + nextbase = NEVENT_MAXCLOCK; + for (i = 0; i < g_nevent.readyevents; i++) + { + id = g_nevent.level[i]; + item = &g_nevent.item[id]; + item->clock -= CPU_BASECLOCK; + if (item->clock > 0) + { + /* イベント待ち中 */ + g_nevent.level[nEvents++] = id; + if (nextbase >= item->clock) + { + nextbase = item->clock; + } + } + else + { + /* イベント発生 */ + if (!(item->flag & (NEVENT_SETEVENT | NEVENT_WAIT))) + { + g_nevent.waitevent[g_nevent.waitevents++] = id; + } + item->flag |= NEVENT_SETEVENT; + item->flag &= ~(NEVENT_ENABLE); +// TRACEOUT(("event = %x", id)); +#if defined(SUPPORT_ASYNC_CPU) + pccore_asynccpustat.screendisp = (id == NEVENT_FLAMES && g_nevent.item[NEVENT_FLAMES].proc == screendisp); +#endif + } + fevtchk |= (id==NEVENT_FLAMES ? 1 : 0); + } + g_nevent.readyevents = nEvents; + CPU_BASECLOCK = nextbase; + CPU_REMCLOCK += nextbase; + nevent_execute(); + + // NEVENT_FLAMESが消える問題に暫定対処 + if(!fevtchk){ + //printf("NEVENT_FLAMES is missing!!¥n"); + pcstat.screendispflag = 0; + } +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif +// TRACEOUT(("nextbase = %d (%d)", nextbase, CPU_REMCLOCK)); +} + +void nevent_changeclock(UINT32 oldclock, UINT32 newclock) +{ + UINT i; + NEVENTID id; + NEVENTITEM item; + SINT32 baseClock; + SINT32 remClock; + +#if defined(SUPPORT_MULTITHREAD) + nevent_enter_criticalsection(); +#endif + + if (oldclock > 0) + { + if (g_nevent.readyevents) + { + // イベントのクロック数を修正 + for (i = 0; i < g_nevent.readyevents; i++) + { + id = g_nevent.level[i]; + item = &g_nevent.item[id]; + if (item->clock > 0) + { + SINT64 newClock = ((SINT64)item->clock * newclock + oldclock / 2) / oldclock; + if (item->clock > 0 && newClock <= 0) newClock = 1; + if (newClock > INT_MAX) newClock = INT_MAX; + item->clock = (SINT32)newClock; + } + } + + // 自動調整のクロック変更のタイミングは CPU_BASECLOCK==CPU_REMCLOCK のタイミングになるように調整済み + if (CPU_BASECLOCK == CPU_REMCLOCK) { + CPU_BASECLOCK = g_nevent.item[g_nevent.level[0]].clock; + CPU_REMCLOCK = CPU_BASECLOCK;/* カウンタへセット */ + } + else { + // I/O経由の場合はずれている場合あり。この場合はスケール + CPU_BASECLOCK = ((SINT64)CPU_BASECLOCK * newclock + oldclock / 2) / oldclock; + CPU_REMCLOCK = ((SINT64)CPU_REMCLOCK * newclock + oldclock / 2) / oldclock; + } + } + } +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif + +} + +void nevent_reset(NEVENTID id) +{ + UINT i; + +#if defined(SUPPORT_MULTITHREAD) + nevent_enter_criticalsection(); +#endif + /* 現在進行してるイベントを検索 */ + for (i = 0; i < g_nevent.readyevents; i++) + { + if (g_nevent.level[i] == id) + { + break; + } + } + /* イベントは存在した? */ + if (i < g_nevent.readyevents) + { + /* 存在していたら削る */ + g_nevent.readyevents--; + for (; i < g_nevent.readyevents; i++) + { + g_nevent.level[i] = g_nevent.level[i + 1]; + } + } +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif +} + +void nevent_waitreset(NEVENTID id) +{ + UINT i; + +#if defined(SUPPORT_MULTITHREAD) + nevent_enter_criticalsection(); +#endif + /* 現在進行してるイベントを検索 */ + for (i = 0; i < g_nevent.waitevents; i++) + { + if (g_nevent.waitevent[i] == id) + { + break; + } + } + /* イベントは存在した? */ + if (i < g_nevent.waitevents) + { + /* 存在していたら削る */ + g_nevent.waitevents--; + for (; i < g_nevent.waitevents; i++) + { + g_nevent.waitevent[i] = g_nevent.waitevent[i + 1]; + } + } +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif +} + +void nevent_set(NEVENTID id, SINT32 eventclock, NEVENTCB proc, NEVENTPOSITION absolute) +{ + SINT32 clk; + NEVENTITEM item; + UINT eventId; + UINT i; + +#if defined(SUPPORT_MULTITHREAD) + nevent_enter_criticalsection(); +#endif +// TRACEOUT(("event %d - %xclocks", id, eventclock)); + + clk = CPU_BASECLOCK - CPU_REMCLOCK; + item = &g_nevent.item[id]; + item->proc = proc; + item->flag = 0; + if (absolute) + { + item->clock = eventclock + clk; + } + else + { + item->clock += eventclock; + } +#if 0 + if (item->clock < clk) + { + item->clock = clk; + } +#endif + /* イベントの削除 */ + nevent_reset(id); + + /* イベントの挿入位置の検索 */ + for (eventId = 0; eventId < g_nevent.readyevents; eventId++) + { + if (item->clock < g_nevent.item[g_nevent.level[eventId]].clock) + { + break; + } + } + + /* イベントの挿入 */ + for (i = g_nevent.readyevents; i > eventId; i--) + { + g_nevent.level[i] = g_nevent.level[i - 1]; + } + g_nevent.level[eventId] = id; + g_nevent.readyevents++; + + /* もし最短イベントだったら... */ + if (eventId == 0) + { + clk = CPU_BASECLOCK - item->clock; + CPU_BASECLOCK -= clk; + CPU_REMCLOCK -= clk; +// TRACEOUT(("reset nextbase -%d (%d)", clock, CPU_REMCLOCK)); + } +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif +} + +void nevent_setbyms(NEVENTID id, SINT32 ms, NEVENTCB proc, NEVENTPOSITION absolute) +{ + UINT64 waittime = (UINT64)(pccore.realclock / 1000) * ms; + if (waittime > INT_MAX - pccore.realclock) + { + nevent_set(id, INT_MAX - pccore.realclock, proc, absolute); + } + else + { + nevent_set(id, (SINT32)waittime, proc, absolute); + } +} + +BOOL nevent_iswork(NEVENTID id) +{ + UINT i; + +#if defined(SUPPORT_MULTITHREAD) + nevent_enter_criticalsection(); +#endif + /* 現在進行してるイベントを検索 */ + for (i = 0; i < g_nevent.readyevents; i++) + { + if (g_nevent.level[i] == id) + { +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif + return TRUE; + } + } +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif + return FALSE; +} + +void nevent_forceexecute(NEVENTID id) +{ + NEVENTITEM item; + +#if defined(SUPPORT_MULTITHREAD) + nevent_enter_criticalsection(); +#endif + item = &g_nevent.item[id]; + + /* コールバックの実行 */ + if (item->proc != NULL) + { + item->proc(item); + } +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif +} + +SINT32 nevent_getremain(NEVENTID id) +{ + UINT i; + +#if defined(SUPPORT_MULTITHREAD) + nevent_enter_criticalsection(); +#endif + /* 現在進行してるイベントを検索 */ + for (i = 0; i < g_nevent.readyevents; i++) + { + if (g_nevent.level[i] == id) + { + SINT32 result = (g_nevent.item[id].clock - (CPU_BASECLOCK - CPU_REMCLOCK)); +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif + return result; + } + } +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif + return -1; +} + +void nevent_forceexit(void) +{ +#if defined(SUPPORT_MULTITHREAD) + nevent_enter_criticalsection(); +#endif + if (CPU_REMCLOCK > 0) + { + CPU_BASECLOCK -= CPU_REMCLOCK; + CPU_REMCLOCK = 0; + } +#if defined(SUPPORT_MULTITHREAD) + nevent_leave_criticalsection(); +#endif +} diff --git a/nevent.h b/nevent.h old mode 100755 new mode 100644 index 6ffc27ce..eebebf34 --- a/nevent.h +++ b/nevent.h @@ -1,153 +1,153 @@ -/** - * @file nevent.h - * @brief Interface of the event - */ - -#pragma once - -enum -{ - NEVENT_MAXCLOCK = 0x400000, -}; - -/** - * NEvent ID - */ -enum tagNEventId -{ - NEVENT_FLAMES = 0, - NEVENT_ITIMER = 1, - NEVENT_BEEP = 2, - NEVENT_RS232C = 3, - NEVENT_MUSICGEN = 4, - NEVENT_FMTIMERA = 5, - NEVENT_FMTIMERB = 6, - NEVENT_FMTIMER2A = 7, - NEVENT_FMTIMER2B = 8, - // NEVENT_FMTIMER3A = 9, - // NEVENT_FMTIMER3B = 10, - // NEVENT_FMTIMER4A = 11, - // NEVENT_FMTIMER4B = 12, - NEVENT_MOUSE = 13, - NEVENT_KEYBOARD = 14, - NEVENT_MIDIWAIT = 15, - NEVENT_MIDIINT = 16, - NEVENT_PICMASK = 17, - NEVENT_S98TIMER = 18, - NEVENT_CS4231 = 19, - NEVENT_GDCSLAVE = 20, - NEVENT_FDBIOSBUSY = 21, - NEVENT_FDCINT = 22, - NEVENT_PC9861CH1 = 23, - NEVENT_PC9861CH2 = 24, - NEVENT_86PCM = 25, - NEVENT_SASIIO = 26, - NEVENT_SCSIIO = 27, - NEVENT_CDWAIT = 28, // XXX: 勝手に使ってOK? - NEVENT_CT1741 = 29, // np2sより 28を使っちゃったので29に np21w ver0.86 rev29 -#if defined(VAEG_EXT) - NEVENT_FDCTIMER = 29, - NEVENT_FDDMOTOR = 30, - NEVENT_FDCSTEPWAIT = 31, -#endif -#if defined(VAEG_FIX) - NEVENT_FDCSTATE = 32, -#endif -#if defined(SUPPORT_WAB) - NEVENT_WABSNDOFF = 33, -#endif - NEVENT_HRTIMER = 34, - /* ---- */ - NEVENT_MAXEVENTS = 35 -}; -typedef enum tagNEventId NEVENTID; - -enum -{ - NEVENT_ENABLE = 0x0001, - NEVENT_SETEVENT = 0x0002, - NEVENT_WAIT = 0x0004 -}; - -/** - * event position - */ -enum tagNEventPosition -{ - NEVENT_RELATIVE = 0, /*!< relative */ - NEVENT_ABSOLUTE = 1 /*!< absolute */ -}; -typedef enum tagNEventPosition NEVENTPOSITION; /*!< the defines of position */ - -struct _neventitem; -typedef struct _neventitem _NEVENTITEM; -typedef struct _neventitem *NEVENTITEM; -typedef void (*NEVENTCB)(NEVENTITEM item); - -struct _neventitem -{ - SINT32 clock; - UINT32 flag; - NEVENTCB proc; - INTPTR userData; -}; - -typedef struct { - UINT readyevents; - UINT waitevents; - NEVENTID level[NEVENT_MAXEVENTS]; - NEVENTID waitevent[NEVENT_MAXEVENTS]; - _NEVENTITEM item[NEVENT_MAXEVENTS]; -} _NEVENT, *NEVENT; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern _NEVENT g_nevent; - -#if defined(SUPPORT_MULTITHREAD) -// 全体の初期化処理 -void nevent_initialize(void); -// 全体の解放処理 -void nevent_shutdown(void); -#endif - -// 初期化 -void nevent_allreset(void); - -// 最短イベントのセット -void nevent_get1stevent(void); - -// 時間を進める -void nevent_progress(void); - -// イベントの実行 -void nevent_execule(void); - -// イベントの追加 -void nevent_set(NEVENTID id, SINT32 eventclock, NEVENTCB proc, NEVENTPOSITION absolute); -void nevent_setbyms(NEVENTID id, SINT32 ms, NEVENTCB proc, NEVENTPOSITION absolute); - -// イベントの削除 -void nevent_reset(NEVENTID id); -void nevent_waitreset(NEVENTID id); - -// イベントの動作状態取得 -BOOL nevent_iswork(NEVENTID id); - -// イベントコールバックの強制実行(注:既存の待ちイベントの無効化は行われない) -void nevent_forceexecute(NEVENTID id); - -// イベント実行までのクロック数の取得 -SINT32 nevent_getremain(NEVENTID id); - -// NEVENTの強制脱出 -void nevent_forceexit(void); - -void nevent_changeclock(UINT32 oldclock, UINT32 newclock); - -#ifdef __cplusplus -} -#endif +/** + * @file nevent.h + * @brief Interface of the event + */ + +#pragma once + +enum +{ + NEVENT_MAXCLOCK = 0x400000, +}; + +/** + * NEvent ID + */ +enum tagNEventId +{ + NEVENT_FLAMES = 0, + NEVENT_ITIMER = 1, + NEVENT_BEEP = 2, + NEVENT_RS232C = 3, + NEVENT_MUSICGEN = 4, + NEVENT_FMTIMERA = 5, + NEVENT_FMTIMERB = 6, + NEVENT_FMTIMER2A = 7, + NEVENT_FMTIMER2B = 8, + // NEVENT_FMTIMER3A = 9, + // NEVENT_FMTIMER3B = 10, + // NEVENT_FMTIMER4A = 11, + // NEVENT_FMTIMER4B = 12, + NEVENT_MOUSE = 13, + NEVENT_KEYBOARD = 14, + NEVENT_MIDIWAIT = 15, + NEVENT_MIDIINT = 16, + NEVENT_PICMASK = 17, + NEVENT_S98TIMER = 18, + NEVENT_CS4231 = 19, + NEVENT_GDCSLAVE = 20, + NEVENT_FDBIOSBUSY = 21, + NEVENT_FDCINT = 22, + NEVENT_PC9861CH1 = 23, + NEVENT_PC9861CH2 = 24, + NEVENT_86PCM = 25, + NEVENT_SASIIO = 26, + NEVENT_SCSIIO = 27, + NEVENT_CDWAIT = 28, // XXX: 勝手に使ってOK? + NEVENT_CT1741 = 29, // np2sより 28を使っちゃったので29に np21w ver0.86 rev29 +#if defined(VAEG_EXT) + NEVENT_FDCTIMER = 29, + NEVENT_FDDMOTOR = 30, + NEVENT_FDCSTEPWAIT = 31, +#endif +#if defined(VAEG_FIX) + NEVENT_FDCSTATE = 32, +#endif +#if defined(SUPPORT_WAB) + NEVENT_WABSNDOFF = 33, +#endif + NEVENT_HRTIMER = 34, + /* ---- */ + NEVENT_MAXEVENTS = 35 +}; +typedef enum tagNEventId NEVENTID; + +enum +{ + NEVENT_ENABLE = 0x0001, + NEVENT_SETEVENT = 0x0002, + NEVENT_WAIT = 0x0004 +}; + +/** + * event position + */ +enum tagNEventPosition +{ + NEVENT_RELATIVE = 0, /*!< relative */ + NEVENT_ABSOLUTE = 1 /*!< absolute */ +}; +typedef enum tagNEventPosition NEVENTPOSITION; /*!< the defines of position */ + +struct _neventitem; +typedef struct _neventitem _NEVENTITEM; +typedef struct _neventitem *NEVENTITEM; +typedef void (*NEVENTCB)(NEVENTITEM item); + +struct _neventitem +{ + SINT32 clock; + UINT32 flag; + NEVENTCB proc; + INTPTR userData; +}; + +typedef struct { + UINT readyevents; + UINT waitevents; + NEVENTID level[NEVENT_MAXEVENTS]; + NEVENTID waitevent[NEVENT_MAXEVENTS]; + _NEVENTITEM item[NEVENT_MAXEVENTS]; +} _NEVENT, *NEVENT; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _NEVENT g_nevent; + +#if defined(SUPPORT_MULTITHREAD) +// 全体の初期化処理 +void nevent_initialize(void); +// 全体の解放処理 +void nevent_shutdown(void); +#endif + +// 初期化 +void nevent_allreset(void); + +// 最短イベントのセット +void nevent_get1stevent(void); + +// 時間を進める +void nevent_progress(void); + +// イベントの実行 +void nevent_execule(void); + +// イベントの追加 +void nevent_set(NEVENTID id, SINT32 eventclock, NEVENTCB proc, NEVENTPOSITION absolute); +void nevent_setbyms(NEVENTID id, SINT32 ms, NEVENTCB proc, NEVENTPOSITION absolute); + +// イベントの削除 +void nevent_reset(NEVENTID id); +void nevent_waitreset(NEVENTID id); + +// イベントの動作状態取得 +BOOL nevent_iswork(NEVENTID id); + +// イベントコールバックの強制実行(注:既存の待ちイベントの無効化は行われない) +void nevent_forceexecute(NEVENTID id); + +// イベント実行までのクロック数の取得 +SINT32 nevent_getremain(NEVENTID id); + +// NEVENTの強制脱出 +void nevent_forceexit(void); + +void nevent_changeclock(UINT32 oldclock, UINT32 newclock); + +#ifdef __cplusplus +} +#endif diff --git a/np2tool/HOSTDRV.INC b/np2tool/HOSTDRV.INC index 5fd4cd5c..b75b81bc 100644 --- a/np2tool/HOSTDRV.INC +++ b/np2tool/HOSTDRV.INC @@ -1,26 +1,26 @@ - -%define VERSION_ID "20250803" - - - struc HDRVIF -.drive_no resb 1 -.dosver resw 1 -.sda_off resw 1 -.sda_seg resw 1 - endstruc - - struc LOL - resb 22 -.cds resd 1 - resb 7 -.lastdrv resb 1 - endstruc - - struc CDS -.cur resb 67 -.flag resw 1 - resb 10 -.root resw 1 -.size - endstruc - + +%define VERSION_ID "20250803" + + + struc HDRVIF +.drive_no resb 1 +.dosver resw 1 +.sda_off resw 1 +.sda_seg resw 1 + endstruc + + struc LOL + resb 22 +.cds resd 1 + resb 7 +.lastdrv resb 1 + endstruc + + struc CDS +.cur resb 67 +.flag resw 1 + resb 10 +.root resw 1 +.size + endstruc + diff --git a/np2tool/HOSTDRV.TXT b/np2tool/HOSTDRV.TXT index b41a7bc6..33b69220 100644 --- a/np2tool/HOSTDRV.TXT +++ b/np2tool/HOSTDRV.TXT @@ -1,45 +1,45 @@ - hostdrv +★ hostdrv -@zXgOSzhCuĎQƂ܂B + ホストOSを仮想ドライブして参照します。 -E +・準備 -@˂[vWFNgII̐ݒt@C(np2.ini np2.cfg)JA -@[NekoProjectII] Ɉȉ̐ݒ܂B + ねこープロジェクトIIの設定ファイル(np2.ini もしくは np2.cfg)を開き、 + [NekoProjectII] に以下の設定を加えます。 -@EzhCu[g̎w -@@@hdrvroot=tH_ -@@@: hdrvroot=c:\windows\temp (Windows) -@@@@@hdrvroot=Machintosh HD:users:yui:Desktop (MacOS) -@@@@@hdrvroot=/home/yui (Unix) + ・仮想ドライブルートの指定 +   hdrvroot=フォルダ名 +   例: hdrvroot=c:\windows\temp (Windows) +     hdrvroot=Machintosh HD:users:yui:Desktop (MacOS) +     hdrvroot=/home/yui (Unix) -@EANZX̎w -@@@hdrv_acc=1 c ǂݍ݂̂݉”\ -@@@hdrv_acc=3 c ǂݏ”\ + ・アクセス権の指定 +   hdrv_acc=1 … 読み込みのみ可能 +   hdrv_acc=3 … 読み書き可能 -Es +・実行 -@˂[vWFNgIIMS-DOSN + ねこープロジェクトIIでMS-DOSを起動中に -@A:\>hostdrv hCuԍ(A`Z) + A:\>hostdrv ドライブ番号(A~Z) -@Ƃď풓ĉB + として常駐して下さい。 -E20250803ł̕ύX_ -pX\\HOSTDRV}EghCũpXɕύX܂B -Win32EXEsoȂȂǂ̖肪C܂B -̏CɂNeko Project 21/W ver0.86 rev9511ȍ~KvłB +・20250803版の変更点 +内部パスを\\HOSTDRVからマウントしたドライブ文字のパスに変更しました。 +Win32上でEXEが実行出来ないなどの問題が修正されます。 +この修正にはNeko Project 21/W ver0.86 rev95β11以降も必要です。 -Neko Project 21/W̋o[W{np2ŎsꍇA -݊ihostdrvƓjœ܂B +Neko Project 21/Wの旧バージョンや本家np2等で実行した場合、 +互換方式(旧hostdrvと同じ挙動)で動きます。 -Vŏ풓ĂꍇAhostdrvł̏풓 -unew protocol enabledvƕ\܂B +新方式で常駐している場合、hostdrvでの常駐時に +「new protocol enabled」と表示されます。 -Vo[WŖNꍇ̂߂ɁAOLDfBNg -o[WuĂ܂B +万が一新バージョンで問題を起こした場合のために、OLDディレクトリに +旧バージョンを置いています。 diff --git a/np2tool/NP2IDLE.TXT b/np2tool/NP2IDLE.TXT index b59b2926..74b65fab 100644 --- a/np2tool/NP2IDLE.TXT +++ b/np2tool/NP2IDLE.TXT @@ -1,26 +1,26 @@ - np2idle +★ np2idle -@{vOINT28hiDOSACh荞݁jtbNAHLT߂ - s邱ƂŃzXgCPUɖʂȕׂȂ悤ɂ܂B -@ɂA͑҂Ȃǂ̎ɃzXg}Vɉߏȕׂ̂ -@hƂł܂B + 本プログラムはINT28h(DOSアイドル割り込み)をフックし、HLT命令を + 実行することでホストCPUに無駄な負荷がかからないようにします。 + これにより、入力待ちなどの時にホストマシンに過剰な負荷がかかるのを + 防ぐことができます。 -y‹z -@ENeko Project IInG~[^MS-DOS +【動作環境】 + ・Neko Project II系エミュレータ上のMS-DOS -ygp@z -@R}hC玟̂悤ɎsĂB +【使用方法】 + コマンドラインから次のように実行してください。 -@@A> NP2IDLE +  A> NP2IDLE - ȂAdÑ`FbN풓@\͂܂B + なお、二重起動のチェックや常駐を解除する機能はありません。 -y܂z -@NP2IDLE.SYSCONFIG.SYSDEVICEƂđgݍ߂悤ɂĂ݂iłB -@VSYNCtH_ɂ̂HLTOVSYNC荞݂ONɂo[WłB -@t[YĂ܂ۂNꍇɎgpĂ݂ĉB +【おまけ】 + NP2IDLE.SYSはCONFIG.SYSのDEVICEとして組み込めるようにしてみた試作品です。 + VSYNCフォルダにあるものはHLT前にVSYNC割り込みをONにするバージョンです。 + フリーズしてしまう現象が起こる場合に使用してみて下さい。 -y܂2z -@FreeDOS(98)Ɋ܂܂PETIDLE͖{vO኱傫łA -@{vO肵ĂON/OFFoĂ߂łB +【おまけ2】 + FreeDOS(98)に含まれるPETIDLEは本プログラムより若干大きいですが、 + 本プログラムより安定していてON/OFFも出来ておすすめです。 diff --git a/np2tool/NP2TOOL.INC b/np2tool/NP2TOOL.INC index 2c76765e..b1cbcbea 100644 --- a/np2tool/NP2TOOL.INC +++ b/np2tool/NP2TOOL.INC @@ -1,4 +1,4 @@ - -NP2PORT equ 07efh -FIXCS equ 2eh - + +NP2PORT equ 07efh +FIXCS equ 2eh + diff --git a/np2tool/NP2TOOL.X86 b/np2tool/NP2TOOL.X86 index fc8d8770..a970824e 100644 --- a/np2tool/NP2TOOL.X86 +++ b/np2tool/NP2TOOL.X86 @@ -1,32 +1,32 @@ - -; in cld/ds=cs / ret z & bx -np2_check: mov ah, 0fh - int 10h - cmp ah, 0fh - mov bx, _msg_pcat - jne short np2check_err - add bx, byte 6 - mov si, bx - call sendnp2port - xchg si, bx -checknp2port: lodsb - mov cl, al -.lp: in al, dx - inc si - cmp al, [si-1] - loope .lp -np2check_err: ret - -sendnp2port: mov dx, NP2PORT - xor cx, cx - lodsb - mov cl, al -.lp: lodsb - out dx, al - loop .lp - ret - -_msg_pcat db 'PC/AT$' - db 3, 'NP2' - db 'Real PC-98x1$' - + +; in cld/ds=cs / ret z & bx +np2_check: mov ah, 0fh + int 10h + cmp ah, 0fh + mov bx, _msg_pcat + jne short np2check_err + add bx, byte 6 + mov si, bx + call sendnp2port + xchg si, bx +checknp2port: lodsb + mov cl, al +.lp: in al, dx + inc si + cmp al, [si-1] + loope .lp +np2check_err: ret + +sendnp2port: mov dx, NP2PORT + xor cx, cx + lodsb + mov cl, al +.lp: lodsb + out dx, al + loop .lp + ret + +_msg_pcat db 'PC/AT$' + db 3, 'NP2' + db 'Real PC-98x1$' + diff --git a/np2tool/PWOFF.TXT b/np2tool/PWOFF.TXT index 3d6a690f..d1d939ac 100644 --- a/np2tool/PWOFF.TXT +++ b/np2tool/PWOFF.TXT @@ -1,7 +1,7 @@ - pwoff +★ pwoff -@NP2I OR}hłB + NP2を終了する 外部コマンドです。 -@MS-DOSG~[g pwoff.coms NP2I܂B + MS-DOSをエミュレート中に pwoff.comを実行すると NP2が終了します。 diff --git a/np2tool/README.TXT b/np2tool/README.TXT index ddfa993d..d1891253 100644 --- a/np2tool/README.TXT +++ b/np2tool/README.TXT @@ -1,7 +1,7 @@ -@˂[vWFNgIIp@t@C + ねこープロジェクトII用 ファイル -@FD/HDC[WɃRs[Ăg + FD/HDイメージにコピーしてお使いください -@\[XNeko Project II\[Xnp2toolfBNgɊ܂܂Ă܂ + ソースはNeko Project IIソースのnp2toolディレクトリに含まれています diff --git a/np2tool/hostdrvnt/hdrvmnt.c b/np2tool/hostdrvnt/hdrvmnt.c index 9b6a539f..279620c8 100644 --- a/np2tool/hostdrvnt/hdrvmnt.c +++ b/np2tool/hostdrvnt/hdrvmnt.c @@ -13,7 +13,7 @@ int main(int argc, char const* argv[]) { char target[MAX_PATH] = {0}; DWORD result; - printf("Neko Project II zXgLhCu for Windows NT\n"); + printf("Neko Project II ホスト共有ドライブ for Windows NT\n"); for(i=1;i [/r] \n", argv[0]); - printf("/r‚ꍇA蓖ĉ܂B\n"); + printf("usage: %s <ドライブ文字> [/r] \n", argv[0]); + printf("/rをつけた場合、割り当て解除します。\n"); return 0; } } - // foCXg邩mF + // そもそもデバイスが使えるか確認 if (GetFileAttributes("\\\\.\\HOSTDRV") == 4294967295) { DWORD err = GetLastError(); - printf("Error: hCoɐڑł܂B(code: %d)\n", err); + printf("Error: ドライバに接続できません。(code: %d)\n", err); return 1; } - // 蓖čς݃`FbN + // 割り当て済みチェック for(i='A';i<='Z';i++){ driveLetterTmp[0] = i; if (QueryDosDevice(driveLetterTmp, target, MAX_PATH)) { @@ -56,34 +56,34 @@ int main(int argc, char const* argv[]) { if(hasarg && !remove){ if(isAllocated){ - printf("݃hCu%sɊ蓖ĂĂ܂B\n", driveLetterTmp); - printf("/rIvVœo^ĂB\n"); + printf("現在ドライブ%sに割り当てられています。\n", driveLetterTmp); + printf("先に/rオプションで登録解除してください。\n"); return 1; } if (!DefineDosDeviceA(DDD_RAW_TARGET_PATH, driveLetter, HOSTDRV_PATH)) { - printf("蓖ĂɎs܂B\n"); + printf("割り当てに失敗しました。\n"); return 1; } - printf("HOSTDRV%sɊ蓖Ă܂B\n", driveLetter); + printf("HOSTDRVを%sに割り当てました。\n", driveLetter); }else if(hasarg && remove){ if(!isAllocated){ - printf("݊蓖ĂĂ܂B\n"); + printf("現在割り当てられていません。\n"); return 1; } if (!DefineDosDeviceA(DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION, driveLetterTmp, HOSTDRV_PATH)) { - printf("蓖ĉɎs܂B\n"); + printf("割り当て解除に失敗しました。\n"); return 1; } - printf("HOSTDRV%s犄蓖ĉ܂B\n", driveLetterTmp); + printf("HOSTDRVを%sから割り当て解除しました。\n", driveLetterTmp); }else if(argc < 1){ - printf("܂B\n", argv[0]); - printf("/?IvVŎg\܂B\n"); + printf("引数が正しくありません。\n", argv[0]); + printf("/?オプションで使い方を表示します。\n"); return 1; }else{ if(isAllocated){ - printf("݃hCu%sɊ蓖ĂĂ܂B\n", driveLetterTmp); + printf("現在ドライブ%sに割り当てられています。\n", driveLetterTmp); }else{ - printf("݊蓖ĂĂ܂B\n"); + printf("現在割り当てられていません。\n"); } } diff --git a/np2tool/hostdrvnt/hostdrv.c b/np2tool/hostdrvnt/hostdrv.c index d149b8a0..50809946 100644 --- a/np2tool/hostdrvnt/hostdrv.c +++ b/np2tool/hostdrvnt/hostdrv.c @@ -3,13 +3,13 @@ #include "minisop.h" #include "irplock.h" -// NonPagedPoolւ̃Rs[ł͂Ȃy[WbNg +// NonPagedPoolへのコピーではなくページロックを使う #define USE_FAST_IRPSTACKLOCK #define HOSTDRVNT_IO_ADDR 0x7EC #define HOSTDRVNT_IO_CMD 0x7EE -// ̃foCXhCõfoCX +// このデバイスドライバのデバイス名 #define DEVICE_NAME L"\\Device\\HOSTDRV" #define DOS_DEVICE_NAME L"\\DosDevices\\HOSTDRV" #define DOS_DRIVE_NAME L"\\DosDevices\\Z:" @@ -25,60 +25,60 @@ #define HOSTDRVNT_VERSION 4 -// G~[^Ƃ̒ʐMp +// エミュレータとの通信用 typedef struct tagHOSTDRV_INFO { - PIO_STACK_LOCATION stack; // IoGetCurrentIrpStackLocation(Irp)Ŏ擾f[^ւ̃AhX - PIO_STATUS_BLOCK status; // Irp->IoStatusւ̃AhX - PVOID systemBuffer; // QXgOSG~[^ւ̃obt@ - ULONG deviceFlags; // irpSp->DeviceObject->Flags̒l - PVOID outBuffer; // G~[^QXgOSւ̃obt@ - PVOID sectionObjectPointer; // irpSp->FileObject->SectionObjectPointerւ̃AhX - ULONG version; // G~[^ʐMo[W - ULONG pendingListCount; // ҋ@pIRP̃Xg̗vf - PIRP *pendingIrpList; // ҋ@pIRP̃Xgւ̃AhX - ULONG *pendingAliveList; // ҋ@ptOiLt@CIuWFNgCfbNXj̃Xgւ̃AhX + PIO_STACK_LOCATION stack; // IoGetCurrentIrpStackLocation(Irp)で取得されるデータへのアドレス + PIO_STATUS_BLOCK status; // Irp->IoStatusへのアドレス + PVOID systemBuffer; // ゲストOS→エミュレータへのバッファ + ULONG deviceFlags; // irpSp->DeviceObject->Flagsの値 + PVOID outBuffer; // エミュレータ→ゲストOSへのバッファ + PVOID sectionObjectPointer; // irpSp->FileObject->SectionObjectPointerへのアドレス + ULONG version; // エミュレータ通信バージョン情報 + ULONG pendingListCount; // 待機用IRPのリストの要素数 + PIRP *pendingIrpList; // 待機用IRPのリストへのアドレス + ULONG *pendingAliveList; // 待機用生存フラグ(猫側ファイルオブジェクトインデックス)のリストへのアドレス union{ - LONG pendingIndex; // STATUS_PENDINĜƂAǂ̃CfbNXɑҋ@pIRPlj邩\iLZbgj - LONG pendingCompleteCount; // STATUS_PENDINGȊO̎Aҋ@̂̐\iLZbgj + LONG pendingIndex; // STATUS_PENDINGのとき、どのインデックスに待機用IRPを追加するかを表す(猫側がセット) + LONG pendingCompleteCount; // STATUS_PENDING以外の時、待機完了したものの数を表す(猫側がセット) } pending; - ULONG hostdrvNTOptions; // HOSTDRV for NTIvV + ULONG hostdrvNTOptions; // HOSTDRV for NTオプション } HOSTDRV_INFO, *PHOSTDRV_INFO; typedef struct tagHOSTDRV_NOTIFYINFO { - ULONG version; // G~[^ʐMo[W - ULONG pendingListCount; // ҋ@pIRP̃Xg̗vf - PIRP *pendingIrpList; // ҋ@pIRP̃Xgւ̃AhX - ULONG *pendingAliveList; // ҋ@ptOiLt@CIuWFNgCfbNXj̃Xgւ̃AhX + ULONG version; // エミュレータ通信バージョン情報 + ULONG pendingListCount; // 待機用IRPのリストの要素数 + PIRP *pendingIrpList; // 待機用IRPのリストへのアドレス + ULONG *pendingAliveList; // 待機用生存フラグ(猫側ファイルオブジェクトインデックス)のリストへのアドレス union{ - LONG pendingCompleteCount; // ҋ@̂̐\iLZbgj + LONG pendingCompleteCount; // 待機完了したものの数を表す(猫側がセット) } pending; } HOSTDRV_NOTIFYINFO, *PHOSTDRV_NOTIFYINFO; -// irpSp->FileObject->FsContext֊i[ -// QlFirpSp->FileObject->FsContext֓KID̂NGBFXȂȂB -// KExAllocatePoolWithTag(NonPagedPool, `Ŋ蓖ĂłKvB -// [Undocumented] \̃TCY͏ȂƂ64byteȂƑʖځH -// ȂOSߑł͈̔͊OQƂIRQL_NOT_LESS_OR_EQUALpBǂ܂łΈS͕sB -// FSRTL_COMMON_FCB_HEADER\̂̍ŏɊ܂߂Ȃ΂ȂȂƂK{̂悤ɂv܂B +// irpSp->FileObject->FsContextへ格納する情報 +// 参考情報:irpSp->FileObject->FsContextへ適当なIDを入れるのはNG。色々動かなくなる。 +// 必ずExAllocatePoolWithTag(NonPagedPool, ~で割り当てたメモリである必要がある。 +// [Undocumented] 構造体サイズは少なくとも64byteないと駄目? +// ないとOSが決め打ちの範囲外参照してIRQL_NOT_LESS_OR_EQUALが頻発。どこまであれば安全かは不明。 +// FSRTL_COMMON_FCB_HEADERを構造体の最初に含めなければならないという条件が必須のようにも思えます。 typedef struct tagHOSTDRV_FSCONTEXT { - FSRTL_COMMON_FCB_HEADER header; // OSĝŐGĂ͂ȂB32bit‹ł40byte - ULONG fileIndex; // G~[^{̂Ǘt@CID - ULONG reserved[5]; // \ + FSRTL_COMMON_FCB_HEADER header; // OSが使うので触ってはいけない。32bit環境では40byte + ULONG fileIndex; // エミュレータ本体が管理するファイルID + ULONG reserved[5]; // 予約 } HOSTDRV_FSCONTEXT, *PHOSTDRV_FSCONTEXT; -// O[oɊǗϐQ -static FAST_MUTEX g_Mutex; // I/O̔rbNp -static PIRP g_pendingIrpList[PENDING_IRP_MAX] = {0}; // I/Oҋ@pIRP̃Xg -static ULONG g_pendingAliveList[PENDING_IRP_MAX] = {0}; // I/Oҋ@ptÕXg -static ULONG g_hostdrvNTOptions = HOSTDRVNTOPTIONS_NONE; // HOSTDRV for NTIvV -static ULONG g_checkNotifyInterval = 10; // zXg̃t@CVXeύXʒmbԊuŃ`FbN邩 -static KTIMER g_checkNotifyTimer = {0}; // zXg̃t@CVXeύXʒmĎ^C}[ -static KDPC g_checkNotifyTimerDpc = {0}; // zXg̃t@CVXeύXʒmĎ^C}[DPC -static WORK_QUEUE_ITEM g_RescheduleTimerWorkItem = {0}; // zXg̃t@CVXeύXʒmĎ^C}[ċNp -static int g_checkNotifyTimerEnabled = 0; // zXg̃t@CVXeύXʒmĎ^C}[Jn -static ULONG g_pendingCounter = 0; // t@CVXeĎSTATUS_PENDINGԂ̂̂̐ -static WCHAR g_autoMountDriveLetter = 0; // }Eg̃hCu^[B0̏ꍇZ珇ɎgꏊTĊ蓖āB - -// ֐` +// グローバルに管理する変数群 +static FAST_MUTEX g_Mutex; // I/Oの排他ロック用 +static PIRP g_pendingIrpList[PENDING_IRP_MAX] = {0}; // I/O待機用IRPのリスト +static ULONG g_pendingAliveList[PENDING_IRP_MAX] = {0}; // I/O待機用生存フラグのリスト +static ULONG g_hostdrvNTOptions = HOSTDRVNTOPTIONS_NONE; // HOSTDRV for NTオプション +static ULONG g_checkNotifyInterval = 10; // ホストのファイルシステム変更通知を何秒間隔でチェックするか +static KTIMER g_checkNotifyTimer = {0}; // ホストのファイルシステム変更通知を監視するタイマー +static KDPC g_checkNotifyTimerDpc = {0}; // ホストのファイルシステム変更通知を監視するタイマーDPC +static WORK_QUEUE_ITEM g_RescheduleTimerWorkItem = {0}; // ホストのファイルシステム変更通知を監視するタイマー再起動用 +static int g_checkNotifyTimerEnabled = 0; // ホストのファイルシステム変更通知を監視するタイマーが開始状態 +static ULONG g_pendingCounter = 0; // ファイルシステム監視でSTATUS_PENDING状態のものの数 +static WCHAR g_autoMountDriveLetter = 0; // 自動マウント時のドライブレター文字。0の場合はZから順に使える場所を探して割り当て。 + +// 関数定義 NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath); NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); VOID HostdrvUnload(IN PDRIVER_OBJECT DriverObject); @@ -86,7 +86,7 @@ VOID HostdrvCancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp); VOID HostdrvTimerDpcRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); VOID HostdrvRescheduleTimer(IN PVOID Context); -// WXgDWORDlǂ +// レジストリのDWORD値を読む ULONG HostdrvReadDWORDReg(HANDLE hKey, WCHAR *valueName) { NTSTATUS status; UNICODE_STRING valueNameUnicode; @@ -112,7 +112,7 @@ ULONG HostdrvReadDWORDReg(HANDLE hKey, WCHAR *valueName) { return 0; } -// WXg̃hCu킷REG_SZǂ +// レジストリのドライブ文字をあらわすREG_SZを読む WCHAR HostdrvReadDriveLetterReg(HANDLE hKey, WCHAR *valueName) { NTSTATUS status; UNICODE_STRING valueNameUnicode; @@ -129,7 +129,7 @@ WCHAR HostdrvReadDriveLetterReg(HANDLE hKey, WCHAR *valueName) { return 0; } status = ZwQueryValueKey(hKey, &valueNameUnicode, KeyValuePartialInformation, pInfo, resultLength, &resultLength); - if (NT_SUCCESS(status) && pInfo->Type == REG_SZ && pInfo->DataLength == 2 * sizeof(WCHAR)) { // NULL܂ރoCg + if (NT_SUCCESS(status) && pInfo->Type == REG_SZ && pInfo->DataLength == 2 * sizeof(WCHAR)) { // NULL文字含むバイト数 WCHAR retValue = ((WCHAR *)(pInfo->Data))[0]; ExFreePool(pInfo); return retValue; @@ -139,7 +139,7 @@ WCHAR HostdrvReadDriveLetterReg(HANDLE hKey, WCHAR *valueName) { return 0; } -// IvṼWXgL[`FbN +// オプションのレジストリキーをチェック VOID HostdrvCheckOptions(IN PUNICODE_STRING RegistryPath) { OBJECT_ATTRIBUTES attributes; HANDLE hKey; @@ -166,21 +166,21 @@ VOID HostdrvCheckOptions(IN PUNICODE_STRING RegistryPath) { } g_checkNotifyInterval = HostdrvReadDWORDReg(hKey, L"CheckNotifyInterval"); if (g_checkNotifyInterval <= 0){ - g_checkNotifyInterval = 5; // ftHgi5bjɂ + g_checkNotifyInterval = 5; // デフォルト(5秒)にする } if (g_checkNotifyInterval > 60){ - g_checkNotifyInterval = 60; // ő60bɂ + g_checkNotifyInterval = 60; // 最大は60秒にする } if (HostdrvReadDWORDReg(hKey, L"AutoMount")){ g_hostdrvNTOptions |= HOSTDRVNTOPTIONS_AUTOMOUNTDRIVE; } g_autoMountDriveLetter = HostdrvReadDriveLetterReg(hKey, L"AutoMountDriveLetter"); if('a' <= g_autoMountDriveLetter && g_autoMountDriveLetter <= 'z'){ - // 啶Ƃ + // 大文字とする g_autoMountDriveLetter = g_autoMountDriveLetter - 'a' + 'A'; } if(!('A' <= g_autoMountDriveLetter && g_autoMountDriveLetter <= 'Z')){ - // Ȃ̂Ŏ蓖ĂƂ + // 無効なので自動割り当てとする g_autoMountDriveLetter = 0; } @@ -255,7 +255,7 @@ NTSTATUS ReserveIoPortRange(PDRIVER_OBJECT DriverObject) pResourceDescriptor->u.Port.Start.QuadPart = HOSTDRVNT_IO_CMD; pResourceDescriptor->u.Port.Length = 1; - // \[Xgp̕ + // リソース使用の報告 RtlInitUnicodeString(&className, L"LegacyDriver"); status = IoReportResourceUsage( &className, // DriverClassName @@ -282,7 +282,7 @@ NTSTATUS ReserveIoPortRange(PDRIVER_OBJECT DriverObject) return STATUS_SUCCESS; } -// foCXhCõGg|Cg +// デバイスドライバのエントリポイント NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { UNICODE_STRING deviceNameUnicodeString, dosDeviceNameUnicodeString; PDEVICE_OBJECT deviceObject = NULL; @@ -291,18 +291,18 @@ NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING Registry NTSTATUS status; int i; - // I/O|[gg邩mF + // I/Oポートが使えるかを確認 status = ReserveIoPortRange(DriverObject); if (!NT_SUCCESS(status)) { return status; } - // hostdrv for NTΉȈՃ`FbN + // hostdrv for NT対応かを簡易チェック if(READ_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_ADDR) != 98 || READ_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_CMD) != 21){ return STATUS_NO_SUCH_DEVICE; } - // hostdrv for NTZbg + // hostdrv for NTをリセット WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_ADDR, (UCHAR)0); WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_ADDR, (UCHAR)0); WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_ADDR, (UCHAR)0); @@ -315,27 +315,27 @@ NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING Registry WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_CMD, (UCHAR)'0'); WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_CMD, (UCHAR)'1'); - // rbN@݂̂Ŕj͂Ȃ + // 排他ロック初期化 初期化のみで破棄処理はいらない ExInitializeFastMutex(&g_Mutex); - // IvV`FbN + // オプションチェック HostdrvCheckOptions(RegistryPath); - // foCX^CvȂǂ̐ݒ + // デバイスタイプなどの設定 if(g_hostdrvNTOptions & HOSTDRVNTOPTIONS_REMOVABLEDEVICE){ - // [oufoCX̐U郂[h + // リムーバブルデバイスの振りをするモード deviceType = FILE_DEVICE_DISK_FILE_SYSTEM; deviceCharacteristics |= FILE_REMOVABLE_MEDIA; }else if(g_hostdrvNTOptions & HOSTDRVNTOPTIONS_DISKDEVICE){ - // [JfBXN̐U郂[h + // ローカルディスクの振りをするモード deviceType = FILE_DEVICE_DISK_FILE_SYSTEM; }else{ - // lbg[Nt@CVXe̐U郂[h + // ネットワークファイルシステムの振りをするモード deviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM; deviceCharacteristics |= FILE_REMOTE_DEVICE; } - // foCX쐬@[JfBXN̐UȂFILE_DEVICE_DISK_FILE_SYSTEM + // デバイスを作成 ローカルディスクの振りをするならFILE_DEVICE_DISK_FILE_SYSTEM RtlInitUnicodeString(&deviceNameUnicodeString, DEVICE_NAME); status = IoCreateDevice(DriverObject, 0, &deviceNameUnicodeString, deviceType, deviceCharacteristics, FALSE, &deviceObject); @@ -343,7 +343,7 @@ NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING Registry return status; } - // foCXDOSo^@\\.\HOSTDRV̂悤ɃANZXł + // デバイスのDOS名を登録 \\.\HOSTDRVのようにアクセスできる RtlInitUnicodeString(&dosDeviceNameUnicodeString, DOS_DEVICE_NAME); status = IoCreateSymbolicLink(&dosDeviceNameUnicodeString, &deviceNameUnicodeString); if (!NT_SUCCESS(status)) { @@ -351,13 +351,13 @@ NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING Registry return status; } - // hCu蓖Ă̏ꍇA蓖 + // 自動ドライブ文字割り当ての場合、割り当て if(g_hostdrvNTOptions & HOSTDRVNTOPTIONS_AUTOMOUNTDRIVE){ UNICODE_STRING dosDriveNameUnicodeString; WCHAR dosDriveName[] = DOS_DRIVE_NAME; RtlInitUnicodeString(&dosDriveNameUnicodeString, dosDriveName); if(g_autoMountDriveLetter== 0){ - // Ŏg镶T + // 自動で使える文字を探す for(g_autoMountDriveLetter='Z';g_autoMountDriveLetter>='A';g_autoMountDriveLetter--){ dosDriveNameUnicodeString.Buffer[12] = g_autoMountDriveLetter; status = IoCreateSymbolicLink(&dosDriveNameUnicodeString, &deviceNameUnicodeString); @@ -366,34 +366,34 @@ NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING Registry } } if(g_autoMountDriveLetter < 'A'){ - // 󂫂Ȃ̂Ŋ蓖ĂłȂ + // 空きがないので割り当てできなかった g_autoMountDriveLetter = 0; } }else{ - // Œ蕶w@gȂĂG[ɂ͂Ȃ + // 固定文字指定 使えなくてもエラーにはしない dosDriveNameUnicodeString.Buffer[12] = g_autoMountDriveLetter; status = IoCreateSymbolicLink(&dosDriveNameUnicodeString, &deviceNameUnicodeString); if (!NT_SUCCESS(status)) { - // 蓖Ďs + // 割り当て失敗 g_autoMountDriveLetter = 0; } } } - // foCXIRP֐o^@vfԍeIRP_MJ_`̔ԍɑΉB - // SG~[^{̂ɓ̂őSɓ֐蓖 + // デバイスのIRP処理関数を登録 要素番号が各IRP_MJ_~の番号に対応。 + // 全部エミュレータ本体に投げるので全部に同じ関数を割り当て for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = HostdrvDispatch; } - // hCȍIo^ + // ドライバの終了処理を登録 DriverObject->DriverUnload = HostdrvUnload; - // LbVł}bvgt@Cg悤ɂWORKAROUNDLbV + // キャッシュ未実装でもメモリマップトファイルが使えるようにするWORKAROUNDキャッシュを初期化 MiniSOP_InitializeCache(DriverObject); - // ̑ljtOݒ - deviceObject->Flags |= DO_BUFFERED_IO; // f[^󂯓nSystemBuffer{ƂHw肵ĂŗƂ͗CB + // その他追加フラグを設定 + deviceObject->Flags |= DO_BUFFERED_IO; // データ受け渡しでSystemBufferを基本とする?指定しても他方式で来るときは来る気がする。 if(g_hostdrvNTOptions & HOSTDRVNTOPTIONS_USECHECKNOTIFY){ KeInitializeTimer(&g_checkNotifyTimer); @@ -409,7 +409,7 @@ VOID HostdrvUnload(IN PDRIVER_OBJECT DriverObject) { UNICODE_STRING dosDeviceNameUnicodeString; int i; - // ҋ@IRPSLZ + // 待機中のIRPを全部キャンセルする for (i = 0; i < PENDING_IRP_MAX; i++) { if (g_pendingIrpList[i] != NULL) { KIRQL oldIrql; @@ -422,26 +422,26 @@ VOID HostdrvUnload(IN PDRIVER_OBJECT DriverObject) { IoReleaseCancelSpinLock(Irp->CancelIrql); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); // LZ + IoCompleteRequest(Irp, IO_NO_INCREMENT); // キャンセルする }else{ - IoReleaseCancelSpinLock(Irp->CancelIrql); // ̂LZς݁@ʏ͂Ȃ͂ + IoReleaseCancelSpinLock(Irp->CancelIrql); // 何故かキャンセル済み 通常はないはず } } } g_pendingCounter = 0; - // r̈Jn + // 排他領域開始 ExAcquireFastMutex(&g_Mutex); HostdrvStopTimer(); - // SOPXg + // SOPリスト解放 MiniSOP_ReleaseSOPList(); - // r̈I + // 排他領域終了 ExReleaseFastMutex(&g_Mutex); - // hCu蓖Ă̏ꍇA + // 自動ドライブ文字割り当ての場合、解除 if(g_hostdrvNTOptions & HOSTDRVNTOPTIONS_AUTOMOUNTDRIVE){ if(g_autoMountDriveLetter != 0){ UNICODE_STRING dosDriveNameUnicodeString; @@ -452,11 +452,11 @@ VOID HostdrvUnload(IN PDRIVER_OBJECT DriverObject) { } } - // DOSo^ + // DOS名を登録解除 RtlInitUnicodeString(&dosDeviceNameUnicodeString, DOS_DEVICE_NAME); IoDeleteSymbolicLink(&dosDeviceNameUnicodeString); - // foCX폜 + // デバイスを削除 IoDeleteDevice(DriverObject->DeviceObject); KdPrint(("Hostdrv: Unloaded\n")); @@ -465,17 +465,17 @@ VOID HostdrvUnload(IN PDRIVER_OBJECT DriverObject) { VOID HostdrvCancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp) { int i; - // ҋ@LZvo^ - //IoSetCancelRoutine(Irp, NULL); // OSœȂ{͂炪 + // 待機キャンセル要求登録解除 + //IoSetCancelRoutine(Irp, NULL); // 旧OSで動かないが本当はこちらが推奨 Irp->CancelRoutine = NULL; - // LZ̃bN + // キャンセルのロックを解除 IoReleaseCancelSpinLock(Irp->CancelIrql); - // r̈Jn + // 排他領域開始 ExAcquireFastMutex(&g_Mutex); - // w肳ꂽIRPo^ + // 指定されたIRPを登録解除 for (i = 0; i < PENDING_IRP_MAX; i++) { if(g_pendingIrpList[i] == Irp){ g_pendingIrpList[i] = NULL; @@ -486,14 +486,14 @@ VOID HostdrvCancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp) { } if(g_pendingCounter == 0){ - // ҋ@ȂΓKvȂ + // 待機中がなければ動かす必要なし HostdrvStopTimer(); } - // r̈I + // 排他領域終了 ExReleaseFastMutex(&g_Mutex); - // LZs + // キャンセル実行 Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -512,23 +512,23 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION irpSpNPPBefore = NULL; #endif BOOLEAN pending = FALSE; - ULONG completeIrpCount = 0; // I/Oҋ@ō񊮗̂̐ - PIRP *completeIrpList = NULL; // I/Oҋ@ō񊮗IRP̃Xg + ULONG completeIrpCount = 0; // I/O待機で今回完了したものの数 + PIRP *completeIrpList = NULL; // I/O待機で今回完了したIRPのリスト ULONG sopIndex = -1; NTSTATUS status; int i; - // IRP_MJ_CREATE̎AKvȃ蓖 + // IRP_MJ_CREATEの時、必要なメモリを仮割り当て if(irpSp->MajorFunction == IRP_MJ_CREATE) { - // FileObjectNULLȂُ͈̂Ȃ̂Œe + // FileObjectがNULLなのは異常なので弾く if(irpSp->FileObject == NULL){ Irp->IoStatus.Status = status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } - // FsContextSectionObjectPointerExAllocatePoolWithTag(NonPagedPool,`Ń蓖 - // NULL̂܂܂Ⴄ@Ŋ蓖ĂƐɓȂ̂Œ + // FsContextとSectionObjectPointerにExAllocatePoolWithTag(NonPagedPool,~でメモリ割り当て + // NULLのままだったり違う方法で割り当てると正常に動かないので注意 irpSp->FileObject->FsContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(HOSTDRV_FSCONTEXT), "HSFC"); if(irpSp->FileObject->FsContext == NULL){ Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES; @@ -538,7 +538,7 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { } RtlZeroMemory(irpSp->FileObject->FsContext, sizeof(HOSTDRV_FSCONTEXT)); - // SOP擾 + // SOP取得 ExAcquireFastMutex(&g_Mutex); sopIndex = MiniSOP_GetSOPIndex(irpSp->FileObject->FileName); ExReleaseFastMutex(&g_Mutex); @@ -553,13 +553,13 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { irpSp->FileObject->SectionObjectPointer = MiniSOP_GetSOP(sopIndex); } - // ftHg̃Xe[^Xݒ + // デフォルトのステータス設定 Irp->IoStatus.Status = status = STATUS_NOT_IMPLEMENTED; Irp->IoStatus.Information = 0; - // G~[^ɓnf[^ݒ + // エミュレータ側に渡すデータ設定 #ifdef USE_FAST_IRPSTACKLOCK - // y[WAEgȂ悤ɃbN + // ページアウトしないようにロック irpLockInfo = LockIrpStack(irpSp); if(!irpLockInfo.isValid){ Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES; @@ -568,8 +568,8 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { return status; } #else - // y[WAEgȂ̈փRs[ - irpSpNPP = CreateNonPagedPoolIrpStack(irpSp); // NonPagedRs[쐬 + // ページアウトしない領域へコピー + irpSpNPP = CreateNonPagedPoolIrpStack(irpSp); // NonPagedコピー作成 if(irpSpNPP == NULL){ Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Information = 0; @@ -577,7 +577,7 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { return status; } irpSpNPPBefore = irpSp; - irpSp = irpSpNPP; // |C^ + irpSp = irpSpNPP; // ポインタ書き換え #endif lpHostdrvInfo = &hostdrvInfo; lpHostdrvInfo->stack = irpSp; @@ -585,17 +585,17 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { lpHostdrvInfo->systemBuffer = Irp->AssociatedIrp.SystemBuffer; lpHostdrvInfo->deviceFlags = irpSp->DeviceObject->Flags; if (Irp->MdlAddress != NULL) { - // MdlAddressgړIȓ] - lpHostdrvInfo->outBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress); // ÂOSΉp - //lpHostdrvInfo->outBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); // ŋ߂OSȂ炱”\iSHj + // MdlAddressを使った直接的な転送 + lpHostdrvInfo->outBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress); // 古いOS対応用 + //lpHostdrvInfo->outBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); // 最近のOSならこれも可能(より安全?) if(lpHostdrvInfo->systemBuffer == NULL){ lpHostdrvInfo->systemBuffer = lpHostdrvInfo->outBuffer; } } else if (Irp->AssociatedIrp.SystemBuffer != NULL) { - // VXeobt@oRł̊ԐړIȓ] + // システムバッファ経由での間接的な転送 lpHostdrvInfo->outBuffer = Irp->AssociatedIrp.SystemBuffer; } else { - // [U[wobt@ւ̓] + // ユーザー指定バッファへの転送 lpHostdrvInfo->outBuffer = Irp->UserBuffer; } if (irpSp->FileObject) { @@ -614,11 +614,11 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { MiniSOP_HandlePreMjSetInformationCache(irpSp); } - // r̈Jn + // 排他領域開始 ExAcquireFastMutex(&g_Mutex); - // \̃AhXŃG~[^ŏinCp[oCU[R[j - // G~[^ŃXe[^Xobt@Ȃǂ̒lZbg + // 構造体アドレスを書き込んでエミュレータで処理させる(ハイパーバイザーコール) + // エミュレータ側でステータスやバッファなどの値がセットされる hostdrvInfoAddr = (ULONG)lpHostdrvInfo; WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_ADDR, (UCHAR)(hostdrvInfoAddr)); WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_ADDR, (UCHAR)(hostdrvInfoAddr >> 8)); @@ -632,17 +632,17 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_CMD, (UCHAR)'0'); WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_CMD, (UCHAR)'1'); if(Irp->IoStatus.Status == STATUS_PENDING){ - // ҋ@] + // 待機希望 if(lpHostdrvInfo->pending.pendingIndex < 0 || PENDING_IRP_MAX <= lpHostdrvInfo->pending.pendingIndex){ - // o^łꏊȂ + // 登録できる場所がない Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Information = 0; }else{ - // o^OK@łg_pendingIrpListɑȂiƑXbhɊĂ܂ꂪj + // 登録OK ここではg_pendingIrpListに代入しない(入れると他スレッドに完了されてしまう恐れがある) pending = TRUE; } }else if(lpHostdrvInfo->pending.pendingCompleteCount > 0){ - // ҋ@݂ + // 待機解除が存在する completeIrpCount = lpHostdrvInfo->pending.pendingCompleteCount; completeIrpList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PIRP) * completeIrpCount, "HSIP"); if(completeIrpList){ @@ -658,33 +658,33 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { } } if(g_pendingCounter == 0){ - // ҋ@ȂΓKvȂ + // 待機中がなければ動かす必要なし HostdrvStopTimer(); } } - // r̈I + // 排他領域終了 ExReleaseFastMutex(&g_Mutex); #ifdef USE_FAST_IRPSTACKLOCK - // bN + // ロック解除 UnlockIrpStack(&irpLockInfo); #else - // NonPagedRs[߂ + // NonPagedコピーを書き戻し ReleaseNonPagedPoolIrpStack(irpSpNPP, irpSpNPPBefore); - irpSp = irpSpNPPBefore; // |C^߂ + irpSp = irpSpNPPBefore; // ポインタ書き戻し irpSpNPP = NULL; #endif - // t@CI[vEN[YȂǂŊ蓖Ă̏ + // ファイルオープン・クローズなどで割り当てたメモリの処理 if(Irp->IoStatus.Status == STATUS_SUCCESS){ - // t@C‚̂Ŕj + // ファイルを閉じたので破棄 if(irpSp->MajorFunction == IRP_MJ_CLOSE) { if(irpSp->FileObject->SectionObjectPointer){ PSECTION_OBJECT_POINTERS sop; - // SOP + // SOP解放 ExAcquireFastMutex(&g_Mutex); sop = irpSp->FileObject->SectionObjectPointer; irpSp->FileObject->SectionObjectPointer = NULL; @@ -701,10 +701,10 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { MiniSOP_HandleMjCleanupCache(irpSp); } }else{ - // 肭sȂj + // 上手く行かなかったら破棄 if(irpSp->MajorFunction == IRP_MJ_CREATE) { if(sopIndex != -1){ - // SOP + // SOP解放 ExAcquireFastMutex(&g_Mutex); irpSp->FileObject->SectionObjectPointer = NULL; MiniSOP_ReleaseSOPByIndex(sopIndex); @@ -717,7 +717,7 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { } } - // ҋ@݂ꍇA + // 待機解除が存在する場合、それらを完了させる if(completeIrpList){ for (i = 0; i < completeIrpCount; i++) { KIRQL oldIrql; @@ -726,9 +726,9 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { if(Irp->CancelRoutine){ Irp->CancelRoutine = NULL; IoReleaseCancelSpinLock(Irp->CancelIrql); - IoCompleteRequest(Irp, IO_NO_INCREMENT); // SLŃZbgĂ̂ŊĂԂł悢 + IoCompleteRequest(Irp, IO_NO_INCREMENT); // 全部猫側でセットされているので完了を呼ぶだけでよい }else{ - IoReleaseCancelSpinLock(Irp->CancelIrql); // ̂LZς݁@ʏ͂Ȃ͂ + IoReleaseCancelSpinLock(Irp->CancelIrql); // 何故かキャンセル済み 通常はないはず } } ExFreePool(completeIrpList); @@ -738,47 +738,47 @@ NTSTATUS HostdrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { if(pending){ KIRQL oldIrql; - // ҋ@ɃZbg + // 待機中にセット IoMarkIrpPending(Irp); - IoAcquireCancelSpinLock(&oldIrql); // یJn + IoAcquireCancelSpinLock(&oldIrql); // 保護開始 - // ɃLZς݂Ȃ炷ɏ + // 既にキャンセル済みならすぐに処理 if (Irp->Cancel) { - IoReleaseCancelSpinLock(oldIrql); // ی + IoReleaseCancelSpinLock(oldIrql); // 保護解除 - // r̈Jn + // 排他領域開始 ExAcquireFastMutex(&g_Mutex); - // XgɓKvȂB + // リストに入れる必要なし。解除する g_pendingIrpList[lpHostdrvInfo->pending.pendingIndex] = NULL; g_pendingAliveList[lpHostdrvInfo->pending.pendingIndex] = 0; - // r̈I + // 排他領域終了 ExReleaseFastMutex(&g_Mutex); Irp->IoStatus.Status = status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); }else{ - // ҋ@LZvo^ - //IoSetCancelRoutine(Irp, HostdrvCancelRoutine); // OSœȂ{͂炪 + // 待機キャンセル要求登録 + //IoSetCancelRoutine(Irp, HostdrvCancelRoutine); // 旧OSで動かないが本当はこちらが推奨 Irp->CancelRoutine = HostdrvCancelRoutine; - IoReleaseCancelSpinLock(oldIrql); // ی + IoReleaseCancelSpinLock(oldIrql); // 保護解除 - // r̈Jn + // 排他領域開始 ExAcquireFastMutex(&g_Mutex); - // ۂɓo^ + // 実際に登録 g_pendingIrpList[lpHostdrvInfo->pending.pendingIndex] = Irp; g_pendingCounter++; - // KvȂĎ^C}[𓮂 + // 必要なら監視タイマーを動かす if(g_hostdrvNTOptions & HOSTDRVNTOPTIONS_USECHECKNOTIFY){ HostdrvStartTimer(); } - // r̈I + // 排他領域終了 ExReleaseFastMutex(&g_Mutex); status = Irp->IoStatus.Status; @@ -797,10 +797,10 @@ VOID HostdrvTimerDpcRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID Sys } if(g_pendingCounter > 0 && g_checkNotifyTimerEnabled) { - // WorkItem֓ IRQL𗎂Ƃ + // WorkItemへ投げる IRQLを落とす ExQueueWorkItem(&g_RescheduleTimerWorkItem, DelayedWorkQueue); }else{ - // ~ + // 停止 g_checkNotifyTimerEnabled = 0; } } @@ -808,25 +808,25 @@ VOID HostdrvRescheduleTimer(IN PVOID Context) { PHOSTDRV_NOTIFYINFO lpHostdrvInfo; ULONG hostdrvInfoAddr; - ULONG completeIrpCount = 0; // I/Oҋ@ō񊮗̂̐ - PIRP *completeIrpList = NULL; // I/Oҋ@ō񊮗IRP̃Xg + ULONG completeIrpCount = 0; // I/O待機で今回完了したものの数 + PIRP *completeIrpList = NULL; // I/O待機で今回完了したIRPのリスト int i; lpHostdrvInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(HOSTDRV_NOTIFYINFO), "HSIM"); - // r̈Jn + // 排他領域開始 ExAcquireFastMutex(&g_Mutex); if(lpHostdrvInfo){ - // G~[^ɓnf[^ݒ + // エミュレータ側に渡すデータ設定 lpHostdrvInfo->version = HOSTDRVNT_VERSION; lpHostdrvInfo->pendingListCount = PENDING_IRP_MAX; lpHostdrvInfo->pendingIrpList = g_pendingIrpList; lpHostdrvInfo->pendingAliveList = g_pendingAliveList; lpHostdrvInfo->pending.pendingCompleteCount = -1; - // \̃AhXŃG~[^ŏinCp[oCU[R[j - // G~[^ŃXe[^Xobt@Ȃǂ̒lZbg + // 構造体アドレスを書き込んでエミュレータで処理させる(ハイパーバイザーコール) + // エミュレータ側でステータスやバッファなどの値がセットされる hostdrvInfoAddr = (ULONG)lpHostdrvInfo; WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_ADDR, (UCHAR)(hostdrvInfoAddr)); WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_ADDR, (UCHAR)(hostdrvInfoAddr >> 8)); @@ -839,7 +839,7 @@ VOID HostdrvRescheduleTimer(IN PVOID Context) WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_CMD, (UCHAR)'8'); WRITE_PORT_UCHAR((PUCHAR)HOSTDRVNT_IO_CMD, (UCHAR)'M'); if(lpHostdrvInfo->pending.pendingCompleteCount > 0){ - // ҋ@݂ + // 待機解除が存在する completeIrpCount = lpHostdrvInfo->pending.pendingCompleteCount; completeIrpList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PIRP) * completeIrpCount, "HSIP"); if(completeIrpList){ @@ -857,25 +857,25 @@ VOID HostdrvRescheduleTimer(IN PVOID Context) } } - // ^C}[Đݒ + // タイマー再設定 if(g_pendingCounter > 0 && g_checkNotifyTimerEnabled) { - // Đݒ + // 再設定 LARGE_INTEGER dueTime = {0}; dueTime.QuadPart = (LONGLONG)(-(LONG)g_checkNotifyInterval * 1000 * 10000); KeSetTimer(&g_checkNotifyTimer, dueTime, &g_checkNotifyTimerDpc); }else{ - // ~ + // 停止 g_checkNotifyTimerEnabled = 0; } - // r̈I + // 排他領域終了 ExReleaseFastMutex(&g_Mutex); if(lpHostdrvInfo){ ExFreePool(lpHostdrvInfo); } - // ҋ@݂ꍇA + // 待機解除が存在する場合、それらを完了させる if(completeIrpList){ for (i = 0; i < completeIrpCount; i++) { KIRQL oldIrql; @@ -884,9 +884,9 @@ VOID HostdrvRescheduleTimer(IN PVOID Context) if(Irp->CancelRoutine){ Irp->CancelRoutine = NULL; IoReleaseCancelSpinLock(Irp->CancelIrql); - IoCompleteRequest(Irp, IO_NO_INCREMENT); // SLŃZbgĂ̂ŊĂԂł悢 + IoCompleteRequest(Irp, IO_NO_INCREMENT); // 全部猫側でセットされているので完了を呼ぶだけでよい }else{ - IoReleaseCancelSpinLock(Irp->CancelIrql); // ̂LZς݁@ʏ͂Ȃ͂ + IoReleaseCancelSpinLock(Irp->CancelIrql); // 何故かキャンセル済み 通常はないはず } } ExFreePool(completeIrpList); diff --git a/np2tool/hostdrvnt/irplock.c b/np2tool/hostdrvnt/irplock.c index 4b0129d4..c3d19f37 100644 --- a/np2tool/hostdrvnt/irplock.c +++ b/np2tool/hostdrvnt/irplock.c @@ -1,12 +1,12 @@ /* * irplock.c - * IrpStacky[WOȂ悤ɂ邽߂̃[eBeB + * IrpStackがページングされないようにするためのユーティリティ */ #include #include "irplock.h" -// y[WtH[gNȊȂ̂Rs[ Ƃ肠gĂ͈͂ +// ページフォールトを起こしそうな危ないものをコピー とりあえず使っている範囲で PIO_STACK_LOCATION CreateNonPagedPoolIrpStack(PIO_STACK_LOCATION src) { PIO_STACK_LOCATION dst = NULL; PFILE_OBJECT fileObject = NULL; @@ -26,7 +26,7 @@ PIO_STACK_LOCATION CreateNonPagedPoolIrpStack(PIO_STACK_LOCATION src) { if (!fileObject) { goto failed; } - RtlCopyMemory(fileObject, src->FileObject, sizeof(FILE_OBJECT)); // src->FileObjectKFILE_OBJECT̃TCYƂ͌ȂAȂƂnp2Ŏg͈͂̓Rs[ + RtlCopyMemory(fileObject, src->FileObject, sizeof(FILE_OBJECT)); // src->FileObjectが必ずしもFILE_OBJECTのサイズとは限らないが、少なくともnp2で使う範囲はコピーする dst->FileObject = fileObject; // IrpSp->FileObject->FileName.Buffer @@ -40,7 +40,7 @@ PIO_STACK_LOCATION CreateNonPagedPoolIrpStack(PIO_STACK_LOCATION src) { } } - // IRP_MJ_DIRECTORY_CONTROL IRP_MN_QUERY_DIRECTORY̏ꍇ + // IRP_MJ_DIRECTORY_CONTROL IRP_MN_QUERY_DIRECTORYの場合 if(src->MajorFunction == IRP_MJ_DIRECTORY_CONTROL && src->MinorFunction == IRP_MN_QUERY_DIRECTORY && src->Parameters.Others.Argument2 != NULL){ // IrpSp->Parameters.QueryDirectory.FileName queryDirectoryFileName = (PUNICODE_STRING)ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING)); @@ -66,40 +66,40 @@ PIO_STACK_LOCATION CreateNonPagedPoolIrpStack(PIO_STACK_LOCATION src) { if (fileObjectFileNameBuffer) ExFreePool(fileObjectFileNameBuffer); if (queryDirectoryFileName) ExFreePool(queryDirectoryFileName); if (queryDirectoryFileNameBuffer) ExFreePool(queryDirectoryFileNameBuffer); - return NULL; // mێs + return NULL; // メモリ確保失敗 } -// ߂ +// 書き戻し VOID ReleaseNonPagedPoolIrpStack(PIO_STACK_LOCATION src, PIO_STACK_LOCATION back) { - // [珑߂ĂƂ̃AhXɖ߂Ă + // 末端から書き戻し&解放してもとのアドレスに戻していく - // IRP_MJ_DIRECTORY_CONTROL IRP_MN_QUERY_DIRECTORY̏ꍇ + // IRP_MJ_DIRECTORY_CONTROL IRP_MN_QUERY_DIRECTORYの場合 if(src->MajorFunction == IRP_MJ_DIRECTORY_CONTROL && src->MinorFunction == IRP_MN_QUERY_DIRECTORY && back->Parameters.Others.Argument2 != NULL){ // IrpSp->Parameters.QueryDirectory.FileName->Buffer - ExFreePool(((PUNICODE_STRING)src->Parameters.Others.Argument2)->Buffer); // ߂sv@邾 + ExFreePool(((PUNICODE_STRING)src->Parameters.Others.Argument2)->Buffer); // 書き戻し不要 解放するだけ ((PUNICODE_STRING)src->Parameters.Others.Argument2)->Buffer = ((PUNICODE_STRING)back->Parameters.Others.Argument2)->Buffer; // IrpSp->Parameters.QueryDirectory.FileName - ExFreePool(src->Parameters.Others.Argument2); // ߂sv@邾 + ExFreePool(src->Parameters.Others.Argument2); // 書き戻し不要 解放するだけ src->Parameters.Others.Argument2 = back->Parameters.Others.Argument2; } if(src->FileObject){ // IrpSp->FileObject->FileName.Buffer if (src->FileObject->FileName.MaximumLength > 0){ - ExFreePool(src->FileObject->FileName.Buffer); // ߂sv@邾 + ExFreePool(src->FileObject->FileName.Buffer); // 書き戻し不要 解放するだけ src->FileObject->FileName.Buffer = back->FileObject->FileName.Buffer; } // IrpSp->FileObject - RtlCopyMemory(back->FileObject, src->FileObject, sizeof(FILE_OBJECT)); // ߂ + RtlCopyMemory(back->FileObject, src->FileObject, sizeof(FILE_OBJECT)); // 書き戻し ExFreePool(src->FileObject); src->FileObject = back->FileObject; } // PIO_STACK_LOCATION IrpSp - RtlCopyMemory(back, src, sizeof(IO_STACK_LOCATION)); // ߂ + RtlCopyMemory(back, src, sizeof(IO_STACK_LOCATION)); // 書き戻し ExFreePool(src); } -// y[WOȂIrpStack擾BNULL̏ꍇs -// src: bNrpStack -// return -> IRPbN +// ページングされないIrpStackを取得する。NULLの場合失敗 +// src: ロックしたいrpStack +// return -> IRPロック情報 IRPSTACKLOCK_INFO LockIrpStack(PIO_STACK_LOCATION src) { IRPSTACKLOCK_INFO info = {0}; @@ -119,7 +119,7 @@ IRPSTACKLOCK_INFO LockIrpStack(PIO_STACK_LOCATION src) { MmProbeAndLockPages(info.mdlFileObjectFileNameBuffer, KernelMode, IoModifyAccess); } } - // IRP_MJ_DIRECTORY_CONTROL IRP_MN_QUERY_DIRECTORY̏ꍇ + // IRP_MJ_DIRECTORY_CONTROL IRP_MN_QUERY_DIRECTORYの場合 if(src->MajorFunction == IRP_MJ_DIRECTORY_CONTROL && src->MinorFunction == IRP_MN_QUERY_DIRECTORY && src->Parameters.Others.Argument2 != NULL){ PUNICODE_STRING queryDirectoryFileName = NULL; @@ -146,9 +146,9 @@ IRPSTACKLOCK_INFO LockIrpStack(PIO_STACK_LOCATION src) { return info; } -// y[WOȂIrpStackj -// src: bNꂽIrpStack -// lpInfo: IRPbNւ̃|C^ +// ページングされないIrpStackを破棄する +// src: ロックされたIrpStack +// lpInfo: IRPロック情報へのポインタ VOID UnlockIrpStack(PIRPSTACKLOCK_INFO lpInfo) { if(lpInfo->mdlQueryDirectoryFileNameBuffer){ MmUnlockPages(lpInfo->mdlQueryDirectoryFileNameBuffer); diff --git a/np2tool/hostdrvnt/irplock.h b/np2tool/hostdrvnt/irplock.h index 70399e59..aaf6911d 100644 --- a/np2tool/hostdrvnt/irplock.h +++ b/np2tool/hostdrvnt/irplock.h @@ -2,9 +2,9 @@ * irplock.h */ -// #include KvB +// 先に#include が必要。 -// IrpStack̃bN +// IrpStackのロック情報 typedef struct tagIRPSTACKLOCK_INFO { ULONG isValid; PMDL mdlIrpStack; @@ -14,22 +14,22 @@ typedef struct tagIRPSTACKLOCK_INFO { PMDL mdlQueryDirectoryFileNameBuffer; } IRPSTACKLOCK_INFO, *PIRPSTACKLOCK_INFO; -// y[WOȂIrpStack擾BNULL̏ꍇs -// src: Rs[ -// return -> y[WOȂIrpStack +// ページングされないIrpStackを取得する。NULLの場合失敗 +// src: コピー元 +// return -> ページングされないIrpStack PIO_STACK_LOCATION CreateNonPagedPoolIrpStack(PIO_STACK_LOCATION src); -// y[WOȂIrpStackj -// src: y[WOȂIrpStack -// back: ߂IrpStack +// ページングされないIrpStackを破棄する +// src: ページングされないIrpStack +// back: 書き戻し先IrpStack VOID ReleaseNonPagedPoolIrpStack(PIO_STACK_LOCATION src, PIO_STACK_LOCATION back); -// y[WOȂIrpStack擾BNULL̏ꍇs -// src: bNrpStack -// return -> IRPbN +// ページングされないIrpStackを取得する。NULLの場合失敗 +// src: ロックしたいrpStack +// return -> IRPロック情報 IRPSTACKLOCK_INFO LockIrpStack(PIO_STACK_LOCATION src); -// y[WOȂIrpStackj -// src: bNꂽIrpStack -// lpInfo: IRPbNւ̃|C^ +// ページングされないIrpStackを破棄する +// src: ロックされたIrpStack +// lpInfo: IRPロック情報へのポインタ VOID UnlockIrpStack(PIRPSTACKLOCK_INFO lpInfo); diff --git a/np2tool/hostdrvnt/miniifs.h b/np2tool/hostdrvnt/miniifs.h index 10536495..4444f64f 100644 --- a/np2tool/hostdrvnt/miniifs.h +++ b/np2tool/hostdrvnt/miniifs.h @@ -1,5 +1,5 @@ -// ŏ\t@CVXehCo𓮂߂̕Kvŏ̊֐\̂̒` -// ȉ̐Ȓ`ntifs.hɑ݁BĂȂ炻includeĂ悢 +// 最小構成ファイルシステムドライバを動かすための必要最小限の関数や構造体の定義 +// 以下の正式な定義はntifs.hに存在。持っているならそれをincludeしてもよい typedef struct _FSRTL_COMMON_FCB_HEADER { CSHORT NodeTypeCode; diff --git a/np2tool/hostdrvnt/minisop.c b/np2tool/hostdrvnt/minisop.c index 594e79d8..e6beb6ee 100644 --- a/np2tool/hostdrvnt/minisop.c +++ b/np2tool/hostdrvnt/minisop.c @@ -1,13 +1,13 @@ /* * minisop.c - * t@CPʂFileObject->SectionObjectPointer(SOP)ȈՎ܂B - * ^ꂽpXvĂ̂𓯂t@Cƌ􂵂āAvĂꍇ͓SOPԂ܂B + * ファイル単位のFileObject->SectionObjectPointer(SOP)を簡易実装します。 + * 与えられたパスが一致しているものを同じファイルと見做して、一致している場合は同じSOPを返します。 * - * t@CPʂŋʂɂv͔ĂMemory-Mapped FileiEXE̎sɂgpjʼne܂B - * ȊOłIRP_MJ_CREATEPʂSOPĂȂ܂B + * ※ファイル単位で共通にする要件は判明している限りMemory-Mapped File(EXEの実行時にも使用)で影響します。 + * それ以外ではIRP_MJ_CREATE単位でSOP生成しても問題なく動きます。 * - * HACK: ܂@\@minisop.h#define USE_CACHEHACKƁA - * LbVł}bvgt@CgWORKAROUND֐gB + * HACK: おまけ機能 minisop.hで#define USE_CACHEHACKすると、 + * キャッシュ未実装でもメモリマップトファイルが使えるWORKAROUND関数が使える。 */ #include @@ -22,37 +22,37 @@ static VOID MiniSOP_ReleaseAllSOP(void); static BOOLEAN MiniSOP_ExpandSOPList(void); -// SECTION_OBJECT_POINTERSێp +// SECTION_OBJECT_POINTERS保持用 typedef struct tagMINISOP_SOP { - UNICODE_STRING path; // Ώۃt@C̃pX@SOP̓t@CɊ蓖Ă̂ŏd͂Ȃ - PSECTION_OBJECT_POINTERS pSOP; // 蓖ĂSECTION_OBJECT_POINTERSւ̃|C^ - ULONG refCount; // QƃJEg 0ɂȂpathpSOP + UNICODE_STRING path; // 対象ファイルのパス SOPはファイル毎に割り当てるので重複はない + PSECTION_OBJECT_POINTERS pSOP; // 割り当てたSECTION_OBJECT_POINTERSへのポインタ + ULONG refCount; // 参照カウント 0になったらpath文字列とpSOPを解放する } MINISOP_SOP, *PMINISOP_SOP; -// SOP̓t@CEfBNgPʂŊǗKv +// SOPはファイル・ディレクトリ単位で管理する必要あり static ULONG g_pendingSOPListCount = 0; static PMINISOP_SOP g_pendingSOPList = NULL; -// QƃJEg𑝂₵SOP擾@Ȃꍇ͐VK쐬@Ȃ-1 +// 参照カウントを増やしてSOPを取得 ない場合は新規作成 作れなければ-1 static BOOLEAN MiniSOP_ExpandSOPList(){ PMINISOP_SOP oldBuffer = g_pendingSOPList; PMINISOP_SOP newBuffer = NULL; ULONG oldCount = g_pendingSOPListCount; ULONG newCount; if(g_pendingSOPListCount == PENDING_SOP_MAX){ - return FALSE; // mۂłȂ + return FALSE; // 確保できない } - newCount = oldCount + 8; // ܂pɂƑςȂ̂łƂ肠8t@CŠg + newCount = oldCount + 8; // あまり頻繁だと大変なのでとりあえず8ファイルずつ拡張 if(newCount > PENDING_SOP_MAX){ newCount = PENDING_SOP_MAX; } newBuffer = ExAllocatePool(NonPagedPool, sizeof(MINISOP_SOP) * newCount); if(newBuffer == NULL){ - return FALSE; // mۂłȂ + return FALSE; // 確保できない } RtlZeroMemory(newBuffer, sizeof(MINISOP_SOP) * newCount); if(g_pendingSOPList != NULL){ - // ݂̓eRs[ + // 現在の内容をコピー RtlCopyMemory(newBuffer, oldBuffer, sizeof(MINISOP_SOP) * oldCount); } g_pendingSOPList = newBuffer; @@ -63,10 +63,10 @@ static BOOLEAN MiniSOP_ExpandSOPList(){ return TRUE; // OK } -// SOPXgBg̃BhCõA[hɌĂяoB +// SOPリストを解放する。中身のメモリも解放される。ドライバのアンロード時に呼び出す。 BOOLEAN MiniSOP_ReleaseSOPList(){ PMINISOP_SOP oldBuffer = g_pendingSOPList; - MiniSOP_ReleaseAllSOP(); // SOPSă[X + MiniSOP_ReleaseAllSOP(); // SOPを全てリリース g_pendingSOPListCount = 0; g_pendingSOPList = NULL; if(oldBuffer != NULL){ @@ -75,23 +75,23 @@ BOOLEAN MiniSOP_ReleaseSOPList(){ return TRUE; // OK } -// w肵t@CɑΉSOPXg̃CfbNXԂB -// Xgɖꍇ͐VK蓖ĂB\[XsŊ蓖ĂłȂꍇ-1ԂB -// ĂԓxɎQƃJEĝŁAsvɂȂKHostdrvReleaseSOPByIndex܂HostdrvReleaseSOP邱ƁB +// 指定したファイル名に対応するSOPリストのインデックスを返す。 +// リストに無い場合は新規割り当てする。リソース不足で割り当てできない場合は-1を返す。 +// 呼ぶ度に参照カウントされるので、不要になったら必ず同じ回数HostdrvReleaseSOPByIndexまたはHostdrvReleaseSOPをすること。 LONG MiniSOP_GetSOPIndex(UNICODE_STRING path){ int i; for(i=0;i 0){ g_pendingSOPList[i].refCount--; } if(g_pendingSOPList[i].refCount==0){ - // QƖȂ̂ŏ + // 参照無くなったので消す ExFreePool(g_pendingSOPList[i].path.Buffer); g_pendingSOPList[i].path.Buffer = NULL; g_pendingSOPList[i].path.Length = 0; @@ -146,7 +146,7 @@ VOID MiniSOP_ReleaseSOPByIndex(LONG i){ } } -// w肵SOP̎QƃJEg炷@0ɂȂ +// 指定したSOPの参照カウントを減らす 0になったら解放 VOID MiniSOP_ReleaseSOP(PSECTION_OBJECT_POINTERS lpSOP){ int i; for(i=0;iFastIoDispatch = &g_FastIoDispatch; } -// IRP_MJ_CREATExɌĂԁBLbVăfBXN̍READB -// irpSp: IRPX^bN|C^ +// IRP_MJ_CREATEが成功する度に呼ぶ。キャッシュ消去してディスクからの再READを強制。 +// irpSp: IRPスタックポインタ VOID MiniSOP_HandleMjCreateCache(PIO_STACK_LOCATION irpSp){ CC_FILE_SIZES sizes = {0}; PFILE_OBJECT pFileObject = irpSp->FileObject; @@ -225,11 +225,11 @@ VOID MiniSOP_HandleMjCreateCache(PIO_STACK_LOCATION irpSp){ return; } - // LbVTCY0ɂ邱ƂŋIɃfBXNēǍ + // キャッシュサイズを0にすることで強制的にディスクから再読込させる CcSetFileSizes(pFileObject, &sizes); } -// IRP_MJ_CLEANUPxɌĂԁBLbV̓eIɃfBXNWRITEB -// irpSp: IRPX^bN|C^ +// IRP_MJ_CLEANUPが成功する度に呼ぶ。キャッシュの内容を強制的にディスクにWRITEさせる。 +// irpSp: IRPスタックポインタ VOID MiniSOP_HandleMjCleanupCache(PIO_STACK_LOCATION irpSp){ IO_STATUS_BLOCK iosb = {0}; PFILE_OBJECT pFileObject = irpSp->FileObject; @@ -238,14 +238,14 @@ VOID MiniSOP_HandleMjCleanupCache(PIO_STACK_LOCATION irpSp){ return; } - // LbV̓eIɃfBXN֏߂ + // キャッシュの内容を強制的にディスクへ書き戻させる CcFlushCache(pFileObject->SectionObjectPointer, NULL, 0, &iosb); //MmFlushImageSection(pFileObject->SectionObjectPointer, MmFlushForDelete); //CcUninitializeCacheMap(pFileObject, NULL, NULL); } -// IRP_MJ_SET_INFORMATIONŎۂ̃t@CTCYύX O ĂԁBLbṼt@CύXʒmB -// ۂ̏́Aw肳ꂽt@CȏňUWRITE遨SetInformationŐ؂̂Ă@ƂɂȂ -// irpSp: IRPX^bN|C^ +// IRP_MJ_SET_INFORMATIONで実際のファイルサイズを変更する 前に 呼ぶ。キャッシュのファイル長さ変更を通知。 +// 実際の処理は、指定されたファイル長さ以上で一旦WRITEされる→SetInformationで切り捨てる という操作になる +// irpSp: IRPスタックポインタ VOID MiniSOP_HandlePreMjSetInformationCache(PIO_STACK_LOCATION irpSp){ if(irpSp->Parameters.QueryFile.FileInformationClass == FileEndOfFileInformation || irpSp->Parameters.QueryFile.FileInformationClass == FileAllocationInformation){ @@ -253,8 +253,8 @@ VOID MiniSOP_HandlePreMjSetInformationCache(PIO_STACK_LOCATION irpSp){ if(pFileObject && pFileObject->SectionObjectPointer){ IO_STATUS_BLOCK iosb = {0}; CC_FILE_SIZES sizes = {0}; - CcFlushCache(pFileObject->SectionObjectPointer, NULL, 0, &iosb); // ݂̃LbVfBXN֏߂ - CcSetFileSizes(pFileObject, &sizes); // LbVZbg + CcFlushCache(pFileObject->SectionObjectPointer, NULL, 0, &iosb); // 現在のキャッシュをディスクへ書き戻し + CcSetFileSizes(pFileObject, &sizes); // キャッシュをリセット } } } diff --git a/np2tool/hostdrvnt/minisop.h b/np2tool/hostdrvnt/minisop.h index 9107aad2..463afdf7 100644 --- a/np2tool/hostdrvnt/minisop.h +++ b/np2tool/hostdrvnt/minisop.h @@ -2,44 +2,44 @@ * minisop.h */ -// #include KvB +// 先に#include が必要。 -// `ĂƃLbVNApWORKAROUND֐gp”\ +// これを定義しておくとキャッシュクリア用のWORKAROUND関数を使用可能 #define USE_CACHEHACK -// SOPXgBg̃BhCõA[hɌĂяoB +// SOPリストを解放する。中身のメモリも解放される。ドライバのアンロード時に呼び出す。 BOOLEAN MiniSOP_ReleaseSOPList(); -// w肵t@CɑΉSOPXg̃CfbNXԂB -// Xgɖꍇ͐VK蓖ĂB\[XsŊ蓖ĂłȂꍇ-1ԂB -// ĂԓxɎQƃJEĝŁAsvɂȂKHostdrvReleaseSOPByIndex܂HostdrvReleaseSOP邱ƁB +// 指定したファイル名に対応するSOPリストのインデックスを返す。 +// リストに無い場合は新規割り当てする。リソース不足で割り当てできない場合は-1を返す。 +// 呼ぶ度に参照カウントされるので、不要になったら必ず同じ回数HostdrvReleaseSOPByIndexまたはHostdrvReleaseSOPをすること。 LONG MiniSOP_GetSOPIndex(UNICODE_STRING path); -// w肵SOPXg̃CfbNXɑΉSECTION_OBJECT_POINTERSւ̃|C^ԂB -// ȃCfbNXłNULLԂ +// 指定したSOPリストのインデックスに対応するSECTION_OBJECT_POINTERSへのポインタを返す。 +// 無効なインデックスであればNULLが返る PSECTION_OBJECT_POINTERS MiniSOP_GetSOP(LONG i); -// w肵SOP̎QƃJEg炷@0ɂȂB +// 指定したSOPの参照カウントを減らす 0になったら解放される。 VOID MiniSOP_ReleaseSOP(PSECTION_OBJECT_POINTERS lpSOP); -// w肵CfbNXSOP̎QƃJEg炷@0ɂȂB +// 指定したインデックスのSOPの参照カウントを減らす 0になったら解放される。 VOID MiniSOP_ReleaseSOPByIndex(LONG i); -// HACK: ܂@\@LbVł}bvgt@Cg悤ɂB +// HACK: おまけ機能 キャッシュ未実装でもメモリマップトファイルが使えるようにする。 #ifdef USE_CACHEHACK -// ̒r[LbV̂߂̏BDriverEntryŌĂԂƁB -// DriverObject: DriverEntrÿŎ󂯎DriverObject +// 未実装の中途半端キャッシュのための初期化。DriverEntryで呼ぶこと。 +// DriverObject: DriverEntryの引数で受け取ったDriverObject VOID MiniSOP_InitializeCache(PDRIVER_OBJECT DriverObject); -// IRP_MJ_CREATExɌĂԁBLbVăfBXN̍READB -// irpSp: IRPX^bN|C^ +// IRP_MJ_CREATEが成功する度に呼ぶ。キャッシュ消去してディスクからの再READを強制。 +// irpSp: IRPスタックポインタ VOID MiniSOP_HandleMjCreateCache(PIO_STACK_LOCATION irpSp); -// IRP_MJ_CLEANUPxɌĂԁBLbV̓eIɃfBXNWRITEB -// irpSp: IRPX^bN|C^ +// IRP_MJ_CLEANUPが成功する度に呼ぶ。キャッシュの内容を強制的にディスクにWRITEさせる。 +// irpSp: IRPスタックポインタ VOID MiniSOP_HandleMjCleanupCache(PIO_STACK_LOCATION irpSp); -// IRP_MJ_SET_INFORMATIONŎۂ̃t@CTCYύX O ĂԁBLbṼt@CύXʒmB -// ۂ̏́Aw肳ꂽt@CȏňUWRITE遨SetInformationŐ؂̂Ă@ƂɂȂ -// irpSp: IRPX^bN|C^ +// IRP_MJ_SET_INFORMATIONで実際のファイルサイズを変更する 前に 呼ぶ。キャッシュのファイル長さ変更を通知。 +// 実際の処理は、指定されたファイル長さ以上で一旦WRITEされる→SetInformationで切り捨てる という操作になる +// irpSp: IRPスタックポインタ VOID MiniSOP_HandlePreMjSetInformationCache(PIO_STACK_LOCATION irpSp); #endif /* USE_CACHEHACK */ diff --git a/np2tool/hostdrvnt/readme.txt b/np2tool/hostdrvnt/readme.txt index adb869ab..c47a267c 100644 --- a/np2tool/hostdrvnt/readme.txt +++ b/np2tool/hostdrvnt/readme.txt @@ -1,149 +1,149 @@ - Neko Project II zXgLhCuhCo for WinNT +■■■ Neko Project II ホスト共有ドライブドライバ for WinNT ■■■ -Windows NTnNeko Project IĨzXgLhCuɃANZX邽߂̃foCX -hCołBG~[^OSzXgPC̎wtH_ɃANZXł܂B -HOSTDRV.COMWindows NTłłBOt@Cl[ɂΉĂ܂B +Windows NT系からNeko Project IIのホスト共有ドライブにアクセスするためのデバイス +ドライバです。エミュレータ内のOSからホストPCの指定フォルダにアクセスできます。 +HOSTDRV.COMのWindows NT版です。ロングファイルネームにも対応しています。 -yӁIIz -Neko Project IĨoOQXgOS̖\ꍇẢezXg̃t@C -ɂyԂƂɂȂ܂̂ŁAL͈͂ƃANZX͕KvŏɂƂǂ߂鎖 -߂܂iȂƂL͈͊O͈SłjB -{@\gpăt@CꍇłA҂͐ӔC𕉂܂B -̂ƂɓӒȂꍇ͎gpȂłB +【注意!!】 +Neko Project IIのバグやゲストOSの暴走が発生した場合、その影響がホストのファイル +にも及ぶことになりますので、共有範囲とアクセス権限は必要最小限にとどめる事を +おすすめします(少なくとも共有範囲外は安全です)。 +本機能を使用してファイルが消失した場合でも、作者は責任を負いません。 +そのことに同意頂けない場合は使用しないでください。 -‹ -yQXgz +●動作環境 +【ゲスト】 Windows NT3.51, NT4.0, 2000 -yzXgz -Neko Project 21/W ver0.86 rev9410ȍ~ -ݒHostdrvHostdrv for NTLɂËiINIݒj - - -CXg[ -hCoQXgOSɃCXg[Ďgp܂B -EWindows NT4.0, 2000̏ꍇ -KV[hCoŃCXg[܂B -hostdrv.infENbNCXg[ -ŃCXg[ł܂B -Abvf[głł܂Afɂ̓VXe̍ċNKvłB -قAtregt@CC|[gĂCXg[ł܂B - -EWindows NT3.51̏ꍇ -tinstinf.exesĂB -蓮ŃCXg[ꍇA -hostdrv.infɋLڂ[NP2HostDrive.AddReg]ZNV̓eQlɁA -regedt32gpĎ蓮őłłB - - -ACXg[ -EWindows NT3.51, NT4.0̏ꍇ -Rg[plfoCXNeko Project II Host DrivẽX^[gAbv -ɂĂBɏꍇAWXgGfB^ +【ホスト】 +Neko Project 21/W ver0.86 rev94β10以降 +設定でHostdrvおよびHostdrv for NTを有効にしている環境(INI設定も可) + + +●インストール +ドライバをゲストOSにインストールして使用します。 +・Windows NT4.0, 2000の場合 +レガシードライバ扱いでインストールします。 +hostdrv.infを右クリック→インストール +でインストールできます。 +アップデートも同じ操作でできますが、反映にはシステムの再起動が必要です。 +ほか、付属のregファイルをインポートしてもインストールできます。 + +・Windows NT3.51の場合 +付属のinstinf.exeを実行してください。 +手動でインストールしたい場合、 +hostdrv.inf内に記載の[NP2HostDrive.AddReg]セクションの内容を参考に、 +regedt32を使用して手動で打ち込んでください。 + + +●アンインストール +・Windows NT3.51, NT4.0の場合 +コントロールパネル→デバイスでNeko Project II Host Driveのスタートアップを +無効にしてください。完璧に消したい場合、レジストリエディタで HKLM\System\CurrentControlSet\Services\hostdrv -ĂB -t@Cꍇ +を消してください。 +ファイルも消したい場合は System32\drivers\hostdrv.sys System32\hdrvmnt.exe -ĂB +を消してください。 -EWindows 2000̏ꍇ -foCX}l[W\\̃foCX̕\ -ŃvOAhvCł͂ȂhCo\A -Neko Project II Host Drive폜ĂB -肭ȂꍇWindows NT3.51, NT4.0̏ꍇƓ菇ō폜ĂB +・Windows 2000の場合 +デバイスマネージャ→表示→非表示のデバイスの表示 +でプラグアンドプレイではないドライバを表示させ、 +Neko Project II Host Driveを削除してください。 +上手く消えない場合はWindows NT3.51, NT4.0の場合と同じ手順で削除してください。 -g -ver.1.5玩}EgftHgŗLɂȂ܂B -蓮}Egɂꍇ́A +●使い方 +ver.1.5から自動マウントがデフォルトで有効になりました。 +手動マウントにしたい場合は、 HKLM\System\CurrentControlSet\Services\hostdrv -̒ɂAutoMount0ɂĂB +の中にあるAutoMountを0にしてください。 -蓮}Egɂꍇ́AVXeɓo^ꂽhdrvmnt.exegpăhCu -蓖Ă܂B -@np2iniUSEHDRVN=trueĉB -Anp2{̂̋LtH_ݒ{ĉB -inp21/wȂDevice->Hostdrv OptionŐݒ”\j -BHOSTDRV.COMƓlɁAhdrvmnt.exehCutĎsĂB +手動マウントにした場合は、システムに登録されたhdrvmnt.exeを使用してドライブ +文字を割り当てます。 +①np2のiniにUSEHDRVN=trueを書いて下さい。 +②np2本体の共有フォルダ設定を実施して下さい。 +(np21/wならDevice->Hostdrv Optionで設定可能) +③HOSTDRV.COMと同様に、hdrvmnt.exeをドライブ文字を付けて実行してください。 -@hdrvmnt hCu(A`Z) + hdrvmnt ドライブ文字(A~Z) -NɎŊ蓖Ăꍇ́ÁuljݒvQƂĂB -ȂAWin2000ŃhCuɁ~}[Nt܂AʂɃANZXł܂ -̂ŋCɂȂʼnB -CɂȂl͂̃hLg̍Ō̕ɂ邨܂̍ڂQƂĂB +起動時に自動で割り当てたい場合は、次の「追加設定」を参照してください。 +なお、Win2000でドライブに×マークが付けられますが、普通にアクセスできます +ので気にしないで下さい。 +気になる人はこのドキュメントの最後の方にあるおまけの項目を参照してください。 -ljݒ +●追加設定 HKLM\System\CurrentControlSet\Services\hostdrv -ֈȉ̒lljƋύXł܂ivċNjB +へ以下の値を追加すると挙動を変更できます(要再起動)。 -IsDiskDevice -DWORDl1ɂƁAlbg[NhCuł͂Ȃʂ̃fBXNhCuƂ -F܂B +○IsDiskDevice +DWORD値を1にすると、ネットワークドライブではなく普通のディスクドライブとして +認識させます。 -IsRemovableDevice -DWORDl1ɂƁAlbg[NhCuł͂Ȃ[ouhCuƂ -F܂BIsDiskDevicẽtOD悳܂B +○IsRemovableDevice +DWORD値を1にすると、ネットワークドライブではなくリムーバブルドライブとして +認識させます。IsDiskDeviceよりもこちらのフラグが優先されます。 -UseRealCapacity -DWORDl1ɂƁAzIȗeʂł͂ȂzXg̃fBXN̎eʂԂ܂B +○UseRealCapacity +DWORD値を1にすると、仮想的な容量ではなくホストのディスクの実容量を返します。 -UseCheckNotify -DWORDl1ɂƁAzXgł̃t@CύXQXgOSɒʒm܂B -GNXv[Ȃǂŕ\XViF5jɃzXgł̃t@Clj폜 -f܂A|[Ôߕׂ܂B +○UseCheckNotify +DWORD値を1にすると、ホストでのファイル変更をゲストOSに通知します。 +エクスプローラなどで表示更新(F5)をせずにホストでのファイル追加削除が +反映されますが、ポーリング処理のため負荷が増加します。 -CheckNotifyInterval -UseCheckNotify=1̂ƂA|[OԊuibjDWORDlŎw肵܂B -ŏ1bAő60błB +○CheckNotifyInterval +UseCheckNotify=1のとき、ポーリング間隔(秒)をDWORD値で指定します。 +最小は1秒、最大は60秒です。 -AutoMount -DWORDl1ɂƁAhCõ[hɎIɃhCu蓖Ă܂B -̃IvVLɂhdrvmnt͎gpł܂iςɂȂ܂jB +○AutoMount +DWORD値を1にすると、ドライバのロード時に自動的にドライブ文字を割り当てます。 +このオプションを有効にするとhdrvmntは使用できません(挙動が変になります)。 -AutoMountDriveLetter -AutoMount=1̂ƂAhCõ[hɎI蓖ĂhCu -REG_SZŎw肵܂BhCuA`Z1Ŏw肵ĉi:͕tȂjB -"Auto"܂͖l̏ꍇ́AZ珇Y,X,W,...Ƌ󂫂T܂B +○AutoMountDriveLetter +AutoMount=1のとき、ドライバのロード時に自動的割り当てるドライブ文字を +REG_SZで指定します。ドライブ文字はA~Zの1文字で指定して下さい(:は付けない)。 +"Auto"または無効値の場合は、Zから順にY,X,W,...と空きを探します。 -\[XR[h -np21/w\[Xnp2tool\hostdrvntɃ\[XR[h܂B -SĔL{̂ƓCBSDCZXƂ܂AIɎRɎgĂ -vłBςȂĂȂ؂\肷Ȃ莩RɂĂB +●ソースコード +np21/wソースのnp2tool\hostdrvntにソースコードがあります。 +全て猫本体と同じ修正BSDライセンスとしますが、実質的に自由に使っていただいて +大丈夫です。煮るなり焼くなり切り貼りするなり自由にしてください。 -SɎg߂̃qg -Neko Project 21/WHostdrvݒŁAANZXOƂ̑֎~ł܂B -ƂWRITEDELETEĂ΁AQXgOS\ŏɏꂽ -ꂽ肷Qh~ł܂i҂͍̂Ƃ͏o킵Ƃ͂ȂłjB -܂AHostdrvݒŋLpX܂܂Ȃꏊւ̓ANZXłȂdl -ȂĂ܂BāAHostdrvݒŋLpX͕Kvŏɔ͈͂ɂ -SłB -OƂāALĂꏊNTFSV{bNNuĂꍇA -̃V{bNN̐ւ̓ANZXłĂ܂܂B -LĂꏊɗ\ȂV{bNN܂܂Ȃ悤ɂĂB -ȂAQXgOS̓V{bNN쐬oȂdlł̂ŁA̓_ -SB +●安全に使うためのヒント +Neko Project 21/WのHostdrv設定で、アクセス権限を外すとその操作を禁止できます。 +たとえばWRITEやDELETE権限を消しておけば、ゲストOS暴走で勝手に書き換えられたり +消されたりする被害を防止できます(作者は今のところは出くわしたことはないです)。 +また、Hostdrv設定で共有するパス部分を含まない場所へはアクセスできない仕様に +なっています。したがって、Hostdrv設定で共有するパスは必要最小限に範囲にする方 +が安全です。 +例外として、共有している場所にNTFSシンボリックリンクが置かれている場合、 +そのシンボリックリンクの先へはアクセスできてしまいます。 +共有している場所に予期しないシンボリックリンクが含まれないようにしてください。 +なお、ゲストOSからはシンボリックリンクを作成出来ない仕様ですので、その点は +ご安心ください。 -܂ -Windows 2000ł̓lbg[NhCuɂƐԐF́~}[Nt܂B -ꂪCɓȂꍇ͑ΏǗÖ@ƂăWXggăhCuACR -u”\łB̓Iɂ͈ȉ̃L[ɐݒs܂B +●おまけ +Windows 2000ではネットワークドライブにすると赤色の×マークが付けられます。 +これが気に入らない場合は対症療法としてレジストリを使ってドライブアイコンの +置き換えが可能です。具体的には以下のキーに設定を行います。 -yz +【やり方】 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DriveIcons\Z\DefaultIcon -̃ftHgl"%SystemRoot%\System32\shell32.dll,9"𑫂B +のデフォルト値に"%SystemRoot%\System32\shell32.dll,9"を足す。 -̏ꍇAZhCũACRIshell32.dll̃ACR9ԂɕύX܂B -tĂdriveico.regZhCuߑłł̐ݒs܂B -AZhCuɉĂⓚpŃlbg[NhCũACRɂȂ -܂Bɖ߂ꍇZȉ̃L[폜čċNĂB +この場合、Zドライブのアイコンを強制的にshell32.dllのアイコン9番に変更します。 +付属させているdriveico.regはZドライブ決め打ちでこの設定を行います。 +ただし、Zドライブに何があっても問答無用でネットワークドライブのアイコンになり +ます。元に戻したい場合はZ以下のキーを削除して再起動してください。 ------------------------ -Neko Project 21/W J +Neko Project 21/W 開発者 SimK diff --git a/np2tool/hostdrvnt/test/fstestA.c b/np2tool/hostdrvnt/test/fstestA.c index 90af2799..bf8988e6 100644 --- a/np2tool/hostdrvnt/test/fstestA.c +++ b/np2tool/hostdrvnt/test/fstestA.c @@ -19,23 +19,23 @@ int main(int argc, char *argv[]) { filePath = (argc > 1) ? argv[1] : "Z:\\test.txt"; if (!GetFileAttributesExA(filePath, GetFileExInfoStandard, &fileInfo)) { - printf("t@C̎擾Ɏs܂BG[R[h: %lu\n", GetLastError()); + printf("ファイル情報の取得に失敗しました。エラーコード: %lu\n", GetLastError()); return 1; } fileSize.HighPart = fileInfo.nFileSizeHigh; fileSize.LowPart = fileInfo.nFileSizeLow; - printf("t@C: %s\n", filePath); - printf("TCY: %lld oCg\n", fileSize.QuadPart); + printf("ファイル: %s\n", filePath); + printf("サイズ: %lld バイト\n", fileSize.QuadPart); - printf("쐬: "); + printf("作成日時: "); PrintFileTime(fileInfo.ftCreationTime); - printf("ŏIANZX: "); + printf("最終アクセス日時: "); PrintFileTime(fileInfo.ftLastAccessTime); - printf("ŏIݓ: "); + printf("最終書き込み日時: "); PrintFileTime(fileInfo.ftLastWriteTime); return 0; diff --git a/np2tool/hostdrvnt/test/fstestB.c b/np2tool/hostdrvnt/test/fstestB.c index cef0d8f0..c028d17a 100644 --- a/np2tool/hostdrvnt/test/fstestB.c +++ b/np2tool/hostdrvnt/test/fstestB.c @@ -6,32 +6,32 @@ void PrintFileSizeUsingGetFileSize(HANDLE hFile) { DWORD lowPart = GetFileSize(hFile, &highPart); ULONGLONG size; if (lowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) { - printf("GetFileSize: G[ %lu\n", GetLastError()); + printf("GetFileSize: エラー %lu\n", GetLastError()); return; } size = ((ULONGLONG)highPart << 32) | lowPart; - printf("[GetFileSize] TCY: %llu oCg\n", size); + printf("[GetFileSize] サイズ: %llu バイト\n", size); } void PrintFileSizeUsingGetFileSizeEx(HANDLE hFile) { LARGE_INTEGER fileSize; if (!GetFileSizeEx(hFile, &fileSize)) { - printf("GetFileSizeEx: G[ %lu\n", GetLastError()); + printf("GetFileSizeEx: エラー %lu\n", GetLastError()); return; } - printf("[GetFileSizeEx] TCY: %lld oCg\n", fileSize.QuadPart); + printf("[GetFileSizeEx] サイズ: %lld バイト\n", fileSize.QuadPart); } void PrintFileSizeUsingGetFileAttributesEx(LPCSTR filePath) { WIN32_FILE_ATTRIBUTE_DATA fileInfo; ULONGLONG size; if (!GetFileAttributesExA(filePath, GetFileExInfoStandard, &fileInfo)) { - printf("GetFileAttributesEx: G[ %lu\n", GetLastError()); + printf("GetFileAttributesEx: エラー %lu\n", GetLastError()); return; } size = ((ULONGLONG)fileInfo.nFileSizeHigh << 32) | fileInfo.nFileSizeLow; - printf("[GetFileAttributesEx] TCY: %llu oCg\n", size); + printf("[GetFileAttributesEx] サイズ: %llu バイト\n", size); } int main(int argc, char *argv[]) { @@ -48,11 +48,11 @@ int main(int argc, char *argv[]) { ); if (hFile == INVALID_HANDLE_VALUE) { - printf("t@CJ܂ł: %lu\n", GetLastError()); + printf("ファイルを開けませんでした: %lu\n", GetLastError()); return 1; } - printf("t@C: %s\n", filePath); + printf("ファイル: %s\n", filePath); PrintFileSizeUsingGetFileSize(hFile); PrintFileSizeUsingGetFileSizeEx(hFile); diff --git a/np2tool/hostdrvnt/test/fstestC.c b/np2tool/hostdrvnt/test/fstestC.c index d8fcbb9a..d808f3b7 100644 --- a/np2tool/hostdrvnt/test/fstestC.c +++ b/np2tool/hostdrvnt/test/fstestC.c @@ -3,7 +3,7 @@ void PrintFileSize(DWORD high, DWORD low) { ULONGLONG size = ((ULONGLONG)high << 32) | low; - printf("TCY: %llu oCg\n", size); + printf("サイズ: %llu バイト\n", size); } int main(int argc, char *argv[]) { @@ -14,22 +14,22 @@ int main(int argc, char *argv[]) { HANDLE hFind = FindFirstFileA(searchPath, &findData); if (hFind == INVALID_HANDLE_VALUE) { - printf("t@C񋓂Ɏs܂BG[R[h: %lu\n", GetLastError()); + printf("ファイル列挙に失敗しました。エラーコード: %lu\n", GetLastError()); return 1; } do { if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - printf("[fBNg] %s\n", findData.cFileName); + printf("[ディレクトリ] %s\n", findData.cFileName); } else { - printf("[t@C] %s\n", findData.cFileName); + printf("[ファイル] %s\n", findData.cFileName); PrintFileSize(findData.nFileSizeHigh, findData.nFileSizeLow); } } while (FindNextFileA(hFind, &findData)); err = GetLastError(); if (err != ERROR_NO_MORE_FILES) { - printf("FindNextFile ŃG[܂: %lu\n", err); + printf("FindNextFile でエラーが発生しました: %lu\n", err); } FindClose(hFind); diff --git a/np2tool/hostdrvnt/test/fstestD.c b/np2tool/hostdrvnt/test/fstestD.c index 9a5144b4..3a09bdb7 100644 --- a/np2tool/hostdrvnt/test/fstestD.c +++ b/np2tool/hostdrvnt/test/fstestD.c @@ -12,7 +12,7 @@ void PrintFileTime(FILETIME ft) { } void PrintAttributes(DWORD attrs) { - printf("t@C: 0x%08lX (", attrs); + printf("ファイル属性: 0x%08lX (", attrs); if (attrs & FILE_ATTRIBUTE_READONLY) printf("READONLY "); if (attrs & FILE_ATTRIBUTE_HIDDEN) printf("HIDDEN "); if (attrs & FILE_ATTRIBUTE_SYSTEM) printf("SYSTEM "); @@ -47,12 +47,12 @@ int main(int argc, char *argv[]) { ); if (hFile == INVALID_HANDLE_VALUE) { - printf("t@CJ܂ł: G[R[h %lu\n", GetLastError()); + printf("ファイルを開けませんでした: エラーコード %lu\n", GetLastError()); return 1; } if (!GetFileInformationByHandle(hFile, &info)) { - printf("GetFileInformationByHandle s: G[R[h %lu\n", GetLastError()); + printf("GetFileInformationByHandle 失敗: エラーコード %lu\n", GetLastError()); CloseHandle(hFile); return 1; } @@ -60,18 +60,18 @@ int main(int argc, char *argv[]) { fileSize = ((ULONGLONG)info.nFileSizeHigh << 32) | info.nFileSizeLow; index = ((ULONGLONG)info.nFileIndexHigh << 32) | info.nFileIndexLow; - printf("t@C: %s\n", filePath); + printf("ファイル: %s\n", filePath); PrintAttributes(info.dwFileAttributes); - printf("쐬: "); + printf("作成日時: "); PrintFileTime(info.ftCreationTime); - printf("ŏIANZX: "); + printf("最終アクセス日時: "); PrintFileTime(info.ftLastAccessTime); - printf("ŏIݓ: "); + printf("最終書き込み日時: "); PrintFileTime(info.ftLastWriteTime); - printf("{[VAԍ: 0x%08lX\n", info.dwVolumeSerialNumber); - printf("t@CTCY: %llu oCg\n", fileSize); - printf("N: %lu\n", info.nNumberOfLinks); - printf("t@CCfbNX: %llu (High: 0x%08lX, Low: 0x%08lX)\n", + printf("ボリュームシリアル番号: 0x%08lX\n", info.dwVolumeSerialNumber); + printf("ファイルサイズ: %llu バイト\n", fileSize); + printf("リンク数: %lu\n", info.nNumberOfLinks); + printf("ファイルインデックス: %llu (High: 0x%08lX, Low: 0x%08lX)\n", index, info.nFileIndexHigh, info.nFileIndexLow); CloseHandle(hFile); diff --git a/np2tool/hostdrvnt/test/fstestE.c b/np2tool/hostdrvnt/test/fstestE.c index 64ab3527..775e36b7 100644 --- a/np2tool/hostdrvnt/test/fstestE.c +++ b/np2tool/hostdrvnt/test/fstestE.c @@ -3,13 +3,13 @@ int main(int argc, char *argv[]) { const char *filePath = (argc > 1) ? argv[1] : "z:\\mmap.txt"; - const DWORD fileSize = 1024; // ŏ1KBm + const DWORD fileSize = 1024; // 最小1KB確保 HANDLE hFile; HANDLE hMapping; LPVOID pMap; char *newData; - // t@CJ܂͍쐬 + // ファイルを開くまたは作成 hFile = CreateFileA( filePath, GENERIC_READ | GENERIC_WRITE, @@ -21,13 +21,13 @@ int main(int argc, char *argv[]) { ); if (hFile == INVALID_HANDLE_VALUE) { - printf("t@CJ܂łBG[: %lu\n", GetLastError()); + printf("ファイルを開けませんでした。エラー: %lu\n", GetLastError()); return 1; } getchar(); - // }bsOIuWFNg̍쐬 + // メモリマッピングオブジェクトの作成 hMapping = CreateFileMappingA( hFile, NULL, @@ -38,12 +38,12 @@ int main(int argc, char *argv[]) { ); if (hMapping == NULL) { - printf("CreateFileMapping sBG[: %lu\n", GetLastError()); + printf("CreateFileMapping 失敗。エラー: %lu\n", GetLastError()); CloseHandle(hFile); return 1; } - // Ƀ}bv + // メモリにマップ pMap = MapViewOfFile( hMapping, FILE_MAP_ALL_ACCESS, @@ -53,25 +53,25 @@ int main(int argc, char *argv[]) { ); if (pMap == NULL) { - printf("MapViewOfFile sBG[: %lu\n", GetLastError()); + printf("MapViewOfFile 失敗。エラー: %lu\n", GetLastError()); CloseHandle(hMapping); CloseHandle(hFile); return 1; } - // f[^\EύXi: 擪ɃbZ[W}j - printf("݂̓ei擪100oCgj:\n"); + // データ表示・変更(例: 先頭にメッセージを挿入) + printf("現在の内容(先頭100バイト):\n"); fwrite(pMap, 1, 100, stdout); - printf("\n\nf[^...\n"); + printf("\n\nデータを書き換え中...\n"); newData = "Hello from memory-mapped file!\n"; memcpy(pMap, newData, strlen(newData)); - // n + // 後始末 UnmapViewOfFile(pMap); CloseHandle(hMapping); CloseHandle(hFile); - printf("܂B\n"); + printf("完了しました。\n"); return 0; } \ No newline at end of file diff --git a/np2tool/nasmmemo.txt b/np2tool/nasmmemo.txt index 946151bb..9ec9c773 100644 --- a/np2tool/nasmmemo.txt +++ b/np2tool/nasmmemo.txt @@ -1,2 +1,2 @@ -ȉ̂悤ɍ쐬 +以下のように作成 nasm -f bin NP2IDLE.ASM -o NP2IDLE.COM \ No newline at end of file diff --git a/np2tool/npmouse/readme.txt b/np2tool/npmouse/readme.txt index 735225a6..160db9df 100644 --- a/np2tool/npmouse/readme.txt +++ b/np2tool/npmouse/readme.txt @@ -1,88 +1,88 @@ - Neko Project II V[X}EXhCo for WinNT +■■■ Neko Project II シームレスマウスドライバ for WinNT ■■■ -WindowsɂNeko Project IIł̃V[X}EX܂B -yӁIIIz -菇ԈႦƃ}EXgȂȂu[XN[ŋNs\ɂȂ肵܂B -}EXgȂ̓L[{[hʼn񕜂ł܂Au[XN[̏ꍇ͕OSŋNāA -WINNT\System32\driversɂnpmouse.sys폜KvAςłB -ɃC[WobNAbvĂ̂ȒPł߂łB +Windows上においてNeko Project II上でのシームレスマウス操作を実現します。 +【注意!!!】 +手順を間違えるとマウスが使えなくなったりブルースクリーンで起動不能になったりします。 +マウスが使えない分はキーボード操作で回復できますが、ブルースクリーンの場合は別OSで起動して、 +WINNT\System32\driversにあるnpmouse.sysを削除する必要があり、復旧が大変です。 +先にイメージ毎バックアップを取っておくのが簡単でおすすめです。 -‹ -yQXgz +●動作環境 +【ゲスト】 Windows NT3.51, NT4.0, 2000 -yzXgz -Neko Project 21/W ver0.86 rev9411ȍ~ -Device->Mouse->Non-capture ControlLȊ‹ - - -CXg[ -EWindows 2000̏ꍇ -T[rX̃CXg[ƃ}EXhCoւ̃tB^o^KvłB -T[rXw2k\npmouse.infENbNCXg[ -ŃCXg[ł܂B -Abvf[głł܂Afɂ̓VXe̍ċNKvłB -}EXhCoւ̃tB^o^iK{j́Aregedt32iregeditł͂ȂjNA +【ホスト】 +Neko Project 21/W ver0.86 rev94β11以降 +Device->Mouse->Non-capture Controlが有効な環境 + + +●インストール +・Windows 2000の場合 +サービスのインストールとマウスドライバへのフィルタ登録が必要です。 +サービスはw2k\npmouse.infを右クリック→インストール +でインストールできます。 +アップデートも同じ操作でできますが、反映にはシステムの再起動が必要です。 +マウスドライバへのフィルタ登録(必須)は、regedt32(regeditではない)を起動し、 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E96F-E325-11CE-BFC1-08002BE10318} -ֈړ܂B̒ɂUpperFiltersmouclassł邱ƂmF܂B -łȂ‹͊Ȃ̂ŒfĂB -ȂȂAUpperFilters̍ڂ_uNbNAȉ2s̓eɂ܂ +へ移動します。その中にあるUpperFiltersがmouclassであることを確認します。 +そうでない環境は危ないので中断してください。 +問題なさそうなら、UpperFiltersの項目をダブルクリックし、以下の2行の内容にします mouclass npmouse -Ԃ厖ł̂ŁAtɂȂłB -ōċN΃V[X}EX삪LɂȂ܂B - -EWindows NT4.0̏ꍇ -KV[hCoŃCXg[܂B -wnt\npmouse.infENbNCXg[ -ŃCXg[ł܂B -Abvf[głł܂Afɂ̓VXe̍ċNKvłB - -EWindows NT3.51̏ꍇ -twnt\instinf.exesĂB -蓮ŃCXg[ꍇA -wnt\npmouse.infɋLڂ[NP2Mouse.AddReg]ZNV̓eQlɁA -regedt32gpĎ蓮őłłB -WINNT\System32\driverswnt\npmouse.sysRs[̂YꂸɁB - - -ACXg[ -EWindows 2000̏ꍇ -K}EXhCoւ̃tB^o^ɍsĂB -Ԃtɂƃ}EXhCoG[ɂȂA}EX삪łȂȂ܂B -iL[{[h삾Ŋ撣Ε͏o܂j -regedt32iregeditł͂ȂjNA +順番も大事ですので、逆にしないでください。 +これで再起動すればシームレスマウス操作が有効になります。 + +・Windows NT4.0の場合 +レガシードライバ扱いでインストールします。 +wnt\npmouse.infを右クリック→インストール +でインストールできます。 +アップデートも同じ操作でできますが、反映にはシステムの再起動が必要です。 + +・Windows NT3.51の場合 +付属のwnt\instinf.exeを実行してください。 +手動でインストールしたい場合、 +wnt\npmouse.inf内に記載の[NP2Mouse.AddReg]セクションの内容を参考に、 +regedt32を使用して手動で打ち込んでください。 +WINNT\System32\driversにwnt\npmouse.sysをコピーするのを忘れずに。 + + +●アンインストール +・Windows 2000の場合 +必ずマウスドライバへのフィルタ登録解除を先に行ってください。 +順番を逆にするとマウスドライバがエラーになり、マウス操作ができなくなります。 +(キーボード操作だけで頑張れば復旧は出来ます) +regedt32(regeditではない)を起動し、 HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E96F-E325-11CE-BFC1-08002BE10318} -ֈړ܂B̒ɂUpperFiltersmouclass1sɖ߂܂B -̌AUċNăV[X삪Ă邱ƂmFĂB -V[X삪Ă邱ƂmFAWXg +へ移動します。その中にあるUpperFiltersをmouclassの1行だけに戻します。 +その後、一旦再起動してシームレス操作が無効化されていることを確認してください。 +シームレス操作が無効化されていることを確認したら、レジストリの HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\npmouse -폜AWINNT\System32\driversɂnpmouse.sys폜΃ACXg[łB +を削除し、WINNT\System32\driversにあるnpmouse.sysを削除すればアンインストール完了です。 -EWindows NT3.51CNT4.0̏ꍇ -WXg +・Windows NT3.51,NT4.0の場合 +レジストリの HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\npmouse -폜AWINNT\System32\driversɂnpmouse.sys폜΃ACXg[łB +を削除し、WINNT\System32\driversにあるnpmouse.sysを削除すればアンインストール完了です。 -g -V[X͈ȉ̏𖞂ꍇɎIɗLɂȂ܂B -@}EXLv`Ԃł͂Ȃ -ADeviceMouseNon-capture ControlON -L̏ȊOł́Aʏ̃}EXhCoƓ΍W̓ɂȂ܂B -‚܂AV[X}EX̐΍WŖN\tgł́A}EX{^ -F12L[Œʏ̃}EXLv`sΖȂgƎv܂B +●使い方 +シームレス操作は以下の条件を満たす場合に自動的に有効になります。 +①マウスキャプチャ状態ではない +②Device→Mouse→Non-capture ControlがON +上記の条件以外では、通常のマウスドライバと同じ相対座標の動作になります。 +つまり、シームレスマウスの絶対座標で問題を起こすソフトでは、マウス中ボタンか +F12キーで通常のマウスキャプチャ操作を行えば問題なく使えると思います。 -\[XR[h -srctH_Ƀ\[XR[h܂B -L{̂ƓCBSDCZXƂ܂AIɎRɎgĂđvłB +●ソースコード +srcフォルダにソースコードがあります。 +いちおう猫本体と同じ修正BSDライセンスとしますが、実質的に自由に使っていただいて大丈夫です。 -XV -2025/06/08 ver.1.0 -2025/06/26 ver.1.1 }EX[[ɎĂƑ삪C +●更新履歴 +2025/06/08 ver.1.0 初版 +2025/06/26 ver.1.1 マウスを左端や上端に持っていくと操作が無視される問題を修正 ------------------------ -Neko Project 21/W J +Neko Project 21/W 開発者 SimK diff --git a/np2tool/npmouse/w2k/npmouse.c b/np2tool/npmouse/w2k/npmouse.c index b2e8c8b7..bb657c21 100644 --- a/np2tool/npmouse/w2k/npmouse.c +++ b/np2tool/npmouse/w2k/npmouse.c @@ -1,5 +1,5 @@ #include -#include // MOUSE_INPUT_DATA Ȃ +#include // MOUSE_INPUT_DATA など #define IOCTL_INTERNAL_MOUSE_CONNECT \ CTL_CODE(FILE_DEVICE_MOUSE, 0x0080, METHOD_NEITHER, FILE_ANY_ACCESS) @@ -21,13 +21,13 @@ typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT Self; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; -KSPIN_LOCK g_IOSpinLock; // I/O̔rbNp +KSPIN_LOCK g_IOSpinLock; // I/Oの排他ロック用 #define NP2_PARAM_PORT 0x7ED #define NP2_CMD_PORT 0x7EF -#define NP2_CMD_MAXLEN 16 // np2dl16byte܂ -#define NP2_READ_MAXLEN 16 // np2dl16byte܂ +#define NP2_CMD_MAXLEN 16 // np2仕様で16byteまで +#define NP2_READ_MAXLEN 16 // np2仕様で16byteまで #define NP2_COMMAND_NP2CHECK "NP2" #define NP2_COMMAND_GETMPOS "getmpos" @@ -40,7 +40,7 @@ BOOLEAN SendNP2Check() char commandText[] = NP2_COMMAND_NP2CHECK; KIRQL oldIrql; - // r̈Jn + // 排他領域開始 KeAcquireSpinLock(&g_IOSpinLock, &oldIrql); for(i=0;i 0 && SendNP2GetMousePos(&x, &y)){ ULONG i; PMOUSE_INPUT_DATA data = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer; - // WORKAROUND: 0Ɩ邱Ƃ̂ōŒł1Ă + // WORKAROUND: 0だと無視されることがあるので最低でも1を入れておく if(x < 1) x = 1; if(y < 1) y = 1; for (i = 0; i < count; i++) { @@ -296,7 +296,7 @@ FilterAddDevice( } } - // g̃foCX쐬 + // 自身のデバイス作成 status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, @@ -310,7 +310,7 @@ FilterAddDevice( KdPrint("npmouse: FilterAddDevice IoCreateDevice success\n"); - // ʂ PDO ɃA^b` + // 下位の PDO にアタッチ lowerDeviceObject = IoAttachDeviceToDeviceStack(filterDeviceObject, PhysicalDeviceObject); if (lowerDeviceObject == NULL) { IoDeleteDevice(filterDeviceObject); @@ -319,13 +319,13 @@ FilterAddDevice( KdPrint("npmouse: FilterAddDevice IoAttachDeviceToDeviceStack success\n"); - // g\̂̏ + // 拡張構造体の初期化 devExt = (PDEVICE_EXTENSION)filterDeviceObject->DeviceExtension; RtlZeroMemory(devExt, sizeof(DEVICE_EXTENSION)); devExt->Self = filterDeviceObject; devExt->UpperConnectData.ClassDeviceObject = lowerDeviceObject; - // foCXtO̐ݒ + // デバイスフラグの設定 filterDeviceObject->Flags |= DO_BUFFERED_IO; if (lowerDeviceObject->Flags & DO_POWER_PAGABLE) filterDeviceObject->Flags |= DO_POWER_PAGABLE; @@ -359,7 +359,7 @@ FilterPower( if(irpStack->MinorFunction == IRP_MN_SET_POWER) { if (irpStack->Parameters.Power.Type == SystemPowerState) { if (irpStack->Parameters.Power.State.SystemState == PowerSystemShutdown) { - // Vbg_EȌ J[\\ėL + // シャットダウン直前の処理 カーソル表示を再有効化 SendNP2ShowCursor(); } } @@ -383,24 +383,24 @@ FilterPnP( KdPrint("npmouse: FilterPnP %d\n", irpStack->MinorFunction); switch (irpStack->MinorFunction) { case IRP_MN_REMOVE_DEVICE: - // A^b` + // アタッチ解除 if (devExt->UpperConnectData.ClassDeviceObject) { IoDetachDevice(devExt->UpperConnectData.ClassDeviceObject); } - // ̃foCX폜 + // 自分のデバイス削除 IoDeleteDevice(DeviceObject); SendNP2ShowCursor(); KdPrint("npmouse: IRP_MN_REMOVE_DEVICE\n"); - // ̃hCo֑ + // 次のドライバへ送る Irp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(devExt->UpperConnectData.ClassDeviceObject, Irp); default: - // ȊOׂ͂ăpXX[ + // それ以外はすべてパススルー IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(devExt->UpperConnectData.ClassDeviceObject, Irp); } @@ -416,7 +416,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) KdPrint("npmouse: loading...\n"); - // rbN@݂̂Ŕj͂Ȃ + // 排他ロック初期化 初期化のみで破棄処理はいらない KeInitializeSpinLock(&g_IOSpinLock); if(!SendNP2Check()) diff --git a/np2tool/npmouse/wnt/npmouse.c b/np2tool/npmouse/wnt/npmouse.c index 823e21ea..6e290710 100644 --- a/np2tool/npmouse/wnt/npmouse.c +++ b/np2tool/npmouse/wnt/npmouse.c @@ -1,5 +1,5 @@ #include -#include // MOUSE_INPUT_DATA Ȃ +#include // MOUSE_INPUT_DATA など #define MOUSEPORT_DEVNAME L"\\Device\\PointerClass0" @@ -22,7 +22,7 @@ typedef struct _DEVICE_EXTENSION { BOOLEAN g_unloaded = FALSE; -KSPIN_LOCK g_IOSpinLock; // I/O̔rbNp +KSPIN_LOCK g_IOSpinLock; // I/Oの排他ロック用 #define HOSTDRVNT_IO_ADDR 0x7EC #define HOSTDRVNT_IO_CMD 0x7EE @@ -30,8 +30,8 @@ BOOLEAN g_unloaded = FALSE; #define NP2_PARAM_PORT 0x7ED #define NP2_CMD_PORT 0x7EF -#define NP2_CMD_MAXLEN 16 // np2dl16byte܂ -#define NP2_READ_MAXLEN 16 // np2dl16byte܂ +#define NP2_CMD_MAXLEN 16 // np2仕様で16byteまで +#define NP2_READ_MAXLEN 16 // np2仕様で16byteまで #define NP2_COMMAND_NP2CHECK "NP2" #define NP2_COMMAND_GETMPOS "getmpos" @@ -44,7 +44,7 @@ BOOLEAN SendNP2Check() char commandText[] = NP2_COMMAND_NP2CHECK; KIRQL oldIrql; - // r̈Jn + // 排他領域開始 KeAcquireSpinLock(&g_IOSpinLock, &oldIrql); for(i=0;i 0 && SendNP2GetMousePos(&x, &y)){ ULONG i; PMOUSE_INPUT_DATA data = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer; - // WORKAROUND: 0Ɩ邱Ƃ̂ōŒł1Ă + // WORKAROUND: 0だと無視されることがあるので最低でも1を入れておく if(x < 1) x = 1; if(y < 1) y = 1; for (i = 0; i < count; i++) { @@ -266,7 +266,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) KdPrint("npmouse: loading...\n"); - // rbN@݂̂Ŕj͂Ȃ + // 排他ロック初期化 初期化のみで破棄処理はいらない KeInitializeSpinLock(&g_IOSpinLock); if(!SendNP2Check()) @@ -291,14 +291,14 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) KdPrint("npmouse: IoCreateDevice success\n"); - // A^b` + // アタッチ status = IoAttachDevice(deviceObject, &devName, &lowerDevice); if (!NT_SUCCESS(status)) { IoDeleteDevice(deviceObject); return status; } - // g\̂̏ + // 拡張構造体の初期化 devExt = (PDEVICE_EXTENSION)deviceObject->DeviceExtension; RtlZeroMemory(devExt, sizeof(DEVICE_EXTENSION)); devExt->Self = deviceObject; @@ -309,7 +309,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) } DriverObject->MajorFunction[IRP_MJ_READ] = FilterRead; - // tO𗧂Ă@Ȃƃu[XN[ + // 初期化完了フラグを立てる これをしないとブルースクリーン deviceObject->Flags |= DO_BUFFERED_IO; if (deviceObject->Flags & DO_POWER_PAGABLE) deviceObject->Flags |= DO_POWER_PAGABLE; diff --git a/np2tool/npstor/npstor.c b/np2tool/npstor/npstor.c index 73e25b5f..3eec801d 100644 --- a/np2tool/npstor/npstor.c +++ b/np2tool/npstor/npstor.c @@ -43,7 +43,7 @@ ULONG DriverEntry(PVOID DriverObject, PVOID RegistryPath) { CHAR deviceId[] = "SCSI\\NP2_____FASTSTORAGE_____1.00"; ULONG status; - // ΉȈՃ`FbN + // 対応かを簡易チェック if(ScsiPortReadPortUchar((PUCHAR)NPSTOR_IO_ADDR) != 98 || ScsiPortReadPortUchar((PUCHAR)NPSTOR_IO_CMD) != 21){ return STATUS_NO_SUCH_DEVICE; } @@ -106,7 +106,7 @@ ULONG HwFindAdapter(PVOID DeviceExtension, PVOID Context, (*ConfigInfo->AccessRanges)[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x7EA); (*ConfigInfo->AccessRanges)[0].RangeLength = 2; - (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE; // FALSE=I/O|[g + (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE; // FALSE=I/Oポート *Again = FALSE; @@ -129,9 +129,9 @@ BOOLEAN HwStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb) { Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; - // ˂[{̂ɏϔC - // f[^i[̉zAhXI/O|[gNPSTOR_IO_ADDR֏݁A - // NPSTOR_IO_CMD0x980x01̏ŏނƔL{̂sB + // ねこー本体に処理を委任する + // データ格納先の仮想メモリアドレスをI/OポートNPSTOR_IO_ADDRへ書き込み、 + // NPSTOR_IO_CMDに0x98→0x01の順で書き込むと猫本体が処理を実行する。 invokeInfo.version = 1; invokeInfo.cmd = 0; invokeInfo.srbAddr = Srb; diff --git a/np2tool/npstor/readme.txt b/np2tool/npstor/readme.txt index d5519dd2..b3664c81 100644 --- a/np2tool/npstor/readme.txt +++ b/np2tool/npstor/readme.txt @@ -1,96 +1,96 @@ - Neko Project II pSCSIRg[hCo for Windows +■■■ Neko Project II 専用SCSIコントローラドライバ for Windows ■■■ -WindowsŎgpoNeko Project II pSCSIRg[hCołB -DMÂ悤Ȏdg݂œ߁AWIDEhCoƔׂƔɍłB +Windowsで使用出来るNeko Project II 専用SCSIコントローラドライバです。 +DMAのような仕組みで動くため、標準IDEドライバと比べると非常に高速です。 -‹ -yQXgz +●動作環境 +【ゲスト】 Windows 95, 98, 98SE, NT3.51, NT4.0, 2000 -yzXgz -Neko Project 21/W ver0.86 rev953ȍ~ -SCSI݊CHSƒfBXNSCSIfBXNƂă}EgË -SCSIłH15܂łȓ_ɓɒӂĂ -hCoWin95, 98, 98SE, 2000pWinNT4.0, 3.51pɕĂ܂ +【ホスト】 +Neko Project 21/W ver0.86 rev95β3以降 +SCSI互換のCHSを持つディスクをSCSIディスクとしてマウントしている環境 +※SCSIではHが15までな点に特に注意してください +※ドライバはWin95, 98, 98SE, 2000用とWinNT4.0, 3.51用に分かれています -CXg[ -EWindows 95, 98, 98SȄꍇ -ZbgAbvDOS݊[hœ܂BWindows̃ZbgAbv -npstor.hdm}An[hEFAEBU[hnpstor.infw肵ăCXg[ -ĂB +●インストール +・Windows 95, 98, 98SEの場合 +セットアップ時はDOS互換モードで動きます。Windowsのセットアップが完了した後で +npstor.hdmを挿入し、ハードウェアウィザードでnpstor.infを指定してインストール +してください。 -EWindows 2000̏ꍇ -yZbgAbvɎgꍇz -ZbgAbvJnF6L[ŃhCoǂݍ܂܂B -ʂoSL[npstor.hdm}ĂB -yZbgAbvɎgꍇz -npstor.hdm}n[hEFA̒ljƍ폜npstor.infw肵ăCXg[ -ĂB +・Windows 2000の場合 +【セットアップ時に使う場合】 +セットアップ開始時にF6キーでドライバを読み込ませます。 +画面が出たらSキーを押してnpstor.hdmを挿入してください。 +【セットアップ後に使う場合】 +npstor.hdmを挿入しハードウェアの追加と削除でnpstor.infを指定してインストール +してください。 -EWindows NT4.0̏ꍇ -yZbgAbvɎgꍇz -ZbgAbvrɃhCoǂݍ܂܂B -ʂoSL[wnt\npstornt.hdm}ĂB -yZbgAbvɎgꍇz -wnt\npstornt.hdm}Rg[plSCSIA_v^npstor.infw肵 -CXg[ĂB +・Windows NT4.0の場合 +【セットアップ時に使う場合】 +セットアップ途中にドライバを読み込ませます。 +画面が出たらSキーを押してwnt\npstornt.hdmを挿入してください。 +【セットアップ後に使う場合】 +wnt\npstornt.hdmを挿入しコントロールパネルのSCSIアダプタでnpstor.infを指定して +インストールしてください。 -EWindows NT3.51̏ꍇ -yZbgAbvɎgꍇz -ZbgAbvrɃhCoǂݍ܂܂B -ʂoSL[wnt\npstornt.hdm}ĂB -yZbgAbvɎgꍇz -CWindows NTZbgAbvJAݒ胁j[SCSIA_v^̒ljƍ폜 -IAwnt\npstornt.hdm}ăhCoCXg[ĂB +・Windows NT3.51の場合 +【セットアップ時に使う場合】 +セットアップ途中にドライバを読み込ませます。 +画面が出たらSキーを押してwnt\npstornt.hdmを挿入してください。 +【セットアップ後に使う場合】 +メインのWindows NTセットアップを開き、設定メニューのSCSIアダプタの追加と削除を +選択し、wnt\npstornt.hdmを挿入してドライバをインストールしてください。 -\[XR[h -srctH_Ƀ\[XR[h܂B -LSCSI̎gɂ‚ẮAnp21w\[Xcbus\scsiio.cQƂĂB -L{̂ƓCBSDCZXƂ܂AIɎRɎgĂđvłB -y̎dlɏ]ēƎhCoꍇ̒Ӂz -Win2000EBDt@Cߐs΍ƂāA20MBޖBUSYԂ܂B -BUSYԂĂꍇCɂɃgCΐ܂B -i̎dlȏꍇANP2STOR_INVOKEINFOcmd1ɂĂj -܂AnAhX̓y[WOLȂ牼zAhXłB -̍ہAnAhXŃy[WtH[gNȂ悤ɂĂB -ȂAnp2wi286A[hŁjł̓T|[gĂ܂B +●ソースコード +srcフォルダにソースコードがあります。 +猫SCSIの使い方については、np21wソースのcbus\scsiio.cも参照してください。 +いちおう猫本体と同じ修正BSDライセンスとしますが、実質的に自由に使っていただいて大丈夫です。 +【この仕様に従って独自ドライバを書きたい場合の注意】 +Win2000のEBDファイル埋め尽くし対策として、約20MB書き込む毎にBUSYを返します。 +BUSYが返ってきた場合何も気にせずにリトライすれば成功します。 +(この仕様が嫌な場合、NP2STOR_INVOKEINFOのcmdを1にしてください) +また、渡すアドレスはページング有効なら仮想メモリアドレスです。 +この際、渡したアドレスでページフォールトが起こらないようにしてください。 +なお、np2w(286リアルモード限定版)ではサポートしていません。 -LSCSIdl -LSCSI͊SɃG~[^OƂ@œ삵܂B -ȉ̎菇œo̓f[^pӂAI/O|[gɒlނƁAnp2{̂ -z}V̏DđɃf[^ǂݏAēxz}Vɐ -߂܂BāAz}VI/O|[gɏ񂾏uԂɃf[^ -ꂽ悤Ɍ܂B -@NP2STOR_INVOKEINFO\̂ziy[Wv[jɊmۂAKvȏ -݂܂Bf[^\np21w\[Xcbus\scsiio.cQƂĂB +●猫SCSI仕様 +猫SCSIは完全にエミュレータを前提とした方法で動作します。 +以下の手順で入出力データを用意し、特定のI/Oポートに値を書き込むと、np2本体が +仮想マシンの処理を奪い取って代わりにデータを読み書きし、再度仮想マシンに制御を +戻します。したがって、仮想マシン内からはI/Oポートに書き込んだ瞬間にデータが処理 +されたように見えます。 +①NP2STOR_INVOKEINFO構造体を仮想メモリ(非ページプール)に確保し、必要な情報を +書き込みます。データ構造はnp21wソースのcbus\scsiio.cを参照してください。 typedef struct { - UINT32 version; // o[W ̂Ƃ1̂ - UINT32 cmd; // R}h NP2STOR_INVOKECMD_xxx@cbus\scsiio.cQ - SCSI_REQUEST_BLOCK *srb; // SCSI_REQUEST_BLOCKւ̉zAhX + UINT32 version; // バージョン 今のところ1のみ + UINT32 cmd; // コマンド NP2STOR_INVOKECMD_xxx cbus\scsiio.cを参照 + SCSI_REQUEST_BLOCK *srb; // SCSI_REQUEST_BLOCKへの仮想メモリアドレス } NP2STOR_INVOKEINFO; -̂srbɂ́AWindowsNTSCSI~j|[ghCoSCSI_REQUEST_BLOCK\ -ւ̉zAhXi[܂B -ꕔgpĂ܂̂őSĂ^ʖڂɖ߂Kv͂܂B -gpĂ̂̏ڍׂnp21w\[Xcbus\scsiio.cQƂĂB -Gcɂ́AFunctionɎs~j|[g@\ACdbSCSIR}h̒gA -DataBufferɓo̓obt@ւ̃AhXADataTransferLengthɃobt@TCY -i䂪Ԃ͖߂lf[^TCYjASrbStatusɃXe[^X܂B -ALNP2STOR_INVOKEINFO\̂̉zAhXI/O|[g7EAh֏݁A -I/O|[g7EBh0x980x01̏ŏނƔL{̂s܂B -Bn\̂srb->SrbStatusĐۂ𔻒f܂B -SCSIOP_WRITE̕ԎSRB_STATUS_BUSY̏ꍇ͉lɃgCOKłB +このうちsrbには、WindowsNTのSCSIミニポートドライバのSCSI_REQUEST_BLOCK構造体 +への仮想メモリアドレスを格納します。 +一部しか使用していませんので全てを真面目に埋める必要はありません。 +何を使用しているのかの詳細はnp21wソースのcbus\scsiio.cを参照してください。 +大雑把には、Functionに実行するミニポート機能、CdbにSCSIコマンドの中身、 +DataBufferに入出力バッファへのアドレス、DataTransferLengthにバッファサイズ +(制御が返った後は戻り値データサイズ)、SrbStatusにステータスがあります。 +②上記NP2STOR_INVOKEINFO構造体の仮想メモリアドレスをI/Oポート7EAhへ書き込み、 +I/Oポート7EBhに0x98→0x01の順で書き込むと猫本体が処理を実行します。 +③渡した構造体のsrb->SrbStatusを見て成否を判断します。 +SCSIOP_WRITE時の返事がSRB_STATUS_BUSYの場合は何も考えずにリトライでOKです。 -yӎzL̃͑SĔy[Wv[ɊmۂĂB -n̈悪y[WAEgĂƐȂƎv܂B -܂Ay[WOԂ̏ꍇ͕AhXnĂB +【注意事項】上記のメモリは全て非ページプールに確保してください。 +渡したメモリ領域がページアウトしていると正しく動かないと思います。 +また、ページング無効状態の場合は物理メモリアドレスを渡してください。 -XV -2025/07/04 ver.1.0 -2025/07/22 ver.1.1 Windows 9xnɑΉ +●更新履歴 +2025/07/04 ver.1.0 初版 +2025/07/22 ver.1.1 Windows 9x系に対応 ------------------------ -Neko Project 21/W J +Neko Project 21/W 開発者 SimK diff --git a/np2tool/npstor/wnt/npstor.c b/np2tool/npstor/wnt/npstor.c index f2710b02..83280517 100644 --- a/np2tool/npstor/wnt/npstor.c +++ b/np2tool/npstor/wnt/npstor.c @@ -35,7 +35,7 @@ BOOLEAN HwStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb); BOOLEAN HwResetBus(PVOID DeviceExtension, ULONG PathId); BOOLEAN HwInterrupt(PVOID DeviceExtension); -KSPIN_LOCK g_spinLock; // I/O̔rbNp +KSPIN_LOCK g_spinLock; // I/Oの排他ロック用 ULONG DriverEntry(PVOID DriverObject, PVOID RegistryPath) { HW_INITIALIZATION_DATA hwInit = {0}; @@ -43,12 +43,12 @@ ULONG DriverEntry(PVOID DriverObject, PVOID RegistryPath) { CHAR deviceId[] = "SCSI\\NP2_____FASTSTORAGE_____1.00"; ULONG status; - // ΉȈՃ`FbN + // 対応かを簡易チェック if(READ_PORT_UCHAR((PUCHAR)NPSTOR_IO_ADDR) != 98 || READ_PORT_UCHAR((PUCHAR)NPSTOR_IO_CMD) != 21){ return STATUS_NO_SUCH_DEVICE; } - // rbN@݂̂Ŕj͂Ȃ + // 排他ロック初期化 初期化のみで破棄処理はいらない KeInitializeSpinLock(&g_spinLock); //DbgPrint("DriverEntry\n"); @@ -102,7 +102,7 @@ ULONG HwFindAdapter(PVOID DeviceExtension, PVOID Context, (*ConfigInfo->AccessRanges)[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x7EA); (*ConfigInfo->AccessRanges)[0].RangeLength = 2; - (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE; // FALSE=I/O|[g + (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE; // FALSE=I/Oポート *Again = FALSE; @@ -125,9 +125,9 @@ BOOLEAN HwStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb) { Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; - // ˂[{̂ɏϔC - // f[^i[̉zAhXI/O|[gNPSTOR_IO_ADDR֏݁A - // NPSTOR_IO_CMD0x980x01̏ŏނƔL{̂sB + // ねこー本体に処理を委任する + // データ格納先の仮想メモリアドレスをI/OポートNPSTOR_IO_ADDRへ書き込み、 + // NPSTOR_IO_CMDに0x98→0x01の順で書き込むと猫本体が処理を実行する。 invokeInfo.version = 1; invokeInfo.cmd = 0; invokeInfo.srbAddr = Srb; diff --git a/np2tool/npsysprt/npcngclk.c b/np2tool/npsysprt/npcngclk.c index 6b9a38e5..cd1a3302 100644 --- a/np2tool/npsysprt/npcngclk.c +++ b/np2tool/npsysprt/npcngclk.c @@ -10,44 +10,44 @@ int main(int argc, char const *argv[]) DWORD returned; int clockMul = 0; - printf("Neko Project II ICPUNbNύXc[\n"); + printf("Neko Project II 動的CPUクロック変更ツール\n"); if(argc > 1) { clockMul = atoi(argv[1]); if(clockMul <= 0 || 255 < clockMul) { - printf("NbN{ %d ͎w”\͈͊OłB\n", clockMul); + printf("クロック倍率 %d は指定可能範囲外です。\n", clockMul); return 1; } } else { - printf("usage: %s \n", argv[0]); + printf("usage: %s \n", argv[0]); } hDevice = CreateFile("\\\\.\\NP2SystemPort", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hDevice == INVALID_HANDLE_VALUE) { - printf("hCoɐڑł܂B\n"); + printf("ドライバに接続できません。\n"); return 1; } if(argc > 1) { DeviceIoControl(hDevice, IOCTL_NP2_CLOCK_READ, &data, sizeof(data), &data, sizeof(data), &returned, NULL); - printf("̃NbN{ = %d\n", data.clockMul); + printf("元のクロック倍率 = %d\n", data.clockMul); data.clockMul = clockMul; DeviceIoControl(hDevice, IOCTL_NP2_CLOCK_WRITE, &data, sizeof(data), NULL, 0, &returned, NULL); - printf("NbN{%dɐݒ肵܂B\n", data.clockMul); + printf("クロック倍率を%dに設定しました。\n", data.clockMul); DeviceIoControl(hDevice, IOCTL_NP2_CLOCK_READ, &data, sizeof(data), &data, sizeof(data), &returned, NULL); - printf("݂̃NbN{ = %d\n", data.clockMul); + printf("現在のクロック倍率 = %d\n", data.clockMul); } else { DeviceIoControl(hDevice, IOCTL_NP2_CLOCK_READ, &data, sizeof(data), &data, sizeof(data), &returned, NULL); - printf("݂̃NbN{ = %d\n", data.clockMul); + printf("現在のクロック倍率 = %d\n", data.clockMul); } CloseHandle(hDevice); diff --git a/np2tool/npsysprt/npgetpos.c b/np2tool/npsysprt/npgetpos.c index 69cb9c06..3fe35c80 100644 --- a/np2tool/npsysprt/npgetpos.c +++ b/np2tool/npsysprt/npgetpos.c @@ -12,22 +12,22 @@ int main(int argc, char const *argv[]) DWORD returned; int clockMul = 0; - printf("Neko Project II }EX΍Wǂݎ\n"); + printf("Neko Project II マウス絶対座標読み取り\n"); hDevice = CreateFile("\\\\.\\NP2SystemPort", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hDevice == INVALID_HANDLE_VALUE) { - printf("hCoɐڑł܂B\n"); + printf("ドライバに接続できません。\n"); return 1; } if(DeviceIoControl(hDevice, IOCTL_NP2_MOUSEPOS_READ, &data, sizeof(data), &data, sizeof(data), &returned, NULL)){ int scrWidth = GetSystemMetrics(SM_CXSCREEN); int scrHeight = GetSystemMetrics(SM_CYSCREEN); - printf("΃}EXWi̒lj= (%d, %d)\n", data.absPosX, data.absPosY); - printf("΃}EXWipixelj= (%d, %d)\n", (ULONG)data.absPosX * scrWidth / 65536, (ULONG)data.absPosY * scrHeight / 65536); + printf("絶対マウス座標(生の値)= (%d, %d)\n", data.absPosX, data.absPosY); + printf("絶対マウス座標(pixel)= (%d, %d)\n", (ULONG)data.absPosX * scrWidth / 65536, (ULONG)data.absPosY * scrHeight / 65536); }else{ - printf("}EXW擾ł܂łB"); + printf("マウス座標情報を取得できませんでした。"); } CloseHandle(hDevice); diff --git a/np2tool/npsysprt/npsyscmd.c b/np2tool/npsysprt/npsyscmd.c index 12699c32..6773a9e5 100644 --- a/np2tool/npsysprt/npsyscmd.c +++ b/np2tool/npsysprt/npsyscmd.c @@ -12,51 +12,51 @@ int main(int argc, char const *argv[]) IOPORT_NP2_SIMPLE_DATA data = {0}; HANDLE hDevice; - // ̏ + // 引数の処理 if(argc <= 1) { - printf("Neko Project II VXe|[g ANZXc[\n"); - printf("usage: %s [p[^lbyte1] [byte2] [byte3] [byte4] \n", argv[0]); + printf("Neko Project II システムポート アクセスツール\n"); + printf("usage: %s <コマンド> [パラメータ値byte1] [byte2] [byte3] [byte4] \n", argv[0]); return 1; } cmdLength = strlen(argv[1]); if(cmdLength > 16) { - printf("Error: R}h16܂łłB\n"); + printf("Error: コマンドは16文字までです。\n"); return 1; } data.paramLength = argc - 2; if(data.paramLength > 4) { - printf("Error: p[^l4byte܂łłB\n"); + printf("Error: パラメータ値は4byteまでです。\n"); return 1; } - // p[^Zbg + // パラメータセット memcpy(data.command, argv[1], cmdLength); for(i=0;iIoStatus.Information = 0; // 0 + Irp->IoStatus.Information = 0; // 仮で0 switch (irpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_NP2_GENERIC: @@ -94,7 +94,7 @@ NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) ULONG commandLen, paramLen, readBufferLen; UCHAR *command, *param, *readBuffer; - // obt@ʒuǂݎ@ُȂG[ɂ + // バッファ位置を読み取る 異常ならエラーにする if(bufferLen < 4) { status = STATUS_BUFFER_TOO_SMALL; break; @@ -121,14 +121,14 @@ NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) break; } - // |[gANZXs + // ポートアクセス実行 status = SendNP2SystemPortData((CHAR*)command, commandLen, param, paramLen, readBuffer, &readBufferLen); if(status != STATUS_SUCCESS) { break; } - // ߂f[^̃TCY + // 戻すデータのサイズ Irp->IoStatus.Information = bufferLen; break; @@ -140,12 +140,12 @@ NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) ULONG commandLen, paramLen, readBufferLen; UCHAR *command, *param, *readBuffer; - // obt@ʒuǂݎ@ُȂG[ɂ + // バッファ位置を読み取る 異常ならエラーにする if(bufferLen != sizeof(IOPORT_NP2_SIMPLE_DATA)) { status = STATUS_BUFFER_TOO_SMALL; break; } - for(commandLen=0;commandLencommand[commandLen] == '\0') break; } if(commandLen == 0) { @@ -162,14 +162,14 @@ NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) readBufferLen = NP2_READ_MAXLEN; readBuffer = data->readBuffer; - // |[gANZXs + // ポートアクセス実行 status = SendNP2SystemPortData((CHAR*)command, commandLen, param, paramLen, readBuffer, &readBufferLen); if(status != STATUS_SUCCESS) { break; } - // ߂f[^̃TCY + // 戻すデータのサイズ Irp->IoStatus.Information = bufferLen; break; @@ -235,7 +235,7 @@ BOOLEAN SendNP2Check() char commandText[] = NP2_COMMAND_NP2CHECK; KIRQL oldIrql; - // r̈Jn + // 排他領域開始 KeAcquireSpinLock(&g_IOSpinLock, &oldIrql); for(i=0;i= 10) break; @@ -296,7 +296,7 @@ ULONG SendNP2GetClock() clockMul += (tmp - '0') % 10; } - // r̈I + // 排他領域終了 KeReleaseSpinLock(&g_IOSpinLock, oldIrql); return clockMul; @@ -310,33 +310,33 @@ ULONG SendNP2GetMousePos(PUSHORT x, PUSHORT y) if(!x || !y) return 0; - // r̈Jn + // 排他領域開始 KeAcquireSpinLock(&g_IOSpinLock, &oldIrql); - // ÂR}hsʂΑ| + // 古いコマンド実行結果があれば掃除 for(i=0;i 4) { return STATUS_INVALID_PARAMETER; } - // p[^obt@w肵Ă̂NULL|C^ȂG[ + // パラメータバッファ長さを指定しているのにNULLポインタならエラー if(paramBufferLen > 0 && !lpParamBuffer) return STATUS_INVALID_PARAMETER; - // ǂݎobt@w肵Ă̂NULL|C^ȂG[ + // 読み取りバッファ長さを指定しているのにNULLポインタならエラー if(lpReadBufferLen && *lpReadBufferLen > 0 && !lpReadBuffer) return STATUS_INVALID_PARAMETER; - // r̈Jn + // 排他領域開始 KeAcquireSpinLock(&g_IOSpinLock, &oldIrql); - // ÂR}hsʂΑ| + // 古いコマンド実行結果があれば掃除 for(i=0;i -ŁAICPUNbN{ς܂B̕ύXEmulateResetŌɖ߂܂B +●使い方 +npcngclk.exeはNeko Project 21/Wの動的CPUクロック変更のためのツールです。 +npcngclk <変更したいクロック倍率> +で、動的にCPUクロック倍率が変わります。この変更はEmulate→Resetで元に戻ります。 -npsyscmd.exeNeko Project IĨVXe|[gɔCӂ̃R}h𑗐Młc[łB -npsyscmd [byte1] [byte2] [byte3] [byte4] -őMł܂BȂłĂ܂̂ŗvӁiႦpoweroffƂ𑗂np2I܂jB +npsyscmd.exeはNeko Project IIのシステムポートに任意のコマンドを送信できるツールです。 +npsyscmd <コマンド> [引数byte1] [引数byte2] [引数byte3] [引数byte4] +で送信できます。なんでも送れてしまうので要注意(例えばpoweroffとかを送るとnp2が終了します)。 -Ⴆ΁A +例えば、 npsyscmd NP2 -sƁANP2ƕԂĂ܂B +を実行すると、NP2と返ってきます。 -MłR}hNeko Project IĨ\[XR[hȉ̃y[WɋLڂ܂B +送信できるコマンドはNeko Project IIのソースコードや以下のページに記載があります。 https://simk98.github.io/np21w/docs/npcngcfg.html -npgetpos.exeNeko Project 21/Wɂă}EX΍WǂݎeXgc[łB -Ώۃo[WNeko Project 21/W rev94 beta11ȍ~łBΉĂȂꍇ̓G[ɂȂ܂B +npgetpos.exeはNeko Project 21/Wにおいてマウス絶対座標を読み取るテストツールです。 +対象バージョンはNeko Project 21/W rev94 beta11以降です。対応していない場合はエラーになります。 npgetpos -ŁA}EX΍W擾ł܂B -̒liX,YƂ0`65535Ń}bvꂽljƃXN[WɊZꂽl\܂B +で、マウス絶対座標を取得できます。 +生の値(X,Yともに0~65535でマップされた値)とスクリーン座標に換算された値を表示します。 -\[XR[h -np21/w\[Xnp2tool\npsysprtɃ\[XR[h܂B -L{̂ƓCBSDCZXƂ܂AIɎRɎgĂđvłB -ςȂĂȂ؂\肷Ȃ莩RɂĂB +●ソースコード +np21/wソースのnp2tool\npsysprtにソースコードがあります。 +いちおう猫本体と同じ修正BSDライセンスとしますが、実質的に自由に使っていただいて大丈夫です。 +煮るなり焼くなり切り貼りするなり自由にしてください。 ------------------------ -Neko Project 21/W J +Neko Project 21/W 開発者 SimK diff --git a/np2ver.h b/np2ver.h old mode 100755 new mode 100644 index e5c31b74..87271b5b --- a/np2ver.h +++ b/np2ver.h @@ -1,11 +1,11 @@ -/** - * @file np2ver.h - * @brief The version - */ - -#if defined(SUPPORT_IA32_HAXM) -#define NP2VER_CORE "HAXM 0.86" -#else -#define NP2VER_CORE "0.86" -#endif - +/** + * @file np2ver.h + * @brief The version + */ + +#if defined(SUPPORT_IA32_HAXM) +#define NP2VER_CORE "HAXM 0.86" +#else +#define NP2VER_CORE "0.86" +#endif + diff --git a/pccore.c b/pccore.c index b1619893..b2bb521c 100644 --- a/pccore.c +++ b/pccore.c @@ -1,1936 +1,1936 @@ -/** - * @file pccore.c - * @brief emluration core - * - * @author $Author: yui $ - * @date $Date: 2011/02/23 10:11:44 $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_SMPU98) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_VIDEOFILTER) -#include -#endif -#include -#include -#ifdef SUPPORT_SOUND_SB16 -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_HOSTDRV) -#include -#endif -#if defined(SUPPORT_HOSTDRVNT) -#include -#endif -#include -#include -#include -#include -#include -#if defined(SUPPORT_WAB) -#include -#endif -#if defined(SUPPORT_CL_GD5430) -#include -#endif -#if defined(SUPPORT_IDEIO) -#include -#include -#endif -#if defined(SUPPORT_GPIB) -#include -#endif -#if defined(CPUCORE_IA32) -#include -#include -#else -#define CPU_VENDOR "GenuineIntel" -#define CPU_FAMILY 2 -#define CPU_MODEL 1 -#define CPU_STEPPING 1 -#define CPU_FEATURES (0) -#define CPU_FEATURES_EX (0) -#define CPU_BRAND_STRING "Intel(R) 80286 Processor " -#define CPU_FEATURES_ECX (0) -#define CPU_FEATURES_EX_ECX (0) -#define CPU_BRAND_ID_AUTO (0xffffffff) -#define CPU_EFLAGS_MASK (0) -#endif -#if defined(SUPPORT_IA32_HAXM) -#if !defined(SUPPORT_NP2_TICKCOUNT) -#error HAXM need NP2_TickCount -#endif -#include -#include -#include -#include -#endif -#include - - -const OEMCHAR np2version[] = OEMTEXT(NP2KAI_GIT_TAG " " NP2KAI_GIT_HASH); - -#if defined(_WIN32_WCE) -#define PCBASEMULTIPLE 2 -#else -#define PCBASEMULTIPLE 20 -#endif - - - NP2CFG np2cfg = { - 0, 1, 0, 32, 0, 0, 0x40, - 0, 0, 0, 0, - {0x3e, 0xe3, 0x7b}, 0, - 0, 0, {1, 1, 6, 1, 8, 1}, - 128, 0x00, 1, -#if defined(SUPPORT_ASYNC_CPU) - 0, 0, -#endif - 1, -#if defined(SUPPORT_IDEIO) - 0xD8, -#endif - - OEMTEXT("VX"), PCBASECLOCK25, PCBASEMULTIPLE, 1, - {0x48, 0x05, 0x04, 0x08, 0x01, 0x00, 0x00, 0x6e}, - 1, 13, 2, 1, 0x000000, 0xffffff, - 44100, 150, 4, 0, - {0, 0, 0}, 0xd1, 0x7f, 0xd1, 0, 0, 1, - - 0x0188, 0x80, 3, 12, 12, 0xff, 0, // 118 - - 0x70, 1, 3, // Mate-X PCM - -#if defined(SUPPORT_SOUND_SB16) - 0xd2, 3, 5, 0, -#endif /* SUPPORT_SOUND_SB16 */ - -#if defined(SUPPORT_FMGEN) - 3, {0x0c, 0x0c, 0x08, 0x06, 0x03, 0x0c}, 100, 64, 64, 64, 64, 64, 128, -#else /* SUPPORT_FMGEN */ - 3, {0x0c, 0x0c, 0x08, 0x06, 0x03, 0x0c}, 100, 64, 64, 64, 64, 64, -#endif /* SUPPORT_FMGEN */ - 1, 0x82, 0, -#if defined(SUPPORT_SMPU98) - 0, 0x82, 0, -#endif /* SUPPORT_SMPU98 */ - 0, {0x17, 0x04, 0x17}, {0x0c, 0x0c, 0x02, 0x10, 0x3f, 0x3f}, -#if defined(SUPPORT_FMGEN) - 1, -#endif /* SUPPORT_FMGEN */ - 3, 0, 50, 0, 0, 1, 0, - - 0, {OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT("")}, -#if defined(SUPPORT_IDEIO) - {OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT("")}, - {SXSIDEV_HDD, SXSIDEV_HDD, SXSIDEV_CDROM, SXSIDEV_HDD}, - {OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT("")}, - 1, 1, 0, 0, 0, 0, 0, 0, 0, -#else - {OEMTEXT(""), OEMTEXT("")}, -#endif -#if defined(SUPPORT_SCSI) - {OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT("")}, -#endif - OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), -#if defined(SUPPORT_NET) - OEMTEXT(""), 0, -#endif -#if defined(SUPPORT_LGY98) - 0, 0x10D0, 5, {0x00, 0x40, 0x26, 0x12, 0x34, 0x56}, -#endif -#if defined(SUPPORT_WAB) -#if defined(__LIBRETRO__) - 1, -#else - 0, -#endif -#endif -#if defined(SUPPORT_CL_GD5430) - 0, 0x5B, 0, CIRRUS_MELCOWAB_OFS_DEFAULT, 0, -#endif -#if defined(SUPPORT_VGA_MODEX) - 0, -#endif -#if defined(SUPPORT_GPIB) - 0, 12, 1, 0, 0, -#endif -#if defined(SUPPORT_PCI) - 0, 0, 0, -#endif -#if defined(SUPPORT_STATSAVE) - 0, /* statsave */ -#endif - 0, 0, - 0, 0xff00, - 0, 0, 0, - 1, - CPU_VENDOR, CPU_FAMILY, CPU_MODEL, CPU_STEPPING, CPU_FEATURES, CPU_FEATURES_EX, CPU_BRAND_STRING, OEMTEXT(""), OEMTEXT(""), CPU_BRAND_ID_AUTO, CPU_FEATURES_ECX, CPU_EFLAGS_MASK, CPU_FEATURES_EX_ECX, - FPU_TYPE_SOFTFLOAT, -#if defined(SUPPORT_FAST_MEMORYCHECK) - 1, -#endif - 0, 0, - 1, 0, -#if defined(SUPPORT_GAMEPORT) - 0, 0, -#endif - 0, 0, 0, 0, - 0, -#if defined(SUPPORT_NP2SCSI) - 1, -#endif - 100, - OEMTEXT(""), - 0, - 0, - 0, -#if defined(SUPPORT_DEBUGSS) - 0, -#endif -#if defined(SUPPORT_VIDEOFILTER) - 0, 0, 3, 0, - {{3, 2}, {3, 2}, {3, 2}}, - { - {{1, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}}, - {{1, 2, 6, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}}, - {{1, 3, 8, 0, 0, 255, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}}, - }, -#endif - 0, 500, 50, - }; - - PCCORE pccore = { PCBASECLOCK25, PCBASEMULTIPLE, - 0, PCMODEL_VX, 0, 0, {0x3e, 0xe3, 0x7b}, 0, - SOUNDID_NONE, 0, - PCBASECLOCK25 * PCBASEMULTIPLE}; - PCSTAT pcstat = {3, TRUE, FALSE, FALSE}; - -// UINT8 screenupdate = 3; -// int screendispflag = 1; - UINT8 soundrenewal = 0; -// BOOL drawframe; - UINT drawcount = 0; -// BOOL hardwarereset = FALSE; -#if defined(SUPPORT_FMGEN) - UINT8 enable_fmgen = 0; -#endif /* SUPPORT_FMGEN */ - -#ifdef SUPPORT_ASYNC_CPU -int asynccpu_lateflag = 0; -int asynccpu_fastflag = 0; -LARGE_INTEGER asynccpu_lastclock = {0}; -LARGE_INTEGER asynccpu_clockpersec = {0}; -LARGE_INTEGER asynccpu_clockcount = {0}; -#endif - -// --------------------------------------------------------------------------- - -void getbiospath(OEMCHAR *path, const OEMCHAR *fname, int maxlen) { - -const OEMCHAR *p; - - p = np2cfg.biospath; - if (p[0]) { - file_cpyname(path, p, maxlen); - file_setseparator(path, maxlen); - file_catname(path, fname, maxlen); - } - else { - file_cpyname(path, file_getcd(fname), maxlen); - } -} - - -// ---- - -static void pccore_set(const NP2CFG *pConfig) -{ - UINT8 model; - UINT32 multiple; -#if defined(SUPPORT_LARGE_MEMORY) - UINT16 extsize; -#else - UINT8 extsize; -#endif - - ZeroMemory(&pccore, sizeof(pccore)); - model = PCMODEL_VX; - if (!milstr_cmp(pConfig->model, str_VM)) { - model = PCMODEL_VM; - } - else if (!milstr_cmp(pConfig->model, str_EPSON)) { - model = PCMODEL_EPSON | PCMODEL_VM; - } - pccore.model = model; - - CPU_TYPE = 0; - if (pConfig->dipsw[2] & 0x80) { - CPU_TYPE = CPUTYPE_V30; - } - - if (np2cfg.baseclock >= ((PCBASECLOCK25 + PCBASECLOCK20) / 2)) - { - pccore.baseclock = PCBASECLOCK25; // 2.5MHz - pccore.cpumode = 0; - } - else - { - pccore.baseclock = PCBASECLOCK20; // 2.0MHz - pccore.cpumode = CPUMODE_8MHZ; - } - multiple = pConfig->multiple; - if (multiple == 0) - { - multiple = 1; - } - else if (multiple > 2048) - { - multiple = 2048; - } - pccore.multiple = multiple; - pccore.maxmultiple = pccore.multiple; - pccore.realclock = pccore.baseclock * multiple; - - // HDDの接続 (I/Oの使用状態が変わるので.. - if (pConfig->dipsw[1] & 0x20) - { - pccore.hddif |= PCHDD_IDE; -#if defined(SUPPORT_IDEIO) - sxsi_setdevtype(0x00, np2cfg.idetype[0]==SXSIDEV_CDROM ? SXSIDEV_CDROM : SXSIDEV_NC); - sxsi_setdevtype(0x01, np2cfg.idetype[1]==SXSIDEV_CDROM ? SXSIDEV_CDROM : SXSIDEV_NC); - sxsi_setdevtype(0x02, np2cfg.idetype[2]==SXSIDEV_CDROM ? SXSIDEV_CDROM : SXSIDEV_NC); - sxsi_setdevtype(0x03, np2cfg.idetype[3]==SXSIDEV_CDROM ? SXSIDEV_CDROM : SXSIDEV_NC); -#endif - } - else - { - sxsi_setdevtype(0x02, SXSIDEV_NC); - sxsi_setdevtype(0x03, SXSIDEV_NC); - } - - // 拡張メモリ - extsize = 0; - if (!(pConfig->dipsw[2] & 0x80)) - { - extsize = np2cfg.EXTMEM; -#if defined(CPUCORE_IA32) - extsize = MIN(extsize, MEMORY_MAXSIZE); -#else - extsize = MIN(extsize, 13); -#endif - } - pccore.extmem = extsize; - CopyMemory(pccore.dipsw, pConfig->dipsw, 3); - - // サウンドボードの接続 - pccore.sound = (SOUNDID)pConfig->SOUND_SW; - - // その他CBUSの接続 - pccore.device = 0; - if (pConfig->pc9861enable) - { - pccore.device |= PCCBUS_PC9861K; - } -#if defined(SUPPORT_SMPU98) - if (pConfig->smpuenable) - { - pccore.device |= PCCBUS_SMPU98; - } - else -#endif - if (pConfig->mpuenable) - { - pccore.device |= PCCBUS_MPU98; - } -} - - -// -------------------------------------------------------------------------- - -#if !defined(DISABLE_SOUND) -static void sound_init(void) -{ - UINT rate; - - rate = np2cfg.samplingrate; - if (sound_create(rate, np2cfg.delayms) != SUCCESS) - { - rate = 0; - } - fddmtrsnd_initialize(rate); - wabrlysnd_initialize(rate); - beep_initialize(rate); - beep_setvol(np2cfg.BEEP_VOL); - tms3631_initialize(rate); - tms3631_setvol(np2cfg.vol14); - opngen_initialize(rate); - opngen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); - psggen_initialize(rate); - psggen_setvol(np2cfg.vol_ssg * np2cfg.vol_master / 100); - rhythm_initialize(rate); - rhythm_setvol(np2cfg.vol_rhythm * np2cfg.vol_master / 100); - adpcm_initialize(rate); - adpcm_setvol(np2cfg.vol_adpcm * np2cfg.vol_master / 100); - pcm86gen_initialize(rate); - pcm86gen_setvol(np2cfg.vol_pcm * np2cfg.vol_master / 100); - cs4231_initialize(rate); -#ifdef SUPPORT_SOUND_SB16 - ct1741_initialize(rate); -#endif - amd98_initialize(rate); - oplgen_initialize(rate); - oplgen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); -} - -static void sound_term(void) { - - soundmng_stop(); - amd98_deinitialize(); - rhythm_deinitialize(); - beep_deinitialize(); - wabrlysnd_deinitialize(); - fddmtrsnd_deinitialize(); - sound_destroy(); -} -#endif - -#if defined(SUPPORT_IA32_HAXM) -int pccore_mem_malloc_virtualalloc = 0; -void pccore_mem_malloc(void) { - if(!mem){ -#if defined(NP2_WIN) - mem = (UINT8*)_aligned_malloc(0x200000, 4096); -#else - mem = (UINT8*)aligned_alloc(4096, 0x200000); -#endif - } - if(!vramex || vramex==vramex_base){ -#if defined(NP2_WIN) - vramex = (UINT8*)_aligned_malloc(0x80000, 4096); -#else - vramex = (UINT8*)aligned_alloc(4096, 0x80000); -#endif - memset(vramex, 0, 0x80000); - } -} -void pccore_mem_free(void) { - if(mem){ -#if defined(NP2_WIN) - _aligned_free(mem); -#else - free(mem); -#endif - mem = NULL; - } - if(vramex && vramex!=vramex_base){ -#if defined(NP2_WIN) - _aligned_free(vramex); -#else - free(vramex); -#endif - vramex = vramex_base; - } -} -#endif - -void pccore_init(void) { - -#if defined(SUPPORT_MULTITHREAD) - nevent_initialize(); - pcm86cs_initialize(); - cs4231cs_initialize(); - ct1741cs_initialize(); -#endif - -#if defined(SUPPORT_IA32_HAXM) - i386hax_check(); - np2hax.enable = 1; - i386hax_initialize(); -#endif - -#if defined(SUPPORT_IA32_HAXM) - pccore_mem_malloc(); -#endif - - CPU_TYPE = 0; - if (np2cfg.dipsw[2] & 0x80) { - CPU_TYPE = CPUTYPE_V30; - } - - CPU_INITIALIZE(); - - pic_initialize(); - -#if defined(SUPPORT_VIDEOFILTER) - { - uint8_t vf_i, vf_j; - - hVFMng1 = VideoFilter_Init(640, 480, 25, 10); - VideoFilterMng_LoadSetting(hVFMng1, np2cfg.vf1_enable, np2cfg.vf1_pcount, np2cfg.vf1_pno); - for(vf_j = 0; vf_j < np2cfg.vf1_pcount; vf_j++) { - VideoFilter_LoadProfile(hVFMng1, vf_j, np2cfg.vf1_profile[vf_j][0], np2cfg.vf1_profile[vf_j][1]); - for(vf_i = 0; vf_i < np2cfg.vf1_profile[vf_j][0]; vf_i++) { - VideoFilter_LoadFilter(hVFMng1, vf_j, vf_i, np2cfg.vf1_param[vf_j][vf_i]); - } - } - } -#endif - pal_initlcdtable(); - pal_makelcdpal(); - pal_makeskiptable(); - dispsync_initialize(); - sxsi_initialize(); - - font_initialize(); - font_load(np2cfg.fontfile, TRUE, np2cfg.fontface); - maketext_initialize(); - makegrph_initialize(); - gdcsub_initialize(); - fddfile_initialize(); - -#if !defined(DISABLE_SOUND) -#if defined(SUPPORT_FMGEN) - enable_fmgen = 0; - if(np2cfg.usefmgen == 1) - enable_fmgen = 1; -#ifdef WIIU - enable_fmgen = 0; -#endif -#endif /* SUPPORT_FMGEN */ - - fmboard_construct(); - sound_init(); -#endif - - rs232c_construct(); - mpu98ii_construct(); -#if defined(SUPPORT_SMPU98) - smpu98_construct(); -#endif - pc9861k_initialize(); - - iocore_create(); - -#if defined(SUPPORT_IDEIO) - ideio_initialize(); -#endif - -#if defined(SUPPORT_HOSTDRV) - hostdrv_initialize(); -#endif - -#if defined(SUPPORT_HOSTDRVNT) - hostdrvNT_initialize(); -#endif - -#if defined(SUPPORT_GPIB) - gpibio_initialize(); -#endif -} - -void pccore_term(void) { - -#if defined(SUPPORT_GPIB) - gpibio_shutdown(); -#endif - -#if defined(SUPPORT_HOSTDRVNT) - hostdrvNT_deinitialize(); -#endif - -#if defined(SUPPORT_HOSTDRV) - hostdrv_deinitialize(); -#endif - -#if !defined(DISABLE_SOUND) - sound_term(); - fmboard_destruct(); -#endif - - fdd_eject(0); - fdd_eject(1); - fdd_eject(2); - fdd_eject(3); - -#if defined(SUPPORT_IDEIO) - ideio_deinitialize(); -#endif - - iocore_destroy(); - - pc9861k_deinitialize(); -#if defined(SUPPORT_SMPU98) - smpu98_destruct(); -#endif - mpu98ii_destruct(); - rs232c_destruct(); - - printif_finalize(); - - hook_fontrom_flush(); - hook_fontrom_defdisable(); - - sxsi_alltrash(); - -#if defined(SUPPORT_VIDEOFILTER) - { - uint8_t vf_i, vf_j; - - VideoFilterMng_SaveSetting(hVFMng1, &np2cfg.vf1_enable, &np2cfg.vf1_pcount, &np2cfg.vf1_pno); - for(vf_j = 0; vf_j < np2cfg.vf1_pcount; vf_j++) { - VideoFilter_SaveProfile(hVFMng1, &np2cfg.vf1_profile[vf_j][0], &np2cfg.vf1_profile[vf_j][1], vf_j); - for(vf_i = 0; vf_i < np2cfg.vf1_profile[vf_j][0]; vf_i++) { - VideoFilter_SaveFilter(hVFMng1, np2cfg.vf1_param[vf_j][vf_i], vf_j, vf_i); - } - } - VideoFilter_Deinit(hVFMng1); - } -#endif - - pic_deinitialize(); - - CPU_SETEXTSIZE(0); // メモリ解放 - CPU_DEINITIALIZE(); - -#if defined(SUPPORT_IA32_HAXM) - i386hax_deinitialize(); -#endif - -#if defined(SUPPORT_IA32_HAXM) - pccore_mem_free(); -#endif - -#if defined(SUPPORT_MULTITHREAD) - pcm86cs_shutdown(); - cs4231cs_shutdown(); - ct1741cs_shutdown(); - nevent_shutdown(); -#endif -} - - -void pccore_cfgupdate(void) { - - BOOL renewal; - int i; - - renewal = FALSE; - for (i=0; i<8; i++) - { - if (np2cfg.memsw[i] != mem[MEMX_MSW + i*4]) - { - np2cfg.memsw[i] = mem[MEMX_MSW + i*4]; - renewal = TRUE; - } - } - for (i=0; i<3; i++) - { - if (np2cfg.dipsw[i] != pccore.dipsw[i]) - { - np2cfg.dipsw[i] = pccore.dipsw[i]; - renewal = TRUE; - } - } - if (renewal) { - sysmng_update(SYS_UPDATECFG); - } -} - -/** - * Reset the virtual machine - */ -void pccore_reset(void) { - - int i; - BOOL epson; - -#if defined(SUPPORT_IA32_HAXM) - if(np2hax.enable){ - i386hax_createVM(); - i386hax_resetVMCPU(); - } -#endif - - soundmng_stop(); -#if !defined(DISABLE_SOUND) -#if defined(SUPPORT_FMGEN) - enable_fmgen = 0; - if(np2cfg.usefmgen == 1) - enable_fmgen = 1; -#ifdef WIIU - enable_fmgen = 0; -#endif -#endif /* SUPPORT_FMGEN */ - - if (soundrenewal) { - soundrenewal = 0; - sound_term(); - sound_init(); - } -#endif - ZeroMemory(mem, 0x110000); - FillMemory(mem + 0xC0000, 0xE8000 - 0xC0000, 0xff); // なぞ - ZeroMemory(mem + VRAM1_B, 0x18000); - ZeroMemory(mem + VRAM1_E, 0x08000); - ZeroMemory(mem + FONT_ADRS, 0x08000); - - //メモリスイッチ - for (i=0; i<8; i++) - { - mem[0xa3fe2 + i*4] = np2cfg.memsw[i]; - } - -#if defined(CPUCORE_IA32) - if(np2cfg.cpu_family == CPU_80386_FAMILY && np2cfg.cpu_model == CPU_80386_MODEL){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_80386); - }else if(np2cfg.cpu_family == CPU_I486SX_FAMILY && np2cfg.cpu_model == CPU_I486SX_MODEL){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_I486SX); - }else if(np2cfg.cpu_family == CPU_I486DX_FAMILY && np2cfg.cpu_model == CPU_I486DX_MODEL){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_I486DX); - }else if(np2cfg.cpu_family == CPU_PENTIUM_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM); - }else if(np2cfg.cpu_family == CPU_MMX_PENTIUM_FAMILY && np2cfg.cpu_model == CPU_MMX_PENTIUM_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_MMX_PENTIUM); - }else if(np2cfg.cpu_family == CPU_PENTIUM_PRO_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_PRO_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_PRO); - }else if(np2cfg.cpu_family == CPU_PENTIUM_II_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_II_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_II); - }else if(np2cfg.cpu_family == CPU_PENTIUM_III_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_III_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_III); - }else if(np2cfg.cpu_family == CPU_PENTIUM_M_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_M_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_M); - }else if(np2cfg.cpu_family == CPU_PENTIUM_4_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_4_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_4); - }else if(np2cfg.cpu_family == CPU_CORE_2_DUO_FAMILY && np2cfg.cpu_model == CPU_CORE_2_DUO_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_CORE_2_DUO); - }else if(np2cfg.cpu_family == CPU_CORE_2_DUOW_FAMILY && np2cfg.cpu_model == CPU_CORE_2_DUOW_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_CORE_2_DUOW); - }else if(np2cfg.cpu_family == CPU_CORE_I_FAMILY && np2cfg.cpu_model == CPU_CORE_I_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_CORE_I); - - }else if(np2cfg.cpu_family == CPU_AMD_K6_2_FAMILY && np2cfg.cpu_model == CPU_AMD_K6_2_MODEL){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K6_2); - }else if(np2cfg.cpu_family == CPU_AMD_K6_III_FAMILY && np2cfg.cpu_model == CPU_AMD_K6_III_MODEL){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K6_III); - }else if(np2cfg.cpu_family == CPU_AMD_K7_ATHLON_FAMILY && np2cfg.cpu_model == CPU_AMD_K7_ATHLON_MODEL){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K7_ATHLON); - }else if(np2cfg.cpu_family == CPU_AMD_K7_ATHLON_XP_FAMILY && np2cfg.cpu_model == CPU_AMD_K7_ATHLON_XP_MODEL){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K7_ATHLON_XP); - }else if(np2cfg.cpu_family == CPU_AMD_K8_ATHLON_64_FAMILY && np2cfg.cpu_model == CPU_AMD_K8_ATHLON_64_MODEL){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K8_ATHLON_64); - }else if(np2cfg.cpu_family == CPU_AMD_K8_ATHLON_64X2_FAMILY && np2cfg.cpu_model == CPU_AMD_K8_ATHLON_64X2_MODEL){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K8_ATHLON_64X2); - }else if(np2cfg.cpu_family == CPU_AMD_K10_PHENOM_FAMILY && np2cfg.cpu_model == CPU_AMD_K10_PHENOM_MODEL){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K10_PHENOM); - - }else if(np2cfg.cpu_family == 0 && np2cfg.cpu_model == 0 && np2cfg.cpu_stepping == 0 && np2cfg.cpu_feature == 0){ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_NEKOPRO); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_NEKOPRO2); - }else{ - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_NEKOPRO); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_NEKOPRO); - } -#if defined(CPUCORE_IA32) - if(strlen(np2cfg.cpu_vendor_o)!=0){ - memset(np2cfg.cpu_vendor, 0, 12); - strcpy(np2cfg.cpu_vendor, np2cfg.cpu_vendor_o); - // 字数が足りない時スペースで埋める - for(i=0;i<12;i++){ - if(np2cfg.cpu_vendor[i] == '\0'){ - np2cfg.cpu_vendor[i] = ' '; - } - } - np2cfg.cpu_vendor[12] = '\0'; - } - if(strlen(np2cfg.cpu_brandstring_o)!=0){ - memset(np2cfg.cpu_brandstring, 0, 48); - strcpy(np2cfg.cpu_brandstring, np2cfg.cpu_brandstring_o); - // 最後に1文字スペースを入れる - strcat(np2cfg.cpu_brandstring, " "); - } -#endif - strcpy(i386cpuid.cpu_vendor, np2cfg.cpu_vendor); - if(np2cfg.cpu_family == 0 && np2cfg.cpu_model == 0 && np2cfg.cpu_stepping == 0 && np2cfg.cpu_feature == 0 && np2cfg.cpu_feature_ex == 0){ - // 設定に関係なく全部使えるようにする - i386cpuid.cpu_family = CPU_FAMILY; - i386cpuid.cpu_model = CPU_MODEL; - i386cpuid.cpu_stepping = CPU_STEPPING; - i386cpuid.cpu_feature = CPU_FEATURES_ALL; - i386cpuid.cpu_feature_ex = CPU_FEATURES_EX_ALL; - i386cpuid.cpu_feature_ecx = CPU_FEATURES_ECX_ALL; - i386cpuid.cpu_feature_ex_ecx = CPU_FEATURES_EX_ECX_ALL; - i386cpuid.cpu_eflags_mask = 0; - i386cpuid.cpu_brandid = 0; - }else{ - i386cpuid.cpu_family = np2cfg.cpu_family; - i386cpuid.cpu_model = np2cfg.cpu_model; - i386cpuid.cpu_stepping = np2cfg.cpu_stepping; - i386cpuid.cpu_feature = CPU_FEATURES_ALL & np2cfg.cpu_feature; - i386cpuid.cpu_feature_ex = CPU_FEATURES_EX_ALL & np2cfg.cpu_feature_ex; - i386cpuid.cpu_feature_ecx = CPU_FEATURES_ECX_ALL & np2cfg.cpu_feature_ecx; - i386cpuid.cpu_feature_ex_ecx = CPU_FEATURES_EX_ECX_ALL & np2cfg.cpu_feature_ex_ecx; - i386cpuid.cpu_eflags_mask = (AC_FLAG) & np2cfg.cpu_eflags_mask; - i386cpuid.cpu_brandid = np2cfg.cpu_brandid; - } - strcpy(i386cpuid.cpu_brandstring, np2cfg.cpu_brandstring); - - // BrandID自動設定(過去バージョンとの互換維持用) - if(i386cpuid.cpu_brandid == CPU_BRAND_ID_AUTO){ - if(strncmp(i386cpuid.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_III, 27)==0){ - CPU_EBX = 0x2; - }else if(strncmp(i386cpuid.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_M, 27)==0){ - CPU_EBX = 0x16; - }else if(strncmp(i386cpuid.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_4, 27)==0){ - CPU_EBX = 0x9; - }else{ - CPU_EBX = 0; - } - } - - // mov cs,xx許可フラグ - i386cpuid.allow_movCS = np2cfg.allowMOVCS; - - // FPU種類を設定 使えないなら別のタイプへ変更する - i386cpuid.fpu_type = np2cfg.fpu_type; -#if !defined(SUPPORT_FPU_SOFTFLOAT) && !defined(SUPPORT_FPU_SOFTFLOAT3) - if (i386cpuid.fpu_type == FPU_TYPE_SOFTFLOAT) { - i386cpuid.fpu_type = FPU_TYPE_DOSBOX2; - } -#elif !defined(SUPPORT_FPU_DOSBOX2) - if (i386cpuid.fpu_type == FPU_TYPE_DOSBOX2) { -#if defined(SUPPORT_FPU_SOFTFLOAT) || defined(SUPPORT_FPU_SOFTFLOAT3) - i386cpuid.fpu_type = FPU_TYPE_SOFTFLOAT; -#else - i386cpuid.fpu_type = FPU_TYPE_DOSBOX; -#endif - } -#elif !defined(SUPPORT_FPU_DOSBOX) - if (i386cpuid.fpu_type == FPU_TYPE_DOSBOX) { -#if defined(SUPPORT_FPU_SOFTFLOAT) || defined(SUPPORT_FPU_SOFTFLOAT3) - i386cpuid.fpu_type = FPU_TYPE_SOFTFLOAT; -#else - i386cpuid.fpu_type = FPU_TYPE_DOSBOX2; -#endif - } -#endif - fpu_initialize(1); -#endif - - pccore_set(&np2cfg); -#if defined(SUPPORT_BMS) - bmsio_set(); -#endif - nevent_allreset(); - - CPU_RESET(); - CPU_SETEXTSIZE((UINT32)pccore.extmem); - - epson = (pccore.model & PCMODEL_EPSON) ? TRUE : FALSE; - if (epson || np2cfg.useram_d) { - /* enable RAM (D0000-DFFFF) */ - CPU_RAM_D000 = 0xffff; - } - font_setchargraph(epson); - -#if defined(SUPPORT_IA32_HAXM) - if(np2hax.hVMDevice){ - i386hax_vm_allocmemory(); - } -#endif - - // HDDセット - diskdrv_hddbind(); - // SASI/IDEどっち? -#if defined(SUPPORT_SASI) - if (sxsi_issasi()) { - pccore.hddif &= ~PCHDD_IDE; - pccore.hddif |= PCHDD_SASI; - TRACEOUT(("supported SASI")); - } -#endif -#if defined(SUPPORT_SCSI) - if (sxsi_isscsi()) { - pccore.hddif |= PCHDD_SCSI; - TRACEOUT(("supported SCSI")); - } -#endif - - sound_changeclock(); - beep_changeclock(); - sound_reset(); - fddmtrsnd_bind(); - wabrlysnd_bind(); - - fddfile_reset2dmode(); - bios0x18_16(0x20, 0xe1); - - iocore_reset(&np2cfg); // サウンドでpicを呼ぶので… - cbuscore_reset(&np2cfg); - fmboard_reset(&np2cfg, pccore.sound); - - MEMM_ARCH((epson) ? 1 : 0); - iocore_build(); - iocore_bind(); - cbuscore_bind(); - fmboard_bind(); - - fddmtr_initialize(); - wabrly_initialize(); - calendar_initialize(); - vram_initialize(); - - pal_change(1); - - bios_initialize(); - - CS_BASE = 0xf0000; - CPU_CS = 0xf000; - CPU_IP = 0xfff0; - - CPU_CLEARPREFETCH(); - sysmng_cpureset(); - -#if defined(SUPPORT_HOSTDRV) - hostdrv_reset(); -#endif -#if defined(SUPPORT_HOSTDRVNT) - hostdrvNT_reset(); -#endif - - timing_reset(); - soundmng_play(); - -#if defined(SUPPORT_IA32_HAXM) - if(np2hax.enable){ - if(np2hax.hVMDevice){ - i386hax_vm_setmemory(); - i386hax_vm_setbankmemory(); - i386hax_vm_setextmemory(); - - i386hax_resetVMMem(); - - np2haxcore.clockpersec = NP2_TickCount_GetFrequency(); - np2haxcore.lastclock = NP2_TickCount_GetCount(); - np2haxcore.clockcount = NP2_TickCount_GetCount(); - np2haxcore.I_ratio = 0; - - np2haxstat.update_regs = np2haxstat.update_fpu = 0; - }else{ - np2hax.enable = 1; - } - } -#endif -#ifdef SUPPORT_ASYNC_CPU -#if defined(NP2_WIN) - if(GetTickCounterMode()==TCMODE_PERFORMANCECOUNTER){ - asynccpu_clockpersec = GetTickCounter_ClockPerSec(); - asynccpu_lastclock = GetTickCounter_Clock(); - asynccpu_clockcount = GetTickCounter_Clock(); - }else{ - asynccpu_clockpersec.QuadPart = 0; - } - pccore_asynccpu_initialize(); - pccore_asynccpu_updatesettings(np2cfg.asynclvl); -#elif defined(__LIBRETRO__) - { - UINT64 c = clock(); - COPY64(&asynccpu_lastclock, &c) - COPY64(&asynccpu_clockcount, &c) - c = CLOCKS_PER_SEC; - COPY64(&asynccpu_clockpersec, &c) - } -#elif defined(USE_SDL) - { - UINT64 c; -#if USE_SDL >= 2 - c = SDL_GetPerformanceCounter(); -#else - c = SDL_GetTicks(); -#endif - COPY64(&asynccpu_lastclock, &c) - COPY64(&asynccpu_clockcount, &c) - c = SDL_GetPerformanceFrequency(); - COPY64(&asynccpu_clockpersec, &c) - } -#endif -#endif - - // エミュレーション速度セット - if (np2cfg.emuspeed < 1) np2cfg.emuspeed = 1; - timing_setspeed(np2cfg.emuspeed * 128 / 100); - -#if defined(NP2_WIN) - // マウスリセット - mousemng_reset(); -#endif - - // キーボードリセット - keystat_initialize(); -} - -static void drawscreen(void) { - - UINT8 timing; - void (VRAMCALL * grphfn)(int page, int alldraw); - UINT8 bit; - - - tramflag.timing++; - timing = ((LOADINTELWORD(gdc.m.para + GDC_CSRFORM + 1)) >> 5) & 0x3e; - if (!timing) { - timing = 0x40; - } - if (tramflag.timing >= timing) { - tramflag.timing = 0; - tramflag.count++; - tramflag.renewal |= (tramflag.count ^ 2) & 2; - tramflag.renewal |= 1; - } - - if (gdcs.textdisp & GDCSCRN_EXT) { - gdc_updateclock(); - } - - if (!pcstat.drawframe) { - return; - } -#ifdef SUPPORT_WAB - if(np2wab.relay & 0x3){ - if(!np2wabcfg.multiwindow){ - pcstat.screenupdate = scrndraw_draw((UINT8)(pcstat.screenupdate & 2)); - drawcount++; - return; - }else{ - pcstat.screenupdate = 1; - drawcount++; - } - } -#endif - if ((gdcs.textdisp & GDCSCRN_EXT) || (gdcs.grphdisp & GDCSCRN_EXT)) { - if (dispsync_renewalvertical()) { - gdcs.textdisp |= GDCSCRN_ALLDRAW2; - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - } - } - if (gdcs.textdisp & GDCSCRN_EXT) { - gdcs.textdisp &= ~GDCSCRN_EXT; - dispsync_renewalhorizontal(); - tramflag.renewal |= 1; - if (dispsync_renewalmode()) { - pcstat.screenupdate |= 2; - } - } - if (gdcs.palchange) { - gdcs.palchange = 0; - pal_change(0); - pcstat.screenupdate |= 1; - } - if (gdcs.grphdisp & GDCSCRN_EXT) { - gdcs.grphdisp &= ~GDCSCRN_EXT; - if (((gdc.clock & 0x80) && (gdc.clock != 0x83)) || - (gdc.clock == 0x03)) { - gdc.clock ^= 0x80; - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - } - } - if (gdcs.grphdisp & GDCSCRN_ENABLE) { - if (!(gdc.mode1 & 2)) { - grphfn = makegrph; - bit = GDCSCRN_MAKE; - if (gdcs.disp) { - bit <<= 1; - } -#if defined(SUPPORT_PC9821) - if (gdc.analog & 2) { - grphfn = makegrphex; - if (gdc.analog & 4) { - bit = GDCSCRN_MAKE | (GDCSCRN_MAKE << 1); - } - } -#endif - if (gdcs.grphdisp & bit) { - (*grphfn)(gdcs.disp, gdcs.grphdisp & bit & GDCSCRN_ALLDRAW2); - gdcs.grphdisp &= ~bit; - pcstat.screenupdate |= 1; - } - } - else { - if (gdcs.textdisp & GDCSCRN_ENABLE) { - if (!gdcs.disp) { - if ((gdcs.grphdisp & GDCSCRN_MAKE) || - (gdcs.textdisp & GDCSCRN_MAKE)) { - if (!(gdc.mode1 & 0x4)) { - maketextgrph(0, gdcs.textdisp & GDCSCRN_ALLDRAW, - gdcs.grphdisp & GDCSCRN_ALLDRAW); - } - else { - maketextgrph40(0, gdcs.textdisp & GDCSCRN_ALLDRAW, - gdcs.grphdisp & GDCSCRN_ALLDRAW); - } - gdcs.grphdisp &= ~GDCSCRN_MAKE; - pcstat.screenupdate |= 1; - } - } - else { - if ((gdcs.grphdisp & (GDCSCRN_MAKE << 1)) || - (gdcs.textdisp & GDCSCRN_MAKE)) { - if (!(gdc.mode1 & 0x4)) { - maketextgrph(1, gdcs.textdisp & GDCSCRN_ALLDRAW, - gdcs.grphdisp & (GDCSCRN_ALLDRAW << 1)); - } - else { - maketextgrph40(1, gdcs.textdisp & GDCSCRN_ALLDRAW, - gdcs.grphdisp & (GDCSCRN_ALLDRAW << 1)); - } - gdcs.grphdisp &= ~(GDCSCRN_MAKE << 1); - pcstat.screenupdate |= 1; - } - } - }else{ - // 白黒グラフィック - grphfn = makegrph; - bit = GDCSCRN_MAKE; - if (gdcs.disp) { - bit <<= 1; - } - if (gdcs.grphdisp & bit) { - (*grphfn)(gdcs.disp, gdcs.grphdisp & bit & GDCSCRN_ALLDRAW2); - gdcs.grphdisp &= ~bit; - pcstat.screenupdate |= 1; - } - } - } - } - if (gdcs.textdisp & GDCSCRN_ENABLE) { - if (tramflag.renewal) { - gdcs.textdisp |= maketext_curblink(); - } - if ((cgwindow.writable & 0x80) && (tramflag.gaiji)) { - gdcs.textdisp |= GDCSCRN_ALLDRAW; - } - cgwindow.writable &= ~0x80; - if (gdcs.textdisp & GDCSCRN_MAKE) { - if (!(gdc.mode1 & 0x4)) { - maketext(gdcs.textdisp & GDCSCRN_ALLDRAW); - } - else { - maketext40(gdcs.textdisp & GDCSCRN_ALLDRAW); - } - gdcs.textdisp &= ~GDCSCRN_MAKE; - pcstat.screenupdate |= 1; - } - } - if (pcstat.screenupdate) { - pcstat.screenupdate = scrndraw_draw((UINT8)(pcstat.screenupdate & 2)); - drawcount++; - } -} - -void screendisp(NEVENTITEM item) { - - PICITEM pi; - - gdc_work(GDCWORK_SLAVE); - gdc.vsync = 0; - pcstat.screendispflag = 0; -#if !defined(SUPPORT_IA32_HAXM) - if (!np2cfg.DISPSYNC) { - drawscreen(); - } -#endif - pi = &pic.pi[0]; - if (pi->irr & PIC_CRTV) { - pi->irr &= ~PIC_CRTV; - gdc.vsyncint = 1; - } - (void)item; -} - -void screenvsync(NEVENTITEM item) { - - MEMWAIT_TRAM = np2cfg.wait[1]; - MEMWAIT_VRAM = np2cfg.wait[3]; - MEMWAIT_GRCG = np2cfg.wait[5]; - gdc_work(GDCWORK_MASTER); - gdc.vsync = 0x20; - if (gdc.vsyncint) { - gdc.vsyncint = 0; - pic_setirq(2); - } - nevent_set(NEVENT_FLAMES, gdc.vsyncclock, screendisp, NEVENT_RELATIVE); - - // drawscreenで pccore.vsyncclockが変更される可能性があります - if (np2cfg.DISPSYNC) { - drawscreen(); - } - (void)item; -} - - -// --------------------------------------------------------------------------- - -// #define SINGLESTEPONLY - -#if defined(TRACE) -static int resetcnt = 0; -static int execcnt = 0; -int piccnt = 0; -#endif - -void pccore_postevent(UINT32 event) { // yet! - - (void)event; -} - -#if defined(SUPPORT_ASYNC_CPU) -ASYNCCPUSTAT pccore_asynccpustat = {0}; -void pccore_asynccpu_initialize(void) -{ - pccore_asynccpustat.drawskip = 1; - pccore_asynccpustat.nowait = 0; - pccore_asynccpustat.lastTimingValue = 0; - pccore_asynccpustat.asyncTarget = 0; - pccore_asynccpustat.lastTimingValid = 0; - pccore_asynccpustat.screendisp = 0; - pccore_asynccpustat.threshold_down = 2; - pccore_asynccpustat.threshold_up = 5; - memset(pccore_asynccpustat.clockUpTbl, 0, sizeof(pccore_asynccpustat.clockUpTbl)); - memset(pccore_asynccpustat.clockDownTbl, 0, sizeof(pccore_asynccpustat.clockDownTbl)); -} -void pccore_asynccpu_updatesettings(int asyncLevel) -{ - int i; - int upBaseValue; - int downBaseValue; - - if (asyncLevel < 0) asyncLevel = 0; - if (asyncLevel > 100) asyncLevel = 100; - pccore_asynccpustat.asyncTarget = asyncLevel; - - // 上げ下げの頻度を設定 安定性を考慮して最低1はつける - pccore_asynccpustat.threshold_down = (6 * asyncLevel + 1 * (100 - asyncLevel)) / 100; - pccore_asynccpustat.threshold_up = (1 * asyncLevel + 6 * (100 - asyncLevel)) / 100; - if (pccore_asynccpustat.threshold_down < 1) pccore_asynccpustat.threshold_down = 1; - if (pccore_asynccpustat.threshold_up < 1) pccore_asynccpustat.threshold_up = 1; - - // 現在のクロック倍率に対してどれだけクロック倍率を上げ下げするかのテーブル - upBaseValue = (8 * asyncLevel + 4 * (100 - asyncLevel)) / 100; // ベース値はクロック倍率40に対してどれだけ上げるかの値とする - downBaseValue = (10 * asyncLevel + 15 * (100 - asyncLevel)) / 100; // ベース値はクロック倍率40に対してどれだけ下げるかの値とする - for (i = 1; i < ASYNCCPU_CLOCKTABLE_MAX; i++) { - pccore_asynccpustat.clockUpTbl[i] = (upBaseValue * i + 39) / 40; // 最低1はつけたいので切り上げ - pccore_asynccpustat.clockDownTbl[i] = (downBaseValue * i + 39) / 40; // 最低1はつけたいので切り上げ - if (pccore_asynccpustat.clockDownTbl[i] > i - 1) { - // クロック倍率0以下は不可 - pccore_asynccpustat.clockDownTbl[i] = i - 1; - } - } - // クロック倍率0はあり得ないが念のため値は書いておく - pccore_asynccpustat.clockDownTbl[0] = 0; - pccore_asynccpustat.clockUpTbl[0] = 1; -} -static void pccore_asynccpu() -{ - // 非同期CPU処理 - static int latecount = 0; - static int latecount2 = 0; - static unsigned int hltflag = 0; - if (np2cfg.asynccpu && !pccore_asynccpustat.nowait) - { - int remclkcnt = INT_MAX; - - if (latecount2 == 0) - { - if (latecount > 0) - { - //latecount--; - } - else if (latecount < 0) - { - latecount++; - } - } - latecount2 = (latecount2 + 1) & 0x1fff; - -#if defined(CPUCORE_IA32) - if (CPU_STAT_HLT) - { - hltflag = pccore.multiple; - } -#endif - if (!asynccpu_fastflag && !asynccpu_lateflag) - { - UINT32 timimg = pccore_asynccpustat.lastTimingValue; - UINT32 shdrawskip = 1 << TIMING_MSSHIFT; - if (timimg > shdrawskip) - { - latecount++; - if (latecount > pccore_asynccpustat.threshold_down) - { - if (pccore.multiple > 1) - { - UINT32 oldmultiple = pccore.multiple; - UINT32 changeValue = pccore_asynccpustat.clockDownTbl[pccore.multiple < ASYNCCPU_CLOCKTABLE_MAX ? pccore.multiple : ASYNCCPU_CLOCKTABLE_MAX - 1]; - if (timimg > 2 * shdrawskip) - { - // そのまま - } - else if (timimg > 15 * shdrawskip / 10) - { - changeValue = (changeValue + 1) / 2; // 1/2 - } - else if (timimg > 12 * shdrawskip / 10) - { - changeValue = (changeValue + 2) / 3; // 1/3 - } - else - { - changeValue = (changeValue + 9) / 10; // 1/10 - } - if (pccore.multiple > changeValue) { - pccore.multiple -= changeValue; - } - else { - pccore.multiple = 1; - } - pccore.realclock = pccore.baseclock * pccore.multiple; - pcm86_changeclock(oldmultiple); - nevent_changeclock(oldmultiple, pccore.multiple); - - sound_changeclock(); - beep_changeclock(); - mpu98ii_changeclock(); -#if defined(SUPPORT_SMPU98) - smpu98_changeclock(); -#endif - keyboard_changeclock(); - mouseif_changeclock(); - gdc_updateclock(); - } - latecount = 0; - } - asynccpu_lateflag = 1; - } - else - { - if (!hltflag && pccore_asynccpustat.screendisp) - { - latecount--; - if (latecount < -pccore_asynccpustat.threshold_up) - { - if (pccore.multiple < pccore.maxmultiple) - { - UINT32 oldmultiple = pccore.multiple; - UINT32 changeValue = pccore_asynccpustat.clockUpTbl[pccore.multiple < ASYNCCPU_CLOCKTABLE_MAX ? pccore.multiple : ASYNCCPU_CLOCKTABLE_MAX - 1]; - if (timimg < 5 * shdrawskip / 10) - { - // そのまま - } - else if (timimg < 7 * shdrawskip / 10) - { - changeValue = (changeValue * 3 + 3) / 4; // 3/4 - } - else if (timimg < 8 * shdrawskip / 10) - { - changeValue = (changeValue + 1) / 2; // 1/2 - } - else - { - changeValue = (changeValue + 3) / 4; // 1/4 - } - if (pccore.multiple + changeValue < pccore.maxmultiple) { - pccore.multiple += changeValue; - } - else { - pccore.multiple = pccore.maxmultiple; - } - pccore.realclock = pccore.baseclock * pccore.multiple; - pcm86_changeclock(oldmultiple); - nevent_changeclock(oldmultiple, pccore.multiple); - - sound_changeclock(); - beep_changeclock(); - mpu98ii_changeclock(); -#if defined(SUPPORT_SMPU98) - smpu98_changeclock(); -#endif - keyboard_changeclock(); - mouseif_changeclock(); - gdc_updateclock(); - } - latecount = 0; - } - asynccpu_fastflag = 1; - } - } - } - } - if (hltflag > 0) hltflag--; -} -#endif - -void pccore_exec(BOOL draw) { - - // ここでローカル変数を使うとsetjmp周りの最適化で破壊される可能性があるので注意 - static UINT32 baseclk = 0; - //UINT32 lastclock; - //UINT32 mflag = 0; - - pcstat.drawframe = (UINT8)draw; -// keystat_sync(); - soundmng_sync(); - mouseif_sync(); - pal_eventclear(); - -#if defined(SUPPORT_IA32_HAXM) - // HAXMの場合、先に描画 - if (!np2cfg.DISPSYNC) { - drawscreen(); - } -#endif - - gdc.vsync = 0; - pcstat.screendispflag = 1; - MEMWAIT_TRAM = np2cfg.wait[0]; - MEMWAIT_VRAM = np2cfg.wait[2]; - MEMWAIT_GRCG = np2cfg.wait[4]; - - nevent_set(NEVENT_FLAMES, gdc.dispclock, screenvsync, NEVENT_RELATIVE); - -// nevent_get1stevent(); - - if(np2cfg.keyrepeat_enable) { - keyrepeat_proc(); - } - - while(pcstat.screendispflag) { -#if defined(TRACE) - resetcnt++; -#endif -#if defined(USE_TSC) - CPU_MSR_TSC += CPU_BASECLOCK * pccore.maxmultiple / pccore.multiple; - baseclk = CPU_BASECLOCK * pccore.maxmultiple / pccore.multiple; -#endif - pic_irq(); -#if defined(SUPPORT_IA32_HAXM) - if (CPU_RESETREQ && (np2hax.emumode || !np2hax.enable || np2haxcore.ready_for_reset)) { -#else - if (CPU_RESETREQ) { -#endif - CPU_RESETREQ = 0; -#if defined(SUPPORT_WAB) - np2wab.relaystateint = np2wab.relaystateext = 0; - np2wab_setRelayState(0); // XXX: -#endif -#if defined(SUPPORT_CL_GD5430) - np2clvga.gd54xxtype = np2clvga.defgd54xxtype; // Auto Select用 - pc98_cirrus_vga_initVRAMWindowAddr(); - pc98_cirrus_vga_resetresolution(); -#endif -#if defined(SUPPORT_IDEIO) - ideio_basereset(); // XXX: Win9xの再起動で必要 -#endif -#if defined(SUPPORT_HOSTDRV) - hostdrv_reset(); // XXX: Win9xの再起動で必要 -#endif -#if defined(SUPPORT_HOSTDRVNT) - hostdrvNT_reset(); // XXX: Win9xの再起動で必要 -#endif -#if defined(SUPPORT_PCI) - pcidev_basereset(); // XXX: Win9xの再起動で必要 -#endif -#if defined(NP2_WIN) - // マウスリセット - mousemng_reset(); -#endif - -#if defined(SUPPORT_IA32_HAXM) - if (!np2hax.emumode && np2hax.enable) { - i386hax_resetVMCPU(); - i386haxfunc_vcpu_setREGs(&np2haxstat.state); - i386haxfunc_vcpu_setFPU(&np2haxstat.fpustate); - ia32hax_copyregHAXtoNP2(); - i386hax_resetVMMem(); - np2haxstat.update_regs = np2haxstat.update_fpu = 1; - np2haxstat.update_segment_regs = 1; - np2haxstat.irq_reqidx_cur = np2haxstat.irq_reqidx_end = 0; - pic_reset(&np2cfg); - np2haxcore.hltflag = 0; - } -#endif - CPU_SHUT(); - } -#if defined(SUPPORT_IA32_HAXM) - if (np2hax.enable) { - i386hax_vm_exec(); - }else -#endif - { -#if !defined(SINGLESTEPONLY) - if (CPU_REMCLOCK > 0) { - if (!(CPU_TYPE & CPUTYPE_V30)) { - CPU_EXEC(); - } - else { - CPU_EXECV30(); - } - } -#else - while(CPU_REMCLOCK > 0) { - CPU_STEPEXEC(); - } -#endif - } -#if defined(USE_TSC) - CPU_MSR_TSC = CPU_MSR_TSC - baseclk + CPU_BASECLOCK * pccore.maxmultiple / pccore.multiple; -#endif -#if defined(SUPPORT_HRTIMER) - upd4990_hrtimer_count(); -#endif -#if defined(SUPPORT_IDEIO) -#if defined(NP2_WIN) - atapi_dataread_asyncwait(INFINITE); -#endif -#endif - nevent_progress(); -#if defined(SUPPORT_ASYNC_CPU) - pccore_asynccpu(); -#endif - } -#if defined(SUPPORT_ASYNC_CPU) - asynccpu_lateflag = 0; - asynccpu_fastflag = 0; -#endif - artic_callback(); - mpu98ii_callback(); -#if defined(SUPPORT_SMPU98) - smpu98_callback(); -#endif - diskdrv_callback(); - calendar_inc(); - S98_sync(); - sound_sync(); - fdc_intdelay(); // FDC SEEK & RECALIBRATE, etc. np21w ver0.86 rev46 - - if (pcstat.hardwarereset) { - pcstat.hardwarereset = FALSE; - pccore_cfgupdate(); - if(nevent_iswork(NEVENT_CDWAIT)){ - nevent_forceexecute(NEVENT_CDWAIT); - } - pccore_reset(); - } - -#if defined(TRACE) - execcnt++; - if (execcnt >= 60) { -// TRACEOUT(("resetcnt = %d / pic %d", resetcnt, piccnt)); - execcnt = 0; - resetcnt = 0; - piccnt = 0; - } -#endif -} - -#if defined(CPUCORE_IA32) -int GetCpuTypeIndex(){ - if((CPU_FEATURES_ALL & CPU_FEATURES_80386) != CPU_FEATURES_80386) goto AMDCPUCheck; - if(np2cfg.cpu_family == CPU_80386_FAMILY && - np2cfg.cpu_model == CPU_80386_MODEL && - np2cfg.cpu_stepping == CPU_80386_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_80386 && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_80386 && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_80386 && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_80386){ - return 1; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_I486SX) != CPU_FEATURES_I486SX) goto AMDCPUCheck; - if(np2cfg.cpu_family == CPU_I486SX_FAMILY && - np2cfg.cpu_model == CPU_I486SX_MODEL && - np2cfg.cpu_stepping == CPU_I486SX_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_I486SX && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_I486SX && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_I486SX && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_I486SX){ - return 2; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_I486DX) != CPU_FEATURES_I486DX) goto AMDCPUCheck; - if(np2cfg.cpu_family == CPU_I486DX_FAMILY && - np2cfg.cpu_model == CPU_I486DX_MODEL && - np2cfg.cpu_stepping == CPU_I486DX_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_I486DX && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_I486DX && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_I486DX && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_I486DX){ - return 3; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM) != CPU_FEATURES_PENTIUM) goto AMDCPUCheck; - if(np2cfg.cpu_family == CPU_PENTIUM_FAMILY && - np2cfg.cpu_model == CPU_PENTIUM_MODEL && - np2cfg.cpu_stepping == CPU_PENTIUM_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM){ - return 4; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_MMX_PENTIUM) != CPU_FEATURES_MMX_PENTIUM) goto AMDCPUCheck; - if(np2cfg.cpu_family == CPU_MMX_PENTIUM_FAMILY && - np2cfg.cpu_model == CPU_MMX_PENTIUM_MODEL && - np2cfg.cpu_stepping == CPU_MMX_PENTIUM_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_MMX_PENTIUM && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_MMX_PENTIUM && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_MMX_PENTIUM && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_MMX_PENTIUM){ - return 5; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM_PRO) != CPU_FEATURES_PENTIUM_PRO) goto AMDCPUCheck; - if(np2cfg.cpu_family == CPU_PENTIUM_PRO_FAMILY && - np2cfg.cpu_model == CPU_PENTIUM_PRO_MODEL && - np2cfg.cpu_stepping == CPU_PENTIUM_PRO_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM_PRO && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM_PRO && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM_PRO && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM_PRO){ - return 6; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM_II) != CPU_FEATURES_PENTIUM_II) goto AMDCPUCheck; - if(np2cfg.cpu_family == CPU_PENTIUM_II_FAMILY && - np2cfg.cpu_model == CPU_PENTIUM_II_MODEL && - np2cfg.cpu_stepping == CPU_PENTIUM_II_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM_II && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM_II && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM_II && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM_II){ - return 7; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM_III) != CPU_FEATURES_PENTIUM_III) goto AMDCPUCheck; - if(np2cfg.cpu_family == CPU_PENTIUM_III_FAMILY && - np2cfg.cpu_model == CPU_PENTIUM_III_MODEL && - np2cfg.cpu_stepping == CPU_PENTIUM_III_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM_III && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM_III && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM_III && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM_III){ - return 8; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM_M) != CPU_FEATURES_PENTIUM_M) goto AMDCPUCheck; - if(np2cfg.cpu_family == CPU_PENTIUM_M_FAMILY && - np2cfg.cpu_model == CPU_PENTIUM_M_MODEL && - np2cfg.cpu_stepping == CPU_PENTIUM_M_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM_M && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM_M && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM_M && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM_M){ - return 9; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM_4) != CPU_FEATURES_PENTIUM_4) goto AMDCPUCheck; - if(np2cfg.cpu_family == CPU_PENTIUM_4_FAMILY && - np2cfg.cpu_model == CPU_PENTIUM_4_MODEL && - np2cfg.cpu_stepping == CPU_PENTIUM_4_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM_4 && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM_4 && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM_4 && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM_4){ - return 10; - } - -AMDCPUCheck: - if((CPU_FEATURES_ALL & CPU_FEATURES_AMD_K6_2) != CPU_FEATURES_AMD_K6_2 || - (CPU_FEATURES_EX_ALL & CPU_FEATURES_EX_AMD_K6_2) != CPU_FEATURES_EX_AMD_K6_2) goto NekoCPUCheck; - if(np2cfg.cpu_family == CPU_AMD_K6_2_FAMILY && - np2cfg.cpu_model == CPU_AMD_K6_2_MODEL && - np2cfg.cpu_stepping == CPU_AMD_K6_2_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_AMD_K6_2 && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_AMD_K6_2 && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_AMD_K6_2 && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_AMD_K6_2){ - return 15; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_AMD_K6_III) != CPU_FEATURES_AMD_K6_III || - (CPU_FEATURES_EX_ALL & CPU_FEATURES_EX_AMD_K6_III) != CPU_FEATURES_EX_AMD_K6_III) goto NekoCPUCheck; - if(np2cfg.cpu_family == CPU_AMD_K6_III_FAMILY && - np2cfg.cpu_model == CPU_AMD_K6_III_MODEL && - np2cfg.cpu_stepping == CPU_AMD_K6_III_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_AMD_K6_III && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_AMD_K6_III && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_AMD_K6_III && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_AMD_K6_III){ - return 16; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_AMD_K7_ATHLON) != CPU_FEATURES_AMD_K7_ATHLON || - (CPU_FEATURES_EX_ALL & CPU_FEATURES_EX_AMD_K7_ATHLON) != CPU_FEATURES_EX_AMD_K7_ATHLON) goto NekoCPUCheck; - if(np2cfg.cpu_family == CPU_AMD_K7_ATHLON_FAMILY && - np2cfg.cpu_model == CPU_AMD_K7_ATHLON_MODEL && - np2cfg.cpu_stepping == CPU_AMD_K7_ATHLON_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_AMD_K7_ATHLON && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_AMD_K7_ATHLON && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_AMD_K7_ATHLON && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_AMD_K7_ATHLON){ - return 17; - } - if((CPU_FEATURES_ALL & CPU_FEATURES_AMD_K7_ATHLON_XP) != CPU_FEATURES_AMD_K7_ATHLON_XP || - (CPU_FEATURES_EX_ALL & CPU_FEATURES_EX_AMD_K7_ATHLON_XP) != CPU_FEATURES_EX_AMD_K7_ATHLON_XP) goto NekoCPUCheck; - if(np2cfg.cpu_family == CPU_AMD_K7_ATHLON_XP_FAMILY && - np2cfg.cpu_model == CPU_AMD_K7_ATHLON_XP_MODEL && - np2cfg.cpu_stepping == CPU_AMD_K7_ATHLON_XP_STEPPING && - (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_AMD_K7_ATHLON_XP && - (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_AMD_K7_ATHLON_XP && - (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_AMD_K7_ATHLON_XP && - np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_AMD_K7_ATHLON_XP){ - return 18; - } - -NekoCPUCheck: - if(np2cfg.cpu_family == 0 && - np2cfg.cpu_model == 0 && - np2cfg.cpu_stepping == 0 && - np2cfg.cpu_feature == 0 && - np2cfg.cpu_feature_ex == 0){ - return 255; - } - return 0; -} -int SetCpuTypeIndex(UINT index){ - switch(index){ - case 1: - np2cfg.cpu_family = CPU_80386_FAMILY; - np2cfg.cpu_model = CPU_80386_MODEL; - np2cfg.cpu_stepping = CPU_80386_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_80386; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_80386; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_80386; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_80386; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_80386); - np2cfg.cpu_brandid = CPU_BRAND_ID_80386; - break; - case 2: - np2cfg.cpu_family = CPU_I486SX_FAMILY; - np2cfg.cpu_model = CPU_I486SX_MODEL; - np2cfg.cpu_stepping = CPU_I486SX_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_I486SX; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_I486SX; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_I486SX; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_I486SX; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_I486SX); - np2cfg.cpu_brandid = CPU_BRAND_ID_I486SX; - break; - case 3: - np2cfg.cpu_family = CPU_I486DX_FAMILY; - np2cfg.cpu_model = CPU_I486DX_MODEL; - np2cfg.cpu_stepping = CPU_I486DX_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_I486DX; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_I486DX; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_I486DX; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_I486DX; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_I486DX); - np2cfg.cpu_brandid = CPU_BRAND_ID_I486DX; - break; - case 4: - np2cfg.cpu_family = CPU_PENTIUM_FAMILY; - np2cfg.cpu_model = CPU_PENTIUM_MODEL; - np2cfg.cpu_stepping = CPU_PENTIUM_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_PENTIUM; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM); - np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM; - break; - case 5: - np2cfg.cpu_family = CPU_MMX_PENTIUM_FAMILY; - np2cfg.cpu_model = CPU_MMX_PENTIUM_MODEL; - np2cfg.cpu_stepping = CPU_MMX_PENTIUM_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_MMX_PENTIUM; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_MMX_PENTIUM; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_MMX_PENTIUM; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_MMX_PENTIUM; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_MMX_PENTIUM); - np2cfg.cpu_brandid = CPU_BRAND_ID_MMX_PENTIUM; - break; - case 6: - np2cfg.cpu_family = CPU_PENTIUM_PRO_FAMILY; - np2cfg.cpu_model = CPU_PENTIUM_PRO_MODEL; - np2cfg.cpu_stepping = CPU_PENTIUM_PRO_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_PENTIUM_PRO; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM_PRO; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM_PRO; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM_PRO; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_PRO); - np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM_PRO; - break; - case 7: - np2cfg.cpu_family = CPU_PENTIUM_II_FAMILY; - np2cfg.cpu_model = CPU_PENTIUM_II_MODEL; - np2cfg.cpu_stepping = CPU_PENTIUM_II_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_PENTIUM_II; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM_II; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM_II; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM_II; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_II); - np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM_II; - break; - case 8: - np2cfg.cpu_family = CPU_PENTIUM_III_FAMILY; - np2cfg.cpu_model = CPU_PENTIUM_III_MODEL; - np2cfg.cpu_stepping = CPU_PENTIUM_III_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_PENTIUM_III; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM_III; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM_III; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM_III; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_III); - np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM_III; - break; - case 9: - np2cfg.cpu_family = CPU_PENTIUM_M_FAMILY; - np2cfg.cpu_model = CPU_PENTIUM_M_MODEL; - np2cfg.cpu_stepping = CPU_PENTIUM_M_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_PENTIUM_M; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM_M; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM_M; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM_M; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_M); - np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM_M; - break; - case 10: - np2cfg.cpu_family = CPU_PENTIUM_4_FAMILY; - np2cfg.cpu_model = CPU_PENTIUM_4_MODEL; - np2cfg.cpu_stepping = CPU_PENTIUM_4_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_PENTIUM_4; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM_4; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM_4; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM_4; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_4); - np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM_4; - break; - case 15: - np2cfg.cpu_family = CPU_AMD_K6_2_FAMILY; - np2cfg.cpu_model = CPU_AMD_K6_2_MODEL; - np2cfg.cpu_stepping = CPU_AMD_K6_2_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_AMD_K6_2; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_AMD_K6_2; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_AMD_K6_2; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_AMD_K6_2; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K6_2); - np2cfg.cpu_brandid = CPU_BRAND_ID_AMD_K6_2; - break; - case 16: - np2cfg.cpu_family = CPU_AMD_K6_III_FAMILY; - np2cfg.cpu_model = CPU_AMD_K6_III_MODEL; - np2cfg.cpu_stepping = CPU_AMD_K6_III_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_AMD_K6_III; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_AMD_K6_III; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_AMD_K6_III; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_AMD_K6_III; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K6_III); - np2cfg.cpu_brandid = CPU_BRAND_ID_AMD_K6_III; - break; - case 17: - np2cfg.cpu_family = CPU_AMD_K7_ATHLON_FAMILY; - np2cfg.cpu_model = CPU_AMD_K7_ATHLON_MODEL; - np2cfg.cpu_stepping = CPU_AMD_K7_ATHLON_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_AMD_K7_ATHLON; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_AMD_K7_ATHLON; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_AMD_K7_ATHLON; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_AMD_K7_ATHLON; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K7_ATHLON); - np2cfg.cpu_brandid = CPU_BRAND_ID_AMD_K7_ATHLON; - break; - case 18: - np2cfg.cpu_family = CPU_AMD_K7_ATHLON_XP_FAMILY; - np2cfg.cpu_model = CPU_AMD_K7_ATHLON_XP_MODEL; - np2cfg.cpu_stepping = CPU_AMD_K7_ATHLON_XP_STEPPING; - np2cfg.cpu_feature = CPU_FEATURES_AMD_K7_ATHLON_XP; - np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_AMD_K7_ATHLON_XP; - np2cfg.cpu_feature_ex = CPU_FEATURES_EX_AMD_K7_ATHLON_XP; - np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_AMD_K7_ATHLON_XP; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K7_ATHLON_XP); - np2cfg.cpu_brandid = CPU_BRAND_ID_AMD_K7_ATHLON_XP; - break; - case 255: // 全機能使用可能 - np2cfg.cpu_family = 0; - np2cfg.cpu_model = 0; - np2cfg.cpu_stepping = 0; - np2cfg.cpu_feature = 0; - np2cfg.cpu_feature_ecx = 0; - np2cfg.cpu_feature_ex = 0; - np2cfg.cpu_eflags_mask = 0; - strcpy(np2cfg.cpu_vendor, CPU_VENDOR_NEKOPRO); - strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_NEKOPRO); - np2cfg.cpu_brandid = 0; - break; - default: - return 0; - } -} -#endif - +/** + * @file pccore.c + * @brief emluration core + * + * @author $Author: yui $ + * @date $Date: 2011/02/23 10:11:44 $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_SMPU98) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_VIDEOFILTER) +#include +#endif +#include +#include +#ifdef SUPPORT_SOUND_SB16 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_HOSTDRV) +#include +#endif +#if defined(SUPPORT_HOSTDRVNT) +#include +#endif +#include +#include +#include +#include +#include +#if defined(SUPPORT_WAB) +#include +#endif +#if defined(SUPPORT_CL_GD5430) +#include +#endif +#if defined(SUPPORT_IDEIO) +#include +#include +#endif +#if defined(SUPPORT_GPIB) +#include +#endif +#if defined(CPUCORE_IA32) +#include +#include +#else +#define CPU_VENDOR "GenuineIntel" +#define CPU_FAMILY 2 +#define CPU_MODEL 1 +#define CPU_STEPPING 1 +#define CPU_FEATURES (0) +#define CPU_FEATURES_EX (0) +#define CPU_BRAND_STRING "Intel(R) 80286 Processor " +#define CPU_FEATURES_ECX (0) +#define CPU_FEATURES_EX_ECX (0) +#define CPU_BRAND_ID_AUTO (0xffffffff) +#define CPU_EFLAGS_MASK (0) +#endif +#if defined(SUPPORT_IA32_HAXM) +#if !defined(SUPPORT_NP2_TICKCOUNT) +#error HAXM need NP2_TickCount +#endif +#include +#include +#include +#include +#endif +#include + + +const OEMCHAR np2version[] = OEMTEXT(NP2KAI_GIT_TAG " " NP2KAI_GIT_HASH); + +#if defined(_WIN32_WCE) +#define PCBASEMULTIPLE 2 +#else +#define PCBASEMULTIPLE 20 +#endif + + + NP2CFG np2cfg = { + 0, 1, 0, 32, 0, 0, 0x40, + 0, 0, 0, 0, + {0x3e, 0xe3, 0x7b}, 0, + 0, 0, {1, 1, 6, 1, 8, 1}, + 128, 0x00, 1, +#if defined(SUPPORT_ASYNC_CPU) + 0, 0, +#endif + 1, +#if defined(SUPPORT_IDEIO) + 0xD8, +#endif + + OEMTEXT("VX"), PCBASECLOCK25, PCBASEMULTIPLE, 1, + {0x48, 0x05, 0x04, 0x08, 0x01, 0x00, 0x00, 0x6e}, + 1, 13, 2, 1, 0x000000, 0xffffff, + 44100, 150, 4, 0, + {0, 0, 0}, 0xd1, 0x7f, 0xd1, 0, 0, 1, + + 0x0188, 0x80, 3, 12, 12, 0xff, 0, // 118 + + 0x70, 1, 3, // Mate-X PCM + +#if defined(SUPPORT_SOUND_SB16) + 0xd2, 3, 5, 0, +#endif /* SUPPORT_SOUND_SB16 */ + +#if defined(SUPPORT_FMGEN) + 3, {0x0c, 0x0c, 0x08, 0x06, 0x03, 0x0c}, 100, 64, 64, 64, 64, 64, 128, +#else /* SUPPORT_FMGEN */ + 3, {0x0c, 0x0c, 0x08, 0x06, 0x03, 0x0c}, 100, 64, 64, 64, 64, 64, +#endif /* SUPPORT_FMGEN */ + 1, 0x82, 0, +#if defined(SUPPORT_SMPU98) + 0, 0x82, 0, +#endif /* SUPPORT_SMPU98 */ + 0, {0x17, 0x04, 0x17}, {0x0c, 0x0c, 0x02, 0x10, 0x3f, 0x3f}, +#if defined(SUPPORT_FMGEN) + 1, +#endif /* SUPPORT_FMGEN */ + 3, 0, 50, 0, 0, 1, 0, + + 0, {OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT("")}, +#if defined(SUPPORT_IDEIO) + {OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT("")}, + {SXSIDEV_HDD, SXSIDEV_HDD, SXSIDEV_CDROM, SXSIDEV_HDD}, + {OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT("")}, + 1, 1, 0, 0, 0, 0, 0, 0, 0, +#else + {OEMTEXT(""), OEMTEXT("")}, +#endif +#if defined(SUPPORT_SCSI) + {OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT("")}, +#endif + OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), +#if defined(SUPPORT_NET) + OEMTEXT(""), 0, +#endif +#if defined(SUPPORT_LGY98) + 0, 0x10D0, 5, {0x00, 0x40, 0x26, 0x12, 0x34, 0x56}, +#endif +#if defined(SUPPORT_WAB) +#if defined(__LIBRETRO__) + 1, +#else + 0, +#endif +#endif +#if defined(SUPPORT_CL_GD5430) + 0, 0x5B, 0, CIRRUS_MELCOWAB_OFS_DEFAULT, 0, +#endif +#if defined(SUPPORT_VGA_MODEX) + 0, +#endif +#if defined(SUPPORT_GPIB) + 0, 12, 1, 0, 0, +#endif +#if defined(SUPPORT_PCI) + 0, 0, 0, +#endif +#if defined(SUPPORT_STATSAVE) + 0, /* statsave */ +#endif + 0, 0, + 0, 0xff00, + 0, 0, 0, + 1, + CPU_VENDOR, CPU_FAMILY, CPU_MODEL, CPU_STEPPING, CPU_FEATURES, CPU_FEATURES_EX, CPU_BRAND_STRING, OEMTEXT(""), OEMTEXT(""), CPU_BRAND_ID_AUTO, CPU_FEATURES_ECX, CPU_EFLAGS_MASK, CPU_FEATURES_EX_ECX, + FPU_TYPE_SOFTFLOAT, +#if defined(SUPPORT_FAST_MEMORYCHECK) + 1, +#endif + 0, 0, + 1, 0, +#if defined(SUPPORT_GAMEPORT) + 0, 0, +#endif + 0, 0, 0, 0, + 0, +#if defined(SUPPORT_NP2SCSI) + 1, +#endif + 100, + OEMTEXT(""), + 0, + 0, + 0, +#if defined(SUPPORT_DEBUGSS) + 0, +#endif +#if defined(SUPPORT_VIDEOFILTER) + 0, 0, 3, 0, + {{3, 2}, {3, 2}, {3, 2}}, + { + {{1, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}}, + {{1, 2, 6, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}}, + {{1, 3, 8, 0, 0, 255, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}}, + }, +#endif + 0, 500, 50, + }; + + PCCORE pccore = { PCBASECLOCK25, PCBASEMULTIPLE, + 0, PCMODEL_VX, 0, 0, {0x3e, 0xe3, 0x7b}, 0, + SOUNDID_NONE, 0, + PCBASECLOCK25 * PCBASEMULTIPLE}; + PCSTAT pcstat = {3, TRUE, FALSE, FALSE}; + +// UINT8 screenupdate = 3; +// int screendispflag = 1; + UINT8 soundrenewal = 0; +// BOOL drawframe; + UINT drawcount = 0; +// BOOL hardwarereset = FALSE; +#if defined(SUPPORT_FMGEN) + UINT8 enable_fmgen = 0; +#endif /* SUPPORT_FMGEN */ + +#ifdef SUPPORT_ASYNC_CPU +int asynccpu_lateflag = 0; +int asynccpu_fastflag = 0; +LARGE_INTEGER asynccpu_lastclock = {0}; +LARGE_INTEGER asynccpu_clockpersec = {0}; +LARGE_INTEGER asynccpu_clockcount = {0}; +#endif + +// --------------------------------------------------------------------------- + +void getbiospath(OEMCHAR *path, const OEMCHAR *fname, int maxlen) { + +const OEMCHAR *p; + + p = np2cfg.biospath; + if (p[0]) { + file_cpyname(path, p, maxlen); + file_setseparator(path, maxlen); + file_catname(path, fname, maxlen); + } + else { + file_cpyname(path, file_getcd(fname), maxlen); + } +} + + +// ---- + +static void pccore_set(const NP2CFG *pConfig) +{ + UINT8 model; + UINT32 multiple; +#if defined(SUPPORT_LARGE_MEMORY) + UINT16 extsize; +#else + UINT8 extsize; +#endif + + ZeroMemory(&pccore, sizeof(pccore)); + model = PCMODEL_VX; + if (!milstr_cmp(pConfig->model, str_VM)) { + model = PCMODEL_VM; + } + else if (!milstr_cmp(pConfig->model, str_EPSON)) { + model = PCMODEL_EPSON | PCMODEL_VM; + } + pccore.model = model; + + CPU_TYPE = 0; + if (pConfig->dipsw[2] & 0x80) { + CPU_TYPE = CPUTYPE_V30; + } + + if (np2cfg.baseclock >= ((PCBASECLOCK25 + PCBASECLOCK20) / 2)) + { + pccore.baseclock = PCBASECLOCK25; // 2.5MHz + pccore.cpumode = 0; + } + else + { + pccore.baseclock = PCBASECLOCK20; // 2.0MHz + pccore.cpumode = CPUMODE_8MHZ; + } + multiple = pConfig->multiple; + if (multiple == 0) + { + multiple = 1; + } + else if (multiple > 2048) + { + multiple = 2048; + } + pccore.multiple = multiple; + pccore.maxmultiple = pccore.multiple; + pccore.realclock = pccore.baseclock * multiple; + + // HDDの接続 (I/Oの使用状態が変わるので.. + if (pConfig->dipsw[1] & 0x20) + { + pccore.hddif |= PCHDD_IDE; +#if defined(SUPPORT_IDEIO) + sxsi_setdevtype(0x00, np2cfg.idetype[0]==SXSIDEV_CDROM ? SXSIDEV_CDROM : SXSIDEV_NC); + sxsi_setdevtype(0x01, np2cfg.idetype[1]==SXSIDEV_CDROM ? SXSIDEV_CDROM : SXSIDEV_NC); + sxsi_setdevtype(0x02, np2cfg.idetype[2]==SXSIDEV_CDROM ? SXSIDEV_CDROM : SXSIDEV_NC); + sxsi_setdevtype(0x03, np2cfg.idetype[3]==SXSIDEV_CDROM ? SXSIDEV_CDROM : SXSIDEV_NC); +#endif + } + else + { + sxsi_setdevtype(0x02, SXSIDEV_NC); + sxsi_setdevtype(0x03, SXSIDEV_NC); + } + + // 拡張メモリ + extsize = 0; + if (!(pConfig->dipsw[2] & 0x80)) + { + extsize = np2cfg.EXTMEM; +#if defined(CPUCORE_IA32) + extsize = MIN(extsize, MEMORY_MAXSIZE); +#else + extsize = MIN(extsize, 13); +#endif + } + pccore.extmem = extsize; + CopyMemory(pccore.dipsw, pConfig->dipsw, 3); + + // サウンドボードの接続 + pccore.sound = (SOUNDID)pConfig->SOUND_SW; + + // その他CBUSの接続 + pccore.device = 0; + if (pConfig->pc9861enable) + { + pccore.device |= PCCBUS_PC9861K; + } +#if defined(SUPPORT_SMPU98) + if (pConfig->smpuenable) + { + pccore.device |= PCCBUS_SMPU98; + } + else +#endif + if (pConfig->mpuenable) + { + pccore.device |= PCCBUS_MPU98; + } +} + + +// -------------------------------------------------------------------------- + +#if !defined(DISABLE_SOUND) +static void sound_init(void) +{ + UINT rate; + + rate = np2cfg.samplingrate; + if (sound_create(rate, np2cfg.delayms) != SUCCESS) + { + rate = 0; + } + fddmtrsnd_initialize(rate); + wabrlysnd_initialize(rate); + beep_initialize(rate); + beep_setvol(np2cfg.BEEP_VOL); + tms3631_initialize(rate); + tms3631_setvol(np2cfg.vol14); + opngen_initialize(rate); + opngen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); + psggen_initialize(rate); + psggen_setvol(np2cfg.vol_ssg * np2cfg.vol_master / 100); + rhythm_initialize(rate); + rhythm_setvol(np2cfg.vol_rhythm * np2cfg.vol_master / 100); + adpcm_initialize(rate); + adpcm_setvol(np2cfg.vol_adpcm * np2cfg.vol_master / 100); + pcm86gen_initialize(rate); + pcm86gen_setvol(np2cfg.vol_pcm * np2cfg.vol_master / 100); + cs4231_initialize(rate); +#ifdef SUPPORT_SOUND_SB16 + ct1741_initialize(rate); +#endif + amd98_initialize(rate); + oplgen_initialize(rate); + oplgen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); +} + +static void sound_term(void) { + + soundmng_stop(); + amd98_deinitialize(); + rhythm_deinitialize(); + beep_deinitialize(); + wabrlysnd_deinitialize(); + fddmtrsnd_deinitialize(); + sound_destroy(); +} +#endif + +#if defined(SUPPORT_IA32_HAXM) +int pccore_mem_malloc_virtualalloc = 0; +void pccore_mem_malloc(void) { + if(!mem){ +#if defined(NP2_WIN) + mem = (UINT8*)_aligned_malloc(0x200000, 4096); +#else + mem = (UINT8*)aligned_alloc(4096, 0x200000); +#endif + } + if(!vramex || vramex==vramex_base){ +#if defined(NP2_WIN) + vramex = (UINT8*)_aligned_malloc(0x80000, 4096); +#else + vramex = (UINT8*)aligned_alloc(4096, 0x80000); +#endif + memset(vramex, 0, 0x80000); + } +} +void pccore_mem_free(void) { + if(mem){ +#if defined(NP2_WIN) + _aligned_free(mem); +#else + free(mem); +#endif + mem = NULL; + } + if(vramex && vramex!=vramex_base){ +#if defined(NP2_WIN) + _aligned_free(vramex); +#else + free(vramex); +#endif + vramex = vramex_base; + } +} +#endif + +void pccore_init(void) { + +#if defined(SUPPORT_MULTITHREAD) + nevent_initialize(); + pcm86cs_initialize(); + cs4231cs_initialize(); + ct1741cs_initialize(); +#endif + +#if defined(SUPPORT_IA32_HAXM) + i386hax_check(); + np2hax.enable = 1; + i386hax_initialize(); +#endif + +#if defined(SUPPORT_IA32_HAXM) + pccore_mem_malloc(); +#endif + + CPU_TYPE = 0; + if (np2cfg.dipsw[2] & 0x80) { + CPU_TYPE = CPUTYPE_V30; + } + + CPU_INITIALIZE(); + + pic_initialize(); + +#if defined(SUPPORT_VIDEOFILTER) + { + uint8_t vf_i, vf_j; + + hVFMng1 = VideoFilter_Init(640, 480, 25, 10); + VideoFilterMng_LoadSetting(hVFMng1, np2cfg.vf1_enable, np2cfg.vf1_pcount, np2cfg.vf1_pno); + for(vf_j = 0; vf_j < np2cfg.vf1_pcount; vf_j++) { + VideoFilter_LoadProfile(hVFMng1, vf_j, np2cfg.vf1_profile[vf_j][0], np2cfg.vf1_profile[vf_j][1]); + for(vf_i = 0; vf_i < np2cfg.vf1_profile[vf_j][0]; vf_i++) { + VideoFilter_LoadFilter(hVFMng1, vf_j, vf_i, np2cfg.vf1_param[vf_j][vf_i]); + } + } + } +#endif + pal_initlcdtable(); + pal_makelcdpal(); + pal_makeskiptable(); + dispsync_initialize(); + sxsi_initialize(); + + font_initialize(); + font_load(np2cfg.fontfile, TRUE, np2cfg.fontface); + maketext_initialize(); + makegrph_initialize(); + gdcsub_initialize(); + fddfile_initialize(); + +#if !defined(DISABLE_SOUND) +#if defined(SUPPORT_FMGEN) + enable_fmgen = 0; + if(np2cfg.usefmgen == 1) + enable_fmgen = 1; +#ifdef WIIU + enable_fmgen = 0; +#endif +#endif /* SUPPORT_FMGEN */ + + fmboard_construct(); + sound_init(); +#endif + + rs232c_construct(); + mpu98ii_construct(); +#if defined(SUPPORT_SMPU98) + smpu98_construct(); +#endif + pc9861k_initialize(); + + iocore_create(); + +#if defined(SUPPORT_IDEIO) + ideio_initialize(); +#endif + +#if defined(SUPPORT_HOSTDRV) + hostdrv_initialize(); +#endif + +#if defined(SUPPORT_HOSTDRVNT) + hostdrvNT_initialize(); +#endif + +#if defined(SUPPORT_GPIB) + gpibio_initialize(); +#endif +} + +void pccore_term(void) { + +#if defined(SUPPORT_GPIB) + gpibio_shutdown(); +#endif + +#if defined(SUPPORT_HOSTDRVNT) + hostdrvNT_deinitialize(); +#endif + +#if defined(SUPPORT_HOSTDRV) + hostdrv_deinitialize(); +#endif + +#if !defined(DISABLE_SOUND) + sound_term(); + fmboard_destruct(); +#endif + + fdd_eject(0); + fdd_eject(1); + fdd_eject(2); + fdd_eject(3); + +#if defined(SUPPORT_IDEIO) + ideio_deinitialize(); +#endif + + iocore_destroy(); + + pc9861k_deinitialize(); +#if defined(SUPPORT_SMPU98) + smpu98_destruct(); +#endif + mpu98ii_destruct(); + rs232c_destruct(); + + printif_finalize(); + + hook_fontrom_flush(); + hook_fontrom_defdisable(); + + sxsi_alltrash(); + +#if defined(SUPPORT_VIDEOFILTER) + { + uint8_t vf_i, vf_j; + + VideoFilterMng_SaveSetting(hVFMng1, &np2cfg.vf1_enable, &np2cfg.vf1_pcount, &np2cfg.vf1_pno); + for(vf_j = 0; vf_j < np2cfg.vf1_pcount; vf_j++) { + VideoFilter_SaveProfile(hVFMng1, &np2cfg.vf1_profile[vf_j][0], &np2cfg.vf1_profile[vf_j][1], vf_j); + for(vf_i = 0; vf_i < np2cfg.vf1_profile[vf_j][0]; vf_i++) { + VideoFilter_SaveFilter(hVFMng1, np2cfg.vf1_param[vf_j][vf_i], vf_j, vf_i); + } + } + VideoFilter_Deinit(hVFMng1); + } +#endif + + pic_deinitialize(); + + CPU_SETEXTSIZE(0); // メモリ解放 + CPU_DEINITIALIZE(); + +#if defined(SUPPORT_IA32_HAXM) + i386hax_deinitialize(); +#endif + +#if defined(SUPPORT_IA32_HAXM) + pccore_mem_free(); +#endif + +#if defined(SUPPORT_MULTITHREAD) + pcm86cs_shutdown(); + cs4231cs_shutdown(); + ct1741cs_shutdown(); + nevent_shutdown(); +#endif +} + + +void pccore_cfgupdate(void) { + + BOOL renewal; + int i; + + renewal = FALSE; + for (i=0; i<8; i++) + { + if (np2cfg.memsw[i] != mem[MEMX_MSW + i*4]) + { + np2cfg.memsw[i] = mem[MEMX_MSW + i*4]; + renewal = TRUE; + } + } + for (i=0; i<3; i++) + { + if (np2cfg.dipsw[i] != pccore.dipsw[i]) + { + np2cfg.dipsw[i] = pccore.dipsw[i]; + renewal = TRUE; + } + } + if (renewal) { + sysmng_update(SYS_UPDATECFG); + } +} + +/** + * Reset the virtual machine + */ +void pccore_reset(void) { + + int i; + BOOL epson; + +#if defined(SUPPORT_IA32_HAXM) + if(np2hax.enable){ + i386hax_createVM(); + i386hax_resetVMCPU(); + } +#endif + + soundmng_stop(); +#if !defined(DISABLE_SOUND) +#if defined(SUPPORT_FMGEN) + enable_fmgen = 0; + if(np2cfg.usefmgen == 1) + enable_fmgen = 1; +#ifdef WIIU + enable_fmgen = 0; +#endif +#endif /* SUPPORT_FMGEN */ + + if (soundrenewal) { + soundrenewal = 0; + sound_term(); + sound_init(); + } +#endif + ZeroMemory(mem, 0x110000); + FillMemory(mem + 0xC0000, 0xE8000 - 0xC0000, 0xff); // なぞ + ZeroMemory(mem + VRAM1_B, 0x18000); + ZeroMemory(mem + VRAM1_E, 0x08000); + ZeroMemory(mem + FONT_ADRS, 0x08000); + + //メモリスイッチ + for (i=0; i<8; i++) + { + mem[0xa3fe2 + i*4] = np2cfg.memsw[i]; + } + +#if defined(CPUCORE_IA32) + if(np2cfg.cpu_family == CPU_80386_FAMILY && np2cfg.cpu_model == CPU_80386_MODEL){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_80386); + }else if(np2cfg.cpu_family == CPU_I486SX_FAMILY && np2cfg.cpu_model == CPU_I486SX_MODEL){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_I486SX); + }else if(np2cfg.cpu_family == CPU_I486DX_FAMILY && np2cfg.cpu_model == CPU_I486DX_MODEL){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_I486DX); + }else if(np2cfg.cpu_family == CPU_PENTIUM_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM); + }else if(np2cfg.cpu_family == CPU_MMX_PENTIUM_FAMILY && np2cfg.cpu_model == CPU_MMX_PENTIUM_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_MMX_PENTIUM); + }else if(np2cfg.cpu_family == CPU_PENTIUM_PRO_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_PRO_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_PRO); + }else if(np2cfg.cpu_family == CPU_PENTIUM_II_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_II_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_II); + }else if(np2cfg.cpu_family == CPU_PENTIUM_III_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_III_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_III); + }else if(np2cfg.cpu_family == CPU_PENTIUM_M_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_M_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_M); + }else if(np2cfg.cpu_family == CPU_PENTIUM_4_FAMILY && np2cfg.cpu_model == CPU_PENTIUM_4_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_4); + }else if(np2cfg.cpu_family == CPU_CORE_2_DUO_FAMILY && np2cfg.cpu_model == CPU_CORE_2_DUO_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_CORE_2_DUO); + }else if(np2cfg.cpu_family == CPU_CORE_2_DUOW_FAMILY && np2cfg.cpu_model == CPU_CORE_2_DUOW_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_CORE_2_DUOW); + }else if(np2cfg.cpu_family == CPU_CORE_I_FAMILY && np2cfg.cpu_model == CPU_CORE_I_MODEL && !(np2cfg.cpu_feature_ex & CPU_FEATURE_EX_3DNOW)){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_CORE_I); + + }else if(np2cfg.cpu_family == CPU_AMD_K6_2_FAMILY && np2cfg.cpu_model == CPU_AMD_K6_2_MODEL){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K6_2); + }else if(np2cfg.cpu_family == CPU_AMD_K6_III_FAMILY && np2cfg.cpu_model == CPU_AMD_K6_III_MODEL){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K6_III); + }else if(np2cfg.cpu_family == CPU_AMD_K7_ATHLON_FAMILY && np2cfg.cpu_model == CPU_AMD_K7_ATHLON_MODEL){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K7_ATHLON); + }else if(np2cfg.cpu_family == CPU_AMD_K7_ATHLON_XP_FAMILY && np2cfg.cpu_model == CPU_AMD_K7_ATHLON_XP_MODEL){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K7_ATHLON_XP); + }else if(np2cfg.cpu_family == CPU_AMD_K8_ATHLON_64_FAMILY && np2cfg.cpu_model == CPU_AMD_K8_ATHLON_64_MODEL){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K8_ATHLON_64); + }else if(np2cfg.cpu_family == CPU_AMD_K8_ATHLON_64X2_FAMILY && np2cfg.cpu_model == CPU_AMD_K8_ATHLON_64X2_MODEL){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K8_ATHLON_64X2); + }else if(np2cfg.cpu_family == CPU_AMD_K10_PHENOM_FAMILY && np2cfg.cpu_model == CPU_AMD_K10_PHENOM_MODEL){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K10_PHENOM); + + }else if(np2cfg.cpu_family == 0 && np2cfg.cpu_model == 0 && np2cfg.cpu_stepping == 0 && np2cfg.cpu_feature == 0){ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_NEKOPRO); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_NEKOPRO2); + }else{ + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_NEKOPRO); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_NEKOPRO); + } +#if defined(CPUCORE_IA32) + if(strlen(np2cfg.cpu_vendor_o)!=0){ + memset(np2cfg.cpu_vendor, 0, 12); + strcpy(np2cfg.cpu_vendor, np2cfg.cpu_vendor_o); + // 字数が足りない時スペースで埋める + for(i=0;i<12;i++){ + if(np2cfg.cpu_vendor[i] == '\0'){ + np2cfg.cpu_vendor[i] = ' '; + } + } + np2cfg.cpu_vendor[12] = '\0'; + } + if(strlen(np2cfg.cpu_brandstring_o)!=0){ + memset(np2cfg.cpu_brandstring, 0, 48); + strcpy(np2cfg.cpu_brandstring, np2cfg.cpu_brandstring_o); + // 最後に1文字スペースを入れる + strcat(np2cfg.cpu_brandstring, " "); + } +#endif + strcpy(i386cpuid.cpu_vendor, np2cfg.cpu_vendor); + if(np2cfg.cpu_family == 0 && np2cfg.cpu_model == 0 && np2cfg.cpu_stepping == 0 && np2cfg.cpu_feature == 0 && np2cfg.cpu_feature_ex == 0){ + // 設定に関係なく全部使えるようにする + i386cpuid.cpu_family = CPU_FAMILY; + i386cpuid.cpu_model = CPU_MODEL; + i386cpuid.cpu_stepping = CPU_STEPPING; + i386cpuid.cpu_feature = CPU_FEATURES_ALL; + i386cpuid.cpu_feature_ex = CPU_FEATURES_EX_ALL; + i386cpuid.cpu_feature_ecx = CPU_FEATURES_ECX_ALL; + i386cpuid.cpu_feature_ex_ecx = CPU_FEATURES_EX_ECX_ALL; + i386cpuid.cpu_eflags_mask = 0; + i386cpuid.cpu_brandid = 0; + }else{ + i386cpuid.cpu_family = np2cfg.cpu_family; + i386cpuid.cpu_model = np2cfg.cpu_model; + i386cpuid.cpu_stepping = np2cfg.cpu_stepping; + i386cpuid.cpu_feature = CPU_FEATURES_ALL & np2cfg.cpu_feature; + i386cpuid.cpu_feature_ex = CPU_FEATURES_EX_ALL & np2cfg.cpu_feature_ex; + i386cpuid.cpu_feature_ecx = CPU_FEATURES_ECX_ALL & np2cfg.cpu_feature_ecx; + i386cpuid.cpu_feature_ex_ecx = CPU_FEATURES_EX_ECX_ALL & np2cfg.cpu_feature_ex_ecx; + i386cpuid.cpu_eflags_mask = (AC_FLAG) & np2cfg.cpu_eflags_mask; + i386cpuid.cpu_brandid = np2cfg.cpu_brandid; + } + strcpy(i386cpuid.cpu_brandstring, np2cfg.cpu_brandstring); + + // BrandID自動設定(過去バージョンとの互換維持用) + if(i386cpuid.cpu_brandid == CPU_BRAND_ID_AUTO){ + if(strncmp(i386cpuid.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_III, 27)==0){ + CPU_EBX = 0x2; + }else if(strncmp(i386cpuid.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_M, 27)==0){ + CPU_EBX = 0x16; + }else if(strncmp(i386cpuid.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_4, 27)==0){ + CPU_EBX = 0x9; + }else{ + CPU_EBX = 0; + } + } + + // mov cs,xx許可フラグ + i386cpuid.allow_movCS = np2cfg.allowMOVCS; + + // FPU種類を設定 使えないなら別のタイプへ変更する + i386cpuid.fpu_type = np2cfg.fpu_type; +#if !defined(SUPPORT_FPU_SOFTFLOAT) && !defined(SUPPORT_FPU_SOFTFLOAT3) + if (i386cpuid.fpu_type == FPU_TYPE_SOFTFLOAT) { + i386cpuid.fpu_type = FPU_TYPE_DOSBOX2; + } +#elif !defined(SUPPORT_FPU_DOSBOX2) + if (i386cpuid.fpu_type == FPU_TYPE_DOSBOX2) { +#if defined(SUPPORT_FPU_SOFTFLOAT) || defined(SUPPORT_FPU_SOFTFLOAT3) + i386cpuid.fpu_type = FPU_TYPE_SOFTFLOAT; +#else + i386cpuid.fpu_type = FPU_TYPE_DOSBOX; +#endif + } +#elif !defined(SUPPORT_FPU_DOSBOX) + if (i386cpuid.fpu_type == FPU_TYPE_DOSBOX) { +#if defined(SUPPORT_FPU_SOFTFLOAT) || defined(SUPPORT_FPU_SOFTFLOAT3) + i386cpuid.fpu_type = FPU_TYPE_SOFTFLOAT; +#else + i386cpuid.fpu_type = FPU_TYPE_DOSBOX2; +#endif + } +#endif + fpu_initialize(1); +#endif + + pccore_set(&np2cfg); +#if defined(SUPPORT_BMS) + bmsio_set(); +#endif + nevent_allreset(); + + CPU_RESET(); + CPU_SETEXTSIZE((UINT32)pccore.extmem); + + epson = (pccore.model & PCMODEL_EPSON) ? TRUE : FALSE; + if (epson || np2cfg.useram_d) { + /* enable RAM (D0000-DFFFF) */ + CPU_RAM_D000 = 0xffff; + } + font_setchargraph(epson); + +#if defined(SUPPORT_IA32_HAXM) + if(np2hax.hVMDevice){ + i386hax_vm_allocmemory(); + } +#endif + + // HDDセット + diskdrv_hddbind(); + // SASI/IDEどっち? +#if defined(SUPPORT_SASI) + if (sxsi_issasi()) { + pccore.hddif &= ~PCHDD_IDE; + pccore.hddif |= PCHDD_SASI; + TRACEOUT(("supported SASI")); + } +#endif +#if defined(SUPPORT_SCSI) + if (sxsi_isscsi()) { + pccore.hddif |= PCHDD_SCSI; + TRACEOUT(("supported SCSI")); + } +#endif + + sound_changeclock(); + beep_changeclock(); + sound_reset(); + fddmtrsnd_bind(); + wabrlysnd_bind(); + + fddfile_reset2dmode(); + bios0x18_16(0x20, 0xe1); + + iocore_reset(&np2cfg); // サウンドでpicを呼ぶので… + cbuscore_reset(&np2cfg); + fmboard_reset(&np2cfg, pccore.sound); + + MEMM_ARCH((epson) ? 1 : 0); + iocore_build(); + iocore_bind(); + cbuscore_bind(); + fmboard_bind(); + + fddmtr_initialize(); + wabrly_initialize(); + calendar_initialize(); + vram_initialize(); + + pal_change(1); + + bios_initialize(); + + CS_BASE = 0xf0000; + CPU_CS = 0xf000; + CPU_IP = 0xfff0; + + CPU_CLEARPREFETCH(); + sysmng_cpureset(); + +#if defined(SUPPORT_HOSTDRV) + hostdrv_reset(); +#endif +#if defined(SUPPORT_HOSTDRVNT) + hostdrvNT_reset(); +#endif + + timing_reset(); + soundmng_play(); + +#if defined(SUPPORT_IA32_HAXM) + if(np2hax.enable){ + if(np2hax.hVMDevice){ + i386hax_vm_setmemory(); + i386hax_vm_setbankmemory(); + i386hax_vm_setextmemory(); + + i386hax_resetVMMem(); + + np2haxcore.clockpersec = NP2_TickCount_GetFrequency(); + np2haxcore.lastclock = NP2_TickCount_GetCount(); + np2haxcore.clockcount = NP2_TickCount_GetCount(); + np2haxcore.I_ratio = 0; + + np2haxstat.update_regs = np2haxstat.update_fpu = 0; + }else{ + np2hax.enable = 1; + } + } +#endif +#ifdef SUPPORT_ASYNC_CPU +#if defined(NP2_WIN) + if(GetTickCounterMode()==TCMODE_PERFORMANCECOUNTER){ + asynccpu_clockpersec = GetTickCounter_ClockPerSec(); + asynccpu_lastclock = GetTickCounter_Clock(); + asynccpu_clockcount = GetTickCounter_Clock(); + }else{ + asynccpu_clockpersec.QuadPart = 0; + } + pccore_asynccpu_initialize(); + pccore_asynccpu_updatesettings(np2cfg.asynclvl); +#elif defined(__LIBRETRO__) + { + UINT64 c = clock(); + COPY64(&asynccpu_lastclock, &c) + COPY64(&asynccpu_clockcount, &c) + c = CLOCKS_PER_SEC; + COPY64(&asynccpu_clockpersec, &c) + } +#elif defined(USE_SDL) + { + UINT64 c; +#if USE_SDL >= 2 + c = SDL_GetPerformanceCounter(); +#else + c = SDL_GetTicks(); +#endif + COPY64(&asynccpu_lastclock, &c) + COPY64(&asynccpu_clockcount, &c) + c = SDL_GetPerformanceFrequency(); + COPY64(&asynccpu_clockpersec, &c) + } +#endif +#endif + + // エミュレーション速度セット + if (np2cfg.emuspeed < 1) np2cfg.emuspeed = 1; + timing_setspeed(np2cfg.emuspeed * 128 / 100); + +#if defined(NP2_WIN) + // マウスリセット + mousemng_reset(); +#endif + + // キーボードリセット + keystat_initialize(); +} + +static void drawscreen(void) { + + UINT8 timing; + void (VRAMCALL * grphfn)(int page, int alldraw); + UINT8 bit; + + + tramflag.timing++; + timing = ((LOADINTELWORD(gdc.m.para + GDC_CSRFORM + 1)) >> 5) & 0x3e; + if (!timing) { + timing = 0x40; + } + if (tramflag.timing >= timing) { + tramflag.timing = 0; + tramflag.count++; + tramflag.renewal |= (tramflag.count ^ 2) & 2; + tramflag.renewal |= 1; + } + + if (gdcs.textdisp & GDCSCRN_EXT) { + gdc_updateclock(); + } + + if (!pcstat.drawframe) { + return; + } +#ifdef SUPPORT_WAB + if(np2wab.relay & 0x3){ + if(!np2wabcfg.multiwindow){ + pcstat.screenupdate = scrndraw_draw((UINT8)(pcstat.screenupdate & 2)); + drawcount++; + return; + }else{ + pcstat.screenupdate = 1; + drawcount++; + } + } +#endif + if ((gdcs.textdisp & GDCSCRN_EXT) || (gdcs.grphdisp & GDCSCRN_EXT)) { + if (dispsync_renewalvertical()) { + gdcs.textdisp |= GDCSCRN_ALLDRAW2; + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + } + } + if (gdcs.textdisp & GDCSCRN_EXT) { + gdcs.textdisp &= ~GDCSCRN_EXT; + dispsync_renewalhorizontal(); + tramflag.renewal |= 1; + if (dispsync_renewalmode()) { + pcstat.screenupdate |= 2; + } + } + if (gdcs.palchange) { + gdcs.palchange = 0; + pal_change(0); + pcstat.screenupdate |= 1; + } + if (gdcs.grphdisp & GDCSCRN_EXT) { + gdcs.grphdisp &= ~GDCSCRN_EXT; + if (((gdc.clock & 0x80) && (gdc.clock != 0x83)) || + (gdc.clock == 0x03)) { + gdc.clock ^= 0x80; + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + } + } + if (gdcs.grphdisp & GDCSCRN_ENABLE) { + if (!(gdc.mode1 & 2)) { + grphfn = makegrph; + bit = GDCSCRN_MAKE; + if (gdcs.disp) { + bit <<= 1; + } +#if defined(SUPPORT_PC9821) + if (gdc.analog & 2) { + grphfn = makegrphex; + if (gdc.analog & 4) { + bit = GDCSCRN_MAKE | (GDCSCRN_MAKE << 1); + } + } +#endif + if (gdcs.grphdisp & bit) { + (*grphfn)(gdcs.disp, gdcs.grphdisp & bit & GDCSCRN_ALLDRAW2); + gdcs.grphdisp &= ~bit; + pcstat.screenupdate |= 1; + } + } + else { + if (gdcs.textdisp & GDCSCRN_ENABLE) { + if (!gdcs.disp) { + if ((gdcs.grphdisp & GDCSCRN_MAKE) || + (gdcs.textdisp & GDCSCRN_MAKE)) { + if (!(gdc.mode1 & 0x4)) { + maketextgrph(0, gdcs.textdisp & GDCSCRN_ALLDRAW, + gdcs.grphdisp & GDCSCRN_ALLDRAW); + } + else { + maketextgrph40(0, gdcs.textdisp & GDCSCRN_ALLDRAW, + gdcs.grphdisp & GDCSCRN_ALLDRAW); + } + gdcs.grphdisp &= ~GDCSCRN_MAKE; + pcstat.screenupdate |= 1; + } + } + else { + if ((gdcs.grphdisp & (GDCSCRN_MAKE << 1)) || + (gdcs.textdisp & GDCSCRN_MAKE)) { + if (!(gdc.mode1 & 0x4)) { + maketextgrph(1, gdcs.textdisp & GDCSCRN_ALLDRAW, + gdcs.grphdisp & (GDCSCRN_ALLDRAW << 1)); + } + else { + maketextgrph40(1, gdcs.textdisp & GDCSCRN_ALLDRAW, + gdcs.grphdisp & (GDCSCRN_ALLDRAW << 1)); + } + gdcs.grphdisp &= ~(GDCSCRN_MAKE << 1); + pcstat.screenupdate |= 1; + } + } + }else{ + // 白黒グラフィック + grphfn = makegrph; + bit = GDCSCRN_MAKE; + if (gdcs.disp) { + bit <<= 1; + } + if (gdcs.grphdisp & bit) { + (*grphfn)(gdcs.disp, gdcs.grphdisp & bit & GDCSCRN_ALLDRAW2); + gdcs.grphdisp &= ~bit; + pcstat.screenupdate |= 1; + } + } + } + } + if (gdcs.textdisp & GDCSCRN_ENABLE) { + if (tramflag.renewal) { + gdcs.textdisp |= maketext_curblink(); + } + if ((cgwindow.writable & 0x80) && (tramflag.gaiji)) { + gdcs.textdisp |= GDCSCRN_ALLDRAW; + } + cgwindow.writable &= ~0x80; + if (gdcs.textdisp & GDCSCRN_MAKE) { + if (!(gdc.mode1 & 0x4)) { + maketext(gdcs.textdisp & GDCSCRN_ALLDRAW); + } + else { + maketext40(gdcs.textdisp & GDCSCRN_ALLDRAW); + } + gdcs.textdisp &= ~GDCSCRN_MAKE; + pcstat.screenupdate |= 1; + } + } + if (pcstat.screenupdate) { + pcstat.screenupdate = scrndraw_draw((UINT8)(pcstat.screenupdate & 2)); + drawcount++; + } +} + +void screendisp(NEVENTITEM item) { + + PICITEM pi; + + gdc_work(GDCWORK_SLAVE); + gdc.vsync = 0; + pcstat.screendispflag = 0; +#if !defined(SUPPORT_IA32_HAXM) + if (!np2cfg.DISPSYNC) { + drawscreen(); + } +#endif + pi = &pic.pi[0]; + if (pi->irr & PIC_CRTV) { + pi->irr &= ~PIC_CRTV; + gdc.vsyncint = 1; + } + (void)item; +} + +void screenvsync(NEVENTITEM item) { + + MEMWAIT_TRAM = np2cfg.wait[1]; + MEMWAIT_VRAM = np2cfg.wait[3]; + MEMWAIT_GRCG = np2cfg.wait[5]; + gdc_work(GDCWORK_MASTER); + gdc.vsync = 0x20; + if (gdc.vsyncint) { + gdc.vsyncint = 0; + pic_setirq(2); + } + nevent_set(NEVENT_FLAMES, gdc.vsyncclock, screendisp, NEVENT_RELATIVE); + + // drawscreenで pccore.vsyncclockが変更される可能性があります + if (np2cfg.DISPSYNC) { + drawscreen(); + } + (void)item; +} + + +// --------------------------------------------------------------------------- + +// #define SINGLESTEPONLY + +#if defined(TRACE) +static int resetcnt = 0; +static int execcnt = 0; +int piccnt = 0; +#endif + +void pccore_postevent(UINT32 event) { // yet! + + (void)event; +} + +#if defined(SUPPORT_ASYNC_CPU) +ASYNCCPUSTAT pccore_asynccpustat = {0}; +void pccore_asynccpu_initialize(void) +{ + pccore_asynccpustat.drawskip = 1; + pccore_asynccpustat.nowait = 0; + pccore_asynccpustat.lastTimingValue = 0; + pccore_asynccpustat.asyncTarget = 0; + pccore_asynccpustat.lastTimingValid = 0; + pccore_asynccpustat.screendisp = 0; + pccore_asynccpustat.threshold_down = 2; + pccore_asynccpustat.threshold_up = 5; + memset(pccore_asynccpustat.clockUpTbl, 0, sizeof(pccore_asynccpustat.clockUpTbl)); + memset(pccore_asynccpustat.clockDownTbl, 0, sizeof(pccore_asynccpustat.clockDownTbl)); +} +void pccore_asynccpu_updatesettings(int asyncLevel) +{ + int i; + int upBaseValue; + int downBaseValue; + + if (asyncLevel < 0) asyncLevel = 0; + if (asyncLevel > 100) asyncLevel = 100; + pccore_asynccpustat.asyncTarget = asyncLevel; + + // 上げ下げの頻度を設定 安定性を考慮して最低1はつける + pccore_asynccpustat.threshold_down = (6 * asyncLevel + 1 * (100 - asyncLevel)) / 100; + pccore_asynccpustat.threshold_up = (1 * asyncLevel + 6 * (100 - asyncLevel)) / 100; + if (pccore_asynccpustat.threshold_down < 1) pccore_asynccpustat.threshold_down = 1; + if (pccore_asynccpustat.threshold_up < 1) pccore_asynccpustat.threshold_up = 1; + + // 現在のクロック倍率に対してどれだけクロック倍率を上げ下げするかのテーブル + upBaseValue = (8 * asyncLevel + 4 * (100 - asyncLevel)) / 100; // ベース値はクロック倍率40に対してどれだけ上げるかの値とする + downBaseValue = (10 * asyncLevel + 15 * (100 - asyncLevel)) / 100; // ベース値はクロック倍率40に対してどれだけ下げるかの値とする + for (i = 1; i < ASYNCCPU_CLOCKTABLE_MAX; i++) { + pccore_asynccpustat.clockUpTbl[i] = (upBaseValue * i + 39) / 40; // 最低1はつけたいので切り上げ + pccore_asynccpustat.clockDownTbl[i] = (downBaseValue * i + 39) / 40; // 最低1はつけたいので切り上げ + if (pccore_asynccpustat.clockDownTbl[i] > i - 1) { + // クロック倍率0以下は不可 + pccore_asynccpustat.clockDownTbl[i] = i - 1; + } + } + // クロック倍率0はあり得ないが念のため値は書いておく + pccore_asynccpustat.clockDownTbl[0] = 0; + pccore_asynccpustat.clockUpTbl[0] = 1; +} +static void pccore_asynccpu() +{ + // 非同期CPU処理 + static int latecount = 0; + static int latecount2 = 0; + static unsigned int hltflag = 0; + if (np2cfg.asynccpu && !pccore_asynccpustat.nowait) + { + int remclkcnt = INT_MAX; + + if (latecount2 == 0) + { + if (latecount > 0) + { + //latecount--; + } + else if (latecount < 0) + { + latecount++; + } + } + latecount2 = (latecount2 + 1) & 0x1fff; + +#if defined(CPUCORE_IA32) + if (CPU_STAT_HLT) + { + hltflag = pccore.multiple; + } +#endif + if (!asynccpu_fastflag && !asynccpu_lateflag) + { + UINT32 timimg = pccore_asynccpustat.lastTimingValue; + UINT32 shdrawskip = 1 << TIMING_MSSHIFT; + if (timimg > shdrawskip) + { + latecount++; + if (latecount > pccore_asynccpustat.threshold_down) + { + if (pccore.multiple > 1) + { + UINT32 oldmultiple = pccore.multiple; + UINT32 changeValue = pccore_asynccpustat.clockDownTbl[pccore.multiple < ASYNCCPU_CLOCKTABLE_MAX ? pccore.multiple : ASYNCCPU_CLOCKTABLE_MAX - 1]; + if (timimg > 2 * shdrawskip) + { + // そのまま + } + else if (timimg > 15 * shdrawskip / 10) + { + changeValue = (changeValue + 1) / 2; // 1/2 + } + else if (timimg > 12 * shdrawskip / 10) + { + changeValue = (changeValue + 2) / 3; // 1/3 + } + else + { + changeValue = (changeValue + 9) / 10; // 1/10 + } + if (pccore.multiple > changeValue) { + pccore.multiple -= changeValue; + } + else { + pccore.multiple = 1; + } + pccore.realclock = pccore.baseclock * pccore.multiple; + pcm86_changeclock(oldmultiple); + nevent_changeclock(oldmultiple, pccore.multiple); + + sound_changeclock(); + beep_changeclock(); + mpu98ii_changeclock(); +#if defined(SUPPORT_SMPU98) + smpu98_changeclock(); +#endif + keyboard_changeclock(); + mouseif_changeclock(); + gdc_updateclock(); + } + latecount = 0; + } + asynccpu_lateflag = 1; + } + else + { + if (!hltflag && pccore_asynccpustat.screendisp) + { + latecount--; + if (latecount < -pccore_asynccpustat.threshold_up) + { + if (pccore.multiple < pccore.maxmultiple) + { + UINT32 oldmultiple = pccore.multiple; + UINT32 changeValue = pccore_asynccpustat.clockUpTbl[pccore.multiple < ASYNCCPU_CLOCKTABLE_MAX ? pccore.multiple : ASYNCCPU_CLOCKTABLE_MAX - 1]; + if (timimg < 5 * shdrawskip / 10) + { + // そのまま + } + else if (timimg < 7 * shdrawskip / 10) + { + changeValue = (changeValue * 3 + 3) / 4; // 3/4 + } + else if (timimg < 8 * shdrawskip / 10) + { + changeValue = (changeValue + 1) / 2; // 1/2 + } + else + { + changeValue = (changeValue + 3) / 4; // 1/4 + } + if (pccore.multiple + changeValue < pccore.maxmultiple) { + pccore.multiple += changeValue; + } + else { + pccore.multiple = pccore.maxmultiple; + } + pccore.realclock = pccore.baseclock * pccore.multiple; + pcm86_changeclock(oldmultiple); + nevent_changeclock(oldmultiple, pccore.multiple); + + sound_changeclock(); + beep_changeclock(); + mpu98ii_changeclock(); +#if defined(SUPPORT_SMPU98) + smpu98_changeclock(); +#endif + keyboard_changeclock(); + mouseif_changeclock(); + gdc_updateclock(); + } + latecount = 0; + } + asynccpu_fastflag = 1; + } + } + } + } + if (hltflag > 0) hltflag--; +} +#endif + +void pccore_exec(BOOL draw) { + + // ここでローカル変数を使うとsetjmp周りの最適化で破壊される可能性があるので注意 + static UINT32 baseclk = 0; + //UINT32 lastclock; + //UINT32 mflag = 0; + + pcstat.drawframe = (UINT8)draw; +// keystat_sync(); + soundmng_sync(); + mouseif_sync(); + pal_eventclear(); + +#if defined(SUPPORT_IA32_HAXM) + // HAXMの場合、先に描画 + if (!np2cfg.DISPSYNC) { + drawscreen(); + } +#endif + + gdc.vsync = 0; + pcstat.screendispflag = 1; + MEMWAIT_TRAM = np2cfg.wait[0]; + MEMWAIT_VRAM = np2cfg.wait[2]; + MEMWAIT_GRCG = np2cfg.wait[4]; + + nevent_set(NEVENT_FLAMES, gdc.dispclock, screenvsync, NEVENT_RELATIVE); + +// nevent_get1stevent(); + + if(np2cfg.keyrepeat_enable) { + keyrepeat_proc(); + } + + while(pcstat.screendispflag) { +#if defined(TRACE) + resetcnt++; +#endif +#if defined(USE_TSC) + CPU_MSR_TSC += CPU_BASECLOCK * pccore.maxmultiple / pccore.multiple; + baseclk = CPU_BASECLOCK * pccore.maxmultiple / pccore.multiple; +#endif + pic_irq(); +#if defined(SUPPORT_IA32_HAXM) + if (CPU_RESETREQ && (np2hax.emumode || !np2hax.enable || np2haxcore.ready_for_reset)) { +#else + if (CPU_RESETREQ) { +#endif + CPU_RESETREQ = 0; +#if defined(SUPPORT_WAB) + np2wab.relaystateint = np2wab.relaystateext = 0; + np2wab_setRelayState(0); // XXX: +#endif +#if defined(SUPPORT_CL_GD5430) + np2clvga.gd54xxtype = np2clvga.defgd54xxtype; // Auto Select用 + pc98_cirrus_vga_initVRAMWindowAddr(); + pc98_cirrus_vga_resetresolution(); +#endif +#if defined(SUPPORT_IDEIO) + ideio_basereset(); // XXX: Win9xの再起動で必要 +#endif +#if defined(SUPPORT_HOSTDRV) + hostdrv_reset(); // XXX: Win9xの再起動で必要 +#endif +#if defined(SUPPORT_HOSTDRVNT) + hostdrvNT_reset(); // XXX: Win9xの再起動で必要 +#endif +#if defined(SUPPORT_PCI) + pcidev_basereset(); // XXX: Win9xの再起動で必要 +#endif +#if defined(NP2_WIN) + // マウスリセット + mousemng_reset(); +#endif + +#if defined(SUPPORT_IA32_HAXM) + if (!np2hax.emumode && np2hax.enable) { + i386hax_resetVMCPU(); + i386haxfunc_vcpu_setREGs(&np2haxstat.state); + i386haxfunc_vcpu_setFPU(&np2haxstat.fpustate); + ia32hax_copyregHAXtoNP2(); + i386hax_resetVMMem(); + np2haxstat.update_regs = np2haxstat.update_fpu = 1; + np2haxstat.update_segment_regs = 1; + np2haxstat.irq_reqidx_cur = np2haxstat.irq_reqidx_end = 0; + pic_reset(&np2cfg); + np2haxcore.hltflag = 0; + } +#endif + CPU_SHUT(); + } +#if defined(SUPPORT_IA32_HAXM) + if (np2hax.enable) { + i386hax_vm_exec(); + }else +#endif + { +#if !defined(SINGLESTEPONLY) + if (CPU_REMCLOCK > 0) { + if (!(CPU_TYPE & CPUTYPE_V30)) { + CPU_EXEC(); + } + else { + CPU_EXECV30(); + } + } +#else + while(CPU_REMCLOCK > 0) { + CPU_STEPEXEC(); + } +#endif + } +#if defined(USE_TSC) + CPU_MSR_TSC = CPU_MSR_TSC - baseclk + CPU_BASECLOCK * pccore.maxmultiple / pccore.multiple; +#endif +#if defined(SUPPORT_HRTIMER) + upd4990_hrtimer_count(); +#endif +#if defined(SUPPORT_IDEIO) +#if defined(NP2_WIN) + atapi_dataread_asyncwait(INFINITE); +#endif +#endif + nevent_progress(); +#if defined(SUPPORT_ASYNC_CPU) + pccore_asynccpu(); +#endif + } +#if defined(SUPPORT_ASYNC_CPU) + asynccpu_lateflag = 0; + asynccpu_fastflag = 0; +#endif + artic_callback(); + mpu98ii_callback(); +#if defined(SUPPORT_SMPU98) + smpu98_callback(); +#endif + diskdrv_callback(); + calendar_inc(); + S98_sync(); + sound_sync(); + fdc_intdelay(); // FDC SEEK & RECALIBRATE, etc. np21w ver0.86 rev46 + + if (pcstat.hardwarereset) { + pcstat.hardwarereset = FALSE; + pccore_cfgupdate(); + if(nevent_iswork(NEVENT_CDWAIT)){ + nevent_forceexecute(NEVENT_CDWAIT); + } + pccore_reset(); + } + +#if defined(TRACE) + execcnt++; + if (execcnt >= 60) { +// TRACEOUT(("resetcnt = %d / pic %d", resetcnt, piccnt)); + execcnt = 0; + resetcnt = 0; + piccnt = 0; + } +#endif +} + +#if defined(CPUCORE_IA32) +int GetCpuTypeIndex(){ + if((CPU_FEATURES_ALL & CPU_FEATURES_80386) != CPU_FEATURES_80386) goto AMDCPUCheck; + if(np2cfg.cpu_family == CPU_80386_FAMILY && + np2cfg.cpu_model == CPU_80386_MODEL && + np2cfg.cpu_stepping == CPU_80386_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_80386 && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_80386 && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_80386 && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_80386){ + return 1; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_I486SX) != CPU_FEATURES_I486SX) goto AMDCPUCheck; + if(np2cfg.cpu_family == CPU_I486SX_FAMILY && + np2cfg.cpu_model == CPU_I486SX_MODEL && + np2cfg.cpu_stepping == CPU_I486SX_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_I486SX && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_I486SX && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_I486SX && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_I486SX){ + return 2; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_I486DX) != CPU_FEATURES_I486DX) goto AMDCPUCheck; + if(np2cfg.cpu_family == CPU_I486DX_FAMILY && + np2cfg.cpu_model == CPU_I486DX_MODEL && + np2cfg.cpu_stepping == CPU_I486DX_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_I486DX && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_I486DX && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_I486DX && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_I486DX){ + return 3; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM) != CPU_FEATURES_PENTIUM) goto AMDCPUCheck; + if(np2cfg.cpu_family == CPU_PENTIUM_FAMILY && + np2cfg.cpu_model == CPU_PENTIUM_MODEL && + np2cfg.cpu_stepping == CPU_PENTIUM_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM){ + return 4; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_MMX_PENTIUM) != CPU_FEATURES_MMX_PENTIUM) goto AMDCPUCheck; + if(np2cfg.cpu_family == CPU_MMX_PENTIUM_FAMILY && + np2cfg.cpu_model == CPU_MMX_PENTIUM_MODEL && + np2cfg.cpu_stepping == CPU_MMX_PENTIUM_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_MMX_PENTIUM && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_MMX_PENTIUM && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_MMX_PENTIUM && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_MMX_PENTIUM){ + return 5; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM_PRO) != CPU_FEATURES_PENTIUM_PRO) goto AMDCPUCheck; + if(np2cfg.cpu_family == CPU_PENTIUM_PRO_FAMILY && + np2cfg.cpu_model == CPU_PENTIUM_PRO_MODEL && + np2cfg.cpu_stepping == CPU_PENTIUM_PRO_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM_PRO && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM_PRO && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM_PRO && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM_PRO){ + return 6; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM_II) != CPU_FEATURES_PENTIUM_II) goto AMDCPUCheck; + if(np2cfg.cpu_family == CPU_PENTIUM_II_FAMILY && + np2cfg.cpu_model == CPU_PENTIUM_II_MODEL && + np2cfg.cpu_stepping == CPU_PENTIUM_II_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM_II && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM_II && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM_II && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM_II){ + return 7; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM_III) != CPU_FEATURES_PENTIUM_III) goto AMDCPUCheck; + if(np2cfg.cpu_family == CPU_PENTIUM_III_FAMILY && + np2cfg.cpu_model == CPU_PENTIUM_III_MODEL && + np2cfg.cpu_stepping == CPU_PENTIUM_III_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM_III && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM_III && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM_III && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM_III){ + return 8; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM_M) != CPU_FEATURES_PENTIUM_M) goto AMDCPUCheck; + if(np2cfg.cpu_family == CPU_PENTIUM_M_FAMILY && + np2cfg.cpu_model == CPU_PENTIUM_M_MODEL && + np2cfg.cpu_stepping == CPU_PENTIUM_M_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM_M && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM_M && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM_M && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM_M){ + return 9; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_PENTIUM_4) != CPU_FEATURES_PENTIUM_4) goto AMDCPUCheck; + if(np2cfg.cpu_family == CPU_PENTIUM_4_FAMILY && + np2cfg.cpu_model == CPU_PENTIUM_4_MODEL && + np2cfg.cpu_stepping == CPU_PENTIUM_4_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_PENTIUM_4 && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_PENTIUM_4 && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_PENTIUM_4 && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_PENTIUM_4){ + return 10; + } + +AMDCPUCheck: + if((CPU_FEATURES_ALL & CPU_FEATURES_AMD_K6_2) != CPU_FEATURES_AMD_K6_2 || + (CPU_FEATURES_EX_ALL & CPU_FEATURES_EX_AMD_K6_2) != CPU_FEATURES_EX_AMD_K6_2) goto NekoCPUCheck; + if(np2cfg.cpu_family == CPU_AMD_K6_2_FAMILY && + np2cfg.cpu_model == CPU_AMD_K6_2_MODEL && + np2cfg.cpu_stepping == CPU_AMD_K6_2_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_AMD_K6_2 && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_AMD_K6_2 && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_AMD_K6_2 && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_AMD_K6_2){ + return 15; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_AMD_K6_III) != CPU_FEATURES_AMD_K6_III || + (CPU_FEATURES_EX_ALL & CPU_FEATURES_EX_AMD_K6_III) != CPU_FEATURES_EX_AMD_K6_III) goto NekoCPUCheck; + if(np2cfg.cpu_family == CPU_AMD_K6_III_FAMILY && + np2cfg.cpu_model == CPU_AMD_K6_III_MODEL && + np2cfg.cpu_stepping == CPU_AMD_K6_III_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_AMD_K6_III && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_AMD_K6_III && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_AMD_K6_III && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_AMD_K6_III){ + return 16; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_AMD_K7_ATHLON) != CPU_FEATURES_AMD_K7_ATHLON || + (CPU_FEATURES_EX_ALL & CPU_FEATURES_EX_AMD_K7_ATHLON) != CPU_FEATURES_EX_AMD_K7_ATHLON) goto NekoCPUCheck; + if(np2cfg.cpu_family == CPU_AMD_K7_ATHLON_FAMILY && + np2cfg.cpu_model == CPU_AMD_K7_ATHLON_MODEL && + np2cfg.cpu_stepping == CPU_AMD_K7_ATHLON_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_AMD_K7_ATHLON && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_AMD_K7_ATHLON && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_AMD_K7_ATHLON && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_AMD_K7_ATHLON){ + return 17; + } + if((CPU_FEATURES_ALL & CPU_FEATURES_AMD_K7_ATHLON_XP) != CPU_FEATURES_AMD_K7_ATHLON_XP || + (CPU_FEATURES_EX_ALL & CPU_FEATURES_EX_AMD_K7_ATHLON_XP) != CPU_FEATURES_EX_AMD_K7_ATHLON_XP) goto NekoCPUCheck; + if(np2cfg.cpu_family == CPU_AMD_K7_ATHLON_XP_FAMILY && + np2cfg.cpu_model == CPU_AMD_K7_ATHLON_XP_MODEL && + np2cfg.cpu_stepping == CPU_AMD_K7_ATHLON_XP_STEPPING && + (np2cfg.cpu_feature & CPU_FEATURES_ALL) == CPU_FEATURES_AMD_K7_ATHLON_XP && + (np2cfg.cpu_feature_ecx & CPU_FEATURES_ECX_ALL) == CPU_FEATURES_ECX_AMD_K7_ATHLON_XP && + (np2cfg.cpu_feature_ex & CPU_FEATURES_EX_ALL) == CPU_FEATURES_EX_AMD_K7_ATHLON_XP && + np2cfg.cpu_eflags_mask == CPU_EFLAGS_MASK_AMD_K7_ATHLON_XP){ + return 18; + } + +NekoCPUCheck: + if(np2cfg.cpu_family == 0 && + np2cfg.cpu_model == 0 && + np2cfg.cpu_stepping == 0 && + np2cfg.cpu_feature == 0 && + np2cfg.cpu_feature_ex == 0){ + return 255; + } + return 0; +} +int SetCpuTypeIndex(UINT index){ + switch(index){ + case 1: + np2cfg.cpu_family = CPU_80386_FAMILY; + np2cfg.cpu_model = CPU_80386_MODEL; + np2cfg.cpu_stepping = CPU_80386_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_80386; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_80386; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_80386; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_80386; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_80386); + np2cfg.cpu_brandid = CPU_BRAND_ID_80386; + break; + case 2: + np2cfg.cpu_family = CPU_I486SX_FAMILY; + np2cfg.cpu_model = CPU_I486SX_MODEL; + np2cfg.cpu_stepping = CPU_I486SX_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_I486SX; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_I486SX; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_I486SX; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_I486SX; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_I486SX); + np2cfg.cpu_brandid = CPU_BRAND_ID_I486SX; + break; + case 3: + np2cfg.cpu_family = CPU_I486DX_FAMILY; + np2cfg.cpu_model = CPU_I486DX_MODEL; + np2cfg.cpu_stepping = CPU_I486DX_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_I486DX; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_I486DX; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_I486DX; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_I486DX; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_I486DX); + np2cfg.cpu_brandid = CPU_BRAND_ID_I486DX; + break; + case 4: + np2cfg.cpu_family = CPU_PENTIUM_FAMILY; + np2cfg.cpu_model = CPU_PENTIUM_MODEL; + np2cfg.cpu_stepping = CPU_PENTIUM_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_PENTIUM; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM); + np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM; + break; + case 5: + np2cfg.cpu_family = CPU_MMX_PENTIUM_FAMILY; + np2cfg.cpu_model = CPU_MMX_PENTIUM_MODEL; + np2cfg.cpu_stepping = CPU_MMX_PENTIUM_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_MMX_PENTIUM; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_MMX_PENTIUM; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_MMX_PENTIUM; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_MMX_PENTIUM; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_MMX_PENTIUM); + np2cfg.cpu_brandid = CPU_BRAND_ID_MMX_PENTIUM; + break; + case 6: + np2cfg.cpu_family = CPU_PENTIUM_PRO_FAMILY; + np2cfg.cpu_model = CPU_PENTIUM_PRO_MODEL; + np2cfg.cpu_stepping = CPU_PENTIUM_PRO_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_PENTIUM_PRO; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM_PRO; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM_PRO; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM_PRO; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_PRO); + np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM_PRO; + break; + case 7: + np2cfg.cpu_family = CPU_PENTIUM_II_FAMILY; + np2cfg.cpu_model = CPU_PENTIUM_II_MODEL; + np2cfg.cpu_stepping = CPU_PENTIUM_II_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_PENTIUM_II; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM_II; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM_II; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM_II; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_II); + np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM_II; + break; + case 8: + np2cfg.cpu_family = CPU_PENTIUM_III_FAMILY; + np2cfg.cpu_model = CPU_PENTIUM_III_MODEL; + np2cfg.cpu_stepping = CPU_PENTIUM_III_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_PENTIUM_III; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM_III; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM_III; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM_III; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_III); + np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM_III; + break; + case 9: + np2cfg.cpu_family = CPU_PENTIUM_M_FAMILY; + np2cfg.cpu_model = CPU_PENTIUM_M_MODEL; + np2cfg.cpu_stepping = CPU_PENTIUM_M_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_PENTIUM_M; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM_M; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM_M; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM_M; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_M); + np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM_M; + break; + case 10: + np2cfg.cpu_family = CPU_PENTIUM_4_FAMILY; + np2cfg.cpu_model = CPU_PENTIUM_4_MODEL; + np2cfg.cpu_stepping = CPU_PENTIUM_4_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_PENTIUM_4; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_PENTIUM_4; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_PENTIUM_4; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_PENTIUM_4; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_INTEL); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_PENTIUM_4); + np2cfg.cpu_brandid = CPU_BRAND_ID_PENTIUM_4; + break; + case 15: + np2cfg.cpu_family = CPU_AMD_K6_2_FAMILY; + np2cfg.cpu_model = CPU_AMD_K6_2_MODEL; + np2cfg.cpu_stepping = CPU_AMD_K6_2_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_AMD_K6_2; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_AMD_K6_2; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_AMD_K6_2; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_AMD_K6_2; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K6_2); + np2cfg.cpu_brandid = CPU_BRAND_ID_AMD_K6_2; + break; + case 16: + np2cfg.cpu_family = CPU_AMD_K6_III_FAMILY; + np2cfg.cpu_model = CPU_AMD_K6_III_MODEL; + np2cfg.cpu_stepping = CPU_AMD_K6_III_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_AMD_K6_III; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_AMD_K6_III; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_AMD_K6_III; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_AMD_K6_III; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K6_III); + np2cfg.cpu_brandid = CPU_BRAND_ID_AMD_K6_III; + break; + case 17: + np2cfg.cpu_family = CPU_AMD_K7_ATHLON_FAMILY; + np2cfg.cpu_model = CPU_AMD_K7_ATHLON_MODEL; + np2cfg.cpu_stepping = CPU_AMD_K7_ATHLON_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_AMD_K7_ATHLON; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_AMD_K7_ATHLON; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_AMD_K7_ATHLON; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_AMD_K7_ATHLON; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K7_ATHLON); + np2cfg.cpu_brandid = CPU_BRAND_ID_AMD_K7_ATHLON; + break; + case 18: + np2cfg.cpu_family = CPU_AMD_K7_ATHLON_XP_FAMILY; + np2cfg.cpu_model = CPU_AMD_K7_ATHLON_XP_MODEL; + np2cfg.cpu_stepping = CPU_AMD_K7_ATHLON_XP_STEPPING; + np2cfg.cpu_feature = CPU_FEATURES_AMD_K7_ATHLON_XP; + np2cfg.cpu_feature_ecx = CPU_FEATURES_ECX_AMD_K7_ATHLON_XP; + np2cfg.cpu_feature_ex = CPU_FEATURES_EX_AMD_K7_ATHLON_XP; + np2cfg.cpu_eflags_mask = CPU_EFLAGS_MASK_AMD_K7_ATHLON_XP; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_AMD); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K7_ATHLON_XP); + np2cfg.cpu_brandid = CPU_BRAND_ID_AMD_K7_ATHLON_XP; + break; + case 255: // 全機能使用可能 + np2cfg.cpu_family = 0; + np2cfg.cpu_model = 0; + np2cfg.cpu_stepping = 0; + np2cfg.cpu_feature = 0; + np2cfg.cpu_feature_ecx = 0; + np2cfg.cpu_feature_ex = 0; + np2cfg.cpu_eflags_mask = 0; + strcpy(np2cfg.cpu_vendor, CPU_VENDOR_NEKOPRO); + strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_NEKOPRO); + np2cfg.cpu_brandid = 0; + break; + default: + return 0; + } +} +#endif + diff --git a/pccore.h b/pccore.h old mode 100755 new mode 100644 index c4a22a66..09c92519 --- a/pccore.h +++ b/pccore.h @@ -1,475 +1,475 @@ -/** - * @file pccore.h - * @brief Interface of the core - */ - -#pragma once - -#include - -enum { - PCBASECLOCK25 = 2457600, - PCBASECLOCK20 = 1996800 -}; - -enum { - CPUMODE_8MHZ = 0x20, - - PCMODEL_VF = 0, - PCMODEL_VM = 1, - PCMODEL_VX = 2, - PCMODELMASK = 0x3f, - PCMODEL_PC9821 = 0x40, - PCMODEL_EPSON = 0x80, - - PCHDD_SASI = 0x01, - PCHDD_SCSI = 0x02, - PCHDD_IDE = 0x04, - - PCROM_BIOS = 0x01, - PCROM_SOUND = 0x02, - PCROM_SASI = 0x04, - PCROM_SCSI = 0x08, - PCROM_BIOS9821 = 0x10, - - PCCBUS_PC9861K = 0x0001, - PCCBUS_MPU98 = 0x0002, - PCCBUS_SMPU98 = 0x0004 -}; - -/** - * Sound ID - */ -enum tagSoundId -{ - SOUNDID_NONE = 0, //!< No boards - SOUNDID_PC_9801_14 = 0x01, //!< PC-9801-14 - SOUNDID_PC_9801_26K = 0x02, //!< PC-9801-26K - SOUNDID_PC_9801_86 = 0x04, //!< PC-9801-86 - SOUNDID_PC_9801_86_26K = 0x06, //!< PC-9801-86 + 26K - SOUNDID_PC_9801_118 = 0x08, //!< PC-9801-118 - SOUNDID_PC_9801_86_ADPCM = 0x14, //!< PC-9801-86 with ADPCM - SOUNDID_SPEAKBOARD = 0x20, //!< Speak board - SOUNDID_86_SPEAKBOARD = 0x24, //!< PC-9801-86 + Speak board - SOUNDID_SPARKBOARD = 0x40, //!< Spark board -#if defined(SUPPORT_SOUND_SB16) - SOUNDID_SB16 = 0x41, //!< Sound Blaster 16 - SOUNDID_PC_9801_86_WSS_SB16 = 0x42, //!< PC-9801-86 + Mate-X PCM(B460) + Sound Blaster 16 - SOUNDID_WSS_SB16 = 0x43, //!< Mate-X PCM(B460) + Sound Blaster 16 - SOUNDID_PC_9801_86_SB16 = 0x44, //!< PC-9801-86 + Sound Blaster 16 - SOUNDID_PC_9801_118_SB16 = 0x45, //!< PC-9801-118 + Sound Blaster 16 - SOUNDID_PC_9801_86_118_SB16 = 0x46, //!< PC-9801-86 + PC-9801-118(B460) + Sound Blaster 16 -#endif - SOUNDID_MATE_X_PCM = 0x60, //!< Mate-X PCM - SOUNDID_PC_9801_86_WSS = 0x64, //!< PC-9801-86 + Mate-X PCM(B460) - SOUNDID_PC_9801_86_118 = 0x68, //!< PC-9801-86 + PC-9801-118(B460) - SOUNDID_WAVESTAR = 0x70, //!< Wave Star - SOUNDID_AMD98 = 0x80, //!< AMD-98 - SOUNDID_SOUNDORCHESTRA = 0x32, //!< SOUND ORCHESTRA - SOUNDID_SOUNDORCHESTRAV = 0x82, //!< SOUND ORCHESTRA-V - SOUNDID_LITTLEORCHESTRAL = 0x22, //!< LITTLE ORCHESTRA L - SOUNDID_MMORCHESTRA = 0x26, //!< MULTIMEDIA ORCHESTRA - -#if defined(SUPPORT_PX) - SOUNDID_PX1 = 0x30, - SOUNDID_PX2 = 0x50, -#endif - - SOUNDID_INVALID = 0xff, /*!< for new statesave checker */ -}; -typedef enum tagSoundId SOUNDID; - -enum { - FPU_TYPE_SOFTFLOAT = 0, /* Berkeley SoftFloat */ - FPU_TYPE_DOSBOX = 1, /* DOSBox FPU */ - FPU_TYPE_DOSBOX2 = 2 /* DOSBox FPU+INT64 */ -}; - -/** - * @brief config - */ -struct tagNP2Config -{ - // エミュレート中によく参照される奴 - UINT8 uPD72020; - UINT8 DISPSYNC; - UINT8 RASTER; - UINT8 realpal; - UINT8 LCD_MODE; - UINT8 skipline; - UINT16 skiplight; - - UINT8 KEY_MODE; - UINT8 XSHIFT; - UINT8 BTN_RAPID; - UINT8 BTN_MODE; - - UINT8 dipsw[3]; - UINT8 MOUSERAPID; - - UINT8 calendar; - UINT8 usefd144; - UINT8 wait[6]; - - UINT8 davolume; - UINT8 modelnum; - - UINT8 timerfix; - -#if defined(SUPPORT_ASYNC_CPU) - UINT8 asynccpu; // 非同期CPUモード有効 - UINT8 asynclvl; // 非同期CPUモード調整レベル(0:制御最弱〜100:アグレッシブ) -#endif - UINT8 consttsc; // RDTSCをAsyncクロック変更によらず一定間隔にする -#if defined(SUPPORT_IDEIO) - UINT8 idebaddr; // IDE BIOS アドレス(デフォルト:D8h(D8000h)) -#endif - - // リセット時とかあんまり参照されない奴 - OEMCHAR model[8]; - UINT baseclock; - UINT multiple; - - UINT8 usebios; - - UINT8 memsw[8]; - - UINT8 ITF_WORK; -#if defined(SUPPORT_LARGE_MEMORY) - UINT16 EXTMEM; -#else - UINT8 EXTMEM; -#endif - UINT8 grcg; - UINT8 color16; - UINT32 BG_COLOR; - UINT32 FG_COLOR; - - UINT32 samplingrate; - UINT16 delayms; - UINT8 SOUND_SW; - UINT8 snd_x; - - UINT8 snd14opt[3]; - UINT8 snd26opt; - UINT8 snd86opt; - UINT8 spbopt; - UINT8 spb_vrc; // ver0.30 - UINT8 spb_vrl; // ver0.30 - UINT8 spb_x; // ver0.30 - - UINT16 snd118io; - UINT8 snd118id; - UINT8 snd118dma; - UINT8 snd118irqf; - UINT8 snd118irqp; - UINT8 snd118irqm; - UINT8 snd118rom; - - UINT8 sndwssid; - UINT8 sndwssdma; - UINT8 sndwssirq; - -#if defined(SUPPORT_SOUND_SB16) - UINT8 sndsb16io; - UINT8 sndsb16dma; - UINT8 sndsb16irq; - UINT8 sndsb16at; -#endif /* SUPPORT_SOUND_SB16 */ - - UINT8 BEEP_VOL; - UINT8 vol14[6]; - UINT8 vol_master; - UINT8 vol_fm; - UINT8 vol_ssg; - UINT8 vol_adpcm; - UINT8 vol_pcm; - UINT8 vol_rhythm; - UINT8 vol_midi; - - UINT8 mpuenable; - UINT8 mpuopt; - UINT8 mpu_at; - -#if defined(SUPPORT_SMPU98) - UINT8 smpuenable; - UINT8 smpuopt; - UINT8 smpumuteB; -#endif /* SUPPORT_SMPU98 */ - - UINT8 pc9861enable; - UINT8 pc9861sw[3]; - UINT8 pc9861jmp[6]; - -#if defined(SUPPORT_FMGEN) - UINT8 usefmgen; -#endif /* SUPPORT_FMGEN */ - - UINT8 fddequip; - UINT8 MOTOR; - UINT8 MOTORVOL; - UINT8 PROTECTMEM; - UINT8 hdrvacc; - UINT8 hdrvenable; - UINT8 hdrvntenable; - - UINT8 savefddfile; // ver0.86w rev20 - OEMCHAR fddfile[4][MAX_PATH]; // ver0.86w rev20 - -#if defined(SUPPORT_IDEIO) - OEMCHAR sasihdd[4][MAX_PATH]; // ver0.86w - UINT8 idetype[4]; // ver0.86w - OEMCHAR idecd[4][MAX_PATH]; // ver0.85w - UINT8 idebios; // ver0.86w rev20 - UINT8 autoidebios; // ver0.86w rev36 - UINT32 iderwait; // IDE読み取りの割り込み遅延時間(clock)。 np21w ver0.86 rev19 - UINT32 idewwait; // IDE書き込みの割り込み遅延時間(clock)。 np21w ver0.86 rev18 - UINT32 idemwait; // IDE BIOSがある場合の割り込み遅延最小値 np21w ver0.86 rev26 廃止 - UINT8 savecdfile; - UINT8 useasynccd; - UINT8 allowcdtraycmd; - UINT8 useasynchd; -#else - OEMCHAR sasihdd[2][MAX_PATH]; // ver0.74 -#endif -#if defined(SUPPORT_SCSI) - OEMCHAR scsihdd[4][MAX_PATH]; // ver0.74 -#endif - OEMCHAR fontfile[MAX_PATH]; - OEMCHAR biospath[MAX_PATH]; - OEMCHAR hdrvroot[MAX_PATH]; - -#ifdef SUPPORT_NET - OEMCHAR np2nettap[MAX_PATH]; - UINT8 np2netpmm; -#endif -#ifdef SUPPORT_LGY98 - UINT8 uselgy98; - UINT16 lgy98io; - UINT8 lgy98irq; - UINT8 lgy98mac[6]; -#endif -#ifdef SUPPORT_WAB - UINT8 wabasw; -#endif -#ifdef SUPPORT_CL_GD5430 - UINT8 usegd5430; - UINT16 gd5430type; - UINT8 gd5430fakecur; - UINT8 gd5430melofs; - UINT8 ga98nb_bigscrn_ex; -#endif -#if defined(SUPPORT_VGA_MODEX) - UINT8 usemodex; -#endif -#if defined(SUPPORT_GPIB) - UINT8 usegpib; // GPIB使用 - UINT8 gpibirq; // GPIB IRQ - UINT8 gpibmode; // GPIB Master/Slave - UINT8 gpibaddr; // GPIB Address - UINT8 gpibexio; // GPIB custom I/O port base -#endif -#if defined(SUPPORT_PCI) - UINT8 usepci; // PCI Bus使用 - UINT8 pci_bios32; // BIOS32使用 - UINT8 pci_pcmc; // PCMC選択 -#endif - -#if defined(SUPPORT_STATSAVE) - UINT8 statsave; -#endif - UINT8 fddrive3; - UINT8 fddrive4; - - UINT8 winntfix; - UINT16 sysiomsk; - - UINT8 memchkmx; - UINT8 sbeeplen; - UINT8 sbeepadj; - - UINT8 biosioemu; - - char cpu_vendor[16]; // ベンダー(12byte) - UINT32 cpu_family; // ファミリ - UINT32 cpu_model; // モデル - UINT32 cpu_stepping; // ステッピング - UINT32 cpu_feature; // 機能フラグ - UINT32 cpu_feature_ex; // 拡張機能フラグ - char cpu_brandstring[64]; // ブランド名(48byte) - OEMCHAR cpu_vendor_o[16]; // ベンダー(12byte)OEMCHAR - OEMCHAR cpu_brandstring_o[64]; // ブランド名(48byte)OEMCHAR - UINT32 cpu_brandid; // ブランドID - UINT32 cpu_feature_ecx; // ECX機能フラグ - UINT32 cpu_feature_ex_ecx; // ECX拡張機能フラグ - UINT32 cpu_eflags_mask; // EFLAGSマスク - - UINT8 fpu_type; // FPU種類(0=Berkeley SoftFloat, 1=DOSBox FPU, 2=DOSBox FPU+INT64) - -#if defined(SUPPORT_FAST_MEMORYCHECK) - UINT8 memcheckspeed; // メモリチェック速度 -#endif - - UINT8 useram_d; // EPSONでなくてもD0000h-DFFFFhをRAMに(ただしIDE BIOS D8000h-DBFFFhは駄目) - UINT8 usepegcplane; // PEGC プレーンモードサポート - - UINT8 usecdecc; // CD-ROM EDC/ECC エミュレーションサポート - UINT8 cddtskip; // CD-ROM オーディオ再生時にデータトラックをスキップ - -#if defined(SUPPORT_GAMEPORT) - UINT8 gameport; // SB16や118音源のゲームポートを使用する - UINT8 analogjoy; // ゲームポートをアナログジョイスティックにする -#endif - UINT8 allowMOVCS; // mov cs,xx命令の実行を許可する(8086) - UINT8 usetexthook; // Text Hookを有効にする(海外向け) - UINT8 rascsi92; // 92互換でRaSCSI形式(*.HDN)を読む - UINT8 nbeepofs; // BEEPの出力オフセットを消す - - SINT64 cal_vofs; // 仮想カレンダ時刻オフセット(秒) - -#if defined(SUPPORT_NP2SCSI) - UINT8 usenp2stor; // np2 SCSIを使用する -#endif - - UINT32 emuspeed; // emulation speed(%) - - OEMCHAR fontface[256]; - - UINT8 slowmous; // 4ビット切り捨ての低速マウスを使う - -#if defined(SUPPORT_DEBUGSS) - UINT8 debugss; -#endif - -#if defined(SUPPORT_VIDEOFILTER) - BOOL vf1_enable; - BOOL vf1_bmponly; - uint8_t vf1_pcount; - uint8_t vf1_pno; - uint8_t vf1_profile[3][2]; - uint32_t vf1_param[3][3][8]; -#endif - - // Setting Keyrepeat - UINT8 keyrepeat_enable; - UINT16 keyrepeat_delay; // Keyrepeat delay time(ms) - UINT16 keyrepeat_interval; // Keyrepeat interval time(ms) -}; -typedef struct tagNP2Config NP2CFG; /*!< The define of config */ - -typedef struct { - UINT32 baseclock; - UINT multiple; - - UINT8 cpumode; - UINT8 model; - UINT8 hddif; -#if defined(SUPPORT_LARGE_MEMORY) - UINT16 extmem; -#else - UINT8 extmem; -#endif - UINT8 dipsw[3]; // リセット時のDIPSW - UINT8 rom; - - SOUNDID sound; - UINT32 device; - - UINT32 realclock; - - UINT maxmultiple; -} PCCORE; - -enum { - COREEVENT_SHUT = 0, - COREEVENT_RESET = 1, - COREEVENT_EXIT = 2 -}; - -typedef struct -{ - UINT8 screenupdate; - UINT8 screendispflag; - UINT8 drawframe; - UINT8 hardwarereset; -} PCSTAT; - -#if defined(SUPPORT_ASYNC_CPU) -#define ASYNCCPU_CLOCKTABLE_MAX 64 -typedef struct -{ - UINT32 drawskip; - UINT32 nowait; - UINT32 lastTimingValue; - UINT32 asyncTarget; - int lastTimingValid; - int screendisp; - int threshold_down; - int threshold_up; - int clockUpTbl[ASYNCCPU_CLOCKTABLE_MAX]; - int clockDownTbl[ASYNCCPU_CLOCKTABLE_MAX]; -} ASYNCCPUSTAT; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -extern const OEMCHAR np2version[]; - -extern NP2CFG np2cfg; -extern PCCORE pccore; -extern PCSTAT pcstat; -extern UINT8 soundrenewal; -extern UINT drawcount; -#if defined(SUPPORT_FMGEN) -extern UINT8 enable_fmgen; -#endif /* SUPPORT_FMGEN */ - -#if defined(SUPPORT_ASYNC_CPU) -extern ASYNCCPUSTAT pccore_asynccpustat; -#endif - -void getbiospath(OEMCHAR *path, const OEMCHAR *fname, int maxlen); -void screendisp(NEVENTITEM item); -void screenvsync(NEVENTITEM item); - - -void pccore_cfgupdate(void); - -#if defined(SUPPORT_IA32_HAXM) -void pccore_mem_malloc(void); -void pccore_mem_free(void); -#endif -void pccore_init(void); -void pccore_term(void); -void pccore_reset(void); -void pccore_exec(BOOL draw); - -void pccore_postevent(UINT32 event); - -#ifdef SUPPORT_ASYNC_CPU -void pccore_asynccpu_initialize(void); -void pccore_asynccpu_updatesettings(int asyncLevel); - -extern int asynccpu_lateflag; -extern int asynccpu_fastflag; -extern LARGE_INTEGER asynccpu_lastclock; -extern LARGE_INTEGER asynccpu_clockpersec; -extern LARGE_INTEGER asynccpu_clockcount; -#endif - -#if defined(CPUCORE_IA32) -extern int GetCpuTypeIndex(); -extern int SetCpuTypeIndex(UINT index); -#endif - -#if defined(NP2_WIN) -extern BOOL QueryPerformanceCounter(LARGE_INTEGER* count); -extern BOOL QueryPerformanceFrequency(LARGE_INTEGER* freq); -#endif - -#ifdef __cplusplus -} -#endif - +/** + * @file pccore.h + * @brief Interface of the core + */ + +#pragma once + +#include + +enum { + PCBASECLOCK25 = 2457600, + PCBASECLOCK20 = 1996800 +}; + +enum { + CPUMODE_8MHZ = 0x20, + + PCMODEL_VF = 0, + PCMODEL_VM = 1, + PCMODEL_VX = 2, + PCMODELMASK = 0x3f, + PCMODEL_PC9821 = 0x40, + PCMODEL_EPSON = 0x80, + + PCHDD_SASI = 0x01, + PCHDD_SCSI = 0x02, + PCHDD_IDE = 0x04, + + PCROM_BIOS = 0x01, + PCROM_SOUND = 0x02, + PCROM_SASI = 0x04, + PCROM_SCSI = 0x08, + PCROM_BIOS9821 = 0x10, + + PCCBUS_PC9861K = 0x0001, + PCCBUS_MPU98 = 0x0002, + PCCBUS_SMPU98 = 0x0004 +}; + +/** + * Sound ID + */ +enum tagSoundId +{ + SOUNDID_NONE = 0, //!< No boards + SOUNDID_PC_9801_14 = 0x01, //!< PC-9801-14 + SOUNDID_PC_9801_26K = 0x02, //!< PC-9801-26K + SOUNDID_PC_9801_86 = 0x04, //!< PC-9801-86 + SOUNDID_PC_9801_86_26K = 0x06, //!< PC-9801-86 + 26K + SOUNDID_PC_9801_118 = 0x08, //!< PC-9801-118 + SOUNDID_PC_9801_86_ADPCM = 0x14, //!< PC-9801-86 with ADPCM + SOUNDID_SPEAKBOARD = 0x20, //!< Speak board + SOUNDID_86_SPEAKBOARD = 0x24, //!< PC-9801-86 + Speak board + SOUNDID_SPARKBOARD = 0x40, //!< Spark board +#if defined(SUPPORT_SOUND_SB16) + SOUNDID_SB16 = 0x41, //!< Sound Blaster 16 + SOUNDID_PC_9801_86_WSS_SB16 = 0x42, //!< PC-9801-86 + Mate-X PCM(B460) + Sound Blaster 16 + SOUNDID_WSS_SB16 = 0x43, //!< Mate-X PCM(B460) + Sound Blaster 16 + SOUNDID_PC_9801_86_SB16 = 0x44, //!< PC-9801-86 + Sound Blaster 16 + SOUNDID_PC_9801_118_SB16 = 0x45, //!< PC-9801-118 + Sound Blaster 16 + SOUNDID_PC_9801_86_118_SB16 = 0x46, //!< PC-9801-86 + PC-9801-118(B460) + Sound Blaster 16 +#endif + SOUNDID_MATE_X_PCM = 0x60, //!< Mate-X PCM + SOUNDID_PC_9801_86_WSS = 0x64, //!< PC-9801-86 + Mate-X PCM(B460) + SOUNDID_PC_9801_86_118 = 0x68, //!< PC-9801-86 + PC-9801-118(B460) + SOUNDID_WAVESTAR = 0x70, //!< Wave Star + SOUNDID_AMD98 = 0x80, //!< AMD-98 + SOUNDID_SOUNDORCHESTRA = 0x32, //!< SOUND ORCHESTRA + SOUNDID_SOUNDORCHESTRAV = 0x82, //!< SOUND ORCHESTRA-V + SOUNDID_LITTLEORCHESTRAL = 0x22, //!< LITTLE ORCHESTRA L + SOUNDID_MMORCHESTRA = 0x26, //!< MULTIMEDIA ORCHESTRA + +#if defined(SUPPORT_PX) + SOUNDID_PX1 = 0x30, + SOUNDID_PX2 = 0x50, +#endif + + SOUNDID_INVALID = 0xff, /*!< for new statesave checker */ +}; +typedef enum tagSoundId SOUNDID; + +enum { + FPU_TYPE_SOFTFLOAT = 0, /* Berkeley SoftFloat */ + FPU_TYPE_DOSBOX = 1, /* DOSBox FPU */ + FPU_TYPE_DOSBOX2 = 2 /* DOSBox FPU+INT64 */ +}; + +/** + * @brief config + */ +struct tagNP2Config +{ + // エミュレート中によく参照される奴 + UINT8 uPD72020; + UINT8 DISPSYNC; + UINT8 RASTER; + UINT8 realpal; + UINT8 LCD_MODE; + UINT8 skipline; + UINT16 skiplight; + + UINT8 KEY_MODE; + UINT8 XSHIFT; + UINT8 BTN_RAPID; + UINT8 BTN_MODE; + + UINT8 dipsw[3]; + UINT8 MOUSERAPID; + + UINT8 calendar; + UINT8 usefd144; + UINT8 wait[6]; + + UINT8 davolume; + UINT8 modelnum; + + UINT8 timerfix; + +#if defined(SUPPORT_ASYNC_CPU) + UINT8 asynccpu; // 非同期CPUモード有効 + UINT8 asynclvl; // 非同期CPUモード調整レベル(0:制御最弱〜100:アグレッシブ) +#endif + UINT8 consttsc; // RDTSCをAsyncクロック変更によらず一定間隔にする +#if defined(SUPPORT_IDEIO) + UINT8 idebaddr; // IDE BIOS アドレス(デフォルト:D8h(D8000h)) +#endif + + // リセット時とかあんまり参照されない奴 + OEMCHAR model[8]; + UINT baseclock; + UINT multiple; + + UINT8 usebios; + + UINT8 memsw[8]; + + UINT8 ITF_WORK; +#if defined(SUPPORT_LARGE_MEMORY) + UINT16 EXTMEM; +#else + UINT8 EXTMEM; +#endif + UINT8 grcg; + UINT8 color16; + UINT32 BG_COLOR; + UINT32 FG_COLOR; + + UINT32 samplingrate; + UINT16 delayms; + UINT8 SOUND_SW; + UINT8 snd_x; + + UINT8 snd14opt[3]; + UINT8 snd26opt; + UINT8 snd86opt; + UINT8 spbopt; + UINT8 spb_vrc; // ver0.30 + UINT8 spb_vrl; // ver0.30 + UINT8 spb_x; // ver0.30 + + UINT16 snd118io; + UINT8 snd118id; + UINT8 snd118dma; + UINT8 snd118irqf; + UINT8 snd118irqp; + UINT8 snd118irqm; + UINT8 snd118rom; + + UINT8 sndwssid; + UINT8 sndwssdma; + UINT8 sndwssirq; + +#if defined(SUPPORT_SOUND_SB16) + UINT8 sndsb16io; + UINT8 sndsb16dma; + UINT8 sndsb16irq; + UINT8 sndsb16at; +#endif /* SUPPORT_SOUND_SB16 */ + + UINT8 BEEP_VOL; + UINT8 vol14[6]; + UINT8 vol_master; + UINT8 vol_fm; + UINT8 vol_ssg; + UINT8 vol_adpcm; + UINT8 vol_pcm; + UINT8 vol_rhythm; + UINT8 vol_midi; + + UINT8 mpuenable; + UINT8 mpuopt; + UINT8 mpu_at; + +#if defined(SUPPORT_SMPU98) + UINT8 smpuenable; + UINT8 smpuopt; + UINT8 smpumuteB; +#endif /* SUPPORT_SMPU98 */ + + UINT8 pc9861enable; + UINT8 pc9861sw[3]; + UINT8 pc9861jmp[6]; + +#if defined(SUPPORT_FMGEN) + UINT8 usefmgen; +#endif /* SUPPORT_FMGEN */ + + UINT8 fddequip; + UINT8 MOTOR; + UINT8 MOTORVOL; + UINT8 PROTECTMEM; + UINT8 hdrvacc; + UINT8 hdrvenable; + UINT8 hdrvntenable; + + UINT8 savefddfile; // ver0.86w rev20 + OEMCHAR fddfile[4][MAX_PATH]; // ver0.86w rev20 + +#if defined(SUPPORT_IDEIO) + OEMCHAR sasihdd[4][MAX_PATH]; // ver0.86w + UINT8 idetype[4]; // ver0.86w + OEMCHAR idecd[4][MAX_PATH]; // ver0.85w + UINT8 idebios; // ver0.86w rev20 + UINT8 autoidebios; // ver0.86w rev36 + UINT32 iderwait; // IDE読み取りの割り込み遅延時間(clock)。 np21w ver0.86 rev19 + UINT32 idewwait; // IDE書き込みの割り込み遅延時間(clock)。 np21w ver0.86 rev18 + UINT32 idemwait; // IDE BIOSがある場合の割り込み遅延最小値 np21w ver0.86 rev26 廃止 + UINT8 savecdfile; + UINT8 useasynccd; + UINT8 allowcdtraycmd; + UINT8 useasynchd; +#else + OEMCHAR sasihdd[2][MAX_PATH]; // ver0.74 +#endif +#if defined(SUPPORT_SCSI) + OEMCHAR scsihdd[4][MAX_PATH]; // ver0.74 +#endif + OEMCHAR fontfile[MAX_PATH]; + OEMCHAR biospath[MAX_PATH]; + OEMCHAR hdrvroot[MAX_PATH]; + +#ifdef SUPPORT_NET + OEMCHAR np2nettap[MAX_PATH]; + UINT8 np2netpmm; +#endif +#ifdef SUPPORT_LGY98 + UINT8 uselgy98; + UINT16 lgy98io; + UINT8 lgy98irq; + UINT8 lgy98mac[6]; +#endif +#ifdef SUPPORT_WAB + UINT8 wabasw; +#endif +#ifdef SUPPORT_CL_GD5430 + UINT8 usegd5430; + UINT16 gd5430type; + UINT8 gd5430fakecur; + UINT8 gd5430melofs; + UINT8 ga98nb_bigscrn_ex; +#endif +#if defined(SUPPORT_VGA_MODEX) + UINT8 usemodex; +#endif +#if defined(SUPPORT_GPIB) + UINT8 usegpib; // GPIB使用 + UINT8 gpibirq; // GPIB IRQ + UINT8 gpibmode; // GPIB Master/Slave + UINT8 gpibaddr; // GPIB Address + UINT8 gpibexio; // GPIB custom I/O port base +#endif +#if defined(SUPPORT_PCI) + UINT8 usepci; // PCI Bus使用 + UINT8 pci_bios32; // BIOS32使用 + UINT8 pci_pcmc; // PCMC選択 +#endif + +#if defined(SUPPORT_STATSAVE) + UINT8 statsave; +#endif + UINT8 fddrive3; + UINT8 fddrive4; + + UINT8 winntfix; + UINT16 sysiomsk; + + UINT8 memchkmx; + UINT8 sbeeplen; + UINT8 sbeepadj; + + UINT8 biosioemu; + + char cpu_vendor[16]; // ベンダー(12byte) + UINT32 cpu_family; // ファミリ + UINT32 cpu_model; // モデル + UINT32 cpu_stepping; // ステッピング + UINT32 cpu_feature; // 機能フラグ + UINT32 cpu_feature_ex; // 拡張機能フラグ + char cpu_brandstring[64]; // ブランド名(48byte) + OEMCHAR cpu_vendor_o[16]; // ベンダー(12byte)OEMCHAR + OEMCHAR cpu_brandstring_o[64]; // ブランド名(48byte)OEMCHAR + UINT32 cpu_brandid; // ブランドID + UINT32 cpu_feature_ecx; // ECX機能フラグ + UINT32 cpu_feature_ex_ecx; // ECX拡張機能フラグ + UINT32 cpu_eflags_mask; // EFLAGSマスク + + UINT8 fpu_type; // FPU種類(0=Berkeley SoftFloat, 1=DOSBox FPU, 2=DOSBox FPU+INT64) + +#if defined(SUPPORT_FAST_MEMORYCHECK) + UINT8 memcheckspeed; // メモリチェック速度 +#endif + + UINT8 useram_d; // EPSONでなくてもD0000h-DFFFFhをRAMに(ただしIDE BIOS D8000h-DBFFFhは駄目) + UINT8 usepegcplane; // PEGC プレーンモードサポート + + UINT8 usecdecc; // CD-ROM EDC/ECC エミュレーションサポート + UINT8 cddtskip; // CD-ROM オーディオ再生時にデータトラックをスキップ + +#if defined(SUPPORT_GAMEPORT) + UINT8 gameport; // SB16や118音源のゲームポートを使用する + UINT8 analogjoy; // ゲームポートをアナログジョイスティックにする +#endif + UINT8 allowMOVCS; // mov cs,xx命令の実行を許可する(8086) + UINT8 usetexthook; // Text Hookを有効にする(海外向け) + UINT8 rascsi92; // 92互換でRaSCSI形式(*.HDN)を読む + UINT8 nbeepofs; // BEEPの出力オフセットを消す + + SINT64 cal_vofs; // 仮想カレンダ時刻オフセット(秒) + +#if defined(SUPPORT_NP2SCSI) + UINT8 usenp2stor; // np2 SCSIを使用する +#endif + + UINT32 emuspeed; // emulation speed(%) + + OEMCHAR fontface[256]; + + UINT8 slowmous; // 4ビット切り捨ての低速マウスを使う + +#if defined(SUPPORT_DEBUGSS) + UINT8 debugss; +#endif + +#if defined(SUPPORT_VIDEOFILTER) + BOOL vf1_enable; + BOOL vf1_bmponly; + uint8_t vf1_pcount; + uint8_t vf1_pno; + uint8_t vf1_profile[3][2]; + uint32_t vf1_param[3][3][8]; +#endif + + // Setting Keyrepeat + UINT8 keyrepeat_enable; + UINT16 keyrepeat_delay; // Keyrepeat delay time(ms) + UINT16 keyrepeat_interval; // Keyrepeat interval time(ms) +}; +typedef struct tagNP2Config NP2CFG; /*!< The define of config */ + +typedef struct { + UINT32 baseclock; + UINT multiple; + + UINT8 cpumode; + UINT8 model; + UINT8 hddif; +#if defined(SUPPORT_LARGE_MEMORY) + UINT16 extmem; +#else + UINT8 extmem; +#endif + UINT8 dipsw[3]; // リセット時のDIPSW + UINT8 rom; + + SOUNDID sound; + UINT32 device; + + UINT32 realclock; + + UINT maxmultiple; +} PCCORE; + +enum { + COREEVENT_SHUT = 0, + COREEVENT_RESET = 1, + COREEVENT_EXIT = 2 +}; + +typedef struct +{ + UINT8 screenupdate; + UINT8 screendispflag; + UINT8 drawframe; + UINT8 hardwarereset; +} PCSTAT; + +#if defined(SUPPORT_ASYNC_CPU) +#define ASYNCCPU_CLOCKTABLE_MAX 64 +typedef struct +{ + UINT32 drawskip; + UINT32 nowait; + UINT32 lastTimingValue; + UINT32 asyncTarget; + int lastTimingValid; + int screendisp; + int threshold_down; + int threshold_up; + int clockUpTbl[ASYNCCPU_CLOCKTABLE_MAX]; + int clockDownTbl[ASYNCCPU_CLOCKTABLE_MAX]; +} ASYNCCPUSTAT; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern const OEMCHAR np2version[]; + +extern NP2CFG np2cfg; +extern PCCORE pccore; +extern PCSTAT pcstat; +extern UINT8 soundrenewal; +extern UINT drawcount; +#if defined(SUPPORT_FMGEN) +extern UINT8 enable_fmgen; +#endif /* SUPPORT_FMGEN */ + +#if defined(SUPPORT_ASYNC_CPU) +extern ASYNCCPUSTAT pccore_asynccpustat; +#endif + +void getbiospath(OEMCHAR *path, const OEMCHAR *fname, int maxlen); +void screendisp(NEVENTITEM item); +void screenvsync(NEVENTITEM item); + + +void pccore_cfgupdate(void); + +#if defined(SUPPORT_IA32_HAXM) +void pccore_mem_malloc(void); +void pccore_mem_free(void); +#endif +void pccore_init(void); +void pccore_term(void); +void pccore_reset(void); +void pccore_exec(BOOL draw); + +void pccore_postevent(UINT32 event); + +#ifdef SUPPORT_ASYNC_CPU +void pccore_asynccpu_initialize(void); +void pccore_asynccpu_updatesettings(int asyncLevel); + +extern int asynccpu_lateflag; +extern int asynccpu_fastflag; +extern LARGE_INTEGER asynccpu_lastclock; +extern LARGE_INTEGER asynccpu_clockpersec; +extern LARGE_INTEGER asynccpu_clockcount; +#endif + +#if defined(CPUCORE_IA32) +extern int GetCpuTypeIndex(); +extern int SetCpuTypeIndex(UINT index); +#endif + +#if defined(NP2_WIN) +extern BOOL QueryPerformanceCounter(LARGE_INTEGER* count); +extern BOOL QueryPerformanceFrequency(LARGE_INTEGER* freq); +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/readme.txt b/readme.txt old mode 100755 new mode 100644 index 93489278..75c769b3 --- a/readme.txt +++ b/readme.txt @@ -1,269 +1,269 @@ -コンパイルに必要なもの -VST3_SDK(win9x/compiler.hから#define SUPPORT_VSTiを消せば省略可) -WinDDK(実CDドライブSUPPORT_PHYSICAL_CDDRV使用の際にコンパイル失敗する場合) -NASM -YASM(x64ビルドに必須) - -vs2010, vs2019プロジェクトのみメンテナンスされています。。 - -// ---- 定義 - - 最適化の為のメモリ使用量の抑制 - MEMOPTIMIZE = 0〜2 - - CPUにより以下の数値をセットされることを期待している - MEMOPTIMIZE未定義 … Celeron333A以降のセカンドキャッシュ有効機 - MEMOPTIMIZE = 0 … x86 - MEMOPTIMIZE = 1 … PowerPC等のデスクトップ用RISC - MEMOPTIMIZE = 2 … StrongARM等の組み込み用RISC - - - コンパイラの引き数・戻り値の最適化 - 引き数・戻り値でint型以外を指定した場合に、最適化が有効に働かない - コンパイラ向けの定義です。 - 通常は common.h の物を使用します。 - REG8 … UINT8型 / (sizeof(REG8) != 1)の場合 上位ビットを0fillする事 - REG16 … UINT16型 / (sizeof(REG16) != 2)の場合 上位ビットを0fillする事 -   いずれも値をセットする側が0fillし、参照側は0fillしたものと見なします。 - - - OSの言語の選択 - OSLANG_SJIS … Shift-JISの漢字コードを解釈する - OSLANG_EUC … EUCの漢字コードを解釈する - - OSLINEBREAK_CR … MacOS "\r" - OSLINEBREAK_LF … Unix "\n" - OSLINEBREAK_CRLF … Windows "\r\n" - - ※現在は以下のソースコード内で個別に設定しています。 - (Windowsが APIによって \r\nの場合と\nの場合があるので…) - ・common/_memory.c - ・debugsub.c - ・statsave.c - - (milstr.h選択用) - SUPPORT_ANK … ANK文字列操作関数をリンクする - SUPPORT_SJIS … SJIS文字列操作関数をリンクする - SUPPORT_EUC … EUC文字列操作関数をリンクする - - ※現在milstr.hですべて定義されたままになっています。 - ver0.73でmilstr.hの定義を外し compiler.hで指定した物となります。 - - - CPUCORE_IA32 -  IA32アーキテクチャを採用 -   i386cを使用する場合の注意点 -   ・CPU panic や警告表示時に msgbox() という API を使用します。 -    compiler.h あたりで適当に定義してください。 -   ・sigsetjmp(3), siglongjmp(3) が無いアーキテクチャは以下の define を -    compiler.h あたりに追加してください。 -    ---------------------------------------------------------------------- - #define sigjmp_buf jmp_buf - #define sigsetjmp(env, mask) setjmp(env) - #define siglongjmp(env, val) longjmp(env, val) -    ---------------------------------------------------------------------- - - CPUSTRUC_MEMWAIT -   cpucore構造体にメモリウェイト値を移動する(vramop) - - SUPPORT_CRT15KHZ -   水平走査15.98kHzをサポートする(DIPSW1-1) - - SUPPORT_CRT31KHZ -   水平走査31.47kHzをサポートする -   Fellowタイプはこれ - - SUPPORT_PC9821 -   PC-9821拡張のサポート -   当然ですが 386必須です。 -   また SUPPORT_CRT31KHZも必要です(ハイレゾBIOSを使用する為) - - SUPPORT_PC9861K -   PC-9861K(RS-232C拡張I/F)をサポート - - SUPPORT_IDEIO -   IDEの I/Oレベルでのサポート -   でも ATAのリード程度しかできない… - - SUPPORT_SASI -   SASI HDDをサポート -   定義がなければ常時IDEとして作動します。 - - SUPPORT_SCSI -   SCSI HDDをサポート…全然動かない - - SUPPORT_S98 -   S98ログを取得 - - SUPPORT_WAVEREC -  Soundレベルで waveファイルの書き出し関数をサポート -  但し書き出し中は サウンド出力が止まるので ほぼデバグ用 - - -// ---- screen - - PC-9801シリーズの画面サイズは標準で 641x400。 - VGAでは収まらないので 強制的にVGAに収める為に 画面横サイズは width + extend -とする。 - 8 < width < 640 - 8 < height < 480 - extend = 0 or 1 - -typedef struct { - BYTE *ptr; // VRAMポインタ - int xalign; // x方向オフセット - int yalign; // y方向オフセット - int width; // 横幅 - int height; // 縦幅 - UINT bpp; // スクリーン色ビット - int extend; // 幅拡張 -} SCRNSURF; - - サーフェスサイズは (width + extern) x height。 - - -const SCRNSURF *scrnmng_surflock(void); - 画面描画開始 - -void scrnmng_surfunlock(const SCRNSURF *surf); - 画面描画終了(このタイミングで描画) - - -void scrnmng_setwidth(int posx, int width) -void scrnmng_setextend(int extend) -void scrnmng_setheight(int posy, int height) - 描画サイズの変更 - ウィンドウサイズの変更する - フルスクリーン中であれば 表示領域を変更。 - SCRNSURFではこの値を返すようにする - posx, widthは 8の倍数 - -BOOL scrnmng_isfullscreen(void) … NP2コアでは未使用 - フルスクリーン状態の取得 - return: 非0でフルスクリーン - -BOOL scrnmng_haveextend(void) - 横幅状態の取得 - return: 非0で 横幅拡張サポート - -UINT scrnmng_getbpp(void) - スクリーン色ビット数の取得 - return: ビット数(8/16/24/32) - -void scrnmng_palchanged(void) - パレット更新の通知(8bitスクリーンサポート時のみ) - -RGB16 scrnmng_makepal16(RGB32 pal32) - RGB32から 16bit色を作成する。(16bitスクリーンサポート時のみ) - - - -// ---- sound - -NP2のサウンドデータは sound.cの以下の関数より取得 - const SINT32 *sound_pcmlock(void) - void sound_pcmunlock(const SINT32 *hdl) - - -SOUND_CRITICAL セマフォを入れる(see sndcsec.c) -SOUNDRESERVE 予約バッファのサイズ(ミリ秒) - サウンドを割り込み処理する場合の指定。 - 割り込みの最大延滞時間をSOUNDRESERVEで指定。 - (Win9xの場合、自前でリングバッファを見張るので 割り込み無し・指定時間通りに - サウンドライトが来るので、この処理は不要だった) - - -UINT soundmng_create(UINT rate, UINT ms) - サウンドストリームの確保 - input: rate サンプリングレート(11025/22050/44100) - ms サンプリングバッファサイズ(ミリ秒) - return: 獲得したバッファのサンプリング数 - - msに従う必要はない(SDLとかバッファサイズが限定されるので) - NP2のサウンドバッファ操作は 返り値のみを利用しています。 - - -void soundmng_destroy(void) - サウンドストリームの終了 - -void soundmng_reset(void) - サウンドストリームのリセット - -void soundmng_play(void) - サウンドストリームの再生 - -void soundmng_stop(void) - サウンドストリームの停止 - -void soundmng_sync(void) - サウンドストリームのコールバック - -void soundmng_setreverse(BOOL reverse) - サウンドストリームの出力反転設定 - input: reverse 非0で左右反転 - -BOOL soundmng_pcmplay(UINT num, BOOL loop) - PCM再生 - input: num PCM番号 - loop 非0でループ - -void soundmng_pcmstop(UINT num) - PCM停止 - input: num PCM番号 - - - -// ---- mouse - -BYTE mousemng_getstat(SINT16 *x, SINT16 *y, int clear) - マウスの状態取得 - input: clear 非0で 状態を取得後にカウンタをリセットする - output: *x clearからのx方向カウント - *y clearからのy方向カウント - return: bit7 左ボタンの状態 (0:押下) - bit5 右ボタンの状態 (0:押下) - - - -// ---- serial/parallel/midi - -COMMNG commng_create(UINT device) - シリアルオープン - input: デバイス番号 - return: ハンドル (失敗時NULL) - - -void commng_destroy(COMMNG hdl) - シリアルクローズ - input: ハンドル (失敗時NULL) - - - -// ---- joy stick - -BYTE joymng_getstat(void) - ジョイスティックの状態取得 - - return: bit0 上ボタンの状態 (0:押下) - bit1 下ボタンの状態 - bit2 左ボタンの状態 - bit3 右ボタンの状態 - bit4 連射ボタン1の状態 - bit5 連射ボタン2の状態 - bit6 ボタン1の状態 - bit7 ボタン2の状態 - - -// ---- - -void sysmng_update(UINT bitmap) - 状態が変化した場合にコールされる。 - -void sysmng_cpureset(void) - リセット時にコールされる - - - -void taskmng_exit(void) - システムを終了する。 - +コンパイルに必要なもの +VST3_SDK(win9x/compiler.hから#define SUPPORT_VSTiを消せば省略可) +WinDDK(実CDドライブSUPPORT_PHYSICAL_CDDRV使用の際にコンパイル失敗する場合) +NASM +YASM(x64ビルドに必須) + +vs2010, vs2019プロジェクトのみメンテナンスされています。。 + +// ---- 定義 + + 最適化の為のメモリ使用量の抑制 + MEMOPTIMIZE = 0〜2 + + CPUにより以下の数値をセットされることを期待している + MEMOPTIMIZE未定義 … Celeron333A以降のセカンドキャッシュ有効機 + MEMOPTIMIZE = 0 … x86 + MEMOPTIMIZE = 1 … PowerPC等のデスクトップ用RISC + MEMOPTIMIZE = 2 … StrongARM等の組み込み用RISC + + + コンパイラの引き数・戻り値の最適化 + 引き数・戻り値でint型以外を指定した場合に、最適化が有効に働かない + コンパイラ向けの定義です。 + 通常は common.h の物を使用します。 + REG8 … UINT8型 / (sizeof(REG8) != 1)の場合 上位ビットを0fillする事 + REG16 … UINT16型 / (sizeof(REG16) != 2)の場合 上位ビットを0fillする事 +   いずれも値をセットする側が0fillし、参照側は0fillしたものと見なします。 + + + OSの言語の選択 + OSLANG_SJIS … Shift-JISの漢字コードを解釈する + OSLANG_EUC … EUCの漢字コードを解釈する + + OSLINEBREAK_CR … MacOS "\r" + OSLINEBREAK_LF … Unix "\n" + OSLINEBREAK_CRLF … Windows "\r\n" + + ※現在は以下のソースコード内で個別に設定しています。 + (Windowsが APIによって \r\nの場合と\nの場合があるので…) + ・common/_memory.c + ・debugsub.c + ・statsave.c + + (milstr.h選択用) + SUPPORT_ANK … ANK文字列操作関数をリンクする + SUPPORT_SJIS … SJIS文字列操作関数をリンクする + SUPPORT_EUC … EUC文字列操作関数をリンクする + + ※現在milstr.hですべて定義されたままになっています。 + ver0.73でmilstr.hの定義を外し compiler.hで指定した物となります。 + + + CPUCORE_IA32 +  IA32アーキテクチャを採用 +   i386cを使用する場合の注意点 +   ・CPU panic や警告表示時に msgbox() という API を使用します。 +    compiler.h あたりで適当に定義してください。 +   ・sigsetjmp(3), siglongjmp(3) が無いアーキテクチャは以下の define を +    compiler.h あたりに追加してください。 +    ---------------------------------------------------------------------- + #define sigjmp_buf jmp_buf + #define sigsetjmp(env, mask) setjmp(env) + #define siglongjmp(env, val) longjmp(env, val) +    ---------------------------------------------------------------------- + + CPUSTRUC_MEMWAIT +   cpucore構造体にメモリウェイト値を移動する(vramop) + + SUPPORT_CRT15KHZ +   水平走査15.98kHzをサポートする(DIPSW1-1) + + SUPPORT_CRT31KHZ +   水平走査31.47kHzをサポートする +   Fellowタイプはこれ + + SUPPORT_PC9821 +   PC-9821拡張のサポート +   当然ですが 386必須です。 +   また SUPPORT_CRT31KHZも必要です(ハイレゾBIOSを使用する為) + + SUPPORT_PC9861K +   PC-9861K(RS-232C拡張I/F)をサポート + + SUPPORT_IDEIO +   IDEの I/Oレベルでのサポート +   でも ATAのリード程度しかできない… + + SUPPORT_SASI +   SASI HDDをサポート +   定義がなければ常時IDEとして作動します。 + + SUPPORT_SCSI +   SCSI HDDをサポート…全然動かない + + SUPPORT_S98 +   S98ログを取得 + + SUPPORT_WAVEREC +  Soundレベルで waveファイルの書き出し関数をサポート +  但し書き出し中は サウンド出力が止まるので ほぼデバグ用 + + +// ---- screen + + PC-9801シリーズの画面サイズは標準で 641x400。 + VGAでは収まらないので 強制的にVGAに収める為に 画面横サイズは width + extend +とする。 + 8 < width < 640 + 8 < height < 480 + extend = 0 or 1 + +typedef struct { + BYTE *ptr; // VRAMポインタ + int xalign; // x方向オフセット + int yalign; // y方向オフセット + int width; // 横幅 + int height; // 縦幅 + UINT bpp; // スクリーン色ビット + int extend; // 幅拡張 +} SCRNSURF; + + サーフェスサイズは (width + extern) x height。 + + +const SCRNSURF *scrnmng_surflock(void); + 画面描画開始 + +void scrnmng_surfunlock(const SCRNSURF *surf); + 画面描画終了(このタイミングで描画) + + +void scrnmng_setwidth(int posx, int width) +void scrnmng_setextend(int extend) +void scrnmng_setheight(int posy, int height) + 描画サイズの変更 + ウィンドウサイズの変更する + フルスクリーン中であれば 表示領域を変更。 + SCRNSURFではこの値を返すようにする + posx, widthは 8の倍数 + +BOOL scrnmng_isfullscreen(void) … NP2コアでは未使用 + フルスクリーン状態の取得 + return: 非0でフルスクリーン + +BOOL scrnmng_haveextend(void) + 横幅状態の取得 + return: 非0で 横幅拡張サポート + +UINT scrnmng_getbpp(void) + スクリーン色ビット数の取得 + return: ビット数(8/16/24/32) + +void scrnmng_palchanged(void) + パレット更新の通知(8bitスクリーンサポート時のみ) + +RGB16 scrnmng_makepal16(RGB32 pal32) + RGB32から 16bit色を作成する。(16bitスクリーンサポート時のみ) + + + +// ---- sound + +NP2のサウンドデータは sound.cの以下の関数より取得 + const SINT32 *sound_pcmlock(void) + void sound_pcmunlock(const SINT32 *hdl) + + +SOUND_CRITICAL セマフォを入れる(see sndcsec.c) +SOUNDRESERVE 予約バッファのサイズ(ミリ秒) + サウンドを割り込み処理する場合の指定。 + 割り込みの最大延滞時間をSOUNDRESERVEで指定。 + (Win9xの場合、自前でリングバッファを見張るので 割り込み無し・指定時間通りに + サウンドライトが来るので、この処理は不要だった) + + +UINT soundmng_create(UINT rate, UINT ms) + サウンドストリームの確保 + input: rate サンプリングレート(11025/22050/44100) + ms サンプリングバッファサイズ(ミリ秒) + return: 獲得したバッファのサンプリング数 + + msに従う必要はない(SDLとかバッファサイズが限定されるので) + NP2のサウンドバッファ操作は 返り値のみを利用しています。 + + +void soundmng_destroy(void) + サウンドストリームの終了 + +void soundmng_reset(void) + サウンドストリームのリセット + +void soundmng_play(void) + サウンドストリームの再生 + +void soundmng_stop(void) + サウンドストリームの停止 + +void soundmng_sync(void) + サウンドストリームのコールバック + +void soundmng_setreverse(BOOL reverse) + サウンドストリームの出力反転設定 + input: reverse 非0で左右反転 + +BOOL soundmng_pcmplay(UINT num, BOOL loop) + PCM再生 + input: num PCM番号 + loop 非0でループ + +void soundmng_pcmstop(UINT num) + PCM停止 + input: num PCM番号 + + + +// ---- mouse + +BYTE mousemng_getstat(SINT16 *x, SINT16 *y, int clear) + マウスの状態取得 + input: clear 非0で 状態を取得後にカウンタをリセットする + output: *x clearからのx方向カウント + *y clearからのy方向カウント + return: bit7 左ボタンの状態 (0:押下) + bit5 右ボタンの状態 (0:押下) + + + +// ---- serial/parallel/midi + +COMMNG commng_create(UINT device) + シリアルオープン + input: デバイス番号 + return: ハンドル (失敗時NULL) + + +void commng_destroy(COMMNG hdl) + シリアルクローズ + input: ハンドル (失敗時NULL) + + + +// ---- joy stick + +BYTE joymng_getstat(void) + ジョイスティックの状態取得 + + return: bit0 上ボタンの状態 (0:押下) + bit1 下ボタンの状態 + bit2 左ボタンの状態 + bit3 右ボタンの状態 + bit4 連射ボタン1の状態 + bit5 連射ボタン2の状態 + bit6 ボタン1の状態 + bit7 ボタン2の状態 + + +// ---- + +void sysmng_update(UINT bitmap) + 状態が変化した場合にコールされる。 + +void sysmng_cpureset(void) + リセット時にコールされる + + + +void taskmng_exit(void) + システムを終了する。 + diff --git a/romimage/BEEP.X86 b/romimage/BEEP.X86 index f5e40edc..595e24f0 100644 --- a/romimage/BEEP.X86 +++ b/romimage/BEEP.X86 @@ -1,35 +1,35 @@ -; BEEP TEST - -beeptestwait: mov al, 4 -beeptestwaitlp1:mov cx, 9000h - loop $ ; mine - dec al - jne beeptestwaitlp1 - ret - -BEEP_TEST: mov bx, 3e6h ; 2.0MHz - in al, 42h - test al, 20h - jne short beephzok - mov bx, 4cdh ; 2.5MHz -beephzok: mov al, 76h - out 77h, al ; BEEP setup mode#0 - - cmp byte ptr ds:[MACTYPE], 0 - jne short beep_Hzset - - call beep_Hzset - mov al, 6 - out 37h, al ; BEEP ON - call beeptestwait - shl bx, 1 - call beep_Hzset - call beeptestwait - mov al, 7 - out 37h, al ; BEEP OFF - shr bx, 1 -beep_Hzset: mov al, bl - out 73h, al - mov al, bh - out 73h, al - ret +; BEEP TEST + +beeptestwait: mov al, 4 +beeptestwaitlp1:mov cx, 9000h + loop $ ; mine + dec al + jne beeptestwaitlp1 + ret + +BEEP_TEST: mov bx, 3e6h ; 2.0MHz + in al, 42h + test al, 20h + jne short beephzok + mov bx, 4cdh ; 2.5MHz +beephzok: mov al, 76h + out 77h, al ; BEEP setup mode#0 + + cmp byte ptr ds:[MACTYPE], 0 + jne short beep_Hzset + + call beep_Hzset + mov al, 6 + out 37h, al ; BEEP ON + call beeptestwait + shl bx, 1 + call beep_Hzset + call beeptestwait + mov al, 7 + out 37h, al ; BEEP OFF + shr bx, 1 +beep_Hzset: mov al, bl + out 73h, al + mov al, bh + out 73h, al + ret diff --git a/romimage/BIOS/BIOSMAIN.X86 b/romimage/BIOS/BIOSMAIN.X86 index 8786d621..bdce0498 100644 --- a/romimage/BIOS/BIOSMAIN.X86 +++ b/romimage/BIOS/BIOSMAIN.X86 @@ -1,90 +1,90 @@ - -biosmain: sti - jmp biosinit - -biosmain2: test byte [0x0480], 2 - je short .cpuided - - CPU 286 - cli - mov al, 0x0e - out 0x37, al - smsw ax - push ax - push cs - push .reset - mov [0x0406], ss - mov [0x0404], sp - mov al, 0 - out 0xf0, al - hlt -.reset: pop ax - lmsw ax - mov [0x0486], dx - sti -.cpuided: - mov al, 0x0f - out 0x37, al - mov al, 0x0b - out 0x37, al - mov al, 0x09 - out 0x37, al - - CPU 8086 - mov word [0x04ac], 0x0c - call diskbios_set -diskbiosinit1: mov es, [0x04ae] - cmp word [es:0x0009], 0xaa55 - jne short nextparag1 - mov al, [bx] - or al, al - jne short nextparag1 - call calldiskbios -nextparag1: inc bx - inc byte [0x04af] - loop diskbiosinit1 - - mov word [0x04ac], 0x0f - call diskbiosinit2 - mov word [0x04ac], 0x12 - call diskbiosinit2 - -%if 0 ; ide test - mov ax, 0a0ah - mov word [0x04ac], 0x15 - call diskbiosinit2 -%else - db 9ah ; call far - dw 027e8h - dw 0fd80h -%endif - - in al, 31h - test al, 1 - jne short callbasic - int 1fh -callbasic: int 1eh - -diskbios_set: mov bx, 04d0h - mov cx, 0010h - mov word [0x04ae], 0xd000 - ret - -diskbiosinit2: call diskbios_set -.loop: test byte [bx], 0x40 - je short .skip - call calldiskbios -.skip: inc bx - inc byte [0x04af] - loop .loop - ret - -calldiskbios: push ax - push bx - push cx - call far [0x04ac] - pop cx - pop bx - pop ax - ret - + +biosmain: sti + jmp biosinit + +biosmain2: test byte [0x0480], 2 + je short .cpuided + + CPU 286 + cli + mov al, 0x0e + out 0x37, al + smsw ax + push ax + push cs + push .reset + mov [0x0406], ss + mov [0x0404], sp + mov al, 0 + out 0xf0, al + hlt +.reset: pop ax + lmsw ax + mov [0x0486], dx + sti +.cpuided: + mov al, 0x0f + out 0x37, al + mov al, 0x0b + out 0x37, al + mov al, 0x09 + out 0x37, al + + CPU 8086 + mov word [0x04ac], 0x0c + call diskbios_set +diskbiosinit1: mov es, [0x04ae] + cmp word [es:0x0009], 0xaa55 + jne short nextparag1 + mov al, [bx] + or al, al + jne short nextparag1 + call calldiskbios +nextparag1: inc bx + inc byte [0x04af] + loop diskbiosinit1 + + mov word [0x04ac], 0x0f + call diskbiosinit2 + mov word [0x04ac], 0x12 + call diskbiosinit2 + +%if 0 ; ide test + mov ax, 0a0ah + mov word [0x04ac], 0x15 + call diskbiosinit2 +%else + db 9ah ; call far + dw 027e8h + dw 0fd80h +%endif + + in al, 31h + test al, 1 + jne short callbasic + int 1fh +callbasic: int 1eh + +diskbios_set: mov bx, 04d0h + mov cx, 0010h + mov word [0x04ae], 0xd000 + ret + +diskbiosinit2: call diskbios_set +.loop: test byte [bx], 0x40 + je short .skip + call calldiskbios +.skip: inc bx + inc byte [0x04af] + loop .loop + ret + +calldiskbios: push ax + push bx + push cx + call far [0x04ac] + pop cx + pop bx + pop ax + ret + diff --git a/romimage/BIOS/EOI.X86 b/romimage/BIOS/EOI.X86 index 9b2fe84a..251f9234 100644 --- a/romimage/BIOS/EOI.X86 +++ b/romimage/BIOS/EOI.X86 @@ -1,25 +1,25 @@ - -sendeoi: push ax - call eoi - pop ax -biosnop: iret - -eoi: mov al, 0bh - out 00h, al - out 5fh, al - in al, 00h - test al, 80h - je short .master - mov al, 20h - out 08h, al - out 5fh, al - mov al, 0bh - out 08h, al - out 5fh, al - in al, 08h - test al, -1 - jne short .ed -.master: mov al, 20h - out 00h, al -.ed: ret - + +sendeoi: push ax + call eoi + pop ax +biosnop: iret + +eoi: mov al, 0bh + out 00h, al + out 5fh, al + in al, 00h + test al, 80h + je short .master + mov al, 20h + out 08h, al + out 5fh, al + mov al, 0bh + out 08h, al + out 5fh, al + in al, 08h + test al, -1 + jne short .ed +.master: mov al, 20h + out 00h, al +.ed: ret + diff --git a/romimage/BIOS/VECT02.X86 b/romimage/BIOS/VECT02.X86 index 3a0914f9..116715f0 100644 --- a/romimage/BIOS/VECT02.X86 +++ b/romimage/BIOS/VECT02.X86 @@ -1,35 +1,35 @@ - -perrbase db 'PARITY ERROR - BASE MEMORY', 0 -perrext db 'PARITY ERROR - EXTENDED MEMORY', 0 - -vect02: push ax - in al, 0x42 - test al, 0x06 - jne short .hlt - pop ax - iret -.hlt: mov si, perrbase - test al, 0x04 - jne short .disp - mov si, perrext -.disp: mov ax, 0xa000 - mov es, ax - xor di, di - cld - in al, 0x31 - and ax, byte 0x04 - shr ax, 1 - inc ax - mov dx, ax - -.loop: db FIXCS - lodsb - test al, -1 - je short .looped - mov byte [es:di + 0x2000], 0x43 - stosb - add di, dx - jmp short .loop -.looped: cli - hlt - + +perrbase db 'PARITY ERROR - BASE MEMORY', 0 +perrext db 'PARITY ERROR - EXTENDED MEMORY', 0 + +vect02: push ax + in al, 0x42 + test al, 0x06 + jne short .hlt + pop ax + iret +.hlt: mov si, perrbase + test al, 0x04 + jne short .disp + mov si, perrext +.disp: mov ax, 0xa000 + mov es, ax + xor di, di + cld + in al, 0x31 + and ax, byte 0x04 + shr ax, 1 + inc ax + mov dx, ax + +.loop: db FIXCS + lodsb + test al, -1 + je short .looped + mov byte [es:di + 0x2000], 0x43 + stosb + add di, dx + jmp short .loop +.looped: cli + hlt + diff --git a/romimage/BIOS/VECT08.X86 b/romimage/BIOS/VECT08.X86 index e4a8eb04..2821d87e 100644 --- a/romimage/BIOS/VECT08.X86 +++ b/romimage/BIOS/VECT08.X86 @@ -1,30 +1,30 @@ - -vect08: sti - push ax - push ds - xor ax, ax - mov ds, ax - dec word [0x058a] - pop ds - cli - je short .1 - mov al, 0x20 - out 0x00, al - out 0x5f, al - sti - mov ah, 0x03 - int 0x1c - pop ax - iret -.1: in al, 0x02 - or al, 0x01 - out 0x5f, al - out 0x02, al - mov al, 0x20 - out 0x00, al - out 0x5f, al - sti - pop ax - int 0x07 - iret - + +vect08: sti + push ax + push ds + xor ax, ax + mov ds, ax + dec word [0x058a] + pop ds + cli + je short .1 + mov al, 0x20 + out 0x00, al + out 0x5f, al + sti + mov ah, 0x03 + int 0x1c + pop ax + iret +.1: in al, 0x02 + or al, 0x01 + out 0x5f, al + out 0x02, al + mov al, 0x20 + out 0x00, al + out 0x5f, al + sti + pop ax + int 0x07 + iret + diff --git a/romimage/BIOS/VECT13.X86 b/romimage/BIOS/VECT13.X86 index b99a2d2d..4cc77304 100644 --- a/romimage/BIOS/VECT13.X86 +++ b/romimage/BIOS/VECT13.X86 @@ -1,101 +1,101 @@ - -vect13: push ax - call eoi - sti - cld - push cx - push dx - push di - push es - xor ax, ax - mov es, ax - mov dx, 0x90 - -.mainlp: in al, dx - test al, 0x10 - jne short .recvstat - mov ah, 0x08 - call fdc_sendcmd - jne short .mained - -.recvstat: call fdc_recvdat - jne short .mained - cmp al, 0x80 - je short .mained - - mov cx, 0x0003 - mov di, ax - and di, cx - shl di, cl - add di, 0x0564 - mov ah, 0x01 - and cl, al - shl ah, cl - -%if 0 - test al, 0x80 - je short .setfddi - test byte [es:0x055e], ah - je short .recvlp -.droplp: call fdc_recvforce - je short .droplp - jmp short .mainlp -%endif - -.setfddi: or byte [es:0x055e], ah -.recvlp: stosb - call fdc_recvforce - je short .recvlp - jmp short .mainlp - -.mained: pop es - pop di - pop dx - pop cx - pop ax - iret - - -fdc_sendcmd: xor cx, cx -.lp: in al, dx - and al, 0xd0 - cmp al, 0x80 - loopnz .lp - jne short .err - inc dx - inc dx - mov al, ah - out dx, al - dec dx - dec dx - xor dh, dh -.err: ret - -fdc_recvdat: xor cx, cx -.lp: in al, dx - and al, 0xd0 - cmp al, 0xd0 - loopne .lp - jne .err - inc dx - inc dx - in al, dx - dec dx - dec dx - xor dh, dh -.err: ret - -fdc_recvforce: mov cx, 32 -.lp: in al, dx - and al, 0xc0 - cmp al, 0xc0 - loopne .lp - jne short .err - inc dx - inc dx - in al, dx - dec dx - dec dx - xor dh, dh -.err: ret - + +vect13: push ax + call eoi + sti + cld + push cx + push dx + push di + push es + xor ax, ax + mov es, ax + mov dx, 0x90 + +.mainlp: in al, dx + test al, 0x10 + jne short .recvstat + mov ah, 0x08 + call fdc_sendcmd + jne short .mained + +.recvstat: call fdc_recvdat + jne short .mained + cmp al, 0x80 + je short .mained + + mov cx, 0x0003 + mov di, ax + and di, cx + shl di, cl + add di, 0x0564 + mov ah, 0x01 + and cl, al + shl ah, cl + +%if 0 + test al, 0x80 + je short .setfddi + test byte [es:0x055e], ah + je short .recvlp +.droplp: call fdc_recvforce + je short .droplp + jmp short .mainlp +%endif + +.setfddi: or byte [es:0x055e], ah +.recvlp: stosb + call fdc_recvforce + je short .recvlp + jmp short .mainlp + +.mained: pop es + pop di + pop dx + pop cx + pop ax + iret + + +fdc_sendcmd: xor cx, cx +.lp: in al, dx + and al, 0xd0 + cmp al, 0x80 + loopnz .lp + jne short .err + inc dx + inc dx + mov al, ah + out dx, al + dec dx + dec dx + xor dh, dh +.err: ret + +fdc_recvdat: xor cx, cx +.lp: in al, dx + and al, 0xd0 + cmp al, 0xd0 + loopne .lp + jne .err + inc dx + inc dx + in al, dx + dec dx + dec dx + xor dh, dh +.err: ret + +fdc_recvforce: mov cx, 32 +.lp: in al, dx + and al, 0xc0 + cmp al, 0xc0 + loopne .lp + jne short .err + inc dx + inc dx + in al, dx + dec dx + dec dx + xor dh, dh +.err: ret + diff --git a/romimage/BIOS/VECT1A.X86 b/romimage/BIOS/VECT1A.X86 index 394f317c..3a16df4f 100644 --- a/romimage/BIOS/VECT1A.X86 +++ b/romimage/BIOS/VECT1A.X86 @@ -1,14 +1,14 @@ - -vect1a: sti ; +00 - push ds ; +01 - push dx ; +02 - test ah, 0x10 ; +03 - jne short .prt ; +06 - call bios1a_cmt ; +08 - jmp short .ed ; +0b - times (0x19 - 0x0d) nop ; +0d -.prt: call bios1a_prt ; +19 (use dos6.20) -.ed: pop dx - pop ds - iret - + +vect1a: sti ; +00 + push ds ; +01 + push dx ; +02 + test ah, 0x10 ; +03 + jne short .prt ; +06 + call bios1a_cmt ; +08 + jmp short .ed ; +0b + times (0x19 - 0x0d) nop ; +0d +.prt: call bios1a_prt ; +19 (use dos6.20) +.ed: pop dx + pop ds + iret + diff --git a/romimage/BIOS/VECT1F.X86 b/romimage/BIOS/VECT1F.X86 index b6a5d6dd..6d48be27 100644 --- a/romimage/BIOS/VECT1F.X86 +++ b/romimage/BIOS/VECT1F.X86 @@ -1,86 +1,86 @@ - -vect1f: cmp ah, 0x91 - je short .91 - jmp bios1f - -.91err: push bp - mov bp, sp - or byte [bp+6], 1 - pop bp - iret - -.91: push ax - in al, 0x42 - test al, 0x02 - pop ax - jne short .91err - - CPU 286 - lgdt [es:bx+0x08] - lidt [es:bx+0x10] - - ; PIC-master - mov al, 0x11 - out 0x00, al - out 0x5f, al - mov al, dh - out 0x02, al - out 0x5f, al - mov al, 0x80 - out 0x02, al - out 0x5f, al - mov al, 0x1d - out 0x02, al - out 0x5f, al - - ; PIC-slave - mov al, 0x11 - out 0x08, al - out 0x5f, al - mov al, dl - out 0x0a, al - out 0x5f, al - mov al, 0x07 - out 0x0a, al - out 0x5f, al - mov al, 0x09 - out 0x0a, al - out 0x5f, al - - ; set descriptor - or word [es:bx+0x38], byte -1 - mov word [es:bx+0x3a], 0xd800 - mov word [es:bx+0x3c], 0x9b0f - and word [es:bx+0x3e], byte 0 - - ; set A20-23 - xor ax, ax - out 0xf2, al - push dx - mov dx, 0x0439 - mov al, 0x30 - out dx, al - pop dx - mov al, 0x0a - out 0x37, al - - mov al, 0x01 - lmsw ax - db 0xea - dw .protected - dw 0x0038 ; segment - -.protected: mov ax, 0x0018 - mov ds, ax - mov al, 0x20 - mov es, ax - mov al, 0x28 - mov ss, ax - pop bx - add sp, byte 4 - push byte 0x30 - push bx - retf - - CPU 8086 - + +vect1f: cmp ah, 0x91 + je short .91 + jmp bios1f + +.91err: push bp + mov bp, sp + or byte [bp+6], 1 + pop bp + iret + +.91: push ax + in al, 0x42 + test al, 0x02 + pop ax + jne short .91err + + CPU 286 + lgdt [es:bx+0x08] + lidt [es:bx+0x10] + + ; PIC-master + mov al, 0x11 + out 0x00, al + out 0x5f, al + mov al, dh + out 0x02, al + out 0x5f, al + mov al, 0x80 + out 0x02, al + out 0x5f, al + mov al, 0x1d + out 0x02, al + out 0x5f, al + + ; PIC-slave + mov al, 0x11 + out 0x08, al + out 0x5f, al + mov al, dl + out 0x0a, al + out 0x5f, al + mov al, 0x07 + out 0x0a, al + out 0x5f, al + mov al, 0x09 + out 0x0a, al + out 0x5f, al + + ; set descriptor + or word [es:bx+0x38], byte -1 + mov word [es:bx+0x3a], 0xd800 + mov word [es:bx+0x3c], 0x9b0f + and word [es:bx+0x3e], byte 0 + + ; set A20-23 + xor ax, ax + out 0xf2, al + push dx + mov dx, 0x0439 + mov al, 0x30 + out dx, al + pop dx + mov al, 0x0a + out 0x37, al + + mov al, 0x01 + lmsw ax + db 0xea + dw .protected + dw 0x0038 ; segment + +.protected: mov ax, 0x0018 + mov ds, ax + mov al, 0x20 + mov es, ax + mov al, 0x28 + mov ss, ax + pop bx + add sp, byte 4 + push byte 0x30 + push bx + retf + + CPU 8086 + diff --git a/romimage/BIOS/vect09.x86 b/romimage/BIOS/vect09.x86 index 7171dbac..72be374d 100644 --- a/romimage/BIOS/vect09.x86 +++ b/romimage/BIOS/vect09.x86 @@ -1,41 +1,41 @@ - -vect09: sti - push ax - push ds - xor ax, ax - mov ds, ax - in al, 0x43 - test al, 0x38 - jne short .err -.force: mov al, 0x16 - out 0x43, al - mov byte [0x0529], 0 - in al, 0x41 - mov ah, al - call bios09 -.eoi: pop ds - cli - mov al, 0x20 - out 0x00, al - cmp ah, 0x60 - je short .int6 - cmp ah, 0x61 - je short .int5 - pop ax - iret -.err: cmp byte [0x0529], 3 - jae short .force - inc byte [0x0529] - mov al, 0x14 - out 0x43, al - in al, 0x41 - jmp short .eoi - -.int5: pop ax - int 0x05 - iret - -.int6: pop ax - int 0x06 - iret - + +vect09: sti + push ax + push ds + xor ax, ax + mov ds, ax + in al, 0x43 + test al, 0x38 + jne short .err +.force: mov al, 0x16 + out 0x43, al + mov byte [0x0529], 0 + in al, 0x41 + mov ah, al + call bios09 +.eoi: pop ds + cli + mov al, 0x20 + out 0x00, al + cmp ah, 0x60 + je short .int6 + cmp ah, 0x61 + je short .int5 + pop ax + iret +.err: cmp byte [0x0529], 3 + jae short .force + inc byte [0x0529] + mov al, 0x14 + out 0x43, al + in al, 0x41 + jmp short .eoi + +.int5: pop ax + int 0x05 + iret + +.int6: pop ax + int 0x06 + iret + diff --git a/romimage/DATASEG.INC b/romimage/DATASEG.INC index 40650af4..0a2bad24 100644 --- a/romimage/DATASEG.INC +++ b/romimage/DATASEG.INC @@ -1,29 +1,29 @@ - -; ITF ROMׁ̈Af[^ZOg͈Ⴄꏊɒ` - -DATASEG equ 0a800h - -int09off equ 09d0h -int09seg equ 09d2h -IMR0 equ 09d4h -IMR1 equ 09d5h -DIPSW_1 equ 09d6h -DIPSW_2 equ 09d7h -DIPSW_3 equ 09d8h -KEYSTAT equ 09d9h -KEYBAK equ 09dah -MACTYPE equ 09dbh - -LOCATION equ 09e0h ; word - LOCATION_X equ 09e0h - LOCATION_Y equ 09e1h - -I2ABUFFER equ 09f0h ; db 11 dup(?) - - -BAK_UNDER16 equ 09fdh ; byte -BAK_OVER16 equ 09feh ; word - -MEMSW_X equ 0a00h - -DATASEGEND equ 0b00h + +; ITFは ROMの為、データセグメントは違う場所に定義する + +DATASEG equ 0a800h + +int09off equ 09d0h +int09seg equ 09d2h +IMR0 equ 09d4h +IMR1 equ 09d5h +DIPSW_1 equ 09d6h +DIPSW_2 equ 09d7h +DIPSW_3 equ 09d8h +KEYSTAT equ 09d9h +KEYBAK equ 09dah +MACTYPE equ 09dbh + +LOCATION equ 09e0h ; word + LOCATION_X equ 09e0h + LOCATION_Y equ 09e1h + +I2ABUFFER equ 09f0h ; db 11 dup(?) + + +BAK_UNDER16 equ 09fdh ; byte +BAK_OVER16 equ 09feh ; word + +MEMSW_X equ 0a00h + +DATASEGEND equ 0b00h diff --git a/romimage/DIPSW.X86 b/romimage/DIPSW.X86 index a0e94189..0b084115 100644 --- a/romimage/DIPSW.X86 +++ b/romimage/DIPSW.X86 @@ -1,119 +1,119 @@ - - -; \tgfBbvXCb`֌W - -; ds:[DIPSW_1] DIPSW-1 -; ds:[DIPSW_2] DIPSW-2 -; ds:[DIPSW_3] DIPSW-3 - - - -_xchgbits: push cx ; albitt]... - mov cx, 8 -xchgbitslp: rcr al, 1 - rcl ah, 1 - loop xchgbitslp - pop cx - ret - - -; --------------------------------------------------------------------------- - -INIT_DIPSW: mov byte ptr ds:[DIPSW_1], 01111100b - mov byte ptr ds:[DIPSW_2], 11001110b - mov byte ptr ds:[DIPSW_3], 11011110b - ret - - - - -; NP2ˑ - -GET_DIPSW: mov dx, 841eh - in al, dx - and al, 11111100b - or al, 00000010b - call _xchgbits - in al, 33h - test al, 08h - jne short getsw1ed - or ah, 80h -getsw1ed: mov ds:[DIPSW_1], ah - - mov dh, 85h - in al, dx - and al, 11101111b - call _xchgbits - mov dh, 87h - in al, dx - test al, 20h - je short getsw2ed - or ah, 08h -getsw2ed: mov ds:[DIPSW_2], ah - - mov dh, 86h - in al, dx - and al, 01111111b - call _xchgbits - mov dh, 08eh - in al, dx - test al, 10h - je short getsw3ed - or ah, 01h -getsw3ed: mov ds:[DIPSW_3], ah - ret - - - -SET_DIPSW: mov dx, 841eh - mov al, ds:[DIPSW_1] - call _xchgbits - and ah, 11111100b - in al, dx - and al, 00000010b ; soundbios - or al, ah - jpo short putdipsw1 - or al, 00000001b -putdipsw1: out dx, al - - inc dh - mov al, ds:[DIPSW_2] - call _xchgbits - mov al, ah - and al, 11101111b - jpo short putdipsw2 - or al, 00010000b -putdipsw2: out dx, al - - inc dh - mov al, ds:[DIPSW_3] - call _xchgbits - mov al, ah - and al, 01111111b - jpo short putdipsw3 - or al, 10000000b -putdipsw3: out dx, al - - inc dh - in al, dx - and al, 01011111b - test byte ptr ds:[DIPSW_2], 08h - je short sw25on - or al, 00100000b -sw25on: test al, al - jpo putdipsw25 - or al, 10000000b -putdipsw25: out dx, al - - mov dh, 08eh - in al, dx - and al, 01101111b - test byte ptr ds:[DIPSW_3], 1 - je short sw38on - or al, 00010000b -sw38on: test al, al - jpo putdipsw38 - or al, 10000000b -putdipsw38: out dx, al - ret - + + +; ソフトディップスイッチ関係 + +; ds:[DIPSW_1] DIPSW-1 +; ds:[DIPSW_2] DIPSW-2 +; ds:[DIPSW_3] DIPSW-3 + + + +_xchgbits: push cx ; alのbitを逆転... + mov cx, 8 +xchgbitslp: rcr al, 1 + rcl ah, 1 + loop xchgbitslp + pop cx + ret + + +; --------------------------------------------------------------------------- + +INIT_DIPSW: mov byte ptr ds:[DIPSW_1], 01111100b + mov byte ptr ds:[DIPSW_2], 11001110b + mov byte ptr ds:[DIPSW_3], 11011110b + ret + + + + +; NP2依存部分 + +GET_DIPSW: mov dx, 841eh + in al, dx + and al, 11111100b + or al, 00000010b + call _xchgbits + in al, 33h + test al, 08h + jne short getsw1ed + or ah, 80h +getsw1ed: mov ds:[DIPSW_1], ah + + mov dh, 85h + in al, dx + and al, 11101111b + call _xchgbits + mov dh, 87h + in al, dx + test al, 20h + je short getsw2ed + or ah, 08h +getsw2ed: mov ds:[DIPSW_2], ah + + mov dh, 86h + in al, dx + and al, 01111111b + call _xchgbits + mov dh, 08eh + in al, dx + test al, 10h + je short getsw3ed + or ah, 01h +getsw3ed: mov ds:[DIPSW_3], ah + ret + + + +SET_DIPSW: mov dx, 841eh + mov al, ds:[DIPSW_1] + call _xchgbits + and ah, 11111100b + in al, dx + and al, 00000010b ; soundbios + or al, ah + jpo short putdipsw1 + or al, 00000001b +putdipsw1: out dx, al + + inc dh + mov al, ds:[DIPSW_2] + call _xchgbits + mov al, ah + and al, 11101111b + jpo short putdipsw2 + or al, 00010000b +putdipsw2: out dx, al + + inc dh + mov al, ds:[DIPSW_3] + call _xchgbits + mov al, ah + and al, 01111111b + jpo short putdipsw3 + or al, 10000000b +putdipsw3: out dx, al + + inc dh + in al, dx + and al, 01011111b + test byte ptr ds:[DIPSW_2], 08h + je short sw25on + or al, 00100000b +sw25on: test al, al + jpo putdipsw25 + or al, 10000000b +putdipsw25: out dx, al + + mov dh, 08eh + in al, dx + and al, 01101111b + test byte ptr ds:[DIPSW_3], 1 + je short sw38on + or al, 00010000b +sw38on: test al, al + jpo putdipsw38 + or al, 10000000b +putdipsw38: out dx, al + ret + diff --git a/romimage/FIRMWARE.X86 b/romimage/FIRMWARE.X86 index e219eb76..b103bb31 100644 --- a/romimage/FIRMWARE.X86 +++ b/romimage/FIRMWARE.X86 @@ -1,70 +1,70 @@ - -; CPU[h̕\ - -cpumoderes db "CPU MODE ", 0 - db "High", 0 - db "Low", 0 - -CPUMODE_DISP: mov si, offset cpumoderes - call TEXTOUT_CS - in al, 42h - test al, 2 - je cpumodedisp1 - add si, 5 -cpumodedisp1: call TEXTOUT_CS - mov dl, 0 - inc dh - ret - -; ---------------------------------------------------------------------------- - -; BIOS UPDATẼ_~[ - -FLASH_WRITE: mov cl, 0e1h - mov si, offset res_wflash - call TEXTOUT_CS -flashwritelp: call WAITVSYNC1 - jmps flashwritelp - -; ---------------------------------------------------------------------------- - -; BIOS Revision - -BIOS_REVISON: mov si, offset res_rev1 - call TEXTOUT_CS - mov si, offset res_revver - call TEXTOUT_CS - mov si, offset res_rev2 - jmp TEXTOUT_CS - -; ---------------------------------------------------------------------------- - -FIRMWARE_TEST: mov si, offset res_firm1 - mov cl, 0a9h - call TEXTOUT_CS - mov cl, 0e1h - mov si, offset res_firm2 - call TEXTOUT_CS - call PUT_CPU - mov si, offset res_firm3 - call TEXTOUT_CS - call PUT_CLOCK - mov si, offset res_firm4 - jmp TEXTOUT_CS - -; ---------------------------------------------------------------------------- - -RESET_ALLSW: mov si, offset res_resdip2 - mov cl, 041h - call TEXTOUT_CS - call MEMSW_INIT -ra_dipinit: call INIT_DIPSW - jmp SET_DIPSW - -; ---------------------------------------------------------------------------- - -FLASH_CLEAR: mov si, offset res_resdip - mov cl, 0c1h - call TEXTOUT_CS - jmp short ra_dipinit - + +; CPUモードの表示 + +cpumoderes db "CPU MODE ", 0 + db "High", 0 + db "Low", 0 + +CPUMODE_DISP: mov si, offset cpumoderes + call TEXTOUT_CS + in al, 42h + test al, 2 + je cpumodedisp1 + add si, 5 +cpumodedisp1: call TEXTOUT_CS + mov dl, 0 + inc dh + ret + +; ---------------------------------------------------------------------------- + +; BIOS UPDATEのダミー + +FLASH_WRITE: mov cl, 0e1h + mov si, offset res_wflash + call TEXTOUT_CS +flashwritelp: call WAITVSYNC1 + jmps flashwritelp + +; ---------------------------------------------------------------------------- + +; BIOS Revision + +BIOS_REVISON: mov si, offset res_rev1 + call TEXTOUT_CS + mov si, offset res_revver + call TEXTOUT_CS + mov si, offset res_rev2 + jmp TEXTOUT_CS + +; ---------------------------------------------------------------------------- + +FIRMWARE_TEST: mov si, offset res_firm1 + mov cl, 0a9h + call TEXTOUT_CS + mov cl, 0e1h + mov si, offset res_firm2 + call TEXTOUT_CS + call PUT_CPU + mov si, offset res_firm3 + call TEXTOUT_CS + call PUT_CLOCK + mov si, offset res_firm4 + jmp TEXTOUT_CS + +; ---------------------------------------------------------------------------- + +RESET_ALLSW: mov si, offset res_resdip2 + mov cl, 041h + call TEXTOUT_CS + call MEMSW_INIT +ra_dipinit: call INIT_DIPSW + jmp SET_DIPSW + +; ---------------------------------------------------------------------------- + +FLASH_CLEAR: mov si, offset res_resdip + mov cl, 0c1h + call TEXTOUT_CS + jmp short ra_dipinit + diff --git a/romimage/ITF.INC b/romimage/ITF.INC index 508268a8..77154df2 100644 --- a/romimage/ITF.INC +++ b/romimage/ITF.INC @@ -1,49 +1,49 @@ - -FIXCS equ 2eh - - -CALLNE macro calllabel - je short $+5 - call calllabel - endm - -CALLNZ macro calllabel - je short $+5 - call calllabel - endm - -CALLE macro calllabel - jne short $+5 - call calllabel - endm - -CALLZ macro calllabel - jne short $+5 - call calllabel - endm - -CALLNC macro calllabel - jc short $+5 - call calllabel - endm - -CALLC macro calllabel - jnc short $+5 - call calllabel - endm - - - -jmps macro label ; N88BASIC MON JMPS - jmp short label - endm - -BOOT_NORMAL equ 00h -BOOT_REVISION equ 01h -BOOT_FIRMWARE equ 02h -BOOT_MENU equ 03h - -BOOT_WFLASH equ 10h -BOOT_RFLASH equ 11h -BOOT_DIPSWINIT equ 12h - + +FIXCS equ 2eh + + +CALLNE macro calllabel + je short $+5 + call calllabel + endm + +CALLNZ macro calllabel + je short $+5 + call calllabel + endm + +CALLE macro calllabel + jne short $+5 + call calllabel + endm + +CALLZ macro calllabel + jne short $+5 + call calllabel + endm + +CALLNC macro calllabel + jc short $+5 + call calllabel + endm + +CALLC macro calllabel + jnc short $+5 + call calllabel + endm + + + +jmps macro label ; N88BASIC MONの JMPSね + jmp short label + endm + +BOOT_NORMAL equ 00h +BOOT_REVISION equ 01h +BOOT_FIRMWARE equ 02h +BOOT_MENU equ 03h + +BOOT_WFLASH equ 10h +BOOT_RFLASH equ 11h +BOOT_DIPSWINIT equ 12h + diff --git a/romimage/ITFSUB.X86 b/romimage/ITFSUB.X86 index 12a55eb4..269bde03 100644 --- a/romimage/ITFSUB.X86 +++ b/romimage/ITFSUB.X86 @@ -1,15 +1,15 @@ - -WAITVSYNC1: push ax - mov ah, 1 - jmps waitvsync_lp1 -WAITVSYNC: push ax -waitvsync_lp1: in al, 0a0h - test al, 20h - jne waitvsync_lp1 -waitvsync_lp2: in al, 0a0h - test al, 20h - je waitvsync_lp2 - dec ah - jne waitvsync_lp1 - pop ax - ret + +WAITVSYNC1: push ax + mov ah, 1 + jmps waitvsync_lp1 +WAITVSYNC: push ax +waitvsync_lp1: in al, 0a0h + test al, 20h + jne waitvsync_lp1 +waitvsync_lp2: in al, 0a0h + test al, 20h + je waitvsync_lp2 + dec ah + jne waitvsync_lp1 + pop ax + ret diff --git a/romimage/KEYBOARD.INC b/romimage/KEYBOARD.INC index 75ea421e..fa8535cc 100644 --- a/romimage/KEYBOARD.INC +++ b/romimage/KEYBOARD.INC @@ -1,57 +1,57 @@ -KEYVECT equ 9 - -; 񂵂R[Ȃ }Nɂ - - -; L[{[hJn -KEYINT_INIT macro - cli - xor ax, ax - mov es, ax - mov ax, offset keyint_proc - xchg ax, es:[KEYVECT*4+0] - mov ds:[int09off], ax - mov ax, cs - xchg ax, es:[KEYVECT*4+2] - mov ds:[int09seg], ax -ifndef DEBUG - in al, 02h - mov ds:[IMR0], al - in al, 0ah - mov ds:[IMR1], al - mov al, 0fdh - out 02h, al - mov al, 0ffh - out 0ah, al - - mov al, 0 - mov cx, 11h - mov di, MEM_KB_KY_STS - rep stosb - mov al, 3ah - out 43h, al - mov cx, 20 - loop $ - mov al, 32h - out 43h, al -endif - sti - endm - - -; L[{[hI / CLIŃR[锤 -KEYINT_TERM macro - xor ax, ax - mov es, ax - mov ax, ds:[int09off] - mov es:[KEYVECT*4+0], ax - mov ax, ds:[int09seg] - mov es:[KEYVECT*4+2], ax -ifndef DEBUG - mov al, ds:[IMR0] - out 02h, al - mov al, ds:[IMR1] - out 0ah, al -endif - endm - +KEYVECT equ 9 + +; 一回しかコールしない物は マクロにする + + +; キーボード処理開始 +KEYINT_INIT macro + cli + xor ax, ax + mov es, ax + mov ax, offset keyint_proc + xchg ax, es:[KEYVECT*4+0] + mov ds:[int09off], ax + mov ax, cs + xchg ax, es:[KEYVECT*4+2] + mov ds:[int09seg], ax +ifndef DEBUG + in al, 02h + mov ds:[IMR0], al + in al, 0ah + mov ds:[IMR1], al + mov al, 0fdh + out 02h, al + mov al, 0ffh + out 0ah, al + + mov al, 0 + mov cx, 11h + mov di, MEM_KB_KY_STS + rep stosb + mov al, 3ah + out 43h, al + mov cx, 20 + loop $ + mov al, 32h + out 43h, al +endif + sti + endm + + +; キーボード終了 / CLIでコールされる筈 +KEYINT_TERM macro + xor ax, ax + mov es, ax + mov ax, ds:[int09off] + mov es:[KEYVECT*4+0], ax + mov ax, ds:[int09seg] + mov es:[KEYVECT*4+2], ax +ifndef DEBUG + mov al, ds:[IMR0] + out 02h, al + mov al, ds:[IMR1] + out 0ah, al +endif + endm + diff --git a/romimage/KEYBOARD.X86 b/romimage/KEYBOARD.X86 index 35e671fc..7df5fd59 100644 --- a/romimage/KEYBOARD.X86 +++ b/romimage/KEYBOARD.X86 @@ -1,84 +1,84 @@ - -keyint_proc: push ax - push bx - push cx - push ds - push es - mov ax, DATASEG ; dsWX^͐ݒ肵ȂĂ - mov ds, ax ; DEBUGɍˁc - xor ax, ax - mov es, ax - in al, 43h - test al, 2 - je short keyint_ed - in al, 41h - mov ds:[KEYSTAT], al - mov cl, al - and cl, 7 - mov ah, 1 - shl ah, cl - xor bx, bx - mov bl, al - mov cl, 3 - shr bl, cl - and bl, 0fh - add bx, MEM_KB_KY_STS - test al, 80h - jne short keyrelease - or es:[bx], ah - jmp short keyint_shift -keyrelease: not ah - and es:[bx], ah - and al, 7fh -keyint_shift: cmp al, 70h - jb short keyint_ed - cmp al, 75h - ja short keyint_ed - mov al, es:[bx] - inc bx - inc bx - and al, 1fh - and byte ptr es:[bx], 0e0h - or es:[bx], al -keyint_ed: mov al, 20h - out 0, al - pop es - pop ds - pop cx - pop bx - pop ax - iret - - -boot_keycheck: push ds - xor cx, cx - mov ds, cx - cmp byte ptr ds:[0531h], cl - jns short bkc_nonhelp - mov al, BOOT_WFLASH - mov cl, ds:[0532h] - test cl, 8 ; '8' - jne short bkc_helpret - mov al, BOOT_REVISION - test byte ptr ds:[0533h], 4 ; '1' - jne short bkc_helpret - mov al, BOOT_RFLASH - test cl, 10h ; '9' - jne short bkc_helpret - mov al, BOOT_MENU -bkc_helpret: pop ds - ret - -bkc_nonhelp: mov cl, ds:[053ah] - mov ch, cl - and cx, 111eh - cmp cl, 1eh - mov al, BOOT_FIRMWARE - je short bkc_end - cmp ch, 11h - mov al, BOOT_DIPSWINIT - je short bkc_end - mov al, BOOT_NORMAL -bkc_end: pop ds - ret - + +keyint_proc: push ax + push bx + push cx + push ds + push es + mov ax, DATASEG ; dsレジスタは設定しなくてもいいん + mov ds, ax ; だけど DEBUG時に困るね… + xor ax, ax + mov es, ax + in al, 43h + test al, 2 + je short keyint_ed + in al, 41h + mov ds:[KEYSTAT], al + mov cl, al + and cl, 7 + mov ah, 1 + shl ah, cl + xor bx, bx + mov bl, al + mov cl, 3 + shr bl, cl + and bl, 0fh + add bx, MEM_KB_KY_STS + test al, 80h + jne short keyrelease + or es:[bx], ah + jmp short keyint_shift +keyrelease: not ah + and es:[bx], ah + and al, 7fh +keyint_shift: cmp al, 70h + jb short keyint_ed + cmp al, 75h + ja short keyint_ed + mov al, es:[bx] + inc bx + inc bx + and al, 1fh + and byte ptr es:[bx], 0e0h + or es:[bx], al +keyint_ed: mov al, 20h + out 0, al + pop es + pop ds + pop cx + pop bx + pop ax + iret + + +boot_keycheck: push ds + xor cx, cx + mov ds, cx + cmp byte ptr ds:[0531h], cl + jns short bkc_nonhelp + mov al, BOOT_WFLASH + mov cl, ds:[0532h] + test cl, 8 ; '8' + jne short bkc_helpret + mov al, BOOT_REVISION + test byte ptr ds:[0533h], 4 ; '1' + jne short bkc_helpret + mov al, BOOT_RFLASH + test cl, 10h ; '9' + jne short bkc_helpret + mov al, BOOT_MENU +bkc_helpret: pop ds + ret + +bkc_nonhelp: mov cl, ds:[053ah] + mov ch, cl + and cx, 111eh + cmp cl, 1eh + mov al, BOOT_FIRMWARE + je short bkc_end + cmp ch, 11h + mov al, BOOT_DIPSWINIT + je short bkc_end + mov al, BOOT_NORMAL +bkc_end: pop ds + ret + diff --git a/romimage/MEMCHK.X86 b/romimage/MEMCHK.X86 index 5b8151c6..0b48fa8b 100644 --- a/romimage/MEMCHK.X86 +++ b/romimage/MEMCHK.X86 @@ -1,240 +1,240 @@ - -; MEMORY_CHECK broken ax - -ifdef NP2 -sub_memchk: push es - push di - push cx - mov es, bx - xor di, di - mov al, cl - mov ah, al - mov cx, 8000h -memchk1: stosw - loop memchk1 - add bh, 10h - mov es, bx - mov cx, 8000h -memchk2: stosw - loop memchk2 - mov cx, 8000h -memchk3: scasw - loopz memchk3 - jne memoryerror - sub bh, 10h - mov es, bx - mov cx, 8000h -memchk4: scasw - loopz memchk4 -memoryerror: pop cx - pop di - pop es - ret - -endif - -ifdef MSDOS -sub_memchk: mov ah, 1 - call WAITVSYNC - sub ax, ax - ret -endif - -; -------------------------------------------------------------------------- - -EXTMEMORYMAX equ 128 ; 128MB MAX - -res_memory128ok db "MEMORY 128" -res_memoryok db "KB OK", 0 -res_plusspace db "+", 0 - -res_ramchk db "RAM check : 128KB Ok", 0 -res_extchk db "Extended RAM : 128KB Ok", 0 - - -extmemory_chk: push ax - mov bx, 2000h - mov cl, 0 - call bp - pop ax - add ax, 128 - adc dx, 0 - push bp - mov bp, sp - push ax - push dx - call STRING_L2A - mov cl, 0e1h - mov dx, [bp+6+2] ; location - mov si, offset res_plusspace - call TEXTOUT_CS - mov si, [bp+2+2] ; offset - call TEXTOUT_DS - mov si, offset res_memoryok - call TEXTOUT_CS - pop dx - pop ax - dec word ptr [bp+4+2] ; count - pop bp - jne extmemory_chk - ret 4 - - -MEMORY_TEST: mov bp, offset sub_memchk - - ; C `128KB - mov bx, 2000h - mov cl, 0 - call bp - mov cl, 0e1h - mov si, offset res_memory128ok - call TEXTOUT_CS - - ; C 128KB`640KB - mov ch, es:[MEM_MSW3] - and ch, 7 - je short mainmemtest_ed - cmp ch, 4 - jbe short mainmemtest_st - mov ch, 4 -mainmemtest_st: mov cl, -1 -mainmemtest_l1: call bp - jne short mainmemtest_ed - inc cl - je mainmemtest_l1 - add bh, 20h - push cx - push dx - mov ax, bx - mov cl, 6 - shr ax, cl - call STRING_I2A - pop dx - pop cx - mov dl, 7 - mov cl, 0e1h - call TEXTOUT_DS - dec ch - jne mainmemtest_st -mainmemtest_ed: - mov dl, 13 - push dx - in al, 42h - test al, 2 - jne short extmemtest_end ; low[h͊g - xor bx, bx - push ds - mov ds, bx - or bl, ds:[MEM_EXPMMSZ] - pop ds - je short extmemtest_end - - mov ah, 12 - call WAITVSYNC - - xor ax, ax - mov dx, ax - push bx - mov cx, I2ABUFFER + 5 - push cx - call extmemory_chk - - push ds - xor bx, bx - mov ds, bx - or bx, ds:[MEM_EXTMSZ] - pop ds - je short extmemtest_end - cmp bx, (EXTMEMORYMAX - 16) - jc short extmomey_o16 - mov bx, (EXTMEMORYMAX - 16) -extmomey_o16: - push ax - mov ah, 6 - call WAITVSYNC - pop ax - mov cl, 3 - shl bx, cl - push bx - mov cx, I2ABUFFER + 3 - push cx - call extmemory_chk - -extmemtest_end: pop dx - ret - - -; ---- epson - -epson_memtest: mov bx, 2000h ; C `128KB - mov cl, 0 - call sub_memchk - mov cl, 0e1h - mov si, offset res_ramchk - call TEXTOUT_CS - - mov ch, es:[MEM_MSW3] ; C 128KB`640KB - and ch, 7 - je short epmt_ext - cmp ch, 4 - jbe short epmt_main_lp - mov ch, 4 -epmt_main_lp: mov cl, 0 - call sub_memchk - add bh, 20h - push cx - push dx - mov ax, bx - mov cl, 6 - shr ax, cl - call STRING_I2A - pop dx - pop cx - mov dl, 17 - mov cl, 0e1h - call TEXTOUT_DS - dec ch - jne epmt_main_lp - -epmt_ext: in al, 42h ; g - test al, 2 - jne short epmt_exit - xor ax, ax - push ds - mov ds, ax - or al, ds:[MEM_EXPMMSZ] - pop ds - je short epmt_exit - inc dh - mov dl, 0 - push ax - mov bx, 2000h - mov cl, 0 - call sub_memchk - mov cl, 0e1h - mov si, offset res_extchk - call TEXTOUT_CS - pop ax -epmt_ext_lp: inc ah - push ax - mov bx, 2000h - mov cl, 0 - call sub_memchk - pop ax - push ax - push dx - mov al, 0 - shr ax, 1 - call STRING_I2A - pop dx - mov cl, 0e1h - mov dl, 15 - mov si, I2ABUFFER + 5 - call TEXTOUT_DS - pop ax - cmp ah, al - jb epmt_ext_lp -epmt_exit: inc dh - mov dl, 0 - ret - + +; MEMORY_CHECK broken ax + +ifdef NP2 +sub_memchk: push es + push di + push cx + mov es, bx + xor di, di + mov al, cl + mov ah, al + mov cx, 8000h +memchk1: stosw + loop memchk1 + add bh, 10h + mov es, bx + mov cx, 8000h +memchk2: stosw + loop memchk2 + mov cx, 8000h +memchk3: scasw + loopz memchk3 + jne memoryerror + sub bh, 10h + mov es, bx + mov cx, 8000h +memchk4: scasw + loopz memchk4 +memoryerror: pop cx + pop di + pop es + ret + +endif + +ifdef MSDOS +sub_memchk: mov ah, 1 + call WAITVSYNC + sub ax, ax + ret +endif + +; -------------------------------------------------------------------------- + +EXTMEMORYMAX equ 128 ; 128MB MAX + +res_memory128ok db "MEMORY 128" +res_memoryok db "KB OK", 0 +res_plusspace db "+", 0 + +res_ramchk db "RAM check : 128KB Ok", 0 +res_extchk db "Extended RAM : 128KB Ok", 0 + + +extmemory_chk: push ax + mov bx, 2000h + mov cl, 0 + call bp + pop ax + add ax, 128 + adc dx, 0 + push bp + mov bp, sp + push ax + push dx + call STRING_L2A + mov cl, 0e1h + mov dx, [bp+6+2] ; location + mov si, offset res_plusspace + call TEXTOUT_CS + mov si, [bp+2+2] ; offset + call TEXTOUT_DS + mov si, offset res_memoryok + call TEXTOUT_CS + pop dx + pop ax + dec word ptr [bp+4+2] ; count + pop bp + jne extmemory_chk + ret 4 + + +MEMORY_TEST: mov bp, offset sub_memchk + + ; メインメモリ ~128KB + mov bx, 2000h + mov cl, 0 + call bp + mov cl, 0e1h + mov si, offset res_memory128ok + call TEXTOUT_CS + + ; メインメモリ 128KB~640KB + mov ch, es:[MEM_MSW3] + and ch, 7 + je short mainmemtest_ed + cmp ch, 4 + jbe short mainmemtest_st + mov ch, 4 +mainmemtest_st: mov cl, -1 +mainmemtest_l1: call bp + jne short mainmemtest_ed + inc cl + je mainmemtest_l1 + add bh, 20h + push cx + push dx + mov ax, bx + mov cl, 6 + shr ax, cl + call STRING_I2A + pop dx + pop cx + mov dl, 7 + mov cl, 0e1h + call TEXTOUT_DS + dec ch + jne mainmemtest_st +mainmemtest_ed: + mov dl, 13 + push dx + in al, 42h + test al, 2 + jne short extmemtest_end ; lowモードは拡張メモリ無し + xor bx, bx + push ds + mov ds, bx + or bl, ds:[MEM_EXPMMSZ] + pop ds + je short extmemtest_end + + mov ah, 12 + call WAITVSYNC + + xor ax, ax + mov dx, ax + push bx + mov cx, I2ABUFFER + 5 + push cx + call extmemory_chk + + push ds + xor bx, bx + mov ds, bx + or bx, ds:[MEM_EXTMSZ] + pop ds + je short extmemtest_end + cmp bx, (EXTMEMORYMAX - 16) + jc short extmomey_o16 + mov bx, (EXTMEMORYMAX - 16) +extmomey_o16: + push ax + mov ah, 6 + call WAITVSYNC + pop ax + mov cl, 3 + shl bx, cl + push bx + mov cx, I2ABUFFER + 3 + push cx + call extmemory_chk + +extmemtest_end: pop dx + ret + + +; ---- epson + +epson_memtest: mov bx, 2000h ; メインメモリ ~128KB + mov cl, 0 + call sub_memchk + mov cl, 0e1h + mov si, offset res_ramchk + call TEXTOUT_CS + + mov ch, es:[MEM_MSW3] ; メインメモリ 128KB~640KB + and ch, 7 + je short epmt_ext + cmp ch, 4 + jbe short epmt_main_lp + mov ch, 4 +epmt_main_lp: mov cl, 0 + call sub_memchk + add bh, 20h + push cx + push dx + mov ax, bx + mov cl, 6 + shr ax, cl + call STRING_I2A + pop dx + pop cx + mov dl, 17 + mov cl, 0e1h + call TEXTOUT_DS + dec ch + jne epmt_main_lp + +epmt_ext: in al, 42h ; 拡張メモリ + test al, 2 + jne short epmt_exit + xor ax, ax + push ds + mov ds, ax + or al, ds:[MEM_EXPMMSZ] + pop ds + je short epmt_exit + inc dh + mov dl, 0 + push ax + mov bx, 2000h + mov cl, 0 + call sub_memchk + mov cl, 0e1h + mov si, offset res_extchk + call TEXTOUT_CS + pop ax +epmt_ext_lp: inc ah + push ax + mov bx, 2000h + mov cl, 0 + call sub_memchk + pop ax + push ax + push dx + mov al, 0 + shr ax, 1 + call STRING_I2A + pop dx + mov cl, 0e1h + mov dl, 15 + mov si, I2ABUFFER + 5 + call TEXTOUT_DS + pop ax + cmp ah, al + jb epmt_ext_lp +epmt_exit: inc dh + mov dl, 0 + ret + diff --git a/romimage/MEMSW.X86 b/romimage/MEMSW.X86 index 1c103441..9dc5f2df 100644 --- a/romimage/MEMSW.X86 +++ b/romimage/MEMSW.X86 @@ -1,17 +1,17 @@ - -mswdefault db 048h, 005h, 004h, 000h, 001h, 000h, 000h, 06Eh - -MEMSW_INIT: mov si, offset mswdefault - mov di, MEM_MSW1 - cli - mov al, 0dh - out 68h, al ; memsw write enable - mov cx, 8 -mswresetlp: db FIXCS - movsb - add di, 3 - loop mswresetlp - mov al, 0ch - out 68h, al ; memsw write disable - sti - ret + +mswdefault db 048h, 005h, 004h, 000h, 001h, 000h, 000h, 06Eh + +MEMSW_INIT: mov si, offset mswdefault + mov di, MEM_MSW1 + cli + mov al, 0dh + out 68h, al ; memsw write enable + mov cx, 8 +mswresetlp: db FIXCS + movsb + add di, 3 + loop mswresetlp + mov al, 0ch + out 68h, al ; memsw write disable + sti + ret diff --git a/romimage/NP2.X86 b/romimage/NP2.X86 index e94e7c43..f35d3524 100644 --- a/romimage/NP2.X86 +++ b/romimage/NP2.X86 @@ -1,73 +1,73 @@ - - -np2str db 3, 'NP2' - db 3, 'ver' -np2str_cpu db 3, 'cpu' -np2str_clock db 5, 'clock' -np2str_hwreset db 13, 'hardwarereset' - - -sendnp2port: mov dx, 07efh - xor cx, cx - db FIXCS - lodsb - mov cl, al - if 1 -@@: db FIXCS - lodsb - out dx, al - loop short @b - else - db FIXCS - rep outsb - endif - ret - -checknp2port: mov cl, cs:[si] -cnp2p_lp: in al, dx - inc si - cmp al, cs:[si] - loope short cnp2p_lp - ret - - -getnp2verb: push cx - push dx - push si - mov si, offset np2str - call sendnp2port - sub si, 4 - call checknp2port - jne short nonhitnp2verb - inc si - call sendnp2port - in al, dx - cmp al, 'B' - jb short nonhitnp2verb - pop si - call sendnp2port - - mov si, I2ABUFFER - push si -rnp2p_lp: in al, dx - mov [si], al - inc si - test al, al - jne short rnp2p_lp -nonhitnp2verb: pop si - pop dx - pop cx - ret - - -PUT_CPU: mov si, offset np2str_cpu - call getnp2verb -np2verbout: jne short unknownout - jmp TEXTOUT_DS - -PUT_CLOCK: mov si, offset np2str_clock - call getnp2verb - je short np2verbout -unknownout: mov si, offset res_unknown - jmp TEXTOUT_CS - + + +np2str db 3, 'NP2' + db 3, 'ver' +np2str_cpu db 3, 'cpu' +np2str_clock db 5, 'clock' +np2str_hwreset db 13, 'hardwarereset' + + +sendnp2port: mov dx, 07efh + xor cx, cx + db FIXCS + lodsb + mov cl, al + if 1 +@@: db FIXCS + lodsb + out dx, al + loop short @b + else + db FIXCS + rep outsb + endif + ret + +checknp2port: mov cl, cs:[si] +cnp2p_lp: in al, dx + inc si + cmp al, cs:[si] + loope short cnp2p_lp + ret + + +getnp2verb: push cx + push dx + push si + mov si, offset np2str + call sendnp2port + sub si, 4 + call checknp2port + jne short nonhitnp2verb + inc si + call sendnp2port + in al, dx + cmp al, 'B' + jb short nonhitnp2verb + pop si + call sendnp2port + + mov si, I2ABUFFER + push si +rnp2p_lp: in al, dx + mov [si], al + inc si + test al, al + jne short rnp2p_lp +nonhitnp2verb: pop si + pop dx + pop cx + ret + + +PUT_CPU: mov si, offset np2str_cpu + call getnp2verb +np2verbout: jne short unknownout + jmp TEXTOUT_DS + +PUT_CLOCK: mov si, offset np2str_clock + call getnp2verb + je short np2verbout +unknownout: mov si, offset res_unknown + jmp TEXTOUT_CS + diff --git a/romimage/PC98.INC b/romimage/PC98.INC index cbbdf806..d06ab6dd 100644 --- a/romimage/PC98.INC +++ b/romimage/PC98.INC @@ -1,17 +1,17 @@ - -;seg=00000h -MEM_EXPMMSZ equ 00401h - -MEM_KB_KY_STS equ 0052ah -MEM_SHIFT_STS equ 0053ah -MEM_EXTMSZ equ 00594h - -;seg=0a000h -MEM_MSW1 equ 03fe2h -MEM_MSW2 equ 03fe6h -MEM_MSW3 equ 03feah -MEM_MSW4 equ 03feeh -MEM_MSW5 equ 03ff2h -MEM_MSW6 equ 03ff6h -MEM_MSW7 equ 03ffah -MEM_MSW8 equ 03ffeh + +;seg=00000h +MEM_EXPMMSZ equ 00401h + +MEM_KB_KY_STS equ 0052ah +MEM_SHIFT_STS equ 0053ah +MEM_EXTMSZ equ 00594h + +;seg=0a000h +MEM_MSW1 equ 03fe2h +MEM_MSW2 equ 03fe6h +MEM_MSW3 equ 03feah +MEM_MSW4 equ 03feeh +MEM_MSW5 equ 03ff2h +MEM_MSW6 equ 03ff6h +MEM_MSW7 equ 03ffah +MEM_MSW8 equ 03ffeh diff --git a/romimage/RESOURCE.TXT b/romimage/RESOURCE.TXT index ab82448e..9b9418aa 100644 --- a/romimage/RESOURCE.TXT +++ b/romimage/RESOURCE.TXT @@ -1,361 +1,361 @@ -# = "(C) Studio Milmake 2000,2003" -# = "tbsB" -# = "fBXN" -# = "NbN" -# = "L" -# = "gp" -# = "w" -# = "" -# = "Ȃ" -# = "[h" -# = "܂" -# = "" -# = "OtBbN" -# = "fBbvXCb`" -# = "XCb`" -# = "ێ" -# = "" -# = "eLXg" -# = "s^" -# = "Œ" -# = "؂藣" -# = "cl`" -# = "Tlg" -# = "^[~i" -# = "M" -# = "M" -# = "@" -# = "RCS" -# = "Ot" -# = "PCQ" -# = "hCu̔ԍ" -# = "DɂD" -# = "^C~O" -# = "^C}gp" -# = "NbNgp" -# = "F\D" -# = "a`rhb" -# = "ŋND" -# = "NCXCb`̓e" -# = "eLXgsPʒQ" -# = "s\D" -# = "g" -# = "k" -# = "œ삳D" -# = "@|||@" -# = "eeeijł" -# = "jaCp҃܂" -# = "ۯ߲ި" -# = "̂ݗL" -# = "a" -# = "qr|QRQb" -# = "f[^" -# = "" -# = "R[h" -# = "cdk" -# = "lZvZbT" -# = "qnlAhX́@" -# = "OOO|" -# = "J[Rs[" -# = "zhCu" -# = "[JhCu" -# = "floppy disk" -# = "hard disk" -# = "BOOT on" - - - - - -res_rev1 = "NEC PC-9800 SERIES Emulator\n\nROM BIOS Revision " -res_revver = "0.73" -res_rev2 = "\n\nCopyright (C) Studio Milmake 2000,2003\n\n" - -res_wflash = "Insert the ROM DATA disk ...Press RETURN key" - -res_unknown = "unknown" - -res_firm1 = "Initial Test Firmware (C) Studio Milmake 2000,2003\n" -res_firm2 = "\n\nProcessor is " -res_firm3 = "\n\nCPU Clock is " -res_firm4 = "\n\nResolution is Normal (640x400)\n\n" - -res_resdip = "SET THE SOFTWARE DIP-SWITCH" -res_resdip2 = "cho@rv܂" - -menu_title = "VXeZbgAbvj[" - -ssp_mntitle = " Cj[ " -ssp_infos = " CtH[V " - -dipsw_title = " fBbvXCb`@ " -dipsw_msg = " fBbvXCb`C[W " -dipnum_msg = " 1 2 3 4 5 6 7 8" - -dip1_msg = "rvP" -dip2_msg = "rvQ" -dip3_msg = "rvR" -off_msg = "OFF" -on_msg = "ON" - -keyctl_meg = ":I,:ݒ,HOME CLR:o׎ݒ,ESC:ƭI" -end_t = "I" -end_i = "VXeZbgAbvj[I܂D" - - -sspmn1_t = "fBbvXCb`P̐ݒ" -sspmn1_s = "vY}fBXvC\z\ztbsBfBXNԍ\z\zVA`[h\z\zOtBbN[h" - -sspmn2_t = "fBbvXCb`Q̐ݒ" -sspmn2_s = "^[~iݒ\z\zeLXgʍs\z\zXCb`\z\zfBXN\z\zfcbNbN" - -sspmn3_t = "fBbvXCb`R̐ݒ" -sspmn3_s = "tbsB[^\z\zcl`NbN\z\zbot[h" - -sspmn4_t = "XCb`̐ݒ" -sspmn4_s = "qr|QRQb\z\zTEh@\\z\za@" -sspmn4_i = "XCb`ݒ肵܂D" - - - -sw13_t = "vY}fBXvC" -sw13_s0 = "gp" -sw13_s1 = "gpȂ" -sw13_i = "ʏfgpȂfŌŒD" - -sw14_t = "tbsBfBXNԍ" -sw14_s0 = "@RCS\zOtPCQ" -sw14_s1 = "@PCQ\zOtRCS" -sw14_i0 = "tbsBfBXNhCu̔ԍOtDɂD" -sw14_i1 = "tbsBfBXNhCu̔ԍDɂD" - -sw15_t = "VA`[h" -sw15_s0 = "abh" -sw15_s1 = "rsQ" -sw15_s2 = "@\" -sw15_s3 = "" -sw15_i0 = "M^C~O͖{̓^C}gpCM^C~O̓f̃NbNgpD" -sw15_i1 = "EM^C~OƂāCf苟NbNgpD" -sw15_i2 = "M^C~O͎Mf[^NbNgpCM͓^C}gpD" -sw15_i3 = "EMƂɖ{̓^C}gpD" - -sw18_t = "OtBbN[h" -sw18_s0 = "g" -sw18_s1 = "W" -sw18_i0 = "gOtBbN[hDSOXUFPUF\D" -sw18_i1 = "{OtBbN[hDWFWF\D" - -sw22_t = "^[~i[hw" -sw22_s0 = "^[~i[h" -sw22_s1 = "a`rhb[h" -sw22_i0 = "a`rhb^[~i[hŋND" -sw22_i1 = "a`rhba`rhb[hŋND" - -sw24_t = "eLXgʍs" -sw24_s0 = "QTs^" -sw24_s1 = "QOs^" -sw24_i0 = "eLXgsPʒQTs\D" -sw24_i1 = "eLXgsPʒQOs\D" - -sw25_t = "XCb`" -sw25_s0 = "ێ" -sw25_s1 = "" -sw25_i0 = "NCXCb`̓eێD" -sw25_i1 = "NCXCb`̓eD" - -sw26_t = "ŒfBXN" -sw26_s0 = "؂藣" -sw26_s1 = "gp" -sw26_i0 = "ŒfBXN؂藣D" -sw26_i1 = "ŒfBXNgpD" - -sw28_t = "fcbNbN" -sw28_s0 = "Tlg" -sw28_s1 = "QDTlg" -sw28_i0 = "fcbTlg̃NbNœ삳D" -sw28_i1 = "fcbQDTlg̃NbNœ삳D" - -sw34_t = "tbsB[^" -sw34_s0 = "Ȃ" -sw34_s1 = "" -sw34_i0 = "tbsBfBXÑ[^ȂD" -sw34_i1 = "tbsBɂPTbԃANZXȂꍇCtbsBfBXÑ[^~D" - -sw35_t = "cl`NbN" -sw35_s0 = "" -sw35_s1 = "݊" -sw35_i0 = "cl`NbNœ삳D" -sw35_i1 = "cl`݊NbNœ삳D" - -sw38_t = "bot[h" -sw38_s0 = "g" -sw38_s1 = "k" -sw38_i0 = "g[hŋND" -sw38_i1 = "k[hŋND" - - - - - -memsw_title = "+++++++ @Dldmt +++++++" -memsw_help1 = "ij@@@EEEE@݂̒l܂\zdrb@@@|||@n߂̉ʂɖ߂܂\zgdko@@|||@܂" -memsw_help2 = "@@|||@I܂\z <-\x@@@@|||@肵܂" - -msg_invalid = "" -msg_valid = "L" -msg_use = "g" -msg_nouse = "gȂ" - - -mswi011_t = "wp[^" -mswi011_i = "Mf[^̃t[̎wł" - -mswi012_t = "ʐM" -mswi012_i = "SdAdIт܂" -mswi012_1 = "Sd" -mswi012_2 = "d" - -mswi013_t = "f[^" -mswi013_i = "f[^̃rbgw肵܂" -mswi013_1 = "V" -mswi013_2 = "W" - -mswi014_t = "peB@`FbN" -mswi014_i = "peB`FbNw肵܂" -mswi014_2 = "" -mswi014_3 = "" - -mswi015_t = "Xgbv" -mswi015_i = "Xgbvrbg̒w肵܂" -mswi015_1 = "P" -mswi015_2 = "PDT" -mswi015_3 = "Q" - -mswi016_t = "{[[g" -mswi016_i = "ʐMxw肵܂" -mswi016_1 = "75" -mswi016_2 = "150" -mswi016_3 = "300" -mswi016_4 = "600" -mswi016_5 = "1200" -mswi016_6 = "2400" -mswi016_7 = "4800" -mswi016_8 = "9600" - - -mswi021_t = "{Vtg@R[h", -mswi021_i = "{VtgR[hw肵܂i^[~i[ĥݗLj" -mswi021_1 = "jhPaSa@jnPaSW" -mswi021_2 = "jhP`VO@jnP`VP" - -mswi022_t = "bqM" -mswi022_i = "bq^bqEkeR[hMw肵܂i^[~i[ĥݗLj" -mswi022_1 = "bq@A{s" -mswi022_2 = "bqEke@A{s@@bq@A" - -mswi023_t = "^[L[̑M", -mswi023_i = "<-\x̑MR[hw肵܂i^[~i[ĥݗLj" -mswi023_1 = "bq" -mswi023_2 = "bqEke" - -mswi024_t = "r@p[^" -mswi024_i = "f[^rbgVrbgŃJiǂw肵܂" - -mswi025_t = "cdkR[hMi^[~i[h^o̓[hj" -mswi025_i ="cdkR[hM̓w܂iBS=08h, DEL=7Fh or FFh, NUL=00hj" -mswi025_1 = "ar^cdk" -mswi025_2 = "mtk^mtk" - - -mswi031_t = "TCY@@EEE" -mswi031_i = "σ̒lw肵܂" -mswi031_1 = "128K" -mswi031_2 = "256K" -mswi031_3 = "384K" -mswi031_4 = "512K" -mswi031_5 = "640K" - - -mswi041_t = "lZvZbT" -mswi041_i = "lZvZbTgpɎw肵܂" - -mswi042_t = "NbNw" -mswi042_i = "ob|XWOÚ@Tlgł̂ݓ܂" -mswi042_1 = "Tlg" -mswi042_2 = "Wlg" - - -mswi051_t = "F" -mswi051_i = "J[fBXvC̎̂ݗLł" -mswi051_1 = "" -mswi051_2 = "" - - -mswi061_t = "TEh{[h" -mswi061_i = "qnlAhX́@bbOOO|beeeeijł" - -mswi062_t = "qr|QRQbiQ^Rj{[h" -mswi062_i = "qnlAhX́@cOOOO|cReeeijł" - -mswi063_t = "fo|ha{[h" -mswi063_i = "qnlAhX́@cSOOO|cTeeeijł" - - -mswi071_t = "ob|oqQOPnv^" -mswi071_i = "LȊÕv^ǵ@LgȂLɂĂ" - -mswi072_t = "gʃn[hRs[@\" -mswi072_i = "Sʂ̃n[hRs[Ƃ܂" - -mswi073_t = "J[Rs[" -mswi073_i = "J[Rs[͊gn[hRs[[hIꂽꍇ̂ݗLł" -mswi073_1 = "mNRs[[h" -mswi073_2 = "J[Rs[[h" - - -mswi081_t = "グu" -mswi081_i = "グhCuw肵܂" -mswi081_1 = "ۯ߲ި -> hard disk" -mswi081_2 = "BOOT on 640KB ۯ߲ި" -mswi081_3 = "BOOT on 1MB ۯ߲ި" -mswi081_4 = "BOOT on hard disk 1" -mswi081_5 = "BOOT on hard disk 2" -mswi081_6 = "ROM BASIC" - -mswi082_t = "ŒfBXND抄t" -mswi082_i = "ŒfBXÑhCuԍw肵܂" -mswi082_1 = "w肵Ȃ@:@floppy disk -> hard disk" -mswi082_2 = "w肷@@:@hard disk -> floppy disk" - -mswi083_t = "ŒfBXN[Uʖ" -mswi083_i = "lŗp鎞ɕ֗ł" - - -mswi091_t = "db䖽߂̎gp" -mswi091_i = "gpƖQOjaCp҃܂" - -mswi092_t = "j^[h" -mswi092_i = "gpƖPVjaCp҃܂" - - -mswi101_t = "lbg[N@a" -mswi101_i = "aq`mbgSUVOlbg[N̂ƂŎgp܂" - -mswi102_t = "hCuԍt@@" -mswi102_i = "zhCuzXg@:@[JhCu^[~i" -mswi102_1 = "zhCu -> [JhCu" -mswi102_2 = "[JhCu -> zhCu" - - -msw_menu00 = "qr|QRQb iݒj" -msw_menu01 = "qr|QRQb iMR[hj" -msw_menu02 = "TCY" -msw_menu03 = "lZvZbT" -msw_menu04 = "bqs Fwisdwsj" -msw_menu05 = "g {[h" -msw_menu06 = "ʃn[hRs[" -msw_menu07 = "グu" -msw_menu08 = "a@" -msw_menu09 = "m@a" - -sw25_off = "fBbvXCb`̂mnDQ@TڂɂĂ" +# = "(C) Studio Milmake 2000,2003" +# = "フロッピィ" +# = "ディスク" +# = "クロック" +# = "有効" +# = "使用" +# = "指定" +# = "する" +# = "しない" +# = "モード" +# = "します" +# = "同期" +# = "グラフィック" +# = "ディップスイッチ" +# = "メモリスイッチ" +# = "保持する" +# = "初期化する" +# = "テキスト" +# = "行/画面" +# = "内蔵固定" +# = "切り離す" +# = "DMA" +# = "5MHz" +# = "ターミナル" +# = "送信" +# = "受信" +# = "内蔵 " +# = "#3,#4" +# = "外付け" +# = "#1,#2" +# = "ドライブの番号を" +# = "優先にする." +# = "タイミング" +# = "内部タイマを使用" +# = "クロックを使用" +# = "色表示." +# = "BASIC" +# = "で起動する." +# = "起動時,メモリスイッチの内容を" +# = "テキスト行数を1画面中2" +# = "行表示する." +# = "High" +# = "Low" +# = "で動作させる." +# = " --- " +# = "FFF(hex)です" +# = "KB,利用者メモリが減ります" +# = "フロッピイディスク" +# = "時のみ有効" +# = "Basic" +# = "RS-232C" +# = "データ" +# = "bit" +# = "コード" +# = "DEL" +# = "数値演算プロセッサ" +# = "ROMアドレスは " +# = "000-" +# = "カラーコピー" +# = "仮想ドライブ" +# = "ローカルドライブ" +# = "floppy disk" +# = "hard disk" +# = "BOOT on" + + + + + +res_rev1 = "NEC PC-9800 SERIES Emulator\n\nROM BIOS Revision " +res_revver = "0.73" +res_rev2 = "\n\nCopyright (C) Studio Milmake 2000,2003\n\n" + +res_wflash = "Insert the ROM DATA disk ...Press RETURN key" + +res_unknown = "unknown" + +res_firm1 = "Initial Test Firmware (C) Studio Milmake 2000,2003\n" +res_firm2 = "\n\nProcessor is " +res_firm3 = "\n\nCPU Clock is " +res_firm4 = "\n\nResolution is Normal (640x400)\n\n" + +res_resdip = "SET THE SOFTWARE DIP-SWITCH" +res_resdip2 = "DIP SW情報を初期化します" + +menu_title = "システムセットアップメニュー" + +ssp_mntitle = " メインメニュー " +ssp_infos = " インフォメーション " + +dipsw_title = " ディップスイッチ  " +dipsw_msg = " ディップスイッチイメージ " +dipnum_msg = " 1 2 3 4 5 6 7 8" + +dip1_msg = "SW1" +dip2_msg = "SW2" +dip3_msg = "SW3" +off_msg = "OFF" +on_msg = "ON" + +keyctl_meg = "↑↓キー:選択,←→キー:設定,HOME CLRキー:出荷時設定,ESCキー:メニュー終了" +end_t = "終了" +end_i = "システムセットアップメニューを終了します." + + +sspmn1_t = "ディップスイッチ1の設定" +sspmn1_s = "プラズマディスプレイ\z\zフロッピィディスク番号\z\zシリアル伝送モード\z\zグラフィックモード" + +sspmn2_t = "ディップスイッチ2の設定" +sspmn2_s = "ターミナル設定\z\zテキスト画面行数\z\zメモリスイッチ\z\z内蔵ディスク\z\zGDCクロック" + +sspmn3_t = "ディップスイッチ3の設定" +sspmn3_s = "フロッピィモータ制御\z\zDMAクロック\z\zCPUモード" + +sspmn4_t = "メモリスイッチの設定" +sspmn4_s = "RS-232C\z\zサウンド機能\z\zBasic mode" +sspmn4_i = "メモリスイッチを設定します." + + + +sw13_t = "プラズマディスプレイ" +sw13_s0 = "使用する" +sw13_s1 = "使用しない" +sw13_i = "通常’使用しない’で固定." + +sw14_t = "フロッピィディスク番号" +sw14_s0 = "内蔵 #3,#4\z外付け#1,#2" +sw14_s1 = "内蔵 #1,#2\z外付け#3,#4" +sw14_i0 = "フロッピィディスクドライブの番号を外付け優先にする." +sw14_i1 = "フロッピィディスクドライブの番号を内蔵優先にする." + +sw15_t = "シリアル伝送モード" +sw15_s0 = "BCI同期" +sw15_s1 = "ST2同期" +sw15_s2 = "同期刻時機構" +sw15_s3 = "調歩同期" +sw15_i0 = "送信タイミングは本体内部タイマを使用,受信タイミングはモデムのクロックを使用." +sw15_i1 = "送・受信タイミングとして,モデムより供給されるクロックを使用." +sw15_i2 = "受信タイミングは受信データから作られるクロックを使用,送信は内部タイマを使用." +sw15_i3 = "送・受信ともに本体内部タイマを使用." + +sw18_t = "グラフィックモード" +sw18_s0 = "拡張" +sw18_s1 = "標準" +sw18_i0 = "拡張グラフィックモード.4096色中16色表示." +sw18_i1 = "基本グラフィックモード.8色中8色表示." + +sw22_t = "ターミナルモード指定" +sw22_s0 = "ターミナルモード" +sw22_s1 = "BASICモード" +sw22_i0 = "BASICをターミナルモードで起動する." +sw22_i1 = "BASICをBASICモードで起動する." + +sw24_t = "テキスト画面行数" +sw24_s0 = "25行/画面" +sw24_s1 = "20行/画面" +sw24_i0 = "テキスト行数を1画面中25行表示する." +sw24_i1 = "テキスト行数を1画面中20行表示する." + +sw25_t = "メモリスイッチ" +sw25_s0 = "保持する" +sw25_s1 = "初期化する" +sw25_i0 = "起動時,メモリスイッチの内容を保持する." +sw25_i1 = "起動時,メモリスイッチの内容を初期化する." + +sw26_t = "内蔵固定ディスク" +sw26_s0 = "切り離す" +sw26_s1 = "使用する" +sw26_i0 = "内蔵固定ディスクを切り離す." +sw26_i1 = "内蔵固定ディスクを使用する." + +sw28_t = "GDCクロック" +sw28_s0 = "5MHz" +sw28_s1 = "2.5MHz" +sw28_i0 = "GDCを5MHzのクロックで動作させる." +sw28_i1 = "GDCを2.5MHzのクロックで動作させる." + +sw34_t = "フロッピィモータ制御" +sw34_s0 = "しない" +sw34_s1 = "する" +sw34_i0 = "フロッピィディスクのモータ制御をしない." +sw34_i1 = "フロッピィに15秒間アクセスがない場合,フロッピィディスクのモータを停止する." + +sw35_t = "DMAクロック" +sw35_s0 = "高速" +sw35_s1 = "互換" +sw35_i0 = "DMAを高速クロックで動作させる." +sw35_i1 = "DMAを互換クロックで動作させる." + +sw38_t = "CPUモード" +sw38_s0 = "High" +sw38_s1 = "Low" +sw38_i0 = "Highモードで起動する." +sw38_i1 = "Lowモードで起動する." + + + + + +memsw_title = "+++++++ switch set.MENU +++++++" +memsw_help1 = "()   ・・・・ 現在の値を示します\zESC   --- 始めの画面に戻ります\zHELP  --- 説明をします" +memsw_help2 = "↑↓ ←→ --- 他を選択します\z <-\x    --- 決定します" + +msg_invalid = "無効" +msg_valid = "有効" +msg_use = "使う" +msg_nouse = "使わない" + + +mswi011_t = "Xパラメータ" +mswi011_i = "受信データのフロー制御の指定です" + +mswi012_t = "通信方式" +mswi012_i = "全二重方式か、半二重方式かを選びます" +mswi012_1 = "全二重" +mswi012_2 = "半二重" + +mswi013_t = "データbit長" +mswi013_i = "データのビット長を指定します" +mswi013_1 = "7bit" +mswi013_2 = "8bit" + +mswi014_t = "パリティ チェック" +mswi014_i = "パリティチェックを指定します" +mswi014_2 = "奇数" +mswi014_3 = "偶数" + +mswi015_t = "ストップbit長" +mswi015_i = "ストップビットの長さを指定します" +mswi015_1 = "1bit" +mswi015_2 = "1.5bit" +mswi015_3 = "2bit" + +mswi016_t = "ボーレート" +mswi016_i = "通信速度を指定します" +mswi016_1 = "75" +mswi016_2 = "150" +mswi016_3 = "300" +mswi016_4 = "600" +mswi016_5 = "1200" +mswi016_6 = "2400" +mswi016_7 = "4800" +mswi016_8 = "9600" + + +mswi021_t = "日本語シフト コード", +mswi021_i = "日本語シフトコードを指定します(ターミナルモード時のみ有効)" +mswi021_1 = "KI=1B4Bh KO=1B48h" +mswi021_2 = "KI=1A70h KO=1A71h" + +mswi022_t = "CR受信処理" +mswi022_i = "CR/CR・LFコード受信動作を指定します(ターミナルモード時のみ有効)" +mswi022_1 = "CR 復帰+改行" +mswi022_2 = "CR・LF 復帰+改行  CR 復帰" + +mswi023_t = "リターンキー押下時の送信処理", +mswi023_i = "<-\xを押した時の送信コードを指定します(ターミナルモード時のみ有効)" +mswi023_1 = "CR" +mswi023_2 = "CR・LF" + +mswi024_t = "S パラメータ" +mswi024_i = "データビット長7ビットでカナを扱うかどうかを指定します" + +mswi025_t = "DELコード受信時動作(ターミナルモード/入出力モード)" +mswi025_i ="DELコード受信時の動作指定をします(BS=08h, DEL=7Fh or FFh, NUL=00h)" +mswi025_1 = "BS/DEL" +mswi025_2 = "NUL/NUL" + + +mswi031_t = "サイズ  ・・・byte" +mswi031_i = "実装済メモリの値を指定します" +mswi031_1 = "128K" +mswi031_2 = "256K" +mswi031_3 = "384K" +mswi031_4 = "512K" +mswi031_5 = "640K" + + +mswi041_t = "数値演算プロセッサ" +mswi041_i = "数値演算プロセッサ使用時に指定します" + +mswi042_t = "動作クロック指定" +mswi042_i = "PC-9806は 5MHzでのみ動きます" +mswi042_1 = "5MHz" +mswi042_2 = "8MHz" + + +mswi051_t = "色" +mswi051_i = "カラーディスプレイの時のみ有効です" +mswi051_1 = "白" +mswi051_2 = "緑" + + +mswi061_t = "サウンドボード" +mswi061_i = "ROMアドレスは CC000-CFFFF(hex)です" + +mswi062_t = "RS-232C(第2回線/第3回線)ボード" +mswi062_i = "ROMアドレスは D0000-D3FFF(hex)です" + +mswi063_t = "GP-IBボード" +mswi063_i = "ROMアドレスは D4000-D5FFF(hex)です" + + +mswi071_t = "PC-PR201系プリンタ" +mswi071_i = "上記以外のプリンタを使う時は ´使わない´にしてください" + +mswi072_t = "拡張画面ハードコピー機能" +mswi072_i = "完全合成画面のハードコピーがとれます" + +mswi073_t = "カラーコピー" +mswi073_i = "カラーコピーは拡張ハードコピーモードが選択された場合のみ有効です" +mswi073_1 = "モノクロコピーモード" +mswi073_2 = "カラーコピーモード" + + +mswi081_t = "立ち上げ装置" +mswi081_i = "立ち上げドライブを指定します" +mswi081_1 = "フロッピイディスク -> hard disk" +mswi081_2 = "BOOT on 640KB フロッピイディスク" +mswi081_3 = "BOOT on 1MB フロッピイディスク" +mswi081_4 = "BOOT on hard disk 1" +mswi081_5 = "BOOT on hard disk 2" +mswi081_6 = "ROM BASIC" + +mswi082_t = "固定ディスク優先割付け" +mswi082_i = "固定ディスクのドライブ番号を指定します" +mswi082_1 = "指定しない : floppy disk -> hard disk" +mswi082_2 = "指定する  : hard disk -> floppy disk" + +mswi083_t = "固定ディスクユーザ識別名" +mswi083_i = "多人数で利用する時に便利です" + + +mswi091_t = "電話制御命令の使用" +mswi091_i = "使用すると約20KB,利用者メモリが減ります" + +mswi092_t = "モニタモード" +mswi092_i = "使用すると約17KB,利用者メモリが減ります" + + +mswi101_t = "ネットワーク Basic" +mswi101_i = "BRANCH4670ネットワークのもとで使用します" + +mswi102_t = "ドライブ番号割付け  *network*" +mswi102_i = "仮想ドライブ=ホスト側 : ローカルドライブ=ターミナル側" +mswi102_1 = "仮想ドライブ -> ローカルドライブ" +mswi102_2 = "ローカルドライブ -> 仮想ドライブ" + + +msw_menu00 = "RS-232C (初期設定)" +msw_menu01 = "RS-232C (送受信コード)" +msw_menu02 = "メモリサイズ" +msw_menu03 = "数値演算プロセッサ" +msw_menu04 = "CRT 初期画面 色指定(TEXT)" +msw_menu05 = "拡張 ボード" +msw_menu06 = "画面ハードコピー" +msw_menu07 = "立ち上げ装置" +msw_menu08 = "Basic mode" +msw_menu09 = "Network Basic" + +sw25_off = "ディップスイッチのNO.2 5bit目をonにしてください" diff --git a/romimage/SSP.X86 b/romimage/SSP.X86 index 74caa990..a7c93ac5 100644 --- a/romimage/SSP.X86 +++ b/romimage/SSP.X86 @@ -1,155 +1,155 @@ -sspm_initmsgs db 0e1h ; ʍ̘g - dw 0100h, 1124h - db 0e1h ; ʉE̘g - dw 0224h, 102ch - db 0a1h ; ʉ̘g - dw 1200h, 0650h - db 0 - db 0e1h ; eLXg - dw 0004h, offset menu_title - db 0e1h - dw 010ah, offset ssp_mntitle - db 0e1h - dw 0230h, offset ssp_infos - db 0c1h - dw 1800h, offset keyctl_meg - db 0 - -SSPMENU_ITEMS equ 5 - -sspmenuitems dw offset sspmn1_t, offset sspmn1_s, 0, 0 - dw offset sspmn2_t, offset sspmn2_s, 0, 0 - dw offset sspmn3_t, offset sspmn3_s, 0, 0 - dw offset sspmn4_t, offset sspmn4_s, offset sspmn4_i, 0 - dw offset end_t, 0, offset end_i, 0 - -ssp_menup: mov ah, 0 - add ax, ax - mov dx, 0304h - add dh, al - add ax, ax - add ax, ax - mov bx, ax - add bx, offset sspmenuitems - mov si, cs:[bx] - jmp TEXTOUT_CS - -sspev_hm: push ax - call INIT_DIPSW - call SET_DIPSW - call MEMSW_INIT - pop ax - jmps ssp_main - -sspev_exit: jmp REBOOT_PROCESS - -sspev_ret: cmp al, 3 - ja sspev_exit - je sspev_clmsw - call dipsw_start - jmps ssp_main - -sspev_clmsw: call memsw_start - mov ax, 3 - jmps ssp_main - - -ssp_start: mov di, 3fe0h -dipswflag: mov al, es:[di] - test al, 10h - jne short dipswflag2 - mov byte ptr ds:[DIPSW_1], 01bh - mov byte ptr ds:[DIPSW_2], 04bh - mov byte ptr ds:[DIPSW_3], 048h - jmp short dipswflaged -dipswflag2: mov byte ptr ds:[DIPSW_1], 01ah - mov byte ptr ds:[DIPSW_2], 070h - mov byte ptr ds:[DIPSW_3], 071h -dipswflaged: call GET_DIPSW - - xor ax, ax -if 0 - call memsw_start - jmp REBOOT_PROCESS -endif - -ssp_main: push ax - mov si, offset sspm_initmsgs - call ssp_resdisp - xor ax, ax - mov cl, 0a1h -ssp_mmitmdisp: push ax - call ssp_menup - pop ax - inc al - cmp al, SSPMENU_ITEMS - jb ssp_mmitmdisp - pop ax - jmps ssp_mmenui0 - -sspev_up: mov bx, ax - dec al - jns ssp_mmenui - mov al, SSPMENU_ITEMS - 1 - jmps ssp_mmenui - -sspev_dn: mov bx, ax - inc al - cmp al, SSPMENU_ITEMS - jc ssp_mmenui - mov al, 0 - -ssp_mmenui: push ax - mov ax, bx - mov cl, 0a1h - call ssp_menup - pop ax - -ssp_mmenui0: push ax - mov cl, 0e5h - call ssp_menup - mov di, 4*160+2ch*2 - mov cx, 0a20h - call boxclear - mov si, cs:[bx+2] - test si, si - je ssp_mmenui1 - mov cl, 0e1h - mov dx, 042ch - call TEXTOUT_CS -ssp_mmenui1: push bx - mov dx, 1200h - mov bx, 0650h - mov cl, 0a1h - call puttextbox - pop bx - mov di, 2+13h*160 - mov cx, 044eh - call boxclear - - mov si, cs:[bx+4] - test si, si - je ssp_mmenui2 - mov cl, 0e1h - mov dx, 1404h - call TEXTOUT_CS - jmps ssp_mmenui3 -ssp_mmenui2: call dipsw_dispall -ssp_mmenui3: pop ax - - mov si, offset sspm_event - jmp ssp_keyevent - -sspm_event db 3ah ; up - dw offset sspev_up - db 3dh ; dn - dw offset sspev_dn - db 3eh ; hm - dw offset sspev_hm - db 1ch ; ret - dw offset sspev_ret - db 0 ; esc - dw offset REBOOT_PROCESS - db -1 - - +sspm_initmsgs db 0e1h ; 画面左の枠 + dw 0100h, 1124h + db 0e1h ; 画面右の枠 + dw 0224h, 102ch + db 0a1h ; 画面下の枠 + dw 1200h, 0650h + db 0 + db 0e1h ; ここからテキスト + dw 0004h, offset menu_title + db 0e1h + dw 010ah, offset ssp_mntitle + db 0e1h + dw 0230h, offset ssp_infos + db 0c1h + dw 1800h, offset keyctl_meg + db 0 + +SSPMENU_ITEMS equ 5 + +sspmenuitems dw offset sspmn1_t, offset sspmn1_s, 0, 0 + dw offset sspmn2_t, offset sspmn2_s, 0, 0 + dw offset sspmn3_t, offset sspmn3_s, 0, 0 + dw offset sspmn4_t, offset sspmn4_s, offset sspmn4_i, 0 + dw offset end_t, 0, offset end_i, 0 + +ssp_menup: mov ah, 0 + add ax, ax + mov dx, 0304h + add dh, al + add ax, ax + add ax, ax + mov bx, ax + add bx, offset sspmenuitems + mov si, cs:[bx] + jmp TEXTOUT_CS + +sspev_hm: push ax + call INIT_DIPSW + call SET_DIPSW + call MEMSW_INIT + pop ax + jmps ssp_main + +sspev_exit: jmp REBOOT_PROCESS + +sspev_ret: cmp al, 3 + ja sspev_exit + je sspev_clmsw + call dipsw_start + jmps ssp_main + +sspev_clmsw: call memsw_start + mov ax, 3 + jmps ssp_main + + +ssp_start: mov di, 3fe0h +dipswflag: mov al, es:[di] + test al, 10h + jne short dipswflag2 + mov byte ptr ds:[DIPSW_1], 01bh + mov byte ptr ds:[DIPSW_2], 04bh + mov byte ptr ds:[DIPSW_3], 048h + jmp short dipswflaged +dipswflag2: mov byte ptr ds:[DIPSW_1], 01ah + mov byte ptr ds:[DIPSW_2], 070h + mov byte ptr ds:[DIPSW_3], 071h +dipswflaged: call GET_DIPSW + + xor ax, ax +if 0 + call memsw_start + jmp REBOOT_PROCESS +endif + +ssp_main: push ax + mov si, offset sspm_initmsgs + call ssp_resdisp + xor ax, ax + mov cl, 0a1h +ssp_mmitmdisp: push ax + call ssp_menup + pop ax + inc al + cmp al, SSPMENU_ITEMS + jb ssp_mmitmdisp + pop ax + jmps ssp_mmenui0 + +sspev_up: mov bx, ax + dec al + jns ssp_mmenui + mov al, SSPMENU_ITEMS - 1 + jmps ssp_mmenui + +sspev_dn: mov bx, ax + inc al + cmp al, SSPMENU_ITEMS + jc ssp_mmenui + mov al, 0 + +ssp_mmenui: push ax + mov ax, bx + mov cl, 0a1h + call ssp_menup + pop ax + +ssp_mmenui0: push ax + mov cl, 0e5h + call ssp_menup + mov di, 4*160+2ch*2 + mov cx, 0a20h + call boxclear + mov si, cs:[bx+2] + test si, si + je ssp_mmenui1 + mov cl, 0e1h + mov dx, 042ch + call TEXTOUT_CS +ssp_mmenui1: push bx + mov dx, 1200h + mov bx, 0650h + mov cl, 0a1h + call puttextbox + pop bx + mov di, 2+13h*160 + mov cx, 044eh + call boxclear + + mov si, cs:[bx+4] + test si, si + je ssp_mmenui2 + mov cl, 0e1h + mov dx, 1404h + call TEXTOUT_CS + jmps ssp_mmenui3 +ssp_mmenui2: call dipsw_dispall +ssp_mmenui3: pop ax + + mov si, offset sspm_event + jmp ssp_keyevent + +sspm_event db 3ah ; up + dw offset sspev_up + db 3dh ; dn + dw offset sspev_dn + db 3eh ; hm + dw offset sspev_hm + db 1ch ; ret + dw offset sspev_ret + db 0 ; esc + dw offset REBOOT_PROCESS + db -1 + + diff --git a/romimage/SSP_DIP.X86 b/romimage/SSP_DIP.X86 index c66115da..e54005c4 100644 --- a/romimage/SSP_DIP.X86 +++ b/romimage/SSP_DIP.X86 @@ -1,164 +1,164 @@ - -dipsw_dispall: push ax - push cx - push dx - push si - push di - xor dx, dx - mov si, 19*160+8*2 -dipsw_boxlp: mov cx, 20 - call dipsw_boxs1 - add si, 160-40 - call dipsw_boxs2 - add si, 8*4 - call dipsw_boxs2 - add si, 160-40 - call dipsw_boxs2 - add si, 8*4 - call dipsw_boxs2 - add si, 160-40 - mov cx, 20 - call dipsw_boxs1 - sub si, 160*3-4*2 - call dipsw_swdisp - inc dx - cmp dl, 3 - jc dipsw_boxlp - mov si, offset dipbox_initmsgs - call ssp_rtxtdisp - pop di - pop si - pop dx - pop cx - pop ax - ret - -dipsw_boxs2: mov cl, 2 -dipsw_boxs1: mov byte ptr es:[si+2000h], 65h - mov word ptr es:[si], 0 - inc si - inc si - loop dipsw_boxs1 - ret - - -dipsw_swdisp: push bx - push cx - push dx - mov di, dx - and di, 3 - mov ch, [di+DIPSW_1] - mov ax, di - add di, di - add di, ax - mov cl, 4 - shl di, cl - add di, 160*20+20 - mov cl, 80h -dipswput_lp: mov bx, 0a1h - test dh, cl - je dipswput_cured - mov bl, 0e5h -dipswput_cured: mov ax, 2101h - test ch, cl - je dipswput_hit - mov ax, 2202h - xchg bl, bh -dipswput_hit: mov es:[di+0000h], ax - mov es:[di+2000h], bh - mov es:[di+2002h], bh - xor ax, 0303h - mov es:[di+00a0h], ax - mov es:[di+20a0h], bl - mov es:[di+20a2h], bl - add di, 4 - shr cl, 1 - jne dipswput_lp - pop dx - pop cx - pop bx - ret - - - -dipsw_start: push ax ; ax = j[ - mov si, offset dips_initmsgs - call ssp_resdisp - call dipsw_dispall - pop dx - -mainlpstart: call dippage_set -mainlpsub: mov si, offset dipsw_event - jmp ssp_keyevent - - -dswev_up: and dl, 7fh - call dispdipitem - dec dh - js short pageprev - call curitemputs - jmp short mainlpsub -pageprev: dec dl - jns short mainlpstart - mov dl, 2 - jmps mainlpstart - - -dswev_dn: and dl, 7fh - call dispdipitem - inc dh - cmp dh, bl - jae short pagenext - call curitemputs - jmps mainlpsub -pagenext: mov dh, 0 - inc dl - cmp dl, 3 - jb short mainlpstart - mov dl, 0 - jmps mainlpstart - - -dswev_lt: dec ch - call setdipitem - jmps mainlpsub - - -dswev_rt: inc ch - call setdipitem - jmps mainlpsub - - -dswev_hm: call INIT_DIPSW - jmps mainlpstart - - -dswev_ret: mov al, dh - inc al - cmp al, bl - jne mainlpsub - -dswev_esc: push dx - call SET_DIPSW - pop ax - and ax, 7fh - ret - - - -dipsw_event db 3ah - dw offset dswev_up - db 3dh - dw offset dswev_dn - db 3bh - dw offset dswev_lt - db 3ch - dw offset dswev_rt - db 3eh - dw offset dswev_hm - db 1ch - dw offset dswev_ret - db 0 - dw offset dswev_esc - db -1 - + +dipsw_dispall: push ax + push cx + push dx + push si + push di + xor dx, dx + mov si, 19*160+8*2 +dipsw_boxlp: mov cx, 20 + call dipsw_boxs1 + add si, 160-40 + call dipsw_boxs2 + add si, 8*4 + call dipsw_boxs2 + add si, 160-40 + call dipsw_boxs2 + add si, 8*4 + call dipsw_boxs2 + add si, 160-40 + mov cx, 20 + call dipsw_boxs1 + sub si, 160*3-4*2 + call dipsw_swdisp + inc dx + cmp dl, 3 + jc dipsw_boxlp + mov si, offset dipbox_initmsgs + call ssp_rtxtdisp + pop di + pop si + pop dx + pop cx + pop ax + ret + +dipsw_boxs2: mov cl, 2 +dipsw_boxs1: mov byte ptr es:[si+2000h], 65h + mov word ptr es:[si], 0 + inc si + inc si + loop dipsw_boxs1 + ret + + +dipsw_swdisp: push bx + push cx + push dx + mov di, dx + and di, 3 + mov ch, [di+DIPSW_1] + mov ax, di + add di, di + add di, ax + mov cl, 4 + shl di, cl + add di, 160*20+20 + mov cl, 80h +dipswput_lp: mov bx, 0a1h + test dh, cl + je dipswput_cured + mov bl, 0e5h +dipswput_cured: mov ax, 2101h + test ch, cl + je dipswput_hit + mov ax, 2202h + xchg bl, bh +dipswput_hit: mov es:[di+0000h], ax + mov es:[di+2000h], bh + mov es:[di+2002h], bh + xor ax, 0303h + mov es:[di+00a0h], ax + mov es:[di+20a0h], bl + mov es:[di+20a2h], bl + add di, 4 + shr cl, 1 + jne dipswput_lp + pop dx + pop cx + pop bx + ret + + + +dipsw_start: push ax ; ax = メニューから入力 + mov si, offset dips_initmsgs + call ssp_resdisp + call dipsw_dispall + pop dx + +mainlpstart: call dippage_set +mainlpsub: mov si, offset dipsw_event + jmp ssp_keyevent + + +dswev_up: and dl, 7fh + call dispdipitem + dec dh + js short pageprev + call curitemputs + jmp short mainlpsub +pageprev: dec dl + jns short mainlpstart + mov dl, 2 + jmps mainlpstart + + +dswev_dn: and dl, 7fh + call dispdipitem + inc dh + cmp dh, bl + jae short pagenext + call curitemputs + jmps mainlpsub +pagenext: mov dh, 0 + inc dl + cmp dl, 3 + jb short mainlpstart + mov dl, 0 + jmps mainlpstart + + +dswev_lt: dec ch + call setdipitem + jmps mainlpsub + + +dswev_rt: inc ch + call setdipitem + jmps mainlpsub + + +dswev_hm: call INIT_DIPSW + jmps mainlpstart + + +dswev_ret: mov al, dh + inc al + cmp al, bl + jne mainlpsub + +dswev_esc: push dx + call SET_DIPSW + pop ax + and ax, 7fh + ret + + + +dipsw_event db 3ah + dw offset dswev_up + db 3dh + dw offset dswev_dn + db 3bh + dw offset dswev_lt + db 3ch + dw offset dswev_rt + db 3eh + dw offset dswev_hm + db 1ch + dw offset dswev_ret + db 0 + dw offset dswev_esc + db -1 + diff --git a/romimage/SSP_MSW.X86 b/romimage/SSP_MSW.X86 index cbb04e94..dab8a43b 100644 --- a/romimage/SSP_MSW.X86 +++ b/romimage/SSP_MSW.X86 @@ -1,527 +1,527 @@ -MLMSW1 equ (MEM_MSW1 and 0ffh) -MLMSW2 equ (MEM_MSW2 and 0ffh) -MLMSW3 equ (MEM_MSW3 and 0ffh) -MLMSW4 equ (MEM_MSW4 and 0ffh) -MLMSW5 equ (MEM_MSW5 and 0ffh) -MLMSW6 equ (MEM_MSW6 and 0ffh) - - -memswbit db 0*8+0, MLMSW1, 001h, 0 - db 0*8+1, MLMSW1, 002h, 0 - db 0*8+2, MLMSW1, 00ch, 1*2-1 ; data bit - db 0*8+3, MLMSW1, 030h, 2*2-1 ; crc - db 0*8+4, MLMSW1, 0c0h, 3*2-1 ; stop bit - db 0*8+5, MLMSW2, 00fh, 4*2-1 ; boau rate - - db 1*8+0, MLMSW2, 010h, 0 - db 1*8+1, MLMSW2, 020h, 0 - db 1*8+2, MLMSW2, 040h, 0 - db 1*8+3, MLMSW2, 080h, 0 - db 1*8+4, MLMSW3, 080h, 0 - - db 2*8+0, MLMSW3, 007h, 5*2-1 ; memory - - db 3*8+0, MLMSW3, 018h, 6*2-1 ; coprocessor - db 3*8+1, MLMSW3, 020h, 0 - - db 4*8+0, MLMSW3, 040h, 0 - - db 5*8+0, MLMSW4, 008h, 0 - db 5*8+1, MLMSW4, 010h, 0 - db 5*8+2, MLMSW4, 020h, 0 - - db 6*8+0, MLMSW5, 001h, 0 - db 6*8+1, MLMSW6, 010h, 0 - db 6*8+2, MLMSW5, 008h, 0 - - db 7*8+0, MLMSW5, 0f0h, 7*2-1 ; boot - db 7*8+1, MLMSW5, 002h, 0 - db 7*8+2, MLMSW5, 004h, 0 - - db 8*8+0, MLMSW6, 008h, 0 - db 8*8+1, MLMSW6, 020h, 0 - -mswsread_p6: push ax - mov ax, 0100h - db 0d5h, 0 - pop ax - je mswsread_p1 - shr al, 1 ; V30 - -mswsread_p1: and al, 1 - ret - -mswsread_p2: shr al, 1 - jnc mswsread_0 - inc al - ret -mswsread_0: mov al, 0 - ret - -mswsread_p3: test al, al - je mswsread_ret - dec al -mswsread_ret: ret - -mswsread_p4: dec al - cmp al, 8 - jc mswsread_ret - mov al, 4 - ret - -mswsread_p5: cmp al, 5 - jc mswsread_ret - mov al, 4 - ret - -mswr_bootdev db 0, 5, 1, 5, 2, 5, 5, 5 - db 5, 5, 3, 4, 5, 5, 5, 5 - -mswsread_p7: mov bx, offset mswr_bootdev - db FIXCS - xlat - ret - -mswsread_p dw offset mswsread_p1, offset mswsread_p2 - dw offset mswsread_p3, offset mswsread_p4 - dw offset mswsread_p5, offset mswsread_p6 - dw offset mswsread_p7 - - -msw_getparam: mov si, offset memswbit - mov cx, 26 -msws_rbitoutlp: mov ax, cs:[si] - mov dx, cs:[si+2] - mov bx, (MEM_MSW1 and 0ff00h) - xchg bl, ah - mov di, ax - mov al, es:[bx] - and al, dl - mov ah, dl - stc -msws_rbitolp: rcr ah, 1 - jc msws_rbitoed - shr al, 1 - jmps msws_rbitolp -msws_rbitoed: dec dh - js msws_rbitout - xor bx, bx - mov bl, dh - call cs:mswsread_p[bx] -msws_rbitout: mov ds:[di + MEMSW_X], al - add si, 4 - loop msws_rbitoutlp - ret - - - - -mswswrite_p1: or al, 2 - ret - -mswswrite_p2: test al, al - jne mswswrite_p2e - mov dl, 10h ; bit - ret -mswswrite_p2e: inc al - ret - -mswswrite_p3: inc al -mswswrite_p5: ret - -mswswrite_p6: push ax - mov ax, 0100h - db 0d5h, 0 - pop ax - mov dl, 08h - je mswswrite_p6e - mov dl, 10h ; V30 -mswswrite_p6e: ret - - -msww_bootdev db 00h, 02h, 04h, 0ah, 0bh, 0fh, 0fh, 0fh - -mswswrite_p7: and al, 7 - mov bx, offset msww_bootdev - db FIXCS - xlat - ret - -mswswrite_p dw offset mswswrite_p1, offset mswswrite_p2 - dw offset mswswrite_p3, offset mswswrite_p3 - dw offset mswswrite_p5, offset mswswrite_p6 - dw offset mswswrite_p7 - -msw_setparam: -ifndef DEBUG - mov al, 0dh - out 68h, al ; memsw write enable -endif - mov si, offset memswbit - mov cx, 26 -msws_wbitoutlp: mov ax, cs:[si] - mov dx, cs:[si+2] - mov bx, (MEM_MSW1 and 0ff00h) - xchg bl, ah - mov di, ax - mov al, ds:[di + MEMSW_X] - dec dh - js msws_wbitout - push bx - xor bx, bx - mov bl, dh - call cs:mswswrite_p[bx] - pop bx -msws_wbitout: not dl - and es:[bx], dl - not dl - stc -msws_wbitolp: rcr dl, 1 - jc msws_wbitoed - shl al, 1 - jmps msws_wbitolp -msws_wbitoed: or es:[bx], al - add si, 4 - loop msws_wbitoutlp -ifndef DEBUG - mov al, 0ch - out 68h, al ; memsw write disable -endif - ret - - - - -; -------------------------------------------------------------------------- - -msw_mitmput: mov dx, 0206h - add dh, al - mov si, ax - add si, si - mov si, cs:mswmainmenus[si] - jmp TEXTOUT_CS - - -memsw_start: call msw_getparam - - call SCREEN_CLEAR - mov dx, 23*256+3 - mov cl, 0e1h - mov si, offset memsw_help2 - call TEXTOUT_CS - - xor ax, ax - -msw_main: push ax - xor di, di - mov cx, 1750h - call boxclear - - mov cl, 0e1h - xor dx, dx - mov si, offset memsw_title - call TEXTOUT_CS - - in al, 31h - test al, 10h - je msw_mainmst - - mov dx, 1204h - mov si, offset sw25_off - call TEXTOUT_CS - -msw_mainmst: xor ax, ax - -msw_mainmlp: push ax - call msw_mitmput - pop ax - inc al - cmp al, MSWMENU_ITEMS - jb msw_mainmlp - pop ax - jmps msw_mainml1 - -mswev_up: mov bx, ax - dec al - jns msw_mainml0 - mov al, MSWMENU_ITEMS - 1 - jmps msw_mainml0 - -mswev_dn: mov bx, ax - inc al - cmp al, MSWMENU_ITEMS - jb msw_mainml0 - mov al, 0 - -msw_mainml0: push ax - mov ax, bx - mov cl, 0e1h - call msw_mitmput - pop ax - -msw_mainml1: push ax - mov cl, 0e5h - call msw_mitmput - pop ax - - mov si, offset memsw_event - jmp ssp_keyevent - -memsw_event db 3ah - dw offset mswev_up - db 3dh - dw offset mswev_dn - db 60h - dw offset mswsv_stop - db 1ch - dw offset mswev_ret - db -1 - -mswev_ret: cmp al, MSWMENU_ITEMS - 1 - jb mews_main - call msw_setparam -mswsv_stop: ret - -; -------------------------------------------------------------------- sub menu - -memswline db "----", 0 - - -msws_miheader: mov si, bx - add si, si - mov si, cs:mswsub_items[si] - ret - -; Ăяoc -msws_mihead: call msws_miheader - push ax - inc si - test ah, ah - je msws_miheaded -msws_miheadlp: mov dl, cs:[si+1] - mov dh, 0 - add dx, dx - add dx, dx - add dx, 6 - add si, dx - dec ah - jne msws_miheadlp -msws_miheaded: pop ax - ret - - - - -mews_main: push ax - xor di, di - mov cx, 1750h - call boxclear - - mov dx, 20*256+3 - mov cl, 0e1h - mov si, offset memsw_help1 - call TEXTOUT_CS - - mov cl, 0e1h - xor dx, dx - mov si, offset memswline - call TEXTOUT_CS - inc dl - inc dl - pop ax - mov bx, ax - push ax - add ax, ax - mov si, ax - mov si, cs:mswmainmenus[si] - call TEXTOUT_CS - inc dl - inc dl - mov si, offset memswline - call TEXTOUT_CS - - ; j[т - mov cl, 0e1h - xor ax, ax - -msws_msdplp0: push ax - call msws_mihead - mov dl, 3 - mov dh, cs:[si] - mov ch, cs:[si+1] - mov si, cs:[si+2] - call TEXTOUT_CS - inc dl - inc dl - call calc_dx2di -msws_menub_lp: mov word ptr es:[di], 00a5h - inc di - inc di - inc dl - cmp dl, 72 - jbe msws_menub_lp - pop ax - -msws_msdplp1: call msws_itemdisp - inc al - cmp al, ch - jb msws_msdplp1 - - call msws_curladrs - mov al, ds:[di] - call msws_micur - - mov al, 0 - inc ah - call msws_miheader - cmp ah, cs:[si] - jb msws_msdplp0 - - xor ax, ax - -mswsubmenu_st: call msws_curladrs - mov al, ds:[di] - push ax - mov di, 18*160 - mov cx, 0150h - call boxclear - pop ax - -mswsubmenu_rd: mov cl, 0e5h - call msws_itemdisp - mov cl, 0e1h -mswsubmenu_lp: mov si, offset memswsub_event - jmp ssp_keyevent - -mswsev_help: call msws_mihead - push ax - mov dx, 18*256 - mov si, cs:[si+4] - call TEXTOUT_CS - pop ax - jmps mswsubmenu_lp - -mswsev_up: call msws_itemdisp - dec ah - jns mswsubmenu_st - call msws_miheader - mov ah, cs:[si] - dec ah - jmps mswsubmenu_st - -mswsev_dn: call msws_itemdisp - inc ah - call msws_miheader - cmp ah, cs:[si] - jb mswsubmenu_st - mov ah, 0 - jmps mswsubmenu_st - -mswsev_lt: call msws_itemdisp - dec al - jns mswsubmenu_rd - mov al, cs:[si+1] - dec al - jmps mswsubmenu_rd - -mswsev_rt: call msws_itemdisp - inc al - cmp al, cs:[si+1] - jb mswsubmenu_rd - mov al, 0 - jmps mswsubmenu_rd - -mswsev_ret: call msws_micur - jmps mswsubmenu_lp - -mswsev_esc: pop ax - jmp msw_main - -mswsev_stop: pop ax - ret ; ߂ - -memswsub_event db 3ah - dw offset mswsev_up - db 3dh - dw offset mswsev_dn - db 3bh - dw offset mswsev_lt - db 3ch - dw offset mswsev_rt - db 1ch - dw offset mswsev_ret - db 3fh - dw offset mswsev_help - db 60h - dw offset mswsev_stop - db 0 - dw offset mswsev_esc - db -1 - - -msws_curladrs: push ax - mov di, bx - add di, di - add di, di - add di, di - mov al, ah - mov ah, 0 - add ax, MEMSW_X - add di, ax - pop ax - ret - - -mswm_cursoledip: mov ah, 0 - add ax, ax - add ax, ax - push si - add si, ax - mov dx, cs:[si + 6] - call calc_dx2di - mov es:[di-2], ch - mov si, cs:[si + 6 + 2] - call TEXTOUT_SKIP - call calc_dx2di - cmp ch, 28h - jne mswm_cursoledipr - inc ch -mswm_cursoledipr: mov es:[di], ch - pop si - ret - - -msws_micur: call msws_mihead - cmp al, cs:[si + 1] - jb mswm_micurdel - mov al, 0 -mswm_micurdel: call msws_curladrs - push ax - xchg al, ds:[di] - cmp al, cs:[si + 1] - jae mswm_micurdld - mov ch, 20h - call mswm_cursoledip -mswm_micurdld: pop ax - push ax - mov ch, 28h - call mswm_cursoledip - pop ax - ret - - -msws_itemdisp: push ax - call msws_mihead - push si - mov ah, 0 - add ax, ax - add ax, ax - add si, ax - mov dx, cs:[si+6] - mov si, cs:[si+6+2] - call TEXTOUT_CS - pop si - pop ax - ret - - +MLMSW1 equ (MEM_MSW1 and 0ffh) +MLMSW2 equ (MEM_MSW2 and 0ffh) +MLMSW3 equ (MEM_MSW3 and 0ffh) +MLMSW4 equ (MEM_MSW4 and 0ffh) +MLMSW5 equ (MEM_MSW5 and 0ffh) +MLMSW6 equ (MEM_MSW6 and 0ffh) + + +memswbit db 0*8+0, MLMSW1, 001h, 0 + db 0*8+1, MLMSW1, 002h, 0 + db 0*8+2, MLMSW1, 00ch, 1*2-1 ; data bit + db 0*8+3, MLMSW1, 030h, 2*2-1 ; crc + db 0*8+4, MLMSW1, 0c0h, 3*2-1 ; stop bit + db 0*8+5, MLMSW2, 00fh, 4*2-1 ; boau rate + + db 1*8+0, MLMSW2, 010h, 0 + db 1*8+1, MLMSW2, 020h, 0 + db 1*8+2, MLMSW2, 040h, 0 + db 1*8+3, MLMSW2, 080h, 0 + db 1*8+4, MLMSW3, 080h, 0 + + db 2*8+0, MLMSW3, 007h, 5*2-1 ; memory + + db 3*8+0, MLMSW3, 018h, 6*2-1 ; coprocessor + db 3*8+1, MLMSW3, 020h, 0 + + db 4*8+0, MLMSW3, 040h, 0 + + db 5*8+0, MLMSW4, 008h, 0 + db 5*8+1, MLMSW4, 010h, 0 + db 5*8+2, MLMSW4, 020h, 0 + + db 6*8+0, MLMSW5, 001h, 0 + db 6*8+1, MLMSW6, 010h, 0 + db 6*8+2, MLMSW5, 008h, 0 + + db 7*8+0, MLMSW5, 0f0h, 7*2-1 ; boot + db 7*8+1, MLMSW5, 002h, 0 + db 7*8+2, MLMSW5, 004h, 0 + + db 8*8+0, MLMSW6, 008h, 0 + db 8*8+1, MLMSW6, 020h, 0 + +mswsread_p6: push ax + mov ax, 0100h + db 0d5h, 0 + pop ax + je mswsread_p1 + shr al, 1 ; V30 + +mswsread_p1: and al, 1 + ret + +mswsread_p2: shr al, 1 + jnc mswsread_0 + inc al + ret +mswsread_0: mov al, 0 + ret + +mswsread_p3: test al, al + je mswsread_ret + dec al +mswsread_ret: ret + +mswsread_p4: dec al + cmp al, 8 + jc mswsread_ret + mov al, 4 + ret + +mswsread_p5: cmp al, 5 + jc mswsread_ret + mov al, 4 + ret + +mswr_bootdev db 0, 5, 1, 5, 2, 5, 5, 5 + db 5, 5, 3, 4, 5, 5, 5, 5 + +mswsread_p7: mov bx, offset mswr_bootdev + db FIXCS + xlat + ret + +mswsread_p dw offset mswsread_p1, offset mswsread_p2 + dw offset mswsread_p3, offset mswsread_p4 + dw offset mswsread_p5, offset mswsread_p6 + dw offset mswsread_p7 + + +msw_getparam: mov si, offset memswbit + mov cx, 26 +msws_rbitoutlp: mov ax, cs:[si] + mov dx, cs:[si+2] + mov bx, (MEM_MSW1 and 0ff00h) + xchg bl, ah + mov di, ax + mov al, es:[bx] + and al, dl + mov ah, dl + stc +msws_rbitolp: rcr ah, 1 + jc msws_rbitoed + shr al, 1 + jmps msws_rbitolp +msws_rbitoed: dec dh + js msws_rbitout + xor bx, bx + mov bl, dh + call cs:mswsread_p[bx] +msws_rbitout: mov ds:[di + MEMSW_X], al + add si, 4 + loop msws_rbitoutlp + ret + + + + +mswswrite_p1: or al, 2 + ret + +mswswrite_p2: test al, al + jne mswswrite_p2e + mov dl, 10h ; bit + ret +mswswrite_p2e: inc al + ret + +mswswrite_p3: inc al +mswswrite_p5: ret + +mswswrite_p6: push ax + mov ax, 0100h + db 0d5h, 0 + pop ax + mov dl, 08h + je mswswrite_p6e + mov dl, 10h ; V30 +mswswrite_p6e: ret + + +msww_bootdev db 00h, 02h, 04h, 0ah, 0bh, 0fh, 0fh, 0fh + +mswswrite_p7: and al, 7 + mov bx, offset msww_bootdev + db FIXCS + xlat + ret + +mswswrite_p dw offset mswswrite_p1, offset mswswrite_p2 + dw offset mswswrite_p3, offset mswswrite_p3 + dw offset mswswrite_p5, offset mswswrite_p6 + dw offset mswswrite_p7 + +msw_setparam: +ifndef DEBUG + mov al, 0dh + out 68h, al ; memsw write enable +endif + mov si, offset memswbit + mov cx, 26 +msws_wbitoutlp: mov ax, cs:[si] + mov dx, cs:[si+2] + mov bx, (MEM_MSW1 and 0ff00h) + xchg bl, ah + mov di, ax + mov al, ds:[di + MEMSW_X] + dec dh + js msws_wbitout + push bx + xor bx, bx + mov bl, dh + call cs:mswswrite_p[bx] + pop bx +msws_wbitout: not dl + and es:[bx], dl + not dl + stc +msws_wbitolp: rcr dl, 1 + jc msws_wbitoed + shl al, 1 + jmps msws_wbitolp +msws_wbitoed: or es:[bx], al + add si, 4 + loop msws_wbitoutlp +ifndef DEBUG + mov al, 0ch + out 68h, al ; memsw write disable +endif + ret + + + + +; -------------------------------------------------------------------------- + +msw_mitmput: mov dx, 0206h + add dh, al + mov si, ax + add si, si + mov si, cs:mswmainmenus[si] + jmp TEXTOUT_CS + + +memsw_start: call msw_getparam + + call SCREEN_CLEAR + mov dx, 23*256+3 + mov cl, 0e1h + mov si, offset memsw_help2 + call TEXTOUT_CS + + xor ax, ax + +msw_main: push ax + xor di, di + mov cx, 1750h + call boxclear + + mov cl, 0e1h + xor dx, dx + mov si, offset memsw_title + call TEXTOUT_CS + + in al, 31h + test al, 10h + je msw_mainmst + + mov dx, 1204h + mov si, offset sw25_off + call TEXTOUT_CS + +msw_mainmst: xor ax, ax + +msw_mainmlp: push ax + call msw_mitmput + pop ax + inc al + cmp al, MSWMENU_ITEMS + jb msw_mainmlp + pop ax + jmps msw_mainml1 + +mswev_up: mov bx, ax + dec al + jns msw_mainml0 + mov al, MSWMENU_ITEMS - 1 + jmps msw_mainml0 + +mswev_dn: mov bx, ax + inc al + cmp al, MSWMENU_ITEMS + jb msw_mainml0 + mov al, 0 + +msw_mainml0: push ax + mov ax, bx + mov cl, 0e1h + call msw_mitmput + pop ax + +msw_mainml1: push ax + mov cl, 0e5h + call msw_mitmput + pop ax + + mov si, offset memsw_event + jmp ssp_keyevent + +memsw_event db 3ah + dw offset mswev_up + db 3dh + dw offset mswev_dn + db 60h + dw offset mswsv_stop + db 1ch + dw offset mswev_ret + db -1 + +mswev_ret: cmp al, MSWMENU_ITEMS - 1 + jb mews_main + call msw_setparam +mswsv_stop: ret + +; -------------------------------------------------------------------- sub menu + +memswline db "----", 0 + + +msws_miheader: mov si, bx + add si, si + mov si, cs:mswsub_items[si] + ret + +; 頭を呼び出し… +msws_mihead: call msws_miheader + push ax + inc si + test ah, ah + je msws_miheaded +msws_miheadlp: mov dl, cs:[si+1] + mov dh, 0 + add dx, dx + add dx, dx + add dx, 6 + add si, dx + dec ah + jne msws_miheadlp +msws_miheaded: pop ax + ret + + + + +mews_main: push ax + xor di, di + mov cx, 1750h + call boxclear + + mov dx, 20*256+3 + mov cl, 0e1h + mov si, offset memsw_help1 + call TEXTOUT_CS + + mov cl, 0e1h + xor dx, dx + mov si, offset memswline + call TEXTOUT_CS + inc dl + inc dl + pop ax + mov bx, ax + push ax + add ax, ax + mov si, ax + mov si, cs:mswmainmenus[si] + call TEXTOUT_CS + inc dl + inc dl + mov si, offset memswline + call TEXTOUT_CS + + ; メニューをびるど + mov cl, 0e1h + xor ax, ax + +msws_msdplp0: push ax + call msws_mihead + mov dl, 3 + mov dh, cs:[si] + mov ch, cs:[si+1] + mov si, cs:[si+2] + call TEXTOUT_CS + inc dl + inc dl + call calc_dx2di +msws_menub_lp: mov word ptr es:[di], 00a5h + inc di + inc di + inc dl + cmp dl, 72 + jbe msws_menub_lp + pop ax + +msws_msdplp1: call msws_itemdisp + inc al + cmp al, ch + jb msws_msdplp1 + + call msws_curladrs + mov al, ds:[di] + call msws_micur + + mov al, 0 + inc ah + call msws_miheader + cmp ah, cs:[si] + jb msws_msdplp0 + + xor ax, ax + +mswsubmenu_st: call msws_curladrs + mov al, ds:[di] + push ax + mov di, 18*160 + mov cx, 0150h + call boxclear + pop ax + +mswsubmenu_rd: mov cl, 0e5h + call msws_itemdisp + mov cl, 0e1h +mswsubmenu_lp: mov si, offset memswsub_event + jmp ssp_keyevent + +mswsev_help: call msws_mihead + push ax + mov dx, 18*256 + mov si, cs:[si+4] + call TEXTOUT_CS + pop ax + jmps mswsubmenu_lp + +mswsev_up: call msws_itemdisp + dec ah + jns mswsubmenu_st + call msws_miheader + mov ah, cs:[si] + dec ah + jmps mswsubmenu_st + +mswsev_dn: call msws_itemdisp + inc ah + call msws_miheader + cmp ah, cs:[si] + jb mswsubmenu_st + mov ah, 0 + jmps mswsubmenu_st + +mswsev_lt: call msws_itemdisp + dec al + jns mswsubmenu_rd + mov al, cs:[si+1] + dec al + jmps mswsubmenu_rd + +mswsev_rt: call msws_itemdisp + inc al + cmp al, cs:[si+1] + jb mswsubmenu_rd + mov al, 0 + jmps mswsubmenu_rd + +mswsev_ret: call msws_micur + jmps mswsubmenu_lp + +mswsev_esc: pop ax + jmp msw_main + +mswsev_stop: pop ax + ret ; 戻る + +memswsub_event db 3ah + dw offset mswsev_up + db 3dh + dw offset mswsev_dn + db 3bh + dw offset mswsev_lt + db 3ch + dw offset mswsev_rt + db 1ch + dw offset mswsev_ret + db 3fh + dw offset mswsev_help + db 60h + dw offset mswsev_stop + db 0 + dw offset mswsev_esc + db -1 + + +msws_curladrs: push ax + mov di, bx + add di, di + add di, di + add di, di + mov al, ah + mov ah, 0 + add ax, MEMSW_X + add di, ax + pop ax + ret + + +mswm_cursoledip: mov ah, 0 + add ax, ax + add ax, ax + push si + add si, ax + mov dx, cs:[si + 6] + call calc_dx2di + mov es:[di-2], ch + mov si, cs:[si + 6 + 2] + call TEXTOUT_SKIP + call calc_dx2di + cmp ch, 28h + jne mswm_cursoledipr + inc ch +mswm_cursoledipr: mov es:[di], ch + pop si + ret + + +msws_micur: call msws_mihead + cmp al, cs:[si + 1] + jb mswm_micurdel + mov al, 0 +mswm_micurdel: call msws_curladrs + push ax + xchg al, ds:[di] + cmp al, cs:[si + 1] + jae mswm_micurdld + mov ch, 20h + call mswm_cursoledip +mswm_micurdld: pop ax + push ax + mov ch, 28h + call mswm_cursoledip + pop ax + ret + + +msws_itemdisp: push ax + call msws_mihead + push si + mov ah, 0 + add ax, ax + add ax, ax + add si, ax + mov dx, cs:[si+6] + mov si, cs:[si+6+2] + call TEXTOUT_CS + pop si + pop ax + ret + + diff --git a/romimage/SSP_RES.X86 b/romimage/SSP_RES.X86 index a4add92c..39fc0040 100644 --- a/romimage/SSP_RES.X86 +++ b/romimage/SSP_RES.X86 @@ -1,312 +1,312 @@ -; SSPp̃\[X - -; ------------------------------------------------- fBbvXCb`j[p - -dips_initmsgs db 0e1h ; ʏ̘g - dw 0100h, 1050h - db 0a1h ; ʉ̘g - dw 1200h, 0650h - db 0 - db 0e1h ; eLXg - dw 0004h, offset menu_title - db 0e1h - dw 011eh, offset dipsw_title - db 0 - -dipbox_initmsgs db 0e1h - dw 121bh, offset dipsw_msg - db 0a1h - dw 130fh, offset dip1_msg - db 0a1h - dw 1327h, offset dip2_msg - db 0a1h - dw 133fh, offset dip3_msg - db 0a1h - dw 1404h, offset off_msg - db 0a1h - dw 1504h, offset on_msg - db 065h - dw 160ah, offset dipnum_msg - db 065h - dw 1622h, offset dipnum_msg - db 065h - dw 163ah, offset dipnum_msg - db 0c1h - dw 1800h, offset keyctl_meg - db 0 - - -dip1items db 2, 3, 20h, 5, 1eh, 28h, 00h, 00h - dw offset sw13_t - dw offset sw13_i , offset sw13_i , 0, 0 - dw offset sw13_s0, offset sw13_s1, 0, 0 - - db 2, 5, 10h, 4, 1eh, 30h, 00h, 00h - dw offset sw14_t - dw offset sw14_i0, offset sw14_i1, 0, 0 - dw offset sw14_s0, offset sw14_s1, 0, 0 - - db 4, 8, 0ch, 2, 1eh, 2ah, 36h, 44h - dw offset sw15_t - dw offset sw15_i0, offset sw15_i1 - dw offset sw15_i2, offset sw15_i3 - dw offset sw15_s0, offset sw15_s1 - dw offset sw15_s2, offset sw15_s3 - - db 2,10, 01h, 0, 1eh, 24h, 00h, 00h - dw offset sw18_t - dw offset sw18_i0, offset sw18_i1, 0, 0 - dw offset sw18_s0, offset sw18_s1, 0, 0 - - db 0,12, 00h, 0, 00h, 00h, 00h, 00h - dw offset end_t, offset end_i - -dip2items db 2, 3, 40h, 6, 1eh, 30h, 00h, 00h - dw offset sw22_t - dw offset sw22_i0, offset sw22_i1, 0, 0 - dw offset sw22_s0, offset sw22_s1, 0, 0 - - db 2, 5, 10h, 4, 1eh, 2ch, 00h, 00h - dw offset sw24_t - dw offset sw24_i0, offset sw24_i1, 0, 0 - dw offset sw24_s0, offset sw24_s1, 0, 0 - - db 2, 7, 08h, 3, 1eh, 28h, 00h, 00h - dw offset sw25_t - dw offset sw25_i0, offset sw25_i1, 0, 0 - dw offset sw25_s0, offset sw25_s1, 0, 0 - - db 2, 9, 04h, 2, 1eh, 28h, 00h, 00h - dw offset sw26_t - dw offset sw26_i0, offset sw26_i1, 0, 0 - dw offset sw26_s0, offset sw26_s1, 0, 0 - - db 2,11, 01h, 0, 1eh, 28h, 00h, 00h - dw offset sw28_t - dw offset sw28_i0, offset sw28_i1, 0, 0 - dw offset sw28_s0, offset sw28_s1, 0, 0 - - db 0,13, 00h, 0, 00h, 00h, 00h, 00h - dw offset end_t, offset end_i - -dip3items db 2, 3, 10h, 4, 1eh, 26h, 00h, 00h - dw offset sw34_t - dw offset sw34_i0, offset sw34_i1, 0, 0 - dw offset sw34_s0, offset sw34_s1, 0, 0 - - db 2, 5, 08h, 3, 1eh, 24h, 00h, 00h - dw offset sw35_t - dw offset sw35_i0, offset sw35_i1, 0, 0 - dw offset sw35_s0, offset sw35_s1, 0, 0 - - db 2, 7, 01h, 0, 1eh, 28h, 00h, 00h - dw offset sw38_t - dw offset sw38_i0, offset sw38_i1, 0, 0 - dw offset sw38_s0, offset sw38_s1, 0, 0 - - db 0, 9, 00h, 0, 00h, 00h, 00h, 00h - dw offset end_t, offset end_i - -dipitems dw offset dip1items, dip2items, dip3items - - - - -; ------------------------------------------------- XCb`j[p - -MSWMENU_ITEMS equ 11 - -mswmainmenus dw offset msw_menu00 - dw offset msw_menu01 - dw offset msw_menu02 - dw offset msw_menu03 - dw offset msw_menu04 - dw offset msw_menu05 - dw offset msw_menu06 - dw offset msw_menu07 - dw offset msw_menu08 - dw offset msw_menu09 - dw offset end_t - - -mswsub_m01 db 6 - - db 1, 2 - dw offset mswi011_t, offset mswi011_i - dw 30+ 2*256, offset msg_invalid - dw 60+ 2*256, offset msg_valid - - db 3, 2 - dw offset mswi012_t, offset mswi012_i - dw 30+ 4*256, offset mswi012_1 - dw 60+ 4*256, offset mswi012_2 - - db 5, 2 - dw offset mswi013_t, offset mswi013_i - dw 30+ 6*256, offset mswi013_1 - dw 60+ 6*256, offset mswi013_2 - - db 7, 3 - dw offset mswi014_t, offset mswi014_i - dw 30+ 8*256, offset msg_nouse - dw 46+ 8*256, offset mswi014_2 - dw 62+ 8*256, offset mswi014_3 - - db 9, 3 - dw offset mswi015_t, offset mswi015_i - dw 30+10*256, offset mswi015_1 - dw 46+10*256, offset mswi015_2 - dw 62+10*256, offset mswi015_3 - - db 11, 8 - dw offset mswi016_t, offset mswi016_i - dw 10+12*256, offset mswi016_1 - dw 30+12*256, offset mswi016_2 - dw 50+12*256, offset mswi016_3 - dw 70+12*256, offset mswi016_4 - dw 10+13*256, offset mswi016_5 - dw 30+13*256, offset mswi016_6 - dw 50+13*256, offset mswi016_7 - dw 70+13*256, offset mswi016_8 - -mswsub_m02 db 5 - - db 1, 2 - dw offset mswi021_t, offset mswi021_i - dw 30+ 2*256, offset mswi021_1 - dw 30+ 3*256, offset mswi021_2 - - db 4, 2 - dw offset mswi022_t, offset mswi022_i - dw 30+ 5*256, offset mswi022_1 - dw 30+ 6*256, offset mswi022_2 - - db 7, 2 - dw offset mswi023_t, offset mswi023_i - dw 30+ 8*256, offset mswi023_1 - dw 60+ 8*256, offset mswi023_2 - - db 9, 2 - dw offset mswi024_t, offset mswi024_i - dw 30+10*256, offset msg_invalid - dw 60+10*256, offset msg_valid - - db 11, 2 - dw offset mswi025_t, offset mswi025_i - dw 30+12*256, offset mswi025_1 - dw 60+12*256, offset mswi025_2 - -mswsub_m03 db 1 - - db 1, 5 - dw offset mswi031_t, offset mswi031_i - dw 4+ 2*256, offset mswi031_1 - dw 18+ 2*256, offset mswi031_2 - dw 32+ 2*256, offset mswi031_3 - dw 46+ 2*256, offset mswi031_4 - dw 60+ 2*256, offset mswi031_5 - -mswsub_m04 db 2 - - db 1, 2 - dw offset mswi041_t, offset mswi041_i - dw 30+ 2*256, offset msg_nouse - dw 60+ 2*256, offset msg_use - - db 3, 2 - dw offset mswi042_t, offset mswi042_i - dw 30+ 4*256, offset mswi042_1 - dw 60+ 4*256, offset mswi042_2 - -mswsub_m05 db 1 - - db 1, 2 - dw offset mswi051_t, offset mswi051_i - dw 30+ 2*256, offset mswi051_1 - dw 60+ 2*256, offset mswi051_2 - -mswsub_m06 db 3 - - db 1, 2 - dw offset mswi061_t, offset mswi061_i - dw 30+ 2*256, offset msg_nouse - dw 60+ 2*256, offset msg_use - - db 3, 2 - dw offset mswi062_t, offset mswi062_i - dw 30+ 4*256, offset msg_nouse - dw 60+ 4*256, offset msg_use - - db 5, 2 - dw offset mswi063_t, offset mswi063_i - dw 30+ 6*256, offset msg_nouse - dw 60+ 6*256, offset msg_use - -mswsub_m07 db 3 - - db 1, 2 - dw offset mswi071_t, offset mswi071_i - dw 30+ 2*256, offset msg_nouse - dw 60+ 2*256, offset msg_use - - db 3, 2 - dw offset mswi072_t, offset mswi072_i - dw 30+ 4*256, offset msg_nouse - dw 60+ 4*256, offset msg_use - - db 5, 2 - dw offset mswi073_t, offset mswi073_i - dw 30+ 6*256, offset mswi073_1 - dw 60+ 6*256, offset mswi073_2 - -mswsub_m08 db 3 - - db 1, 6 - dw offset mswi081_t, offset mswi081_i - dw 20+ 2*256, offset mswi081_1 - dw 20+ 3*256, offset mswi081_2 - dw 20+ 4*256, offset mswi081_3 - dw 20+ 5*256, offset mswi081_4 - dw 20+ 6*256, offset mswi081_5 - dw 20+ 7*256, offset mswi081_6 - - db 8, 2 - dw offset mswi082_t, offset mswi082_i - dw 20+ 9*256, offset mswi082_1 - dw 20+10*256, offset mswi082_2 - - db 11, 2 - dw offset mswi083_t, offset mswi083_i - dw 30+12*256, offset msg_use - dw 60+12*256, offset msg_nouse - -mswsub_m09 db 2 - - db 1, 2 - dw offset mswi091_t, offset mswi091_i - dw 30+ 2*256, offset msg_nouse - dw 60+ 2*256, offset msg_use - - db 3, 2 - dw offset mswi092_t, offset mswi092_i - dw 30+ 4*256, offset msg_nouse - dw 60+ 4*256, offset msg_use - -mswsub_m10 db 2 - - db 1, 2 - dw offset mswi101_t, offset mswi101_i - dw 30+ 2*256, offset msg_nouse - dw 60+ 2*256, offset msg_use - - db 3, 2 - dw offset mswi102_t, offset mswi102_i - dw 20+ 4*256, offset mswi102_1 - dw 20+ 5*256, offset mswi102_2 - - -mswsub_items dw offset mswsub_m01, offset mswsub_m02 - dw offset mswsub_m03, offset mswsub_m04 - dw offset mswsub_m05, offset mswsub_m06 - dw offset mswsub_m07, offset mswsub_m08 - dw offset mswsub_m09, offset mswsub_m10 +; SSP用のリソース + +; ------------------------------------------------- ディップスイッチメニュー用 + +dips_initmsgs db 0e1h ; 画面上の枠 + dw 0100h, 1050h + db 0a1h ; 画面下の枠 + dw 1200h, 0650h + db 0 + db 0e1h ; ここからテキスト + dw 0004h, offset menu_title + db 0e1h + dw 011eh, offset dipsw_title + db 0 + +dipbox_initmsgs db 0e1h + dw 121bh, offset dipsw_msg + db 0a1h + dw 130fh, offset dip1_msg + db 0a1h + dw 1327h, offset dip2_msg + db 0a1h + dw 133fh, offset dip3_msg + db 0a1h + dw 1404h, offset off_msg + db 0a1h + dw 1504h, offset on_msg + db 065h + dw 160ah, offset dipnum_msg + db 065h + dw 1622h, offset dipnum_msg + db 065h + dw 163ah, offset dipnum_msg + db 0c1h + dw 1800h, offset keyctl_meg + db 0 + + +dip1items db 2, 3, 20h, 5, 1eh, 28h, 00h, 00h + dw offset sw13_t + dw offset sw13_i , offset sw13_i , 0, 0 + dw offset sw13_s0, offset sw13_s1, 0, 0 + + db 2, 5, 10h, 4, 1eh, 30h, 00h, 00h + dw offset sw14_t + dw offset sw14_i0, offset sw14_i1, 0, 0 + dw offset sw14_s0, offset sw14_s1, 0, 0 + + db 4, 8, 0ch, 2, 1eh, 2ah, 36h, 44h + dw offset sw15_t + dw offset sw15_i0, offset sw15_i1 + dw offset sw15_i2, offset sw15_i3 + dw offset sw15_s0, offset sw15_s1 + dw offset sw15_s2, offset sw15_s3 + + db 2,10, 01h, 0, 1eh, 24h, 00h, 00h + dw offset sw18_t + dw offset sw18_i0, offset sw18_i1, 0, 0 + dw offset sw18_s0, offset sw18_s1, 0, 0 + + db 0,12, 00h, 0, 00h, 00h, 00h, 00h + dw offset end_t, offset end_i + +dip2items db 2, 3, 40h, 6, 1eh, 30h, 00h, 00h + dw offset sw22_t + dw offset sw22_i0, offset sw22_i1, 0, 0 + dw offset sw22_s0, offset sw22_s1, 0, 0 + + db 2, 5, 10h, 4, 1eh, 2ch, 00h, 00h + dw offset sw24_t + dw offset sw24_i0, offset sw24_i1, 0, 0 + dw offset sw24_s0, offset sw24_s1, 0, 0 + + db 2, 7, 08h, 3, 1eh, 28h, 00h, 00h + dw offset sw25_t + dw offset sw25_i0, offset sw25_i1, 0, 0 + dw offset sw25_s0, offset sw25_s1, 0, 0 + + db 2, 9, 04h, 2, 1eh, 28h, 00h, 00h + dw offset sw26_t + dw offset sw26_i0, offset sw26_i1, 0, 0 + dw offset sw26_s0, offset sw26_s1, 0, 0 + + db 2,11, 01h, 0, 1eh, 28h, 00h, 00h + dw offset sw28_t + dw offset sw28_i0, offset sw28_i1, 0, 0 + dw offset sw28_s0, offset sw28_s1, 0, 0 + + db 0,13, 00h, 0, 00h, 00h, 00h, 00h + dw offset end_t, offset end_i + +dip3items db 2, 3, 10h, 4, 1eh, 26h, 00h, 00h + dw offset sw34_t + dw offset sw34_i0, offset sw34_i1, 0, 0 + dw offset sw34_s0, offset sw34_s1, 0, 0 + + db 2, 5, 08h, 3, 1eh, 24h, 00h, 00h + dw offset sw35_t + dw offset sw35_i0, offset sw35_i1, 0, 0 + dw offset sw35_s0, offset sw35_s1, 0, 0 + + db 2, 7, 01h, 0, 1eh, 28h, 00h, 00h + dw offset sw38_t + dw offset sw38_i0, offset sw38_i1, 0, 0 + dw offset sw38_s0, offset sw38_s1, 0, 0 + + db 0, 9, 00h, 0, 00h, 00h, 00h, 00h + dw offset end_t, offset end_i + +dipitems dw offset dip1items, dip2items, dip3items + + + + +; ------------------------------------------------- メモリスイッチメニュー用 + +MSWMENU_ITEMS equ 11 + +mswmainmenus dw offset msw_menu00 + dw offset msw_menu01 + dw offset msw_menu02 + dw offset msw_menu03 + dw offset msw_menu04 + dw offset msw_menu05 + dw offset msw_menu06 + dw offset msw_menu07 + dw offset msw_menu08 + dw offset msw_menu09 + dw offset end_t + + +mswsub_m01 db 6 + + db 1, 2 + dw offset mswi011_t, offset mswi011_i + dw 30+ 2*256, offset msg_invalid + dw 60+ 2*256, offset msg_valid + + db 3, 2 + dw offset mswi012_t, offset mswi012_i + dw 30+ 4*256, offset mswi012_1 + dw 60+ 4*256, offset mswi012_2 + + db 5, 2 + dw offset mswi013_t, offset mswi013_i + dw 30+ 6*256, offset mswi013_1 + dw 60+ 6*256, offset mswi013_2 + + db 7, 3 + dw offset mswi014_t, offset mswi014_i + dw 30+ 8*256, offset msg_nouse + dw 46+ 8*256, offset mswi014_2 + dw 62+ 8*256, offset mswi014_3 + + db 9, 3 + dw offset mswi015_t, offset mswi015_i + dw 30+10*256, offset mswi015_1 + dw 46+10*256, offset mswi015_2 + dw 62+10*256, offset mswi015_3 + + db 11, 8 + dw offset mswi016_t, offset mswi016_i + dw 10+12*256, offset mswi016_1 + dw 30+12*256, offset mswi016_2 + dw 50+12*256, offset mswi016_3 + dw 70+12*256, offset mswi016_4 + dw 10+13*256, offset mswi016_5 + dw 30+13*256, offset mswi016_6 + dw 50+13*256, offset mswi016_7 + dw 70+13*256, offset mswi016_8 + +mswsub_m02 db 5 + + db 1, 2 + dw offset mswi021_t, offset mswi021_i + dw 30+ 2*256, offset mswi021_1 + dw 30+ 3*256, offset mswi021_2 + + db 4, 2 + dw offset mswi022_t, offset mswi022_i + dw 30+ 5*256, offset mswi022_1 + dw 30+ 6*256, offset mswi022_2 + + db 7, 2 + dw offset mswi023_t, offset mswi023_i + dw 30+ 8*256, offset mswi023_1 + dw 60+ 8*256, offset mswi023_2 + + db 9, 2 + dw offset mswi024_t, offset mswi024_i + dw 30+10*256, offset msg_invalid + dw 60+10*256, offset msg_valid + + db 11, 2 + dw offset mswi025_t, offset mswi025_i + dw 30+12*256, offset mswi025_1 + dw 60+12*256, offset mswi025_2 + +mswsub_m03 db 1 + + db 1, 5 + dw offset mswi031_t, offset mswi031_i + dw 4+ 2*256, offset mswi031_1 + dw 18+ 2*256, offset mswi031_2 + dw 32+ 2*256, offset mswi031_3 + dw 46+ 2*256, offset mswi031_4 + dw 60+ 2*256, offset mswi031_5 + +mswsub_m04 db 2 + + db 1, 2 + dw offset mswi041_t, offset mswi041_i + dw 30+ 2*256, offset msg_nouse + dw 60+ 2*256, offset msg_use + + db 3, 2 + dw offset mswi042_t, offset mswi042_i + dw 30+ 4*256, offset mswi042_1 + dw 60+ 4*256, offset mswi042_2 + +mswsub_m05 db 1 + + db 1, 2 + dw offset mswi051_t, offset mswi051_i + dw 30+ 2*256, offset mswi051_1 + dw 60+ 2*256, offset mswi051_2 + +mswsub_m06 db 3 + + db 1, 2 + dw offset mswi061_t, offset mswi061_i + dw 30+ 2*256, offset msg_nouse + dw 60+ 2*256, offset msg_use + + db 3, 2 + dw offset mswi062_t, offset mswi062_i + dw 30+ 4*256, offset msg_nouse + dw 60+ 4*256, offset msg_use + + db 5, 2 + dw offset mswi063_t, offset mswi063_i + dw 30+ 6*256, offset msg_nouse + dw 60+ 6*256, offset msg_use + +mswsub_m07 db 3 + + db 1, 2 + dw offset mswi071_t, offset mswi071_i + dw 30+ 2*256, offset msg_nouse + dw 60+ 2*256, offset msg_use + + db 3, 2 + dw offset mswi072_t, offset mswi072_i + dw 30+ 4*256, offset msg_nouse + dw 60+ 4*256, offset msg_use + + db 5, 2 + dw offset mswi073_t, offset mswi073_i + dw 30+ 6*256, offset mswi073_1 + dw 60+ 6*256, offset mswi073_2 + +mswsub_m08 db 3 + + db 1, 6 + dw offset mswi081_t, offset mswi081_i + dw 20+ 2*256, offset mswi081_1 + dw 20+ 3*256, offset mswi081_2 + dw 20+ 4*256, offset mswi081_3 + dw 20+ 5*256, offset mswi081_4 + dw 20+ 6*256, offset mswi081_5 + dw 20+ 7*256, offset mswi081_6 + + db 8, 2 + dw offset mswi082_t, offset mswi082_i + dw 20+ 9*256, offset mswi082_1 + dw 20+10*256, offset mswi082_2 + + db 11, 2 + dw offset mswi083_t, offset mswi083_i + dw 30+12*256, offset msg_use + dw 60+12*256, offset msg_nouse + +mswsub_m09 db 2 + + db 1, 2 + dw offset mswi091_t, offset mswi091_i + dw 30+ 2*256, offset msg_nouse + dw 60+ 2*256, offset msg_use + + db 3, 2 + dw offset mswi092_t, offset mswi092_i + dw 30+ 4*256, offset msg_nouse + dw 60+ 4*256, offset msg_use + +mswsub_m10 db 2 + + db 1, 2 + dw offset mswi101_t, offset mswi101_i + dw 30+ 2*256, offset msg_nouse + dw 60+ 2*256, offset msg_use + + db 3, 2 + dw offset mswi102_t, offset mswi102_i + dw 20+ 4*256, offset mswi102_1 + dw 20+ 5*256, offset mswi102_2 + + +mswsub_items dw offset mswsub_m01, offset mswsub_m02 + dw offset mswsub_m03, offset mswsub_m04 + dw offset mswsub_m05, offset mswsub_m06 + dw offset mswsub_m07, offset mswsub_m08 + dw offset mswsub_m09, offset mswsub_m10 diff --git a/romimage/SSP_SUB.X86 b/romimage/SSP_SUB.X86 index 18bdbc6f..ae0b8648 100644 --- a/romimage/SSP_SUB.X86 +++ b/romimage/SSP_SUB.X86 @@ -1,56 +1,56 @@ -ssp_resdisp: xor di, di - mov cx, 1950h - call boxclear -ssp_rboxdisp: db FIXCS - lodsb - cmp al, 0 - je short ssp_rtxtdisp - mov cl, al - db FIXCS - lodsw - mov dx, ax - db FIXCS - lodsw - mov bx, ax - call puttextbox - jmps ssp_rboxdisp -ssp_rtxtdisp: db FIXCS - lodsb - cmp al, 0 - je ssp_resdsp_ed - mov cl, al - db FIXCS - lodsw - mov dx, ax - db FIXCS - lodsw - push si - mov si, ax - call disptextjis - pop si - jmps ssp_rtxtdisp -ssp_resdsp_ed: ret - - - -ssp_keyevent: push ax -keyeventst: mov al, -1 -keyeventlp: out 5fh, al - xchg al, ds:[KEYSTAT] - out 5fh, al - cmp al, -1 - je keyeventlp - push si -keyeventsea: mov ah, cs:[si] - cmp ah, al - je keyeventhit - add si, 3 - cmp ah, -1 - jne keyeventsea - pop si - jmps keyeventst -keyeventhit: pop ax - pop ax - jmp word ptr cs:[si+1] - - +ssp_resdisp: xor di, di + mov cx, 1950h + call boxclear +ssp_rboxdisp: db FIXCS + lodsb + cmp al, 0 + je short ssp_rtxtdisp + mov cl, al + db FIXCS + lodsw + mov dx, ax + db FIXCS + lodsw + mov bx, ax + call puttextbox + jmps ssp_rboxdisp +ssp_rtxtdisp: db FIXCS + lodsb + cmp al, 0 + je ssp_resdsp_ed + mov cl, al + db FIXCS + lodsw + mov dx, ax + db FIXCS + lodsw + push si + mov si, ax + call disptextjis + pop si + jmps ssp_rtxtdisp +ssp_resdsp_ed: ret + + + +ssp_keyevent: push ax +keyeventst: mov al, -1 +keyeventlp: out 5fh, al + xchg al, ds:[KEYSTAT] + out 5fh, al + cmp al, -1 + je keyeventlp + push si +keyeventsea: mov ah, cs:[si] + cmp ah, al + je keyeventhit + add si, 3 + cmp ah, -1 + jne keyeventsea + pop si + jmps keyeventst +keyeventhit: pop ax + pop ax + jmp word ptr cs:[si+1] + + diff --git a/romimage/TEXTDISP.X86 b/romimage/TEXTDISP.X86 index 01ee8778..dfb03793 100644 --- a/romimage/TEXTDISP.X86 +++ b/romimage/TEXTDISP.X86 @@ -1,273 +1,273 @@ -; eLXgn - -SCREEN_CLEAR: mov ax, 0a000h - mov es, ax - xor di, di - mov ax, 20h ; ' ' - mov cx, 1000h - rep stosw - mov cx, 0fe0h - mov al, 0e1h -scrnclr_atrclr: stosb - inc di - loop scrnclr_atrclr - ret - -; --------------------------------------------------------------------------- - -sub_clri2a: mov si, I2ABUFFER - mov cx, 10 -sub_clri2al: mov byte ptr [si], 20h - inc si - loop sub_clri2al - mov [si], cl - ret - -; i2a in-ax / out-si / broken ax,cx,dx -STRING_I2A: call sub_clri2a - or ax, ax - jne short sub_i2a - dec si - mov byte ptr [si], '0' - mov cx, 4 - ret - -; l2a in-ax,dx / out-si / broken ax,cx,dx -STRING_L2A: mov cx, 10000 - div cx ; error case - dx:ax > 655350000 - push ax - mov ax, dx - call STRING_I2A - pop ax - or ax, ax - je short sub_i2aed2 - dec cx - je sub_i2a -sub_l2afil0: dec si - mov byte ptr [si], '0' - loop sub_l2afil0 - -sub_i2a: push bx - mov cx, 5 - mov bx, 10 -sub_i2alp1: xor dx, dx - cmp ax, dx - je short sub_i2aed1 - div bx - add dl, '0' - dec si - mov [si], dl - loop sub_i2alp1 -sub_i2aed1: pop bx -sub_i2aed2: ret - -; --------------------------------------------------------------------------- - -calc_dx2di: mov di, dx - and di, 007fh - add di, di - mov al, 160 - mul dh - add di, ax -textoutexit: ret - -;TEXTOUT_DSLOC: mov dx, ds:[LOCATION] -TEXTOUT_DS: call calc_dx2di -textoutdslp: lodsb - and ax, 7fh - je short textoutexit - mov es:[di+2000h], cl - stosw - inc dl - jmps textoutdslp - -textoutcsr: pop dx - inc dh -TEXTOUT_CS: push dx -textoutcsl: call calc_dx2di -textoutcslp: db FIXCS - lodsb - and ax, 00ffh - je short textoutcse - cmp al, 7fh - jae textoutcsext - cmp al, 20h - jc short textoutcsp -textoutcs1: mov es:[di+2000h], cl - stosw - inc dl - jmps textoutcslp -textoutcse: add sp, 2 - ret -textoutcsp: dec al -textoutcsp2: add ax, ax - push si - mov si, ax - mov si, cs:KEYTABLE[si] - mov ax, offset textoutcspe - push ax - push dx - jmps textoutcslp -textoutcspe: pop si - jmps textoutcslp - -textoutcsext: jne short textoutcsk - inc dh - mov dl, ah - jmps textoutcsl -textoutcse2: je textoutcsr - dec al - mov ah, al - db FIXCS - lodsb - add ax, 31 - jmps textoutcsp2 -textoutcsk: sub al, 80h - je short textoutcska - cmp al, 1fh - jbe short textoutcse2 - mov ah, al - db FIXCS - lodsb - mov es:[di+2000h], cl - stosw - mov es:[di+2000h], cl - inc di - inc di - add dl, 2 - jmps textoutcslp -textoutcska: db FIXCS - lodsb - jmps textoutcs1 - - - - - - - -textoutskpr: pop dx - inc dh -TEXTOUT_SKIP: push dx -textoutskplp: db FIXCS - lodsb - and ax, 00ffh - je short textoutcse - cmp al, 7fh - jae textoutskpext - cmp al, 20h - jc short textoutskpp - inc dl - jmps textoutskplp -textoutskpe2: je textoutskpr - dec al - mov ah, al - db FIXCS - lodsb - add ax, 32 -textoutskpp: dec al -textoutskp2: add ax, ax - push si - mov si, ax - mov si, cs:KEYTABLE[si] - mov ax, offset textoutskppe - push ax - push dx - jmps textoutskplp -textoutskppe: pop si - jmps textoutskplp -textoutskpext: jne short textoutskpk - inc dh - mov dl, ah - jmps textoutskplp -textoutskpk: sub al, 80h - je short textoutskpka - cmp al, 1fh - jbe short textoutskpe2 - inc dl -textoutskpka: inc si - inc dl - jmps textoutskplp - - - - - -; --------------------------------------------------------------------------- - -; boxclear: Fboxfill - in: adrs->di, y->ch x->cl - -boxclear: push bx - mov ax, 20h - mov bh, 0e1h - mov bl, ch -boxclearylp: push di - push cx - mov ch, 0 -boxclearxlp: mov es:[di+2000h], bh - stosw - loop boxclearxlp - pop cx - pop di - add di, 160 - dec bl - jne boxclearylp - pop bx - ret - - - -; puttextbox: g - in: start->dx, size->bx, color->cl - -puttextbox: push bx - push cx - push dx - push di - call calc_dx2di - mov ch, bh - sub ch, 2 - js putbox_ed - mov bh, 0 - sub bx, 2 - js putbox_ed - mov ax, 09ch - call putboxv - add di, 160 - or ch, ch - je putbox_bm - push bx - inc bx - add bx, bx -putboxh_lp: mov word ptr es:[di], 96h - mov es:[di+2000h], cl - mov word ptr es:[di+bx], 96h - mov es:[di+bx+2000h], cl - add di, 160 - dec ch - jne putboxh_lp - pop bx -putbox_bm: mov ax, 09eh - call putboxv -putbox_ed: pop di - pop dx - pop cx - pop bx - ret -putboxv: push di - mov es:[di+2000h], cl - stosw - or bx, bx - je putboxr - push bx -putboxc_lp: mov es:[di+2000h], cl - mov word ptr es:[di], 0095h - inc di - inc di - dec bx - jne putboxc_lp - pop bx -putboxr: inc al - mov es:[di+2000h], cl - stosw - pop di - ret +; テキスト操作系 + +SCREEN_CLEAR: mov ax, 0a000h + mov es, ax + xor di, di + mov ax, 20h ; ' ' + mov cx, 1000h + rep stosw + mov cx, 0fe0h + mov al, 0e1h +scrnclr_atrclr: stosb + inc di + loop scrnclr_atrclr + ret + +; --------------------------------------------------------------------------- + +sub_clri2a: mov si, I2ABUFFER + mov cx, 10 +sub_clri2al: mov byte ptr [si], 20h + inc si + loop sub_clri2al + mov [si], cl + ret + +; i2a in-ax / out-si / broken ax,cx,dx +STRING_I2A: call sub_clri2a + or ax, ax + jne short sub_i2a + dec si + mov byte ptr [si], '0' + mov cx, 4 + ret + +; l2a in-ax,dx / out-si / broken ax,cx,dx +STRING_L2A: mov cx, 10000 + div cx ; error case - dx:ax > 655350000 + push ax + mov ax, dx + call STRING_I2A + pop ax + or ax, ax + je short sub_i2aed2 + dec cx + je sub_i2a +sub_l2afil0: dec si + mov byte ptr [si], '0' + loop sub_l2afil0 + +sub_i2a: push bx + mov cx, 5 + mov bx, 10 +sub_i2alp1: xor dx, dx + cmp ax, dx + je short sub_i2aed1 + div bx + add dl, '0' + dec si + mov [si], dl + loop sub_i2alp1 +sub_i2aed1: pop bx +sub_i2aed2: ret + +; --------------------------------------------------------------------------- + +calc_dx2di: mov di, dx + and di, 007fh + add di, di + mov al, 160 + mul dh + add di, ax +textoutexit: ret + +;TEXTOUT_DSLOC: mov dx, ds:[LOCATION] +TEXTOUT_DS: call calc_dx2di +textoutdslp: lodsb + and ax, 7fh + je short textoutexit + mov es:[di+2000h], cl + stosw + inc dl + jmps textoutdslp + +textoutcsr: pop dx + inc dh +TEXTOUT_CS: push dx +textoutcsl: call calc_dx2di +textoutcslp: db FIXCS + lodsb + and ax, 00ffh + je short textoutcse + cmp al, 7fh + jae textoutcsext + cmp al, 20h + jc short textoutcsp +textoutcs1: mov es:[di+2000h], cl + stosw + inc dl + jmps textoutcslp +textoutcse: add sp, 2 + ret +textoutcsp: dec al +textoutcsp2: add ax, ax + push si + mov si, ax + mov si, cs:KEYTABLE[si] + mov ax, offset textoutcspe + push ax + push dx + jmps textoutcslp +textoutcspe: pop si + jmps textoutcslp + +textoutcsext: jne short textoutcsk + inc dh + mov dl, ah + jmps textoutcsl +textoutcse2: je textoutcsr + dec al + mov ah, al + db FIXCS + lodsb + add ax, 31 + jmps textoutcsp2 +textoutcsk: sub al, 80h + je short textoutcska + cmp al, 1fh + jbe short textoutcse2 + mov ah, al + db FIXCS + lodsb + mov es:[di+2000h], cl + stosw + mov es:[di+2000h], cl + inc di + inc di + add dl, 2 + jmps textoutcslp +textoutcska: db FIXCS + lodsb + jmps textoutcs1 + + + + + + + +textoutskpr: pop dx + inc dh +TEXTOUT_SKIP: push dx +textoutskplp: db FIXCS + lodsb + and ax, 00ffh + je short textoutcse + cmp al, 7fh + jae textoutskpext + cmp al, 20h + jc short textoutskpp + inc dl + jmps textoutskplp +textoutskpe2: je textoutskpr + dec al + mov ah, al + db FIXCS + lodsb + add ax, 32 +textoutskpp: dec al +textoutskp2: add ax, ax + push si + mov si, ax + mov si, cs:KEYTABLE[si] + mov ax, offset textoutskppe + push ax + push dx + jmps textoutskplp +textoutskppe: pop si + jmps textoutskplp +textoutskpext: jne short textoutskpk + inc dh + mov dl, ah + jmps textoutskplp +textoutskpk: sub al, 80h + je short textoutskpka + cmp al, 1fh + jbe short textoutskpe2 + inc dl +textoutskpka: inc si + inc dl + jmps textoutskplp + + + + + +; --------------------------------------------------------------------------- + +; boxclear: 黒色のboxfill - in: adrs->di, y->ch x->cl + +boxclear: push bx + mov ax, 20h + mov bh, 0e1h + mov bl, ch +boxclearylp: push di + push cx + mov ch, 0 +boxclearxlp: mov es:[di+2000h], bh + stosw + loop boxclearxlp + pop cx + pop di + add di, 160 + dec bl + jne boxclearylp + pop bx + ret + + + +; puttextbox: 枠 - in: start->dx, size->bx, color->cl + +puttextbox: push bx + push cx + push dx + push di + call calc_dx2di + mov ch, bh + sub ch, 2 + js putbox_ed + mov bh, 0 + sub bx, 2 + js putbox_ed + mov ax, 09ch + call putboxv + add di, 160 + or ch, ch + je putbox_bm + push bx + inc bx + add bx, bx +putboxh_lp: mov word ptr es:[di], 96h + mov es:[di+2000h], cl + mov word ptr es:[di+bx], 96h + mov es:[di+bx+2000h], cl + add di, 160 + dec ch + jne putboxh_lp + pop bx +putbox_bm: mov ax, 09eh + call putboxv +putbox_ed: pop di + pop dx + pop cx + pop bx + ret +putboxv: push di + mov es:[di+2000h], cl + stosw + or bx, bx + je putboxr + push bx +putboxc_lp: mov es:[di+2000h], cl + mov word ptr es:[di], 0095h + inc di + inc di + dec bx + jne putboxc_lp + pop bx +putboxr: inc al + mov es:[di+2000h], cl + stosw + pop di + ret diff --git a/romimage/readme.txt b/romimage/readme.txt index 4d725447..4f97db78 100644 --- a/romimage/readme.txt +++ b/romimage/readme.txt @@ -1,6 +1,6 @@ - -@NP2ł eROMC[W̃\[XłB -@MASM5.1 + EXE2BINłB - -@NP2rh鎞ɂ́AAZu̕Kv͂܂B - + + NP2が抱き込んでいる 各種ROMイメージのソースです。 + MASM5.1 + EXE2BINです。 + + NP2をビルドする時には、アセンブルの必要はありません。 + diff --git a/romimage/tool/BIN2TXT.C b/romimage/tool/BIN2TXT.C index 26035a69..aa5b3e16 100644 --- a/romimage/tool/BIN2TXT.C +++ b/romimage/tool/BIN2TXT.C @@ -1,58 +1,58 @@ -#include -#include -#include "common.h" -#include - -// ----------------------------------------- C - -int main(int argc, BYTE *argv[], BYTE *envp[]) { - - FILEH fh; - BYTE buf[12]; - BYTE out[256]; - WORD i; - WORD j; - - if (argc < 2) { - printf("t@Cw肵ĉ.\n"); - return(1); - } - if ((fh = file_open(argv[1])) == -1) { - printf("t@C‚܂.\n"); - return(2); - } - - if (argc >= 3) { - printf("\nstatic const unsigned char %s[] = {\n", argv[2]); - } - else { - int i; - for (i=0; ; i++) { - if (!argv[1][i]) { - break; - } - if (argv[1][i] == '.') { - break; - } - out[i] = argv[1][i]; - } - out[i] = 0; - printf("\nstatic const unsigned char %s[] = {\n", out); - } - - while(1) { - j = file_read(fh, buf, 12); - if ((j == 0) || (j == -1)) { - break; - } - for (i=0; i +#include +#include "common.h" +#include + +// ----------------------------------------- メイン + +int main(int argc, BYTE *argv[], BYTE *envp[]) { + + FILEH fh; + BYTE buf[12]; + BYTE out[256]; + WORD i; + WORD j; + + if (argc < 2) { + printf("ファイルを指定して下さい.\n"); + return(1); + } + if ((fh = file_open(argv[1])) == -1) { + printf("ファイルが見つかりません.\n"); + return(2); + } + + if (argc >= 3) { + printf("\nstatic const unsigned char %s[] = {\n", argv[2]); + } + else { + int i; + for (i=0; ; i++) { + if (!argv[1][i]) { + break; + } + if (argv[1][i] == '.') { + break; + } + out[i] = argv[1][i]; + } + out[i] = 0; + printf("\nstatic const unsigned char %s[] = {\n", out); + } + + while(1) { + j = file_read(fh, buf, 12); + if ((j == 0) || (j == -1)) { + break; + } + for (i=0; i -#include -#include "common.h" -#include - -#define MAXKEY 256 -#define MAXKEYSIZE 4096 - - char keywork[MAXKEYSIZE]; - char *strkey[MAXKEY]; - char key_hit[MAXKEY]; - char key_byte[MAXKEY]; - - int keys; - int keypos; - -static void milstr_textadj(char *str) { - - int qout = 0; - unsigned char *p, *q; - unsigned char c; - - p = (unsigned char *)str; - q = p; - - while(1) { - if ((c = *p++) == '\0') { - break; - } - if (!qout) { - if (c <= ' ') { - continue; - } - if (c == ';') { - break; - } - } - if (c == '\"') { - if ((!qout) || (*p != '\"')) { - qout ^= 1; - continue; - } - p++; - } - *q++ = c; - } - *q = '\0'; -} - -// --------------------------------------------------- - -char nowsym[80] = ""; -char linestr[80] = ""; -int linestrp = 0; - -void ldata_flash(void) { - - int len; - int tabs; - - if (!linestrp) { - return; - } - - tabs = 1; - len = strlen(nowsym); - if (len < 15) { - tabs += ((15 - len) >> 2); - } - while(tabs--) { - nowsym[len++] = '\t'; - } - nowsym[len] = '\0'; - printf(nowsym); - puts(linestr); - nowsym[0] = 0; - linestrp = 0; -} - -void ldata_set(BYTE dat) { - - if ( linestrp) { - linestr[linestrp++] = ','; - } - else { - strcpy(linestr, "db\t"); - linestrp = 3; - } - sprintf(linestr + linestrp, "0%02xh", dat); - linestrp += 4; - if (linestrp >= 58) { - ldata_flash(); - } -} - -void ldata_symbolset(char *sym) { - - strcpy(nowsym, sym); -} - -// --------------------------------------------------- - -int abstrcmp(BYTE *str) { - - int i; - - for (i=0; i= 0x80) && (c < 0xa0)) || - ((c >= 0xe0) && (c < 0xfc))) { - if (!p[0]) { - break; - } - code = sjis2jis(((*p++) << 8) + c); - if (code) { - ldata_set((BYTE)(code | 0x80)); - ldata_set((BYTE)(code >> 8)); - ret += 2; - } - } - else { - if (c == '\\') { - if (p[0] == '\\') { - ldata_set('\\'); - ret++; - p++; - } - else if (p[0] == 'n') { - ldata_set(0x7f); - ret++; - p++; - } - else if (p[0] == 'z') { - ldata_set(0x9f); - ret++; - p++; - } - else if (p[0] == 'x') { - ldata_set(0x80); - ldata_set(0x9b); - ret+=2; - p++; - } - } - else { - if (c & 0x80) { - ldata_set(0x80); - ret++; - } - ldata_set(c); - ret++; - } - } - } - ldata_set(0); - ldata_flash(); - return(ret + 1); -} - -// --------------------------------------------------- - -void keyinit(void) { - - memset(keywork, 0, sizeof(keywork)); - memset(key_hit, 0, sizeof(key_hit)); - memset(key_byte, 0, sizeof(key_byte)); - keys = 0; - keypos = 0; -} - -void checkkey(BYTE *str) { - - int len; - - if ((str[0] != '#') || (str[1] != '=')) { - return; - } - str += 2; - if (keys >= MAXKEY) { - return; - } - len = strlen(str) + 1; - if ((keypos + len) > MAXKEYSIZE) { - return; - } - strkey[keys] = keywork + keypos; - memcpy(strkey[keys], str, len); - key_byte[keys] = (BYTE)packingout(str); - keypos += len; - keys++; -} - -void txtpacking(BYTE *str) { - - char *p; - int keymatch; - int size; - - p = str; - if ((str[0] == '#') && (str[1] == '=')) { - return; - } - while(*p) { - if (*p == '=') { - break; - } - p++; - } - if (*p != '=') { - return; - } - *p++ = '\0'; - ldata_symbolset(str); - - keymatch = abstrcmp(p); - if (keymatch--) { - size = 0; - while(keymatch--) { - size += (int)key_byte[keymatch]; - } - sprintf(linestr, "equ\t\tKEYDATA + %d", size); - linestrp = 1; - ldata_flash(); - } - else { - packingout(p); - } -} - -// ----------------------------------------- C - -void main(int argc, BYTE *argv[], BYTE *envp[]) { - - FILEH fh; - char str[256]; - int i; - int size; - - keyinit(); - - if (argc < 2) { - printf("͖w肵ĉ.\n"); - return; - } - - if ((fh = file_open(argv[1])) == -1) { - printf("t@C‚܂.\n"); - return; - } - - puts("KEYDATA\tlabel\tbyte"); - - while(file_lread(fh, str, 255)) { - milstr_textadj(str); - checkkey(str); - } - - puts("\nKEYTABLE\tlabel\tword"); - size = 0; - for (i=0; i +#include +#include "common.h" +#include + +#define MAXKEY 256 +#define MAXKEYSIZE 4096 + + char keywork[MAXKEYSIZE]; + char *strkey[MAXKEY]; + char key_hit[MAXKEY]; + char key_byte[MAXKEY]; + + int keys; + int keypos; + +static void milstr_textadj(char *str) { + + int qout = 0; + unsigned char *p, *q; + unsigned char c; + + p = (unsigned char *)str; + q = p; + + while(1) { + if ((c = *p++) == '\0') { + break; + } + if (!qout) { + if (c <= ' ') { + continue; + } + if (c == ';') { + break; + } + } + if (c == '\"') { + if ((!qout) || (*p != '\"')) { + qout ^= 1; + continue; + } + p++; + } + *q++ = c; + } + *q = '\0'; +} + +// --------------------------------------------------- + +char nowsym[80] = ""; +char linestr[80] = ""; +int linestrp = 0; + +void ldata_flash(void) { + + int len; + int tabs; + + if (!linestrp) { + return; + } + + tabs = 1; + len = strlen(nowsym); + if (len < 15) { + tabs += ((15 - len) >> 2); + } + while(tabs--) { + nowsym[len++] = '\t'; + } + nowsym[len] = '\0'; + printf(nowsym); + puts(linestr); + nowsym[0] = 0; + linestrp = 0; +} + +void ldata_set(BYTE dat) { + + if ( linestrp) { + linestr[linestrp++] = ','; + } + else { + strcpy(linestr, "db\t"); + linestrp = 3; + } + sprintf(linestr + linestrp, "0%02xh", dat); + linestrp += 4; + if (linestrp >= 58) { + ldata_flash(); + } +} + +void ldata_symbolset(char *sym) { + + strcpy(nowsym, sym); +} + +// --------------------------------------------------- + +int abstrcmp(BYTE *str) { + + int i; + + for (i=0; i= 0x80) && (c < 0xa0)) || + ((c >= 0xe0) && (c < 0xfc))) { + if (!p[0]) { + break; + } + code = sjis2jis(((*p++) << 8) + c); + if (code) { + ldata_set((BYTE)(code | 0x80)); + ldata_set((BYTE)(code >> 8)); + ret += 2; + } + } + else { + if (c == '\\') { + if (p[0] == '\\') { + ldata_set('\\'); + ret++; + p++; + } + else if (p[0] == 'n') { + ldata_set(0x7f); + ret++; + p++; + } + else if (p[0] == 'z') { + ldata_set(0x9f); + ret++; + p++; + } + else if (p[0] == 'x') { + ldata_set(0x80); + ldata_set(0x9b); + ret+=2; + p++; + } + } + else { + if (c & 0x80) { + ldata_set(0x80); + ret++; + } + ldata_set(c); + ret++; + } + } + } + ldata_set(0); + ldata_flash(); + return(ret + 1); +} + +// --------------------------------------------------- + +void keyinit(void) { + + memset(keywork, 0, sizeof(keywork)); + memset(key_hit, 0, sizeof(key_hit)); + memset(key_byte, 0, sizeof(key_byte)); + keys = 0; + keypos = 0; +} + +void checkkey(BYTE *str) { + + int len; + + if ((str[0] != '#') || (str[1] != '=')) { + return; + } + str += 2; + if (keys >= MAXKEY) { + return; + } + len = strlen(str) + 1; + if ((keypos + len) > MAXKEYSIZE) { + return; + } + strkey[keys] = keywork + keypos; + memcpy(strkey[keys], str, len); + key_byte[keys] = (BYTE)packingout(str); + keypos += len; + keys++; +} + +void txtpacking(BYTE *str) { + + char *p; + int keymatch; + int size; + + p = str; + if ((str[0] == '#') && (str[1] == '=')) { + return; + } + while(*p) { + if (*p == '=') { + break; + } + p++; + } + if (*p != '=') { + return; + } + *p++ = '\0'; + ldata_symbolset(str); + + keymatch = abstrcmp(p); + if (keymatch--) { + size = 0; + while(keymatch--) { + size += (int)key_byte[keymatch]; + } + sprintf(linestr, "equ\t\tKEYDATA + %d", size); + linestrp = 1; + ldata_flash(); + } + else { + packingout(p); + } +} + +// ----------------------------------------- メイン + +void main(int argc, BYTE *argv[], BYTE *envp[]) { + + FILEH fh; + char str[256]; + int i; + int size; + + keyinit(); + + if (argc < 2) { + printf("入力名を指定して下さい.\n"); + return; + } + + if ((fh = file_open(argv[1])) == -1) { + printf("ファイルが見つかりません.\n"); + return; + } + + puts("KEYDATA\tlabel\tbyte"); + + while(file_lread(fh, str, 255)) { + milstr_textadj(str); + checkkey(str); + } + + puts("\nKEYTABLE\tlabel\tword"); + size = 0; + for (i=0; i - -#include "np2.h" -#include "commng.h" -#include - - -// ---- non connect - -static UINT -ncread(COMMNG self, UINT8 *data) -{ - - (void)self; - (void)data; - - return 0; -} - -static UINT -ncwrite(COMMNG self, UINT8 data) -{ - - (void)self; - (void)data; - - return 0; -} - -static UINT -ncwriteretry(COMMNG self) -{ - - (void)self; - - return 1; -} - -static void -ncbeginblocktranster(COMMNG self) -{ - - (void)self; - - return; -} - -static void -ncendblocktranster(COMMNG self) -{ - - (void)self; - - return; -} - -static UINT -nclastwritesuccess(COMMNG self) -{ - - (void)self; - - return 1; -} - -static UINT8 -ncgetstat(COMMNG self) -{ - - (void)self; - - return 0xf0; -} - -static INTPTR -ncmsg(COMMNG self, UINT msg, INTPTR param) -{ - - (void)self; - (void)msg; - (void)param; - - return 0; -} - -static void -ncrelease(COMMNG self) -{ - - /* Nothing to do */ - - (void)self; -} - -static _COMMNG com_nc = { - COMCONNECT_OFF, ncread, ncwrite, ncwriteretry, ncbeginblocktranster, ncendblocktranster, nclastwritesuccess, ncgetstat, ncmsg, ncrelease -}; - - -// ---- - -void -commng_initialize(void) -{ - - cmmidi_initailize(); -} - -COMMNG -commng_create(UINT device, BOOL onReset) -{ - COMMNG ret; - COMCFG *cfg; - - ret = NULL; - - switch (device) { -#if !defined(__LIBRETRO__) - case COMCREATE_SERIAL: - cfg = &np2oscfg.com[0]; - break; - - case COMCREATE_PC9861K1: - cfg = &np2oscfg.com[1]; - break; - - case COMCREATE_PC9861K2: - cfg = &np2oscfg.com[2]; - break; -#endif /* __LIBRETRO__ */ - - case COMCREATE_MPU98II: - cfg = &np2oscfg.mpu; - break; - -#if defined(SUPPORT_SMPU98) - case COMCREATE_SMPU98_A: - cfg = &np2oscfg.smpuA; - break; - - case COMCREATE_SMPU98_B: - cfg = &np2oscfg.smpuB; - break; -#endif - -#if !defined(__LIBRETRO__) - case COMCREATE_PRINTER: - cfg = NULL; - if (np2oscfg.jastsnd) { - ret = cmjasts_create(); - } - break; -#endif /* __LIBRETRO__ */ - - default: - cfg = NULL; - break; - } - if (cfg) { - if ((cfg->port >= COMPORT_COM1) - && (cfg->port <= COMPORT_COM4)) { - if(onReset) return NULL; -#if !defined(__LIBRETRO__) && !defined(EMSCRIPTEN) - ret = cmserial_create(cfg->port - COMPORT_COM1 + 1, cfg->param, cfg->speed); -#endif /* __LIBRETRO__ */ - } else if (cfg->port == COMPORT_MIDI) { - if(onReset) return NULL; -#if !defined(EMSCRIPTEN) - ret = cmmidi_create(device, cfg->mout, cfg->min, cfg->mdl); -#endif - if (ret) { - (*ret->msg)(ret, COMMSG_MIMPIDEFFILE, (INTPTR)cfg->def); - (*ret->msg)(ret, COMMSG_MIMPIDEFEN, (INTPTR)cfg->def_en); - } - } - } - if (ret) - return ret; - return (COMMNG)&com_nc; -} - -void -commng_destroy(COMMNG hdl) -{ - - if (hdl) { - if(hdl->release) { - hdl->release(hdl); - } - } -} +#include + +#include "np2.h" +#include "commng.h" +#include + + +// ---- non connect + +static UINT +ncread(COMMNG self, UINT8 *data) +{ + + (void)self; + (void)data; + + return 0; +} + +static UINT +ncwrite(COMMNG self, UINT8 data) +{ + + (void)self; + (void)data; + + return 0; +} + +static UINT +ncwriteretry(COMMNG self) +{ + + (void)self; + + return 1; +} + +static void +ncbeginblocktranster(COMMNG self) +{ + + (void)self; + + return; +} + +static void +ncendblocktranster(COMMNG self) +{ + + (void)self; + + return; +} + +static UINT +nclastwritesuccess(COMMNG self) +{ + + (void)self; + + return 1; +} + +static UINT8 +ncgetstat(COMMNG self) +{ + + (void)self; + + return 0xf0; +} + +static INTPTR +ncmsg(COMMNG self, UINT msg, INTPTR param) +{ + + (void)self; + (void)msg; + (void)param; + + return 0; +} + +static void +ncrelease(COMMNG self) +{ + + /* Nothing to do */ + + (void)self; +} + +static _COMMNG com_nc = { + COMCONNECT_OFF, ncread, ncwrite, ncwriteretry, ncbeginblocktranster, ncendblocktranster, nclastwritesuccess, ncgetstat, ncmsg, ncrelease +}; + + +// ---- + +void +commng_initialize(void) +{ + + cmmidi_initailize(); +} + +COMMNG +commng_create(UINT device, BOOL onReset) +{ + COMMNG ret; + COMCFG *cfg; + + ret = NULL; + + switch (device) { +#if !defined(__LIBRETRO__) + case COMCREATE_SERIAL: + cfg = &np2oscfg.com[0]; + break; + + case COMCREATE_PC9861K1: + cfg = &np2oscfg.com[1]; + break; + + case COMCREATE_PC9861K2: + cfg = &np2oscfg.com[2]; + break; +#endif /* __LIBRETRO__ */ + + case COMCREATE_MPU98II: + cfg = &np2oscfg.mpu; + break; + +#if defined(SUPPORT_SMPU98) + case COMCREATE_SMPU98_A: + cfg = &np2oscfg.smpuA; + break; + + case COMCREATE_SMPU98_B: + cfg = &np2oscfg.smpuB; + break; +#endif + +#if !defined(__LIBRETRO__) + case COMCREATE_PRINTER: + cfg = NULL; + if (np2oscfg.jastsnd) { + ret = cmjasts_create(); + } + break; +#endif /* __LIBRETRO__ */ + + default: + cfg = NULL; + break; + } + if (cfg) { + if ((cfg->port >= COMPORT_COM1) + && (cfg->port <= COMPORT_COM4)) { + if(onReset) return NULL; +#if !defined(__LIBRETRO__) && !defined(EMSCRIPTEN) + ret = cmserial_create(cfg->port - COMPORT_COM1 + 1, cfg->param, cfg->speed); +#endif /* __LIBRETRO__ */ + } else if (cfg->port == COMPORT_MIDI) { + if(onReset) return NULL; +#if !defined(EMSCRIPTEN) + ret = cmmidi_create(device, cfg->mout, cfg->min, cfg->mdl); +#endif + if (ret) { + (*ret->msg)(ret, COMMSG_MIMPIDEFFILE, (INTPTR)cfg->def); + (*ret->msg)(ret, COMMSG_MIMPIDEFEN, (INTPTR)cfg->def_en); + } + } + } + if (ret) + return ret; + return (COMMNG)&com_nc; +} + +void +commng_destroy(COMMNG hdl) +{ + + if (hdl) { + if(hdl->release) { + hdl->release(hdl); + } + } +} diff --git a/sdl/fontmng.c b/sdl/fontmng.c index f64cf09a..6b23000e 100644 --- a/sdl/fontmng.c +++ b/sdl/fontmng.c @@ -1,701 +1,701 @@ -/** - * @file fontmng.c - * @brief Implementation of the font manager - */ - -#include -#include - -#if defined(NP2_SIZE_QVGA) -#include "ank10.res" -#else /* defined(NP2_SIZE_QVGA) */ -#include "ank12.res" -#endif /* defined(NP2_SIZE_QVGA) */ - -#if defined(SUPPORT_SDL_TTF) /* use TTF */ - -#define FONTMNG_CACHE 64 /*!< Cache count */ - -/*! White */ -static const SDL_Color s_white = {0xff, 0xff, 0xff, 0}; - -#if defined(FONTMNG_CACHE) -typedef struct -{ - UINT16 str; /*!< String Id */ - UINT16 next; /*!< Next index */ -} FNTCTBL; -#endif - -#endif /* defined(SUPPORT_SDL_TTF) */ - -/*! Font face */ -static char s_sFontName[MAX_PATH] = "./default.ttf"; - -/** - * @brief Handle - */ -struct TagFontManager -{ - int fontsize; - UINT fonttype; - -#if defined(SUPPORT_SDL_TTF) - TTF_Font *ttf_font; - int ptsize; - int fontalign; -#endif /* defined(SUPPORT_SDL_TTF) */ - -#if defined(FONTMNG_CACHE) - UINT caches; - UINT cachehead; - FNTCTBL cache[FONTMNG_CACHE]; -#endif /* defined(FONTMNG_CACHE) */ -}; -typedef struct TagFontManager *FNTMNG; /*!< Defines handle */ - -#if defined(FONTMNG_CACHE) -/** - * - */ -static BOOL fdatgetcache(FNTMNG fhdl, UINT16 c, FNTDAT *pfdat) -{ - BOOL r; - FNTCTBL *fct; - UINT pos; - UINT prev; - UINT cnt; - - r = FALSE; - fct = fhdl->cache; - cnt = fhdl->caches; - pos = fhdl->cachehead; - prev = FONTMNG_CACHE; - while (cnt--) - { - if (fct[pos].str != c) - { - prev = pos; - pos = fct[pos].next; - continue; - } - if (prev < FONTMNG_CACHE) - { - fct[prev].next = fct[pos].next; - fct[pos].next = (UINT16)fhdl->cachehead; - fhdl->cachehead = pos; - } - r = TRUE; - break; - } - if (r == FALSE) - { - if (fhdl->caches < FONTMNG_CACHE) - { - pos = fhdl->caches; - fhdl->caches++; - } - else - { - pos = prev; - } - fct[pos].str = c; - fct[pos].next = (UINT16)fhdl->cachehead; - fhdl->cachehead = pos; - } - if (pfdat) - { - *pfdat = (FNTDAT)(((UINT8 *)(fhdl + 1)) + (pos * fhdl->fontalign)); - } - return r; -} -#endif /* defined(FONTMNG_CACHE) */ - -/** - * Initialize - * @retval SUCCESS Succeeded - * @retval FAILURE Failed - */ -BRESULT fontmng_init(void) -{ -#if defined(SUPPORT_SDL_TTF) - - if (TTF_Init() < 0) - { - fprintf(stderr, "Couldn't initialize TTF: %s\n", SDL_GetError()); - return FAILURE; - } -#ifndef WIN32 - atexit(TTF_Quit); -#endif - -#endif /* defined(SUPPORT_SDL_TTF) */ - - return SUCCESS; -} - -/** - * Sets font face - * @param[in] name name - */ -void fontmng_setdeffontname(const char *name) -{ - milstr_ncpy(s_sFontName, name, NELEMENTS(s_sFontName)); -} - -/** - * Creates instance - */ -void *fontmng_create(int size, UINT type, const char *fontface) -{ - int fontalign; - int fontwork; - int allocsize; - FNTMNG ret; - -#if defined(SUPPORT_SDL_TTF) - TTF_Font *ttf_font; - int ptsize; -#endif /* defined(SUPPORT_SDL_TTF) */ - - if (size < 0) - { - size = -size; - } - if (size < 6) - { - size = 6; - } - else if (size > 128) - { - size = 128; - } - -#if defined(SUPPORT_SDL_TTF) - - if (size < 10) - { - type |= FDAT_ALIAS; - } - else if (size < 16) - { - type &= ~FDAT_BOLD; - } - - ptsize = size; - if (type & FDAT_ALIAS) - { - ptsize *= 2; - } - ttf_font = TTF_OpenFont(s_sFontName, ptsize); - if (ttf_font == NULL) - { - fprintf(stderr, "Couldn't load %d points font from %s: %s\n", ptsize, s_sFontName, SDL_GetError()); - - if (size < ANKFONTSIZE) - { - return NULL; - } - - ptsize = size; - type &= FDAT_PROPORTIONAL; - } - -#else /* defined(SUPPORT_SDL_TTF) */ - - if (size < ANKFONTSIZE) - { - return NULL; - } - -#endif /* defined(SUPPORT_SDL_TTF) */ - - fontalign = sizeof(_FNTDAT) + (size * size); - fontalign = (fontalign + 3) & (~3); -#if defined(FONTMNG_CACHE) - fontwork = fontalign * FONTMNG_CACHE; -#else - fontwork = fontalign; -#endif - - allocsize = sizeof(*ret) + fontwork; - ret = (FNTMNG)_MALLOC(allocsize, "font mng"); - if (ret == NULL) - { -#if defined(SUPPORT_SDL_TTF) - TTF_CloseFont(ttf_font); -#endif /* defined(SUPPORT_SDL_TTF) */ - return NULL; - } - - memset(ret, 0, allocsize); - ret->fontsize = size; - ret->fonttype = type; - -#if defined(SUPPORT_SDL_TTF) - ret->ttf_font = ttf_font; - ret->ptsize = ptsize; - ret->fontalign = fontalign; -#endif /* defined(SUPPORT_SDL_TTF) */ - - return ret; -} - -/** - * Destroy - * @param[in] hdl Handle - */ -void fontmng_destroy(void *hdl) -{ - FNTMNG _this; - - _this = (FNTMNG)hdl; - if (_this) - { - -#if defined(SUPPORT_SDL_TTF) - TTF_CloseFont(_this->ttf_font); -#endif /* defined(SUPPORT_SDL_TTF) */ - - _MFREE(_this); - } -} - -/** - * Sets font header - * @param[in] _this Instance - * @param[out] fdat Data header - * @param[in] s SDL_Surface - */ -static void AnkSetFontHeader(FNTMNG _this, FNTDAT fdat, int width) -{ - if (_this->fonttype & FDAT_PROPORTIONAL) - { - fdat->width = width; - fdat->pitch = width + 1; - fdat->height = _this->fontsize; - } - else - { - fdat->width = MAX(width, _this->fontsize >> 1); - fdat->pitch = (_this->fontsize >> 1) + 1; - fdat->height = _this->fontsize; - } -} - -/** - * Gets font length - * @param[in] _this Instance - * @param[out] fdat Data - * @param[in] c Charactor - */ -static void AnkGetLength1(FNTMNG _this, FNTDAT fdat, UINT16 c) -{ - c = c - 0x20; - if ((c < 0) || (c >= 0x60)) - { - c = 0x1f; /* '?' */ - } - AnkSetFontHeader(_this, fdat, ankfont[c * ANKFONTSIZE]); -} - -/** - * Gets font face (TTF) - * @param[in] _this Instance - * @param[out] fdat Data - * @param[in] c Charactor - */ -static void AnkGetFont1(FNTMNG _this, FNTDAT fdat, UINT16 c) -{ -const UINT8 *src; - int width; - UINT8 *dst; - int x; - int y; - - c = c - 0x20; - if ((c < 0) || (c >= 0x60)) - { - c = 0x1f; /* '?' */ - } - src = ankfont + (c * ANKFONTSIZE); - width = *src++; - AnkSetFontHeader(_this, fdat, width); - dst = (UINT8 *)(fdat + 1); - memset(dst, 0, fdat->width * fdat->height); - dst += ((fdat->height - ANKFONTSIZE) / 2) * fdat->width; - dst += (fdat->width - width) / 2; - for (y = 0; y < (ANKFONTSIZE - 1); y++) - { - dst += fdat->width; - for (x = 0; x < width; x++) - { - dst[x] = (src[0] & (0x80 >> x)) ? 0xff : 0x00; - } - src++; - } -} - -#if !defined(SUPPORT_SDL_TTF) - -#define GetLength1 AnkGetLength1 /*!< length function */ -#define GetFont1 AnkGetFont1 /*!< face function */ - -#else // !defined(SUPPORT_SDL_TTF) - -#define GetLength1 TTFGetLength1 /*!< length function */ -#define GetFont1 TTFGetFont1 /*!< face function */ - -/** - * Sets font header (TTF) - * @param[in] _this Instance - * @param[out] fdat Data header - * @param[in] s SDL_Surface - */ -static void TTFSetFontHeader(FNTMNG _this, FNTDAT fdat, const SDL_Surface *s) -{ - int width; - int height; - int pitch; - - if (s) - { - width = MIN(s->w, _this->ptsize); - height = MIN(s->h, _this->ptsize); - } - else - { - width = _this->fontsize; - height = _this->fontsize; - } - - pitch = width; - if (_this->fonttype & FDAT_ALIAS) - { - width = (width + 1) >> 1; - pitch = width >> 1; - height = (height + 1) >> 1; - } - fdat->width = width; - fdat->pitch = pitch; - fdat->height = height; -} - -/** - * Get pixel - * @param[in] s SDL_Surface - * @param[in] x x - * @param[in] y y - * @return pixel - */ -static UINT8 TTFGetPixelDepth(const SDL_Surface *s, int x, int y) -{ - int nXAlign; - const UINT8 *ptr; - - if ((x >= 0) && (x < s->w) && (y >= 0) && (y < s->h)) - { -#if USE_SDL >= 3 - nXAlign = SDL_BYTESPERPIXEL(s->format); -#else - nXAlign = s->format->BytesPerPixel; -#endif - ptr = (UINT8 *)s->pixels + (y * s->pitch) + (x * nXAlign); - switch (nXAlign) - { - case 1: - return (ptr[0] != 0) ? FDAT_DEPTH : 0; - - case 3: - case 4: - return (ptr[0] * FDAT_DEPTH / 255); - } - } - return 0; -} - -/** - * Gets font length (TTF) - * @param[in] _this Instance - * @param[out] fdat Data - * @param[in] c Charactor - */ -static void TTFGetLength1(FNTMNG _this, FNTDAT fdat, UINT16 c) -{ - UINT16 sString[2]; - SDL_Surface *s; - - sString[0] = c; - sString[1] = 0; - s = NULL; - if (_this->ttf_font) - { -#if USE_SDL >= 3 - s = TTF_RenderText_Solid(_this->ttf_font, sString, strlen(sString), s_white); -#else - s = TTF_RenderUNICODE_Solid(_this->ttf_font, sString, s_white); -#endif - } - if (s) - { - TTFSetFontHeader(_this, fdat, s); -#if USE_SDL >= 3 - SDL_DestroySurface(s); -#else - SDL_FreeSurface(s); -#endif - } - else - { - AnkGetLength1(_this, fdat, c); - } -} - -/** - * Gets font face (TTF) - * @param[in] _this Instance - * @param[out] fdat Data - * @param[in] c Charactor - */ -static void TTFGetFont1(FNTMNG _this, FNTDAT fdat, UINT16 c) -{ - UINT16 sString[2]; - SDL_Surface *s; - UINT8 *dst; - int x; - int y; - int depth; - int minx; - int maxy; - int advance; - - sString[0] = c; - sString[1] = 0; - s = NULL; - if (_this->ttf_font) - { -#if USE_SDL >= 3 - s = TTF_RenderText_Solid(_this->ttf_font, sString, strlen(sString), s_white); -#else - s = TTF_RenderUNICODE_Solid(_this->ttf_font, sString, s_white); -#endif - } - if (s) - { - TTFSetFontHeader(_this, fdat, s); - dst = (UINT8 *)(fdat + 1); - if (_this->fonttype & FDAT_ALIAS) - { -#if USE_SDL >= 3 - TTF_GetGlyphMetrics(_this->ttf_font,s,&minx,NULL,NULL,&maxy,&advance); -#else - TTF_GlyphMetrics(_this->ttf_font,s,&minx,NULL,NULL,&maxy,&advance); -#endif - for (y = 0; y < fdat->height; y++) - { - for (x = 0; x < fdat->width; x++) - { -#if USE_SDL >= 3 - depth = TTFGetPixelDepth(s, (x-minx)*2+0, (y+(TTF_GetFontAscent(_this->ttf_font)-maxy))*2+0); - depth += TTFGetPixelDepth(s, (x-minx)*2+1, (y+(TTF_GetFontAscent(_this->ttf_font)-maxy))*2+0); - depth += TTFGetPixelDepth(s, (x-minx)*2+0, (y+(TTF_GetFontAscent(_this->ttf_font)-maxy))*2+1); - depth += TTFGetPixelDepth(s, (x-minx)*2+1, (y+(TTF_GetFontAscent(_this->ttf_font)-maxy))*2+1); -#else - depth = TTFGetPixelDepth(s, (x-minx)*2+0, (y+(TTF_FontAscent(_this->ttf_font)-maxy))*2+0); - depth += TTFGetPixelDepth(s, (x-minx)*2+1, (y+(TTF_FontAscent(_this->ttf_font)-maxy))*2+0); - depth += TTFGetPixelDepth(s, (x-minx)*2+0, (y+(TTF_FontAscent(_this->ttf_font)-maxy))*2+1); - depth += TTFGetPixelDepth(s, (x-minx)*2+1, (y+(TTF_FontAscent(_this->ttf_font)-maxy))*2+1); -#endif - } - } - } - else - { -#if USE_SDL >= 3 - TTF_GetGlyphMetrics(_this->ttf_font,s,&minx,NULL,NULL,&maxy,&advance); -#else - TTF_GlyphMetrics(_this->ttf_font,s,&minx,NULL,NULL,&maxy,&advance); -#endif - for (y = 0; y < fdat->height; y++) - { - for (x = 0; x < fdat->width; x++) - { -#if USE_SDL >= 3 - *dst++ = TTFGetPixelDepth(s, x-minx, (y+(TTF_GetFontAscent(_this->ttf_font)-maxy))); -#else - *dst++ = TTFGetPixelDepth(s, x-minx, (y+(TTF_FontAscent(_this->ttf_font)-maxy))); -#endif - } - } - } -#if USE_SDL >= 3 - SDL_DestroySurface(s); -#else - SDL_FreeSurface(s); -#endif - } - else - { - AnkGetFont1(_this, fdat, c); - } -} - -#endif /* !defined(SUPPORT_SDL_TTF) */ - -/** - * Get charactor - * @param[in,out] lppString Pointer - * @return Charactor - */ -static UINT16 GetChar(const char** lppString) -{ - const char *lpString; - UINT16 c; - - lpString = *lppString; - if (lpString == NULL) - { - return 0; - } - - c = 0; - if ((lpString[0] & 0x80) == 0) - { - c = lpString[0] & 0x7f; - lpString++; - } - else if (((lpString[0] & 0xe0) == 0xc0) && ((lpString[1] & 0xc0) == 0x80)) - { - c = ((lpString[0] & 0x1f) << 6) | (lpString[1] & 0x3f); - lpString += 2; - } - else if (((lpString[0] & 0xf0) == 0xe0) && ((lpString[1] & 0xc0) == 0x80) && ((lpString[2] & 0xc0) == 0x80)) - { - c = ((lpString[0] & 0x0f) << 12) | ((lpString[1] & 0x3f) << 6) | (lpString[2] & 0x3f); - lpString += 3; - } - - *lppString = lpString; - return c; -} - -/** - * Get font size - * @param[in] hdl Handle - * @param[in] lpString String - * @param[out] pt Size - * @retval SUCCESS Succeeded - * @retval FAILURE Failed - */ -BRESULT fontmng_getsize(void *hdl, const char *lpString, POINT_T *pt) -{ - FNTMNG _this; - int nWidth; - UINT16 c; - _FNTDAT fontData; - - _this = (FNTMNG)hdl; - if ((_this == NULL) || (lpString == NULL)) - { - return FAILURE; - } - - nWidth = 0; - while (1 /* EVER */) - { - c = GetChar(&lpString); - if (c == 0) - { - break; - } - GetLength1(_this, &fontData, c); - nWidth += fontData.pitch; - } - - if (pt) - { - pt->x = nWidth; - pt->y = _this->fontsize; - } - return SUCCESS; -} - -/** - * Get draw area - * @param[in] hdl Handle - * @param[in] lpString String - * @param[out] pt An area - * @retval SUCCESS Succeeded - * @retval FAILURE Failed - */ -BRESULT fontmng_getdrawsize(void *hdl, const char *lpString, POINT_T *pt) -{ - FNTMNG _this; - int nWidth; - int nPosX; - UINT16 c; - _FNTDAT fontData; - - _this = (FNTMNG)hdl; - if (_this == NULL) - { - return FAILURE; - } - - nWidth = 0; - nPosX = 0; - while (1 /* EVER */) - { - c = GetChar(&lpString); - if (c == 0) - { - break; - } - GetLength1(_this, &fontData, c); - nWidth = nPosX + MAX(fontData.width, fontData.pitch); - nPosX += fontData.pitch; - } - if (pt) - { - pt->x = nWidth; - pt->y = _this->fontsize; - } - return SUCCESS; -} - -/** - * Get font data - * @param[in] hdl Handle - * @param[in] lpString String - * @return Data - */ -FNTDAT fontmng_get(void *hdl, const char *lpString) -{ - FNTMNG _this; - UINT16 c; - FNTDAT fontData; - - _this = (FNTMNG)hdl; - if (_this == NULL) - { - return NULL; - } - - c = GetChar(&lpString); - if (c == 0) - { - return NULL; - } - -#if defined(FONTMNG_CACHE) - if (fdatgetcache(_this, c, &fontData)) - { - return fontData; - } -#else /*! defined(FONTMNG_CACHE) */ - fontData = (FNTDAT)(_this + 1); -#endif /*! defined(FONTMNG_CACHE) */ - - GetFont1(_this, fontData, c); - return fontData; -} +/** + * @file fontmng.c + * @brief Implementation of the font manager + */ + +#include +#include + +#if defined(NP2_SIZE_QVGA) +#include "ank10.res" +#else /* defined(NP2_SIZE_QVGA) */ +#include "ank12.res" +#endif /* defined(NP2_SIZE_QVGA) */ + +#if defined(SUPPORT_SDL_TTF) /* use TTF */ + +#define FONTMNG_CACHE 64 /*!< Cache count */ + +/*! White */ +static const SDL_Color s_white = {0xff, 0xff, 0xff, 0}; + +#if defined(FONTMNG_CACHE) +typedef struct +{ + UINT16 str; /*!< String Id */ + UINT16 next; /*!< Next index */ +} FNTCTBL; +#endif + +#endif /* defined(SUPPORT_SDL_TTF) */ + +/*! Font face */ +static char s_sFontName[MAX_PATH] = "./default.ttf"; + +/** + * @brief Handle + */ +struct TagFontManager +{ + int fontsize; + UINT fonttype; + +#if defined(SUPPORT_SDL_TTF) + TTF_Font *ttf_font; + int ptsize; + int fontalign; +#endif /* defined(SUPPORT_SDL_TTF) */ + +#if defined(FONTMNG_CACHE) + UINT caches; + UINT cachehead; + FNTCTBL cache[FONTMNG_CACHE]; +#endif /* defined(FONTMNG_CACHE) */ +}; +typedef struct TagFontManager *FNTMNG; /*!< Defines handle */ + +#if defined(FONTMNG_CACHE) +/** + * + */ +static BOOL fdatgetcache(FNTMNG fhdl, UINT16 c, FNTDAT *pfdat) +{ + BOOL r; + FNTCTBL *fct; + UINT pos; + UINT prev; + UINT cnt; + + r = FALSE; + fct = fhdl->cache; + cnt = fhdl->caches; + pos = fhdl->cachehead; + prev = FONTMNG_CACHE; + while (cnt--) + { + if (fct[pos].str != c) + { + prev = pos; + pos = fct[pos].next; + continue; + } + if (prev < FONTMNG_CACHE) + { + fct[prev].next = fct[pos].next; + fct[pos].next = (UINT16)fhdl->cachehead; + fhdl->cachehead = pos; + } + r = TRUE; + break; + } + if (r == FALSE) + { + if (fhdl->caches < FONTMNG_CACHE) + { + pos = fhdl->caches; + fhdl->caches++; + } + else + { + pos = prev; + } + fct[pos].str = c; + fct[pos].next = (UINT16)fhdl->cachehead; + fhdl->cachehead = pos; + } + if (pfdat) + { + *pfdat = (FNTDAT)(((UINT8 *)(fhdl + 1)) + (pos * fhdl->fontalign)); + } + return r; +} +#endif /* defined(FONTMNG_CACHE) */ + +/** + * Initialize + * @retval SUCCESS Succeeded + * @retval FAILURE Failed + */ +BRESULT fontmng_init(void) +{ +#if defined(SUPPORT_SDL_TTF) + + if (TTF_Init() < 0) + { + fprintf(stderr, "Couldn't initialize TTF: %s\n", SDL_GetError()); + return FAILURE; + } +#ifndef WIN32 + atexit(TTF_Quit); +#endif + +#endif /* defined(SUPPORT_SDL_TTF) */ + + return SUCCESS; +} + +/** + * Sets font face + * @param[in] name name + */ +void fontmng_setdeffontname(const char *name) +{ + milstr_ncpy(s_sFontName, name, NELEMENTS(s_sFontName)); +} + +/** + * Creates instance + */ +void *fontmng_create(int size, UINT type, const char *fontface) +{ + int fontalign; + int fontwork; + int allocsize; + FNTMNG ret; + +#if defined(SUPPORT_SDL_TTF) + TTF_Font *ttf_font; + int ptsize; +#endif /* defined(SUPPORT_SDL_TTF) */ + + if (size < 0) + { + size = -size; + } + if (size < 6) + { + size = 6; + } + else if (size > 128) + { + size = 128; + } + +#if defined(SUPPORT_SDL_TTF) + + if (size < 10) + { + type |= FDAT_ALIAS; + } + else if (size < 16) + { + type &= ~FDAT_BOLD; + } + + ptsize = size; + if (type & FDAT_ALIAS) + { + ptsize *= 2; + } + ttf_font = TTF_OpenFont(s_sFontName, ptsize); + if (ttf_font == NULL) + { + fprintf(stderr, "Couldn't load %d points font from %s: %s\n", ptsize, s_sFontName, SDL_GetError()); + + if (size < ANKFONTSIZE) + { + return NULL; + } + + ptsize = size; + type &= FDAT_PROPORTIONAL; + } + +#else /* defined(SUPPORT_SDL_TTF) */ + + if (size < ANKFONTSIZE) + { + return NULL; + } + +#endif /* defined(SUPPORT_SDL_TTF) */ + + fontalign = sizeof(_FNTDAT) + (size * size); + fontalign = (fontalign + 3) & (~3); +#if defined(FONTMNG_CACHE) + fontwork = fontalign * FONTMNG_CACHE; +#else + fontwork = fontalign; +#endif + + allocsize = sizeof(*ret) + fontwork; + ret = (FNTMNG)_MALLOC(allocsize, "font mng"); + if (ret == NULL) + { +#if defined(SUPPORT_SDL_TTF) + TTF_CloseFont(ttf_font); +#endif /* defined(SUPPORT_SDL_TTF) */ + return NULL; + } + + memset(ret, 0, allocsize); + ret->fontsize = size; + ret->fonttype = type; + +#if defined(SUPPORT_SDL_TTF) + ret->ttf_font = ttf_font; + ret->ptsize = ptsize; + ret->fontalign = fontalign; +#endif /* defined(SUPPORT_SDL_TTF) */ + + return ret; +} + +/** + * Destroy + * @param[in] hdl Handle + */ +void fontmng_destroy(void *hdl) +{ + FNTMNG _this; + + _this = (FNTMNG)hdl; + if (_this) + { + +#if defined(SUPPORT_SDL_TTF) + TTF_CloseFont(_this->ttf_font); +#endif /* defined(SUPPORT_SDL_TTF) */ + + _MFREE(_this); + } +} + +/** + * Sets font header + * @param[in] _this Instance + * @param[out] fdat Data header + * @param[in] s SDL_Surface + */ +static void AnkSetFontHeader(FNTMNG _this, FNTDAT fdat, int width) +{ + if (_this->fonttype & FDAT_PROPORTIONAL) + { + fdat->width = width; + fdat->pitch = width + 1; + fdat->height = _this->fontsize; + } + else + { + fdat->width = MAX(width, _this->fontsize >> 1); + fdat->pitch = (_this->fontsize >> 1) + 1; + fdat->height = _this->fontsize; + } +} + +/** + * Gets font length + * @param[in] _this Instance + * @param[out] fdat Data + * @param[in] c Charactor + */ +static void AnkGetLength1(FNTMNG _this, FNTDAT fdat, UINT16 c) +{ + c = c - 0x20; + if ((c < 0) || (c >= 0x60)) + { + c = 0x1f; /* '?' */ + } + AnkSetFontHeader(_this, fdat, ankfont[c * ANKFONTSIZE]); +} + +/** + * Gets font face (TTF) + * @param[in] _this Instance + * @param[out] fdat Data + * @param[in] c Charactor + */ +static void AnkGetFont1(FNTMNG _this, FNTDAT fdat, UINT16 c) +{ +const UINT8 *src; + int width; + UINT8 *dst; + int x; + int y; + + c = c - 0x20; + if ((c < 0) || (c >= 0x60)) + { + c = 0x1f; /* '?' */ + } + src = ankfont + (c * ANKFONTSIZE); + width = *src++; + AnkSetFontHeader(_this, fdat, width); + dst = (UINT8 *)(fdat + 1); + memset(dst, 0, fdat->width * fdat->height); + dst += ((fdat->height - ANKFONTSIZE) / 2) * fdat->width; + dst += (fdat->width - width) / 2; + for (y = 0; y < (ANKFONTSIZE - 1); y++) + { + dst += fdat->width; + for (x = 0; x < width; x++) + { + dst[x] = (src[0] & (0x80 >> x)) ? 0xff : 0x00; + } + src++; + } +} + +#if !defined(SUPPORT_SDL_TTF) + +#define GetLength1 AnkGetLength1 /*!< length function */ +#define GetFont1 AnkGetFont1 /*!< face function */ + +#else // !defined(SUPPORT_SDL_TTF) + +#define GetLength1 TTFGetLength1 /*!< length function */ +#define GetFont1 TTFGetFont1 /*!< face function */ + +/** + * Sets font header (TTF) + * @param[in] _this Instance + * @param[out] fdat Data header + * @param[in] s SDL_Surface + */ +static void TTFSetFontHeader(FNTMNG _this, FNTDAT fdat, const SDL_Surface *s) +{ + int width; + int height; + int pitch; + + if (s) + { + width = MIN(s->w, _this->ptsize); + height = MIN(s->h, _this->ptsize); + } + else + { + width = _this->fontsize; + height = _this->fontsize; + } + + pitch = width; + if (_this->fonttype & FDAT_ALIAS) + { + width = (width + 1) >> 1; + pitch = width >> 1; + height = (height + 1) >> 1; + } + fdat->width = width; + fdat->pitch = pitch; + fdat->height = height; +} + +/** + * Get pixel + * @param[in] s SDL_Surface + * @param[in] x x + * @param[in] y y + * @return pixel + */ +static UINT8 TTFGetPixelDepth(const SDL_Surface *s, int x, int y) +{ + int nXAlign; + const UINT8 *ptr; + + if ((x >= 0) && (x < s->w) && (y >= 0) && (y < s->h)) + { +#if USE_SDL >= 3 + nXAlign = SDL_BYTESPERPIXEL(s->format); +#else + nXAlign = s->format->BytesPerPixel; +#endif + ptr = (UINT8 *)s->pixels + (y * s->pitch) + (x * nXAlign); + switch (nXAlign) + { + case 1: + return (ptr[0] != 0) ? FDAT_DEPTH : 0; + + case 3: + case 4: + return (ptr[0] * FDAT_DEPTH / 255); + } + } + return 0; +} + +/** + * Gets font length (TTF) + * @param[in] _this Instance + * @param[out] fdat Data + * @param[in] c Charactor + */ +static void TTFGetLength1(FNTMNG _this, FNTDAT fdat, UINT16 c) +{ + UINT16 sString[2]; + SDL_Surface *s; + + sString[0] = c; + sString[1] = 0; + s = NULL; + if (_this->ttf_font) + { +#if USE_SDL >= 3 + s = TTF_RenderText_Solid(_this->ttf_font, sString, strlen(sString), s_white); +#else + s = TTF_RenderUNICODE_Solid(_this->ttf_font, sString, s_white); +#endif + } + if (s) + { + TTFSetFontHeader(_this, fdat, s); +#if USE_SDL >= 3 + SDL_DestroySurface(s); +#else + SDL_FreeSurface(s); +#endif + } + else + { + AnkGetLength1(_this, fdat, c); + } +} + +/** + * Gets font face (TTF) + * @param[in] _this Instance + * @param[out] fdat Data + * @param[in] c Charactor + */ +static void TTFGetFont1(FNTMNG _this, FNTDAT fdat, UINT16 c) +{ + UINT16 sString[2]; + SDL_Surface *s; + UINT8 *dst; + int x; + int y; + int depth; + int minx; + int maxy; + int advance; + + sString[0] = c; + sString[1] = 0; + s = NULL; + if (_this->ttf_font) + { +#if USE_SDL >= 3 + s = TTF_RenderText_Solid(_this->ttf_font, sString, strlen(sString), s_white); +#else + s = TTF_RenderUNICODE_Solid(_this->ttf_font, sString, s_white); +#endif + } + if (s) + { + TTFSetFontHeader(_this, fdat, s); + dst = (UINT8 *)(fdat + 1); + if (_this->fonttype & FDAT_ALIAS) + { +#if USE_SDL >= 3 + TTF_GetGlyphMetrics(_this->ttf_font,s,&minx,NULL,NULL,&maxy,&advance); +#else + TTF_GlyphMetrics(_this->ttf_font,s,&minx,NULL,NULL,&maxy,&advance); +#endif + for (y = 0; y < fdat->height; y++) + { + for (x = 0; x < fdat->width; x++) + { +#if USE_SDL >= 3 + depth = TTFGetPixelDepth(s, (x-minx)*2+0, (y+(TTF_GetFontAscent(_this->ttf_font)-maxy))*2+0); + depth += TTFGetPixelDepth(s, (x-minx)*2+1, (y+(TTF_GetFontAscent(_this->ttf_font)-maxy))*2+0); + depth += TTFGetPixelDepth(s, (x-minx)*2+0, (y+(TTF_GetFontAscent(_this->ttf_font)-maxy))*2+1); + depth += TTFGetPixelDepth(s, (x-minx)*2+1, (y+(TTF_GetFontAscent(_this->ttf_font)-maxy))*2+1); +#else + depth = TTFGetPixelDepth(s, (x-minx)*2+0, (y+(TTF_FontAscent(_this->ttf_font)-maxy))*2+0); + depth += TTFGetPixelDepth(s, (x-minx)*2+1, (y+(TTF_FontAscent(_this->ttf_font)-maxy))*2+0); + depth += TTFGetPixelDepth(s, (x-minx)*2+0, (y+(TTF_FontAscent(_this->ttf_font)-maxy))*2+1); + depth += TTFGetPixelDepth(s, (x-minx)*2+1, (y+(TTF_FontAscent(_this->ttf_font)-maxy))*2+1); +#endif + } + } + } + else + { +#if USE_SDL >= 3 + TTF_GetGlyphMetrics(_this->ttf_font,s,&minx,NULL,NULL,&maxy,&advance); +#else + TTF_GlyphMetrics(_this->ttf_font,s,&minx,NULL,NULL,&maxy,&advance); +#endif + for (y = 0; y < fdat->height; y++) + { + for (x = 0; x < fdat->width; x++) + { +#if USE_SDL >= 3 + *dst++ = TTFGetPixelDepth(s, x-minx, (y+(TTF_GetFontAscent(_this->ttf_font)-maxy))); +#else + *dst++ = TTFGetPixelDepth(s, x-minx, (y+(TTF_FontAscent(_this->ttf_font)-maxy))); +#endif + } + } + } +#if USE_SDL >= 3 + SDL_DestroySurface(s); +#else + SDL_FreeSurface(s); +#endif + } + else + { + AnkGetFont1(_this, fdat, c); + } +} + +#endif /* !defined(SUPPORT_SDL_TTF) */ + +/** + * Get charactor + * @param[in,out] lppString Pointer + * @return Charactor + */ +static UINT16 GetChar(const char** lppString) +{ + const char *lpString; + UINT16 c; + + lpString = *lppString; + if (lpString == NULL) + { + return 0; + } + + c = 0; + if ((lpString[0] & 0x80) == 0) + { + c = lpString[0] & 0x7f; + lpString++; + } + else if (((lpString[0] & 0xe0) == 0xc0) && ((lpString[1] & 0xc0) == 0x80)) + { + c = ((lpString[0] & 0x1f) << 6) | (lpString[1] & 0x3f); + lpString += 2; + } + else if (((lpString[0] & 0xf0) == 0xe0) && ((lpString[1] & 0xc0) == 0x80) && ((lpString[2] & 0xc0) == 0x80)) + { + c = ((lpString[0] & 0x0f) << 12) | ((lpString[1] & 0x3f) << 6) | (lpString[2] & 0x3f); + lpString += 3; + } + + *lppString = lpString; + return c; +} + +/** + * Get font size + * @param[in] hdl Handle + * @param[in] lpString String + * @param[out] pt Size + * @retval SUCCESS Succeeded + * @retval FAILURE Failed + */ +BRESULT fontmng_getsize(void *hdl, const char *lpString, POINT_T *pt) +{ + FNTMNG _this; + int nWidth; + UINT16 c; + _FNTDAT fontData; + + _this = (FNTMNG)hdl; + if ((_this == NULL) || (lpString == NULL)) + { + return FAILURE; + } + + nWidth = 0; + while (1 /* EVER */) + { + c = GetChar(&lpString); + if (c == 0) + { + break; + } + GetLength1(_this, &fontData, c); + nWidth += fontData.pitch; + } + + if (pt) + { + pt->x = nWidth; + pt->y = _this->fontsize; + } + return SUCCESS; +} + +/** + * Get draw area + * @param[in] hdl Handle + * @param[in] lpString String + * @param[out] pt An area + * @retval SUCCESS Succeeded + * @retval FAILURE Failed + */ +BRESULT fontmng_getdrawsize(void *hdl, const char *lpString, POINT_T *pt) +{ + FNTMNG _this; + int nWidth; + int nPosX; + UINT16 c; + _FNTDAT fontData; + + _this = (FNTMNG)hdl; + if (_this == NULL) + { + return FAILURE; + } + + nWidth = 0; + nPosX = 0; + while (1 /* EVER */) + { + c = GetChar(&lpString); + if (c == 0) + { + break; + } + GetLength1(_this, &fontData, c); + nWidth = nPosX + MAX(fontData.width, fontData.pitch); + nPosX += fontData.pitch; + } + if (pt) + { + pt->x = nWidth; + pt->y = _this->fontsize; + } + return SUCCESS; +} + +/** + * Get font data + * @param[in] hdl Handle + * @param[in] lpString String + * @return Data + */ +FNTDAT fontmng_get(void *hdl, const char *lpString) +{ + FNTMNG _this; + UINT16 c; + FNTDAT fontData; + + _this = (FNTMNG)hdl; + if (_this == NULL) + { + return NULL; + } + + c = GetChar(&lpString); + if (c == 0) + { + return NULL; + } + +#if defined(FONTMNG_CACHE) + if (fdatgetcache(_this, c, &fontData)) + { + return fontData; + } +#else /*! defined(FONTMNG_CACHE) */ + fontData = (FNTDAT)(_this + 1); +#endif /*! defined(FONTMNG_CACHE) */ + + GetFont1(_this, fontData, c); + return fontData; +} diff --git a/sdl/fontmng.h b/sdl/fontmng.h old mode 100755 new mode 100644 index 9770896e..e5a538a6 --- a/sdl/fontmng.h +++ b/sdl/fontmng.h @@ -1,51 +1,51 @@ -/** - * @file fongmng.h - * @brief Interface of the font manager - */ - -#pragma once - -enum -{ - FDAT_BOLD = 0x01, - FDAT_PROPORTIONAL = 0x02, - FDAT_ALIAS = 0x04, - FDAT_ANSI = 0x08 -}; - -enum -{ - FDAT_DEPTH = 255, - FDAT_DEPTHBIT = 8 -}; - -typedef struct -{ - int width; - int height; - int pitch; -} _FNTDAT, *FNTDAT; - - -#ifdef __cplusplus -extern "C" -{ -#endif - -void *fontmng_create(int size, UINT type, const char *fontface); -void fontmng_destroy(void *hdl); - -BRESULT fontmng_getsize(void *hdl, const char *string, POINT_T *pt); -BRESULT fontmng_getdrawsize(void *hdl, const char *string, POINT_T *pt); -FNTDAT fontmng_get(void *hdl, const char *string); - -#ifdef __cplusplus -} -#endif - - - -// ---- for SDL - -BRESULT fontmng_init(void); -void fontmng_setdeffontname(const char *name); +/** + * @file fongmng.h + * @brief Interface of the font manager + */ + +#pragma once + +enum +{ + FDAT_BOLD = 0x01, + FDAT_PROPORTIONAL = 0x02, + FDAT_ALIAS = 0x04, + FDAT_ANSI = 0x08 +}; + +enum +{ + FDAT_DEPTH = 255, + FDAT_DEPTHBIT = 8 +}; + +typedef struct +{ + int width; + int height; + int pitch; +} _FNTDAT, *FNTDAT; + + +#ifdef __cplusplus +extern "C" +{ +#endif + +void *fontmng_create(int size, UINT type, const char *fontface); +void fontmng_destroy(void *hdl); + +BRESULT fontmng_getsize(void *hdl, const char *string, POINT_T *pt); +BRESULT fontmng_getdrawsize(void *hdl, const char *string, POINT_T *pt); +FNTDAT fontmng_get(void *hdl, const char *string); + +#ifdef __cplusplus +} +#endif + + + +// ---- for SDL + +BRESULT fontmng_init(void); +void fontmng_setdeffontname(const char *name); diff --git a/sdl/ini.c b/sdl/ini.c old mode 100755 new mode 100644 index df77b5cb..2b784d1b --- a/sdl/ini.c +++ b/sdl/ini.c @@ -1,1009 +1,1009 @@ -#include - -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_BMS) -#include -#endif - -#include -#include -#include "kbdmng.h" -#include - - -typedef struct { - const OEMCHAR *title; - INITBL *tbl; - INITBL *tblterm; - UINT count; -} _INIARG, *INIARG; - - -static BOOL -inigetbmp(const UINT8 *ptr, UINT pos) -{ - - return ((ptr[pos >> 3] >> (pos & 7)) & 1); -} - -static void -inisetbmp(UINT8 *ptr, UINT pos, BOOL set) -{ - UINT8 bit; - - ptr += (pos >> 3); - bit = 1 << (pos & 7); - if (set) { - *ptr |= bit; - } else { - *ptr &= ~bit; - } -} - -static void -inirdargu32(const char *src, INITBL *ini) -{ - uint32_t *dst; - int dsize; - int i; - char c; - - dst = (uint32_t *)ini->value; - dsize = ini->arg; - - for (i = 0; i < dsize; i++) { - while (*src == ' ') { - src++; - } - if (*src == '\0') { - break; - } - dst[i] = (uint32_t)milstr_solveINT(src); - while (*src != '\0') { - c = *src++; - if (c == ',') { - break; - } - } - } -} - -static void -iniwrsetargu32(char *work, int size, INITBL *ini) -{ - char tmp[256]; - const uint32_t *ptr; - UINT arg; - UINT i; - - ptr = (uint32_t *)(ini->value); - arg = ini->arg; - for (i = 0; i < arg; i++) { - if(i + 1 >= arg) { - snprintf(tmp, sizeof(tmp), "%d", ptr[i]); - } else { - snprintf(tmp, sizeof(tmp), "%d,", ptr[i]); - } - milstr_ncat(work, tmp, size); - } -} - -static void -inirdargs16(const OEMCHAR *src, INITBL *ini) -{ - SINT16 *dst; - int dsize; - int i; - OEMCHAR c; - - dst = (SINT16 *)ini->value; - dsize = ini->arg; - - for (i = 0; i < dsize; i++) { - while (*src == ' ') { - src++; - } - if (*src == '\0') { - break; - } - dst[i] = (SINT16)milstr_solveINT(src); - while (*src != '\0') { - c = *src++; - if (c == ',') { - break; - } - } - } -} - -static void -inirdargh8(const OEMCHAR *src, INITBL *ini) -{ - UINT8 *dst; - int dsize; - int i; - UINT8 val; - BOOL set; - OEMCHAR c; - - dst = (UINT8 *)ini->value; - dsize = ini->arg; - - for (i=0; i= '0') && (c <= '9')) { - val <<= 4; - val += c - '0'; - set = TRUE; - } - else { - c |= 0x20; - if ((c >= 'a') && (c <= 'f')) { - val <<= 4; - val += c - 'a' + 10; - set = TRUE; - } - } - src++; - } - if (set == FALSE) { - break; - } - dst[i] = val; - } -} - -static void -iniwrsetargh8(OEMCHAR *work, int size, INITBL *ini) -{ - OEMCHAR tmp[16]; - const UINT8 *ptr; - UINT arg; - UINT i; - - ptr = (UINT8 *)(ini->value); - arg = ini->arg; - if (arg > 0) { - OEMSNPRINTF(tmp, sizeof(tmp), "%.2x ", ptr[0]); - milstr_ncpy(work, tmp, size); - } - for (i = 1; i < arg; i++) { - OEMSNPRINTF(tmp, sizeof(tmp), "%.2x ", ptr[i]); - milstr_ncat(work, tmp, size); - } -} - -/* ----- user */ - -static void -inirdbyte3(const OEMCHAR *src, INITBL *ini) -{ - UINT i; - - for (i = 0; i < 3; i++) { - if (src[i] == '\0') { - break; - } - if ((((src[i] - '0') & 0xff) < 9) || - (((src[i] - 'A') & 0xdf) < 26)) { - ((UINT8 *)ini->value)[i] = src[i]; - } - } -} - -static void -inirdkb(const OEMCHAR *src, INITBL *ini) -{ - - if ((!milstr_extendcmp(src, "DOS")) - || (!milstr_cmp(src, "JIS")) - || (!milstr_cmp(src, "106")) - || (!milstr_cmp(src, "JP")) - || (!milstr_cmp(src, "PCAT")) - || (!milstr_cmp(src, "AT"))) { - *(UINT8 *)ini->value = KEY_KEY106; - } else if ((!milstr_extendcmp(src, "KEY101")) - || (!milstr_cmp(src, "ASCII")) - || (!milstr_cmp(src, "EN")) - || (!milstr_cmp(src, "US")) - || (!milstr_cmp(src, "101"))) { - *(UINT8 *)ini->value = KEY_KEY101; - } -} - -static void -inirdsnddrv(const OEMCHAR *src, INITBL *ini) -{ - - *(UINT8 *)ini->value = snddrv_drv2num(src); -} - -static void -inirdinterp(const OEMCHAR *src, INITBL *ini) -{ - - if (!milstr_cmp(src, "NEAREST")) { - *(UINT8 *)ini->value = INTERP_NEAREST; - } else if (!milstr_cmp(src, "TILES")) { - *(UINT8 *)ini->value = INTERP_TILES; - } else if (!milstr_cmp(src, "HYPER")) { - *(UINT8 *)ini->value = INTERP_HYPER; - } else { - *(UINT8 *)ini->value = INTERP_BILINEAR; - } -} - -static void update_iniread_flag(const INITBL *p); - -static BRESULT -inireadcb(void *arg, const OEMCHAR *para, const OEMCHAR *key, const OEMCHAR *data) -{ - OEMCHAR work[512]; - INITBL *p; - BOOL rv; - - if (arg == NULL) { - return(FAILURE); - } - if (milstr_cmp(para, ((INIARG)arg)->title)) { - return(SUCCESS); - } - p = ((INIARG)arg)->tbl; - while (p < ((INIARG)arg)->tblterm) { - if (!milstr_cmp(key, p->item)) { - rv = TRUE; - switch (p->itemtype & INITYPE_MASK) { - case INITYPE_STR: - milstr_ncpy((OEMCHAR *)p->value, data, p->arg); - break; - - case INITYPE_BOOL: - *((UINT8 *)p->value) = (!milstr_cmp(data, str_true))?1:0; - break; - - case INITYPE_BITMAP: - inisetbmp((UINT8 *)p->value, p->arg, milstr_cmp(data, str_true) == 0); - break; - - case INITYPE_ARGU32: - milstr_ncpy(work, data, 512); - inirdargu32(work, p); - break; - - case INITYPE_ARGS16: - milstr_ncpy(work, data, 512); - inirdargs16(work, p); - break; - - case INITYPE_ARGH8: - milstr_ncpy(work, data, 512); - inirdargh8(work, p); - break; - - case INITYPE_SINT8: - case INITYPE_UINT8: - *((UINT8 *)p->value) = (UINT8)milstr_solveINT(data); - break; - - case INITYPE_SINT16: - case INITYPE_UINT16: - *((UINT16 *)p->value) = (UINT16)milstr_solveINT(data); - break; - - case INITYPE_SINT32: - case INITYPE_UINT32: - *((UINT32 *)p->value) = (UINT32)milstr_solveINT(data); - break; - - case INITYPE_HEX8: - *((UINT8 *)p->value) = (UINT8)milstr_solveHEX(data); - break; - - case INITYPE_HEX16: - *((UINT16 *)p->value) = (UINT16)milstr_solveHEX(data); - break; - - case INITYPE_HEX32: - *((UINT32 *)p->value) = (UINT32)milstr_solveHEX(data); - break; - - case INITYPE_BYTE3: - milstr_ncpy(work, data, 512); - inirdbyte3(work, p); - break; - - case INITYPE_KB: - milstr_ncpy(work, data, 512); - inirdkb(work, p); - break; - - case INITYPE_SNDDRV: - milstr_ncpy(work, data, 512); - inirdsnddrv(work, p); - break; - - case INITYPE_INTERP: - milstr_ncpy(work, data, 512); - inirdinterp(work, p); - break; - - default: - rv = FALSE; - break; - } - if (rv) { - update_iniread_flag(p); - } - } - p++; - } - return(SUCCESS); -} - -void -ini_read(const OEMCHAR *path, const OEMCHAR *title, const INITBL *tbl, UINT count) -{ - _INIARG iniarg; - - if (path == NULL) { - return; - } - iniarg.title = title; - iniarg.tbl = (INITBL *)tbl; - iniarg.tblterm = (INITBL *)(tbl + count); - profile_enum(path, &iniarg, inireadcb); -} - - -static void -iniwrsetstr(OEMCHAR *work, int size, const OEMCHAR *ptr) -{ - UINT i; - OEMCHAR c; - - if (ptr[0] == ' ') { - goto iwss_extend; - - } - i = (UINT)strlen(ptr); - if ((i) && (ptr[i-1] == ' ')) { - goto iwss_extend; - } - while(i > 0) { - i--; - if (ptr[i] == '\"') { - goto iwss_extend; - } - } - milstr_ncpy(work, ptr, size); - return; - -iwss_extend: - if (size > 3) { - size -= 3; - *work++ = '\"'; - while(size > 0) { - size--; - c = *ptr++; - if (c == '\"') { - if (size > 0) { - size--; - work[0] = c; - work[1] = c; - work += 2; - } - } - else { - *work++ = c; - } - } - work[0] = '\"'; - work[1] = '\0'; - } -} - -static void iniwrsetarg8(OEMCHAR *work, int size, const UINT8 *ptr, int arg) { - - int i; - OEMCHAR tmp[8]; - - if (arg > 0) { - OEMSNPRINTF(tmp, sizeof(tmp), OEMTEXT("%.2x"), ptr[0]); - milstr_ncpy(work, tmp, size); - } - for (i=1; iitemtype & INIFLAG_RO) || read_iniread_flag(p)) { - work[0] = '\0'; - set = SUCCESS; - switch (p->itemtype & INITYPE_MASK) { - case INITYPE_STR: - iniwrsetstr(work, sizeof(work), (OEMCHAR *)p->value); - break; - - case INITYPE_BOOL: - milstr_ncpy(work, (*((UINT8 *)p->value))?str_true:str_false, - sizeof(work)); - break; - - case INITYPE_BITMAP: - milstr_ncpy(work, inigetbmp((UINT8 *)p->value, p->arg) ? str_true : str_false, sizeof(work)); - break; - - case INITYPE_ARGU32: - iniwrsetargu32(work, sizeof(work), (INITBL *)p); - break; - - case INITYPE_ARGH8: - iniwrsetargh8(work, sizeof(work), (INITBL *)p); - break; - - case INITYPE_SINT8: - OEMSNPRINTF(work, sizeof(work), str_d, *((SINT8 *)p->value)); - break; - - case INITYPE_SINT16: - OEMSNPRINTF(work, sizeof(work), str_d, *((SINT16 *)p->value)); - break; - - case INITYPE_SINT32: - OEMSNPRINTF(work, sizeof(work), str_d, *((SINT32 *)p->value)); - break; - - case INITYPE_SINT64: - OEMSNPRINTF(work, sizeof(work), str_d, *((SINT64 *)p->value)); - break; - - case INITYPE_UINT8: - OEMSNPRINTF(work, sizeof(work), str_u, *((UINT8 *)p->value)); - break; - - case INITYPE_UINT16: - OEMSNPRINTF(work, sizeof(work), str_u, *((UINT16 *)p->value)); - break; - - case INITYPE_UINT32: - OEMSNPRINTF(work, sizeof(work), str_u, *((UINT32 *)p->value)); - break; - - case INITYPE_UINT64: - OEMSNPRINTF(work, sizeof(work), str_u, *((UINT64 *)p->value)); - break; - - case INITYPE_HEX8: - OEMSNPRINTF(work, sizeof(work), str_x, *((UINT8 *)p->value)); - break; - - case INITYPE_HEX16: - OEMSNPRINTF(work, sizeof(work), str_x, *((UINT16 *)p->value)); - break; - - case INITYPE_HEX32: - OEMSNPRINTF(work, sizeof(work), str_x, *((UINT32 *)p->value)); - break; - - case INITYPE_HEX64: - OEMSNPRINTF(work, sizeof(work), str_x, *((UINT64 *)p->value)); - break; - - case INITYPE_KB: - if (*(UINT8 *)p->value == KEY_KEY101) - milstr_ncpy(work, OEMTEXT("101"), sizeof(work)); - else - milstr_ncpy(work, OEMTEXT("106"), sizeof(work)); - break; - - case INITYPE_SNDDRV: - OEMSNPRINTF(work, sizeof(work), OEMTEXT("%s"), snddrv_num2drv(*(UINT8 *)p->value)); - break; - - case INITYPE_INTERP: - OEMSNPRINTF(work, sizeof(work), OEMTEXT("%s"), iniwrinterp(*(UINT8 *)p->value)); - break; - - default: - set = FAILURE; - break; - } - if (set == SUCCESS) { - file_write(fh, p->item, (UINT)OEMSTRLEN(p->item)); - file_write(fh, " = ", 3); - file_write(fh, work, (UINT)OEMSTRLEN(work)); - file_write(fh, "\n", 1); - } - } - p++; - } - file_close(fh); -} - -#if defined(CPUCORE_IA32) && !defined(__LIBRETRO__) -static const OEMCHAR ini_title[] = OEMTEXT("NekoProject21kai"); -static const OEMCHAR inifile[] = OEMTEXT("np21kai.cfg"); -#else -static const OEMCHAR ini_title[] = OEMTEXT("NekoProjectIIkai"); -static const OEMCHAR inifile[] = OEMTEXT("np2kai.cfg"); -#endif - -enum { - INIRO_STR = INIFLAG_RO | INITYPE_STR, - INIRO_BOOL = INIFLAG_RO | INITYPE_BOOL, - INIRO_BITMAP = INIFLAG_RO | INITYPE_BITMAP, - INIRO_UINT8 = INIFLAG_RO | INITYPE_UINT8, - INIRO_HEX8 = INIFLAG_RO | INITYPE_HEX8, - INIMAX_UINT8 = INIFLAG_MAX | INITYPE_UINT8, - INIAND_UINT8 = INIFLAG_AND | INITYPE_UINT8, - INIROMAX_SINT32 = INIFLAG_RO | INIFLAG_MAX | INITYPE_SINT32, - INIROAND_HEX32 = INIFLAG_RO | INIFLAG_AND | INITYPE_HEX32, - - INIRO_BYTE3 = INIFLAG_RO | INITYPE_BYTE3, - INIRO_KB = INIFLAG_RO | INITYPE_KB -}; - -static const INITBL iniitem[] = { - {OEMTEXT("FDfolder"), INITYPE_STR, fddfolder, MAX_PATH}, - {OEMTEXT("HDfolder"), INITYPE_STR, hddfolder, MAX_PATH}, - {OEMTEXT("bmap_Dir"), INITYPE_STR, bmpfilefolder, MAX_PATH}, - {OEMTEXT("bmap_Num"), INITYPE_UINT32, &bmpfilenumber, 0}, - {OEMTEXT("fontfile"), INITYPE_STR, np2cfg.fontfile, MAX_PATH}, - {OEMTEXT("biospath"), INIRO_STR, np2cfg.biospath, MAX_PATH}, -#if defined(SUPPORT_HOSTDRV) - {OEMTEXT("use_hdrv"), INITYPE_BOOL, &np2cfg.hdrvenable, 0}, - {OEMTEXT("hdrvroot"), INITYPE_STR, &np2cfg.hdrvroot, MAX_PATH}, - {OEMTEXT("hdrv_acc"), INITYPE_UINT8, &np2cfg.hdrvacc, 0}, -#endif -#if defined(SUPPORT_HOSTDRVNT) - {OEMTEXT("usehdrvn"), INITYPE_BOOL, &np2cfg.hdrvntenable, 0}, -#endif - - {OEMTEXT("pc_model"), INITYPE_STR, np2cfg.model, sizeof(np2cfg.model)}, - - {OEMTEXT("clk_base"), INITYPE_UINT32, &np2cfg.baseclock, 0}, - {OEMTEXT("clk_mult"), INITYPE_UINT32, &np2cfg.multiple, 0}, - - {OEMTEXT("DIPswtch"), INITYPE_ARGH8, np2cfg.dipsw, 3}, - {OEMTEXT("MEMswtch"), INITYPE_ARGH8, np2cfg.memsw, 8}, -#if defined(SUPPORT_LARGE_MEMORY) - {OEMTEXT("ExMemory"), INITYPE_UINT16, &np2cfg.EXTMEM, 13}, -#else - {OEMTEXT("ExMemory"), INIMAX_UINT8, &np2cfg.EXTMEM, 13}, -#endif - {OEMTEXT("ITF_WORK"), INIRO_BOOL, &np2cfg.ITF_WORK, 0}, - - {OEMTEXT("HDD1FILE"), INITYPE_STR, np2cfg.sasihdd[0], MAX_PATH}, - {OEMTEXT("HDD2FILE"), INITYPE_STR, np2cfg.sasihdd[1], MAX_PATH}, -#if defined(SUPPORT_SCSI) - {OEMTEXT("SCSIHDD0"), INITYPE_STR, np2cfg.scsihdd[0], MAX_PATH}, - {OEMTEXT("SCSIHDD1"), INITYPE_STR, np2cfg.scsihdd[1], MAX_PATH}, - {OEMTEXT("SCSIHDD2"), INITYPE_STR, np2cfg.scsihdd[2], MAX_PATH}, - {OEMTEXT("SCSIHDD3"), INITYPE_STR, np2cfg.scsihdd[3], MAX_PATH}, -#endif -#if defined(SUPPORT_IDEIO) - {OEMTEXT("HDD3FILE"), INIRO_STR, np2cfg.sasihdd[2], MAX_PATH}, - {OEMTEXT("HDD4FILE"), INIRO_STR, np2cfg.sasihdd[3], MAX_PATH}, - {OEMTEXT("IDE1TYPE"), INIRO_UINT8, &np2cfg.idetype[0], 0}, - {OEMTEXT("IDE2TYPE"), INIRO_UINT8, &np2cfg.idetype[1], 0}, - {OEMTEXT("IDE3TYPE"), INIRO_UINT8, &np2cfg.idetype[2], 0}, - {OEMTEXT("IDE4TYPE"), INIRO_UINT8, &np2cfg.idetype[3], 0}, - {OEMTEXT("IDE_BIOS"), INIRO_BOOL, &np2cfg.idebios, 0}, - {OEMTEXT("AIDEBIOS"), INIRO_BOOL, &np2cfg.autoidebios, 0}, - {OEMTEXT("IDERWAIT"), INITYPE_UINT32, &np2cfg.iderwait, 0}, - {OEMTEXT("IDEWWAIT"), INITYPE_UINT32, &np2cfg.idewwait, 0}, - {OEMTEXT("IDEMWAIT"), INITYPE_UINT32, &np2cfg.idemwait, 0}, -#endif - {OEMTEXT("SampleHz"), INITYPE_UINT32, &np2cfg.samplingrate, 0}, - {OEMTEXT("Latencys"), INITYPE_UINT16, &np2cfg.delayms, 0}, - {OEMTEXT("SNDboard"), INITYPE_HEX8, &np2cfg.SOUND_SW, 0}, - {OEMTEXT("BEEP_vol"), INIAND_UINT8, &np2cfg.BEEP_VOL, 3}, - {OEMTEXT("xspeaker"), INIRO_BOOL, &np2cfg.snd_x, 0}, - - {OEMTEXT("SND14vol"), INITYPE_ARGH8, np2cfg.vol14, 6}, -// {OEMTEXT("opt14BRD"), INITYPE_ARGH8, np2cfg.snd14opt, 3}, - {OEMTEXT("opt26BRD"), INITYPE_HEX8, &np2cfg.snd26opt, 0}, - {OEMTEXT("opt86BRD"), INITYPE_HEX8, &np2cfg.snd86opt, 0}, - {OEMTEXT("optSPBRD"), INITYPE_HEX8, &np2cfg.spbopt, 0}, - {OEMTEXT("optSPBVR"), INITYPE_HEX8, &np2cfg.spb_vrc, 0}, - {OEMTEXT("optSPBVL"), INIMAX_UINT8, &np2cfg.spb_vrl, 24}, - {OEMTEXT("optSPB_X"), INITYPE_BOOL, &np2cfg.spb_x, 0}, - {OEMTEXT("USEMPU98"), INITYPE_BOOL, &np2cfg.mpuenable, 0}, - {OEMTEXT("optMPU98"), INITYPE_HEX8, &np2cfg.mpuopt, 0}, - {OEMTEXT("optMPUAT"), INITYPE_BOOL, &np2cfg.mpu_at, 0}, -#if defined(SUPPORT_SMPU98) - {OEMTEXT("USE_SMPU"), INITYPE_BOOL, &np2cfg.smpuenable, 0}, - {OEMTEXT("opt_SMPU"), INITYPE_HEX8, &np2cfg.smpuopt, 0}, - {OEMTEXT("SMPUMUTB"), INITYPE_BOOL, &np2cfg.smpumuteB, 0}, -#endif - {OEMTEXT("opt118io"), INITYPE_HEX16, &np2cfg.snd118io, 0}, - {OEMTEXT("opt118id"), INITYPE_HEX8, &np2cfg.snd118id, 0}, - {OEMTEXT("opt118dm"), INITYPE_UINT8, &np2cfg.snd118dma, 0}, - {OEMTEXT("opt118if"), INITYPE_UINT8, &np2cfg.snd118irqf, 0}, - {OEMTEXT("opt118ip"), INITYPE_UINT8, &np2cfg.snd118irqp, 0}, - {OEMTEXT("opt118im"), INITYPE_UINT8, &np2cfg.snd118irqm, 0}, - {OEMTEXT("opt118ro"), INITYPE_UINT8, &np2cfg.snd118rom, 0}, - - {OEMTEXT("optwssid"), INITYPE_HEX8, &np2cfg.sndwssid, 0}, - {OEMTEXT("optwssdm"), INITYPE_UINT8, &np2cfg.sndwssdma, 0}, - {OEMTEXT("optwssip"), INITYPE_UINT8, &np2cfg.sndwssirq, 0}, - -#if defined(SUPPORT_SOUND_SB16) - {OEMTEXT("optsb16p"), INITYPE_HEX8, &np2cfg.sndsb16io, 0}, - {OEMTEXT("optsb16d"), INITYPE_UINT8, &np2cfg.sndsb16dma, 0}, - {OEMTEXT("optsb16i"), INITYPE_UINT8, &np2cfg.sndsb16irq, 0}, - {OEMTEXT("optsb16A"), INITYPE_BOOL, &np2cfg.sndsb16at, 0}, -#endif /* SUPPORT_SOUND_SB16 */ - - {OEMTEXT("volume_F"), INIMAX_UINT8, &np2cfg.vol_fm, 128}, - {OEMTEXT("volume_S"), INIMAX_UINT8, &np2cfg.vol_ssg, 128}, - {OEMTEXT("volume_A"), INIMAX_UINT8, &np2cfg.vol_adpcm, 128}, - {OEMTEXT("volume_P"), INIMAX_UINT8, &np2cfg.vol_pcm, 128}, - {OEMTEXT("volume_R"), INIMAX_UINT8, &np2cfg.vol_rhythm, 128}, - {OEMTEXT("DAVOLUME"), INIMAX_UINT8, &np2cfg.davolume, 128}, - -#if defined(SUPPORT_FMGEN) - {OEMTEXT("USEFMGEN"), INITYPE_BOOL, &np2cfg.usefmgen, 0}, -#endif /* SUPPORT_FMGEN */ - - {OEMTEXT("Seek_Snd"), INITYPE_BOOL, &np2cfg.MOTOR, 0}, - {OEMTEXT("Seek_Vol"), INIMAX_UINT8, &np2cfg.MOTORVOL, 100}, - - {OEMTEXT("btnRAPID"), INITYPE_BOOL, &np2cfg.BTN_RAPID, 0}, - {OEMTEXT("btn_MODE"), INITYPE_BOOL, &np2cfg.BTN_MODE, 0}, - {OEMTEXT("MS_RAPID"), INITYPE_BOOL, &np2cfg.MOUSERAPID, 0}, - - {OEMTEXT("VRAMwait"), INITYPE_ARGH8, np2cfg.wait, 6}, - {OEMTEXT("DispSync"), INITYPE_BOOL, &np2cfg.DISPSYNC, 0}, - {OEMTEXT("Real_Pal"), INITYPE_BOOL, &np2cfg.RASTER, 0}, - {OEMTEXT("RPal_tim"), INIMAX_UINT8, &np2cfg.realpal, 64}, - {OEMTEXT("uPD72020"), INITYPE_BOOL, &np2cfg.uPD72020, 0}, - {OEMTEXT("GRCG_EGC"), INIAND_UINT8, &np2cfg.grcg, 3}, - {OEMTEXT("color16b"), INITYPE_BOOL, &np2cfg.color16, 0}, - {OEMTEXT("skipline"), INITYPE_BOOL, &np2cfg.skipline, 0}, - {OEMTEXT("skplight"), INITYPE_SINT16, &np2cfg.skiplight, 0}, - {OEMTEXT("LCD_MODE"), INIAND_UINT8, &np2cfg.LCD_MODE, 0x03}, - {OEMTEXT("BG_COLOR"), INIROAND_HEX32, &np2cfg.BG_COLOR, 0xffffff}, - {OEMTEXT("FG_COLOR"), INIROAND_HEX32, &np2cfg.FG_COLOR, 0xffffff}, - - {OEMTEXT("pc9861_e"), INITYPE_BOOL, &np2cfg.pc9861enable, 0}, - {OEMTEXT("pc9861_s"), INITYPE_ARGH8, np2cfg.pc9861sw, 3}, - {OEMTEXT("pc9861_j"), INITYPE_ARGH8, np2cfg.pc9861jmp, 6}, - - {OEMTEXT("calendar"), INITYPE_BOOL, &np2cfg.calendar, 0}, - {OEMTEXT("USE144FD"), INITYPE_BOOL, &np2cfg.usefd144, 0}, - {OEMTEXT("FDDRIVE1"), INIRO_BITMAP, &np2cfg.fddequip, 0}, - {OEMTEXT("FDDRIVE2"), INIRO_BITMAP, &np2cfg.fddequip, 1}, - {OEMTEXT("FDDRIVE3"), INIRO_BITMAP, &np2cfg.fddequip, 2}, - {OEMTEXT("FDDRIVE4"), INIRO_BITMAP, &np2cfg.fddequip, 3}, - -#if defined(SUPPORT_BMS) - {OEMTEXT("Use_BMS_"), INITYPE_BOOL, &bmsiocfg.enabled, 0}, - {OEMTEXT("BMS_Port"), INIROAND_HEX32, &bmsiocfg.port, 0}, - {OEMTEXT("BMS_Size"), INIMAX_UINT8, &bmsiocfg.numbanks, 256}, -#endif - -#if defined(SUPPORT_NET) - {OEMTEXT("NP2NETTAP"), INITYPE_STR, &np2cfg.np2nettap, 0}, - {OEMTEXT("NP2NETPMM"), INITYPE_BOOL, &np2cfg.np2netpmm, 0}, -#endif -#if defined(SUPPORT_LGY98) - {OEMTEXT("USELGY98"), INITYPE_BOOL, &np2cfg.uselgy98, 0}, - {OEMTEXT("LGY98_IO"), INITYPE_UINT16, &np2cfg.lgy98io, 0}, - {OEMTEXT("LGY98IRQ"), INITYPE_UINT8, &np2cfg.lgy98irq, 0}, - {OEMTEXT("LGY98MAC"), INITYPE_ARGH8, np2cfg.lgy98mac, 6}, -#endif -#if defined(SUPPORT_WAB) - {OEMTEXT("WAB_ANSW"), INITYPE_UINT8, &np2cfg.wabasw, 0}, -#endif -#if defined(SUPPORT_CL_GD5430) - {OEMTEXT("USE_CLGD"), INITYPE_BOOL, &np2cfg.usegd5430, 0}, - {OEMTEXT("CLGDTYPE"), INITYPE_UINT16, &np2cfg.gd5430type, 0}, - {OEMTEXT("CLGDFCUR"), INITYPE_BOOL, &np2cfg.gd5430fakecur, 0}, - {OEMTEXT("GDMELOFS"), INITYPE_UINT8, &np2cfg.gd5430melofs, 0}, - {OEMTEXT("GANBBSEX"), INITYPE_BOOL, &np2cfg.ga98nb_bigscrn_ex, 0}, -#endif -#if defined(SUPPORT_PCI) - {OEMTEXT("USE98PCI"), INITYPE_BOOL, &np2cfg.usepci, 0}, - {OEMTEXT("PCI_PCMC"), INITYPE_UINT8, &np2cfg.pci_pcmc, 0}, - {OEMTEXT("P_BIOS32"), INITYPE_BOOL, &np2cfg.pci_bios32, 0}, -#endif - {OEMTEXT("TIMERFIX"), INITYPE_BOOL, &np2cfg.timerfix, 0}, - - {OEMTEXT("WINNTFIX"), INITYPE_BOOL, &np2cfg.winntfix, 0}, - - {OEMTEXT("SYSIOMSK"), INITYPE_HEX16, &np2cfg.sysiomsk, 0}, - - {OEMTEXT("MEMCHKMX"), INITYPE_UINT8, &np2cfg.memchkmx, 0}, - {OEMTEXT("SBEEPLEN"), INITYPE_UINT8, &np2cfg.sbeeplen, 0}, - {OEMTEXT("SBEEPADJ"), INITYPE_BOOL, &np2cfg.sbeepadj, 0}, - - {OEMTEXT("cpu_vend"), INITYPE_STR, np2cfg.cpu_vendor_o, 15}, - {OEMTEXT("cpu_fami"), INITYPE_UINT32, &np2cfg.cpu_family, 0}, - {OEMTEXT("cpu_mode"), INITYPE_UINT32, &np2cfg.cpu_model, 0}, - {OEMTEXT("cpu_step"), INITYPE_UINT32, &np2cfg.cpu_stepping, 0}, - {OEMTEXT("cpu_feat"), INITYPE_HEX32, &np2cfg.cpu_feature, 0}, - {OEMTEXT("cpu_f_ex"), INITYPE_HEX32, &np2cfg.cpu_feature_ex, 0}, - {OEMTEXT("cpu_bran"), INIRO_STR, np2cfg.cpu_brandstring_o, 63}, - {OEMTEXT("cpu_brid"), INITYPE_HEX32, &np2cfg.cpu_brandid, 0}, - {OEMTEXT("cpu_fecx"), INITYPE_HEX32, &np2cfg.cpu_feature_ecx, 0}, - {OEMTEXT("cpu_eflg"), INITYPE_HEX32, &np2cfg.cpu_eflags_mask, 0}, - - {OEMTEXT("FPU_TYPE"), INITYPE_UINT8, &np2cfg.fpu_type, 0}, -#if defined(SUPPORT_FAST_MEMORYCHECK) - {OEMTEXT("memckspd"), INITYPE_UINT8, &np2cfg.memcheckspeed, 0}, -#endif - {OEMTEXT("USERAM_D"), INITYPE_BOOL, &np2cfg.useram_d, 0}, -#if defined(SUPPORT_ASYNC_CPU) - {OEMTEXT("ASYNCCPU"), INITYPE_BOOL, &np2cfg.asynccpu, 0}, - {OEMTEXT("ASYNCLVL"), INITYPE_UINT8, &np2cfg.asynclvl, 0}, -#endif - {OEMTEXT("CONSTTSC"), INITYPE_BOOL, &np2cfg.consttsc, 0}, -#if defined(SUPPORT_IDEIO) - {OEMTEXT("IDEBADDR"), INIRO_HEX8, &np2cfg.idebaddr, 0}, -#endif -#if defined(SUPPORT_GAMEPORT) - {OEMTEXT("GAMEPORT"), INITYPE_BOOL, &np2cfg.gameport, 0}, - {OEMTEXT("ANLG_JOY"), INITYPE_BOOL, &np2cfg.analogjoy, 0}, -#endif - {OEMTEXT("USEMOVCS"), INIRO_BOOL, &np2cfg.allowMOVCS, 0}, - {OEMTEXT("USETHOOK"), INIRO_BOOL, &np2cfg.usetexthook, 0}, - {OEMTEXT("RASCSI92"), INIRO_BOOL, &np2cfg.rascsi92, 0}, - {OEMTEXT("NBEEPOFS"), INIRO_BOOL, &np2cfg.nbeepofs, 0}, - {OEMTEXT("CAL_VOFS"), INITYPE_SINT64, &np2cfg.cal_vofs, 0}, -#if defined(SUPPORT_NP2SCSI) - {OEMTEXT("USENP2ST"), INIRO_BOOL, &np2cfg.usenp2stor, 0}, -#endif - {OEMTEXT("CPUSPEED"), INITYPE_UINT32, &np2cfg.emuspeed, 0}, - {OEMTEXT("fontface"), INIRO_STR, np2cfg.fontface, 255}, - {OEMTEXT("SLOWMOUS"), INIRO_BOOL, &np2cfg.slowmous, 0}, - - {OEMTEXT("keyboard"), INITYPE_KB, &np2oscfg.KEYBOARD, 0}, -#if !defined(__LIBRETRO__) - {OEMTEXT("Joystick"), INITYPE_BOOL, &np2oscfg.JOYPAD1, 0}, - {OEMTEXT("Joy1_btn"), INITYPE_ARGH8, np2oscfg.JOY1BTN, JOY_NBUTTON}, - {OEMTEXT("Joy1_dev"), INITYPE_STR, &np2oscfg.JOYDEV[0], MAX_PATH}, - {OEMTEXT("Joy1amap"), INITYPE_ARGH8, np2oscfg.JOYAXISMAP[0], JOY_NAXIS}, - {OEMTEXT("Joy1bmap"), INITYPE_ARGH8, np2oscfg.JOYBTNMAP[0], JOY_NBUTTON}, -#else /* __LIBRETRO__ */ - {OEMTEXT("lrjoybtn"), INITYPE_ARGH8, np2oscfg.lrjoybtn, 24}, -#endif /* __LIBRETRO__ */ - - {OEMTEXT("mpu98port"), INIMAX_UINT8, &np2oscfg.mpu.port, COMPORT_MIDI}, - {OEMTEXT("mpu98dir"), INITYPE_BOOL, &np2oscfg.mpu.direct, 0}, - {OEMTEXT("mpu98map"), INITYPE_STR, np2oscfg.mpu.mout, MAX_PATH}, - {OEMTEXT("mpu98min"), INITYPE_STR, np2oscfg.mpu.min, MAX_PATH}, - {OEMTEXT("mpu98mdl"), INITYPE_STR, np2oscfg.mpu.mdl, 64}, - {OEMTEXT("mpu98def"), INITYPE_STR, np2oscfg.mpu.def, MAX_PATH}, - -#if defined(SUPPORT_SMPU98) - {OEMTEXT("smpuAmap"), INITYPE_STR, np2oscfg.smpuA.mout, MAX_PATH}, - {OEMTEXT("smpuAmin"), INITYPE_STR, np2oscfg.smpuA.min, MAX_PATH}, - {OEMTEXT("smpuAmdl"), INITYPE_STR, np2oscfg.smpuA.mdl, 64}, - {OEMTEXT("smpuAdef"), INITYPE_STR, np2oscfg.smpuA.def, MAX_PATH}, - {OEMTEXT("smpuBmap"), INITYPE_STR, np2oscfg.smpuB.mout, MAX_PATH}, - {OEMTEXT("smpuBmin"), INITYPE_STR, np2oscfg.smpuB.min, MAX_PATH}, - {OEMTEXT("smpuBmdl"), INITYPE_STR, np2oscfg.smpuB.mdl, 64}, - {OEMTEXT("smpuBdef"), INITYPE_STR, np2oscfg.smpuB.def, MAX_PATH}, -#endif - -#if !defined(__LIBRETRO__) - {OEMTEXT("com1port"), INIMAX_UINT8, &np2oscfg.com[0].port, COMPORT_NONE}, - {OEMTEXT("com1dir"), INITYPE_BOOL, &np2oscfg.com[0].direct, 1}, - {OEMTEXT("com1para"), INITYPE_UINT8, &np2oscfg.com[0].param, 0}, - {OEMTEXT("com1_bps"), INITYPE_UINT32, &np2oscfg.com[0].speed, 0}, - {OEMTEXT("com1mmap"), INITYPE_STR, np2oscfg.com[0].mout, MAX_PATH}, - {OEMTEXT("com1mmdl"), INITYPE_STR, np2oscfg.com[0].mdl, 64}, - {OEMTEXT("com1mdef"), INITYPE_STR, np2oscfg.com[0].def, MAX_PATH}, - - {OEMTEXT("com2port"), INIMAX_UINT8, &np2oscfg.com[1].port, COMPORT_NONE}, - {OEMTEXT("com2dir"), INITYPE_BOOL, &np2oscfg.com[1].direct, 1}, - {OEMTEXT("com2para"), INITYPE_UINT8, &np2oscfg.com[1].param, 0}, - {OEMTEXT("com2_bps"), INITYPE_UINT32, &np2oscfg.com[1].speed, 0}, - {OEMTEXT("com2mmap"), INITYPE_STR, np2oscfg.com[1].mout, MAX_PATH}, - {OEMTEXT("com2mmdl"), INITYPE_STR, np2oscfg.com[1].mdl, 64}, - {OEMTEXT("com2mdef"), INITYPE_STR, np2oscfg.com[1].def, MAX_PATH}, - - {OEMTEXT("com3port"), INIMAX_UINT8, &np2oscfg.com[2].port, COMPORT_NONE}, - {OEMTEXT("com3dir"), INITYPE_BOOL, &np2oscfg.com[2].direct, 1}, - {OEMTEXT("com3para"), INITYPE_UINT8, &np2oscfg.com[2].param, 0}, - {OEMTEXT("com3_bps"), INITYPE_UINT32, &np2oscfg.com[2].speed, 0}, - {OEMTEXT("com3mmap"), INITYPE_STR, np2oscfg.com[2].mout, MAX_PATH}, - {OEMTEXT("com3mmdl"), INITYPE_STR, np2oscfg.com[2].mdl, 64}, - {OEMTEXT("com3mdef"), INITYPE_STR, np2oscfg.com[2].def, MAX_PATH}, -#endif /* __LIBRETRO__ */ - -#if defined(SUPPORT_RESUME) - {OEMTEXT("e_resume"), INITYPE_BOOL, &np2oscfg.resume, 0}, -#endif -#if defined(SUPPORT_STATSAVE) - {OEMTEXT("STATSAVE"), INITYPE_BOOL, &np2cfg.statsave, 0}, -#endif - - {OEMTEXT("xrollkey"), INITYPE_BOOL, &np2oscfg.xrollkey, 0}, - - {OEMTEXT("sounddrv"), INITYPE_SNDDRV, &np2oscfg.snddrv, 0}, -#if !defined(__LIBRETRO__) -#if defined(_WIN32) - {OEMTEXT("MIDIOUTd"), INITYPE_STR, &np2oscfg.MIDIDEV[0], MAX_PATH}, - {OEMTEXT("MIDIIN_d"), INITYPE_STR, &np2oscfg.MIDIDEV[1], MAX_PATH}, -#if defined(SUPPORT_SMPU98) - {OEMTEXT("MIDIOUAd"), INITYPE_STR, &np2oscfg.MIDIDEVA[0], MAX_PATH}, - {OEMTEXT("MIDIINAd"), INITYPE_STR, &np2oscfg.MIDIDEVA[1], MAX_PATH}, - {OEMTEXT("MIDIOUBd"), INITYPE_STR, &np2oscfg.MIDIDEVB[0], MAX_PATH}, - {OEMTEXT("MIDIINBd"), INITYPE_STR, &np2oscfg.MIDIDEVB[1], MAX_PATH}, -#endif - {OEMTEXT("MIDIWAIT"), INITYPE_UINT32, &np2oscfg.MIDIWAIT, 0}, -#endif /* _WIN32 */ -#endif /* __LIBRETRO__ */ - - {OEMTEXT("s_NOWAIT"), INITYPE_BOOL, &np2oscfg.NOWAIT, 0}, - {OEMTEXT("SkpFrame"), INITYPE_UINT8, &np2oscfg.DRAW_SKIP, 0}, - {OEMTEXT("jast_snd"), INITYPE_BOOL, &np2oscfg.jastsnd, 0}, - -#if defined(SUPPORT_VIDEOFILTER) - {OEMTEXT("vf1_enable"), INITYPE_BOOL, &np2cfg.vf1_enable, 0}, - {OEMTEXT("vf1_pcount"), INITYPE_UINT8, &np2cfg.vf1_pcount, 3}, - {OEMTEXT("vf1_pno"), INITYPE_UINT8, &np2cfg.vf1_pno, 0}, - {OEMTEXT("vf1_p0_fc"), INITYPE_UINT8, &np2cfg.vf1_profile[0][0], 3}, - {OEMTEXT("vf1_p0_fno"), INITYPE_UINT8, &np2cfg.vf1_profile[0][1], 2}, - {OEMTEXT("vf1_p0_p0"), INITYPE_ARGU32, np2cfg.vf1_param[0][0], 8}, - {OEMTEXT("vf1_p0_p1"), INITYPE_ARGU32, np2cfg.vf1_param[0][1], 8}, - {OEMTEXT("vf1_p0_p2"), INITYPE_ARGU32, np2cfg.vf1_param[0][2], 8}, - {OEMTEXT("vf1_p1_fc"), INITYPE_UINT8, &np2cfg.vf1_profile[1][0], 3}, - {OEMTEXT("vf1_p1_fno"), INITYPE_UINT8, &np2cfg.vf1_profile[1][1], 2}, - {OEMTEXT("vf1_p1_p0"), INITYPE_ARGU32, np2cfg.vf1_param[1][0], 8}, - {OEMTEXT("vf1_p1_p1"), INITYPE_ARGU32, np2cfg.vf1_param[1][1], 8}, - {OEMTEXT("vf1_p1_p2"), INITYPE_ARGU32, np2cfg.vf1_param[1][2], 8}, - {OEMTEXT("vf1_p2_fc"), INITYPE_UINT8, &np2cfg.vf1_profile[2][0], 3}, - {OEMTEXT("vf1_p2_fno"), INITYPE_UINT8, &np2cfg.vf1_profile[2][1], 2}, - {OEMTEXT("vf1_p2_p0"), INITYPE_ARGU32, np2cfg.vf1_param[2][0], 8}, - {OEMTEXT("vf1_p2_p1"), INITYPE_ARGU32, np2cfg.vf1_param[2][1], 8}, - {OEMTEXT("vf1_p2_p2"), INITYPE_ARGU32, np2cfg.vf1_param[2][2], 8}, -#endif - - // Keyrepeat - {OEMTEXT("keyrepeat_enable"), INITYPE_BOOL, &np2cfg.keyrepeat_enable, 0}, - {OEMTEXT("keyrepeat_delay"), INITYPE_UINT16, &np2cfg.keyrepeat_delay, 500}, - {OEMTEXT("keyrepeat_interval"), INITYPE_UINT16, &np2cfg.keyrepeat_interval, 50}, -}; - -#define INIITEMS (sizeof(iniitem) / sizeof(INITBL)) - - -static BOOL iniread_flag[INIITEMS]; - -static int -calc_index(const INITBL *p) -{ - UINT offset; - UINT idx; - - if (p) { - offset = (const OEMCHAR *)p - (const OEMCHAR *)iniitem; - if ((offset % sizeof(iniitem[0])) == 0) { - idx = offset / sizeof(iniitem[0]); - if (idx < INIITEMS) { - return idx; - } - } - } - return -1; -} - -static void -update_iniread_flag(const INITBL *p) -{ - int idx; - - idx = calc_index(p); - if (idx >= 0) { - iniread_flag[idx] = TRUE; - } -} - -static BOOL -read_iniread_flag(const INITBL *p) -{ - int idx; - - idx = calc_index(p); - if (idx >= 0) { - return iniread_flag[idx]; - } - return FALSE; -} - -void initload(void) { - - OEMCHAR path[MAX_PATH]; - - milstr_ncpy(path, file_getcd(inifile), sizeof(path)); - fprintf(stderr, OEMTEXT("Loading %s from %s\n"), inifile, path); -// TRACEOUT(OEMTEXT("Loading %s from %s", inifile, path)); - ini_read(path, ini_title, iniitem, INIITEMS); -} - -void initsave(void) { - - OEMCHAR path[MAX_PATH]; - - milstr_ncpy(path, file_getcd(inifile), sizeof(path)); - fprintf(stderr, OEMTEXT("Saving %s to %s\n"), inifile, path); - ini_write(path, ini_title, iniitem, INIITEMS); -} - -static const OEMCHAR s_szExt[] = OEMTEXT(".ini"); - -void initgetfile(OEMCHAR *lpPath, unsigned int cchPath) -{ - const OEMCHAR *lpIni = inifile; - if (lpIni) - { - file_cpyname(lpPath, lpIni, cchPath); - //LPCTSTR lpExt = file_getext(lpPath); - //if (lpExt[0] != '\0') - //{ - // file_catname(lpPath, s_szExt, cchPath); - //} - } - else - { - file_cpyname(lpPath, modulefile, cchPath); - file_cutext(lpPath); - file_catname(lpPath, s_szExt, cchPath); - } -} - +#include + +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_BMS) +#include +#endif + +#include +#include +#include "kbdmng.h" +#include + + +typedef struct { + const OEMCHAR *title; + INITBL *tbl; + INITBL *tblterm; + UINT count; +} _INIARG, *INIARG; + + +static BOOL +inigetbmp(const UINT8 *ptr, UINT pos) +{ + + return ((ptr[pos >> 3] >> (pos & 7)) & 1); +} + +static void +inisetbmp(UINT8 *ptr, UINT pos, BOOL set) +{ + UINT8 bit; + + ptr += (pos >> 3); + bit = 1 << (pos & 7); + if (set) { + *ptr |= bit; + } else { + *ptr &= ~bit; + } +} + +static void +inirdargu32(const char *src, INITBL *ini) +{ + uint32_t *dst; + int dsize; + int i; + char c; + + dst = (uint32_t *)ini->value; + dsize = ini->arg; + + for (i = 0; i < dsize; i++) { + while (*src == ' ') { + src++; + } + if (*src == '\0') { + break; + } + dst[i] = (uint32_t)milstr_solveINT(src); + while (*src != '\0') { + c = *src++; + if (c == ',') { + break; + } + } + } +} + +static void +iniwrsetargu32(char *work, int size, INITBL *ini) +{ + char tmp[256]; + const uint32_t *ptr; + UINT arg; + UINT i; + + ptr = (uint32_t *)(ini->value); + arg = ini->arg; + for (i = 0; i < arg; i++) { + if(i + 1 >= arg) { + snprintf(tmp, sizeof(tmp), "%d", ptr[i]); + } else { + snprintf(tmp, sizeof(tmp), "%d,", ptr[i]); + } + milstr_ncat(work, tmp, size); + } +} + +static void +inirdargs16(const OEMCHAR *src, INITBL *ini) +{ + SINT16 *dst; + int dsize; + int i; + OEMCHAR c; + + dst = (SINT16 *)ini->value; + dsize = ini->arg; + + for (i = 0; i < dsize; i++) { + while (*src == ' ') { + src++; + } + if (*src == '\0') { + break; + } + dst[i] = (SINT16)milstr_solveINT(src); + while (*src != '\0') { + c = *src++; + if (c == ',') { + break; + } + } + } +} + +static void +inirdargh8(const OEMCHAR *src, INITBL *ini) +{ + UINT8 *dst; + int dsize; + int i; + UINT8 val; + BOOL set; + OEMCHAR c; + + dst = (UINT8 *)ini->value; + dsize = ini->arg; + + for (i=0; i= '0') && (c <= '9')) { + val <<= 4; + val += c - '0'; + set = TRUE; + } + else { + c |= 0x20; + if ((c >= 'a') && (c <= 'f')) { + val <<= 4; + val += c - 'a' + 10; + set = TRUE; + } + } + src++; + } + if (set == FALSE) { + break; + } + dst[i] = val; + } +} + +static void +iniwrsetargh8(OEMCHAR *work, int size, INITBL *ini) +{ + OEMCHAR tmp[16]; + const UINT8 *ptr; + UINT arg; + UINT i; + + ptr = (UINT8 *)(ini->value); + arg = ini->arg; + if (arg > 0) { + OEMSNPRINTF(tmp, sizeof(tmp), "%.2x ", ptr[0]); + milstr_ncpy(work, tmp, size); + } + for (i = 1; i < arg; i++) { + OEMSNPRINTF(tmp, sizeof(tmp), "%.2x ", ptr[i]); + milstr_ncat(work, tmp, size); + } +} + +/* ----- user */ + +static void +inirdbyte3(const OEMCHAR *src, INITBL *ini) +{ + UINT i; + + for (i = 0; i < 3; i++) { + if (src[i] == '\0') { + break; + } + if ((((src[i] - '0') & 0xff) < 9) || + (((src[i] - 'A') & 0xdf) < 26)) { + ((UINT8 *)ini->value)[i] = src[i]; + } + } +} + +static void +inirdkb(const OEMCHAR *src, INITBL *ini) +{ + + if ((!milstr_extendcmp(src, "DOS")) + || (!milstr_cmp(src, "JIS")) + || (!milstr_cmp(src, "106")) + || (!milstr_cmp(src, "JP")) + || (!milstr_cmp(src, "PCAT")) + || (!milstr_cmp(src, "AT"))) { + *(UINT8 *)ini->value = KEY_KEY106; + } else if ((!milstr_extendcmp(src, "KEY101")) + || (!milstr_cmp(src, "ASCII")) + || (!milstr_cmp(src, "EN")) + || (!milstr_cmp(src, "US")) + || (!milstr_cmp(src, "101"))) { + *(UINT8 *)ini->value = KEY_KEY101; + } +} + +static void +inirdsnddrv(const OEMCHAR *src, INITBL *ini) +{ + + *(UINT8 *)ini->value = snddrv_drv2num(src); +} + +static void +inirdinterp(const OEMCHAR *src, INITBL *ini) +{ + + if (!milstr_cmp(src, "NEAREST")) { + *(UINT8 *)ini->value = INTERP_NEAREST; + } else if (!milstr_cmp(src, "TILES")) { + *(UINT8 *)ini->value = INTERP_TILES; + } else if (!milstr_cmp(src, "HYPER")) { + *(UINT8 *)ini->value = INTERP_HYPER; + } else { + *(UINT8 *)ini->value = INTERP_BILINEAR; + } +} + +static void update_iniread_flag(const INITBL *p); + +static BRESULT +inireadcb(void *arg, const OEMCHAR *para, const OEMCHAR *key, const OEMCHAR *data) +{ + OEMCHAR work[512]; + INITBL *p; + BOOL rv; + + if (arg == NULL) { + return(FAILURE); + } + if (milstr_cmp(para, ((INIARG)arg)->title)) { + return(SUCCESS); + } + p = ((INIARG)arg)->tbl; + while (p < ((INIARG)arg)->tblterm) { + if (!milstr_cmp(key, p->item)) { + rv = TRUE; + switch (p->itemtype & INITYPE_MASK) { + case INITYPE_STR: + milstr_ncpy((OEMCHAR *)p->value, data, p->arg); + break; + + case INITYPE_BOOL: + *((UINT8 *)p->value) = (!milstr_cmp(data, str_true))?1:0; + break; + + case INITYPE_BITMAP: + inisetbmp((UINT8 *)p->value, p->arg, milstr_cmp(data, str_true) == 0); + break; + + case INITYPE_ARGU32: + milstr_ncpy(work, data, 512); + inirdargu32(work, p); + break; + + case INITYPE_ARGS16: + milstr_ncpy(work, data, 512); + inirdargs16(work, p); + break; + + case INITYPE_ARGH8: + milstr_ncpy(work, data, 512); + inirdargh8(work, p); + break; + + case INITYPE_SINT8: + case INITYPE_UINT8: + *((UINT8 *)p->value) = (UINT8)milstr_solveINT(data); + break; + + case INITYPE_SINT16: + case INITYPE_UINT16: + *((UINT16 *)p->value) = (UINT16)milstr_solveINT(data); + break; + + case INITYPE_SINT32: + case INITYPE_UINT32: + *((UINT32 *)p->value) = (UINT32)milstr_solveINT(data); + break; + + case INITYPE_HEX8: + *((UINT8 *)p->value) = (UINT8)milstr_solveHEX(data); + break; + + case INITYPE_HEX16: + *((UINT16 *)p->value) = (UINT16)milstr_solveHEX(data); + break; + + case INITYPE_HEX32: + *((UINT32 *)p->value) = (UINT32)milstr_solveHEX(data); + break; + + case INITYPE_BYTE3: + milstr_ncpy(work, data, 512); + inirdbyte3(work, p); + break; + + case INITYPE_KB: + milstr_ncpy(work, data, 512); + inirdkb(work, p); + break; + + case INITYPE_SNDDRV: + milstr_ncpy(work, data, 512); + inirdsnddrv(work, p); + break; + + case INITYPE_INTERP: + milstr_ncpy(work, data, 512); + inirdinterp(work, p); + break; + + default: + rv = FALSE; + break; + } + if (rv) { + update_iniread_flag(p); + } + } + p++; + } + return(SUCCESS); +} + +void +ini_read(const OEMCHAR *path, const OEMCHAR *title, const INITBL *tbl, UINT count) +{ + _INIARG iniarg; + + if (path == NULL) { + return; + } + iniarg.title = title; + iniarg.tbl = (INITBL *)tbl; + iniarg.tblterm = (INITBL *)(tbl + count); + profile_enum(path, &iniarg, inireadcb); +} + + +static void +iniwrsetstr(OEMCHAR *work, int size, const OEMCHAR *ptr) +{ + UINT i; + OEMCHAR c; + + if (ptr[0] == ' ') { + goto iwss_extend; + + } + i = (UINT)strlen(ptr); + if ((i) && (ptr[i-1] == ' ')) { + goto iwss_extend; + } + while(i > 0) { + i--; + if (ptr[i] == '\"') { + goto iwss_extend; + } + } + milstr_ncpy(work, ptr, size); + return; + +iwss_extend: + if (size > 3) { + size -= 3; + *work++ = '\"'; + while(size > 0) { + size--; + c = *ptr++; + if (c == '\"') { + if (size > 0) { + size--; + work[0] = c; + work[1] = c; + work += 2; + } + } + else { + *work++ = c; + } + } + work[0] = '\"'; + work[1] = '\0'; + } +} + +static void iniwrsetarg8(OEMCHAR *work, int size, const UINT8 *ptr, int arg) { + + int i; + OEMCHAR tmp[8]; + + if (arg > 0) { + OEMSNPRINTF(tmp, sizeof(tmp), OEMTEXT("%.2x"), ptr[0]); + milstr_ncpy(work, tmp, size); + } + for (i=1; iitemtype & INIFLAG_RO) || read_iniread_flag(p)) { + work[0] = '\0'; + set = SUCCESS; + switch (p->itemtype & INITYPE_MASK) { + case INITYPE_STR: + iniwrsetstr(work, sizeof(work), (OEMCHAR *)p->value); + break; + + case INITYPE_BOOL: + milstr_ncpy(work, (*((UINT8 *)p->value))?str_true:str_false, + sizeof(work)); + break; + + case INITYPE_BITMAP: + milstr_ncpy(work, inigetbmp((UINT8 *)p->value, p->arg) ? str_true : str_false, sizeof(work)); + break; + + case INITYPE_ARGU32: + iniwrsetargu32(work, sizeof(work), (INITBL *)p); + break; + + case INITYPE_ARGH8: + iniwrsetargh8(work, sizeof(work), (INITBL *)p); + break; + + case INITYPE_SINT8: + OEMSNPRINTF(work, sizeof(work), str_d, *((SINT8 *)p->value)); + break; + + case INITYPE_SINT16: + OEMSNPRINTF(work, sizeof(work), str_d, *((SINT16 *)p->value)); + break; + + case INITYPE_SINT32: + OEMSNPRINTF(work, sizeof(work), str_d, *((SINT32 *)p->value)); + break; + + case INITYPE_SINT64: + OEMSNPRINTF(work, sizeof(work), str_d, *((SINT64 *)p->value)); + break; + + case INITYPE_UINT8: + OEMSNPRINTF(work, sizeof(work), str_u, *((UINT8 *)p->value)); + break; + + case INITYPE_UINT16: + OEMSNPRINTF(work, sizeof(work), str_u, *((UINT16 *)p->value)); + break; + + case INITYPE_UINT32: + OEMSNPRINTF(work, sizeof(work), str_u, *((UINT32 *)p->value)); + break; + + case INITYPE_UINT64: + OEMSNPRINTF(work, sizeof(work), str_u, *((UINT64 *)p->value)); + break; + + case INITYPE_HEX8: + OEMSNPRINTF(work, sizeof(work), str_x, *((UINT8 *)p->value)); + break; + + case INITYPE_HEX16: + OEMSNPRINTF(work, sizeof(work), str_x, *((UINT16 *)p->value)); + break; + + case INITYPE_HEX32: + OEMSNPRINTF(work, sizeof(work), str_x, *((UINT32 *)p->value)); + break; + + case INITYPE_HEX64: + OEMSNPRINTF(work, sizeof(work), str_x, *((UINT64 *)p->value)); + break; + + case INITYPE_KB: + if (*(UINT8 *)p->value == KEY_KEY101) + milstr_ncpy(work, OEMTEXT("101"), sizeof(work)); + else + milstr_ncpy(work, OEMTEXT("106"), sizeof(work)); + break; + + case INITYPE_SNDDRV: + OEMSNPRINTF(work, sizeof(work), OEMTEXT("%s"), snddrv_num2drv(*(UINT8 *)p->value)); + break; + + case INITYPE_INTERP: + OEMSNPRINTF(work, sizeof(work), OEMTEXT("%s"), iniwrinterp(*(UINT8 *)p->value)); + break; + + default: + set = FAILURE; + break; + } + if (set == SUCCESS) { + file_write(fh, p->item, (UINT)OEMSTRLEN(p->item)); + file_write(fh, " = ", 3); + file_write(fh, work, (UINT)OEMSTRLEN(work)); + file_write(fh, "\n", 1); + } + } + p++; + } + file_close(fh); +} + +#if defined(CPUCORE_IA32) && !defined(__LIBRETRO__) +static const OEMCHAR ini_title[] = OEMTEXT("NekoProject21kai"); +static const OEMCHAR inifile[] = OEMTEXT("np21kai.cfg"); +#else +static const OEMCHAR ini_title[] = OEMTEXT("NekoProjectIIkai"); +static const OEMCHAR inifile[] = OEMTEXT("np2kai.cfg"); +#endif + +enum { + INIRO_STR = INIFLAG_RO | INITYPE_STR, + INIRO_BOOL = INIFLAG_RO | INITYPE_BOOL, + INIRO_BITMAP = INIFLAG_RO | INITYPE_BITMAP, + INIRO_UINT8 = INIFLAG_RO | INITYPE_UINT8, + INIRO_HEX8 = INIFLAG_RO | INITYPE_HEX8, + INIMAX_UINT8 = INIFLAG_MAX | INITYPE_UINT8, + INIAND_UINT8 = INIFLAG_AND | INITYPE_UINT8, + INIROMAX_SINT32 = INIFLAG_RO | INIFLAG_MAX | INITYPE_SINT32, + INIROAND_HEX32 = INIFLAG_RO | INIFLAG_AND | INITYPE_HEX32, + + INIRO_BYTE3 = INIFLAG_RO | INITYPE_BYTE3, + INIRO_KB = INIFLAG_RO | INITYPE_KB +}; + +static const INITBL iniitem[] = { + {OEMTEXT("FDfolder"), INITYPE_STR, fddfolder, MAX_PATH}, + {OEMTEXT("HDfolder"), INITYPE_STR, hddfolder, MAX_PATH}, + {OEMTEXT("bmap_Dir"), INITYPE_STR, bmpfilefolder, MAX_PATH}, + {OEMTEXT("bmap_Num"), INITYPE_UINT32, &bmpfilenumber, 0}, + {OEMTEXT("fontfile"), INITYPE_STR, np2cfg.fontfile, MAX_PATH}, + {OEMTEXT("biospath"), INIRO_STR, np2cfg.biospath, MAX_PATH}, +#if defined(SUPPORT_HOSTDRV) + {OEMTEXT("use_hdrv"), INITYPE_BOOL, &np2cfg.hdrvenable, 0}, + {OEMTEXT("hdrvroot"), INITYPE_STR, &np2cfg.hdrvroot, MAX_PATH}, + {OEMTEXT("hdrv_acc"), INITYPE_UINT8, &np2cfg.hdrvacc, 0}, +#endif +#if defined(SUPPORT_HOSTDRVNT) + {OEMTEXT("usehdrvn"), INITYPE_BOOL, &np2cfg.hdrvntenable, 0}, +#endif + + {OEMTEXT("pc_model"), INITYPE_STR, np2cfg.model, sizeof(np2cfg.model)}, + + {OEMTEXT("clk_base"), INITYPE_UINT32, &np2cfg.baseclock, 0}, + {OEMTEXT("clk_mult"), INITYPE_UINT32, &np2cfg.multiple, 0}, + + {OEMTEXT("DIPswtch"), INITYPE_ARGH8, np2cfg.dipsw, 3}, + {OEMTEXT("MEMswtch"), INITYPE_ARGH8, np2cfg.memsw, 8}, +#if defined(SUPPORT_LARGE_MEMORY) + {OEMTEXT("ExMemory"), INITYPE_UINT16, &np2cfg.EXTMEM, 13}, +#else + {OEMTEXT("ExMemory"), INIMAX_UINT8, &np2cfg.EXTMEM, 13}, +#endif + {OEMTEXT("ITF_WORK"), INIRO_BOOL, &np2cfg.ITF_WORK, 0}, + + {OEMTEXT("HDD1FILE"), INITYPE_STR, np2cfg.sasihdd[0], MAX_PATH}, + {OEMTEXT("HDD2FILE"), INITYPE_STR, np2cfg.sasihdd[1], MAX_PATH}, +#if defined(SUPPORT_SCSI) + {OEMTEXT("SCSIHDD0"), INITYPE_STR, np2cfg.scsihdd[0], MAX_PATH}, + {OEMTEXT("SCSIHDD1"), INITYPE_STR, np2cfg.scsihdd[1], MAX_PATH}, + {OEMTEXT("SCSIHDD2"), INITYPE_STR, np2cfg.scsihdd[2], MAX_PATH}, + {OEMTEXT("SCSIHDD3"), INITYPE_STR, np2cfg.scsihdd[3], MAX_PATH}, +#endif +#if defined(SUPPORT_IDEIO) + {OEMTEXT("HDD3FILE"), INIRO_STR, np2cfg.sasihdd[2], MAX_PATH}, + {OEMTEXT("HDD4FILE"), INIRO_STR, np2cfg.sasihdd[3], MAX_PATH}, + {OEMTEXT("IDE1TYPE"), INIRO_UINT8, &np2cfg.idetype[0], 0}, + {OEMTEXT("IDE2TYPE"), INIRO_UINT8, &np2cfg.idetype[1], 0}, + {OEMTEXT("IDE3TYPE"), INIRO_UINT8, &np2cfg.idetype[2], 0}, + {OEMTEXT("IDE4TYPE"), INIRO_UINT8, &np2cfg.idetype[3], 0}, + {OEMTEXT("IDE_BIOS"), INIRO_BOOL, &np2cfg.idebios, 0}, + {OEMTEXT("AIDEBIOS"), INIRO_BOOL, &np2cfg.autoidebios, 0}, + {OEMTEXT("IDERWAIT"), INITYPE_UINT32, &np2cfg.iderwait, 0}, + {OEMTEXT("IDEWWAIT"), INITYPE_UINT32, &np2cfg.idewwait, 0}, + {OEMTEXT("IDEMWAIT"), INITYPE_UINT32, &np2cfg.idemwait, 0}, +#endif + {OEMTEXT("SampleHz"), INITYPE_UINT32, &np2cfg.samplingrate, 0}, + {OEMTEXT("Latencys"), INITYPE_UINT16, &np2cfg.delayms, 0}, + {OEMTEXT("SNDboard"), INITYPE_HEX8, &np2cfg.SOUND_SW, 0}, + {OEMTEXT("BEEP_vol"), INIAND_UINT8, &np2cfg.BEEP_VOL, 3}, + {OEMTEXT("xspeaker"), INIRO_BOOL, &np2cfg.snd_x, 0}, + + {OEMTEXT("SND14vol"), INITYPE_ARGH8, np2cfg.vol14, 6}, +// {OEMTEXT("opt14BRD"), INITYPE_ARGH8, np2cfg.snd14opt, 3}, + {OEMTEXT("opt26BRD"), INITYPE_HEX8, &np2cfg.snd26opt, 0}, + {OEMTEXT("opt86BRD"), INITYPE_HEX8, &np2cfg.snd86opt, 0}, + {OEMTEXT("optSPBRD"), INITYPE_HEX8, &np2cfg.spbopt, 0}, + {OEMTEXT("optSPBVR"), INITYPE_HEX8, &np2cfg.spb_vrc, 0}, + {OEMTEXT("optSPBVL"), INIMAX_UINT8, &np2cfg.spb_vrl, 24}, + {OEMTEXT("optSPB_X"), INITYPE_BOOL, &np2cfg.spb_x, 0}, + {OEMTEXT("USEMPU98"), INITYPE_BOOL, &np2cfg.mpuenable, 0}, + {OEMTEXT("optMPU98"), INITYPE_HEX8, &np2cfg.mpuopt, 0}, + {OEMTEXT("optMPUAT"), INITYPE_BOOL, &np2cfg.mpu_at, 0}, +#if defined(SUPPORT_SMPU98) + {OEMTEXT("USE_SMPU"), INITYPE_BOOL, &np2cfg.smpuenable, 0}, + {OEMTEXT("opt_SMPU"), INITYPE_HEX8, &np2cfg.smpuopt, 0}, + {OEMTEXT("SMPUMUTB"), INITYPE_BOOL, &np2cfg.smpumuteB, 0}, +#endif + {OEMTEXT("opt118io"), INITYPE_HEX16, &np2cfg.snd118io, 0}, + {OEMTEXT("opt118id"), INITYPE_HEX8, &np2cfg.snd118id, 0}, + {OEMTEXT("opt118dm"), INITYPE_UINT8, &np2cfg.snd118dma, 0}, + {OEMTEXT("opt118if"), INITYPE_UINT8, &np2cfg.snd118irqf, 0}, + {OEMTEXT("opt118ip"), INITYPE_UINT8, &np2cfg.snd118irqp, 0}, + {OEMTEXT("opt118im"), INITYPE_UINT8, &np2cfg.snd118irqm, 0}, + {OEMTEXT("opt118ro"), INITYPE_UINT8, &np2cfg.snd118rom, 0}, + + {OEMTEXT("optwssid"), INITYPE_HEX8, &np2cfg.sndwssid, 0}, + {OEMTEXT("optwssdm"), INITYPE_UINT8, &np2cfg.sndwssdma, 0}, + {OEMTEXT("optwssip"), INITYPE_UINT8, &np2cfg.sndwssirq, 0}, + +#if defined(SUPPORT_SOUND_SB16) + {OEMTEXT("optsb16p"), INITYPE_HEX8, &np2cfg.sndsb16io, 0}, + {OEMTEXT("optsb16d"), INITYPE_UINT8, &np2cfg.sndsb16dma, 0}, + {OEMTEXT("optsb16i"), INITYPE_UINT8, &np2cfg.sndsb16irq, 0}, + {OEMTEXT("optsb16A"), INITYPE_BOOL, &np2cfg.sndsb16at, 0}, +#endif /* SUPPORT_SOUND_SB16 */ + + {OEMTEXT("volume_F"), INIMAX_UINT8, &np2cfg.vol_fm, 128}, + {OEMTEXT("volume_S"), INIMAX_UINT8, &np2cfg.vol_ssg, 128}, + {OEMTEXT("volume_A"), INIMAX_UINT8, &np2cfg.vol_adpcm, 128}, + {OEMTEXT("volume_P"), INIMAX_UINT8, &np2cfg.vol_pcm, 128}, + {OEMTEXT("volume_R"), INIMAX_UINT8, &np2cfg.vol_rhythm, 128}, + {OEMTEXT("DAVOLUME"), INIMAX_UINT8, &np2cfg.davolume, 128}, + +#if defined(SUPPORT_FMGEN) + {OEMTEXT("USEFMGEN"), INITYPE_BOOL, &np2cfg.usefmgen, 0}, +#endif /* SUPPORT_FMGEN */ + + {OEMTEXT("Seek_Snd"), INITYPE_BOOL, &np2cfg.MOTOR, 0}, + {OEMTEXT("Seek_Vol"), INIMAX_UINT8, &np2cfg.MOTORVOL, 100}, + + {OEMTEXT("btnRAPID"), INITYPE_BOOL, &np2cfg.BTN_RAPID, 0}, + {OEMTEXT("btn_MODE"), INITYPE_BOOL, &np2cfg.BTN_MODE, 0}, + {OEMTEXT("MS_RAPID"), INITYPE_BOOL, &np2cfg.MOUSERAPID, 0}, + + {OEMTEXT("VRAMwait"), INITYPE_ARGH8, np2cfg.wait, 6}, + {OEMTEXT("DispSync"), INITYPE_BOOL, &np2cfg.DISPSYNC, 0}, + {OEMTEXT("Real_Pal"), INITYPE_BOOL, &np2cfg.RASTER, 0}, + {OEMTEXT("RPal_tim"), INIMAX_UINT8, &np2cfg.realpal, 64}, + {OEMTEXT("uPD72020"), INITYPE_BOOL, &np2cfg.uPD72020, 0}, + {OEMTEXT("GRCG_EGC"), INIAND_UINT8, &np2cfg.grcg, 3}, + {OEMTEXT("color16b"), INITYPE_BOOL, &np2cfg.color16, 0}, + {OEMTEXT("skipline"), INITYPE_BOOL, &np2cfg.skipline, 0}, + {OEMTEXT("skplight"), INITYPE_SINT16, &np2cfg.skiplight, 0}, + {OEMTEXT("LCD_MODE"), INIAND_UINT8, &np2cfg.LCD_MODE, 0x03}, + {OEMTEXT("BG_COLOR"), INIROAND_HEX32, &np2cfg.BG_COLOR, 0xffffff}, + {OEMTEXT("FG_COLOR"), INIROAND_HEX32, &np2cfg.FG_COLOR, 0xffffff}, + + {OEMTEXT("pc9861_e"), INITYPE_BOOL, &np2cfg.pc9861enable, 0}, + {OEMTEXT("pc9861_s"), INITYPE_ARGH8, np2cfg.pc9861sw, 3}, + {OEMTEXT("pc9861_j"), INITYPE_ARGH8, np2cfg.pc9861jmp, 6}, + + {OEMTEXT("calendar"), INITYPE_BOOL, &np2cfg.calendar, 0}, + {OEMTEXT("USE144FD"), INITYPE_BOOL, &np2cfg.usefd144, 0}, + {OEMTEXT("FDDRIVE1"), INIRO_BITMAP, &np2cfg.fddequip, 0}, + {OEMTEXT("FDDRIVE2"), INIRO_BITMAP, &np2cfg.fddequip, 1}, + {OEMTEXT("FDDRIVE3"), INIRO_BITMAP, &np2cfg.fddequip, 2}, + {OEMTEXT("FDDRIVE4"), INIRO_BITMAP, &np2cfg.fddequip, 3}, + +#if defined(SUPPORT_BMS) + {OEMTEXT("Use_BMS_"), INITYPE_BOOL, &bmsiocfg.enabled, 0}, + {OEMTEXT("BMS_Port"), INIROAND_HEX32, &bmsiocfg.port, 0}, + {OEMTEXT("BMS_Size"), INIMAX_UINT8, &bmsiocfg.numbanks, 256}, +#endif + +#if defined(SUPPORT_NET) + {OEMTEXT("NP2NETTAP"), INITYPE_STR, &np2cfg.np2nettap, 0}, + {OEMTEXT("NP2NETPMM"), INITYPE_BOOL, &np2cfg.np2netpmm, 0}, +#endif +#if defined(SUPPORT_LGY98) + {OEMTEXT("USELGY98"), INITYPE_BOOL, &np2cfg.uselgy98, 0}, + {OEMTEXT("LGY98_IO"), INITYPE_UINT16, &np2cfg.lgy98io, 0}, + {OEMTEXT("LGY98IRQ"), INITYPE_UINT8, &np2cfg.lgy98irq, 0}, + {OEMTEXT("LGY98MAC"), INITYPE_ARGH8, np2cfg.lgy98mac, 6}, +#endif +#if defined(SUPPORT_WAB) + {OEMTEXT("WAB_ANSW"), INITYPE_UINT8, &np2cfg.wabasw, 0}, +#endif +#if defined(SUPPORT_CL_GD5430) + {OEMTEXT("USE_CLGD"), INITYPE_BOOL, &np2cfg.usegd5430, 0}, + {OEMTEXT("CLGDTYPE"), INITYPE_UINT16, &np2cfg.gd5430type, 0}, + {OEMTEXT("CLGDFCUR"), INITYPE_BOOL, &np2cfg.gd5430fakecur, 0}, + {OEMTEXT("GDMELOFS"), INITYPE_UINT8, &np2cfg.gd5430melofs, 0}, + {OEMTEXT("GANBBSEX"), INITYPE_BOOL, &np2cfg.ga98nb_bigscrn_ex, 0}, +#endif +#if defined(SUPPORT_PCI) + {OEMTEXT("USE98PCI"), INITYPE_BOOL, &np2cfg.usepci, 0}, + {OEMTEXT("PCI_PCMC"), INITYPE_UINT8, &np2cfg.pci_pcmc, 0}, + {OEMTEXT("P_BIOS32"), INITYPE_BOOL, &np2cfg.pci_bios32, 0}, +#endif + {OEMTEXT("TIMERFIX"), INITYPE_BOOL, &np2cfg.timerfix, 0}, + + {OEMTEXT("WINNTFIX"), INITYPE_BOOL, &np2cfg.winntfix, 0}, + + {OEMTEXT("SYSIOMSK"), INITYPE_HEX16, &np2cfg.sysiomsk, 0}, + + {OEMTEXT("MEMCHKMX"), INITYPE_UINT8, &np2cfg.memchkmx, 0}, + {OEMTEXT("SBEEPLEN"), INITYPE_UINT8, &np2cfg.sbeeplen, 0}, + {OEMTEXT("SBEEPADJ"), INITYPE_BOOL, &np2cfg.sbeepadj, 0}, + + {OEMTEXT("cpu_vend"), INITYPE_STR, np2cfg.cpu_vendor_o, 15}, + {OEMTEXT("cpu_fami"), INITYPE_UINT32, &np2cfg.cpu_family, 0}, + {OEMTEXT("cpu_mode"), INITYPE_UINT32, &np2cfg.cpu_model, 0}, + {OEMTEXT("cpu_step"), INITYPE_UINT32, &np2cfg.cpu_stepping, 0}, + {OEMTEXT("cpu_feat"), INITYPE_HEX32, &np2cfg.cpu_feature, 0}, + {OEMTEXT("cpu_f_ex"), INITYPE_HEX32, &np2cfg.cpu_feature_ex, 0}, + {OEMTEXT("cpu_bran"), INIRO_STR, np2cfg.cpu_brandstring_o, 63}, + {OEMTEXT("cpu_brid"), INITYPE_HEX32, &np2cfg.cpu_brandid, 0}, + {OEMTEXT("cpu_fecx"), INITYPE_HEX32, &np2cfg.cpu_feature_ecx, 0}, + {OEMTEXT("cpu_eflg"), INITYPE_HEX32, &np2cfg.cpu_eflags_mask, 0}, + + {OEMTEXT("FPU_TYPE"), INITYPE_UINT8, &np2cfg.fpu_type, 0}, +#if defined(SUPPORT_FAST_MEMORYCHECK) + {OEMTEXT("memckspd"), INITYPE_UINT8, &np2cfg.memcheckspeed, 0}, +#endif + {OEMTEXT("USERAM_D"), INITYPE_BOOL, &np2cfg.useram_d, 0}, +#if defined(SUPPORT_ASYNC_CPU) + {OEMTEXT("ASYNCCPU"), INITYPE_BOOL, &np2cfg.asynccpu, 0}, + {OEMTEXT("ASYNCLVL"), INITYPE_UINT8, &np2cfg.asynclvl, 0}, +#endif + {OEMTEXT("CONSTTSC"), INITYPE_BOOL, &np2cfg.consttsc, 0}, +#if defined(SUPPORT_IDEIO) + {OEMTEXT("IDEBADDR"), INIRO_HEX8, &np2cfg.idebaddr, 0}, +#endif +#if defined(SUPPORT_GAMEPORT) + {OEMTEXT("GAMEPORT"), INITYPE_BOOL, &np2cfg.gameport, 0}, + {OEMTEXT("ANLG_JOY"), INITYPE_BOOL, &np2cfg.analogjoy, 0}, +#endif + {OEMTEXT("USEMOVCS"), INIRO_BOOL, &np2cfg.allowMOVCS, 0}, + {OEMTEXT("USETHOOK"), INIRO_BOOL, &np2cfg.usetexthook, 0}, + {OEMTEXT("RASCSI92"), INIRO_BOOL, &np2cfg.rascsi92, 0}, + {OEMTEXT("NBEEPOFS"), INIRO_BOOL, &np2cfg.nbeepofs, 0}, + {OEMTEXT("CAL_VOFS"), INITYPE_SINT64, &np2cfg.cal_vofs, 0}, +#if defined(SUPPORT_NP2SCSI) + {OEMTEXT("USENP2ST"), INIRO_BOOL, &np2cfg.usenp2stor, 0}, +#endif + {OEMTEXT("CPUSPEED"), INITYPE_UINT32, &np2cfg.emuspeed, 0}, + {OEMTEXT("fontface"), INIRO_STR, np2cfg.fontface, 255}, + {OEMTEXT("SLOWMOUS"), INIRO_BOOL, &np2cfg.slowmous, 0}, + + {OEMTEXT("keyboard"), INITYPE_KB, &np2oscfg.KEYBOARD, 0}, +#if !defined(__LIBRETRO__) + {OEMTEXT("Joystick"), INITYPE_BOOL, &np2oscfg.JOYPAD1, 0}, + {OEMTEXT("Joy1_btn"), INITYPE_ARGH8, np2oscfg.JOY1BTN, JOY_NBUTTON}, + {OEMTEXT("Joy1_dev"), INITYPE_STR, &np2oscfg.JOYDEV[0], MAX_PATH}, + {OEMTEXT("Joy1amap"), INITYPE_ARGH8, np2oscfg.JOYAXISMAP[0], JOY_NAXIS}, + {OEMTEXT("Joy1bmap"), INITYPE_ARGH8, np2oscfg.JOYBTNMAP[0], JOY_NBUTTON}, +#else /* __LIBRETRO__ */ + {OEMTEXT("lrjoybtn"), INITYPE_ARGH8, np2oscfg.lrjoybtn, 24}, +#endif /* __LIBRETRO__ */ + + {OEMTEXT("mpu98port"), INIMAX_UINT8, &np2oscfg.mpu.port, COMPORT_MIDI}, + {OEMTEXT("mpu98dir"), INITYPE_BOOL, &np2oscfg.mpu.direct, 0}, + {OEMTEXT("mpu98map"), INITYPE_STR, np2oscfg.mpu.mout, MAX_PATH}, + {OEMTEXT("mpu98min"), INITYPE_STR, np2oscfg.mpu.min, MAX_PATH}, + {OEMTEXT("mpu98mdl"), INITYPE_STR, np2oscfg.mpu.mdl, 64}, + {OEMTEXT("mpu98def"), INITYPE_STR, np2oscfg.mpu.def, MAX_PATH}, + +#if defined(SUPPORT_SMPU98) + {OEMTEXT("smpuAmap"), INITYPE_STR, np2oscfg.smpuA.mout, MAX_PATH}, + {OEMTEXT("smpuAmin"), INITYPE_STR, np2oscfg.smpuA.min, MAX_PATH}, + {OEMTEXT("smpuAmdl"), INITYPE_STR, np2oscfg.smpuA.mdl, 64}, + {OEMTEXT("smpuAdef"), INITYPE_STR, np2oscfg.smpuA.def, MAX_PATH}, + {OEMTEXT("smpuBmap"), INITYPE_STR, np2oscfg.smpuB.mout, MAX_PATH}, + {OEMTEXT("smpuBmin"), INITYPE_STR, np2oscfg.smpuB.min, MAX_PATH}, + {OEMTEXT("smpuBmdl"), INITYPE_STR, np2oscfg.smpuB.mdl, 64}, + {OEMTEXT("smpuBdef"), INITYPE_STR, np2oscfg.smpuB.def, MAX_PATH}, +#endif + +#if !defined(__LIBRETRO__) + {OEMTEXT("com1port"), INIMAX_UINT8, &np2oscfg.com[0].port, COMPORT_NONE}, + {OEMTEXT("com1dir"), INITYPE_BOOL, &np2oscfg.com[0].direct, 1}, + {OEMTEXT("com1para"), INITYPE_UINT8, &np2oscfg.com[0].param, 0}, + {OEMTEXT("com1_bps"), INITYPE_UINT32, &np2oscfg.com[0].speed, 0}, + {OEMTEXT("com1mmap"), INITYPE_STR, np2oscfg.com[0].mout, MAX_PATH}, + {OEMTEXT("com1mmdl"), INITYPE_STR, np2oscfg.com[0].mdl, 64}, + {OEMTEXT("com1mdef"), INITYPE_STR, np2oscfg.com[0].def, MAX_PATH}, + + {OEMTEXT("com2port"), INIMAX_UINT8, &np2oscfg.com[1].port, COMPORT_NONE}, + {OEMTEXT("com2dir"), INITYPE_BOOL, &np2oscfg.com[1].direct, 1}, + {OEMTEXT("com2para"), INITYPE_UINT8, &np2oscfg.com[1].param, 0}, + {OEMTEXT("com2_bps"), INITYPE_UINT32, &np2oscfg.com[1].speed, 0}, + {OEMTEXT("com2mmap"), INITYPE_STR, np2oscfg.com[1].mout, MAX_PATH}, + {OEMTEXT("com2mmdl"), INITYPE_STR, np2oscfg.com[1].mdl, 64}, + {OEMTEXT("com2mdef"), INITYPE_STR, np2oscfg.com[1].def, MAX_PATH}, + + {OEMTEXT("com3port"), INIMAX_UINT8, &np2oscfg.com[2].port, COMPORT_NONE}, + {OEMTEXT("com3dir"), INITYPE_BOOL, &np2oscfg.com[2].direct, 1}, + {OEMTEXT("com3para"), INITYPE_UINT8, &np2oscfg.com[2].param, 0}, + {OEMTEXT("com3_bps"), INITYPE_UINT32, &np2oscfg.com[2].speed, 0}, + {OEMTEXT("com3mmap"), INITYPE_STR, np2oscfg.com[2].mout, MAX_PATH}, + {OEMTEXT("com3mmdl"), INITYPE_STR, np2oscfg.com[2].mdl, 64}, + {OEMTEXT("com3mdef"), INITYPE_STR, np2oscfg.com[2].def, MAX_PATH}, +#endif /* __LIBRETRO__ */ + +#if defined(SUPPORT_RESUME) + {OEMTEXT("e_resume"), INITYPE_BOOL, &np2oscfg.resume, 0}, +#endif +#if defined(SUPPORT_STATSAVE) + {OEMTEXT("STATSAVE"), INITYPE_BOOL, &np2cfg.statsave, 0}, +#endif + + {OEMTEXT("xrollkey"), INITYPE_BOOL, &np2oscfg.xrollkey, 0}, + + {OEMTEXT("sounddrv"), INITYPE_SNDDRV, &np2oscfg.snddrv, 0}, +#if !defined(__LIBRETRO__) +#if defined(_WIN32) + {OEMTEXT("MIDIOUTd"), INITYPE_STR, &np2oscfg.MIDIDEV[0], MAX_PATH}, + {OEMTEXT("MIDIIN_d"), INITYPE_STR, &np2oscfg.MIDIDEV[1], MAX_PATH}, +#if defined(SUPPORT_SMPU98) + {OEMTEXT("MIDIOUAd"), INITYPE_STR, &np2oscfg.MIDIDEVA[0], MAX_PATH}, + {OEMTEXT("MIDIINAd"), INITYPE_STR, &np2oscfg.MIDIDEVA[1], MAX_PATH}, + {OEMTEXT("MIDIOUBd"), INITYPE_STR, &np2oscfg.MIDIDEVB[0], MAX_PATH}, + {OEMTEXT("MIDIINBd"), INITYPE_STR, &np2oscfg.MIDIDEVB[1], MAX_PATH}, +#endif + {OEMTEXT("MIDIWAIT"), INITYPE_UINT32, &np2oscfg.MIDIWAIT, 0}, +#endif /* _WIN32 */ +#endif /* __LIBRETRO__ */ + + {OEMTEXT("s_NOWAIT"), INITYPE_BOOL, &np2oscfg.NOWAIT, 0}, + {OEMTEXT("SkpFrame"), INITYPE_UINT8, &np2oscfg.DRAW_SKIP, 0}, + {OEMTEXT("jast_snd"), INITYPE_BOOL, &np2oscfg.jastsnd, 0}, + +#if defined(SUPPORT_VIDEOFILTER) + {OEMTEXT("vf1_enable"), INITYPE_BOOL, &np2cfg.vf1_enable, 0}, + {OEMTEXT("vf1_pcount"), INITYPE_UINT8, &np2cfg.vf1_pcount, 3}, + {OEMTEXT("vf1_pno"), INITYPE_UINT8, &np2cfg.vf1_pno, 0}, + {OEMTEXT("vf1_p0_fc"), INITYPE_UINT8, &np2cfg.vf1_profile[0][0], 3}, + {OEMTEXT("vf1_p0_fno"), INITYPE_UINT8, &np2cfg.vf1_profile[0][1], 2}, + {OEMTEXT("vf1_p0_p0"), INITYPE_ARGU32, np2cfg.vf1_param[0][0], 8}, + {OEMTEXT("vf1_p0_p1"), INITYPE_ARGU32, np2cfg.vf1_param[0][1], 8}, + {OEMTEXT("vf1_p0_p2"), INITYPE_ARGU32, np2cfg.vf1_param[0][2], 8}, + {OEMTEXT("vf1_p1_fc"), INITYPE_UINT8, &np2cfg.vf1_profile[1][0], 3}, + {OEMTEXT("vf1_p1_fno"), INITYPE_UINT8, &np2cfg.vf1_profile[1][1], 2}, + {OEMTEXT("vf1_p1_p0"), INITYPE_ARGU32, np2cfg.vf1_param[1][0], 8}, + {OEMTEXT("vf1_p1_p1"), INITYPE_ARGU32, np2cfg.vf1_param[1][1], 8}, + {OEMTEXT("vf1_p1_p2"), INITYPE_ARGU32, np2cfg.vf1_param[1][2], 8}, + {OEMTEXT("vf1_p2_fc"), INITYPE_UINT8, &np2cfg.vf1_profile[2][0], 3}, + {OEMTEXT("vf1_p2_fno"), INITYPE_UINT8, &np2cfg.vf1_profile[2][1], 2}, + {OEMTEXT("vf1_p2_p0"), INITYPE_ARGU32, np2cfg.vf1_param[2][0], 8}, + {OEMTEXT("vf1_p2_p1"), INITYPE_ARGU32, np2cfg.vf1_param[2][1], 8}, + {OEMTEXT("vf1_p2_p2"), INITYPE_ARGU32, np2cfg.vf1_param[2][2], 8}, +#endif + + // Keyrepeat + {OEMTEXT("keyrepeat_enable"), INITYPE_BOOL, &np2cfg.keyrepeat_enable, 0}, + {OEMTEXT("keyrepeat_delay"), INITYPE_UINT16, &np2cfg.keyrepeat_delay, 500}, + {OEMTEXT("keyrepeat_interval"), INITYPE_UINT16, &np2cfg.keyrepeat_interval, 50}, +}; + +#define INIITEMS (sizeof(iniitem) / sizeof(INITBL)) + + +static BOOL iniread_flag[INIITEMS]; + +static int +calc_index(const INITBL *p) +{ + UINT offset; + UINT idx; + + if (p) { + offset = (const OEMCHAR *)p - (const OEMCHAR *)iniitem; + if ((offset % sizeof(iniitem[0])) == 0) { + idx = offset / sizeof(iniitem[0]); + if (idx < INIITEMS) { + return idx; + } + } + } + return -1; +} + +static void +update_iniread_flag(const INITBL *p) +{ + int idx; + + idx = calc_index(p); + if (idx >= 0) { + iniread_flag[idx] = TRUE; + } +} + +static BOOL +read_iniread_flag(const INITBL *p) +{ + int idx; + + idx = calc_index(p); + if (idx >= 0) { + return iniread_flag[idx]; + } + return FALSE; +} + +void initload(void) { + + OEMCHAR path[MAX_PATH]; + + milstr_ncpy(path, file_getcd(inifile), sizeof(path)); + fprintf(stderr, OEMTEXT("Loading %s from %s\n"), inifile, path); +// TRACEOUT(OEMTEXT("Loading %s from %s", inifile, path)); + ini_read(path, ini_title, iniitem, INIITEMS); +} + +void initsave(void) { + + OEMCHAR path[MAX_PATH]; + + milstr_ncpy(path, file_getcd(inifile), sizeof(path)); + fprintf(stderr, OEMTEXT("Saving %s to %s\n"), inifile, path); + ini_write(path, ini_title, iniitem, INIITEMS); +} + +static const OEMCHAR s_szExt[] = OEMTEXT(".ini"); + +void initgetfile(OEMCHAR *lpPath, unsigned int cchPath) +{ + const OEMCHAR *lpIni = inifile; + if (lpIni) + { + file_cpyname(lpPath, lpIni, cchPath); + //LPCTSTR lpExt = file_getext(lpPath); + //if (lpExt[0] != '\0') + //{ + // file_catname(lpPath, s_szExt, cchPath); + //} + } + else + { + file_cpyname(lpPath, modulefile, cchPath); + file_cutext(lpPath); + file_catname(lpPath, s_szExt, cchPath); + } +} + diff --git a/sdl/inputmng.h b/sdl/inputmng.h old mode 100755 new mode 100644 index f2771af1..4c959297 --- a/sdl/inputmng.h +++ b/sdl/inputmng.h @@ -1,33 +1,33 @@ - -enum { - LBUTTON_BIT = (1 << 0), - RBUTTON_BIT = (1 << 1), - LBUTTON_DOWNBIT = (1 << 2), - RBUTTON_DOWNBIT = (1 << 3), - LBUTTON_UPBIT = (1 << 4), - RBUTTON_UPBIT = (1 << 5), - MOUSE_MOVEBIT = (1 << 6), - - KEY_ENTER = 0x01, - KEY_MENU = 0x02, - KEY_SKIP = 0x04, - KEY_EXT = 0x08, - NP2_KEY_UP = 0x10, - NP2_KEY_DOWN = 0x20, - NP2_KEY_LEFT = 0x40, - NP2_KEY_RIGHT = 0x80 -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -void inputmng_init(void); -void inputmng_keybind(short key, UINT bit); -UINT inputmng_getkey(short key); - -#ifdef __cplusplus -} -#endif - + +enum { + LBUTTON_BIT = (1 << 0), + RBUTTON_BIT = (1 << 1), + LBUTTON_DOWNBIT = (1 << 2), + RBUTTON_DOWNBIT = (1 << 3), + LBUTTON_UPBIT = (1 << 4), + RBUTTON_UPBIT = (1 << 5), + MOUSE_MOVEBIT = (1 << 6), + + KEY_ENTER = 0x01, + KEY_MENU = 0x02, + KEY_SKIP = 0x04, + KEY_EXT = 0x08, + NP2_KEY_UP = 0x10, + NP2_KEY_DOWN = 0x20, + NP2_KEY_LEFT = 0x40, + NP2_KEY_RIGHT = 0x80 +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +void inputmng_init(void); +void inputmng_keybind(short key, UINT bit); +UINT inputmng_getkey(short key); + +#ifdef __cplusplus +} +#endif + diff --git a/sdl/libretro/compiler.h b/sdl/libretro/compiler.h old mode 100755 new mode 100644 index a7b1ea0c..2040d5ad --- a/sdl/libretro/compiler.h +++ b/sdl/libretro/compiler.h @@ -1,32 +1,32 @@ -/** - * @file compiler.h - * @brief include file for standard system include files, - * or project specific include files that are used frequently, - * but are changed infrequently - */ - -#ifndef COMPILER_H -#define COMPILER_H - -#include "features/features_cpu.h" -#include "compiler_base.h" - -#include "sdlremap/sdl.h" -#include "sdlremap/sdl_keycode.h" - -#define msgbox(title, msg) - -#define __ASSERT(s) - -#define RESOURCE_US - -#define NP2_SIZE_VGA - -#define GETTICK() (cpu_features_get_time_usec() / 1000) // millisecond timer - -//#include "retro_inline.h" -#include -#include - -#endif // COMPILER_H - +/** + * @file compiler.h + * @brief include file for standard system include files, + * or project specific include files that are used frequently, + * but are changed infrequently + */ + +#ifndef COMPILER_H +#define COMPILER_H + +#include "features/features_cpu.h" +#include "compiler_base.h" + +#include "sdlremap/sdl.h" +#include "sdlremap/sdl_keycode.h" + +#define msgbox(title, msg) + +#define __ASSERT(s) + +#define RESOURCE_US + +#define NP2_SIZE_VGA + +#define GETTICK() (cpu_features_get_time_usec() / 1000) // millisecond timer + +//#include "retro_inline.h" +#include +#include + +#endif // COMPILER_H + diff --git a/sdl/libretro/libretro-common/include/glsym/rglgen_private_headers.h b/sdl/libretro/libretro-common/include/glsym/rglgen_private_headers.h index 2b5e520c..251e0ced 100644 --- a/sdl/libretro/libretro-common/include/glsym/rglgen_private_headers.h +++ b/sdl/libretro/libretro-common/include/glsym/rglgen_private_headers.h @@ -1,76 +1,76 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this libretro SDK code part (glsym). - * --------------------------------------------------------------------------------------- - * - * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef RGLGEN_PRIVATE_HEADERS_H__ -#define RGLGEN_PRIVATE_HEADERS_H__ - -#if defined(IOS) - -#if defined(HAVE_OPENGLES3) -#include -#include -#else -#include -#include -#endif - -#elif defined(__APPLE__) -#include -#if MAC_OS_X_VERSION_10_7 -#include -#include -#else -#include -#include -#endif -#elif defined(HAVE_PSGL) -#include -#include -#elif defined(HAVE_OPENGL_MODERN) -#include -#include -#elif defined(HAVE_OPENGLES3) -#include -#define __gl2_h_ -#include -#elif defined(HAVE_OPENGLES2) -#include -#include -#elif defined(HAVE_OPENGLES1) -#include -#include -#else -#if defined(_WIN32) && !defined(_XBOX) -#define WIN32_LEAN_AND_MEAN -#include -#endif -#ifndef HAVE_LIBNX -#include -#include -#else -/* We need to avoid including on this platform */ -#include "switch/nx_gl.h" -#include -#endif /* SWITCH */ -#endif - -#endif +/* Copyright (C) 2010-2020 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro SDK code part (glsym). + * --------------------------------------------------------------------------------------- + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef RGLGEN_PRIVATE_HEADERS_H__ +#define RGLGEN_PRIVATE_HEADERS_H__ + +#if defined(IOS) + +#if defined(HAVE_OPENGLES3) +#include +#include +#else +#include +#include +#endif + +#elif defined(__APPLE__) +#include +#if MAC_OS_X_VERSION_10_7 +#include +#include +#else +#include +#include +#endif +#elif defined(HAVE_PSGL) +#include +#include +#elif defined(HAVE_OPENGL_MODERN) +#include +#include +#elif defined(HAVE_OPENGLES3) +#include +#define __gl2_h_ +#include +#elif defined(HAVE_OPENGLES2) +#include +#include +#elif defined(HAVE_OPENGLES1) +#include +#include +#else +#if defined(_WIN32) && !defined(_XBOX) +#define WIN32_LEAN_AND_MEAN +#include +#endif +#ifndef HAVE_LIBNX +#include +#include +#else +/* We need to avoid including on this platform */ +#include "switch/nx_gl.h" +#include +#endif /* SWITCH */ +#endif + +#endif diff --git a/sdl/libretro/libretro.c b/sdl/libretro/libretro.c old mode 100755 new mode 100644 index 8a34ef66..0d4b3ef3 --- a/sdl/libretro/libretro.c +++ b/sdl/libretro/libretro.c @@ -1,1902 +1,1902 @@ -#include -#include -#ifndef _MSC_VER -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#include "libretro.h" -#include "libretro_params.h" -#include "libretro_core_options.h" -#include "file_stream.h" - -#include //required to prevent missing type errors -#include -#include -#include -#include -#include -#include -#include "newdisk.h" -#include -#include -#include "kbdmng.h" -#include -#include -#include -#include -#include -#include -#include -#include "kbtrans.h" -#include -#include -#include -#if defined(SUPPORT_VIDEOFILTER) -#include -#endif -#include "sysmenu.h" -#include -#include -#include -#include -#include -#include -#include "gdc.h" -#if defined(SUPPORT_FMGEN) -#include -#endif /* defined(SUPPORT_FMGEN) */ -#if defined(SUPPORT_WAB) -#include -#include -#endif /* defined(SUPPORT_WAB) */ - -extern void sdlaudio_callback(void *userdata, unsigned char *stream, int len); - -signed short soundbuf[SNDSZ*2]; //16bit*2ch - -char RPATH[512]; -OEMCHAR tmppath[MAX_PATH]; - -retro_log_printf_t log_cb = NULL; -static retro_video_refresh_t video_cb = NULL; -static retro_input_poll_t poll_cb = NULL; -retro_input_state_t input_cb = NULL; -retro_environment_t environ_cb = NULL; -extern struct retro_midi_interface *retro_midi_interface; - -uint32_t FrameBuffer[LR_SCREENWIDTH * LR_SCREENHEIGHT]; - -retro_audio_sample_batch_t audio_batch_cb = NULL; - -static char CMDFILE[1024]; - -bool did_reset, joy2key; -int lr_init = 0; - -char lr_game_base_dir[MAX_PATH]; - -int lr_uselasthddmount; - -#ifdef _WIN32 -static char slash = '\\'; -#else -static char slash = '/'; -#endif - -static void update_variables(void); - -/* media swap support */ -struct retro_disk_control_callback dskcb; -extern char np2_main_disk_images_paths[50][MAX_PATH]; -extern unsigned int np2_main_disk_images_count; -static unsigned drvno = 1; -static unsigned disk_index = 0; -static bool disk_inserted = false; -static unsigned int lastidx = 0; - -//all the fake functions used to limit swapping to 1 disk drive -bool setdskeject(bool ejected){ - disk_inserted = !ejected; - return true; -} - -bool getdskeject(){ - return !disk_inserted; -} - -unsigned getdskindex(){ - return disk_index; -} - -bool setdskindex(unsigned index){ - disk_index = index; - if(disk_index == np2_main_disk_images_count) - { - //retroarch is trying to set "no disk in tray" - return true; - } - - update_variables(); - strcpy(np2cfg.fddfile[drvno], np2_main_disk_images_paths[disk_index]); - diskdrv_setfdd(drvno, np2_main_disk_images_paths[disk_index], 0); - return true; -} - -unsigned getnumimages(){ - return np2_main_disk_images_count; -} - -bool addimageindex() { - if (np2_main_disk_images_count >= 50) - return false; - - np2_main_disk_images_count++; - return true; -} - -bool replacedsk(unsigned index,const struct retro_game_info *info){ - strcpy(np2_main_disk_images_paths[index], info->path); - return true; -} - -void attach_disk_swap_interface(){ - //these functions are unused - dskcb.set_eject_state = setdskeject; - dskcb.get_eject_state = getdskeject; - dskcb.set_image_index = setdskindex; - dskcb.get_image_index = getdskindex; - dskcb.get_num_images = getnumimages; - dskcb.add_image_index = addimageindex; - dskcb.replace_image_index = replacedsk; - if(np2_main_disk_images_count) { - disk_inserted = true; - } - - environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE,&dskcb); -} - -void setnxtdskindex(void){ - if(np2_main_disk_images_count > 2) { - if(disk_index + 1 != np2_main_disk_images_count) { - setdskindex(disk_index + 1); - } else { - setdskindex(0); - } - } -} - -void setpredskindex(void){ - if(np2_main_disk_images_count > 2) { - if(disk_index == 0) { - setdskindex(np2_main_disk_images_count - 1); - } else { - setdskindex(disk_index - 1); - } - } -} -/* end media swap support */ - -int loadcmdfile(char *argv) -{ - int res = 0; - - RFILE* fp = filestream_open(argv, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); - if(fp != NULL) { - if(filestream_gets(fp, CMDFILE, 1024) != NULL) { - res = 1; - } - filestream_close(fp); - } - - return res; -} - -int HandleExtension(char *path,char *ext) -{ - int len = strlen(path); - - if (len >= 4 && - path[len-4] == '.' && - path[len-3] == ext[0] && - path[len-2] == ext[1] && - path[len-1] == ext[2]) - { - return 1; - } - - return 0; -} -//Args for experimental_cmdline -static char ARGUV[64][1024]; -static unsigned char ARGUC=0; - -// Args for Core -static char XARGV[64][1024]; -static const char* xargv_cmd[64]; -int PARAMCOUNT=0; - -extern int cmain(int argc, char *argv[]); - -void parse_cmdline(const char *argv); - -static void extract_directory(char *buf, const char *path, size_t size) -{ - char *base = NULL; - - strncpy(buf, path, size - 1); - buf[size - 1] = '\0'; - - base = strrchr(buf, '/'); - if (!base) - base = strrchr(buf, '\\'); - - if (base) - *base = '\0'; - else - buf[0] = '\0'; -} - -void Add_Option(const char* option) -{ - static int first=0; - - if(first==0) - { - PARAMCOUNT=0; - first++; - } - - sprintf(XARGV[PARAMCOUNT++],"%s",option); -} - -int pre_main(const char *argv) { - int i; - - CMDFILE[0] = '\0'; - if(strlen(argv) > strlen("cmd")) { - if(HandleExtension((char*)argv, "cmd") || HandleExtension((char*)argv, "CMD")) { - i = loadcmdfile((char*)argv); - } - } - - if(CMDFILE[0] == '\0') { - milstr_ncpy(CMDFILE, "np2kai \"", 1024); - milstr_ncat(CMDFILE, argv, 1024); - milstr_ncat(CMDFILE, "\"", 1024); - } - parse_cmdline(CMDFILE); - - for (i = 0; i<64; i++) - xargv_cmd[i] = NULL; - - for (i = 0; i < ARGUC; i++) - Add_Option(ARGUV[i]); - - for (i = 0; i < PARAMCOUNT; i++) - { - xargv_cmd[i] = (char*)(XARGV[i]); - printf("arg_%d:%s\n",i,xargv_cmd[i]); - printf("argl_%d:%d\n",i,strlen(xargv_cmd[i])); - } - - dosio_init(); - - i=np2_main(PARAMCOUNT,( char **)xargv_cmd); - - xargv_cmd[PARAMCOUNT - 2] = NULL; - - return 0; -} - -void parse_cmdline(const char *argv) { - char *p, *p2, *start_of_word; - int c, c2; - static char buffer[512 * 4]; - enum states { DULL, IN_WORD, IN_STRING } state = DULL; - - strcpy(buffer, argv); - strcat(buffer," \0"); - - for(p = buffer; *p != '\0'; p++) { - c = (unsigned char)*p; /* convert to unsigned char for is* functions */ - switch(state) { - case DULL: /* not in a word, not in a double quoted string */ - if(c == ' ' || c == '\t' || c == '\r' || c == '\n') { /* still not in a word, so ignore this char */ - continue; - } - /* not a space -- if it's a double quote we go to IN_STRING, else to IN_WORD */ - if(c == '"') { - state = IN_STRING; - start_of_word = p + 1; /* word starts at *next* char, not this one */ - continue; - } - state = IN_WORD; - start_of_word = p; /* word starts here */ - continue; - - case IN_STRING: - /* we're in a double quoted string, so keep going until we hit a close " */ - if(c == '"') { - /* word goes from start_of_word to p-1 */ - for(c2 = 0, p2 = start_of_word; p2 < p; p2++, c2++) { - ARGUV[ARGUC][c2] = (unsigned char)*p2; - } - ARGUC++; - state = DULL; /* back to "not in word, not in string" state */ - } - continue; /* either still IN_STRING or we handled the end above */ - - case IN_WORD: - /* we're in a word, so keep going until we get to a space */ - if(c == ' ' || c == '\t' || c == '\r' || c == '\n') { - /* word goes from start_of_word to p-1 */ - for(c2 = 0, p2 = start_of_word; p2 < p; p2++, c2++) { - ARGUV[ARGUC][c2] = (unsigned char)*p2; - } - ARGUC++; - state = DULL; /* back to "not in word, not in string" state */ - } - continue; /* either still IN_WORD or we handled the end above */ - } - } -} - -static const char *cross[] = { - "X ", - "XX ", - "X.X ", - "X..X ", - "X...X ", - "X....X ", - "X.....X ", - "X......X ", - "X.......X ", - "X........X ", - "X.....XXXXX ", - "X..X..X ", - "X.X X..X ", - "XX X..X ", - "X X..X ", - " X..X ", - " X..X ", - " X..X ", - " XX ", - " ", -}; - -void DrawPointBmp(unsigned int *buffer,int x, int y, unsigned int color) -{ - int idx; - int w, h; - - scrnmng_getsize(&w, &h); - - if(x>=0&&y>=0&&x= w) mposx = w - 1; - mposy += mouse_y_device; if(mposy < 0) mposy = 0; if(mposy >= h) mposy = h - 1; - if(lastx != mposx || lasty != mposy) - menubase_moving(mposx, mposy, 0); - } - } - - // Joy2Mouse - if(m_tJoyMode == LR_NP2KAI_JOYMODE_MOUSE) { - int j2m_move_x, j2m_move_y; - int j2m_u, j2m_d, j2m_l, j2m_r; - - j2m_move_x = j2m_move_y = 0; - - j2m_u = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP); - j2m_d = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN); - j2m_l = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT); - j2m_r = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT); - - if((j2m_u || j2m_d || j2m_l || j2m_r) && j2m_movebtn == 0) { - j2m_movebtn = 1; - j2m_axel = 1.0; - } else if(!(j2m_u || j2m_d || j2m_l || j2m_r) && j2m_movebtn == 1) { - j2m_movebtn = 0; - } - j2m_axel += 0.1; - - if(j2m_movebtn) { - if(j2m_u) { - if(j2m_l) { - j2m_move_x = 1.0 * -j2m_axel; - j2m_move_y = 1.0 * -j2m_axel; - } else if(j2m_r) { - j2m_move_x = 1.0 * j2m_axel; - j2m_move_y = 1.0 * -j2m_axel; - } else { - j2m_move_y = 1.0 * -j2m_axel / 1.414; - } - } else if(j2m_d) { - if(j2m_l) { - j2m_move_x = 1.0 * -j2m_axel; - j2m_move_y = 1.0 * j2m_axel; - } else if(j2m_r) { - j2m_move_x = 1.0 * j2m_axel; - j2m_move_y = 1.0 * j2m_axel; - } else { - j2m_move_y = 1.0 * j2m_axel / 1.414; - } - } else { - if(j2m_l) - j2m_move_x = 1.0 * -j2m_axel / 1.414; - else if(j2m_r) - j2m_move_x = 1.0 * j2m_axel / 1.414; - } - } - - if(menuvram == NULL) { - mousemng_sync(j2m_move_x, j2m_move_y); - } else { - mposx += j2m_move_x; - if(mposx < 0) - mposx = 0; - if(mposx >= w) - mposx = w - 1; - mposy += j2m_move_y; - if(mposy < 0) - mposy = 0; - if(mposy >= h) - mposy = h - 1; - if(lastx != mposx || lasty != mposy) - if(menuvram != NULL) - menubase_moving(mposx, mposy, 0); - } - } - - // Stick2Mouse - if(s2m) { - int use_stick; - int16_t analog_x, analog_y; - int mouse_move_x, mouse_move_y; - - if(s2m_no) { - use_stick = RETRO_DEVICE_INDEX_ANALOG_RIGHT; - } else { - use_stick = RETRO_DEVICE_INDEX_ANALOG_LEFT; - } - - analog_x = input_cb(0, RETRO_DEVICE_ANALOG, use_stick, RETRO_DEVICE_ID_ANALOG_X); - analog_y = input_cb(0, RETRO_DEVICE_ANALOG, use_stick, RETRO_DEVICE_ID_ANALOG_Y); - - mouse_move_x = (int)(analog_x * ((float)10 / 0x10000)); - mouse_move_y = (int)(analog_y * ((float)10 / 0x10000)); - - if(menuvram == NULL) { - mousemng_sync(mouse_move_x, mouse_move_y); - } else { - mposx += mouse_move_x; - if(mposx < 0) - mposx = 0; - if(mposx >= w) - mposx = w - 1; - mposy += mouse_move_y; - if(mposy < 0) - mposy = 0; - if(mposy >= h) - mposy = h - 1; - if(lastx != mposx || lasty != mposy) - menubase_moving(mposx, mposy, 0); - } - } - - lastx = mposx; lasty = mposy; - - // --- input mouse button - - // mouse - int mouse_l_device = 0; - int mouse_r_device = 0; - if(m_bInputMouse) { - mouse_l_device = input_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT); - mouse_r_device = input_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT); - } - int mouse_l, mouse_r; - - mouse_l = mouse_r = 0; - - if(mouse_l_device) { - mouse_l = 1; - } - if(mouse_r_device) { - mouse_r = 1; - } - - // joy2mouse - if(m_tJoyMode == LR_NP2KAI_JOYMODE_MOUSE) { - int j2m_a = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A); - int j2m_b = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B); - if(j2m_a) { - mouse_r = 1; - } - if(j2m_b) { - mouse_l = 1; - } - } - - // Stick2Mouse - if(s2m) { - int use_thumb; - int16_t analog_thumb; - int shift_btn = 0; - - if(s2m_no) { - use_thumb = RETRO_DEVICE_ID_JOYPAD_R3; - } else { - use_thumb = RETRO_DEVICE_ID_JOYPAD_L3; - } - - analog_thumb = input_cb(0, RETRO_DEVICE_JOYPAD, 0, use_thumb); - if(s2m_shift != 0xFF) { - shift_btn = input_cb(0, RETRO_DEVICE_JOYPAD, 0, s2m_shift); - } - - if(analog_thumb && !shift_btn) { - mouse_l = 1; - } else if(analog_thumb && shift_btn) { - mouse_r = 1; - } - } - - if(j2m_l_down == 0 && mouse_l) { - j2m_l_down = 1; - if(menuvram == NULL) { - mousemng_buttonevent(MOUSEMNG_LEFTDOWN); - } else { - menubase_moving(mposx, mposy, 1); - scrndraw_redraw(); - } - } else if(j2m_l_down == 1 && !mouse_l) { - j2m_l_down = 0; - if(menuvram == NULL) { - mousemng_buttonevent(MOUSEMNG_LEFTUP); - } else { - menubase_moving(mposx, mposy, 2); - scrndraw_redraw(); - } - } - if(j2m_r_down == 0 && mouse_r) { - j2m_r_down = 1; - if(menuvram == NULL) { - mousemng_buttonevent(MOUSEMNG_RIGHTDOWN); - scrndraw_redraw(); - } - } else if(j2m_r_down == 1 && !mouse_r) { - j2m_r_down= 0; - if(menuvram == NULL) { - mousemng_buttonevent(MOUSEMNG_RIGHTUP); - scrndraw_redraw(); - } - } -} - -void *retro_get_memory_data(unsigned type) -{ - if ( type == RETRO_MEMORY_SYSTEM_RAM ) - return CPU_EXTMEM; - return NULL; -} -size_t retro_get_memory_size(unsigned type) -{ - if ( type == RETRO_MEMORY_SYSTEM_RAM ) - return CPU_EXTMEMSIZE; - return 0; -} - -//dummy functions -void retro_set_audio_sample(retro_audio_sample_t cb){} -bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info){return false;} -void retro_unload_game (void){} - -void retro_set_video_refresh(retro_video_refresh_t cb) -{ - video_cb = cb; -} - -void retro_set_input_poll(retro_input_poll_t cb) -{ - poll_cb = cb; -} - -void retro_set_input_state(retro_input_state_t cb) -{ - input_cb = cb; -} - -void lowerstring(char* str) -{ - int i; - for (i=0; str[i]; i++) - { - str[i] = tolower(str[i]); - } -} - -void retro_set_environment(retro_environment_t cb) -{ - struct retro_log_callback logging; - BOOL allow_no_game = true; - - environ_cb = cb; - - //bool no_rom = !LR_REQUIRESROM; - //environ_cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_rom); - - environ_cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &allow_no_game); - - libretro_set_core_options(environ_cb); -} - -static void update_variables(void) -{ - struct retro_variable var = {0}; - - var.key = "np2kai_drive"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "FDD1") == 0) - drvno = 0; - else if (strcmp(var.value, "FDD2") == 0) - drvno = 1; - } - - var.key = "np2kai_keyrepeat"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "ON") == 0) - np2cfg.keyrepeat_enable = 1; - else - np2cfg.keyrepeat_enable = 0; - } - - var.key = "np2kai_keyrepeat_delay"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "250ms") == 0) - np2cfg.keyrepeat_delay = 250; - else if (strcmp(var.value, "1000ms") == 0) - np2cfg.keyrepeat_delay = 1000; - else - np2cfg.keyrepeat_delay = 500; - } - - var.key = "np2kai_keyrepeat_interval"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "25ms") == 0) - np2cfg.keyrepeat_interval = 25; - else if (strcmp(var.value, "100ms") == 0) - np2cfg.keyrepeat_interval = 100; - else - np2cfg.keyrepeat_interval = 50; - } - - var.key = "np2kai_keyboard"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "Us") == 0) - np2oscfg.KEYBOARD = KEY_KEY101; - else - np2oscfg.KEYBOARD = KEY_KEY106; - init_lrkey_to_pc98(); - } - - var.key = "np2kai_model"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "PC-9801VX") == 0) - milstr_ncpy(np2cfg.model, str_VX, 3); - else if (strcmp(var.value, "PC-286") == 0) - milstr_ncpy(np2cfg.model, str_EPSON, 6); - else if (strcmp(var.value, "PC-9801VM") == 0) - milstr_ncpy(np2cfg.model, str_VM, 3); - } - - var.key = "np2kai_clk_base"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "1.9968 MHz") == 0) - np2cfg.baseclock = 1996800; - else - np2cfg.baseclock = 2457600; - } - - var.key = "np2kai_cpu_feature"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - UINT cpu_index; - - if (strcmp(var.value, "Intel 80386") == 0) - cpu_index = 1; - else if (strcmp(var.value, "Intel i486SX") == 0) - cpu_index = 2; - else if (strcmp(var.value, "Intel i486DX") == 0) - cpu_index = 3; - else if (strcmp(var.value, "Intel Pentium") == 0) - cpu_index = 4; - else if (strcmp(var.value, "Intel MMX Pentium") == 0) - cpu_index = 5; - else if (strcmp(var.value, "Intel Pentium Pro") == 0) - cpu_index = 6; - else if (strcmp(var.value, "Intel Pentium II") == 0) - cpu_index = 7; - else if (strcmp(var.value, "Intel Pentium III") == 0) - cpu_index = 8; - else if (strcmp(var.value, "Intel Pentium M") == 0) - cpu_index = 9; - else if (strcmp(var.value, "Intel Pentium 4") == 0) - cpu_index = 10; - else if (strcmp(var.value, "AMD K6-2") == 0) - cpu_index = 15; - else if (strcmp(var.value, "AMD K6-III") == 0) - cpu_index = 16; - else if (strcmp(var.value, "AMD K7 Athlon") == 0) - cpu_index = 17; - else if (strcmp(var.value, "AMD K7 Athlon XP") == 0) - cpu_index = 18; - else if (strcmp(var.value, "Neko Processor II") == 0) - cpu_index = 255; - else - cpu_index = 0; - SetCpuTypeIndex(cpu_index); - } - - var.key = "np2kai_clk_mult"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - np2cfg.multiple = atoi(var.value); - } - -#if defined(SUPPORT_ASYNC_CPU) - var.key = "np2kai_async_cpu"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "OFF") == 0) - np2cfg.asynccpu = 0; - else - np2cfg.asynccpu = 1; - } -#endif - - var.key = "np2kai_ExMemory"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - np2cfg.EXTMEM = atoi(var.value); - } - - var.key = "np2kai_uselasthddmount"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "OFF") == 0) - lr_uselasthddmount = 0; - else - lr_uselasthddmount = 1; - } - - var.key = "np2kai_FastMC"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "OFF") == 0) - np2cfg.memcheckspeed = 1; - else - np2cfg.memcheckspeed = 8; - } - -#if defined(SUPPORT_VIDEOFILTER) - var.key = "np2kai_vf1"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "Profile 0") == 0) { - np2cfg.vf1_enable = 1; - np2cfg.vf1_pno = 0; - VideoFilter_SetEnable(hVFMng1, np2cfg.vf1_enable); - VideoFilter_SetProfileNo(hVFMng1, 0); - } else if (strcmp(var.value, "Profile 1") == 0) { - np2cfg.vf1_enable = 1; - np2cfg.vf1_pno = 1; - VideoFilter_SetEnable(hVFMng1, np2cfg.vf1_enable); - VideoFilter_SetProfileNo(hVFMng1, 1); - } else if (strcmp(var.value, "Profile 2") == 0) { - np2cfg.vf1_enable = 1; - np2cfg.vf1_pno = 2; - VideoFilter_SetEnable(hVFMng1, np2cfg.vf1_enable); - VideoFilter_SetProfileNo(hVFMng1, 2); - } else { - np2cfg.vf1_enable = 0; - VideoFilter_SetEnable(hVFMng1, np2cfg.vf1_enable); - } - scrndraw_redraw(); - } -#endif - - var.key = "np2kai_skipline"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "OFF") == 0) - np2cfg.skipline = false; - else if (strcmp(var.value, "ON") == 0) - np2cfg.skipline = true; - else if (strcmp(var.value, "Full 255 lines") == 0){ - np2cfg.skiplight = 255; - np2cfg.skipline = true; - } - scrndraw_redraw(); - } - - var.key = "np2kai_realpal"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "OFF") == 0) - np2cfg.RASTER = 0; - else - np2cfg.RASTER = 1; - } - - var.key = "np2kai_SNDboard"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "PC9801-86") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_86; - else if (strcmp(var.value, "PC9801-26K + 86") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_86_26K; - else if (strcmp(var.value, "PC9801-86 + Chibi-oto") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_14; - else if (strcmp(var.value, "PC9801-118") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_118; - else if (strcmp(var.value, "PC9801-86 + Mate-X PCM(B460)") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_86_WSS; - else if (strcmp(var.value, "PC9801-86 + 118(B460)") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_86_118; - else if (strcmp(var.value, "Mate-X PCM") == 0) - np2cfg.SOUND_SW = SOUNDID_MATE_X_PCM; - else if (strcmp(var.value, "Speak Board") == 0) - np2cfg.SOUND_SW = SOUNDID_SPEAKBOARD; - else if (strcmp(var.value, "PC9801-86 + Speak Board") == 0) - np2cfg.SOUND_SW = SOUNDID_86_SPEAKBOARD; - else if (strcmp(var.value, "Spark Board") == 0) - np2cfg.SOUND_SW = SOUNDID_SPARKBOARD; - else if (strcmp(var.value, "Sound Orchestra") == 0) - np2cfg.SOUND_SW = SOUNDID_SOUNDORCHESTRA; - else if (strcmp(var.value, "Sound Orchestra-V") == 0) - np2cfg.SOUND_SW = SOUNDID_SOUNDORCHESTRAV; - else if (strcmp(var.value, "Little Orchestra L") == 0) - np2cfg.SOUND_SW = SOUNDID_LITTLEORCHESTRAL; - else if (strcmp(var.value, "Multimedia Orchestra") == 0) - np2cfg.SOUND_SW = SOUNDID_MMORCHESTRA; -#if defined(SUPPORT_SOUND_SB16) - else if (strcmp(var.value, "Sound Blaster 16") == 0) - np2cfg.SOUND_SW = SOUNDID_SB16; - else if (strcmp(var.value, "PC9801-86 + Sound Blaster 16") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_86_SB16; - else if (strcmp(var.value, "Mate-X PCM + Sound Blaster 16") == 0) - np2cfg.SOUND_SW = SOUNDID_WSS_SB16; - else if (strcmp(var.value, "PC9801-118 + Sound Blaster 16") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_118_SB16; - else if (strcmp(var.value, "PC9801-86 + Mate-X PCM(B460) + Sound Blaster 16") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_86_WSS_SB16; - else if (strcmp(var.value, "PC9801-86 + 118(B460) + Sound Blaster 16") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_86_118_SB16; -#endif - else if (strcmp(var.value, "AMD-98") == 0) - np2cfg.SOUND_SW = SOUNDID_AMD98; - else if (strcmp(var.value, "WaveStar") == 0) - np2cfg.SOUND_SW = SOUNDID_WAVESTAR; -#if defined(SUPPORT_PX) - else if (strcmp(var.value, "Otomi-chanx2") == 0) - np2cfg.SOUND_SW = SOUNDID_PX1; - else if (strcmp(var.value, "Otomi-chanx2 + 86") == 0) - np2cfg.SOUND_SW = SOUNDID_PX2; -#endif - else if (strcmp(var.value, "None") == 0) - np2cfg.SOUND_SW = SOUNDID_NONE; - else if (strcmp(var.value, "PC9801-14") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_14; - else if (strcmp(var.value, "PC9801-26K") == 0) - np2cfg.SOUND_SW = SOUNDID_PC_9801_26K; - } - - var.key = "np2kai_118ROM"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "OFF") == 0) - np2cfg.snd118rom = 0; - else if (strcmp(var.value, "ON") == 0) - np2cfg.snd118rom = 1; - } - - var.key = "np2kai_jast_snd"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "OFF") == 0) - np2oscfg.jastsnd = 0; - else if (strcmp(var.value, "ON") == 0) - np2oscfg.jastsnd = 1; - } - - var.key = "np2kai_usefmgen"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "Default") == 0) - np2cfg.usefmgen = 0x00; - else if (strcmp(var.value, "fmgen") == 0) - np2cfg.usefmgen = 0x01; - } - - var.key = "np2kai_xroll"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "OFF") == 0) - np2oscfg.xrollkey = 0; - else if (strcmp(var.value, "ON") == 0) - np2oscfg.xrollkey = 1; - } - - var.key = "np2kai_volume_M"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - np2cfg.vol_master = atoi(var.value); - } - - var.key = "np2kai_volume_F"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - np2cfg.vol_fm = atoi(var.value); - opngen_setvol(np2cfg.vol_fm); - oplgen_setvol(np2cfg.vol_fm); -#if defined(SUPPORT_FMGEN) - if(g_opna[0].fmgen) - OPNA_SetVolumeFM(g_opna[0].fmgen, pow((double)np2cfg.vol_fm / 128, 0.12) * (20 + 192) - 192); -#endif /* defined(SUPPORT_FMGEN) */ - } - - var.key = "np2kai_volume_S"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - np2cfg.vol_ssg = atoi(var.value); - psggen_setvol(np2cfg.vol_ssg); -#if defined(SUPPORT_FMGEN) - if(g_opna[0].fmgen) - OPNA_SetVolumePSG(g_opna[0].fmgen, pow((double)np2cfg.vol_ssg / 128, 0.12) * (20 + 192) - 192); -#endif /* defined(SUPPORT_FMGEN) */ - } - - var.key = "np2kai_volume_A"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - np2cfg.vol_adpcm = atoi(var.value); - adpcm_setvol(np2cfg.vol_adpcm); - } - - var.key = "np2kai_volume_P"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - np2cfg.vol_pcm = atoi(var.value); - pcm86gen_setvol(np2cfg.vol_pcm); -#if defined(SUPPORT_FMGEN) - if(g_opna[0].fmgen) - OPNA_SetVolumeADPCM(g_opna[0].fmgen, pow((double)np2cfg.vol_pcm / 128, 0.12) * (20 + 192) - 192); -#endif /* defined(SUPPORT_FMGEN) */ - } - - var.key = "np2kai_volume_R"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - np2cfg.vol_rhythm = atoi(var.value); - rhythm_setvol(np2cfg.vol_rhythm); -#if defined(SUPPORT_FMGEN) - if(g_opna[0].fmgen) - OPNA_SetVolumeRhythmTotal(g_opna[0].fmgen, pow((double)np2cfg.vol_rhythm / 128, 0.12) * (20 + 192) - 192); -#endif /* defined(SUPPORT_FMGEN) */ - } - - var.key = "np2kai_volume_C"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - np2cfg.davolume = atoi(var.value); - rhythm_setvol(np2cfg.davolume); - } - - var.key = "np2kai_Seek_Snd"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "OFF") == 0) - np2cfg.MOTOR = false; - else if (strcmp(var.value, "ON") == 0) - np2cfg.MOTOR = true; - } - - var.key = "np2kai_Seek_Vol"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - np2cfg.MOTORVOL = atoi(var.value); - } - - var.key = "np2kai_BEEP_vol"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - np2cfg.BEEP_VOL = atoi(var.value); - beep_setvol(np2cfg.BEEP_VOL); - } - -#if defined(SUPPORT_WAB) - var.key = "np2kai_CLGD_en"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "ON") == 0) - np2cfg.usegd5430 = 1; - else - np2cfg.usegd5430 = 0; - } - - var.key = "np2kai_CLGD_type"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "PC-9821Xe10,Xa7e,Xb10 built-in") == 0) - np2cfg.gd5430type = CIRRUS_98ID_Xe10; - else if (strcmp(var.value, "PC-9821Bp,Bs,Be,Bf built-in") == 0) - np2cfg.gd5430type = CIRRUS_98ID_Be; - else if (strcmp(var.value, "PC-9821Xe built-in") == 0) - np2cfg.gd5430type = CIRRUS_98ID_Xe; - else if (strcmp(var.value, "PC-9821Cb built-in") == 0) - np2cfg.gd5430type = CIRRUS_98ID_Cb; - else if (strcmp(var.value, "PC-9821Cf built-in") == 0) - np2cfg.gd5430type = CIRRUS_98ID_Cf; - else if (strcmp(var.value, "PC-9821Cb2 built-in") == 0) - np2cfg.gd5430type = CIRRUS_98ID_Cb2; - else if (strcmp(var.value, "PC-9821Cx2 built-in") == 0) - np2cfg.gd5430type = CIRRUS_98ID_Cx2; - else if (strcmp(var.value, "PC-9821 PCI CL-GD5446 built-in") == 0) - np2cfg.gd5430type = CIRRUS_98ID_PCI; - else if (strcmp(var.value, "MELCO WAB-S") == 0) - np2cfg.gd5430type = CIRRUS_98ID_WAB; - else if (strcmp(var.value, "MELCO WSN-A2F") == 0) - np2cfg.gd5430type = CIRRUS_98ID_WSN_A2F; - else if (strcmp(var.value, "MELCO WSN-A4F") == 0) - np2cfg.gd5430type = CIRRUS_98ID_WSN; - else if (strcmp(var.value, "I-O DATA GA-98NBI/C") == 0) - np2cfg.gd5430type = CIRRUS_98ID_GA98NBIC; - else if (strcmp(var.value, "I-O DATA GA-98NBII") == 0) - np2cfg.gd5430type = CIRRUS_98ID_GA98NBII; - else if (strcmp(var.value, "I-O DATA GA-98NBIV") == 0) - np2cfg.gd5430type = CIRRUS_98ID_GA98NBIV; - else if (strcmp(var.value, "PC-9801-96(PC-9801B3-E02)") == 0) - np2cfg.gd5430type = CIRRUS_98ID_96; - else if (strcmp(var.value, "Auto Select(Xe10, GA-98NBI/C), PCI") == 0) - np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_G1_PCI; - else if (strcmp(var.value, "Auto Select(Xe10, GA-98NBII), PCI") == 0) - np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_G2_PCI; - else if (strcmp(var.value, "Auto Select(Xe10, GA-98NBIV), PCI") == 0) - np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_G4_PCI; - else if (strcmp(var.value, "Auto Select(Xe10, WAB-S), PCI") == 0) - np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_WA_PCI; - else if (strcmp(var.value, "Auto Select(Xe10, WSN-A2F), PCI") == 0) - np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_WS_PCI; - else if (strcmp(var.value, "Auto Select(Xe10, WSN-A4F), PCI") == 0) - np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_W4_PCI; - else if (strcmp(var.value, "Auto Select(Xe10, WAB-S)") == 0) - np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE10_WABS; - else if (strcmp(var.value, "Auto Select(Xe10, WSN-A2F)") == 0) - np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE10_WSN2; - else if (strcmp(var.value, "Auto Select(Xe10, WSN-A4F)") == 0) - np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE10_WSN4; - } - - var.key = "np2kai_CLGD_fc"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "ON") == 0) - np2cfg.gd5430fakecur = 1; - else - np2cfg.gd5430fakecur = 0; - } -#endif /* defined(SUPPORT_WAB) */ - -#if defined(SUPPORT_PEGC) - var.key = "np2kai_PEGC"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "ON") == 0) - np2cfg.usepegcplane = 1; - else - np2cfg.usepegcplane = 0; - } -#endif - -#if defined(SUPPORT_PCI) - var.key = "np2kai_PCI_en"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "ON") == 0) - np2cfg.usepci = 1; - else - np2cfg.usepci = 0; - } - - var.key = "np2kai_PCI_type"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "Intel 82434LX") == 0) - np2cfg.pci_pcmc = PCI_PCMC_82434LX; - else if (strcmp(var.value, "Intel 82441FX") == 0) - np2cfg.pci_pcmc = PCI_PCMC_82441FX; - else if (strcmp(var.value, "VLSI Wildcat") == 0) - np2cfg.pci_pcmc = PCI_PCMC_WILDCAT; - } - - var.key = "np2kai_PCI_bios32"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "ON") == 0) - np2cfg.pci_bios32 = 1; - else - np2cfg.pci_bios32 = 0; - } -#endif /* defined(SUPPORT_PCI) */ - - var.key = "np2kai_usecdecc"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "ON") == 0) - np2cfg.usecdecc = 1; - else - np2cfg.usecdecc = 0; - } - - var.key = "np2kai_inputmouse"; - var.value = NULL; - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - if(strcmp(var.value, "ON") == 0) { - m_bInputMouse = true; - } else { - m_bInputMouse = false; - } - } - - var.key = "np2kai_stick2mouse"; - var.value = NULL; - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - if(strcmp(var.value, "L-stick") == 0) { - s2m = true; - s2m_no = 0; - } else if(strcmp(var.value, "R-stick") == 0) { - s2m = true; - s2m_no = 1; - } else { - s2m = false; - } - } - - var.key = "np2kai_stick2mouse_shift"; - var.value = NULL; - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - if(strcmp(var.value, "R1") == 0) { - s2m_shift = RETRO_DEVICE_ID_JOYPAD_R; - } else if(strcmp(var.value, "R2") == 0) { - s2m_shift = RETRO_DEVICE_ID_JOYPAD_R2; - } else if(strcmp(var.value, "L1") == 0) { - s2m_shift = RETRO_DEVICE_ID_JOYPAD_L; - } else if(strcmp(var.value, "L2") == 0) { - s2m_shift = RETRO_DEVICE_ID_JOYPAD_L2; - } else { - s2m_shift = 0xFF; - } - } - - var.key = "np2kai_joymode"; - var.value = NULL; - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - int preJoyModeInt = m_tJoyModeInt; - if(strcmp(var.value, "Mouse") == 0) { - m_tJoyMode = LR_NP2KAI_JOYMODE_MOUSE; - m_tJoyModeInt = 1; - } else if(strcmp(var.value, "Arrows") == 0) { - m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; - memcpy(j2k_key, j2k_key_arrow, sizeof(uint16_t) * 12); - m_tJoyModeInt = 2; - } else if(strcmp(var.value, "Arrows 3button") == 0) { - m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; - memcpy(j2k_key, j2k_key_arrow3, sizeof(uint16_t) * 12); - m_tJoyModeInt = 3; - } else if(strcmp(var.value, "Keypad") == 0) { - m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; - memcpy(j2k_key, j2k_key_kpad, sizeof(uint16_t) * 12); - m_tJoyModeInt = 4; - } else if(strcmp(var.value, "Keypad 3button") == 0) { - m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; - memcpy(j2k_key, j2k_key_kpad3, sizeof(uint16_t) * 12); - m_tJoyModeInt = 5; - } else if(strcmp(var.value, "Manual Keyboard") == 0) { - m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; - memcpy(j2k_key, np2oscfg.lrjoybtn, sizeof(uint16_t) * 12); - m_tJoyModeInt = 6; - } else if(strcmp(var.value, "Atari Joypad") == 0) { - m_tJoyMode = LR_NP2KAI_JOYMODE_ATARI; - m_tJoyModeInt = 7; - } else if(strcmp(var.value, "Keypad Fighting") == 0) { - m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; - memcpy(j2k_key, j2k_key_kpadf, sizeof(uint16_t) * 12); - m_tJoyModeInt = 8; - } else { - m_tJoyMode = LR_NP2KAI_JOYMODE_NONE; - m_tJoyModeInt = 0; - } - if(m_tJoyModeInt != preJoyModeInt) { - m_bJoyModeChange = TRUE; - } - } - - var.key = "np2kai_joynp2menu"; - var.value = NULL; - if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - if(strcmp(var.value, "A") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_A; - } else if(strcmp(var.value, "B") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_B; - } else if(strcmp(var.value, "X") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_X; - } else if(strcmp(var.value, "Y") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_Y; - } else if(strcmp(var.value, "L1") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_L; - } else if(strcmp(var.value, "L2") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_L2; - } else if(strcmp(var.value, "R1") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_R; - } else if(strcmp(var.value, "R2") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_R2; - } else if(strcmp(var.value, "L3") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_L3; - } else if(strcmp(var.value, "R3") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_R3; - } else if(strcmp(var.value, "Start") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_START; - } else if(strcmp(var.value, "Select") == 0) { - joyNP2menu = TRUE; - joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_SELECT; - } else { - joyNP2menu = FALSE; - } - } - - var.key = "np2kai_lcd"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "OFF") == 0) - np2cfg.LCD_MODE = 0; - else - np2cfg.LCD_MODE = 1; - pal_makelcdpal(); - scrndraw_redraw(); - } - - var.key = "np2kai_gdc"; - var.value = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (strcmp(var.value, "uPD72020") == 0) - np2cfg.uPD72020 = 1; - else - np2cfg.uPD72020 = 0; - gdc_restorekacmode(); - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - } - - sysmng_update(SYS_UPDATEOSCFG | SYS_UPDATECFG); - -} - -void retro_get_system_info(struct retro_system_info *info) -{ - memset(info, 0, sizeof(*info)); - info->need_fullpath = LR_NEEDFILEPATH; - info->valid_extensions = LR_VALIDFILEEXT; - info->library_version = LR_LIBVERSION; - info->library_name = LR_CORENAME; - info->block_extract = LR_BLOCKARCEXTRACT; -} - -void retro_get_system_av_info(struct retro_system_av_info *info) -{ - int w, h; - - scrnmng_getsize(&w, &h); - - info->geometry.base_width = w; - info->geometry.base_height = h; - info->geometry.max_width = w; - info->geometry.max_height = h; - info->geometry.aspect_ratio = (double)w / h; - info->timing.fps = LR_SCREENFPS; - info->timing.sample_rate = LR_SOUNDRATE; -} - -void retro_init (void) -{ - enum retro_pixel_format rgb; - - scrnmng_initialize(); - - update_variables(); - - struct retro_log_callback log; - if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) - log_cb = log.log; - else - log_cb = NULL; - - if (log_cb) - log_cb(RETRO_LOG_INFO, "Logger interface initialized\n"); - - if(log_cb) { - log_cb(RETRO_LOG_INFO, "*** Start NP2kai " NP2KAI_GIT_TAG " " NP2KAI_GIT_HASH "***\n"); - } - - uint64_t statestate = \ - RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE | \ - RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE | \ - RETRO_SERIALIZATION_QUIRK_FRONT_VARIABLE_SIZE | \ - RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT; - - environ_cb(RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS, &statestate); - - static struct retro_midi_interface midi_interface; - if(environ_cb(RETRO_ENVIRONMENT_GET_MIDI_INTERFACE, &midi_interface)) - retro_midi_interface = &midi_interface; - else - retro_midi_interface = NULL; - - if (log_cb) - log_cb(RETRO_LOG_INFO, "MIDI interface %s.\n", - retro_midi_interface ? "initialized" : "unavailable\n"); - -#if defined(SUPPORT_CL_GD5430) - draw32bit = np2cfg.usegd5430; -#endif - if(draw32bit) { - rgb = RETRO_PIXEL_FORMAT_XRGB8888; - } else { - rgb = RETRO_PIXEL_FORMAT_RGB565; - } - if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb) && log_cb) - log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 (or XRGB8888).\n"); -} - -void retro_deinit(void) -{ - np2_end(); -} - -void retro_reset (void) -{ - if(menuvram) { - menubase_close(); - menu_active = 0; - } - resetInput(); - pccore_reset(); - did_reset = true; -} -extern void playretro(); - -static int firstcall=1; - -void retro_run (void) -{ - if(firstcall) - { - pre_main(RPATH); - update_variables(); - pccore_cfgupdate(); - pccore_reset(); - firstcall=0; - printf("INIT done\n"); - return; - } - - bool updated = false; - int w, h; - - scrnmng_getsize(&w, &h); - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) - { - update_variables(); - } - - if (did_reset){ - if(menuvram) { - menubase_close(); - menu_active = 0; - } - resetInput(); - pccore_cfgupdate(); - if(nevent_iswork(NEVENT_CDWAIT)){ - nevent_forceexecute(NEVENT_CDWAIT); - } - pccore_reset(); - did_reset = false; - } - - updateInput(); - - if (menuvram != NULL){ - scrnmng_update(); - draw_cross(lastx,lasty); - } - else { - //emulate 1 frame - pccore_exec(true /*draw*/); - sdlaudio_callback(NULL, NULL,SNDSZ*4); - } - - if(draw32bit) { - video_cb(FrameBuffer, w, h, w * 4/*Pitch*/); - } else { - video_cb(FrameBuffer, w, h, w * 2/*Pitch*/); - } - - if (retro_midi_interface && retro_midi_interface->output_enabled()) - retro_midi_interface->flush(); -} - -void retro_cheat_reset(void) -{ - //no cheats on this core -} - -void retro_cheat_set(unsigned index, bool enabled, const char *code) -{ - //no cheats on this core -} - -bool retro_load_game(const struct retro_game_info *game) -{ - //get system dir - const char* syspath = 0; - OEMCHAR np2path[MAX_PATH]; - bool load_floppy=false; - bool worked = environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &syspath); - if(!worked)abort(); - - if(game != NULL) - extract_directory(lr_game_base_dir, game->path, sizeof(lr_game_base_dir)); - - milstr_ncpy(np2path, syspath, MAX_PATH); - lr_init = 1; - -#ifdef _WIN32 - milstr_ncat(np2path, OEMTEXT("\\np2kai"), MAX_PATH); -#else - milstr_ncat(np2path, OEMTEXT("/np2kai"), MAX_PATH); -#endif - - OEMSNPRINTF(tmppath, MAX_PATH, OEMTEXT("%s%c"), np2path, OEMPATHDIVC); - - np2cfg.delayms = 0; - - OEMSNPRINTF(np2cfg.fontfile, MAX_PATH, OEMTEXT("%s%cfont.bmp"), np2path, OEMPATHDIVC); - file_setcd(np2cfg.fontfile); - OEMSNPRINTF(np2cfg.biospath, MAX_PATH, OEMTEXT("%s%c"), np2path, OEMPATHDIVC); - - if(game != NULL) - strcpy(RPATH,game->path); - else - strcpy(RPATH,""); - - return true; -} - -void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) -{ - audio_batch_cb = cb; -} - -unsigned retro_api_version(void) -{ - return RETRO_API_VERSION; -} - -void retro_set_controller_port_device(unsigned port, unsigned device) -{ - (void)port; - (void)device; -} - -unsigned retro_get_region (void) -{ - return RETRO_REGION_NTSC; -} - -#define RETRO_NP2_TEMPSTATE "temp_.sxx" - -size_t retro_serialize_size(void) -{ - int ret; - char *path; - size_t size; - FILEH fh; - - path = file_getcd(RETRO_NP2_TEMPSTATE); - ret = statsave_save_d(path); - if(ret) { - size = 0; - } else { - fh = file_open_rb(path); - size = file_getsize(fh); - file_close(fh); - } - file_delete(path); - - return size; -} - -bool retro_serialize(void *data, size_t size) -{ - int ret; - char *path; - FILEH fh; - - path = file_getcd(RETRO_NP2_TEMPSTATE); - ret = statsave_save_d(path); - if(ret) { - file_delete(path); - return false; - } - fh = file_open_rb(path); - file_read(fh, data, size); - file_close(fh); - file_delete(path); - return true; -} - -bool retro_unserialize(const void *data, size_t size) -{ - int ret; - char *path; - FILEH fh; - - if(size <= 0) { - return false; - } - path = file_getcd(RETRO_NP2_TEMPSTATE); - fh = file_create(path); - file_write(fh, data, size); - file_close(fh); - statsave_load_d(path); - file_delete(path); - return true; -} - +#include +#include +#ifndef _MSC_VER +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "libretro.h" +#include "libretro_params.h" +#include "libretro_core_options.h" +#include "file_stream.h" + +#include //required to prevent missing type errors +#include +#include +#include +#include +#include +#include +#include "newdisk.h" +#include +#include +#include "kbdmng.h" +#include +#include +#include +#include +#include +#include +#include +#include "kbtrans.h" +#include +#include +#include +#if defined(SUPPORT_VIDEOFILTER) +#include +#endif +#include "sysmenu.h" +#include +#include +#include +#include +#include +#include +#include "gdc.h" +#if defined(SUPPORT_FMGEN) +#include +#endif /* defined(SUPPORT_FMGEN) */ +#if defined(SUPPORT_WAB) +#include +#include +#endif /* defined(SUPPORT_WAB) */ + +extern void sdlaudio_callback(void *userdata, unsigned char *stream, int len); + +signed short soundbuf[SNDSZ*2]; //16bit*2ch + +char RPATH[512]; +OEMCHAR tmppath[MAX_PATH]; + +retro_log_printf_t log_cb = NULL; +static retro_video_refresh_t video_cb = NULL; +static retro_input_poll_t poll_cb = NULL; +retro_input_state_t input_cb = NULL; +retro_environment_t environ_cb = NULL; +extern struct retro_midi_interface *retro_midi_interface; + +uint32_t FrameBuffer[LR_SCREENWIDTH * LR_SCREENHEIGHT]; + +retro_audio_sample_batch_t audio_batch_cb = NULL; + +static char CMDFILE[1024]; + +bool did_reset, joy2key; +int lr_init = 0; + +char lr_game_base_dir[MAX_PATH]; + +int lr_uselasthddmount; + +#ifdef _WIN32 +static char slash = '\\'; +#else +static char slash = '/'; +#endif + +static void update_variables(void); + +/* media swap support */ +struct retro_disk_control_callback dskcb; +extern char np2_main_disk_images_paths[50][MAX_PATH]; +extern unsigned int np2_main_disk_images_count; +static unsigned drvno = 1; +static unsigned disk_index = 0; +static bool disk_inserted = false; +static unsigned int lastidx = 0; + +//all the fake functions used to limit swapping to 1 disk drive +bool setdskeject(bool ejected){ + disk_inserted = !ejected; + return true; +} + +bool getdskeject(){ + return !disk_inserted; +} + +unsigned getdskindex(){ + return disk_index; +} + +bool setdskindex(unsigned index){ + disk_index = index; + if(disk_index == np2_main_disk_images_count) + { + //retroarch is trying to set "no disk in tray" + return true; + } + + update_variables(); + strcpy(np2cfg.fddfile[drvno], np2_main_disk_images_paths[disk_index]); + diskdrv_setfdd(drvno, np2_main_disk_images_paths[disk_index], 0); + return true; +} + +unsigned getnumimages(){ + return np2_main_disk_images_count; +} + +bool addimageindex() { + if (np2_main_disk_images_count >= 50) + return false; + + np2_main_disk_images_count++; + return true; +} + +bool replacedsk(unsigned index,const struct retro_game_info *info){ + strcpy(np2_main_disk_images_paths[index], info->path); + return true; +} + +void attach_disk_swap_interface(){ + //these functions are unused + dskcb.set_eject_state = setdskeject; + dskcb.get_eject_state = getdskeject; + dskcb.set_image_index = setdskindex; + dskcb.get_image_index = getdskindex; + dskcb.get_num_images = getnumimages; + dskcb.add_image_index = addimageindex; + dskcb.replace_image_index = replacedsk; + if(np2_main_disk_images_count) { + disk_inserted = true; + } + + environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE,&dskcb); +} + +void setnxtdskindex(void){ + if(np2_main_disk_images_count > 2) { + if(disk_index + 1 != np2_main_disk_images_count) { + setdskindex(disk_index + 1); + } else { + setdskindex(0); + } + } +} + +void setpredskindex(void){ + if(np2_main_disk_images_count > 2) { + if(disk_index == 0) { + setdskindex(np2_main_disk_images_count - 1); + } else { + setdskindex(disk_index - 1); + } + } +} +/* end media swap support */ + +int loadcmdfile(char *argv) +{ + int res = 0; + + RFILE* fp = filestream_open(argv, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); + if(fp != NULL) { + if(filestream_gets(fp, CMDFILE, 1024) != NULL) { + res = 1; + } + filestream_close(fp); + } + + return res; +} + +int HandleExtension(char *path,char *ext) +{ + int len = strlen(path); + + if (len >= 4 && + path[len-4] == '.' && + path[len-3] == ext[0] && + path[len-2] == ext[1] && + path[len-1] == ext[2]) + { + return 1; + } + + return 0; +} +//Args for experimental_cmdline +static char ARGUV[64][1024]; +static unsigned char ARGUC=0; + +// Args for Core +static char XARGV[64][1024]; +static const char* xargv_cmd[64]; +int PARAMCOUNT=0; + +extern int cmain(int argc, char *argv[]); + +void parse_cmdline(const char *argv); + +static void extract_directory(char *buf, const char *path, size_t size) +{ + char *base = NULL; + + strncpy(buf, path, size - 1); + buf[size - 1] = '\0'; + + base = strrchr(buf, '/'); + if (!base) + base = strrchr(buf, '\\'); + + if (base) + *base = '\0'; + else + buf[0] = '\0'; +} + +void Add_Option(const char* option) +{ + static int first=0; + + if(first==0) + { + PARAMCOUNT=0; + first++; + } + + sprintf(XARGV[PARAMCOUNT++],"%s",option); +} + +int pre_main(const char *argv) { + int i; + + CMDFILE[0] = '\0'; + if(strlen(argv) > strlen("cmd")) { + if(HandleExtension((char*)argv, "cmd") || HandleExtension((char*)argv, "CMD")) { + i = loadcmdfile((char*)argv); + } + } + + if(CMDFILE[0] == '\0') { + milstr_ncpy(CMDFILE, "np2kai \"", 1024); + milstr_ncat(CMDFILE, argv, 1024); + milstr_ncat(CMDFILE, "\"", 1024); + } + parse_cmdline(CMDFILE); + + for (i = 0; i<64; i++) + xargv_cmd[i] = NULL; + + for (i = 0; i < ARGUC; i++) + Add_Option(ARGUV[i]); + + for (i = 0; i < PARAMCOUNT; i++) + { + xargv_cmd[i] = (char*)(XARGV[i]); + printf("arg_%d:%s\n",i,xargv_cmd[i]); + printf("argl_%d:%d\n",i,strlen(xargv_cmd[i])); + } + + dosio_init(); + + i=np2_main(PARAMCOUNT,( char **)xargv_cmd); + + xargv_cmd[PARAMCOUNT - 2] = NULL; + + return 0; +} + +void parse_cmdline(const char *argv) { + char *p, *p2, *start_of_word; + int c, c2; + static char buffer[512 * 4]; + enum states { DULL, IN_WORD, IN_STRING } state = DULL; + + strcpy(buffer, argv); + strcat(buffer," \0"); + + for(p = buffer; *p != '\0'; p++) { + c = (unsigned char)*p; /* convert to unsigned char for is* functions */ + switch(state) { + case DULL: /* not in a word, not in a double quoted string */ + if(c == ' ' || c == '\t' || c == '\r' || c == '\n') { /* still not in a word, so ignore this char */ + continue; + } + /* not a space -- if it's a double quote we go to IN_STRING, else to IN_WORD */ + if(c == '"') { + state = IN_STRING; + start_of_word = p + 1; /* word starts at *next* char, not this one */ + continue; + } + state = IN_WORD; + start_of_word = p; /* word starts here */ + continue; + + case IN_STRING: + /* we're in a double quoted string, so keep going until we hit a close " */ + if(c == '"') { + /* word goes from start_of_word to p-1 */ + for(c2 = 0, p2 = start_of_word; p2 < p; p2++, c2++) { + ARGUV[ARGUC][c2] = (unsigned char)*p2; + } + ARGUC++; + state = DULL; /* back to "not in word, not in string" state */ + } + continue; /* either still IN_STRING or we handled the end above */ + + case IN_WORD: + /* we're in a word, so keep going until we get to a space */ + if(c == ' ' || c == '\t' || c == '\r' || c == '\n') { + /* word goes from start_of_word to p-1 */ + for(c2 = 0, p2 = start_of_word; p2 < p; p2++, c2++) { + ARGUV[ARGUC][c2] = (unsigned char)*p2; + } + ARGUC++; + state = DULL; /* back to "not in word, not in string" state */ + } + continue; /* either still IN_WORD or we handled the end above */ + } + } +} + +static const char *cross[] = { + "X ", + "XX ", + "X.X ", + "X..X ", + "X...X ", + "X....X ", + "X.....X ", + "X......X ", + "X.......X ", + "X........X ", + "X.....XXXXX ", + "X..X..X ", + "X.X X..X ", + "XX X..X ", + "X X..X ", + " X..X ", + " X..X ", + " X..X ", + " XX ", + " ", +}; + +void DrawPointBmp(unsigned int *buffer,int x, int y, unsigned int color) +{ + int idx; + int w, h; + + scrnmng_getsize(&w, &h); + + if(x>=0&&y>=0&&x= w) mposx = w - 1; + mposy += mouse_y_device; if(mposy < 0) mposy = 0; if(mposy >= h) mposy = h - 1; + if(lastx != mposx || lasty != mposy) + menubase_moving(mposx, mposy, 0); + } + } + + // Joy2Mouse + if(m_tJoyMode == LR_NP2KAI_JOYMODE_MOUSE) { + int j2m_move_x, j2m_move_y; + int j2m_u, j2m_d, j2m_l, j2m_r; + + j2m_move_x = j2m_move_y = 0; + + j2m_u = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP); + j2m_d = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN); + j2m_l = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT); + j2m_r = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT); + + if((j2m_u || j2m_d || j2m_l || j2m_r) && j2m_movebtn == 0) { + j2m_movebtn = 1; + j2m_axel = 1.0; + } else if(!(j2m_u || j2m_d || j2m_l || j2m_r) && j2m_movebtn == 1) { + j2m_movebtn = 0; + } + j2m_axel += 0.1; + + if(j2m_movebtn) { + if(j2m_u) { + if(j2m_l) { + j2m_move_x = 1.0 * -j2m_axel; + j2m_move_y = 1.0 * -j2m_axel; + } else if(j2m_r) { + j2m_move_x = 1.0 * j2m_axel; + j2m_move_y = 1.0 * -j2m_axel; + } else { + j2m_move_y = 1.0 * -j2m_axel / 1.414; + } + } else if(j2m_d) { + if(j2m_l) { + j2m_move_x = 1.0 * -j2m_axel; + j2m_move_y = 1.0 * j2m_axel; + } else if(j2m_r) { + j2m_move_x = 1.0 * j2m_axel; + j2m_move_y = 1.0 * j2m_axel; + } else { + j2m_move_y = 1.0 * j2m_axel / 1.414; + } + } else { + if(j2m_l) + j2m_move_x = 1.0 * -j2m_axel / 1.414; + else if(j2m_r) + j2m_move_x = 1.0 * j2m_axel / 1.414; + } + } + + if(menuvram == NULL) { + mousemng_sync(j2m_move_x, j2m_move_y); + } else { + mposx += j2m_move_x; + if(mposx < 0) + mposx = 0; + if(mposx >= w) + mposx = w - 1; + mposy += j2m_move_y; + if(mposy < 0) + mposy = 0; + if(mposy >= h) + mposy = h - 1; + if(lastx != mposx || lasty != mposy) + if(menuvram != NULL) + menubase_moving(mposx, mposy, 0); + } + } + + // Stick2Mouse + if(s2m) { + int use_stick; + int16_t analog_x, analog_y; + int mouse_move_x, mouse_move_y; + + if(s2m_no) { + use_stick = RETRO_DEVICE_INDEX_ANALOG_RIGHT; + } else { + use_stick = RETRO_DEVICE_INDEX_ANALOG_LEFT; + } + + analog_x = input_cb(0, RETRO_DEVICE_ANALOG, use_stick, RETRO_DEVICE_ID_ANALOG_X); + analog_y = input_cb(0, RETRO_DEVICE_ANALOG, use_stick, RETRO_DEVICE_ID_ANALOG_Y); + + mouse_move_x = (int)(analog_x * ((float)10 / 0x10000)); + mouse_move_y = (int)(analog_y * ((float)10 / 0x10000)); + + if(menuvram == NULL) { + mousemng_sync(mouse_move_x, mouse_move_y); + } else { + mposx += mouse_move_x; + if(mposx < 0) + mposx = 0; + if(mposx >= w) + mposx = w - 1; + mposy += mouse_move_y; + if(mposy < 0) + mposy = 0; + if(mposy >= h) + mposy = h - 1; + if(lastx != mposx || lasty != mposy) + menubase_moving(mposx, mposy, 0); + } + } + + lastx = mposx; lasty = mposy; + + // --- input mouse button + + // mouse + int mouse_l_device = 0; + int mouse_r_device = 0; + if(m_bInputMouse) { + mouse_l_device = input_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT); + mouse_r_device = input_cb(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT); + } + int mouse_l, mouse_r; + + mouse_l = mouse_r = 0; + + if(mouse_l_device) { + mouse_l = 1; + } + if(mouse_r_device) { + mouse_r = 1; + } + + // joy2mouse + if(m_tJoyMode == LR_NP2KAI_JOYMODE_MOUSE) { + int j2m_a = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A); + int j2m_b = input_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B); + if(j2m_a) { + mouse_r = 1; + } + if(j2m_b) { + mouse_l = 1; + } + } + + // Stick2Mouse + if(s2m) { + int use_thumb; + int16_t analog_thumb; + int shift_btn = 0; + + if(s2m_no) { + use_thumb = RETRO_DEVICE_ID_JOYPAD_R3; + } else { + use_thumb = RETRO_DEVICE_ID_JOYPAD_L3; + } + + analog_thumb = input_cb(0, RETRO_DEVICE_JOYPAD, 0, use_thumb); + if(s2m_shift != 0xFF) { + shift_btn = input_cb(0, RETRO_DEVICE_JOYPAD, 0, s2m_shift); + } + + if(analog_thumb && !shift_btn) { + mouse_l = 1; + } else if(analog_thumb && shift_btn) { + mouse_r = 1; + } + } + + if(j2m_l_down == 0 && mouse_l) { + j2m_l_down = 1; + if(menuvram == NULL) { + mousemng_buttonevent(MOUSEMNG_LEFTDOWN); + } else { + menubase_moving(mposx, mposy, 1); + scrndraw_redraw(); + } + } else if(j2m_l_down == 1 && !mouse_l) { + j2m_l_down = 0; + if(menuvram == NULL) { + mousemng_buttonevent(MOUSEMNG_LEFTUP); + } else { + menubase_moving(mposx, mposy, 2); + scrndraw_redraw(); + } + } + if(j2m_r_down == 0 && mouse_r) { + j2m_r_down = 1; + if(menuvram == NULL) { + mousemng_buttonevent(MOUSEMNG_RIGHTDOWN); + scrndraw_redraw(); + } + } else if(j2m_r_down == 1 && !mouse_r) { + j2m_r_down= 0; + if(menuvram == NULL) { + mousemng_buttonevent(MOUSEMNG_RIGHTUP); + scrndraw_redraw(); + } + } +} + +void *retro_get_memory_data(unsigned type) +{ + if ( type == RETRO_MEMORY_SYSTEM_RAM ) + return CPU_EXTMEM; + return NULL; +} +size_t retro_get_memory_size(unsigned type) +{ + if ( type == RETRO_MEMORY_SYSTEM_RAM ) + return CPU_EXTMEMSIZE; + return 0; +} + +//dummy functions +void retro_set_audio_sample(retro_audio_sample_t cb){} +bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info){return false;} +void retro_unload_game (void){} + +void retro_set_video_refresh(retro_video_refresh_t cb) +{ + video_cb = cb; +} + +void retro_set_input_poll(retro_input_poll_t cb) +{ + poll_cb = cb; +} + +void retro_set_input_state(retro_input_state_t cb) +{ + input_cb = cb; +} + +void lowerstring(char* str) +{ + int i; + for (i=0; str[i]; i++) + { + str[i] = tolower(str[i]); + } +} + +void retro_set_environment(retro_environment_t cb) +{ + struct retro_log_callback logging; + BOOL allow_no_game = true; + + environ_cb = cb; + + //bool no_rom = !LR_REQUIRESROM; + //environ_cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_rom); + + environ_cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &allow_no_game); + + libretro_set_core_options(environ_cb); +} + +static void update_variables(void) +{ + struct retro_variable var = {0}; + + var.key = "np2kai_drive"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "FDD1") == 0) + drvno = 0; + else if (strcmp(var.value, "FDD2") == 0) + drvno = 1; + } + + var.key = "np2kai_keyrepeat"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "ON") == 0) + np2cfg.keyrepeat_enable = 1; + else + np2cfg.keyrepeat_enable = 0; + } + + var.key = "np2kai_keyrepeat_delay"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "250ms") == 0) + np2cfg.keyrepeat_delay = 250; + else if (strcmp(var.value, "1000ms") == 0) + np2cfg.keyrepeat_delay = 1000; + else + np2cfg.keyrepeat_delay = 500; + } + + var.key = "np2kai_keyrepeat_interval"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "25ms") == 0) + np2cfg.keyrepeat_interval = 25; + else if (strcmp(var.value, "100ms") == 0) + np2cfg.keyrepeat_interval = 100; + else + np2cfg.keyrepeat_interval = 50; + } + + var.key = "np2kai_keyboard"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "Us") == 0) + np2oscfg.KEYBOARD = KEY_KEY101; + else + np2oscfg.KEYBOARD = KEY_KEY106; + init_lrkey_to_pc98(); + } + + var.key = "np2kai_model"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "PC-9801VX") == 0) + milstr_ncpy(np2cfg.model, str_VX, 3); + else if (strcmp(var.value, "PC-286") == 0) + milstr_ncpy(np2cfg.model, str_EPSON, 6); + else if (strcmp(var.value, "PC-9801VM") == 0) + milstr_ncpy(np2cfg.model, str_VM, 3); + } + + var.key = "np2kai_clk_base"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "1.9968 MHz") == 0) + np2cfg.baseclock = 1996800; + else + np2cfg.baseclock = 2457600; + } + + var.key = "np2kai_cpu_feature"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + UINT cpu_index; + + if (strcmp(var.value, "Intel 80386") == 0) + cpu_index = 1; + else if (strcmp(var.value, "Intel i486SX") == 0) + cpu_index = 2; + else if (strcmp(var.value, "Intel i486DX") == 0) + cpu_index = 3; + else if (strcmp(var.value, "Intel Pentium") == 0) + cpu_index = 4; + else if (strcmp(var.value, "Intel MMX Pentium") == 0) + cpu_index = 5; + else if (strcmp(var.value, "Intel Pentium Pro") == 0) + cpu_index = 6; + else if (strcmp(var.value, "Intel Pentium II") == 0) + cpu_index = 7; + else if (strcmp(var.value, "Intel Pentium III") == 0) + cpu_index = 8; + else if (strcmp(var.value, "Intel Pentium M") == 0) + cpu_index = 9; + else if (strcmp(var.value, "Intel Pentium 4") == 0) + cpu_index = 10; + else if (strcmp(var.value, "AMD K6-2") == 0) + cpu_index = 15; + else if (strcmp(var.value, "AMD K6-III") == 0) + cpu_index = 16; + else if (strcmp(var.value, "AMD K7 Athlon") == 0) + cpu_index = 17; + else if (strcmp(var.value, "AMD K7 Athlon XP") == 0) + cpu_index = 18; + else if (strcmp(var.value, "Neko Processor II") == 0) + cpu_index = 255; + else + cpu_index = 0; + SetCpuTypeIndex(cpu_index); + } + + var.key = "np2kai_clk_mult"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + np2cfg.multiple = atoi(var.value); + } + +#if defined(SUPPORT_ASYNC_CPU) + var.key = "np2kai_async_cpu"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "OFF") == 0) + np2cfg.asynccpu = 0; + else + np2cfg.asynccpu = 1; + } +#endif + + var.key = "np2kai_ExMemory"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + np2cfg.EXTMEM = atoi(var.value); + } + + var.key = "np2kai_uselasthddmount"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "OFF") == 0) + lr_uselasthddmount = 0; + else + lr_uselasthddmount = 1; + } + + var.key = "np2kai_FastMC"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "OFF") == 0) + np2cfg.memcheckspeed = 1; + else + np2cfg.memcheckspeed = 8; + } + +#if defined(SUPPORT_VIDEOFILTER) + var.key = "np2kai_vf1"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "Profile 0") == 0) { + np2cfg.vf1_enable = 1; + np2cfg.vf1_pno = 0; + VideoFilter_SetEnable(hVFMng1, np2cfg.vf1_enable); + VideoFilter_SetProfileNo(hVFMng1, 0); + } else if (strcmp(var.value, "Profile 1") == 0) { + np2cfg.vf1_enable = 1; + np2cfg.vf1_pno = 1; + VideoFilter_SetEnable(hVFMng1, np2cfg.vf1_enable); + VideoFilter_SetProfileNo(hVFMng1, 1); + } else if (strcmp(var.value, "Profile 2") == 0) { + np2cfg.vf1_enable = 1; + np2cfg.vf1_pno = 2; + VideoFilter_SetEnable(hVFMng1, np2cfg.vf1_enable); + VideoFilter_SetProfileNo(hVFMng1, 2); + } else { + np2cfg.vf1_enable = 0; + VideoFilter_SetEnable(hVFMng1, np2cfg.vf1_enable); + } + scrndraw_redraw(); + } +#endif + + var.key = "np2kai_skipline"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "OFF") == 0) + np2cfg.skipline = false; + else if (strcmp(var.value, "ON") == 0) + np2cfg.skipline = true; + else if (strcmp(var.value, "Full 255 lines") == 0){ + np2cfg.skiplight = 255; + np2cfg.skipline = true; + } + scrndraw_redraw(); + } + + var.key = "np2kai_realpal"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "OFF") == 0) + np2cfg.RASTER = 0; + else + np2cfg.RASTER = 1; + } + + var.key = "np2kai_SNDboard"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "PC9801-86") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_86; + else if (strcmp(var.value, "PC9801-26K + 86") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_86_26K; + else if (strcmp(var.value, "PC9801-86 + Chibi-oto") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_14; + else if (strcmp(var.value, "PC9801-118") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_118; + else if (strcmp(var.value, "PC9801-86 + Mate-X PCM(B460)") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_86_WSS; + else if (strcmp(var.value, "PC9801-86 + 118(B460)") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_86_118; + else if (strcmp(var.value, "Mate-X PCM") == 0) + np2cfg.SOUND_SW = SOUNDID_MATE_X_PCM; + else if (strcmp(var.value, "Speak Board") == 0) + np2cfg.SOUND_SW = SOUNDID_SPEAKBOARD; + else if (strcmp(var.value, "PC9801-86 + Speak Board") == 0) + np2cfg.SOUND_SW = SOUNDID_86_SPEAKBOARD; + else if (strcmp(var.value, "Spark Board") == 0) + np2cfg.SOUND_SW = SOUNDID_SPARKBOARD; + else if (strcmp(var.value, "Sound Orchestra") == 0) + np2cfg.SOUND_SW = SOUNDID_SOUNDORCHESTRA; + else if (strcmp(var.value, "Sound Orchestra-V") == 0) + np2cfg.SOUND_SW = SOUNDID_SOUNDORCHESTRAV; + else if (strcmp(var.value, "Little Orchestra L") == 0) + np2cfg.SOUND_SW = SOUNDID_LITTLEORCHESTRAL; + else if (strcmp(var.value, "Multimedia Orchestra") == 0) + np2cfg.SOUND_SW = SOUNDID_MMORCHESTRA; +#if defined(SUPPORT_SOUND_SB16) + else if (strcmp(var.value, "Sound Blaster 16") == 0) + np2cfg.SOUND_SW = SOUNDID_SB16; + else if (strcmp(var.value, "PC9801-86 + Sound Blaster 16") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_86_SB16; + else if (strcmp(var.value, "Mate-X PCM + Sound Blaster 16") == 0) + np2cfg.SOUND_SW = SOUNDID_WSS_SB16; + else if (strcmp(var.value, "PC9801-118 + Sound Blaster 16") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_118_SB16; + else if (strcmp(var.value, "PC9801-86 + Mate-X PCM(B460) + Sound Blaster 16") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_86_WSS_SB16; + else if (strcmp(var.value, "PC9801-86 + 118(B460) + Sound Blaster 16") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_86_118_SB16; +#endif + else if (strcmp(var.value, "AMD-98") == 0) + np2cfg.SOUND_SW = SOUNDID_AMD98; + else if (strcmp(var.value, "WaveStar") == 0) + np2cfg.SOUND_SW = SOUNDID_WAVESTAR; +#if defined(SUPPORT_PX) + else if (strcmp(var.value, "Otomi-chanx2") == 0) + np2cfg.SOUND_SW = SOUNDID_PX1; + else if (strcmp(var.value, "Otomi-chanx2 + 86") == 0) + np2cfg.SOUND_SW = SOUNDID_PX2; +#endif + else if (strcmp(var.value, "None") == 0) + np2cfg.SOUND_SW = SOUNDID_NONE; + else if (strcmp(var.value, "PC9801-14") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_14; + else if (strcmp(var.value, "PC9801-26K") == 0) + np2cfg.SOUND_SW = SOUNDID_PC_9801_26K; + } + + var.key = "np2kai_118ROM"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "OFF") == 0) + np2cfg.snd118rom = 0; + else if (strcmp(var.value, "ON") == 0) + np2cfg.snd118rom = 1; + } + + var.key = "np2kai_jast_snd"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "OFF") == 0) + np2oscfg.jastsnd = 0; + else if (strcmp(var.value, "ON") == 0) + np2oscfg.jastsnd = 1; + } + + var.key = "np2kai_usefmgen"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "Default") == 0) + np2cfg.usefmgen = 0x00; + else if (strcmp(var.value, "fmgen") == 0) + np2cfg.usefmgen = 0x01; + } + + var.key = "np2kai_xroll"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "OFF") == 0) + np2oscfg.xrollkey = 0; + else if (strcmp(var.value, "ON") == 0) + np2oscfg.xrollkey = 1; + } + + var.key = "np2kai_volume_M"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + np2cfg.vol_master = atoi(var.value); + } + + var.key = "np2kai_volume_F"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + np2cfg.vol_fm = atoi(var.value); + opngen_setvol(np2cfg.vol_fm); + oplgen_setvol(np2cfg.vol_fm); +#if defined(SUPPORT_FMGEN) + if(g_opna[0].fmgen) + OPNA_SetVolumeFM(g_opna[0].fmgen, pow((double)np2cfg.vol_fm / 128, 0.12) * (20 + 192) - 192); +#endif /* defined(SUPPORT_FMGEN) */ + } + + var.key = "np2kai_volume_S"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + np2cfg.vol_ssg = atoi(var.value); + psggen_setvol(np2cfg.vol_ssg); +#if defined(SUPPORT_FMGEN) + if(g_opna[0].fmgen) + OPNA_SetVolumePSG(g_opna[0].fmgen, pow((double)np2cfg.vol_ssg / 128, 0.12) * (20 + 192) - 192); +#endif /* defined(SUPPORT_FMGEN) */ + } + + var.key = "np2kai_volume_A"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + np2cfg.vol_adpcm = atoi(var.value); + adpcm_setvol(np2cfg.vol_adpcm); + } + + var.key = "np2kai_volume_P"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + np2cfg.vol_pcm = atoi(var.value); + pcm86gen_setvol(np2cfg.vol_pcm); +#if defined(SUPPORT_FMGEN) + if(g_opna[0].fmgen) + OPNA_SetVolumeADPCM(g_opna[0].fmgen, pow((double)np2cfg.vol_pcm / 128, 0.12) * (20 + 192) - 192); +#endif /* defined(SUPPORT_FMGEN) */ + } + + var.key = "np2kai_volume_R"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + np2cfg.vol_rhythm = atoi(var.value); + rhythm_setvol(np2cfg.vol_rhythm); +#if defined(SUPPORT_FMGEN) + if(g_opna[0].fmgen) + OPNA_SetVolumeRhythmTotal(g_opna[0].fmgen, pow((double)np2cfg.vol_rhythm / 128, 0.12) * (20 + 192) - 192); +#endif /* defined(SUPPORT_FMGEN) */ + } + + var.key = "np2kai_volume_C"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + np2cfg.davolume = atoi(var.value); + rhythm_setvol(np2cfg.davolume); + } + + var.key = "np2kai_Seek_Snd"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "OFF") == 0) + np2cfg.MOTOR = false; + else if (strcmp(var.value, "ON") == 0) + np2cfg.MOTOR = true; + } + + var.key = "np2kai_Seek_Vol"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + np2cfg.MOTORVOL = atoi(var.value); + } + + var.key = "np2kai_BEEP_vol"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + np2cfg.BEEP_VOL = atoi(var.value); + beep_setvol(np2cfg.BEEP_VOL); + } + +#if defined(SUPPORT_WAB) + var.key = "np2kai_CLGD_en"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "ON") == 0) + np2cfg.usegd5430 = 1; + else + np2cfg.usegd5430 = 0; + } + + var.key = "np2kai_CLGD_type"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "PC-9821Xe10,Xa7e,Xb10 built-in") == 0) + np2cfg.gd5430type = CIRRUS_98ID_Xe10; + else if (strcmp(var.value, "PC-9821Bp,Bs,Be,Bf built-in") == 0) + np2cfg.gd5430type = CIRRUS_98ID_Be; + else if (strcmp(var.value, "PC-9821Xe built-in") == 0) + np2cfg.gd5430type = CIRRUS_98ID_Xe; + else if (strcmp(var.value, "PC-9821Cb built-in") == 0) + np2cfg.gd5430type = CIRRUS_98ID_Cb; + else if (strcmp(var.value, "PC-9821Cf built-in") == 0) + np2cfg.gd5430type = CIRRUS_98ID_Cf; + else if (strcmp(var.value, "PC-9821Cb2 built-in") == 0) + np2cfg.gd5430type = CIRRUS_98ID_Cb2; + else if (strcmp(var.value, "PC-9821Cx2 built-in") == 0) + np2cfg.gd5430type = CIRRUS_98ID_Cx2; + else if (strcmp(var.value, "PC-9821 PCI CL-GD5446 built-in") == 0) + np2cfg.gd5430type = CIRRUS_98ID_PCI; + else if (strcmp(var.value, "MELCO WAB-S") == 0) + np2cfg.gd5430type = CIRRUS_98ID_WAB; + else if (strcmp(var.value, "MELCO WSN-A2F") == 0) + np2cfg.gd5430type = CIRRUS_98ID_WSN_A2F; + else if (strcmp(var.value, "MELCO WSN-A4F") == 0) + np2cfg.gd5430type = CIRRUS_98ID_WSN; + else if (strcmp(var.value, "I-O DATA GA-98NBI/C") == 0) + np2cfg.gd5430type = CIRRUS_98ID_GA98NBIC; + else if (strcmp(var.value, "I-O DATA GA-98NBII") == 0) + np2cfg.gd5430type = CIRRUS_98ID_GA98NBII; + else if (strcmp(var.value, "I-O DATA GA-98NBIV") == 0) + np2cfg.gd5430type = CIRRUS_98ID_GA98NBIV; + else if (strcmp(var.value, "PC-9801-96(PC-9801B3-E02)") == 0) + np2cfg.gd5430type = CIRRUS_98ID_96; + else if (strcmp(var.value, "Auto Select(Xe10, GA-98NBI/C), PCI") == 0) + np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_G1_PCI; + else if (strcmp(var.value, "Auto Select(Xe10, GA-98NBII), PCI") == 0) + np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_G2_PCI; + else if (strcmp(var.value, "Auto Select(Xe10, GA-98NBIV), PCI") == 0) + np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_G4_PCI; + else if (strcmp(var.value, "Auto Select(Xe10, WAB-S), PCI") == 0) + np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_WA_PCI; + else if (strcmp(var.value, "Auto Select(Xe10, WSN-A2F), PCI") == 0) + np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_WS_PCI; + else if (strcmp(var.value, "Auto Select(Xe10, WSN-A4F), PCI") == 0) + np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE_W4_PCI; + else if (strcmp(var.value, "Auto Select(Xe10, WAB-S)") == 0) + np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE10_WABS; + else if (strcmp(var.value, "Auto Select(Xe10, WSN-A2F)") == 0) + np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE10_WSN2; + else if (strcmp(var.value, "Auto Select(Xe10, WSN-A4F)") == 0) + np2cfg.gd5430type = CIRRUS_98ID_AUTO_XE10_WSN4; + } + + var.key = "np2kai_CLGD_fc"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "ON") == 0) + np2cfg.gd5430fakecur = 1; + else + np2cfg.gd5430fakecur = 0; + } +#endif /* defined(SUPPORT_WAB) */ + +#if defined(SUPPORT_PEGC) + var.key = "np2kai_PEGC"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "ON") == 0) + np2cfg.usepegcplane = 1; + else + np2cfg.usepegcplane = 0; + } +#endif + +#if defined(SUPPORT_PCI) + var.key = "np2kai_PCI_en"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "ON") == 0) + np2cfg.usepci = 1; + else + np2cfg.usepci = 0; + } + + var.key = "np2kai_PCI_type"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "Intel 82434LX") == 0) + np2cfg.pci_pcmc = PCI_PCMC_82434LX; + else if (strcmp(var.value, "Intel 82441FX") == 0) + np2cfg.pci_pcmc = PCI_PCMC_82441FX; + else if (strcmp(var.value, "VLSI Wildcat") == 0) + np2cfg.pci_pcmc = PCI_PCMC_WILDCAT; + } + + var.key = "np2kai_PCI_bios32"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "ON") == 0) + np2cfg.pci_bios32 = 1; + else + np2cfg.pci_bios32 = 0; + } +#endif /* defined(SUPPORT_PCI) */ + + var.key = "np2kai_usecdecc"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "ON") == 0) + np2cfg.usecdecc = 1; + else + np2cfg.usecdecc = 0; + } + + var.key = "np2kai_inputmouse"; + var.value = NULL; + if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if(strcmp(var.value, "ON") == 0) { + m_bInputMouse = true; + } else { + m_bInputMouse = false; + } + } + + var.key = "np2kai_stick2mouse"; + var.value = NULL; + if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if(strcmp(var.value, "L-stick") == 0) { + s2m = true; + s2m_no = 0; + } else if(strcmp(var.value, "R-stick") == 0) { + s2m = true; + s2m_no = 1; + } else { + s2m = false; + } + } + + var.key = "np2kai_stick2mouse_shift"; + var.value = NULL; + if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if(strcmp(var.value, "R1") == 0) { + s2m_shift = RETRO_DEVICE_ID_JOYPAD_R; + } else if(strcmp(var.value, "R2") == 0) { + s2m_shift = RETRO_DEVICE_ID_JOYPAD_R2; + } else if(strcmp(var.value, "L1") == 0) { + s2m_shift = RETRO_DEVICE_ID_JOYPAD_L; + } else if(strcmp(var.value, "L2") == 0) { + s2m_shift = RETRO_DEVICE_ID_JOYPAD_L2; + } else { + s2m_shift = 0xFF; + } + } + + var.key = "np2kai_joymode"; + var.value = NULL; + if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + int preJoyModeInt = m_tJoyModeInt; + if(strcmp(var.value, "Mouse") == 0) { + m_tJoyMode = LR_NP2KAI_JOYMODE_MOUSE; + m_tJoyModeInt = 1; + } else if(strcmp(var.value, "Arrows") == 0) { + m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; + memcpy(j2k_key, j2k_key_arrow, sizeof(uint16_t) * 12); + m_tJoyModeInt = 2; + } else if(strcmp(var.value, "Arrows 3button") == 0) { + m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; + memcpy(j2k_key, j2k_key_arrow3, sizeof(uint16_t) * 12); + m_tJoyModeInt = 3; + } else if(strcmp(var.value, "Keypad") == 0) { + m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; + memcpy(j2k_key, j2k_key_kpad, sizeof(uint16_t) * 12); + m_tJoyModeInt = 4; + } else if(strcmp(var.value, "Keypad 3button") == 0) { + m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; + memcpy(j2k_key, j2k_key_kpad3, sizeof(uint16_t) * 12); + m_tJoyModeInt = 5; + } else if(strcmp(var.value, "Manual Keyboard") == 0) { + m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; + memcpy(j2k_key, np2oscfg.lrjoybtn, sizeof(uint16_t) * 12); + m_tJoyModeInt = 6; + } else if(strcmp(var.value, "Atari Joypad") == 0) { + m_tJoyMode = LR_NP2KAI_JOYMODE_ATARI; + m_tJoyModeInt = 7; + } else if(strcmp(var.value, "Keypad Fighting") == 0) { + m_tJoyMode = LR_NP2KAI_JOYMODE_KEY; + memcpy(j2k_key, j2k_key_kpadf, sizeof(uint16_t) * 12); + m_tJoyModeInt = 8; + } else { + m_tJoyMode = LR_NP2KAI_JOYMODE_NONE; + m_tJoyModeInt = 0; + } + if(m_tJoyModeInt != preJoyModeInt) { + m_bJoyModeChange = TRUE; + } + } + + var.key = "np2kai_joynp2menu"; + var.value = NULL; + if(environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + if(strcmp(var.value, "A") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_A; + } else if(strcmp(var.value, "B") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_B; + } else if(strcmp(var.value, "X") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_X; + } else if(strcmp(var.value, "Y") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_Y; + } else if(strcmp(var.value, "L1") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_L; + } else if(strcmp(var.value, "L2") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_L2; + } else if(strcmp(var.value, "R1") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_R; + } else if(strcmp(var.value, "R2") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_R2; + } else if(strcmp(var.value, "L3") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_L3; + } else if(strcmp(var.value, "R3") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_R3; + } else if(strcmp(var.value, "Start") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_START; + } else if(strcmp(var.value, "Select") == 0) { + joyNP2menu = TRUE; + joyNP2menubtn = RETRO_DEVICE_ID_JOYPAD_SELECT; + } else { + joyNP2menu = FALSE; + } + } + + var.key = "np2kai_lcd"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "OFF") == 0) + np2cfg.LCD_MODE = 0; + else + np2cfg.LCD_MODE = 1; + pal_makelcdpal(); + scrndraw_redraw(); + } + + var.key = "np2kai_gdc"; + var.value = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "uPD72020") == 0) + np2cfg.uPD72020 = 1; + else + np2cfg.uPD72020 = 0; + gdc_restorekacmode(); + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + } + + sysmng_update(SYS_UPDATEOSCFG | SYS_UPDATECFG); + +} + +void retro_get_system_info(struct retro_system_info *info) +{ + memset(info, 0, sizeof(*info)); + info->need_fullpath = LR_NEEDFILEPATH; + info->valid_extensions = LR_VALIDFILEEXT; + info->library_version = LR_LIBVERSION; + info->library_name = LR_CORENAME; + info->block_extract = LR_BLOCKARCEXTRACT; +} + +void retro_get_system_av_info(struct retro_system_av_info *info) +{ + int w, h; + + scrnmng_getsize(&w, &h); + + info->geometry.base_width = w; + info->geometry.base_height = h; + info->geometry.max_width = w; + info->geometry.max_height = h; + info->geometry.aspect_ratio = (double)w / h; + info->timing.fps = LR_SCREENFPS; + info->timing.sample_rate = LR_SOUNDRATE; +} + +void retro_init (void) +{ + enum retro_pixel_format rgb; + + scrnmng_initialize(); + + update_variables(); + + struct retro_log_callback log; + if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) + log_cb = log.log; + else + log_cb = NULL; + + if (log_cb) + log_cb(RETRO_LOG_INFO, "Logger interface initialized\n"); + + if(log_cb) { + log_cb(RETRO_LOG_INFO, "*** Start NP2kai " NP2KAI_GIT_TAG " " NP2KAI_GIT_HASH "***\n"); + } + + uint64_t statestate = \ + RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE | \ + RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE | \ + RETRO_SERIALIZATION_QUIRK_FRONT_VARIABLE_SIZE | \ + RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT; + + environ_cb(RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS, &statestate); + + static struct retro_midi_interface midi_interface; + if(environ_cb(RETRO_ENVIRONMENT_GET_MIDI_INTERFACE, &midi_interface)) + retro_midi_interface = &midi_interface; + else + retro_midi_interface = NULL; + + if (log_cb) + log_cb(RETRO_LOG_INFO, "MIDI interface %s.\n", + retro_midi_interface ? "initialized" : "unavailable\n"); + +#if defined(SUPPORT_CL_GD5430) + draw32bit = np2cfg.usegd5430; +#endif + if(draw32bit) { + rgb = RETRO_PIXEL_FORMAT_XRGB8888; + } else { + rgb = RETRO_PIXEL_FORMAT_RGB565; + } + if(environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb) && log_cb) + log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 (or XRGB8888).\n"); +} + +void retro_deinit(void) +{ + np2_end(); +} + +void retro_reset (void) +{ + if(menuvram) { + menubase_close(); + menu_active = 0; + } + resetInput(); + pccore_reset(); + did_reset = true; +} +extern void playretro(); + +static int firstcall=1; + +void retro_run (void) +{ + if(firstcall) + { + pre_main(RPATH); + update_variables(); + pccore_cfgupdate(); + pccore_reset(); + firstcall=0; + printf("INIT done\n"); + return; + } + + bool updated = false; + int w, h; + + scrnmng_getsize(&w, &h); + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) + { + update_variables(); + } + + if (did_reset){ + if(menuvram) { + menubase_close(); + menu_active = 0; + } + resetInput(); + pccore_cfgupdate(); + if(nevent_iswork(NEVENT_CDWAIT)){ + nevent_forceexecute(NEVENT_CDWAIT); + } + pccore_reset(); + did_reset = false; + } + + updateInput(); + + if (menuvram != NULL){ + scrnmng_update(); + draw_cross(lastx,lasty); + } + else { + //emulate 1 frame + pccore_exec(true /*draw*/); + sdlaudio_callback(NULL, NULL,SNDSZ*4); + } + + if(draw32bit) { + video_cb(FrameBuffer, w, h, w * 4/*Pitch*/); + } else { + video_cb(FrameBuffer, w, h, w * 2/*Pitch*/); + } + + if (retro_midi_interface && retro_midi_interface->output_enabled()) + retro_midi_interface->flush(); +} + +void retro_cheat_reset(void) +{ + //no cheats on this core +} + +void retro_cheat_set(unsigned index, bool enabled, const char *code) +{ + //no cheats on this core +} + +bool retro_load_game(const struct retro_game_info *game) +{ + //get system dir + const char* syspath = 0; + OEMCHAR np2path[MAX_PATH]; + bool load_floppy=false; + bool worked = environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &syspath); + if(!worked)abort(); + + if(game != NULL) + extract_directory(lr_game_base_dir, game->path, sizeof(lr_game_base_dir)); + + milstr_ncpy(np2path, syspath, MAX_PATH); + lr_init = 1; + +#ifdef _WIN32 + milstr_ncat(np2path, OEMTEXT("\\np2kai"), MAX_PATH); +#else + milstr_ncat(np2path, OEMTEXT("/np2kai"), MAX_PATH); +#endif + + OEMSNPRINTF(tmppath, MAX_PATH, OEMTEXT("%s%c"), np2path, OEMPATHDIVC); + + np2cfg.delayms = 0; + + OEMSNPRINTF(np2cfg.fontfile, MAX_PATH, OEMTEXT("%s%cfont.bmp"), np2path, OEMPATHDIVC); + file_setcd(np2cfg.fontfile); + OEMSNPRINTF(np2cfg.biospath, MAX_PATH, OEMTEXT("%s%c"), np2path, OEMPATHDIVC); + + if(game != NULL) + strcpy(RPATH,game->path); + else + strcpy(RPATH,""); + + return true; +} + +void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) +{ + audio_batch_cb = cb; +} + +unsigned retro_api_version(void) +{ + return RETRO_API_VERSION; +} + +void retro_set_controller_port_device(unsigned port, unsigned device) +{ + (void)port; + (void)device; +} + +unsigned retro_get_region (void) +{ + return RETRO_REGION_NTSC; +} + +#define RETRO_NP2_TEMPSTATE "temp_.sxx" + +size_t retro_serialize_size(void) +{ + int ret; + char *path; + size_t size; + FILEH fh; + + path = file_getcd(RETRO_NP2_TEMPSTATE); + ret = statsave_save_d(path); + if(ret) { + size = 0; + } else { + fh = file_open_rb(path); + size = file_getsize(fh); + file_close(fh); + } + file_delete(path); + + return size; +} + +bool retro_serialize(void *data, size_t size) +{ + int ret; + char *path; + FILEH fh; + + path = file_getcd(RETRO_NP2_TEMPSTATE); + ret = statsave_save_d(path); + if(ret) { + file_delete(path); + return false; + } + fh = file_open_rb(path); + file_read(fh, data, size); + file_close(fh); + file_delete(path); + return true; +} + +bool retro_unserialize(const void *data, size_t size) +{ + int ret; + char *path; + FILEH fh; + + if(size <= 0) { + return false; + } + path = file_getcd(RETRO_NP2_TEMPSTATE); + fh = file_create(path); + file_write(fh, data, size); + file_close(fh); + statsave_load_d(path); + file_delete(path); + return true; +} + diff --git a/sdl/libretro/libretro_core_options.h b/sdl/libretro/libretro_core_options.h index c94d59df..951c65fe 100644 --- a/sdl/libretro/libretro_core_options.h +++ b/sdl/libretro/libretro_core_options.h @@ -1,2023 +1,2023 @@ -#ifndef LIBRETRO_CORE_OPTIONS_H__ -#define LIBRETRO_CORE_OPTIONS_H__ - -#include -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - ******************************** - * Core Option Definitions - ******************************** -*/ - -/* RETRO_LANGUAGE_ENGLISH */ - -/* Default language: - * - All other languages must include the same keys and values - * - Will be used as a fallback in the event that frontend language - * is not available - * - Will be used as a fallback for any missing entries in - * frontend language definition */ - -struct retro_core_option_definition option_defs_us[] = { - { - "np2kai_drive", - "Swap Disks on Drive", - NULL, - { - { "FDD1", NULL }, - { "FDD2", NULL }, - { NULL, NULL}, - }, - "FDD2" - }, - { - "np2kai_keyboard", - "Keyboard (Restart)", - "Japanese or US keyboard type.", - { - { "Ja", NULL }, - { "Us", NULL }, - { NULL, NULL}, - }, - "Ja" - }, - { - "np2kai_keyrepeat", - "Key-repeat", - "Continue press key, key-repeat.", - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_keyrepeat_delay", - "Key-repeat delay", - "Key-repeat start after delay.", - { - { "250ms", NULL }, - { "500ms", NULL }, - { "1000ms", NULL }, - { NULL, NULL}, - }, - "500ms" - }, - { - "np2kai_keyrepeat_interval", - "Key-repeat interval", - "Key-repeat interval.", - { - { "25ms", NULL }, - { "50ms", NULL }, - { "100ms", NULL }, - { NULL, NULL}, - }, - "50ms" - }, - { - "np2kai_model", - "PC Model (Restart)", - NULL, - { - - { "PC-286", NULL }, - { "PC-9801VM", NULL }, - { "PC-9801VX", NULL }, - { NULL, NULL}, - }, - "PC-9801VX" - }, - { - "np2kai_clk_base", - "CPU Base Clock (Restart)", - NULL, - { - { "1.9968 MHz", NULL }, - { "2.4576 MHz", NULL }, - { NULL, NULL}, - }, - "2.4576 MHz" - }, - { - "np2kai_cpu_feature", - "CPU Feature (Restart)", - NULL, - { - { "(custom)", NULL }, - { "Intel 80386", NULL }, - { "Intel i486SX", NULL }, - { "Intel i486DX", NULL }, - { "Intel Pentium", NULL }, - { "Intel MMX Pentium", NULL }, - { "Intel Pentium Pro", NULL }, - { "Intel Pentium II", NULL }, - { "Intel Pentium III", NULL }, - { "Intel Pentium M", NULL }, - { "Intel Pentium 4", NULL }, - { "AMD K6-2", NULL }, - { "AMD K6-III", NULL }, - { "AMD K7 Athlon", NULL }, - { "AMD K7 Athlon XP", NULL }, - { "Neko Processor II", NULL }, - { NULL, NULL}, - }, - "Intel 80386" - }, - { - "np2kai_clk_mult", - "CPU Clock Multiplier (Restart)", - "Higher values require a fast machine. Can make some games run too fast.", - { - { "2", NULL }, - { "4", NULL }, - { "5", NULL }, - { "6", NULL }, - { "8", NULL }, - { "10", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "30", NULL }, - { "36", NULL }, - { "40", NULL }, - { "42", NULL }, - { "52", NULL }, - { "64", NULL }, - { "76", NULL }, - { "88", NULL }, - { "100", NULL }, - { NULL, NULL}, - }, - "4" - }, -#if defined(SUPPORT_ASYNC_CPU) - { - "np2kai_async_cpu", - "Async CPU(experimental) (Restart)", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, -#endif - { - "np2kai_ExMemory", - "RAM Size (Restart)", - "Amount of memory the virtual machine can use. Save states size will grow accordingly.", - { - { "1", NULL }, - { "3", NULL }, - { "7", NULL }, - { "11", NULL }, - { "13", NULL }, -#if defined(CPUCORE_IA32) - { "16", NULL }, - { "32", NULL }, - { "64", NULL }, - { "120", NULL }, - { "230", NULL }, - { "512", NULL }, - { "1024", NULL }, -#endif - { NULL, NULL}, - }, - "3" - }, - { - "np2kai_FastMC", - "Fast memcheck", - "Do a faster memory checking at startup.", - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_uselasthddmount", - "Use last HDD mount", - "Last HDD mount at core start.", - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, -#if defined(SUPPORT_VIDEOFILTER) - { - "np2kai_vf1", - "Video filter", - "Video filter setting. (Setting details set in cfg file)", - { - { "OFF", NULL }, - { "Profile 0", NULL }, - { "Profile 1", NULL }, - { "Profile 2", NULL }, - { NULL, NULL}, - }, - "OFF" - }, -#endif - { - "np2kai_gdc", - "GDC", - "Graphic Display Controller model.", - { - { "uPD7220", NULL }, - { "uPD72020", NULL }, - { NULL, NULL}, - }, - "uPD7220" - }, - { - "np2kai_skipline", - "Skipline Revisions", - "'Off' will show black scanlines in older games.", - { - { "Full 255 lines", NULL }, - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "Full 255 lines" - }, - { - "np2kai_realpal", - "Real Palettes", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_lcd", - "LCD (old monochrome)", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_SNDboard", - "Sound Board (Restart)", - NULL, - { - { "PC9801-14", NULL }, - { "PC9801-86", NULL }, - { "PC9801-86 + 118(B460)", NULL }, - { "PC9801-86 + Mate-X PCM(B460)", NULL }, - { "PC9801-86 + Chibi-oto", NULL }, - { "PC9801-86 + Speak Board", NULL }, - { "PC9801-26K", NULL }, - { "PC9801-26K + 86", NULL }, - { "PC9801-118", NULL }, - { "Mate-X PCM", NULL }, - { "Chibi-oto", NULL }, - { "Speak Board", NULL }, - { "Spark Board", NULL }, - { "Sound Orchestra", NULL }, - { "Sound Orchestra-V", NULL }, - { "Little Orchestra L", NULL }, - { "Multimedia Orchestra", NULL }, -#if defined(SUPPORT_SOUND_SB16) - { "Sound Blaster 16", NULL }, - { "PC9801-86 + Sound Blaster 16", NULL }, - { "Mate-X PCM + Sound Blaster 16", NULL }, - { "PC9801-118 + Sound Blaster 16", NULL }, - { "PC9801-86 + Mate-X PCM(B460) + Sound Blaster 16", NULL }, - { "PC9801-86 + 118(B460) + Sound Blaster 16", NULL }, -#endif - { "AMD-98", NULL }, - { "WaveStar", NULL }, -#if defined(SUPPORT_PX) - { "Otomi-chanx2", NULL }, - { "Otomi-chanx2 + 86", NULL }, -#endif - { "None", NULL }, - { NULL, NULL}, - }, - "PC9801-86" - }, - { - "np2kai_118ROM", - "enable 118 ROM", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "ON" - }, - { - "np2kai_jast_snd", - "JastSound", - "Enable Jast Sound PCM device.", - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_xroll", - "Swap PageUp/PageDown", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "ON" - }, - { - "np2kai_usefmgen", - "Sound Generator", - "Use 'fmgen' for enhanced sound rendering.", - { - { "Default", NULL }, - { "fmgen", NULL }, - { NULL, NULL}, - }, - "fmgen" - }, - { - "np2kai_volume_M", - "Volume Master", - NULL, - { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL}, - }, - "100" - }, - { - "np2kai_volume_F", - "Volume FM", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "64" - }, - { - "np2kai_volume_S", - "Volume SSG", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "28" - }, - { - "np2kai_volume_A", - "Volume ADPCM", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "64" - }, - { - "np2kai_volume_P", - "Volume PCM", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "92" - }, - { - "np2kai_volume_R", - "Volume RHYTHM", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "64" - }, - { - "np2kai_volume_C", - "Volume CD-DA", - NULL, - { - { "0", NULL }, - { "8", NULL }, - { "16", NULL }, - { "24", NULL }, - { "32", NULL }, - { "40", NULL }, - { "48", NULL }, - { "56", NULL }, - { "64", NULL }, - { "72", NULL }, - { "80", NULL }, - { "88", NULL }, - { "96", NULL }, - { "104", NULL }, - { "112", NULL }, - { "120", NULL }, - { "128", NULL }, - { "136", NULL }, - { "144", NULL }, - { "154", NULL }, - { "160", NULL }, - { "168", NULL }, - { "196", NULL }, - { "184", NULL }, - { "192", NULL }, - { "200", NULL }, - { "208", NULL }, - { "216", NULL }, - { "224", NULL }, - { "232", NULL }, - { "240", NULL }, - { "248", NULL }, - { "255", NULL }, - { NULL, NULL}, - }, - "128" - }, - { - "np2kai_Seek_Snd", - "Floppy Seek Sound", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_Seek_Vol", - "Volume Floppy Seek", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "" - }, - { - "np2kai_BEEP_vol", - "Volume Beep", - NULL, - { - { "0", NULL }, - { "1", NULL }, - { "2", NULL }, - { "3", NULL }, - { NULL, NULL}, - }, - "3" - }, -#if defined(SUPPORT_WAB) - { - "np2kai_CLGD_en", - "Enable WAB (Restart App)", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_CLGD_type", - "WAB Type", - NULL, - { - { "PC-9821Xe10,Xa7e,Xb10 built-in", NULL }, - { "PC-9821Bp,Bs,Be,Bf built-in", NULL }, - { "PC-9821Xe built-in", NULL }, - { "PC-9821Cb built-in", NULL }, - { "PC-9821Cf built-in", NULL }, - { "PC-9821Cb2 built-in", NULL }, - { "PC-9821Cx2 built-in", NULL }, - { "PC-9821 PCI CL-GD5446 built-in", NULL }, - { "MELCO WAB-S", NULL }, - { "MELCO WSN-A2F", NULL }, - { "MELCO WSN-A4F", NULL }, - { "I-O DATA GA-98NBI/C", NULL }, - { "I-O DATA GA-98NBII", NULL }, - { "I-O DATA GA-98NBIV", NULL }, - { "PC-9801-96(PC-9801B3-E02)", NULL }, - { "Auto Select(Xe10, GA-98NBI/C), PCI", NULL }, - { "Auto Select(Xe10, GA-98NBII), PCI", NULL }, - { "Auto Select(Xe10, GA-98NBIV), PCI", NULL }, - { "Auto Select(Xe10, WAB-S), PCI", NULL }, - { "Auto Select(Xe10, WSN-A2F), PCI", NULL }, - { "Auto Select(Xe10, WSN-A4F), PCI", NULL }, - { "Auto Select(Xe10, WAB-S)", NULL }, - { "Auto Select(Xe10, WSN-A2F)", NULL }, - { "Auto Select(Xe10, WSN-A4F)", NULL }, - { NULL, NULL}, - }, - "PC-9821Xe10,Xa7e,Xb10 built-in" - }, - { - "np2kai_CLGD_fc", - "Use Fake Hardware Cursor", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, -#endif /* defined(SUPPORT_WAB) */ -#if defined(SUPPORT_PEGC) - { - "np2kai_PEGC", - "Enable PEGC plane mode", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "ON" - }, -#endif -#if defined(SUPPORT_PCI) - { - "np2kai_PCI_en", - "Enable PCI (Restart App)", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_PCI_type", - "PCMC Type", - NULL, - { - { "Intel 82434LX", NULL }, - { "Intel 82441FX", NULL }, - { "VLSI Wildcat", NULL }, - { NULL, NULL}, - }, - "Intel 82434LX" - }, - { - "np2kai_PCI_bios32", - "Use BIOS32 (not recommended)", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, -#endif /* defined(SUPPORT_PCI) */ - { - "np2kai_usecdecc", - "Use CD-ROM EDC/ECC Emulation", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "ON" - }, - { - "np2kai_inputmouse", - "Use mouse or touchpanel to input mouse", - "", - { - {"OFF", NULL}, - {"ON", NULL}, - {NULL, NULL}, - }, - "ON" - }, - { - "np2kai_stick2mouse", - "S2M(Joypad Analog Stick to Mouse) Mapping", - "Emulate a mouse on your gamepad's analog stick.", - { - {"OFF", NULL}, - {"L-stick", NULL}, - {"R-stick", NULL}, - {NULL, NULL}, - }, - "R-stick" - }, - { - "np2kai_stick2mouse_shift", - "S2M Click Shift Button Mapping", - "Stick push shift to left->right click.", - { - {"OFF", NULL}, - {"L1", NULL}, - {"L2", NULL}, - {"R1", NULL}, - {"R2", NULL}, - {NULL, NULL}, - }, - "R1" - }, - { - "np2kai_joymode", - "Joypad D-pad to Mouse/Keyboard/Joypad Mapping", - "Emulate a keyboard/mouse/joypad on your gamepad. Map keyboard 'Arrows' or 'Keypad' on the D-pad.", - { - {"OFF", NULL}, - {"Mouse", NULL}, - {"Arrows", NULL}, - {"Arrows 3button", NULL}, - {"Keypad", NULL}, - {"Keypad 3button", NULL}, - {"Manual Keyboard", NULL}, - {"Atari Joypad", NULL}, - {"Keypad Fighting", NULL}, - {NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_joynp2menu", - "Joypad to NP2 menu Mapping", - "Select a gamepad button to open NP2 Menu.", - { - {"OFF", NULL}, - {"L1", NULL}, - {"L2", NULL}, - {"L3", NULL}, - {"R1", NULL}, - {"R2", NULL}, - {"R3", NULL}, - {"A", NULL}, - {"B", NULL}, - {"X", NULL}, - {"Y", NULL}, - {"Start", NULL}, - {"Select", NULL}, - {NULL, NULL}, - }, - "L2" - }, - {NULL, NULL, NULL, {{0}}, NULL}, -}; - -/* RETRO_LANGUAGE_JAPANESE */ - -struct retro_core_option_definition option_defs_ja[] = { - { - "np2kai_drive", - "ディスク入れ替えドライブ", - NULL, - { - { "FDD1", NULL }, - { "FDD2", NULL }, - { NULL, NULL}, - }, - "FDD2" - }, - { - "np2kai_keyrepeat", - "キーリピート", - "キーを押し続けると、リピート入力します。", - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_keyrepeat_delay", - "キーリピート 開始遅延", - "キーリピート開始するまでの遅延時間。", - { - { "250ms", NULL }, - { "500ms", NULL }, - { "1000ms", NULL }, - { NULL, NULL}, - }, - "500ms" - }, - { - "np2kai_keyrepeat_interval", - "キーリピート 間隔", - "キーリピートの入力間隔。", - { - { "25ms", NULL }, - { "50ms", NULL }, - { "100ms", NULL }, - { NULL, NULL}, - }, - "50ms" - }, - { - "np2kai_keyboard", - "キーボード形式 (要リスタート)", - "日本語106、もしくは英語101", - { - { "Ja", NULL }, - { "Us", NULL }, - { NULL, NULL}, - }, - "Ja" - }, - { - "np2kai_model", - "基本アーキテクチャ (要リスタート)", - NULL, - { - - { "PC-286", NULL }, - { "PC-9801VM", NULL }, - { "PC-9801VX", NULL }, - { NULL, NULL}, - }, - "PC-9801VX" - }, - { - "np2kai_clk_base", - "CPUベースクロック (要リスタート)", - NULL, - { - { "1.9968 MHz", NULL }, - { "2.4576 MHz", NULL }, - { NULL, NULL}, - }, - "2.4576 MHz" - }, - { - "np2kai_cpu_feature", - "CPU仕様 (要リスタート)", - NULL, - { - { "(custom)", NULL }, - { "Intel 80386", NULL }, - { "Intel i486SX", NULL }, - { "Intel i486DX", NULL }, - { "Intel Pentium", NULL }, - { "Intel MMX Pentium", NULL }, - { "Intel Pentium Pro", NULL }, - { "Intel Pentium II", NULL }, - { "Intel Pentium III", NULL }, - { "Intel Pentium M", NULL }, - { "Intel Pentium 4", NULL }, - { "AMD K6-2", NULL }, - { "AMD K6-III", NULL }, - { "AMD K7 Athlon", NULL }, - { "AMD K7 Athlon XP", NULL }, - { "Neko Processor II", NULL }, - { NULL, NULL}, - }, - "Intel 80386" - }, - { - "np2kai_clk_mult", - "CPUクロック倍率 (要リスタート)", - "動作が遅い場合は値を増やしてください。ゲームによってはオーバースピードになる可能性があります。", - { - { "2", NULL }, - { "4", NULL }, - { "5", NULL }, - { "6", NULL }, - { "8", NULL }, - { "10", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "30", NULL }, - { "36", NULL }, - { "40", NULL }, - { "42", NULL }, - { "52", NULL }, - { "64", NULL }, - { "76", NULL }, - { "88", NULL }, - { "100", NULL }, - { NULL, NULL}, - }, - "4" - }, -#if defined(SUPPORT_ASYNC_CPU) - { - "np2kai_async_cpu", - "非同期CPU(experimental) (要リスタート)", - "動機を待たずにCPUを先行処理させます。(プチフリする)", - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, -#endif - { - "np2kai_ExMemory", - "メモリサイズ (要リスタート)", - "大きなシステムには大きなメモリが必要ですが、ステートセーブのサイズが大きくなります。", - { - { "1", NULL }, - { "3", NULL }, - { "7", NULL }, - { "11", NULL }, - { "13", NULL }, -#if defined(CPUCORE_IA32) - { "16", NULL }, - { "32", NULL }, - { "64", NULL }, - { "120", NULL }, - { "230", NULL }, - { "512", NULL }, - { "1024", NULL }, -#endif - { NULL, NULL}, - }, - "3" - }, - { - "np2kai_FastMC", - "高速メモリチェック", - "スタートアップ時のメモリチェックを素早くします。", - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_uselasthddmount", - "前回のHDDマウントを使用", - "前回のHDDをコア開始時にマウントします。", - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, -#if defined(SUPPORT_VIDEOFILTER) - { - "np2kai_vf1", - "ビデオフィルタ", - "ビデオフィルタを設定します。(内容はcfgファイルにて設定。)", - { - { "OFF", NULL }, - { "Profile 0", NULL }, - { "Profile 1", NULL }, - { "Profile 2", NULL }, - { NULL, NULL}, - }, - "OFF" - }, -#endif - { - "np2kai_gdc", - "GDCタイプ", - "Graphic Display Controller。", - { - { "uPD7220", NULL }, - { "uPD72020", NULL }, - { NULL, NULL}, - }, - "uPD7220" - }, - { - "np2kai_skipline", - "Skipline Revisions", - "'Off' will show black scanlines in older games.", - { - { "Full 255 lines", NULL }, - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "Full 255 lines" - }, - { - "np2kai_realpal", - "擬似多色パレット", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_lcd", - "(古いモノクロ)液晶ディスプレイ", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_SNDboard", - "サウンドボード (要リスタート)", - NULL, - { - { "PC9801-14", NULL }, - { "PC9801-86", NULL }, - { "PC9801-86 + 118(B460)", NULL }, - { "PC9801-86 + Mate-X PCM(B460)", NULL }, - { "PC9801-86 + Chibi-oto", NULL }, - { "PC9801-86 + Speak Board", NULL }, - { "PC9801-26K", NULL }, - { "PC9801-26K + 86", NULL }, - { "PC9801-118", NULL }, - { "Mate-X PCM", NULL }, - { "Chibi-oto", NULL }, - { "Speak Board", NULL }, - { "Spark Board", NULL }, - { "Sound Orchestra", NULL }, - { "Sound Orchestra-V", NULL }, - { "Little Orchestra L", NULL }, - { "Multimedia Orchestra", NULL }, -#if defined(SUPPORT_SOUND_SB16) - { "Sound Blaster 16", NULL }, - { "PC9801-86 + Sound Blaster 16", NULL }, - { "Mate-X PCM + Sound Blaster 16", NULL }, - { "PC9801-118 + Sound Blaster 16", NULL }, - { "PC9801-86 + Mate-X PCM(B460) + Sound Blaster 16", NULL }, - { "PC9801-86 + 118(B460) + Sound Blaster 16", NULL }, -#endif - { "AMD-98", NULL }, - { "WaveStar", NULL }, -#if defined(SUPPORT_PX) - { "Otomi-chanx2", NULL }, - { "Otomi-chanx2 + 86", NULL }, -#endif - { "None", NULL }, - { NULL, NULL}, - }, - "PC9801-86" - }, - { - "np2kai_118ROM", - "118用サウンドROM", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "ON" - }, - { - "np2kai_jast_snd", - "JastSound", - "Enable Jast Sound PCM device.", - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_xroll", - "PageUp/PageDownキーを入れ替え", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "ON" - }, - { - "np2kai_usefmgen", - "音源ジェネレータ (要リスタート)", - "Defaultは猫OPNA、fmgenはより正確な音質になります。", - { - { "Default", NULL }, - { "fmgen", NULL }, - { NULL, NULL}, - }, - "fmgen" - }, - { - "np2kai_volume_M", - "ボリューム: マスター", - NULL, - { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL}, - }, - "100" - }, - { - "np2kai_volume_F", - "ボリューム: FM", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "64" - }, - { - "np2kai_volume_S", - "ボリューム: SSG", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "28" - }, - { - "np2kai_volume_A", - "ボリューム: ADPCM", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "64" - }, - { - "np2kai_volume_P", - "ボリューム: PCM", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "90" - }, - { - "np2kai_volume_R", - "ボリューム: リズム音源", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "64" - }, - { - "np2kai_volume_C", - "ボリューム: CD-DA", - NULL, - { - { "0", NULL }, - { "8", NULL }, - { "16", NULL }, - { "24", NULL }, - { "32", NULL }, - { "40", NULL }, - { "48", NULL }, - { "56", NULL }, - { "64", NULL }, - { "72", NULL }, - { "80", NULL }, - { "88", NULL }, - { "96", NULL }, - { "104", NULL }, - { "112", NULL }, - { "120", NULL }, - { "128", NULL }, - { "136", NULL }, - { "144", NULL }, - { "154", NULL }, - { "160", NULL }, - { "168", NULL }, - { "196", NULL }, - { "184", NULL }, - { "192", NULL }, - { "200", NULL }, - { "208", NULL }, - { "216", NULL }, - { "224", NULL }, - { "232", NULL }, - { "240", NULL }, - { "248", NULL }, - { "255", NULL }, - { NULL, NULL}, - }, - "128" - }, - { - "np2kai_Seek_Snd", - "フロッピーシーク音", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_Seek_Vol", - "ボリューム: フロッピーシーク音", - NULL, - { - { "0", NULL }, - { "4", NULL }, - { "8", NULL }, - { "12", NULL }, - { "16", NULL }, - { "20", NULL }, - { "24", NULL }, - { "28", NULL }, - { "32", NULL }, - { "36", NULL }, - { "40", NULL }, - { "44", NULL }, - { "48", NULL }, - { "52", NULL }, - { "56", NULL }, - { "60", NULL }, - { "64", NULL }, - { "68", NULL }, - { "72", NULL }, - { "76", NULL }, - { "80", NULL }, - { "84", NULL }, - { "88", NULL }, - { "92", NULL }, - { "96", NULL }, - { "100", NULL }, - { "104", NULL }, - { "108", NULL }, - { "112", NULL }, - { "116", NULL }, - { "120", NULL }, - { "124", NULL }, - { "128", NULL }, - { NULL, NULL}, - }, - "" - }, - { - "np2kai_BEEP_vol", - "ボリューム: BEEP", - NULL, - { - { "0", NULL }, - { "1", NULL }, - { "2", NULL }, - { "3", NULL }, - { NULL, NULL}, - }, - "3" - }, -#if defined(SUPPORT_WAB) - { - "np2kai_CLGD_en", - "WAB有効 (要リスタート)", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_CLGD_type", - "WABタイプ", - NULL, - { - { "PC-9821Xe10,Xa7e,Xb10 built-in", NULL }, - { "PC-9821Bp,Bs,Be,Bf built-in", NULL }, - { "PC-9821Xe built-in", NULL }, - { "PC-9821Cb built-in", NULL }, - { "PC-9821Cf built-in", NULL }, - { "PC-9821Cb2 built-in", NULL }, - { "PC-9821Cx2 built-in", NULL }, - { "PC-9821 PCI CL-GD5446 built-in", NULL }, - { "MELCO WAB-S", NULL }, - { "MELCO WSN-A2F", NULL }, - { "MELCO WSN-A4F", NULL }, - { "I-O DATA GA-98NBI/C", NULL }, - { "I-O DATA GA-98NBII", NULL }, - { "I-O DATA GA-98NBIV", NULL }, - { "PC-9801-96(PC-9801B3-E02)", NULL }, - { "Auto Select(Xe10, GA-98NBI/C), PCI", NULL }, - { "Auto Select(Xe10, GA-98NBII), PCI", NULL }, - { "Auto Select(Xe10, GA-98NBIV), PCI", NULL }, - { "Auto Select(Xe10, WAB-S), PCI", NULL }, - { "Auto Select(Xe10, WSN-A2F), PCI", NULL }, - { "Auto Select(Xe10, WSN-A4F), PCI", NULL }, - { "Auto Select(Xe10, WAB-S)", NULL }, - { "Auto Select(Xe10, WSN-A2F)", NULL }, - { "Auto Select(Xe10, WSN-A4F)", NULL }, - { NULL, NULL}, - }, - "PC-9821Xe10,Xa7e,Xb10 built-in" - }, - { - "np2kai_CLGD_fc", - "WAB時のフェイクカーソル表示", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, -#endif /* defined(SUPPORT_WAB) */ -#if defined(SUPPORT_PEGC) - { - "np2kai_PEGC", - "PEGCプレーンモード", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "ON" - }, -#endif -#if defined(SUPPORT_PCI) - { - "np2kai_PCI_en", - "PCIバス有効 (要リスタート)", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_PCI_type", - "PCMCタイプ", - NULL, - { - { "Intel 82434LX", NULL }, - { "Intel 82441FX", NULL }, - { "VLSI Wildcat", NULL }, - { NULL, NULL}, - }, - "Intel 82434LX" - }, - { - "np2kai_PCI_bios32", - "BIOS32使用 (オススメしません)", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "OFF" - }, -#endif /* defined(SUPPORT_PCI) */ - { - "np2kai_usecdecc", - "CD-ROM EDC/ECCエミュレーション", - NULL, - { - { "OFF", NULL }, - { "ON", NULL }, - { NULL, NULL}, - }, - "ON" - }, - { - "np2kai_inputmouse", - "マウス操作用にマウスまたはタッチパッドを使用", - "", - { - {"OFF", NULL}, - {"ON", NULL}, - {NULL, NULL}, - }, - "ON" - }, - { - "np2kai_stick2mouse", - "S2M(ジョイパッド アナログスティック->マウス マッピング", - "ジョイパッドのアナログスティックをマウスに割り当てる。", - { - {"OFF", NULL}, - {"L-stick", NULL}, - {"R-stick", NULL}, - {NULL, NULL}, - }, - "R-stick" - }, - { - "np2kai_stick2mouse_shift", - "S2M クリックシフトボタン マッピング", - "スティック押し込みを左→右クリックにシフトするボタンを割り当てる。", - { - {"OFF", NULL}, - {"L1", NULL}, - {"L2", NULL}, - {"R1", NULL}, - {"R2", NULL}, - {NULL, NULL}, - }, - "R1" - }, - { - "np2kai_joymode", - "ジョイパッド デジタルボタン マッピング", - "ジョイパッドのデジタルボタンをキーボード/マウス/ジョイパッドの操作に割り当てる。", - { - {"OFF", NULL}, - {"Mouse", NULL}, - {"Arrows", NULL}, - {"Arrows 3button", NULL}, - {"Keypad", NULL}, - {"Keypad 3button", NULL}, - {"Manual Keyboard", NULL}, - {"Atari Joypad", NULL}, - {"Keypad Fighting", NULL}, - {NULL, NULL}, - }, - "OFF" - }, - { - "np2kai_joynp2menu", - "NP2メニュー表示ボタン設定", - NULL, - { - {"OFF", NULL}, - {"L1", NULL}, - {"L2", NULL}, - {"L3", NULL}, - {"R1", NULL}, - {"R2", NULL}, - {"R3", NULL}, - {"A", NULL}, - {"B", NULL}, - {"X", NULL}, - {"Y", NULL}, - {"Start", NULL}, - {"Select", NULL}, - {NULL, NULL}, - }, - "L2" - }, - {NULL, NULL, NULL, {{0}}, NULL}, -}; - -/* RETRO_LANGUAGE_FRENCH */ - -/* RETRO_LANGUAGE_SPANISH */ - -/* RETRO_LANGUAGE_GERMAN */ - -/* RETRO_LANGUAGE_ITALIAN */ - -/* RETRO_LANGUAGE_DUTCH */ - -/* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ - -/* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ - -/* RETRO_LANGUAGE_RUSSIAN */ - -/* RETRO_LANGUAGE_KOREAN */ - -/* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ - -/* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ - -/* RETRO_LANGUAGE_ESPERANTO */ - -/* RETRO_LANGUAGE_POLISH */ - -/* RETRO_LANGUAGE_VIETNAMESE */ - -/* RETRO_LANGUAGE_ARABIC */ - -/* RETRO_LANGUAGE_GREEK */ - -/* RETRO_LANGUAGE_TURKISH */ - -/* - ******************************** - * Language Mapping - ******************************** -*/ - -struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = { - option_defs_us, /* RETRO_LANGUAGE_ENGLISH */ - option_defs_ja, /* RETRO_LANGUAGE_JAPANESE */ - NULL, /* RETRO_LANGUAGE_FRENCH */ - NULL, /* RETRO_LANGUAGE_SPANISH */ - NULL, /* RETRO_LANGUAGE_GERMAN */ - NULL, /* RETRO_LANGUAGE_ITALIAN */ - NULL, /* RETRO_LANGUAGE_DUTCH */ - NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ - NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ - NULL, /* RETRO_LANGUAGE_RUSSIAN */ - NULL, /* RETRO_LANGUAGE_KOREAN */ - NULL, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ - NULL, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ - NULL, /* RETRO_LANGUAGE_ESPERANTO */ - NULL, /* RETRO_LANGUAGE_POLISH */ - NULL, /* RETRO_LANGUAGE_VIETNAMESE */ - NULL, /* RETRO_LANGUAGE_ARABIC */ - NULL, /* RETRO_LANGUAGE_GREEK */ - NULL, /* RETRO_LANGUAGE_TURKISH */ -}; - -/* - ******************************** - * Functions - ******************************** -*/ - -/* Handles configuration/setting of core options. - * Should only be called inside retro_set_environment(). - * > We place the function body in the header to avoid the - * necessity of adding more .c files (i.e. want this to - * be as painless as possible for core devs) - */ - -static INLINE void libretro_set_core_options(retro_environment_t environ_cb) -{ - unsigned version = 0; - - if (!environ_cb) - return; - - if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version == 1)) - { - struct retro_core_options_intl core_options_intl; - unsigned language = 0; - - core_options_intl.us = option_defs_us; - core_options_intl.local = NULL; - - if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) && - (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH)) - core_options_intl.local = option_defs_intl[language]; - - environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl); - } - else - { - size_t i; - size_t option_index = 0; - size_t num_options = 0; - struct retro_variable *variables = NULL; - char **values_buf = NULL; - - /* Determine number of options - * > Note: We are going to skip a number of irrelevant - * core options when building the retro_variable array, - * but we'll allocate space for all of them. The difference - * in resource usage is negligible, and this allows us to - * keep the code 'cleaner' */ - while (true) - { - if (option_defs_us[num_options].key) - num_options++; - else - break; - } - - /* Allocate arrays */ - variables = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable)); - values_buf = (char **)calloc(num_options, sizeof(char *)); - - if (!variables || !values_buf) - goto error; - - /* Copy parameters from option_defs_us array */ - for (i = 0; i < num_options; i++) - { - const char *key = option_defs_us[i].key; - const char *desc = option_defs_us[i].desc; - const char *default_value = option_defs_us[i].default_value; - struct retro_core_option_value *values = option_defs_us[i].values; - size_t buf_len = 3; - size_t default_index = 0; - - values_buf[i] = NULL; - - if (desc) - { - size_t num_values = 0; - - /* Determine number of values */ - while (true) - { - if (values[num_values].value) - { - /* Check if this is the default value */ - if (default_value) - if (strcmp(values[num_values].value, default_value) == 0) - default_index = num_values; - - buf_len += strlen(values[num_values].value); - num_values++; - } - else - break; - } - - /* Build values string */ - if (num_values > 1) - { - size_t j; - - buf_len += num_values - 1; - buf_len += strlen(desc); - - values_buf[i] = (char *)calloc(buf_len, sizeof(char)); - if (!values_buf[i]) - goto error; - - strcpy(values_buf[i], desc); - strcat(values_buf[i], "; "); - - /* Default value goes first */ - strcat(values_buf[i], values[default_index].value); - - /* Add remaining values */ - for (j = 0; j < num_values; j++) - { - if (j != default_index) - { - strcat(values_buf[i], "|"); - strcat(values_buf[i], values[j].value); - } - } - } - } - - variables[option_index].key = key; - variables[option_index].value = values_buf[i]; - option_index++; - } - - /* Set variables */ - environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); - -error: - - /* Clean up */ - if (values_buf) - { - for (i = 0; i < num_options; i++) - { - if (values_buf[i]) - { - free(values_buf[i]); - values_buf[i] = NULL; - } - } - - free(values_buf); - values_buf = NULL; - } - - if (variables) - { - free(variables); - variables = NULL; - } - } -} - -#ifdef __cplusplus -} -#endif - -#endif +#ifndef LIBRETRO_CORE_OPTIONS_H__ +#define LIBRETRO_CORE_OPTIONS_H__ + +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + ******************************** + * Core Option Definitions + ******************************** +*/ + +/* RETRO_LANGUAGE_ENGLISH */ + +/* Default language: + * - All other languages must include the same keys and values + * - Will be used as a fallback in the event that frontend language + * is not available + * - Will be used as a fallback for any missing entries in + * frontend language definition */ + +struct retro_core_option_definition option_defs_us[] = { + { + "np2kai_drive", + "Swap Disks on Drive", + NULL, + { + { "FDD1", NULL }, + { "FDD2", NULL }, + { NULL, NULL}, + }, + "FDD2" + }, + { + "np2kai_keyboard", + "Keyboard (Restart)", + "Japanese or US keyboard type.", + { + { "Ja", NULL }, + { "Us", NULL }, + { NULL, NULL}, + }, + "Ja" + }, + { + "np2kai_keyrepeat", + "Key-repeat", + "Continue press key, key-repeat.", + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_keyrepeat_delay", + "Key-repeat delay", + "Key-repeat start after delay.", + { + { "250ms", NULL }, + { "500ms", NULL }, + { "1000ms", NULL }, + { NULL, NULL}, + }, + "500ms" + }, + { + "np2kai_keyrepeat_interval", + "Key-repeat interval", + "Key-repeat interval.", + { + { "25ms", NULL }, + { "50ms", NULL }, + { "100ms", NULL }, + { NULL, NULL}, + }, + "50ms" + }, + { + "np2kai_model", + "PC Model (Restart)", + NULL, + { + + { "PC-286", NULL }, + { "PC-9801VM", NULL }, + { "PC-9801VX", NULL }, + { NULL, NULL}, + }, + "PC-9801VX" + }, + { + "np2kai_clk_base", + "CPU Base Clock (Restart)", + NULL, + { + { "1.9968 MHz", NULL }, + { "2.4576 MHz", NULL }, + { NULL, NULL}, + }, + "2.4576 MHz" + }, + { + "np2kai_cpu_feature", + "CPU Feature (Restart)", + NULL, + { + { "(custom)", NULL }, + { "Intel 80386", NULL }, + { "Intel i486SX", NULL }, + { "Intel i486DX", NULL }, + { "Intel Pentium", NULL }, + { "Intel MMX Pentium", NULL }, + { "Intel Pentium Pro", NULL }, + { "Intel Pentium II", NULL }, + { "Intel Pentium III", NULL }, + { "Intel Pentium M", NULL }, + { "Intel Pentium 4", NULL }, + { "AMD K6-2", NULL }, + { "AMD K6-III", NULL }, + { "AMD K7 Athlon", NULL }, + { "AMD K7 Athlon XP", NULL }, + { "Neko Processor II", NULL }, + { NULL, NULL}, + }, + "Intel 80386" + }, + { + "np2kai_clk_mult", + "CPU Clock Multiplier (Restart)", + "Higher values require a fast machine. Can make some games run too fast.", + { + { "2", NULL }, + { "4", NULL }, + { "5", NULL }, + { "6", NULL }, + { "8", NULL }, + { "10", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "30", NULL }, + { "36", NULL }, + { "40", NULL }, + { "42", NULL }, + { "52", NULL }, + { "64", NULL }, + { "76", NULL }, + { "88", NULL }, + { "100", NULL }, + { NULL, NULL}, + }, + "4" + }, +#if defined(SUPPORT_ASYNC_CPU) + { + "np2kai_async_cpu", + "Async CPU(experimental) (Restart)", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, +#endif + { + "np2kai_ExMemory", + "RAM Size (Restart)", + "Amount of memory the virtual machine can use. Save states size will grow accordingly.", + { + { "1", NULL }, + { "3", NULL }, + { "7", NULL }, + { "11", NULL }, + { "13", NULL }, +#if defined(CPUCORE_IA32) + { "16", NULL }, + { "32", NULL }, + { "64", NULL }, + { "120", NULL }, + { "230", NULL }, + { "512", NULL }, + { "1024", NULL }, +#endif + { NULL, NULL}, + }, + "3" + }, + { + "np2kai_FastMC", + "Fast memcheck", + "Do a faster memory checking at startup.", + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_uselasthddmount", + "Use last HDD mount", + "Last HDD mount at core start.", + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, +#if defined(SUPPORT_VIDEOFILTER) + { + "np2kai_vf1", + "Video filter", + "Video filter setting. (Setting details set in cfg file)", + { + { "OFF", NULL }, + { "Profile 0", NULL }, + { "Profile 1", NULL }, + { "Profile 2", NULL }, + { NULL, NULL}, + }, + "OFF" + }, +#endif + { + "np2kai_gdc", + "GDC", + "Graphic Display Controller model.", + { + { "uPD7220", NULL }, + { "uPD72020", NULL }, + { NULL, NULL}, + }, + "uPD7220" + }, + { + "np2kai_skipline", + "Skipline Revisions", + "'Off' will show black scanlines in older games.", + { + { "Full 255 lines", NULL }, + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "Full 255 lines" + }, + { + "np2kai_realpal", + "Real Palettes", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_lcd", + "LCD (old monochrome)", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_SNDboard", + "Sound Board (Restart)", + NULL, + { + { "PC9801-14", NULL }, + { "PC9801-86", NULL }, + { "PC9801-86 + 118(B460)", NULL }, + { "PC9801-86 + Mate-X PCM(B460)", NULL }, + { "PC9801-86 + Chibi-oto", NULL }, + { "PC9801-86 + Speak Board", NULL }, + { "PC9801-26K", NULL }, + { "PC9801-26K + 86", NULL }, + { "PC9801-118", NULL }, + { "Mate-X PCM", NULL }, + { "Chibi-oto", NULL }, + { "Speak Board", NULL }, + { "Spark Board", NULL }, + { "Sound Orchestra", NULL }, + { "Sound Orchestra-V", NULL }, + { "Little Orchestra L", NULL }, + { "Multimedia Orchestra", NULL }, +#if defined(SUPPORT_SOUND_SB16) + { "Sound Blaster 16", NULL }, + { "PC9801-86 + Sound Blaster 16", NULL }, + { "Mate-X PCM + Sound Blaster 16", NULL }, + { "PC9801-118 + Sound Blaster 16", NULL }, + { "PC9801-86 + Mate-X PCM(B460) + Sound Blaster 16", NULL }, + { "PC9801-86 + 118(B460) + Sound Blaster 16", NULL }, +#endif + { "AMD-98", NULL }, + { "WaveStar", NULL }, +#if defined(SUPPORT_PX) + { "Otomi-chanx2", NULL }, + { "Otomi-chanx2 + 86", NULL }, +#endif + { "None", NULL }, + { NULL, NULL}, + }, + "PC9801-86" + }, + { + "np2kai_118ROM", + "enable 118 ROM", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "ON" + }, + { + "np2kai_jast_snd", + "JastSound", + "Enable Jast Sound PCM device.", + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_xroll", + "Swap PageUp/PageDown", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "ON" + }, + { + "np2kai_usefmgen", + "Sound Generator", + "Use 'fmgen' for enhanced sound rendering.", + { + { "Default", NULL }, + { "fmgen", NULL }, + { NULL, NULL}, + }, + "fmgen" + }, + { + "np2kai_volume_M", + "Volume Master", + NULL, + { + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL}, + }, + "100" + }, + { + "np2kai_volume_F", + "Volume FM", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "64" + }, + { + "np2kai_volume_S", + "Volume SSG", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "28" + }, + { + "np2kai_volume_A", + "Volume ADPCM", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "64" + }, + { + "np2kai_volume_P", + "Volume PCM", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "92" + }, + { + "np2kai_volume_R", + "Volume RHYTHM", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "64" + }, + { + "np2kai_volume_C", + "Volume CD-DA", + NULL, + { + { "0", NULL }, + { "8", NULL }, + { "16", NULL }, + { "24", NULL }, + { "32", NULL }, + { "40", NULL }, + { "48", NULL }, + { "56", NULL }, + { "64", NULL }, + { "72", NULL }, + { "80", NULL }, + { "88", NULL }, + { "96", NULL }, + { "104", NULL }, + { "112", NULL }, + { "120", NULL }, + { "128", NULL }, + { "136", NULL }, + { "144", NULL }, + { "154", NULL }, + { "160", NULL }, + { "168", NULL }, + { "196", NULL }, + { "184", NULL }, + { "192", NULL }, + { "200", NULL }, + { "208", NULL }, + { "216", NULL }, + { "224", NULL }, + { "232", NULL }, + { "240", NULL }, + { "248", NULL }, + { "255", NULL }, + { NULL, NULL}, + }, + "128" + }, + { + "np2kai_Seek_Snd", + "Floppy Seek Sound", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_Seek_Vol", + "Volume Floppy Seek", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "" + }, + { + "np2kai_BEEP_vol", + "Volume Beep", + NULL, + { + { "0", NULL }, + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { NULL, NULL}, + }, + "3" + }, +#if defined(SUPPORT_WAB) + { + "np2kai_CLGD_en", + "Enable WAB (Restart App)", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_CLGD_type", + "WAB Type", + NULL, + { + { "PC-9821Xe10,Xa7e,Xb10 built-in", NULL }, + { "PC-9821Bp,Bs,Be,Bf built-in", NULL }, + { "PC-9821Xe built-in", NULL }, + { "PC-9821Cb built-in", NULL }, + { "PC-9821Cf built-in", NULL }, + { "PC-9821Cb2 built-in", NULL }, + { "PC-9821Cx2 built-in", NULL }, + { "PC-9821 PCI CL-GD5446 built-in", NULL }, + { "MELCO WAB-S", NULL }, + { "MELCO WSN-A2F", NULL }, + { "MELCO WSN-A4F", NULL }, + { "I-O DATA GA-98NBI/C", NULL }, + { "I-O DATA GA-98NBII", NULL }, + { "I-O DATA GA-98NBIV", NULL }, + { "PC-9801-96(PC-9801B3-E02)", NULL }, + { "Auto Select(Xe10, GA-98NBI/C), PCI", NULL }, + { "Auto Select(Xe10, GA-98NBII), PCI", NULL }, + { "Auto Select(Xe10, GA-98NBIV), PCI", NULL }, + { "Auto Select(Xe10, WAB-S), PCI", NULL }, + { "Auto Select(Xe10, WSN-A2F), PCI", NULL }, + { "Auto Select(Xe10, WSN-A4F), PCI", NULL }, + { "Auto Select(Xe10, WAB-S)", NULL }, + { "Auto Select(Xe10, WSN-A2F)", NULL }, + { "Auto Select(Xe10, WSN-A4F)", NULL }, + { NULL, NULL}, + }, + "PC-9821Xe10,Xa7e,Xb10 built-in" + }, + { + "np2kai_CLGD_fc", + "Use Fake Hardware Cursor", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, +#endif /* defined(SUPPORT_WAB) */ +#if defined(SUPPORT_PEGC) + { + "np2kai_PEGC", + "Enable PEGC plane mode", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "ON" + }, +#endif +#if defined(SUPPORT_PCI) + { + "np2kai_PCI_en", + "Enable PCI (Restart App)", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_PCI_type", + "PCMC Type", + NULL, + { + { "Intel 82434LX", NULL }, + { "Intel 82441FX", NULL }, + { "VLSI Wildcat", NULL }, + { NULL, NULL}, + }, + "Intel 82434LX" + }, + { + "np2kai_PCI_bios32", + "Use BIOS32 (not recommended)", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, +#endif /* defined(SUPPORT_PCI) */ + { + "np2kai_usecdecc", + "Use CD-ROM EDC/ECC Emulation", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "ON" + }, + { + "np2kai_inputmouse", + "Use mouse or touchpanel to input mouse", + "", + { + {"OFF", NULL}, + {"ON", NULL}, + {NULL, NULL}, + }, + "ON" + }, + { + "np2kai_stick2mouse", + "S2M(Joypad Analog Stick to Mouse) Mapping", + "Emulate a mouse on your gamepad's analog stick.", + { + {"OFF", NULL}, + {"L-stick", NULL}, + {"R-stick", NULL}, + {NULL, NULL}, + }, + "R-stick" + }, + { + "np2kai_stick2mouse_shift", + "S2M Click Shift Button Mapping", + "Stick push shift to left->right click.", + { + {"OFF", NULL}, + {"L1", NULL}, + {"L2", NULL}, + {"R1", NULL}, + {"R2", NULL}, + {NULL, NULL}, + }, + "R1" + }, + { + "np2kai_joymode", + "Joypad D-pad to Mouse/Keyboard/Joypad Mapping", + "Emulate a keyboard/mouse/joypad on your gamepad. Map keyboard 'Arrows' or 'Keypad' on the D-pad.", + { + {"OFF", NULL}, + {"Mouse", NULL}, + {"Arrows", NULL}, + {"Arrows 3button", NULL}, + {"Keypad", NULL}, + {"Keypad 3button", NULL}, + {"Manual Keyboard", NULL}, + {"Atari Joypad", NULL}, + {"Keypad Fighting", NULL}, + {NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_joynp2menu", + "Joypad to NP2 menu Mapping", + "Select a gamepad button to open NP2 Menu.", + { + {"OFF", NULL}, + {"L1", NULL}, + {"L2", NULL}, + {"L3", NULL}, + {"R1", NULL}, + {"R2", NULL}, + {"R3", NULL}, + {"A", NULL}, + {"B", NULL}, + {"X", NULL}, + {"Y", NULL}, + {"Start", NULL}, + {"Select", NULL}, + {NULL, NULL}, + }, + "L2" + }, + {NULL, NULL, NULL, {{0}}, NULL}, +}; + +/* RETRO_LANGUAGE_JAPANESE */ + +struct retro_core_option_definition option_defs_ja[] = { + { + "np2kai_drive", + "ディスク入れ替えドライブ", + NULL, + { + { "FDD1", NULL }, + { "FDD2", NULL }, + { NULL, NULL}, + }, + "FDD2" + }, + { + "np2kai_keyrepeat", + "キーリピート", + "キーを押し続けると、リピート入力します。", + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_keyrepeat_delay", + "キーリピート 開始遅延", + "キーリピート開始するまでの遅延時間。", + { + { "250ms", NULL }, + { "500ms", NULL }, + { "1000ms", NULL }, + { NULL, NULL}, + }, + "500ms" + }, + { + "np2kai_keyrepeat_interval", + "キーリピート 間隔", + "キーリピートの入力間隔。", + { + { "25ms", NULL }, + { "50ms", NULL }, + { "100ms", NULL }, + { NULL, NULL}, + }, + "50ms" + }, + { + "np2kai_keyboard", + "キーボード形式 (要リスタート)", + "日本語106、もしくは英語101", + { + { "Ja", NULL }, + { "Us", NULL }, + { NULL, NULL}, + }, + "Ja" + }, + { + "np2kai_model", + "基本アーキテクチャ (要リスタート)", + NULL, + { + + { "PC-286", NULL }, + { "PC-9801VM", NULL }, + { "PC-9801VX", NULL }, + { NULL, NULL}, + }, + "PC-9801VX" + }, + { + "np2kai_clk_base", + "CPUベースクロック (要リスタート)", + NULL, + { + { "1.9968 MHz", NULL }, + { "2.4576 MHz", NULL }, + { NULL, NULL}, + }, + "2.4576 MHz" + }, + { + "np2kai_cpu_feature", + "CPU仕様 (要リスタート)", + NULL, + { + { "(custom)", NULL }, + { "Intel 80386", NULL }, + { "Intel i486SX", NULL }, + { "Intel i486DX", NULL }, + { "Intel Pentium", NULL }, + { "Intel MMX Pentium", NULL }, + { "Intel Pentium Pro", NULL }, + { "Intel Pentium II", NULL }, + { "Intel Pentium III", NULL }, + { "Intel Pentium M", NULL }, + { "Intel Pentium 4", NULL }, + { "AMD K6-2", NULL }, + { "AMD K6-III", NULL }, + { "AMD K7 Athlon", NULL }, + { "AMD K7 Athlon XP", NULL }, + { "Neko Processor II", NULL }, + { NULL, NULL}, + }, + "Intel 80386" + }, + { + "np2kai_clk_mult", + "CPUクロック倍率 (要リスタート)", + "動作が遅い場合は値を増やしてください。ゲームによってはオーバースピードになる可能性があります。", + { + { "2", NULL }, + { "4", NULL }, + { "5", NULL }, + { "6", NULL }, + { "8", NULL }, + { "10", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "30", NULL }, + { "36", NULL }, + { "40", NULL }, + { "42", NULL }, + { "52", NULL }, + { "64", NULL }, + { "76", NULL }, + { "88", NULL }, + { "100", NULL }, + { NULL, NULL}, + }, + "4" + }, +#if defined(SUPPORT_ASYNC_CPU) + { + "np2kai_async_cpu", + "非同期CPU(experimental) (要リスタート)", + "動機を待たずにCPUを先行処理させます。(プチフリする)", + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, +#endif + { + "np2kai_ExMemory", + "メモリサイズ (要リスタート)", + "大きなシステムには大きなメモリが必要ですが、ステートセーブのサイズが大きくなります。", + { + { "1", NULL }, + { "3", NULL }, + { "7", NULL }, + { "11", NULL }, + { "13", NULL }, +#if defined(CPUCORE_IA32) + { "16", NULL }, + { "32", NULL }, + { "64", NULL }, + { "120", NULL }, + { "230", NULL }, + { "512", NULL }, + { "1024", NULL }, +#endif + { NULL, NULL}, + }, + "3" + }, + { + "np2kai_FastMC", + "高速メモリチェック", + "スタートアップ時のメモリチェックを素早くします。", + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_uselasthddmount", + "前回のHDDマウントを使用", + "前回のHDDをコア開始時にマウントします。", + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, +#if defined(SUPPORT_VIDEOFILTER) + { + "np2kai_vf1", + "ビデオフィルタ", + "ビデオフィルタを設定します。(内容はcfgファイルにて設定。)", + { + { "OFF", NULL }, + { "Profile 0", NULL }, + { "Profile 1", NULL }, + { "Profile 2", NULL }, + { NULL, NULL}, + }, + "OFF" + }, +#endif + { + "np2kai_gdc", + "GDCタイプ", + "Graphic Display Controller。", + { + { "uPD7220", NULL }, + { "uPD72020", NULL }, + { NULL, NULL}, + }, + "uPD7220" + }, + { + "np2kai_skipline", + "Skipline Revisions", + "'Off' will show black scanlines in older games.", + { + { "Full 255 lines", NULL }, + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "Full 255 lines" + }, + { + "np2kai_realpal", + "擬似多色パレット", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_lcd", + "(古いモノクロ)液晶ディスプレイ", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_SNDboard", + "サウンドボード (要リスタート)", + NULL, + { + { "PC9801-14", NULL }, + { "PC9801-86", NULL }, + { "PC9801-86 + 118(B460)", NULL }, + { "PC9801-86 + Mate-X PCM(B460)", NULL }, + { "PC9801-86 + Chibi-oto", NULL }, + { "PC9801-86 + Speak Board", NULL }, + { "PC9801-26K", NULL }, + { "PC9801-26K + 86", NULL }, + { "PC9801-118", NULL }, + { "Mate-X PCM", NULL }, + { "Chibi-oto", NULL }, + { "Speak Board", NULL }, + { "Spark Board", NULL }, + { "Sound Orchestra", NULL }, + { "Sound Orchestra-V", NULL }, + { "Little Orchestra L", NULL }, + { "Multimedia Orchestra", NULL }, +#if defined(SUPPORT_SOUND_SB16) + { "Sound Blaster 16", NULL }, + { "PC9801-86 + Sound Blaster 16", NULL }, + { "Mate-X PCM + Sound Blaster 16", NULL }, + { "PC9801-118 + Sound Blaster 16", NULL }, + { "PC9801-86 + Mate-X PCM(B460) + Sound Blaster 16", NULL }, + { "PC9801-86 + 118(B460) + Sound Blaster 16", NULL }, +#endif + { "AMD-98", NULL }, + { "WaveStar", NULL }, +#if defined(SUPPORT_PX) + { "Otomi-chanx2", NULL }, + { "Otomi-chanx2 + 86", NULL }, +#endif + { "None", NULL }, + { NULL, NULL}, + }, + "PC9801-86" + }, + { + "np2kai_118ROM", + "118用サウンドROM", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "ON" + }, + { + "np2kai_jast_snd", + "JastSound", + "Enable Jast Sound PCM device.", + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_xroll", + "PageUp/PageDownキーを入れ替え", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "ON" + }, + { + "np2kai_usefmgen", + "音源ジェネレータ (要リスタート)", + "Defaultは猫OPNA、fmgenはより正確な音質になります。", + { + { "Default", NULL }, + { "fmgen", NULL }, + { NULL, NULL}, + }, + "fmgen" + }, + { + "np2kai_volume_M", + "ボリューム: マスター", + NULL, + { + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL}, + }, + "100" + }, + { + "np2kai_volume_F", + "ボリューム: FM", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "64" + }, + { + "np2kai_volume_S", + "ボリューム: SSG", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "28" + }, + { + "np2kai_volume_A", + "ボリューム: ADPCM", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "64" + }, + { + "np2kai_volume_P", + "ボリューム: PCM", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "90" + }, + { + "np2kai_volume_R", + "ボリューム: リズム音源", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "64" + }, + { + "np2kai_volume_C", + "ボリューム: CD-DA", + NULL, + { + { "0", NULL }, + { "8", NULL }, + { "16", NULL }, + { "24", NULL }, + { "32", NULL }, + { "40", NULL }, + { "48", NULL }, + { "56", NULL }, + { "64", NULL }, + { "72", NULL }, + { "80", NULL }, + { "88", NULL }, + { "96", NULL }, + { "104", NULL }, + { "112", NULL }, + { "120", NULL }, + { "128", NULL }, + { "136", NULL }, + { "144", NULL }, + { "154", NULL }, + { "160", NULL }, + { "168", NULL }, + { "196", NULL }, + { "184", NULL }, + { "192", NULL }, + { "200", NULL }, + { "208", NULL }, + { "216", NULL }, + { "224", NULL }, + { "232", NULL }, + { "240", NULL }, + { "248", NULL }, + { "255", NULL }, + { NULL, NULL}, + }, + "128" + }, + { + "np2kai_Seek_Snd", + "フロッピーシーク音", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_Seek_Vol", + "ボリューム: フロッピーシーク音", + NULL, + { + { "0", NULL }, + { "4", NULL }, + { "8", NULL }, + { "12", NULL }, + { "16", NULL }, + { "20", NULL }, + { "24", NULL }, + { "28", NULL }, + { "32", NULL }, + { "36", NULL }, + { "40", NULL }, + { "44", NULL }, + { "48", NULL }, + { "52", NULL }, + { "56", NULL }, + { "60", NULL }, + { "64", NULL }, + { "68", NULL }, + { "72", NULL }, + { "76", NULL }, + { "80", NULL }, + { "84", NULL }, + { "88", NULL }, + { "92", NULL }, + { "96", NULL }, + { "100", NULL }, + { "104", NULL }, + { "108", NULL }, + { "112", NULL }, + { "116", NULL }, + { "120", NULL }, + { "124", NULL }, + { "128", NULL }, + { NULL, NULL}, + }, + "" + }, + { + "np2kai_BEEP_vol", + "ボリューム: BEEP", + NULL, + { + { "0", NULL }, + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { NULL, NULL}, + }, + "3" + }, +#if defined(SUPPORT_WAB) + { + "np2kai_CLGD_en", + "WAB有効 (要リスタート)", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_CLGD_type", + "WABタイプ", + NULL, + { + { "PC-9821Xe10,Xa7e,Xb10 built-in", NULL }, + { "PC-9821Bp,Bs,Be,Bf built-in", NULL }, + { "PC-9821Xe built-in", NULL }, + { "PC-9821Cb built-in", NULL }, + { "PC-9821Cf built-in", NULL }, + { "PC-9821Cb2 built-in", NULL }, + { "PC-9821Cx2 built-in", NULL }, + { "PC-9821 PCI CL-GD5446 built-in", NULL }, + { "MELCO WAB-S", NULL }, + { "MELCO WSN-A2F", NULL }, + { "MELCO WSN-A4F", NULL }, + { "I-O DATA GA-98NBI/C", NULL }, + { "I-O DATA GA-98NBII", NULL }, + { "I-O DATA GA-98NBIV", NULL }, + { "PC-9801-96(PC-9801B3-E02)", NULL }, + { "Auto Select(Xe10, GA-98NBI/C), PCI", NULL }, + { "Auto Select(Xe10, GA-98NBII), PCI", NULL }, + { "Auto Select(Xe10, GA-98NBIV), PCI", NULL }, + { "Auto Select(Xe10, WAB-S), PCI", NULL }, + { "Auto Select(Xe10, WSN-A2F), PCI", NULL }, + { "Auto Select(Xe10, WSN-A4F), PCI", NULL }, + { "Auto Select(Xe10, WAB-S)", NULL }, + { "Auto Select(Xe10, WSN-A2F)", NULL }, + { "Auto Select(Xe10, WSN-A4F)", NULL }, + { NULL, NULL}, + }, + "PC-9821Xe10,Xa7e,Xb10 built-in" + }, + { + "np2kai_CLGD_fc", + "WAB時のフェイクカーソル表示", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, +#endif /* defined(SUPPORT_WAB) */ +#if defined(SUPPORT_PEGC) + { + "np2kai_PEGC", + "PEGCプレーンモード", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "ON" + }, +#endif +#if defined(SUPPORT_PCI) + { + "np2kai_PCI_en", + "PCIバス有効 (要リスタート)", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_PCI_type", + "PCMCタイプ", + NULL, + { + { "Intel 82434LX", NULL }, + { "Intel 82441FX", NULL }, + { "VLSI Wildcat", NULL }, + { NULL, NULL}, + }, + "Intel 82434LX" + }, + { + "np2kai_PCI_bios32", + "BIOS32使用 (オススメしません)", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "OFF" + }, +#endif /* defined(SUPPORT_PCI) */ + { + "np2kai_usecdecc", + "CD-ROM EDC/ECCエミュレーション", + NULL, + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL}, + }, + "ON" + }, + { + "np2kai_inputmouse", + "マウス操作用にマウスまたはタッチパッドを使用", + "", + { + {"OFF", NULL}, + {"ON", NULL}, + {NULL, NULL}, + }, + "ON" + }, + { + "np2kai_stick2mouse", + "S2M(ジョイパッド アナログスティック->マウス マッピング", + "ジョイパッドのアナログスティックをマウスに割り当てる。", + { + {"OFF", NULL}, + {"L-stick", NULL}, + {"R-stick", NULL}, + {NULL, NULL}, + }, + "R-stick" + }, + { + "np2kai_stick2mouse_shift", + "S2M クリックシフトボタン マッピング", + "スティック押し込みを左→右クリックにシフトするボタンを割り当てる。", + { + {"OFF", NULL}, + {"L1", NULL}, + {"L2", NULL}, + {"R1", NULL}, + {"R2", NULL}, + {NULL, NULL}, + }, + "R1" + }, + { + "np2kai_joymode", + "ジョイパッド デジタルボタン マッピング", + "ジョイパッドのデジタルボタンをキーボード/マウス/ジョイパッドの操作に割り当てる。", + { + {"OFF", NULL}, + {"Mouse", NULL}, + {"Arrows", NULL}, + {"Arrows 3button", NULL}, + {"Keypad", NULL}, + {"Keypad 3button", NULL}, + {"Manual Keyboard", NULL}, + {"Atari Joypad", NULL}, + {"Keypad Fighting", NULL}, + {NULL, NULL}, + }, + "OFF" + }, + { + "np2kai_joynp2menu", + "NP2メニュー表示ボタン設定", + NULL, + { + {"OFF", NULL}, + {"L1", NULL}, + {"L2", NULL}, + {"L3", NULL}, + {"R1", NULL}, + {"R2", NULL}, + {"R3", NULL}, + {"A", NULL}, + {"B", NULL}, + {"X", NULL}, + {"Y", NULL}, + {"Start", NULL}, + {"Select", NULL}, + {NULL, NULL}, + }, + "L2" + }, + {NULL, NULL, NULL, {{0}}, NULL}, +}; + +/* RETRO_LANGUAGE_FRENCH */ + +/* RETRO_LANGUAGE_SPANISH */ + +/* RETRO_LANGUAGE_GERMAN */ + +/* RETRO_LANGUAGE_ITALIAN */ + +/* RETRO_LANGUAGE_DUTCH */ + +/* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ + +/* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ + +/* RETRO_LANGUAGE_RUSSIAN */ + +/* RETRO_LANGUAGE_KOREAN */ + +/* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ + +/* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ + +/* RETRO_LANGUAGE_ESPERANTO */ + +/* RETRO_LANGUAGE_POLISH */ + +/* RETRO_LANGUAGE_VIETNAMESE */ + +/* RETRO_LANGUAGE_ARABIC */ + +/* RETRO_LANGUAGE_GREEK */ + +/* RETRO_LANGUAGE_TURKISH */ + +/* + ******************************** + * Language Mapping + ******************************** +*/ + +struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = { + option_defs_us, /* RETRO_LANGUAGE_ENGLISH */ + option_defs_ja, /* RETRO_LANGUAGE_JAPANESE */ + NULL, /* RETRO_LANGUAGE_FRENCH */ + NULL, /* RETRO_LANGUAGE_SPANISH */ + NULL, /* RETRO_LANGUAGE_GERMAN */ + NULL, /* RETRO_LANGUAGE_ITALIAN */ + NULL, /* RETRO_LANGUAGE_DUTCH */ + NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ + NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ + NULL, /* RETRO_LANGUAGE_RUSSIAN */ + NULL, /* RETRO_LANGUAGE_KOREAN */ + NULL, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ + NULL, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ + NULL, /* RETRO_LANGUAGE_ESPERANTO */ + NULL, /* RETRO_LANGUAGE_POLISH */ + NULL, /* RETRO_LANGUAGE_VIETNAMESE */ + NULL, /* RETRO_LANGUAGE_ARABIC */ + NULL, /* RETRO_LANGUAGE_GREEK */ + NULL, /* RETRO_LANGUAGE_TURKISH */ +}; + +/* + ******************************** + * Functions + ******************************** +*/ + +/* Handles configuration/setting of core options. + * Should only be called inside retro_set_environment(). + * > We place the function body in the header to avoid the + * necessity of adding more .c files (i.e. want this to + * be as painless as possible for core devs) + */ + +static INLINE void libretro_set_core_options(retro_environment_t environ_cb) +{ + unsigned version = 0; + + if (!environ_cb) + return; + + if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version == 1)) + { + struct retro_core_options_intl core_options_intl; + unsigned language = 0; + + core_options_intl.us = option_defs_us; + core_options_intl.local = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) && + (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH)) + core_options_intl.local = option_defs_intl[language]; + + environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl); + } + else + { + size_t i; + size_t option_index = 0; + size_t num_options = 0; + struct retro_variable *variables = NULL; + char **values_buf = NULL; + + /* Determine number of options + * > Note: We are going to skip a number of irrelevant + * core options when building the retro_variable array, + * but we'll allocate space for all of them. The difference + * in resource usage is negligible, and this allows us to + * keep the code 'cleaner' */ + while (true) + { + if (option_defs_us[num_options].key) + num_options++; + else + break; + } + + /* Allocate arrays */ + variables = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable)); + values_buf = (char **)calloc(num_options, sizeof(char *)); + + if (!variables || !values_buf) + goto error; + + /* Copy parameters from option_defs_us array */ + for (i = 0; i < num_options; i++) + { + const char *key = option_defs_us[i].key; + const char *desc = option_defs_us[i].desc; + const char *default_value = option_defs_us[i].default_value; + struct retro_core_option_value *values = option_defs_us[i].values; + size_t buf_len = 3; + size_t default_index = 0; + + values_buf[i] = NULL; + + if (desc) + { + size_t num_values = 0; + + /* Determine number of values */ + while (true) + { + if (values[num_values].value) + { + /* Check if this is the default value */ + if (default_value) + if (strcmp(values[num_values].value, default_value) == 0) + default_index = num_values; + + buf_len += strlen(values[num_values].value); + num_values++; + } + else + break; + } + + /* Build values string */ + if (num_values > 1) + { + size_t j; + + buf_len += num_values - 1; + buf_len += strlen(desc); + + values_buf[i] = (char *)calloc(buf_len, sizeof(char)); + if (!values_buf[i]) + goto error; + + strcpy(values_buf[i], desc); + strcat(values_buf[i], "; "); + + /* Default value goes first */ + strcat(values_buf[i], values[default_index].value); + + /* Add remaining values */ + for (j = 0; j < num_values; j++) + { + if (j != default_index) + { + strcat(values_buf[i], "|"); + strcat(values_buf[i], values[j].value); + } + } + } + } + + variables[option_index].key = key; + variables[option_index].value = values_buf[i]; + option_index++; + } + + /* Set variables */ + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); + +error: + + /* Clean up */ + if (values_buf) + { + for (i = 0; i < num_options; i++) + { + if (values_buf[i]) + { + free(values_buf[i]); + values_buf[i] = NULL; + } + } + + free(values_buf); + values_buf = NULL; + } + + if (variables) + { + free(variables); + variables = NULL; + } + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdl/libretro/rsemaphore.h b/sdl/libretro/rsemaphore.h index a00e5704..6c0f1a39 100644 --- a/sdl/libretro/rsemaphore.h +++ b/sdl/libretro/rsemaphore.h @@ -1,54 +1,54 @@ -/* Copyright (C) 2010-2015 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (rsemaphore.h). - * --------------------------------------------------------------------------------------- - * - * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __LIBRETRO_SDK_SEMAPHORE_H -#define __LIBRETRO_SDK_SEMAPHORE_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct ssem ssem_t; - -/** - * ssem_create: - * @value : initial value for the semaphore - * - * Create a new semaphore. - * - * Returns: pointer to new semaphore if successful, otherwise NULL. - */ -ssem_t *ssem_new(int value); - -void ssem_free(ssem_t *semaphore); - -int ssem_get(ssem_t *semaphore); - -void ssem_wait(ssem_t *semaphore); - -void ssem_signal(ssem_t *semaphore); - -#ifdef __cplusplus -} -#endif - -#endif /* __LIBRETRO_SDK_SEMAPHORE_H */ +/* Copyright (C) 2010-2015 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (rsemaphore.h). + * --------------------------------------------------------------------------------------- + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __LIBRETRO_SDK_SEMAPHORE_H +#define __LIBRETRO_SDK_SEMAPHORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ssem ssem_t; + +/** + * ssem_create: + * @value : initial value for the semaphore + * + * Create a new semaphore. + * + * Returns: pointer to new semaphore if successful, otherwise NULL. + */ +ssem_t *ssem_new(int value); + +void ssem_free(ssem_t *semaphore); + +int ssem_get(ssem_t *semaphore); + +void ssem_wait(ssem_t *semaphore); + +void ssem_signal(ssem_t *semaphore); + +#ifdef __cplusplus +} +#endif + +#endif /* __LIBRETRO_SDK_SEMAPHORE_H */ diff --git a/sdl/np2.c b/sdl/np2.c old mode 100755 new mode 100644 index 3637e5b4..90558755 --- a/sdl/np2.c +++ b/sdl/np2.c @@ -1,884 +1,884 @@ -#include -#if defined(__LIBRETRO__) -#include "file_stream.h" -#endif -#include -#include "np2.h" -#if defined(CPUCORE_IA32) -#include -#endif -#include "dosio.h" -#include "commng.h" -#include -#include "fontmng.h" -#include "inputmng.h" -#include "joymng.h" -#include "kbdmng.h" -#include "mousemng.h" -#include "scrnmng.h" -#include "soundmng.h" -#include "sysmng.h" -#include "taskmng.h" -#include "kbtrans.h" -#include "ini.h" -#include -#include -#include -#include -#include -#include -#include -#include "timing.h" -#include -#include -#include -#include "sysmenu.h" -#if defined(SUPPORT_NET) -#include -#endif -#if defined(SUPPORT_WAB) -#include -#include -#endif -#if defined(SUPPORT_CL_GD5430) -#include -#endif -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif -#include - -static const char appname[] = -#if defined(CPUCORE_IA32) - "sdlnp21kai" -#else - "sdlnp2kai" -#endif -; - -NP2OSCFG np2oscfg = { - 0, /* NOWAIT */ - 0, /* DRAW_SKIP */ - - KEY_KEY106, /* KEYBOARD */ - -#if !defined(__LIBRETRO__) - 0, /* JOYPAD1 */ - 0, /* JOYPAD2 */ - { 1, 2, 5, 6 }, /* JOY1BTN */ - { - { 0, 1 }, /* JOYAXISMAP[0] */ - { 0, 1 }, /* JOYAXISMAP[1] */ - }, - { - { 0, 1, 0xff, 0xff }, /* JOYBTNMAP[0] */ - { 0, 1, 0xff, 0xff }, /* JOYBTNMAP[1] */ - }, - { "", "" }, /* JOYDEV */ -#else /* __LIBRETRO__ */ - { 273, 274, 276, 275, 120, 122, 32, 306, 8, 303, 27, 13 }, /* lrjoybtn */ -#endif /* __LIBRETRO__ */ - - 0, /* resume */ - 0, /* jastsnd */ - 0, /* I286SAVE */ - 1, /* xrollkey */ - - SNDDRV_SDL, /* snddrv */ - { "", "" }, /* MIDIDEV */ -#if defined(SUPPORT_SMPU98) - { "", "" }, /* MIDIDEVA */ - { "", "" }, /* MIDIDEVB */ -#endif - 0, /* MIDIWAIT */ - - { TRUE, COMPORT_MIDI, 0, 0x3e, 19200, "", "", "", "" }, /* mpu */ -#if defined(SUPPORT_SMPU98) - { TRUE, COMPORT_MIDI, 0, 0x3e, 19200, "", "", "", "" }, /* s-mpu */ - { TRUE, COMPORT_MIDI, 0, 0x3e, 19200, "", "", "", "" }, /* s-mpu */ -#endif -#if !defined(__LIBRETRO__) - { - { TRUE, COMPORT_NONE, 0, 0x3e, 19200, "", "", "", "" },/* com1 */ - { TRUE, COMPORT_NONE, 0, 0x3e, 19200, "", "", "", "" },/* com2 */ - { TRUE, COMPORT_NONE, 0, 0x3e, 19200, "", "", "", "" },/* com3 */ - }, -#endif /* __LIBRETRO__ */ - - 0, /* readonly */ -}; -static UINT framecnt; -static UINT waitcnt; -static UINT framemax = 1; -static UINT lateframecount; // フレーム遅れ数 -#if defined(EMSCRIPTEN) && !defined(__LIBRETRO__) && defined(USE_EMULARITY_NP2DIR) -static char datadir[256] = EMSCRIPTEN_DIR; -#else -static char datadir[3] = "/"; -#endif - -BOOL s98logging = FALSE; -int s98log_count = 0; - -char hddfolder[MAX_PATH]; -char fddfolder[MAX_PATH]; -char bmpfilefolder[MAX_PATH]; -UINT bmpfilenumber; -char modulefile[MAX_PATH]; -char draw32bit; - -static void np2exec(); -unsigned int np2_main_disk_images_count = 0; -static unsigned int np2_main_cd_images_count = 0; -OEMCHAR np2_main_disk_images_paths[50][MAX_PATH] = {0}; -static OEMCHAR np2_main_cd_images_paths[5][MAX_PATH] = {0}; -static unsigned int np2_main_cd_drv[5] = {0xF, 0xF, 0xF, 0xF, 0xF}; - -UINT8 scrnmode = 0; -UINT8 changescreeninit = 0; - -static void usage(const char *progname) { - - printf("Usage: %s [options]\n", progname); - printf("\t--help [-h] : print this message\n"); - printf("\t--config [-c] : specify config file\n"); -} - - -// ---- resume - -static void getstatfilename(OEMCHAR *path, const OEMCHAR *ext, int size) -{ - OEMCHAR filename[32]; - OEMSNPRINTF(filename, sizeof(filename), OEMTEXT("np2.%s"), ext); - - file_cpyname(path, file_getcd(filename), size); -} - -int flagsave(const OEMCHAR *ext) { - - int ret; - OEMCHAR path[MAX_PATH]; - - getstatfilename(path, ext, sizeof(path)); - ret = statsave_save(path); - if (ret) { - file_delete(path); - } - return(ret); -} - -void flagdelete(const OEMCHAR *ext) { - - OEMCHAR path[MAX_PATH]; - - getstatfilename(path, ext, sizeof(path)); - file_delete(path); -} - -int flagload(const OEMCHAR *ext, const OEMCHAR *title, BOOL force) { - - int ret; - int id; - OEMCHAR path[MAX_PATH]; - OEMCHAR buf[1024]; - OEMCHAR buf2[1024 + 256]; - - getstatfilename(path, ext, sizeof(path)); - id = DID_YES; - ret = statsave_check(path, buf, sizeof(buf)); - if (ret & (~STATFLAG_DISKCHG)) { - menumbox("Couldn't restart", title, MBOX_OK | MBOX_ICONSTOP); - id = DID_NO; - } - else if ((!force) && (ret & STATFLAG_DISKCHG)) { - OEMSNPRINTF(buf2, sizeof(buf2), OEMTEXT("Conflict!\n\n%s\nContinue?"), buf); - id = menumbox(buf2, title, MBOX_YESNOCAN | MBOX_ICONQUESTION); - } - if (id == DID_YES) { - statsave_load(path); - } - return(id); -} - -void -changescreen(UINT8 newmode) -{ - UINT8 change; - UINT8 renewal; - UINT8 res; - - change = scrnmode ^ newmode; - renewal = (change & SCRNMODE_FULLSCREEN); - if (newmode & SCRNMODE_FULLSCREEN) { - renewal |= (change & SCRNMODE_HIGHCOLOR); - } else { - renewal |= (change & SCRNMODE_ROTATEMASK); - } - if (renewal) { - if(menuvram) { - menubase_close(); - } - changescreeninit = 1; - soundmng_stop(); - scrnmng_destroy(); - sysmenu_destroy(); - - if(scrnmng_create(newmode) == SUCCESS) { - scrnmode = newmode; - } else { - if(scrnmng_create(scrnmode) != SUCCESS) { - return; - } - } - sysmenu_create(); - changescreeninit = 0; - scrndraw_redraw(); - soundmng_play(); - } else { - scrnmode = newmode; - } -} - -// ---- proc - -#define framereset(cnt) framecnt = 0 - -static void processwait(UINT cnt) { - - if (timing_getcount() >= cnt) { -#if defined(SUPPORT_IA32_HAXM) - if (np2hax.enable) { - np2haxcore.hltflag = 0; - if(lateframecount > 0 && np2haxcore.I_ratio < 254){ - np2haxcore.I_ratio++; - }else if(np2haxcore.I_ratio > 1){ - //np2haxcore.I_ratio--; - } - lateframecount = 0; - } -#endif - timing_setcount(0); - framereset(cnt); - } - else { -#if defined(SUPPORT_IA32_HAXM) - if (np2hax.enable) { - if(np2haxcore.I_ratio > 1){ - np2haxcore.I_ratio--; - } - } -#endif - taskmng_sleep(1); - } -} - -int is_absolute(const char *path) -{ - if (path[0] == '/' || path[1] == ':') - return 1; - if (path[0] == '\\' && path[1] == '\\') - return 1; -#if defined (_3DS) || defined (PSP) || defined (VITA) - char *pcolon = strchr(path, ':'); - if (pcolon != NULL && pcolon[1] == '/') - return 1; -#endif - return 0; -} - -void np2_main_getfullpath(char* fullpath, const char* file, const char* base_dir) { - int len; - - milstr_ncpy(fullpath, file, MAX_PATH); - len = OEMSTRLEN(fullpath); - if(len > 1) { - if(!is_absolute(fullpath)) { - milstr_ncpy(fullpath, base_dir, MAX_PATH); - file_setseparator(fullpath, MAX_PATH); - milstr_ncat(fullpath, file, MAX_PATH); - } - } -} - -char np2_isfdimage(const char *file, const int len) { - char fd = 0; - char* ext; - - if(len > 4) { - ext = file + len - 4; - if (milstr_cmp(ext, ".d88") == 0) fd = 1; - else if (milstr_cmp(ext, ".d98") == 0) fd = 1; - else if (milstr_cmp(ext, ".fdi") == 0) fd = 1; - else if (milstr_cmp(ext, ".hdm") == 0) fd = 1; - else if (milstr_cmp(ext, ".xdf") == 0) fd = 1; - else if (milstr_cmp(ext, ".dup") == 0) fd = 1; - else if (milstr_cmp(ext, ".2hd") == 0) fd = 1; - else if (milstr_cmp(ext, ".nfd") == 0) fd = 1; - else if (milstr_cmp(ext, ".fdd") == 0) fd = 1; - else if (milstr_cmp(ext, ".hd4") == 0) fd = 1; - else if (milstr_cmp(ext, ".hd5") == 0) fd = 1; - else if (milstr_cmp(ext, ".hd9") == 0) fd = 1; - else if (milstr_cmp(ext, ".h01") == 0) fd = 1; - else if (milstr_cmp(ext, ".hdb") == 0) fd = 1; - else if (milstr_cmp(ext, ".ddb") == 0) fd = 1; - else if (milstr_cmp(ext, ".dd6") == 0) fd = 1; - else if (milstr_cmp(ext, ".dd9") == 0) fd = 1; - else if (milstr_cmp(ext, ".dcp") == 0) fd = 1; - else if (milstr_cmp(ext, ".dcu") == 0) fd = 1; - else if (milstr_cmp(ext, ".flp") == 0) fd = 1; - else if (milstr_cmp(ext, ".bin") == 0) fd = 1; - else if (milstr_cmp(ext, ".tfd") == 0) fd = 1; - else if (milstr_cmp(ext, ".fim") == 0) fd = 1; - else if (milstr_cmp(ext, ".img") == 0) fd = 1; - else if (milstr_cmp(ext, ".ima") == 0) fd = 1; - } - - return fd; -} - -char np2_main_read_m3u(const char *file) -{ - char res = 0; - char line[MAX_PATH]; - char name[MAX_PATH]; - char base_dir[MAX_PATH]; -#if defined(__LIBRETRO__) - RFILE *f; -#else - FILE *f; -#endif - -#if defined(NP2_WIN) - wchar_t wfile[MAX_PATH]; - codecnv_utf8toucs2(wfile, MAX_PATH, file, -1); - f = _wfopen(wfile, "r"); -#elif defined(__LIBRETRO__) - f = filestream_open(file, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); -#else - f = fopen(file, "r"); -#endif - if (!f) { - res = 1; - return res; - } - - milstr_ncpy(base_dir, file, MAX_PATH); - file_cutname(base_dir); - -#if defined(__LIBRETRO__) - while (filestream_gets(f, line, sizeof(line)) && np2_main_disk_images_count < sizeof(np2_main_disk_images_paths) / MAX_PATH) -#else - while (fgets(f, line, sizeof(line)) && np2_main_disk_images_count < sizeof(np2_main_disk_images_paths) / MAX_PATH) -#endif - { - if (line[0] == '#') - continue; - - char *carriage_return = strchr(line, '\r'); - if (carriage_return) - *carriage_return = '\0'; - - char *newline = strchr(line, '\n'); - if (newline) - *newline = '\0'; - - // Remove any beginning and ending quotes as these can cause issues when feeding the paths into command line later - if (line[0] == '"') - memmove(line, line + 1, OEMSTRLEN(line)); - - if (line[OEMSTRLEN(line) - 1] == '"') - line[OEMSTRLEN(line) - 1] = '\0'; - - if (OEMSTRLEN(line) > 4) - { - milstr_ncpy(name, line, MAX_PATH); - if(line[0] != '/' && line[1] != ':' && (line[0] != '\\' && line[1] != '\\')) { - milstr_ncpy(name, base_dir, MAX_PATH); - milstr_ncat(name, line, MAX_PATH); - } - if(np2_isfdimage(name, OEMSTRLEN(name))) { - milstr_ncpy(np2_main_disk_images_paths[np2_main_disk_images_count], name, MAX_PATH); - np2_main_disk_images_count++; - } - } - } - -#if defined(__LIBRETRO__) - filestream_close(f); -#else - fclose(f); -#endif - return res; -} - -#if defined(__LIBRETRO__) -extern char lr_game_base_dir[MAX_PATH]; -extern void attach_disk_swap_interface(void); -extern int lr_uselasthddmount; -#endif - -int np2_main(int argc, char *argv[]) { - - int pos; - char *p; - int id; - int i, j, imagetype, drvfdd, setmedia, drvhddSCSI, HDCount, CDCount, CDDrv[4], CDArgv[4]; - OEMCHAR *ext; - OEMCHAR base_dir[MAX_PATH]; - OEMCHAR fullpath[MAX_PATH]; - FILEH fcheck; - - pos = 1; - while(pos < argc) { - p = argv[pos++]; - if ((!milstr_cmp(p, "-h")) || (!milstr_cmp(p, "--help"))) { - usage(argv[0]); - goto np2main_err1; - } else if ((!milstr_cmp(p, "-c")) || (!milstr_cmp(p, "--config"))) { - if(pos < argc) { - milstr_ncpy(modulefile, argv[pos++], sizeof(modulefile)); - } else { - printf("Invalid option.\n"); - goto np2main_err1; - } - }/* - else { - printf("error command: %s\n", p); - goto np2main_err1; - }*/ - } - -#if defined(NP2_WIN) - milstr_ncpy(np2cfg.biospath, "./", sizeof(np2cfg.biospath)); - file_setcd(np2cfg.biospath); -#elif defined(__LIBRETRO__) - milstr_ncpy(base_dir, lr_game_base_dir, MAX_PATH); -#elif defined(EMSCRIPTEN) - milstr_ncat(np2cfg.biospath, datadir, sizeof(np2cfg.biospath)); - file_setcd(np2cfg.biospath); -#else - char *config_home = getenv("XDG_CONFIG_HOME"); - char *home = getenv("HOME"); - if (config_home && config_home[0] == '/') { - /* base dir */ - milstr_ncpy(np2cfg.biospath, config_home, sizeof(np2cfg.biospath)); - milstr_ncat(np2cfg.biospath, "/", sizeof(np2cfg.biospath)); - milstr_ncat(np2cfg.biospath, appname, sizeof(np2cfg.biospath)); - milstr_ncat(np2cfg.biospath, "/", sizeof(np2cfg.biospath)); - } else if (home) { - /* base dir */ - milstr_ncpy(np2cfg.biospath, home, sizeof(np2cfg.biospath)); - milstr_ncat(np2cfg.biospath, "/.config/", sizeof(np2cfg.biospath)); - milstr_ncat(np2cfg.biospath, appname, sizeof(np2cfg.biospath)); - milstr_ncat(np2cfg.biospath, "/", sizeof(np2cfg.biospath)); - } else { - printf("$HOME isn't defined.\n"); - goto np2main_err1; - } - file_setcd(np2cfg.biospath); - milstr_ncpy(base_dir, np2cfg.biospath, MAX_PATH); -#endif /* __LIBRETRO__ */ - - initload(); -#if defined(SUPPORT_WAB) - wabwin_readini(); -#endif // defined(SUPPORT_WAB) - - mmxflag = havemmx() ? 0 : MMXFLAG_NOTSUPPORT; - -#if defined(SUPPORT_CL_GD5430) - draw32bit = np2cfg.usegd5430; -#endif - - OEMSNPRINTF(fullpath, sizeof(fullpath), OEMTEXT("%sdefault.ttf"), np2cfg.biospath); - fcheck = file_open_rb(fullpath); - if (fcheck != NULL) { - file_close(fcheck); - fontmng_setdeffontname(fullpath); - } - - setmedia = drvhddSCSI = HDCount = CDCount = 0; -#if defined(__LIBRETRO__) - if(!lr_uselasthddmount) { -#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) - for(i = 0; i < 4; i++) { - milstr_ncpy(np2cfg.sasihdd[i], "", MAX_PATH); - } -#endif -#if defined(SUPPORT_SCSI) - for(i = 0; i < 4; i++) { - milstr_ncpy(np2cfg.scsihdd[i], "", MAX_PATH); - } -#endif - } -#endif /* __LIBRETRO__ */ - for (i = 1; i < argc; i++) { - if (OEMSTRLEN(argv[i]) < 5) { - continue; - } - - if(argv[i][0] == '"' && argv[i][OEMSTRLEN(argv[i]) - 1] == '"') { - argv[i]++; - argv[i][OEMSTRLEN(argv[i]) - 1] = '\0'; - } - - imagetype = IMAGETYPE_UNKNOWN; - np2_main_getfullpath(fullpath, argv[i], base_dir); - ext = fullpath + (OEMSTRLEN(fullpath) - 4); - -#if !defined(__LIBRETRO__) - if(milstr_cmp(ext, ".m3u") == 0) { - imagetype = IMAGETYPE_OTHER; - np2_main_read_m3u(fullpath); - } -#endif - - if(np2_isfdimage(fullpath, OEMSTRLEN(fullpath))) { - imagetype = IMAGETYPE_FDD; - milstr_ncpy(np2_main_disk_images_paths[np2_main_disk_images_count], fullpath, MAX_PATH); - np2_main_disk_images_count++; - } -#if defined(__LIBRETRO__) - attach_disk_swap_interface(); -#endif - -#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) || defined(SUPPORT_SCSI) - if(imagetype == IMAGETYPE_UNKNOWN) { -#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) - if (milstr_cmp(ext, ".hdi") == 0) imagetype = IMAGETYPE_SASI_IDE; // SASI/IDE - else if (milstr_cmp(ext, ".thd") == 0) imagetype = IMAGETYPE_SASI_IDE; - else if (milstr_cmp(ext, ".nhd") == 0) imagetype = IMAGETYPE_SASI_IDE; - else if (milstr_cmp(ext, ".vhd") == 0) imagetype = IMAGETYPE_SASI_IDE; - else if (milstr_cmp(ext, ".sln") == 0) imagetype = IMAGETYPE_SASI_IDE; - else if (milstr_cmp(ext, ".iso") == 0) imagetype = IMAGETYPE_SASI_IDE_CD; // SASI/IDE CD - else if (milstr_cmp(ext, ".cue") == 0) imagetype = IMAGETYPE_SASI_IDE_CD; - else if (milstr_cmp(ext, ".ccd") == 0) imagetype = IMAGETYPE_SASI_IDE_CD; - else if (milstr_cmp(ext, ".mds") == 0) imagetype = IMAGETYPE_SASI_IDE_CD; - else if (milstr_cmp(ext, ".nrg") == 0) imagetype = IMAGETYPE_SASI_IDE_CD; -#endif -#if defined(SUPPORT_SCSI) - if (milstr_cmp(ext, ".hdd") == 0) imagetype = IMAGETYPE_SCSI; // SCSI - else if (milstr_cmp(ext, ".hdn") == 0) imagetype = IMAGETYPE_SCSI; -#endif - switch (imagetype) { -#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) - case IMAGETYPE_SASI_IDE: - for(j = 0; j < 4; j++) { - if(np2cfg.idetype[j] == SXSIDEV_HDD) { - if(!(setmedia & (1 << j))) { - milstr_ncpy(np2cfg.sasihdd[j], fullpath, MAX_PATH); - setmedia |= 1 << j; - HDCount++; - break; - } - } - } - break; - case IMAGETYPE_SASI_IDE_CD: - if(np2_main_cd_images_count < sizeof(np2_main_cd_images_paths) / MAX_PATH) { - milstr_ncpy(np2_main_cd_images_paths[np2_main_cd_images_count], fullpath, MAX_PATH); - for(j = 0; j < 4; j++) { - if(np2cfg.idetype[j] == SXSIDEV_CDROM) { - if(!(setmedia & (1 << j))) { - np2_main_cd_drv[np2_main_cd_images_count] = j; - setmedia |= 1 << j; - } - break; - } - } - np2_main_cd_images_count++; - } - break; -#endif -#if defined(SUPPORT_SCSI) - case IMAGETYPE_SCSI: - if(drvhddSCSI < 4) { - milstr_ncpy(np2cfg.scsihdd[drvhddSCSI], fullpath, MAX_PATH); - drvhddSCSI++; - } - break; -#endif - } - } -#endif - } - - TRACEINIT(); - - if (fontmng_init() != SUCCESS) { - goto np2main_err2; - } - inputmng_init(); - keystat_initialize(); - - if (sysmenu_create() != SUCCESS) { - goto np2main_err3; - } - -#if !defined(__LIBRETRO__) - joymng_initialize(); -#endif /* __LIBRETRO__ */ - mousemng_initialize(); - - scrnmng_initialize(); - if (scrnmng_create(0) != SUCCESS) { - goto np2main_err4; - } - - soundmng_initialize(); - commng_initialize(); - sysmng_initialize(); - taskmng_initialize(); - pccore_init(); - S98_init(); - -#if defined(SUPPORT_NET) - np2net_init(); -#endif -#ifdef SUPPORT_WAB - np2wab_init(); -#endif -#ifdef SUPPORT_CL_GD5430 - pc98_cirrus_vga_init(); -#endif -#if !defined(__LIBRETRO__) - mousemng_hidecursor(); -#endif /* __LIBRETRO__ */ - scrndraw_redraw(); - pccore_reset(); - -#if defined(SUPPORT_RESUME) - if (np2oscfg.resume) { - id = flagload(str_sav, str_resume, FALSE); - if (id == DID_CANCEL) { - goto np2main_err5; - } - } -#endif /* defined(SUPPORT_RESUME) */ - - for (i = 0; i < np2_main_cd_images_count; i++) { - if (i < 1) { - sxsi_devopen(np2_main_cd_drv[i], np2_main_cd_images_paths[i]); - } - } - - drvfdd = 0; - for (i = 0; i < np2_main_disk_images_count; i++) { - if (i < 2) { - diskdrv_setfdd(i, np2_main_disk_images_paths[i], 0); - } - } - -//printf("bd:%s\n",base_dir); -//printf("fdin:%d\n",drvfdd); -//printf("hdin:%d\n",HDCount); -//printf("cdin:%d\n",CDCount); - -#if defined(__LIBRETRO__) - return(SUCCESS); - -#if defined(SUPPORT_RESUME) -np2main_err5: - pccore_term(); - S98_trash(); - soundmng_deinitialize(); -#endif /* defined(SUPPORT_RESUME) */ - -np2main_err4: - scrnmng_destroy(); - -np2main_err3: - sysmenu_destroy(); - -np2main_err2: - TRACETERM(); - //SDL_Quit(); - -np2main_err1: - return(FAILURE); -} - -int np2_end(){ -#else /* __LIBRETRO__ */ - np2exec(); - -#endif /* __LIBRETRO__ */ - - pccore_cfgupdate(); -#if defined(SUPPORT_RESUME) - if (np2oscfg.resume) { - flagsave(str_sav); - } - else { - flagdelete(str_sav); - } -#endif -#if !defined(__LIBRETRO__) - joymng_deinitialize(); -#endif /* __LIBRETRO__ */ -#if defined(SUPPORT_NET) - np2net_shutdown(); -#endif -#ifdef SUPPORT_CL_GD5430 - pc98_cirrus_vga_shutdown(); -#endif -#ifdef SUPPORT_WAB - np2wab_shutdown(); -#endif - pccore_term(); - S98_trash(); - soundmng_deinitialize(); - - sysmng_deinitialize(); - - scrnmng_destroy(); - sysmenu_destroy(); -#if defined(SUPPORT_WAB) - wabwin_writeini(); - np2wabcfg.readonly = np2oscfg.readonly; -#endif // defined(SUPPORT_WAB) - TRACETERM(); -#if !defined(__LIBRETRO__) - SDL_Quit(); -#endif /* __LIBRETRO__ */ - return(SUCCESS); - -#if !defined(__LIBRETRO__) -#if defined(SUPPORT_RESUME) -np2main_err5: - pccore_term(); - S98_trash(); - soundmng_deinitialize(); -#endif /* defined(SUPPORT_RESUME) */ - -np2main_err4: - scrnmng_destroy(); - -np2main_err3: - sysmenu_destroy(); - -np2main_err2: - TRACETERM(); - SDL_Quit(); - -np2main_err1: - return(FAILURE); -#endif /* __LIBRETRO__ */ -} - -int mmxflag; - -int -havemmx(void) -{ -#if !defined(GCC_CPU_ARCH_IA32) - return 0; -#else /* GCC_CPU_ARCH_IA32 */ - int rv; - -#if defined(GCC_CPU_ARCH_AMD64) || defined(__ANDROID__) - rv = 1; -#else /* !GCC_CPU_ARCH_AMD64 */ - asm volatile ( - "pushf;" - "popl %%eax;" - "movl %%eax, %%edx;" - "xorl $0x00200000, %%eax;" - "pushl %%eax;" - "popf;" - "pushf;" - "popl %%eax;" - "subl %%edx, %%eax;" - "je .nocpuid;" - "xorl %%eax, %%eax;" - "incl %%eax;" - "pushl %%ebx;" - "cpuid;" - "popl %%ebx;" - "movl %%edx, %0;" - "andl $0x00800000, %0;" - ".nocpuid:" - : "=a" (rv)); -#endif /* GCC_CPU_ARCH_AMD64 */ - return rv; -#endif /* GCC_CPU_ARCH_IA32 */ -} - -static void np2exec() -{ - while(taskmng_isavail()) { -#if !defined(__LIBRETRO__) - if(g_u8ControlState == 1) { - statsave_save_d(); - } else if(g_u8ControlState == 2) { - statsave_load_d(); - } - g_u8ControlState = 0; -#endif - - taskmng_rol(); -#if defined(EMSCRIPTEN) && !defined(__LIBRETRO__) -// emscripten_sleep_with_yield(0); - emscripten_sleep(0); -#endif - if (np2oscfg.NOWAIT) { - joymng_sync(); - pccore_exec(framecnt == 0); - if (np2oscfg.DRAW_SKIP) { // nowait frame skip - framecnt++; - if (framecnt >= np2oscfg.DRAW_SKIP) { - processwait(0); - } - } - else { // nowait auto skip - framecnt = 1; - if (timing_getcount()) { - processwait(0); - } - } - } - else if (np2oscfg.DRAW_SKIP) { // frame skip - if (framecnt < np2oscfg.DRAW_SKIP) { - joymng_sync(); - pccore_exec(framecnt == 0); - framecnt++; - } - else { - processwait(np2oscfg.DRAW_SKIP); - } - } - else { // auto skip - if (!waitcnt) { - UINT cnt; - joymng_sync(); - pccore_exec(framecnt == 0); - framecnt++; - cnt = timing_getcount(); - if (framecnt > cnt) { - waitcnt = framecnt; - if (framemax > 1) { - framemax--; - } - } - else if (framecnt >= framemax) { - if (framemax < 12) { - framemax++; - } - if (cnt >= 12) { - timing_reset(); - } - else { - timing_setcount(cnt - framecnt); - } - framereset(0); - } - } - else { - processwait(waitcnt); - waitcnt = framecnt; - } - } - } -} +#include +#if defined(__LIBRETRO__) +#include "file_stream.h" +#endif +#include +#include "np2.h" +#if defined(CPUCORE_IA32) +#include +#endif +#include "dosio.h" +#include "commng.h" +#include +#include "fontmng.h" +#include "inputmng.h" +#include "joymng.h" +#include "kbdmng.h" +#include "mousemng.h" +#include "scrnmng.h" +#include "soundmng.h" +#include "sysmng.h" +#include "taskmng.h" +#include "kbtrans.h" +#include "ini.h" +#include +#include +#include +#include +#include +#include +#include +#include "timing.h" +#include +#include +#include +#include "sysmenu.h" +#if defined(SUPPORT_NET) +#include +#endif +#if defined(SUPPORT_WAB) +#include +#include +#endif +#if defined(SUPPORT_CL_GD5430) +#include +#endif +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif +#include + +static const char appname[] = +#if defined(CPUCORE_IA32) + "sdlnp21kai" +#else + "sdlnp2kai" +#endif +; + +NP2OSCFG np2oscfg = { + 0, /* NOWAIT */ + 0, /* DRAW_SKIP */ + + KEY_KEY106, /* KEYBOARD */ + +#if !defined(__LIBRETRO__) + 0, /* JOYPAD1 */ + 0, /* JOYPAD2 */ + { 1, 2, 5, 6 }, /* JOY1BTN */ + { + { 0, 1 }, /* JOYAXISMAP[0] */ + { 0, 1 }, /* JOYAXISMAP[1] */ + }, + { + { 0, 1, 0xff, 0xff }, /* JOYBTNMAP[0] */ + { 0, 1, 0xff, 0xff }, /* JOYBTNMAP[1] */ + }, + { "", "" }, /* JOYDEV */ +#else /* __LIBRETRO__ */ + { 273, 274, 276, 275, 120, 122, 32, 306, 8, 303, 27, 13 }, /* lrjoybtn */ +#endif /* __LIBRETRO__ */ + + 0, /* resume */ + 0, /* jastsnd */ + 0, /* I286SAVE */ + 1, /* xrollkey */ + + SNDDRV_SDL, /* snddrv */ + { "", "" }, /* MIDIDEV */ +#if defined(SUPPORT_SMPU98) + { "", "" }, /* MIDIDEVA */ + { "", "" }, /* MIDIDEVB */ +#endif + 0, /* MIDIWAIT */ + + { TRUE, COMPORT_MIDI, 0, 0x3e, 19200, "", "", "", "" }, /* mpu */ +#if defined(SUPPORT_SMPU98) + { TRUE, COMPORT_MIDI, 0, 0x3e, 19200, "", "", "", "" }, /* s-mpu */ + { TRUE, COMPORT_MIDI, 0, 0x3e, 19200, "", "", "", "" }, /* s-mpu */ +#endif +#if !defined(__LIBRETRO__) + { + { TRUE, COMPORT_NONE, 0, 0x3e, 19200, "", "", "", "" },/* com1 */ + { TRUE, COMPORT_NONE, 0, 0x3e, 19200, "", "", "", "" },/* com2 */ + { TRUE, COMPORT_NONE, 0, 0x3e, 19200, "", "", "", "" },/* com3 */ + }, +#endif /* __LIBRETRO__ */ + + 0, /* readonly */ +}; +static UINT framecnt; +static UINT waitcnt; +static UINT framemax = 1; +static UINT lateframecount; // フレーム遅れ数 +#if defined(EMSCRIPTEN) && !defined(__LIBRETRO__) && defined(USE_EMULARITY_NP2DIR) +static char datadir[256] = EMSCRIPTEN_DIR; +#else +static char datadir[3] = "/"; +#endif + +BOOL s98logging = FALSE; +int s98log_count = 0; + +char hddfolder[MAX_PATH]; +char fddfolder[MAX_PATH]; +char bmpfilefolder[MAX_PATH]; +UINT bmpfilenumber; +char modulefile[MAX_PATH]; +char draw32bit; + +static void np2exec(); +unsigned int np2_main_disk_images_count = 0; +static unsigned int np2_main_cd_images_count = 0; +OEMCHAR np2_main_disk_images_paths[50][MAX_PATH] = {0}; +static OEMCHAR np2_main_cd_images_paths[5][MAX_PATH] = {0}; +static unsigned int np2_main_cd_drv[5] = {0xF, 0xF, 0xF, 0xF, 0xF}; + +UINT8 scrnmode = 0; +UINT8 changescreeninit = 0; + +static void usage(const char *progname) { + + printf("Usage: %s [options]\n", progname); + printf("\t--help [-h] : print this message\n"); + printf("\t--config [-c] : specify config file\n"); +} + + +// ---- resume + +static void getstatfilename(OEMCHAR *path, const OEMCHAR *ext, int size) +{ + OEMCHAR filename[32]; + OEMSNPRINTF(filename, sizeof(filename), OEMTEXT("np2.%s"), ext); + + file_cpyname(path, file_getcd(filename), size); +} + +int flagsave(const OEMCHAR *ext) { + + int ret; + OEMCHAR path[MAX_PATH]; + + getstatfilename(path, ext, sizeof(path)); + ret = statsave_save(path); + if (ret) { + file_delete(path); + } + return(ret); +} + +void flagdelete(const OEMCHAR *ext) { + + OEMCHAR path[MAX_PATH]; + + getstatfilename(path, ext, sizeof(path)); + file_delete(path); +} + +int flagload(const OEMCHAR *ext, const OEMCHAR *title, BOOL force) { + + int ret; + int id; + OEMCHAR path[MAX_PATH]; + OEMCHAR buf[1024]; + OEMCHAR buf2[1024 + 256]; + + getstatfilename(path, ext, sizeof(path)); + id = DID_YES; + ret = statsave_check(path, buf, sizeof(buf)); + if (ret & (~STATFLAG_DISKCHG)) { + menumbox("Couldn't restart", title, MBOX_OK | MBOX_ICONSTOP); + id = DID_NO; + } + else if ((!force) && (ret & STATFLAG_DISKCHG)) { + OEMSNPRINTF(buf2, sizeof(buf2), OEMTEXT("Conflict!\n\n%s\nContinue?"), buf); + id = menumbox(buf2, title, MBOX_YESNOCAN | MBOX_ICONQUESTION); + } + if (id == DID_YES) { + statsave_load(path); + } + return(id); +} + +void +changescreen(UINT8 newmode) +{ + UINT8 change; + UINT8 renewal; + UINT8 res; + + change = scrnmode ^ newmode; + renewal = (change & SCRNMODE_FULLSCREEN); + if (newmode & SCRNMODE_FULLSCREEN) { + renewal |= (change & SCRNMODE_HIGHCOLOR); + } else { + renewal |= (change & SCRNMODE_ROTATEMASK); + } + if (renewal) { + if(menuvram) { + menubase_close(); + } + changescreeninit = 1; + soundmng_stop(); + scrnmng_destroy(); + sysmenu_destroy(); + + if(scrnmng_create(newmode) == SUCCESS) { + scrnmode = newmode; + } else { + if(scrnmng_create(scrnmode) != SUCCESS) { + return; + } + } + sysmenu_create(); + changescreeninit = 0; + scrndraw_redraw(); + soundmng_play(); + } else { + scrnmode = newmode; + } +} + +// ---- proc + +#define framereset(cnt) framecnt = 0 + +static void processwait(UINT cnt) { + + if (timing_getcount() >= cnt) { +#if defined(SUPPORT_IA32_HAXM) + if (np2hax.enable) { + np2haxcore.hltflag = 0; + if(lateframecount > 0 && np2haxcore.I_ratio < 254){ + np2haxcore.I_ratio++; + }else if(np2haxcore.I_ratio > 1){ + //np2haxcore.I_ratio--; + } + lateframecount = 0; + } +#endif + timing_setcount(0); + framereset(cnt); + } + else { +#if defined(SUPPORT_IA32_HAXM) + if (np2hax.enable) { + if(np2haxcore.I_ratio > 1){ + np2haxcore.I_ratio--; + } + } +#endif + taskmng_sleep(1); + } +} + +int is_absolute(const char *path) +{ + if (path[0] == '/' || path[1] == ':') + return 1; + if (path[0] == '\\' && path[1] == '\\') + return 1; +#if defined (_3DS) || defined (PSP) || defined (VITA) + char *pcolon = strchr(path, ':'); + if (pcolon != NULL && pcolon[1] == '/') + return 1; +#endif + return 0; +} + +void np2_main_getfullpath(char* fullpath, const char* file, const char* base_dir) { + int len; + + milstr_ncpy(fullpath, file, MAX_PATH); + len = OEMSTRLEN(fullpath); + if(len > 1) { + if(!is_absolute(fullpath)) { + milstr_ncpy(fullpath, base_dir, MAX_PATH); + file_setseparator(fullpath, MAX_PATH); + milstr_ncat(fullpath, file, MAX_PATH); + } + } +} + +char np2_isfdimage(const char *file, const int len) { + char fd = 0; + char* ext; + + if(len > 4) { + ext = file + len - 4; + if (milstr_cmp(ext, ".d88") == 0) fd = 1; + else if (milstr_cmp(ext, ".d98") == 0) fd = 1; + else if (milstr_cmp(ext, ".fdi") == 0) fd = 1; + else if (milstr_cmp(ext, ".hdm") == 0) fd = 1; + else if (milstr_cmp(ext, ".xdf") == 0) fd = 1; + else if (milstr_cmp(ext, ".dup") == 0) fd = 1; + else if (milstr_cmp(ext, ".2hd") == 0) fd = 1; + else if (milstr_cmp(ext, ".nfd") == 0) fd = 1; + else if (milstr_cmp(ext, ".fdd") == 0) fd = 1; + else if (milstr_cmp(ext, ".hd4") == 0) fd = 1; + else if (milstr_cmp(ext, ".hd5") == 0) fd = 1; + else if (milstr_cmp(ext, ".hd9") == 0) fd = 1; + else if (milstr_cmp(ext, ".h01") == 0) fd = 1; + else if (milstr_cmp(ext, ".hdb") == 0) fd = 1; + else if (milstr_cmp(ext, ".ddb") == 0) fd = 1; + else if (milstr_cmp(ext, ".dd6") == 0) fd = 1; + else if (milstr_cmp(ext, ".dd9") == 0) fd = 1; + else if (milstr_cmp(ext, ".dcp") == 0) fd = 1; + else if (milstr_cmp(ext, ".dcu") == 0) fd = 1; + else if (milstr_cmp(ext, ".flp") == 0) fd = 1; + else if (milstr_cmp(ext, ".bin") == 0) fd = 1; + else if (milstr_cmp(ext, ".tfd") == 0) fd = 1; + else if (milstr_cmp(ext, ".fim") == 0) fd = 1; + else if (milstr_cmp(ext, ".img") == 0) fd = 1; + else if (milstr_cmp(ext, ".ima") == 0) fd = 1; + } + + return fd; +} + +char np2_main_read_m3u(const char *file) +{ + char res = 0; + char line[MAX_PATH]; + char name[MAX_PATH]; + char base_dir[MAX_PATH]; +#if defined(__LIBRETRO__) + RFILE *f; +#else + FILE *f; +#endif + +#if defined(NP2_WIN) + wchar_t wfile[MAX_PATH]; + codecnv_utf8toucs2(wfile, MAX_PATH, file, -1); + f = _wfopen(wfile, "r"); +#elif defined(__LIBRETRO__) + f = filestream_open(file, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); +#else + f = fopen(file, "r"); +#endif + if (!f) { + res = 1; + return res; + } + + milstr_ncpy(base_dir, file, MAX_PATH); + file_cutname(base_dir); + +#if defined(__LIBRETRO__) + while (filestream_gets(f, line, sizeof(line)) && np2_main_disk_images_count < sizeof(np2_main_disk_images_paths) / MAX_PATH) +#else + while (fgets(f, line, sizeof(line)) && np2_main_disk_images_count < sizeof(np2_main_disk_images_paths) / MAX_PATH) +#endif + { + if (line[0] == '#') + continue; + + char *carriage_return = strchr(line, '\r'); + if (carriage_return) + *carriage_return = '\0'; + + char *newline = strchr(line, '\n'); + if (newline) + *newline = '\0'; + + // Remove any beginning and ending quotes as these can cause issues when feeding the paths into command line later + if (line[0] == '"') + memmove(line, line + 1, OEMSTRLEN(line)); + + if (line[OEMSTRLEN(line) - 1] == '"') + line[OEMSTRLEN(line) - 1] = '\0'; + + if (OEMSTRLEN(line) > 4) + { + milstr_ncpy(name, line, MAX_PATH); + if(line[0] != '/' && line[1] != ':' && (line[0] != '\\' && line[1] != '\\')) { + milstr_ncpy(name, base_dir, MAX_PATH); + milstr_ncat(name, line, MAX_PATH); + } + if(np2_isfdimage(name, OEMSTRLEN(name))) { + milstr_ncpy(np2_main_disk_images_paths[np2_main_disk_images_count], name, MAX_PATH); + np2_main_disk_images_count++; + } + } + } + +#if defined(__LIBRETRO__) + filestream_close(f); +#else + fclose(f); +#endif + return res; +} + +#if defined(__LIBRETRO__) +extern char lr_game_base_dir[MAX_PATH]; +extern void attach_disk_swap_interface(void); +extern int lr_uselasthddmount; +#endif + +int np2_main(int argc, char *argv[]) { + + int pos; + char *p; + int id; + int i, j, imagetype, drvfdd, setmedia, drvhddSCSI, HDCount, CDCount, CDDrv[4], CDArgv[4]; + OEMCHAR *ext; + OEMCHAR base_dir[MAX_PATH]; + OEMCHAR fullpath[MAX_PATH]; + FILEH fcheck; + + pos = 1; + while(pos < argc) { + p = argv[pos++]; + if ((!milstr_cmp(p, "-h")) || (!milstr_cmp(p, "--help"))) { + usage(argv[0]); + goto np2main_err1; + } else if ((!milstr_cmp(p, "-c")) || (!milstr_cmp(p, "--config"))) { + if(pos < argc) { + milstr_ncpy(modulefile, argv[pos++], sizeof(modulefile)); + } else { + printf("Invalid option.\n"); + goto np2main_err1; + } + }/* + else { + printf("error command: %s\n", p); + goto np2main_err1; + }*/ + } + +#if defined(NP2_WIN) + milstr_ncpy(np2cfg.biospath, "./", sizeof(np2cfg.biospath)); + file_setcd(np2cfg.biospath); +#elif defined(__LIBRETRO__) + milstr_ncpy(base_dir, lr_game_base_dir, MAX_PATH); +#elif defined(EMSCRIPTEN) + milstr_ncat(np2cfg.biospath, datadir, sizeof(np2cfg.biospath)); + file_setcd(np2cfg.biospath); +#else + char *config_home = getenv("XDG_CONFIG_HOME"); + char *home = getenv("HOME"); + if (config_home && config_home[0] == '/') { + /* base dir */ + milstr_ncpy(np2cfg.biospath, config_home, sizeof(np2cfg.biospath)); + milstr_ncat(np2cfg.biospath, "/", sizeof(np2cfg.biospath)); + milstr_ncat(np2cfg.biospath, appname, sizeof(np2cfg.biospath)); + milstr_ncat(np2cfg.biospath, "/", sizeof(np2cfg.biospath)); + } else if (home) { + /* base dir */ + milstr_ncpy(np2cfg.biospath, home, sizeof(np2cfg.biospath)); + milstr_ncat(np2cfg.biospath, "/.config/", sizeof(np2cfg.biospath)); + milstr_ncat(np2cfg.biospath, appname, sizeof(np2cfg.biospath)); + milstr_ncat(np2cfg.biospath, "/", sizeof(np2cfg.biospath)); + } else { + printf("$HOME isn't defined.\n"); + goto np2main_err1; + } + file_setcd(np2cfg.biospath); + milstr_ncpy(base_dir, np2cfg.biospath, MAX_PATH); +#endif /* __LIBRETRO__ */ + + initload(); +#if defined(SUPPORT_WAB) + wabwin_readini(); +#endif // defined(SUPPORT_WAB) + + mmxflag = havemmx() ? 0 : MMXFLAG_NOTSUPPORT; + +#if defined(SUPPORT_CL_GD5430) + draw32bit = np2cfg.usegd5430; +#endif + + OEMSNPRINTF(fullpath, sizeof(fullpath), OEMTEXT("%sdefault.ttf"), np2cfg.biospath); + fcheck = file_open_rb(fullpath); + if (fcheck != NULL) { + file_close(fcheck); + fontmng_setdeffontname(fullpath); + } + + setmedia = drvhddSCSI = HDCount = CDCount = 0; +#if defined(__LIBRETRO__) + if(!lr_uselasthddmount) { +#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) + for(i = 0; i < 4; i++) { + milstr_ncpy(np2cfg.sasihdd[i], "", MAX_PATH); + } +#endif +#if defined(SUPPORT_SCSI) + for(i = 0; i < 4; i++) { + milstr_ncpy(np2cfg.scsihdd[i], "", MAX_PATH); + } +#endif + } +#endif /* __LIBRETRO__ */ + for (i = 1; i < argc; i++) { + if (OEMSTRLEN(argv[i]) < 5) { + continue; + } + + if(argv[i][0] == '"' && argv[i][OEMSTRLEN(argv[i]) - 1] == '"') { + argv[i]++; + argv[i][OEMSTRLEN(argv[i]) - 1] = '\0'; + } + + imagetype = IMAGETYPE_UNKNOWN; + np2_main_getfullpath(fullpath, argv[i], base_dir); + ext = fullpath + (OEMSTRLEN(fullpath) - 4); + +#if !defined(__LIBRETRO__) + if(milstr_cmp(ext, ".m3u") == 0) { + imagetype = IMAGETYPE_OTHER; + np2_main_read_m3u(fullpath); + } +#endif + + if(np2_isfdimage(fullpath, OEMSTRLEN(fullpath))) { + imagetype = IMAGETYPE_FDD; + milstr_ncpy(np2_main_disk_images_paths[np2_main_disk_images_count], fullpath, MAX_PATH); + np2_main_disk_images_count++; + } +#if defined(__LIBRETRO__) + attach_disk_swap_interface(); +#endif + +#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) || defined(SUPPORT_SCSI) + if(imagetype == IMAGETYPE_UNKNOWN) { +#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) + if (milstr_cmp(ext, ".hdi") == 0) imagetype = IMAGETYPE_SASI_IDE; // SASI/IDE + else if (milstr_cmp(ext, ".thd") == 0) imagetype = IMAGETYPE_SASI_IDE; + else if (milstr_cmp(ext, ".nhd") == 0) imagetype = IMAGETYPE_SASI_IDE; + else if (milstr_cmp(ext, ".vhd") == 0) imagetype = IMAGETYPE_SASI_IDE; + else if (milstr_cmp(ext, ".sln") == 0) imagetype = IMAGETYPE_SASI_IDE; + else if (milstr_cmp(ext, ".iso") == 0) imagetype = IMAGETYPE_SASI_IDE_CD; // SASI/IDE CD + else if (milstr_cmp(ext, ".cue") == 0) imagetype = IMAGETYPE_SASI_IDE_CD; + else if (milstr_cmp(ext, ".ccd") == 0) imagetype = IMAGETYPE_SASI_IDE_CD; + else if (milstr_cmp(ext, ".mds") == 0) imagetype = IMAGETYPE_SASI_IDE_CD; + else if (milstr_cmp(ext, ".nrg") == 0) imagetype = IMAGETYPE_SASI_IDE_CD; +#endif +#if defined(SUPPORT_SCSI) + if (milstr_cmp(ext, ".hdd") == 0) imagetype = IMAGETYPE_SCSI; // SCSI + else if (milstr_cmp(ext, ".hdn") == 0) imagetype = IMAGETYPE_SCSI; +#endif + switch (imagetype) { +#if defined(SUPPORT_IDEIO) || defined(SUPPORT_SASI) + case IMAGETYPE_SASI_IDE: + for(j = 0; j < 4; j++) { + if(np2cfg.idetype[j] == SXSIDEV_HDD) { + if(!(setmedia & (1 << j))) { + milstr_ncpy(np2cfg.sasihdd[j], fullpath, MAX_PATH); + setmedia |= 1 << j; + HDCount++; + break; + } + } + } + break; + case IMAGETYPE_SASI_IDE_CD: + if(np2_main_cd_images_count < sizeof(np2_main_cd_images_paths) / MAX_PATH) { + milstr_ncpy(np2_main_cd_images_paths[np2_main_cd_images_count], fullpath, MAX_PATH); + for(j = 0; j < 4; j++) { + if(np2cfg.idetype[j] == SXSIDEV_CDROM) { + if(!(setmedia & (1 << j))) { + np2_main_cd_drv[np2_main_cd_images_count] = j; + setmedia |= 1 << j; + } + break; + } + } + np2_main_cd_images_count++; + } + break; +#endif +#if defined(SUPPORT_SCSI) + case IMAGETYPE_SCSI: + if(drvhddSCSI < 4) { + milstr_ncpy(np2cfg.scsihdd[drvhddSCSI], fullpath, MAX_PATH); + drvhddSCSI++; + } + break; +#endif + } + } +#endif + } + + TRACEINIT(); + + if (fontmng_init() != SUCCESS) { + goto np2main_err2; + } + inputmng_init(); + keystat_initialize(); + + if (sysmenu_create() != SUCCESS) { + goto np2main_err3; + } + +#if !defined(__LIBRETRO__) + joymng_initialize(); +#endif /* __LIBRETRO__ */ + mousemng_initialize(); + + scrnmng_initialize(); + if (scrnmng_create(0) != SUCCESS) { + goto np2main_err4; + } + + soundmng_initialize(); + commng_initialize(); + sysmng_initialize(); + taskmng_initialize(); + pccore_init(); + S98_init(); + +#if defined(SUPPORT_NET) + np2net_init(); +#endif +#ifdef SUPPORT_WAB + np2wab_init(); +#endif +#ifdef SUPPORT_CL_GD5430 + pc98_cirrus_vga_init(); +#endif +#if !defined(__LIBRETRO__) + mousemng_hidecursor(); +#endif /* __LIBRETRO__ */ + scrndraw_redraw(); + pccore_reset(); + +#if defined(SUPPORT_RESUME) + if (np2oscfg.resume) { + id = flagload(str_sav, str_resume, FALSE); + if (id == DID_CANCEL) { + goto np2main_err5; + } + } +#endif /* defined(SUPPORT_RESUME) */ + + for (i = 0; i < np2_main_cd_images_count; i++) { + if (i < 1) { + sxsi_devopen(np2_main_cd_drv[i], np2_main_cd_images_paths[i]); + } + } + + drvfdd = 0; + for (i = 0; i < np2_main_disk_images_count; i++) { + if (i < 2) { + diskdrv_setfdd(i, np2_main_disk_images_paths[i], 0); + } + } + +//printf("bd:%s\n",base_dir); +//printf("fdin:%d\n",drvfdd); +//printf("hdin:%d\n",HDCount); +//printf("cdin:%d\n",CDCount); + +#if defined(__LIBRETRO__) + return(SUCCESS); + +#if defined(SUPPORT_RESUME) +np2main_err5: + pccore_term(); + S98_trash(); + soundmng_deinitialize(); +#endif /* defined(SUPPORT_RESUME) */ + +np2main_err4: + scrnmng_destroy(); + +np2main_err3: + sysmenu_destroy(); + +np2main_err2: + TRACETERM(); + //SDL_Quit(); + +np2main_err1: + return(FAILURE); +} + +int np2_end(){ +#else /* __LIBRETRO__ */ + np2exec(); + +#endif /* __LIBRETRO__ */ + + pccore_cfgupdate(); +#if defined(SUPPORT_RESUME) + if (np2oscfg.resume) { + flagsave(str_sav); + } + else { + flagdelete(str_sav); + } +#endif +#if !defined(__LIBRETRO__) + joymng_deinitialize(); +#endif /* __LIBRETRO__ */ +#if defined(SUPPORT_NET) + np2net_shutdown(); +#endif +#ifdef SUPPORT_CL_GD5430 + pc98_cirrus_vga_shutdown(); +#endif +#ifdef SUPPORT_WAB + np2wab_shutdown(); +#endif + pccore_term(); + S98_trash(); + soundmng_deinitialize(); + + sysmng_deinitialize(); + + scrnmng_destroy(); + sysmenu_destroy(); +#if defined(SUPPORT_WAB) + wabwin_writeini(); + np2wabcfg.readonly = np2oscfg.readonly; +#endif // defined(SUPPORT_WAB) + TRACETERM(); +#if !defined(__LIBRETRO__) + SDL_Quit(); +#endif /* __LIBRETRO__ */ + return(SUCCESS); + +#if !defined(__LIBRETRO__) +#if defined(SUPPORT_RESUME) +np2main_err5: + pccore_term(); + S98_trash(); + soundmng_deinitialize(); +#endif /* defined(SUPPORT_RESUME) */ + +np2main_err4: + scrnmng_destroy(); + +np2main_err3: + sysmenu_destroy(); + +np2main_err2: + TRACETERM(); + SDL_Quit(); + +np2main_err1: + return(FAILURE); +#endif /* __LIBRETRO__ */ +} + +int mmxflag; + +int +havemmx(void) +{ +#if !defined(GCC_CPU_ARCH_IA32) + return 0; +#else /* GCC_CPU_ARCH_IA32 */ + int rv; + +#if defined(GCC_CPU_ARCH_AMD64) || defined(__ANDROID__) + rv = 1; +#else /* !GCC_CPU_ARCH_AMD64 */ + asm volatile ( + "pushf;" + "popl %%eax;" + "movl %%eax, %%edx;" + "xorl $0x00200000, %%eax;" + "pushl %%eax;" + "popf;" + "pushf;" + "popl %%eax;" + "subl %%edx, %%eax;" + "je .nocpuid;" + "xorl %%eax, %%eax;" + "incl %%eax;" + "pushl %%ebx;" + "cpuid;" + "popl %%ebx;" + "movl %%edx, %0;" + "andl $0x00800000, %0;" + ".nocpuid:" + : "=a" (rv)); +#endif /* GCC_CPU_ARCH_AMD64 */ + return rv; +#endif /* GCC_CPU_ARCH_IA32 */ +} + +static void np2exec() +{ + while(taskmng_isavail()) { +#if !defined(__LIBRETRO__) + if(g_u8ControlState == 1) { + statsave_save_d(); + } else if(g_u8ControlState == 2) { + statsave_load_d(); + } + g_u8ControlState = 0; +#endif + + taskmng_rol(); +#if defined(EMSCRIPTEN) && !defined(__LIBRETRO__) +// emscripten_sleep_with_yield(0); + emscripten_sleep(0); +#endif + if (np2oscfg.NOWAIT) { + joymng_sync(); + pccore_exec(framecnt == 0); + if (np2oscfg.DRAW_SKIP) { // nowait frame skip + framecnt++; + if (framecnt >= np2oscfg.DRAW_SKIP) { + processwait(0); + } + } + else { // nowait auto skip + framecnt = 1; + if (timing_getcount()) { + processwait(0); + } + } + } + else if (np2oscfg.DRAW_SKIP) { // frame skip + if (framecnt < np2oscfg.DRAW_SKIP) { + joymng_sync(); + pccore_exec(framecnt == 0); + framecnt++; + } + else { + processwait(np2oscfg.DRAW_SKIP); + } + } + else { // auto skip + if (!waitcnt) { + UINT cnt; + joymng_sync(); + pccore_exec(framecnt == 0); + framecnt++; + cnt = timing_getcount(); + if (framecnt > cnt) { + waitcnt = framecnt; + if (framemax > 1) { + framemax--; + } + } + else if (framecnt >= framemax) { + if (framemax < 12) { + framemax++; + } + if (cnt >= 12) { + timing_reset(); + } + else { + timing_setcount(cnt - framecnt); + } + framereset(0); + } + } + else { + processwait(waitcnt); + waitcnt = framecnt; + } + } + } +} diff --git a/sdl/oemtext.h b/sdl/oemtext.h old mode 100755 new mode 100644 index 6f7e465b..7ffa7036 --- a/sdl/oemtext.h +++ b/sdl/oemtext.h @@ -1,19 +1,19 @@ -/** - * @file oemtext.h - * @breif defines converter - */ - -#pragma once - -#include - -#define oemtext_oemtosjis(a, b, c, d) codecnv_utf8tosjis(a, b, c, d) -#define oemtext_sjistooem(a, b, c, d) codecnv_sjistoutf8(a, b, c, d) - -#ifdef __cplusplus -#include -namespace std -{ - typedef string oemstring; -} -#endif /* __cplusplus */ +/** + * @file oemtext.h + * @breif defines converter + */ + +#pragma once + +#include + +#define oemtext_oemtosjis(a, b, c, d) codecnv_utf8tosjis(a, b, c, d) +#define oemtext_sjistooem(a, b, c, d) codecnv_sjistoutf8(a, b, c, d) + +#ifdef __cplusplus +#include +namespace std +{ + typedef string oemstring; +} +#endif /* __cplusplus */ diff --git a/sdl/sysmenu.h b/sdl/sysmenu.h old mode 100755 new mode 100644 index 4ca19638..8f4516d4 --- a/sdl/sysmenu.h +++ b/sdl/sysmenu.h @@ -1,19 +1,19 @@ - -enum { - MENUTYPE_NORMAL = 0 -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT sysmenu_create(void); -void sysmenu_destroy(void); - -BRESULT sysmenu_menuopen(UINT menutype, int x, int y); - -#ifdef __cplusplus -} -#endif - + +enum { + MENUTYPE_NORMAL = 0 +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT sysmenu_create(void); +void sysmenu_destroy(void); + +BRESULT sysmenu_menuopen(UINT menutype, int x, int y); + +#ifdef __cplusplus +} +#endif + diff --git a/sdl/sysmng.h b/sdl/sysmng.h old mode 100755 new mode 100644 index e58eb0d7..fe23c4fa --- a/sdl/sysmng.h +++ b/sdl/sysmng.h @@ -1,60 +1,60 @@ -/** - * @file sysmng.h - * @brief Interface of the system - */ - -#ifndef NP2_SYSMNG_H -#define NP2_SYSMNG_H - -// どーでもいい通知系 - -enum { - SYS_UPDATECFG = 0x0001, - SYS_UPDATEOSCFG = 0x0002, - SYS_UPDATECLOCK = 0x0004, - SYS_UPDATERATE = 0x0008, - SYS_UPDATESBUF = 0x0010, - SYS_UPDATEMIDI = 0x0020, - SYS_UPDATESBOARD = 0x0040, - SYS_UPDATEFDD = 0x0080, - SYS_UPDATEHDD = 0x0100, - SYS_UPDATEMEMORY = 0x0200, - SYS_UPDATESERIAL1 = 0x0400 -}; - -enum { - SYS_UPDATECAPTION_FDD = 0x01, - SYS_UPDATECAPTION_CLK = 0x02, - SYS_UPDATECAPTION_MISC = 0x04, - - SYS_UPDATECAPTION_ALL = 0xff, -}; - -typedef struct { - UINT8 showvolume; - UINT8 showmousespeed; -} SYSMNGMISCINFO; - -#ifdef __cplusplus -extern "C" { -#endif - -extern UINT sys_updates; - -extern SYSMNGMISCINFO sys_miscinfo; - -void sysmng_initialize(void); -void sysmng_deinitialize(void); - -void sysmng_update(UINT update); -void sysmng_cpureset(void); -#define sysmng_fddaccess(a) -#define sysmng_hddaccess(a) -void sysmng_updatecaption(UINT8 flag); - -#ifdef __cplusplus -} -#endif - -#endif /* NP2_SYSMNG_H */ - +/** + * @file sysmng.h + * @brief Interface of the system + */ + +#ifndef NP2_SYSMNG_H +#define NP2_SYSMNG_H + +// どーでもいい通知系 + +enum { + SYS_UPDATECFG = 0x0001, + SYS_UPDATEOSCFG = 0x0002, + SYS_UPDATECLOCK = 0x0004, + SYS_UPDATERATE = 0x0008, + SYS_UPDATESBUF = 0x0010, + SYS_UPDATEMIDI = 0x0020, + SYS_UPDATESBOARD = 0x0040, + SYS_UPDATEFDD = 0x0080, + SYS_UPDATEHDD = 0x0100, + SYS_UPDATEMEMORY = 0x0200, + SYS_UPDATESERIAL1 = 0x0400 +}; + +enum { + SYS_UPDATECAPTION_FDD = 0x01, + SYS_UPDATECAPTION_CLK = 0x02, + SYS_UPDATECAPTION_MISC = 0x04, + + SYS_UPDATECAPTION_ALL = 0xff, +}; + +typedef struct { + UINT8 showvolume; + UINT8 showmousespeed; +} SYSMNGMISCINFO; + +#ifdef __cplusplus +extern "C" { +#endif + +extern UINT sys_updates; + +extern SYSMNGMISCINFO sys_miscinfo; + +void sysmng_initialize(void); +void sysmng_deinitialize(void); + +void sysmng_update(UINT update); +void sysmng_cpureset(void); +#define sysmng_fddaccess(a) +#define sysmng_hddaccess(a) +void sysmng_updatecaption(UINT8 flag); + +#ifdef __cplusplus +} +#endif + +#endif /* NP2_SYSMNG_H */ + diff --git a/sdl/taskmng.h b/sdl/taskmng.h old mode 100755 new mode 100644 index 207a95da..21d8d817 --- a/sdl/taskmng.h +++ b/sdl/taskmng.h @@ -1,17 +1,17 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -extern BOOL task_avail; - -void taskmng_initialize(void); -void taskmng_exit(void); -void taskmng_rol(void); -#define taskmng_isavail() (task_avail) -BOOL taskmng_sleep(UINT32 tick); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +extern BOOL task_avail; + +void taskmng_initialize(void); +void taskmng_exit(void); +void taskmng_rol(void); +#define taskmng_isavail() (task_avail) +BOOL taskmng_sleep(UINT32 tick); + +#ifdef __cplusplus +} +#endif + diff --git a/sdl/timemng.h b/sdl/timemng.h old mode 100755 new mode 100644 index 6d3999ad..58a2a1f7 --- a/sdl/timemng.h +++ b/sdl/timemng.h @@ -1,25 +1,25 @@ - -// Win32 SYSTEMTIME ストラクチャ - -typedef struct { - UINT16 year; - UINT16 month; - UINT16 week; - UINT16 day; - UINT16 hour; - UINT16 minute; - UINT16 second; - UINT16 milli; -} _SYSTIME; - - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT timemng_gettime(_SYSTIME *systime); - -#ifdef __cplusplus -} -#endif - + +// Win32 SYSTEMTIME ストラクチャ + +typedef struct { + UINT16 year; + UINT16 month; + UINT16 week; + UINT16 day; + UINT16 hour; + UINT16 minute; + UINT16 second; + UINT16 milli; +} _SYSTIME; + + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT timemng_gettime(_SYSTIME *systime); + +#ifdef __cplusplus +} +#endif + diff --git a/sdl/trace.c b/sdl/trace.c old mode 100755 new mode 100644 index 98790c43..10c35c4e --- a/sdl/trace.c +++ b/sdl/trace.c @@ -1,33 +1,33 @@ -#include -#include -#if defined(WIN32) && defined(OSLANG_EUC) -#include -#endif - -#ifdef TRACE -void trace_init(void) { -} - -void trace_term(void) { -} - -void trace_fmt(const char *fmt, ...) { - - va_list ap; - char buf[1024]; -#if defined(WIN32) && defined(OSLANG_EUC) - char sjis[1024]; -#endif - - va_start(ap, fmt); - vsprintf(buf, fmt, ap); - va_end(ap); -#if defined(WIN32) && defined(OSLANG_EUC) - codecnv_euctosjis(sjis, NELEMENTS(sjis), buf, (UINT)-1); - printf("%s\n", sjis); -#else - printf("%s\n", buf); -#endif -} -#endif - +#include +#include +#if defined(WIN32) && defined(OSLANG_EUC) +#include +#endif + +#ifdef TRACE +void trace_init(void) { +} + +void trace_term(void) { +} + +void trace_fmt(const char *fmt, ...) { + + va_list ap; + char buf[1024]; +#if defined(WIN32) && defined(OSLANG_EUC) + char sjis[1024]; +#endif + + va_start(ap, fmt); + vsprintf(buf, fmt, ap); + va_end(ap); +#if defined(WIN32) && defined(OSLANG_EUC) + codecnv_euctosjis(sjis, NELEMENTS(sjis), buf, (UINT)-1); + printf("%s\n", sjis); +#else + printf("%s\n", buf); +#endif +} +#endif + diff --git a/sdl/trace.h b/sdl/trace.h old mode 100755 new mode 100644 index 70d046b2..b464db38 --- a/sdl/trace.h +++ b/sdl/trace.h @@ -1,29 +1,29 @@ - -#ifndef TRACE - -#define TRACEINIT() -#define TRACETERM() -#define TRACEOUT(a) -#define VERBOSE(a) - -#else - -#ifdef __cplusplus -extern "C" { -#endif - -void trace_init(void); -void trace_term(void); -void trace_fmt(const char *str, ...); - -#define TRACEINIT() trace_init() -#define TRACETERM() trace_term() -#define TRACEOUT(arg) trace_fmt arg -#define VERBOSE(arg) trace_fmt arg - -#ifdef __cplusplus -}; -#endif - -#endif - + +#ifndef TRACE + +#define TRACEINIT() +#define TRACETERM() +#define TRACEOUT(a) +#define VERBOSE(a) + +#else + +#ifdef __cplusplus +extern "C" { +#endif + +void trace_init(void); +void trace_term(void); +void trace_fmt(const char *str, ...); + +#define TRACEINIT() trace_init() +#define TRACETERM() trace_term() +#define TRACEOUT(arg) trace_fmt arg +#define VERBOSE(arg) trace_fmt arg + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/sdl/windows/main.c b/sdl/windows/main.c old mode 100755 new mode 100644 index 3b94efc9..b3657b95 --- a/sdl/windows/main.c +++ b/sdl/windows/main.c @@ -1,33 +1,33 @@ -/** - * @file main.c - * @brief メイン - */ - -#include -#include -#include "..\fontmng.h" - -#pragma comment(lib, "SDL2.lib") -#pragma comment(lib, "SDL2main.lib") - -#if !defined(RESOURCE_US) -#pragma comment(lib, "SDL2_ttf.lib") -#endif - -/** - * メイン - * @param[in] argc 引数 - * @param[in] argv 引数 - * @return リザルト コード - */ -int main(int argc, char *argv[]) -{ - UINT nLength; - TCHAR szFont[MAX_PATH]; - - nLength = GetWindowsDirectory(szFont, SDL_arraysize(szFont)); - lstrcpy(szFont + nLength, TEXT("\\Fonts\\msgothic.ttc")); - fontmng_setdeffontname(szFont); - - return np2_main(argc, argv); -} +/** + * @file main.c + * @brief メイン + */ + +#include +#include +#include "..\fontmng.h" + +#pragma comment(lib, "SDL2.lib") +#pragma comment(lib, "SDL2main.lib") + +#if !defined(RESOURCE_US) +#pragma comment(lib, "SDL2_ttf.lib") +#endif + +/** + * メイン + * @param[in] argc 引数 + * @param[in] argv 引数 + * @return リザルト コード + */ +int main(int argc, char *argv[]) +{ + UINT nLength; + TCHAR szFont[MAX_PATH]; + + nLength = GetWindowsDirectory(szFont, SDL_arraysize(szFont)); + lstrcpy(szFont + nLength, TEXT("\\Fonts\\msgothic.ttc")); + fontmng_setdeffontname(szFont); + + return np2_main(argc, argv); +} diff --git a/sound/adpcm.h b/sound/adpcm.h old mode 100755 new mode 100644 index 69765db2..d2ad20c2 --- a/sound/adpcm.h +++ b/sound/adpcm.h @@ -1,85 +1,85 @@ -/** - * @file adpcm.h - * @brief Interface of the OPNA ADPCM - */ - -#pragma once - -#include - -enum { - ADTIMING_BIT = 11, - ADTIMING = (1 << ADTIMING_BIT), - ADPCM_SHIFT = 3 -}; - -typedef struct { - UINT8 ctrl1; // 00 - UINT8 ctrl2; // 01 - UINT8 start[2]; // 02 - UINT8 stop[2]; // 04 - UINT8 reg06; - UINT8 reg07; - UINT8 data; // 08 - UINT8 delta[2]; // 09 - UINT8 level; // 0b - UINT8 limit[2]; // 0c - UINT8 reg0e; - UINT8 reg0f; - UINT8 flag; // 10 - UINT8 reg11; - UINT8 reg12; - UINT8 reg13; -} ADPCMREG; - -typedef struct { - ADPCMREG reg; - UINT32 pos; - UINT32 start; - UINT32 stop; - UINT32 limit; - SINT32 level; - UINT32 base; - SINT32 samp; - SINT32 delta; - SINT32 remain; - SINT32 step; - SINT32 out0; - SINT32 out1; - SINT32 fb; - SINT32 pertim; - UINT8 status; - UINT8 play; - UINT8 mask; - UINT8 fifopos; - UINT8 fifo[2]; - UINT8 padding[2]; - UINT8 buf[0x40000]; -} _ADPCM, *ADPCM; - -typedef struct { - UINT rate; - UINT vol; -} ADPCMCFG; - - -#ifdef __cplusplus -extern "C" { -#endif - -void adpcm_initialize(UINT rate); -void adpcm_setvol(UINT vol); - -void adpcm_reset(ADPCM ad); -void adpcm_update(ADPCM ad); -void adpcm_setreg(ADPCM ad, UINT reg, REG8 value); -REG8 adpcm_status(ADPCM ad); - -REG8 SOUNDCALL adpcm_readsample(ADPCM ad); -void SOUNDCALL adpcm_datawrite(ADPCM ad, REG8 data); -void SOUNDCALL adpcm_getpcm(ADPCM ad, SINT32 *buf, UINT count); -void SOUNDCALL adpcm_getpcm_dummy(ADPCM ad, SINT32 *buf, UINT count); - -#ifdef __cplusplus -} -#endif +/** + * @file adpcm.h + * @brief Interface of the OPNA ADPCM + */ + +#pragma once + +#include + +enum { + ADTIMING_BIT = 11, + ADTIMING = (1 << ADTIMING_BIT), + ADPCM_SHIFT = 3 +}; + +typedef struct { + UINT8 ctrl1; // 00 + UINT8 ctrl2; // 01 + UINT8 start[2]; // 02 + UINT8 stop[2]; // 04 + UINT8 reg06; + UINT8 reg07; + UINT8 data; // 08 + UINT8 delta[2]; // 09 + UINT8 level; // 0b + UINT8 limit[2]; // 0c + UINT8 reg0e; + UINT8 reg0f; + UINT8 flag; // 10 + UINT8 reg11; + UINT8 reg12; + UINT8 reg13; +} ADPCMREG; + +typedef struct { + ADPCMREG reg; + UINT32 pos; + UINT32 start; + UINT32 stop; + UINT32 limit; + SINT32 level; + UINT32 base; + SINT32 samp; + SINT32 delta; + SINT32 remain; + SINT32 step; + SINT32 out0; + SINT32 out1; + SINT32 fb; + SINT32 pertim; + UINT8 status; + UINT8 play; + UINT8 mask; + UINT8 fifopos; + UINT8 fifo[2]; + UINT8 padding[2]; + UINT8 buf[0x40000]; +} _ADPCM, *ADPCM; + +typedef struct { + UINT rate; + UINT vol; +} ADPCMCFG; + + +#ifdef __cplusplus +extern "C" { +#endif + +void adpcm_initialize(UINT rate); +void adpcm_setvol(UINT vol); + +void adpcm_reset(ADPCM ad); +void adpcm_update(ADPCM ad); +void adpcm_setreg(ADPCM ad, UINT reg, REG8 value); +REG8 adpcm_status(ADPCM ad); + +REG8 SOUNDCALL adpcm_readsample(ADPCM ad); +void SOUNDCALL adpcm_datawrite(ADPCM ad, REG8 data); +void SOUNDCALL adpcm_getpcm(ADPCM ad, SINT32 *buf, UINT count); +void SOUNDCALL adpcm_getpcm_dummy(ADPCM ad, SINT32 *buf, UINT count); + +#ifdef __cplusplus +} +#endif diff --git a/sound/adpcmc.c b/sound/adpcmc.c old mode 100755 new mode 100644 index 36a5276a..682229ba --- a/sound/adpcmc.c +++ b/sound/adpcmc.c @@ -1,129 +1,129 @@ -/** - * @file adpcmc.c - * @brief Implementation of the OPNA ADPCM - */ - -#include -#include "adpcm.h" -#include - - ADPCMCFG adpcmcfg; - -void adpcm_initialize(UINT rate) { - - adpcmcfg.rate = rate; -} - -void adpcm_setvol(UINT vol) { - - adpcmcfg.vol = vol; -} - -void adpcm_reset(ADPCM ad) { - - memset(ad, 0, sizeof(*ad)); - ad->mask = 0; // (UINT8)~0x1c; - ad->delta = 127; - STOREINTELWORD(ad->reg.stop, 0x0002); - STOREINTELWORD(ad->reg.limit, 0xffff); - ad->stop = 0x000060; - ad->limit = 0x200000; - adpcm_update(ad); -} - -void adpcm_update(ADPCM ad) { - - UINT32 addr; - - if (adpcmcfg.rate) { - ad->base = ADTIMING * (OPNA_CLOCK / 72) / adpcmcfg.rate; - } - addr = LOADINTELWORD(ad->reg.delta); - addr = (addr * ad->base) >> 16; - if (addr < 0x80) { - addr = 0x80; - } - ad->step = addr; - ad->pertim = (1 << (ADTIMING_BIT * 2)) / addr; - ad->level = (ad->reg.level * adpcmcfg.vol) >> 4; -} - -void adpcm_setreg(ADPCM ad, UINT reg, REG8 value) { - - UINT32 addr; - - sound_sync(); - ((UINT8 *)(&ad->reg))[reg] = value; - switch(reg) { - case 0x00: // control1 - if ((value & 0x80) && (!ad->play)) { - ad->play = 0x20; - ad->pos = ad->start; - ad->samp = 0; - ad->delta = 127; - ad->remain = 0; - } - if (value & 1) { - ad->play = 0; - } - break; - - case 0x01: // control2 - break; - - case 0x02: case 0x03: // start address - addr = (LOADINTELWORD(ad->reg.start)) << 5; - ad->pos = addr; - ad->start = addr; - break; - - case 0x04: case 0x05: // stop address - addr = (LOADINTELWORD(ad->reg.stop) + 1) << 5; - ad->stop = addr; - break; - - case 0x08: // data - if ((ad->reg.ctrl1 & 0x60) == 0x60) { - adpcm_datawrite(ad, value); - } - break; - - case 0x09: case 0x0a: // delta - addr = LOADINTELWORD(ad->reg.delta); - addr = (addr * ad->base) >> 16; - if (addr < 0x80) { - addr = 0x80; - } - ad->step = addr; - ad->pertim = (1 << (ADTIMING_BIT * 2)) / addr; - break; - - case 0x0b: // level - ad->level = (value * adpcmcfg.vol) >> 4; - break; - - case 0x0c: case 0x0d: // limit address - addr = (LOADINTELWORD(ad->reg.limit) + 1) << 5; - ad->limit = addr; - break; - - case 0x0e: // DAC data - ad->status |= 0x04; // EOS - break; - - case 0x10: // flag - if (value & 0x80) { - ad->status = 0; - } - else { - ad->mask = ~(value & 0x1f); - } - break; - } -} - -REG8 adpcm_status(ADPCM ad) { - - return(((ad->status | 8) & ad->mask) | ad->play); -} - +/** + * @file adpcmc.c + * @brief Implementation of the OPNA ADPCM + */ + +#include +#include "adpcm.h" +#include + + ADPCMCFG adpcmcfg; + +void adpcm_initialize(UINT rate) { + + adpcmcfg.rate = rate; +} + +void adpcm_setvol(UINT vol) { + + adpcmcfg.vol = vol; +} + +void adpcm_reset(ADPCM ad) { + + memset(ad, 0, sizeof(*ad)); + ad->mask = 0; // (UINT8)~0x1c; + ad->delta = 127; + STOREINTELWORD(ad->reg.stop, 0x0002); + STOREINTELWORD(ad->reg.limit, 0xffff); + ad->stop = 0x000060; + ad->limit = 0x200000; + adpcm_update(ad); +} + +void adpcm_update(ADPCM ad) { + + UINT32 addr; + + if (adpcmcfg.rate) { + ad->base = ADTIMING * (OPNA_CLOCK / 72) / adpcmcfg.rate; + } + addr = LOADINTELWORD(ad->reg.delta); + addr = (addr * ad->base) >> 16; + if (addr < 0x80) { + addr = 0x80; + } + ad->step = addr; + ad->pertim = (1 << (ADTIMING_BIT * 2)) / addr; + ad->level = (ad->reg.level * adpcmcfg.vol) >> 4; +} + +void adpcm_setreg(ADPCM ad, UINT reg, REG8 value) { + + UINT32 addr; + + sound_sync(); + ((UINT8 *)(&ad->reg))[reg] = value; + switch(reg) { + case 0x00: // control1 + if ((value & 0x80) && (!ad->play)) { + ad->play = 0x20; + ad->pos = ad->start; + ad->samp = 0; + ad->delta = 127; + ad->remain = 0; + } + if (value & 1) { + ad->play = 0; + } + break; + + case 0x01: // control2 + break; + + case 0x02: case 0x03: // start address + addr = (LOADINTELWORD(ad->reg.start)) << 5; + ad->pos = addr; + ad->start = addr; + break; + + case 0x04: case 0x05: // stop address + addr = (LOADINTELWORD(ad->reg.stop) + 1) << 5; + ad->stop = addr; + break; + + case 0x08: // data + if ((ad->reg.ctrl1 & 0x60) == 0x60) { + adpcm_datawrite(ad, value); + } + break; + + case 0x09: case 0x0a: // delta + addr = LOADINTELWORD(ad->reg.delta); + addr = (addr * ad->base) >> 16; + if (addr < 0x80) { + addr = 0x80; + } + ad->step = addr; + ad->pertim = (1 << (ADTIMING_BIT * 2)) / addr; + break; + + case 0x0b: // level + ad->level = (value * adpcmcfg.vol) >> 4; + break; + + case 0x0c: case 0x0d: // limit address + addr = (LOADINTELWORD(ad->reg.limit) + 1) << 5; + ad->limit = addr; + break; + + case 0x0e: // DAC data + ad->status |= 0x04; // EOS + break; + + case 0x10: // flag + if (value & 0x80) { + ad->status = 0; + } + else { + ad->mask = ~(value & 0x1f); + } + break; + } +} + +REG8 adpcm_status(ADPCM ad) { + + return(((ad->status | 8) & ad->mask) | ad->play); +} + diff --git a/sound/adpcmg.c b/sound/adpcmg.c old mode 100755 new mode 100644 index 667bbda2..e22a4f27 --- a/sound/adpcmg.c +++ b/sound/adpcmg.c @@ -1,360 +1,360 @@ -/** - * @file adpcmg.c - * @brief Implementation of the OPNA ADPCM - */ - -#include -#include "adpcm.h" - -#define ADPCM_NBR 0x80000000 - -static const UINT adpcmdeltatable[8] = { - // 0.89, 0.89, 0.89, 0.89, 1.2, 1.6, 2.0, 2.4 - 228, 228, 228, 228, 308, 408, 512, 612}; - - -REG8 SOUNDCALL adpcm_readsample(ADPCM ad) { - - UINT32 pos; - REG8 data; - REG8 ret; - - if ((ad->reg.ctrl1 & 0x60) == 0x20) { - pos = ad->pos & 0x1fffff; - if (!(ad->reg.ctrl2 & 2)) { - data = ad->buf[pos >> 3]; - pos += 8; - } - else { - const UINT8 *ptr; - REG8 bit; - UINT tmp; - ptr = ad->buf + ((pos >> 3) & 0x7fff); - bit = 1 << (pos & 7); - tmp = (ptr[0x00000] & bit); - tmp += (ptr[0x08000] & bit) << 1; - tmp += (ptr[0x10000] & bit) << 2; - tmp += (ptr[0x18000] & bit) << 3; - tmp += (ptr[0x20000] & bit) << 4; - tmp += (ptr[0x28000] & bit) << 5; - tmp += (ptr[0x30000] & bit) << 6; - tmp += (ptr[0x38000] & bit) << 7; - data = (REG8)(tmp >> (pos & 7)); - pos++; - } - if (pos != ad->stop) { - pos &= 0x1fffff; - ad->status |= 4; - } - if (pos >= ad->limit) { - pos = 0; - } - ad->pos = pos; - } - else { - data = 0; - } - pos = ad->fifopos; - ret = ad->fifo[ad->fifopos]; - ad->fifo[ad->fifopos] = data; - ad->fifopos ^= 1; - return(ret); -} - -void SOUNDCALL adpcm_datawrite(ADPCM ad, REG8 data) { - - UINT32 pos; - - pos = ad->pos & 0x1fffff; - if (!(ad->reg.ctrl2 & 2)) { - ad->buf[pos >> 3] = data; - pos += 8; - } - else { - UINT8 *ptr; - UINT8 bit; - UINT8 mask; - ptr = ad->buf + ((pos >> 3) & 0x7fff); - bit = 1 << (pos & 7); - mask = ~bit; - ptr[0x00000] &= mask; - if (data & 0x01) { - ptr[0x00000] |= bit; - } - ptr[0x08000] &= mask; - if (data & 0x02) { - ptr[0x08000] |= bit; - } - ptr[0x10000] &= mask; - if (data & 0x04) { - ptr[0x10000] |= bit; - } - ptr[0x18000] &= mask; - if (data & 0x08) { - ptr[0x18000] |= bit; - } - ptr[0x20000] &= mask; - if (data & 0x10) { - ptr[0x20000] |= bit; - } - ptr[0x28000] &= mask; - if (data & 0x20) { - ptr[0x28000] |= bit; - } - ptr[0x30000] &= mask; - if (data & 0x40) { - ptr[0x30000] |= bit; - } - ptr[0x38000] &= mask; - if (data & 0x80) { - ptr[0x38000] |= bit; - } - pos++; - } - if (pos == ad->stop) { - pos &= 0x1fffff; - ad->status |= 4; - } - if (pos >= ad->limit) { - pos = 0; - } - ad->pos = pos; -} - -static void SOUNDCALL getadpcmdata(ADPCM ad) { - - UINT32 pos; - UINT data; - UINT dir; - SINT32 dlt; - SINT32 samp; - - pos = ad->pos; - if (!(ad->reg.ctrl2 & 2)) { - data = ad->buf[(pos >> 3) & 0x3ffff]; - if (!(pos & ADPCM_NBR)) { - data >>= 4; - } - pos += ADPCM_NBR + 4; - } - else { - const UINT8 *ptr; - REG8 bit; - UINT tmp; - ptr = ad->buf + ((pos >> 3) & 0x7fff); - bit = 1 << (pos & 7); - if (!(pos & ADPCM_NBR)) { - tmp = (ptr[0x20000] & bit); - tmp += (ptr[0x28000] & bit) << 1; - tmp += (ptr[0x30000] & bit) << 2; - tmp += (ptr[0x38000] & bit) << 3; - data = tmp >> (pos & 7); - pos += ADPCM_NBR; - } - else { - tmp = (ptr[0x00000] & bit); - tmp += (ptr[0x08000] & bit) << 1; - tmp += (ptr[0x10000] & bit) << 2; - tmp += (ptr[0x18000] & bit) << 3; - data = tmp >> (pos & 7); - pos += ADPCM_NBR + 1; - } - } - dir = data & 8; - data &= 7; - dlt = adpcmdeltatable[data] * ad->delta; - dlt >>= 8; - if (dlt < 127) { - dlt = 127; - } - else if (dlt > 24000) { - dlt = 24000; - } - samp = ad->delta; - ad->delta = dlt; - samp *= ((data * 2) + 1); - samp >>= ADPCM_SHIFT; - if (!dir) { - samp += ad->samp; - if (samp > 32767) { - samp = 32767; - } - } - else { - samp = ad->samp - samp; - if (samp < -32767) { - samp = -32767; - } - } - ad->samp = samp; - - if (!(pos & ADPCM_NBR)) { - if (pos == ad->stop) { - if (ad->reg.ctrl1 & 0x10) { - pos = ad->start; - ad->samp = 0; - ad->delta = 127; - } - else { - pos &= 0x1fffff; - ad->status |= 4; - ad->play = 0; - } - } - else if (pos >= ad->limit) { - pos = 0; - } - } - ad->pos = pos; - samp *= ad->level; - samp >>= (10 + 1); - ad->out0 = ad->out1; - ad->out1 = samp + ad->fb; - ad->fb = samp >> 1; -} - -void SOUNDCALL adpcm_getpcm(ADPCM ad, SINT32 *pcm, UINT count) { - - SINT32 remain; - SINT32 samp; - - if ((count == 0) || (ad->play == 0)) { - return; - } - remain = ad->remain; - if (ad->step <= ADTIMING) { - do { - if (remain < 0) { - remain += ADTIMING; - getadpcmdata(ad); - if (ad->play == 0) { - if (remain > 0) { - do { - samp = (ad->out0 * remain) >> ADTIMING_BIT; - if (ad->reg.ctrl2 & 0x80) { - pcm[0] += samp; - } - if (ad->reg.ctrl2 & 0x40) { - pcm[1] += samp; - } - pcm += 2; - remain -= ad->step; - } while((remain > 0) && (--count)); - } - goto adpcmstop; - } - } - samp = (ad->out0 * remain) + (ad->out1 * (ADTIMING - remain)); - samp >>= ADTIMING_BIT; - if (ad->reg.ctrl2 & 0x80) { - pcm[0] += samp; - } - if (ad->reg.ctrl2 & 0x40) { - pcm[1] += samp; - } - pcm += 2; - remain -= ad->step; - } while(--count); - } - else { - do { - if (remain > 0) { - samp = ad->out0 * (ADTIMING - remain); - do { - getadpcmdata(ad); - if (ad->play == 0) { - goto adpcmstop; - } - samp += ad->out0 * MIN(remain, ad->pertim); - remain -= ad->pertim; - } while(remain > 0); - } - else { - samp = ad->out0 * ADTIMING; - } - remain += ADTIMING; - samp >>= ADTIMING_BIT; - if (ad->reg.ctrl2 & 0x80) { - pcm[0] += samp; - } - if (ad->reg.ctrl2 & 0x40) { - pcm[1] += samp; - } - pcm += 2; - } while(--count); - } - ad->remain = remain; - return; - -adpcmstop: - ad->out0 = 0; - ad->out1 = 0; - ad->fb = 0; - ad->remain = 0; -} - -/** - * Step adpcm - * @param[in] ad An instance of ADPCM - * @param[out] pcm A pointer to a buffer - * @param[in] count The size of the buffer - */ -void SOUNDCALL adpcm_getpcm_dummy(ADPCM ad, SINT32 *pcm, UINT count) -{ - SINT32 remain; - - if ((count == 0) || (ad->play == 0)) - { - return; - } - remain = ad->remain; - if (ad->step <= ADTIMING) - { - do - { - if (remain < 0) - { - remain += ADTIMING; - getadpcmdata(ad); - if (ad->play == 0) - { - if (remain > 0) - { - do - { - remain -= ad->step; - } while ((remain > 0) && (--count)); - } - goto adpcmstop; - } - } - remain -= ad->step; - } while(--count); - } - else - { - do - { - if (remain > 0) - { - do { - getadpcmdata(ad); - if (ad->play == 0) - { - goto adpcmstop; - } - remain -= ad->pertim; - } while (remain > 0); - } - remain += ADTIMING; - } while (--count); - } - ad->remain = remain; - return; - -adpcmstop: - ad->out0 = 0; - ad->out1 = 0; - ad->fb = 0; - ad->remain = 0; -} +/** + * @file adpcmg.c + * @brief Implementation of the OPNA ADPCM + */ + +#include +#include "adpcm.h" + +#define ADPCM_NBR 0x80000000 + +static const UINT adpcmdeltatable[8] = { + // 0.89, 0.89, 0.89, 0.89, 1.2, 1.6, 2.0, 2.4 + 228, 228, 228, 228, 308, 408, 512, 612}; + + +REG8 SOUNDCALL adpcm_readsample(ADPCM ad) { + + UINT32 pos; + REG8 data; + REG8 ret; + + if ((ad->reg.ctrl1 & 0x60) == 0x20) { + pos = ad->pos & 0x1fffff; + if (!(ad->reg.ctrl2 & 2)) { + data = ad->buf[pos >> 3]; + pos += 8; + } + else { + const UINT8 *ptr; + REG8 bit; + UINT tmp; + ptr = ad->buf + ((pos >> 3) & 0x7fff); + bit = 1 << (pos & 7); + tmp = (ptr[0x00000] & bit); + tmp += (ptr[0x08000] & bit) << 1; + tmp += (ptr[0x10000] & bit) << 2; + tmp += (ptr[0x18000] & bit) << 3; + tmp += (ptr[0x20000] & bit) << 4; + tmp += (ptr[0x28000] & bit) << 5; + tmp += (ptr[0x30000] & bit) << 6; + tmp += (ptr[0x38000] & bit) << 7; + data = (REG8)(tmp >> (pos & 7)); + pos++; + } + if (pos != ad->stop) { + pos &= 0x1fffff; + ad->status |= 4; + } + if (pos >= ad->limit) { + pos = 0; + } + ad->pos = pos; + } + else { + data = 0; + } + pos = ad->fifopos; + ret = ad->fifo[ad->fifopos]; + ad->fifo[ad->fifopos] = data; + ad->fifopos ^= 1; + return(ret); +} + +void SOUNDCALL adpcm_datawrite(ADPCM ad, REG8 data) { + + UINT32 pos; + + pos = ad->pos & 0x1fffff; + if (!(ad->reg.ctrl2 & 2)) { + ad->buf[pos >> 3] = data; + pos += 8; + } + else { + UINT8 *ptr; + UINT8 bit; + UINT8 mask; + ptr = ad->buf + ((pos >> 3) & 0x7fff); + bit = 1 << (pos & 7); + mask = ~bit; + ptr[0x00000] &= mask; + if (data & 0x01) { + ptr[0x00000] |= bit; + } + ptr[0x08000] &= mask; + if (data & 0x02) { + ptr[0x08000] |= bit; + } + ptr[0x10000] &= mask; + if (data & 0x04) { + ptr[0x10000] |= bit; + } + ptr[0x18000] &= mask; + if (data & 0x08) { + ptr[0x18000] |= bit; + } + ptr[0x20000] &= mask; + if (data & 0x10) { + ptr[0x20000] |= bit; + } + ptr[0x28000] &= mask; + if (data & 0x20) { + ptr[0x28000] |= bit; + } + ptr[0x30000] &= mask; + if (data & 0x40) { + ptr[0x30000] |= bit; + } + ptr[0x38000] &= mask; + if (data & 0x80) { + ptr[0x38000] |= bit; + } + pos++; + } + if (pos == ad->stop) { + pos &= 0x1fffff; + ad->status |= 4; + } + if (pos >= ad->limit) { + pos = 0; + } + ad->pos = pos; +} + +static void SOUNDCALL getadpcmdata(ADPCM ad) { + + UINT32 pos; + UINT data; + UINT dir; + SINT32 dlt; + SINT32 samp; + + pos = ad->pos; + if (!(ad->reg.ctrl2 & 2)) { + data = ad->buf[(pos >> 3) & 0x3ffff]; + if (!(pos & ADPCM_NBR)) { + data >>= 4; + } + pos += ADPCM_NBR + 4; + } + else { + const UINT8 *ptr; + REG8 bit; + UINT tmp; + ptr = ad->buf + ((pos >> 3) & 0x7fff); + bit = 1 << (pos & 7); + if (!(pos & ADPCM_NBR)) { + tmp = (ptr[0x20000] & bit); + tmp += (ptr[0x28000] & bit) << 1; + tmp += (ptr[0x30000] & bit) << 2; + tmp += (ptr[0x38000] & bit) << 3; + data = tmp >> (pos & 7); + pos += ADPCM_NBR; + } + else { + tmp = (ptr[0x00000] & bit); + tmp += (ptr[0x08000] & bit) << 1; + tmp += (ptr[0x10000] & bit) << 2; + tmp += (ptr[0x18000] & bit) << 3; + data = tmp >> (pos & 7); + pos += ADPCM_NBR + 1; + } + } + dir = data & 8; + data &= 7; + dlt = adpcmdeltatable[data] * ad->delta; + dlt >>= 8; + if (dlt < 127) { + dlt = 127; + } + else if (dlt > 24000) { + dlt = 24000; + } + samp = ad->delta; + ad->delta = dlt; + samp *= ((data * 2) + 1); + samp >>= ADPCM_SHIFT; + if (!dir) { + samp += ad->samp; + if (samp > 32767) { + samp = 32767; + } + } + else { + samp = ad->samp - samp; + if (samp < -32767) { + samp = -32767; + } + } + ad->samp = samp; + + if (!(pos & ADPCM_NBR)) { + if (pos == ad->stop) { + if (ad->reg.ctrl1 & 0x10) { + pos = ad->start; + ad->samp = 0; + ad->delta = 127; + } + else { + pos &= 0x1fffff; + ad->status |= 4; + ad->play = 0; + } + } + else if (pos >= ad->limit) { + pos = 0; + } + } + ad->pos = pos; + samp *= ad->level; + samp >>= (10 + 1); + ad->out0 = ad->out1; + ad->out1 = samp + ad->fb; + ad->fb = samp >> 1; +} + +void SOUNDCALL adpcm_getpcm(ADPCM ad, SINT32 *pcm, UINT count) { + + SINT32 remain; + SINT32 samp; + + if ((count == 0) || (ad->play == 0)) { + return; + } + remain = ad->remain; + if (ad->step <= ADTIMING) { + do { + if (remain < 0) { + remain += ADTIMING; + getadpcmdata(ad); + if (ad->play == 0) { + if (remain > 0) { + do { + samp = (ad->out0 * remain) >> ADTIMING_BIT; + if (ad->reg.ctrl2 & 0x80) { + pcm[0] += samp; + } + if (ad->reg.ctrl2 & 0x40) { + pcm[1] += samp; + } + pcm += 2; + remain -= ad->step; + } while((remain > 0) && (--count)); + } + goto adpcmstop; + } + } + samp = (ad->out0 * remain) + (ad->out1 * (ADTIMING - remain)); + samp >>= ADTIMING_BIT; + if (ad->reg.ctrl2 & 0x80) { + pcm[0] += samp; + } + if (ad->reg.ctrl2 & 0x40) { + pcm[1] += samp; + } + pcm += 2; + remain -= ad->step; + } while(--count); + } + else { + do { + if (remain > 0) { + samp = ad->out0 * (ADTIMING - remain); + do { + getadpcmdata(ad); + if (ad->play == 0) { + goto adpcmstop; + } + samp += ad->out0 * MIN(remain, ad->pertim); + remain -= ad->pertim; + } while(remain > 0); + } + else { + samp = ad->out0 * ADTIMING; + } + remain += ADTIMING; + samp >>= ADTIMING_BIT; + if (ad->reg.ctrl2 & 0x80) { + pcm[0] += samp; + } + if (ad->reg.ctrl2 & 0x40) { + pcm[1] += samp; + } + pcm += 2; + } while(--count); + } + ad->remain = remain; + return; + +adpcmstop: + ad->out0 = 0; + ad->out1 = 0; + ad->fb = 0; + ad->remain = 0; +} + +/** + * Step adpcm + * @param[in] ad An instance of ADPCM + * @param[out] pcm A pointer to a buffer + * @param[in] count The size of the buffer + */ +void SOUNDCALL adpcm_getpcm_dummy(ADPCM ad, SINT32 *pcm, UINT count) +{ + SINT32 remain; + + if ((count == 0) || (ad->play == 0)) + { + return; + } + remain = ad->remain; + if (ad->step <= ADTIMING) + { + do + { + if (remain < 0) + { + remain += ADTIMING; + getadpcmdata(ad); + if (ad->play == 0) + { + if (remain > 0) + { + do + { + remain -= ad->step; + } while ((remain > 0) && (--count)); + } + goto adpcmstop; + } + } + remain -= ad->step; + } while(--count); + } + else + { + do + { + if (remain > 0) + { + do { + getadpcmdata(ad); + if (ad->play == 0) + { + goto adpcmstop; + } + remain -= ad->pertim; + } while (remain > 0); + } + remain += ADTIMING; + } while (--count); + } + ad->remain = remain; + return; + +adpcmstop: + ad->out0 = 0; + ad->out1 = 0; + ad->fb = 0; + ad->remain = 0; +} diff --git a/sound/beep.h b/sound/beep.h old mode 100755 new mode 100644 index b69b8128..5ac1a24c --- a/sound/beep.h +++ b/sound/beep.h @@ -1,83 +1,83 @@ - -#if !defined(DISABLE_SOUND) - -enum { - BEEPEVENT_MAXBIT = 8, - BEEPEVENT_MAX = (1 << BEEPEVENT_MAXBIT) -}; - -typedef struct { - UINT32 clock; - int enable; -} BPEVENT; - -typedef struct { - UINT16 cnt; - UINT16 hz; - int buz; - int __puchi; - UINT8 mode; - UINT8 padding[3]; - - int low; - int enable; - int lastenable; - int lastremain; - int lastonevt; - int lastclk; - UINT32 clock; - UINT32 beep_data_curr_loc; - UINT32 beep_data_load_loc; - UINT32 beep_laskclk; - UINT events; - BPEVENT event[BEEPEVENT_MAX]; -} _BEEP, *BEEP; - -typedef struct { - UINT rate; - UINT vol; - UINT __puchibase; - UINT samplebase; -} BEEPCFG; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern _BEEP g_beep; -#define BEEPDATACOUNT 0x100000 -extern UINT16 beep_data[BEEPDATACOUNT]; -extern UINT32 beep_time[BEEPDATACOUNT]; - -void beep_initialize(UINT rate); -void beep_deinitialize(void); -void beep_setvol(UINT vol); -void beep_changeclock(void); - -void beep_reset(void); -void beep_hzset(UINT16 cnt); -void beep_modeset(void); -void beep_eventinit(void); -void beep_eventreset(void); -void beep_lheventset(int beep_low); -void beep_oneventset(void); - -void SOUNDCALL beep_getpcm(BEEP bp, SINT32 *pcm, UINT count); - -#ifdef __cplusplus -} -#endif - -#else - -#define beep_setvol(v) -#define beep_changeclock() -#define beep_hzset(c) -#define beep_modeset() -#define beep_eventreset() -#define beep_lheventset(b) -#define beep_oneventset() - -#endif - + +#if !defined(DISABLE_SOUND) + +enum { + BEEPEVENT_MAXBIT = 8, + BEEPEVENT_MAX = (1 << BEEPEVENT_MAXBIT) +}; + +typedef struct { + UINT32 clock; + int enable; +} BPEVENT; + +typedef struct { + UINT16 cnt; + UINT16 hz; + int buz; + int __puchi; + UINT8 mode; + UINT8 padding[3]; + + int low; + int enable; + int lastenable; + int lastremain; + int lastonevt; + int lastclk; + UINT32 clock; + UINT32 beep_data_curr_loc; + UINT32 beep_data_load_loc; + UINT32 beep_laskclk; + UINT events; + BPEVENT event[BEEPEVENT_MAX]; +} _BEEP, *BEEP; + +typedef struct { + UINT rate; + UINT vol; + UINT __puchibase; + UINT samplebase; +} BEEPCFG; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _BEEP g_beep; +#define BEEPDATACOUNT 0x100000 +extern UINT16 beep_data[BEEPDATACOUNT]; +extern UINT32 beep_time[BEEPDATACOUNT]; + +void beep_initialize(UINT rate); +void beep_deinitialize(void); +void beep_setvol(UINT vol); +void beep_changeclock(void); + +void beep_reset(void); +void beep_hzset(UINT16 cnt); +void beep_modeset(void); +void beep_eventinit(void); +void beep_eventreset(void); +void beep_lheventset(int beep_low); +void beep_oneventset(void); + +void SOUNDCALL beep_getpcm(BEEP bp, SINT32 *pcm, UINT count); + +#ifdef __cplusplus +} +#endif + +#else + +#define beep_setvol(v) +#define beep_changeclock() +#define beep_hzset(c) +#define beep_modeset() +#define beep_eventreset() +#define beep_lheventset(b) +#define beep_oneventset() + +#endif + diff --git a/sound/beepc.c b/sound/beepc.c old mode 100755 new mode 100644 index 7a874e6c..2770f281 --- a/sound/beepc.c +++ b/sound/beepc.c @@ -1,176 +1,176 @@ -#include -#include -#include -#include -#include -#include -#include -#include - - - _BEEP g_beep; - BEEPCFG beepcfg; - UINT16 beep_data[BEEPDATACOUNT]; - UINT32 beep_time[BEEPDATACOUNT]; - -// #define BEEPLOG - -#if defined(BEEPLOG) -static struct { - FILEH fh; - UINT events; - UINT32 event[0x10000]; -} bplog; - -static void beeplogflash(void) { - - if ((bplog.fh != FILEH_INVALID) && (bplog.events)) { - file_write(bplog.fh, bplog.event, bplog.events * sizeof(UINT32)); - bplog.events = 0; - } -} -#endif - - -void beep_initialize(UINT rate) { - - beepcfg.rate = rate; - beepcfg.vol = 2; -#if defined(BEEPLOG) - bplog.fh = file_create("beeplog"); - bplog.events = 0; -#endif -} - -void beep_deinitialize(void) { - -#if defined(BEEPLOG) - beeplogflash(); - if (bplog.fh != FILEH_INVALID) { - file_close(bplog.fh); - bplog.fh = FILEH_INVALID; - } -#endif -} - -void beep_setvol(UINT vol) { - - beepcfg.vol = vol & 3; -} - -void beep_changeclock(void) { - - UINT32 hz; - UINT rate; - - hz = pccore.realclock / 25; - rate = beepcfg.rate / 25; - beepcfg.samplebase = (1 << 16) * rate / hz; -} - -void beep_reset(void) { - - beep_changeclock(); - ZeroMemory(&g_beep, sizeof(g_beep)); - g_beep.mode = 1; -} - -void beep_hzset(UINT16 cnt) { - - double hz; - - sound_sync(); - g_beep.hz = 0; - if ((cnt & 0xff80) && (beepcfg.rate)) { - hz = 65536.0 / 4.0 * pccore.baseclock / beepcfg.rate / cnt; - if (hz < 0x8000) { - g_beep.hz = (UINT16)hz; - return; - } - } -} - -void beep_modeset(void) { - - UINT8 newmode; - - newmode = (pit.ch[1].ctrl >> 2) & 3; - if (g_beep.mode != newmode) { - sound_sync(); - g_beep.mode = newmode; - beep_eventinit(); - } -} - -static void beep_eventset(void) { - - BPEVENT *evt; - int enable; - SINT32 clk; - - enable = g_beep.low & g_beep.buz; - if (g_beep.enable != enable) { -#if defined(BEEPLOG) - UINT32 tmp; - tmp = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - if (enable) { - tmp |= 0x80000000; - } - else { - tmp &= ~0x80000000; - } - bplog.event[bplog.events++] = tmp; - if (bplog.events >= NELEMENTS(bplog.event)) { - beeplogflash(); - } -#endif - if (g_beep.events >= (BEEPEVENT_MAX / 2)) { - sound_sync(); - } - g_beep.enable = enable; - if (g_beep.events < BEEPEVENT_MAX) { - clk = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - evt = g_beep.event + g_beep.events; - g_beep.events++; - evt->clock = (clk - g_beep.clock) * beepcfg.samplebase; - evt->enable = enable; - g_beep.clock = clk; - } - } -} - -void beep_eventinit(void) { - - g_beep.low = 0; - g_beep.enable = 0; - g_beep.lastenable = 0; - g_beep.clock = soundcfg.lastclock; - g_beep.events = 0; -} - -void beep_eventreset(void) { - - g_beep.lastenable = g_beep.enable; - g_beep.clock = soundcfg.lastclock; - g_beep.events = 0; -} - -void beep_lheventset(int low) { - - if (g_beep.low != low) { - g_beep.low = low; - beep_eventset(); - } -} - -void beep_oneventset(void) { - - int buz; - - buz = (sysport.c & 8)?0:1; - if (g_beep.buz != buz) { - g_beep.buz = buz; - beep_eventset(); - } -} - +#include +#include +#include +#include +#include +#include +#include +#include + + + _BEEP g_beep; + BEEPCFG beepcfg; + UINT16 beep_data[BEEPDATACOUNT]; + UINT32 beep_time[BEEPDATACOUNT]; + +// #define BEEPLOG + +#if defined(BEEPLOG) +static struct { + FILEH fh; + UINT events; + UINT32 event[0x10000]; +} bplog; + +static void beeplogflash(void) { + + if ((bplog.fh != FILEH_INVALID) && (bplog.events)) { + file_write(bplog.fh, bplog.event, bplog.events * sizeof(UINT32)); + bplog.events = 0; + } +} +#endif + + +void beep_initialize(UINT rate) { + + beepcfg.rate = rate; + beepcfg.vol = 2; +#if defined(BEEPLOG) + bplog.fh = file_create("beeplog"); + bplog.events = 0; +#endif +} + +void beep_deinitialize(void) { + +#if defined(BEEPLOG) + beeplogflash(); + if (bplog.fh != FILEH_INVALID) { + file_close(bplog.fh); + bplog.fh = FILEH_INVALID; + } +#endif +} + +void beep_setvol(UINT vol) { + + beepcfg.vol = vol & 3; +} + +void beep_changeclock(void) { + + UINT32 hz; + UINT rate; + + hz = pccore.realclock / 25; + rate = beepcfg.rate / 25; + beepcfg.samplebase = (1 << 16) * rate / hz; +} + +void beep_reset(void) { + + beep_changeclock(); + ZeroMemory(&g_beep, sizeof(g_beep)); + g_beep.mode = 1; +} + +void beep_hzset(UINT16 cnt) { + + double hz; + + sound_sync(); + g_beep.hz = 0; + if ((cnt & 0xff80) && (beepcfg.rate)) { + hz = 65536.0 / 4.0 * pccore.baseclock / beepcfg.rate / cnt; + if (hz < 0x8000) { + g_beep.hz = (UINT16)hz; + return; + } + } +} + +void beep_modeset(void) { + + UINT8 newmode; + + newmode = (pit.ch[1].ctrl >> 2) & 3; + if (g_beep.mode != newmode) { + sound_sync(); + g_beep.mode = newmode; + beep_eventinit(); + } +} + +static void beep_eventset(void) { + + BPEVENT *evt; + int enable; + SINT32 clk; + + enable = g_beep.low & g_beep.buz; + if (g_beep.enable != enable) { +#if defined(BEEPLOG) + UINT32 tmp; + tmp = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + if (enable) { + tmp |= 0x80000000; + } + else { + tmp &= ~0x80000000; + } + bplog.event[bplog.events++] = tmp; + if (bplog.events >= NELEMENTS(bplog.event)) { + beeplogflash(); + } +#endif + if (g_beep.events >= (BEEPEVENT_MAX / 2)) { + sound_sync(); + } + g_beep.enable = enable; + if (g_beep.events < BEEPEVENT_MAX) { + clk = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + evt = g_beep.event + g_beep.events; + g_beep.events++; + evt->clock = (clk - g_beep.clock) * beepcfg.samplebase; + evt->enable = enable; + g_beep.clock = clk; + } + } +} + +void beep_eventinit(void) { + + g_beep.low = 0; + g_beep.enable = 0; + g_beep.lastenable = 0; + g_beep.clock = soundcfg.lastclock; + g_beep.events = 0; +} + +void beep_eventreset(void) { + + g_beep.lastenable = g_beep.enable; + g_beep.clock = soundcfg.lastclock; + g_beep.events = 0; +} + +void beep_lheventset(int low) { + + if (g_beep.low != low) { + g_beep.low = low; + beep_eventset(); + } +} + +void beep_oneventset(void) { + + int buz; + + buz = (sysport.c & 8)?0:1; + if (g_beep.buz != buz) { + g_beep.buz = buz; + beep_eventset(); + } +} + diff --git a/sound/beepg.c b/sound/beepg.c old mode 100755 new mode 100644 index 01bf4572..a35c1661 --- a/sound/beepg.c +++ b/sound/beepg.c @@ -1,177 +1,177 @@ -#include -#include -#include -#include -#include - - -static int beepOffsetCounter = 0; -static SINT32 beepOffsetSum = 0; -static SINT32 beepOffset = 0; - -static void pushBeepOffsetData(SINT32 data) { - if (np2cfg.nbeepofs) { - beepOffsetSum += data; - beepOffsetCounter++; - beepOffset = beepOffsetSum / beepOffsetCounter; - } -} -static void resetBeepOffsetData() { - beepOffsetCounter = 0; - beepOffsetSum = 0; - beepOffset = 0; -} - -extern BEEPCFG beepcfg; - -static void oneshot(BEEP bp, SINT32 *pcm, UINT count) { - - SINT32 volM; - SINT32 samp; - UINT32 firsttime = beep_time[bp->beep_data_curr_loc]; - UINT32 time = firsttime; - UINT32 bound; - SINT32 curBeepOffset = beepOffset; - - if (!np2cfg.nbeepofs) { - curBeepOffset = 0x2500 * beepcfg.vol; // 固定オフセット - } - - volM = np2cfg.vol_master; - - if(bp->beep_data_load_loc != 0) - bound = (beep_time[bp->beep_data_load_loc - 1] - firsttime) / count; - else - bound = (beep_time[BEEPDATACOUNT - 1] - firsttime) / count; - - while(count--) { - while(time >= beep_time[bp->beep_data_curr_loc] && bp->beep_data_curr_loc != bp->beep_data_load_loc) { - bp->beep_data_curr_loc++; - if(bp->beep_data_curr_loc >= BEEPDATACOUNT) - bp->beep_data_curr_loc = 0; - } - if(bp->beep_data_curr_loc != 0) - samp = beep_data[bp->beep_data_curr_loc - 1]; - else - samp = beep_data[BEEPDATACOUNT - 1]; - samp = (SINT32)((double)samp / 0x100 * (0x5000 * beepcfg.vol)); - if (beepOffsetCounter < 500 && np2cfg.nbeepofs) - { - // 平均オフセット 500サンプルまでを見る - pushBeepOffsetData(samp); - curBeepOffset = beepOffset; - } - samp -= curBeepOffset; - pcm[0] += samp * volM / 100; - pcm[1] += samp * volM / 100; - pcm += 2; - time += bound; - } -} - -static void rategenerator(BEEP bp, SINT32 *pcm, UINT count) { - - SINT32 vol; - SINT32 volM; -const BPEVENT *bev; - SINT32 samp; - SINT32 remain; - SINT32 clk; - int event; - UINT r; - - volM = np2cfg.vol_master; - - vol = beepcfg.vol; - bev = bp->event; - if (bp->events) { - bp->events--; - clk = bev->clock; - event = bev->enable; - bev++; - } - else { - clk = 0x40000000; - event = bp->lastenable; - } - do { - if (clk >= (1 << 16)) { - r = clk >> 16; - r = MIN(r, count); - clk -= r << 16; - count -= r; - if (bp->lastenable) { - do { - samp = (bp->cnt & 0x8000)?1:-1; - bp->cnt += bp->hz; - samp += (bp->cnt & 0x8000)?1:-1; - bp->cnt += bp->hz; - samp += (bp->cnt & 0x8000)?1:-1; - bp->cnt += bp->hz; - samp += (bp->cnt & 0x8000)?1:-1; - bp->cnt += bp->hz; - samp *= vol; - samp <<= (10 - 2); - if(samp > 32767) samp = 0; // XXX: 処理落ち時のノイズ回避 np21w ver0.86 rev42 - if(samp < -32768) samp = 0; // XXX: 処理落ち時のノイズ回避 np21w ver0.86 rev42 - pcm[0] += samp * volM / 100; - pcm[1] += samp * volM / 100; - pcm += 2; - } while(--r); - } - else { - pcm += 2 * r; - } - } - else { - remain = (1 << 16); - samp = 0; - while(remain >= clk) { - remain -= clk; - if (bp->lastenable) { - samp += clk; - } - bp->lastenable = event; - bp->cnt = 0; - if (bp->events) { - bp->events--; - clk = bev->clock; - event = bev->enable; - bev++; - } - else { - clk = 0x40000000; - } - } - clk -= remain; - if (bp->lastenable) { - samp += remain; - } - samp *= vol; - samp >>= (16 - 10); - if(samp > 32767) samp = 0; // XXX: 処理落ち時のノイズ回避 np21w ver0.86 rev42 - if(samp < -32768) samp = 0; // XXX: 処理落ち時のノイズ回避 np21w ver0.86 rev42 - pcm[0] += samp * volM / 100; - pcm[1] += samp * volM / 100; - pcm += 2; - count--; - } - } while(count); - bp->lastenable = event; - bp->events = 0; -} - -void SOUNDCALL beep_getpcm(BEEP bp, SINT32 *pcm, UINT count) { - - if ((count) && (beepcfg.vol)) { - if (bp->mode == 0) { - if (bp->events) { - oneshot(bp, pcm, count); - } - } - else if (bp->mode == 1) { - rategenerator(bp, pcm, count); - } - } -} - +#include +#include +#include +#include +#include + + +static int beepOffsetCounter = 0; +static SINT32 beepOffsetSum = 0; +static SINT32 beepOffset = 0; + +static void pushBeepOffsetData(SINT32 data) { + if (np2cfg.nbeepofs) { + beepOffsetSum += data; + beepOffsetCounter++; + beepOffset = beepOffsetSum / beepOffsetCounter; + } +} +static void resetBeepOffsetData() { + beepOffsetCounter = 0; + beepOffsetSum = 0; + beepOffset = 0; +} + +extern BEEPCFG beepcfg; + +static void oneshot(BEEP bp, SINT32 *pcm, UINT count) { + + SINT32 volM; + SINT32 samp; + UINT32 firsttime = beep_time[bp->beep_data_curr_loc]; + UINT32 time = firsttime; + UINT32 bound; + SINT32 curBeepOffset = beepOffset; + + if (!np2cfg.nbeepofs) { + curBeepOffset = 0x2500 * beepcfg.vol; // 固定オフセット + } + + volM = np2cfg.vol_master; + + if(bp->beep_data_load_loc != 0) + bound = (beep_time[bp->beep_data_load_loc - 1] - firsttime) / count; + else + bound = (beep_time[BEEPDATACOUNT - 1] - firsttime) / count; + + while(count--) { + while(time >= beep_time[bp->beep_data_curr_loc] && bp->beep_data_curr_loc != bp->beep_data_load_loc) { + bp->beep_data_curr_loc++; + if(bp->beep_data_curr_loc >= BEEPDATACOUNT) + bp->beep_data_curr_loc = 0; + } + if(bp->beep_data_curr_loc != 0) + samp = beep_data[bp->beep_data_curr_loc - 1]; + else + samp = beep_data[BEEPDATACOUNT - 1]; + samp = (SINT32)((double)samp / 0x100 * (0x5000 * beepcfg.vol)); + if (beepOffsetCounter < 500 && np2cfg.nbeepofs) + { + // 平均オフセット 500サンプルまでを見る + pushBeepOffsetData(samp); + curBeepOffset = beepOffset; + } + samp -= curBeepOffset; + pcm[0] += samp * volM / 100; + pcm[1] += samp * volM / 100; + pcm += 2; + time += bound; + } +} + +static void rategenerator(BEEP bp, SINT32 *pcm, UINT count) { + + SINT32 vol; + SINT32 volM; +const BPEVENT *bev; + SINT32 samp; + SINT32 remain; + SINT32 clk; + int event; + UINT r; + + volM = np2cfg.vol_master; + + vol = beepcfg.vol; + bev = bp->event; + if (bp->events) { + bp->events--; + clk = bev->clock; + event = bev->enable; + bev++; + } + else { + clk = 0x40000000; + event = bp->lastenable; + } + do { + if (clk >= (1 << 16)) { + r = clk >> 16; + r = MIN(r, count); + clk -= r << 16; + count -= r; + if (bp->lastenable) { + do { + samp = (bp->cnt & 0x8000)?1:-1; + bp->cnt += bp->hz; + samp += (bp->cnt & 0x8000)?1:-1; + bp->cnt += bp->hz; + samp += (bp->cnt & 0x8000)?1:-1; + bp->cnt += bp->hz; + samp += (bp->cnt & 0x8000)?1:-1; + bp->cnt += bp->hz; + samp *= vol; + samp <<= (10 - 2); + if(samp > 32767) samp = 0; // XXX: 処理落ち時のノイズ回避 np21w ver0.86 rev42 + if(samp < -32768) samp = 0; // XXX: 処理落ち時のノイズ回避 np21w ver0.86 rev42 + pcm[0] += samp * volM / 100; + pcm[1] += samp * volM / 100; + pcm += 2; + } while(--r); + } + else { + pcm += 2 * r; + } + } + else { + remain = (1 << 16); + samp = 0; + while(remain >= clk) { + remain -= clk; + if (bp->lastenable) { + samp += clk; + } + bp->lastenable = event; + bp->cnt = 0; + if (bp->events) { + bp->events--; + clk = bev->clock; + event = bev->enable; + bev++; + } + else { + clk = 0x40000000; + } + } + clk -= remain; + if (bp->lastenable) { + samp += remain; + } + samp *= vol; + samp >>= (16 - 10); + if(samp > 32767) samp = 0; // XXX: 処理落ち時のノイズ回避 np21w ver0.86 rev42 + if(samp < -32768) samp = 0; // XXX: 処理落ち時のノイズ回避 np21w ver0.86 rev42 + pcm[0] += samp * volM / 100; + pcm[1] += samp * volM / 100; + pcm += 2; + count--; + } + } while(count); + bp->lastenable = event; + bp->events = 0; +} + +void SOUNDCALL beep_getpcm(BEEP bp, SINT32 *pcm, UINT count) { + + if ((count) && (beepcfg.vol)) { + if (bp->mode == 0) { + if (bp->events) { + oneshot(bp, pcm, count); + } + } + else if (bp->mode == 1) { + rategenerator(bp, pcm, count); + } + } +} + diff --git a/sound/cs4231.h b/sound/cs4231.h old mode 100755 new mode 100644 index b7ce3035..e579a68a --- a/sound/cs4231.h +++ b/sound/cs4231.h @@ -1,183 +1,183 @@ -/** -sudo make - * @file cs4231.h - * @brief Interface of the CS4231 - */ - -#pragma once - -#include -#include - -enum { - CS4231_BUFFERS = (1 << 11), - CS4231_BUFMASK = (CS4231_BUFFERS - 1), - CS4231_MAXDMAREADBYTES = (1 << 9), - CS4231_PIOBUFFERS = (CS4231_BUFFERS / 2) // 本当はもっと小さいがサウンド再生ストリームのバッファ周期と合わないのでまともに再生できない。厳密にするなら86PCMと同じく仮想バッファを実装すべし -}; - -typedef struct { - UINT8 adc_l; // 0 - UINT8 adc_r; // 1 - UINT8 aux1_l; // 2 - UINT8 aux1_r; // 3 - UINT8 aux2_l; // 4 - UINT8 aux2_r; // 5 - UINT8 dac_l; // 6 - UINT8 dac_r; // 7 - UINT8 datafmt; // 8 - UINT8 iface; // 9 - UINT8 pinctrl; // a - UINT8 errorstatus; //b - UINT8 mode_id; //c - UINT8 loopctrl; //d - UINT8 playcount[2]; //e-f - UINT8 featurefunc[2]; //10-11 - UINT8 line_l; //12 - UINT8 line_r; //13 - UINT8 timer[2]; //14-15 - UINT8 reserved1; //16 - UINT8 reserved2; //17 - UINT8 featurestatus; //18 - UINT8 chipid; //19 - UINT8 monoinput; //1a - UINT8 reserved3; //1b - UINT8 cap_datafmt; //1c - UINT8 reserved4; //1d - UINT8 cap_basecount[2]; //1e-1f -} CS4231REG; - -typedef struct { - UINT bufsize; // サウンド再生用の循環バッファサイズ。データのread/writeは4byte単位(16bitステレオの1サンプル単位)で行うこと - UINT bufdatas; // = (bufwpos-bufpos)&CS4231_BUFMASK - UINT bufpos; // バッファの読み取り位置。bufwposと一致してもよいが追い越してはいけない - UINT bufwpos; // バッファの書き込み位置。周回遅れのbufposに追いついてはいけない(一致も不可) - UINT32 pos12; - UINT32 step12; - - UINT8 enable; // CS4231有効フラグ - UINT8 portctrl; - UINT8 dmairq; // CS4231 IRQ - UINT8 dmach; // CS4231 DMAチャネル - UINT16 port[16]; // I/Oポートアドレス(再配置可能) - UINT8 adrs; // DMA読み取りアドレス - UINT8 index; // Index Address Register - UINT8 intflag; // Status Register - UINT8 outenable; - UINT8 extfunc; - UINT8 extindex; - - UINT16 timer; // 廃止 - SINT32 timercounter; // TI割り込み用のダウンカウンタ(の予定) - - CS4231REG reg; - UINT8 buffer[CS4231_BUFFERS]; // DMA読み取りアドレス - - UINT8 devvolume[0x100]; // CS4231内蔵ボリューム - - SINT32 totalsample; // PI割り込み用のデータ数カウンタ -} _CS4231, *CS4231; - -typedef struct { // ステートセーブ互換性維持用(変更禁止) - UINT bufsize; // サウンド再生用の循環バッファサイズ。データのread/writeは4byte単位(16bitステレオの1サンプル単位)で行うこと - UINT bufdatas; // = (bufwpos-bufpos)&CS4231_BUFMASK - UINT bufpos; // バッファの読み取り位置。bufwposと一致してもよいが追い越してはいけない - UINT bufwpos; // バッファの書き込み位置。周回遅れのbufposに追いついてはいけない(一致も不可) - UINT32 pos12; - UINT32 step12; - - UINT8 enable; // CS4231有効フラグ - UINT8 portctrl; - UINT8 dmairq; // CS4231 IRQ - UINT8 dmach; // CS4231 DMAチャネル - UINT16 port[16]; // I/Oポートアドレス(再配置可能) - UINT8 adrs; // DMA読み取りアドレス - UINT8 index; // Index Address Register - UINT8 intflag; // Status Register - UINT8 outenable; - UINT8 extfunc; - UINT8 extindex; - - UINT16 timer; // 廃止 - SINT32 timercounter; // TI割り込み用のダウンカウンタ(の予定) - - CS4231REG reg; - UINT8 buffer[CS4231_BUFFERS]; // DMA読み取りアドレス - - UINT8 devvolume[0x100]; // CS4231内蔵ボリューム - - SINT32 totalsample; // PI割り込み用のデータ数カウンタ -} _CS4231_OLD, *CS4231_OLD; - - -typedef struct { - UINT rate; -} CS4231CFG; - - -#ifdef __cplusplus -extern "C" -{ -#endif - -// Index Address Register (R0) 0xf44 -#define TRD (1 << 5) //cs4231.index bit5 Transfer Request Disable -#define MCE (1 << 6) //cs4231.index bit6 Mode Change Enable - -// Status Register (R2, Read Only) 0xf46 -#define INt (1 << 0) //cs4231.intflag bit0 Interrupt Status -#define PRDY (1 << 1) //cs4231.intflag bit1 Playback Data Ready(PIO data) -#define PLR (1 << 2) //cs4231.intflag bit2 Playback Left/Right Sample -#define PULR (1 << 3) //cs4231.intflag bit3 Playback Upper/Lower Byte -#define SER (1 << 4) //cs4231.intflag bit4 Sample Error -#define CRDY (1 << 5) //cs4231.intflag bit5 Capture Data Ready -#define CLR (1 << 6) //cs4231.intflag bit6 Capture Left/Right Sample -#define CUL (1 << 7) //cs4231.intglag bit7 Capture Upper/Lower Byte - -//cs4231.reg.iface(9) Interface Configuration (I9) -#define PEN (1 << 0) //bit0 Playback Enable set and reset without MCE -#define CEN (1 << 1) //bit1 Capture Enable -#define SDC (1 << 2) //bit2 Single DMA Channel 0 Dual 1 Single 逆と思ってたので修正すべし -#define CAL0 (1 << 3) //bit3 Calibration 0 No Calibration 1 Converter calibration -#define CAL1 (1 << 4) //bit4 2 DAC calibration 3 Full Calibration -#define PPIO (1 << 6) //bit6 Playback PIO Enable 0 DMA 1 PIO -#define CPIO (1 << 7) //bit7 Capture PIO Enable 0 DMA 1 PIO - -//cs4231.reg.errorstatus(11)0xb Error Status and Initialization (I11, Read Only) -#define ACI (1 << 5) //bit5 Auto-calibrate In-Progress - -//cs4231.reg.pinctrl(10)0xa Pin Control (I10) -#define IEN (1 << 1) //bit1 Interrupt Enable reflect cs4231.intflag bit0 -#define DEN (1 << 3) //bit3 Dither Enable only active in 8-bit unsigned mode - -//cs4231.reg.modeid(12)0xc MODE and ID (I12) -#define MODE2 (1 << 6) //bit6 - -//cs4231.reg.featurestatus(24)0x18 Alternate Feature Status (I24) -#define PI (1 << 4) //bit4 Playback Interrupt pending from Playback DMA count registers -#define CI (1 << 5) //bit5 Capture Interrupt pending from record DMA count registers when SDC=1 non-functional -#define TI (1 << 6) //bit6 Timer Interrupt pending from timer count registers -// PI,CI,TI bits are reset by writing a "0" to the particular interrupt bit or by writing any value to the Status register - -void cs4231_dma(NEVENTITEM item); -REG8 DMACCALL cs4231dmafunc(REG8 func); -void cs4231_datasend(REG8 dat); - -#if defined(SUPPORT_MULTITHREAD) -void cs4231cs_enter_criticalsection(); -void cs4231cs_leave_criticalsection(); -void cs4231cs_initialize(); -void cs4231cs_shutdown(); -#endif - -void cs4231_initialize(UINT rate); -void cs4231_setvol(UINT vol); - -void cs4231_reset(void); -void cs4231_update(void); -void cs4231_control(UINT index, REG8 dat); - -void SOUNDCALL cs4231_getpcm(CS4231 cs, SINT32 *pcm, UINT count); - -#ifdef __cplusplus -} -#endif +/** +sudo make - * @file cs4231.h + * @brief Interface of the CS4231 + */ + +#pragma once + +#include +#include + +enum { + CS4231_BUFFERS = (1 << 11), + CS4231_BUFMASK = (CS4231_BUFFERS - 1), + CS4231_MAXDMAREADBYTES = (1 << 9), + CS4231_PIOBUFFERS = (CS4231_BUFFERS / 2) // 本当はもっと小さいがサウンド再生ストリームのバッファ周期と合わないのでまともに再生できない。厳密にするなら86PCMと同じく仮想バッファを実装すべし +}; + +typedef struct { + UINT8 adc_l; // 0 + UINT8 adc_r; // 1 + UINT8 aux1_l; // 2 + UINT8 aux1_r; // 3 + UINT8 aux2_l; // 4 + UINT8 aux2_r; // 5 + UINT8 dac_l; // 6 + UINT8 dac_r; // 7 + UINT8 datafmt; // 8 + UINT8 iface; // 9 + UINT8 pinctrl; // a + UINT8 errorstatus; //b + UINT8 mode_id; //c + UINT8 loopctrl; //d + UINT8 playcount[2]; //e-f + UINT8 featurefunc[2]; //10-11 + UINT8 line_l; //12 + UINT8 line_r; //13 + UINT8 timer[2]; //14-15 + UINT8 reserved1; //16 + UINT8 reserved2; //17 + UINT8 featurestatus; //18 + UINT8 chipid; //19 + UINT8 monoinput; //1a + UINT8 reserved3; //1b + UINT8 cap_datafmt; //1c + UINT8 reserved4; //1d + UINT8 cap_basecount[2]; //1e-1f +} CS4231REG; + +typedef struct { + UINT bufsize; // サウンド再生用の循環バッファサイズ。データのread/writeは4byte単位(16bitステレオの1サンプル単位)で行うこと + UINT bufdatas; // = (bufwpos-bufpos)&CS4231_BUFMASK + UINT bufpos; // バッファの読み取り位置。bufwposと一致してもよいが追い越してはいけない + UINT bufwpos; // バッファの書き込み位置。周回遅れのbufposに追いついてはいけない(一致も不可) + UINT32 pos12; + UINT32 step12; + + UINT8 enable; // CS4231有効フラグ + UINT8 portctrl; + UINT8 dmairq; // CS4231 IRQ + UINT8 dmach; // CS4231 DMAチャネル + UINT16 port[16]; // I/Oポートアドレス(再配置可能) + UINT8 adrs; // DMA読み取りアドレス + UINT8 index; // Index Address Register + UINT8 intflag; // Status Register + UINT8 outenable; + UINT8 extfunc; + UINT8 extindex; + + UINT16 timer; // 廃止 + SINT32 timercounter; // TI割り込み用のダウンカウンタ(の予定) + + CS4231REG reg; + UINT8 buffer[CS4231_BUFFERS]; // DMA読み取りアドレス + + UINT8 devvolume[0x100]; // CS4231内蔵ボリューム + + SINT32 totalsample; // PI割り込み用のデータ数カウンタ +} _CS4231, *CS4231; + +typedef struct { // ステートセーブ互換性維持用(変更禁止) + UINT bufsize; // サウンド再生用の循環バッファサイズ。データのread/writeは4byte単位(16bitステレオの1サンプル単位)で行うこと + UINT bufdatas; // = (bufwpos-bufpos)&CS4231_BUFMASK + UINT bufpos; // バッファの読み取り位置。bufwposと一致してもよいが追い越してはいけない + UINT bufwpos; // バッファの書き込み位置。周回遅れのbufposに追いついてはいけない(一致も不可) + UINT32 pos12; + UINT32 step12; + + UINT8 enable; // CS4231有効フラグ + UINT8 portctrl; + UINT8 dmairq; // CS4231 IRQ + UINT8 dmach; // CS4231 DMAチャネル + UINT16 port[16]; // I/Oポートアドレス(再配置可能) + UINT8 adrs; // DMA読み取りアドレス + UINT8 index; // Index Address Register + UINT8 intflag; // Status Register + UINT8 outenable; + UINT8 extfunc; + UINT8 extindex; + + UINT16 timer; // 廃止 + SINT32 timercounter; // TI割り込み用のダウンカウンタ(の予定) + + CS4231REG reg; + UINT8 buffer[CS4231_BUFFERS]; // DMA読み取りアドレス + + UINT8 devvolume[0x100]; // CS4231内蔵ボリューム + + SINT32 totalsample; // PI割り込み用のデータ数カウンタ +} _CS4231_OLD, *CS4231_OLD; + + +typedef struct { + UINT rate; +} CS4231CFG; + + +#ifdef __cplusplus +extern "C" +{ +#endif + +// Index Address Register (R0) 0xf44 +#define TRD (1 << 5) //cs4231.index bit5 Transfer Request Disable +#define MCE (1 << 6) //cs4231.index bit6 Mode Change Enable + +// Status Register (R2, Read Only) 0xf46 +#define INt (1 << 0) //cs4231.intflag bit0 Interrupt Status +#define PRDY (1 << 1) //cs4231.intflag bit1 Playback Data Ready(PIO data) +#define PLR (1 << 2) //cs4231.intflag bit2 Playback Left/Right Sample +#define PULR (1 << 3) //cs4231.intflag bit3 Playback Upper/Lower Byte +#define SER (1 << 4) //cs4231.intflag bit4 Sample Error +#define CRDY (1 << 5) //cs4231.intflag bit5 Capture Data Ready +#define CLR (1 << 6) //cs4231.intflag bit6 Capture Left/Right Sample +#define CUL (1 << 7) //cs4231.intglag bit7 Capture Upper/Lower Byte + +//cs4231.reg.iface(9) Interface Configuration (I9) +#define PEN (1 << 0) //bit0 Playback Enable set and reset without MCE +#define CEN (1 << 1) //bit1 Capture Enable +#define SDC (1 << 2) //bit2 Single DMA Channel 0 Dual 1 Single 逆と思ってたので修正すべし +#define CAL0 (1 << 3) //bit3 Calibration 0 No Calibration 1 Converter calibration +#define CAL1 (1 << 4) //bit4 2 DAC calibration 3 Full Calibration +#define PPIO (1 << 6) //bit6 Playback PIO Enable 0 DMA 1 PIO +#define CPIO (1 << 7) //bit7 Capture PIO Enable 0 DMA 1 PIO + +//cs4231.reg.errorstatus(11)0xb Error Status and Initialization (I11, Read Only) +#define ACI (1 << 5) //bit5 Auto-calibrate In-Progress + +//cs4231.reg.pinctrl(10)0xa Pin Control (I10) +#define IEN (1 << 1) //bit1 Interrupt Enable reflect cs4231.intflag bit0 +#define DEN (1 << 3) //bit3 Dither Enable only active in 8-bit unsigned mode + +//cs4231.reg.modeid(12)0xc MODE and ID (I12) +#define MODE2 (1 << 6) //bit6 + +//cs4231.reg.featurestatus(24)0x18 Alternate Feature Status (I24) +#define PI (1 << 4) //bit4 Playback Interrupt pending from Playback DMA count registers +#define CI (1 << 5) //bit5 Capture Interrupt pending from record DMA count registers when SDC=1 non-functional +#define TI (1 << 6) //bit6 Timer Interrupt pending from timer count registers +// PI,CI,TI bits are reset by writing a "0" to the particular interrupt bit or by writing any value to the Status register + +void cs4231_dma(NEVENTITEM item); +REG8 DMACCALL cs4231dmafunc(REG8 func); +void cs4231_datasend(REG8 dat); + +#if defined(SUPPORT_MULTITHREAD) +void cs4231cs_enter_criticalsection(); +void cs4231cs_leave_criticalsection(); +void cs4231cs_initialize(); +void cs4231cs_shutdown(); +#endif + +void cs4231_initialize(UINT rate); +void cs4231_setvol(UINT vol); + +void cs4231_reset(void); +void cs4231_update(void); +void cs4231_control(UINT index, REG8 dat); + +void SOUNDCALL cs4231_getpcm(CS4231 cs, SINT32 *pcm, UINT count); + +#ifdef __cplusplus +} +#endif diff --git a/sound/cs4231c.c b/sound/cs4231c.c old mode 100755 new mode 100644 index 5708d9bb..a6800877 --- a/sound/cs4231c.c +++ b/sound/cs4231c.c @@ -1,488 +1,488 @@ -/** - * @file cs4231c.c - * @brief Implementation of the CS4231 - */ - -#include -#include -#include -#include -#include -#include -#ifndef CPU_STAT_PM -#define CPU_STAT_PM 0 -#endif -#define CS4231_BUFREADSMP 128 - - CS4231CFG cs4231cfg; - - int cs4231_bufdelaycounter = 0; - - static int playcountsmp_Ictl = CS4231_BUFREADSMP; // 積分制御で無理やり一定サンプルずつ読むようにする・・・ - -// 1サンプルあたりのバイト数(モノラル, ステレオの順) -static const SINT32 cs4231_playcountshift[16] = { - 1 , // 0: 8bit PCM - 1*2, - 1 , // 1: u-Law - 1 , - 1*2, // 2: 16bit PCM(little endian)? - 1*4, - 1 , // 3: A-Law - 1 , - 1 , // 4: - 1 , - 1 , // 5: ADPCM - 1 , - 1*2, // 6: 16bit PCM - 1*4, - 1 , // 7: ADPCM - 1 }; - -// Indirect Mapped Registers -enum { - CS4231REG_LINPUT = 0x00, // Left ADC Input Control (I0) - CS4231REG_RINPUT = 0x01, // Right ADC Input Control (I1) - CS4231REG_AUX1L = 0x02, // Left Auxiliary #1 Input Control (I2) - CS4231REG_AUX1R = 0x03, // Right Auxiliary #1 Input Control (I3) - CS4231REG_AUX2L = 0x04, // Left Auxiliary #2 Input Control (I4) - CS4231REG_AUX2R = 0x05, // Right Auxiliary #2 Input Control (I5) - CS4231REG_LOUTPUT = 0x06, // Left DAC Output Control (I6) - CS4231REG_ROUTPUT = 0x07, // Right DAC Output Control (I7) - CS4231REG_PLAYFMT = 0x08, // Fs and Playback Data Format (I8) - CS4231REG_INTERFACE = 0x09, // Interface Configuration (I9) - CS4231REG_PINCTRL = 0x0a, // Pin Control (I10) - CS4231REG_TESTINIT = 0x0b, // Error Status and Initialization (I11, Read Only) - CS4231REG_MISCINFO = 0x0c, // MODE and ID (I12) - CS4231REG_LOOPBACK = 0x0d, // Loopback Control (I13) - CS4231REG_PLAYCNTM = 0x0e, // Playback Upper Base (I14) - CS4231REG_PLAYCNTL = 0x0f, // Playback Lower Base (I15) - - CS4231REG_FEATURE1 = 0x10, // Alternate Feature Enable I (I16) - CS4231REG_FEATURE2 = 0x11, // Alternate Feature Enable II (I17) - CS4231REG_LLINEIN = 0x12, // Left Line Input Control (I18) - CS4231REG_RLINEIN = 0x13, // Right Line Input Control (I19) - CS4231REG_TIMERL = 0x14, // Timer Lower Base (I20) - CS4231REG_TIMERH = 0x15, // Timer Upper Base (I21) - CS4231REG_RESERVED1 = 0x16, // RESERVED (I22) - CS4231REG_RESERVED2 = 0x17, // Alternate Feature Enable III (I23) - CS4231REG_IRQSTAT = 0x18, // Alternate Feature Status (I24) - CS4231REG_VERSION = 0x19, // Version / ID (I25) - CS4231REG_MONOCTRL = 0x1a, // Mono Input & Output Control (I26) - CS4231REG_RESERVED3 = 0x1b, // RESERVED (I27) - CS4231REG_RECFMT = 0x1c, // Capture Data Format (I28) - CS4231REG_PLAYFREQ = 0x1d, // RESERVED (I29) - CS4231REG_RECCNTM = 0x1e, // Capture Upper Base (I30) - CS4231REG_RECCNTL = 0x1f // Capture Lower Base (I31) -}; - - -UINT dmac_getdata_(DMACH dmach, UINT8 *buf, UINT offset, UINT size); -static const UINT32 cs4231xtal64[2] = {24576000/64, 16934400/64}; - -static const UINT8 cs4231cnt64[8] = { - 3072/64, // 8000/ 5510 - 1536/64, // 16000/11025 - 896/64, // 27420/18900 - 768/64, // 32000/22050 - 448/64, // 54840/37800 - 384/64, // 64000/44100 - 512/64, // 48000/33075 - 2560/64}; // 9600/ 6620 - -// 640:441 - -#if defined(SUPPORT_MULTITHREAD) -static int cs4231_cs_initialized = 0; -static CRITICAL_SECTION cs4231_cs; - -void cs4231cs_enter_criticalsection(void) -{ - if (!cs4231_cs_initialized) return; - EnterCriticalSection(&cs4231_cs); -} -void cs4231cs_leave_criticalsection(void) -{ - if (!cs4231_cs_initialized) return; - LeaveCriticalSection(&cs4231_cs); -} - -void cs4231cs_initialize(void) -{ - /* クリティカルセクション準備 */ - if (!cs4231_cs_initialized) - { - memset(&cs4231_cs, 0, sizeof(cs4231_cs)); - InitializeCriticalSection(&cs4231_cs); - cs4231_cs_initialized = 1; - } -} -void cs4231cs_shutdown(void) -{ - /* クリティカルセクション破棄 */ - if (cs4231_cs_initialized) - { - memset(&cs4231_cs, 0, sizeof(cs4231_cs)); - DeleteCriticalSection(&cs4231_cs); - cs4231_cs_initialized = 0; - } -} -#endif - -void cs4231_initialize(UINT rate) { - - cs4231cfg.rate = rate; -} - -void cs4231_reset(void) { - - ZeroMemory(&cs4231, sizeof(cs4231)); - cs4231.bufsize = CS4231_BUFFERS; -// cs4231.proc = cs4231_nodecode; - cs4231.dmach = 0xff; - cs4231.dmairq = 0xff; - cs4231.totalsample = 0; - FillMemory(cs4231.port, sizeof(cs4231.port), 0xff); -} - -void cs4231_update(void) { -} - -// 廃止:cs4231g.cで調整 -void cs4231_setvol(UINT vol) { - - (void)vol; -} - -// CS4231 DMA処理 -void cs4231_dma(NEVENTITEM item) { - - DMACH dmach; - UINT rem; - UINT pos; - UINT size; - UINT r = 0; - //SINT32 cnt; - if (item->flag & NEVENT_SETEVENT) { - if (cs4231.dmach != 0xff && !(cs4231.reg.iface & PPIO)) { - dmach = dmac.dmach + cs4231.dmach; - - // サウンド再生用バッファに送る(cs4231g.c) - sound_sync(); - - // バッファに空きがあればデータを読み出す -#if defined(SUPPORT_MULTITHREAD) - cs4231cs_enter_criticalsection(); -#endif - if (cs4231.bufsize * cs4231_playcountshift[cs4231.reg.datafmt >> 4] / 4 - 4 > cs4231.bufdatas) { - rem = MIN(cs4231.bufsize - 4 - cs4231.bufdatas, CS4231_MAXDMAREADBYTES); //読み取り単位は16bitステレオの1サンプル分(4byte)にしておかないと雑音化する - pos = cs4231.bufwpos & CS4231_BUFMASK; // バッファ書き込み位置 - size = MIN(rem, (UINT)dmach->startcount + 1); // バッファ書き込みサイズ - r = dmac_getdata_(dmach, cs4231.buffer, pos, size); // DMA読み取り実行 - cs4231.bufwpos = (cs4231.bufwpos + r) & CS4231_BUFMASK; // バッファ書き込み位置を更新 - cs4231.bufdatas += r; // バッファ内の有効なデータ数を更新 = (bufwpos-bufpos)&CS4231_BUFMASK - } -#if defined(SUPPORT_MULTITHREAD) - cs4231cs_leave_criticalsection(); -#endif - - // NEVENTをセット - if (cs4231cfg.rate) { - playcountsmp_Ictl += ((CS4231_BUFREADSMP - (int)r) / cs4231_playcountshift[cs4231.reg.datafmt >> 4])/2; - if(playcountsmp_Ictl < 1) - playcountsmp_Ictl = 1; - if(playcountsmp_Ictl > CS4231_MAXDMAREADBYTES) - playcountsmp_Ictl = CS4231_MAXDMAREADBYTES; - nevent_set(NEVENT_CS4231, pccore.realclock / cs4231cfg.rate * playcountsmp_Ictl, cs4231_dma, NEVENT_RELATIVE); - } - } - } - (void)item; -} - -// PIO再生用 -void cs4231_datasend(REG8 dat) { - UINT pos; - if (cs4231.reg.iface & PPIO) { // PIO play enable - if (cs4231.bufdatas > 0) - { - sound_sync(); - } -#if defined(SUPPORT_MULTITHREAD) - cs4231cs_enter_criticalsection(); -#endif - if (cs4231.bufsize > cs4231.bufdatas) { - pos = (cs4231.bufwpos) & CS4231_BUFMASK; - cs4231.buffer[pos] = dat; - cs4231.bufdatas++; - cs4231.bufwpos = (cs4231.bufwpos + 1) & CS4231_BUFMASK; - } - if (cs4231.bufdatas > CS4231_PIOBUFFERS) - { - cs4231.intflag &= ~PRDY; - } - else - { - cs4231.intflag |= PRDY; - } -#if defined(SUPPORT_MULTITHREAD) - cs4231cs_leave_criticalsection(); -#endif - } -} - -// DMA再生開始・終了・中断時に呼ばれる(つもり) -REG8 DMACCALL cs4231dmafunc(REG8 func) { - DMACH dmach; - SINT32 cnt; - switch(func) { - case DMAEXT_START: - if (cs4231cfg.rate) { -#if defined(SUPPORT_MULTITHREAD) - cs4231cs_enter_criticalsection(); -#endif - // DMA読み取り数カウンタを初期化 - cs4231.totalsample = 0; - - // ディレイ再生カウンタもリセット - cs4231_bufdelaycounter = 0; - - // 再生位置も戻す - cs4231.bufpos = cs4231.bufwpos; - cs4231.bufdatas = 0; - cs4231.pos12 = 0; - -#if defined(SUPPORT_MULTITHREAD) - cs4231cs_leave_criticalsection(); -#endif - // DMA読み取り処理開始(NEVENTセット) - playcountsmp_Ictl = CS4231_BUFREADSMP; - cnt = (pccore.realclock / cs4231cfg.rate * playcountsmp_Ictl) / 2; - if (cnt < 1) cnt = 1; - nevent_set(NEVENT_CS4231, cnt, cs4231_dma, NEVENT_ABSOLUTE); - } - break; - case DMAEXT_END: - // ここでの割り込みは要らない? - //if ((cs4231.reg.pinctrl & IEN) && (cs4231.dmairq != 0xff)) { - // cs4231.intflag |= INt; - // cs4231.reg.featurestatus |= PI; - // pic_setirq(cs4231.dmairq); - //} - - break; - - case DMAEXT_BREAK: - // DMA読み取り処理終了(NEVENT解除) - nevent_reset(NEVENT_CS4231); - - break; - - } - return(0); -} - -// バッファ位置のズレ修正用(雑音化防止) -static void setdataalign(void) { - - UINT step; - - // バッファ位置がズレていたら修正(4byte単位に) - step = (0 - cs4231.bufpos) & 3; - if (step) { - cs4231.bufpos += step; - cs4231.bufdatas -= MIN(step, cs4231.bufdatas); - } - cs4231.bufdatas &= ~3; - step = (0 - cs4231.bufwpos) & 3; - if (step) { - cs4231.bufwpos += step; - } -} - -// CS4231 Indexed Data registerのWRITE処理 -void cs4231_control(UINT idx, REG8 dat) { - UINT8 modify; - DMACH dmach; - switch(idx){ - case 0x2: // Left Auxiliary #1 Input Control - if(g_nSoundID==SOUNDID_WAVESTAR){ - UINT i; - if(dat >= 0x10) dat = 15; - cs4231.devvolume[0xff] = (~dat) & 15; - opngen_setvol(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - psggen_setvol(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - rhythm_setvol(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); -#if defined(SUPPORT_FMGEN) - if(np2cfg.usefmgen) { - opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - } -#endif - for (i = 0; i < NELEMENTS(g_opna); i++) - { - rhythm_update(&g_opna[i].rhythm); - } - oplgen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); - } - break; - case 0x3: // Right Auxiliary #1 Input Control - if(g_nSoundID==SOUNDID_WAVESTAR){ - // XXX: 本当は左右のボリューム調整が必要 - } - break; - case 0xd: - break; - case 0xc: - // MODE and ID (I12) - dat &= 0x40; - dat |= 0x8a; - break; - case 0xb://ErrorStatus - case 0x19://Version ID - return; - case CS4231REG_IRQSTAT: - // バッファオーバーラン・アンダーランや割り込みの状態を表すレジスタ Alternate Feature Status (I24) - // 0をセットしたビットだけ消す(1の場合はそのまま) - modify = ((UINT8 *)&cs4231.reg)[idx] & (~(dat|0x0f)); - ((UINT8 *)&cs4231.reg)[idx] &= dat|0x0f; - if (modify & (PI|TI|CI)) { - // PI,TI,CIビットが全て消去されていたら割り込み解除 - if(((((UINT8 *)&cs4231.reg)[idx]) & (PI|TI|CI)) == 0){ - pic_resetirq(cs4231.dmairq); - cs4231.intflag &= ~INt; - } - } - return; // 他とは処理が違うので抜ける - default: - break; - - } - dmach = dmac.dmach + cs4231.dmach; - modify = ((UINT8 *)&cs4231.reg)[idx] ^ dat; // 変更されたビットを取得 - ((UINT8 *)&cs4231.reg)[idx] = dat; // レジスタ値を新しい値に変更 - switch(idx) { - case CS4231REG_PLAYFMT: - // 再生フォーマット設定とか Fs and Playback Data Format (I8) - if (modify & 0xf0) { - //dmach->adrs.d = dmach->startaddr; - cs4231.bufpos = cs4231.bufwpos; - cs4231.bufdatas = 0; - setdataalign(); - } - if (cs4231cfg.rate) { - UINT32 r; - r = cs4231xtal64[dat & 1] / cs4231cnt64[(dat >> 1) & 7]; - TRACEOUT(("samprate = %d", r)); - r <<= 12; - r /= cs4231cfg.rate; - cs4231.step12 = r; - TRACEOUT(("step12 = %d", r)); - } - else { - cs4231.step12 = 0; - } - // DMA読み取り位置を戻す - dmach->adrs.d = dmach->startaddr; - break; - case CS4231REG_INTERFACE: - // 再生録音の有効無効とかDMAとかの設定 Interface Configuration (I9) - if (modify & PEN ) { - if (cs4231.dmach != 0xff) { - dmach = dmac.dmach + cs4231.dmach; - if ((dat & (PEN)) == (PEN)){ - dmach->ready = 1; - } - else { - dmach->ready = 0; - } - dmac_check(); - } - if (!(dat & PEN)) { // stop! - cs4231.pos12 = 0; - } - } - break; - } -} - -// CS4231 DMAデータ読み取り -UINT dmac_getdata_(DMACH dmach, UINT8 *buf, UINT offset, UINT size) { - UINT leng; // 読み取り数 - UINT lengsum; // 合計読み取り数 - UINT32 addr; - UINT i; - SINT32 sampleirq = 0; // 割り込みまでに必要なデータ転送数(byte) - - lengsum = 0; - while(size > 0) { - leng = MIN(dmach->leng.w, size); - if (leng) { - int playcount = ((cs4231.reg.playcount[1]|(cs4231.reg.playcount[0] << 8))) * cs4231_playcountshift[cs4231.reg.datafmt >> 4]+4; // PI割り込みを発生させるサンプル数(Playback Base register) * サンプルあたりのバイト数 - if(cs4231.totalsample + (SINT32)leng > playcount){ - // DMA再生サンプル数カウンタ(Playback DMA count register)がPI割り込みを発生させるサンプル数(Playback Base register)を超えないように調整 - leng = playcount - cs4231.totalsample; - } - - addr = dmach->adrs.d; // 現在のメモリ読み取り位置 - if (!(dmach->mode & 0x20)) { // dir + - // +方向にDMA転送 - for (i=0; i CS4231 BUFFER - addr++; - if(addr > dmach->lastaddr){ - addr = dmach->startaddr; // DMA読み取りアドレスがアドレス範囲の最後に到達したら最初に戻す - } - offset = (offset+1) & CS4231_BUFMASK; // DMAデータ読み取りバッファの書き込み位置を進める(&最後に到達したら最初に戻す) - } - - dmach->adrs.d = addr; // DMA読み取りアドレス現在位置を更新 - } - else { // dir - - // -方向にDMA転送 - for (i=0; i CS4231 BUFFER - addr--; - if(addr < dmach->startaddr){ - addr = dmach->lastaddr; // DMA読み取りアドレスがアドレス範囲の最初に到達したら最後に戻す - } - offset = (offset+1) & CS4231_BUFMASK; // DMAデータ読み取りバッファの書き込み位置を進める(&最後に到達したら最初に戻す) - } - dmach->adrs.d = addr; - } - - // 読み取りバイト数だけdmach->leng.wを減らす(0以下になったらdmach->startcount+1に戻す) - if (dmach->leng.w <= leng) { - dmach->leng.w = (UINT16)((UINT)dmach->leng.w + dmach->startcount + 1 - leng); // 戻す - dmach->proc.extproc(DMAEXT_END); - }else{ - dmach->leng.w -= leng; - } - - // 読み取り数と残り数更新 - lengsum += leng; - size -= leng; - - // 読み取り数カウント - cs4231.totalsample += leng; - - // DMA再生バイト数カウンタ(Playback DMA count register)がPI割り込みを発生させるバイト数になったらPI割り込みを発生させる - if(cs4231.totalsample >= playcount){ - cs4231.totalsample -= playcount; - // 割り込みが有効な場合割り込みを発生させる - if ((cs4231.reg.pinctrl & IEN) && (cs4231.dmairq != 0xff)) { - cs4231.intflag |= INt; // 割り込み中(Interrupt Status)ビットをセット - cs4231.reg.featurestatus |= PI; // PI(Playback Interrupt)ビットをセット - pic_setirq(cs4231.dmairq); // 割り込みを発生させる - } - break; - } - }else{ - break; - } - } - - return(lengsum); -} - +/** + * @file cs4231c.c + * @brief Implementation of the CS4231 + */ + +#include +#include +#include +#include +#include +#include +#ifndef CPU_STAT_PM +#define CPU_STAT_PM 0 +#endif +#define CS4231_BUFREADSMP 128 + + CS4231CFG cs4231cfg; + + int cs4231_bufdelaycounter = 0; + + static int playcountsmp_Ictl = CS4231_BUFREADSMP; // 積分制御で無理やり一定サンプルずつ読むようにする・・・ + +// 1サンプルあたりのバイト数(モノラル, ステレオの順) +static const SINT32 cs4231_playcountshift[16] = { + 1 , // 0: 8bit PCM + 1*2, + 1 , // 1: u-Law + 1 , + 1*2, // 2: 16bit PCM(little endian)? + 1*4, + 1 , // 3: A-Law + 1 , + 1 , // 4: + 1 , + 1 , // 5: ADPCM + 1 , + 1*2, // 6: 16bit PCM + 1*4, + 1 , // 7: ADPCM + 1 }; + +// Indirect Mapped Registers +enum { + CS4231REG_LINPUT = 0x00, // Left ADC Input Control (I0) + CS4231REG_RINPUT = 0x01, // Right ADC Input Control (I1) + CS4231REG_AUX1L = 0x02, // Left Auxiliary #1 Input Control (I2) + CS4231REG_AUX1R = 0x03, // Right Auxiliary #1 Input Control (I3) + CS4231REG_AUX2L = 0x04, // Left Auxiliary #2 Input Control (I4) + CS4231REG_AUX2R = 0x05, // Right Auxiliary #2 Input Control (I5) + CS4231REG_LOUTPUT = 0x06, // Left DAC Output Control (I6) + CS4231REG_ROUTPUT = 0x07, // Right DAC Output Control (I7) + CS4231REG_PLAYFMT = 0x08, // Fs and Playback Data Format (I8) + CS4231REG_INTERFACE = 0x09, // Interface Configuration (I9) + CS4231REG_PINCTRL = 0x0a, // Pin Control (I10) + CS4231REG_TESTINIT = 0x0b, // Error Status and Initialization (I11, Read Only) + CS4231REG_MISCINFO = 0x0c, // MODE and ID (I12) + CS4231REG_LOOPBACK = 0x0d, // Loopback Control (I13) + CS4231REG_PLAYCNTM = 0x0e, // Playback Upper Base (I14) + CS4231REG_PLAYCNTL = 0x0f, // Playback Lower Base (I15) + + CS4231REG_FEATURE1 = 0x10, // Alternate Feature Enable I (I16) + CS4231REG_FEATURE2 = 0x11, // Alternate Feature Enable II (I17) + CS4231REG_LLINEIN = 0x12, // Left Line Input Control (I18) + CS4231REG_RLINEIN = 0x13, // Right Line Input Control (I19) + CS4231REG_TIMERL = 0x14, // Timer Lower Base (I20) + CS4231REG_TIMERH = 0x15, // Timer Upper Base (I21) + CS4231REG_RESERVED1 = 0x16, // RESERVED (I22) + CS4231REG_RESERVED2 = 0x17, // Alternate Feature Enable III (I23) + CS4231REG_IRQSTAT = 0x18, // Alternate Feature Status (I24) + CS4231REG_VERSION = 0x19, // Version / ID (I25) + CS4231REG_MONOCTRL = 0x1a, // Mono Input & Output Control (I26) + CS4231REG_RESERVED3 = 0x1b, // RESERVED (I27) + CS4231REG_RECFMT = 0x1c, // Capture Data Format (I28) + CS4231REG_PLAYFREQ = 0x1d, // RESERVED (I29) + CS4231REG_RECCNTM = 0x1e, // Capture Upper Base (I30) + CS4231REG_RECCNTL = 0x1f // Capture Lower Base (I31) +}; + + +UINT dmac_getdata_(DMACH dmach, UINT8 *buf, UINT offset, UINT size); +static const UINT32 cs4231xtal64[2] = {24576000/64, 16934400/64}; + +static const UINT8 cs4231cnt64[8] = { + 3072/64, // 8000/ 5510 + 1536/64, // 16000/11025 + 896/64, // 27420/18900 + 768/64, // 32000/22050 + 448/64, // 54840/37800 + 384/64, // 64000/44100 + 512/64, // 48000/33075 + 2560/64}; // 9600/ 6620 + +// 640:441 + +#if defined(SUPPORT_MULTITHREAD) +static int cs4231_cs_initialized = 0; +static CRITICAL_SECTION cs4231_cs; + +void cs4231cs_enter_criticalsection(void) +{ + if (!cs4231_cs_initialized) return; + EnterCriticalSection(&cs4231_cs); +} +void cs4231cs_leave_criticalsection(void) +{ + if (!cs4231_cs_initialized) return; + LeaveCriticalSection(&cs4231_cs); +} + +void cs4231cs_initialize(void) +{ + /* クリティカルセクション準備 */ + if (!cs4231_cs_initialized) + { + memset(&cs4231_cs, 0, sizeof(cs4231_cs)); + InitializeCriticalSection(&cs4231_cs); + cs4231_cs_initialized = 1; + } +} +void cs4231cs_shutdown(void) +{ + /* クリティカルセクション破棄 */ + if (cs4231_cs_initialized) + { + memset(&cs4231_cs, 0, sizeof(cs4231_cs)); + DeleteCriticalSection(&cs4231_cs); + cs4231_cs_initialized = 0; + } +} +#endif + +void cs4231_initialize(UINT rate) { + + cs4231cfg.rate = rate; +} + +void cs4231_reset(void) { + + ZeroMemory(&cs4231, sizeof(cs4231)); + cs4231.bufsize = CS4231_BUFFERS; +// cs4231.proc = cs4231_nodecode; + cs4231.dmach = 0xff; + cs4231.dmairq = 0xff; + cs4231.totalsample = 0; + FillMemory(cs4231.port, sizeof(cs4231.port), 0xff); +} + +void cs4231_update(void) { +} + +// 廃止:cs4231g.cで調整 +void cs4231_setvol(UINT vol) { + + (void)vol; +} + +// CS4231 DMA処理 +void cs4231_dma(NEVENTITEM item) { + + DMACH dmach; + UINT rem; + UINT pos; + UINT size; + UINT r = 0; + //SINT32 cnt; + if (item->flag & NEVENT_SETEVENT) { + if (cs4231.dmach != 0xff && !(cs4231.reg.iface & PPIO)) { + dmach = dmac.dmach + cs4231.dmach; + + // サウンド再生用バッファに送る(cs4231g.c) + sound_sync(); + + // バッファに空きがあればデータを読み出す +#if defined(SUPPORT_MULTITHREAD) + cs4231cs_enter_criticalsection(); +#endif + if (cs4231.bufsize * cs4231_playcountshift[cs4231.reg.datafmt >> 4] / 4 - 4 > cs4231.bufdatas) { + rem = MIN(cs4231.bufsize - 4 - cs4231.bufdatas, CS4231_MAXDMAREADBYTES); //読み取り単位は16bitステレオの1サンプル分(4byte)にしておかないと雑音化する + pos = cs4231.bufwpos & CS4231_BUFMASK; // バッファ書き込み位置 + size = MIN(rem, (UINT)dmach->startcount + 1); // バッファ書き込みサイズ + r = dmac_getdata_(dmach, cs4231.buffer, pos, size); // DMA読み取り実行 + cs4231.bufwpos = (cs4231.bufwpos + r) & CS4231_BUFMASK; // バッファ書き込み位置を更新 + cs4231.bufdatas += r; // バッファ内の有効なデータ数を更新 = (bufwpos-bufpos)&CS4231_BUFMASK + } +#if defined(SUPPORT_MULTITHREAD) + cs4231cs_leave_criticalsection(); +#endif + + // NEVENTをセット + if (cs4231cfg.rate) { + playcountsmp_Ictl += ((CS4231_BUFREADSMP - (int)r) / cs4231_playcountshift[cs4231.reg.datafmt >> 4])/2; + if(playcountsmp_Ictl < 1) + playcountsmp_Ictl = 1; + if(playcountsmp_Ictl > CS4231_MAXDMAREADBYTES) + playcountsmp_Ictl = CS4231_MAXDMAREADBYTES; + nevent_set(NEVENT_CS4231, pccore.realclock / cs4231cfg.rate * playcountsmp_Ictl, cs4231_dma, NEVENT_RELATIVE); + } + } + } + (void)item; +} + +// PIO再生用 +void cs4231_datasend(REG8 dat) { + UINT pos; + if (cs4231.reg.iface & PPIO) { // PIO play enable + if (cs4231.bufdatas > 0) + { + sound_sync(); + } +#if defined(SUPPORT_MULTITHREAD) + cs4231cs_enter_criticalsection(); +#endif + if (cs4231.bufsize > cs4231.bufdatas) { + pos = (cs4231.bufwpos) & CS4231_BUFMASK; + cs4231.buffer[pos] = dat; + cs4231.bufdatas++; + cs4231.bufwpos = (cs4231.bufwpos + 1) & CS4231_BUFMASK; + } + if (cs4231.bufdatas > CS4231_PIOBUFFERS) + { + cs4231.intflag &= ~PRDY; + } + else + { + cs4231.intflag |= PRDY; + } +#if defined(SUPPORT_MULTITHREAD) + cs4231cs_leave_criticalsection(); +#endif + } +} + +// DMA再生開始・終了・中断時に呼ばれる(つもり) +REG8 DMACCALL cs4231dmafunc(REG8 func) { + DMACH dmach; + SINT32 cnt; + switch(func) { + case DMAEXT_START: + if (cs4231cfg.rate) { +#if defined(SUPPORT_MULTITHREAD) + cs4231cs_enter_criticalsection(); +#endif + // DMA読み取り数カウンタを初期化 + cs4231.totalsample = 0; + + // ディレイ再生カウンタもリセット + cs4231_bufdelaycounter = 0; + + // 再生位置も戻す + cs4231.bufpos = cs4231.bufwpos; + cs4231.bufdatas = 0; + cs4231.pos12 = 0; + +#if defined(SUPPORT_MULTITHREAD) + cs4231cs_leave_criticalsection(); +#endif + // DMA読み取り処理開始(NEVENTセット) + playcountsmp_Ictl = CS4231_BUFREADSMP; + cnt = (pccore.realclock / cs4231cfg.rate * playcountsmp_Ictl) / 2; + if (cnt < 1) cnt = 1; + nevent_set(NEVENT_CS4231, cnt, cs4231_dma, NEVENT_ABSOLUTE); + } + break; + case DMAEXT_END: + // ここでの割り込みは要らない? + //if ((cs4231.reg.pinctrl & IEN) && (cs4231.dmairq != 0xff)) { + // cs4231.intflag |= INt; + // cs4231.reg.featurestatus |= PI; + // pic_setirq(cs4231.dmairq); + //} + + break; + + case DMAEXT_BREAK: + // DMA読み取り処理終了(NEVENT解除) + nevent_reset(NEVENT_CS4231); + + break; + + } + return(0); +} + +// バッファ位置のズレ修正用(雑音化防止) +static void setdataalign(void) { + + UINT step; + + // バッファ位置がズレていたら修正(4byte単位に) + step = (0 - cs4231.bufpos) & 3; + if (step) { + cs4231.bufpos += step; + cs4231.bufdatas -= MIN(step, cs4231.bufdatas); + } + cs4231.bufdatas &= ~3; + step = (0 - cs4231.bufwpos) & 3; + if (step) { + cs4231.bufwpos += step; + } +} + +// CS4231 Indexed Data registerのWRITE処理 +void cs4231_control(UINT idx, REG8 dat) { + UINT8 modify; + DMACH dmach; + switch(idx){ + case 0x2: // Left Auxiliary #1 Input Control + if(g_nSoundID==SOUNDID_WAVESTAR){ + UINT i; + if(dat >= 0x10) dat = 15; + cs4231.devvolume[0xff] = (~dat) & 15; + opngen_setvol(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + psggen_setvol(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + rhythm_setvol(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); +#if defined(SUPPORT_FMGEN) + if(np2cfg.usefmgen) { + opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + } +#endif + for (i = 0; i < NELEMENTS(g_opna); i++) + { + rhythm_update(&g_opna[i].rhythm); + } + oplgen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); + } + break; + case 0x3: // Right Auxiliary #1 Input Control + if(g_nSoundID==SOUNDID_WAVESTAR){ + // XXX: 本当は左右のボリューム調整が必要 + } + break; + case 0xd: + break; + case 0xc: + // MODE and ID (I12) + dat &= 0x40; + dat |= 0x8a; + break; + case 0xb://ErrorStatus + case 0x19://Version ID + return; + case CS4231REG_IRQSTAT: + // バッファオーバーラン・アンダーランや割り込みの状態を表すレジスタ Alternate Feature Status (I24) + // 0をセットしたビットだけ消す(1の場合はそのまま) + modify = ((UINT8 *)&cs4231.reg)[idx] & (~(dat|0x0f)); + ((UINT8 *)&cs4231.reg)[idx] &= dat|0x0f; + if (modify & (PI|TI|CI)) { + // PI,TI,CIビットが全て消去されていたら割り込み解除 + if(((((UINT8 *)&cs4231.reg)[idx]) & (PI|TI|CI)) == 0){ + pic_resetirq(cs4231.dmairq); + cs4231.intflag &= ~INt; + } + } + return; // 他とは処理が違うので抜ける + default: + break; + + } + dmach = dmac.dmach + cs4231.dmach; + modify = ((UINT8 *)&cs4231.reg)[idx] ^ dat; // 変更されたビットを取得 + ((UINT8 *)&cs4231.reg)[idx] = dat; // レジスタ値を新しい値に変更 + switch(idx) { + case CS4231REG_PLAYFMT: + // 再生フォーマット設定とか Fs and Playback Data Format (I8) + if (modify & 0xf0) { + //dmach->adrs.d = dmach->startaddr; + cs4231.bufpos = cs4231.bufwpos; + cs4231.bufdatas = 0; + setdataalign(); + } + if (cs4231cfg.rate) { + UINT32 r; + r = cs4231xtal64[dat & 1] / cs4231cnt64[(dat >> 1) & 7]; + TRACEOUT(("samprate = %d", r)); + r <<= 12; + r /= cs4231cfg.rate; + cs4231.step12 = r; + TRACEOUT(("step12 = %d", r)); + } + else { + cs4231.step12 = 0; + } + // DMA読み取り位置を戻す + dmach->adrs.d = dmach->startaddr; + break; + case CS4231REG_INTERFACE: + // 再生録音の有効無効とかDMAとかの設定 Interface Configuration (I9) + if (modify & PEN ) { + if (cs4231.dmach != 0xff) { + dmach = dmac.dmach + cs4231.dmach; + if ((dat & (PEN)) == (PEN)){ + dmach->ready = 1; + } + else { + dmach->ready = 0; + } + dmac_check(); + } + if (!(dat & PEN)) { // stop! + cs4231.pos12 = 0; + } + } + break; + } +} + +// CS4231 DMAデータ読み取り +UINT dmac_getdata_(DMACH dmach, UINT8 *buf, UINT offset, UINT size) { + UINT leng; // 読み取り数 + UINT lengsum; // 合計読み取り数 + UINT32 addr; + UINT i; + SINT32 sampleirq = 0; // 割り込みまでに必要なデータ転送数(byte) + + lengsum = 0; + while(size > 0) { + leng = MIN(dmach->leng.w, size); + if (leng) { + int playcount = ((cs4231.reg.playcount[1]|(cs4231.reg.playcount[0] << 8))) * cs4231_playcountshift[cs4231.reg.datafmt >> 4]+4; // PI割り込みを発生させるサンプル数(Playback Base register) * サンプルあたりのバイト数 + if(cs4231.totalsample + (SINT32)leng > playcount){ + // DMA再生サンプル数カウンタ(Playback DMA count register)がPI割り込みを発生させるサンプル数(Playback Base register)を超えないように調整 + leng = playcount - cs4231.totalsample; + } + + addr = dmach->adrs.d; // 現在のメモリ読み取り位置 + if (!(dmach->mode & 0x20)) { // dir + + // +方向にDMA転送 + for (i=0; i CS4231 BUFFER + addr++; + if(addr > dmach->lastaddr){ + addr = dmach->startaddr; // DMA読み取りアドレスがアドレス範囲の最後に到達したら最初に戻す + } + offset = (offset+1) & CS4231_BUFMASK; // DMAデータ読み取りバッファの書き込み位置を進める(&最後に到達したら最初に戻す) + } + + dmach->adrs.d = addr; // DMA読み取りアドレス現在位置を更新 + } + else { // dir - + // -方向にDMA転送 + for (i=0; i CS4231 BUFFER + addr--; + if(addr < dmach->startaddr){ + addr = dmach->lastaddr; // DMA読み取りアドレスがアドレス範囲の最初に到達したら最後に戻す + } + offset = (offset+1) & CS4231_BUFMASK; // DMAデータ読み取りバッファの書き込み位置を進める(&最後に到達したら最初に戻す) + } + dmach->adrs.d = addr; + } + + // 読み取りバイト数だけdmach->leng.wを減らす(0以下になったらdmach->startcount+1に戻す) + if (dmach->leng.w <= leng) { + dmach->leng.w = (UINT16)((UINT)dmach->leng.w + dmach->startcount + 1 - leng); // 戻す + dmach->proc.extproc(DMAEXT_END); + }else{ + dmach->leng.w -= leng; + } + + // 読み取り数と残り数更新 + lengsum += leng; + size -= leng; + + // 読み取り数カウント + cs4231.totalsample += leng; + + // DMA再生バイト数カウンタ(Playback DMA count register)がPI割り込みを発生させるバイト数になったらPI割り込みを発生させる + if(cs4231.totalsample >= playcount){ + cs4231.totalsample -= playcount; + // 割り込みが有効な場合割り込みを発生させる + if ((cs4231.reg.pinctrl & IEN) && (cs4231.dmairq != 0xff)) { + cs4231.intflag |= INt; // 割り込み中(Interrupt Status)ビットをセット + cs4231.reg.featurestatus |= PI; // PI(Playback Interrupt)ビットをセット + pic_setirq(cs4231.dmairq); // 割り込みを発生させる + } + break; + } + }else{ + break; + } + } + + return(lengsum); +} + diff --git a/sound/cs4231g.c b/sound/cs4231g.c old mode 100755 new mode 100644 index fc0b23ae..2fbe84ba --- a/sound/cs4231g.c +++ b/sound/cs4231g.c @@ -1,380 +1,380 @@ -/** - * @file cs4231g.c - * @brief Implementation of the CS4231 - */ - -#include -#include -#include -#include -#include - -extern CS4231CFG cs4231cfg; - -extern int cs4231_bufdelaycounter; - -static SINT32 cs4231_DACvolume_L = 1024; -static SINT32 cs4231_DACvolume_R = 1024; -static UINT16 cs4231_DACvolumereg_L = 0xff; -static UINT16 cs4231_DACvolumereg_R = 0xff; - -// 8bit モノラル -static void SOUNDCALL pcm8m(CS4231 cs, SINT32 *pcm, UINT count) { - - UINT32 leng; - UINT32 pos12; - SINT32 fract; - UINT32 samppos; -const UINT8 *ptr1; -const UINT8 *ptr2; - SINT32 samp1; - SINT32 samp2; - - leng = cs->bufdatas >> 0; - if (!leng) { - return; - } - pos12 = cs->pos12; - do { - samppos = pos12 >> 12; - if (leng <= samppos) { - break; - } - fract = pos12 & ((1 << 12) - 1); - ptr1 = cs->buffer + - ((cs->bufpos + (samppos << 0) + 0) & CS4231_BUFMASK); - ptr2 = cs->buffer + - ((cs->bufpos + (samppos << 0) + 1) & CS4231_BUFMASK); - samp1 = (ptr1[0] - 0x80) << 8; - samp2 = (ptr2[0] - 0x80) << 8; - samp1 += ((samp2 - samp1) * fract) >> 12; - pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - pcm += 2; - pos12 += cs->step12; - } while(--count); - - leng = MIN(leng, (pos12 >> 12)); - cs->bufdatas -= (leng << 0); - cs->bufpos = (cs->bufpos + (leng << 0)) & CS4231_BUFMASK; - cs->pos12 = pos12 & ((1 << 12) - 1); -} - -// 8bit ステレオ -static void SOUNDCALL pcm8s(CS4231 cs, SINT32 *pcm, UINT count) { - - UINT32 leng; - UINT32 pos12; - SINT32 fract; - UINT32 samppos; -const UINT8 *ptr1; -const UINT8 *ptr2; - SINT32 samp1; - SINT32 samp2; - - leng = cs->bufdatas >> 1; - if (!leng) { - return; - } - pos12 = cs->pos12; - do { - samppos = pos12 >> 12; - if (leng <= samppos) { - break; - } - fract = pos12 & ((1 << 12) - 1); - ptr1 = cs->buffer + - ((cs->bufpos + (samppos << 1) + 0) & CS4231_BUFMASK); - ptr2 = cs->buffer + - ((cs->bufpos + (samppos << 1) + 2) & CS4231_BUFMASK); - samp1 = (ptr1[0] - 0x80) << 8; - samp2 = (ptr2[0] - 0x80) << 8; - samp1 += ((samp2 - samp1) * fract) >> 12; - pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - samp1 = (ptr1[1] - 0x80) << 8; - samp2 = (ptr2[1] - 0x80) << 8; - samp1 += ((samp2 - samp1) * fract) >> 12; - pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - pcm += 2; - pos12 += cs->step12; - } while(--count); - - leng = MIN(leng, (pos12 >> 12)); - cs->bufdatas -= (leng << 1); - cs->bufpos = (cs->bufpos + (leng << 1)) & CS4231_BUFMASK; - cs->pos12 = pos12 & ((1 << 12) - 1); -} - -// 16bit モノラル -static void SOUNDCALL pcm16m(CS4231 cs, SINT32 *pcm, UINT count) { - - UINT32 leng; - UINT32 pos12; - SINT32 fract; - UINT32 samppos; -const UINT8 *ptr1; -const UINT8 *ptr2; - SINT32 samp1; - SINT32 samp2; - - leng = cs->bufdatas >> 1; - if (!leng) { - return; - } - pos12 = cs->pos12; - do { - samppos = pos12 >> 12; - if (leng <= samppos) { - break; - } - fract = pos12 & ((1 << 12) - 1); - ptr1 = cs->buffer + - ((cs->bufpos + (samppos << 1) + 0) & CS4231_BUFMASK); - ptr2 = cs->buffer + - ((cs->bufpos + (samppos << 1) + 2) & CS4231_BUFMASK); - samp1 = (((SINT8)ptr1[0]) << 8) + ptr1[1]; - samp2 = (((SINT8)ptr2[0]) << 8) + ptr2[1]; - samp1 += ((samp2 - samp1) * fract) >> 12; - pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - pcm += 2; - pos12 += cs->step12; - } while(--count); - - leng = MIN(leng, (pos12 >> 12)); - cs->bufdatas -= (leng << 1); - cs->bufpos = (cs->bufpos + (leng << 1)) & CS4231_BUFMASK; - cs->pos12 = pos12 & ((1 << 12) - 1); -} - -// 16bit ステレオ -static void SOUNDCALL pcm16s(CS4231 cs, SINT32 *pcm, UINT count) { - - UINT32 leng; - UINT32 pos12; - SINT32 fract; - UINT32 samppos; -const UINT8 *ptr1; -const UINT8 *ptr2; - SINT32 samp1; - SINT32 samp2; - - leng = cs->bufdatas >> 2; - if (!leng) { - return; - } - pos12 = cs->pos12; - do { - samppos = pos12 >> 12; - if (leng <= samppos) { - break; - } - fract = pos12 & ((1 << 12) - 1); - ptr1 = cs->buffer + - ((cs->bufpos + (samppos << 2) + 0) & CS4231_BUFMASK); - ptr2 = cs->buffer + - ((cs->bufpos + (samppos << 2) + 4) & CS4231_BUFMASK); - samp1 = (((SINT8)ptr1[0]) << 8) + ptr1[1]; - samp2 = (((SINT8)ptr2[0]) << 8) + ptr2[1]; - samp1 += ((samp2 - samp1) * fract) >> 12; - pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - samp1 = (((SINT8)ptr1[2]) << 8) + ptr1[3]; - samp2 = (((SINT8)ptr2[2]) << 8) + ptr2[3]; - samp1 += ((samp2 - samp1) * fract) >> 12; - pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - pcm += 2; - pos12 += cs->step12; - } while(--count); - - leng = MIN(leng, (pos12 >> 12)); - cs->bufdatas -= (leng << 2); - cs->bufpos = (cs->bufpos + (leng << 2)) & CS4231_BUFMASK; - cs->pos12 = pos12 & ((1 << 12) - 1); -} - -// 16bit モノラル(little endian) -static void SOUNDCALL pcm16m_ex(CS4231 cs, SINT32 *pcm, UINT count) { - - UINT32 leng; - UINT32 pos12; - SINT32 fract; - UINT32 samppos; -const UINT8 *ptr1; -const UINT8 *ptr2; - SINT32 samp1; - SINT32 samp2; - - leng = cs->bufdatas >> 1; - if (!leng) { - return; - } - pos12 = cs->pos12; - do { - samppos = pos12 >> 12; - if (leng <= samppos) { - break; - } - fract = pos12 & ((1 << 12) - 1); - ptr1 = cs->buffer + - ((cs->bufpos + (samppos << 1) + 0) & CS4231_BUFMASK); - ptr2 = cs->buffer + - ((cs->bufpos + (samppos << 1) + 2) & CS4231_BUFMASK); - samp1 = (((SINT8)ptr1[1]) << 8) + ptr1[0]; - samp2 = (((SINT8)ptr2[1]) << 8) + ptr2[0]; - samp1 += ((samp2 - samp1) * fract) >> 12; - pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - pcm += 2; - pos12 += cs->step12; - } while(--count); - - leng = MIN(leng, (pos12 >> 12)); - cs->bufdatas -= (leng << 1); - cs->bufpos = (cs->bufpos + (leng << 1)) & CS4231_BUFMASK; - cs->pos12 = pos12 & ((1 << 12) - 1); -} - -// 16bit ステレオ(little endian) -static void SOUNDCALL pcm16s_ex(CS4231 cs, SINT32 *pcm, UINT count) { - - UINT32 leng; - UINT32 pos12; - SINT32 fract; - UINT32 samppos; -const UINT8 *ptr1; -const UINT8 *ptr2; - SINT32 samp1; - SINT32 samp2; - - leng = cs->bufdatas >> 2; - if (!leng) { - return; - } - pos12 = cs->pos12; - do { - samppos = pos12 >> 12; - if (leng <= samppos) { - break; - } - fract = pos12 & ((1 << 12) - 1); - ptr1 = cs->buffer + - ((cs->bufpos + (samppos << 2) + 0) & CS4231_BUFMASK); - ptr2 = cs->buffer + - ((cs->bufpos + (samppos << 2) + 4) & CS4231_BUFMASK); - samp1 = (((SINT8)ptr1[1]) << 8) + ptr1[0]; - samp2 = (((SINT8)ptr2[1]) << 8) + ptr2[0]; - samp1 += ((samp2 - samp1) * fract) >> 12; - pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - samp1 = (((SINT8)ptr1[3]) << 8) + ptr1[2]; - samp2 = (((SINT8)ptr2[3]) << 8) + ptr2[2]; - samp1 += ((samp2 - samp1) * fract) >> 12; - pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; - pcm += 2; - pos12 += cs->step12; - } while(--count); - - leng = MIN(leng, (pos12 >> 12)); - cs->bufdatas -= (leng << 2); - cs->bufpos = (cs->bufpos + (leng << 2)) & CS4231_BUFMASK; - cs->pos12 = pos12 & ((1 << 12) - 1); -} - -static void SOUNDCALL nomake(CS4231 cs, SINT32 *pcm, UINT count) { - - (void)cs; - (void)pcm; - (void)count; -} - - -typedef void (SOUNDCALL * CS4231FN)(CS4231 cs, SINT32 *pcm, UINT count); - -static const CS4231FN cs4231fn[16] = { - pcm8m, // 0: 8bit PCM - pcm8s, - nomake, // 1: u-Law - nomake, - pcm16m_ex, // 2: 16bit PCM(little endian)? - pcm16s_ex, - nomake, // 3: A-Law - nomake, - nomake, // 4: - nomake, - nomake, // 5: ADPCM - nomake, - pcm16m, // 6: 16bit PCM - pcm16s, - nomake, // 7: ADPCM - nomake}; - - -// ---- - -void SOUNDCALL cs4231_getpcm(CS4231 cs, SINT32 *pcm, UINT count) { - static int lastPlaybackEnable = 0; - - if (((cs->reg.iface & 1) || cs4231_bufdelaycounter > 0) && (count)) { - // CS4231内蔵ボリューム - if(cs4231_DACvolumereg_L != cs->reg.dac_l){ - cs4231_DACvolumereg_L = cs->reg.dac_l; - if(cs->reg.dac_l & 0x80){ // DAC L Mute - cs4231_DACvolume_L = 0; - }else{ - cs4231_DACvolume_L = (int)(pow(10, -1.5 * ((cs4231_DACvolumereg_L) & 0x3f) / 20.0) * 1024); // DAC L Volume (1bit毎に-1.5dB) - } - } - if(cs4231_DACvolumereg_R != cs->reg.dac_r){ - cs4231_DACvolumereg_R = cs->reg.dac_r; - if(cs->reg.dac_r & 0x80){ // DAC R Mute - cs4231_DACvolume_R = 0; - }else{ - cs4231_DACvolume_R = (int)(pow(10, -1.5 * ((cs4231_DACvolumereg_R) & 0x3f) / 20.0) * 1024); // DAC R Volume (1bit毎に-1.5dB) - } - } - - // 再生用バッファに送る -#if defined(SUPPORT_MULTITHREAD) - cs4231cs_enter_criticalsection(); -#endif - (*cs4231fn[cs->reg.datafmt >> 4])(cs, pcm, count); - - // PIO play enable - if (cs4231.reg.iface & PPIO) - { - if (cs4231.bufsize / 2 < cs4231.bufdatas) - { - cs4231.intflag &= ~PRDY; - } - else - { - cs4231.intflag |= PRDY; - } - } - - // Playback Enableがローになってもバッファのディレイ分は再生する - if (cs->reg.iface & 1) - { - cs4231_bufdelaycounter = 0; - lastPlaybackEnable = 1; - } - else - { - if (lastPlaybackEnable) - { - cs4231_bufdelaycounter = cs->bufdatas; - } - else if (cs->bufdatas == 0) - { - cs4231_bufdelaycounter = 0; - } - else - { - cs4231_bufdelaycounter--; - } - lastPlaybackEnable = 0; - } -#if defined(SUPPORT_MULTITHREAD) - cs4231cs_leave_criticalsection(); -#endif - } -} +/** + * @file cs4231g.c + * @brief Implementation of the CS4231 + */ + +#include +#include +#include +#include +#include + +extern CS4231CFG cs4231cfg; + +extern int cs4231_bufdelaycounter; + +static SINT32 cs4231_DACvolume_L = 1024; +static SINT32 cs4231_DACvolume_R = 1024; +static UINT16 cs4231_DACvolumereg_L = 0xff; +static UINT16 cs4231_DACvolumereg_R = 0xff; + +// 8bit モノラル +static void SOUNDCALL pcm8m(CS4231 cs, SINT32 *pcm, UINT count) { + + UINT32 leng; + UINT32 pos12; + SINT32 fract; + UINT32 samppos; +const UINT8 *ptr1; +const UINT8 *ptr2; + SINT32 samp1; + SINT32 samp2; + + leng = cs->bufdatas >> 0; + if (!leng) { + return; + } + pos12 = cs->pos12; + do { + samppos = pos12 >> 12; + if (leng <= samppos) { + break; + } + fract = pos12 & ((1 << 12) - 1); + ptr1 = cs->buffer + + ((cs->bufpos + (samppos << 0) + 0) & CS4231_BUFMASK); + ptr2 = cs->buffer + + ((cs->bufpos + (samppos << 0) + 1) & CS4231_BUFMASK); + samp1 = (ptr1[0] - 0x80) << 8; + samp2 = (ptr2[0] - 0x80) << 8; + samp1 += ((samp2 - samp1) * fract) >> 12; + pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + pcm += 2; + pos12 += cs->step12; + } while(--count); + + leng = MIN(leng, (pos12 >> 12)); + cs->bufdatas -= (leng << 0); + cs->bufpos = (cs->bufpos + (leng << 0)) & CS4231_BUFMASK; + cs->pos12 = pos12 & ((1 << 12) - 1); +} + +// 8bit ステレオ +static void SOUNDCALL pcm8s(CS4231 cs, SINT32 *pcm, UINT count) { + + UINT32 leng; + UINT32 pos12; + SINT32 fract; + UINT32 samppos; +const UINT8 *ptr1; +const UINT8 *ptr2; + SINT32 samp1; + SINT32 samp2; + + leng = cs->bufdatas >> 1; + if (!leng) { + return; + } + pos12 = cs->pos12; + do { + samppos = pos12 >> 12; + if (leng <= samppos) { + break; + } + fract = pos12 & ((1 << 12) - 1); + ptr1 = cs->buffer + + ((cs->bufpos + (samppos << 1) + 0) & CS4231_BUFMASK); + ptr2 = cs->buffer + + ((cs->bufpos + (samppos << 1) + 2) & CS4231_BUFMASK); + samp1 = (ptr1[0] - 0x80) << 8; + samp2 = (ptr2[0] - 0x80) << 8; + samp1 += ((samp2 - samp1) * fract) >> 12; + pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + samp1 = (ptr1[1] - 0x80) << 8; + samp2 = (ptr2[1] - 0x80) << 8; + samp1 += ((samp2 - samp1) * fract) >> 12; + pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + pcm += 2; + pos12 += cs->step12; + } while(--count); + + leng = MIN(leng, (pos12 >> 12)); + cs->bufdatas -= (leng << 1); + cs->bufpos = (cs->bufpos + (leng << 1)) & CS4231_BUFMASK; + cs->pos12 = pos12 & ((1 << 12) - 1); +} + +// 16bit モノラル +static void SOUNDCALL pcm16m(CS4231 cs, SINT32 *pcm, UINT count) { + + UINT32 leng; + UINT32 pos12; + SINT32 fract; + UINT32 samppos; +const UINT8 *ptr1; +const UINT8 *ptr2; + SINT32 samp1; + SINT32 samp2; + + leng = cs->bufdatas >> 1; + if (!leng) { + return; + } + pos12 = cs->pos12; + do { + samppos = pos12 >> 12; + if (leng <= samppos) { + break; + } + fract = pos12 & ((1 << 12) - 1); + ptr1 = cs->buffer + + ((cs->bufpos + (samppos << 1) + 0) & CS4231_BUFMASK); + ptr2 = cs->buffer + + ((cs->bufpos + (samppos << 1) + 2) & CS4231_BUFMASK); + samp1 = (((SINT8)ptr1[0]) << 8) + ptr1[1]; + samp2 = (((SINT8)ptr2[0]) << 8) + ptr2[1]; + samp1 += ((samp2 - samp1) * fract) >> 12; + pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + pcm += 2; + pos12 += cs->step12; + } while(--count); + + leng = MIN(leng, (pos12 >> 12)); + cs->bufdatas -= (leng << 1); + cs->bufpos = (cs->bufpos + (leng << 1)) & CS4231_BUFMASK; + cs->pos12 = pos12 & ((1 << 12) - 1); +} + +// 16bit ステレオ +static void SOUNDCALL pcm16s(CS4231 cs, SINT32 *pcm, UINT count) { + + UINT32 leng; + UINT32 pos12; + SINT32 fract; + UINT32 samppos; +const UINT8 *ptr1; +const UINT8 *ptr2; + SINT32 samp1; + SINT32 samp2; + + leng = cs->bufdatas >> 2; + if (!leng) { + return; + } + pos12 = cs->pos12; + do { + samppos = pos12 >> 12; + if (leng <= samppos) { + break; + } + fract = pos12 & ((1 << 12) - 1); + ptr1 = cs->buffer + + ((cs->bufpos + (samppos << 2) + 0) & CS4231_BUFMASK); + ptr2 = cs->buffer + + ((cs->bufpos + (samppos << 2) + 4) & CS4231_BUFMASK); + samp1 = (((SINT8)ptr1[0]) << 8) + ptr1[1]; + samp2 = (((SINT8)ptr2[0]) << 8) + ptr2[1]; + samp1 += ((samp2 - samp1) * fract) >> 12; + pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + samp1 = (((SINT8)ptr1[2]) << 8) + ptr1[3]; + samp2 = (((SINT8)ptr2[2]) << 8) + ptr2[3]; + samp1 += ((samp2 - samp1) * fract) >> 12; + pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + pcm += 2; + pos12 += cs->step12; + } while(--count); + + leng = MIN(leng, (pos12 >> 12)); + cs->bufdatas -= (leng << 2); + cs->bufpos = (cs->bufpos + (leng << 2)) & CS4231_BUFMASK; + cs->pos12 = pos12 & ((1 << 12) - 1); +} + +// 16bit モノラル(little endian) +static void SOUNDCALL pcm16m_ex(CS4231 cs, SINT32 *pcm, UINT count) { + + UINT32 leng; + UINT32 pos12; + SINT32 fract; + UINT32 samppos; +const UINT8 *ptr1; +const UINT8 *ptr2; + SINT32 samp1; + SINT32 samp2; + + leng = cs->bufdatas >> 1; + if (!leng) { + return; + } + pos12 = cs->pos12; + do { + samppos = pos12 >> 12; + if (leng <= samppos) { + break; + } + fract = pos12 & ((1 << 12) - 1); + ptr1 = cs->buffer + + ((cs->bufpos + (samppos << 1) + 0) & CS4231_BUFMASK); + ptr2 = cs->buffer + + ((cs->bufpos + (samppos << 1) + 2) & CS4231_BUFMASK); + samp1 = (((SINT8)ptr1[1]) << 8) + ptr1[0]; + samp2 = (((SINT8)ptr2[1]) << 8) + ptr2[0]; + samp1 += ((samp2 - samp1) * fract) >> 12; + pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + pcm += 2; + pos12 += cs->step12; + } while(--count); + + leng = MIN(leng, (pos12 >> 12)); + cs->bufdatas -= (leng << 1); + cs->bufpos = (cs->bufpos + (leng << 1)) & CS4231_BUFMASK; + cs->pos12 = pos12 & ((1 << 12) - 1); +} + +// 16bit ステレオ(little endian) +static void SOUNDCALL pcm16s_ex(CS4231 cs, SINT32 *pcm, UINT count) { + + UINT32 leng; + UINT32 pos12; + SINT32 fract; + UINT32 samppos; +const UINT8 *ptr1; +const UINT8 *ptr2; + SINT32 samp1; + SINT32 samp2; + + leng = cs->bufdatas >> 2; + if (!leng) { + return; + } + pos12 = cs->pos12; + do { + samppos = pos12 >> 12; + if (leng <= samppos) { + break; + } + fract = pos12 & ((1 << 12) - 1); + ptr1 = cs->buffer + + ((cs->bufpos + (samppos << 2) + 0) & CS4231_BUFMASK); + ptr2 = cs->buffer + + ((cs->bufpos + (samppos << 2) + 4) & CS4231_BUFMASK); + samp1 = (((SINT8)ptr1[1]) << 8) + ptr1[0]; + samp2 = (((SINT8)ptr2[1]) << 8) + ptr2[0]; + samp1 += ((samp2 - samp1) * fract) >> 12; + pcm[0] += (samp1 * cs4231_DACvolume_L * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + samp1 = (((SINT8)ptr1[3]) << 8) + ptr1[2]; + samp2 = (((SINT8)ptr2[3]) << 8) + ptr2[2]; + samp1 += ((samp2 - samp1) * fract) >> 12; + pcm[1] += (samp1 * cs4231_DACvolume_R * ((int)np2cfg.vol_pcm * np2cfg.vol_master / 100)) >> 15; + pcm += 2; + pos12 += cs->step12; + } while(--count); + + leng = MIN(leng, (pos12 >> 12)); + cs->bufdatas -= (leng << 2); + cs->bufpos = (cs->bufpos + (leng << 2)) & CS4231_BUFMASK; + cs->pos12 = pos12 & ((1 << 12) - 1); +} + +static void SOUNDCALL nomake(CS4231 cs, SINT32 *pcm, UINT count) { + + (void)cs; + (void)pcm; + (void)count; +} + + +typedef void (SOUNDCALL * CS4231FN)(CS4231 cs, SINT32 *pcm, UINT count); + +static const CS4231FN cs4231fn[16] = { + pcm8m, // 0: 8bit PCM + pcm8s, + nomake, // 1: u-Law + nomake, + pcm16m_ex, // 2: 16bit PCM(little endian)? + pcm16s_ex, + nomake, // 3: A-Law + nomake, + nomake, // 4: + nomake, + nomake, // 5: ADPCM + nomake, + pcm16m, // 6: 16bit PCM + pcm16s, + nomake, // 7: ADPCM + nomake}; + + +// ---- + +void SOUNDCALL cs4231_getpcm(CS4231 cs, SINT32 *pcm, UINT count) { + static int lastPlaybackEnable = 0; + + if (((cs->reg.iface & 1) || cs4231_bufdelaycounter > 0) && (count)) { + // CS4231内蔵ボリューム + if(cs4231_DACvolumereg_L != cs->reg.dac_l){ + cs4231_DACvolumereg_L = cs->reg.dac_l; + if(cs->reg.dac_l & 0x80){ // DAC L Mute + cs4231_DACvolume_L = 0; + }else{ + cs4231_DACvolume_L = (int)(pow(10, -1.5 * ((cs4231_DACvolumereg_L) & 0x3f) / 20.0) * 1024); // DAC L Volume (1bit毎に-1.5dB) + } + } + if(cs4231_DACvolumereg_R != cs->reg.dac_r){ + cs4231_DACvolumereg_R = cs->reg.dac_r; + if(cs->reg.dac_r & 0x80){ // DAC R Mute + cs4231_DACvolume_R = 0; + }else{ + cs4231_DACvolume_R = (int)(pow(10, -1.5 * ((cs4231_DACvolumereg_R) & 0x3f) / 20.0) * 1024); // DAC R Volume (1bit毎に-1.5dB) + } + } + + // 再生用バッファに送る +#if defined(SUPPORT_MULTITHREAD) + cs4231cs_enter_criticalsection(); +#endif + (*cs4231fn[cs->reg.datafmt >> 4])(cs, pcm, count); + + // PIO play enable + if (cs4231.reg.iface & PPIO) + { + if (cs4231.bufsize / 2 < cs4231.bufdatas) + { + cs4231.intflag &= ~PRDY; + } + else + { + cs4231.intflag |= PRDY; + } + } + + // Playback Enableがローになってもバッファのディレイ分は再生する + if (cs->reg.iface & 1) + { + cs4231_bufdelaycounter = 0; + lastPlaybackEnable = 1; + } + else + { + if (lastPlaybackEnable) + { + cs4231_bufdelaycounter = cs->bufdatas; + } + else if (cs->bufdatas == 0) + { + cs4231_bufdelaycounter = 0; + } + else + { + cs4231_bufdelaycounter--; + } + lastPlaybackEnable = 0; + } +#if defined(SUPPORT_MULTITHREAD) + cs4231cs_leave_criticalsection(); +#endif + } +} diff --git a/sound/fmboard.c b/sound/fmboard.c old mode 100755 new mode 100644 index 289b13d5..245b5987 --- a/sound/fmboard.c +++ b/sound/fmboard.c @@ -1,610 +1,610 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_PX) -#include -#endif // defined(SUPPORT_PX) -#include -#include -#include -#include -#if defined(SUPPORT_SOUND_SB16) -#include -#endif // defined(SUPPORT_SOUND_SB16) -#include -#include -#include -#include -#include -#include -#include -#include - - - SOUNDID g_nSoundID; - OPL3 g_opl3[OPL3_MAX]; // index: 0=PC-9891-118, 1=Sound Blaster 16, 2=Sound Orchestra - OPNA g_opna[OPNA_MAX]; -#ifdef USE_MAME - void *g_mame_opl3[OPL3_MAX] = {0}; -#endif - -#if defined(SUPPORT_SOUND_SB16) - SB16 g_sb16; -#endif // defined(SUPPORT_SOUND_SB16) - - _PCM86 g_pcm86; - _CS4231 cs4231; - -static void (*extfn)(REG8 enable); - - -// ---- - -static REG8 s_rapids = 0; - -REG8 fmboard_getjoy(POPNA opna) -{ - REG8 ret; - - s_rapids ^= 0xf0; // ver0.28 - ret = 0xff; - if (!(opna->s.reg[15] & 0x40)) - { -// ret &= (joymng_getstat() | (s_rapids & 0x30)); - ret &= joymng_getstat(); - if (np2cfg.KEY_MODE == 1) - { - ret &= keystat_getjoy(); - } - } - else - { - if (np2cfg.KEY_MODE == 2) - { - ret &= keystat_getjoy(); - } - } - if (np2cfg.BTN_RAPID) - { - ret |= s_rapids; - } - - // rapidと非rapidを合成 // ver0.28 - ret &= ((ret >> 2) | (~0x30)); - - if (np2cfg.BTN_MODE) - { - UINT8 bit1 = (ret & 0x20) >> 1; // ver0.28 - UINT8 bit2 = (ret & 0x10) << 1; - ret = (ret & (~0x30)) | bit1 | bit2; - } - - // intr 反映して終わり // ver0.28 - ret &= 0x3f; - ret |= opna->s.intr; - return ret; -} - -void fmboard_updatevolume(){ - UINT volex = 15; - UINT i; - if(g_nSoundID==SOUNDID_WAVESTAR){ - volex = cs4231.devvolume[0xff]; - } - opngen_setvol(np2cfg.vol_fm * volex / 15 * np2cfg.vol_master / 100); -#if defined(SUPPORT_FMGEN) - opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * volex / 15 * np2cfg.vol_master / 100); -#endif /* SUPPORT_FMGEN */ - psggen_setvol(np2cfg.vol_ssg * volex / 15 * np2cfg.vol_master / 100); -#if defined(SUPPORT_FMGEN) - opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * volex / 15 * np2cfg.vol_master / 100); -#endif /* SUPPORT_FMGEN */ - - adpcm_setvol(np2cfg.vol_adpcm * np2cfg.vol_master / 100); -#if defined(SUPPORT_FMGEN) - opna_fmgen_setallvolumeADPCM_linear(np2cfg.vol_adpcm * np2cfg.vol_master / 100); -#endif /* SUPPORT_FMGEN */ - for (i = 0; i < OPNA_MAX; i++) - { - adpcm_update(&g_opna[i].adpcm); - } - - pcm86gen_setvol(np2cfg.vol_pcm * np2cfg.vol_master / 100); - pcm86gen_update(); - - rhythm_setvol(np2cfg.vol_rhythm * volex / 15 * np2cfg.vol_master / 100); -#if defined(SUPPORT_FMGEN) - opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * volex / 15 * np2cfg.vol_master / 100); -#endif /* SUPPORT_FMGEN */ - for (i = 0; i < OPNA_MAX; i++) - { - rhythm_update(&g_opna[i].rhythm); - } - - oplgen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); -} - - -// ---- - -void fmboard_extreg(void (*ext)(REG8 enable)) { - - extfn = ext; -} - -void fmboard_extenable(REG8 enable) { - - if (extfn) { - (*extfn)(enable); - } -} - - - -// ---- - -/** - * Constructor - */ -void fmboard_construct(void) -{ - UINT i; - - for (i = 0; i < NELEMENTS(g_opna); i++) - { - opna_construct(&g_opna[i]); - } - for (i = 0; i < NELEMENTS(g_opl3); i++) - { - opl3_construct(&g_opl3[i]); - } -} - -/** - * Destructor - */ -void fmboard_destruct(void) -{ - UINT i; - - for (i = 0; i < NELEMENTS(g_opna); i++) - { - opna_destruct(&g_opna[i]); - } - for (i = 0; i < NELEMENTS(g_opl3); i++) - { - opl3_destruct(&g_opl3[i]); - } - - board118_finalize(); -#ifdef SUPPORT_SOUND_SB16 - boardsb16_finalize(); -#endif -} - -/** - * Reset - * @param[in] pConfig The pointer of config - * @param[in] nSoundId The sound ID - */ -void fmboard_reset(const NP2CFG *pConfig, SOUNDID nSoundID) -{ - UINT i; - UINT8 cross = 0; - - soundrom_reset(); - beep_reset(); // ver0.27a - - if (g_nSoundID != nSoundID) - { - for (i = 0; i < NELEMENTS(g_opna); i++) - { - opna_reset(&g_opna[i], 0); - } - for (i = 0; i < NELEMENTS(g_opl3); i++) - { - opl3_reset(&g_opl3[i], 0); - } - } - - extfn = NULL; - pcm86_reset(); - cs4231_reset(); - - board14_reset(pConfig, (nSoundID == SOUNDID_PC_9801_14) ? TRUE : FALSE); - amd98_reset(pConfig); - - g_nSoundID = nSoundID; // XXX: 先に設定 - switch (nSoundID) - { - case SOUNDID_PC_9801_14: - break; - - case SOUNDID_PC_9801_26K: - board26k_reset(pConfig); - break; - - case SOUNDID_PC_9801_86: - board86_reset(pConfig, FALSE); - break; - - case SOUNDID_PC_9801_86_26K: - boardx2_reset(pConfig); - break; - - case SOUNDID_PC_9801_118: - board118_reset(pConfig); - break; - - case SOUNDID_PC_9801_86_WSS: - board118_reset(pConfig); - board86_reset(pConfig, TRUE); - break; - - case SOUNDID_PC_9801_86_118: - board118_reset(pConfig); - board86_reset(pConfig, TRUE); - break; - - case SOUNDID_MATE_X_PCM: - board118_reset(pConfig); - break; - - case SOUNDID_PC_9801_86_ADPCM: - board86_reset(pConfig, TRUE); - break; - - case SOUNDID_WAVESTAR: - board118_reset(pConfig); - board86_reset(pConfig, FALSE); - break; - - case SOUNDID_SPEAKBOARD: - boardspb_reset(pConfig, 0); - cross ^= pConfig->spb_x; - break; - - case SOUNDID_86_SPEAKBOARD: - boardspb_reset(pConfig, 1); - board86_reset(pConfig, FALSE); - cross ^= pConfig->spb_x; - break; - - case SOUNDID_SPARKBOARD: - boardspr_reset(pConfig); - cross ^= pConfig->spb_x; - break; - - case SOUNDID_AMD98: - amd98_reset(pConfig); - break; - - case SOUNDID_SOUNDORCHESTRA: - boardso_reset(pConfig, FALSE); - break; - - case SOUNDID_SOUNDORCHESTRAV: - boardso_reset(pConfig, TRUE); - break; - - case SOUNDID_LITTLEORCHESTRAL: - boardlol_reset(pConfig); - break; - - case SOUNDID_MMORCHESTRA: - boardmo_reset(pConfig); - break; - -#if defined(SUPPORT_SOUND_SB16) - case SOUNDID_SB16: - boardsb16_reset(pConfig); - break; - - case SOUNDID_PC_9801_86_SB16: - boardsb16_reset(pConfig); - board86_reset(pConfig, TRUE); - break; - - case SOUNDID_WSS_SB16: - boardsb16_reset(pConfig); - board118_reset(pConfig); - break; - - case SOUNDID_PC_9801_86_WSS_SB16: - boardsb16_reset(pConfig); - board118_reset(pConfig); - board86_reset(pConfig, TRUE); - break; - break; - - case SOUNDID_PC_9801_118_SB16: - boardsb16_reset(pConfig); - board118_reset(pConfig); - break; - - case SOUNDID_PC_9801_86_118_SB16: - boardsb16_reset(pConfig); - board118_reset(pConfig); - board86_reset(pConfig, TRUE); - break; -#endif - -#if defined(SUPPORT_PX) - case SOUNDID_PX1: - boardpx1_reset(pConfig); - break; - - case SOUNDID_PX2: - boardpx2_reset(pConfig); - break; -#endif // defined(SUPPORT_PX) - - default: - g_nSoundID = SOUNDID_NONE; - break; - } - soundmng_setreverse((pConfig->snd_x ^ cross) & 0x1); - opngen_setVR(pConfig->spb_vrc, pConfig->spb_vrl); -} - -void fmboard_bind(void) { - - keydisp_reset(); - switch (g_nSoundID) - { - case SOUNDID_PC_9801_14: - board14_bind(); - break; - - case SOUNDID_PC_9801_26K: - board26k_bind(); - break; - - case SOUNDID_PC_9801_86: - board86_bind(); - break; - - case SOUNDID_PC_9801_86_26K: - boardx2_bind(); - break; - - case SOUNDID_PC_9801_118: - board118_bind(); - break; - - case SOUNDID_PC_9801_86_WSS: - board118_bind(); - board86_bind(); - break; - - case SOUNDID_PC_9801_86_118: - board118_bind(); - board86_bind(); - break; - - case SOUNDID_MATE_X_PCM: - board118_bind(); - break; - - case SOUNDID_PC_9801_86_ADPCM: - board86_bind(); - break; - - case SOUNDID_WAVESTAR: - board118_bind(); - board86_bind(); - break; - - case SOUNDID_SPEAKBOARD: - boardspb_bind(); - break; - - case SOUNDID_86_SPEAKBOARD: - boardspb_bind(); - board86_bind(); - break; - - case SOUNDID_SPARKBOARD: - boardspr_bind(); - break; - - case SOUNDID_AMD98: - amd98_bind(); - break; - - case SOUNDID_SOUNDORCHESTRA: - case SOUNDID_SOUNDORCHESTRAV: - boardso_bind(); - break; - - case SOUNDID_LITTLEORCHESTRAL: - boardlol_bind(); - break; - - case SOUNDID_MMORCHESTRA: - boardmo_bind(); - break; - -#if defined(SUPPORT_SOUND_SB16) - case SOUNDID_SB16: - boardsb16_bind(); - break; - - case SOUNDID_PC_9801_86_SB16: - boardsb16_bind(); - board86_bind(); - break; - - case SOUNDID_WSS_SB16: - boardsb16_bind(); - board118_bind(); - break; - - case SOUNDID_PC_9801_86_WSS_SB16: - boardsb16_bind(); - board118_bind(); - board86_bind(); - break; - - case SOUNDID_PC_9801_118_SB16: - boardsb16_bind(); - board118_bind(); - break; - - case SOUNDID_PC_9801_86_118_SB16: - boardsb16_bind(); - board118_bind(); - board86_bind(); - break; -#endif // defined(SUPPORT_SOUND_SB16) - -#if defined(SUPPORT_PX) - case SOUNDID_PX1: - boardpx1_bind(); - break; - - case SOUNDID_PX2: - boardpx2_bind(); - break; -#endif // defined(SUPPORT_PX) - - default: - break; - } - - sound_streamregist(&g_beep, (SOUNDCB)beep_getpcm); -} - -void fmboard_unbind(void) { - - switch (g_nSoundID) - { - case SOUNDID_PC_9801_14: - board14_unbind(); - break; - - case SOUNDID_PC_9801_26K: - board26k_unbind(); - break; - - case SOUNDID_PC_9801_86: - board86_unbind(); - break; - - case SOUNDID_PC_9801_86_26K: - boardx2_unbind(); - break; - - case SOUNDID_PC_9801_118: - board118_unbind(); - break; - - case SOUNDID_PC_9801_86_WSS: - board118_unbind(); - board86_unbind(); - break; - - case SOUNDID_PC_9801_86_118: - board118_unbind(); - board86_unbind(); - break; - - case SOUNDID_MATE_X_PCM: - board118_unbind(); - break; - - case SOUNDID_PC_9801_86_ADPCM: - board86_unbind(); - break; - - case SOUNDID_WAVESTAR: - board118_unbind(); - board86_unbind(); - break; - - case SOUNDID_SPEAKBOARD: - boardspb_unbind(); - break; - - case SOUNDID_86_SPEAKBOARD: - board86_unbind(); - boardspb_unbind(); - break; - - case SOUNDID_SPARKBOARD: - boardspr_unbind(); - break; - - case SOUNDID_AMD98: - amd98_unbind(); - break; - - case SOUNDID_SOUNDORCHESTRA: - case SOUNDID_SOUNDORCHESTRAV: - boardso_unbind(); - break; - - case SOUNDID_LITTLEORCHESTRAL: - boardlol_unbind(); - break; - - case SOUNDID_MMORCHESTRA: - boardmo_unbind(); - break; - -#if defined(SUPPORT_SOUND_SB16) - case SOUNDID_SB16: - boardsb16_unbind(); - break; - - case SOUNDID_PC_9801_86_SB16: - boardsb16_unbind(); - board86_unbind(); - break; - - case SOUNDID_WSS_SB16: - boardsb16_unbind(); - board118_unbind(); - break; - - case SOUNDID_PC_9801_86_WSS_SB16: - boardsb16_unbind(); - board118_unbind(); - board86_unbind(); - break; - - case SOUNDID_PC_9801_118_SB16: - boardsb16_unbind(); - board118_unbind(); - break; - - case SOUNDID_PC_9801_86_118_SB16: - boardsb16_unbind(); - board118_unbind(); - board86_unbind(); - break; -#endif // defined(SUPPORT_SOUND_SB16) - -#if defined(SUPPORT_PX) - case SOUNDID_PX1: - boardpx1_unbind(); - break; - - case SOUNDID_PX2: - boardpx2_unbind(); - break; -#endif // defined(SUPPORT_PX) - - default: - break; - } -} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_PX) +#include +#endif // defined(SUPPORT_PX) +#include +#include +#include +#include +#if defined(SUPPORT_SOUND_SB16) +#include +#endif // defined(SUPPORT_SOUND_SB16) +#include +#include +#include +#include +#include +#include +#include +#include + + + SOUNDID g_nSoundID; + OPL3 g_opl3[OPL3_MAX]; // index: 0=PC-9891-118, 1=Sound Blaster 16, 2=Sound Orchestra + OPNA g_opna[OPNA_MAX]; +#ifdef USE_MAME + void *g_mame_opl3[OPL3_MAX] = {0}; +#endif + +#if defined(SUPPORT_SOUND_SB16) + SB16 g_sb16; +#endif // defined(SUPPORT_SOUND_SB16) + + _PCM86 g_pcm86; + _CS4231 cs4231; + +static void (*extfn)(REG8 enable); + + +// ---- + +static REG8 s_rapids = 0; + +REG8 fmboard_getjoy(POPNA opna) +{ + REG8 ret; + + s_rapids ^= 0xf0; // ver0.28 + ret = 0xff; + if (!(opna->s.reg[15] & 0x40)) + { +// ret &= (joymng_getstat() | (s_rapids & 0x30)); + ret &= joymng_getstat(); + if (np2cfg.KEY_MODE == 1) + { + ret &= keystat_getjoy(); + } + } + else + { + if (np2cfg.KEY_MODE == 2) + { + ret &= keystat_getjoy(); + } + } + if (np2cfg.BTN_RAPID) + { + ret |= s_rapids; + } + + // rapidと非rapidを合成 // ver0.28 + ret &= ((ret >> 2) | (~0x30)); + + if (np2cfg.BTN_MODE) + { + UINT8 bit1 = (ret & 0x20) >> 1; // ver0.28 + UINT8 bit2 = (ret & 0x10) << 1; + ret = (ret & (~0x30)) | bit1 | bit2; + } + + // intr 反映して終わり // ver0.28 + ret &= 0x3f; + ret |= opna->s.intr; + return ret; +} + +void fmboard_updatevolume(){ + UINT volex = 15; + UINT i; + if(g_nSoundID==SOUNDID_WAVESTAR){ + volex = cs4231.devvolume[0xff]; + } + opngen_setvol(np2cfg.vol_fm * volex / 15 * np2cfg.vol_master / 100); +#if defined(SUPPORT_FMGEN) + opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * volex / 15 * np2cfg.vol_master / 100); +#endif /* SUPPORT_FMGEN */ + psggen_setvol(np2cfg.vol_ssg * volex / 15 * np2cfg.vol_master / 100); +#if defined(SUPPORT_FMGEN) + opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * volex / 15 * np2cfg.vol_master / 100); +#endif /* SUPPORT_FMGEN */ + + adpcm_setvol(np2cfg.vol_adpcm * np2cfg.vol_master / 100); +#if defined(SUPPORT_FMGEN) + opna_fmgen_setallvolumeADPCM_linear(np2cfg.vol_adpcm * np2cfg.vol_master / 100); +#endif /* SUPPORT_FMGEN */ + for (i = 0; i < OPNA_MAX; i++) + { + adpcm_update(&g_opna[i].adpcm); + } + + pcm86gen_setvol(np2cfg.vol_pcm * np2cfg.vol_master / 100); + pcm86gen_update(); + + rhythm_setvol(np2cfg.vol_rhythm * volex / 15 * np2cfg.vol_master / 100); +#if defined(SUPPORT_FMGEN) + opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * volex / 15 * np2cfg.vol_master / 100); +#endif /* SUPPORT_FMGEN */ + for (i = 0; i < OPNA_MAX; i++) + { + rhythm_update(&g_opna[i].rhythm); + } + + oplgen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); +} + + +// ---- + +void fmboard_extreg(void (*ext)(REG8 enable)) { + + extfn = ext; +} + +void fmboard_extenable(REG8 enable) { + + if (extfn) { + (*extfn)(enable); + } +} + + + +// ---- + +/** + * Constructor + */ +void fmboard_construct(void) +{ + UINT i; + + for (i = 0; i < NELEMENTS(g_opna); i++) + { + opna_construct(&g_opna[i]); + } + for (i = 0; i < NELEMENTS(g_opl3); i++) + { + opl3_construct(&g_opl3[i]); + } +} + +/** + * Destructor + */ +void fmboard_destruct(void) +{ + UINT i; + + for (i = 0; i < NELEMENTS(g_opna); i++) + { + opna_destruct(&g_opna[i]); + } + for (i = 0; i < NELEMENTS(g_opl3); i++) + { + opl3_destruct(&g_opl3[i]); + } + + board118_finalize(); +#ifdef SUPPORT_SOUND_SB16 + boardsb16_finalize(); +#endif +} + +/** + * Reset + * @param[in] pConfig The pointer of config + * @param[in] nSoundId The sound ID + */ +void fmboard_reset(const NP2CFG *pConfig, SOUNDID nSoundID) +{ + UINT i; + UINT8 cross = 0; + + soundrom_reset(); + beep_reset(); // ver0.27a + + if (g_nSoundID != nSoundID) + { + for (i = 0; i < NELEMENTS(g_opna); i++) + { + opna_reset(&g_opna[i], 0); + } + for (i = 0; i < NELEMENTS(g_opl3); i++) + { + opl3_reset(&g_opl3[i], 0); + } + } + + extfn = NULL; + pcm86_reset(); + cs4231_reset(); + + board14_reset(pConfig, (nSoundID == SOUNDID_PC_9801_14) ? TRUE : FALSE); + amd98_reset(pConfig); + + g_nSoundID = nSoundID; // XXX: 先に設定 + switch (nSoundID) + { + case SOUNDID_PC_9801_14: + break; + + case SOUNDID_PC_9801_26K: + board26k_reset(pConfig); + break; + + case SOUNDID_PC_9801_86: + board86_reset(pConfig, FALSE); + break; + + case SOUNDID_PC_9801_86_26K: + boardx2_reset(pConfig); + break; + + case SOUNDID_PC_9801_118: + board118_reset(pConfig); + break; + + case SOUNDID_PC_9801_86_WSS: + board118_reset(pConfig); + board86_reset(pConfig, TRUE); + break; + + case SOUNDID_PC_9801_86_118: + board118_reset(pConfig); + board86_reset(pConfig, TRUE); + break; + + case SOUNDID_MATE_X_PCM: + board118_reset(pConfig); + break; + + case SOUNDID_PC_9801_86_ADPCM: + board86_reset(pConfig, TRUE); + break; + + case SOUNDID_WAVESTAR: + board118_reset(pConfig); + board86_reset(pConfig, FALSE); + break; + + case SOUNDID_SPEAKBOARD: + boardspb_reset(pConfig, 0); + cross ^= pConfig->spb_x; + break; + + case SOUNDID_86_SPEAKBOARD: + boardspb_reset(pConfig, 1); + board86_reset(pConfig, FALSE); + cross ^= pConfig->spb_x; + break; + + case SOUNDID_SPARKBOARD: + boardspr_reset(pConfig); + cross ^= pConfig->spb_x; + break; + + case SOUNDID_AMD98: + amd98_reset(pConfig); + break; + + case SOUNDID_SOUNDORCHESTRA: + boardso_reset(pConfig, FALSE); + break; + + case SOUNDID_SOUNDORCHESTRAV: + boardso_reset(pConfig, TRUE); + break; + + case SOUNDID_LITTLEORCHESTRAL: + boardlol_reset(pConfig); + break; + + case SOUNDID_MMORCHESTRA: + boardmo_reset(pConfig); + break; + +#if defined(SUPPORT_SOUND_SB16) + case SOUNDID_SB16: + boardsb16_reset(pConfig); + break; + + case SOUNDID_PC_9801_86_SB16: + boardsb16_reset(pConfig); + board86_reset(pConfig, TRUE); + break; + + case SOUNDID_WSS_SB16: + boardsb16_reset(pConfig); + board118_reset(pConfig); + break; + + case SOUNDID_PC_9801_86_WSS_SB16: + boardsb16_reset(pConfig); + board118_reset(pConfig); + board86_reset(pConfig, TRUE); + break; + break; + + case SOUNDID_PC_9801_118_SB16: + boardsb16_reset(pConfig); + board118_reset(pConfig); + break; + + case SOUNDID_PC_9801_86_118_SB16: + boardsb16_reset(pConfig); + board118_reset(pConfig); + board86_reset(pConfig, TRUE); + break; +#endif + +#if defined(SUPPORT_PX) + case SOUNDID_PX1: + boardpx1_reset(pConfig); + break; + + case SOUNDID_PX2: + boardpx2_reset(pConfig); + break; +#endif // defined(SUPPORT_PX) + + default: + g_nSoundID = SOUNDID_NONE; + break; + } + soundmng_setreverse((pConfig->snd_x ^ cross) & 0x1); + opngen_setVR(pConfig->spb_vrc, pConfig->spb_vrl); +} + +void fmboard_bind(void) { + + keydisp_reset(); + switch (g_nSoundID) + { + case SOUNDID_PC_9801_14: + board14_bind(); + break; + + case SOUNDID_PC_9801_26K: + board26k_bind(); + break; + + case SOUNDID_PC_9801_86: + board86_bind(); + break; + + case SOUNDID_PC_9801_86_26K: + boardx2_bind(); + break; + + case SOUNDID_PC_9801_118: + board118_bind(); + break; + + case SOUNDID_PC_9801_86_WSS: + board118_bind(); + board86_bind(); + break; + + case SOUNDID_PC_9801_86_118: + board118_bind(); + board86_bind(); + break; + + case SOUNDID_MATE_X_PCM: + board118_bind(); + break; + + case SOUNDID_PC_9801_86_ADPCM: + board86_bind(); + break; + + case SOUNDID_WAVESTAR: + board118_bind(); + board86_bind(); + break; + + case SOUNDID_SPEAKBOARD: + boardspb_bind(); + break; + + case SOUNDID_86_SPEAKBOARD: + boardspb_bind(); + board86_bind(); + break; + + case SOUNDID_SPARKBOARD: + boardspr_bind(); + break; + + case SOUNDID_AMD98: + amd98_bind(); + break; + + case SOUNDID_SOUNDORCHESTRA: + case SOUNDID_SOUNDORCHESTRAV: + boardso_bind(); + break; + + case SOUNDID_LITTLEORCHESTRAL: + boardlol_bind(); + break; + + case SOUNDID_MMORCHESTRA: + boardmo_bind(); + break; + +#if defined(SUPPORT_SOUND_SB16) + case SOUNDID_SB16: + boardsb16_bind(); + break; + + case SOUNDID_PC_9801_86_SB16: + boardsb16_bind(); + board86_bind(); + break; + + case SOUNDID_WSS_SB16: + boardsb16_bind(); + board118_bind(); + break; + + case SOUNDID_PC_9801_86_WSS_SB16: + boardsb16_bind(); + board118_bind(); + board86_bind(); + break; + + case SOUNDID_PC_9801_118_SB16: + boardsb16_bind(); + board118_bind(); + break; + + case SOUNDID_PC_9801_86_118_SB16: + boardsb16_bind(); + board118_bind(); + board86_bind(); + break; +#endif // defined(SUPPORT_SOUND_SB16) + +#if defined(SUPPORT_PX) + case SOUNDID_PX1: + boardpx1_bind(); + break; + + case SOUNDID_PX2: + boardpx2_bind(); + break; +#endif // defined(SUPPORT_PX) + + default: + break; + } + + sound_streamregist(&g_beep, (SOUNDCB)beep_getpcm); +} + +void fmboard_unbind(void) { + + switch (g_nSoundID) + { + case SOUNDID_PC_9801_14: + board14_unbind(); + break; + + case SOUNDID_PC_9801_26K: + board26k_unbind(); + break; + + case SOUNDID_PC_9801_86: + board86_unbind(); + break; + + case SOUNDID_PC_9801_86_26K: + boardx2_unbind(); + break; + + case SOUNDID_PC_9801_118: + board118_unbind(); + break; + + case SOUNDID_PC_9801_86_WSS: + board118_unbind(); + board86_unbind(); + break; + + case SOUNDID_PC_9801_86_118: + board118_unbind(); + board86_unbind(); + break; + + case SOUNDID_MATE_X_PCM: + board118_unbind(); + break; + + case SOUNDID_PC_9801_86_ADPCM: + board86_unbind(); + break; + + case SOUNDID_WAVESTAR: + board118_unbind(); + board86_unbind(); + break; + + case SOUNDID_SPEAKBOARD: + boardspb_unbind(); + break; + + case SOUNDID_86_SPEAKBOARD: + board86_unbind(); + boardspb_unbind(); + break; + + case SOUNDID_SPARKBOARD: + boardspr_unbind(); + break; + + case SOUNDID_AMD98: + amd98_unbind(); + break; + + case SOUNDID_SOUNDORCHESTRA: + case SOUNDID_SOUNDORCHESTRAV: + boardso_unbind(); + break; + + case SOUNDID_LITTLEORCHESTRAL: + boardlol_unbind(); + break; + + case SOUNDID_MMORCHESTRA: + boardmo_unbind(); + break; + +#if defined(SUPPORT_SOUND_SB16) + case SOUNDID_SB16: + boardsb16_unbind(); + break; + + case SOUNDID_PC_9801_86_SB16: + boardsb16_unbind(); + board86_unbind(); + break; + + case SOUNDID_WSS_SB16: + boardsb16_unbind(); + board118_unbind(); + break; + + case SOUNDID_PC_9801_86_WSS_SB16: + boardsb16_unbind(); + board118_unbind(); + board86_unbind(); + break; + + case SOUNDID_PC_9801_118_SB16: + boardsb16_unbind(); + board118_unbind(); + break; + + case SOUNDID_PC_9801_86_118_SB16: + boardsb16_unbind(); + board118_unbind(); + board86_unbind(); + break; +#endif // defined(SUPPORT_SOUND_SB16) + +#if defined(SUPPORT_PX) + case SOUNDID_PX1: + boardpx1_unbind(); + break; + + case SOUNDID_PX2: + boardpx2_unbind(); + break; +#endif // defined(SUPPORT_PX) + + default: + break; + } +} diff --git a/sound/fmboard.h b/sound/fmboard.h old mode 100755 new mode 100644 index 11525a06..0225f8f0 --- a/sound/fmboard.h +++ b/sound/fmboard.h @@ -1,61 +1,61 @@ -/** - * @file fmboard.h - * @brief Interface of The board manager - */ - -#pragma once - -#if !defined(DISABLE_SOUND) - -#include -#include "opl3.h" -#include "opna.h" -#include "opntimer.h" -#include -#include "ct1741.h" - -#if defined(SUPPORT_PX) -#define OPNA_MAX 5 -#else /* defined(SUPPORT_PX) */ -#define OPNA_MAX 3 -#endif /* defined(SUPPORT_PX) */ -#define OPL3_MAX 8 - -#ifdef __cplusplus -extern "C" -{ -#endif - -extern SOUNDID g_nSoundID; -extern OPL3 g_opl3[OPL3_MAX]; -extern OPNA g_opna[OPNA_MAX]; -#ifdef USE_MAME -extern void *g_mame_opl3[OPL3_MAX]; -#endif -extern _PCM86 g_pcm86; -extern _CS4231 cs4231; -extern SB16 g_sb16; - -REG8 fmboard_getjoy(POPNA opna); - -void fmboard_updatevolume(void); - -void fmboard_extreg(void (*ext)(REG8 enable)); -void fmboard_extenable(REG8 enable); - -void fmboard_construct(void); -void fmboard_destruct(void); -void fmboard_reset(const NP2CFG *pConfig, SOUNDID nSoundID); -void fmboard_bind(void); -void fmboard_unbind(void); - -#ifdef __cplusplus -} -#endif - -#else - -#define fmboard_reset(c, t) -#define fmboard_bind() - -#endif +/** + * @file fmboard.h + * @brief Interface of The board manager + */ + +#pragma once + +#if !defined(DISABLE_SOUND) + +#include +#include "opl3.h" +#include "opna.h" +#include "opntimer.h" +#include +#include "ct1741.h" + +#if defined(SUPPORT_PX) +#define OPNA_MAX 5 +#else /* defined(SUPPORT_PX) */ +#define OPNA_MAX 3 +#endif /* defined(SUPPORT_PX) */ +#define OPL3_MAX 8 + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern SOUNDID g_nSoundID; +extern OPL3 g_opl3[OPL3_MAX]; +extern OPNA g_opna[OPNA_MAX]; +#ifdef USE_MAME +extern void *g_mame_opl3[OPL3_MAX]; +#endif +extern _PCM86 g_pcm86; +extern _CS4231 cs4231; +extern SB16 g_sb16; + +REG8 fmboard_getjoy(POPNA opna); + +void fmboard_updatevolume(void); + +void fmboard_extreg(void (*ext)(REG8 enable)); +void fmboard_extenable(REG8 enable); + +void fmboard_construct(void); +void fmboard_destruct(void); +void fmboard_reset(const NP2CFG *pConfig, SOUNDID nSoundID); +void fmboard_bind(void); +void fmboard_unbind(void); + +#ifdef __cplusplus +} +#endif + +#else + +#define fmboard_reset(c, t) +#define fmboard_bind() + +#endif diff --git a/sound/fmgen/fmgen_diag.h b/sound/fmgen/fmgen_diag.h old mode 100755 new mode 100644 index 6e953048..01973328 --- a/sound/fmgen/fmgen_diag.h +++ b/sound/fmgen/fmgen_diag.h @@ -1,20 +1,20 @@ -#pragma once -#if defined(SUPPORT_FMGEN) - -#ifndef incl_diag_h -#define incl_diag_h - -#define LOG0(m) void (0) -#define LOG1(m,a) void (0) -#define LOG2(m,a,b) void (0) -#define LOG3(m,a,b,c) void (0) -#define LOG4(m,a,b,c,d) void (0) -#define LOG5(m,a,b,c,d,e) void (0) -#define LOG6(m,a,b,c,d,e,f) void (0) -#define LOG7(m,a,b,c,d,e,f,g) void (0) -#define LOG8(m,a,b,c,d,e,f,g,h) void (0) -#define LOG9(m,a,b,c,d,e,f,g,h,i) void (0) - -#endif // incl_diag_h - +#pragma once +#if defined(SUPPORT_FMGEN) + +#ifndef incl_diag_h +#define incl_diag_h + +#define LOG0(m) void (0) +#define LOG1(m,a) void (0) +#define LOG2(m,a,b) void (0) +#define LOG3(m,a,b,c) void (0) +#define LOG4(m,a,b,c,d) void (0) +#define LOG5(m,a,b,c,d,e) void (0) +#define LOG6(m,a,b,c,d,e,f) void (0) +#define LOG7(m,a,b,c,d,e,f,g) void (0) +#define LOG8(m,a,b,c,d,e,f,g,h) void (0) +#define LOG9(m,a,b,c,d,e,f,g,h,i) void (0) + +#endif // incl_diag_h + #endif /* SUPPORT_FMGEN */ \ No newline at end of file diff --git a/sound/fmgen/fmgen_file.cpp b/sound/fmgen/fmgen_file.cpp old mode 100755 new mode 100644 index ce5abc16..9c85dcca --- a/sound/fmgen/fmgen_file.cpp +++ b/sound/fmgen/fmgen_file.cpp @@ -1,195 +1,195 @@ -// $Id: file.cpp,v 1.6 1999/12/28 11:14:05 cisc Exp $ - -#if defined(SUPPORT_FMGEN) - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#ifdef __cplusplus -} -#endif - -#include "fmgen_types.h" -#include "fmgen_headers.h" -#include "fmgen_file.h" - -// --------------------------------------------------------------------------- -// 構築/消滅 -// --------------------------------------------------------------------------- - -FileIO::FileIO() -{ - pfile = NULL; - flags = 0; -} - -FileIO::FileIO(const char* filename, uint flg) -{ - pfile = NULL; - flags = 0; - Open(filename, flg); -} - -FileIO::~FileIO() -{ - Close(); -} - -// --------------------------------------------------------------------------- -// ファイルを開く -// --------------------------------------------------------------------------- - -bool FileIO::Open(const char* filename, uint flg) -{ - char mode[5] = "rwb"; - Close(); - - strncpy(path, filename, MAX_PATH); - - if(flg & readonly) - strcpy(mode, "rb"); - else { - if(flg & create) - strcpy(mode, "rwb+"); - else - strcpy(mode, "rwb"); - } - - pfile = fopen(filename, mode); - - flags = (flg & readonly) | (pfile == NULL ? 0 : open); - - if (pfile == NULL) - error = file_not_found; - - SetLogicalOrigin(0); - - return !(pfile == NULL); -} - -// --------------------------------------------------------------------------- -// ファイルがない場合は作成 -// --------------------------------------------------------------------------- - -bool FileIO::CreateNew(const char* filename) -{ - uint flg = create; - - return Open(filename, flg); -} - -// --------------------------------------------------------------------------- -// ファイルを作り直す -// --------------------------------------------------------------------------- - -bool FileIO::Reopen(uint flg) -{ - if (!(flags & open)) return false; - if ((flags & readonly) && (flg & create)) return false; - - if (flags & readonly) flg |= readonly; - - return Open(path, flg); -} - -// --------------------------------------------------------------------------- -// ファイルを閉じる -// --------------------------------------------------------------------------- - -void FileIO::Close() -{ - if (GetFlags() & open) - { - if(pfile) { - fclose(pfile); - pfile = NULL; - } - flags = 0; - } -} - -// --------------------------------------------------------------------------- -// ファイル殻の読み出し -// --------------------------------------------------------------------------- - -int32 FileIO::Read(void* dest, int32 size) -{ - if (!(GetFlags() & open)) - return -1; - - DWORD readsize; - if (!(readsize = fread(dest, 1, size, pfile))) - return -1; - return size; -} - -// --------------------------------------------------------------------------- -// ファイルへの書き出し -// --------------------------------------------------------------------------- - -int32 FileIO::Write(const void* dest, int32 size) -{ - if (!(GetFlags() & open) || (GetFlags() & readonly)) - return -1; - - DWORD writtensize; - if (!(writtensize = fwrite(dest, 1, size, pfile))) - return -1; - return writtensize; -} - -// --------------------------------------------------------------------------- -// ファイルをシーク -// --------------------------------------------------------------------------- - -bool FileIO::Seek(int32 pos, SeekMethod method) -{ - if (!(GetFlags() & open)) - return false; - - int origin; - switch (method) - { - case begin: - origin = SEEK_SET; - break; - case current: - origin = SEEK_CUR; - break; - case end: - origin = SEEK_END; - break; - default: - return false; - } - - return fseek(pfile, pos, origin); -} - -// --------------------------------------------------------------------------- -// ファイルの位置を得る -// --------------------------------------------------------------------------- - -int32 FileIO::Tellp() -{ - if (!(GetFlags() & open)) - return 0; - - return ftell(pfile); -} - -// --------------------------------------------------------------------------- -// 現在の位置をファイルの終端とする -// --------------------------------------------------------------------------- - -bool FileIO::SetEndOfFile() -{ - if (!(GetFlags() & open)) - return false; - return Seek(0, end); -} - +// $Id: file.cpp,v 1.6 1999/12/28 11:14:05 cisc Exp $ + +#if defined(SUPPORT_FMGEN) + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __cplusplus +} +#endif + +#include "fmgen_types.h" +#include "fmgen_headers.h" +#include "fmgen_file.h" + +// --------------------------------------------------------------------------- +// 構築/消滅 +// --------------------------------------------------------------------------- + +FileIO::FileIO() +{ + pfile = NULL; + flags = 0; +} + +FileIO::FileIO(const char* filename, uint flg) +{ + pfile = NULL; + flags = 0; + Open(filename, flg); +} + +FileIO::~FileIO() +{ + Close(); +} + +// --------------------------------------------------------------------------- +// ファイルを開く +// --------------------------------------------------------------------------- + +bool FileIO::Open(const char* filename, uint flg) +{ + char mode[5] = "rwb"; + Close(); + + strncpy(path, filename, MAX_PATH); + + if(flg & readonly) + strcpy(mode, "rb"); + else { + if(flg & create) + strcpy(mode, "rwb+"); + else + strcpy(mode, "rwb"); + } + + pfile = fopen(filename, mode); + + flags = (flg & readonly) | (pfile == NULL ? 0 : open); + + if (pfile == NULL) + error = file_not_found; + + SetLogicalOrigin(0); + + return !(pfile == NULL); +} + +// --------------------------------------------------------------------------- +// ファイルがない場合は作成 +// --------------------------------------------------------------------------- + +bool FileIO::CreateNew(const char* filename) +{ + uint flg = create; + + return Open(filename, flg); +} + +// --------------------------------------------------------------------------- +// ファイルを作り直す +// --------------------------------------------------------------------------- + +bool FileIO::Reopen(uint flg) +{ + if (!(flags & open)) return false; + if ((flags & readonly) && (flg & create)) return false; + + if (flags & readonly) flg |= readonly; + + return Open(path, flg); +} + +// --------------------------------------------------------------------------- +// ファイルを閉じる +// --------------------------------------------------------------------------- + +void FileIO::Close() +{ + if (GetFlags() & open) + { + if(pfile) { + fclose(pfile); + pfile = NULL; + } + flags = 0; + } +} + +// --------------------------------------------------------------------------- +// ファイル殻の読み出し +// --------------------------------------------------------------------------- + +int32 FileIO::Read(void* dest, int32 size) +{ + if (!(GetFlags() & open)) + return -1; + + DWORD readsize; + if (!(readsize = fread(dest, 1, size, pfile))) + return -1; + return size; +} + +// --------------------------------------------------------------------------- +// ファイルへの書き出し +// --------------------------------------------------------------------------- + +int32 FileIO::Write(const void* dest, int32 size) +{ + if (!(GetFlags() & open) || (GetFlags() & readonly)) + return -1; + + DWORD writtensize; + if (!(writtensize = fwrite(dest, 1, size, pfile))) + return -1; + return writtensize; +} + +// --------------------------------------------------------------------------- +// ファイルをシーク +// --------------------------------------------------------------------------- + +bool FileIO::Seek(int32 pos, SeekMethod method) +{ + if (!(GetFlags() & open)) + return false; + + int origin; + switch (method) + { + case begin: + origin = SEEK_SET; + break; + case current: + origin = SEEK_CUR; + break; + case end: + origin = SEEK_END; + break; + default: + return false; + } + + return fseek(pfile, pos, origin); +} + +// --------------------------------------------------------------------------- +// ファイルの位置を得る +// --------------------------------------------------------------------------- + +int32 FileIO::Tellp() +{ + if (!(GetFlags() & open)) + return 0; + + return ftell(pfile); +} + +// --------------------------------------------------------------------------- +// 現在の位置をファイルの終端とする +// --------------------------------------------------------------------------- + +bool FileIO::SetEndOfFile() +{ + if (!(GetFlags() & open)) + return false; + return Seek(0, end); +} + #endif /* SUPPORT_FMGEN */ \ No newline at end of file diff --git a/sound/fmgen/fmgen_file.h b/sound/fmgen/fmgen_file.h old mode 100755 new mode 100644 index e088a7ca..ff4e0b3c --- a/sound/fmgen/fmgen_file.h +++ b/sound/fmgen/fmgen_file.h @@ -1,69 +1,69 @@ -// $Id: file.h,v 1.6 1999/11/26 10:14:09 cisc Exp $ - -#pragma once -#if defined(SUPPORT_FMGEN) - -#if !defined(win32_file_h) -#define win32_file_h - -#include "fmgen_types.h" - -// --------------------------------------------------------------------------- - -class FileIO -{ -public: - enum Flags - { - open = 0x000001, - readonly = 0x000002, - create = 0x000004, - }; - - enum SeekMethod - { - begin = 0, current = 1, end = 2, - }; - - enum Error - { - success = 0, - file_not_found, - sharing_violation, - unknown = -1 - }; - -public: - FileIO(); - FileIO(const char* filename, uint flg = 0); - virtual ~FileIO(); - - bool Open(const char* filename, uint flg = 0); - bool CreateNew(const char* filename); - bool Reopen(uint flg = 0); - void Close(); - Error GetError() { return error; } - - int32 Read(void* dest, int32 len); - int32 Write(const void* src, int32 len); - bool Seek(int32 fpos, SeekMethod method); - int32 Tellp(); - bool SetEndOfFile(); - - uint GetFlags() { return flags; } - void SetLogicalOrigin(int32 origin) { lorigin = origin; } - -private: - FILE* pfile; - uint flags; - uint32 lorigin; - Error error; - char path[MAX_PATH]; - - FileIO(const FileIO&); - const FileIO& operator=(const FileIO&); -}; - -#endif // - -#endif /* SUPPORT_FMGEN */ +// $Id: file.h,v 1.6 1999/11/26 10:14:09 cisc Exp $ + +#pragma once +#if defined(SUPPORT_FMGEN) + +#if !defined(win32_file_h) +#define win32_file_h + +#include "fmgen_types.h" + +// --------------------------------------------------------------------------- + +class FileIO +{ +public: + enum Flags + { + open = 0x000001, + readonly = 0x000002, + create = 0x000004, + }; + + enum SeekMethod + { + begin = 0, current = 1, end = 2, + }; + + enum Error + { + success = 0, + file_not_found, + sharing_violation, + unknown = -1 + }; + +public: + FileIO(); + FileIO(const char* filename, uint flg = 0); + virtual ~FileIO(); + + bool Open(const char* filename, uint flg = 0); + bool CreateNew(const char* filename); + bool Reopen(uint flg = 0); + void Close(); + Error GetError() { return error; } + + int32 Read(void* dest, int32 len); + int32 Write(const void* src, int32 len); + bool Seek(int32 fpos, SeekMethod method); + int32 Tellp(); + bool SetEndOfFile(); + + uint GetFlags() { return flags; } + void SetLogicalOrigin(int32 origin) { lorigin = origin; } + +private: + FILE* pfile; + uint flags; + uint32 lorigin; + Error error; + char path[MAX_PATH]; + + FileIO(const FileIO&); + const FileIO& operator=(const FileIO&); +}; + +#endif // + +#endif /* SUPPORT_FMGEN */ diff --git a/sound/fmgen/fmgen_fmgen.cpp b/sound/fmgen/fmgen_fmgen.cpp old mode 100755 new mode 100644 index e9b5295a..9a6125ae --- a/sound/fmgen/fmgen_fmgen.cpp +++ b/sound/fmgen/fmgen_fmgen.cpp @@ -1,1090 +1,1090 @@ -// --------------------------------------------------------------------------- -// FM Sound Generator - Core Unit -// Copyright (C) cisc 1998, 2003. -// --------------------------------------------------------------------------- -// $Id: fmgen.cpp,v 1.49 2003/09/02 14:51:04 cisc Exp $ -// --------------------------------------------------------------------------- -// 参考: -// FM sound generator for M.A.M.E., written by Tatsuyuki Satoh. -// -// 謎: -// OPNB の CSM モード(仕様がよくわからない) -// -// 制限: -// ・AR!=31 で SSGEC を使うと波形が実際と異なる可能性あり -// -// 謝辞: -// Tatsuyuki Satoh さん(fm.c) -// Hiromitsu Shioya さん(ADPCM-A) -// DMP-SOFT. さん(OPNB) -// KAJA さん(test program) -// ほか掲示板等で様々なご助言,ご支援をお寄せいただいた皆様に -// --------------------------------------------------------------------------- - -#if defined(SUPPORT_FMGEN) - -#include "fmgen_headers.h" -#include "fmgen_misc.h" -#include "fmgen_fmgen.h" -#include "fmgen_fmgeninl.h" - -#define LOGNAME "fmgen" - -// --------------------------------------------------------------------------- - -#define FM_EG_BOTTOM 955 - -// --------------------------------------------------------------------------- -// Table/etc -// -namespace FM -{ - const uint8 Operator::notetable[128] = - { - 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, - 16, 16, 16, 16, 16, 16, 16, 17, 18, 19, 19, 19, 19, 19, 19, 19, - 20, 20, 20, 20, 20, 20, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, - 24, 24, 24, 24, 24, 24, 24, 25, 26, 27, 27, 27, 27, 27, 27, 27, - 28, 28, 28, 28, 28, 28, 28, 29, 30, 31, 31, 31, 31, 31, 31, 31, - }; - - const int8 Operator::dttable[256] = - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, - 4, 6, 6, 6, 8, 8, 8, 10, 10, 12, 12, 14, 16, 16, 16, 16, - 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, - 10, 12, 12, 14, 16, 16, 18, 20, 22, 24, 26, 28, 32, 32, 32, 32, - 4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, 10, 12, 12, 14, - 16, 16, 18, 20, 22, 24, 26, 28, 32, 34, 38, 40, 44, 44, 44, 44, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -2, -2, -2, -2, -2, -2, -2, -2, -4, -4, -4, -4, - -4, -6, -6, -6, -8, -8, -8,-10,-10,-12,-12,-14,-16,-16,-16,-16, - -2, -2, -2, -2, -4, -4, -4, -4, -4, -6, -6, -6, -8, -8, -8,-10, - -10,-12,-12,-14,-16,-16,-18,-20,-22,-24,-26,-28,-32,-32,-32,-32, - -4, -4, -4, -4, -4, -6, -6, -6, -8, -8, -8,-10,-10,-12,-12,-14, - -16,-16,-18,-20,-22,-24,-26,-28,-32,-34,-38,-40,-44,-44,-44,-44, - }; - - const int8 Operator::decaytable1[64][8] = - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 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, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, - 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, - 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 4, 2, 2, 2, - 4, 2, 4, 2, 4, 2, 4, 2, 4, 4, 4, 2, 4, 4, 4, 2, - 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 4, 4, - 8, 4, 8, 4, 8, 4, 8, 4, 8, 8, 8, 4, 8, 8, 8, 4, - 16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16, - 16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16, - }; - - const int Operator::decaytable2[16] = - { - 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2047, 2047, 2047, 2047, 2047 - }; - - const int8 Operator::attacktable[64][8] = - { - -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4,-1, - 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, - 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, - 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, - 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, - 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, - 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, - 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, - 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, - 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, - 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, - 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, - 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, - 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, - 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, - 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, - 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, - 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, - 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, - 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, - 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, - 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, - 3, 4, 3, 4, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, - 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 2, 2, 2, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, - 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, - }; - - const int Operator::ssgenvtable[8][2][3][2] = - { - 1, 1, 1, 1, 1, 1, // 08 - 0, 1, 1, 1, 1, 1, // 08 56~ - 0, 1, 2, 0, 2, 0, // 09 - 0, 1, 2, 0, 2, 0, // 09 - 1,-1, 0, 1, 1,-1, // 10 - 0, 1, 1,-1, 0, 1, // 10 60~ - 1,-1, 0, 0, 0, 0, // 11 - 0, 1, 0, 0, 0, 0, // 11 60~ - 2,-1, 2,-1, 2,-1, // 12 - 1,-1, 2,-1, 2,-1, // 12 56~ - 1,-1, 0, 0, 0, 0, // 13 - 1,-1, 0, 0, 0, 0, // 13 - 0, 1, 1,-1, 0, 1, // 14 - 1,-1, 0, 1, 1,-1, // 14 60~ - 0, 1, 2, 0, 2, 0, // 15 - 1,-1, 2, 0, 2, 0, // 15 60~ - }; - - // fixed equasion-based tables - int pmtable[2][8][FM_LFOENTS]; - uint amtable[2][4][FM_LFOENTS]; - - static bool tablemade = false; -} - -namespace FM -{ - -// --------------------------------------------------------------------------- -// テーブル作成 -// -void MakeLFOTable() -{ - if (tablemade) - return; - - tablemade = true; - - int i; - - static const double pms[2][8] = - { - { 0, 1/360., 2/360., 3/360., 4/360., 6/360., 12/360., 24/360., }, // OPNA -// { 0, 1/240., 2/240., 4/240., 10/240., 20/240., 80/240., 140/240., }, // OPM - { 0, 1/480., 2/480., 4/480., 10/480., 20/480., 80/480., 140/480., }, // OPM -// { 0, 1/960., 2/960., 4/960., 10/960., 20/960., 80/960., 140/960., }, // OPM - }; - // 3 6, 12 30 60 240 420 / 720 - // 1.000963 - // lfofref[level * max * wave]; - // pre = lfofref[level][pms * wave >> 8]; - static const uint8 amt[2][4] = - { - { 31, 6, 4, 3 }, // OPNA - { 31, 2, 1, 0 }, // OPM - }; - - for (int type = 0; type < 2; type++) - { - for (i=0; i<8; i++) - { - double pmb = pms[type][i]; - for (int j=0; j> amt[type][i]) * 2) << 2; - } - } - } -} - - -// --------------------------------------------------------------------------- -// チップ内で共通な部分 -// -Chip::Chip() -: ratio_(0), aml_(0), pml_(0), pmv_(0), optype_(typeN) -{ -} - -// クロック・サンプリングレート比に依存するテーブルを作成 -void Chip::SetRatio(uint ratio) -{ - if (ratio_ != ratio) - { - ratio_ = ratio; - MakeTable(); - } -} - -void Chip::MakeTable() -{ - int h, l; - - // PG Part - static const float dt2lv[4] = { 1.f, 1.414f, 1.581f, 1.732f }; - for (h=0; h<4; h++) - { - assert(2 + FM_RATIOBITS - FM_PGBITS >= 0); - double rr = dt2lv[h] * double(ratio_) / (1 << (2 + FM_RATIOBITS - FM_PGBITS)); - for (l=0; l<16; l++) - { - int mul = l ? l * 2 : 1; - multable_[h][l] = uint(mul * rr); - } - } -} - -void Chip::DataSave(struct ChipData* data) -{ - data->ratio_ = ratio_; - data->aml_ = aml_; - data->pml_ = pml_; - data->pmv_ = pmv_; - memcpy(data->multable_, multable_, sizeof(uint32) * 4 * 16); -} - -void Chip::DataLoad(struct ChipData* data) -{ - ratio_ = data->ratio_; - aml_ = data->aml_; - pml_ = data->pml_; - pmv_ = data->pmv_; - memcpy(multable_, data->multable_, sizeof(uint32) * 4 * 16); -} - -// --------------------------------------------------------------------------- -// Operator -// -bool FM::Operator::tablehasmade = false; -uint FM::Operator::sinetable[1024]; -int32 FM::Operator::cltable[FM_CLENTS]; - -// 構築 -FM::Operator::Operator() -: chip_(0) -{ - if (!tablehasmade) - MakeTable(); - - // EG Part - ar_ = dr_ = sr_ = rr_ = key_scale_rate_ = 0; - ams_ = amtable[0][0]; - mute_ = false; - keyon_ = false; - tl_out_ = false; - ssg_type_ = 0; - - // PG Part - multiple_ = 0; - detune_ = 0; - detune2_ = 0; - - // LFO - ms_ = 0; - -// Reset(); -} - -// 初期化 -void FM::Operator::Reset() -{ - // EG part - tl_ = tl_latch_ = 127; - ShiftPhase(off); - eg_count_ = 0; - eg_curve_count_ = 0; - ssg_phase_ = 0; - - // PG part - pg_count_ = 0; - - // OP part - out_ = out2_ = 0; - - param_changed_ = true; - PARAMCHANGE(0); -} - -void Operator::MakeTable() -{ - // 対数テーブルの作成 - assert(FM_CLENTS >= 256); - - int* p = cltable; - int i; - for (i=0; i<256; i++) - { - int v = int(floor(pow(2., 13. - i / 256.))); - v = (v + 2) & ~3; - *p++ = v; - *p++ = -v; - } - while (p < cltable + FM_CLENTS) - { - //*p++ = p[-512] / 2; - *p = p[-512] / 2; - p++; - } - -// for (i=0; i<13*256; i++) -// printf("%4d, %d, %d\n", i, cltable[i*2], cltable[i*2+1]); - - // サインテーブルの作成 - double log2 = log(2.); - for (i=0; iGetMulValue(detune2_, multiple_); - pg_diff_lfo_ = pg_diff_ >> 11; - - // EG Part - key_scale_rate_ = bn_ >> (3-ks_); - tl_out_ = mute_ ? 0x3ff : tl_ * 8; - - switch (eg_phase_) - { - case attack: - SetEGRate(ar_ ? Min(63, ar_ + key_scale_rate_) : 0); - break; - case decay: - SetEGRate(dr_ ? Min(63, dr_ + key_scale_rate_) : 0); - eg_level_on_next_phase_ = sl_ * 8; - break; - case sustain: - SetEGRate(sr_ ? Min(63, sr_ + key_scale_rate_) : 0); - break; - case release: - SetEGRate(Min(63, rr_ + key_scale_rate_)); - break; - } - - // SSG-EG - if (ssg_type_ && (eg_phase_ != release)) - { - int m = ar_ >= ((ssg_type_ == 8 || ssg_type_ == 12) ? 56 : 60); - - assert(0 <= ssg_phase_ && ssg_phase_ <= 2); - const int* table = ssgenvtable[ssg_type_ & 7][m][ssg_phase_]; - - ssg_offset_ = table[0] * 0x200; - ssg_vector_ = table[1]; - } - // LFO - ams_ = amtable[type_][amon_ ? (ms_ >> 4) & 3 : 0]; - EGUpdate(); - - dbgopout_ = 0; - } -} - -void Operator::DataSave(struct OperatorData* data) -{ - data->out_ = out_; - data->out2_ = out2_; - data->in2_ = in2_; - data->dp_ = dp_; - data->detune_ = detune_; - data->detune2_ = detune2_; - data->multiple_ = multiple_; - data->pg_count_ = pg_count_; - data->pg_diff_ = pg_diff_; - data->pg_diff_lfo_ = pg_diff_lfo_; - data->type_ = type_; - data->bn_ = bn_; - data->eg_level_ = eg_level_; - data->eg_level_on_next_phase_ = eg_level_on_next_phase_; - data->eg_count_ = eg_count_; - data->eg_count_diff_ = eg_count_diff_; - data->eg_out_ = eg_out_; - data->tl_out_ = tl_out_; - data->eg_rate_ = eg_rate_; - data->eg_curve_count_ = eg_curve_count_; - data->ssg_offset_ = ssg_offset_; - data->ssg_vector_ = ssg_vector_; - data->ssg_phase_ = ssg_phase_; - data->key_scale_rate_ = key_scale_rate_; - data->eg_phase_ = eg_phase_; - data->ms_ = ms_; - data->tl_ = tl_; - data->tl_latch_ = tl_latch_; - data->ar_ = ar_; - data->dr_ = dr_; - data->sr_ = sr_; - data->sl_ = sl_; - data->rr_ = rr_; - data->ks_ = ks_; - data->ssg_type_ = ssg_type_; - data->keyon_ = keyon_; - data->amon_ = amon_; - data->param_changed_ = param_changed_; - data->mute_ = mute_; -} - -void Operator::DataLoad(struct OperatorData* data) -{ - out_ = data->out_; - out2_ = data->out2_; - in2_ = data->in2_; - dp_ = data->dp_; - detune_ = data->detune_; - detune2_ = data->detune2_; - multiple_ = data->multiple_; - pg_count_ = data->pg_count_; - pg_diff_ = data->pg_diff_; - pg_diff_lfo_ = data->pg_diff_lfo_; - type_ = data->type_; - bn_ = data->bn_; - eg_level_ = data->eg_level_; - eg_level_on_next_phase_ = data->eg_level_on_next_phase_; - eg_count_ = data->eg_count_; - eg_count_diff_ = data->eg_count_diff_; - eg_out_ = data->eg_out_; - tl_out_ = data->tl_out_; - eg_rate_ = data->eg_rate_; - eg_curve_count_ = data->eg_curve_count_; - ssg_offset_ = data->ssg_offset_; - ssg_vector_ = data->ssg_vector_; - ssg_phase_ = data->ssg_phase_; - key_scale_rate_ = data->key_scale_rate_; - eg_phase_ = data->eg_phase_; - ms_ = data->ms_; - tl_ = data->tl_; - tl_latch_ = data->tl_latch_; - ar_ = data->ar_; - dr_ = data->dr_; - sr_ = data->sr_; - sl_ = data->sl_; - rr_ = data->rr_; - ks_ = data->ks_; - ssg_type_ = data->ssg_type_; - keyon_ = data->keyon_; - amon_ = data->amon_; - param_changed_ = data->param_changed_; - mute_ = data->mute_; - ams_ = amtable[type_][amon_ ? (ms_ >> 4) & 3 : 0]; -} - - -// envelop の eg_phase_ 変更 -void Operator::ShiftPhase(EGPhase nextphase) -{ - switch (nextphase) - { - case attack: // Attack Phase - tl_ = tl_latch_; - if (ssg_type_) - { - ssg_phase_ = ssg_phase_ + 1; - if (ssg_phase_ > 2) - ssg_phase_ = 1; - - int m = ar_ >= ((ssg_type_ == 8 || ssg_type_ == 12) ? 56 : 60); - - assert(0 <= ssg_phase_ && ssg_phase_ <= 2); - const int* table = ssgenvtable[ssg_type_ & 7][m][ssg_phase_]; - - ssg_offset_ = table[0] * 0x200; - ssg_vector_ = table[1]; - } - if ((ar_ + key_scale_rate_) < 62) - { - SetEGRate(ar_ ? Min(63, ar_ + key_scale_rate_) : 0); - eg_phase_ = attack; - break; - } - case decay: // Decay Phase - if (sl_) - { - eg_level_ = 0; - eg_level_on_next_phase_ = ssg_type_ ? Min(sl_ * 8, 0x200) : sl_ * 8; - - SetEGRate(dr_ ? Min(63, dr_ + key_scale_rate_) : 0); - eg_phase_ = decay; - break; - } - case sustain: // Sustain Phase - eg_level_ = sl_ * 8; - eg_level_on_next_phase_ = ssg_type_ ? 0x200 : 0x400; - - SetEGRate(sr_ ? Min(63, sr_ + key_scale_rate_) : 0); - eg_phase_ = sustain; - break; - - case release: // Release Phase - if (ssg_type_) - { - eg_level_ = eg_level_ * ssg_vector_ + ssg_offset_; - ssg_vector_ = 1; - ssg_offset_ = 0; - } - if (eg_phase_ == attack || (eg_level_ < FM_EG_BOTTOM)) //0x400/* && eg_phase_ != off*/)) - { - eg_level_on_next_phase_ = 0x400; - SetEGRate(Min(63, rr_ + key_scale_rate_)); - eg_phase_ = release; - break; - } - case off: // off - default: - eg_level_ = FM_EG_BOTTOM; - eg_level_on_next_phase_ = FM_EG_BOTTOM; - EGUpdate(); - SetEGRate(0); - eg_phase_ = off; - break; - } -} - -// Block/F-Num -void Operator::SetFNum(uint f) -{ - dp_ = (f & 2047) << ((f >> 11) & 7); - bn_ = notetable[(f >> 7) & 127]; - param_changed_ = true; - PARAMCHANGE(2); -} - -// 1サンプル合成 - -// ISample を envelop count (2π) に変換するシフト量 -#define IS2EC_SHIFT ((20 + FM_PGBITS) - 13) - - -// 入力: s = 20+FM_PGBITS = 29 -#define Sine(s) sinetable[((s) >> (20+FM_PGBITS-FM_OPSINBITS))&(FM_OPSINENTS-1)] -#define SINE(s) sinetable[(s) & (FM_OPSINENTS-1)] - -inline FM::ISample Operator::LogToLin(uint a) -{ -#if 1 // FM_CLENTS < 0xc00 // 400 for TL, 400 for ENV, 400 for LFO. - return (a < FM_CLENTS) ? cltable[a] : 0; -#else - return cltable[a]; -#endif -} - -inline void Operator::EGUpdate() -{ - if (!ssg_type_) - { - eg_out_ = Min(tl_out_ + eg_level_, 0x3ff) << (1 + 2); - } - else - { - eg_out_ = Min(tl_out_ + eg_level_ * ssg_vector_ + ssg_offset_, 0x3ff) << (1 + 2); - } -} - -inline void Operator::SetEGRate(uint rate) -{ - eg_rate_ = rate; - eg_count_diff_ = decaytable2[rate / 4] * chip_->GetRatio(); -} - -// EG 計算 -void FM::Operator::EGCalc() -{ - eg_count_ = (2047 * 3) << FM_RATIOBITS; // ##この手抜きは再現性を低下させる - - if (eg_phase_ == attack) - { - int c = attacktable[eg_rate_][eg_curve_count_ & 7]; - if (c >= 0) - { - eg_level_ -= 1 + (eg_level_ >> c); - if (eg_level_ <= 0) - ShiftPhase(decay); - } - EGUpdate(); - } - else - { - if (!ssg_type_) - { - eg_level_ += decaytable1[eg_rate_][eg_curve_count_ & 7]; - if (eg_level_ >= eg_level_on_next_phase_) - ShiftPhase(EGPhase(eg_phase_+1)); - EGUpdate(); - } - else - { - eg_level_ += 4 * decaytable1[eg_rate_][eg_curve_count_ & 7]; - if (eg_level_ >= eg_level_on_next_phase_) - { - EGUpdate(); - switch (eg_phase_) - { - case decay: - ShiftPhase(sustain); - break; - case sustain: - ShiftPhase(attack); - break; - case release: - ShiftPhase(off); - break; - } - } - } - } - eg_curve_count_++; -} - -inline void FM::Operator::EGStep() -{ - eg_count_ -= eg_count_diff_; - - // EG の変化は全スロットで同期しているという噂もある - if (eg_count_ <= 0) - EGCalc(); -} - -// PG 計算 -// ret:2^(20+PGBITS) / cycle -inline uint32 FM::Operator::PGCalc() -{ - uint32 ret = pg_count_; - pg_count_ += pg_diff_; - dbgpgout_ = ret; - return ret; -} - -inline uint32 FM::Operator::PGCalcL() -{ - uint32 ret = pg_count_; - pg_count_ += pg_diff_ + ((pg_diff_lfo_ * chip_->GetPMV()) >> 5);// & -(1 << (2+IS2EC_SHIFT))); - dbgpgout_ = ret; - return ret /* + pmv * pg_diff_;*/; -} - -// OP 計算 -// in: ISample (最大 8π) -inline FM::ISample FM::Operator::Calc(ISample in) -{ - EGStep(); - out2_ = out_; - - int pgin = PGCalc() >> (20+FM_PGBITS-FM_OPSINBITS); - pgin += in >> (20+FM_PGBITS-FM_OPSINBITS-(2+IS2EC_SHIFT)); - out_ = LogToLin(eg_out_ + SINE(pgin)); - - dbgopout_ = out_; - return out_; -} - -inline FM::ISample FM::Operator::CalcL(ISample in) -{ - EGStep(); - - int pgin = PGCalcL() >> (20+FM_PGBITS-FM_OPSINBITS); - pgin += in >> (20+FM_PGBITS-FM_OPSINBITS-(2+IS2EC_SHIFT)); - out_ = LogToLin(eg_out_ + SINE(pgin) + ams_[chip_->GetAML()]); - - dbgopout_ = out_; - return out_; -} - -inline FM::ISample FM::Operator::CalcN(uint noise) -{ - EGStep(); - - int lv = Max(0, 0x3ff - (tl_out_ + eg_level_)) << 1; - - // noise & 1 ? lv : -lv と等価 - noise = (noise & 1) - 1; - out_ = (lv + noise) ^ noise; - - dbgopout_ = out_; - return out_; -} - -// OP (FB) 計算 -// Self Feedback の変調最大 = 4π -inline FM::ISample FM::Operator::CalcFB(uint fb) -{ - EGStep(); - - ISample in = out_ + out2_; - out2_ = out_; - - int pgin = PGCalc() >> (20+FM_PGBITS-FM_OPSINBITS); - if (fb < 31) - { - pgin += ((in << (1 + IS2EC_SHIFT)) >> fb) >> (20+FM_PGBITS-FM_OPSINBITS); - } - out_ = LogToLin(eg_out_ + SINE(pgin)); - dbgopout_ = out2_; - - return out2_; -} - -inline FM::ISample FM::Operator::CalcFBL(uint fb) -{ - EGStep(); - - ISample in = out_ + out2_; - out2_ = out_; - - int pgin = PGCalcL() >> (20+FM_PGBITS-FM_OPSINBITS); - if (fb < 31) - { - pgin += ((in << (1 + IS2EC_SHIFT)) >> fb) >> (20+FM_PGBITS-FM_OPSINBITS); - } - - out_ = LogToLin(eg_out_ + SINE(pgin) + ams_[chip_->GetAML()]); - dbgopout_ = out_; - - return out_; -} - -#undef Sine - -// --------------------------------------------------------------------------- -// 4-op Channel -// -const uint8 Channel4::fbtable[8] = { 31, 7, 6, 5, 4, 3, 2, 1 }; -int Channel4::kftable[64]; - -bool Channel4::tablehasmade = false; - - -Channel4::Channel4() -{ - if (!tablehasmade) - MakeTable(); - - SetAlgorithm(0); - pms = pmtable[0][0]; -} - -void Channel4::MakeTable() -{ - // 100/64 cent = 2^(i*100/64*1200) - for (int i=0; i<64; i++) - { - kftable[i] = int(0x10000 * pow(2., i / 768.) ); - } -} - -// リセット -void Channel4::Reset() -{ - op[0].Reset(); - op[1].Reset(); - op[2].Reset(); - op[3].Reset(); -} - -// Calc の用意 -int Channel4::Prepare() -{ - op[0].Prepare(); - op[1].Prepare(); - op[2].Prepare(); - op[3].Prepare(); - - pms = pmtable[op[0].type_][op[0].ms_ & 7]; - int key = (op[0].IsOn() | op[1].IsOn() | op[2].IsOn() | op[3].IsOn()) ? 1 : 0; - int lfo = op[0].ms_ & (op[0].amon_ | op[1].amon_ | op[2].amon_ | op[3].amon_ ? 0x37 : 7) ? 2 : 0; - return key | lfo; -} - -// F-Number/BLOCK を設定 -void Channel4::SetFNum(uint f) -{ - for (int i=0; i<4; i++) - op[i].SetFNum(f); -} - -// KC/KF を設定 -void Channel4::SetKCKF(uint kc, uint kf) -{ - const static uint kctable[16] = - { - 5197, 5506, 5833, 6180, 6180, 6547, 6937, 7349, - 7349, 7786, 8249, 8740, 8740, 9259, 9810, 10394, - }; - - int oct = 19 - ((kc >> 4) & 7); - -//printf("%p", this); - uint kcv = kctable[kc & 0x0f]; - kcv = (kcv + 2) / 4 * 4; -//printf(" %.4x", kcv); - uint dp = kcv * kftable[kf & 0x3f]; -//printf(" %.4x %.4x %.8x", kcv, kftable[kf & 0x3f], dp >> oct); - dp >>= 16 + 3; - dp <<= 16 + 3; - dp >>= oct; - uint bn = (kc >> 2) & 31; - op[0].SetDPBN(dp, bn); - op[1].SetDPBN(dp, bn); - op[2].SetDPBN(dp, bn); - op[3].SetDPBN(dp, bn); -//printf(" %.8x\n", dp); -} - -// キー制御 -void Channel4::KeyControl(uint key) -{ - if (key & 0x1) op[0].KeyOn(); else op[0].KeyOff(); - if (key & 0x2) op[1].KeyOn(); else op[1].KeyOff(); - if (key & 0x4) op[2].KeyOn(); else op[2].KeyOff(); - if (key & 0x8) op[3].KeyOn(); else op[3].KeyOff(); -} - -// アルゴリズムを設定 -void Channel4::SetAlgorithm(uint algo) -{ - static const uint8 table1[8][6] = - { - { 0, 1, 1, 2, 2, 3 }, { 1, 0, 0, 1, 1, 2 }, - { 1, 1, 1, 0, 0, 2 }, { 0, 1, 2, 1, 1, 2 }, - { 0, 1, 2, 2, 2, 1 }, { 0, 1, 0, 1, 0, 1 }, - { 0, 1, 2, 1, 2, 1 }, { 1, 0, 1, 0, 1, 0 }, - }; - - in [0] = &buf[table1[algo][0]]; - out[0] = &buf[table1[algo][1]]; - in [1] = &buf[table1[algo][2]]; - out[1] = &buf[table1[algo][3]]; - in [2] = &buf[table1[algo][4]]; - out[2] = &buf[table1[algo][5]]; - - op[0].ResetFB(); - algo_ = algo; -} - -// 合成 -ISample Channel4::Calc() -{ - int r; - switch (algo_) - { - case 0: - op[2].Calc(op[1].Out()); - op[1].Calc(op[0].Out()); - r = op[3].Calc(op[2].Out()); - op[0].CalcFB(fb); - break; - case 1: - op[2].Calc(op[0].Out() + op[1].Out()); - op[1].Calc(0); - r = op[3].Calc(op[2].Out()); - op[0].CalcFB(fb); - break; - case 2: - op[2].Calc(op[1].Out()); - op[1].Calc(0); - r = op[3].Calc(op[0].Out() + op[2].Out()); - op[0].CalcFB(fb); - break; - case 3: - op[2].Calc(0); - op[1].Calc(op[0].Out()); - r = op[3].Calc(op[1].Out() + op[2].Out()); - op[0].CalcFB(fb); - break; - case 4: - op[2].Calc(0); - r = op[1].Calc(op[0].Out()); - r += op[3].Calc(op[2].Out()); - op[0].CalcFB(fb); - break; - case 5: - r = op[2].Calc(op[0].Out()); - r += op[1].Calc(op[0].Out()); - r += op[3].Calc(op[0].Out()); - op[0].CalcFB(fb); - break; - case 6: - r = op[2].Calc(0); - r += op[1].Calc(op[0].Out()); - r += op[3].Calc(0); - op[0].CalcFB(fb); - break; - case 7: - r = op[2].Calc(0); - r += op[1].Calc(0); - r += op[3].Calc(0); - r += op[0].CalcFB(fb); - break; - } - return r; -} - -// 合成 -ISample Channel4::CalcL() -{ - chip_->SetPMV(pms[chip_->GetPML()]); - - int r; - switch (algo_) - { - case 0: - op[2].CalcL(op[1].Out()); - op[1].CalcL(op[0].Out()); - r = op[3].CalcL(op[2].Out()); - op[0].CalcFBL(fb); - break; - case 1: - op[2].CalcL(op[0].Out() + op[1].Out()); - op[1].CalcL(0); - r = op[3].CalcL(op[2].Out()); - op[0].CalcFBL(fb); - break; - case 2: - op[2].CalcL(op[1].Out()); - op[1].CalcL(0); - r = op[3].CalcL(op[0].Out() + op[2].Out()); - op[0].CalcFBL(fb); - break; - case 3: - op[2].CalcL(0); - op[1].CalcL(op[0].Out()); - r = op[3].CalcL(op[1].Out() + op[2].Out()); - op[0].CalcFBL(fb); - break; - case 4: - op[2].CalcL(0); - r = op[1].CalcL(op[0].Out()); - r += op[3].CalcL(op[2].Out()); - op[0].CalcFBL(fb); - break; - case 5: - r = op[2].CalcL(op[0].Out()); - r += op[1].CalcL(op[0].Out()); - r += op[3].CalcL(op[0].Out()); - op[0].CalcFBL(fb); - break; - case 6: - r = op[2].CalcL(0); - r += op[1].CalcL(op[0].Out()); - r += op[3].CalcL(0); - op[0].CalcFBL(fb); - break; - case 7: - r = op[2].CalcL(0); - r += op[1].CalcL(0); - r += op[3].CalcL(0); - r += op[0].CalcFBL(fb); - break; - } - return r; -} - -// 合成 -ISample Channel4::CalcN(uint noise) -{ - buf[1] = buf[2] = buf[3] = 0; - - buf[0] = op[0].out_; op[0].CalcFB(fb); - *out[0] += op[1].Calc(*in[0]); - *out[1] += op[2].Calc(*in[1]); - int o = op[3].out_; - op[3].CalcN(noise); - return *out[2] + o; -} - -// 合成 -ISample Channel4::CalcLN(uint noise) -{ - chip_->SetPMV(pms[chip_->GetPML()]); - buf[1] = buf[2] = buf[3] = 0; - - buf[0] = op[0].out_; op[0].CalcFBL(fb); - *out[0] += op[1].CalcL(*in[0]); - *out[1] += op[2].CalcL(*in[1]); - int o = op[3].out_; - op[3].CalcN(noise); - return *out[2] + o; -} - -void Channel4::DataSave(struct Channel4Data* data) { - data->fb = fb; - memcpy(data->buf, buf, sizeof(int) * 4); - data->algo_ = algo_; - for(int i = 0; i < 4; i++) { - op[i].DataSave(&data->op[i]); - } -} - -void Channel4::DataLoad(struct Channel4Data* data) { - fb = data->fb; - memcpy(buf, data->buf, sizeof(int) * 4); - algo_ = data->algo_; - SetAlgorithm(algo_); - for(int i = 0; i < 4; i++) { - op[i].DataLoad(&data->op[i]); - } - pms = pmtable[op[0].type_][op[0].ms_ & 7]; -} -} // namespace FM - +// --------------------------------------------------------------------------- +// FM Sound Generator - Core Unit +// Copyright (C) cisc 1998, 2003. +// --------------------------------------------------------------------------- +// $Id: fmgen.cpp,v 1.49 2003/09/02 14:51:04 cisc Exp $ +// --------------------------------------------------------------------------- +// 参考: +// FM sound generator for M.A.M.E., written by Tatsuyuki Satoh. +// +// 謎: +// OPNB の CSM モード(仕様がよくわからない) +// +// 制限: +// ・AR!=31 で SSGEC を使うと波形が実際と異なる可能性あり +// +// 謝辞: +// Tatsuyuki Satoh さん(fm.c) +// Hiromitsu Shioya さん(ADPCM-A) +// DMP-SOFT. さん(OPNB) +// KAJA さん(test program) +// ほか掲示板等で様々なご助言,ご支援をお寄せいただいた皆様に +// --------------------------------------------------------------------------- + +#if defined(SUPPORT_FMGEN) + +#include "fmgen_headers.h" +#include "fmgen_misc.h" +#include "fmgen_fmgen.h" +#include "fmgen_fmgeninl.h" + +#define LOGNAME "fmgen" + +// --------------------------------------------------------------------------- + +#define FM_EG_BOTTOM 955 + +// --------------------------------------------------------------------------- +// Table/etc +// +namespace FM +{ + const uint8 Operator::notetable[128] = + { + 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 17, 18, 19, 19, 19, 19, 19, 19, 19, + 20, 20, 20, 20, 20, 20, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, + 24, 24, 24, 24, 24, 24, 24, 25, 26, 27, 27, 27, 27, 27, 27, 27, + 28, 28, 28, 28, 28, 28, 28, 29, 30, 31, 31, 31, 31, 31, 31, 31, + }; + + const int8 Operator::dttable[256] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, + 4, 6, 6, 6, 8, 8, 8, 10, 10, 12, 12, 14, 16, 16, 16, 16, + 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, + 10, 12, 12, 14, 16, 16, 18, 20, 22, 24, 26, 28, 32, 32, 32, 32, + 4, 4, 4, 4, 4, 6, 6, 6, 8, 8, 8, 10, 10, 12, 12, 14, + 16, 16, 18, 20, 22, 24, 26, 28, 32, 34, 38, 40, 44, 44, 44, 44, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -2, -2, -2, -2, -2, -2, -2, -2, -4, -4, -4, -4, + -4, -6, -6, -6, -8, -8, -8,-10,-10,-12,-12,-14,-16,-16,-16,-16, + -2, -2, -2, -2, -4, -4, -4, -4, -4, -6, -6, -6, -8, -8, -8,-10, + -10,-12,-12,-14,-16,-16,-18,-20,-22,-24,-26,-28,-32,-32,-32,-32, + -4, -4, -4, -4, -4, -6, -6, -6, -8, -8, -8,-10,-10,-12,-12,-14, + -16,-16,-18,-20,-22,-24,-26,-28,-32,-34,-38,-40,-44,-44,-44,-44, + }; + + const int8 Operator::decaytable1[64][8] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 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, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, + 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 4, 2, 2, 2, + 4, 2, 4, 2, 4, 2, 4, 2, 4, 4, 4, 2, 4, 4, 4, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 4, 4, + 8, 4, 8, 4, 8, 4, 8, 4, 8, 8, 8, 4, 8, 8, 8, 4, + 16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16, + }; + + const int Operator::decaytable2[16] = + { + 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2047, 2047, 2047, 2047, 2047 + }; + + const int8 Operator::attacktable[64][8] = + { + -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4,-1, + 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, + 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, + 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, + 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, + 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, + 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, + 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, + 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, + 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, + 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, + 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, + 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, + 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, + 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, + 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, + 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, + 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, + 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, + 4,-1, 4,-1, 4,-1, 4,-1, 4, 4, 4,-1, 4,-1, 4,-1, + 4, 4, 4,-1, 4, 4, 4,-1, 4, 4, 4, 4, 4, 4, 4,-1, + 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, + 3, 4, 3, 4, 3, 4, 3, 4, 3, 3, 3, 4, 3, 3, 3, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 3, 2, 2, 2, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, + }; + + const int Operator::ssgenvtable[8][2][3][2] = + { + 1, 1, 1, 1, 1, 1, // 08 + 0, 1, 1, 1, 1, 1, // 08 56~ + 0, 1, 2, 0, 2, 0, // 09 + 0, 1, 2, 0, 2, 0, // 09 + 1,-1, 0, 1, 1,-1, // 10 + 0, 1, 1,-1, 0, 1, // 10 60~ + 1,-1, 0, 0, 0, 0, // 11 + 0, 1, 0, 0, 0, 0, // 11 60~ + 2,-1, 2,-1, 2,-1, // 12 + 1,-1, 2,-1, 2,-1, // 12 56~ + 1,-1, 0, 0, 0, 0, // 13 + 1,-1, 0, 0, 0, 0, // 13 + 0, 1, 1,-1, 0, 1, // 14 + 1,-1, 0, 1, 1,-1, // 14 60~ + 0, 1, 2, 0, 2, 0, // 15 + 1,-1, 2, 0, 2, 0, // 15 60~ + }; + + // fixed equasion-based tables + int pmtable[2][8][FM_LFOENTS]; + uint amtable[2][4][FM_LFOENTS]; + + static bool tablemade = false; +} + +namespace FM +{ + +// --------------------------------------------------------------------------- +// テーブル作成 +// +void MakeLFOTable() +{ + if (tablemade) + return; + + tablemade = true; + + int i; + + static const double pms[2][8] = + { + { 0, 1/360., 2/360., 3/360., 4/360., 6/360., 12/360., 24/360., }, // OPNA +// { 0, 1/240., 2/240., 4/240., 10/240., 20/240., 80/240., 140/240., }, // OPM + { 0, 1/480., 2/480., 4/480., 10/480., 20/480., 80/480., 140/480., }, // OPM +// { 0, 1/960., 2/960., 4/960., 10/960., 20/960., 80/960., 140/960., }, // OPM + }; + // 3 6, 12 30 60 240 420 / 720 + // 1.000963 + // lfofref[level * max * wave]; + // pre = lfofref[level][pms * wave >> 8]; + static const uint8 amt[2][4] = + { + { 31, 6, 4, 3 }, // OPNA + { 31, 2, 1, 0 }, // OPM + }; + + for (int type = 0; type < 2; type++) + { + for (i=0; i<8; i++) + { + double pmb = pms[type][i]; + for (int j=0; j> amt[type][i]) * 2) << 2; + } + } + } +} + + +// --------------------------------------------------------------------------- +// チップ内で共通な部分 +// +Chip::Chip() +: ratio_(0), aml_(0), pml_(0), pmv_(0), optype_(typeN) +{ +} + +// クロック・サンプリングレート比に依存するテーブルを作成 +void Chip::SetRatio(uint ratio) +{ + if (ratio_ != ratio) + { + ratio_ = ratio; + MakeTable(); + } +} + +void Chip::MakeTable() +{ + int h, l; + + // PG Part + static const float dt2lv[4] = { 1.f, 1.414f, 1.581f, 1.732f }; + for (h=0; h<4; h++) + { + assert(2 + FM_RATIOBITS - FM_PGBITS >= 0); + double rr = dt2lv[h] * double(ratio_) / (1 << (2 + FM_RATIOBITS - FM_PGBITS)); + for (l=0; l<16; l++) + { + int mul = l ? l * 2 : 1; + multable_[h][l] = uint(mul * rr); + } + } +} + +void Chip::DataSave(struct ChipData* data) +{ + data->ratio_ = ratio_; + data->aml_ = aml_; + data->pml_ = pml_; + data->pmv_ = pmv_; + memcpy(data->multable_, multable_, sizeof(uint32) * 4 * 16); +} + +void Chip::DataLoad(struct ChipData* data) +{ + ratio_ = data->ratio_; + aml_ = data->aml_; + pml_ = data->pml_; + pmv_ = data->pmv_; + memcpy(multable_, data->multable_, sizeof(uint32) * 4 * 16); +} + +// --------------------------------------------------------------------------- +// Operator +// +bool FM::Operator::tablehasmade = false; +uint FM::Operator::sinetable[1024]; +int32 FM::Operator::cltable[FM_CLENTS]; + +// 構築 +FM::Operator::Operator() +: chip_(0) +{ + if (!tablehasmade) + MakeTable(); + + // EG Part + ar_ = dr_ = sr_ = rr_ = key_scale_rate_ = 0; + ams_ = amtable[0][0]; + mute_ = false; + keyon_ = false; + tl_out_ = false; + ssg_type_ = 0; + + // PG Part + multiple_ = 0; + detune_ = 0; + detune2_ = 0; + + // LFO + ms_ = 0; + +// Reset(); +} + +// 初期化 +void FM::Operator::Reset() +{ + // EG part + tl_ = tl_latch_ = 127; + ShiftPhase(off); + eg_count_ = 0; + eg_curve_count_ = 0; + ssg_phase_ = 0; + + // PG part + pg_count_ = 0; + + // OP part + out_ = out2_ = 0; + + param_changed_ = true; + PARAMCHANGE(0); +} + +void Operator::MakeTable() +{ + // 対数テーブルの作成 + assert(FM_CLENTS >= 256); + + int* p = cltable; + int i; + for (i=0; i<256; i++) + { + int v = int(floor(pow(2., 13. - i / 256.))); + v = (v + 2) & ~3; + *p++ = v; + *p++ = -v; + } + while (p < cltable + FM_CLENTS) + { + //*p++ = p[-512] / 2; + *p = p[-512] / 2; + p++; + } + +// for (i=0; i<13*256; i++) +// printf("%4d, %d, %d\n", i, cltable[i*2], cltable[i*2+1]); + + // サインテーブルの作成 + double log2 = log(2.); + for (i=0; iGetMulValue(detune2_, multiple_); + pg_diff_lfo_ = pg_diff_ >> 11; + + // EG Part + key_scale_rate_ = bn_ >> (3-ks_); + tl_out_ = mute_ ? 0x3ff : tl_ * 8; + + switch (eg_phase_) + { + case attack: + SetEGRate(ar_ ? Min(63, ar_ + key_scale_rate_) : 0); + break; + case decay: + SetEGRate(dr_ ? Min(63, dr_ + key_scale_rate_) : 0); + eg_level_on_next_phase_ = sl_ * 8; + break; + case sustain: + SetEGRate(sr_ ? Min(63, sr_ + key_scale_rate_) : 0); + break; + case release: + SetEGRate(Min(63, rr_ + key_scale_rate_)); + break; + } + + // SSG-EG + if (ssg_type_ && (eg_phase_ != release)) + { + int m = ar_ >= ((ssg_type_ == 8 || ssg_type_ == 12) ? 56 : 60); + + assert(0 <= ssg_phase_ && ssg_phase_ <= 2); + const int* table = ssgenvtable[ssg_type_ & 7][m][ssg_phase_]; + + ssg_offset_ = table[0] * 0x200; + ssg_vector_ = table[1]; + } + // LFO + ams_ = amtable[type_][amon_ ? (ms_ >> 4) & 3 : 0]; + EGUpdate(); + + dbgopout_ = 0; + } +} + +void Operator::DataSave(struct OperatorData* data) +{ + data->out_ = out_; + data->out2_ = out2_; + data->in2_ = in2_; + data->dp_ = dp_; + data->detune_ = detune_; + data->detune2_ = detune2_; + data->multiple_ = multiple_; + data->pg_count_ = pg_count_; + data->pg_diff_ = pg_diff_; + data->pg_diff_lfo_ = pg_diff_lfo_; + data->type_ = type_; + data->bn_ = bn_; + data->eg_level_ = eg_level_; + data->eg_level_on_next_phase_ = eg_level_on_next_phase_; + data->eg_count_ = eg_count_; + data->eg_count_diff_ = eg_count_diff_; + data->eg_out_ = eg_out_; + data->tl_out_ = tl_out_; + data->eg_rate_ = eg_rate_; + data->eg_curve_count_ = eg_curve_count_; + data->ssg_offset_ = ssg_offset_; + data->ssg_vector_ = ssg_vector_; + data->ssg_phase_ = ssg_phase_; + data->key_scale_rate_ = key_scale_rate_; + data->eg_phase_ = eg_phase_; + data->ms_ = ms_; + data->tl_ = tl_; + data->tl_latch_ = tl_latch_; + data->ar_ = ar_; + data->dr_ = dr_; + data->sr_ = sr_; + data->sl_ = sl_; + data->rr_ = rr_; + data->ks_ = ks_; + data->ssg_type_ = ssg_type_; + data->keyon_ = keyon_; + data->amon_ = amon_; + data->param_changed_ = param_changed_; + data->mute_ = mute_; +} + +void Operator::DataLoad(struct OperatorData* data) +{ + out_ = data->out_; + out2_ = data->out2_; + in2_ = data->in2_; + dp_ = data->dp_; + detune_ = data->detune_; + detune2_ = data->detune2_; + multiple_ = data->multiple_; + pg_count_ = data->pg_count_; + pg_diff_ = data->pg_diff_; + pg_diff_lfo_ = data->pg_diff_lfo_; + type_ = data->type_; + bn_ = data->bn_; + eg_level_ = data->eg_level_; + eg_level_on_next_phase_ = data->eg_level_on_next_phase_; + eg_count_ = data->eg_count_; + eg_count_diff_ = data->eg_count_diff_; + eg_out_ = data->eg_out_; + tl_out_ = data->tl_out_; + eg_rate_ = data->eg_rate_; + eg_curve_count_ = data->eg_curve_count_; + ssg_offset_ = data->ssg_offset_; + ssg_vector_ = data->ssg_vector_; + ssg_phase_ = data->ssg_phase_; + key_scale_rate_ = data->key_scale_rate_; + eg_phase_ = data->eg_phase_; + ms_ = data->ms_; + tl_ = data->tl_; + tl_latch_ = data->tl_latch_; + ar_ = data->ar_; + dr_ = data->dr_; + sr_ = data->sr_; + sl_ = data->sl_; + rr_ = data->rr_; + ks_ = data->ks_; + ssg_type_ = data->ssg_type_; + keyon_ = data->keyon_; + amon_ = data->amon_; + param_changed_ = data->param_changed_; + mute_ = data->mute_; + ams_ = amtable[type_][amon_ ? (ms_ >> 4) & 3 : 0]; +} + + +// envelop の eg_phase_ 変更 +void Operator::ShiftPhase(EGPhase nextphase) +{ + switch (nextphase) + { + case attack: // Attack Phase + tl_ = tl_latch_; + if (ssg_type_) + { + ssg_phase_ = ssg_phase_ + 1; + if (ssg_phase_ > 2) + ssg_phase_ = 1; + + int m = ar_ >= ((ssg_type_ == 8 || ssg_type_ == 12) ? 56 : 60); + + assert(0 <= ssg_phase_ && ssg_phase_ <= 2); + const int* table = ssgenvtable[ssg_type_ & 7][m][ssg_phase_]; + + ssg_offset_ = table[0] * 0x200; + ssg_vector_ = table[1]; + } + if ((ar_ + key_scale_rate_) < 62) + { + SetEGRate(ar_ ? Min(63, ar_ + key_scale_rate_) : 0); + eg_phase_ = attack; + break; + } + case decay: // Decay Phase + if (sl_) + { + eg_level_ = 0; + eg_level_on_next_phase_ = ssg_type_ ? Min(sl_ * 8, 0x200) : sl_ * 8; + + SetEGRate(dr_ ? Min(63, dr_ + key_scale_rate_) : 0); + eg_phase_ = decay; + break; + } + case sustain: // Sustain Phase + eg_level_ = sl_ * 8; + eg_level_on_next_phase_ = ssg_type_ ? 0x200 : 0x400; + + SetEGRate(sr_ ? Min(63, sr_ + key_scale_rate_) : 0); + eg_phase_ = sustain; + break; + + case release: // Release Phase + if (ssg_type_) + { + eg_level_ = eg_level_ * ssg_vector_ + ssg_offset_; + ssg_vector_ = 1; + ssg_offset_ = 0; + } + if (eg_phase_ == attack || (eg_level_ < FM_EG_BOTTOM)) //0x400/* && eg_phase_ != off*/)) + { + eg_level_on_next_phase_ = 0x400; + SetEGRate(Min(63, rr_ + key_scale_rate_)); + eg_phase_ = release; + break; + } + case off: // off + default: + eg_level_ = FM_EG_BOTTOM; + eg_level_on_next_phase_ = FM_EG_BOTTOM; + EGUpdate(); + SetEGRate(0); + eg_phase_ = off; + break; + } +} + +// Block/F-Num +void Operator::SetFNum(uint f) +{ + dp_ = (f & 2047) << ((f >> 11) & 7); + bn_ = notetable[(f >> 7) & 127]; + param_changed_ = true; + PARAMCHANGE(2); +} + +// 1サンプル合成 + +// ISample を envelop count (2π) に変換するシフト量 +#define IS2EC_SHIFT ((20 + FM_PGBITS) - 13) + + +// 入力: s = 20+FM_PGBITS = 29 +#define Sine(s) sinetable[((s) >> (20+FM_PGBITS-FM_OPSINBITS))&(FM_OPSINENTS-1)] +#define SINE(s) sinetable[(s) & (FM_OPSINENTS-1)] + +inline FM::ISample Operator::LogToLin(uint a) +{ +#if 1 // FM_CLENTS < 0xc00 // 400 for TL, 400 for ENV, 400 for LFO. + return (a < FM_CLENTS) ? cltable[a] : 0; +#else + return cltable[a]; +#endif +} + +inline void Operator::EGUpdate() +{ + if (!ssg_type_) + { + eg_out_ = Min(tl_out_ + eg_level_, 0x3ff) << (1 + 2); + } + else + { + eg_out_ = Min(tl_out_ + eg_level_ * ssg_vector_ + ssg_offset_, 0x3ff) << (1 + 2); + } +} + +inline void Operator::SetEGRate(uint rate) +{ + eg_rate_ = rate; + eg_count_diff_ = decaytable2[rate / 4] * chip_->GetRatio(); +} + +// EG 計算 +void FM::Operator::EGCalc() +{ + eg_count_ = (2047 * 3) << FM_RATIOBITS; // ##この手抜きは再現性を低下させる + + if (eg_phase_ == attack) + { + int c = attacktable[eg_rate_][eg_curve_count_ & 7]; + if (c >= 0) + { + eg_level_ -= 1 + (eg_level_ >> c); + if (eg_level_ <= 0) + ShiftPhase(decay); + } + EGUpdate(); + } + else + { + if (!ssg_type_) + { + eg_level_ += decaytable1[eg_rate_][eg_curve_count_ & 7]; + if (eg_level_ >= eg_level_on_next_phase_) + ShiftPhase(EGPhase(eg_phase_+1)); + EGUpdate(); + } + else + { + eg_level_ += 4 * decaytable1[eg_rate_][eg_curve_count_ & 7]; + if (eg_level_ >= eg_level_on_next_phase_) + { + EGUpdate(); + switch (eg_phase_) + { + case decay: + ShiftPhase(sustain); + break; + case sustain: + ShiftPhase(attack); + break; + case release: + ShiftPhase(off); + break; + } + } + } + } + eg_curve_count_++; +} + +inline void FM::Operator::EGStep() +{ + eg_count_ -= eg_count_diff_; + + // EG の変化は全スロットで同期しているという噂もある + if (eg_count_ <= 0) + EGCalc(); +} + +// PG 計算 +// ret:2^(20+PGBITS) / cycle +inline uint32 FM::Operator::PGCalc() +{ + uint32 ret = pg_count_; + pg_count_ += pg_diff_; + dbgpgout_ = ret; + return ret; +} + +inline uint32 FM::Operator::PGCalcL() +{ + uint32 ret = pg_count_; + pg_count_ += pg_diff_ + ((pg_diff_lfo_ * chip_->GetPMV()) >> 5);// & -(1 << (2+IS2EC_SHIFT))); + dbgpgout_ = ret; + return ret /* + pmv * pg_diff_;*/; +} + +// OP 計算 +// in: ISample (最大 8π) +inline FM::ISample FM::Operator::Calc(ISample in) +{ + EGStep(); + out2_ = out_; + + int pgin = PGCalc() >> (20+FM_PGBITS-FM_OPSINBITS); + pgin += in >> (20+FM_PGBITS-FM_OPSINBITS-(2+IS2EC_SHIFT)); + out_ = LogToLin(eg_out_ + SINE(pgin)); + + dbgopout_ = out_; + return out_; +} + +inline FM::ISample FM::Operator::CalcL(ISample in) +{ + EGStep(); + + int pgin = PGCalcL() >> (20+FM_PGBITS-FM_OPSINBITS); + pgin += in >> (20+FM_PGBITS-FM_OPSINBITS-(2+IS2EC_SHIFT)); + out_ = LogToLin(eg_out_ + SINE(pgin) + ams_[chip_->GetAML()]); + + dbgopout_ = out_; + return out_; +} + +inline FM::ISample FM::Operator::CalcN(uint noise) +{ + EGStep(); + + int lv = Max(0, 0x3ff - (tl_out_ + eg_level_)) << 1; + + // noise & 1 ? lv : -lv と等価 + noise = (noise & 1) - 1; + out_ = (lv + noise) ^ noise; + + dbgopout_ = out_; + return out_; +} + +// OP (FB) 計算 +// Self Feedback の変調最大 = 4π +inline FM::ISample FM::Operator::CalcFB(uint fb) +{ + EGStep(); + + ISample in = out_ + out2_; + out2_ = out_; + + int pgin = PGCalc() >> (20+FM_PGBITS-FM_OPSINBITS); + if (fb < 31) + { + pgin += ((in << (1 + IS2EC_SHIFT)) >> fb) >> (20+FM_PGBITS-FM_OPSINBITS); + } + out_ = LogToLin(eg_out_ + SINE(pgin)); + dbgopout_ = out2_; + + return out2_; +} + +inline FM::ISample FM::Operator::CalcFBL(uint fb) +{ + EGStep(); + + ISample in = out_ + out2_; + out2_ = out_; + + int pgin = PGCalcL() >> (20+FM_PGBITS-FM_OPSINBITS); + if (fb < 31) + { + pgin += ((in << (1 + IS2EC_SHIFT)) >> fb) >> (20+FM_PGBITS-FM_OPSINBITS); + } + + out_ = LogToLin(eg_out_ + SINE(pgin) + ams_[chip_->GetAML()]); + dbgopout_ = out_; + + return out_; +} + +#undef Sine + +// --------------------------------------------------------------------------- +// 4-op Channel +// +const uint8 Channel4::fbtable[8] = { 31, 7, 6, 5, 4, 3, 2, 1 }; +int Channel4::kftable[64]; + +bool Channel4::tablehasmade = false; + + +Channel4::Channel4() +{ + if (!tablehasmade) + MakeTable(); + + SetAlgorithm(0); + pms = pmtable[0][0]; +} + +void Channel4::MakeTable() +{ + // 100/64 cent = 2^(i*100/64*1200) + for (int i=0; i<64; i++) + { + kftable[i] = int(0x10000 * pow(2., i / 768.) ); + } +} + +// リセット +void Channel4::Reset() +{ + op[0].Reset(); + op[1].Reset(); + op[2].Reset(); + op[3].Reset(); +} + +// Calc の用意 +int Channel4::Prepare() +{ + op[0].Prepare(); + op[1].Prepare(); + op[2].Prepare(); + op[3].Prepare(); + + pms = pmtable[op[0].type_][op[0].ms_ & 7]; + int key = (op[0].IsOn() | op[1].IsOn() | op[2].IsOn() | op[3].IsOn()) ? 1 : 0; + int lfo = op[0].ms_ & (op[0].amon_ | op[1].amon_ | op[2].amon_ | op[3].amon_ ? 0x37 : 7) ? 2 : 0; + return key | lfo; +} + +// F-Number/BLOCK を設定 +void Channel4::SetFNum(uint f) +{ + for (int i=0; i<4; i++) + op[i].SetFNum(f); +} + +// KC/KF を設定 +void Channel4::SetKCKF(uint kc, uint kf) +{ + const static uint kctable[16] = + { + 5197, 5506, 5833, 6180, 6180, 6547, 6937, 7349, + 7349, 7786, 8249, 8740, 8740, 9259, 9810, 10394, + }; + + int oct = 19 - ((kc >> 4) & 7); + +//printf("%p", this); + uint kcv = kctable[kc & 0x0f]; + kcv = (kcv + 2) / 4 * 4; +//printf(" %.4x", kcv); + uint dp = kcv * kftable[kf & 0x3f]; +//printf(" %.4x %.4x %.8x", kcv, kftable[kf & 0x3f], dp >> oct); + dp >>= 16 + 3; + dp <<= 16 + 3; + dp >>= oct; + uint bn = (kc >> 2) & 31; + op[0].SetDPBN(dp, bn); + op[1].SetDPBN(dp, bn); + op[2].SetDPBN(dp, bn); + op[3].SetDPBN(dp, bn); +//printf(" %.8x\n", dp); +} + +// キー制御 +void Channel4::KeyControl(uint key) +{ + if (key & 0x1) op[0].KeyOn(); else op[0].KeyOff(); + if (key & 0x2) op[1].KeyOn(); else op[1].KeyOff(); + if (key & 0x4) op[2].KeyOn(); else op[2].KeyOff(); + if (key & 0x8) op[3].KeyOn(); else op[3].KeyOff(); +} + +// アルゴリズムを設定 +void Channel4::SetAlgorithm(uint algo) +{ + static const uint8 table1[8][6] = + { + { 0, 1, 1, 2, 2, 3 }, { 1, 0, 0, 1, 1, 2 }, + { 1, 1, 1, 0, 0, 2 }, { 0, 1, 2, 1, 1, 2 }, + { 0, 1, 2, 2, 2, 1 }, { 0, 1, 0, 1, 0, 1 }, + { 0, 1, 2, 1, 2, 1 }, { 1, 0, 1, 0, 1, 0 }, + }; + + in [0] = &buf[table1[algo][0]]; + out[0] = &buf[table1[algo][1]]; + in [1] = &buf[table1[algo][2]]; + out[1] = &buf[table1[algo][3]]; + in [2] = &buf[table1[algo][4]]; + out[2] = &buf[table1[algo][5]]; + + op[0].ResetFB(); + algo_ = algo; +} + +// 合成 +ISample Channel4::Calc() +{ + int r; + switch (algo_) + { + case 0: + op[2].Calc(op[1].Out()); + op[1].Calc(op[0].Out()); + r = op[3].Calc(op[2].Out()); + op[0].CalcFB(fb); + break; + case 1: + op[2].Calc(op[0].Out() + op[1].Out()); + op[1].Calc(0); + r = op[3].Calc(op[2].Out()); + op[0].CalcFB(fb); + break; + case 2: + op[2].Calc(op[1].Out()); + op[1].Calc(0); + r = op[3].Calc(op[0].Out() + op[2].Out()); + op[0].CalcFB(fb); + break; + case 3: + op[2].Calc(0); + op[1].Calc(op[0].Out()); + r = op[3].Calc(op[1].Out() + op[2].Out()); + op[0].CalcFB(fb); + break; + case 4: + op[2].Calc(0); + r = op[1].Calc(op[0].Out()); + r += op[3].Calc(op[2].Out()); + op[0].CalcFB(fb); + break; + case 5: + r = op[2].Calc(op[0].Out()); + r += op[1].Calc(op[0].Out()); + r += op[3].Calc(op[0].Out()); + op[0].CalcFB(fb); + break; + case 6: + r = op[2].Calc(0); + r += op[1].Calc(op[0].Out()); + r += op[3].Calc(0); + op[0].CalcFB(fb); + break; + case 7: + r = op[2].Calc(0); + r += op[1].Calc(0); + r += op[3].Calc(0); + r += op[0].CalcFB(fb); + break; + } + return r; +} + +// 合成 +ISample Channel4::CalcL() +{ + chip_->SetPMV(pms[chip_->GetPML()]); + + int r; + switch (algo_) + { + case 0: + op[2].CalcL(op[1].Out()); + op[1].CalcL(op[0].Out()); + r = op[3].CalcL(op[2].Out()); + op[0].CalcFBL(fb); + break; + case 1: + op[2].CalcL(op[0].Out() + op[1].Out()); + op[1].CalcL(0); + r = op[3].CalcL(op[2].Out()); + op[0].CalcFBL(fb); + break; + case 2: + op[2].CalcL(op[1].Out()); + op[1].CalcL(0); + r = op[3].CalcL(op[0].Out() + op[2].Out()); + op[0].CalcFBL(fb); + break; + case 3: + op[2].CalcL(0); + op[1].CalcL(op[0].Out()); + r = op[3].CalcL(op[1].Out() + op[2].Out()); + op[0].CalcFBL(fb); + break; + case 4: + op[2].CalcL(0); + r = op[1].CalcL(op[0].Out()); + r += op[3].CalcL(op[2].Out()); + op[0].CalcFBL(fb); + break; + case 5: + r = op[2].CalcL(op[0].Out()); + r += op[1].CalcL(op[0].Out()); + r += op[3].CalcL(op[0].Out()); + op[0].CalcFBL(fb); + break; + case 6: + r = op[2].CalcL(0); + r += op[1].CalcL(op[0].Out()); + r += op[3].CalcL(0); + op[0].CalcFBL(fb); + break; + case 7: + r = op[2].CalcL(0); + r += op[1].CalcL(0); + r += op[3].CalcL(0); + r += op[0].CalcFBL(fb); + break; + } + return r; +} + +// 合成 +ISample Channel4::CalcN(uint noise) +{ + buf[1] = buf[2] = buf[3] = 0; + + buf[0] = op[0].out_; op[0].CalcFB(fb); + *out[0] += op[1].Calc(*in[0]); + *out[1] += op[2].Calc(*in[1]); + int o = op[3].out_; + op[3].CalcN(noise); + return *out[2] + o; +} + +// 合成 +ISample Channel4::CalcLN(uint noise) +{ + chip_->SetPMV(pms[chip_->GetPML()]); + buf[1] = buf[2] = buf[3] = 0; + + buf[0] = op[0].out_; op[0].CalcFBL(fb); + *out[0] += op[1].CalcL(*in[0]); + *out[1] += op[2].CalcL(*in[1]); + int o = op[3].out_; + op[3].CalcN(noise); + return *out[2] + o; +} + +void Channel4::DataSave(struct Channel4Data* data) { + data->fb = fb; + memcpy(data->buf, buf, sizeof(int) * 4); + data->algo_ = algo_; + for(int i = 0; i < 4; i++) { + op[i].DataSave(&data->op[i]); + } +} + +void Channel4::DataLoad(struct Channel4Data* data) { + fb = data->fb; + memcpy(buf, data->buf, sizeof(int) * 4); + algo_ = data->algo_; + SetAlgorithm(algo_); + for(int i = 0; i < 4; i++) { + op[i].DataLoad(&data->op[i]); + } + pms = pmtable[op[0].type_][op[0].ms_ & 7]; +} +} // namespace FM + #endif /* SUPPORT_FMGEN */ \ No newline at end of file diff --git a/sound/fmgen/fmgen_fmgen.h b/sound/fmgen/fmgen_fmgen.h old mode 100755 new mode 100644 index 8566b988..e44c5994 --- a/sound/fmgen/fmgen_fmgen.h +++ b/sound/fmgen/fmgen_fmgen.h @@ -1,340 +1,340 @@ -// --------------------------------------------------------------------------- -// FM Sound Generator -// Copyright (C) cisc 1998, 2001. -// --------------------------------------------------------------------------- -// $Id: fmgen.h,v 1.37 2003/08/25 13:33:11 cisc Exp $ - -#pragma once -#if defined(SUPPORT_FMGEN) - -#ifndef FM_GEN_H -#define FM_GEN_H - -#include "fmgen_types.h" - -// --------------------------------------------------------------------------- -// 出力サンプルの型 -// -#define FM_SAMPLETYPE int32 // int16 or int32 - -// --------------------------------------------------------------------------- -// 定数その1 -// 静的テーブルのサイズ - -#define FM_LFOBITS 8 // 変更不可 -#define FM_TLBITS 7 - -// --------------------------------------------------------------------------- - -#define FM_TLENTS (1 << FM_TLBITS) -#define FM_LFOENTS (1 << FM_LFOBITS) -#define FM_TLPOS (FM_TLENTS/4) - -// サイン波の精度は 2^(1/256) -#define FM_CLENTS (0x1000 * 2) // sin + TL + LFO - -// --------------------------------------------------------------------------- - -namespace FM -{ - // Types ---------------------------------------------------------------- - typedef FM_SAMPLETYPE Sample; - typedef int32 ISample; - - enum OpType { typeN=0, typeM=1 }; - enum EGPhase { next, attack, decay, sustain, release, off }; - - void StoreSample(ISample& dest, int data); - - class Chip; - struct ChipData; - - // Operator ------------------------------------------------------------- - struct OperatorData { - ISample out_; - ISample out2_; - ISample in2_; - uint dp_; - uint detune_; - uint detune2_; - uint multiple_; - uint32 pg_count_; - uint32 pg_diff_; - int32 pg_diff_lfo_; - OpType type_; - uint bn_; - int eg_level_; - int eg_level_on_next_phase_; - int eg_count_; - int eg_count_diff_; - int eg_out_; - int tl_out_; - int eg_rate_; - int eg_curve_count_; - int ssg_offset_; - int ssg_vector_; - int ssg_phase_; - uint key_scale_rate_; - EGPhase eg_phase_; - uint ms_; - - uint tl_; - uint tl_latch_; - uint ar_; - uint dr_; - uint sr_; - uint sl_; - uint rr_; - uint ks_; - uint ssg_type_; - - bool keyon_; - bool amon_; - bool param_changed_; - bool mute_; - }; - - class Operator - { - public: - Operator(); - void SetChip(Chip* chip) { chip_ = chip; } - - static void MakeTimeTable(uint ratio); - - ISample Calc(ISample in); - ISample CalcL(ISample in); - ISample CalcFB(uint fb); - ISample CalcFBL(uint fb); - ISample CalcN(uint noise); - void Prepare(); - void KeyOn(); - void KeyOff(); - void Reset(); - void ResetFB(); - int IsOn(); - - void SetDT(uint dt); - void SetDT2(uint dt2); - void SetMULTI(uint multi); - void SetTL(uint tl, bool csm); - void SetKS(uint ks); - void SetAR(uint ar); - void SetDR(uint dr); - void SetSR(uint sr); - void SetRR(uint rr); - void SetSL(uint sl); - void SetSSGEC(uint ssgec); - void SetFNum(uint fnum); - void SetDPBN(uint dp, uint bn); - void SetMode(bool modulator); - void SetAMON(bool on); - void SetMS(uint ms); - void Mute(bool); - -// static void SetAML(uint l); -// static void SetPML(uint l); - - int Out() { return out_; } - - int dbgGetIn2() { return in2_; } - void dbgStopPG() { pg_diff_ = 0; pg_diff_lfo_ = 0; } - - void DataSave(struct OperatorData* data); - void DataLoad(struct OperatorData* data); - - private: - typedef uint32 Counter; - - Chip* chip_; - ISample out_, out2_; - ISample in2_; - - // Phase Generator ------------------------------------------------------ - uint32 PGCalc(); - uint32 PGCalcL(); - - uint dp_; // ΔP - uint detune_; // Detune - uint detune2_; // DT2 - uint multiple_; // Multiple - uint32 pg_count_; // Phase 現在値 - uint32 pg_diff_; // Phase 差分値 - int32 pg_diff_lfo_; // Phase 差分値 >> x - - // Envelop Generator --------------------------------------------------- - void EGCalc(); - void EGStep(); - void ShiftPhase(EGPhase nextphase); - void SSGShiftPhase(int mode); - void SetEGRate(uint); - void EGUpdate(); - int FBCalc(int fb); - ISample LogToLin(uint a); - - - OpType type_; // OP の種類 (M, N...) - uint bn_; // Block/Note - int eg_level_; // EG の出力値 - int eg_level_on_next_phase_; // 次の eg_phase_ に移る値 - int eg_count_; // EG の次の変移までの時間 - int eg_count_diff_; // eg_count_ の差分 - int eg_out_; // EG+TL を合わせた出力値 - int tl_out_; // TL 分の出力値 -// int pm_depth_; // PM depth -// int am_depth_; // AM depth - int eg_rate_; - int eg_curve_count_; - int ssg_offset_; - int ssg_vector_; - int ssg_phase_; - - - uint key_scale_rate_; // key scale rate - EGPhase eg_phase_; - uint* ams_; - uint ms_; - - uint tl_; // Total Level (0-127) - uint tl_latch_; // Total Level Latch (for CSM mode) - uint ar_; // Attack Rate (0-63) - uint dr_; // Decay Rate (0-63) - uint sr_; // Sustain Rate (0-63) - uint sl_; // Sustain Level (0-127) - uint rr_; // Release Rate (0-63) - uint ks_; // Keyscale (0-3) - uint ssg_type_; // SSG-Type Envelop Control - - bool keyon_; - bool amon_; // enable Amplitude Modulation - bool param_changed_; // パラメータが更新された - bool mute_; - - // Tables --------------------------------------------------------------- - static Counter rate_table[16]; - static uint32 multable[4][16]; - - static const uint8 notetable[128]; - static const int8 dttable[256]; - static const int8 decaytable1[64][8]; - static const int decaytable2[16]; - static const int8 attacktable[64][8]; - static const int ssgenvtable[8][2][3][2]; - - static uint sinetable[1024]; - static int32 cltable[FM_CLENTS]; - - static bool tablehasmade; - static void MakeTable(); - - - - // friends -------------------------------------------------------------- - friend class Channel4; - friend void __stdcall FM_NextPhase(Operator* op); - - public: - int dbgopout_; - int dbgpgout_; - static const int32* dbgGetClTable() { return cltable; } - static const uint* dbgGetSineTable() { return sinetable; } - }; - - // 4-op Channel --------------------------------------------------------- - struct Channel4Data { - uint fb; - int buf[4]; - int algo_; - struct OperatorData op[4]; - }; - - class Channel4 - { - public: - Channel4(); - void SetChip(Chip* chip); - void SetType(OpType type); - - ISample Calc(); - ISample CalcL(); - ISample CalcN(uint noise); - ISample CalcLN(uint noise); - void SetFNum(uint fnum); - void SetFB(uint fb); - void SetKCKF(uint kc, uint kf); - void SetAlgorithm(uint algo); - int Prepare(); - void KeyControl(uint key); - void Reset(); - void SetMS(uint ms); - void Mute(bool); - void Refresh(); - - void dbgStopPG() { for (int i=0; i<4; i++) op[i].dbgStopPG(); } - - void DataSave(struct Channel4Data* data); - void DataLoad(struct Channel4Data* data); - - private: - static const uint8 fbtable[8]; - uint fb; - int buf[4]; - int* in[3]; // 各 OP の入力ポインタ - int* out[3]; // 各 OP の出力ポインタ - int* pms; - int algo_; - Chip* chip_; - - static void MakeTable(); - - static bool tablehasmade; - static int kftable[64]; - - - public: - Operator op[4]; - }; - - // Chip resource - struct ChipData { - uint ratio_; - uint aml_; - uint pml_; - int pmv_; - OpType optype_; - uint32 multable_[4][16]; - }; - - class Chip - { - public: - Chip(); - void SetRatio(uint ratio); - void SetAML(uint l); - void SetPML(uint l); - void SetPMV(int pmv) { pmv_ = pmv; } - - uint32 GetMulValue(uint dt2, uint mul) { return multable_[dt2][mul]; } - uint GetAML() { return aml_; } - uint GetPML() { return pml_; } - int GetPMV() { return pmv_; } - uint GetRatio() { return ratio_; } - - void DataSave(struct ChipData* data); - void DataLoad(struct ChipData* data); - - private: - void MakeTable(); - - uint ratio_; - uint aml_; - uint pml_; - int pmv_; - OpType optype_; - uint32 multable_[4][16]; - }; -} - -#endif // FM_GEN_H - -#endif /* SUPPORT_FMGEN */ +// --------------------------------------------------------------------------- +// FM Sound Generator +// Copyright (C) cisc 1998, 2001. +// --------------------------------------------------------------------------- +// $Id: fmgen.h,v 1.37 2003/08/25 13:33:11 cisc Exp $ + +#pragma once +#if defined(SUPPORT_FMGEN) + +#ifndef FM_GEN_H +#define FM_GEN_H + +#include "fmgen_types.h" + +// --------------------------------------------------------------------------- +// 出力サンプルの型 +// +#define FM_SAMPLETYPE int32 // int16 or int32 + +// --------------------------------------------------------------------------- +// 定数その1 +// 静的テーブルのサイズ + +#define FM_LFOBITS 8 // 変更不可 +#define FM_TLBITS 7 + +// --------------------------------------------------------------------------- + +#define FM_TLENTS (1 << FM_TLBITS) +#define FM_LFOENTS (1 << FM_LFOBITS) +#define FM_TLPOS (FM_TLENTS/4) + +// サイン波の精度は 2^(1/256) +#define FM_CLENTS (0x1000 * 2) // sin + TL + LFO + +// --------------------------------------------------------------------------- + +namespace FM +{ + // Types ---------------------------------------------------------------- + typedef FM_SAMPLETYPE Sample; + typedef int32 ISample; + + enum OpType { typeN=0, typeM=1 }; + enum EGPhase { next, attack, decay, sustain, release, off }; + + void StoreSample(ISample& dest, int data); + + class Chip; + struct ChipData; + + // Operator ------------------------------------------------------------- + struct OperatorData { + ISample out_; + ISample out2_; + ISample in2_; + uint dp_; + uint detune_; + uint detune2_; + uint multiple_; + uint32 pg_count_; + uint32 pg_diff_; + int32 pg_diff_lfo_; + OpType type_; + uint bn_; + int eg_level_; + int eg_level_on_next_phase_; + int eg_count_; + int eg_count_diff_; + int eg_out_; + int tl_out_; + int eg_rate_; + int eg_curve_count_; + int ssg_offset_; + int ssg_vector_; + int ssg_phase_; + uint key_scale_rate_; + EGPhase eg_phase_; + uint ms_; + + uint tl_; + uint tl_latch_; + uint ar_; + uint dr_; + uint sr_; + uint sl_; + uint rr_; + uint ks_; + uint ssg_type_; + + bool keyon_; + bool amon_; + bool param_changed_; + bool mute_; + }; + + class Operator + { + public: + Operator(); + void SetChip(Chip* chip) { chip_ = chip; } + + static void MakeTimeTable(uint ratio); + + ISample Calc(ISample in); + ISample CalcL(ISample in); + ISample CalcFB(uint fb); + ISample CalcFBL(uint fb); + ISample CalcN(uint noise); + void Prepare(); + void KeyOn(); + void KeyOff(); + void Reset(); + void ResetFB(); + int IsOn(); + + void SetDT(uint dt); + void SetDT2(uint dt2); + void SetMULTI(uint multi); + void SetTL(uint tl, bool csm); + void SetKS(uint ks); + void SetAR(uint ar); + void SetDR(uint dr); + void SetSR(uint sr); + void SetRR(uint rr); + void SetSL(uint sl); + void SetSSGEC(uint ssgec); + void SetFNum(uint fnum); + void SetDPBN(uint dp, uint bn); + void SetMode(bool modulator); + void SetAMON(bool on); + void SetMS(uint ms); + void Mute(bool); + +// static void SetAML(uint l); +// static void SetPML(uint l); + + int Out() { return out_; } + + int dbgGetIn2() { return in2_; } + void dbgStopPG() { pg_diff_ = 0; pg_diff_lfo_ = 0; } + + void DataSave(struct OperatorData* data); + void DataLoad(struct OperatorData* data); + + private: + typedef uint32 Counter; + + Chip* chip_; + ISample out_, out2_; + ISample in2_; + + // Phase Generator ------------------------------------------------------ + uint32 PGCalc(); + uint32 PGCalcL(); + + uint dp_; // ΔP + uint detune_; // Detune + uint detune2_; // DT2 + uint multiple_; // Multiple + uint32 pg_count_; // Phase 現在値 + uint32 pg_diff_; // Phase 差分値 + int32 pg_diff_lfo_; // Phase 差分値 >> x + + // Envelop Generator --------------------------------------------------- + void EGCalc(); + void EGStep(); + void ShiftPhase(EGPhase nextphase); + void SSGShiftPhase(int mode); + void SetEGRate(uint); + void EGUpdate(); + int FBCalc(int fb); + ISample LogToLin(uint a); + + + OpType type_; // OP の種類 (M, N...) + uint bn_; // Block/Note + int eg_level_; // EG の出力値 + int eg_level_on_next_phase_; // 次の eg_phase_ に移る値 + int eg_count_; // EG の次の変移までの時間 + int eg_count_diff_; // eg_count_ の差分 + int eg_out_; // EG+TL を合わせた出力値 + int tl_out_; // TL 分の出力値 +// int pm_depth_; // PM depth +// int am_depth_; // AM depth + int eg_rate_; + int eg_curve_count_; + int ssg_offset_; + int ssg_vector_; + int ssg_phase_; + + + uint key_scale_rate_; // key scale rate + EGPhase eg_phase_; + uint* ams_; + uint ms_; + + uint tl_; // Total Level (0-127) + uint tl_latch_; // Total Level Latch (for CSM mode) + uint ar_; // Attack Rate (0-63) + uint dr_; // Decay Rate (0-63) + uint sr_; // Sustain Rate (0-63) + uint sl_; // Sustain Level (0-127) + uint rr_; // Release Rate (0-63) + uint ks_; // Keyscale (0-3) + uint ssg_type_; // SSG-Type Envelop Control + + bool keyon_; + bool amon_; // enable Amplitude Modulation + bool param_changed_; // パラメータが更新された + bool mute_; + + // Tables --------------------------------------------------------------- + static Counter rate_table[16]; + static uint32 multable[4][16]; + + static const uint8 notetable[128]; + static const int8 dttable[256]; + static const int8 decaytable1[64][8]; + static const int decaytable2[16]; + static const int8 attacktable[64][8]; + static const int ssgenvtable[8][2][3][2]; + + static uint sinetable[1024]; + static int32 cltable[FM_CLENTS]; + + static bool tablehasmade; + static void MakeTable(); + + + + // friends -------------------------------------------------------------- + friend class Channel4; + friend void __stdcall FM_NextPhase(Operator* op); + + public: + int dbgopout_; + int dbgpgout_; + static const int32* dbgGetClTable() { return cltable; } + static const uint* dbgGetSineTable() { return sinetable; } + }; + + // 4-op Channel --------------------------------------------------------- + struct Channel4Data { + uint fb; + int buf[4]; + int algo_; + struct OperatorData op[4]; + }; + + class Channel4 + { + public: + Channel4(); + void SetChip(Chip* chip); + void SetType(OpType type); + + ISample Calc(); + ISample CalcL(); + ISample CalcN(uint noise); + ISample CalcLN(uint noise); + void SetFNum(uint fnum); + void SetFB(uint fb); + void SetKCKF(uint kc, uint kf); + void SetAlgorithm(uint algo); + int Prepare(); + void KeyControl(uint key); + void Reset(); + void SetMS(uint ms); + void Mute(bool); + void Refresh(); + + void dbgStopPG() { for (int i=0; i<4; i++) op[i].dbgStopPG(); } + + void DataSave(struct Channel4Data* data); + void DataLoad(struct Channel4Data* data); + + private: + static const uint8 fbtable[8]; + uint fb; + int buf[4]; + int* in[3]; // 各 OP の入力ポインタ + int* out[3]; // 各 OP の出力ポインタ + int* pms; + int algo_; + Chip* chip_; + + static void MakeTable(); + + static bool tablehasmade; + static int kftable[64]; + + + public: + Operator op[4]; + }; + + // Chip resource + struct ChipData { + uint ratio_; + uint aml_; + uint pml_; + int pmv_; + OpType optype_; + uint32 multable_[4][16]; + }; + + class Chip + { + public: + Chip(); + void SetRatio(uint ratio); + void SetAML(uint l); + void SetPML(uint l); + void SetPMV(int pmv) { pmv_ = pmv; } + + uint32 GetMulValue(uint dt2, uint mul) { return multable_[dt2][mul]; } + uint GetAML() { return aml_; } + uint GetPML() { return pml_; } + int GetPMV() { return pmv_; } + uint GetRatio() { return ratio_; } + + void DataSave(struct ChipData* data); + void DataLoad(struct ChipData* data); + + private: + void MakeTable(); + + uint ratio_; + uint aml_; + uint pml_; + int pmv_; + OpType optype_; + uint32 multable_[4][16]; + }; +} + +#endif // FM_GEN_H + +#endif /* SUPPORT_FMGEN */ diff --git a/sound/fmgen/fmgen_fmgeninl.h b/sound/fmgen/fmgen_fmgeninl.h old mode 100755 new mode 100644 index 3a3e2705..e2aaa0ed --- a/sound/fmgen/fmgen_fmgeninl.h +++ b/sound/fmgen/fmgen_fmgeninl.h @@ -1,273 +1,273 @@ -// --------------------------------------------------------------------------- -// FM Sound Generator -// Copyright (C) cisc 1998, 2003. -// --------------------------------------------------------------------------- -// $Id: fmgeninl.h,v 1.26 2003/06/12 13:14:36 cisc Exp $ - -#pragma once -#if defined(SUPPORT_FMGEN) - -#ifndef FM_GEN_INL_H -#define FM_GEN_INL_H - -// --------------------------------------------------------------------------- -// 定数その2 -// -#define FM_PI 3.14159265358979323846 - -#define FM_SINEPRESIS 2 // EGとサイン波の精度の差 0(低)-2(高) - - -#define FM_OPSINBITS 10 -#define FM_OPSINENTS (1 << FM_OPSINBITS) - -#define FM_EGCBITS 18 // eg の count のシフト値 -#define FM_LFOCBITS 14 - -#ifdef FM_TUNEBUILD - #define FM_PGBITS 2 - #define FM_RATIOBITS 0 -#else - #define FM_PGBITS 9 - #define FM_RATIOBITS 7 // 8-12 くらいまで? -#endif - -#define FM_EGBITS 16 - -//extern int paramcount[]; -//#define PARAMCHANGE(i) paramcount[i]++; -#define PARAMCHANGE(i) - -namespace FM -{ - -// --------------------------------------------------------------------------- -// Operator -// -// フィードバックバッファをクリア -inline void Operator::ResetFB() -{ - out_ = out2_ = 0; -} - -// キーオン -inline void Operator::KeyOn() -{ - if (!keyon_) - { - keyon_ = true; - if (eg_phase_ == off || eg_phase_ == release) - { - ssg_phase_ = -1; - ShiftPhase(attack); - EGUpdate(); - in2_ = out_ = out2_ = 0; - pg_count_ = 0; - } - } -} - -// キーオフ -inline void Operator::KeyOff() -{ - if (keyon_) - { - keyon_ = false; - ShiftPhase(release); - } -} - -// オペレータは稼働中か? -inline int Operator::IsOn() -{ - return eg_phase_ - off; -} - -// Detune (0-7) -inline void Operator::SetDT(uint dt) -{ - detune_ = dt * 0x20, param_changed_ = true; - PARAMCHANGE(4); -} - -// DT2 (0-3) -inline void Operator::SetDT2(uint dt2) -{ - detune2_ = dt2 & 3, param_changed_ = true; - PARAMCHANGE(5); -} - -// Multiple (0-15) -inline void Operator::SetMULTI(uint mul) -{ - multiple_ = mul, param_changed_ = true; - PARAMCHANGE(6); -} - -// Total Level (0-127) (0.75dB step) -inline void Operator::SetTL(uint tl, bool csm) -{ - if (!csm) - { - tl_ = tl, param_changed_ = true; - PARAMCHANGE(7); - } - tl_latch_ = tl; -} - -// Attack Rate (0-63) -inline void Operator::SetAR(uint ar) -{ - ar_ = ar; - param_changed_ = true; - PARAMCHANGE(8); -} - -// Decay Rate (0-63) -inline void Operator::SetDR(uint dr) -{ - dr_ = dr; - param_changed_ = true; - PARAMCHANGE(9); -} - -// Sustain Rate (0-63) -inline void Operator::SetSR(uint sr) -{ - sr_ = sr; - param_changed_ = true; - PARAMCHANGE(10); -} - -// Sustain Level (0-127) -inline void Operator::SetSL(uint sl) -{ - sl_ = sl; - param_changed_ = true; - PARAMCHANGE(11); -} - -// Release Rate (0-63) -inline void Operator::SetRR(uint rr) -{ - rr_ = rr; - param_changed_ = true; - PARAMCHANGE(12); -} - -// Keyscale (0-3) -inline void Operator::SetKS(uint ks) -{ - ks_ = ks; - param_changed_ = true; - PARAMCHANGE(13); -} - -// SSG-type Envelop (0-15) -inline void Operator::SetSSGEC(uint ssgec) -{ - if (ssgec & 8) - ssg_type_ = ssgec; - else - ssg_type_ = 0; -} - -inline void Operator::SetAMON(bool amon) -{ - amon_ = amon; - param_changed_ = true; - PARAMCHANGE(14); -} - -inline void Operator::Mute(bool mute) -{ - mute_ = mute; - param_changed_ = true; - PARAMCHANGE(15); -} - -inline void Operator::SetMS(uint ms) -{ - ms_ = ms; - param_changed_ = true; - PARAMCHANGE(16); -} - -// --------------------------------------------------------------------------- -// 4-op Channel - -// オペレータの種類 (LFO) を設定 -inline void Channel4::SetType(OpType type) -{ - for (int i=0; i<4; i++) - op[i].type_ = type; -} - -// セルフ・フィードバックレートの設定 (0-7) -inline void Channel4::SetFB(uint feedback) -{ - fb = fbtable[feedback]; -} - -// OPNA 系 LFO の設定 -inline void Channel4::SetMS(uint ms) -{ - op[0].SetMS(ms); - op[1].SetMS(ms); - op[2].SetMS(ms); - op[3].SetMS(ms); -} - -// チャンネル・マスク -inline void Channel4::Mute(bool m) -{ - for (int i=0; i<4; i++) - op[i].Mute(m); -} - -// 内部パラメータを再計算 -inline void Channel4::Refresh() -{ - for (int i=0; i<4; i++) - op[i].param_changed_ = true; - PARAMCHANGE(3); -} - -inline void Channel4::SetChip(Chip* chip) -{ - chip_ = chip; - for (int i=0; i<4; i++) - op[i].SetChip(chip); -} - -// --------------------------------------------------------------------------- -// -// -inline void StoreSample(Sample& dest, ISample data) -{ - if (sizeof(Sample) == 2) - dest = (Sample) Limit(dest + data, 0x7fff, -0x8000); - else - dest += data; -} - - -// --------------------------------------------------------------------------- -// AM のレベルを設定 -inline void Chip::SetAML(uint l) -{ - aml_ = l & (FM_LFOENTS - 1); -} - -// PM のレベルを設定 -inline void Chip::SetPML(uint l) -{ - pml_ = l & (FM_LFOENTS - 1); -} - - -} - -#endif // FM_GEN_INL_H - -#endif /* SUPPORT_FMGEN */ +// --------------------------------------------------------------------------- +// FM Sound Generator +// Copyright (C) cisc 1998, 2003. +// --------------------------------------------------------------------------- +// $Id: fmgeninl.h,v 1.26 2003/06/12 13:14:36 cisc Exp $ + +#pragma once +#if defined(SUPPORT_FMGEN) + +#ifndef FM_GEN_INL_H +#define FM_GEN_INL_H + +// --------------------------------------------------------------------------- +// 定数その2 +// +#define FM_PI 3.14159265358979323846 + +#define FM_SINEPRESIS 2 // EGとサイン波の精度の差 0(低)-2(高) + + +#define FM_OPSINBITS 10 +#define FM_OPSINENTS (1 << FM_OPSINBITS) + +#define FM_EGCBITS 18 // eg の count のシフト値 +#define FM_LFOCBITS 14 + +#ifdef FM_TUNEBUILD + #define FM_PGBITS 2 + #define FM_RATIOBITS 0 +#else + #define FM_PGBITS 9 + #define FM_RATIOBITS 7 // 8-12 くらいまで? +#endif + +#define FM_EGBITS 16 + +//extern int paramcount[]; +//#define PARAMCHANGE(i) paramcount[i]++; +#define PARAMCHANGE(i) + +namespace FM +{ + +// --------------------------------------------------------------------------- +// Operator +// +// フィードバックバッファをクリア +inline void Operator::ResetFB() +{ + out_ = out2_ = 0; +} + +// キーオン +inline void Operator::KeyOn() +{ + if (!keyon_) + { + keyon_ = true; + if (eg_phase_ == off || eg_phase_ == release) + { + ssg_phase_ = -1; + ShiftPhase(attack); + EGUpdate(); + in2_ = out_ = out2_ = 0; + pg_count_ = 0; + } + } +} + +// キーオフ +inline void Operator::KeyOff() +{ + if (keyon_) + { + keyon_ = false; + ShiftPhase(release); + } +} + +// オペレータは稼働中か? +inline int Operator::IsOn() +{ + return eg_phase_ - off; +} + +// Detune (0-7) +inline void Operator::SetDT(uint dt) +{ + detune_ = dt * 0x20, param_changed_ = true; + PARAMCHANGE(4); +} + +// DT2 (0-3) +inline void Operator::SetDT2(uint dt2) +{ + detune2_ = dt2 & 3, param_changed_ = true; + PARAMCHANGE(5); +} + +// Multiple (0-15) +inline void Operator::SetMULTI(uint mul) +{ + multiple_ = mul, param_changed_ = true; + PARAMCHANGE(6); +} + +// Total Level (0-127) (0.75dB step) +inline void Operator::SetTL(uint tl, bool csm) +{ + if (!csm) + { + tl_ = tl, param_changed_ = true; + PARAMCHANGE(7); + } + tl_latch_ = tl; +} + +// Attack Rate (0-63) +inline void Operator::SetAR(uint ar) +{ + ar_ = ar; + param_changed_ = true; + PARAMCHANGE(8); +} + +// Decay Rate (0-63) +inline void Operator::SetDR(uint dr) +{ + dr_ = dr; + param_changed_ = true; + PARAMCHANGE(9); +} + +// Sustain Rate (0-63) +inline void Operator::SetSR(uint sr) +{ + sr_ = sr; + param_changed_ = true; + PARAMCHANGE(10); +} + +// Sustain Level (0-127) +inline void Operator::SetSL(uint sl) +{ + sl_ = sl; + param_changed_ = true; + PARAMCHANGE(11); +} + +// Release Rate (0-63) +inline void Operator::SetRR(uint rr) +{ + rr_ = rr; + param_changed_ = true; + PARAMCHANGE(12); +} + +// Keyscale (0-3) +inline void Operator::SetKS(uint ks) +{ + ks_ = ks; + param_changed_ = true; + PARAMCHANGE(13); +} + +// SSG-type Envelop (0-15) +inline void Operator::SetSSGEC(uint ssgec) +{ + if (ssgec & 8) + ssg_type_ = ssgec; + else + ssg_type_ = 0; +} + +inline void Operator::SetAMON(bool amon) +{ + amon_ = amon; + param_changed_ = true; + PARAMCHANGE(14); +} + +inline void Operator::Mute(bool mute) +{ + mute_ = mute; + param_changed_ = true; + PARAMCHANGE(15); +} + +inline void Operator::SetMS(uint ms) +{ + ms_ = ms; + param_changed_ = true; + PARAMCHANGE(16); +} + +// --------------------------------------------------------------------------- +// 4-op Channel + +// オペレータの種類 (LFO) を設定 +inline void Channel4::SetType(OpType type) +{ + for (int i=0; i<4; i++) + op[i].type_ = type; +} + +// セルフ・フィードバックレートの設定 (0-7) +inline void Channel4::SetFB(uint feedback) +{ + fb = fbtable[feedback]; +} + +// OPNA 系 LFO の設定 +inline void Channel4::SetMS(uint ms) +{ + op[0].SetMS(ms); + op[1].SetMS(ms); + op[2].SetMS(ms); + op[3].SetMS(ms); +} + +// チャンネル・マスク +inline void Channel4::Mute(bool m) +{ + for (int i=0; i<4; i++) + op[i].Mute(m); +} + +// 内部パラメータを再計算 +inline void Channel4::Refresh() +{ + for (int i=0; i<4; i++) + op[i].param_changed_ = true; + PARAMCHANGE(3); +} + +inline void Channel4::SetChip(Chip* chip) +{ + chip_ = chip; + for (int i=0; i<4; i++) + op[i].SetChip(chip); +} + +// --------------------------------------------------------------------------- +// +// +inline void StoreSample(Sample& dest, ISample data) +{ + if (sizeof(Sample) == 2) + dest = (Sample) Limit(dest + data, 0x7fff, -0x8000); + else + dest += data; +} + + +// --------------------------------------------------------------------------- +// AM のレベルを設定 +inline void Chip::SetAML(uint l) +{ + aml_ = l & (FM_LFOENTS - 1); +} + +// PM のレベルを設定 +inline void Chip::SetPML(uint l) +{ + pml_ = l & (FM_LFOENTS - 1); +} + + +} + +#endif // FM_GEN_INL_H + +#endif /* SUPPORT_FMGEN */ diff --git a/sound/fmgen/fmgen_fmtimer.cpp b/sound/fmgen/fmgen_fmtimer.cpp old mode 100755 new mode 100644 index dbc4edea..4e09901f --- a/sound/fmgen/fmgen_fmtimer.cpp +++ b/sound/fmgen/fmgen_fmtimer.cpp @@ -1,221 +1,221 @@ -// --------------------------------------------------------------------------- -// FM sound generator common timer module -// Copyright (C) cisc 1998, 2000. -// --------------------------------------------------------------------------- -// $Id: fmtimer.cpp,v 1.1 2000/09/08 13:45:56 cisc Exp $ - -#if defined(SUPPORT_FMGEN) - -#include "fmgen_headers.h" -#include "fmgen_fmtimer.h" - -using namespace FM; - -// --------------------------------------------------------------------------- -// タイマー制御 -// -void Timer::SetTimerControl(uint data) -{ - uint tmp = regtc ^ data; - regtc = uint8(data); - - if (data & 0x10) - ResetStatus(1); - if (data & 0x20) - ResetStatus(2); - - if (tmp & 0x01) - timera_count = (data & 1) ? timera : 0; - if (tmp & 0x02) - timerb_count = (data & 2) ? timerb : 0; -} - -#if 1 - -// --------------------------------------------------------------------------- -// タイマーA 周期設定 -// -void Timer::SetTimerA(uint addr, uint data) -{ - uint tmp; - regta[addr & 1] = uint8(data); - tmp = (regta[0] << 2) + (regta[1] & 3); - timera = (1024-tmp) * timer_step; -// LOG2("Timer A = %d %d us\n", tmp, timera >> 16); -} - -// --------------------------------------------------------------------------- -// タイマーB 周期設定 -// -void Timer::SetTimerB(uint data) -{ - timerb = (256-data) * timer_step; -// LOG2("Timer B = %d %d us\n", data, timerb >> 12); -} - -// --------------------------------------------------------------------------- -// タイマー時間処理 -// -bool Timer::Count(int32 us) -{ - bool event = false; - - if (timera_count) - { - timera_count -= us << 16; - if (timera_count <= 0) - { - event = true; - TimerA(); - - while (timera_count <= 0) - timera_count += timera; - - if (regtc & 4) - SetStatus(1); - } - } - if (timerb_count) - { - timerb_count -= us << 12; - if (timerb_count <= 0) - { - event = true; - while (timerb_count <= 0) - timerb_count += timerb; - - if (regtc & 8) - SetStatus(2); - } - } - return event; -} - -// --------------------------------------------------------------------------- -// 次にタイマーが発生するまでの時間を求める -// -int32 Timer::GetNextEvent() -{ - uint32 ta = ((timera_count + 0xffff) >> 16) - 1; - uint32 tb = ((timerb_count + 0xfff) >> 12) - 1; - return (ta < tb ? ta : tb) + 1; -} - -// --------------------------------------------------------------------------- -void Timer::DataSave(struct TimerData* data) -{ - data->status = status; - data->regtc = regtc; - data->regta[0] = regta[0]; - data->regta[1] = regta[1]; - data->timera = timera; - data->timera_count = timera_count; - data->timerb = timerb; - data->timerb_count = timerb_count; - data->timer_step = timer_step; -} - -// --------------------------------------------------------------------------- -void Timer::DataLoad(struct TimerData* data) -{ - status = data->status; - regtc = data->regtc; - regta[0] = data->regta[0]; - regta[1] = data->regta[1]; - timera = data->timera; - timera_count = data->timera_count; - timerb = data->timerb; - timerb_count = data->timerb_count; - timer_step = data->timer_step; -} - -// --------------------------------------------------------------------------- -// タイマー基準値設定 -// -void Timer::SetTimerBase(uint clock) -{ - timer_step = int32(1000000. * 65536 / clock); -} - -#else - -// --------------------------------------------------------------------------- -// タイマーA 周期設定 -// -void Timer::SetTimerA(uint addr, uint data) -{ - regta[addr & 1] = uint8(data); - timera = (1024 - ((regta[0] << 2) + (regta[1] & 3))) << 16; -} - -// --------------------------------------------------------------------------- -// タイマーB 周期設定 -// -void Timer::SetTimerB(uint data) -{ - timerb = (256-data) << (16 + 4); -} - -// --------------------------------------------------------------------------- -// タイマー時間処理 -// -bool Timer::Count(int32 us) -{ - bool event = false; - - int tick = us * timer_step; - - if (timera_count) - { - timera_count -= tick; - if (timera_count <= 0) - { - event = true; - TimerA(); - - while (timera_count <= 0) - timera_count += timera; - - if (regtc & 4) - SetStatus(1); - } - } - if (timerb_count) - { - timerb_count -= tick; - if (timerb_count <= 0) - { - event = true; - while (timerb_count <= 0) - timerb_count += timerb; - - if (regtc & 8) - SetStatus(2); - } - } - return event; -} - -// --------------------------------------------------------------------------- -// 次にタイマーが発生するまでの時間を求める -// -int32 Timer::GetNextEvent() -{ - uint32 ta = timera_count - 1; - uint32 tb = timerb_count - 1; - uint32 t = (ta < tb ? ta : tb) + 1; - - return (t+timer_step-1) / timer_step; -} - -// --------------------------------------------------------------------------- -// タイマー基準値設定 -// -void Timer::SetTimerBase(uint clock) -{ - timer_step = clock * 1024 / 15625; -} - -#endif - +// --------------------------------------------------------------------------- +// FM sound generator common timer module +// Copyright (C) cisc 1998, 2000. +// --------------------------------------------------------------------------- +// $Id: fmtimer.cpp,v 1.1 2000/09/08 13:45:56 cisc Exp $ + +#if defined(SUPPORT_FMGEN) + +#include "fmgen_headers.h" +#include "fmgen_fmtimer.h" + +using namespace FM; + +// --------------------------------------------------------------------------- +// タイマー制御 +// +void Timer::SetTimerControl(uint data) +{ + uint tmp = regtc ^ data; + regtc = uint8(data); + + if (data & 0x10) + ResetStatus(1); + if (data & 0x20) + ResetStatus(2); + + if (tmp & 0x01) + timera_count = (data & 1) ? timera : 0; + if (tmp & 0x02) + timerb_count = (data & 2) ? timerb : 0; +} + +#if 1 + +// --------------------------------------------------------------------------- +// タイマーA 周期設定 +// +void Timer::SetTimerA(uint addr, uint data) +{ + uint tmp; + regta[addr & 1] = uint8(data); + tmp = (regta[0] << 2) + (regta[1] & 3); + timera = (1024-tmp) * timer_step; +// LOG2("Timer A = %d %d us\n", tmp, timera >> 16); +} + +// --------------------------------------------------------------------------- +// タイマーB 周期設定 +// +void Timer::SetTimerB(uint data) +{ + timerb = (256-data) * timer_step; +// LOG2("Timer B = %d %d us\n", data, timerb >> 12); +} + +// --------------------------------------------------------------------------- +// タイマー時間処理 +// +bool Timer::Count(int32 us) +{ + bool event = false; + + if (timera_count) + { + timera_count -= us << 16; + if (timera_count <= 0) + { + event = true; + TimerA(); + + while (timera_count <= 0) + timera_count += timera; + + if (regtc & 4) + SetStatus(1); + } + } + if (timerb_count) + { + timerb_count -= us << 12; + if (timerb_count <= 0) + { + event = true; + while (timerb_count <= 0) + timerb_count += timerb; + + if (regtc & 8) + SetStatus(2); + } + } + return event; +} + +// --------------------------------------------------------------------------- +// 次にタイマーが発生するまでの時間を求める +// +int32 Timer::GetNextEvent() +{ + uint32 ta = ((timera_count + 0xffff) >> 16) - 1; + uint32 tb = ((timerb_count + 0xfff) >> 12) - 1; + return (ta < tb ? ta : tb) + 1; +} + +// --------------------------------------------------------------------------- +void Timer::DataSave(struct TimerData* data) +{ + data->status = status; + data->regtc = regtc; + data->regta[0] = regta[0]; + data->regta[1] = regta[1]; + data->timera = timera; + data->timera_count = timera_count; + data->timerb = timerb; + data->timerb_count = timerb_count; + data->timer_step = timer_step; +} + +// --------------------------------------------------------------------------- +void Timer::DataLoad(struct TimerData* data) +{ + status = data->status; + regtc = data->regtc; + regta[0] = data->regta[0]; + regta[1] = data->regta[1]; + timera = data->timera; + timera_count = data->timera_count; + timerb = data->timerb; + timerb_count = data->timerb_count; + timer_step = data->timer_step; +} + +// --------------------------------------------------------------------------- +// タイマー基準値設定 +// +void Timer::SetTimerBase(uint clock) +{ + timer_step = int32(1000000. * 65536 / clock); +} + +#else + +// --------------------------------------------------------------------------- +// タイマーA 周期設定 +// +void Timer::SetTimerA(uint addr, uint data) +{ + regta[addr & 1] = uint8(data); + timera = (1024 - ((regta[0] << 2) + (regta[1] & 3))) << 16; +} + +// --------------------------------------------------------------------------- +// タイマーB 周期設定 +// +void Timer::SetTimerB(uint data) +{ + timerb = (256-data) << (16 + 4); +} + +// --------------------------------------------------------------------------- +// タイマー時間処理 +// +bool Timer::Count(int32 us) +{ + bool event = false; + + int tick = us * timer_step; + + if (timera_count) + { + timera_count -= tick; + if (timera_count <= 0) + { + event = true; + TimerA(); + + while (timera_count <= 0) + timera_count += timera; + + if (regtc & 4) + SetStatus(1); + } + } + if (timerb_count) + { + timerb_count -= tick; + if (timerb_count <= 0) + { + event = true; + while (timerb_count <= 0) + timerb_count += timerb; + + if (regtc & 8) + SetStatus(2); + } + } + return event; +} + +// --------------------------------------------------------------------------- +// 次にタイマーが発生するまでの時間を求める +// +int32 Timer::GetNextEvent() +{ + uint32 ta = timera_count - 1; + uint32 tb = timerb_count - 1; + uint32 t = (ta < tb ? ta : tb) + 1; + + return (t+timer_step-1) / timer_step; +} + +// --------------------------------------------------------------------------- +// タイマー基準値設定 +// +void Timer::SetTimerBase(uint clock) +{ + timer_step = clock * 1024 / 15625; +} + +#endif + #endif /* SUPPORT_FMGEN */ \ No newline at end of file diff --git a/sound/fmgen/fmgen_fmtimer.h b/sound/fmgen/fmgen_fmtimer.h old mode 100755 new mode 100644 index 9286371c..eb24d561 --- a/sound/fmgen/fmgen_fmtimer.h +++ b/sound/fmgen/fmgen_fmtimer.h @@ -1,72 +1,72 @@ -// --------------------------------------------------------------------------- -// FM sound generator common timer module -// Copyright (C) cisc 1998, 2000. -// --------------------------------------------------------------------------- -// $Id: fmtimer.h,v 1.2 2003/04/22 13:12:53 cisc Exp $ - -#pragma once -#if defined(SUPPORT_FMGEN) - -#ifndef FM_TIMER_H -#define FM_TIMER_H - -#include "fmgen_types.h" - -// --------------------------------------------------------------------------- - -namespace FM -{ - struct TimerData { - uint8 status; - uint8 regtc; - uint8 regta[2]; - int32 timera, timera_count; - int32 timerb, timerb_count; - int32 timer_step; - }; - - class Timer - { - public: - void Reset(); - bool Count(int32 us); - int32 GetNextEvent(); - - void DataSave(struct TimerData* data); - void DataLoad(struct TimerData* data); - - protected: - virtual void SetStatus(uint bit) = 0; - virtual void ResetStatus(uint bit) = 0; - - void SetTimerBase(uint clock); - void SetTimerA(uint addr, uint data); - void SetTimerB(uint data); - void SetTimerControl(uint data); - - uint8 status; - uint8 regtc; - - private: - virtual void TimerA() {} - uint8 regta[2]; - - int32 timera, timera_count; - int32 timerb, timerb_count; - int32 timer_step; - }; - -// --------------------------------------------------------------------------- -// 初期化 -// -inline void Timer::Reset() -{ - timera_count = 0; - timerb_count = 0; -} - -} // namespace FM - -#endif // FM_TIMER_H - -#endif /* SUPPORT_FMGEN */ +// --------------------------------------------------------------------------- +// FM sound generator common timer module +// Copyright (C) cisc 1998, 2000. +// --------------------------------------------------------------------------- +// $Id: fmtimer.h,v 1.2 2003/04/22 13:12:53 cisc Exp $ + +#pragma once +#if defined(SUPPORT_FMGEN) + +#ifndef FM_TIMER_H +#define FM_TIMER_H + +#include "fmgen_types.h" + +// --------------------------------------------------------------------------- + +namespace FM +{ + struct TimerData { + uint8 status; + uint8 regtc; + uint8 regta[2]; + int32 timera, timera_count; + int32 timerb, timerb_count; + int32 timer_step; + }; + + class Timer + { + public: + void Reset(); + bool Count(int32 us); + int32 GetNextEvent(); + + void DataSave(struct TimerData* data); + void DataLoad(struct TimerData* data); + + protected: + virtual void SetStatus(uint bit) = 0; + virtual void ResetStatus(uint bit) = 0; + + void SetTimerBase(uint clock); + void SetTimerA(uint addr, uint data); + void SetTimerB(uint data); + void SetTimerControl(uint data); + + uint8 status; + uint8 regtc; + + private: + virtual void TimerA() {} + uint8 regta[2]; + + int32 timera, timera_count; + int32 timerb, timerb_count; + int32 timer_step; + }; + +// --------------------------------------------------------------------------- +// 初期化 +// +inline void Timer::Reset() +{ + timera_count = 0; + timerb_count = 0; +} + +} // namespace FM + +#endif // FM_TIMER_H + +#endif /* SUPPORT_FMGEN */ diff --git a/sound/fmgen/fmgen_headers.h b/sound/fmgen/fmgen_headers.h old mode 100755 new mode 100644 index 8934bfeb..5abfb212 --- a/sound/fmgen/fmgen_headers.h +++ b/sound/fmgen/fmgen_headers.h @@ -1,30 +1,30 @@ -#pragma once -#if defined(SUPPORT_FMGEN) - -#ifndef WIN_HEADERS_H -#define WIN_HEADERS_H - -#define STRICT -#define WIN32_LEAN_AND_MEAN - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _MSC_VER - #undef max - #define max _MAX - #undef min - #define min _MIN -#endif - -#ifdef __cplusplus -} -#endif - -#endif // WIN_HEADERS_H - -#endif /* SUPPORT_FMGEN */ +#pragma once +#if defined(SUPPORT_FMGEN) + +#ifndef WIN_HEADERS_H +#define WIN_HEADERS_H + +#define STRICT +#define WIN32_LEAN_AND_MEAN + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _MSC_VER + #undef max + #define max _MAX + #undef min + #define min _MIN +#endif + +#ifdef __cplusplus +} +#endif + +#endif // WIN_HEADERS_H + +#endif /* SUPPORT_FMGEN */ diff --git a/sound/fmgen/fmgen_misc.h b/sound/fmgen/fmgen_misc.h old mode 100755 new mode 100644 index 475555c4..0b2ac0f0 --- a/sound/fmgen/fmgen_misc.h +++ b/sound/fmgen/fmgen_misc.h @@ -1,74 +1,74 @@ -// --------------------------------------------------------------------------- -// misc.h -// Copyright (C) cisc 1998, 1999. -// --------------------------------------------------------------------------- -// $Id: misc.h,v 1.5 2002/05/31 09:45:20 cisc Exp $ - -#pragma once -#if defined(SUPPORT_FMGEN) - -#ifndef MISC_H -#define MISC_H - -inline int Max(int x, int y) { return (x > y) ? x : y; } -inline int Min(int x, int y) { return (x < y) ? x : y; } -inline int Abs(int x) { return x >= 0 ? x : -x; } - -inline int Limit(int v, int max, int min) -{ - return v > max ? max : (v < min ? min : v); -} - -inline unsigned int BSwap(unsigned int a) -{ - return (a >> 24) | ((a >> 8) & 0xff00) | ((a << 8) & 0xff0000) | (a << 24); -} - -inline unsigned int NtoBCD(unsigned int a) -{ - return ((a / 10) << 4) + (a % 10); -} - -inline unsigned int BCDtoN(unsigned int v) -{ - return (v >> 4) * 10 + (v & 15); -} - - -template -inline T gcd(T x, T y) -{ - T t; - while (y) - { - t = x % y; - x = y; - y = t; - } - return x; -} - - -template -T bessel0(T x) -{ - T p, r, s; - - r = 1.0; - s = 1.0; - p = (x / 2.0) / s; - - while (p > 1.0E-10) - { - r += p * p; - s += 1.0; - p *= (x / 2.0) / s; - } - return r; -} - - -#endif // MISC_H - -#endif /* SUPPORT_FMGEN */ - +// --------------------------------------------------------------------------- +// misc.h +// Copyright (C) cisc 1998, 1999. +// --------------------------------------------------------------------------- +// $Id: misc.h,v 1.5 2002/05/31 09:45:20 cisc Exp $ + +#pragma once +#if defined(SUPPORT_FMGEN) + +#ifndef MISC_H +#define MISC_H + +inline int Max(int x, int y) { return (x > y) ? x : y; } +inline int Min(int x, int y) { return (x < y) ? x : y; } +inline int Abs(int x) { return x >= 0 ? x : -x; } + +inline int Limit(int v, int max, int min) +{ + return v > max ? max : (v < min ? min : v); +} + +inline unsigned int BSwap(unsigned int a) +{ + return (a >> 24) | ((a >> 8) & 0xff00) | ((a << 8) & 0xff0000) | (a << 24); +} + +inline unsigned int NtoBCD(unsigned int a) +{ + return ((a / 10) << 4) + (a % 10); +} + +inline unsigned int BCDtoN(unsigned int v) +{ + return (v >> 4) * 10 + (v & 15); +} + + +template +inline T gcd(T x, T y) +{ + T t; + while (y) + { + t = x % y; + x = y; + y = t; + } + return x; +} + + +template +T bessel0(T x) +{ + T p, r, s; + + r = 1.0; + s = 1.0; + p = (x / 2.0) / s; + + while (p > 1.0E-10) + { + r += p * p; + s += 1.0; + p *= (x / 2.0) / s; + } + return r; +} + + +#endif // MISC_H + +#endif /* SUPPORT_FMGEN */ + diff --git a/sound/fmgen/fmgen_opm.cpp b/sound/fmgen/fmgen_opm.cpp old mode 100755 new mode 100644 index 92deb633..788b0ba6 --- a/sound/fmgen/fmgen_opm.cpp +++ b/sound/fmgen/fmgen_opm.cpp @@ -1,568 +1,568 @@ -// --------------------------------------------------------------------------- -// OPM interface -// Copyright (C) cisc 1998, 2003. -// --------------------------------------------------------------------------- -// $Id: opm.cpp,v 1.26 2003/08/25 13:53:08 cisc Exp $ - -#if defined(SUPPORT_FMGEN) - -#include "fmgen_headers.h" -#include "fmgen_misc.h" -#include "fmgen_opm.h" -#include "fmgen_fmgeninl.h" - -//#define LOGNAME "opm" - -namespace FM -{ - -int OPM::amtable[4][OPM_LFOENTS] = { -1, }; -int OPM::pmtable[4][OPM_LFOENTS]; - -// --------------------------------------------------------------------------- -// 構築 -// -OPM::OPM() -{ - lfo_count_ = 0; - lfo_count_prev_ = ~0; - BuildLFOTable(); - for (int i=0; i<8; i++) - { - ch[i].SetChip(&chip); - ch[i].SetType(typeM); - } -} - -// --------------------------------------------------------------------------- -// 初期化 -// -bool OPM::Init(uint c, uint rf, bool ip) -{ - if (!SetRate(c, rf, ip)) - return false; - - Reset(); - - SetVolume(0); - SetChannelMask(0); - return true; -} - -// --------------------------------------------------------------------------- -// 再設定 -// -bool OPM::SetRate(uint c, uint r, bool) -{ - clock = c; - pcmrate = r; - rate = r; - - RebuildTimeTable(); - - return true; -} - -// --------------------------------------------------------------------------- -// チャンネルマスクの設定 -// -void OPM::SetChannelMask(uint mask) -{ - for (int i=0; i<8; i++) - ch[i].Mute(!!(mask & (1 << i))); -} - -// --------------------------------------------------------------------------- -// リセット -// -void OPM::Reset() -{ - int i; - for (i=0x0; i<0x100; i++) SetReg(i, 0); - SetReg(0x19, 0x80); - Timer::Reset(); - - status = 0; - noise = 12345; - noisecount = 0; - - for (i=0; i<8; i++) - ch[i].Reset(); -} - -// --------------------------------------------------------------------------- -// 設定に依存するテーブルの作成 -// -void OPM::RebuildTimeTable() -{ - uint fmclock = clock / 64; - - assert(fmclock < (0x80000000 >> FM_RATIOBITS)); - rateratio = ((fmclock << FM_RATIOBITS) + rate/2) / rate; - SetTimerBase(fmclock); - -// FM::MakeTimeTable(rateratio); - chip.SetRatio(rateratio); - -// lfo_diff_ = - - -// lfodcount = (16 + (lfofreq & 15)) << (lfofreq >> 4); -// lfodcount = lfodcount * rateratio >> FM_RATIOBITS; -} - -// --------------------------------------------------------------------------- -// タイマー A 発生時イベント (CSM) -// -void OPM::TimerA() -{ - if (regtc & 0x80) - { - for (int i=0; i<8; i++) - { - ch[i].KeyControl(0); - ch[i].KeyControl(0xf); - } - } -} - -// --------------------------------------------------------------------------- -// 音量設定 -// -void OPM::SetVolume(int db) -{ - db = Min(db, 20); - if (db > -192) - fmvolume = int(16384.0 * pow((double)10, (double)db / 40.0)); - else - fmvolume = 0; -} - -// --------------------------------------------------------------------------- -// ステータスフラグ設定 -// -void OPM::SetStatus(uint bits) -{ - if (!(status & bits)) - { - status |= bits; - Intr(true); - } -} - -// --------------------------------------------------------------------------- -// ステータスフラグ解除 -// -void OPM::ResetStatus(uint bits) -{ - if (status & bits) - { - status &= ~bits; - if (!status) - Intr(false); - } -} - -// --------------------------------------------------------------------------- -// レジスタアレイにデータを設定 -// -void OPM::SetReg(uint addr, uint data) -{ - if (addr >= 0x100) - return; - - int c = addr & 7; - switch (addr & 0xff) - { - case 0x01: // TEST (lfo restart) - if (data & 2) - { - lfo_count_ = 0; - lfo_count_prev_ = ~0; - } - reg01 = data; - break; - - case 0x08: // KEYON - if (!(regtc & 0x80)) - ch[data & 7].KeyControl(data >> 3); - else - { - c = data & 7; - if (!(data & 0x08)) ch[c].op[0].KeyOff(); - if (!(data & 0x10)) ch[c].op[1].KeyOff(); - if (!(data & 0x20)) ch[c].op[2].KeyOff(); - if (!(data & 0x40)) ch[c].op[3].KeyOff(); - } - break; - - case 0x10: case 0x11: // CLKA1, CLKA2 - SetTimerA(addr, data); - break; - - case 0x12: // CLKB - SetTimerB(data); - break; - - case 0x14: // CSM, TIMER - SetTimerControl(data); - break; - - case 0x18: // LFRQ(lfo freq) - lfofreq = data; - - assert(16-4-FM_RATIOBITS >= 0); - lfo_count_diff_ = - rateratio - * ((16 + (lfofreq & 15)) << (16 - 4 - FM_RATIOBITS)) - / (1 << (15 - (lfofreq >> 4))); - - break; - - case 0x19: // PMD/AMD - (data & 0x80 ? pmd : amd) = data & 0x7f; - break; - - case 0x1b: // CT, W(lfo waveform) - lfowaveform = data & 3; - break; - - // RL, FB, Connect - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - ch[c].SetFB((data >> 3) & 7); - ch[c].SetAlgorithm(data & 7); - pan[c] = (data >> 6) & 3; - break; - - // KC - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - kc[c] = data; - ch[c].SetKCKF(kc[c], kf[c]); - break; - - // KF - case 0x30: case 0x31: case 0x32: case 0x33: - case 0x34: case 0x35: case 0x36: case 0x37: - kf[c] = data >> 2; - ch[c].SetKCKF(kc[c], kf[c]); - break; - - // PMS, AMS - case 0x38: case 0x39: case 0x3a: case 0x3b: - case 0x3c: case 0x3d: case 0x3e: case 0x3f: - ch[c].SetMS((data << 4) | (data >> 4)); - break; - - case 0x0f: // NE/NFRQ (noise) - noisedelta = data; - noisecount = 0; - break; - - default: - if (addr >= 0x40) - OPM::SetParameter(addr, data); - break; - } -} - - -// --------------------------------------------------------------------------- -// パラメータセット -// -void OPM::SetParameter(uint addr, uint data) -{ - const static uint8 sltable[16] = - { - 0, 4, 8, 12, 16, 20, 24, 28, - 32, 36, 40, 44, 48, 52, 56, 124, - }; - const static uint8 slottable[4] = { 0, 2, 1, 3 }; - - uint slot = slottable[(addr >> 3) & 3]; - Operator* op = &ch[addr & 7].op[slot]; - - switch ((addr >> 5) & 7) - { - case 2: // 40-5F DT1/MULTI - op->SetDT((data >> 4) & 0x07); - op->SetMULTI(data & 0x0f); - break; - - case 3: // 60-7F TL - op->SetTL(data & 0x7f, (regtc & 0x80) != 0); - break; - - case 4: // 80-9F KS/AR - op->SetKS((data >> 6) & 3); - op->SetAR((data & 0x1f) * 2); - break; - - case 5: // A0-BF DR/AMON(D1R/AMS-EN) - op->SetDR((data & 0x1f) * 2); - op->SetAMON((data & 0x80) != 0); - break; - - case 6: // C0-DF SR(D2R), DT2 - op->SetSR((data & 0x1f) * 2); - op->SetDT2((data >> 6) & 3); - break; - - case 7: // E0-FF SL(D1L)/RR - op->SetSL(sltable[(data >> 4) & 15]); - op->SetRR((data & 0x0f) * 4 + 2); - break; - } -} - -// --------------------------------------------------------------------------- -// -// -void OPM::BuildLFOTable() -{ - if (amtable[0][0] != -1) - return; - - for (int type=0; type<4; type++) - { - int r = 0; - for (int c=0; c> 15) & 0x1fe; -// fprintf(stderr, "%.8x %.2x\n", lfo_count_, c); - chip.SetPML(pmtable[lfowaveform][c] * pmd / 128 + 0x80); - chip.SetAML(amtable[lfowaveform][c] * amd / 128); - } - } - else - { - if ((lfo_count_ ^ lfo_count_prev_) & ~((1 << 17) - 1)) - { - int c = (rand() / 17) & 0xff; - chip.SetPML((c - 0x80) * pmd / 128 + 0x80); - chip.SetAML(c * amd / 128); - } - } - lfo_count_prev_ = lfo_count_; - lfo_step_++; - if ((lfo_step_ & 7) == 0) - { - lfo_count_ += lfo_count_diff_; - } -} - -inline uint OPM::Noise() -{ - noisecount += 2 * rateratio; - if (noisecount >= (32 << FM_RATIOBITS)) - { - int n = 32 - (noisedelta & 0x1f); - if (n == 1) - n = 2; - - noisecount = noisecount - (n << FM_RATIOBITS); - if ((noisedelta & 0x1f) == 0x1f) - noisecount -= FM_RATIOBITS; - noise = (noise >> 1) ^ (noise & 1 ? 0x8408 : 0); - } - return noise; -} - -// --------------------------------------------------------------------------- -// 合成の一部 -// -inline void OPM::MixSub(int activech, ISample** idest) -{ - if (activech & 0x4000) (*idest[0] = ch[0].Calc()); - if (activech & 0x1000) (*idest[1] += ch[1].Calc()); - if (activech & 0x0400) (*idest[2] += ch[2].Calc()); - if (activech & 0x0100) (*idest[3] += ch[3].Calc()); - if (activech & 0x0040) (*idest[4] += ch[4].Calc()); - if (activech & 0x0010) (*idest[5] += ch[5].Calc()); - if (activech & 0x0004) (*idest[6] += ch[6].Calc()); - if (activech & 0x0001) - { - if (noisedelta & 0x80) - *idest[7] += ch[7].CalcN(Noise()); - else - *idest[7] += ch[7].Calc(); - } -} - -inline void OPM::MixSubL(int activech, ISample** idest) -{ - if (activech & 0x4000) (*idest[0] = ch[0].CalcL()); - if (activech & 0x1000) (*idest[1] += ch[1].CalcL()); - if (activech & 0x0400) (*idest[2] += ch[2].CalcL()); - if (activech & 0x0100) (*idest[3] += ch[3].CalcL()); - if (activech & 0x0040) (*idest[4] += ch[4].CalcL()); - if (activech & 0x0010) (*idest[5] += ch[5].CalcL()); - if (activech & 0x0004) (*idest[6] += ch[6].CalcL()); - if (activech & 0x0001) - { - if (noisedelta & 0x80) - *idest[7] += ch[7].CalcLN(Noise()); - else - *idest[7] += ch[7].CalcL(); - } -} - - -// --------------------------------------------------------------------------- -// 合成 (stereo) -// -void OPM::Mix(Sample* buffer, int nsamples) -{ -#define IStoSample(s) ((Limit(s, 0xffff, -0x10000) * fmvolume) >> 14) -//#define IStoSample(s) ((s * fmvolume) >> 14) - - // odd bits - active, even bits - lfo - uint activech=0; - for (int i=0; i<8; i++) - activech = (activech << 2) | ch[i].Prepare(); - - if (activech & 0x5555) - { - // LFO 波形初期化ビット = 1 ならば LFO はかからない? - if (reg01 & 0x02) - activech &= 0x5555; - - // Mix - ISample ibuf[8]; - ISample* idest[8]; - idest[0] = &ibuf[pan[0]]; - idest[1] = &ibuf[pan[1]]; - idest[2] = &ibuf[pan[2]]; - idest[3] = &ibuf[pan[3]]; - idest[4] = &ibuf[pan[4]]; - idest[5] = &ibuf[pan[5]]; - idest[6] = &ibuf[pan[6]]; - idest[7] = &ibuf[pan[7]]; - - Sample* limit = buffer + nsamples * 2; - for (Sample* dest = buffer; dest < limit; dest+=2) - { - ibuf[1] = ibuf[2] = ibuf[3] = 0; - if (activech & 0xaaaa) - LFO(), MixSubL(activech, idest); - else - LFO(), MixSub(activech, idest); - - StoreSample(dest[0], IStoSample(ibuf[1] + ibuf[3])); - StoreSample(dest[1], IStoSample(ibuf[2] + ibuf[3])); - } - } -#undef IStoSample -} - -void OPM::DataSave(struct OPMData* data) { - Timer::DataSave(&data->timer); - data->fmvolume = fmvolume; - data->clock = clock; - data->rate = rate; - data->pcmrate = pcmrate; - data->pmd = pmd; - data->amd = amd; - data->lfocount = lfocount; - data->lfodcount = lfodcount; - data->lfo_count_ = lfo_count_; - data->lfo_count_diff_ = lfo_count_diff_; - data->lfo_step_ = lfo_step_; - data->lfo_count_prev_ = lfo_count_prev_; - data->lfowaveform = lfowaveform; - data->rateratio = rateratio; - data->noise = noise; - data->noisecount = noisecount; - data->noisedelta = noisedelta; - data->interpolation = interpolation; - data->lfofreq = lfofreq; - data->status = status; - data->reg01 = reg01; - memcpy(data->kc, kc, 8); - memcpy(data->kf, kf, 8); - memcpy(data->pan, pan, 8); - for(int i = 0; i < 8; i++) { - ch[i].DataSave(&data->ch[i]); - } - chip.DataSave(&data->chip); -} - -void OPM::DataLoad(struct OPMData* data) { - Timer::DataLoad(&data->timer); - fmvolume = data->fmvolume; - clock = data->clock; - rate = data->rate; - pcmrate = data->pcmrate; - pmd = data->pmd; - amd = data->amd; - lfocount = data->lfocount; - lfodcount = data->lfodcount; - lfo_count_ = data->lfo_count_; - lfo_count_diff_ = data->lfo_count_diff_; - lfo_step_ = data->lfo_step_; - lfo_count_prev_ = data->lfo_count_prev_; - lfowaveform = data->lfowaveform; - rateratio = data->rateratio; - noise = data->noise; - noisecount = data->noisecount; - noisedelta = data->noisedelta; - interpolation = data->interpolation; - lfofreq = data->lfofreq; - status = data->status; - reg01 = data->reg01; - memcpy(kc, data->kc, 8); - memcpy(kf, data->kf, 8); - memcpy(pan, data->pan, 8); - for(int i = 0; i < 8; i++) { - ch[i].DataLoad(&data->ch[i]); - } - chip.DataLoad(&data->chip); -} - -} // namespace FM - -#endif /* SUPPORT_FMGEN */ +// --------------------------------------------------------------------------- +// OPM interface +// Copyright (C) cisc 1998, 2003. +// --------------------------------------------------------------------------- +// $Id: opm.cpp,v 1.26 2003/08/25 13:53:08 cisc Exp $ + +#if defined(SUPPORT_FMGEN) + +#include "fmgen_headers.h" +#include "fmgen_misc.h" +#include "fmgen_opm.h" +#include "fmgen_fmgeninl.h" + +//#define LOGNAME "opm" + +namespace FM +{ + +int OPM::amtable[4][OPM_LFOENTS] = { -1, }; +int OPM::pmtable[4][OPM_LFOENTS]; + +// --------------------------------------------------------------------------- +// 構築 +// +OPM::OPM() +{ + lfo_count_ = 0; + lfo_count_prev_ = ~0; + BuildLFOTable(); + for (int i=0; i<8; i++) + { + ch[i].SetChip(&chip); + ch[i].SetType(typeM); + } +} + +// --------------------------------------------------------------------------- +// 初期化 +// +bool OPM::Init(uint c, uint rf, bool ip) +{ + if (!SetRate(c, rf, ip)) + return false; + + Reset(); + + SetVolume(0); + SetChannelMask(0); + return true; +} + +// --------------------------------------------------------------------------- +// 再設定 +// +bool OPM::SetRate(uint c, uint r, bool) +{ + clock = c; + pcmrate = r; + rate = r; + + RebuildTimeTable(); + + return true; +} + +// --------------------------------------------------------------------------- +// チャンネルマスクの設定 +// +void OPM::SetChannelMask(uint mask) +{ + for (int i=0; i<8; i++) + ch[i].Mute(!!(mask & (1 << i))); +} + +// --------------------------------------------------------------------------- +// リセット +// +void OPM::Reset() +{ + int i; + for (i=0x0; i<0x100; i++) SetReg(i, 0); + SetReg(0x19, 0x80); + Timer::Reset(); + + status = 0; + noise = 12345; + noisecount = 0; + + for (i=0; i<8; i++) + ch[i].Reset(); +} + +// --------------------------------------------------------------------------- +// 設定に依存するテーブルの作成 +// +void OPM::RebuildTimeTable() +{ + uint fmclock = clock / 64; + + assert(fmclock < (0x80000000 >> FM_RATIOBITS)); + rateratio = ((fmclock << FM_RATIOBITS) + rate/2) / rate; + SetTimerBase(fmclock); + +// FM::MakeTimeTable(rateratio); + chip.SetRatio(rateratio); + +// lfo_diff_ = + + +// lfodcount = (16 + (lfofreq & 15)) << (lfofreq >> 4); +// lfodcount = lfodcount * rateratio >> FM_RATIOBITS; +} + +// --------------------------------------------------------------------------- +// タイマー A 発生時イベント (CSM) +// +void OPM::TimerA() +{ + if (regtc & 0x80) + { + for (int i=0; i<8; i++) + { + ch[i].KeyControl(0); + ch[i].KeyControl(0xf); + } + } +} + +// --------------------------------------------------------------------------- +// 音量設定 +// +void OPM::SetVolume(int db) +{ + db = Min(db, 20); + if (db > -192) + fmvolume = int(16384.0 * pow((double)10, (double)db / 40.0)); + else + fmvolume = 0; +} + +// --------------------------------------------------------------------------- +// ステータスフラグ設定 +// +void OPM::SetStatus(uint bits) +{ + if (!(status & bits)) + { + status |= bits; + Intr(true); + } +} + +// --------------------------------------------------------------------------- +// ステータスフラグ解除 +// +void OPM::ResetStatus(uint bits) +{ + if (status & bits) + { + status &= ~bits; + if (!status) + Intr(false); + } +} + +// --------------------------------------------------------------------------- +// レジスタアレイにデータを設定 +// +void OPM::SetReg(uint addr, uint data) +{ + if (addr >= 0x100) + return; + + int c = addr & 7; + switch (addr & 0xff) + { + case 0x01: // TEST (lfo restart) + if (data & 2) + { + lfo_count_ = 0; + lfo_count_prev_ = ~0; + } + reg01 = data; + break; + + case 0x08: // KEYON + if (!(regtc & 0x80)) + ch[data & 7].KeyControl(data >> 3); + else + { + c = data & 7; + if (!(data & 0x08)) ch[c].op[0].KeyOff(); + if (!(data & 0x10)) ch[c].op[1].KeyOff(); + if (!(data & 0x20)) ch[c].op[2].KeyOff(); + if (!(data & 0x40)) ch[c].op[3].KeyOff(); + } + break; + + case 0x10: case 0x11: // CLKA1, CLKA2 + SetTimerA(addr, data); + break; + + case 0x12: // CLKB + SetTimerB(data); + break; + + case 0x14: // CSM, TIMER + SetTimerControl(data); + break; + + case 0x18: // LFRQ(lfo freq) + lfofreq = data; + + assert(16-4-FM_RATIOBITS >= 0); + lfo_count_diff_ = + rateratio + * ((16 + (lfofreq & 15)) << (16 - 4 - FM_RATIOBITS)) + / (1 << (15 - (lfofreq >> 4))); + + break; + + case 0x19: // PMD/AMD + (data & 0x80 ? pmd : amd) = data & 0x7f; + break; + + case 0x1b: // CT, W(lfo waveform) + lfowaveform = data & 3; + break; + + // RL, FB, Connect + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + ch[c].SetFB((data >> 3) & 7); + ch[c].SetAlgorithm(data & 7); + pan[c] = (data >> 6) & 3; + break; + + // KC + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + kc[c] = data; + ch[c].SetKCKF(kc[c], kf[c]); + break; + + // KF + case 0x30: case 0x31: case 0x32: case 0x33: + case 0x34: case 0x35: case 0x36: case 0x37: + kf[c] = data >> 2; + ch[c].SetKCKF(kc[c], kf[c]); + break; + + // PMS, AMS + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + ch[c].SetMS((data << 4) | (data >> 4)); + break; + + case 0x0f: // NE/NFRQ (noise) + noisedelta = data; + noisecount = 0; + break; + + default: + if (addr >= 0x40) + OPM::SetParameter(addr, data); + break; + } +} + + +// --------------------------------------------------------------------------- +// パラメータセット +// +void OPM::SetParameter(uint addr, uint data) +{ + const static uint8 sltable[16] = + { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 124, + }; + const static uint8 slottable[4] = { 0, 2, 1, 3 }; + + uint slot = slottable[(addr >> 3) & 3]; + Operator* op = &ch[addr & 7].op[slot]; + + switch ((addr >> 5) & 7) + { + case 2: // 40-5F DT1/MULTI + op->SetDT((data >> 4) & 0x07); + op->SetMULTI(data & 0x0f); + break; + + case 3: // 60-7F TL + op->SetTL(data & 0x7f, (regtc & 0x80) != 0); + break; + + case 4: // 80-9F KS/AR + op->SetKS((data >> 6) & 3); + op->SetAR((data & 0x1f) * 2); + break; + + case 5: // A0-BF DR/AMON(D1R/AMS-EN) + op->SetDR((data & 0x1f) * 2); + op->SetAMON((data & 0x80) != 0); + break; + + case 6: // C0-DF SR(D2R), DT2 + op->SetSR((data & 0x1f) * 2); + op->SetDT2((data >> 6) & 3); + break; + + case 7: // E0-FF SL(D1L)/RR + op->SetSL(sltable[(data >> 4) & 15]); + op->SetRR((data & 0x0f) * 4 + 2); + break; + } +} + +// --------------------------------------------------------------------------- +// +// +void OPM::BuildLFOTable() +{ + if (amtable[0][0] != -1) + return; + + for (int type=0; type<4; type++) + { + int r = 0; + for (int c=0; c> 15) & 0x1fe; +// fprintf(stderr, "%.8x %.2x\n", lfo_count_, c); + chip.SetPML(pmtable[lfowaveform][c] * pmd / 128 + 0x80); + chip.SetAML(amtable[lfowaveform][c] * amd / 128); + } + } + else + { + if ((lfo_count_ ^ lfo_count_prev_) & ~((1 << 17) - 1)) + { + int c = (rand() / 17) & 0xff; + chip.SetPML((c - 0x80) * pmd / 128 + 0x80); + chip.SetAML(c * amd / 128); + } + } + lfo_count_prev_ = lfo_count_; + lfo_step_++; + if ((lfo_step_ & 7) == 0) + { + lfo_count_ += lfo_count_diff_; + } +} + +inline uint OPM::Noise() +{ + noisecount += 2 * rateratio; + if (noisecount >= (32 << FM_RATIOBITS)) + { + int n = 32 - (noisedelta & 0x1f); + if (n == 1) + n = 2; + + noisecount = noisecount - (n << FM_RATIOBITS); + if ((noisedelta & 0x1f) == 0x1f) + noisecount -= FM_RATIOBITS; + noise = (noise >> 1) ^ (noise & 1 ? 0x8408 : 0); + } + return noise; +} + +// --------------------------------------------------------------------------- +// 合成の一部 +// +inline void OPM::MixSub(int activech, ISample** idest) +{ + if (activech & 0x4000) (*idest[0] = ch[0].Calc()); + if (activech & 0x1000) (*idest[1] += ch[1].Calc()); + if (activech & 0x0400) (*idest[2] += ch[2].Calc()); + if (activech & 0x0100) (*idest[3] += ch[3].Calc()); + if (activech & 0x0040) (*idest[4] += ch[4].Calc()); + if (activech & 0x0010) (*idest[5] += ch[5].Calc()); + if (activech & 0x0004) (*idest[6] += ch[6].Calc()); + if (activech & 0x0001) + { + if (noisedelta & 0x80) + *idest[7] += ch[7].CalcN(Noise()); + else + *idest[7] += ch[7].Calc(); + } +} + +inline void OPM::MixSubL(int activech, ISample** idest) +{ + if (activech & 0x4000) (*idest[0] = ch[0].CalcL()); + if (activech & 0x1000) (*idest[1] += ch[1].CalcL()); + if (activech & 0x0400) (*idest[2] += ch[2].CalcL()); + if (activech & 0x0100) (*idest[3] += ch[3].CalcL()); + if (activech & 0x0040) (*idest[4] += ch[4].CalcL()); + if (activech & 0x0010) (*idest[5] += ch[5].CalcL()); + if (activech & 0x0004) (*idest[6] += ch[6].CalcL()); + if (activech & 0x0001) + { + if (noisedelta & 0x80) + *idest[7] += ch[7].CalcLN(Noise()); + else + *idest[7] += ch[7].CalcL(); + } +} + + +// --------------------------------------------------------------------------- +// 合成 (stereo) +// +void OPM::Mix(Sample* buffer, int nsamples) +{ +#define IStoSample(s) ((Limit(s, 0xffff, -0x10000) * fmvolume) >> 14) +//#define IStoSample(s) ((s * fmvolume) >> 14) + + // odd bits - active, even bits - lfo + uint activech=0; + for (int i=0; i<8; i++) + activech = (activech << 2) | ch[i].Prepare(); + + if (activech & 0x5555) + { + // LFO 波形初期化ビット = 1 ならば LFO はかからない? + if (reg01 & 0x02) + activech &= 0x5555; + + // Mix + ISample ibuf[8]; + ISample* idest[8]; + idest[0] = &ibuf[pan[0]]; + idest[1] = &ibuf[pan[1]]; + idest[2] = &ibuf[pan[2]]; + idest[3] = &ibuf[pan[3]]; + idest[4] = &ibuf[pan[4]]; + idest[5] = &ibuf[pan[5]]; + idest[6] = &ibuf[pan[6]]; + idest[7] = &ibuf[pan[7]]; + + Sample* limit = buffer + nsamples * 2; + for (Sample* dest = buffer; dest < limit; dest+=2) + { + ibuf[1] = ibuf[2] = ibuf[3] = 0; + if (activech & 0xaaaa) + LFO(), MixSubL(activech, idest); + else + LFO(), MixSub(activech, idest); + + StoreSample(dest[0], IStoSample(ibuf[1] + ibuf[3])); + StoreSample(dest[1], IStoSample(ibuf[2] + ibuf[3])); + } + } +#undef IStoSample +} + +void OPM::DataSave(struct OPMData* data) { + Timer::DataSave(&data->timer); + data->fmvolume = fmvolume; + data->clock = clock; + data->rate = rate; + data->pcmrate = pcmrate; + data->pmd = pmd; + data->amd = amd; + data->lfocount = lfocount; + data->lfodcount = lfodcount; + data->lfo_count_ = lfo_count_; + data->lfo_count_diff_ = lfo_count_diff_; + data->lfo_step_ = lfo_step_; + data->lfo_count_prev_ = lfo_count_prev_; + data->lfowaveform = lfowaveform; + data->rateratio = rateratio; + data->noise = noise; + data->noisecount = noisecount; + data->noisedelta = noisedelta; + data->interpolation = interpolation; + data->lfofreq = lfofreq; + data->status = status; + data->reg01 = reg01; + memcpy(data->kc, kc, 8); + memcpy(data->kf, kf, 8); + memcpy(data->pan, pan, 8); + for(int i = 0; i < 8; i++) { + ch[i].DataSave(&data->ch[i]); + } + chip.DataSave(&data->chip); +} + +void OPM::DataLoad(struct OPMData* data) { + Timer::DataLoad(&data->timer); + fmvolume = data->fmvolume; + clock = data->clock; + rate = data->rate; + pcmrate = data->pcmrate; + pmd = data->pmd; + amd = data->amd; + lfocount = data->lfocount; + lfodcount = data->lfodcount; + lfo_count_ = data->lfo_count_; + lfo_count_diff_ = data->lfo_count_diff_; + lfo_step_ = data->lfo_step_; + lfo_count_prev_ = data->lfo_count_prev_; + lfowaveform = data->lfowaveform; + rateratio = data->rateratio; + noise = data->noise; + noisecount = data->noisecount; + noisedelta = data->noisedelta; + interpolation = data->interpolation; + lfofreq = data->lfofreq; + status = data->status; + reg01 = data->reg01; + memcpy(kc, data->kc, 8); + memcpy(kf, data->kf, 8); + memcpy(pan, data->pan, 8); + for(int i = 0; i < 8; i++) { + ch[i].DataLoad(&data->ch[i]); + } + chip.DataLoad(&data->chip); +} + +} // namespace FM + +#endif /* SUPPORT_FMGEN */ diff --git a/sound/fmgen/fmgen_opm.h b/sound/fmgen/fmgen_opm.h old mode 100755 new mode 100644 index cc1a4df8..c84adfad --- a/sound/fmgen/fmgen_opm.h +++ b/sound/fmgen/fmgen_opm.h @@ -1,206 +1,206 @@ -// --------------------------------------------------------------------------- -// OPM-like Sound Generator -// Copyright (C) cisc 1998, 2003. -// --------------------------------------------------------------------------- -// $Id: opm.h,v 1.14 2003/06/07 08:25:53 cisc Exp $ - -#pragma once -#if defined(SUPPORT_FMGEN) - -#ifndef FM_OPM_H -#define FM_OPM_H - -#include "fmgen_fmgen.h" -#include "fmgen_fmtimer.h" -#include "fmgen_psg.h" - -// --------------------------------------------------------------------------- -// class OPM -// OPM に良く似た(?)音を生成する音源ユニット -// -// interface: -// bool Init(uint clock, uint rate, bool); -// 初期化.このクラスを使用する前にかならず呼んでおくこと. -// 注意: 線形補完モードは廃止されました -// -// clock: OPM のクロック周波数(Hz) -// -// rate: 生成する PCM の標本周波数(Hz) -// -// -// 返値 初期化に成功すれば true -// -// bool SetRate(uint clock, uint rate, bool) -// クロックや PCM レートを変更する -// 引数等は Init と同様. -// -// void Mix(Sample* dest, int nsamples) -// Stereo PCM データを nsamples 分合成し, dest で始まる配列に -// 加える(加算する) -// ・dest には sample*2 個分の領域が必要 -// ・格納形式は L, R, L, R... となる. -// ・あくまで加算なので,あらかじめ配列をゼロクリアする必要がある -// ・FM_SAMPLETYPE が short 型の場合クリッピングが行われる. -// ・この関数は音源内部のタイマーとは独立している. -// Timer は Count と GetNextEvent で操作する必要がある. -// -// void Reset() -// 音源をリセット(初期化)する -// -// void SetReg(uint reg, uint data) -// 音源のレジスタ reg に data を書き込む -// -// uint ReadStatus() -// 音源のステータスレジスタを読み出す -// busy フラグは常に 0 -// -// bool Count(uint32 t) -// 音源のタイマーを t [10^(-6) 秒] 進める. -// 音源の内部状態に変化があった時(timer オーバーフロー) -// true を返す -// -// uint32 GetNextEvent() -// 音源のタイマーのどちらかがオーバーフローするまでに必要な -// 時間[μ秒]を返す -// タイマーが停止している場合は 0 を返す. -// -// void SetVolume(int db) -// 各音源の音量を+−方向に調節する.標準値は 0. -// 単位は約 1/2 dB,有効範囲の上限は 20 (10dB) -// -// 仮想関数: -// virtual void Intr(bool irq) -// IRQ 出力に変化があった場合呼ばれる. -// irq = true: IRQ 要求が発生 -// irq = false: IRQ 要求が消える -// -namespace FM -{ - // YM2151(OPM) ---------------------------------------------------- - struct OPMData { - struct TimerData timer; - int fmvolume; - - uint clock; - uint rate; - uint pcmrate; - - uint pmd; - uint amd; - uint lfocount; - uint lfodcount; - - uint lfo_count_; - uint lfo_count_diff_; - uint lfo_step_; - uint lfo_count_prev_; - - uint lfowaveform; - uint rateratio; - uint noise; - int32 noisecount; - uint32 noisedelta; - - bool interpolation; - uint8 lfofreq; - uint8 status; - uint8 reg01; - - uint8 kc[8]; - uint8 kf[8]; - uint8 pan[8]; - - struct Channel4Data ch[8]; - struct ChipData chip; - }; - - class OPM : public Timer - { - public: - OPM(); - ~OPM() {} - - bool Init(uint c, uint r, bool=false); - bool SetRate(uint c, uint r, bool); - void SetLPFCutoff(uint freq); - void Reset(); - - void SetReg(uint addr, uint data); - uint GetReg(uint addr); - uint ReadStatus() { return status & 0x03; } - - void Mix(Sample* buffer, int nsamples); - - void SetVolume(int db); - void SetChannelMask(uint mask); - - void DataSave(struct OPMData* data); - void DataLoad(struct OPMData* data); - - private: - virtual void Intr(bool) {} - - private: - enum - { - OPM_LFOENTS = 512, - }; - - void SetStatus(uint bit); - void ResetStatus(uint bit); - void SetParameter(uint addr, uint data); - void TimerA(); - void RebuildTimeTable(); - void MixSub(int activech, ISample**); - void MixSubL(int activech, ISample**); - void LFO(); - uint Noise(); - - int fmvolume; - - uint clock; - uint rate; - uint pcmrate; - - uint pmd; - uint amd; - uint lfocount; - uint lfodcount; - - uint lfo_count_; - uint lfo_count_diff_; - uint lfo_step_; - uint lfo_count_prev_; - - uint lfowaveform; - uint rateratio; - uint noise; - int32 noisecount; - uint32 noisedelta; - - bool interpolation; - uint8 lfofreq; - uint8 status; - uint8 reg01; - - uint8 kc[8]; - uint8 kf[8]; - uint8 pan[8]; - - Channel4 ch[8]; - Chip chip; - - static void BuildLFOTable(); - static int amtable[4][OPM_LFOENTS]; - static int pmtable[4][OPM_LFOENTS]; - - public: - int dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; } - Channel4* dbgGetCh(int c) { return &ch[c]; } - - }; -} - -#endif // FM_OPM_H - -#endif /* SUPPORT_FMGEN */ +// --------------------------------------------------------------------------- +// OPM-like Sound Generator +// Copyright (C) cisc 1998, 2003. +// --------------------------------------------------------------------------- +// $Id: opm.h,v 1.14 2003/06/07 08:25:53 cisc Exp $ + +#pragma once +#if defined(SUPPORT_FMGEN) + +#ifndef FM_OPM_H +#define FM_OPM_H + +#include "fmgen_fmgen.h" +#include "fmgen_fmtimer.h" +#include "fmgen_psg.h" + +// --------------------------------------------------------------------------- +// class OPM +// OPM に良く似た(?)音を生成する音源ユニット +// +// interface: +// bool Init(uint clock, uint rate, bool); +// 初期化.このクラスを使用する前にかならず呼んでおくこと. +// 注意: 線形補完モードは廃止されました +// +// clock: OPM のクロック周波数(Hz) +// +// rate: 生成する PCM の標本周波数(Hz) +// +// +// 返値 初期化に成功すれば true +// +// bool SetRate(uint clock, uint rate, bool) +// クロックや PCM レートを変更する +// 引数等は Init と同様. +// +// void Mix(Sample* dest, int nsamples) +// Stereo PCM データを nsamples 分合成し, dest で始まる配列に +// 加える(加算する) +// ・dest には sample*2 個分の領域が必要 +// ・格納形式は L, R, L, R... となる. +// ・あくまで加算なので,あらかじめ配列をゼロクリアする必要がある +// ・FM_SAMPLETYPE が short 型の場合クリッピングが行われる. +// ・この関数は音源内部のタイマーとは独立している. +// Timer は Count と GetNextEvent で操作する必要がある. +// +// void Reset() +// 音源をリセット(初期化)する +// +// void SetReg(uint reg, uint data) +// 音源のレジスタ reg に data を書き込む +// +// uint ReadStatus() +// 音源のステータスレジスタを読み出す +// busy フラグは常に 0 +// +// bool Count(uint32 t) +// 音源のタイマーを t [10^(-6) 秒] 進める. +// 音源の内部状態に変化があった時(timer オーバーフロー) +// true を返す +// +// uint32 GetNextEvent() +// 音源のタイマーのどちらかがオーバーフローするまでに必要な +// 時間[μ秒]を返す +// タイマーが停止している場合は 0 を返す. +// +// void SetVolume(int db) +// 各音源の音量を+−方向に調節する.標準値は 0. +// 単位は約 1/2 dB,有効範囲の上限は 20 (10dB) +// +// 仮想関数: +// virtual void Intr(bool irq) +// IRQ 出力に変化があった場合呼ばれる. +// irq = true: IRQ 要求が発生 +// irq = false: IRQ 要求が消える +// +namespace FM +{ + // YM2151(OPM) ---------------------------------------------------- + struct OPMData { + struct TimerData timer; + int fmvolume; + + uint clock; + uint rate; + uint pcmrate; + + uint pmd; + uint amd; + uint lfocount; + uint lfodcount; + + uint lfo_count_; + uint lfo_count_diff_; + uint lfo_step_; + uint lfo_count_prev_; + + uint lfowaveform; + uint rateratio; + uint noise; + int32 noisecount; + uint32 noisedelta; + + bool interpolation; + uint8 lfofreq; + uint8 status; + uint8 reg01; + + uint8 kc[8]; + uint8 kf[8]; + uint8 pan[8]; + + struct Channel4Data ch[8]; + struct ChipData chip; + }; + + class OPM : public Timer + { + public: + OPM(); + ~OPM() {} + + bool Init(uint c, uint r, bool=false); + bool SetRate(uint c, uint r, bool); + void SetLPFCutoff(uint freq); + void Reset(); + + void SetReg(uint addr, uint data); + uint GetReg(uint addr); + uint ReadStatus() { return status & 0x03; } + + void Mix(Sample* buffer, int nsamples); + + void SetVolume(int db); + void SetChannelMask(uint mask); + + void DataSave(struct OPMData* data); + void DataLoad(struct OPMData* data); + + private: + virtual void Intr(bool) {} + + private: + enum + { + OPM_LFOENTS = 512, + }; + + void SetStatus(uint bit); + void ResetStatus(uint bit); + void SetParameter(uint addr, uint data); + void TimerA(); + void RebuildTimeTable(); + void MixSub(int activech, ISample**); + void MixSubL(int activech, ISample**); + void LFO(); + uint Noise(); + + int fmvolume; + + uint clock; + uint rate; + uint pcmrate; + + uint pmd; + uint amd; + uint lfocount; + uint lfodcount; + + uint lfo_count_; + uint lfo_count_diff_; + uint lfo_step_; + uint lfo_count_prev_; + + uint lfowaveform; + uint rateratio; + uint noise; + int32 noisecount; + uint32 noisedelta; + + bool interpolation; + uint8 lfofreq; + uint8 status; + uint8 reg01; + + uint8 kc[8]; + uint8 kf[8]; + uint8 pan[8]; + + Channel4 ch[8]; + Chip chip; + + static void BuildLFOTable(); + static int amtable[4][OPM_LFOENTS]; + static int pmtable[4][OPM_LFOENTS]; + + public: + int dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; } + Channel4* dbgGetCh(int c) { return &ch[c]; } + + }; +} + +#endif // FM_OPM_H + +#endif /* SUPPORT_FMGEN */ diff --git a/sound/fmgen/fmgen_opna.h b/sound/fmgen/fmgen_opna.h old mode 100755 new mode 100644 index 77c26622..2cb7929b --- a/sound/fmgen/fmgen_opna.h +++ b/sound/fmgen/fmgen_opna.h @@ -1,522 +1,522 @@ -// --------------------------------------------------------------------------- -// OPN/A/B interface with ADPCM support -// Copyright (C) cisc 1998, 2003. -// --------------------------------------------------------------------------- -// $Id: opna.h,v 1.33 2003/06/12 13:14:37 cisc Exp $ - -#pragma once -#if defined(SUPPORT_FMGEN) - -#ifndef FM_OPNA_H -#define FM_OPNA_H - -#include "fmgen_fmgen.h" -#include "fmgen_fmtimer.h" -#include "fmgen_psg.h" - -// --------------------------------------------------------------------------- -// class OPN/OPNA -// OPN/OPNA に良く似た音を生成する音源ユニット -// -// interface: -// bool Init(uint clock, uint rate, bool, const char* path); -// 初期化.このクラスを使用する前にかならず呼んでおくこと. -// OPNA の場合はこの関数でリズムサンプルを読み込む -// -// clock: OPN/OPNA/OPNB のクロック周波数(Hz) -// -// rate: 生成する PCM の標本周波数(Hz) -// -// path: リズムサンプルのパス(OPNA のみ有効) -// 省略時はカレントディレクトリから読み込む -// 文字列の末尾には '\' や '/' などをつけること -// -// 返り値 初期化に成功すれば true -// -// bool LoadRhythmSample(const char* path) -// (OPNA ONLY) -// Rhythm サンプルを読み直す. -// path は Init の path と同じ. -// -// bool SetRate(uint clock, uint rate, bool) -// クロックや PCM レートを変更する -// 引数等は Init を参照のこと. -// -// void Mix(FM_SAMPLETYPE* dest, int nsamples) -// Stereo PCM データを nsamples 分合成し, dest で始まる配列に -// 加える(加算する) -// ・dest には sample*2 個分の領域が必要 -// ・格納形式は L, R, L, R... となる. -// ・あくまで加算なので,あらかじめ配列をゼロクリアする必要がある -// ・FM_SAMPLETYPE が short 型の場合クリッピングが行われる. -// ・この関数は音源内部のタイマーとは独立している. -// Timer は Count と GetNextEvent で操作する必要がある. -// -// void Reset() -// 音源をリセット(初期化)する -// -// void SetReg(uint reg, uint data) -// 音源のレジスタ reg に data を書き込む -// -// uint GetReg(uint reg) -// 音源のレジスタ reg の内容を読み出す -// 読み込むことが出来るレジスタは PSG, ADPCM の一部,ID(0xff) とか -// -// uint ReadStatus()/ReadStatusEx() -// 音源のステータスレジスタを読み出す -// ReadStatusEx は拡張ステータスレジスタの読み出し(OPNA) -// busy フラグは常に 0 -// -// bool Count(uint32 t) -// 音源のタイマーを t [μ秒] 進める. -// 音源の内部状態に変化があった時(timer オーバーフロー) -// true を返す -// -// uint32 GetNextEvent() -// 音源のタイマーのどちらかがオーバーフローするまでに必要な -// 時間[μ秒]を返す -// タイマーが停止している場合は ULONG_MAX を返す… と思う -// -// void SetVolumeFM(int db)/SetVolumePSG(int db) ... -// 各音源の音量を+-方向に調節する.標準値は 0. -// 単位は約 1/2 dB,有効範囲の上限は 20 (10dB) -// -namespace FM -{ - // OPN Base ------------------------------------------------------- - struct OPNBaseData { - struct TimerData timer; - int fmvolume; - uint clock; - uint rate; - uint psgrate; - uint status; - uint8 prescale; - struct ChipData chip; - struct PSGData psg; - }; - - class OPNBase : public Timer - { - public: - OPNBase(); - - bool Init(uint c, uint r); - virtual void Reset(); - - void SetVolumeFM(int db); - void SetVolumePSG(int db); - void SetLPFCutoff(uint freq) {} // obsolete - - void DataSave(struct OPNBaseData* data); - void DataLoad(struct OPNBaseData* data); - - protected: - void SetParameter(Channel4* ch, uint addr, uint data); - void SetPrescaler(uint p); - void RebuildTimeTable(); - - int fmvolume; - - uint clock; // OPN クロック - uint rate; // FM 音源合成レート - uint psgrate; // FMGen 出力レート - uint status; - Channel4* csmch; - - - static uint32 lfotable[8]; - - private: - void TimerA(); - uint8 prescale; - - protected: - Chip chip; - PSG psg; - }; - - // OPN2 Base ------------------------------------------------------ - struct OPNABaseData { - struct OPNBaseData opnbase; - uint8 pan[6]; - uint8 fnum2[9]; - uint8 reg22; - uint reg29; - uint stmask; - uint statusnext; - uint32 lfocount; - uint32 lfodcount; - uint fnum[6]; - uint fnum3[3]; - bool is_adpcmbuf; - uint8 adpcmbuf[0x40000]; - uint adpcmmask; - uint adpcmnotice; - uint startaddr; - uint stopaddr; - uint memaddr; - uint limitaddr; - int adpcmlevel; - int adpcmvolume; - int adpcmvol; - uint deltan; - int adplc; - int adpld; - uint adplbase; - int adpcmx; - int adpcmd; - int adpcmout; - int apout0; - int apout1; - uint adpcmreadbuf; - bool adpcmplay; - int8 granuality; - bool adpcmmask_; - uint8 control1; - uint8 control2; - uint8 adpcmreg[8]; - int rhythmmask_; - struct Channel4Data ch[6]; - }; - - class OPNABase : public OPNBase - { - public: - OPNABase(); - ~OPNABase(); - - uint ReadStatus() { return status & 0x03; } - uint ReadStatusEx(); - void SetChannelMask(uint mask); - - void DataSave(struct OPNABaseData* data); - void DataLoad(struct OPNABaseData* data); - - private: - virtual void Intr(bool) {} - - void MakeTable2(); - - protected: - bool Init(uint c, uint r, bool); - bool SetRate(uint c, uint r, bool); - - void Reset(); - void SetReg(uint addr, uint data); - void SetADPCMBReg(uint reg, uint data); - uint GetReg(uint addr); - - protected: - void FMMix(Sample* buffer, int nsamples); - void Mix6(Sample* buffer, int nsamples, int activech); - - void MixSubS(int activech, ISample**); - void MixSubSL(int activech, ISample**); - - void SetStatus(uint bit); - void ResetStatus(uint bit); - void UpdateStatus(); - void LFO(); - - void DecodeADPCMB(); - void ADPCMBMix(Sample* dest, uint count); - - void WriteRAM(uint data); - uint ReadRAM(); - int ReadRAMN(); - int DecodeADPCMBSample(uint); - - // FM 音源関係 - uint8 pan[6]; - uint8 fnum2[9]; - - uint8 reg22; - uint reg29; // OPNA only? - - uint stmask; - uint statusnext; - - uint32 lfocount; - uint32 lfodcount; - - uint fnum[6]; - uint fnum3[3]; - - // ADPCM 関係 - uint8* adpcmbuf; // ADPCM RAM - uint adpcmmask; // メモリアドレスに対するビットマスク - uint adpcmnotice; // ADPCM 再生終了時にたつビット - uint startaddr; // Start address - uint stopaddr; // Stop address - uint memaddr; // 再生中アドレス - uint limitaddr; // Limit address/mask - int adpcmlevel; // ADPCM 音量 - int adpcmvolume; - int adpcmvol; - uint deltan; // ⊿N - int adplc; // 周波数変換用変数 - int adpld; // 周波数変換用変数差分値 - uint adplbase; // adpld の元 - int adpcmx; // ADPCM 合成用 x - int adpcmd; // ADPCM 合成用 ⊿ - int adpcmout; // ADPCM 合成後の出力 - int apout0; // out(t-2)+out(t-1) - int apout1; // out(t-1)+out(t) - - uint adpcmreadbuf; // ADPCM リード用バッファ - bool adpcmplay; // ADPCM 再生中 - int8 granuality; - bool adpcmmask_; - - uint8 control1; // ADPCM コントロールレジスタ1 - uint8 control2; // ADPCM コントロールレジスタ2 - uint8 adpcmreg[8]; // ADPCM レジスタの一部分 - - int rhythmmask_; - - Channel4 ch[6]; - - static void BuildLFOTable(); - static int amtable[FM_LFOENTS]; - static int pmtable[FM_LFOENTS]; - static int32 tltable[FM_TLENTS+FM_TLPOS]; - static bool tablehasmade; - }; - - // YM2203(OPN) ---------------------------------------------------- - struct OPNData { - struct OPNBaseData opnbase; - uint fnum[3]; - uint fnum3[3]; - uint8 fnum2[6]; - struct Channel4Data ch[3]; - }; - - class OPN : public OPNBase - { - public: - OPN(); - virtual ~OPN() {} - - bool Init(uint c, uint r, bool=false, const char* =0); - bool SetRate(uint c, uint r, bool=false); - - void Reset(); - void Mix(Sample* buffer, int nsamples); - void SetReg(uint addr, uint data); - uint GetReg(uint addr); - uint ReadStatus() { return status & 0x03; } - uint ReadStatusEx() { return 0xff; } - - void SetChannelMask(uint mask); - - int dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; } - int dbgGetPGOut(int c, int s) { return ch[c].op[s].dbgpgout_; } - Channel4* dbgGetCh(int c) { return &ch[c]; } - - void DataSave(struct OPNData* data); - void DataLoad(struct OPNData* data); - - private: - virtual void Intr(bool) {} - - void SetStatus(uint bit); - void ResetStatus(uint bit); - - uint fnum[3]; - uint fnum3[3]; - uint8 fnum2[6]; - - Channel4 ch[3]; - }; - - // YM2608(OPNA) --------------------------------------------------- - struct Rhythm - { - uint8 pan; // ぱん - int8 level; // おんりょう - int volume; // おんりょうせってい - int16* sample; // さんぷる - uint size; // さいず - uint pos; // いち - uint step; // すてっぷち - uint rate; // さんぷるのれーと - }; - - struct OPNAData { - struct OPNABaseData opnabase; - Rhythm rhythm[6]; - int8 rhythmtl; - int rhythmtvol; - uint8 rhythmkey; - }; - - class OPNA : public OPNABase - { - public: - OPNA(); - virtual ~OPNA(); - - bool Init(uint c, uint r, bool = false, const char* rhythmpath=0); - bool LoadRhythmSample(const char*); - - bool SetRate(uint c, uint r, bool = false); - void Mix(Sample* buffer, int nsamples); - - void Reset(); - void SetReg(uint addr, uint data); - uint GetReg(uint addr); - - void SetVolumeADPCM(int db); - void SetVolumeRhythmTotal(int db); - void SetVolumeRhythm(int index, int db); - - uint8* GetADPCMBuffer() { return adpcmbuf; } - - int dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; } - int dbgGetPGOut(int c, int s) { return ch[c].op[s].dbgpgout_; } - Channel4* dbgGetCh(int c) { return &ch[c]; } - - void DataSave(struct OPNAData* data); - void DataLoad(struct OPNAData* data); - - private: - void RhythmMix(Sample* buffer, uint count); - - // リズム音源関係 - Rhythm rhythm[6]; - int8 rhythmtl; // リズム全体の音量 - int rhythmtvol; - uint8 rhythmkey; // リズムのキー - }; - - // YM2610/B(OPNB) --------------------------------------------------- - struct ADPCMA - { - uint8 pan; // ぱん - int8 level; // おんりょう - int volume; // おんりょうせってい - uint pos; // いち - uint step; // すてっぷち - - uint start; // 開始 - uint stop; // 終了 - uint nibble; // 次の 4 bit - int adpcmx; // 変換用 - int adpcmd; // 変換用 - }; - - struct OPNBData { - struct OPNABaseData opnabase; -// uint8* adpcmabuf; - int adpcmasize; - ADPCMA adpcma[6]; - int8 adpcmatl; - int adpcmatvol; - uint8 adpcmakey; - int adpcmastep; - uint8 adpcmareg[32]; - struct Channel4Data ch[6]; - }; - - class OPNB : public OPNABase - { - public: - OPNB(); - virtual ~OPNB(); - - bool Init(uint c, uint r, bool = false, - uint8 *_adpcma = 0, int _adpcma_size = 0, - uint8 *_adpcmb = 0, int _adpcmb_size = 0); - - bool SetRate(uint c, uint r, bool = false); - void Mix(Sample* buffer, int nsamples); - - void Reset(); - void SetReg(uint addr, uint data); - uint GetReg(uint addr); - uint ReadStatusEx(); - - void SetVolumeADPCMATotal(int db); - void SetVolumeADPCMA(int index, int db); - void SetVolumeADPCMB(int db); - -// void SetChannelMask(uint mask); - - void DataSave(struct OPNBData* data, void* adpcmdata); - void DataLoad(struct OPNBData* data, void* adpcmdata); - - private: - int DecodeADPCMASample(uint); - void ADPCMAMix(Sample* buffer, uint count); - static void InitADPCMATable(); - - // ADPCMA 関係 - uint8* adpcmabuf; // ADPCMA ROM - int adpcmasize; - ADPCMA adpcma[6]; - int8 adpcmatl; // ADPCMA 全体の音量 - int adpcmatvol; - uint8 adpcmakey; // ADPCMA のキー - int adpcmastep; - uint8 adpcmareg[32]; - - static int jedi_table[(48+1)*16]; - - Channel4 ch[6]; - }; - - // YM2612/3438(OPN2) ---------------------------------------------------- - class OPN2 : public OPNBase - { - public: - OPN2(); - virtual ~OPN2() {} - - bool Init(uint c, uint r, bool=false, const char* =0); - bool SetRate(uint c, uint r, bool); - - void Reset(); - void Mix(Sample* buffer, int nsamples); - void SetReg(uint addr, uint data); - uint GetReg(uint addr); - uint ReadStatus() { return status & 0x03; } - uint ReadStatusEx() { return 0xff; } - - void SetChannelMask(uint mask); - - private: - virtual void Intr(bool) {} - - void SetStatus(uint bit); - void ResetStatus(uint bit); - - uint fnum[3]; - uint fnum3[3]; - uint8 fnum2[6]; - - // 線形補間用ワーク - int32 mixc, mixc1; - - Channel4 ch[3]; - }; -} - -// --------------------------------------------------------------------------- - -inline void FM::OPNBase::RebuildTimeTable() -{ - int p = prescale; - prescale = -1; - SetPrescaler(p); -} - -inline void FM::OPNBase::SetVolumePSG(int db) -{ - psg.SetVolume(db); -} - -#endif // FM_OPNA_H - -#endif /* SUPPORT_FMGEN */ +// --------------------------------------------------------------------------- +// OPN/A/B interface with ADPCM support +// Copyright (C) cisc 1998, 2003. +// --------------------------------------------------------------------------- +// $Id: opna.h,v 1.33 2003/06/12 13:14:37 cisc Exp $ + +#pragma once +#if defined(SUPPORT_FMGEN) + +#ifndef FM_OPNA_H +#define FM_OPNA_H + +#include "fmgen_fmgen.h" +#include "fmgen_fmtimer.h" +#include "fmgen_psg.h" + +// --------------------------------------------------------------------------- +// class OPN/OPNA +// OPN/OPNA に良く似た音を生成する音源ユニット +// +// interface: +// bool Init(uint clock, uint rate, bool, const char* path); +// 初期化.このクラスを使用する前にかならず呼んでおくこと. +// OPNA の場合はこの関数でリズムサンプルを読み込む +// +// clock: OPN/OPNA/OPNB のクロック周波数(Hz) +// +// rate: 生成する PCM の標本周波数(Hz) +// +// path: リズムサンプルのパス(OPNA のみ有効) +// 省略時はカレントディレクトリから読み込む +// 文字列の末尾には '\' や '/' などをつけること +// +// 返り値 初期化に成功すれば true +// +// bool LoadRhythmSample(const char* path) +// (OPNA ONLY) +// Rhythm サンプルを読み直す. +// path は Init の path と同じ. +// +// bool SetRate(uint clock, uint rate, bool) +// クロックや PCM レートを変更する +// 引数等は Init を参照のこと. +// +// void Mix(FM_SAMPLETYPE* dest, int nsamples) +// Stereo PCM データを nsamples 分合成し, dest で始まる配列に +// 加える(加算する) +// ・dest には sample*2 個分の領域が必要 +// ・格納形式は L, R, L, R... となる. +// ・あくまで加算なので,あらかじめ配列をゼロクリアする必要がある +// ・FM_SAMPLETYPE が short 型の場合クリッピングが行われる. +// ・この関数は音源内部のタイマーとは独立している. +// Timer は Count と GetNextEvent で操作する必要がある. +// +// void Reset() +// 音源をリセット(初期化)する +// +// void SetReg(uint reg, uint data) +// 音源のレジスタ reg に data を書き込む +// +// uint GetReg(uint reg) +// 音源のレジスタ reg の内容を読み出す +// 読み込むことが出来るレジスタは PSG, ADPCM の一部,ID(0xff) とか +// +// uint ReadStatus()/ReadStatusEx() +// 音源のステータスレジスタを読み出す +// ReadStatusEx は拡張ステータスレジスタの読み出し(OPNA) +// busy フラグは常に 0 +// +// bool Count(uint32 t) +// 音源のタイマーを t [μ秒] 進める. +// 音源の内部状態に変化があった時(timer オーバーフロー) +// true を返す +// +// uint32 GetNextEvent() +// 音源のタイマーのどちらかがオーバーフローするまでに必要な +// 時間[μ秒]を返す +// タイマーが停止している場合は ULONG_MAX を返す… と思う +// +// void SetVolumeFM(int db)/SetVolumePSG(int db) ... +// 各音源の音量を+-方向に調節する.標準値は 0. +// 単位は約 1/2 dB,有効範囲の上限は 20 (10dB) +// +namespace FM +{ + // OPN Base ------------------------------------------------------- + struct OPNBaseData { + struct TimerData timer; + int fmvolume; + uint clock; + uint rate; + uint psgrate; + uint status; + uint8 prescale; + struct ChipData chip; + struct PSGData psg; + }; + + class OPNBase : public Timer + { + public: + OPNBase(); + + bool Init(uint c, uint r); + virtual void Reset(); + + void SetVolumeFM(int db); + void SetVolumePSG(int db); + void SetLPFCutoff(uint freq) {} // obsolete + + void DataSave(struct OPNBaseData* data); + void DataLoad(struct OPNBaseData* data); + + protected: + void SetParameter(Channel4* ch, uint addr, uint data); + void SetPrescaler(uint p); + void RebuildTimeTable(); + + int fmvolume; + + uint clock; // OPN クロック + uint rate; // FM 音源合成レート + uint psgrate; // FMGen 出力レート + uint status; + Channel4* csmch; + + + static uint32 lfotable[8]; + + private: + void TimerA(); + uint8 prescale; + + protected: + Chip chip; + PSG psg; + }; + + // OPN2 Base ------------------------------------------------------ + struct OPNABaseData { + struct OPNBaseData opnbase; + uint8 pan[6]; + uint8 fnum2[9]; + uint8 reg22; + uint reg29; + uint stmask; + uint statusnext; + uint32 lfocount; + uint32 lfodcount; + uint fnum[6]; + uint fnum3[3]; + bool is_adpcmbuf; + uint8 adpcmbuf[0x40000]; + uint adpcmmask; + uint adpcmnotice; + uint startaddr; + uint stopaddr; + uint memaddr; + uint limitaddr; + int adpcmlevel; + int adpcmvolume; + int adpcmvol; + uint deltan; + int adplc; + int adpld; + uint adplbase; + int adpcmx; + int adpcmd; + int adpcmout; + int apout0; + int apout1; + uint adpcmreadbuf; + bool adpcmplay; + int8 granuality; + bool adpcmmask_; + uint8 control1; + uint8 control2; + uint8 adpcmreg[8]; + int rhythmmask_; + struct Channel4Data ch[6]; + }; + + class OPNABase : public OPNBase + { + public: + OPNABase(); + ~OPNABase(); + + uint ReadStatus() { return status & 0x03; } + uint ReadStatusEx(); + void SetChannelMask(uint mask); + + void DataSave(struct OPNABaseData* data); + void DataLoad(struct OPNABaseData* data); + + private: + virtual void Intr(bool) {} + + void MakeTable2(); + + protected: + bool Init(uint c, uint r, bool); + bool SetRate(uint c, uint r, bool); + + void Reset(); + void SetReg(uint addr, uint data); + void SetADPCMBReg(uint reg, uint data); + uint GetReg(uint addr); + + protected: + void FMMix(Sample* buffer, int nsamples); + void Mix6(Sample* buffer, int nsamples, int activech); + + void MixSubS(int activech, ISample**); + void MixSubSL(int activech, ISample**); + + void SetStatus(uint bit); + void ResetStatus(uint bit); + void UpdateStatus(); + void LFO(); + + void DecodeADPCMB(); + void ADPCMBMix(Sample* dest, uint count); + + void WriteRAM(uint data); + uint ReadRAM(); + int ReadRAMN(); + int DecodeADPCMBSample(uint); + + // FM 音源関係 + uint8 pan[6]; + uint8 fnum2[9]; + + uint8 reg22; + uint reg29; // OPNA only? + + uint stmask; + uint statusnext; + + uint32 lfocount; + uint32 lfodcount; + + uint fnum[6]; + uint fnum3[3]; + + // ADPCM 関係 + uint8* adpcmbuf; // ADPCM RAM + uint adpcmmask; // メモリアドレスに対するビットマスク + uint adpcmnotice; // ADPCM 再生終了時にたつビット + uint startaddr; // Start address + uint stopaddr; // Stop address + uint memaddr; // 再生中アドレス + uint limitaddr; // Limit address/mask + int adpcmlevel; // ADPCM 音量 + int adpcmvolume; + int adpcmvol; + uint deltan; // ⊿N + int adplc; // 周波数変換用変数 + int adpld; // 周波数変換用変数差分値 + uint adplbase; // adpld の元 + int adpcmx; // ADPCM 合成用 x + int adpcmd; // ADPCM 合成用 ⊿ + int adpcmout; // ADPCM 合成後の出力 + int apout0; // out(t-2)+out(t-1) + int apout1; // out(t-1)+out(t) + + uint adpcmreadbuf; // ADPCM リード用バッファ + bool adpcmplay; // ADPCM 再生中 + int8 granuality; + bool adpcmmask_; + + uint8 control1; // ADPCM コントロールレジスタ1 + uint8 control2; // ADPCM コントロールレジスタ2 + uint8 adpcmreg[8]; // ADPCM レジスタの一部分 + + int rhythmmask_; + + Channel4 ch[6]; + + static void BuildLFOTable(); + static int amtable[FM_LFOENTS]; + static int pmtable[FM_LFOENTS]; + static int32 tltable[FM_TLENTS+FM_TLPOS]; + static bool tablehasmade; + }; + + // YM2203(OPN) ---------------------------------------------------- + struct OPNData { + struct OPNBaseData opnbase; + uint fnum[3]; + uint fnum3[3]; + uint8 fnum2[6]; + struct Channel4Data ch[3]; + }; + + class OPN : public OPNBase + { + public: + OPN(); + virtual ~OPN() {} + + bool Init(uint c, uint r, bool=false, const char* =0); + bool SetRate(uint c, uint r, bool=false); + + void Reset(); + void Mix(Sample* buffer, int nsamples); + void SetReg(uint addr, uint data); + uint GetReg(uint addr); + uint ReadStatus() { return status & 0x03; } + uint ReadStatusEx() { return 0xff; } + + void SetChannelMask(uint mask); + + int dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; } + int dbgGetPGOut(int c, int s) { return ch[c].op[s].dbgpgout_; } + Channel4* dbgGetCh(int c) { return &ch[c]; } + + void DataSave(struct OPNData* data); + void DataLoad(struct OPNData* data); + + private: + virtual void Intr(bool) {} + + void SetStatus(uint bit); + void ResetStatus(uint bit); + + uint fnum[3]; + uint fnum3[3]; + uint8 fnum2[6]; + + Channel4 ch[3]; + }; + + // YM2608(OPNA) --------------------------------------------------- + struct Rhythm + { + uint8 pan; // ぱん + int8 level; // おんりょう + int volume; // おんりょうせってい + int16* sample; // さんぷる + uint size; // さいず + uint pos; // いち + uint step; // すてっぷち + uint rate; // さんぷるのれーと + }; + + struct OPNAData { + struct OPNABaseData opnabase; + Rhythm rhythm[6]; + int8 rhythmtl; + int rhythmtvol; + uint8 rhythmkey; + }; + + class OPNA : public OPNABase + { + public: + OPNA(); + virtual ~OPNA(); + + bool Init(uint c, uint r, bool = false, const char* rhythmpath=0); + bool LoadRhythmSample(const char*); + + bool SetRate(uint c, uint r, bool = false); + void Mix(Sample* buffer, int nsamples); + + void Reset(); + void SetReg(uint addr, uint data); + uint GetReg(uint addr); + + void SetVolumeADPCM(int db); + void SetVolumeRhythmTotal(int db); + void SetVolumeRhythm(int index, int db); + + uint8* GetADPCMBuffer() { return adpcmbuf; } + + int dbgGetOpOut(int c, int s) { return ch[c].op[s].dbgopout_; } + int dbgGetPGOut(int c, int s) { return ch[c].op[s].dbgpgout_; } + Channel4* dbgGetCh(int c) { return &ch[c]; } + + void DataSave(struct OPNAData* data); + void DataLoad(struct OPNAData* data); + + private: + void RhythmMix(Sample* buffer, uint count); + + // リズム音源関係 + Rhythm rhythm[6]; + int8 rhythmtl; // リズム全体の音量 + int rhythmtvol; + uint8 rhythmkey; // リズムのキー + }; + + // YM2610/B(OPNB) --------------------------------------------------- + struct ADPCMA + { + uint8 pan; // ぱん + int8 level; // おんりょう + int volume; // おんりょうせってい + uint pos; // いち + uint step; // すてっぷち + + uint start; // 開始 + uint stop; // 終了 + uint nibble; // 次の 4 bit + int adpcmx; // 変換用 + int adpcmd; // 変換用 + }; + + struct OPNBData { + struct OPNABaseData opnabase; +// uint8* adpcmabuf; + int adpcmasize; + ADPCMA adpcma[6]; + int8 adpcmatl; + int adpcmatvol; + uint8 adpcmakey; + int adpcmastep; + uint8 adpcmareg[32]; + struct Channel4Data ch[6]; + }; + + class OPNB : public OPNABase + { + public: + OPNB(); + virtual ~OPNB(); + + bool Init(uint c, uint r, bool = false, + uint8 *_adpcma = 0, int _adpcma_size = 0, + uint8 *_adpcmb = 0, int _adpcmb_size = 0); + + bool SetRate(uint c, uint r, bool = false); + void Mix(Sample* buffer, int nsamples); + + void Reset(); + void SetReg(uint addr, uint data); + uint GetReg(uint addr); + uint ReadStatusEx(); + + void SetVolumeADPCMATotal(int db); + void SetVolumeADPCMA(int index, int db); + void SetVolumeADPCMB(int db); + +// void SetChannelMask(uint mask); + + void DataSave(struct OPNBData* data, void* adpcmdata); + void DataLoad(struct OPNBData* data, void* adpcmdata); + + private: + int DecodeADPCMASample(uint); + void ADPCMAMix(Sample* buffer, uint count); + static void InitADPCMATable(); + + // ADPCMA 関係 + uint8* adpcmabuf; // ADPCMA ROM + int adpcmasize; + ADPCMA adpcma[6]; + int8 adpcmatl; // ADPCMA 全体の音量 + int adpcmatvol; + uint8 adpcmakey; // ADPCMA のキー + int adpcmastep; + uint8 adpcmareg[32]; + + static int jedi_table[(48+1)*16]; + + Channel4 ch[6]; + }; + + // YM2612/3438(OPN2) ---------------------------------------------------- + class OPN2 : public OPNBase + { + public: + OPN2(); + virtual ~OPN2() {} + + bool Init(uint c, uint r, bool=false, const char* =0); + bool SetRate(uint c, uint r, bool); + + void Reset(); + void Mix(Sample* buffer, int nsamples); + void SetReg(uint addr, uint data); + uint GetReg(uint addr); + uint ReadStatus() { return status & 0x03; } + uint ReadStatusEx() { return 0xff; } + + void SetChannelMask(uint mask); + + private: + virtual void Intr(bool) {} + + void SetStatus(uint bit); + void ResetStatus(uint bit); + + uint fnum[3]; + uint fnum3[3]; + uint8 fnum2[6]; + + // 線形補間用ワーク + int32 mixc, mixc1; + + Channel4 ch[3]; + }; +} + +// --------------------------------------------------------------------------- + +inline void FM::OPNBase::RebuildTimeTable() +{ + int p = prescale; + prescale = -1; + SetPrescaler(p); +} + +inline void FM::OPNBase::SetVolumePSG(int db) +{ + psg.SetVolume(db); +} + +#endif // FM_OPNA_H + +#endif /* SUPPORT_FMGEN */ diff --git a/sound/fmgen/fmgen_psg.cpp b/sound/fmgen/fmgen_psg.cpp old mode 100755 new mode 100644 index ba519e29..47c3742d --- a/sound/fmgen/fmgen_psg.cpp +++ b/sound/fmgen/fmgen_psg.cpp @@ -1,399 +1,399 @@ -// --------------------------------------------------------------------------- -// PSG Sound Implementation -// Copyright (C) cisc 1997, 1999. -// --------------------------------------------------------------------------- -// $Id: psg.cpp,v 1.10 2002/05/15 21:38:01 cisc Exp $ - -#if defined(SUPPORT_FMGEN) - -#include "fmgen_headers.h" -#include "fmgen_misc.h" -#include "fmgen_psg.h" - -// --------------------------------------------------------------------------- -// コンストラクタ・デストラクタ -// -PSG::PSG() -{ - SetVolume(0); - MakeNoiseTable(); - Reset(); - mask = 0x3f; -} - -PSG::~PSG() -{ - -} - -// --------------------------------------------------------------------------- -// PSG を初期化する(RESET) -// -void PSG::Reset() -{ - for (int i=0; i<14; i++) - SetReg(i, 0); - SetReg(7, 0xff); - SetReg(14, 0xff); - SetReg(15, 0xff); -} - -// --------------------------------------------------------------------------- -// クロック周波数の設定 -// -void PSG::SetClock(int clock, int rate) -{ - tperiodbase = int((1 << toneshift ) / 4.0 * clock / rate); - eperiodbase = int((1 << envshift ) / 4.0 * clock / rate); - nperiodbase = int((1 << noiseshift) / 4.0 * clock / rate); - - // 各データの更新 - int tmp; - tmp = ((reg[0] + reg[1] * 256) & 0xfff); - speriod[0] = tmp ? tperiodbase / tmp : tperiodbase; - tmp = ((reg[2] + reg[3] * 256) & 0xfff); - speriod[1] = tmp ? tperiodbase / tmp : tperiodbase; - tmp = ((reg[4] + reg[5] * 256) & 0xfff); - speriod[2] = tmp ? tperiodbase / tmp : tperiodbase; - tmp = reg[6] & 0x1f; - nperiod = tmp ? nperiodbase / tmp / 2 : nperiodbase / 2; - tmp = ((reg[11] + reg[12] * 256) & 0xffff); - eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2; -} - -// --------------------------------------------------------------------------- -// ノイズテーブルを作成する -// -void PSG::MakeNoiseTable() -{ - if (!noisetable[0]) - { - int noise = 14321; - for (int i=0; i> 1) | (((noise << 14) ^ (noise << 16)) & 0x10000); - } - noisetable[i] = n; - } - } -} - -// --------------------------------------------------------------------------- -// 出力テーブルを作成 -// 素直にテーブルで持ったほうが省スペース。 -// -void PSG::SetVolume(int volume) -{ - double base = 0x4000 / 3.0 * pow(10.0, volume / 40.0); - for (int i=31; i>=2; i--) - { - EmitTable[i] = int(base); - base /= 1.189207115; - } - EmitTable[1] = 0; - EmitTable[0] = 0; - MakeEnvelopTable(); - - SetChannelMask(~mask); -} - -void PSG::SetChannelMask(int c) -{ - mask = ~c; - for (int i=0; i<3; i++) - olevel[i] = mask & (1 << i) ? EmitTable[(reg[8+i] & 15) * 2 + 1] : 0; -} - -// --------------------------------------------------------------------------- -// エンベロープ波形テーブル -// -void PSG::MakeEnvelopTable() -{ - // 0 lo 1 up 2 down 3 hi - static uint8 table1[16*2] = - { - 2,0, 2,0, 2,0, 2,0, 1,0, 1,0, 1,0, 1,0, - 2,2, 2,0, 2,1, 2,3, 1,1, 1,3, 1,2, 1,0, - }; - static uint8 table2[4] = { 0, 0, 31, 31 }; - static int8 table3[4] = { 0, 1, -1, 0 }; - - uint* ptr = enveloptable[0]; - - for (int i=0; i<16*2; i++) - { - uint8 v = table2[table1[i]]; - - for (int j=0; j<32; j++) - { - *ptr++ = EmitTable[v]; - v += table3[table1[i]]; - } - } -} - -// --------------------------------------------------------------------------- -// PSG のレジスタに値をセットする -// regnum レジスタの番号 (0 - 15) -// data セットする値 -// -void PSG::SetReg(uint regnum, uint8 data) -{ - if (regnum < 0x10) - { - reg[regnum] = data; - switch (regnum) - { - int tmp; - - case 0: // ChA Fine Tune - case 1: // ChA Coarse Tune - tmp = ((reg[0] + reg[1] * 256) & 0xfff); - speriod[0] = tmp ? tperiodbase / tmp : tperiodbase; - break; - - case 2: // ChB Fine Tune - case 3: // ChB Coarse Tune - tmp = ((reg[2] + reg[3] * 256) & 0xfff); - speriod[1] = tmp ? tperiodbase / tmp : tperiodbase; - break; - - case 4: // ChC Fine Tune - case 5: // ChC Coarse Tune - tmp = ((reg[4] + reg[5] * 256) & 0xfff); - speriod[2] = tmp ? tperiodbase / tmp : tperiodbase; - break; - - case 6: // Noise generator control - data &= 0x1f; - nperiod = data ? nperiodbase / data : nperiodbase; - break; - - case 8: - olevel[0] = mask & 1 ? EmitTable[(data & 15) * 2 + 1] : 0; - break; - - case 9: - olevel[1] = mask & 2 ? EmitTable[(data & 15) * 2 + 1] : 0; - break; - - case 10: - olevel[2] = mask & 4 ? EmitTable[(data & 15) * 2 + 1] : 0; - break; - - case 11: // Envelop period - case 12: - tmp = ((reg[11] + reg[12] * 256) & 0xffff); - eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2; - break; - - case 13: // Envelop shape - ecount = 0; - envelop = enveloptable[data & 15]; - break; - } - } -} - -// --------------------------------------------------------------------------- -void PSG::DataSave(struct PSGData* data) { - memcpy(data->reg, reg, 16); - memcpy(data->olevel, olevel, sizeof(uint) * 6); - memcpy(data->scount, scount, sizeof(uint32) * 3); - memcpy(data->speriod, speriod, sizeof(uint32) * 3); - data->ecount = ecount; - data->eperiod = eperiod; - data->ncount = ncount; - data->nperiod = nperiod; - data->tperiodbase = tperiodbase; - data->eperiodbase = eperiodbase; - data->nperiodbase = nperiodbase; - data->volume = volume; - data->mask = mask; -} - -// --------------------------------------------------------------------------- -void PSG::DataLoad(struct PSGData* data) { - memcpy(reg, data->reg, 16); - memcpy(olevel, data->olevel, sizeof(uint) * 6); - memcpy(scount, data->scount, sizeof(uint32) * 3); - memcpy(speriod, data->speriod, sizeof(uint32) * 3); - ecount = data->ecount; - eperiod = data->eperiod; - ncount = data->ncount; - nperiod = data->nperiod; - tperiodbase = data->tperiodbase; - eperiodbase = data->eperiodbase; - nperiodbase = data->nperiodbase; - volume = data->volume; - mask = data->mask; -} - -// --------------------------------------------------------------------------- -// -// -inline void PSG::StoreSample(Sample& dest, int32 data) -{ - if (sizeof(Sample) == 2) - dest = (Sample) Limit(dest + data, 0x7fff, -0x8000); - else - dest += data; -} - -// --------------------------------------------------------------------------- -// PCM データを吐き出す(2ch) -// dest PCM データを展開するポインタ -// nsamples 展開する PCM のサンプル数 -// -void PSG::Mix(Sample* dest, int nsamples) -{ - uint8 chenable[3], nenable[3]; - uint8 r7 = ~reg[7]; - - if ((r7 & 0x3f) | ((reg[8] | reg[9] | reg[10]) & 0x1f)) - { - chenable[0] = (r7 & 0x01) && (speriod[0] <= (1 << toneshift)); - chenable[1] = (r7 & 0x02) && (speriod[1] <= (1 << toneshift)); - chenable[2] = (r7 & 0x04) && (speriod[2] <= (1 << toneshift)); - nenable[0] = (r7 >> 3) & 1; - nenable[1] = (r7 >> 4) & 1; - nenable[2] = (r7 >> 5) & 1; - - int noise, sample; - uint env; - uint* p1 = ((mask & 1) && (reg[ 8] & 0x10)) ? &env : &olevel[0]; - uint* p2 = ((mask & 2) && (reg[ 9] & 0x10)) ? &env : &olevel[1]; - uint* p3 = ((mask & 4) && (reg[10] & 0x10)) ? &env : &olevel[2]; - - #define SCOUNT(ch) (scount[ch] >> (toneshift+oversampling)) - - if (p1 != &env && p2 != &env && p3 != &env) - { - // エンベロープ無し - if ((r7 & 0x38) == 0) - { - // ノイズ無し - for (int i=0; i> (noiseshift+oversampling+6)) & (noisetablesize-1)] - >> (ncount >> (noiseshift+oversampling+1)); -#else - noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] - >> (ncount >> (noiseshift+oversampling+1) & 31); -#endif - ncount += nperiod; - - int x, y, z; - x = ((SCOUNT(0) & chenable[0]) | (nenable[0] & noise)) - 1; // 0 or -1 - sample += (olevel[0] + x) ^ x; - scount[0] += speriod[0]; - y = ((SCOUNT(1) & chenable[1]) | (nenable[1] & noise)) - 1; - sample += (olevel[1] + y) ^ y; - scount[1] += speriod[1]; - z = ((SCOUNT(2) & chenable[2]) | (nenable[2] & noise)) - 1; - sample += (olevel[2] + z) ^ z; - scount[2] += speriod[2]; - } - sample /= (1 << oversampling); - StoreSample(dest[0], sample); - StoreSample(dest[1], sample); - dest += 2; - } - } - - // エンベロープの計算をさぼった帳尻あわせ - ecount = (ecount >> 8) + (eperiod >> (8-oversampling)) * nsamples; - if (ecount >= (1 << (envshift+6+oversampling-8))) - { - if ((reg[0x0d] & 0x0b) != 0x0a) - ecount |= (1 << (envshift+5+oversampling-8)); - ecount &= (1 << (envshift+6+oversampling-8)) - 1; - } - ecount <<= 8; - } - else - { - // エンベロープあり - for (int i=0; i> (envshift+oversampling)]; - ecount += eperiod; - if (ecount >= (1 << (envshift+6+oversampling))) - { - if ((reg[0x0d] & 0x0b) != 0x0a) - ecount |= (1 << (envshift+5+oversampling)); - ecount &= (1 << (envshift+6+oversampling)) - 1; - } -#ifdef _M_IX86 - noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] - >> (ncount >> (noiseshift+oversampling+1)); -#else - noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] - >> (ncount >> (noiseshift+oversampling+1) & 31); -#endif - ncount += nperiod; - - int x, y, z; - x = ((SCOUNT(0) & chenable[0]) | (nenable[0] & noise)) - 1; // 0 or -1 - sample += (*p1 + x) ^ x; - scount[0] += speriod[0]; - y = ((SCOUNT(1) & chenable[1]) | (nenable[1] & noise)) - 1; - sample += (*p2 + y) ^ y; - scount[1] += speriod[1]; - z = ((SCOUNT(2) & chenable[2]) | (nenable[2] & noise)) - 1; - sample += (*p3 + z) ^ z; - scount[2] += speriod[2]; - } - sample /= (1 << oversampling); - StoreSample(dest[0], sample); - StoreSample(dest[1], sample); - dest += 2; - } - } - } -} - -// --------------------------------------------------------------------------- -// テーブル -// -uint PSG::noisetable[noisetablesize] = { 0, }; -int PSG::EmitTable[0x20] = { -1, }; -uint PSG::enveloptable[16][64] = { 0, }; - +// --------------------------------------------------------------------------- +// PSG Sound Implementation +// Copyright (C) cisc 1997, 1999. +// --------------------------------------------------------------------------- +// $Id: psg.cpp,v 1.10 2002/05/15 21:38:01 cisc Exp $ + +#if defined(SUPPORT_FMGEN) + +#include "fmgen_headers.h" +#include "fmgen_misc.h" +#include "fmgen_psg.h" + +// --------------------------------------------------------------------------- +// コンストラクタ・デストラクタ +// +PSG::PSG() +{ + SetVolume(0); + MakeNoiseTable(); + Reset(); + mask = 0x3f; +} + +PSG::~PSG() +{ + +} + +// --------------------------------------------------------------------------- +// PSG を初期化する(RESET) +// +void PSG::Reset() +{ + for (int i=0; i<14; i++) + SetReg(i, 0); + SetReg(7, 0xff); + SetReg(14, 0xff); + SetReg(15, 0xff); +} + +// --------------------------------------------------------------------------- +// クロック周波数の設定 +// +void PSG::SetClock(int clock, int rate) +{ + tperiodbase = int((1 << toneshift ) / 4.0 * clock / rate); + eperiodbase = int((1 << envshift ) / 4.0 * clock / rate); + nperiodbase = int((1 << noiseshift) / 4.0 * clock / rate); + + // 各データの更新 + int tmp; + tmp = ((reg[0] + reg[1] * 256) & 0xfff); + speriod[0] = tmp ? tperiodbase / tmp : tperiodbase; + tmp = ((reg[2] + reg[3] * 256) & 0xfff); + speriod[1] = tmp ? tperiodbase / tmp : tperiodbase; + tmp = ((reg[4] + reg[5] * 256) & 0xfff); + speriod[2] = tmp ? tperiodbase / tmp : tperiodbase; + tmp = reg[6] & 0x1f; + nperiod = tmp ? nperiodbase / tmp / 2 : nperiodbase / 2; + tmp = ((reg[11] + reg[12] * 256) & 0xffff); + eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2; +} + +// --------------------------------------------------------------------------- +// ノイズテーブルを作成する +// +void PSG::MakeNoiseTable() +{ + if (!noisetable[0]) + { + int noise = 14321; + for (int i=0; i> 1) | (((noise << 14) ^ (noise << 16)) & 0x10000); + } + noisetable[i] = n; + } + } +} + +// --------------------------------------------------------------------------- +// 出力テーブルを作成 +// 素直にテーブルで持ったほうが省スペース。 +// +void PSG::SetVolume(int volume) +{ + double base = 0x4000 / 3.0 * pow(10.0, volume / 40.0); + for (int i=31; i>=2; i--) + { + EmitTable[i] = int(base); + base /= 1.189207115; + } + EmitTable[1] = 0; + EmitTable[0] = 0; + MakeEnvelopTable(); + + SetChannelMask(~mask); +} + +void PSG::SetChannelMask(int c) +{ + mask = ~c; + for (int i=0; i<3; i++) + olevel[i] = mask & (1 << i) ? EmitTable[(reg[8+i] & 15) * 2 + 1] : 0; +} + +// --------------------------------------------------------------------------- +// エンベロープ波形テーブル +// +void PSG::MakeEnvelopTable() +{ + // 0 lo 1 up 2 down 3 hi + static uint8 table1[16*2] = + { + 2,0, 2,0, 2,0, 2,0, 1,0, 1,0, 1,0, 1,0, + 2,2, 2,0, 2,1, 2,3, 1,1, 1,3, 1,2, 1,0, + }; + static uint8 table2[4] = { 0, 0, 31, 31 }; + static int8 table3[4] = { 0, 1, -1, 0 }; + + uint* ptr = enveloptable[0]; + + for (int i=0; i<16*2; i++) + { + uint8 v = table2[table1[i]]; + + for (int j=0; j<32; j++) + { + *ptr++ = EmitTable[v]; + v += table3[table1[i]]; + } + } +} + +// --------------------------------------------------------------------------- +// PSG のレジスタに値をセットする +// regnum レジスタの番号 (0 - 15) +// data セットする値 +// +void PSG::SetReg(uint regnum, uint8 data) +{ + if (regnum < 0x10) + { + reg[regnum] = data; + switch (regnum) + { + int tmp; + + case 0: // ChA Fine Tune + case 1: // ChA Coarse Tune + tmp = ((reg[0] + reg[1] * 256) & 0xfff); + speriod[0] = tmp ? tperiodbase / tmp : tperiodbase; + break; + + case 2: // ChB Fine Tune + case 3: // ChB Coarse Tune + tmp = ((reg[2] + reg[3] * 256) & 0xfff); + speriod[1] = tmp ? tperiodbase / tmp : tperiodbase; + break; + + case 4: // ChC Fine Tune + case 5: // ChC Coarse Tune + tmp = ((reg[4] + reg[5] * 256) & 0xfff); + speriod[2] = tmp ? tperiodbase / tmp : tperiodbase; + break; + + case 6: // Noise generator control + data &= 0x1f; + nperiod = data ? nperiodbase / data : nperiodbase; + break; + + case 8: + olevel[0] = mask & 1 ? EmitTable[(data & 15) * 2 + 1] : 0; + break; + + case 9: + olevel[1] = mask & 2 ? EmitTable[(data & 15) * 2 + 1] : 0; + break; + + case 10: + olevel[2] = mask & 4 ? EmitTable[(data & 15) * 2 + 1] : 0; + break; + + case 11: // Envelop period + case 12: + tmp = ((reg[11] + reg[12] * 256) & 0xffff); + eperiod = tmp ? eperiodbase / tmp : eperiodbase * 2; + break; + + case 13: // Envelop shape + ecount = 0; + envelop = enveloptable[data & 15]; + break; + } + } +} + +// --------------------------------------------------------------------------- +void PSG::DataSave(struct PSGData* data) { + memcpy(data->reg, reg, 16); + memcpy(data->olevel, olevel, sizeof(uint) * 6); + memcpy(data->scount, scount, sizeof(uint32) * 3); + memcpy(data->speriod, speriod, sizeof(uint32) * 3); + data->ecount = ecount; + data->eperiod = eperiod; + data->ncount = ncount; + data->nperiod = nperiod; + data->tperiodbase = tperiodbase; + data->eperiodbase = eperiodbase; + data->nperiodbase = nperiodbase; + data->volume = volume; + data->mask = mask; +} + +// --------------------------------------------------------------------------- +void PSG::DataLoad(struct PSGData* data) { + memcpy(reg, data->reg, 16); + memcpy(olevel, data->olevel, sizeof(uint) * 6); + memcpy(scount, data->scount, sizeof(uint32) * 3); + memcpy(speriod, data->speriod, sizeof(uint32) * 3); + ecount = data->ecount; + eperiod = data->eperiod; + ncount = data->ncount; + nperiod = data->nperiod; + tperiodbase = data->tperiodbase; + eperiodbase = data->eperiodbase; + nperiodbase = data->nperiodbase; + volume = data->volume; + mask = data->mask; +} + +// --------------------------------------------------------------------------- +// +// +inline void PSG::StoreSample(Sample& dest, int32 data) +{ + if (sizeof(Sample) == 2) + dest = (Sample) Limit(dest + data, 0x7fff, -0x8000); + else + dest += data; +} + +// --------------------------------------------------------------------------- +// PCM データを吐き出す(2ch) +// dest PCM データを展開するポインタ +// nsamples 展開する PCM のサンプル数 +// +void PSG::Mix(Sample* dest, int nsamples) +{ + uint8 chenable[3], nenable[3]; + uint8 r7 = ~reg[7]; + + if ((r7 & 0x3f) | ((reg[8] | reg[9] | reg[10]) & 0x1f)) + { + chenable[0] = (r7 & 0x01) && (speriod[0] <= (1 << toneshift)); + chenable[1] = (r7 & 0x02) && (speriod[1] <= (1 << toneshift)); + chenable[2] = (r7 & 0x04) && (speriod[2] <= (1 << toneshift)); + nenable[0] = (r7 >> 3) & 1; + nenable[1] = (r7 >> 4) & 1; + nenable[2] = (r7 >> 5) & 1; + + int noise, sample; + uint env; + uint* p1 = ((mask & 1) && (reg[ 8] & 0x10)) ? &env : &olevel[0]; + uint* p2 = ((mask & 2) && (reg[ 9] & 0x10)) ? &env : &olevel[1]; + uint* p3 = ((mask & 4) && (reg[10] & 0x10)) ? &env : &olevel[2]; + + #define SCOUNT(ch) (scount[ch] >> (toneshift+oversampling)) + + if (p1 != &env && p2 != &env && p3 != &env) + { + // エンベロープ無し + if ((r7 & 0x38) == 0) + { + // ノイズ無し + for (int i=0; i> (noiseshift+oversampling+6)) & (noisetablesize-1)] + >> (ncount >> (noiseshift+oversampling+1)); +#else + noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] + >> (ncount >> (noiseshift+oversampling+1) & 31); +#endif + ncount += nperiod; + + int x, y, z; + x = ((SCOUNT(0) & chenable[0]) | (nenable[0] & noise)) - 1; // 0 or -1 + sample += (olevel[0] + x) ^ x; + scount[0] += speriod[0]; + y = ((SCOUNT(1) & chenable[1]) | (nenable[1] & noise)) - 1; + sample += (olevel[1] + y) ^ y; + scount[1] += speriod[1]; + z = ((SCOUNT(2) & chenable[2]) | (nenable[2] & noise)) - 1; + sample += (olevel[2] + z) ^ z; + scount[2] += speriod[2]; + } + sample /= (1 << oversampling); + StoreSample(dest[0], sample); + StoreSample(dest[1], sample); + dest += 2; + } + } + + // エンベロープの計算をさぼった帳尻あわせ + ecount = (ecount >> 8) + (eperiod >> (8-oversampling)) * nsamples; + if (ecount >= (1 << (envshift+6+oversampling-8))) + { + if ((reg[0x0d] & 0x0b) != 0x0a) + ecount |= (1 << (envshift+5+oversampling-8)); + ecount &= (1 << (envshift+6+oversampling-8)) - 1; + } + ecount <<= 8; + } + else + { + // エンベロープあり + for (int i=0; i> (envshift+oversampling)]; + ecount += eperiod; + if (ecount >= (1 << (envshift+6+oversampling))) + { + if ((reg[0x0d] & 0x0b) != 0x0a) + ecount |= (1 << (envshift+5+oversampling)); + ecount &= (1 << (envshift+6+oversampling)) - 1; + } +#ifdef _M_IX86 + noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] + >> (ncount >> (noiseshift+oversampling+1)); +#else + noise = noisetable[(ncount >> (noiseshift+oversampling+6)) & (noisetablesize-1)] + >> (ncount >> (noiseshift+oversampling+1) & 31); +#endif + ncount += nperiod; + + int x, y, z; + x = ((SCOUNT(0) & chenable[0]) | (nenable[0] & noise)) - 1; // 0 or -1 + sample += (*p1 + x) ^ x; + scount[0] += speriod[0]; + y = ((SCOUNT(1) & chenable[1]) | (nenable[1] & noise)) - 1; + sample += (*p2 + y) ^ y; + scount[1] += speriod[1]; + z = ((SCOUNT(2) & chenable[2]) | (nenable[2] & noise)) - 1; + sample += (*p3 + z) ^ z; + scount[2] += speriod[2]; + } + sample /= (1 << oversampling); + StoreSample(dest[0], sample); + StoreSample(dest[1], sample); + dest += 2; + } + } + } +} + +// --------------------------------------------------------------------------- +// テーブル +// +uint PSG::noisetable[noisetablesize] = { 0, }; +int PSG::EmitTable[0x20] = { -1, }; +uint PSG::enveloptable[16][64] = { 0, }; + #endif /* SUPPORT_FMGEN */ \ No newline at end of file diff --git a/sound/fmgen/fmgen_psg.h b/sound/fmgen/fmgen_psg.h old mode 100755 new mode 100644 index ae500ba5..b68d2d59 --- a/sound/fmgen/fmgen_psg.h +++ b/sound/fmgen/fmgen_psg.h @@ -1,119 +1,119 @@ -// --------------------------------------------------------------------------- -// PSG-like sound generator -// Copyright (C) cisc 1997, 1999. -// --------------------------------------------------------------------------- -// $Id: psg.h,v 1.8 2003/04/22 13:12:53 cisc Exp $ - -#pragma once -#if defined(SUPPORT_FMGEN) - -#ifndef PSG_H -#define PSG_H - -#include "fmgen_types.h" - -#define PSG_SAMPLETYPE int32 // int32 or int16 - -// --------------------------------------------------------------------------- -// class PSG -// PSG に良く似た音を生成する音源ユニット -// -// interface: -// bool SetClock(uint clock, uint rate) -// 初期化.このクラスを使用する前にかならず呼んでおくこと. -// PSG のクロックや PCM レートを設定する -// -// clock: PSG の動作クロック -// rate: 生成する PCM のレート -// retval 初期化に成功すれば true -// -// void Mix(Sample* dest, int nsamples) -// PCM を nsamples 分合成し, dest で始まる配列に加える(加算する) -// あくまで加算なので,最初に配列をゼロクリアする必要がある -// -// void Reset() -// リセットする -// -// void SetReg(uint reg, uint8 data) -// レジスタ reg に data を書き込む -// -// uint GetReg(uint reg) -// レジスタ reg の内容を読み出す -// -// void SetVolume(int db) -// 各音源の音量を調節する -// 単位は約 1/2 dB -// -struct PSGData { - uint8 reg[16]; - uint olevel[3]; - uint32 scount[3]; - uint32 speriod[3]; - uint32 ecount; - uint32 eperiod; - uint32 ncount; - uint32 nperiod; - uint32 tperiodbase; - uint32 eperiodbase; - uint32 nperiodbase; - int volume; - int mask; -}; - -class PSG -{ -public: - typedef PSG_SAMPLETYPE Sample; - - enum - { - noisetablesize = 1 << 11, // ←メモリ使用量を減らしたいなら減らして - toneshift = 24, - envshift = 22, - noiseshift = 14, - oversampling = 2, // ← 音質より速度が優先なら減らすといいかも - }; - -public: - PSG(); - ~PSG(); - - void Mix(Sample* dest, int nsamples); - void SetClock(int clock, int rate); - - void SetVolume(int vol); - void SetChannelMask(int c); - - void Reset(); - void SetReg(uint regnum, uint8 data); - uint GetReg(uint regnum) { return reg[regnum & 0x0f]; } - - void DataSave(struct PSGData* data); - void DataLoad(struct PSGData* data); - -protected: - void MakeNoiseTable(); - void MakeEnvelopTable(); - static void StoreSample(Sample& dest, int32 data); - - uint8 reg[16]; - - const uint* envelop; - uint olevel[3]; - uint32 scount[3], speriod[3]; - uint32 ecount, eperiod; - uint32 ncount, nperiod; - uint32 tperiodbase; - uint32 eperiodbase; - uint32 nperiodbase; - int volume; - int mask; - - static uint enveloptable[16][64]; - static uint noisetable[noisetablesize]; - static int EmitTable[32]; -}; - -#endif // PSG_H - -#endif /* SUPPORT_FMGEN */ +// --------------------------------------------------------------------------- +// PSG-like sound generator +// Copyright (C) cisc 1997, 1999. +// --------------------------------------------------------------------------- +// $Id: psg.h,v 1.8 2003/04/22 13:12:53 cisc Exp $ + +#pragma once +#if defined(SUPPORT_FMGEN) + +#ifndef PSG_H +#define PSG_H + +#include "fmgen_types.h" + +#define PSG_SAMPLETYPE int32 // int32 or int16 + +// --------------------------------------------------------------------------- +// class PSG +// PSG に良く似た音を生成する音源ユニット +// +// interface: +// bool SetClock(uint clock, uint rate) +// 初期化.このクラスを使用する前にかならず呼んでおくこと. +// PSG のクロックや PCM レートを設定する +// +// clock: PSG の動作クロック +// rate: 生成する PCM のレート +// retval 初期化に成功すれば true +// +// void Mix(Sample* dest, int nsamples) +// PCM を nsamples 分合成し, dest で始まる配列に加える(加算する) +// あくまで加算なので,最初に配列をゼロクリアする必要がある +// +// void Reset() +// リセットする +// +// void SetReg(uint reg, uint8 data) +// レジスタ reg に data を書き込む +// +// uint GetReg(uint reg) +// レジスタ reg の内容を読み出す +// +// void SetVolume(int db) +// 各音源の音量を調節する +// 単位は約 1/2 dB +// +struct PSGData { + uint8 reg[16]; + uint olevel[3]; + uint32 scount[3]; + uint32 speriod[3]; + uint32 ecount; + uint32 eperiod; + uint32 ncount; + uint32 nperiod; + uint32 tperiodbase; + uint32 eperiodbase; + uint32 nperiodbase; + int volume; + int mask; +}; + +class PSG +{ +public: + typedef PSG_SAMPLETYPE Sample; + + enum + { + noisetablesize = 1 << 11, // ←メモリ使用量を減らしたいなら減らして + toneshift = 24, + envshift = 22, + noiseshift = 14, + oversampling = 2, // ← 音質より速度が優先なら減らすといいかも + }; + +public: + PSG(); + ~PSG(); + + void Mix(Sample* dest, int nsamples); + void SetClock(int clock, int rate); + + void SetVolume(int vol); + void SetChannelMask(int c); + + void Reset(); + void SetReg(uint regnum, uint8 data); + uint GetReg(uint regnum) { return reg[regnum & 0x0f]; } + + void DataSave(struct PSGData* data); + void DataLoad(struct PSGData* data); + +protected: + void MakeNoiseTable(); + void MakeEnvelopTable(); + static void StoreSample(Sample& dest, int32 data); + + uint8 reg[16]; + + const uint* envelop; + uint olevel[3]; + uint32 scount[3], speriod[3]; + uint32 ecount, eperiod; + uint32 ncount, nperiod; + uint32 tperiodbase; + uint32 eperiodbase; + uint32 nperiodbase; + int volume; + int mask; + + static uint enveloptable[16][64]; + static uint noisetable[noisetablesize]; + static int EmitTable[32]; +}; + +#endif // PSG_H + +#endif /* SUPPORT_FMGEN */ diff --git a/sound/fmgen/fmgen_readme.txt b/sound/fmgen/fmgen_readme.txt old mode 100755 new mode 100644 index 05625be5..1d42c245 --- a/sound/fmgen/fmgen_readme.txt +++ b/sound/fmgen/fmgen_readme.txt @@ -1,93 +1,93 @@ ------------------------------------------------------------------------------- - FM Sound Generator with OPN/OPM interface - Copyright (C) by cisc 1998, 2003. ------------------------------------------------------------------------------- - -【概要】 - C++ による FM/PSG 音源の実装です。 - - AY8910, YM2203, YM2151, YM2608, YM2610 相当のインターフェースも - 実装してあります。 - - -【使い方】 - (TODO:中身を書く) - -【注意】 - 以前のバージョンから幾分手を加えました。インターフェースは - いじっていないつもりですが、何かしらのバグが隠れているかもしれません。 - - YM2610 は動作チェックすらしていません。 - - 線形補完モード(interpolation)は廃止されました。 - Init() の引数仕様は変わっていませんが、interpolation = true にしても - 動作は変わりません。 - - OPNA::Init/SetRate で与えるチップクロックの値の仕様が - 以前の M88 に搭載されていたバージョンと異なっています. - - -【著作権、免責規定】 - - ・本ソースコードは作者(cisc@retropc.net) が著作権を所有しています。 - - ・本ソースコードはあるがままに提供されるものであり, - 暗黙及び明示的な保証を一切含みません. - - ・本ソースコードを利用したこと,利用しなかったこと, - 利用できなかったことに関して生じたあるいは生じると予測される - 損害について,作者は一切責任を負いません. - - ・本ソースコードは,以下の制限を満たす限り自由に改変・組み込み・ - 配布・利用することができます. - - 1. 本ソフトの由来(作者, 著作権)を明記すること. - 2. 配布する際にはフリーソフトとすること. - 3. 改変したソースコードを配布する際は改変内容を明示すること. - 4. ソースコードを配布する際にはこのテキストを一切改変せずに - そのまま添付すること. - - ・公開の際に作者への連絡を頂ければ幸いです. - - ・商用ソフト(シェアウェア含む) に本ソースコードの一部,または - 全部を組み込む際には,事前に作者の合意を得る必要があります. - - -【変更点】 -008 030902 ・出力サンプリングレートの設定を、チップ元来の合成サンプ - リングレートと異なる設定にするとエンベロープがおかしく - なる問題を修正。 - -007a 030608 ・領域外アクセスがあったのを修正 (Thanks to PI.様) - -007 030607 ・再現性の向上 - ・OPN: SSG-EG のサポート - ・線形補完の廃止 - ・asm 版の廃止 - ・マルチスレッドフリーになった? - -006 010330 ・再現性に関していくらか手直し(正弦波,出力タイミング等) - -005 010317 ・OPN: FM 音源の合成周波数が出力周波数よりも低いときに, - 補完を使うと音痴になる/音がまともに出なくなる問題を修正. - ・FM: 補完を使わない時の精度を上げてみる. - 問題が起きたら fmgeninl.h の FM_RATIOBITS を 8 に戻すと吉. - -004a 010311 ・OPM: ノイズをそこそこ聞けるレベル(?)まで修正. - ・OPNA/OPM: FM_USE_CALC2 廃止. - ・デグレ修正, なんのために cvs で管理しているんだか…(T-T - OPNB: ADPCMB ROM マスク作成ミス. - OPNB: ADPCMA ステータスフラグ関係の挙動修復. - OPM: LFO パラメータの初期化を忘れていたのを修正. - -003 010124 ・OPNA/OPM: 実際には補完前の値を出力していたバグを修正. - -002 010123 ・合成周波数が出力周波数より低いときでも補間が効くようにする. - ・OPN: 補間時にプリスケーラの設定を変更したときに音化けする - バグを修正. - ・OPNA/B: LFO が効かないバグを修正. - -001 000928 ・初期バージョン - - -$Id: readme.txt,v 1.1 2003/06/07 08:25:20 cisc Exp $ +------------------------------------------------------------------------------ + FM Sound Generator with OPN/OPM interface + Copyright (C) by cisc 1998, 2003. +------------------------------------------------------------------------------ + +【概要】 + C++ による FM/PSG 音源の実装です。 + + AY8910, YM2203, YM2151, YM2608, YM2610 相当のインターフェースも + 実装してあります。 + + +【使い方】 + (TODO:中身を書く) + +【注意】 + 以前のバージョンから幾分手を加えました。インターフェースは + いじっていないつもりですが、何かしらのバグが隠れているかもしれません。 + + YM2610 は動作チェックすらしていません。 + + 線形補完モード(interpolation)は廃止されました。 + Init() の引数仕様は変わっていませんが、interpolation = true にしても + 動作は変わりません。 + + OPNA::Init/SetRate で与えるチップクロックの値の仕様が + 以前の M88 に搭載されていたバージョンと異なっています. + + +【著作権、免責規定】 + + ・本ソースコードは作者(cisc@retropc.net) が著作権を所有しています。 + + ・本ソースコードはあるがままに提供されるものであり, + 暗黙及び明示的な保証を一切含みません. + + ・本ソースコードを利用したこと,利用しなかったこと, + 利用できなかったことに関して生じたあるいは生じると予測される + 損害について,作者は一切責任を負いません. + + ・本ソースコードは,以下の制限を満たす限り自由に改変・組み込み・ + 配布・利用することができます. + + 1. 本ソフトの由来(作者, 著作権)を明記すること. + 2. 配布する際にはフリーソフトとすること. + 3. 改変したソースコードを配布する際は改変内容を明示すること. + 4. ソースコードを配布する際にはこのテキストを一切改変せずに + そのまま添付すること. + + ・公開の際に作者への連絡を頂ければ幸いです. + + ・商用ソフト(シェアウェア含む) に本ソースコードの一部,または + 全部を組み込む際には,事前に作者の合意を得る必要があります. + + +【変更点】 +008 030902 ・出力サンプリングレートの設定を、チップ元来の合成サンプ + リングレートと異なる設定にするとエンベロープがおかしく + なる問題を修正。 + +007a 030608 ・領域外アクセスがあったのを修正 (Thanks to PI.様) + +007 030607 ・再現性の向上 + ・OPN: SSG-EG のサポート + ・線形補完の廃止 + ・asm 版の廃止 + ・マルチスレッドフリーになった? + +006 010330 ・再現性に関していくらか手直し(正弦波,出力タイミング等) + +005 010317 ・OPN: FM 音源の合成周波数が出力周波数よりも低いときに, + 補完を使うと音痴になる/音がまともに出なくなる問題を修正. + ・FM: 補完を使わない時の精度を上げてみる. + 問題が起きたら fmgeninl.h の FM_RATIOBITS を 8 に戻すと吉. + +004a 010311 ・OPM: ノイズをそこそこ聞けるレベル(?)まで修正. + ・OPNA/OPM: FM_USE_CALC2 廃止. + ・デグレ修正, なんのために cvs で管理しているんだか…(T-T + OPNB: ADPCMB ROM マスク作成ミス. + OPNB: ADPCMA ステータスフラグ関係の挙動修復. + OPM: LFO パラメータの初期化を忘れていたのを修正. + +003 010124 ・OPNA/OPM: 実際には補完前の値を出力していたバグを修正. + +002 010123 ・合成周波数が出力周波数より低いときでも補間が効くようにする. + ・OPN: 補間時にプリスケーラの設定を変更したときに音化けする + バグを修正. + ・OPNA/B: LFO が効かないバグを修正. + +001 000928 ・初期バージョン + + +$Id: readme.txt,v 1.1 2003/06/07 08:25:20 cisc Exp $ diff --git a/sound/fmgen/fmgen_types.h b/sound/fmgen/fmgen_types.h index 9e840987..17807b78 100644 --- a/sound/fmgen/fmgen_types.h +++ b/sound/fmgen/fmgen_types.h @@ -1,33 +1,33 @@ -#pragma once -#if defined(SUPPORT_FMGEN) - -#include - -#if !defined(win32_types_h) -#define win32_types_h - -#if !defined(_MSC_VER) -#define __stdcall -#define HANDLE void * -#endif - -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; -typedef unsigned long ulong; - -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; - -typedef signed char sint8; -typedef signed short sint16; -typedef signed int sint32; - -typedef signed char int8; -typedef signed short int16; -typedef signed int int32; - -#endif // win32_types_h - -#endif /* SUPPORT_FMGEN */ +#pragma once +#if defined(SUPPORT_FMGEN) + +#include + +#if !defined(win32_types_h) +#define win32_types_h + +#if !defined(_MSC_VER) +#define __stdcall +#define HANDLE void * +#endif + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; + +typedef signed char sint8; +typedef signed short sint16; +typedef signed int sint32; + +typedef signed char int8; +typedef signed short int16; +typedef signed int int32; + +#endif // win32_types_h + +#endif /* SUPPORT_FMGEN */ diff --git a/sound/getsnd/getmp3.c b/sound/getsnd/getmp3.c old mode 100755 new mode 100644 index 1591b170..62bd02b6 --- a/sound/getsnd/getmp3.c +++ b/sound/getsnd/getmp3.c @@ -1,113 +1,113 @@ -#include -#include "getsnd.h" - - -#if defined(SUPPORT_MP3) -#include "amethyst.h" - -#define mp3_getdecver __mp3_getdecver -#define mp3_create __mp3_create -#define mp3_destroy __mp3_destroy -#define mp3_predecode __mp3_predecode -#define mp3_decode __mp3_decode -#define mp3_adjustgain __mp3_adjustgain - - -static UINT mp3_dec(GETSND snd, short *dst) { - - UINT8 *src; - MPEGL3 *mp3; - int r; - - src = snd->datptr; - mp3 = (MPEGL3 *)snd->snd; - if (snd->datsize < 4) { - goto mp3dec_err; - } - r = mp3_predecode(mp3, src); - if (r) { - if ((r != MPEGHEAD_RENEWAL) || - (snd->samplingrate != mp3->c.samplingrate) || - (snd->channels != mp3->c.channels)) { - TRACEOUT(("mp3 decord err")); - goto mp3dec_err; - } - } - - if (snd->datsize < mp3->c.insize) { - goto mp3dec_err; - } - snd->datptr += mp3->c.insize; - snd->datsize -= mp3->c.insize; - mp3_decode(mp3, dst, src, mp3->c.insize); - return(mp3->c.outsamples); - -mp3dec_err: - return(0); -} - -static void mp3_decend(GETSND snd) { - - mp3_destroy((MPEGL3 *)snd->snd); -} - -BRESULT __mp3_open(GETSND snd, UINT8 *ptr, UINT size) { - - MPEGL3 *mp3; - - if (size < 4) { - goto mp3opn_err; - } - mp3 = mp3_create(ptr); - if (mp3 == NULL) { - goto mp3opn_err; - } - snd->datptr = ptr; - snd->datsize = size; - - snd->snd = mp3; - snd->dec = (GSDEC)mp3_dec; - snd->decend = mp3_decend; - - snd->samplingrate = mp3->c.samplingrate; - snd->channels = mp3->c.channels; - snd->blocksize = 1728; - snd->blocksamples = mp3->c.outsamples; - snd->bit = 16; - TRACEOUT(("mp3: %dHz %dkbps", mp3->c.samplingrate, mp3->c.kbitrate)); - return(SUCCESS); - -mp3opn_err: - return(FAILURE); -} - -BRESULT getmp3_open(GETSND snd, UINT8 *ptr, UINT size) { - - UINT pos; - - if ((size < 10) && (!memcmp(ptr, "ID3", 3))) { - pos = (ptr[6] & 0x7f); - pos <<= 7; - pos |= (ptr[7] & 0x7f); - pos <<= 7; - pos |= (ptr[8] & 0x7f); - pos <<= 7; - pos |= (ptr[9] & 0x7f); - pos += 10; - TRACEOUT(("ID3 Tag - size:%dbyte(s)", pos)); - if (size < pos) { - goto mp3opn_err; - } - ptr += pos; - size -= pos; - } - if (__mp3_open(snd, ptr, size) != SUCCESS) { - goto mp3opn_err; - } - return(SUCCESS); - -mp3opn_err: - return(FAILURE); -} -#endif - +#include +#include "getsnd.h" + + +#if defined(SUPPORT_MP3) +#include "amethyst.h" + +#define mp3_getdecver __mp3_getdecver +#define mp3_create __mp3_create +#define mp3_destroy __mp3_destroy +#define mp3_predecode __mp3_predecode +#define mp3_decode __mp3_decode +#define mp3_adjustgain __mp3_adjustgain + + +static UINT mp3_dec(GETSND snd, short *dst) { + + UINT8 *src; + MPEGL3 *mp3; + int r; + + src = snd->datptr; + mp3 = (MPEGL3 *)snd->snd; + if (snd->datsize < 4) { + goto mp3dec_err; + } + r = mp3_predecode(mp3, src); + if (r) { + if ((r != MPEGHEAD_RENEWAL) || + (snd->samplingrate != mp3->c.samplingrate) || + (snd->channels != mp3->c.channels)) { + TRACEOUT(("mp3 decord err")); + goto mp3dec_err; + } + } + + if (snd->datsize < mp3->c.insize) { + goto mp3dec_err; + } + snd->datptr += mp3->c.insize; + snd->datsize -= mp3->c.insize; + mp3_decode(mp3, dst, src, mp3->c.insize); + return(mp3->c.outsamples); + +mp3dec_err: + return(0); +} + +static void mp3_decend(GETSND snd) { + + mp3_destroy((MPEGL3 *)snd->snd); +} + +BRESULT __mp3_open(GETSND snd, UINT8 *ptr, UINT size) { + + MPEGL3 *mp3; + + if (size < 4) { + goto mp3opn_err; + } + mp3 = mp3_create(ptr); + if (mp3 == NULL) { + goto mp3opn_err; + } + snd->datptr = ptr; + snd->datsize = size; + + snd->snd = mp3; + snd->dec = (GSDEC)mp3_dec; + snd->decend = mp3_decend; + + snd->samplingrate = mp3->c.samplingrate; + snd->channels = mp3->c.channels; + snd->blocksize = 1728; + snd->blocksamples = mp3->c.outsamples; + snd->bit = 16; + TRACEOUT(("mp3: %dHz %dkbps", mp3->c.samplingrate, mp3->c.kbitrate)); + return(SUCCESS); + +mp3opn_err: + return(FAILURE); +} + +BRESULT getmp3_open(GETSND snd, UINT8 *ptr, UINT size) { + + UINT pos; + + if ((size < 10) && (!memcmp(ptr, "ID3", 3))) { + pos = (ptr[6] & 0x7f); + pos <<= 7; + pos |= (ptr[7] & 0x7f); + pos <<= 7; + pos |= (ptr[8] & 0x7f); + pos <<= 7; + pos |= (ptr[9] & 0x7f); + pos += 10; + TRACEOUT(("ID3 Tag - size:%dbyte(s)", pos)); + if (size < pos) { + goto mp3opn_err; + } + ptr += pos; + size -= pos; + } + if (__mp3_open(snd, ptr, size) != SUCCESS) { + goto mp3opn_err; + } + return(SUCCESS); + +mp3opn_err: + return(FAILURE); +} +#endif + diff --git a/sound/getsnd/getogg.c b/sound/getsnd/getogg.c old mode 100755 new mode 100644 index a1c8534f..4a27afcb --- a/sound/getsnd/getogg.c +++ b/sound/getsnd/getogg.c @@ -1,264 +1,264 @@ -#include -#include "getsnd.h" - - -#if defined(SUPPORT_OGG) -#include -#include "vorbis/codec.h" - -typedef struct { - int phase; - ogg_sync_state oy; - ogg_stream_state os; - ogg_page og; - ogg_packet op; - - vorbis_info vi; - vorbis_comment vc; - vorbis_dsp_state vd; - vorbis_block vb; -} __OV; - - -// ---- - -static int snd_read(GETSND snd, void *buffer, int size) { - - UINT rsize; - - if (size <= 0) { - goto sndrd_err; - } - rsize = (UINT)size; - if (rsize >= snd->datsize) { - rsize = snd->datsize; - } - CopyMemory(buffer, snd->datptr, rsize); - snd->datptr += rsize; - snd->datsize -= rsize; - return((int)rsize); - -sndrd_err: - return(0); -} - -enum { - OVPHASE_HEAD = 0, - OVPHASE_STREAMIN, - OVPHASE_GETPCM, - OVPHASE_NEXT, - OVPHASE_CLOSE -}; - -static UINT ogg_dec(GETSND snd, short *dst) { - - __OV *ov; - int result; - char *buffer; - int bytes; - float **pcm; - int samples; - int i; - int j; - float *mono; - short *ptr; - long val; - - ov = (__OV *)snd->snd; - - do { - switch(ov->phase) { - case OVPHASE_HEAD: - result = ogg_sync_pageout(&ov->oy, &ov->og); - if (result > 0) { - ogg_stream_pagein(&ov->os, &ov->og); - ov->phase = OVPHASE_STREAMIN; - } - else if (result == 0) { - ov->phase = OVPHASE_NEXT; - } - else { - TRACEOUT(("Corrupt or missing data in bitstream")); - } - break; - - case OVPHASE_STREAMIN: - result = ogg_stream_packetout(&ov->os, &ov->op); - if (result > 0) { - if (vorbis_synthesis(&ov->vb, &ov->op) == 0) { - vorbis_synthesis_blockin(&ov->vd, &ov->vb); - } - ov->phase = OVPHASE_GETPCM; - } - else if (result == 0) { - if (!ogg_page_eos(&ov->og)) { - ov->phase = OVPHASE_NEXT; - } - else { - ov->phase = OVPHASE_CLOSE; - } - } - break; - - case OVPHASE_GETPCM: - samples = vorbis_synthesis_pcmout(&ov->vd, &pcm); - if (samples > 0) { - if (samples > (int)snd->blocksamples) { - samples = (int)snd->blocksamples; - } - for (i=0; ivi.channels; i++) { - ptr = dst + i; - mono = pcm[i]; - for (j=0; j 32767) { - val = 32767; - } - if (val < -32768) { - val = -32768; - } - *ptr = (short)val; - ptr += ov->vi.channels; - } - } - vorbis_synthesis_read(&ov->vd, samples); - return((UINT)samples); - } - ov->phase = OVPHASE_STREAMIN; - break; - - case OVPHASE_NEXT: - buffer = ogg_sync_buffer(&ov->oy, 4096); - bytes = snd_read(snd, buffer, 4096); - ogg_sync_wrote(&ov->oy, bytes); -#if 1 - ov->phase = OVPHASE_HEAD; -#else - if (bytes) { - ov->phase = OVPHASE_HEAD; - } - else { - ov->phase = OVPHASE_CLOSE; - } -#endif - break; - - case OVPHASE_CLOSE: - return(0); - } - } while(1); -} - -static void ogg_decend(GETSND snd) { - - __OV *ov; - - ov = (__OV *)snd->snd; - - ogg_stream_clear(&ov->os); - vorbis_block_clear(&ov->vb); - vorbis_dsp_clear(&ov->vd); - vorbis_comment_clear(&ov->vc); - vorbis_info_clear(&ov->vi); - ogg_sync_clear(&ov->oy); - _MFREE(ov); -} - -BOOL getogg_open(GETSND snd, UINT8 *ptr, UINT size) { - - __OV *ov; - char *buffer; - int bytes; - int i; - int result; - - snd->datptr = ptr; - snd->datsize = size; - - ov = (__OV *)_MALLOC(sizeof(__OV), "__OV"); - if (ov == NULL) { - goto ovopn_err0; - } - ZeroMemory(ov, sizeof(__OV)); - - buffer = ogg_sync_buffer(&ov->oy, 4096); - bytes = snd_read(snd, buffer, 4096); - ogg_sync_wrote(&ov->oy, bytes); - - if (ogg_sync_pageout(&ov->oy, &ov->og) != 1) { - TRACEOUT(("Input does not appear to be an Ogg bitstream.")); - goto ovopn_err1; - } - ogg_stream_init(&ov->os, ogg_page_serialno(&ov->og)); - - vorbis_info_init(&ov->vi); - vorbis_comment_init(&ov->vc); - if (ogg_stream_pagein(&ov->os, &ov->og) < 0) { - TRACEOUT(("Error reading first page of Ogg bitstream data.")); - goto ovopn_err1; - } - - if (ogg_stream_packetout(&ov->os, &ov->op) != 1) { - TRACEOUT(("Error reading initial header packet.")); - goto ovopn_err1; - } - - if (vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op) < 0) { - TRACEOUT(("This Ogg bitstream does not contain Vorbis audio data.")); - goto ovopn_err1; - } - - i = 0; - while(i < 2) { - while(i < 2) { - result = ogg_sync_pageout(&ov->oy, &ov->og); - if (result == 0) { - break; - } - if (result == 1) { - ogg_stream_pagein(&ov->os, &ov->og); - while(i < 2) { - result = ogg_stream_packetout(&ov->os, &ov->op); - if (result == 0) { - break; - } - if (result < 0) { - TRACEOUT(("Corrupt secondary header. Exiting.")); - goto ovopn_err1; - } - vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op); - i++; - } - } - } - buffer = ogg_sync_buffer(&ov->oy, 4096); - bytes = snd_read(snd, buffer, 4096); - if ((bytes == 0) && (i < 2)) { - TRACEOUT(("End of file before finding all Vorbis headers!")); - return(-1); - } - ogg_sync_wrote(&ov->oy, bytes); - } - - snd->snd = ov; - snd->dec = (GSDEC)ogg_dec; - snd->decend = ogg_decend; - snd->samplingrate = ov->vi.rate; - snd->channels = ov->vi.channels; - snd->blocksize = 4096 * 2; - snd->blocksamples = 4096 / ov->vi.channels; - snd->bit = 16; - - vorbis_synthesis_init(&ov->vd, &ov->vi); - vorbis_block_init(&ov->vd, &ov->vb); - return(SUCCESS); - -ovopn_err1: - ogg_sync_clear(&ov->oy); - _MFREE(ov); - -ovopn_err0: - return(FAILURE); -} -#endif - +#include +#include "getsnd.h" + + +#if defined(SUPPORT_OGG) +#include +#include "vorbis/codec.h" + +typedef struct { + int phase; + ogg_sync_state oy; + ogg_stream_state os; + ogg_page og; + ogg_packet op; + + vorbis_info vi; + vorbis_comment vc; + vorbis_dsp_state vd; + vorbis_block vb; +} __OV; + + +// ---- + +static int snd_read(GETSND snd, void *buffer, int size) { + + UINT rsize; + + if (size <= 0) { + goto sndrd_err; + } + rsize = (UINT)size; + if (rsize >= snd->datsize) { + rsize = snd->datsize; + } + CopyMemory(buffer, snd->datptr, rsize); + snd->datptr += rsize; + snd->datsize -= rsize; + return((int)rsize); + +sndrd_err: + return(0); +} + +enum { + OVPHASE_HEAD = 0, + OVPHASE_STREAMIN, + OVPHASE_GETPCM, + OVPHASE_NEXT, + OVPHASE_CLOSE +}; + +static UINT ogg_dec(GETSND snd, short *dst) { + + __OV *ov; + int result; + char *buffer; + int bytes; + float **pcm; + int samples; + int i; + int j; + float *mono; + short *ptr; + long val; + + ov = (__OV *)snd->snd; + + do { + switch(ov->phase) { + case OVPHASE_HEAD: + result = ogg_sync_pageout(&ov->oy, &ov->og); + if (result > 0) { + ogg_stream_pagein(&ov->os, &ov->og); + ov->phase = OVPHASE_STREAMIN; + } + else if (result == 0) { + ov->phase = OVPHASE_NEXT; + } + else { + TRACEOUT(("Corrupt or missing data in bitstream")); + } + break; + + case OVPHASE_STREAMIN: + result = ogg_stream_packetout(&ov->os, &ov->op); + if (result > 0) { + if (vorbis_synthesis(&ov->vb, &ov->op) == 0) { + vorbis_synthesis_blockin(&ov->vd, &ov->vb); + } + ov->phase = OVPHASE_GETPCM; + } + else if (result == 0) { + if (!ogg_page_eos(&ov->og)) { + ov->phase = OVPHASE_NEXT; + } + else { + ov->phase = OVPHASE_CLOSE; + } + } + break; + + case OVPHASE_GETPCM: + samples = vorbis_synthesis_pcmout(&ov->vd, &pcm); + if (samples > 0) { + if (samples > (int)snd->blocksamples) { + samples = (int)snd->blocksamples; + } + for (i=0; ivi.channels; i++) { + ptr = dst + i; + mono = pcm[i]; + for (j=0; j 32767) { + val = 32767; + } + if (val < -32768) { + val = -32768; + } + *ptr = (short)val; + ptr += ov->vi.channels; + } + } + vorbis_synthesis_read(&ov->vd, samples); + return((UINT)samples); + } + ov->phase = OVPHASE_STREAMIN; + break; + + case OVPHASE_NEXT: + buffer = ogg_sync_buffer(&ov->oy, 4096); + bytes = snd_read(snd, buffer, 4096); + ogg_sync_wrote(&ov->oy, bytes); +#if 1 + ov->phase = OVPHASE_HEAD; +#else + if (bytes) { + ov->phase = OVPHASE_HEAD; + } + else { + ov->phase = OVPHASE_CLOSE; + } +#endif + break; + + case OVPHASE_CLOSE: + return(0); + } + } while(1); +} + +static void ogg_decend(GETSND snd) { + + __OV *ov; + + ov = (__OV *)snd->snd; + + ogg_stream_clear(&ov->os); + vorbis_block_clear(&ov->vb); + vorbis_dsp_clear(&ov->vd); + vorbis_comment_clear(&ov->vc); + vorbis_info_clear(&ov->vi); + ogg_sync_clear(&ov->oy); + _MFREE(ov); +} + +BOOL getogg_open(GETSND snd, UINT8 *ptr, UINT size) { + + __OV *ov; + char *buffer; + int bytes; + int i; + int result; + + snd->datptr = ptr; + snd->datsize = size; + + ov = (__OV *)_MALLOC(sizeof(__OV), "__OV"); + if (ov == NULL) { + goto ovopn_err0; + } + ZeroMemory(ov, sizeof(__OV)); + + buffer = ogg_sync_buffer(&ov->oy, 4096); + bytes = snd_read(snd, buffer, 4096); + ogg_sync_wrote(&ov->oy, bytes); + + if (ogg_sync_pageout(&ov->oy, &ov->og) != 1) { + TRACEOUT(("Input does not appear to be an Ogg bitstream.")); + goto ovopn_err1; + } + ogg_stream_init(&ov->os, ogg_page_serialno(&ov->og)); + + vorbis_info_init(&ov->vi); + vorbis_comment_init(&ov->vc); + if (ogg_stream_pagein(&ov->os, &ov->og) < 0) { + TRACEOUT(("Error reading first page of Ogg bitstream data.")); + goto ovopn_err1; + } + + if (ogg_stream_packetout(&ov->os, &ov->op) != 1) { + TRACEOUT(("Error reading initial header packet.")); + goto ovopn_err1; + } + + if (vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op) < 0) { + TRACEOUT(("This Ogg bitstream does not contain Vorbis audio data.")); + goto ovopn_err1; + } + + i = 0; + while(i < 2) { + while(i < 2) { + result = ogg_sync_pageout(&ov->oy, &ov->og); + if (result == 0) { + break; + } + if (result == 1) { + ogg_stream_pagein(&ov->os, &ov->og); + while(i < 2) { + result = ogg_stream_packetout(&ov->os, &ov->op); + if (result == 0) { + break; + } + if (result < 0) { + TRACEOUT(("Corrupt secondary header. Exiting.")); + goto ovopn_err1; + } + vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op); + i++; + } + } + } + buffer = ogg_sync_buffer(&ov->oy, 4096); + bytes = snd_read(snd, buffer, 4096); + if ((bytes == 0) && (i < 2)) { + TRACEOUT(("End of file before finding all Vorbis headers!")); + return(-1); + } + ogg_sync_wrote(&ov->oy, bytes); + } + + snd->snd = ov; + snd->dec = (GSDEC)ogg_dec; + snd->decend = ogg_decend; + snd->samplingrate = ov->vi.rate; + snd->channels = ov->vi.channels; + snd->blocksize = 4096 * 2; + snd->blocksamples = 4096 / ov->vi.channels; + snd->bit = 16; + + vorbis_synthesis_init(&ov->vd, &ov->vi); + vorbis_block_init(&ov->vd, &ov->vb); + return(SUCCESS); + +ovopn_err1: + ogg_sync_clear(&ov->oy); + _MFREE(ov); + +ovopn_err0: + return(FAILURE); +} +#endif + diff --git a/sound/getsnd/getsmix.c b/sound/getsnd/getsmix.c old mode 100755 new mode 100644 index 07a2f772..517e1eeb --- a/sound/getsnd/getsmix.c +++ b/sound/getsnd/getsmix.c @@ -1,153 +1,153 @@ -#include -#include "getsnd.h" - - -#define DNBASEBITS 12 -#define DNMIXBASE (1 << DNBASEBITS) - -#define UPBASEBITS 12 -#define UPMIXBASE (1 << UPBASEBITS) - - -// 偽物てんぷれーと -// マイクロソフトはマクロ展開下手だから動作チェキするように。 - -// ---- モノラル出力 - -#define MIX_INPUTBIT 8 -#define MIX_OUTPUTBIT 16 -#define MIX_CHANNELS 1 -#define FUNC_NOR m8m16nr -#define FUNC_DOWN m8m16dn -#define FUNC_UP m8m16up -#include "getsndmn.mcr" - -#define MIX_INPUTBIT 8 -#define MIX_OUTPUTBIT 16 -#define MIX_CHANNELS 2 -#define FUNC_NOR s8m16nr -#define FUNC_DOWN s8m16dn -#define FUNC_UP s8m16up -#include "getsndmn.mcr" - -#define MIX_INPUTBIT 16 -#define MIX_OUTPUTBIT 16 -#define MIX_CHANNELS 1 -#define FUNC_NOR m16m16nr -#define FUNC_DOWN m16m16dn -#define FUNC_UP m16m16up -#include "getsndmn.mcr" - -#define MIX_INPUTBIT 16 -#define MIX_OUTPUTBIT 16 -#define MIX_CHANNELS 2 -#define FUNC_NOR s16m16nr -#define FUNC_DOWN s16m16dn -#define FUNC_UP s16m16up -#include "getsndmn.mcr" - - -// ---- ステレオ出力 - -#define MIX_INPUTBIT 8 -#define MIX_OUTPUTBIT 16 -#define MIX_CHANNELS 1 -#define FUNC_NOR m8s16nr -#define FUNC_DOWN m8s16dn -#define FUNC_UP m8s16up -#include "getsndst.mcr" - -#define MIX_INPUTBIT 8 -#define MIX_OUTPUTBIT 16 -#define MIX_CHANNELS 2 -#define FUNC_NOR s8s16nr -#define FUNC_DOWN s8s16dn -#define FUNC_UP s8s16up -#include "getsndst.mcr" - -#define MIX_INPUTBIT 16 -#define MIX_OUTPUTBIT 16 -#define MIX_CHANNELS 1 -#define FUNC_NOR m16s16nr -#define FUNC_DOWN m16s16dn -#define FUNC_UP m16s16up -#include "getsndst.mcr" - -#define MIX_INPUTBIT 16 -#define MIX_OUTPUTBIT 16 -#define MIX_CHANNELS 2 -#define FUNC_NOR s16s16nr -#define FUNC_DOWN s16s16dn -#define FUNC_UP s16s16up -#include "getsndst.mcr" - - -static const GSCNV cnvfunc[] = { - (GSCNV)m8m16nr, (GSCNV)m8m16dn, (GSCNV)m8m16up, - (GSCNV)s8m16nr, (GSCNV)s8m16dn, (GSCNV)s8m16up, - (GSCNV)m16m16nr, (GSCNV)m16m16dn, (GSCNV)m16m16up, - (GSCNV)s16m16nr, (GSCNV)s16m16dn, (GSCNV)s16m16up, - - (GSCNV)m8s16nr, (GSCNV)m8s16dn, (GSCNV)m8s16up, - (GSCNV)s8s16nr, (GSCNV)s8s16dn, (GSCNV)s8s16up, - (GSCNV)m16s16nr, (GSCNV)m16s16dn, (GSCNV)m16s16up, - (GSCNV)s16s16nr, (GSCNV)s16s16dn, (GSCNV)s16s16up}; - - -BRESULT getsnd_setmixproc(GETSND snd, UINT samprate, UINT channles) { - - int funcnum; - - if ((snd->samplingrate < 8000) || (snd->samplingrate > 96000)) { - goto gssmp_err; - } - if ((samprate < 8000) || (samprate > 96000)) { - goto gssmp_err; - } - - funcnum = 0; - if (snd->channels == 1) { - } - else if (snd->channels == 2) { - funcnum |= 1; - } - else { - goto gssmp_err; - } - - if (snd->bit == 8) { - } - else if (snd->bit == 16) { - funcnum |= 2; - } - else { - goto gssmp_err; - } - - if (channles == 1) { - } - else if (channles == 2) { - funcnum |= 4; - } - else { - goto gssmp_err; - } - - funcnum *= 3; - - if (snd->samplingrate > samprate) { - snd->mrate = (DNMIXBASE * samprate) / snd->samplingrate; - snd->rem = DNMIXBASE; - funcnum += 1; - } - else if (snd->samplingrate < samprate) { - snd->mrate = (UPMIXBASE * samprate) / snd->samplingrate; - funcnum += 2; - } - snd->cnv = cnvfunc[funcnum]; - return(SUCCESS); - -gssmp_err: - return(FAILURE); -} - +#include +#include "getsnd.h" + + +#define DNBASEBITS 12 +#define DNMIXBASE (1 << DNBASEBITS) + +#define UPBASEBITS 12 +#define UPMIXBASE (1 << UPBASEBITS) + + +// 偽物てんぷれーと +// マイクロソフトはマクロ展開下手だから動作チェキするように。 + +// ---- モノラル出力 + +#define MIX_INPUTBIT 8 +#define MIX_OUTPUTBIT 16 +#define MIX_CHANNELS 1 +#define FUNC_NOR m8m16nr +#define FUNC_DOWN m8m16dn +#define FUNC_UP m8m16up +#include "getsndmn.mcr" + +#define MIX_INPUTBIT 8 +#define MIX_OUTPUTBIT 16 +#define MIX_CHANNELS 2 +#define FUNC_NOR s8m16nr +#define FUNC_DOWN s8m16dn +#define FUNC_UP s8m16up +#include "getsndmn.mcr" + +#define MIX_INPUTBIT 16 +#define MIX_OUTPUTBIT 16 +#define MIX_CHANNELS 1 +#define FUNC_NOR m16m16nr +#define FUNC_DOWN m16m16dn +#define FUNC_UP m16m16up +#include "getsndmn.mcr" + +#define MIX_INPUTBIT 16 +#define MIX_OUTPUTBIT 16 +#define MIX_CHANNELS 2 +#define FUNC_NOR s16m16nr +#define FUNC_DOWN s16m16dn +#define FUNC_UP s16m16up +#include "getsndmn.mcr" + + +// ---- ステレオ出力 + +#define MIX_INPUTBIT 8 +#define MIX_OUTPUTBIT 16 +#define MIX_CHANNELS 1 +#define FUNC_NOR m8s16nr +#define FUNC_DOWN m8s16dn +#define FUNC_UP m8s16up +#include "getsndst.mcr" + +#define MIX_INPUTBIT 8 +#define MIX_OUTPUTBIT 16 +#define MIX_CHANNELS 2 +#define FUNC_NOR s8s16nr +#define FUNC_DOWN s8s16dn +#define FUNC_UP s8s16up +#include "getsndst.mcr" + +#define MIX_INPUTBIT 16 +#define MIX_OUTPUTBIT 16 +#define MIX_CHANNELS 1 +#define FUNC_NOR m16s16nr +#define FUNC_DOWN m16s16dn +#define FUNC_UP m16s16up +#include "getsndst.mcr" + +#define MIX_INPUTBIT 16 +#define MIX_OUTPUTBIT 16 +#define MIX_CHANNELS 2 +#define FUNC_NOR s16s16nr +#define FUNC_DOWN s16s16dn +#define FUNC_UP s16s16up +#include "getsndst.mcr" + + +static const GSCNV cnvfunc[] = { + (GSCNV)m8m16nr, (GSCNV)m8m16dn, (GSCNV)m8m16up, + (GSCNV)s8m16nr, (GSCNV)s8m16dn, (GSCNV)s8m16up, + (GSCNV)m16m16nr, (GSCNV)m16m16dn, (GSCNV)m16m16up, + (GSCNV)s16m16nr, (GSCNV)s16m16dn, (GSCNV)s16m16up, + + (GSCNV)m8s16nr, (GSCNV)m8s16dn, (GSCNV)m8s16up, + (GSCNV)s8s16nr, (GSCNV)s8s16dn, (GSCNV)s8s16up, + (GSCNV)m16s16nr, (GSCNV)m16s16dn, (GSCNV)m16s16up, + (GSCNV)s16s16nr, (GSCNV)s16s16dn, (GSCNV)s16s16up}; + + +BRESULT getsnd_setmixproc(GETSND snd, UINT samprate, UINT channles) { + + int funcnum; + + if ((snd->samplingrate < 8000) || (snd->samplingrate > 96000)) { + goto gssmp_err; + } + if ((samprate < 8000) || (samprate > 96000)) { + goto gssmp_err; + } + + funcnum = 0; + if (snd->channels == 1) { + } + else if (snd->channels == 2) { + funcnum |= 1; + } + else { + goto gssmp_err; + } + + if (snd->bit == 8) { + } + else if (snd->bit == 16) { + funcnum |= 2; + } + else { + goto gssmp_err; + } + + if (channles == 1) { + } + else if (channles == 2) { + funcnum |= 4; + } + else { + goto gssmp_err; + } + + funcnum *= 3; + + if (snd->samplingrate > samprate) { + snd->mrate = (DNMIXBASE * samprate) / snd->samplingrate; + snd->rem = DNMIXBASE; + funcnum += 1; + } + else if (snd->samplingrate < samprate) { + snd->mrate = (UPMIXBASE * samprate) / snd->samplingrate; + funcnum += 2; + } + snd->cnv = cnvfunc[funcnum]; + return(SUCCESS); + +gssmp_err: + return(FAILURE); +} + diff --git a/sound/getsnd/getsnd.c b/sound/getsnd/getsnd.c old mode 100755 new mode 100644 index a293c04f..5b3f0add --- a/sound/getsnd/getsnd.c +++ b/sound/getsnd/getsnd.c @@ -1,102 +1,102 @@ -#include -#include "getsnd.h" - - -GETSND getsnd_create(void *datptr, UINT datsize) { - - _GETSND snd; - BRESULT r; - UINT size; - UINT blkwork; - GETSND ret; - - ZeroMemory(&snd, sizeof(snd)); - r = getwave_open(&snd, (UINT8 *)datptr, datsize); -#if defined(SUPPORT_MP3) - if (r == FAILURE) { - r = getmp3_open(&snd, (UINT8 *)datptr, datsize); - } -#endif -#if defined(SUPPORT_OGG) - if (r == FAILURE) { - r = getogg_open(&snd, (UINT8 *)datptr, datsize); - } -#endif - if (r == FAILURE) { - goto gscre_err0; - } - - blkwork = (snd.bit + 7) >> 3; - blkwork *= snd.channels; - blkwork *= snd.blocksamples; - size = blkwork + snd.blocksize; - - ret = (GETSND)_MALLOC(sizeof(_GETSND) + size, "GETSND"); - if (ret == NULL) { - goto gscre_err1; - } - ZeroMemory(ret + 1, size); - - // ワークとか設定。 - snd.buffer = (UINT8 *)(ret + 1); - snd.work = snd.buffer + blkwork; - *ret = snd; - if (getsnd_setmixproc(ret, snd.samplingrate, snd.channels) != SUCCESS) { - TRACEOUT(("err")); - goto gscre_err1; - } - return(ret); - -gscre_err1: - if (snd.decend) { - (*snd.decend)(&snd); - } - -gscre_err0: - return(NULL); -} - - -void getsnd_destroy(GETSND snd) { - - if (snd == NULL) { - goto gsdes_end; - } - if (snd->decend) { - (*snd->decend)(snd); - } - _MFREE(snd); - -gsdes_end: - return; -} - -UINT getsnd_getpcmbyleng(GETSND snd, void *pcm, UINT leng) { - - UINT8 *pcmp; - UINT8 *pcmterm; - - if (snd == NULL) { - goto gsgpl_err; - } - - pcmp = (UINT8 *)pcm; - pcmterm = pcmp + leng; - while(pcmp < pcmterm) { - if (snd->remain != 0) { - pcmp = (UINT8 *)(*snd->cnv)(snd, pcmp, pcmterm); - } - if (snd->remain == 0) { - snd->buf = snd->buffer; - snd->remain = (*snd->dec)(snd, snd->buffer); - if (snd->remain == 0) { - break; - } - } - } - return((UINT)(pcmp - (UINT8 *)pcm)); - -gsgpl_err: - return(0); -} - +#include +#include "getsnd.h" + + +GETSND getsnd_create(void *datptr, UINT datsize) { + + _GETSND snd; + BRESULT r; + UINT size; + UINT blkwork; + GETSND ret; + + ZeroMemory(&snd, sizeof(snd)); + r = getwave_open(&snd, (UINT8 *)datptr, datsize); +#if defined(SUPPORT_MP3) + if (r == FAILURE) { + r = getmp3_open(&snd, (UINT8 *)datptr, datsize); + } +#endif +#if defined(SUPPORT_OGG) + if (r == FAILURE) { + r = getogg_open(&snd, (UINT8 *)datptr, datsize); + } +#endif + if (r == FAILURE) { + goto gscre_err0; + } + + blkwork = (snd.bit + 7) >> 3; + blkwork *= snd.channels; + blkwork *= snd.blocksamples; + size = blkwork + snd.blocksize; + + ret = (GETSND)_MALLOC(sizeof(_GETSND) + size, "GETSND"); + if (ret == NULL) { + goto gscre_err1; + } + ZeroMemory(ret + 1, size); + + // ワークとか設定。 + snd.buffer = (UINT8 *)(ret + 1); + snd.work = snd.buffer + blkwork; + *ret = snd; + if (getsnd_setmixproc(ret, snd.samplingrate, snd.channels) != SUCCESS) { + TRACEOUT(("err")); + goto gscre_err1; + } + return(ret); + +gscre_err1: + if (snd.decend) { + (*snd.decend)(&snd); + } + +gscre_err0: + return(NULL); +} + + +void getsnd_destroy(GETSND snd) { + + if (snd == NULL) { + goto gsdes_end; + } + if (snd->decend) { + (*snd->decend)(snd); + } + _MFREE(snd); + +gsdes_end: + return; +} + +UINT getsnd_getpcmbyleng(GETSND snd, void *pcm, UINT leng) { + + UINT8 *pcmp; + UINT8 *pcmterm; + + if (snd == NULL) { + goto gsgpl_err; + } + + pcmp = (UINT8 *)pcm; + pcmterm = pcmp + leng; + while(pcmp < pcmterm) { + if (snd->remain != 0) { + pcmp = (UINT8 *)(*snd->cnv)(snd, pcmp, pcmterm); + } + if (snd->remain == 0) { + snd->buf = snd->buffer; + snd->remain = (*snd->dec)(snd, snd->buffer); + if (snd->remain == 0) { + break; + } + } + } + return((UINT)(pcmp - (UINT8 *)pcm)); + +gsgpl_err: + return(0); +} + diff --git a/sound/getsnd/getsnd.h b/sound/getsnd/getsnd.h old mode 100755 new mode 100644 index e5dfd616..42666032 --- a/sound/getsnd/getsnd.h +++ b/sound/getsnd/getsnd.h @@ -1,57 +1,57 @@ - -// #define SUPPORT_MP3 -// #define SUPPORT_OGG - - -#ifdef __cplusplus -extern "C" { -#endif - -struct _getsnd; -typedef struct _getsnd _GETSND; -typedef struct _getsnd *GETSND; - -typedef UINT (*GSDEC)(GETSND self, void *buf); -typedef void (*GSDECEND)(GETSND self); -typedef void *(*GSCNV)(GETSND self, void *buf, void *bufterm); - -BRESULT getwave_open(GETSND snd, UINT8 *ptr, UINT size); -BRESULT getmp3_open(GETSND snd, UINT8 *ptr, UINT size); -BOOL getogg_open(GETSND snd, UINT8 *ptr, UINT size); -BRESULT getsnd_setmixproc(GETSND snd, UINT samprate, UINT channles); - -struct _getsnd { - UINT8 *work; // data load用バッファ - UINT8 *buffer; // デコード済みバッファ - - void *buf; - UINT remain; - long mrate; - long rem; - long pcml; - long pcmr; - - UINT8 *datptr; - UINT datsize; - - void *snd; // optional - GSDEC dec; - GSDECEND decend; // optional - GSCNV cnv; - - UINT samplingrate; - UINT channels; - UINT bit; - UINT blocksamples; // ブロックサンプル数 - UINT blocksize; // 1ブロックのワークサイズ -}; - -GETSND getsnd_create(void *datptr, UINT datsize); -void getsnd_destroy(GETSND hdl); - -UINT getsnd_getpcmbyleng(GETSND hdl, void *pcm, UINT leng); - -#ifdef __cplusplus -} -#endif - + +// #define SUPPORT_MP3 +// #define SUPPORT_OGG + + +#ifdef __cplusplus +extern "C" { +#endif + +struct _getsnd; +typedef struct _getsnd _GETSND; +typedef struct _getsnd *GETSND; + +typedef UINT (*GSDEC)(GETSND self, void *buf); +typedef void (*GSDECEND)(GETSND self); +typedef void *(*GSCNV)(GETSND self, void *buf, void *bufterm); + +BRESULT getwave_open(GETSND snd, UINT8 *ptr, UINT size); +BRESULT getmp3_open(GETSND snd, UINT8 *ptr, UINT size); +BOOL getogg_open(GETSND snd, UINT8 *ptr, UINT size); +BRESULT getsnd_setmixproc(GETSND snd, UINT samprate, UINT channles); + +struct _getsnd { + UINT8 *work; // data load用バッファ + UINT8 *buffer; // デコード済みバッファ + + void *buf; + UINT remain; + long mrate; + long rem; + long pcml; + long pcmr; + + UINT8 *datptr; + UINT datsize; + + void *snd; // optional + GSDEC dec; + GSDECEND decend; // optional + GSCNV cnv; + + UINT samplingrate; + UINT channels; + UINT bit; + UINT blocksamples; // ブロックサンプル数 + UINT blocksize; // 1ブロックのワークサイズ +}; + +GETSND getsnd_create(void *datptr, UINT datsize); +void getsnd_destroy(GETSND hdl); + +UINT getsnd_getpcmbyleng(GETSND hdl, void *pcm, UINT leng); + +#ifdef __cplusplus +} +#endif + diff --git a/sound/getsnd/getsndmn.mcr b/sound/getsnd/getsndmn.mcr old mode 100755 new mode 100644 index 839d63e1..364b153e --- a/sound/getsnd/getsndmn.mcr +++ b/sound/getsnd/getsndmn.mcr @@ -1,160 +1,160 @@ - -#if (MIX_INPUTBIT == 8) -#define _SMP_IN unsigned char -#define _SAMP(s) (((long)(s) - 0x80) << 8) -#elif (MIX_INPUTBIT == 16) -#define _SMP_IN short -#define _SAMP(s) (long)(s) -#endif - - -#if (MIX_OUTPUTBIT == 8) -#define _SMP_OUT unsigned char -#define _SAMPLIMIT(s) if ((s) > 32767) { \ - (s) = 32767; \ - } \ - else if ((s) < -32768) { \ - (s) = -32768; \ - } -#define _OUTSAMP(d, s) (d) = (_SMP_OUT)(((s) >> 8) + 0x80) -#elif (MIX_OUTPUTBIT == 16) -#define _SMP_OUT short -#define _SAMPLIMIT(s) if ((s) > 32767) { \ - (s) = 32767; \ - } \ - else if ((s) < -32768) { \ - (s) = -32768; \ - } -#define _OUTSAMP(d, s) (d) = (_SMP_OUT)(s) -#endif - - -static _SMP_OUT *FUNC_NOR(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { - - _SMP_IN *samp; - UINT size; - - size = MIN(trk->remain, (UINT)(pcmterm - pcm)); - trk->remain -= size; - samp = (_SMP_IN *)trk->buf; - do { - long out; - out = _SAMP(*samp++); -#if (MIX_CHANNELS == 2) - out += _SAMP(*samp++); - out >>= 1; -#endif - _SAMPLIMIT(out); - _OUTSAMP(pcm[0], out); - pcm += 1; - } while(--size); - trk->buf = samp; - return(pcm); -} - -static _SMP_OUT *FUNC_DOWN(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { - - long mrate; - _SMP_IN *samp; - long smp; - - samp = (_SMP_IN *)trk->buf; - mrate = trk->mrate; - do { - if (trk->rem > mrate) { - trk->rem -= mrate; - smp = _SAMP(*samp++); -#if (MIX_CHANNELS == 2) - smp += _SAMP(*samp++); - smp >>= 1; -#endif - trk->pcml += smp * mrate; - } - else { - long out; - long tmp; - out = trk->pcml; - out += _SAMP(samp[0]) * trk->rem; - out >>= DNBASEBITS; - _SAMPLIMIT(out); - _OUTSAMP(pcm[0], out); - tmp = mrate - trk->rem; - smp = _SAMP(*samp++); -#if (MIX_CHANNELS == 2) - smp += _SAMP(*samp++); - smp >>= 1; -#endif - trk->pcml = smp * tmp; - trk->rem = DNMIXBASE - tmp; - pcm += 1; - if (pcm >= pcmterm) { - trk->remain--; - break; - } - } - } while(--trk->remain); - trk->buf = samp; - return(pcm); -} - -static _SMP_OUT *FUNC_UP(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { - - _SMP_IN *samp; - long mrate; - - samp = (_SMP_IN *)trk->buf; - mrate = trk->mrate; - do { - long tmp; - tmp = UPMIXBASE - trk->rem; - if (tmp >= 0) { - long dat; - long next; - dat = (trk->pcml * trk->rem); - next = _SAMP(*samp++); -#if (MIX_CHANNELS == 2) - next += _SAMP(*samp++); - next >>= 1; -#endif - dat += (next * tmp); - dat >>= UPBASEBITS; - _SAMPLIMIT(dat); - trk->pcml = next; - _OUTSAMP(pcm[0], dat); - trk->remain--; - trk->rem = trk->mrate - tmp; - pcm += 1; - if (pcm >= pcmterm) { - goto upsampterm; - } - } - while(trk->rem >= UPMIXBASE) { - long out; - trk->rem -= UPMIXBASE; - out = trk->pcml; - _SAMPLIMIT(out); - _OUTSAMP(pcm[0], out); - pcm += 1; - if (pcm >= pcmterm) { - goto upsampterm; - } - } - } while(trk->remain); -upsampterm: - trk->buf = samp; - return(pcm); -} - -#undef _SAMP -#undef _SMP_IN -#undef _SMP_OUT -#undef _SAMPLIMIT -#undef _OUTSAMP - -#undef MIX_INPUTBIT -#undef MIX_OUTPUTBIT -#undef MIX_CHANNELS -#undef FUNC_NOR -#undef FUNC_DOWN -#undef FUNC_UP - + +#if (MIX_INPUTBIT == 8) +#define _SMP_IN unsigned char +#define _SAMP(s) (((long)(s) - 0x80) << 8) +#elif (MIX_INPUTBIT == 16) +#define _SMP_IN short +#define _SAMP(s) (long)(s) +#endif + + +#if (MIX_OUTPUTBIT == 8) +#define _SMP_OUT unsigned char +#define _SAMPLIMIT(s) if ((s) > 32767) { \ + (s) = 32767; \ + } \ + else if ((s) < -32768) { \ + (s) = -32768; \ + } +#define _OUTSAMP(d, s) (d) = (_SMP_OUT)(((s) >> 8) + 0x80) +#elif (MIX_OUTPUTBIT == 16) +#define _SMP_OUT short +#define _SAMPLIMIT(s) if ((s) > 32767) { \ + (s) = 32767; \ + } \ + else if ((s) < -32768) { \ + (s) = -32768; \ + } +#define _OUTSAMP(d, s) (d) = (_SMP_OUT)(s) +#endif + + +static _SMP_OUT *FUNC_NOR(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { + + _SMP_IN *samp; + UINT size; + + size = MIN(trk->remain, (UINT)(pcmterm - pcm)); + trk->remain -= size; + samp = (_SMP_IN *)trk->buf; + do { + long out; + out = _SAMP(*samp++); +#if (MIX_CHANNELS == 2) + out += _SAMP(*samp++); + out >>= 1; +#endif + _SAMPLIMIT(out); + _OUTSAMP(pcm[0], out); + pcm += 1; + } while(--size); + trk->buf = samp; + return(pcm); +} + +static _SMP_OUT *FUNC_DOWN(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { + + long mrate; + _SMP_IN *samp; + long smp; + + samp = (_SMP_IN *)trk->buf; + mrate = trk->mrate; + do { + if (trk->rem > mrate) { + trk->rem -= mrate; + smp = _SAMP(*samp++); +#if (MIX_CHANNELS == 2) + smp += _SAMP(*samp++); + smp >>= 1; +#endif + trk->pcml += smp * mrate; + } + else { + long out; + long tmp; + out = trk->pcml; + out += _SAMP(samp[0]) * trk->rem; + out >>= DNBASEBITS; + _SAMPLIMIT(out); + _OUTSAMP(pcm[0], out); + tmp = mrate - trk->rem; + smp = _SAMP(*samp++); +#if (MIX_CHANNELS == 2) + smp += _SAMP(*samp++); + smp >>= 1; +#endif + trk->pcml = smp * tmp; + trk->rem = DNMIXBASE - tmp; + pcm += 1; + if (pcm >= pcmterm) { + trk->remain--; + break; + } + } + } while(--trk->remain); + trk->buf = samp; + return(pcm); +} + +static _SMP_OUT *FUNC_UP(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { + + _SMP_IN *samp; + long mrate; + + samp = (_SMP_IN *)trk->buf; + mrate = trk->mrate; + do { + long tmp; + tmp = UPMIXBASE - trk->rem; + if (tmp >= 0) { + long dat; + long next; + dat = (trk->pcml * trk->rem); + next = _SAMP(*samp++); +#if (MIX_CHANNELS == 2) + next += _SAMP(*samp++); + next >>= 1; +#endif + dat += (next * tmp); + dat >>= UPBASEBITS; + _SAMPLIMIT(dat); + trk->pcml = next; + _OUTSAMP(pcm[0], dat); + trk->remain--; + trk->rem = trk->mrate - tmp; + pcm += 1; + if (pcm >= pcmterm) { + goto upsampterm; + } + } + while(trk->rem >= UPMIXBASE) { + long out; + trk->rem -= UPMIXBASE; + out = trk->pcml; + _SAMPLIMIT(out); + _OUTSAMP(pcm[0], out); + pcm += 1; + if (pcm >= pcmterm) { + goto upsampterm; + } + } + } while(trk->remain); +upsampterm: + trk->buf = samp; + return(pcm); +} + +#undef _SAMP +#undef _SMP_IN +#undef _SMP_OUT +#undef _SAMPLIMIT +#undef _OUTSAMP + +#undef MIX_INPUTBIT +#undef MIX_OUTPUTBIT +#undef MIX_CHANNELS +#undef FUNC_NOR +#undef FUNC_DOWN +#undef FUNC_UP + diff --git a/sound/getsnd/getsndst.mcr b/sound/getsnd/getsndst.mcr old mode 100755 new mode 100644 index 7831b842..982e598d --- a/sound/getsnd/getsndst.mcr +++ b/sound/getsnd/getsndst.mcr @@ -1,173 +1,173 @@ - -#if (MIX_INPUTBIT == 8) -#define _SMP_IN unsigned char -#define _SAMP(s) (((long)(s) - 0x80) << 8) -#elif (MIX_INPUTBIT == 16) -#define _SMP_IN short -#define _SAMP(s) (long)(s) -#endif - - -#if (MIX_OUTPUTBIT == 8) -#define _SMP_OUT unsigned char -#define _SAMPLIMIT(s) if ((s) > 32767) { \ - (s) = 32767; \ - } \ - else if ((s) < -32768) { \ - (s) = -32768; \ - } -#define _OUTSAMP(d, s) (d) = (_SMP_OUT)(((s) >> 8) + 0x80) -#elif (MIX_OUTPUTBIT == 16) -#define _SMP_OUT short -#define _SAMPLIMIT(s) if ((s) > 32767) { \ - (s) = 32767; \ - } \ - else if ((s) < -32768) { \ - (s) = -32768; \ - } -#define _OUTSAMP(d, s) (d) = (_SMP_OUT)(s) -#endif - - -static _SMP_OUT *FUNC_NOR(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { - - _SMP_IN *samp; - UINT size; - - size = MIN(trk->remain, (UINT)((pcmterm - pcm) / 2)); - trk->remain -= size; - samp = (_SMP_IN *)trk->buf; - do { - long out; - out = _SAMP(*samp++); - _SAMPLIMIT(out); - _OUTSAMP(pcm[0], out); -#if (MIX_CHANNELS == 2) - out = _SAMP(*samp++); - _SAMPLIMIT(out); -#endif - _OUTSAMP(pcm[1], out); - pcm += 2; - } while(--size); - trk->buf = samp; - return(pcm); -} - -static _SMP_OUT *FUNC_DOWN(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { - - long mrate; - _SMP_IN *samp; - - samp = (_SMP_IN *)trk->buf; - mrate = trk->mrate; - do { - if (trk->rem > mrate) { - trk->rem -= mrate; - trk->pcml += _SAMP(*samp++) * mrate; -#if (MIX_CHANNELS == 2) - trk->pcmr += _SAMP(*samp++) * mrate; -#endif - } - else { - long out; - long tmp; - out = trk->pcml; - out += _SAMP(samp[0]) * trk->rem; - out >>= DNBASEBITS; - _SAMPLIMIT(out); - _OUTSAMP(pcm[0], out); -#if (MIX_CHANNELS == 2) - out = trk->pcmr; - out += _SAMP(samp[1]) * trk->rem; - out >>= DNBASEBITS; - _SAMPLIMIT(out); -#endif - _OUTSAMP(pcm[1], out); - tmp = mrate - trk->rem; - trk->pcml = _SAMP(*samp++) * tmp; -#if (MIX_CHANNELS == 2) - trk->pcmr = _SAMP(*samp++) * tmp; -#endif - trk->rem = DNMIXBASE - tmp; - pcm += 2; - if (pcm >= pcmterm) { - trk->remain--; - break; - } - } - } while(--trk->remain); - trk->buf = samp; - return(pcm); -} - -static _SMP_OUT *FUNC_UP(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { - - _SMP_IN *samp; - long mrate; - - samp = (_SMP_IN *)trk->buf; - mrate = trk->mrate; - do { - long tmp; - tmp = UPMIXBASE - trk->rem; - if (tmp >= 0) { - long dat; - long next; - dat = (trk->pcml * trk->rem); - next = _SAMP(*samp++); - dat += (next * tmp); - dat >>= UPBASEBITS; - _SAMPLIMIT(dat); - trk->pcml = next; - _OUTSAMP(pcm[0], dat); -#if (MIX_CHANNELS == 2) - dat = (trk->pcmr * trk->rem); - next = _SAMP(*samp++); - dat += (next * tmp); - dat >>= UPBASEBITS; - _SAMPLIMIT(dat); - trk->pcmr = next; -#endif - _OUTSAMP(pcm[1], dat); - trk->remain--; - trk->rem = trk->mrate - tmp; - pcm += 2; - if (pcm >= pcmterm) { - goto upsampterm; - } - } - while(trk->rem >= UPMIXBASE) { - long out; - trk->rem -= UPMIXBASE; - out = trk->pcml; - _SAMPLIMIT(out); - _OUTSAMP(pcm[0], out); -#if (MIX_CHANNELS == 2) - out = trk->pcmr; - _SAMPLIMIT(out); -#endif - _OUTSAMP(pcm[1], out); - pcm += 2; - if (pcm >= pcmterm) { - goto upsampterm; - } - } - } while(trk->remain); -upsampterm: - trk->buf = samp; - return(pcm); -} - -#undef _SAMP -#undef _SMP_IN -#undef _SMP_OUT -#undef _SAMPLIMIT -#undef _OUTSAMP - -#undef MIX_INPUTBIT -#undef MIX_OUTPUTBIT -#undef MIX_CHANNELS -#undef FUNC_NOR -#undef FUNC_DOWN -#undef FUNC_UP - + +#if (MIX_INPUTBIT == 8) +#define _SMP_IN unsigned char +#define _SAMP(s) (((long)(s) - 0x80) << 8) +#elif (MIX_INPUTBIT == 16) +#define _SMP_IN short +#define _SAMP(s) (long)(s) +#endif + + +#if (MIX_OUTPUTBIT == 8) +#define _SMP_OUT unsigned char +#define _SAMPLIMIT(s) if ((s) > 32767) { \ + (s) = 32767; \ + } \ + else if ((s) < -32768) { \ + (s) = -32768; \ + } +#define _OUTSAMP(d, s) (d) = (_SMP_OUT)(((s) >> 8) + 0x80) +#elif (MIX_OUTPUTBIT == 16) +#define _SMP_OUT short +#define _SAMPLIMIT(s) if ((s) > 32767) { \ + (s) = 32767; \ + } \ + else if ((s) < -32768) { \ + (s) = -32768; \ + } +#define _OUTSAMP(d, s) (d) = (_SMP_OUT)(s) +#endif + + +static _SMP_OUT *FUNC_NOR(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { + + _SMP_IN *samp; + UINT size; + + size = MIN(trk->remain, (UINT)((pcmterm - pcm) / 2)); + trk->remain -= size; + samp = (_SMP_IN *)trk->buf; + do { + long out; + out = _SAMP(*samp++); + _SAMPLIMIT(out); + _OUTSAMP(pcm[0], out); +#if (MIX_CHANNELS == 2) + out = _SAMP(*samp++); + _SAMPLIMIT(out); +#endif + _OUTSAMP(pcm[1], out); + pcm += 2; + } while(--size); + trk->buf = samp; + return(pcm); +} + +static _SMP_OUT *FUNC_DOWN(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { + + long mrate; + _SMP_IN *samp; + + samp = (_SMP_IN *)trk->buf; + mrate = trk->mrate; + do { + if (trk->rem > mrate) { + trk->rem -= mrate; + trk->pcml += _SAMP(*samp++) * mrate; +#if (MIX_CHANNELS == 2) + trk->pcmr += _SAMP(*samp++) * mrate; +#endif + } + else { + long out; + long tmp; + out = trk->pcml; + out += _SAMP(samp[0]) * trk->rem; + out >>= DNBASEBITS; + _SAMPLIMIT(out); + _OUTSAMP(pcm[0], out); +#if (MIX_CHANNELS == 2) + out = trk->pcmr; + out += _SAMP(samp[1]) * trk->rem; + out >>= DNBASEBITS; + _SAMPLIMIT(out); +#endif + _OUTSAMP(pcm[1], out); + tmp = mrate - trk->rem; + trk->pcml = _SAMP(*samp++) * tmp; +#if (MIX_CHANNELS == 2) + trk->pcmr = _SAMP(*samp++) * tmp; +#endif + trk->rem = DNMIXBASE - tmp; + pcm += 2; + if (pcm >= pcmterm) { + trk->remain--; + break; + } + } + } while(--trk->remain); + trk->buf = samp; + return(pcm); +} + +static _SMP_OUT *FUNC_UP(GETSND trk, _SMP_OUT *pcm, _SMP_OUT *pcmterm) { + + _SMP_IN *samp; + long mrate; + + samp = (_SMP_IN *)trk->buf; + mrate = trk->mrate; + do { + long tmp; + tmp = UPMIXBASE - trk->rem; + if (tmp >= 0) { + long dat; + long next; + dat = (trk->pcml * trk->rem); + next = _SAMP(*samp++); + dat += (next * tmp); + dat >>= UPBASEBITS; + _SAMPLIMIT(dat); + trk->pcml = next; + _OUTSAMP(pcm[0], dat); +#if (MIX_CHANNELS == 2) + dat = (trk->pcmr * trk->rem); + next = _SAMP(*samp++); + dat += (next * tmp); + dat >>= UPBASEBITS; + _SAMPLIMIT(dat); + trk->pcmr = next; +#endif + _OUTSAMP(pcm[1], dat); + trk->remain--; + trk->rem = trk->mrate - tmp; + pcm += 2; + if (pcm >= pcmterm) { + goto upsampterm; + } + } + while(trk->rem >= UPMIXBASE) { + long out; + trk->rem -= UPMIXBASE; + out = trk->pcml; + _SAMPLIMIT(out); + _OUTSAMP(pcm[0], out); +#if (MIX_CHANNELS == 2) + out = trk->pcmr; + _SAMPLIMIT(out); +#endif + _OUTSAMP(pcm[1], out); + pcm += 2; + if (pcm >= pcmterm) { + goto upsampterm; + } + } + } while(trk->remain); +upsampterm: + trk->buf = samp; + return(pcm); +} + +#undef _SAMP +#undef _SMP_IN +#undef _SMP_OUT +#undef _SAMPLIMIT +#undef _OUTSAMP + +#undef MIX_INPUTBIT +#undef MIX_OUTPUTBIT +#undef MIX_CHANNELS +#undef FUNC_NOR +#undef FUNC_DOWN +#undef FUNC_UP + diff --git a/sound/getsnd/getwave.c b/sound/getsnd/getwave.c old mode 100755 new mode 100644 index 66524023..9bd26ba7 --- a/sound/getsnd/getwave.c +++ b/sound/getsnd/getwave.c @@ -1,576 +1,576 @@ -#include -#include "getsnd.h" - - -#if defined(__GNUC__) -typedef struct { - char head[4]; - UINT8 size[4]; - char fmt[4]; -} __attribute__ ((packed)) RIFF_HEADER; - -typedef struct { - char head[4]; - UINT8 size[4]; -} __attribute__ ((packed)) WAVE_HEADER; - -typedef struct { - UINT8 format[2]; - UINT8 channel[2]; - UINT8 rate[4]; - UINT8 rps[4]; - UINT8 block[2]; - UINT8 bit[2]; -} __attribute__ ((packed)) WAVE_INFOS; - -typedef struct { - UINT8 exsize[2]; - UINT8 spb[2]; - UINT8 numcoef[2]; -} __attribute__ ((packed)) WAVE_MSA_INFO; - -#else /* __GNUC__ */ - -#pragma pack(push, 1) -typedef struct { - char head[4]; - UINT8 size[4]; - char fmt[4]; -} RIFF_HEADER; - -typedef struct { - char head[4]; - UINT8 size[4]; -} WAVE_HEADER; - -typedef struct { - UINT8 format[2]; - UINT8 channel[2]; - UINT8 rate[4]; - UINT8 rps[4]; - UINT8 block[2]; - UINT8 bit[2]; -} WAVE_INFOS; - -typedef struct { - UINT8 exsize[2]; - UINT8 spb[2]; - UINT8 numcoef[2]; -} WAVE_MSA_INFO; -#pragma pack(pop) - -#endif /* __GNUC__ */ - -static const char fmt_riff[] = "RIFF"; -static const char fmt_wave[] = "WAVE"; -static const char fmt_rmp3[] = "RMP3"; -static const char chunk_fmt[] = "fmt "; -static const char chunk_data[] = "data"; - - -// ---- PCM - -#if defined(BYTESEX_LITTLE) -static UINT pcm_dec(GETSND snd, void *dst) { - - UINT size; - - size = MIN(snd->blocksize, snd->datsize); - if (size) { - CopyMemory(dst, snd->datptr, size); - snd->datptr += size; - snd->datsize -= size; - size >>= (int)(INTPTR)snd->snd; - } - return(size); -} -#elif defined(BYTESEX_BIG) -static UINT pcm_dec(GETSND snd, UINT8 *dst) { - - UINT size; - UINT cnt; - UINT8 *src; - - size = MIN(snd->blocksize, snd->datsize); - if (size) { - if (snd->bit == 16) { - cnt = size >> 1; - src = snd->datptr; - while(cnt) { - cnt--; - dst[0] = src[1]; - dst[1] = src[0]; - src += 2; - dst += 2; - } - } - else { - CopyMemory(dst, snd->datptr, size); - } - snd->datptr += size; - snd->datsize -= size; - size >>= (int)(long)snd->snd; - } - return(size); -} -#endif - -static const UINT8 abits[4] = {0, 1, 0, 2}; - -static BRESULT pcm_open(GETSND snd) { - - UINT align; - - if ((snd->bit != 8) && (snd->bit != 16)) { - goto pcmopn_err; - } - align = snd->channels * (snd->bit >> 3); - if (snd->blocksize != align) { - goto pcmopn_err; - } - snd->blocksamples = 0x800; // 適当に。 - snd->blocksize *= snd->blocksamples; - snd->snd = (void *)(INTPTR)abits[align - 1]; - snd->dec = (GSDEC)pcm_dec; - return(SUCCESS); - -pcmopn_err: - return(FAILURE); -} - - -// ---- MS-ADPCM - -typedef struct { - SINT16 Coef1; - SINT16 Coef2; -} __COEFPAIR; - -static const int MSADPCMTable[16] = { - 230, 230, 230, 230, 307, 409, 512, 614, - 768, 614, 512, 409, 307, 230, 230, 230 -}; - -static UINT msa_dec(GETSND snd, SINT16 *dst) { - - UINT8 *buf; - UINT size; - UINT outsamples; - int pred[2], delta[2], nibble; - UINT i; - UINT8 indata; - __COEFPAIR *coef; - UINT ch; - SINT32 outdata; - - buf = snd->datptr; // ワーク使ってません。 - size = MIN(snd->datsize, snd->blocksize); - snd->datptr += size; - snd->datsize -= size; - - outsamples = 0; - if (snd->channels == 1) { - if (size >= 7) { - pred[0] = buf[0]; - pred[1] = 0; - delta[0] = LOADINTELWORD(buf+1); - delta[1] = 0; - *dst++ = (SINT16)LOADINTELWORD(buf+5); - *dst++ = (SINT16)LOADINTELWORD(buf+3); - buf += 7; - outsamples = 2 + ((size - 7) * 2); - } - } - else { - if (size >= 14) { - pred[0] = buf[0]; - pred[1] = buf[1]; - delta[0] = LOADINTELWORD(buf+2); - delta[1] = LOADINTELWORD(buf+4); - *dst++ = (SINT16)LOADINTELWORD(buf+10); - *dst++ = (SINT16)LOADINTELWORD(buf+12); - *dst++ = (SINT16)LOADINTELWORD(buf+6); - *dst++ = (SINT16)LOADINTELWORD(buf+8); - buf += 14; - outsamples = 2 + (size - 14); - } - } - coef = (__COEFPAIR *)snd->snd; - nibble = 0; - indata = 0; // for gcc - for (i=2; ichannels; ch++) { - int d = delta[ch], p, data; - if (!nibble) { - indata = *buf++; - data = indata >> 4; - } - else { - data = indata & 15; - } - nibble ^= 1; - delta[ch] = (MSADPCMTable[data] * d) >> 8; - if (delta[ch] < 16) { - delta[ch] = 16; - } - p = (((*(dst - snd->channels )) * coef[pred[ch]].Coef1) - +((*(dst - snd->channels*2)) * coef[pred[ch]].Coef2)); - p >>= 8; - outdata = (((data>=8)?(data-16):data) * d) + p; - if (outdata > 32767) { - outdata = 32767; - } - else if (outdata < -32768) { - outdata = -32768; - } - *dst++ = (SINT16)outdata; - } - } - return(outsamples); -} - -static void msa_decend(GETSND snd) { - - _MFREE(snd->snd); -} - -static BRESULT msa_open(GETSND snd, WAVE_INFOS *wavehead, UINT headsize) { - - WAVE_MSA_INFO *info; - UINT exsize; - UINT numcoef; - UINT spb; - UINT blk; - __COEFPAIR *coef; - UINT8 *p; - - if ((snd->bit != 4) || - (headsize < (sizeof(WAVE_INFOS) + sizeof(WAVE_MSA_INFO)))) { - goto msaopn_err; - } - info = (WAVE_MSA_INFO *)(wavehead + 1); - headsize -= sizeof(WAVE_INFOS); - headsize -= sizeof(WAVE_MSA_INFO); - exsize = LOADINTELWORD(info->exsize); - spb = LOADINTELWORD(info->spb); - numcoef = LOADINTELWORD(info->numcoef); - blk = snd->blocksize; - blk /= snd->channels; - blk -= 6; - blk *= 2; - TRACEOUT(("wav: msa: ExtraSize %d / SPB=%d NumOfCoefs=%d", - exsize, spb, numcoef)); - - if (blk != spb) { - TRACEOUT(("wav: msa: block size error")); - goto msaopn_err; - } - if (exsize < (numcoef * 4 + 4)) { - TRACEOUT(("wav: msa: extra info size error")); - goto msaopn_err; - } - if (numcoef == 0) { - TRACEOUT(("wav: msa: coef == 0")); - goto msaopn_err; - } - - coef = (__COEFPAIR*)_MALLOC(numcoef * sizeof(__COEFPAIR), "adpcm coefs"); - if (coef == NULL) { - goto msaopn_err; - } - - snd->blocksamples = spb; - snd->bit = 16; - snd->dec = (GSDEC)msa_dec; - snd->decend = msa_decend; - snd->snd = (void *)coef; - - p = (UINT8 *)(info + 1); - do { - coef->Coef1 = LOADINTELWORD(p + 0); - coef->Coef2 = LOADINTELWORD(p + 2); - coef++; - p += 4; - } while(--numcoef); - return(SUCCESS); - -msaopn_err: - return(FAILURE); -} - - -// ---- IMA - -#define IMA_MAXSTEP 89 - -static BOOL ima_init = FALSE; -static UINT8 ima_statetbl[IMA_MAXSTEP][8]; - -static const int ima_stateadj[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; - -static const int ima_steptable[IMA_MAXSTEP] = { - 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, - 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, - 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, - 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, - 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, - 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, - 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493,10442, - 11487,12635,13899,15289,16818,18500,20350,22385,24623,27086,29794,32767}; - -static void ima_inittable(void) { - - int i, j, k; - - for (i=0; i= IMA_MAXSTEP) { - k = IMA_MAXSTEP - 1; - } - ima_statetbl[i][j] = (UINT8)k; - } - } -} - -static UINT ima_dec(GETSND snd, SINT16 *dst) { - - UINT c; - SINT32 val[2]; - int state[2]; - UINT8 *src; - UINT blk; - - if (snd->blocksize > snd->datsize) { - goto imadec_err; - } - src = snd->datptr; // ワーク使ってません。 - snd->datptr += snd->blocksize; - snd->datsize -= snd->blocksize; - - blk = snd->blocksamples; - for (c=0; cchannels; c++) { - SINT16 tmp; - tmp = LOADINTELWORD(src); - val[c] = tmp; - *dst++ = (SINT16)val[c]; - state[c] = src[2]; - if (state[c] >= IMA_MAXSTEP) { - state[c] = 0; - } - src += 4; - } - blk--; - - while(blk >= 8) { - blk -= 8; - for (c=0; cchannels; c++) { - UINT samp, r; - samp = 0; // for gcc - r = 8; - do { - int step, dp; - if (!(r & 1)) { - samp = *src++; - } - else { - samp >>= 4; - } - step = ima_steptable[state[c]]; - state[c] = ima_statetbl[state[c]][samp & 7]; - dp = ((((samp & 7) << 1) + 1) * step) >> 3; - if (!(samp & 8)) { - val[c] += dp; - if (val[c] > 32767) { - val[c] = 32767; - } - } - else { - val[c] -= dp; - if (val[c] < -32768) { - val[c] = -32768; - } - } - *dst = (SINT16)val[c]; - dst += snd->channels; - } while(--r); - dst -= (8 * snd->channels); - dst++; - } - dst += (7 * snd->channels); - } - return(snd->blocksamples); - -imadec_err: - return(0); -} - -static BRESULT ima_open(GETSND snd) { - - int blk; - - if (snd->bit != 4) { - goto imaopn_err; - } - blk = snd->blocksize; - blk /= snd->channels; - if (blk & 3) { - goto imaopn_err; - } - blk -= 4; // first block; - blk *= 2; - blk += 1; - snd->blocksamples = blk; - snd->bit = 16; - snd->dec = (GSDEC)ima_dec; - if (!ima_init) { - ima_init = TRUE; - ima_inittable(); - } - return(SUCCESS); - -imaopn_err: - return(FAILURE); -} - - -// ---- MP3 - -#if defined(SUPPORT_MP3) -extern BOOL __mp3_open(GETSND snd, UINT8 *ptr, UINT size); -#endif - - -// ---- - -BRESULT getwave_open(GETSND snd, UINT8 *ptr, UINT size) { - - RIFF_HEADER *riff; - WAVE_HEADER *head; - WAVE_INFOS *info; - UINT pos; - UINT format; - BRESULT r; - UINT headsize = 0; - UINT datasize; - - info = NULL; // for gcc - - // RIFFのチェック - riff = (RIFF_HEADER *)ptr; - pos = sizeof(RIFF_HEADER); - if (size < pos) { - TRACEOUT(("wav: error RIFF header")); - goto gwopn_err; - } - if (memcmp(riff->head, fmt_riff, 4)) { - TRACEOUT(("wav: error RIFF header")); - goto gwopn_err; - } - if (!memcmp(riff->fmt, fmt_wave, 4)) { - // フォーマットヘッダチェック - head = (WAVE_HEADER *)(ptr + pos); - pos += sizeof(WAVE_HEADER); - if (size < pos) { - TRACEOUT(("wav: error fmt header")); - goto gwopn_err; - } - if (memcmp(head->head, chunk_fmt, 4)) { - TRACEOUT(("wav: error fmt header")); - goto gwopn_err; - } - headsize = LOADINTELDWORD(head->size); - if (headsize < sizeof(WAVE_INFOS)) { - TRACEOUT(("wav: error fmt length")); - goto gwopn_err; - } - - // フォーマットチェック - info = (WAVE_INFOS *)(ptr + pos); - pos += headsize; - if (size < pos) { - TRACEOUT(("wav: error fmt data")); - goto gwopn_err; - } - format = LOADINTELWORD(info->format); - snd->channels = LOADINTELWORD(info->channel); - snd->samplingrate = LOADINTELDWORD(info->rate); - snd->blocksize = LOADINTELWORD(info->block); - snd->bit = LOADINTELWORD(info->bit); - TRACEOUT(("wav: fmt: %x / %dch %dHz %dbit", - format, snd->channels, snd->samplingrate, snd->bit)); - if ((UINT)(snd->channels - 1) >= 2) { - TRACEOUT(("wav: channels err")); - goto gwopn_err; - } - } - else if (!memcmp(riff->fmt, fmt_rmp3, 4)) { - format = 0x55; - } - else { - TRACEOUT(("wav: error WAVE header")); - goto gwopn_err; - } - - // dataまで移動。 - while(1) { - head = (WAVE_HEADER *)(ptr + pos); - pos += sizeof(WAVE_HEADER); - if (size < pos) { - TRACEOUT(("wav: error data header")); - goto gwopn_err; - } - if (!memcmp(head->head, chunk_data, 4)) { - break; - } - pos += LOADINTELDWORD(head->size); - } - ptr += pos; - size -= pos; - datasize = LOADINTELDWORD(head->size); - size = MIN(size, datasize); - - switch(format) { - case 0x01: // PCM - r = pcm_open(snd); - break; - - case 0x02: - r = msa_open(snd, info, headsize); - break; - - case 0x11: - r = ima_open(snd); - break; - -#if defined(SUPPORT_MP3) - case 0x55: - return(__mp3_open(snd, ptr, size)); -#endif - -#if defined(SUPPORT_OGG) - case 0x6751: - return(getogg_open(snd, ptr, size)); -#endif - - default: - r = FAILURE; - break; - } - if (r != SUCCESS) { - TRACEOUT(("wav: decord open error")); - goto gwopn_err; - } - - // 登録〜 - snd->datptr = ptr; - snd->datsize = size; - return(SUCCESS); - -gwopn_err: - return(FAILURE); -} - +#include +#include "getsnd.h" + + +#if defined(__GNUC__) +typedef struct { + char head[4]; + UINT8 size[4]; + char fmt[4]; +} __attribute__ ((packed)) RIFF_HEADER; + +typedef struct { + char head[4]; + UINT8 size[4]; +} __attribute__ ((packed)) WAVE_HEADER; + +typedef struct { + UINT8 format[2]; + UINT8 channel[2]; + UINT8 rate[4]; + UINT8 rps[4]; + UINT8 block[2]; + UINT8 bit[2]; +} __attribute__ ((packed)) WAVE_INFOS; + +typedef struct { + UINT8 exsize[2]; + UINT8 spb[2]; + UINT8 numcoef[2]; +} __attribute__ ((packed)) WAVE_MSA_INFO; + +#else /* __GNUC__ */ + +#pragma pack(push, 1) +typedef struct { + char head[4]; + UINT8 size[4]; + char fmt[4]; +} RIFF_HEADER; + +typedef struct { + char head[4]; + UINT8 size[4]; +} WAVE_HEADER; + +typedef struct { + UINT8 format[2]; + UINT8 channel[2]; + UINT8 rate[4]; + UINT8 rps[4]; + UINT8 block[2]; + UINT8 bit[2]; +} WAVE_INFOS; + +typedef struct { + UINT8 exsize[2]; + UINT8 spb[2]; + UINT8 numcoef[2]; +} WAVE_MSA_INFO; +#pragma pack(pop) + +#endif /* __GNUC__ */ + +static const char fmt_riff[] = "RIFF"; +static const char fmt_wave[] = "WAVE"; +static const char fmt_rmp3[] = "RMP3"; +static const char chunk_fmt[] = "fmt "; +static const char chunk_data[] = "data"; + + +// ---- PCM + +#if defined(BYTESEX_LITTLE) +static UINT pcm_dec(GETSND snd, void *dst) { + + UINT size; + + size = MIN(snd->blocksize, snd->datsize); + if (size) { + CopyMemory(dst, snd->datptr, size); + snd->datptr += size; + snd->datsize -= size; + size >>= (int)(INTPTR)snd->snd; + } + return(size); +} +#elif defined(BYTESEX_BIG) +static UINT pcm_dec(GETSND snd, UINT8 *dst) { + + UINT size; + UINT cnt; + UINT8 *src; + + size = MIN(snd->blocksize, snd->datsize); + if (size) { + if (snd->bit == 16) { + cnt = size >> 1; + src = snd->datptr; + while(cnt) { + cnt--; + dst[0] = src[1]; + dst[1] = src[0]; + src += 2; + dst += 2; + } + } + else { + CopyMemory(dst, snd->datptr, size); + } + snd->datptr += size; + snd->datsize -= size; + size >>= (int)(long)snd->snd; + } + return(size); +} +#endif + +static const UINT8 abits[4] = {0, 1, 0, 2}; + +static BRESULT pcm_open(GETSND snd) { + + UINT align; + + if ((snd->bit != 8) && (snd->bit != 16)) { + goto pcmopn_err; + } + align = snd->channels * (snd->bit >> 3); + if (snd->blocksize != align) { + goto pcmopn_err; + } + snd->blocksamples = 0x800; // 適当に。 + snd->blocksize *= snd->blocksamples; + snd->snd = (void *)(INTPTR)abits[align - 1]; + snd->dec = (GSDEC)pcm_dec; + return(SUCCESS); + +pcmopn_err: + return(FAILURE); +} + + +// ---- MS-ADPCM + +typedef struct { + SINT16 Coef1; + SINT16 Coef2; +} __COEFPAIR; + +static const int MSADPCMTable[16] = { + 230, 230, 230, 230, 307, 409, 512, 614, + 768, 614, 512, 409, 307, 230, 230, 230 +}; + +static UINT msa_dec(GETSND snd, SINT16 *dst) { + + UINT8 *buf; + UINT size; + UINT outsamples; + int pred[2], delta[2], nibble; + UINT i; + UINT8 indata; + __COEFPAIR *coef; + UINT ch; + SINT32 outdata; + + buf = snd->datptr; // ワーク使ってません。 + size = MIN(snd->datsize, snd->blocksize); + snd->datptr += size; + snd->datsize -= size; + + outsamples = 0; + if (snd->channels == 1) { + if (size >= 7) { + pred[0] = buf[0]; + pred[1] = 0; + delta[0] = LOADINTELWORD(buf+1); + delta[1] = 0; + *dst++ = (SINT16)LOADINTELWORD(buf+5); + *dst++ = (SINT16)LOADINTELWORD(buf+3); + buf += 7; + outsamples = 2 + ((size - 7) * 2); + } + } + else { + if (size >= 14) { + pred[0] = buf[0]; + pred[1] = buf[1]; + delta[0] = LOADINTELWORD(buf+2); + delta[1] = LOADINTELWORD(buf+4); + *dst++ = (SINT16)LOADINTELWORD(buf+10); + *dst++ = (SINT16)LOADINTELWORD(buf+12); + *dst++ = (SINT16)LOADINTELWORD(buf+6); + *dst++ = (SINT16)LOADINTELWORD(buf+8); + buf += 14; + outsamples = 2 + (size - 14); + } + } + coef = (__COEFPAIR *)snd->snd; + nibble = 0; + indata = 0; // for gcc + for (i=2; ichannels; ch++) { + int d = delta[ch], p, data; + if (!nibble) { + indata = *buf++; + data = indata >> 4; + } + else { + data = indata & 15; + } + nibble ^= 1; + delta[ch] = (MSADPCMTable[data] * d) >> 8; + if (delta[ch] < 16) { + delta[ch] = 16; + } + p = (((*(dst - snd->channels )) * coef[pred[ch]].Coef1) + +((*(dst - snd->channels*2)) * coef[pred[ch]].Coef2)); + p >>= 8; + outdata = (((data>=8)?(data-16):data) * d) + p; + if (outdata > 32767) { + outdata = 32767; + } + else if (outdata < -32768) { + outdata = -32768; + } + *dst++ = (SINT16)outdata; + } + } + return(outsamples); +} + +static void msa_decend(GETSND snd) { + + _MFREE(snd->snd); +} + +static BRESULT msa_open(GETSND snd, WAVE_INFOS *wavehead, UINT headsize) { + + WAVE_MSA_INFO *info; + UINT exsize; + UINT numcoef; + UINT spb; + UINT blk; + __COEFPAIR *coef; + UINT8 *p; + + if ((snd->bit != 4) || + (headsize < (sizeof(WAVE_INFOS) + sizeof(WAVE_MSA_INFO)))) { + goto msaopn_err; + } + info = (WAVE_MSA_INFO *)(wavehead + 1); + headsize -= sizeof(WAVE_INFOS); + headsize -= sizeof(WAVE_MSA_INFO); + exsize = LOADINTELWORD(info->exsize); + spb = LOADINTELWORD(info->spb); + numcoef = LOADINTELWORD(info->numcoef); + blk = snd->blocksize; + blk /= snd->channels; + blk -= 6; + blk *= 2; + TRACEOUT(("wav: msa: ExtraSize %d / SPB=%d NumOfCoefs=%d", + exsize, spb, numcoef)); + + if (blk != spb) { + TRACEOUT(("wav: msa: block size error")); + goto msaopn_err; + } + if (exsize < (numcoef * 4 + 4)) { + TRACEOUT(("wav: msa: extra info size error")); + goto msaopn_err; + } + if (numcoef == 0) { + TRACEOUT(("wav: msa: coef == 0")); + goto msaopn_err; + } + + coef = (__COEFPAIR*)_MALLOC(numcoef * sizeof(__COEFPAIR), "adpcm coefs"); + if (coef == NULL) { + goto msaopn_err; + } + + snd->blocksamples = spb; + snd->bit = 16; + snd->dec = (GSDEC)msa_dec; + snd->decend = msa_decend; + snd->snd = (void *)coef; + + p = (UINT8 *)(info + 1); + do { + coef->Coef1 = LOADINTELWORD(p + 0); + coef->Coef2 = LOADINTELWORD(p + 2); + coef++; + p += 4; + } while(--numcoef); + return(SUCCESS); + +msaopn_err: + return(FAILURE); +} + + +// ---- IMA + +#define IMA_MAXSTEP 89 + +static BOOL ima_init = FALSE; +static UINT8 ima_statetbl[IMA_MAXSTEP][8]; + +static const int ima_stateadj[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; + +static const int ima_steptable[IMA_MAXSTEP] = { + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, + 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, + 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, + 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, + 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, + 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, + 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493,10442, + 11487,12635,13899,15289,16818,18500,20350,22385,24623,27086,29794,32767}; + +static void ima_inittable(void) { + + int i, j, k; + + for (i=0; i= IMA_MAXSTEP) { + k = IMA_MAXSTEP - 1; + } + ima_statetbl[i][j] = (UINT8)k; + } + } +} + +static UINT ima_dec(GETSND snd, SINT16 *dst) { + + UINT c; + SINT32 val[2]; + int state[2]; + UINT8 *src; + UINT blk; + + if (snd->blocksize > snd->datsize) { + goto imadec_err; + } + src = snd->datptr; // ワーク使ってません。 + snd->datptr += snd->blocksize; + snd->datsize -= snd->blocksize; + + blk = snd->blocksamples; + for (c=0; cchannels; c++) { + SINT16 tmp; + tmp = LOADINTELWORD(src); + val[c] = tmp; + *dst++ = (SINT16)val[c]; + state[c] = src[2]; + if (state[c] >= IMA_MAXSTEP) { + state[c] = 0; + } + src += 4; + } + blk--; + + while(blk >= 8) { + blk -= 8; + for (c=0; cchannels; c++) { + UINT samp, r; + samp = 0; // for gcc + r = 8; + do { + int step, dp; + if (!(r & 1)) { + samp = *src++; + } + else { + samp >>= 4; + } + step = ima_steptable[state[c]]; + state[c] = ima_statetbl[state[c]][samp & 7]; + dp = ((((samp & 7) << 1) + 1) * step) >> 3; + if (!(samp & 8)) { + val[c] += dp; + if (val[c] > 32767) { + val[c] = 32767; + } + } + else { + val[c] -= dp; + if (val[c] < -32768) { + val[c] = -32768; + } + } + *dst = (SINT16)val[c]; + dst += snd->channels; + } while(--r); + dst -= (8 * snd->channels); + dst++; + } + dst += (7 * snd->channels); + } + return(snd->blocksamples); + +imadec_err: + return(0); +} + +static BRESULT ima_open(GETSND snd) { + + int blk; + + if (snd->bit != 4) { + goto imaopn_err; + } + blk = snd->blocksize; + blk /= snd->channels; + if (blk & 3) { + goto imaopn_err; + } + blk -= 4; // first block; + blk *= 2; + blk += 1; + snd->blocksamples = blk; + snd->bit = 16; + snd->dec = (GSDEC)ima_dec; + if (!ima_init) { + ima_init = TRUE; + ima_inittable(); + } + return(SUCCESS); + +imaopn_err: + return(FAILURE); +} + + +// ---- MP3 + +#if defined(SUPPORT_MP3) +extern BOOL __mp3_open(GETSND snd, UINT8 *ptr, UINT size); +#endif + + +// ---- + +BRESULT getwave_open(GETSND snd, UINT8 *ptr, UINT size) { + + RIFF_HEADER *riff; + WAVE_HEADER *head; + WAVE_INFOS *info; + UINT pos; + UINT format; + BRESULT r; + UINT headsize = 0; + UINT datasize; + + info = NULL; // for gcc + + // RIFFのチェック + riff = (RIFF_HEADER *)ptr; + pos = sizeof(RIFF_HEADER); + if (size < pos) { + TRACEOUT(("wav: error RIFF header")); + goto gwopn_err; + } + if (memcmp(riff->head, fmt_riff, 4)) { + TRACEOUT(("wav: error RIFF header")); + goto gwopn_err; + } + if (!memcmp(riff->fmt, fmt_wave, 4)) { + // フォーマットヘッダチェック + head = (WAVE_HEADER *)(ptr + pos); + pos += sizeof(WAVE_HEADER); + if (size < pos) { + TRACEOUT(("wav: error fmt header")); + goto gwopn_err; + } + if (memcmp(head->head, chunk_fmt, 4)) { + TRACEOUT(("wav: error fmt header")); + goto gwopn_err; + } + headsize = LOADINTELDWORD(head->size); + if (headsize < sizeof(WAVE_INFOS)) { + TRACEOUT(("wav: error fmt length")); + goto gwopn_err; + } + + // フォーマットチェック + info = (WAVE_INFOS *)(ptr + pos); + pos += headsize; + if (size < pos) { + TRACEOUT(("wav: error fmt data")); + goto gwopn_err; + } + format = LOADINTELWORD(info->format); + snd->channels = LOADINTELWORD(info->channel); + snd->samplingrate = LOADINTELDWORD(info->rate); + snd->blocksize = LOADINTELWORD(info->block); + snd->bit = LOADINTELWORD(info->bit); + TRACEOUT(("wav: fmt: %x / %dch %dHz %dbit", + format, snd->channels, snd->samplingrate, snd->bit)); + if ((UINT)(snd->channels - 1) >= 2) { + TRACEOUT(("wav: channels err")); + goto gwopn_err; + } + } + else if (!memcmp(riff->fmt, fmt_rmp3, 4)) { + format = 0x55; + } + else { + TRACEOUT(("wav: error WAVE header")); + goto gwopn_err; + } + + // dataまで移動。 + while(1) { + head = (WAVE_HEADER *)(ptr + pos); + pos += sizeof(WAVE_HEADER); + if (size < pos) { + TRACEOUT(("wav: error data header")); + goto gwopn_err; + } + if (!memcmp(head->head, chunk_data, 4)) { + break; + } + pos += LOADINTELDWORD(head->size); + } + ptr += pos; + size -= pos; + datasize = LOADINTELDWORD(head->size); + size = MIN(size, datasize); + + switch(format) { + case 0x01: // PCM + r = pcm_open(snd); + break; + + case 0x02: + r = msa_open(snd, info, headsize); + break; + + case 0x11: + r = ima_open(snd); + break; + +#if defined(SUPPORT_MP3) + case 0x55: + return(__mp3_open(snd, ptr, size)); +#endif + +#if defined(SUPPORT_OGG) + case 0x6751: + return(getogg_open(snd, ptr, size)); +#endif + + default: + r = FAILURE; + break; + } + if (r != SUCCESS) { + TRACEOUT(("wav: decord open error")); + goto gwopn_err; + } + + // 登録〜 + snd->datptr = ptr; + snd->datsize = size; + return(SUCCESS); + +gwopn_err: + return(FAILURE); +} + diff --git a/sound/mamebsdsub/np2compatible.cpp b/sound/mamebsdsub/np2compatible.cpp index 6b13fef6..52767d44 100644 --- a/sound/mamebsdsub/np2compatible.cpp +++ b/sound/mamebsdsub/np2compatible.cpp @@ -14,7 +14,7 @@ #include "np2ymfm.h" - // np21wƂ̃Xe[gZ[u݊ێ@V̂݌݊ + // 旧np21wとのステートセーブ互換を維持する 旧→新のみ互換 #include "np2compatible.h" #if defined(INTPTR_MAX) && defined(INT64_MAX) @@ -25,8 +25,8 @@ #define IS_64BIT #endif -// Xe[gZ[uf[^̃TCYʒuȂ -// 64bit +// ステートセーブデータのサイズや位置など +// 64bit版 #define NP2REV97OPL_64_SAVESIZE 14344 #define NP2REV97OPL_64_CHSIZE 528 #define NP2REV97OPL_64_SLOTSIZE 136 @@ -50,7 +50,7 @@ #define NP2REV97OPL_64_OFS_SL 64 #define NP2REV97OPL_64_OFS_RR 8 #define NP2REV97OPL_64_OFS_WS 101 -// 32bit +// 32bit版 #define NP2REV97OPL_32_SAVESIZE 14032 #define NP2REV97OPL_32_CHSIZE 512 #define NP2REV97OPL_32_SLOTSIZE 128 @@ -151,13 +151,13 @@ int YMF262FlagLoad_NP2REV97(opl3bsd* chipbsd, void* srcbuf, int size) { NP2REV97OPL_OFS_WS = NP2REV97OPL_32_OFS_WS; } else { - return 0; // + return 0; // 無効 } ymfm::ymf262& chipcore = chipbsd->m_chip->GetChip(); - // WX^փZbgĂ - // Expansion Register Set@ɂݒ肵ĂȂhĩZbgoȂ̂Őɐݒ + // レジスタへセットしていく + // Expansion Register Set 先にこれを設定しておかないとhiのセットが出来ないので先に設定 chipcore.write_address_hi(0x5); chipcore.write_data( (*(UINT8*)((char*)srcbuf + NP2REV97OPL_OFS_EXREG) ? 0x01 : 0) diff --git a/sound/mamebsdsub/np2interop.cpp b/sound/mamebsdsub/np2interop.cpp index 38ac7aa2..7fa71219 100644 --- a/sound/mamebsdsub/np2interop.cpp +++ b/sound/mamebsdsub/np2interop.cpp @@ -13,7 +13,7 @@ #include "np2ymfm.h" - // np21wƂ̃Xe[gZ[u݊ێ@V̂݌݊ + // 旧np21wとのステートセーブ互換を維持する 旧→新のみ互換 #include "np2compatible.h" void* YMF262Init(int clock, int rate) @@ -71,7 +71,7 @@ int YMF262Write(void* chipptr, int a, int v) chipcore.write(a, v); - // ^C}[ + // 仮実装タイマー if (a == 0) { chipbsd->m_data.reg_addr = v; @@ -143,17 +143,17 @@ unsigned char YMF262Read(void* chipptr, int a) opl3bsd* chipbsd = (opl3bsd*)chipptr; ymfm::ymf262& chipcore = chipbsd->m_chip->GetChip(); - // ^C}[ |[gĂ񂾂Ƃɔ肷i荞ݔȂǂ͂Ȃj + // 仮実装タイマー ポートを呼んだときに判定する(割り込み発生などはしない) if (chipbsd->m_data.timer_valid[0] && !(chipbsd->m_data.reg_timerctrl & 0x40)) { if (chipbsd->m_data.timer_intr[0]) { - // Ĕsv 荞݂ĂĂ + // 再判定不要 割り込みも立てておく tmr |= 0xc0; } else if (CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK - chipbsd->m_data.timer_startclock[0] >= pccore.realclock / 1000 * (256 - chipbsd->m_data.reg_timer1) * 808 / 10000) { - // Ԍo߂@\ 80.8 usec + // 時間経過した 分解能は 80.8 usec chipbsd->m_data.timer_intr[0] = true; tmr |= 0xc0; } @@ -162,12 +162,12 @@ unsigned char YMF262Read(void* chipptr, int a) { if (chipbsd->m_data.timer_intr[1]) { - // Ĕsv 荞݂ĂĂ + // 再判定不要 割り込みも立てておく tmr |= 0xa0; } else if (CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK - chipbsd->m_data.timer_startclock[1] >= pccore.realclock / 1000 * (256 - chipbsd->m_data.reg_timer1) * 3231 / 10000) { - // Ԍo߂@\ 323.1 usec + // 時間経過した 分解能は 323.1 usec chipbsd->m_data.timer_intr[1] = true; tmr |= 0xa0; } @@ -183,7 +183,7 @@ int YMF262FlagSave(void* chipptr, void* dstbuf) opl3bsd* chipbsd = (opl3bsd*)chipptr; ymfm::ymf262& chipcore = chipbsd->m_chip->GetChip(); - // ۑ + // 保存 std::vector buffer; ymfm::ymfm_saved_state saver(buffer, true); chipcore.save_restore(saver); @@ -204,30 +204,30 @@ int YMF262FlagLoad(void* chipptr, void* srcbuf, int size) if (srcbuf == NULL) return 0; - // obt@TCY擾 + // バッファサイズを取得 std::vector dummybuffer; ymfm::ymfm_saved_state saver(dummybuffer, true); chipcore.save_restore(saver); const int fmbufsize = dummybuffer.size(); dummybuffer.insert(dummybuffer.end(), (uint8_t*)&chipbsd->m_data, (uint8_t*)(&chipbsd->m_data + 1)); - // obt@TCYĂȂĂʂ + // バッファサイズがあっていなくても通す if (size != dummybuffer.size()) { // reset chipcore.reset(); - // Ō݊ێp@݊[hs‚Ȃ0Ԃ + // 旧版互換維持用 互換ロード不可なら0を返す const int ret = YMF262FlagLoad_NP2REV97(chipbsd, srcbuf, size); if (ret) return ret; return dummybuffer.size(); } - // f[^ǂݎobt@֑ + // データ読み取りバッファへ送る std::vector buffer; buffer.insert(buffer.end(), (uint8_t*)srcbuf, (uint8_t*)srcbuf + fmbufsize); - // s + // 復元実行 ymfm::ymfm_saved_state restorer(buffer, false); chipcore.save_restore(restorer); memcpy(&chipbsd->m_data, (uint8_t*)srcbuf + fmbufsize, sizeof(chipbsd->m_data)); diff --git a/sound/mamebsdsub/np2ymfm.h b/sound/mamebsdsub/np2ymfm.h index dd2f531d..265a643d 100644 --- a/sound/mamebsdsub/np2ymfm.h +++ b/sound/mamebsdsub/np2ymfm.h @@ -33,7 +33,7 @@ typedef struct { double fmcounter_rem; INT16 lastsample[4]; - // ^C}[@ɂNEVENTgׂH + // 仮実装タイマー 正式にはNEVENTを使うべき? UINT8 reg_addr; UINT8 reg_timer1; UINT8 reg_timer2; diff --git a/sound/opl3.c b/sound/opl3.c old mode 100755 new mode 100644 index 9b7d2e6b..6edd9358 --- a/sound/opl3.c +++ b/sound/opl3.c @@ -1,313 +1,313 @@ -/** - * @file opl3.c - * @brief Implementation of OPL3 - */ - -#include -#include "opl3.h" -#include -#include - -static void writeRegister(POPL3 opl3, UINT nAddress, REG8 cData); -static void writeExtendedRegister(POPL3 opl3, UINT nAddress, REG8 cData); - -/** - * Initialize instance - * @param[in] opl3 The instance - */ -void opl3_construct(POPL3 opl3) -{ - memset(opl3, 0, sizeof(*opl3)); -} - -/** - * Deinitialize instance - * @param[in] opl3 The instance - */ -void opl3_destruct(POPL3 opl3) -{ -} - -/** - * Reset - * @param[in] opl3 The instance - * @param[in] cCaps - */ -void opl3_reset(POPL3 opl3, REG8 cCaps) -{ - UINT i; - - memset(&opl3->s, 0, sizeof(opl3->s)); - opl3->s.cCaps = cCaps; - for (i = 0; i < 2; i++) - { - memset(opl3->s.reg + (i * 0x100) + 0x20, 0xff, 0x80); - } -} - -/** - * Restore - * @param[in] opl3 The instance - */ -static void restore(POPL3 opl3) -{ - UINT i; - - writeExtendedRegister(opl3, 0x05, opl3->s.reg[0x105]); - writeExtendedRegister(opl3, 0x04, opl3->s.reg[0x104]); - writeExtendedRegister(opl3, 0x08, opl3->s.reg[0x108]); - - for (i = 0x20; i < 0x100; i++) - { - if (((i & 0xe0) == 0xa0) || ((i & 0xe0) == 0xc0)) - { - continue; - } - if (((i & 0x1f) >= 0x18) || ((i & 0x07) >= 0x06)) - { - continue; - } - writeRegister(opl3, i, opl3->s.reg[i]); - writeExtendedRegister(opl3, i, opl3->s.reg[i + 0x100]); - } - for (i = 0xa0; i < 0xa9; i++) - { - writeRegister(opl3, i, opl3->s.reg[i]); - writeRegister(opl3, i + 0x10, (REG8)(opl3->s.reg[i + 0x10] & 0xdf)); - writeRegister(opl3, i + 0x20, opl3->s.reg[i + 0x20]); - writeExtendedRegister(opl3, i, opl3->s.reg[i + 0x100]); - writeExtendedRegister(opl3, i + 0x10, (REG8)(opl3->s.reg[i + 0x110] & 0xdf)); - writeExtendedRegister(opl3, i + 0x20, opl3->s.reg[i + 0x120]); - } - writeExtendedRegister(opl3, 0xbd, opl3->s.reg[0xbd]); -} - -/** - * Bind - * @param[in] opl3 The instance - */ -void opl3_bind(POPL3 opl3) -{ - UINT nBaseClock = 3579545; - UINT8 cCaps = opl3->s.cCaps; - - nBaseClock = (cCaps & OPL3_HAS_OPL3) ? 3579545 : 3993600; - - oplgen_reset(&opl3->oplgen, nBaseClock); - sound_streamregist(&opl3->oplgen, (SOUNDCB)oplgen_getpcm); - - restore(opl3); - - keydisp_bindopl3(opl3->s.reg, (cCaps & OPL3_HAS_OPL3) ? 18 : 9, nBaseClock); -} - -/** - * Status - * @param[in] opl3 The instance - * @return Status - */ -REG8 opl3_readStatus(POPL3 opl3) -{ - return 0; -} - -/** - * Writes register - * @param[in] opl3 The instance - * @param[in] nAddress The address - * @param[in] cData The data - */ -void opl3_writeRegister(POPL3 opl3, UINT nAddress, REG8 cData) -{ - opl3->s.reg[nAddress] = cData; - writeRegister(opl3, nAddress, cData); -} - -/** - * Writes register (Inner) - * @param[in] opl3 The instance - * @param[in] nAddress The address - * @param[in] cData The data - */ -static void writeRegister(POPL3 opl3, UINT nAddress, REG8 cData) -{ - const UINT8 cCaps = opl3->s.cCaps; - - switch (nAddress & 0xe0) - { - case 0x20: - case 0x40: - case 0x60: - case 0x80: - if (((nAddress & 0x1f) >= 0x18) || ((nAddress & 7) >= 6)) - { - return; - } - break; - - case 0xa0: - if (nAddress == 0xbd) - { - break; - } - if ((nAddress & 0x0f) >= 9) - { - return; - } - if (nAddress & 0x10) - { - keydisp_opl3keyon(opl3->s.reg, (REG8)(nAddress & 0x0f), cData); - } - break; - - case 0xc0: - if ((nAddress & 0x1f) >= 9) - { - return; - } - if (!(cCaps & OPL3_HAS_OPL3)) - { - cData |= 0x30; - } - break; - - case 0xe0: - if (!(cCaps & OPL3_HAS_OPL2)) - { - return; - } - if (((nAddress & 0x1f) >= 0x18) || ((nAddress & 7) >= 6)) - { - return; - } - break; - - default: - return; - } - - sound_sync(); - oplgen_setreg(&opl3->oplgen, nAddress, cData); -} - -/** - * Writes extended register - * @param[in] opl3 The instance - * @param[in] nAddress The address - * @param[in] cData The data - */ -void opl3_writeExtendedRegister(POPL3 opl3, UINT nAddress, REG8 cData) -{ - opl3->s.reg[nAddress + 0x100] = cData; - writeExtendedRegister(opl3, nAddress, cData); -} - -/** - * Writes extended register (Inner) - * @param[in] opl3 The instance - * @param[in] nAddress The address - * @param[in] cData The data - */ -static void writeExtendedRegister(POPL3 opl3, UINT nAddress, REG8 cData) -{ - const UINT8 cCaps = opl3->s.cCaps; - - if (!(cCaps & OPL3_HAS_OPL3)) - { - return; - } - - switch (nAddress & 0xe0) - { - case 0x20: - case 0x40: - case 0x60: - case 0x80: - case 0xe0: - if (((nAddress & 0x1f) >= 0x18) || ((nAddress & 7) >= 6)) - { - return; - } - break; - - case 0xa0: - if ((nAddress & 0x0f) >= 9) - { - return; - } - if (nAddress & 0x10) - { - keydisp_opl3keyon(opl3->s.reg, (REG8)((nAddress & 0x0f) + 9), cData); - } - break; - - case 0xc0: - if ((nAddress & 0x1f) >= 9) - { - return; - } - break; - - default: - if ((nAddress == 0x04) || (nAddress == 0x05) || (nAddress == 0x08)) - { - break; - } - return; - } - -#if 0 - sound_sync(); - oplgen_setreg(&opl3->oplgen, nAddress + 0x100, cData); -#endif -} - -/** - * Reads register - * @param[in] opl3 The instance - * @param[in] nAddress The address - * @return data - */ -REG8 opl3_readRegister(POPL3 opl3, UINT nAddress) -{ - return 0xff; -} - -/** - * Reads extended register - * @param[in] opl3 The instance - * @param[in] nAddress The address - * @return data - */ -REG8 opl3_readExtendedRegister(POPL3 opl3, UINT nAddress) -{ - return 0xff; -} - - - -// ---- statsave - -/** - * Save - * @param[in] opl3 The instance - * @param[in] sfh The handle of statsave - * @param[in] tbl The item of statsave - * @return Error - */ -int opl3_sfsave(PCOPL3 opl3, STFLAGH sfh, const SFENTRY *tbl) -{ - return statflag_write(sfh, &opl3->s, sizeof(opl3->s)); -} - -/** - * Load - * @param[in] opl3 The instance - * @param[in] sfh The handle of statsave - * @param[in] tbl The item of statsave - * @return Error - */ -int opl3_sfload(POPL3 opl3, STFLAGH sfh, const SFENTRY *tbl) -{ - return statflag_read(sfh, &opl3->s, sizeof(opl3->s)); -} +/** + * @file opl3.c + * @brief Implementation of OPL3 + */ + +#include +#include "opl3.h" +#include +#include + +static void writeRegister(POPL3 opl3, UINT nAddress, REG8 cData); +static void writeExtendedRegister(POPL3 opl3, UINT nAddress, REG8 cData); + +/** + * Initialize instance + * @param[in] opl3 The instance + */ +void opl3_construct(POPL3 opl3) +{ + memset(opl3, 0, sizeof(*opl3)); +} + +/** + * Deinitialize instance + * @param[in] opl3 The instance + */ +void opl3_destruct(POPL3 opl3) +{ +} + +/** + * Reset + * @param[in] opl3 The instance + * @param[in] cCaps + */ +void opl3_reset(POPL3 opl3, REG8 cCaps) +{ + UINT i; + + memset(&opl3->s, 0, sizeof(opl3->s)); + opl3->s.cCaps = cCaps; + for (i = 0; i < 2; i++) + { + memset(opl3->s.reg + (i * 0x100) + 0x20, 0xff, 0x80); + } +} + +/** + * Restore + * @param[in] opl3 The instance + */ +static void restore(POPL3 opl3) +{ + UINT i; + + writeExtendedRegister(opl3, 0x05, opl3->s.reg[0x105]); + writeExtendedRegister(opl3, 0x04, opl3->s.reg[0x104]); + writeExtendedRegister(opl3, 0x08, opl3->s.reg[0x108]); + + for (i = 0x20; i < 0x100; i++) + { + if (((i & 0xe0) == 0xa0) || ((i & 0xe0) == 0xc0)) + { + continue; + } + if (((i & 0x1f) >= 0x18) || ((i & 0x07) >= 0x06)) + { + continue; + } + writeRegister(opl3, i, opl3->s.reg[i]); + writeExtendedRegister(opl3, i, opl3->s.reg[i + 0x100]); + } + for (i = 0xa0; i < 0xa9; i++) + { + writeRegister(opl3, i, opl3->s.reg[i]); + writeRegister(opl3, i + 0x10, (REG8)(opl3->s.reg[i + 0x10] & 0xdf)); + writeRegister(opl3, i + 0x20, opl3->s.reg[i + 0x20]); + writeExtendedRegister(opl3, i, opl3->s.reg[i + 0x100]); + writeExtendedRegister(opl3, i + 0x10, (REG8)(opl3->s.reg[i + 0x110] & 0xdf)); + writeExtendedRegister(opl3, i + 0x20, opl3->s.reg[i + 0x120]); + } + writeExtendedRegister(opl3, 0xbd, opl3->s.reg[0xbd]); +} + +/** + * Bind + * @param[in] opl3 The instance + */ +void opl3_bind(POPL3 opl3) +{ + UINT nBaseClock = 3579545; + UINT8 cCaps = opl3->s.cCaps; + + nBaseClock = (cCaps & OPL3_HAS_OPL3) ? 3579545 : 3993600; + + oplgen_reset(&opl3->oplgen, nBaseClock); + sound_streamregist(&opl3->oplgen, (SOUNDCB)oplgen_getpcm); + + restore(opl3); + + keydisp_bindopl3(opl3->s.reg, (cCaps & OPL3_HAS_OPL3) ? 18 : 9, nBaseClock); +} + +/** + * Status + * @param[in] opl3 The instance + * @return Status + */ +REG8 opl3_readStatus(POPL3 opl3) +{ + return 0; +} + +/** + * Writes register + * @param[in] opl3 The instance + * @param[in] nAddress The address + * @param[in] cData The data + */ +void opl3_writeRegister(POPL3 opl3, UINT nAddress, REG8 cData) +{ + opl3->s.reg[nAddress] = cData; + writeRegister(opl3, nAddress, cData); +} + +/** + * Writes register (Inner) + * @param[in] opl3 The instance + * @param[in] nAddress The address + * @param[in] cData The data + */ +static void writeRegister(POPL3 opl3, UINT nAddress, REG8 cData) +{ + const UINT8 cCaps = opl3->s.cCaps; + + switch (nAddress & 0xe0) + { + case 0x20: + case 0x40: + case 0x60: + case 0x80: + if (((nAddress & 0x1f) >= 0x18) || ((nAddress & 7) >= 6)) + { + return; + } + break; + + case 0xa0: + if (nAddress == 0xbd) + { + break; + } + if ((nAddress & 0x0f) >= 9) + { + return; + } + if (nAddress & 0x10) + { + keydisp_opl3keyon(opl3->s.reg, (REG8)(nAddress & 0x0f), cData); + } + break; + + case 0xc0: + if ((nAddress & 0x1f) >= 9) + { + return; + } + if (!(cCaps & OPL3_HAS_OPL3)) + { + cData |= 0x30; + } + break; + + case 0xe0: + if (!(cCaps & OPL3_HAS_OPL2)) + { + return; + } + if (((nAddress & 0x1f) >= 0x18) || ((nAddress & 7) >= 6)) + { + return; + } + break; + + default: + return; + } + + sound_sync(); + oplgen_setreg(&opl3->oplgen, nAddress, cData); +} + +/** + * Writes extended register + * @param[in] opl3 The instance + * @param[in] nAddress The address + * @param[in] cData The data + */ +void opl3_writeExtendedRegister(POPL3 opl3, UINT nAddress, REG8 cData) +{ + opl3->s.reg[nAddress + 0x100] = cData; + writeExtendedRegister(opl3, nAddress, cData); +} + +/** + * Writes extended register (Inner) + * @param[in] opl3 The instance + * @param[in] nAddress The address + * @param[in] cData The data + */ +static void writeExtendedRegister(POPL3 opl3, UINT nAddress, REG8 cData) +{ + const UINT8 cCaps = opl3->s.cCaps; + + if (!(cCaps & OPL3_HAS_OPL3)) + { + return; + } + + switch (nAddress & 0xe0) + { + case 0x20: + case 0x40: + case 0x60: + case 0x80: + case 0xe0: + if (((nAddress & 0x1f) >= 0x18) || ((nAddress & 7) >= 6)) + { + return; + } + break; + + case 0xa0: + if ((nAddress & 0x0f) >= 9) + { + return; + } + if (nAddress & 0x10) + { + keydisp_opl3keyon(opl3->s.reg, (REG8)((nAddress & 0x0f) + 9), cData); + } + break; + + case 0xc0: + if ((nAddress & 0x1f) >= 9) + { + return; + } + break; + + default: + if ((nAddress == 0x04) || (nAddress == 0x05) || (nAddress == 0x08)) + { + break; + } + return; + } + +#if 0 + sound_sync(); + oplgen_setreg(&opl3->oplgen, nAddress + 0x100, cData); +#endif +} + +/** + * Reads register + * @param[in] opl3 The instance + * @param[in] nAddress The address + * @return data + */ +REG8 opl3_readRegister(POPL3 opl3, UINT nAddress) +{ + return 0xff; +} + +/** + * Reads extended register + * @param[in] opl3 The instance + * @param[in] nAddress The address + * @return data + */ +REG8 opl3_readExtendedRegister(POPL3 opl3, UINT nAddress) +{ + return 0xff; +} + + + +// ---- statsave + +/** + * Save + * @param[in] opl3 The instance + * @param[in] sfh The handle of statsave + * @param[in] tbl The item of statsave + * @return Error + */ +int opl3_sfsave(PCOPL3 opl3, STFLAGH sfh, const SFENTRY *tbl) +{ + return statflag_write(sfh, &opl3->s, sizeof(opl3->s)); +} + +/** + * Load + * @param[in] opl3 The instance + * @param[in] sfh The handle of statsave + * @param[in] tbl The item of statsave + * @return Error + */ +int opl3_sfload(POPL3 opl3, STFLAGH sfh, const SFENTRY *tbl) +{ + return statflag_read(sfh, &opl3->s, sizeof(opl3->s)); +} diff --git a/sound/opl3.h b/sound/opl3.h old mode 100755 new mode 100644 index b7a9665a..c36fc024 --- a/sound/opl3.h +++ b/sound/opl3.h @@ -1,77 +1,77 @@ -/** - * @file opl3.h - * @brief Interface of OPL3 - */ - -#pragma once - -#include "oplgen.h" -#include - -/** - * Chips flags - */ -enum -{ - OPL3_HAS_TIMER = 0x01, /*!< Has timer */ - OPL3_HAS_OPL = 0x02, /*!< Has OPL */ - OPL3_HAS_OPL2 = 0x04, /*!< Has OPL2 */ - OPL3_HAS_OPL3 = 0x08, /*!< Has OPL3 */ - OPL3_HAS_OPL3L = 0x10, /*!< Has OPL3-L */ - OPL3_HAS_8950ADPCM = 0x20, /*!< Has 8950 ADPCM */ - - OPL3_MODE_8950 = OPL3_HAS_OPL | OPL3_HAS_8950ADPCM, - OPL3_MODE_3812 = OPL3_HAS_OPL | OPL3_HAS_OPL2, - OPL3_MODE_262 = OPL3_HAS_OPL | OPL3_HAS_OPL2 | OPL3_HAS_OPL3 -}; - -/** - * @brief opl3 - */ -struct tagOpl3State -{ - UINT8 addrl; - UINT8 addrh; - UINT8 data; - UINT8 cCaps; - UINT8 reg[0x200]; -}; - -/** - * @brief opl3 - */ -struct tagOpl3 -{ - struct tagOpl3State s; - INTPTR userdata; - _OPLGEN oplgen; -}; - -typedef struct tagOpl3 OPL3; -typedef struct tagOpl3* POPL3; -typedef const struct tagOpl3* PCOPL3; - -#ifdef __cplusplus -extern "C" -{ -#endif - -void opl3_construct(POPL3 opl3); -void opl3_destruct(POPL3 opl3); -void opl3_reset(POPL3 opl3, REG8 cCaps); -void opl3_bind(POPL3 opl3); - -REG8 opl3_readStatus(POPL3 opl3); - -void opl3_writeRegister(POPL3 opl3, UINT nAddress, REG8 cData); -void opl3_writeExtendedRegister(POPL3 opl3, UINT nAddress, REG8 cData); - -REG8 opl3_readRegister(POPL3 opl3, UINT nAddress); -REG8 opl3_readExtendedRegister(POPL3 opl3, UINT nAddress); - -int opl3_sfsave(PCOPL3 opl3, STFLAGH sfh, const SFENTRY *tbl); -int opl3_sfload(POPL3 opl3, STFLAGH sfh, const SFENTRY *tbl); - -#ifdef __cplusplus -} -#endif +/** + * @file opl3.h + * @brief Interface of OPL3 + */ + +#pragma once + +#include "oplgen.h" +#include + +/** + * Chips flags + */ +enum +{ + OPL3_HAS_TIMER = 0x01, /*!< Has timer */ + OPL3_HAS_OPL = 0x02, /*!< Has OPL */ + OPL3_HAS_OPL2 = 0x04, /*!< Has OPL2 */ + OPL3_HAS_OPL3 = 0x08, /*!< Has OPL3 */ + OPL3_HAS_OPL3L = 0x10, /*!< Has OPL3-L */ + OPL3_HAS_8950ADPCM = 0x20, /*!< Has 8950 ADPCM */ + + OPL3_MODE_8950 = OPL3_HAS_OPL | OPL3_HAS_8950ADPCM, + OPL3_MODE_3812 = OPL3_HAS_OPL | OPL3_HAS_OPL2, + OPL3_MODE_262 = OPL3_HAS_OPL | OPL3_HAS_OPL2 | OPL3_HAS_OPL3 +}; + +/** + * @brief opl3 + */ +struct tagOpl3State +{ + UINT8 addrl; + UINT8 addrh; + UINT8 data; + UINT8 cCaps; + UINT8 reg[0x200]; +}; + +/** + * @brief opl3 + */ +struct tagOpl3 +{ + struct tagOpl3State s; + INTPTR userdata; + _OPLGEN oplgen; +}; + +typedef struct tagOpl3 OPL3; +typedef struct tagOpl3* POPL3; +typedef const struct tagOpl3* PCOPL3; + +#ifdef __cplusplus +extern "C" +{ +#endif + +void opl3_construct(POPL3 opl3); +void opl3_destruct(POPL3 opl3); +void opl3_reset(POPL3 opl3, REG8 cCaps); +void opl3_bind(POPL3 opl3); + +REG8 opl3_readStatus(POPL3 opl3); + +void opl3_writeRegister(POPL3 opl3, UINT nAddress, REG8 cData); +void opl3_writeExtendedRegister(POPL3 opl3, UINT nAddress, REG8 cData); + +REG8 opl3_readRegister(POPL3 opl3, UINT nAddress); +REG8 opl3_readExtendedRegister(POPL3 opl3, UINT nAddress); + +int opl3_sfsave(PCOPL3 opl3, STFLAGH sfh, const SFENTRY *tbl); +int opl3_sfload(POPL3 opl3, STFLAGH sfh, const SFENTRY *tbl); + +#ifdef __cplusplus +} +#endif diff --git a/sound/oplgen.h b/sound/oplgen.h old mode 100755 new mode 100644 index cb59bd2c..2e95abd1 --- a/sound/oplgen.h +++ b/sound/oplgen.h @@ -1,85 +1,85 @@ -/** - * @file oplgen.h - * @brief Interface of the OPL generator - */ - -#pragma once - -#include - -enum -{ - OPLCH_MAX = 9, - OPL_CLOCK = 3579545, -}; - -typedef struct -{ - SINT32 totallevel; /* total level */ - SINT32 totallevel2; /* total level */ - SINT32 decaylevel; /* decay level */ -const SINT32 *attack; /* attack ratio */ -const SINT32 *decay1; /* decay1 ratio */ -const SINT32 *release; /* release ratio */ - SINT32 freq_cnt; /* frequency count */ - SINT32 freq_inc; /* frequency step */ - UINT8 multiple; /* multiple */ - UINT8 mode; - UINT8 keyscalelevel; /* key scale */ - UINT8 keyscalerate; /* key scale */ - UINT8 env_mode; /* envelope mode */ - UINT8 envratio; /* envelope ratio */ - - SINT32 env_cnt; /* envelope count */ - SINT32 env_end; /* envelope end count */ - SINT32 env_inc; /* envelope step */ - SINT32 env_inc_attack; /* envelope attack step */ - SINT32 env_inc_decay1; /* envelope decay1 step */ - SINT32 env_inc_release; /* envelope release step */ - - SINT32* sintable; /* sin */ -} OPLSLOT; - -typedef struct -{ - OPLSLOT slot[2]; - UINT8 algorithm; /* algorithm */ - UINT8 feedback; /* self feedback */ - UINT8 playing; - UINT8 kcode; /* key code */ - SINT32 op1fb; /* operator1 feedback */ - SINT32 *connect1; /* operator1 connect */ - SINT32 *connect2; /* operator2 connect */ - UINT blkfnum; /* block and fnumber */ - UINT32 keynote; /* key note */ - UINT32 kslbase; -} OPLCH; - -typedef struct -{ - UINT playing; - UINT8 rhythm; - SINT32 feedback2; - SINT32 outdc; - SINT32 calcremain; - UINT noise; - SINT32 calc1024; - OPLCH oplch[OPLCH_MAX]; -} _OPLGEN, *OPLGEN; - -#ifdef __cplusplus -extern "C" -{ -#endif - -void oplgen_initialize(UINT rate); -void oplgen_setvol(UINT vol); - -void oplgen_reset(OPLGEN oplgen, UINT nBaseClock); -void oplgen_setreg(OPLGEN oplgen, UINT reg, REG8 value); - -void SOUNDCALL oplgen_getpcm(OPLGEN oplgen, SINT32 *buf, UINT count); - -#ifdef __cplusplus -} -#endif +/** + * @file oplgen.h + * @brief Interface of the OPL generator + */ + +#pragma once + +#include + +enum +{ + OPLCH_MAX = 9, + OPL_CLOCK = 3579545, +}; + +typedef struct +{ + SINT32 totallevel; /* total level */ + SINT32 totallevel2; /* total level */ + SINT32 decaylevel; /* decay level */ +const SINT32 *attack; /* attack ratio */ +const SINT32 *decay1; /* decay1 ratio */ +const SINT32 *release; /* release ratio */ + SINT32 freq_cnt; /* frequency count */ + SINT32 freq_inc; /* frequency step */ + UINT8 multiple; /* multiple */ + UINT8 mode; + UINT8 keyscalelevel; /* key scale */ + UINT8 keyscalerate; /* key scale */ + UINT8 env_mode; /* envelope mode */ + UINT8 envratio; /* envelope ratio */ + + SINT32 env_cnt; /* envelope count */ + SINT32 env_end; /* envelope end count */ + SINT32 env_inc; /* envelope step */ + SINT32 env_inc_attack; /* envelope attack step */ + SINT32 env_inc_decay1; /* envelope decay1 step */ + SINT32 env_inc_release; /* envelope release step */ + + SINT32* sintable; /* sin */ +} OPLSLOT; + +typedef struct +{ + OPLSLOT slot[2]; + UINT8 algorithm; /* algorithm */ + UINT8 feedback; /* self feedback */ + UINT8 playing; + UINT8 kcode; /* key code */ + SINT32 op1fb; /* operator1 feedback */ + SINT32 *connect1; /* operator1 connect */ + SINT32 *connect2; /* operator2 connect */ + UINT blkfnum; /* block and fnumber */ + UINT32 keynote; /* key note */ + UINT32 kslbase; +} OPLCH; + +typedef struct +{ + UINT playing; + UINT8 rhythm; + SINT32 feedback2; + SINT32 outdc; + SINT32 calcremain; + UINT noise; + SINT32 calc1024; + OPLCH oplch[OPLCH_MAX]; +} _OPLGEN, *OPLGEN; + +#ifdef __cplusplus +extern "C" +{ +#endif + +void oplgen_initialize(UINT rate); +void oplgen_setvol(UINT vol); + +void oplgen_reset(OPLGEN oplgen, UINT nBaseClock); +void oplgen_setreg(OPLGEN oplgen, UINT reg, REG8 value); + +void SOUNDCALL oplgen_getpcm(OPLGEN oplgen, SINT32 *buf, UINT count); + +#ifdef __cplusplus +} +#endif diff --git a/sound/oplgenc.c b/sound/oplgenc.c index 23305b2d..0bc31f95 100644 --- a/sound/oplgenc.c +++ b/sound/oplgenc.c @@ -1,576 +1,576 @@ -/** - * @file oplgenc.c - * @brief Implementation of the OPL generator - */ - -#include -#include "oplgen.h" -#include -#include "oplgencfg.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846264338327 -#endif - - OPLCFG oplcfg; - -#define OPM_ARRATE 399128L -#define OPM_DRRATE 5514396L - -#define EG_STEP (96.0 / EVC_ENT) /* dB step */ -#define SC(db) (SINT32)((db) * ((3.0 / EG_STEP) * (1 << ENV_BITS))) + EC_DECAY - -static SINT32 attacktable[94]; -static SINT32 decaytable[94]; - -static const SINT32 decayleveltable[16] = { - SC( 0),SC( 1),SC( 2),SC( 3),SC( 4),SC( 5),SC( 6),SC( 7), - SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)}; -static const UINT8 multipletable[] = { - 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30}; -static const SINT32 nulltable[] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -#define DV(db) (UINT32)((db) / (0.1875 / 2.0)) -static const UINT32 ksl_tab[8 * 16]= -{ - /* OCT 0 */ - DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), - DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), - DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), - DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), - /* OCT 1 */ - DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), - DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), - DV( 0.000),DV( 0.750),DV( 1.125),DV( 1.500), - DV( 1.875),DV( 2.250),DV( 2.625),DV( 3.000), - /* OCT 2 */ - DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), - DV( 0.000),DV( 1.125),DV( 1.875),DV( 2.625), - DV( 3.000),DV( 3.750),DV( 4.125),DV( 4.500), - DV( 4.875),DV( 5.250),DV( 5.625),DV( 6.000), - /* OCT 3 */ - DV( 0.000),DV( 0.000),DV( 0.000),DV( 1.875), - DV( 3.000),DV( 4.125),DV( 4.875),DV( 5.625), - DV( 6.000),DV( 6.750),DV( 7.125),DV( 7.500), - DV( 7.875),DV( 8.250),DV( 8.625),DV( 9.000), - /* OCT 4 */ - DV( 0.000),DV( 0.000),DV( 3.000),DV( 4.875), - DV( 6.000),DV( 7.125),DV( 7.875),DV( 8.625), - DV( 9.000),DV( 9.750),DV(10.125),DV(10.500), - DV(10.875),DV(11.250),DV(11.625),DV(12.000), - /* OCT 5 */ - DV( 0.000),DV( 3.000),DV( 6.000),DV( 7.875), - DV( 9.000),DV(10.125),DV(10.875),DV(11.625), - DV(12.000),DV(12.750),DV(13.125),DV(13.500), - DV(13.875),DV(14.250),DV(14.625),DV(15.000), - /* OCT 6 */ - DV( 0.000),DV( 6.000),DV( 9.000),DV(10.875), - DV(12.000),DV(13.125),DV(13.875),DV(14.625), - DV(15.000),DV(15.750),DV(16.125),DV(16.500), - DV(16.875),DV(17.250),DV(17.625),DV(18.000), - /* OCT 7 */ - DV( 0.000),DV( 9.000),DV(12.000),DV(13.875), - DV(15.000),DV(16.125),DV(16.875),DV(17.625), - DV(18.000),DV(18.750),DV(19.125),DV(19.500), - DV(19.875),DV(20.250),DV(20.625),DV(21.000) -}; - -void oplgen_initialize(UINT rate) -{ - UINT ratebit; - int i; -#if defined(OPLGEN_ENVSHIFT) - char sft; -#endif /* defined(OPLGEN_ENVSHIFT) */ - double pom; - double freq; - - if (rate > (OPL_CLOCK / 144.0)) - { - ratebit = 0; - } - else if (rate > (OPL_CLOCK / 288.0)) - { - ratebit = 1; - } - else - { - ratebit = 2; - } - - for (i = 0; i < EVC_ENT; i++) - { -#if defined(OPLGEN_ENVSHIFT) - sft = ENVTBL_BIT; - while (sft < (ENVTBL_BIT + 8)) - { - pom = (double)(1 << sft) / pow(10.0, EG_STEP * (EVC_ENT - i) / 20.0); - oplcfg.envtable[i] = (SINT32)pom; - oplcfg.envshift[i] = sft - TL_BITS; - if (oplcfg.envtable[i] >= (1 << (ENVTBL_BIT - 1))) - { - break; - } - sft++; - } -#else /* defined(OPLGEN_ENVSHIFT) */ - pom = (double)(1 << ENVTBL_BIT) / pow(10.0, EG_STEP * (EVC_ENT - i) / 20.0); - oplcfg.envtable[i] = (SINT32)pom; -#endif /* defined(OPLGEN_ENVSHIFT) */ - } - for (i = 0; i < SIN_ENT; i++) - { - pom = (double)((1 << SINTBL_BIT) - 1) * sin(2 * M_PI * i / SIN_ENT); - oplcfg.sintable[0][i] = (SINT32)pom; - } - for (i = 0; i < SIN_ENT; i++) - { - if (( 3/(8*SIN_ENT) < i) && (i < 4/(8*SIN_ENT))){ - oplcfg.sintable[1][i] = 0; - oplcfg.sintable[2][i] = -oplcfg.sintable[0][i]; - } - else if (i > 7/(8*SIN_ENT)){ - oplcfg.sintable[1][i] = 0; - oplcfg.sintable[2][i] = -oplcfg.sintable[0][i]; - } - else - oplcfg.sintable[1][i] = oplcfg.sintable[0][i]; - oplcfg.sintable[2][i] = oplcfg.sintable[0][i]; -// oplcfg.sintable[1][i] = (i & (SIN_ENT >> 1)) ? 0 : oplcfg.sintable[0][i]; -// oplcfg.sintable[2][i] = oplcfg.sintable[0][i & ((SIN_ENT >> 1) - 1)]; -// oplcfg.sintable[3][i] = (i & (SIN_ENT >> 2)) ? 0 : oplcfg.sintable[0][i & ((SIN_ENT >> 2) - 1)]; - } - for (i = 0; i < SIN_ENT; i++) - { - pom = (double)((1 << SINTBL_BIT) - 1) * sin(4 * M_PI * i / SIN_ENT); - if (( 3/(8*SIN_ENT) < i) && (i < 4/(8*SIN_ENT))) oplcfg.sintable[4][i] = 0; - else if (i > 7/(8*SIN_ENT)) oplcfg.sintable[4][i] = 0; - else oplcfg.sintable[4][i] = (SINT32)pom; - } - for (i = 0; i < SIN_ENT; i++) - { - if (( 3/(8*SIN_ENT) < i) && (i < 4/(8*SIN_ENT))){ - oplcfg.sintable[5][i] = 0; - oplcfg.sintable[7][i] = 0; - } - else if (i > 7/(8*SIN_ENT)){ - oplcfg.sintable[5][i] = 0; - oplcfg.sintable[7][i] = 0; - } - } - for (i = 0; i < EVC_ENT; i++) - { - pom = pow(((double)(EVC_ENT - 1 - i) / EVC_ENT), (double)8) * EVC_ENT; - oplcfg.envcurve[i] = (SINT32)pom; - oplcfg.envcurve[EVC_ENT + i] = i; - } - oplcfg.envcurve[EVC_ENT * 2] = EVC_ENT; - - oplcfg.rate = rate; - oplcfg.ratebit = ratebit; - - for (i = 0; i < 4; i++) - { - attacktable[i] = decaytable[i] = 0; - } - for (i = 4; i < 64; i++) - { - freq = (EVC_ENT << (ENV_BITS + ratebit)) * 72.0 / 64.0; - if (i < 60) - { - freq *= 1.0 + (i & 3) * 0.25; - } - freq *= (double)(1 << ((i >> 2) - 1)); - attacktable[i] = (SINT32)(freq * 3.0 / OPM_ARRATE); - decaytable[i] = (SINT32)(freq * 2.0 / OPM_DRRATE); -#if 0 - if (attacktable[i] >= EC_DECAY) - { - printf("attacktable %d %d %ld\n", i, attacktable[i], EC_DECAY); - } - if (decaytable[i] >= EC_DECAY) - { - printf("decaytable %d %d %ld\n", i, decaytable[i], EC_DECAY); - } -#endif - } - attacktable[62] = EC_DECAY - 1; - attacktable[63] = EC_DECAY - 1; - for (i = 64; i < 94; i++) - { - attacktable[i] = attacktable[63]; - decaytable[i] = decaytable[63]; - } -} - -void oplgen_setvol(UINT vol) -{ - oplcfg.fmvol = vol * 5 / 4; -#if defined(OPLGENX86) - oplcfg.fmvol <<= (32 - (OPM_OUTSB + 1 - FMVOL_SFTBIT + FMDIV_BITS + 6)); -#endif -} - - -/* ---- */ - -static void set_am_vib_egt_ksr_mult(OPLSLOT *slot, REG8 value) -{ - slot->mode = value; - slot->keyscalerate = (value & 0x10) ? 0 : 2; - slot->multiple = (SINT32)multipletable[value & 0x0f]; -} - -static void set_ksl_tl(OPLSLOT *slot, REG8 value) -{ - REG8 ksl; - - ksl = value >> 6; - slot->keyscalelevel = (ksl) ? (3 - ksl) : 31; - -#if (EVC_BITS >= 7) - slot->totallevel = (0x7f - (value & 0x3f)) << (EVC_BITS - 7); -#else - slot->totallevel = (0x7f - (value & 0x3f)) >> (7 - EVC_BITS); -#endif -} - -static void set_ar_dr(OPLSLOT *slot, REG8 value) -{ - UINT attack; - UINT decay1; - - attack = value >> 4; - slot->attack = (value) ? (attacktable + (attack << 2)) : nulltable; - slot->env_inc_attack = slot->attack[slot->envratio]; - if (slot->env_mode == EM_ATTACK) - { - slot->env_inc = slot->env_inc_attack; - } - - decay1 = value & 15; - slot->decay1 = (decay1) ? (decaytable + (decay1 << 2)) : nulltable; - slot->env_inc_decay1 = slot->decay1[slot->envratio]; - if (slot->env_mode == EM_DECAY1) - { - slot->env_inc = slot->env_inc_decay1; - } -} - -static void set_sl_rr(OPLSLOT *slot, REG8 value) -{ - slot->decaylevel = decayleveltable[(value >> 4)]; - slot->release = decaytable + ((value & 15) << 2) + 2; - slot->env_inc_release = slot->release[slot->envratio]; - if (slot->env_mode == EM_RELEASE) - { - slot->env_inc = slot->env_inc_release; - if (value == 0xff) - { - slot->env_mode = EM_OFF; - slot->env_cnt = EC_OFF; - slot->env_end = EC_OFF + 1; - slot->env_inc = 0; - } - } -} - -static void set_wavesel(OPLSLOT *slot, REG8 value) -{ - slot->sintable = oplcfg.sintable[value & 7]; - -} - -/* ----- */ - -static void set_fnumberl(OPLCH *ch, REG8 value) -{ - UINT blk; - UINT fn; - - ch->blkfnum = (ch->blkfnum & 0x1f00) | value; - - blk = ch->blkfnum >> 10; - fn = ch->blkfnum & 0x3ff; - ch->kcode = ch->blkfnum >> 9; - ch->keynote = (fn << blk) << (FREQ_BITS - 20); - ch->kslbase = ksl_tab[ch->blkfnum >> 6] << 1; -} - -static void set_kon_block_fnumh(OPLCH *ch, REG8 value) -{ - UINT blk; - UINT fn; - - ch->blkfnum = (ch->blkfnum & 0xff) | ((value & 0x1f) << 8); - - blk = ch->blkfnum >> 10; - fn = ch->blkfnum & 0x3ff; - ch->kcode = ch->blkfnum >> 9; - ch->keynote = (fn << blk) << (FREQ_BITS - 20); - ch->kslbase = ksl_tab[ch->blkfnum >> 6] << 1; -} - -static void set_fb_cnt(OPLCH *ch, REG8 value) -{ - REG8 feedback; - - feedback = (value >> 1) & 7; - if (feedback) - { - ch->feedback = 8 - feedback; - } - else - { - ch->feedback = 0; - } - ch->algorithm = value & 1; -} - -static void set_algorithm(OPLGEN oplgen, OPLCH *ch) -{ - SINT32 *outd; - - outd = &oplgen->outdc; - - if (!ch->algorithm) - { - ch->connect1 = &oplgen->feedback2; - } - else - { - ch->connect1 = outd; - } - ch->connect2 = outd; -} - -static void channleupdate(OPLCH *ch) -{ - OPLSLOT *slot; - UINT i; - UINT evr; - - slot = ch->slot; - for (i = 0; i < 2; i++, slot++) - { - slot->totallevel2 = slot->totallevel - (ch->kslbase >> slot->keyscalelevel); - slot->freq_inc = (ch->keynote * slot->multiple) >> 1; - evr = ch->kcode >> slot->keyscalerate; - if (slot->envratio != evr) - { - slot->envratio = evr; - slot->env_inc_attack = slot->attack[evr]; - slot->env_inc_decay1 = slot->decay1[evr]; - slot->env_inc_release = slot->release[evr]; - } - } -} - -static void keyon(OPLGEN oplgen, OPLCH *ch, UINT keyon) -{ - UINT i; - OPLSLOT *slot; - - oplgen->playing = 1; - ch->playing |= keyon; - - slot = ch->slot; - for (i = 0; i < 2; i++) - { - if (keyon & (1 << i)) /* keyon */ - { - if (slot->env_mode <= EM_RELEASE) - { - slot->freq_cnt = 0; - if (i == OPLSLOT1) - { - ch->op1fb = 0; - } - slot->env_mode = EM_ATTACK; - slot->env_inc = slot->env_inc_attack; - slot->env_cnt = EC_ATTACK; - slot->env_end = EC_DECAY; - } - } - else /* keyoff */ - { - if (slot->env_mode > EM_RELEASE) - { - slot->env_mode = EM_RELEASE; - if (!(slot->env_cnt & EC_DECAY)) - { - slot->env_cnt = (oplcfg.envcurve[slot->env_cnt >> ENV_BITS] << ENV_BITS) + EC_DECAY; - } - slot->env_end = EC_OFF; - slot->env_inc = slot->env_inc_release; - } - } - slot++; - } -} - -static void rhythmon(OPLGEN oplgen, REG8 value) -{ - oplgen->rhythm = value; - - if (!(value & 0x20)) - { - value = 0; - } - - keyon(oplgen, &oplgen->oplch[6], (value & 0x10) ? 3 : 0); - keyon(oplgen, &oplgen->oplch[7], ((value & 0x01) ? 1 : 0) | ((value & 0x08) ? 2 : 0)); - keyon(oplgen, &oplgen->oplch[8], ((value & 0x04) ? 1 : 0) | ((value & 0x02) ? 2 : 0)); -} - -/* ---- */ - -void oplgen_reset(OPLGEN oplgen, UINT nBaseClock) -{ - OPLCH *ch; - UINT i; - OPLSLOT *slot; - UINT j; - - memset(oplgen, 0, sizeof(*oplgen)); - oplgen->noise = 1; - oplgen->calc1024 = (SINT32)((FMDIV_ENT * (oplcfg.rate << oplcfg.ratebit) / (nBaseClock / 72.0)) + 0.5); - - ch = oplgen->oplch; - for (i = 0; i < OPLCH_MAX; i++) - { - ch->keynote = 0; - slot = ch->slot; - for (j = 0; j < 2; j++) - { - slot->env_mode = EM_OFF; - slot->env_cnt = EC_OFF; - slot->env_end = EC_OFF + 1; - slot->env_inc = 0; - slot->attack = nulltable; - slot->decay1 = nulltable; - slot->release = decaytable; - slot++; - } - ch++; - } - - for (i = 0x20; i < 0xa0; i++) - { - oplgen_setreg(oplgen, i, 0xff); - } - for (i = 0xa0; i < 0x100; i++) - { - oplgen_setreg(oplgen, i, 0x00); - } -} - -static void setslot(OPLGEN oplgen, UINT reg, REG8 value) -{ - UINT nBase; - UINT nSlot; - OPLCH *ch; - OPLSLOT *slot; - - nBase = (reg >> 3) & 3; - if (nBase >= 3) - { - return; - } - - nSlot = reg & 7; - if (nSlot >= 6) - { - return; - } - - ch = oplgen->oplch + (nBase * 3) + (nSlot % 3); - slot = &ch->slot[nSlot / 3]; - - switch (reg & 0xe0) - { - case 0x20: /* AM:VIB:EGT:KSR:MULT */ - set_am_vib_egt_ksr_mult(slot, value); - channleupdate(ch); - break; - - case 0x40: /* KSL:TL */ - set_ksl_tl(slot, value); - channleupdate(ch); - break; - - case 0x60: /* AR:DR */ - set_ar_dr(slot, value); - break; - - case 0x80: /* SL:RR */ - set_sl_rr(slot, value); - break; - - case 0xe0: /* WSEL */ - set_wavesel(slot, value); - break; - } -} - -static void setch(OPLGEN oplgen, UINT reg, REG8 value) -{ - UINT nChannel; - OPLCH *ch; - - if (reg == 0xbd) - { - rhythmon(oplgen, value); - return; - } - - nChannel = reg & 15; - if (nChannel >= 9) - { - return; - } - ch = oplgen->oplch + nChannel; - - switch (reg & 0xf0) - { - case 0xa0: /* F-NUMBER(L) */ - set_fnumberl(ch, value); - channleupdate(ch); - break; - - case 0xb0: /* KON:BLOCK:F-NUM(H) */ - set_kon_block_fnumh(ch, value); - channleupdate(ch); - keyon(oplgen, ch, (value & 0x20) ? 3 : 0); - break; - - case 0xc0: /* FB:CNT */ - set_fb_cnt(ch, value); - set_algorithm(oplgen, ch); - break; - } -} - -void oplgen_setreg(OPLGEN oplgen, UINT reg, REG8 value) -{ - switch (reg & 0xe0) - { - case 0x00: - break; - - case 0x20: - case 0x40: - case 0x60: - case 0x80: - case 0xe0: - setslot(oplgen, reg, value); - break; - - case 0xa0: - case 0xc0: - setch(oplgen, reg, value); - break; - } -} +/** + * @file oplgenc.c + * @brief Implementation of the OPL generator + */ + +#include +#include "oplgen.h" +#include +#include "oplgencfg.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327 +#endif + + OPLCFG oplcfg; + +#define OPM_ARRATE 399128L +#define OPM_DRRATE 5514396L + +#define EG_STEP (96.0 / EVC_ENT) /* dB step */ +#define SC(db) (SINT32)((db) * ((3.0 / EG_STEP) * (1 << ENV_BITS))) + EC_DECAY + +static SINT32 attacktable[94]; +static SINT32 decaytable[94]; + +static const SINT32 decayleveltable[16] = { + SC( 0),SC( 1),SC( 2),SC( 3),SC( 4),SC( 5),SC( 6),SC( 7), + SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)}; +static const UINT8 multipletable[] = { + 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30}; +static const SINT32 nulltable[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +#define DV(db) (UINT32)((db) / (0.1875 / 2.0)) +static const UINT32 ksl_tab[8 * 16]= +{ + /* OCT 0 */ + DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), + DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), + DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), + DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), + /* OCT 1 */ + DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), + DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), + DV( 0.000),DV( 0.750),DV( 1.125),DV( 1.500), + DV( 1.875),DV( 2.250),DV( 2.625),DV( 3.000), + /* OCT 2 */ + DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000), + DV( 0.000),DV( 1.125),DV( 1.875),DV( 2.625), + DV( 3.000),DV( 3.750),DV( 4.125),DV( 4.500), + DV( 4.875),DV( 5.250),DV( 5.625),DV( 6.000), + /* OCT 3 */ + DV( 0.000),DV( 0.000),DV( 0.000),DV( 1.875), + DV( 3.000),DV( 4.125),DV( 4.875),DV( 5.625), + DV( 6.000),DV( 6.750),DV( 7.125),DV( 7.500), + DV( 7.875),DV( 8.250),DV( 8.625),DV( 9.000), + /* OCT 4 */ + DV( 0.000),DV( 0.000),DV( 3.000),DV( 4.875), + DV( 6.000),DV( 7.125),DV( 7.875),DV( 8.625), + DV( 9.000),DV( 9.750),DV(10.125),DV(10.500), + DV(10.875),DV(11.250),DV(11.625),DV(12.000), + /* OCT 5 */ + DV( 0.000),DV( 3.000),DV( 6.000),DV( 7.875), + DV( 9.000),DV(10.125),DV(10.875),DV(11.625), + DV(12.000),DV(12.750),DV(13.125),DV(13.500), + DV(13.875),DV(14.250),DV(14.625),DV(15.000), + /* OCT 6 */ + DV( 0.000),DV( 6.000),DV( 9.000),DV(10.875), + DV(12.000),DV(13.125),DV(13.875),DV(14.625), + DV(15.000),DV(15.750),DV(16.125),DV(16.500), + DV(16.875),DV(17.250),DV(17.625),DV(18.000), + /* OCT 7 */ + DV( 0.000),DV( 9.000),DV(12.000),DV(13.875), + DV(15.000),DV(16.125),DV(16.875),DV(17.625), + DV(18.000),DV(18.750),DV(19.125),DV(19.500), + DV(19.875),DV(20.250),DV(20.625),DV(21.000) +}; + +void oplgen_initialize(UINT rate) +{ + UINT ratebit; + int i; +#if defined(OPLGEN_ENVSHIFT) + char sft; +#endif /* defined(OPLGEN_ENVSHIFT) */ + double pom; + double freq; + + if (rate > (OPL_CLOCK / 144.0)) + { + ratebit = 0; + } + else if (rate > (OPL_CLOCK / 288.0)) + { + ratebit = 1; + } + else + { + ratebit = 2; + } + + for (i = 0; i < EVC_ENT; i++) + { +#if defined(OPLGEN_ENVSHIFT) + sft = ENVTBL_BIT; + while (sft < (ENVTBL_BIT + 8)) + { + pom = (double)(1 << sft) / pow(10.0, EG_STEP * (EVC_ENT - i) / 20.0); + oplcfg.envtable[i] = (SINT32)pom; + oplcfg.envshift[i] = sft - TL_BITS; + if (oplcfg.envtable[i] >= (1 << (ENVTBL_BIT - 1))) + { + break; + } + sft++; + } +#else /* defined(OPLGEN_ENVSHIFT) */ + pom = (double)(1 << ENVTBL_BIT) / pow(10.0, EG_STEP * (EVC_ENT - i) / 20.0); + oplcfg.envtable[i] = (SINT32)pom; +#endif /* defined(OPLGEN_ENVSHIFT) */ + } + for (i = 0; i < SIN_ENT; i++) + { + pom = (double)((1 << SINTBL_BIT) - 1) * sin(2 * M_PI * i / SIN_ENT); + oplcfg.sintable[0][i] = (SINT32)pom; + } + for (i = 0; i < SIN_ENT; i++) + { + if (( 3/(8*SIN_ENT) < i) && (i < 4/(8*SIN_ENT))){ + oplcfg.sintable[1][i] = 0; + oplcfg.sintable[2][i] = -oplcfg.sintable[0][i]; + } + else if (i > 7/(8*SIN_ENT)){ + oplcfg.sintable[1][i] = 0; + oplcfg.sintable[2][i] = -oplcfg.sintable[0][i]; + } + else + oplcfg.sintable[1][i] = oplcfg.sintable[0][i]; + oplcfg.sintable[2][i] = oplcfg.sintable[0][i]; +// oplcfg.sintable[1][i] = (i & (SIN_ENT >> 1)) ? 0 : oplcfg.sintable[0][i]; +// oplcfg.sintable[2][i] = oplcfg.sintable[0][i & ((SIN_ENT >> 1) - 1)]; +// oplcfg.sintable[3][i] = (i & (SIN_ENT >> 2)) ? 0 : oplcfg.sintable[0][i & ((SIN_ENT >> 2) - 1)]; + } + for (i = 0; i < SIN_ENT; i++) + { + pom = (double)((1 << SINTBL_BIT) - 1) * sin(4 * M_PI * i / SIN_ENT); + if (( 3/(8*SIN_ENT) < i) && (i < 4/(8*SIN_ENT))) oplcfg.sintable[4][i] = 0; + else if (i > 7/(8*SIN_ENT)) oplcfg.sintable[4][i] = 0; + else oplcfg.sintable[4][i] = (SINT32)pom; + } + for (i = 0; i < SIN_ENT; i++) + { + if (( 3/(8*SIN_ENT) < i) && (i < 4/(8*SIN_ENT))){ + oplcfg.sintable[5][i] = 0; + oplcfg.sintable[7][i] = 0; + } + else if (i > 7/(8*SIN_ENT)){ + oplcfg.sintable[5][i] = 0; + oplcfg.sintable[7][i] = 0; + } + } + for (i = 0; i < EVC_ENT; i++) + { + pom = pow(((double)(EVC_ENT - 1 - i) / EVC_ENT), (double)8) * EVC_ENT; + oplcfg.envcurve[i] = (SINT32)pom; + oplcfg.envcurve[EVC_ENT + i] = i; + } + oplcfg.envcurve[EVC_ENT * 2] = EVC_ENT; + + oplcfg.rate = rate; + oplcfg.ratebit = ratebit; + + for (i = 0; i < 4; i++) + { + attacktable[i] = decaytable[i] = 0; + } + for (i = 4; i < 64; i++) + { + freq = (EVC_ENT << (ENV_BITS + ratebit)) * 72.0 / 64.0; + if (i < 60) + { + freq *= 1.0 + (i & 3) * 0.25; + } + freq *= (double)(1 << ((i >> 2) - 1)); + attacktable[i] = (SINT32)(freq * 3.0 / OPM_ARRATE); + decaytable[i] = (SINT32)(freq * 2.0 / OPM_DRRATE); +#if 0 + if (attacktable[i] >= EC_DECAY) + { + printf("attacktable %d %d %ld\n", i, attacktable[i], EC_DECAY); + } + if (decaytable[i] >= EC_DECAY) + { + printf("decaytable %d %d %ld\n", i, decaytable[i], EC_DECAY); + } +#endif + } + attacktable[62] = EC_DECAY - 1; + attacktable[63] = EC_DECAY - 1; + for (i = 64; i < 94; i++) + { + attacktable[i] = attacktable[63]; + decaytable[i] = decaytable[63]; + } +} + +void oplgen_setvol(UINT vol) +{ + oplcfg.fmvol = vol * 5 / 4; +#if defined(OPLGENX86) + oplcfg.fmvol <<= (32 - (OPM_OUTSB + 1 - FMVOL_SFTBIT + FMDIV_BITS + 6)); +#endif +} + + +/* ---- */ + +static void set_am_vib_egt_ksr_mult(OPLSLOT *slot, REG8 value) +{ + slot->mode = value; + slot->keyscalerate = (value & 0x10) ? 0 : 2; + slot->multiple = (SINT32)multipletable[value & 0x0f]; +} + +static void set_ksl_tl(OPLSLOT *slot, REG8 value) +{ + REG8 ksl; + + ksl = value >> 6; + slot->keyscalelevel = (ksl) ? (3 - ksl) : 31; + +#if (EVC_BITS >= 7) + slot->totallevel = (0x7f - (value & 0x3f)) << (EVC_BITS - 7); +#else + slot->totallevel = (0x7f - (value & 0x3f)) >> (7 - EVC_BITS); +#endif +} + +static void set_ar_dr(OPLSLOT *slot, REG8 value) +{ + UINT attack; + UINT decay1; + + attack = value >> 4; + slot->attack = (value) ? (attacktable + (attack << 2)) : nulltable; + slot->env_inc_attack = slot->attack[slot->envratio]; + if (slot->env_mode == EM_ATTACK) + { + slot->env_inc = slot->env_inc_attack; + } + + decay1 = value & 15; + slot->decay1 = (decay1) ? (decaytable + (decay1 << 2)) : nulltable; + slot->env_inc_decay1 = slot->decay1[slot->envratio]; + if (slot->env_mode == EM_DECAY1) + { + slot->env_inc = slot->env_inc_decay1; + } +} + +static void set_sl_rr(OPLSLOT *slot, REG8 value) +{ + slot->decaylevel = decayleveltable[(value >> 4)]; + slot->release = decaytable + ((value & 15) << 2) + 2; + slot->env_inc_release = slot->release[slot->envratio]; + if (slot->env_mode == EM_RELEASE) + { + slot->env_inc = slot->env_inc_release; + if (value == 0xff) + { + slot->env_mode = EM_OFF; + slot->env_cnt = EC_OFF; + slot->env_end = EC_OFF + 1; + slot->env_inc = 0; + } + } +} + +static void set_wavesel(OPLSLOT *slot, REG8 value) +{ + slot->sintable = oplcfg.sintable[value & 7]; + +} + +/* ----- */ + +static void set_fnumberl(OPLCH *ch, REG8 value) +{ + UINT blk; + UINT fn; + + ch->blkfnum = (ch->blkfnum & 0x1f00) | value; + + blk = ch->blkfnum >> 10; + fn = ch->blkfnum & 0x3ff; + ch->kcode = ch->blkfnum >> 9; + ch->keynote = (fn << blk) << (FREQ_BITS - 20); + ch->kslbase = ksl_tab[ch->blkfnum >> 6] << 1; +} + +static void set_kon_block_fnumh(OPLCH *ch, REG8 value) +{ + UINT blk; + UINT fn; + + ch->blkfnum = (ch->blkfnum & 0xff) | ((value & 0x1f) << 8); + + blk = ch->blkfnum >> 10; + fn = ch->blkfnum & 0x3ff; + ch->kcode = ch->blkfnum >> 9; + ch->keynote = (fn << blk) << (FREQ_BITS - 20); + ch->kslbase = ksl_tab[ch->blkfnum >> 6] << 1; +} + +static void set_fb_cnt(OPLCH *ch, REG8 value) +{ + REG8 feedback; + + feedback = (value >> 1) & 7; + if (feedback) + { + ch->feedback = 8 - feedback; + } + else + { + ch->feedback = 0; + } + ch->algorithm = value & 1; +} + +static void set_algorithm(OPLGEN oplgen, OPLCH *ch) +{ + SINT32 *outd; + + outd = &oplgen->outdc; + + if (!ch->algorithm) + { + ch->connect1 = &oplgen->feedback2; + } + else + { + ch->connect1 = outd; + } + ch->connect2 = outd; +} + +static void channleupdate(OPLCH *ch) +{ + OPLSLOT *slot; + UINT i; + UINT evr; + + slot = ch->slot; + for (i = 0; i < 2; i++, slot++) + { + slot->totallevel2 = slot->totallevel - (ch->kslbase >> slot->keyscalelevel); + slot->freq_inc = (ch->keynote * slot->multiple) >> 1; + evr = ch->kcode >> slot->keyscalerate; + if (slot->envratio != evr) + { + slot->envratio = evr; + slot->env_inc_attack = slot->attack[evr]; + slot->env_inc_decay1 = slot->decay1[evr]; + slot->env_inc_release = slot->release[evr]; + } + } +} + +static void keyon(OPLGEN oplgen, OPLCH *ch, UINT keyon) +{ + UINT i; + OPLSLOT *slot; + + oplgen->playing = 1; + ch->playing |= keyon; + + slot = ch->slot; + for (i = 0; i < 2; i++) + { + if (keyon & (1 << i)) /* keyon */ + { + if (slot->env_mode <= EM_RELEASE) + { + slot->freq_cnt = 0; + if (i == OPLSLOT1) + { + ch->op1fb = 0; + } + slot->env_mode = EM_ATTACK; + slot->env_inc = slot->env_inc_attack; + slot->env_cnt = EC_ATTACK; + slot->env_end = EC_DECAY; + } + } + else /* keyoff */ + { + if (slot->env_mode > EM_RELEASE) + { + slot->env_mode = EM_RELEASE; + if (!(slot->env_cnt & EC_DECAY)) + { + slot->env_cnt = (oplcfg.envcurve[slot->env_cnt >> ENV_BITS] << ENV_BITS) + EC_DECAY; + } + slot->env_end = EC_OFF; + slot->env_inc = slot->env_inc_release; + } + } + slot++; + } +} + +static void rhythmon(OPLGEN oplgen, REG8 value) +{ + oplgen->rhythm = value; + + if (!(value & 0x20)) + { + value = 0; + } + + keyon(oplgen, &oplgen->oplch[6], (value & 0x10) ? 3 : 0); + keyon(oplgen, &oplgen->oplch[7], ((value & 0x01) ? 1 : 0) | ((value & 0x08) ? 2 : 0)); + keyon(oplgen, &oplgen->oplch[8], ((value & 0x04) ? 1 : 0) | ((value & 0x02) ? 2 : 0)); +} + +/* ---- */ + +void oplgen_reset(OPLGEN oplgen, UINT nBaseClock) +{ + OPLCH *ch; + UINT i; + OPLSLOT *slot; + UINT j; + + memset(oplgen, 0, sizeof(*oplgen)); + oplgen->noise = 1; + oplgen->calc1024 = (SINT32)((FMDIV_ENT * (oplcfg.rate << oplcfg.ratebit) / (nBaseClock / 72.0)) + 0.5); + + ch = oplgen->oplch; + for (i = 0; i < OPLCH_MAX; i++) + { + ch->keynote = 0; + slot = ch->slot; + for (j = 0; j < 2; j++) + { + slot->env_mode = EM_OFF; + slot->env_cnt = EC_OFF; + slot->env_end = EC_OFF + 1; + slot->env_inc = 0; + slot->attack = nulltable; + slot->decay1 = nulltable; + slot->release = decaytable; + slot++; + } + ch++; + } + + for (i = 0x20; i < 0xa0; i++) + { + oplgen_setreg(oplgen, i, 0xff); + } + for (i = 0xa0; i < 0x100; i++) + { + oplgen_setreg(oplgen, i, 0x00); + } +} + +static void setslot(OPLGEN oplgen, UINT reg, REG8 value) +{ + UINT nBase; + UINT nSlot; + OPLCH *ch; + OPLSLOT *slot; + + nBase = (reg >> 3) & 3; + if (nBase >= 3) + { + return; + } + + nSlot = reg & 7; + if (nSlot >= 6) + { + return; + } + + ch = oplgen->oplch + (nBase * 3) + (nSlot % 3); + slot = &ch->slot[nSlot / 3]; + + switch (reg & 0xe0) + { + case 0x20: /* AM:VIB:EGT:KSR:MULT */ + set_am_vib_egt_ksr_mult(slot, value); + channleupdate(ch); + break; + + case 0x40: /* KSL:TL */ + set_ksl_tl(slot, value); + channleupdate(ch); + break; + + case 0x60: /* AR:DR */ + set_ar_dr(slot, value); + break; + + case 0x80: /* SL:RR */ + set_sl_rr(slot, value); + break; + + case 0xe0: /* WSEL */ + set_wavesel(slot, value); + break; + } +} + +static void setch(OPLGEN oplgen, UINT reg, REG8 value) +{ + UINT nChannel; + OPLCH *ch; + + if (reg == 0xbd) + { + rhythmon(oplgen, value); + return; + } + + nChannel = reg & 15; + if (nChannel >= 9) + { + return; + } + ch = oplgen->oplch + nChannel; + + switch (reg & 0xf0) + { + case 0xa0: /* F-NUMBER(L) */ + set_fnumberl(ch, value); + channleupdate(ch); + break; + + case 0xb0: /* KON:BLOCK:F-NUM(H) */ + set_kon_block_fnumh(ch, value); + channleupdate(ch); + keyon(oplgen, ch, (value & 0x20) ? 3 : 0); + break; + + case 0xc0: /* FB:CNT */ + set_fb_cnt(ch, value); + set_algorithm(oplgen, ch); + break; + } +} + +void oplgen_setreg(OPLGEN oplgen, UINT reg, REG8 value) +{ + switch (reg & 0xe0) + { + case 0x00: + break; + + case 0x20: + case 0x40: + case 0x60: + case 0x80: + case 0xe0: + setslot(oplgen, reg, value); + break; + + case 0xa0: + case 0xc0: + setch(oplgen, reg, value); + break; + } +} diff --git a/sound/oplgencfg.h b/sound/oplgencfg.h old mode 100755 new mode 100644 index af17071e..0bbb40c9 --- a/sound/oplgencfg.h +++ b/sound/oplgencfg.h @@ -1,62 +1,62 @@ -/** - * @file oplgencfg.h - * @brief Interface of the OPL generator - */ - -#pragma once - -// #define OPLGEN_ENVSHIFT -// #define OPLGENX86 - -enum -{ - FMDIV_BITS = 10, - FMDIV_ENT = (1 << FMDIV_BITS), - FMVOL_SFTBIT = 4 -}; - -#define SIN_BITS 10 -#define EVC_BITS 10 -#define ENV_BITS 16 -#define FREQ_BITS 21 -#define ENVTBL_BIT 14 -#define SINTBL_BIT 15 - -#define TL_BITS (FREQ_BITS + 2) -#define OPM_OUTSB (TL_BITS + 2 - 16) /* OPM output 16bit */ - -#define SIN_ENT (1L << SIN_BITS) -#define EVC_ENT (1L << EVC_BITS) - -#define EC_ATTACK 0 /* ATTACK start */ -#define EC_DECAY (EVC_ENT << ENV_BITS) /* DECAY start */ -#define EC_OFF ((2 * EVC_ENT) << ENV_BITS) /* OFF */ - -enum -{ - /* slot number */ - OPLSLOT1 = 0, - OPLSLOT2 = 1, - - EM_ATTACK = 4, - EM_DECAY1 = 3, - EM_DECAY2 = 2, - EM_RELEASE = 1, - EM_OFF = 0 -}; - -typedef struct -{ - SINT32 fmvol; - UINT rate; - UINT ratebit; - - SINT32 sintable[8][SIN_ENT]; - SINT32 envtable[EVC_ENT]; -#if defined(OPLGEN_ENVSHIFT) - char envshift[EVC_ENT]; -#endif /* defined(OPLGEN_ENVSHIFT) */ - SINT32 envcurve[EVC_ENT * 2 + 1]; -} OPLCFG; - -extern OPLCFG oplcfg; +/** + * @file oplgencfg.h + * @brief Interface of the OPL generator + */ + +#pragma once + +// #define OPLGEN_ENVSHIFT +// #define OPLGENX86 + +enum +{ + FMDIV_BITS = 10, + FMDIV_ENT = (1 << FMDIV_BITS), + FMVOL_SFTBIT = 4 +}; + +#define SIN_BITS 10 +#define EVC_BITS 10 +#define ENV_BITS 16 +#define FREQ_BITS 21 +#define ENVTBL_BIT 14 +#define SINTBL_BIT 15 + +#define TL_BITS (FREQ_BITS + 2) +#define OPM_OUTSB (TL_BITS + 2 - 16) /* OPM output 16bit */ + +#define SIN_ENT (1L << SIN_BITS) +#define EVC_ENT (1L << EVC_BITS) + +#define EC_ATTACK 0 /* ATTACK start */ +#define EC_DECAY (EVC_ENT << ENV_BITS) /* DECAY start */ +#define EC_OFF ((2 * EVC_ENT) << ENV_BITS) /* OFF */ + +enum +{ + /* slot number */ + OPLSLOT1 = 0, + OPLSLOT2 = 1, + + EM_ATTACK = 4, + EM_DECAY1 = 3, + EM_DECAY2 = 2, + EM_RELEASE = 1, + EM_OFF = 0 +}; + +typedef struct +{ + SINT32 fmvol; + UINT rate; + UINT ratebit; + + SINT32 sintable[8][SIN_ENT]; + SINT32 envtable[EVC_ENT]; +#if defined(OPLGEN_ENVSHIFT) + char envshift[EVC_ENT]; +#endif /* defined(OPLGEN_ENVSHIFT) */ + SINT32 envcurve[EVC_ENT * 2 + 1]; +} OPLCFG; + +extern OPLCFG oplcfg; diff --git a/sound/oplgeng.c b/sound/oplgeng.c old mode 100755 new mode 100644 index 2e84f133..185181e4 --- a/sound/oplgeng.c +++ b/sound/oplgeng.c @@ -1,306 +1,306 @@ -/** - * @file oplgeng.c - * @brief Implementation of the OPL generator - */ - -#include -#include "oplgen.h" -#include "oplgencfg.h" - -#define CALCENV(e, c, s) \ - (c)->slot[(s)].env_cnt += (c)->slot[(s)].env_inc; \ - if ((c)->slot[(s)].env_cnt >= (c)->slot[(s)].env_end) \ - { \ - switch ((c)->slot[(s)].env_mode) \ - { \ - case EM_ATTACK: \ - (c)->slot[(s)].env_mode = EM_DECAY1; \ - (c)->slot[(s)].env_cnt = EC_DECAY; \ - (c)->slot[(s)].env_end = (c)->slot[(s)].decaylevel; \ - (c)->slot[(s)].env_inc = (c)->slot[(s)].env_inc_decay1; \ - break; \ - case EM_DECAY1: \ - (c)->slot[(s)].env_mode = EM_DECAY2; \ - (c)->slot[(s)].env_cnt = (c)->slot[(s)].decaylevel; \ - (c)->slot[(s)].env_end = EC_OFF; \ - if (!((c)->slot[(s)].mode & 0x20)) \ - { \ - (c)->slot[(s)].env_inc = c->slot[(s)].env_inc_release; \ - break; \ - } \ - case EM_DECAY2: \ - (c)->slot[(s)].env_inc = 0; \ - break; \ - case EM_RELEASE: \ - (c)->slot[(s)].env_mode = EM_OFF; \ - (c)->slot[(s)].env_cnt = EC_OFF; \ - (c)->slot[(s)].env_end = EC_OFF + 1; \ - (c)->slot[(s)].env_inc = 0; \ - (c)->playing &= ~(1 << (s)); \ - break; \ - } \ - } \ - (e) = (c)->slot[(s)].totallevel2 - \ - oplcfg.envcurve[(c)->slot[(s)].env_cnt >> ENV_BITS]; - -#if defined(OPLGEN_ENVSHIFT) -static SINT32 SLOTOUT(const SINT32* s, SINT32 e, SINT32 c) -{ - c = (c >> (FREQ_BITS - SIN_BITS)) & (SIN_ENT - 1); - return ((s)[c] * oplcfg.envtable[e]) >> (SINTBL_BIT + oplcfg.envshift[e]); -} -#else /* defined(OPLGEN_ENVSHIFT) */ -#define SLOTOUT(s, e, c) \ - (((s)[((c) >> (FREQ_BITS - SIN_BITS)) & (SIN_ENT - 1)] \ - * oplcfg.envtable[(e)]) >> (ENVTBL_BIT + SINTBL_BIT - TL_BITS)) -#endif /* defined(OPLGEN_ENVSHIFT) */ - -#define DEG2FREQ(s) (UINT32)((s) * (1 << FREQ_BITS) / 360.0) - -static void calcratechannel(OPLGEN oplgen, OPLCH *ch) -{ - SINT32 envout; - SINT32 opout; - - ch->slot[0].freq_cnt += ch->slot[0].freq_inc; - ch->slot[1].freq_cnt += ch->slot[1].freq_inc; - - oplgen->feedback2 = 0; - - /* SLOT 1 */ - CALCENV(envout, ch, 0); - if (envout >= 0) - { - if (ch->feedback) - { - /* with self feed back */ - opout = ch->op1fb; - ch->op1fb = SLOTOUT(ch->slot[0].sintable, envout, ch->slot[0].freq_cnt + ((ch->op1fb >> ch->feedback) << (FREQ_BITS - (TL_BITS - 2)))); - opout = (opout + ch->op1fb) >> 1; - } - else - { - /* without self feed back */ - opout = SLOTOUT(ch->slot[0].sintable, envout, ch->slot[0].freq_cnt); - } - /* output slot1 */ - *ch->connect1 += opout; - } - /* SLOT 2 */ - CALCENV(envout, ch, 1); - if (envout >= 0) - { - *ch->connect2 += SLOTOUT(ch->slot[1].sintable, envout, ch->slot[1].freq_cnt + (oplgen->feedback2 << (FREQ_BITS - (TL_BITS - 2)))); - } -} - -static UINT calcraterhythm(OPLGEN oplgen) -{ - UINT playing; - OPLCH *ch7; - SINT32 envout; - SINT32 opout; - OPLCH *ch8; - OPLCH *ch9; - UINT on; - UINT freq; - - if (oplgen->noise & 1) - { - oplgen->noise ^= 0x800302; - } - oplgen->noise >>= 1; - - playing = 0; - - /* Channel 7 */ - ch7 = &oplgen->oplch[6]; - if (ch7->playing & 2) - { - oplgen->feedback2 = 0; - - /* SLOT 1 */ - opout = 0; - if (ch7->algorithm == 0) - { - ch7->slot[0].freq_cnt += ch7->slot[0].freq_inc; - CALCENV(envout, ch7, 0); - if (envout >= 0) - { - if (ch7->feedback) - { - /* with self feed back */ - opout = ch7->op1fb; - ch7->op1fb = SLOTOUT(ch7->slot[0].sintable, envout, ch7->slot[0].freq_cnt + ((ch7->op1fb >> ch7->feedback) << (FREQ_BITS - (TL_BITS - 2)))); - opout = (opout + ch7->op1fb) >> 1; - } - else - { - /* without self feed back */ - opout = SLOTOUT(ch7->slot[0].sintable, envout, ch7->slot[0].freq_cnt); - } - } - } - - /* SLOT 2 */ - ch7->slot[1].freq_cnt += ch7->slot[1].freq_inc; - CALCENV(envout, ch7, 1); - if (envout >= 0) - { - *ch7->connect2 += SLOTOUT(ch7->slot[1].sintable, envout, ch7->slot[1].freq_cnt + (opout << (FREQ_BITS - (TL_BITS - 2)))); - } - playing++; - } - - /* Channel 8 & 9 */ - ch8 = &oplgen->oplch[7]; - ch9 = &oplgen->oplch[8]; - - ch8->slot[0].freq_cnt += ch8->slot[0].freq_inc; - ch9->slot[1].freq_cnt += ch9->slot[1].freq_inc; - - on = ch8->slot[0].freq_cnt & (3 << (FREQ_BITS - 8)); - on ^= (ch8->slot[0].freq_cnt >> 5) & (1 << (FREQ_BITS - 8)); - on |= (ch9->slot[1].freq_cnt ^ (ch9->slot[1].freq_cnt << 2)) & (1 << (FREQ_BITS - 5)); - - /* High Hat */ - if (ch8->playing & 1) - { - CALCENV(envout, ch8, 0); - if (envout >= 0) - { - freq = (on) ? DEG2FREQ(270 - 18) : DEG2FREQ(18); - if (oplgen->noise & 1) - { - freq += DEG2FREQ(90); - } - *ch8->connect2 += SLOTOUT(ch8->slot[0].sintable, envout, freq); - } - playing++; - } - - /* Snare Drum */ - if (ch8->playing & 2) - { - ch8->slot[1].freq_cnt += ch8->slot[1].freq_inc; - CALCENV(envout, ch8, 1); - if (envout >= 0) - { - freq = (ch8->slot[0].freq_cnt & (1 << (FREQ_BITS - 2))) ? DEG2FREQ(180) : DEG2FREQ(90); - if (oplgen->noise & 1) - { - freq += DEG2FREQ(90); - } - *ch8->connect2 += SLOTOUT(ch8->slot[1].sintable, envout, freq); - } - playing++; - } - - /* Tom Tom */ - if (ch9->playing & 1) - { - ch9->slot[0].freq_cnt += ch9->slot[0].freq_inc; - CALCENV(envout, ch9, 0); - if (envout >= 0) - { - *ch9->connect2 += SLOTOUT(ch9->slot[0].sintable, envout, ch9->slot[0].freq_cnt); - } - playing++; - } - - /* Top Cymbal */ - if (ch9->playing & 2) - { - CALCENV(envout, ch9, 1); - if (envout >= 0) - { - freq = (on) ? DEG2FREQ(270) : DEG2FREQ(90); - *ch9->connect2 += SLOTOUT(ch9->slot[1].sintable, envout, freq); - } - playing++; - } - return playing; -} - -void SOUNDCALL oplgen_getpcm(OPLGEN oplgen, SINT32 *pcm, UINT count) -{ - SINT32 samp_c; - UINT playing; - UINT i; - OPLCH *ch; - - if ((!oplgen->playing) || (!count)) - { - return; - } - - do - { - samp_c = oplgen->outdc; - if (oplgen->calcremain < FMDIV_ENT) - { - samp_c *= oplgen->calcremain; - oplgen->calcremain = FMDIV_ENT - oplgen->calcremain; - while (TRUE /*CONSTCOND*/) - { - oplgen->outdc = 0; - playing = 0; - for (i = 0; i < 6; i++) - { - ch = &oplgen->oplch[i]; - if (ch->playing & 3) - { - calcratechannel(oplgen, ch); - playing++; - } - } - if (!(oplgen->rhythm & 0x20)) - { - for (i = 6; i < 9; i++) - { - ch = &oplgen->oplch[i]; - if (ch->playing & 3) - { - calcratechannel(oplgen, ch); - playing++; - } - } - } - else - { - playing += calcraterhythm(oplgen); - } - oplgen->playing = playing; - - oplgen->outdc >>= (FMVOL_SFTBIT + 1); - if (oplgen->calcremain > oplgen->calc1024) - { - oplgen->calcremain -= oplgen->calc1024; - samp_c += oplgen->outdc * oplgen->calc1024; - } - else - { - break; - } - } - samp_c += oplgen->outdc * oplgen->calcremain; - } - else - { - samp_c *= FMDIV_ENT; - oplgen->calcremain -= FMDIV_ENT; - } -#if defined(OPLGENX86) - pcm[0] += (SINT32)(((SINT64)samp_c * (SINT32)oplcfg.fmvol) >> 32); - pcm[1] += (SINT32)(((SINT64)samp_c * (SINT32)oplcfg.fmvol) >> 32); -#else /* defined(OPLGENX86) */ - samp_c >>= 8; - samp_c *= oplcfg.fmvol; - samp_c >>= (OPM_OUTSB + FMDIV_BITS + 1 - FMVOL_SFTBIT - 8 + 6); - pcm[0] += samp_c; - pcm[1] += samp_c; -#endif /* defined(OPLGENX86) */ - oplgen->calcremain = oplgen->calc1024 - oplgen->calcremain; - pcm += 2; - } while (--count); -} +/** + * @file oplgeng.c + * @brief Implementation of the OPL generator + */ + +#include +#include "oplgen.h" +#include "oplgencfg.h" + +#define CALCENV(e, c, s) \ + (c)->slot[(s)].env_cnt += (c)->slot[(s)].env_inc; \ + if ((c)->slot[(s)].env_cnt >= (c)->slot[(s)].env_end) \ + { \ + switch ((c)->slot[(s)].env_mode) \ + { \ + case EM_ATTACK: \ + (c)->slot[(s)].env_mode = EM_DECAY1; \ + (c)->slot[(s)].env_cnt = EC_DECAY; \ + (c)->slot[(s)].env_end = (c)->slot[(s)].decaylevel; \ + (c)->slot[(s)].env_inc = (c)->slot[(s)].env_inc_decay1; \ + break; \ + case EM_DECAY1: \ + (c)->slot[(s)].env_mode = EM_DECAY2; \ + (c)->slot[(s)].env_cnt = (c)->slot[(s)].decaylevel; \ + (c)->slot[(s)].env_end = EC_OFF; \ + if (!((c)->slot[(s)].mode & 0x20)) \ + { \ + (c)->slot[(s)].env_inc = c->slot[(s)].env_inc_release; \ + break; \ + } \ + case EM_DECAY2: \ + (c)->slot[(s)].env_inc = 0; \ + break; \ + case EM_RELEASE: \ + (c)->slot[(s)].env_mode = EM_OFF; \ + (c)->slot[(s)].env_cnt = EC_OFF; \ + (c)->slot[(s)].env_end = EC_OFF + 1; \ + (c)->slot[(s)].env_inc = 0; \ + (c)->playing &= ~(1 << (s)); \ + break; \ + } \ + } \ + (e) = (c)->slot[(s)].totallevel2 - \ + oplcfg.envcurve[(c)->slot[(s)].env_cnt >> ENV_BITS]; + +#if defined(OPLGEN_ENVSHIFT) +static SINT32 SLOTOUT(const SINT32* s, SINT32 e, SINT32 c) +{ + c = (c >> (FREQ_BITS - SIN_BITS)) & (SIN_ENT - 1); + return ((s)[c] * oplcfg.envtable[e]) >> (SINTBL_BIT + oplcfg.envshift[e]); +} +#else /* defined(OPLGEN_ENVSHIFT) */ +#define SLOTOUT(s, e, c) \ + (((s)[((c) >> (FREQ_BITS - SIN_BITS)) & (SIN_ENT - 1)] \ + * oplcfg.envtable[(e)]) >> (ENVTBL_BIT + SINTBL_BIT - TL_BITS)) +#endif /* defined(OPLGEN_ENVSHIFT) */ + +#define DEG2FREQ(s) (UINT32)((s) * (1 << FREQ_BITS) / 360.0) + +static void calcratechannel(OPLGEN oplgen, OPLCH *ch) +{ + SINT32 envout; + SINT32 opout; + + ch->slot[0].freq_cnt += ch->slot[0].freq_inc; + ch->slot[1].freq_cnt += ch->slot[1].freq_inc; + + oplgen->feedback2 = 0; + + /* SLOT 1 */ + CALCENV(envout, ch, 0); + if (envout >= 0) + { + if (ch->feedback) + { + /* with self feed back */ + opout = ch->op1fb; + ch->op1fb = SLOTOUT(ch->slot[0].sintable, envout, ch->slot[0].freq_cnt + ((ch->op1fb >> ch->feedback) << (FREQ_BITS - (TL_BITS - 2)))); + opout = (opout + ch->op1fb) >> 1; + } + else + { + /* without self feed back */ + opout = SLOTOUT(ch->slot[0].sintable, envout, ch->slot[0].freq_cnt); + } + /* output slot1 */ + *ch->connect1 += opout; + } + /* SLOT 2 */ + CALCENV(envout, ch, 1); + if (envout >= 0) + { + *ch->connect2 += SLOTOUT(ch->slot[1].sintable, envout, ch->slot[1].freq_cnt + (oplgen->feedback2 << (FREQ_BITS - (TL_BITS - 2)))); + } +} + +static UINT calcraterhythm(OPLGEN oplgen) +{ + UINT playing; + OPLCH *ch7; + SINT32 envout; + SINT32 opout; + OPLCH *ch8; + OPLCH *ch9; + UINT on; + UINT freq; + + if (oplgen->noise & 1) + { + oplgen->noise ^= 0x800302; + } + oplgen->noise >>= 1; + + playing = 0; + + /* Channel 7 */ + ch7 = &oplgen->oplch[6]; + if (ch7->playing & 2) + { + oplgen->feedback2 = 0; + + /* SLOT 1 */ + opout = 0; + if (ch7->algorithm == 0) + { + ch7->slot[0].freq_cnt += ch7->slot[0].freq_inc; + CALCENV(envout, ch7, 0); + if (envout >= 0) + { + if (ch7->feedback) + { + /* with self feed back */ + opout = ch7->op1fb; + ch7->op1fb = SLOTOUT(ch7->slot[0].sintable, envout, ch7->slot[0].freq_cnt + ((ch7->op1fb >> ch7->feedback) << (FREQ_BITS - (TL_BITS - 2)))); + opout = (opout + ch7->op1fb) >> 1; + } + else + { + /* without self feed back */ + opout = SLOTOUT(ch7->slot[0].sintable, envout, ch7->slot[0].freq_cnt); + } + } + } + + /* SLOT 2 */ + ch7->slot[1].freq_cnt += ch7->slot[1].freq_inc; + CALCENV(envout, ch7, 1); + if (envout >= 0) + { + *ch7->connect2 += SLOTOUT(ch7->slot[1].sintable, envout, ch7->slot[1].freq_cnt + (opout << (FREQ_BITS - (TL_BITS - 2)))); + } + playing++; + } + + /* Channel 8 & 9 */ + ch8 = &oplgen->oplch[7]; + ch9 = &oplgen->oplch[8]; + + ch8->slot[0].freq_cnt += ch8->slot[0].freq_inc; + ch9->slot[1].freq_cnt += ch9->slot[1].freq_inc; + + on = ch8->slot[0].freq_cnt & (3 << (FREQ_BITS - 8)); + on ^= (ch8->slot[0].freq_cnt >> 5) & (1 << (FREQ_BITS - 8)); + on |= (ch9->slot[1].freq_cnt ^ (ch9->slot[1].freq_cnt << 2)) & (1 << (FREQ_BITS - 5)); + + /* High Hat */ + if (ch8->playing & 1) + { + CALCENV(envout, ch8, 0); + if (envout >= 0) + { + freq = (on) ? DEG2FREQ(270 - 18) : DEG2FREQ(18); + if (oplgen->noise & 1) + { + freq += DEG2FREQ(90); + } + *ch8->connect2 += SLOTOUT(ch8->slot[0].sintable, envout, freq); + } + playing++; + } + + /* Snare Drum */ + if (ch8->playing & 2) + { + ch8->slot[1].freq_cnt += ch8->slot[1].freq_inc; + CALCENV(envout, ch8, 1); + if (envout >= 0) + { + freq = (ch8->slot[0].freq_cnt & (1 << (FREQ_BITS - 2))) ? DEG2FREQ(180) : DEG2FREQ(90); + if (oplgen->noise & 1) + { + freq += DEG2FREQ(90); + } + *ch8->connect2 += SLOTOUT(ch8->slot[1].sintable, envout, freq); + } + playing++; + } + + /* Tom Tom */ + if (ch9->playing & 1) + { + ch9->slot[0].freq_cnt += ch9->slot[0].freq_inc; + CALCENV(envout, ch9, 0); + if (envout >= 0) + { + *ch9->connect2 += SLOTOUT(ch9->slot[0].sintable, envout, ch9->slot[0].freq_cnt); + } + playing++; + } + + /* Top Cymbal */ + if (ch9->playing & 2) + { + CALCENV(envout, ch9, 1); + if (envout >= 0) + { + freq = (on) ? DEG2FREQ(270) : DEG2FREQ(90); + *ch9->connect2 += SLOTOUT(ch9->slot[1].sintable, envout, freq); + } + playing++; + } + return playing; +} + +void SOUNDCALL oplgen_getpcm(OPLGEN oplgen, SINT32 *pcm, UINT count) +{ + SINT32 samp_c; + UINT playing; + UINT i; + OPLCH *ch; + + if ((!oplgen->playing) || (!count)) + { + return; + } + + do + { + samp_c = oplgen->outdc; + if (oplgen->calcremain < FMDIV_ENT) + { + samp_c *= oplgen->calcremain; + oplgen->calcremain = FMDIV_ENT - oplgen->calcremain; + while (TRUE /*CONSTCOND*/) + { + oplgen->outdc = 0; + playing = 0; + for (i = 0; i < 6; i++) + { + ch = &oplgen->oplch[i]; + if (ch->playing & 3) + { + calcratechannel(oplgen, ch); + playing++; + } + } + if (!(oplgen->rhythm & 0x20)) + { + for (i = 6; i < 9; i++) + { + ch = &oplgen->oplch[i]; + if (ch->playing & 3) + { + calcratechannel(oplgen, ch); + playing++; + } + } + } + else + { + playing += calcraterhythm(oplgen); + } + oplgen->playing = playing; + + oplgen->outdc >>= (FMVOL_SFTBIT + 1); + if (oplgen->calcremain > oplgen->calc1024) + { + oplgen->calcremain -= oplgen->calc1024; + samp_c += oplgen->outdc * oplgen->calc1024; + } + else + { + break; + } + } + samp_c += oplgen->outdc * oplgen->calcremain; + } + else + { + samp_c *= FMDIV_ENT; + oplgen->calcremain -= FMDIV_ENT; + } +#if defined(OPLGENX86) + pcm[0] += (SINT32)(((SINT64)samp_c * (SINT32)oplcfg.fmvol) >> 32); + pcm[1] += (SINT32)(((SINT64)samp_c * (SINT32)oplcfg.fmvol) >> 32); +#else /* defined(OPLGENX86) */ + samp_c >>= 8; + samp_c *= oplcfg.fmvol; + samp_c >>= (OPM_OUTSB + FMDIV_BITS + 1 - FMVOL_SFTBIT - 8 + 6); + pcm[0] += samp_c; + pcm[1] += samp_c; +#endif /* defined(OPLGENX86) */ + oplgen->calcremain = oplgen->calc1024 - oplgen->calcremain; + pcm += 2; + } while (--count); +} diff --git a/sound/opngen.h b/sound/opngen.h old mode 100755 new mode 100644 index 95fdb35a..a60a06f7 --- a/sound/opngen.h +++ b/sound/opngen.h @@ -1,102 +1,102 @@ -/** - * @file opngen.h - * @brief Interface of the OPN generator - */ - -#pragma once - -#include - -enum -{ - OPNCH_MAX = 6, - OPNA_CLOCK = 3993600, - - OPN_CHMASK = 0x80000000, - OPN_STEREO = 0x80000000, - OPN_MONORAL = 0x00000000 -}; - -typedef struct -{ - SINT32 *detune1; /* detune1 */ - SINT32 totallevel; /* total level */ - SINT32 decaylevel; /* decay level */ -const SINT32 *attack; /* attack ratio */ -const SINT32 *decay1; /* decay1 ratio */ -const SINT32 *decay2; /* decay2 ratio */ -const SINT32 *release; /* release ratio */ - SINT32 freq_cnt; /* frequency count */ - SINT32 freq_inc; /* frequency step */ - SINT32 multiple; /* multiple */ - UINT8 keyscalerate; /* key scale */ - UINT8 env_mode; /* envelope mode */ - UINT8 envratio; /* envelope ratio */ - UINT8 ssgeg1; /* SSG-EG */ - - SINT32 env_cnt; /* envelope count */ - SINT32 env_end; /* envelope end count */ - SINT32 env_inc; /* envelope step */ - SINT32 env_inc_attack; /* envelope attack step */ - SINT32 env_inc_decay1; /* envelope decay1 step */ - SINT32 env_inc_decay2; /* envelope decay2 step */ - SINT32 env_inc_release; /* envelope release step */ -} OPNSLOT; - -typedef struct -{ - OPNSLOT slot[4]; - UINT8 algorithm; /* algorithm */ - UINT8 feedback; /* self feedback */ - UINT8 playing; - UINT8 outslot; - SINT32 op1fb; /* operator1 feedback */ - SINT32 *connect1; /* operator1 connect */ - SINT32 *connect3; /* operator3 connect */ - SINT32 *connect2; /* operator2 connect */ - SINT32 *connect4; /* operator4 connect */ - UINT32 keynote[4]; /* key note */ - - UINT8 keyfunc[4]; /* key function */ - UINT8 kcode[4]; /* key code */ - UINT8 pan; /* pan */ - UINT8 extop; /* extendopelator-enable */ - UINT8 stereo; /* stereo-enable */ - UINT8 padding; -} OPNCH; - -typedef struct -{ - UINT playchannels; - UINT playing; - SINT32 feedback2; - SINT32 feedback3; - SINT32 feedback4; - SINT32 outdl; - SINT32 outdc; - SINT32 outdr; - SINT32 calcremain; - OPNCH opnch[OPNCH_MAX]; -} _OPNGEN, *OPNGEN; - -#ifdef __cplusplus -extern "C" { -#endif - -void opngen_initialize(UINT rate); -void opngen_setvol(UINT vol); -void opngen_setVR(REG8 channel, REG8 value); - -void opngen_reset(OPNGEN opngen); -void opngen_setcfg(OPNGEN opngen, REG8 maxch, UINT32 flag); -void opngen_setextch(OPNGEN opngen, UINT chnum, REG8 data); -void opngen_setreg(OPNGEN opngen, REG8 chbase, UINT reg, REG8 value); -void opngen_keyon(OPNGEN opngen, UINT chnum, REG8 value); -void opngen_csm(OPNGEN opngen); - -void SOUNDCALL opngen_getpcm(OPNGEN opngen, SINT32 *buf, UINT count); -void SOUNDCALL opngen_getpcmvr(OPNGEN opngen, SINT32 *buf, UINT count); - -#ifdef __cplusplus -} -#endif +/** + * @file opngen.h + * @brief Interface of the OPN generator + */ + +#pragma once + +#include + +enum +{ + OPNCH_MAX = 6, + OPNA_CLOCK = 3993600, + + OPN_CHMASK = 0x80000000, + OPN_STEREO = 0x80000000, + OPN_MONORAL = 0x00000000 +}; + +typedef struct +{ + SINT32 *detune1; /* detune1 */ + SINT32 totallevel; /* total level */ + SINT32 decaylevel; /* decay level */ +const SINT32 *attack; /* attack ratio */ +const SINT32 *decay1; /* decay1 ratio */ +const SINT32 *decay2; /* decay2 ratio */ +const SINT32 *release; /* release ratio */ + SINT32 freq_cnt; /* frequency count */ + SINT32 freq_inc; /* frequency step */ + SINT32 multiple; /* multiple */ + UINT8 keyscalerate; /* key scale */ + UINT8 env_mode; /* envelope mode */ + UINT8 envratio; /* envelope ratio */ + UINT8 ssgeg1; /* SSG-EG */ + + SINT32 env_cnt; /* envelope count */ + SINT32 env_end; /* envelope end count */ + SINT32 env_inc; /* envelope step */ + SINT32 env_inc_attack; /* envelope attack step */ + SINT32 env_inc_decay1; /* envelope decay1 step */ + SINT32 env_inc_decay2; /* envelope decay2 step */ + SINT32 env_inc_release; /* envelope release step */ +} OPNSLOT; + +typedef struct +{ + OPNSLOT slot[4]; + UINT8 algorithm; /* algorithm */ + UINT8 feedback; /* self feedback */ + UINT8 playing; + UINT8 outslot; + SINT32 op1fb; /* operator1 feedback */ + SINT32 *connect1; /* operator1 connect */ + SINT32 *connect3; /* operator3 connect */ + SINT32 *connect2; /* operator2 connect */ + SINT32 *connect4; /* operator4 connect */ + UINT32 keynote[4]; /* key note */ + + UINT8 keyfunc[4]; /* key function */ + UINT8 kcode[4]; /* key code */ + UINT8 pan; /* pan */ + UINT8 extop; /* extendopelator-enable */ + UINT8 stereo; /* stereo-enable */ + UINT8 padding; +} OPNCH; + +typedef struct +{ + UINT playchannels; + UINT playing; + SINT32 feedback2; + SINT32 feedback3; + SINT32 feedback4; + SINT32 outdl; + SINT32 outdc; + SINT32 outdr; + SINT32 calcremain; + OPNCH opnch[OPNCH_MAX]; +} _OPNGEN, *OPNGEN; + +#ifdef __cplusplus +extern "C" { +#endif + +void opngen_initialize(UINT rate); +void opngen_setvol(UINT vol); +void opngen_setVR(REG8 channel, REG8 value); + +void opngen_reset(OPNGEN opngen); +void opngen_setcfg(OPNGEN opngen, REG8 maxch, UINT32 flag); +void opngen_setextch(OPNGEN opngen, UINT chnum, REG8 data); +void opngen_setreg(OPNGEN opngen, REG8 chbase, UINT reg, REG8 value); +void opngen_keyon(OPNGEN opngen, UINT chnum, REG8 value); +void opngen_csm(OPNGEN opngen); + +void SOUNDCALL opngen_getpcm(OPNGEN opngen, SINT32 *buf, UINT count); +void SOUNDCALL opngen_getpcmvr(OPNGEN opngen, SINT32 *buf, UINT count); + +#ifdef __cplusplus +} +#endif diff --git a/sound/opngenc.c b/sound/opngenc.c old mode 100755 new mode 100644 index 289357dd..9da10411 --- a/sound/opngenc.c +++ b/sound/opngenc.c @@ -1,667 +1,667 @@ -/** - * @file opngenc.c - * @brief Implementation of the OPN generator - */ - -#include -#include -#include -#include "opngencfg.h" -#include - -#ifndef M_PI -#define M_PI 3.14159265358979323846264338327 -#endif - -#define OPM_ARRATE 399128L -#define OPM_DRRATE 5514396L - -#define EG_STEP (96.0 / EVC_ENT) /* dB step */ -#define SC(db) (SINT32)((db) * ((3.0 / EG_STEP) * (1 << ENV_BITS))) + EC_DECAY - - - OPNCFG opncfg; -#ifdef OPNGENX86 - char envshift[EVC_ENT]; - char sinshift[SIN_ENT]; -#endif - - -static SINT32 detunetable[8][32]; -static SINT32 attacktable[94]; -static SINT32 decaytable[94]; - -static const SINT32 decayleveltable[16] = { - SC( 0),SC( 1),SC( 2),SC( 3),SC( 4),SC( 5),SC( 6),SC( 7), - SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)}; -static const UINT8 multipletable[] = { - 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}; -static const SINT32 nulltable[] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -static const UINT8 kftable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3}; -static const UINT8 dttable[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, - 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8, - 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, - 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16, - 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, - 8, 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22}; -static const int extendslot[4] = {2, 3, 1, 0}; -static const int fmslot[4] = {0, 2, 1, 3}; - - -void opngen_initialize(UINT rate) -{ - UINT ratebit; - int i; - char sft; - int j; - double pom; - SINT32 detune; - double freq; - - if (rate > (OPNA_CLOCK / 144.0)) - { - ratebit = 0; - } - else if (rate > (OPNA_CLOCK / 288.0)) - { - ratebit = 1; - } - else - { - ratebit = 2; - } - opncfg.calc1024 = (SINT32)((FMDIV_ENT * (rate << ratebit) / (OPNA_CLOCK / 72.0)) + 0.5); - - for (i = 0; i < EVC_ENT; i++) - { -#ifdef OPNGENX86 - sft = ENVTBL_BIT; - while (sft < (ENVTBL_BIT + 8)) - { - pom = (double)(1 << sft) / pow(10.0, EG_STEP * (EVC_ENT - i) / 20.0); - opncfg.envtable[i] = (SINT32)pom; - envshift[i] = sft - TL_BITS; - if (opncfg.envtable[i] >= (1 << (ENVTBL_BIT - 1))) - { - break; - } - sft++; - } -#else - pom = (double)(1 << ENVTBL_BIT) / pow(10.0, EG_STEP * (EVC_ENT - i) / 20.0); - opncfg.envtable[i] = (SINT32)pom; -#endif - } - for (i = 0; i < SIN_ENT; i++) - { -#ifdef OPNGENX86 - sft = SINTBL_BIT; - while (sft < (SINTBL_BIT + 8)) - { - pom = (double)((1 << sft) - 1) * sin(2 * M_PI * i / SIN_ENT); - opncfg.sintable[i] = (SINT32)pom; - sinshift[i] = sft; - if (opncfg.sintable[i] >= (1 << (SINTBL_BIT - 1))) - { - break; - } - if (opncfg.sintable[i] <= -1 * (1 << (SINTBL_BIT - 1))) - { - break; - } - sft++; - } -#else - pom = (double)((1 << SINTBL_BIT) - 1) * sin(2 * M_PI * i / SIN_ENT); - opncfg.sintable[i] = (SINT32)pom; -#endif - } - for (i = 0; i < EVC_ENT; i++) - { - pom = pow(((double)(EVC_ENT - 1 - i) / EVC_ENT), 8) * EVC_ENT; - opncfg.envcurve[i] = (SINT32)pom; - opncfg.envcurve[EVC_ENT + i] = i; - } - opncfg.envcurve[EVC_ENT * 2] = EVC_ENT; - - opncfg.ratebit = ratebit; - - for (i = 0; i < 4; i++) - { - for (j = 0; j < 32; j++) - { - detune = dttable[i*32 + j]; - sft = ratebit + (FREQ_BITS - 20); - if (sft >= 0) - { - detune <<= sft; - } - else - { - detune >>= (0 - sft); - } - - detunetable[i + 0][j] = detune; - detunetable[i + 4][j] = -detune; - } - } - for (i = 0; i < 4; i++) - { - attacktable[i] = decaytable[i] = 0; - } - for (i = 4; i < 64; i++) - { - freq = (EVC_ENT << (ENV_BITS + ratebit)) * 72.0 / 64.0; - if (i < 60) - { - freq *= 1.0 + (i & 3) * 0.25; - } - freq *= (double)(1 << ((i >> 2) - 1)); - attacktable[i] = (SINT32)(freq / OPM_ARRATE); - decaytable[i] = (SINT32)(freq / OPM_DRRATE); - if (attacktable[i] >= EC_DECAY) - { - TRACEOUT(("attacktable %d %d %ld", i, attacktable[i], EC_DECAY)); - } - if (decaytable[i] >= EC_DECAY) - { - TRACEOUT(("decaytable %d %d %ld", i, decaytable[i], EC_DECAY)); - } - } - attacktable[62] = EC_DECAY - 1; - attacktable[63] = EC_DECAY - 1; - for (i = 64; i < 94; i++) - { - attacktable[i] = attacktable[63]; - decaytable[i] = decaytable[63]; - } -} - -void opngen_setvol(UINT vol) -{ - opncfg.fmvol = vol * 5 / 4; -#if defined(OPNGENX86) - opncfg.fmvol <<= (32 - (OPM_OUTSB + 1 - FMVOL_SFTBIT + FMDIV_BITS + 6)); -#endif -} - -void opngen_setVR(REG8 channel, REG8 value) -{ - if ((channel & 3) && (value)) - { - opncfg.vr_en = TRUE; - opncfg.vr_l = (channel & 1) ? value : 0; - opncfg.vr_r = (channel & 2) ? value : 0; - } - else - { - opncfg.vr_en = FALSE; - } -} - - -/* ---- */ - -static void set_algorithm(OPNGEN opngen, OPNCH *ch) -{ - SINT32 *outd; - UINT8 outslot; - - outd = &opngen->outdc; - if (ch->stereo) - { - switch (ch->pan & 0xc0) - { - case 0x80: - outd = &opngen->outdl; - break; - - case 0x40: - outd = &opngen->outdr; - break; - } - } - switch (ch->algorithm) - { - case 0: - ch->connect1 = &opngen->feedback2; - ch->connect2 = &opngen->feedback3; - ch->connect3 = &opngen->feedback4; - outslot = 0x08; - break; - - case 1: - ch->connect1 = &opngen->feedback3; - ch->connect2 = &opngen->feedback3; - ch->connect3 = &opngen->feedback4; - outslot = 0x08; - break; - - case 2: - ch->connect1 = &opngen->feedback4; - ch->connect2 = &opngen->feedback3; - ch->connect3 = &opngen->feedback4; - outslot = 0x08; - break; - - case 3: - ch->connect1 = &opngen->feedback2; - ch->connect2 = &opngen->feedback4; - ch->connect3 = &opngen->feedback4; - outslot = 0x08; - break; - - case 4: - ch->connect1 = &opngen->feedback2; - ch->connect2 = outd; - ch->connect3 = &opngen->feedback4; - outslot = 0x0a; - break; - - case 5: - ch->connect1 = 0; - ch->connect2 = outd; - ch->connect3 = outd; - outslot = 0x0e; - break; - - case 6: - ch->connect1 = &opngen->feedback2; - ch->connect2 = outd; - ch->connect3 = outd; - outslot = 0x0e; - break; - - case 7: - default: - ch->connect1 = outd; - ch->connect2 = outd; - ch->connect3 = outd; - outslot = 0x0f; - } - ch->connect4 = outd; - ch->outslot = outslot; -} - -static void set_dt1_mul(OPNSLOT *slot, REG8 value) -{ - slot->multiple = (SINT32)multipletable[value & 0x0f]; - slot->detune1 = detunetable[(value >> 4) & 7]; -} - -static void set_tl(OPNSLOT *slot, REG8 value) -{ -#if (EVC_BITS >= 7) - slot->totallevel = ((~value) & 0x007f) << (EVC_BITS - 7); -#else - slot->totallevel = ((~value) & 0x007f) >> (7 - EVC_BITS); -#endif -} - -static void set_ks_ar(OPNSLOT *slot, REG8 value) -{ - slot->keyscalerate = ((~value) >> 6) & 3; - value &= 0x1f; - slot->attack = (value) ? (attacktable + (value << 1)) : nulltable; - slot->env_inc_attack = slot->attack[slot->envratio]; - if (slot->env_mode == EM_ATTACK) - { - slot->env_inc = slot->env_inc_attack; - } -} - -static void set_d1r(OPNSLOT *slot, REG8 value) -{ - value &= 0x1f; - slot->decay1 = (value) ? (decaytable + (value << 1)) : nulltable; - slot->env_inc_decay1 = slot->decay1[slot->envratio]; - if (slot->env_mode == EM_DECAY1) - { - slot->env_inc = slot->env_inc_decay1; - } -} - -static void set_dt2_d2r(OPNSLOT *slot, REG8 value) -{ - value &= 0x1f; - slot->decay2 = (value) ? (decaytable + (value << 1)) : nulltable; - if (slot->ssgeg1) - { - slot->env_inc_decay2 = 0; - } - else - { - slot->env_inc_decay2 = slot->decay2[slot->envratio]; - } - if (slot->env_mode == EM_DECAY2) - { - slot->env_inc = slot->env_inc_decay2; - } -} - -static void set_d1l_rr(OPNSLOT *slot, REG8 value) -{ - slot->decaylevel = decayleveltable[(value >> 4)]; - slot->release = decaytable + ((value & 0x0f) << 2) + 2; - slot->env_inc_release = slot->release[slot->envratio]; - if (slot->env_mode == EM_RELEASE) - { - slot->env_inc = slot->env_inc_release; - if (value == 0xff) - { - slot->env_mode = EM_OFF; - slot->env_cnt = EC_OFF; - slot->env_end = EC_OFF + 1; - slot->env_inc = 0; - } - } -} - -static void set_ssgeg(OPNSLOT *slot, REG8 value) -{ - value &= 0xf; - if ((value == 0xb) || (value == 0xd)) - { - slot->ssgeg1 = 1; - slot->env_inc_decay2 = 0; - } - else - { - slot->ssgeg1 = 0; - slot->env_inc_decay2 = slot->decay2[slot->envratio]; - } - if (slot->env_mode == EM_DECAY2) - { - slot->env_inc = slot->env_inc_decay2; - } -} - -static void channleupdate(OPNCH *ch) -{ - UINT i; - UINT32 fc = ch->keynote[0]; - UINT8 kc = ch->kcode[0]; - UINT evr; - OPNSLOT *slot; - int s; - - slot = ch->slot; - if (!(ch->extop)) - { - for (i = 0; i < 4; i++, slot++) - { - slot->freq_inc = ((fc + slot->detune1[kc]) * slot->multiple) >> 1; - evr = kc >> slot->keyscalerate; - if (slot->envratio != evr) - { - slot->envratio = evr; - slot->env_inc_attack = slot->attack[evr]; - slot->env_inc_decay1 = slot->decay1[evr]; - slot->env_inc_decay2 = slot->decay2[evr]; - slot->env_inc_release = slot->release[evr]; - } - } - } - else - { - for (i = 0; i < 4; i++, slot++) - { - s = extendslot[i]; - slot->freq_inc = ((ch->keynote[s] + slot->detune1[ch->kcode[s]]) * slot->multiple) >> 1; - evr = ch->kcode[s] >> slot->keyscalerate; - if (slot->envratio != evr) - { - slot->envratio = evr; - slot->env_inc_attack = slot->attack[evr]; - slot->env_inc_decay1 = slot->decay1[evr]; - slot->env_inc_decay2 = slot->decay2[evr]; - slot->env_inc_release = slot->release[evr]; - } - } - } -} - - -/* ---- */ - -void opngen_reset(OPNGEN opngen) -{ - OPNCH *ch; - UINT i; - OPNSLOT *slot; - UINT j; - - memset(opngen, 0, sizeof(*opngen)); - opngen->playchannels = 3; - - ch = opngen->opnch; - for (i = 0; i < OPNCH_MAX; i++) - { - ch->keynote[0] = 0; - slot = ch->slot; - for (j = 0; j < 4; j++) - { - slot->env_mode = EM_OFF; - slot->env_cnt = EC_OFF; - slot->env_end = EC_OFF + 1; - slot->env_inc = 0; - slot->detune1 = detunetable[0]; - slot->attack = nulltable; - slot->decay1 = nulltable; - slot->decay2 = nulltable; - slot->release = decaytable; - slot++; - } - ch++; - } - for (i = 0x30; i < 0xc0; i++) - { - opngen_setreg(opngen, 0, i, 0xff); - opngen_setreg(opngen, 3, i, 0xff); - } -} - -void opngen_setcfg(OPNGEN opngen, REG8 maxch, UINT32 flag) -{ - OPNCH *ch; - UINT i; - - opngen->playchannels = maxch; - ch = opngen->opnch; - if ((flag & OPN_CHMASK) == OPN_STEREO) - { - for (i = 0; i < OPNCH_MAX; i++) - { - if (flag & (1 << i)) - { - ch->stereo = TRUE; - set_algorithm(opngen, ch); - } - ch++; - } - } - else - { - for (i = 0; i < OPNCH_MAX; i++) - { - if (flag & (1 << i)) - { - ch->stereo = FALSE; - set_algorithm(opngen, ch); - } - ch++; - } - } -} - -void opngen_setextch(OPNGEN opngen, UINT chnum, REG8 data) -{ - OPNCH *ch; - - ch = opngen->opnch; - ch[chnum].extop = data; -} - -void opngen_setreg(OPNGEN opngen, REG8 chbase, UINT reg, REG8 value) -{ - UINT chpos; - OPNCH *ch; - OPNSLOT *slot; - UINT fn; - UINT8 blk; - - chpos = reg & 3; - if (chpos == 3) - { - return; - } - sound_sync(); - ch = opngen->opnch + chbase + chpos; - if (reg < 0xa0) - { - slot = ch->slot + fmslot[(reg >> 2) & 3]; - switch (reg & 0xf0) - { - case 0x30: /* DT1 MUL */ - set_dt1_mul(slot, value); - channleupdate(ch); - break; - - case 0x40: /* TL */ - set_tl(slot, value); - break; - - case 0x50: /* KS AR */ - set_ks_ar(slot, value); - channleupdate(ch); - break; - - case 0x60: /* D1R */ - set_d1r(slot, value); - break; - - case 0x70: /* DT2 D2R */ - set_dt2_d2r(slot, value); - channleupdate(ch); - break; - - case 0x80: /* D1L RR */ - set_d1l_rr(slot, value); - break; - - case 0x90: - set_ssgeg(slot, value); - channleupdate(ch); - break; - } - } - else - { - switch (reg & 0xfc) - { - case 0xa0: - blk = ch->keyfunc[0] >> 3; - fn = ((ch->keyfunc[0] & 7) << 8) + value; - ch->kcode[0] = (blk << 2) | kftable[fn >> 7]; - ch->keynote[0] = fn << (opncfg.ratebit + blk + FREQ_BITS - 21); - channleupdate(ch); - break; - - case 0xa4: - ch->keyfunc[0] = value & 0x3f; - break; - - case 0xa8: - ch = opngen->opnch + chbase + 2; - blk = ch->keyfunc[chpos+1] >> 3; - fn = ((ch->keyfunc[chpos+1] & 7) << 8) + value; - ch->kcode[chpos + 1] = (blk << 2) | kftable[fn >> 7]; - ch->keynote[chpos + 1] = fn << (opncfg.ratebit + blk + FREQ_BITS - 21); - channleupdate(ch); - break; - - case 0xac: - ch = opngen->opnch + chbase + 2; - ch->keyfunc[chpos + 1] = value & 0x3f; - break; - - case 0xb0: - ch->algorithm = (UINT8)(value & 7); - value = (value >> 3) & 7; - if (value) - { - ch->feedback = 8 - value; - } - else - { - ch->feedback = 0; - } - set_algorithm(opngen, ch); - break; - - case 0xb4: - ch->pan = (UINT8)(value & 0xc0); - set_algorithm(opngen, ch); - break; - } - } -} - -void opngen_keyon(OPNGEN opngen, UINT chnum, REG8 value) -{ - OPNCH *ch; - OPNSLOT *slot; - REG8 bit; - UINT i; - - sound_sync(); - opngen->playing++; - ch = opngen->opnch + chnum; - ch->playing |= value >> 4; - slot = ch->slot; - bit = 0x10; - for (i = 0; i < 4; i++) - { - if (value & bit) /* keyon */ - { - if (slot->env_mode <= EM_RELEASE) - { - slot->freq_cnt = 0; - if (i == OPNSLOT1) - { - ch->op1fb = 0; - } - slot->env_mode = EM_ATTACK; - slot->env_inc = slot->env_inc_attack; - slot->env_cnt = EC_ATTACK; - slot->env_end = EC_DECAY; - } - } - else /* keyoff */ - { - if (slot->env_mode > EM_RELEASE) - { - slot->env_mode = EM_RELEASE; - if (!(slot->env_cnt & EC_DECAY)) - { - slot->env_cnt = (opncfg.envcurve[slot->env_cnt >> ENV_BITS] << ENV_BITS) + EC_DECAY; - } - slot->env_end = EC_OFF; - slot->env_inc = slot->env_inc_release; - } - } - slot++; - bit <<= 1; - } -} - -void opngen_csm(OPNGEN opngen) -{ - opngen_keyon(opngen, 2, 0x02); - opngen_keyon(opngen, 2, 0xf2); -} +/** + * @file opngenc.c + * @brief Implementation of the OPN generator + */ + +#include +#include +#include +#include "opngencfg.h" +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327 +#endif + +#define OPM_ARRATE 399128L +#define OPM_DRRATE 5514396L + +#define EG_STEP (96.0 / EVC_ENT) /* dB step */ +#define SC(db) (SINT32)((db) * ((3.0 / EG_STEP) * (1 << ENV_BITS))) + EC_DECAY + + + OPNCFG opncfg; +#ifdef OPNGENX86 + char envshift[EVC_ENT]; + char sinshift[SIN_ENT]; +#endif + + +static SINT32 detunetable[8][32]; +static SINT32 attacktable[94]; +static SINT32 decaytable[94]; + +static const SINT32 decayleveltable[16] = { + SC( 0),SC( 1),SC( 2),SC( 3),SC( 4),SC( 5),SC( 6),SC( 7), + SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)}; +static const UINT8 multipletable[] = { + 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}; +static const SINT32 nulltable[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +static const UINT8 kftable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3}; +static const UINT8 dttable[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, + 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16, + 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, + 8, 8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22}; +static const int extendslot[4] = {2, 3, 1, 0}; +static const int fmslot[4] = {0, 2, 1, 3}; + + +void opngen_initialize(UINT rate) +{ + UINT ratebit; + int i; + char sft; + int j; + double pom; + SINT32 detune; + double freq; + + if (rate > (OPNA_CLOCK / 144.0)) + { + ratebit = 0; + } + else if (rate > (OPNA_CLOCK / 288.0)) + { + ratebit = 1; + } + else + { + ratebit = 2; + } + opncfg.calc1024 = (SINT32)((FMDIV_ENT * (rate << ratebit) / (OPNA_CLOCK / 72.0)) + 0.5); + + for (i = 0; i < EVC_ENT; i++) + { +#ifdef OPNGENX86 + sft = ENVTBL_BIT; + while (sft < (ENVTBL_BIT + 8)) + { + pom = (double)(1 << sft) / pow(10.0, EG_STEP * (EVC_ENT - i) / 20.0); + opncfg.envtable[i] = (SINT32)pom; + envshift[i] = sft - TL_BITS; + if (opncfg.envtable[i] >= (1 << (ENVTBL_BIT - 1))) + { + break; + } + sft++; + } +#else + pom = (double)(1 << ENVTBL_BIT) / pow(10.0, EG_STEP * (EVC_ENT - i) / 20.0); + opncfg.envtable[i] = (SINT32)pom; +#endif + } + for (i = 0; i < SIN_ENT; i++) + { +#ifdef OPNGENX86 + sft = SINTBL_BIT; + while (sft < (SINTBL_BIT + 8)) + { + pom = (double)((1 << sft) - 1) * sin(2 * M_PI * i / SIN_ENT); + opncfg.sintable[i] = (SINT32)pom; + sinshift[i] = sft; + if (opncfg.sintable[i] >= (1 << (SINTBL_BIT - 1))) + { + break; + } + if (opncfg.sintable[i] <= -1 * (1 << (SINTBL_BIT - 1))) + { + break; + } + sft++; + } +#else + pom = (double)((1 << SINTBL_BIT) - 1) * sin(2 * M_PI * i / SIN_ENT); + opncfg.sintable[i] = (SINT32)pom; +#endif + } + for (i = 0; i < EVC_ENT; i++) + { + pom = pow(((double)(EVC_ENT - 1 - i) / EVC_ENT), 8) * EVC_ENT; + opncfg.envcurve[i] = (SINT32)pom; + opncfg.envcurve[EVC_ENT + i] = i; + } + opncfg.envcurve[EVC_ENT * 2] = EVC_ENT; + + opncfg.ratebit = ratebit; + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 32; j++) + { + detune = dttable[i*32 + j]; + sft = ratebit + (FREQ_BITS - 20); + if (sft >= 0) + { + detune <<= sft; + } + else + { + detune >>= (0 - sft); + } + + detunetable[i + 0][j] = detune; + detunetable[i + 4][j] = -detune; + } + } + for (i = 0; i < 4; i++) + { + attacktable[i] = decaytable[i] = 0; + } + for (i = 4; i < 64; i++) + { + freq = (EVC_ENT << (ENV_BITS + ratebit)) * 72.0 / 64.0; + if (i < 60) + { + freq *= 1.0 + (i & 3) * 0.25; + } + freq *= (double)(1 << ((i >> 2) - 1)); + attacktable[i] = (SINT32)(freq / OPM_ARRATE); + decaytable[i] = (SINT32)(freq / OPM_DRRATE); + if (attacktable[i] >= EC_DECAY) + { + TRACEOUT(("attacktable %d %d %ld", i, attacktable[i], EC_DECAY)); + } + if (decaytable[i] >= EC_DECAY) + { + TRACEOUT(("decaytable %d %d %ld", i, decaytable[i], EC_DECAY)); + } + } + attacktable[62] = EC_DECAY - 1; + attacktable[63] = EC_DECAY - 1; + for (i = 64; i < 94; i++) + { + attacktable[i] = attacktable[63]; + decaytable[i] = decaytable[63]; + } +} + +void opngen_setvol(UINT vol) +{ + opncfg.fmvol = vol * 5 / 4; +#if defined(OPNGENX86) + opncfg.fmvol <<= (32 - (OPM_OUTSB + 1 - FMVOL_SFTBIT + FMDIV_BITS + 6)); +#endif +} + +void opngen_setVR(REG8 channel, REG8 value) +{ + if ((channel & 3) && (value)) + { + opncfg.vr_en = TRUE; + opncfg.vr_l = (channel & 1) ? value : 0; + opncfg.vr_r = (channel & 2) ? value : 0; + } + else + { + opncfg.vr_en = FALSE; + } +} + + +/* ---- */ + +static void set_algorithm(OPNGEN opngen, OPNCH *ch) +{ + SINT32 *outd; + UINT8 outslot; + + outd = &opngen->outdc; + if (ch->stereo) + { + switch (ch->pan & 0xc0) + { + case 0x80: + outd = &opngen->outdl; + break; + + case 0x40: + outd = &opngen->outdr; + break; + } + } + switch (ch->algorithm) + { + case 0: + ch->connect1 = &opngen->feedback2; + ch->connect2 = &opngen->feedback3; + ch->connect3 = &opngen->feedback4; + outslot = 0x08; + break; + + case 1: + ch->connect1 = &opngen->feedback3; + ch->connect2 = &opngen->feedback3; + ch->connect3 = &opngen->feedback4; + outslot = 0x08; + break; + + case 2: + ch->connect1 = &opngen->feedback4; + ch->connect2 = &opngen->feedback3; + ch->connect3 = &opngen->feedback4; + outslot = 0x08; + break; + + case 3: + ch->connect1 = &opngen->feedback2; + ch->connect2 = &opngen->feedback4; + ch->connect3 = &opngen->feedback4; + outslot = 0x08; + break; + + case 4: + ch->connect1 = &opngen->feedback2; + ch->connect2 = outd; + ch->connect3 = &opngen->feedback4; + outslot = 0x0a; + break; + + case 5: + ch->connect1 = 0; + ch->connect2 = outd; + ch->connect3 = outd; + outslot = 0x0e; + break; + + case 6: + ch->connect1 = &opngen->feedback2; + ch->connect2 = outd; + ch->connect3 = outd; + outslot = 0x0e; + break; + + case 7: + default: + ch->connect1 = outd; + ch->connect2 = outd; + ch->connect3 = outd; + outslot = 0x0f; + } + ch->connect4 = outd; + ch->outslot = outslot; +} + +static void set_dt1_mul(OPNSLOT *slot, REG8 value) +{ + slot->multiple = (SINT32)multipletable[value & 0x0f]; + slot->detune1 = detunetable[(value >> 4) & 7]; +} + +static void set_tl(OPNSLOT *slot, REG8 value) +{ +#if (EVC_BITS >= 7) + slot->totallevel = ((~value) & 0x007f) << (EVC_BITS - 7); +#else + slot->totallevel = ((~value) & 0x007f) >> (7 - EVC_BITS); +#endif +} + +static void set_ks_ar(OPNSLOT *slot, REG8 value) +{ + slot->keyscalerate = ((~value) >> 6) & 3; + value &= 0x1f; + slot->attack = (value) ? (attacktable + (value << 1)) : nulltable; + slot->env_inc_attack = slot->attack[slot->envratio]; + if (slot->env_mode == EM_ATTACK) + { + slot->env_inc = slot->env_inc_attack; + } +} + +static void set_d1r(OPNSLOT *slot, REG8 value) +{ + value &= 0x1f; + slot->decay1 = (value) ? (decaytable + (value << 1)) : nulltable; + slot->env_inc_decay1 = slot->decay1[slot->envratio]; + if (slot->env_mode == EM_DECAY1) + { + slot->env_inc = slot->env_inc_decay1; + } +} + +static void set_dt2_d2r(OPNSLOT *slot, REG8 value) +{ + value &= 0x1f; + slot->decay2 = (value) ? (decaytable + (value << 1)) : nulltable; + if (slot->ssgeg1) + { + slot->env_inc_decay2 = 0; + } + else + { + slot->env_inc_decay2 = slot->decay2[slot->envratio]; + } + if (slot->env_mode == EM_DECAY2) + { + slot->env_inc = slot->env_inc_decay2; + } +} + +static void set_d1l_rr(OPNSLOT *slot, REG8 value) +{ + slot->decaylevel = decayleveltable[(value >> 4)]; + slot->release = decaytable + ((value & 0x0f) << 2) + 2; + slot->env_inc_release = slot->release[slot->envratio]; + if (slot->env_mode == EM_RELEASE) + { + slot->env_inc = slot->env_inc_release; + if (value == 0xff) + { + slot->env_mode = EM_OFF; + slot->env_cnt = EC_OFF; + slot->env_end = EC_OFF + 1; + slot->env_inc = 0; + } + } +} + +static void set_ssgeg(OPNSLOT *slot, REG8 value) +{ + value &= 0xf; + if ((value == 0xb) || (value == 0xd)) + { + slot->ssgeg1 = 1; + slot->env_inc_decay2 = 0; + } + else + { + slot->ssgeg1 = 0; + slot->env_inc_decay2 = slot->decay2[slot->envratio]; + } + if (slot->env_mode == EM_DECAY2) + { + slot->env_inc = slot->env_inc_decay2; + } +} + +static void channleupdate(OPNCH *ch) +{ + UINT i; + UINT32 fc = ch->keynote[0]; + UINT8 kc = ch->kcode[0]; + UINT evr; + OPNSLOT *slot; + int s; + + slot = ch->slot; + if (!(ch->extop)) + { + for (i = 0; i < 4; i++, slot++) + { + slot->freq_inc = ((fc + slot->detune1[kc]) * slot->multiple) >> 1; + evr = kc >> slot->keyscalerate; + if (slot->envratio != evr) + { + slot->envratio = evr; + slot->env_inc_attack = slot->attack[evr]; + slot->env_inc_decay1 = slot->decay1[evr]; + slot->env_inc_decay2 = slot->decay2[evr]; + slot->env_inc_release = slot->release[evr]; + } + } + } + else + { + for (i = 0; i < 4; i++, slot++) + { + s = extendslot[i]; + slot->freq_inc = ((ch->keynote[s] + slot->detune1[ch->kcode[s]]) * slot->multiple) >> 1; + evr = ch->kcode[s] >> slot->keyscalerate; + if (slot->envratio != evr) + { + slot->envratio = evr; + slot->env_inc_attack = slot->attack[evr]; + slot->env_inc_decay1 = slot->decay1[evr]; + slot->env_inc_decay2 = slot->decay2[evr]; + slot->env_inc_release = slot->release[evr]; + } + } + } +} + + +/* ---- */ + +void opngen_reset(OPNGEN opngen) +{ + OPNCH *ch; + UINT i; + OPNSLOT *slot; + UINT j; + + memset(opngen, 0, sizeof(*opngen)); + opngen->playchannels = 3; + + ch = opngen->opnch; + for (i = 0; i < OPNCH_MAX; i++) + { + ch->keynote[0] = 0; + slot = ch->slot; + for (j = 0; j < 4; j++) + { + slot->env_mode = EM_OFF; + slot->env_cnt = EC_OFF; + slot->env_end = EC_OFF + 1; + slot->env_inc = 0; + slot->detune1 = detunetable[0]; + slot->attack = nulltable; + slot->decay1 = nulltable; + slot->decay2 = nulltable; + slot->release = decaytable; + slot++; + } + ch++; + } + for (i = 0x30; i < 0xc0; i++) + { + opngen_setreg(opngen, 0, i, 0xff); + opngen_setreg(opngen, 3, i, 0xff); + } +} + +void opngen_setcfg(OPNGEN opngen, REG8 maxch, UINT32 flag) +{ + OPNCH *ch; + UINT i; + + opngen->playchannels = maxch; + ch = opngen->opnch; + if ((flag & OPN_CHMASK) == OPN_STEREO) + { + for (i = 0; i < OPNCH_MAX; i++) + { + if (flag & (1 << i)) + { + ch->stereo = TRUE; + set_algorithm(opngen, ch); + } + ch++; + } + } + else + { + for (i = 0; i < OPNCH_MAX; i++) + { + if (flag & (1 << i)) + { + ch->stereo = FALSE; + set_algorithm(opngen, ch); + } + ch++; + } + } +} + +void opngen_setextch(OPNGEN opngen, UINT chnum, REG8 data) +{ + OPNCH *ch; + + ch = opngen->opnch; + ch[chnum].extop = data; +} + +void opngen_setreg(OPNGEN opngen, REG8 chbase, UINT reg, REG8 value) +{ + UINT chpos; + OPNCH *ch; + OPNSLOT *slot; + UINT fn; + UINT8 blk; + + chpos = reg & 3; + if (chpos == 3) + { + return; + } + sound_sync(); + ch = opngen->opnch + chbase + chpos; + if (reg < 0xa0) + { + slot = ch->slot + fmslot[(reg >> 2) & 3]; + switch (reg & 0xf0) + { + case 0x30: /* DT1 MUL */ + set_dt1_mul(slot, value); + channleupdate(ch); + break; + + case 0x40: /* TL */ + set_tl(slot, value); + break; + + case 0x50: /* KS AR */ + set_ks_ar(slot, value); + channleupdate(ch); + break; + + case 0x60: /* D1R */ + set_d1r(slot, value); + break; + + case 0x70: /* DT2 D2R */ + set_dt2_d2r(slot, value); + channleupdate(ch); + break; + + case 0x80: /* D1L RR */ + set_d1l_rr(slot, value); + break; + + case 0x90: + set_ssgeg(slot, value); + channleupdate(ch); + break; + } + } + else + { + switch (reg & 0xfc) + { + case 0xa0: + blk = ch->keyfunc[0] >> 3; + fn = ((ch->keyfunc[0] & 7) << 8) + value; + ch->kcode[0] = (blk << 2) | kftable[fn >> 7]; + ch->keynote[0] = fn << (opncfg.ratebit + blk + FREQ_BITS - 21); + channleupdate(ch); + break; + + case 0xa4: + ch->keyfunc[0] = value & 0x3f; + break; + + case 0xa8: + ch = opngen->opnch + chbase + 2; + blk = ch->keyfunc[chpos+1] >> 3; + fn = ((ch->keyfunc[chpos+1] & 7) << 8) + value; + ch->kcode[chpos + 1] = (blk << 2) | kftable[fn >> 7]; + ch->keynote[chpos + 1] = fn << (opncfg.ratebit + blk + FREQ_BITS - 21); + channleupdate(ch); + break; + + case 0xac: + ch = opngen->opnch + chbase + 2; + ch->keyfunc[chpos + 1] = value & 0x3f; + break; + + case 0xb0: + ch->algorithm = (UINT8)(value & 7); + value = (value >> 3) & 7; + if (value) + { + ch->feedback = 8 - value; + } + else + { + ch->feedback = 0; + } + set_algorithm(opngen, ch); + break; + + case 0xb4: + ch->pan = (UINT8)(value & 0xc0); + set_algorithm(opngen, ch); + break; + } + } +} + +void opngen_keyon(OPNGEN opngen, UINT chnum, REG8 value) +{ + OPNCH *ch; + OPNSLOT *slot; + REG8 bit; + UINT i; + + sound_sync(); + opngen->playing++; + ch = opngen->opnch + chnum; + ch->playing |= value >> 4; + slot = ch->slot; + bit = 0x10; + for (i = 0; i < 4; i++) + { + if (value & bit) /* keyon */ + { + if (slot->env_mode <= EM_RELEASE) + { + slot->freq_cnt = 0; + if (i == OPNSLOT1) + { + ch->op1fb = 0; + } + slot->env_mode = EM_ATTACK; + slot->env_inc = slot->env_inc_attack; + slot->env_cnt = EC_ATTACK; + slot->env_end = EC_DECAY; + } + } + else /* keyoff */ + { + if (slot->env_mode > EM_RELEASE) + { + slot->env_mode = EM_RELEASE; + if (!(slot->env_cnt & EC_DECAY)) + { + slot->env_cnt = (opncfg.envcurve[slot->env_cnt >> ENV_BITS] << ENV_BITS) + EC_DECAY; + } + slot->env_end = EC_OFF; + slot->env_inc = slot->env_inc_release; + } + } + slot++; + bit <<= 1; + } +} + +void opngen_csm(OPNGEN opngen) +{ + opngen_keyon(opngen, 2, 0x02); + opngen_keyon(opngen, 2, 0xf2); +} diff --git a/sound/opngencfg.h b/sound/opngencfg.h old mode 100755 new mode 100644 index 876666c7..d6434793 --- a/sound/opngencfg.h +++ b/sound/opngencfg.h @@ -1,78 +1,78 @@ -/** - * @file opngencfg.h - * @brief Interface of the OPN generator - */ - -#pragma once - -enum -{ - FMDIV_BITS = 10, - FMDIV_ENT = (1 << FMDIV_BITS), - FMVOL_SFTBIT = 4 -}; - -#if defined(OPNGENX86) - -#define SIN_BITS 11 -#define EVC_BITS 10 -#define ENV_BITS 16 -#define FREQ_BITS 21 -#define ENVTBL_BIT 14 -#define SINTBL_BIT 14 - -#else - -#define SIN_BITS 10 -#define EVC_BITS 10 -#define ENV_BITS 16 -#define FREQ_BITS 21 -#define ENVTBL_BIT 14 -#define SINTBL_BIT 15 - -#endif - -#define TL_BITS (FREQ_BITS + 2) -#define OPM_OUTSB (TL_BITS + 2 - 16) /* OPM output 16bit */ - -#define SIN_ENT (1L << SIN_BITS) -#define EVC_ENT (1L << EVC_BITS) - -#define EC_ATTACK 0 /* ATTACK start */ -#define EC_DECAY (EVC_ENT << ENV_BITS) /* DECAY start */ -#define EC_OFF ((2 * EVC_ENT) << ENV_BITS) /* OFF */ - -enum -{ - /* slot number */ - OPNSLOT1 = 0, - OPNSLOT2 = 1, - OPNSLOT3 = 2, - OPNSLOT4 = 3, - - EM_ATTACK = 4, - EM_DECAY1 = 3, - EM_DECAY2 = 2, - EM_RELEASE = 1, - EM_OFF = 0 -}; - -typedef struct -{ - SINT32 calc1024; - SINT32 fmvol; - UINT ratebit; - UINT vr_en; - SINT32 vr_l; - SINT32 vr_r; - - SINT32 sintable[SIN_ENT]; - SINT32 envtable[EVC_ENT]; - SINT32 envcurve[EVC_ENT*2 + 1]; - -#if defined(SUPPORT_FMGEN) - UINT8 usefmgen; -#endif /* SUPPORT_FMGEN */ -} OPNCFG; - -extern OPNCFG opncfg; +/** + * @file opngencfg.h + * @brief Interface of the OPN generator + */ + +#pragma once + +enum +{ + FMDIV_BITS = 10, + FMDIV_ENT = (1 << FMDIV_BITS), + FMVOL_SFTBIT = 4 +}; + +#if defined(OPNGENX86) + +#define SIN_BITS 11 +#define EVC_BITS 10 +#define ENV_BITS 16 +#define FREQ_BITS 21 +#define ENVTBL_BIT 14 +#define SINTBL_BIT 14 + +#else + +#define SIN_BITS 10 +#define EVC_BITS 10 +#define ENV_BITS 16 +#define FREQ_BITS 21 +#define ENVTBL_BIT 14 +#define SINTBL_BIT 15 + +#endif + +#define TL_BITS (FREQ_BITS + 2) +#define OPM_OUTSB (TL_BITS + 2 - 16) /* OPM output 16bit */ + +#define SIN_ENT (1L << SIN_BITS) +#define EVC_ENT (1L << EVC_BITS) + +#define EC_ATTACK 0 /* ATTACK start */ +#define EC_DECAY (EVC_ENT << ENV_BITS) /* DECAY start */ +#define EC_OFF ((2 * EVC_ENT) << ENV_BITS) /* OFF */ + +enum +{ + /* slot number */ + OPNSLOT1 = 0, + OPNSLOT2 = 1, + OPNSLOT3 = 2, + OPNSLOT4 = 3, + + EM_ATTACK = 4, + EM_DECAY1 = 3, + EM_DECAY2 = 2, + EM_RELEASE = 1, + EM_OFF = 0 +}; + +typedef struct +{ + SINT32 calc1024; + SINT32 fmvol; + UINT ratebit; + UINT vr_en; + SINT32 vr_l; + SINT32 vr_r; + + SINT32 sintable[SIN_ENT]; + SINT32 envtable[EVC_ENT]; + SINT32 envcurve[EVC_ENT*2 + 1]; + +#if defined(SUPPORT_FMGEN) + UINT8 usefmgen; +#endif /* SUPPORT_FMGEN */ +} OPNCFG; + +extern OPNCFG opncfg; diff --git a/sound/opngeng.c b/sound/opngeng.c old mode 100755 new mode 100644 index 0e61c71f..54b90ad3 --- a/sound/opngeng.c +++ b/sound/opngeng.c @@ -1,285 +1,285 @@ -/** - * @file opngeng.c - * @brief Implementation of the OPN generator - */ - -#include -#include -#include "opngencfg.h" - -#if defined(OPNGENX86) -extern char envshift[EVC_ENT]; -extern char sinshift[SIN_ENT]; -#endif /* defined(OPNGENX86) */ - -#define CALCENV(e, c, s) \ - (c)->slot[(s)].freq_cnt += (c)->slot[(s)].freq_inc; \ - (c)->slot[(s)].env_cnt += (c)->slot[(s)].env_inc; \ - if ((c)->slot[(s)].env_cnt >= (c)->slot[(s)].env_end) \ - { \ - switch ((c)->slot[(s)].env_mode) \ - { \ - case EM_ATTACK: \ - (c)->slot[(s)].env_mode = EM_DECAY1; \ - (c)->slot[(s)].env_cnt = EC_DECAY; \ - (c)->slot[(s)].env_end = (c)->slot[(s)].decaylevel; \ - (c)->slot[(s)].env_inc = (c)->slot[(s)].env_inc_decay1; \ - break; \ - case EM_DECAY1: \ - (c)->slot[(s)].env_mode = EM_DECAY2; \ - (c)->slot[(s)].env_cnt = (c)->slot[(s)].decaylevel; \ - (c)->slot[(s)].env_end = EC_OFF; \ - (c)->slot[(s)].env_inc = (c)->slot[(s)].env_inc_decay2; \ - break; \ - case EM_RELEASE: \ - (c)->slot[(s)].env_mode = EM_OFF; \ - case EM_DECAY2: \ - (c)->slot[(s)].env_cnt = EC_OFF; \ - (c)->slot[(s)].env_end = EC_OFF + 1; \ - (c)->slot[(s)].env_inc = 0; \ - (c)->playing &= ~(1 << (s)); \ - break; \ - } \ - } \ - (e) = (c)->slot[(s)].totallevel - \ - opncfg.envcurve[(c)->slot[(s)].env_cnt >> ENV_BITS]; - -#if defined(OPNGENX86) -static SINT32 SLOTOUT(SINT32 e, SINT32 c) -{ - c = (c >> (FREQ_BITS - SIN_BITS)) & (SIN_ENT - 1); - return (opncfg.sintable[c] * opncfg.envtable[e]) >> (sinshift[c] + envshift[e]); -} -#else /* defined(OPNGENX86) */ -#define SLOTOUT(e, c) \ - ((opncfg.sintable[((c) >> (FREQ_BITS - SIN_BITS)) & (SIN_ENT - 1)] \ - * opncfg.envtable[(e)]) >> (ENVTBL_BIT + SINTBL_BIT - TL_BITS)) -#endif /* defined(OPNGENX86) */ - - -static void calcratechannel(OPNGEN opngen, OPNCH *ch) -{ - SINT32 envout; - SINT32 opout; - - opngen->feedback2 = 0; - opngen->feedback3 = 0; - opngen->feedback4 = 0; - - /* SLOT 1 */ - CALCENV(envout, ch, 0); - if (envout >= 0) - { - if (ch->feedback) - { - /* with self feed back */ - opout = ch->op1fb; - ch->op1fb = SLOTOUT(envout, ch->slot[0].freq_cnt + ((ch->op1fb >> ch->feedback) << (FREQ_BITS - (TL_BITS - 2)))); - opout = (opout + ch->op1fb) >> 1; - } - else - { - /* without self feed back */ - opout = SLOTOUT(envout, ch->slot[0].freq_cnt); - } - /* output slot1 */ - if (!ch->connect1) - { - opngen->feedback2 = opngen->feedback3 = opngen->feedback4 = opout; - } - else - { - *ch->connect1 += opout; - } - } - /* SLOT 2 */ - CALCENV(envout, ch, 1); - if (envout >= 0) - { - *ch->connect2 += SLOTOUT(envout, ch->slot[1].freq_cnt + (opngen->feedback2 << (FREQ_BITS - (TL_BITS - 2)))); - } - /* SLOT 3 */ - CALCENV(envout, ch, 2); - if (envout >= 0) - { - *ch->connect3 += SLOTOUT(envout, ch->slot[2].freq_cnt + (opngen->feedback3 << (FREQ_BITS - (TL_BITS - 2)))); - } - /* SLOT 4 */ - CALCENV(envout, ch, 3); - if (envout >= 0) - { - *ch->connect4 += SLOTOUT(envout, ch->slot[3].freq_cnt + (opngen->feedback4 << (FREQ_BITS - (TL_BITS - 2)))); - } -} - -void SOUNDCALL opngen_getpcm(OPNGEN opngen, SINT32 *pcm, UINT count) -{ - SINT32 samp_l; - SINT32 samp_r; - UINT playing; - UINT i; - OPNCH *ch; - - if ((!opngen->playing) || (!count)) - { - return; - } - - do - { - samp_l = opngen->outdl; - samp_r = opngen->outdr; - if (opngen->calcremain < FMDIV_ENT) - { - samp_l *= opngen->calcremain; - samp_r *= opngen->calcremain; - opngen->calcremain = FMDIV_ENT - opngen->calcremain; - while (TRUE /*CONSTCOND*/) - { - opngen->outdc = 0; - opngen->outdl = 0; - opngen->outdr = 0; - playing = 0; - for (i = 0; i < opngen->playchannels; i++) - { - ch = &opngen->opnch[i]; - if (ch->playing & ch->outslot) - { - calcratechannel(opngen, ch); - playing++; - } - } - opngen->playing = playing; - - opngen->outdl += opngen->outdc; - opngen->outdr += opngen->outdc; - opngen->outdl >>= FMVOL_SFTBIT; - opngen->outdr >>= FMVOL_SFTBIT; - if (opngen->calcremain > opncfg.calc1024) - { - opngen->calcremain -= opncfg.calc1024; - samp_l += opngen->outdl * opncfg.calc1024; - samp_r += opngen->outdr * opncfg.calc1024; - } - else - { - break; - } - } - samp_l += opngen->outdl * opngen->calcremain; - samp_r += opngen->outdr * opngen->calcremain; - opngen->calcremain = opncfg.calc1024 - opngen->calcremain; - } - else - { - samp_l *= FMDIV_ENT; - samp_r *= FMDIV_ENT; - opngen->calcremain -= FMDIV_ENT; - } - -#if defined(OPNGENX86) - pcm[0] += (SINT32)(((SINT64)samp_l * (SINT32)opncfg.fmvol) >> 32); - pcm[1] += (SINT32)(((SINT64)samp_r * (SINT32)opncfg.fmvol) >> 32); -#else /* defined(OPNGENX86) */ - samp_l >>= 8; - samp_l *= opncfg.fmvol; - samp_l >>= (OPM_OUTSB + FMDIV_BITS + 1 - FMVOL_SFTBIT - 8 + 6); - pcm[0] += samp_l; - samp_r >>= 8; - samp_r *= opncfg.fmvol; - samp_r >>= (OPM_OUTSB + FMDIV_BITS + 1 - FMVOL_SFTBIT - 8 + 6); - pcm[1] += samp_r; -#endif /* defined(OPNGENX86) */ - pcm += 2; - } while (--count); -} - -void SOUNDCALL opngen_getpcmvr(OPNGEN opngen, SINT32 *pcm, UINT count) -{ - SINT32 samp_l; - SINT32 samp_r; - UINT playing; - UINT i; - OPNCH *ch; - - if ((!opngen->playing) || (!count)) - { - return; - } - - do - { - samp_l = opngen->outdl; - samp_r = opngen->outdr; - if (opngen->calcremain < FMDIV_ENT) - { - samp_l *= opngen->calcremain; - samp_r *= opngen->calcremain; - opngen->calcremain = FMDIV_ENT - opngen->calcremain; - while (TRUE /*CONSTCOND*/) - { - opngen->outdc = 0; - opngen->outdl = 0; - opngen->outdr = 0; - playing = 0; - for (i = 0; i < opngen->playchannels; i++) - { - ch = &opngen->opnch[i]; - if (ch->playing & ch->outslot) - { - calcratechannel(opngen, ch); - playing++; - } - } - opngen->playing = playing; - - if (opncfg.vr_en) - { - SINT32 tmpl; - SINT32 tmpr; - tmpl = opngen->outdl * opncfg.vr_l; - tmpr = opngen->outdr * opncfg.vr_r; - opngen->outdl += (tmpr >> 5) + (tmpl >> 7); - opngen->outdr += (tmpl >> 5) + (tmpr >> 7); - } - opngen->outdl += opngen->outdc; - opngen->outdr += opngen->outdc; - opngen->outdl >>= FMVOL_SFTBIT; - opngen->outdr >>= FMVOL_SFTBIT; - if (opngen->calcremain > opncfg.calc1024) - { - samp_l += opngen->outdl * opncfg.calc1024; - samp_r += opngen->outdr * opncfg.calc1024; - opngen->calcremain -= opncfg.calc1024; - } - else - { - break; - } - } - samp_l += opngen->outdl * opngen->calcremain; - samp_r += opngen->outdr * opngen->calcremain; - } - else - { - samp_l *= FMDIV_ENT; - samp_r *= FMDIV_ENT; - opngen->calcremain -= FMDIV_ENT; - } -#if defined(OPNGENX86) - pcm[0] += (SINT32)(((SINT64)samp_l * (SINT32)opncfg.fmvol) >> 32); - pcm[1] += (SINT32)(((SINT64)samp_r * (SINT32)opncfg.fmvol) >> 32); -#else /* defined(OPNGENX86) */ - samp_l >>= 8; - samp_l *= opncfg.fmvol; - samp_l >>= (OPM_OUTSB + FMDIV_BITS + 1 - FMVOL_SFTBIT - 8 + 6); - pcm[0] += samp_l; - samp_r >>= 8; - samp_r *= opncfg.fmvol; - samp_r >>= (OPM_OUTSB + FMDIV_BITS + 1 - FMVOL_SFTBIT - 8 + 6); - pcm[1] += samp_r; -#endif /* defined(OPNGENX86) */ - opngen->calcremain = opncfg.calc1024 - opngen->calcremain; - pcm += 2; - } while (--count); -} +/** + * @file opngeng.c + * @brief Implementation of the OPN generator + */ + +#include +#include +#include "opngencfg.h" + +#if defined(OPNGENX86) +extern char envshift[EVC_ENT]; +extern char sinshift[SIN_ENT]; +#endif /* defined(OPNGENX86) */ + +#define CALCENV(e, c, s) \ + (c)->slot[(s)].freq_cnt += (c)->slot[(s)].freq_inc; \ + (c)->slot[(s)].env_cnt += (c)->slot[(s)].env_inc; \ + if ((c)->slot[(s)].env_cnt >= (c)->slot[(s)].env_end) \ + { \ + switch ((c)->slot[(s)].env_mode) \ + { \ + case EM_ATTACK: \ + (c)->slot[(s)].env_mode = EM_DECAY1; \ + (c)->slot[(s)].env_cnt = EC_DECAY; \ + (c)->slot[(s)].env_end = (c)->slot[(s)].decaylevel; \ + (c)->slot[(s)].env_inc = (c)->slot[(s)].env_inc_decay1; \ + break; \ + case EM_DECAY1: \ + (c)->slot[(s)].env_mode = EM_DECAY2; \ + (c)->slot[(s)].env_cnt = (c)->slot[(s)].decaylevel; \ + (c)->slot[(s)].env_end = EC_OFF; \ + (c)->slot[(s)].env_inc = (c)->slot[(s)].env_inc_decay2; \ + break; \ + case EM_RELEASE: \ + (c)->slot[(s)].env_mode = EM_OFF; \ + case EM_DECAY2: \ + (c)->slot[(s)].env_cnt = EC_OFF; \ + (c)->slot[(s)].env_end = EC_OFF + 1; \ + (c)->slot[(s)].env_inc = 0; \ + (c)->playing &= ~(1 << (s)); \ + break; \ + } \ + } \ + (e) = (c)->slot[(s)].totallevel - \ + opncfg.envcurve[(c)->slot[(s)].env_cnt >> ENV_BITS]; + +#if defined(OPNGENX86) +static SINT32 SLOTOUT(SINT32 e, SINT32 c) +{ + c = (c >> (FREQ_BITS - SIN_BITS)) & (SIN_ENT - 1); + return (opncfg.sintable[c] * opncfg.envtable[e]) >> (sinshift[c] + envshift[e]); +} +#else /* defined(OPNGENX86) */ +#define SLOTOUT(e, c) \ + ((opncfg.sintable[((c) >> (FREQ_BITS - SIN_BITS)) & (SIN_ENT - 1)] \ + * opncfg.envtable[(e)]) >> (ENVTBL_BIT + SINTBL_BIT - TL_BITS)) +#endif /* defined(OPNGENX86) */ + + +static void calcratechannel(OPNGEN opngen, OPNCH *ch) +{ + SINT32 envout; + SINT32 opout; + + opngen->feedback2 = 0; + opngen->feedback3 = 0; + opngen->feedback4 = 0; + + /* SLOT 1 */ + CALCENV(envout, ch, 0); + if (envout >= 0) + { + if (ch->feedback) + { + /* with self feed back */ + opout = ch->op1fb; + ch->op1fb = SLOTOUT(envout, ch->slot[0].freq_cnt + ((ch->op1fb >> ch->feedback) << (FREQ_BITS - (TL_BITS - 2)))); + opout = (opout + ch->op1fb) >> 1; + } + else + { + /* without self feed back */ + opout = SLOTOUT(envout, ch->slot[0].freq_cnt); + } + /* output slot1 */ + if (!ch->connect1) + { + opngen->feedback2 = opngen->feedback3 = opngen->feedback4 = opout; + } + else + { + *ch->connect1 += opout; + } + } + /* SLOT 2 */ + CALCENV(envout, ch, 1); + if (envout >= 0) + { + *ch->connect2 += SLOTOUT(envout, ch->slot[1].freq_cnt + (opngen->feedback2 << (FREQ_BITS - (TL_BITS - 2)))); + } + /* SLOT 3 */ + CALCENV(envout, ch, 2); + if (envout >= 0) + { + *ch->connect3 += SLOTOUT(envout, ch->slot[2].freq_cnt + (opngen->feedback3 << (FREQ_BITS - (TL_BITS - 2)))); + } + /* SLOT 4 */ + CALCENV(envout, ch, 3); + if (envout >= 0) + { + *ch->connect4 += SLOTOUT(envout, ch->slot[3].freq_cnt + (opngen->feedback4 << (FREQ_BITS - (TL_BITS - 2)))); + } +} + +void SOUNDCALL opngen_getpcm(OPNGEN opngen, SINT32 *pcm, UINT count) +{ + SINT32 samp_l; + SINT32 samp_r; + UINT playing; + UINT i; + OPNCH *ch; + + if ((!opngen->playing) || (!count)) + { + return; + } + + do + { + samp_l = opngen->outdl; + samp_r = opngen->outdr; + if (opngen->calcremain < FMDIV_ENT) + { + samp_l *= opngen->calcremain; + samp_r *= opngen->calcremain; + opngen->calcremain = FMDIV_ENT - opngen->calcremain; + while (TRUE /*CONSTCOND*/) + { + opngen->outdc = 0; + opngen->outdl = 0; + opngen->outdr = 0; + playing = 0; + for (i = 0; i < opngen->playchannels; i++) + { + ch = &opngen->opnch[i]; + if (ch->playing & ch->outslot) + { + calcratechannel(opngen, ch); + playing++; + } + } + opngen->playing = playing; + + opngen->outdl += opngen->outdc; + opngen->outdr += opngen->outdc; + opngen->outdl >>= FMVOL_SFTBIT; + opngen->outdr >>= FMVOL_SFTBIT; + if (opngen->calcremain > opncfg.calc1024) + { + opngen->calcremain -= opncfg.calc1024; + samp_l += opngen->outdl * opncfg.calc1024; + samp_r += opngen->outdr * opncfg.calc1024; + } + else + { + break; + } + } + samp_l += opngen->outdl * opngen->calcremain; + samp_r += opngen->outdr * opngen->calcremain; + opngen->calcremain = opncfg.calc1024 - opngen->calcremain; + } + else + { + samp_l *= FMDIV_ENT; + samp_r *= FMDIV_ENT; + opngen->calcremain -= FMDIV_ENT; + } + +#if defined(OPNGENX86) + pcm[0] += (SINT32)(((SINT64)samp_l * (SINT32)opncfg.fmvol) >> 32); + pcm[1] += (SINT32)(((SINT64)samp_r * (SINT32)opncfg.fmvol) >> 32); +#else /* defined(OPNGENX86) */ + samp_l >>= 8; + samp_l *= opncfg.fmvol; + samp_l >>= (OPM_OUTSB + FMDIV_BITS + 1 - FMVOL_SFTBIT - 8 + 6); + pcm[0] += samp_l; + samp_r >>= 8; + samp_r *= opncfg.fmvol; + samp_r >>= (OPM_OUTSB + FMDIV_BITS + 1 - FMVOL_SFTBIT - 8 + 6); + pcm[1] += samp_r; +#endif /* defined(OPNGENX86) */ + pcm += 2; + } while (--count); +} + +void SOUNDCALL opngen_getpcmvr(OPNGEN opngen, SINT32 *pcm, UINT count) +{ + SINT32 samp_l; + SINT32 samp_r; + UINT playing; + UINT i; + OPNCH *ch; + + if ((!opngen->playing) || (!count)) + { + return; + } + + do + { + samp_l = opngen->outdl; + samp_r = opngen->outdr; + if (opngen->calcremain < FMDIV_ENT) + { + samp_l *= opngen->calcremain; + samp_r *= opngen->calcremain; + opngen->calcremain = FMDIV_ENT - opngen->calcremain; + while (TRUE /*CONSTCOND*/) + { + opngen->outdc = 0; + opngen->outdl = 0; + opngen->outdr = 0; + playing = 0; + for (i = 0; i < opngen->playchannels; i++) + { + ch = &opngen->opnch[i]; + if (ch->playing & ch->outslot) + { + calcratechannel(opngen, ch); + playing++; + } + } + opngen->playing = playing; + + if (opncfg.vr_en) + { + SINT32 tmpl; + SINT32 tmpr; + tmpl = opngen->outdl * opncfg.vr_l; + tmpr = opngen->outdr * opncfg.vr_r; + opngen->outdl += (tmpr >> 5) + (tmpl >> 7); + opngen->outdr += (tmpl >> 5) + (tmpr >> 7); + } + opngen->outdl += opngen->outdc; + opngen->outdr += opngen->outdc; + opngen->outdl >>= FMVOL_SFTBIT; + opngen->outdr >>= FMVOL_SFTBIT; + if (opngen->calcremain > opncfg.calc1024) + { + samp_l += opngen->outdl * opncfg.calc1024; + samp_r += opngen->outdr * opncfg.calc1024; + opngen->calcremain -= opncfg.calc1024; + } + else + { + break; + } + } + samp_l += opngen->outdl * opngen->calcremain; + samp_r += opngen->outdr * opngen->calcremain; + } + else + { + samp_l *= FMDIV_ENT; + samp_r *= FMDIV_ENT; + opngen->calcremain -= FMDIV_ENT; + } +#if defined(OPNGENX86) + pcm[0] += (SINT32)(((SINT64)samp_l * (SINT32)opncfg.fmvol) >> 32); + pcm[1] += (SINT32)(((SINT64)samp_r * (SINT32)opncfg.fmvol) >> 32); +#else /* defined(OPNGENX86) */ + samp_l >>= 8; + samp_l *= opncfg.fmvol; + samp_l >>= (OPM_OUTSB + FMDIV_BITS + 1 - FMVOL_SFTBIT - 8 + 6); + pcm[0] += samp_l; + samp_r >>= 8; + samp_r *= opncfg.fmvol; + samp_r >>= (OPM_OUTSB + FMDIV_BITS + 1 - FMVOL_SFTBIT - 8 + 6); + pcm[1] += samp_r; +#endif /* defined(OPNGENX86) */ + opngen->calcremain = opncfg.calc1024 - opngen->calcremain; + pcm += 2; + } while (--count); +} diff --git a/sound/opntimer.c b/sound/opntimer.c old mode 100755 new mode 100644 index 244a1a0d..cfd8ce95 --- a/sound/opntimer.c +++ b/sound/opntimer.c @@ -1,225 +1,225 @@ -/** - * @file opntimer.c - * @brief Implementation of OPN timer - */ - -#include -#include "opntimer.h" -#include -#include -#include - -/** IRQ */ -static const UINT8 s_irqtable[4] = {0x03, 0x0d, 0x0a, 0x0c}; - -/** - * Rise Timer-A - * @param[in] opna The instance - * @param[in] absolute If ture is absolute - */ -static void set_fmtimeraevent(POPNA opna, NEVENTPOSITION absolute) -{ - SINT32 l; - int OPNAidx; - int v_NEVENT_FMTIMERA, v_NEVENT_FMTIMERB; - - OPNAidx = (opna == &(g_opna[1])) ? 1 : 0; - v_NEVENT_FMTIMERA = (OPNAidx==0) ? NEVENT_FMTIMERA : NEVENT_FMTIMER2A; - v_NEVENT_FMTIMERB = (OPNAidx==0) ? NEVENT_FMTIMERB : NEVENT_FMTIMER2B; - - l = 18 * (1024 - ((opna->s.reg[0x24] << 2) | (opna->s.reg[0x25] & 3))); - if (pccore.cpumode & CPUMODE_8MHZ) /* 4MHz */ - { - l = (l * 1248) / 625; - } - else /* 5MHz */ - { - l = (l * 1536) / 625; - } - l *= pccore.multiple; -// TRACEOUT(("FMTIMER-A: %08x-%d", l, absolute)); - nevent_set((NEVENTID)v_NEVENT_FMTIMERA, l, fmport_a, absolute); -} - -/** - * Rise Timer-B - * @param[in] opna The instance - * @param[in] absolute If ture is absolute - */ -static void set_fmtimerbevent(POPNA opna, NEVENTPOSITION absolute) -{ - SINT32 l; - int OPNAidx; - int v_NEVENT_FMTIMERA, v_NEVENT_FMTIMERB; - - OPNAidx = (opna == &(g_opna[1])) ? 1 : 0; - v_NEVENT_FMTIMERA = (OPNAidx==0) ? NEVENT_FMTIMERA : NEVENT_FMTIMER2A; - v_NEVENT_FMTIMERB = (OPNAidx==0) ? NEVENT_FMTIMERB : NEVENT_FMTIMER2B; - - l = 288 * (256 - opna->s.reg[0x26]); - if (pccore.cpumode & CPUMODE_8MHZ) /* 4MHz */ - { - l = (l * 1248) / 625; - } - else - { /* 5MHz */ - l = (l * 1536) / 625; - } - l *= pccore.multiple; -// TRACEOUT(("FMTIMER-B: %08x-%d", l, absolute)); - nevent_set((NEVENTID)v_NEVENT_FMTIMERB, l, fmport_b, absolute); -} - -/** - * Timer-A event - * @param[in] item The item of event - */ -void fmport_a(NEVENTITEM item) -{ - POPNA opna = (POPNA)item->userData; - BOOL intreq = FALSE; - - if(!opna) return; - - if (item->flag & NEVENT_SETEVENT) - { - if(g_pcm86.irq==opna->s.irq){ - intreq = pcm86gen_intrq(1); - if(!(opna->s.status & 0x01) && g_pcm86.irqflag){ - intreq = TRUE; - } - } - if ((opna->s.reg[0x27] & 0x04) && !(opna->s.status & 0x01)) - { - opna->s.status |= 0x01; - intreq = TRUE; - } - if ((intreq) && (opna->s.irq != 0xff)) - { - pic_setirq(opna->s.irq); -// TRACEOUT(("fm int-A")); - } - - set_fmtimeraevent(opna, NEVENT_RELATIVE); - - if ((opna->s.reg[0x27] & 0xc0) == 0x80) - { - opngen_csm(&opna->opngen); - } - } -} - -/** - * Timer-B event - * @param[in] item The item of event - */ -void fmport_b(NEVENTITEM item) -{ - POPNA opna = (POPNA)item->userData; - BOOL intreq = FALSE; - - if(!opna) return; - - if (item->flag & NEVENT_SETEVENT) - { - if(g_pcm86.irq==opna->s.irq){ - intreq = pcm86gen_intrq(1); - if(!(opna->s.status & 0x02) && g_pcm86.irqflag){ - intreq = TRUE; - } - } - if ((opna->s.reg[0x27] & 0x08) && !(opna->s.status & 0x02)) - { - opna->s.status |= 0x02; - intreq = TRUE; - } - if ((intreq) && (opna->s.irq != 0xff)) - { - pic_setirq(opna->s.irq); -// TRACEOUT(("fm int-B")); - } - - set_fmtimerbevent(opna, NEVENT_RELATIVE); - } -} - -/** - * Reset - * @param[in] opna The instance - * @param[in] nIrq DIPSW - * @param[in] nTimerA The ID of Timer-A - * @param[in] nTimerB The ID of Timer-B - */ -void opna_timer(POPNA opna, UINT nIrq, NEVENTID nTimerA, NEVENTID nTimerB) -{ - opna->s.intr = nIrq & 0xc0; - if (nIrq & 0x10) - { - opna->s.irq = s_irqtable[nIrq >> 6]; - } - - g_nevent.item[nTimerA].userData = (INTPTR)opna; - g_nevent.item[nTimerB].userData = (INTPTR)opna; - -// pic_registext(opna->s.irq); -} - -/** - * Write the register - * @param[in] opna The instance - * @param[in] cData The data - */ -void opna_settimer(POPNA opna, REG8 cData) -{ -// TRACEOUT(("fm 27 %x [%.4x:%.4x]", cData, CPU_CS, CPU_IP)); - int OPNAidx; - int v_NEVENT_FMTIMERA, v_NEVENT_FMTIMERB; - - OPNAidx = (opna == &(g_opna[1])) ? 1 : 0; - v_NEVENT_FMTIMERA = (OPNAidx==0) ? NEVENT_FMTIMERA : NEVENT_FMTIMER2A; - v_NEVENT_FMTIMERB = (OPNAidx==0) ? NEVENT_FMTIMERB : NEVENT_FMTIMER2B; - - if(cData & 0x10){ - //nevent_reset((NEVENTID)v_NEVENT_FMTIMERA); - opna->s.reg[0x27] &= ~0x10; - opna->s.status &= ~0x01; - } - if(cData & 0x20){ - //nevent_reset((NEVENTID)v_NEVENT_FMTIMERB); - opna->s.reg[0x27] &= ~0x20; - opna->s.status &= ~0x02; - } - - opna->s.status &= ~((cData & 0x30) >> 4); - if (cData & 0x01) - { - if (!nevent_iswork((NEVENTID)v_NEVENT_FMTIMERA)) - { - set_fmtimeraevent(opna, NEVENT_ABSOLUTE); - } - } - else - { - nevent_reset((NEVENTID)v_NEVENT_FMTIMERA); - } - - if (cData & 0x02) - { - if (!nevent_iswork((NEVENTID)v_NEVENT_FMTIMERB)) - { - set_fmtimerbevent(opna, NEVENT_ABSOLUTE); - } - } - else - { - nevent_reset((NEVENTID)v_NEVENT_FMTIMERB); - } - - if ((!(cData & 0x03) || (cData & 0x30)) && (opna->s.irq != 0xff)) - { - PCM86 pcm86 = &g_pcm86; - if(pcm86->irq!=opna->s.irq || !pcm86->irqflag){ - pic_resetirq(opna->s.irq); - } - } -} +/** + * @file opntimer.c + * @brief Implementation of OPN timer + */ + +#include +#include "opntimer.h" +#include +#include +#include + +/** IRQ */ +static const UINT8 s_irqtable[4] = {0x03, 0x0d, 0x0a, 0x0c}; + +/** + * Rise Timer-A + * @param[in] opna The instance + * @param[in] absolute If ture is absolute + */ +static void set_fmtimeraevent(POPNA opna, NEVENTPOSITION absolute) +{ + SINT32 l; + int OPNAidx; + int v_NEVENT_FMTIMERA, v_NEVENT_FMTIMERB; + + OPNAidx = (opna == &(g_opna[1])) ? 1 : 0; + v_NEVENT_FMTIMERA = (OPNAidx==0) ? NEVENT_FMTIMERA : NEVENT_FMTIMER2A; + v_NEVENT_FMTIMERB = (OPNAidx==0) ? NEVENT_FMTIMERB : NEVENT_FMTIMER2B; + + l = 18 * (1024 - ((opna->s.reg[0x24] << 2) | (opna->s.reg[0x25] & 3))); + if (pccore.cpumode & CPUMODE_8MHZ) /* 4MHz */ + { + l = (l * 1248) / 625; + } + else /* 5MHz */ + { + l = (l * 1536) / 625; + } + l *= pccore.multiple; +// TRACEOUT(("FMTIMER-A: %08x-%d", l, absolute)); + nevent_set((NEVENTID)v_NEVENT_FMTIMERA, l, fmport_a, absolute); +} + +/** + * Rise Timer-B + * @param[in] opna The instance + * @param[in] absolute If ture is absolute + */ +static void set_fmtimerbevent(POPNA opna, NEVENTPOSITION absolute) +{ + SINT32 l; + int OPNAidx; + int v_NEVENT_FMTIMERA, v_NEVENT_FMTIMERB; + + OPNAidx = (opna == &(g_opna[1])) ? 1 : 0; + v_NEVENT_FMTIMERA = (OPNAidx==0) ? NEVENT_FMTIMERA : NEVENT_FMTIMER2A; + v_NEVENT_FMTIMERB = (OPNAidx==0) ? NEVENT_FMTIMERB : NEVENT_FMTIMER2B; + + l = 288 * (256 - opna->s.reg[0x26]); + if (pccore.cpumode & CPUMODE_8MHZ) /* 4MHz */ + { + l = (l * 1248) / 625; + } + else + { /* 5MHz */ + l = (l * 1536) / 625; + } + l *= pccore.multiple; +// TRACEOUT(("FMTIMER-B: %08x-%d", l, absolute)); + nevent_set((NEVENTID)v_NEVENT_FMTIMERB, l, fmport_b, absolute); +} + +/** + * Timer-A event + * @param[in] item The item of event + */ +void fmport_a(NEVENTITEM item) +{ + POPNA opna = (POPNA)item->userData; + BOOL intreq = FALSE; + + if(!opna) return; + + if (item->flag & NEVENT_SETEVENT) + { + if(g_pcm86.irq==opna->s.irq){ + intreq = pcm86gen_intrq(1); + if(!(opna->s.status & 0x01) && g_pcm86.irqflag){ + intreq = TRUE; + } + } + if ((opna->s.reg[0x27] & 0x04) && !(opna->s.status & 0x01)) + { + opna->s.status |= 0x01; + intreq = TRUE; + } + if ((intreq) && (opna->s.irq != 0xff)) + { + pic_setirq(opna->s.irq); +// TRACEOUT(("fm int-A")); + } + + set_fmtimeraevent(opna, NEVENT_RELATIVE); + + if ((opna->s.reg[0x27] & 0xc0) == 0x80) + { + opngen_csm(&opna->opngen); + } + } +} + +/** + * Timer-B event + * @param[in] item The item of event + */ +void fmport_b(NEVENTITEM item) +{ + POPNA opna = (POPNA)item->userData; + BOOL intreq = FALSE; + + if(!opna) return; + + if (item->flag & NEVENT_SETEVENT) + { + if(g_pcm86.irq==opna->s.irq){ + intreq = pcm86gen_intrq(1); + if(!(opna->s.status & 0x02) && g_pcm86.irqflag){ + intreq = TRUE; + } + } + if ((opna->s.reg[0x27] & 0x08) && !(opna->s.status & 0x02)) + { + opna->s.status |= 0x02; + intreq = TRUE; + } + if ((intreq) && (opna->s.irq != 0xff)) + { + pic_setirq(opna->s.irq); +// TRACEOUT(("fm int-B")); + } + + set_fmtimerbevent(opna, NEVENT_RELATIVE); + } +} + +/** + * Reset + * @param[in] opna The instance + * @param[in] nIrq DIPSW + * @param[in] nTimerA The ID of Timer-A + * @param[in] nTimerB The ID of Timer-B + */ +void opna_timer(POPNA opna, UINT nIrq, NEVENTID nTimerA, NEVENTID nTimerB) +{ + opna->s.intr = nIrq & 0xc0; + if (nIrq & 0x10) + { + opna->s.irq = s_irqtable[nIrq >> 6]; + } + + g_nevent.item[nTimerA].userData = (INTPTR)opna; + g_nevent.item[nTimerB].userData = (INTPTR)opna; + +// pic_registext(opna->s.irq); +} + +/** + * Write the register + * @param[in] opna The instance + * @param[in] cData The data + */ +void opna_settimer(POPNA opna, REG8 cData) +{ +// TRACEOUT(("fm 27 %x [%.4x:%.4x]", cData, CPU_CS, CPU_IP)); + int OPNAidx; + int v_NEVENT_FMTIMERA, v_NEVENT_FMTIMERB; + + OPNAidx = (opna == &(g_opna[1])) ? 1 : 0; + v_NEVENT_FMTIMERA = (OPNAidx==0) ? NEVENT_FMTIMERA : NEVENT_FMTIMER2A; + v_NEVENT_FMTIMERB = (OPNAidx==0) ? NEVENT_FMTIMERB : NEVENT_FMTIMER2B; + + if(cData & 0x10){ + //nevent_reset((NEVENTID)v_NEVENT_FMTIMERA); + opna->s.reg[0x27] &= ~0x10; + opna->s.status &= ~0x01; + } + if(cData & 0x20){ + //nevent_reset((NEVENTID)v_NEVENT_FMTIMERB); + opna->s.reg[0x27] &= ~0x20; + opna->s.status &= ~0x02; + } + + opna->s.status &= ~((cData & 0x30) >> 4); + if (cData & 0x01) + { + if (!nevent_iswork((NEVENTID)v_NEVENT_FMTIMERA)) + { + set_fmtimeraevent(opna, NEVENT_ABSOLUTE); + } + } + else + { + nevent_reset((NEVENTID)v_NEVENT_FMTIMERA); + } + + if (cData & 0x02) + { + if (!nevent_iswork((NEVENTID)v_NEVENT_FMTIMERB)) + { + set_fmtimerbevent(opna, NEVENT_ABSOLUTE); + } + } + else + { + nevent_reset((NEVENTID)v_NEVENT_FMTIMERB); + } + + if ((!(cData & 0x03) || (cData & 0x30)) && (opna->s.irq != 0xff)) + { + PCM86 pcm86 = &g_pcm86; + if(pcm86->irq!=opna->s.irq || !pcm86->irqflag){ + pic_resetirq(opna->s.irq); + } + } +} diff --git a/sound/opntimer.h b/sound/opntimer.h old mode 100755 new mode 100644 index e36f6058..75f71ff7 --- a/sound/opntimer.h +++ b/sound/opntimer.h @@ -1,23 +1,23 @@ -/** - * @file opntimer.h - * @brief Interface of OPN timer - */ - -#pragma once - -#include -#include "opna.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void fmport_a(NEVENTITEM item); -void fmport_b(NEVENTITEM item); - -void opna_timer(POPNA opna, UINT nIrq, NEVENTID nTimerA, NEVENTID nTimerB); -void opna_settimer(POPNA opna, REG8 cData); - -#ifdef __cplusplus -} -#endif +/** + * @file opntimer.h + * @brief Interface of OPN timer + */ + +#pragma once + +#include +#include "opna.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void fmport_a(NEVENTITEM item); +void fmport_b(NEVENTITEM item); + +void opna_timer(POPNA opna, UINT nIrq, NEVENTID nTimerA, NEVENTID nTimerB); +void opna_settimer(POPNA opna, REG8 cData); + +#ifdef __cplusplus +} +#endif diff --git a/sound/pcm86.h b/sound/pcm86.h old mode 100755 new mode 100644 index 5363997f..34fadd7f --- a/sound/pcm86.h +++ b/sound/pcm86.h @@ -1,159 +1,159 @@ -/** - * @file pcm86.h - * @brief Interface of the 86-PCM - */ - -#pragma once - -#include -#include - -enum { - PCM86_LOGICALBUF = 0x8000, - PCM86_BUFSIZE = (1 << 16), - PCM86_BUFMSK = ((1 << 16) - 1), - - PCM86_DIVBIT = 10, - PCM86_DIVENV = (1 << PCM86_DIVBIT), - - PCM86_RESCUE = 20 -}; - -#define PCM86_EXTBUF g_pcm86.rescue /* 救済延滞… */ -#define PCM86_REALBUFSIZE (PCM86_LOGICALBUF + PCM86_EXTBUF) - -void RECALC_NOWCLKWAIT(UINT64 cnt); -//#define RECALC_NOWCLKWAIT(cnt) ¥ -// do ¥ -// { ¥ -// SINT64 decvalue =(SINT64)(cnt << g_pcm86.stepbit); ¥ -// if (g_pcm86.virbuf - decvalue < g_pcm86.virbuf) ¥ -// { ¥ -// g_pcm86.virbuf -= decvalue; ¥ -// } ¥ -// if (g_pcm86.virbuf < 0) ¥ -// { ¥ -// g_pcm86.virbuf &= g_pcm86.stepmask; ¥ -// } ¥ -// } while (0 /*CONSTCOND*/) - -typedef struct { - SINT32 divremain; - SINT32 div; - SINT32 div2; - SINT32 smp; - SINT32 lastsmp; - SINT32 smp_l; - SINT32 lastsmp_l; - SINT32 smp_r; - SINT32 lastsmp_r; - - UINT32 readpos; /* DSOUND再生位置 */ - UINT32 wrtpos; /* 書込み位置 */ - SINT32 realbuf; /* DSOUND用のデータ数 */ - SINT32 virbuf; /* 86PCM(bufsize:0x8000)のデータ数 */ - SINT32 rescue; - - SINT32 fifosize; - SINT32 volume; - SINT32 vol5; - - union { - struct { - UINT32 lastclock_obsolate; - UINT32 stepclock_obsolate; - } obsolate; - UINT64 lastclockforwait; - }; - UINT stepmask; - - UINT8 fifo; - UINT8 soundflags; /*!< サウンド フラグ (A460) */ - UINT8 dactrl; - UINT8 _write; - UINT8 stepbit; - UINT8 irq; - UINT8 reqirq; - UINT8 irqflag; - - UINT8 buffer[PCM86_BUFSIZE]; - - UINT rateval; - - UINT64 lastclock; - UINT64 stepclock; -} _PCM86, *PCM86; - -typedef struct { // ステートセーブ互換性維持用(変更禁止) - SINT32 divremain; - SINT32 div; - SINT32 div2; - SINT32 smp; - SINT32 lastsmp; - SINT32 smp_l; - SINT32 lastsmp_l; - SINT32 smp_r; - SINT32 lastsmp_r; - - UINT32 readpos; /* DSOUND再生位置 */ - UINT32 wrtpos; /* 書込み位置 */ - SINT32 realbuf; /* DSOUND用のデータ数 */ - SINT32 virbuf; /* 86PCM(bufsize:0x8000)のデータ数 */ - SINT32 rescue; - - SINT32 fifosize; - SINT32 volume; - SINT32 vol5; - - UINT32 lastclock; - UINT32 stepclock; - UINT stepmask; - - UINT8 fifo; - UINT8 soundflags; /*!< サウンド フラグ (A460) */ - UINT8 dactrl; - UINT8 _write; - UINT8 stepbit; - UINT8 irq; - UINT8 reqirq; - UINT8 irqflag; - - UINT8 buffer[PCM86_BUFSIZE]; -} _PCM86_OLD, *PCM86_OLD; - -typedef struct { - UINT rate; - UINT vol; -} PCM86CFG; - - -#ifdef __cplusplus -extern "C" -{ -#endif - -extern const UINT pcm86rate8[]; - -void pcm86_cb(NEVENTITEM item); - -void pcm86cs_initialize(); -void pcm86cs_shutdown(); -void pcm86cs_enter_criticalsection(); -void pcm86cs_leave_criticalsection(); - -void pcm86_reset(void); -void pcm86gen_initialize(UINT rate); -void pcm86gen_setvol(UINT vol); -void pcm86gen_update(void); -void pcm86_setpcmrate(REG8 val); -void pcm86_setnextintr(void); -void pcm86_changeclock(UINT oldmultiple); - -void SOUNDCALL pcm86gen_checkbuf(PCM86 pcm86, UINT nCount); -void SOUNDCALL pcm86gen_getpcm(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount); - -BOOL pcm86gen_intrq(int fromFMTimer); - -#ifdef __cplusplus -} -#endif +/** + * @file pcm86.h + * @brief Interface of the 86-PCM + */ + +#pragma once + +#include +#include + +enum { + PCM86_LOGICALBUF = 0x8000, + PCM86_BUFSIZE = (1 << 16), + PCM86_BUFMSK = ((1 << 16) - 1), + + PCM86_DIVBIT = 10, + PCM86_DIVENV = (1 << PCM86_DIVBIT), + + PCM86_RESCUE = 20 +}; + +#define PCM86_EXTBUF g_pcm86.rescue /* 救済延滞… */ +#define PCM86_REALBUFSIZE (PCM86_LOGICALBUF + PCM86_EXTBUF) + +void RECALC_NOWCLKWAIT(UINT64 cnt); +//#define RECALC_NOWCLKWAIT(cnt) ¥ +// do ¥ +// { ¥ +// SINT64 decvalue =(SINT64)(cnt << g_pcm86.stepbit); ¥ +// if (g_pcm86.virbuf - decvalue < g_pcm86.virbuf) ¥ +// { ¥ +// g_pcm86.virbuf -= decvalue; ¥ +// } ¥ +// if (g_pcm86.virbuf < 0) ¥ +// { ¥ +// g_pcm86.virbuf &= g_pcm86.stepmask; ¥ +// } ¥ +// } while (0 /*CONSTCOND*/) + +typedef struct { + SINT32 divremain; + SINT32 div; + SINT32 div2; + SINT32 smp; + SINT32 lastsmp; + SINT32 smp_l; + SINT32 lastsmp_l; + SINT32 smp_r; + SINT32 lastsmp_r; + + UINT32 readpos; /* DSOUND再生位置 */ + UINT32 wrtpos; /* 書込み位置 */ + SINT32 realbuf; /* DSOUND用のデータ数 */ + SINT32 virbuf; /* 86PCM(bufsize:0x8000)のデータ数 */ + SINT32 rescue; + + SINT32 fifosize; + SINT32 volume; + SINT32 vol5; + + union { + struct { + UINT32 lastclock_obsolate; + UINT32 stepclock_obsolate; + } obsolate; + UINT64 lastclockforwait; + }; + UINT stepmask; + + UINT8 fifo; + UINT8 soundflags; /*!< サウンド フラグ (A460) */ + UINT8 dactrl; + UINT8 _write; + UINT8 stepbit; + UINT8 irq; + UINT8 reqirq; + UINT8 irqflag; + + UINT8 buffer[PCM86_BUFSIZE]; + + UINT rateval; + + UINT64 lastclock; + UINT64 stepclock; +} _PCM86, *PCM86; + +typedef struct { // ステートセーブ互換性維持用(変更禁止) + SINT32 divremain; + SINT32 div; + SINT32 div2; + SINT32 smp; + SINT32 lastsmp; + SINT32 smp_l; + SINT32 lastsmp_l; + SINT32 smp_r; + SINT32 lastsmp_r; + + UINT32 readpos; /* DSOUND再生位置 */ + UINT32 wrtpos; /* 書込み位置 */ + SINT32 realbuf; /* DSOUND用のデータ数 */ + SINT32 virbuf; /* 86PCM(bufsize:0x8000)のデータ数 */ + SINT32 rescue; + + SINT32 fifosize; + SINT32 volume; + SINT32 vol5; + + UINT32 lastclock; + UINT32 stepclock; + UINT stepmask; + + UINT8 fifo; + UINT8 soundflags; /*!< サウンド フラグ (A460) */ + UINT8 dactrl; + UINT8 _write; + UINT8 stepbit; + UINT8 irq; + UINT8 reqirq; + UINT8 irqflag; + + UINT8 buffer[PCM86_BUFSIZE]; +} _PCM86_OLD, *PCM86_OLD; + +typedef struct { + UINT rate; + UINT vol; +} PCM86CFG; + + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern const UINT pcm86rate8[]; + +void pcm86_cb(NEVENTITEM item); + +void pcm86cs_initialize(); +void pcm86cs_shutdown(); +void pcm86cs_enter_criticalsection(); +void pcm86cs_leave_criticalsection(); + +void pcm86_reset(void); +void pcm86gen_initialize(UINT rate); +void pcm86gen_setvol(UINT vol); +void pcm86gen_update(void); +void pcm86_setpcmrate(REG8 val); +void pcm86_setnextintr(void); +void pcm86_changeclock(UINT oldmultiple); + +void SOUNDCALL pcm86gen_checkbuf(PCM86 pcm86, UINT nCount); +void SOUNDCALL pcm86gen_getpcm(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount); + +BOOL pcm86gen_intrq(int fromFMTimer); + +#ifdef __cplusplus +} +#endif diff --git a/sound/pcm86c.c b/sound/pcm86c.c old mode 100755 new mode 100644 index a51e10a5..ef69f268 --- a/sound/pcm86c.c +++ b/sound/pcm86c.c @@ -1,498 +1,498 @@ -/** - * @file pcm86c.c - * @brief Implementation of the 86-PCM - */ - -#include -#include -#include -#include -#include -#include - -#if 0 -#undef TRACEOUT -static void trace_fmt_ex(const char *fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#else -#define TRACEOUT(s) (void)(s) -#endif /* 1 */ - -/* サンプリングレートに8掛けた物 */ -const UINT pcm86rate8[] = {352800, 264600, 176400, 132300, - 88200, 66150, 44010, 33075}; - -/* 32,24,16,12, 8, 6, 4, 3 - 最少公倍数: 96 */ -/* 3, 4, 6, 8,12,16,24,32 */ - -static const UINT clk25_128[] = { - 0x00001bde, 0x00002527, 0x000037bb, 0x00004a4e, - 0x00006f75, 0x0000949c, 0x0000df5f, 0x00012938}; -static const UINT clk20_128[] = { - 0x000016a4, 0x00001e30, 0x00002d48, 0x00003c60, - 0x00005a8f, 0x000078bf, 0x0000b57d, 0x0000f17d}; - - - PCM86CFG pcm86cfg; - - UINT64 datawriteirqwait = 0; - static SINT32 bufunferflag = 0; - static SINT32 vbufunferflag = 0; - -#if defined(SUPPORT_MULTITHREAD) - static int pcm86_cs_initialized = 0; - static CRITICAL_SECTION pcm86_cs; - - void pcm86cs_enter_criticalsection(void) - { - if (!pcm86_cs_initialized) return; - EnterCriticalSection(&pcm86_cs); - } - void pcm86cs_leave_criticalsection(void) - { - if (!pcm86_cs_initialized) return; - LeaveCriticalSection(&pcm86_cs); - } - - void pcm86cs_initialize(void) - { - /* クリティカルセクション準備 */ - if (!pcm86_cs_initialized) - { - memset(&pcm86_cs, 0, sizeof(pcm86_cs)); - InitializeCriticalSection(&pcm86_cs); - pcm86_cs_initialized = 1; - } - } - void pcm86cs_shutdown(void) - { - /* クリティカルセクション破棄 */ - if (pcm86_cs_initialized) - { - memset(&pcm86_cs, 0, sizeof(pcm86_cs)); - DeleteCriticalSection(&pcm86_cs); - pcm86_cs_initialized = 0; - } - } -#endif - -void pcm86gen_initialize(UINT rate) -{ - pcm86cfg.rate = rate; -} - -void pcm86gen_setvol(UINT vol) -{ - pcm86cfg.vol = vol; - pcm86gen_update(); -} - -void pcm86_reset(void) -{ - PCM86 pcm86 = &g_pcm86; - - memset(pcm86, 0, sizeof(*pcm86)); - pcm86->fifosize = 0x80; - pcm86->dactrl = 0x32; - pcm86->stepmask = (1 << 2) - 1; - pcm86->stepbit = 2; - pcm86->stepclock = ((UINT64)pccore.baseclock << 6); - pcm86->stepclock /= 44100; - pcm86->stepclock *= pccore.multiple; - pcm86->rescue = (PCM86_RESCUE * 32) << 2; - pcm86->irq = 0xff; - pcm86_setpcmrate(pcm86->fifo); // デフォルト値をセット -} - -void pcm86gen_update(void) -{ - PCM86 pcm86 = &g_pcm86; - - pcm86->volume = pcm86cfg.vol * pcm86->vol5; - pcm86_setpcmrate(pcm86->fifo); -} - -void pcm86_setwaittime() -{ - // WORKAROUND: データ書き込みから割り込み発生までの時間が短すぎると不具合が起こる場合があるのでわざと遅延 値に根拠はなし - datawriteirqwait = 20000 * pccore.multiple; -} - -void pcm86_setpcmrate(REG8 val) -{ - PCM86 pcm86 = &g_pcm86; - SINT32 rate; - - pcm86->rateval = rate = pcm86rate8[val & 7]; - pcm86->stepclock = ((UINT64)pccore.baseclock << 6); - pcm86->stepclock /= rate; - pcm86->stepclock *= (pccore.multiple << 3); - if (pcm86cfg.rate) - { - pcm86->div = (rate << (PCM86_DIVBIT - 3)) / pcm86cfg.rate; - pcm86->div2 = (pcm86cfg.rate << (PCM86_DIVBIT + 3)) / rate; - } - - pcm86_setwaittime(); -} - -void pcm86_cb(NEVENTITEM item) -{ - PCM86 pcm86 = &g_pcm86; - SINT32 adjustbuf; - - if (pcm86->reqirq) - { - sound_sync(); - // RECALC_NOWCLKP; - - adjustbuf = (SINT32)(((SINT64)pcm86->virbuf * 4 + pcm86->realbuf) / 5); - if (pcm86->virbuf <= pcm86->fifosize || pcm86->realbuf > pcm86->stepmask && adjustbuf <= pcm86->fifosize) - { - pcm86->reqirq = 0; - pcm86->irqflag = 1; - if (pcm86->irq != 0xff) - { - pic_setirq(pcm86->irq); - } - } - else - { - pcm86_setnextintr(); - } - } - else - { - pcm86_setnextintr(); - } - - (void)item; -} - -void pcm86_setnextintr(void) { - - PCM86 pcm86 = &g_pcm86; - SINT32 cntv; - SINT32 cntr; - SINT32 cnt; - SINT32 clk; - - if (pcm86->fifo & 0x80) - { - cntv = pcm86->virbuf - pcm86->fifosize; - cntr = pcm86->realbuf - pcm86->fifosize; - if (pcm86->realbuf > pcm86->stepmask) - { - if (cntr < cntv) - { - //cnt = cntr; - if (bufunferflag > 32000) - { - cnt = (SINT32)(((SINT64)cntv * 9 + cntr) / 10); - TRACEOUT(("Buf Under2", bufunferflag)); - } - else if (bufunferflag > 4000) - { - cnt = (SINT32)(((SINT64)cntv * 99 + cntr) / 100); - TRACEOUT(("Buf Under", bufunferflag)); - } - else - { - cnt = cntv; - } - } - else - { - if (vbufunferflag > 64000) - { - cnt = (SINT32)(((SINT64)cntv * 9 + cntr) / 10); - TRACEOUT(("VBuf Under3", vbufunferflag)); - } - else if (vbufunferflag > 16000) - { - cnt = (SINT32)(((SINT64)cntv * 49 + cntr) / 50); - TRACEOUT(("VBuf Under2", vbufunferflag)); - } - else if (vbufunferflag > 4000) - { - cnt = (SINT32)(((SINT64)cntv * 99 + cntr) / 100); - TRACEOUT(("VBuf Under", vbufunferflag)); - } - else - { - cnt = cntv; - } - } - } - else - { - cnt = cntv; - } - //cnt = (SINT32)(((SINT64)cntv + cntr) / 2); - if (cnt > 0) - { - cnt += pcm86->stepmask; - cnt >>= pcm86->stepbit; - //cnt += 4; - /* ここで clk = pccore.realclock * cnt / 86pcm_rate */ - /* clk = ((pccore.baseclock / 86pcm_rate) * cnt) * pccore.multiple */ - if (pccore.cpumode & CPUMODE_8MHZ) { - clk = clk20_128[pcm86->fifo & 7]; - } - else { - clk = clk25_128[pcm86->fifo & 7]; - } - /* cntは最大 8000h で 32bitで収まるように… */ - clk *= cnt; - clk >>= 7; -// clk++; /* roundup */ - //clk--; /* roundup */ - //if (clk > 1) clk--; - clk *= pccore.multiple; - nevent_set(NEVENT_86PCM, clk, pcm86_cb, NEVENT_ABSOLUTE); - TRACEOUT(("%d,%d", pcm86->virbuf, pcm86->realbuf)); - } - else - { - if (pcm86->reqirq) - { - // 即時 - nevent_set(NEVENT_86PCM, 1, pcm86_cb, NEVENT_ABSOLUTE); - } - else - { - // WORKAROUND: 前回の割り込みがうまくいっていない。適当な時間間隔で再度割り込みを送る。早すぎるとNT4等が割り込み無限ループするので注意 - pcm86->reqirq = 1; - nevent_set(NEVENT_86PCM, 100 * pccore.multiple, pcm86_cb, NEVENT_ABSOLUTE); - } - } - } -} - -void RECALC_NOWCLKWAIT(UINT64 cnt) -{ - SINT64 decvalue = (SINT64)(cnt << g_pcm86.stepbit); -#if defined(SUPPORT_MULTITHREAD) - pcm86cs_enter_criticalsection(); -#endif - if (g_pcm86.virbuf - decvalue < g_pcm86.virbuf) - { - g_pcm86.virbuf -= decvalue; - } - if (g_pcm86.virbuf < 0) - { - g_pcm86.virbuf &= g_pcm86.stepmask; - } -#if defined(SUPPORT_MULTITHREAD) - pcm86cs_leave_criticalsection(); -#endif -} - -void pcm86_changeclock(UINT oldmultiple) -{ - PCM86 pcm86 = &g_pcm86; - if(pcm86){ - if(pcm86->rateval){ - UINT64 cur; - UINT64 past; - UINT64 pastCycle; - UINT64 newstepclock; - newstepclock = ((UINT64)pccore.baseclock << 6); - newstepclock /= pcm86->rateval; - newstepclock *= ((UINT64)pccore.multiple << 3); - pastCycle = (UINT64)UINT_MAX << 6; - cur = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - cur <<= 6; - past = (cur + pastCycle - pcm86->lastclock) % pastCycle; - if (past > pastCycle / 2) - { - // 負の値になってしまっているとき - if (past < pastCycle - pcm86->stepclock * 4) - { - // かなり小さいならリセットをかける - past = 1; - pcm86->lastclock = cur - 1; - } - else - { - // 小さいなら様子見で0扱いとする - past = 0; - } - } - if (past >= pcm86->stepclock) - { - //SINT32 latvirbuf = pcm86->virbuf; - past = past / pcm86->stepclock; - pcm86->lastclock = (pcm86->lastclock + past * pcm86->stepclock) % pastCycle; - RECALC_NOWCLKWAIT(past); - //TRACEOUT(("%d %d %d", latvirbuf, pcm86->virbuf, past)); - } - past = (cur + pastCycle - pcm86->lastclock) % pastCycle; - pcm86->lastclock = (cur + pastCycle - (past * newstepclock + pcm86->stepclock / 2) / pcm86->stepclock) % pastCycle; // 補正 - pcm86->stepclock = newstepclock; - - pcm86_setwaittime(); - }else{ - //pcm86->stepclock = ((UINT64)pccore.baseclock << 6); - //pcm86->stepclock /= 44100; - //pcm86->stepclock *= pccore.multiple; - } - } -} - -void SOUNDCALL pcm86gen_checkbuf(PCM86 pcm86, UINT nCount) -{ - long bufs; - UINT64 cur; - UINT64 past; - UINT64 pastCycle; - UINT64 curClock; - SINT32 flagStep; - static UINT32 lastClock = 0; - curClock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - if (lastClock == 0) - { - flagStep = 0; - } - else - { - flagStep = (SINT32)((SINT64)(curClock - lastClock) * 1000 / pccore.realclock); - } - //TRACEOUT(("FS %d", flagStep)); - - pastCycle = (UINT64)UINT_MAX << 6; - cur = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - cur <<= 6; - past = (cur + pastCycle - pcm86->lastclock) % pastCycle; - if (past > pastCycle / 2) - { - // 負の値になってしまっているとき - if (past < pastCycle - pcm86->stepclock * 4) - { - // かなり小さいならリセットをかける - past = 1; - pcm86->lastclock = cur - 1; - } - else - { - // 小さいなら様子見で0扱いとする - past = 0; - } - } - if (past >= pcm86->stepclock) - { - past = past / pcm86->stepclock; - pcm86->lastclock = (pcm86->lastclock + past * pcm86->stepclock) % pastCycle; - RECALC_NOWCLKWAIT(past); - } - - //pcm86->virbuf = pcm86->realbuf; - bufs = pcm86->realbuf - pcm86->virbuf; - if (bufs < 0) - { - // 処理落ちてるかもしれない - if (bufs <= -pcm86->fifosize && pcm86->virbuf < pcm86->fifosize) - { - // 駄目そうな場合 - //TRACEOUT(("CRITCAL buf: real %d, vir %d, (FIFOSIZE: %d) FORCE IRQ", pcm86->realbuf, pcm86->virbuf, pcm86->fifosize)); - bufs &= ~3; - pcm86->virbuf += bufs; - // nevent_setでデッドロックする可能性があるので割り込みはしない - } - //TRACEOUT(("buf: real %d, vir %d, (FIFOSIZE: %d) FORCE IRQ", pcm86->realbuf, pcm86->virbuf, pcm86->fifosize)); - //pcm86->lastclock += pcm86->stepclock / 50; - if (bufunferflag < INT_MAX - flagStep) - { - if (lastClock != 0) - { - bufunferflag += flagStep; - } - //TRACEOUT(("%d", bufunferflag)); - } - //} - //else if (bufs < pcm86->fifosize) - //{ - // if (bufunferflag < 8000) - // { - // if (lastClock != 0) - // { - // bufunferflag += flagStep; - // } - // //TRACEOUT(("%d", bufunferflag)); - // } - } - else - { - // 余裕あり - //bufs -= PCM86_EXTBUF; - //if (bufs > 0) - //{ - // bufs &= ~3; - // pcm86->realbuf -= bufs; - // pcm86->readpos += bufs; - //} - - //TRACEOUT(("%d,%d", pcm86->virbuf, pcm86->realbuf)); - if (pcm86->virbuf > pcm86->fifosize && pcm86->realbuf > pcm86->stepmask && pcm86->realbuf > pcm86->virbuf + pcm86->fifosize * 3) - { - //if (vbufunferflag < INT_MAX - flagStep) - //{ - // if (lastClock != 0) - // { - // vbufunferflag += flagStep; - // } - // //TRACEOUT(("v %d", vbufunferflag)); - //} - pcm86->virbuf += (pcm86->realbuf - (pcm86->virbuf - pcm86->fifosize * 3)) / 8; - TRACEOUT(("ADJUST!")); - } - //else - //{ - // //vbufunferflag = 0; - // if (lastClock != 0) - // { - // vbufunferflag -= flagStep; - // } - // if (vbufunferflag < 0) vbufunferflag = 0; - //} - bufunferflag = 0; - } - - lastClock = curClock; -} - -BOOL pcm86gen_intrq(int fromFMTimer) -{ - PCM86 pcm86 = &g_pcm86; - UINT64 curclk = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - // WORKAROUND: データ書き込みから割り込み発生までの時間が短すぎると不具合が起こる場合があるのでわざと遅延 - // XXX: 本当は循環しているのでg_pcm86.lastclockforwaitセットから時間が経ちすぎると不味い - // しかし仮に500MHzとしたときUINT64が1周するのは40万日くらいなので事実上問題ない - if (!(pcm86->fifo & 0x20) || !(curclk - g_pcm86.lastclockforwait >= datawriteirqwait)) - { - return FALSE; - } - if (pcm86->irqflag) - { - return TRUE; - } - if (!nevent_iswork(NEVENT_86PCM)) { - sound_sync(); - if (!(pcm86->irqflag) && (pcm86->virbuf <= pcm86->fifosize || pcm86->realbuf > pcm86->stepmask && pcm86->realbuf <= pcm86->fifosize)) - { - //pcm86->reqirq = 0; - pcm86->irqflag = 1; - return TRUE; - } - } - return FALSE; +/** + * @file pcm86c.c + * @brief Implementation of the 86-PCM + */ + +#include +#include +#include +#include +#include +#include + +#if 0 +#undef TRACEOUT +static void trace_fmt_ex(const char *fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "¥n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#else +#define TRACEOUT(s) (void)(s) +#endif /* 1 */ + +/* サンプリングレートに8掛けた物 */ +const UINT pcm86rate8[] = {352800, 264600, 176400, 132300, + 88200, 66150, 44010, 33075}; + +/* 32,24,16,12, 8, 6, 4, 3 - 最少公倍数: 96 */ +/* 3, 4, 6, 8,12,16,24,32 */ + +static const UINT clk25_128[] = { + 0x00001bde, 0x00002527, 0x000037bb, 0x00004a4e, + 0x00006f75, 0x0000949c, 0x0000df5f, 0x00012938}; +static const UINT clk20_128[] = { + 0x000016a4, 0x00001e30, 0x00002d48, 0x00003c60, + 0x00005a8f, 0x000078bf, 0x0000b57d, 0x0000f17d}; + + + PCM86CFG pcm86cfg; + + UINT64 datawriteirqwait = 0; + static SINT32 bufunferflag = 0; + static SINT32 vbufunferflag = 0; + +#if defined(SUPPORT_MULTITHREAD) + static int pcm86_cs_initialized = 0; + static CRITICAL_SECTION pcm86_cs; + + void pcm86cs_enter_criticalsection(void) + { + if (!pcm86_cs_initialized) return; + EnterCriticalSection(&pcm86_cs); + } + void pcm86cs_leave_criticalsection(void) + { + if (!pcm86_cs_initialized) return; + LeaveCriticalSection(&pcm86_cs); + } + + void pcm86cs_initialize(void) + { + /* クリティカルセクション準備 */ + if (!pcm86_cs_initialized) + { + memset(&pcm86_cs, 0, sizeof(pcm86_cs)); + InitializeCriticalSection(&pcm86_cs); + pcm86_cs_initialized = 1; + } + } + void pcm86cs_shutdown(void) + { + /* クリティカルセクション破棄 */ + if (pcm86_cs_initialized) + { + memset(&pcm86_cs, 0, sizeof(pcm86_cs)); + DeleteCriticalSection(&pcm86_cs); + pcm86_cs_initialized = 0; + } + } +#endif + +void pcm86gen_initialize(UINT rate) +{ + pcm86cfg.rate = rate; +} + +void pcm86gen_setvol(UINT vol) +{ + pcm86cfg.vol = vol; + pcm86gen_update(); +} + +void pcm86_reset(void) +{ + PCM86 pcm86 = &g_pcm86; + + memset(pcm86, 0, sizeof(*pcm86)); + pcm86->fifosize = 0x80; + pcm86->dactrl = 0x32; + pcm86->stepmask = (1 << 2) - 1; + pcm86->stepbit = 2; + pcm86->stepclock = ((UINT64)pccore.baseclock << 6); + pcm86->stepclock /= 44100; + pcm86->stepclock *= pccore.multiple; + pcm86->rescue = (PCM86_RESCUE * 32) << 2; + pcm86->irq = 0xff; + pcm86_setpcmrate(pcm86->fifo); // デフォルト値をセット +} + +void pcm86gen_update(void) +{ + PCM86 pcm86 = &g_pcm86; + + pcm86->volume = pcm86cfg.vol * pcm86->vol5; + pcm86_setpcmrate(pcm86->fifo); +} + +void pcm86_setwaittime() +{ + // WORKAROUND: データ書き込みから割り込み発生までの時間が短すぎると不具合が起こる場合があるのでわざと遅延 値に根拠はなし + datawriteirqwait = 20000 * pccore.multiple; +} + +void pcm86_setpcmrate(REG8 val) +{ + PCM86 pcm86 = &g_pcm86; + SINT32 rate; + + pcm86->rateval = rate = pcm86rate8[val & 7]; + pcm86->stepclock = ((UINT64)pccore.baseclock << 6); + pcm86->stepclock /= rate; + pcm86->stepclock *= (pccore.multiple << 3); + if (pcm86cfg.rate) + { + pcm86->div = (rate << (PCM86_DIVBIT - 3)) / pcm86cfg.rate; + pcm86->div2 = (pcm86cfg.rate << (PCM86_DIVBIT + 3)) / rate; + } + + pcm86_setwaittime(); +} + +void pcm86_cb(NEVENTITEM item) +{ + PCM86 pcm86 = &g_pcm86; + SINT32 adjustbuf; + + if (pcm86->reqirq) + { + sound_sync(); + // RECALC_NOWCLKP; + + adjustbuf = (SINT32)(((SINT64)pcm86->virbuf * 4 + pcm86->realbuf) / 5); + if (pcm86->virbuf <= pcm86->fifosize || pcm86->realbuf > pcm86->stepmask && adjustbuf <= pcm86->fifosize) + { + pcm86->reqirq = 0; + pcm86->irqflag = 1; + if (pcm86->irq != 0xff) + { + pic_setirq(pcm86->irq); + } + } + else + { + pcm86_setnextintr(); + } + } + else + { + pcm86_setnextintr(); + } + + (void)item; +} + +void pcm86_setnextintr(void) { + + PCM86 pcm86 = &g_pcm86; + SINT32 cntv; + SINT32 cntr; + SINT32 cnt; + SINT32 clk; + + if (pcm86->fifo & 0x80) + { + cntv = pcm86->virbuf - pcm86->fifosize; + cntr = pcm86->realbuf - pcm86->fifosize; + if (pcm86->realbuf > pcm86->stepmask) + { + if (cntr < cntv) + { + //cnt = cntr; + if (bufunferflag > 32000) + { + cnt = (SINT32)(((SINT64)cntv * 9 + cntr) / 10); + TRACEOUT(("Buf Under2", bufunferflag)); + } + else if (bufunferflag > 4000) + { + cnt = (SINT32)(((SINT64)cntv * 99 + cntr) / 100); + TRACEOUT(("Buf Under", bufunferflag)); + } + else + { + cnt = cntv; + } + } + else + { + if (vbufunferflag > 64000) + { + cnt = (SINT32)(((SINT64)cntv * 9 + cntr) / 10); + TRACEOUT(("VBuf Under3", vbufunferflag)); + } + else if (vbufunferflag > 16000) + { + cnt = (SINT32)(((SINT64)cntv * 49 + cntr) / 50); + TRACEOUT(("VBuf Under2", vbufunferflag)); + } + else if (vbufunferflag > 4000) + { + cnt = (SINT32)(((SINT64)cntv * 99 + cntr) / 100); + TRACEOUT(("VBuf Under", vbufunferflag)); + } + else + { + cnt = cntv; + } + } + } + else + { + cnt = cntv; + } + //cnt = (SINT32)(((SINT64)cntv + cntr) / 2); + if (cnt > 0) + { + cnt += pcm86->stepmask; + cnt >>= pcm86->stepbit; + //cnt += 4; + /* ここで clk = pccore.realclock * cnt / 86pcm_rate */ + /* clk = ((pccore.baseclock / 86pcm_rate) * cnt) * pccore.multiple */ + if (pccore.cpumode & CPUMODE_8MHZ) { + clk = clk20_128[pcm86->fifo & 7]; + } + else { + clk = clk25_128[pcm86->fifo & 7]; + } + /* cntは最大 8000h で 32bitで収まるように… */ + clk *= cnt; + clk >>= 7; +// clk++; /* roundup */ + //clk--; /* roundup */ + //if (clk > 1) clk--; + clk *= pccore.multiple; + nevent_set(NEVENT_86PCM, clk, pcm86_cb, NEVENT_ABSOLUTE); + TRACEOUT(("%d,%d", pcm86->virbuf, pcm86->realbuf)); + } + else + { + if (pcm86->reqirq) + { + // 即時 + nevent_set(NEVENT_86PCM, 1, pcm86_cb, NEVENT_ABSOLUTE); + } + else + { + // WORKAROUND: 前回の割り込みがうまくいっていない。適当な時間間隔で再度割り込みを送る。早すぎるとNT4等が割り込み無限ループするので注意 + pcm86->reqirq = 1; + nevent_set(NEVENT_86PCM, 100 * pccore.multiple, pcm86_cb, NEVENT_ABSOLUTE); + } + } + } +} + +void RECALC_NOWCLKWAIT(UINT64 cnt) +{ + SINT64 decvalue = (SINT64)(cnt << g_pcm86.stepbit); +#if defined(SUPPORT_MULTITHREAD) + pcm86cs_enter_criticalsection(); +#endif + if (g_pcm86.virbuf - decvalue < g_pcm86.virbuf) + { + g_pcm86.virbuf -= decvalue; + } + if (g_pcm86.virbuf < 0) + { + g_pcm86.virbuf &= g_pcm86.stepmask; + } +#if defined(SUPPORT_MULTITHREAD) + pcm86cs_leave_criticalsection(); +#endif +} + +void pcm86_changeclock(UINT oldmultiple) +{ + PCM86 pcm86 = &g_pcm86; + if(pcm86){ + if(pcm86->rateval){ + UINT64 cur; + UINT64 past; + UINT64 pastCycle; + UINT64 newstepclock; + newstepclock = ((UINT64)pccore.baseclock << 6); + newstepclock /= pcm86->rateval; + newstepclock *= ((UINT64)pccore.multiple << 3); + pastCycle = (UINT64)UINT_MAX << 6; + cur = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + cur <<= 6; + past = (cur + pastCycle - pcm86->lastclock) % pastCycle; + if (past > pastCycle / 2) + { + // 負の値になってしまっているとき + if (past < pastCycle - pcm86->stepclock * 4) + { + // かなり小さいならリセットをかける + past = 1; + pcm86->lastclock = cur - 1; + } + else + { + // 小さいなら様子見で0扱いとする + past = 0; + } + } + if (past >= pcm86->stepclock) + { + //SINT32 latvirbuf = pcm86->virbuf; + past = past / pcm86->stepclock; + pcm86->lastclock = (pcm86->lastclock + past * pcm86->stepclock) % pastCycle; + RECALC_NOWCLKWAIT(past); + //TRACEOUT(("%d %d %d", latvirbuf, pcm86->virbuf, past)); + } + past = (cur + pastCycle - pcm86->lastclock) % pastCycle; + pcm86->lastclock = (cur + pastCycle - (past * newstepclock + pcm86->stepclock / 2) / pcm86->stepclock) % pastCycle; // 補正 + pcm86->stepclock = newstepclock; + + pcm86_setwaittime(); + }else{ + //pcm86->stepclock = ((UINT64)pccore.baseclock << 6); + //pcm86->stepclock /= 44100; + //pcm86->stepclock *= pccore.multiple; + } + } +} + +void SOUNDCALL pcm86gen_checkbuf(PCM86 pcm86, UINT nCount) +{ + long bufs; + UINT64 cur; + UINT64 past; + UINT64 pastCycle; + UINT64 curClock; + SINT32 flagStep; + static UINT32 lastClock = 0; + curClock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + if (lastClock == 0) + { + flagStep = 0; + } + else + { + flagStep = (SINT32)((SINT64)(curClock - lastClock) * 1000 / pccore.realclock); + } + //TRACEOUT(("FS %d", flagStep)); + + pastCycle = (UINT64)UINT_MAX << 6; + cur = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + cur <<= 6; + past = (cur + pastCycle - pcm86->lastclock) % pastCycle; + if (past > pastCycle / 2) + { + // 負の値になってしまっているとき + if (past < pastCycle - pcm86->stepclock * 4) + { + // かなり小さいならリセットをかける + past = 1; + pcm86->lastclock = cur - 1; + } + else + { + // 小さいなら様子見で0扱いとする + past = 0; + } + } + if (past >= pcm86->stepclock) + { + past = past / pcm86->stepclock; + pcm86->lastclock = (pcm86->lastclock + past * pcm86->stepclock) % pastCycle; + RECALC_NOWCLKWAIT(past); + } + + //pcm86->virbuf = pcm86->realbuf; + bufs = pcm86->realbuf - pcm86->virbuf; + if (bufs < 0) + { + // 処理落ちてるかもしれない + if (bufs <= -pcm86->fifosize && pcm86->virbuf < pcm86->fifosize) + { + // 駄目そうな場合 + //TRACEOUT(("CRITCAL buf: real %d, vir %d, (FIFOSIZE: %d) FORCE IRQ", pcm86->realbuf, pcm86->virbuf, pcm86->fifosize)); + bufs &= ~3; + pcm86->virbuf += bufs; + // nevent_setでデッドロックする可能性があるので割り込みはしない + } + //TRACEOUT(("buf: real %d, vir %d, (FIFOSIZE: %d) FORCE IRQ", pcm86->realbuf, pcm86->virbuf, pcm86->fifosize)); + //pcm86->lastclock += pcm86->stepclock / 50; + if (bufunferflag < INT_MAX - flagStep) + { + if (lastClock != 0) + { + bufunferflag += flagStep; + } + //TRACEOUT(("%d", bufunferflag)); + } + //} + //else if (bufs < pcm86->fifosize) + //{ + // if (bufunferflag < 8000) + // { + // if (lastClock != 0) + // { + // bufunferflag += flagStep; + // } + // //TRACEOUT(("%d", bufunferflag)); + // } + } + else + { + // 余裕あり + //bufs -= PCM86_EXTBUF; + //if (bufs > 0) + //{ + // bufs &= ~3; + // pcm86->realbuf -= bufs; + // pcm86->readpos += bufs; + //} + + //TRACEOUT(("%d,%d", pcm86->virbuf, pcm86->realbuf)); + if (pcm86->virbuf > pcm86->fifosize && pcm86->realbuf > pcm86->stepmask && pcm86->realbuf > pcm86->virbuf + pcm86->fifosize * 3) + { + //if (vbufunferflag < INT_MAX - flagStep) + //{ + // if (lastClock != 0) + // { + // vbufunferflag += flagStep; + // } + // //TRACEOUT(("v %d", vbufunferflag)); + //} + pcm86->virbuf += (pcm86->realbuf - (pcm86->virbuf - pcm86->fifosize * 3)) / 8; + TRACEOUT(("ADJUST!")); + } + //else + //{ + // //vbufunferflag = 0; + // if (lastClock != 0) + // { + // vbufunferflag -= flagStep; + // } + // if (vbufunferflag < 0) vbufunferflag = 0; + //} + bufunferflag = 0; + } + + lastClock = curClock; +} + +BOOL pcm86gen_intrq(int fromFMTimer) +{ + PCM86 pcm86 = &g_pcm86; + UINT64 curclk = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + // WORKAROUND: データ書き込みから割り込み発生までの時間が短すぎると不具合が起こる場合があるのでわざと遅延 + // XXX: 本当は循環しているのでg_pcm86.lastclockforwaitセットから時間が経ちすぎると不味い + // しかし仮に500MHzとしたときUINT64が1周するのは40万日くらいなので事実上問題ない + if (!(pcm86->fifo & 0x20) || !(curclk - g_pcm86.lastclockforwait >= datawriteirqwait)) + { + return FALSE; + } + if (pcm86->irqflag) + { + return TRUE; + } + if (!nevent_iswork(NEVENT_86PCM)) { + sound_sync(); + if (!(pcm86->irqflag) && (pcm86->virbuf <= pcm86->fifosize || pcm86->realbuf > pcm86->stepmask && pcm86->realbuf <= pcm86->fifosize)) + { + //pcm86->reqirq = 0; + pcm86->irqflag = 1; + return TRUE; + } + } + return FALSE; } \ No newline at end of file diff --git a/sound/pcm86g.c b/sound/pcm86g.c old mode 100755 new mode 100644 index 74d7c886..679cc090 --- a/sound/pcm86g.c +++ b/sound/pcm86g.c @@ -1,394 +1,394 @@ -/** - * @file pcm86g.c - * @brief Implementation of the 86-PCM - */ - -#include -#include - -#if 0 -#undef TRACEOUT -#define TRACEOUT(s) (void)(s) -static void trace_fmt_ex(const char* fmt, ...) -{ - char stmp[2048]; - va_list ap; - va_start(ap, fmt); - vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); - va_end(ap); - OutputDebugStringA(stmp); -} -#define TRACEOUT(s) trace_fmt_ex s -#endif /* 1 */ - -#define PCM86GET8(p, a) \ - do \ - { \ - (a) = (SINT8)((p)->buffer[(p)->readpos & PCM86_BUFMSK]) << 8; \ - (p)->readpos++; \ - } while (0 /*CONSTCOND*/) - -#define PCM86GET16(p, a) \ - do \ - { \ - (a) = (SINT8)((p)->buffer[(p)->readpos & PCM86_BUFMSK]) << 8; \ - (a) |= (p)->buffer[((p)->readpos + 1) & PCM86_BUFMSK]; \ - (p)->readpos += 2; \ - } while (0 /*CONSTCOND*/) - -#define BYVOLUME(p, s) ((((s) >> 6) * (p)->volume) >> (PCM86_DIVBIT + 4)) - - -static void pcm86mono16(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount) -{ - if (pcm86->div < PCM86_DIVENV) /* アップさんぷる */ - { - do - { - SINT32 smp; - if (pcm86->divremain < 0) - { - SINT32 dat; - pcm86->divremain += PCM86_DIVENV; - pcm86->realbuf -= 2; - if (pcm86->realbuf < 0) - { - goto pm16_bufempty; - } - PCM86GET16(pcm86, dat); - pcm86->lastsmp = pcm86->smp; - pcm86->smp = dat; - } - smp = (pcm86->lastsmp * pcm86->divremain) - (pcm86->smp * (pcm86->divremain - PCM86_DIVENV)); - lpBuffer[0] += BYVOLUME(pcm86, smp); - lpBuffer += 2; - pcm86->divremain -= pcm86->div; - } while (--nCount); - } - else - { - do - { - SINT32 smp; - smp = pcm86->smp * (pcm86->divremain * -1); - pcm86->divremain += PCM86_DIVENV; - while (1) - { - SINT32 dat; - pcm86->realbuf -= 2; - if (pcm86->realbuf < 0) - { - goto pm16_bufempty; - } - PCM86GET16(pcm86, dat); - pcm86->lastsmp = pcm86->smp; - pcm86->smp = dat; - if (pcm86->divremain > pcm86->div2) - { - pcm86->divremain -= pcm86->div2; - smp += pcm86->smp * pcm86->div2; - } - else - { - break; - } - } - smp += pcm86->smp * pcm86->divremain; - lpBuffer[0] += BYVOLUME(pcm86, smp); - lpBuffer += 2; - pcm86->divremain -= pcm86->div2; - } while (--nCount); - } - return; - -pm16_bufempty: - pcm86->realbuf += 2; - pcm86->divremain = 0; - pcm86->smp = 0; - pcm86->lastsmp = 0; -} - -static void pcm86stereo16(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount) -{ - if (pcm86->div < PCM86_DIVENV) /* アップさんぷる */ - { - do - { - SINT32 smp; - if (pcm86->divremain < 0) - { - SINT32 dat; - pcm86->divremain += PCM86_DIVENV; - pcm86->realbuf -= 4; - if (pcm86->realbuf < 0) - { - goto ps16_bufempty; - } - PCM86GET16(pcm86, dat); - pcm86->lastsmp_l = pcm86->smp_l; - pcm86->smp_l = dat; - PCM86GET16(pcm86, dat); - pcm86->lastsmp_r = pcm86->smp_r; - pcm86->smp_r = dat; - } - smp = (pcm86->lastsmp_l * pcm86->divremain) - (pcm86->smp_l * (pcm86->divremain - PCM86_DIVENV)); - lpBuffer[0] += BYVOLUME(pcm86, smp); - smp = (pcm86->lastsmp_r * pcm86->divremain) - (pcm86->smp_r * (pcm86->divremain - PCM86_DIVENV)); - lpBuffer[1] += BYVOLUME(pcm86, smp); - lpBuffer += 2; - pcm86->divremain -= pcm86->div; - } while (--nCount); - } - else - { - do - { - SINT32 smp_l; - SINT32 smp_r; - smp_l = pcm86->smp_l * (pcm86->divremain * -1); - smp_r = pcm86->smp_r * (pcm86->divremain * -1); - pcm86->divremain += PCM86_DIVENV; - while (1 /*CONSTCOND*/) - { - SINT32 dat; - pcm86->realbuf -= 4; - //if (pcm86->realbuf < 4) // ??? - if (pcm86->realbuf < 0) - { - goto ps16_bufempty; - } - PCM86GET16(pcm86, dat); - pcm86->lastsmp_l = pcm86->smp_l; - pcm86->smp_l = dat; - PCM86GET16(pcm86, dat); - pcm86->lastsmp_r = pcm86->smp_r; - pcm86->smp_r = dat; - if (pcm86->divremain > pcm86->div2) - { - pcm86->divremain -= pcm86->div2; - smp_l += pcm86->smp_l * pcm86->div2; - smp_r += pcm86->smp_r * pcm86->div2; - } - else - { - break; - } - } - smp_l += pcm86->smp_l * pcm86->divremain; - smp_r += pcm86->smp_r * pcm86->divremain; - lpBuffer[0] += BYVOLUME(pcm86, smp_l); - lpBuffer[1] += BYVOLUME(pcm86, smp_r); - lpBuffer += 2; - pcm86->divremain -= pcm86->div2; - } while (--nCount); - } - return; - -ps16_bufempty: - pcm86->realbuf += 4; - pcm86->divremain = 0; - pcm86->smp_l = 0; - pcm86->smp_r = 0; - pcm86->lastsmp_l = 0; - pcm86->lastsmp_r = 0; -} - -static void pcm86mono8(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount) -{ - if (pcm86->div < PCM86_DIVENV) /* アップさんぷる */ - { - do - { - SINT32 smp; - if (pcm86->divremain < 0) - { - SINT32 dat; - pcm86->divremain += PCM86_DIVENV; - pcm86->realbuf--; - if (pcm86->realbuf < 0) - { - goto pm8_bufempty; - } - PCM86GET8(pcm86, dat); - pcm86->lastsmp = pcm86->smp; - pcm86->smp = dat; - } - smp = (pcm86->lastsmp * pcm86->divremain) - (pcm86->smp * (pcm86->divremain - PCM86_DIVENV)); - lpBuffer[0] += BYVOLUME(pcm86, smp); - lpBuffer += 2; - pcm86->divremain -= pcm86->div; - } while (--nCount); - } - else - { - do - { - SINT32 smp; - smp = pcm86->smp * (pcm86->divremain * -1); - pcm86->divremain += PCM86_DIVENV; - while (1 /*CONSTCOND*/) - { - SINT32 dat; - pcm86->realbuf--; - if (pcm86->realbuf < 0) - { - goto pm8_bufempty; - } - PCM86GET8(pcm86, dat); - pcm86->lastsmp = pcm86->smp; - pcm86->smp = dat; - if (pcm86->divremain > pcm86->div2) - { - pcm86->divremain -= pcm86->div2; - smp += pcm86->smp * pcm86->div2; - } - else - { - break; - } - } - smp += pcm86->smp * pcm86->divremain; - lpBuffer[0] += BYVOLUME(pcm86, smp); - lpBuffer += 2; - pcm86->divremain -= pcm86->div2; - } while (--nCount); - } - return; - -pm8_bufempty: - pcm86->realbuf += 1; - pcm86->divremain = 0; - pcm86->smp = 0; - pcm86->lastsmp = 0; -} - -static void pcm86stereo8(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount) -{ - if (pcm86->div < PCM86_DIVENV) /* アップさんぷる */ - { - do - { - SINT32 smp; - if (pcm86->divremain < 0) - { - SINT32 dat; - pcm86->divremain += PCM86_DIVENV; - pcm86->realbuf -= 2; - if (pcm86->realbuf < 0) - { - goto pm8_bufempty; - } - PCM86GET8(pcm86, dat); - pcm86->lastsmp_l = pcm86->smp_l; - pcm86->smp_l = dat; - PCM86GET8(pcm86, dat); - pcm86->lastsmp_r = pcm86->smp_r; - pcm86->smp_r = dat; - } - smp = (pcm86->lastsmp_l * pcm86->divremain) - (pcm86->smp_l * (pcm86->divremain - PCM86_DIVENV)); - lpBuffer[0] += BYVOLUME(pcm86, smp); - smp = (pcm86->lastsmp_r * pcm86->divremain) - (pcm86->smp_r * (pcm86->divremain - PCM86_DIVENV)); - lpBuffer[1] += BYVOLUME(pcm86, smp); - lpBuffer += 2; - pcm86->divremain -= pcm86->div; - } while (--nCount); - } - else - { - do - { - SINT32 smp_l; - SINT32 smp_r; - smp_l = pcm86->smp_l * (pcm86->divremain * -1); - smp_r = pcm86->smp_r * (pcm86->divremain * -1); - pcm86->divremain += PCM86_DIVENV; - while (1 /*CONSTCOND*/) - { - SINT32 dat; - pcm86->realbuf -= 2; - if (pcm86->realbuf < 0) - { - goto pm8_bufempty; - } - PCM86GET8(pcm86, dat); - pcm86->lastsmp_l = pcm86->smp_l; - pcm86->smp_l = dat; - PCM86GET8(pcm86, dat); - pcm86->lastsmp_r = pcm86->smp_r; - pcm86->smp_r = dat; - if (pcm86->divremain > pcm86->div2) - { - pcm86->divremain -= pcm86->div2; - smp_l += pcm86->smp_l * pcm86->div2; - smp_r += pcm86->smp_r * pcm86->div2; - } - else - { - break; - } - } - smp_l += pcm86->smp_l * pcm86->divremain; - smp_r += pcm86->smp_r * pcm86->divremain; - lpBuffer[0] += BYVOLUME(pcm86, smp_l); - lpBuffer[1] += BYVOLUME(pcm86, smp_r); - lpBuffer += 2; - pcm86->divremain -= pcm86->div2; - } while (--nCount); - } - return; - -pm8_bufempty: - pcm86->realbuf += 2; - pcm86->divremain = 0; - pcm86->smp_l = 0; - pcm86->smp_r = 0; - pcm86->lastsmp_l = 0; - pcm86->lastsmp_r = 0; -} - -void SOUNDCALL pcm86gen_getpcm(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount) -{ - if ((nCount) && (pcm86->fifo & 0x80) && (pcm86->div)) - { -#if defined(SUPPORT_MULTITHREAD) - pcm86cs_enter_criticalsection(); -#endif - switch (pcm86->dactrl & 0x70) - { - case 0x00: /* 16bit-none */ - break; - - case 0x10: /* 16bit-right */ - pcm86mono16(pcm86, lpBuffer + 1, nCount); - break; - - case 0x20: /* 16bit-left */ - pcm86mono16(pcm86, lpBuffer, nCount); - break; - - case 0x30: /* 16bit-stereo */ - pcm86stereo16(pcm86, lpBuffer, nCount); - break; - - case 0x40: /* 8bit-none */ - break; - - case 0x50: /* 8bit-right */ - pcm86mono8(pcm86, lpBuffer + 1, nCount); - break; - - case 0x60: /* 8bit-left */ - pcm86mono8(pcm86, lpBuffer, nCount); - break; - - case 0x70: /* 8bit-stereo */ - pcm86stereo8(pcm86, lpBuffer, nCount); - break; - } -#if defined(SUPPORT_MULTITHREAD) - pcm86cs_leave_criticalsection(); -#endif - pcm86gen_checkbuf(pcm86, nCount); - } +/** + * @file pcm86g.c + * @brief Implementation of the 86-PCM + */ + +#include +#include + +#if 0 +#undef TRACEOUT +#define TRACEOUT(s) (void)(s) +static void trace_fmt_ex(const char* fmt, ...) +{ + char stmp[2048]; + va_list ap; + va_start(ap, fmt); + vsprintf(stmp, fmt, ap); + strcat(stmp, "¥n"); + va_end(ap); + OutputDebugStringA(stmp); +} +#define TRACEOUT(s) trace_fmt_ex s +#endif /* 1 */ + +#define PCM86GET8(p, a) \ + do \ + { \ + (a) = (SINT8)((p)->buffer[(p)->readpos & PCM86_BUFMSK]) << 8; \ + (p)->readpos++; \ + } while (0 /*CONSTCOND*/) + +#define PCM86GET16(p, a) \ + do \ + { \ + (a) = (SINT8)((p)->buffer[(p)->readpos & PCM86_BUFMSK]) << 8; \ + (a) |= (p)->buffer[((p)->readpos + 1) & PCM86_BUFMSK]; \ + (p)->readpos += 2; \ + } while (0 /*CONSTCOND*/) + +#define BYVOLUME(p, s) ((((s) >> 6) * (p)->volume) >> (PCM86_DIVBIT + 4)) + + +static void pcm86mono16(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount) +{ + if (pcm86->div < PCM86_DIVENV) /* アップさんぷる */ + { + do + { + SINT32 smp; + if (pcm86->divremain < 0) + { + SINT32 dat; + pcm86->divremain += PCM86_DIVENV; + pcm86->realbuf -= 2; + if (pcm86->realbuf < 0) + { + goto pm16_bufempty; + } + PCM86GET16(pcm86, dat); + pcm86->lastsmp = pcm86->smp; + pcm86->smp = dat; + } + smp = (pcm86->lastsmp * pcm86->divremain) - (pcm86->smp * (pcm86->divremain - PCM86_DIVENV)); + lpBuffer[0] += BYVOLUME(pcm86, smp); + lpBuffer += 2; + pcm86->divremain -= pcm86->div; + } while (--nCount); + } + else + { + do + { + SINT32 smp; + smp = pcm86->smp * (pcm86->divremain * -1); + pcm86->divremain += PCM86_DIVENV; + while (1) + { + SINT32 dat; + pcm86->realbuf -= 2; + if (pcm86->realbuf < 0) + { + goto pm16_bufempty; + } + PCM86GET16(pcm86, dat); + pcm86->lastsmp = pcm86->smp; + pcm86->smp = dat; + if (pcm86->divremain > pcm86->div2) + { + pcm86->divremain -= pcm86->div2; + smp += pcm86->smp * pcm86->div2; + } + else + { + break; + } + } + smp += pcm86->smp * pcm86->divremain; + lpBuffer[0] += BYVOLUME(pcm86, smp); + lpBuffer += 2; + pcm86->divremain -= pcm86->div2; + } while (--nCount); + } + return; + +pm16_bufempty: + pcm86->realbuf += 2; + pcm86->divremain = 0; + pcm86->smp = 0; + pcm86->lastsmp = 0; +} + +static void pcm86stereo16(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount) +{ + if (pcm86->div < PCM86_DIVENV) /* アップさんぷる */ + { + do + { + SINT32 smp; + if (pcm86->divremain < 0) + { + SINT32 dat; + pcm86->divremain += PCM86_DIVENV; + pcm86->realbuf -= 4; + if (pcm86->realbuf < 0) + { + goto ps16_bufempty; + } + PCM86GET16(pcm86, dat); + pcm86->lastsmp_l = pcm86->smp_l; + pcm86->smp_l = dat; + PCM86GET16(pcm86, dat); + pcm86->lastsmp_r = pcm86->smp_r; + pcm86->smp_r = dat; + } + smp = (pcm86->lastsmp_l * pcm86->divremain) - (pcm86->smp_l * (pcm86->divremain - PCM86_DIVENV)); + lpBuffer[0] += BYVOLUME(pcm86, smp); + smp = (pcm86->lastsmp_r * pcm86->divremain) - (pcm86->smp_r * (pcm86->divremain - PCM86_DIVENV)); + lpBuffer[1] += BYVOLUME(pcm86, smp); + lpBuffer += 2; + pcm86->divremain -= pcm86->div; + } while (--nCount); + } + else + { + do + { + SINT32 smp_l; + SINT32 smp_r; + smp_l = pcm86->smp_l * (pcm86->divremain * -1); + smp_r = pcm86->smp_r * (pcm86->divremain * -1); + pcm86->divremain += PCM86_DIVENV; + while (1 /*CONSTCOND*/) + { + SINT32 dat; + pcm86->realbuf -= 4; + //if (pcm86->realbuf < 4) // ??? + if (pcm86->realbuf < 0) + { + goto ps16_bufempty; + } + PCM86GET16(pcm86, dat); + pcm86->lastsmp_l = pcm86->smp_l; + pcm86->smp_l = dat; + PCM86GET16(pcm86, dat); + pcm86->lastsmp_r = pcm86->smp_r; + pcm86->smp_r = dat; + if (pcm86->divremain > pcm86->div2) + { + pcm86->divremain -= pcm86->div2; + smp_l += pcm86->smp_l * pcm86->div2; + smp_r += pcm86->smp_r * pcm86->div2; + } + else + { + break; + } + } + smp_l += pcm86->smp_l * pcm86->divremain; + smp_r += pcm86->smp_r * pcm86->divremain; + lpBuffer[0] += BYVOLUME(pcm86, smp_l); + lpBuffer[1] += BYVOLUME(pcm86, smp_r); + lpBuffer += 2; + pcm86->divremain -= pcm86->div2; + } while (--nCount); + } + return; + +ps16_bufempty: + pcm86->realbuf += 4; + pcm86->divremain = 0; + pcm86->smp_l = 0; + pcm86->smp_r = 0; + pcm86->lastsmp_l = 0; + pcm86->lastsmp_r = 0; +} + +static void pcm86mono8(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount) +{ + if (pcm86->div < PCM86_DIVENV) /* アップさんぷる */ + { + do + { + SINT32 smp; + if (pcm86->divremain < 0) + { + SINT32 dat; + pcm86->divremain += PCM86_DIVENV; + pcm86->realbuf--; + if (pcm86->realbuf < 0) + { + goto pm8_bufempty; + } + PCM86GET8(pcm86, dat); + pcm86->lastsmp = pcm86->smp; + pcm86->smp = dat; + } + smp = (pcm86->lastsmp * pcm86->divremain) - (pcm86->smp * (pcm86->divremain - PCM86_DIVENV)); + lpBuffer[0] += BYVOLUME(pcm86, smp); + lpBuffer += 2; + pcm86->divremain -= pcm86->div; + } while (--nCount); + } + else + { + do + { + SINT32 smp; + smp = pcm86->smp * (pcm86->divremain * -1); + pcm86->divremain += PCM86_DIVENV; + while (1 /*CONSTCOND*/) + { + SINT32 dat; + pcm86->realbuf--; + if (pcm86->realbuf < 0) + { + goto pm8_bufempty; + } + PCM86GET8(pcm86, dat); + pcm86->lastsmp = pcm86->smp; + pcm86->smp = dat; + if (pcm86->divremain > pcm86->div2) + { + pcm86->divremain -= pcm86->div2; + smp += pcm86->smp * pcm86->div2; + } + else + { + break; + } + } + smp += pcm86->smp * pcm86->divremain; + lpBuffer[0] += BYVOLUME(pcm86, smp); + lpBuffer += 2; + pcm86->divremain -= pcm86->div2; + } while (--nCount); + } + return; + +pm8_bufempty: + pcm86->realbuf += 1; + pcm86->divremain = 0; + pcm86->smp = 0; + pcm86->lastsmp = 0; +} + +static void pcm86stereo8(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount) +{ + if (pcm86->div < PCM86_DIVENV) /* アップさんぷる */ + { + do + { + SINT32 smp; + if (pcm86->divremain < 0) + { + SINT32 dat; + pcm86->divremain += PCM86_DIVENV; + pcm86->realbuf -= 2; + if (pcm86->realbuf < 0) + { + goto pm8_bufempty; + } + PCM86GET8(pcm86, dat); + pcm86->lastsmp_l = pcm86->smp_l; + pcm86->smp_l = dat; + PCM86GET8(pcm86, dat); + pcm86->lastsmp_r = pcm86->smp_r; + pcm86->smp_r = dat; + } + smp = (pcm86->lastsmp_l * pcm86->divremain) - (pcm86->smp_l * (pcm86->divremain - PCM86_DIVENV)); + lpBuffer[0] += BYVOLUME(pcm86, smp); + smp = (pcm86->lastsmp_r * pcm86->divremain) - (pcm86->smp_r * (pcm86->divremain - PCM86_DIVENV)); + lpBuffer[1] += BYVOLUME(pcm86, smp); + lpBuffer += 2; + pcm86->divremain -= pcm86->div; + } while (--nCount); + } + else + { + do + { + SINT32 smp_l; + SINT32 smp_r; + smp_l = pcm86->smp_l * (pcm86->divremain * -1); + smp_r = pcm86->smp_r * (pcm86->divremain * -1); + pcm86->divremain += PCM86_DIVENV; + while (1 /*CONSTCOND*/) + { + SINT32 dat; + pcm86->realbuf -= 2; + if (pcm86->realbuf < 0) + { + goto pm8_bufempty; + } + PCM86GET8(pcm86, dat); + pcm86->lastsmp_l = pcm86->smp_l; + pcm86->smp_l = dat; + PCM86GET8(pcm86, dat); + pcm86->lastsmp_r = pcm86->smp_r; + pcm86->smp_r = dat; + if (pcm86->divremain > pcm86->div2) + { + pcm86->divremain -= pcm86->div2; + smp_l += pcm86->smp_l * pcm86->div2; + smp_r += pcm86->smp_r * pcm86->div2; + } + else + { + break; + } + } + smp_l += pcm86->smp_l * pcm86->divremain; + smp_r += pcm86->smp_r * pcm86->divremain; + lpBuffer[0] += BYVOLUME(pcm86, smp_l); + lpBuffer[1] += BYVOLUME(pcm86, smp_r); + lpBuffer += 2; + pcm86->divremain -= pcm86->div2; + } while (--nCount); + } + return; + +pm8_bufempty: + pcm86->realbuf += 2; + pcm86->divremain = 0; + pcm86->smp_l = 0; + pcm86->smp_r = 0; + pcm86->lastsmp_l = 0; + pcm86->lastsmp_r = 0; +} + +void SOUNDCALL pcm86gen_getpcm(PCM86 pcm86, SINT32 *lpBuffer, UINT nCount) +{ + if ((nCount) && (pcm86->fifo & 0x80) && (pcm86->div)) + { +#if defined(SUPPORT_MULTITHREAD) + pcm86cs_enter_criticalsection(); +#endif + switch (pcm86->dactrl & 0x70) + { + case 0x00: /* 16bit-none */ + break; + + case 0x10: /* 16bit-right */ + pcm86mono16(pcm86, lpBuffer + 1, nCount); + break; + + case 0x20: /* 16bit-left */ + pcm86mono16(pcm86, lpBuffer, nCount); + break; + + case 0x30: /* 16bit-stereo */ + pcm86stereo16(pcm86, lpBuffer, nCount); + break; + + case 0x40: /* 8bit-none */ + break; + + case 0x50: /* 8bit-right */ + pcm86mono8(pcm86, lpBuffer + 1, nCount); + break; + + case 0x60: /* 8bit-left */ + pcm86mono8(pcm86, lpBuffer, nCount); + break; + + case 0x70: /* 8bit-stereo */ + pcm86stereo8(pcm86, lpBuffer, nCount); + break; + } +#if defined(SUPPORT_MULTITHREAD) + pcm86cs_leave_criticalsection(); +#endif + pcm86gen_checkbuf(pcm86, nCount); + } } \ No newline at end of file diff --git a/sound/pcmmix.c b/sound/pcmmix.c old mode 100755 new mode 100644 index 5849e1f9..e580c944 --- a/sound/pcmmix.c +++ b/sound/pcmmix.c @@ -1,164 +1,164 @@ -/** - * @file pcmmix.c - * @brief Implementation of the pcm sound - */ - -#include -#include -#include "getsnd/getsnd.h" -#include - -BRESULT pcmmix_regist(PMIXDAT *dat, void *datptr, UINT datsize, UINT rate) { - - GETSND gs; - UINT8 tmp[256]; - UINT size; - UINT r; - SINT16 *buf; - - gs = getsnd_create(datptr, datsize); - if (gs == NULL) { - goto pmr_err1; - } - if (getsnd_setmixproc(gs, rate, 1) != SUCCESS) { - goto pmr_err2; - } - size = 0; - do { - r = getsnd_getpcmbyleng(gs, tmp, sizeof(tmp)); - size += r; - } while(r); - getsnd_destroy(gs); - if (size == 0) { - goto pmr_err1; - } - - buf = (SINT16 *)_MALLOC(size, "PCM DATA"); - if (buf == NULL) { - goto pmr_err1; - } - gs = getsnd_create(datptr, datsize); - if (gs == NULL) { - goto pmr_err1; - } - if (getsnd_setmixproc(gs, rate, 1) != SUCCESS) { - goto pmr_err2; - } - r = getsnd_getpcmbyleng(gs, buf, size); - getsnd_destroy(gs); - dat->sample = buf; - dat->samples = r / 2; - return(SUCCESS); - -pmr_err2: - getsnd_destroy(gs); - -pmr_err1: - return(FAILURE); -} - -BRESULT pcmmix_regfile(PMIXDAT *dat, const OEMCHAR *fname, UINT rate) { - - FILEH fh; - UINT size; - UINT8 *ptr; - BRESULT r; - - r = FAILURE; - fh = file_open_rb(fname); - if (fh == FILEH_INVALID) { - goto pmrf_err1; - } - size = (UINT)file_getsize(fh); - if (size == 0) { - goto pmrf_err2; - } - ptr = (UINT8 *)_MALLOC(size, fname); - if (ptr == NULL) { - goto pmrf_err2; - } - file_read(fh, ptr, size); - file_close(fh); - r = pcmmix_regist(dat, ptr, size, rate); - _MFREE(ptr); - return(r); - -pmrf_err2: - file_close(fh); - -pmrf_err1: - return(FAILURE); -} - -void SOUNDCALL pcmmix_getpcm(PCMMIX hdl, SINT32 *pcm, UINT count) { - - UINT32 bitmap; - PMIXTRK *t; -const SINT16 *s; - UINT srem; - SINT32 *d; - UINT drem; - UINT r; - UINT j; - UINT flag; - SINT32 vol; - SINT32 samp; - - if ((hdl->hdr.playing == 0) || (count == 0)) { - return; - } - t = hdl->trk; - bitmap = 1; - do { - if (hdl->hdr.playing & bitmap) { - s = t->pcm; - srem = t->remain; - d = pcm; - drem = count; - flag = t->flag; - vol = t->volume; - do { - r = MIN(srem, drem); - switch(flag & (PMIXFLAG_L | PMIXFLAG_R)) { - case PMIXFLAG_L: - for (j=0; j> 12; - } - break; - - case PMIXFLAG_R: - for (j=0; j> 12; - } - break; - - case PMIXFLAG_L | PMIXFLAG_R: - for (j=0; j> 12; - d[j*2+0] += samp; - d[j*2+1] += samp; - } - break; - } - s += r; - d += r*2; - srem -= r; - if (srem == 0) { - if (flag & PMIXFLAG_LOOP) { - s = t->data.sample; - srem = t->data.samples; - } - else { - hdl->hdr.playing &= ~bitmap; - break; - } - } - drem -= r; - } while(drem); - t->pcm = s; - t->remain = srem; - } - t++; - bitmap <<= 1; - } while(bitmap < hdl->hdr.enable); -} +/** + * @file pcmmix.c + * @brief Implementation of the pcm sound + */ + +#include +#include +#include "getsnd/getsnd.h" +#include + +BRESULT pcmmix_regist(PMIXDAT *dat, void *datptr, UINT datsize, UINT rate) { + + GETSND gs; + UINT8 tmp[256]; + UINT size; + UINT r; + SINT16 *buf; + + gs = getsnd_create(datptr, datsize); + if (gs == NULL) { + goto pmr_err1; + } + if (getsnd_setmixproc(gs, rate, 1) != SUCCESS) { + goto pmr_err2; + } + size = 0; + do { + r = getsnd_getpcmbyleng(gs, tmp, sizeof(tmp)); + size += r; + } while(r); + getsnd_destroy(gs); + if (size == 0) { + goto pmr_err1; + } + + buf = (SINT16 *)_MALLOC(size, "PCM DATA"); + if (buf == NULL) { + goto pmr_err1; + } + gs = getsnd_create(datptr, datsize); + if (gs == NULL) { + goto pmr_err1; + } + if (getsnd_setmixproc(gs, rate, 1) != SUCCESS) { + goto pmr_err2; + } + r = getsnd_getpcmbyleng(gs, buf, size); + getsnd_destroy(gs); + dat->sample = buf; + dat->samples = r / 2; + return(SUCCESS); + +pmr_err2: + getsnd_destroy(gs); + +pmr_err1: + return(FAILURE); +} + +BRESULT pcmmix_regfile(PMIXDAT *dat, const OEMCHAR *fname, UINT rate) { + + FILEH fh; + UINT size; + UINT8 *ptr; + BRESULT r; + + r = FAILURE; + fh = file_open_rb(fname); + if (fh == FILEH_INVALID) { + goto pmrf_err1; + } + size = (UINT)file_getsize(fh); + if (size == 0) { + goto pmrf_err2; + } + ptr = (UINT8 *)_MALLOC(size, fname); + if (ptr == NULL) { + goto pmrf_err2; + } + file_read(fh, ptr, size); + file_close(fh); + r = pcmmix_regist(dat, ptr, size, rate); + _MFREE(ptr); + return(r); + +pmrf_err2: + file_close(fh); + +pmrf_err1: + return(FAILURE); +} + +void SOUNDCALL pcmmix_getpcm(PCMMIX hdl, SINT32 *pcm, UINT count) { + + UINT32 bitmap; + PMIXTRK *t; +const SINT16 *s; + UINT srem; + SINT32 *d; + UINT drem; + UINT r; + UINT j; + UINT flag; + SINT32 vol; + SINT32 samp; + + if ((hdl->hdr.playing == 0) || (count == 0)) { + return; + } + t = hdl->trk; + bitmap = 1; + do { + if (hdl->hdr.playing & bitmap) { + s = t->pcm; + srem = t->remain; + d = pcm; + drem = count; + flag = t->flag; + vol = t->volume; + do { + r = MIN(srem, drem); + switch(flag & (PMIXFLAG_L | PMIXFLAG_R)) { + case PMIXFLAG_L: + for (j=0; j> 12; + } + break; + + case PMIXFLAG_R: + for (j=0; j> 12; + } + break; + + case PMIXFLAG_L | PMIXFLAG_R: + for (j=0; j> 12; + d[j*2+0] += samp; + d[j*2+1] += samp; + } + break; + } + s += r; + d += r*2; + srem -= r; + if (srem == 0) { + if (flag & PMIXFLAG_LOOP) { + s = t->data.sample; + srem = t->data.samples; + } + else { + hdl->hdr.playing &= ~bitmap; + break; + } + } + drem -= r; + } while(drem); + t->pcm = s; + t->remain = srem; + } + t++; + bitmap <<= 1; + } while(bitmap < hdl->hdr.enable); +} diff --git a/sound/pcmmix.h b/sound/pcmmix.h old mode 100755 new mode 100644 index 92dc802e..eb127dad --- a/sound/pcmmix.h +++ b/sound/pcmmix.h @@ -1,52 +1,52 @@ -/** - * @file pcmmix.h - * @brief Interface of the pcm sound - */ - -#pragma once - -#include - -enum { - PMIXFLAG_L = 0x0001, - PMIXFLAG_R = 0x0002, - PMIXFLAG_LOOP = 0x0004 -}; - -typedef struct { - UINT32 playing; - UINT32 enable; -} PMIXHDR; - -typedef struct { - SINT16 *sample; - UINT samples; -} PMIXDAT; - -typedef struct { -const SINT16 *pcm; - UINT remain; - PMIXDAT data; - UINT flag; - SINT32 volume; -} PMIXTRK; - -typedef struct { - PMIXHDR hdr; - PMIXTRK trk[1]; -} _PCMMIX, *PCMMIX; - - -#ifdef __cplusplus -extern "C" -{ -#endif - -BRESULT pcmmix_regist(PMIXDAT *dat, void *datptr, UINT datsize, UINT rate); -BRESULT pcmmix_regfile(PMIXDAT *dat, const OEMCHAR *fname, UINT rate); - -void SOUNDCALL pcmmix_getpcm(PCMMIX hdl, SINT32 *pcm, UINT count); - -#ifdef __cplusplus -} -#endif +/** + * @file pcmmix.h + * @brief Interface of the pcm sound + */ + +#pragma once + +#include + +enum { + PMIXFLAG_L = 0x0001, + PMIXFLAG_R = 0x0002, + PMIXFLAG_LOOP = 0x0004 +}; + +typedef struct { + UINT32 playing; + UINT32 enable; +} PMIXHDR; + +typedef struct { + SINT16 *sample; + UINT samples; +} PMIXDAT; + +typedef struct { +const SINT16 *pcm; + UINT remain; + PMIXDAT data; + UINT flag; + SINT32 volume; +} PMIXTRK; + +typedef struct { + PMIXHDR hdr; + PMIXTRK trk[1]; +} _PCMMIX, *PCMMIX; + + +#ifdef __cplusplus +extern "C" +{ +#endif + +BRESULT pcmmix_regist(PMIXDAT *dat, void *datptr, UINT datsize, UINT rate); +BRESULT pcmmix_regfile(PMIXDAT *dat, const OEMCHAR *fname, UINT rate); + +void SOUNDCALL pcmmix_getpcm(PCMMIX hdl, SINT32 *pcm, UINT count); + +#ifdef __cplusplus +} +#endif diff --git a/sound/psggen.h b/sound/psggen.h old mode 100755 new mode 100644 index 3b1dd2fa..ece6b03c --- a/sound/psggen.h +++ b/sound/psggen.h @@ -1,88 +1,88 @@ -/** - * @file psggen.h - * @brief Interface of the PSG - */ - -#pragma once - -#include - -enum { - PSGFREQPADBIT = 12, - PSGADDEDBIT = 3 -}; - -enum { - PSGENV_INC = 15, - PSGENV_ONESHOT = 16, - PSGENV_LASTON = 32, - PSGENV_ONECYCLE = 64 -}; - -typedef struct { - SINT32 freq; - SINT32 count; - SINT32 *pvol; // !! - UINT16 puchi; - UINT8 pan; - UINT8 padding; -} PSGTONE; - -typedef struct { - UINT32 freq; /*!< frequency */ - UINT32 count; /*!< counter */ - UINT lfsr; /*!< linear feedback shift register */ -} PSGNOISE; - -typedef struct { - UINT8 tune[3][2]; // 0 - UINT8 noise; // 6 - UINT8 mixer; // 7 - UINT8 vol[3]; // 8 - UINT8 envtime[2]; // b - UINT8 env; // d - UINT8 io1; - UINT8 io2; -} PSGREG; - -typedef struct { - PSGTONE tone[3]; - PSGNOISE noise; - PSGREG reg; - UINT16 envcnt; - UINT16 envmax; - UINT8 mixer; - UINT8 envmode; - UINT8 envvol; - SINT8 envvolcnt; - SINT32 evol; // !! - UINT puchicount; -} _PSGGEN, *PSGGEN; - -typedef struct { - SINT32 volume[16]; - SINT32 voltbl[16]; - UINT rate; - UINT32 base; - UINT16 puchidec; -} PSGGENCFG; - - -#ifdef __cplusplus -extern "C" { -#endif - -void psggen_initialize(UINT rate); -void psggen_setvol(UINT vol); - -void psggen_reset(PSGGEN psg); -void psggen_restore(PSGGEN psg); -void psggen_setreg(PSGGEN psg, UINT reg, REG8 val); -REG8 psggen_getreg(PSGGEN psg, UINT reg); -void psggen_setpan(PSGGEN psg, UINT ch, REG8 pan); - -void SOUNDCALL psggen_getpcm(PSGGEN psg, SINT32 *pcm, UINT count); - -#ifdef __cplusplus -} -#endif +/** + * @file psggen.h + * @brief Interface of the PSG + */ + +#pragma once + +#include + +enum { + PSGFREQPADBIT = 12, + PSGADDEDBIT = 3 +}; + +enum { + PSGENV_INC = 15, + PSGENV_ONESHOT = 16, + PSGENV_LASTON = 32, + PSGENV_ONECYCLE = 64 +}; + +typedef struct { + SINT32 freq; + SINT32 count; + SINT32 *pvol; // !! + UINT16 puchi; + UINT8 pan; + UINT8 padding; +} PSGTONE; + +typedef struct { + UINT32 freq; /*!< frequency */ + UINT32 count; /*!< counter */ + UINT lfsr; /*!< linear feedback shift register */ +} PSGNOISE; + +typedef struct { + UINT8 tune[3][2]; // 0 + UINT8 noise; // 6 + UINT8 mixer; // 7 + UINT8 vol[3]; // 8 + UINT8 envtime[2]; // b + UINT8 env; // d + UINT8 io1; + UINT8 io2; +} PSGREG; + +typedef struct { + PSGTONE tone[3]; + PSGNOISE noise; + PSGREG reg; + UINT16 envcnt; + UINT16 envmax; + UINT8 mixer; + UINT8 envmode; + UINT8 envvol; + SINT8 envvolcnt; + SINT32 evol; // !! + UINT puchicount; +} _PSGGEN, *PSGGEN; + +typedef struct { + SINT32 volume[16]; + SINT32 voltbl[16]; + UINT rate; + UINT32 base; + UINT16 puchidec; +} PSGGENCFG; + + +#ifdef __cplusplus +extern "C" { +#endif + +void psggen_initialize(UINT rate); +void psggen_setvol(UINT vol); + +void psggen_reset(PSGGEN psg); +void psggen_restore(PSGGEN psg); +void psggen_setreg(PSGGEN psg, UINT reg, REG8 val); +REG8 psggen_getreg(PSGGEN psg, UINT reg); +void psggen_setpan(PSGGEN psg, UINT ch, REG8 pan); + +void SOUNDCALL psggen_getpcm(PSGGEN psg, SINT32 *pcm, UINT count); + +#ifdef __cplusplus +} +#endif diff --git a/sound/psggenc.c b/sound/psggenc.c old mode 100755 new mode 100644 index 18deadc4..c7ce405c --- a/sound/psggenc.c +++ b/sound/psggenc.c @@ -1,174 +1,174 @@ -/** - * @file psggenc.c - * @brief Implementation of the PSG - */ - -#include -#include -#include "psggen.h" - - PSGGENCFG psggencfg; - -static const UINT8 psggen_deftbl[0x10] = - {0, 0, 0, 0, 0, 0, 0, 0xbf, 0, 0, 0, 0, 0, 0, 0xff, 0xff}; - -static const UINT8 psgenv_pat[16] = { - PSGENV_ONESHOT, - PSGENV_ONESHOT, - PSGENV_ONESHOT, - PSGENV_ONESHOT, - PSGENV_ONESHOT | PSGENV_INC, - PSGENV_ONESHOT | PSGENV_INC, - PSGENV_ONESHOT | PSGENV_INC, - PSGENV_ONESHOT | PSGENV_INC, - PSGENV_ONECYCLE, - PSGENV_ONESHOT, - 0, - PSGENV_ONESHOT | PSGENV_LASTON, - PSGENV_ONECYCLE | PSGENV_INC, - PSGENV_ONESHOT | PSGENV_INC | PSGENV_LASTON, - PSGENV_INC, - PSGENV_ONESHOT | PSGENV_INC}; - - -void psggen_initialize(UINT rate) { - - double pom; - UINT i; - - memset(&psggencfg, 0, sizeof(psggencfg)); - psggencfg.rate = rate; - pom = (double)0x0c00; - for (i=15; i; i--) { - psggencfg.voltbl[i] = (SINT32)pom; - pom /= 1.41492; - } - psggencfg.puchidec = (UINT16)(rate / 11025) * 2; - if (psggencfg.puchidec == 0) { - psggencfg.puchidec = 1; - } - if (rate) { - psggencfg.base = (5000 * (1 << (32 - PSGFREQPADBIT - PSGADDEDBIT))) - / (rate / 25); - } -} - -void psggen_setvol(UINT vol) { - - UINT i; - - for (i=1; i<16; i++) { - psggencfg.volume[i] = (psggencfg.voltbl[i] * vol) >> - (6 + PSGADDEDBIT); - } -} - -void psggen_reset(PSGGEN psg) { - - UINT i; - - memset(psg, 0, sizeof(*psg)); - for (i=0; i<3; i++) { - psg->tone[i].pvol = psggencfg.volume + 0; - } - psg->noise.lfsr = 1; - for (i=0; ireg)[i]); - } -} - -void psggen_setreg(PSGGEN psg, UINT reg, REG8 value) { - - UINT ch; - UINT freq; - - reg = reg & 15; - if (reg < 14) { - sound_sync(); - } - ((UINT8 *)&psg->reg)[reg] = value; - switch(reg) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - ch = reg >> 1; - freq = LOADINTELWORD(psg->reg.tune[ch]) & 0xfff; - if (freq > 9) { - psg->tone[ch].freq = (psggencfg.base / freq) << PSGFREQPADBIT; - } - else { - psg->tone[ch].freq = 0; - } - break; - - case 6: - freq = value & 0x1f; - if (freq == 0) { - freq = 1; - } - psg->noise.freq = (psggencfg.base / freq) << PSGFREQPADBIT; - break; - - case 7: - psg->mixer = ~value; - psg->puchicount = psggencfg.puchidec; -// TRACEOUT(("psg %x 7 %d", (long)psg, value)); - break; - - case 8: - case 9: - case 10: - ch = reg - 8; - if (value & 0x10) { - psg->tone[ch].pvol = &psg->evol; - } - else { - psg->tone[ch].pvol = psggencfg.volume + (value & 15); - } - psg->tone[ch].puchi = psggencfg.puchidec; - psg->puchicount = psggencfg.puchidec; -// TRACEOUT(("psg %x %x %d", (long)psg, reg, value)); - break; - - case 11: - case 12: - freq = LOADINTELWORD(psg->reg.envtime); - freq = psggencfg.rate * freq / 125000; - if (freq == 0) { - freq = 1; - } - psg->envmax = freq; - break; - - case 13: - psg->envmode = psgenv_pat[value & 0x0f]; - psg->envvolcnt = 16; - psg->envcnt = 1; - break; - } -} - -REG8 psggen_getreg(PSGGEN psg, UINT reg) { - - return(((UINT8 *)&psg->reg)[reg & 15]); -} - -void psggen_setpan(PSGGEN psg, UINT ch, REG8 pan) { - - if ((psg) && (ch < 3)) { - psg->tone[ch].pan = pan; - } -} - +/** + * @file psggenc.c + * @brief Implementation of the PSG + */ + +#include +#include +#include "psggen.h" + + PSGGENCFG psggencfg; + +static const UINT8 psggen_deftbl[0x10] = + {0, 0, 0, 0, 0, 0, 0, 0xbf, 0, 0, 0, 0, 0, 0, 0xff, 0xff}; + +static const UINT8 psgenv_pat[16] = { + PSGENV_ONESHOT, + PSGENV_ONESHOT, + PSGENV_ONESHOT, + PSGENV_ONESHOT, + PSGENV_ONESHOT | PSGENV_INC, + PSGENV_ONESHOT | PSGENV_INC, + PSGENV_ONESHOT | PSGENV_INC, + PSGENV_ONESHOT | PSGENV_INC, + PSGENV_ONECYCLE, + PSGENV_ONESHOT, + 0, + PSGENV_ONESHOT | PSGENV_LASTON, + PSGENV_ONECYCLE | PSGENV_INC, + PSGENV_ONESHOT | PSGENV_INC | PSGENV_LASTON, + PSGENV_INC, + PSGENV_ONESHOT | PSGENV_INC}; + + +void psggen_initialize(UINT rate) { + + double pom; + UINT i; + + memset(&psggencfg, 0, sizeof(psggencfg)); + psggencfg.rate = rate; + pom = (double)0x0c00; + for (i=15; i; i--) { + psggencfg.voltbl[i] = (SINT32)pom; + pom /= 1.41492; + } + psggencfg.puchidec = (UINT16)(rate / 11025) * 2; + if (psggencfg.puchidec == 0) { + psggencfg.puchidec = 1; + } + if (rate) { + psggencfg.base = (5000 * (1 << (32 - PSGFREQPADBIT - PSGADDEDBIT))) + / (rate / 25); + } +} + +void psggen_setvol(UINT vol) { + + UINT i; + + for (i=1; i<16; i++) { + psggencfg.volume[i] = (psggencfg.voltbl[i] * vol) >> + (6 + PSGADDEDBIT); + } +} + +void psggen_reset(PSGGEN psg) { + + UINT i; + + memset(psg, 0, sizeof(*psg)); + for (i=0; i<3; i++) { + psg->tone[i].pvol = psggencfg.volume + 0; + } + psg->noise.lfsr = 1; + for (i=0; ireg)[i]); + } +} + +void psggen_setreg(PSGGEN psg, UINT reg, REG8 value) { + + UINT ch; + UINT freq; + + reg = reg & 15; + if (reg < 14) { + sound_sync(); + } + ((UINT8 *)&psg->reg)[reg] = value; + switch(reg) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + ch = reg >> 1; + freq = LOADINTELWORD(psg->reg.tune[ch]) & 0xfff; + if (freq > 9) { + psg->tone[ch].freq = (psggencfg.base / freq) << PSGFREQPADBIT; + } + else { + psg->tone[ch].freq = 0; + } + break; + + case 6: + freq = value & 0x1f; + if (freq == 0) { + freq = 1; + } + psg->noise.freq = (psggencfg.base / freq) << PSGFREQPADBIT; + break; + + case 7: + psg->mixer = ~value; + psg->puchicount = psggencfg.puchidec; +// TRACEOUT(("psg %x 7 %d", (long)psg, value)); + break; + + case 8: + case 9: + case 10: + ch = reg - 8; + if (value & 0x10) { + psg->tone[ch].pvol = &psg->evol; + } + else { + psg->tone[ch].pvol = psggencfg.volume + (value & 15); + } + psg->tone[ch].puchi = psggencfg.puchidec; + psg->puchicount = psggencfg.puchidec; +// TRACEOUT(("psg %x %x %d", (long)psg, reg, value)); + break; + + case 11: + case 12: + freq = LOADINTELWORD(psg->reg.envtime); + freq = psggencfg.rate * freq / 125000; + if (freq == 0) { + freq = 1; + } + psg->envmax = freq; + break; + + case 13: + psg->envmode = psgenv_pat[value & 0x0f]; + psg->envvolcnt = 16; + psg->envcnt = 1; + break; + } +} + +REG8 psggen_getreg(PSGGEN psg, UINT reg) { + + return(((UINT8 *)&psg->reg)[reg & 15]); +} + +void psggen_setpan(PSGGEN psg, UINT ch, REG8 pan) { + + if ((psg) && (ch < 3)) { + psg->tone[ch].pan = pan; + } +} + diff --git a/sound/psggeng.c b/sound/psggeng.c old mode 100755 new mode 100644 index 99281a16..9866cced --- a/sound/psggeng.c +++ b/sound/psggeng.c @@ -1,124 +1,124 @@ -/** - * @file psggeng.c - * @brief Implementation of the PSG - */ - -#include -#include "psggen.h" -#include - -extern PSGGENCFG psggencfg; - - -void SOUNDCALL psggen_getpcm(PSGGEN psg, SINT32 *pcm, UINT count) { - - SINT32 noisevol; - UINT8 mixer; - UINT noisetbl; - PSGTONE *tone; - PSGTONE *toneterm; - SINT32 samp; - SINT32 vol; - UINT i; - UINT noise; - - if ((psg->mixer & 0x3f) == 0) { - count = MIN(count, psg->puchicount); - psg->puchicount -= count; - } - if (count == 0) { - return; - } - do { - noisevol = 0; - if (psg->envcnt) { - psg->envcnt--; - if (psg->envcnt == 0) { - psg->envvolcnt--; - if (psg->envvolcnt < 0) { - if (psg->envmode & PSGENV_ONESHOT) { - psg->envvol = (psg->envmode & PSGENV_LASTON)?15:0; - } - else { - psg->envvolcnt = 15; - if (!(psg->envmode & PSGENV_ONECYCLE)) { - psg->envmode ^= PSGENV_INC; - } - psg->envcnt = psg->envmax; - psg->envvol = (psg->envvolcnt ^ psg->envmode) & 0x0f; - } - } - else { - psg->envcnt = psg->envmax; - psg->envvol = (psg->envvolcnt ^ psg->envmode) & 0x0f; - } - psg->evol = psggencfg.volume[psg->envvol]; - } - } - mixer = psg->mixer; - noisetbl = 0; - if (mixer & 0x38) { - for (i=0; i<(1 << PSGADDEDBIT); i++) { - if (psg->noise.count > psg->noise.freq) { - psg->noise.lfsr = (psg->noise.lfsr >> 1) ^ ((psg->noise.lfsr & 1) * 0x12000); - } - psg->noise.count -= psg->noise.freq; - noisetbl |= (psg->noise.lfsr & 1) << i; - } - } - tone = psg->tone; - toneterm = tone + 3; - do { - vol = *(tone->pvol); - if (vol) { - samp = 0; - switch(mixer & 9) { - case 0: // no mix - if (tone->puchi) { - tone->puchi--; - samp += vol << PSGADDEDBIT; - } - break; - - case 1: // tone only - for (i=0; i<(1 << PSGADDEDBIT); i++) { - tone->count += tone->freq; - samp += vol * ((tone->count>=0)?1:-1); - } - break; - - case 8: // noise only - noise = noisetbl; - for (i=0; i<(1 << PSGADDEDBIT); i++) { - samp += vol * ((noise & 1)?1:-1); - noise >>= 1; - } - break; - - case 9: - noise = noisetbl; - for (i=0; i<(1 << PSGADDEDBIT); i++) { - tone->count += tone->freq; - if ((tone->count >= 0) || (noise & 1)) { - samp += vol; - } - else { - samp -= vol; - } - noise >>= 1; - } - break; - } - if (!(tone->pan & 1)) { - pcm[0] += samp; - } - if (!(tone->pan & 2)) { - pcm[1] += samp; - } - } - mixer >>= 1; - } while(++tone < toneterm); - pcm += 2; - } while(--count); -} - +/** + * @file psggeng.c + * @brief Implementation of the PSG + */ + +#include +#include "psggen.h" +#include + +extern PSGGENCFG psggencfg; + + +void SOUNDCALL psggen_getpcm(PSGGEN psg, SINT32 *pcm, UINT count) { + + SINT32 noisevol; + UINT8 mixer; + UINT noisetbl; + PSGTONE *tone; + PSGTONE *toneterm; + SINT32 samp; + SINT32 vol; + UINT i; + UINT noise; + + if ((psg->mixer & 0x3f) == 0) { + count = MIN(count, psg->puchicount); + psg->puchicount -= count; + } + if (count == 0) { + return; + } + do { + noisevol = 0; + if (psg->envcnt) { + psg->envcnt--; + if (psg->envcnt == 0) { + psg->envvolcnt--; + if (psg->envvolcnt < 0) { + if (psg->envmode & PSGENV_ONESHOT) { + psg->envvol = (psg->envmode & PSGENV_LASTON)?15:0; + } + else { + psg->envvolcnt = 15; + if (!(psg->envmode & PSGENV_ONECYCLE)) { + psg->envmode ^= PSGENV_INC; + } + psg->envcnt = psg->envmax; + psg->envvol = (psg->envvolcnt ^ psg->envmode) & 0x0f; + } + } + else { + psg->envcnt = psg->envmax; + psg->envvol = (psg->envvolcnt ^ psg->envmode) & 0x0f; + } + psg->evol = psggencfg.volume[psg->envvol]; + } + } + mixer = psg->mixer; + noisetbl = 0; + if (mixer & 0x38) { + for (i=0; i<(1 << PSGADDEDBIT); i++) { + if (psg->noise.count > psg->noise.freq) { + psg->noise.lfsr = (psg->noise.lfsr >> 1) ^ ((psg->noise.lfsr & 1) * 0x12000); + } + psg->noise.count -= psg->noise.freq; + noisetbl |= (psg->noise.lfsr & 1) << i; + } + } + tone = psg->tone; + toneterm = tone + 3; + do { + vol = *(tone->pvol); + if (vol) { + samp = 0; + switch(mixer & 9) { + case 0: // no mix + if (tone->puchi) { + tone->puchi--; + samp += vol << PSGADDEDBIT; + } + break; + + case 1: // tone only + for (i=0; i<(1 << PSGADDEDBIT); i++) { + tone->count += tone->freq; + samp += vol * ((tone->count>=0)?1:-1); + } + break; + + case 8: // noise only + noise = noisetbl; + for (i=0; i<(1 << PSGADDEDBIT); i++) { + samp += vol * ((noise & 1)?1:-1); + noise >>= 1; + } + break; + + case 9: + noise = noisetbl; + for (i=0; i<(1 << PSGADDEDBIT); i++) { + tone->count += tone->freq; + if ((tone->count >= 0) || (noise & 1)) { + samp += vol; + } + else { + samp -= vol; + } + noise >>= 1; + } + break; + } + if (!(tone->pan & 1)) { + pcm[0] += samp; + } + if (!(tone->pan & 2)) { + pcm[1] += samp; + } + } + mixer >>= 1; + } while(++tone < toneterm); + pcm += 2; + } while(--count); +} + diff --git a/sound/rhythm.h b/sound/rhythm.h old mode 100755 new mode 100644 index 3d2ab8b9..96481e3b --- a/sound/rhythm.h +++ b/sound/rhythm.h @@ -1,34 +1,34 @@ -/** - * @file rhythm.h - * @brief Interface of the OPNA rhythm - */ - -#pragma once - -#include - -typedef struct { - PMIXHDR hdr; - PMIXTRK trk[6]; - UINT vol; - UINT8 trkvol[8]; -} _RHYTHM, *RHYTHM; - - -#ifdef __cplusplus -extern "C" { -#endif - -void rhythm_initialize(UINT rate); -void rhythm_deinitialize(void); -UINT rhythm_getcaps(void); -void rhythm_setvol(UINT vol); - -void rhythm_reset(RHYTHM rhy); -void rhythm_bind(RHYTHM rhy); -void rhythm_update(RHYTHM rhy); -void rhythm_setreg(RHYTHM rhy, UINT reg, REG8 val); - -#ifdef __cplusplus -} -#endif +/** + * @file rhythm.h + * @brief Interface of the OPNA rhythm + */ + +#pragma once + +#include + +typedef struct { + PMIXHDR hdr; + PMIXTRK trk[6]; + UINT vol; + UINT8 trkvol[8]; +} _RHYTHM, *RHYTHM; + + +#ifdef __cplusplus +extern "C" { +#endif + +void rhythm_initialize(UINT rate); +void rhythm_deinitialize(void); +UINT rhythm_getcaps(void); +void rhythm_setvol(UINT vol); + +void rhythm_reset(RHYTHM rhy); +void rhythm_bind(RHYTHM rhy); +void rhythm_update(RHYTHM rhy); +void rhythm_setreg(RHYTHM rhy, UINT reg, REG8 val); + +#ifdef __cplusplus +} +#endif diff --git a/sound/rhythmc.c b/sound/rhythmc.c old mode 100755 new mode 100644 index a590cf41..6030ae11 --- a/sound/rhythmc.c +++ b/sound/rhythmc.c @@ -1,159 +1,159 @@ -/** - * @file rhythmc.c - * @brief Implementation of the OPNA rhythm - */ - -#include -#include -#include "rhythm.h" -#include - -static const OEMCHAR file_2608bd[] = OEMTEXT("2608_bd.wav"); -static const OEMCHAR file_2608sd[] = OEMTEXT("2608_sd.wav"); -static const OEMCHAR file_2608top[] = OEMTEXT("2608_top.wav"); -static const OEMCHAR file_2608hh[] = OEMTEXT("2608_hh.wav"); -static const OEMCHAR file_2608tom[] = OEMTEXT("2608_tom.wav"); -static const OEMCHAR file_2608rim[] = OEMTEXT("2608_rim.wav"); - -static const OEMCHAR *rhythmfile[6] = { - file_2608bd, file_2608sd, file_2608top, - file_2608hh, file_2608tom, file_2608rim}; - -typedef struct { - UINT rate; - UINT pcmexist; - PMIXDAT pcm[6]; - UINT vol; - UINT voltbl[96]; -} RHYTHMCFG; - -static RHYTHMCFG rhythmcfg; - - -void rhythm_initialize(UINT rate) { - - UINT i; - - ZeroMemory(&rhythmcfg, sizeof(rhythmcfg)); - rhythmcfg.rate = rate; - - for (i=0; i<96; i++) { - rhythmcfg.voltbl[i] = (UINT)(32768.0 * - pow(2.0, (double)i * (-3.0) / 40.0)); - } -} - -void rhythm_deinitialize(void) { - - UINT i; - SINT16 *ptr; - - for (i=0; i<6; i++) { - ptr = rhythmcfg.pcm[i].sample; - rhythmcfg.pcm[i].sample = NULL; - if (ptr) { - _MFREE(ptr); - } - } -} - -static void rhythm_load(void) { - - int i; - OEMCHAR path[MAX_PATH]; - - for (i=0; i<6; i++) { - if (rhythmcfg.pcm[i].sample == NULL) { - getbiospath(path, rhythmfile[i], NELEMENTS(path)); - pcmmix_regfile(rhythmcfg.pcm + i, path, rhythmcfg.rate); - } - } -} - -UINT rhythm_getcaps(void) { - - UINT ret; - UINT i; - - ret = 0; - for (i=0; i<6; i++) { - if (rhythmcfg.pcm[i].sample) { - ret |= 1 << i; - } - } - return(ret); -} - -void rhythm_setvol(UINT vol) { - - rhythmcfg.vol = vol; -} - -void rhythm_reset(RHYTHM rhy) -{ - memset(rhy, 0, sizeof(*rhy)); -} - -void rhythm_bind(RHYTHM rhy) { - - UINT i; - - rhythm_load(); - rhy->hdr.enable = 0x3f; - for (i=0; i<6; i++) { - rhy->trk[i].data = rhythmcfg.pcm[i]; - } - rhythm_update(rhy); - sound_streamregist(rhy, (SOUNDCB)pcmmix_getpcm); -} - -void rhythm_update(RHYTHM rhy) { - - UINT i; - - for (i=0; i<6; i++) { - rhy->trk[i].volume = (rhythmcfg.voltbl[rhy->vol + rhy->trkvol[i]] * - rhythmcfg.vol) >> 10; - } -} - -void rhythm_setreg(RHYTHM rhy, UINT reg, REG8 value) { - - PMIXTRK *trk; - REG8 bit; - - if (reg == 0x10) { - sound_sync(); - trk = rhy->trk; - bit = 0x01; - do { - if (value & bit) { - if (value & 0x80) { - rhy->hdr.playing &= ~((UINT)bit); - } - else if (trk->data.sample) { - trk->pcm = trk->data.sample; - trk->remain = trk->data.samples; - rhy->hdr.playing |= bit; - } - } - trk++; - bit <<= 1; - } while(bit < 0x40); - } - else if (reg == 0x11) { - sound_sync(); - rhy->vol = (~value) & 0x3f; - rhythm_update(rhy); - } - else if ((reg >= 0x18) && (reg < 0x1e)) { - sound_sync(); - trk = rhy->trk + (reg - 0x18); - trk->flag = ((value & 0x80) >> 7) + ((value & 0x40) >> 5); - value = (~value) & 0x1f; - rhy->trkvol[reg - 0x18] = (UINT8)value; - trk->volume = (rhythmcfg.voltbl[rhy->vol + value] * - rhythmcfg.vol) >> 10; - } -} - +/** + * @file rhythmc.c + * @brief Implementation of the OPNA rhythm + */ + +#include +#include +#include "rhythm.h" +#include + +static const OEMCHAR file_2608bd[] = OEMTEXT("2608_bd.wav"); +static const OEMCHAR file_2608sd[] = OEMTEXT("2608_sd.wav"); +static const OEMCHAR file_2608top[] = OEMTEXT("2608_top.wav"); +static const OEMCHAR file_2608hh[] = OEMTEXT("2608_hh.wav"); +static const OEMCHAR file_2608tom[] = OEMTEXT("2608_tom.wav"); +static const OEMCHAR file_2608rim[] = OEMTEXT("2608_rim.wav"); + +static const OEMCHAR *rhythmfile[6] = { + file_2608bd, file_2608sd, file_2608top, + file_2608hh, file_2608tom, file_2608rim}; + +typedef struct { + UINT rate; + UINT pcmexist; + PMIXDAT pcm[6]; + UINT vol; + UINT voltbl[96]; +} RHYTHMCFG; + +static RHYTHMCFG rhythmcfg; + + +void rhythm_initialize(UINT rate) { + + UINT i; + + ZeroMemory(&rhythmcfg, sizeof(rhythmcfg)); + rhythmcfg.rate = rate; + + for (i=0; i<96; i++) { + rhythmcfg.voltbl[i] = (UINT)(32768.0 * + pow(2.0, (double)i * (-3.0) / 40.0)); + } +} + +void rhythm_deinitialize(void) { + + UINT i; + SINT16 *ptr; + + for (i=0; i<6; i++) { + ptr = rhythmcfg.pcm[i].sample; + rhythmcfg.pcm[i].sample = NULL; + if (ptr) { + _MFREE(ptr); + } + } +} + +static void rhythm_load(void) { + + int i; + OEMCHAR path[MAX_PATH]; + + for (i=0; i<6; i++) { + if (rhythmcfg.pcm[i].sample == NULL) { + getbiospath(path, rhythmfile[i], NELEMENTS(path)); + pcmmix_regfile(rhythmcfg.pcm + i, path, rhythmcfg.rate); + } + } +} + +UINT rhythm_getcaps(void) { + + UINT ret; + UINT i; + + ret = 0; + for (i=0; i<6; i++) { + if (rhythmcfg.pcm[i].sample) { + ret |= 1 << i; + } + } + return(ret); +} + +void rhythm_setvol(UINT vol) { + + rhythmcfg.vol = vol; +} + +void rhythm_reset(RHYTHM rhy) +{ + memset(rhy, 0, sizeof(*rhy)); +} + +void rhythm_bind(RHYTHM rhy) { + + UINT i; + + rhythm_load(); + rhy->hdr.enable = 0x3f; + for (i=0; i<6; i++) { + rhy->trk[i].data = rhythmcfg.pcm[i]; + } + rhythm_update(rhy); + sound_streamregist(rhy, (SOUNDCB)pcmmix_getpcm); +} + +void rhythm_update(RHYTHM rhy) { + + UINT i; + + for (i=0; i<6; i++) { + rhy->trk[i].volume = (rhythmcfg.voltbl[rhy->vol + rhy->trkvol[i]] * + rhythmcfg.vol) >> 10; + } +} + +void rhythm_setreg(RHYTHM rhy, UINT reg, REG8 value) { + + PMIXTRK *trk; + REG8 bit; + + if (reg == 0x10) { + sound_sync(); + trk = rhy->trk; + bit = 0x01; + do { + if (value & bit) { + if (value & 0x80) { + rhy->hdr.playing &= ~((UINT)bit); + } + else if (trk->data.sample) { + trk->pcm = trk->data.sample; + trk->remain = trk->data.samples; + rhy->hdr.playing |= bit; + } + } + trk++; + bit <<= 1; + } while(bit < 0x40); + } + else if (reg == 0x11) { + sound_sync(); + rhy->vol = (~value) & 0x3f; + rhythm_update(rhy); + } + else if ((reg >= 0x18) && (reg < 0x1e)) { + sound_sync(); + trk = rhy->trk + (reg - 0x18); + trk->flag = ((value & 0x80) >> 7) + ((value & 0x40) >> 5); + value = (~value) & 0x1f; + rhy->trkvol[reg - 0x18] = (UINT8)value; + trk->volume = (rhythmcfg.voltbl[rhy->vol + value] * + rhythmcfg.vol) >> 10; + } +} + diff --git a/sound/sndcsec.c b/sound/sndcsec.c old mode 100755 new mode 100644 index b268148e..3a7082e9 --- a/sound/sndcsec.c +++ b/sound/sndcsec.c @@ -1,13 +1,13 @@ -/** - * @file sndcsec.c - * @brief Implementation of the critical section for sound - */ - -#include -#include "sndcsec.h" - -#if defined(SOUND_CRITICAL) && defined(SUPPORT_NP2_THREAD) - - NP2_Semaphore_t semSoundCritical; - -#endif /* defined(SOUND_CRITICAL) defined(SUPPORT_NP2_THREAD) */ +/** + * @file sndcsec.c + * @brief Implementation of the critical section for sound + */ + +#include +#include "sndcsec.h" + +#if defined(SOUND_CRITICAL) && defined(SUPPORT_NP2_THREAD) + + NP2_Semaphore_t semSoundCritical; + +#endif /* defined(SOUND_CRITICAL) defined(SUPPORT_NP2_THREAD) */ diff --git a/sound/sndcsec.h b/sound/sndcsec.h old mode 100755 new mode 100644 index 93274728..aa033f0c --- a/sound/sndcsec.h +++ b/sound/sndcsec.h @@ -1,35 +1,35 @@ -/** - * @file sndcsec.h - * @brief Interface of the critical section for sound - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -#if defined(SOUND_CRITICAL) && defined(SUPPORT_NP2_THREAD) - -extern NP2_Semaphore_t semSoundCritical; - -#define SNDCSEC_INIT NP2_Semaphore_Create(&semSoundCritical, 1) -#define SNDCSEC_TERM NP2_Semaphore_Destroy(&semSoundCritical) -#define SNDCSEC_ENTER NP2_Semaphore_Wait(&semSoundCritical) -#define SNDCSEC_LEAVE NP2_Semaphore_Release(&semSoundCritical) - -#else - -#define SNDCSEC_INIT -#define SNDCSEC_TERM -#define SNDCSEC_ENTER -#define SNDCSEC_LEAVE - -#endif /* defined(SOUND_CRITICAL) defined(SUPPORT_NP2_THREAD) */ - -#ifdef __cplusplus -} -#endif +/** + * @file sndcsec.h + * @brief Interface of the critical section for sound + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if defined(SOUND_CRITICAL) && defined(SUPPORT_NP2_THREAD) + +extern NP2_Semaphore_t semSoundCritical; + +#define SNDCSEC_INIT NP2_Semaphore_Create(&semSoundCritical, 1) +#define SNDCSEC_TERM NP2_Semaphore_Destroy(&semSoundCritical) +#define SNDCSEC_ENTER NP2_Semaphore_Wait(&semSoundCritical) +#define SNDCSEC_LEAVE NP2_Semaphore_Release(&semSoundCritical) + +#else + +#define SNDCSEC_INIT +#define SNDCSEC_TERM +#define SNDCSEC_ENTER +#define SNDCSEC_LEAVE + +#endif /* defined(SOUND_CRITICAL) defined(SUPPORT_NP2_THREAD) */ + +#ifdef __cplusplus +} +#endif diff --git a/sound/sound.c b/sound/sound.c old mode 100755 new mode 100644 index d8ce8f2e..219eb010 --- a/sound/sound.c +++ b/sound/sound.c @@ -1,439 +1,439 @@ -/** - * @file sound.c - * @brief Implementation of the sound - */ - -#include -#include -#include -#include -#include -#include "sndcsec.h" -#include -#include -#if defined(SUPPORT_WAVEREC) -#include -#endif /* defined(SUPPORT_WAVEREC) */ - - SOUNDCFG soundcfg; - - -#define STREAM_CBMAX 16 - -typedef struct { - void *hdl; - SOUNDCB cbfn; -} CBTBL; - -typedef struct { - SINT32 *buffer; - SINT32 *ptr; - UINT samples; - UINT reserve; - UINT remain; -#if defined(SUPPORT_WAVEREC) - WAVEFILEH rec; -#endif /* defined(SUPPORT_WAVEREC) */ - CBTBL *cbreg; - CBTBL cb[STREAM_CBMAX]; -} SNDSTREAM; - -static SNDSTREAM sndstream; - -static void streamreset(void) { - - SNDCSEC_ENTER; - sndstream.ptr = sndstream.buffer; - sndstream.remain = sndstream.samples + sndstream.reserve; - sndstream.cbreg = sndstream.cb; - SNDCSEC_LEAVE; -} - -static void streamprepare(UINT samples) { - - CBTBL *cb; - UINT count; - - count = MIN(sndstream.remain, samples); - if (count) { - ZeroMemory(sndstream.ptr, count * 2 * sizeof(SINT32)); - cb = sndstream.cb; - while(cb < sndstream.cbreg) { - cb->cbfn(cb->hdl, sndstream.ptr, count); - cb++; - } - sndstream.ptr += count * 2; - sndstream.remain -= count; - } -} - - -#if defined(SUPPORT_WAVEREC) -// ---- wave rec - -/** - * Starts recording - * @param[in] lpFilename The filename - * @retval SUCCESS If succeeded - * @retval FAILURE If failed - */ -BRESULT sound_recstart(const OEMCHAR *lpFilename) -{ - WAVEFILEH rec; - - sound_recstop(); - if (sndstream.buffer == NULL) - { - return FAILURE; - } - rec = wavefile_create(lpFilename, soundcfg.rate, 16, 2); - sndstream.rec = rec; - if (rec) - { - return SUCCESS; - } - return FAILURE; -} - -/** - * Stops recording - */ -void sound_recstop(void) -{ - WAVEFILEH rec; - - rec = sndstream.rec; - sndstream.rec = NULL; - wavefile_close(rec); -} - -/** - * is recording? - * @retval TRUE Yes - */ -BOOL sound_isrecording(void) -{ - return (sndstream.rec != NULL) ? TRUE : FALSE; -} - -/** - * write - * @param[in] samples The count of samples - */ -static void streamfilewrite(UINT nSamples) -{ - UINT nCount; - SINT32 buf32[2 * 512]; - CBTBL *cb; - UINT8 buf[2 * 512][2]; - UINT r; - UINT i; - SINT32 nSample; - - while (nSamples) - { - nCount = MIN(nSamples, 512); - memset(buf32, 0, nCount * 2 * sizeof(buf32[0])); - cb = sndstream.cb; - while (cb < sndstream.cbreg) - { - cb->cbfn(cb->hdl, buf32, nCount); - cb++; - } - r = MIN(sndstream.remain, nCount); - if (r) - { - memcpy(sndstream.ptr, buf32, r * 2 * sizeof(buf32[0])); - sndstream.ptr += r * 2; - sndstream.remain -= r; - } - for (i = 0; i < nCount * 2; i++) - { - nSample = buf32[i]; - if (nSample > 32767) - { - nSample = 32767; - } - else if (nSample < -32768) - { - nSample = -32768; - } - // little endianなので satuation_s16は使えない - buf[i][0] = (UINT8)nSample; - buf[i][1] = (UINT8)(nSample >> 8); - } - wavefile_write(sndstream.rec, buf, nCount * 2 * sizeof(buf[0])); - nSamples -= nCount; - } -} - -/** - * fill - * @param[in] samples The count of samples - */ -static void filltailsample(UINT nCount) -{ - SINT32 *ptr; - UINT nOrgSize; - SINT32 nSampleL; - SINT32 nSampleR; - - nCount = MIN(sndstream.remain, nCount); - if (nCount) - { - ptr = sndstream.ptr; - nOrgSize = (UINT)((ptr - sndstream.buffer) / 2); - if (nOrgSize == 0) - { - nSampleL = 0; - nSampleR = 0; - } - else - { - nSampleL = *(ptr - 2); - nSampleR = *(ptr - 1); - } - sndstream.ptr += nCount * 2; - sndstream.remain -= nCount; - do - { - ptr[0] = nSampleL; - ptr[1] = nSampleR; - ptr += 2; - } while (--nCount); - } -} -#endif /* defined(SUPPORT_WAVEREC) */ - - -// ---- - -BRESULT sound_create(UINT rate, UINT ms) { - - UINT samples; - UINT reserve; - - ZeroMemory(&sndstream, sizeof(sndstream)); - switch(rate) { - case 11025: - case 22050: - case 44100: - case 48000: - case 88200: - case 96000: - case 176400: - case 192000: - break; - - default: - return(FAILURE); - } - samples = soundmng_create(rate, ms); - if (samples == 0) { - goto scre_err1; - } - soundmng_reset(); - - soundcfg.rate = rate; - sound_changeclock(); - -#if defined(SOUNDRESERVE) - reserve = rate * SOUNDRESERVE / 1000; -#else - reserve = 0; -#endif - sndstream.buffer = (SINT32 *)_MALLOC((samples + reserve) * 2 - * sizeof(SINT32), "stream"); - if (sndstream.buffer == NULL) { - goto scre_err2; - } - sndstream.samples = samples; - sndstream.reserve = reserve; - - SNDCSEC_INIT; - streamreset(); - return(SUCCESS); - -scre_err2: - soundmng_destroy(); - -scre_err1: - return(FAILURE); -} - -void sound_destroy(void) { - - if (sndstream.buffer) { -#if defined(SUPPORT_WAVEREC) - sound_recstop(); -#endif /* defined(SUPPORT_WAVEREC) */ - soundmng_stop(); - streamreset(); - soundmng_destroy(); - SNDCSEC_TERM; - _MFREE(sndstream.buffer); - sndstream.buffer = NULL; - } -} - -void sound_reset(void) { - - if (sndstream.buffer) { - soundmng_reset(); - streamreset(); - soundcfg.lastclock = CPU_CLOCK; - beep_eventreset(); - } -} - -void sound_changeclock(void) { - - UINT32 clk; - UINT hz; - UINT hzmax; - - if (sndstream.buffer == NULL) { - return; - } - - // とりあえず 25で割り切れる。 - clk = pccore.realclock / 25; - hz = soundcfg.rate / 25; - - // で、クロック数に合せて調整。(64bit演算しろよな的) - hzmax = (1 << (32 - 8)) / (clk >> 8); - while(hzmax < hz) { - clk = (clk + 1) >> 1; - hz = (hz + 1) >> 1; - } - TRACEOUT(("hzbase/clockbase = %d/%d", hz, clk)); - soundcfg.hzbase = hz; - soundcfg.clockbase = clk; - soundcfg.minclock = 2 * clk / hz; - soundcfg.lastclock = CPU_CLOCK; -} - -void sound_streamregist(void *hdl, SOUNDCB cbfn) { - - if (sndstream.buffer) { - if ((cbfn) && - (sndstream.cbreg < (sndstream.cb + STREAM_CBMAX))) { - sndstream.cbreg->hdl = hdl; - sndstream.cbreg->cbfn = cbfn; - sndstream.cbreg++; - } - } -} - - -// ---- - -void sound_sync(void) -{ - - UINT32 length; - - if (sndstream.buffer == NULL) - { - return; - } - - length = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK - soundcfg.lastclock; - if (length < soundcfg.minclock) - { - return; - } - length = (length * soundcfg.hzbase) / soundcfg.clockbase; - if (length == 0) - { - return; - } -#ifdef SNDCSEC_TRYENTER - if (length < 1024) - { - if (!SNDCSEC_TRYENTER) - { - return; - } - } - else - { - SNDCSEC_ENTER; - } -#else - SNDCSEC_ENTER; -#endif -#if defined(SUPPORT_WAVEREC) - if (sndstream.rec) - { - streamfilewrite(length); - } - else -#endif /* defined(SUPPORT_WAVEREC) */ - streamprepare(length); - soundcfg.lastclock += length * soundcfg.clockbase / soundcfg.hzbase; - beep_eventreset(); - SNDCSEC_LEAVE; - - soundcfg.writecount += length; - if (soundcfg.writecount >= 100) - { - soundcfg.writecount = 0; - soundmng_sync(); - } -} - -static volatile int locks = 0; - -const SINT32 *sound_pcmlock(void) { - -const SINT32 *ret; - - if (locks) { - TRACEOUT(("sound pcm lock: already locked")); - return(NULL); - } - locks++; - ret = sndstream.buffer; - if (ret) { - SNDCSEC_ENTER; - if (sndstream.remain > sndstream.reserve) -#if defined(SUPPORT_WAVEREC) - if (sndstream.rec) { - filltailsample(sndstream.remain - sndstream.reserve); - } - else -#endif /* defined(SUPPORT_WAVEREC) */ - { - streamprepare(sndstream.remain - sndstream.reserve); - soundcfg.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; - beep_eventreset(); - } - } - else { - locks--; - } - return(ret); -} - -void sound_pcmunlock(const SINT32 *hdl) { - - int leng; - - if (hdl) { - leng = sndstream.reserve - sndstream.remain; - if (leng > 0) { - //CopyMemory(sndstream.buffer, - // sndstream.buffer + (sndstream.samples * 2), - // (sndstream.samples * 2)); - CopyMemory(sndstream.buffer, - sndstream.buffer + (sndstream.samples * 2), - leng * 2 * sizeof(SINT32)); - } - sndstream.ptr = sndstream.buffer + (leng * 2); -// sndstream.remain = sndstream.samples + sndstream.reserve - leng; - sndstream.remain += sndstream.samples; - SNDCSEC_LEAVE; - locks--; - } -} +/** + * @file sound.c + * @brief Implementation of the sound + */ + +#include +#include +#include +#include +#include +#include "sndcsec.h" +#include +#include +#if defined(SUPPORT_WAVEREC) +#include +#endif /* defined(SUPPORT_WAVEREC) */ + + SOUNDCFG soundcfg; + + +#define STREAM_CBMAX 16 + +typedef struct { + void *hdl; + SOUNDCB cbfn; +} CBTBL; + +typedef struct { + SINT32 *buffer; + SINT32 *ptr; + UINT samples; + UINT reserve; + UINT remain; +#if defined(SUPPORT_WAVEREC) + WAVEFILEH rec; +#endif /* defined(SUPPORT_WAVEREC) */ + CBTBL *cbreg; + CBTBL cb[STREAM_CBMAX]; +} SNDSTREAM; + +static SNDSTREAM sndstream; + +static void streamreset(void) { + + SNDCSEC_ENTER; + sndstream.ptr = sndstream.buffer; + sndstream.remain = sndstream.samples + sndstream.reserve; + sndstream.cbreg = sndstream.cb; + SNDCSEC_LEAVE; +} + +static void streamprepare(UINT samples) { + + CBTBL *cb; + UINT count; + + count = MIN(sndstream.remain, samples); + if (count) { + ZeroMemory(sndstream.ptr, count * 2 * sizeof(SINT32)); + cb = sndstream.cb; + while(cb < sndstream.cbreg) { + cb->cbfn(cb->hdl, sndstream.ptr, count); + cb++; + } + sndstream.ptr += count * 2; + sndstream.remain -= count; + } +} + + +#if defined(SUPPORT_WAVEREC) +// ---- wave rec + +/** + * Starts recording + * @param[in] lpFilename The filename + * @retval SUCCESS If succeeded + * @retval FAILURE If failed + */ +BRESULT sound_recstart(const OEMCHAR *lpFilename) +{ + WAVEFILEH rec; + + sound_recstop(); + if (sndstream.buffer == NULL) + { + return FAILURE; + } + rec = wavefile_create(lpFilename, soundcfg.rate, 16, 2); + sndstream.rec = rec; + if (rec) + { + return SUCCESS; + } + return FAILURE; +} + +/** + * Stops recording + */ +void sound_recstop(void) +{ + WAVEFILEH rec; + + rec = sndstream.rec; + sndstream.rec = NULL; + wavefile_close(rec); +} + +/** + * is recording? + * @retval TRUE Yes + */ +BOOL sound_isrecording(void) +{ + return (sndstream.rec != NULL) ? TRUE : FALSE; +} + +/** + * write + * @param[in] samples The count of samples + */ +static void streamfilewrite(UINT nSamples) +{ + UINT nCount; + SINT32 buf32[2 * 512]; + CBTBL *cb; + UINT8 buf[2 * 512][2]; + UINT r; + UINT i; + SINT32 nSample; + + while (nSamples) + { + nCount = MIN(nSamples, 512); + memset(buf32, 0, nCount * 2 * sizeof(buf32[0])); + cb = sndstream.cb; + while (cb < sndstream.cbreg) + { + cb->cbfn(cb->hdl, buf32, nCount); + cb++; + } + r = MIN(sndstream.remain, nCount); + if (r) + { + memcpy(sndstream.ptr, buf32, r * 2 * sizeof(buf32[0])); + sndstream.ptr += r * 2; + sndstream.remain -= r; + } + for (i = 0; i < nCount * 2; i++) + { + nSample = buf32[i]; + if (nSample > 32767) + { + nSample = 32767; + } + else if (nSample < -32768) + { + nSample = -32768; + } + // little endianなので satuation_s16は使えない + buf[i][0] = (UINT8)nSample; + buf[i][1] = (UINT8)(nSample >> 8); + } + wavefile_write(sndstream.rec, buf, nCount * 2 * sizeof(buf[0])); + nSamples -= nCount; + } +} + +/** + * fill + * @param[in] samples The count of samples + */ +static void filltailsample(UINT nCount) +{ + SINT32 *ptr; + UINT nOrgSize; + SINT32 nSampleL; + SINT32 nSampleR; + + nCount = MIN(sndstream.remain, nCount); + if (nCount) + { + ptr = sndstream.ptr; + nOrgSize = (UINT)((ptr - sndstream.buffer) / 2); + if (nOrgSize == 0) + { + nSampleL = 0; + nSampleR = 0; + } + else + { + nSampleL = *(ptr - 2); + nSampleR = *(ptr - 1); + } + sndstream.ptr += nCount * 2; + sndstream.remain -= nCount; + do + { + ptr[0] = nSampleL; + ptr[1] = nSampleR; + ptr += 2; + } while (--nCount); + } +} +#endif /* defined(SUPPORT_WAVEREC) */ + + +// ---- + +BRESULT sound_create(UINT rate, UINT ms) { + + UINT samples; + UINT reserve; + + ZeroMemory(&sndstream, sizeof(sndstream)); + switch(rate) { + case 11025: + case 22050: + case 44100: + case 48000: + case 88200: + case 96000: + case 176400: + case 192000: + break; + + default: + return(FAILURE); + } + samples = soundmng_create(rate, ms); + if (samples == 0) { + goto scre_err1; + } + soundmng_reset(); + + soundcfg.rate = rate; + sound_changeclock(); + +#if defined(SOUNDRESERVE) + reserve = rate * SOUNDRESERVE / 1000; +#else + reserve = 0; +#endif + sndstream.buffer = (SINT32 *)_MALLOC((samples + reserve) * 2 + * sizeof(SINT32), "stream"); + if (sndstream.buffer == NULL) { + goto scre_err2; + } + sndstream.samples = samples; + sndstream.reserve = reserve; + + SNDCSEC_INIT; + streamreset(); + return(SUCCESS); + +scre_err2: + soundmng_destroy(); + +scre_err1: + return(FAILURE); +} + +void sound_destroy(void) { + + if (sndstream.buffer) { +#if defined(SUPPORT_WAVEREC) + sound_recstop(); +#endif /* defined(SUPPORT_WAVEREC) */ + soundmng_stop(); + streamreset(); + soundmng_destroy(); + SNDCSEC_TERM; + _MFREE(sndstream.buffer); + sndstream.buffer = NULL; + } +} + +void sound_reset(void) { + + if (sndstream.buffer) { + soundmng_reset(); + streamreset(); + soundcfg.lastclock = CPU_CLOCK; + beep_eventreset(); + } +} + +void sound_changeclock(void) { + + UINT32 clk; + UINT hz; + UINT hzmax; + + if (sndstream.buffer == NULL) { + return; + } + + // とりあえず 25で割り切れる。 + clk = pccore.realclock / 25; + hz = soundcfg.rate / 25; + + // で、クロック数に合せて調整。(64bit演算しろよな的) + hzmax = (1 << (32 - 8)) / (clk >> 8); + while(hzmax < hz) { + clk = (clk + 1) >> 1; + hz = (hz + 1) >> 1; + } + TRACEOUT(("hzbase/clockbase = %d/%d", hz, clk)); + soundcfg.hzbase = hz; + soundcfg.clockbase = clk; + soundcfg.minclock = 2 * clk / hz; + soundcfg.lastclock = CPU_CLOCK; +} + +void sound_streamregist(void *hdl, SOUNDCB cbfn) { + + if (sndstream.buffer) { + if ((cbfn) && + (sndstream.cbreg < (sndstream.cb + STREAM_CBMAX))) { + sndstream.cbreg->hdl = hdl; + sndstream.cbreg->cbfn = cbfn; + sndstream.cbreg++; + } + } +} + + +// ---- + +void sound_sync(void) +{ + + UINT32 length; + + if (sndstream.buffer == NULL) + { + return; + } + + length = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK - soundcfg.lastclock; + if (length < soundcfg.minclock) + { + return; + } + length = (length * soundcfg.hzbase) / soundcfg.clockbase; + if (length == 0) + { + return; + } +#ifdef SNDCSEC_TRYENTER + if (length < 1024) + { + if (!SNDCSEC_TRYENTER) + { + return; + } + } + else + { + SNDCSEC_ENTER; + } +#else + SNDCSEC_ENTER; +#endif +#if defined(SUPPORT_WAVEREC) + if (sndstream.rec) + { + streamfilewrite(length); + } + else +#endif /* defined(SUPPORT_WAVEREC) */ + streamprepare(length); + soundcfg.lastclock += length * soundcfg.clockbase / soundcfg.hzbase; + beep_eventreset(); + SNDCSEC_LEAVE; + + soundcfg.writecount += length; + if (soundcfg.writecount >= 100) + { + soundcfg.writecount = 0; + soundmng_sync(); + } +} + +static volatile int locks = 0; + +const SINT32 *sound_pcmlock(void) { + +const SINT32 *ret; + + if (locks) { + TRACEOUT(("sound pcm lock: already locked")); + return(NULL); + } + locks++; + ret = sndstream.buffer; + if (ret) { + SNDCSEC_ENTER; + if (sndstream.remain > sndstream.reserve) +#if defined(SUPPORT_WAVEREC) + if (sndstream.rec) { + filltailsample(sndstream.remain - sndstream.reserve); + } + else +#endif /* defined(SUPPORT_WAVEREC) */ + { + streamprepare(sndstream.remain - sndstream.reserve); + soundcfg.lastclock = CPU_CLOCK + CPU_BASECLOCK - CPU_REMCLOCK; + beep_eventreset(); + } + } + else { + locks--; + } + return(ret); +} + +void sound_pcmunlock(const SINT32 *hdl) { + + int leng; + + if (hdl) { + leng = sndstream.reserve - sndstream.remain; + if (leng > 0) { + //CopyMemory(sndstream.buffer, + // sndstream.buffer + (sndstream.samples * 2), + // (sndstream.samples * 2)); + CopyMemory(sndstream.buffer, + sndstream.buffer + (sndstream.samples * 2), + leng * 2 * sizeof(SINT32)); + } + sndstream.ptr = sndstream.buffer + (leng * 2); +// sndstream.remain = sndstream.samples + sndstream.reserve - leng; + sndstream.remain += sndstream.samples; + SNDCSEC_LEAVE; + locks--; + } +} diff --git a/sound/sound.h b/sound/sound.h old mode 100755 new mode 100644 index 6cda71b6..bb33e7ed --- a/sound/sound.h +++ b/sound/sound.h @@ -1,63 +1,63 @@ -/** - * @file sound.h - * @brief Interface of the sound - */ - -#pragma once - -#ifndef SOUNDCALL -#define SOUNDCALL -#endif - -#if !defined(DISABLE_SOUND) - -typedef void (SOUNDCALL * SOUNDCB)(void *hdl, SINT32 *pcm, UINT count); - -typedef struct { - UINT rate; - UINT32 hzbase; - UINT32 clockbase; - UINT32 minclock; - UINT32 lastclock; - UINT writecount; -} SOUNDCFG; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern SOUNDCFG soundcfg; - -BRESULT sound_create(UINT rate, UINT ms); -void sound_destroy(void); - -void sound_reset(void); -void sound_changeclock(void); -void sound_streamregist(void *hdl, SOUNDCB cbfn); - -void sound_sync(void); - -const SINT32 *sound_pcmlock(void); -void sound_pcmunlock(const SINT32 *hdl); - -#if defined(SUPPORT_WAVEREC) -BRESULT sound_recstart(const OEMCHAR *filename); -void sound_recstop(void); -BOOL sound_isrecording(void); -#endif - -#ifdef __cplusplus -} -#endif - -#else - -#define sound_pcmlock() (NULL) -#define sound_pcmunlock(h) -#define sound_reset() -#define sound_changeclock() -#define sound_sync() - -#endif - +/** + * @file sound.h + * @brief Interface of the sound + */ + +#pragma once + +#ifndef SOUNDCALL +#define SOUNDCALL +#endif + +#if !defined(DISABLE_SOUND) + +typedef void (SOUNDCALL * SOUNDCB)(void *hdl, SINT32 *pcm, UINT count); + +typedef struct { + UINT rate; + UINT32 hzbase; + UINT32 clockbase; + UINT32 minclock; + UINT32 lastclock; + UINT writecount; +} SOUNDCFG; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern SOUNDCFG soundcfg; + +BRESULT sound_create(UINT rate, UINT ms); +void sound_destroy(void); + +void sound_reset(void); +void sound_changeclock(void); +void sound_streamregist(void *hdl, SOUNDCB cbfn); + +void sound_sync(void); + +const SINT32 *sound_pcmlock(void); +void sound_pcmunlock(const SINT32 *hdl); + +#if defined(SUPPORT_WAVEREC) +BRESULT sound_recstart(const OEMCHAR *filename); +void sound_recstop(void); +BOOL sound_isrecording(void); +#endif + +#ifdef __cplusplus +} +#endif + +#else + +#define sound_pcmlock() (NULL) +#define sound_pcmunlock(h) +#define sound_reset() +#define sound_changeclock() +#define sound_sync() + +#endif + diff --git a/sound/tms3631.h b/sound/tms3631.h old mode 100755 new mode 100644 index d20b347c..0cfa5c27 --- a/sound/tms3631.h +++ b/sound/tms3631.h @@ -1,52 +1,52 @@ -/** - * @file tms3631.h - * @brief Interface of the TMS3631 - */ - -#pragma once - -#include - -enum -{ - TMS3631_FREQ = 16, - TMS3631_MUL = 4 -}; - -typedef struct -{ - UINT32 freq; - UINT32 count; -} TMSCH; - -typedef struct -{ - TMSCH ch[8]; - UINT enable; -} _TMS3631, *TMS3631; - -typedef struct -{ - SINT32 left; - SINT32 right; - SINT32 feet[16]; - UINT32 freqtbl[64]; -} TMS3631CFG; - -#ifdef __cplusplus -extern "C" -{ -#endif - -void tms3631_initialize(UINT rate); -void tms3631_setvol(const UINT8 *vol); - -void tms3631_reset(TMS3631 tms); -void tms3631_setkey(TMS3631 tms, REG8 ch, REG8 key); -void tms3631_setenable(TMS3631 tms, REG8 enable); - -void SOUNDCALL tms3631_getpcm(TMS3631 tms, SINT32 *pcm, UINT count); - -#ifdef __cplusplus -} -#endif +/** + * @file tms3631.h + * @brief Interface of the TMS3631 + */ + +#pragma once + +#include + +enum +{ + TMS3631_FREQ = 16, + TMS3631_MUL = 4 +}; + +typedef struct +{ + UINT32 freq; + UINT32 count; +} TMSCH; + +typedef struct +{ + TMSCH ch[8]; + UINT enable; +} _TMS3631, *TMS3631; + +typedef struct +{ + SINT32 left; + SINT32 right; + SINT32 feet[16]; + UINT32 freqtbl[64]; +} TMS3631CFG; + +#ifdef __cplusplus +extern "C" +{ +#endif + +void tms3631_initialize(UINT rate); +void tms3631_setvol(const UINT8 *vol); + +void tms3631_reset(TMS3631 tms); +void tms3631_setkey(TMS3631 tms, REG8 ch, REG8 key); +void tms3631_setenable(TMS3631 tms, REG8 enable); + +void SOUNDCALL tms3631_getpcm(TMS3631 tms, SINT32 *pcm, UINT count); + +#ifdef __cplusplus +} +#endif diff --git a/sound/tms3631c.c b/sound/tms3631c.c old mode 100755 new mode 100644 index 961b9201..22920139 --- a/sound/tms3631c.c +++ b/sound/tms3631c.c @@ -1,66 +1,66 @@ -/** - * @file tms3631c.c - * @brief Implementation of the TMS3631 - */ - -#include -#include -#include - - TMS3631CFG tms3631cfg; - -void tms3631_initialize(UINT rate) -{ - UINT i, j; - double f; - - ZeroMemory(&tms3631cfg, sizeof(tms3631cfg)); - - for (i = 0; i < 4; i++) - { - for (j = 0; j < 12; j++) - { - f = 440.0 * pow(2.0, (i - 3.0) + ((j - 9.0) / 12.0)); - f = f * TMS3631_MUL * (1 << (TMS3631_FREQ + 1)) / rate; - tms3631cfg.freqtbl[(i * 16) + j + 1] = (UINT32)floor(f + 0.5); - } - } -} - -void tms3631_setvol(const UINT8 *vol) -{ - UINT i; - UINT j; - SINT32 data; - - tms3631cfg.left = (vol[0] & 15) << 5; - tms3631cfg.right = (vol[1] & 15) << 5; - vol += 2; - for (i = 0; i < 16; i++) - { - data = 0; - for (j = 0; j < 4; j++) - { - data += (vol[j] & 15) * ((i & (1 << j)) ? 1 : -1); - } - tms3631cfg.feet[i] = data << 5; - } -} - - -// ---- - -void tms3631_reset(TMS3631 tms) -{ - memset(tms, 0, sizeof(*tms)); -} - -void tms3631_setkey(TMS3631 tms, REG8 ch, REG8 key) -{ - tms->ch[ch & 7].freq = tms3631cfg.freqtbl[key & 0x3f]; -} - -void tms3631_setenable(TMS3631 tms, REG8 enable) -{ - tms->enable = enable; -} +/** + * @file tms3631c.c + * @brief Implementation of the TMS3631 + */ + +#include +#include +#include + + TMS3631CFG tms3631cfg; + +void tms3631_initialize(UINT rate) +{ + UINT i, j; + double f; + + ZeroMemory(&tms3631cfg, sizeof(tms3631cfg)); + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 12; j++) + { + f = 440.0 * pow(2.0, (i - 3.0) + ((j - 9.0) / 12.0)); + f = f * TMS3631_MUL * (1 << (TMS3631_FREQ + 1)) / rate; + tms3631cfg.freqtbl[(i * 16) + j + 1] = (UINT32)floor(f + 0.5); + } + } +} + +void tms3631_setvol(const UINT8 *vol) +{ + UINT i; + UINT j; + SINT32 data; + + tms3631cfg.left = (vol[0] & 15) << 5; + tms3631cfg.right = (vol[1] & 15) << 5; + vol += 2; + for (i = 0; i < 16; i++) + { + data = 0; + for (j = 0; j < 4; j++) + { + data += (vol[j] & 15) * ((i & (1 << j)) ? 1 : -1); + } + tms3631cfg.feet[i] = data << 5; + } +} + + +// ---- + +void tms3631_reset(TMS3631 tms) +{ + memset(tms, 0, sizeof(*tms)); +} + +void tms3631_setkey(TMS3631 tms, REG8 ch, REG8 key) +{ + tms->ch[ch & 7].freq = tms3631cfg.freqtbl[key & 0x3f]; +} + +void tms3631_setenable(TMS3631 tms, REG8 enable) +{ + tms->enable = enable; +} diff --git a/sound/tms3631g.c b/sound/tms3631g.c old mode 100755 new mode 100644 index 96eb4826..032a33af --- a/sound/tms3631g.c +++ b/sound/tms3631g.c @@ -1,62 +1,62 @@ -/** - * @file tms3631g.c - * @brief Implementation of the TMS3631 - */ - -#include -#include - -extern TMS3631CFG tms3631cfg; - -void SOUNDCALL tms3631_getpcm(TMS3631 tms, SINT32 *pcm, UINT count) -{ - UINT ch; - SINT32 data; - UINT i; - - if (tms->enable == 0) - { - return; - } - while (count--) - { - ch = 0; - data = 0; - do /* centre */ - { - if ((tms->enable & (1 << ch)) && (tms->ch[ch].freq)) - { - for (i = 0; i < TMS3631_MUL; i++) - { - tms->ch[ch].count += tms->ch[ch].freq; - data += (tms->ch[ch].count & (1 << TMS3631_FREQ)) ? 1 : -1; - } - } - } while (++ch < 2); - pcm[0] += data * tms3631cfg.left; - pcm[1] += data * tms3631cfg.right; - do /* left */ - { - if ((tms->enable & (1 << ch)) && (tms->ch[ch].freq)) - { - for (i = 0; i < TMS3631_MUL; i++) - { - tms->ch[ch].count += tms->ch[ch].freq; - pcm[0] += tms3631cfg.feet[(tms->ch[ch].count >> TMS3631_FREQ) & 15]; - } - } - } while (++ch < 5); - do /* right */ - { - if ((tms->enable & (1 << ch)) && (tms->ch[ch].freq)) - { - for (i = 0; i < TMS3631_MUL; i++) - { - tms->ch[ch].count += tms->ch[ch].freq; - pcm[1] += tms3631cfg.feet[(tms->ch[ch].count >> TMS3631_FREQ) & 15]; - } - } - } while (++ch < 8); - pcm += 2; - } -} +/** + * @file tms3631g.c + * @brief Implementation of the TMS3631 + */ + +#include +#include + +extern TMS3631CFG tms3631cfg; + +void SOUNDCALL tms3631_getpcm(TMS3631 tms, SINT32 *pcm, UINT count) +{ + UINT ch; + SINT32 data; + UINT i; + + if (tms->enable == 0) + { + return; + } + while (count--) + { + ch = 0; + data = 0; + do /* centre */ + { + if ((tms->enable & (1 << ch)) && (tms->ch[ch].freq)) + { + for (i = 0; i < TMS3631_MUL; i++) + { + tms->ch[ch].count += tms->ch[ch].freq; + data += (tms->ch[ch].count & (1 << TMS3631_FREQ)) ? 1 : -1; + } + } + } while (++ch < 2); + pcm[0] += data * tms3631cfg.left; + pcm[1] += data * tms3631cfg.right; + do /* left */ + { + if ((tms->enable & (1 << ch)) && (tms->ch[ch].freq)) + { + for (i = 0; i < TMS3631_MUL; i++) + { + tms->ch[ch].count += tms->ch[ch].freq; + pcm[0] += tms3631cfg.feet[(tms->ch[ch].count >> TMS3631_FREQ) & 15]; + } + } + } while (++ch < 5); + do /* right */ + { + if ((tms->enable & (1 << ch)) && (tms->ch[ch].freq)) + { + for (i = 0; i < TMS3631_MUL; i++) + { + tms->ch[ch].count += tms->ch[ch].freq; + pcm[1] += tms3631cfg.feet[(tms->ch[ch].count >> TMS3631_FREQ) & 15]; + } + } + } while (++ch < 8); + pcm += 2; + } +} diff --git a/sound/vermouth/midimod.c b/sound/vermouth/midimod.c old mode 100755 new mode 100644 index f6d3f285..11f005cd --- a/sound/vermouth/midimod.c +++ b/sound/vermouth/midimod.c @@ -1,597 +1,597 @@ -#include -#include -#include -#include -#include "midiout.h" - - -#define CFG_MAXAMP 400 -#define MAX_NAME 64 - -enum { - CFG_DIR = 0, - CFG_SOURCE, - CFG_DEFAULT, - CFG_BANK, - CFG_DRUM -}; - -static const OEMCHAR str_dir[] = OEMTEXT("dir"); -static const OEMCHAR str_source[] = OEMTEXT("source"); -static const OEMCHAR str_default[] = OEMTEXT("default"); -static const OEMCHAR str_bank[] = OEMTEXT("bank"); -static const OEMCHAR str_drumset[] = OEMTEXT("drumset"); -static const OEMCHAR *cfgstr[] = {str_dir, str_source, str_default, - str_bank, str_drumset}; - -static const OEMCHAR str_amp[] = OEMTEXT("amp"); -static const OEMCHAR str_keep[] = OEMTEXT("keep"); -static const OEMCHAR str_note[] = OEMTEXT("note"); -static const OEMCHAR str_pan[] = OEMTEXT("pan"); -static const OEMCHAR str_strip[] = OEMTEXT("strip"); -static const OEMCHAR str_left[] = OEMTEXT("left"); -static const OEMCHAR str_center[] = OEMTEXT("center"); -static const OEMCHAR str_right[] = OEMTEXT("right"); -static const OEMCHAR str_env[] = OEMTEXT("env"); -static const OEMCHAR str_loop[] = OEMTEXT("loop"); -static const OEMCHAR str_tail[] = OEMTEXT("tail"); -static const OEMCHAR file_timiditycfg[] = OEMTEXT("timidity.cfg"); -static const OEMCHAR str_basedir[] = OEMTEXT("${basedir}"); - - -static void VERMOUTHCL pathadd(MIDIMOD mod, const OEMCHAR *path) { - - _PATHLIST pl; - PATHLIST p; - - ZeroMemory(&pl, sizeof(pl)); - if (path) { - pl.path[0] = '\0'; - // separator change! - file_catname(pl.path, path, NELEMENTS(pl.path)); - if (path[0]) { - file_setseparator(pl.path, NELEMENTS(pl.path)); - } - } - - pl.next = mod->pathlist; - p = pl.next; - while(p) { - if (!file_cmpname(p->path, pl.path)) { - return; - } - p = p->next; - } - p = (PATHLIST)listarray_append(mod->pathtbl, &pl); - if (p) { - mod->pathlist = p; - } -} - -static void VERMOUTHCL pathaddex(MIDIMOD mod, const OEMCHAR *path) { - - OEMCHAR _path[MAX_PATH]; - - if (milstr_memcmp(path, str_basedir)) { - pathadd(mod, path); - } - else { - file_cpyname(_path, file_getcd(str_null), NELEMENTS(_path)); - file_cutseparator(_path); - file_catname(_path, path + 10, NELEMENTS(_path)); - pathadd(mod, _path); - } -} - -static int VERMOUTHCL cfggetarg(OEMCHAR *str, OEMCHAR *arg[], int maxarg) { - - int ret; - BOOL quot; - OEMCHAR *p; - OEMCHAR c; - - ret = 0; - while(maxarg--) { - quot = FALSE; - while(1) { - c = *str; - if ((c == 0) || (c == 0x23)) { - goto cga_done; - } - if ((c < 0) || (c > 0x20)) { - break; - } - str++; - } - arg[ret++] = str; - p = str; - while(1) { - c = *str; - if (c == 0) { - break; - } - str++; - if (c == 0x22) { - quot = !quot; - } - else if (quot) { - *p++ = c; - } - else if (c == 0x23) { - *p = '\0'; - goto cga_done; - } - else if ((c < 0) || (c > 0x20)) { - *p++ = c; - } - else { - break; - } - } - *p = '\0'; - } - -cga_done: - return(ret); -} - -static OEMCHAR *VERMOUTHCL seachr(const OEMCHAR *str, OEMCHAR sepa) { - - OEMCHAR c; - - while(1) { - c = *str; - if (c == '\0') { - break; - } - if (c == sepa) { - return((OEMCHAR *)str); - } - str++; - } - return(NULL); -} - -enum { - VAL_EXIST = 1, - VAL_SIGN = 2 -}; - -static BRESULT VERMOUTHCL cfggetval(const OEMCHAR *str, int *val) { - - int ret; - int flag; - int c; - - ret = 0; - flag = 0; - c = *str; - if (c == '+') { - str++; - } - else if (c == '-') { - str++; - flag |= VAL_SIGN; - } - while(1) { - c = *str++; - c -= '0'; - if ((unsigned)c < 10) { - ret *= 10; - ret += c; - flag |= VAL_EXIST; - } - else { - break; - } - } - if (flag & VAL_EXIST) { - if (flag & VAL_SIGN) { - ret *= -1; - } - if (val) { - *val = ret; - } - return(SUCCESS); - } - else { - return(FAILURE); - } -} - - -// ---- - -static void VERMOUTHCL settone(MIDIMOD mod, int bank, int argc, - OEMCHAR *argv[]) { - - int val; - TONECFG tone; - OEMCHAR *name; - int i; - OEMCHAR *key; - OEMCHAR *data; - UINT8 flag; - - if ((bank < 0) || (bank >= (MIDI_BANKS * 2)) || (argc < 2) || - (cfggetval(argv[0], &val) != SUCCESS) || (val < 0) || (val >= 128)) { - return; - } - tone = mod->tonecfg[bank]; - if (tone == NULL) { - tone = (TONECFG)_MALLOC(sizeof(_TONECFG) * 128, "tone cfg"); - if (tone == NULL) { - return; - } - mod->tonecfg[bank] = tone; - ZeroMemory(tone, sizeof(_TONECFG) * 128); - } - tone += val; - name = tone->name; - if (name == NULL) { - name = (OEMCHAR *)listarray_append(mod->namelist, NULL); - tone->name = name; - } - if (name) { - name[0] = '\0'; - file_catname(name, argv[1], MAX_NAME); // separator change! - } - flag = TONECFG_EXIST; - tone->amp = TONECFG_AUTOAMP; - tone->pan = TONECFG_VARIABLE; - - if (!(bank & 1)) { // for tone - tone->note = TONECFG_VARIABLE; - } - else { // for drums - flag |= TONECFG_NOLOOP | TONECFG_NOENV; - tone->note = (UINT8)val; - } - - for (i=2; i CFG_MAXAMP) { - val = CFG_MAXAMP; - } - tone->amp = val; - } - } - else if (!milstr_cmp(key, str_keep)) { - if (!milstr_cmp(data, str_env)) { - flag &= ~TONECFG_NOENV; - flag |= TONECFG_KEEPENV; - } - else if (!milstr_cmp(data, str_loop)) { - flag &= ~TONECFG_NOLOOP; - } - } - else if (!milstr_cmp(key, str_note)) { - if ((cfggetval(data, &val) == SUCCESS) && - (val >= 0) && (val < 128)) { - tone->note = (UINT8)val; - } - } - else if (!milstr_cmp(key, str_pan)) { - if (!milstr_cmp(data, str_left)) { - val = 0; - } - else if (!milstr_cmp(data, str_center)) { - val = 64; - } - else if (!milstr_cmp(data, str_right)) { - val = 127; - } - else if (cfggetval(data, &val) == SUCCESS) { - if (val < -100) { - val = -100; - } - else if (val > 100) { - val = 100; - } - val = val + 100; - val *= 127; - val += 100; - val /= 200; - } - else { - continue; - } - tone->pan = (UINT8)val; - } - else if (!milstr_cmp(key, str_strip)) { - if (!milstr_cmp(data, str_env)) { - flag &= ~TONECFG_KEEPENV; - flag |= TONECFG_NOENV; - } - else if (!milstr_cmp(data, str_loop)) { - flag |= TONECFG_NOLOOP; - } - else if (!milstr_cmp(data, str_tail)) { - flag |= TONECFG_NOTAIL; - } - } - } - tone->flag = flag; -} - - -// ---- - -BRESULT VERMOUTHCL midimod_getfile(MIDIMOD mod, const OEMCHAR *filename, - OEMCHAR *path, int size) { - - PATHLIST p; - short attr; - - if ((filename == NULL) || (filename[0] == '\0') || - (path == NULL) || (size == 0)) { - goto fpgf_exit; - } - p = mod->pathlist; - while(p) { - file_cpyname(path, p->path, size); - file_catname(path, filename, size); - attr = file_attr(path); - if (attr != -1) { - return(SUCCESS); - } - p = p->next; - } - -fpgf_exit: - return(FAILURE); -} - -static BRESULT VERMOUTHCL cfgfile_load(MIDIMOD mod, const OEMCHAR *filename, - int depth) { - - TEXTFILEH tfh; - OEMCHAR buf[1024]; - int bank; - int i; - int argc; - OEMCHAR *argv[16]; - int val; - UINT cfg; - - bank = -1; - - if ((depth >= 16) || - (midimod_getfile(mod, filename, buf, NELEMENTS(buf)) != SUCCESS)) { - goto cfl_err; - } -// TRACEOUT(("open: %s", buf)); - tfh = textfile_open(buf, 0x1000); - if (tfh == NULL) { - goto cfl_err; - } - while(textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) { - argc = cfggetarg(buf, argv, NELEMENTS(argv)); - if (argc < 2) { - continue; - } - cfg = 0; - while(cfg < NELEMENTS(cfgstr)) { - if (!milstr_cmp(argv[0], cfgstr[cfg])) { - break; - } - cfg++; - } - switch(cfg) { - case CFG_DIR: - for (i=1; i= 0) && (val < 128)) { - val <<= 1; - if (cfg == CFG_DRUM) { - val++; - } - bank = val; - } - break; - - default: - settone(mod, bank, argc, argv); - break; - } - } - textfile_close(tfh); - return(SUCCESS); - -cfl_err: - return(FAILURE); -} - - -// ---- - -VEXTERN MIDIMOD VEXPORT midimod_create(UINT samprate) { - - UINT size; - MIDIMOD ret; - BRESULT r; - - size = sizeof(_MIDIMOD); - size += sizeof(INSTRUMENT) * 128 * 2; - size += sizeof(_TONECFG) * 128 * 2; - ret = (MIDIMOD)_MALLOC(size, "MIDIMOD"); - if (ret == NULL) { - goto mmcre_err1; - } - ZeroMemory(ret, size); - ret->samprate = samprate; - ret->tone[0] = (INSTRUMENT *)(ret + 1); - ret->tone[1] = ret->tone[0] + 128; - ret->tonecfg[0] = (TONECFG)(ret->tone[1] + 128); - ret->tonecfg[1] = ret->tonecfg[0] + 128; - ret->pathtbl = listarray_new(sizeof(_PATHLIST), 16); - pathadd(ret, NULL); - pathadd(ret, file_getcd(str_null)); - ret->namelist = listarray_new(MAX_NAME, 128); - r = cfgfile_load(ret, file_timiditycfg, 0); -#if defined(TIMIDITY_CFGFILE) - if (r != SUCCESS) { - r = cfgfile_load(ret, TIMIDITY_CFGFILE, 0); - } -#endif - if (r != SUCCESS) { - goto mmcre_err2; - } - midimod_lock(ret); - return(ret); - -mmcre_err2: - listarray_destroy(ret->namelist); - listarray_destroy(ret->pathtbl); - _MFREE(ret); - -mmcre_err1: - return(NULL); -} - -void VERMOUTHCL midimod_lock(MIDIMOD mod) { - - mod->lockcount++; -} - -void VERMOUTHCL midimod_unlock(MIDIMOD mod) { - - UINT r; - TONECFG bank; - - if (!mod->lockcount) { - return; - } - mod->lockcount--; - if (mod->lockcount) { - return; - } - - r = 128; - do { - r--; - inst_bankfree(mod, r); - } while(r > 0); - for (r=2; r<(MIDI_BANKS*2); r++) { - bank = mod->tonecfg[r]; - if (bank) { - _MFREE(bank); - } - } - listarray_destroy(mod->namelist); - listarray_destroy(mod->pathtbl); - _MFREE(mod); -} - -VEXTERN void VEXPORT midimod_destroy(MIDIMOD mod) { - - if (mod) { - midimod_unlock(mod); - } -} - -VEXTERN BRESULT VEXPORT midimod_cfgload(MIDIMOD mod, - const OEMCHAR *filename) { - - return(cfgfile_load(mod, filename, 0)); -} - -VEXTERN void VEXPORT midimod_loadprogram(MIDIMOD mod, UINT num) { - - UINT bank; - - if (mod != NULL) { - bank = (num >> 8) & 0x7f; - num &= 0x7f; - if (inst_singleload(mod, bank << 1, num) != MIDIOUT_SUCCESS) { - inst_singleload(mod, 0, num); - } - } -} - -VEXTERN void VEXPORT midimod_loadrhythm(MIDIMOD mod, UINT num) { - - UINT bank; - - if (mod != NULL) { - bank = (num >> 8) & 0x7f; - num &= 0x7f; - if (inst_singleload(mod, (bank << 1) + 1, num) != MIDIOUT_SUCCESS) { - inst_singleload(mod, 1, num); - } - } -} - -VEXTERN void VEXPORT midimod_loadgm(MIDIMOD mod) { - - if (mod) { - inst_bankload(mod, 0); - inst_bankload(mod, 1); - } -} - -VEXTERN void VEXPORT midimod_loadall(MIDIMOD mod) { - - UINT b; - - if (mod) { - for (b=0; b<(MIDI_BANKS*2); b++) { - inst_bankload(mod, b); - } - } -} - - -VEXTERN int VEXPORT midimod_loadallex(MIDIMOD mod, FNMIDIOUTLAEXCB cb, - void *userdata) { - - int result; - MIDIOUTLAEXPARAM param; - UINT b; - - result = MIDIOUT_SUCCESS; - if (mod) { - ZeroMemory(¶m, sizeof(param)); - param.userdata = userdata; - for (b=0; b<(MIDI_BANKS*2); b++) { - param.totaltones += inst_gettones(mod, b); - } - for (b=0; b<(MIDI_BANKS*2); b++) { - param.bank = b; - result = inst_bankloadex(mod, b, cb, ¶m); - if (result != MIDIOUT_SUCCESS) - { - break; - } - } - } - return result; -} - +#include +#include +#include +#include +#include "midiout.h" + + +#define CFG_MAXAMP 400 +#define MAX_NAME 64 + +enum { + CFG_DIR = 0, + CFG_SOURCE, + CFG_DEFAULT, + CFG_BANK, + CFG_DRUM +}; + +static const OEMCHAR str_dir[] = OEMTEXT("dir"); +static const OEMCHAR str_source[] = OEMTEXT("source"); +static const OEMCHAR str_default[] = OEMTEXT("default"); +static const OEMCHAR str_bank[] = OEMTEXT("bank"); +static const OEMCHAR str_drumset[] = OEMTEXT("drumset"); +static const OEMCHAR *cfgstr[] = {str_dir, str_source, str_default, + str_bank, str_drumset}; + +static const OEMCHAR str_amp[] = OEMTEXT("amp"); +static const OEMCHAR str_keep[] = OEMTEXT("keep"); +static const OEMCHAR str_note[] = OEMTEXT("note"); +static const OEMCHAR str_pan[] = OEMTEXT("pan"); +static const OEMCHAR str_strip[] = OEMTEXT("strip"); +static const OEMCHAR str_left[] = OEMTEXT("left"); +static const OEMCHAR str_center[] = OEMTEXT("center"); +static const OEMCHAR str_right[] = OEMTEXT("right"); +static const OEMCHAR str_env[] = OEMTEXT("env"); +static const OEMCHAR str_loop[] = OEMTEXT("loop"); +static const OEMCHAR str_tail[] = OEMTEXT("tail"); +static const OEMCHAR file_timiditycfg[] = OEMTEXT("timidity.cfg"); +static const OEMCHAR str_basedir[] = OEMTEXT("${basedir}"); + + +static void VERMOUTHCL pathadd(MIDIMOD mod, const OEMCHAR *path) { + + _PATHLIST pl; + PATHLIST p; + + ZeroMemory(&pl, sizeof(pl)); + if (path) { + pl.path[0] = '\0'; + // separator change! + file_catname(pl.path, path, NELEMENTS(pl.path)); + if (path[0]) { + file_setseparator(pl.path, NELEMENTS(pl.path)); + } + } + + pl.next = mod->pathlist; + p = pl.next; + while(p) { + if (!file_cmpname(p->path, pl.path)) { + return; + } + p = p->next; + } + p = (PATHLIST)listarray_append(mod->pathtbl, &pl); + if (p) { + mod->pathlist = p; + } +} + +static void VERMOUTHCL pathaddex(MIDIMOD mod, const OEMCHAR *path) { + + OEMCHAR _path[MAX_PATH]; + + if (milstr_memcmp(path, str_basedir)) { + pathadd(mod, path); + } + else { + file_cpyname(_path, file_getcd(str_null), NELEMENTS(_path)); + file_cutseparator(_path); + file_catname(_path, path + 10, NELEMENTS(_path)); + pathadd(mod, _path); + } +} + +static int VERMOUTHCL cfggetarg(OEMCHAR *str, OEMCHAR *arg[], int maxarg) { + + int ret; + BOOL quot; + OEMCHAR *p; + OEMCHAR c; + + ret = 0; + while(maxarg--) { + quot = FALSE; + while(1) { + c = *str; + if ((c == 0) || (c == 0x23)) { + goto cga_done; + } + if ((c < 0) || (c > 0x20)) { + break; + } + str++; + } + arg[ret++] = str; + p = str; + while(1) { + c = *str; + if (c == 0) { + break; + } + str++; + if (c == 0x22) { + quot = !quot; + } + else if (quot) { + *p++ = c; + } + else if (c == 0x23) { + *p = '\0'; + goto cga_done; + } + else if ((c < 0) || (c > 0x20)) { + *p++ = c; + } + else { + break; + } + } + *p = '\0'; + } + +cga_done: + return(ret); +} + +static OEMCHAR *VERMOUTHCL seachr(const OEMCHAR *str, OEMCHAR sepa) { + + OEMCHAR c; + + while(1) { + c = *str; + if (c == '\0') { + break; + } + if (c == sepa) { + return((OEMCHAR *)str); + } + str++; + } + return(NULL); +} + +enum { + VAL_EXIST = 1, + VAL_SIGN = 2 +}; + +static BRESULT VERMOUTHCL cfggetval(const OEMCHAR *str, int *val) { + + int ret; + int flag; + int c; + + ret = 0; + flag = 0; + c = *str; + if (c == '+') { + str++; + } + else if (c == '-') { + str++; + flag |= VAL_SIGN; + } + while(1) { + c = *str++; + c -= '0'; + if ((unsigned)c < 10) { + ret *= 10; + ret += c; + flag |= VAL_EXIST; + } + else { + break; + } + } + if (flag & VAL_EXIST) { + if (flag & VAL_SIGN) { + ret *= -1; + } + if (val) { + *val = ret; + } + return(SUCCESS); + } + else { + return(FAILURE); + } +} + + +// ---- + +static void VERMOUTHCL settone(MIDIMOD mod, int bank, int argc, + OEMCHAR *argv[]) { + + int val; + TONECFG tone; + OEMCHAR *name; + int i; + OEMCHAR *key; + OEMCHAR *data; + UINT8 flag; + + if ((bank < 0) || (bank >= (MIDI_BANKS * 2)) || (argc < 2) || + (cfggetval(argv[0], &val) != SUCCESS) || (val < 0) || (val >= 128)) { + return; + } + tone = mod->tonecfg[bank]; + if (tone == NULL) { + tone = (TONECFG)_MALLOC(sizeof(_TONECFG) * 128, "tone cfg"); + if (tone == NULL) { + return; + } + mod->tonecfg[bank] = tone; + ZeroMemory(tone, sizeof(_TONECFG) * 128); + } + tone += val; + name = tone->name; + if (name == NULL) { + name = (OEMCHAR *)listarray_append(mod->namelist, NULL); + tone->name = name; + } + if (name) { + name[0] = '\0'; + file_catname(name, argv[1], MAX_NAME); // separator change! + } + flag = TONECFG_EXIST; + tone->amp = TONECFG_AUTOAMP; + tone->pan = TONECFG_VARIABLE; + + if (!(bank & 1)) { // for tone + tone->note = TONECFG_VARIABLE; + } + else { // for drums + flag |= TONECFG_NOLOOP | TONECFG_NOENV; + tone->note = (UINT8)val; + } + + for (i=2; i CFG_MAXAMP) { + val = CFG_MAXAMP; + } + tone->amp = val; + } + } + else if (!milstr_cmp(key, str_keep)) { + if (!milstr_cmp(data, str_env)) { + flag &= ~TONECFG_NOENV; + flag |= TONECFG_KEEPENV; + } + else if (!milstr_cmp(data, str_loop)) { + flag &= ~TONECFG_NOLOOP; + } + } + else if (!milstr_cmp(key, str_note)) { + if ((cfggetval(data, &val) == SUCCESS) && + (val >= 0) && (val < 128)) { + tone->note = (UINT8)val; + } + } + else if (!milstr_cmp(key, str_pan)) { + if (!milstr_cmp(data, str_left)) { + val = 0; + } + else if (!milstr_cmp(data, str_center)) { + val = 64; + } + else if (!milstr_cmp(data, str_right)) { + val = 127; + } + else if (cfggetval(data, &val) == SUCCESS) { + if (val < -100) { + val = -100; + } + else if (val > 100) { + val = 100; + } + val = val + 100; + val *= 127; + val += 100; + val /= 200; + } + else { + continue; + } + tone->pan = (UINT8)val; + } + else if (!milstr_cmp(key, str_strip)) { + if (!milstr_cmp(data, str_env)) { + flag &= ~TONECFG_KEEPENV; + flag |= TONECFG_NOENV; + } + else if (!milstr_cmp(data, str_loop)) { + flag |= TONECFG_NOLOOP; + } + else if (!milstr_cmp(data, str_tail)) { + flag |= TONECFG_NOTAIL; + } + } + } + tone->flag = flag; +} + + +// ---- + +BRESULT VERMOUTHCL midimod_getfile(MIDIMOD mod, const OEMCHAR *filename, + OEMCHAR *path, int size) { + + PATHLIST p; + short attr; + + if ((filename == NULL) || (filename[0] == '\0') || + (path == NULL) || (size == 0)) { + goto fpgf_exit; + } + p = mod->pathlist; + while(p) { + file_cpyname(path, p->path, size); + file_catname(path, filename, size); + attr = file_attr(path); + if (attr != -1) { + return(SUCCESS); + } + p = p->next; + } + +fpgf_exit: + return(FAILURE); +} + +static BRESULT VERMOUTHCL cfgfile_load(MIDIMOD mod, const OEMCHAR *filename, + int depth) { + + TEXTFILEH tfh; + OEMCHAR buf[1024]; + int bank; + int i; + int argc; + OEMCHAR *argv[16]; + int val; + UINT cfg; + + bank = -1; + + if ((depth >= 16) || + (midimod_getfile(mod, filename, buf, NELEMENTS(buf)) != SUCCESS)) { + goto cfl_err; + } +// TRACEOUT(("open: %s", buf)); + tfh = textfile_open(buf, 0x1000); + if (tfh == NULL) { + goto cfl_err; + } + while(textfile_read(tfh, buf, NELEMENTS(buf)) == SUCCESS) { + argc = cfggetarg(buf, argv, NELEMENTS(argv)); + if (argc < 2) { + continue; + } + cfg = 0; + while(cfg < NELEMENTS(cfgstr)) { + if (!milstr_cmp(argv[0], cfgstr[cfg])) { + break; + } + cfg++; + } + switch(cfg) { + case CFG_DIR: + for (i=1; i= 0) && (val < 128)) { + val <<= 1; + if (cfg == CFG_DRUM) { + val++; + } + bank = val; + } + break; + + default: + settone(mod, bank, argc, argv); + break; + } + } + textfile_close(tfh); + return(SUCCESS); + +cfl_err: + return(FAILURE); +} + + +// ---- + +VEXTERN MIDIMOD VEXPORT midimod_create(UINT samprate) { + + UINT size; + MIDIMOD ret; + BRESULT r; + + size = sizeof(_MIDIMOD); + size += sizeof(INSTRUMENT) * 128 * 2; + size += sizeof(_TONECFG) * 128 * 2; + ret = (MIDIMOD)_MALLOC(size, "MIDIMOD"); + if (ret == NULL) { + goto mmcre_err1; + } + ZeroMemory(ret, size); + ret->samprate = samprate; + ret->tone[0] = (INSTRUMENT *)(ret + 1); + ret->tone[1] = ret->tone[0] + 128; + ret->tonecfg[0] = (TONECFG)(ret->tone[1] + 128); + ret->tonecfg[1] = ret->tonecfg[0] + 128; + ret->pathtbl = listarray_new(sizeof(_PATHLIST), 16); + pathadd(ret, NULL); + pathadd(ret, file_getcd(str_null)); + ret->namelist = listarray_new(MAX_NAME, 128); + r = cfgfile_load(ret, file_timiditycfg, 0); +#if defined(TIMIDITY_CFGFILE) + if (r != SUCCESS) { + r = cfgfile_load(ret, TIMIDITY_CFGFILE, 0); + } +#endif + if (r != SUCCESS) { + goto mmcre_err2; + } + midimod_lock(ret); + return(ret); + +mmcre_err2: + listarray_destroy(ret->namelist); + listarray_destroy(ret->pathtbl); + _MFREE(ret); + +mmcre_err1: + return(NULL); +} + +void VERMOUTHCL midimod_lock(MIDIMOD mod) { + + mod->lockcount++; +} + +void VERMOUTHCL midimod_unlock(MIDIMOD mod) { + + UINT r; + TONECFG bank; + + if (!mod->lockcount) { + return; + } + mod->lockcount--; + if (mod->lockcount) { + return; + } + + r = 128; + do { + r--; + inst_bankfree(mod, r); + } while(r > 0); + for (r=2; r<(MIDI_BANKS*2); r++) { + bank = mod->tonecfg[r]; + if (bank) { + _MFREE(bank); + } + } + listarray_destroy(mod->namelist); + listarray_destroy(mod->pathtbl); + _MFREE(mod); +} + +VEXTERN void VEXPORT midimod_destroy(MIDIMOD mod) { + + if (mod) { + midimod_unlock(mod); + } +} + +VEXTERN BRESULT VEXPORT midimod_cfgload(MIDIMOD mod, + const OEMCHAR *filename) { + + return(cfgfile_load(mod, filename, 0)); +} + +VEXTERN void VEXPORT midimod_loadprogram(MIDIMOD mod, UINT num) { + + UINT bank; + + if (mod != NULL) { + bank = (num >> 8) & 0x7f; + num &= 0x7f; + if (inst_singleload(mod, bank << 1, num) != MIDIOUT_SUCCESS) { + inst_singleload(mod, 0, num); + } + } +} + +VEXTERN void VEXPORT midimod_loadrhythm(MIDIMOD mod, UINT num) { + + UINT bank; + + if (mod != NULL) { + bank = (num >> 8) & 0x7f; + num &= 0x7f; + if (inst_singleload(mod, (bank << 1) + 1, num) != MIDIOUT_SUCCESS) { + inst_singleload(mod, 1, num); + } + } +} + +VEXTERN void VEXPORT midimod_loadgm(MIDIMOD mod) { + + if (mod) { + inst_bankload(mod, 0); + inst_bankload(mod, 1); + } +} + +VEXTERN void VEXPORT midimod_loadall(MIDIMOD mod) { + + UINT b; + + if (mod) { + for (b=0; b<(MIDI_BANKS*2); b++) { + inst_bankload(mod, b); + } + } +} + + +VEXTERN int VEXPORT midimod_loadallex(MIDIMOD mod, FNMIDIOUTLAEXCB cb, + void *userdata) { + + int result; + MIDIOUTLAEXPARAM param; + UINT b; + + result = MIDIOUT_SUCCESS; + if (mod) { + ZeroMemory(¶m, sizeof(param)); + param.userdata = userdata; + for (b=0; b<(MIDI_BANKS*2); b++) { + param.totaltones += inst_gettones(mod, b); + } + for (b=0; b<(MIDI_BANKS*2); b++) { + param.bank = b; + result = inst_bankloadex(mod, b, cb, ¶m); + if (result != MIDIOUT_SUCCESS) + { + break; + } + } + } + return result; +} + diff --git a/sound/vermouth/midimod.h b/sound/vermouth/midimod.h old mode 100755 new mode 100644 index 9753fdfc..58811adb --- a/sound/vermouth/midimod.h +++ b/sound/vermouth/midimod.h @@ -1,43 +1,43 @@ - -struct _pathlist; -typedef struct _pathlist _PATHLIST; -typedef struct _pathlist *PATHLIST; - -struct _pathlist { - PATHLIST next; - OEMCHAR path[MAX_PATH]; -}; - -enum { - TONECFG_EXIST = 0x01, - TONECFG_NOLOOP = 0x02, - TONECFG_NOENV = 0x04, - TONECFG_KEEPENV = 0x08, - TONECFG_NOTAIL = 0x10, - - TONECFG_AUTOAMP = -1, - TONECFG_VARIABLE = 0xff -}; - -typedef struct { - OEMCHAR *name; - int amp; - UINT8 flag; - UINT8 pan; - UINT8 note; -} _TONECFG, *TONECFG; - - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT VERMOUTHCL midimod_getfile(MIDIMOD mod, const OEMCHAR *filename, - OEMCHAR *path, int size); -void VERMOUTHCL midimod_lock(MIDIMOD mod); -void VERMOUTHCL midimod_unlock(MIDIMOD mod); - -#ifdef __cplusplus -} -#endif - + +struct _pathlist; +typedef struct _pathlist _PATHLIST; +typedef struct _pathlist *PATHLIST; + +struct _pathlist { + PATHLIST next; + OEMCHAR path[MAX_PATH]; +}; + +enum { + TONECFG_EXIST = 0x01, + TONECFG_NOLOOP = 0x02, + TONECFG_NOENV = 0x04, + TONECFG_KEEPENV = 0x08, + TONECFG_NOTAIL = 0x10, + + TONECFG_AUTOAMP = -1, + TONECFG_VARIABLE = 0xff +}; + +typedef struct { + OEMCHAR *name; + int amp; + UINT8 flag; + UINT8 pan; + UINT8 note; +} _TONECFG, *TONECFG; + + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT VERMOUTHCL midimod_getfile(MIDIMOD mod, const OEMCHAR *filename, + OEMCHAR *path, int size); +void VERMOUTHCL midimod_lock(MIDIMOD mod); +void VERMOUTHCL midimod_unlock(MIDIMOD mod); + +#ifdef __cplusplus +} +#endif + diff --git a/sound/vermouth/midinst.c b/sound/vermouth/midinst.c old mode 100755 new mode 100644 index 249b6381..855c9e6b --- a/sound/vermouth/midinst.c +++ b/sound/vermouth/midinst.c @@ -1,599 +1,599 @@ -#include -#include -#include "midiout.h" - - -#define _FILEH FILEH -#define _FILEH_INVALID FILEH_INVALID -#define _file_open file_open -#define _file_read file_read -#define _file_close file_close - - -// GUS format references: http://www.onicos.com/staff/iz/formats/guspat.html - -typedef struct { - char sig[12]; - char id[10]; - char description[60]; - - UINT8 instruments; - UINT8 voice; - UINT8 channels; - UINT8 waveforms[2]; - UINT8 volume[2]; - UINT8 datasize[4]; - UINT8 reserved1[36]; - - UINT8 instrument[2]; - UINT8 instname[16]; - UINT8 instsize[4]; - UINT8 layers; - UINT8 reserved2[40]; - - UINT8 layerdupe; - UINT8 layer; - UINT8 layersize[4]; - UINT8 layersamples; - UINT8 reserved3[40]; -} GUSHEAD; - -typedef struct { - UINT8 wavename[7]; - UINT8 fractions; - UINT8 datasize[4]; - UINT8 loopstart[4]; - UINT8 loopend[4]; - UINT8 samprate[2]; - UINT8 freqlow[4]; - UINT8 freqhigh[4]; - UINT8 freqroot[4]; - UINT8 tune[2]; - UINT8 balance; - UINT8 env[6]; - UINT8 envpos[6]; - UINT8 tre_sweep; - UINT8 tre_rate; - UINT8 tre_depth; - UINT8 vib_sweep; - UINT8 vib_rate; - UINT8 vib_depth; - UINT8 mode; - UINT8 scalefreq[2]; - UINT8 scalefactor[2]; - UINT8 reserved[36]; -} GUSWAVE; - - -static void VERMOUTHCL inst_destroy(INSTRUMENT inst); - - -// ---- resample - -#define BASEBITS 9 -#define MIXBASE (1 << BASEBITS) - -static SAMPLE VERMOUTHCL downsamp(SAMPLE dst, SAMPLE src, int count, - int mrate) { - - int rem; - SINT32 pcm; - - rem = MIXBASE; - pcm = 0; - do { - if (rem > mrate) { - rem -= mrate; - pcm += (*src++) * mrate; - } - else { - pcm += (*src) * rem; - pcm >>= BASEBITS; - *dst++ = (_SAMPLE)pcm; - pcm = mrate - rem; - rem = MIXBASE - pcm; - pcm *= (*src++); - } - } while(--count); - if (rem != MIXBASE) { - *dst++ = (_SAMPLE)(pcm >> BASEBITS); - } - return(dst); -} - -static SAMPLE VERMOUTHCL upsamp(SAMPLE dst, SAMPLE src, int count, - int mrate) { - - int rem; - SINT32 tmp; - SINT32 pcm; - SINT32 dat; - - rem = 0; - pcm = 0; - do { - tmp = MIXBASE - rem; - if (tmp >= 0) { - dat = (pcm * rem); - pcm = *src++; - dat += (pcm * tmp); - dat >>= BASEBITS; - *dst++ = (_SAMPLE)dat; - rem = mrate - tmp; - count--; - } - while(rem >= MIXBASE) { - rem -= MIXBASE; - *dst++ = (_SAMPLE)pcm; - } - } while(count); - if (rem) { - *dst++ = rem >> BASEBITS; - } - return(dst); -} - -static void VERMOUTHCL resample(MIDIMOD mod, INSTLAYER inst, int freq) { - - int mrate; - int orgcnt; - int newcnt; - SAMPLE dst; - SAMPLE dstterm; - - mrate = (int)((float)MIXBASE * - (float)mod->samprate / (float)inst->samprate * - (float)inst->freqroot / (float)freq); - if (mrate != MIXBASE) { - orgcnt = inst->datasize >> FREQ_SHIFT; - newcnt = (orgcnt * mrate + MIXBASE - 1) >> BASEBITS; - dst = (SAMPLE)_MALLOC((newcnt + 1) * sizeof(_SAMPLE), "resampled"); - if (dst == NULL) { - return; - } - dst[newcnt] = 0; - if (mrate > MIXBASE) { - dstterm = upsamp(dst, inst->data, orgcnt, mrate); - } - else { - dstterm = downsamp(dst, inst->data, orgcnt, mrate); - } -#if 0 - if ((dstterm - dst) != newcnt) { - TRACEOUT(("resample error %d %d", newcnt, dstterm - dst)); - } -#endif - inst->datasize = newcnt << FREQ_SHIFT; - inst->loopstart = 0; - inst->loopend = newcnt << FREQ_SHIFT; - _MFREE(inst->data); - inst->data = dst; - } - inst->samprate = 0; -} - - -// ---- load - -static const OEMCHAR ext_pat[] = OEMTEXT(".pat"); -static const char sig_GF1PATCH100[] = "GF1PATCH100"; -static const char sig_GF1PATCH110[] = "GF1PATCH110"; -static const char sig_ID000002[] = "ID#000002"; -static const char str_question6[] = "??????"; - -static INSTRUMENT VERMOUTHCL inst_create(MIDIMOD mod, const _TONECFG *cfg) { - - OEMCHAR filename[MAX_PATH]; - OEMCHAR path[MAX_PATH]; - _FILEH fh; - INSTRUMENT ret; - GUSHEAD head; - int layers; - int size; - INSTLAYER layer; - GUSWAVE wave; - int i; - SAMPLE dat; - _SAMPLE tmp; -const UINT8 *d; - SINT16 *p; - SINT16 *q; - int cnt; - - if (cfg->name == NULL) { - goto li_err1; - } - file_cpyname(filename, cfg->name, NELEMENTS(filename)); - file_cutext(filename); - file_catname(filename, ext_pat, NELEMENTS(filename)); - if (midimod_getfile(mod, filename, path, NELEMENTS(path)) != SUCCESS) { - goto li_err1; - } - fh = _file_open(path); - if (fh == _FILEH_INVALID) { -// TRACEOUT(("not found: %s", path)); - goto li_err1; - } - - // head check - if ((_file_read(fh, &head, sizeof(head)) != sizeof(head)) && - (memcmp(head.sig, sig_GF1PATCH100, 12)) && - (memcmp(head.sig, sig_GF1PATCH110, 12)) && - (memcmp(head.id, sig_ID000002, 10)) && - (head.instruments != 0) && (head.instruments != 1) && - (head.layers != 0) && (head.layers != 1)) { - goto li_err2; - } - - layers = head.layersamples; - if (!layers) { - goto li_err2; - } - size = sizeof(_INSTRUMENT) + (layers * sizeof(_INSTLAYER)); - ret = (INSTRUMENT)_MALLOC(size, "instrument"); - if (ret == NULL) { - goto li_err2; - } - ZeroMemory(ret, size); - layer = (INSTLAYER)(ret + 1); - ret->layers = layers; - if (cfg->note != TONECFG_VARIABLE) { - ret->freq = ver_freq_table[cfg->note]; - } - - do { - UINT8 fractions; - - if (_file_read(fh, &wave, sizeof(wave)) != sizeof(wave)) { - goto li_err3; - } - fractions = wave.fractions; - layer->datasize = LOADINTELDWORD(wave.datasize); - layer->loopstart = LOADINTELDWORD(wave.loopstart); - layer->loopend = LOADINTELDWORD(wave.loopend); - layer->samprate = LOADINTELWORD(wave.samprate); - layer->freqlow = LOADINTELDWORD(wave.freqlow); - layer->freqhigh = LOADINTELDWORD(wave.freqhigh); - layer->freqroot = LOADINTELDWORD(wave.freqroot); - if (cfg->pan == TONECFG_VARIABLE) { - layer->panpot = ((wave.balance * 8) + 4) & 0x7f; - } - else { - layer->panpot = cfg->pan & 0x7f; - } - - if (wave.mode & MODE_LOOPING) { - wave.mode |= MODE_SUSTAIN; - } - if (cfg->flag & TONECFG_NOLOOP) { - wave.mode &= ~(MODE_SUSTAIN | MODE_LOOPING | MODE_PINGPONG | - MODE_REVERSE); - } - if (cfg->flag & TONECFG_NOENV) { - wave.mode &= ~MODE_ENVELOPE; - } - else if (!(cfg->flag & TONECFG_KEEPENV)) { - if (wave.mode & (MODE_LOOPING | MODE_PINGPONG | MODE_REVERSE)) { - if ((!(wave.mode & MODE_SUSTAIN)) || - (!memcmp(wave.env, str_question6, 6)) || - (wave.envpos[5] >= 100)) { - wave.mode &= ~MODE_ENVELOPE; - } - } - else { - wave.mode &= ~(MODE_SUSTAIN | MODE_ENVELOPE); - } - } - - for (i=0; i<6; i++) { - int sft; - sft = ((wave.env[i] >> 6) ^ 3) * 3; - layer->envratetbl[i] = ((((wave.env[i] & 0x3f) << sft) * 44100 - / mod->samprate) * ENV_RATE) << (3 + 1); - layer->envpostbl[i] = wave.envpos[i] << (7 + 9); - } - if ((wave.tre_rate != 0) && (wave.tre_depth != 0)) { - layer->tremolo_step = ((ENV_RATE * wave.tre_rate) - << (SINENT_BIT + TRERATE_SHIFT)) - / (TRERATE_TUNE * mod->samprate); - if (wave.tre_sweep) { - layer->tremolo_sweep = ((ENV_RATE * TRESWEEP_TUNE) - << TRESWEEP_SHIFT) - / (wave.tre_sweep * mod->samprate); - } - layer->tremolo_depth = wave.tre_depth; - } - if ((wave.vib_rate != 0) && (wave.vib_depth != 0)) { - layer->vibrate_rate = (VIBRATE_TUNE * mod->samprate) / - (wave.vib_rate << VIBRATE_SHIFT); - if (wave.vib_sweep) { - layer->vibrate_sweep = - ((VIBRATE_TUNE * VIBSWEEP_TUNE) << VIBSWEEP_SHIFT) / - (wave.vib_sweep * wave.vib_rate << VIBRATE_SHIFT); - } - layer->vibrate_depth = wave.vib_depth; - } - - cnt = layer->datasize; - if (!cnt) { - goto li_err3; - } - if (wave.mode & MODE_16BIT) { - cnt >>= 1; - } - dat = (SAMPLE)_MALLOC((cnt + 1) * sizeof(_SAMPLE), "data"); - if (dat == NULL) { - goto li_err3; - } - layer->data = dat; - if (_file_read(fh, dat, layer->datasize) != (UINT)layer->datasize) { - goto li_err3; - } - dat[cnt] = 0; - if (wave.mode & MODE_16BIT) { - layer->datasize >>= 1; - layer->loopstart >>= 1; - layer->loopend >>= 1; -#if defined(BYTESEX_LITTLE) - if (sizeof(_SAMPLE) != 2) { // Ara!? -#endif - d = (UINT8 *)dat; - d += layer->datasize * 2; - q = dat + layer->datasize; - do { - d -= 2; - q--; - *q = (_SAMPLE)LOADINTELWORD(d); - } while(q > dat); -#if defined(BYTESEX_LITTLE) - } -#endif - } - else { - d = (UINT8 *)dat; - d += layer->datasize; - q = dat + layer->datasize; - do { - d--; - q--; - *q = (_SAMPLE)((*d) * 257); - } while(q > dat); - } - if (wave.mode & MODE_UNSIGNED) { - q = dat + layer->datasize; - do { - q--; - *q -= (_SAMPLE)0x8000; - } while(q > dat); - } - if (wave.mode & MODE_REVERSE) { - p = dat; - q = dat + layer->datasize; - do { - q--; - tmp = *p; - *p = *q; - *q = tmp; - p++; - } while(p < q); - } - - if (cfg->amp == TONECFG_AUTOAMP) { - int sampdat; - int sampmax; - q = (SAMPLE)dat; - cnt = layer->datasize; - sampmax = 32768 / 4; - do { - sampdat = *q++; - if (sampdat < 0) { - sampdat *= -1; - } - sampmax = MAX(sampmax, sampdat); - } while(--cnt); - layer->volume = 32768 * 128 / sampmax; - } - else { - layer->volume = cfg->amp * 128 / 100; - } - - layer->datasize <<= FREQ_SHIFT; - layer->loopstart <<= FREQ_SHIFT; - layer->loopend <<= FREQ_SHIFT; - layer->loopstart |= (fractions & 0x0F) << (FREQ_SHIFT - 4); - layer->loopend |= ((fractions >> 4) & 0x0F) << (FREQ_SHIFT - 4); - - if (layer->loopstart > layer->datasize) { - layer->loopstart = layer->datasize; - } - if (layer->loopend > layer->datasize) { - layer->loopend = layer->datasize; - } - if (wave.mode & MODE_REVERSE) { - cnt = layer->loopstart; - layer->loopstart = layer->datasize - layer->loopend; - layer->loopend = layer->datasize - cnt; - wave.mode &= ~MODE_REVERSE; - wave.mode |= MODE_LOOPING; - } - - if ((ret->freq) && (!(wave.mode & MODE_LOOPING))) { -// TRACEOUT(("resample: %s", cfg->name)); - resample(mod, layer, ret->freq); - } - if (cfg->flag & TONECFG_NOTAIL) { - layer->datasize = layer->loopend; - } - layer->mode = wave.mode; - - layer++; - } while(--layers); - - _file_close(fh); - return(ret); - -li_err3: - inst_destroy(ret); - -li_err2: - _file_close(fh); - -li_err1: - return(NULL); -} - -static void VERMOUTHCL inst_destroy(INSTRUMENT inst) { - - int layers; - INSTLAYER layer; - - if (inst) { - layers = inst->layers; - layer = (INSTLAYER)(inst + 1); - while(layers--) { - if (layer->data) { - _MFREE(layer->data); - } - layer++; - } - _MFREE(inst); - } -} - -int VERMOUTHCL inst_singleload(MIDIMOD mod, UINT bank, UINT num) { - - INSTRUMENT *inst; - INSTRUMENT tone; -const _TONECFG *cfg; - - if (bank >= (MIDI_BANKS * 2)) { - return(MIDIOUT_FAILURE); - } - cfg = mod->tonecfg[bank]; - if (cfg == NULL) { - return(MIDIOUT_FAILURE); - } - inst = mod->tone[bank]; - num &= 0x7f; - if ((inst == NULL) || (inst[num] == NULL)) { - tone = inst_create(mod, cfg + num); - if (tone == NULL) { - return(MIDIOUT_FAILURE); - } - if (inst == NULL) { - inst = (INSTRUMENT *)_MALLOC(sizeof(INSTRUMENT) * 128, "INST"); - if (inst == NULL) { - inst_destroy(tone); - return(MIDIOUT_FAILURE); - } - mod->tone[bank] = inst; - ZeroMemory(inst, sizeof(INSTRUMENT) * 128); - } - inst[num] = tone; - } - return(MIDIOUT_SUCCESS); -} - -int VERMOUTHCL inst_bankload(MIDIMOD mod, UINT bank) { - - return(inst_bankloadex(mod, bank, NULL, NULL)); -} - -int VERMOUTHCL inst_bankloadex(MIDIMOD mod, UINT bank, - FNMIDIOUTLAEXCB cb, MIDIOUTLAEXPARAM *param) { - - INSTRUMENT *inst; - INSTRUMENT tone; -const _TONECFG *cfg; - UINT num; - - if (bank >= (MIDI_BANKS * 2)) { - return(MIDIOUT_FAILURE); - } - cfg = mod->tonecfg[bank]; - if (cfg == NULL) { - return(MIDIOUT_FAILURE); - } - inst = mod->tone[bank]; - for (num = 0; num<0x80; num++) { - if ((inst == NULL) || (inst[num] == NULL)) { - if ((cb != NULL) && (cfg[num].name != NULL)) { - if (param) { - param->progress++; - param->num = num; - } - if ((*cb)(param) != SUCCESS) { - return(MIDIOUT_ABORT); - } - } - tone = inst_create(mod, cfg + num); - if (tone) { -// TRACEOUT(("load %d %d", bank, num)); - if (inst == NULL) { - inst = (INSTRUMENT *)_MALLOC( - sizeof(INSTRUMENT) * 128, "INST"); - if (inst == NULL) { - inst_destroy(tone); - return(MIDIOUT_FAILURE); - } - mod->tone[bank] = inst; - ZeroMemory(inst, sizeof(INSTRUMENT) * 128); - } - inst[num] = tone; - } - } - } - return(MIDIOUT_SUCCESS); -} - -void VERMOUTHCL inst_bankfree(MIDIMOD mod, UINT bank) { - - INSTRUMENT *inst; - INSTRUMENT *i; - - if (bank >= (MIDI_BANKS * 2)) { - return; - } - inst = mod->tone[bank]; - if (inst == NULL) { - return; - } - i = inst + 128; - do { - i--; - inst_destroy(*i); - } while(i > inst); - if (bank >= 2) { - mod->tone[bank] = NULL; - _MFREE(inst); - } - else { - ZeroMemory(inst, sizeof(INSTRUMENT) * 128); - } -} - -UINT VERMOUTHCL inst_gettones(MIDIMOD mod, UINT bank) { - - INSTRUMENT *inst; -const _TONECFG *cfg; - UINT ret; - UINT num; - - if (bank >= (MIDI_BANKS * 2)) { - return(0); - } - cfg = mod->tonecfg[bank]; - if (cfg == NULL) { - return(0); - } - inst = mod->tone[bank]; - ret = 0; - for (num = 0; num<0x80; num++) { - if ((inst == NULL) || (inst[num] == NULL)) { - if (cfg[num].name != NULL) { - ret++; - } - } - } - return(ret); -} +#include +#include +#include "midiout.h" + + +#define _FILEH FILEH +#define _FILEH_INVALID FILEH_INVALID +#define _file_open file_open +#define _file_read file_read +#define _file_close file_close + + +// GUS format references: http://www.onicos.com/staff/iz/formats/guspat.html + +typedef struct { + char sig[12]; + char id[10]; + char description[60]; + + UINT8 instruments; + UINT8 voice; + UINT8 channels; + UINT8 waveforms[2]; + UINT8 volume[2]; + UINT8 datasize[4]; + UINT8 reserved1[36]; + + UINT8 instrument[2]; + UINT8 instname[16]; + UINT8 instsize[4]; + UINT8 layers; + UINT8 reserved2[40]; + + UINT8 layerdupe; + UINT8 layer; + UINT8 layersize[4]; + UINT8 layersamples; + UINT8 reserved3[40]; +} GUSHEAD; + +typedef struct { + UINT8 wavename[7]; + UINT8 fractions; + UINT8 datasize[4]; + UINT8 loopstart[4]; + UINT8 loopend[4]; + UINT8 samprate[2]; + UINT8 freqlow[4]; + UINT8 freqhigh[4]; + UINT8 freqroot[4]; + UINT8 tune[2]; + UINT8 balance; + UINT8 env[6]; + UINT8 envpos[6]; + UINT8 tre_sweep; + UINT8 tre_rate; + UINT8 tre_depth; + UINT8 vib_sweep; + UINT8 vib_rate; + UINT8 vib_depth; + UINT8 mode; + UINT8 scalefreq[2]; + UINT8 scalefactor[2]; + UINT8 reserved[36]; +} GUSWAVE; + + +static void VERMOUTHCL inst_destroy(INSTRUMENT inst); + + +// ---- resample + +#define BASEBITS 9 +#define MIXBASE (1 << BASEBITS) + +static SAMPLE VERMOUTHCL downsamp(SAMPLE dst, SAMPLE src, int count, + int mrate) { + + int rem; + SINT32 pcm; + + rem = MIXBASE; + pcm = 0; + do { + if (rem > mrate) { + rem -= mrate; + pcm += (*src++) * mrate; + } + else { + pcm += (*src) * rem; + pcm >>= BASEBITS; + *dst++ = (_SAMPLE)pcm; + pcm = mrate - rem; + rem = MIXBASE - pcm; + pcm *= (*src++); + } + } while(--count); + if (rem != MIXBASE) { + *dst++ = (_SAMPLE)(pcm >> BASEBITS); + } + return(dst); +} + +static SAMPLE VERMOUTHCL upsamp(SAMPLE dst, SAMPLE src, int count, + int mrate) { + + int rem; + SINT32 tmp; + SINT32 pcm; + SINT32 dat; + + rem = 0; + pcm = 0; + do { + tmp = MIXBASE - rem; + if (tmp >= 0) { + dat = (pcm * rem); + pcm = *src++; + dat += (pcm * tmp); + dat >>= BASEBITS; + *dst++ = (_SAMPLE)dat; + rem = mrate - tmp; + count--; + } + while(rem >= MIXBASE) { + rem -= MIXBASE; + *dst++ = (_SAMPLE)pcm; + } + } while(count); + if (rem) { + *dst++ = rem >> BASEBITS; + } + return(dst); +} + +static void VERMOUTHCL resample(MIDIMOD mod, INSTLAYER inst, int freq) { + + int mrate; + int orgcnt; + int newcnt; + SAMPLE dst; + SAMPLE dstterm; + + mrate = (int)((float)MIXBASE * + (float)mod->samprate / (float)inst->samprate * + (float)inst->freqroot / (float)freq); + if (mrate != MIXBASE) { + orgcnt = inst->datasize >> FREQ_SHIFT; + newcnt = (orgcnt * mrate + MIXBASE - 1) >> BASEBITS; + dst = (SAMPLE)_MALLOC((newcnt + 1) * sizeof(_SAMPLE), "resampled"); + if (dst == NULL) { + return; + } + dst[newcnt] = 0; + if (mrate > MIXBASE) { + dstterm = upsamp(dst, inst->data, orgcnt, mrate); + } + else { + dstterm = downsamp(dst, inst->data, orgcnt, mrate); + } +#if 0 + if ((dstterm - dst) != newcnt) { + TRACEOUT(("resample error %d %d", newcnt, dstterm - dst)); + } +#endif + inst->datasize = newcnt << FREQ_SHIFT; + inst->loopstart = 0; + inst->loopend = newcnt << FREQ_SHIFT; + _MFREE(inst->data); + inst->data = dst; + } + inst->samprate = 0; +} + + +// ---- load + +static const OEMCHAR ext_pat[] = OEMTEXT(".pat"); +static const char sig_GF1PATCH100[] = "GF1PATCH100"; +static const char sig_GF1PATCH110[] = "GF1PATCH110"; +static const char sig_ID000002[] = "ID#000002"; +static const char str_question6[] = "??????"; + +static INSTRUMENT VERMOUTHCL inst_create(MIDIMOD mod, const _TONECFG *cfg) { + + OEMCHAR filename[MAX_PATH]; + OEMCHAR path[MAX_PATH]; + _FILEH fh; + INSTRUMENT ret; + GUSHEAD head; + int layers; + int size; + INSTLAYER layer; + GUSWAVE wave; + int i; + SAMPLE dat; + _SAMPLE tmp; +const UINT8 *d; + SINT16 *p; + SINT16 *q; + int cnt; + + if (cfg->name == NULL) { + goto li_err1; + } + file_cpyname(filename, cfg->name, NELEMENTS(filename)); + file_cutext(filename); + file_catname(filename, ext_pat, NELEMENTS(filename)); + if (midimod_getfile(mod, filename, path, NELEMENTS(path)) != SUCCESS) { + goto li_err1; + } + fh = _file_open(path); + if (fh == _FILEH_INVALID) { +// TRACEOUT(("not found: %s", path)); + goto li_err1; + } + + // head check + if ((_file_read(fh, &head, sizeof(head)) != sizeof(head)) && + (memcmp(head.sig, sig_GF1PATCH100, 12)) && + (memcmp(head.sig, sig_GF1PATCH110, 12)) && + (memcmp(head.id, sig_ID000002, 10)) && + (head.instruments != 0) && (head.instruments != 1) && + (head.layers != 0) && (head.layers != 1)) { + goto li_err2; + } + + layers = head.layersamples; + if (!layers) { + goto li_err2; + } + size = sizeof(_INSTRUMENT) + (layers * sizeof(_INSTLAYER)); + ret = (INSTRUMENT)_MALLOC(size, "instrument"); + if (ret == NULL) { + goto li_err2; + } + ZeroMemory(ret, size); + layer = (INSTLAYER)(ret + 1); + ret->layers = layers; + if (cfg->note != TONECFG_VARIABLE) { + ret->freq = ver_freq_table[cfg->note]; + } + + do { + UINT8 fractions; + + if (_file_read(fh, &wave, sizeof(wave)) != sizeof(wave)) { + goto li_err3; + } + fractions = wave.fractions; + layer->datasize = LOADINTELDWORD(wave.datasize); + layer->loopstart = LOADINTELDWORD(wave.loopstart); + layer->loopend = LOADINTELDWORD(wave.loopend); + layer->samprate = LOADINTELWORD(wave.samprate); + layer->freqlow = LOADINTELDWORD(wave.freqlow); + layer->freqhigh = LOADINTELDWORD(wave.freqhigh); + layer->freqroot = LOADINTELDWORD(wave.freqroot); + if (cfg->pan == TONECFG_VARIABLE) { + layer->panpot = ((wave.balance * 8) + 4) & 0x7f; + } + else { + layer->panpot = cfg->pan & 0x7f; + } + + if (wave.mode & MODE_LOOPING) { + wave.mode |= MODE_SUSTAIN; + } + if (cfg->flag & TONECFG_NOLOOP) { + wave.mode &= ~(MODE_SUSTAIN | MODE_LOOPING | MODE_PINGPONG | + MODE_REVERSE); + } + if (cfg->flag & TONECFG_NOENV) { + wave.mode &= ~MODE_ENVELOPE; + } + else if (!(cfg->flag & TONECFG_KEEPENV)) { + if (wave.mode & (MODE_LOOPING | MODE_PINGPONG | MODE_REVERSE)) { + if ((!(wave.mode & MODE_SUSTAIN)) || + (!memcmp(wave.env, str_question6, 6)) || + (wave.envpos[5] >= 100)) { + wave.mode &= ~MODE_ENVELOPE; + } + } + else { + wave.mode &= ~(MODE_SUSTAIN | MODE_ENVELOPE); + } + } + + for (i=0; i<6; i++) { + int sft; + sft = ((wave.env[i] >> 6) ^ 3) * 3; + layer->envratetbl[i] = ((((wave.env[i] & 0x3f) << sft) * 44100 + / mod->samprate) * ENV_RATE) << (3 + 1); + layer->envpostbl[i] = wave.envpos[i] << (7 + 9); + } + if ((wave.tre_rate != 0) && (wave.tre_depth != 0)) { + layer->tremolo_step = ((ENV_RATE * wave.tre_rate) + << (SINENT_BIT + TRERATE_SHIFT)) + / (TRERATE_TUNE * mod->samprate); + if (wave.tre_sweep) { + layer->tremolo_sweep = ((ENV_RATE * TRESWEEP_TUNE) + << TRESWEEP_SHIFT) + / (wave.tre_sweep * mod->samprate); + } + layer->tremolo_depth = wave.tre_depth; + } + if ((wave.vib_rate != 0) && (wave.vib_depth != 0)) { + layer->vibrate_rate = (VIBRATE_TUNE * mod->samprate) / + (wave.vib_rate << VIBRATE_SHIFT); + if (wave.vib_sweep) { + layer->vibrate_sweep = + ((VIBRATE_TUNE * VIBSWEEP_TUNE) << VIBSWEEP_SHIFT) / + (wave.vib_sweep * wave.vib_rate << VIBRATE_SHIFT); + } + layer->vibrate_depth = wave.vib_depth; + } + + cnt = layer->datasize; + if (!cnt) { + goto li_err3; + } + if (wave.mode & MODE_16BIT) { + cnt >>= 1; + } + dat = (SAMPLE)_MALLOC((cnt + 1) * sizeof(_SAMPLE), "data"); + if (dat == NULL) { + goto li_err3; + } + layer->data = dat; + if (_file_read(fh, dat, layer->datasize) != (UINT)layer->datasize) { + goto li_err3; + } + dat[cnt] = 0; + if (wave.mode & MODE_16BIT) { + layer->datasize >>= 1; + layer->loopstart >>= 1; + layer->loopend >>= 1; +#if defined(BYTESEX_LITTLE) + if (sizeof(_SAMPLE) != 2) { // Ara!? +#endif + d = (UINT8 *)dat; + d += layer->datasize * 2; + q = dat + layer->datasize; + do { + d -= 2; + q--; + *q = (_SAMPLE)LOADINTELWORD(d); + } while(q > dat); +#if defined(BYTESEX_LITTLE) + } +#endif + } + else { + d = (UINT8 *)dat; + d += layer->datasize; + q = dat + layer->datasize; + do { + d--; + q--; + *q = (_SAMPLE)((*d) * 257); + } while(q > dat); + } + if (wave.mode & MODE_UNSIGNED) { + q = dat + layer->datasize; + do { + q--; + *q -= (_SAMPLE)0x8000; + } while(q > dat); + } + if (wave.mode & MODE_REVERSE) { + p = dat; + q = dat + layer->datasize; + do { + q--; + tmp = *p; + *p = *q; + *q = tmp; + p++; + } while(p < q); + } + + if (cfg->amp == TONECFG_AUTOAMP) { + int sampdat; + int sampmax; + q = (SAMPLE)dat; + cnt = layer->datasize; + sampmax = 32768 / 4; + do { + sampdat = *q++; + if (sampdat < 0) { + sampdat *= -1; + } + sampmax = MAX(sampmax, sampdat); + } while(--cnt); + layer->volume = 32768 * 128 / sampmax; + } + else { + layer->volume = cfg->amp * 128 / 100; + } + + layer->datasize <<= FREQ_SHIFT; + layer->loopstart <<= FREQ_SHIFT; + layer->loopend <<= FREQ_SHIFT; + layer->loopstart |= (fractions & 0x0F) << (FREQ_SHIFT - 4); + layer->loopend |= ((fractions >> 4) & 0x0F) << (FREQ_SHIFT - 4); + + if (layer->loopstart > layer->datasize) { + layer->loopstart = layer->datasize; + } + if (layer->loopend > layer->datasize) { + layer->loopend = layer->datasize; + } + if (wave.mode & MODE_REVERSE) { + cnt = layer->loopstart; + layer->loopstart = layer->datasize - layer->loopend; + layer->loopend = layer->datasize - cnt; + wave.mode &= ~MODE_REVERSE; + wave.mode |= MODE_LOOPING; + } + + if ((ret->freq) && (!(wave.mode & MODE_LOOPING))) { +// TRACEOUT(("resample: %s", cfg->name)); + resample(mod, layer, ret->freq); + } + if (cfg->flag & TONECFG_NOTAIL) { + layer->datasize = layer->loopend; + } + layer->mode = wave.mode; + + layer++; + } while(--layers); + + _file_close(fh); + return(ret); + +li_err3: + inst_destroy(ret); + +li_err2: + _file_close(fh); + +li_err1: + return(NULL); +} + +static void VERMOUTHCL inst_destroy(INSTRUMENT inst) { + + int layers; + INSTLAYER layer; + + if (inst) { + layers = inst->layers; + layer = (INSTLAYER)(inst + 1); + while(layers--) { + if (layer->data) { + _MFREE(layer->data); + } + layer++; + } + _MFREE(inst); + } +} + +int VERMOUTHCL inst_singleload(MIDIMOD mod, UINT bank, UINT num) { + + INSTRUMENT *inst; + INSTRUMENT tone; +const _TONECFG *cfg; + + if (bank >= (MIDI_BANKS * 2)) { + return(MIDIOUT_FAILURE); + } + cfg = mod->tonecfg[bank]; + if (cfg == NULL) { + return(MIDIOUT_FAILURE); + } + inst = mod->tone[bank]; + num &= 0x7f; + if ((inst == NULL) || (inst[num] == NULL)) { + tone = inst_create(mod, cfg + num); + if (tone == NULL) { + return(MIDIOUT_FAILURE); + } + if (inst == NULL) { + inst = (INSTRUMENT *)_MALLOC(sizeof(INSTRUMENT) * 128, "INST"); + if (inst == NULL) { + inst_destroy(tone); + return(MIDIOUT_FAILURE); + } + mod->tone[bank] = inst; + ZeroMemory(inst, sizeof(INSTRUMENT) * 128); + } + inst[num] = tone; + } + return(MIDIOUT_SUCCESS); +} + +int VERMOUTHCL inst_bankload(MIDIMOD mod, UINT bank) { + + return(inst_bankloadex(mod, bank, NULL, NULL)); +} + +int VERMOUTHCL inst_bankloadex(MIDIMOD mod, UINT bank, + FNMIDIOUTLAEXCB cb, MIDIOUTLAEXPARAM *param) { + + INSTRUMENT *inst; + INSTRUMENT tone; +const _TONECFG *cfg; + UINT num; + + if (bank >= (MIDI_BANKS * 2)) { + return(MIDIOUT_FAILURE); + } + cfg = mod->tonecfg[bank]; + if (cfg == NULL) { + return(MIDIOUT_FAILURE); + } + inst = mod->tone[bank]; + for (num = 0; num<0x80; num++) { + if ((inst == NULL) || (inst[num] == NULL)) { + if ((cb != NULL) && (cfg[num].name != NULL)) { + if (param) { + param->progress++; + param->num = num; + } + if ((*cb)(param) != SUCCESS) { + return(MIDIOUT_ABORT); + } + } + tone = inst_create(mod, cfg + num); + if (tone) { +// TRACEOUT(("load %d %d", bank, num)); + if (inst == NULL) { + inst = (INSTRUMENT *)_MALLOC( + sizeof(INSTRUMENT) * 128, "INST"); + if (inst == NULL) { + inst_destroy(tone); + return(MIDIOUT_FAILURE); + } + mod->tone[bank] = inst; + ZeroMemory(inst, sizeof(INSTRUMENT) * 128); + } + inst[num] = tone; + } + } + } + return(MIDIOUT_SUCCESS); +} + +void VERMOUTHCL inst_bankfree(MIDIMOD mod, UINT bank) { + + INSTRUMENT *inst; + INSTRUMENT *i; + + if (bank >= (MIDI_BANKS * 2)) { + return; + } + inst = mod->tone[bank]; + if (inst == NULL) { + return; + } + i = inst + 128; + do { + i--; + inst_destroy(*i); + } while(i > inst); + if (bank >= 2) { + mod->tone[bank] = NULL; + _MFREE(inst); + } + else { + ZeroMemory(inst, sizeof(INSTRUMENT) * 128); + } +} + +UINT VERMOUTHCL inst_gettones(MIDIMOD mod, UINT bank) { + + INSTRUMENT *inst; +const _TONECFG *cfg; + UINT ret; + UINT num; + + if (bank >= (MIDI_BANKS * 2)) { + return(0); + } + cfg = mod->tonecfg[bank]; + if (cfg == NULL) { + return(0); + } + inst = mod->tone[bank]; + ret = 0; + for (num = 0; num<0x80; num++) { + if ((inst == NULL) || (inst[num] == NULL)) { + if (cfg[num].name != NULL) { + ret++; + } + } + } + return(ret); +} diff --git a/sound/vermouth/midinst.h b/sound/vermouth/midinst.h old mode 100755 new mode 100644 index 9e444609..48a07708 --- a/sound/vermouth/midinst.h +++ b/sound/vermouth/midinst.h @@ -1,71 +1,71 @@ - -typedef SINT16 _SAMPLE; -typedef SINT16 *SAMPLE; - -enum { - MODE_16BIT = 0x01, - MODE_UNSIGNED = 0x02, - MODE_LOOPING = 0x04, - MODE_PINGPONG = 0x08, - MODE_REVERSE = 0x10, - MODE_SUSTAIN = 0x20, - MODE_ENVELOPE = 0x40 -}; - -typedef struct { - int sweep; - int step; -} INSTTRE; - -typedef struct { - int sweep; - int rate; -} INSTVIB; - -typedef struct { - SAMPLE data; - int loopstart; - int loopend; - int datasize; - int samprate; - int freqlow; - int freqhigh; - int freqroot; - int envratetbl[6]; - int envpostbl[6]; - int volume; - int tremolo_sweep; - int tremolo_step; - int vibrate_sweep; - int vibrate_rate; - UINT8 tremolo_depth; - UINT8 vibrate_depth; - UINT8 mode; - UINT8 panpot; -} _INSTLAYER, *INSTLAYER; - -typedef struct { - int layers; - int freq; -} _INSTRUMENT, *INSTRUMENT; - -struct _miditoneloadparam; -typedef struct _miditoneloadparam MIDIOUTLAEXPARAM; -typedef int (VERMOUTHCL *FNMIDIOUTLAEXCB)(MIDIOUTLAEXPARAM *param); - - -#ifdef __cplusplus -extern "C" { -#endif - -int VERMOUTHCL inst_singleload(MIDIMOD mod, UINT bank, UINT num); -int VERMOUTHCL inst_bankload(MIDIMOD mod, UINT bank); -int VERMOUTHCL inst_bankloadex(MIDIMOD mod, UINT bank, - FNMIDIOUTLAEXCB cb, MIDIOUTLAEXPARAM *param); -void VERMOUTHCL inst_bankfree(MIDIMOD mod, UINT bank); -UINT VERMOUTHCL inst_gettones(MIDIMOD mod, UINT bank); - -#ifdef __cplusplus -} -#endif - + +typedef SINT16 _SAMPLE; +typedef SINT16 *SAMPLE; + +enum { + MODE_16BIT = 0x01, + MODE_UNSIGNED = 0x02, + MODE_LOOPING = 0x04, + MODE_PINGPONG = 0x08, + MODE_REVERSE = 0x10, + MODE_SUSTAIN = 0x20, + MODE_ENVELOPE = 0x40 +}; + +typedef struct { + int sweep; + int step; +} INSTTRE; + +typedef struct { + int sweep; + int rate; +} INSTVIB; + +typedef struct { + SAMPLE data; + int loopstart; + int loopend; + int datasize; + int samprate; + int freqlow; + int freqhigh; + int freqroot; + int envratetbl[6]; + int envpostbl[6]; + int volume; + int tremolo_sweep; + int tremolo_step; + int vibrate_sweep; + int vibrate_rate; + UINT8 tremolo_depth; + UINT8 vibrate_depth; + UINT8 mode; + UINT8 panpot; +} _INSTLAYER, *INSTLAYER; + +typedef struct { + int layers; + int freq; +} _INSTRUMENT, *INSTRUMENT; + +struct _miditoneloadparam; +typedef struct _miditoneloadparam MIDIOUTLAEXPARAM; +typedef int (VERMOUTHCL *FNMIDIOUTLAEXCB)(MIDIOUTLAEXPARAM *param); + + +#ifdef __cplusplus +extern "C" { +#endif + +int VERMOUTHCL inst_singleload(MIDIMOD mod, UINT bank, UINT num); +int VERMOUTHCL inst_bankload(MIDIMOD mod, UINT bank); +int VERMOUTHCL inst_bankloadex(MIDIMOD mod, UINT bank, + FNMIDIOUTLAEXCB cb, MIDIOUTLAEXPARAM *param); +void VERMOUTHCL inst_bankfree(MIDIMOD mod, UINT bank); +UINT VERMOUTHCL inst_gettones(MIDIMOD mod, UINT bank); + +#ifdef __cplusplus +} +#endif + diff --git a/sound/vermouth/midiout.c b/sound/vermouth/midiout.c old mode 100755 new mode 100644 index daf0a39b..3782048e --- a/sound/vermouth/midiout.c +++ b/sound/vermouth/midiout.c @@ -1,1250 +1,1250 @@ -#include -#include "midiout.h" - - -#define MIDIOUT_VERSION 0x116 -#define MIDIOUT_VERSTRING "VERMOUTH 1.16" - -static const char vermouthver[] = MIDIOUT_VERSTRING; - -static const int gaintbl[24+1] = - { 16, 19, 22, 26, 32, 38, 45, 53, - 64, 76, 90, 107, 128, 152, 181, 215, - 256, 304, 362, 430, 512, 608, 724, 861, 1024}; - - -// ---- voice - -#define VOICEHDLPTR(hdl) ((hdl)->voice) -#define VOICEHDLEND(hdl) (VOICE)((hdl) + 1) - -static void VERMOUTHCL voice_volupdate(VOICE v) { - - CHANNEL ch; - int vol; - - ch = v->channel; -#if defined(VOLUME_ACURVE) - vol = ch->level * acurve[v->velocity]; - vol >>= 8; -#else - vol = ch->level * v->velocity; - vol >>= 7; -#endif - vol *= v->sample->volume; - vol >>= (21 - 16); -#if defined(PANPOT_REVA) - switch(v->flag & VOICE_MIXMASK) { - case VOICE_MIXNORMAL: - v->volleft = (vol * revacurve[v->panpot ^ 127]) >> 8; - v->volright = (vol * revacurve[v->panpot]) >> 8; - break; - - case VOICE_MIXCENTRE: - v->volleft = (vol * 155) >> 8; - break; - - default: - v->volleft = vol; - break; - } -#else - v->volleft = vol; - if ((v->flag & VOICE_MIXMASK) == VOICE_MIXNORMAL) { - if (v->panpot < 64) { - vol *= (v->panpot + 1); - vol >>= 6; - v->volright = vol; - } - else { - v->volright = vol; - vol *= (127 - v->panpot); - vol >>= 6; - v->volleft = vol; - } - } -#endif -} - -static INSTLAYER VERMOUTHCL selectlayer(VOICE v, INSTRUMENT inst) { - - int layers; - INSTLAYER layer; - INSTLAYER layerterm; - int freq; - int diffmin; - int diff; - INSTLAYER layersel; - - layers = inst->layers; - layer = (INSTLAYER)(inst + 1); - - if (layers == 1) { - return(layer); - } - - layerterm = layer + layers; - freq = v->frequency; - do { - if ((freq >= layer->freqlow) && (freq <= layer->freqhigh)) { - return(layer); - } - layer++; - } while(layer < layerterm); - - layer = (INSTLAYER)(inst + 1); - layersel = layer; - diffmin = layer->freqroot - freq; - if (diffmin < 0) { - diffmin *= -1; - } - layer++; - do { - diff = layer->freqroot - freq; - if (diff < 0) { - diff *= -1; - } - if (diffmin > diff) { - diffmin = diff; - layersel = layer; - } - layer++; - } while(layer < layerterm); - return(layersel); -} - -static void VERMOUTHCL freq_update(VOICE v) { - - CHANNEL ch; - float step; - - if (v->flag & VOICE_FIXPITCH) { - return; - } - - ch = v->channel; - step = v->freq; - if (ch->pitchbend != 0x2000) { - step *= ch->pitchfactor; - } -#if defined(ENABLE_VIRLATE) - v->freqnow = step; -#endif - step *= (float)(1 << FREQ_SHIFT); - if (v->sampstep < 0) { - step *= -1.0; - } - v->sampstep = (int)step; -} - -static void VERMOUTHCL voice_on(MIDIHDL hdl, CHANNEL ch, VOICE v, int key, - int vel) { - - INSTRUMENT inst; - INSTLAYER layer; - int panpot; - - key &= 0x7f; - if (!(ch->flag & CHANNEL_RHYTHM)) { - inst = ch->inst; - if (inst == NULL) { - return; - } - if (inst->freq) { - v->frequency = inst->freq; - } - else { - v->frequency = ver_freq_table[key]; - } - layer = selectlayer(v, inst); - } - else { -#if !defined(MIDI_GMONLY) - inst = ch->rhythm[key]; - if (inst == NULL) { - inst = hdl->bank0[1][key]; - } -#else - inst = hdl->bank0[1][key]; -#endif - if (inst == NULL) { - return; - } - layer = (INSTLAYER)(inst + 1); - if (inst->freq) { - v->frequency = inst->freq; - } - else { - v->frequency = ver_freq_table[key]; - } - } - v->sample = layer; - - v->phase = VOICE_ON; - v->channel = ch; - v->note = key; - v->velocity = vel; - v->samppos = 0; - v->sampstep = 0; - -#if defined(ENABLE_TREMOLO) - v->tremolo.count = 0; - v->tremolo.step = layer->tremolo_step; - v->tremolo.sweepstep = layer->tremolo_sweep; - v->tremolo.sweepcount = 0; -#endif - -#if defined(ENABLE_VIRLATE) - v->vibrate.sweepstep = layer->vibrate_sweep; - v->vibrate.sweepcount = 0; - v->vibrate.rate = layer->vibrate_rate; - v->vibrate.count = 0; - v->vibrate.phase = 0; -#endif - - if (!(ch->flag & CHANNEL_RHYTHM)) { - panpot = ch->panpot; - } - else { - panpot = layer->panpot; - } -#if defined(PANPOT_REVA) - if (panpot == 64) { - v->flag = VOICE_MIXCENTRE; - } - else if (panpot < 3) { - v->flag = VOICE_MIXLEFT; - } - else if (panpot >= 126) { - v->flag = VOICE_MIXRIGHT; - } - else { - v->flag = VOICE_MIXNORMAL; - v->panpot = panpot; - } -#else - if ((panpot >= 60) && (panpot < 68)) { - v->flag = VOICE_MIXCENTRE; - } - else if (panpot < 5) { - v->flag = VOICE_MIXLEFT; - } - else if (panpot >= 123) { - v->flag = VOICE_MIXRIGHT; - } - else { - v->flag = VOICE_MIXNORMAL; - v->panpot = panpot; - } -#endif - if (!layer->samprate) { - v->flag |= VOICE_FIXPITCH; - } - else { - v->freq = (float)layer->samprate / (float)hdl->samprate * - (float)v->frequency / (float)layer->freqroot; - } - voice_setphase(v, VOICE_ON); - freq_update(v); - voice_volupdate(v); - v->envcount = 0; - if (layer->mode & MODE_ENVELOPE) { - v->envvol = 0; - envlope_setphase(v, 0); - } - else { - v->envstep = 0; - } - voice_setmix(v); - envelope_updates(v); -} - -static void VERMOUTHCL voice_off(VOICE v) { - - voice_setphase(v, VOICE_OFF); - if (v->sample->mode & MODE_ENVELOPE) { - envlope_setphase(v, 3); - voice_setmix(v); - envelope_updates(v); - } -} - -static void VERMOUTHCL allresetvoices(MIDIHDL hdl) { - - VOICE v; - VOICE vterm; - - v = VOICEHDLPTR(hdl); - vterm = VOICEHDLEND(hdl); - do { - voice_setfree(v); - v++; - } while(v < vterm); -} - - -// ---- key - -static void VERMOUTHCL key_on(MIDIHDL hdl, CHANNEL ch, int key, int vel) { - - VOICE v; - VOICE v1; - VOICE v2; - int vol; - int volmin; - - v = NULL; - v1 = VOICEHDLPTR(hdl); - v2 = VOICEHDLEND(hdl); - do { - v2--; - if (v2->phase == VOICE_FREE) { - v = v2; - } - else if ((v2->channel == ch) && - ((v2->note == key) || (ch->flag & CHANNEL_MONO))) { - voice_setphase(v2, VOICE_REL); - voice_setmix(v2); - } - } while(v1 < v2); - - if (v != NULL) { - voice_on(hdl, ch, v, key, vel); - return; - } - - volmin = 0x7fffffff; - v2 = VOICEHDLEND(hdl); - do { - v2--; - if (!(v2->phase & (VOICE_ON | VOICE_REL))) { - vol = v2->envleft; - if ((v2->flag & VOICE_MIXMASK) == VOICE_MIXNORMAL) { - vol = MAX(vol, v2->envright); - } - if (volmin > vol) { - volmin = vol; - v = v2; - } - } - } while(v1 < v2); - - if (v != NULL) { - voice_setfree(v); - voice_on(hdl, ch, v, key, vel); - } -} - -static void VERMOUTHCL key_off(MIDIHDL hdl, CHANNEL ch, int key) { - - VOICE v; - VOICE vterm; - - v = VOICEHDLPTR(hdl); - vterm = VOICEHDLEND(hdl); - do { - if ((v->phase & VOICE_ON) && - (v->channel == ch) && (v->note == key)) { - if (ch->flag & CHANNEL_SUSTAIN) { - voice_setphase(v, VOICE_SUSTAIN); - } - else { - voice_off(v); - } - return; - } - v++; - } while(v < vterm); -} - -static void VERMOUTHCL key_pressure(MIDIHDL hdl, CHANNEL ch, int key, - int vel) { - - VOICE v; - VOICE vterm; - - v = VOICEHDLPTR(hdl); - vterm = VOICEHDLEND(hdl); - do { - if ((v->phase & VOICE_ON) && - (v->channel == ch) && (v->note == key)) { - v->velocity = vel; - voice_volupdate(v); - envelope_updates(v); - break; - } - v++; - } while(v < vterm); -} - - -// ---- control - -static void VERMOUTHCL volumeupdate(MIDIHDL hdl, CHANNEL ch) { - - VOICE v; - VOICE vterm; - -#if defined(VOLUME_ACURVE) - ch->level = (hdl->level * acurve[ch->volume] * ch->expression) >> 15; -#else - ch->level = (hdl->level * ch->volume * ch->expression) >> 14; -#endif - v = VOICEHDLPTR(hdl); - vterm = VOICEHDLEND(hdl); - do { - if ((v->phase & (VOICE_ON | VOICE_SUSTAIN)) && (v->channel == ch)) { - voice_volupdate(v); - envelope_updates(v); - } - v++; - } while(v < vterm); -} - -static void VERMOUTHCL pedaloff(MIDIHDL hdl, CHANNEL ch) { - - VOICE v; - VOICE vterm; - - v = VOICEHDLPTR(hdl); - vterm = VOICEHDLEND(hdl); - do { - if ((v->phase & VOICE_SUSTAIN) && (v->channel == ch)) { - voice_off(v); - } - v++; - } while(v < vterm); -} - -static void VERMOUTHCL allsoundsoff(MIDIHDL hdl, CHANNEL ch) { - - VOICE v; - VOICE vterm; - - v = VOICEHDLPTR(hdl); - vterm = VOICEHDLEND(hdl); - do { - if ((v->phase != VOICE_FREE) && (v->channel == ch)) { - voice_setphase(v, VOICE_REL); - voice_setmix(v); - } - v++; - } while(v < vterm); -} - -static void VERMOUTHCL resetallcontrollers(CHANNEL ch) { - - ch->flag &= CHANNEL_MASK; - if (ch->flag == 9) { - ch->flag |= CHANNEL_RHYTHM; - } - ch->volume = 90; - ch->expression = 127; - ch->pitchbend = 0x2000; - ch->pitchfactor = 1.0; -} - -static void VERMOUTHCL allnotesoff(MIDIHDL hdl, CHANNEL ch) { - - VOICE v; - VOICE vterm; - - v = VOICEHDLPTR(hdl); - vterm = VOICEHDLEND(hdl); - do { -#if 1 - if ((v->phase & (VOICE_ON | VOICE_SUSTAIN)) && (v->channel == ch)) { - voice_off(v); - } -#else - if ((v->phase & VOICE_ON) && (v->channel == ch)) { - if (ch->flag & CHANNEL_SUSTAIN) { - voice_setphase(v, VOICE_SUSTAIN); - } - else { - voice_off(v); - } - } -#endif - v++; - } while(v < vterm); -} - -static void VERMOUTHCL ctrlchange(MIDIHDL hdl, CHANNEL ch, int ctrl, - int val) { - - val &= 0x7f; - switch(ctrl & 0x7f) { -#if !defined(MIDI_GMONLY) - case CTRL_PGBANK: -#if defined(ENABLE_GSRX) - if (!(ch->gsrx[2] & GSRX2_BANKSELECT)) { - break; - } -#endif - ch->bank = val; - break; -#endif - - case CTRL_DATA_M: -// TRACEOUT(("data: %x %x %x", c->rpn_l, c->rpn_m, val)); - if ((ch->rpn_l == 0) && (ch->rpn_m == 0)) { - if (val >= 24) { - val = 24; - } - ch->pitchsens = val; - } - break; - - case CTRL_VOLUME: - ch->volume = val; - volumeupdate(hdl, ch); - break; - - case CTRL_PANPOT: - ch->panpot = val; - break; - - case CTRL_EXPRESS: - ch->expression = val; - volumeupdate(hdl, ch); - break; - - case CTRL_PEDAL: - if (val == 0) { - ch->flag &= ~CHANNEL_SUSTAIN; - pedaloff(hdl, ch); - } - else { - ch->flag |= CHANNEL_SUSTAIN; - } - break; - - case CTRL_RPN_L: - ch->rpn_l = val; - break; - - case CTRL_RPN_M: - ch->rpn_m = val; - break; - - case CTRL_SOUNDOFF: - allsoundsoff(hdl, ch); - break; - - case CTRL_RESETCTRL: - resetallcontrollers(ch); - /*FALLTHROUGH*/ - - case CTRL_NOTEOFF: - allnotesoff(hdl, ch); - break; - - case CTRL_MONOON: - ch->flag |= CHANNEL_MONO; - break; - - case CTRL_POLYON: - ch->flag &= ~CHANNEL_MONO; - break; - - default: -// TRACEOUT(("ctrl: %x %x", ctrl, val); - break; - } -} - -static void VERMOUTHCL progchange(MIDIHDL hdl, CHANNEL ch, int val) { - -#if !defined(MIDI_GMONLY) - MIDIMOD mod; - INSTRUMENT *bank; - INSTRUMENT inst; - - mod = hdl->module; - inst = NULL; - if (ch->bank < MIDI_BANKS) { - bank = mod->tone[ch->bank * 2]; - if (bank) { - inst = bank[val]; - } - } - if (inst == NULL) { - bank = hdl->bank0[0]; - inst = bank[val]; - } - ch->inst = inst; - - bank = NULL; - if (ch->bank < MIDI_BANKS) { - bank = mod->tone[ch->bank * 2 + 1]; - } - if (bank == NULL) { - bank = hdl->bank0[1]; - } - ch->rhythm = bank; -#else - ch->inst = hdl->bank0[0][val]; -#endif - ch->program = val; -} - -static void VERMOUTHCL chpressure(MIDIHDL hdl, CHANNEL ch, int vel) { - - VOICE v; - VOICE vterm; - - v = VOICEHDLPTR(hdl); - vterm = VOICEHDLEND(hdl); - do { - if ((v->phase & VOICE_ON) && (v->channel == ch)) { - v->velocity = vel; - voice_volupdate(v); - envelope_updates(v); - break; - } - v++; - } while(v < vterm); -} - -static void VERMOUTHCL pitchbendor(MIDIHDL hdl, CHANNEL ch, int val1, - int val2) { - - VOICE v; - VOICE vterm; - - val1 &= 0x7f; - val1 += (val2 & 0x7f) << 7; - if (1) { - ch->pitchbend = val1; - val1 -= 0x2000; - if (!val1) { - ch->pitchfactor = 1.0; - } - else { - val1 *= ch->pitchsens; - ch->pitchfactor = bendhtbl[(val1 >> (6 + 7)) + 24] * - bendltbl[(val1 >> 7) & 0x3f]; - } - v = VOICEHDLPTR(hdl); - vterm = VOICEHDLEND(hdl); - do { - if ((v->phase != VOICE_FREE) && (v->channel == ch)) { - freq_update(v); - } - v++; - } while(v < vterm); - } -} - -static void VERMOUTHCL allvolupdate(MIDIHDL hdl) { - - int level; - CHANNEL ch; - CHANNEL chterm; - VOICE v; - VOICE vterm; - - level = gaintbl[hdl->gain + 16] >> 1; - level *= hdl->master; - hdl->level = level; - ch = hdl->channel; - chterm = ch + CHANNEL_MAX; - do { - ch->level = (level * ch->volume * ch->expression) >> 14; - ch++; - } while(ch < chterm); - v = VOICEHDLPTR(hdl); - vterm = VOICEHDLEND(hdl); - do { - if (v->phase & (VOICE_ON | VOICE_SUSTAIN)) { - voice_volupdate(v); - envelope_updates(v); - } - v++; - } while(v < vterm); -} - -#if defined(ENABLE_GSRX) -static void VERMOUTHCL allresetmidi(MIDIHDL hdl, BOOL gs) -#else -#define allresetmidi(m, g) _allresetmidi(m) -static void VERMOUTHCL _allresetmidi(MIDIHDL hdl) -#endif -{ - CHANNEL ch; - CHANNEL chterm; - UINT flag; - - hdl->master = 127; - ch = hdl->channel; - chterm = ch + CHANNEL_MAX; - ZeroMemory(ch, sizeof(_CHANNEL) * CHANNEL_MAX); - flag = 0; - do { - ch->flag = flag++; - ch->pitchsens = 2; -#if !defined(MIDI_GMONLY) - ch->bank = 0; -#endif - ch->panpot = 64; - progchange(hdl, ch, 0); - resetallcontrollers(ch); -#if defined(ENABLE_GSRX) - ch->keyshift = 0x40; - ch->noterange[0] = 0x00; - ch->noterange[1] = 0x7f; - if (gs) { - ch->gsrx[0] = 0xff; - ch->gsrx[1] = 0xff; - ch->gsrx[2] = 0xff; - } - else { - ch->gsrx[0] = 0x7f; - ch->gsrx[1] = 0xff; - ch->gsrx[2] = 0x02; - } -#endif - ch++; - } while(ch < chterm); - allresetvoices(hdl); - allvolupdate(hdl); -} - - -// ---- - -VEXTERN UINT VEXPORT midiout_getver(char *string, UINT leng) { - - leng = MIN(leng, sizeof(vermouthver)); - CopyMemory(string, vermouthver, leng); - return((MIDIOUT_VERSION << 8) | 0x00); -} - -VEXTERN MIDIHDL VEXPORT midiout_create(MIDIMOD mod, UINT worksize) { - - UINT size; - MIDIHDL ret; - - if (mod == NULL) { - return(NULL); - } - worksize = MIN(worksize, 512U); - worksize = MAX(worksize, 16384U); - size = sizeof(_MIDIHDL); - size += sizeof(SINT32) * 2 * worksize; - size += sizeof(_SAMPLE) * worksize; - ret = (MIDIHDL)_MALLOC(size, "MIDIHDL"); - if (ret) { - midimod_lock(mod); - ZeroMemory(ret, size); - ret->samprate = mod->samprate; - ret->worksize = worksize; - ret->module = mod; - // ret->master = 127; - ret->bank0[0] = mod->tone[0]; - ret->bank0[1] = mod->tone[1]; - ret->sampbuf = (SINT32 *)(ret + 1); - ret->resampbuf = (SAMPLE)(ret->sampbuf + worksize * 2); - allresetmidi(ret, FALSE); - } - return(ret); -} - -VEXTERN void VEXPORT midiout_destroy(MIDIHDL hdl) { - - MIDIMOD mod; - - if (hdl) { - mod = hdl->module; - _MFREE(hdl); - midimod_lock(mod); - } -} - -VEXTERN void VEXPORT midiout_shortmsg(MIDIHDL hdl, UINT32 msg) { - - UINT cmd; - CHANNEL ch; - - if (hdl == NULL) { - return; - } - cmd = msg & 0xff; - if (cmd & 0x80) { - hdl->status = cmd; - } - else { - msg <<= 8; - msg += hdl->status; - } - ch = hdl->channel + (cmd & 0x0f); - switch((cmd >> 4) & 7) { - case (MIDI_NOTE_OFF >> 4) & 7: - key_off(hdl, ch, (msg >> 8) & 0x7f); - break; - - case (MIDI_NOTE_ON >> 4) & 7: - if (msg & (0x7f << 16)) { - key_on(hdl, ch, (msg >> 8) & 0x7f, (msg >> 16) & 0x7f); - } - else { - key_off(hdl, ch, (msg >> 8) & 0x7f); - } - break; - - case (MIDI_KEYPRESS >> 4) & 7: - key_pressure(hdl, ch, (msg >> 8) & 0x7f, (msg >> 16) & 0x7f); - break; - - case (MIDI_CTRLCHANGE >> 4) & 7: - ctrlchange(hdl, ch, (msg >> 8) & 0x7f, (msg >> 16) & 0x7f); - break; - - case (MIDI_PROGCHANGE >> 4) & 7: - progchange(hdl, ch, (msg >> 8) & 0x7f); - break; - - case (MIDI_CHPRESS >> 4) & 7: - chpressure(hdl, ch, (msg >> 8) & 0x7f); - break; - - case (MIDI_PITCHBEND >> 4) & 7: - pitchbendor(hdl, ch, (msg >> 8) & 0x7f, (msg >> 16) & 0x7f); - break; - } -} - -static void VERMOUTHCL longmsg_uni(MIDIHDL hdl, const UINT8 *msg, UINT size) { - - if ((size >= 6) && (msg[2] == 0x7f)) { - switch(msg[3]) { - case 0x04: - if ((msg[4] == 0x01) && (size >= 8)) { - hdl->master = msg[6] & 0x7f; - allvolupdate(hdl); - } - break; - } - } -} - -static void VERMOUTHCL longmsg_gm(MIDIHDL hdl, const UINT8 *msg, UINT size) { - - if ((size >= 6) && (msg[2] == 0x7f)) { - switch(msg[3]) { - case 0x09: - if (msg[4] == 0x01) { - allresetmidi(hdl, FALSE); // GM reset - break; - } -#if !defined(MIDI_GMONLY) - else if ((msg[4] == 0x02) || (msg[4] == 0x03)) { - allresetmidi(hdl, TRUE); // GM reset - break; - } -#endif - break; - } - } -} - -static void VERMOUTHCL rolandcmd4(MIDIHDL hdl, UINT addr, UINT8 data) { - - UINT part; - CHANNEL ch; -#if defined(ENABLE_GSRX) - UINT8 bit; -#endif - - addr = addr & 0x000fffff; - if (addr == 0x00004) { // Vol - hdl->master = data; - allvolupdate(hdl); - } - else if ((addr & (~0xff)) == 0x00100) { - const UINT pos = addr & 0xff; - if (pos < 0x30) { // Patch Name - } - else { - switch(addr & 0xff) { - case 0x30: // Reverb Macro - case 0x31: // Reverb Charactor - case 0x32: // Reverb Pre-LPF - case 0x33: // Reverb Level - case 0x34: // Reverb Time - case 0x35: // Reverb Delay FeedBack - case 0x37: // Reverb Predelay Time - case 0x38: // Chorus Macro - case 0x39: // Chorus Pre-LPF - case 0x3a: // Chorus Level - case 0x3b: // Chorus FeedBack - case 0x3c: // Chorus Delay - case 0x3d: // Chorus Rate - case 0x3e: // Chorus Depth - case 0x3f: // Chorus send level to reverb - case 0x40: // Chorus send level to delay - case 0x50: // Delay Macro - case 0x51: // Delay Time Pre-LPF - case 0x52: // Delay Time Center - case 0x53: // Delay Time Ratio Left - case 0x54: // Delay Time Ratio Right - case 0x55: // Delay Level Center - case 0x56: // Delay Level Left - case 0x57: // Delay Level Right - case 0x58: // Delay Level - case 0x59: // Delay Freeback - case 0x5a: // Delay sendlevel to Reverb - break; - } - } - } - else if ((addr & (~(0x0fff))) == 0x01000) { // GS CH - part = (addr >> 8) & 0x0f; - if (part == 0) { // part10 - part = 9; - } - else if (part < 10) { // part1-9 - part--; - } - ch = hdl->channel + part; - switch(addr & 0xff) { -#if !defined(MIDI_GMONLY) - case 0x00: // TONE NUMBER - ch->bank = data; - break; -#endif - - case 0x01: // PROGRAM NUMBER - progchange(hdl, ch, data); - break; - - case 0x02: // Rx.CHANNEL - TRACEOUT(("RxCHANNEL: %d", data)); - break; - -#if defined(ENABLE_GSRX) - case 0x03: // Rx.PITCHBEND - case 0x04: // Rx.CH PRESSURE - case 0x05: // Rx.PROGRAM CHANGE - case 0x06: // Rx.CONTROL CHANGE - case 0x07: // Rx.POLY PRESSURE - case 0x08: // Rx.NOTE MESSAGE - case 0x09: // Rx.PRN - case 0x0a: // Rx.NRPN - bit = 1 << ((addr - 0x03) & 7); - if (data == 0) { - ch->gsrx[0] = ch->gsrx[0] & (~bit); - } - else if (data == 1) { - ch->gsrx[0] = ch->gsrx[0] | bit; - } - break; - - case 0x0b: // Rx.MODULATION - case 0x0c: // Rx.VOLUME - case 0x0d: // Rx.PANPOT - case 0x0e: // Rx.EXPRESSION - case 0x0f: // Rx.HOLD1 - case 0x10: // Rx.PORTAMENTO - case 0x11: // Rx.SOSTENUTO - case 0x12: // Rx.SOFT - bit = 1 << ((addr - 0x0b) & 7); - if (data == 0) { - ch->gsrx[1] = ch->gsrx[1] & (~bit); - } - else if (data == 1) { - ch->gsrx[1] = ch->gsrx[1] | bit; - } - break; -#endif - case 0x15: // USE FOR RHYTHM PART - if (data == 0) { - ch->flag &= ~CHANNEL_RHYTHM; - TRACEOUT(("ch%d - tone", part + 1)); - } - else if ((data == 1) || (data == 2)) { - ch->flag |= CHANNEL_RHYTHM; - TRACEOUT(("ch%d - rhythm", part + 1)); - } - break; - -#if defined(ENABLE_GSRX) - case 0x16: // PITCH KEY SHIFT - if ((data >= 0x28) && (data <= 0x58)) { - ch->keyshift = data; - } - break; - - case 0x1d: // KEYBOARD RANGE LOW - ch->noterange[0] = data; - break; - - case 0x1e: // KEYBOARD RANGE HIGH - ch->noterange[1] = data; - break; - - case 0x23: // Rx.BANK SELECT - case 0x24: // Rx.BANK SELECT LSB - bit = 1 << ((addr - 0x23) & 7); - if (data == 0) { - ch->gsrx[2] = ch->gsrx[2] & (~bit); - } - else if (data == 1) { - ch->gsrx[2] = ch->gsrx[2] | bit; - } - break; -#endif - default: - TRACEOUT(("Roland GS - %.6x %.2x", addr, data)); - break; - } - } - else { - TRACEOUT(("Roland GS - %.6x %.2x", addr, data)); - } -} - -static void VERMOUTHCL longmsg_roland(MIDIHDL hdl, const UINT8 *msg, - UINT size) { - - UINT addr; - UINT8 data; - - if (size <= 10) { - return; - } - // GS data set - if ((msg[2] != 0x10) || (msg[3] != 0x42) || (msg[4] != 0x12)) { - return; - } - addr = (msg[5] << 16) + (msg[6] << 8) + msg[7]; - msg += 8; - size -= 10; - while(size) { - size--; - data = (*msg++) & 0x7f; - if ((addr & (~0x400000)) == 0x7f) { // GS reset - allresetmidi(hdl, TRUE); - TRACEOUT(("GS-Reset")); - } - else if ((addr & 0xfff00000) == 0x00400000) { - rolandcmd4(hdl, addr, data); - } -#if defined(ENABLE_PORTB) - else if ((addr & 0xfff00000) == 0x00500000) { - if (hdl->portb) { - rolandcmd4(hdl->portb, addr, data); - } - } -#endif // defined(ENABLE_PORTB) - addr++; - } -} - -VEXTERN void VEXPORT midiout_longmsg(MIDIHDL hdl, const UINT8 *msg, UINT size) { - - UINT id; - - if ((hdl == NULL) || (msg == NULL)) { - return; - } - if (size > 3) { // (msg[size - 1] == 0xf7) - id = msg[1]; - if (id == 0x7f) { // Universal realtime - longmsg_uni(hdl, msg, size); - } - else if (id == 0x7e) { // GM - longmsg_gm(hdl, msg, size); - } - else if (id == 0x41) { // Roland - longmsg_roland(hdl, msg, size); - } - else { - TRACEOUT(("long msg unknown id:%02x", id)); - } - } -} - -static UINT VERMOUTHCL preparepcm(MIDIHDL hdl, UINT size) { - - UINT ret; - SINT32 *buf; - VOICE v; - VOICE vterm; - SAMPLE src; - SAMPLE srcterm; - UINT cnt; - UINT pos; - UINT rem; - - ret = 0; - size = MIN(size, hdl->worksize); - buf = hdl->sampbuf; - ZeroMemory(buf, size * 2 * sizeof(SINT32)); - v = VOICEHDLPTR(hdl); - vterm = VOICEHDLEND(hdl); - do { - if (v->phase != VOICE_FREE) { - ret = size; - cnt = size; - if (v->phase & VOICE_REL) { - voice_setfree(v); - if (cnt > REL_COUNT) { - cnt = REL_COUNT; - } - } - if (v->flag & VOICE_FIXPITCH) { - pos = v->samppos >> FREQ_SHIFT; - src = v->sample->data + pos; - rem = (v->sample->datasize >> FREQ_SHIFT) - pos; - if (cnt < rem) { - v->samppos += cnt << FREQ_SHIFT; - srcterm = src + cnt; - } - else { - voice_setfree(v); - srcterm = src + rem; - } - } - else { - src = hdl->resampbuf; - srcterm = v->resamp(v, src, src + cnt); - } - if (src != srcterm) { - v->mix(v, buf, src, srcterm); - } - } - v++; - } while(v < vterm); - return(ret); -} - -VEXTERN const SINT32 * VEXPORT midiout_get(MIDIHDL hdl, UINT *samples) { - - UINT size; - SINT32 *buf; - SINT32 *bufterm; - - if ((hdl == NULL) || (samples == NULL)) { - goto moget_err; - } - size = *samples; - if (size == 0) { - goto moget_err; - } - size = preparepcm(hdl, size); - if (size == 0) { - goto moget_err; - } - - *samples = size; - buf = hdl->sampbuf; - bufterm = buf + (size * 2); - do { - buf[0] >>= (SAMP_SHIFT + 1); - buf[1] >>= (SAMP_SHIFT + 1); - buf += 2; - } while(buf < bufterm); - return(hdl->sampbuf); - -moget_err: - return(NULL); -} - -VEXTERN UINT VEXPORT midiout_get16(MIDIHDL hdl, SINT16 *pcm, UINT size) { - - UINT step; - SINT32 *buf; - SINT32 l; - SINT32 r; - - if (hdl != NULL) { - while(size) { - step = preparepcm(hdl, size); - if (step == 0) { - break; - } - size -= step; - buf = hdl->sampbuf; - do { - l = pcm[0]; - r = pcm[1]; - l += buf[0] >> (SAMP_SHIFT + 1); - r += buf[1] >> (SAMP_SHIFT + 1); - if (l < -32768) { - l = -32768; - } - else if (l > 32767) { - l = 32767; - } - if (r < -32768) { - r = -32768; - } - else if (r > 32767) { - r = 32767; - } - pcm[0] = l; - pcm[1] = r; - buf += 2; - pcm += 2; - } while(--step); - } - } - return(0); -} - -VEXTERN UINT VEXPORT midiout_get32(MIDIHDL hdl, SINT32 *pcm, UINT size) { - - UINT step; - SINT32 *buf; - - if (hdl != NULL) { - while(size) { - step = preparepcm(hdl, size); - if (step == 0) { - break; - } - size -= step; - buf = hdl->sampbuf; - do { - pcm[0] += buf[0] >> (SAMP_SHIFT + 1); - pcm[1] += buf[1] >> (SAMP_SHIFT + 1); - buf += 2; - pcm += 2; - } while(--step); - } - } - return(0); -} - -VEXTERN void VEXPORT midiout_setgain(MIDIHDL hdl, int gain) { - - if (hdl) { - if (gain < -16) { - gain = 16; - } - else if (gain > 8) { - gain = 8; - } - hdl->gain = (SINT8)gain; - allvolupdate(hdl); - } -} - -VEXTERN void VEXPORT midiout_setmoduleid(MIDIHDL hdl, UINT8 moduleid) { - - if (hdl) { - hdl->moduleid = moduleid; - } -} - -VEXTERN void VEXPORT midiout_setportb(MIDIHDL hdl, MIDIHDL portb) { - -#if defined(ENABLE_PORTB) - if (hdl) { - hdl->portb = portb; - } -#endif // defined(ENABLE_PORTB) -} - +#include +#include "midiout.h" + + +#define MIDIOUT_VERSION 0x116 +#define MIDIOUT_VERSTRING "VERMOUTH 1.16" + +static const char vermouthver[] = MIDIOUT_VERSTRING; + +static const int gaintbl[24+1] = + { 16, 19, 22, 26, 32, 38, 45, 53, + 64, 76, 90, 107, 128, 152, 181, 215, + 256, 304, 362, 430, 512, 608, 724, 861, 1024}; + + +// ---- voice + +#define VOICEHDLPTR(hdl) ((hdl)->voice) +#define VOICEHDLEND(hdl) (VOICE)((hdl) + 1) + +static void VERMOUTHCL voice_volupdate(VOICE v) { + + CHANNEL ch; + int vol; + + ch = v->channel; +#if defined(VOLUME_ACURVE) + vol = ch->level * acurve[v->velocity]; + vol >>= 8; +#else + vol = ch->level * v->velocity; + vol >>= 7; +#endif + vol *= v->sample->volume; + vol >>= (21 - 16); +#if defined(PANPOT_REVA) + switch(v->flag & VOICE_MIXMASK) { + case VOICE_MIXNORMAL: + v->volleft = (vol * revacurve[v->panpot ^ 127]) >> 8; + v->volright = (vol * revacurve[v->panpot]) >> 8; + break; + + case VOICE_MIXCENTRE: + v->volleft = (vol * 155) >> 8; + break; + + default: + v->volleft = vol; + break; + } +#else + v->volleft = vol; + if ((v->flag & VOICE_MIXMASK) == VOICE_MIXNORMAL) { + if (v->panpot < 64) { + vol *= (v->panpot + 1); + vol >>= 6; + v->volright = vol; + } + else { + v->volright = vol; + vol *= (127 - v->panpot); + vol >>= 6; + v->volleft = vol; + } + } +#endif +} + +static INSTLAYER VERMOUTHCL selectlayer(VOICE v, INSTRUMENT inst) { + + int layers; + INSTLAYER layer; + INSTLAYER layerterm; + int freq; + int diffmin; + int diff; + INSTLAYER layersel; + + layers = inst->layers; + layer = (INSTLAYER)(inst + 1); + + if (layers == 1) { + return(layer); + } + + layerterm = layer + layers; + freq = v->frequency; + do { + if ((freq >= layer->freqlow) && (freq <= layer->freqhigh)) { + return(layer); + } + layer++; + } while(layer < layerterm); + + layer = (INSTLAYER)(inst + 1); + layersel = layer; + diffmin = layer->freqroot - freq; + if (diffmin < 0) { + diffmin *= -1; + } + layer++; + do { + diff = layer->freqroot - freq; + if (diff < 0) { + diff *= -1; + } + if (diffmin > diff) { + diffmin = diff; + layersel = layer; + } + layer++; + } while(layer < layerterm); + return(layersel); +} + +static void VERMOUTHCL freq_update(VOICE v) { + + CHANNEL ch; + float step; + + if (v->flag & VOICE_FIXPITCH) { + return; + } + + ch = v->channel; + step = v->freq; + if (ch->pitchbend != 0x2000) { + step *= ch->pitchfactor; + } +#if defined(ENABLE_VIRLATE) + v->freqnow = step; +#endif + step *= (float)(1 << FREQ_SHIFT); + if (v->sampstep < 0) { + step *= -1.0; + } + v->sampstep = (int)step; +} + +static void VERMOUTHCL voice_on(MIDIHDL hdl, CHANNEL ch, VOICE v, int key, + int vel) { + + INSTRUMENT inst; + INSTLAYER layer; + int panpot; + + key &= 0x7f; + if (!(ch->flag & CHANNEL_RHYTHM)) { + inst = ch->inst; + if (inst == NULL) { + return; + } + if (inst->freq) { + v->frequency = inst->freq; + } + else { + v->frequency = ver_freq_table[key]; + } + layer = selectlayer(v, inst); + } + else { +#if !defined(MIDI_GMONLY) + inst = ch->rhythm[key]; + if (inst == NULL) { + inst = hdl->bank0[1][key]; + } +#else + inst = hdl->bank0[1][key]; +#endif + if (inst == NULL) { + return; + } + layer = (INSTLAYER)(inst + 1); + if (inst->freq) { + v->frequency = inst->freq; + } + else { + v->frequency = ver_freq_table[key]; + } + } + v->sample = layer; + + v->phase = VOICE_ON; + v->channel = ch; + v->note = key; + v->velocity = vel; + v->samppos = 0; + v->sampstep = 0; + +#if defined(ENABLE_TREMOLO) + v->tremolo.count = 0; + v->tremolo.step = layer->tremolo_step; + v->tremolo.sweepstep = layer->tremolo_sweep; + v->tremolo.sweepcount = 0; +#endif + +#if defined(ENABLE_VIRLATE) + v->vibrate.sweepstep = layer->vibrate_sweep; + v->vibrate.sweepcount = 0; + v->vibrate.rate = layer->vibrate_rate; + v->vibrate.count = 0; + v->vibrate.phase = 0; +#endif + + if (!(ch->flag & CHANNEL_RHYTHM)) { + panpot = ch->panpot; + } + else { + panpot = layer->panpot; + } +#if defined(PANPOT_REVA) + if (panpot == 64) { + v->flag = VOICE_MIXCENTRE; + } + else if (panpot < 3) { + v->flag = VOICE_MIXLEFT; + } + else if (panpot >= 126) { + v->flag = VOICE_MIXRIGHT; + } + else { + v->flag = VOICE_MIXNORMAL; + v->panpot = panpot; + } +#else + if ((panpot >= 60) && (panpot < 68)) { + v->flag = VOICE_MIXCENTRE; + } + else if (panpot < 5) { + v->flag = VOICE_MIXLEFT; + } + else if (panpot >= 123) { + v->flag = VOICE_MIXRIGHT; + } + else { + v->flag = VOICE_MIXNORMAL; + v->panpot = panpot; + } +#endif + if (!layer->samprate) { + v->flag |= VOICE_FIXPITCH; + } + else { + v->freq = (float)layer->samprate / (float)hdl->samprate * + (float)v->frequency / (float)layer->freqroot; + } + voice_setphase(v, VOICE_ON); + freq_update(v); + voice_volupdate(v); + v->envcount = 0; + if (layer->mode & MODE_ENVELOPE) { + v->envvol = 0; + envlope_setphase(v, 0); + } + else { + v->envstep = 0; + } + voice_setmix(v); + envelope_updates(v); +} + +static void VERMOUTHCL voice_off(VOICE v) { + + voice_setphase(v, VOICE_OFF); + if (v->sample->mode & MODE_ENVELOPE) { + envlope_setphase(v, 3); + voice_setmix(v); + envelope_updates(v); + } +} + +static void VERMOUTHCL allresetvoices(MIDIHDL hdl) { + + VOICE v; + VOICE vterm; + + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); + do { + voice_setfree(v); + v++; + } while(v < vterm); +} + + +// ---- key + +static void VERMOUTHCL key_on(MIDIHDL hdl, CHANNEL ch, int key, int vel) { + + VOICE v; + VOICE v1; + VOICE v2; + int vol; + int volmin; + + v = NULL; + v1 = VOICEHDLPTR(hdl); + v2 = VOICEHDLEND(hdl); + do { + v2--; + if (v2->phase == VOICE_FREE) { + v = v2; + } + else if ((v2->channel == ch) && + ((v2->note == key) || (ch->flag & CHANNEL_MONO))) { + voice_setphase(v2, VOICE_REL); + voice_setmix(v2); + } + } while(v1 < v2); + + if (v != NULL) { + voice_on(hdl, ch, v, key, vel); + return; + } + + volmin = 0x7fffffff; + v2 = VOICEHDLEND(hdl); + do { + v2--; + if (!(v2->phase & (VOICE_ON | VOICE_REL))) { + vol = v2->envleft; + if ((v2->flag & VOICE_MIXMASK) == VOICE_MIXNORMAL) { + vol = MAX(vol, v2->envright); + } + if (volmin > vol) { + volmin = vol; + v = v2; + } + } + } while(v1 < v2); + + if (v != NULL) { + voice_setfree(v); + voice_on(hdl, ch, v, key, vel); + } +} + +static void VERMOUTHCL key_off(MIDIHDL hdl, CHANNEL ch, int key) { + + VOICE v; + VOICE vterm; + + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); + do { + if ((v->phase & VOICE_ON) && + (v->channel == ch) && (v->note == key)) { + if (ch->flag & CHANNEL_SUSTAIN) { + voice_setphase(v, VOICE_SUSTAIN); + } + else { + voice_off(v); + } + return; + } + v++; + } while(v < vterm); +} + +static void VERMOUTHCL key_pressure(MIDIHDL hdl, CHANNEL ch, int key, + int vel) { + + VOICE v; + VOICE vterm; + + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); + do { + if ((v->phase & VOICE_ON) && + (v->channel == ch) && (v->note == key)) { + v->velocity = vel; + voice_volupdate(v); + envelope_updates(v); + break; + } + v++; + } while(v < vterm); +} + + +// ---- control + +static void VERMOUTHCL volumeupdate(MIDIHDL hdl, CHANNEL ch) { + + VOICE v; + VOICE vterm; + +#if defined(VOLUME_ACURVE) + ch->level = (hdl->level * acurve[ch->volume] * ch->expression) >> 15; +#else + ch->level = (hdl->level * ch->volume * ch->expression) >> 14; +#endif + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); + do { + if ((v->phase & (VOICE_ON | VOICE_SUSTAIN)) && (v->channel == ch)) { + voice_volupdate(v); + envelope_updates(v); + } + v++; + } while(v < vterm); +} + +static void VERMOUTHCL pedaloff(MIDIHDL hdl, CHANNEL ch) { + + VOICE v; + VOICE vterm; + + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); + do { + if ((v->phase & VOICE_SUSTAIN) && (v->channel == ch)) { + voice_off(v); + } + v++; + } while(v < vterm); +} + +static void VERMOUTHCL allsoundsoff(MIDIHDL hdl, CHANNEL ch) { + + VOICE v; + VOICE vterm; + + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); + do { + if ((v->phase != VOICE_FREE) && (v->channel == ch)) { + voice_setphase(v, VOICE_REL); + voice_setmix(v); + } + v++; + } while(v < vterm); +} + +static void VERMOUTHCL resetallcontrollers(CHANNEL ch) { + + ch->flag &= CHANNEL_MASK; + if (ch->flag == 9) { + ch->flag |= CHANNEL_RHYTHM; + } + ch->volume = 90; + ch->expression = 127; + ch->pitchbend = 0x2000; + ch->pitchfactor = 1.0; +} + +static void VERMOUTHCL allnotesoff(MIDIHDL hdl, CHANNEL ch) { + + VOICE v; + VOICE vterm; + + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); + do { +#if 1 + if ((v->phase & (VOICE_ON | VOICE_SUSTAIN)) && (v->channel == ch)) { + voice_off(v); + } +#else + if ((v->phase & VOICE_ON) && (v->channel == ch)) { + if (ch->flag & CHANNEL_SUSTAIN) { + voice_setphase(v, VOICE_SUSTAIN); + } + else { + voice_off(v); + } + } +#endif + v++; + } while(v < vterm); +} + +static void VERMOUTHCL ctrlchange(MIDIHDL hdl, CHANNEL ch, int ctrl, + int val) { + + val &= 0x7f; + switch(ctrl & 0x7f) { +#if !defined(MIDI_GMONLY) + case CTRL_PGBANK: +#if defined(ENABLE_GSRX) + if (!(ch->gsrx[2] & GSRX2_BANKSELECT)) { + break; + } +#endif + ch->bank = val; + break; +#endif + + case CTRL_DATA_M: +// TRACEOUT(("data: %x %x %x", c->rpn_l, c->rpn_m, val)); + if ((ch->rpn_l == 0) && (ch->rpn_m == 0)) { + if (val >= 24) { + val = 24; + } + ch->pitchsens = val; + } + break; + + case CTRL_VOLUME: + ch->volume = val; + volumeupdate(hdl, ch); + break; + + case CTRL_PANPOT: + ch->panpot = val; + break; + + case CTRL_EXPRESS: + ch->expression = val; + volumeupdate(hdl, ch); + break; + + case CTRL_PEDAL: + if (val == 0) { + ch->flag &= ~CHANNEL_SUSTAIN; + pedaloff(hdl, ch); + } + else { + ch->flag |= CHANNEL_SUSTAIN; + } + break; + + case CTRL_RPN_L: + ch->rpn_l = val; + break; + + case CTRL_RPN_M: + ch->rpn_m = val; + break; + + case CTRL_SOUNDOFF: + allsoundsoff(hdl, ch); + break; + + case CTRL_RESETCTRL: + resetallcontrollers(ch); + /*FALLTHROUGH*/ + + case CTRL_NOTEOFF: + allnotesoff(hdl, ch); + break; + + case CTRL_MONOON: + ch->flag |= CHANNEL_MONO; + break; + + case CTRL_POLYON: + ch->flag &= ~CHANNEL_MONO; + break; + + default: +// TRACEOUT(("ctrl: %x %x", ctrl, val); + break; + } +} + +static void VERMOUTHCL progchange(MIDIHDL hdl, CHANNEL ch, int val) { + +#if !defined(MIDI_GMONLY) + MIDIMOD mod; + INSTRUMENT *bank; + INSTRUMENT inst; + + mod = hdl->module; + inst = NULL; + if (ch->bank < MIDI_BANKS) { + bank = mod->tone[ch->bank * 2]; + if (bank) { + inst = bank[val]; + } + } + if (inst == NULL) { + bank = hdl->bank0[0]; + inst = bank[val]; + } + ch->inst = inst; + + bank = NULL; + if (ch->bank < MIDI_BANKS) { + bank = mod->tone[ch->bank * 2 + 1]; + } + if (bank == NULL) { + bank = hdl->bank0[1]; + } + ch->rhythm = bank; +#else + ch->inst = hdl->bank0[0][val]; +#endif + ch->program = val; +} + +static void VERMOUTHCL chpressure(MIDIHDL hdl, CHANNEL ch, int vel) { + + VOICE v; + VOICE vterm; + + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); + do { + if ((v->phase & VOICE_ON) && (v->channel == ch)) { + v->velocity = vel; + voice_volupdate(v); + envelope_updates(v); + break; + } + v++; + } while(v < vterm); +} + +static void VERMOUTHCL pitchbendor(MIDIHDL hdl, CHANNEL ch, int val1, + int val2) { + + VOICE v; + VOICE vterm; + + val1 &= 0x7f; + val1 += (val2 & 0x7f) << 7; + if (1) { + ch->pitchbend = val1; + val1 -= 0x2000; + if (!val1) { + ch->pitchfactor = 1.0; + } + else { + val1 *= ch->pitchsens; + ch->pitchfactor = bendhtbl[(val1 >> (6 + 7)) + 24] * + bendltbl[(val1 >> 7) & 0x3f]; + } + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); + do { + if ((v->phase != VOICE_FREE) && (v->channel == ch)) { + freq_update(v); + } + v++; + } while(v < vterm); + } +} + +static void VERMOUTHCL allvolupdate(MIDIHDL hdl) { + + int level; + CHANNEL ch; + CHANNEL chterm; + VOICE v; + VOICE vterm; + + level = gaintbl[hdl->gain + 16] >> 1; + level *= hdl->master; + hdl->level = level; + ch = hdl->channel; + chterm = ch + CHANNEL_MAX; + do { + ch->level = (level * ch->volume * ch->expression) >> 14; + ch++; + } while(ch < chterm); + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); + do { + if (v->phase & (VOICE_ON | VOICE_SUSTAIN)) { + voice_volupdate(v); + envelope_updates(v); + } + v++; + } while(v < vterm); +} + +#if defined(ENABLE_GSRX) +static void VERMOUTHCL allresetmidi(MIDIHDL hdl, BOOL gs) +#else +#define allresetmidi(m, g) _allresetmidi(m) +static void VERMOUTHCL _allresetmidi(MIDIHDL hdl) +#endif +{ + CHANNEL ch; + CHANNEL chterm; + UINT flag; + + hdl->master = 127; + ch = hdl->channel; + chterm = ch + CHANNEL_MAX; + ZeroMemory(ch, sizeof(_CHANNEL) * CHANNEL_MAX); + flag = 0; + do { + ch->flag = flag++; + ch->pitchsens = 2; +#if !defined(MIDI_GMONLY) + ch->bank = 0; +#endif + ch->panpot = 64; + progchange(hdl, ch, 0); + resetallcontrollers(ch); +#if defined(ENABLE_GSRX) + ch->keyshift = 0x40; + ch->noterange[0] = 0x00; + ch->noterange[1] = 0x7f; + if (gs) { + ch->gsrx[0] = 0xff; + ch->gsrx[1] = 0xff; + ch->gsrx[2] = 0xff; + } + else { + ch->gsrx[0] = 0x7f; + ch->gsrx[1] = 0xff; + ch->gsrx[2] = 0x02; + } +#endif + ch++; + } while(ch < chterm); + allresetvoices(hdl); + allvolupdate(hdl); +} + + +// ---- + +VEXTERN UINT VEXPORT midiout_getver(char *string, UINT leng) { + + leng = MIN(leng, sizeof(vermouthver)); + CopyMemory(string, vermouthver, leng); + return((MIDIOUT_VERSION << 8) | 0x00); +} + +VEXTERN MIDIHDL VEXPORT midiout_create(MIDIMOD mod, UINT worksize) { + + UINT size; + MIDIHDL ret; + + if (mod == NULL) { + return(NULL); + } + worksize = MIN(worksize, 512U); + worksize = MAX(worksize, 16384U); + size = sizeof(_MIDIHDL); + size += sizeof(SINT32) * 2 * worksize; + size += sizeof(_SAMPLE) * worksize; + ret = (MIDIHDL)_MALLOC(size, "MIDIHDL"); + if (ret) { + midimod_lock(mod); + ZeroMemory(ret, size); + ret->samprate = mod->samprate; + ret->worksize = worksize; + ret->module = mod; + // ret->master = 127; + ret->bank0[0] = mod->tone[0]; + ret->bank0[1] = mod->tone[1]; + ret->sampbuf = (SINT32 *)(ret + 1); + ret->resampbuf = (SAMPLE)(ret->sampbuf + worksize * 2); + allresetmidi(ret, FALSE); + } + return(ret); +} + +VEXTERN void VEXPORT midiout_destroy(MIDIHDL hdl) { + + MIDIMOD mod; + + if (hdl) { + mod = hdl->module; + _MFREE(hdl); + midimod_lock(mod); + } +} + +VEXTERN void VEXPORT midiout_shortmsg(MIDIHDL hdl, UINT32 msg) { + + UINT cmd; + CHANNEL ch; + + if (hdl == NULL) { + return; + } + cmd = msg & 0xff; + if (cmd & 0x80) { + hdl->status = cmd; + } + else { + msg <<= 8; + msg += hdl->status; + } + ch = hdl->channel + (cmd & 0x0f); + switch((cmd >> 4) & 7) { + case (MIDI_NOTE_OFF >> 4) & 7: + key_off(hdl, ch, (msg >> 8) & 0x7f); + break; + + case (MIDI_NOTE_ON >> 4) & 7: + if (msg & (0x7f << 16)) { + key_on(hdl, ch, (msg >> 8) & 0x7f, (msg >> 16) & 0x7f); + } + else { + key_off(hdl, ch, (msg >> 8) & 0x7f); + } + break; + + case (MIDI_KEYPRESS >> 4) & 7: + key_pressure(hdl, ch, (msg >> 8) & 0x7f, (msg >> 16) & 0x7f); + break; + + case (MIDI_CTRLCHANGE >> 4) & 7: + ctrlchange(hdl, ch, (msg >> 8) & 0x7f, (msg >> 16) & 0x7f); + break; + + case (MIDI_PROGCHANGE >> 4) & 7: + progchange(hdl, ch, (msg >> 8) & 0x7f); + break; + + case (MIDI_CHPRESS >> 4) & 7: + chpressure(hdl, ch, (msg >> 8) & 0x7f); + break; + + case (MIDI_PITCHBEND >> 4) & 7: + pitchbendor(hdl, ch, (msg >> 8) & 0x7f, (msg >> 16) & 0x7f); + break; + } +} + +static void VERMOUTHCL longmsg_uni(MIDIHDL hdl, const UINT8 *msg, UINT size) { + + if ((size >= 6) && (msg[2] == 0x7f)) { + switch(msg[3]) { + case 0x04: + if ((msg[4] == 0x01) && (size >= 8)) { + hdl->master = msg[6] & 0x7f; + allvolupdate(hdl); + } + break; + } + } +} + +static void VERMOUTHCL longmsg_gm(MIDIHDL hdl, const UINT8 *msg, UINT size) { + + if ((size >= 6) && (msg[2] == 0x7f)) { + switch(msg[3]) { + case 0x09: + if (msg[4] == 0x01) { + allresetmidi(hdl, FALSE); // GM reset + break; + } +#if !defined(MIDI_GMONLY) + else if ((msg[4] == 0x02) || (msg[4] == 0x03)) { + allresetmidi(hdl, TRUE); // GM reset + break; + } +#endif + break; + } + } +} + +static void VERMOUTHCL rolandcmd4(MIDIHDL hdl, UINT addr, UINT8 data) { + + UINT part; + CHANNEL ch; +#if defined(ENABLE_GSRX) + UINT8 bit; +#endif + + addr = addr & 0x000fffff; + if (addr == 0x00004) { // Vol + hdl->master = data; + allvolupdate(hdl); + } + else if ((addr & (~0xff)) == 0x00100) { + const UINT pos = addr & 0xff; + if (pos < 0x30) { // Patch Name + } + else { + switch(addr & 0xff) { + case 0x30: // Reverb Macro + case 0x31: // Reverb Charactor + case 0x32: // Reverb Pre-LPF + case 0x33: // Reverb Level + case 0x34: // Reverb Time + case 0x35: // Reverb Delay FeedBack + case 0x37: // Reverb Predelay Time + case 0x38: // Chorus Macro + case 0x39: // Chorus Pre-LPF + case 0x3a: // Chorus Level + case 0x3b: // Chorus FeedBack + case 0x3c: // Chorus Delay + case 0x3d: // Chorus Rate + case 0x3e: // Chorus Depth + case 0x3f: // Chorus send level to reverb + case 0x40: // Chorus send level to delay + case 0x50: // Delay Macro + case 0x51: // Delay Time Pre-LPF + case 0x52: // Delay Time Center + case 0x53: // Delay Time Ratio Left + case 0x54: // Delay Time Ratio Right + case 0x55: // Delay Level Center + case 0x56: // Delay Level Left + case 0x57: // Delay Level Right + case 0x58: // Delay Level + case 0x59: // Delay Freeback + case 0x5a: // Delay sendlevel to Reverb + break; + } + } + } + else if ((addr & (~(0x0fff))) == 0x01000) { // GS CH + part = (addr >> 8) & 0x0f; + if (part == 0) { // part10 + part = 9; + } + else if (part < 10) { // part1-9 + part--; + } + ch = hdl->channel + part; + switch(addr & 0xff) { +#if !defined(MIDI_GMONLY) + case 0x00: // TONE NUMBER + ch->bank = data; + break; +#endif + + case 0x01: // PROGRAM NUMBER + progchange(hdl, ch, data); + break; + + case 0x02: // Rx.CHANNEL + TRACEOUT(("RxCHANNEL: %d", data)); + break; + +#if defined(ENABLE_GSRX) + case 0x03: // Rx.PITCHBEND + case 0x04: // Rx.CH PRESSURE + case 0x05: // Rx.PROGRAM CHANGE + case 0x06: // Rx.CONTROL CHANGE + case 0x07: // Rx.POLY PRESSURE + case 0x08: // Rx.NOTE MESSAGE + case 0x09: // Rx.PRN + case 0x0a: // Rx.NRPN + bit = 1 << ((addr - 0x03) & 7); + if (data == 0) { + ch->gsrx[0] = ch->gsrx[0] & (~bit); + } + else if (data == 1) { + ch->gsrx[0] = ch->gsrx[0] | bit; + } + break; + + case 0x0b: // Rx.MODULATION + case 0x0c: // Rx.VOLUME + case 0x0d: // Rx.PANPOT + case 0x0e: // Rx.EXPRESSION + case 0x0f: // Rx.HOLD1 + case 0x10: // Rx.PORTAMENTO + case 0x11: // Rx.SOSTENUTO + case 0x12: // Rx.SOFT + bit = 1 << ((addr - 0x0b) & 7); + if (data == 0) { + ch->gsrx[1] = ch->gsrx[1] & (~bit); + } + else if (data == 1) { + ch->gsrx[1] = ch->gsrx[1] | bit; + } + break; +#endif + case 0x15: // USE FOR RHYTHM PART + if (data == 0) { + ch->flag &= ~CHANNEL_RHYTHM; + TRACEOUT(("ch%d - tone", part + 1)); + } + else if ((data == 1) || (data == 2)) { + ch->flag |= CHANNEL_RHYTHM; + TRACEOUT(("ch%d - rhythm", part + 1)); + } + break; + +#if defined(ENABLE_GSRX) + case 0x16: // PITCH KEY SHIFT + if ((data >= 0x28) && (data <= 0x58)) { + ch->keyshift = data; + } + break; + + case 0x1d: // KEYBOARD RANGE LOW + ch->noterange[0] = data; + break; + + case 0x1e: // KEYBOARD RANGE HIGH + ch->noterange[1] = data; + break; + + case 0x23: // Rx.BANK SELECT + case 0x24: // Rx.BANK SELECT LSB + bit = 1 << ((addr - 0x23) & 7); + if (data == 0) { + ch->gsrx[2] = ch->gsrx[2] & (~bit); + } + else if (data == 1) { + ch->gsrx[2] = ch->gsrx[2] | bit; + } + break; +#endif + default: + TRACEOUT(("Roland GS - %.6x %.2x", addr, data)); + break; + } + } + else { + TRACEOUT(("Roland GS - %.6x %.2x", addr, data)); + } +} + +static void VERMOUTHCL longmsg_roland(MIDIHDL hdl, const UINT8 *msg, + UINT size) { + + UINT addr; + UINT8 data; + + if (size <= 10) { + return; + } + // GS data set + if ((msg[2] != 0x10) || (msg[3] != 0x42) || (msg[4] != 0x12)) { + return; + } + addr = (msg[5] << 16) + (msg[6] << 8) + msg[7]; + msg += 8; + size -= 10; + while(size) { + size--; + data = (*msg++) & 0x7f; + if ((addr & (~0x400000)) == 0x7f) { // GS reset + allresetmidi(hdl, TRUE); + TRACEOUT(("GS-Reset")); + } + else if ((addr & 0xfff00000) == 0x00400000) { + rolandcmd4(hdl, addr, data); + } +#if defined(ENABLE_PORTB) + else if ((addr & 0xfff00000) == 0x00500000) { + if (hdl->portb) { + rolandcmd4(hdl->portb, addr, data); + } + } +#endif // defined(ENABLE_PORTB) + addr++; + } +} + +VEXTERN void VEXPORT midiout_longmsg(MIDIHDL hdl, const UINT8 *msg, UINT size) { + + UINT id; + + if ((hdl == NULL) || (msg == NULL)) { + return; + } + if (size > 3) { // (msg[size - 1] == 0xf7) + id = msg[1]; + if (id == 0x7f) { // Universal realtime + longmsg_uni(hdl, msg, size); + } + else if (id == 0x7e) { // GM + longmsg_gm(hdl, msg, size); + } + else if (id == 0x41) { // Roland + longmsg_roland(hdl, msg, size); + } + else { + TRACEOUT(("long msg unknown id:%02x", id)); + } + } +} + +static UINT VERMOUTHCL preparepcm(MIDIHDL hdl, UINT size) { + + UINT ret; + SINT32 *buf; + VOICE v; + VOICE vterm; + SAMPLE src; + SAMPLE srcterm; + UINT cnt; + UINT pos; + UINT rem; + + ret = 0; + size = MIN(size, hdl->worksize); + buf = hdl->sampbuf; + ZeroMemory(buf, size * 2 * sizeof(SINT32)); + v = VOICEHDLPTR(hdl); + vterm = VOICEHDLEND(hdl); + do { + if (v->phase != VOICE_FREE) { + ret = size; + cnt = size; + if (v->phase & VOICE_REL) { + voice_setfree(v); + if (cnt > REL_COUNT) { + cnt = REL_COUNT; + } + } + if (v->flag & VOICE_FIXPITCH) { + pos = v->samppos >> FREQ_SHIFT; + src = v->sample->data + pos; + rem = (v->sample->datasize >> FREQ_SHIFT) - pos; + if (cnt < rem) { + v->samppos += cnt << FREQ_SHIFT; + srcterm = src + cnt; + } + else { + voice_setfree(v); + srcterm = src + rem; + } + } + else { + src = hdl->resampbuf; + srcterm = v->resamp(v, src, src + cnt); + } + if (src != srcterm) { + v->mix(v, buf, src, srcterm); + } + } + v++; + } while(v < vterm); + return(ret); +} + +VEXTERN const SINT32 * VEXPORT midiout_get(MIDIHDL hdl, UINT *samples) { + + UINT size; + SINT32 *buf; + SINT32 *bufterm; + + if ((hdl == NULL) || (samples == NULL)) { + goto moget_err; + } + size = *samples; + if (size == 0) { + goto moget_err; + } + size = preparepcm(hdl, size); + if (size == 0) { + goto moget_err; + } + + *samples = size; + buf = hdl->sampbuf; + bufterm = buf + (size * 2); + do { + buf[0] >>= (SAMP_SHIFT + 1); + buf[1] >>= (SAMP_SHIFT + 1); + buf += 2; + } while(buf < bufterm); + return(hdl->sampbuf); + +moget_err: + return(NULL); +} + +VEXTERN UINT VEXPORT midiout_get16(MIDIHDL hdl, SINT16 *pcm, UINT size) { + + UINT step; + SINT32 *buf; + SINT32 l; + SINT32 r; + + if (hdl != NULL) { + while(size) { + step = preparepcm(hdl, size); + if (step == 0) { + break; + } + size -= step; + buf = hdl->sampbuf; + do { + l = pcm[0]; + r = pcm[1]; + l += buf[0] >> (SAMP_SHIFT + 1); + r += buf[1] >> (SAMP_SHIFT + 1); + if (l < -32768) { + l = -32768; + } + else if (l > 32767) { + l = 32767; + } + if (r < -32768) { + r = -32768; + } + else if (r > 32767) { + r = 32767; + } + pcm[0] = l; + pcm[1] = r; + buf += 2; + pcm += 2; + } while(--step); + } + } + return(0); +} + +VEXTERN UINT VEXPORT midiout_get32(MIDIHDL hdl, SINT32 *pcm, UINT size) { + + UINT step; + SINT32 *buf; + + if (hdl != NULL) { + while(size) { + step = preparepcm(hdl, size); + if (step == 0) { + break; + } + size -= step; + buf = hdl->sampbuf; + do { + pcm[0] += buf[0] >> (SAMP_SHIFT + 1); + pcm[1] += buf[1] >> (SAMP_SHIFT + 1); + buf += 2; + pcm += 2; + } while(--step); + } + } + return(0); +} + +VEXTERN void VEXPORT midiout_setgain(MIDIHDL hdl, int gain) { + + if (hdl) { + if (gain < -16) { + gain = 16; + } + else if (gain > 8) { + gain = 8; + } + hdl->gain = (SINT8)gain; + allvolupdate(hdl); + } +} + +VEXTERN void VEXPORT midiout_setmoduleid(MIDIHDL hdl, UINT8 moduleid) { + + if (hdl) { + hdl->moduleid = moduleid; + } +} + +VEXTERN void VEXPORT midiout_setportb(MIDIHDL hdl, MIDIHDL portb) { + +#if defined(ENABLE_PORTB) + if (hdl) { + hdl->portb = portb; + } +#endif // defined(ENABLE_PORTB) +} + diff --git a/sound/vermouth/midiout.h b/sound/vermouth/midiout.h old mode 100755 new mode 100644 index 69a1830d..110cb1df --- a/sound/vermouth/midiout.h +++ b/sound/vermouth/midiout.h @@ -1,149 +1,149 @@ - -#if !defined(_WIN32_WCE) && !defined(SLZAURUS) -#define ENABLE_TREMOLO -#define ENABLE_VIRLATE -#else -#define MIDI_GMONLY -#endif -#define ENABLE_GSRX -#define PANPOT_REVA -// #define VOLUME_ACURVE -#define ENABLE_PORTB - -#ifndef VERMOUTHCL -#define VERMOUTHCL -#endif - -struct _midimodule; -typedef struct _midimodule _MIDIMOD; -typedef struct _midimodule *MIDIMOD; - -struct _midictrl; -typedef struct _midictrl _MIDIHDL; -typedef struct _midictrl *MIDIHDL; - -enum { - MIDIOUT_SUCCESS = 0, - MIDIOUT_FAILURE = -1, - MIDIOUT_ABORT = -2 -}; - -#define CHANNEL_MAX 16 -#define VOICE_MAX 24 - -#define SAMP_SHIFT 12 -#define SAMP_LIMIT ((1 << (SAMP_SHIFT + 1)) - 1) - -#define FREQ_SHIFT 12 -#define FREQ_MASK ((1 << FREQ_SHIFT) - 1) - -#define ENV_RATE 22 -#define ENVRATE_SHIFT 10 - -#define TRESWEEP_SHIFT 16 -#define TRERATE_SHIFT 5 -#define TRESWEEP_TUNE 38 -#define TRERATE_TUNE 38 - -#define VIBSWEEP_SHIFT 16 -#define VIBRATE_SHIFT 6 -#define VIBSWEEP_TUNE 38 -#define VIBRATE_TUNE 38 - -#define REL_COUNT 20 - - -#if defined(MIDI_GMONLY) -#define MIDI_BANKS 1 -#else -#define MIDI_BANKS 128 -#endif - - -#include "midimod.h" -#include "midinst.h" -#include "midvoice.h" -#include "midtable.h" - - -struct _midimodule { - UINT samprate; - UINT lockcount; - INSTRUMENT *tone[MIDI_BANKS * 2]; - TONECFG tonecfg[MIDI_BANKS * 2]; - - PATHLIST pathlist; - LISTARRAY pathtbl; - LISTARRAY namelist; -}; - -struct _midictrl { - UINT samprate; - UINT worksize; - int level; - UINT8 status; - SINT8 gain; - UINT8 master; - UINT8 moduleid; - - MIDIMOD module; - INSTRUMENT *bank0[2]; - - SINT32 *sampbuf; - SAMPLE resampbuf; - -#if defined(ENABLE_PORTB) - MIDIHDL portb; -#endif // defined(ENABLE_PORTB); - - _CHANNEL channel[CHANNEL_MAX]; - _VOICE voice[VOICE_MAX]; -}; - -struct _miditoneloadparam { - void *userdata; - UINT totaltones; - UINT progress; - UINT bank; - UINT num; -}; - - -#ifndef VERMOUTH_EXPORTS -#define VEXTERN -#define VEXPORT VERMOUTHCL -#else -#define VEXTERN __declspec(dllexport) -#define VEXPORT WINAPI -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -VEXTERN UINT VEXPORT midiout_getver(char *string, UINT leng); -VEXTERN _MIDIHDL * VEXPORT midiout_create(MIDIMOD mod, UINT worksize); -VEXTERN void VEXPORT midiout_destroy(MIDIHDL hdl); -VEXTERN void VEXPORT midiout_shortmsg(MIDIHDL hdl, UINT32 msg); -VEXTERN void VEXPORT midiout_longmsg(MIDIHDL hdl, const UINT8 *msg, UINT size); -VEXTERN const SINT32 * VEXPORT midiout_get(MIDIHDL hdl, UINT *samples); -VEXTERN UINT VEXPORT midiout_get16(MIDIHDL hdl, SINT16 *pcm, UINT size); -VEXTERN UINT VEXPORT midiout_get32(MIDIHDL hdl, SINT32 *pcm, UINT size); -VEXTERN void VEXPORT midiout_setgain(MIDIHDL hdl, int gain); -VEXTERN void VEXPORT midiout_setmoduleid(MIDIHDL hdl, UINT8 moduleid); -VEXTERN void VEXPORT midiout_setportb(MIDIHDL hdl, MIDIHDL portb); - -VEXTERN _MIDIMOD * VEXPORT midimod_create(UINT samprate); -VEXTERN void VEXPORT midimod_destroy(MIDIMOD mod); -VEXTERN BRESULT VEXPORT midimod_cfgload(MIDIMOD mod, const OEMCHAR *filename); -VEXTERN void VEXPORT midimod_loadprogram(MIDIMOD mod, UINT num); -VEXTERN void VEXPORT midimod_loadrhythm(MIDIMOD mod, UINT num); -VEXTERN void VEXPORT midimod_loadgm(MIDIMOD mod); -VEXTERN void VEXPORT midimod_loadall(MIDIMOD mod); -VEXTERN int VEXPORT midimod_loadallex(MIDIMOD mod, FNMIDIOUTLAEXCB cb, - void *userdata); - -#ifdef __cplusplus -} -#endif - + +#if !defined(_WIN32_WCE) && !defined(SLZAURUS) +#define ENABLE_TREMOLO +#define ENABLE_VIRLATE +#else +#define MIDI_GMONLY +#endif +#define ENABLE_GSRX +#define PANPOT_REVA +// #define VOLUME_ACURVE +#define ENABLE_PORTB + +#ifndef VERMOUTHCL +#define VERMOUTHCL +#endif + +struct _midimodule; +typedef struct _midimodule _MIDIMOD; +typedef struct _midimodule *MIDIMOD; + +struct _midictrl; +typedef struct _midictrl _MIDIHDL; +typedef struct _midictrl *MIDIHDL; + +enum { + MIDIOUT_SUCCESS = 0, + MIDIOUT_FAILURE = -1, + MIDIOUT_ABORT = -2 +}; + +#define CHANNEL_MAX 16 +#define VOICE_MAX 24 + +#define SAMP_SHIFT 12 +#define SAMP_LIMIT ((1 << (SAMP_SHIFT + 1)) - 1) + +#define FREQ_SHIFT 12 +#define FREQ_MASK ((1 << FREQ_SHIFT) - 1) + +#define ENV_RATE 22 +#define ENVRATE_SHIFT 10 + +#define TRESWEEP_SHIFT 16 +#define TRERATE_SHIFT 5 +#define TRESWEEP_TUNE 38 +#define TRERATE_TUNE 38 + +#define VIBSWEEP_SHIFT 16 +#define VIBRATE_SHIFT 6 +#define VIBSWEEP_TUNE 38 +#define VIBRATE_TUNE 38 + +#define REL_COUNT 20 + + +#if defined(MIDI_GMONLY) +#define MIDI_BANKS 1 +#else +#define MIDI_BANKS 128 +#endif + + +#include "midimod.h" +#include "midinst.h" +#include "midvoice.h" +#include "midtable.h" + + +struct _midimodule { + UINT samprate; + UINT lockcount; + INSTRUMENT *tone[MIDI_BANKS * 2]; + TONECFG tonecfg[MIDI_BANKS * 2]; + + PATHLIST pathlist; + LISTARRAY pathtbl; + LISTARRAY namelist; +}; + +struct _midictrl { + UINT samprate; + UINT worksize; + int level; + UINT8 status; + SINT8 gain; + UINT8 master; + UINT8 moduleid; + + MIDIMOD module; + INSTRUMENT *bank0[2]; + + SINT32 *sampbuf; + SAMPLE resampbuf; + +#if defined(ENABLE_PORTB) + MIDIHDL portb; +#endif // defined(ENABLE_PORTB); + + _CHANNEL channel[CHANNEL_MAX]; + _VOICE voice[VOICE_MAX]; +}; + +struct _miditoneloadparam { + void *userdata; + UINT totaltones; + UINT progress; + UINT bank; + UINT num; +}; + + +#ifndef VERMOUTH_EXPORTS +#define VEXTERN +#define VEXPORT VERMOUTHCL +#else +#define VEXTERN __declspec(dllexport) +#define VEXPORT WINAPI +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +VEXTERN UINT VEXPORT midiout_getver(char *string, UINT leng); +VEXTERN _MIDIHDL * VEXPORT midiout_create(MIDIMOD mod, UINT worksize); +VEXTERN void VEXPORT midiout_destroy(MIDIHDL hdl); +VEXTERN void VEXPORT midiout_shortmsg(MIDIHDL hdl, UINT32 msg); +VEXTERN void VEXPORT midiout_longmsg(MIDIHDL hdl, const UINT8 *msg, UINT size); +VEXTERN const SINT32 * VEXPORT midiout_get(MIDIHDL hdl, UINT *samples); +VEXTERN UINT VEXPORT midiout_get16(MIDIHDL hdl, SINT16 *pcm, UINT size); +VEXTERN UINT VEXPORT midiout_get32(MIDIHDL hdl, SINT32 *pcm, UINT size); +VEXTERN void VEXPORT midiout_setgain(MIDIHDL hdl, int gain); +VEXTERN void VEXPORT midiout_setmoduleid(MIDIHDL hdl, UINT8 moduleid); +VEXTERN void VEXPORT midiout_setportb(MIDIHDL hdl, MIDIHDL portb); + +VEXTERN _MIDIMOD * VEXPORT midimod_create(UINT samprate); +VEXTERN void VEXPORT midimod_destroy(MIDIMOD mod); +VEXTERN BRESULT VEXPORT midimod_cfgload(MIDIMOD mod, const OEMCHAR *filename); +VEXTERN void VEXPORT midimod_loadprogram(MIDIMOD mod, UINT num); +VEXTERN void VEXPORT midimod_loadrhythm(MIDIMOD mod, UINT num); +VEXTERN void VEXPORT midimod_loadgm(MIDIMOD mod); +VEXTERN void VEXPORT midimod_loadall(MIDIMOD mod); +VEXTERN int VEXPORT midimod_loadallex(MIDIMOD mod, FNMIDIOUTLAEXCB cb, + void *userdata); + +#ifdef __cplusplus +} +#endif + diff --git a/sound/vermouth/midtable.c b/sound/vermouth/midtable.c old mode 100755 new mode 100644 index 8b63aecd..5b4ab406 --- a/sound/vermouth/midtable.c +++ b/sound/vermouth/midtable.c @@ -1,168 +1,168 @@ -#include -#include "midiout.h" - - -const SINT32 ver_freq_table[128] = { - 8175, 8661, 9177, 9722, 10300, 10913, - 11562, 12249, 12978, 13750, 14567, 15433, - - 16351, 17323, 18354, 19445, 20601, 21826, - 23124, 24499, 25956, 27500, 29135, 30867, - - 32703, 34647, 36708, 38890, 41203, 43653, - 46249, 48999, 51913, 55000, 58270, 61735, - - 65406, 69295, 73416, 77781, 82406, 87307, - 92498, 97998, 103826, 110000, 116540, 123470, - - 130812, 138591, 146832, 155563, 164813, 174614, - 184997, 195997, 207652, 220000, 233081, 246941, - - 261625, 277182, 293664, 311126, 329627, 349228, - 369994, 391995, 415304, 440000, 466163, 493883, - - 523251, 554365, 587329, 622253, 659255, 698456, - 739988, 783990, 830609, 880000, 932327, 987766, - - 1046502, 1108730, 1174659, 1244507, 1318510, 1396912, - 1479977, 1567981, 1661218, 1760000, 1864655, 1975533, - - 2093004, 2217461, 2349318, 2489015, 2637020, 2793825, - 2959955, 3135963, 3322437, 3520000, 3729310, 3951066, - - 4186009, 4434922, 4698636, 4978031, 5274040, 5587651, - 5919910, 6271926, 6644875, 7040000, 7458620, 7902132, - - 8372018, 8869844, 9397272, 9956063, 10548081, 11175303, - 11839821, 12543853}; - -const SINT16 envsin12q[1 << (SINENT_BIT - 2)] = { - 0, 50, 100, 150, 200, 251, 301, 351, - 401, 451, 501, 551, 601, 650, 700, 749, - 799, 848, 897, 946, 995, 1043, 1092, 1140, - 1189, 1237, 1284, 1332, 1379, 1427, 1474, 1520, - 1567, 1613, 1659, 1705, 1751, 1796, 1841, 1886, - 1930, 1975, 2018, 2062, 2105, 2148, 2191, 2233, - 2275, 2317, 2358, 2399, 2439, 2480, 2519, 2559, - 2598, 2637, 2675, 2713, 2750, 2787, 2824, 2860, - 2896, 2931, 2966, 3000, 3034, 3068, 3101, 3134, - 3166, 3197, 3229, 3259, 3289, 3319, 3348, 3377, - 3405, 3433, 3460, 3487, 3513, 3538, 3563, 3588, - 3612, 3635, 3658, 3680, 3702, 3723, 3744, 3764, - 3784, 3803, 3821, 3839, 3856, 3873, 3889, 3904, - 3919, 3933, 3947, 3960, 3973, 3985, 3996, 4007, - 4017, 4026, 4035, 4043, 4051, 4058, 4065, 4071, - 4076, 4080, 4084, 4088, 4091, 4093, 4094, 4095}; - -const SINT16 vibsin12[1 << VIBRATE_SHIFT] = { - 0, 401, 799, 1189, 1567, 1930, 2275, 2598, - 2896, 3166, 3405, 3612, 3784, 3919, 4017, 4076, - 4096, 4076, 4017, 3919, 3784, 3612, 3405, 3166, - 2896, 2598, 2275, 1930, 1567, 1189, 799, 401, - 0, -401, -799, -1189, -1567, -1930, -2275, -2598, - -2896, -3166, -3405, -3612, -3784, -3919, -4017, -4076, - -4096, -4076, -4017, -3919, -3784, -3612, -3405, -3166, - -2896, -2598, -2275, -1930, -1567, -1189, -799, -401}; - -const SINT16 voltbl12[128] = { - 256, 261, 267, 273, 279, 285, 291, 298, - 304, 311, 318, 325, 332, 340, 347, 355, - 363, 371, 379, 387, 396, 404, 413, 422, - 432, 441, 451, 461, 471, 482, 492, 503, - 514, 526, 537, 549, 561, 574, 586, 599, - 613, 626, 640, 654, 668, 683, 698, 714, - 730, 746, 762, 779, 796, 814, 832, 850, - 869, 888, 908, 928, 948, 969, 991, 1012, - 1035, 1058, 1081, 1105, 1129, 1154, 1180, 1206, - 1232, 1260, 1287, 1316, 1345, 1374, 1405, 1436, - 1468, 1500, 1533, 1567, 1602, 1637, 1673, 1710, - 1748, 1786, 1826, 1866, 1907, 1949, 1992, 2036, - 2081, 2127, 2174, 2222, 2271, 2321, 2373, 2425, - 2479, 2533, 2589, 2646, 2705, 2765, 2826, 2888, - 2952, 3017, 3083, 3151, 3221, 3292, 3365, 3439, - 3515, 3593, 3672, 3753, 3836, 3921, 4007, 4096}; - -const float bendltbl[64] = { - (float)1.0, (float)1.0009029427989777, - (float)1.0018067009036538, (float)1.0027112750502025, - (float)1.0036166659754628, (float)1.0045228744169397, - (float)1.0054299011128027, (float)1.0063377468018895, - (float)1.0072464122237039, (float)1.0081558981184175, - (float)1.0090662052268706, (float)1.009977334290572, - (float)1.0108892860517005, (float)1.0118020612531047, - (float)1.0127156606383041, (float)1.0136300849514894, - (float)1.0145453349375237, (float)1.015461411341942, - (float)1.0163783149109531, (float)1.0172960463914391, - (float)1.0182146065309567, (float)1.0191339960777379, - (float)1.0200542157806898, (float)1.0209752663893958, - (float)1.0218971486541166, (float)1.0228198633257899, - (float)1.0237434111560313, (float)1.0246677928971357, - (float)1.0255930093020766, (float)1.0265190611245079, - (float)1.0274459491187637, (float)1.0283736740398595, - (float)1.0293022366434921, (float)1.030231637686041, - (float)1.0311618779245688, (float)1.0320929581168212, - (float)1.0330248790212284, (float)1.0339576413969056, - (float)1.034891246003653, (float)1.0358256936019572, - (float)1.0367609849529913, (float)1.0376971208186156, - (float)1.0386341019613787, (float)1.0395719291445176, - (float)1.0405106031319582, (float)1.0414501246883161, - (float)1.042390494578898, (float)1.0433317135697009, - (float)1.0442737824274138, (float)1.0452167019194181, - (float)1.0461604728137874, (float)1.0471050958792898, - (float)1.048050571885387, (float)1.0489969016022356, - (float)1.0499440858006872, (float)1.0508921252522903, - (float)1.0518410207292894, (float)1.0527907730046264, - (float)1.0537413828519411, (float)1.0546928510455722, - (float)1.0556451783605572, (float)1.0565983655726334, - (float)1.057552413458239, (float)1.0585073227945128}; - -const float bendhtbl[48] = { - (float)0.25, (float)0.26486577358982383, - (float)0.28061551207734325, (float)0.29730177875068026, - (float)0.3149802624737183, (float)0.33370996354250859, - (float)0.35355339059327379, (float)0.37457676921917044, - (float)0.3968502629920499, (float)0.42044820762685725, - (float)0.44544935907016969, (float)0.47193715634084676, - (float)0.5, (float)0.52973154717964765, - (float)0.56123102415468651, (float)0.59460355750136051, - (float)0.6299605249474366, (float)0.66741992708501718, - (float)0.70710678118654757, (float)0.74915353843834076, - (float)0.79370052598409979, (float)0.8408964152537145, - (float)0.89089871814033927, (float)0.94387431268169353, - (float)1.0, (float)1.0594630943592953, - (float)1.122462048309373, (float)1.189207115002721, - (float)1.2599210498948732, (float)1.3348398541700344, - (float)1.4142135623730951, (float)1.4983070768766815, - (float)1.5874010519681994, (float)1.681792830507429, - (float)1.7817974362806785, (float)1.8877486253633868, - (float)2.0, (float)2.1189261887185906, - (float)2.2449240966187456, (float)2.3784142300054421, - (float)2.5198420997897464, (float)2.6696797083400683, - (float)2.8284271247461903, (float)2.996614153753363, - (float)3.1748021039363987, (float)3.363585661014858, - (float)3.5635948725613571, (float)3.7754972507267737}; - -#if defined(PANPOT_REVA) -const UINT8 revacurve[] = { - 0, 4, 10, 14, 16, 17, 18, 19, 21, 22, 23, 25, 27, 28, 30, 32, - 35, 37, 39, 42, 44, 47, 49, 51, 54, 56, 59, 61, 64, 66, 69, 71, - 74, 76, 79, 81, 84, 86, 89, 91, 94, 97, 99,102,104,107,109,112, - 115,117,120,122,125,127,130,132,135,137,140,142,145,147,150,152, - 155,157,159,162,164,166,169,171,173,176,178,180,182,185,186,189, - 191,193,195,197,199,201,203,205,207,209,211,213,214,216,218,220, - 222,224,225,226,228,229,230,232,233,235,237,238,239,241,241,243, - 245,246,246,248,249,249,250,251,252,252,252,253,254,254,255,255}; -#endif - -#if defined(VOLUME_ACURVE) -const UINT8 acurve[] = { - 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, - 7, 8, 8, 9, 10, 10, 11, 11, 12, 13, 14, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 31, 32, 33, 35, 36, 38, - 39, 41, 42, 44, 46, 47, 49, 51, 52, 54, 56, 58, 60, 62, 64, 66, - 68, 70, 72, 74, 77, 79, 81, 83, 85, 88, 90, 93, 95, 98,100,102, - 105,108,110,113,116,119,121,124,127,130,133,136,138,141,145,148, - 150,154,157,160,163,167,170,173,176,180,183,186,189,193,196,199, - 203,206,210,213,217,220,224,227,231,234,238,242,245,249,253,255}; -#endif - +#include +#include "midiout.h" + + +const SINT32 ver_freq_table[128] = { + 8175, 8661, 9177, 9722, 10300, 10913, + 11562, 12249, 12978, 13750, 14567, 15433, + + 16351, 17323, 18354, 19445, 20601, 21826, + 23124, 24499, 25956, 27500, 29135, 30867, + + 32703, 34647, 36708, 38890, 41203, 43653, + 46249, 48999, 51913, 55000, 58270, 61735, + + 65406, 69295, 73416, 77781, 82406, 87307, + 92498, 97998, 103826, 110000, 116540, 123470, + + 130812, 138591, 146832, 155563, 164813, 174614, + 184997, 195997, 207652, 220000, 233081, 246941, + + 261625, 277182, 293664, 311126, 329627, 349228, + 369994, 391995, 415304, 440000, 466163, 493883, + + 523251, 554365, 587329, 622253, 659255, 698456, + 739988, 783990, 830609, 880000, 932327, 987766, + + 1046502, 1108730, 1174659, 1244507, 1318510, 1396912, + 1479977, 1567981, 1661218, 1760000, 1864655, 1975533, + + 2093004, 2217461, 2349318, 2489015, 2637020, 2793825, + 2959955, 3135963, 3322437, 3520000, 3729310, 3951066, + + 4186009, 4434922, 4698636, 4978031, 5274040, 5587651, + 5919910, 6271926, 6644875, 7040000, 7458620, 7902132, + + 8372018, 8869844, 9397272, 9956063, 10548081, 11175303, + 11839821, 12543853}; + +const SINT16 envsin12q[1 << (SINENT_BIT - 2)] = { + 0, 50, 100, 150, 200, 251, 301, 351, + 401, 451, 501, 551, 601, 650, 700, 749, + 799, 848, 897, 946, 995, 1043, 1092, 1140, + 1189, 1237, 1284, 1332, 1379, 1427, 1474, 1520, + 1567, 1613, 1659, 1705, 1751, 1796, 1841, 1886, + 1930, 1975, 2018, 2062, 2105, 2148, 2191, 2233, + 2275, 2317, 2358, 2399, 2439, 2480, 2519, 2559, + 2598, 2637, 2675, 2713, 2750, 2787, 2824, 2860, + 2896, 2931, 2966, 3000, 3034, 3068, 3101, 3134, + 3166, 3197, 3229, 3259, 3289, 3319, 3348, 3377, + 3405, 3433, 3460, 3487, 3513, 3538, 3563, 3588, + 3612, 3635, 3658, 3680, 3702, 3723, 3744, 3764, + 3784, 3803, 3821, 3839, 3856, 3873, 3889, 3904, + 3919, 3933, 3947, 3960, 3973, 3985, 3996, 4007, + 4017, 4026, 4035, 4043, 4051, 4058, 4065, 4071, + 4076, 4080, 4084, 4088, 4091, 4093, 4094, 4095}; + +const SINT16 vibsin12[1 << VIBRATE_SHIFT] = { + 0, 401, 799, 1189, 1567, 1930, 2275, 2598, + 2896, 3166, 3405, 3612, 3784, 3919, 4017, 4076, + 4096, 4076, 4017, 3919, 3784, 3612, 3405, 3166, + 2896, 2598, 2275, 1930, 1567, 1189, 799, 401, + 0, -401, -799, -1189, -1567, -1930, -2275, -2598, + -2896, -3166, -3405, -3612, -3784, -3919, -4017, -4076, + -4096, -4076, -4017, -3919, -3784, -3612, -3405, -3166, + -2896, -2598, -2275, -1930, -1567, -1189, -799, -401}; + +const SINT16 voltbl12[128] = { + 256, 261, 267, 273, 279, 285, 291, 298, + 304, 311, 318, 325, 332, 340, 347, 355, + 363, 371, 379, 387, 396, 404, 413, 422, + 432, 441, 451, 461, 471, 482, 492, 503, + 514, 526, 537, 549, 561, 574, 586, 599, + 613, 626, 640, 654, 668, 683, 698, 714, + 730, 746, 762, 779, 796, 814, 832, 850, + 869, 888, 908, 928, 948, 969, 991, 1012, + 1035, 1058, 1081, 1105, 1129, 1154, 1180, 1206, + 1232, 1260, 1287, 1316, 1345, 1374, 1405, 1436, + 1468, 1500, 1533, 1567, 1602, 1637, 1673, 1710, + 1748, 1786, 1826, 1866, 1907, 1949, 1992, 2036, + 2081, 2127, 2174, 2222, 2271, 2321, 2373, 2425, + 2479, 2533, 2589, 2646, 2705, 2765, 2826, 2888, + 2952, 3017, 3083, 3151, 3221, 3292, 3365, 3439, + 3515, 3593, 3672, 3753, 3836, 3921, 4007, 4096}; + +const float bendltbl[64] = { + (float)1.0, (float)1.0009029427989777, + (float)1.0018067009036538, (float)1.0027112750502025, + (float)1.0036166659754628, (float)1.0045228744169397, + (float)1.0054299011128027, (float)1.0063377468018895, + (float)1.0072464122237039, (float)1.0081558981184175, + (float)1.0090662052268706, (float)1.009977334290572, + (float)1.0108892860517005, (float)1.0118020612531047, + (float)1.0127156606383041, (float)1.0136300849514894, + (float)1.0145453349375237, (float)1.015461411341942, + (float)1.0163783149109531, (float)1.0172960463914391, + (float)1.0182146065309567, (float)1.0191339960777379, + (float)1.0200542157806898, (float)1.0209752663893958, + (float)1.0218971486541166, (float)1.0228198633257899, + (float)1.0237434111560313, (float)1.0246677928971357, + (float)1.0255930093020766, (float)1.0265190611245079, + (float)1.0274459491187637, (float)1.0283736740398595, + (float)1.0293022366434921, (float)1.030231637686041, + (float)1.0311618779245688, (float)1.0320929581168212, + (float)1.0330248790212284, (float)1.0339576413969056, + (float)1.034891246003653, (float)1.0358256936019572, + (float)1.0367609849529913, (float)1.0376971208186156, + (float)1.0386341019613787, (float)1.0395719291445176, + (float)1.0405106031319582, (float)1.0414501246883161, + (float)1.042390494578898, (float)1.0433317135697009, + (float)1.0442737824274138, (float)1.0452167019194181, + (float)1.0461604728137874, (float)1.0471050958792898, + (float)1.048050571885387, (float)1.0489969016022356, + (float)1.0499440858006872, (float)1.0508921252522903, + (float)1.0518410207292894, (float)1.0527907730046264, + (float)1.0537413828519411, (float)1.0546928510455722, + (float)1.0556451783605572, (float)1.0565983655726334, + (float)1.057552413458239, (float)1.0585073227945128}; + +const float bendhtbl[48] = { + (float)0.25, (float)0.26486577358982383, + (float)0.28061551207734325, (float)0.29730177875068026, + (float)0.3149802624737183, (float)0.33370996354250859, + (float)0.35355339059327379, (float)0.37457676921917044, + (float)0.3968502629920499, (float)0.42044820762685725, + (float)0.44544935907016969, (float)0.47193715634084676, + (float)0.5, (float)0.52973154717964765, + (float)0.56123102415468651, (float)0.59460355750136051, + (float)0.6299605249474366, (float)0.66741992708501718, + (float)0.70710678118654757, (float)0.74915353843834076, + (float)0.79370052598409979, (float)0.8408964152537145, + (float)0.89089871814033927, (float)0.94387431268169353, + (float)1.0, (float)1.0594630943592953, + (float)1.122462048309373, (float)1.189207115002721, + (float)1.2599210498948732, (float)1.3348398541700344, + (float)1.4142135623730951, (float)1.4983070768766815, + (float)1.5874010519681994, (float)1.681792830507429, + (float)1.7817974362806785, (float)1.8877486253633868, + (float)2.0, (float)2.1189261887185906, + (float)2.2449240966187456, (float)2.3784142300054421, + (float)2.5198420997897464, (float)2.6696797083400683, + (float)2.8284271247461903, (float)2.996614153753363, + (float)3.1748021039363987, (float)3.363585661014858, + (float)3.5635948725613571, (float)3.7754972507267737}; + +#if defined(PANPOT_REVA) +const UINT8 revacurve[] = { + 0, 4, 10, 14, 16, 17, 18, 19, 21, 22, 23, 25, 27, 28, 30, 32, + 35, 37, 39, 42, 44, 47, 49, 51, 54, 56, 59, 61, 64, 66, 69, 71, + 74, 76, 79, 81, 84, 86, 89, 91, 94, 97, 99,102,104,107,109,112, + 115,117,120,122,125,127,130,132,135,137,140,142,145,147,150,152, + 155,157,159,162,164,166,169,171,173,176,178,180,182,185,186,189, + 191,193,195,197,199,201,203,205,207,209,211,213,214,216,218,220, + 222,224,225,226,228,229,230,232,233,235,237,238,239,241,241,243, + 245,246,246,248,249,249,250,251,252,252,252,253,254,254,255,255}; +#endif + +#if defined(VOLUME_ACURVE) +const UINT8 acurve[] = { + 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, + 7, 8, 8, 9, 10, 10, 11, 11, 12, 13, 14, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 31, 32, 33, 35, 36, 38, + 39, 41, 42, 44, 46, 47, 49, 51, 52, 54, 56, 58, 60, 62, 64, 66, + 68, 70, 72, 74, 77, 79, 81, 83, 85, 88, 90, 93, 95, 98,100,102, + 105,108,110,113,116,119,121,124,127,130,133,136,138,141,145,148, + 150,154,157,160,163,167,170,173,176,180,183,186,189,193,196,199, + 203,206,210,213,217,220,224,227,231,234,238,242,245,249,253,255}; +#endif + diff --git a/sound/vermouth/midtable.h b/sound/vermouth/midtable.h old mode 100755 new mode 100644 index 8ce1a954..1d551ca8 --- a/sound/vermouth/midtable.h +++ b/sound/vermouth/midtable.h @@ -1,67 +1,67 @@ - -#define SINENT_BIT 9 - -enum { - MIDI_NOTE_OFF = 0x80, - MIDI_NOTE_ON = 0x90, - MIDI_KEYPRESS = 0xa0, - MIDI_CTRLCHANGE = 0xb0, - MIDI_PROGCHANGE = 0xc0, - MIDI_CHPRESS = 0xd0, - MIDI_PITCHBEND = 0xe0 -}; - -enum { - CTRL_PGBANK = 0, - CTRL_MODULAT = 1, - CTRL_PORTA_T = 5, - CTRL_DATA_M = 6, - CTRL_VOLUME = 7, - CTRL_PANPOT = 10, - CTRL_EXPRESS = 11, - CTRL_PGBANKH = 32, - CTRL_DATA_L = 38, - CTRL_PEDAL = 64, - CTRL_PORTAM = 65, - CTRL_SOSTEN = 66, - CTRL_SOFT = 67, - CTRL_LEGART = 84, - CTRL_REVERB = 91, - CTRL_CHORUS = 93, - CTRL_NRPN_L = 98, - CTRL_NRPN_M = 99, - CTRL_RPN_L = 100, - CTRL_RPN_M = 101, - CTRL_SOUNDOFF = 120, - CTRL_RESETCTRL = 121, - CTRL_LOCALCTRL = 122, - CTRL_NOTEOFF = 123, - CTRL_OMNIOFF = 124, - CTRL_OMNION = 125, - CTRL_MONOON = 126, - CTRL_POLYON = 127 -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern const SINT32 ver_freq_table[128]; -extern const SINT16 envsin12q[1 << (SINENT_BIT - 2)]; -extern const SINT16 vibsin12[1 << VIBRATE_SHIFT]; -extern const SINT16 voltbl12[128]; -extern const float bendltbl[64]; -extern const float bendhtbl[48]; - -#if defined(PANPOT_REVA) -extern const UINT8 revacurve[]; -#endif -#if defined(VOLUME_ACURVE) -extern const UINT8 acurve[]; -#endif - -#ifdef __cplusplus -} -#endif - + +#define SINENT_BIT 9 + +enum { + MIDI_NOTE_OFF = 0x80, + MIDI_NOTE_ON = 0x90, + MIDI_KEYPRESS = 0xa0, + MIDI_CTRLCHANGE = 0xb0, + MIDI_PROGCHANGE = 0xc0, + MIDI_CHPRESS = 0xd0, + MIDI_PITCHBEND = 0xe0 +}; + +enum { + CTRL_PGBANK = 0, + CTRL_MODULAT = 1, + CTRL_PORTA_T = 5, + CTRL_DATA_M = 6, + CTRL_VOLUME = 7, + CTRL_PANPOT = 10, + CTRL_EXPRESS = 11, + CTRL_PGBANKH = 32, + CTRL_DATA_L = 38, + CTRL_PEDAL = 64, + CTRL_PORTAM = 65, + CTRL_SOSTEN = 66, + CTRL_SOFT = 67, + CTRL_LEGART = 84, + CTRL_REVERB = 91, + CTRL_CHORUS = 93, + CTRL_NRPN_L = 98, + CTRL_NRPN_M = 99, + CTRL_RPN_L = 100, + CTRL_RPN_M = 101, + CTRL_SOUNDOFF = 120, + CTRL_RESETCTRL = 121, + CTRL_LOCALCTRL = 122, + CTRL_NOTEOFF = 123, + CTRL_OMNIOFF = 124, + CTRL_OMNION = 125, + CTRL_MONOON = 126, + CTRL_POLYON = 127 +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern const SINT32 ver_freq_table[128]; +extern const SINT16 envsin12q[1 << (SINENT_BIT - 2)]; +extern const SINT16 vibsin12[1 << VIBRATE_SHIFT]; +extern const SINT16 voltbl12[128]; +extern const float bendltbl[64]; +extern const float bendhtbl[48]; + +#if defined(PANPOT_REVA) +extern const UINT8 revacurve[]; +#endif +#if defined(VOLUME_ACURVE) +extern const UINT8 acurve[]; +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/sound/vermouth/midvoice.c b/sound/vermouth/midvoice.c old mode 100755 new mode 100644 index b2d33e3f..9c4d475b --- a/sound/vermouth/midvoice.c +++ b/sound/vermouth/midvoice.c @@ -1,883 +1,883 @@ -#include -#include "midiout.h" - - -#define RELBIT 6 - -#define SAMPMULREL(a, b) ((a) * (b >> RELBIT)) -#define SAMPMULVOL(a, b) ((a) * (b)) - -#define RESAMPLING(d, s, p) { \ - int dat1; \ - int dat2; \ - int _div; \ - dat1 = (s)[(p) >> FREQ_SHIFT]; \ - _div = (p) & FREQ_MASK; \ - if (_div) { \ - dat2 = (s)[((p) >> FREQ_SHIFT) + 1]; \ - dat1 += ((dat2 - dat1) * _div) >> FREQ_SHIFT; \ - } \ - *(d) = (_SAMPLE)dat1; \ -} - - -#if defined(ENABLE_VIRLATE) - -// ---- vibrate - -static int VERMOUTHCL vibrate_update(VOICE v) { - - int depth; - int phase; - int pitch; - float step; - - depth = v->sample->vibrate_depth << 6; - if (v->vibrate.sweepstep) { - v->vibrate.sweepcount += v->vibrate.sweepstep; - if (v->vibrate.sweepcount >= (1 << VIBSWEEP_SHIFT)) { - v->vibrate.sweepstep = 0; - } - else { - depth *= v->vibrate.sweepcount; - depth >>= VIBSWEEP_SHIFT; - } - } - - phase = v->vibrate.phase++; - phase &= (1 << VIBRATE_SHIFT) - 1; - pitch = (vibsin12[phase] * depth) >> 12; - step = v->freqnow * bendhtbl[(pitch >> (6 + 7)) + 24] * - bendltbl[(pitch >> 7) & 0x3f]; - return((int)(step * (float)(1 << FREQ_SHIFT))); -} - -static SAMPLE VERMOUTHCL resample_vibrate(VOICE v, SAMPLE dst, - SAMPLE dstterm) { - - SAMPLE src; - SAMPLE dstbreak; - int pos; - int step; - int last; - int cnt; - - src = v->sample->data; - pos = v->samppos; - step = v->sampstep; - if (step < 0) { - step *= -1; - } - last = v->sample->datasize; - - cnt = v->vibrate.count; - if (cnt == 0) { - cnt = v->vibrate.rate; - step = vibrate_update(v); - v->sampstep = step; - } - - dstbreak = dst + cnt; - if (dstbreak < dstterm) { - do { - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos > last) { - voice_setfree(v); - return(dst); - } - } while(dst < dstbreak); - - step = vibrate_update(v); - cnt = v->vibrate.rate; - dstbreak += cnt; - } while(dstbreak < dstterm); - v->sampstep = step; - } - v->vibrate.count = cnt - (int)(dstterm - dst); - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos > last) { - voice_setfree(v); - return(dst); - } - } while(dst < dstterm); - v->samppos = pos; - return(dst); -} - -static SAMPLE VERMOUTHCL resample_vibloop(VOICE v, SAMPLE dst, - SAMPLE dstterm) { - - SAMPLE src; - SAMPLE dstbreak; - int pos; - int step; - int last; - int cnt; - - src = v->sample->data; - pos = v->samppos; - step = v->sampstep; - last = v->sample->loopend; - - cnt = v->vibrate.count; - if (cnt == 0) { - step = vibrate_update(v); - cnt = v->vibrate.rate; - v->sampstep = step; - } - - dstbreak = dst + cnt; - if (dstbreak < dstterm) { - do { - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos > last) { - pos -= last - v->sample->loopstart; - } - } while(dst < dstbreak); - step = vibrate_update(v); - cnt = v->vibrate.rate; - dstbreak += cnt; - } while(dstbreak < dstterm); - v->sampstep = step; - } - v->vibrate.count = cnt - (int)(dstterm - dst); - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos > last) { - pos -= last - v->sample->loopstart; - } - } while(dst < dstterm); - - v->samppos = pos; - return(dst); -} - -static SAMPLE VERMOUTHCL resample_vibround(VOICE v, SAMPLE dst, - SAMPLE dstterm) { - - SAMPLE src; - SAMPLE dstbreak; - int pos; - int step; - int start; - int last; - int cnt; - BOOL stepsign; - - src = v->sample->data; - pos = v->samppos; - step = v->sampstep; - start = v->sample->loopstart; - last = v->sample->loopend; - - cnt = v->vibrate.count; - if (cnt == 0) { - cnt = v->vibrate.rate; - stepsign = (step < 0); - step = vibrate_update(v); - if (stepsign) { - step = 0 - step; - } - v->sampstep = step; - } - dstbreak = dst + cnt; - - if (step < 0) { - goto rr_backward; - } - - if (dstbreak < dstterm) { - do { - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos > last) { - pos = last - (pos - last); - step *= -1; - goto rr_backward1; - } -rr_forward1:; - } while(dst < dstbreak); - step = vibrate_update(v); - cnt = v->vibrate.rate; - dstbreak += cnt; - } while(dstbreak < dstterm); - } - v->vibrate.count = cnt - (int)(dstterm - dst); - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos > last) { - pos = last - (pos - last); - step *= -1; - goto rr_backward2; - } -rr_forward2:; - } while(dst < dstterm); - goto rr_done; - -rr_backward: - if (dstbreak < dstterm) { - do { - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos < start) { - pos = start + (start - pos); - step *= -1; - goto rr_forward1; - } -rr_backward1:; - } while(dst < dstbreak); - step = 0 - vibrate_update(v); - cnt = v->vibrate.rate; - dstbreak += cnt; - } while(dstbreak < dstterm); - } - v->vibrate.count = cnt - (int)(dstterm - dst); - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos < start) { - pos = start + (start - pos); - step *= -1; - goto rr_forward2; - } -rr_backward2:; - } while(dst < dstterm); - -rr_done: - v->samppos = pos; - v->sampstep = step; - return(dst); -} - -#endif - - -// ---- normal - -static SAMPLE VERMOUTHCL resample_normal(VOICE v, SAMPLE dst, SAMPLE dstterm) { - - SAMPLE src; - int pos; - int step; - int last; - - src = v->sample->data; - pos = v->samppos; - step = v->sampstep; - if (step < 0) { - step *= -1; - } - last = v->sample->datasize; - - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos > last) { - voice_setfree(v); - return(dst); - } - } while(dst < dstterm); - - v->samppos = pos; - return(dst); -} - -static SAMPLE VERMOUTHCL resample_loop(VOICE v, SAMPLE dst, SAMPLE dstterm) { - - SAMPLE src; - int pos; - int step; - int last; - - src = v->sample->data; - pos = v->samppos; - step = v->sampstep; - last = v->sample->loopend; - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos > last) { - pos -= last - v->sample->loopstart; - } - } while(dst < dstterm); - v->samppos = pos; - return(dst); -} - -static SAMPLE VERMOUTHCL resample_round(VOICE v, SAMPLE dst, SAMPLE dstterm) { - - SAMPLE src; - int pos; - int step; - int start; - int last; - - src = v->sample->data; - pos = v->samppos; - step = v->sampstep; - start = v->sample->loopstart; - last = v->sample->loopend; - - if (step < 0) { - goto rr_backward; - } -rr_forward: - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos > last) { - pos = last - (pos - last); - step *= -1; - if (dst < dstterm) { - goto rr_backward; - } - } - } while(dst < dstterm); - goto rr_done; - -rr_backward: - do { - RESAMPLING(dst, src, pos); - dst++; - pos += step; - if (pos < start) { - pos = start + (start - pos); - step *= -1; - if (dst < dstterm) { - goto rr_forward; - } - } - } while(dst < dstterm); - -rr_done: - v->samppos = pos; - v->sampstep = step; - return(dst); -} - - -// ---- - -int VERMOUTHCL envlope_setphase(VOICE v, int phase) { - - do { - if (phase >= 6) { - voice_setfree(v); - return(1); - } - if (v->sample->mode & MODE_ENVELOPE) { - if (v->phase & (VOICE_ON | VOICE_SUSTAIN)) { - if (phase >= 3) { - v->envstep = 0; - return(0); - } - } - } - phase += 1; - } while(v->envvol == v->sample->envpostbl[phase-1]); - v->envphase = phase; - v->envterm = v->sample->envpostbl[phase-1]; - v->envstep = v->sample->envratetbl[phase-1]; - if (v->envterm < v->envvol) { - v->envstep *= -1; - } - return(0); -} - -void VERMOUTHCL envelope_updates(VOICE v) { - - int envl; - int envr; - int vol; - - envl = v->volleft; - if ((v->flag & VOICE_MIXMASK) == VOICE_MIXNORMAL) { - envr = v->volright; -#if defined(ENABLE_TREMOLO) - if (v->tremolo.step) { - envl *= v->tremolo.volume; - envl >>= 12; - envr *= v->tremolo.volume; - envr >>= 12; - } -#endif - if (v->sample->mode & MODE_ENVELOPE) { - vol = voltbl12[v->envvol >> (7 + 9 + 1)]; - envl *= vol; - envl >>= 12; - envr *= vol; - envr >>= 12; - } - envl >>= (16 - SAMP_SHIFT); - if (envl > SAMP_LIMIT) { - envl = SAMP_LIMIT; - } - v->envleft = envl; - envr >>= (16 - SAMP_SHIFT); - if (envr > SAMP_LIMIT) { - envr = SAMP_LIMIT; - } - v->envright = envr; - } - else { -#if defined(ENABLE_TREMOLO) - if (v->tremolo.step) { - envl *= v->tremolo.volume; - envl >>= 12; - } -#endif - if (v->sample->mode & MODE_ENVELOPE) { - envl *= voltbl12[v->envvol >> (7 + 9 + 1)]; - envl >>= 12; - } - envl >>= (16 - SAMP_SHIFT); - if (envl > SAMP_LIMIT) { - envl = SAMP_LIMIT; - } - v->envleft = envl; - } -} - -#if defined(ENABLE_TREMOLO) -static void VERMOUTHCL tremolo_update(VOICE v) { - - int depth; - int cnt; - int vol; - int pos; - - depth = v->sample->tremolo_depth << 8; - if (v->tremolo.sweepstep) { - v->tremolo.sweepcount += v->tremolo.sweepstep; - if (v->tremolo.sweepcount < (1 << TRESWEEP_SHIFT)) { - depth *= v->tremolo.sweepcount; - depth >>= TRESWEEP_SHIFT; - } - else { - v->tremolo.sweepstep = 0; - } - } - v->tremolo.count += v->tremolo.step; - cnt = v->tremolo.count >> TRERATE_SHIFT; - pos = cnt & ((1 << (SINENT_BIT - 2)) - 1); - if (cnt & (1 << (SINENT_BIT - 2))) { - pos ^= ((1 << (SINENT_BIT - 2)) - 1); - } - vol = envsin12q[pos]; - if (cnt & (1 << (SINENT_BIT - 1))) { - vol = 0 - vol; - } - v->tremolo.volume = (1 << 12) - ((vol * depth) >> (2 + 8 + 8)); -} -#endif - -static int envelope_update(VOICE v) { - - if (v->envstep) { - v->envvol += v->envstep; - if (((v->envstep < 0) && (v->envvol <= v->envterm)) || - ((v->envstep > 0) && (v->envvol >= v->envterm))) { - v->envvol = v->envterm; - if (envlope_setphase(v, v->envphase)) { - return(1); - } - if (v->envstep == 0) { - voice_setmix(v); - } - } - } -#if defined(ENABLE_TREMOLO) - if (v->tremolo.step) { - tremolo_update(v); - } -#endif - envelope_updates(v); - return(0); -} - - -// ---- release - -static void VERMOUTHCL mixrel_normal(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - int samples; - SINT32 voll; - SINT32 rell; - SINT32 volr; - SINT32 relr; - _SAMPLE s; - - samples = (int)(srcterm - src); - voll = v->envleft << RELBIT; - rell = -(voll / samples); - if (!rell) { - rell = -1; - } - volr = v->envright << RELBIT; - relr = -(volr / samples); - if (!relr) { - relr = -1; - } - do { - s = *src++; - voll += rell; - if (voll > 0) { - dst[0] += SAMPMULREL(s, voll); - } - volr += relr; - if (volr > 0) { - dst[1] += SAMPMULREL(s, volr); - } - dst += 2; - } while(src < srcterm); -} - -static void VERMOUTHCL mixrel_left(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - SINT32 vol; - SINT32 rel; - _SAMPLE s; - - vol = v->envleft << RELBIT; - rel = - (vol / (int)(srcterm - src)); - if (!rel) { - rel = -1; - } - do { - vol += rel; - if (vol <= 0) { - break; - } - s = *src++; - dst[0] += SAMPMULREL(s, vol); - dst += 2; - } while(src < srcterm); -} - -static void VERMOUTHCL mixrel_right(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - mixrel_left(v, dst + 1, src, srcterm); -} - -static void VERMOUTHCL mixrel_centre(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - SINT32 vol; - SINT32 rel; - _SAMPLE s; - SINT32 d; - - vol = v->envleft << RELBIT; - rel = - (vol / (int)(srcterm - src)); - if (!rel) { - rel = -1; - } - do { - vol += rel; - if (vol <= 0) { - break; - } - s = *src++; - d = SAMPMULREL(s, vol); - dst[0] += d; - dst[1] += d; - dst += 2; - } while(src < srcterm); -} - - -// ---- normal - -static void VERMOUTHCL mixnor_normal(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - SINT32 voll; - SINT32 volr; - _SAMPLE s; - - voll = v->envleft; - volr = v->envright; - do { - s = *src++; - dst[0] += SAMPMULVOL(s, voll); - dst[1] += SAMPMULVOL(s, volr); - dst += 2; - } while(src < srcterm); -} - -static void VERMOUTHCL mixnor_left(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - SINT32 vol; - _SAMPLE s; - - vol = v->envleft; - do { - s = *src++; - dst[0] += SAMPMULVOL(s, vol); - dst += 2; - } while(src < srcterm); -} - -static void VERMOUTHCL mixnor_right(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - SINT32 vol; - _SAMPLE s; - - vol = v->envleft; - do { - s = *src++; - dst[1] += SAMPMULVOL(s, vol); - dst += 2; - } while(src < srcterm); -} - -static void VERMOUTHCL mixnor_centre(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - SINT32 vol; - _SAMPLE s; - SINT32 d; - - vol = v->envleft; - do { - s = *src++; - d = SAMPMULVOL(s, vol); - dst[0] += d; - dst[1] += d; - dst += 2; - } while(src < srcterm); -} - - -// ---- env - -static void VERMOUTHCL mixenv_normal(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - int cnt; - SINT32 voll; - SINT32 volr; - SAMPLE srcbreak; - _SAMPLE s; - - cnt = v->envcount; - if (!cnt) { - cnt = ENV_RATE; - if (envelope_update(v)) { - return; - } - } - voll = v->envleft; - volr = v->envright; - - srcbreak = src + cnt; - if (srcbreak < srcterm) { - do { - do { - s = *src++; - dst[0] += SAMPMULVOL(s, voll); - dst[1] += SAMPMULVOL(s, volr); - dst += 2; - } while(src < srcbreak); - cnt = ENV_RATE; - if (envelope_update(v)) { - return; - } - voll = v->envleft; - volr = v->envright; - srcbreak = src + cnt; - } while(srcbreak < srcterm); - } - - v->envcount = cnt - (int)(srcterm - src); - do { - s = *src++; - dst[0] += SAMPMULVOL(s, voll); - dst[1] += SAMPMULVOL(s, volr); - dst += 2; - } while(src < srcterm); -} - -static void VERMOUTHCL mixenv_left(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - int cnt; - SINT32 vol; - SAMPLE srcbreak; - _SAMPLE s; - - cnt = v->envcount; - if (!cnt) { - cnt = ENV_RATE; - if (envelope_update(v)) { - return; - } - } - vol = v->envleft; - - srcbreak = src + cnt; - if (srcbreak < srcterm) { - do { - do { - s = *src++; - dst[0] += SAMPMULVOL(s, vol); - dst += 2; - } while(src < srcbreak); - cnt = ENV_RATE; - if (envelope_update(v)) { - return; - } - vol = v->envleft; - srcbreak = src + cnt; - } while(srcbreak < srcterm); - } - - v->envcount = cnt - (int)(srcterm - src); - do { - s = *src++; - dst[0] += SAMPMULVOL(s, vol); - dst += 2; - } while(src < srcterm); -} - -static void VERMOUTHCL mixenv_right(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - mixenv_left(v, dst + 1, src, srcterm); -} - -static void VERMOUTHCL mixenv_centre(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm) { - - int cnt; - SINT32 vol; - SAMPLE srcbreak; - _SAMPLE s; - SINT32 d; - - cnt = v->envcount; - if (!cnt) { - cnt = ENV_RATE; - if (envelope_update(v)) { - return; - } - } - vol = v->envleft; - - srcbreak = src + cnt; - if (srcbreak < srcterm) { - do { - do { - s = *src++; - d = SAMPMULVOL(s, vol); - dst[0] += d; - dst[1] += d; - dst += 2; - } while(src < srcbreak); - cnt = ENV_RATE; - if (envelope_update(v)) { - return; - } - vol = v->envleft; - srcbreak = src + cnt; - } while(srcbreak < srcterm); - } - - v->envcount = cnt - (int)(srcterm - src); - do { - s = *src++; - d = SAMPMULVOL(s, vol); - dst[0] += d; - dst[1] += d; - dst += 2; - } while(src < srcterm); -} - - -// ---- - -static const RESPROC resproc[] = { - resample_normal, resample_loop, resample_round, -#if defined(ENABLE_VIRLATE) - resample_vibrate, resample_vibloop, resample_vibround, -#endif -}; - -void VERMOUTHCL voice_setphase(VOICE v, UINT8 phase) { - - int proc; - int mode; - - v->phase = phase; - -#if defined(ENABLE_VIRLATE) - proc = (v->vibrate.rate)?3:0; -#else - proc = 0; -#endif - mode = v->sample->mode; - if ((mode & MODE_LOOPING) && - ((mode & MODE_ENVELOPE) || (phase & (VOICE_ON | VOICE_SUSTAIN)))) { - proc++; - if (mode & MODE_PINGPONG) { - proc++; - } - } - v->resamp = resproc[proc]; -} - - -// ---- - -static const MIXPROC mixproc[] = { - mixnor_normal, mixnor_left, mixnor_right, mixnor_centre, - mixenv_normal, mixenv_left, mixenv_right, mixenv_centre, - mixrel_normal, mixrel_left, mixrel_right, mixrel_centre}; - -void VERMOUTHCL voice_setmix(VOICE v) { - - int proc; - - proc = v->flag & VOICE_MIXMASK; - if (!(v->phase & VOICE_REL)) { -#if defined(ENABLE_TREMOLO) - if ((v->envstep != 0) || (v->tremolo.step != 0)) -#else - if (v->envstep != 0) -#endif - { - proc += 1 << 2; - } - } - else { - proc += 2 << 2; - } - v->mix = mixproc[proc]; -} - +#include +#include "midiout.h" + + +#define RELBIT 6 + +#define SAMPMULREL(a, b) ((a) * (b >> RELBIT)) +#define SAMPMULVOL(a, b) ((a) * (b)) + +#define RESAMPLING(d, s, p) { \ + int dat1; \ + int dat2; \ + int _div; \ + dat1 = (s)[(p) >> FREQ_SHIFT]; \ + _div = (p) & FREQ_MASK; \ + if (_div) { \ + dat2 = (s)[((p) >> FREQ_SHIFT) + 1]; \ + dat1 += ((dat2 - dat1) * _div) >> FREQ_SHIFT; \ + } \ + *(d) = (_SAMPLE)dat1; \ +} + + +#if defined(ENABLE_VIRLATE) + +// ---- vibrate + +static int VERMOUTHCL vibrate_update(VOICE v) { + + int depth; + int phase; + int pitch; + float step; + + depth = v->sample->vibrate_depth << 6; + if (v->vibrate.sweepstep) { + v->vibrate.sweepcount += v->vibrate.sweepstep; + if (v->vibrate.sweepcount >= (1 << VIBSWEEP_SHIFT)) { + v->vibrate.sweepstep = 0; + } + else { + depth *= v->vibrate.sweepcount; + depth >>= VIBSWEEP_SHIFT; + } + } + + phase = v->vibrate.phase++; + phase &= (1 << VIBRATE_SHIFT) - 1; + pitch = (vibsin12[phase] * depth) >> 12; + step = v->freqnow * bendhtbl[(pitch >> (6 + 7)) + 24] * + bendltbl[(pitch >> 7) & 0x3f]; + return((int)(step * (float)(1 << FREQ_SHIFT))); +} + +static SAMPLE VERMOUTHCL resample_vibrate(VOICE v, SAMPLE dst, + SAMPLE dstterm) { + + SAMPLE src; + SAMPLE dstbreak; + int pos; + int step; + int last; + int cnt; + + src = v->sample->data; + pos = v->samppos; + step = v->sampstep; + if (step < 0) { + step *= -1; + } + last = v->sample->datasize; + + cnt = v->vibrate.count; + if (cnt == 0) { + cnt = v->vibrate.rate; + step = vibrate_update(v); + v->sampstep = step; + } + + dstbreak = dst + cnt; + if (dstbreak < dstterm) { + do { + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos > last) { + voice_setfree(v); + return(dst); + } + } while(dst < dstbreak); + + step = vibrate_update(v); + cnt = v->vibrate.rate; + dstbreak += cnt; + } while(dstbreak < dstterm); + v->sampstep = step; + } + v->vibrate.count = cnt - (int)(dstterm - dst); + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos > last) { + voice_setfree(v); + return(dst); + } + } while(dst < dstterm); + v->samppos = pos; + return(dst); +} + +static SAMPLE VERMOUTHCL resample_vibloop(VOICE v, SAMPLE dst, + SAMPLE dstterm) { + + SAMPLE src; + SAMPLE dstbreak; + int pos; + int step; + int last; + int cnt; + + src = v->sample->data; + pos = v->samppos; + step = v->sampstep; + last = v->sample->loopend; + + cnt = v->vibrate.count; + if (cnt == 0) { + step = vibrate_update(v); + cnt = v->vibrate.rate; + v->sampstep = step; + } + + dstbreak = dst + cnt; + if (dstbreak < dstterm) { + do { + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos > last) { + pos -= last - v->sample->loopstart; + } + } while(dst < dstbreak); + step = vibrate_update(v); + cnt = v->vibrate.rate; + dstbreak += cnt; + } while(dstbreak < dstterm); + v->sampstep = step; + } + v->vibrate.count = cnt - (int)(dstterm - dst); + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos > last) { + pos -= last - v->sample->loopstart; + } + } while(dst < dstterm); + + v->samppos = pos; + return(dst); +} + +static SAMPLE VERMOUTHCL resample_vibround(VOICE v, SAMPLE dst, + SAMPLE dstterm) { + + SAMPLE src; + SAMPLE dstbreak; + int pos; + int step; + int start; + int last; + int cnt; + BOOL stepsign; + + src = v->sample->data; + pos = v->samppos; + step = v->sampstep; + start = v->sample->loopstart; + last = v->sample->loopend; + + cnt = v->vibrate.count; + if (cnt == 0) { + cnt = v->vibrate.rate; + stepsign = (step < 0); + step = vibrate_update(v); + if (stepsign) { + step = 0 - step; + } + v->sampstep = step; + } + dstbreak = dst + cnt; + + if (step < 0) { + goto rr_backward; + } + + if (dstbreak < dstterm) { + do { + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos > last) { + pos = last - (pos - last); + step *= -1; + goto rr_backward1; + } +rr_forward1:; + } while(dst < dstbreak); + step = vibrate_update(v); + cnt = v->vibrate.rate; + dstbreak += cnt; + } while(dstbreak < dstterm); + } + v->vibrate.count = cnt - (int)(dstterm - dst); + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos > last) { + pos = last - (pos - last); + step *= -1; + goto rr_backward2; + } +rr_forward2:; + } while(dst < dstterm); + goto rr_done; + +rr_backward: + if (dstbreak < dstterm) { + do { + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos < start) { + pos = start + (start - pos); + step *= -1; + goto rr_forward1; + } +rr_backward1:; + } while(dst < dstbreak); + step = 0 - vibrate_update(v); + cnt = v->vibrate.rate; + dstbreak += cnt; + } while(dstbreak < dstterm); + } + v->vibrate.count = cnt - (int)(dstterm - dst); + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos < start) { + pos = start + (start - pos); + step *= -1; + goto rr_forward2; + } +rr_backward2:; + } while(dst < dstterm); + +rr_done: + v->samppos = pos; + v->sampstep = step; + return(dst); +} + +#endif + + +// ---- normal + +static SAMPLE VERMOUTHCL resample_normal(VOICE v, SAMPLE dst, SAMPLE dstterm) { + + SAMPLE src; + int pos; + int step; + int last; + + src = v->sample->data; + pos = v->samppos; + step = v->sampstep; + if (step < 0) { + step *= -1; + } + last = v->sample->datasize; + + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos > last) { + voice_setfree(v); + return(dst); + } + } while(dst < dstterm); + + v->samppos = pos; + return(dst); +} + +static SAMPLE VERMOUTHCL resample_loop(VOICE v, SAMPLE dst, SAMPLE dstterm) { + + SAMPLE src; + int pos; + int step; + int last; + + src = v->sample->data; + pos = v->samppos; + step = v->sampstep; + last = v->sample->loopend; + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos > last) { + pos -= last - v->sample->loopstart; + } + } while(dst < dstterm); + v->samppos = pos; + return(dst); +} + +static SAMPLE VERMOUTHCL resample_round(VOICE v, SAMPLE dst, SAMPLE dstterm) { + + SAMPLE src; + int pos; + int step; + int start; + int last; + + src = v->sample->data; + pos = v->samppos; + step = v->sampstep; + start = v->sample->loopstart; + last = v->sample->loopend; + + if (step < 0) { + goto rr_backward; + } +rr_forward: + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos > last) { + pos = last - (pos - last); + step *= -1; + if (dst < dstterm) { + goto rr_backward; + } + } + } while(dst < dstterm); + goto rr_done; + +rr_backward: + do { + RESAMPLING(dst, src, pos); + dst++; + pos += step; + if (pos < start) { + pos = start + (start - pos); + step *= -1; + if (dst < dstterm) { + goto rr_forward; + } + } + } while(dst < dstterm); + +rr_done: + v->samppos = pos; + v->sampstep = step; + return(dst); +} + + +// ---- + +int VERMOUTHCL envlope_setphase(VOICE v, int phase) { + + do { + if (phase >= 6) { + voice_setfree(v); + return(1); + } + if (v->sample->mode & MODE_ENVELOPE) { + if (v->phase & (VOICE_ON | VOICE_SUSTAIN)) { + if (phase >= 3) { + v->envstep = 0; + return(0); + } + } + } + phase += 1; + } while(v->envvol == v->sample->envpostbl[phase-1]); + v->envphase = phase; + v->envterm = v->sample->envpostbl[phase-1]; + v->envstep = v->sample->envratetbl[phase-1]; + if (v->envterm < v->envvol) { + v->envstep *= -1; + } + return(0); +} + +void VERMOUTHCL envelope_updates(VOICE v) { + + int envl; + int envr; + int vol; + + envl = v->volleft; + if ((v->flag & VOICE_MIXMASK) == VOICE_MIXNORMAL) { + envr = v->volright; +#if defined(ENABLE_TREMOLO) + if (v->tremolo.step) { + envl *= v->tremolo.volume; + envl >>= 12; + envr *= v->tremolo.volume; + envr >>= 12; + } +#endif + if (v->sample->mode & MODE_ENVELOPE) { + vol = voltbl12[v->envvol >> (7 + 9 + 1)]; + envl *= vol; + envl >>= 12; + envr *= vol; + envr >>= 12; + } + envl >>= (16 - SAMP_SHIFT); + if (envl > SAMP_LIMIT) { + envl = SAMP_LIMIT; + } + v->envleft = envl; + envr >>= (16 - SAMP_SHIFT); + if (envr > SAMP_LIMIT) { + envr = SAMP_LIMIT; + } + v->envright = envr; + } + else { +#if defined(ENABLE_TREMOLO) + if (v->tremolo.step) { + envl *= v->tremolo.volume; + envl >>= 12; + } +#endif + if (v->sample->mode & MODE_ENVELOPE) { + envl *= voltbl12[v->envvol >> (7 + 9 + 1)]; + envl >>= 12; + } + envl >>= (16 - SAMP_SHIFT); + if (envl > SAMP_LIMIT) { + envl = SAMP_LIMIT; + } + v->envleft = envl; + } +} + +#if defined(ENABLE_TREMOLO) +static void VERMOUTHCL tremolo_update(VOICE v) { + + int depth; + int cnt; + int vol; + int pos; + + depth = v->sample->tremolo_depth << 8; + if (v->tremolo.sweepstep) { + v->tremolo.sweepcount += v->tremolo.sweepstep; + if (v->tremolo.sweepcount < (1 << TRESWEEP_SHIFT)) { + depth *= v->tremolo.sweepcount; + depth >>= TRESWEEP_SHIFT; + } + else { + v->tremolo.sweepstep = 0; + } + } + v->tremolo.count += v->tremolo.step; + cnt = v->tremolo.count >> TRERATE_SHIFT; + pos = cnt & ((1 << (SINENT_BIT - 2)) - 1); + if (cnt & (1 << (SINENT_BIT - 2))) { + pos ^= ((1 << (SINENT_BIT - 2)) - 1); + } + vol = envsin12q[pos]; + if (cnt & (1 << (SINENT_BIT - 1))) { + vol = 0 - vol; + } + v->tremolo.volume = (1 << 12) - ((vol * depth) >> (2 + 8 + 8)); +} +#endif + +static int envelope_update(VOICE v) { + + if (v->envstep) { + v->envvol += v->envstep; + if (((v->envstep < 0) && (v->envvol <= v->envterm)) || + ((v->envstep > 0) && (v->envvol >= v->envterm))) { + v->envvol = v->envterm; + if (envlope_setphase(v, v->envphase)) { + return(1); + } + if (v->envstep == 0) { + voice_setmix(v); + } + } + } +#if defined(ENABLE_TREMOLO) + if (v->tremolo.step) { + tremolo_update(v); + } +#endif + envelope_updates(v); + return(0); +} + + +// ---- release + +static void VERMOUTHCL mixrel_normal(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + int samples; + SINT32 voll; + SINT32 rell; + SINT32 volr; + SINT32 relr; + _SAMPLE s; + + samples = (int)(srcterm - src); + voll = v->envleft << RELBIT; + rell = -(voll / samples); + if (!rell) { + rell = -1; + } + volr = v->envright << RELBIT; + relr = -(volr / samples); + if (!relr) { + relr = -1; + } + do { + s = *src++; + voll += rell; + if (voll > 0) { + dst[0] += SAMPMULREL(s, voll); + } + volr += relr; + if (volr > 0) { + dst[1] += SAMPMULREL(s, volr); + } + dst += 2; + } while(src < srcterm); +} + +static void VERMOUTHCL mixrel_left(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + SINT32 vol; + SINT32 rel; + _SAMPLE s; + + vol = v->envleft << RELBIT; + rel = - (vol / (int)(srcterm - src)); + if (!rel) { + rel = -1; + } + do { + vol += rel; + if (vol <= 0) { + break; + } + s = *src++; + dst[0] += SAMPMULREL(s, vol); + dst += 2; + } while(src < srcterm); +} + +static void VERMOUTHCL mixrel_right(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + mixrel_left(v, dst + 1, src, srcterm); +} + +static void VERMOUTHCL mixrel_centre(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + SINT32 vol; + SINT32 rel; + _SAMPLE s; + SINT32 d; + + vol = v->envleft << RELBIT; + rel = - (vol / (int)(srcterm - src)); + if (!rel) { + rel = -1; + } + do { + vol += rel; + if (vol <= 0) { + break; + } + s = *src++; + d = SAMPMULREL(s, vol); + dst[0] += d; + dst[1] += d; + dst += 2; + } while(src < srcterm); +} + + +// ---- normal + +static void VERMOUTHCL mixnor_normal(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + SINT32 voll; + SINT32 volr; + _SAMPLE s; + + voll = v->envleft; + volr = v->envright; + do { + s = *src++; + dst[0] += SAMPMULVOL(s, voll); + dst[1] += SAMPMULVOL(s, volr); + dst += 2; + } while(src < srcterm); +} + +static void VERMOUTHCL mixnor_left(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + SINT32 vol; + _SAMPLE s; + + vol = v->envleft; + do { + s = *src++; + dst[0] += SAMPMULVOL(s, vol); + dst += 2; + } while(src < srcterm); +} + +static void VERMOUTHCL mixnor_right(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + SINT32 vol; + _SAMPLE s; + + vol = v->envleft; + do { + s = *src++; + dst[1] += SAMPMULVOL(s, vol); + dst += 2; + } while(src < srcterm); +} + +static void VERMOUTHCL mixnor_centre(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + SINT32 vol; + _SAMPLE s; + SINT32 d; + + vol = v->envleft; + do { + s = *src++; + d = SAMPMULVOL(s, vol); + dst[0] += d; + dst[1] += d; + dst += 2; + } while(src < srcterm); +} + + +// ---- env + +static void VERMOUTHCL mixenv_normal(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + int cnt; + SINT32 voll; + SINT32 volr; + SAMPLE srcbreak; + _SAMPLE s; + + cnt = v->envcount; + if (!cnt) { + cnt = ENV_RATE; + if (envelope_update(v)) { + return; + } + } + voll = v->envleft; + volr = v->envright; + + srcbreak = src + cnt; + if (srcbreak < srcterm) { + do { + do { + s = *src++; + dst[0] += SAMPMULVOL(s, voll); + dst[1] += SAMPMULVOL(s, volr); + dst += 2; + } while(src < srcbreak); + cnt = ENV_RATE; + if (envelope_update(v)) { + return; + } + voll = v->envleft; + volr = v->envright; + srcbreak = src + cnt; + } while(srcbreak < srcterm); + } + + v->envcount = cnt - (int)(srcterm - src); + do { + s = *src++; + dst[0] += SAMPMULVOL(s, voll); + dst[1] += SAMPMULVOL(s, volr); + dst += 2; + } while(src < srcterm); +} + +static void VERMOUTHCL mixenv_left(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + int cnt; + SINT32 vol; + SAMPLE srcbreak; + _SAMPLE s; + + cnt = v->envcount; + if (!cnt) { + cnt = ENV_RATE; + if (envelope_update(v)) { + return; + } + } + vol = v->envleft; + + srcbreak = src + cnt; + if (srcbreak < srcterm) { + do { + do { + s = *src++; + dst[0] += SAMPMULVOL(s, vol); + dst += 2; + } while(src < srcbreak); + cnt = ENV_RATE; + if (envelope_update(v)) { + return; + } + vol = v->envleft; + srcbreak = src + cnt; + } while(srcbreak < srcterm); + } + + v->envcount = cnt - (int)(srcterm - src); + do { + s = *src++; + dst[0] += SAMPMULVOL(s, vol); + dst += 2; + } while(src < srcterm); +} + +static void VERMOUTHCL mixenv_right(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + mixenv_left(v, dst + 1, src, srcterm); +} + +static void VERMOUTHCL mixenv_centre(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm) { + + int cnt; + SINT32 vol; + SAMPLE srcbreak; + _SAMPLE s; + SINT32 d; + + cnt = v->envcount; + if (!cnt) { + cnt = ENV_RATE; + if (envelope_update(v)) { + return; + } + } + vol = v->envleft; + + srcbreak = src + cnt; + if (srcbreak < srcterm) { + do { + do { + s = *src++; + d = SAMPMULVOL(s, vol); + dst[0] += d; + dst[1] += d; + dst += 2; + } while(src < srcbreak); + cnt = ENV_RATE; + if (envelope_update(v)) { + return; + } + vol = v->envleft; + srcbreak = src + cnt; + } while(srcbreak < srcterm); + } + + v->envcount = cnt - (int)(srcterm - src); + do { + s = *src++; + d = SAMPMULVOL(s, vol); + dst[0] += d; + dst[1] += d; + dst += 2; + } while(src < srcterm); +} + + +// ---- + +static const RESPROC resproc[] = { + resample_normal, resample_loop, resample_round, +#if defined(ENABLE_VIRLATE) + resample_vibrate, resample_vibloop, resample_vibround, +#endif +}; + +void VERMOUTHCL voice_setphase(VOICE v, UINT8 phase) { + + int proc; + int mode; + + v->phase = phase; + +#if defined(ENABLE_VIRLATE) + proc = (v->vibrate.rate)?3:0; +#else + proc = 0; +#endif + mode = v->sample->mode; + if ((mode & MODE_LOOPING) && + ((mode & MODE_ENVELOPE) || (phase & (VOICE_ON | VOICE_SUSTAIN)))) { + proc++; + if (mode & MODE_PINGPONG) { + proc++; + } + } + v->resamp = resproc[proc]; +} + + +// ---- + +static const MIXPROC mixproc[] = { + mixnor_normal, mixnor_left, mixnor_right, mixnor_centre, + mixenv_normal, mixenv_left, mixenv_right, mixenv_centre, + mixrel_normal, mixrel_left, mixrel_right, mixrel_centre}; + +void VERMOUTHCL voice_setmix(VOICE v) { + + int proc; + + proc = v->flag & VOICE_MIXMASK; + if (!(v->phase & VOICE_REL)) { +#if defined(ENABLE_TREMOLO) + if ((v->envstep != 0) || (v->tremolo.step != 0)) +#else + if (v->envstep != 0) +#endif + { + proc += 1 << 2; + } + } + else { + proc += 2 << 2; + } + v->mix = mixproc[proc]; +} + diff --git a/sound/vermouth/midvoice.h b/sound/vermouth/midvoice.h old mode 100755 new mode 100644 index 25f15bc9..4fd75b0e --- a/sound/vermouth/midvoice.h +++ b/sound/vermouth/midvoice.h @@ -1,158 +1,158 @@ - -struct _midivoice; -typedef struct _midivoice _VOICE; -typedef struct _midivoice *VOICE; - -typedef void (VERMOUTHCL *MIXPROC)(VOICE v, SINT32 *dst, SAMPLE src, - SAMPLE srcterm); -typedef SAMPLE (VERMOUTHCL *RESPROC)(VOICE v, SAMPLE dst, SAMPLE dstterm); - -enum { - CHANNEL_MASK = 0x0f, - CHANNEL_RHYTHM = 0x10, - CHANNEL_SUSTAIN = 0x20, - CHANNEL_MONO = 0x40 -}; - -enum { - VOICE_FREE = 0x00, - VOICE_ON = 0x01, - VOICE_SUSTAIN = 0x02, - VOICE_OFF = 0x04, - VOICE_REL = 0x08 -}; - -enum { - VOICE_MIXNORMAL = 0x00, - VOICE_MIXLEFT = 0x01, - VOICE_MIXRIGHT = 0x02, - VOICE_MIXCENTRE = 0x03, - VOICE_MIXMASK = 0x03, - VOICE_FIXPITCH = 0x04 -}; - -#if !defined(MIDI_GMONLY) -enum { - GSRX0_PITCHBEND = 0x01, - GSRX0_CHPRESSURE = 0x02, - GSRX0_PROGRAMCHANGE = 0x04, - GSRX0_CONTROLCHANGE = 0x08, - GSRX0_POLYPRESSURE = 0x10, - GSRX0_NOTEMESSAGE = 0x20, - GSRX0_RPN = 0x40, - GSRX0_NRPN = 0x80, - GSRX1_MODULATION = 0x01, - GSRX1_VOLUE = 0x02, - GSRX1_PANPOT = 0x04, - GSRX1_EXPRESSION = 0x08, - GSRX1_HOLD1 = 0x10, - GSRX1_PORTAMENTO = 0x20, - GSRX1_SOSTENUTO = 0x40, - GSRX1_SOFT = 0x80, - GSRX2_BANKSELECT = 0x01, - GSRX2_BANKSELECTLSB = 0x02 -}; -#endif - -typedef struct { - UINT flag; - int level; - int pitchbend; - int pitchsens; - float pitchfactor; - INSTRUMENT inst; -#if !defined(MIDI_GMONLY) - INSTRUMENT *rhythm; -#endif - -#if !defined(MIDI_GMONLY) - UINT8 bank; -#endif - UINT8 program; - UINT8 volume; - UINT8 expression; - UINT8 panpot; - UINT8 rpn_l; - UINT8 rpn_m; -#if defined(ENABLE_GSRX) - UINT8 keyshift; - UINT8 noterange[2]; - UINT8 gsrx[4]; -#endif -} _CHANNEL, *CHANNEL; - -typedef struct { - int sweepstep; - int sweepcount; - int count; - int step; - int volume; -} VOICETRE; - -typedef struct { - int sweepstep; - int sweepcount; - int phase; - int rate; - int count; -} VOICEVIB; - -struct _midivoice { - UINT8 phase; - UINT8 flag; - UINT8 note; - UINT8 velocity; - - CHANNEL channel; - int frequency; - float freq; - int panpot; - - MIXPROC mix; - RESPROC resamp; - INSTLAYER sample; - int samppos; - int sampstep; - int envvol; - int envterm; - int envstep; - int envleft; - int envright; - int envphase; - int envcount; - - int volleft; - int volright; - -#if defined(ENABLE_TREMOLO) - VOICETRE tremolo; -#endif -#if defined(ENABLE_VIRLATE) - float freqnow; - VOICEVIB vibrate; -#endif -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -int VERMOUTHCL envlope_setphase(VOICE v, int phase); -void VERMOUTHCL envelope_updates(VOICE v); - -void VERMOUTHCL voice_setphase(VOICE v, UINT8 phase); -void VERMOUTHCL voice_setmix(VOICE v); - -#ifdef __cplusplus -} -#endif - - -// ---- macro - -#define voice_setfree(v) \ - do { \ - (v)->phase = VOICE_FREE; \ - } while(0 /*CONSTCOND*/) - + +struct _midivoice; +typedef struct _midivoice _VOICE; +typedef struct _midivoice *VOICE; + +typedef void (VERMOUTHCL *MIXPROC)(VOICE v, SINT32 *dst, SAMPLE src, + SAMPLE srcterm); +typedef SAMPLE (VERMOUTHCL *RESPROC)(VOICE v, SAMPLE dst, SAMPLE dstterm); + +enum { + CHANNEL_MASK = 0x0f, + CHANNEL_RHYTHM = 0x10, + CHANNEL_SUSTAIN = 0x20, + CHANNEL_MONO = 0x40 +}; + +enum { + VOICE_FREE = 0x00, + VOICE_ON = 0x01, + VOICE_SUSTAIN = 0x02, + VOICE_OFF = 0x04, + VOICE_REL = 0x08 +}; + +enum { + VOICE_MIXNORMAL = 0x00, + VOICE_MIXLEFT = 0x01, + VOICE_MIXRIGHT = 0x02, + VOICE_MIXCENTRE = 0x03, + VOICE_MIXMASK = 0x03, + VOICE_FIXPITCH = 0x04 +}; + +#if !defined(MIDI_GMONLY) +enum { + GSRX0_PITCHBEND = 0x01, + GSRX0_CHPRESSURE = 0x02, + GSRX0_PROGRAMCHANGE = 0x04, + GSRX0_CONTROLCHANGE = 0x08, + GSRX0_POLYPRESSURE = 0x10, + GSRX0_NOTEMESSAGE = 0x20, + GSRX0_RPN = 0x40, + GSRX0_NRPN = 0x80, + GSRX1_MODULATION = 0x01, + GSRX1_VOLUE = 0x02, + GSRX1_PANPOT = 0x04, + GSRX1_EXPRESSION = 0x08, + GSRX1_HOLD1 = 0x10, + GSRX1_PORTAMENTO = 0x20, + GSRX1_SOSTENUTO = 0x40, + GSRX1_SOFT = 0x80, + GSRX2_BANKSELECT = 0x01, + GSRX2_BANKSELECTLSB = 0x02 +}; +#endif + +typedef struct { + UINT flag; + int level; + int pitchbend; + int pitchsens; + float pitchfactor; + INSTRUMENT inst; +#if !defined(MIDI_GMONLY) + INSTRUMENT *rhythm; +#endif + +#if !defined(MIDI_GMONLY) + UINT8 bank; +#endif + UINT8 program; + UINT8 volume; + UINT8 expression; + UINT8 panpot; + UINT8 rpn_l; + UINT8 rpn_m; +#if defined(ENABLE_GSRX) + UINT8 keyshift; + UINT8 noterange[2]; + UINT8 gsrx[4]; +#endif +} _CHANNEL, *CHANNEL; + +typedef struct { + int sweepstep; + int sweepcount; + int count; + int step; + int volume; +} VOICETRE; + +typedef struct { + int sweepstep; + int sweepcount; + int phase; + int rate; + int count; +} VOICEVIB; + +struct _midivoice { + UINT8 phase; + UINT8 flag; + UINT8 note; + UINT8 velocity; + + CHANNEL channel; + int frequency; + float freq; + int panpot; + + MIXPROC mix; + RESPROC resamp; + INSTLAYER sample; + int samppos; + int sampstep; + int envvol; + int envterm; + int envstep; + int envleft; + int envright; + int envphase; + int envcount; + + int volleft; + int volright; + +#if defined(ENABLE_TREMOLO) + VOICETRE tremolo; +#endif +#if defined(ENABLE_VIRLATE) + float freqnow; + VOICEVIB vibrate; +#endif +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +int VERMOUTHCL envlope_setphase(VOICE v, int phase); +void VERMOUTHCL envelope_updates(VOICE v); + +void VERMOUTHCL voice_setphase(VOICE v, UINT8 phase); +void VERMOUTHCL voice_setmix(VOICE v); + +#ifdef __cplusplus +} +#endif + + +// ---- macro + +#define voice_setfree(v) \ + do { \ + (v)->phase = VOICE_FREE; \ + } while(0 /*CONSTCOND*/) + diff --git a/sound/vermouth/vermouth.h b/sound/vermouth/vermouth.h old mode 100755 new mode 100644 index 44d5615a..02de43e4 --- a/sound/vermouth/vermouth.h +++ b/sound/vermouth/vermouth.h @@ -1,67 +1,67 @@ - -#ifndef __VERMOUTH_H -#define __VERMOUTH_H - -#ifndef VERMOUTHCL -#define VERMOUTHCL -#endif - -#ifndef VERMOUTH_EXPORTS -#define VEXTERN -#define VEXPORT VERMOUTHCL -#else -#define VEXTERN __declspec(dllexport) -#define VEXPORT WINAPI -#endif - -typedef struct { - UINT samprate; -} *MIDIMOD; - -typedef struct { - UINT samprate; - UINT worksize; -} *MIDIHDL; - -typedef struct { - void *userdata; - UINT totaltones; - UINT progress; - UINT bank; - UINT num; -} MIDIOUTLAEXPARAM; -typedef BRESULT (*FNMIDIOUTLAEXCB)(MIDIOUTLAEXPARAM *param); - - -#ifdef __cplusplus -extern "C" { -#endif - -VEXTERN UINT VEXPORT midiout_getver(char *string, UINT leng); -VEXTERN MIDIHDL VEXPORT midiout_create(MIDIMOD mod, UINT worksize); -VEXTERN void VEXPORT midiout_destroy(MIDIHDL hdl); -VEXTERN void VEXPORT midiout_shortmsg(MIDIHDL hdl, UINT32 msg); -VEXTERN void VEXPORT midiout_longmsg(MIDIHDL hdl, const void *msg, UINT size); -VEXTERN const SINT32 * VEXPORT midiout_get(MIDIHDL hdl, UINT *samples); -VEXTERN UINT VEXPORT midiout_get16(MIDIHDL hdl, SINT16 *pcm, UINT size); -VEXTERN UINT VEXPORT midiout_get32(MIDIHDL hdl, SINT32 *pcm, UINT size); -VEXTERN void VEXPORT midiout_setgain(MIDIHDL hdl, int gain); -VEXTERN void VEXPORT midiout_setmoduleid(MIDIHDL hdl, UINT8 moduleid); -VEXTERN void VEXPORT midiout_setportb(MIDIHDL hdl, MIDIHDL portb); - -VEXTERN MIDIMOD VEXPORT midimod_create(UINT samprate); -VEXTERN void VEXPORT midimod_destroy(MIDIMOD hdl); -VEXTERN void VEXPORT midimod_destroy(MIDIMOD hdl); -VEXTERN BRESULT VEXPORT midimod_cfgload(MIDIMOD mod, const OEMCHAR *filename); -VEXTERN void VEXPORT midimod_loadprogram(MIDIMOD hdl, UINT num); -VEXTERN void VEXPORT midimod_loadrhythm(MIDIMOD hdl, UINT num); -VEXTERN void VEXPORT midimod_loadgm(MIDIMOD hdl); -VEXTERN void VEXPORT midimod_loadall(MIDIMOD hdl); -VEXTERN int VEXPORT midimod_loadallex(MIDIMOD hdl, FNMIDIOUTLAEXCB cb, void *userdata); - -#ifdef __cplusplus -} -#endif - -#endif - + +#ifndef __VERMOUTH_H +#define __VERMOUTH_H + +#ifndef VERMOUTHCL +#define VERMOUTHCL +#endif + +#ifndef VERMOUTH_EXPORTS +#define VEXTERN +#define VEXPORT VERMOUTHCL +#else +#define VEXTERN __declspec(dllexport) +#define VEXPORT WINAPI +#endif + +typedef struct { + UINT samprate; +} *MIDIMOD; + +typedef struct { + UINT samprate; + UINT worksize; +} *MIDIHDL; + +typedef struct { + void *userdata; + UINT totaltones; + UINT progress; + UINT bank; + UINT num; +} MIDIOUTLAEXPARAM; +typedef BRESULT (*FNMIDIOUTLAEXCB)(MIDIOUTLAEXPARAM *param); + + +#ifdef __cplusplus +extern "C" { +#endif + +VEXTERN UINT VEXPORT midiout_getver(char *string, UINT leng); +VEXTERN MIDIHDL VEXPORT midiout_create(MIDIMOD mod, UINT worksize); +VEXTERN void VEXPORT midiout_destroy(MIDIHDL hdl); +VEXTERN void VEXPORT midiout_shortmsg(MIDIHDL hdl, UINT32 msg); +VEXTERN void VEXPORT midiout_longmsg(MIDIHDL hdl, const void *msg, UINT size); +VEXTERN const SINT32 * VEXPORT midiout_get(MIDIHDL hdl, UINT *samples); +VEXTERN UINT VEXPORT midiout_get16(MIDIHDL hdl, SINT16 *pcm, UINT size); +VEXTERN UINT VEXPORT midiout_get32(MIDIHDL hdl, SINT32 *pcm, UINT size); +VEXTERN void VEXPORT midiout_setgain(MIDIHDL hdl, int gain); +VEXTERN void VEXPORT midiout_setmoduleid(MIDIHDL hdl, UINT8 moduleid); +VEXTERN void VEXPORT midiout_setportb(MIDIHDL hdl, MIDIHDL portb); + +VEXTERN MIDIMOD VEXPORT midimod_create(UINT samprate); +VEXTERN void VEXPORT midimod_destroy(MIDIMOD hdl); +VEXTERN void VEXPORT midimod_destroy(MIDIMOD hdl); +VEXTERN BRESULT VEXPORT midimod_cfgload(MIDIMOD mod, const OEMCHAR *filename); +VEXTERN void VEXPORT midimod_loadprogram(MIDIMOD hdl, UINT num); +VEXTERN void VEXPORT midimod_loadrhythm(MIDIMOD hdl, UINT num); +VEXTERN void VEXPORT midimod_loadgm(MIDIMOD hdl); +VEXTERN void VEXPORT midimod_loadall(MIDIMOD hdl); +VEXTERN int VEXPORT midimod_loadallex(MIDIMOD hdl, FNMIDIOUTLAEXCB cb, void *userdata); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/statsave.c b/statsave.c old mode 100755 new mode 100644 index 5b5c81d7..14af2252 --- a/statsave.c +++ b/statsave.c @@ -1,2103 +1,2103 @@ -/** - * @file statsave.cpp - * @brief Implementation of State save - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "mousemng.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_SMPU98) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef SUPPORT_SOUND_SB16 -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_HOSTDRVNT) -#include -#endif -#include -#include -#include -#if defined(SUPPORT_WAB) -#include -#endif -#if defined(SUPPORT_CL_GD5430) -#include -#endif -#if defined(SUPPORT_NET) -#include -#endif -#if defined(SUPPORT_LGY98) -#include -#include -#endif -#if defined(CPUCORE_IA32) -#include -#endif -#if defined(BIOS_IO_EMULATION) -#include -#endif -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif - -uint8_t g_u8ControlState; -static OEMCHAR m_strStateFilename[MAX_PATH]; - -#ifdef USE_MAME -#ifdef USE_MAME_BSD -#if defined(_MSC_VER) -#if _MSC_VER < 1900 -#include -#else -#include -#endif -#else -#include -#endif -#else -#include -#endif -#endif - -extern int sxsi_unittbl[]; - -#if defined(MACOS) -#define CRCONST str_cr -#else -#define CRCONST str_lf -#endif - -typedef struct { - char name[16]; - char vername[28]; - UINT32 ver; -} NP2FHDR; - -typedef struct { - char index[10]; - UINT16 ver; - UINT32 size; -} NP2FENT; - -/** - * @brief handle - */ -struct TagStatFlagHandle -{ - NP2FENT hdr; - UINT pos; - OEMCHAR *err; - int errlen; -}; -typedef struct TagStatFlagHandle _STFLAGH; /* define */ - -enum -{ - STATFLAG_BIN = 0, - STATFLAG_TERM, - STATFLAG_COM, - STATFLAG_DMA, - STATFLAG_EGC, - STATFLAG_EPSON, - STATFLAG_EVT, - STATFLAG_EXT, - STATFLAG_FDD, - STATFLAG_FM, - STATFLAG_GIJ, -#if defined(SUPPORT_HOSTDRV) - STATFLAG_HDRV, -#endif - STATFLAG_MEM, -#if defined(SUPPORT_BMS) - STATFLAG_BMS, -#endif - STATFLAG_SXSI, - STATFLAG_HDRVNT, - STATFLAG_MASK = 0x3fff, - - STATFLAG_BWD_COMPATIBLE = 0x4000, // このフラグが立っているとき、古いバージョンのステートセーブと互換性がある(足りないデータは0で埋められるので注意する)いまのところSTATFLAG_BINのみサポート - STATFLAG_FWD_COMPATIBLE = 0x8000, // このフラグが立っているとき、新しいバージョンのステートセーブと互換性がある(足りないデータは無かったことになるので注意する)いまのところSTATFLAG_BINのみサポート -}; - -typedef struct { - UINT32 id; - void *proc; -} PROCTBL; - -typedef struct { - UINT32 id; - NEVENTID num; -} ENUMTBL; - -#define PROCID(a, b, c, d) (((d) << 24) + ((c) << 16) + ((b) << 8) + (a)) -#define PROC2NUM(a, b) proc2num(&(a), (b), sizeof(b)/sizeof(PROCTBL)) -#define NUM2PROC(a, b) num2proc(&(a), (b), sizeof(b)/sizeof(PROCTBL)) - -#include "statsave.tbl" - - -extern COMMNG cm_mpu98; -#if defined(SUPPORT_SMPU98) -extern COMMNG cm_smpu98[]; -#endif -extern COMMNG cm_rs232c; - -typedef struct { - OEMCHAR *buf; - int remain; -} ERR_BUF; - - -// ---- - -enum { - SFFILEH_WRITE = 0x0001, - SFFILEH_BLOCK = 0x0002, - SFFILEH_ERROR = 0x0004 -}; - -typedef struct { - _STFLAGH sfh; - UINT stat; - FILEH fh; - UINT secpos; - NP2FHDR f; -} _SFFILEH, *SFFILEH; - -static SFFILEH statflag_open(const OEMCHAR *filename, OEMCHAR *err, int errlen) { - - FILEH fh; - SFFILEH ret; - - fh = file_open_rb(filename); - if (fh == FILEH_INVALID) { - goto sfo_err1; - } - ret = (SFFILEH)_MALLOC(sizeof(_SFFILEH), filename); - if (ret == NULL) { - goto sfo_err2; - } - if ((file_read(fh, &ret->f, sizeof(NP2FHDR)) == sizeof(NP2FHDR)) && - (!memcmp(&ret->f, &np2flagdef, sizeof(np2flagdef)))) { - ZeroMemory(ret, sizeof(_SFFILEH)); - ret->fh = fh; - ret->secpos = sizeof(NP2FHDR); - if ((err) && (errlen > 0)) { - err[0] = '\0'; - ret->sfh.err = err; - ret->sfh.errlen = errlen; - } - return(ret); - } - _MFREE(ret); - -sfo_err2: - file_close(fh); - -sfo_err1: - return(NULL); -} - -static int statflag_closesection(SFFILEH sffh) { - - UINT leng; - UINT8 zero[16]; - - if (sffh == NULL) { - goto sfcs_err1; - } - if (sffh->stat == (SFFILEH_BLOCK | SFFILEH_WRITE)) { - leng = (0 - sffh->sfh.hdr.size) & 15; - if (leng) { - ZeroMemory(zero, sizeof(zero)); - if (file_write(sffh->fh, zero, leng) != leng) { - goto sfcs_err2; - } - } - if ((file_seek(sffh->fh, (long)sffh->secpos, FSEEK_SET) - != (long)sffh->secpos) || - (file_write(sffh->fh, &sffh->sfh.hdr, sizeof(sffh->sfh.hdr)) - != sizeof(sffh->sfh.hdr))) { - goto sfcs_err2; - } - } - if (sffh->stat & SFFILEH_BLOCK) { - sffh->stat &= ~SFFILEH_BLOCK; - sffh->secpos += sizeof(sffh->sfh.hdr) + - ((sffh->sfh.hdr.size + 15) & (~15)); - if (file_seek(sffh->fh, (long)sffh->secpos, FSEEK_SET) - != (long)sffh->secpos) { - goto sfcs_err2; - } - } - return(STATFLAG_SUCCESS); - -sfcs_err2: - sffh->stat = SFFILEH_ERROR; - -sfcs_err1: - return(STATFLAG_FAILURE); -} - -static int statflag_readsection(SFFILEH sffh) { - - int ret; - - ret = statflag_closesection(sffh); - if (ret != STATFLAG_SUCCESS) { - return(ret); - } - if ((sffh->stat == 0) && - (file_read(sffh->fh, &sffh->sfh.hdr, sizeof(sffh->sfh.hdr)) - == sizeof(sffh->sfh.hdr))) { - sffh->stat = SFFILEH_BLOCK; - sffh->sfh.pos = 0; - return(STATFLAG_SUCCESS); - } - sffh->stat = SFFILEH_ERROR; - return(STATFLAG_FAILURE); -} - -int statflag_read(STFLAGH sfh, void *buf, UINT size) { - - if ((sfh == NULL) || (buf == NULL) || - ((sfh->pos + size) > sfh->hdr.size)) { - goto sfr_err; - } - if (size) { - if (file_read(((SFFILEH)sfh)->fh, buf, size) != size) { - goto sfr_err; - } - sfh->pos += size; - } - return(STATFLAG_SUCCESS); - -sfr_err: - return(STATFLAG_FAILURE); -} - -static SFFILEH statflag_create(const OEMCHAR *filename) { - - SFFILEH ret; - FILEH fh; - - ret = (SFFILEH)_MALLOC(sizeof(_SFFILEH), filename); - if (ret == NULL) { - goto sfc_err1; - } - fh = file_create(filename); - if (fh == FILEH_INVALID) { - goto sfc_err2; - } - if (file_write(fh, &np2flagdef, sizeof(NP2FHDR)) == sizeof(NP2FHDR)) { - ZeroMemory(ret, sizeof(_SFFILEH)); - ret->stat = SFFILEH_WRITE; - ret->fh = fh; - ret->secpos = sizeof(NP2FHDR); - return(ret); - } - file_close(fh); - file_delete(filename); - -sfc_err2: - _MFREE(ret); - -sfc_err1: - return(NULL); -} - -static int statflag_createsection(SFFILEH sffh, const SFENTRY *tbl) { - - int ret; - - ret = statflag_closesection(sffh); - if (ret != STATFLAG_SUCCESS) { - return(ret); - } - if (sffh->stat != SFFILEH_WRITE) { - sffh->stat = SFFILEH_ERROR; - return(STATFLAG_FAILURE); - } - CopyMemory(sffh->sfh.hdr.index, tbl->index, sizeof(sffh->sfh.hdr.index)); - sffh->sfh.hdr.ver = tbl->ver; - sffh->sfh.hdr.size = 0; - return(STATFLAG_SUCCESS); -} - -int statflag_write(STFLAGH sfh, const void *buf, UINT size) { - - SFFILEH sffh; - - if (sfh == NULL) { - goto sfw_err1; - } - sffh = (SFFILEH)sfh; - if (!(sffh->stat & SFFILEH_WRITE)) { - goto sfw_err2; - } - if (!(sffh->stat & SFFILEH_BLOCK)) { - sffh->stat |= SFFILEH_BLOCK; - sfh->pos = 0; - if (file_write(sffh->fh, &sfh->hdr, sizeof(sfh->hdr)) - != sizeof(sfh->hdr)) { - goto sfw_err2; - } - } - if (size) { - if ((buf == NULL) || (file_write(sffh->fh, buf, size) != size)) { - goto sfw_err2; - } - sfh->pos += size; - if (sfh->hdr.size < sfh->pos) { - sfh->hdr.size = sfh->pos; - } - } - return(STATFLAG_SUCCESS); - -sfw_err2: - sffh->stat = SFFILEH_ERROR; - -sfw_err1: - return(STATFLAG_FAILURE); -} - -static void statflag_close(SFFILEH sffh) { - - if (sffh) { - statflag_closesection(sffh); - file_close(sffh->fh); - _MFREE(sffh); - } -} - -void statflag_seterr(STFLAGH sfh, const OEMCHAR *str) { - - if ((sfh) && (sfh->errlen)) { - milstr_ncat(sfh->err, str, sfh->errlen); - milstr_ncat(sfh->err, CRCONST, sfh->errlen); - } -} - - -// ---- function - -// 関数ポインタを intに変更。 -static BRESULT proc2num(void *func, const PROCTBL *tbl, int size) { - - int i; - - for (i=0; iproc) { - *(INTPTR *)func = (INTPTR)tbl->id; - return(SUCCESS); - } - tbl++; - } - return(FAILURE); -} - -static BRESULT num2proc(void *func, const PROCTBL *tbl, int size) { - - int i; - - for (i=0; iid) { - *(INTPTR *)func = (INTPTR)tbl->proc; - return(SUCCESS); - } - tbl++; - } - return(FAILURE); -} - - -// ---- file - -typedef struct { - OEMCHAR path[MAX_PATH]; - UINT ftype; - int readonly; - DOSDATE date; - DOSTIME time; -} STATPATH; - -static const OEMCHAR str_updated[] = OEMTEXT("%s: updated"); -static const OEMCHAR str_notfound[] = OEMTEXT("%s: not found"); - -static int statflag_writepath(STFLAGH sfh, const OEMCHAR *path, - UINT ftype, int readonly) { - - STATPATH sp; - FILEH fh; - - ZeroMemory(&sp, sizeof(sp)); - if ((path) && (path[0])) { - file_cpyname(sp.path, path, NELEMENTS(sp.path)); - sp.ftype = ftype; - sp.readonly = readonly; - fh = file_open_rb(path); - if (fh != FILEH_INVALID) { - file_getdatetime(fh, &sp.date, &sp.time); - file_close(fh); - } - } - return(statflag_write(sfh, &sp, sizeof(sp))); -} - -static int statflag_checkpath(STFLAGH sfh, const OEMCHAR *dvname) { - - int ret; - STATPATH sp; - FILEH fh; - OEMCHAR buf[256]; - DOSDATE dosdate; - DOSTIME dostime; - - ret = statflag_read(sfh, &sp, sizeof(sp)); - if (sp.path[0]) { - fh = file_open_rb(sp.path); - if (fh != FILEH_INVALID) { - file_getdatetime(fh, &dosdate, &dostime); - file_close(fh); - if ((memcmp(&sp.date, &dosdate, sizeof(dosdate))) || - (memcmp(&sp.time, &dostime, sizeof(dostime)))) { - ret |= STATFLAG_DISKCHG; - OEMSNPRINTF(buf, sizeof(buf), str_updated, dvname); - statflag_seterr(sfh, buf); - } - } - else { - ret |= STATFLAG_DISKCHG; - OEMSNPRINTF(buf, sizeof(buf), str_notfound, dvname); - statflag_seterr(sfh, buf); - } - } - return(ret); -} - - -// ---- common - -static int flagsave_common(STFLAGH sfh, const SFENTRY *tbl) { - - return(statflag_write(sfh, tbl->arg1, tbl->arg2)); -} - -static int flagload_common(STFLAGH sfh, const SFENTRY *tbl) { - - memset(tbl->arg1, 0, tbl->arg2); - return(statflag_read(sfh, tbl->arg1, MIN(tbl->arg2, sfh->hdr.size))); -} - - -// ---- memory - -static int flagsave_mem(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - - ret = statflag_write(sfh, mem, 0x110000); - ret |= statflag_write(sfh, mem + VRAM1_B, 0x18000); - ret |= statflag_write(sfh, mem + VRAM1_E, 0x8000); - (void)tbl; - return(ret); -} - -static int flagload_mem(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - - ret = statflag_read(sfh, mem, 0x110000); - ret |= statflag_read(sfh, mem + VRAM1_B, 0x18000); - ret |= statflag_read(sfh, mem + VRAM1_E, 0x8000); - (void)tbl; - return(ret); -} - - -// ---- dma - -static int flagsave_dma(STFLAGH sfh, const SFENTRY *tbl) { - - int i; - _DMAC dmabak; - - dmabak = dmac; - for (i=0; i<4; i++) { - if ((PROC2NUM(dmabak.dmach[i].proc.outproc, dmaproc)) || - (PROC2NUM(dmabak.dmach[i].proc.inproc, dmaproc)) || - (PROC2NUM(dmabak.dmach[i].proc.extproc, dmaproc))) { - return(STATFLAG_FAILURE); - } - } - (void)tbl; - return(statflag_write(sfh, &dmabak, sizeof(dmabak))); -} - -static int flagload_dma(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - int i; - - ret = statflag_read(sfh, &dmac, sizeof(dmac)); - - for (i=0; i<4; i++) { - if (NUM2PROC(dmac.dmach[i].proc.outproc, dmaproc)) { - dmac.dmach[i].proc.outproc = dma_dummyout; - ret |= STATFLAG_WARNING; - } - if (NUM2PROC(dmac.dmach[i].proc.inproc, dmaproc)) { - dmac.dmach[i].proc.inproc = dma_dummyin; - ret |= STATFLAG_WARNING; - } - if (NUM2PROC(dmac.dmach[i].proc.extproc, dmaproc)) { - dmac.dmach[i].proc.extproc = dma_dummyproc; - ret |= STATFLAG_WARNING; - } - } - (void)tbl; - return(ret); -} - - -// ---- egc - -static int flagsave_egc(STFLAGH sfh, const SFENTRY *tbl) { - - _EGC egcbak; - - egcbak = egc; - egcbak.inptr -= (INTPTR)egc.buf; - egcbak.outptr -= (INTPTR)egc.buf; - (void)tbl; - return(statflag_write(sfh, &egcbak, sizeof(egcbak))); -} - -static int flagload_egc(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - - ret = statflag_read(sfh, &egc, sizeof(egc)); - egc.inptr += (INTPTR)egc.buf; - egc.outptr += (INTPTR)egc.buf; - (void)tbl; - return(ret); -} - - -// ---- epson - -static int flagsave_epson(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - - if (!(pccore.model & PCMODEL_EPSON)) { - return(STATFLAG_SUCCESS); - } - ret = statflag_write(sfh, &epsonio, sizeof(epsonio)); - ret |= statflag_write(sfh, mem + 0x1c0000, 0x8000); - ret |= statflag_write(sfh, mem + 0x1e8000, 0x18000); - (void)tbl; - return(ret); -} - -static int flagload_epson(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - - ret = statflag_read(sfh, &epsonio, sizeof(epsonio)); - ret |= statflag_read(sfh, mem + 0x1c0000, 0x8000); - ret |= statflag_read(sfh, mem + 0x1e8000, 0x18000); - (void)tbl; - return(ret); -} - - -// ---- event - -typedef struct { - UINT readyevents; - UINT waitevents; -} NEVTSAVE; - -typedef struct { - UINT32 id; - SINT32 clock; - UINT32 flag; - NEVENTCB proc; -} NEVTITEM; - -static int nevent_write(STFLAGH sfh, NEVENTID num) { - - NEVTITEM nit; - UINT i; - - ZeroMemory(&nit, sizeof(nit)); - for (i=0; i sizeof(g_musicgen)) return STATFLAG_FAILURE; // 旧バージョンで読めないようにしておく(コメントアウトすると読めるようになるが、ちゃんと考えて設計しないと危険) - ret |= statflag_read(sfh, &g_musicgen, MIN(datalen, sizeof(g_musicgen))); - if(datalen > sizeof(g_musicgen)){ - sfh->pos += datalen - sizeof(g_musicgen); - }else{ - memset((UINT8*)(&g_musicgen) + datalen, 0, sizeof(g_musicgen) - datalen); // ない部分は0埋め - } - board14_allkeymake(); - } - for (i = 0; i < NELEMENTS(g_opna); i++) - { - if (nSaveFlags & (FLAG_OPNA1 << i)) - { - ret |= opna_sfload(&g_opna[i], sfh, tbl); - } - } - if (nSaveFlags & FLAG_PCM86) - { - ret |= statflag_read(sfh, &datalen, sizeof(datalen)); - if(datalen > sizeof(g_pcm86)) return STATFLAG_FAILURE; // 旧バージョンで読めないようにしておく(コメントアウトすると読めるようになるが、ちゃんと考えて設計しないと危険) - ret |= statflag_read(sfh, &g_pcm86, MIN(datalen, sizeof(g_pcm86))); - if(datalen > sizeof(g_pcm86)){ - sfh->pos += datalen - sizeof(g_pcm86); - }else{ - memset((UINT8*)(&g_pcm86) + datalen, 0, sizeof(g_pcm86) - datalen); // ない部分は0埋め - } - } - if (nSaveFlags & FLAG_CS4231) - { - ret |= statflag_read(sfh, &datalen, sizeof(datalen)); - if(datalen > sizeof(cs4231)) return STATFLAG_FAILURE; // 旧バージョンで読めないようにしておく(コメントアウトすると読めるようになるが、ちゃんと考えて設計しないと危険) - ret |= statflag_read(sfh, &cs4231, MIN(datalen, sizeof(cs4231))); - if(datalen > sizeof(cs4231)){ - sfh->pos += datalen - sizeof(cs4231); - }else{ - memset((UINT8*)(&cs4231) + datalen, 0, sizeof(cs4231) - datalen); // ない部分は0埋め - } - } - if (nSaveFlags & FLAG_AMD98) - { - ret |= amd98_sfload(sfh, tbl); - } - if (nSaveFlags & FLAG_OPL3) - { - for (i = 0; i < NELEMENTS(g_opl3); i++) - { - ret |= opl3_sfload(&g_opl3[i], sfh, tbl); - } -#ifdef USE_MAME - for (i = 0; i < NELEMENTS(g_mame_opl3); i++) - { - void* buffer; - int bufsize = 0; - ret |= statflag_read(sfh, &bufsize, sizeof(SINT32)); - if(bufsize!=0){ - buffer = malloc(bufsize); - ret |= statflag_read(sfh, buffer, bufsize); - if (g_mame_opl3[i]) { - if (!YMF262FlagLoad(g_mame_opl3[i], buffer, bufsize)) { - free(buffer); - ret = STATFLAG_FAILURE; - break; - } - } - free(buffer); - } - } -#endif - } -#if defined(SUPPORT_SOUND_SB16) - if (nSaveFlags & FLAG_SB16) - { - ret |= statflag_read(sfh, &datalen, sizeof(datalen)); - if(datalen > sizeof(g_sb16)) return STATFLAG_FAILURE; // 旧バージョンで読めないようにしておく(コメントアウトすると読めるようになるが、ちゃんと考えて設計しないと危険) - ret |= statflag_read(sfh, &g_sb16, MIN(datalen, sizeof(g_sb16))); - if(datalen > sizeof(g_sb16)){ - sfh->pos += datalen - sizeof(g_sb16); - }else{ - memset((UINT8*)(&g_sb16) + datalen, 0, sizeof(g_sb16) - datalen); // ない部分は0埋め - } - } -#endif - }else{ - // old statsave - nSaveFlags = GetSoundFlags(g_nSoundID); - if (nSaveFlags & FLAG_MG) - { - ret |= statflag_read(sfh, &g_musicgen, sizeof(MUSICGEN_OLD)); - if(sizeof(MUSICGEN_OLD) < sizeof(g_musicgen)){ - memset((UINT8*)(&g_musicgen) + sizeof(MUSICGEN_OLD), 0, sizeof(g_musicgen) - sizeof(MUSICGEN_OLD)); // ない部分は0埋め - } - board14_allkeymake(); - } - for (i = 0; i < NELEMENTS(g_opna); i++) - { - if (nSaveFlags & (FLAG_OPNA1 << i)) - { - ret |= opna_sfload(&g_opna[i], sfh, tbl); - } - } - if (nSaveFlags & FLAG_PCM86) - { - ret |= statflag_read(sfh, &g_pcm86, sizeof(_PCM86_OLD)); - if(sizeof(_PCM86_OLD) < sizeof(g_pcm86)){ - memset((UINT8*)(&g_pcm86) + sizeof(_PCM86_OLD), 0, sizeof(g_pcm86) - sizeof(_PCM86_OLD)); // ない部分は0埋め - } - g_pcm86.lastclock = g_pcm86.obsolate.lastclock_obsolate; - g_pcm86.stepclock = g_pcm86.obsolate.stepclock_obsolate; - } - if (nSaveFlags & FLAG_CS4231) - { - ret |= statflag_read(sfh, &cs4231, sizeof(_CS4231_OLD)); - if(sizeof(_CS4231_OLD) < sizeof(cs4231)){ - memset((UINT8*)(&cs4231) + sizeof(_CS4231_OLD), 0, sizeof(cs4231) - sizeof(_CS4231_OLD)); // ない部分は0埋め - } - } - if (nSaveFlags & FLAG_AMD98) - { - ret |= amd98_sfload(sfh, tbl); - } - if (nSaveFlags & FLAG_OPL3) - { - for (i = 0; i < NELEMENTS(g_opl3); i++) - { - ret |= opl3_sfload(&g_opl3[i], sfh, tbl); - } -#ifdef USE_MAME - for (i = 0; i < NELEMENTS(g_mame_opl3); i++) - { - void* buffer; - int bufsize = 0; - ret |= statflag_read(sfh, &bufsize, sizeof(SINT32)); - if(bufsize!=0){ - buffer = malloc(bufsize); - ret |= statflag_read(sfh, buffer, bufsize); - if (g_mame_opl3[i]) { - if (!YMF262FlagLoad(g_mame_opl3[i], buffer, bufsize)) { - free(buffer); - ret = STATFLAG_FAILURE; - break; - } - } - free(buffer); - } - } -#endif - } -#if defined(SUPPORT_SOUND_SB16) - if (nSaveFlags & FLAG_SB16) - { - ret |= statflag_read(sfh, &g_sb16, SIZEOF_SB16_OLD); - if(SIZEOF_SB16_OLD < sizeof(g_sb16)){ - memset((UINT8*)(&g_sb16) + SIZEOF_SB16_OLD, 0, sizeof(g_sb16) - SIZEOF_SB16_OLD); // ない部分は0埋め - } - } -#endif - } - - // 復元。 これ移動すること! - pcm86gen_update(); - if (nSaveFlags & FLAG_PCM86) - { - fmboard_extenable((REG8)(g_pcm86.soundflags & 1)); - } - if (nSaveFlags & FLAG_CS4231) - { - fmboard_extenable((REG8)(cs4231.extfunc & 1)); - } -#if defined(SUPPORT_SOUND_SB16) - if (nSaveFlags & FLAG_SB16) - { - g_sb16.dsp_info.dma.dmach = dmac.dmach + g_sb16.dmachnum; // DMAチャネル復元 - dmac_attach(DMADEV_CT1741, g_sb16.dmachnum); // 再割り当て - } -#endif - return(ret); -} -#endif - - -// ---- fdd - -static const OEMCHAR str_fddx[] = OEMTEXT("FDD%u"); - -static int flagsave_fdd(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - UINT8 i; -const OEMCHAR *path; - UINT ftype; - int ro; - - ret = STATFLAG_SUCCESS; - for (i=0; i<4; i++) { - path = fdd_getfileex(i, &ftype, &ro); - ret |= statflag_writepath(sfh, path, ftype, ro); - } - (void)tbl; - return(ret); -} - -static int flagcheck_fdd(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - int i; - OEMCHAR buf[32]; - - ret = STATFLAG_SUCCESS; - for (i=0; i<4; i++) { - OEMSNPRINTF(buf, sizeof(buf), str_fddx, i+1); - ret |= statflag_checkpath(sfh, buf); - } - (void)tbl; - return(ret); -} - -static int flagload_fdd(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - UINT8 i; - STATPATH sp; - - ret = STATFLAG_SUCCESS; - for (i=0; i<4; i++) { - ret |= statflag_read(sfh, &sp, sizeof(sp)); - if (sp.path[0]) { - fdd_set(i, sp.path, sp.ftype, sp.readonly); - } - } - (void)tbl; - return(ret); -} - - -// ---- sxsi - -typedef struct { - UINT8 ide[4]; - UINT8 scsi[8]; -} SXSIDEVS; - -#ifdef SUPPORT_IDEIO -static const OEMCHAR str_sasix[] = OEMTEXT("IDE#%u"); -#else -static const OEMCHAR str_sasix[] = OEMTEXT("SASI%u"); -#endif -static const OEMCHAR str_scsix[] = OEMTEXT("SCSI%u"); - -static int flagsave_sxsi(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - UINT i; - SXSIDEVS sds; -const OEMCHAR *path; - - sxsi_allflash(); - ret = STATFLAG_SUCCESS; - for (i=0; iarg1; - switch(device) { - case 0: - cm = cm_mpu98; - break; - - case 1: - cm = cm_rs232c; - break; - -#if defined(SUPPORT_SMPU98) - case 2: - cm = cm_smpu98[0]; - break; - - case 3: - cm = cm_smpu98[1]; - break; -#endif - - default: - cm = NULL; - break; - } - ret = STATFLAG_SUCCESS; - if (cm) { - flag = (COMFLAG)cm->msg(cm, COMMSG_GETFLAG, 0); - if (flag) { - ret |= statflag_write(sfh, flag, flag->size); - _MFREE(flag); - } - } - return(ret); -} - -static int flagload_com(STFLAGH sfh, const SFENTRY *tbl) { - - UINT device; - COMMNG cm; - int ret; - _COMFLAG fhdr; - COMFLAG flag; - - ret = statflag_read(sfh, &fhdr, sizeof(fhdr)); - if (ret != STATFLAG_SUCCESS) { - goto flcom_err1; - } - if (fhdr.size < sizeof(fhdr)) { - goto flcom_err1; - } - flag = (COMFLAG)_MALLOC(fhdr.size, "com stat flag"); - if (flag == NULL) { - goto flcom_err1; - } - CopyMemory(flag, &fhdr, sizeof(fhdr)); - ret |= statflag_read(sfh, flag + 1, fhdr.size - sizeof(fhdr)); - if (ret != STATFLAG_SUCCESS) { - goto flcom_err2; - } - - device = (UINT)(INTPTR)tbl->arg1; - switch(device) { - case 0: - commng_destroy(cm_mpu98); - cm = commng_create(COMCREATE_MPU98II, FALSE); - cm_mpu98 = cm; - break; - - case 1: - commng_destroy(cm_rs232c); - cm = commng_create(COMCREATE_SERIAL, FALSE); - cm_rs232c = cm; - break; - -#if defined(SUPPORT_SMPU98) - case 2: - commng_destroy(cm_smpu98[0]); - cm = commng_create(COMCREATE_SMPU98_A, FALSE); - cm_smpu98[0] = cm; - break; - - case 3: - commng_destroy(cm_smpu98[1]); - cm = commng_create(COMCREATE_SMPU98_B, FALSE); - cm_smpu98[1] = cm; - break; -#endif - - default: - cm = NULL; - break; - } - if (cm) { - cm->msg(cm, COMMSG_SETFLAG, (INTPTR)flag); - } - -flcom_err2: - _MFREE(flag); - -flcom_err1: - return(ret); -} - -// ---- bms - -#if defined(SUPPORT_BMS) - -static int flagsave_bms(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - - ret = STATFLAG_SUCCESS; - if (bmsiowork.bmsmem) { - ret = statflag_write(sfh, bmsiowork.bmsmem, bmsiowork.bmsmemsize); - } - (void)tbl; - return(ret); -} - -static int flagload_bms(STFLAGH sfh, const SFENTRY *tbl) { - - int ret; - - ret = STATFLAG_SUCCESS; - if (bmsiowork.bmsmem) { - ret = statflag_read(sfh, bmsiowork.bmsmem, bmsiowork.bmsmemsize); - } - (void)tbl; - return(ret); -} - -#endif - -// ---- - -static int flagcheck_versize(STFLAGH sfh, const SFENTRY *tbl) { - - if ((sfh->hdr.ver == tbl->ver) && ((sfh->hdr.size == tbl->arg2) || - ((tbl->type & STATFLAG_BWD_COMPATIBLE) && sfh->hdr.size < tbl->arg2) || - ((tbl->type & STATFLAG_FWD_COMPATIBLE) && sfh->hdr.size > tbl->arg2))) { - return(STATFLAG_SUCCESS); - } - return(STATFLAG_FAILURE); -} - -static int flagcheck_veronly(STFLAGH sfh, const SFENTRY *tbl) { - - if (sfh->hdr.ver == tbl->ver) { - return(STATFLAG_SUCCESS); - } - return(STATFLAG_FAILURE); -} - - -// ---- - -int statsave_save(const OEMCHAR *filename) { - if(filename) { - milstr_ncpy(m_strStateFilename, filename, MAX_PATH); - g_u8ControlState = 1; - } -} - -#if defined(__LIBRETRO__) -int statsave_save_d(const OEMCHAR *filename) { -#else -int statsave_save_d(void) { -#endif - - SFFILEH sffh; - int ret; -const SFENTRY *tbl; -const SFENTRY *tblterm; - -#if defined(__LIBRETRO__) - sffh = statflag_create(filename); -#else - sffh = statflag_create(m_strStateFilename); -#endif - if (sffh == NULL) { - return(STATFLAG_FAILURE); - } - -#if defined(SUPPORT_CL_GD5430) - pc98_cirrus_vga_save(); -#endif - -#if defined(SUPPORT_IA32_HAXM) - memcpy(vramex_base, vramex, sizeof(vramex_base)); - i386haxfunc_vcpu_getMSRs(&np2haxstat.msrstate); -#endif - - ret = STATFLAG_SUCCESS; - tbl = np2tbl; - tblterm = tbl + NELEMENTS(np2tbl); - while(tbl < tblterm) { - ret |= statflag_createsection(sffh, tbl); - switch(tbl->type & STATFLAG_MASK) { - case STATFLAG_BIN: - case STATFLAG_TERM: - ret |= flagsave_common(&sffh->sfh, tbl); - break; - - case STATFLAG_COM: - ret |= flagsave_com(&sffh->sfh, tbl); - break; - - case STATFLAG_DMA: - ret |= flagsave_dma(&sffh->sfh, tbl); - break; - - case STATFLAG_EGC: - ret |= flagsave_egc(&sffh->sfh, tbl); - break; - - case STATFLAG_EPSON: - ret |= flagsave_epson(&sffh->sfh, tbl); - break; - - case STATFLAG_EVT: - ret |= flagsave_evt(&sffh->sfh, tbl); - break; - - case STATFLAG_EXT: - ret |= flagsave_ext(&sffh->sfh, tbl); - break; - - case STATFLAG_FDD: - ret |= flagsave_fdd(&sffh->sfh, tbl); - break; - -#if !defined(DISABLE_SOUND) - case STATFLAG_FM: - ret |= flagsave_fm(&sffh->sfh, tbl); - break; -#endif - - case STATFLAG_GIJ: - ret |= flagsave_gij(&sffh->sfh, tbl); - break; - -#if defined(SUPPORT_HOSTDRV) - case STATFLAG_HDRV: - ret |= hostdrv_sfsave(&sffh->sfh, tbl); - break; -#endif -#if defined(SUPPORT_HOSTDRVNT) - case STATFLAG_HDRVNT: - ret |= hostdrvNT_sfsave(&sffh->sfh, tbl); - break; -#endif - - case STATFLAG_MEM: - ret |= flagsave_mem(&sffh->sfh, tbl); - break; - -#if defined(SUPPORT_BMS) - case STATFLAG_BMS: - ret |= flagsave_bms(&sffh->sfh, tbl); - break; -#endif - - case STATFLAG_SXSI: - ret |= flagsave_sxsi(&sffh->sfh, tbl); - break; - } - tbl++; - } - statflag_close(sffh); - return(ret); -} - -int statsave_check(const OEMCHAR *filename, OEMCHAR *buf, int size) { - - SFFILEH sffh; - int ret; - BOOL done; -const SFENTRY *tbl; -const SFENTRY *tblterm; - - sffh = statflag_open(filename, buf, size); - if (sffh == NULL) { - return(STATFLAG_FAILURE); - } - - done = FALSE; - ret = STATFLAG_SUCCESS; - while((!done) && (ret != STATFLAG_FAILURE)) { - ret |= statflag_readsection(sffh); - tbl = np2tbl; - tblterm = tbl + NELEMENTS(np2tbl); - while(tbl < tblterm) { - if (!memcmp(sffh->sfh.hdr.index, tbl->index, sizeof(sffh->sfh.hdr.index))) { - break; - } - tbl++; - } - if (tbl < tblterm) { - switch(tbl->type & STATFLAG_MASK) { - case STATFLAG_BIN: - case STATFLAG_MEM: - ret |= flagcheck_versize(&sffh->sfh, tbl); - break; - - case STATFLAG_TERM: - done = TRUE; - break; - - case STATFLAG_COM: - case STATFLAG_DMA: - case STATFLAG_EGC: - case STATFLAG_EPSON: - case STATFLAG_EVT: - case STATFLAG_EXT: - case STATFLAG_GIJ: -#if !defined(DISABLE_SOUND) - case STATFLAG_FM: -#endif - ret |= flagcheck_veronly(&sffh->sfh, tbl); - break; - -#if defined(SUPPORT_HOSTDRV) - case STATFLAG_HDRV: - ret |= flagcheck_veronly(&sffh->sfh, tbl); - break; -#endif - -#if defined(SUPPORT_HOSTDRVNT) - case STATFLAG_HDRVNT: - ret |= flagcheck_veronly(&sffh->sfh, tbl); - break; -#endif - - case STATFLAG_FDD: - ret |= flagcheck_fdd(&sffh->sfh, tbl); - break; - - case STATFLAG_SXSI: - ret |= flagcheck_sxsi(&sffh->sfh, tbl); - break; - - default: - ret |= STATFLAG_WARNING; - break; - } - } - else { - ret |= STATFLAG_WARNING; - } - } - statflag_close(sffh); - return(ret); -} - -int statsave_load(const OEMCHAR *filename) { - if(filename) { - milstr_ncpy(m_strStateFilename, filename, MAX_PATH); - g_u8ControlState = 2; - } -} - -#if defined(__LIBRETRO__) -int statsave_load_d(const OEMCHAR *filename) { -#else -int statsave_load_d(void) { -#endif - - SFFILEH sffh; - int ret; - BOOL done; -const SFENTRY *tbl; -const SFENTRY *tblterm; - UINT i; -#if defined(SUPPORT_FMGEN) - UINT8 usefmgen = 0; -#endif - -#if defined(__LIBRETRO__) - sffh = statflag_open(filename, NULL, 0); -#else - sffh = statflag_open(m_strStateFilename, NULL, 0); -#endif - if (sffh == NULL) { - return(STATFLAG_FAILURE); - } - - // PCCORE read! - ret = statflag_readsection(sffh); - if ((ret != STATFLAG_SUCCESS) || - (memcmp(sffh->sfh.hdr.index, np2tbl[0].index, sizeof(sffh->sfh.hdr.index)))) { - statflag_close(sffh); - return(STATFLAG_FAILURE); - } - - soundmng_stop(); - rs232c_midipanic(); - mpu98ii_midipanic(); -#if defined(SUPPORT_SMPU98) - smpu98_midipanic(); -#endif - pc9861k_midipanic(); - sxsi_alltrash(); - - ret |= flagload_common(&sffh->sfh, np2tbl); - - CPU_RESET(); - CPU_SETEXTSIZE((UINT32)pccore.extmem); - nevent_allreset(); - - sound_changeclock(); - beep_changeclock(); - sound_reset(); - fddmtrsnd_bind(); - wabrlysnd_bind(); - - iocore_reset(&np2cfg); // サウンドでpicを呼ぶので… - cbuscore_reset(&np2cfg); - fmboard_reset(&np2cfg, pccore.sound); - - done = FALSE; - while((!done) && (ret != STATFLAG_FAILURE)) { - ret |= statflag_readsection(sffh); - tbl = np2tbl + 1; - tblterm = np2tbl + NELEMENTS(np2tbl); - while(tbl < tblterm) { - if (!memcmp(sffh->sfh.hdr.index, tbl->index, sizeof(sffh->sfh.hdr.index))) { - break; - } - tbl++; - } - if (tbl < tblterm) { - switch(tbl->type & STATFLAG_MASK) { - case STATFLAG_BIN: - ret |= flagload_common(&sffh->sfh, tbl); - break; - - case STATFLAG_TERM: - done = TRUE; - break; - - case STATFLAG_COM: - ret |= flagload_com(&sffh->sfh, tbl); - break; - - case STATFLAG_DMA: - ret |= flagload_dma(&sffh->sfh, tbl); - break; - - case STATFLAG_EGC: - ret |= flagload_egc(&sffh->sfh, tbl); - break; - - case STATFLAG_EPSON: - ret |= flagload_epson(&sffh->sfh, tbl); - break; - - case STATFLAG_EVT: - ret |= flagload_evt(&sffh->sfh, tbl); - break; - - case STATFLAG_EXT: - ret |= flagload_ext(&sffh->sfh, tbl); - break; - - case STATFLAG_FDD: - ret |= flagload_fdd(&sffh->sfh, tbl); - break; - -#if !defined(DISABLE_SOUND) - case STATFLAG_FM: - ret |= flagload_fm(&sffh->sfh, tbl); - break; -#endif - - case STATFLAG_GIJ: - ret |= flagload_gij(&sffh->sfh, tbl); - break; - -#if defined(SUPPORT_HOSTDRV) - case STATFLAG_HDRV: - ret |= hostdrv_sfload(&sffh->sfh, tbl); - break; -#endif - -#if defined(SUPPORT_HOSTDRVNT) - case STATFLAG_HDRVNT: - ret |= hostdrvNT_sfload(&sffh->sfh, tbl); - break; -#endif - - case STATFLAG_MEM: - ret |= flagload_mem(&sffh->sfh, tbl); - break; - -#if defined(SUPPORT_BMS) - case STATFLAG_BMS: - ret |= flagload_bms(&sffh->sfh, tbl); - break; -#endif - - case STATFLAG_SXSI: - ret |= flagload_sxsi(&sffh->sfh, tbl); - break; - - default: - ret |= STATFLAG_WARNING; - break; - } - } - else { - ret |= STATFLAG_WARNING; - } - } - statflag_close(sffh); - - // ステートセーブ互換性維持用 - if(pccore.maxmultiple == 0) pccore.maxmultiple = pccore.multiple; - -#if defined(CPUCORE_IA32) - // FPUロード - fpu_statesave_load(); -#endif - -#if defined(SUPPORT_IA32_HAXM) - memcpy(vramex, vramex_base, sizeof(vramex_base)); - i386haxfunc_vcpu_setREGs(&np2haxstat.state); - i386haxfunc_vcpu_setFPU(&np2haxstat.fpustate); - { - HAX_MSR_DATA msrstate_set = {0}; - i386haxfunc_vcpu_setMSRs(&np2haxstat.msrstate, &msrstate_set); - } - i386hax_vm_sethmemory(CPU_ADRSMASK != 0x000fffff); - i386hax_vm_setitfmemory(CPU_ITFBANK); - i386hax_vm_setvga256linearmemory(); - np2haxcore.clockpersec = NP2_TickCount_GetFrequency(); - np2haxcore.lastclock = NP2_TickCount_GetCount(); - np2haxcore.clockcount = NP2_TickCount_GetCount(); - np2haxcore.I_ratio = 0; -#endif - - // I/O作り直し - MEMM_ARCH((pccore.model & PCMODEL_EPSON)?1:0); - iocore_build(); - iocore_bind(); - cbuscore_bind(); - fmboard_bind(); - - // DA/UAと要素番号の対応関係を初期化 - for(i=0;i<4;i++){ - sxsi_unittbl[i] = i; - } -#if defined(SUPPORT_IDEIO) - if (pccore.hddif & PCHDD_IDE) { - int i, idx, ncidx; - // 未接続のものを無視して接続順にDA/UAを割り当てる - ncidx = idx = 0; - for(i=0;i<4;i++){ - if(sxsi_getdevtype(i)==SXSIDEV_HDD){ - sxsi_unittbl[idx] = i; - idx++; - }else{ - ncidx = i; - } - } - for(;idx<4;idx++){ - sxsi_unittbl[idx] = ncidx; // XXX: 余ったDA/UAはとりあえず未接続の番号に設定 - } - } -#endif - -#if defined(SUPPORT_PC9821)&&defined(SUPPORT_PCI) - pcidev_bind(); -#endif - -#if defined(CPUCORE_IA32) -#if defined(USE_CPU_EIPMASK) - CPU_EIPMASK = CPU_STATSAVE.cpu_inst_default.op_32 ? 0xffffffff : 0xffff; -#endif - fpu_initialize(0); -#endif - -#if defined(SUPPORT_NET) - np2net_reset(&np2cfg); - np2net_bind(); -#endif -#if defined(SUPPORT_LGY98) - lgy98_bind(); -#endif -#if defined(SUPPORT_WAB) - np2wab_bind(); -#endif -#if defined(SUPPORT_CL_GD5430) - pc98_cirrus_vga_bind(); - pc98_cirrus_vga_load(); -#endif - - // OPNAボリューム再設定 -#if defined(SUPPORT_FMGEN) - for (i = 0; i < OPNA_MAX; i++) { - usefmgen |= g_opna[i].usefmgen; - } -#endif - if(g_nSoundID == SOUNDID_WAVESTAR){ - opngen_setvol(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - psggen_setvol(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - rhythm_setvol(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); -#if defined(SUPPORT_FMGEN) - if(usefmgen) { - opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); - } -#endif - }else{ - opngen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); - psggen_setvol(np2cfg.vol_ssg * np2cfg.vol_master / 100); - rhythm_setvol(np2cfg.vol_rhythm * np2cfg.vol_master / 100); -#if defined(SUPPORT_FMGEN) - if(usefmgen) { - opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * np2cfg.vol_master / 100); - opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * np2cfg.vol_master / 100); - opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * np2cfg.vol_master / 100); - } -#endif - oplgen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); - } - for (i = 0; i < NELEMENTS(g_opna); i++) - { - rhythm_update(&g_opna[i].rhythm); - } - - gdcs.textdisp |= GDCSCRN_EXT; - gdcs.textdisp |= GDCSCRN_ALLDRAW2; - gdcs.grphdisp |= GDCSCRN_EXT; - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - gdcs.palchange = GDCSCRN_REDRAW; - tramflag.renewal = 1; - cgwindow.writable |= 0x80; -#if defined(CPUSTRUC_FONTPTR) - FONTPTR_LOW = fontrom + cgwindow.low; - FONTPTR_HIGH = fontrom + cgwindow.high; -#endif - MEMM_VRAM(vramop.operate); - fddmtr_reset(); - soundmng_play(); - -#if defined(SUPPORT_WAB) - { - UINT8 wabaswtmp = np2cfg.wabasw; - np2cfg.wabasw = 1; // リレー音を鳴らさない - np2wab.relay = 0; - np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); - np2wab.realWidth = np2wab.wndWidth; // XXX: ??? - np2wab.realHeight = np2wab.wndHeight; // XXX: ??? - np2wab.lastWidth = 0; - np2wab.lastHeight = 0; - np2wab_setScreenSize(np2wab.wndWidth, np2wab.wndHeight); - np2cfg.wabasw = wabaswtmp; - } -#endif - - pit_setrs232cspeed((pit.ch + 2)->value); -#if defined(SUPPORT_RS232C_FIFO) - rs232c_vfast_setrs232cspeed(rs232cfifo.vfast); -#endif - -#if defined(NP2_WIN) - // カーソル表示状態復元 - mousemng_updateautohidecursor(); -#endif - - return(ret); -} - -int statsave_save_hdd(const OEMCHAR *ext) -{ - BRESULT r; - - r = sxsi_state_save(ext); - if (r == SUCCESS) - { - return (STATFLAG_SUCCESS); - } - else - { - return (STATFLAG_FAILURE); - } -} - -int statsave_load_hdd(const OEMCHAR *ext) -{ - BRESULT r; - - r = sxsi_state_load(ext); - if (r == SUCCESS) - { - return (STATFLAG_SUCCESS); - } - else - { - return (STATFLAG_FAILURE); - } -} - +/** + * @file statsave.cpp + * @brief Implementation of State save + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mousemng.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_SMPU98) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SUPPORT_SOUND_SB16 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_HOSTDRVNT) +#include +#endif +#include +#include +#include +#if defined(SUPPORT_WAB) +#include +#endif +#if defined(SUPPORT_CL_GD5430) +#include +#endif +#if defined(SUPPORT_NET) +#include +#endif +#if defined(SUPPORT_LGY98) +#include +#include +#endif +#if defined(CPUCORE_IA32) +#include +#endif +#if defined(BIOS_IO_EMULATION) +#include +#endif +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif + +uint8_t g_u8ControlState; +static OEMCHAR m_strStateFilename[MAX_PATH]; + +#ifdef USE_MAME +#ifdef USE_MAME_BSD +#if defined(_MSC_VER) +#if _MSC_VER < 1900 +#include +#else +#include +#endif +#else +#include +#endif +#else +#include +#endif +#endif + +extern int sxsi_unittbl[]; + +#if defined(MACOS) +#define CRCONST str_cr +#else +#define CRCONST str_lf +#endif + +typedef struct { + char name[16]; + char vername[28]; + UINT32 ver; +} NP2FHDR; + +typedef struct { + char index[10]; + UINT16 ver; + UINT32 size; +} NP2FENT; + +/** + * @brief handle + */ +struct TagStatFlagHandle +{ + NP2FENT hdr; + UINT pos; + OEMCHAR *err; + int errlen; +}; +typedef struct TagStatFlagHandle _STFLAGH; /* define */ + +enum +{ + STATFLAG_BIN = 0, + STATFLAG_TERM, + STATFLAG_COM, + STATFLAG_DMA, + STATFLAG_EGC, + STATFLAG_EPSON, + STATFLAG_EVT, + STATFLAG_EXT, + STATFLAG_FDD, + STATFLAG_FM, + STATFLAG_GIJ, +#if defined(SUPPORT_HOSTDRV) + STATFLAG_HDRV, +#endif + STATFLAG_MEM, +#if defined(SUPPORT_BMS) + STATFLAG_BMS, +#endif + STATFLAG_SXSI, + STATFLAG_HDRVNT, + STATFLAG_MASK = 0x3fff, + + STATFLAG_BWD_COMPATIBLE = 0x4000, // このフラグが立っているとき、古いバージョンのステートセーブと互換性がある(足りないデータは0で埋められるので注意する)いまのところSTATFLAG_BINのみサポート + STATFLAG_FWD_COMPATIBLE = 0x8000, // このフラグが立っているとき、新しいバージョンのステートセーブと互換性がある(足りないデータは無かったことになるので注意する)いまのところSTATFLAG_BINのみサポート +}; + +typedef struct { + UINT32 id; + void *proc; +} PROCTBL; + +typedef struct { + UINT32 id; + NEVENTID num; +} ENUMTBL; + +#define PROCID(a, b, c, d) (((d) << 24) + ((c) << 16) + ((b) << 8) + (a)) +#define PROC2NUM(a, b) proc2num(&(a), (b), sizeof(b)/sizeof(PROCTBL)) +#define NUM2PROC(a, b) num2proc(&(a), (b), sizeof(b)/sizeof(PROCTBL)) + +#include "statsave.tbl" + + +extern COMMNG cm_mpu98; +#if defined(SUPPORT_SMPU98) +extern COMMNG cm_smpu98[]; +#endif +extern COMMNG cm_rs232c; + +typedef struct { + OEMCHAR *buf; + int remain; +} ERR_BUF; + + +// ---- + +enum { + SFFILEH_WRITE = 0x0001, + SFFILEH_BLOCK = 0x0002, + SFFILEH_ERROR = 0x0004 +}; + +typedef struct { + _STFLAGH sfh; + UINT stat; + FILEH fh; + UINT secpos; + NP2FHDR f; +} _SFFILEH, *SFFILEH; + +static SFFILEH statflag_open(const OEMCHAR *filename, OEMCHAR *err, int errlen) { + + FILEH fh; + SFFILEH ret; + + fh = file_open_rb(filename); + if (fh == FILEH_INVALID) { + goto sfo_err1; + } + ret = (SFFILEH)_MALLOC(sizeof(_SFFILEH), filename); + if (ret == NULL) { + goto sfo_err2; + } + if ((file_read(fh, &ret->f, sizeof(NP2FHDR)) == sizeof(NP2FHDR)) && + (!memcmp(&ret->f, &np2flagdef, sizeof(np2flagdef)))) { + ZeroMemory(ret, sizeof(_SFFILEH)); + ret->fh = fh; + ret->secpos = sizeof(NP2FHDR); + if ((err) && (errlen > 0)) { + err[0] = '\0'; + ret->sfh.err = err; + ret->sfh.errlen = errlen; + } + return(ret); + } + _MFREE(ret); + +sfo_err2: + file_close(fh); + +sfo_err1: + return(NULL); +} + +static int statflag_closesection(SFFILEH sffh) { + + UINT leng; + UINT8 zero[16]; + + if (sffh == NULL) { + goto sfcs_err1; + } + if (sffh->stat == (SFFILEH_BLOCK | SFFILEH_WRITE)) { + leng = (0 - sffh->sfh.hdr.size) & 15; + if (leng) { + ZeroMemory(zero, sizeof(zero)); + if (file_write(sffh->fh, zero, leng) != leng) { + goto sfcs_err2; + } + } + if ((file_seek(sffh->fh, (long)sffh->secpos, FSEEK_SET) + != (long)sffh->secpos) || + (file_write(sffh->fh, &sffh->sfh.hdr, sizeof(sffh->sfh.hdr)) + != sizeof(sffh->sfh.hdr))) { + goto sfcs_err2; + } + } + if (sffh->stat & SFFILEH_BLOCK) { + sffh->stat &= ~SFFILEH_BLOCK; + sffh->secpos += sizeof(sffh->sfh.hdr) + + ((sffh->sfh.hdr.size + 15) & (~15)); + if (file_seek(sffh->fh, (long)sffh->secpos, FSEEK_SET) + != (long)sffh->secpos) { + goto sfcs_err2; + } + } + return(STATFLAG_SUCCESS); + +sfcs_err2: + sffh->stat = SFFILEH_ERROR; + +sfcs_err1: + return(STATFLAG_FAILURE); +} + +static int statflag_readsection(SFFILEH sffh) { + + int ret; + + ret = statflag_closesection(sffh); + if (ret != STATFLAG_SUCCESS) { + return(ret); + } + if ((sffh->stat == 0) && + (file_read(sffh->fh, &sffh->sfh.hdr, sizeof(sffh->sfh.hdr)) + == sizeof(sffh->sfh.hdr))) { + sffh->stat = SFFILEH_BLOCK; + sffh->sfh.pos = 0; + return(STATFLAG_SUCCESS); + } + sffh->stat = SFFILEH_ERROR; + return(STATFLAG_FAILURE); +} + +int statflag_read(STFLAGH sfh, void *buf, UINT size) { + + if ((sfh == NULL) || (buf == NULL) || + ((sfh->pos + size) > sfh->hdr.size)) { + goto sfr_err; + } + if (size) { + if (file_read(((SFFILEH)sfh)->fh, buf, size) != size) { + goto sfr_err; + } + sfh->pos += size; + } + return(STATFLAG_SUCCESS); + +sfr_err: + return(STATFLAG_FAILURE); +} + +static SFFILEH statflag_create(const OEMCHAR *filename) { + + SFFILEH ret; + FILEH fh; + + ret = (SFFILEH)_MALLOC(sizeof(_SFFILEH), filename); + if (ret == NULL) { + goto sfc_err1; + } + fh = file_create(filename); + if (fh == FILEH_INVALID) { + goto sfc_err2; + } + if (file_write(fh, &np2flagdef, sizeof(NP2FHDR)) == sizeof(NP2FHDR)) { + ZeroMemory(ret, sizeof(_SFFILEH)); + ret->stat = SFFILEH_WRITE; + ret->fh = fh; + ret->secpos = sizeof(NP2FHDR); + return(ret); + } + file_close(fh); + file_delete(filename); + +sfc_err2: + _MFREE(ret); + +sfc_err1: + return(NULL); +} + +static int statflag_createsection(SFFILEH sffh, const SFENTRY *tbl) { + + int ret; + + ret = statflag_closesection(sffh); + if (ret != STATFLAG_SUCCESS) { + return(ret); + } + if (sffh->stat != SFFILEH_WRITE) { + sffh->stat = SFFILEH_ERROR; + return(STATFLAG_FAILURE); + } + CopyMemory(sffh->sfh.hdr.index, tbl->index, sizeof(sffh->sfh.hdr.index)); + sffh->sfh.hdr.ver = tbl->ver; + sffh->sfh.hdr.size = 0; + return(STATFLAG_SUCCESS); +} + +int statflag_write(STFLAGH sfh, const void *buf, UINT size) { + + SFFILEH sffh; + + if (sfh == NULL) { + goto sfw_err1; + } + sffh = (SFFILEH)sfh; + if (!(sffh->stat & SFFILEH_WRITE)) { + goto sfw_err2; + } + if (!(sffh->stat & SFFILEH_BLOCK)) { + sffh->stat |= SFFILEH_BLOCK; + sfh->pos = 0; + if (file_write(sffh->fh, &sfh->hdr, sizeof(sfh->hdr)) + != sizeof(sfh->hdr)) { + goto sfw_err2; + } + } + if (size) { + if ((buf == NULL) || (file_write(sffh->fh, buf, size) != size)) { + goto sfw_err2; + } + sfh->pos += size; + if (sfh->hdr.size < sfh->pos) { + sfh->hdr.size = sfh->pos; + } + } + return(STATFLAG_SUCCESS); + +sfw_err2: + sffh->stat = SFFILEH_ERROR; + +sfw_err1: + return(STATFLAG_FAILURE); +} + +static void statflag_close(SFFILEH sffh) { + + if (sffh) { + statflag_closesection(sffh); + file_close(sffh->fh); + _MFREE(sffh); + } +} + +void statflag_seterr(STFLAGH sfh, const OEMCHAR *str) { + + if ((sfh) && (sfh->errlen)) { + milstr_ncat(sfh->err, str, sfh->errlen); + milstr_ncat(sfh->err, CRCONST, sfh->errlen); + } +} + + +// ---- function + +// 関数ポインタを intに変更。 +static BRESULT proc2num(void *func, const PROCTBL *tbl, int size) { + + int i; + + for (i=0; iproc) { + *(INTPTR *)func = (INTPTR)tbl->id; + return(SUCCESS); + } + tbl++; + } + return(FAILURE); +} + +static BRESULT num2proc(void *func, const PROCTBL *tbl, int size) { + + int i; + + for (i=0; iid) { + *(INTPTR *)func = (INTPTR)tbl->proc; + return(SUCCESS); + } + tbl++; + } + return(FAILURE); +} + + +// ---- file + +typedef struct { + OEMCHAR path[MAX_PATH]; + UINT ftype; + int readonly; + DOSDATE date; + DOSTIME time; +} STATPATH; + +static const OEMCHAR str_updated[] = OEMTEXT("%s: updated"); +static const OEMCHAR str_notfound[] = OEMTEXT("%s: not found"); + +static int statflag_writepath(STFLAGH sfh, const OEMCHAR *path, + UINT ftype, int readonly) { + + STATPATH sp; + FILEH fh; + + ZeroMemory(&sp, sizeof(sp)); + if ((path) && (path[0])) { + file_cpyname(sp.path, path, NELEMENTS(sp.path)); + sp.ftype = ftype; + sp.readonly = readonly; + fh = file_open_rb(path); + if (fh != FILEH_INVALID) { + file_getdatetime(fh, &sp.date, &sp.time); + file_close(fh); + } + } + return(statflag_write(sfh, &sp, sizeof(sp))); +} + +static int statflag_checkpath(STFLAGH sfh, const OEMCHAR *dvname) { + + int ret; + STATPATH sp; + FILEH fh; + OEMCHAR buf[256]; + DOSDATE dosdate; + DOSTIME dostime; + + ret = statflag_read(sfh, &sp, sizeof(sp)); + if (sp.path[0]) { + fh = file_open_rb(sp.path); + if (fh != FILEH_INVALID) { + file_getdatetime(fh, &dosdate, &dostime); + file_close(fh); + if ((memcmp(&sp.date, &dosdate, sizeof(dosdate))) || + (memcmp(&sp.time, &dostime, sizeof(dostime)))) { + ret |= STATFLAG_DISKCHG; + OEMSNPRINTF(buf, sizeof(buf), str_updated, dvname); + statflag_seterr(sfh, buf); + } + } + else { + ret |= STATFLAG_DISKCHG; + OEMSNPRINTF(buf, sizeof(buf), str_notfound, dvname); + statflag_seterr(sfh, buf); + } + } + return(ret); +} + + +// ---- common + +static int flagsave_common(STFLAGH sfh, const SFENTRY *tbl) { + + return(statflag_write(sfh, tbl->arg1, tbl->arg2)); +} + +static int flagload_common(STFLAGH sfh, const SFENTRY *tbl) { + + memset(tbl->arg1, 0, tbl->arg2); + return(statflag_read(sfh, tbl->arg1, MIN(tbl->arg2, sfh->hdr.size))); +} + + +// ---- memory + +static int flagsave_mem(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + + ret = statflag_write(sfh, mem, 0x110000); + ret |= statflag_write(sfh, mem + VRAM1_B, 0x18000); + ret |= statflag_write(sfh, mem + VRAM1_E, 0x8000); + (void)tbl; + return(ret); +} + +static int flagload_mem(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + + ret = statflag_read(sfh, mem, 0x110000); + ret |= statflag_read(sfh, mem + VRAM1_B, 0x18000); + ret |= statflag_read(sfh, mem + VRAM1_E, 0x8000); + (void)tbl; + return(ret); +} + + +// ---- dma + +static int flagsave_dma(STFLAGH sfh, const SFENTRY *tbl) { + + int i; + _DMAC dmabak; + + dmabak = dmac; + for (i=0; i<4; i++) { + if ((PROC2NUM(dmabak.dmach[i].proc.outproc, dmaproc)) || + (PROC2NUM(dmabak.dmach[i].proc.inproc, dmaproc)) || + (PROC2NUM(dmabak.dmach[i].proc.extproc, dmaproc))) { + return(STATFLAG_FAILURE); + } + } + (void)tbl; + return(statflag_write(sfh, &dmabak, sizeof(dmabak))); +} + +static int flagload_dma(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + int i; + + ret = statflag_read(sfh, &dmac, sizeof(dmac)); + + for (i=0; i<4; i++) { + if (NUM2PROC(dmac.dmach[i].proc.outproc, dmaproc)) { + dmac.dmach[i].proc.outproc = dma_dummyout; + ret |= STATFLAG_WARNING; + } + if (NUM2PROC(dmac.dmach[i].proc.inproc, dmaproc)) { + dmac.dmach[i].proc.inproc = dma_dummyin; + ret |= STATFLAG_WARNING; + } + if (NUM2PROC(dmac.dmach[i].proc.extproc, dmaproc)) { + dmac.dmach[i].proc.extproc = dma_dummyproc; + ret |= STATFLAG_WARNING; + } + } + (void)tbl; + return(ret); +} + + +// ---- egc + +static int flagsave_egc(STFLAGH sfh, const SFENTRY *tbl) { + + _EGC egcbak; + + egcbak = egc; + egcbak.inptr -= (INTPTR)egc.buf; + egcbak.outptr -= (INTPTR)egc.buf; + (void)tbl; + return(statflag_write(sfh, &egcbak, sizeof(egcbak))); +} + +static int flagload_egc(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + + ret = statflag_read(sfh, &egc, sizeof(egc)); + egc.inptr += (INTPTR)egc.buf; + egc.outptr += (INTPTR)egc.buf; + (void)tbl; + return(ret); +} + + +// ---- epson + +static int flagsave_epson(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + + if (!(pccore.model & PCMODEL_EPSON)) { + return(STATFLAG_SUCCESS); + } + ret = statflag_write(sfh, &epsonio, sizeof(epsonio)); + ret |= statflag_write(sfh, mem + 0x1c0000, 0x8000); + ret |= statflag_write(sfh, mem + 0x1e8000, 0x18000); + (void)tbl; + return(ret); +} + +static int flagload_epson(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + + ret = statflag_read(sfh, &epsonio, sizeof(epsonio)); + ret |= statflag_read(sfh, mem + 0x1c0000, 0x8000); + ret |= statflag_read(sfh, mem + 0x1e8000, 0x18000); + (void)tbl; + return(ret); +} + + +// ---- event + +typedef struct { + UINT readyevents; + UINT waitevents; +} NEVTSAVE; + +typedef struct { + UINT32 id; + SINT32 clock; + UINT32 flag; + NEVENTCB proc; +} NEVTITEM; + +static int nevent_write(STFLAGH sfh, NEVENTID num) { + + NEVTITEM nit; + UINT i; + + ZeroMemory(&nit, sizeof(nit)); + for (i=0; i sizeof(g_musicgen)) return STATFLAG_FAILURE; // 旧バージョンで読めないようにしておく(コメントアウトすると読めるようになるが、ちゃんと考えて設計しないと危険) + ret |= statflag_read(sfh, &g_musicgen, MIN(datalen, sizeof(g_musicgen))); + if(datalen > sizeof(g_musicgen)){ + sfh->pos += datalen - sizeof(g_musicgen); + }else{ + memset((UINT8*)(&g_musicgen) + datalen, 0, sizeof(g_musicgen) - datalen); // ない部分は0埋め + } + board14_allkeymake(); + } + for (i = 0; i < NELEMENTS(g_opna); i++) + { + if (nSaveFlags & (FLAG_OPNA1 << i)) + { + ret |= opna_sfload(&g_opna[i], sfh, tbl); + } + } + if (nSaveFlags & FLAG_PCM86) + { + ret |= statflag_read(sfh, &datalen, sizeof(datalen)); + if(datalen > sizeof(g_pcm86)) return STATFLAG_FAILURE; // 旧バージョンで読めないようにしておく(コメントアウトすると読めるようになるが、ちゃんと考えて設計しないと危険) + ret |= statflag_read(sfh, &g_pcm86, MIN(datalen, sizeof(g_pcm86))); + if(datalen > sizeof(g_pcm86)){ + sfh->pos += datalen - sizeof(g_pcm86); + }else{ + memset((UINT8*)(&g_pcm86) + datalen, 0, sizeof(g_pcm86) - datalen); // ない部分は0埋め + } + } + if (nSaveFlags & FLAG_CS4231) + { + ret |= statflag_read(sfh, &datalen, sizeof(datalen)); + if(datalen > sizeof(cs4231)) return STATFLAG_FAILURE; // 旧バージョンで読めないようにしておく(コメントアウトすると読めるようになるが、ちゃんと考えて設計しないと危険) + ret |= statflag_read(sfh, &cs4231, MIN(datalen, sizeof(cs4231))); + if(datalen > sizeof(cs4231)){ + sfh->pos += datalen - sizeof(cs4231); + }else{ + memset((UINT8*)(&cs4231) + datalen, 0, sizeof(cs4231) - datalen); // ない部分は0埋め + } + } + if (nSaveFlags & FLAG_AMD98) + { + ret |= amd98_sfload(sfh, tbl); + } + if (nSaveFlags & FLAG_OPL3) + { + for (i = 0; i < NELEMENTS(g_opl3); i++) + { + ret |= opl3_sfload(&g_opl3[i], sfh, tbl); + } +#ifdef USE_MAME + for (i = 0; i < NELEMENTS(g_mame_opl3); i++) + { + void* buffer; + int bufsize = 0; + ret |= statflag_read(sfh, &bufsize, sizeof(SINT32)); + if(bufsize!=0){ + buffer = malloc(bufsize); + ret |= statflag_read(sfh, buffer, bufsize); + if (g_mame_opl3[i]) { + if (!YMF262FlagLoad(g_mame_opl3[i], buffer, bufsize)) { + free(buffer); + ret = STATFLAG_FAILURE; + break; + } + } + free(buffer); + } + } +#endif + } +#if defined(SUPPORT_SOUND_SB16) + if (nSaveFlags & FLAG_SB16) + { + ret |= statflag_read(sfh, &datalen, sizeof(datalen)); + if(datalen > sizeof(g_sb16)) return STATFLAG_FAILURE; // 旧バージョンで読めないようにしておく(コメントアウトすると読めるようになるが、ちゃんと考えて設計しないと危険) + ret |= statflag_read(sfh, &g_sb16, MIN(datalen, sizeof(g_sb16))); + if(datalen > sizeof(g_sb16)){ + sfh->pos += datalen - sizeof(g_sb16); + }else{ + memset((UINT8*)(&g_sb16) + datalen, 0, sizeof(g_sb16) - datalen); // ない部分は0埋め + } + } +#endif + }else{ + // old statsave + nSaveFlags = GetSoundFlags(g_nSoundID); + if (nSaveFlags & FLAG_MG) + { + ret |= statflag_read(sfh, &g_musicgen, sizeof(MUSICGEN_OLD)); + if(sizeof(MUSICGEN_OLD) < sizeof(g_musicgen)){ + memset((UINT8*)(&g_musicgen) + sizeof(MUSICGEN_OLD), 0, sizeof(g_musicgen) - sizeof(MUSICGEN_OLD)); // ない部分は0埋め + } + board14_allkeymake(); + } + for (i = 0; i < NELEMENTS(g_opna); i++) + { + if (nSaveFlags & (FLAG_OPNA1 << i)) + { + ret |= opna_sfload(&g_opna[i], sfh, tbl); + } + } + if (nSaveFlags & FLAG_PCM86) + { + ret |= statflag_read(sfh, &g_pcm86, sizeof(_PCM86_OLD)); + if(sizeof(_PCM86_OLD) < sizeof(g_pcm86)){ + memset((UINT8*)(&g_pcm86) + sizeof(_PCM86_OLD), 0, sizeof(g_pcm86) - sizeof(_PCM86_OLD)); // ない部分は0埋め + } + g_pcm86.lastclock = g_pcm86.obsolate.lastclock_obsolate; + g_pcm86.stepclock = g_pcm86.obsolate.stepclock_obsolate; + } + if (nSaveFlags & FLAG_CS4231) + { + ret |= statflag_read(sfh, &cs4231, sizeof(_CS4231_OLD)); + if(sizeof(_CS4231_OLD) < sizeof(cs4231)){ + memset((UINT8*)(&cs4231) + sizeof(_CS4231_OLD), 0, sizeof(cs4231) - sizeof(_CS4231_OLD)); // ない部分は0埋め + } + } + if (nSaveFlags & FLAG_AMD98) + { + ret |= amd98_sfload(sfh, tbl); + } + if (nSaveFlags & FLAG_OPL3) + { + for (i = 0; i < NELEMENTS(g_opl3); i++) + { + ret |= opl3_sfload(&g_opl3[i], sfh, tbl); + } +#ifdef USE_MAME + for (i = 0; i < NELEMENTS(g_mame_opl3); i++) + { + void* buffer; + int bufsize = 0; + ret |= statflag_read(sfh, &bufsize, sizeof(SINT32)); + if(bufsize!=0){ + buffer = malloc(bufsize); + ret |= statflag_read(sfh, buffer, bufsize); + if (g_mame_opl3[i]) { + if (!YMF262FlagLoad(g_mame_opl3[i], buffer, bufsize)) { + free(buffer); + ret = STATFLAG_FAILURE; + break; + } + } + free(buffer); + } + } +#endif + } +#if defined(SUPPORT_SOUND_SB16) + if (nSaveFlags & FLAG_SB16) + { + ret |= statflag_read(sfh, &g_sb16, SIZEOF_SB16_OLD); + if(SIZEOF_SB16_OLD < sizeof(g_sb16)){ + memset((UINT8*)(&g_sb16) + SIZEOF_SB16_OLD, 0, sizeof(g_sb16) - SIZEOF_SB16_OLD); // ない部分は0埋め + } + } +#endif + } + + // 復元。 これ移動すること! + pcm86gen_update(); + if (nSaveFlags & FLAG_PCM86) + { + fmboard_extenable((REG8)(g_pcm86.soundflags & 1)); + } + if (nSaveFlags & FLAG_CS4231) + { + fmboard_extenable((REG8)(cs4231.extfunc & 1)); + } +#if defined(SUPPORT_SOUND_SB16) + if (nSaveFlags & FLAG_SB16) + { + g_sb16.dsp_info.dma.dmach = dmac.dmach + g_sb16.dmachnum; // DMAチャネル復元 + dmac_attach(DMADEV_CT1741, g_sb16.dmachnum); // 再割り当て + } +#endif + return(ret); +} +#endif + + +// ---- fdd + +static const OEMCHAR str_fddx[] = OEMTEXT("FDD%u"); + +static int flagsave_fdd(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + UINT8 i; +const OEMCHAR *path; + UINT ftype; + int ro; + + ret = STATFLAG_SUCCESS; + for (i=0; i<4; i++) { + path = fdd_getfileex(i, &ftype, &ro); + ret |= statflag_writepath(sfh, path, ftype, ro); + } + (void)tbl; + return(ret); +} + +static int flagcheck_fdd(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + int i; + OEMCHAR buf[32]; + + ret = STATFLAG_SUCCESS; + for (i=0; i<4; i++) { + OEMSNPRINTF(buf, sizeof(buf), str_fddx, i+1); + ret |= statflag_checkpath(sfh, buf); + } + (void)tbl; + return(ret); +} + +static int flagload_fdd(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + UINT8 i; + STATPATH sp; + + ret = STATFLAG_SUCCESS; + for (i=0; i<4; i++) { + ret |= statflag_read(sfh, &sp, sizeof(sp)); + if (sp.path[0]) { + fdd_set(i, sp.path, sp.ftype, sp.readonly); + } + } + (void)tbl; + return(ret); +} + + +// ---- sxsi + +typedef struct { + UINT8 ide[4]; + UINT8 scsi[8]; +} SXSIDEVS; + +#ifdef SUPPORT_IDEIO +static const OEMCHAR str_sasix[] = OEMTEXT("IDE#%u"); +#else +static const OEMCHAR str_sasix[] = OEMTEXT("SASI%u"); +#endif +static const OEMCHAR str_scsix[] = OEMTEXT("SCSI%u"); + +static int flagsave_sxsi(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + UINT i; + SXSIDEVS sds; +const OEMCHAR *path; + + sxsi_allflash(); + ret = STATFLAG_SUCCESS; + for (i=0; iarg1; + switch(device) { + case 0: + cm = cm_mpu98; + break; + + case 1: + cm = cm_rs232c; + break; + +#if defined(SUPPORT_SMPU98) + case 2: + cm = cm_smpu98[0]; + break; + + case 3: + cm = cm_smpu98[1]; + break; +#endif + + default: + cm = NULL; + break; + } + ret = STATFLAG_SUCCESS; + if (cm) { + flag = (COMFLAG)cm->msg(cm, COMMSG_GETFLAG, 0); + if (flag) { + ret |= statflag_write(sfh, flag, flag->size); + _MFREE(flag); + } + } + return(ret); +} + +static int flagload_com(STFLAGH sfh, const SFENTRY *tbl) { + + UINT device; + COMMNG cm; + int ret; + _COMFLAG fhdr; + COMFLAG flag; + + ret = statflag_read(sfh, &fhdr, sizeof(fhdr)); + if (ret != STATFLAG_SUCCESS) { + goto flcom_err1; + } + if (fhdr.size < sizeof(fhdr)) { + goto flcom_err1; + } + flag = (COMFLAG)_MALLOC(fhdr.size, "com stat flag"); + if (flag == NULL) { + goto flcom_err1; + } + CopyMemory(flag, &fhdr, sizeof(fhdr)); + ret |= statflag_read(sfh, flag + 1, fhdr.size - sizeof(fhdr)); + if (ret != STATFLAG_SUCCESS) { + goto flcom_err2; + } + + device = (UINT)(INTPTR)tbl->arg1; + switch(device) { + case 0: + commng_destroy(cm_mpu98); + cm = commng_create(COMCREATE_MPU98II, FALSE); + cm_mpu98 = cm; + break; + + case 1: + commng_destroy(cm_rs232c); + cm = commng_create(COMCREATE_SERIAL, FALSE); + cm_rs232c = cm; + break; + +#if defined(SUPPORT_SMPU98) + case 2: + commng_destroy(cm_smpu98[0]); + cm = commng_create(COMCREATE_SMPU98_A, FALSE); + cm_smpu98[0] = cm; + break; + + case 3: + commng_destroy(cm_smpu98[1]); + cm = commng_create(COMCREATE_SMPU98_B, FALSE); + cm_smpu98[1] = cm; + break; +#endif + + default: + cm = NULL; + break; + } + if (cm) { + cm->msg(cm, COMMSG_SETFLAG, (INTPTR)flag); + } + +flcom_err2: + _MFREE(flag); + +flcom_err1: + return(ret); +} + +// ---- bms + +#if defined(SUPPORT_BMS) + +static int flagsave_bms(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + + ret = STATFLAG_SUCCESS; + if (bmsiowork.bmsmem) { + ret = statflag_write(sfh, bmsiowork.bmsmem, bmsiowork.bmsmemsize); + } + (void)tbl; + return(ret); +} + +static int flagload_bms(STFLAGH sfh, const SFENTRY *tbl) { + + int ret; + + ret = STATFLAG_SUCCESS; + if (bmsiowork.bmsmem) { + ret = statflag_read(sfh, bmsiowork.bmsmem, bmsiowork.bmsmemsize); + } + (void)tbl; + return(ret); +} + +#endif + +// ---- + +static int flagcheck_versize(STFLAGH sfh, const SFENTRY *tbl) { + + if ((sfh->hdr.ver == tbl->ver) && ((sfh->hdr.size == tbl->arg2) || + ((tbl->type & STATFLAG_BWD_COMPATIBLE) && sfh->hdr.size < tbl->arg2) || + ((tbl->type & STATFLAG_FWD_COMPATIBLE) && sfh->hdr.size > tbl->arg2))) { + return(STATFLAG_SUCCESS); + } + return(STATFLAG_FAILURE); +} + +static int flagcheck_veronly(STFLAGH sfh, const SFENTRY *tbl) { + + if (sfh->hdr.ver == tbl->ver) { + return(STATFLAG_SUCCESS); + } + return(STATFLAG_FAILURE); +} + + +// ---- + +int statsave_save(const OEMCHAR *filename) { + if(filename) { + milstr_ncpy(m_strStateFilename, filename, MAX_PATH); + g_u8ControlState = 1; + } +} + +#if defined(__LIBRETRO__) +int statsave_save_d(const OEMCHAR *filename) { +#else +int statsave_save_d(void) { +#endif + + SFFILEH sffh; + int ret; +const SFENTRY *tbl; +const SFENTRY *tblterm; + +#if defined(__LIBRETRO__) + sffh = statflag_create(filename); +#else + sffh = statflag_create(m_strStateFilename); +#endif + if (sffh == NULL) { + return(STATFLAG_FAILURE); + } + +#if defined(SUPPORT_CL_GD5430) + pc98_cirrus_vga_save(); +#endif + +#if defined(SUPPORT_IA32_HAXM) + memcpy(vramex_base, vramex, sizeof(vramex_base)); + i386haxfunc_vcpu_getMSRs(&np2haxstat.msrstate); +#endif + + ret = STATFLAG_SUCCESS; + tbl = np2tbl; + tblterm = tbl + NELEMENTS(np2tbl); + while(tbl < tblterm) { + ret |= statflag_createsection(sffh, tbl); + switch(tbl->type & STATFLAG_MASK) { + case STATFLAG_BIN: + case STATFLAG_TERM: + ret |= flagsave_common(&sffh->sfh, tbl); + break; + + case STATFLAG_COM: + ret |= flagsave_com(&sffh->sfh, tbl); + break; + + case STATFLAG_DMA: + ret |= flagsave_dma(&sffh->sfh, tbl); + break; + + case STATFLAG_EGC: + ret |= flagsave_egc(&sffh->sfh, tbl); + break; + + case STATFLAG_EPSON: + ret |= flagsave_epson(&sffh->sfh, tbl); + break; + + case STATFLAG_EVT: + ret |= flagsave_evt(&sffh->sfh, tbl); + break; + + case STATFLAG_EXT: + ret |= flagsave_ext(&sffh->sfh, tbl); + break; + + case STATFLAG_FDD: + ret |= flagsave_fdd(&sffh->sfh, tbl); + break; + +#if !defined(DISABLE_SOUND) + case STATFLAG_FM: + ret |= flagsave_fm(&sffh->sfh, tbl); + break; +#endif + + case STATFLAG_GIJ: + ret |= flagsave_gij(&sffh->sfh, tbl); + break; + +#if defined(SUPPORT_HOSTDRV) + case STATFLAG_HDRV: + ret |= hostdrv_sfsave(&sffh->sfh, tbl); + break; +#endif +#if defined(SUPPORT_HOSTDRVNT) + case STATFLAG_HDRVNT: + ret |= hostdrvNT_sfsave(&sffh->sfh, tbl); + break; +#endif + + case STATFLAG_MEM: + ret |= flagsave_mem(&sffh->sfh, tbl); + break; + +#if defined(SUPPORT_BMS) + case STATFLAG_BMS: + ret |= flagsave_bms(&sffh->sfh, tbl); + break; +#endif + + case STATFLAG_SXSI: + ret |= flagsave_sxsi(&sffh->sfh, tbl); + break; + } + tbl++; + } + statflag_close(sffh); + return(ret); +} + +int statsave_check(const OEMCHAR *filename, OEMCHAR *buf, int size) { + + SFFILEH sffh; + int ret; + BOOL done; +const SFENTRY *tbl; +const SFENTRY *tblterm; + + sffh = statflag_open(filename, buf, size); + if (sffh == NULL) { + return(STATFLAG_FAILURE); + } + + done = FALSE; + ret = STATFLAG_SUCCESS; + while((!done) && (ret != STATFLAG_FAILURE)) { + ret |= statflag_readsection(sffh); + tbl = np2tbl; + tblterm = tbl + NELEMENTS(np2tbl); + while(tbl < tblterm) { + if (!memcmp(sffh->sfh.hdr.index, tbl->index, sizeof(sffh->sfh.hdr.index))) { + break; + } + tbl++; + } + if (tbl < tblterm) { + switch(tbl->type & STATFLAG_MASK) { + case STATFLAG_BIN: + case STATFLAG_MEM: + ret |= flagcheck_versize(&sffh->sfh, tbl); + break; + + case STATFLAG_TERM: + done = TRUE; + break; + + case STATFLAG_COM: + case STATFLAG_DMA: + case STATFLAG_EGC: + case STATFLAG_EPSON: + case STATFLAG_EVT: + case STATFLAG_EXT: + case STATFLAG_GIJ: +#if !defined(DISABLE_SOUND) + case STATFLAG_FM: +#endif + ret |= flagcheck_veronly(&sffh->sfh, tbl); + break; + +#if defined(SUPPORT_HOSTDRV) + case STATFLAG_HDRV: + ret |= flagcheck_veronly(&sffh->sfh, tbl); + break; +#endif + +#if defined(SUPPORT_HOSTDRVNT) + case STATFLAG_HDRVNT: + ret |= flagcheck_veronly(&sffh->sfh, tbl); + break; +#endif + + case STATFLAG_FDD: + ret |= flagcheck_fdd(&sffh->sfh, tbl); + break; + + case STATFLAG_SXSI: + ret |= flagcheck_sxsi(&sffh->sfh, tbl); + break; + + default: + ret |= STATFLAG_WARNING; + break; + } + } + else { + ret |= STATFLAG_WARNING; + } + } + statflag_close(sffh); + return(ret); +} + +int statsave_load(const OEMCHAR *filename) { + if(filename) { + milstr_ncpy(m_strStateFilename, filename, MAX_PATH); + g_u8ControlState = 2; + } +} + +#if defined(__LIBRETRO__) +int statsave_load_d(const OEMCHAR *filename) { +#else +int statsave_load_d(void) { +#endif + + SFFILEH sffh; + int ret; + BOOL done; +const SFENTRY *tbl; +const SFENTRY *tblterm; + UINT i; +#if defined(SUPPORT_FMGEN) + UINT8 usefmgen = 0; +#endif + +#if defined(__LIBRETRO__) + sffh = statflag_open(filename, NULL, 0); +#else + sffh = statflag_open(m_strStateFilename, NULL, 0); +#endif + if (sffh == NULL) { + return(STATFLAG_FAILURE); + } + + // PCCORE read! + ret = statflag_readsection(sffh); + if ((ret != STATFLAG_SUCCESS) || + (memcmp(sffh->sfh.hdr.index, np2tbl[0].index, sizeof(sffh->sfh.hdr.index)))) { + statflag_close(sffh); + return(STATFLAG_FAILURE); + } + + soundmng_stop(); + rs232c_midipanic(); + mpu98ii_midipanic(); +#if defined(SUPPORT_SMPU98) + smpu98_midipanic(); +#endif + pc9861k_midipanic(); + sxsi_alltrash(); + + ret |= flagload_common(&sffh->sfh, np2tbl); + + CPU_RESET(); + CPU_SETEXTSIZE((UINT32)pccore.extmem); + nevent_allreset(); + + sound_changeclock(); + beep_changeclock(); + sound_reset(); + fddmtrsnd_bind(); + wabrlysnd_bind(); + + iocore_reset(&np2cfg); // サウンドでpicを呼ぶので… + cbuscore_reset(&np2cfg); + fmboard_reset(&np2cfg, pccore.sound); + + done = FALSE; + while((!done) && (ret != STATFLAG_FAILURE)) { + ret |= statflag_readsection(sffh); + tbl = np2tbl + 1; + tblterm = np2tbl + NELEMENTS(np2tbl); + while(tbl < tblterm) { + if (!memcmp(sffh->sfh.hdr.index, tbl->index, sizeof(sffh->sfh.hdr.index))) { + break; + } + tbl++; + } + if (tbl < tblterm) { + switch(tbl->type & STATFLAG_MASK) { + case STATFLAG_BIN: + ret |= flagload_common(&sffh->sfh, tbl); + break; + + case STATFLAG_TERM: + done = TRUE; + break; + + case STATFLAG_COM: + ret |= flagload_com(&sffh->sfh, tbl); + break; + + case STATFLAG_DMA: + ret |= flagload_dma(&sffh->sfh, tbl); + break; + + case STATFLAG_EGC: + ret |= flagload_egc(&sffh->sfh, tbl); + break; + + case STATFLAG_EPSON: + ret |= flagload_epson(&sffh->sfh, tbl); + break; + + case STATFLAG_EVT: + ret |= flagload_evt(&sffh->sfh, tbl); + break; + + case STATFLAG_EXT: + ret |= flagload_ext(&sffh->sfh, tbl); + break; + + case STATFLAG_FDD: + ret |= flagload_fdd(&sffh->sfh, tbl); + break; + +#if !defined(DISABLE_SOUND) + case STATFLAG_FM: + ret |= flagload_fm(&sffh->sfh, tbl); + break; +#endif + + case STATFLAG_GIJ: + ret |= flagload_gij(&sffh->sfh, tbl); + break; + +#if defined(SUPPORT_HOSTDRV) + case STATFLAG_HDRV: + ret |= hostdrv_sfload(&sffh->sfh, tbl); + break; +#endif + +#if defined(SUPPORT_HOSTDRVNT) + case STATFLAG_HDRVNT: + ret |= hostdrvNT_sfload(&sffh->sfh, tbl); + break; +#endif + + case STATFLAG_MEM: + ret |= flagload_mem(&sffh->sfh, tbl); + break; + +#if defined(SUPPORT_BMS) + case STATFLAG_BMS: + ret |= flagload_bms(&sffh->sfh, tbl); + break; +#endif + + case STATFLAG_SXSI: + ret |= flagload_sxsi(&sffh->sfh, tbl); + break; + + default: + ret |= STATFLAG_WARNING; + break; + } + } + else { + ret |= STATFLAG_WARNING; + } + } + statflag_close(sffh); + + // ステートセーブ互換性維持用 + if(pccore.maxmultiple == 0) pccore.maxmultiple = pccore.multiple; + +#if defined(CPUCORE_IA32) + // FPUロード + fpu_statesave_load(); +#endif + +#if defined(SUPPORT_IA32_HAXM) + memcpy(vramex, vramex_base, sizeof(vramex_base)); + i386haxfunc_vcpu_setREGs(&np2haxstat.state); + i386haxfunc_vcpu_setFPU(&np2haxstat.fpustate); + { + HAX_MSR_DATA msrstate_set = {0}; + i386haxfunc_vcpu_setMSRs(&np2haxstat.msrstate, &msrstate_set); + } + i386hax_vm_sethmemory(CPU_ADRSMASK != 0x000fffff); + i386hax_vm_setitfmemory(CPU_ITFBANK); + i386hax_vm_setvga256linearmemory(); + np2haxcore.clockpersec = NP2_TickCount_GetFrequency(); + np2haxcore.lastclock = NP2_TickCount_GetCount(); + np2haxcore.clockcount = NP2_TickCount_GetCount(); + np2haxcore.I_ratio = 0; +#endif + + // I/O作り直し + MEMM_ARCH((pccore.model & PCMODEL_EPSON)?1:0); + iocore_build(); + iocore_bind(); + cbuscore_bind(); + fmboard_bind(); + + // DA/UAと要素番号の対応関係を初期化 + for(i=0;i<4;i++){ + sxsi_unittbl[i] = i; + } +#if defined(SUPPORT_IDEIO) + if (pccore.hddif & PCHDD_IDE) { + int i, idx, ncidx; + // 未接続のものを無視して接続順にDA/UAを割り当てる + ncidx = idx = 0; + for(i=0;i<4;i++){ + if(sxsi_getdevtype(i)==SXSIDEV_HDD){ + sxsi_unittbl[idx] = i; + idx++; + }else{ + ncidx = i; + } + } + for(;idx<4;idx++){ + sxsi_unittbl[idx] = ncidx; // XXX: 余ったDA/UAはとりあえず未接続の番号に設定 + } + } +#endif + +#if defined(SUPPORT_PC9821)&&defined(SUPPORT_PCI) + pcidev_bind(); +#endif + +#if defined(CPUCORE_IA32) +#if defined(USE_CPU_EIPMASK) + CPU_EIPMASK = CPU_STATSAVE.cpu_inst_default.op_32 ? 0xffffffff : 0xffff; +#endif + fpu_initialize(0); +#endif + +#if defined(SUPPORT_NET) + np2net_reset(&np2cfg); + np2net_bind(); +#endif +#if defined(SUPPORT_LGY98) + lgy98_bind(); +#endif +#if defined(SUPPORT_WAB) + np2wab_bind(); +#endif +#if defined(SUPPORT_CL_GD5430) + pc98_cirrus_vga_bind(); + pc98_cirrus_vga_load(); +#endif + + // OPNAボリューム再設定 +#if defined(SUPPORT_FMGEN) + for (i = 0; i < OPNA_MAX; i++) { + usefmgen |= g_opna[i].usefmgen; + } +#endif + if(g_nSoundID == SOUNDID_WAVESTAR){ + opngen_setvol(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + psggen_setvol(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + rhythm_setvol(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); +#if defined(SUPPORT_FMGEN) + if(usefmgen) { + opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * cs4231.devvolume[0xff] / 15 * np2cfg.vol_master / 100); + } +#endif + }else{ + opngen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); + psggen_setvol(np2cfg.vol_ssg * np2cfg.vol_master / 100); + rhythm_setvol(np2cfg.vol_rhythm * np2cfg.vol_master / 100); +#if defined(SUPPORT_FMGEN) + if(usefmgen) { + opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * np2cfg.vol_master / 100); + opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * np2cfg.vol_master / 100); + opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * np2cfg.vol_master / 100); + } +#endif + oplgen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); + } + for (i = 0; i < NELEMENTS(g_opna); i++) + { + rhythm_update(&g_opna[i].rhythm); + } + + gdcs.textdisp |= GDCSCRN_EXT; + gdcs.textdisp |= GDCSCRN_ALLDRAW2; + gdcs.grphdisp |= GDCSCRN_EXT; + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + gdcs.palchange = GDCSCRN_REDRAW; + tramflag.renewal = 1; + cgwindow.writable |= 0x80; +#if defined(CPUSTRUC_FONTPTR) + FONTPTR_LOW = fontrom + cgwindow.low; + FONTPTR_HIGH = fontrom + cgwindow.high; +#endif + MEMM_VRAM(vramop.operate); + fddmtr_reset(); + soundmng_play(); + +#if defined(SUPPORT_WAB) + { + UINT8 wabaswtmp = np2cfg.wabasw; + np2cfg.wabasw = 1; // リレー音を鳴らさない + np2wab.relay = 0; + np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); + np2wab.realWidth = np2wab.wndWidth; // XXX: ??? + np2wab.realHeight = np2wab.wndHeight; // XXX: ??? + np2wab.lastWidth = 0; + np2wab.lastHeight = 0; + np2wab_setScreenSize(np2wab.wndWidth, np2wab.wndHeight); + np2cfg.wabasw = wabaswtmp; + } +#endif + + pit_setrs232cspeed((pit.ch + 2)->value); +#if defined(SUPPORT_RS232C_FIFO) + rs232c_vfast_setrs232cspeed(rs232cfifo.vfast); +#endif + +#if defined(NP2_WIN) + // カーソル表示状態復元 + mousemng_updateautohidecursor(); +#endif + + return(ret); +} + +int statsave_save_hdd(const OEMCHAR *ext) +{ + BRESULT r; + + r = sxsi_state_save(ext); + if (r == SUCCESS) + { + return (STATFLAG_SUCCESS); + } + else + { + return (STATFLAG_FAILURE); + } +} + +int statsave_load_hdd(const OEMCHAR *ext) +{ + BRESULT r; + + r = sxsi_state_load(ext); + if (r == SUCCESS) + { + return (STATFLAG_SUCCESS); + } + else + { + return (STATFLAG_FAILURE); + } +} + diff --git a/statsave.h b/statsave.h old mode 100755 new mode 100644 index f652a098..5ed95d41 --- a/statsave.h +++ b/statsave.h @@ -1,64 +1,64 @@ -/** - * @file statsave.h - * @brief Interface of state save - */ - -#pragma once - -/** - * Result code - */ -enum -{ - STATFLAG_SUCCESS = 0, - STATFLAG_DISKCHG = 0x0001, - STATFLAG_VERCHG = 0x0002, - STATFLAG_WARNING = 0x0080, - STATFLAG_VERSION = 0x0100, - STATFLAG_FAILURE = -1 -}; - -struct TagStatFlagHandle; -typedef struct TagStatFlagHandle *STFLAGH; - -/** - * @brief The entry of state flag - */ -struct TagStatFlagEntry -{ - char index[12]; - UINT16 ver; - UINT16 type; - void *arg1; - UINT arg2; -}; -typedef struct TagStatFlagEntry SFENTRY; - -#ifdef __cplusplus -extern "C" -{ -#endif - -extern uint8_t g_u8ControlState; - -int statflag_read(STFLAGH sfh, void *ptr, UINT size); -int statflag_write(STFLAGH sfh, const void *ptr, UINT size); -void statflag_seterr(STFLAGH sfh, const OEMCHAR *str); - -int statsave_save(const OEMCHAR *filename); -int statsave_check(const OEMCHAR *filename, OEMCHAR *buf, int size); -int statsave_load(const OEMCHAR *filename); -int statsave_save_hdd(const OEMCHAR *ext); -int statsave_load_hdd(const OEMCHAR *ext); - -#if defined(__LIBRETRO__) -int statsave_save_d(const OEMCHAR *filename); -int statsave_load_d(const OEMCHAR *filename); -#else -int statsave_save_d(void); -int statsave_load_d(void); -#endif - -#ifdef __cplusplus -} -#endif +/** + * @file statsave.h + * @brief Interface of state save + */ + +#pragma once + +/** + * Result code + */ +enum +{ + STATFLAG_SUCCESS = 0, + STATFLAG_DISKCHG = 0x0001, + STATFLAG_VERCHG = 0x0002, + STATFLAG_WARNING = 0x0080, + STATFLAG_VERSION = 0x0100, + STATFLAG_FAILURE = -1 +}; + +struct TagStatFlagHandle; +typedef struct TagStatFlagHandle *STFLAGH; + +/** + * @brief The entry of state flag + */ +struct TagStatFlagEntry +{ + char index[12]; + UINT16 ver; + UINT16 type; + void *arg1; + UINT arg2; +}; +typedef struct TagStatFlagEntry SFENTRY; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern uint8_t g_u8ControlState; + +int statflag_read(STFLAGH sfh, void *ptr, UINT size); +int statflag_write(STFLAGH sfh, const void *ptr, UINT size); +void statflag_seterr(STFLAGH sfh, const OEMCHAR *str); + +int statsave_save(const OEMCHAR *filename); +int statsave_check(const OEMCHAR *filename, OEMCHAR *buf, int size); +int statsave_load(const OEMCHAR *filename); +int statsave_save_hdd(const OEMCHAR *ext); +int statsave_load_hdd(const OEMCHAR *ext); + +#if defined(__LIBRETRO__) +int statsave_save_d(const OEMCHAR *filename); +int statsave_load_d(const OEMCHAR *filename); +#else +int statsave_save_d(void); +int statsave_load_d(void); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/timing.c b/timing.c old mode 100755 new mode 100644 index 9cf7fcd9..bf4ccba2 --- a/timing.c +++ b/timing.c @@ -1,104 +1,104 @@ -#include -#include -#include -#include -#include - - -typedef struct { - UINT32 tick; - UINT32 msstep; - UINT cnt; - UINT32 fraction; -} TIMING; - -static TIMING timing; - -static UINT32 timimg_speed = 100; - -void timing_reset(void) { - - timing.tick = GETTICK(); - timing.cnt = 0; - timing.fraction = 0; -} - -void timing_setrate(UINT lines, UINT crthz) { - - timing.msstep = (crthz << (TIMING_MSSHIFT - 3)) / lines / (1000 >> 3); -} - -void timing_setcount(UINT value) { - - timing.cnt = value; -} - -void timing_setspeed(UINT32 value) -{ - timimg_speed = value; -} - -UINT32 timing_getmsstep(void) -{ - return(timing.msstep); -} - - -UINT timing_getcount(void) { - - UINT32 ticknow; - UINT32 span; - UINT32 fraction; - - ticknow = GETTICK(); - span = ticknow - timing.tick; - span = span * timimg_speed / 128; - if (span) { - timing.tick = ticknow; - fddmtr_callback(ticknow); - - if (span >= 1000) { - span = 1000; - } - fraction = timing.fraction + (span * timing.msstep); - timing.cnt += fraction >> TIMING_MSSHIFT; - timing.fraction = fraction & ((1 << TIMING_MSSHIFT) - 1); - } - return(timing.cnt); -} - -UINT timing_getcount_baseclock(void) { - - UINT32 ticknow; - UINT32 span; - UINT32 fraction; - UINT32 ret = 0; - - ticknow = GETTICK(); - span = ticknow - timing.tick; - span = span * timimg_speed / 128; - if (span) { - if (span >= 1000) { - span = 1000; - } - fraction = timing.fraction + (span * timing.msstep); - ret = timing.cnt + (fraction >> TIMING_MSSHIFT); - } - return(ret); -} - -UINT32 timing_getcount_raw(void) { - - UINT32 ticknow; - UINT32 span; - UINT32 fraction; - - ticknow = GETTICK(); - span = ticknow - timing.tick; - span = span * timimg_speed / 128; - if (span >= 1000) { - span = 1000; - } - fraction = timing.fraction + (span * timing.msstep); - return((timing.cnt << TIMING_MSSHIFT) + fraction); +#include +#include +#include +#include +#include + + +typedef struct { + UINT32 tick; + UINT32 msstep; + UINT cnt; + UINT32 fraction; +} TIMING; + +static TIMING timing; + +static UINT32 timimg_speed = 100; + +void timing_reset(void) { + + timing.tick = GETTICK(); + timing.cnt = 0; + timing.fraction = 0; +} + +void timing_setrate(UINT lines, UINT crthz) { + + timing.msstep = (crthz << (TIMING_MSSHIFT - 3)) / lines / (1000 >> 3); +} + +void timing_setcount(UINT value) { + + timing.cnt = value; +} + +void timing_setspeed(UINT32 value) +{ + timimg_speed = value; +} + +UINT32 timing_getmsstep(void) +{ + return(timing.msstep); +} + + +UINT timing_getcount(void) { + + UINT32 ticknow; + UINT32 span; + UINT32 fraction; + + ticknow = GETTICK(); + span = ticknow - timing.tick; + span = span * timimg_speed / 128; + if (span) { + timing.tick = ticknow; + fddmtr_callback(ticknow); + + if (span >= 1000) { + span = 1000; + } + fraction = timing.fraction + (span * timing.msstep); + timing.cnt += fraction >> TIMING_MSSHIFT; + timing.fraction = fraction & ((1 << TIMING_MSSHIFT) - 1); + } + return(timing.cnt); +} + +UINT timing_getcount_baseclock(void) { + + UINT32 ticknow; + UINT32 span; + UINT32 fraction; + UINT32 ret = 0; + + ticknow = GETTICK(); + span = ticknow - timing.tick; + span = span * timimg_speed / 128; + if (span) { + if (span >= 1000) { + span = 1000; + } + fraction = timing.fraction + (span * timing.msstep); + ret = timing.cnt + (fraction >> TIMING_MSSHIFT); + } + return(ret); +} + +UINT32 timing_getcount_raw(void) { + + UINT32 ticknow; + UINT32 span; + UINT32 fraction; + + ticknow = GETTICK(); + span = ticknow - timing.tick; + span = span * timimg_speed / 128; + if (span >= 1000) { + span = 1000; + } + fraction = timing.fraction + (span * timing.msstep); + return((timing.cnt << TIMING_MSSHIFT) + fraction); } \ No newline at end of file diff --git a/timing.h b/timing.h old mode 100755 new mode 100644 index 0efc9bd7..883217a0 --- a/timing.h +++ b/timing.h @@ -1,21 +1,21 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -#define TIMING_MSSHIFT 16 -#define TIMING_MSSHIFT_VALUE (1 << TIMING_MSSHIFT) -#define TIMING_MSSHIFT_MASK (TIMING_MSSHIFT_VALUE - 1) - -void timing_reset(void); -void timing_setrate(UINT lines, UINT crthz); -void timing_setcount(UINT value); -UINT32 timing_getmsstep(void); -UINT timing_getcount(void); -UINT timing_getcount_baseclock(void); -UINT32 timing_getcount_raw(void); -void timing_setspeed(UINT32 speed); - -#ifdef __cplusplus -} -#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define TIMING_MSSHIFT 16 +#define TIMING_MSSHIFT_VALUE (1 << TIMING_MSSHIFT) +#define TIMING_MSSHIFT_MASK (TIMING_MSSHIFT_VALUE - 1) + +void timing_reset(void); +void timing_setrate(UINT lines, UINT crthz); +void timing_setcount(UINT value); +UINT32 timing_getmsstep(void); +UINT timing_getcount(void); +UINT timing_getcount_baseclock(void); +UINT32 timing_getcount_raw(void); +void timing_setspeed(UINT32 speed); + +#ifdef __cplusplus +} +#endif diff --git a/trap/inttrap.c b/trap/inttrap.c old mode 100755 new mode 100644 index 5c80f49e..46229420 --- a/trap/inttrap.c +++ b/trap/inttrap.c @@ -1,286 +1,286 @@ -/** - * @file inttrap.c - * @brief Implementation of the trap of interrupt - */ - -#include - -#if defined(ENABLE_TRAP) -#include "inttrap.h" -#include - -void CPUCALL softinttrap(UINT cs, UINT32 eip, UINT vect) { - -// ---- ここにトラップ条件コードを書きます - if (vect == 0x7f) { - switch(CPU_AH) { - case 0: - TRACEOUT(("INT-7F AH=00 Load data DS:DX = %.4x:%.4x", CPU_DS, CPU_DX)); - break; - - case 1: - TRACEOUT(("INT-7F AH=01 Play data AL=%.2x", CPU_AL)); - break; - - case 2: - TRACEOUT(("INT-7F AH=02 Stop Data")); - break; - -// case 3: -// TRACEOUT(("INT-7F AH=03 Get Status")); -// break; - - case 4: - TRACEOUT(("INT-7F AH=04 Set Parameter AL=%.2x", CPU_AL)); - break; - } - } - return; - - if (vect == 0x50) { - if (CPU_AX != 9) - TRACEOUT(("%.4x:%.4x INT-50 AX=%.4x BX=%.4x DX=%.4x", cs, eip, CPU_AX, CPU_BX, CPU_DX)); - } - if (vect == 0x51) { - TRACEOUT(("%.4x:%.4x INT-51 AX=%.4x BX=%.4x DX=%.4x", cs, eip, CPU_AX, CPU_BX, CPU_DX)); - } - return; - -#if 0 -// if (vect == 0x2f) { -// TRACEOUT(("%.4x:%.4x INT-2F AX=%.4x", cs, eip, CPU_AX)); -// } - if (vect == 0x67) { - TRACEOUT(("%.4x:%.4x INT-67 AX=%.4x BX=%.4x DX=%.4x", cs, eip, CPU_AX, CPU_BX, CPU_DX)); - } -#endif -#if 0 - if ((vect == 0x42) && (CPU_AL != 6)) { - TRACEOUT(("%.4x:%.4x INT-42 AL=%.2x", cs, eip, CPU_AL)); - } -#endif -#if 0 - if (vect == 0x2f) { - TRACEOUT(("%.4x:%.4x INT-2f BX=%.4x/DX=%.4x", cs, eip, CPU_BX, CPU_DX)); - } -#endif -#if 0 - if (vect == 0xd2) { - TRACEOUT(("%.4x:%.4x INT-d2 AX=%.4x", cs, eip, CPU_AX)); - } -#endif -#if 0 - if (vect == 0x60) { - TRACEOUT(("%.4x:%.4x INT-60 AX=%.4x", cs, eip, CPU_AX)); - } -#endif -#if 0 - if (vect == 0xa0) { - TRACEOUT(("%.4x:%.4x INT-a0 AX=%.4x", cs, eip, CPU_AX)); - } - if (vect == 0xa2) { - TRACEOUT(("%.4x:%.4x INT-a2", cs, eip)); - } - if (vect == 0xa4) { - TRACEOUT(("%.4x:%.4x INT-a4", cs, eip)); - } -#endif -#if 0 - if (vect == 0x60) { - TRACEOUT(("%.4x:%.4x INT-60 AH=%.2x", cs, eip, CPU_AH)); - if (CPU_AH == 1) { - TRACEOUT(("->%.4x:%.4x", CPU_ES, CPU_BX)); - } - } -#endif -#if 0 - if (vect == 0x40) { - TRACEOUT(("%.4x:%.4x INT-40 AH=%.2x", cs, eip, CPU_AH)); - } - if (vect == 0x66) { - switch(CPU_AL) { - case 1: - TRACEOUT(("%.4x:%.4x INT-66:01 play", cs, eip)); - break; - case 2: - TRACEOUT(("%.4x:%.4x INT-66:02 stop", cs, eip)); - break; - case 9: - TRACEOUT(("%.4x:%.4x INT-66:09 setdata AH=%.2x ES:BX=%.4x:%.4x DX=%.4x", cs, eip, CPU_AH, CPU_ES, CPU_BX, CPU_DX)); - break; - case 0x0d: - TRACEOUT(("%.4x:%.4x INT-66:0d setdata ES:BX=%.4x:%.4x", cs, eip, CPU_ES, CPU_BX)); - break; - - default: - TRACEOUT(("%.4x:%.4x INT-66 AX=%.4x", cs, eip, CPU_AX)); - break; - } - } -#endif -#if 0 - if (vect == 0x40) { - TRACEOUT(("%.4x:%.4x INT-40 AX=%.4x DS=%.4x DI=%.4x", cs, eip, CPU_AX, CPU_DS, CPU_DI)); - } - if (vect == 0x41) { - TRACEOUT(("%.4x:%.4x INT-41 AX=%.4x DX=%.4x", cs, eip, CPU_AX, CPU_DX)); - } -#endif -#if 0 - if (vect == 0x41) { - TRACEOUT(("%.4x:%.4x INT-41 AX=%.4x %.4x:%.4x", - cs, eip, CPU_AX, CPU_DS, CPU_SI)); - } - if (vect == 0x42) { - switch(CPU_AH) { - case 0xd3: - case 0xd0: - break; - - case 0xfd: - case 0xfc: - case 0xfa: - case 0xf8: - case 0xe3: - TRACEOUT(("%.4x:%.4x INT-42 AX=%.4x %.4x:%.4x", - cs, eip, CPU_AX, CPU_BX, CPU_BP)); - break; - - default: - TRACEOUT(("%.4x:%.4x INT-42 AX=%.4x", cs, eip, CPU_AX)); - break; - } - } -#endif -#if 0 - if (vect == 0x40) { - TRACEOUT(("%.4x:%.4x INT-40 SI=%.4x %.4x:%.4x:%.4x", - cs, eip, CPU_SI, - MEMR_READ16(CPU_DS, CPU_SI + 0), - MEMR_READ16(CPU_DS, CPU_SI + 2), - MEMR_READ16(CPU_DS, CPU_SI + 4))); - } - if (vect == 0xd2) { - TRACEOUT(("%.4x:%.4x INT-D2 AX=%.4x", cs, eip, CPU_AX)); - } -#endif -#if 0 - if (vect == 0x40) { - TRACEOUT(("INT 40H - AL=%.2x", CPU_AL)); - } -#endif -#if 1 - if (vect == 0x21) { - char f[128]; - UINT i; - char c; - switch(CPU_AH) { - case 0x3d: - for (i=0; i<127; i++) { - c = MEMR_READ8(CPU_DS, CPU_DX + i); - if (c == '\0') break; - f[i] = c; - } - f[i] = 0; - TRACEOUT(("DOS: %.4x:%.4x Open Handle AL=%.2x DS:DX=%.4x:%.4x[%s]", cs, eip, CPU_AL, CPU_DS, CPU_DX, f)); - break; - - case 0x3f: - TRACEOUT(("DOS: %.4x:%.4x Read Handle BX=%.4x DS:DX=%.4x:%.4x CX=%.4x", cs, eip, CPU_BX, CPU_DS, CPU_DX, CPU_CX)); - break; - - case 0x42: - TRACEOUT(("DOS: %.4x:%.4x Move File Pointer BX=%.4x CX:DX=%.4x:%.4x AL=%.2x", cs, eip, CPU_BX, CPU_CX, CPU_DX, CPU_AL)); - break; - } - } -#endif -#if 0 - if (vect == 0xf5) { - TRACEOUT(("%.4x:%.4x INT-F5 AH=%.2x STACK=%.4x", cs, eip, - CPU_AH, MEMR_READ16(CPU_SS, CPU_SP + 2))); - } -#endif -#if 0 - if (vect == 0x69) { - TRACEOUT(("%.4x:%.4x INT-69 AX=%.4x", cs, eip, CPU_AX)); - } -#endif -#if 0 - if ((vect == 0x40) && (CPU_AX != 4)) { - TRACEOUT(("%.4x:%.4x INT-40 AX=%.4x", cs, eip, CPU_AX)); - } -#endif -#if 0 - if (vect == 0x7f) { - switch(CPU_AH) { - case 0: - TRACEOUT(("INT-7F AH=00 Load data DS:DX = %.4x:%.4x", CPU_DS, CPU_DX)); - break; - - case 1: - TRACEOUT(("INT-7F AH=01 Play data AL=%.2x", CPU_AL)); - break; - - case 2: - TRACEOUT(("INT-7F AH=02 Stop Data")); - break; - - case 3: - TRACEOUT(("INT-7F AH=03 Get Status")); - break; - - case 4: - TRACEOUT(("INT-7F AH=04 Set Parameter AL=%.2x", CPU_AL)); - break; - } - } -#endif -#if defined(TRACE) - if (vect == 0x7f) { - UINT i, j; - switch(CPU_AH) { - case 0: - TRACEOUT(("INT-7F AH=00 Load data DS:DX = %.4x:%.4x", CPU_DS, CPU_DX)); - for (i=0; i<16; i+=4) { - char buf[256]; - for (j=0; j<4; j++) { - sprintf(buf + (j * 6), "0x%.2x, ", - MEMR_READ8(CPU_DS, CPU_DX + i + j)); - } - TRACEOUT(("%s", buf)); - } - break; - - case 1: - TRACEOUT(("INT-7F AH=01 Play data AL=%.2x", CPU_AL)); - break; - - case 2: - TRACEOUT(("INT-7F AH=02 Stop Data")); - break; - - case 3: -// TRACEOUT(("INT-7F AH=03 Get Status")); - break; - - case 4: - TRACEOUT(("INT-7F AH=04 Set Parameter AL=%.2x", CPU_AL)); - break; - - default: - TRACEOUT(("INT-7F AH=%.2x", CPU_AH)); - break; - } - } -#endif -#if 0 // defined(TRACE) - if ((vect >= 0xa0) && (vect < 0xb0)) { -extern void lio_look(UINT vect); - lio_look(vect); - } -#endif -} - -#endif - +/** + * @file inttrap.c + * @brief Implementation of the trap of interrupt + */ + +#include + +#if defined(ENABLE_TRAP) +#include "inttrap.h" +#include + +void CPUCALL softinttrap(UINT cs, UINT32 eip, UINT vect) { + +// ---- ここにトラップ条件コードを書きます + if (vect == 0x7f) { + switch(CPU_AH) { + case 0: + TRACEOUT(("INT-7F AH=00 Load data DS:DX = %.4x:%.4x", CPU_DS, CPU_DX)); + break; + + case 1: + TRACEOUT(("INT-7F AH=01 Play data AL=%.2x", CPU_AL)); + break; + + case 2: + TRACEOUT(("INT-7F AH=02 Stop Data")); + break; + +// case 3: +// TRACEOUT(("INT-7F AH=03 Get Status")); +// break; + + case 4: + TRACEOUT(("INT-7F AH=04 Set Parameter AL=%.2x", CPU_AL)); + break; + } + } + return; + + if (vect == 0x50) { + if (CPU_AX != 9) + TRACEOUT(("%.4x:%.4x INT-50 AX=%.4x BX=%.4x DX=%.4x", cs, eip, CPU_AX, CPU_BX, CPU_DX)); + } + if (vect == 0x51) { + TRACEOUT(("%.4x:%.4x INT-51 AX=%.4x BX=%.4x DX=%.4x", cs, eip, CPU_AX, CPU_BX, CPU_DX)); + } + return; + +#if 0 +// if (vect == 0x2f) { +// TRACEOUT(("%.4x:%.4x INT-2F AX=%.4x", cs, eip, CPU_AX)); +// } + if (vect == 0x67) { + TRACEOUT(("%.4x:%.4x INT-67 AX=%.4x BX=%.4x DX=%.4x", cs, eip, CPU_AX, CPU_BX, CPU_DX)); + } +#endif +#if 0 + if ((vect == 0x42) && (CPU_AL != 6)) { + TRACEOUT(("%.4x:%.4x INT-42 AL=%.2x", cs, eip, CPU_AL)); + } +#endif +#if 0 + if (vect == 0x2f) { + TRACEOUT(("%.4x:%.4x INT-2f BX=%.4x/DX=%.4x", cs, eip, CPU_BX, CPU_DX)); + } +#endif +#if 0 + if (vect == 0xd2) { + TRACEOUT(("%.4x:%.4x INT-d2 AX=%.4x", cs, eip, CPU_AX)); + } +#endif +#if 0 + if (vect == 0x60) { + TRACEOUT(("%.4x:%.4x INT-60 AX=%.4x", cs, eip, CPU_AX)); + } +#endif +#if 0 + if (vect == 0xa0) { + TRACEOUT(("%.4x:%.4x INT-a0 AX=%.4x", cs, eip, CPU_AX)); + } + if (vect == 0xa2) { + TRACEOUT(("%.4x:%.4x INT-a2", cs, eip)); + } + if (vect == 0xa4) { + TRACEOUT(("%.4x:%.4x INT-a4", cs, eip)); + } +#endif +#if 0 + if (vect == 0x60) { + TRACEOUT(("%.4x:%.4x INT-60 AH=%.2x", cs, eip, CPU_AH)); + if (CPU_AH == 1) { + TRACEOUT(("->%.4x:%.4x", CPU_ES, CPU_BX)); + } + } +#endif +#if 0 + if (vect == 0x40) { + TRACEOUT(("%.4x:%.4x INT-40 AH=%.2x", cs, eip, CPU_AH)); + } + if (vect == 0x66) { + switch(CPU_AL) { + case 1: + TRACEOUT(("%.4x:%.4x INT-66:01 play", cs, eip)); + break; + case 2: + TRACEOUT(("%.4x:%.4x INT-66:02 stop", cs, eip)); + break; + case 9: + TRACEOUT(("%.4x:%.4x INT-66:09 setdata AH=%.2x ES:BX=%.4x:%.4x DX=%.4x", cs, eip, CPU_AH, CPU_ES, CPU_BX, CPU_DX)); + break; + case 0x0d: + TRACEOUT(("%.4x:%.4x INT-66:0d setdata ES:BX=%.4x:%.4x", cs, eip, CPU_ES, CPU_BX)); + break; + + default: + TRACEOUT(("%.4x:%.4x INT-66 AX=%.4x", cs, eip, CPU_AX)); + break; + } + } +#endif +#if 0 + if (vect == 0x40) { + TRACEOUT(("%.4x:%.4x INT-40 AX=%.4x DS=%.4x DI=%.4x", cs, eip, CPU_AX, CPU_DS, CPU_DI)); + } + if (vect == 0x41) { + TRACEOUT(("%.4x:%.4x INT-41 AX=%.4x DX=%.4x", cs, eip, CPU_AX, CPU_DX)); + } +#endif +#if 0 + if (vect == 0x41) { + TRACEOUT(("%.4x:%.4x INT-41 AX=%.4x %.4x:%.4x", + cs, eip, CPU_AX, CPU_DS, CPU_SI)); + } + if (vect == 0x42) { + switch(CPU_AH) { + case 0xd3: + case 0xd0: + break; + + case 0xfd: + case 0xfc: + case 0xfa: + case 0xf8: + case 0xe3: + TRACEOUT(("%.4x:%.4x INT-42 AX=%.4x %.4x:%.4x", + cs, eip, CPU_AX, CPU_BX, CPU_BP)); + break; + + default: + TRACEOUT(("%.4x:%.4x INT-42 AX=%.4x", cs, eip, CPU_AX)); + break; + } + } +#endif +#if 0 + if (vect == 0x40) { + TRACEOUT(("%.4x:%.4x INT-40 SI=%.4x %.4x:%.4x:%.4x", + cs, eip, CPU_SI, + MEMR_READ16(CPU_DS, CPU_SI + 0), + MEMR_READ16(CPU_DS, CPU_SI + 2), + MEMR_READ16(CPU_DS, CPU_SI + 4))); + } + if (vect == 0xd2) { + TRACEOUT(("%.4x:%.4x INT-D2 AX=%.4x", cs, eip, CPU_AX)); + } +#endif +#if 0 + if (vect == 0x40) { + TRACEOUT(("INT 40H - AL=%.2x", CPU_AL)); + } +#endif +#if 1 + if (vect == 0x21) { + char f[128]; + UINT i; + char c; + switch(CPU_AH) { + case 0x3d: + for (i=0; i<127; i++) { + c = MEMR_READ8(CPU_DS, CPU_DX + i); + if (c == '\0') break; + f[i] = c; + } + f[i] = 0; + TRACEOUT(("DOS: %.4x:%.4x Open Handle AL=%.2x DS:DX=%.4x:%.4x[%s]", cs, eip, CPU_AL, CPU_DS, CPU_DX, f)); + break; + + case 0x3f: + TRACEOUT(("DOS: %.4x:%.4x Read Handle BX=%.4x DS:DX=%.4x:%.4x CX=%.4x", cs, eip, CPU_BX, CPU_DS, CPU_DX, CPU_CX)); + break; + + case 0x42: + TRACEOUT(("DOS: %.4x:%.4x Move File Pointer BX=%.4x CX:DX=%.4x:%.4x AL=%.2x", cs, eip, CPU_BX, CPU_CX, CPU_DX, CPU_AL)); + break; + } + } +#endif +#if 0 + if (vect == 0xf5) { + TRACEOUT(("%.4x:%.4x INT-F5 AH=%.2x STACK=%.4x", cs, eip, + CPU_AH, MEMR_READ16(CPU_SS, CPU_SP + 2))); + } +#endif +#if 0 + if (vect == 0x69) { + TRACEOUT(("%.4x:%.4x INT-69 AX=%.4x", cs, eip, CPU_AX)); + } +#endif +#if 0 + if ((vect == 0x40) && (CPU_AX != 4)) { + TRACEOUT(("%.4x:%.4x INT-40 AX=%.4x", cs, eip, CPU_AX)); + } +#endif +#if 0 + if (vect == 0x7f) { + switch(CPU_AH) { + case 0: + TRACEOUT(("INT-7F AH=00 Load data DS:DX = %.4x:%.4x", CPU_DS, CPU_DX)); + break; + + case 1: + TRACEOUT(("INT-7F AH=01 Play data AL=%.2x", CPU_AL)); + break; + + case 2: + TRACEOUT(("INT-7F AH=02 Stop Data")); + break; + + case 3: + TRACEOUT(("INT-7F AH=03 Get Status")); + break; + + case 4: + TRACEOUT(("INT-7F AH=04 Set Parameter AL=%.2x", CPU_AL)); + break; + } + } +#endif +#if defined(TRACE) + if (vect == 0x7f) { + UINT i, j; + switch(CPU_AH) { + case 0: + TRACEOUT(("INT-7F AH=00 Load data DS:DX = %.4x:%.4x", CPU_DS, CPU_DX)); + for (i=0; i<16; i+=4) { + char buf[256]; + for (j=0; j<4; j++) { + sprintf(buf + (j * 6), "0x%.2x, ", + MEMR_READ8(CPU_DS, CPU_DX + i + j)); + } + TRACEOUT(("%s", buf)); + } + break; + + case 1: + TRACEOUT(("INT-7F AH=01 Play data AL=%.2x", CPU_AL)); + break; + + case 2: + TRACEOUT(("INT-7F AH=02 Stop Data")); + break; + + case 3: +// TRACEOUT(("INT-7F AH=03 Get Status")); + break; + + case 4: + TRACEOUT(("INT-7F AH=04 Set Parameter AL=%.2x", CPU_AL)); + break; + + default: + TRACEOUT(("INT-7F AH=%.2x", CPU_AH)); + break; + } + } +#endif +#if 0 // defined(TRACE) + if ((vect >= 0xa0) && (vect < 0xb0)) { +extern void lio_look(UINT vect); + lio_look(vect); + } +#endif +} + +#endif + diff --git a/trap/inttrap.h b/trap/inttrap.h old mode 100755 new mode 100644 index 189c1fe8..d921e5b4 --- a/trap/inttrap.h +++ b/trap/inttrap.h @@ -1,21 +1,21 @@ -/** - * @file inttrap.h - * @brief Interface of the trap of interrupt - */ - -#pragma once - -#if defined(ENABLE_TRAP) - -#ifdef __cplusplus -extern "C" { -#endif - -void CPUCALL softinttrap(UINT cs, UINT32 eip, UINT vect); - -#ifdef __cplusplus -} -#endif - -#endif - +/** + * @file inttrap.h + * @brief Interface of the trap of interrupt + */ + +#pragma once + +#if defined(ENABLE_TRAP) + +#ifdef __cplusplus +extern "C" { +#endif + +void CPUCALL softinttrap(UINT cs, UINT32 eip, UINT vect); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/trap/steptrap.c b/trap/steptrap.c old mode 100755 new mode 100644 index bdb6f632..f60665ae --- a/trap/steptrap.c +++ b/trap/steptrap.c @@ -1,238 +1,238 @@ -/** - * @file steptrap.c - * @brief Implementation of the step trap - */ - -#include - -#define IPTRACE (1 << 12) - -#if defined(ENABLE_TRAP) -#include "steptrap.h" -#include -#include -#include -#include -#include - - -#if IPTRACE -static UINT trpos = 0; -static UINT32 trcs[IPTRACE]; -static UINT32 treip[IPTRACE]; -#endif - -void CPUCALL steptrap(UINT cs, UINT32 eip) { - -// TRACEOUT(("%.4x:%.4x", cs, eip)); - -#if IPTRACE - trcs[trpos & (IPTRACE - 1)] = cs; - treip[trpos & (IPTRACE - 1)] = eip; - trpos++; -#endif - - -// ---- ここにトラップ条件コードを書きます -{ - static UINT32 x; - UINT32 tmp; - tmp = *(UINT32 *)(mem + 0x7ade1); - if (x != tmp) { - TRACEOUT(("%.4x:%.4x: %.8x -> %.8x", cs, eip, x, tmp)); - x = tmp; - } -} - - return; - - if ((cs == 0x1ea) && (eip == 0x0617)) { - TRACEOUT(("ES:BP+1 = %.2x", CPU_AL)); - } - return; - - if ((cs == 0x0601) && (eip == 0x025c)) { - TRACEOUT(("INT-D2 AX=%.4x BX=%.4x DX=%.4x", CPU_AX, CPU_BX, CPU_DX)); - } - return; - -// if (cs4231.intflag) TRACEOUT(("%.4x:%.4x", cs, eip)); - if (cs == 0x1311) TRACEOUT(("%.4x:%.4x", cs, eip)); - if (cs == 0x0d77) TRACEOUT(("%.4x:%.4x", cs, eip)); - if (cs == 0x0f5d) TRACEOUT(("%.4x:%.4x", cs, eip)); - if (cs == 0x0e91) TRACEOUT(("%.4x:%.4x", cs, eip)); - -#if 0 -{ - static UINT tmp = 0; - if (tmp != *(UINT16 *)(mem + 0xa0000 + 18 * 2)) { - TRACEOUT(("change text %.4x -> %.4x at %.4x:%.4x", tmp, *(UINT16 *)(mem + 0xa0000 + 18 * 2), cs, eip)); - tmp = *(UINT16 *)(mem + 0xa0000 + 18 * 2); - if (tmp == 0x4303) { - steptrap_hisfileout(); - } - } -} -#endif - - - // IDEテスト用 -#if 0 - if ((cs == 0x1300) && (eip == 0x1E97)) { - TRACEOUT(("-------- NECCD: function: %.2x", CPU_AL)); - } - if (cs == 0xdf6) TRACEOUT(("%.4x:%.4x", CPU_CS, CPU_IP)); -#endif -#if 1 - if ((cs == 0x0620) && (eip == 0x1E97)) { - TRACEOUT(("-------- NECCD: function: %.2x", CPU_AL)); - } -#endif - - return; - -#if 0 - if (cs == 0x05a0) { - if (eip == 0xe2) { - TRACEOUT(("result: %.2x", CPU_AH)); - } - } -#endif -#if 0 - if (cs == 0x0000) { - if (eip == 0x1191) { - char buf[10]; - int i; - for (i=0; i<6; i++) { - buf[i] = MEML_READ8(0x1000, CPU_BX + i); - } - buf[6] = '\0'; - TRACEOUT(("load: %s", buf)); - } - if (eip == 0x1265) { - TRACEOUT(("%.4x:%.4x addr=%.4x ret=%.4x", - cs, eip, CPU_DX, - MEML_READ16(CPU_SS, CPU_SP))); - } - } -#endif -#if 0 - if (cs == 0x0080) { - if (eip == 0x052A) { - UINT i; - UINT addr; - char fname[9]; - addr = MEML_READ16(CPU_SS, CPU_BP + 4); - for (i=0; i<8; i++) { - fname[i] = MEML_READ8(CPU_DS, addr + i); - } - fname[8] = 0; - TRACEOUT(("%.4x:%.4x play... addr:%.4x %s", - cs, eip, addr, fname)); - } - } -#endif -#if 0 - if (cs == 0x800) { - if (eip == 0x017A) { - TRACEOUT(("%.4x:%.4x solve... DS=%.4x SIZE=%.4x KEY=%.4x", - cs, eip, - MEML_READ16(CPU_SS, CPU_BP - 0x06), - CPU_DX, - MEML_READ16(CPU_SS, CPU_BP - 0x08))); - } - } -#endif -#if 0 - if (cs == 0x3d52) { - if (eip == 0x4A57) { - TRACEOUT(("%.4x:%.4x %.4x:%.4x/%.4x/%.4x", - CPU_DX, CPU_BX, CPU_DS, - MEML_READ16(CPU_SS, CPU_BP + 0x06), - MEML_READ16(CPU_SS, CPU_BP + 0x08), - MEML_READ16(CPU_SS, CPU_BP + 0x0a))); - } - if (eip == 0x4BF8) { - debugsub_memorydump(); - } -#if 0 - if (eip == 0x4B7A) { - TRACEOUT(("datum = %x", CPU_AX)); - } - if (eip == 0x4B87) { - TRACEOUT(("leng = %x", CPU_AX)); - } - if (eip == 0x4BD5) { - TRACEOUT(("%.4x:%.4x <- %.2x[%.4x]", - CPU_ES, CPU_BX, CPU_AL, CPU_DI)); - } -#endif - } -#endif -#if 0 // DC - if (cs == 0x1000) { - if (eip == 0x5924) { - TRACEOUT(("%.4x:%.4x -> %.4x:%.4x", cs, eip, - MEML_READ16(CPU_DS, 0x6846), - MEML_READ16(CPU_DS, 0x6848))); - } - } -#endif -#if 0 // 羅針盤 - if (cs == 0x60) { - if (eip == 0xADF9) { - TRACEOUT(("%.4x:%.4x -> %.4x:%.4x:%.4x", cs, eip, CPU_BX, CPU_SI, CPU_AX)); - } - else if (eip == 0xC7E1) { - TRACEOUT(("%.4x:%.4x -> %.4x:%.4x", cs, eip, CPU_ES, CPU_BX)); - } - } -#endif -#if 0 - if (cs == 0x60) { - if (eip == 0x8AC2) { - UINT pos = CPU_SI + (CPU_AX * 6); - TRACEOUT(("%.4x:%.4x -> %.4x:%.4x-%.4x:%.4x [%.2x %.2x %.2x %.2x %.2x %.2x]", cs, eip, CPU_SI, CPU_AX, CPU_DX, CPU_DI, - MEML_READ8(CPU_DS, pos+0), - MEML_READ8(CPU_DS, pos+1), - MEML_READ8(CPU_DS, pos+2), - MEML_READ8(CPU_DS, pos+3), - MEML_READ8(CPU_DS, pos+4), - MEML_READ8(CPU_DS, pos+5))); - } - } -#endif -} - - -#if IPTRACE -void steptrap_hisfileout(void) { - - UINT s; - FILEH fh; - UINT pos; - char buf[32]; - - s = trpos; - if (s > IPTRACE) { - s -= IPTRACE; - } - else { - s = 0; - } - fh = file_create_c(OEMTEXT("his.txt")); - while(s < trpos) { - pos = s & (IPTRACE - 1); - s++; - SPRINTF(buf, "%.4x:%.8x\r\n", trcs[pos], treip[pos]); - file_write(fh, buf, STRLEN(buf)); - } - file_close(fh); -} -#else -void steptrap_hisfileout(void) { -} -#endif - -#endif - +/** + * @file steptrap.c + * @brief Implementation of the step trap + */ + +#include + +#define IPTRACE (1 << 12) + +#if defined(ENABLE_TRAP) +#include "steptrap.h" +#include +#include +#include +#include +#include + + +#if IPTRACE +static UINT trpos = 0; +static UINT32 trcs[IPTRACE]; +static UINT32 treip[IPTRACE]; +#endif + +void CPUCALL steptrap(UINT cs, UINT32 eip) { + +// TRACEOUT(("%.4x:%.4x", cs, eip)); + +#if IPTRACE + trcs[trpos & (IPTRACE - 1)] = cs; + treip[trpos & (IPTRACE - 1)] = eip; + trpos++; +#endif + + +// ---- ここにトラップ条件コードを書きます +{ + static UINT32 x; + UINT32 tmp; + tmp = *(UINT32 *)(mem + 0x7ade1); + if (x != tmp) { + TRACEOUT(("%.4x:%.4x: %.8x -> %.8x", cs, eip, x, tmp)); + x = tmp; + } +} + + return; + + if ((cs == 0x1ea) && (eip == 0x0617)) { + TRACEOUT(("ES:BP+1 = %.2x", CPU_AL)); + } + return; + + if ((cs == 0x0601) && (eip == 0x025c)) { + TRACEOUT(("INT-D2 AX=%.4x BX=%.4x DX=%.4x", CPU_AX, CPU_BX, CPU_DX)); + } + return; + +// if (cs4231.intflag) TRACEOUT(("%.4x:%.4x", cs, eip)); + if (cs == 0x1311) TRACEOUT(("%.4x:%.4x", cs, eip)); + if (cs == 0x0d77) TRACEOUT(("%.4x:%.4x", cs, eip)); + if (cs == 0x0f5d) TRACEOUT(("%.4x:%.4x", cs, eip)); + if (cs == 0x0e91) TRACEOUT(("%.4x:%.4x", cs, eip)); + +#if 0 +{ + static UINT tmp = 0; + if (tmp != *(UINT16 *)(mem + 0xa0000 + 18 * 2)) { + TRACEOUT(("change text %.4x -> %.4x at %.4x:%.4x", tmp, *(UINT16 *)(mem + 0xa0000 + 18 * 2), cs, eip)); + tmp = *(UINT16 *)(mem + 0xa0000 + 18 * 2); + if (tmp == 0x4303) { + steptrap_hisfileout(); + } + } +} +#endif + + + // IDEテスト用 +#if 0 + if ((cs == 0x1300) && (eip == 0x1E97)) { + TRACEOUT(("-------- NECCD: function: %.2x", CPU_AL)); + } + if (cs == 0xdf6) TRACEOUT(("%.4x:%.4x", CPU_CS, CPU_IP)); +#endif +#if 1 + if ((cs == 0x0620) && (eip == 0x1E97)) { + TRACEOUT(("-------- NECCD: function: %.2x", CPU_AL)); + } +#endif + + return; + +#if 0 + if (cs == 0x05a0) { + if (eip == 0xe2) { + TRACEOUT(("result: %.2x", CPU_AH)); + } + } +#endif +#if 0 + if (cs == 0x0000) { + if (eip == 0x1191) { + char buf[10]; + int i; + for (i=0; i<6; i++) { + buf[i] = MEML_READ8(0x1000, CPU_BX + i); + } + buf[6] = '\0'; + TRACEOUT(("load: %s", buf)); + } + if (eip == 0x1265) { + TRACEOUT(("%.4x:%.4x addr=%.4x ret=%.4x", + cs, eip, CPU_DX, + MEML_READ16(CPU_SS, CPU_SP))); + } + } +#endif +#if 0 + if (cs == 0x0080) { + if (eip == 0x052A) { + UINT i; + UINT addr; + char fname[9]; + addr = MEML_READ16(CPU_SS, CPU_BP + 4); + for (i=0; i<8; i++) { + fname[i] = MEML_READ8(CPU_DS, addr + i); + } + fname[8] = 0; + TRACEOUT(("%.4x:%.4x play... addr:%.4x %s", + cs, eip, addr, fname)); + } + } +#endif +#if 0 + if (cs == 0x800) { + if (eip == 0x017A) { + TRACEOUT(("%.4x:%.4x solve... DS=%.4x SIZE=%.4x KEY=%.4x", + cs, eip, + MEML_READ16(CPU_SS, CPU_BP - 0x06), + CPU_DX, + MEML_READ16(CPU_SS, CPU_BP - 0x08))); + } + } +#endif +#if 0 + if (cs == 0x3d52) { + if (eip == 0x4A57) { + TRACEOUT(("%.4x:%.4x %.4x:%.4x/%.4x/%.4x", + CPU_DX, CPU_BX, CPU_DS, + MEML_READ16(CPU_SS, CPU_BP + 0x06), + MEML_READ16(CPU_SS, CPU_BP + 0x08), + MEML_READ16(CPU_SS, CPU_BP + 0x0a))); + } + if (eip == 0x4BF8) { + debugsub_memorydump(); + } +#if 0 + if (eip == 0x4B7A) { + TRACEOUT(("datum = %x", CPU_AX)); + } + if (eip == 0x4B87) { + TRACEOUT(("leng = %x", CPU_AX)); + } + if (eip == 0x4BD5) { + TRACEOUT(("%.4x:%.4x <- %.2x[%.4x]", + CPU_ES, CPU_BX, CPU_AL, CPU_DI)); + } +#endif + } +#endif +#if 0 // DC + if (cs == 0x1000) { + if (eip == 0x5924) { + TRACEOUT(("%.4x:%.4x -> %.4x:%.4x", cs, eip, + MEML_READ16(CPU_DS, 0x6846), + MEML_READ16(CPU_DS, 0x6848))); + } + } +#endif +#if 0 // 羅針盤 + if (cs == 0x60) { + if (eip == 0xADF9) { + TRACEOUT(("%.4x:%.4x -> %.4x:%.4x:%.4x", cs, eip, CPU_BX, CPU_SI, CPU_AX)); + } + else if (eip == 0xC7E1) { + TRACEOUT(("%.4x:%.4x -> %.4x:%.4x", cs, eip, CPU_ES, CPU_BX)); + } + } +#endif +#if 0 + if (cs == 0x60) { + if (eip == 0x8AC2) { + UINT pos = CPU_SI + (CPU_AX * 6); + TRACEOUT(("%.4x:%.4x -> %.4x:%.4x-%.4x:%.4x [%.2x %.2x %.2x %.2x %.2x %.2x]", cs, eip, CPU_SI, CPU_AX, CPU_DX, CPU_DI, + MEML_READ8(CPU_DS, pos+0), + MEML_READ8(CPU_DS, pos+1), + MEML_READ8(CPU_DS, pos+2), + MEML_READ8(CPU_DS, pos+3), + MEML_READ8(CPU_DS, pos+4), + MEML_READ8(CPU_DS, pos+5))); + } + } +#endif +} + + +#if IPTRACE +void steptrap_hisfileout(void) { + + UINT s; + FILEH fh; + UINT pos; + char buf[32]; + + s = trpos; + if (s > IPTRACE) { + s -= IPTRACE; + } + else { + s = 0; + } + fh = file_create_c(OEMTEXT("his.txt")); + while(s < trpos) { + pos = s & (IPTRACE - 1); + s++; + SPRINTF(buf, "%.4x:%.8x\r\n", trcs[pos], treip[pos]); + file_write(fh, buf, STRLEN(buf)); + } + file_close(fh); +} +#else +void steptrap_hisfileout(void) { +} +#endif + +#endif + diff --git a/trap/steptrap.h b/trap/steptrap.h old mode 100755 new mode 100644 index 384a6883..16d276b9 --- a/trap/steptrap.h +++ b/trap/steptrap.h @@ -1,22 +1,22 @@ -/** - * @file steptrap.h - * @brief Interface of the step trap - */ - -#pragma once - -#if defined(ENABLE_TRAP) - -#ifdef __cplusplus -extern "C" { -#endif - -void steptrap_hisfileout(void); - -void CPUCALL steptrap(UINT cs, UINT32 eip); - -#ifdef __cplusplus -} -#endif - -#endif +/** + * @file steptrap.h + * @brief Interface of the step trap + */ + +#pragma once + +#if defined(ENABLE_TRAP) + +#ifdef __cplusplus +extern "C" { +#endif + +void steptrap_hisfileout(void); + +void CPUCALL steptrap(UINT cs, UINT32 eip); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/update.txt b/update.txt old mode 100755 new mode 100644 index aecc3509..8db77839 --- a/update.txt +++ b/update.txt @@ -1,784 +1,784 @@ - -// ---- info - - TRACE版(i286_step())で シングルステップ割り込みが割り込み続けるとか - mov SS直後に割り込みが発生するとか不都合があります。 - これについては、直す気力があれば(286コードを追っかける時だけだし…) - - - CHARSET_OEMについて -  要は毎回Shift-JISに変換せずに OS依存の文字コードで処理しようとする… -  まだ機能しません。定義しないで下さい。 - -  OEMCHAR (現状char固定、将来として UCS2でUINT16、UCS4でUINT32) -  OEMTEXTの追加 -  コンパイルが通るかご確認下さい。 - -  ステップ.1 (WinCE,X11) -   OEMコードと SJIS(EMBED/hostdrv)の変換調整 -   (FONTMNGは SJISのままで EMBEDで変換) - -   つか…X11版のDOSIO file_catname,file_cmpnameの入力が sjisになってる… -   (NP2はファイル名は OSLANGに従う…筈… -   と思ったら hostdrvで SJISのまま食わせてる?(汗 - -   EUCの2バイトコード判定が (((c - 0xa1) & 0xff) < 0x5d)で -   半角カナ(0x8e)の判定で狂う -   (c & 0x80)のほうが良い? - -   現状の… - -   ・codecnv.hのインクルードは compiler.hに移動 - -   ・#if defined(OSLANG_EUC) -     codecnv_sjis2euc(tmp, NELEMENTS(tmp), src, (UINT)-1); -     file_catname(path, tmp, NELEMENTS(path)); -    #elif defined(OSLANG_UTF8) -     oemtext_sjis2oem(tmp, NELEMENTS(tmp), src, (UINT)-1); -     file_catname(path, tmp, NELEMENTS(path)); -    #else -     file_catname(path, src, NELEMENTS(path)); -    #endif - -    を - -    #define oemtext_sjis2oem codecnv_sjis2euc -    #define oemtext_oemsjis2 codecnv_euc2sjis - -    としておいて - -    #if defined(OSLANG_ANK) || defined(OSLANG_SJIS) -     file_catname(path, src, NELEMENTS(path)); -    #else -     oemtext_sjis2oem(tmp, NELEMENTS(tmp), src, (UINT)-1); -     file_catname(path, tmp, NELEMENTS(path)); -    #endif - -    とする? - -   メモ: http://euc.jp/i18n/charcode.ja.html - -  ステップ.2 (WinNT,MacOSX) -   OEMCHARのUCS2対応 - -  ステップ.3 (MacOSX) -   ANSI PageCodeと Macintosh PageCodeの調整 -   メモ: http://homepage1.nifty.com/nomenclator/unicode/normalization.htm - -  ステップ.4 (WinNT,WinCE,MacOSX,X11) -   フォント関数回りを SJISからOEMコードに移行 - - -// ---- - - ver0.84 → ver0.85 - - (X11) -  ・環境によってサウンドの設定を変更した後にリセットするとプログラムが -   クラッシュする不具合を修正 -  ・SDL 2.0 サポート追加 -   configure では SDL 2.0 → SDL 1.2 の順番でライブラリを検索するので -   SDL 1.2 を明示的に使用したい場合には configure のオプションに -   --disable-sdl2 を指定する必要がある -  ・SDL audio のバックエンドとして PulseAudio を使用している場合に音が正常に -   鳴らない不具合を修正 -  ・USB 接続外部 FM 音源サポート追加。C86BOX を使用するには libusb 1.0 が必要 -   SPFM Light + RE:birth RE1-YM2608、C86BOX + PC-9801-86 で動作確認済み - - -// ---- - - ver0.83 → ver0.84 - ・i386c - 色々と変更 - ・i386c - rcl, rcr 命令の不具合を修正 - ・i386c - 命令実行中に例外が発生した際にスタックポインタがずれてしまう不具合 -   を修正 - ・i386c - 割込みゲート、トラップゲートで不正なエラーコードが設定されてしまう -   不具合を修正 - ・i386c - セグメント有効範囲チェックの不具合を修正 - ・i386c - enter, leave, call, pusha, popa 命令でリアルモード時でもスタック -   サイズチェックで例外が発生してしまう不具合を修正 - ・i386c - セグメントレジスタ設定時の不具合を修正 - ・i386c - タスクゲート処理時のエラーコードプッシュ処理の不具合を修正 - ・i386c - iret 命令で仮想86モードに復帰する際にスタック上の値によっては例外が -   発生してしまう不具合を修正 - ・i386c - ゲートを通じて別コードセグメント移行時に使用するオペランドサイズに -   ゲートタイプではなくスタックセグメントを使用していた不具合を修正 - ・BIOS - 1F90h A20有効後に戻していない不具合を修正 - ・BIOS - 1Bh メモリアクセスを修正 - - (Win32) -  ・NASM 2.09を使用するように修正 -  ・UNICODE版(np2nt.exe) で hostdrv が利用できないバグを修正 -  ・G.I.M.I.C、C86BOX、RE:birth に対応 - - (X11) -  ・STATSAVE 用のメニューを作成 -  ・レジューム/STATSAVE のファイル名を変更 -   - レジューム: ${HOME}/.np2/sav/sav → ${HOME}/.np2/sav/np2.sav -   - STATSAVE : ${HOME}/.np2/sav/s00 → ${HOME}/.np2/sav/np2.s00 -  ・フォントパスに設定ファイル名が含まれてしまう不具合を修正 -  ・エミュレーションウィンドウサイズ変更用のメニューを作成 -  ・GLIB, GTK+ の deprecated なインタフェースを使用しない様に修正 -  ・CPU 使用率を軽減する様に修正 -  ・コンフィグ画面からサウンドドライバを変更出切る様に修正 -  ・環境によってサウンドを有効にした場合にプログラムがクラッシュする -   不具合を修正 -  ・ビルド、インストールに Autotools(configure) を使用するように修正 -  ・ファイル保存時に既に同名ファイルが存在した場合、上書き確認ダイアログを -   表示するように修正 (GTK+-2.8 以降のみ有効) -  ・F12 キー機能割り当てに Help キーを追加 -  ・ファイルダイアログの floppy disk image Files にて拡張子が flp のファイル -   を表示する様に修正 -  ・Screen Option の LCD のチェックを外しても外れない不具合を修正 -  ・FDD シーク音が鳴らない不具合を修正 -  ・色深度が 8bpp の場合に配列の範囲外にアクセスしていた不具合を修正 -  ・F11 キーにフルスクリーン表示切り替え、フルスクリーン時のメニュー表示 -   切り替え機能を割り当て - - - (MacOSX) -  ・新規対応 - - (iOS) -  ・新規対応 - - -// ---- - - ver0.82 → ver0.83 - - (X11) -  ・ファイルダイアログにて拡張子が大文字のディスク・イメージを認識する様に修正 -  ・ファイルダイアログの IDE disk image Files にて拡張子が .hdi .tfd の -   ファイルを表示する様に修正 - - -// ---- - - ver0.81a → ver0.82 - ・MPU-PC98II - モード切替時のMIDIリセットを修正 - ・VERMOUTH - ver1.15版に差し替え - - (Win9x) -  ・モジュール判定不具合修正 - - (X11) -  ・PC9801-26K の I/O ポートが設定できなかった不具合を修正 -  ・フルスクリーンモードサポート -  ・F11 キーに機能割り当て -   - フルスクリーンモードトグル -   - フルスクリーン時のメニュー表示トグル - - -// ---- - - ver0.81 → ver0.81a - ・80286 (ARM版) - 割り込みハンドラを修正 - ・MOUSE - ボタンフラグの修正 - ・PIT - シリアルカウンタの修正 - ・HOSTDRV - 拡張子を消去する不都合を修正 (ver0.81エンバグ) - ・BIOS - FDCスイッチ/シグナルの修正 - - - - ver0.80 → ver0.81 - ・80286 (x86版) - rep ins, 2バイトmov8命令の不都合修正 - ・80286 (x86版) - クロック修正 (enter) - ・80286 (C版) - クロック修正 (cmp, jcc, test, enter) - ・80286 (ARM版) - pop ss命令の修正 - ・80286 (ARM版) - クロック修正 (cmp, jcc, test, enter) - ・80286 (C版) - rep outsw命令を修正 - ・MPU-PC98II - conductor修正 - ・MPU-PC98II - Request PC/Tempo コマンドの追加 - ・DMA - セルフイニシャライズを追加 - ・GDC - ソフトリセット時のフラグ修正 - ・GRCG - ソフトリセット時のフラグ修正 - ・PIT - シリアルカウンタの修正 - ・MOUSE - 割り込み修正 - ・ATRIC - 時間巻き戻りバグ修正 - ・SOUND - アドレスバスの修正 - ・WSS - データ転送サイズの修正 - ・BIOS - 1842h スクリーンモードを破壊する不都合修正 (ver0.75エンバグ) - ・BIOS - CRTBIOSフラグ修正 (PC-9821モード) - ・BIOS - FDDアクセス時にstatsaveを行なうと復帰できなくなる不都合修正 - ・一部(というか大部分…)のキーボードのmake/break関係を修正 - - ・メモリを修正(C版コア) - ・16MB以上のメモリをサポート(IA32) - - ・内部変更 -  たぶん -   #define OEMTEXT(string) (string) -  を -   #define OEMTEXT(string) string -  にする必要がある。 - -  CPUフォルダの DMA EGC等がほぼ同様のコードなので memフォルダへ移動し -  共通にしました。 - -  embedのShift-JISを ネイティブコードにしました。 -  文字コードがEUCの環境では SUPPORT_SJISは不要になります。 -  また、fontmng_getsize, fontmng_getdrawsizeの引き数の文字コードが -  SJISからEUCへ変更になっています。 - -  codecnvとucscnvを /codecnv へ移動しました。 - -  pccore.cとかにあるデバグコードがウザイので trapフォルダへ移動。 -  ENABLE_TRAPが定義されてなければ見る必要はありません。 - - -// ---- - - ver0.79 → ver0.80 - ・BIOS - スクロールコマンド修正 - ・BIOS - システムポートの修正(i286/V30ではほぼ無意味) - ・GDC - ステップフラグの反映 - ・FDC - レディ信号を修正 - ・i286x - div命令 (i286モード側) - ・i286c - div命令 (V30モード側) - - - (X11) -  ・ジョイスティックサポート -   サウンドドライバに SDL を使用している時にのみ使用可 -  ・screen depth == 24bpp の時にキーディスプレイ、ソフトウェアキーボードの -   描画がおかしい不具合を修正 -  ・T98-Next(.NHD)形式、Anex(.HDI)形式ハードディスクイメージ作成サポート - -(MacOSX) -  ・日本語リソース追加 -  ・ソフトウェアキーボードを有効にした - - -// ---- - - ver0.78 → ver0.79 - ・CGROM - JIS83罫線の不都合修正 - ・CGROM - 2バイト半角アクセス修正 - ・86PCM - バッファリングの不都合を修正 - ・BEEP - BEEP PCMの修正 - ・BIOS - 2Dタイプのシリンダ倍移動を修正 - ・BIOS - FDD割り込みフラグを修正 - ・AMD98 - レジスタリードの追加 - ・VRAM - スキップライン描画の修正 - ・BMPSave - スキップライン有効時のセーブ不都合を修正 - - (Win9x) -  ・ソフトウェアキーボードを有効にした - - (MacOSX) -  ・カレンダーに対応 - - - ・内部変更 - -   char *file_getext(const char *path); -   char *file_getname(const char *path); -   (constが付きます) - -   記念に gif保存に対応してみたり -    vram/scrnbmp.c の代わりに vram/scrnsave.c をリンクして - -     SCRNSAVE ss = scrnsave_get(); -     scrnsave_writegif(ss, "out.gif", SCRNSAVE_AUTO); -    scrnsave_trash(ss); - -     bmpなら scrnsave_writebmp(ss, "out.bmp", SCRNSAVE_AUTO); - -     np21のVGA時に 257色以上になるのに注意 -     (ss->type == SCRNSAVE_24BITの時にgif保存出来ません) - - -// ---- - - ver0.77 → ver0.78 - ・PIC - スレーヴのマスクの修正 - ・CGROM - JIS83罫線の不都合修正 - ・TEXTRAM - JIS83罫線の不都合修正 - ・86PCM - 割り込みステータスの修正 - ・BIOS - ブート時にメモリを完全に消去するようにした -      ※ RanceII対策、他のホットスタートで不都合が出るかも - ・BIOS - 直線描画のアルゴリズム修正 - ・BIOS - 円の半径が異常だった不都合の修正 - ・BIOS - JIS83罫線の不都合修正 - ・LIO - 内部塗り潰し指定付きBOX描画の対応 - ・LIO - 半角ひらがなの対応 - ・LIO - 円の仮サポート - - (X11) -  ・ソフトウェアキーボードサポート - - ・内部変更 - -   追加ファイル -    /lio/gcircle.c - - - -// ---- - - ver0.76 → ver0.77 - ・BIOS - FDC BIOSの修正 - ・FDD - ディスクシーク音再生中にリセットを行なうと 以降ディスクアクセスが行なえなくなる不都合を修正。 - - (X11) -  ・i386 アーキテクチャ以外でコンパイルできない不具合を修正 - - - -// ---- - - ver0.74 → ver0.76 (branch...) - ・DMA - バンク・アドレスマスクの修正 - ・PIC - スペシャルマスクモードの対応 - ・PIT - マルチプルラッチコマンドのサポート(uPD71054) - ・CGROM - 2バイト半角の処理を修正 - ・CGWINDOW - ワードアクセスの挙動修正 (MacOS9/MacOSX/x11/SDL) - ・MOUSE - uPD8255のコマンドレジスタの修正 - ・86PCM - 停止時にもかかわらずバッファを進めてしまう不都合を修正 - ・CS4231 - PIOサポート - ・BIOS - ベクタ08/1A/1Fの修正 - ・BIOS - リセット時の挙動の修正 - - (Windows9x) -  ・ATマシンの場合に PageUp/PageDownを反転 - - - ・内部変更 -   基本的にファイルが存在しなければプロジェクトから除外、 -   リンクエラーが出たらgrepしてファイル追加 - -    追加ファイル -     /bios/bios1f.c -     /bios/biosfd80.res -     /cbus/ideio.h -     /cbus/ideio.c (SUPPORT_IDEIO定義時) -     /cbus/atapicmd.h -     /cbus/atapicmd.c (SUPPORT_IDEIO定義時) -     /cbus/idebios.res -     /io/pcidev.h -     /io/pcidev.c (SUPPORT_PC9821定義時) - - -    削除ファイル -     /bios/bios02.c -     /bios/bios08.c -     /bios/biosboot.res -     /common/pf_key.tbl -     /sound/wavemix.h -     /sound/wavemix.c -     /sound/rhythmg.c -     /lio/gview.c -     /lio/gcolor1.c -     /lio/gcolor2.c -     /lio/gcls.c - - -   ROMIMAGEは MASMからNASMへ移行中でつ。 - -   SUPPORT_IDEIOは定義しないで下さい(まだマトモに動きません) - -   IA32でもハードウェアEMSを有効にしてみるテスト。 - - - -// ---- - - ver0.74 → ver0.75 - - ・GDC - ベクタの初期化し忘れを修正 - ・GDC - パターンの修正 - ・ITF/BIOS - リセット時の挙動の修正 - ・BIOS - 1842h モノクロフラグを修正 - ・EGCの高速化(?) - ・リズムの修正(PCM 44khz 16bit monoralの制限を外した) - ・LIOの修正 - - - (Windows) -  ・(I286X) EGCバイトアクセス修正 -  ・(I286X) ストリング命令修正 -  ・フロッピードライブ接続状態指定 - - (MacOS9) -  ・フロッピードライブ接続状態指定 -  ・MPU-PC98IIの設定ダイアログ - - (WinCE) -  ・(I286A) メモリの修正 -  ・GDC - GDCクロック 1.79MHzのサポート - - (X11) -  ・Configure Dialog にてアーキテクチャの指定を追加 - - (MacOSX) -  ・フロッピードライブ接続状態指定(FDD1、FDD2のみ) -  ・設定ダイアログのディップスイッチ画像表示 -  ・CoreMID経由のMIDI演奏に対応 -  ・MPU-PC98IIの設定ダイアログ拡充 -  ・Key Display対応(マウスクリックでFMとMIDIが切り替わります) - - - ・200ラインモードについて (正式サポート / #define SUPPORT_CRT15KHZ) -  PC-9801シリーズ(FELLOW、PC-9821、ハイレゾ機を除く)に搭載されている -  200ラインモードは設定ファイルのDIPswtchにて設定可能となります。 - -   400ラインモード -    DIPswtch=3e ?? ?? - -   200ラインモード -    DIPswtch=3f ?? ?? - -  本機能は DIPSW1-1に相当する機能であり、PC-9801VM以降のマシンで -  一般に言われている200ラインモードとは異なる機能です。 - -  ※PC-98シリーズの一般的な200ラインモードは、640x200を縦に2倍拡大し -   400ラインモードで動作しています。 - -  本機能は DIPSW1-1の切り替え機能を削除した FELLOW、PC-9821、ハイレゾ機の -  BIOS.ROMを使用時には正常に動作致しません。 -  これを理由に、本機能は NP2上で設定スイッチを設けません。 - -  また、レジューム動作時に DIPswtchの値を変更した場合、正常に -  スクリーンモードを変更できなくなります。 -  (PC-98動作中にディップスイッチを変更した時と同じ状態になります。) -  必ずリセットして下さい。 - - - - ・キー設定について -  bios.romとかと同じフォルダに key.txtというファイル名のテキストファイルを -  作成して、キー設定を記入して下さい。 - -  書式) -   [keyname] = [key1] (key2) (key3) -   [keyname] [TAB] [key1] (key2) (key3) -   userkey[1-2] = [key1] (key2) (key3) ... (key15) -    フルキー 0〜9 A〜Z - ^ \ @ [ ] ; : , . / _ -     STOP COPY ESC TAB BS RET SPC XFER NFER - INS DEL RLUP RLDN HMCL HELP -    ファンク F1〜F10 VF1〜VF5 -    テンキー [0]〜[9] [-] [/] [*] [+] [=] [,] [.] -    シフト SHIFT CAPS KANA GRPH CTRL - -   通常キーは3個、userkeyは15個の同時押し設定が可能です。 -   [=] キーは = で区切られてしまうので TABで区切るか [EQU]として下さい。 - -   例: -    W = UP (ダイアモンドキーをカーソルにしてみたり…) -    S = LEFT -    D = RIGHT -    X = DOWN -    [7] = [4] [8] (テンキー斜め同時押しにしてみたり…) -    [9] = [6] [8] -    [1] = [4] [2] -    [3] = [6] [2] -    userkey1 = CTRL XFER (CTRL+XFER FEP切り替え) -    userkey2 = D O A Z (D+O+A+Z 同時押し) - - - - ・内部変更 -   win9x/unasmをgenericへ移動(+P6,FPU命令をサポート) - -   np2infoをgenericへ移動 -    エスケープ文字を !KEY から %KEY%へ変更 -    ex == NULLで OS指定の改行コードになる筈 -    (MacOSXは np2info.cppがそのまんま移動になるかと思われ - -   io/serial.*に存在した keystat系を /keystat.* へ移動 -    keystat.cをリンク、 keystat.hをインクルード - -   SUPPORT_WAVEMIX廃止 -    → SUPPORT_SWSEEKSNDに変更 -    ハードウェアで対応してる場合には 一応 SUPPORT_HWSEEKSNDと定義して -    くれると嬉すぃ - -  ・keystat_initialize(keystat_reset)をコールして初期化すること… - - -// ---- - - ver0.73 → ver0.74 - - ・I/OレベルでのSASIに対応(INT3/DMA#0/BIOS:d0000-d0fff) - ・SCSI HDDに対応 - ・np2qn形式 HOSTDRVに対応 - ・拡張メモリの修正 (80286) - ・VRAM - 通常ディスプレイ時にメモリを破壊するバグを修正 - ・GDC - GDCクロック 1.79MHzのサポート - ・GDC - 走査周波数を可変にした - ・GDC - マスクが左右反転していたのを修正 - ・GDC - テキスト処理を修正(uPD7220A? cmd:05) - ・GDC - VECTEコマンド(R)を修正 (undocumented Tを追加) - ・GDC - TEXTEコマンド(SL/T)を修正 (undocumented L/C/Rを追加) - ・GDC - GRCG/EGC動作中の挙動を修正 - ・EGC - マスクフラグを修正 - ・FDC - DMAとステータスを修正 - ・SERIAL - キーボードステータスの修正 - ・uPD4990 - ホールド時の出力が不定になっていたのを修正 - ・RHYTHM - レジュームが反映されなかった不都合を修正 - ・ADPCM - サンプルリードがMSB/LSB逆転していたのを修正 - ・BIOS - ブート時にディップスイッチで指定した画面モードを反映 - ・BIOS - 1840h/1841h/1842h/1847hの結果をワークメモリへ反映するようにした - ・BIOS - 1847h マスクを左右反転させていなかったのを修正 - ・BIOS - 1848h/1849h/184ahをサポート - ・ITF - PC-9801VM/PC-286時に BEEPが初期化されない不都合を修正 - ・ITF - SSP終了時にハードウェアリセットをかけるように修正 - ・IDE - ディップスイッチ内容(SW2-6)を反映するように修正 - - - (Windows) -  ・(I286X) sidt命令の修正 -  ・(I286X) テキストRAMアクセスの修正 -  ・(I286X) 割り込みの修正 -  ・(I286X) EGCシフタを修正 -  ・Aboutダイアログの修正 -  ・ろみおとか… - - (MacOS9) -  ・テンキーの [+] [/] の修正 -  ・file_attr()で FILEATTR_READONLY を返すように… - - (MacOSX) -  ・テンキーの [+] [/] の修正 -  ・file_attr()で FILEATTR_READONLY を返すように… -  ・ツールウィンドウ修正 -  ・FDIイメージ対応(仕事早いよー>ゆいさん) -  ・フルスクリーン修正(たぶん・・) -  ・マウスドラッグに対応(タコミス・汗) - - - ・Userkeyについて -  userkey1, userkey2は、cfgを書換えることによりキーを自由に変更することが -  出来ます。 -  書式) -   userkey1 = [key1] (key2) (key3)... -    フルキー 0〜9 A〜Z - ^ \ @ [ ] ; : , . / _ -     STOP COPY ESC TAB BS RET SPC XFER NFER - INS DEL RLUP RLDN HMCL HELP -    ファンク F1〜F10 VF1〜VF5 -    テンキー [0]〜[9] [-] [/] [*] [+] [=] [,] [.] -    シフト SHIFT CAPS KANA GRPH CTRL - -   例: -    userkey1 = CTRL XFER (CTRL+XFER FEP切り替え用) -    userkey2 = D O A Z (D+O+A+Z 同時押し) - -  本機能は 簡易的な実装であり ver0.75で変更されます。 -  また、ver0.74ではシフト系は不整合が発生する可能性があります。 - - - - ・内部変更 -   pccore.h の中で statsave.hをインクルード -    → #include をトル - -   io/extmem を io/emsioに変更 -   (IA32は emsioは要らないが、NEC EMSバンク形式で必要になるかも) - -   np2cfg.hddfile[2] -> np2cfg.sasihdd[2] - -   void diskdrv_sethdd(REG8 drv, const char *fname); -    drv = BIOSのデバイス番号 -     0x00〜0x01 SASI #0-1 -     0x20〜0x23 SCSI #0-3 (SUPPORT_SCSIを定義した時のみ) - -   bios/sxsibios.c はリンク必須 -   cbus/sasiio.c - SUPPORT_SCSIを定義した時にリンク -   cbus/scsiio.c cbus/scsicmd.c - SUPPORT_SCSIを定義した時にリンク - -   IA32でハードウェアEMSを禁止しました。 -     → #define CPU_SETEXTSIZE() init_mem() に変更 (済) -     → memory.cの EMM部分をトル (済) -     → cpumem extmem_size を CPU_EXTMEM, CPU_EXTMEMSIZEに変更(済) -     → protectmem_sizeをトル (済) - -   しかし emm386.exeが使えないから ハードウェアEMSを有効にした -   ほーがいいかな? 辻褄は合いそうだし。 -   386以降に乗っかってる NEC EMSバンク方式だと あまりにアホだし。 - -   dosio.hの FTYPEを common.hへ移動。 -   こそーり fdiを読めるよーにしてみたり。 - -   フロッピードライブについて np2cfg.fddequipを見に行くようにしました -   デフォルトで2基 -   np2cfg.fddequip = 0x03 (ドライブ1 = ビット0 〜 ドライブ4 = ビット3) -   (実際に動作中の装備状態は fdc.equipで リセット時に更新されます) -   必要によって main()で変える、cfgに書き出す等してください。 - -   S98について SUPPORT_S98定義時のみリンクするようにしました。 -   (Win9x, MacOSX, x11(USE_GTK)) - -   PC9861Kについて SUPPORT_PC9861K定義時のみリンクするようにしました。 -   (シリアル通信に対応していなければ無意味な機能です) - -   userkey -    ini.cで profile_setkeys, profile_getkeysで np2cfg.userkeyを更新 -    キーボードのどこかにキーに キーコード 0x76,0x77を追加 - - - メモ -  実機で FDでVRAMクリアされるのは何故? - - -// ---- - - ver0.72 → ver0.73 - - ・主にRISC向けの最適化、その2 - ・EPSON PCシリーズのアーキテクチャをサポート - ・ARM版CPUコアのサポート - ・CPU(I286C) … シングルステップ割り込みの修正 - ・CPU(I286C) … int3 / int imm8 / into クロック数を修正 - ・CPU(I286C) … shl r/m8,cl / shr r/m8,cl の修正 - ・CPU(I286C) … sar r/m (eVC3/eVC4コンパイラバグ回避) - ・CPU(I286C/I286X/I286A) … グループ7とか… - ・DMAC … インプットでアドレスとカウンタが逆なのを修正 - ・PIT … ビープカウンタを修正 - ・NP2SYSP … ポートを叩いた瞬間 フリーズするバグを修正 - ・CALENDAR … 時間をインクリメントしないバグの修正 - ・ITF … 拡張メモリ使用時にエミュレーション内部のメモリを破壊するのを修正 - ・CS4231 … 再生しなくなっていたのを修正 - ・CS4231 … DMA,IRQを変更出来るようにしました - ・CS4231 … デフォルトのDMAチャネルを #1に変更 - ・MIDI … STATSAVEの修正 - ・SOUND … JAST SOUNDをサポート - ・Vermouth … Roland GSコマンドの一部に対応 - - 補足 -  ver0.73では EPSONモードの時 D000〜DFFFがRAM化されます。 -  ・SOUND BIOSは D000,D400に配置しないで下さい、もしくはUMB等で破壊されないようにして下さい。 - - - (X11) -  ・Qt 2.x の実験的なサポート -  ・SDL の実験的なサポート -  ・ビープ音量が設定ファイルに保存されないのを修正 - - - ver0.73向け -  ・io/necio.c io/epsonio.c をリンクして下さい -  ・io/itf.cをリンクよりはずして下さい - -  ・configのモデル選択 http://retropc.net/yui/cvs/config.gif -   np2cfg.model に それぞれ "VM" "VX" "EPSON"の文字列を設定する。 -   (それぞれ common/strresにstr_VM, str_VX, str_EPSONが用意されています) - -  ・JAST SOUNDの選択 http://retropc.net/yui/cvs/jastsnd.gif -   パラレルなので 機種依存部の COMMNG.Cを修正して CMJASTCを呼ぶ -   使用・未使用判定は OSごとに(np2oscfgで)設定すること - -  ・wavemix sound/getsnd については ver0.73では不要ですが、 -   ver0.74あたりで使用する予定(Seeksnd?/OPNA/AMD-98の共用ルーチン化) -   今までのseeksndインタフェイスはどうするかね… - - - 更新履歴に書かなくていい変更点 -  ・i286a/i286c/i286xに簡易プロテクトモードを追加(保護・タスクなし) -  ・DMACを再配置できるように修正 -  ・CPU/EGCのストラクチャの調整 -  ・BIOS … DISK BIOSをサポート(但し 通常のBIOSコールは DISK BIOSを使用せずに BIOSレベルでシミュレートしています) -  ・BIOS … SASI/SCSI BIOS ROMをサポート(BIOSアドレス d000:0000) -   補足→ (ver0.74に回す) -    SASI/SCSI BIOSは 殆どの場合にはブート時にしか使っていないので RAM内容を破壊しても HDDアクセスは正常に行なわれます。 -    ※アプリケーションが SASI/SCSI BIOSを直視しない限りは大丈夫。 -     ver0.72までは SASI/SCSI BIOSがサポートされていない(=つまり使われていない) ver0.72までに動いていたソフトウェアはほぼ大丈夫と言えます。 -  ・hostdrv... - - -// ---- - - ver0.71 → ver0.72 - - ・主にRISC向けの最適化(CPU, BEEP counter, BIOS etc...) - ・CPU … aaa命令の修正 - ・PIT … インターバルタイマの割り込みを修正、リカバリ修正 - ・VRAM … SLとLRの関係をミスってた。 - ・PC-9801-26K … ステータスを修正 - ・PSG … サウンド作成タイミングの修正(ヴォリューム変更時) - ・マウス … 負方向の演算の不都合を修正 - ・一部の設定だけを変更しても cfgに保存されないのを修正 - ・vermouth … Win9x,MacOS,X11でバンク切替えを有効にした - (済: MacOSX→cmverを使って下さい) - (済: x11→midimod_loadprogram/rhythmの代わりに midimod_loadallを) - ・ini/cfg … biospathの追加 (nullstringでdosioカレント) - - (MacOSX) -  ・Open/Saveダイアログ修正 -  ・ドラッグ&ドロップ修正 -  ・vermouthをcmverを使うように変更 -  ・XFERとNFERをそれぞれカナキーと英数キーに割り当てた。 -  ・ウィンドウの位置をnp2.cfgに記録するようになった。 -  ・これまでF12に割り当てていたキーをF11とF12で分担するように変更(要再設定)。 -  ・割り当て可能なキーにNFERとXFER(とカナ)を追加。 -  ・コマンド+クリックを右クリックに割り当てるように変更。 - - (Win9x) -  ・標準ディスプレイ→プラズマディスプレイ移行時にゴミがのこるのを修正 - - (WinCE) -  ・ソフトウェアキーボードのサポート - - (X11) -  ・Qt の実験的なサポート -  ・MIT Shared-Memory Extention shared Pixmap サポート -  ・画面描画時の無駄を減らした -  ・Key Display のサポート - - - でぶねこ補足 -  ・必須 -    compiler.h に 以下のうち必要な定義を入れること -      OSLANG_SJIS, OSLANG_EUC -      OSLINEBREAK_CR, OSLINEBREAK_LF, OSLINEBREAK_CRLF -      SUPPORT_ANK, SUPPORT_SJIS, SUPPORT_EUC - -  ・変更 -    (target)/keydisp -> (generic)/keydisp -    (target)/cmmidi -> (target)/cmver (vermouthのみ使用の場合) - -  基本的には WinCE版とSDL版用のファイルで追加されたファイルで -  リンクエラーが発生しない限りは必要はないと思われ。 - - -// ---- - - ver0.70 → ver0.71 - - ・CPU … enter命令(level>=2)の修正(C版のみ) - ・メモリスイッチ … 初期値を修正(コプロセッサフラグ) - ・FDC … Read IDの対応 - ・FDD … Write ID時にキャッシュがフラッシュされていなかったバグの修正 - ・np2sysp … ポート指定ミスを修正 - ・PSG … ステレオ出力の対応 - ・PC-9801-14 … DIPSWポートの修正、PITのクロックを変更 - ・AMD-98 … クロックを修正、レジュームの対応 - - - (Win9x) -  ・keydisp PSG修正 -  ・マウス修正 - - (MacOS9) -  ・マウス対応(Classicのみ) -  ・キーボード修正 -    バックグラウンド処理中にキー入力を抑制 - Classic - 旧Classicルーチンを使用するようにした - Carbon - キーリピートに対応 -  ・メニュー修正 -  ・エミュレーションウィンドウを可変サイズに - - (MacOSX) -  ・マウス修正 -  ・New Disk修正 -  ・ヘルプ対応 -  ・IIx専用ロゴ追加 -  ・書類アイコン追加/変更 -  ・About表示変更 -  ・AMD-98対応 -  ・画面回転対応 -  ・エミュレーションキー追加 -  ・シークサウンドをリソースに追加(外部ファイルは不要です) -  ・その他にも細かな修正あり + +// ---- info + + TRACE版(i286_step())で シングルステップ割り込みが割り込み続けるとか + mov SS直後に割り込みが発生するとか不都合があります。 + これについては、直す気力があれば(286コードを追っかける時だけだし…) + + + CHARSET_OEMについて +  要は毎回Shift-JISに変換せずに OS依存の文字コードで処理しようとする… +  まだ機能しません。定義しないで下さい。 + +  OEMCHAR (現状char固定、将来として UCS2でUINT16、UCS4でUINT32) +  OEMTEXTの追加 +  コンパイルが通るかご確認下さい。 + +  ステップ.1 (WinCE,X11) +   OEMコードと SJIS(EMBED/hostdrv)の変換調整 +   (FONTMNGは SJISのままで EMBEDで変換) + +   つか…X11版のDOSIO file_catname,file_cmpnameの入力が sjisになってる… +   (NP2はファイル名は OSLANGに従う…筈… +   と思ったら hostdrvで SJISのまま食わせてる?(汗 + +   EUCの2バイトコード判定が (((c - 0xa1) & 0xff) < 0x5d)で +   半角カナ(0x8e)の判定で狂う +   (c & 0x80)のほうが良い? + +   現状の… + +   ・codecnv.hのインクルードは compiler.hに移動 + +   ・#if defined(OSLANG_EUC) +     codecnv_sjis2euc(tmp, NELEMENTS(tmp), src, (UINT)-1); +     file_catname(path, tmp, NELEMENTS(path)); +    #elif defined(OSLANG_UTF8) +     oemtext_sjis2oem(tmp, NELEMENTS(tmp), src, (UINT)-1); +     file_catname(path, tmp, NELEMENTS(path)); +    #else +     file_catname(path, src, NELEMENTS(path)); +    #endif + +    を + +    #define oemtext_sjis2oem codecnv_sjis2euc +    #define oemtext_oemsjis2 codecnv_euc2sjis + +    としておいて + +    #if defined(OSLANG_ANK) || defined(OSLANG_SJIS) +     file_catname(path, src, NELEMENTS(path)); +    #else +     oemtext_sjis2oem(tmp, NELEMENTS(tmp), src, (UINT)-1); +     file_catname(path, tmp, NELEMENTS(path)); +    #endif + +    とする? + +   メモ: http://euc.jp/i18n/charcode.ja.html + +  ステップ.2 (WinNT,MacOSX) +   OEMCHARのUCS2対応 + +  ステップ.3 (MacOSX) +   ANSI PageCodeと Macintosh PageCodeの調整 +   メモ: http://homepage1.nifty.com/nomenclator/unicode/normalization.htm + +  ステップ.4 (WinNT,WinCE,MacOSX,X11) +   フォント関数回りを SJISからOEMコードに移行 + + +// ---- + + ver0.84 → ver0.85 + + (X11) +  ・環境によってサウンドの設定を変更した後にリセットするとプログラムが +   クラッシュする不具合を修正 +  ・SDL 2.0 サポート追加 +   configure では SDL 2.0 → SDL 1.2 の順番でライブラリを検索するので +   SDL 1.2 を明示的に使用したい場合には configure のオプションに +   --disable-sdl2 を指定する必要がある +  ・SDL audio のバックエンドとして PulseAudio を使用している場合に音が正常に +   鳴らない不具合を修正 +  ・USB 接続外部 FM 音源サポート追加。C86BOX を使用するには libusb 1.0 が必要 +   SPFM Light + RE:birth RE1-YM2608、C86BOX + PC-9801-86 で動作確認済み + + +// ---- + + ver0.83 → ver0.84 + ・i386c - 色々と変更 + ・i386c - rcl, rcr 命令の不具合を修正 + ・i386c - 命令実行中に例外が発生した際にスタックポインタがずれてしまう不具合 +   を修正 + ・i386c - 割込みゲート、トラップゲートで不正なエラーコードが設定されてしまう +   不具合を修正 + ・i386c - セグメント有効範囲チェックの不具合を修正 + ・i386c - enter, leave, call, pusha, popa 命令でリアルモード時でもスタック +   サイズチェックで例外が発生してしまう不具合を修正 + ・i386c - セグメントレジスタ設定時の不具合を修正 + ・i386c - タスクゲート処理時のエラーコードプッシュ処理の不具合を修正 + ・i386c - iret 命令で仮想86モードに復帰する際にスタック上の値によっては例外が +   発生してしまう不具合を修正 + ・i386c - ゲートを通じて別コードセグメント移行時に使用するオペランドサイズに +   ゲートタイプではなくスタックセグメントを使用していた不具合を修正 + ・BIOS - 1F90h A20有効後に戻していない不具合を修正 + ・BIOS - 1Bh メモリアクセスを修正 + + (Win32) +  ・NASM 2.09を使用するように修正 +  ・UNICODE版(np2nt.exe) で hostdrv が利用できないバグを修正 +  ・G.I.M.I.C、C86BOX、RE:birth に対応 + + (X11) +  ・STATSAVE 用のメニューを作成 +  ・レジューム/STATSAVE のファイル名を変更 +   - レジューム: ${HOME}/.np2/sav/sav → ${HOME}/.np2/sav/np2.sav +   - STATSAVE : ${HOME}/.np2/sav/s00 → ${HOME}/.np2/sav/np2.s00 +  ・フォントパスに設定ファイル名が含まれてしまう不具合を修正 +  ・エミュレーションウィンドウサイズ変更用のメニューを作成 +  ・GLIB, GTK+ の deprecated なインタフェースを使用しない様に修正 +  ・CPU 使用率を軽減する様に修正 +  ・コンフィグ画面からサウンドドライバを変更出切る様に修正 +  ・環境によってサウンドを有効にした場合にプログラムがクラッシュする +   不具合を修正 +  ・ビルド、インストールに Autotools(configure) を使用するように修正 +  ・ファイル保存時に既に同名ファイルが存在した場合、上書き確認ダイアログを +   表示するように修正 (GTK+-2.8 以降のみ有効) +  ・F12 キー機能割り当てに Help キーを追加 +  ・ファイルダイアログの floppy disk image Files にて拡張子が flp のファイル +   を表示する様に修正 +  ・Screen Option の LCD のチェックを外しても外れない不具合を修正 +  ・FDD シーク音が鳴らない不具合を修正 +  ・色深度が 8bpp の場合に配列の範囲外にアクセスしていた不具合を修正 +  ・F11 キーにフルスクリーン表示切り替え、フルスクリーン時のメニュー表示 +   切り替え機能を割り当て + + + (MacOSX) +  ・新規対応 + + (iOS) +  ・新規対応 + + +// ---- + + ver0.82 → ver0.83 + + (X11) +  ・ファイルダイアログにて拡張子が大文字のディスク・イメージを認識する様に修正 +  ・ファイルダイアログの IDE disk image Files にて拡張子が .hdi .tfd の +   ファイルを表示する様に修正 + + +// ---- + + ver0.81a → ver0.82 + ・MPU-PC98II - モード切替時のMIDIリセットを修正 + ・VERMOUTH - ver1.15版に差し替え + + (Win9x) +  ・モジュール判定不具合修正 + + (X11) +  ・PC9801-26K の I/O ポートが設定できなかった不具合を修正 +  ・フルスクリーンモードサポート +  ・F11 キーに機能割り当て +   - フルスクリーンモードトグル +   - フルスクリーン時のメニュー表示トグル + + +// ---- + + ver0.81 → ver0.81a + ・80286 (ARM版) - 割り込みハンドラを修正 + ・MOUSE - ボタンフラグの修正 + ・PIT - シリアルカウンタの修正 + ・HOSTDRV - 拡張子を消去する不都合を修正 (ver0.81エンバグ) + ・BIOS - FDCスイッチ/シグナルの修正 + + + + ver0.80 → ver0.81 + ・80286 (x86版) - rep ins, 2バイトmov8命令の不都合修正 + ・80286 (x86版) - クロック修正 (enter) + ・80286 (C版) - クロック修正 (cmp, jcc, test, enter) + ・80286 (ARM版) - pop ss命令の修正 + ・80286 (ARM版) - クロック修正 (cmp, jcc, test, enter) + ・80286 (C版) - rep outsw命令を修正 + ・MPU-PC98II - conductor修正 + ・MPU-PC98II - Request PC/Tempo コマンドの追加 + ・DMA - セルフイニシャライズを追加 + ・GDC - ソフトリセット時のフラグ修正 + ・GRCG - ソフトリセット時のフラグ修正 + ・PIT - シリアルカウンタの修正 + ・MOUSE - 割り込み修正 + ・ATRIC - 時間巻き戻りバグ修正 + ・SOUND - アドレスバスの修正 + ・WSS - データ転送サイズの修正 + ・BIOS - 1842h スクリーンモードを破壊する不都合修正 (ver0.75エンバグ) + ・BIOS - CRTBIOSフラグ修正 (PC-9821モード) + ・BIOS - FDDアクセス時にstatsaveを行なうと復帰できなくなる不都合修正 + ・一部(というか大部分…)のキーボードのmake/break関係を修正 + + ・メモリを修正(C版コア) + ・16MB以上のメモリをサポート(IA32) + + ・内部変更 +  たぶん +   #define OEMTEXT(string) (string) +  を +   #define OEMTEXT(string) string +  にする必要がある。 + +  CPUフォルダの DMA EGC等がほぼ同様のコードなので memフォルダへ移動し +  共通にしました。 + +  embedのShift-JISを ネイティブコードにしました。 +  文字コードがEUCの環境では SUPPORT_SJISは不要になります。 +  また、fontmng_getsize, fontmng_getdrawsizeの引き数の文字コードが +  SJISからEUCへ変更になっています。 + +  codecnvとucscnvを /codecnv へ移動しました。 + +  pccore.cとかにあるデバグコードがウザイので trapフォルダへ移動。 +  ENABLE_TRAPが定義されてなければ見る必要はありません。 + + +// ---- + + ver0.79 → ver0.80 + ・BIOS - スクロールコマンド修正 + ・BIOS - システムポートの修正(i286/V30ではほぼ無意味) + ・GDC - ステップフラグの反映 + ・FDC - レディ信号を修正 + ・i286x - div命令 (i286モード側) + ・i286c - div命令 (V30モード側) + + + (X11) +  ・ジョイスティックサポート +   サウンドドライバに SDL を使用している時にのみ使用可 +  ・screen depth == 24bpp の時にキーディスプレイ、ソフトウェアキーボードの +   描画がおかしい不具合を修正 +  ・T98-Next(.NHD)形式、Anex(.HDI)形式ハードディスクイメージ作成サポート + +(MacOSX) +  ・日本語リソース追加 +  ・ソフトウェアキーボードを有効にした + + +// ---- + + ver0.78 → ver0.79 + ・CGROM - JIS83罫線の不都合修正 + ・CGROM - 2バイト半角アクセス修正 + ・86PCM - バッファリングの不都合を修正 + ・BEEP - BEEP PCMの修正 + ・BIOS - 2Dタイプのシリンダ倍移動を修正 + ・BIOS - FDD割り込みフラグを修正 + ・AMD98 - レジスタリードの追加 + ・VRAM - スキップライン描画の修正 + ・BMPSave - スキップライン有効時のセーブ不都合を修正 + + (Win9x) +  ・ソフトウェアキーボードを有効にした + + (MacOSX) +  ・カレンダーに対応 + + + ・内部変更 + +   char *file_getext(const char *path); +   char *file_getname(const char *path); +   (constが付きます) + +   記念に gif保存に対応してみたり +    vram/scrnbmp.c の代わりに vram/scrnsave.c をリンクして + +     SCRNSAVE ss = scrnsave_get(); +     scrnsave_writegif(ss, "out.gif", SCRNSAVE_AUTO); +    scrnsave_trash(ss); + +     bmpなら scrnsave_writebmp(ss, "out.bmp", SCRNSAVE_AUTO); + +     np21のVGA時に 257色以上になるのに注意 +     (ss->type == SCRNSAVE_24BITの時にgif保存出来ません) + + +// ---- + + ver0.77 → ver0.78 + ・PIC - スレーヴのマスクの修正 + ・CGROM - JIS83罫線の不都合修正 + ・TEXTRAM - JIS83罫線の不都合修正 + ・86PCM - 割り込みステータスの修正 + ・BIOS - ブート時にメモリを完全に消去するようにした +      ※ RanceII対策、他のホットスタートで不都合が出るかも + ・BIOS - 直線描画のアルゴリズム修正 + ・BIOS - 円の半径が異常だった不都合の修正 + ・BIOS - JIS83罫線の不都合修正 + ・LIO - 内部塗り潰し指定付きBOX描画の対応 + ・LIO - 半角ひらがなの対応 + ・LIO - 円の仮サポート + + (X11) +  ・ソフトウェアキーボードサポート + + ・内部変更 + +   追加ファイル +    /lio/gcircle.c + + + +// ---- + + ver0.76 → ver0.77 + ・BIOS - FDC BIOSの修正 + ・FDD - ディスクシーク音再生中にリセットを行なうと 以降ディスクアクセスが行なえなくなる不都合を修正。 + + (X11) +  ・i386 アーキテクチャ以外でコンパイルできない不具合を修正 + + + +// ---- + + ver0.74 → ver0.76 (branch...) + ・DMA - バンク・アドレスマスクの修正 + ・PIC - スペシャルマスクモードの対応 + ・PIT - マルチプルラッチコマンドのサポート(uPD71054) + ・CGROM - 2バイト半角の処理を修正 + ・CGWINDOW - ワードアクセスの挙動修正 (MacOS9/MacOSX/x11/SDL) + ・MOUSE - uPD8255のコマンドレジスタの修正 + ・86PCM - 停止時にもかかわらずバッファを進めてしまう不都合を修正 + ・CS4231 - PIOサポート + ・BIOS - ベクタ08/1A/1Fの修正 + ・BIOS - リセット時の挙動の修正 + + (Windows9x) +  ・ATマシンの場合に PageUp/PageDownを反転 + + + ・内部変更 +   基本的にファイルが存在しなければプロジェクトから除外、 +   リンクエラーが出たらgrepしてファイル追加 + +    追加ファイル +     /bios/bios1f.c +     /bios/biosfd80.res +     /cbus/ideio.h +     /cbus/ideio.c (SUPPORT_IDEIO定義時) +     /cbus/atapicmd.h +     /cbus/atapicmd.c (SUPPORT_IDEIO定義時) +     /cbus/idebios.res +     /io/pcidev.h +     /io/pcidev.c (SUPPORT_PC9821定義時) + + +    削除ファイル +     /bios/bios02.c +     /bios/bios08.c +     /bios/biosboot.res +     /common/pf_key.tbl +     /sound/wavemix.h +     /sound/wavemix.c +     /sound/rhythmg.c +     /lio/gview.c +     /lio/gcolor1.c +     /lio/gcolor2.c +     /lio/gcls.c + + +   ROMIMAGEは MASMからNASMへ移行中でつ。 + +   SUPPORT_IDEIOは定義しないで下さい(まだマトモに動きません) + +   IA32でもハードウェアEMSを有効にしてみるテスト。 + + + +// ---- + + ver0.74 → ver0.75 + + ・GDC - ベクタの初期化し忘れを修正 + ・GDC - パターンの修正 + ・ITF/BIOS - リセット時の挙動の修正 + ・BIOS - 1842h モノクロフラグを修正 + ・EGCの高速化(?) + ・リズムの修正(PCM 44khz 16bit monoralの制限を外した) + ・LIOの修正 + + + (Windows) +  ・(I286X) EGCバイトアクセス修正 +  ・(I286X) ストリング命令修正 +  ・フロッピードライブ接続状態指定 + + (MacOS9) +  ・フロッピードライブ接続状態指定 +  ・MPU-PC98IIの設定ダイアログ + + (WinCE) +  ・(I286A) メモリの修正 +  ・GDC - GDCクロック 1.79MHzのサポート + + (X11) +  ・Configure Dialog にてアーキテクチャの指定を追加 + + (MacOSX) +  ・フロッピードライブ接続状態指定(FDD1、FDD2のみ) +  ・設定ダイアログのディップスイッチ画像表示 +  ・CoreMID経由のMIDI演奏に対応 +  ・MPU-PC98IIの設定ダイアログ拡充 +  ・Key Display対応(マウスクリックでFMとMIDIが切り替わります) + + + ・200ラインモードについて (正式サポート / #define SUPPORT_CRT15KHZ) +  PC-9801シリーズ(FELLOW、PC-9821、ハイレゾ機を除く)に搭載されている +  200ラインモードは設定ファイルのDIPswtchにて設定可能となります。 + +   400ラインモード +    DIPswtch=3e ?? ?? + +   200ラインモード +    DIPswtch=3f ?? ?? + +  本機能は DIPSW1-1に相当する機能であり、PC-9801VM以降のマシンで +  一般に言われている200ラインモードとは異なる機能です。 + +  ※PC-98シリーズの一般的な200ラインモードは、640x200を縦に2倍拡大し +   400ラインモードで動作しています。 + +  本機能は DIPSW1-1の切り替え機能を削除した FELLOW、PC-9821、ハイレゾ機の +  BIOS.ROMを使用時には正常に動作致しません。 +  これを理由に、本機能は NP2上で設定スイッチを設けません。 + +  また、レジューム動作時に DIPswtchの値を変更した場合、正常に +  スクリーンモードを変更できなくなります。 +  (PC-98動作中にディップスイッチを変更した時と同じ状態になります。) +  必ずリセットして下さい。 + + + + ・キー設定について +  bios.romとかと同じフォルダに key.txtというファイル名のテキストファイルを +  作成して、キー設定を記入して下さい。 + +  書式) +   [keyname] = [key1] (key2) (key3) +   [keyname] [TAB] [key1] (key2) (key3) +   userkey[1-2] = [key1] (key2) (key3) ... (key15) +    フルキー 0〜9 A〜Z - ^ \ @ [ ] ; : , . / _ +     STOP COPY ESC TAB BS RET SPC XFER NFER + INS DEL RLUP RLDN HMCL HELP +    ファンク F1〜F10 VF1〜VF5 +    テンキー [0]〜[9] [-] [/] [*] [+] [=] [,] [.] +    シフト SHIFT CAPS KANA GRPH CTRL + +   通常キーは3個、userkeyは15個の同時押し設定が可能です。 +   [=] キーは = で区切られてしまうので TABで区切るか [EQU]として下さい。 + +   例: +    W = UP (ダイアモンドキーをカーソルにしてみたり…) +    S = LEFT +    D = RIGHT +    X = DOWN +    [7] = [4] [8] (テンキー斜め同時押しにしてみたり…) +    [9] = [6] [8] +    [1] = [4] [2] +    [3] = [6] [2] +    userkey1 = CTRL XFER (CTRL+XFER FEP切り替え) +    userkey2 = D O A Z (D+O+A+Z 同時押し) + + + + ・内部変更 +   win9x/unasmをgenericへ移動(+P6,FPU命令をサポート) + +   np2infoをgenericへ移動 +    エスケープ文字を !KEY から %KEY%へ変更 +    ex == NULLで OS指定の改行コードになる筈 +    (MacOSXは np2info.cppがそのまんま移動になるかと思われ + +   io/serial.*に存在した keystat系を /keystat.* へ移動 +    keystat.cをリンク、 keystat.hをインクルード + +   SUPPORT_WAVEMIX廃止 +    → SUPPORT_SWSEEKSNDに変更 +    ハードウェアで対応してる場合には 一応 SUPPORT_HWSEEKSNDと定義して +    くれると嬉すぃ + +  ・keystat_initialize(keystat_reset)をコールして初期化すること… + + +// ---- + + ver0.73 → ver0.74 + + ・I/OレベルでのSASIに対応(INT3/DMA#0/BIOS:d0000-d0fff) + ・SCSI HDDに対応 + ・np2qn形式 HOSTDRVに対応 + ・拡張メモリの修正 (80286) + ・VRAM - 通常ディスプレイ時にメモリを破壊するバグを修正 + ・GDC - GDCクロック 1.79MHzのサポート + ・GDC - 走査周波数を可変にした + ・GDC - マスクが左右反転していたのを修正 + ・GDC - テキスト処理を修正(uPD7220A? cmd:05) + ・GDC - VECTEコマンド(R)を修正 (undocumented Tを追加) + ・GDC - TEXTEコマンド(SL/T)を修正 (undocumented L/C/Rを追加) + ・GDC - GRCG/EGC動作中の挙動を修正 + ・EGC - マスクフラグを修正 + ・FDC - DMAとステータスを修正 + ・SERIAL - キーボードステータスの修正 + ・uPD4990 - ホールド時の出力が不定になっていたのを修正 + ・RHYTHM - レジュームが反映されなかった不都合を修正 + ・ADPCM - サンプルリードがMSB/LSB逆転していたのを修正 + ・BIOS - ブート時にディップスイッチで指定した画面モードを反映 + ・BIOS - 1840h/1841h/1842h/1847hの結果をワークメモリへ反映するようにした + ・BIOS - 1847h マスクを左右反転させていなかったのを修正 + ・BIOS - 1848h/1849h/184ahをサポート + ・ITF - PC-9801VM/PC-286時に BEEPが初期化されない不都合を修正 + ・ITF - SSP終了時にハードウェアリセットをかけるように修正 + ・IDE - ディップスイッチ内容(SW2-6)を反映するように修正 + + + (Windows) +  ・(I286X) sidt命令の修正 +  ・(I286X) テキストRAMアクセスの修正 +  ・(I286X) 割り込みの修正 +  ・(I286X) EGCシフタを修正 +  ・Aboutダイアログの修正 +  ・ろみおとか… + + (MacOS9) +  ・テンキーの [+] [/] の修正 +  ・file_attr()で FILEATTR_READONLY を返すように… + + (MacOSX) +  ・テンキーの [+] [/] の修正 +  ・file_attr()で FILEATTR_READONLY を返すように… +  ・ツールウィンドウ修正 +  ・FDIイメージ対応(仕事早いよー>ゆいさん) +  ・フルスクリーン修正(たぶん・・) +  ・マウスドラッグに対応(タコミス・汗) + + + ・Userkeyについて +  userkey1, userkey2は、cfgを書換えることによりキーを自由に変更することが +  出来ます。 +  書式) +   userkey1 = [key1] (key2) (key3)... +    フルキー 0〜9 A〜Z - ^ \ @ [ ] ; : , . / _ +     STOP COPY ESC TAB BS RET SPC XFER NFER + INS DEL RLUP RLDN HMCL HELP +    ファンク F1〜F10 VF1〜VF5 +    テンキー [0]〜[9] [-] [/] [*] [+] [=] [,] [.] +    シフト SHIFT CAPS KANA GRPH CTRL + +   例: +    userkey1 = CTRL XFER (CTRL+XFER FEP切り替え用) +    userkey2 = D O A Z (D+O+A+Z 同時押し) + +  本機能は 簡易的な実装であり ver0.75で変更されます。 +  また、ver0.74ではシフト系は不整合が発生する可能性があります。 + + + + ・内部変更 +   pccore.h の中で statsave.hをインクルード +    → #include をトル + +   io/extmem を io/emsioに変更 +   (IA32は emsioは要らないが、NEC EMSバンク形式で必要になるかも) + +   np2cfg.hddfile[2] -> np2cfg.sasihdd[2] + +   void diskdrv_sethdd(REG8 drv, const char *fname); +    drv = BIOSのデバイス番号 +     0x00〜0x01 SASI #0-1 +     0x20〜0x23 SCSI #0-3 (SUPPORT_SCSIを定義した時のみ) + +   bios/sxsibios.c はリンク必須 +   cbus/sasiio.c - SUPPORT_SCSIを定義した時にリンク +   cbus/scsiio.c cbus/scsicmd.c - SUPPORT_SCSIを定義した時にリンク + +   IA32でハードウェアEMSを禁止しました。 +     → #define CPU_SETEXTSIZE() init_mem() に変更 (済) +     → memory.cの EMM部分をトル (済) +     → cpumem extmem_size を CPU_EXTMEM, CPU_EXTMEMSIZEに変更(済) +     → protectmem_sizeをトル (済) + +   しかし emm386.exeが使えないから ハードウェアEMSを有効にした +   ほーがいいかな? 辻褄は合いそうだし。 +   386以降に乗っかってる NEC EMSバンク方式だと あまりにアホだし。 + +   dosio.hの FTYPEを common.hへ移動。 +   こそーり fdiを読めるよーにしてみたり。 + +   フロッピードライブについて np2cfg.fddequipを見に行くようにしました +   デフォルトで2基 +   np2cfg.fddequip = 0x03 (ドライブ1 = ビット0 〜 ドライブ4 = ビット3) +   (実際に動作中の装備状態は fdc.equipで リセット時に更新されます) +   必要によって main()で変える、cfgに書き出す等してください。 + +   S98について SUPPORT_S98定義時のみリンクするようにしました。 +   (Win9x, MacOSX, x11(USE_GTK)) + +   PC9861Kについて SUPPORT_PC9861K定義時のみリンクするようにしました。 +   (シリアル通信に対応していなければ無意味な機能です) + +   userkey +    ini.cで profile_setkeys, profile_getkeysで np2cfg.userkeyを更新 +    キーボードのどこかにキーに キーコード 0x76,0x77を追加 + + + メモ +  実機で FDでVRAMクリアされるのは何故? + + +// ---- + + ver0.72 → ver0.73 + + ・主にRISC向けの最適化、その2 + ・EPSON PCシリーズのアーキテクチャをサポート + ・ARM版CPUコアのサポート + ・CPU(I286C) … シングルステップ割り込みの修正 + ・CPU(I286C) … int3 / int imm8 / into クロック数を修正 + ・CPU(I286C) … shl r/m8,cl / shr r/m8,cl の修正 + ・CPU(I286C) … sar r/m (eVC3/eVC4コンパイラバグ回避) + ・CPU(I286C/I286X/I286A) … グループ7とか… + ・DMAC … インプットでアドレスとカウンタが逆なのを修正 + ・PIT … ビープカウンタを修正 + ・NP2SYSP … ポートを叩いた瞬間 フリーズするバグを修正 + ・CALENDAR … 時間をインクリメントしないバグの修正 + ・ITF … 拡張メモリ使用時にエミュレーション内部のメモリを破壊するのを修正 + ・CS4231 … 再生しなくなっていたのを修正 + ・CS4231 … DMA,IRQを変更出来るようにしました + ・CS4231 … デフォルトのDMAチャネルを #1に変更 + ・MIDI … STATSAVEの修正 + ・SOUND … JAST SOUNDをサポート + ・Vermouth … Roland GSコマンドの一部に対応 + + 補足 +  ver0.73では EPSONモードの時 D000〜DFFFがRAM化されます。 +  ・SOUND BIOSは D000,D400に配置しないで下さい、もしくはUMB等で破壊されないようにして下さい。 + + + (X11) +  ・Qt 2.x の実験的なサポート +  ・SDL の実験的なサポート +  ・ビープ音量が設定ファイルに保存されないのを修正 + + + ver0.73向け +  ・io/necio.c io/epsonio.c をリンクして下さい +  ・io/itf.cをリンクよりはずして下さい + +  ・configのモデル選択 http://retropc.net/yui/cvs/config.gif +   np2cfg.model に それぞれ "VM" "VX" "EPSON"の文字列を設定する。 +   (それぞれ common/strresにstr_VM, str_VX, str_EPSONが用意されています) + +  ・JAST SOUNDの選択 http://retropc.net/yui/cvs/jastsnd.gif +   パラレルなので 機種依存部の COMMNG.Cを修正して CMJASTCを呼ぶ +   使用・未使用判定は OSごとに(np2oscfgで)設定すること + +  ・wavemix sound/getsnd については ver0.73では不要ですが、 +   ver0.74あたりで使用する予定(Seeksnd?/OPNA/AMD-98の共用ルーチン化) +   今までのseeksndインタフェイスはどうするかね… + + + 更新履歴に書かなくていい変更点 +  ・i286a/i286c/i286xに簡易プロテクトモードを追加(保護・タスクなし) +  ・DMACを再配置できるように修正 +  ・CPU/EGCのストラクチャの調整 +  ・BIOS … DISK BIOSをサポート(但し 通常のBIOSコールは DISK BIOSを使用せずに BIOSレベルでシミュレートしています) +  ・BIOS … SASI/SCSI BIOS ROMをサポート(BIOSアドレス d000:0000) +   補足→ (ver0.74に回す) +    SASI/SCSI BIOSは 殆どの場合にはブート時にしか使っていないので RAM内容を破壊しても HDDアクセスは正常に行なわれます。 +    ※アプリケーションが SASI/SCSI BIOSを直視しない限りは大丈夫。 +     ver0.72までは SASI/SCSI BIOSがサポートされていない(=つまり使われていない) ver0.72までに動いていたソフトウェアはほぼ大丈夫と言えます。 +  ・hostdrv... + + +// ---- + + ver0.71 → ver0.72 + + ・主にRISC向けの最適化(CPU, BEEP counter, BIOS etc...) + ・CPU … aaa命令の修正 + ・PIT … インターバルタイマの割り込みを修正、リカバリ修正 + ・VRAM … SLとLRの関係をミスってた。 + ・PC-9801-26K … ステータスを修正 + ・PSG … サウンド作成タイミングの修正(ヴォリューム変更時) + ・マウス … 負方向の演算の不都合を修正 + ・一部の設定だけを変更しても cfgに保存されないのを修正 + ・vermouth … Win9x,MacOS,X11でバンク切替えを有効にした + (済: MacOSX→cmverを使って下さい) + (済: x11→midimod_loadprogram/rhythmの代わりに midimod_loadallを) + ・ini/cfg … biospathの追加 (nullstringでdosioカレント) + + (MacOSX) +  ・Open/Saveダイアログ修正 +  ・ドラッグ&ドロップ修正 +  ・vermouthをcmverを使うように変更 +  ・XFERとNFERをそれぞれカナキーと英数キーに割り当てた。 +  ・ウィンドウの位置をnp2.cfgに記録するようになった。 +  ・これまでF12に割り当てていたキーをF11とF12で分担するように変更(要再設定)。 +  ・割り当て可能なキーにNFERとXFER(とカナ)を追加。 +  ・コマンド+クリックを右クリックに割り当てるように変更。 + + (Win9x) +  ・標準ディスプレイ→プラズマディスプレイ移行時にゴミがのこるのを修正 + + (WinCE) +  ・ソフトウェアキーボードのサポート + + (X11) +  ・Qt の実験的なサポート +  ・MIT Shared-Memory Extention shared Pixmap サポート +  ・画面描画時の無駄を減らした +  ・Key Display のサポート + + + でぶねこ補足 +  ・必須 +    compiler.h に 以下のうち必要な定義を入れること +      OSLANG_SJIS, OSLANG_EUC +      OSLINEBREAK_CR, OSLINEBREAK_LF, OSLINEBREAK_CRLF +      SUPPORT_ANK, SUPPORT_SJIS, SUPPORT_EUC + +  ・変更 +    (target)/keydisp -> (generic)/keydisp +    (target)/cmmidi -> (target)/cmver (vermouthのみ使用の場合) + +  基本的には WinCE版とSDL版用のファイルで追加されたファイルで +  リンクエラーが発生しない限りは必要はないと思われ。 + + +// ---- + + ver0.70 → ver0.71 + + ・CPU … enter命令(level>=2)の修正(C版のみ) + ・メモリスイッチ … 初期値を修正(コプロセッサフラグ) + ・FDC … Read IDの対応 + ・FDD … Write ID時にキャッシュがフラッシュされていなかったバグの修正 + ・np2sysp … ポート指定ミスを修正 + ・PSG … ステレオ出力の対応 + ・PC-9801-14 … DIPSWポートの修正、PITのクロックを変更 + ・AMD-98 … クロックを修正、レジュームの対応 + + + (Win9x) +  ・keydisp PSG修正 +  ・マウス修正 + + (MacOS9) +  ・マウス対応(Classicのみ) +  ・キーボード修正 +    バックグラウンド処理中にキー入力を抑制 + Classic - 旧Classicルーチンを使用するようにした + Carbon - キーリピートに対応 +  ・メニュー修正 +  ・エミュレーションウィンドウを可変サイズに + + (MacOSX) +  ・マウス修正 +  ・New Disk修正 +  ・ヘルプ対応 +  ・IIx専用ロゴ追加 +  ・書類アイコン追加/変更 +  ・About表示変更 +  ・AMD-98対応 +  ・画面回転対応 +  ・エミュレーションキー追加 +  ・シークサウンドをリソースに追加(外部ファイルは不要です) +  ・その他にも細かな修正あり diff --git a/vram/dispsync.c b/vram/dispsync.c old mode 100755 new mode 100644 index a761af26..f066d407 --- a/vram/dispsync.c +++ b/vram/dispsync.c @@ -1,151 +1,151 @@ -#include -#include -#include -#include -#include -#include - - - DSYNC dsync; - - -void dispsync_initialize(void) { - - ZeroMemory(&dsync, sizeof(dsync)); - dsync.textymax = 400; - dsync.grphymax = 400; - - dsync.scrnxmax = 640; - dsync.scrnxextend = 0; - dsync.scrnymax = 400; - -// scrnmng_setwidth(0, 640); -// scrnmng_setextend(0); -// scrnmng_setheight(0, 400); -} - -BOOL dispsync_renewalmode(void) { - - UINT disp; - - if (!scrnmng_haveextend()) { - return(FALSE); - } - disp = 0; - if ((!(np2cfg.LCD_MODE & 1)) && ((gdc.display & 7) < 3)) { - disp = 1; - } - if (dsync.scrnxextend != disp) { - dsync.scrnxextend = disp; - scrnmng_setextend(disp); - return(TRUE); - } - return(FALSE); -} - -BOOL dispsync_renewalhorizontal(void) { - - UINT hbp; - UINT cr; - UINT scrnxpos; - UINT scrnxmax; - - hbp = gdc.m.para[GDC_SYNC + 4] & 0x1f; - cr = gdc.m.para[GDC_SYNC + 1]; - - scrnxpos = 0; - if (hbp >= 7) { - scrnxpos = hbp - 7; - } - scrnxmax = cr + 2; - if ((scrnxpos + scrnxmax) > 80) { - scrnxmax = MIN(scrnxmax, 80); - scrnxpos = 80 - scrnxmax; - } - scrnxpos <<= 3; - scrnxmax <<= 3; - if ((dsync.scrnxpos != scrnxpos) || (dsync.scrnxmax != scrnxmax)) { - dsync.scrnxpos = scrnxpos; - dsync.scrnxmax = scrnxmax; - scrnmng_setwidth(scrnxpos, scrnxmax); - return(TRUE); - } - else { - return(FALSE); - } -} - -BOOL dispsync_renewalvertical(void) { - - UINT text_vbp; - UINT grph_vbp; - UINT textymax; - UINT grphymax; - UINT scrnymax; - - text_vbp = gdc.m.para[GDC_SYNC + 7] >> 2; - grph_vbp = gdc.s.para[GDC_SYNC + 7] >> 2; - if (text_vbp >= grph_vbp) { - text_vbp -= grph_vbp; - grph_vbp = 0; - } - else { - grph_vbp -= text_vbp; - text_vbp = 0; - } - - textymax = LOADINTELWORD(gdc.m.para + GDC_SYNC + 6); - textymax = ((textymax - 1) & 0x3ff) + 1; - textymax += text_vbp; - - grphymax = LOADINTELWORD(gdc.s.para + GDC_SYNC + 6); - grphymax = ((grphymax - 1) & 0x3ff) + 1; - grphymax += grph_vbp; - -#if defined(SUPPORT_CRT15KHZ) - if (gdc.crt15khz & 2) { - textymax *= 2; - grphymax *= 2; - } -#endif - if (textymax > SURFACE_HEIGHT) { - textymax = SURFACE_HEIGHT; - } - if (grphymax > SURFACE_HEIGHT) { - grphymax = SURFACE_HEIGHT; - } - if ((dsync.text_vbp == text_vbp) && (dsync.grph_vbp == grph_vbp) && - (dsync.textymax == textymax) && (dsync.grphymax == grphymax)) { - return(FALSE); - } - dsync.text_vbp = text_vbp; - dsync.grph_vbp = grph_vbp; - dsync.textymax = textymax; - dsync.grphymax = grphymax; - - scrnymax = MAX(grphymax, textymax); - scrnymax = (scrnymax + 7) & (~7); - if (dsync.scrnymax != scrnymax) { - dsync.scrnymax = scrnymax; - scrnmng_setheight(0, scrnymax); - } - - dsync.textvad = text_vbp * 640; - dsync.grphvad = grph_vbp * 640; - if (text_vbp) { - ZeroMemory(np2_tram, text_vbp * 640); - } - if (scrnymax - textymax) { - ZeroMemory(np2_tram + textymax * 640, (scrnymax - textymax) * 640); - } - if (grph_vbp) { - ZeroMemory(np2_vram[0], grph_vbp * 640); - ZeroMemory(np2_vram[1], grph_vbp * 640); - } - if (scrnymax - grphymax) { - ZeroMemory(np2_vram[0] + grphymax * 640, (scrnymax - grphymax) * 640); - ZeroMemory(np2_vram[1] + grphymax * 640, (scrnymax - grphymax) * 640); - } - return(TRUE); -} - +#include +#include +#include +#include +#include +#include + + + DSYNC dsync; + + +void dispsync_initialize(void) { + + ZeroMemory(&dsync, sizeof(dsync)); + dsync.textymax = 400; + dsync.grphymax = 400; + + dsync.scrnxmax = 640; + dsync.scrnxextend = 0; + dsync.scrnymax = 400; + +// scrnmng_setwidth(0, 640); +// scrnmng_setextend(0); +// scrnmng_setheight(0, 400); +} + +BOOL dispsync_renewalmode(void) { + + UINT disp; + + if (!scrnmng_haveextend()) { + return(FALSE); + } + disp = 0; + if ((!(np2cfg.LCD_MODE & 1)) && ((gdc.display & 7) < 3)) { + disp = 1; + } + if (dsync.scrnxextend != disp) { + dsync.scrnxextend = disp; + scrnmng_setextend(disp); + return(TRUE); + } + return(FALSE); +} + +BOOL dispsync_renewalhorizontal(void) { + + UINT hbp; + UINT cr; + UINT scrnxpos; + UINT scrnxmax; + + hbp = gdc.m.para[GDC_SYNC + 4] & 0x1f; + cr = gdc.m.para[GDC_SYNC + 1]; + + scrnxpos = 0; + if (hbp >= 7) { + scrnxpos = hbp - 7; + } + scrnxmax = cr + 2; + if ((scrnxpos + scrnxmax) > 80) { + scrnxmax = MIN(scrnxmax, 80); + scrnxpos = 80 - scrnxmax; + } + scrnxpos <<= 3; + scrnxmax <<= 3; + if ((dsync.scrnxpos != scrnxpos) || (dsync.scrnxmax != scrnxmax)) { + dsync.scrnxpos = scrnxpos; + dsync.scrnxmax = scrnxmax; + scrnmng_setwidth(scrnxpos, scrnxmax); + return(TRUE); + } + else { + return(FALSE); + } +} + +BOOL dispsync_renewalvertical(void) { + + UINT text_vbp; + UINT grph_vbp; + UINT textymax; + UINT grphymax; + UINT scrnymax; + + text_vbp = gdc.m.para[GDC_SYNC + 7] >> 2; + grph_vbp = gdc.s.para[GDC_SYNC + 7] >> 2; + if (text_vbp >= grph_vbp) { + text_vbp -= grph_vbp; + grph_vbp = 0; + } + else { + grph_vbp -= text_vbp; + text_vbp = 0; + } + + textymax = LOADINTELWORD(gdc.m.para + GDC_SYNC + 6); + textymax = ((textymax - 1) & 0x3ff) + 1; + textymax += text_vbp; + + grphymax = LOADINTELWORD(gdc.s.para + GDC_SYNC + 6); + grphymax = ((grphymax - 1) & 0x3ff) + 1; + grphymax += grph_vbp; + +#if defined(SUPPORT_CRT15KHZ) + if (gdc.crt15khz & 2) { + textymax *= 2; + grphymax *= 2; + } +#endif + if (textymax > SURFACE_HEIGHT) { + textymax = SURFACE_HEIGHT; + } + if (grphymax > SURFACE_HEIGHT) { + grphymax = SURFACE_HEIGHT; + } + if ((dsync.text_vbp == text_vbp) && (dsync.grph_vbp == grph_vbp) && + (dsync.textymax == textymax) && (dsync.grphymax == grphymax)) { + return(FALSE); + } + dsync.text_vbp = text_vbp; + dsync.grph_vbp = grph_vbp; + dsync.textymax = textymax; + dsync.grphymax = grphymax; + + scrnymax = MAX(grphymax, textymax); + scrnymax = (scrnymax + 7) & (~7); + if (dsync.scrnymax != scrnymax) { + dsync.scrnymax = scrnymax; + scrnmng_setheight(0, scrnymax); + } + + dsync.textvad = text_vbp * 640; + dsync.grphvad = grph_vbp * 640; + if (text_vbp) { + ZeroMemory(np2_tram, text_vbp * 640); + } + if (scrnymax - textymax) { + ZeroMemory(np2_tram + textymax * 640, (scrnymax - textymax) * 640); + } + if (grph_vbp) { + ZeroMemory(np2_vram[0], grph_vbp * 640); + ZeroMemory(np2_vram[1], grph_vbp * 640); + } + if (scrnymax - grphymax) { + ZeroMemory(np2_vram[0] + grphymax * 640, (scrnymax - grphymax) * 640); + ZeroMemory(np2_vram[1] + grphymax * 640, (scrnymax - grphymax) * 640); + } + return(TRUE); +} + diff --git a/vram/dispsync.h b/vram/dispsync.h old mode 100755 new mode 100644 index 6e916916..3e6bd4af --- a/vram/dispsync.h +++ b/vram/dispsync.h @@ -1,31 +1,31 @@ - -typedef struct { - UINT text_vbp; - UINT textymax; - UINT grph_vbp; - UINT grphymax; - - UINT scrnxpos; - UINT scrnxmax; - UINT scrnxextend; - UINT scrnymax; - UINT32 textvad; - UINT32 grphvad; -} DSYNC; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern DSYNC dsync; - -void dispsync_initialize(void); -BOOL dispsync_renewalmode(void); -BOOL dispsync_renewalhorizontal(void); -BOOL dispsync_renewalvertical(void); - -#ifdef __cplusplus -} -#endif - + +typedef struct { + UINT text_vbp; + UINT textymax; + UINT grph_vbp; + UINT grphymax; + + UINT scrnxpos; + UINT scrnxmax; + UINT scrnxextend; + UINT scrnymax; + UINT32 textvad; + UINT32 grphvad; +} DSYNC; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern DSYNC dsync; + +void dispsync_initialize(void); +BOOL dispsync_renewalmode(void); +BOOL dispsync_renewalhorizontal(void); +BOOL dispsync_renewalvertical(void); + +#ifdef __cplusplus +} +#endif + diff --git a/vram/makegrex.c b/vram/makegrex.c old mode 100755 new mode 100644 index f70d4a1a..4169e1c4 --- a/vram/makegrex.c +++ b/vram/makegrex.c @@ -1,321 +1,321 @@ -#include - -#if defined(SUPPORT_PC9821) - -#include -#include -#include -#include -#include -#include -#include - - -typedef struct { - UINT32 *vm; - UINT liney; - UINT pitch; -} _MKGREX, *MKGREX; - - -static BOOL grphput_indirty0(MKGREX mkgrex, int gpos) { - - _MKGREX mg; - UINT vad; - UINT remain; - UINT vc; - UINT32 *p; - UINT32 *pterm; - - mg = *mkgrex; - vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); - vad = LOW15(vad << 1); - remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); - remain = LOW14(remain) >> 4; - while(1) { - vc = vad; - p = mg.vm; - pterm = p + (80 * 2); - do { - if (vramupdate[vc] & 1) { - renewal_line[mg.liney] |= 1; - p[0] = *(UINT32 *)(vramex + (vc * 8) + 0); - p[1] = *(UINT32 *)(vramex + (vc * 8) + 4); - } - vc = LOW15(vc + 1); - p += 2; - } while(p < pterm); - mg.liney++; - if (mg.liney >= dsync.grphymax) { - return(TRUE); - } - mg.vm += 80*2; - remain--; - if (!remain) { - break; - } - vad = LOW15(vad + mg.pitch); - } - mkgrex->vm = mg.vm; - mkgrex->liney = mg.liney; - return(FALSE); -} - -static BOOL grphput_all0(MKGREX mkgrex, int gpos) { - - _MKGREX mg; - UINT vad; - UINT remain; - UINT vc; - UINT32 *p; - UINT32 *pterm; - - mg = *mkgrex; - vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); - vad = LOW15(vad << 1); - remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); - remain = LOW14(remain) >> 4; - while(1) { - vc = vad; - p = mg.vm; - pterm = p + (80 * 2); - do { - p[0] = *(UINT32 *)(vramex + (vc * 8) + 0); - p[1] = *(UINT32 *)(vramex + (vc * 8) + 4); - vc = LOW15(vc + 1); - p += 2; - } while(p < pterm); - renewal_line[mg.liney] |= 1; - mg.liney++; - if (mg.liney >= dsync.grphymax) { - return(TRUE); - } - mg.vm += 80*2; - remain--; - if (!remain) { - break; - } - vad = LOW15(vad + mg.pitch); - } - mkgrex->vm = mg.vm; - mkgrex->liney = mg.liney; - return(FALSE); -} - -static BOOL grphput_indirty1(MKGREX mkgrex, int gpos) { - - _MKGREX mg; - UINT vad; - UINT remain; - UINT vc; - UINT32 *p; - UINT32 *pterm; - - mg = *mkgrex; - vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); - vad = LOW15(vad << 1); - remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); - remain = LOW14(remain) >> 4; - while(1) { - vc = vad; - p = mg.vm; - pterm = p + (80 * 2); - do { - if (vramupdate[vc] & 2) { - renewal_line[mg.liney] |= 2; - p[0] = *(UINT32 *)(vramex + 0x40000 + (vc * 8) + 0); - p[1] = *(UINT32 *)(vramex + 0x40000 + (vc * 8) + 4); - } - vc = LOW15(vc + 1); - p += 2; - } while(p < pterm); - mg.liney++; - if (mg.liney >= dsync.grphymax) { - return(TRUE); - } - mg.vm += 80*2; - remain--; - if (!remain) { - break; - } - vad = LOW15(vad + mg.pitch); - } - mkgrex->vm = mg.vm; - mkgrex->liney = mg.liney; - return(FALSE); -} - -static BOOL grphput_all1(MKGREX mkgrex, int gpos) { - - _MKGREX mg; - UINT vad; - UINT remain; - UINT vc; - UINT32 *p; - UINT32 *pterm; - - mg = *mkgrex; - vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); - vad = LOW15(vad << 1); - remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); - remain = LOW14(remain) >> 4; - while(1) { - vc = vad; - p = mg.vm; - pterm = p + (80 * 2); - do { - p[0] = *(UINT32 *)(vramex + 0x40000 + (vc * 8) + 0); - p[1] = *(UINT32 *)(vramex + 0x40000 + (vc * 8) + 4); - vc = LOW15(vc + 1); - p += 2; - } while(p < pterm); - renewal_line[mg.liney] |= 2; - mg.liney++; - if (mg.liney >= dsync.grphymax) { - return(TRUE); - } - mg.vm += 80*2; - remain--; - if (!remain) { - break; - } - vad = LOW15(vad + mg.pitch); - } - mkgrex->vm = mg.vm; - mkgrex->liney = mg.liney; - return(FALSE); -} - - -// ---- all - -static BOOL grphput_indirty(MKGREX mkgrex, int gpos) { - - _MKGREX mg; - UINT vad; - UINT remain; - UINT vc; - UINT32 *p; - UINT32 *pterm; - - mg = *mkgrex; - vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); - vad = LOW16(vad << 1); - remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); - remain = LOW15(remain) >> 4; - while(1) { - vc = vad; - p = mg.vm; - pterm = p + (80 * 2); - do { - if (vramupdate[LOW15(vc)] & 3) { - renewal_line[mg.liney] |= 3; - p[0] = *(UINT32 *)(vramex + (vc * 8) + 0); - p[1] = *(UINT32 *)(vramex + (vc * 8) + 4); - } - vc = LOW16(vc + 1); - p += 2; - } while(p < pterm); - mg.liney++; - if (mg.liney >= dsync.grphymax) { - return(TRUE); - } - mg.vm += 80*2; - remain--; - if (!remain) { - break; - } - vad = LOW16(vad + mg.pitch); - } - mkgrex->vm = mg.vm; - mkgrex->liney = mg.liney; - return(FALSE); -} - -static BOOL grphput_all(MKGREX mkgrex, int gpos) { - - _MKGREX mg; - UINT vad; - UINT remain; - UINT vc; - UINT32 *p; - UINT32 *pterm; - - mg = *mkgrex; - vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); - vad = LOW16(vad << 1); - remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); - remain = LOW15(remain) >> 4; - while(1) { - vc = vad; - p = mg.vm; - pterm = p + (80 * 2); - do { - p[0] = *(UINT32 *)(vramex + (vc * 8) + 0); - p[1] = *(UINT32 *)(vramex + (vc * 8) + 4); - vc = LOW16(vc + 1); - p += 2; - } while(p < pterm); - renewal_line[mg.liney] |= 3; - mg.liney++; - if (mg.liney >= dsync.grphymax) { - return(TRUE); - } - mg.vm += 80*2; - remain--; - if (!remain) { - break; - } - vad = LOW16(vad + mg.pitch); - } - mkgrex->vm = mg.vm; - mkgrex->liney = mg.liney; - return(FALSE); -} - - -// ---- - -void VRAMCALL makegrphex(int page, int alldraw) { - - _MKGREX mg; - int i; - BOOL (*grphput)(MKGREX mkgrex, int gpos); - UINT32 mask; - - mg.pitch = gdc.s.para[GDC_PITCH]; - if (!(gdc.clock & 0x80)) { - mg.pitch <<= 1; - } - mg.pitch &= 0xfe; - mg.liney = dsync.grph_vbp; - - if (gdc.analog & 4) { - mg.vm = (UINT32 *)(np2_vram[0] + dsync.grphvad); - grphput = (alldraw)?grphput_all:grphput_indirty; - mask = ~0x03030303; - } - else if (!page) { - mg.vm = (UINT32 *)(np2_vram[0] + dsync.grphvad); - grphput = (alldraw)?grphput_all0:grphput_indirty0; - mask = ~0x01010101; - } - else { - mg.vm = (UINT32 *)(np2_vram[1] + dsync.grphvad); - grphput = (alldraw)?grphput_all1:grphput_indirty1; - mask = ~0x02020202; - } - while(1) { - if ((*grphput)(&mg, 0)) { - break; - } - if ((*grphput)(&mg, 4)) { - break; - } - } - for (i=0; i<0x8000; i+=4) { - *(UINT32 *)(vramupdate + i) &= mask; - } -} -#endif - +#include + +#if defined(SUPPORT_PC9821) + +#include +#include +#include +#include +#include +#include +#include + + +typedef struct { + UINT32 *vm; + UINT liney; + UINT pitch; +} _MKGREX, *MKGREX; + + +static BOOL grphput_indirty0(MKGREX mkgrex, int gpos) { + + _MKGREX mg; + UINT vad; + UINT remain; + UINT vc; + UINT32 *p; + UINT32 *pterm; + + mg = *mkgrex; + vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); + vad = LOW15(vad << 1); + remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); + remain = LOW14(remain) >> 4; + while(1) { + vc = vad; + p = mg.vm; + pterm = p + (80 * 2); + do { + if (vramupdate[vc] & 1) { + renewal_line[mg.liney] |= 1; + p[0] = *(UINT32 *)(vramex + (vc * 8) + 0); + p[1] = *(UINT32 *)(vramex + (vc * 8) + 4); + } + vc = LOW15(vc + 1); + p += 2; + } while(p < pterm); + mg.liney++; + if (mg.liney >= dsync.grphymax) { + return(TRUE); + } + mg.vm += 80*2; + remain--; + if (!remain) { + break; + } + vad = LOW15(vad + mg.pitch); + } + mkgrex->vm = mg.vm; + mkgrex->liney = mg.liney; + return(FALSE); +} + +static BOOL grphput_all0(MKGREX mkgrex, int gpos) { + + _MKGREX mg; + UINT vad; + UINT remain; + UINT vc; + UINT32 *p; + UINT32 *pterm; + + mg = *mkgrex; + vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); + vad = LOW15(vad << 1); + remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); + remain = LOW14(remain) >> 4; + while(1) { + vc = vad; + p = mg.vm; + pterm = p + (80 * 2); + do { + p[0] = *(UINT32 *)(vramex + (vc * 8) + 0); + p[1] = *(UINT32 *)(vramex + (vc * 8) + 4); + vc = LOW15(vc + 1); + p += 2; + } while(p < pterm); + renewal_line[mg.liney] |= 1; + mg.liney++; + if (mg.liney >= dsync.grphymax) { + return(TRUE); + } + mg.vm += 80*2; + remain--; + if (!remain) { + break; + } + vad = LOW15(vad + mg.pitch); + } + mkgrex->vm = mg.vm; + mkgrex->liney = mg.liney; + return(FALSE); +} + +static BOOL grphput_indirty1(MKGREX mkgrex, int gpos) { + + _MKGREX mg; + UINT vad; + UINT remain; + UINT vc; + UINT32 *p; + UINT32 *pterm; + + mg = *mkgrex; + vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); + vad = LOW15(vad << 1); + remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); + remain = LOW14(remain) >> 4; + while(1) { + vc = vad; + p = mg.vm; + pterm = p + (80 * 2); + do { + if (vramupdate[vc] & 2) { + renewal_line[mg.liney] |= 2; + p[0] = *(UINT32 *)(vramex + 0x40000 + (vc * 8) + 0); + p[1] = *(UINT32 *)(vramex + 0x40000 + (vc * 8) + 4); + } + vc = LOW15(vc + 1); + p += 2; + } while(p < pterm); + mg.liney++; + if (mg.liney >= dsync.grphymax) { + return(TRUE); + } + mg.vm += 80*2; + remain--; + if (!remain) { + break; + } + vad = LOW15(vad + mg.pitch); + } + mkgrex->vm = mg.vm; + mkgrex->liney = mg.liney; + return(FALSE); +} + +static BOOL grphput_all1(MKGREX mkgrex, int gpos) { + + _MKGREX mg; + UINT vad; + UINT remain; + UINT vc; + UINT32 *p; + UINT32 *pterm; + + mg = *mkgrex; + vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); + vad = LOW15(vad << 1); + remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); + remain = LOW14(remain) >> 4; + while(1) { + vc = vad; + p = mg.vm; + pterm = p + (80 * 2); + do { + p[0] = *(UINT32 *)(vramex + 0x40000 + (vc * 8) + 0); + p[1] = *(UINT32 *)(vramex + 0x40000 + (vc * 8) + 4); + vc = LOW15(vc + 1); + p += 2; + } while(p < pterm); + renewal_line[mg.liney] |= 2; + mg.liney++; + if (mg.liney >= dsync.grphymax) { + return(TRUE); + } + mg.vm += 80*2; + remain--; + if (!remain) { + break; + } + vad = LOW15(vad + mg.pitch); + } + mkgrex->vm = mg.vm; + mkgrex->liney = mg.liney; + return(FALSE); +} + + +// ---- all + +static BOOL grphput_indirty(MKGREX mkgrex, int gpos) { + + _MKGREX mg; + UINT vad; + UINT remain; + UINT vc; + UINT32 *p; + UINT32 *pterm; + + mg = *mkgrex; + vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); + vad = LOW16(vad << 1); + remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); + remain = LOW15(remain) >> 4; + while(1) { + vc = vad; + p = mg.vm; + pterm = p + (80 * 2); + do { + if (vramupdate[LOW15(vc)] & 3) { + renewal_line[mg.liney] |= 3; + p[0] = *(UINT32 *)(vramex + (vc * 8) + 0); + p[1] = *(UINT32 *)(vramex + (vc * 8) + 4); + } + vc = LOW16(vc + 1); + p += 2; + } while(p < pterm); + mg.liney++; + if (mg.liney >= dsync.grphymax) { + return(TRUE); + } + mg.vm += 80*2; + remain--; + if (!remain) { + break; + } + vad = LOW16(vad + mg.pitch); + } + mkgrex->vm = mg.vm; + mkgrex->liney = mg.liney; + return(FALSE); +} + +static BOOL grphput_all(MKGREX mkgrex, int gpos) { + + _MKGREX mg; + UINT vad; + UINT remain; + UINT vc; + UINT32 *p; + UINT32 *pterm; + + mg = *mkgrex; + vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); + vad = LOW16(vad << 1); + remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); + remain = LOW15(remain) >> 4; + while(1) { + vc = vad; + p = mg.vm; + pterm = p + (80 * 2); + do { + p[0] = *(UINT32 *)(vramex + (vc * 8) + 0); + p[1] = *(UINT32 *)(vramex + (vc * 8) + 4); + vc = LOW16(vc + 1); + p += 2; + } while(p < pterm); + renewal_line[mg.liney] |= 3; + mg.liney++; + if (mg.liney >= dsync.grphymax) { + return(TRUE); + } + mg.vm += 80*2; + remain--; + if (!remain) { + break; + } + vad = LOW16(vad + mg.pitch); + } + mkgrex->vm = mg.vm; + mkgrex->liney = mg.liney; + return(FALSE); +} + + +// ---- + +void VRAMCALL makegrphex(int page, int alldraw) { + + _MKGREX mg; + int i; + BOOL (*grphput)(MKGREX mkgrex, int gpos); + UINT32 mask; + + mg.pitch = gdc.s.para[GDC_PITCH]; + if (!(gdc.clock & 0x80)) { + mg.pitch <<= 1; + } + mg.pitch &= 0xfe; + mg.liney = dsync.grph_vbp; + + if (gdc.analog & 4) { + mg.vm = (UINT32 *)(np2_vram[0] + dsync.grphvad); + grphput = (alldraw)?grphput_all:grphput_indirty; + mask = ~0x03030303; + } + else if (!page) { + mg.vm = (UINT32 *)(np2_vram[0] + dsync.grphvad); + grphput = (alldraw)?grphput_all0:grphput_indirty0; + mask = ~0x01010101; + } + else { + mg.vm = (UINT32 *)(np2_vram[1] + dsync.grphvad); + grphput = (alldraw)?grphput_all1:grphput_indirty1; + mask = ~0x02020202; + } + while(1) { + if ((*grphput)(&mg, 0)) { + break; + } + if ((*grphput)(&mg, 4)) { + break; + } + } + for (i=0; i<0x8000; i+=4) { + *(UINT32 *)(vramupdate + i) &= mask; + } +} +#endif + diff --git a/vram/makegrex.h b/vram/makegrex.h old mode 100755 new mode 100644 index 06faf8cf..1322124a --- a/vram/makegrex.h +++ b/vram/makegrex.h @@ -1,15 +1,15 @@ - -#if defined(SUPPORT_PC9821) - -#ifdef __cplusplus -extern "C" { -#endif - -void VRAMCALL makegrphex(int page, int alldraw); - -#ifdef __cplusplus -} -#endif - -#endif - + +#if defined(SUPPORT_PC9821) + +#ifdef __cplusplus +extern "C" { +#endif + +void VRAMCALL makegrphex(int page, int alldraw); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/vram/makegrph.c b/vram/makegrph.c old mode 100755 new mode 100644 index e95ce37f..25f96cea --- a/vram/makegrph.c +++ b/vram/makegrph.c @@ -1,453 +1,453 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "makegrph.mcr" - - -typedef struct { - UINT32 *vm; - UINT liney; -// UINT pitch; - UINT lr; -} _MKGRPH, *MKGRPH; - - -#if (!defined(MEMOPTIMIZE)) || (MEMOPTIMIZE == 0) - - UINT32 grph_table[4*256*2]; - -void makegrph_initialize(void) { - - int i, j; - UINT8 bit; - UINT32 tmp; - - tmp = 0; - for (i=0; i<256; i++) { -#if defined(BYTESEX_LITTLE) - for (bit=1; bit<0x10; bit<<=1) -#else - for (bit=8; bit; bit>>=1) -#endif - { - tmp <<= 8; - if (i & bit) { - tmp++; - } - } - for (j=0; j<4; j++, tmp<<=1) { - grph_table[j*512+i*2+1] = tmp; - } -#if defined(BYTESEX_LITTLE) - for (; bit; bit<<=1) -#else - for (bit=0x80; bit & 0xf0; bit>>=1) -#endif - { - tmp <<= 8; - if (i & bit) { - tmp++; - } - } - for (j=0; j<4; j++, tmp<<=1) { - grph_table[j*512+i*2+0] = tmp; - } - } -} - -#elif (MEMOPTIMIZE == 1) - - UINT32 grph_table1[256*2]; - -void makegrph_initialize(void) { - - int i; - UINT8 bit; - UINT32 tmp; - - tmp = 0; - for (i=0; i<256; i++) { -#if defined(BYTESEX_LITTLE) - for (bit=1; bit<0x10; bit<<=1) -#else - for (bit=8; bit; bit>>=1) -#endif - { - tmp <<= 8; - if (i & bit) { - tmp++; - } - } - grph_table1[i*2+1] = tmp; -#if defined(BYTESEX_LITTLE) - for (; bit; bit<<=1) -#else - for (bit=0x80; bit & 0xf0; bit>>=1) -#endif - { - tmp <<= 8; - if (i & bit) { - tmp++; - } - } - grph_table1[i*2+0] = tmp; - } -} - -#else - - UINT32 grph_table0[16]; - -void makegrph_initialize(void) { - - int i; - UINT8 bit; - UINT32 tmp; - - tmp = 0; - for (i=0; i<16; i++) { -#if defined(BYTESEX_LITTLE) - for (bit=1; bit<0x10; bit<<=1) -#else - for (bit=8; bit; bit>>=1) -#endif - { - tmp <<= 8; - if (i & bit) { - tmp++; - } - } - grph_table0[i] = tmp; - } -} -#endif - - -static BOOL grphput_indirty0(MKGRPH mkgrph, int gpos) { - - _MKGRPH mg; - UINT vad; - UINT remain; - UINT pitch; - UINT mul; - UINT vc; - UINT32 *p; - UINT32 *pterm; - - mg = *mkgrph; - vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); - vad = LOW15(vad << 1); - remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); - pitch = gdc.s.para[GDC_PITCH]; - if (!(remain & (1 << 14))) { - pitch <<= 1; - } - pitch &= 0xfe; - remain = LOW14(remain) >> 4; - mul = mg.lr; - while(1) { - if ((!(mg.liney & 1)) || (!(gdc.mode1 & 0x10))) { - vc = vad; - p = mg.vm; - pterm = p + (80 * 2); - do { - if (vramupdate[vc] & 1) { - renewal_line[mg.liney] |= 1; - GRPHDATASET(p, vc); - } - vc = LOW15(vc + 1); - p += 2; - } while(p < pterm); - } - mg.liney++; - if (mg.liney >= dsync.grphymax) { - return(TRUE); - } - mg.vm += 80*2; - remain--; - if (!remain) { - break; - } - mul--; - if (!mul) { - mul = mg.lr; - vad = LOW15(vad + pitch); - } - } - mkgrph->vm = mg.vm; - mkgrph->liney = mg.liney; - return(FALSE); -} - -static BOOL grphput_indirty1(MKGRPH mkgrph, int gpos) { - - _MKGRPH mg; - UINT vad; - UINT remain; - UINT pitch; - UINT mul; - UINT vc; - UINT32 *p; - UINT32 *pterm; - - mg = *mkgrph; - vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); - vad = LOW15(vad << 1); - remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); - pitch = gdc.s.para[GDC_PITCH]; - if (!(remain & (1 << 14))) { - pitch <<= 1; - } - pitch &= 0xfe; - remain = LOW14(remain) >> 4; - mul = mg.lr; - while(1) { - if ((!(mg.liney & 1)) || (!(gdc.mode1 & 0x10))) { - vc = vad; - p = mg.vm; - pterm = p + (80 * 2); - do { - if (vramupdate[vc] & 2) { - renewal_line[mg.liney] |= 2; - GRPHDATASET(p, vc + VRAM_STEP); - } - vc = LOW15(vc + 1); - p += 2; - } while(p < pterm); - } - mg.liney++; - if (mg.liney >= dsync.grphymax) { - return(TRUE); - } - mg.vm += 80*2; - remain--; - if (!remain) { - break; - } - mul--; - if (!mul) { - mul = mg.lr; - vad = LOW15(vad + pitch); - } - } - mkgrph->vm = mg.vm; - mkgrph->liney = mg.liney; - return(FALSE); -} - -static BOOL grphput_all0(MKGRPH mkgrph, int gpos) { - - _MKGRPH mg; - UINT vad; - UINT remain; - UINT pitch; - UINT mul; - UINT vc; - UINT32 *p; - UINT32 *pterm; - - mg = *mkgrph; - vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); - vad = LOW15(vad << 1); - remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); - pitch = gdc.s.para[GDC_PITCH]; - if (!(remain & (1 << 14))) { - pitch <<= 1; - } - pitch &= 0xfe; - remain = LOW14(remain) >> 4; - mul = mg.lr; - while(1) { - if ((!(mg.liney & 1)) || (!(gdc.mode1 & 0x10))) { - vc = vad; - p = mg.vm; - pterm = p + (80 * 2); - do { - GRPHDATASET(p, vc); - vc = LOW15(vc + 1); - p += 2; - } while(p < pterm); - } - renewal_line[mg.liney] |= 1; - mg.liney++; - if (mg.liney >= dsync.grphymax) { - return(TRUE); - } - mg.vm += 80*2; - remain--; - if (!remain) { - break; - } - mul--; - if (!mul) { - mul = mg.lr; - vad = LOW15(vad + pitch); - } - } - mkgrph->vm = mg.vm; - mkgrph->liney = mg.liney; - return(FALSE); -} - -static BOOL grphput_all1(MKGRPH mkgrph, int gpos) { - - _MKGRPH mg; - UINT vad; - UINT remain; - UINT pitch; - UINT mul; - UINT vc; - UINT32 *p; - UINT32 *pterm; - - mg = *mkgrph; - vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); - vad = LOW15(vad << 1); - remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); - pitch = gdc.s.para[GDC_PITCH]; - if (!(remain & (1 << 14))) { - pitch <<= 1; - } - pitch &= 0xfe; - remain = LOW14(remain) >> 4; - mul = mg.lr; - while(1) { - if ((!(mg.liney & 1)) || (!(gdc.mode1 & 0x10))) { - vc = vad; - p = mg.vm; - pterm = p + (80 * 2); - do { - GRPHDATASET(p, vc + VRAM_STEP); - vc = LOW15(vc + 1); - p += 2; - } while(p < pterm); - } - renewal_line[mg.liney] |= 2; - mg.liney++; - if (mg.liney >= dsync.grphymax) { - return(TRUE); - } - mg.vm += 80*2; - remain--; - if (!remain) { - break; - } - mul--; - if (!mul) { - mul = mg.lr; - vad = LOW15(vad + pitch); - } - } - mkgrph->vm = mg.vm; - mkgrph->liney = mg.liney; - return(FALSE); -} - -void VRAMCALL makegrph(int page, int alldraw) { - - _MKGRPH mg; - int i; - -// mg.pitch = gdc.s.para[GDC_PITCH]; -// if (!(gdc.clock & 0x80)) { -// mg.pitch <<= 1; -// } -// mg.pitch &= 0xfe; - mg.lr = (gdc.s.para[GDC_CSRFORM] & 0x1f) + 1; - mg.liney = dsync.grph_vbp; - - if (!page) { - mg.vm = (UINT32 *)(np2_vram[0] + dsync.grphvad); - if (!alldraw) { - while(1) { - if (grphput_indirty0(&mg, 0)) { - break; - } - if (grphput_indirty0(&mg, 4)) { - break; - } - if (np2cfg.uPD72020) { - continue; - } - if (grphput_indirty0(&mg, 8)) { - break; - } - if (grphput_indirty0(&mg, 12)) { - break; - } - } - } - else { - while(1) { - if (grphput_all0(&mg, 0)) { - break; - } - if (grphput_all0(&mg, 4)) { - break; - } - if (np2cfg.uPD72020) { - continue; - } - if (grphput_all0(&mg, 8)) { - break; - } - if (grphput_all0(&mg, 12)) { - break; - } - } - } - for (i=0; i<0x8000; i+=4) { - *(UINT32 *)(vramupdate + i) &= ~0x01010101; - } - } - else { - mg.vm = (UINT32 *)(np2_vram[1] + dsync.grphvad); - if (!alldraw) { - while(1) { - if (grphput_indirty1(&mg, 0)) { - break; - } - if (grphput_indirty1(&mg, 4)) { - break; - } - if (np2cfg.uPD72020) { - continue; - } - if (grphput_indirty1(&mg, 8)) { - break; - } - if (grphput_indirty1(&mg, 12)) { - break; - } - } - } - else { - while(1) { - if (grphput_all1(&mg, 0)) { - break; - } - if (grphput_all1(&mg, 4)) { - break; - } - if (np2cfg.uPD72020) { - continue; - } - if (grphput_all1(&mg, 8)) { - break; - } - if (grphput_all1(&mg, 12)) { - break; - } - } - } - for (i=0; i<0x8000; i+=4) { - *(UINT32 *)(vramupdate + i) &= ~0x02020202; - } - } -} - +#include +#include +#include +#include +#include +#include +#include +#include +#include "makegrph.mcr" + + +typedef struct { + UINT32 *vm; + UINT liney; +// UINT pitch; + UINT lr; +} _MKGRPH, *MKGRPH; + + +#if (!defined(MEMOPTIMIZE)) || (MEMOPTIMIZE == 0) + + UINT32 grph_table[4*256*2]; + +void makegrph_initialize(void) { + + int i, j; + UINT8 bit; + UINT32 tmp; + + tmp = 0; + for (i=0; i<256; i++) { +#if defined(BYTESEX_LITTLE) + for (bit=1; bit<0x10; bit<<=1) +#else + for (bit=8; bit; bit>>=1) +#endif + { + tmp <<= 8; + if (i & bit) { + tmp++; + } + } + for (j=0; j<4; j++, tmp<<=1) { + grph_table[j*512+i*2+1] = tmp; + } +#if defined(BYTESEX_LITTLE) + for (; bit; bit<<=1) +#else + for (bit=0x80; bit & 0xf0; bit>>=1) +#endif + { + tmp <<= 8; + if (i & bit) { + tmp++; + } + } + for (j=0; j<4; j++, tmp<<=1) { + grph_table[j*512+i*2+0] = tmp; + } + } +} + +#elif (MEMOPTIMIZE == 1) + + UINT32 grph_table1[256*2]; + +void makegrph_initialize(void) { + + int i; + UINT8 bit; + UINT32 tmp; + + tmp = 0; + for (i=0; i<256; i++) { +#if defined(BYTESEX_LITTLE) + for (bit=1; bit<0x10; bit<<=1) +#else + for (bit=8; bit; bit>>=1) +#endif + { + tmp <<= 8; + if (i & bit) { + tmp++; + } + } + grph_table1[i*2+1] = tmp; +#if defined(BYTESEX_LITTLE) + for (; bit; bit<<=1) +#else + for (bit=0x80; bit & 0xf0; bit>>=1) +#endif + { + tmp <<= 8; + if (i & bit) { + tmp++; + } + } + grph_table1[i*2+0] = tmp; + } +} + +#else + + UINT32 grph_table0[16]; + +void makegrph_initialize(void) { + + int i; + UINT8 bit; + UINT32 tmp; + + tmp = 0; + for (i=0; i<16; i++) { +#if defined(BYTESEX_LITTLE) + for (bit=1; bit<0x10; bit<<=1) +#else + for (bit=8; bit; bit>>=1) +#endif + { + tmp <<= 8; + if (i & bit) { + tmp++; + } + } + grph_table0[i] = tmp; + } +} +#endif + + +static BOOL grphput_indirty0(MKGRPH mkgrph, int gpos) { + + _MKGRPH mg; + UINT vad; + UINT remain; + UINT pitch; + UINT mul; + UINT vc; + UINT32 *p; + UINT32 *pterm; + + mg = *mkgrph; + vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); + vad = LOW15(vad << 1); + remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); + pitch = gdc.s.para[GDC_PITCH]; + if (!(remain & (1 << 14))) { + pitch <<= 1; + } + pitch &= 0xfe; + remain = LOW14(remain) >> 4; + mul = mg.lr; + while(1) { + if ((!(mg.liney & 1)) || (!(gdc.mode1 & 0x10))) { + vc = vad; + p = mg.vm; + pterm = p + (80 * 2); + do { + if (vramupdate[vc] & 1) { + renewal_line[mg.liney] |= 1; + GRPHDATASET(p, vc); + } + vc = LOW15(vc + 1); + p += 2; + } while(p < pterm); + } + mg.liney++; + if (mg.liney >= dsync.grphymax) { + return(TRUE); + } + mg.vm += 80*2; + remain--; + if (!remain) { + break; + } + mul--; + if (!mul) { + mul = mg.lr; + vad = LOW15(vad + pitch); + } + } + mkgrph->vm = mg.vm; + mkgrph->liney = mg.liney; + return(FALSE); +} + +static BOOL grphput_indirty1(MKGRPH mkgrph, int gpos) { + + _MKGRPH mg; + UINT vad; + UINT remain; + UINT pitch; + UINT mul; + UINT vc; + UINT32 *p; + UINT32 *pterm; + + mg = *mkgrph; + vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); + vad = LOW15(vad << 1); + remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); + pitch = gdc.s.para[GDC_PITCH]; + if (!(remain & (1 << 14))) { + pitch <<= 1; + } + pitch &= 0xfe; + remain = LOW14(remain) >> 4; + mul = mg.lr; + while(1) { + if ((!(mg.liney & 1)) || (!(gdc.mode1 & 0x10))) { + vc = vad; + p = mg.vm; + pterm = p + (80 * 2); + do { + if (vramupdate[vc] & 2) { + renewal_line[mg.liney] |= 2; + GRPHDATASET(p, vc + VRAM_STEP); + } + vc = LOW15(vc + 1); + p += 2; + } while(p < pterm); + } + mg.liney++; + if (mg.liney >= dsync.grphymax) { + return(TRUE); + } + mg.vm += 80*2; + remain--; + if (!remain) { + break; + } + mul--; + if (!mul) { + mul = mg.lr; + vad = LOW15(vad + pitch); + } + } + mkgrph->vm = mg.vm; + mkgrph->liney = mg.liney; + return(FALSE); +} + +static BOOL grphput_all0(MKGRPH mkgrph, int gpos) { + + _MKGRPH mg; + UINT vad; + UINT remain; + UINT pitch; + UINT mul; + UINT vc; + UINT32 *p; + UINT32 *pterm; + + mg = *mkgrph; + vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); + vad = LOW15(vad << 1); + remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); + pitch = gdc.s.para[GDC_PITCH]; + if (!(remain & (1 << 14))) { + pitch <<= 1; + } + pitch &= 0xfe; + remain = LOW14(remain) >> 4; + mul = mg.lr; + while(1) { + if ((!(mg.liney & 1)) || (!(gdc.mode1 & 0x10))) { + vc = vad; + p = mg.vm; + pterm = p + (80 * 2); + do { + GRPHDATASET(p, vc); + vc = LOW15(vc + 1); + p += 2; + } while(p < pterm); + } + renewal_line[mg.liney] |= 1; + mg.liney++; + if (mg.liney >= dsync.grphymax) { + return(TRUE); + } + mg.vm += 80*2; + remain--; + if (!remain) { + break; + } + mul--; + if (!mul) { + mul = mg.lr; + vad = LOW15(vad + pitch); + } + } + mkgrph->vm = mg.vm; + mkgrph->liney = mg.liney; + return(FALSE); +} + +static BOOL grphput_all1(MKGRPH mkgrph, int gpos) { + + _MKGRPH mg; + UINT vad; + UINT remain; + UINT pitch; + UINT mul; + UINT vc; + UINT32 *p; + UINT32 *pterm; + + mg = *mkgrph; + vad = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 0); + vad = LOW15(vad << 1); + remain = LOADINTELWORD(gdc.s.para + GDC_SCROLL + gpos + 2); + pitch = gdc.s.para[GDC_PITCH]; + if (!(remain & (1 << 14))) { + pitch <<= 1; + } + pitch &= 0xfe; + remain = LOW14(remain) >> 4; + mul = mg.lr; + while(1) { + if ((!(mg.liney & 1)) || (!(gdc.mode1 & 0x10))) { + vc = vad; + p = mg.vm; + pterm = p + (80 * 2); + do { + GRPHDATASET(p, vc + VRAM_STEP); + vc = LOW15(vc + 1); + p += 2; + } while(p < pterm); + } + renewal_line[mg.liney] |= 2; + mg.liney++; + if (mg.liney >= dsync.grphymax) { + return(TRUE); + } + mg.vm += 80*2; + remain--; + if (!remain) { + break; + } + mul--; + if (!mul) { + mul = mg.lr; + vad = LOW15(vad + pitch); + } + } + mkgrph->vm = mg.vm; + mkgrph->liney = mg.liney; + return(FALSE); +} + +void VRAMCALL makegrph(int page, int alldraw) { + + _MKGRPH mg; + int i; + +// mg.pitch = gdc.s.para[GDC_PITCH]; +// if (!(gdc.clock & 0x80)) { +// mg.pitch <<= 1; +// } +// mg.pitch &= 0xfe; + mg.lr = (gdc.s.para[GDC_CSRFORM] & 0x1f) + 1; + mg.liney = dsync.grph_vbp; + + if (!page) { + mg.vm = (UINT32 *)(np2_vram[0] + dsync.grphvad); + if (!alldraw) { + while(1) { + if (grphput_indirty0(&mg, 0)) { + break; + } + if (grphput_indirty0(&mg, 4)) { + break; + } + if (np2cfg.uPD72020) { + continue; + } + if (grphput_indirty0(&mg, 8)) { + break; + } + if (grphput_indirty0(&mg, 12)) { + break; + } + } + } + else { + while(1) { + if (grphput_all0(&mg, 0)) { + break; + } + if (grphput_all0(&mg, 4)) { + break; + } + if (np2cfg.uPD72020) { + continue; + } + if (grphput_all0(&mg, 8)) { + break; + } + if (grphput_all0(&mg, 12)) { + break; + } + } + } + for (i=0; i<0x8000; i+=4) { + *(UINT32 *)(vramupdate + i) &= ~0x01010101; + } + } + else { + mg.vm = (UINT32 *)(np2_vram[1] + dsync.grphvad); + if (!alldraw) { + while(1) { + if (grphput_indirty1(&mg, 0)) { + break; + } + if (grphput_indirty1(&mg, 4)) { + break; + } + if (np2cfg.uPD72020) { + continue; + } + if (grphput_indirty1(&mg, 8)) { + break; + } + if (grphput_indirty1(&mg, 12)) { + break; + } + } + } + else { + while(1) { + if (grphput_all1(&mg, 0)) { + break; + } + if (grphput_all1(&mg, 4)) { + break; + } + if (np2cfg.uPD72020) { + continue; + } + if (grphput_all1(&mg, 8)) { + break; + } + if (grphput_all1(&mg, 12)) { + break; + } + } + } + for (i=0; i<0x8000; i+=4) { + *(UINT32 *)(vramupdate + i) &= ~0x02020202; + } + } +} + diff --git a/vram/makegrph.h b/vram/makegrph.h old mode 100755 new mode 100644 index c276afe6..9ab45d40 --- a/vram/makegrph.h +++ b/vram/makegrph.h @@ -1,18 +1,18 @@ - -enum { - GRPHXMAX = 80, - GRPHYMAX = 400 -}; - - -#ifdef __cplusplus -extern "C" { -#endif - -void makegrph_initialize(void); -void VRAMCALL makegrph(int page, int alldraw); - -#ifdef __cplusplus -} -#endif - + +enum { + GRPHXMAX = 80, + GRPHYMAX = 400 +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +void makegrph_initialize(void); +void VRAMCALL makegrph(int page, int alldraw); + +#ifdef __cplusplus +} +#endif + diff --git a/vram/makegrph.mcr b/vram/makegrph.mcr old mode 100755 new mode 100644 index 0c0bfb08..8afe73be --- a/vram/makegrph.mcr +++ b/vram/makegrph.mcr @@ -1,80 +1,80 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -#if (!defined(MEMOPTIMIZE)) || (MEMOPTIMIZE == 0) - -extern UINT32 grph_table[4*256*2]; - -#define GRPHDATASET(d, a) { \ - UINT8 dat; \ - UINT32 l32, r32; \ - dat = mem[(a) + VRAM_B]; \ - l32 = grph_table[dat*2 + 0*0x200 + 0]; \ - r32 = grph_table[dat*2 + 0*0x200 + 1]; \ - dat = mem[(a) + VRAM_R]; \ - l32 += grph_table[dat*2 + 1*0x200 + 0]; \ - r32 += grph_table[dat*2 + 1*0x200 + 1]; \ - dat = mem[(a) + VRAM_G]; \ - l32 += grph_table[dat*2 + 2*0x200 + 0]; \ - r32 += grph_table[dat*2 + 2*0x200 + 1]; \ - dat = mem[(a) + VRAM_E]; \ - l32 += grph_table[dat*2 + 3*0x200 + 0]; \ - r32 += grph_table[dat*2 + 3*0x200 + 1]; \ - (d)[0] = l32; \ - (d)[1] = r32; \ -} - -#elif (MEMOPTIMIZE == 1) // for Mac - -extern UINT32 grph_table1[256*2]; - -#define GRPHDATASET(d, a) { \ - UINT8 dat; \ - UINT32 l32, r32; \ - dat = mem[(a) + VRAM_B]; \ - l32 = grph_table1[dat*2 + 0]; \ - r32 = grph_table1[dat*2 + 1]; \ - dat = mem[(a) + VRAM_R]; \ - l32 += grph_table1[dat*2 + 0] << 1; \ - r32 += grph_table1[dat*2 + 1] << 1; \ - dat = mem[(a) + VRAM_G]; \ - l32 += grph_table1[dat*2 + 0] << 2; \ - r32 += grph_table1[dat*2 + 1] << 2; \ - dat = mem[(a) + VRAM_E]; \ - l32 += grph_table1[dat*2 + 0] << 3; \ - r32 += grph_table1[dat*2 + 1] << 3; \ - (d)[0] = l32; \ - (d)[1] = r32; \ -} - -#else // for ARM - -extern UINT32 grph_table0[16]; - -#define GRPHDATASET(d, a) { \ - UINT8 dat; \ - UINT32 l32, r32; \ - dat = mem[(a) + VRAM_B]; \ - l32 = grph_table0[dat >> 4]; \ - r32 = grph_table0[dat & 15]; \ - dat = mem[(a) + VRAM_R]; \ - l32 += grph_table0[dat >> 4] << 1; \ - r32 += grph_table0[dat & 15] << 1; \ - dat = mem[(a) + VRAM_G]; \ - l32 += grph_table0[dat >> 4] << 2; \ - r32 += grph_table0[dat & 15] << 2; \ - dat = mem[(a) + VRAM_E]; \ - l32 += grph_table0[dat >> 4] << 3; \ - r32 += grph_table0[dat & 15] << 3; \ - (d)[0] = l32; \ - (d)[1] = r32; \ -} - -#endif - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +#if (!defined(MEMOPTIMIZE)) || (MEMOPTIMIZE == 0) + +extern UINT32 grph_table[4*256*2]; + +#define GRPHDATASET(d, a) { \ + UINT8 dat; \ + UINT32 l32, r32; \ + dat = mem[(a) + VRAM_B]; \ + l32 = grph_table[dat*2 + 0*0x200 + 0]; \ + r32 = grph_table[dat*2 + 0*0x200 + 1]; \ + dat = mem[(a) + VRAM_R]; \ + l32 += grph_table[dat*2 + 1*0x200 + 0]; \ + r32 += grph_table[dat*2 + 1*0x200 + 1]; \ + dat = mem[(a) + VRAM_G]; \ + l32 += grph_table[dat*2 + 2*0x200 + 0]; \ + r32 += grph_table[dat*2 + 2*0x200 + 1]; \ + dat = mem[(a) + VRAM_E]; \ + l32 += grph_table[dat*2 + 3*0x200 + 0]; \ + r32 += grph_table[dat*2 + 3*0x200 + 1]; \ + (d)[0] = l32; \ + (d)[1] = r32; \ +} + +#elif (MEMOPTIMIZE == 1) // for Mac + +extern UINT32 grph_table1[256*2]; + +#define GRPHDATASET(d, a) { \ + UINT8 dat; \ + UINT32 l32, r32; \ + dat = mem[(a) + VRAM_B]; \ + l32 = grph_table1[dat*2 + 0]; \ + r32 = grph_table1[dat*2 + 1]; \ + dat = mem[(a) + VRAM_R]; \ + l32 += grph_table1[dat*2 + 0] << 1; \ + r32 += grph_table1[dat*2 + 1] << 1; \ + dat = mem[(a) + VRAM_G]; \ + l32 += grph_table1[dat*2 + 0] << 2; \ + r32 += grph_table1[dat*2 + 1] << 2; \ + dat = mem[(a) + VRAM_E]; \ + l32 += grph_table1[dat*2 + 0] << 3; \ + r32 += grph_table1[dat*2 + 1] << 3; \ + (d)[0] = l32; \ + (d)[1] = r32; \ +} + +#else // for ARM + +extern UINT32 grph_table0[16]; + +#define GRPHDATASET(d, a) { \ + UINT8 dat; \ + UINT32 l32, r32; \ + dat = mem[(a) + VRAM_B]; \ + l32 = grph_table0[dat >> 4]; \ + r32 = grph_table0[dat & 15]; \ + dat = mem[(a) + VRAM_R]; \ + l32 += grph_table0[dat >> 4] << 1; \ + r32 += grph_table0[dat & 15] << 1; \ + dat = mem[(a) + VRAM_G]; \ + l32 += grph_table0[dat >> 4] << 2; \ + r32 += grph_table0[dat & 15] << 2; \ + dat = mem[(a) + VRAM_E]; \ + l32 += grph_table0[dat >> 4] << 3; \ + r32 += grph_table0[dat & 15] << 3; \ + (d)[0] = l32; \ + (d)[1] = r32; \ +} + +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/vram/maketext.c b/vram/maketext.c old mode 100755 new mode 100644 index fd7ec3ca..8a0f82b1 --- a/vram/maketext.c +++ b/vram/maketext.c @@ -1,765 +1,765 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - TRAM_T tramflag; -static UINT32 text_table[512]; -static UINT32 text_tblx2[512][2]; - - -void maketext_initialize(void) { - - int i; - int j; - UINT8 bit; - - ZeroMemory(text_table, sizeof(text_table)); - for (i=0; i<8; i++) { - for (j=0; j<16; j++) { -#if defined(BYTESEX_LITTLE) - for (bit=1; bit<0x10; bit<<=1) -#elif defined(BYTESEX_BIG) - for (bit=8; bit; bit>>=1) -#endif - { - text_table[i*16+j] <<= 8; - text_table[i*16+j+128] <<= 8; - if (j & bit) { - text_table[i*16+j] |= (i+1) << 4; - } - else { - text_table[i*16+j+128] |= (i+1) << 4; - } - } - } - } - for (i=0; i<256; i++) { - text_table[i+256] = text_table[i ^ 0x80]; - } - for (i=0; i<512; i++) { -#if defined(BYTESEX_LITTLE) - text_tblx2[i][0] = (text_table[i] & 0x000000ff); - text_tblx2[i][0] |= (text_table[i] & 0x0000ffff) << 8; - text_tblx2[i][0] |= (text_table[i] & 0x0000ff00) << 16; - text_tblx2[i][1] = (text_table[i] & 0x00ff0000) >> 16; - text_tblx2[i][1] |= (text_table[i] & 0xffff0000) >> 8; - text_tblx2[i][1] |= (text_table[i] & 0xff000000); -#elif defined(BYTESEX_BIG) - text_tblx2[i][0] = (text_table[i] & 0xff000000); - text_tblx2[i][0] |= (text_table[i] & 0xffff0000) >> 8; - text_tblx2[i][0] |= (text_table[i] & 0x00ff0000) >> 16; - text_tblx2[i][1] = (text_table[i] & 0x0000ff00) << 16; - text_tblx2[i][1] |= (text_table[i] & 0x0000ffff) << 8; - text_tblx2[i][1] |= (text_table[i] & 0x000000ff); -#endif - } -} - -void maketext_reset(void) { - - ZeroMemory(&tramflag, sizeof(tramflag)); -} - -static UINT8 dirtyonblink(void) { - - UINT8 ret; - int i; - - ret = 0; - for (i=0; i<0x1000; i++) { - if (mem[0xa2000 + i*2] & TXTATR_BL) { - ret = 1; - tramupdate[i] |= 1; - } - } - return(ret); -} - -UINT8 maketext_curblink(void) { - - UINT8 ret; - UINT16 csrw; - - ret = 0; - if (tramflag.renewal & 1) { - tramflag.curdisp = tramflag.count & 1; - if (!(gdc.m.para[GDC_CSRFORM] & 0x80)) { - tramflag.curdisp = 0; - } - else if (gdc.m.para[GDC_CSRFORM+1] & 0x20) { - tramflag.curdisp = 1; - } - csrw = LOADINTELWORD(gdc.m.para + GDC_CSRW); - if ((tramflag.curdisp != tramflag.curdisplast) || - (tramflag.curpos != csrw)) { - if ((tramflag.curdisplast) && (tramflag.curpos < 0x1000)) { - tramupdate[tramflag.curpos] |= 1; - } - tramflag.curdisplast = tramflag.curdisp; - tramflag.curpos = csrw; - if ((tramflag.curdisplast) && (tramflag.curpos < 0x1000)) { - tramupdate[tramflag.curpos] |= 1; - } - ret = GDCSCRN_REDRAW; - } - } - if (tramflag.renewal & 2) { - tramflag.blinkdisp = ((tramflag.count & 3)?1:0); - if (tramflag.blink) { - tramflag.blink = dirtyonblink(); - if (tramflag.blink) { - ret = GDCSCRN_REDRAW; - } - } - } - tramflag.renewal = 0; - return(ret); -} - -void maketext(int text_renewal) { - - UINT8 multiple; - UINT8 TEXT_LR; - int TEXT_PL; - int TEXT_BL; - int TEXT_CL; - int TEXT_SUR; - int TEXT_SDR; - int topline; - int lines; - int nowline; - UINT8 wait2; - UINT pitch; - UINT csrw; - UINT esi; - UINT scroll; - int scrp; - UINT8 wait1; - UINT8 LRcnt; - BOOL reloadline; - int new_flag; - int cur_line; - int linecnt; - UINT8 *q; - UINT y; - UINT8 line_effect = 0; // for gcc - int x; - UINT32 bitmap[TEXTXMAX]; - UINT8 curx[TEXTXMAX+1]; - UINT16 color[TEXTXMAX]; - - if (text_renewal) { - tramflag.gaiji = 0; - } - - multiple = ((!(gdc.mode1 & 8)) && (!(gdc.crt15khz & 1)))?0x20:0x00; - TEXT_LR = gdc.m.para[GDC_CSRFORM] & 0x1f; - TEXT_PL = crtc.reg.pl; - TEXT_BL = crtc.reg.bl + 1; - TEXT_CL = crtc.reg.cl; - TEXT_SUR = crtc.reg.sur; - TEXT_SDR = -1; - if (TEXT_CL > 16) { - TEXT_CL = 16; - } - if (TEXT_PL >= 16) { - topline = TEXT_PL - 32; - lines = TEXT_BL; - } - else { - topline = TEXT_PL; - lines = TEXT_BL - topline; - if (lines <= 0) { - lines += 32; // 補正 - } - } - nowline = topline; - - wait2 = 0; - if (!TEXT_SUR) { - wait2 = crtc.reg.ssl; - TEXT_SDR = crtc.reg.sdr + 1; - } - else { - TEXT_SUR = 32 - TEXT_SUR; - } - - pitch = gdc.m.para[GDC_PITCH] & 0xfe; - csrw = LOADINTELWORD(gdc.m.para + GDC_CSRW); - esi = LOW12(LOADINTELWORD(gdc.m.para + GDC_SCROLL)); - scroll = LOADINTELWORD(gdc.m.para + GDC_SCROLL + 2); - scroll = LOW14(scroll) >> 4; - scrp = 0; - - wait1 = 0; - LRcnt = 0; - reloadline = FALSE; - new_flag = 0; - cur_line = -1; - linecnt = 0; - q = np2_tram + dsync.textvad; - for (y=dsync.text_vbp; y> 1; - if (curx[x] & TXTATR_RV) { // text reverse - color[x] |= 0x80; - } - if (kanji2nd) { - kanji2nd = FALSE; - bitmap[x] = lastbitp + 0x800; - curx[x-1] |= 0x80; - curx[x] |= curx[x-1] & 0x20; - } - else if (!(mem[0xa0001 + edi*2] & gdc.bitac)) { - gaiji1st = 0; - if (gdc.mode1 & 8) { - bitmap[x] = 0x80000 + - (mem[0xa0000 + edi*2] << 4); - if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { - bitmap[x] += 0x1000; - } - } - else { - bitmap[x] = 0x82000 + - (mem[0xa0000 + edi*2] << 4); - curx[x] |= multiple; // ver0.74 - if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { - bitmap[x] += 8; - } - } - } - else { - UINT kc; - kc = LOADINTELWORD(mem + 0xa0000 + edi*2); - bitmap[x] = (kc & 0x7f7f) << 4; - kc &= 0x7f; // ver0.78 - if ((kc == 0x56) || (kc == 0x57)) { - tramflag.gaiji = 1; - if ((gaiji1st) && - (bitmap[x] == (lastbitp & (~15)))) { - curx[x-1] |= 0x80; - } - bitmap[x] += gaiji1st; - gaiji1st ^= 0x800; - } - else { - gaiji1st = 0; - if ((kc < 0x09) || (kc >= 0x0c)) { - kanji2nd = TRUE; - } - } - if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { - curx[x] |= 0x20; - bitmap[x] += 8; - } - else if (!(gdc.mode1 & 8)) { - curx[x] |= multiple; - } - } - lastbitp = bitmap[x]; - if (!(curx[x] & TXTATR_ST)) { - bitmap[x] = 0; - } - else if (curx[x] & TXTATR_BL) { - tramflag.blink = 1; - if (!tramflag.blinkdisp) { - bitmap[x] = 0; - } - } - edi = LOW12(edi + 1); - } - if (!tramflag.curdisp) { - cur_line = -1; - } - } - esi = LOW12(esi + pitch); - } - - if ((!TEXT_SDR) && (nowline >= topline + crtc.reg.ssl)) { - nowline = topline; - TEXT_SDR--; - wait1 = crtc.reg.ssl; - } - - if (!wait2) { - if (new_flag) { - renewal_line[y] |= 4; - if (cur_line >= 0) { - if ((nowline >= (gdc.m.para[GDC_CSRFORM+1] & 0x1f)) && - (nowline <= (gdc.m.para[GDC_CSRFORM+2] >> 3))) { - color[cur_line] |= 256; - if (curx[cur_line] & 0x80) { - color[cur_line+1] |= 256; - } - } - else { - color[cur_line] &= ~(256); - if (curx[cur_line] & 0x80) { - color[cur_line+1] &= ~(256); - } - } - } - if ((nowline >= 0) && (nowline < TEXT_CL)) { - // width80 - for (x=0; x>= 1; - } - if(!fntline) { - hook_fontrom(bitmap[x] + (fntline & 0x0f)); - hf_codeul = 0; - } - data = fontrom[bitmap[x] + (fntline & 0x0f)]; - *(UINT32 *)(q+0) = text_table[color[x] + (data >> 4)]; - *(UINT32 *)(q+4) = text_table[color[x] + (data & 15)]; - q += 8; - } - } - else { - // width80 - for (x=0; x<(TEXTXMAX); x++) { - *(UINT32 *)(q+0) = text_table[color[x]]; - *(UINT32 *)(q+4) = text_table[color[x]]; - q += 8; - } - } - if ((line_effect & TXTATR_UL) && - ((nowline + 1) == lines)) { // アンダーライン位置 - // width80 - q -= TEXTXMAX * 8; - q += 4; - for (x=0; x<(TEXTXMAX-1); x++) { - if (curx[x] & TXTATR_UL) { - *(UINT32 *)(q+0) = text_table[(color[x] & 0x70) - + 0x0f]; - *(UINT32 *)(q+4) = text_table[(color[x+1] & 0x70) - + 0x0f]; - } - q += 8; - } - if (curx[TEXTXMAX-1] & TXTATR_UL) { - *(UINT32 *)q = text_table[(color[TEXTXMAX-1] & 0x70) - + 0x0f]; - } - q += 4; - } - if ((line_effect & TXTATR_VL) && (!(gdc.mode1 & 1))) { - // width80 - q -= TEXTXMAX * 8; - for (x=0; x> 4; - reloadline = TRUE; - } - } - else { - wait2--; - } - - nowline++; - if ((TEXT_SDR) && (nowline >= lines)) { - nowline = topline; - TEXT_SDR--; - if (++linecnt == TEXT_SUR) { - wait2 = crtc.reg.ssl; - TEXT_SDR = crtc.reg.sdr + 1; - } - } - } - ZeroMemory(tramupdate, sizeof(tramupdate)); -} - -void maketext40(int text_renewal) { - - UINT8 multiple; - UINT8 TEXT_LR; - int TEXT_PL; - int TEXT_BL; - int TEXT_CL; - int TEXT_SUR; - int TEXT_SDR; - int topline; - int lines; - int nowline; - UINT8 wait2; - UINT pitch; - UINT csrw; - UINT esi; - UINT scroll; - int scrp; - UINT8 wait1; - UINT8 LRcnt; - BOOL reloadline; - int new_flag; - int cur_line; - int linecnt; - UINT8 *q; - UINT y; - UINT8 line_effect = 0; // for gcc - int x; - UINT32 bitmap[TEXTXMAX]; - UINT8 curx[TEXTXMAX+1]; - UINT16 color[TEXTXMAX]; - - if (text_renewal) { - tramflag.gaiji = 0; - } - - multiple = ((!(gdc.mode1 & 8)) && (!(gdc.crt15khz & 1)))?0x20:0x00; - TEXT_LR = gdc.m.para[GDC_CSRFORM] & 0x1f; - TEXT_PL = crtc.reg.pl; - TEXT_BL = crtc.reg.bl + 1; - TEXT_CL = crtc.reg.cl; - TEXT_SUR = crtc.reg.sur; - TEXT_SDR = -1; - if (TEXT_CL > 16) { - TEXT_CL = 16; - } - if (TEXT_PL >= 16) { - topline = TEXT_PL - 32; - lines = TEXT_BL; - } - else { - topline = TEXT_PL; - lines = TEXT_BL - topline; - if (lines <= 0) { - lines += 32; // 補正 - } - } - nowline = topline; - - wait2 = 0; - if (!TEXT_SUR) { - wait2 = crtc.reg.ssl; - TEXT_SDR = crtc.reg.sdr + 1; - } - else { - TEXT_SUR = 32 - TEXT_SUR; - } - - pitch = gdc.m.para[GDC_PITCH] & 0xfe; - csrw = LOADINTELWORD(gdc.m.para + GDC_CSRW); - esi = LOW12(LOADINTELWORD(gdc.m.para + GDC_SCROLL)); - scroll = LOADINTELWORD(gdc.m.para + GDC_SCROLL + 2); - scroll = LOW14(scroll) >> 4; - scrp = 0; - - wait1 = 0; - LRcnt = 0; - reloadline = FALSE; - new_flag = 0; - cur_line = -1; - linecnt = 0; - q = np2_tram + dsync.textvad; - for (y=dsync.text_vbp; y> 1; - if (curx[x] & TXTATR_RV) { // text reverse - color[x] |= 0x80; - } - if (kanji2nd) { - kanji2nd = FALSE; - bitmap[x] = lastbitp + 0x800; - curx[x-1] |= 0x80; - curx[x] |= curx[x-1] & 0x20; - } - else if (!(mem[0xa0001 + edi*2] & gdc.bitac)) { - gaiji1st = 0; - if (gdc.mode1 & 8) { - bitmap[x] = 0x80000 + - (mem[0xa0000 + edi*2] << 4); - if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { - bitmap[x] += 0x1000; - } - } - else { - bitmap[x] = 0x82000 + - (mem[0xa0000 + edi*2] << 4); - curx[x] |= multiple; // ver0.74 - if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { - bitmap[x] += 8; - } - } - } - else { - UINT kc; - kc = LOADINTELWORD(mem + 0xa0000 + edi*2); - bitmap[x] = (kc & 0x7f7f) << 4; - kc &= 0x7f; // ver0.78 - if ((kc == 0x56) || (kc == 0x57)) { - tramflag.gaiji = 1; - if ((gaiji1st) && - (bitmap[x] == (lastbitp & (~15)))) { - curx[x-1] |= 0x80; - } - bitmap[x] += gaiji1st; - gaiji1st ^= 0x800; - } - else { - gaiji1st = 0; - if ((kc < 0x09) || (kc >= 0x0c)) { - kanji2nd = TRUE; - } - } - if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { - curx[x] |= 0x20; - bitmap[x] += 8; - } - else if (!(gdc.mode1 & 8)) { - curx[x] |= multiple; - } - } - lastbitp = bitmap[x]; - if (!(curx[x] & TXTATR_ST)) { - bitmap[x] = 0; - } - else if (curx[x] & TXTATR_BL) { - tramflag.blink = 1; - if (!tramflag.blinkdisp) { - bitmap[x] = 0; - } - } - edi = LOW12(edi + 2); // width40 - } - if (!tramflag.curdisp) { - cur_line = -1; - } - } - esi = LOW12(esi + pitch); - } - - if ((!TEXT_SDR) && (nowline >= topline + crtc.reg.ssl)) { - nowline = topline; - TEXT_SDR--; - wait1 = crtc.reg.ssl; - } - - if (!wait2) { - if (new_flag) { - renewal_line[y] |= 4; - if (cur_line >= 0) { - if ((nowline >= (gdc.m.para[GDC_CSRFORM+1] & 0x1f)) && - (nowline <= (gdc.m.para[GDC_CSRFORM+2] >> 3))) { - color[cur_line] |= 256; - if (curx[cur_line] & 0x80) { - color[cur_line+1] |= 256; - } - } - else { - color[cur_line] &= ~(256); - if (curx[cur_line] & 0x80) { - color[cur_line+1] &= ~(256); - } - } - } - if ((nowline >= 0) && (nowline < TEXT_CL)) { - // width40 - for (x=0; x<(TEXTXMAX/2); x++) { - int fntline; - UINT8 data; - fntline = nowline; - if (curx[x] & 0x20) { - fntline >>= 1; - } - if(!fntline) { - hook_fontrom(bitmap[x] + (fntline & 0x0f)); - hf_codeul = 0; - } - data = fontrom[bitmap[x] + (fntline & 0x0f)]; - *(UINT32 *)(q+ 0) = text_tblx2[color[x] + - (data>>4)][0]; - *(UINT32 *)(q+ 4) = text_tblx2[color[x] + - (data>>4)][1]; - *(UINT32 *)(q+ 8) = text_tblx2[color[x] + - (data&0xf)][0]; - *(UINT32 *)(q+12) = text_tblx2[color[x] + - (data&0xf)][1]; - q += 16; - } - } - else { - // width40 - for (x=0; x<(TEXTXMAX/2); x++) { - *(UINT32 *)(q+ 0) = text_table[color[x]]; - *(UINT32 *)(q+ 4) = text_table[color[x]]; - *(UINT32 *)(q+ 8) = text_table[color[x]]; - *(UINT32 *)(q+12) = text_table[color[x]]; - q += 16; - } - } - if ((line_effect & TXTATR_UL) && - ((nowline + 1) == lines)) { // アンダーライン位置 - // width40 - q -= TEXTXMAX * 8; - q += 4; - for (x=0; x<((TEXTXMAX/2)-1); x++) { - if (curx[x] & 8) { - *(UINT32 *)(q+ 0) = text_table[(color[x] & 0x70) - + 0x0f]; - *(UINT32 *)(q+ 4) = text_table[(color[x] & 0x70) - + 0x0f]; - *(UINT32 *)(q+ 8) = text_table[(color[x] & 0x70) - + 0x0f]; - *(UINT32 *)(q+12) = text_table[(color[x+1] & 0x70) - + 0x0f]; - } - q += 16; - } - if (curx[(TEXTXMAX/2)-1] & TXTATR_UL) { - *(UINT32 *)(q+0) = text_table[ - (color[TEXTXMAX-1] & 0x70) + 0x0f]; - *(UINT32 *)(q+4) = text_table[ - (color[TEXTXMAX-1] & 0x70) + 0x0f]; - *(UINT32 *)(q+8) = text_table[ - (color[TEXTXMAX-1] & 0x70) + 0x0f]; - } - q += 12; - } - if ((line_effect & TXTATR_VL) && (!(gdc.mode1 & 1))) { - // width40 - q -= TEXTXMAX * 8; - for (x=0; x<(TEXTXMAX/2); x++) { - if (curx[x] & TXTATR_VL) { - // text_table[] を 使ってないので注意 - *(q+ 4) |= (color[x] & 0x70) + 0x10; - *(q+12) |= (color[x] & 0x70) + 0x10; - } - q += 16; - } - } - } - else { - q += TEXTXMAX * 8; - } - y++; - if (!(--scroll)) { - scrp = (scrp + 4) & 0x0c; - esi = LOW12(LOADINTELWORD(gdc.m.para + GDC_SCROLL + scrp)); - scroll = LOADINTELWORD(gdc.m.para + GDC_SCROLL + scrp + 2); - scroll = LOW14(scroll) >> 4; - reloadline = TRUE; - } - } - else { - wait2--; - } - - nowline++; - if ((TEXT_SDR) && (nowline >= lines)) { - nowline = topline; - TEXT_SDR--; - if (++linecnt == TEXT_SUR) { - wait2 = crtc.reg.ssl; - TEXT_SDR = crtc.reg.sdr + 1; - } - } - } - ZeroMemory(tramupdate, sizeof(tramupdate)); -} - +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + TRAM_T tramflag; +static UINT32 text_table[512]; +static UINT32 text_tblx2[512][2]; + + +void maketext_initialize(void) { + + int i; + int j; + UINT8 bit; + + ZeroMemory(text_table, sizeof(text_table)); + for (i=0; i<8; i++) { + for (j=0; j<16; j++) { +#if defined(BYTESEX_LITTLE) + for (bit=1; bit<0x10; bit<<=1) +#elif defined(BYTESEX_BIG) + for (bit=8; bit; bit>>=1) +#endif + { + text_table[i*16+j] <<= 8; + text_table[i*16+j+128] <<= 8; + if (j & bit) { + text_table[i*16+j] |= (i+1) << 4; + } + else { + text_table[i*16+j+128] |= (i+1) << 4; + } + } + } + } + for (i=0; i<256; i++) { + text_table[i+256] = text_table[i ^ 0x80]; + } + for (i=0; i<512; i++) { +#if defined(BYTESEX_LITTLE) + text_tblx2[i][0] = (text_table[i] & 0x000000ff); + text_tblx2[i][0] |= (text_table[i] & 0x0000ffff) << 8; + text_tblx2[i][0] |= (text_table[i] & 0x0000ff00) << 16; + text_tblx2[i][1] = (text_table[i] & 0x00ff0000) >> 16; + text_tblx2[i][1] |= (text_table[i] & 0xffff0000) >> 8; + text_tblx2[i][1] |= (text_table[i] & 0xff000000); +#elif defined(BYTESEX_BIG) + text_tblx2[i][0] = (text_table[i] & 0xff000000); + text_tblx2[i][0] |= (text_table[i] & 0xffff0000) >> 8; + text_tblx2[i][0] |= (text_table[i] & 0x00ff0000) >> 16; + text_tblx2[i][1] = (text_table[i] & 0x0000ff00) << 16; + text_tblx2[i][1] |= (text_table[i] & 0x0000ffff) << 8; + text_tblx2[i][1] |= (text_table[i] & 0x000000ff); +#endif + } +} + +void maketext_reset(void) { + + ZeroMemory(&tramflag, sizeof(tramflag)); +} + +static UINT8 dirtyonblink(void) { + + UINT8 ret; + int i; + + ret = 0; + for (i=0; i<0x1000; i++) { + if (mem[0xa2000 + i*2] & TXTATR_BL) { + ret = 1; + tramupdate[i] |= 1; + } + } + return(ret); +} + +UINT8 maketext_curblink(void) { + + UINT8 ret; + UINT16 csrw; + + ret = 0; + if (tramflag.renewal & 1) { + tramflag.curdisp = tramflag.count & 1; + if (!(gdc.m.para[GDC_CSRFORM] & 0x80)) { + tramflag.curdisp = 0; + } + else if (gdc.m.para[GDC_CSRFORM+1] & 0x20) { + tramflag.curdisp = 1; + } + csrw = LOADINTELWORD(gdc.m.para + GDC_CSRW); + if ((tramflag.curdisp != tramflag.curdisplast) || + (tramflag.curpos != csrw)) { + if ((tramflag.curdisplast) && (tramflag.curpos < 0x1000)) { + tramupdate[tramflag.curpos] |= 1; + } + tramflag.curdisplast = tramflag.curdisp; + tramflag.curpos = csrw; + if ((tramflag.curdisplast) && (tramflag.curpos < 0x1000)) { + tramupdate[tramflag.curpos] |= 1; + } + ret = GDCSCRN_REDRAW; + } + } + if (tramflag.renewal & 2) { + tramflag.blinkdisp = ((tramflag.count & 3)?1:0); + if (tramflag.blink) { + tramflag.blink = dirtyonblink(); + if (tramflag.blink) { + ret = GDCSCRN_REDRAW; + } + } + } + tramflag.renewal = 0; + return(ret); +} + +void maketext(int text_renewal) { + + UINT8 multiple; + UINT8 TEXT_LR; + int TEXT_PL; + int TEXT_BL; + int TEXT_CL; + int TEXT_SUR; + int TEXT_SDR; + int topline; + int lines; + int nowline; + UINT8 wait2; + UINT pitch; + UINT csrw; + UINT esi; + UINT scroll; + int scrp; + UINT8 wait1; + UINT8 LRcnt; + BOOL reloadline; + int new_flag; + int cur_line; + int linecnt; + UINT8 *q; + UINT y; + UINT8 line_effect = 0; // for gcc + int x; + UINT32 bitmap[TEXTXMAX]; + UINT8 curx[TEXTXMAX+1]; + UINT16 color[TEXTXMAX]; + + if (text_renewal) { + tramflag.gaiji = 0; + } + + multiple = ((!(gdc.mode1 & 8)) && (!(gdc.crt15khz & 1)))?0x20:0x00; + TEXT_LR = gdc.m.para[GDC_CSRFORM] & 0x1f; + TEXT_PL = crtc.reg.pl; + TEXT_BL = crtc.reg.bl + 1; + TEXT_CL = crtc.reg.cl; + TEXT_SUR = crtc.reg.sur; + TEXT_SDR = -1; + if (TEXT_CL > 16) { + TEXT_CL = 16; + } + if (TEXT_PL >= 16) { + topline = TEXT_PL - 32; + lines = TEXT_BL; + } + else { + topline = TEXT_PL; + lines = TEXT_BL - topline; + if (lines <= 0) { + lines += 32; // 補正 + } + } + nowline = topline; + + wait2 = 0; + if (!TEXT_SUR) { + wait2 = crtc.reg.ssl; + TEXT_SDR = crtc.reg.sdr + 1; + } + else { + TEXT_SUR = 32 - TEXT_SUR; + } + + pitch = gdc.m.para[GDC_PITCH] & 0xfe; + csrw = LOADINTELWORD(gdc.m.para + GDC_CSRW); + esi = LOW12(LOADINTELWORD(gdc.m.para + GDC_SCROLL)); + scroll = LOADINTELWORD(gdc.m.para + GDC_SCROLL + 2); + scroll = LOW14(scroll) >> 4; + scrp = 0; + + wait1 = 0; + LRcnt = 0; + reloadline = FALSE; + new_flag = 0; + cur_line = -1; + linecnt = 0; + q = np2_tram + dsync.textvad; + for (y=dsync.text_vbp; y> 1; + if (curx[x] & TXTATR_RV) { // text reverse + color[x] |= 0x80; + } + if (kanji2nd) { + kanji2nd = FALSE; + bitmap[x] = lastbitp + 0x800; + curx[x-1] |= 0x80; + curx[x] |= curx[x-1] & 0x20; + } + else if (!(mem[0xa0001 + edi*2] & gdc.bitac)) { + gaiji1st = 0; + if (gdc.mode1 & 8) { + bitmap[x] = 0x80000 + + (mem[0xa0000 + edi*2] << 4); + if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { + bitmap[x] += 0x1000; + } + } + else { + bitmap[x] = 0x82000 + + (mem[0xa0000 + edi*2] << 4); + curx[x] |= multiple; // ver0.74 + if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { + bitmap[x] += 8; + } + } + } + else { + UINT kc; + kc = LOADINTELWORD(mem + 0xa0000 + edi*2); + bitmap[x] = (kc & 0x7f7f) << 4; + kc &= 0x7f; // ver0.78 + if ((kc == 0x56) || (kc == 0x57)) { + tramflag.gaiji = 1; + if ((gaiji1st) && + (bitmap[x] == (lastbitp & (~15)))) { + curx[x-1] |= 0x80; + } + bitmap[x] += gaiji1st; + gaiji1st ^= 0x800; + } + else { + gaiji1st = 0; + if ((kc < 0x09) || (kc >= 0x0c)) { + kanji2nd = TRUE; + } + } + if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { + curx[x] |= 0x20; + bitmap[x] += 8; + } + else if (!(gdc.mode1 & 8)) { + curx[x] |= multiple; + } + } + lastbitp = bitmap[x]; + if (!(curx[x] & TXTATR_ST)) { + bitmap[x] = 0; + } + else if (curx[x] & TXTATR_BL) { + tramflag.blink = 1; + if (!tramflag.blinkdisp) { + bitmap[x] = 0; + } + } + edi = LOW12(edi + 1); + } + if (!tramflag.curdisp) { + cur_line = -1; + } + } + esi = LOW12(esi + pitch); + } + + if ((!TEXT_SDR) && (nowline >= topline + crtc.reg.ssl)) { + nowline = topline; + TEXT_SDR--; + wait1 = crtc.reg.ssl; + } + + if (!wait2) { + if (new_flag) { + renewal_line[y] |= 4; + if (cur_line >= 0) { + if ((nowline >= (gdc.m.para[GDC_CSRFORM+1] & 0x1f)) && + (nowline <= (gdc.m.para[GDC_CSRFORM+2] >> 3))) { + color[cur_line] |= 256; + if (curx[cur_line] & 0x80) { + color[cur_line+1] |= 256; + } + } + else { + color[cur_line] &= ~(256); + if (curx[cur_line] & 0x80) { + color[cur_line+1] &= ~(256); + } + } + } + if ((nowline >= 0) && (nowline < TEXT_CL)) { + // width80 + for (x=0; x>= 1; + } + if(!fntline) { + hook_fontrom(bitmap[x] + (fntline & 0x0f)); + hf_codeul = 0; + } + data = fontrom[bitmap[x] + (fntline & 0x0f)]; + *(UINT32 *)(q+0) = text_table[color[x] + (data >> 4)]; + *(UINT32 *)(q+4) = text_table[color[x] + (data & 15)]; + q += 8; + } + } + else { + // width80 + for (x=0; x<(TEXTXMAX); x++) { + *(UINT32 *)(q+0) = text_table[color[x]]; + *(UINT32 *)(q+4) = text_table[color[x]]; + q += 8; + } + } + if ((line_effect & TXTATR_UL) && + ((nowline + 1) == lines)) { // アンダーライン位置 + // width80 + q -= TEXTXMAX * 8; + q += 4; + for (x=0; x<(TEXTXMAX-1); x++) { + if (curx[x] & TXTATR_UL) { + *(UINT32 *)(q+0) = text_table[(color[x] & 0x70) + + 0x0f]; + *(UINT32 *)(q+4) = text_table[(color[x+1] & 0x70) + + 0x0f]; + } + q += 8; + } + if (curx[TEXTXMAX-1] & TXTATR_UL) { + *(UINT32 *)q = text_table[(color[TEXTXMAX-1] & 0x70) + + 0x0f]; + } + q += 4; + } + if ((line_effect & TXTATR_VL) && (!(gdc.mode1 & 1))) { + // width80 + q -= TEXTXMAX * 8; + for (x=0; x> 4; + reloadline = TRUE; + } + } + else { + wait2--; + } + + nowline++; + if ((TEXT_SDR) && (nowline >= lines)) { + nowline = topline; + TEXT_SDR--; + if (++linecnt == TEXT_SUR) { + wait2 = crtc.reg.ssl; + TEXT_SDR = crtc.reg.sdr + 1; + } + } + } + ZeroMemory(tramupdate, sizeof(tramupdate)); +} + +void maketext40(int text_renewal) { + + UINT8 multiple; + UINT8 TEXT_LR; + int TEXT_PL; + int TEXT_BL; + int TEXT_CL; + int TEXT_SUR; + int TEXT_SDR; + int topline; + int lines; + int nowline; + UINT8 wait2; + UINT pitch; + UINT csrw; + UINT esi; + UINT scroll; + int scrp; + UINT8 wait1; + UINT8 LRcnt; + BOOL reloadline; + int new_flag; + int cur_line; + int linecnt; + UINT8 *q; + UINT y; + UINT8 line_effect = 0; // for gcc + int x; + UINT32 bitmap[TEXTXMAX]; + UINT8 curx[TEXTXMAX+1]; + UINT16 color[TEXTXMAX]; + + if (text_renewal) { + tramflag.gaiji = 0; + } + + multiple = ((!(gdc.mode1 & 8)) && (!(gdc.crt15khz & 1)))?0x20:0x00; + TEXT_LR = gdc.m.para[GDC_CSRFORM] & 0x1f; + TEXT_PL = crtc.reg.pl; + TEXT_BL = crtc.reg.bl + 1; + TEXT_CL = crtc.reg.cl; + TEXT_SUR = crtc.reg.sur; + TEXT_SDR = -1; + if (TEXT_CL > 16) { + TEXT_CL = 16; + } + if (TEXT_PL >= 16) { + topline = TEXT_PL - 32; + lines = TEXT_BL; + } + else { + topline = TEXT_PL; + lines = TEXT_BL - topline; + if (lines <= 0) { + lines += 32; // 補正 + } + } + nowline = topline; + + wait2 = 0; + if (!TEXT_SUR) { + wait2 = crtc.reg.ssl; + TEXT_SDR = crtc.reg.sdr + 1; + } + else { + TEXT_SUR = 32 - TEXT_SUR; + } + + pitch = gdc.m.para[GDC_PITCH] & 0xfe; + csrw = LOADINTELWORD(gdc.m.para + GDC_CSRW); + esi = LOW12(LOADINTELWORD(gdc.m.para + GDC_SCROLL)); + scroll = LOADINTELWORD(gdc.m.para + GDC_SCROLL + 2); + scroll = LOW14(scroll) >> 4; + scrp = 0; + + wait1 = 0; + LRcnt = 0; + reloadline = FALSE; + new_flag = 0; + cur_line = -1; + linecnt = 0; + q = np2_tram + dsync.textvad; + for (y=dsync.text_vbp; y> 1; + if (curx[x] & TXTATR_RV) { // text reverse + color[x] |= 0x80; + } + if (kanji2nd) { + kanji2nd = FALSE; + bitmap[x] = lastbitp + 0x800; + curx[x-1] |= 0x80; + curx[x] |= curx[x-1] & 0x20; + } + else if (!(mem[0xa0001 + edi*2] & gdc.bitac)) { + gaiji1st = 0; + if (gdc.mode1 & 8) { + bitmap[x] = 0x80000 + + (mem[0xa0000 + edi*2] << 4); + if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { + bitmap[x] += 0x1000; + } + } + else { + bitmap[x] = 0x82000 + + (mem[0xa0000 + edi*2] << 4); + curx[x] |= multiple; // ver0.74 + if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { + bitmap[x] += 8; + } + } + } + else { + UINT kc; + kc = LOADINTELWORD(mem + 0xa0000 + edi*2); + bitmap[x] = (kc & 0x7f7f) << 4; + kc &= 0x7f; // ver0.78 + if ((kc == 0x56) || (kc == 0x57)) { + tramflag.gaiji = 1; + if ((gaiji1st) && + (bitmap[x] == (lastbitp & (~15)))) { + curx[x-1] |= 0x80; + } + bitmap[x] += gaiji1st; + gaiji1st ^= 0x800; + } + else { + gaiji1st = 0; + if ((kc < 0x09) || (kc >= 0x0c)) { + kanji2nd = TRUE; + } + } + if ((curx[x] & TXTATR_BG) && (gdc.mode1 & 1)) { + curx[x] |= 0x20; + bitmap[x] += 8; + } + else if (!(gdc.mode1 & 8)) { + curx[x] |= multiple; + } + } + lastbitp = bitmap[x]; + if (!(curx[x] & TXTATR_ST)) { + bitmap[x] = 0; + } + else if (curx[x] & TXTATR_BL) { + tramflag.blink = 1; + if (!tramflag.blinkdisp) { + bitmap[x] = 0; + } + } + edi = LOW12(edi + 2); // width40 + } + if (!tramflag.curdisp) { + cur_line = -1; + } + } + esi = LOW12(esi + pitch); + } + + if ((!TEXT_SDR) && (nowline >= topline + crtc.reg.ssl)) { + nowline = topline; + TEXT_SDR--; + wait1 = crtc.reg.ssl; + } + + if (!wait2) { + if (new_flag) { + renewal_line[y] |= 4; + if (cur_line >= 0) { + if ((nowline >= (gdc.m.para[GDC_CSRFORM+1] & 0x1f)) && + (nowline <= (gdc.m.para[GDC_CSRFORM+2] >> 3))) { + color[cur_line] |= 256; + if (curx[cur_line] & 0x80) { + color[cur_line+1] |= 256; + } + } + else { + color[cur_line] &= ~(256); + if (curx[cur_line] & 0x80) { + color[cur_line+1] &= ~(256); + } + } + } + if ((nowline >= 0) && (nowline < TEXT_CL)) { + // width40 + for (x=0; x<(TEXTXMAX/2); x++) { + int fntline; + UINT8 data; + fntline = nowline; + if (curx[x] & 0x20) { + fntline >>= 1; + } + if(!fntline) { + hook_fontrom(bitmap[x] + (fntline & 0x0f)); + hf_codeul = 0; + } + data = fontrom[bitmap[x] + (fntline & 0x0f)]; + *(UINT32 *)(q+ 0) = text_tblx2[color[x] + + (data>>4)][0]; + *(UINT32 *)(q+ 4) = text_tblx2[color[x] + + (data>>4)][1]; + *(UINT32 *)(q+ 8) = text_tblx2[color[x] + + (data&0xf)][0]; + *(UINT32 *)(q+12) = text_tblx2[color[x] + + (data&0xf)][1]; + q += 16; + } + } + else { + // width40 + for (x=0; x<(TEXTXMAX/2); x++) { + *(UINT32 *)(q+ 0) = text_table[color[x]]; + *(UINT32 *)(q+ 4) = text_table[color[x]]; + *(UINT32 *)(q+ 8) = text_table[color[x]]; + *(UINT32 *)(q+12) = text_table[color[x]]; + q += 16; + } + } + if ((line_effect & TXTATR_UL) && + ((nowline + 1) == lines)) { // アンダーライン位置 + // width40 + q -= TEXTXMAX * 8; + q += 4; + for (x=0; x<((TEXTXMAX/2)-1); x++) { + if (curx[x] & 8) { + *(UINT32 *)(q+ 0) = text_table[(color[x] & 0x70) + + 0x0f]; + *(UINT32 *)(q+ 4) = text_table[(color[x] & 0x70) + + 0x0f]; + *(UINT32 *)(q+ 8) = text_table[(color[x] & 0x70) + + 0x0f]; + *(UINT32 *)(q+12) = text_table[(color[x+1] & 0x70) + + 0x0f]; + } + q += 16; + } + if (curx[(TEXTXMAX/2)-1] & TXTATR_UL) { + *(UINT32 *)(q+0) = text_table[ + (color[TEXTXMAX-1] & 0x70) + 0x0f]; + *(UINT32 *)(q+4) = text_table[ + (color[TEXTXMAX-1] & 0x70) + 0x0f]; + *(UINT32 *)(q+8) = text_table[ + (color[TEXTXMAX-1] & 0x70) + 0x0f]; + } + q += 12; + } + if ((line_effect & TXTATR_VL) && (!(gdc.mode1 & 1))) { + // width40 + q -= TEXTXMAX * 8; + for (x=0; x<(TEXTXMAX/2); x++) { + if (curx[x] & TXTATR_VL) { + // text_table[] を 使ってないので注意 + *(q+ 4) |= (color[x] & 0x70) + 0x10; + *(q+12) |= (color[x] & 0x70) + 0x10; + } + q += 16; + } + } + } + else { + q += TEXTXMAX * 8; + } + y++; + if (!(--scroll)) { + scrp = (scrp + 4) & 0x0c; + esi = LOW12(LOADINTELWORD(gdc.m.para + GDC_SCROLL + scrp)); + scroll = LOADINTELWORD(gdc.m.para + GDC_SCROLL + scrp + 2); + scroll = LOW14(scroll) >> 4; + reloadline = TRUE; + } + } + else { + wait2--; + } + + nowline++; + if ((TEXT_SDR) && (nowline >= lines)) { + nowline = topline; + TEXT_SDR--; + if (++linecnt == TEXT_SUR) { + wait2 = crtc.reg.ssl; + TEXT_SDR = crtc.reg.sdr + 1; + } + } + } + ZeroMemory(tramupdate, sizeof(tramupdate)); +} + diff --git a/vram/maketext.h b/vram/maketext.h old mode 100755 new mode 100644 index 724d56bc..566ebf3b --- a/vram/maketext.h +++ b/vram/maketext.h @@ -1,44 +1,44 @@ - -enum { - TEXTXMAX = 80, - TEXTYMAX = 400, - - TXTATR_ST = 0x01, // ~シークレット - TXTATR_BL = 0x02, // ブリンク - TXTATR_RV = 0x04, // リバース - TXTATR_UL = 0x08, // アンダーライン - TXTATR_VL = 0x10, // バーチカルライン - TXTATR_BG = 0x10, // 簡易グラフ - TEXTATR_RGB = 0xe0 // ビット並びはGRBの順 -}; - -typedef struct { - UINT8 timing; - UINT8 count; - UINT8 renewal; - UINT8 gaiji; - UINT8 attr; - UINT8 curdisp; - UINT8 curdisplast; - UINT8 blink; - UINT8 blinkdisp; - UINT16 curpos; -} TRAM_T; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern TRAM_T tramflag; - -void maketext_initialize(void); -void maketext_reset(void); -UINT8 maketext_curblink(void); -void maketext(int text_renewal); -void maketext40(int text_renewal); - -#ifdef __cplusplus -} -#endif - + +enum { + TEXTXMAX = 80, + TEXTYMAX = 400, + + TXTATR_ST = 0x01, // ~シークレット + TXTATR_BL = 0x02, // ブリンク + TXTATR_RV = 0x04, // リバース + TXTATR_UL = 0x08, // アンダーライン + TXTATR_VL = 0x10, // バーチカルライン + TXTATR_BG = 0x10, // 簡易グラフ + TEXTATR_RGB = 0xe0 // ビット並びはGRBの順 +}; + +typedef struct { + UINT8 timing; + UINT8 count; + UINT8 renewal; + UINT8 gaiji; + UINT8 attr; + UINT8 curdisp; + UINT8 curdisplast; + UINT8 blink; + UINT8 blinkdisp; + UINT16 curpos; +} TRAM_T; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern TRAM_T tramflag; + +void maketext_initialize(void); +void maketext_reset(void); +UINT8 maketext_curblink(void); +void maketext(int text_renewal); +void maketext40(int text_renewal); + +#ifdef __cplusplus +} +#endif + diff --git a/vram/maketgrp.c b/vram/maketgrp.c old mode 100755 new mode 100644 index cacb4270..d68bbfa2 --- a/vram/maketgrp.c +++ b/vram/maketgrp.c @@ -1,535 +1,535 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "makegrph.mcr" - - -// extern int displaymoder; -#define displaymoder dsync.scrnxextend - - -void maketextgrph(int plane, int text_renewal, int grph_renewal) { - - UINT8 TEXT_LR; - int TEXT_PL; - int TEXT_BL; - int TEXT_CL; - int TEXT_SUR; - int TEXT_SDR; - int topline; - int lines; - int nowline; - UINT8 wait2; - UINT m_pitch; - UINT esi; - UINT m_scr; - int m_scrp; - UINT s_pitch; - UINT ebp; - UINT s_scr; - int s_scrp; - int s_scrpmask; - UINT8 GRPH_LR; - UINT8 GRPH_LRcnt; - UINT32 ppage; - UINT32 gbit; - UINT ymax; - UINT8 *q; - UINT8 wait1; - UINT8 TEXT_LRcnt; - BOOL reloadline; - int new_flag; - int linecnt; - UINT y; - UINT edi; - UINT x; - int i; - UINT8 color[TEXTXMAX]; - UINT32 bit[160]; - - TEXT_LR = gdc.m.para[GDC_CSRFORM] & 0x1f; - TEXT_PL = crtc.reg.pl; - TEXT_BL = crtc.reg.bl + 1; - TEXT_CL = crtc.reg.cl; - TEXT_SUR = crtc.reg.sur; - TEXT_SDR = -1; - if (TEXT_CL > 16) { - TEXT_CL = 16; - } - if (TEXT_PL >= 16) { - topline = TEXT_PL - 32; - lines = TEXT_BL; - } - else { - topline = TEXT_PL; - lines = TEXT_BL - topline; - if (lines <= 0) { - lines += 32; - } - } - nowline = topline; - - wait2 = 0; - if (!TEXT_SUR) { - wait2 = crtc.reg.ssl; - TEXT_SDR = crtc.reg.sdr + 1; - } - else { - TEXT_SUR = 32 - TEXT_SUR; - } - - m_pitch = gdc.m.para[GDC_PITCH] & 0xfe; - esi = LOW12(LOADINTELWORD(gdc.m.para + GDC_SCROLL)); - m_scr = LOADINTELWORD(gdc.m.para + GDC_SCROLL + 2); - m_scr = LOW14(m_scr) >> 4; - m_scrp = 0; - - s_pitch = gdc.s.para[GDC_PITCH]; - if (!(gdc.clock & 0x80)) { - s_pitch <<= 1; - } - s_pitch &= 0xfe; - ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL); - ebp = LOW15(ebp << 1); - s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + 2); - s_scr = LOW14(s_scr) >> 4; - s_scrp = 0; - s_scrpmask = (np2cfg.uPD72020)?0x4:0xc; - - GRPH_LR = gdc.s.para[GDC_CSRFORM] & 0x1f; - GRPH_LRcnt = GRPH_LR; - - // グラフのほーが上… - if (dsync.text_vbp > dsync.grph_vbp) { - UINT remain; - remain = dsync.text_vbp - dsync.grph_vbp; - do { - if (!GRPH_LRcnt) { - GRPH_LRcnt = GRPH_LR; - s_scr--; - if (!s_scr) { - s_scrp = (s_scrp + 4) & s_scrpmask; - ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL + s_scrp); - ebp = LOW15(ebp << 1); - s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + - s_scrp + 2); - s_scr = LOW14(s_scr) >> 4; - } - else { - ebp = LOW15(ebp + s_pitch); - } - } - else { - GRPH_LRcnt--; - } - } while(--remain); - } - - ppage = (plane)?VRAM_STEP:0; - gbit = 0x01010101 << plane; - ymax = MIN(dsync.textymax, dsync.grphymax); - q = np2_vram[plane] + dsync.textvad; - wait1 = 0; - TEXT_LRcnt = 0; - reloadline = FALSE; - new_flag = 0; - linecnt = 0; - for (y=dsync.text_vbp; y> 5; - edi = LOW12(edi + 1); // width80 - } - esi = LOW12(esi + m_pitch); - } - - if ((!TEXT_SDR) && (nowline >= topline + crtc.reg.ssl)) { - nowline = topline; - TEXT_SDR--; - wait1 = crtc.reg.ssl; - } - - if (!wait2) { - int grph_new; - grph_new = 0; - if (y >= dsync.grph_vbp) { - grph_new = new_flag | grph_renewal; - if (!grph_new) { - UINT vc = ebp; - for (x=0; x> 4; - reloadline = TRUE; - } - if (!GRPH_LRcnt) { - GRPH_LRcnt = GRPH_LR; - s_scr--; - if (!s_scr) { - s_scrp = (s_scrp + 4) & s_scrpmask; - ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL + s_scrp); - ebp = LOW15(ebp << 1); - s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + - s_scrp + 2); - s_scr = LOW14(s_scr) >> 4; - } - else { - ebp = LOW15(ebp + s_pitch); - } - } - else { - GRPH_LRcnt--; - } - } - else { - wait2--; - } - - nowline++; - if ((TEXT_SDR) && (nowline >= lines)) { - nowline = topline; - TEXT_SDR--; - if (++linecnt == TEXT_SUR) { - wait2 = crtc.reg.ssl; - TEXT_SDR = crtc.reg.sdr + 1; - } - } - } - - gbit = ~gbit; - for (i=0; i<0x8000; i+=4) { - *(UINT32 *)(vramupdate + i) &= gbit; - } -} - -void maketextgrph40(int plane, int text_renewal, int grph_renewal) { - - UINT8 TEXT_LR; - int TEXT_PL; - int TEXT_BL; - int TEXT_CL; - int TEXT_SUR; - int TEXT_SDR; - int topline; - int lines; - int nowline = 0; - UINT8 wait2 = 0; - UINT m_pitch; - UINT esi; - UINT m_scr; - int m_scrp; - UINT s_pitch; - UINT ebp; - UINT s_scr; - int s_scrp; - int s_scrpmask; - UINT8 GRPH_LR; - UINT8 GRPH_LRcnt; - UINT32 ppage; - UINT32 gbit; - UINT ymax; - UINT8 *q; - UINT8 wait1; - UINT8 TEXT_LRcnt; - BOOL reloadline; - int new_flag; - int linecnt; - UINT y; - UINT edi; - UINT x; - int i; - UINT8 color[TEXTXMAX]; - UINT32 bit[160]; - - TEXT_LR = gdc.m.para[GDC_CSRFORM] & 0x1f; - TEXT_PL = crtc.reg.pl; - TEXT_BL = crtc.reg.bl + 1; - TEXT_CL = crtc.reg.cl; - TEXT_SUR = crtc.reg.sur; - TEXT_SDR = -1; - if (TEXT_CL > 16) { - TEXT_CL = 16; - } - if (TEXT_PL >= 16) { - topline = TEXT_PL - 32; - lines = TEXT_BL; - } - else { - topline = TEXT_PL; - lines = TEXT_BL - topline; - if (lines <= 0) { - lines += 32; - } - } - nowline = topline; - - wait2 = 0; - if (!TEXT_SUR) { - wait2 = crtc.reg.ssl; - TEXT_SDR = crtc.reg.sdr + 1; - } - else { - TEXT_SUR = 32 - TEXT_SUR; - } - - m_pitch = gdc.m.para[GDC_PITCH] & 0xfe; - esi = LOW12(LOADINTELWORD(gdc.m.para + GDC_SCROLL)); - m_scr = LOADINTELWORD(gdc.m.para + GDC_SCROLL + 2); - m_scr = LOW14(m_scr) >> 4; - m_scrp = 0; - - s_pitch = gdc.s.para[GDC_PITCH]; - if (!(gdc.clock & 0x80)) { - s_pitch <<= 1; - } - s_pitch &= 0xfe; - ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL); - ebp = LOW15(ebp << 1); - s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + 2); - s_scr = LOW14(s_scr) >> 4; - s_scrp = 0; - s_scrpmask = (np2cfg.uPD72020)?0x4:0xc; - - GRPH_LR = gdc.s.para[GDC_CSRFORM] & 0x1f; - GRPH_LRcnt = GRPH_LR; - - // グラフのほーが上… - if (dsync.text_vbp > dsync.grph_vbp) { - UINT remain; - remain = dsync.text_vbp - dsync.grph_vbp; - do { - if (!GRPH_LRcnt) { - GRPH_LRcnt = GRPH_LR; - s_scr--; - if (!s_scr) { - s_scrp = (s_scrp + 4) & s_scrpmask; - ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL + s_scrp); - ebp = LOW15(ebp << 1); - s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + - s_scrp + 2); - s_scr = LOW14(s_scr) >> 4; - } - else { - ebp = LOW15(ebp + s_pitch); - } - } - else { - GRPH_LRcnt--; - } - } while(--remain); - } - - ppage = (plane)?VRAM_STEP:0; - gbit = 0x01010101 << plane; - ymax = MIN(dsync.textymax, dsync.grphymax); - q = np2_vram[plane] + dsync.textvad; - wait1 = 0; - TEXT_LRcnt = 0; - reloadline = FALSE; - new_flag = 0; - linecnt = 0; - for (y=dsync.text_vbp; y> 5; - edi = LOW12(edi + 2); // width40 - } - esi = LOW12(esi + m_pitch); - } - - if ((!TEXT_SDR) && (nowline >= topline + crtc.reg.ssl)) { - nowline = topline; - TEXT_SDR--; - wait1 = crtc.reg.ssl; - } - - if (!wait2) { - int grph_new; - grph_new = 0; - if (y >= dsync.grph_vbp) { - grph_new = new_flag | grph_renewal; - if (!grph_new) { - UINT vc = ebp; - for (x=0; x> 4; - reloadline = TRUE; - } - if (!GRPH_LRcnt) { - GRPH_LRcnt = GRPH_LR; - s_scr--; - if (!s_scr) { - s_scrp = (s_scrp + 4) & s_scrpmask; - ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL + s_scrp); - ebp = LOW15(ebp << 1); - s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + - s_scrp + 2); - s_scr = LOW14(s_scr) >> 4; - } - else { - ebp = LOW15(ebp + s_pitch); - } - } - else { - GRPH_LRcnt--; - } - } - else { - wait2--; - } - - nowline++; - if ((TEXT_SDR) && (nowline >= lines)) { - nowline = topline; - TEXT_SDR--; - if (++linecnt == TEXT_SUR) { - wait2 = crtc.reg.ssl; - TEXT_SDR = crtc.reg.sdr + 1; - } - } - } - - gbit = ~gbit; - for (i=0; i<0x8000; i+=4) { - *(UINT32 *)(vramupdate + i) &= gbit; - } -} - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "makegrph.mcr" + + +// extern int displaymoder; +#define displaymoder dsync.scrnxextend + + +void maketextgrph(int plane, int text_renewal, int grph_renewal) { + + UINT8 TEXT_LR; + int TEXT_PL; + int TEXT_BL; + int TEXT_CL; + int TEXT_SUR; + int TEXT_SDR; + int topline; + int lines; + int nowline; + UINT8 wait2; + UINT m_pitch; + UINT esi; + UINT m_scr; + int m_scrp; + UINT s_pitch; + UINT ebp; + UINT s_scr; + int s_scrp; + int s_scrpmask; + UINT8 GRPH_LR; + UINT8 GRPH_LRcnt; + UINT32 ppage; + UINT32 gbit; + UINT ymax; + UINT8 *q; + UINT8 wait1; + UINT8 TEXT_LRcnt; + BOOL reloadline; + int new_flag; + int linecnt; + UINT y; + UINT edi; + UINT x; + int i; + UINT8 color[TEXTXMAX]; + UINT32 bit[160]; + + TEXT_LR = gdc.m.para[GDC_CSRFORM] & 0x1f; + TEXT_PL = crtc.reg.pl; + TEXT_BL = crtc.reg.bl + 1; + TEXT_CL = crtc.reg.cl; + TEXT_SUR = crtc.reg.sur; + TEXT_SDR = -1; + if (TEXT_CL > 16) { + TEXT_CL = 16; + } + if (TEXT_PL >= 16) { + topline = TEXT_PL - 32; + lines = TEXT_BL; + } + else { + topline = TEXT_PL; + lines = TEXT_BL - topline; + if (lines <= 0) { + lines += 32; + } + } + nowline = topline; + + wait2 = 0; + if (!TEXT_SUR) { + wait2 = crtc.reg.ssl; + TEXT_SDR = crtc.reg.sdr + 1; + } + else { + TEXT_SUR = 32 - TEXT_SUR; + } + + m_pitch = gdc.m.para[GDC_PITCH] & 0xfe; + esi = LOW12(LOADINTELWORD(gdc.m.para + GDC_SCROLL)); + m_scr = LOADINTELWORD(gdc.m.para + GDC_SCROLL + 2); + m_scr = LOW14(m_scr) >> 4; + m_scrp = 0; + + s_pitch = gdc.s.para[GDC_PITCH]; + if (!(gdc.clock & 0x80)) { + s_pitch <<= 1; + } + s_pitch &= 0xfe; + ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL); + ebp = LOW15(ebp << 1); + s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + 2); + s_scr = LOW14(s_scr) >> 4; + s_scrp = 0; + s_scrpmask = (np2cfg.uPD72020)?0x4:0xc; + + GRPH_LR = gdc.s.para[GDC_CSRFORM] & 0x1f; + GRPH_LRcnt = GRPH_LR; + + // グラフのほーが上… + if (dsync.text_vbp > dsync.grph_vbp) { + UINT remain; + remain = dsync.text_vbp - dsync.grph_vbp; + do { + if (!GRPH_LRcnt) { + GRPH_LRcnt = GRPH_LR; + s_scr--; + if (!s_scr) { + s_scrp = (s_scrp + 4) & s_scrpmask; + ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL + s_scrp); + ebp = LOW15(ebp << 1); + s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + + s_scrp + 2); + s_scr = LOW14(s_scr) >> 4; + } + else { + ebp = LOW15(ebp + s_pitch); + } + } + else { + GRPH_LRcnt--; + } + } while(--remain); + } + + ppage = (plane)?VRAM_STEP:0; + gbit = 0x01010101 << plane; + ymax = MIN(dsync.textymax, dsync.grphymax); + q = np2_vram[plane] + dsync.textvad; + wait1 = 0; + TEXT_LRcnt = 0; + reloadline = FALSE; + new_flag = 0; + linecnt = 0; + for (y=dsync.text_vbp; y> 5; + edi = LOW12(edi + 1); // width80 + } + esi = LOW12(esi + m_pitch); + } + + if ((!TEXT_SDR) && (nowline >= topline + crtc.reg.ssl)) { + nowline = topline; + TEXT_SDR--; + wait1 = crtc.reg.ssl; + } + + if (!wait2) { + int grph_new; + grph_new = 0; + if (y >= dsync.grph_vbp) { + grph_new = new_flag | grph_renewal; + if (!grph_new) { + UINT vc = ebp; + for (x=0; x> 4; + reloadline = TRUE; + } + if (!GRPH_LRcnt) { + GRPH_LRcnt = GRPH_LR; + s_scr--; + if (!s_scr) { + s_scrp = (s_scrp + 4) & s_scrpmask; + ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL + s_scrp); + ebp = LOW15(ebp << 1); + s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + + s_scrp + 2); + s_scr = LOW14(s_scr) >> 4; + } + else { + ebp = LOW15(ebp + s_pitch); + } + } + else { + GRPH_LRcnt--; + } + } + else { + wait2--; + } + + nowline++; + if ((TEXT_SDR) && (nowline >= lines)) { + nowline = topline; + TEXT_SDR--; + if (++linecnt == TEXT_SUR) { + wait2 = crtc.reg.ssl; + TEXT_SDR = crtc.reg.sdr + 1; + } + } + } + + gbit = ~gbit; + for (i=0; i<0x8000; i+=4) { + *(UINT32 *)(vramupdate + i) &= gbit; + } +} + +void maketextgrph40(int plane, int text_renewal, int grph_renewal) { + + UINT8 TEXT_LR; + int TEXT_PL; + int TEXT_BL; + int TEXT_CL; + int TEXT_SUR; + int TEXT_SDR; + int topline; + int lines; + int nowline = 0; + UINT8 wait2 = 0; + UINT m_pitch; + UINT esi; + UINT m_scr; + int m_scrp; + UINT s_pitch; + UINT ebp; + UINT s_scr; + int s_scrp; + int s_scrpmask; + UINT8 GRPH_LR; + UINT8 GRPH_LRcnt; + UINT32 ppage; + UINT32 gbit; + UINT ymax; + UINT8 *q; + UINT8 wait1; + UINT8 TEXT_LRcnt; + BOOL reloadline; + int new_flag; + int linecnt; + UINT y; + UINT edi; + UINT x; + int i; + UINT8 color[TEXTXMAX]; + UINT32 bit[160]; + + TEXT_LR = gdc.m.para[GDC_CSRFORM] & 0x1f; + TEXT_PL = crtc.reg.pl; + TEXT_BL = crtc.reg.bl + 1; + TEXT_CL = crtc.reg.cl; + TEXT_SUR = crtc.reg.sur; + TEXT_SDR = -1; + if (TEXT_CL > 16) { + TEXT_CL = 16; + } + if (TEXT_PL >= 16) { + topline = TEXT_PL - 32; + lines = TEXT_BL; + } + else { + topline = TEXT_PL; + lines = TEXT_BL - topline; + if (lines <= 0) { + lines += 32; + } + } + nowline = topline; + + wait2 = 0; + if (!TEXT_SUR) { + wait2 = crtc.reg.ssl; + TEXT_SDR = crtc.reg.sdr + 1; + } + else { + TEXT_SUR = 32 - TEXT_SUR; + } + + m_pitch = gdc.m.para[GDC_PITCH] & 0xfe; + esi = LOW12(LOADINTELWORD(gdc.m.para + GDC_SCROLL)); + m_scr = LOADINTELWORD(gdc.m.para + GDC_SCROLL + 2); + m_scr = LOW14(m_scr) >> 4; + m_scrp = 0; + + s_pitch = gdc.s.para[GDC_PITCH]; + if (!(gdc.clock & 0x80)) { + s_pitch <<= 1; + } + s_pitch &= 0xfe; + ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL); + ebp = LOW15(ebp << 1); + s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + 2); + s_scr = LOW14(s_scr) >> 4; + s_scrp = 0; + s_scrpmask = (np2cfg.uPD72020)?0x4:0xc; + + GRPH_LR = gdc.s.para[GDC_CSRFORM] & 0x1f; + GRPH_LRcnt = GRPH_LR; + + // グラフのほーが上… + if (dsync.text_vbp > dsync.grph_vbp) { + UINT remain; + remain = dsync.text_vbp - dsync.grph_vbp; + do { + if (!GRPH_LRcnt) { + GRPH_LRcnt = GRPH_LR; + s_scr--; + if (!s_scr) { + s_scrp = (s_scrp + 4) & s_scrpmask; + ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL + s_scrp); + ebp = LOW15(ebp << 1); + s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + + s_scrp + 2); + s_scr = LOW14(s_scr) >> 4; + } + else { + ebp = LOW15(ebp + s_pitch); + } + } + else { + GRPH_LRcnt--; + } + } while(--remain); + } + + ppage = (plane)?VRAM_STEP:0; + gbit = 0x01010101 << plane; + ymax = MIN(dsync.textymax, dsync.grphymax); + q = np2_vram[plane] + dsync.textvad; + wait1 = 0; + TEXT_LRcnt = 0; + reloadline = FALSE; + new_flag = 0; + linecnt = 0; + for (y=dsync.text_vbp; y> 5; + edi = LOW12(edi + 2); // width40 + } + esi = LOW12(esi + m_pitch); + } + + if ((!TEXT_SDR) && (nowline >= topline + crtc.reg.ssl)) { + nowline = topline; + TEXT_SDR--; + wait1 = crtc.reg.ssl; + } + + if (!wait2) { + int grph_new; + grph_new = 0; + if (y >= dsync.grph_vbp) { + grph_new = new_flag | grph_renewal; + if (!grph_new) { + UINT vc = ebp; + for (x=0; x> 4; + reloadline = TRUE; + } + if (!GRPH_LRcnt) { + GRPH_LRcnt = GRPH_LR; + s_scr--; + if (!s_scr) { + s_scrp = (s_scrp + 4) & s_scrpmask; + ebp = LOADINTELWORD(gdc.s.para + GDC_SCROLL + s_scrp); + ebp = LOW15(ebp << 1); + s_scr = LOADINTELWORD(gdc.s.para + GDC_SCROLL + + s_scrp + 2); + s_scr = LOW14(s_scr) >> 4; + } + else { + ebp = LOW15(ebp + s_pitch); + } + } + else { + GRPH_LRcnt--; + } + } + else { + wait2--; + } + + nowline++; + if ((TEXT_SDR) && (nowline >= lines)) { + nowline = topline; + TEXT_SDR--; + if (++linecnt == TEXT_SUR) { + wait2 = crtc.reg.ssl; + TEXT_SDR = crtc.reg.sdr + 1; + } + } + } + + gbit = ~gbit; + for (i=0; i<0x8000; i+=4) { + *(UINT32 *)(vramupdate + i) &= gbit; + } +} + diff --git a/vram/maketgrp.h b/vram/maketgrp.h old mode 100755 new mode 100644 index 481c62e9..4e1afa48 --- a/vram/maketgrp.h +++ b/vram/maketgrp.h @@ -1,12 +1,12 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void maketextgrph(int plane, int text_renewal, int grph_renewal); -void maketextgrph40(int plane, int text_renewal, int grph_renewal); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void maketextgrph(int plane, int text_renewal, int grph_renewal); +void maketextgrph40(int plane, int text_renewal, int grph_renewal); + +#ifdef __cplusplus +} +#endif + diff --git a/vram/palettes.c b/vram/palettes.c old mode 100755 new mode 100644 index ba54ac1d..26de35a2 --- a/vram/palettes.c +++ b/vram/palettes.c @@ -1,557 +1,557 @@ -#include -#include -#include -#include -#include -#include - - RGB32 np2_pal32[NP2PAL_MAX]; -#if defined(SUPPORT_16BPP) - RGB16 np2_pal16[NP2PAL_MAX]; -#endif - - PALEVENT palevent; -static RGB32 degpal1[8]; -static RGB32 degpal2[8]; -static UINT8 anapal1[16]; -static UINT8 anapal2[16]; - -static RGB32 lcdpal[15]; -static UINT8 lcdtbl[0x1000]; - UINT8 pal_monotable[16] = {0, 0, 0, 0, 1, 1, 1, 1, - 0, 0, 0, 0, 1, 1, 1, 1}; - -static const UINT8 lcdpal_a[27] = { 0, 1, 2, 3, 5, 2, 4, 4, 6, - 7, 9, 2,11,13, 2, 4, 4, 6, - 8, 8,10, 8, 8,10,12,12,14}; -static const UINT8 deftbl[4] = {0x04, 0x15, 0x26, 0x37}; - - -void pal_makegrad(RGB32 *pal, int pals, UINT32 bg, UINT32 fg) { - - int i; - - if (pals >= 2) { - pals--; - for (i=0; i<=pals; i++) { - pal[i].p.b = (UINT8) - ((((fg >> 0) & 0x0000ff) * i + - ((bg >> 0) & 0x0000ff) * (pals-i)) / pals); - pal[i].p.g = (UINT8) - ((((fg >> 8) & 0x0000ff) * i + - ((bg >> 8) & 0x0000ff) * (pals-i)) / pals); - pal[i].p.r = (UINT8) - ((((fg >> 16) & 0x0000ff) * i + - ((bg >> 16) & 0x0000ff) * (pals-i)) / pals); - pal[i].p.e = 0; - } - } -} - - -// ---- - -void pal_initlcdtable(void) { - - UINT i; - int j; - - for (i=0; i<0x1000; i++) { - j = 0; - if ((i & 0x00f) >= 0x004) { // b - j++; - if ((i & 0x00f) >= 0x00b) { - j++; - } - } - if ((i & 0x0f0) >= 0x040) { // r - j += 3; - if ((i & 0x0f0) >= 0x0b0) { - j += 3; - } - } - if ((i & 0xf00) >= 0x400) { // g - j += 9; - if ((i & 0xf00) >= 0xb00) { - j += 9; - } - } - lcdtbl[i] = lcdpal_a[j]; - } -} - -void pal_makelcdpal(void) { - - if (!(np2cfg.LCD_MODE & 2)) { - pal_makegrad(lcdpal, 15, np2cfg.BG_COLOR, np2cfg.FG_COLOR); - } - else { - pal_makegrad(lcdpal, 15, np2cfg.FG_COLOR, np2cfg.BG_COLOR); - } -} - -void pal_makeskiptable(void) { - - int i; - RGB32 pal; - UINT8 ana; - - for (i=0; i<8; i++) { - pal.p.b = (UINT8)(i & 1); - pal.p.r = (UINT8)((i >> 1) & 1); - pal.p.g = (UINT8)((i >> 2) & 1); - pal.p.e = 0; - degpal1[i].d = pal.d * 255; - degpal2[i].d = pal.d * np2cfg.skiplight; - } - for (i=0; i<16; i++) { - ana = (UINT8)(i * 0x11); - anapal1[i] = ana; - anapal2[i] = (UINT8)((np2cfg.skiplight * anapal1[i]) / 255); - } -} - - -// --------------------------------------------------------------------------- - -void pal_makeanalog(RGB32 *pal, UINT16 bit) { - - UINT i; - - for (i=0; ip.b & 15]; - np2_pal32[i+NP2PAL_GRPH].p.g = anapal1[pal->p.g & 15]; - np2_pal32[i+NP2PAL_GRPH].p.r = anapal1[pal->p.r & 15]; - if (np2cfg.skipline) { - np2_pal32[i+NP2PAL_SKIP].p.b = anapal2[pal->p.b & 15]; - np2_pal32[i+NP2PAL_SKIP].p.g = anapal2[pal->p.g & 15]; - np2_pal32[i+NP2PAL_SKIP].p.r = anapal2[pal->p.r & 15]; - } - } - } -#if defined(SUPPORT_16BPP) - if (scrnmng_getbpp() == 16) { - for (i=0; i> 4) & 7].d; - np2_pal32[i+NP2PAL_GRPH+ 4].d = - np2_pal32[i+NP2PAL_GRPH+12].d = - degpal1[paltbl[i] & 7].d; - if (np2cfg.skipline) { - np2_pal32[i+NP2PAL_SKIP+ 0].d = - np2_pal32[i+NP2PAL_SKIP+ 8].d = - degpal2[(paltbl[i] >> 4) & 7].d; - np2_pal32[i+NP2PAL_SKIP+ 4].d = - np2_pal32[i+NP2PAL_SKIP+12].d = - degpal2[paltbl[i] & 7].d; - } - } -#if defined(SUPPORT_16BPP) - if (scrnmng_getbpp() == 16) { - for (i=0; i<4; i++) { - np2_pal16[i+NP2PAL_GRPH+ 0] = - np2_pal16[i+NP2PAL_GRPH+ 8] = - scrnmng_makepal16(np2_pal32[i+NP2PAL_GRPH+0]); - np2_pal16[i+NP2PAL_GRPH+ 4] = - np2_pal16[i+NP2PAL_GRPH+12] = - scrnmng_makepal16(np2_pal32[i+NP2PAL_GRPH+4]); - } - if (np2cfg.skipline) { - for (i=0; i<4; i++) { - np2_pal16[i+NP2PAL_SKIP+ 0] = - np2_pal16[i+NP2PAL_SKIP+ 8] = - scrnmng_makepal16(np2_pal32[i+NP2PAL_SKIP+0]); - np2_pal16[i+NP2PAL_SKIP+ 4] = - np2_pal16[i+NP2PAL_SKIP+12] = - scrnmng_makepal16(np2_pal32[i+NP2PAL_SKIP+4]); - } - } - } -#endif -} - -static void pal_makedegital_mono(const UINT8 *paltbl) { - - UINT i; -#if defined(SUPPORT_16BPP) - RGB16 pal16; -#endif - - if ((np2cfg.LCD_MODE & 3) == 3) { - // LCD mode - for (i = 0; i < 8; i++) - { - np2_pal32[i + NP2PAL_GRPH].d = lcdpal[i].d; - } - np2_pal32[8 + NP2PAL_GRPH].d = 0xffffff; - if (np2cfg.skipline) { - for (i = 0; i < 8; i++) - { - np2_pal32[i + NP2PAL_SKIP].d = lcdpal[i].d; - } - } - } -#if defined(SUPPORT_16BPP) - if (scrnmng_getbpp() == 16) { - for (i = 0; i < 8; i++) - { - pal16 = scrnmng_makepal16(lcdpal[i]); - np2_pal16[i + NP2PAL_GRPH] = pal16; - } - np2_pal16[8 + NP2PAL_GRPH] = scrnmng_makepal16(np2_pal32[8 + NP2PAL_GRPH]); - if (np2cfg.skipline) - { - for (i = 0; i < 8; i++) - { - pal16 = scrnmng_makepal16(lcdpal[i]); - np2_pal16[i + NP2PAL_SKIP] = pal16; - } - } - } else -#endif - { - for (i = 0; i < 8; i++) - { - np2_pal32[i + NP2PAL_GRPH].d = degpal1[i].d; - } - np2_pal32[8 + NP2PAL_GRPH].d = 0x0000000; - if (np2cfg.skipline) { - for (i = 0; i < 8; i++) - { - np2_pal32[i + NP2PAL_SKIP].d = degpal1[i].d; - } - } -#if defined(SUPPORT_16BPP) - if (scrnmng_getbpp() == 16) - { - for (i = 0; i < 8; i++) - { - pal16 = scrnmng_makepal16(degpal1[i]); - np2_pal16[i + NP2PAL_GRPH] = pal16; - } - np2_pal16[8 + NP2PAL_GRPH] = scrnmng_makepal16(np2_pal32[8 + NP2PAL_GRPH]); - if (np2cfg.skipline) - { - for (i = 0; i < 8; i++) - { - pal16 = scrnmng_makepal16(degpal1[i]); - np2_pal16[i + NP2PAL_SKIP] = pal16; - } - } - } -#endif - } -} - -void pal_makeanalog_lcd(RGB32 *pal, UINT16 bit) { - - UINT i; - UINT j; - - for (i=0; ip.b & 15); - j |= (pal->p.r & 15) << 4; - j |= (pal->p.g & 15) << 8; - np2_pal32[i+NP2PAL_SKIP].d = - np2_pal32[i+NP2PAL_GRPH].d = lcdpal[lcdtbl[j]].d; - } - } -#if defined(SUPPORT_16BPP) - if (scrnmng_getbpp() == 16) { - for (i=0; i> 3) & 14].d; - np2_pal32[i+NP2PAL_GRPH+ 0].d = pal32; - np2_pal32[i+NP2PAL_GRPH+ 8].d = pal32; - pal32 = lcdpal[(paltbl[i] << 1) & 14].d; - np2_pal32[i+NP2PAL_GRPH+ 4].d = pal32; - np2_pal32[i+NP2PAL_GRPH+12].d = pal32; - if (np2cfg.skipline) { - pal32 = np2_pal32[i+NP2PAL_GRPH+ 0].d; - np2_pal32[i+NP2PAL_SKIP+ 0].d = pal32; - np2_pal32[i+NP2PAL_SKIP+ 8].d = pal32; - pal32 = np2_pal32[i+NP2PAL_GRPH+ 4].d; - np2_pal32[i+NP2PAL_SKIP+ 4].d = pal32; - np2_pal32[i+NP2PAL_SKIP+12].d = pal32; - } - } -#if defined(SUPPORT_16BPP) - if (scrnmng_getbpp() == 16) { - for (i=0; i<4; i++) { - pal16 = scrnmng_makepal16(np2_pal32[i+NP2PAL_GRPH+0]); - np2_pal16[i+NP2PAL_GRPH+ 0] = pal16; - np2_pal16[i+NP2PAL_GRPH+ 8] = pal16; - pal16 = scrnmng_makepal16(np2_pal32[i+NP2PAL_GRPH+4]); - np2_pal16[i+NP2PAL_GRPH+ 4] = pal16; - np2_pal16[i+NP2PAL_GRPH+12] = pal16; - } - if (np2cfg.skipline) { - for (i=0; i<4; i++) { - pal16 = np2_pal16[i+NP2PAL_GRPH+ 0]; - np2_pal16[i+NP2PAL_SKIP+ 0] = pal16; - np2_pal16[i+NP2PAL_SKIP+ 8] = pal16; - pal16 = np2_pal16[i+NP2PAL_GRPH+ 4]; - np2_pal16[i+NP2PAL_SKIP+ 4] = pal16; - np2_pal16[i+NP2PAL_SKIP+12] = pal16; - } - } - } -#endif -} - -static void pal_maketext(void) { - - UINT i; - UINT j; - UINT k; -#if defined(SUPPORT_16BPP) - RGB16 pal16; -#endif - - k = NP2PAL_TEXT2; - for (i=0; i<8; i++) { - np2_pal32[i+1+NP2PAL_TEXT].d = degpal1[i].d; - np2_pal32[i+1+NP2PAL_TEXT3].d = degpal1[i].d; - for (j=0; j +#include +#include +#include +#include +#include + + RGB32 np2_pal32[NP2PAL_MAX]; +#if defined(SUPPORT_16BPP) + RGB16 np2_pal16[NP2PAL_MAX]; +#endif + + PALEVENT palevent; +static RGB32 degpal1[8]; +static RGB32 degpal2[8]; +static UINT8 anapal1[16]; +static UINT8 anapal2[16]; + +static RGB32 lcdpal[15]; +static UINT8 lcdtbl[0x1000]; + UINT8 pal_monotable[16] = {0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 1, 1, 1}; + +static const UINT8 lcdpal_a[27] = { 0, 1, 2, 3, 5, 2, 4, 4, 6, + 7, 9, 2,11,13, 2, 4, 4, 6, + 8, 8,10, 8, 8,10,12,12,14}; +static const UINT8 deftbl[4] = {0x04, 0x15, 0x26, 0x37}; + + +void pal_makegrad(RGB32 *pal, int pals, UINT32 bg, UINT32 fg) { + + int i; + + if (pals >= 2) { + pals--; + for (i=0; i<=pals; i++) { + pal[i].p.b = (UINT8) + ((((fg >> 0) & 0x0000ff) * i + + ((bg >> 0) & 0x0000ff) * (pals-i)) / pals); + pal[i].p.g = (UINT8) + ((((fg >> 8) & 0x0000ff) * i + + ((bg >> 8) & 0x0000ff) * (pals-i)) / pals); + pal[i].p.r = (UINT8) + ((((fg >> 16) & 0x0000ff) * i + + ((bg >> 16) & 0x0000ff) * (pals-i)) / pals); + pal[i].p.e = 0; + } + } +} + + +// ---- + +void pal_initlcdtable(void) { + + UINT i; + int j; + + for (i=0; i<0x1000; i++) { + j = 0; + if ((i & 0x00f) >= 0x004) { // b + j++; + if ((i & 0x00f) >= 0x00b) { + j++; + } + } + if ((i & 0x0f0) >= 0x040) { // r + j += 3; + if ((i & 0x0f0) >= 0x0b0) { + j += 3; + } + } + if ((i & 0xf00) >= 0x400) { // g + j += 9; + if ((i & 0xf00) >= 0xb00) { + j += 9; + } + } + lcdtbl[i] = lcdpal_a[j]; + } +} + +void pal_makelcdpal(void) { + + if (!(np2cfg.LCD_MODE & 2)) { + pal_makegrad(lcdpal, 15, np2cfg.BG_COLOR, np2cfg.FG_COLOR); + } + else { + pal_makegrad(lcdpal, 15, np2cfg.FG_COLOR, np2cfg.BG_COLOR); + } +} + +void pal_makeskiptable(void) { + + int i; + RGB32 pal; + UINT8 ana; + + for (i=0; i<8; i++) { + pal.p.b = (UINT8)(i & 1); + pal.p.r = (UINT8)((i >> 1) & 1); + pal.p.g = (UINT8)((i >> 2) & 1); + pal.p.e = 0; + degpal1[i].d = pal.d * 255; + degpal2[i].d = pal.d * np2cfg.skiplight; + } + for (i=0; i<16; i++) { + ana = (UINT8)(i * 0x11); + anapal1[i] = ana; + anapal2[i] = (UINT8)((np2cfg.skiplight * anapal1[i]) / 255); + } +} + + +// --------------------------------------------------------------------------- + +void pal_makeanalog(RGB32 *pal, UINT16 bit) { + + UINT i; + + for (i=0; ip.b & 15]; + np2_pal32[i+NP2PAL_GRPH].p.g = anapal1[pal->p.g & 15]; + np2_pal32[i+NP2PAL_GRPH].p.r = anapal1[pal->p.r & 15]; + if (np2cfg.skipline) { + np2_pal32[i+NP2PAL_SKIP].p.b = anapal2[pal->p.b & 15]; + np2_pal32[i+NP2PAL_SKIP].p.g = anapal2[pal->p.g & 15]; + np2_pal32[i+NP2PAL_SKIP].p.r = anapal2[pal->p.r & 15]; + } + } + } +#if defined(SUPPORT_16BPP) + if (scrnmng_getbpp() == 16) { + for (i=0; i> 4) & 7].d; + np2_pal32[i+NP2PAL_GRPH+ 4].d = + np2_pal32[i+NP2PAL_GRPH+12].d = + degpal1[paltbl[i] & 7].d; + if (np2cfg.skipline) { + np2_pal32[i+NP2PAL_SKIP+ 0].d = + np2_pal32[i+NP2PAL_SKIP+ 8].d = + degpal2[(paltbl[i] >> 4) & 7].d; + np2_pal32[i+NP2PAL_SKIP+ 4].d = + np2_pal32[i+NP2PAL_SKIP+12].d = + degpal2[paltbl[i] & 7].d; + } + } +#if defined(SUPPORT_16BPP) + if (scrnmng_getbpp() == 16) { + for (i=0; i<4; i++) { + np2_pal16[i+NP2PAL_GRPH+ 0] = + np2_pal16[i+NP2PAL_GRPH+ 8] = + scrnmng_makepal16(np2_pal32[i+NP2PAL_GRPH+0]); + np2_pal16[i+NP2PAL_GRPH+ 4] = + np2_pal16[i+NP2PAL_GRPH+12] = + scrnmng_makepal16(np2_pal32[i+NP2PAL_GRPH+4]); + } + if (np2cfg.skipline) { + for (i=0; i<4; i++) { + np2_pal16[i+NP2PAL_SKIP+ 0] = + np2_pal16[i+NP2PAL_SKIP+ 8] = + scrnmng_makepal16(np2_pal32[i+NP2PAL_SKIP+0]); + np2_pal16[i+NP2PAL_SKIP+ 4] = + np2_pal16[i+NP2PAL_SKIP+12] = + scrnmng_makepal16(np2_pal32[i+NP2PAL_SKIP+4]); + } + } + } +#endif +} + +static void pal_makedegital_mono(const UINT8 *paltbl) { + + UINT i; +#if defined(SUPPORT_16BPP) + RGB16 pal16; +#endif + + if ((np2cfg.LCD_MODE & 3) == 3) { + // LCD mode + for (i = 0; i < 8; i++) + { + np2_pal32[i + NP2PAL_GRPH].d = lcdpal[i].d; + } + np2_pal32[8 + NP2PAL_GRPH].d = 0xffffff; + if (np2cfg.skipline) { + for (i = 0; i < 8; i++) + { + np2_pal32[i + NP2PAL_SKIP].d = lcdpal[i].d; + } + } + } +#if defined(SUPPORT_16BPP) + if (scrnmng_getbpp() == 16) { + for (i = 0; i < 8; i++) + { + pal16 = scrnmng_makepal16(lcdpal[i]); + np2_pal16[i + NP2PAL_GRPH] = pal16; + } + np2_pal16[8 + NP2PAL_GRPH] = scrnmng_makepal16(np2_pal32[8 + NP2PAL_GRPH]); + if (np2cfg.skipline) + { + for (i = 0; i < 8; i++) + { + pal16 = scrnmng_makepal16(lcdpal[i]); + np2_pal16[i + NP2PAL_SKIP] = pal16; + } + } + } else +#endif + { + for (i = 0; i < 8; i++) + { + np2_pal32[i + NP2PAL_GRPH].d = degpal1[i].d; + } + np2_pal32[8 + NP2PAL_GRPH].d = 0x0000000; + if (np2cfg.skipline) { + for (i = 0; i < 8; i++) + { + np2_pal32[i + NP2PAL_SKIP].d = degpal1[i].d; + } + } +#if defined(SUPPORT_16BPP) + if (scrnmng_getbpp() == 16) + { + for (i = 0; i < 8; i++) + { + pal16 = scrnmng_makepal16(degpal1[i]); + np2_pal16[i + NP2PAL_GRPH] = pal16; + } + np2_pal16[8 + NP2PAL_GRPH] = scrnmng_makepal16(np2_pal32[8 + NP2PAL_GRPH]); + if (np2cfg.skipline) + { + for (i = 0; i < 8; i++) + { + pal16 = scrnmng_makepal16(degpal1[i]); + np2_pal16[i + NP2PAL_SKIP] = pal16; + } + } + } +#endif + } +} + +void pal_makeanalog_lcd(RGB32 *pal, UINT16 bit) { + + UINT i; + UINT j; + + for (i=0; ip.b & 15); + j |= (pal->p.r & 15) << 4; + j |= (pal->p.g & 15) << 8; + np2_pal32[i+NP2PAL_SKIP].d = + np2_pal32[i+NP2PAL_GRPH].d = lcdpal[lcdtbl[j]].d; + } + } +#if defined(SUPPORT_16BPP) + if (scrnmng_getbpp() == 16) { + for (i=0; i> 3) & 14].d; + np2_pal32[i+NP2PAL_GRPH+ 0].d = pal32; + np2_pal32[i+NP2PAL_GRPH+ 8].d = pal32; + pal32 = lcdpal[(paltbl[i] << 1) & 14].d; + np2_pal32[i+NP2PAL_GRPH+ 4].d = pal32; + np2_pal32[i+NP2PAL_GRPH+12].d = pal32; + if (np2cfg.skipline) { + pal32 = np2_pal32[i+NP2PAL_GRPH+ 0].d; + np2_pal32[i+NP2PAL_SKIP+ 0].d = pal32; + np2_pal32[i+NP2PAL_SKIP+ 8].d = pal32; + pal32 = np2_pal32[i+NP2PAL_GRPH+ 4].d; + np2_pal32[i+NP2PAL_SKIP+ 4].d = pal32; + np2_pal32[i+NP2PAL_SKIP+12].d = pal32; + } + } +#if defined(SUPPORT_16BPP) + if (scrnmng_getbpp() == 16) { + for (i=0; i<4; i++) { + pal16 = scrnmng_makepal16(np2_pal32[i+NP2PAL_GRPH+0]); + np2_pal16[i+NP2PAL_GRPH+ 0] = pal16; + np2_pal16[i+NP2PAL_GRPH+ 8] = pal16; + pal16 = scrnmng_makepal16(np2_pal32[i+NP2PAL_GRPH+4]); + np2_pal16[i+NP2PAL_GRPH+ 4] = pal16; + np2_pal16[i+NP2PAL_GRPH+12] = pal16; + } + if (np2cfg.skipline) { + for (i=0; i<4; i++) { + pal16 = np2_pal16[i+NP2PAL_GRPH+ 0]; + np2_pal16[i+NP2PAL_SKIP+ 0] = pal16; + np2_pal16[i+NP2PAL_SKIP+ 8] = pal16; + pal16 = np2_pal16[i+NP2PAL_GRPH+ 4]; + np2_pal16[i+NP2PAL_SKIP+ 4] = pal16; + np2_pal16[i+NP2PAL_SKIP+12] = pal16; + } + } + } +#endif +} + +static void pal_maketext(void) { + + UINT i; + UINT j; + UINT k; +#if defined(SUPPORT_16BPP) + RGB16 pal16; +#endif + + k = NP2PAL_TEXT2; + for (i=0; i<8; i++) { + np2_pal32[i+1+NP2PAL_TEXT].d = degpal1[i].d; + np2_pal32[i+1+NP2PAL_TEXT3].d = degpal1[i].d; + for (j=0; j -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_VIDEOFILTER) -#include -#endif - -/** - * @brief The structure of screen saver - */ -struct tagScrnSave -{ - int width; - int height; - UINT pals; - UINT type; -}; - -#if defined(SUPPORT_PC9821) -#if defined(SUPPORT_VIDEOFILTER) -typedef uint32_t PALNUM; -#else -typedef unsigned short PALNUM; -#endif -#else -typedef unsigned char PALNUM; -#endif - -typedef union { - UINT32 d; - UINT8 rgb[4]; -} BMPPAL; - -typedef struct { - int width; - int height; - UINT pals; - UINT type; - BMPPAL pal[NP2PAL_MAX]; - PALNUM dat[SURFACE_WIDTH * SURFACE_HEIGHT]; -} SCRNDATA; - - -static void screenmix(PALNUM *dest, const UINT8 *src1, const UINT8 *src2, const int normaldisp) { - - int x, y; - int i; - - if (normaldisp) { - for (y = 0; y < SURFACE_HEIGHT; y++) { - for (x = 0; x < SURFACE_WIDTH - 1; x++) { - i = y * SURFACE_WIDTH + x; - dest[i] = src1[i + 1]; - } - } - for (i = 0; i < (SURFACE_WIDTH * SURFACE_HEIGHT); i++) { - dest[i] += src2[i] + NP2PAL_GRPH; - } - }else{ - for (i=0; i<(SURFACE_WIDTH * SURFACE_HEIGHT); i++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || src1[i]) { - dest[i] = src1[i]; - } else { - VideoFilter_PutDest(hVFMng1, &dest[i], i % SURFACE_WIDTH, i / SURFACE_WIDTH, 4); - } -#else - dest[i] = src1[i] + src2[i] + NP2PAL_GRPH; -#endif - } - } -} - -static void screenmix2(PALNUM *dest, const UINT8 *src1, const UINT8 *src2, const int normaldisp) { - - int x, y; - - if (normaldisp) { - for (y = 0; y < (SURFACE_HEIGHT / 2); y++) { - for (x = 0; x < SURFACE_WIDTH - 1; x++) { - dest[x] = src1[x + 1] + src2[x] + NP2PAL_GRPH; - } - dest[SURFACE_WIDTH - 1] = src2[SURFACE_WIDTH - 1] + NP2PAL_GRPH; - dest += SURFACE_WIDTH; - src1 += SURFACE_WIDTH; - src2 += SURFACE_WIDTH; - for (x = 0; x < SURFACE_WIDTH - 1; x++) { - dest[x] = (src1[x + 1] >> 4) + NP2PAL_TEXT; - } - dest[SURFACE_WIDTH - 1] = NP2PAL_TEXT; - dest += SURFACE_WIDTH; - src1 += SURFACE_WIDTH; - src2 += SURFACE_WIDTH; - } - } else { - for (y = 0; y < (SURFACE_HEIGHT / 2); y++) { - for (x = 0; x < SURFACE_WIDTH; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || src1[x]) { - dest[x] = src1[x]; - } else { - VideoFilter_PutDest(hVFMng1, &dest[x], x, y * 2, 4); - } -#else - dest[x] = src1[x] + src2[x] + NP2PAL_GRPH; -#endif - } - dest += SURFACE_WIDTH; - src1 += SURFACE_WIDTH; - src2 += SURFACE_WIDTH; - for (x = 0; x < SURFACE_WIDTH; x++) { - dest[x] = (src1[x] >> 4) + NP2PAL_TEXT; - } - dest += SURFACE_WIDTH; - src1 += SURFACE_WIDTH; - src2 += SURFACE_WIDTH; - } - } -} - -static void screenmix3(PALNUM *dest, const UINT8 *src1, const UINT8 *src2, const int normaldisp) { - - PALNUM c; - int x, y; - - if (normaldisp) { - for (y = 0; y < (SURFACE_HEIGHT / 2); y++) { - // dest == src1, dest == src2 の時があるので… - for (x = 0; x < SURFACE_WIDTH - 1; x++) { - c = (src1[x + 1 + SURFACE_WIDTH]) >> 4; - if (!c) { - c = src2[x] + NP2PAL_SKIP; - } - dest[x + SURFACE_WIDTH] = c; - dest[x] = src1[x + 1] + src2[x] + NP2PAL_GRPH; - } - c = src2[(SURFACE_WIDTH - 1)] + NP2PAL_SKIP; - dest[(SURFACE_WIDTH - 1) + SURFACE_WIDTH] = c; - dest[(SURFACE_WIDTH - 1)] = src2[(SURFACE_WIDTH - 1)] + NP2PAL_GRPH; - dest += SURFACE_WIDTH * 2; - src1 += SURFACE_WIDTH * 2; - src2 += SURFACE_WIDTH * 2; - } - }else{ - for (y = 0; y < (SURFACE_HEIGHT / 2); y++) { - // dest == src1, dest == src2 の時があるので… - for (x = 0; x < SURFACE_WIDTH; x++) { - c = (src1[x + SURFACE_WIDTH]) >> 4; - if (!c) { - c = src2[x] + NP2PAL_SKIP; - } - dest[x + SURFACE_WIDTH] = c; -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || src1[x]) { - dest[x] = src1[x] + NP2PAL_GRPH; - } else { - VideoFilter_PutDest(hVFMng1, &dest[x], x, y * 2, 4); - } -#else - dest[x] = src1[x] + src2[x] + NP2PAL_GRPH; -#endif -} - } - dest += SURFACE_WIDTH * 2; - src1 += SURFACE_WIDTH * 2; - src2 += SURFACE_WIDTH * 2; - } - } - -#if defined(SUPPORT_PC9821) -static void screenmix4(PALNUM *dest, const UINT8 *src1, const UINT8 *src2, const int normaldisp) { - - int x, y; - int i; - if (normaldisp) { - for (y = 0; y < SURFACE_HEIGHT; y++) { - for (x = 0; x < SURFACE_WIDTH; x++) { - i = y * SURFACE_WIDTH + x; - if (x < SURFACE_WIDTH - 1 && src1[i + 1]) { - dest[i] = (src1[i + 1] >> 4) + NP2PAL_TEXTEX; - } - else { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - dest[i] = src2[i] + NP2PAL_GRPHEX; - } else { - VideoFilter_PutDest(hVFMng1, &dest[i], i % SURFACE_WIDTH, i / SURFACE_WIDTH, 4); - } -#else - dest[i] = src2[i] + NP2PAL_GRPHEX; -#endif - } - } - } - } else { - for (i = 0; i < (SURFACE_WIDTH * SURFACE_HEIGHT); i++) { - if (src1[i]) { - dest[i] = (src1[i] >> 4) + NP2PAL_TEXTEX; - } - else { - dest[i] = src2[i] + NP2PAL_GRPHEX; - } - } - } -} -#endif - - -// ---- - -/** - * Create - * @return The handle of saver - */ -SCRNSAVE scrnsave_create(void) -{ - int width; - int height; - SCRNDATA *sd; - PALNUM *dat; - UINT scrnsize; - UINT8 *datanull; - UINT8 *datatext; - UINT8 *datagrph; - void (*mix)(PALNUM *dest, const UINT8 *src1, const UINT8 *src2, const int src1ofs); - PALNUM *s; - UINT pals; - PALNUM remap[NP2PAL_MAX]; - UINT8 remapflag[NP2PAL_MAX]; - int x; - int y; - PALNUM col; - BMPPAL curpal; - UINT pos; - uint8_t* dirty[SURFACE_HEIGHT]; - int normaldisp = 0; - - width = dsync.scrnxmax; - height = dsync.scrnymax; - if ((width <= 0) || (height <= 0)) { - goto ssg_err; - } - sd = (SCRNDATA *)_MALLOC(sizeof(SCRNDATA), "screen data"); - if (sd == NULL) { - goto ssg_err; - } - ZeroMemory(sd, sizeof(SCRNDATA)); - - normaldisp = (!(np2cfg.LCD_MODE & 1)) && ((gdc.display & 7) < 3) ? 1 : 0; - - memset(dirty, 1, SURFACE_HEIGHT); - - dat = sd->dat; - scrnsize = SURFACE_WIDTH * SURFACE_HEIGHT; - datanull = ((UINT8 *)dat) + (scrnsize * (sizeof(PALNUM) - 1)); - datatext = datanull; - datagrph = datanull; - if (gdcs.textdisp & 0x80) { - datatext = np2_tram; - } - if (gdcs.grphdisp & 0x80) { -#if defined(SUPPORT_PC9821) - if ((gdc.analog & 6) == 6) { - datagrph = np2_vram[0]; - } - else -#endif - datagrph = np2_vram[gdcs.disp]; - } -#if defined(SUPPORT_PC9821) - if (gdc.analog & 2) { - mix = screenmix4; - } - else -#endif - if (!(gdc.mode1 & 0x10)) { - mix = screenmix; - } - else if (!np2cfg.skipline) { - mix = screenmix2; - } - else { - mix = screenmix3; - } -#if defined(SUPPORT_VIDEOFILTER) - bVFEnable = VideoFilter_GetEnable(hVFMng1); - if(bVFEnable) { - VideoFilter_Import98(hVFMng1, datagrph, dirty, (gdc.analog & 2) ? TRUE : FALSE); - VideoFilter_Calc(hVFMng1); - } -#endif - (*mix)(sd->dat, datatext, datagrph, normaldisp); - -#if defined(SUPPORT_VIDEOFILTER) - sd->width = width; - sd->height = height; - sd->pals = 16777216; - sd->type = SCRNSAVE_24BIT; -#else - // パレット最適化 - s = sd->dat; - pals = 0; - ZeroMemory(remap, sizeof(remap)); - ZeroMemory(remapflag, sizeof(remapflag)); - for (y=0; ypal[pos].d == curpal.d) { - break; - } - } - if (pos >= pals) { - sd->pal[pos].d = curpal.d; - pals++; - } - remap[col] = (PALNUM)pos; - } - s[x] = remap[col]; - } - s += SURFACE_WIDTH; - } - sd->width = width; - sd->height = height; - sd->pals = pals; - if (pals <= 2) { - sd->type = SCRNSAVE_1BIT; - } - else if (pals <= 16) { - sd->type = SCRNSAVE_4BIT; - } - else if (pals <= 256) { - sd->type = SCRNSAVE_8BIT; - } - else { - sd->type = SCRNSAVE_24BIT; - } -#endif - return((SCRNSAVE)sd); - -ssg_err: - return(NULL); -} - -/** - * Destroy - * @param[in] hdl The handle of saver - */ -void scrnsave_destroy(SCRNSAVE hdl) -{ - if (hdl) - { - _MFREE(hdl); - } -} - -/** - * Get BPP - * @param[in] hdl The handle of saver - * @return bpp - */ -int scrnsave_gettype(SCRNSAVE hdl) -{ - int ret = 0; - - if (hdl) - { - ret = hdl->type; - } - return ret; -} - -// ---- BMP - -BRESULT scrnsave_writebmp(SCRNSAVE hdl, const OEMCHAR *filename, UINT flag) { - -const SCRNDATA *sd; - FILEH fh; - BMPDATA bd; - UINT type; - UINT palsize; - BMPFILE bf; - UINT pos; - BMPINFO bi; - UINT8 palwork[1024]; - UINT align; - UINT8 *work; -const PALNUM *s; - int r; - int x; - BMPPAL curpal; - - (void)flag; - - if (hdl == NULL) { - goto sswb_err1; - } - sd = (SCRNDATA *)hdl; - - fh = file_create(filename); - if (fh == FILEH_INVALID) { - goto sswb_err1; - } - - bd.width = sd->width; - bd.height = sd->height; - if (sd->pals <= 2) { - type = SCRNSAVE_1BIT; - bd.bpp = 1; - palsize = 4 << 1; - } - else if (sd->pals <= 16) { - type = SCRNSAVE_4BIT; - bd.bpp = 4; - palsize = 4 << 4; - } - else if (sd->pals <= 256) { - type = SCRNSAVE_8BIT; - bd.bpp = 8; - palsize = 4 << 8; - } - else { - type = SCRNSAVE_24BIT; - bd.bpp = 24; - palsize = 0; - } - - // Bitmap File - ZeroMemory(&bf, sizeof(bf)); - bf.bfType[0] = 'B'; - bf.bfType[1] = 'M'; - pos = sizeof(BMPFILE) + sizeof(BMPINFO) + palsize; - STOREINTELDWORD(bf.bfOffBits, pos); - - // Bitmap Info - bmpdata_setinfo(&bi, &bd); - STOREINTELDWORD(bi.biClrImportant, sd->pals); - align = bmpdata_getalign(&bi); - - // Bitmap File (size) - STOREINTELDWORD(bf.bfSize, (sizeof(BMPFILE) + sizeof(BMPINFO) + palsize + bmpdata_getalign(&bi) * bd.height)); - - if (file_write(fh, &bf, sizeof(bf)) != sizeof(bf)) { - goto sswb_err2; - } - if (file_write(fh, &bi, sizeof(bi)) != sizeof(bi)) { - goto sswb_err2; - } - - if (palsize) { - ZeroMemory(palwork, palsize); - CopyMemory(palwork, sd->pal, sd->pals * 4); - if (file_write(fh, palwork, palsize) != palsize) { - goto sswb_err2; - } - } - - work = (UINT8 *)_MALLOC(align, filename); - if (work == NULL) { - goto sswb_err2; - } - ZeroMemory(work, align); - - s = sd->dat + (SURFACE_WIDTH * bd.height); - do { - s -= SURFACE_WIDTH; - switch(type) { - case SCRNSAVE_1BIT: - ZeroMemory(work, align); - for (x=0; x> 3] |= 0x80 >> (x & 7); - } - } - break; - - case SCRNSAVE_4BIT: - r = bd.width / 2; - for (x=0; xpal[s[x]].d; -#endif - work[x*3+0] = curpal.rgb[0]; - work[x*3+1] = curpal.rgb[1]; - work[x*3+2] = curpal.rgb[2]; - } - break; - } - if (file_write(fh, work, align) != align) { - goto sswb_err3; - } - } while(--bd.height); - - file_close(fh); - _MFREE(work); - return(SUCCESS); - -sswb_err3: - _MFREE(work); - -sswb_err2: - file_close(fh); - file_delete(filename); - -sswb_err1: - return(FAILURE); -} - -BRESULT scrnsave_getbmp(SCRNSAVE hdl, BMPFILE *lpbf, BMPINFO *lpbi, UINT8 **lplppal, UINT8 **lplppixels, UINT flag) { - -const SCRNDATA *sd; - BMPDATA bd; - UINT type; - UINT palsize; - BMPFILE bf; - UINT pos; - BMPINFO bi; - UINT8 palwork[1024]; - UINT align; - UINT8 *work; -const PALNUM *s; - int r; - int x; - BMPPAL curpal; - UINT8 *dstpix; - - (void)flag; - - if (hdl == NULL) { - goto sswb_err1; - } - sd = (SCRNDATA *)hdl; - - bd.width = sd->width; - bd.height = sd->height; - if (sd->pals <= 2) { - type = SCRNSAVE_1BIT; - bd.bpp = 1; - palsize = 4 << 1; - } - else if (sd->pals <= 16) { - type = SCRNSAVE_4BIT; - bd.bpp = 4; - palsize = 4 << 4; - } - else if (sd->pals <= 256) { - type = SCRNSAVE_8BIT; - bd.bpp = 8; - palsize = 4 << 8; - } - else { - type = SCRNSAVE_24BIT; - bd.bpp = 24; - palsize = 0; - } - - // Bitmap File - ZeroMemory(&bf, sizeof(bf)); - bf.bfType[0] = 'B'; - bf.bfType[1] = 'M'; - pos = sizeof(BMPFILE) + sizeof(BMPINFO) + palsize; - STOREINTELDWORD(bf.bfOffBits, pos); - - // Bitmap Info - bmpdata_setinfo(&bi, &bd); - STOREINTELDWORD(bi.biClrImportant, sd->pals); - align = bmpdata_getalign(&bi); - CopyMemory(lpbi, &bi, sizeof(bi)); - *lplppal = (UINT8*)malloc(palsize); - if (palsize) { - ZeroMemory(palwork, palsize); - CopyMemory(palwork, sd->pal, sd->pals * 4); - CopyMemory(*lplppal, palwork, palsize); - } - - // Bitmap File (size) - STOREINTELDWORD(bf.bfSize, (sizeof(BMPFILE) + sizeof(BMPINFO) + palsize + bmpdata_getalign(&bi) * bd.height)); - CopyMemory(lpbf, &bf, sizeof(bf)); - - work = (UINT8 *)_MALLOC(align, filename); - if (work == NULL) { - goto sswb_err2; - } - ZeroMemory(work, align); - - *lplppixels = (UINT8*)malloc(bmpdata_getalign(&bi) * bd.height); - dstpix = *lplppixels; - s = sd->dat + (SURFACE_WIDTH * bd.height); - do { - s -= SURFACE_WIDTH; - switch(type) { - case SCRNSAVE_1BIT: - ZeroMemory(work, align); - for (x=0; x> 3] |= 0x80 >> (x & 7); - } - } - break; - - case SCRNSAVE_4BIT: - r = bd.width / 2; - for (x=0; xpal[s[x]].d; - work[x*3+0] = curpal.rgb[0]; - work[x*3+1] = curpal.rgb[1]; - work[x*3+2] = curpal.rgb[2]; - - } - break; - } - - CopyMemory(dstpix, work, align); - dstpix += align; - } while(--bd.height); - - - _MFREE(work); - return(SUCCESS); - -//sswb_err3: -// _MFREE(work); -sswb_err2: -sswb_err1: - return(FAILURE); -} - - -// ---- GIF - -#if 1 -#define MAXGIFBITS 12 - -#if MAXGIFBITS == 12 -#define HASHTBLSIZE 5003 -#elif MAXGIFBITS == 13 -#define HASHTBLSIZE 9001 -#elif MAXGIFBITS == 14 -#define HASHTBLSIZE 18013 -#elif MAXGIFBITS == 15 -#define HASHTBLSIZE 35023 -#elif MAXGIFBITS == 16 -#define HASHTBLSIZE 69001 -#endif - -#define GIFBITDATAWRITE(dat) \ - do { \ - bitdata |= (dat) << bits; \ - bits += bitcount; \ - while(bits >= 8) { \ - bitbuf[++bitdatas] = (UINT8)bitdata; \ - if (bitdatas >= 255) { \ - bitbuf[0] = (UINT8)bitdatas; \ - r = 1 + bitdatas; \ - if (file_write(fh, bitbuf, r) != r) { \ - goto sswg_err4; \ - } \ - bitdatas = 0; \ - } \ - bitdata >>= 8; \ - bits -= 8; \ - } \ - } while(/*CONSTCOND*/ 0) - -#define GIFBITEXTENSION \ - do { \ - if (codefree > codemax) { \ - bitcount++; \ - if (bitcount < MAXGIFBITS) { \ - codemax = (codemax << 1) + 1; \ - } \ - else { \ - codemax = 1 << MAXGIFBITS; \ - } \ - } \ - } while(/*CONSTCOND*/ 0) - -#define GIFBITDATAFLASH \ - do { \ - if (bits) { \ - bitbuf[++bitdatas] = (UINT8)bitdata; \ - } \ - if (bitdatas) { \ - bitbuf[0] = (UINT8)bitdatas; \ - r = 1 + bitdatas; \ - if (file_write(fh, bitbuf, r) != r) { \ - goto sswg_err4; \ - } \ - } \ - } while(/*CONSTCOND*/ 0) - - -BRESULT scrnsave_writegif(SCRNSAVE hdl, const OEMCHAR *filename, UINT flag) { - -const SCRNDATA *sd; - UINT bpp; - UINT *hash_code; - UINT32 *hash_data; - FILEH fh; - UINT r; -const PALNUM *s; - - UINT codeclear; - UINT codeeoi; - UINT codefree; - UINT codemax; - - UINT8 bits; - UINT8 bitcount; - UINT bitdata; - UINT bitdatas; - UINT8 bitbuf[3+256*3]; - - int x; - int y; - UINT b; - UINT32 c; - int i; - int disp; - - (void)flag; - - if (hdl == NULL) { - goto sswg_err1; - } - sd = (SCRNDATA *)hdl; - - bpp = 1; - while(sd->pals > (UINT)(1 << bpp)) { - bpp++; - } - if (bpp > 8) { - goto sswg_err1; - } - - hash_code = (UINT *)_MALLOC(HASHTBLSIZE * sizeof(UINT), "hash_code"); - if (hash_code == NULL) { - goto sswg_err1; - } - hash_data = (UINT32 *)_MALLOC(HASHTBLSIZE * sizeof(UINT32), "hash_data"); - if (hash_data == NULL) { - goto sswg_err2; - } - - fh = file_create(filename); - if (fh == FILEH_INVALID) { - goto sswg_err3; - } - - CopyMemory(bitbuf, "GIF87a", 6); - STOREINTELWORD(bitbuf + 6, sd->width); - STOREINTELWORD(bitbuf + 8, sd->height); - if (file_write(fh, bitbuf, 10) != 10) { - goto sswg_err4; - } - - ZeroMemory(bitbuf, sizeof(bitbuf)); - bitbuf[0] = (UINT8)(0x80 + ((8 - 1) << 4) + (bpp - 1)); -// bitbuf[1] = 0; // background -// bitbuf[2] = 0; // reserved - for (r=0; rpals; r++) { - bitbuf[r*3+3] = sd->pal[r].rgb[2]; // R - bitbuf[r*3+4] = sd->pal[r].rgb[1]; // G - bitbuf[r*3+5] = sd->pal[r].rgb[0]; // B - } - r = (1 << bpp) * 3 + 3; - if (file_write(fh, bitbuf, r) != r) { - goto sswg_err4; - } - - bitbuf[0] = 0x2c; // separator - STOREINTELWORD(bitbuf + 1, 0); // sx - STOREINTELWORD(bitbuf + 3, 0); // sy - STOREINTELWORD(bitbuf + 5, sd->width); // cx - STOREINTELWORD(bitbuf + 7, sd->height); // cy - bitbuf[9] = 0; // noninterlace - - bpp = MAX(bpp, 2); - bitbuf[10] = (UINT8)bpp; - if (file_write(fh, bitbuf, 11) != 11) { - goto sswg_err4; - } - - codeclear = 1 << bpp; - codeeoi = codeclear + 1; - codefree = codeclear + 2; - codemax = (codeclear << 1) - 1; - - bits = 0; - bitdata = 0; - bitdatas = 0; - bitcount = (UINT8)(bpp + 1); - GIFBITDATAWRITE(codeclear); - - ZeroMemory(hash_code, HASHTBLSIZE * sizeof(UINT)); - - x = 0; - y = 0; - s = sd->dat; - b = s[x++]; - do { - while(x < sd->width) { - c = s[x++]; - i = (c << (MAXGIFBITS - 8)) + b; - c = (c << 16) + b; - if (i >= HASHTBLSIZE) { - i -= HASHTBLSIZE; - } - disp = (i != 0)?(i - HASHTBLSIZE):-1; - while(1) { - if (hash_code[i] == 0) { - GIFBITDATAWRITE(b); - GIFBITEXTENSION; - if (codefree < (1 << MAXGIFBITS)) { - hash_code[i] = codefree++; - hash_data[i] = c; - } - else { - ZeroMemory(hash_code, HASHTBLSIZE * sizeof(UINT)); - GIFBITDATAWRITE(codeclear); - codefree = codeclear + 2; - codemax = (codeclear << 1) - 1; - bitcount = (UINT8)(bpp + 1); - } - b = c >> 16; - break; - } - else if (hash_data[i] == c) { - b = hash_code[i]; - break; - } - else { - i += disp; - if (i < 0) { - i += HASHTBLSIZE; - } - } - } - } - x = 0; - s += SURFACE_WIDTH; - y++; - } while(y < sd->height); - - GIFBITDATAWRITE(b); - GIFBITEXTENSION; - GIFBITDATAWRITE(codeeoi); - GIFBITDATAFLASH; - - bitbuf[0] = 0; - if (file_write(fh, bitbuf, 1) != 1) { - goto sswg_err4; - } - - bitbuf[0] = 0x3b; // terminator - if (file_write(fh, bitbuf, 1) != 1) { - goto sswg_err4; - } - - file_close(fh); - _MFREE(hash_data); - _MFREE(hash_code); - return(SUCCESS); - -sswg_err4: - file_close(fh); - file_delete(filename); - -sswg_err3: - _MFREE(hash_data); - -sswg_err2: - _MFREE(hash_code); - -sswg_err1: - return(FAILURE); -} -#endif - +/** + * @file scrnsave.c + * @brief Implementation of the screen saver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_VIDEOFILTER) +#include +#endif + +/** + * @brief The structure of screen saver + */ +struct tagScrnSave +{ + int width; + int height; + UINT pals; + UINT type; +}; + +#if defined(SUPPORT_PC9821) +#if defined(SUPPORT_VIDEOFILTER) +typedef uint32_t PALNUM; +#else +typedef unsigned short PALNUM; +#endif +#else +typedef unsigned char PALNUM; +#endif + +typedef union { + UINT32 d; + UINT8 rgb[4]; +} BMPPAL; + +typedef struct { + int width; + int height; + UINT pals; + UINT type; + BMPPAL pal[NP2PAL_MAX]; + PALNUM dat[SURFACE_WIDTH * SURFACE_HEIGHT]; +} SCRNDATA; + + +static void screenmix(PALNUM *dest, const UINT8 *src1, const UINT8 *src2, const int normaldisp) { + + int x, y; + int i; + + if (normaldisp) { + for (y = 0; y < SURFACE_HEIGHT; y++) { + for (x = 0; x < SURFACE_WIDTH - 1; x++) { + i = y * SURFACE_WIDTH + x; + dest[i] = src1[i + 1]; + } + } + for (i = 0; i < (SURFACE_WIDTH * SURFACE_HEIGHT); i++) { + dest[i] += src2[i] + NP2PAL_GRPH; + } + }else{ + for (i=0; i<(SURFACE_WIDTH * SURFACE_HEIGHT); i++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || src1[i]) { + dest[i] = src1[i]; + } else { + VideoFilter_PutDest(hVFMng1, &dest[i], i % SURFACE_WIDTH, i / SURFACE_WIDTH, 4); + } +#else + dest[i] = src1[i] + src2[i] + NP2PAL_GRPH; +#endif + } + } +} + +static void screenmix2(PALNUM *dest, const UINT8 *src1, const UINT8 *src2, const int normaldisp) { + + int x, y; + + if (normaldisp) { + for (y = 0; y < (SURFACE_HEIGHT / 2); y++) { + for (x = 0; x < SURFACE_WIDTH - 1; x++) { + dest[x] = src1[x + 1] + src2[x] + NP2PAL_GRPH; + } + dest[SURFACE_WIDTH - 1] = src2[SURFACE_WIDTH - 1] + NP2PAL_GRPH; + dest += SURFACE_WIDTH; + src1 += SURFACE_WIDTH; + src2 += SURFACE_WIDTH; + for (x = 0; x < SURFACE_WIDTH - 1; x++) { + dest[x] = (src1[x + 1] >> 4) + NP2PAL_TEXT; + } + dest[SURFACE_WIDTH - 1] = NP2PAL_TEXT; + dest += SURFACE_WIDTH; + src1 += SURFACE_WIDTH; + src2 += SURFACE_WIDTH; + } + } else { + for (y = 0; y < (SURFACE_HEIGHT / 2); y++) { + for (x = 0; x < SURFACE_WIDTH; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || src1[x]) { + dest[x] = src1[x]; + } else { + VideoFilter_PutDest(hVFMng1, &dest[x], x, y * 2, 4); + } +#else + dest[x] = src1[x] + src2[x] + NP2PAL_GRPH; +#endif + } + dest += SURFACE_WIDTH; + src1 += SURFACE_WIDTH; + src2 += SURFACE_WIDTH; + for (x = 0; x < SURFACE_WIDTH; x++) { + dest[x] = (src1[x] >> 4) + NP2PAL_TEXT; + } + dest += SURFACE_WIDTH; + src1 += SURFACE_WIDTH; + src2 += SURFACE_WIDTH; + } + } +} + +static void screenmix3(PALNUM *dest, const UINT8 *src1, const UINT8 *src2, const int normaldisp) { + + PALNUM c; + int x, y; + + if (normaldisp) { + for (y = 0; y < (SURFACE_HEIGHT / 2); y++) { + // dest == src1, dest == src2 の時があるので… + for (x = 0; x < SURFACE_WIDTH - 1; x++) { + c = (src1[x + 1 + SURFACE_WIDTH]) >> 4; + if (!c) { + c = src2[x] + NP2PAL_SKIP; + } + dest[x + SURFACE_WIDTH] = c; + dest[x] = src1[x + 1] + src2[x] + NP2PAL_GRPH; + } + c = src2[(SURFACE_WIDTH - 1)] + NP2PAL_SKIP; + dest[(SURFACE_WIDTH - 1) + SURFACE_WIDTH] = c; + dest[(SURFACE_WIDTH - 1)] = src2[(SURFACE_WIDTH - 1)] + NP2PAL_GRPH; + dest += SURFACE_WIDTH * 2; + src1 += SURFACE_WIDTH * 2; + src2 += SURFACE_WIDTH * 2; + } + }else{ + for (y = 0; y < (SURFACE_HEIGHT / 2); y++) { + // dest == src1, dest == src2 の時があるので… + for (x = 0; x < SURFACE_WIDTH; x++) { + c = (src1[x + SURFACE_WIDTH]) >> 4; + if (!c) { + c = src2[x] + NP2PAL_SKIP; + } + dest[x + SURFACE_WIDTH] = c; +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || src1[x]) { + dest[x] = src1[x] + NP2PAL_GRPH; + } else { + VideoFilter_PutDest(hVFMng1, &dest[x], x, y * 2, 4); + } +#else + dest[x] = src1[x] + src2[x] + NP2PAL_GRPH; +#endif +} + } + dest += SURFACE_WIDTH * 2; + src1 += SURFACE_WIDTH * 2; + src2 += SURFACE_WIDTH * 2; + } + } + +#if defined(SUPPORT_PC9821) +static void screenmix4(PALNUM *dest, const UINT8 *src1, const UINT8 *src2, const int normaldisp) { + + int x, y; + int i; + if (normaldisp) { + for (y = 0; y < SURFACE_HEIGHT; y++) { + for (x = 0; x < SURFACE_WIDTH; x++) { + i = y * SURFACE_WIDTH + x; + if (x < SURFACE_WIDTH - 1 && src1[i + 1]) { + dest[i] = (src1[i + 1] >> 4) + NP2PAL_TEXTEX; + } + else { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + dest[i] = src2[i] + NP2PAL_GRPHEX; + } else { + VideoFilter_PutDest(hVFMng1, &dest[i], i % SURFACE_WIDTH, i / SURFACE_WIDTH, 4); + } +#else + dest[i] = src2[i] + NP2PAL_GRPHEX; +#endif + } + } + } + } else { + for (i = 0; i < (SURFACE_WIDTH * SURFACE_HEIGHT); i++) { + if (src1[i]) { + dest[i] = (src1[i] >> 4) + NP2PAL_TEXTEX; + } + else { + dest[i] = src2[i] + NP2PAL_GRPHEX; + } + } + } +} +#endif + + +// ---- + +/** + * Create + * @return The handle of saver + */ +SCRNSAVE scrnsave_create(void) +{ + int width; + int height; + SCRNDATA *sd; + PALNUM *dat; + UINT scrnsize; + UINT8 *datanull; + UINT8 *datatext; + UINT8 *datagrph; + void (*mix)(PALNUM *dest, const UINT8 *src1, const UINT8 *src2, const int src1ofs); + PALNUM *s; + UINT pals; + PALNUM remap[NP2PAL_MAX]; + UINT8 remapflag[NP2PAL_MAX]; + int x; + int y; + PALNUM col; + BMPPAL curpal; + UINT pos; + uint8_t* dirty[SURFACE_HEIGHT]; + int normaldisp = 0; + + width = dsync.scrnxmax; + height = dsync.scrnymax; + if ((width <= 0) || (height <= 0)) { + goto ssg_err; + } + sd = (SCRNDATA *)_MALLOC(sizeof(SCRNDATA), "screen data"); + if (sd == NULL) { + goto ssg_err; + } + ZeroMemory(sd, sizeof(SCRNDATA)); + + normaldisp = (!(np2cfg.LCD_MODE & 1)) && ((gdc.display & 7) < 3) ? 1 : 0; + + memset(dirty, 1, SURFACE_HEIGHT); + + dat = sd->dat; + scrnsize = SURFACE_WIDTH * SURFACE_HEIGHT; + datanull = ((UINT8 *)dat) + (scrnsize * (sizeof(PALNUM) - 1)); + datatext = datanull; + datagrph = datanull; + if (gdcs.textdisp & 0x80) { + datatext = np2_tram; + } + if (gdcs.grphdisp & 0x80) { +#if defined(SUPPORT_PC9821) + if ((gdc.analog & 6) == 6) { + datagrph = np2_vram[0]; + } + else +#endif + datagrph = np2_vram[gdcs.disp]; + } +#if defined(SUPPORT_PC9821) + if (gdc.analog & 2) { + mix = screenmix4; + } + else +#endif + if (!(gdc.mode1 & 0x10)) { + mix = screenmix; + } + else if (!np2cfg.skipline) { + mix = screenmix2; + } + else { + mix = screenmix3; + } +#if defined(SUPPORT_VIDEOFILTER) + bVFEnable = VideoFilter_GetEnable(hVFMng1); + if(bVFEnable) { + VideoFilter_Import98(hVFMng1, datagrph, dirty, (gdc.analog & 2) ? TRUE : FALSE); + VideoFilter_Calc(hVFMng1); + } +#endif + (*mix)(sd->dat, datatext, datagrph, normaldisp); + +#if defined(SUPPORT_VIDEOFILTER) + sd->width = width; + sd->height = height; + sd->pals = 16777216; + sd->type = SCRNSAVE_24BIT; +#else + // パレット最適化 + s = sd->dat; + pals = 0; + ZeroMemory(remap, sizeof(remap)); + ZeroMemory(remapflag, sizeof(remapflag)); + for (y=0; ypal[pos].d == curpal.d) { + break; + } + } + if (pos >= pals) { + sd->pal[pos].d = curpal.d; + pals++; + } + remap[col] = (PALNUM)pos; + } + s[x] = remap[col]; + } + s += SURFACE_WIDTH; + } + sd->width = width; + sd->height = height; + sd->pals = pals; + if (pals <= 2) { + sd->type = SCRNSAVE_1BIT; + } + else if (pals <= 16) { + sd->type = SCRNSAVE_4BIT; + } + else if (pals <= 256) { + sd->type = SCRNSAVE_8BIT; + } + else { + sd->type = SCRNSAVE_24BIT; + } +#endif + return((SCRNSAVE)sd); + +ssg_err: + return(NULL); +} + +/** + * Destroy + * @param[in] hdl The handle of saver + */ +void scrnsave_destroy(SCRNSAVE hdl) +{ + if (hdl) + { + _MFREE(hdl); + } +} + +/** + * Get BPP + * @param[in] hdl The handle of saver + * @return bpp + */ +int scrnsave_gettype(SCRNSAVE hdl) +{ + int ret = 0; + + if (hdl) + { + ret = hdl->type; + } + return ret; +} + +// ---- BMP + +BRESULT scrnsave_writebmp(SCRNSAVE hdl, const OEMCHAR *filename, UINT flag) { + +const SCRNDATA *sd; + FILEH fh; + BMPDATA bd; + UINT type; + UINT palsize; + BMPFILE bf; + UINT pos; + BMPINFO bi; + UINT8 palwork[1024]; + UINT align; + UINT8 *work; +const PALNUM *s; + int r; + int x; + BMPPAL curpal; + + (void)flag; + + if (hdl == NULL) { + goto sswb_err1; + } + sd = (SCRNDATA *)hdl; + + fh = file_create(filename); + if (fh == FILEH_INVALID) { + goto sswb_err1; + } + + bd.width = sd->width; + bd.height = sd->height; + if (sd->pals <= 2) { + type = SCRNSAVE_1BIT; + bd.bpp = 1; + palsize = 4 << 1; + } + else if (sd->pals <= 16) { + type = SCRNSAVE_4BIT; + bd.bpp = 4; + palsize = 4 << 4; + } + else if (sd->pals <= 256) { + type = SCRNSAVE_8BIT; + bd.bpp = 8; + palsize = 4 << 8; + } + else { + type = SCRNSAVE_24BIT; + bd.bpp = 24; + palsize = 0; + } + + // Bitmap File + ZeroMemory(&bf, sizeof(bf)); + bf.bfType[0] = 'B'; + bf.bfType[1] = 'M'; + pos = sizeof(BMPFILE) + sizeof(BMPINFO) + palsize; + STOREINTELDWORD(bf.bfOffBits, pos); + + // Bitmap Info + bmpdata_setinfo(&bi, &bd); + STOREINTELDWORD(bi.biClrImportant, sd->pals); + align = bmpdata_getalign(&bi); + + // Bitmap File (size) + STOREINTELDWORD(bf.bfSize, (sizeof(BMPFILE) + sizeof(BMPINFO) + palsize + bmpdata_getalign(&bi) * bd.height)); + + if (file_write(fh, &bf, sizeof(bf)) != sizeof(bf)) { + goto sswb_err2; + } + if (file_write(fh, &bi, sizeof(bi)) != sizeof(bi)) { + goto sswb_err2; + } + + if (palsize) { + ZeroMemory(palwork, palsize); + CopyMemory(palwork, sd->pal, sd->pals * 4); + if (file_write(fh, palwork, palsize) != palsize) { + goto sswb_err2; + } + } + + work = (UINT8 *)_MALLOC(align, filename); + if (work == NULL) { + goto sswb_err2; + } + ZeroMemory(work, align); + + s = sd->dat + (SURFACE_WIDTH * bd.height); + do { + s -= SURFACE_WIDTH; + switch(type) { + case SCRNSAVE_1BIT: + ZeroMemory(work, align); + for (x=0; x> 3] |= 0x80 >> (x & 7); + } + } + break; + + case SCRNSAVE_4BIT: + r = bd.width / 2; + for (x=0; xpal[s[x]].d; +#endif + work[x*3+0] = curpal.rgb[0]; + work[x*3+1] = curpal.rgb[1]; + work[x*3+2] = curpal.rgb[2]; + } + break; + } + if (file_write(fh, work, align) != align) { + goto sswb_err3; + } + } while(--bd.height); + + file_close(fh); + _MFREE(work); + return(SUCCESS); + +sswb_err3: + _MFREE(work); + +sswb_err2: + file_close(fh); + file_delete(filename); + +sswb_err1: + return(FAILURE); +} + +BRESULT scrnsave_getbmp(SCRNSAVE hdl, BMPFILE *lpbf, BMPINFO *lpbi, UINT8 **lplppal, UINT8 **lplppixels, UINT flag) { + +const SCRNDATA *sd; + BMPDATA bd; + UINT type; + UINT palsize; + BMPFILE bf; + UINT pos; + BMPINFO bi; + UINT8 palwork[1024]; + UINT align; + UINT8 *work; +const PALNUM *s; + int r; + int x; + BMPPAL curpal; + UINT8 *dstpix; + + (void)flag; + + if (hdl == NULL) { + goto sswb_err1; + } + sd = (SCRNDATA *)hdl; + + bd.width = sd->width; + bd.height = sd->height; + if (sd->pals <= 2) { + type = SCRNSAVE_1BIT; + bd.bpp = 1; + palsize = 4 << 1; + } + else if (sd->pals <= 16) { + type = SCRNSAVE_4BIT; + bd.bpp = 4; + palsize = 4 << 4; + } + else if (sd->pals <= 256) { + type = SCRNSAVE_8BIT; + bd.bpp = 8; + palsize = 4 << 8; + } + else { + type = SCRNSAVE_24BIT; + bd.bpp = 24; + palsize = 0; + } + + // Bitmap File + ZeroMemory(&bf, sizeof(bf)); + bf.bfType[0] = 'B'; + bf.bfType[1] = 'M'; + pos = sizeof(BMPFILE) + sizeof(BMPINFO) + palsize; + STOREINTELDWORD(bf.bfOffBits, pos); + + // Bitmap Info + bmpdata_setinfo(&bi, &bd); + STOREINTELDWORD(bi.biClrImportant, sd->pals); + align = bmpdata_getalign(&bi); + CopyMemory(lpbi, &bi, sizeof(bi)); + *lplppal = (UINT8*)malloc(palsize); + if (palsize) { + ZeroMemory(palwork, palsize); + CopyMemory(palwork, sd->pal, sd->pals * 4); + CopyMemory(*lplppal, palwork, palsize); + } + + // Bitmap File (size) + STOREINTELDWORD(bf.bfSize, (sizeof(BMPFILE) + sizeof(BMPINFO) + palsize + bmpdata_getalign(&bi) * bd.height)); + CopyMemory(lpbf, &bf, sizeof(bf)); + + work = (UINT8 *)_MALLOC(align, filename); + if (work == NULL) { + goto sswb_err2; + } + ZeroMemory(work, align); + + *lplppixels = (UINT8*)malloc(bmpdata_getalign(&bi) * bd.height); + dstpix = *lplppixels; + s = sd->dat + (SURFACE_WIDTH * bd.height); + do { + s -= SURFACE_WIDTH; + switch(type) { + case SCRNSAVE_1BIT: + ZeroMemory(work, align); + for (x=0; x> 3] |= 0x80 >> (x & 7); + } + } + break; + + case SCRNSAVE_4BIT: + r = bd.width / 2; + for (x=0; xpal[s[x]].d; + work[x*3+0] = curpal.rgb[0]; + work[x*3+1] = curpal.rgb[1]; + work[x*3+2] = curpal.rgb[2]; + + } + break; + } + + CopyMemory(dstpix, work, align); + dstpix += align; + } while(--bd.height); + + + _MFREE(work); + return(SUCCESS); + +//sswb_err3: +// _MFREE(work); +sswb_err2: +sswb_err1: + return(FAILURE); +} + + +// ---- GIF + +#if 1 +#define MAXGIFBITS 12 + +#if MAXGIFBITS == 12 +#define HASHTBLSIZE 5003 +#elif MAXGIFBITS == 13 +#define HASHTBLSIZE 9001 +#elif MAXGIFBITS == 14 +#define HASHTBLSIZE 18013 +#elif MAXGIFBITS == 15 +#define HASHTBLSIZE 35023 +#elif MAXGIFBITS == 16 +#define HASHTBLSIZE 69001 +#endif + +#define GIFBITDATAWRITE(dat) \ + do { \ + bitdata |= (dat) << bits; \ + bits += bitcount; \ + while(bits >= 8) { \ + bitbuf[++bitdatas] = (UINT8)bitdata; \ + if (bitdatas >= 255) { \ + bitbuf[0] = (UINT8)bitdatas; \ + r = 1 + bitdatas; \ + if (file_write(fh, bitbuf, r) != r) { \ + goto sswg_err4; \ + } \ + bitdatas = 0; \ + } \ + bitdata >>= 8; \ + bits -= 8; \ + } \ + } while(/*CONSTCOND*/ 0) + +#define GIFBITEXTENSION \ + do { \ + if (codefree > codemax) { \ + bitcount++; \ + if (bitcount < MAXGIFBITS) { \ + codemax = (codemax << 1) + 1; \ + } \ + else { \ + codemax = 1 << MAXGIFBITS; \ + } \ + } \ + } while(/*CONSTCOND*/ 0) + +#define GIFBITDATAFLASH \ + do { \ + if (bits) { \ + bitbuf[++bitdatas] = (UINT8)bitdata; \ + } \ + if (bitdatas) { \ + bitbuf[0] = (UINT8)bitdatas; \ + r = 1 + bitdatas; \ + if (file_write(fh, bitbuf, r) != r) { \ + goto sswg_err4; \ + } \ + } \ + } while(/*CONSTCOND*/ 0) + + +BRESULT scrnsave_writegif(SCRNSAVE hdl, const OEMCHAR *filename, UINT flag) { + +const SCRNDATA *sd; + UINT bpp; + UINT *hash_code; + UINT32 *hash_data; + FILEH fh; + UINT r; +const PALNUM *s; + + UINT codeclear; + UINT codeeoi; + UINT codefree; + UINT codemax; + + UINT8 bits; + UINT8 bitcount; + UINT bitdata; + UINT bitdatas; + UINT8 bitbuf[3+256*3]; + + int x; + int y; + UINT b; + UINT32 c; + int i; + int disp; + + (void)flag; + + if (hdl == NULL) { + goto sswg_err1; + } + sd = (SCRNDATA *)hdl; + + bpp = 1; + while(sd->pals > (UINT)(1 << bpp)) { + bpp++; + } + if (bpp > 8) { + goto sswg_err1; + } + + hash_code = (UINT *)_MALLOC(HASHTBLSIZE * sizeof(UINT), "hash_code"); + if (hash_code == NULL) { + goto sswg_err1; + } + hash_data = (UINT32 *)_MALLOC(HASHTBLSIZE * sizeof(UINT32), "hash_data"); + if (hash_data == NULL) { + goto sswg_err2; + } + + fh = file_create(filename); + if (fh == FILEH_INVALID) { + goto sswg_err3; + } + + CopyMemory(bitbuf, "GIF87a", 6); + STOREINTELWORD(bitbuf + 6, sd->width); + STOREINTELWORD(bitbuf + 8, sd->height); + if (file_write(fh, bitbuf, 10) != 10) { + goto sswg_err4; + } + + ZeroMemory(bitbuf, sizeof(bitbuf)); + bitbuf[0] = (UINT8)(0x80 + ((8 - 1) << 4) + (bpp - 1)); +// bitbuf[1] = 0; // background +// bitbuf[2] = 0; // reserved + for (r=0; rpals; r++) { + bitbuf[r*3+3] = sd->pal[r].rgb[2]; // R + bitbuf[r*3+4] = sd->pal[r].rgb[1]; // G + bitbuf[r*3+5] = sd->pal[r].rgb[0]; // B + } + r = (1 << bpp) * 3 + 3; + if (file_write(fh, bitbuf, r) != r) { + goto sswg_err4; + } + + bitbuf[0] = 0x2c; // separator + STOREINTELWORD(bitbuf + 1, 0); // sx + STOREINTELWORD(bitbuf + 3, 0); // sy + STOREINTELWORD(bitbuf + 5, sd->width); // cx + STOREINTELWORD(bitbuf + 7, sd->height); // cy + bitbuf[9] = 0; // noninterlace + + bpp = MAX(bpp, 2); + bitbuf[10] = (UINT8)bpp; + if (file_write(fh, bitbuf, 11) != 11) { + goto sswg_err4; + } + + codeclear = 1 << bpp; + codeeoi = codeclear + 1; + codefree = codeclear + 2; + codemax = (codeclear << 1) - 1; + + bits = 0; + bitdata = 0; + bitdatas = 0; + bitcount = (UINT8)(bpp + 1); + GIFBITDATAWRITE(codeclear); + + ZeroMemory(hash_code, HASHTBLSIZE * sizeof(UINT)); + + x = 0; + y = 0; + s = sd->dat; + b = s[x++]; + do { + while(x < sd->width) { + c = s[x++]; + i = (c << (MAXGIFBITS - 8)) + b; + c = (c << 16) + b; + if (i >= HASHTBLSIZE) { + i -= HASHTBLSIZE; + } + disp = (i != 0)?(i - HASHTBLSIZE):-1; + while(1) { + if (hash_code[i] == 0) { + GIFBITDATAWRITE(b); + GIFBITEXTENSION; + if (codefree < (1 << MAXGIFBITS)) { + hash_code[i] = codefree++; + hash_data[i] = c; + } + else { + ZeroMemory(hash_code, HASHTBLSIZE * sizeof(UINT)); + GIFBITDATAWRITE(codeclear); + codefree = codeclear + 2; + codemax = (codeclear << 1) - 1; + bitcount = (UINT8)(bpp + 1); + } + b = c >> 16; + break; + } + else if (hash_data[i] == c) { + b = hash_code[i]; + break; + } + else { + i += disp; + if (i < 0) { + i += HASHTBLSIZE; + } + } + } + } + x = 0; + s += SURFACE_WIDTH; + y++; + } while(y < sd->height); + + GIFBITDATAWRITE(b); + GIFBITEXTENSION; + GIFBITDATAWRITE(codeeoi); + GIFBITDATAFLASH; + + bitbuf[0] = 0; + if (file_write(fh, bitbuf, 1) != 1) { + goto sswg_err4; + } + + bitbuf[0] = 0x3b; // terminator + if (file_write(fh, bitbuf, 1) != 1) { + goto sswg_err4; + } + + file_close(fh); + _MFREE(hash_data); + _MFREE(hash_code); + return(SUCCESS); + +sswg_err4: + file_close(fh); + file_delete(filename); + +sswg_err3: + _MFREE(hash_data); + +sswg_err2: + _MFREE(hash_code); + +sswg_err1: + return(FAILURE); +} +#endif + diff --git a/vram/scrnsave.h b/vram/scrnsave.h old mode 100755 new mode 100644 index 0bf87f9f..db65783c --- a/vram/scrnsave.h +++ b/vram/scrnsave.h @@ -1,47 +1,47 @@ -/** - * @file scrnsave.h - * @brief Interface of the screen saver - */ - -#pragma once - -#include - -/** - * types - */ -enum tagScrnSaveType -{ - SCRNSAVE_1BIT = 0, - SCRNSAVE_4BIT = 1, - SCRNSAVE_8BIT = 2, - SCRNSAVE_24BIT = 3 -}; - -/** - * flags - */ -enum tagScrnSaveFlags -{ - SCRNSAVE_AUTO = 0 -}; - -struct tagScrnSave; -typedef struct tagScrnSave * SCRNSAVE; - - -#ifdef __cplusplus -extern "C" -{ -#endif - -SCRNSAVE scrnsave_create(void); -void scrnsave_destroy(SCRNSAVE hdl); -int scrnsave_gettype(SCRNSAVE hdl); -BRESULT scrnsave_writebmp(SCRNSAVE hdl, const OEMCHAR *filename, UINT flag); -BRESULT scrnsave_getbmp(SCRNSAVE hdl, BMPFILE *lpbf, BMPINFO *lpbi, UINT8 **lplppal, UINT8 **lplppixels, UINT flag); -BRESULT scrnsave_writegif(SCRNSAVE hdl, const OEMCHAR *filename, UINT flag); - -#ifdef __cplusplus -} -#endif +/** + * @file scrnsave.h + * @brief Interface of the screen saver + */ + +#pragma once + +#include + +/** + * types + */ +enum tagScrnSaveType +{ + SCRNSAVE_1BIT = 0, + SCRNSAVE_4BIT = 1, + SCRNSAVE_8BIT = 2, + SCRNSAVE_24BIT = 3 +}; + +/** + * flags + */ +enum tagScrnSaveFlags +{ + SCRNSAVE_AUTO = 0 +}; + +struct tagScrnSave; +typedef struct tagScrnSave * SCRNSAVE; + + +#ifdef __cplusplus +extern "C" +{ +#endif + +SCRNSAVE scrnsave_create(void); +void scrnsave_destroy(SCRNSAVE hdl); +int scrnsave_gettype(SCRNSAVE hdl); +BRESULT scrnsave_writebmp(SCRNSAVE hdl, const OEMCHAR *filename, UINT flag); +BRESULT scrnsave_getbmp(SCRNSAVE hdl, BMPFILE *lpbf, BMPINFO *lpbi, UINT8 **lplppal, UINT8 **lplppixels, UINT flag); +BRESULT scrnsave_writegif(SCRNSAVE hdl, const OEMCHAR *filename, UINT flag); + +#ifdef __cplusplus +} +#endif diff --git a/vram/sdraw.c b/vram/sdraw.c old mode 100755 new mode 100644 index 605babfd..9964effe --- a/vram/sdraw.c +++ b/vram/sdraw.c @@ -1,174 +1,174 @@ -#include -#include -#include -#include "sdraw.h" -#include -#if defined(SUPPORT_VIDEOFILTER) -#include -#endif - -#if defined(SUPPORT_VIDEOFILTER) -BOOL bVFEnable; -BOOL bVFImport; -#endif - -#if !defined(NP2_SIZE_QVGA) || defined(SIZE_VGATEST) - -#if defined(SUPPORT_8BPP) -#define SDSYM(sym) sdraw8##sym -#define SDSETPIXEL(ptr, pal) *(ptr) = (pal) + START_PAL -#include "sdraw.mcr" -#undef SDSYM -#undef SDSETPIXEL -#endif - -#if defined(SUPPORT_16BPP) -#define SDSYM(sym) sdraw16##sym -#define SDSETPIXEL(ptr, pal) *(UINT16 *)(ptr) = np2_pal16[(pal)] -#include "sdraw.mcr" -#include "sdrawex.mcr" -#undef SDSYM -#undef SDSETPIXEL -#endif - -#if defined(SUPPORT_24BPP) -#define SDSYM(sym) sdraw24##sym -#define SDSETPIXEL(ptr, pal) (ptr)[RGB24_R] = np2_pal32[(pal)].p.r; \ - (ptr)[RGB24_G] = np2_pal32[(pal)].p.g; \ - (ptr)[RGB24_B] = np2_pal32[(pal)].p.b -#include "sdraw.mcr" -#include "sdrawex.mcr" -#undef SDSYM -#undef SDSETPIXEL -#endif - -#if defined(SUPPORT_32BPP) -#define SDSYM(sym) sdraw32##sym -#define SDSETPIXEL(ptr, pal) *(UINT32 *)(ptr) = np2_pal32[(pal)].d -#include "sdraw.mcr" -#include "sdrawex.mcr" -#undef SDSYM -#undef SDSETPIXEL -#endif - - -// ---- - -static const SDRAWFN *tbl[] = { -#if defined(SUPPORT_8BPP) - sdraw8p, -#else - NULL, -#endif -#if defined(SUPPORT_16BPP) - sdraw16p, -#else - NULL, -#endif -#if defined(SUPPORT_24BPP) - sdraw24p, -#else - NULL, -#endif -#if defined(SUPPORT_32BPP) - sdraw32p, -#else - NULL, -#endif - -#if defined(SUPPORT_NORMALDISP) -#if defined(SUPPORT_8BPP) - sdraw8n, -#else - NULL, -#endif -#if defined(SUPPORT_16BPP) - sdraw16n, -#else - NULL, -#endif -#if defined(SUPPORT_24BPP) - sdraw24n, -#else - NULL, -#endif -#if defined(SUPPORT_32BPP) - sdraw32n, -#else - NULL, -#endif -#endif -}; - -const SDRAWFN *sdraw_getproctbl(const SCRNSURF *surf) { - - int proc; - - proc = ((surf->bpp >> 3) - 1) & 3; -#if defined(SUPPORT_NORMALDISP) - if (surf->extend) { - proc += 4; - } -#endif - return(tbl[proc]); -} - - -// ---- PC-9821 - -#if defined(SUPPORT_PC9821) - -static const SDRAWFN *tblex[] = { - NULL, -#if defined(SUPPORT_16BPP) - sdraw16pex, -#else - NULL, -#endif -#if defined(SUPPORT_24BPP) - sdraw24pex, -#else - NULL, -#endif -#if defined(SUPPORT_32BPP) - sdraw32pex, -#else - NULL, -#endif - -#if defined(SUPPORT_NORMALDISP) - NULL, -#if defined(SUPPORT_16BPP) - sdraw16nex, -#else - NULL, -#endif -#if defined(SUPPORT_24BPP) - sdraw24nex, -#else - NULL, -#endif -#if defined(SUPPORT_32BPP) - sdraw32nex, -#else - NULL, -#endif -#endif -}; - -const SDRAWFN *sdraw_getproctblex(const SCRNSURF *surf) { - - int proc; - - proc = ((surf->bpp >> 3) - 1) & 3; -#if defined(SUPPORT_NORMALDISP) - if (surf->extend) { - proc += 4; - } -#endif - return(tblex[proc]); -} -#endif - -#endif - +#include +#include +#include +#include "sdraw.h" +#include +#if defined(SUPPORT_VIDEOFILTER) +#include +#endif + +#if defined(SUPPORT_VIDEOFILTER) +BOOL bVFEnable; +BOOL bVFImport; +#endif + +#if !defined(NP2_SIZE_QVGA) || defined(SIZE_VGATEST) + +#if defined(SUPPORT_8BPP) +#define SDSYM(sym) sdraw8##sym +#define SDSETPIXEL(ptr, pal) *(ptr) = (pal) + START_PAL +#include "sdraw.mcr" +#undef SDSYM +#undef SDSETPIXEL +#endif + +#if defined(SUPPORT_16BPP) +#define SDSYM(sym) sdraw16##sym +#define SDSETPIXEL(ptr, pal) *(UINT16 *)(ptr) = np2_pal16[(pal)] +#include "sdraw.mcr" +#include "sdrawex.mcr" +#undef SDSYM +#undef SDSETPIXEL +#endif + +#if defined(SUPPORT_24BPP) +#define SDSYM(sym) sdraw24##sym +#define SDSETPIXEL(ptr, pal) (ptr)[RGB24_R] = np2_pal32[(pal)].p.r; \ + (ptr)[RGB24_G] = np2_pal32[(pal)].p.g; \ + (ptr)[RGB24_B] = np2_pal32[(pal)].p.b +#include "sdraw.mcr" +#include "sdrawex.mcr" +#undef SDSYM +#undef SDSETPIXEL +#endif + +#if defined(SUPPORT_32BPP) +#define SDSYM(sym) sdraw32##sym +#define SDSETPIXEL(ptr, pal) *(UINT32 *)(ptr) = np2_pal32[(pal)].d +#include "sdraw.mcr" +#include "sdrawex.mcr" +#undef SDSYM +#undef SDSETPIXEL +#endif + + +// ---- + +static const SDRAWFN *tbl[] = { +#if defined(SUPPORT_8BPP) + sdraw8p, +#else + NULL, +#endif +#if defined(SUPPORT_16BPP) + sdraw16p, +#else + NULL, +#endif +#if defined(SUPPORT_24BPP) + sdraw24p, +#else + NULL, +#endif +#if defined(SUPPORT_32BPP) + sdraw32p, +#else + NULL, +#endif + +#if defined(SUPPORT_NORMALDISP) +#if defined(SUPPORT_8BPP) + sdraw8n, +#else + NULL, +#endif +#if defined(SUPPORT_16BPP) + sdraw16n, +#else + NULL, +#endif +#if defined(SUPPORT_24BPP) + sdraw24n, +#else + NULL, +#endif +#if defined(SUPPORT_32BPP) + sdraw32n, +#else + NULL, +#endif +#endif +}; + +const SDRAWFN *sdraw_getproctbl(const SCRNSURF *surf) { + + int proc; + + proc = ((surf->bpp >> 3) - 1) & 3; +#if defined(SUPPORT_NORMALDISP) + if (surf->extend) { + proc += 4; + } +#endif + return(tbl[proc]); +} + + +// ---- PC-9821 + +#if defined(SUPPORT_PC9821) + +static const SDRAWFN *tblex[] = { + NULL, +#if defined(SUPPORT_16BPP) + sdraw16pex, +#else + NULL, +#endif +#if defined(SUPPORT_24BPP) + sdraw24pex, +#else + NULL, +#endif +#if defined(SUPPORT_32BPP) + sdraw32pex, +#else + NULL, +#endif + +#if defined(SUPPORT_NORMALDISP) + NULL, +#if defined(SUPPORT_16BPP) + sdraw16nex, +#else + NULL, +#endif +#if defined(SUPPORT_24BPP) + sdraw24nex, +#else + NULL, +#endif +#if defined(SUPPORT_32BPP) + sdraw32nex, +#else + NULL, +#endif +#endif +}; + +const SDRAWFN *sdraw_getproctblex(const SCRNSURF *surf) { + + int proc; + + proc = ((surf->bpp >> 3) - 1) & 3; +#if defined(SUPPORT_NORMALDISP) + if (surf->extend) { + proc += 4; + } +#endif + return(tblex[proc]); +} +#endif + +#endif + diff --git a/vram/sdraw.h b/vram/sdraw.h old mode 100755 new mode 100644 index e2355229..a4700418 --- a/vram/sdraw.h +++ b/vram/sdraw.h @@ -1,38 +1,38 @@ - -#include -#include - -typedef struct { -const UINT8 *src; -const UINT8 *src2; - UINT8 *dst; - int width; - int xbytes; - int y; - int xalign; - int yalign; - UINT8 dirty[SURFACE_HEIGHT]; -} _SDRAW, *SDRAW; - -typedef void (SCRNCALL * SDRAWFN)(SDRAW sdraw, int maxy); - - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(SUPPORT_VIDEOFILTER) -extern BOOL bVFEnable; -extern BOOL bVFImport; -#endif - -const SDRAWFN *sdraw_getproctbl(const SCRNSURF *surf); - -#if defined(SUPPORT_PC9821) -const SDRAWFN *sdraw_getproctblex(const SCRNSURF *surf); -#endif - -#ifdef __cplusplus -} -#endif - + +#include +#include + +typedef struct { +const UINT8 *src; +const UINT8 *src2; + UINT8 *dst; + int width; + int xbytes; + int y; + int xalign; + int yalign; + UINT8 dirty[SURFACE_HEIGHT]; +} _SDRAW, *SDRAW; + +typedef void (SCRNCALL * SDRAWFN)(SDRAW sdraw, int maxy); + + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(SUPPORT_VIDEOFILTER) +extern BOOL bVFEnable; +extern BOOL bVFImport; +#endif + +const SDRAWFN *sdraw_getproctbl(const SCRNSURF *surf); + +#if defined(SUPPORT_PC9821) +const SDRAWFN *sdraw_getproctblex(const SCRNSURF *surf); +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/vram/sdraw.mcr b/vram/sdraw.mcr old mode 100755 new mode 100644 index f040511c..4507ddb6 --- a/vram/sdraw.mcr +++ b/vram/sdraw.mcr @@ -1,1054 +1,1054 @@ - -// ---- plasma display - -// vram off -static void SCRNCALL SDSYM(p_0)(SDRAW sdraw, int maxy) { - - UINT8 *p; - int y; - int x; - - p = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { - SDSETPIXEL(p, NP2PAL_TEXT2); - p += sdraw->xalign; - } - p -= sdraw->xbytes; - } - p += sdraw->yalign; - } while(++y < maxy); - - sdraw->dst = p; - sdraw->y = y; -} - -// text or grph 1プレーン -static void SCRNCALL SDSYM(p_1)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || !bVFImport) { - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); -#endif - q += sdraw->xalign; - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph -static void SCRNCALL SDSYM(p_2)(SDRAW sdraw, int maxy) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int y; - int x; - - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || q[x]) { - SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, r, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); -#endif - r += sdraw->xalign; - } - r -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += SURFACE_WIDTH; - r += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} - -// text + (grph:interleave) -static void SCRNCALL SDSYM(p_ti)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || !bVFImport) { - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); -#endif - q += sdraw->xalign; - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - - if (sdraw->dirty[y+1]) { - for (x=0; xwidth; x++) { - SDSETPIXEL(q, (p[x] >> 4) + NP2PAL_TEXT); - q += sdraw->xalign; - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// grph:interleave -static void SCRNCALL SDSYM(p_gi)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); -#endif - q += sdraw->xalign; - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - - if (sdraw->dirty[y+1]) { - for (x=0; xwidth; x++) { - SDSETPIXEL(q, NP2PAL_TEXT); - q += sdraw->xalign; - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph:interleave -static void SCRNCALL SDSYM(p_2i)(SDRAW sdraw, int maxy) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int y; - int x; - - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || q[x]) { - SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, r, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); -#endif - r += sdraw->xalign; - } - r -= sdraw->xbytes; - } - q += SURFACE_WIDTH; - r += sdraw->yalign; - - if (sdraw->dirty[y+1]) { - for (x=0; xwidth; x++) { - SDSETPIXEL(r, (q[x] >> 4) + NP2PAL_TEXT); - r += sdraw->xalign; - } - r -= sdraw->xbytes; - } - p += (SURFACE_WIDTH * 2); - q += SURFACE_WIDTH; - r += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} - -// grph:interleave ex -static void SCRNCALL SDSYM(p_gie)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - sdraw->dirty[y+1] |= 0xff; - for (x=0; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || !bVFImport) { - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); -#endif - q += sdraw->xalign; - } - q -= sdraw->xbytes; - } - q += sdraw->yalign; - - if (sdraw->dirty[y+1]) { - for (x=0; xwidth; x++) { - SDSETPIXEL(q, p[x] + NP2PAL_SKIP); - q += sdraw->xalign; - } - q -= sdraw->xbytes; - } - p += (SURFACE_WIDTH * 2); - q += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph:interleave ex -static void SCRNCALL SDSYM(p_2ie)(SDRAW sdraw, int maxy) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int y; - int x; - UINT8 c; - - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - sdraw->dirty[y+1] |= 0xff; - for (x=0; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || q[x]) { - SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, r, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); -#endif - r += sdraw->xalign; - } - r -= sdraw->xbytes; - } - q += SURFACE_WIDTH; - r += sdraw->yalign; - - if (sdraw->dirty[y+1]) { - for (x=0; xwidth; x++) { - c = q[x] >> 4; - if (!c) { - c = p[x] + NP2PALS_TXT; - } - SDSETPIXEL(r, c + NP2PAL_TEXT); - r += sdraw->xalign; - } - r -= sdraw->xbytes; - } - p += (SURFACE_WIDTH * 2); - q += SURFACE_WIDTH; - r += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} - -#if defined(SUPPORT_CRT15KHZ) -// text or grph 1プレーン(15kHz) -static void SCRNCALL SDSYM(p_1d)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int a; - int y; - int x; - int c; - - p = sdraw->src; - q = sdraw->dst; - a = sdraw->yalign; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || !bVFImport) { - c = p[x] + NP2PAL_GRPH; - SDSETPIXEL(q, c); - SDSETPIXEL((q + a), c); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - VideoFilter_PutDest(hVFMng1, q + a, x, y, sdraw->xalign); - } -#else - c = p[x] + NP2PAL_GRPH; - SDSETPIXEL(q, c); - SDSETPIXEL((q + a), c); -#endif - q += sdraw->xalign; - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += a * 2; - } while(++y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph (15kHz) -static void SCRNCALL SDSYM(p_2d)(SDRAW sdraw, int maxy) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int a; - int y; - int x; - int c; - - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - a = sdraw->yalign; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || q[x]) { - c = p[x] + q[x] + NP2PAL_GRPH; - SDSETPIXEL(r, c); - SDSETPIXEL((r + a), c); - } else { - VideoFilter_PutDest(hVFMng1, r, x, y, sdraw->xalign); - VideoFilter_PutDest(hVFMng1, r + a, x, y, sdraw->xalign); - } -#else - c = p[x] + q[x] + NP2PAL_GRPH; - SDSETPIXEL(r, c); - SDSETPIXEL((r + a), c); -#endif - r += sdraw->xalign; - } - r -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += SURFACE_WIDTH; - r += a * 2; - } while(++y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} -#endif - -static const SDRAWFN SDSYM(p)[] = { - SDSYM(p_0), SDSYM(p_1), SDSYM(p_1), SDSYM(p_2), - SDSYM(p_0), SDSYM(p_ti), SDSYM(p_gi), SDSYM(p_2i), - SDSYM(p_0), SDSYM(p_ti), SDSYM(p_gie), SDSYM(p_2ie), -#if defined(SUPPORT_CRT15KHZ) - SDSYM(p_0), SDSYM(p_1d), SDSYM(p_1d), SDSYM(p_2d), -#endif - }; - -// ---- normal display - -#ifdef SUPPORT_NORMALDISP - -// vram off -static void SCRNCALL SDSYM(n_0)(SDRAW sdraw, int maxy) { - - UINT8 *p; - int y; - int x; - - p = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(p, NP2PAL_TEXT3); - for (x=0; xwidth; x++) { - p += sdraw->xalign; - SDSETPIXEL(p, NP2PAL_TEXT2); - } - p -= sdraw->xbytes; - } - p += sdraw->yalign; - } while(++y < maxy); - - sdraw->dst = p; - sdraw->y = y; -} - -// text 1プレーン -static void SCRNCALL SDSYM(n_t)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(q, (p[0] >> 4) + NP2PAL_TEXT3); - q += sdraw->xalign; - for (x=1; xwidth; x++) { - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); - q += sdraw->xalign; - } - SDSETPIXEL(q, NP2PAL_TEXT2); - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// grph 1プレーン -static void SCRNCALL SDSYM(n_g)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(q, NP2PAL_TEXT3); - for (x=0; xwidth; x++) { - q += sdraw->xalign; -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); -#endif - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph -static void SCRNCALL SDSYM(n_2)(SDRAW sdraw, int maxy) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int y; - int x; - - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); - r += sdraw->xalign; - for (x=1; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || q[x]) { - SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); - } -#else - SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); -#endif - r += sdraw->xalign; - } -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); - } -#else - SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); -#endif - r -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += SURFACE_WIDTH; - r += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} - -// text + (grph:interleave) -static void SCRNCALL SDSYM(n_ti)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(q, (p[0] >> 4) + NP2PAL_TEXT3); - q += sdraw->xalign; - for (x=1; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || !bVFImport) { - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); -#endif - q += sdraw->xalign; - } - SDSETPIXEL(q, NP2PAL_GRPH); - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - - if (sdraw->dirty[y+1]) { - SDSETPIXEL(q, (p[0] >> 4) + NP2PAL_TEXT3); - q += sdraw->xalign; - for (x=1; xwidth; x++) { - SDSETPIXEL(q, (p[x] >> 4) + NP2PAL_TEXT); - q += sdraw->xalign; - } - SDSETPIXEL(q, NP2PAL_TEXT); - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// grph:interleave -static void SCRNCALL SDSYM(n_gi)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(q, NP2PAL_TEXT3); - for (x=0; xwidth; x++) { - q += sdraw->xalign; -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); -#endif - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - - if (sdraw->dirty[y+1]) { - SDSETPIXEL(q, NP2PAL_TEXT3); - for (x=0; xwidth; x++) { - q += sdraw->xalign; - SDSETPIXEL(q, NP2PAL_TEXT); - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph:interleave -static void SCRNCALL SDSYM(n_2i)(SDRAW sdraw, int maxy) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int y; - int x; - - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); - r += sdraw->xalign; - for (x=1; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || q[x]) { - SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); - } -#else - SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); -#endif - r += sdraw->xalign; - } -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); - } -#else - SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); -#endif - r -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += SURFACE_WIDTH; - r += sdraw->yalign; - - if (sdraw->dirty[y+1]) { - SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); - r += sdraw->xalign; - for (x=1; xwidth; x++) { - SDSETPIXEL(r, (q[x] >> 4) + NP2PAL_TEXT); - r += sdraw->xalign; - } - SDSETPIXEL(r, NP2PAL_TEXT); - r -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += SURFACE_WIDTH; - r += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} - -// grph:interleave ex -static void SCRNCALL SDSYM(n_gie)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - sdraw->dirty[y+1] |= 0xff; - SDSETPIXEL(q, NP2PAL_TEXT3); - for (x=0; xwidth; x++) { - q += sdraw->xalign; -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(q, p[x] + NP2PAL_GRPH); -#endif - } - q -= sdraw->xbytes; - } - q += sdraw->yalign; - - if (sdraw->dirty[y+1]) { - SDSETPIXEL(q, NP2PAL_TEXT3); - for (x=0; xwidth; x++) { - q += sdraw->xalign; - SDSETPIXEL(q, p[x] + NP2PAL_SKIP); - } - q -= sdraw->xbytes; - } - p += (SURFACE_WIDTH * 2); - q += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph:interleave ex -static void SCRNCALL SDSYM(n_2ie)(SDRAW sdraw, int maxy) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int y; - int x; - UINT8 c; - - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - sdraw->dirty[y+1] |= 0xff; - SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); - r += sdraw->xalign; - for (x=1; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || q[x]) { - SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); - } -#else - SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); -#endif - r += sdraw->xalign; - } -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); - } else { - VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); - } -#else - SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); -#endif - r -= sdraw->xbytes; - } - q += SURFACE_WIDTH; - r += sdraw->yalign; - - if (sdraw->dirty[y+1]) { - SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); - r += sdraw->xalign; - for (x=1; xwidth; x++) { - c = q[x] >> 4; - if (!c) { - c = p[x-1] + NP2PALS_TXT; - } - SDSETPIXEL(r, c + NP2PAL_TEXT); - r += sdraw->xalign; - } - SDSETPIXEL(r, p[x-1] + NP2PAL_SKIP); - r -= sdraw->xbytes; - } - p += (SURFACE_WIDTH * 2); - q += SURFACE_WIDTH; - r += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} - -#if defined(SUPPORT_CRT15KHZ) -// text 1プレーン (15kHz) -static void SCRNCALL SDSYM(n_td)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int a; - int y; - int x; - int c; - - p = sdraw->src; - q = sdraw->dst; - a = sdraw->yalign; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - c = (p[0] >> 4) + NP2PAL_TEXT3; - SDSETPIXEL(q, c); - SDSETPIXEL((q + a), c); - q += sdraw->xalign; - for (x=1; xwidth; x++) { - c = p[x] + NP2PAL_GRPH; - SDSETPIXEL(q, c); - SDSETPIXEL((q + a), c); - q += sdraw->xalign; - } - SDSETPIXEL(q, NP2PAL_TEXT2); - SDSETPIXEL((q + a), NP2PAL_TEXT2); - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += a * 2; - } while(++y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// grph 1プレーン (15kHz) -static void SCRNCALL SDSYM(n_gd)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int a; - int y; - int x; - int c; - - p = sdraw->src; - q = sdraw->dst; - a = sdraw->yalign; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(q, NP2PAL_TEXT3); - SDSETPIXEL((q + a), NP2PAL_TEXT3); - for (x=0; xwidth; x++) { - q += sdraw->xalign; -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - c = p[x] + NP2PAL_GRPH; - SDSETPIXEL(q, c); - SDSETPIXEL((q + a), c); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - VideoFilter_PutDest(hVFMng1, q, x, y + 1, sdraw->xalign); - } -#else - c = p[x] + NP2PAL_GRPH; - SDSETPIXEL(q, c); - SDSETPIXEL((q + a), c); -#endif - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += a * 2; - } while(++y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph (15kHz) -static void SCRNCALL SDSYM(n_2d)(SDRAW sdraw, int maxy) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int a; - int y; - int x; - int c; - - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - a = sdraw->yalign; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - c = (q[0] >> 4) + NP2PAL_TEXT3; - SDSETPIXEL(r, c); - SDSETPIXEL((r + a), c); - r += sdraw->xalign; - for (x=1; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable || q[x]) { - c = p[x-1] + q[x] + NP2PAL_GRPH; - SDSETPIXEL(r, c); - SDSETPIXEL((r + a), c); - } else { - VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); - VideoFilter_PutDest(hVFMng1, r, x - 1, y + 1, sdraw->xalign); - } -#else - c = p[x-1] + q[x] + NP2PAL_GRPH; - SDSETPIXEL(r, c); - SDSETPIXEL((r + a), c); -#endif - r += sdraw->xalign; - } -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - c = p[x-1] + NP2PAL_GRPH; - SDSETPIXEL(r, c); - SDSETPIXEL((r + a), c); - } else { - VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); - VideoFilter_PutDest(hVFMng1, r, x - 1, y + 1, sdraw->xalign); - } -#else - c = p[x-1] + NP2PAL_GRPH; - SDSETPIXEL(r, c); - SDSETPIXEL((r + a), c); -#endif - r -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += SURFACE_WIDTH; - r += a * 2; - } while(++y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} -#endif - -static const SDRAWFN SDSYM(n)[] = { - SDSYM(n_0), SDSYM(n_t), SDSYM(n_g), SDSYM(n_2), - SDSYM(n_0), SDSYM(n_ti), SDSYM(n_gi), SDSYM(n_2i), - SDSYM(n_0), SDSYM(n_ti), SDSYM(n_gie), SDSYM(n_2ie), -#if defined(SUPPORT_CRT15KHZ) - SDSYM(n_0), SDSYM(n_td), SDSYM(n_gd), SDSYM(n_2d), -#endif - }; -#endif - + +// ---- plasma display + +// vram off +static void SCRNCALL SDSYM(p_0)(SDRAW sdraw, int maxy) { + + UINT8 *p; + int y; + int x; + + p = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { + SDSETPIXEL(p, NP2PAL_TEXT2); + p += sdraw->xalign; + } + p -= sdraw->xbytes; + } + p += sdraw->yalign; + } while(++y < maxy); + + sdraw->dst = p; + sdraw->y = y; +} + +// text or grph 1プレーン +static void SCRNCALL SDSYM(p_1)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || !bVFImport) { + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); +#endif + q += sdraw->xalign; + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph +static void SCRNCALL SDSYM(p_2)(SDRAW sdraw, int maxy) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int y; + int x; + + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || q[x]) { + SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, r, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); +#endif + r += sdraw->xalign; + } + r -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += SURFACE_WIDTH; + r += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} + +// text + (grph:interleave) +static void SCRNCALL SDSYM(p_ti)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || !bVFImport) { + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); +#endif + q += sdraw->xalign; + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + + if (sdraw->dirty[y+1]) { + for (x=0; xwidth; x++) { + SDSETPIXEL(q, (p[x] >> 4) + NP2PAL_TEXT); + q += sdraw->xalign; + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// grph:interleave +static void SCRNCALL SDSYM(p_gi)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); +#endif + q += sdraw->xalign; + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + + if (sdraw->dirty[y+1]) { + for (x=0; xwidth; x++) { + SDSETPIXEL(q, NP2PAL_TEXT); + q += sdraw->xalign; + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph:interleave +static void SCRNCALL SDSYM(p_2i)(SDRAW sdraw, int maxy) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int y; + int x; + + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || q[x]) { + SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, r, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); +#endif + r += sdraw->xalign; + } + r -= sdraw->xbytes; + } + q += SURFACE_WIDTH; + r += sdraw->yalign; + + if (sdraw->dirty[y+1]) { + for (x=0; xwidth; x++) { + SDSETPIXEL(r, (q[x] >> 4) + NP2PAL_TEXT); + r += sdraw->xalign; + } + r -= sdraw->xbytes; + } + p += (SURFACE_WIDTH * 2); + q += SURFACE_WIDTH; + r += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} + +// grph:interleave ex +static void SCRNCALL SDSYM(p_gie)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + sdraw->dirty[y+1] |= 0xff; + for (x=0; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || !bVFImport) { + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); +#endif + q += sdraw->xalign; + } + q -= sdraw->xbytes; + } + q += sdraw->yalign; + + if (sdraw->dirty[y+1]) { + for (x=0; xwidth; x++) { + SDSETPIXEL(q, p[x] + NP2PAL_SKIP); + q += sdraw->xalign; + } + q -= sdraw->xbytes; + } + p += (SURFACE_WIDTH * 2); + q += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph:interleave ex +static void SCRNCALL SDSYM(p_2ie)(SDRAW sdraw, int maxy) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int y; + int x; + UINT8 c; + + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + sdraw->dirty[y+1] |= 0xff; + for (x=0; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || q[x]) { + SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, r, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(r, p[x] + q[x] + NP2PAL_GRPH); +#endif + r += sdraw->xalign; + } + r -= sdraw->xbytes; + } + q += SURFACE_WIDTH; + r += sdraw->yalign; + + if (sdraw->dirty[y+1]) { + for (x=0; xwidth; x++) { + c = q[x] >> 4; + if (!c) { + c = p[x] + NP2PALS_TXT; + } + SDSETPIXEL(r, c + NP2PAL_TEXT); + r += sdraw->xalign; + } + r -= sdraw->xbytes; + } + p += (SURFACE_WIDTH * 2); + q += SURFACE_WIDTH; + r += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} + +#if defined(SUPPORT_CRT15KHZ) +// text or grph 1プレーン(15kHz) +static void SCRNCALL SDSYM(p_1d)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int a; + int y; + int x; + int c; + + p = sdraw->src; + q = sdraw->dst; + a = sdraw->yalign; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || !bVFImport) { + c = p[x] + NP2PAL_GRPH; + SDSETPIXEL(q, c); + SDSETPIXEL((q + a), c); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + VideoFilter_PutDest(hVFMng1, q + a, x, y, sdraw->xalign); + } +#else + c = p[x] + NP2PAL_GRPH; + SDSETPIXEL(q, c); + SDSETPIXEL((q + a), c); +#endif + q += sdraw->xalign; + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += a * 2; + } while(++y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph (15kHz) +static void SCRNCALL SDSYM(p_2d)(SDRAW sdraw, int maxy) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int a; + int y; + int x; + int c; + + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + a = sdraw->yalign; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || q[x]) { + c = p[x] + q[x] + NP2PAL_GRPH; + SDSETPIXEL(r, c); + SDSETPIXEL((r + a), c); + } else { + VideoFilter_PutDest(hVFMng1, r, x, y, sdraw->xalign); + VideoFilter_PutDest(hVFMng1, r + a, x, y, sdraw->xalign); + } +#else + c = p[x] + q[x] + NP2PAL_GRPH; + SDSETPIXEL(r, c); + SDSETPIXEL((r + a), c); +#endif + r += sdraw->xalign; + } + r -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += SURFACE_WIDTH; + r += a * 2; + } while(++y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} +#endif + +static const SDRAWFN SDSYM(p)[] = { + SDSYM(p_0), SDSYM(p_1), SDSYM(p_1), SDSYM(p_2), + SDSYM(p_0), SDSYM(p_ti), SDSYM(p_gi), SDSYM(p_2i), + SDSYM(p_0), SDSYM(p_ti), SDSYM(p_gie), SDSYM(p_2ie), +#if defined(SUPPORT_CRT15KHZ) + SDSYM(p_0), SDSYM(p_1d), SDSYM(p_1d), SDSYM(p_2d), +#endif + }; + +// ---- normal display + +#ifdef SUPPORT_NORMALDISP + +// vram off +static void SCRNCALL SDSYM(n_0)(SDRAW sdraw, int maxy) { + + UINT8 *p; + int y; + int x; + + p = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(p, NP2PAL_TEXT3); + for (x=0; xwidth; x++) { + p += sdraw->xalign; + SDSETPIXEL(p, NP2PAL_TEXT2); + } + p -= sdraw->xbytes; + } + p += sdraw->yalign; + } while(++y < maxy); + + sdraw->dst = p; + sdraw->y = y; +} + +// text 1プレーン +static void SCRNCALL SDSYM(n_t)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(q, (p[0] >> 4) + NP2PAL_TEXT3); + q += sdraw->xalign; + for (x=1; xwidth; x++) { + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); + q += sdraw->xalign; + } + SDSETPIXEL(q, NP2PAL_TEXT2); + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// grph 1プレーン +static void SCRNCALL SDSYM(n_g)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(q, NP2PAL_TEXT3); + for (x=0; xwidth; x++) { + q += sdraw->xalign; +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); +#endif + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph +static void SCRNCALL SDSYM(n_2)(SDRAW sdraw, int maxy) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int y; + int x; + + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); + r += sdraw->xalign; + for (x=1; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || q[x]) { + SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); + } +#else + SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); +#endif + r += sdraw->xalign; + } +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); + } +#else + SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); +#endif + r -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += SURFACE_WIDTH; + r += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} + +// text + (grph:interleave) +static void SCRNCALL SDSYM(n_ti)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(q, (p[0] >> 4) + NP2PAL_TEXT3); + q += sdraw->xalign; + for (x=1; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || !bVFImport) { + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); +#endif + q += sdraw->xalign; + } + SDSETPIXEL(q, NP2PAL_GRPH); + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + + if (sdraw->dirty[y+1]) { + SDSETPIXEL(q, (p[0] >> 4) + NP2PAL_TEXT3); + q += sdraw->xalign; + for (x=1; xwidth; x++) { + SDSETPIXEL(q, (p[x] >> 4) + NP2PAL_TEXT); + q += sdraw->xalign; + } + SDSETPIXEL(q, NP2PAL_TEXT); + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// grph:interleave +static void SCRNCALL SDSYM(n_gi)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(q, NP2PAL_TEXT3); + for (x=0; xwidth; x++) { + q += sdraw->xalign; +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); +#endif + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + + if (sdraw->dirty[y+1]) { + SDSETPIXEL(q, NP2PAL_TEXT3); + for (x=0; xwidth; x++) { + q += sdraw->xalign; + SDSETPIXEL(q, NP2PAL_TEXT); + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph:interleave +static void SCRNCALL SDSYM(n_2i)(SDRAW sdraw, int maxy) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int y; + int x; + + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); + r += sdraw->xalign; + for (x=1; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || q[x]) { + SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); + } +#else + SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); +#endif + r += sdraw->xalign; + } +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); + } +#else + SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); +#endif + r -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += SURFACE_WIDTH; + r += sdraw->yalign; + + if (sdraw->dirty[y+1]) { + SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); + r += sdraw->xalign; + for (x=1; xwidth; x++) { + SDSETPIXEL(r, (q[x] >> 4) + NP2PAL_TEXT); + r += sdraw->xalign; + } + SDSETPIXEL(r, NP2PAL_TEXT); + r -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += SURFACE_WIDTH; + r += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} + +// grph:interleave ex +static void SCRNCALL SDSYM(n_gie)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + sdraw->dirty[y+1] |= 0xff; + SDSETPIXEL(q, NP2PAL_TEXT3); + for (x=0; xwidth; x++) { + q += sdraw->xalign; +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(q, p[x] + NP2PAL_GRPH); +#endif + } + q -= sdraw->xbytes; + } + q += sdraw->yalign; + + if (sdraw->dirty[y+1]) { + SDSETPIXEL(q, NP2PAL_TEXT3); + for (x=0; xwidth; x++) { + q += sdraw->xalign; + SDSETPIXEL(q, p[x] + NP2PAL_SKIP); + } + q -= sdraw->xbytes; + } + p += (SURFACE_WIDTH * 2); + q += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph:interleave ex +static void SCRNCALL SDSYM(n_2ie)(SDRAW sdraw, int maxy) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int y; + int x; + UINT8 c; + + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + sdraw->dirty[y+1] |= 0xff; + SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); + r += sdraw->xalign; + for (x=1; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || q[x]) { + SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); + } +#else + SDSETPIXEL(r, p[x-1] + q[x] + NP2PAL_GRPH); +#endif + r += sdraw->xalign; + } +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); + } else { + VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); + } +#else + SDSETPIXEL(r, p[x-1] + NP2PAL_GRPH); +#endif + r -= sdraw->xbytes; + } + q += SURFACE_WIDTH; + r += sdraw->yalign; + + if (sdraw->dirty[y+1]) { + SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); + r += sdraw->xalign; + for (x=1; xwidth; x++) { + c = q[x] >> 4; + if (!c) { + c = p[x-1] + NP2PALS_TXT; + } + SDSETPIXEL(r, c + NP2PAL_TEXT); + r += sdraw->xalign; + } + SDSETPIXEL(r, p[x-1] + NP2PAL_SKIP); + r -= sdraw->xbytes; + } + p += (SURFACE_WIDTH * 2); + q += SURFACE_WIDTH; + r += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} + +#if defined(SUPPORT_CRT15KHZ) +// text 1プレーン (15kHz) +static void SCRNCALL SDSYM(n_td)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int a; + int y; + int x; + int c; + + p = sdraw->src; + q = sdraw->dst; + a = sdraw->yalign; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + c = (p[0] >> 4) + NP2PAL_TEXT3; + SDSETPIXEL(q, c); + SDSETPIXEL((q + a), c); + q += sdraw->xalign; + for (x=1; xwidth; x++) { + c = p[x] + NP2PAL_GRPH; + SDSETPIXEL(q, c); + SDSETPIXEL((q + a), c); + q += sdraw->xalign; + } + SDSETPIXEL(q, NP2PAL_TEXT2); + SDSETPIXEL((q + a), NP2PAL_TEXT2); + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += a * 2; + } while(++y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// grph 1プレーン (15kHz) +static void SCRNCALL SDSYM(n_gd)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int a; + int y; + int x; + int c; + + p = sdraw->src; + q = sdraw->dst; + a = sdraw->yalign; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(q, NP2PAL_TEXT3); + SDSETPIXEL((q + a), NP2PAL_TEXT3); + for (x=0; xwidth; x++) { + q += sdraw->xalign; +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + c = p[x] + NP2PAL_GRPH; + SDSETPIXEL(q, c); + SDSETPIXEL((q + a), c); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + VideoFilter_PutDest(hVFMng1, q, x, y + 1, sdraw->xalign); + } +#else + c = p[x] + NP2PAL_GRPH; + SDSETPIXEL(q, c); + SDSETPIXEL((q + a), c); +#endif + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += a * 2; + } while(++y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph (15kHz) +static void SCRNCALL SDSYM(n_2d)(SDRAW sdraw, int maxy) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int a; + int y; + int x; + int c; + + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + a = sdraw->yalign; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + c = (q[0] >> 4) + NP2PAL_TEXT3; + SDSETPIXEL(r, c); + SDSETPIXEL((r + a), c); + r += sdraw->xalign; + for (x=1; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable || q[x]) { + c = p[x-1] + q[x] + NP2PAL_GRPH; + SDSETPIXEL(r, c); + SDSETPIXEL((r + a), c); + } else { + VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); + VideoFilter_PutDest(hVFMng1, r, x - 1, y + 1, sdraw->xalign); + } +#else + c = p[x-1] + q[x] + NP2PAL_GRPH; + SDSETPIXEL(r, c); + SDSETPIXEL((r + a), c); +#endif + r += sdraw->xalign; + } +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + c = p[x-1] + NP2PAL_GRPH; + SDSETPIXEL(r, c); + SDSETPIXEL((r + a), c); + } else { + VideoFilter_PutDest(hVFMng1, r, x - 1, y, sdraw->xalign); + VideoFilter_PutDest(hVFMng1, r, x - 1, y + 1, sdraw->xalign); + } +#else + c = p[x-1] + NP2PAL_GRPH; + SDSETPIXEL(r, c); + SDSETPIXEL((r + a), c); +#endif + r -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += SURFACE_WIDTH; + r += a * 2; + } while(++y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} +#endif + +static const SDRAWFN SDSYM(n)[] = { + SDSYM(n_0), SDSYM(n_t), SDSYM(n_g), SDSYM(n_2), + SDSYM(n_0), SDSYM(n_ti), SDSYM(n_gi), SDSYM(n_2i), + SDSYM(n_0), SDSYM(n_ti), SDSYM(n_gie), SDSYM(n_2ie), +#if defined(SUPPORT_CRT15KHZ) + SDSYM(n_0), SDSYM(n_td), SDSYM(n_gd), SDSYM(n_2d), +#endif + }; +#endif + diff --git a/vram/sdrawex.mcr b/vram/sdrawex.mcr old mode 100755 new mode 100644 index a072fb6d..9427bc30 --- a/vram/sdrawex.mcr +++ b/vram/sdrawex.mcr @@ -1,302 +1,302 @@ - -#if defined(SUPPORT_PC9821) - -// ---- plasma display - -// vram off -static void SCRNCALL SDSYM(pex_0)(SDRAW sdraw, int maxy) { - - UINT8 *p; - int y; - int x; - - p = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { - SDSETPIXEL(p, NP2PAL_TEXTEX); - p += sdraw->xalign; - } - p -= sdraw->xbytes; - } - p += sdraw->yalign; - } while(++y < maxy); - - sdraw->dst = p; - sdraw->y = y; -} - -// text 1プレーン -static void SCRNCALL SDSYM(pex_t)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { - SDSETPIXEL(q, (p[x] >> 4) + NP2PAL_TEXTEX); - q += sdraw->xalign; - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// grph 1プレーン -static void SCRNCALL SDSYM(pex_g)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - SDSETPIXEL(q, p[x] + NP2PAL_GRPHEX); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(q, p[x] + NP2PAL_GRPHEX); -#endif - q += sdraw->xalign; - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph -static void SCRNCALL SDSYM(pex_2)(SDRAW sdraw, int maxy) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int y; - int x; - int c; - - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x++) { - c = q[x]; - if (c != 0) { - c = (c >> 4) + NP2PAL_TEXTEX; - } - else { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - c = p[x] + NP2PAL_GRPHEX; - } else { - VideoFilter_PutDest(hVFMng1, &c, x, y, sdraw->xalign); - } -#else - c = p[x] + NP2PAL_GRPHEX; -#endif - } - SDSETPIXEL(r, c); - r += sdraw->xalign; - } - r -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += SURFACE_WIDTH; - r += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} - - -static const SDRAWFN SDSYM(pex)[] = { - SDSYM(pex_0), SDSYM(pex_t), SDSYM(pex_g), SDSYM(pex_2), - }; - - -// ---- normal display - -#ifdef SUPPORT_NORMALDISP - -// vram off -static void SCRNCALL SDSYM(nex_0)(SDRAW sdraw, int maxy) { - - UINT8 *p; - int y; - int x; - - p = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(p, NP2PAL_TEXTEX3); - for (x=0; xwidth; x++) { - p += sdraw->xalign; - SDSETPIXEL(p, NP2PAL_TEXTEX); - } - p -= sdraw->xbytes; - } - p += sdraw->yalign; - } while(++y < maxy); - - sdraw->dst = p; - sdraw->y = y; -} - -// text 1プレーン -static void SCRNCALL SDSYM(nex_t)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(q, (p[0] >> 4) + NP2PAL_TEXTEX3); - q += sdraw->xalign; - for (x=1; xwidth; x++) { - SDSETPIXEL(q, (p[x] >> 4) + NP2PAL_TEXTEX); - q += sdraw->xalign; - } - SDSETPIXEL(q, NP2PAL_TEXTEX); - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// grph 1プレーン -static void SCRNCALL SDSYM(nex_g)(SDRAW sdraw, int maxy) { - -const UINT8 *p; - UINT8 *q; - int y; - int x; - - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(q, NP2PAL_TEXTEX3); - for (x=0; xwidth; x++) { - q += sdraw->xalign; -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - SDSETPIXEL(q, p[x] + NP2PAL_GRPHEX); - } else { - VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); - } -#else - SDSETPIXEL(q, p[x] + NP2PAL_GRPHEX); -#endif - } - q -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph -static void SCRNCALL SDSYM(nex_2)(SDRAW sdraw, int maxy) { - -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int y; - int x; - int c; - - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); - r += sdraw->xalign; - for (x=1; xwidth; x++) { - c = q[x]; - if (c) { - c = (c >> 4) + NP2PAL_TEXTEX; - } - else { -#if defined(SUPPORT_VIDEOFILTER) - if(!bVFEnable) { - c = p[x-1] + NP2PAL_GRPHEX; - } else { - VideoFilter_PutDest(hVFMng1, &c, x - 1, y, sdraw->xalign); - } -#else - c = p[x-1] + NP2PAL_GRPHEX; -#endif - } - SDSETPIXEL(r, c); - r += sdraw->xalign; - } - SDSETPIXEL(r, p[x-1] + NP2PAL_GRPHEX); - r -= sdraw->xbytes; - } - p += SURFACE_WIDTH; - q += SURFACE_WIDTH; - r += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} - -static const SDRAWFN SDSYM(nex)[] = { - SDSYM(nex_0), SDSYM(nex_t), SDSYM(nex_g), SDSYM(nex_2) - }; -#endif - -#endif - + +#if defined(SUPPORT_PC9821) + +// ---- plasma display + +// vram off +static void SCRNCALL SDSYM(pex_0)(SDRAW sdraw, int maxy) { + + UINT8 *p; + int y; + int x; + + p = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { + SDSETPIXEL(p, NP2PAL_TEXTEX); + p += sdraw->xalign; + } + p -= sdraw->xbytes; + } + p += sdraw->yalign; + } while(++y < maxy); + + sdraw->dst = p; + sdraw->y = y; +} + +// text 1プレーン +static void SCRNCALL SDSYM(pex_t)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { + SDSETPIXEL(q, (p[x] >> 4) + NP2PAL_TEXTEX); + q += sdraw->xalign; + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// grph 1プレーン +static void SCRNCALL SDSYM(pex_g)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + SDSETPIXEL(q, p[x] + NP2PAL_GRPHEX); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(q, p[x] + NP2PAL_GRPHEX); +#endif + q += sdraw->xalign; + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph +static void SCRNCALL SDSYM(pex_2)(SDRAW sdraw, int maxy) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int y; + int x; + int c; + + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x++) { + c = q[x]; + if (c != 0) { + c = (c >> 4) + NP2PAL_TEXTEX; + } + else { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + c = p[x] + NP2PAL_GRPHEX; + } else { + VideoFilter_PutDest(hVFMng1, &c, x, y, sdraw->xalign); + } +#else + c = p[x] + NP2PAL_GRPHEX; +#endif + } + SDSETPIXEL(r, c); + r += sdraw->xalign; + } + r -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += SURFACE_WIDTH; + r += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} + + +static const SDRAWFN SDSYM(pex)[] = { + SDSYM(pex_0), SDSYM(pex_t), SDSYM(pex_g), SDSYM(pex_2), + }; + + +// ---- normal display + +#ifdef SUPPORT_NORMALDISP + +// vram off +static void SCRNCALL SDSYM(nex_0)(SDRAW sdraw, int maxy) { + + UINT8 *p; + int y; + int x; + + p = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(p, NP2PAL_TEXTEX3); + for (x=0; xwidth; x++) { + p += sdraw->xalign; + SDSETPIXEL(p, NP2PAL_TEXTEX); + } + p -= sdraw->xbytes; + } + p += sdraw->yalign; + } while(++y < maxy); + + sdraw->dst = p; + sdraw->y = y; +} + +// text 1プレーン +static void SCRNCALL SDSYM(nex_t)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(q, (p[0] >> 4) + NP2PAL_TEXTEX3); + q += sdraw->xalign; + for (x=1; xwidth; x++) { + SDSETPIXEL(q, (p[x] >> 4) + NP2PAL_TEXTEX); + q += sdraw->xalign; + } + SDSETPIXEL(q, NP2PAL_TEXTEX); + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// grph 1プレーン +static void SCRNCALL SDSYM(nex_g)(SDRAW sdraw, int maxy) { + +const UINT8 *p; + UINT8 *q; + int y; + int x; + + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(q, NP2PAL_TEXTEX3); + for (x=0; xwidth; x++) { + q += sdraw->xalign; +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + SDSETPIXEL(q, p[x] + NP2PAL_GRPHEX); + } else { + VideoFilter_PutDest(hVFMng1, q, x, y, sdraw->xalign); + } +#else + SDSETPIXEL(q, p[x] + NP2PAL_GRPHEX); +#endif + } + q -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph +static void SCRNCALL SDSYM(nex_2)(SDRAW sdraw, int maxy) { + +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int y; + int x; + int c; + + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + SDSETPIXEL(r, (q[0] >> 4) + NP2PAL_TEXT3); + r += sdraw->xalign; + for (x=1; xwidth; x++) { + c = q[x]; + if (c) { + c = (c >> 4) + NP2PAL_TEXTEX; + } + else { +#if defined(SUPPORT_VIDEOFILTER) + if(!bVFEnable) { + c = p[x-1] + NP2PAL_GRPHEX; + } else { + VideoFilter_PutDest(hVFMng1, &c, x - 1, y, sdraw->xalign); + } +#else + c = p[x-1] + NP2PAL_GRPHEX; +#endif + } + SDSETPIXEL(r, c); + r += sdraw->xalign; + } + SDSETPIXEL(r, p[x-1] + NP2PAL_GRPHEX); + r -= sdraw->xbytes; + } + p += SURFACE_WIDTH; + q += SURFACE_WIDTH; + r += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} + +static const SDRAWFN SDSYM(nex)[] = { + SDSYM(nex_0), SDSYM(nex_t), SDSYM(nex_g), SDSYM(nex_2) + }; +#endif + +#endif + diff --git a/vram/sdrawq16.c b/vram/sdrawq16.c old mode 100755 new mode 100644 index e7411174..28d9f94c --- a/vram/sdrawq16.c +++ b/vram/sdrawq16.c @@ -1,306 +1,306 @@ -#include -#include -#include -#include "sdraw.h" -#include - - -#if defined(NP2_SIZE_QVGA) && !defined(SIZE_VGATEST) && defined(SUPPORT_16BPP) - -// vram off -static void SCRNCALL qvga16p_0(SDRAW sdraw, int maxy) { - - int xbytes; - UINT32 palwork; - UINT16 pal; - UINT8 *p; - int y; - int x; - - xbytes = sdraw->xalign * sdraw->width / 2; - palwork = np2_pal16[NP2PAL_TEXT2]; - pal = (UINT16)(palwork + (palwork >> 16)); - p = sdraw->dst; - y = sdraw->y; - do { - if (*(UINT16 *)(sdraw->dirty + y)) { - for (x=0; xwidth; x+=2) { - *(UINT16 *)p = pal; - p += sdraw->xalign; - } - p -= xbytes; - } - p += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->dst = p; - sdraw->y = y; -} - -// text or grph 1プレーン -static void SCRNCALL qvga16p_1(SDRAW sdraw, int maxy) { - - int xbytes; -const UINT8 *p; - UINT8 *q; - int y; - int x; - UINT32 work; - - xbytes = sdraw->xalign * sdraw->width / 2; - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (*(UINT16 *)(sdraw->dirty + y)) { - for (x=0; xwidth; x+=2) { - work = np2_pal16[p[x+0] + NP2PAL_GRPH]; - work += np2_pal16[p[x+1] + NP2PAL_GRPH]; - work += np2_pal16[p[x+0+SURFACE_WIDTH] + NP2PAL_GRPH]; - work += np2_pal16[p[x+1+SURFACE_WIDTH] + NP2PAL_GRPH]; - work &= 0x07e0f81f << 2; - *(UINT16 *)q = (UINT16)((work >> 2) + (work >> 18)); - q += sdraw->xalign; - } - q -= xbytes; - } - p += SURFACE_WIDTH * 2; - q += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph -static void SCRNCALL qvga16p_2(SDRAW sdraw, int maxy) { - - int xbytes; -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int y; - int x; - UINT32 work; - - xbytes = sdraw->xalign * sdraw->width / 2; - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - y = sdraw->y; - do { - if (*(UINT16 *)(sdraw->dirty + y)) { - for (x=0; xwidth; x+=2) { - work = np2_pal16[p[x+0] + q[x+0] + NP2PAL_GRPH]; - work += np2_pal16[p[x+1] + q[x+1] + NP2PAL_GRPH]; - work += np2_pal16[p[x+0+SURFACE_WIDTH] + - q[x+0+SURFACE_WIDTH] + NP2PAL_GRPH]; - work += np2_pal16[p[x+1+SURFACE_WIDTH] + - q[x+1+SURFACE_WIDTH] + NP2PAL_GRPH]; - work &= 0x07e0f81f << 2; - *(UINT16 *)r = (UINT16)((work >> 2) + (work >> 18)); - r += sdraw->xalign; - } - r -= xbytes; - } - p += SURFACE_WIDTH * 2; - q += SURFACE_WIDTH * 2; - r += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} - -// text + (grph:interleave) - > qvga16p_1 - -// grph:interleave -static void SCRNCALL qvga16p_gi(SDRAW sdraw, int maxy) { - - int xbytes; -const UINT8 *p; - UINT8 *q; - int y; - int x; - UINT32 work; - - xbytes = sdraw->xalign * sdraw->width / 2; - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (*(UINT16 *)(sdraw->dirty + y)) { - for (x=0; xwidth; x+=2) { - work = np2_pal16[p[x+0] + NP2PAL_GRPH]; - work += np2_pal16[p[x+1] + NP2PAL_GRPH]; - work &= 0x07e0f81f << 1; - *(UINT16 *)q = (UINT16)((work >> 1) + (work >> 17)); - q += sdraw->xalign; - } - q -= xbytes; - } - p += SURFACE_WIDTH * 2; - q += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph:interleave -static void SCRNCALL qvga16p_2i(SDRAW sdraw, int maxy) { - - int xbytes; -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int y; - int x; - UINT32 work; - - xbytes = sdraw->xalign * sdraw->width / 2; - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - y = sdraw->y; - do { - if (*(UINT16 *)(sdraw->dirty + y)) { - for (x=0; xwidth; x+=2) { - work = np2_pal16[p[x+0] + q[x+0] + NP2PAL_GRPH]; - work += np2_pal16[p[x+1] + q[x+1] + NP2PAL_GRPH]; - if (q[x+0+SURFACE_WIDTH] & 0xf0) { - work += np2_pal16[(q[x+0+SURFACE_WIDTH] >> 4) - + NP2PAL_TEXT]; - } - else { - work += np2_pal16[p[x+0] + NP2PAL_GRPH]; - } - if (q[x+1+SURFACE_WIDTH] & 0xf0) { - work += np2_pal16[(q[x+1+SURFACE_WIDTH] >> 4) - + NP2PAL_TEXT]; - } - else { - work += np2_pal16[p[x+1] + NP2PAL_GRPH]; - } - work &= 0x07e0f81f << 2; - *(UINT16 *)r = (UINT16)((work >> 2) + (work >> 18)); - r += sdraw->xalign; - } - r -= xbytes; - } - p += SURFACE_WIDTH * 2; - q += SURFACE_WIDTH * 2; - r += sdraw->yalign; - y += 2; - } while(y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} - -#if defined(SUPPORT_CRT15KHZ) -// text or grph 1プレーン (15kHz) -static void SCRNCALL qvga16p_1d(SDRAW sdraw, int maxy) { - - int xbytes; -const UINT8 *p; - UINT8 *q; - int y; - int x; - UINT32 work; - - xbytes = sdraw->xalign * sdraw->width / 2; - p = sdraw->src; - q = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x+=2) { - work = np2_pal16[p[x+0] + NP2PAL_GRPH]; - work += np2_pal16[p[x+1] + NP2PAL_GRPH]; - work &= 0x07e0f81f << 1; - *(UINT16 *)q = (UINT16)((work >> 1) + (work >> 17)); - q += sdraw->xalign; - } - q -= xbytes; - } - p += SURFACE_WIDTH; - q += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->dst = q; - sdraw->y = y; -} - -// text + grph (15kHz) -static void SCRNCALL qvga16p_2d(SDRAW sdraw, int maxy) { - - int xbytes; -const UINT8 *p; -const UINT8 *q; - UINT8 *r; - int y; - int x; - UINT32 work; - - xbytes = sdraw->xalign * sdraw->width / 2; - p = sdraw->src; - q = sdraw->src2; - r = sdraw->dst; - y = sdraw->y; - do { - if (sdraw->dirty[y]) { - for (x=0; xwidth; x+=2) { - work = np2_pal16[p[x+0] + q[x+0] + NP2PAL_GRPH]; - work += np2_pal16[p[x+1] + q[x+1] + NP2PAL_GRPH]; - work &= 0x07e0f81f << 1; - *(UINT16 *)r = (UINT16)((work >> 1) + (work >> 17)); - r += sdraw->xalign; - } - r -= xbytes; - } - p += SURFACE_WIDTH; - q += SURFACE_WIDTH; - r += sdraw->yalign; - } while(++y < maxy); - - sdraw->src = p; - sdraw->src2 = q; - sdraw->dst = r; - sdraw->y = y; -} -#endif - - -static const SDRAWFN qvga16p[] = { - qvga16p_0, qvga16p_1, qvga16p_1, qvga16p_2, - qvga16p_0, qvga16p_1, qvga16p_gi, qvga16p_2i, - qvga16p_0, qvga16p_1, qvga16p_gi, qvga16p_2i, -#if defined(SUPPORT_CRT15KHZ) - qvga16p_0, qvga16p_1d, qvga16p_1d, qvga16p_2d, -#endif - }; - -const SDRAWFN *sdraw_getproctbl(const SCRNSURF *surf) { - - if (surf->bpp == 16) { - return(qvga16p); - } - else { - return(NULL); - } -} - -#endif - +#include +#include +#include +#include "sdraw.h" +#include + + +#if defined(NP2_SIZE_QVGA) && !defined(SIZE_VGATEST) && defined(SUPPORT_16BPP) + +// vram off +static void SCRNCALL qvga16p_0(SDRAW sdraw, int maxy) { + + int xbytes; + UINT32 palwork; + UINT16 pal; + UINT8 *p; + int y; + int x; + + xbytes = sdraw->xalign * sdraw->width / 2; + palwork = np2_pal16[NP2PAL_TEXT2]; + pal = (UINT16)(palwork + (palwork >> 16)); + p = sdraw->dst; + y = sdraw->y; + do { + if (*(UINT16 *)(sdraw->dirty + y)) { + for (x=0; xwidth; x+=2) { + *(UINT16 *)p = pal; + p += sdraw->xalign; + } + p -= xbytes; + } + p += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->dst = p; + sdraw->y = y; +} + +// text or grph 1プレーン +static void SCRNCALL qvga16p_1(SDRAW sdraw, int maxy) { + + int xbytes; +const UINT8 *p; + UINT8 *q; + int y; + int x; + UINT32 work; + + xbytes = sdraw->xalign * sdraw->width / 2; + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (*(UINT16 *)(sdraw->dirty + y)) { + for (x=0; xwidth; x+=2) { + work = np2_pal16[p[x+0] + NP2PAL_GRPH]; + work += np2_pal16[p[x+1] + NP2PAL_GRPH]; + work += np2_pal16[p[x+0+SURFACE_WIDTH] + NP2PAL_GRPH]; + work += np2_pal16[p[x+1+SURFACE_WIDTH] + NP2PAL_GRPH]; + work &= 0x07e0f81f << 2; + *(UINT16 *)q = (UINT16)((work >> 2) + (work >> 18)); + q += sdraw->xalign; + } + q -= xbytes; + } + p += SURFACE_WIDTH * 2; + q += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph +static void SCRNCALL qvga16p_2(SDRAW sdraw, int maxy) { + + int xbytes; +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int y; + int x; + UINT32 work; + + xbytes = sdraw->xalign * sdraw->width / 2; + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + y = sdraw->y; + do { + if (*(UINT16 *)(sdraw->dirty + y)) { + for (x=0; xwidth; x+=2) { + work = np2_pal16[p[x+0] + q[x+0] + NP2PAL_GRPH]; + work += np2_pal16[p[x+1] + q[x+1] + NP2PAL_GRPH]; + work += np2_pal16[p[x+0+SURFACE_WIDTH] + + q[x+0+SURFACE_WIDTH] + NP2PAL_GRPH]; + work += np2_pal16[p[x+1+SURFACE_WIDTH] + + q[x+1+SURFACE_WIDTH] + NP2PAL_GRPH]; + work &= 0x07e0f81f << 2; + *(UINT16 *)r = (UINT16)((work >> 2) + (work >> 18)); + r += sdraw->xalign; + } + r -= xbytes; + } + p += SURFACE_WIDTH * 2; + q += SURFACE_WIDTH * 2; + r += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} + +// text + (grph:interleave) - > qvga16p_1 + +// grph:interleave +static void SCRNCALL qvga16p_gi(SDRAW sdraw, int maxy) { + + int xbytes; +const UINT8 *p; + UINT8 *q; + int y; + int x; + UINT32 work; + + xbytes = sdraw->xalign * sdraw->width / 2; + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (*(UINT16 *)(sdraw->dirty + y)) { + for (x=0; xwidth; x+=2) { + work = np2_pal16[p[x+0] + NP2PAL_GRPH]; + work += np2_pal16[p[x+1] + NP2PAL_GRPH]; + work &= 0x07e0f81f << 1; + *(UINT16 *)q = (UINT16)((work >> 1) + (work >> 17)); + q += sdraw->xalign; + } + q -= xbytes; + } + p += SURFACE_WIDTH * 2; + q += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph:interleave +static void SCRNCALL qvga16p_2i(SDRAW sdraw, int maxy) { + + int xbytes; +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int y; + int x; + UINT32 work; + + xbytes = sdraw->xalign * sdraw->width / 2; + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + y = sdraw->y; + do { + if (*(UINT16 *)(sdraw->dirty + y)) { + for (x=0; xwidth; x+=2) { + work = np2_pal16[p[x+0] + q[x+0] + NP2PAL_GRPH]; + work += np2_pal16[p[x+1] + q[x+1] + NP2PAL_GRPH]; + if (q[x+0+SURFACE_WIDTH] & 0xf0) { + work += np2_pal16[(q[x+0+SURFACE_WIDTH] >> 4) + + NP2PAL_TEXT]; + } + else { + work += np2_pal16[p[x+0] + NP2PAL_GRPH]; + } + if (q[x+1+SURFACE_WIDTH] & 0xf0) { + work += np2_pal16[(q[x+1+SURFACE_WIDTH] >> 4) + + NP2PAL_TEXT]; + } + else { + work += np2_pal16[p[x+1] + NP2PAL_GRPH]; + } + work &= 0x07e0f81f << 2; + *(UINT16 *)r = (UINT16)((work >> 2) + (work >> 18)); + r += sdraw->xalign; + } + r -= xbytes; + } + p += SURFACE_WIDTH * 2; + q += SURFACE_WIDTH * 2; + r += sdraw->yalign; + y += 2; + } while(y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} + +#if defined(SUPPORT_CRT15KHZ) +// text or grph 1プレーン (15kHz) +static void SCRNCALL qvga16p_1d(SDRAW sdraw, int maxy) { + + int xbytes; +const UINT8 *p; + UINT8 *q; + int y; + int x; + UINT32 work; + + xbytes = sdraw->xalign * sdraw->width / 2; + p = sdraw->src; + q = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x+=2) { + work = np2_pal16[p[x+0] + NP2PAL_GRPH]; + work += np2_pal16[p[x+1] + NP2PAL_GRPH]; + work &= 0x07e0f81f << 1; + *(UINT16 *)q = (UINT16)((work >> 1) + (work >> 17)); + q += sdraw->xalign; + } + q -= xbytes; + } + p += SURFACE_WIDTH; + q += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->dst = q; + sdraw->y = y; +} + +// text + grph (15kHz) +static void SCRNCALL qvga16p_2d(SDRAW sdraw, int maxy) { + + int xbytes; +const UINT8 *p; +const UINT8 *q; + UINT8 *r; + int y; + int x; + UINT32 work; + + xbytes = sdraw->xalign * sdraw->width / 2; + p = sdraw->src; + q = sdraw->src2; + r = sdraw->dst; + y = sdraw->y; + do { + if (sdraw->dirty[y]) { + for (x=0; xwidth; x+=2) { + work = np2_pal16[p[x+0] + q[x+0] + NP2PAL_GRPH]; + work += np2_pal16[p[x+1] + q[x+1] + NP2PAL_GRPH]; + work &= 0x07e0f81f << 1; + *(UINT16 *)r = (UINT16)((work >> 1) + (work >> 17)); + r += sdraw->xalign; + } + r -= xbytes; + } + p += SURFACE_WIDTH; + q += SURFACE_WIDTH; + r += sdraw->yalign; + } while(++y < maxy); + + sdraw->src = p; + sdraw->src2 = q; + sdraw->dst = r; + sdraw->y = y; +} +#endif + + +static const SDRAWFN qvga16p[] = { + qvga16p_0, qvga16p_1, qvga16p_1, qvga16p_2, + qvga16p_0, qvga16p_1, qvga16p_gi, qvga16p_2i, + qvga16p_0, qvga16p_1, qvga16p_gi, qvga16p_2i, +#if defined(SUPPORT_CRT15KHZ) + qvga16p_0, qvga16p_1d, qvga16p_1d, qvga16p_2d, +#endif + }; + +const SDRAWFN *sdraw_getproctbl(const SCRNSURF *surf) { + + if (surf->bpp == 16) { + return(qvga16p); + } + else { + return(NULL); + } +} + +#endif + diff --git a/vram/vram.c b/vram/vram.c old mode 100755 new mode 100644 index 85e1ca75..acf89bc9 --- a/vram/vram.c +++ b/vram/vram.c @@ -1,24 +1,24 @@ -#include -#include -#include - - - _VRAMOP vramop; - UINT8 tramupdate[0x1000]; - UINT8 vramupdate[0x8000]; -#if defined(SUPPORT_PC9821) -#if defined(SUPPORT_IA32_HAXM) - UINT8 vramex_base[0x80000]; // PEGC VRAM - UINT8 *vramex = vramex_base; // PEGC VRAM Alloc in pccore_mem_malloc() -#else - UINT8 vramex[0x80000]; // PEGC VRAM -#endif -#endif - - -void vram_initialize(void) { - - ZeroMemory(&vramop, sizeof(vramop)); - MEMM_VRAM(0); -} - +#include +#include +#include + + + _VRAMOP vramop; + UINT8 tramupdate[0x1000]; + UINT8 vramupdate[0x8000]; +#if defined(SUPPORT_PC9821) +#if defined(SUPPORT_IA32_HAXM) + UINT8 vramex_base[0x80000]; // PEGC VRAM + UINT8 *vramex = vramex_base; // PEGC VRAM Alloc in pccore_mem_malloc() +#else + UINT8 vramex[0x80000]; // PEGC VRAM +#endif +#endif + + +void vram_initialize(void) { + + ZeroMemory(&vramop, sizeof(vramop)); + MEMM_VRAM(0); +} + diff --git a/vram/vram.h b/vram/vram.h old mode 100755 new mode 100644 index 7aa64a56..6cc2fc31 --- a/vram/vram.h +++ b/vram/vram.h @@ -1,73 +1,73 @@ - -#ifndef VRAMCALL -#define VRAMCALL -#endif - - -typedef struct { - UINT operate; -#if !defined(CPUSTRUC_MEMWAIT) - UINT tramwait; - UINT vramwait; - UINT grcgwait; -#endif -#if defined(SUPPORT_PC9821) - UINT8 mio1[4]; // PEGC Packed-pixel Mode バンク切り替え(mio1[0〜1] E0004H, mio1[2〜3] E0006H) - UINT8 mio2[0x100]; // PEGC MMIOレジスタ(mio2[0〜1] E0100H 〜 E0200H) -#endif -} _VRAMOP, *VRAMOP; - -// operate: bit0 access page -// bit1 egc enable -// bit2 grcg bit6 -// bit3 grcg bit7 -// bit4 analog enable -// bit5 pc9821 vga - -enum { - VOPBIT_ACCESS = 0, - VOPBIT_EGC = 1, - VOPBIT_GRCG = 2, - VOPBIT_ANALOG = 4, - VOPBIT_VGA = 5 -}; - -// VOP_ACCESSBIT = 0x01, -// VOP_EGCBIT = 0x02, -// VOP_GRCGBIT = 0x0c, -// VOP_ANALOGBIT = 0x10, - -// VOP_ACCESSMASK = ~(0x01), -// VOP_EGCMASK = ~(0x02), -// VOP_GRCGMASK = ~(0x0c), -// VOP_ANALOGMASK = ~(0x10) - - -#ifdef __cplusplus -extern "C" { -#endif - -extern _VRAMOP vramop; -extern UINT8 tramupdate[0x1000]; -extern UINT8 vramupdate[0x8000]; -#if defined(SUPPORT_PC9821) -#if defined(SUPPORT_IA32_HAXM) -extern UINT8 vramex_base[0x80000]; -extern UINT8 *vramex; // PEGC VRAM Alloc in pccore_mem_malloc() -#else -extern UINT8 vramex[0x80000]; -#endif -#endif - -void vram_initialize(void); - -#if !defined(CPUSTRUC_MEMWAIT) -#define MEMWAIT_TRAM vramop.tramwait -#define MEMWAIT_VRAM vramop.vramwait -#define MEMWAIT_GRCG vramop.grcgwait -#endif - -#ifdef __cplusplus -} -#endif - + +#ifndef VRAMCALL +#define VRAMCALL +#endif + + +typedef struct { + UINT operate; +#if !defined(CPUSTRUC_MEMWAIT) + UINT tramwait; + UINT vramwait; + UINT grcgwait; +#endif +#if defined(SUPPORT_PC9821) + UINT8 mio1[4]; // PEGC Packed-pixel Mode バンク切り替え(mio1[0〜1] E0004H, mio1[2〜3] E0006H) + UINT8 mio2[0x100]; // PEGC MMIOレジスタ(mio2[0〜1] E0100H 〜 E0200H) +#endif +} _VRAMOP, *VRAMOP; + +// operate: bit0 access page +// bit1 egc enable +// bit2 grcg bit6 +// bit3 grcg bit7 +// bit4 analog enable +// bit5 pc9821 vga + +enum { + VOPBIT_ACCESS = 0, + VOPBIT_EGC = 1, + VOPBIT_GRCG = 2, + VOPBIT_ANALOG = 4, + VOPBIT_VGA = 5 +}; + +// VOP_ACCESSBIT = 0x01, +// VOP_EGCBIT = 0x02, +// VOP_GRCGBIT = 0x0c, +// VOP_ANALOGBIT = 0x10, + +// VOP_ACCESSMASK = ~(0x01), +// VOP_EGCMASK = ~(0x02), +// VOP_GRCGMASK = ~(0x0c), +// VOP_ANALOGMASK = ~(0x10) + + +#ifdef __cplusplus +extern "C" { +#endif + +extern _VRAMOP vramop; +extern UINT8 tramupdate[0x1000]; +extern UINT8 vramupdate[0x8000]; +#if defined(SUPPORT_PC9821) +#if defined(SUPPORT_IA32_HAXM) +extern UINT8 vramex_base[0x80000]; +extern UINT8 *vramex; // PEGC VRAM Alloc in pccore_mem_malloc() +#else +extern UINT8 vramex[0x80000]; +#endif +#endif + +void vram_initialize(void); + +#if !defined(CPUSTRUC_MEMWAIT) +#define MEMWAIT_TRAM vramop.tramwait +#define MEMWAIT_VRAM vramop.vramwait +#define MEMWAIT_GRCG vramop.grcgwait +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/wab/cirrus_vga.c b/wab/cirrus_vga.c old mode 100755 new mode 100644 index e0a3ccfb..e493cb30 --- a/wab/cirrus_vga.c +++ b/wab/cirrus_vga.c @@ -1,7811 +1,7811 @@ - -/* - * QEMU Cirrus CLGD 54xx VGA Emulator. - * - * Copyright (c) 2004 Fabrice Bellard - * Copyright (c) 2004 Makoto Suzuki (suzu) - * - * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/* - * Reference: Finn Thogersons' VGADOC4b - * available at http://home.worldonline.dk/~finth/ - */ - -/* - Neko Project 21/W 開発者のコメント: - ・元はQEMU/9821のコードですが強引に移植するためにあちこち削ったりしています - ・このファイルに関してはOS依存性は少ないはず(画面転送部分cirrusvga_drawGraphicだけOS依存・他のOS依存っぽいところは消してもたぶん害無し) - ・MMIOとかVRAMウィンドウとかリニアVRAMとかはcpumem.cで乗っ取っているのでそちらを参照 - ・16bit/32bit I/Oはiocore.cで乗っ取っているのでそちらを参照 - ・VRAM画面はcirrusvga->vram_ptrに、パレットはcirrusvga->paletteに入ってます - ・転送の仕方はcirrusvga_drawGraphicを参考に(自分もよく分かってないけど) - ・細かいところはQEMU/9821の同名ファイルを参照 -*/ - -#include - - -#if defined(SUPPORT_CL_GD5430) - -#include -#include -#include -#include "cirrus_vga.h" -#include "vga_int.h" -#include -#include -#include -#include -#include - -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif - -#if defined(NP2_X) -#include -#include -#endif - -//#if 1 -//#undef TRACEOUT -//#define USE_TRACEOUT_VS -////#define MEM_BDA_TRACEOUT -////#define MEM_D8_TRACEOUT -//#ifdef USE_TRACEOUT_VS -//static void trace_fmt_ex(const char *fmt, ...) -//{ -// char stmp[2048]; -// va_list ap; -// va_start(ap, fmt); -// vsprintf(stmp, fmt, ap); -// strcat(stmp, "¥n"); -// va_end(ap); -// OutputDebugStringA(stmp); -//} -//#define TRACEOUT(s) trace_fmt_ex s -//#else -//#define TRACEOUT(s) (void)(s) -//#endif -//#endif /* 1 */ -/* force some bits to zero */ -const uint8_t sr_mask[8] = { - (uint8_t)~0xfc, - (uint8_t)~0xc2, - (uint8_t)~0x00, // np21w ver0.86 rev29 (uint8_t)~0xf0, 上位ビットも残さないとWin9xで文字表示がおかしくなる - (uint8_t)~0xc0, - (uint8_t)~0xf1, - (uint8_t)~0xff, - (uint8_t)~0xff, - (uint8_t)~0x00, -}; - -const uint8_t gr_mask[16] = { - (uint8_t)~0xf0, /* 0x00 */ - (uint8_t)~0xf0, /* 0x01 */ - (uint8_t)~0xf0, /* 0x02 */ - (uint8_t)~0xe0, /* 0x03 */ - (uint8_t)~0xfc, /* 0x04 */ - (uint8_t)~0x84, /* 0x05 */ - (uint8_t)~0xf0, /* 0x06 */ - (uint8_t)~0xf0, /* 0x07 */ - (uint8_t)~0x00, /* 0x08 */ - (uint8_t)~0xff, /* 0x09 */ - (uint8_t)~0xff, /* 0x0a */ - (uint8_t)~0xff, /* 0x0b */ - (uint8_t)~0xff, /* 0x0c */ - (uint8_t)~0xff, /* 0x0d */ - (uint8_t)~0xff, /* 0x0e */ - (uint8_t)~0xff, /* 0x0f */ -}; - -int pcidev_cirrus_deviceid = 10; - -// 内蔵アクセラレータ用 -REG8 cirrusvga_regindexA2 = 0; // I/OポートFA2hで指定されているレジスタ番号 -REG8 cirrusvga_regindex = 0; // I/OポートFAAhで指定されているレジスタ番号 - -// WAB, WSN用 -int cirrusvga_wab_59e1 = 0x06; // この値じゃないとWSN Win95ドライバがNGを返す -int cirrusvga_wab_51e1 = 0xC2; // WSN CHECK IO RETURN VALUE -int cirrusvga_wab_5be1 = 0xf7; // bit3:0=4M,1=2M ?????? -int cirrusvga_wab_40e1 = 0x7b; -int cirrusvga_wab_42e1 = 0x00; -//int cirrusvga_wab_0fe1 = 0xC2; -int cirrusvga_wab_46e8 = 0x18; -int cirrusvga_melcowab_ofs = CIRRUS_MELCOWAB_OFS_DEFAULT; - -NP2CLVGA np2clvga = {0}; -void *cirrusvga_opaque = NULL; // CIRRUS VGAの変数をグローバルアクセス出来るようにしておく・・・(良くない実装) -UINT8 cirrusvga_statsavebuf[CIRRUS_VRAM_SIZE_4MB + 1024 * 1024]; // ステートセーブ用のバッファ(無駄が多いけど互換性は保ちやすいはず) - -int g_cirrus_linear_map_enabled = 0; // CIRRUS VGAの変数のリニアメモリアクセス(cpumem.cのmemp_*)有効フラグ -CPUWriteMemoryFunc *g_cirrus_linear_write[3] = {0}; // CIRRUS VGAの変数のリニアメモリアクセスWRITEで呼ばれる関数([0]=8bit, [0]=16bit, [0]=32bit) - -uint8_t* vramptr; // CIRRUS VGAのVRAMへのポインタ(メモリサイズはCIRRUS_VRAM_SIZEで十分のはずだが念のため2倍確保されている) -uint8_t* cursorptr; // CIRRUS VGAのカーソル画像バッファへのポインタ -#if defined(SUPPORT_IA32_HAXM) -uint8_t* vramptr_cmp; // メモリ更新を検出するためのvramptrのコピー -#endif - -DisplayState ds = {0}; // np21/wでは実質的に使われない - -#if defined(NP2_WIN) -BITMAPINFO *ga_bmpInfo; // CIRRUS VGAのVRAM映像を転送する時に使うBITMAPINFO構造体 -BITMAPINFO *ga_bmpInfo_cursor; // CIRRUS VGAのカーソル画像を転送する時に使うBITMAPINFO構造体 -HBITMAP ga_hbmp_cursor; // CIRRUS VGAのカーソルのHBITMAP -HDC ga_hdc_cursor; // CIRRUS VGAのカーソル画像のHDC - -static HCURSOR ga_hFakeCursor = NULL; // ハードウェアカーソル(仮)CIRRUS VGAのカーソル画像が上手く表示出来ない場合用 -#endif - -#if defined(SUPPORT_IA32_HAXM) -#define MMIO_MODE_MMIO 0 -#define MMIO_MODE_VRAM1 1 -#define MMIO_MODE_VRAM2 2 -int mmio_mode = MMIO_MODE_MMIO; // 0==MMIO, 1==VRAM -UINT32 mmio_mode_region1 = 0; // 0==MMIO, 1==VRAM -UINT32 mmio_mode_region2 = 0; // 0==MMIO, 1==VRAM -UINT8 lastlinmmio = 0; -#endif - -void pcidev_cirrus_cfgreg_w(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value); -void pc98_cirrus_setWABreg(void); -static void cirrusvga_setAutoWABID(void); - -// QEMUで使われているけどよく分からなかったので無視されている関数や変数達(ォィ -static void cpu_register_physical_memory(target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t phys_offset){ -} -void np2vga_ds_dpy_update(struct DisplayState *s, int x, int y, int w, int h) -{ -} -void np2vga_ds_dpy_resize(struct DisplayState *s) -{ -} -void np2vga_ds_dpy_setdata(struct DisplayState *s) -{ -} -void np2vga_ds_dpy_refresh(struct DisplayState *s) -{ -} -void np2vga_ds_dpy_copy(struct DisplayState *s, int src_x, int src_y, - int dst_x, int dst_y, int w, int h) -{ -} -void np2vga_ds_dpy_fill(struct DisplayState *s, int x, int y, - int w, int h, uint32_t_ c) -{ -} -void np2vga_ds_dpy_text_cursor(struct DisplayState *s, int x, int y) -{ -} -DisplaySurface np2vga_ds_surface = {0}; -DisplayChangeListener np2vga_ds_listeners = {0, 0, np2vga_ds_dpy_update, np2vga_ds_dpy_resize, - np2vga_ds_dpy_setdata, np2vga_ds_dpy_refresh, - np2vga_ds_dpy_copy, np2vga_ds_dpy_fill, - np2vga_ds_dpy_text_cursor, NULL}; -void np2vga_ds_mouse_set(int x, int y, int on){ -} -void np2vga_ds_cursor_define(int width, int height, int bpp, int hot_x, int hot_y, - uint8_t *image, uint8_t *mask){ -} - -DisplayState *graphic_console_init(vga_hw_update_ptr update, - vga_hw_invalidate_ptr invalidate, - vga_hw_screen_dump_ptr screen_dump, - vga_hw_text_update_ptr text_update, - void *opaque) -{ - ds.opaque = opaque; - np2vga_ds_surface.width = 640; - np2vga_ds_surface.height = 480; - np2vga_ds_surface.pf.bits_per_pixel = 32; - np2vga_ds_surface.pf.bytes_per_pixel = 4; - - return &ds; -} - -/*************************************** - * - * definitions - * - ***************************************/ - -#define qemu_MIN(a,b) ((a) < (b) ? (a) : (b)) - -// ID -#define CIRRUS_ID_CLGD5422 (0x23<<2) -#define CIRRUS_ID_CLGD5426 (0x24<<2) -#define CIRRUS_ID_CLGD5424 (0x25<<2) -#define CIRRUS_ID_CLGD5428 (0x26<<2) -#define CIRRUS_ID_CLGD5430 (0x28<<2) -#define CIRRUS_ID_CLGD5434 (0x2A<<2) -#define CIRRUS_ID_CLGD5436 (0x2B<<2) -#define CIRRUS_ID_CLGD5440 (0x2C<<2) -#define CIRRUS_ID_CLGD5446 (0x2E<<2) - -// sequencer 0x07 -#define CIRRUS_SR7_BPP_VGA 0x00 -#define CIRRUS_SR7_BPP_SVGA 0x01 -#define CIRRUS_SR7_BPP_MASK 0x0e -#define CIRRUS_SR7_BPP_8 0x00 -#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02 -#define CIRRUS_SR7_BPP_24 0x04 -#define CIRRUS_SR7_BPP_16 0x06 -#define CIRRUS_SR7_BPP_32 0x08 -//#define CIRRUS_SR7_ISAADDR_MASK 0xe0 -#define CIRRUS_SR7_ISAADDR_MASK 0xf0 - -// sequencer 0x0f -#define CIRRUS_MEMSIZE_512k 0x08 -#define CIRRUS_MEMSIZE_1M 0x10 -#define CIRRUS_MEMSIZE_2M 0x18 -#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled. - -// sequencer 0x12 -#define CIRRUS_CURSOR_SHOW 0x01 -#define CIRRUS_CURSOR_HIDDENPEL 0x02 -#define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear - -// sequencer 0x17 -#define CIRRUS_BUSTYPE_VLBFAST 0x10 -#define CIRRUS_BUSTYPE_PCI 0x20 -#define CIRRUS_BUSTYPE_VLBSLOW 0x30 -#define CIRRUS_BUSTYPE_ISA 0x38 -#define CIRRUS_MMIO_ENABLE 0x04 -#define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared. -#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80 - -// control 0x0b -#define CIRRUS_BANKING_DUAL 0x01 -#define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k - -// control 0x30 -#define CIRRUS_BLTMODE_BACKWARDS 0x01 -#define CIRRUS_BLTMODE_MEMSYSDEST 0x02 -#define CIRRUS_BLTMODE_MEMSYSSRC 0x04 -#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08 -#define CIRRUS_BLTMODE_PATTERNCOPY 0x40 -#define CIRRUS_BLTMODE_COLOREXPAND 0x80 -#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30 -#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00 -#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10 -#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 -#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 - -// control 0x31 -#define CIRRUS_BLT_BUSY 0x01 -#define CIRRUS_BLT_START 0x02 -#define CIRRUS_BLT_RESET 0x04 -#define CIRRUS_BLT_FIFOUSED 0x10 -#define CIRRUS_BLT_AUTOSTART 0x80 - -// control 0x32 -#define CIRRUS_ROP_0 0x00 -#define CIRRUS_ROP_SRC_AND_DST 0x05 -#define CIRRUS_ROP_NOP 0x06 -#define CIRRUS_ROP_SRC_AND_NOTDST 0x09 -#define CIRRUS_ROP_NOTDST 0x0b -#define CIRRUS_ROP_SRC 0x0d -#define CIRRUS_ROP_1 0x0e -#define CIRRUS_ROP_NOTSRC_AND_DST 0x50 -#define CIRRUS_ROP_SRC_XOR_DST 0x59 -#define CIRRUS_ROP_SRC_OR_DST 0x6d -#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90 -#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95 -#define CIRRUS_ROP_SRC_OR_NOTDST 0xad -#define CIRRUS_ROP_NOTSRC 0xd0 -#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6 -#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda - -#define CIRRUS_ROP_NOP_INDEX 2 -#define CIRRUS_ROP_SRC_INDEX 5 - -// control 0x33 -#define CIRRUS_BLTMODEEXT_BLTSYNCDISP 0x10 -#define CIRRUS_BLTMODEEXT_BGNDONLYCLIP 0x08 -#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 -#define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02 -#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 - -// memory-mapped IO -#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword -#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword -#define CIRRUS_MMIO_BLTWIDTH 0x08 // word -#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word -#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word -#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word -#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword -#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword -#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte -#define CIRRUS_MMIO_BLTMODE 0x18 // byte -#define CIRRUS_MMIO_BLTROP 0x1a // byte -#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte -#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c // word? -#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word? -#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24 // word -#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26 // word -#define CIRRUS_MMIO_LINEARDRAW_END_X 0x28 // word -#define CIRRUS_MMIO_LINEARDRAW_END_Y 0x2a // word -#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c // byte -#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d // byte -#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e // byte -#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f // byte -#define CIRRUS_MMIO_BRESENHAM_K1 0x30 // word -#define CIRRUS_MMIO_BRESENHAM_K3 0x32 // word -#define CIRRUS_MMIO_BRESENHAM_ERROR 0x34 // word -#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36 // word -#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38 // byte -#define CIRRUS_MMIO_LINEDRAW_MODE 0x39 // byte -#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte - -// PCI 0x02: device -#define PCI_DEVICE_CLGD5462 0x00d0 -#define PCI_DEVICE_CLGD5465 0x00d6 - -// PCI 0x04: command(word), 0x06(word): status -#define PCI_COMMAND_IOACCESS 0x0001 -#define PCI_COMMAND_MEMACCESS 0x0002 -#define PCI_COMMAND_BUSMASTER 0x0004 -#define PCI_COMMAND_SPECIALCYCLE 0x0008 -#define PCI_COMMAND_MEMWRITEINVALID 0x0010 -#define PCI_COMMAND_PALETTESNOOPING 0x0020 -#define PCI_COMMAND_PARITYDETECTION 0x0040 -#define PCI_COMMAND_ADDRESSDATASTEPPING 0x0080 -#define PCI_COMMAND_SERR 0x0100 -#define PCI_COMMAND_BACKTOBACKTRANS 0x0200 -// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev) -#define PCI_CLASS_BASE_DISPLAY 0x03 -// PCI 0x08, 0x00ff0000 -#define PCI_CLASS_SUB_VGA 0x00 -// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test) -#define PCI_CLASS_HEADERTYPE_00h 0x00 -// 0x10-0x3f (headertype 00h) -// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers -// 0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x) -#define PCI_MAP_MEM 0x0 -#define PCI_MAP_IO 0x1 -#define PCI_MAP_MEM_ADDR_MASK (~0xf) -#define PCI_MAP_IO_ADDR_MASK (~0x3) -#define PCI_MAP_MEMFLAGS_32BIT 0x0 -#define PCI_MAP_MEMFLAGS_32BIT_1M 0x1 -#define PCI_MAP_MEMFLAGS_64BIT 0x4 -#define PCI_MAP_MEMFLAGS_CACHEABLE 0x8 -// PCI 0x28: cardbus CIS pointer -// PCI 0x2c: subsystem vendor id, 0x2e: subsystem id -// PCI 0x30: expansion ROM base address -#define PCI_ROMBIOS_ENABLED 0x1 -// PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer -// PCI 0x38: reserved -// PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat - -#define CIRRUS_PNPMMIO_SIZE 0x1000 - - -/* I/O and memory hook */ -#define CIRRUS_HOOK_NOT_HANDLED 0 -#define CIRRUS_HOOK_HANDLED 1 - -#define ABS(a) ((signed)(a) > 0 ? a : -a) - -// XXX: WAB系をとりあえず使えるようにするために4MB VRAMサイズまで書き込み許可 -#define BLTUNSAFE_DST(s) \ - ( /* check dst is within bounds */ \ - ((s)->cirrus_blt_dstpitch >= 0) ? /* ピッチの正負を確認 */ \ - ((s)->cirrus_blt_height * (s)->cirrus_blt_dstpitch + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > CIRRUS_VRAM_SIZE_4MB) : /* ピッチが正の時、VRAM最大を超えないか確認 */ \ - (((s)->cirrus_blt_height-1) * -(s)->cirrus_blt_dstpitch > ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask)) /* ピッチが負の時、0未満にならないか確認 */ \ - ) -#define BLTUNSAFE_SRC(s) \ - ( /* check src is within bounds */ \ - ((s)->cirrus_blt_srcpitch >= 0) ? /* ピッチの正負を確認 */ \ - ((s)->cirrus_blt_height * (s)->cirrus_blt_srcpitch + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > CIRRUS_VRAM_SIZE_4MB) : /* ピッチが正の時、VRAM最大を超えないか確認 */ \ - (((s)->cirrus_blt_height-1) * -(s)->cirrus_blt_srcpitch > ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask)) /* ピッチが負の時、0未満にならないか確認 */ \ - ) -#define BLTUNSAFE(s) \ - ( \ - BLTUNSAFE_DST(s) || BLTUNSAFE_SRC(s) \ - ) -// SRC未使用なら1 -#define BLTUNSAFE_NOSRC(s) \ - ( \ - rop_to_index[(s)->gr[0x32]]==0 || rop_to_index[(s)->gr[0x32]]==2 || rop_to_index[(s)->gr[0x32]]==4 || rop_to_index[(s)->gr[0x32]]==6 \ - ) -//#define BLTUNSAFE(s) \ -// ( \ -// ( /* check dst is within bounds */ \ -// (s)->cirrus_blt_height * ABS((s)->cirrus_blt_dstpitch) \ -// + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \ -// (s)->vram_size \ -// ) || \ -// ( /* check src is within bounds */ \ -// (s)->cirrus_blt_height * ABS((s)->cirrus_blt_srcpitch) \ -// + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \ -// (s)->vram_size \ -// ) \ -// ) - -struct CirrusVGAState; -typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s, - uint8_t * dst, const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight); -typedef void (*cirrus_fill_t)(struct CirrusVGAState *s, - uint8_t *dst, int dst_pitch, int width, int height); - -static int cirrusvga_updated = 1; - -typedef struct CirrusVGAState { - VGA_STATE_COMMON - - int cirrus_linear_io_addr; - int cirrus_linear_bitblt_io_addr; - int cirrus_mmio_io_addr; - uint32_t_ cirrus_addr_mask; - uint32_t_ linear_mmio_mask; - uint8_t cirrus_shadow_gr0; - uint8_t cirrus_shadow_gr1; - uint8_t cirrus_hidden_dac_lockindex; - uint8_t cirrus_hidden_dac_data; - uint32_t_ cirrus_bank_base[2]; - uint32_t_ cirrus_bank_limit[2]; - uint8_t cirrus_hidden_palette[48]; - uint32_t_ hw_cursor_x; - uint32_t_ hw_cursor_y; - int cirrus_blt_pixelwidth; - int cirrus_blt_width; - int cirrus_blt_height; - int cirrus_blt_dstpitch; - int cirrus_blt_srcpitch; - uint32_t_ cirrus_blt_fgcol; - uint32_t_ cirrus_blt_bgcol; - uint32_t_ cirrus_blt_dstaddr; - uint32_t_ cirrus_blt_srcaddr; - uint8_t cirrus_blt_mode; - uint8_t cirrus_blt_modeext; - cirrus_bitblt_rop_t cirrus_rop; -#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */ - uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE]; - uint8_t *cirrus_srcptr; - uint8_t *cirrus_srcptr_end; - uint32_t_ cirrus_srccounter; - /* hwcursor display state */ - int last_hw_cursor_size; - int last_hw_cursor_x; - int last_hw_cursor_y; - int last_hw_cursor_y_start; - int last_hw_cursor_y_end; - int real_vram_size; /* XXX: suppress that */ - //CPUWriteMemoryFunc **cirrus_linear_write; - int device_id; - int bustype; - uint8_t videowindow_dblbuf_index; - uint8_t graphics_dblbuf_index; -} CirrusVGAState; - -CirrusVGAState *cirrusvga = NULL; - -#define CIRRUS_FMC_W 16 -#define CIRRUS_FMC_H 32 - -UINT8 FakeMouseCursorData[CIRRUS_FMC_W * CIRRUS_FMC_H] = { - // 0:transparent 1:black 2:white - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, - 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 1, 2, 2, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, 1, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0 -}; - -static uint8_t vga_dumb_retrace(VGAState *s) -{ - return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE); -} - -static uint8_t rop_to_index[256]; - -typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b); -#define NB_DEPTHS 7 - -static unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, - unsigned int b) -{ - return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6); -} - -static unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, - unsigned int b) -{ - return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); -} - -static unsigned int rgb_to_pixel15bgr(unsigned int r, unsigned int g, - unsigned int b) -{ - return ((b >> 3) << 10) | ((g >> 3) << 5) | (r >> 3); -} - -static unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, - unsigned int b) -{ - return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); -} - -static unsigned int rgb_to_pixel16bgr(unsigned int r, unsigned int g, - unsigned int b) -{ - return ((b >> 3) << 11) | ((g >> 2) << 5) | (r >> 3); -} - -static unsigned int rgb_to_pixel24(unsigned int r, unsigned int g, - unsigned int b) -{ - return (r << 16) | (g << 8) | b; -} - -static unsigned int rgb_to_pixel24bgr(unsigned int r, unsigned int g, - unsigned int b) -{ - return (b << 16) | (g << 8) | r; -} - -static unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, - unsigned int b) -{ - return (r << 16) | (g << 8) | b; -} - -static unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, - unsigned int b) -{ - return (b << 16) | (g << 8) | r; -} - -static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b) -{ - unsigned int col; - col = rgb_to_pixel8(r, g, b); - col |= col << 8; - col |= col << 16; - return col; -} - -static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b) -{ - unsigned int col; - col = rgb_to_pixel15(r, g, b); - col |= col << 16; - return col; -} - -static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g, - unsigned int b) -{ - unsigned int col; - col = rgb_to_pixel15bgr(r, g, b); - col |= col << 16; - return col; -} - -static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b) -{ - unsigned int col; - col = rgb_to_pixel16(r, g, b); - col |= col << 16; - return col; -} - -static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g, - unsigned int b) -{ - unsigned int col; - col = rgb_to_pixel16bgr(r, g, b); - col |= col << 16; - return col; -} - -static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b) -{ - unsigned int col; - col = rgb_to_pixel32(r, g, b); - return col; -} - -static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b) -{ - unsigned int col; - col = rgb_to_pixel32bgr(r, g, b); - return col; -} - - -static int ds_get_linesize(DisplayState *ds) -{ - return np2wab.realWidth*4; -} - -static uint8_t* ds_get_data(DisplayState *ds) -{ - return ds->surface->data; -} - -static int ds_get_width(DisplayState *ds) -{ - return np2wab.realWidth;//ds->surface->width; -} - -static int ds_get_height(DisplayState *ds) -{ - return np2wab.realHeight;//ds->surface->height; -} - -static int ds_get_bits_per_pixel(DisplayState *ds) -{ - return 32;//ds->surface->pf.bits_per_pixel; -} - -static int ds_get_bytes_per_pixel(DisplayState *ds) -{ - return 4;//ds->surface->pf.bytes_per_pixel; -} - -static void dpy_update(DisplayState *s, int x, int y, int w, int h) -{ - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - dcl->dpy_update(s, x, y, w, h); - dcl = dcl->next; - } -} - -static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = { - rgb_to_pixel8_dup, - rgb_to_pixel15_dup, - rgb_to_pixel16_dup, - rgb_to_pixel32_dup, - rgb_to_pixel32bgr_dup, - rgb_to_pixel15bgr_dup, - rgb_to_pixel16bgr_dup, -}; - -/*************************************** - * - * prototypes. - * - ***************************************/ - -static void cirrus_bitblt_dblbufferswitch(); -static void cirrus_bitblt_reset(CirrusVGAState *s); -static void cirrus_update_memory_access(CirrusVGAState *s); - -/*************************************** - * - * raster operations - * - ***************************************/ - -static void cirrus_bitblt_rop_nop(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ -} - -static void cirrus_bitblt_fill_nop(CirrusVGAState *s, - uint8_t *dst, - int dstpitch, int bltwidth,int bltheight) -{ -} - -#define ROP_NAME 0 -#define ROP_OP(d, s) d = 0 -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_and_dst -#define ROP_OP(d, s) d = (s) & (d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_and_notdst -#define ROP_OP(d, s) d = (s) & (~(d)) -#include "cirrus_vga_rop.h" - -#define ROP_NAME notdst -#define ROP_OP(d, s) d = ~(d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src -#define ROP_OP(d, s) d = s -#include "cirrus_vga_rop.h" - -#define ROP_NAME 1 -#define ROP_OP(d, s) d = ~0 -#include "cirrus_vga_rop.h" - -#define ROP_NAME notsrc_and_dst -#define ROP_OP(d, s) d = (~(s)) & (d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_xor_dst -#define ROP_OP(d, s) d = (s) ^ (d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_or_dst -#define ROP_OP(d, s) d = (s) | (d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME notsrc_or_notdst -#define ROP_OP(d, s) d = (~(s)) | (~(d)) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_notxor_dst -#define ROP_OP(d, s) d = ~((s) ^ (d)) -#include "cirrus_vga_rop.h" - -#define ROP_NAME src_or_notdst -#define ROP_OP(d, s) d = (s) | (~(d)) -#include "cirrus_vga_rop.h" - -#define ROP_NAME notsrc -#define ROP_OP(d, s) d = (~(s)) -#include "cirrus_vga_rop.h" - -#define ROP_NAME notsrc_or_dst -#define ROP_OP(d, s) d = (~(s)) | (d) -#include "cirrus_vga_rop.h" - -#define ROP_NAME notsrc_and_notdst -#define ROP_OP(d, s) d = (~(s)) & (~(d)) -#include "cirrus_vga_rop.h" - -static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = { - cirrus_bitblt_rop_fwd_0, - cirrus_bitblt_rop_fwd_src_and_dst, - cirrus_bitblt_rop_nop, - cirrus_bitblt_rop_fwd_src_and_notdst, - cirrus_bitblt_rop_fwd_notdst, - cirrus_bitblt_rop_fwd_src, - cirrus_bitblt_rop_fwd_1, - cirrus_bitblt_rop_fwd_notsrc_and_dst, - cirrus_bitblt_rop_fwd_src_xor_dst, - cirrus_bitblt_rop_fwd_src_or_dst, - cirrus_bitblt_rop_fwd_notsrc_or_notdst, - cirrus_bitblt_rop_fwd_src_notxor_dst, - cirrus_bitblt_rop_fwd_src_or_notdst, - cirrus_bitblt_rop_fwd_notsrc, - cirrus_bitblt_rop_fwd_notsrc_or_dst, - cirrus_bitblt_rop_fwd_notsrc_and_notdst, -}; - -static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = { - cirrus_bitblt_rop_bkwd_0, - cirrus_bitblt_rop_bkwd_src_and_dst, - cirrus_bitblt_rop_nop, - cirrus_bitblt_rop_bkwd_src_and_notdst, - cirrus_bitblt_rop_bkwd_notdst, - cirrus_bitblt_rop_bkwd_src, - cirrus_bitblt_rop_bkwd_1, - cirrus_bitblt_rop_bkwd_notsrc_and_dst, - cirrus_bitblt_rop_bkwd_src_xor_dst, - cirrus_bitblt_rop_bkwd_src_or_dst, - cirrus_bitblt_rop_bkwd_notsrc_or_notdst, - cirrus_bitblt_rop_bkwd_src_notxor_dst, - cirrus_bitblt_rop_bkwd_src_or_notdst, - cirrus_bitblt_rop_bkwd_notsrc, - cirrus_bitblt_rop_bkwd_notsrc_or_dst, - cirrus_bitblt_rop_bkwd_notsrc_and_notdst, -}; - -#define TRANSP_ROP(name) {\ - name ## _8,\ - name ## _16,\ - } -#define TRANSP_NOP(func) {\ - func,\ - func,\ - } - -static const cirrus_bitblt_rop_t cirrus_fwd_transp_rop[16][2] = { - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_0), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_dst), - TRANSP_NOP(cirrus_bitblt_rop_nop), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_notdst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notdst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_1), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_dst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_xor_dst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_dst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_notdst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_notxor_dst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_notdst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_dst), - TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_notdst), -}; - -static const cirrus_bitblt_rop_t cirrus_bkwd_transp_rop[16][2] = { - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_0), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_dst), - TRANSP_NOP(cirrus_bitblt_rop_nop), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_notdst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notdst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_1), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_dst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_xor_dst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_dst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_notdst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_notxor_dst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_notdst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_dst), - TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_notdst), -}; - -#define ROP2(name) {\ - name ## _8,\ - name ## _16,\ - name ## _24,\ - name ## _32,\ - } - -#define ROP_NOP2(func) {\ - func,\ - func,\ - func,\ - func,\ - } - -static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = { - ROP2(cirrus_patternfill_0), - ROP2(cirrus_patternfill_src_and_dst), - ROP_NOP2(cirrus_bitblt_rop_nop), - ROP2(cirrus_patternfill_src_and_notdst), - ROP2(cirrus_patternfill_notdst), - ROP2(cirrus_patternfill_src), - ROP2(cirrus_patternfill_1), - ROP2(cirrus_patternfill_notsrc_and_dst), - ROP2(cirrus_patternfill_src_xor_dst), - ROP2(cirrus_patternfill_src_or_dst), - ROP2(cirrus_patternfill_notsrc_or_notdst), - ROP2(cirrus_patternfill_src_notxor_dst), - ROP2(cirrus_patternfill_src_or_notdst), - ROP2(cirrus_patternfill_notsrc), - ROP2(cirrus_patternfill_notsrc_or_dst), - ROP2(cirrus_patternfill_notsrc_and_notdst), -}; - -static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = { - ROP2(cirrus_colorexpand_transp_0), - ROP2(cirrus_colorexpand_transp_src_and_dst), - ROP_NOP2(cirrus_bitblt_rop_nop), - ROP2(cirrus_colorexpand_transp_src_and_notdst), - ROP2(cirrus_colorexpand_transp_notdst), - ROP2(cirrus_colorexpand_transp_src), - ROP2(cirrus_colorexpand_transp_1), - ROP2(cirrus_colorexpand_transp_notsrc_and_dst), - ROP2(cirrus_colorexpand_transp_src_xor_dst), - ROP2(cirrus_colorexpand_transp_src_or_dst), - ROP2(cirrus_colorexpand_transp_notsrc_or_notdst), - ROP2(cirrus_colorexpand_transp_src_notxor_dst), - ROP2(cirrus_colorexpand_transp_src_or_notdst), - ROP2(cirrus_colorexpand_transp_notsrc), - ROP2(cirrus_colorexpand_transp_notsrc_or_dst), - ROP2(cirrus_colorexpand_transp_notsrc_and_notdst), -}; - -static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = { - ROP2(cirrus_colorexpand_0), - ROP2(cirrus_colorexpand_src_and_dst), - ROP_NOP2(cirrus_bitblt_rop_nop), - ROP2(cirrus_colorexpand_src_and_notdst), - ROP2(cirrus_colorexpand_notdst), - ROP2(cirrus_colorexpand_src), - ROP2(cirrus_colorexpand_1), - ROP2(cirrus_colorexpand_notsrc_and_dst), - ROP2(cirrus_colorexpand_src_xor_dst), - ROP2(cirrus_colorexpand_src_or_dst), - ROP2(cirrus_colorexpand_notsrc_or_notdst), - ROP2(cirrus_colorexpand_src_notxor_dst), - ROP2(cirrus_colorexpand_src_or_notdst), - ROP2(cirrus_colorexpand_notsrc), - ROP2(cirrus_colorexpand_notsrc_or_dst), - ROP2(cirrus_colorexpand_notsrc_and_notdst), -}; - -static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = { - ROP2(cirrus_colorexpand_pattern_transp_0), - ROP2(cirrus_colorexpand_pattern_transp_src_and_dst), - ROP_NOP2(cirrus_bitblt_rop_nop), - ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst), - ROP2(cirrus_colorexpand_pattern_transp_notdst), - ROP2(cirrus_colorexpand_pattern_transp_src), - ROP2(cirrus_colorexpand_pattern_transp_1), - ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst), - ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst), - ROP2(cirrus_colorexpand_pattern_transp_src_or_dst), - ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst), - ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst), - ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst), - ROP2(cirrus_colorexpand_pattern_transp_notsrc), - ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst), - ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst), -}; - -static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = { - ROP2(cirrus_colorexpand_pattern_0), - ROP2(cirrus_colorexpand_pattern_src_and_dst), - ROP_NOP2(cirrus_bitblt_rop_nop), - ROP2(cirrus_colorexpand_pattern_src_and_notdst), - ROP2(cirrus_colorexpand_pattern_notdst), - ROP2(cirrus_colorexpand_pattern_src), - ROP2(cirrus_colorexpand_pattern_1), - ROP2(cirrus_colorexpand_pattern_notsrc_and_dst), - ROP2(cirrus_colorexpand_pattern_src_xor_dst), - ROP2(cirrus_colorexpand_pattern_src_or_dst), - ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst), - ROP2(cirrus_colorexpand_pattern_src_notxor_dst), - ROP2(cirrus_colorexpand_pattern_src_or_notdst), - ROP2(cirrus_colorexpand_pattern_notsrc), - ROP2(cirrus_colorexpand_pattern_notsrc_or_dst), - ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst), -}; - -static const cirrus_fill_t cirrus_fill[16][4] = { - ROP2(cirrus_fill_0), - ROP2(cirrus_fill_src_and_dst), - ROP_NOP2(cirrus_bitblt_fill_nop), - ROP2(cirrus_fill_src_and_notdst), - ROP2(cirrus_fill_notdst), - ROP2(cirrus_fill_src), - ROP2(cirrus_fill_1), - ROP2(cirrus_fill_notsrc_and_dst), - ROP2(cirrus_fill_src_xor_dst), - ROP2(cirrus_fill_src_or_dst), - ROP2(cirrus_fill_notsrc_or_notdst), - ROP2(cirrus_fill_src_notxor_dst), - ROP2(cirrus_fill_src_or_notdst), - ROP2(cirrus_fill_notsrc), - ROP2(cirrus_fill_notsrc_or_dst), - ROP2(cirrus_fill_notsrc_and_notdst), -}; - -static void cirrus_bitblt_fgcol(CirrusVGAState *s) -{ - unsigned int color; - switch (s->cirrus_blt_pixelwidth) { - case 1: - s->cirrus_blt_fgcol = s->cirrus_shadow_gr1; - break; - case 2: - color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8); - s->cirrus_blt_fgcol = le16_to_cpu(color); - break; - case 3: - s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 | - (s->gr[0x11] << 8) | (s->gr[0x13] << 16); - break; - default: - case 4: - color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) | - (s->gr[0x13] << 16) | (s->gr[0x15] << 24); - s->cirrus_blt_fgcol = le32_to_cpu(color); - break; - } -} - -static void cirrus_bitblt_bgcol(CirrusVGAState *s) -{ - unsigned int color; - switch (s->cirrus_blt_pixelwidth) { - case 1: - s->cirrus_blt_bgcol = s->cirrus_shadow_gr0; - break; - case 2: - color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8); - s->cirrus_blt_bgcol = le16_to_cpu(color); - break; - case 3: - s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 | - (s->gr[0x10] << 8) | (s->gr[0x12] << 16); - break; - default: - case 4: - color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8) | - (s->gr[0x12] << 16) | (s->gr[0x14] << 24); - s->cirrus_blt_bgcol = le32_to_cpu(color); - break; - } -} - -static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, - int off_pitch, int bytesperline, - int lines) -{ - int y; - int off_cur; - int off_cur_end; - - for (y = 0; y < lines; y++) { - off_cur = off_begin; - off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask; - off_cur &= TARGET_PAGE_MASK; - while (off_cur < off_cur_end) { - cpu_physical_memory_set_dirty(s->vram_offset + off_cur); - off_cur += TARGET_PAGE_SIZE; - } - off_begin += off_pitch; - } - cirrusvga_updated = 1; -} - -static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, - const uint8_t * src) -{ - uint8_t *dst; - - dst = s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask); - - if(BLTUNSAFE_DST(s)){ - return 0; - } - - (*s->cirrus_rop) (s, dst, src, - s->cirrus_blt_dstpitch, 0, - s->cirrus_blt_width, s->cirrus_blt_height); - cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, - s->cirrus_blt_dstpitch, s->cirrus_blt_width, - s->cirrus_blt_height); - cirrusvga_updated = 1; - return 1; -} - -/* fill */ - -static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop) -{ - cirrus_fill_t rop_func; - - if(BLTUNSAFE_DST(s)){ - return 0; - } - - rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - rop_func(s, s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), - s->cirrus_blt_dstpitch, - s->cirrus_blt_width, s->cirrus_blt_height); - cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, - s->cirrus_blt_dstpitch, s->cirrus_blt_width, - s->cirrus_blt_height); - cirrus_bitblt_reset(s); - cirrusvga_updated = 1; - return 1; -} - -/*************************************** - * - * bitblt (video-to-video) - * - ***************************************/ - -static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) -{ - return cirrus_bitblt_common_patterncopy(s, - s->vram_ptr + ((s->cirrus_blt_srcaddr & ~7) & - s->cirrus_addr_mask)); -} - -static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) -{ - int sx, sy; - int dx, dy; - int width, height; - int depth; - int notify = 0; - - depth = s->get_bpp((VGAState *)s) / 8; - if(depth==0) return; - if(s->cirrus_blt_srcpitch==0) return; - if(s->cirrus_blt_dstpitch==0) return; - s->get_resolution((VGAState *)s, &width, &height); - - /* extra x, y */ - sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth; - sy = (src / ABS(s->cirrus_blt_srcpitch)); - dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth; - dy = (dst / ABS(s->cirrus_blt_dstpitch)); - - /* normalize width */ - w /= depth; - - /* if we're doing a backward copy, we have to adjust - our x/y to be the upper left corner (instead of the lower - right corner) */ - if (s->cirrus_blt_dstpitch < 0) { - sx -= (s->cirrus_blt_width / depth) - 1; - dx -= (s->cirrus_blt_width / depth) - 1; - sy -= s->cirrus_blt_height - 1; - dy -= s->cirrus_blt_height - 1; - } - - /* are we in the visible portion of memory? */ - if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 && - (sx + w) <= width && (sy + h) <= height && - (dx + w) <= width && (dy + h) <= height) { - notify = 1; - } - - /* make to sure only copy if it's a plain copy ROP */ - if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src && - *s->cirrus_rop != cirrus_bitblt_rop_bkwd_src) - notify = 0; - - /* we have to flush all pending changes so that the copy - is generated at the appropriate moment in time */ - if (notify){ - vga_hw_update(); - } - (*s->cirrus_rop) (s, s->vram_ptr + - (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), - s->vram_ptr + - (s->cirrus_blt_srcaddr & s->cirrus_addr_mask), - s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, - s->cirrus_blt_width, s->cirrus_blt_height); - cirrusvga_updated = 1; - - if (notify){ - qemu_console_copy(s->ds, - sx, sy, dx, dy, - s->cirrus_blt_width / depth, - s->cirrus_blt_height); - } - - /* we don't have to notify the display that this portion has - changed since qemu_console_copy implies this */ - - cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, - s->cirrus_blt_dstpitch, s->cirrus_blt_width, - s->cirrus_blt_height); - cirrusvga_updated = 1; -} - -static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) -{ - if(BLTUNSAFE_DST(s) || (!BLTUNSAFE_NOSRC(s) && BLTUNSAFE_SRC(s))){ // XXX: ソースを使用しないならソースの範囲外チェック不要。抜本解決必要 - return 0; - } - - cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr, - s->cirrus_blt_srcaddr - s->start_addr, - s->cirrus_blt_width, s->cirrus_blt_height); - - return 1; -} - -/*************************************** - * - * bitblt (cpu-to-video) - * - ***************************************/ - -static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s) -{ - int copy_count; - uint8_t *end_ptr; - - if (s->cirrus_srccounter > 0) { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf); - the_end: - s->cirrus_srccounter = 0; - cirrus_bitblt_dblbufferswitch(); - cirrus_bitblt_reset(s); - } else { - /* at least one scan line */ - do { - (*s->cirrus_rop)(s, s->vram_ptr + - (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), - s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1); - cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, - s->cirrus_blt_width, 1); - s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch; - s->cirrus_srccounter -= s->cirrus_blt_srcpitch; - if (s->cirrus_srccounter <= 0) - goto the_end; - /* more bytes than needed can be transfered because of - word alignment, so we keep them for the next line */ - /* XXX: keep alignment to speed up transfer */ - end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; - copy_count = (int)(s->cirrus_srcptr_end - end_ptr); - if(copy_count >= 0 && s->cirrus_blt_srcpitch + copy_count <= sizeof(s->cirrus_bltbuf)) // 範囲外になっていないかチェック - memmove(s->cirrus_bltbuf, end_ptr, copy_count); - s->cirrus_srcptr = s->cirrus_bltbuf + copy_count; - if(s->cirrus_blt_srcpitch <= sizeof(s->cirrus_bltbuf)){ - s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; - }else{ - s->cirrus_srcptr_end = s->cirrus_bltbuf + sizeof(s->cirrus_bltbuf); - } - } while (s->cirrus_srcptr >= s->cirrus_srcptr_end); - } - cirrusvga_updated = 1; - } -} - -/*************************************** - * - * bitblt (video-to-cpu) - * - ***************************************/ - -static void cirrus_bitblt_videotocpu_next(CirrusVGAState * s) -{ - if (s->cirrus_srccounter > 0) { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - // XXX: not implemented - //cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf); - the_end: - s->cirrus_srccounter = 0; - cirrus_bitblt_dblbufferswitch(); - cirrus_bitblt_reset(s); - } else { - s->cirrus_blt_srcaddr += s->cirrus_blt_srcpitch; - s->cirrus_srccounter -= s->cirrus_blt_dstpitch; - if (s->cirrus_srccounter <= 0) - goto the_end; - (*s->cirrus_rop)(s, s->cirrus_bltbuf, s->vram_ptr + - (s->cirrus_blt_srcaddr & s->cirrus_addr_mask), - 0, 0, s->cirrus_blt_width, 1); - s->cirrus_srcptr = s->cirrus_bltbuf; - if(s->cirrus_blt_srcpitch <= sizeof(s->cirrus_bltbuf)){ - s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; - }else{ - s->cirrus_srcptr_end = s->cirrus_bltbuf + sizeof(s->cirrus_bltbuf); - } - } - cirrusvga_updated = 1; - } -} - -/*************************************** - * - * bitblt wrapper - * - ***************************************/ - -static void cirrus_bitblt_reset(CirrusVGAState * s) -{ - int need_update; - - s->gr[0x31] &= - ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED); - need_update = s->cirrus_srcptr != &s->cirrus_bltbuf[0] - || s->cirrus_srcptr_end != &s->cirrus_bltbuf[0]; - s->cirrus_srcptr = &s->cirrus_bltbuf[0]; - s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; - s->cirrus_srccounter = 0; - if (!need_update) - return; - cirrus_update_memory_access(s); -} - -static int cirrus_bitblt_cputovideo(CirrusVGAState * s) -{ - int w; - - s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; - s->cirrus_srcptr = &s->cirrus_bltbuf[0]; - s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; - - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { - s->cirrus_blt_srcpitch = 8; - } else { - /* XXX: check for 24 bpp */ - s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth; - } - s->cirrus_srccounter = s->cirrus_blt_srcpitch; - } else { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { - w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth; - if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) - s->cirrus_blt_srcpitch = ((w + 31) >> 5); - else - s->cirrus_blt_srcpitch = ((w + 7) >> 3); - } else { - /* always align input size to 32 bits */ - s->cirrus_blt_srcpitch = (s->cirrus_blt_width + 3) & ~3; - } - s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height; - } - s->cirrus_srcptr = s->cirrus_bltbuf; - if(s->cirrus_blt_srcpitch <= sizeof(s->cirrus_bltbuf)){ - s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; - }else{ - s->cirrus_srcptr_end = s->cirrus_bltbuf + sizeof(s->cirrus_bltbuf); - } - cirrus_update_memory_access(s); - return 1; -} - -static int cirrus_bitblt_videotocpu(CirrusVGAState * s) -{ - // np21/w bitblt (video to cpu) 暫定プログラム(cputovideoからの推測・正しいかは不明) - int w; - - s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; - s->cirrus_srcptr = &s->cirrus_bltbuf[0]; - s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; - - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { - s->cirrus_blt_dstpitch = 8; - } else { - /* XXX: check for 24 bpp */ - s->cirrus_blt_dstpitch = 8 * 8 * s->cirrus_blt_pixelwidth; - } - s->cirrus_srccounter = s->cirrus_blt_dstpitch; - } else { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { - w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth; - if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) - s->cirrus_blt_dstpitch = ((w + 31) >> 5); - else - s->cirrus_blt_dstpitch = ((w + 7) >> 3); - } else { - /* always align input size to 32 bits */ - s->cirrus_blt_dstpitch = (s->cirrus_blt_width + 3) & ~3; - } - s->cirrus_srccounter = s->cirrus_blt_dstpitch * s->cirrus_blt_height; - } - s->cirrus_srcptr = s->cirrus_bltbuf; - if(s->cirrus_blt_dstpitch <= sizeof(s->cirrus_bltbuf)){ - s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_dstpitch; - }else{ - s->cirrus_srcptr_end = s->cirrus_bltbuf + sizeof(s->cirrus_bltbuf); - } - if(s->cirrus_blt_dstpitch<0){ - cirrus_update_memory_access(s); - } - cirrus_update_memory_access(s); - - memset(s->cirrus_bltbuf, 0, s->cirrus_blt_width); - - // Copy 1st data - (*s->cirrus_rop)(s, s->cirrus_bltbuf, s->vram_ptr + - (s->cirrus_blt_srcaddr & s->cirrus_addr_mask), - 0, 0, s->cirrus_blt_width, 1); - cirrusvga_updated = 1; - return 1; -} - -static int cirrus_bitblt_videotovideo(CirrusVGAState * s) -{ - int ret; - - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - ret = cirrus_bitblt_videotovideo_patterncopy(s); - } else { - ret = cirrus_bitblt_videotovideo_copy(s); - } - if (ret) - cirrus_bitblt_reset(s); - - cirrus_bitblt_dblbufferswitch(); - - return ret; -} - -static void cirrus_bitblt_start(CirrusVGAState * s) -{ - uint8_t blt_rop; - - s->gr[0x31] |= CIRRUS_BLT_BUSY; - - s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1; - s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1; - s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8)); - s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8)); - s->cirrus_blt_dstaddr = (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16)); - s->cirrus_blt_srcaddr = (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16)); - s->cirrus_blt_mode = s->gr[0x30]; - blt_rop = s->gr[0x32]; - if(s->device_id == CIRRUS_ID_CLGD5446){ - s->cirrus_blt_modeext = s->gr[0x33]; - }else{ - s->cirrus_blt_modeext = 0; // ver0.86 rev8 - } - -#ifdef DEBUG_BITBLT - printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n", - blt_rop, - s->cirrus_blt_mode, - s->cirrus_blt_modeext, - s->cirrus_blt_width, - s->cirrus_blt_height, - s->cirrus_blt_dstpitch, - s->cirrus_blt_srcpitch, - s->cirrus_blt_dstaddr, - s->cirrus_blt_srcaddr, - s->gr[0x2f]); -#endif - - switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { - case CIRRUS_BLTMODE_PIXELWIDTH8: - s->cirrus_blt_pixelwidth = 1; - break; - case CIRRUS_BLTMODE_PIXELWIDTH16: - s->cirrus_blt_pixelwidth = 2; - break; - case CIRRUS_BLTMODE_PIXELWIDTH24: - s->cirrus_blt_pixelwidth = 3; - break; - case CIRRUS_BLTMODE_PIXELWIDTH32: - s->cirrus_blt_pixelwidth = 4; - break; - default: -#ifdef DEBUG_BITBLT - printf("cirrus: bitblt - pixel width is unknown\n"); -#endif - goto bitblt_ignore; - } - s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK; - - if ((s-> - cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) - == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) { -#ifdef DEBUG_BITBLT - printf("cirrus: bitblt - memory-to-memory copy is requested\n"); -#endif - goto bitblt_ignore; - } - - if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) && - (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | - CIRRUS_BLTMODE_TRANSPARENTCOMP | - CIRRUS_BLTMODE_PATTERNCOPY | - CIRRUS_BLTMODE_COLOREXPAND)) == - (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) { - cirrus_bitblt_fgcol(s); - cirrus_bitblt_solidfill(s, blt_rop); - } else { - if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND | - CIRRUS_BLTMODE_PATTERNCOPY)) == - CIRRUS_BLTMODE_COLOREXPAND) { - - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { - if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) - cirrus_bitblt_bgcol(s); - else - cirrus_bitblt_fgcol(s); - s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } else { - cirrus_bitblt_fgcol(s); - cirrus_bitblt_bgcol(s); - s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } - } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { - if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) - cirrus_bitblt_bgcol(s); - else - cirrus_bitblt_fgcol(s); - s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } else { - cirrus_bitblt_fgcol(s); - cirrus_bitblt_bgcol(s); - s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } - } else { - s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } - } else { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { - if (s->cirrus_blt_pixelwidth > 2) { - printf("src transparent without colorexpand must be 8bpp or 16bpp\n"); - goto bitblt_ignore; - } - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) { - s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch; - s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch; - s->cirrus_rop = cirrus_bkwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } else { - s->cirrus_rop = cirrus_fwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - } - } else { - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) { - s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch; - s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch; - s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]]; - } else { - s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]]; - } - } - } - // setup bitblt engine. - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) { - if (!cirrus_bitblt_cputovideo(s)) - goto bitblt_ignore; - } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) { - if (!cirrus_bitblt_videotocpu(s)) - goto bitblt_ignore; - } else { - if (!cirrus_bitblt_videotovideo(s)) - goto bitblt_ignore; - } - } - return; - bitblt_ignore:; - cirrus_bitblt_reset(s); -} - -static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value) -{ - unsigned old_value; - - old_value = s->gr[0x31]; - s->gr[0x31] = reg_value & 0xee; - - if (((old_value & CIRRUS_BLT_RESET) != 0) && - ((reg_value & CIRRUS_BLT_RESET) == 0)) { - if(s->device_id == CIRRUS_ID_CLGD5446){ - cirrus_bitblt_reset(s); - }else{ - cirrus_bitblt_start(s);// XXX: Win2000のハードウェアアクセラレーションを正常に動かすのに必要。根拠無し。 - if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ - // XXX: Win3.1の最初のBitBltが無視される問題の回避策 - if(!(old_value & 0x04)){ - cirrus_bitblt_reset(s); - } - }else{ - cirrus_bitblt_reset(s); - } - } - } else if (((old_value & CIRRUS_BLT_START) == 0) && - ((reg_value & CIRRUS_BLT_START) != 0)) { - cirrus_bitblt_start(s); - } -} - -static void cirrus_bitblt_dblbufferswitch(){ - CirrusVGAState *s = cirrusvga; - if(s->device_id == CIRRUS_ID_CLGD5446){ - if(s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_BLTSYNCDISP){ - if((s->cr[0x5e] & 0x7) == 0x7){ - s->graphics_dblbuf_index = (s->graphics_dblbuf_index + 1) & 0x1; - } - if((s->cr[0x5e] & 0x30) == 0x30){ - s->videowindow_dblbuf_index = (s->videowindow_dblbuf_index + 1) & 0x1; - } - } - } -} - - -/*************************************** - * - * basic parameters - * - ***************************************/ - -static void cirrus_get_offsets(VGAState *s1, - uint32_t_ *pline_offset, - uint32_t_ *pstart_addr, - uint32_t_ *pline_compare) -{ - CirrusVGAState * s = (CirrusVGAState *)s1; - uint32_t_ start_addr, line_offset, line_compare; - - line_offset = s->cr[0x13] - | ((s->cr[0x1b] & 0x10) << 4); - line_offset <<= 3; - *pline_offset = line_offset; - - start_addr = (s->cr[0x0c] << 8) - | s->cr[0x0d] - | ((s->cr[0x1b] & 0x01) << 16) - | ((s->cr[0x1b] & 0x0c) << 15) - | ((s->cr[0x1d] & 0x80) << 12); - *pstart_addr = start_addr; - - line_compare = s->cr[0x18] | - ((s->cr[0x07] & 0x10) << 4) | - ((s->cr[0x09] & 0x40) << 3); - *pline_compare = line_compare; -} - -static uint32_t_ cirrus_get_bpp16_depth(CirrusVGAState * s) -{ - uint32_t_ ret = 16; - - switch (s->cirrus_hidden_dac_data & 0xf) { - case 0: - ret = 15; - break; /* Sierra HiColor */ - case 1: - ret = 16; - break; /* XGA HiColor */ - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: invalid DAC value %x in 16bpp\n", - (s->cirrus_hidden_dac_data & 0xf)); -#endif - ret = 15; /* XXX */ - break; - } - return ret; -} - -static int cirrus_get_bpp(VGAState *s1) -{ - CirrusVGAState * s = (CirrusVGAState *)s1; - uint32_t_ ret = 8; - - if ((s->sr[0x07] & 0x01) != 0) { - /* Cirrus SVGA */ - switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) { - case CIRRUS_SR7_BPP_8: - ret = 8; - break; - case CIRRUS_SR7_BPP_16_DOUBLEVCLK: - ret = cirrus_get_bpp16_depth(s); - break; - case CIRRUS_SR7_BPP_24: - ret = 24; - break; - case CIRRUS_SR7_BPP_16: - ret = cirrus_get_bpp16_depth(s); - break; - case CIRRUS_SR7_BPP_32: - ret = 32; - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]); -#endif - ret = 8; - break; - } - } else { - //ret = 8; - /* VGA */ - ret = 0; - } - - return ret; -} - -static void cirrus_get_resolution(VGAState *s, int *pwidth, int *pheight) -{ - int width, height; - - width = (s->cr[0x01] + 1) * 8; - height = s->cr[0x12] | - ((s->cr[0x07] & 0x02) << 7) | - ((s->cr[0x07] & 0x40) << 3); - height = (height + 1); - /* interlace support */ - if (s->cr[0x1a] & 0x01) - height = height * 2; - if(width==320) height /= 2; // XXX: Win98で表示がおかしくなるのでとりあえず仮 - if(width==400) height = 300; // XXX: Win98で表示がおかしくなるのでとりあえず仮 - if(width==512) height = 384; // XXX: Win98で表示がおかしくなるのでとりあえず仮 - if(height >= width * 3 / 4 * 2){ - height /= 2; // XXX: 縦長過ぎるとき、高さ半分にしておく - } - - // WSN 1280x1024 - if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WAB || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ - // XXX: WSN用やっつけ修正 - if(width==1280){ - height = 1024; - } - } - - *pwidth = width; - *pheight = height; -} - -/*************************************** - * - * bank memory - * - ***************************************/ - -static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index) -{ - unsigned offset; - unsigned limit; - - if ((s->gr[0x0b] & 0x01) != 0) /* dual bank */ - offset = s->gr[0x09 + bank_index]; - else /* single bank */ - offset = s->gr[0x09]; - - if ((s->gr[0x0b] & 0x20) != 0) - offset <<= 14; - else - offset <<= 12; - - if ((unsigned int)s->real_vram_size <= offset) - limit = 0; - else - limit = s->real_vram_size - offset; - - if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) { - if (limit > 0x8000) { - offset += 0x8000; - limit -= 0x8000; - } else { - limit = 0; - } - } - - if (limit > 0) { - /* Thinking about changing bank base? First, drop the dirty bitmap information - * on the current location, otherwise we lose this pointer forever */ - if (s->lfb_vram_mapped) { - target_phys_addr_t base_addr = isa_mem_base + 0xF80000 + bank_index * 0x8000; - cpu_physical_sync_dirty_bitmap(base_addr, base_addr + 0x8000); - TRACEOUT(("UNSUPPORT1")); - } - s->cirrus_bank_base[bank_index] = offset; - s->cirrus_bank_limit[bank_index] = limit; - } else { - s->cirrus_bank_base[bank_index] = 0; - s->cirrus_bank_limit[bank_index] = 0; - } -} - -/*************************************** - * - * I/O access between 0x3c4-0x3c5 - * - ***************************************/ - -static int -cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value) -{ - switch (reg_index) { - case 0x00: // Standard VGA - case 0x01: // Standard VGA - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - return CIRRUS_HOOK_NOT_HANDLED; - case 0x06: // Unlock Cirrus extensions - *reg_value = s->sr[reg_index]; - break; - case 0x10: - case 0x30: - case 0x50: - case 0x70: // Graphics Cursor X - case 0x90: - case 0xb0: - case 0xd0: - case 0xf0: // Graphics Cursor X - *reg_value = s->sr[0x10]; - break; - case 0x11: - case 0x31: - case 0x51: - case 0x71: // Graphics Cursor Y - case 0x91: - case 0xb1: - case 0xd1: - case 0xf1: // Graphics Cursor Y - *reg_value = s->sr[0x11]; - break; - case 0x05: // ??? - case 0x07: // Extended Sequencer Mode -// cirrus_update_memory_access(s); -#ifdef DEBUG_CIRRUS - printf("cirrus: handled inport sr_index %02x\n", reg_index); -#endif - *reg_value = s->sr[reg_index]; - break; - case 0x08: // EEPROM Control -#if defined(SUPPORT_PCI) - // XXX: Win2000でPnPデバイス検出を動かすのに必要。理由は謎 - if(pcidev.enable && np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - *reg_value = cirrusvga->sr[0x08] = 0xFE; - break; - } -#endif - case 0x09: // Scratch Register 0 - case 0x0a: // Scratch Register 1 - case 0x0b: // VCLK 0 - case 0x0c: // VCLK 1 - case 0x0d: // VCLK 2 - case 0x0e: // VCLK 3 - case 0x0f: // DRAM Control - case 0x12: // Graphics Cursor Attribute - case 0x13: // Graphics Cursor Pattern Address - case 0x14: // Scratch Register 2 - case 0x15: // Scratch Register 3 - case 0x16: // Performance Tuning Register - case 0x17: // Configuration Readback and Extended Control - case 0x18: // Signature Generator Control - case 0x19: // Signal Generator Result - case 0x1a: // Signal Generator Result - case 0x1b: // VCLK 0 Denominator & Post - case 0x1c: // VCLK 1 Denominator & Post - case 0x1d: // VCLK 2 Denominator & Post - case 0x1e: // VCLK 3 Denominator & Post - case 0x1f: // BIOS Write Enable and MCLK select -#ifdef DEBUG_CIRRUS - printf("cirrus: handled inport sr_index %02x\n", reg_index); -#endif - *reg_value = s->sr[reg_index]; - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: inport sr_index %02x\n", reg_index); -#endif - *reg_value = 0xff; - break; - } - - return CIRRUS_HOOK_HANDLED; -} - -static int -cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) -{ - switch (reg_index) { - case 0x00: // Standard VGA - case 0x01: // Standard VGA - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - return CIRRUS_HOOK_NOT_HANDLED; - case 0x06: // Unlock Cirrus extensions - reg_value &= 0x17; - if (reg_value == 0x12) { - s->sr[reg_index] = 0x12; - } else { - s->sr[reg_index] = 0x0f; - } - break; - case 0x10: - case 0x30: - case 0x50: - case 0x70: // Graphics Cursor X - case 0x90: - case 0xb0: - case 0xd0: - case 0xf0: // Graphics Cursor X - s->sr[0x10] = reg_value; - s->hw_cursor_x = (reg_value << 3) | (reg_index >> 5); - cirrusvga_updated = 1; - break; - case 0x11: - case 0x31: - case 0x51: - case 0x71: // Graphics Cursor Y - case 0x91: - case 0xb1: - case 0xd1: - case 0xf1: // Graphics Cursor Y - s->sr[0x11] = reg_value; - s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5); - cirrusvga_updated = 1; - break; - case 0x07: // Extended Sequencer Mode -// cirrus_update_memory_access(s); - case 0x08: // EEPROM Control - case 0x09: // Scratch Register 0 - case 0x0a: // Scratch Register 1 - case 0x0b: // VCLK 0 - case 0x0c: // VCLK 1 - case 0x0d: // VCLK 2 - case 0x0e: // VCLK 3 - case 0x0f: // DRAM Control - case 0x12: // Graphics Cursor Attribute - case 0x13: // Graphics Cursor Pattern Address - case 0x14: // Scratch Register 2 - case 0x15: // Scratch Register 3 - case 0x16: // Performance Tuning Register - case 0x18: // Signature Generator Control - case 0x19: // Signature Generator Result - case 0x1a: // Signature Generator Result - case 0x1b: // VCLK 0 Denominator & Post - case 0x1c: // VCLK 1 Denominator & Post - case 0x1d: // VCLK 2 Denominator & Post - case 0x1e: // VCLK 3 Denominator & Post - case 0x1f: // BIOS Write Enable and MCLK select - if(reg_index==0x07 && np2clvga.gd54xxtype < 0xff && np2clvga.gd54xxtype != CIRRUS_98ID_PCI){ - s->sr[reg_index] = (s->sr[reg_index] & 0xf0) | (reg_value & 0x0f); - }else{ - s->sr[reg_index] = reg_value; - } - s->sr[reg_index] = reg_value; - cirrus_update_memory_access(s); -#ifdef DEBUG_CIRRUS - printf("cirrus: handled outport sr_index %02x, sr_value %02x\n", - reg_index, reg_value); -#endif - break; - case 0x17: // Configuration Readback and Extended Control - s->sr[reg_index] = (s->sr[reg_index] & 0x38) | (reg_value & 0xc7); - cirrus_update_memory_access(s); - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index, - reg_value); -#endif - break; - } - - return CIRRUS_HOOK_HANDLED; -} - -/*************************************** - * - * I/O access at 0x3c6 - * - ***************************************/ - -static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value) -{ - *reg_value = 0xff; - if (++s->cirrus_hidden_dac_lockindex == 5) { - *reg_value = s->cirrus_hidden_dac_data; - s->cirrus_hidden_dac_lockindex = 0; - } -} - -static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value) -{ - if (s->cirrus_hidden_dac_lockindex == 4) { - s->cirrus_hidden_dac_data = reg_value; -#if defined(DEBUG_CIRRUS) - printf("cirrus: outport hidden DAC, value %02x\n", reg_value); -#endif - } - s->cirrus_hidden_dac_lockindex = 0; -} - -/*************************************** - * - * I/O access at 0x3c9 - * - ***************************************/ - -static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value) -{ - if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) - return CIRRUS_HOOK_NOT_HANDLED; - *reg_value = - s->cirrus_hidden_palette[(s->dac_read_index & 0x0f) * 3 + - s->dac_sub_index]; - if (++s->dac_sub_index == 3) { - s->dac_sub_index = 0; - s->dac_read_index++; - } - return CIRRUS_HOOK_HANDLED; -} - -static int cirrus_hook_write_palette(CirrusVGAState* s, int reg_value) -{ - if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) - return CIRRUS_HOOK_NOT_HANDLED; - s->dac_cache[s->dac_sub_index] = reg_value; - if (++s->dac_sub_index == 3) - { - memcpy(&s->cirrus_hidden_palette[(s->dac_write_index & 0x0f) * 3], - s->dac_cache, 3); - /* XXX update cursor */ - s->dac_sub_index = 0; - s->dac_write_index++; - cirrusvga_updated = 1; - } - return CIRRUS_HOOK_HANDLED; -} - -/*************************************** - * - * I/O access between 0x3ce-0x3cf - * - ***************************************/ - -static int -cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value) -{ - switch (reg_index) { - case 0x00: // Standard VGA, BGCOLOR 0x000000ff - *reg_value = s->cirrus_shadow_gr0; - return CIRRUS_HOOK_HANDLED; - case 0x01: // Standard VGA, FGCOLOR 0x000000ff - *reg_value = s->cirrus_shadow_gr1; - return CIRRUS_HOOK_HANDLED; - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - return CIRRUS_HOOK_NOT_HANDLED; - case 0x06: // Standard VGA - *reg_value = s->gr[0x06]; - return CIRRUS_HOOK_HANDLED; - case 0x07: // Standard VGA - case 0x08: // Standard VGA - return CIRRUS_HOOK_NOT_HANDLED; - case 0x05: // Standard VGA, Cirrus extended mode - default: - break; - } - - if (reg_index < 0x3a) { - *reg_value = s->gr[reg_index]; - } else { -#ifdef DEBUG_CIRRUS - printf("cirrus: inport gr_index %02x\n", reg_index); -#endif - *reg_value = 0xff; - } - - return CIRRUS_HOOK_HANDLED; -} - -static int -cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) -{ -#if defined(DEBUG_BITBLT) && 0 - printf("gr%02x: %02x\n", reg_index, reg_value); -#endif - switch (reg_index) { - case 0x00: // Standard VGA, BGCOLOR 0x000000ff - s->cirrus_shadow_gr0 = reg_value; - return CIRRUS_HOOK_NOT_HANDLED; - case 0x01: // Standard VGA, FGCOLOR 0x000000ff - s->cirrus_shadow_gr1 = reg_value; - return CIRRUS_HOOK_NOT_HANDLED; - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - return CIRRUS_HOOK_NOT_HANDLED; - case 0x06: // Standard VGA - s->gr[reg_index] = reg_value & 0x0f; - cirrus_update_memory_access(s); - break; - case 0x07: // Standard VGA - case 0x08: // Standard VGA - return CIRRUS_HOOK_NOT_HANDLED; - case 0x05: // Standard VGA, Cirrus extended mode - s->gr[reg_index] = reg_value & 0x7f; - cirrus_update_memory_access(s); - break; - case 0x09: // bank offset #0 - case 0x0A: // bank offset #1 - s->gr[reg_index] = reg_value; - cirrus_update_bank_ptr(s, 0); - cirrus_update_bank_ptr(s, 1); - cirrus_update_memory_access(s); - break; - case 0x0B: - s->gr[reg_index] = reg_value; - cirrus_update_bank_ptr(s, 0); - cirrus_update_bank_ptr(s, 1); - cirrus_update_memory_access(s); - break; - case 0x0e: // Power Management (CL-GD5446) - case 0x10: // BGCOLOR 0x0000ff00 - case 0x11: // FGCOLOR 0x0000ff00 - case 0x12: // BGCOLOR 0x00ff0000 - case 0x13: // FGCOLOR 0x00ff0000 - case 0x14: // BGCOLOR 0xff000000 - case 0x15: // FGCOLOR 0xff000000 - case 0x20: // BLT WIDTH 0x0000ff - case 0x22: // BLT HEIGHT 0x0000ff - case 0x24: // BLT DEST PITCH 0x0000ff - case 0x26: // BLT SRC PITCH 0x0000ff - case 0x28: // BLT DEST ADDR 0x0000ff - case 0x29: // BLT DEST ADDR 0x00ff00 - case 0x2c: // BLT SRC ADDR 0x0000ff - case 0x2d: // BLT SRC ADDR 0x00ff00 - case 0x2f: // BLT WRITEMASK - case 0x30: // BLT MODE - case 0x32: // RASTER OP - case 0x34: // BLT TRANSPARENT COLOR 0x00ff - case 0x35: // BLT TRANSPARENT COLOR 0xff00 - case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff - case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00 - s->gr[reg_index] = reg_value; - break; - case 0x21: // BLT WIDTH 0x001f00 - case 0x23: // BLT HEIGHT 0x001f00 - case 0x25: // BLT DEST PITCH 0x001f00 - case 0x27: // BLT SRC PITCH 0x001f00 - s->gr[reg_index] = reg_value & 0x1f; - break; - case 0x2a: // BLT DEST ADDR 0x3f0000 - s->gr[reg_index] = reg_value & 0x3f; - /* if auto start mode, starts bit blt now */ - if (s->gr[0x31] & CIRRUS_BLT_AUTOSTART) { - cirrus_bitblt_start(s); - } - break; - case 0x2e: // BLT SRC ADDR 0x3f0000 - s->gr[reg_index] = reg_value & 0x3f; - break; - case 0x31: // BLT STATUS/START - cirrus_write_bitblt(s, reg_value); - //cirrus_write_bitblt(s, reg_value); - break; - case 0x33: // BLT MODEEXT - if(s->device_id != CIRRUS_ID_CLGD5446 || - ((s->gr[0x0e] & 0x20) || (s->gr[0x31] & 0x80)) && (s->cr[0x5e] & 0x20)) { - s->gr[reg_index] = reg_value; - } - - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index, - reg_value); -#endif - break; - } - - return CIRRUS_HOOK_HANDLED; -} - -/*************************************** - * - * I/O access between 0x3d4-0x3d5 - * - ***************************************/ - -static int -cirrus_hook_read_cr(CirrusVGAState * s, unsigned reg_index, int *reg_value) -{ - switch (reg_index) { - case 0x00: // Standard VGA - case 0x01: // Standard VGA - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - case 0x05: // Standard VGA - case 0x06: // Standard VGA - case 0x07: // Standard VGA - case 0x08: // Standard VGA - case 0x09: // Standard VGA - case 0x0a: // Standard VGA - case 0x0b: // Standard VGA - case 0x0c: // Standard VGA - case 0x0d: // Standard VGA - case 0x0e: // Standard VGA - case 0x0f: // Standard VGA - case 0x10: // Standard VGA - case 0x11: // Standard VGA - case 0x12: // Standard VGA - case 0x13: // Standard VGA - case 0x14: // Standard VGA - case 0x15: // Standard VGA - case 0x16: // Standard VGA - case 0x17: // Standard VGA - case 0x18: // Standard VGA - return CIRRUS_HOOK_NOT_HANDLED; - case 0x24: // Attribute Controller Toggle Readback (R) - *reg_value = (s->ar_flip_flop << 7); - break; - case 0x19: // Interlace End - case 0x1a: // Miscellaneous Control - case 0x1b: // Extended Display Control - case 0x1c: // Sync Adjust and Genlock - case 0x1d: // Overlay Extended Control - case 0x22: // Graphics Data Latches Readback (R) - *reg_value = s->cr[reg_index]; - break; - case 0x25: // Part Status - *reg_value = s->cr[reg_index]; - break; - case 0x27: // Part ID (R) - if(np2clvga.gd54xxtype <= 0xff){ - *reg_value = s->cr[reg_index]; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ - *reg_value = CIRRUS_ID_CLGD5428; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ - *reg_value = CIRRUS_ID_CLGD5434; - }else if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - *reg_value = CIRRUS_ID_CLGD5434; - }else{ - *reg_value = s->cr[reg_index]; - } - s->cr[0x5e] |= 0x20; // XXX: Part IDを読んだらGR33を書き込み可能にする(WinNT4専用の不具合回避) - break; - case 0x28: // Class ID Register - if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ - *reg_value = 0x03; - }else if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC) { - *reg_value = 0x03; - } - break; - case 0x26: // Attribute Controller Index Readback (R) - *reg_value = s->ar_index & 0x3f; - break; - case 0x31: // Video Window Horizontal Zoom Control - case 0x32: // Video Window Vertical Zoom Control - case 0x33: // Video Window Horizontal Region 1 Size - case 0x34: // Video Window Region 2 Skip Size - case 0x35: // Video Window Region 2 Active Size - case 0x36: // Video Window Horizontal Overflow - case 0x37: // Video Window Vertical Start - case 0x38: // Video Window Vertical End - case 0x39: // Video Window Vertical Overflow - case 0x3a: // Video Buffer 1 Start Address Byte 0 - case 0x3b: // Video Buffer 1 Start Address Byte 1 - case 0x3c: // Video Buffer 1 Start Address Byte 2 - case 0x3d: // Video Window Address Offset - case 0x3e: // Video Window Master Control - case 0x3f: // Host Video Data Path Control - case 0x5d: // Video Window Pixel Alignment - if(s->device_id >= CIRRUS_ID_CLGD5440){ - *reg_value = s->cr[reg_index]; - } - break; - case 0x5e: // Double Buffer Control (CL-GD5446) - if(s->device_id == CIRRUS_ID_CLGD5446){ - *reg_value = s->cr[reg_index]; - } - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: inport cr_index %02x\n", reg_index); - *reg_value = 0xff; -#endif - break; - } - - return CIRRUS_HOOK_HANDLED; -} - -static int -cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value) -{ - switch (reg_index) { - case 0x00: // Standard VGA - case 0x01: // Standard VGA - case 0x02: // Standard VGA - case 0x03: // Standard VGA - case 0x04: // Standard VGA - case 0x05: // Standard VGA - case 0x06: // Standard VGA - case 0x07: // Standard VGA - case 0x08: // Standard VGA - case 0x09: // Standard VGA - case 0x0a: // Standard VGA - case 0x0b: // Standard VGA - case 0x0c: // Standard VGA - case 0x0d: // Standard VGA - case 0x0e: // Standard VGA - case 0x0f: // Standard VGA - case 0x10: // Standard VGA - case 0x11: // Standard VGA - case 0x12: // Standard VGA - case 0x13: // Standard VGA - case 0x14: // Standard VGA - case 0x15: // Standard VGA - case 0x16: // Standard VGA - case 0x17: // Standard VGA - case 0x18: // Standard VGA - return CIRRUS_HOOK_NOT_HANDLED; - case 0x19: // Interlace End - case 0x1a: // Miscellaneous Control - case 0x1b: // Extended Display Control - case 0x1c: // Sync Adjust and Genlock - case 0x1d: // Overlay Extended Control - s->cr[reg_index] = reg_value; -#ifdef DEBUG_CIRRUS - printf("cirrus: handled outport cr_index %02x, cr_value %02x\n", - reg_index, reg_value); -#endif - break; - case 0x22: // Graphics Data Latches Readback (R) - case 0x24: // Attribute Controller Toggle Readback (R) - case 0x26: // Attribute Controller Index Readback (R) - case 0x27: // Part ID (R) - break; - case 0x31: // Video Window Horizontal Zoom Control - case 0x32: // Video Window Vertical Zoom Control - case 0x33: // Video Window Horizontal Region 1 Size - case 0x34: // Video Window Region 2 Skip Size - case 0x35: // Video Window Region 2 Active Size - case 0x36: // Video Window Horizontal Overflow - case 0x37: // Video Window Vertical Start - case 0x38: // Video Window Vertical End - case 0x39: // Video Window Vertical Overflow - case 0x3a: // Video Buffer 1 Start Address Byte 0 - case 0x3b: // Video Buffer 1 Start Address Byte 1 - case 0x3c: // Video Buffer 1 Start Address Byte 2 - case 0x3d: // Video Window Address Offset - case 0x3e: // Video Window Master Control - case 0x3f: // Host Video Data Path Control - case 0x5d: // Video Window Pixel Alignment - if(s->device_id >= CIRRUS_ID_CLGD5440){ - s->cr[reg_index] = reg_value; - } - break; - case 0x5e: // Double Buffer Control (CL-GD5446) - if(s->device_id == CIRRUS_ID_CLGD5446){ - s->cr[reg_index] = reg_value; - switch(reg_value & 0x7){ - case 0: // Compatible VGA display address control - s->graphics_dblbuf_index = 0; - break; - case 1: // VSYNC switching - break; - case 2: // Forces graphics buffer 1 as display - s->graphics_dblbuf_index = 0; - break; - case 3: // Forces graphics buffer 2 as display - s->graphics_dblbuf_index = 1; - break; - case 4: // A18 controls switching - break; - case 5: // A19 controls switching - break; - case 6: // Reserved - break; - case 7: // Bitblt switches - break; - } - } - break; - case 0x25: // Part Status - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: outport cr_index %02x, cr_value %02x\n", reg_index, - reg_value); -#endif - break; - } - - return CIRRUS_HOOK_HANDLED; -} - -/*************************************** - * - * memory-mapped I/O (bitblt) - * - ***************************************/ - -static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address) -{ - int value = 0xff; - - switch (address) { - case (CIRRUS_MMIO_BLTBGCOLOR + 0): - cirrus_hook_read_gr(s, 0x00, &value); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 1): - cirrus_hook_read_gr(s, 0x10, &value); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 2): - cirrus_hook_read_gr(s, 0x12, &value); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 3): - cirrus_hook_read_gr(s, 0x14, &value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 0): - cirrus_hook_read_gr(s, 0x01, &value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 1): - cirrus_hook_read_gr(s, 0x11, &value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 2): - cirrus_hook_read_gr(s, 0x13, &value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 3): - cirrus_hook_read_gr(s, 0x15, &value); - break; - case (CIRRUS_MMIO_BLTWIDTH + 0): - cirrus_hook_read_gr(s, 0x20, &value); - break; - case (CIRRUS_MMIO_BLTWIDTH + 1): - cirrus_hook_read_gr(s, 0x21, &value); - break; - case (CIRRUS_MMIO_BLTHEIGHT + 0): - cirrus_hook_read_gr(s, 0x22, &value); - break; - case (CIRRUS_MMIO_BLTHEIGHT + 1): - cirrus_hook_read_gr(s, 0x23, &value); - break; - case (CIRRUS_MMIO_BLTDESTPITCH + 0): - cirrus_hook_read_gr(s, 0x24, &value); - break; - case (CIRRUS_MMIO_BLTDESTPITCH + 1): - cirrus_hook_read_gr(s, 0x25, &value); - break; - case (CIRRUS_MMIO_BLTSRCPITCH + 0): - cirrus_hook_read_gr(s, 0x26, &value); - break; - case (CIRRUS_MMIO_BLTSRCPITCH + 1): - cirrus_hook_read_gr(s, 0x27, &value); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 0): - cirrus_hook_read_gr(s, 0x28, &value); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 1): - cirrus_hook_read_gr(s, 0x29, &value); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 2): - cirrus_hook_read_gr(s, 0x2a, &value); - break; - case (CIRRUS_MMIO_BLTSRCADDR + 0): - cirrus_hook_read_gr(s, 0x2c, &value); - break; - case (CIRRUS_MMIO_BLTSRCADDR + 1): - cirrus_hook_read_gr(s, 0x2d, &value); - break; - case (CIRRUS_MMIO_BLTSRCADDR + 2): - cirrus_hook_read_gr(s, 0x2e, &value); - break; - case CIRRUS_MMIO_BLTWRITEMASK: - cirrus_hook_read_gr(s, 0x2f, &value); - break; - case CIRRUS_MMIO_BLTMODE: - cirrus_hook_read_gr(s, 0x30, &value); - break; - case CIRRUS_MMIO_BLTROP: - cirrus_hook_read_gr(s, 0x32, &value); - break; - case CIRRUS_MMIO_BLTMODEEXT: - cirrus_hook_read_gr(s, 0x33, &value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0): - cirrus_hook_read_gr(s, 0x34, &value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1): - cirrus_hook_read_gr(s, 0x35, &value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0): - cirrus_hook_read_gr(s, 0x38, &value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1): - cirrus_hook_read_gr(s, 0x39, &value); - break; - case CIRRUS_MMIO_BLTSTATUS: - cirrus_hook_read_gr(s, 0x31, &value); - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: mmio read - address 0x%04x\n", address); -#endif - break; - } - - return (uint8_t) value; -} - -static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address, - uint8_t value) -{ - switch (address) { - case (CIRRUS_MMIO_BLTBGCOLOR + 0): - cirrus_hook_write_gr(s, 0x00, value); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 1): - cirrus_hook_write_gr(s, 0x10, value); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 2): - cirrus_hook_write_gr(s, 0x12, value); - break; - case (CIRRUS_MMIO_BLTBGCOLOR + 3): - cirrus_hook_write_gr(s, 0x14, value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 0): - cirrus_hook_write_gr(s, 0x01, value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 1): - cirrus_hook_write_gr(s, 0x11, value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 2): - cirrus_hook_write_gr(s, 0x13, value); - break; - case (CIRRUS_MMIO_BLTFGCOLOR + 3): - cirrus_hook_write_gr(s, 0x15, value); - break; - case (CIRRUS_MMIO_BLTWIDTH + 0): - cirrus_hook_write_gr(s, 0x20, value); - break; - case (CIRRUS_MMIO_BLTWIDTH + 1): - cirrus_hook_write_gr(s, 0x21, value); - break; - case (CIRRUS_MMIO_BLTHEIGHT + 0): - cirrus_hook_write_gr(s, 0x22, value); - break; - case (CIRRUS_MMIO_BLTHEIGHT + 1): - cirrus_hook_write_gr(s, 0x23, value); - break; - case (CIRRUS_MMIO_BLTDESTPITCH + 0): - cirrus_hook_write_gr(s, 0x24, value); - break; - case (CIRRUS_MMIO_BLTDESTPITCH + 1): - cirrus_hook_write_gr(s, 0x25, value); - break; - case (CIRRUS_MMIO_BLTSRCPITCH + 0): - cirrus_hook_write_gr(s, 0x26, value); - break; - case (CIRRUS_MMIO_BLTSRCPITCH + 1): - cirrus_hook_write_gr(s, 0x27, value); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 0): - cirrus_hook_write_gr(s, 0x28, value); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 1): - cirrus_hook_write_gr(s, 0x29, value); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 2): - cirrus_hook_write_gr(s, 0x2a, value); - break; - case (CIRRUS_MMIO_BLTDESTADDR + 3): - /* ignored */ - break; - case (CIRRUS_MMIO_BLTSRCADDR + 0): - cirrus_hook_write_gr(s, 0x2c, value); - break; - case (CIRRUS_MMIO_BLTSRCADDR + 1): - cirrus_hook_write_gr(s, 0x2d, value); - break; - case (CIRRUS_MMIO_BLTSRCADDR + 2): - cirrus_hook_write_gr(s, 0x2e, value); - break; - case CIRRUS_MMIO_BLTWRITEMASK: - cirrus_hook_write_gr(s, 0x2f, value); - break; - case CIRRUS_MMIO_BLTMODE: - cirrus_hook_write_gr(s, 0x30, value); - break; - case CIRRUS_MMIO_BLTROP: - cirrus_hook_write_gr(s, 0x32, value); - break; - case CIRRUS_MMIO_BLTMODEEXT: - cirrus_hook_write_gr(s, 0x33, value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0): - cirrus_hook_write_gr(s, 0x34, value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1): - cirrus_hook_write_gr(s, 0x35, value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0): - cirrus_hook_write_gr(s, 0x38, value); - break; - case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1): - cirrus_hook_write_gr(s, 0x39, value); - break; - case CIRRUS_MMIO_BLTSTATUS: - cirrus_hook_write_gr(s, 0x31, value); - break; - default: -#ifdef DEBUG_CIRRUS - printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n", - address, value); -#endif - break; - } -} - -/*************************************** - * - * write mode 4/5 - * - * assume TARGET_PAGE_SIZE >= 16 - * - ***************************************/ - -static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s, - unsigned mode, - unsigned offset, - uint32_t_ mem_value) -{ - int x; - unsigned val = mem_value; - unsigned mask = s->sr[0x2]; - uint8_t *dst; - if(s->gr[0xb] & 0x04){ - }else{ - mask = 0xff; - } - - dst = s->vram_ptr + (offset &= s->cirrus_addr_mask); - for (x = 0; x < 8; x++) { - if (mask & 0x80) { - if (val & 0x80) { - *dst = s->cirrus_shadow_gr1; - } else if (mode == 5) { - *dst = s->cirrus_shadow_gr0; - } - } - val <<= 1; - mask <<= 1; - dst++; - } - cpu_physical_memory_set_dirty(s->vram_offset + offset); - cpu_physical_memory_set_dirty(s->vram_offset + offset + 7); - cirrusvga_updated = 1; -} - -static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s, - unsigned mode, - unsigned offset, - uint32_t_ mem_value) -{ - int x; - unsigned val = mem_value; - unsigned mask = s->sr[0x2]; - uint8_t *dst; - - if(s->gr[0xb] & 0x04){ - }else{ - mask = 0xffff; - } - if(s->gr[0xb] & 0x10){ - // SR2 Doubling Enabled - mask |= mask << 8; - } - - dst = s->vram_ptr + (offset &= s->cirrus_addr_mask); - for (x = 0; x < 8; x++) { - if (mask & 0x80) { - if (val & 0x80) { - *dst = s->cirrus_shadow_gr1; - *(dst + 1) = s->gr[0x11]; - } else if (mode == 5) { - *dst = s->cirrus_shadow_gr0; - *(dst + 1) = s->gr[0x10]; - } - } - val <<= 1; - mask <<= 1; - dst += 2; - } - cpu_physical_memory_set_dirty(s->vram_offset + offset); - cpu_physical_memory_set_dirty(s->vram_offset + offset + 15); - cirrusvga_updated = 1; -} - -/*************************************** - * - * memory access between 0xa0000-0xbffff - * - ***************************************/ - -#define ADDR_SH1 0x000 - -uint32_t_ cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState*)opaque; - unsigned bank_index; - unsigned bank_offset; - uint32_t_ val; - - - addr += ADDR_SH1; - - if ((s->sr[0x07] & 0x01) == 0) { - return vga_mem_readb(s, addr); - } - addr &= 0x1ffff; - - if (addr < 0x10000) { - /* XXX handle bitblt */ - /* video memory */ - bank_index = addr >> 15; - bank_offset = addr & 0x7fff; - if (bank_offset < s->cirrus_bank_limit[bank_index]) { - bank_offset += s->cirrus_bank_base[bank_index]; - if ((s->gr[0x0B] & 0x14) == 0x14) { - bank_offset <<= 4; - } else if (s->gr[0x0B] & 0x02) { - bank_offset <<= 3; - } - bank_offset &= s->cirrus_addr_mask; - val = *(s->vram_ptr + bank_offset); - } else - val = 0xff; - } else if (addr >= 0x18000 && addr < 0x18100) { - /* memory-mapped I/O */ - val = 0xff; - if ((s->sr[0x17] & 0x44) == 0x04) { - val = cirrus_mmio_blt_read(s, addr & 0xff); - } - } else { - val = 0xff; -#ifdef DEBUG_CIRRUS - printf("cirrus: mem_readb %06x\n", addr); -#endif - } - return val; -} - -uint32_t_ cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_vga_mem_readb(opaque, addr) << 8; - v |= cirrus_vga_mem_readb(opaque, addr + 1); -#else - v = cirrus_vga_mem_readb(opaque, addr); - v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8; -#endif - return v; -} - -uint32_t_ cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_vga_mem_readb(opaque, addr) << 24; - v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16; - v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8; - v |= cirrus_vga_mem_readb(opaque, addr + 3); -#else - v = cirrus_vga_mem_readb(opaque, addr); - v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8; - v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16; - v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24; -#endif - return v; -} - -void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, - uint32_t_ mem_value) -{ - CirrusVGAState *s = (CirrusVGAState*)opaque; - unsigned bank_index; - unsigned bank_offset; - unsigned mode; - - addr += ADDR_SH1; - - if ((s->sr[0x07] & 0x01) == 0) { - vga_mem_writeb(s, addr, mem_value); - return; - } - - addr &= 0x1ffff; - - if (addr < 0x10000) { - if (s->cirrus_srcptr != s->cirrus_srcptr_end) { - /* bitblt */ - *s->cirrus_srcptr++ = (uint8_t) mem_value; - *s->cirrus_srcptr++; - if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { - cirrus_bitblt_cputovideo_next(s); - } - } else { - /* video memory */ - bank_index = addr >> 15; - bank_offset = addr & 0x7fff; - if (bank_offset < s->cirrus_bank_limit[bank_index]) { - bank_offset += s->cirrus_bank_base[bank_index]; - if ((s->gr[0x0B] & 0x14) == 0x14) { - bank_offset <<= 4; - } else if (s->gr[0x0B] & 0x02) { - bank_offset <<= 3; - } - bank_offset &= s->cirrus_addr_mask; - mode = s->gr[0x05] & 0x7; - if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { - *(s->vram_ptr + bank_offset) = mem_value; - cpu_physical_memory_set_dirty(s->vram_offset + - bank_offset); - cirrusvga_updated = 1; - } else { - if ((s->gr[0x0B] & 0x14) != 0x14) { - cirrus_mem_writeb_mode4and5_8bpp(s, mode, - bank_offset, - mem_value); - } else { - cirrus_mem_writeb_mode4and5_16bpp(s, mode, - bank_offset, - mem_value); - } - } - } - } - } else if (addr >= 0x18000 && addr < 0x18100) { - /* memory-mapped I/O */ - if ((s->sr[0x17] & 0x44) == 0x04) { - cirrus_mmio_blt_write(s, addr & 0xff, mem_value); - } - } else { -#ifdef DEBUG_CIRRUS - printf("cirrus: mem_writeb %06x value %02x\n", addr, mem_value); -#endif - } -} - -void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val) -{ -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff); - cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff); -#else - cirrus_vga_mem_writeb(opaque, addr, val & 0xff); - cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); -#endif -} - -void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val) -{ -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff); - cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff); - cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff); - cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff); -#else - cirrus_vga_mem_writeb(opaque, addr, val & 0xff); - cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); - cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff); - cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff); -#endif -} - -static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = { - cirrus_vga_mem_readb, - cirrus_vga_mem_readw, - cirrus_vga_mem_readl, -}; - -static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = { - cirrus_vga_mem_writeb, - cirrus_vga_mem_writew, - cirrus_vga_mem_writel, -}; - -/*************************************** - * - * hardware cursor - * - ***************************************/ - -static void invalidate_cursor1(CirrusVGAState *s) -{ - if (s->last_hw_cursor_size) { - vga_invalidate_scanlines((VGAState *)s, - s->last_hw_cursor_y + s->last_hw_cursor_y_start, - s->last_hw_cursor_y + s->last_hw_cursor_y_end); - } -} - -static void cirrus_cursor_compute_yrange(CirrusVGAState *s) -{ - const uint8_t *src; - uint32_t_ content; - int y, y_min, y_max; - - src = s->vram_ptr + s->real_vram_size - 16 * 1024; - if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) { - src += (s->sr[0x13] & 0x3c) * 256; - y_min = 64; - y_max = -1; - for(y = 0; y < 64; y++) { - content = ((uint32_t_ *)src)[0] | - ((uint32_t_ *)src)[1] | - ((uint32_t_ *)src)[2] | - ((uint32_t_ *)src)[3]; - if (content) { - if (y < y_min) - y_min = y; - if (y > y_max) - y_max = y; - } - src += 16; - } - } else { - src += (s->sr[0x13] & 0x3f) * 256; - y_min = 32; - y_max = -1; - for(y = 0; y < 32; y++) { - content = ((uint32_t_ *)src)[0] | - ((uint32_t_ *)(src + 128))[0]; - if (content) { - if (y < y_min) - y_min = y; - if (y > y_max) - y_max = y; - } - src += 4; - } - } - if (y_min > y_max) { - s->last_hw_cursor_y_start = 0; - s->last_hw_cursor_y_end = 0; - } else { - s->last_hw_cursor_y_start = y_min; - s->last_hw_cursor_y_end = y_max + 1; - } -} - -/* NOTE: we do not currently handle the cursor bitmap change, so we - update the cursor only if it moves. */ -static void cirrus_cursor_invalidate(VGAState *s1) -{ - CirrusVGAState *s = (CirrusVGAState *)s1; - int size; - - if (!s->sr[0x12] & CIRRUS_CURSOR_SHOW) { - size = 0; - } else { - if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) - size = 64; - else - size = 32; - } - /* invalidate last cursor and new cursor if any change */ - if (s->last_hw_cursor_size != size || - s->last_hw_cursor_x != s->hw_cursor_x || - s->last_hw_cursor_y != s->hw_cursor_y) { - - invalidate_cursor1(s); - - s->last_hw_cursor_size = size; - s->last_hw_cursor_x = s->hw_cursor_x; - s->last_hw_cursor_y = s->hw_cursor_y; - /* compute the real cursor min and max y */ - cirrus_cursor_compute_yrange(s); - invalidate_cursor1(s); - cirrusvga_updated = 1; - } -} - -static int get_depth_index(DisplayState *s) -{ - switch(ds_get_bits_per_pixel(s)) { - default: - case 8: - return 0; - case 15: - return 1; - case 16: - return 2; - case 32: - return 3; - } -} -static void cirrus_cursor_draw_line(VGAState *s1, uint8_t *d1, int scr_y) -{ -} - -/*************************************** - * - * LFB memory access - * - ***************************************/ - -void cirrus_linear_mmio_update(void *opaque) -{ -#if defined(SUPPORT_IA32_HAXM) - CirrusVGAState *s = (CirrusVGAState *) opaque; - uint32_t_ ret; - uint8_t mode; - uint8_t linmmio = (s->sr[0x17] & 0x44) == 0x44; - mode = s->gr[0x05] & 0x7; - - if((0) || - (s->cirrus_srcptr != s->cirrus_srcptr_end) || - ((s->gr[0x0B] & 0x14) == 0x14) || - (s->gr[0x0B] & 0x02) || - !(mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0))){ - if(mmio_mode != MMIO_MODE_MMIO){ - if(np2clvga.VRAMWindowAddr){ - if(mmio_mode_region1) i386hax_vm_removememoryarea(vramptr, mmio_mode_region1, cirrusvga->real_vram_size - (mmio_mode==MMIO_MODE_VRAM1 ? 0x1000 : 0)); - } - mmio_mode_region1 = 0; - if(np2clvga.pciLFB_Addr){ - if(mmio_mode_region2) i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, cirrusvga->real_vram_size); - } - mmio_mode_region2 = 0; - lastlinmmio = linmmio; - mmio_mode = MMIO_MODE_MMIO; - } - }else{ - //if((s->sr[0x17] & 0x44) == 0x44 && (s->gr[0x6] & 0x0c) == 0x04){ - // if(mmio_mode != MMIO_MODE_VRAM1 || np2clvga.VRAMWindowAddr!=mmio_mode_region1 || np2clvga.pciLFB_Addr!=mmio_mode_region2 || lastlinmmio!=linmmio){ - // if(np2clvga.VRAMWindowAddr){ - // if(mmio_mode_region1) i386hax_vm_removememoryarea(vramptr, mmio_mode_region1, cirrusvga->real_vram_size); - // i386hax_vm_setmemoryarea(vramptr, np2clvga.VRAMWindowAddr, cirrusvga->real_vram_size - 0x1000); - // } - // mmio_mode_region1 = np2clvga.VRAMWindowAddr; - // if(np2clvga.pciLFB_Addr){ - // if(mmio_mode_region2) i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, linmmio ? s->linear_mmio_mask : cirrusvga->real_vram_size); - // i386hax_vm_setmemoryarea(vramptr, np2clvga.pciLFB_Addr, linmmio ? s->linear_mmio_mask : cirrusvga->real_vram_size); - // } - // mmio_mode_region2 = np2clvga.pciLFB_Addr; - // lastlinmmio = linmmio; - // mmio_mode = MMIO_MODE_VRAM1; - // } - //}else{ - if(mmio_mode != MMIO_MODE_VRAM2 || np2clvga.VRAMWindowAddr!=mmio_mode_region1 || np2clvga.pciLFB_Addr!=mmio_mode_region2 || lastlinmmio!=linmmio){ - if(np2clvga.VRAMWindowAddr){ - if(mmio_mode_region1) i386hax_vm_removememoryarea(vramptr, mmio_mode_region1, cirrusvga->real_vram_size - (mmio_mode==MMIO_MODE_VRAM1 ? 0x1000 : 0)); - i386hax_vm_setmemoryarea(vramptr, np2clvga.VRAMWindowAddr, cirrusvga->real_vram_size); - } - mmio_mode_region1 = np2clvga.VRAMWindowAddr; - if(np2clvga.pciLFB_Addr){ - if(mmio_mode_region2) i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, linmmio ? s->linear_mmio_mask : cirrusvga->real_vram_size); - i386hax_vm_setmemoryarea(vramptr, np2clvga.pciLFB_Addr, linmmio ? s->linear_mmio_mask : cirrusvga->real_vram_size); - } - mmio_mode_region2 = np2clvga.pciLFB_Addr; - lastlinmmio = linmmio; - mmio_mode = MMIO_MODE_VRAM2; - } - //} - } -#endif - cirrusvga_updated = 1; -} - -uint32_t_ cirrus_linear_readb(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - uint32_t_ ret; - - addr &= s->cirrus_addr_mask; - - if (((s->sr[0x17] & 0x44) == 0x44) && - ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) { - /* memory-mapped I/O */ - ret = cirrus_mmio_blt_read(s, addr & 0xff); - } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { - /* XXX handle bitblt */ - //ret = 0xff; - ret = *s->cirrus_srcptr; - s->cirrus_srcptr++; - if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { - cirrus_bitblt_videotocpu_next(s); - } - } else { - /* video memory */ - if ((s->gr[0x0B] & 0x14) == 0x14) { - addr <<= 4; - } else if (s->gr[0x0B] & 0x02) { - addr <<= 3; - } - addr &= s->cirrus_addr_mask; - ret = *(s->vram_ptr + addr); - //if(addr >= 0x1ff000){ - // TRACEOUT(("vga: read 0x%x", addr)); - //} - //if (0x1fff00 <= addr && addr < 0x1fff40){ - // ret = s->cr[addr & 0xff]; - //} - //if (addr == 0x1fff40){ - // if(np2wab.relaystateint & 0x2){ - // ret = 0x80; - // }else{ - // ret = 0x00; - // } - //} - } - - return ret; -} - -uint32_t_ cirrus_linear_readw(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_linear_readb(opaque, addr) << 8; - v |= cirrus_linear_readb(opaque, addr + 1); -#else - v = cirrus_linear_readb(opaque, addr); - v |= cirrus_linear_readb(opaque, addr + 1) << 8; -#endif - return v; -} - -uint32_t_ cirrus_linear_readl(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_linear_readb(opaque, addr) << 24; - v |= cirrus_linear_readb(opaque, addr + 1) << 16; - v |= cirrus_linear_readb(opaque, addr + 2) << 8; - v |= cirrus_linear_readb(opaque, addr + 3); -#else - v = cirrus_linear_readb(opaque, addr); - v |= cirrus_linear_readb(opaque, addr + 1) << 8; - v |= cirrus_linear_readb(opaque, addr + 2) << 16; - v |= cirrus_linear_readb(opaque, addr + 3) << 24; -#endif - return v; -} - -void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - unsigned mode; - - addr &= s->cirrus_addr_mask; - - if (((s->sr[0x17] & 0x44) == 0x44) && - ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) { - /* memory-mapped I/O */ - cirrus_mmio_blt_write(s, addr & 0xff, val); - } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { - /* bitblt */ - *s->cirrus_srcptr++ = (uint8_t) val; - if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { - cirrus_bitblt_cputovideo_next(s); - } - } else { - /* video memory */ - if ((s->gr[0x0B] & 0x14) == 0x14) { - addr <<= 4; - } else if (s->gr[0x0B] & 0x02) { - addr <<= 3; - } - addr &= s->cirrus_addr_mask; - - mode = s->gr[0x05] & 0x7; - if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { - *(s->vram_ptr + addr) = (uint8_t) val; - cpu_physical_memory_set_dirty(s->vram_offset + addr); - cirrusvga_updated = 1; - } else { - if ((s->gr[0x0B] & 0x14) != 0x14) { - cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val); - } else { - cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val); - } - } - //if (0x1fff00 <= addr && addr < 0x1fff40){ - // cirrus_mmio_blt_write(s, addr & 0xff, val); - // //cirrus_hook_write_cr(s, addr & 0xff, val); - //} - //if (addr == 0x1fff40){ - // char dat = 0x0; - // if(val == 0x80){ - // dat = 0x2; - // } - // if((!!np2wab.relaystateint) != (!!(dat & 0x2))){ - // np2wab.relaystateint = dat & 0x2; - // np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) - // } - // np2clvga.mmioenable = (dat&0x1); - // TRACEOUT(("vga: write 0x%x=%02x", addr, val)); - //} - //if(0x1ff000 <= addr && addr < 0x1fff00){ - // TRACEOUT(("vga: write 0x%x=%02x", addr, val)); - //} - //if(addr >= 0x1ff000){ - // TRACEOUT(("vga: write 0x%x=%02x", addr, val)); - //} - } -} - -void cirrus_linear_writew(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff); - cirrus_linear_writeb(opaque, addr + 1, val & 0xff); -#else - cirrus_linear_writeb(opaque, addr, val & 0xff); - cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff); -#endif -} - -void cirrus_linear_writel(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - // XXX: Workaround for Win9x Driver - CirrusVGAState *s = (CirrusVGAState *) opaque; - if(s->device_id == CIRRUS_ID_CLGD5446){ - if (((s->sr[0x17] & 0x44) == 0x44) && - ((addr & s->cirrus_addr_mask & s->linear_mmio_mask) == s->linear_mmio_mask)) { - if((addr & 0xff) == 0x0c && val==0){ - return; - } - } - } - -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff); - cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff); - cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff); - cirrus_linear_writeb(opaque, addr + 3, val & 0xff); -#else - cirrus_linear_writeb(opaque, addr, val & 0xff); - cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff); - cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff); - cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff); -#endif -} - - -static CPUReadMemoryFunc *cirrus_linear_read[3] = { - cirrus_linear_readb, - cirrus_linear_readw, - cirrus_linear_readl, -}; - -static CPUWriteMemoryFunc *cirrus_linear_write[3] = { - cirrus_linear_writeb, - cirrus_linear_writew, - cirrus_linear_writel, -}; - -void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - addr &= s->cirrus_addr_mask; - *(s->vram_ptr + addr) = val; - cpu_physical_memory_set_dirty(s->vram_offset + addr); - cirrusvga_updated = 1; -} - -void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - addr &= s->cirrus_addr_mask; - cpu_to_le16w((uint16_t_ *)(s->vram_ptr + addr), val); - cpu_physical_memory_set_dirty(s->vram_offset + addr); - cirrusvga_updated = 1; -} - -void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - addr &= s->cirrus_addr_mask; - cpu_to_le32w((uint32_t_ *)(s->vram_ptr + addr), val); - cpu_physical_memory_set_dirty(s->vram_offset + addr); - cirrusvga_updated = 1; -} - -/*************************************** - * - * E-BANK memory access - * - ***************************************/ - -// convert E-BANK VRAM window address to linear address -void cirrus_linear_memwnd_addr_convert(void *opaque, target_phys_addr_t *addrval){ - CirrusVGAState *s = (CirrusVGAState *) opaque; - int offset; - target_phys_addr_t addr = *addrval; - - if(np2clvga.gd54xxtype <= 0xff){ - //addr &= s->cirrus_addr_mask; - addr -= np2clvga.VRAMWindowAddr2; - //addr &= 0x7fff; - if ((s->gr[0x0b] & 0x01) != 0){ - /* dual bank */ - if(addr < 0x4000){ - offset = s->gr[0x09]; - }else{ - addr -= 0x4000; - offset = s->gr[0x0a]; - } - }else{ - /* single bank */ - offset = s->gr[0x09]; - } - if ((s->gr[0x0b] & 0x20) != 0) - offset <<= 14; - else - offset <<= 12; - - addr += (offset); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ - addr &= 0x7fff; - if ((s->gr[0x0b] & 0x01) != 0){ - /* dual bank */ - if(addr < 0x4000){ - offset = s->gr[0x09]; - }else{ - addr -= 0x4000; - offset = s->gr[0x0a]; - } - }else{ - /* single bank */ - offset = s->gr[0x09]; - } - if ((s->gr[0x0b] & 0x20) != 0) - offset <<= 14; - else - offset <<= 12; - - addr += (offset); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ - addr &= 0x7fff; - if ((s->gr[0x0b] & 0x01) != 0){ - /* dual bank */ - if(addr < 0x4000){ - offset = s->gr[0x09]; - }else{ - addr -= 0x4000; - offset = s->gr[0x0a]; - } - }else{ - /* single bank */ - offset = s->gr[0x09]; - } - if ((s->gr[0x0b] & 0x20) != 0) - offset <<= 14; - else - offset <<= 12; - - addr += (offset); - }else{ - addr &= 0x7fff; - if ((s->gr[0x0b] & 0x01) != 0){ - /* dual bank */ - if(addr < 0x4000){ - offset = s->gr[0x09]; - }else{ - addr -= 0x4000; - offset = s->gr[0x0a]; - } - }else{ - /* single bank */ - offset = s->gr[0x09]; - } - //if ((s->gr[0x0b] & 0x01) != 0) /* dual bank */ - // offset = s->gr[0x09/* + bank_index*/]; - //else /* single bank */ - // offset = s->gr[0x09]; - - if ((s->gr[0x0b] & 0x20) != 0) - addr += (offset) << 14L; - else - addr += (offset) << 12L; - } - addr &= s->cirrus_addr_mask; - *addrval = addr; -} -// I-O DATA用 -int cirrus_linear_memwnd_addr_convert_iodata(void *opaque, target_phys_addr_t *addrval){ - CirrusVGAState *s = (CirrusVGAState *) opaque; - int offset; - target_phys_addr_t addr = *addrval; - int ret = 0; - - // MMIO判定 - // 本当は... - // SR17[2]=1でMMIOイネーブル If this bit is set to '1', the BlT source will be system memory rather than display memory. - // 本当はそれに加えGR6[3-2]=01じゃないとMMIOモードにならない - // MMIOアドレスはSR17[6]=0:0xb8000に割り当て、1:リニアメモリの最後256byteに割り当て(CL-GD5430/'36/'40 only) - if ((s->sr[0x17] & CIRRUS_MMIO_ENABLE) != 0 && /*(s->gr[0x06] & 0x0c)==0x04 &&*/ ((addr & 0xff000) == 0xb8000)) { - ret = 1; // MMIO - } - - addr &= 0x7fff; - if ((s->gr[0x0b] & 0x01) != 0){ - /* dual bank */ - if(addr < 0x4000){ - offset = s->gr[0x09]; - }else{ - addr -= 0x4000; - offset = s->gr[0x0a]; - } - }else{ - /* single bank */ - offset = s->gr[0x09]; - if(addr >= 0x4000){ - ret = 1; // XXX: 光栄製ゲーム用??? - } - } - if ((s->gr[0x0b] & 0x20) != 0) - offset <<= 14; - else - offset <<= 12; - - addr += (offset); - addr &= s->cirrus_addr_mask; - - *addrval = addr; - - return ret; -} - -void cirrus_linear_memwnd_writeb(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd_addr_convert(opaque, &addr); - g_cirrus_linear_write[0](opaque, addr, val); - //cirrus_linear_mem_writeb(opaque, addr, val); - //cirrus_linear_writeb(opaque, addr, val); - }else{ - int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); - if(r==0){ - g_cirrus_linear_write[0](opaque, addr, val); - }else{ - cirrus_mmio_writeb_iodata(opaque, addr, val); - } - } -} - -void cirrus_linear_memwnd_writew(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd_addr_convert(opaque, &addr); - g_cirrus_linear_write[1](opaque, addr, val); - //cirrus_linear_mem_writew(opaque, addr, val); - //cirrus_linear_writew(opaque, addr, val); - }else{ - int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); - if(r==0){ - g_cirrus_linear_write[1](opaque, addr, val); - }else{ - cirrus_mmio_writew_iodata(opaque, addr, val); - } - } -} - -void cirrus_linear_memwnd_writel(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd_addr_convert(opaque, &addr); - g_cirrus_linear_write[2](opaque, addr, val); - //cirrus_linear_mem_writel(opaque, addr, val); - //cirrus_linear_writel(opaque, addr, val); - }else{ - int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); - if(r==0){ - g_cirrus_linear_write[2](opaque, addr, val); - }else{ - cirrus_mmio_writel_iodata(opaque, addr, val); - } - } -} - -uint32_t_ cirrus_linear_memwnd_readb(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd_addr_convert(opaque, &addr); - return cirrus_linear_readb(opaque, addr); - }else{ - int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); - //if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 - if ((cirrusvga_wab_40e1 & 0x02) == 0 ) { - return 0xff; //DRAM REFRESH Mode - }else if(r == 0) { - return cirrus_linear_readb(opaque, addr); - }else{ - return cirrus_mmio_readb_iodata(opaque, addr); - //return cirrus_linear_readb(opaque, addr); - } - } -} - -uint32_t_ cirrus_linear_memwnd_readw(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd_addr_convert(opaque, &addr); - return cirrus_linear_readw(opaque, addr); - }else{ - int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); - //if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 - if ((cirrusvga_wab_40e1 & 0x02) == 0 ) { - return 0xff; //DRAM REFRESH Mode - }else if (r == 0) { - return cirrus_linear_readw(opaque, addr); - }else{ - return cirrus_mmio_readw_iodata(opaque, addr); - //return cirrus_linear_readw(opaque, addr); - } - } -} - -uint32_t_ cirrus_linear_memwnd_readl(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd_addr_convert(opaque, &addr); - return cirrus_linear_readl(opaque, addr); - }else{ - int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); - //if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 - if ((cirrusvga_wab_40e1 & 0x02) == 0 ) { - return 0xff; //DRAM REFRESH Mode - }else if (r == 0) { - return cirrus_linear_readl(opaque, addr); - }else{ - return cirrus_mmio_readl_iodata(opaque, addr); - //return cirrus_linear_readl(opaque, addr); - } - } -} - -/*************************************** - * - * XXX: F00000 memory access ? - * - ***************************************/ - -// XXX: convert F00000 VRAM window address to linear address(どうしたら良いか分からん) -void cirrus_linear_memwnd3_addr_convert(void *opaque, target_phys_addr_t *addrval){ - CirrusVGAState *s = (CirrusVGAState *) opaque; - int offset; - target_phys_addr_t addr = *addrval; - - addr -= np2clvga.VRAMWindowAddr3; - addr &= 0xffff; - if ((s->gr[0x0b] & 0x01) != 0){ - /* dual bank */ - if(addr < 0x8000){ - offset = s->gr[0x09]; - }else{ - addr -= 0x8000; - offset = s->gr[0x0a]; - } - }else{ - /* single bank */ - offset = s->gr[0x09]; - } - if ((s->gr[0x0b] & 0x20) != 0) - offset <<= 14; - else - offset <<= 12; - - addr += (offset); - - addr &= s->cirrus_addr_mask; - *addrval = addr; -} -// I-O DATA用 -int cirrus_linear_memwnd3_addr_convert_iodata(void *opaque, target_phys_addr_t *addrval){ - CirrusVGAState *s = (CirrusVGAState *) opaque; - int offset; - target_phys_addr_t addr = *addrval; - int ret = 0; - - // MMIO判定 - // 本当は... - // SR17[2]=1でMMIOイネーブル If this bit is set to '1', the BlT source will be system memory rather than display memory. - // 本当はそれに加えGR6[3-2]=01じゃないとMMIOモードにならない - // MMIOアドレスはSR17[6]=0:0xb8000に割り当て、1:リニアメモリの最後256byteに割り当て(CL-GD5430/'36/'40 only) - if ((s->sr[0x17] & CIRRUS_MMIO_ENABLE) != 0 /*&& (s->gr[0x06] & 0x0c)==0x04*/ && ((addr & 0xff000) == 0xb8000)) { - ret = 1; // MMIO - } - - addr -= np2clvga.VRAMWindowAddr3; - - if ((s->gr[0x0b] & 0x01) != 0){ - /* dual bank */ - if(addr < 0x8000){ - offset = s->gr[0x09]; - }else{ - addr -= 0x8000; - offset = s->gr[0x0a]; - } - }else{ - /* single bank */ - offset = s->gr[0x09]; - // if(addr >= 0x8000){ - // ret = 1; - // } - } - if ((s->gr[0x0b] & 0x20) != 0) - offset <<= 14; - else - offset <<= 12; - - addr += (offset); - addr &= s->cirrus_addr_mask; - - *addrval = addr; - - return ret; -} - -void cirrus_linear_memwnd3_writeb(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd3_addr_convert(opaque, &addr); - - //cirrus_linear_bitblt_writeb(opaque, addr, val); - g_cirrus_linear_write[0](opaque, addr, val); - //cirrus_linear_mem_writeb(opaque, addr, val); - //cirrus_linear_writeb(opaque, addr, val); - }else{ - int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); - if(r==0){ - g_cirrus_linear_write[0](opaque, addr, val); - }else{ - cirrus_mmio_writeb_iodata(opaque, addr, val); - } - } -} - -void cirrus_linear_memwnd3_writew(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd3_addr_convert(opaque, &addr); - - //cirrus_linear_bitblt_writew(opaque, addr, val); - g_cirrus_linear_write[1](opaque, addr, val); - //cirrus_linear_mem_writew(opaque, addr, val); - //cirrus_linear_writew(opaque, addr, val); - }else{ - int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); - if(r==0){ - g_cirrus_linear_write[1](opaque, addr, val); - }else{ - cirrus_mmio_writew_iodata(opaque, addr, val); - } - } -} - -void cirrus_linear_memwnd3_writel(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd3_addr_convert(opaque, &addr); - - //cirrus_linear_bitblt_writel(opaque, addr, val); - g_cirrus_linear_write[2](opaque, addr, val); - //cirrus_linear_mem_writel(opaque, addr, val); - //cirrus_linear_writel(opaque, addr, val); - }else{ - int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); - if(r==0){ - g_cirrus_linear_write[2](opaque, addr, val); - }else{ - cirrus_mmio_writel_iodata(opaque, addr, val); - } - } -} - -uint32_t_ cirrus_linear_memwnd3_readb(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd3_addr_convert(opaque, &addr); - - return cirrus_linear_readb(opaque, addr); - }else{ - int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); - // if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 - if ((cirrusvga_wab_40e1 & 0x02) == 0 ) { - return 0xff; //DRAM REFRESH Mode - }else if(r == 0) { - return cirrus_linear_readb(opaque, addr); - }else{ - return cirrus_mmio_readb_iodata(opaque, addr); - } - } -} - -uint32_t_ cirrus_linear_memwnd3_readw(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd3_addr_convert(opaque, &addr); - - return cirrus_linear_readw(opaque, addr); - }else{ - int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); - // if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 - if ((cirrusvga_wab_40e1 & 0x02) == 0) { - return 0xffff; //DRAM REFRESH Mode - }else if (r == 0) { - return cirrus_linear_readw(opaque, addr); - }else{ - return cirrus_mmio_readw_iodata(opaque, addr); - } - } -} - -uint32_t_ cirrus_linear_memwnd3_readl(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ - cirrus_linear_memwnd3_addr_convert(opaque, &addr); - - return cirrus_linear_readl(opaque, addr); - }else{ - int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); - // if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 - if ((cirrusvga_wab_40e1 & 0x02) == 0) { - return 0xffffffff; //DRAM REFRESH Mode - }else if (r == 0) { - return cirrus_linear_readl(opaque, addr); - }else{ - return cirrus_mmio_readl_iodata(opaque, addr); - } - } -} - - -/*************************************** - * - * system to screen memory access - * - ***************************************/ - - -uint32_t_ cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - uint32_t_ ret = 0; - - /* handle bitblt */ - if (s->cirrus_srcptr != s->cirrus_srcptr_end) { - ret = *s->cirrus_srcptr; - s->cirrus_srcptr++; - if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { - cirrus_bitblt_videotocpu_next(s); - } - } - return ret; -} - -uint32_t_ cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_linear_bitblt_readb(opaque, addr) << 8; - v |= cirrus_linear_bitblt_readb(opaque, addr + 1); -#else - v = cirrus_linear_bitblt_readb(opaque, addr); - v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8; -#endif - return v; -} - -uint32_t_ cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_linear_bitblt_readb(opaque, addr) << 24; - v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16; - v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8; - v |= cirrus_linear_bitblt_readb(opaque, addr + 3); -#else - v = cirrus_linear_bitblt_readb(opaque, addr); - v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8; - v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16; - v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24; -#endif - return v; -} - -void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - if (s->cirrus_srcptr != s->cirrus_srcptr_end) { - /* bitblt */ - *s->cirrus_srcptr++ = (uint8_t) val; - if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { - cirrus_bitblt_cputovideo_next(s); - } - } -} - -void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff); - cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff); -#else - cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff); - cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff); -#endif -} - -void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff); - cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff); - cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff); - cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff); -#else - cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff); - cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff); - cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff); - cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff); -#endif -} - - -static CPUReadMemoryFunc *cirrus_linear_bitblt_read[3] = { - cirrus_linear_bitblt_readb, - cirrus_linear_bitblt_readw, - cirrus_linear_bitblt_readl, -}; - -static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = { - cirrus_linear_bitblt_writeb, - cirrus_linear_bitblt_writew, - cirrus_linear_bitblt_writel, -}; - -static void map_linear_vram(CirrusVGAState *s) -{ - g_cirrus_linear_map_enabled = 1; - - vga_dirty_log_stop((VGAState *)s); - - if (!s->map_addr && s->lfb_addr && s->lfb_end) { - s->map_addr = s->lfb_addr; - s->map_end = s->lfb_end; - cpu_register_physical_memory(s->map_addr, s->map_end - s->map_addr, s->vram_offset); - } - - if (!s->map_addr) - return; - - s->lfb_vram_mapped = 0; - - // このcpu_register_physical_memoryの詳細がさっぱり分からない・・・ - cpu_register_physical_memory(isa_mem_base + 0xF80000, 0x8000, - (s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_UNASSIGNED); - cpu_register_physical_memory(isa_mem_base + 0xF88000, 0x8000, - (s->vram_offset + s->cirrus_bank_base[1]) | IO_MEM_UNASSIGNED); - if (!(s->cirrus_srcptr != s->cirrus_srcptr_end) - && !((s->sr[0x07] & 0x01) == 0) - && !((s->gr[0x0B] & 0x14) == 0x14) - && !(s->gr[0x0B] & 0x02)) { - - vga_dirty_log_stop((VGAState *)s); - // ここも - cpu_register_physical_memory(isa_mem_base + 0xF80000, 0x8000, - (s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM); - cpu_register_physical_memory(isa_mem_base + 0xF88000, 0x8000, - (s->vram_offset + s->cirrus_bank_base[1]) | IO_MEM_RAM); - - s->lfb_vram_mapped = 1; - } - else { - cpu_register_physical_memory(isa_mem_base + 0xF80000, 0x20000, - s->vga_io_memory); - } - - vga_dirty_log_start((VGAState *)s); -} - -static void unmap_linear_vram(CirrusVGAState *s) -{ - g_cirrus_linear_map_enabled = 0; - - vga_dirty_log_stop((VGAState *)s); - - if (s->map_addr && s->lfb_addr && s->lfb_end) - s->map_addr = s->map_end = 0; - - // ここも - cpu_register_physical_memory(isa_mem_base + 0xF80000, 0x20000, - s->vga_io_memory); - - vga_dirty_log_start((VGAState *)s); -} - -/* Compute the memory access functions */ -static void cirrus_update_memory_access(CirrusVGAState *s) -{ - unsigned mode; - - // メモリ割り付けアドレス更新 - - // inear address - // sr7[7-4]<>0:sr7[7-4]をaddress23-20に割り当て、ただしgrb[5]=1の時sr7[4]はd.c. - // sr7[7-4] =0:gr6[3-2]=00,01:A0000に割り当て 10,11:B0000に割り当て - // WSNは42e1hがかかわっているかも????? - - if (np2clvga.gd54xxtype > 0xff && (cirrusvga_wab_42e1 & 0x18) == 0x18){ - np2clvga.VRAMWindowAddr3 = 0xf00000; - } - else if ( -#if defined(SUPPORT_VGA_MODEX) - !np2clvga.modex && -#endif - (s->sr[0x07] & CIRRUS_SR7_ISAADDR_MASK) != 0) { - np2clvga.VRAMWindowAddr3 = (s->sr[0x07] & CIRRUS_SR7_ISAADDR_MASK & ~((s->gr[0x0b] >> 1) & 0x10)) << 16; - } - else { -#if defined(SUPPORT_VGA_MODEX) - if(np2clvga.modex){ - if (s->gr[0x06] & 0x08) { - np2clvga.VRAMWindowAddr3 = 0xb0000; - } - else { - np2clvga.VRAMWindowAddr3 = 0xa0000; - } - }else -#endif - { - // アクセス不可にしておく - np2clvga.VRAMWindowAddr3 = 0; - } - } - - if ((s->sr[0x17] & 0x44) == 0x44) { - goto generic_io; - } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { - goto generic_io; - } else { - if ((s->gr[0x0B] & 0x14) == 0x14) { - goto generic_io; - } else if (s->gr[0x0B] & 0x02) { - goto generic_io; - } - - mode = s->gr[0x05] & 0x7; - if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { - map_linear_vram(s); - g_cirrus_linear_write[0] = cirrus_linear_mem_writeb; - g_cirrus_linear_write[1] = cirrus_linear_mem_writew; - g_cirrus_linear_write[2] = cirrus_linear_mem_writel; - } else { - generic_io: - unmap_linear_vram(s); - g_cirrus_linear_write[0] = cirrus_linear_writeb; - g_cirrus_linear_write[1] = cirrus_linear_writew; - g_cirrus_linear_write[2] = cirrus_linear_writel; - } - } - cirrus_linear_mmio_update(s); -} - - -/* I/O ports */ -// PC-98用I/Oポート -> CL-GD54xxネイティブポート変換 -uint32_t_ vga_convert_ioport(uint32_t_ addr){ -#if defined(SUPPORT_PCI) - // PCI版はポート番号そのまま - if(pcidev.enable && - (np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI)){ - if((addr & 0xFF0) == 0x3C0 || (addr & 0xFF0) == 0x3B0 || (addr & 0xFF0) == 0x3D0){ - np2clvga.gd54xxtype = CIRRUS_98ID_PCI; - cirrusvga->sr[0x1F] = 0x2d; // MemClock - cirrusvga->gr[0x18] = 0x0f; // fastest memory configuration - cirrusvga->sr[0x0f] = CIRRUS_MEMSIZE_2M; - cirrusvga->sr[0x17] = 0x20; - cirrusvga->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ - cirrusvga->device_id = CIRRUS_ID_CLGD5446; - cirrusvga->cr[0x27] = cirrusvga->device_id; - cirrusvga->bustype = CIRRUS_BUSTYPE_PCI; -#if defined(SUPPORT_IA32_HAXM) - i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); - i386hax_vm_removememoryarea(vramptr, np2clvga.pciLFB_Addr, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); - lastlinmmio = 0; -#endif - cirrus_update_memory_access(cirrusvga); - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - } - } -#endif - if(np2clvga.gd54xxtype <= 0xff){ - // 内蔵・純正ボード用 - if((addr & 0xFF0) == 0xCA0 || (addr & 0xFF0) == 0xC50){ - addr = 0x3C0 | (addr & 0xf); - }else{ - if(addr==0xBA4 || addr==0xB54) addr = 0x3B4; - if(addr==0xBA5 || addr==0xB55) addr = 0x3B5; - if(addr==0xDA4 || addr==0xD54) addr = 0x3D4; - if(addr==0xDA5 || addr==0xD55) addr = 0x3D5; - if(addr==0xBAA || addr==0xB5A) addr = 0x3BA; - if(addr==0xDAA || addr==0xD5A) addr = 0x3DA; - } - }else{ - // WAB用 - if((addr & 0xF0FF) == (0x40E0 | cirrusvga_melcowab_ofs)){ - addr = 0x3C0 | ((addr >> 8) & 0xf); - }else{ - //if(addr==0x51E1+cirrusvga_melcowab_ofs) addr = 0x3B4; // ??? - //if(addr==0x57E1+cirrusvga_melcowab_ofs) addr = 0x3B5; // ??? - //if(addr==0x54E0+cirrusvga_melcowab_ofs) addr = 0x3D4; - //if(addr==0x55E0+cirrusvga_melcowab_ofs) addr = 0x3D5; - //if(addr==0x5BE1+cirrusvga_melcowab_ofs) addr = 0x3BA; // ??? - //if(addr==0x5AE0+cirrusvga_melcowab_ofs) addr = 0x3DA; - if (addr == 0x58E0 + cirrusvga_melcowab_ofs) addr = 0x3B4; - if (addr == 0x59E0 + cirrusvga_melcowab_ofs) addr = 0x3B5; - ////if (addr == 0x3AE0 + cirrusvga_melcowab_ofs) addr = 0x3BA; - if (addr == 0x54E0 + cirrusvga_melcowab_ofs) addr = 0x3D4; - if (addr == 0x55E0 + cirrusvga_melcowab_ofs) addr = 0x3D5; - if (addr == 0x5AE0 + cirrusvga_melcowab_ofs) addr = 0x3DA; - } - } - return addr; -} - -static uint32_t_ vga_ioport_read(void *opaque, uint32_t_ addr) -{ - CirrusVGAState *s = (CirrusVGAState *)opaque; - int val, index; - - // ポート決め打ちなので無理矢理変換 - addr = vga_convert_ioport(addr); - - //TRACEOUT(("CIRRUS VGA: read %04X", addr)); - - /* check port range access depending on color/monochrome mode */ - if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) - || (addr >= 0x3d0 && addr <= 0x3df - && !(s->msr & MSR_COLOR_EMULATION))) { - val = 0xff; - } else { - switch (addr) { - case 0x3c0: - if (s->ar_flip_flop == 0) { - val = s->ar_index; - } else { - val = 0; - } - break; - case 0x3c1: - index = s->ar_index & 0x1f; - if (index < 21) - val = s->ar[index]; - else - val = 0; - break; - case 0x3c2: - val = s->st00; - break; - case 0x3c4: - val = s->sr_index; - break; - case 0x3c5: - if (cirrus_hook_read_sr(s, s->sr_index, &val)) - break; - val = s->sr[s->sr_index]; -#ifdef DEBUG_VGA_REG - printf("vga: read SR%x = 0x%02x\n", s->sr_index, val); -#endif - break; - case 0x3c6: - cirrus_read_hidden_dac(s, &val); - break; - case 0x3c7: - val = s->dac_state; - break; - case 0x3c8: - val = s->dac_write_index; - s->cirrus_hidden_dac_lockindex = 0; - break; - case 0x3c9: - if (cirrus_hook_read_palette(s, &val)) - break; - val = s->palette[s->dac_read_index * 3 + s->dac_sub_index]; - if (++s->dac_sub_index == 3) { - s->dac_sub_index = 0; - s->dac_read_index++; - } - break; - case 0x3ca: - val = s->fcr; - break; - case 0x3cc: - val = s->msr; - break; - case 0x3ce: - val = s->gr_index; - break; - case 0x3cf: - if (cirrus_hook_read_gr(s, s->gr_index, &val)) - break; - val = s->gr[s->gr_index]; -#ifdef DEBUG_VGA_REG - printf("vga: read GR%x = 0x%02x\n", s->gr_index, val); -#endif - break; - case 0x3b4: - case 0x3d4: - val = s->cr_index; - break; - case 0x3b5: - case 0x3d5: - if (cirrus_hook_read_cr(s, s->cr_index, &val)) - break; - val = s->cr[s->cr_index]; -#ifdef DEBUG_VGA_REG - printf("vga: read CR%x = 0x%02x\n", s->cr_index, val); -#endif - break; - case 0x3ba: - case 0x3da: - /* just toggle to fool polling */ - val = s->st01 = s->retrace((VGAState *) s); - //if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ - // val = 0xC2; - //} - //if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ - // val = 0xc7; - //} - s->ar_flip_flop = 0; - break; - default: - val = 0x00; - break; - } - } -#if defined(TRACE) - //TRACEOUT(("VGA: read addr=0x%04x data=0x%02x\n", addr, val)); -#endif - return val; -} -static REG8 IOOUTCALL vga_ioport_read_wrap(UINT addr) -{ - return vga_ioport_read(cirrusvga, addr); -} -UINT IOOUTCALL cirrusvga_ioport_read_wrap16(UINT addr) -{ - UINT16 ret; - addr = vga_convert_ioport(addr); - ret = ((REG16)vga_ioport_read(cirrusvga, addr ) ); - ret |= ((REG16)vga_ioport_read(cirrusvga, addr+1) << 8); - return ret; -} -UINT IOOUTCALL cirrusvga_ioport_read_wrap32(UINT addr) -{ - UINT32 ret; - addr = vga_convert_ioport(addr); - ret = ((UINT32)vga_ioport_read(cirrusvga, addr ) ); - ret |= ((UINT32)vga_ioport_read(cirrusvga, addr+1) << 8); - ret |= ((UINT32)vga_ioport_read(cirrusvga, addr+2) << 16); - ret |= ((UINT32)vga_ioport_read(cirrusvga, addr+3) << 24); - return ret; -} - -static void vga_ioport_write(void *opaque, uint32_t_ addr, uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *)opaque; - int index; - - // ポート決め打ちなので無理矢理変換 - addr = vga_convert_ioport(addr); - - //TRACEOUT(("CIRRUS VGA: write %04X %02X", addr, val)); - - /* check port range access depending on color/monochrome mode */ - if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) - || (addr >= 0x3d0 && addr <= 0x3df - && !(s->msr & MSR_COLOR_EMULATION))) - return; - -#ifdef TRACE - //TRACEOUT(("VGA: write addr=0x%04x data=0x%02x\n", addr, val)); -#endif - - switch (addr) { - case 0x3c0: - if (s->ar_flip_flop == 0) { - val &= 0x3f; - s->ar_index = val; - } else { - index = s->ar_index & 0x1f; - switch (index) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - s->ar[index] = val & 0x3f; - break; - case 0x10: - s->ar[index] = val & ~0x10; - break; - case 0x11: - s->ar[index] = val; - break; - case 0x12: - s->ar[index] = val & ~0xc0; - break; - case 0x13: - s->ar[index] = val & ~0xf0; - break; - case 0x14: - s->ar[index] = val & ~0xf0; - break; - default: - break; - } - } - s->ar_flip_flop ^= 1; - break; - case 0x3c2: - s->msr = val & ~0x10; - s->update_retrace_info((VGAState *) s); - break; - case 0x3c4: - s->sr_index = val; - break; - case 0x3c5: - if (cirrus_hook_write_sr(s, s->sr_index, val)) - break; -#ifdef DEBUG_VGA_REG - printf("vga: write SR%x = 0x%02x\n", s->sr_index, val); -#endif - s->sr[s->sr_index] = val & sr_mask[s->sr_index]; - if (s->sr_index == 1) s->update_retrace_info((VGAState *) s); - break; - case 0x3c6: - cirrus_write_hidden_dac(s, val); - break; - case 0x3c7: - s->dac_read_index = val; - s->dac_sub_index = 0; - s->dac_state = 3; - break; - case 0x3c8: - s->dac_write_index = val; - s->dac_sub_index = 0; - s->dac_state = 0; - break; - case 0x3c9: - if (cirrus_hook_write_palette(s, val)) - break; - s->dac_cache[s->dac_sub_index] = val; - if (++s->dac_sub_index == 3) { - memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3); - s->dac_sub_index = 0; - s->dac_write_index++; - np2wab.paletteChanged = 1; // パレット変えました - cirrusvga_updated = 1; - } - break; - //case 0x3cc: - // s->msr = val; - // break; - case 0x3ce: - s->gr_index = val; - break; - case 0x3cf: - if (cirrus_hook_write_gr(s, s->gr_index, val)) - break; -#ifdef DEBUG_VGA_REG - printf("vga: write GR%x = 0x%02x\n", s->gr_index, val); -#endif - s->gr[s->gr_index] = val & gr_mask[s->gr_index]; - break; - case 0x3b4: - case 0x3d4: - s->cr_index = val; - break; - case 0x3b5: - case 0x3d5: - if (cirrus_hook_write_cr(s, s->cr_index, val)) - { - cirrusvga_updated = 1; - break; - } -#ifdef DEBUG_VGA_REG - printf("vga: write CR%x = 0x%02x\n", s->cr_index, val); -#endif - /* handle CR0-7 protection */ - if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) { - /* can always write bit 4 of CR7 */ - if (s->cr_index == 7) - s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); - cirrusvga_updated = 1; - return; - } - switch (s->cr_index) { - case 0x01: /* horizontal display end */ - case 0x07: - case 0x09: - case 0x0c: - case 0x0d: - case 0x12: /* vertical display end */ - s->cr[s->cr_index] = val; - break; - - default: - s->cr[s->cr_index] = val; - break; - } - - switch(s->cr_index) { - case 0x00: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x11: - case 0x17: - s->update_retrace_info((VGAState *) s); - break; - } - //if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ - // int width, height; - // cirrus_get_resolution((VGAState *) s, &width, &height); - // switch(s->cr_index) { - // case 0x04: - // if(width==640) - // np2wab.shiftX = val - 0x54; - // else if(width==800) - // np2wab.shiftX = val - 0x69; - // else if(width==1024) - // np2wab.shiftX = val - 0x85; - // else - // np2wab.shiftX = 0; - // break; - // case 0x10: - // if(width==640) - // np2wab.shiftX = val - 0xEA; - // else if(width==800) - // np2wab.shiftX = val - 0x5D; - // else if(width==1024) - // np2wab.shiftX = val - 0x68; - // else - // np2wab.shiftX = 0; - // break; - // } - //} - cirrusvga_updated = 1; - break; - case 0x3ba: - case 0x3da: - s->fcr = val & 0x10; - break; - } -} -static void IOOUTCALL vga_ioport_write_wrap(UINT addr, REG8 dat) -{ - vga_ioport_write(cirrusvga, addr, dat); -} -void IOOUTCALL cirrusvga_ioport_write_wrap16(UINT addr, UINT dat) -{ - addr = vga_convert_ioport(addr); - vga_ioport_write(cirrusvga, addr , ((UINT32)dat ) & 0xff); - vga_ioport_write(cirrusvga, addr+1, ((UINT32)dat >> 8) & 0xff); -} -void IOOUTCALL cirrusvga_ioport_write_wrap32(UINT addr, UINT dat) -{ - addr = vga_convert_ioport(addr); - vga_ioport_write(cirrusvga, addr , (dat ) & 0xff); - vga_ioport_write(cirrusvga, addr+1, (dat >> 8) & 0xff); - vga_ioport_write(cirrusvga, addr+2, (dat >> 16) & 0xff); - vga_ioport_write(cirrusvga, addr+3, (dat >> 24) & 0xff); -} - -/*************************************** - * - * memory-mapped I/O access - * - ***************************************/ - -uint32_t_ cirrus_mmio_readb(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - addr &= CIRRUS_PNPMMIO_SIZE - 1; - - if (addr >= 0x100) { - return cirrus_mmio_blt_read(s, addr - 0x100); - } else { - return vga_ioport_read(s, addr + 0x3c0); - } -} - -uint32_t_ cirrus_mmio_readw(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_mmio_readb(opaque, addr) << 8; - v |= cirrus_mmio_readb(opaque, addr + 1); -#else - v = cirrus_mmio_readb(opaque, addr); - v |= cirrus_mmio_readb(opaque, addr + 1) << 8; -#endif - return v; -} - -uint32_t_ cirrus_mmio_readl(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_mmio_readb(opaque, addr) << 24; - v |= cirrus_mmio_readb(opaque, addr + 1) << 16; - v |= cirrus_mmio_readb(opaque, addr + 2) << 8; - v |= cirrus_mmio_readb(opaque, addr + 3); -#else - v = cirrus_mmio_readb(opaque, addr); - v |= cirrus_mmio_readb(opaque, addr + 1) << 8; - v |= cirrus_mmio_readb(opaque, addr + 2) << 16; - v |= cirrus_mmio_readb(opaque, addr + 3) << 24; -#endif - return v; -} - -void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - addr &= CIRRUS_PNPMMIO_SIZE - 1; - - if (addr >= 0x100) { - cirrus_mmio_blt_write(s, addr - 0x100, val); - } else { - vga_ioport_write(s, addr + 0x3c0, val); - } -} - -void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff); - cirrus_mmio_writeb(opaque, addr + 1, val & 0xff); -#else - cirrus_mmio_writeb(opaque, addr, val & 0xff); - cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff); -#endif -} - -void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff); - cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff); - cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff); - cirrus_mmio_writeb(opaque, addr + 3, val & 0xff); -#else - cirrus_mmio_writeb(opaque, addr, val & 0xff); - cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff); - cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff); - cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff); -#endif -} - -uint32_t_ cirrus_mmio_readb_wab(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - addr &= ~np2clvga.pciMMIO_Mask; - if (addr >= 0x8000) { - return cirrus_mmio_blt_read(s, (addr - 0x8000) & 0x7fff); - } else { - return vga_ioport_read(s, addr & 0x7fff); - } -} - -uint32_t_ cirrus_mmio_readw_wab(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_mmio_readb_wab(opaque, addr) << 8; - v |= cirrus_mmio_readb_wab(opaque, addr + 1); -#else - v = cirrus_mmio_readb_wab(opaque, addr); - v |= cirrus_mmio_readb_wab(opaque, addr + 1) << 8; -#endif - return v; -} - -uint32_t_ cirrus_mmio_readl_wab(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_mmio_readb_wab(opaque, addr) << 24; - v |= cirrus_mmio_readb_wab(opaque, addr + 1) << 16; - v |= cirrus_mmio_readb_wab(opaque, addr + 2) << 8; - v |= cirrus_mmio_readb_wab(opaque, addr + 3); -#else - v = cirrus_mmio_readb_wab(opaque, addr); - v |= cirrus_mmio_readb_wab(opaque, addr + 1) << 8; - v |= cirrus_mmio_readb_wab(opaque, addr + 2) << 16; - v |= cirrus_mmio_readb_wab(opaque, addr + 3) << 24; -#endif - return v; -} - -void cirrus_mmio_writeb_wab(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - addr &= ~np2clvga.pciMMIO_Mask; - if (addr >= 0x8000) { - //addr = (addr - 0x8000) & 0x7fff; - cirrus_mmio_blt_write(s, (addr - 0x8000) & 0x7fff, val); - } else { - //addr = addr & 0x7fff; - //if(addr > CIRRUS_PNPMMIO_SIZE) return; - vga_ioport_write(s, addr & 0x7fff, val); - } -} - -void cirrus_mmio_writew_wab(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_mmio_writeb_wab(opaque, addr, (val >> 8) & 0xff); - cirrus_mmio_writeb_wab(opaque, addr + 1, val & 0xff); -#else - cirrus_mmio_writeb_wab(opaque, addr, val & 0xff); - cirrus_mmio_writeb_wab(opaque, addr + 1, (val >> 8) & 0xff); -#endif -} - -void cirrus_mmio_writel_wab(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_mmio_writeb_wab(opaque, addr, (val >> 24) & 0xff); - cirrus_mmio_writeb_wab(opaque, addr + 1, (val >> 16) & 0xff); - cirrus_mmio_writeb_wab(opaque, addr + 2, (val >> 8) & 0xff); - cirrus_mmio_writeb_wab(opaque, addr + 3, val & 0xff); -#else - cirrus_mmio_writeb_wab(opaque, addr, val & 0xff); - cirrus_mmio_writeb_wab(opaque, addr + 1, (val >> 8) & 0xff); - cirrus_mmio_writeb_wab(opaque, addr + 2, (val >> 16) & 0xff); - cirrus_mmio_writeb_wab(opaque, addr + 3, (val >> 24) & 0xff); -#endif -} - -uint32_t_ cirrus_mmio_readb_iodata(void *opaque, target_phys_addr_t addr) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - addr &= ~np2clvga.pciMMIO_Mask; - addr = (addr - 0x8000) & 0x7fff; - return cirrus_mmio_blt_read(s, (addr/* - 0x8000*/) & (CIRRUS_PNPMMIO_SIZE-1)); -} - -uint32_t_ cirrus_mmio_readw_iodata(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_mmio_readb_iodata(opaque, addr) << 8; - v |= cirrus_mmio_readb_iodata(opaque, addr + 1); -#else - v = cirrus_mmio_readb_iodata(opaque, addr); - v |= cirrus_mmio_readb_iodata(opaque, addr + 1) << 8; -#endif - return v; -} - -uint32_t_ cirrus_mmio_readl_iodata(void *opaque, target_phys_addr_t addr) -{ - uint32_t_ v; -#ifdef TARGET_WORDS_BIGENDIAN - v = cirrus_mmio_readb_iodata(opaque, addr) << 24; - v |= cirrus_mmio_readb_iodata(opaque, addr + 1) << 16; - v |= cirrus_mmio_readb_iodata(opaque, addr + 2) << 8; - v |= cirrus_mmio_readb_iodata(opaque, addr + 3); -#else - v = cirrus_mmio_readb_iodata(opaque, addr); - v |= cirrus_mmio_readb_iodata(opaque, addr + 1) << 8; - v |= cirrus_mmio_readb_iodata(opaque, addr + 2) << 16; - v |= cirrus_mmio_readb_iodata(opaque, addr + 3) << 24; -#endif - return v; -} - -void cirrus_mmio_writeb_iodata(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ - CirrusVGAState *s = (CirrusVGAState *) opaque; - - addr &= ~np2clvga.pciMMIO_Mask; - if ((s->gr[0x31] & CIRRUS_BLT_BUSY)==0) { - addr = (addr - 0x8000) & 0x7fff; - cirrus_mmio_blt_write(s, (addr/* - 0x8000*/) & (CIRRUS_PNPMMIO_SIZE-1), val); - } - /*}*/ - // } else { - ////addr = addr & 0x7fff; - ////if(addr > CIRRUS_PNPMMIO_SIZE) return; - // //vga_ioport_write(s, addr & 0x7fff, val); - // } -} - -void cirrus_mmio_writew_iodata(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_mmio_writeb_iodata(opaque, addr, (val >> 8) & 0xff); - cirrus_mmio_writeb_iodata(opaque, addr + 1, val & 0xff); -#else - cirrus_mmio_writeb_iodata(opaque, addr, val & 0xff); - cirrus_mmio_writeb_iodata(opaque, addr + 1, (val >> 8) & 0xff); -#endif -} - -void cirrus_mmio_writel_iodata(void *opaque, target_phys_addr_t addr, - uint32_t_ val) -{ -#ifdef TARGET_WORDS_BIGENDIAN - cirrus_mmio_writeb_iodata(opaque, addr, (val >> 24) & 0xff); - cirrus_mmio_writeb_iodata(opaque, addr + 1, (val >> 16) & 0xff); - cirrus_mmio_writeb_iodata(opaque, addr + 2, (val >> 8) & 0xff); - cirrus_mmio_writeb_iodata(opaque, addr + 3, val & 0xff); -#else - cirrus_mmio_writeb_iodata(opaque, addr, val & 0xff); - cirrus_mmio_writeb_iodata(opaque, addr + 1, (val >> 8) & 0xff); - cirrus_mmio_writeb_iodata(opaque, addr + 2, (val >> 16) & 0xff); - cirrus_mmio_writeb_iodata(opaque, addr + 3, (val >> 24) & 0xff); -#endif -} - - -CPUReadMemoryFunc *cirrus_mmio_read[3] = { - cirrus_mmio_readb, - cirrus_mmio_readw, - cirrus_mmio_readl, -}; - -CPUWriteMemoryFunc *cirrus_mmio_write[3] = { - cirrus_mmio_writeb, - cirrus_mmio_writew, - cirrus_mmio_writel, -}; - -#define array_write(ary, pos, data, len) \ - memcpy(ary+pos, data, len); \ - pos += len; - -#define array_read(ary, pos, data, len) \ - memcpy(data, ary+pos, len); \ - pos += len; - - -/* load/save state */ -void pc98_cirrus_vga_save() -{ - CirrusVGAState *s = cirrusvga; - int pos = 0; - UINT8 *f = cirrusvga_statsavebuf; - //char test[500] = {0}; - uint32_t_ state_ver = 6; - uint32_t_ intbuf; - char en[3] = "en"; - - array_write(f, pos, &state_ver, sizeof(state_ver)); // ステートセーブ バージョン番号 - - if(vramptr == NULL || s == NULL) { - strcpy(en, "di"); - array_write(f, pos, en, 2); - return; - } - array_write(f, pos, en, 2); - - // この際全部保存 - array_write(f, pos, vramptr, CIRRUS_VRAM_SIZE); - array_write(f, pos, &s->vram_offset, sizeof(s->vram_offset)); - array_write(f, pos, &s->vram_size, sizeof(s->vram_size)); - array_write(f, pos, &s->lfb_addr, sizeof(s->lfb_addr)); - array_write(f, pos, &s->lfb_end, sizeof(s->lfb_end)); - array_write(f, pos, &s->map_addr, sizeof(s->map_addr)); - array_write(f, pos, &s->map_end, sizeof(s->map_end)); - array_write(f, pos, &s->lfb_vram_mapped, sizeof(s->lfb_vram_mapped)); - array_write(f, pos, &s->bios_offset, sizeof(s->bios_offset)); - array_write(f, pos, &s->bios_size, sizeof(s->bios_size)); - array_write(f, pos, &s->it_shift, sizeof(s->it_shift)); - - array_write(f, pos, &s->latch, sizeof(s->latch)); - array_write(f, pos, &s->sr_index, sizeof(s->sr_index)); - array_write(f, pos, s->sr, sizeof(s->sr)); - array_write(f, pos, &s->gr_index, sizeof(s->gr_index)); - array_write(f, pos, s->gr, sizeof(s->gr)); - array_write(f, pos, &s->ar_index, sizeof(s->ar_index)); - array_write(f, pos, s->ar, sizeof(s->ar)); - array_write(f, pos, &s->ar_flip_flop, sizeof(s->ar_flip_flop)); - array_write(f, pos, &s->cr_index, sizeof(s->cr_index)); - array_write(f, pos, s->cr, sizeof(s->cr)); - array_write(f, pos, &s->msr, sizeof(s->msr)); - array_write(f, pos, &s->fcr, sizeof(s->fcr)); - array_write(f, pos, &s->st00, sizeof(s->st00)); - array_write(f, pos, &s->st01, sizeof(s->st01)); - array_write(f, pos, &s->dac_state, sizeof(s->dac_state)); - array_write(f, pos, &s->dac_sub_index, sizeof(s->dac_sub_index)); - array_write(f, pos, &s->dac_read_index, sizeof(s->dac_read_index)); - array_write(f, pos, &s->dac_write_index, sizeof(s->dac_write_index)); - array_write(f, pos, s->dac_cache, sizeof(s->dac_cache)); - array_write(f, pos, &s->dac_8bit, sizeof(s->dac_8bit)); - array_write(f, pos, s->palette, sizeof(s->palette)); - array_write(f, pos, &s->bank_offset, sizeof(s->bank_offset)); - array_write(f, pos, &s->vga_io_memory, sizeof(s->vga_io_memory)); - array_write(f, pos, &s->vbe_index, sizeof(s->vbe_index)); - array_write(f, pos, s->vbe_regs, sizeof(s->vbe_regs)); - array_write(f, pos, &s->vbe_start_addr, sizeof(s->vbe_start_addr)); - array_write(f, pos, &s->vbe_line_offset, sizeof(s->vbe_line_offset)); - array_write(f, pos, &s->vbe_bank_mask, sizeof(s->vbe_bank_mask)); - - array_write(f, pos, s->font_offsets, sizeof(s->font_offsets)); - array_write(f, pos, &s->graphic_mode, sizeof(s->graphic_mode)); - array_write(f, pos, &s->shift_control, sizeof(s->shift_control)); - array_write(f, pos, &s->double_scan, sizeof(s->double_scan)); - array_write(f, pos, &s->line_offset, sizeof(s->line_offset)); - array_write(f, pos, &s->line_compare, sizeof(s->line_compare)); - array_write(f, pos, &s->start_addr, sizeof(s->start_addr)); - array_write(f, pos, &s->plane_updated, sizeof(s->plane_updated)); - array_write(f, pos, &s->last_line_offset, sizeof(s->last_line_offset)); - array_write(f, pos, &s->last_cw, sizeof(s->last_cw)); - array_write(f, pos, &s->last_ch, sizeof(s->last_ch)); - array_write(f, pos, &s->last_width, sizeof(s->last_width)); - array_write(f, pos, &s->last_height, sizeof(s->last_height)); - array_write(f, pos, &s->last_scr_width, sizeof(s->last_scr_width)); - array_write(f, pos, &s->last_scr_height, sizeof(s->last_scr_height)); - array_write(f, pos, &s->last_depth, sizeof(s->last_depth)); - array_write(f, pos, &s->cursor_start, sizeof(s->cursor_start)); - array_write(f, pos, &s->cursor_end, sizeof(s->cursor_end)); - array_write(f, pos, &s->cursor_offset, sizeof(s->cursor_offset)); - - array_write(f, pos, s->invalidated_y_table, sizeof(s->invalidated_y_table)); - array_write(f, pos, s->last_palette, sizeof(s->last_palette)); - array_write(f, pos, s->last_ch_attr, sizeof(s->last_ch_attr)); - - array_write(f, pos, &s->cirrus_linear_io_addr, sizeof(s->cirrus_linear_io_addr)); - array_write(f, pos, &s->cirrus_linear_bitblt_io_addr, sizeof(s->cirrus_linear_bitblt_io_addr)); - array_write(f, pos, &s->cirrus_mmio_io_addr, sizeof(s->cirrus_mmio_io_addr)); - array_write(f, pos, &s->cirrus_addr_mask, sizeof(s->cirrus_addr_mask)); - array_write(f, pos, &s->linear_mmio_mask, sizeof(s->linear_mmio_mask)); - array_write(f, pos, &s->cirrus_shadow_gr0, sizeof(s->cirrus_shadow_gr0)); - array_write(f, pos, &s->cirrus_shadow_gr1, sizeof(s->cirrus_shadow_gr1)); - array_write(f, pos, &s->cirrus_hidden_dac_lockindex, sizeof(s->cirrus_hidden_dac_lockindex)); - array_write(f, pos, &s->cirrus_hidden_dac_data, sizeof(s->cirrus_hidden_dac_data)); - array_write(f, pos, s->cirrus_bank_base, sizeof(s->cirrus_bank_base)); - array_write(f, pos, s->cirrus_bank_limit, sizeof(s->cirrus_bank_limit)); - array_write(f, pos, s->cirrus_hidden_palette, sizeof(s->cirrus_hidden_palette)); - array_write(f, pos, &s->hw_cursor_x, sizeof(s->hw_cursor_x)); - array_write(f, pos, &s->hw_cursor_y, sizeof(s->hw_cursor_y)); - array_write(f, pos, &s->cirrus_blt_pixelwidth, sizeof(s->cirrus_blt_pixelwidth)); - array_write(f, pos, &s->cirrus_blt_width, sizeof(s->cirrus_blt_width)); - array_write(f, pos, &s->cirrus_blt_height, sizeof(s->cirrus_blt_height)); - array_write(f, pos, &s->cirrus_blt_dstpitch, sizeof(s->cirrus_blt_dstpitch)); - array_write(f, pos, &s->cirrus_blt_srcpitch, sizeof(s->cirrus_blt_srcpitch)); - array_write(f, pos, &s->cirrus_blt_fgcol, sizeof(s->cirrus_blt_fgcol)); - array_write(f, pos, &s->cirrus_blt_bgcol, sizeof(s->cirrus_blt_bgcol)); - array_write(f, pos, &s->cirrus_blt_dstaddr, sizeof(s->cirrus_blt_dstaddr)); - array_write(f, pos, &s->cirrus_blt_srcaddr, sizeof(s->cirrus_blt_srcaddr)); - array_write(f, pos, &s->cirrus_blt_mode, sizeof(s->cirrus_blt_mode)); - array_write(f, pos, &s->cirrus_blt_modeext, sizeof(s->cirrus_blt_modeext)); - array_write(f, pos, s->cirrus_bltbuf, sizeof(s->cirrus_bltbuf)); - intbuf = (UINT32)(s->cirrus_srcptr - s->cirrus_bltbuf); - array_write(f, pos, &intbuf, sizeof(intbuf)); - intbuf = (UINT32)(s->cirrus_srcptr_end - s->cirrus_bltbuf); - array_write(f, pos, &intbuf, sizeof(intbuf)); - array_write(f, pos, &s->cirrus_srccounter, sizeof(s->cirrus_srccounter)); - array_write(f, pos, &s->last_hw_cursor_size, sizeof(s->last_hw_cursor_size)); - array_write(f, pos, &s->last_hw_cursor_x, sizeof(s->last_hw_cursor_x)); - array_write(f, pos, &s->last_hw_cursor_y, sizeof(s->last_hw_cursor_y)); - array_write(f, pos, &s->last_hw_cursor_y_start, sizeof(s->last_hw_cursor_y_start)); - array_write(f, pos, &s->last_hw_cursor_y_end, sizeof(s->last_hw_cursor_y_end)); - array_write(f, pos, &s->real_vram_size, sizeof(s->real_vram_size)); - array_write(f, pos, &s->device_id, sizeof(s->device_id)); - array_write(f, pos, &s->bustype, sizeof(s->bustype)); - - array_write(f, pos, &np2clvga.VRAMWindowAddr3, sizeof(np2clvga.VRAMWindowAddr3)); - - array_write(f, pos, &s->videowindow_dblbuf_index, sizeof(s->videowindow_dblbuf_index)); - array_write(f, pos, &s->graphics_dblbuf_index, sizeof(s->graphics_dblbuf_index)); - - array_write(f, pos, &cirrusvga_wab_59e1, sizeof(cirrusvga_wab_59e1)) - array_write(f, pos, &cirrusvga_wab_51e1, sizeof(cirrusvga_wab_51e1)); - array_write(f, pos, &cirrusvga_wab_5be1, sizeof(cirrusvga_wab_5be1)); - array_write(f, pos, &cirrusvga_wab_40e1, sizeof(cirrusvga_wab_40e1)); - array_write(f, pos, &cirrusvga_wab_46e8, sizeof(cirrusvga_wab_46e8)); - - array_write(f, pos, &cirrusvga_melcowab_ofs, sizeof(cirrusvga_melcowab_ofs)); - - array_write(f, pos, &cirrusvga_wab_42e1, sizeof(cirrusvga_wab_42e1)); - - TRACEOUT(("CIRRUS VGA datalen=%d, (max %d bytes)", pos, sizeof(cirrusvga_statsavebuf))); -#if defined(_WIN32) - // テスト用 - if(pos > sizeof(cirrusvga_statsavebuf)){ - MessageBox(NULL, _T("State save: Buffer Full"), _T("Warning"), 0); - } -#endif -} - -void pc98_cirrus_vga_load() -{ - CirrusVGAState *s = cirrusvga; - UINT8 *f = cirrusvga_statsavebuf; - int pos = 0; - uint32_t_ state_ver = 0; - uint32_t_ intbuf; - //int width, height; - char en[3]; - -#if defined(SUPPORT_IA32_HAXM) - // HAXMはレジューム前にPCIメモリ割り当て解除 - i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); - i386hax_vm_removememoryarea(vramptr, np2clvga.pciLFB_Addr, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); - lastlinmmio = 0; -#endif - - array_read(f, pos, &state_ver, sizeof(state_ver)); // バージョン番号 - switch(state_ver){ - case 0: - s->latch = state_ver; // ver0.86 rev22以前はlatchは常にゼロ(のはず) - array_read(f, pos, &s->sr_index, sizeof(s->sr_index)); - array_read(f, pos, s->sr, 256); - array_read(f, pos, &s->gr_index, sizeof(s->gr_index)); - array_read(f, pos, &s->cirrus_shadow_gr0, sizeof(s->cirrus_shadow_gr0)); - array_read(f, pos, &s->cirrus_shadow_gr1, sizeof(s->cirrus_shadow_gr1)); - s->gr[0x00] = s->cirrus_shadow_gr0 & 0x0f; - s->gr[0x01] = s->cirrus_shadow_gr1 & 0x0f; - array_read(f, pos, s->gr + 2, 254); - array_read(f, pos, &s->ar_index, sizeof(s->ar_index)); - array_read(f, pos, s->ar, 21); - array_read(f, pos, &s->ar_flip_flop, sizeof(s->ar_flip_flop)); - array_read(f, pos, &s->cr_index, sizeof(s->cr_index)); - array_read(f, pos, s->cr, 256); - array_read(f, pos, &s->msr, sizeof(s->msr)); - array_read(f, pos, &s->fcr, sizeof(s->fcr)); - array_read(f, pos, &s->st00, sizeof(s->st00)); - array_read(f, pos, &s->st01, sizeof(s->st01)); - - array_read(f, pos, &s->dac_state, sizeof(s->dac_state)); - array_read(f, pos, &s->dac_sub_index, sizeof(s->dac_sub_index)); - array_read(f, pos, &s->dac_read_index, sizeof(s->dac_read_index)); - array_read(f, pos, &s->dac_write_index, sizeof(s->dac_write_index)); - array_read(f, pos, s->dac_cache, 3); - array_read(f, pos, s->palette, 768); - - array_read(f, pos, &s->bank_offset, sizeof(s->bank_offset)); - - array_read(f, pos, &s->cirrus_hidden_dac_lockindex, sizeof(s->cirrus_hidden_dac_lockindex)); - array_read(f, pos, &s->cirrus_hidden_dac_data, sizeof(s->cirrus_hidden_dac_data)); - - array_read(f, pos, &s->hw_cursor_x, sizeof(s->hw_cursor_x)); - array_read(f, pos, &s->hw_cursor_y, sizeof(s->hw_cursor_y)); - - array_read(f, pos, vramptr, CIRRUS_VRAM_SIZE); - - break; - case 3: - case 4: - case 5: - case 6: - array_read(f, pos, en, 2); - if(en[0] != 'e' || en[0] != 'n') - break; - - case 1: - case 2: - // この際全部保存 - array_read(f, pos, vramptr, CIRRUS_VRAM_SIZE); - array_read(f, pos, &s->vram_offset, sizeof(s->vram_offset)); - array_read(f, pos, &s->vram_size, sizeof(s->vram_size)); - array_read(f, pos, &s->lfb_addr, sizeof(s->lfb_addr)); - array_read(f, pos, &s->lfb_end, sizeof(s->lfb_end)); - array_read(f, pos, &s->map_addr, sizeof(s->map_addr)); - array_read(f, pos, &s->map_end, sizeof(s->map_end)); - array_read(f, pos, &s->lfb_vram_mapped, sizeof(s->lfb_vram_mapped)); - array_read(f, pos, &s->bios_offset, sizeof(s->bios_offset)); - array_read(f, pos, &s->bios_size, sizeof(s->bios_size)); - array_read(f, pos, &s->it_shift, sizeof(s->it_shift)); - - array_read(f, pos, &s->latch, sizeof(s->latch)); - array_read(f, pos, &s->sr_index, sizeof(s->sr_index)); - array_read(f, pos, s->sr, sizeof(s->sr)); - array_read(f, pos, &s->gr_index, sizeof(s->gr_index)); - array_read(f, pos, s->gr, sizeof(s->gr)); - array_read(f, pos, &s->ar_index, sizeof(s->ar_index)); - array_read(f, pos, s->ar, sizeof(s->ar)); - array_read(f, pos, &s->ar_flip_flop, sizeof(s->ar_flip_flop)); - array_read(f, pos, &s->cr_index, sizeof(s->cr_index)); - array_read(f, pos, s->cr, sizeof(s->cr)); - array_read(f, pos, &s->msr, sizeof(s->msr)); - array_read(f, pos, &s->fcr, sizeof(s->fcr)); - array_read(f, pos, &s->st00, sizeof(s->st00)); - array_read(f, pos, &s->st01, sizeof(s->st01)); - array_read(f, pos, &s->dac_state, sizeof(s->dac_state)); - array_read(f, pos, &s->dac_sub_index, sizeof(s->dac_sub_index)); - array_read(f, pos, &s->dac_read_index, sizeof(s->dac_read_index)); - array_read(f, pos, &s->dac_write_index, sizeof(s->dac_write_index)); - array_read(f, pos, s->dac_cache, sizeof(s->dac_cache)); - array_read(f, pos, &s->dac_8bit, sizeof(s->dac_8bit)); - array_read(f, pos, s->palette, sizeof(s->palette)); - array_read(f, pos, &s->bank_offset, sizeof(s->bank_offset)); - array_read(f, pos, &s->vga_io_memory, sizeof(s->vga_io_memory)); - array_read(f, pos, &s->vbe_index, sizeof(s->vbe_index)); - array_read(f, pos, s->vbe_regs, sizeof(s->vbe_regs)); - array_read(f, pos, &s->vbe_start_addr, sizeof(s->vbe_start_addr)); - array_read(f, pos, &s->vbe_line_offset, sizeof(s->vbe_line_offset)); - array_read(f, pos, &s->vbe_bank_mask, sizeof(s->vbe_bank_mask)); - - array_read(f, pos, s->font_offsets, sizeof(s->font_offsets)); - array_read(f, pos, &s->graphic_mode, sizeof(s->graphic_mode)); - array_read(f, pos, &s->shift_control, sizeof(s->shift_control)); - array_read(f, pos, &s->double_scan, sizeof(s->double_scan)); - array_read(f, pos, &s->line_offset, sizeof(s->line_offset)); - array_read(f, pos, &s->line_compare, sizeof(s->line_compare)); - array_read(f, pos, &s->start_addr, sizeof(s->start_addr)); - array_read(f, pos, &s->plane_updated, sizeof(s->plane_updated)); - array_read(f, pos, &s->last_line_offset, sizeof(s->last_line_offset)); - array_read(f, pos, &s->last_cw, sizeof(s->last_cw)); - array_read(f, pos, &s->last_ch, sizeof(s->last_ch)); - array_read(f, pos, &s->last_width, sizeof(s->last_width)); - array_read(f, pos, &s->last_height, sizeof(s->last_height)); - array_read(f, pos, &s->last_scr_width, sizeof(s->last_scr_width)); - array_read(f, pos, &s->last_scr_height, sizeof(s->last_scr_height)); - array_read(f, pos, &s->last_depth, sizeof(s->last_depth)); - array_read(f, pos, &s->cursor_start, sizeof(s->cursor_start)); - array_read(f, pos, &s->cursor_end, sizeof(s->cursor_end)); - array_read(f, pos, &s->cursor_offset, sizeof(s->cursor_offset)); - - array_read(f, pos, s->invalidated_y_table, sizeof(s->invalidated_y_table)); - array_read(f, pos, s->last_palette, sizeof(s->last_palette)); - array_read(f, pos, s->last_ch_attr, sizeof(s->last_ch_attr)); - - array_read(f, pos, &s->cirrus_linear_io_addr, sizeof(s->cirrus_linear_io_addr)); - array_read(f, pos, &s->cirrus_linear_bitblt_io_addr, sizeof(s->cirrus_linear_bitblt_io_addr)); - array_read(f, pos, &s->cirrus_mmio_io_addr, sizeof(s->cirrus_mmio_io_addr)); - array_read(f, pos, &s->cirrus_addr_mask, sizeof(s->cirrus_addr_mask)); - array_read(f, pos, &s->linear_mmio_mask, sizeof(s->linear_mmio_mask)); - array_read(f, pos, &s->cirrus_shadow_gr0, sizeof(s->cirrus_shadow_gr0)); - array_read(f, pos, &s->cirrus_shadow_gr1, sizeof(s->cirrus_shadow_gr1)); - array_read(f, pos, &s->cirrus_hidden_dac_lockindex, sizeof(s->cirrus_hidden_dac_lockindex)); - array_read(f, pos, &s->cirrus_hidden_dac_data, sizeof(s->cirrus_hidden_dac_data)); - array_read(f, pos, s->cirrus_bank_base, sizeof(s->cirrus_bank_base)); - array_read(f, pos, s->cirrus_bank_limit, sizeof(s->cirrus_bank_limit)); - array_read(f, pos, s->cirrus_hidden_palette, sizeof(s->cirrus_hidden_palette)); - array_read(f, pos, &s->hw_cursor_x, sizeof(s->hw_cursor_x)); - array_read(f, pos, &s->hw_cursor_y, sizeof(s->hw_cursor_y)); - array_read(f, pos, &s->cirrus_blt_pixelwidth, sizeof(s->cirrus_blt_pixelwidth)); - array_read(f, pos, &s->cirrus_blt_width, sizeof(s->cirrus_blt_width)); - array_read(f, pos, &s->cirrus_blt_height, sizeof(s->cirrus_blt_height)); - array_read(f, pos, &s->cirrus_blt_dstpitch, sizeof(s->cirrus_blt_dstpitch)); - array_read(f, pos, &s->cirrus_blt_srcpitch, sizeof(s->cirrus_blt_srcpitch)); - array_read(f, pos, &s->cirrus_blt_fgcol, sizeof(s->cirrus_blt_fgcol)); - array_read(f, pos, &s->cirrus_blt_bgcol, sizeof(s->cirrus_blt_bgcol)); - array_read(f, pos, &s->cirrus_blt_dstaddr, sizeof(s->cirrus_blt_dstaddr)); - array_read(f, pos, &s->cirrus_blt_srcaddr, sizeof(s->cirrus_blt_srcaddr)); - array_read(f, pos, &s->cirrus_blt_mode, sizeof(s->cirrus_blt_mode)); - array_read(f, pos, &s->cirrus_blt_modeext, sizeof(s->cirrus_blt_modeext)); - array_read(f, pos, s->cirrus_bltbuf, sizeof(s->cirrus_bltbuf)); - array_read(f, pos, &intbuf, sizeof(intbuf)); - s->cirrus_srcptr = s->cirrus_bltbuf + intbuf; - array_read(f, pos, &intbuf, sizeof(intbuf)); - s->cirrus_srcptr_end = s->cirrus_bltbuf + intbuf; - array_read(f, pos, &s->cirrus_srccounter, sizeof(s->cirrus_srccounter)); - array_read(f, pos, &s->last_hw_cursor_size, sizeof(s->last_hw_cursor_size)); - array_read(f, pos, &s->last_hw_cursor_x, sizeof(s->last_hw_cursor_x)); - array_read(f, pos, &s->last_hw_cursor_y, sizeof(s->last_hw_cursor_y)); - array_read(f, pos, &s->last_hw_cursor_y_start, sizeof(s->last_hw_cursor_y_start)); - array_read(f, pos, &s->last_hw_cursor_y_end, sizeof(s->last_hw_cursor_y_end)); - array_read(f, pos, &s->real_vram_size, sizeof(s->real_vram_size)); - array_read(f, pos, &s->device_id, sizeof(s->device_id)); - array_read(f, pos, &s->bustype, sizeof(s->bustype)); - - if(state_ver >= 2){ - array_read(f, pos, &np2clvga.VRAMWindowAddr3, sizeof(np2clvga.VRAMWindowAddr3)); - } - if(state_ver >= 4){ - array_read(f, pos, &s->videowindow_dblbuf_index, sizeof(s->videowindow_dblbuf_index)); - array_read(f, pos, &s->graphics_dblbuf_index, sizeof(s->graphics_dblbuf_index)); - } - if(state_ver >= 5){ - array_read(f, pos, &cirrusvga_wab_59e1, sizeof(cirrusvga_wab_59e1)); - array_read(f, pos, &cirrusvga_wab_51e1, sizeof(cirrusvga_wab_51e1)); - array_read(f, pos, &cirrusvga_wab_5be1, sizeof(cirrusvga_wab_5be1)); - array_read(f, pos, &cirrusvga_wab_40e1, sizeof(cirrusvga_wab_40e1)); - array_read(f, pos, &cirrusvga_wab_46e8, sizeof(cirrusvga_wab_46e8)); - array_read(f, pos, &cirrusvga_melcowab_ofs, sizeof(cirrusvga_melcowab_ofs)); - } - if(state_ver >= 6){ - array_read(f, pos, &cirrusvga_wab_42e1, sizeof(cirrusvga_wab_42e1)); - } - // - - break; - default: - break; - } - - s->cirrus_rop = cirrus_bitblt_rop_nop; // XXX: 本当はステートセーブで保存しないと駄目 - -#ifdef SUPPORT_PCI - // 関数アドレス入れ直し - pcidev.devices[pcidev_cirrus_deviceid].regwfn = &pcidev_cirrus_cfgreg_w; -#endif - - pc98_cirrus_vga_updatePCIaddr(); - -#if defined(SUPPORT_IA32_HAXM) - mmio_mode = MMIO_MODE_MMIO; // 0==MMIO, 1==VRAM - mmio_mode_region1 = 0; // 0==MMIO, 1==VRAM - mmio_mode_region2 = 0; // 0==MMIO, 1==VRAM - lastlinmmio = 0; - //i386hax_vm_removememoryarea(vramptr, np2clvga.pciLFB_Addr, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); -#endif - - cirrus_update_memory_access(s); - - s->graphic_mode = -1; - cirrus_update_bank_ptr(s, 0); - cirrus_update_bank_ptr(s, 1); - - // WAB画面サイズ強制更新 - np2wab.realWidth = 0; - np2wab.realHeight = 0; - - np2wab.paletteChanged = 1; // パレット変えました - cirrusvga_updated = 1; -} - -/*************************************** - * - * initialize - * - ***************************************/ -void cirrus_reset(void *opaque) -{ - CirrusVGAState *s = (CirrusVGAState*)opaque; - - memset(s->sr, 0, sizeof(s->sr)); - memset(s->cr, 0, sizeof(s->cr)); - memset(s->gr, 0, sizeof(s->gr)); - - vga_reset(s); - unmap_linear_vram(s); - s->sr[0x06] = 0x0f; - if (s->device_id == CIRRUS_ID_CLGD5446) { - /* 4MB 64 bit memory config, always PCI */ - s->sr[0x1F] = 0x2d; // MemClock - s->gr[0x18] = 0x0f; // fastest memory configuration - s->sr[0x0f] = CIRRUS_MEMSIZE_2M; //0x98; - s->sr[0x17] = 0x20; - s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ - } else { - s->sr[0x1F] = 0x22; // MemClock - s->sr[0x0F] = CIRRUS_MEMSIZE_2M; - s->sr[0x17] = s->bustype; - s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ - } - s->cr[0x27] = s->device_id; - if (np2clvga.gd54xxtype == CIRRUS_98ID_WAB) { - s->sr[0x0F] = CIRRUS_MEMSIZE_1M; - s->sr[0x15] = 0x02; - } - pc98_cirrus_setWABreg(); - -#if defined(NP2_WIN) - BitBlt(np2wabwnd.hDCBuf, 0, 0, WAB_MAX_WIDTH, WAB_MAX_HEIGHT, NULL, 0, 0, BLACKNESS); -#endif - if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F) { - memset(s->vram_ptr, 0x00, s->real_vram_size); - }else{ - /* Win2K seems to assume that the pattern buffer is at 0xff - initially ! */ - memset(s->vram_ptr, 0xff, s->real_vram_size); - } - memset(s->palette, 0, sizeof(s->palette)); - memset(s->cirrus_hidden_palette, 0, sizeof(s->cirrus_hidden_palette)); - - s->cirrus_hidden_dac_lockindex = 5; - //s->cirrus_hidden_dac_data = 0; - - // XXX: for WinNT4.0 - s->cirrus_hidden_dac_data = 1; - - // XXX: Win2000のハードウェアアクセラレーションを動かすのに必要。理由は謎 - s->gr[0x25] = 0x06; - s->gr[0x26] = 0x20; - - // XXX: Win2000で動かすのに必要。理由は謎 -#if defined(SUPPORT_PCI) - if(pcidev.enable && (np2clvga.gd54xxtype == CIRRUS_98ID_PCI || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI)){ - s->msr = 0x03; - s->sr[0x08] = 0xFE; - s->gr[0x0e] &= ~0x20; // XXX: for WinNT4.0 - s->gr[0x33] = 0x04; // XXX: for WinNT4.0 - s->cr[0x5e] &= ~0x20;//s->cr[0x5e] |= 0x20; // XXX: Part IDを読むまでGR33を書き込み禁止にする(WinNT4専用の不具合回避) - } -#endif - //fh = fopen("vgadump.bin", "w+"); - //if (fh != FILEH_INVALID) { - // fwrite(s, sizeof(CirrusVGAState), 1, fh); - // fclose(fh); - //} - cirrusvga_updated = 1; -} - -#if defined(NP2_WIN) -LOGPALETTE * NewLogPal(const uint8_t *pCirrusPalette , int iSize) { - LOGPALETTE *lpPalette; - int count; - - lpPalette = (LOGPALETTE*)malloc(sizeof (LOGPALETTE) + iSize * sizeof (PALETTEENTRY)); - lpPalette->palVersion = 0x0300; - lpPalette->palNumEntries = iSize; - - for (count = 0 ; count < iSize ; count++) { - lpPalette->palPalEntry[count].peRed = c6_to_8(pCirrusPalette[count*3]); - lpPalette->palPalEntry[count].peGreen = c6_to_8(pCirrusPalette[count*3+1]); - lpPalette->palPalEntry[count].peBlue = c6_to_8(pCirrusPalette[count*3+2]); - lpPalette->palPalEntry[count].peFlags = 0; - } - return lpPalette; -} -#endif - -void ConvertYUV2RGB(int width, unsigned char *srcYUV16, unsigned char *dstRGB32Line){ - int j; - int offset = 128; - if(cirrusvga->cr[0x3f] & 0x10){ - //if(cirrusvga->cr[0x3f] & 0x08){ - // // RGB555 - // //memcpy(dstRGB32Line, srcYUV16, width); - //}else{ - // YCC422 - for(j=0;j> 8; - int g0 = (298 * (y0 - 16) - 100 * (u0 - offset) - 208 * (v0 - offset) + 128) >> 8; - int b0 = (298 * (y0 - 16) + 516 * (u0 - offset) + 128) >> 8; - int r1 = (298 * (y1 - 16) + 409 * (v0 - offset) + 128) >> 8; - int g1 = (298 * (y1 - 16) - 100 * (u0 - offset) - 208 * (v0 - offset) + 128) >> 8; - int b1 = (298 * (y1 - 16) + 516 * (u0 - offset) + 128) >> 8; - dstRGB32Line[j*8 + 0] = (b0 < 0 ? 0 : (b0 > 255 ? 255 : b0)); - dstRGB32Line[j*8 + 1] = (g0 < 0 ? 0 : (g0 > 255 ? 255 : g0)); - dstRGB32Line[j*8 + 2] = (r0 < 0 ? 0 : (r0 > 255 ? 255 : r0)); - dstRGB32Line[j*8 + 4] = (b1 < 0 ? 0 : (b1 > 255 ? 255 : b1)); - dstRGB32Line[j*8 + 5] = (g1 < 0 ? 0 : (g1 > 255 ? 255 : g1)); - dstRGB32Line[j*8 + 6] = (r1 < 0 ? 0 : (r1 > 255 ? 255 : r1)); - } - //} - }else{ - for(j=0;j> 8; - int g0 = (298 * (y0 - 16) - 100 * (u0 - offset) - 208 * (v0 - offset) + 128) >> 8; - int b0 = (298 * (y0 - 16) + 516 * (u0 - offset) + 128) >> 8; - int r1 = (298 * (y1 - 16) + 409 * (v0 - offset) + 128) >> 8; - int g1 = (298 * (y1 - 16) - 100 * (u0 - offset) - 208 * (v0 - offset) + 128) >> 8; - int b1 = (298 * (y1 - 16) + 516 * (u0 - offset) + 128) >> 8; - dstRGB32Line[j*8 + 0] = (b0 < 0 ? 0 : (b0 > 255 ? 255 : b0)); - dstRGB32Line[j*8 + 1] = (g0 < 0 ? 0 : (g0 > 255 ? 255 : g0)); - dstRGB32Line[j*8 + 2] = (r0 < 0 ? 0 : (r0 > 255 ? 255 : r0)); - dstRGB32Line[j*8 + 4] = (b1 < 0 ? 0 : (b1 > 255 ? 255 : b1)); - dstRGB32Line[j*8 + 5] = (g1 < 0 ? 0 : (g1 > 255 ? 255 : g1)); - dstRGB32Line[j*8 + 6] = (r1 < 0 ? 0 : (r1 > 255 ? 255 : r1)); - } - } -} - -// 画面表示(仮) 本当はQEMUのオリジナルのコードを移植すべきなんだけど・・・ -// Cirrus VRAM (screen & cursor) -> GDI Device Independent Bitmap -int cirrusvga_drawGraphic(){ -//#define DEBUG_CIRRUS_VRAM -#if defined(DEBUG_CIRRUS_VRAM) - //static UINT32 kdown = 0; - //static UINT32 kdownc = 0; - static INT32 memshift = 0; // DEBUG - static INT32 sysmemmode = 0; // DEBUG - static INT32 tabon = 0; // DEBUG -#endif - int i, j, width, height, bpp; - uint32_t_ line_offset = 0; -#if defined(NP2_WIN) - LOGPALETTE * lpPalette; - static HPALETTE hPalette = NULL, oldPalette = NULL; - HDC hdc = np2wabwnd.hDCBuf; -#endif - static int waitscreenchange = 0; - int r; - int scanW = 0; // VRAM上の1ラインのデータ幅(byte) - int scanpixW = 0; // 実際に転送すべき1ラインのピクセル数(pixel) - int scanshift = 0; - uint8_t *scanptr; - uint8_t *vram_ptr; - -#if defined(NP2_X) - GdkPixbuf *VRAMBuf = NULL; - char* p; -#elif defined(USE_SDL) || defined(__LIBRETRO__) - unsigned int *VRAMBuf = NULL; - char* p; -#endif - - int cursot_ofs_x = 0; - int cursot_ofs_y = 0; - - int realWidth = 0; - int realHeight = 0; - - if (!cirrusvga_updated && !np2wab.paletteChanged) return 0; - cirrusvga_updated = 0; - - static int lastvramoffs = -1; - -#if defined(SUPPORT_IA32_HAXM) - // XXX: HAXMの仮想CPUがvramptrを書き換えることがあり、これの捕捉はできない。なのでメモリ比較で強引に検出 4MBくらいなら今時のPCならいいでしょう - if (memcmp(vramptr_cmp, vramptr, CIRRUS_VRAM_SIZE)) - { - memcpy(vramptr_cmp, vramptr, CIRRUS_VRAM_SIZE); - cirrusvga_updated = 1; - } -#endif - -// 20260127 Win2k起動不良のためコメントアウト -// if (!cirrusvga_updated && !np2wab.paletteChanged && lastvramoffs == np2wab.vramoffs) return 0; - // VRAM上での1ラインのサイズ(表示幅と等しくない場合有り) - line_offset = cirrusvga->cr[0x13] | ((cirrusvga->cr[0x1b] & 0x10) << 4); - line_offset <<= 3; - - vram_ptr = cirrusvga->vram_ptr + np2wab.vramoffs; - lastvramoffs = np2wab.vramoffs; - - //if(cirrusvga->device_id == CIRRUS_ID_CLGD5446 || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || (np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB){ - //if((cirrusvga->cr[0x5e] & 0x7) == 0x1){ - // cirrusvga->graphics_dblbuf_index = (cirrusvga->graphics_dblbuf_index + 1) & 0x1; - //} - //if(cirrusvga->graphics_dblbuf_index != 0 || (cirrusvga->cr[0x1a] & 0x2) || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || (np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB) - { - // Screen Start A - int addroffset = - (((int)(cirrusvga->cr[0x1d] >> 7) & 0x01) << 19)| - (((int)(cirrusvga->cr[0x1b] >> 2) & 0x03) << 17)| - (((int)(cirrusvga->cr[0x1b] >> 0) & 0x01) << 16)| - (((int)(cirrusvga->cr[0x0c] >> 0) & 0xff) << 8)| - (((int)(cirrusvga->cr[0x0d] >> 0) & 0xff) << 0); - vram_ptr += addroffset * 4; // ??? - } - //} - -#if defined(DEBUG_CIRRUS_VRAM) - // DEBUG - ////// vram_ptr = mem + 640*16*memshift; - //vram_ptr += 640*16*memshift; - if(GetKeyState(VK_SHIFT)<0){ - memshift++; - // kdown = 1; - //}else if(kdown){ - // //vram_ptr = vram_ptr + 1024*768*1; - // kdown = 0; - } - if(GetKeyState(VK_CONTROL)<0){ - memshift--; - if(memshift<0) memshift = 0; - //vram_ptr = mem + 1024*768*memshift; - // kdownc = 1; - //}else if(kdownc){ - // //vram_ptr = vram_ptr + 1024*768*1; - // kdownc = 0; - } - if(GetKeyState(VK_TAB)<0){ - if(!tabon){ - sysmemmode = (sysmemmode + 1) % 3; - tabon = 1; - } - }else{ - tabon = 0; - } - //if(GetKeyState(VK_CONTROL)<0){ - switch(sysmemmode){ - case 0: - vram_ptr = vram_ptr + 256*16*memshift; - break; - case 1: - vram_ptr = mem + 256*16*memshift; - break; - case 2: - vram_ptr = CPU_EXTMEMBASE + 256*16*memshift; - break; - } - //} - // DEBUG (END) -#endif - - // Cirrusの色数と解像度を取得 - bpp = cirrusvga->get_bpp((VGAState*)cirrusvga); - cirrusvga->get_resolution((VGAState*)cirrusvga, &width, &height); - //bpp = 16; - //width = 1024; - //height = 768; - -#if defined(SUPPORT_VGA_MODEX) - // PC/AT MODE X compatible - if (np2clvga.gd54xxtype <= 0xff){ - static UINT8 lastmodex = 0; - if(np2clvga.modex){ - if(!lastmodex){ - cirrusvga->sr[0x07] &= ~0x01; - } - bpp = 8; - width = 320; - height = 240; - line_offset = 320; - }else{ - if(!lastmodex){ - cirrusvga->sr[0x07] |= 0x01; - } - } - lastmodex = np2clvga.modex; - } -#endif - - if(bpp==0) return 0; - - // Palette mode > 85MHz (1280x1024) - if((cirrusvga->cirrus_hidden_dac_data & 0xCF) == 0x4A){ - bpp = 8; - width *= 2; - height *= 2; - } - - // GA-98NB用 1280x1024 - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - // XXX: Win3.1用 やっつけ修正 - if(width==640 && height==512 && bpp==15/* && - cirrusvga->cr[0x00]==0x63 && cirrusvga->cr[0x04]==0x53 && cirrusvga->cr[0x05]==0x1e && - cirrusvga->cr[0x06]==0x15 && cirrusvga->cr[0x10]==0x04 && cirrusvga->cr[0x11]==0x88*/){ - bpp = 8; - width *= 2; - height *= 2; - } - } - - // WAB解像度設定 - realWidth = width; - realHeight = height; - - // CRTC offset 設定 - scanW = width*(bpp/8); - scanpixW = width; - if(bpp && line_offset){ - // 32bit color用やっつけ修正 for GA-98NB & WSN-A2F/A4F - if(bpp==32){ - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || (np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB){ - line_offset <<= 1; - } - } - scanW = line_offset; - } - - // 色数判定 -#if defined(NP2_WIN) - if(bpp==16){ - // ビットフィールドでRGB565を指定 - uint32_t_* bitfleld = (uint32_t_*)(ga_bmpInfo->bmiColors); - bitfleld[0] = 0x0000F800; - bitfleld[1] = 0x000007E0; - bitfleld[2] = 0x0000001F; - ga_bmpInfo->bmiHeader.biCompression = BI_BITFIELDS; - }else{ - ga_bmpInfo->bmiHeader.biCompression = BI_RGB; - } - // Windowsの16bitカラーは標準でRGB555なのでそのままbpp=16に変更 - if(bpp==15){ - bpp = 16; - } -#endif - - // GA-98NB用 - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - if(np2cfg.ga98nb_bigscrn_ex && (bpp==8 || bpp==16) && (width==1024 || width==1280) && scanW*8/bpp==1600){ - // 1600x1024 Big Screen Extension - int addroffset = - (((int)(cirrusvga->cr[0x1d] >> 7) & 0x01) << 19)| - (((int)(cirrusvga->cr[0x1b] >> 2) & 0x03) << 17)| - (((int)(cirrusvga->cr[0x1b] >> 0) & 0x01) << 16)| - (((int)(cirrusvga->cr[0x0c] >> 0) & 0xff) << 8)| - (((int)(cirrusvga->cr[0x0d] >> 0) & 0xff) << 0); - addroffset *= 4; - realWidth = 1600; - realHeight = 1024; - width = 1600; - height = 1024; - scanpixW = 1600; - vram_ptr = cirrusvga->vram_ptr + np2wab.vramoffs; - cursot_ofs_x = (addroffset*8/bpp) % 1600; - cursot_ofs_y = (addroffset*8/bpp) / 1600; - } - } - - // WAB解像度更新 - np2wab.realWidth = realWidth; - np2wab.realHeight = realHeight; - -#if defined(NP2_WIN) - if(ga_bmpInfo->bmiHeader.biBitCount!=8 && bpp==8){ - np2wab.paletteChanged = 1; - } - - ga_bmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - ga_bmpInfo->bmiHeader.biWidth = width; // 仮セット - ga_bmpInfo->bmiHeader.biHeight = 1; // 仮セット - ga_bmpInfo->bmiHeader.biPlanes = 1; - ga_bmpInfo->bmiHeader.biBitCount = bpp; -#endif - if(bpp<=8){ - if(np2wab.paletteChanged){ -#if defined(NP2_WIN) - WORD* PalIndexes = (WORD*)((char*)ga_bmpInfo + sizeof(BITMAPINFOHEADER)); - for (i = 0; i < 256; ++i) PalIndexes[i] = i; - lpPalette = NewLogPal(cirrusvga->palette , 1<bmiHeader.biWidth = scanpixW; - ga_bmpInfo->bmiHeader.biHeight = -height; - scanptr = vram_ptr; - SetDIBitsToDevice( - hdc , 0 , 0 , - ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , - 0 , 0 , 0 , -ga_bmpInfo->bmiHeader.biHeight , - vram_ptr+scanshift*bpp/8 , ga_bmpInfo , DIB_PAL_COLORS - ); - //int scanshiftY = scanshift/scanpixW; - //ga_bmpInfo->bmiHeader.biWidth = scanpixW; - //ga_bmpInfo->bmiHeader.biHeight = -height; - //SetDIBitsToDevice( - // hdc , 0 , 0 , - // ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , - // 0 , 0 , scanshiftY , -ga_bmpInfo->bmiHeader.biHeight , - // vram_ptr , ga_bmpInfo , DIB_PAL_COLORS - //); - //SetDIBitsToDevice( - // hdc , 0 , 0 , - // ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , - // 0 , 0 , 0 , scanshiftY , - // vram_ptr , ga_bmpInfo , DIB_PAL_COLORS - //); -#elif defined(NP2_X) - scanptr = vram_ptr; - if(np2wabwnd.pPixbuf) { - VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); - p = gdk_pixbuf_get_pixels(VRAMBuf); - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 3 ] = cirrusvga->palette[vram_ptr[j * width + i] * 3 ] << 2; - p[(j * width + i) * 3 + 1] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 1] << 2; - p[(j * width + i) * 3 + 2] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 2] << 2; - } - } - } -#else - scanptr = vram_ptr; - VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); - p = (unsigned char*)VRAMBuf; - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 + 2] = cirrusvga->palette[vram_ptr[j * width + i] * 3 ] << 2; - p[(j * width + i) * 4 + 1] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 1] << 2; - p[(j * width + i) * 4 ] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 2] << 2; - } - } -#endif - }else{ -#if defined(NP2_WIN) - ga_bmpInfo->bmiHeader.biWidth = scanpixW; - ga_bmpInfo->bmiHeader.biHeight = -height; - scanptr = vram_ptr; - SetDIBitsToDevice( - hdc , 0 , 0 , - ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , - 0 , 0 , 0 , -ga_bmpInfo->bmiHeader.biHeight , - vram_ptr , ga_bmpInfo , DIB_PAL_COLORS - ); -#elif defined(NP2_X) - scanptr = vram_ptr; - if(np2wabwnd.pPixbuf) { - VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); - p = gdk_pixbuf_get_pixels(VRAMBuf); - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 3 ] = cirrusvga->palette[vram_ptr[j * width + i] * 3 ] << 2; - p[(j * width + i) * 3 + 1] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 1] << 2; - p[(j * width + i) * 3 + 2] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 2] << 2; - } - } - } -#else - scanptr = vram_ptr; - VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); - p = (unsigned char*)VRAMBuf; - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 + 2] = cirrusvga->palette[vram_ptr[j * width + i] * 3 ] << 2; - p[(j * width + i) * 4 + 1] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 1] << 2; - p[(j * width + i) * 4 ] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 2] << 2; - } - } -#endif - } - }else{ - // ズレがあるなら1ラインずつ転送 -#if defined(NP2_WIN) - scanptr = vram_ptr; - for(i=0;ibmiHeader.biWidth = width; - ga_bmpInfo->bmiHeader.biHeight = 1; - r = SetDIBitsToDevice( - hdc , 0 , i , - width , 1 , - 0 , 0 , 0 , 1 , - scanptr , ga_bmpInfo , DIB_PAL_COLORS - ); - scanptr += scanW; - } -#elif defined(NP2_X) - scanptr = vram_ptr; - if(np2wabwnd.pPixbuf) { - GdkPixbuf *VRAMBuf; - VRAMBuf = gdk_pixbuf_new_from_data(vram_ptr, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width*bpp/8, NULL,NULL); - } -#else - scanptr = vram_ptr; - VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); - p = (unsigned char*)VRAMBuf; - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 + 2] = cirrusvga->palette[vram_ptr[j * width + i] * 3 ] << 2; - p[(j * width + i) * 4 + 1] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 1] << 2; - p[(j * width + i) * 4 ] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 2] << 2; - } - } -#endif - } - }else{ - np2wab.paletteChanged = 0; // パレットではないので更新不要 - if(scanpixW*bpp/8==scanW){ - if(scanshift){ - // XXX: スキャン位置シフト -#if defined(NP2_WIN) - ga_bmpInfo->bmiHeader.biWidth = scanpixW; - ga_bmpInfo->bmiHeader.biHeight = -height; - scanptr = vram_ptr; - SetDIBitsToDevice( - hdc , 0 , 0 , - ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , - 0 , 0 , 0 , -ga_bmpInfo->bmiHeader.biHeight , - vram_ptr+scanshift*bpp/8 , ga_bmpInfo , DIB_RGB_COLORS - ); -#elif defined(NP2_X) - scanptr = vram_ptr; - if(np2wabwnd.pPixbuf) { - VRAMBuf = gdk_pixbuf_new_from_data(vram_ptr, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width*bpp/8, NULL,NULL); - p = gdk_pixbuf_get_pixels(VRAMBuf); - } -#else - scanptr = vram_ptr; - VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); - p = (unsigned char*)VRAMBuf; - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 ] = vram_ptr[(j * width + i) * 3 ]; - p[(j * width + i) * 4 + 1] = vram_ptr[(j * width + i) * 3 + 1]; - p[(j * width + i) * 4 + 2] = vram_ptr[(j * width + i) * 3 + 2]; - } - } -#endif - }else{ -#if defined(NP2_WIN) - ga_bmpInfo->bmiHeader.biWidth = scanpixW; - ga_bmpInfo->bmiHeader.biHeight = -height; - scanptr = vram_ptr; - SetDIBitsToDevice( - hdc , 0 , 0 , - ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , - 0 , 0 , 0 , -ga_bmpInfo->bmiHeader.biHeight , - vram_ptr , ga_bmpInfo , DIB_RGB_COLORS - ); -#elif defined(NP2_X) - scanptr = vram_ptr; - if(np2wabwnd.pPixbuf) { - if(bpp == 24) { - VRAMBuf = gdk_pixbuf_new_from_data(vram_ptr, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width*bpp/8, NULL,NULL); - } else if(bpp == 16) { - VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); - p = gdk_pixbuf_get_pixels(VRAMBuf); - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 3 ] = (((((UINT16*)vram_ptr)[j * width + i]) & 0xF800) >> 8) & 0xFF; - p[(j * width + i) * 3 + 1] = (((((UINT16*)vram_ptr)[j * width + i]) & 0x07C0) >> 3) & 0xFF; - p[(j * width + i) * 3 + 2] = (((((UINT16*)vram_ptr)[j * width + i]) & 0x001F) << 3) & 0xFF; - } - } - } else if(bpp == 32) { - VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); - p = gdk_pixbuf_get_pixels(VRAMBuf); - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 3 ] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x00FF0000) >> 16) & 0xFF; - p[(j * width + i) * 3 + 1] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x0000FF00) >> 8) & 0xFF; - p[(j * width + i) * 3 + 2] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x000000FF) ) & 0xFF; - } - } - } - } -#else - scanptr = vram_ptr; - VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); - p = (unsigned char*)VRAMBuf; - if(bpp == 24) { - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 ] = vram_ptr[(j * width + i) * 3 ]; - p[(j * width + i) * 4 + 1] = vram_ptr[(j * width + i) * 3 + 1]; - p[(j * width + i) * 4 + 2] = vram_ptr[(j * width + i) * 3 + 2]; - } - } - } else if(bpp == 16) { - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 + 2] = (((((UINT16*)vram_ptr)[j * width + i]) & 0xF800) >> 8) & 0xFF; - p[(j * width + i) * 4 + 1] = (((((UINT16*)vram_ptr)[j * width + i]) & 0x07C0) >> 3) & 0xFF; - p[(j * width + i) * 4 ] = (((((UINT16*)vram_ptr)[j * width + i]) & 0x001F) << 3) & 0xFF; - } - } - } else if(bpp == 32) { - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 + 2] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x00FF0000) >> 16) & 0xFF; - p[(j * width + i) * 4 + 1] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x0000FF00) >> 8) & 0xFF; - p[(j * width + i) * 4 ] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x000000FF) ) & 0xFF; - } - } - } -#endif - } - }else{ - // ズレがあるなら1ラインずつ転送 -#if defined(NP2_WIN) - scanptr = vram_ptr; - for(i=0;ibmiHeader.biWidth = width; - ga_bmpInfo->bmiHeader.biHeight = 1; - r = SetDIBitsToDevice( - hdc , 0 , i , - width , 1 , - 0 , 0 , 0 , 1 , - scanptr , ga_bmpInfo , DIB_RGB_COLORS - ); - scanptr += scanW; - } -#elif defined(NP2_X) - scanptr = vram_ptr; - if(np2wabwnd.pPixbuf) { - if(bpp == 15) { - VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); - p = gdk_pixbuf_get_pixels(VRAMBuf); - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 3 ] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x7C00) >> 7) & 0xFF; - p[(j * width + i) * 3 + 1] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x03E0) >> 2) & 0xFF; - p[(j * width + i) * 3 + 2] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x001F) << 3) & 0xFF; - } - } - } else if(bpp == 16) { - VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); - p = gdk_pixbuf_get_pixels(VRAMBuf); - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 3 ] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0xF800) >> 8) & 0xFF; - p[(j * width + i) * 3 + 1] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x07C0) >> 3) & 0xFF; - p[(j * width + i) * 3 + 2] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x001F) << 3) & 0xFF; - } - } - } else if(bpp == 24) { - VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); - p = gdk_pixbuf_get_pixels(VRAMBuf); - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 3 ] = vram_ptr[(j * scanW) + i * 3 ]; - p[(j * width + i) * 3 + 1] = vram_ptr[(j * scanW) + i * 3 + 1]; - p[(j * width + i) * 3 + 2] = vram_ptr[(j * scanW) + i * 3 + 2]; - } - } - } else if(bpp == 32) { - VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); - p = gdk_pixbuf_get_pixels(VRAMBuf); - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 3 ] = vram_ptr[(j * scanW) + i * 4 ]; - p[(j * width + i) * 3 + 1] = vram_ptr[(j * scanW) + i * 4 + 1]; - p[(j * width + i) * 3 + 2] = vram_ptr[(j * scanW) + i * 4 + 2]; - } - } - } else { - VRAMBuf = gdk_pixbuf_new_from_data(vram_ptr, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width*(bpp/8), NULL,NULL); - } - } -#else - scanptr = vram_ptr; - VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); - p = (unsigned char*)VRAMBuf; - if(bpp == 15) { - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 + 2] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x7C00) >> 7) & 0xFF; - p[(j * width + i) * 4 + 1] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x03E0) >> 2) & 0xFF; - p[(j * width + i) * 4 ] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x001F) << 3) & 0xFF; - } - } - } else if(bpp == 16) { - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 ] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0xF800) >> 8) & 0xFF; - p[(j * width + i) * 4 + 1] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x07C0) >> 3) & 0xFF; - p[(j * width + i) * 4 + 2] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x001F) << 3) & 0xFF; - } - } - } else if(bpp == 24) { - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 ] = vram_ptr[j * scanW + i * 3 ]; - p[(j * width + i) * 4 + 1] = vram_ptr[j * scanW + i * 3 + 1]; - p[(j * width + i) * 4 + 2] = vram_ptr[j * scanW + i * 3 + 2]; - } - } - } else if(bpp == 32) { - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 + 2] = ((*(UINT32*)(vram_ptr + j * scanW + i * 4) & 0x00FF0000) >> 16) & 0xFF; - p[(j * width + i) * 4 + 1] = ((*(UINT32*)(vram_ptr + j * scanW + i * 4) & 0x0000FF00) >> 8) & 0xFF; - p[(j * width + i) * 4 ] = ((*(UINT32*)(vram_ptr + j * scanW + i * 4) & 0x000000FF) ) & 0xFF; - } - } - } else { - for(j = 0; j < height; j++) { - for(i = 0; i < width; i++) { - p[(j * width + i) * 4 ] = vram_ptr[j * scanW + i * 3 ]; - p[(j * width + i) * 4 + 1] = vram_ptr[j * scanW + i * 3 + 1]; - p[(j * width + i) * 4 + 2] = vram_ptr[j * scanW + i * 3 + 2]; - } - } - } -#endif - } - } - - // CL-GD544x Video Window - if(cirrusvga->cr[0x3e] & 0x01){ // Check Video Window Master Enable bit - uint32_t_* bitfleld; - int vidwnd_format = ((cirrusvga->cr[0x3e] >> 1) & 0x7); - int vidwnd_bpp = (vidwnd_format==0 || vidwnd_format==4 || vidwnd_format==5) ? 16 : 8; - int vidwnd_horizontalZoom = (cirrusvga->cr[0x31]); - int vidwnd_verticalZoom = (cirrusvga->cr[0x32]); - int vidwnd_region1Adj = (cirrusvga->cr[0x5d]>>0) & 0x3; - int vidwnd_region2Adj = (cirrusvga->cr[0x5d]>>4) & 0x3; - int vidwnd_region1Size = (((cirrusvga->cr[0x36] >> 0) & 0x03) << 8)|(cirrusvga->cr[0x33]); - int vidwnd_region2Size = (((cirrusvga->cr[0x36] >> 2) & 0x03) << 8)|(cirrusvga->cr[0x34]); - int vidwnd_region2SDSize = (((cirrusvga->cr[0x36] >> 4) & 0x03) << 8)|(cirrusvga->cr[0x35]); - int vidwnd_verticalStart = (((cirrusvga->cr[0x39] >> 0) & 0x03) << 8)|(cirrusvga->cr[0x37]); - int vidwnd_verticalEnd = (((cirrusvga->cr[0x39] >> 2) & 0x03) << 8)|(cirrusvga->cr[0x38]); - int vidwnd_startAddress = ((cirrusvga->cr[0x3c] & 0x0f) << 18)|(cirrusvga->cr[0x3b] << 10)|(cirrusvga->cr[0x3a] << 2); - int vidwnd_bufAddressOffset = (((cirrusvga->cr[0x3c] >> 5) & 0x01) << 11)|(cirrusvga->cr[0x3d] << 3); - int vidwnd_srcwidth = vidwnd_region2SDSize * vidwnd_bpp/8; - int vidwnd_srcheight = vidwnd_verticalEnd - vidwnd_verticalStart; - int vidwnd_srcpitch = vidwnd_bufAddressOffset; - int vidwnd_dstwidth = vidwnd_srcwidth;//vidwnd_region2Size * bpp/8; - int vidwnd_dstheight = vidwnd_verticalEnd - vidwnd_verticalStart; - int vidwnd_dstX = vidwnd_region1Size * 32 / bpp + vidwnd_region1Adj * 8 / bpp; - int vidwnd_dstY = vidwnd_verticalStart; - int vidwnd_yuv = 0; - if(vidwnd_horizontalZoom > 0) vidwnd_dstwidth = vidwnd_srcwidth * 256 / vidwnd_horizontalZoom; - if(vidwnd_verticalZoom > 0) vidwnd_srcheight = vidwnd_dstheight * vidwnd_verticalZoom / 256; -#if defined(NP2_WIN) - switch(vidwnd_format){ - case 0: // YUV 4:2:2 UYVY - vidwnd_yuv = 1; - vidwnd_bpp = 32; - ga_bmpInfo->bmiHeader.biCompression = BI_RGB; - break; - case 4: // RGB555 - //// XXX: RGB555になってない??? - //ga_bmpInfo->bmiHeader.biCompression = BI_RGB; - //break; - case 5: // RGB565 - // ビットフィールドでRGB565を指定 - bitfleld = (uint32_t_*)(ga_bmpInfo->bmiColors); - bitfleld[0] = 0x0000F800; - bitfleld[1] = 0x000007E0; - bitfleld[2] = 0x0000001F; - ga_bmpInfo->bmiHeader.biCompression = BI_BITFIELDS; - break; - default: - break; - } - ga_bmpInfo->bmiHeader.biBitCount = vidwnd_bpp; - scanptr = vram_ptr + vidwnd_startAddress; -#if defined(DEBUG_CIRRUS_VRAM) - scanptr = scanptr - 1280*16*memshift; // DEBUG -#endif - if(vidwnd_dstwidth == vidwnd_srcwidth && vidwnd_dstheight == vidwnd_srcheight){ - if(!vidwnd_yuv){ - for(i=0;ibmiHeader.biWidth = width; - ga_bmpInfo->bmiHeader.biHeight = 1; - r = SetDIBitsToDevice( - hdc , vidwnd_dstX , vidwnd_dstY + i , - vidwnd_srcwidth , 1 , - 0 , 0 , 0 , 1 , - scanptr , ga_bmpInfo , DIB_RGB_COLORS - ); - scanptr += vidwnd_srcpitch; - } - }else{ - unsigned char *linebuf = (unsigned char*)malloc(vidwnd_srcwidth*4); - for(i=0;ibmiHeader.biWidth = width; - ga_bmpInfo->bmiHeader.biHeight = 1; - r = SetDIBitsToDevice( - hdc , vidwnd_dstX , vidwnd_dstY + i , - vidwnd_srcwidth , 1 , - 0 , 0 , 0 , 1 , - linebuf , ga_bmpInfo , DIB_RGB_COLORS - ); - scanptr += vidwnd_srcpitch; - } - free(linebuf); - } - }else{ - if(!vidwnd_yuv){ - for(i=0;ibmiHeader.biWidth = width; - ga_bmpInfo->bmiHeader.biHeight = 1; - r = StretchDIBits( - hdc , vidwnd_dstX , vidwnd_dstY + i , - vidwnd_dstwidth , 1 , - 0 , 0 , vidwnd_srcwidth , 1 , - scanptr + (i * vidwnd_srcheight / vidwnd_dstheight) * vidwnd_srcpitch, ga_bmpInfo , DIB_RGB_COLORS , SRCCOPY - ); - } - }else{ - int lastline = -1; - unsigned char *linebuf = (unsigned char*)malloc(vidwnd_srcwidth*4); - for(i=0;ibmiHeader.biWidth = width; - ga_bmpInfo->bmiHeader.biHeight = 1; - r = StretchDIBits( - hdc , vidwnd_dstX , vidwnd_dstY + i , - vidwnd_dstwidth , 1 , - 0 , 0 , vidwnd_srcwidth , 1 , - linebuf, ga_bmpInfo , DIB_RGB_COLORS , SRCCOPY - ); - } - free(linebuf); - } - } -#else - // TODO: 非Windows用コードを書く -#endif - } - - if ((cirrusvga->sr[0x12] & CIRRUS_CURSOR_SHOW)){ - int hwcur_x = cirrusvga->hw_cursor_x + cursot_ofs_x; - int hwcur_y = cirrusvga->hw_cursor_y + cursot_ofs_y; - // GA-98NB用 カーソル位置調整 - if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - if(width==320 && height==240){ - hwcur_y /= 2; - } - } - if(np2cfg.gd5430fakecur){ - // ハードウェアカーソルが上手く表示できない場合用 -#if defined(NP2_WIN) - DrawIcon(hdc, hwcur_x, hwcur_y, ga_hFakeCursor); -#elif defined(NP2_X) - int fcx, fcy; - UINT8 col; - p = gdk_pixbuf_get_pixels(VRAMBuf); - for(fcy = 0; fcy < CIRRUS_FMC_H; fcy++) { - for(fcx = 0; fcx < CIRRUS_FMC_W; fcx++) { - col = FakeMouseCursorData[fcy * CIRRUS_FMC_W + fcx]; - if(col && cirrusvga->hw_cursor_x + fcx < width && cirrusvga->hw_cursor_y + fcy < height) { - col--; - p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 3 ] = \ - p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 3 + 1] = \ - p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 3 + 2] = col * 0xFF; - } - } - } -#else - int fcx, fcy; - UINT8 col; - for(fcy = 0; fcy < CIRRUS_FMC_H; fcy++) { - for(fcx = 0; fcx < CIRRUS_FMC_W; fcx++) { - col = FakeMouseCursorData[fcy * CIRRUS_FMC_W + fcx]; - if(col && cirrusvga->hw_cursor_x + fcx < width && cirrusvga->hw_cursor_y + fcy < height) { - col--; - p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 4 ] = \ - p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 4 + 1] = \ - p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 4 + 2] = col * 0xFF; - } - } - } -#endif - }else{ - //HPALETTE oldCurPalette; - int cursize = 32; - int x, y; - int x1, x2, h, w; - //unsigned int basecolor; - unsigned int color0, color1; - uint8_t *d1 = cirrusvga->vram_ptr; - uint8_t *palette, *src, *base; - uint32_t_ *dst; - uint32_t_ content; - uint32_t_ colortmp; - const uint8_t *plane0, *plane1; - int b0, b1; - int poffset; - if (cirrusvga->sr[0x12] & CIRRUS_CURSOR_LARGE) { - cursize = 64; - } -#if defined(NP2_WIN) - BitBlt(ga_hdc_cursor , 0 , 0 , cursize , cursize , hdc , hwcur_x , hwcur_y , SRCCOPY); - - if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; - }else if(np2clvga.gd54xxtype <= 0xff){ - base = cirrusvga->vram_ptr + 1024 * 1024 - 16 * 1024; // ??? 1MB前提? - }else{ - base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; - } - if (height >= hwcur_y && 0 <= (hwcur_y + cursize)){ - int y1, y2; - y1 = hwcur_y; - y2 = hwcur_y+cursize; - h = cursize; - dst = (uint32_t_ *)cursorptr; - dst += 64*64; - dst -= 64; - palette = cirrusvga->cirrus_hidden_palette; - color0 = rgb_to_pixel32(c6_to_8(palette[0x0 * 3]), - c6_to_8(palette[0x0 * 3 + 1]), - c6_to_8(palette[0x0 * 3 + 2])); - color1 = rgb_to_pixel32(c6_to_8(palette[0xf * 3]), - c6_to_8(palette[0xf * 3 + 1]), - c6_to_8(palette[0xf * 3 + 2])); - for(y=y1;ysr[0x12] & CIRRUS_CURSOR_LARGE) { - src += (cirrusvga->sr[0x13] & 0x3c) * 256; - src += (y - (int)hwcur_y) * 16; - poffset = 8; - content = ((uint32_t_ *)src)[0] | - ((uint32_t_ *)src)[1] | - ((uint32_t_ *)src)[2] | - ((uint32_t_ *)src)[3]; - } else { - src += (cirrusvga->sr[0x13] & 0x3f) * 256; - src += (y - (int)hwcur_y) * 4; - poffset = 128; - content = ((uint32_t_ *)src)[0] | - ((uint32_t_ *)(src + 128))[0]; - } - /* if nothing to draw, no need to continue */ - x1 = hwcur_x; - if (x1 < width){ - x2 = hwcur_x + cursize; - w = x2 - x1; - for(x=0;x> 3] >> (7 - ((x) & 7))) & 1; - b1 = (plane1[(x) >> 3] >> (7 - ((x) & 7))) & 1; - switch(b0 | (b1 << 1)) { - case 0: - break; - case 1: - colortmp ^= 0xffffff; - break; - case 2: - colortmp = color0; - break; - case 3: - colortmp = color1; - break; - } - *dst = colortmp; - dst++; - } - dst += (64 - w); - } - dst -= 64*2; - } - } - BitBlt(hdc , hwcur_x , hwcur_y , cursize , cursize , ga_hdc_cursor , 0 , 0 , SRCCOPY); -#elif defined(NP2_X) - if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; - }else if(np2clvga.gd54xxtype <= 0xff){ - base = cirrusvga->vram_ptr + 1024 * 1024 - 16 * 1024; // ??? 1MB前提? - }else{ - base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; - } - if (height >= hwcur_y && 0 <= (hwcur_y + cursize)){ - UINT8 color0_r, color0_g, color0_b; - UINT8 color1_r, color1_g, color1_b; - int y1, y2; - y1 = hwcur_y; - y2 = hwcur_y+cursize; - h = cursize; - p = gdk_pixbuf_get_pixels(VRAMBuf); - p += (cirrusvga->hw_cursor_y * width + cirrusvga->hw_cursor_x) * 3; // カーソル位置のポインタ - palette = cirrusvga->cirrus_hidden_palette; - color0_r = c6_to_8(palette[0x0 * 3]); - color0_g = c6_to_8(palette[0x0 * 3 + 1]); - color0_b = c6_to_8(palette[0x0 * 3 + 2]); - color1_r = c6_to_8(palette[0xf * 3]); - color1_g = c6_to_8(palette[0xf * 3 + 1]); - color1_b = c6_to_8(palette[0xf * 3 + 2]); - if(y2 > height) y2 = height; - for(y=y1;ysr[0x12] & CIRRUS_CURSOR_LARGE) { - src += (cirrusvga->sr[0x13] & 0x3c) * 256; - src += (y - (int)hwcur_y) * 16; - poffset = 8; - content = ((uint32_t_ *)src)[0] | - ((uint32_t_ *)src)[1] | - ((uint32_t_ *)src)[2] | - ((uint32_t_ *)src)[3]; - } else { - src += (cirrusvga->sr[0x13] & 0x3f) * 256; - src += (y - (int)hwcur_y) * 4; - poffset = 128; - content = ((uint32_t_ *)src)[0] | - ((uint32_t_ *)(src + 128))[0]; - } - /* if nothing to draw, no need to continue */ - UINT8 colortmp_r, colortmp_g, colortmp_b; - const uint8_t *plane0, *plane1; - int b0, b1; - x1 = hwcur_x; - if (x1 < width){ - x2 = hwcur_x + cursize; - w = x2 - x1; - for(x=0;x> 3] >> (7 - ((x) & 7))) & 1; - b1 = (plane1[(x) >> 3] >> (7 - ((x) & 7))) & 1; - switch(b0 | (b1 << 1)) { - case 0: - break; - case 1: - colortmp_r ^= 0xff; - colortmp_g ^= 0xff; - colortmp_b ^= 0xff; - break; - case 2: - colortmp_r = color0_r; - colortmp_g = color0_g; - colortmp_b = color0_b; - break; - case 3: - colortmp_r = color1_r; - colortmp_g = color1_g; - colortmp_b = color1_b; - break; - } - *p = colortmp_r; - *(p+1) = colortmp_g; - *(p+2) = colortmp_b; - } - p += 3; - } - p += (width - w) * 3; - } - } - } -#else - if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; - }else if(np2clvga.gd54xxtype <= 0xff){ - base = cirrusvga->vram_ptr + 1024 * 1024 - 16 * 1024; // ??? 1MB前提? - }else{ - base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; - } - if (height >= hwcur_y && 0 <= (hwcur_y + cursize)){ - UINT8 color0_r, color0_g, color0_b; - UINT8 color1_r, color1_g, color1_b; - int y1, y2; - y1 = hwcur_y; - y2 = hwcur_y+cursize; - h = cursize; - p += (cirrusvga->hw_cursor_y * width + cirrusvga->hw_cursor_x) * 4; // カーソル位置のポインタ - palette = cirrusvga->cirrus_hidden_palette; - color0_r = c6_to_8(palette[0x0 * 3]); - color0_g = c6_to_8(palette[0x0 * 3 + 1]); - color0_b = c6_to_8(palette[0x0 * 3 + 2]); - color1_r = c6_to_8(palette[0xf * 3]); - color1_g = c6_to_8(palette[0xf * 3 + 1]); - color1_b = c6_to_8(palette[0xf * 3 + 2]); - if(y2 > height) y2 = height; - for(y=y1;ysr[0x12] & CIRRUS_CURSOR_LARGE) { - src += (cirrusvga->sr[0x13] & 0x3c) * 256; - src += (y - (int)hwcur_y) * 16; - poffset = 8; - content = ((uint32_t_ *)src)[0] | - ((uint32_t_ *)src)[1] | - ((uint32_t_ *)src)[2] | - ((uint32_t_ *)src)[3]; - } else { - src += (cirrusvga->sr[0x13] & 0x3f) * 256; - src += (y - (int)hwcur_y) * 4; - poffset = 128; - content = ((uint32_t_ *)src)[0] | - ((uint32_t_ *)(src + 128))[0]; - } - /* if nothing to draw, no need to continue */ - x1 = hwcur_x; - if (x1 < width){ - x2 = hwcur_x + cursize; - w = x2 - x1; - for(x=0;x> 3] >> (7 - ((x) & 7))) & 1; - b1 = (plane1[(x) >> 3] >> (7 - ((x) & 7))) & 1; - switch(b0 | (b1 << 1)) { - case 0: - break; - case 1: - colortmp_r ^= 0xff; - colortmp_g ^= 0xff; - colortmp_b ^= 0xff; - break; - case 2: - colortmp_r = color0_r; - colortmp_g = color0_g; - colortmp_b = color0_b; - break; - case 3: - colortmp_r = color1_r; - colortmp_g = color1_g; - colortmp_b = color1_b; - break; - } - *p = colortmp_r; - *(p+1) = colortmp_g; - *(p+2) = colortmp_b; - } - p += 4; - } - p += (width - w) * 4; - } - } - } -#endif - } - } -#if defined(NP2_WIN) - ga_bmpInfo->bmiHeader.biWidth = width; // 前回の解像度を保存 - ga_bmpInfo->bmiHeader.biHeight = height; // 前回の解像度を保存 -#elif defined(NP2_X) - if(VRAMBuf && np2wabwnd.pPixbuf) { - gdk_pixbuf_scale(VRAMBuf, np2wabwnd.pPixbuf, - 0, 0, width, height, - 0, 0, 1, 1, - GDK_INTERP_NEAREST); - g_object_unref(VRAMBuf); - if(bpp == 24) { - UINT8* ptr = (UINT8 *)gdk_pixbuf_get_pixels(np2wabwnd.pPixbuf); - for(i = 0; i < 1280 * 1024; i++) { - j = ptr[i * 3]; - ptr[i * 3] = ptr[i * 3 + 2]; - ptr[i * 3 + 2] = j; - } - } - } -#else - memcpy(np2wabwnd.pBuffer, VRAMBuf, width * height * sizeof(unsigned int)); - free(VRAMBuf); -#endif - return 1; -} - -/*************************************** - * - * PC-9821 support - * - ***************************************/ -static void IOOUTCALL cirrusvga_ofa2(UINT port, REG8 dat) { - TRACEOUT(("CIRRUS VGA: set register index %02X", dat)); - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - } - cirrusvga_regindexA2 = dat; - (void)port; - (void)dat; -} -static REG8 IOINPCALL cirrusvga_ifa2(UINT port) { - TRACEOUT(("CIRRUS VGA: get register index %02X", cirrusvga_regindex)); - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - } - return cirrusvga_regindexA2; -} -static void IOOUTCALL cirrusvga_ofa3(UINT port, REG8 dat) { - TRACEOUT(("CIRRUS VGA: out %04X d=%.2X", port, dat)); - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - } - switch(cirrusvga_regindexA2){ - case 0x00: - // 機種判定? - break; - case 0x01: - // VRAMウィンドウアドレス設定 - switch(dat){ - case 0x10: - np2clvga.VRAMWindowAddr2 = 0x0b0000; - break; - case 0x80: - np2clvga.VRAMWindowAddr2 = 0xf20000; - break; - case 0xA0: - np2clvga.VRAMWindowAddr2 = 0xf00000; - break; - case 0xC0: - np2clvga.VRAMWindowAddr2 = 0xf40000; - break; - case 0xE0: - np2clvga.VRAMWindowAddr2 = 0xf60000; - break; - } - break; - case 0x02: - // リニアVRAMアクセス用アドレス設定 - if(np2clvga.gd54xxtype != CIRRUS_98ID_PCI){ - if(np2clvga.gd54xxtype <= 0xff){ - if(dat!=0x00 && dat!=0xff) np2clvga.VRAMWindowAddr = (dat<<24); - } - } - break; - case 0x03: - // 出力切替リレー制御 - if((!!np2wab.relaystateint) != (!!(dat&0x2))){ - np2wab.relaystateint = dat & 0x2; - np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) - } - np2clvga.mmioenable = (dat&0x1); - break; - } - (void)port; - (void)dat; -} -static REG8 IOINPCALL cirrusvga_ifa3(UINT port) { - REG8 ret = 0xff; - - TRACEOUT(("CIRRUS VGA: inp %04X", port)); - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - } - switch(cirrusvga_regindexA2){ - case 0x00: - // 機種判定? - if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - ret = 0xff; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ - ret = (REG8)np2clvga.gd54xxtype; - }else{ - ret = 0xff; - } - break; - case 0x01: - // VRAMウィンドウアドレス設定 - //if(np2clvga.gd54xxtype <= 0xff){ - switch(np2clvga.VRAMWindowAddr2){ - case 0x0b0000: - ret = 0x10; - break; - case 0xf00000: - ret = 0xA0; - break; - case 0xf20000: - ret = 0x80; - break; - case 0xf40000: - ret = 0xC0; - break; - case 0xf60000: - ret = 0xE0; - break; - } - //}else{ - // ret = 0xff; - //} - break; - case 0x02: - // リニアVRAMアクセス用アドレス設定 - if(np2clvga.gd54xxtype <= 0xff){ - ret = (np2clvga.VRAMWindowAddr>>24)&0xff; - }else{ - ret = 0xff; - } - break; - case 0x03: - // 出力切替リレー制御 - ret = ((np2wab.relaystateint&0x2) ? 0x2 : 0x0) | np2clvga.mmioenable; - break; - case 0x04: - // ? - ret = 0x00; - break; - } - return ret; -} - -static void IOOUTCALL cirrusvga_ofaa(UINT port, REG8 dat) { - TRACEOUT(("CIRRUS VGA: set register index %02X", dat)); - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - } - cirrusvga_regindex = dat; - (void)port; - (void)dat; -} -static REG8 IOINPCALL cirrusvga_ifaa(UINT port) { - TRACEOUT(("CIRRUS VGA: get register index %02X", cirrusvga_regindex)); - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - } - return cirrusvga_regindex; -} -static void IOOUTCALL cirrusvga_ofab(UINT port, REG8 dat) { - TRACEOUT(("CIRRUS VGA: out %04X d=%.2X", port, dat)); - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - } - switch(cirrusvga_regindex){ - case 0x00: - // 機種判定 - break; - case 0x01: - // VRAMウィンドウアドレス設定 - switch(dat){ - case 0x10: - np2clvga.VRAMWindowAddr2 = 0x0b0000; - break; - case 0x80: - np2clvga.VRAMWindowAddr2 = 0xf20000; - break; - case 0xA0: - np2clvga.VRAMWindowAddr2 = 0xf00000; - break; - case 0xC0: - np2clvga.VRAMWindowAddr2 = 0xf40000; - break; - case 0xE0: - np2clvga.VRAMWindowAddr2 = 0xf60000; - break; - } - break; - case 0x02: - // リニアVRAMアクセス用アドレス設定 - if(dat!=0x00 && dat!=0xff) np2clvga.VRAMWindowAddr = (dat<<24); - //cirrusvga->vram_offset = np2clvga.VRAMWindowAddr; - break; - case 0x03: - // 出力切替リレー制御 - if((!!np2wab.relaystateint) != (!!(dat&0x2))){ - np2wab.relaystateint = dat & 0x2; - np2wab.relaystateext = dat & 0x2; // ( ̄∀ ̄;) - np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) - } - np2clvga.mmioenable = (dat&0x1); - break; - } - (void)port; - (void)dat; -} -static REG8 IOINPCALL cirrusvga_ifab(UINT port) { - REG8 ret = 0xff; - TRACEOUT(("CIRRUS VGA: inp %04X", port)); - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - } - switch(cirrusvga_regindex){ - case 0x00: - // 機種判定 - if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - ret = 0xff; - }else if(np2clvga.gd54xxtype <= 0xff){ - ret = (REG8)np2clvga.gd54xxtype;//0x5B; - }else{ - ret = 0xff; - } - break; - case 0x01: - // VRAMウィンドウアドレス設定 - if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - ret = 0x80; - }else{ - if(np2clvga.gd54xxtype <= 0xff){ - switch(np2clvga.VRAMWindowAddr2){ - case 0x0b0000: - ret = 0x10; - break; - case 0xf20000: - ret = 0x80; - break; - case 0xf00000: - ret = 0xA0; - break; - case 0xf40000: - ret = 0xC0; - break; - case 0xf60000: - ret = 0xE0; - break; - } - }else{ - ret = 0xff; - } - } - break; - case 0x02: - // リニアVRAMアクセス用アドレス設定 - if(np2clvga.gd54xxtype <= 0xff){ - ret = (np2clvga.VRAMWindowAddr>>24)&0xff; - }else{ - ret = 0xff; - } - break; - case 0x03: - // 出力切替リレー制御 - ret = (np2wab.relay ? 0x2 : 0x0) | np2clvga.mmioenable; - break; - } - return ret; -} - -int cirrusvga_videoenable = 0x00; -static void IOOUTCALL cirrusvga_off82(UINT port, REG8 dat) { - TRACEOUT(("CIRRUS VGA: out %04X d=%02X", port, dat)); - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - } - cirrusvga_videoenable = dat & 0x1; - (void)port; - (void)dat; -} -static REG8 IOINPCALL cirrusvga_iff82(UINT port) { - TRACEOUT(("CIRRUS VGA: inp %04X", port)); - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - } - return cirrusvga_videoenable; -} - -int cirrusvga_reg0904 = 0x00; -static void IOOUTCALL cirrusvga_o0904(UINT port, REG8 dat) { - TRACEOUT(("CIRRUS VGA: out %04X d=%02X", port, dat)); - cirrusvga_reg0904 = dat; - (void)port; - (void)dat; -} -static REG8 IOINPCALL cirrusvga_i0904(UINT port) { - TRACEOUT(("CIRRUS VGA: inp %04X", port)); - return cirrusvga_reg0904; -} - -// WAB, WSN用 -static void cirrusvga_setAutoWABID() { - switch(np2clvga.defgd54xxtype){ - case CIRRUS_98ID_AUTO_XE_G1_PCI: - np2clvga.gd54xxtype = CIRRUS_98ID_GA98NBIC; - memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); - cirrusvga_wab_59e1 = 0x06; // d.c. - cirrusvga_wab_51e1 = 0xC2; // d.c. - cirrusvga_wab_5be1 = 0xf7; // d.c. - cirrusvga_wab_40e1 = 0xC2; // bit1=0:DRAM REFRESH MODE?? とりあえず初期値はC2hじゃないとWin95ドライバはボードを認識しない - cirrusvga_wab_42e1 = 0x18; // 存在しない - cirrusvga_wab_46e8 = 0x18; - break; - case CIRRUS_98ID_AUTO_XE_G2_PCI: - np2clvga.gd54xxtype = CIRRUS_98ID_GA98NBII; - memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); - cirrusvga_wab_59e1 = 0x06; // d.c. - cirrusvga_wab_51e1 = 0xC2; // d.c. - cirrusvga_wab_5be1 = 0xf7; // d.c. - cirrusvga_wab_40e1 = 0xC2; // bit1=0:DRAM REFRESH MODE?? とりあえず初期値はC2hじゃないとWin95ドライバはボードを認識しない - cirrusvga_wab_42e1 = 0x18; // 存在しない - cirrusvga_wab_46e8 = 0x18; - break; - case CIRRUS_98ID_AUTO_XE_G4_PCI: - np2clvga.gd54xxtype = CIRRUS_98ID_GA98NBIV; - memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); - cirrusvga_wab_59e1 = 0x06; // d.c. - cirrusvga_wab_51e1 = 0xC2; // d.c. - cirrusvga_wab_5be1 = 0xf7; // d.c. - cirrusvga_wab_40e1 = 0xC2; // bit1=0:DRAM REFRESH MODE?? とりあえず初期値はC2hじゃないとWin95ドライバはボードを認識しない - cirrusvga_wab_42e1 = 0x18; // 存在しない - cirrusvga_wab_46e8 = 0x18; - break; - case CIRRUS_98ID_AUTO_XE10_WABS: - case CIRRUS_98ID_AUTO_XE_WA_PCI: - np2clvga.gd54xxtype = CIRRUS_98ID_WAB; - break; - case CIRRUS_98ID_AUTO_XE10_WSN4: - case CIRRUS_98ID_AUTO_XE_W4_PCI: - np2clvga.gd54xxtype = CIRRUS_98ID_WSN; - break; - default: - np2clvga.gd54xxtype = CIRRUS_98ID_WSN_A2F; - break; - } - pc98_cirrus_setWABreg(); - pc98_cirrus_vga_setvramsize(); - pc98_cirrus_vga_initVRAMWindowAddr(); - cirrusvga_updated = 1; -} - -static REG8 IOINPCALL cirrusvga_i59e1(UINT port) { - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - cirrusvga_setAutoWABID(); - } - return cirrusvga_wab_59e1; -} -static REG8 IOINPCALL cirrusvga_i51e1(UINT port) { - REG8 ret = cirrusvga_wab_51e1; - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - cirrusvga_setAutoWABID(); - } - //if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ - // ret = 0xC2; - //} - if (port == 0x51e1) { - return 0xff; - } - else { - return ret; - } -} -static void IOOUTCALL cirrusvga_o51e1(UINT port, REG8 dat) { - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - cirrusvga_setAutoWABID(); - } - cirrusvga_wab_51e1 = dat; - (void)port; - (void)dat; -} -static REG8 IOINPCALL cirrusvga_i5be1(UINT port) { - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - cirrusvga_setAutoWABID(); - } -// return 0xf7; // XXX: 0x08 is VRAM 4M flag? - if (np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F) { - cirrusvga_wab_5be1 |= 0x08; - } - return cirrusvga_wab_5be1; -} -//static void IOOUTCALL cirrusvga_o5be3(UINT port, REG8 dat) { -// if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ -// cirrusvga_setAutoWABID(); -// } -// (void)port; -// (void)dat; -//} - -static REG8 IOINPCALL cirrusvga_i40e1(UINT port) { - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || - (np2clvga.defgd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK && (np2clvga.gd54xxtype == CIRRUS_98ID_Xe10 || np2clvga.gd54xxtype == CIRRUS_98ID_PCI)){ // 強制変更を許す - cirrusvga_setAutoWABID(); - } - //cirrusvga_wab_40e1--; - //TRACEOUT(("CIRRUS VGA: out %04X d=%02X", port, cirrusvga_wab_40e1)); - return cirrusvga_wab_40e1; -} -static void IOOUTCALL cirrusvga_o40e1(UINT port, REG8 dat) { - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - cirrusvga_setAutoWABID(); - } - cirrusvga_wab_40e1 = dat; - - np2wab.relaystateint = (np2wab.relaystateint & ~0x1) | (cirrusvga_wab_40e1 & 0x1); - np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) - (void)port; - (void)dat; -} -static REG8 IOINPCALL cirrusvga_i42e1(UINT port) { - if ((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK) { - cirrusvga_setAutoWABID(); - } - return cirrusvga_wab_42e1; -} -static void IOOUTCALL cirrusvga_o42e1(UINT port, REG8 dat) { - if ((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK) { - cirrusvga_setAutoWABID(); - } - cirrusvga_wab_42e1 = dat; - cirrus_update_memory_access(cirrusvga); - (void)port; - (void)dat; -} -static REG8 IOINPCALL cirrusvga_i46e8(UINT port) { - REG8 ret = cirrusvga_wab_46e8; - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - cirrusvga_setAutoWABID(); - } - //np2wab.relaystateint = (np2wab.relaystateint & ~0x1) | (cirrusvga_wab_40e1 & 0x1); - //np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) - return ret; -} -static void IOOUTCALL cirrusvga_o46e8(UINT port, REG8 dat) { - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - cirrusvga_setAutoWABID(); - } - cirrusvga_wab_46e8 = dat; - (void)port; - (void)dat; -} - -//int cirrusvga_wab_52E2 = 0x18; -//static REG8 IOINPCALL cirrusvga_i52E2(UINT port) { -// REG8 ret = cirrusvga_wab_52E2; -// return ret; -//} -//static void IOOUTCALL cirrusvga_o52E2(UINT port, REG8 dat) { -// cirrusvga_wab_52E2 = dat; -// (void)port; -// (void)dat; -//} -//int cirrusvga_wab_56E2 = 0x80; -//static REG8 IOINPCALL cirrusvga_i56E2(UINT port) { -// REG8 ret = cirrusvga_wab_56E2; -// return ret; -//} -//static void IOOUTCALL cirrusvga_o56E2(UINT port, REG8 dat) { -// cirrusvga_wab_56E2 = dat; -// (void)port; -// (void)dat; -//} -//int cirrusvga_wab_59E2 = 0x18; -//static REG8 IOINPCALL cirrusvga_i59E2(UINT port) { -// REG8 ret = cirrusvga_wab_59E2; -// return ret; -//} -//static void IOOUTCALL cirrusvga_o59E2(UINT port, REG8 dat) { -// cirrusvga_wab_59E2 = dat; -// (void)port; -// (void)dat; -//} -//int cirrusvga_wab_5BE2 = 0x18; -//static REG8 IOINPCALL cirrusvga_i5BE2(UINT port) { -// REG8 ret = cirrusvga_wab_5BE2; -// return ret; -//} -//static void IOOUTCALL cirrusvga_o5BE2(UINT port, REG8 dat) { -// cirrusvga_wab_5BE2 = dat; -// (void)port; -// (void)dat; -//} - -static void vga_dumb_update_retrace_info(VGAState *s) -{ - (void) s; -} - -// MMIOウィンドウを設定する -void pc98_cirrus_setMMIOWindowAddr(){ - if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ - cirrus_mmio_read[0] = cirrus_mmio_readb_wab; - cirrus_mmio_read[1] = cirrus_mmio_readw_wab; - cirrus_mmio_read[2] = cirrus_mmio_readl_wab; - cirrus_mmio_write[0] = cirrus_mmio_writeb_wab; - cirrus_mmio_write[1] = cirrus_mmio_writew_wab; - cirrus_mmio_write[2] = cirrus_mmio_writel_wab; - }else if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC) { - cirrus_mmio_read[0] = cirrus_mmio_readb_wab; - cirrus_mmio_read[1] = cirrus_mmio_readw_wab; - cirrus_mmio_read[2] = cirrus_mmio_readl_wab; - cirrus_mmio_write[0] = cirrus_mmio_writeb_wab; - cirrus_mmio_write[1] = cirrus_mmio_writew_wab; - cirrus_mmio_write[2] = cirrus_mmio_writel_wab; - }else{ - cirrus_mmio_read[0] = cirrus_mmio_readb; - cirrus_mmio_read[1] = cirrus_mmio_readw; - cirrus_mmio_read[2] = cirrus_mmio_readl; - cirrus_mmio_write[0] = cirrus_mmio_writeb; - cirrus_mmio_write[1] = cirrus_mmio_writew; - cirrus_mmio_write[2] = cirrus_mmio_writel; - } -} - -void pc98_cirrus_vga_updatePCIaddr(){ - if((np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - pc98_cirrus_setMMIOWindowAddr(); - return; - } -#if defined(SUPPORT_PCI) - if((pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[0] & 0xfffffff0) != ~pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[0]){ - np2clvga.pciLFB_Addr = pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[0] & 0xfffffff0; - np2clvga.pciLFB_Mask = ~pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[0]; - - cirrusvga->map_addr = cirrusvga->map_end = 0; - cirrusvga->lfb_addr = np2clvga.pciLFB_Addr & TARGET_PAGE_MASK; - cirrusvga->lfb_end = ((np2clvga.pciLFB_Addr + cirrusvga->real_vram_size) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; - /* account for overflow */ - if (cirrusvga->lfb_end < np2clvga.pciLFB_Addr + cirrusvga->real_vram_size) - cirrusvga->lfb_end = np2clvga.pciLFB_Addr + cirrusvga->real_vram_size; - }else{ - np2clvga.pciLFB_Addr = 0; - } - if((pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[1] & 0xfffffff0) != ~pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[1]){ - np2clvga.pciMMIO_Addr = pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[1] & 0xfffffff0; - np2clvga.pciMMIO_Mask = ~pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[1]; - }else{ - np2clvga.pciMMIO_Addr = 0; - } - - pc98_cirrus_setMMIOWindowAddr(); - cirrus_update_memory_access(cirrusvga); -#endif -} - -// VRAMウィンドウアドレスをデフォルト値に設定する -void pc98_cirrus_vga_initVRAMWindowAddr(){ - np2clvga.pciLFB_Addr = 0; - np2clvga.pciLFB_Mask = 0; - np2clvga.pciMMIO_Addr = 0; - np2clvga.pciMMIO_Mask = 0; -#if defined(SUPPORT_PCI) - pcidev.devices[pcidev_cirrus_deviceid].enable = 0; -#endif - if(np2clvga.gd54xxtype == CIRRUS_98ID_Be){ - np2clvga.VRAMWindowAddr = 0; - np2clvga.VRAMWindowAddr2 = 0xf00000; - np2clvga.VRAMWindowAddr3 = 0; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ - np2clvga.VRAMWindowAddr = 0; - np2clvga.VRAMWindowAddr2 = 0xf00000; - np2clvga.VRAMWindowAddr3 = 0; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - np2clvga.VRAMWindowAddr = 0; - np2clvga.VRAMWindowAddr2 = 0; - np2clvga.VRAMWindowAddr3 = 0; -#if defined(SUPPORT_PCI) - pcidev.devices[pcidev_cirrus_deviceid].enable = 1; -#endif - pc98_cirrus_vga_updatePCIaddr(); - }else if(np2clvga.gd54xxtype <= 0xff){ - np2clvga.VRAMWindowAddr = 0; - np2clvga.VRAMWindowAddr2 = 0xf60000; - np2clvga.VRAMWindowAddr3 = 0; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ - np2clvga.VRAMWindowAddr = 0; - np2clvga.VRAMWindowAddr2 = 0xE0000; - np2clvga.VRAMWindowAddr3 = 0xF00000; - np2clvga.pciMMIO_Addr = 0xf10000; - np2clvga.pciMMIO_Mask = ~(0x10000-1); - }else if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC) { - np2clvga.VRAMWindowAddr = 0; - np2clvga.VRAMWindowAddr2 = 0xE0000; - np2clvga.VRAMWindowAddr3 = 0xF00000; - np2clvga.pciMMIO_Addr = 0xf10000; - np2clvga.pciMMIO_Mask = ~(0x10000-1); - }else{ - np2clvga.VRAMWindowAddr = 0; - np2clvga.VRAMWindowAddr2 = 0; - np2clvga.VRAMWindowAddr3 = 0; - if(np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI){ -#if defined(SUPPORT_PCI) - pcidev.devices[pcidev_cirrus_deviceid].enable = 1; -#endif - pc98_cirrus_vga_updatePCIaddr(); - } - } - pc98_cirrus_setMMIOWindowAddr(); - cirrus_update_memory_access(cirrusvga); -} - -// ボード種類からVRAMサイズを決定する -void pc98_cirrus_vga_setvramsize(){ -#if defined(SUPPORT_IA32_HAXM) - // PCIメモリ割り当て解除 - i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); - i386hax_vm_removememoryarea(vramptr, np2clvga.pciLFB_Addr, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); - lastlinmmio = 0; -#endif - - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ - cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ - cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_1MB; //(cirrusvga->device_id == CIRRUS_ID_CLGD5446) ? CIRRUS_VRAM_SIZE : CIRRUS_VRAM_SIZE; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_Be){ - cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_1MB; //(cirrusvga->device_id == CIRRUS_ID_CLGD5446) ? CIRRUS_VRAM_SIZE : CIRRUS_VRAM_SIZE; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_2MB; - }else if(np2clvga.gd54xxtype <= 0xff){ - cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE; //(cirrusvga->device_id == CIRRUS_ID_CLGD5446) ? CIRRUS_VRAM_SIZE : CIRRUS_VRAM_SIZE; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ - cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_WAB; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ - cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_2MB; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ - cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_4MB; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_GA98NBIC){ - cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_1MB; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_GA98NBII){ - cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_2MB; - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_GA98NBIV){ - cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_4MB; - }else{ - cirrusvga->real_vram_size = (cirrusvga->device_id == CIRRUS_ID_CLGD5446) ? CIRRUS_VRAM_SIZE : CIRRUS_VRAM_SIZE; - } - cirrusvga->vram_ptr = vramptr; - cirrusvga->vram_offset = 0; - cirrusvga->vram_size = cirrusvga->real_vram_size; - - /* XXX: s->vram_size must be a power of two */ - cirrusvga->cirrus_addr_mask = cirrusvga->real_vram_size - 1; - cirrusvga->linear_mmio_mask = cirrusvga->real_vram_size - 256; - -#if defined(SUPPORT_IA32_HAXM) - cirrus_linear_mmio_update(cirrusvga); -#endif -} -void pc98_cirrus_vga_setVRAMWindowAddr3(UINT32 addr) -{ - cirrusvga->sr[0x07] = (cirrusvga->sr[0x07] & 0x0f) | ((addr >> 16) & 0xf0); - cirrus_update_memory_access(cirrusvga); -} -static void pc98_cirrus_reset(CirrusVGAState * s, int device_id, int is_pci) -{ - //np2clvga.VRAMWindowAddr = (0x0F<<24); - //np2clvga.VRAMWindowAddr2 = (0xf20000); - - np2clvga.VRAMWindowAddr2 = 0; - np2clvga.VRAMWindowAddr3 = 0; - - pc98_cirrus_vga_initVRAMWindowAddr(); - - s->cirrus_rop = cirrus_bitblt_rop_nop; - - np2wab.relaystateext = 0; - np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); -#if defined(NP2_WINX) - ShowWindow(np2wabwnd.hWndWAB, SW_HIDE); // 設定変更対策 -#endif - - np2clvga.mmioenable = 0; - np2wab.paletteChanged = 1; -} -void pcidev_cirrus_cfgreg_w(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value){ - if(0x10 <= cfgregOffset && cfgregOffset < 0x28){ - pc98_cirrus_vga_initVRAMWindowAddr(); - } -} -static void pc98_cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci) -{ - int i; - - for(i = 0;i < 256; i++) - rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */ - rop_to_index[CIRRUS_ROP_0] = 0; - rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1; - rop_to_index[CIRRUS_ROP_NOP] = 2; - rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3; - rop_to_index[CIRRUS_ROP_NOTDST] = 4; - rop_to_index[CIRRUS_ROP_SRC] = 5; - rop_to_index[CIRRUS_ROP_1] = 6; - rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7; - rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8; - rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9; - rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10; - rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11; - rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12; - rop_to_index[CIRRUS_ROP_NOTSRC] = 13; - rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14; - rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15; - s->device_id = device_id; - s->bustype = CIRRUS_BUSTYPE_ISA; - - cirrusvga_wab_46e8 = 0x18; // デフォルトで有効 - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype <= 0xff){ - // ONBOARD -#if defined(SUPPORT_PCI) - if(pcidev.enable && (np2clvga.gd54xxtype == CIRRUS_98ID_PCI || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI)){ - // Cirrus CL-GD5446 PCI - ZeroMemory(pcidev.devices+pcidev_cirrus_deviceid, sizeof(_PCIDEVICE)); - pcidev.devices[pcidev_cirrus_deviceid].enable = 1; - pcidev.devices[pcidev_cirrus_deviceid].skipirqtbl = 1; - pcidev.devices[pcidev_cirrus_deviceid].regwfn = &pcidev_cirrus_cfgreg_w; - pcidev.devices[pcidev_cirrus_deviceid].header.vendorID = 0x1013; - pcidev.devices[pcidev_cirrus_deviceid].header.deviceID = CIRRUS_ID_CLGD5446; - pcidev.devices[pcidev_cirrus_deviceid].header.command = 0x0003;//0x0006;//;0x0003; - pcidev.devices[pcidev_cirrus_deviceid].header.status = 0x0000;//0x0000;//0x0280; - pcidev.devices[pcidev_cirrus_deviceid].header.revisionID = 0x00; - pcidev.devices[pcidev_cirrus_deviceid].header.classcode[0] = 0x00; // レジスタレベルプログラミングインタフェース - pcidev.devices[pcidev_cirrus_deviceid].header.classcode[1] = 0x00; // サブクラスコード - pcidev.devices[pcidev_cirrus_deviceid].header.classcode[2] = 0x03; // ベースクラスコード - pcidev.devices[pcidev_cirrus_deviceid].header.cachelinesize = 0; - pcidev.devices[pcidev_cirrus_deviceid].header.latencytimer = 0x00; - pcidev.devices[pcidev_cirrus_deviceid].header.headertype = 0; - pcidev.devices[pcidev_cirrus_deviceid].header.BIST = 0x00; - pcidev.devices[pcidev_cirrus_deviceid].header.subsysID = 0x0000; - pcidev.devices[pcidev_cirrus_deviceid].header.subsysventorID = 0x0000; - pcidev.devices[pcidev_cirrus_deviceid].header.interruptpin = 0xff; - pcidev.devices[pcidev_cirrus_deviceid].header.interruptline = 0x00; -#if defined(SUPPORT_IA32_HAXM) - pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[0] = 0xFC000000; - pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[1] = 0xFE000000; -#else - pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[0] = 0xF0000000; - pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[1] = 0xF2000000; -#endif - pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[0] = 0x02000000-1; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[1] = CIRRUS_PNPMMIO_SIZE-1; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[2] = 0xffffffff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[3] = 0xffffffff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[4] = 0xffffffff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[5] = 0xffffffff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.expROMbaseaddr = 0xffffffff; - pc98_cirrus_vga_initVRAMWindowAddr(); - s->bustype = CIRRUS_BUSTYPE_PCI; - - // ROM領域設定 - pcidev.devices[pcidev_cirrus_deviceid].headerrom.vendorID = 0xffff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.deviceID = 0xffff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.status = 0xffff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.command = 0xffdd; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.revisionID = 0xff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.classcode[0] = 0xff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.classcode[1] = 0xff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.classcode[2] = 0xff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.subsysID = 0xffff; - pcidev.devices[pcidev_cirrus_deviceid].headerrom.subsysventorID = 0xffff; - - for(i=0;i<16;i++){ - iocore_attachout(0x3c0 + i, vga_ioport_write_wrap); - iocore_attachinp(0x3c0 + i, vga_ioport_read_wrap); - } - - iocore_attachout(0x3b4, vga_ioport_write_wrap); - iocore_attachinp(0x3b4, vga_ioport_read_wrap); - iocore_attachout(0x3b5, vga_ioport_write_wrap); - iocore_attachinp(0x3b5, vga_ioport_read_wrap); - iocore_attachout(0x3ba, vga_ioport_write_wrap); - iocore_attachinp(0x3ba, vga_ioport_read_wrap); - iocore_attachout(0x3d4, vga_ioport_write_wrap); - iocore_attachinp(0x3d4, vga_ioport_read_wrap); - iocore_attachout(0x3d5, vga_ioport_write_wrap); - iocore_attachinp(0x3d5, vga_ioport_read_wrap); - iocore_attachout(0x3da, vga_ioport_write_wrap); - iocore_attachinp(0x3da, vga_ioport_read_wrap); - - pcidev_updateRoutingTable(); - } - if(np2clvga.gd54xxtype != CIRRUS_98ID_PCI) -#endif - { - iocore_attachout(0xfa2, cirrusvga_ofa2); - iocore_attachinp(0xfa2, cirrusvga_ifa2); - - iocore_attachout(0xfa3, cirrusvga_ofa3); - iocore_attachinp(0xfa3, cirrusvga_ifa3); - - iocore_attachout(0xfaa, cirrusvga_ofaa); - iocore_attachinp(0xfaa, cirrusvga_ifaa); - - iocore_attachout(0xfab, cirrusvga_ofab); - iocore_attachinp(0xfab, cirrusvga_ifab); - - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype == CIRRUS_98ID_96){ - iocore_attachout(0x0902, cirrusvga_off82); - iocore_attachinp(0x0902, cirrusvga_iff82); - - // XXX: 102Access Control Register 0904h は無視 - - for(i=0;i<16;i++){ - iocore_attachout(0xc50 + i, vga_ioport_write_wrap); // 0x3C0 to 0x3CF - iocore_attachinp(0xc50 + i, vga_ioport_read_wrap); // 0x3C0 to 0x3CF - } - - // この辺のマッピング本当にあってる? - iocore_attachout(0xb54, vga_ioport_write_wrap); // 0x3B4 - iocore_attachinp(0xb54, vga_ioport_read_wrap); // 0x3B4 - iocore_attachout(0xb55, vga_ioport_write_wrap); // 0x3B5 - iocore_attachinp(0xb55, vga_ioport_read_wrap); // 0x3B5 - - iocore_attachout(0xd54, vga_ioport_write_wrap); // 0x3D4 - iocore_attachinp(0xd54, vga_ioport_read_wrap); // 0x3D4 - iocore_attachout(0xd55, vga_ioport_write_wrap); // 0x3D5 - iocore_attachinp(0xd55, vga_ioport_read_wrap); // 0x3D5 - - iocore_attachout(0xb5a, vga_ioport_write_wrap); // 0x3BA - iocore_attachinp(0xb5a, vga_ioport_read_wrap); // 0x3BA - - iocore_attachout(0xd5a, vga_ioport_write_wrap); // 0x3DA - iocore_attachinp(0xd5a, vga_ioport_read_wrap); // 0x3DA - - //iocore_attachout(0x46E8, cirrusvga_o46e8); - //iocore_attachinp(0x46E8, cirrusvga_i46e8); - } - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype != CIRRUS_98ID_96){ - iocore_attachout(0xff82, cirrusvga_off82); - iocore_attachinp(0xff82, cirrusvga_iff82); - - //iocore_attachout(0x904, cirrusvga_o0904); - //iocore_attachinp(0x904, cirrusvga_i0904); - - for(i=0;i<16;i++){ - iocore_attachout(0xca0 + i, vga_ioport_write_wrap); // 0x3C0 to 0x3CF - iocore_attachinp(0xca0 + i, vga_ioport_read_wrap); // 0x3C0 to 0x3CF - } - - // この辺のマッピング本当にあってる? - iocore_attachout(0xba4, vga_ioport_write_wrap); // 0x3B4 - iocore_attachinp(0xba4, vga_ioport_read_wrap); // 0x3B4 - iocore_attachout(0xba5, vga_ioport_write_wrap); // 0x3B5 - iocore_attachinp(0xba5, vga_ioport_read_wrap); // 0x3B5 - - iocore_attachout(0xda4, vga_ioport_write_wrap); // 0x3D4 - iocore_attachinp(0xda4, vga_ioport_read_wrap); // 0x3D4 - iocore_attachout(0xda5, vga_ioport_write_wrap); // 0x3D5 - iocore_attachinp(0xda5, vga_ioport_read_wrap); // 0x3D5 - - iocore_attachout(0xbaa, vga_ioport_write_wrap); // 0x3BA - iocore_attachinp(0xbaa, vga_ioport_read_wrap); // 0x3BA - - iocore_attachout(0xdaa, vga_ioport_write_wrap); // 0x3DA - iocore_attachinp(0xdaa, vga_ioport_read_wrap); // 0x3DA - } - } - } - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype > 0xff){ - // WAB, WSN, GA-98NB - for(i=0;i<0x1000;i+=0x100){ - iocore_attachout(0x40E0 + cirrusvga_melcowab_ofs + i, vga_ioport_write_wrap); // 0x3C0 to 0x3CF - iocore_attachinp(0x40E0 + cirrusvga_melcowab_ofs + i, vga_ioport_read_wrap); // 0x3C0 to 0x3CF - } - - // この辺のマッピング本当にあってる? - // | - // V - // Odd Address:ボード制御,FM音源,PCM音源(Melco) - // Even Address:CIRRUS (Melco,IO-Data) - // モノクロは自信無し,WSN Win95ドライバは58e2h,59e2hをアクセスしてレジスタが - // ffhになっている(カラーモードなので)ことを確認している - //****************************************************** - // port <<= 8; - // port &= 0x7f00; /* Mask 0111 1111 0000 0000 */ - // port |= 0xE0; - //****************************************************** - - iocore_attachout(0x58E0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3B4 これは使っている - iocore_attachinp(0x58E0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3B4 これは使っている - iocore_attachout(0x59E0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3B5 これは使っている - iocore_attachinp(0x59E0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3B5 これは使っている - ////iocore_attachout(0x3AE0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3BA 使ってないからいいや - ////iocore_attachinp(0x3AE0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3BA 使ってないからいいや - - iocore_attachout(0x54E0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3D4 - iocore_attachinp(0x54E0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3D4 - iocore_attachout(0x55E0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3D5 - iocore_attachinp(0x55E0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3D5 - iocore_attachout(0x5AE0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3DA - iocore_attachinp(0x5AE0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3DA - - //if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ - // iocore_attachout(0x5BE3, cirrusvga_o5be3); - // iocore_attachinp(0x5BE3, cirrusvga_i5be3); - //} - -// iocore_attachout(0x51E1 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3BA -// iocore_attachinp(0x51E1 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3BA - -// iocore_attachout(0x57E1 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3DA -// iocore_attachinp(0x57E1 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3DA - - iocore_attachout(0x40E1 + cirrusvga_melcowab_ofs, cirrusvga_o40e1); - iocore_attachinp(0x40E1 + cirrusvga_melcowab_ofs, cirrusvga_i40e1); - - iocore_attachout(0x46E8, cirrusvga_o46e8); - iocore_attachinp(0x46E8, cirrusvga_i46e8); - - // WSN - if ((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F) { - iocore_attachout(0x51E1, cirrusvga_o51e1); // CHECK IO 空振り用 - iocore_attachinp(0x51E1, cirrusvga_i51e1); - iocore_attachout(0x51E3, cirrusvga_o51e1); // CHECK IO - iocore_attachinp(0x51E3, cirrusvga_i51e1); - - ////iocore_attachinp(0x59E0 + cirrusvga_melcowab_ofs, cirrusvga_i59e0); - iocore_attachinp(0x59E1 + cirrusvga_melcowab_ofs, cirrusvga_i59e1); // これがないとドライバがNGを返す - iocore_attachinp(0x5BE1 + cirrusvga_melcowab_ofs, cirrusvga_i5be1); - - iocore_attachout(0x42E1 + cirrusvga_melcowab_ofs, cirrusvga_o42e1); - iocore_attachinp(0x42E1 + cirrusvga_melcowab_ofs, cirrusvga_i42e1); - } - - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) != CIRRUS_98ID_AUTOMSK){ - np2clvga.VRAMWindowAddr2 = 0xE0000; - } - - //// GA-98NB - //if (np2clvga.gd54xxtype == CIRRUS_98ID_GA98NB) { - // np2clvga.VRAMWindowAddr2 = 0xf00000; - //} - - if (np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE10_WSN2 || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE10_WSN4 || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI) { - cirrusvga_wab_59e1 = 0x06; // この値じゃないとWSN Win95ドライバがNGを返す - cirrusvga_wab_51e1 = 0xC2; // WSN CHECK IO RETURN VALUE - cirrusvga_wab_5be1 = 0xf7; // bit3:0=4M,1=2M ?????? - cirrusvga_wab_40e1 = 0x7b; - cirrusvga_wab_42e1 = 0x00; - cirrusvga_wab_46e8 = 0x18; // 最初からON - }else if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI) { - memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); - cirrusvga_wab_59e1 = 0x06; // d.c. - cirrusvga_wab_51e1 = 0xC2; // d.c. - cirrusvga_wab_5be1 = 0xf7; // d.c. - cirrusvga_wab_40e1 = 0xC2; // bit1=0:DRAM REFRESH MODE?? とりあえず初期値はC2hじゃないとWin95ドライバはボードを認識しない - cirrusvga_wab_42e1 = 0x18; // 存在しない - cirrusvga_wab_46e8 = 0x10; - cirrusvga_updated = 1; - } - - //np2clvga.VRAMWindowAddr3 = 0xF00000; // XXX - //np2clvga.VRAMWindowAddr3size = 256*1024; - - //iocore_attachout(0x52E2, cirrusvga_o52E2); - //iocore_attachinp(0x52E2, cirrusvga_i52E2); - // - //iocore_attachout(0x56E2, cirrusvga_o56E2); - //iocore_attachinp(0x56E2, cirrusvga_i56E2); - //iocore_attachout(0x56E3, cirrusvga_o56E2); - //iocore_attachinp(0x56E3, cirrusvga_i56E2); - // - //iocore_attachout(0x59E2, cirrusvga_o59E2); - //iocore_attachinp(0x59E2, cirrusvga_i59E2); - //iocore_attachout(0x59E3, cirrusvga_o59E2); - //iocore_attachinp(0x59E3, cirrusvga_i59E2); - // - //iocore_attachout(0x58E2, cirrusvga_o5BE2); - //iocore_attachinp(0x58E2, cirrusvga_i5BE2); - //iocore_attachout(0x5BE2, cirrusvga_o5BE2); - //iocore_attachinp(0x5BE2, cirrusvga_i5BE2); - } - - pc98_cirrus_vga_setvramsize(); - - s->get_bpp = cirrus_get_bpp; - s->get_offsets = cirrus_get_offsets; - s->get_resolution = cirrus_get_resolution; - s->cursor_invalidate = cirrus_cursor_invalidate; - s->cursor_draw_line = cirrus_cursor_draw_line; - - s->update_retrace_info = vga_dumb_update_retrace_info; - s->retrace = vga_dumb_retrace; - - qemu_register_reset(cirrus_reset, s); - cirrus_reset(s); - cirrus_update_memory_access(s); - //register_savevm("cirrus_vga", 0, 2, cirrus_vga_save, cirrus_vga_load, s);// XXX: - //if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB || np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ - // //s->sr[0x06] = 0x12; // Unlock Cirrus extensions by default - //} - cirrusvga_updated = 1; -} -static void pc98_cirrus_deinit_common(CirrusVGAState * s, int device_id, int is_pci) -{ - int i; - - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype <= 0xff){ - // ONBOARD -#if defined(SUPPORT_PCI) - if(pcidev.enable && (np2clvga.gd54xxtype == CIRRUS_98ID_PCI || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI)){ - // Cirrus CL-GD5446 PCI - pcidev.devices[pcidev_cirrus_deviceid].enable = 0; - for(i=0;i<16;i++){ - iocore_detachout(0x3c0 + i); - iocore_detachinp(0x3c0 + i); - } - iocore_detachout(0x3b4); - iocore_detachinp(0x3b4); - iocore_detachout(0x3ba); - iocore_detachinp(0x3ba); - iocore_detachout(0x3d4); - iocore_detachinp(0x3d4); - iocore_detachout(0x3da); - iocore_detachinp(0x3da); - } - if(np2clvga.gd54xxtype != CIRRUS_98ID_PCI) -#endif - { - iocore_detachout(0xfa2); - iocore_detachinp(0xfa2); - - iocore_detachout(0xfa3); - iocore_detachinp(0xfa3); - - iocore_detachout(0xfaa); - iocore_detachinp(0xfaa); - - iocore_detachout(0xfab); - iocore_detachinp(0xfab); - - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype == CIRRUS_98ID_96){ - iocore_detachout(0x0902); - iocore_detachinp(0x0902); - - // XXX: 102Access Control Register 0904h は無視 - - for(i=0;i<16;i++){ - iocore_detachout(0xc50 + i); // 0x3C0 to 0x3CF - iocore_detachinp(0xc50 + i); // 0x3C0 to 0x3CF - } - - // この辺のマッピング本当にあってる? - iocore_detachout(0xb54); // 0x3B4 - iocore_detachinp(0xb54); // 0x3B4 - iocore_detachout(0xb55); // 0x3B5 - iocore_detachinp(0xb55); // 0x3B5 - - iocore_detachout(0xd54); // 0x3D4 - iocore_detachinp(0xd54); // 0x3D4 - iocore_detachout(0xd55); // 0x3D5 - iocore_detachinp(0xd55); // 0x3D5 - - iocore_detachout(0xb5a); // 0x3BA - iocore_detachinp(0xb5a); // 0x3BA - - iocore_detachout(0xd5a); // 0x3DA - iocore_detachinp(0xd5a); // 0x3DA - } - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype != CIRRUS_98ID_96){ - iocore_detachout(0xff82); - iocore_detachinp(0xff82); - - for(i=0;i<16;i++){ - iocore_detachout(0xca0 + i); // 0x3C0 to 0x3CF - iocore_detachinp(0xca0 + i); // 0x3C0 to 0x3CF - } - - // この辺のマッピング本当にあってる? - iocore_detachout(0xba4); // 0x3B4 - iocore_detachinp(0xba4); // 0x3B4 - iocore_detachout(0xba5); // 0x3B5 - iocore_detachinp(0xba5); // 0x3B5 - - iocore_detachout(0xda4); // 0x3D4 - iocore_detachinp(0xda4); // 0x3D4 - iocore_detachout(0xda5); // 0x3D5 - iocore_detachinp(0xda5); // 0x3D5 - - iocore_detachout(0xbaa); // 0x3BA - iocore_detachinp(0xbaa); // 0x3BA - - iocore_detachout(0xdaa); // 0x3DA - iocore_detachinp(0xdaa); // 0x3DA - -#ifdef SUPPORT_VGA_MODEX - if(np2cfg.usemodex){ - for(i=0;i<16;i++){ - iocore_attachout(0x3c0 + i, vga_ioport_write_wrap); - iocore_attachinp(0x3c0 + i, vga_ioport_read_wrap); - } - - iocore_attachout(0x3b4, vga_ioport_write_wrap); - iocore_attachinp(0x3b4, vga_ioport_read_wrap); - iocore_attachout(0x3b5, vga_ioport_write_wrap); - iocore_attachinp(0x3b5, vga_ioport_read_wrap); - iocore_attachout(0x3ba, vga_ioport_write_wrap); - iocore_attachinp(0x3ba, vga_ioport_read_wrap); - iocore_attachout(0x3d4, vga_ioport_write_wrap); - iocore_attachinp(0x3d4, vga_ioport_read_wrap); - iocore_attachout(0x3d5, vga_ioport_write_wrap); - iocore_attachinp(0x3d5, vga_ioport_read_wrap); - iocore_attachout(0x3da, vga_ioport_write_wrap); - iocore_attachinp(0x3da, vga_ioport_read_wrap); - } -#endif - } - } - } - if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype > 0xff){ - // WAB, WSN, GA-98NB - for(i=0;i<0x1000;i+=0x100){ - iocore_detachout(0x40E0 + cirrusvga_melcowab_ofs + i); // 0x3C0 to 0x3CF - iocore_detachinp(0x40E0 + cirrusvga_melcowab_ofs + i); // 0x3C0 to 0x3CF - } - - // この辺のマッピング本当にあってる? - iocore_detachout(0x58E0 + cirrusvga_melcowab_ofs); // 0x3B4 - iocore_detachinp(0x58E0 + cirrusvga_melcowab_ofs); // 0x3B4 - iocore_detachout(0x59E0 + cirrusvga_melcowab_ofs); // 0x3B5 - iocore_detachinp(0x59E0 + cirrusvga_melcowab_ofs); // 0x3B5 - ////iocore_detachout(0x3AE0 + cirrusvga_melcowab_ofs); // 0x3BA - ////iocore_detachinp(0x3AE0 + cirrusvga_melcowab_ofs); // 0x3BA - - iocore_detachout(0x54E0 + cirrusvga_melcowab_ofs); // 0x3D4 - iocore_detachinp(0x54E0 + cirrusvga_melcowab_ofs); // 0x3D4 - iocore_detachout(0x55E0 + cirrusvga_melcowab_ofs); // 0x3D5 - iocore_detachinp(0x55E0 + cirrusvga_melcowab_ofs); // 0x3D5 - iocore_detachout(0x5AE0 + cirrusvga_melcowab_ofs); // 0x3DA - iocore_detachinp(0x5AE0 + cirrusvga_melcowab_ofs); // 0x3DA - -// iocore_detachout(0x51E1 + cirrusvga_melcowab_ofs); // 0x3BA -// iocore_detachinp(0x51E1 + cirrusvga_melcowab_ofs); // 0x3BA - -// iocore_detachout(0x57E1 + cirrusvga_melcowab_ofs); // 0x3DA -// iocore_detachinp(0x57E1 + cirrusvga_melcowab_ofs); // 0x3DA - - iocore_detachout(0x40E1 + cirrusvga_melcowab_ofs); - iocore_detachinp(0x40E1 + cirrusvga_melcowab_ofs); - - iocore_detachout(0x46E8); - iocore_detachinp(0x46E8); - - iocore_detachout(0x51E1); - iocore_detachinp(0x51E1); - iocore_detachout(0x51E3); - iocore_detachinp(0x51E3); - - ////iocore_detachinp(0x59E0 + cirrusvga_melcowab_ofs); - iocore_detachinp(0x59E1 + cirrusvga_melcowab_ofs); - iocore_detachinp(0x5BE1 + cirrusvga_melcowab_ofs); - - iocore_detachinp(0x42E1 + cirrusvga_melcowab_ofs); - iocore_detachout(0x42E1 + cirrusvga_melcowab_ofs); - } -} - - -void pc98_cirrus_vga_init(void) -{ -#if defined(NP2_WIN) - HDC hdc; - UINT i; - WORD* PalIndexes; - //CirrusVGAState *s; - //HBITMAP hbmp; - //BOOL b; - - ga_bmpInfo = (BITMAPINFO*)calloc(1, sizeof(BITMAPINFO)+sizeof(WORD)*256); - PalIndexes = (WORD*)((char*)ga_bmpInfo + sizeof(BITMAPINFOHEADER)); - for (i = 0; i < 256; ++i) PalIndexes[i] = i; - - ga_bmpInfo_cursor = (BITMAPINFO*)calloc(1, sizeof(BITMAPINFO)); - -#if defined(SUPPORT_IA32_HAXM) - vramptr = (uint8_t*)_aligned_malloc(CIRRUS_VRAM_SIZE*2, 4096); // 2倍取っておく - vramptr_cmp = (uint8_t*)_aligned_malloc(CIRRUS_VRAM_SIZE * 2, 4096); // 2倍取っておく -#else - vramptr = (uint8_t*)malloc(CIRRUS_VRAM_SIZE*2); // 2倍取っておく -#endif - - ga_bmpInfo_cursor->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - ga_bmpInfo_cursor->bmiHeader.biPlanes = 1; - ga_bmpInfo_cursor->bmiHeader.biBitCount = 32; - ga_bmpInfo_cursor->bmiHeader.biCompression = BI_RGB; - ga_bmpInfo_cursor->bmiHeader.biWidth = 64; - ga_bmpInfo_cursor->bmiHeader.biHeight = 64; - ga_hbmp_cursor = CreateDIBSection(NULL, ga_bmpInfo_cursor, DIB_RGB_COLORS, (void **)(&cursorptr), NULL, 0); - hdc = GetDC(NULL); - ga_hdc_cursor = CreateCompatibleDC(hdc); - ReleaseDC(NULL, hdc); - SelectObject(ga_hdc_cursor, ga_hbmp_cursor); - - ds.surface = &np2vga_ds_surface; - ds.listeners = &np2vga_ds_listeners; - ds.mouse_set = np2vga_ds_mouse_set; - ds.cursor_define = np2vga_ds_cursor_define; - ds.next = NULL; - - ga_hFakeCursor = LoadCursor(NULL, IDC_ARROW); - -#else - vramptr = (uint8_t*)malloc(CIRRUS_VRAM_SIZE*2); // 2倍取っておく - - ds.surface = &np2vga_ds_surface; - ds.listeners = &np2vga_ds_listeners; - ds.mouse_set = np2vga_ds_mouse_set; - ds.cursor_define = np2vga_ds_cursor_define; - ds.next = NULL; -#endif - - if(cirrusvga_opaque){ - free(cirrusvga_opaque); - cirrusvga_opaque = cirrusvga = NULL; - } - - cirrusvga_opaque = cirrusvga = (CirrusVGAState*)calloc(1, sizeof(CirrusVGAState)); -} -void pc98_cirrus_vga_reset(const NP2CFG *pConfig) -{ - CirrusVGAState *s; - - np2clvga.enabled = np2cfg.usegd5430; - if(!np2clvga.enabled){ - TRACEOUT(("CL-GD54xx: Window Accelerator Disabled")); - return; - } - -#if defined(SUPPORT_IA32_HAXM) - if(!np2haxcore.allocwabmem){ - i386hax_vm_allocmemoryex(vramptr, CIRRUS_VRAM_SIZE*2); - np2haxcore.allocwabmem = 1; - } - mmio_mode = MMIO_MODE_MMIO; // 0==MMIO, 1==VRAM - mmio_mode_region1 = 0; // 0==MMIO, 1==VRAM - mmio_mode_region2 = 0; // 0==MMIO, 1==VRAM - lastlinmmio = 0; -#endif - -#if defined(SUPPORT_VGA_MODEX) - np2clvga.modex = 0; -#endif - np2clvga.defgd54xxtype = np2cfg.gd5430type; - np2clvga.gd54xxtype = np2cfg.gd5430type; - //np2clvga.defgd54xxtype = CIRRUS_98ID_PCI; - //np2clvga.gd54xxtype = CIRRUS_98ID_PCI; - - s = cirrusvga; - //memset(s, 0, sizeof(CirrusVGAState)); - if(np2clvga.gd54xxtype <= 0x57){ - pc98_cirrus_reset(s, CIRRUS_ID_CLGD5428, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ - pc98_cirrus_reset(s, CIRRUS_ID_CLGD5428, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - pc98_cirrus_reset(s, CIRRUS_ID_CLGD5446, 0); - }else if(np2clvga.gd54xxtype <= 0xff){ - pc98_cirrus_reset(s, CIRRUS_ID_CLGD5434, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ - pc98_cirrus_reset(s, CIRRUS_ID_CLGD5426, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ - pc98_cirrus_reset(s, CIRRUS_ID_CLGD5434, 0); - }else if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - pc98_cirrus_reset(s, CIRRUS_ID_CLGD5434, 0); - }else{ - pc98_cirrus_reset(s, CIRRUS_ID_CLGD5430, 0); - } - - cirrusvga_updated = 1; -} -void pc98_cirrus_vga_bind(void) -{ - CirrusVGAState *s; - if(!np2clvga.enabled){ - TRACEOUT(("CL-GD54xx: Window Accelerator Disabled")); - return; - } - if (np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE10_WSN2 || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE10_WSN4 || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI) { - cirrusvga_melcowab_ofs = 0x2; // WSNだけ2で固定 - } - else { - cirrusvga_melcowab_ofs = np2cfg.gd5430melofs; // WSN以外は自由選択可 - } - - s = cirrusvga; - //memset(s, 0, sizeof(CirrusVGAState)); - if(np2clvga.gd54xxtype <= 0x57){ - pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5428, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ - pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5428, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5446, 0); - }else if(np2clvga.gd54xxtype <= 0xff){ - pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ - pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5426, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ - pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5434, 0); - }else if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5434, 0); - }else{ - pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0); - } - s->ds = graphic_console_init(s->update, s->invalidate, s->screen_dump, s->text_update, s); - - np2wabwnd.drawframe = cirrusvga_drawGraphic; - -#if defined(NP2_WIN) - ga_bmpInfo->bmiHeader.biWidth = 0; - ga_bmpInfo->bmiHeader.biHeight = 0; -#endif - - TRACEOUT(("CL-GD54xx: Window Accelerator Enabled")); -} -void pc98_cirrus_vga_unbind(void) -{ - CirrusVGAState *s; - - s = cirrusvga; - if(np2clvga.gd54xxtype <= 0x57){ - pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5428, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ - pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5428, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ - pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5446, 0); - }else if(np2clvga.gd54xxtype <= 0xff){ - pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5430, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ - pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5426, 0); - }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ - pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5434, 0); - }else if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ - pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5434, 0); - }else{ - pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5430, 0); - } -} - -void pc98_cirrus_vga_shutdown(void) -{ - np2wabwnd.drawframe = NULL; -#if defined(NP2_WIN) - free(ga_bmpInfo_cursor); - free(ga_bmpInfo); -#endif -#if defined(SUPPORT_IA32_HAXM) -#if defined(NP2_WIN) - _aligned_free(vramptr); - _aligned_free(vramptr_cmp); -#else - free(vramptr); -#endif -#else - free(vramptr); -#endif -#if defined(NP2_WIN) - DeleteDC(ga_hdc_cursor); - DeleteObject(ga_hbmp_cursor); -#endif - if(cirrusvga_opaque){ - free(cirrusvga_opaque); - cirrusvga_opaque = cirrusvga = NULL; - } - //free(cursorptr); -} - -void pc98_cirrus_vga_resetresolution(void) -{ - if(!np2clvga.enabled) return; - - cirrusvga->cr[0x01] = 0; - cirrusvga->cr[0x12] = 0; - cirrusvga->cr[0x07] &= ~0x42; - // ついでにVRAMもクリア -// if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F) { - if (np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F) { - memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); - cirrusvga_wab_59e1 = 0x06; // この値じゃないとWSN Win95ドライバがNGを返す - cirrusvga_wab_51e1 = 0xC2; // WSN CHECK IO RETURN VALUE - cirrusvga_wab_5be1 = 0xf7; // bit3:0=4M,1=2M ?????? - cirrusvga_wab_40e1 = 0x7b; - cirrusvga_wab_42e1 = 0x00; - cirrusvga_wab_46e8 = 0x18; // 最初からON - }else if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC) { - memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); - cirrusvga_wab_59e1 = 0x06; // d.c. - cirrusvga_wab_51e1 = 0xC2; // d.c. - cirrusvga_wab_5be1 = 0xf7; // d.c. - cirrusvga_wab_40e1 = 0xC2; // bit1=0:DRAM REFRESH MODE?? とりあえず初期値はC2hじゃないとWin95ドライバはボードを認識しない - cirrusvga_wab_42e1 = 0x18; // 存在しない - cirrusvga_wab_46e8 = 0x10; - }else{ - memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); - cirrusvga_wab_46e8 = 0x18; - } -#if defined(SUPPORT_PCI) - // XXX: Win2000で動かすのに必要。理由は謎 - if(pcidev.enable && (np2clvga.gd54xxtype == CIRRUS_98ID_PCI || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || - np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI)){ - cirrusvga->msr = 0x03; - cirrusvga->sr[0x08] = 0xFE; - } -#endif - cirrusvga_updated = 1; -} - -// MELCO WAB系ポートならTRUE -int pc98_cirrus_isWABport(UINT port){ - if((port & 0xF0FF) == (0x40E0 + cirrusvga_melcowab_ofs)) return 1; - if (port == 0x58E0 + cirrusvga_melcowab_ofs) return 1; - if (port == 0x59E0 + cirrusvga_melcowab_ofs) return 1; - ////if (port == 0x3AE0 + cirrusvga_melcowab_ofs) return 1; - if (port == 0x54E0 + cirrusvga_melcowab_ofs) return 1; - if (port == 0x55E0 + cirrusvga_melcowab_ofs) return 1; - if (port == 0x5AE0 + cirrusvga_melcowab_ofs) return 1; - return 0; -} - -// MELCO WAB / I-O DATA GA-98NB 自動選択 レジスタ設定 -void pc98_cirrus_setWABreg(){ - CirrusVGAState *s; - - s = cirrusvga; - switch(np2clvga.gd54xxtype){ - case CIRRUS_98ID_WAB: - s->device_id = CIRRUS_ID_CLGD5426; - s->bustype = CIRRUS_BUSTYPE_ISA; - s->cr[0x27] = s->device_id; - s->sr[0x0F] = CIRRUS_MEMSIZE_1M; - s->sr[0x15] = 0x02; - break; - case CIRRUS_98ID_WSN_A2F: - s->device_id = CIRRUS_ID_CLGD5434; - s->bustype = CIRRUS_BUSTYPE_ISA; - s->cr[0x27] = s->device_id; - //s->sr[0x1F] = 0x2d; // MemClock - //s->gr[0x18] = 0x0f; // fastest memory configuration - s->sr[0x0f] = CIRRUS_MEMSIZE_2M; - //s->sr[0x17] = 0x20; - s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ - //s->sr[0x0F] = 0x20; - break; - case CIRRUS_98ID_WSN: // WSN-A4F - s->device_id = CIRRUS_ID_CLGD5434; - s->bustype = CIRRUS_BUSTYPE_ISA; - s->cr[0x27] = s->device_id; - //s->sr[0x1F] = 0x2d; // MemClock - //s->gr[0x18] = 0x0f; // fastest memory configuration - s->sr[0x0f] = CIRRUS_MEMSIZE_2M | CIRRUS_MEMFLAGS_BANKSWITCH; - //s->sr[0x17] = 0x20; - s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */ - //s->sr[0x0F] = 0x20; - break; - - case CIRRUS_98ID_GA98NBIC: - s->device_id = CIRRUS_ID_CLGD5434; - s->bustype = CIRRUS_BUSTYPE_ISA; - s->cr[0x27] = s->device_id; - s->sr[0x0f] = CIRRUS_MEMSIZE_1M; - s->sr[0x15] = 0x02; - break; - case CIRRUS_98ID_GA98NBII: - s->device_id = CIRRUS_ID_CLGD5434; - s->bustype = CIRRUS_BUSTYPE_ISA; - s->cr[0x27] = s->device_id; - s->sr[0x0f] = CIRRUS_MEMSIZE_2M; - s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ - break; - case CIRRUS_98ID_GA98NBIV: - s->device_id = CIRRUS_ID_CLGD5434; - s->bustype = CIRRUS_BUSTYPE_ISA; - s->cr[0x27] = s->device_id; - s->sr[0x0f] = CIRRUS_MEMSIZE_2M | CIRRUS_MEMFLAGS_BANKSWITCH; - s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */ - break; - } -} - -#endif + +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * Copyright (c) 2004 Makoto Suzuki (suzu) + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* + * Reference: Finn Thogersons' VGADOC4b + * available at http://home.worldonline.dk/~finth/ + */ + +/* + Neko Project 21/W 開発者のコメント: + ・元はQEMU/9821のコードですが強引に移植するためにあちこち削ったりしています + ・このファイルに関してはOS依存性は少ないはず(画面転送部分cirrusvga_drawGraphicだけOS依存・他のOS依存っぽいところは消してもたぶん害無し) + ・MMIOとかVRAMウィンドウとかリニアVRAMとかはcpumem.cで乗っ取っているのでそちらを参照 + ・16bit/32bit I/Oはiocore.cで乗っ取っているのでそちらを参照 + ・VRAM画面はcirrusvga->vram_ptrに、パレットはcirrusvga->paletteに入ってます + ・転送の仕方はcirrusvga_drawGraphicを参考に(自分もよく分かってないけど) + ・細かいところはQEMU/9821の同名ファイルを参照 +*/ + +#include + + +#if defined(SUPPORT_CL_GD5430) + +#include +#include +#include +#include "cirrus_vga.h" +#include "vga_int.h" +#include +#include +#include +#include +#include + +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif + +#if defined(NP2_X) +#include +#include +#endif + +//#if 1 +//#undef TRACEOUT +//#define USE_TRACEOUT_VS +////#define MEM_BDA_TRACEOUT +////#define MEM_D8_TRACEOUT +//#ifdef USE_TRACEOUT_VS +//static void trace_fmt_ex(const char *fmt, ...) +//{ +// char stmp[2048]; +// va_list ap; +// va_start(ap, fmt); +// vsprintf(stmp, fmt, ap); +// strcat(stmp, "¥n"); +// va_end(ap); +// OutputDebugStringA(stmp); +//} +//#define TRACEOUT(s) trace_fmt_ex s +//#else +//#define TRACEOUT(s) (void)(s) +//#endif +//#endif /* 1 */ +/* force some bits to zero */ +const uint8_t sr_mask[8] = { + (uint8_t)~0xfc, + (uint8_t)~0xc2, + (uint8_t)~0x00, // np21w ver0.86 rev29 (uint8_t)~0xf0, 上位ビットも残さないとWin9xで文字表示がおかしくなる + (uint8_t)~0xc0, + (uint8_t)~0xf1, + (uint8_t)~0xff, + (uint8_t)~0xff, + (uint8_t)~0x00, +}; + +const uint8_t gr_mask[16] = { + (uint8_t)~0xf0, /* 0x00 */ + (uint8_t)~0xf0, /* 0x01 */ + (uint8_t)~0xf0, /* 0x02 */ + (uint8_t)~0xe0, /* 0x03 */ + (uint8_t)~0xfc, /* 0x04 */ + (uint8_t)~0x84, /* 0x05 */ + (uint8_t)~0xf0, /* 0x06 */ + (uint8_t)~0xf0, /* 0x07 */ + (uint8_t)~0x00, /* 0x08 */ + (uint8_t)~0xff, /* 0x09 */ + (uint8_t)~0xff, /* 0x0a */ + (uint8_t)~0xff, /* 0x0b */ + (uint8_t)~0xff, /* 0x0c */ + (uint8_t)~0xff, /* 0x0d */ + (uint8_t)~0xff, /* 0x0e */ + (uint8_t)~0xff, /* 0x0f */ +}; + +int pcidev_cirrus_deviceid = 10; + +// 内蔵アクセラレータ用 +REG8 cirrusvga_regindexA2 = 0; // I/OポートFA2hで指定されているレジスタ番号 +REG8 cirrusvga_regindex = 0; // I/OポートFAAhで指定されているレジスタ番号 + +// WAB, WSN用 +int cirrusvga_wab_59e1 = 0x06; // この値じゃないとWSN Win95ドライバがNGを返す +int cirrusvga_wab_51e1 = 0xC2; // WSN CHECK IO RETURN VALUE +int cirrusvga_wab_5be1 = 0xf7; // bit3:0=4M,1=2M ?????? +int cirrusvga_wab_40e1 = 0x7b; +int cirrusvga_wab_42e1 = 0x00; +//int cirrusvga_wab_0fe1 = 0xC2; +int cirrusvga_wab_46e8 = 0x18; +int cirrusvga_melcowab_ofs = CIRRUS_MELCOWAB_OFS_DEFAULT; + +NP2CLVGA np2clvga = {0}; +void *cirrusvga_opaque = NULL; // CIRRUS VGAの変数をグローバルアクセス出来るようにしておく・・・(良くない実装) +UINT8 cirrusvga_statsavebuf[CIRRUS_VRAM_SIZE_4MB + 1024 * 1024]; // ステートセーブ用のバッファ(無駄が多いけど互換性は保ちやすいはず) + +int g_cirrus_linear_map_enabled = 0; // CIRRUS VGAの変数のリニアメモリアクセス(cpumem.cのmemp_*)有効フラグ +CPUWriteMemoryFunc *g_cirrus_linear_write[3] = {0}; // CIRRUS VGAの変数のリニアメモリアクセスWRITEで呼ばれる関数([0]=8bit, [0]=16bit, [0]=32bit) + +uint8_t* vramptr; // CIRRUS VGAのVRAMへのポインタ(メモリサイズはCIRRUS_VRAM_SIZEで十分のはずだが念のため2倍確保されている) +uint8_t* cursorptr; // CIRRUS VGAのカーソル画像バッファへのポインタ +#if defined(SUPPORT_IA32_HAXM) +uint8_t* vramptr_cmp; // メモリ更新を検出するためのvramptrのコピー +#endif + +DisplayState ds = {0}; // np21/wでは実質的に使われない + +#if defined(NP2_WIN) +BITMAPINFO *ga_bmpInfo; // CIRRUS VGAのVRAM映像を転送する時に使うBITMAPINFO構造体 +BITMAPINFO *ga_bmpInfo_cursor; // CIRRUS VGAのカーソル画像を転送する時に使うBITMAPINFO構造体 +HBITMAP ga_hbmp_cursor; // CIRRUS VGAのカーソルのHBITMAP +HDC ga_hdc_cursor; // CIRRUS VGAのカーソル画像のHDC + +static HCURSOR ga_hFakeCursor = NULL; // ハードウェアカーソル(仮)CIRRUS VGAのカーソル画像が上手く表示出来ない場合用 +#endif + +#if defined(SUPPORT_IA32_HAXM) +#define MMIO_MODE_MMIO 0 +#define MMIO_MODE_VRAM1 1 +#define MMIO_MODE_VRAM2 2 +int mmio_mode = MMIO_MODE_MMIO; // 0==MMIO, 1==VRAM +UINT32 mmio_mode_region1 = 0; // 0==MMIO, 1==VRAM +UINT32 mmio_mode_region2 = 0; // 0==MMIO, 1==VRAM +UINT8 lastlinmmio = 0; +#endif + +void pcidev_cirrus_cfgreg_w(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value); +void pc98_cirrus_setWABreg(void); +static void cirrusvga_setAutoWABID(void); + +// QEMUで使われているけどよく分からなかったので無視されている関数や変数達(ォィ +static void cpu_register_physical_memory(target_phys_addr_t start_addr, ram_addr_t size, ram_addr_t phys_offset){ +} +void np2vga_ds_dpy_update(struct DisplayState *s, int x, int y, int w, int h) +{ +} +void np2vga_ds_dpy_resize(struct DisplayState *s) +{ +} +void np2vga_ds_dpy_setdata(struct DisplayState *s) +{ +} +void np2vga_ds_dpy_refresh(struct DisplayState *s) +{ +} +void np2vga_ds_dpy_copy(struct DisplayState *s, int src_x, int src_y, + int dst_x, int dst_y, int w, int h) +{ +} +void np2vga_ds_dpy_fill(struct DisplayState *s, int x, int y, + int w, int h, uint32_t_ c) +{ +} +void np2vga_ds_dpy_text_cursor(struct DisplayState *s, int x, int y) +{ +} +DisplaySurface np2vga_ds_surface = {0}; +DisplayChangeListener np2vga_ds_listeners = {0, 0, np2vga_ds_dpy_update, np2vga_ds_dpy_resize, + np2vga_ds_dpy_setdata, np2vga_ds_dpy_refresh, + np2vga_ds_dpy_copy, np2vga_ds_dpy_fill, + np2vga_ds_dpy_text_cursor, NULL}; +void np2vga_ds_mouse_set(int x, int y, int on){ +} +void np2vga_ds_cursor_define(int width, int height, int bpp, int hot_x, int hot_y, + uint8_t *image, uint8_t *mask){ +} + +DisplayState *graphic_console_init(vga_hw_update_ptr update, + vga_hw_invalidate_ptr invalidate, + vga_hw_screen_dump_ptr screen_dump, + vga_hw_text_update_ptr text_update, + void *opaque) +{ + ds.opaque = opaque; + np2vga_ds_surface.width = 640; + np2vga_ds_surface.height = 480; + np2vga_ds_surface.pf.bits_per_pixel = 32; + np2vga_ds_surface.pf.bytes_per_pixel = 4; + + return &ds; +} + +/*************************************** + * + * definitions + * + ***************************************/ + +#define qemu_MIN(a,b) ((a) < (b) ? (a) : (b)) + +// ID +#define CIRRUS_ID_CLGD5422 (0x23<<2) +#define CIRRUS_ID_CLGD5426 (0x24<<2) +#define CIRRUS_ID_CLGD5424 (0x25<<2) +#define CIRRUS_ID_CLGD5428 (0x26<<2) +#define CIRRUS_ID_CLGD5430 (0x28<<2) +#define CIRRUS_ID_CLGD5434 (0x2A<<2) +#define CIRRUS_ID_CLGD5436 (0x2B<<2) +#define CIRRUS_ID_CLGD5440 (0x2C<<2) +#define CIRRUS_ID_CLGD5446 (0x2E<<2) + +// sequencer 0x07 +#define CIRRUS_SR7_BPP_VGA 0x00 +#define CIRRUS_SR7_BPP_SVGA 0x01 +#define CIRRUS_SR7_BPP_MASK 0x0e +#define CIRRUS_SR7_BPP_8 0x00 +#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02 +#define CIRRUS_SR7_BPP_24 0x04 +#define CIRRUS_SR7_BPP_16 0x06 +#define CIRRUS_SR7_BPP_32 0x08 +//#define CIRRUS_SR7_ISAADDR_MASK 0xe0 +#define CIRRUS_SR7_ISAADDR_MASK 0xf0 + +// sequencer 0x0f +#define CIRRUS_MEMSIZE_512k 0x08 +#define CIRRUS_MEMSIZE_1M 0x10 +#define CIRRUS_MEMSIZE_2M 0x18 +#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled. + +// sequencer 0x12 +#define CIRRUS_CURSOR_SHOW 0x01 +#define CIRRUS_CURSOR_HIDDENPEL 0x02 +#define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear + +// sequencer 0x17 +#define CIRRUS_BUSTYPE_VLBFAST 0x10 +#define CIRRUS_BUSTYPE_PCI 0x20 +#define CIRRUS_BUSTYPE_VLBSLOW 0x30 +#define CIRRUS_BUSTYPE_ISA 0x38 +#define CIRRUS_MMIO_ENABLE 0x04 +#define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared. +#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80 + +// control 0x0b +#define CIRRUS_BANKING_DUAL 0x01 +#define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k + +// control 0x30 +#define CIRRUS_BLTMODE_BACKWARDS 0x01 +#define CIRRUS_BLTMODE_MEMSYSDEST 0x02 +#define CIRRUS_BLTMODE_MEMSYSSRC 0x04 +#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08 +#define CIRRUS_BLTMODE_PATTERNCOPY 0x40 +#define CIRRUS_BLTMODE_COLOREXPAND 0x80 +#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30 +#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00 +#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10 +#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 +#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 + +// control 0x31 +#define CIRRUS_BLT_BUSY 0x01 +#define CIRRUS_BLT_START 0x02 +#define CIRRUS_BLT_RESET 0x04 +#define CIRRUS_BLT_FIFOUSED 0x10 +#define CIRRUS_BLT_AUTOSTART 0x80 + +// control 0x32 +#define CIRRUS_ROP_0 0x00 +#define CIRRUS_ROP_SRC_AND_DST 0x05 +#define CIRRUS_ROP_NOP 0x06 +#define CIRRUS_ROP_SRC_AND_NOTDST 0x09 +#define CIRRUS_ROP_NOTDST 0x0b +#define CIRRUS_ROP_SRC 0x0d +#define CIRRUS_ROP_1 0x0e +#define CIRRUS_ROP_NOTSRC_AND_DST 0x50 +#define CIRRUS_ROP_SRC_XOR_DST 0x59 +#define CIRRUS_ROP_SRC_OR_DST 0x6d +#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90 +#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95 +#define CIRRUS_ROP_SRC_OR_NOTDST 0xad +#define CIRRUS_ROP_NOTSRC 0xd0 +#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6 +#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda + +#define CIRRUS_ROP_NOP_INDEX 2 +#define CIRRUS_ROP_SRC_INDEX 5 + +// control 0x33 +#define CIRRUS_BLTMODEEXT_BLTSYNCDISP 0x10 +#define CIRRUS_BLTMODEEXT_BGNDONLYCLIP 0x08 +#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 +#define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02 +#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 + +// memory-mapped IO +#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword +#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword +#define CIRRUS_MMIO_BLTWIDTH 0x08 // word +#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word +#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word +#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word +#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword +#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword +#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte +#define CIRRUS_MMIO_BLTMODE 0x18 // byte +#define CIRRUS_MMIO_BLTROP 0x1a // byte +#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte +#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c // word? +#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word? +#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24 // word +#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26 // word +#define CIRRUS_MMIO_LINEARDRAW_END_X 0x28 // word +#define CIRRUS_MMIO_LINEARDRAW_END_Y 0x2a // word +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c // byte +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d // byte +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e // byte +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f // byte +#define CIRRUS_MMIO_BRESENHAM_K1 0x30 // word +#define CIRRUS_MMIO_BRESENHAM_K3 0x32 // word +#define CIRRUS_MMIO_BRESENHAM_ERROR 0x34 // word +#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36 // word +#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38 // byte +#define CIRRUS_MMIO_LINEDRAW_MODE 0x39 // byte +#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte + +// PCI 0x02: device +#define PCI_DEVICE_CLGD5462 0x00d0 +#define PCI_DEVICE_CLGD5465 0x00d6 + +// PCI 0x04: command(word), 0x06(word): status +#define PCI_COMMAND_IOACCESS 0x0001 +#define PCI_COMMAND_MEMACCESS 0x0002 +#define PCI_COMMAND_BUSMASTER 0x0004 +#define PCI_COMMAND_SPECIALCYCLE 0x0008 +#define PCI_COMMAND_MEMWRITEINVALID 0x0010 +#define PCI_COMMAND_PALETTESNOOPING 0x0020 +#define PCI_COMMAND_PARITYDETECTION 0x0040 +#define PCI_COMMAND_ADDRESSDATASTEPPING 0x0080 +#define PCI_COMMAND_SERR 0x0100 +#define PCI_COMMAND_BACKTOBACKTRANS 0x0200 +// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev) +#define PCI_CLASS_BASE_DISPLAY 0x03 +// PCI 0x08, 0x00ff0000 +#define PCI_CLASS_SUB_VGA 0x00 +// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test) +#define PCI_CLASS_HEADERTYPE_00h 0x00 +// 0x10-0x3f (headertype 00h) +// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers +// 0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x) +#define PCI_MAP_MEM 0x0 +#define PCI_MAP_IO 0x1 +#define PCI_MAP_MEM_ADDR_MASK (~0xf) +#define PCI_MAP_IO_ADDR_MASK (~0x3) +#define PCI_MAP_MEMFLAGS_32BIT 0x0 +#define PCI_MAP_MEMFLAGS_32BIT_1M 0x1 +#define PCI_MAP_MEMFLAGS_64BIT 0x4 +#define PCI_MAP_MEMFLAGS_CACHEABLE 0x8 +// PCI 0x28: cardbus CIS pointer +// PCI 0x2c: subsystem vendor id, 0x2e: subsystem id +// PCI 0x30: expansion ROM base address +#define PCI_ROMBIOS_ENABLED 0x1 +// PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer +// PCI 0x38: reserved +// PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat + +#define CIRRUS_PNPMMIO_SIZE 0x1000 + + +/* I/O and memory hook */ +#define CIRRUS_HOOK_NOT_HANDLED 0 +#define CIRRUS_HOOK_HANDLED 1 + +#define ABS(a) ((signed)(a) > 0 ? a : -a) + +// XXX: WAB系をとりあえず使えるようにするために4MB VRAMサイズまで書き込み許可 +#define BLTUNSAFE_DST(s) \ + ( /* check dst is within bounds */ \ + ((s)->cirrus_blt_dstpitch >= 0) ? /* ピッチの正負を確認 */ \ + ((s)->cirrus_blt_height * (s)->cirrus_blt_dstpitch + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > CIRRUS_VRAM_SIZE_4MB) : /* ピッチが正の時、VRAM最大を超えないか確認 */ \ + (((s)->cirrus_blt_height-1) * -(s)->cirrus_blt_dstpitch > ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask)) /* ピッチが負の時、0未満にならないか確認 */ \ + ) +#define BLTUNSAFE_SRC(s) \ + ( /* check src is within bounds */ \ + ((s)->cirrus_blt_srcpitch >= 0) ? /* ピッチの正負を確認 */ \ + ((s)->cirrus_blt_height * (s)->cirrus_blt_srcpitch + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > CIRRUS_VRAM_SIZE_4MB) : /* ピッチが正の時、VRAM最大を超えないか確認 */ \ + (((s)->cirrus_blt_height-1) * -(s)->cirrus_blt_srcpitch > ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask)) /* ピッチが負の時、0未満にならないか確認 */ \ + ) +#define BLTUNSAFE(s) \ + ( \ + BLTUNSAFE_DST(s) || BLTUNSAFE_SRC(s) \ + ) +// SRC未使用なら1 +#define BLTUNSAFE_NOSRC(s) \ + ( \ + rop_to_index[(s)->gr[0x32]]==0 || rop_to_index[(s)->gr[0x32]]==2 || rop_to_index[(s)->gr[0x32]]==4 || rop_to_index[(s)->gr[0x32]]==6 \ + ) +//#define BLTUNSAFE(s) \ +// ( \ +// ( /* check dst is within bounds */ \ +// (s)->cirrus_blt_height * ABS((s)->cirrus_blt_dstpitch) \ +// + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \ +// (s)->vram_size \ +// ) || \ +// ( /* check src is within bounds */ \ +// (s)->cirrus_blt_height * ABS((s)->cirrus_blt_srcpitch) \ +// + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \ +// (s)->vram_size \ +// ) \ +// ) + +struct CirrusVGAState; +typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s, + uint8_t * dst, const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight); +typedef void (*cirrus_fill_t)(struct CirrusVGAState *s, + uint8_t *dst, int dst_pitch, int width, int height); + +static int cirrusvga_updated = 1; + +typedef struct CirrusVGAState { + VGA_STATE_COMMON + + int cirrus_linear_io_addr; + int cirrus_linear_bitblt_io_addr; + int cirrus_mmio_io_addr; + uint32_t_ cirrus_addr_mask; + uint32_t_ linear_mmio_mask; + uint8_t cirrus_shadow_gr0; + uint8_t cirrus_shadow_gr1; + uint8_t cirrus_hidden_dac_lockindex; + uint8_t cirrus_hidden_dac_data; + uint32_t_ cirrus_bank_base[2]; + uint32_t_ cirrus_bank_limit[2]; + uint8_t cirrus_hidden_palette[48]; + uint32_t_ hw_cursor_x; + uint32_t_ hw_cursor_y; + int cirrus_blt_pixelwidth; + int cirrus_blt_width; + int cirrus_blt_height; + int cirrus_blt_dstpitch; + int cirrus_blt_srcpitch; + uint32_t_ cirrus_blt_fgcol; + uint32_t_ cirrus_blt_bgcol; + uint32_t_ cirrus_blt_dstaddr; + uint32_t_ cirrus_blt_srcaddr; + uint8_t cirrus_blt_mode; + uint8_t cirrus_blt_modeext; + cirrus_bitblt_rop_t cirrus_rop; +#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */ + uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE]; + uint8_t *cirrus_srcptr; + uint8_t *cirrus_srcptr_end; + uint32_t_ cirrus_srccounter; + /* hwcursor display state */ + int last_hw_cursor_size; + int last_hw_cursor_x; + int last_hw_cursor_y; + int last_hw_cursor_y_start; + int last_hw_cursor_y_end; + int real_vram_size; /* XXX: suppress that */ + //CPUWriteMemoryFunc **cirrus_linear_write; + int device_id; + int bustype; + uint8_t videowindow_dblbuf_index; + uint8_t graphics_dblbuf_index; +} CirrusVGAState; + +CirrusVGAState *cirrusvga = NULL; + +#define CIRRUS_FMC_W 16 +#define CIRRUS_FMC_H 32 + +UINT8 FakeMouseCursorData[CIRRUS_FMC_W * CIRRUS_FMC_H] = { + // 0:transparent 1:black 2:white + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 1, 2, 2, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 1, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0 +}; + +static uint8_t vga_dumb_retrace(VGAState *s) +{ + return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE); +} + +static uint8_t rop_to_index[256]; + +typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b); +#define NB_DEPTHS 7 + +static unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, + unsigned int b) +{ + return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6); +} + +static unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, + unsigned int b) +{ + return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); +} + +static unsigned int rgb_to_pixel15bgr(unsigned int r, unsigned int g, + unsigned int b) +{ + return ((b >> 3) << 10) | ((g >> 3) << 5) | (r >> 3); +} + +static unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, + unsigned int b) +{ + return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); +} + +static unsigned int rgb_to_pixel16bgr(unsigned int r, unsigned int g, + unsigned int b) +{ + return ((b >> 3) << 11) | ((g >> 2) << 5) | (r >> 3); +} + +static unsigned int rgb_to_pixel24(unsigned int r, unsigned int g, + unsigned int b) +{ + return (r << 16) | (g << 8) | b; +} + +static unsigned int rgb_to_pixel24bgr(unsigned int r, unsigned int g, + unsigned int b) +{ + return (b << 16) | (g << 8) | r; +} + +static unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, + unsigned int b) +{ + return (r << 16) | (g << 8) | b; +} + +static unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, + unsigned int b) +{ + return (b << 16) | (g << 8) | r; +} + +static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel8(r, g, b); + col |= col << 8; + col |= col << 16; + return col; +} + +static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel15(r, g, b); + col |= col << 16; + return col; +} + +static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g, + unsigned int b) +{ + unsigned int col; + col = rgb_to_pixel15bgr(r, g, b); + col |= col << 16; + return col; +} + +static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel16(r, g, b); + col |= col << 16; + return col; +} + +static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g, + unsigned int b) +{ + unsigned int col; + col = rgb_to_pixel16bgr(r, g, b); + col |= col << 16; + return col; +} + +static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel32(r, g, b); + return col; +} + +static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel32bgr(r, g, b); + return col; +} + + +static int ds_get_linesize(DisplayState *ds) +{ + return np2wab.realWidth*4; +} + +static uint8_t* ds_get_data(DisplayState *ds) +{ + return ds->surface->data; +} + +static int ds_get_width(DisplayState *ds) +{ + return np2wab.realWidth;//ds->surface->width; +} + +static int ds_get_height(DisplayState *ds) +{ + return np2wab.realHeight;//ds->surface->height; +} + +static int ds_get_bits_per_pixel(DisplayState *ds) +{ + return 32;//ds->surface->pf.bits_per_pixel; +} + +static int ds_get_bytes_per_pixel(DisplayState *ds) +{ + return 4;//ds->surface->pf.bytes_per_pixel; +} + +static void dpy_update(DisplayState *s, int x, int y, int w, int h) +{ + struct DisplayChangeListener *dcl = s->listeners; + while (dcl != NULL) { + dcl->dpy_update(s, x, y, w, h); + dcl = dcl->next; + } +} + +static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = { + rgb_to_pixel8_dup, + rgb_to_pixel15_dup, + rgb_to_pixel16_dup, + rgb_to_pixel32_dup, + rgb_to_pixel32bgr_dup, + rgb_to_pixel15bgr_dup, + rgb_to_pixel16bgr_dup, +}; + +/*************************************** + * + * prototypes. + * + ***************************************/ + +static void cirrus_bitblt_dblbufferswitch(); +static void cirrus_bitblt_reset(CirrusVGAState *s); +static void cirrus_update_memory_access(CirrusVGAState *s); + +/*************************************** + * + * raster operations + * + ***************************************/ + +static void cirrus_bitblt_rop_nop(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ +} + +static void cirrus_bitblt_fill_nop(CirrusVGAState *s, + uint8_t *dst, + int dstpitch, int bltwidth,int bltheight) +{ +} + +#define ROP_NAME 0 +#define ROP_OP(d, s) d = 0 +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_and_dst +#define ROP_OP(d, s) d = (s) & (d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_and_notdst +#define ROP_OP(d, s) d = (s) & (~(d)) +#include "cirrus_vga_rop.h" + +#define ROP_NAME notdst +#define ROP_OP(d, s) d = ~(d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src +#define ROP_OP(d, s) d = s +#include "cirrus_vga_rop.h" + +#define ROP_NAME 1 +#define ROP_OP(d, s) d = ~0 +#include "cirrus_vga_rop.h" + +#define ROP_NAME notsrc_and_dst +#define ROP_OP(d, s) d = (~(s)) & (d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_xor_dst +#define ROP_OP(d, s) d = (s) ^ (d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_or_dst +#define ROP_OP(d, s) d = (s) | (d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME notsrc_or_notdst +#define ROP_OP(d, s) d = (~(s)) | (~(d)) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_notxor_dst +#define ROP_OP(d, s) d = ~((s) ^ (d)) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_or_notdst +#define ROP_OP(d, s) d = (s) | (~(d)) +#include "cirrus_vga_rop.h" + +#define ROP_NAME notsrc +#define ROP_OP(d, s) d = (~(s)) +#include "cirrus_vga_rop.h" + +#define ROP_NAME notsrc_or_dst +#define ROP_OP(d, s) d = (~(s)) | (d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME notsrc_and_notdst +#define ROP_OP(d, s) d = (~(s)) & (~(d)) +#include "cirrus_vga_rop.h" + +static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = { + cirrus_bitblt_rop_fwd_0, + cirrus_bitblt_rop_fwd_src_and_dst, + cirrus_bitblt_rop_nop, + cirrus_bitblt_rop_fwd_src_and_notdst, + cirrus_bitblt_rop_fwd_notdst, + cirrus_bitblt_rop_fwd_src, + cirrus_bitblt_rop_fwd_1, + cirrus_bitblt_rop_fwd_notsrc_and_dst, + cirrus_bitblt_rop_fwd_src_xor_dst, + cirrus_bitblt_rop_fwd_src_or_dst, + cirrus_bitblt_rop_fwd_notsrc_or_notdst, + cirrus_bitblt_rop_fwd_src_notxor_dst, + cirrus_bitblt_rop_fwd_src_or_notdst, + cirrus_bitblt_rop_fwd_notsrc, + cirrus_bitblt_rop_fwd_notsrc_or_dst, + cirrus_bitblt_rop_fwd_notsrc_and_notdst, +}; + +static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = { + cirrus_bitblt_rop_bkwd_0, + cirrus_bitblt_rop_bkwd_src_and_dst, + cirrus_bitblt_rop_nop, + cirrus_bitblt_rop_bkwd_src_and_notdst, + cirrus_bitblt_rop_bkwd_notdst, + cirrus_bitblt_rop_bkwd_src, + cirrus_bitblt_rop_bkwd_1, + cirrus_bitblt_rop_bkwd_notsrc_and_dst, + cirrus_bitblt_rop_bkwd_src_xor_dst, + cirrus_bitblt_rop_bkwd_src_or_dst, + cirrus_bitblt_rop_bkwd_notsrc_or_notdst, + cirrus_bitblt_rop_bkwd_src_notxor_dst, + cirrus_bitblt_rop_bkwd_src_or_notdst, + cirrus_bitblt_rop_bkwd_notsrc, + cirrus_bitblt_rop_bkwd_notsrc_or_dst, + cirrus_bitblt_rop_bkwd_notsrc_and_notdst, +}; + +#define TRANSP_ROP(name) {\ + name ## _8,\ + name ## _16,\ + } +#define TRANSP_NOP(func) {\ + func,\ + func,\ + } + +static const cirrus_bitblt_rop_t cirrus_fwd_transp_rop[16][2] = { + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_0), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_dst), + TRANSP_NOP(cirrus_bitblt_rop_nop), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_notdst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notdst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_1), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_dst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_xor_dst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_dst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_notdst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_notxor_dst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_notdst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_dst), + TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_notdst), +}; + +static const cirrus_bitblt_rop_t cirrus_bkwd_transp_rop[16][2] = { + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_0), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_dst), + TRANSP_NOP(cirrus_bitblt_rop_nop), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_notdst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notdst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_1), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_dst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_xor_dst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_dst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_notdst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_notxor_dst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_notdst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_dst), + TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_notdst), +}; + +#define ROP2(name) {\ + name ## _8,\ + name ## _16,\ + name ## _24,\ + name ## _32,\ + } + +#define ROP_NOP2(func) {\ + func,\ + func,\ + func,\ + func,\ + } + +static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = { + ROP2(cirrus_patternfill_0), + ROP2(cirrus_patternfill_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_patternfill_src_and_notdst), + ROP2(cirrus_patternfill_notdst), + ROP2(cirrus_patternfill_src), + ROP2(cirrus_patternfill_1), + ROP2(cirrus_patternfill_notsrc_and_dst), + ROP2(cirrus_patternfill_src_xor_dst), + ROP2(cirrus_patternfill_src_or_dst), + ROP2(cirrus_patternfill_notsrc_or_notdst), + ROP2(cirrus_patternfill_src_notxor_dst), + ROP2(cirrus_patternfill_src_or_notdst), + ROP2(cirrus_patternfill_notsrc), + ROP2(cirrus_patternfill_notsrc_or_dst), + ROP2(cirrus_patternfill_notsrc_and_notdst), +}; + +static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = { + ROP2(cirrus_colorexpand_transp_0), + ROP2(cirrus_colorexpand_transp_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_transp_src_and_notdst), + ROP2(cirrus_colorexpand_transp_notdst), + ROP2(cirrus_colorexpand_transp_src), + ROP2(cirrus_colorexpand_transp_1), + ROP2(cirrus_colorexpand_transp_notsrc_and_dst), + ROP2(cirrus_colorexpand_transp_src_xor_dst), + ROP2(cirrus_colorexpand_transp_src_or_dst), + ROP2(cirrus_colorexpand_transp_notsrc_or_notdst), + ROP2(cirrus_colorexpand_transp_src_notxor_dst), + ROP2(cirrus_colorexpand_transp_src_or_notdst), + ROP2(cirrus_colorexpand_transp_notsrc), + ROP2(cirrus_colorexpand_transp_notsrc_or_dst), + ROP2(cirrus_colorexpand_transp_notsrc_and_notdst), +}; + +static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = { + ROP2(cirrus_colorexpand_0), + ROP2(cirrus_colorexpand_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_src_and_notdst), + ROP2(cirrus_colorexpand_notdst), + ROP2(cirrus_colorexpand_src), + ROP2(cirrus_colorexpand_1), + ROP2(cirrus_colorexpand_notsrc_and_dst), + ROP2(cirrus_colorexpand_src_xor_dst), + ROP2(cirrus_colorexpand_src_or_dst), + ROP2(cirrus_colorexpand_notsrc_or_notdst), + ROP2(cirrus_colorexpand_src_notxor_dst), + ROP2(cirrus_colorexpand_src_or_notdst), + ROP2(cirrus_colorexpand_notsrc), + ROP2(cirrus_colorexpand_notsrc_or_dst), + ROP2(cirrus_colorexpand_notsrc_and_notdst), +}; + +static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = { + ROP2(cirrus_colorexpand_pattern_transp_0), + ROP2(cirrus_colorexpand_pattern_transp_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst), + ROP2(cirrus_colorexpand_pattern_transp_notdst), + ROP2(cirrus_colorexpand_pattern_transp_src), + ROP2(cirrus_colorexpand_pattern_transp_1), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst), + ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst), + ROP2(cirrus_colorexpand_pattern_transp_src_or_dst), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst), + ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst), + ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst), + ROP2(cirrus_colorexpand_pattern_transp_notsrc), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst), +}; + +static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = { + ROP2(cirrus_colorexpand_pattern_0), + ROP2(cirrus_colorexpand_pattern_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_pattern_src_and_notdst), + ROP2(cirrus_colorexpand_pattern_notdst), + ROP2(cirrus_colorexpand_pattern_src), + ROP2(cirrus_colorexpand_pattern_1), + ROP2(cirrus_colorexpand_pattern_notsrc_and_dst), + ROP2(cirrus_colorexpand_pattern_src_xor_dst), + ROP2(cirrus_colorexpand_pattern_src_or_dst), + ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst), + ROP2(cirrus_colorexpand_pattern_src_notxor_dst), + ROP2(cirrus_colorexpand_pattern_src_or_notdst), + ROP2(cirrus_colorexpand_pattern_notsrc), + ROP2(cirrus_colorexpand_pattern_notsrc_or_dst), + ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst), +}; + +static const cirrus_fill_t cirrus_fill[16][4] = { + ROP2(cirrus_fill_0), + ROP2(cirrus_fill_src_and_dst), + ROP_NOP2(cirrus_bitblt_fill_nop), + ROP2(cirrus_fill_src_and_notdst), + ROP2(cirrus_fill_notdst), + ROP2(cirrus_fill_src), + ROP2(cirrus_fill_1), + ROP2(cirrus_fill_notsrc_and_dst), + ROP2(cirrus_fill_src_xor_dst), + ROP2(cirrus_fill_src_or_dst), + ROP2(cirrus_fill_notsrc_or_notdst), + ROP2(cirrus_fill_src_notxor_dst), + ROP2(cirrus_fill_src_or_notdst), + ROP2(cirrus_fill_notsrc), + ROP2(cirrus_fill_notsrc_or_dst), + ROP2(cirrus_fill_notsrc_and_notdst), +}; + +static void cirrus_bitblt_fgcol(CirrusVGAState *s) +{ + unsigned int color; + switch (s->cirrus_blt_pixelwidth) { + case 1: + s->cirrus_blt_fgcol = s->cirrus_shadow_gr1; + break; + case 2: + color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8); + s->cirrus_blt_fgcol = le16_to_cpu(color); + break; + case 3: + s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 | + (s->gr[0x11] << 8) | (s->gr[0x13] << 16); + break; + default: + case 4: + color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) | + (s->gr[0x13] << 16) | (s->gr[0x15] << 24); + s->cirrus_blt_fgcol = le32_to_cpu(color); + break; + } +} + +static void cirrus_bitblt_bgcol(CirrusVGAState *s) +{ + unsigned int color; + switch (s->cirrus_blt_pixelwidth) { + case 1: + s->cirrus_blt_bgcol = s->cirrus_shadow_gr0; + break; + case 2: + color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8); + s->cirrus_blt_bgcol = le16_to_cpu(color); + break; + case 3: + s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 | + (s->gr[0x10] << 8) | (s->gr[0x12] << 16); + break; + default: + case 4: + color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8) | + (s->gr[0x12] << 16) | (s->gr[0x14] << 24); + s->cirrus_blt_bgcol = le32_to_cpu(color); + break; + } +} + +static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, + int off_pitch, int bytesperline, + int lines) +{ + int y; + int off_cur; + int off_cur_end; + + for (y = 0; y < lines; y++) { + off_cur = off_begin; + off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask; + off_cur &= TARGET_PAGE_MASK; + while (off_cur < off_cur_end) { + cpu_physical_memory_set_dirty(s->vram_offset + off_cur); + off_cur += TARGET_PAGE_SIZE; + } + off_begin += off_pitch; + } + cirrusvga_updated = 1; +} + +static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, + const uint8_t * src) +{ + uint8_t *dst; + + dst = s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask); + + if(BLTUNSAFE_DST(s)){ + return 0; + } + + (*s->cirrus_rop) (s, dst, src, + s->cirrus_blt_dstpitch, 0, + s->cirrus_blt_width, s->cirrus_blt_height); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, + s->cirrus_blt_dstpitch, s->cirrus_blt_width, + s->cirrus_blt_height); + cirrusvga_updated = 1; + return 1; +} + +/* fill */ + +static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop) +{ + cirrus_fill_t rop_func; + + if(BLTUNSAFE_DST(s)){ + return 0; + } + + rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + rop_func(s, s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), + s->cirrus_blt_dstpitch, + s->cirrus_blt_width, s->cirrus_blt_height); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, + s->cirrus_blt_dstpitch, s->cirrus_blt_width, + s->cirrus_blt_height); + cirrus_bitblt_reset(s); + cirrusvga_updated = 1; + return 1; +} + +/*************************************** + * + * bitblt (video-to-video) + * + ***************************************/ + +static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) +{ + return cirrus_bitblt_common_patterncopy(s, + s->vram_ptr + ((s->cirrus_blt_srcaddr & ~7) & + s->cirrus_addr_mask)); +} + +static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) +{ + int sx, sy; + int dx, dy; + int width, height; + int depth; + int notify = 0; + + depth = s->get_bpp((VGAState *)s) / 8; + if(depth==0) return; + if(s->cirrus_blt_srcpitch==0) return; + if(s->cirrus_blt_dstpitch==0) return; + s->get_resolution((VGAState *)s, &width, &height); + + /* extra x, y */ + sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth; + sy = (src / ABS(s->cirrus_blt_srcpitch)); + dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth; + dy = (dst / ABS(s->cirrus_blt_dstpitch)); + + /* normalize width */ + w /= depth; + + /* if we're doing a backward copy, we have to adjust + our x/y to be the upper left corner (instead of the lower + right corner) */ + if (s->cirrus_blt_dstpitch < 0) { + sx -= (s->cirrus_blt_width / depth) - 1; + dx -= (s->cirrus_blt_width / depth) - 1; + sy -= s->cirrus_blt_height - 1; + dy -= s->cirrus_blt_height - 1; + } + + /* are we in the visible portion of memory? */ + if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 && + (sx + w) <= width && (sy + h) <= height && + (dx + w) <= width && (dy + h) <= height) { + notify = 1; + } + + /* make to sure only copy if it's a plain copy ROP */ + if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src && + *s->cirrus_rop != cirrus_bitblt_rop_bkwd_src) + notify = 0; + + /* we have to flush all pending changes so that the copy + is generated at the appropriate moment in time */ + if (notify){ + vga_hw_update(); + } + (*s->cirrus_rop) (s, s->vram_ptr + + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), + s->vram_ptr + + (s->cirrus_blt_srcaddr & s->cirrus_addr_mask), + s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, + s->cirrus_blt_width, s->cirrus_blt_height); + cirrusvga_updated = 1; + + if (notify){ + qemu_console_copy(s->ds, + sx, sy, dx, dy, + s->cirrus_blt_width / depth, + s->cirrus_blt_height); + } + + /* we don't have to notify the display that this portion has + changed since qemu_console_copy implies this */ + + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, + s->cirrus_blt_dstpitch, s->cirrus_blt_width, + s->cirrus_blt_height); + cirrusvga_updated = 1; +} + +static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) +{ + if(BLTUNSAFE_DST(s) || (!BLTUNSAFE_NOSRC(s) && BLTUNSAFE_SRC(s))){ // XXX: ソースを使用しないならソースの範囲外チェック不要。抜本解決必要 + return 0; + } + + cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr, + s->cirrus_blt_srcaddr - s->start_addr, + s->cirrus_blt_width, s->cirrus_blt_height); + + return 1; +} + +/*************************************** + * + * bitblt (cpu-to-video) + * + ***************************************/ + +static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s) +{ + int copy_count; + uint8_t *end_ptr; + + if (s->cirrus_srccounter > 0) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { + cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf); + the_end: + s->cirrus_srccounter = 0; + cirrus_bitblt_dblbufferswitch(); + cirrus_bitblt_reset(s); + } else { + /* at least one scan line */ + do { + (*s->cirrus_rop)(s, s->vram_ptr + + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), + s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, + s->cirrus_blt_width, 1); + s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch; + s->cirrus_srccounter -= s->cirrus_blt_srcpitch; + if (s->cirrus_srccounter <= 0) + goto the_end; + /* more bytes than needed can be transfered because of + word alignment, so we keep them for the next line */ + /* XXX: keep alignment to speed up transfer */ + end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; + copy_count = (int)(s->cirrus_srcptr_end - end_ptr); + if(copy_count >= 0 && s->cirrus_blt_srcpitch + copy_count <= sizeof(s->cirrus_bltbuf)) // 範囲外になっていないかチェック + memmove(s->cirrus_bltbuf, end_ptr, copy_count); + s->cirrus_srcptr = s->cirrus_bltbuf + copy_count; + if(s->cirrus_blt_srcpitch <= sizeof(s->cirrus_bltbuf)){ + s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; + }else{ + s->cirrus_srcptr_end = s->cirrus_bltbuf + sizeof(s->cirrus_bltbuf); + } + } while (s->cirrus_srcptr >= s->cirrus_srcptr_end); + } + cirrusvga_updated = 1; + } +} + +/*************************************** + * + * bitblt (video-to-cpu) + * + ***************************************/ + +static void cirrus_bitblt_videotocpu_next(CirrusVGAState * s) +{ + if (s->cirrus_srccounter > 0) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { + // XXX: not implemented + //cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf); + the_end: + s->cirrus_srccounter = 0; + cirrus_bitblt_dblbufferswitch(); + cirrus_bitblt_reset(s); + } else { + s->cirrus_blt_srcaddr += s->cirrus_blt_srcpitch; + s->cirrus_srccounter -= s->cirrus_blt_dstpitch; + if (s->cirrus_srccounter <= 0) + goto the_end; + (*s->cirrus_rop)(s, s->cirrus_bltbuf, s->vram_ptr + + (s->cirrus_blt_srcaddr & s->cirrus_addr_mask), + 0, 0, s->cirrus_blt_width, 1); + s->cirrus_srcptr = s->cirrus_bltbuf; + if(s->cirrus_blt_srcpitch <= sizeof(s->cirrus_bltbuf)){ + s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; + }else{ + s->cirrus_srcptr_end = s->cirrus_bltbuf + sizeof(s->cirrus_bltbuf); + } + } + cirrusvga_updated = 1; + } +} + +/*************************************** + * + * bitblt wrapper + * + ***************************************/ + +static void cirrus_bitblt_reset(CirrusVGAState * s) +{ + int need_update; + + s->gr[0x31] &= + ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED); + need_update = s->cirrus_srcptr != &s->cirrus_bltbuf[0] + || s->cirrus_srcptr_end != &s->cirrus_bltbuf[0]; + s->cirrus_srcptr = &s->cirrus_bltbuf[0]; + s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; + s->cirrus_srccounter = 0; + if (!need_update) + return; + cirrus_update_memory_access(s); +} + +static int cirrus_bitblt_cputovideo(CirrusVGAState * s) +{ + int w; + + s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; + s->cirrus_srcptr = &s->cirrus_bltbuf[0]; + s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; + + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { + s->cirrus_blt_srcpitch = 8; + } else { + /* XXX: check for 24 bpp */ + s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth; + } + s->cirrus_srccounter = s->cirrus_blt_srcpitch; + } else { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { + w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth; + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) + s->cirrus_blt_srcpitch = ((w + 31) >> 5); + else + s->cirrus_blt_srcpitch = ((w + 7) >> 3); + } else { + /* always align input size to 32 bits */ + s->cirrus_blt_srcpitch = (s->cirrus_blt_width + 3) & ~3; + } + s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height; + } + s->cirrus_srcptr = s->cirrus_bltbuf; + if(s->cirrus_blt_srcpitch <= sizeof(s->cirrus_bltbuf)){ + s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; + }else{ + s->cirrus_srcptr_end = s->cirrus_bltbuf + sizeof(s->cirrus_bltbuf); + } + cirrus_update_memory_access(s); + return 1; +} + +static int cirrus_bitblt_videotocpu(CirrusVGAState * s) +{ + // np21/w bitblt (video to cpu) 暫定プログラム(cputovideoからの推測・正しいかは不明) + int w; + + s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; + s->cirrus_srcptr = &s->cirrus_bltbuf[0]; + s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; + + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { + s->cirrus_blt_dstpitch = 8; + } else { + /* XXX: check for 24 bpp */ + s->cirrus_blt_dstpitch = 8 * 8 * s->cirrus_blt_pixelwidth; + } + s->cirrus_srccounter = s->cirrus_blt_dstpitch; + } else { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { + w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth; + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) + s->cirrus_blt_dstpitch = ((w + 31) >> 5); + else + s->cirrus_blt_dstpitch = ((w + 7) >> 3); + } else { + /* always align input size to 32 bits */ + s->cirrus_blt_dstpitch = (s->cirrus_blt_width + 3) & ~3; + } + s->cirrus_srccounter = s->cirrus_blt_dstpitch * s->cirrus_blt_height; + } + s->cirrus_srcptr = s->cirrus_bltbuf; + if(s->cirrus_blt_dstpitch <= sizeof(s->cirrus_bltbuf)){ + s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_dstpitch; + }else{ + s->cirrus_srcptr_end = s->cirrus_bltbuf + sizeof(s->cirrus_bltbuf); + } + if(s->cirrus_blt_dstpitch<0){ + cirrus_update_memory_access(s); + } + cirrus_update_memory_access(s); + + memset(s->cirrus_bltbuf, 0, s->cirrus_blt_width); + + // Copy 1st data + (*s->cirrus_rop)(s, s->cirrus_bltbuf, s->vram_ptr + + (s->cirrus_blt_srcaddr & s->cirrus_addr_mask), + 0, 0, s->cirrus_blt_width, 1); + cirrusvga_updated = 1; + return 1; +} + +static int cirrus_bitblt_videotovideo(CirrusVGAState * s) +{ + int ret; + + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { + ret = cirrus_bitblt_videotovideo_patterncopy(s); + } else { + ret = cirrus_bitblt_videotovideo_copy(s); + } + if (ret) + cirrus_bitblt_reset(s); + + cirrus_bitblt_dblbufferswitch(); + + return ret; +} + +static void cirrus_bitblt_start(CirrusVGAState * s) +{ + uint8_t blt_rop; + + s->gr[0x31] |= CIRRUS_BLT_BUSY; + + s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1; + s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1; + s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8)); + s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8)); + s->cirrus_blt_dstaddr = (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16)); + s->cirrus_blt_srcaddr = (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16)); + s->cirrus_blt_mode = s->gr[0x30]; + blt_rop = s->gr[0x32]; + if(s->device_id == CIRRUS_ID_CLGD5446){ + s->cirrus_blt_modeext = s->gr[0x33]; + }else{ + s->cirrus_blt_modeext = 0; // ver0.86 rev8 + } + +#ifdef DEBUG_BITBLT + printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n", + blt_rop, + s->cirrus_blt_mode, + s->cirrus_blt_modeext, + s->cirrus_blt_width, + s->cirrus_blt_height, + s->cirrus_blt_dstpitch, + s->cirrus_blt_srcpitch, + s->cirrus_blt_dstaddr, + s->cirrus_blt_srcaddr, + s->gr[0x2f]); +#endif + + switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { + case CIRRUS_BLTMODE_PIXELWIDTH8: + s->cirrus_blt_pixelwidth = 1; + break; + case CIRRUS_BLTMODE_PIXELWIDTH16: + s->cirrus_blt_pixelwidth = 2; + break; + case CIRRUS_BLTMODE_PIXELWIDTH24: + s->cirrus_blt_pixelwidth = 3; + break; + case CIRRUS_BLTMODE_PIXELWIDTH32: + s->cirrus_blt_pixelwidth = 4; + break; + default: +#ifdef DEBUG_BITBLT + printf("cirrus: bitblt - pixel width is unknown\n"); +#endif + goto bitblt_ignore; + } + s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK; + + if ((s-> + cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) + == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) { +#ifdef DEBUG_BITBLT + printf("cirrus: bitblt - memory-to-memory copy is requested\n"); +#endif + goto bitblt_ignore; + } + + if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) && + (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | + CIRRUS_BLTMODE_TRANSPARENTCOMP | + CIRRUS_BLTMODE_PATTERNCOPY | + CIRRUS_BLTMODE_COLOREXPAND)) == + (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) { + cirrus_bitblt_fgcol(s); + cirrus_bitblt_solidfill(s, blt_rop); + } else { + if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND | + CIRRUS_BLTMODE_PATTERNCOPY)) == + CIRRUS_BLTMODE_COLOREXPAND) { + + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) + cirrus_bitblt_bgcol(s); + else + cirrus_bitblt_fgcol(s); + s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } else { + cirrus_bitblt_fgcol(s); + cirrus_bitblt_bgcol(s); + s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } + } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) + cirrus_bitblt_bgcol(s); + else + cirrus_bitblt_fgcol(s); + s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } else { + cirrus_bitblt_fgcol(s); + cirrus_bitblt_bgcol(s); + s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } + } else { + s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } + } else { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { + if (s->cirrus_blt_pixelwidth > 2) { + printf("src transparent without colorexpand must be 8bpp or 16bpp\n"); + goto bitblt_ignore; + } + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) { + s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch; + s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch; + s->cirrus_rop = cirrus_bkwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } else { + s->cirrus_rop = cirrus_fwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } + } else { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) { + s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch; + s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch; + s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]]; + } else { + s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]]; + } + } + } + // setup bitblt engine. + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) { + if (!cirrus_bitblt_cputovideo(s)) + goto bitblt_ignore; + } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) { + if (!cirrus_bitblt_videotocpu(s)) + goto bitblt_ignore; + } else { + if (!cirrus_bitblt_videotovideo(s)) + goto bitblt_ignore; + } + } + return; + bitblt_ignore:; + cirrus_bitblt_reset(s); +} + +static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value) +{ + unsigned old_value; + + old_value = s->gr[0x31]; + s->gr[0x31] = reg_value & 0xee; + + if (((old_value & CIRRUS_BLT_RESET) != 0) && + ((reg_value & CIRRUS_BLT_RESET) == 0)) { + if(s->device_id == CIRRUS_ID_CLGD5446){ + cirrus_bitblt_reset(s); + }else{ + cirrus_bitblt_start(s);// XXX: Win2000のハードウェアアクセラレーションを正常に動かすのに必要。根拠無し。 + if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ + // XXX: Win3.1の最初のBitBltが無視される問題の回避策 + if(!(old_value & 0x04)){ + cirrus_bitblt_reset(s); + } + }else{ + cirrus_bitblt_reset(s); + } + } + } else if (((old_value & CIRRUS_BLT_START) == 0) && + ((reg_value & CIRRUS_BLT_START) != 0)) { + cirrus_bitblt_start(s); + } +} + +static void cirrus_bitblt_dblbufferswitch(){ + CirrusVGAState *s = cirrusvga; + if(s->device_id == CIRRUS_ID_CLGD5446){ + if(s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_BLTSYNCDISP){ + if((s->cr[0x5e] & 0x7) == 0x7){ + s->graphics_dblbuf_index = (s->graphics_dblbuf_index + 1) & 0x1; + } + if((s->cr[0x5e] & 0x30) == 0x30){ + s->videowindow_dblbuf_index = (s->videowindow_dblbuf_index + 1) & 0x1; + } + } + } +} + + +/*************************************** + * + * basic parameters + * + ***************************************/ + +static void cirrus_get_offsets(VGAState *s1, + uint32_t_ *pline_offset, + uint32_t_ *pstart_addr, + uint32_t_ *pline_compare) +{ + CirrusVGAState * s = (CirrusVGAState *)s1; + uint32_t_ start_addr, line_offset, line_compare; + + line_offset = s->cr[0x13] + | ((s->cr[0x1b] & 0x10) << 4); + line_offset <<= 3; + *pline_offset = line_offset; + + start_addr = (s->cr[0x0c] << 8) + | s->cr[0x0d] + | ((s->cr[0x1b] & 0x01) << 16) + | ((s->cr[0x1b] & 0x0c) << 15) + | ((s->cr[0x1d] & 0x80) << 12); + *pstart_addr = start_addr; + + line_compare = s->cr[0x18] | + ((s->cr[0x07] & 0x10) << 4) | + ((s->cr[0x09] & 0x40) << 3); + *pline_compare = line_compare; +} + +static uint32_t_ cirrus_get_bpp16_depth(CirrusVGAState * s) +{ + uint32_t_ ret = 16; + + switch (s->cirrus_hidden_dac_data & 0xf) { + case 0: + ret = 15; + break; /* Sierra HiColor */ + case 1: + ret = 16; + break; /* XGA HiColor */ + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: invalid DAC value %x in 16bpp\n", + (s->cirrus_hidden_dac_data & 0xf)); +#endif + ret = 15; /* XXX */ + break; + } + return ret; +} + +static int cirrus_get_bpp(VGAState *s1) +{ + CirrusVGAState * s = (CirrusVGAState *)s1; + uint32_t_ ret = 8; + + if ((s->sr[0x07] & 0x01) != 0) { + /* Cirrus SVGA */ + switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) { + case CIRRUS_SR7_BPP_8: + ret = 8; + break; + case CIRRUS_SR7_BPP_16_DOUBLEVCLK: + ret = cirrus_get_bpp16_depth(s); + break; + case CIRRUS_SR7_BPP_24: + ret = 24; + break; + case CIRRUS_SR7_BPP_16: + ret = cirrus_get_bpp16_depth(s); + break; + case CIRRUS_SR7_BPP_32: + ret = 32; + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]); +#endif + ret = 8; + break; + } + } else { + //ret = 8; + /* VGA */ + ret = 0; + } + + return ret; +} + +static void cirrus_get_resolution(VGAState *s, int *pwidth, int *pheight) +{ + int width, height; + + width = (s->cr[0x01] + 1) * 8; + height = s->cr[0x12] | + ((s->cr[0x07] & 0x02) << 7) | + ((s->cr[0x07] & 0x40) << 3); + height = (height + 1); + /* interlace support */ + if (s->cr[0x1a] & 0x01) + height = height * 2; + if(width==320) height /= 2; // XXX: Win98で表示がおかしくなるのでとりあえず仮 + if(width==400) height = 300; // XXX: Win98で表示がおかしくなるのでとりあえず仮 + if(width==512) height = 384; // XXX: Win98で表示がおかしくなるのでとりあえず仮 + if(height >= width * 3 / 4 * 2){ + height /= 2; // XXX: 縦長過ぎるとき、高さ半分にしておく + } + + // WSN 1280x1024 + if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WAB || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ + // XXX: WSN用やっつけ修正 + if(width==1280){ + height = 1024; + } + } + + *pwidth = width; + *pheight = height; +} + +/*************************************** + * + * bank memory + * + ***************************************/ + +static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index) +{ + unsigned offset; + unsigned limit; + + if ((s->gr[0x0b] & 0x01) != 0) /* dual bank */ + offset = s->gr[0x09 + bank_index]; + else /* single bank */ + offset = s->gr[0x09]; + + if ((s->gr[0x0b] & 0x20) != 0) + offset <<= 14; + else + offset <<= 12; + + if ((unsigned int)s->real_vram_size <= offset) + limit = 0; + else + limit = s->real_vram_size - offset; + + if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) { + if (limit > 0x8000) { + offset += 0x8000; + limit -= 0x8000; + } else { + limit = 0; + } + } + + if (limit > 0) { + /* Thinking about changing bank base? First, drop the dirty bitmap information + * on the current location, otherwise we lose this pointer forever */ + if (s->lfb_vram_mapped) { + target_phys_addr_t base_addr = isa_mem_base + 0xF80000 + bank_index * 0x8000; + cpu_physical_sync_dirty_bitmap(base_addr, base_addr + 0x8000); + TRACEOUT(("UNSUPPORT1")); + } + s->cirrus_bank_base[bank_index] = offset; + s->cirrus_bank_limit[bank_index] = limit; + } else { + s->cirrus_bank_base[bank_index] = 0; + s->cirrus_bank_limit[bank_index] = 0; + } +} + +/*************************************** + * + * I/O access between 0x3c4-0x3c5 + * + ***************************************/ + +static int +cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value) +{ + switch (reg_index) { + case 0x00: // Standard VGA + case 0x01: // Standard VGA + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x06: // Unlock Cirrus extensions + *reg_value = s->sr[reg_index]; + break; + case 0x10: + case 0x30: + case 0x50: + case 0x70: // Graphics Cursor X + case 0x90: + case 0xb0: + case 0xd0: + case 0xf0: // Graphics Cursor X + *reg_value = s->sr[0x10]; + break; + case 0x11: + case 0x31: + case 0x51: + case 0x71: // Graphics Cursor Y + case 0x91: + case 0xb1: + case 0xd1: + case 0xf1: // Graphics Cursor Y + *reg_value = s->sr[0x11]; + break; + case 0x05: // ??? + case 0x07: // Extended Sequencer Mode +// cirrus_update_memory_access(s); +#ifdef DEBUG_CIRRUS + printf("cirrus: handled inport sr_index %02x\n", reg_index); +#endif + *reg_value = s->sr[reg_index]; + break; + case 0x08: // EEPROM Control +#if defined(SUPPORT_PCI) + // XXX: Win2000でPnPデバイス検出を動かすのに必要。理由は謎 + if(pcidev.enable && np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + *reg_value = cirrusvga->sr[0x08] = 0xFE; + break; + } +#endif + case 0x09: // Scratch Register 0 + case 0x0a: // Scratch Register 1 + case 0x0b: // VCLK 0 + case 0x0c: // VCLK 1 + case 0x0d: // VCLK 2 + case 0x0e: // VCLK 3 + case 0x0f: // DRAM Control + case 0x12: // Graphics Cursor Attribute + case 0x13: // Graphics Cursor Pattern Address + case 0x14: // Scratch Register 2 + case 0x15: // Scratch Register 3 + case 0x16: // Performance Tuning Register + case 0x17: // Configuration Readback and Extended Control + case 0x18: // Signature Generator Control + case 0x19: // Signal Generator Result + case 0x1a: // Signal Generator Result + case 0x1b: // VCLK 0 Denominator & Post + case 0x1c: // VCLK 1 Denominator & Post + case 0x1d: // VCLK 2 Denominator & Post + case 0x1e: // VCLK 3 Denominator & Post + case 0x1f: // BIOS Write Enable and MCLK select +#ifdef DEBUG_CIRRUS + printf("cirrus: handled inport sr_index %02x\n", reg_index); +#endif + *reg_value = s->sr[reg_index]; + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: inport sr_index %02x\n", reg_index); +#endif + *reg_value = 0xff; + break; + } + + return CIRRUS_HOOK_HANDLED; +} + +static int +cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) +{ + switch (reg_index) { + case 0x00: // Standard VGA + case 0x01: // Standard VGA + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x06: // Unlock Cirrus extensions + reg_value &= 0x17; + if (reg_value == 0x12) { + s->sr[reg_index] = 0x12; + } else { + s->sr[reg_index] = 0x0f; + } + break; + case 0x10: + case 0x30: + case 0x50: + case 0x70: // Graphics Cursor X + case 0x90: + case 0xb0: + case 0xd0: + case 0xf0: // Graphics Cursor X + s->sr[0x10] = reg_value; + s->hw_cursor_x = (reg_value << 3) | (reg_index >> 5); + cirrusvga_updated = 1; + break; + case 0x11: + case 0x31: + case 0x51: + case 0x71: // Graphics Cursor Y + case 0x91: + case 0xb1: + case 0xd1: + case 0xf1: // Graphics Cursor Y + s->sr[0x11] = reg_value; + s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5); + cirrusvga_updated = 1; + break; + case 0x07: // Extended Sequencer Mode +// cirrus_update_memory_access(s); + case 0x08: // EEPROM Control + case 0x09: // Scratch Register 0 + case 0x0a: // Scratch Register 1 + case 0x0b: // VCLK 0 + case 0x0c: // VCLK 1 + case 0x0d: // VCLK 2 + case 0x0e: // VCLK 3 + case 0x0f: // DRAM Control + case 0x12: // Graphics Cursor Attribute + case 0x13: // Graphics Cursor Pattern Address + case 0x14: // Scratch Register 2 + case 0x15: // Scratch Register 3 + case 0x16: // Performance Tuning Register + case 0x18: // Signature Generator Control + case 0x19: // Signature Generator Result + case 0x1a: // Signature Generator Result + case 0x1b: // VCLK 0 Denominator & Post + case 0x1c: // VCLK 1 Denominator & Post + case 0x1d: // VCLK 2 Denominator & Post + case 0x1e: // VCLK 3 Denominator & Post + case 0x1f: // BIOS Write Enable and MCLK select + if(reg_index==0x07 && np2clvga.gd54xxtype < 0xff && np2clvga.gd54xxtype != CIRRUS_98ID_PCI){ + s->sr[reg_index] = (s->sr[reg_index] & 0xf0) | (reg_value & 0x0f); + }else{ + s->sr[reg_index] = reg_value; + } + s->sr[reg_index] = reg_value; + cirrus_update_memory_access(s); +#ifdef DEBUG_CIRRUS + printf("cirrus: handled outport sr_index %02x, sr_value %02x\n", + reg_index, reg_value); +#endif + break; + case 0x17: // Configuration Readback and Extended Control + s->sr[reg_index] = (s->sr[reg_index] & 0x38) | (reg_value & 0xc7); + cirrus_update_memory_access(s); + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index, + reg_value); +#endif + break; + } + + return CIRRUS_HOOK_HANDLED; +} + +/*************************************** + * + * I/O access at 0x3c6 + * + ***************************************/ + +static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value) +{ + *reg_value = 0xff; + if (++s->cirrus_hidden_dac_lockindex == 5) { + *reg_value = s->cirrus_hidden_dac_data; + s->cirrus_hidden_dac_lockindex = 0; + } +} + +static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value) +{ + if (s->cirrus_hidden_dac_lockindex == 4) { + s->cirrus_hidden_dac_data = reg_value; +#if defined(DEBUG_CIRRUS) + printf("cirrus: outport hidden DAC, value %02x\n", reg_value); +#endif + } + s->cirrus_hidden_dac_lockindex = 0; +} + +/*************************************** + * + * I/O access at 0x3c9 + * + ***************************************/ + +static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value) +{ + if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) + return CIRRUS_HOOK_NOT_HANDLED; + *reg_value = + s->cirrus_hidden_palette[(s->dac_read_index & 0x0f) * 3 + + s->dac_sub_index]; + if (++s->dac_sub_index == 3) { + s->dac_sub_index = 0; + s->dac_read_index++; + } + return CIRRUS_HOOK_HANDLED; +} + +static int cirrus_hook_write_palette(CirrusVGAState* s, int reg_value) +{ + if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) + return CIRRUS_HOOK_NOT_HANDLED; + s->dac_cache[s->dac_sub_index] = reg_value; + if (++s->dac_sub_index == 3) + { + memcpy(&s->cirrus_hidden_palette[(s->dac_write_index & 0x0f) * 3], + s->dac_cache, 3); + /* XXX update cursor */ + s->dac_sub_index = 0; + s->dac_write_index++; + cirrusvga_updated = 1; + } + return CIRRUS_HOOK_HANDLED; +} + +/*************************************** + * + * I/O access between 0x3ce-0x3cf + * + ***************************************/ + +static int +cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value) +{ + switch (reg_index) { + case 0x00: // Standard VGA, BGCOLOR 0x000000ff + *reg_value = s->cirrus_shadow_gr0; + return CIRRUS_HOOK_HANDLED; + case 0x01: // Standard VGA, FGCOLOR 0x000000ff + *reg_value = s->cirrus_shadow_gr1; + return CIRRUS_HOOK_HANDLED; + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x06: // Standard VGA + *reg_value = s->gr[0x06]; + return CIRRUS_HOOK_HANDLED; + case 0x07: // Standard VGA + case 0x08: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x05: // Standard VGA, Cirrus extended mode + default: + break; + } + + if (reg_index < 0x3a) { + *reg_value = s->gr[reg_index]; + } else { +#ifdef DEBUG_CIRRUS + printf("cirrus: inport gr_index %02x\n", reg_index); +#endif + *reg_value = 0xff; + } + + return CIRRUS_HOOK_HANDLED; +} + +static int +cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) +{ +#if defined(DEBUG_BITBLT) && 0 + printf("gr%02x: %02x\n", reg_index, reg_value); +#endif + switch (reg_index) { + case 0x00: // Standard VGA, BGCOLOR 0x000000ff + s->cirrus_shadow_gr0 = reg_value; + return CIRRUS_HOOK_NOT_HANDLED; + case 0x01: // Standard VGA, FGCOLOR 0x000000ff + s->cirrus_shadow_gr1 = reg_value; + return CIRRUS_HOOK_NOT_HANDLED; + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x06: // Standard VGA + s->gr[reg_index] = reg_value & 0x0f; + cirrus_update_memory_access(s); + break; + case 0x07: // Standard VGA + case 0x08: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x05: // Standard VGA, Cirrus extended mode + s->gr[reg_index] = reg_value & 0x7f; + cirrus_update_memory_access(s); + break; + case 0x09: // bank offset #0 + case 0x0A: // bank offset #1 + s->gr[reg_index] = reg_value; + cirrus_update_bank_ptr(s, 0); + cirrus_update_bank_ptr(s, 1); + cirrus_update_memory_access(s); + break; + case 0x0B: + s->gr[reg_index] = reg_value; + cirrus_update_bank_ptr(s, 0); + cirrus_update_bank_ptr(s, 1); + cirrus_update_memory_access(s); + break; + case 0x0e: // Power Management (CL-GD5446) + case 0x10: // BGCOLOR 0x0000ff00 + case 0x11: // FGCOLOR 0x0000ff00 + case 0x12: // BGCOLOR 0x00ff0000 + case 0x13: // FGCOLOR 0x00ff0000 + case 0x14: // BGCOLOR 0xff000000 + case 0x15: // FGCOLOR 0xff000000 + case 0x20: // BLT WIDTH 0x0000ff + case 0x22: // BLT HEIGHT 0x0000ff + case 0x24: // BLT DEST PITCH 0x0000ff + case 0x26: // BLT SRC PITCH 0x0000ff + case 0x28: // BLT DEST ADDR 0x0000ff + case 0x29: // BLT DEST ADDR 0x00ff00 + case 0x2c: // BLT SRC ADDR 0x0000ff + case 0x2d: // BLT SRC ADDR 0x00ff00 + case 0x2f: // BLT WRITEMASK + case 0x30: // BLT MODE + case 0x32: // RASTER OP + case 0x34: // BLT TRANSPARENT COLOR 0x00ff + case 0x35: // BLT TRANSPARENT COLOR 0xff00 + case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff + case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00 + s->gr[reg_index] = reg_value; + break; + case 0x21: // BLT WIDTH 0x001f00 + case 0x23: // BLT HEIGHT 0x001f00 + case 0x25: // BLT DEST PITCH 0x001f00 + case 0x27: // BLT SRC PITCH 0x001f00 + s->gr[reg_index] = reg_value & 0x1f; + break; + case 0x2a: // BLT DEST ADDR 0x3f0000 + s->gr[reg_index] = reg_value & 0x3f; + /* if auto start mode, starts bit blt now */ + if (s->gr[0x31] & CIRRUS_BLT_AUTOSTART) { + cirrus_bitblt_start(s); + } + break; + case 0x2e: // BLT SRC ADDR 0x3f0000 + s->gr[reg_index] = reg_value & 0x3f; + break; + case 0x31: // BLT STATUS/START + cirrus_write_bitblt(s, reg_value); + //cirrus_write_bitblt(s, reg_value); + break; + case 0x33: // BLT MODEEXT + if(s->device_id != CIRRUS_ID_CLGD5446 || + ((s->gr[0x0e] & 0x20) || (s->gr[0x31] & 0x80)) && (s->cr[0x5e] & 0x20)) { + s->gr[reg_index] = reg_value; + } + + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index, + reg_value); +#endif + break; + } + + return CIRRUS_HOOK_HANDLED; +} + +/*************************************** + * + * I/O access between 0x3d4-0x3d5 + * + ***************************************/ + +static int +cirrus_hook_read_cr(CirrusVGAState * s, unsigned reg_index, int *reg_value) +{ + switch (reg_index) { + case 0x00: // Standard VGA + case 0x01: // Standard VGA + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + case 0x05: // Standard VGA + case 0x06: // Standard VGA + case 0x07: // Standard VGA + case 0x08: // Standard VGA + case 0x09: // Standard VGA + case 0x0a: // Standard VGA + case 0x0b: // Standard VGA + case 0x0c: // Standard VGA + case 0x0d: // Standard VGA + case 0x0e: // Standard VGA + case 0x0f: // Standard VGA + case 0x10: // Standard VGA + case 0x11: // Standard VGA + case 0x12: // Standard VGA + case 0x13: // Standard VGA + case 0x14: // Standard VGA + case 0x15: // Standard VGA + case 0x16: // Standard VGA + case 0x17: // Standard VGA + case 0x18: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x24: // Attribute Controller Toggle Readback (R) + *reg_value = (s->ar_flip_flop << 7); + break; + case 0x19: // Interlace End + case 0x1a: // Miscellaneous Control + case 0x1b: // Extended Display Control + case 0x1c: // Sync Adjust and Genlock + case 0x1d: // Overlay Extended Control + case 0x22: // Graphics Data Latches Readback (R) + *reg_value = s->cr[reg_index]; + break; + case 0x25: // Part Status + *reg_value = s->cr[reg_index]; + break; + case 0x27: // Part ID (R) + if(np2clvga.gd54xxtype <= 0xff){ + *reg_value = s->cr[reg_index]; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ + *reg_value = CIRRUS_ID_CLGD5428; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ + *reg_value = CIRRUS_ID_CLGD5434; + }else if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + *reg_value = CIRRUS_ID_CLGD5434; + }else{ + *reg_value = s->cr[reg_index]; + } + s->cr[0x5e] |= 0x20; // XXX: Part IDを読んだらGR33を書き込み可能にする(WinNT4専用の不具合回避) + break; + case 0x28: // Class ID Register + if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ + *reg_value = 0x03; + }else if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC) { + *reg_value = 0x03; + } + break; + case 0x26: // Attribute Controller Index Readback (R) + *reg_value = s->ar_index & 0x3f; + break; + case 0x31: // Video Window Horizontal Zoom Control + case 0x32: // Video Window Vertical Zoom Control + case 0x33: // Video Window Horizontal Region 1 Size + case 0x34: // Video Window Region 2 Skip Size + case 0x35: // Video Window Region 2 Active Size + case 0x36: // Video Window Horizontal Overflow + case 0x37: // Video Window Vertical Start + case 0x38: // Video Window Vertical End + case 0x39: // Video Window Vertical Overflow + case 0x3a: // Video Buffer 1 Start Address Byte 0 + case 0x3b: // Video Buffer 1 Start Address Byte 1 + case 0x3c: // Video Buffer 1 Start Address Byte 2 + case 0x3d: // Video Window Address Offset + case 0x3e: // Video Window Master Control + case 0x3f: // Host Video Data Path Control + case 0x5d: // Video Window Pixel Alignment + if(s->device_id >= CIRRUS_ID_CLGD5440){ + *reg_value = s->cr[reg_index]; + } + break; + case 0x5e: // Double Buffer Control (CL-GD5446) + if(s->device_id == CIRRUS_ID_CLGD5446){ + *reg_value = s->cr[reg_index]; + } + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: inport cr_index %02x\n", reg_index); + *reg_value = 0xff; +#endif + break; + } + + return CIRRUS_HOOK_HANDLED; +} + +static int +cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value) +{ + switch (reg_index) { + case 0x00: // Standard VGA + case 0x01: // Standard VGA + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + case 0x05: // Standard VGA + case 0x06: // Standard VGA + case 0x07: // Standard VGA + case 0x08: // Standard VGA + case 0x09: // Standard VGA + case 0x0a: // Standard VGA + case 0x0b: // Standard VGA + case 0x0c: // Standard VGA + case 0x0d: // Standard VGA + case 0x0e: // Standard VGA + case 0x0f: // Standard VGA + case 0x10: // Standard VGA + case 0x11: // Standard VGA + case 0x12: // Standard VGA + case 0x13: // Standard VGA + case 0x14: // Standard VGA + case 0x15: // Standard VGA + case 0x16: // Standard VGA + case 0x17: // Standard VGA + case 0x18: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x19: // Interlace End + case 0x1a: // Miscellaneous Control + case 0x1b: // Extended Display Control + case 0x1c: // Sync Adjust and Genlock + case 0x1d: // Overlay Extended Control + s->cr[reg_index] = reg_value; +#ifdef DEBUG_CIRRUS + printf("cirrus: handled outport cr_index %02x, cr_value %02x\n", + reg_index, reg_value); +#endif + break; + case 0x22: // Graphics Data Latches Readback (R) + case 0x24: // Attribute Controller Toggle Readback (R) + case 0x26: // Attribute Controller Index Readback (R) + case 0x27: // Part ID (R) + break; + case 0x31: // Video Window Horizontal Zoom Control + case 0x32: // Video Window Vertical Zoom Control + case 0x33: // Video Window Horizontal Region 1 Size + case 0x34: // Video Window Region 2 Skip Size + case 0x35: // Video Window Region 2 Active Size + case 0x36: // Video Window Horizontal Overflow + case 0x37: // Video Window Vertical Start + case 0x38: // Video Window Vertical End + case 0x39: // Video Window Vertical Overflow + case 0x3a: // Video Buffer 1 Start Address Byte 0 + case 0x3b: // Video Buffer 1 Start Address Byte 1 + case 0x3c: // Video Buffer 1 Start Address Byte 2 + case 0x3d: // Video Window Address Offset + case 0x3e: // Video Window Master Control + case 0x3f: // Host Video Data Path Control + case 0x5d: // Video Window Pixel Alignment + if(s->device_id >= CIRRUS_ID_CLGD5440){ + s->cr[reg_index] = reg_value; + } + break; + case 0x5e: // Double Buffer Control (CL-GD5446) + if(s->device_id == CIRRUS_ID_CLGD5446){ + s->cr[reg_index] = reg_value; + switch(reg_value & 0x7){ + case 0: // Compatible VGA display address control + s->graphics_dblbuf_index = 0; + break; + case 1: // VSYNC switching + break; + case 2: // Forces graphics buffer 1 as display + s->graphics_dblbuf_index = 0; + break; + case 3: // Forces graphics buffer 2 as display + s->graphics_dblbuf_index = 1; + break; + case 4: // A18 controls switching + break; + case 5: // A19 controls switching + break; + case 6: // Reserved + break; + case 7: // Bitblt switches + break; + } + } + break; + case 0x25: // Part Status + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: outport cr_index %02x, cr_value %02x\n", reg_index, + reg_value); +#endif + break; + } + + return CIRRUS_HOOK_HANDLED; +} + +/*************************************** + * + * memory-mapped I/O (bitblt) + * + ***************************************/ + +static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address) +{ + int value = 0xff; + + switch (address) { + case (CIRRUS_MMIO_BLTBGCOLOR + 0): + cirrus_hook_read_gr(s, 0x00, &value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 1): + cirrus_hook_read_gr(s, 0x10, &value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 2): + cirrus_hook_read_gr(s, 0x12, &value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 3): + cirrus_hook_read_gr(s, 0x14, &value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 0): + cirrus_hook_read_gr(s, 0x01, &value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 1): + cirrus_hook_read_gr(s, 0x11, &value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 2): + cirrus_hook_read_gr(s, 0x13, &value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 3): + cirrus_hook_read_gr(s, 0x15, &value); + break; + case (CIRRUS_MMIO_BLTWIDTH + 0): + cirrus_hook_read_gr(s, 0x20, &value); + break; + case (CIRRUS_MMIO_BLTWIDTH + 1): + cirrus_hook_read_gr(s, 0x21, &value); + break; + case (CIRRUS_MMIO_BLTHEIGHT + 0): + cirrus_hook_read_gr(s, 0x22, &value); + break; + case (CIRRUS_MMIO_BLTHEIGHT + 1): + cirrus_hook_read_gr(s, 0x23, &value); + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 0): + cirrus_hook_read_gr(s, 0x24, &value); + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 1): + cirrus_hook_read_gr(s, 0x25, &value); + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 0): + cirrus_hook_read_gr(s, 0x26, &value); + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 1): + cirrus_hook_read_gr(s, 0x27, &value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 0): + cirrus_hook_read_gr(s, 0x28, &value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 1): + cirrus_hook_read_gr(s, 0x29, &value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 2): + cirrus_hook_read_gr(s, 0x2a, &value); + break; + case (CIRRUS_MMIO_BLTSRCADDR + 0): + cirrus_hook_read_gr(s, 0x2c, &value); + break; + case (CIRRUS_MMIO_BLTSRCADDR + 1): + cirrus_hook_read_gr(s, 0x2d, &value); + break; + case (CIRRUS_MMIO_BLTSRCADDR + 2): + cirrus_hook_read_gr(s, 0x2e, &value); + break; + case CIRRUS_MMIO_BLTWRITEMASK: + cirrus_hook_read_gr(s, 0x2f, &value); + break; + case CIRRUS_MMIO_BLTMODE: + cirrus_hook_read_gr(s, 0x30, &value); + break; + case CIRRUS_MMIO_BLTROP: + cirrus_hook_read_gr(s, 0x32, &value); + break; + case CIRRUS_MMIO_BLTMODEEXT: + cirrus_hook_read_gr(s, 0x33, &value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0): + cirrus_hook_read_gr(s, 0x34, &value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1): + cirrus_hook_read_gr(s, 0x35, &value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0): + cirrus_hook_read_gr(s, 0x38, &value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1): + cirrus_hook_read_gr(s, 0x39, &value); + break; + case CIRRUS_MMIO_BLTSTATUS: + cirrus_hook_read_gr(s, 0x31, &value); + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: mmio read - address 0x%04x\n", address); +#endif + break; + } + + return (uint8_t) value; +} + +static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address, + uint8_t value) +{ + switch (address) { + case (CIRRUS_MMIO_BLTBGCOLOR + 0): + cirrus_hook_write_gr(s, 0x00, value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 1): + cirrus_hook_write_gr(s, 0x10, value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 2): + cirrus_hook_write_gr(s, 0x12, value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 3): + cirrus_hook_write_gr(s, 0x14, value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 0): + cirrus_hook_write_gr(s, 0x01, value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 1): + cirrus_hook_write_gr(s, 0x11, value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 2): + cirrus_hook_write_gr(s, 0x13, value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 3): + cirrus_hook_write_gr(s, 0x15, value); + break; + case (CIRRUS_MMIO_BLTWIDTH + 0): + cirrus_hook_write_gr(s, 0x20, value); + break; + case (CIRRUS_MMIO_BLTWIDTH + 1): + cirrus_hook_write_gr(s, 0x21, value); + break; + case (CIRRUS_MMIO_BLTHEIGHT + 0): + cirrus_hook_write_gr(s, 0x22, value); + break; + case (CIRRUS_MMIO_BLTHEIGHT + 1): + cirrus_hook_write_gr(s, 0x23, value); + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 0): + cirrus_hook_write_gr(s, 0x24, value); + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 1): + cirrus_hook_write_gr(s, 0x25, value); + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 0): + cirrus_hook_write_gr(s, 0x26, value); + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 1): + cirrus_hook_write_gr(s, 0x27, value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 0): + cirrus_hook_write_gr(s, 0x28, value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 1): + cirrus_hook_write_gr(s, 0x29, value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 2): + cirrus_hook_write_gr(s, 0x2a, value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 3): + /* ignored */ + break; + case (CIRRUS_MMIO_BLTSRCADDR + 0): + cirrus_hook_write_gr(s, 0x2c, value); + break; + case (CIRRUS_MMIO_BLTSRCADDR + 1): + cirrus_hook_write_gr(s, 0x2d, value); + break; + case (CIRRUS_MMIO_BLTSRCADDR + 2): + cirrus_hook_write_gr(s, 0x2e, value); + break; + case CIRRUS_MMIO_BLTWRITEMASK: + cirrus_hook_write_gr(s, 0x2f, value); + break; + case CIRRUS_MMIO_BLTMODE: + cirrus_hook_write_gr(s, 0x30, value); + break; + case CIRRUS_MMIO_BLTROP: + cirrus_hook_write_gr(s, 0x32, value); + break; + case CIRRUS_MMIO_BLTMODEEXT: + cirrus_hook_write_gr(s, 0x33, value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0): + cirrus_hook_write_gr(s, 0x34, value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1): + cirrus_hook_write_gr(s, 0x35, value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0): + cirrus_hook_write_gr(s, 0x38, value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1): + cirrus_hook_write_gr(s, 0x39, value); + break; + case CIRRUS_MMIO_BLTSTATUS: + cirrus_hook_write_gr(s, 0x31, value); + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n", + address, value); +#endif + break; + } +} + +/*************************************** + * + * write mode 4/5 + * + * assume TARGET_PAGE_SIZE >= 16 + * + ***************************************/ + +static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s, + unsigned mode, + unsigned offset, + uint32_t_ mem_value) +{ + int x; + unsigned val = mem_value; + unsigned mask = s->sr[0x2]; + uint8_t *dst; + if(s->gr[0xb] & 0x04){ + }else{ + mask = 0xff; + } + + dst = s->vram_ptr + (offset &= s->cirrus_addr_mask); + for (x = 0; x < 8; x++) { + if (mask & 0x80) { + if (val & 0x80) { + *dst = s->cirrus_shadow_gr1; + } else if (mode == 5) { + *dst = s->cirrus_shadow_gr0; + } + } + val <<= 1; + mask <<= 1; + dst++; + } + cpu_physical_memory_set_dirty(s->vram_offset + offset); + cpu_physical_memory_set_dirty(s->vram_offset + offset + 7); + cirrusvga_updated = 1; +} + +static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s, + unsigned mode, + unsigned offset, + uint32_t_ mem_value) +{ + int x; + unsigned val = mem_value; + unsigned mask = s->sr[0x2]; + uint8_t *dst; + + if(s->gr[0xb] & 0x04){ + }else{ + mask = 0xffff; + } + if(s->gr[0xb] & 0x10){ + // SR2 Doubling Enabled + mask |= mask << 8; + } + + dst = s->vram_ptr + (offset &= s->cirrus_addr_mask); + for (x = 0; x < 8; x++) { + if (mask & 0x80) { + if (val & 0x80) { + *dst = s->cirrus_shadow_gr1; + *(dst + 1) = s->gr[0x11]; + } else if (mode == 5) { + *dst = s->cirrus_shadow_gr0; + *(dst + 1) = s->gr[0x10]; + } + } + val <<= 1; + mask <<= 1; + dst += 2; + } + cpu_physical_memory_set_dirty(s->vram_offset + offset); + cpu_physical_memory_set_dirty(s->vram_offset + offset + 15); + cirrusvga_updated = 1; +} + +/*************************************** + * + * memory access between 0xa0000-0xbffff + * + ***************************************/ + +#define ADDR_SH1 0x000 + +uint32_t_ cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState*)opaque; + unsigned bank_index; + unsigned bank_offset; + uint32_t_ val; + + + addr += ADDR_SH1; + + if ((s->sr[0x07] & 0x01) == 0) { + return vga_mem_readb(s, addr); + } + addr &= 0x1ffff; + + if (addr < 0x10000) { + /* XXX handle bitblt */ + /* video memory */ + bank_index = addr >> 15; + bank_offset = addr & 0x7fff; + if (bank_offset < s->cirrus_bank_limit[bank_index]) { + bank_offset += s->cirrus_bank_base[bank_index]; + if ((s->gr[0x0B] & 0x14) == 0x14) { + bank_offset <<= 4; + } else if (s->gr[0x0B] & 0x02) { + bank_offset <<= 3; + } + bank_offset &= s->cirrus_addr_mask; + val = *(s->vram_ptr + bank_offset); + } else + val = 0xff; + } else if (addr >= 0x18000 && addr < 0x18100) { + /* memory-mapped I/O */ + val = 0xff; + if ((s->sr[0x17] & 0x44) == 0x04) { + val = cirrus_mmio_blt_read(s, addr & 0xff); + } + } else { + val = 0xff; +#ifdef DEBUG_CIRRUS + printf("cirrus: mem_readb %06x\n", addr); +#endif + } + return val; +} + +uint32_t_ cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_vga_mem_readb(opaque, addr) << 8; + v |= cirrus_vga_mem_readb(opaque, addr + 1); +#else + v = cirrus_vga_mem_readb(opaque, addr); + v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8; +#endif + return v; +} + +uint32_t_ cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_vga_mem_readb(opaque, addr) << 24; + v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16; + v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8; + v |= cirrus_vga_mem_readb(opaque, addr + 3); +#else + v = cirrus_vga_mem_readb(opaque, addr); + v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8; + v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16; + v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24; +#endif + return v; +} + +void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, + uint32_t_ mem_value) +{ + CirrusVGAState *s = (CirrusVGAState*)opaque; + unsigned bank_index; + unsigned bank_offset; + unsigned mode; + + addr += ADDR_SH1; + + if ((s->sr[0x07] & 0x01) == 0) { + vga_mem_writeb(s, addr, mem_value); + return; + } + + addr &= 0x1ffff; + + if (addr < 0x10000) { + if (s->cirrus_srcptr != s->cirrus_srcptr_end) { + /* bitblt */ + *s->cirrus_srcptr++ = (uint8_t) mem_value; + *s->cirrus_srcptr++; + if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { + cirrus_bitblt_cputovideo_next(s); + } + } else { + /* video memory */ + bank_index = addr >> 15; + bank_offset = addr & 0x7fff; + if (bank_offset < s->cirrus_bank_limit[bank_index]) { + bank_offset += s->cirrus_bank_base[bank_index]; + if ((s->gr[0x0B] & 0x14) == 0x14) { + bank_offset <<= 4; + } else if (s->gr[0x0B] & 0x02) { + bank_offset <<= 3; + } + bank_offset &= s->cirrus_addr_mask; + mode = s->gr[0x05] & 0x7; + if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { + *(s->vram_ptr + bank_offset) = mem_value; + cpu_physical_memory_set_dirty(s->vram_offset + + bank_offset); + cirrusvga_updated = 1; + } else { + if ((s->gr[0x0B] & 0x14) != 0x14) { + cirrus_mem_writeb_mode4and5_8bpp(s, mode, + bank_offset, + mem_value); + } else { + cirrus_mem_writeb_mode4and5_16bpp(s, mode, + bank_offset, + mem_value); + } + } + } + } + } else if (addr >= 0x18000 && addr < 0x18100) { + /* memory-mapped I/O */ + if ((s->sr[0x17] & 0x44) == 0x04) { + cirrus_mmio_blt_write(s, addr & 0xff, mem_value); + } + } else { +#ifdef DEBUG_CIRRUS + printf("cirrus: mem_writeb %06x value %02x\n", addr, mem_value); +#endif + } +} + +void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff); +#else + cirrus_vga_mem_writeb(opaque, addr, val & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff); +#else + cirrus_vga_mem_writeb(opaque, addr, val & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + +static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = { + cirrus_vga_mem_readb, + cirrus_vga_mem_readw, + cirrus_vga_mem_readl, +}; + +static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = { + cirrus_vga_mem_writeb, + cirrus_vga_mem_writew, + cirrus_vga_mem_writel, +}; + +/*************************************** + * + * hardware cursor + * + ***************************************/ + +static void invalidate_cursor1(CirrusVGAState *s) +{ + if (s->last_hw_cursor_size) { + vga_invalidate_scanlines((VGAState *)s, + s->last_hw_cursor_y + s->last_hw_cursor_y_start, + s->last_hw_cursor_y + s->last_hw_cursor_y_end); + } +} + +static void cirrus_cursor_compute_yrange(CirrusVGAState *s) +{ + const uint8_t *src; + uint32_t_ content; + int y, y_min, y_max; + + src = s->vram_ptr + s->real_vram_size - 16 * 1024; + if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) { + src += (s->sr[0x13] & 0x3c) * 256; + y_min = 64; + y_max = -1; + for(y = 0; y < 64; y++) { + content = ((uint32_t_ *)src)[0] | + ((uint32_t_ *)src)[1] | + ((uint32_t_ *)src)[2] | + ((uint32_t_ *)src)[3]; + if (content) { + if (y < y_min) + y_min = y; + if (y > y_max) + y_max = y; + } + src += 16; + } + } else { + src += (s->sr[0x13] & 0x3f) * 256; + y_min = 32; + y_max = -1; + for(y = 0; y < 32; y++) { + content = ((uint32_t_ *)src)[0] | + ((uint32_t_ *)(src + 128))[0]; + if (content) { + if (y < y_min) + y_min = y; + if (y > y_max) + y_max = y; + } + src += 4; + } + } + if (y_min > y_max) { + s->last_hw_cursor_y_start = 0; + s->last_hw_cursor_y_end = 0; + } else { + s->last_hw_cursor_y_start = y_min; + s->last_hw_cursor_y_end = y_max + 1; + } +} + +/* NOTE: we do not currently handle the cursor bitmap change, so we + update the cursor only if it moves. */ +static void cirrus_cursor_invalidate(VGAState *s1) +{ + CirrusVGAState *s = (CirrusVGAState *)s1; + int size; + + if (!s->sr[0x12] & CIRRUS_CURSOR_SHOW) { + size = 0; + } else { + if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) + size = 64; + else + size = 32; + } + /* invalidate last cursor and new cursor if any change */ + if (s->last_hw_cursor_size != size || + s->last_hw_cursor_x != s->hw_cursor_x || + s->last_hw_cursor_y != s->hw_cursor_y) { + + invalidate_cursor1(s); + + s->last_hw_cursor_size = size; + s->last_hw_cursor_x = s->hw_cursor_x; + s->last_hw_cursor_y = s->hw_cursor_y; + /* compute the real cursor min and max y */ + cirrus_cursor_compute_yrange(s); + invalidate_cursor1(s); + cirrusvga_updated = 1; + } +} + +static int get_depth_index(DisplayState *s) +{ + switch(ds_get_bits_per_pixel(s)) { + default: + case 8: + return 0; + case 15: + return 1; + case 16: + return 2; + case 32: + return 3; + } +} +static void cirrus_cursor_draw_line(VGAState *s1, uint8_t *d1, int scr_y) +{ +} + +/*************************************** + * + * LFB memory access + * + ***************************************/ + +void cirrus_linear_mmio_update(void *opaque) +{ +#if defined(SUPPORT_IA32_HAXM) + CirrusVGAState *s = (CirrusVGAState *) opaque; + uint32_t_ ret; + uint8_t mode; + uint8_t linmmio = (s->sr[0x17] & 0x44) == 0x44; + mode = s->gr[0x05] & 0x7; + + if((0) || + (s->cirrus_srcptr != s->cirrus_srcptr_end) || + ((s->gr[0x0B] & 0x14) == 0x14) || + (s->gr[0x0B] & 0x02) || + !(mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0))){ + if(mmio_mode != MMIO_MODE_MMIO){ + if(np2clvga.VRAMWindowAddr){ + if(mmio_mode_region1) i386hax_vm_removememoryarea(vramptr, mmio_mode_region1, cirrusvga->real_vram_size - (mmio_mode==MMIO_MODE_VRAM1 ? 0x1000 : 0)); + } + mmio_mode_region1 = 0; + if(np2clvga.pciLFB_Addr){ + if(mmio_mode_region2) i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, cirrusvga->real_vram_size); + } + mmio_mode_region2 = 0; + lastlinmmio = linmmio; + mmio_mode = MMIO_MODE_MMIO; + } + }else{ + //if((s->sr[0x17] & 0x44) == 0x44 && (s->gr[0x6] & 0x0c) == 0x04){ + // if(mmio_mode != MMIO_MODE_VRAM1 || np2clvga.VRAMWindowAddr!=mmio_mode_region1 || np2clvga.pciLFB_Addr!=mmio_mode_region2 || lastlinmmio!=linmmio){ + // if(np2clvga.VRAMWindowAddr){ + // if(mmio_mode_region1) i386hax_vm_removememoryarea(vramptr, mmio_mode_region1, cirrusvga->real_vram_size); + // i386hax_vm_setmemoryarea(vramptr, np2clvga.VRAMWindowAddr, cirrusvga->real_vram_size - 0x1000); + // } + // mmio_mode_region1 = np2clvga.VRAMWindowAddr; + // if(np2clvga.pciLFB_Addr){ + // if(mmio_mode_region2) i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, linmmio ? s->linear_mmio_mask : cirrusvga->real_vram_size); + // i386hax_vm_setmemoryarea(vramptr, np2clvga.pciLFB_Addr, linmmio ? s->linear_mmio_mask : cirrusvga->real_vram_size); + // } + // mmio_mode_region2 = np2clvga.pciLFB_Addr; + // lastlinmmio = linmmio; + // mmio_mode = MMIO_MODE_VRAM1; + // } + //}else{ + if(mmio_mode != MMIO_MODE_VRAM2 || np2clvga.VRAMWindowAddr!=mmio_mode_region1 || np2clvga.pciLFB_Addr!=mmio_mode_region2 || lastlinmmio!=linmmio){ + if(np2clvga.VRAMWindowAddr){ + if(mmio_mode_region1) i386hax_vm_removememoryarea(vramptr, mmio_mode_region1, cirrusvga->real_vram_size - (mmio_mode==MMIO_MODE_VRAM1 ? 0x1000 : 0)); + i386hax_vm_setmemoryarea(vramptr, np2clvga.VRAMWindowAddr, cirrusvga->real_vram_size); + } + mmio_mode_region1 = np2clvga.VRAMWindowAddr; + if(np2clvga.pciLFB_Addr){ + if(mmio_mode_region2) i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, linmmio ? s->linear_mmio_mask : cirrusvga->real_vram_size); + i386hax_vm_setmemoryarea(vramptr, np2clvga.pciLFB_Addr, linmmio ? s->linear_mmio_mask : cirrusvga->real_vram_size); + } + mmio_mode_region2 = np2clvga.pciLFB_Addr; + lastlinmmio = linmmio; + mmio_mode = MMIO_MODE_VRAM2; + } + //} + } +#endif + cirrusvga_updated = 1; +} + +uint32_t_ cirrus_linear_readb(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + uint32_t_ ret; + + addr &= s->cirrus_addr_mask; + + if (((s->sr[0x17] & 0x44) == 0x44) && + ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) { + /* memory-mapped I/O */ + ret = cirrus_mmio_blt_read(s, addr & 0xff); + } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { + /* XXX handle bitblt */ + //ret = 0xff; + ret = *s->cirrus_srcptr; + s->cirrus_srcptr++; + if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { + cirrus_bitblt_videotocpu_next(s); + } + } else { + /* video memory */ + if ((s->gr[0x0B] & 0x14) == 0x14) { + addr <<= 4; + } else if (s->gr[0x0B] & 0x02) { + addr <<= 3; + } + addr &= s->cirrus_addr_mask; + ret = *(s->vram_ptr + addr); + //if(addr >= 0x1ff000){ + // TRACEOUT(("vga: read 0x%x", addr)); + //} + //if (0x1fff00 <= addr && addr < 0x1fff40){ + // ret = s->cr[addr & 0xff]; + //} + //if (addr == 0x1fff40){ + // if(np2wab.relaystateint & 0x2){ + // ret = 0x80; + // }else{ + // ret = 0x00; + // } + //} + } + + return ret; +} + +uint32_t_ cirrus_linear_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_linear_readb(opaque, addr) << 8; + v |= cirrus_linear_readb(opaque, addr + 1); +#else + v = cirrus_linear_readb(opaque, addr); + v |= cirrus_linear_readb(opaque, addr + 1) << 8; +#endif + return v; +} + +uint32_t_ cirrus_linear_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_linear_readb(opaque, addr) << 24; + v |= cirrus_linear_readb(opaque, addr + 1) << 16; + v |= cirrus_linear_readb(opaque, addr + 2) << 8; + v |= cirrus_linear_readb(opaque, addr + 3); +#else + v = cirrus_linear_readb(opaque, addr); + v |= cirrus_linear_readb(opaque, addr + 1) << 8; + v |= cirrus_linear_readb(opaque, addr + 2) << 16; + v |= cirrus_linear_readb(opaque, addr + 3) << 24; +#endif + return v; +} + +void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + unsigned mode; + + addr &= s->cirrus_addr_mask; + + if (((s->sr[0x17] & 0x44) == 0x44) && + ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) { + /* memory-mapped I/O */ + cirrus_mmio_blt_write(s, addr & 0xff, val); + } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { + /* bitblt */ + *s->cirrus_srcptr++ = (uint8_t) val; + if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { + cirrus_bitblt_cputovideo_next(s); + } + } else { + /* video memory */ + if ((s->gr[0x0B] & 0x14) == 0x14) { + addr <<= 4; + } else if (s->gr[0x0B] & 0x02) { + addr <<= 3; + } + addr &= s->cirrus_addr_mask; + + mode = s->gr[0x05] & 0x7; + if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { + *(s->vram_ptr + addr) = (uint8_t) val; + cpu_physical_memory_set_dirty(s->vram_offset + addr); + cirrusvga_updated = 1; + } else { + if ((s->gr[0x0B] & 0x14) != 0x14) { + cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val); + } else { + cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val); + } + } + //if (0x1fff00 <= addr && addr < 0x1fff40){ + // cirrus_mmio_blt_write(s, addr & 0xff, val); + // //cirrus_hook_write_cr(s, addr & 0xff, val); + //} + //if (addr == 0x1fff40){ + // char dat = 0x0; + // if(val == 0x80){ + // dat = 0x2; + // } + // if((!!np2wab.relaystateint) != (!!(dat & 0x2))){ + // np2wab.relaystateint = dat & 0x2; + // np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) + // } + // np2clvga.mmioenable = (dat&0x1); + // TRACEOUT(("vga: write 0x%x=%02x", addr, val)); + //} + //if(0x1ff000 <= addr && addr < 0x1fff00){ + // TRACEOUT(("vga: write 0x%x=%02x", addr, val)); + //} + //if(addr >= 0x1ff000){ + // TRACEOUT(("vga: write 0x%x=%02x", addr, val)); + //} + } +} + +void cirrus_linear_writew(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff); + cirrus_linear_writeb(opaque, addr + 1, val & 0xff); +#else + cirrus_linear_writeb(opaque, addr, val & 0xff); + cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +void cirrus_linear_writel(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + // XXX: Workaround for Win9x Driver + CirrusVGAState *s = (CirrusVGAState *) opaque; + if(s->device_id == CIRRUS_ID_CLGD5446){ + if (((s->sr[0x17] & 0x44) == 0x44) && + ((addr & s->cirrus_addr_mask & s->linear_mmio_mask) == s->linear_mmio_mask)) { + if((addr & 0xff) == 0x0c && val==0){ + return; + } + } + } + +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff); + cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff); + cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff); + cirrus_linear_writeb(opaque, addr + 3, val & 0xff); +#else + cirrus_linear_writeb(opaque, addr, val & 0xff); + cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff); + cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff); + cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + + +static CPUReadMemoryFunc *cirrus_linear_read[3] = { + cirrus_linear_readb, + cirrus_linear_readw, + cirrus_linear_readl, +}; + +static CPUWriteMemoryFunc *cirrus_linear_write[3] = { + cirrus_linear_writeb, + cirrus_linear_writew, + cirrus_linear_writel, +}; + +void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= s->cirrus_addr_mask; + *(s->vram_ptr + addr) = val; + cpu_physical_memory_set_dirty(s->vram_offset + addr); + cirrusvga_updated = 1; +} + +void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= s->cirrus_addr_mask; + cpu_to_le16w((uint16_t_ *)(s->vram_ptr + addr), val); + cpu_physical_memory_set_dirty(s->vram_offset + addr); + cirrusvga_updated = 1; +} + +void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= s->cirrus_addr_mask; + cpu_to_le32w((uint32_t_ *)(s->vram_ptr + addr), val); + cpu_physical_memory_set_dirty(s->vram_offset + addr); + cirrusvga_updated = 1; +} + +/*************************************** + * + * E-BANK memory access + * + ***************************************/ + +// convert E-BANK VRAM window address to linear address +void cirrus_linear_memwnd_addr_convert(void *opaque, target_phys_addr_t *addrval){ + CirrusVGAState *s = (CirrusVGAState *) opaque; + int offset; + target_phys_addr_t addr = *addrval; + + if(np2clvga.gd54xxtype <= 0xff){ + //addr &= s->cirrus_addr_mask; + addr -= np2clvga.VRAMWindowAddr2; + //addr &= 0x7fff; + if ((s->gr[0x0b] & 0x01) != 0){ + /* dual bank */ + if(addr < 0x4000){ + offset = s->gr[0x09]; + }else{ + addr -= 0x4000; + offset = s->gr[0x0a]; + } + }else{ + /* single bank */ + offset = s->gr[0x09]; + } + if ((s->gr[0x0b] & 0x20) != 0) + offset <<= 14; + else + offset <<= 12; + + addr += (offset); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ + addr &= 0x7fff; + if ((s->gr[0x0b] & 0x01) != 0){ + /* dual bank */ + if(addr < 0x4000){ + offset = s->gr[0x09]; + }else{ + addr -= 0x4000; + offset = s->gr[0x0a]; + } + }else{ + /* single bank */ + offset = s->gr[0x09]; + } + if ((s->gr[0x0b] & 0x20) != 0) + offset <<= 14; + else + offset <<= 12; + + addr += (offset); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ + addr &= 0x7fff; + if ((s->gr[0x0b] & 0x01) != 0){ + /* dual bank */ + if(addr < 0x4000){ + offset = s->gr[0x09]; + }else{ + addr -= 0x4000; + offset = s->gr[0x0a]; + } + }else{ + /* single bank */ + offset = s->gr[0x09]; + } + if ((s->gr[0x0b] & 0x20) != 0) + offset <<= 14; + else + offset <<= 12; + + addr += (offset); + }else{ + addr &= 0x7fff; + if ((s->gr[0x0b] & 0x01) != 0){ + /* dual bank */ + if(addr < 0x4000){ + offset = s->gr[0x09]; + }else{ + addr -= 0x4000; + offset = s->gr[0x0a]; + } + }else{ + /* single bank */ + offset = s->gr[0x09]; + } + //if ((s->gr[0x0b] & 0x01) != 0) /* dual bank */ + // offset = s->gr[0x09/* + bank_index*/]; + //else /* single bank */ + // offset = s->gr[0x09]; + + if ((s->gr[0x0b] & 0x20) != 0) + addr += (offset) << 14L; + else + addr += (offset) << 12L; + } + addr &= s->cirrus_addr_mask; + *addrval = addr; +} +// I-O DATA用 +int cirrus_linear_memwnd_addr_convert_iodata(void *opaque, target_phys_addr_t *addrval){ + CirrusVGAState *s = (CirrusVGAState *) opaque; + int offset; + target_phys_addr_t addr = *addrval; + int ret = 0; + + // MMIO判定 + // 本当は... + // SR17[2]=1でMMIOイネーブル If this bit is set to '1', the BlT source will be system memory rather than display memory. + // 本当はそれに加えGR6[3-2]=01じゃないとMMIOモードにならない + // MMIOアドレスはSR17[6]=0:0xb8000に割り当て、1:リニアメモリの最後256byteに割り当て(CL-GD5430/'36/'40 only) + if ((s->sr[0x17] & CIRRUS_MMIO_ENABLE) != 0 && /*(s->gr[0x06] & 0x0c)==0x04 &&*/ ((addr & 0xff000) == 0xb8000)) { + ret = 1; // MMIO + } + + addr &= 0x7fff; + if ((s->gr[0x0b] & 0x01) != 0){ + /* dual bank */ + if(addr < 0x4000){ + offset = s->gr[0x09]; + }else{ + addr -= 0x4000; + offset = s->gr[0x0a]; + } + }else{ + /* single bank */ + offset = s->gr[0x09]; + if(addr >= 0x4000){ + ret = 1; // XXX: 光栄製ゲーム用??? + } + } + if ((s->gr[0x0b] & 0x20) != 0) + offset <<= 14; + else + offset <<= 12; + + addr += (offset); + addr &= s->cirrus_addr_mask; + + *addrval = addr; + + return ret; +} + +void cirrus_linear_memwnd_writeb(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd_addr_convert(opaque, &addr); + g_cirrus_linear_write[0](opaque, addr, val); + //cirrus_linear_mem_writeb(opaque, addr, val); + //cirrus_linear_writeb(opaque, addr, val); + }else{ + int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); + if(r==0){ + g_cirrus_linear_write[0](opaque, addr, val); + }else{ + cirrus_mmio_writeb_iodata(opaque, addr, val); + } + } +} + +void cirrus_linear_memwnd_writew(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd_addr_convert(opaque, &addr); + g_cirrus_linear_write[1](opaque, addr, val); + //cirrus_linear_mem_writew(opaque, addr, val); + //cirrus_linear_writew(opaque, addr, val); + }else{ + int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); + if(r==0){ + g_cirrus_linear_write[1](opaque, addr, val); + }else{ + cirrus_mmio_writew_iodata(opaque, addr, val); + } + } +} + +void cirrus_linear_memwnd_writel(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd_addr_convert(opaque, &addr); + g_cirrus_linear_write[2](opaque, addr, val); + //cirrus_linear_mem_writel(opaque, addr, val); + //cirrus_linear_writel(opaque, addr, val); + }else{ + int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); + if(r==0){ + g_cirrus_linear_write[2](opaque, addr, val); + }else{ + cirrus_mmio_writel_iodata(opaque, addr, val); + } + } +} + +uint32_t_ cirrus_linear_memwnd_readb(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd_addr_convert(opaque, &addr); + return cirrus_linear_readb(opaque, addr); + }else{ + int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); + //if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 + if ((cirrusvga_wab_40e1 & 0x02) == 0 ) { + return 0xff; //DRAM REFRESH Mode + }else if(r == 0) { + return cirrus_linear_readb(opaque, addr); + }else{ + return cirrus_mmio_readb_iodata(opaque, addr); + //return cirrus_linear_readb(opaque, addr); + } + } +} + +uint32_t_ cirrus_linear_memwnd_readw(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd_addr_convert(opaque, &addr); + return cirrus_linear_readw(opaque, addr); + }else{ + int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); + //if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 + if ((cirrusvga_wab_40e1 & 0x02) == 0 ) { + return 0xff; //DRAM REFRESH Mode + }else if (r == 0) { + return cirrus_linear_readw(opaque, addr); + }else{ + return cirrus_mmio_readw_iodata(opaque, addr); + //return cirrus_linear_readw(opaque, addr); + } + } +} + +uint32_t_ cirrus_linear_memwnd_readl(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd_addr_convert(opaque, &addr); + return cirrus_linear_readl(opaque, addr); + }else{ + int r = cirrus_linear_memwnd_addr_convert_iodata(opaque, &addr); + //if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 + if ((cirrusvga_wab_40e1 & 0x02) == 0 ) { + return 0xff; //DRAM REFRESH Mode + }else if (r == 0) { + return cirrus_linear_readl(opaque, addr); + }else{ + return cirrus_mmio_readl_iodata(opaque, addr); + //return cirrus_linear_readl(opaque, addr); + } + } +} + +/*************************************** + * + * XXX: F00000 memory access ? + * + ***************************************/ + +// XXX: convert F00000 VRAM window address to linear address(どうしたら良いか分からん) +void cirrus_linear_memwnd3_addr_convert(void *opaque, target_phys_addr_t *addrval){ + CirrusVGAState *s = (CirrusVGAState *) opaque; + int offset; + target_phys_addr_t addr = *addrval; + + addr -= np2clvga.VRAMWindowAddr3; + addr &= 0xffff; + if ((s->gr[0x0b] & 0x01) != 0){ + /* dual bank */ + if(addr < 0x8000){ + offset = s->gr[0x09]; + }else{ + addr -= 0x8000; + offset = s->gr[0x0a]; + } + }else{ + /* single bank */ + offset = s->gr[0x09]; + } + if ((s->gr[0x0b] & 0x20) != 0) + offset <<= 14; + else + offset <<= 12; + + addr += (offset); + + addr &= s->cirrus_addr_mask; + *addrval = addr; +} +// I-O DATA用 +int cirrus_linear_memwnd3_addr_convert_iodata(void *opaque, target_phys_addr_t *addrval){ + CirrusVGAState *s = (CirrusVGAState *) opaque; + int offset; + target_phys_addr_t addr = *addrval; + int ret = 0; + + // MMIO判定 + // 本当は... + // SR17[2]=1でMMIOイネーブル If this bit is set to '1', the BlT source will be system memory rather than display memory. + // 本当はそれに加えGR6[3-2]=01じゃないとMMIOモードにならない + // MMIOアドレスはSR17[6]=0:0xb8000に割り当て、1:リニアメモリの最後256byteに割り当て(CL-GD5430/'36/'40 only) + if ((s->sr[0x17] & CIRRUS_MMIO_ENABLE) != 0 /*&& (s->gr[0x06] & 0x0c)==0x04*/ && ((addr & 0xff000) == 0xb8000)) { + ret = 1; // MMIO + } + + addr -= np2clvga.VRAMWindowAddr3; + + if ((s->gr[0x0b] & 0x01) != 0){ + /* dual bank */ + if(addr < 0x8000){ + offset = s->gr[0x09]; + }else{ + addr -= 0x8000; + offset = s->gr[0x0a]; + } + }else{ + /* single bank */ + offset = s->gr[0x09]; + // if(addr >= 0x8000){ + // ret = 1; + // } + } + if ((s->gr[0x0b] & 0x20) != 0) + offset <<= 14; + else + offset <<= 12; + + addr += (offset); + addr &= s->cirrus_addr_mask; + + *addrval = addr; + + return ret; +} + +void cirrus_linear_memwnd3_writeb(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd3_addr_convert(opaque, &addr); + + //cirrus_linear_bitblt_writeb(opaque, addr, val); + g_cirrus_linear_write[0](opaque, addr, val); + //cirrus_linear_mem_writeb(opaque, addr, val); + //cirrus_linear_writeb(opaque, addr, val); + }else{ + int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); + if(r==0){ + g_cirrus_linear_write[0](opaque, addr, val); + }else{ + cirrus_mmio_writeb_iodata(opaque, addr, val); + } + } +} + +void cirrus_linear_memwnd3_writew(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd3_addr_convert(opaque, &addr); + + //cirrus_linear_bitblt_writew(opaque, addr, val); + g_cirrus_linear_write[1](opaque, addr, val); + //cirrus_linear_mem_writew(opaque, addr, val); + //cirrus_linear_writew(opaque, addr, val); + }else{ + int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); + if(r==0){ + g_cirrus_linear_write[1](opaque, addr, val); + }else{ + cirrus_mmio_writew_iodata(opaque, addr, val); + } + } +} + +void cirrus_linear_memwnd3_writel(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd3_addr_convert(opaque, &addr); + + //cirrus_linear_bitblt_writel(opaque, addr, val); + g_cirrus_linear_write[2](opaque, addr, val); + //cirrus_linear_mem_writel(opaque, addr, val); + //cirrus_linear_writel(opaque, addr, val); + }else{ + int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); + if(r==0){ + g_cirrus_linear_write[2](opaque, addr, val); + }else{ + cirrus_mmio_writel_iodata(opaque, addr, val); + } + } +} + +uint32_t_ cirrus_linear_memwnd3_readb(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd3_addr_convert(opaque, &addr); + + return cirrus_linear_readb(opaque, addr); + }else{ + int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); + // if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 + if ((cirrusvga_wab_40e1 & 0x02) == 0 ) { + return 0xff; //DRAM REFRESH Mode + }else if(r == 0) { + return cirrus_linear_readb(opaque, addr); + }else{ + return cirrus_mmio_readb_iodata(opaque, addr); + } + } +} + +uint32_t_ cirrus_linear_memwnd3_readw(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd3_addr_convert(opaque, &addr); + + return cirrus_linear_readw(opaque, addr); + }else{ + int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); + // if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 + if ((cirrusvga_wab_40e1 & 0x02) == 0) { + return 0xffff; //DRAM REFRESH Mode + }else if (r == 0) { + return cirrus_linear_readw(opaque, addr); + }else{ + return cirrus_mmio_readw_iodata(opaque, addr); + } + } +} + +uint32_t_ cirrus_linear_memwnd3_readl(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) != CIRRUS_98ID_GA98NBIC){ + cirrus_linear_memwnd3_addr_convert(opaque, &addr); + + return cirrus_linear_readl(opaque, addr); + }else{ + int r = cirrus_linear_memwnd3_addr_convert_iodata(opaque, &addr); + // if (r == 0 && (s->gr[0x31] & CIRRUS_BLT_RESET)!=0 || (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST)!=0) { // XXX: 明らかに正しくないけどとりあえず動くように調整 + if ((cirrusvga_wab_40e1 & 0x02) == 0) { + return 0xffffffff; //DRAM REFRESH Mode + }else if (r == 0) { + return cirrus_linear_readl(opaque, addr); + }else{ + return cirrus_mmio_readl_iodata(opaque, addr); + } + } +} + + +/*************************************** + * + * system to screen memory access + * + ***************************************/ + + +uint32_t_ cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + uint32_t_ ret = 0; + + /* handle bitblt */ + if (s->cirrus_srcptr != s->cirrus_srcptr_end) { + ret = *s->cirrus_srcptr; + s->cirrus_srcptr++; + if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { + cirrus_bitblt_videotocpu_next(s); + } + } + return ret; +} + +uint32_t_ cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_linear_bitblt_readb(opaque, addr) << 8; + v |= cirrus_linear_bitblt_readb(opaque, addr + 1); +#else + v = cirrus_linear_bitblt_readb(opaque, addr); + v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8; +#endif + return v; +} + +uint32_t_ cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_linear_bitblt_readb(opaque, addr) << 24; + v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16; + v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8; + v |= cirrus_linear_bitblt_readb(opaque, addr + 3); +#else + v = cirrus_linear_bitblt_readb(opaque, addr); + v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8; + v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16; + v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24; +#endif + return v; +} + +void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if (s->cirrus_srcptr != s->cirrus_srcptr_end) { + /* bitblt */ + *s->cirrus_srcptr++ = (uint8_t) val; + if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { + cirrus_bitblt_cputovideo_next(s); + } + } +} + +void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff); +#else + cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff); +#else + cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + + +static CPUReadMemoryFunc *cirrus_linear_bitblt_read[3] = { + cirrus_linear_bitblt_readb, + cirrus_linear_bitblt_readw, + cirrus_linear_bitblt_readl, +}; + +static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = { + cirrus_linear_bitblt_writeb, + cirrus_linear_bitblt_writew, + cirrus_linear_bitblt_writel, +}; + +static void map_linear_vram(CirrusVGAState *s) +{ + g_cirrus_linear_map_enabled = 1; + + vga_dirty_log_stop((VGAState *)s); + + if (!s->map_addr && s->lfb_addr && s->lfb_end) { + s->map_addr = s->lfb_addr; + s->map_end = s->lfb_end; + cpu_register_physical_memory(s->map_addr, s->map_end - s->map_addr, s->vram_offset); + } + + if (!s->map_addr) + return; + + s->lfb_vram_mapped = 0; + + // このcpu_register_physical_memoryの詳細がさっぱり分からない・・・ + cpu_register_physical_memory(isa_mem_base + 0xF80000, 0x8000, + (s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_UNASSIGNED); + cpu_register_physical_memory(isa_mem_base + 0xF88000, 0x8000, + (s->vram_offset + s->cirrus_bank_base[1]) | IO_MEM_UNASSIGNED); + if (!(s->cirrus_srcptr != s->cirrus_srcptr_end) + && !((s->sr[0x07] & 0x01) == 0) + && !((s->gr[0x0B] & 0x14) == 0x14) + && !(s->gr[0x0B] & 0x02)) { + + vga_dirty_log_stop((VGAState *)s); + // ここも + cpu_register_physical_memory(isa_mem_base + 0xF80000, 0x8000, + (s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM); + cpu_register_physical_memory(isa_mem_base + 0xF88000, 0x8000, + (s->vram_offset + s->cirrus_bank_base[1]) | IO_MEM_RAM); + + s->lfb_vram_mapped = 1; + } + else { + cpu_register_physical_memory(isa_mem_base + 0xF80000, 0x20000, + s->vga_io_memory); + } + + vga_dirty_log_start((VGAState *)s); +} + +static void unmap_linear_vram(CirrusVGAState *s) +{ + g_cirrus_linear_map_enabled = 0; + + vga_dirty_log_stop((VGAState *)s); + + if (s->map_addr && s->lfb_addr && s->lfb_end) + s->map_addr = s->map_end = 0; + + // ここも + cpu_register_physical_memory(isa_mem_base + 0xF80000, 0x20000, + s->vga_io_memory); + + vga_dirty_log_start((VGAState *)s); +} + +/* Compute the memory access functions */ +static void cirrus_update_memory_access(CirrusVGAState *s) +{ + unsigned mode; + + // メモリ割り付けアドレス更新 + + // inear address + // sr7[7-4]<>0:sr7[7-4]をaddress23-20に割り当て、ただしgrb[5]=1の時sr7[4]はd.c. + // sr7[7-4] =0:gr6[3-2]=00,01:A0000に割り当て 10,11:B0000に割り当て + // WSNは42e1hがかかわっているかも????? + + if (np2clvga.gd54xxtype > 0xff && (cirrusvga_wab_42e1 & 0x18) == 0x18){ + np2clvga.VRAMWindowAddr3 = 0xf00000; + } + else if ( +#if defined(SUPPORT_VGA_MODEX) + !np2clvga.modex && +#endif + (s->sr[0x07] & CIRRUS_SR7_ISAADDR_MASK) != 0) { + np2clvga.VRAMWindowAddr3 = (s->sr[0x07] & CIRRUS_SR7_ISAADDR_MASK & ~((s->gr[0x0b] >> 1) & 0x10)) << 16; + } + else { +#if defined(SUPPORT_VGA_MODEX) + if(np2clvga.modex){ + if (s->gr[0x06] & 0x08) { + np2clvga.VRAMWindowAddr3 = 0xb0000; + } + else { + np2clvga.VRAMWindowAddr3 = 0xa0000; + } + }else +#endif + { + // アクセス不可にしておく + np2clvga.VRAMWindowAddr3 = 0; + } + } + + if ((s->sr[0x17] & 0x44) == 0x44) { + goto generic_io; + } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { + goto generic_io; + } else { + if ((s->gr[0x0B] & 0x14) == 0x14) { + goto generic_io; + } else if (s->gr[0x0B] & 0x02) { + goto generic_io; + } + + mode = s->gr[0x05] & 0x7; + if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { + map_linear_vram(s); + g_cirrus_linear_write[0] = cirrus_linear_mem_writeb; + g_cirrus_linear_write[1] = cirrus_linear_mem_writew; + g_cirrus_linear_write[2] = cirrus_linear_mem_writel; + } else { + generic_io: + unmap_linear_vram(s); + g_cirrus_linear_write[0] = cirrus_linear_writeb; + g_cirrus_linear_write[1] = cirrus_linear_writew; + g_cirrus_linear_write[2] = cirrus_linear_writel; + } + } + cirrus_linear_mmio_update(s); +} + + +/* I/O ports */ +// PC-98用I/Oポート -> CL-GD54xxネイティブポート変換 +uint32_t_ vga_convert_ioport(uint32_t_ addr){ +#if defined(SUPPORT_PCI) + // PCI版はポート番号そのまま + if(pcidev.enable && + (np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI)){ + if((addr & 0xFF0) == 0x3C0 || (addr & 0xFF0) == 0x3B0 || (addr & 0xFF0) == 0x3D0){ + np2clvga.gd54xxtype = CIRRUS_98ID_PCI; + cirrusvga->sr[0x1F] = 0x2d; // MemClock + cirrusvga->gr[0x18] = 0x0f; // fastest memory configuration + cirrusvga->sr[0x0f] = CIRRUS_MEMSIZE_2M; + cirrusvga->sr[0x17] = 0x20; + cirrusvga->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ + cirrusvga->device_id = CIRRUS_ID_CLGD5446; + cirrusvga->cr[0x27] = cirrusvga->device_id; + cirrusvga->bustype = CIRRUS_BUSTYPE_PCI; +#if defined(SUPPORT_IA32_HAXM) + i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); + i386hax_vm_removememoryarea(vramptr, np2clvga.pciLFB_Addr, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); + lastlinmmio = 0; +#endif + cirrus_update_memory_access(cirrusvga); + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + } + } +#endif + if(np2clvga.gd54xxtype <= 0xff){ + // 内蔵・純正ボード用 + if((addr & 0xFF0) == 0xCA0 || (addr & 0xFF0) == 0xC50){ + addr = 0x3C0 | (addr & 0xf); + }else{ + if(addr==0xBA4 || addr==0xB54) addr = 0x3B4; + if(addr==0xBA5 || addr==0xB55) addr = 0x3B5; + if(addr==0xDA4 || addr==0xD54) addr = 0x3D4; + if(addr==0xDA5 || addr==0xD55) addr = 0x3D5; + if(addr==0xBAA || addr==0xB5A) addr = 0x3BA; + if(addr==0xDAA || addr==0xD5A) addr = 0x3DA; + } + }else{ + // WAB用 + if((addr & 0xF0FF) == (0x40E0 | cirrusvga_melcowab_ofs)){ + addr = 0x3C0 | ((addr >> 8) & 0xf); + }else{ + //if(addr==0x51E1+cirrusvga_melcowab_ofs) addr = 0x3B4; // ??? + //if(addr==0x57E1+cirrusvga_melcowab_ofs) addr = 0x3B5; // ??? + //if(addr==0x54E0+cirrusvga_melcowab_ofs) addr = 0x3D4; + //if(addr==0x55E0+cirrusvga_melcowab_ofs) addr = 0x3D5; + //if(addr==0x5BE1+cirrusvga_melcowab_ofs) addr = 0x3BA; // ??? + //if(addr==0x5AE0+cirrusvga_melcowab_ofs) addr = 0x3DA; + if (addr == 0x58E0 + cirrusvga_melcowab_ofs) addr = 0x3B4; + if (addr == 0x59E0 + cirrusvga_melcowab_ofs) addr = 0x3B5; + ////if (addr == 0x3AE0 + cirrusvga_melcowab_ofs) addr = 0x3BA; + if (addr == 0x54E0 + cirrusvga_melcowab_ofs) addr = 0x3D4; + if (addr == 0x55E0 + cirrusvga_melcowab_ofs) addr = 0x3D5; + if (addr == 0x5AE0 + cirrusvga_melcowab_ofs) addr = 0x3DA; + } + } + return addr; +} + +static uint32_t_ vga_ioport_read(void *opaque, uint32_t_ addr) +{ + CirrusVGAState *s = (CirrusVGAState *)opaque; + int val, index; + + // ポート決め打ちなので無理矢理変換 + addr = vga_convert_ioport(addr); + + //TRACEOUT(("CIRRUS VGA: read %04X", addr)); + + /* check port range access depending on color/monochrome mode */ + if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) + || (addr >= 0x3d0 && addr <= 0x3df + && !(s->msr & MSR_COLOR_EMULATION))) { + val = 0xff; + } else { + switch (addr) { + case 0x3c0: + if (s->ar_flip_flop == 0) { + val = s->ar_index; + } else { + val = 0; + } + break; + case 0x3c1: + index = s->ar_index & 0x1f; + if (index < 21) + val = s->ar[index]; + else + val = 0; + break; + case 0x3c2: + val = s->st00; + break; + case 0x3c4: + val = s->sr_index; + break; + case 0x3c5: + if (cirrus_hook_read_sr(s, s->sr_index, &val)) + break; + val = s->sr[s->sr_index]; +#ifdef DEBUG_VGA_REG + printf("vga: read SR%x = 0x%02x\n", s->sr_index, val); +#endif + break; + case 0x3c6: + cirrus_read_hidden_dac(s, &val); + break; + case 0x3c7: + val = s->dac_state; + break; + case 0x3c8: + val = s->dac_write_index; + s->cirrus_hidden_dac_lockindex = 0; + break; + case 0x3c9: + if (cirrus_hook_read_palette(s, &val)) + break; + val = s->palette[s->dac_read_index * 3 + s->dac_sub_index]; + if (++s->dac_sub_index == 3) { + s->dac_sub_index = 0; + s->dac_read_index++; + } + break; + case 0x3ca: + val = s->fcr; + break; + case 0x3cc: + val = s->msr; + break; + case 0x3ce: + val = s->gr_index; + break; + case 0x3cf: + if (cirrus_hook_read_gr(s, s->gr_index, &val)) + break; + val = s->gr[s->gr_index]; +#ifdef DEBUG_VGA_REG + printf("vga: read GR%x = 0x%02x\n", s->gr_index, val); +#endif + break; + case 0x3b4: + case 0x3d4: + val = s->cr_index; + break; + case 0x3b5: + case 0x3d5: + if (cirrus_hook_read_cr(s, s->cr_index, &val)) + break; + val = s->cr[s->cr_index]; +#ifdef DEBUG_VGA_REG + printf("vga: read CR%x = 0x%02x\n", s->cr_index, val); +#endif + break; + case 0x3ba: + case 0x3da: + /* just toggle to fool polling */ + val = s->st01 = s->retrace((VGAState *) s); + //if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ + // val = 0xC2; + //} + //if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ + // val = 0xc7; + //} + s->ar_flip_flop = 0; + break; + default: + val = 0x00; + break; + } + } +#if defined(TRACE) + //TRACEOUT(("VGA: read addr=0x%04x data=0x%02x\n", addr, val)); +#endif + return val; +} +static REG8 IOOUTCALL vga_ioport_read_wrap(UINT addr) +{ + return vga_ioport_read(cirrusvga, addr); +} +UINT IOOUTCALL cirrusvga_ioport_read_wrap16(UINT addr) +{ + UINT16 ret; + addr = vga_convert_ioport(addr); + ret = ((REG16)vga_ioport_read(cirrusvga, addr ) ); + ret |= ((REG16)vga_ioport_read(cirrusvga, addr+1) << 8); + return ret; +} +UINT IOOUTCALL cirrusvga_ioport_read_wrap32(UINT addr) +{ + UINT32 ret; + addr = vga_convert_ioport(addr); + ret = ((UINT32)vga_ioport_read(cirrusvga, addr ) ); + ret |= ((UINT32)vga_ioport_read(cirrusvga, addr+1) << 8); + ret |= ((UINT32)vga_ioport_read(cirrusvga, addr+2) << 16); + ret |= ((UINT32)vga_ioport_read(cirrusvga, addr+3) << 24); + return ret; +} + +static void vga_ioport_write(void *opaque, uint32_t_ addr, uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *)opaque; + int index; + + // ポート決め打ちなので無理矢理変換 + addr = vga_convert_ioport(addr); + + //TRACEOUT(("CIRRUS VGA: write %04X %02X", addr, val)); + + /* check port range access depending on color/monochrome mode */ + if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) + || (addr >= 0x3d0 && addr <= 0x3df + && !(s->msr & MSR_COLOR_EMULATION))) + return; + +#ifdef TRACE + //TRACEOUT(("VGA: write addr=0x%04x data=0x%02x\n", addr, val)); +#endif + + switch (addr) { + case 0x3c0: + if (s->ar_flip_flop == 0) { + val &= 0x3f; + s->ar_index = val; + } else { + index = s->ar_index & 0x1f; + switch (index) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + s->ar[index] = val & 0x3f; + break; + case 0x10: + s->ar[index] = val & ~0x10; + break; + case 0x11: + s->ar[index] = val; + break; + case 0x12: + s->ar[index] = val & ~0xc0; + break; + case 0x13: + s->ar[index] = val & ~0xf0; + break; + case 0x14: + s->ar[index] = val & ~0xf0; + break; + default: + break; + } + } + s->ar_flip_flop ^= 1; + break; + case 0x3c2: + s->msr = val & ~0x10; + s->update_retrace_info((VGAState *) s); + break; + case 0x3c4: + s->sr_index = val; + break; + case 0x3c5: + if (cirrus_hook_write_sr(s, s->sr_index, val)) + break; +#ifdef DEBUG_VGA_REG + printf("vga: write SR%x = 0x%02x\n", s->sr_index, val); +#endif + s->sr[s->sr_index] = val & sr_mask[s->sr_index]; + if (s->sr_index == 1) s->update_retrace_info((VGAState *) s); + break; + case 0x3c6: + cirrus_write_hidden_dac(s, val); + break; + case 0x3c7: + s->dac_read_index = val; + s->dac_sub_index = 0; + s->dac_state = 3; + break; + case 0x3c8: + s->dac_write_index = val; + s->dac_sub_index = 0; + s->dac_state = 0; + break; + case 0x3c9: + if (cirrus_hook_write_palette(s, val)) + break; + s->dac_cache[s->dac_sub_index] = val; + if (++s->dac_sub_index == 3) { + memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3); + s->dac_sub_index = 0; + s->dac_write_index++; + np2wab.paletteChanged = 1; // パレット変えました + cirrusvga_updated = 1; + } + break; + //case 0x3cc: + // s->msr = val; + // break; + case 0x3ce: + s->gr_index = val; + break; + case 0x3cf: + if (cirrus_hook_write_gr(s, s->gr_index, val)) + break; +#ifdef DEBUG_VGA_REG + printf("vga: write GR%x = 0x%02x\n", s->gr_index, val); +#endif + s->gr[s->gr_index] = val & gr_mask[s->gr_index]; + break; + case 0x3b4: + case 0x3d4: + s->cr_index = val; + break; + case 0x3b5: + case 0x3d5: + if (cirrus_hook_write_cr(s, s->cr_index, val)) + { + cirrusvga_updated = 1; + break; + } +#ifdef DEBUG_VGA_REG + printf("vga: write CR%x = 0x%02x\n", s->cr_index, val); +#endif + /* handle CR0-7 protection */ + if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) { + /* can always write bit 4 of CR7 */ + if (s->cr_index == 7) + s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); + cirrusvga_updated = 1; + return; + } + switch (s->cr_index) { + case 0x01: /* horizontal display end */ + case 0x07: + case 0x09: + case 0x0c: + case 0x0d: + case 0x12: /* vertical display end */ + s->cr[s->cr_index] = val; + break; + + default: + s->cr[s->cr_index] = val; + break; + } + + switch(s->cr_index) { + case 0x00: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x11: + case 0x17: + s->update_retrace_info((VGAState *) s); + break; + } + //if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ + // int width, height; + // cirrus_get_resolution((VGAState *) s, &width, &height); + // switch(s->cr_index) { + // case 0x04: + // if(width==640) + // np2wab.shiftX = val - 0x54; + // else if(width==800) + // np2wab.shiftX = val - 0x69; + // else if(width==1024) + // np2wab.shiftX = val - 0x85; + // else + // np2wab.shiftX = 0; + // break; + // case 0x10: + // if(width==640) + // np2wab.shiftX = val - 0xEA; + // else if(width==800) + // np2wab.shiftX = val - 0x5D; + // else if(width==1024) + // np2wab.shiftX = val - 0x68; + // else + // np2wab.shiftX = 0; + // break; + // } + //} + cirrusvga_updated = 1; + break; + case 0x3ba: + case 0x3da: + s->fcr = val & 0x10; + break; + } +} +static void IOOUTCALL vga_ioport_write_wrap(UINT addr, REG8 dat) +{ + vga_ioport_write(cirrusvga, addr, dat); +} +void IOOUTCALL cirrusvga_ioport_write_wrap16(UINT addr, UINT dat) +{ + addr = vga_convert_ioport(addr); + vga_ioport_write(cirrusvga, addr , ((UINT32)dat ) & 0xff); + vga_ioport_write(cirrusvga, addr+1, ((UINT32)dat >> 8) & 0xff); +} +void IOOUTCALL cirrusvga_ioport_write_wrap32(UINT addr, UINT dat) +{ + addr = vga_convert_ioport(addr); + vga_ioport_write(cirrusvga, addr , (dat ) & 0xff); + vga_ioport_write(cirrusvga, addr+1, (dat >> 8) & 0xff); + vga_ioport_write(cirrusvga, addr+2, (dat >> 16) & 0xff); + vga_ioport_write(cirrusvga, addr+3, (dat >> 24) & 0xff); +} + +/*************************************** + * + * memory-mapped I/O access + * + ***************************************/ + +uint32_t_ cirrus_mmio_readb(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= CIRRUS_PNPMMIO_SIZE - 1; + + if (addr >= 0x100) { + return cirrus_mmio_blt_read(s, addr - 0x100); + } else { + return vga_ioport_read(s, addr + 0x3c0); + } +} + +uint32_t_ cirrus_mmio_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_mmio_readb(opaque, addr) << 8; + v |= cirrus_mmio_readb(opaque, addr + 1); +#else + v = cirrus_mmio_readb(opaque, addr); + v |= cirrus_mmio_readb(opaque, addr + 1) << 8; +#endif + return v; +} + +uint32_t_ cirrus_mmio_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_mmio_readb(opaque, addr) << 24; + v |= cirrus_mmio_readb(opaque, addr + 1) << 16; + v |= cirrus_mmio_readb(opaque, addr + 2) << 8; + v |= cirrus_mmio_readb(opaque, addr + 3); +#else + v = cirrus_mmio_readb(opaque, addr); + v |= cirrus_mmio_readb(opaque, addr + 1) << 8; + v |= cirrus_mmio_readb(opaque, addr + 2) << 16; + v |= cirrus_mmio_readb(opaque, addr + 3) << 24; +#endif + return v; +} + +void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= CIRRUS_PNPMMIO_SIZE - 1; + + if (addr >= 0x100) { + cirrus_mmio_blt_write(s, addr - 0x100, val); + } else { + vga_ioport_write(s, addr + 0x3c0, val); + } +} + +void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff); + cirrus_mmio_writeb(opaque, addr + 1, val & 0xff); +#else + cirrus_mmio_writeb(opaque, addr, val & 0xff); + cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff); + cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff); + cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff); + cirrus_mmio_writeb(opaque, addr + 3, val & 0xff); +#else + cirrus_mmio_writeb(opaque, addr, val & 0xff); + cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff); + cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff); + cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + +uint32_t_ cirrus_mmio_readb_wab(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= ~np2clvga.pciMMIO_Mask; + if (addr >= 0x8000) { + return cirrus_mmio_blt_read(s, (addr - 0x8000) & 0x7fff); + } else { + return vga_ioport_read(s, addr & 0x7fff); + } +} + +uint32_t_ cirrus_mmio_readw_wab(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_mmio_readb_wab(opaque, addr) << 8; + v |= cirrus_mmio_readb_wab(opaque, addr + 1); +#else + v = cirrus_mmio_readb_wab(opaque, addr); + v |= cirrus_mmio_readb_wab(opaque, addr + 1) << 8; +#endif + return v; +} + +uint32_t_ cirrus_mmio_readl_wab(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_mmio_readb_wab(opaque, addr) << 24; + v |= cirrus_mmio_readb_wab(opaque, addr + 1) << 16; + v |= cirrus_mmio_readb_wab(opaque, addr + 2) << 8; + v |= cirrus_mmio_readb_wab(opaque, addr + 3); +#else + v = cirrus_mmio_readb_wab(opaque, addr); + v |= cirrus_mmio_readb_wab(opaque, addr + 1) << 8; + v |= cirrus_mmio_readb_wab(opaque, addr + 2) << 16; + v |= cirrus_mmio_readb_wab(opaque, addr + 3) << 24; +#endif + return v; +} + +void cirrus_mmio_writeb_wab(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= ~np2clvga.pciMMIO_Mask; + if (addr >= 0x8000) { + //addr = (addr - 0x8000) & 0x7fff; + cirrus_mmio_blt_write(s, (addr - 0x8000) & 0x7fff, val); + } else { + //addr = addr & 0x7fff; + //if(addr > CIRRUS_PNPMMIO_SIZE) return; + vga_ioport_write(s, addr & 0x7fff, val); + } +} + +void cirrus_mmio_writew_wab(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_mmio_writeb_wab(opaque, addr, (val >> 8) & 0xff); + cirrus_mmio_writeb_wab(opaque, addr + 1, val & 0xff); +#else + cirrus_mmio_writeb_wab(opaque, addr, val & 0xff); + cirrus_mmio_writeb_wab(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +void cirrus_mmio_writel_wab(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_mmio_writeb_wab(opaque, addr, (val >> 24) & 0xff); + cirrus_mmio_writeb_wab(opaque, addr + 1, (val >> 16) & 0xff); + cirrus_mmio_writeb_wab(opaque, addr + 2, (val >> 8) & 0xff); + cirrus_mmio_writeb_wab(opaque, addr + 3, val & 0xff); +#else + cirrus_mmio_writeb_wab(opaque, addr, val & 0xff); + cirrus_mmio_writeb_wab(opaque, addr + 1, (val >> 8) & 0xff); + cirrus_mmio_writeb_wab(opaque, addr + 2, (val >> 16) & 0xff); + cirrus_mmio_writeb_wab(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + +uint32_t_ cirrus_mmio_readb_iodata(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= ~np2clvga.pciMMIO_Mask; + addr = (addr - 0x8000) & 0x7fff; + return cirrus_mmio_blt_read(s, (addr/* - 0x8000*/) & (CIRRUS_PNPMMIO_SIZE-1)); +} + +uint32_t_ cirrus_mmio_readw_iodata(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_mmio_readb_iodata(opaque, addr) << 8; + v |= cirrus_mmio_readb_iodata(opaque, addr + 1); +#else + v = cirrus_mmio_readb_iodata(opaque, addr); + v |= cirrus_mmio_readb_iodata(opaque, addr + 1) << 8; +#endif + return v; +} + +uint32_t_ cirrus_mmio_readl_iodata(void *opaque, target_phys_addr_t addr) +{ + uint32_t_ v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_mmio_readb_iodata(opaque, addr) << 24; + v |= cirrus_mmio_readb_iodata(opaque, addr + 1) << 16; + v |= cirrus_mmio_readb_iodata(opaque, addr + 2) << 8; + v |= cirrus_mmio_readb_iodata(opaque, addr + 3); +#else + v = cirrus_mmio_readb_iodata(opaque, addr); + v |= cirrus_mmio_readb_iodata(opaque, addr + 1) << 8; + v |= cirrus_mmio_readb_iodata(opaque, addr + 2) << 16; + v |= cirrus_mmio_readb_iodata(opaque, addr + 3) << 24; +#endif + return v; +} + +void cirrus_mmio_writeb_iodata(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= ~np2clvga.pciMMIO_Mask; + if ((s->gr[0x31] & CIRRUS_BLT_BUSY)==0) { + addr = (addr - 0x8000) & 0x7fff; + cirrus_mmio_blt_write(s, (addr/* - 0x8000*/) & (CIRRUS_PNPMMIO_SIZE-1), val); + } + /*}*/ + // } else { + ////addr = addr & 0x7fff; + ////if(addr > CIRRUS_PNPMMIO_SIZE) return; + // //vga_ioport_write(s, addr & 0x7fff, val); + // } +} + +void cirrus_mmio_writew_iodata(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_mmio_writeb_iodata(opaque, addr, (val >> 8) & 0xff); + cirrus_mmio_writeb_iodata(opaque, addr + 1, val & 0xff); +#else + cirrus_mmio_writeb_iodata(opaque, addr, val & 0xff); + cirrus_mmio_writeb_iodata(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +void cirrus_mmio_writel_iodata(void *opaque, target_phys_addr_t addr, + uint32_t_ val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_mmio_writeb_iodata(opaque, addr, (val >> 24) & 0xff); + cirrus_mmio_writeb_iodata(opaque, addr + 1, (val >> 16) & 0xff); + cirrus_mmio_writeb_iodata(opaque, addr + 2, (val >> 8) & 0xff); + cirrus_mmio_writeb_iodata(opaque, addr + 3, val & 0xff); +#else + cirrus_mmio_writeb_iodata(opaque, addr, val & 0xff); + cirrus_mmio_writeb_iodata(opaque, addr + 1, (val >> 8) & 0xff); + cirrus_mmio_writeb_iodata(opaque, addr + 2, (val >> 16) & 0xff); + cirrus_mmio_writeb_iodata(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + + +CPUReadMemoryFunc *cirrus_mmio_read[3] = { + cirrus_mmio_readb, + cirrus_mmio_readw, + cirrus_mmio_readl, +}; + +CPUWriteMemoryFunc *cirrus_mmio_write[3] = { + cirrus_mmio_writeb, + cirrus_mmio_writew, + cirrus_mmio_writel, +}; + +#define array_write(ary, pos, data, len) \ + memcpy(ary+pos, data, len); \ + pos += len; + +#define array_read(ary, pos, data, len) \ + memcpy(data, ary+pos, len); \ + pos += len; + + +/* load/save state */ +void pc98_cirrus_vga_save() +{ + CirrusVGAState *s = cirrusvga; + int pos = 0; + UINT8 *f = cirrusvga_statsavebuf; + //char test[500] = {0}; + uint32_t_ state_ver = 6; + uint32_t_ intbuf; + char en[3] = "en"; + + array_write(f, pos, &state_ver, sizeof(state_ver)); // ステートセーブ バージョン番号 + + if(vramptr == NULL || s == NULL) { + strcpy(en, "di"); + array_write(f, pos, en, 2); + return; + } + array_write(f, pos, en, 2); + + // この際全部保存 + array_write(f, pos, vramptr, CIRRUS_VRAM_SIZE); + array_write(f, pos, &s->vram_offset, sizeof(s->vram_offset)); + array_write(f, pos, &s->vram_size, sizeof(s->vram_size)); + array_write(f, pos, &s->lfb_addr, sizeof(s->lfb_addr)); + array_write(f, pos, &s->lfb_end, sizeof(s->lfb_end)); + array_write(f, pos, &s->map_addr, sizeof(s->map_addr)); + array_write(f, pos, &s->map_end, sizeof(s->map_end)); + array_write(f, pos, &s->lfb_vram_mapped, sizeof(s->lfb_vram_mapped)); + array_write(f, pos, &s->bios_offset, sizeof(s->bios_offset)); + array_write(f, pos, &s->bios_size, sizeof(s->bios_size)); + array_write(f, pos, &s->it_shift, sizeof(s->it_shift)); + + array_write(f, pos, &s->latch, sizeof(s->latch)); + array_write(f, pos, &s->sr_index, sizeof(s->sr_index)); + array_write(f, pos, s->sr, sizeof(s->sr)); + array_write(f, pos, &s->gr_index, sizeof(s->gr_index)); + array_write(f, pos, s->gr, sizeof(s->gr)); + array_write(f, pos, &s->ar_index, sizeof(s->ar_index)); + array_write(f, pos, s->ar, sizeof(s->ar)); + array_write(f, pos, &s->ar_flip_flop, sizeof(s->ar_flip_flop)); + array_write(f, pos, &s->cr_index, sizeof(s->cr_index)); + array_write(f, pos, s->cr, sizeof(s->cr)); + array_write(f, pos, &s->msr, sizeof(s->msr)); + array_write(f, pos, &s->fcr, sizeof(s->fcr)); + array_write(f, pos, &s->st00, sizeof(s->st00)); + array_write(f, pos, &s->st01, sizeof(s->st01)); + array_write(f, pos, &s->dac_state, sizeof(s->dac_state)); + array_write(f, pos, &s->dac_sub_index, sizeof(s->dac_sub_index)); + array_write(f, pos, &s->dac_read_index, sizeof(s->dac_read_index)); + array_write(f, pos, &s->dac_write_index, sizeof(s->dac_write_index)); + array_write(f, pos, s->dac_cache, sizeof(s->dac_cache)); + array_write(f, pos, &s->dac_8bit, sizeof(s->dac_8bit)); + array_write(f, pos, s->palette, sizeof(s->palette)); + array_write(f, pos, &s->bank_offset, sizeof(s->bank_offset)); + array_write(f, pos, &s->vga_io_memory, sizeof(s->vga_io_memory)); + array_write(f, pos, &s->vbe_index, sizeof(s->vbe_index)); + array_write(f, pos, s->vbe_regs, sizeof(s->vbe_regs)); + array_write(f, pos, &s->vbe_start_addr, sizeof(s->vbe_start_addr)); + array_write(f, pos, &s->vbe_line_offset, sizeof(s->vbe_line_offset)); + array_write(f, pos, &s->vbe_bank_mask, sizeof(s->vbe_bank_mask)); + + array_write(f, pos, s->font_offsets, sizeof(s->font_offsets)); + array_write(f, pos, &s->graphic_mode, sizeof(s->graphic_mode)); + array_write(f, pos, &s->shift_control, sizeof(s->shift_control)); + array_write(f, pos, &s->double_scan, sizeof(s->double_scan)); + array_write(f, pos, &s->line_offset, sizeof(s->line_offset)); + array_write(f, pos, &s->line_compare, sizeof(s->line_compare)); + array_write(f, pos, &s->start_addr, sizeof(s->start_addr)); + array_write(f, pos, &s->plane_updated, sizeof(s->plane_updated)); + array_write(f, pos, &s->last_line_offset, sizeof(s->last_line_offset)); + array_write(f, pos, &s->last_cw, sizeof(s->last_cw)); + array_write(f, pos, &s->last_ch, sizeof(s->last_ch)); + array_write(f, pos, &s->last_width, sizeof(s->last_width)); + array_write(f, pos, &s->last_height, sizeof(s->last_height)); + array_write(f, pos, &s->last_scr_width, sizeof(s->last_scr_width)); + array_write(f, pos, &s->last_scr_height, sizeof(s->last_scr_height)); + array_write(f, pos, &s->last_depth, sizeof(s->last_depth)); + array_write(f, pos, &s->cursor_start, sizeof(s->cursor_start)); + array_write(f, pos, &s->cursor_end, sizeof(s->cursor_end)); + array_write(f, pos, &s->cursor_offset, sizeof(s->cursor_offset)); + + array_write(f, pos, s->invalidated_y_table, sizeof(s->invalidated_y_table)); + array_write(f, pos, s->last_palette, sizeof(s->last_palette)); + array_write(f, pos, s->last_ch_attr, sizeof(s->last_ch_attr)); + + array_write(f, pos, &s->cirrus_linear_io_addr, sizeof(s->cirrus_linear_io_addr)); + array_write(f, pos, &s->cirrus_linear_bitblt_io_addr, sizeof(s->cirrus_linear_bitblt_io_addr)); + array_write(f, pos, &s->cirrus_mmio_io_addr, sizeof(s->cirrus_mmio_io_addr)); + array_write(f, pos, &s->cirrus_addr_mask, sizeof(s->cirrus_addr_mask)); + array_write(f, pos, &s->linear_mmio_mask, sizeof(s->linear_mmio_mask)); + array_write(f, pos, &s->cirrus_shadow_gr0, sizeof(s->cirrus_shadow_gr0)); + array_write(f, pos, &s->cirrus_shadow_gr1, sizeof(s->cirrus_shadow_gr1)); + array_write(f, pos, &s->cirrus_hidden_dac_lockindex, sizeof(s->cirrus_hidden_dac_lockindex)); + array_write(f, pos, &s->cirrus_hidden_dac_data, sizeof(s->cirrus_hidden_dac_data)); + array_write(f, pos, s->cirrus_bank_base, sizeof(s->cirrus_bank_base)); + array_write(f, pos, s->cirrus_bank_limit, sizeof(s->cirrus_bank_limit)); + array_write(f, pos, s->cirrus_hidden_palette, sizeof(s->cirrus_hidden_palette)); + array_write(f, pos, &s->hw_cursor_x, sizeof(s->hw_cursor_x)); + array_write(f, pos, &s->hw_cursor_y, sizeof(s->hw_cursor_y)); + array_write(f, pos, &s->cirrus_blt_pixelwidth, sizeof(s->cirrus_blt_pixelwidth)); + array_write(f, pos, &s->cirrus_blt_width, sizeof(s->cirrus_blt_width)); + array_write(f, pos, &s->cirrus_blt_height, sizeof(s->cirrus_blt_height)); + array_write(f, pos, &s->cirrus_blt_dstpitch, sizeof(s->cirrus_blt_dstpitch)); + array_write(f, pos, &s->cirrus_blt_srcpitch, sizeof(s->cirrus_blt_srcpitch)); + array_write(f, pos, &s->cirrus_blt_fgcol, sizeof(s->cirrus_blt_fgcol)); + array_write(f, pos, &s->cirrus_blt_bgcol, sizeof(s->cirrus_blt_bgcol)); + array_write(f, pos, &s->cirrus_blt_dstaddr, sizeof(s->cirrus_blt_dstaddr)); + array_write(f, pos, &s->cirrus_blt_srcaddr, sizeof(s->cirrus_blt_srcaddr)); + array_write(f, pos, &s->cirrus_blt_mode, sizeof(s->cirrus_blt_mode)); + array_write(f, pos, &s->cirrus_blt_modeext, sizeof(s->cirrus_blt_modeext)); + array_write(f, pos, s->cirrus_bltbuf, sizeof(s->cirrus_bltbuf)); + intbuf = (UINT32)(s->cirrus_srcptr - s->cirrus_bltbuf); + array_write(f, pos, &intbuf, sizeof(intbuf)); + intbuf = (UINT32)(s->cirrus_srcptr_end - s->cirrus_bltbuf); + array_write(f, pos, &intbuf, sizeof(intbuf)); + array_write(f, pos, &s->cirrus_srccounter, sizeof(s->cirrus_srccounter)); + array_write(f, pos, &s->last_hw_cursor_size, sizeof(s->last_hw_cursor_size)); + array_write(f, pos, &s->last_hw_cursor_x, sizeof(s->last_hw_cursor_x)); + array_write(f, pos, &s->last_hw_cursor_y, sizeof(s->last_hw_cursor_y)); + array_write(f, pos, &s->last_hw_cursor_y_start, sizeof(s->last_hw_cursor_y_start)); + array_write(f, pos, &s->last_hw_cursor_y_end, sizeof(s->last_hw_cursor_y_end)); + array_write(f, pos, &s->real_vram_size, sizeof(s->real_vram_size)); + array_write(f, pos, &s->device_id, sizeof(s->device_id)); + array_write(f, pos, &s->bustype, sizeof(s->bustype)); + + array_write(f, pos, &np2clvga.VRAMWindowAddr3, sizeof(np2clvga.VRAMWindowAddr3)); + + array_write(f, pos, &s->videowindow_dblbuf_index, sizeof(s->videowindow_dblbuf_index)); + array_write(f, pos, &s->graphics_dblbuf_index, sizeof(s->graphics_dblbuf_index)); + + array_write(f, pos, &cirrusvga_wab_59e1, sizeof(cirrusvga_wab_59e1)) + array_write(f, pos, &cirrusvga_wab_51e1, sizeof(cirrusvga_wab_51e1)); + array_write(f, pos, &cirrusvga_wab_5be1, sizeof(cirrusvga_wab_5be1)); + array_write(f, pos, &cirrusvga_wab_40e1, sizeof(cirrusvga_wab_40e1)); + array_write(f, pos, &cirrusvga_wab_46e8, sizeof(cirrusvga_wab_46e8)); + + array_write(f, pos, &cirrusvga_melcowab_ofs, sizeof(cirrusvga_melcowab_ofs)); + + array_write(f, pos, &cirrusvga_wab_42e1, sizeof(cirrusvga_wab_42e1)); + + TRACEOUT(("CIRRUS VGA datalen=%d, (max %d bytes)", pos, sizeof(cirrusvga_statsavebuf))); +#if defined(_WIN32) + // テスト用 + if(pos > sizeof(cirrusvga_statsavebuf)){ + MessageBox(NULL, _T("State save: Buffer Full"), _T("Warning"), 0); + } +#endif +} + +void pc98_cirrus_vga_load() +{ + CirrusVGAState *s = cirrusvga; + UINT8 *f = cirrusvga_statsavebuf; + int pos = 0; + uint32_t_ state_ver = 0; + uint32_t_ intbuf; + //int width, height; + char en[3]; + +#if defined(SUPPORT_IA32_HAXM) + // HAXMはレジューム前にPCIメモリ割り当て解除 + i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); + i386hax_vm_removememoryarea(vramptr, np2clvga.pciLFB_Addr, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); + lastlinmmio = 0; +#endif + + array_read(f, pos, &state_ver, sizeof(state_ver)); // バージョン番号 + switch(state_ver){ + case 0: + s->latch = state_ver; // ver0.86 rev22以前はlatchは常にゼロ(のはず) + array_read(f, pos, &s->sr_index, sizeof(s->sr_index)); + array_read(f, pos, s->sr, 256); + array_read(f, pos, &s->gr_index, sizeof(s->gr_index)); + array_read(f, pos, &s->cirrus_shadow_gr0, sizeof(s->cirrus_shadow_gr0)); + array_read(f, pos, &s->cirrus_shadow_gr1, sizeof(s->cirrus_shadow_gr1)); + s->gr[0x00] = s->cirrus_shadow_gr0 & 0x0f; + s->gr[0x01] = s->cirrus_shadow_gr1 & 0x0f; + array_read(f, pos, s->gr + 2, 254); + array_read(f, pos, &s->ar_index, sizeof(s->ar_index)); + array_read(f, pos, s->ar, 21); + array_read(f, pos, &s->ar_flip_flop, sizeof(s->ar_flip_flop)); + array_read(f, pos, &s->cr_index, sizeof(s->cr_index)); + array_read(f, pos, s->cr, 256); + array_read(f, pos, &s->msr, sizeof(s->msr)); + array_read(f, pos, &s->fcr, sizeof(s->fcr)); + array_read(f, pos, &s->st00, sizeof(s->st00)); + array_read(f, pos, &s->st01, sizeof(s->st01)); + + array_read(f, pos, &s->dac_state, sizeof(s->dac_state)); + array_read(f, pos, &s->dac_sub_index, sizeof(s->dac_sub_index)); + array_read(f, pos, &s->dac_read_index, sizeof(s->dac_read_index)); + array_read(f, pos, &s->dac_write_index, sizeof(s->dac_write_index)); + array_read(f, pos, s->dac_cache, 3); + array_read(f, pos, s->palette, 768); + + array_read(f, pos, &s->bank_offset, sizeof(s->bank_offset)); + + array_read(f, pos, &s->cirrus_hidden_dac_lockindex, sizeof(s->cirrus_hidden_dac_lockindex)); + array_read(f, pos, &s->cirrus_hidden_dac_data, sizeof(s->cirrus_hidden_dac_data)); + + array_read(f, pos, &s->hw_cursor_x, sizeof(s->hw_cursor_x)); + array_read(f, pos, &s->hw_cursor_y, sizeof(s->hw_cursor_y)); + + array_read(f, pos, vramptr, CIRRUS_VRAM_SIZE); + + break; + case 3: + case 4: + case 5: + case 6: + array_read(f, pos, en, 2); + if(en[0] != 'e' || en[0] != 'n') + break; + + case 1: + case 2: + // この際全部保存 + array_read(f, pos, vramptr, CIRRUS_VRAM_SIZE); + array_read(f, pos, &s->vram_offset, sizeof(s->vram_offset)); + array_read(f, pos, &s->vram_size, sizeof(s->vram_size)); + array_read(f, pos, &s->lfb_addr, sizeof(s->lfb_addr)); + array_read(f, pos, &s->lfb_end, sizeof(s->lfb_end)); + array_read(f, pos, &s->map_addr, sizeof(s->map_addr)); + array_read(f, pos, &s->map_end, sizeof(s->map_end)); + array_read(f, pos, &s->lfb_vram_mapped, sizeof(s->lfb_vram_mapped)); + array_read(f, pos, &s->bios_offset, sizeof(s->bios_offset)); + array_read(f, pos, &s->bios_size, sizeof(s->bios_size)); + array_read(f, pos, &s->it_shift, sizeof(s->it_shift)); + + array_read(f, pos, &s->latch, sizeof(s->latch)); + array_read(f, pos, &s->sr_index, sizeof(s->sr_index)); + array_read(f, pos, s->sr, sizeof(s->sr)); + array_read(f, pos, &s->gr_index, sizeof(s->gr_index)); + array_read(f, pos, s->gr, sizeof(s->gr)); + array_read(f, pos, &s->ar_index, sizeof(s->ar_index)); + array_read(f, pos, s->ar, sizeof(s->ar)); + array_read(f, pos, &s->ar_flip_flop, sizeof(s->ar_flip_flop)); + array_read(f, pos, &s->cr_index, sizeof(s->cr_index)); + array_read(f, pos, s->cr, sizeof(s->cr)); + array_read(f, pos, &s->msr, sizeof(s->msr)); + array_read(f, pos, &s->fcr, sizeof(s->fcr)); + array_read(f, pos, &s->st00, sizeof(s->st00)); + array_read(f, pos, &s->st01, sizeof(s->st01)); + array_read(f, pos, &s->dac_state, sizeof(s->dac_state)); + array_read(f, pos, &s->dac_sub_index, sizeof(s->dac_sub_index)); + array_read(f, pos, &s->dac_read_index, sizeof(s->dac_read_index)); + array_read(f, pos, &s->dac_write_index, sizeof(s->dac_write_index)); + array_read(f, pos, s->dac_cache, sizeof(s->dac_cache)); + array_read(f, pos, &s->dac_8bit, sizeof(s->dac_8bit)); + array_read(f, pos, s->palette, sizeof(s->palette)); + array_read(f, pos, &s->bank_offset, sizeof(s->bank_offset)); + array_read(f, pos, &s->vga_io_memory, sizeof(s->vga_io_memory)); + array_read(f, pos, &s->vbe_index, sizeof(s->vbe_index)); + array_read(f, pos, s->vbe_regs, sizeof(s->vbe_regs)); + array_read(f, pos, &s->vbe_start_addr, sizeof(s->vbe_start_addr)); + array_read(f, pos, &s->vbe_line_offset, sizeof(s->vbe_line_offset)); + array_read(f, pos, &s->vbe_bank_mask, sizeof(s->vbe_bank_mask)); + + array_read(f, pos, s->font_offsets, sizeof(s->font_offsets)); + array_read(f, pos, &s->graphic_mode, sizeof(s->graphic_mode)); + array_read(f, pos, &s->shift_control, sizeof(s->shift_control)); + array_read(f, pos, &s->double_scan, sizeof(s->double_scan)); + array_read(f, pos, &s->line_offset, sizeof(s->line_offset)); + array_read(f, pos, &s->line_compare, sizeof(s->line_compare)); + array_read(f, pos, &s->start_addr, sizeof(s->start_addr)); + array_read(f, pos, &s->plane_updated, sizeof(s->plane_updated)); + array_read(f, pos, &s->last_line_offset, sizeof(s->last_line_offset)); + array_read(f, pos, &s->last_cw, sizeof(s->last_cw)); + array_read(f, pos, &s->last_ch, sizeof(s->last_ch)); + array_read(f, pos, &s->last_width, sizeof(s->last_width)); + array_read(f, pos, &s->last_height, sizeof(s->last_height)); + array_read(f, pos, &s->last_scr_width, sizeof(s->last_scr_width)); + array_read(f, pos, &s->last_scr_height, sizeof(s->last_scr_height)); + array_read(f, pos, &s->last_depth, sizeof(s->last_depth)); + array_read(f, pos, &s->cursor_start, sizeof(s->cursor_start)); + array_read(f, pos, &s->cursor_end, sizeof(s->cursor_end)); + array_read(f, pos, &s->cursor_offset, sizeof(s->cursor_offset)); + + array_read(f, pos, s->invalidated_y_table, sizeof(s->invalidated_y_table)); + array_read(f, pos, s->last_palette, sizeof(s->last_palette)); + array_read(f, pos, s->last_ch_attr, sizeof(s->last_ch_attr)); + + array_read(f, pos, &s->cirrus_linear_io_addr, sizeof(s->cirrus_linear_io_addr)); + array_read(f, pos, &s->cirrus_linear_bitblt_io_addr, sizeof(s->cirrus_linear_bitblt_io_addr)); + array_read(f, pos, &s->cirrus_mmio_io_addr, sizeof(s->cirrus_mmio_io_addr)); + array_read(f, pos, &s->cirrus_addr_mask, sizeof(s->cirrus_addr_mask)); + array_read(f, pos, &s->linear_mmio_mask, sizeof(s->linear_mmio_mask)); + array_read(f, pos, &s->cirrus_shadow_gr0, sizeof(s->cirrus_shadow_gr0)); + array_read(f, pos, &s->cirrus_shadow_gr1, sizeof(s->cirrus_shadow_gr1)); + array_read(f, pos, &s->cirrus_hidden_dac_lockindex, sizeof(s->cirrus_hidden_dac_lockindex)); + array_read(f, pos, &s->cirrus_hidden_dac_data, sizeof(s->cirrus_hidden_dac_data)); + array_read(f, pos, s->cirrus_bank_base, sizeof(s->cirrus_bank_base)); + array_read(f, pos, s->cirrus_bank_limit, sizeof(s->cirrus_bank_limit)); + array_read(f, pos, s->cirrus_hidden_palette, sizeof(s->cirrus_hidden_palette)); + array_read(f, pos, &s->hw_cursor_x, sizeof(s->hw_cursor_x)); + array_read(f, pos, &s->hw_cursor_y, sizeof(s->hw_cursor_y)); + array_read(f, pos, &s->cirrus_blt_pixelwidth, sizeof(s->cirrus_blt_pixelwidth)); + array_read(f, pos, &s->cirrus_blt_width, sizeof(s->cirrus_blt_width)); + array_read(f, pos, &s->cirrus_blt_height, sizeof(s->cirrus_blt_height)); + array_read(f, pos, &s->cirrus_blt_dstpitch, sizeof(s->cirrus_blt_dstpitch)); + array_read(f, pos, &s->cirrus_blt_srcpitch, sizeof(s->cirrus_blt_srcpitch)); + array_read(f, pos, &s->cirrus_blt_fgcol, sizeof(s->cirrus_blt_fgcol)); + array_read(f, pos, &s->cirrus_blt_bgcol, sizeof(s->cirrus_blt_bgcol)); + array_read(f, pos, &s->cirrus_blt_dstaddr, sizeof(s->cirrus_blt_dstaddr)); + array_read(f, pos, &s->cirrus_blt_srcaddr, sizeof(s->cirrus_blt_srcaddr)); + array_read(f, pos, &s->cirrus_blt_mode, sizeof(s->cirrus_blt_mode)); + array_read(f, pos, &s->cirrus_blt_modeext, sizeof(s->cirrus_blt_modeext)); + array_read(f, pos, s->cirrus_bltbuf, sizeof(s->cirrus_bltbuf)); + array_read(f, pos, &intbuf, sizeof(intbuf)); + s->cirrus_srcptr = s->cirrus_bltbuf + intbuf; + array_read(f, pos, &intbuf, sizeof(intbuf)); + s->cirrus_srcptr_end = s->cirrus_bltbuf + intbuf; + array_read(f, pos, &s->cirrus_srccounter, sizeof(s->cirrus_srccounter)); + array_read(f, pos, &s->last_hw_cursor_size, sizeof(s->last_hw_cursor_size)); + array_read(f, pos, &s->last_hw_cursor_x, sizeof(s->last_hw_cursor_x)); + array_read(f, pos, &s->last_hw_cursor_y, sizeof(s->last_hw_cursor_y)); + array_read(f, pos, &s->last_hw_cursor_y_start, sizeof(s->last_hw_cursor_y_start)); + array_read(f, pos, &s->last_hw_cursor_y_end, sizeof(s->last_hw_cursor_y_end)); + array_read(f, pos, &s->real_vram_size, sizeof(s->real_vram_size)); + array_read(f, pos, &s->device_id, sizeof(s->device_id)); + array_read(f, pos, &s->bustype, sizeof(s->bustype)); + + if(state_ver >= 2){ + array_read(f, pos, &np2clvga.VRAMWindowAddr3, sizeof(np2clvga.VRAMWindowAddr3)); + } + if(state_ver >= 4){ + array_read(f, pos, &s->videowindow_dblbuf_index, sizeof(s->videowindow_dblbuf_index)); + array_read(f, pos, &s->graphics_dblbuf_index, sizeof(s->graphics_dblbuf_index)); + } + if(state_ver >= 5){ + array_read(f, pos, &cirrusvga_wab_59e1, sizeof(cirrusvga_wab_59e1)); + array_read(f, pos, &cirrusvga_wab_51e1, sizeof(cirrusvga_wab_51e1)); + array_read(f, pos, &cirrusvga_wab_5be1, sizeof(cirrusvga_wab_5be1)); + array_read(f, pos, &cirrusvga_wab_40e1, sizeof(cirrusvga_wab_40e1)); + array_read(f, pos, &cirrusvga_wab_46e8, sizeof(cirrusvga_wab_46e8)); + array_read(f, pos, &cirrusvga_melcowab_ofs, sizeof(cirrusvga_melcowab_ofs)); + } + if(state_ver >= 6){ + array_read(f, pos, &cirrusvga_wab_42e1, sizeof(cirrusvga_wab_42e1)); + } + // + + break; + default: + break; + } + + s->cirrus_rop = cirrus_bitblt_rop_nop; // XXX: 本当はステートセーブで保存しないと駄目 + +#ifdef SUPPORT_PCI + // 関数アドレス入れ直し + pcidev.devices[pcidev_cirrus_deviceid].regwfn = &pcidev_cirrus_cfgreg_w; +#endif + + pc98_cirrus_vga_updatePCIaddr(); + +#if defined(SUPPORT_IA32_HAXM) + mmio_mode = MMIO_MODE_MMIO; // 0==MMIO, 1==VRAM + mmio_mode_region1 = 0; // 0==MMIO, 1==VRAM + mmio_mode_region2 = 0; // 0==MMIO, 1==VRAM + lastlinmmio = 0; + //i386hax_vm_removememoryarea(vramptr, np2clvga.pciLFB_Addr, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); +#endif + + cirrus_update_memory_access(s); + + s->graphic_mode = -1; + cirrus_update_bank_ptr(s, 0); + cirrus_update_bank_ptr(s, 1); + + // WAB画面サイズ強制更新 + np2wab.realWidth = 0; + np2wab.realHeight = 0; + + np2wab.paletteChanged = 1; // パレット変えました + cirrusvga_updated = 1; +} + +/*************************************** + * + * initialize + * + ***************************************/ +void cirrus_reset(void *opaque) +{ + CirrusVGAState *s = (CirrusVGAState*)opaque; + + memset(s->sr, 0, sizeof(s->sr)); + memset(s->cr, 0, sizeof(s->cr)); + memset(s->gr, 0, sizeof(s->gr)); + + vga_reset(s); + unmap_linear_vram(s); + s->sr[0x06] = 0x0f; + if (s->device_id == CIRRUS_ID_CLGD5446) { + /* 4MB 64 bit memory config, always PCI */ + s->sr[0x1F] = 0x2d; // MemClock + s->gr[0x18] = 0x0f; // fastest memory configuration + s->sr[0x0f] = CIRRUS_MEMSIZE_2M; //0x98; + s->sr[0x17] = 0x20; + s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ + } else { + s->sr[0x1F] = 0x22; // MemClock + s->sr[0x0F] = CIRRUS_MEMSIZE_2M; + s->sr[0x17] = s->bustype; + s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ + } + s->cr[0x27] = s->device_id; + if (np2clvga.gd54xxtype == CIRRUS_98ID_WAB) { + s->sr[0x0F] = CIRRUS_MEMSIZE_1M; + s->sr[0x15] = 0x02; + } + pc98_cirrus_setWABreg(); + +#if defined(NP2_WIN) + BitBlt(np2wabwnd.hDCBuf, 0, 0, WAB_MAX_WIDTH, WAB_MAX_HEIGHT, NULL, 0, 0, BLACKNESS); +#endif + if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F) { + memset(s->vram_ptr, 0x00, s->real_vram_size); + }else{ + /* Win2K seems to assume that the pattern buffer is at 0xff + initially ! */ + memset(s->vram_ptr, 0xff, s->real_vram_size); + } + memset(s->palette, 0, sizeof(s->palette)); + memset(s->cirrus_hidden_palette, 0, sizeof(s->cirrus_hidden_palette)); + + s->cirrus_hidden_dac_lockindex = 5; + //s->cirrus_hidden_dac_data = 0; + + // XXX: for WinNT4.0 + s->cirrus_hidden_dac_data = 1; + + // XXX: Win2000のハードウェアアクセラレーションを動かすのに必要。理由は謎 + s->gr[0x25] = 0x06; + s->gr[0x26] = 0x20; + + // XXX: Win2000で動かすのに必要。理由は謎 +#if defined(SUPPORT_PCI) + if(pcidev.enable && (np2clvga.gd54xxtype == CIRRUS_98ID_PCI || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI)){ + s->msr = 0x03; + s->sr[0x08] = 0xFE; + s->gr[0x0e] &= ~0x20; // XXX: for WinNT4.0 + s->gr[0x33] = 0x04; // XXX: for WinNT4.0 + s->cr[0x5e] &= ~0x20;//s->cr[0x5e] |= 0x20; // XXX: Part IDを読むまでGR33を書き込み禁止にする(WinNT4専用の不具合回避) + } +#endif + //fh = fopen("vgadump.bin", "w+"); + //if (fh != FILEH_INVALID) { + // fwrite(s, sizeof(CirrusVGAState), 1, fh); + // fclose(fh); + //} + cirrusvga_updated = 1; +} + +#if defined(NP2_WIN) +LOGPALETTE * NewLogPal(const uint8_t *pCirrusPalette , int iSize) { + LOGPALETTE *lpPalette; + int count; + + lpPalette = (LOGPALETTE*)malloc(sizeof (LOGPALETTE) + iSize * sizeof (PALETTEENTRY)); + lpPalette->palVersion = 0x0300; + lpPalette->palNumEntries = iSize; + + for (count = 0 ; count < iSize ; count++) { + lpPalette->palPalEntry[count].peRed = c6_to_8(pCirrusPalette[count*3]); + lpPalette->palPalEntry[count].peGreen = c6_to_8(pCirrusPalette[count*3+1]); + lpPalette->palPalEntry[count].peBlue = c6_to_8(pCirrusPalette[count*3+2]); + lpPalette->palPalEntry[count].peFlags = 0; + } + return lpPalette; +} +#endif + +void ConvertYUV2RGB(int width, unsigned char *srcYUV16, unsigned char *dstRGB32Line){ + int j; + int offset = 128; + if(cirrusvga->cr[0x3f] & 0x10){ + //if(cirrusvga->cr[0x3f] & 0x08){ + // // RGB555 + // //memcpy(dstRGB32Line, srcYUV16, width); + //}else{ + // YCC422 + for(j=0;j> 8; + int g0 = (298 * (y0 - 16) - 100 * (u0 - offset) - 208 * (v0 - offset) + 128) >> 8; + int b0 = (298 * (y0 - 16) + 516 * (u0 - offset) + 128) >> 8; + int r1 = (298 * (y1 - 16) + 409 * (v0 - offset) + 128) >> 8; + int g1 = (298 * (y1 - 16) - 100 * (u0 - offset) - 208 * (v0 - offset) + 128) >> 8; + int b1 = (298 * (y1 - 16) + 516 * (u0 - offset) + 128) >> 8; + dstRGB32Line[j*8 + 0] = (b0 < 0 ? 0 : (b0 > 255 ? 255 : b0)); + dstRGB32Line[j*8 + 1] = (g0 < 0 ? 0 : (g0 > 255 ? 255 : g0)); + dstRGB32Line[j*8 + 2] = (r0 < 0 ? 0 : (r0 > 255 ? 255 : r0)); + dstRGB32Line[j*8 + 4] = (b1 < 0 ? 0 : (b1 > 255 ? 255 : b1)); + dstRGB32Line[j*8 + 5] = (g1 < 0 ? 0 : (g1 > 255 ? 255 : g1)); + dstRGB32Line[j*8 + 6] = (r1 < 0 ? 0 : (r1 > 255 ? 255 : r1)); + } + //} + }else{ + for(j=0;j> 8; + int g0 = (298 * (y0 - 16) - 100 * (u0 - offset) - 208 * (v0 - offset) + 128) >> 8; + int b0 = (298 * (y0 - 16) + 516 * (u0 - offset) + 128) >> 8; + int r1 = (298 * (y1 - 16) + 409 * (v0 - offset) + 128) >> 8; + int g1 = (298 * (y1 - 16) - 100 * (u0 - offset) - 208 * (v0 - offset) + 128) >> 8; + int b1 = (298 * (y1 - 16) + 516 * (u0 - offset) + 128) >> 8; + dstRGB32Line[j*8 + 0] = (b0 < 0 ? 0 : (b0 > 255 ? 255 : b0)); + dstRGB32Line[j*8 + 1] = (g0 < 0 ? 0 : (g0 > 255 ? 255 : g0)); + dstRGB32Line[j*8 + 2] = (r0 < 0 ? 0 : (r0 > 255 ? 255 : r0)); + dstRGB32Line[j*8 + 4] = (b1 < 0 ? 0 : (b1 > 255 ? 255 : b1)); + dstRGB32Line[j*8 + 5] = (g1 < 0 ? 0 : (g1 > 255 ? 255 : g1)); + dstRGB32Line[j*8 + 6] = (r1 < 0 ? 0 : (r1 > 255 ? 255 : r1)); + } + } +} + +// 画面表示(仮) 本当はQEMUのオリジナルのコードを移植すべきなんだけど・・・ +// Cirrus VRAM (screen & cursor) -> GDI Device Independent Bitmap +int cirrusvga_drawGraphic(){ +//#define DEBUG_CIRRUS_VRAM +#if defined(DEBUG_CIRRUS_VRAM) + //static UINT32 kdown = 0; + //static UINT32 kdownc = 0; + static INT32 memshift = 0; // DEBUG + static INT32 sysmemmode = 0; // DEBUG + static INT32 tabon = 0; // DEBUG +#endif + int i, j, width, height, bpp; + uint32_t_ line_offset = 0; +#if defined(NP2_WIN) + LOGPALETTE * lpPalette; + static HPALETTE hPalette = NULL, oldPalette = NULL; + HDC hdc = np2wabwnd.hDCBuf; +#endif + static int waitscreenchange = 0; + int r; + int scanW = 0; // VRAM上の1ラインのデータ幅(byte) + int scanpixW = 0; // 実際に転送すべき1ラインのピクセル数(pixel) + int scanshift = 0; + uint8_t *scanptr; + uint8_t *vram_ptr; + +#if defined(NP2_X) + GdkPixbuf *VRAMBuf = NULL; + char* p; +#elif defined(USE_SDL) || defined(__LIBRETRO__) + unsigned int *VRAMBuf = NULL; + char* p; +#endif + + int cursot_ofs_x = 0; + int cursot_ofs_y = 0; + + int realWidth = 0; + int realHeight = 0; + + if (!cirrusvga_updated && !np2wab.paletteChanged) return 0; + cirrusvga_updated = 0; + + static int lastvramoffs = -1; + +#if defined(SUPPORT_IA32_HAXM) + // XXX: HAXMの仮想CPUがvramptrを書き換えることがあり、これの捕捉はできない。なのでメモリ比較で強引に検出 4MBくらいなら今時のPCならいいでしょう + if (memcmp(vramptr_cmp, vramptr, CIRRUS_VRAM_SIZE)) + { + memcpy(vramptr_cmp, vramptr, CIRRUS_VRAM_SIZE); + cirrusvga_updated = 1; + } +#endif + +// 20260127 Win2k起動不良のためコメントアウト +// if (!cirrusvga_updated && !np2wab.paletteChanged && lastvramoffs == np2wab.vramoffs) return 0; + // VRAM上での1ラインのサイズ(表示幅と等しくない場合有り) + line_offset = cirrusvga->cr[0x13] | ((cirrusvga->cr[0x1b] & 0x10) << 4); + line_offset <<= 3; + + vram_ptr = cirrusvga->vram_ptr + np2wab.vramoffs; + lastvramoffs = np2wab.vramoffs; + + //if(cirrusvga->device_id == CIRRUS_ID_CLGD5446 || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || (np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB){ + //if((cirrusvga->cr[0x5e] & 0x7) == 0x1){ + // cirrusvga->graphics_dblbuf_index = (cirrusvga->graphics_dblbuf_index + 1) & 0x1; + //} + //if(cirrusvga->graphics_dblbuf_index != 0 || (cirrusvga->cr[0x1a] & 0x2) || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || (np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB) + { + // Screen Start A + int addroffset = + (((int)(cirrusvga->cr[0x1d] >> 7) & 0x01) << 19)| + (((int)(cirrusvga->cr[0x1b] >> 2) & 0x03) << 17)| + (((int)(cirrusvga->cr[0x1b] >> 0) & 0x01) << 16)| + (((int)(cirrusvga->cr[0x0c] >> 0) & 0xff) << 8)| + (((int)(cirrusvga->cr[0x0d] >> 0) & 0xff) << 0); + vram_ptr += addroffset * 4; // ??? + } + //} + +#if defined(DEBUG_CIRRUS_VRAM) + // DEBUG + ////// vram_ptr = mem + 640*16*memshift; + //vram_ptr += 640*16*memshift; + if(GetKeyState(VK_SHIFT)<0){ + memshift++; + // kdown = 1; + //}else if(kdown){ + // //vram_ptr = vram_ptr + 1024*768*1; + // kdown = 0; + } + if(GetKeyState(VK_CONTROL)<0){ + memshift--; + if(memshift<0) memshift = 0; + //vram_ptr = mem + 1024*768*memshift; + // kdownc = 1; + //}else if(kdownc){ + // //vram_ptr = vram_ptr + 1024*768*1; + // kdownc = 0; + } + if(GetKeyState(VK_TAB)<0){ + if(!tabon){ + sysmemmode = (sysmemmode + 1) % 3; + tabon = 1; + } + }else{ + tabon = 0; + } + //if(GetKeyState(VK_CONTROL)<0){ + switch(sysmemmode){ + case 0: + vram_ptr = vram_ptr + 256*16*memshift; + break; + case 1: + vram_ptr = mem + 256*16*memshift; + break; + case 2: + vram_ptr = CPU_EXTMEMBASE + 256*16*memshift; + break; + } + //} + // DEBUG (END) +#endif + + // Cirrusの色数と解像度を取得 + bpp = cirrusvga->get_bpp((VGAState*)cirrusvga); + cirrusvga->get_resolution((VGAState*)cirrusvga, &width, &height); + //bpp = 16; + //width = 1024; + //height = 768; + +#if defined(SUPPORT_VGA_MODEX) + // PC/AT MODE X compatible + if (np2clvga.gd54xxtype <= 0xff){ + static UINT8 lastmodex = 0; + if(np2clvga.modex){ + if(!lastmodex){ + cirrusvga->sr[0x07] &= ~0x01; + } + bpp = 8; + width = 320; + height = 240; + line_offset = 320; + }else{ + if(!lastmodex){ + cirrusvga->sr[0x07] |= 0x01; + } + } + lastmodex = np2clvga.modex; + } +#endif + + if(bpp==0) return 0; + + // Palette mode > 85MHz (1280x1024) + if((cirrusvga->cirrus_hidden_dac_data & 0xCF) == 0x4A){ + bpp = 8; + width *= 2; + height *= 2; + } + + // GA-98NB用 1280x1024 + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + // XXX: Win3.1用 やっつけ修正 + if(width==640 && height==512 && bpp==15/* && + cirrusvga->cr[0x00]==0x63 && cirrusvga->cr[0x04]==0x53 && cirrusvga->cr[0x05]==0x1e && + cirrusvga->cr[0x06]==0x15 && cirrusvga->cr[0x10]==0x04 && cirrusvga->cr[0x11]==0x88*/){ + bpp = 8; + width *= 2; + height *= 2; + } + } + + // WAB解像度設定 + realWidth = width; + realHeight = height; + + // CRTC offset 設定 + scanW = width*(bpp/8); + scanpixW = width; + if(bpp && line_offset){ + // 32bit color用やっつけ修正 for GA-98NB & WSN-A2F/A4F + if(bpp==32){ + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || (np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB){ + line_offset <<= 1; + } + } + scanW = line_offset; + } + + // 色数判定 +#if defined(NP2_WIN) + if(bpp==16){ + // ビットフィールドでRGB565を指定 + uint32_t_* bitfleld = (uint32_t_*)(ga_bmpInfo->bmiColors); + bitfleld[0] = 0x0000F800; + bitfleld[1] = 0x000007E0; + bitfleld[2] = 0x0000001F; + ga_bmpInfo->bmiHeader.biCompression = BI_BITFIELDS; + }else{ + ga_bmpInfo->bmiHeader.biCompression = BI_RGB; + } + // Windowsの16bitカラーは標準でRGB555なのでそのままbpp=16に変更 + if(bpp==15){ + bpp = 16; + } +#endif + + // GA-98NB用 + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + if(np2cfg.ga98nb_bigscrn_ex && (bpp==8 || bpp==16) && (width==1024 || width==1280) && scanW*8/bpp==1600){ + // 1600x1024 Big Screen Extension + int addroffset = + (((int)(cirrusvga->cr[0x1d] >> 7) & 0x01) << 19)| + (((int)(cirrusvga->cr[0x1b] >> 2) & 0x03) << 17)| + (((int)(cirrusvga->cr[0x1b] >> 0) & 0x01) << 16)| + (((int)(cirrusvga->cr[0x0c] >> 0) & 0xff) << 8)| + (((int)(cirrusvga->cr[0x0d] >> 0) & 0xff) << 0); + addroffset *= 4; + realWidth = 1600; + realHeight = 1024; + width = 1600; + height = 1024; + scanpixW = 1600; + vram_ptr = cirrusvga->vram_ptr + np2wab.vramoffs; + cursot_ofs_x = (addroffset*8/bpp) % 1600; + cursot_ofs_y = (addroffset*8/bpp) / 1600; + } + } + + // WAB解像度更新 + np2wab.realWidth = realWidth; + np2wab.realHeight = realHeight; + +#if defined(NP2_WIN) + if(ga_bmpInfo->bmiHeader.biBitCount!=8 && bpp==8){ + np2wab.paletteChanged = 1; + } + + ga_bmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + ga_bmpInfo->bmiHeader.biWidth = width; // 仮セット + ga_bmpInfo->bmiHeader.biHeight = 1; // 仮セット + ga_bmpInfo->bmiHeader.biPlanes = 1; + ga_bmpInfo->bmiHeader.biBitCount = bpp; +#endif + if(bpp<=8){ + if(np2wab.paletteChanged){ +#if defined(NP2_WIN) + WORD* PalIndexes = (WORD*)((char*)ga_bmpInfo + sizeof(BITMAPINFOHEADER)); + for (i = 0; i < 256; ++i) PalIndexes[i] = i; + lpPalette = NewLogPal(cirrusvga->palette , 1<bmiHeader.biWidth = scanpixW; + ga_bmpInfo->bmiHeader.biHeight = -height; + scanptr = vram_ptr; + SetDIBitsToDevice( + hdc , 0 , 0 , + ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , + 0 , 0 , 0 , -ga_bmpInfo->bmiHeader.biHeight , + vram_ptr+scanshift*bpp/8 , ga_bmpInfo , DIB_PAL_COLORS + ); + //int scanshiftY = scanshift/scanpixW; + //ga_bmpInfo->bmiHeader.biWidth = scanpixW; + //ga_bmpInfo->bmiHeader.biHeight = -height; + //SetDIBitsToDevice( + // hdc , 0 , 0 , + // ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , + // 0 , 0 , scanshiftY , -ga_bmpInfo->bmiHeader.biHeight , + // vram_ptr , ga_bmpInfo , DIB_PAL_COLORS + //); + //SetDIBitsToDevice( + // hdc , 0 , 0 , + // ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , + // 0 , 0 , 0 , scanshiftY , + // vram_ptr , ga_bmpInfo , DIB_PAL_COLORS + //); +#elif defined(NP2_X) + scanptr = vram_ptr; + if(np2wabwnd.pPixbuf) { + VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); + p = gdk_pixbuf_get_pixels(VRAMBuf); + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 3 ] = cirrusvga->palette[vram_ptr[j * width + i] * 3 ] << 2; + p[(j * width + i) * 3 + 1] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 1] << 2; + p[(j * width + i) * 3 + 2] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 2] << 2; + } + } + } +#else + scanptr = vram_ptr; + VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); + p = (unsigned char*)VRAMBuf; + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 + 2] = cirrusvga->palette[vram_ptr[j * width + i] * 3 ] << 2; + p[(j * width + i) * 4 + 1] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 1] << 2; + p[(j * width + i) * 4 ] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 2] << 2; + } + } +#endif + }else{ +#if defined(NP2_WIN) + ga_bmpInfo->bmiHeader.biWidth = scanpixW; + ga_bmpInfo->bmiHeader.biHeight = -height; + scanptr = vram_ptr; + SetDIBitsToDevice( + hdc , 0 , 0 , + ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , + 0 , 0 , 0 , -ga_bmpInfo->bmiHeader.biHeight , + vram_ptr , ga_bmpInfo , DIB_PAL_COLORS + ); +#elif defined(NP2_X) + scanptr = vram_ptr; + if(np2wabwnd.pPixbuf) { + VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); + p = gdk_pixbuf_get_pixels(VRAMBuf); + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 3 ] = cirrusvga->palette[vram_ptr[j * width + i] * 3 ] << 2; + p[(j * width + i) * 3 + 1] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 1] << 2; + p[(j * width + i) * 3 + 2] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 2] << 2; + } + } + } +#else + scanptr = vram_ptr; + VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); + p = (unsigned char*)VRAMBuf; + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 + 2] = cirrusvga->palette[vram_ptr[j * width + i] * 3 ] << 2; + p[(j * width + i) * 4 + 1] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 1] << 2; + p[(j * width + i) * 4 ] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 2] << 2; + } + } +#endif + } + }else{ + // ズレがあるなら1ラインずつ転送 +#if defined(NP2_WIN) + scanptr = vram_ptr; + for(i=0;ibmiHeader.biWidth = width; + ga_bmpInfo->bmiHeader.biHeight = 1; + r = SetDIBitsToDevice( + hdc , 0 , i , + width , 1 , + 0 , 0 , 0 , 1 , + scanptr , ga_bmpInfo , DIB_PAL_COLORS + ); + scanptr += scanW; + } +#elif defined(NP2_X) + scanptr = vram_ptr; + if(np2wabwnd.pPixbuf) { + GdkPixbuf *VRAMBuf; + VRAMBuf = gdk_pixbuf_new_from_data(vram_ptr, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width*bpp/8, NULL,NULL); + } +#else + scanptr = vram_ptr; + VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); + p = (unsigned char*)VRAMBuf; + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 + 2] = cirrusvga->palette[vram_ptr[j * width + i] * 3 ] << 2; + p[(j * width + i) * 4 + 1] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 1] << 2; + p[(j * width + i) * 4 ] = cirrusvga->palette[vram_ptr[j * width + i] * 3 + 2] << 2; + } + } +#endif + } + }else{ + np2wab.paletteChanged = 0; // パレットではないので更新不要 + if(scanpixW*bpp/8==scanW){ + if(scanshift){ + // XXX: スキャン位置シフト +#if defined(NP2_WIN) + ga_bmpInfo->bmiHeader.biWidth = scanpixW; + ga_bmpInfo->bmiHeader.biHeight = -height; + scanptr = vram_ptr; + SetDIBitsToDevice( + hdc , 0 , 0 , + ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , + 0 , 0 , 0 , -ga_bmpInfo->bmiHeader.biHeight , + vram_ptr+scanshift*bpp/8 , ga_bmpInfo , DIB_RGB_COLORS + ); +#elif defined(NP2_X) + scanptr = vram_ptr; + if(np2wabwnd.pPixbuf) { + VRAMBuf = gdk_pixbuf_new_from_data(vram_ptr, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width*bpp/8, NULL,NULL); + p = gdk_pixbuf_get_pixels(VRAMBuf); + } +#else + scanptr = vram_ptr; + VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); + p = (unsigned char*)VRAMBuf; + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 ] = vram_ptr[(j * width + i) * 3 ]; + p[(j * width + i) * 4 + 1] = vram_ptr[(j * width + i) * 3 + 1]; + p[(j * width + i) * 4 + 2] = vram_ptr[(j * width + i) * 3 + 2]; + } + } +#endif + }else{ +#if defined(NP2_WIN) + ga_bmpInfo->bmiHeader.biWidth = scanpixW; + ga_bmpInfo->bmiHeader.biHeight = -height; + scanptr = vram_ptr; + SetDIBitsToDevice( + hdc , 0 , 0 , + ga_bmpInfo->bmiHeader.biWidth , -ga_bmpInfo->bmiHeader.biHeight , + 0 , 0 , 0 , -ga_bmpInfo->bmiHeader.biHeight , + vram_ptr , ga_bmpInfo , DIB_RGB_COLORS + ); +#elif defined(NP2_X) + scanptr = vram_ptr; + if(np2wabwnd.pPixbuf) { + if(bpp == 24) { + VRAMBuf = gdk_pixbuf_new_from_data(vram_ptr, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width*bpp/8, NULL,NULL); + } else if(bpp == 16) { + VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); + p = gdk_pixbuf_get_pixels(VRAMBuf); + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 3 ] = (((((UINT16*)vram_ptr)[j * width + i]) & 0xF800) >> 8) & 0xFF; + p[(j * width + i) * 3 + 1] = (((((UINT16*)vram_ptr)[j * width + i]) & 0x07C0) >> 3) & 0xFF; + p[(j * width + i) * 3 + 2] = (((((UINT16*)vram_ptr)[j * width + i]) & 0x001F) << 3) & 0xFF; + } + } + } else if(bpp == 32) { + VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); + p = gdk_pixbuf_get_pixels(VRAMBuf); + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 3 ] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x00FF0000) >> 16) & 0xFF; + p[(j * width + i) * 3 + 1] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x0000FF00) >> 8) & 0xFF; + p[(j * width + i) * 3 + 2] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x000000FF) ) & 0xFF; + } + } + } + } +#else + scanptr = vram_ptr; + VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); + p = (unsigned char*)VRAMBuf; + if(bpp == 24) { + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 ] = vram_ptr[(j * width + i) * 3 ]; + p[(j * width + i) * 4 + 1] = vram_ptr[(j * width + i) * 3 + 1]; + p[(j * width + i) * 4 + 2] = vram_ptr[(j * width + i) * 3 + 2]; + } + } + } else if(bpp == 16) { + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 + 2] = (((((UINT16*)vram_ptr)[j * width + i]) & 0xF800) >> 8) & 0xFF; + p[(j * width + i) * 4 + 1] = (((((UINT16*)vram_ptr)[j * width + i]) & 0x07C0) >> 3) & 0xFF; + p[(j * width + i) * 4 ] = (((((UINT16*)vram_ptr)[j * width + i]) & 0x001F) << 3) & 0xFF; + } + } + } else if(bpp == 32) { + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 + 2] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x00FF0000) >> 16) & 0xFF; + p[(j * width + i) * 4 + 1] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x0000FF00) >> 8) & 0xFF; + p[(j * width + i) * 4 ] = (((((UINT32*)vram_ptr)[j * width + i]) & 0x000000FF) ) & 0xFF; + } + } + } +#endif + } + }else{ + // ズレがあるなら1ラインずつ転送 +#if defined(NP2_WIN) + scanptr = vram_ptr; + for(i=0;ibmiHeader.biWidth = width; + ga_bmpInfo->bmiHeader.biHeight = 1; + r = SetDIBitsToDevice( + hdc , 0 , i , + width , 1 , + 0 , 0 , 0 , 1 , + scanptr , ga_bmpInfo , DIB_RGB_COLORS + ); + scanptr += scanW; + } +#elif defined(NP2_X) + scanptr = vram_ptr; + if(np2wabwnd.pPixbuf) { + if(bpp == 15) { + VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); + p = gdk_pixbuf_get_pixels(VRAMBuf); + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 3 ] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x7C00) >> 7) & 0xFF; + p[(j * width + i) * 3 + 1] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x03E0) >> 2) & 0xFF; + p[(j * width + i) * 3 + 2] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x001F) << 3) & 0xFF; + } + } + } else if(bpp == 16) { + VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); + p = gdk_pixbuf_get_pixels(VRAMBuf); + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 3 ] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0xF800) >> 8) & 0xFF; + p[(j * width + i) * 3 + 1] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x07C0) >> 3) & 0xFF; + p[(j * width + i) * 3 + 2] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x001F) << 3) & 0xFF; + } + } + } else if(bpp == 24) { + VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); + p = gdk_pixbuf_get_pixels(VRAMBuf); + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 3 ] = vram_ptr[(j * scanW) + i * 3 ]; + p[(j * width + i) * 3 + 1] = vram_ptr[(j * scanW) + i * 3 + 1]; + p[(j * width + i) * 3 + 2] = vram_ptr[(j * scanW) + i * 3 + 2]; + } + } + } else if(bpp == 32) { + VRAMBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height); + p = gdk_pixbuf_get_pixels(VRAMBuf); + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 3 ] = vram_ptr[(j * scanW) + i * 4 ]; + p[(j * width + i) * 3 + 1] = vram_ptr[(j * scanW) + i * 4 + 1]; + p[(j * width + i) * 3 + 2] = vram_ptr[(j * scanW) + i * 4 + 2]; + } + } + } else { + VRAMBuf = gdk_pixbuf_new_from_data(vram_ptr, GDK_COLORSPACE_RGB, FALSE, 8, width, height, width*(bpp/8), NULL,NULL); + } + } +#else + scanptr = vram_ptr; + VRAMBuf = (unsigned int*)malloc(width * height * sizeof(unsigned int)); + p = (unsigned char*)VRAMBuf; + if(bpp == 15) { + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 + 2] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x7C00) >> 7) & 0xFF; + p[(j * width + i) * 4 + 1] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x03E0) >> 2) & 0xFF; + p[(j * width + i) * 4 ] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x001F) << 3) & 0xFF; + } + } + } else if(bpp == 16) { + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 ] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0xF800) >> 8) & 0xFF; + p[(j * width + i) * 4 + 1] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x07C0) >> 3) & 0xFF; + p[(j * width + i) * 4 + 2] = ((*(UINT16*)(vram_ptr + j * scanW + i * 2) & 0x001F) << 3) & 0xFF; + } + } + } else if(bpp == 24) { + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 ] = vram_ptr[j * scanW + i * 3 ]; + p[(j * width + i) * 4 + 1] = vram_ptr[j * scanW + i * 3 + 1]; + p[(j * width + i) * 4 + 2] = vram_ptr[j * scanW + i * 3 + 2]; + } + } + } else if(bpp == 32) { + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 + 2] = ((*(UINT32*)(vram_ptr + j * scanW + i * 4) & 0x00FF0000) >> 16) & 0xFF; + p[(j * width + i) * 4 + 1] = ((*(UINT32*)(vram_ptr + j * scanW + i * 4) & 0x0000FF00) >> 8) & 0xFF; + p[(j * width + i) * 4 ] = ((*(UINT32*)(vram_ptr + j * scanW + i * 4) & 0x000000FF) ) & 0xFF; + } + } + } else { + for(j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + p[(j * width + i) * 4 ] = vram_ptr[j * scanW + i * 3 ]; + p[(j * width + i) * 4 + 1] = vram_ptr[j * scanW + i * 3 + 1]; + p[(j * width + i) * 4 + 2] = vram_ptr[j * scanW + i * 3 + 2]; + } + } + } +#endif + } + } + + // CL-GD544x Video Window + if(cirrusvga->cr[0x3e] & 0x01){ // Check Video Window Master Enable bit + uint32_t_* bitfleld; + int vidwnd_format = ((cirrusvga->cr[0x3e] >> 1) & 0x7); + int vidwnd_bpp = (vidwnd_format==0 || vidwnd_format==4 || vidwnd_format==5) ? 16 : 8; + int vidwnd_horizontalZoom = (cirrusvga->cr[0x31]); + int vidwnd_verticalZoom = (cirrusvga->cr[0x32]); + int vidwnd_region1Adj = (cirrusvga->cr[0x5d]>>0) & 0x3; + int vidwnd_region2Adj = (cirrusvga->cr[0x5d]>>4) & 0x3; + int vidwnd_region1Size = (((cirrusvga->cr[0x36] >> 0) & 0x03) << 8)|(cirrusvga->cr[0x33]); + int vidwnd_region2Size = (((cirrusvga->cr[0x36] >> 2) & 0x03) << 8)|(cirrusvga->cr[0x34]); + int vidwnd_region2SDSize = (((cirrusvga->cr[0x36] >> 4) & 0x03) << 8)|(cirrusvga->cr[0x35]); + int vidwnd_verticalStart = (((cirrusvga->cr[0x39] >> 0) & 0x03) << 8)|(cirrusvga->cr[0x37]); + int vidwnd_verticalEnd = (((cirrusvga->cr[0x39] >> 2) & 0x03) << 8)|(cirrusvga->cr[0x38]); + int vidwnd_startAddress = ((cirrusvga->cr[0x3c] & 0x0f) << 18)|(cirrusvga->cr[0x3b] << 10)|(cirrusvga->cr[0x3a] << 2); + int vidwnd_bufAddressOffset = (((cirrusvga->cr[0x3c] >> 5) & 0x01) << 11)|(cirrusvga->cr[0x3d] << 3); + int vidwnd_srcwidth = vidwnd_region2SDSize * vidwnd_bpp/8; + int vidwnd_srcheight = vidwnd_verticalEnd - vidwnd_verticalStart; + int vidwnd_srcpitch = vidwnd_bufAddressOffset; + int vidwnd_dstwidth = vidwnd_srcwidth;//vidwnd_region2Size * bpp/8; + int vidwnd_dstheight = vidwnd_verticalEnd - vidwnd_verticalStart; + int vidwnd_dstX = vidwnd_region1Size * 32 / bpp + vidwnd_region1Adj * 8 / bpp; + int vidwnd_dstY = vidwnd_verticalStart; + int vidwnd_yuv = 0; + if(vidwnd_horizontalZoom > 0) vidwnd_dstwidth = vidwnd_srcwidth * 256 / vidwnd_horizontalZoom; + if(vidwnd_verticalZoom > 0) vidwnd_srcheight = vidwnd_dstheight * vidwnd_verticalZoom / 256; +#if defined(NP2_WIN) + switch(vidwnd_format){ + case 0: // YUV 4:2:2 UYVY + vidwnd_yuv = 1; + vidwnd_bpp = 32; + ga_bmpInfo->bmiHeader.biCompression = BI_RGB; + break; + case 4: // RGB555 + //// XXX: RGB555になってない??? + //ga_bmpInfo->bmiHeader.biCompression = BI_RGB; + //break; + case 5: // RGB565 + // ビットフィールドでRGB565を指定 + bitfleld = (uint32_t_*)(ga_bmpInfo->bmiColors); + bitfleld[0] = 0x0000F800; + bitfleld[1] = 0x000007E0; + bitfleld[2] = 0x0000001F; + ga_bmpInfo->bmiHeader.biCompression = BI_BITFIELDS; + break; + default: + break; + } + ga_bmpInfo->bmiHeader.biBitCount = vidwnd_bpp; + scanptr = vram_ptr + vidwnd_startAddress; +#if defined(DEBUG_CIRRUS_VRAM) + scanptr = scanptr - 1280*16*memshift; // DEBUG +#endif + if(vidwnd_dstwidth == vidwnd_srcwidth && vidwnd_dstheight == vidwnd_srcheight){ + if(!vidwnd_yuv){ + for(i=0;ibmiHeader.biWidth = width; + ga_bmpInfo->bmiHeader.biHeight = 1; + r = SetDIBitsToDevice( + hdc , vidwnd_dstX , vidwnd_dstY + i , + vidwnd_srcwidth , 1 , + 0 , 0 , 0 , 1 , + scanptr , ga_bmpInfo , DIB_RGB_COLORS + ); + scanptr += vidwnd_srcpitch; + } + }else{ + unsigned char *linebuf = (unsigned char*)malloc(vidwnd_srcwidth*4); + for(i=0;ibmiHeader.biWidth = width; + ga_bmpInfo->bmiHeader.biHeight = 1; + r = SetDIBitsToDevice( + hdc , vidwnd_dstX , vidwnd_dstY + i , + vidwnd_srcwidth , 1 , + 0 , 0 , 0 , 1 , + linebuf , ga_bmpInfo , DIB_RGB_COLORS + ); + scanptr += vidwnd_srcpitch; + } + free(linebuf); + } + }else{ + if(!vidwnd_yuv){ + for(i=0;ibmiHeader.biWidth = width; + ga_bmpInfo->bmiHeader.biHeight = 1; + r = StretchDIBits( + hdc , vidwnd_dstX , vidwnd_dstY + i , + vidwnd_dstwidth , 1 , + 0 , 0 , vidwnd_srcwidth , 1 , + scanptr + (i * vidwnd_srcheight / vidwnd_dstheight) * vidwnd_srcpitch, ga_bmpInfo , DIB_RGB_COLORS , SRCCOPY + ); + } + }else{ + int lastline = -1; + unsigned char *linebuf = (unsigned char*)malloc(vidwnd_srcwidth*4); + for(i=0;ibmiHeader.biWidth = width; + ga_bmpInfo->bmiHeader.biHeight = 1; + r = StretchDIBits( + hdc , vidwnd_dstX , vidwnd_dstY + i , + vidwnd_dstwidth , 1 , + 0 , 0 , vidwnd_srcwidth , 1 , + linebuf, ga_bmpInfo , DIB_RGB_COLORS , SRCCOPY + ); + } + free(linebuf); + } + } +#else + // TODO: 非Windows用コードを書く +#endif + } + + if ((cirrusvga->sr[0x12] & CIRRUS_CURSOR_SHOW)){ + int hwcur_x = cirrusvga->hw_cursor_x + cursot_ofs_x; + int hwcur_y = cirrusvga->hw_cursor_y + cursot_ofs_y; + // GA-98NB用 カーソル位置調整 + if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + if(width==320 && height==240){ + hwcur_y /= 2; + } + } + if(np2cfg.gd5430fakecur){ + // ハードウェアカーソルが上手く表示できない場合用 +#if defined(NP2_WIN) + DrawIcon(hdc, hwcur_x, hwcur_y, ga_hFakeCursor); +#elif defined(NP2_X) + int fcx, fcy; + UINT8 col; + p = gdk_pixbuf_get_pixels(VRAMBuf); + for(fcy = 0; fcy < CIRRUS_FMC_H; fcy++) { + for(fcx = 0; fcx < CIRRUS_FMC_W; fcx++) { + col = FakeMouseCursorData[fcy * CIRRUS_FMC_W + fcx]; + if(col && cirrusvga->hw_cursor_x + fcx < width && cirrusvga->hw_cursor_y + fcy < height) { + col--; + p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 3 ] = \ + p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 3 + 1] = \ + p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 3 + 2] = col * 0xFF; + } + } + } +#else + int fcx, fcy; + UINT8 col; + for(fcy = 0; fcy < CIRRUS_FMC_H; fcy++) { + for(fcx = 0; fcx < CIRRUS_FMC_W; fcx++) { + col = FakeMouseCursorData[fcy * CIRRUS_FMC_W + fcx]; + if(col && cirrusvga->hw_cursor_x + fcx < width && cirrusvga->hw_cursor_y + fcy < height) { + col--; + p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 4 ] = \ + p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 4 + 1] = \ + p[((cirrusvga->hw_cursor_y + fcy) * width + cirrusvga->hw_cursor_x + fcx) * 4 + 2] = col * 0xFF; + } + } + } +#endif + }else{ + //HPALETTE oldCurPalette; + int cursize = 32; + int x, y; + int x1, x2, h, w; + //unsigned int basecolor; + unsigned int color0, color1; + uint8_t *d1 = cirrusvga->vram_ptr; + uint8_t *palette, *src, *base; + uint32_t_ *dst; + uint32_t_ content; + uint32_t_ colortmp; + const uint8_t *plane0, *plane1; + int b0, b1; + int poffset; + if (cirrusvga->sr[0x12] & CIRRUS_CURSOR_LARGE) { + cursize = 64; + } +#if defined(NP2_WIN) + BitBlt(ga_hdc_cursor , 0 , 0 , cursize , cursize , hdc , hwcur_x , hwcur_y , SRCCOPY); + + if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; + }else if(np2clvga.gd54xxtype <= 0xff){ + base = cirrusvga->vram_ptr + 1024 * 1024 - 16 * 1024; // ??? 1MB前提? + }else{ + base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; + } + if (height >= hwcur_y && 0 <= (hwcur_y + cursize)){ + int y1, y2; + y1 = hwcur_y; + y2 = hwcur_y+cursize; + h = cursize; + dst = (uint32_t_ *)cursorptr; + dst += 64*64; + dst -= 64; + palette = cirrusvga->cirrus_hidden_palette; + color0 = rgb_to_pixel32(c6_to_8(palette[0x0 * 3]), + c6_to_8(palette[0x0 * 3 + 1]), + c6_to_8(palette[0x0 * 3 + 2])); + color1 = rgb_to_pixel32(c6_to_8(palette[0xf * 3]), + c6_to_8(palette[0xf * 3 + 1]), + c6_to_8(palette[0xf * 3 + 2])); + for(y=y1;ysr[0x12] & CIRRUS_CURSOR_LARGE) { + src += (cirrusvga->sr[0x13] & 0x3c) * 256; + src += (y - (int)hwcur_y) * 16; + poffset = 8; + content = ((uint32_t_ *)src)[0] | + ((uint32_t_ *)src)[1] | + ((uint32_t_ *)src)[2] | + ((uint32_t_ *)src)[3]; + } else { + src += (cirrusvga->sr[0x13] & 0x3f) * 256; + src += (y - (int)hwcur_y) * 4; + poffset = 128; + content = ((uint32_t_ *)src)[0] | + ((uint32_t_ *)(src + 128))[0]; + } + /* if nothing to draw, no need to continue */ + x1 = hwcur_x; + if (x1 < width){ + x2 = hwcur_x + cursize; + w = x2 - x1; + for(x=0;x> 3] >> (7 - ((x) & 7))) & 1; + b1 = (plane1[(x) >> 3] >> (7 - ((x) & 7))) & 1; + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + colortmp ^= 0xffffff; + break; + case 2: + colortmp = color0; + break; + case 3: + colortmp = color1; + break; + } + *dst = colortmp; + dst++; + } + dst += (64 - w); + } + dst -= 64*2; + } + } + BitBlt(hdc , hwcur_x , hwcur_y , cursize , cursize , ga_hdc_cursor , 0 , 0 , SRCCOPY); +#elif defined(NP2_X) + if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; + }else if(np2clvga.gd54xxtype <= 0xff){ + base = cirrusvga->vram_ptr + 1024 * 1024 - 16 * 1024; // ??? 1MB前提? + }else{ + base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; + } + if (height >= hwcur_y && 0 <= (hwcur_y + cursize)){ + UINT8 color0_r, color0_g, color0_b; + UINT8 color1_r, color1_g, color1_b; + int y1, y2; + y1 = hwcur_y; + y2 = hwcur_y+cursize; + h = cursize; + p = gdk_pixbuf_get_pixels(VRAMBuf); + p += (cirrusvga->hw_cursor_y * width + cirrusvga->hw_cursor_x) * 3; // カーソル位置のポインタ + palette = cirrusvga->cirrus_hidden_palette; + color0_r = c6_to_8(palette[0x0 * 3]); + color0_g = c6_to_8(palette[0x0 * 3 + 1]); + color0_b = c6_to_8(palette[0x0 * 3 + 2]); + color1_r = c6_to_8(palette[0xf * 3]); + color1_g = c6_to_8(palette[0xf * 3 + 1]); + color1_b = c6_to_8(palette[0xf * 3 + 2]); + if(y2 > height) y2 = height; + for(y=y1;ysr[0x12] & CIRRUS_CURSOR_LARGE) { + src += (cirrusvga->sr[0x13] & 0x3c) * 256; + src += (y - (int)hwcur_y) * 16; + poffset = 8; + content = ((uint32_t_ *)src)[0] | + ((uint32_t_ *)src)[1] | + ((uint32_t_ *)src)[2] | + ((uint32_t_ *)src)[3]; + } else { + src += (cirrusvga->sr[0x13] & 0x3f) * 256; + src += (y - (int)hwcur_y) * 4; + poffset = 128; + content = ((uint32_t_ *)src)[0] | + ((uint32_t_ *)(src + 128))[0]; + } + /* if nothing to draw, no need to continue */ + UINT8 colortmp_r, colortmp_g, colortmp_b; + const uint8_t *plane0, *plane1; + int b0, b1; + x1 = hwcur_x; + if (x1 < width){ + x2 = hwcur_x + cursize; + w = x2 - x1; + for(x=0;x> 3] >> (7 - ((x) & 7))) & 1; + b1 = (plane1[(x) >> 3] >> (7 - ((x) & 7))) & 1; + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + colortmp_r ^= 0xff; + colortmp_g ^= 0xff; + colortmp_b ^= 0xff; + break; + case 2: + colortmp_r = color0_r; + colortmp_g = color0_g; + colortmp_b = color0_b; + break; + case 3: + colortmp_r = color1_r; + colortmp_g = color1_g; + colortmp_b = color1_b; + break; + } + *p = colortmp_r; + *(p+1) = colortmp_g; + *(p+2) = colortmp_b; + } + p += 3; + } + p += (width - w) * 3; + } + } + } +#else + if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; + }else if(np2clvga.gd54xxtype <= 0xff){ + base = cirrusvga->vram_ptr + 1024 * 1024 - 16 * 1024; // ??? 1MB前提? + }else{ + base = cirrusvga->vram_ptr + cirrusvga->real_vram_size - 16 * 1024; + } + if (height >= hwcur_y && 0 <= (hwcur_y + cursize)){ + UINT8 color0_r, color0_g, color0_b; + UINT8 color1_r, color1_g, color1_b; + int y1, y2; + y1 = hwcur_y; + y2 = hwcur_y+cursize; + h = cursize; + p += (cirrusvga->hw_cursor_y * width + cirrusvga->hw_cursor_x) * 4; // カーソル位置のポインタ + palette = cirrusvga->cirrus_hidden_palette; + color0_r = c6_to_8(palette[0x0 * 3]); + color0_g = c6_to_8(palette[0x0 * 3 + 1]); + color0_b = c6_to_8(palette[0x0 * 3 + 2]); + color1_r = c6_to_8(palette[0xf * 3]); + color1_g = c6_to_8(palette[0xf * 3 + 1]); + color1_b = c6_to_8(palette[0xf * 3 + 2]); + if(y2 > height) y2 = height; + for(y=y1;ysr[0x12] & CIRRUS_CURSOR_LARGE) { + src += (cirrusvga->sr[0x13] & 0x3c) * 256; + src += (y - (int)hwcur_y) * 16; + poffset = 8; + content = ((uint32_t_ *)src)[0] | + ((uint32_t_ *)src)[1] | + ((uint32_t_ *)src)[2] | + ((uint32_t_ *)src)[3]; + } else { + src += (cirrusvga->sr[0x13] & 0x3f) * 256; + src += (y - (int)hwcur_y) * 4; + poffset = 128; + content = ((uint32_t_ *)src)[0] | + ((uint32_t_ *)(src + 128))[0]; + } + /* if nothing to draw, no need to continue */ + x1 = hwcur_x; + if (x1 < width){ + x2 = hwcur_x + cursize; + w = x2 - x1; + for(x=0;x> 3] >> (7 - ((x) & 7))) & 1; + b1 = (plane1[(x) >> 3] >> (7 - ((x) & 7))) & 1; + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + colortmp_r ^= 0xff; + colortmp_g ^= 0xff; + colortmp_b ^= 0xff; + break; + case 2: + colortmp_r = color0_r; + colortmp_g = color0_g; + colortmp_b = color0_b; + break; + case 3: + colortmp_r = color1_r; + colortmp_g = color1_g; + colortmp_b = color1_b; + break; + } + *p = colortmp_r; + *(p+1) = colortmp_g; + *(p+2) = colortmp_b; + } + p += 4; + } + p += (width - w) * 4; + } + } + } +#endif + } + } +#if defined(NP2_WIN) + ga_bmpInfo->bmiHeader.biWidth = width; // 前回の解像度を保存 + ga_bmpInfo->bmiHeader.biHeight = height; // 前回の解像度を保存 +#elif defined(NP2_X) + if(VRAMBuf && np2wabwnd.pPixbuf) { + gdk_pixbuf_scale(VRAMBuf, np2wabwnd.pPixbuf, + 0, 0, width, height, + 0, 0, 1, 1, + GDK_INTERP_NEAREST); + g_object_unref(VRAMBuf); + if(bpp == 24) { + UINT8* ptr = (UINT8 *)gdk_pixbuf_get_pixels(np2wabwnd.pPixbuf); + for(i = 0; i < 1280 * 1024; i++) { + j = ptr[i * 3]; + ptr[i * 3] = ptr[i * 3 + 2]; + ptr[i * 3 + 2] = j; + } + } + } +#else + memcpy(np2wabwnd.pBuffer, VRAMBuf, width * height * sizeof(unsigned int)); + free(VRAMBuf); +#endif + return 1; +} + +/*************************************** + * + * PC-9821 support + * + ***************************************/ +static void IOOUTCALL cirrusvga_ofa2(UINT port, REG8 dat) { + TRACEOUT(("CIRRUS VGA: set register index %02X", dat)); + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + } + cirrusvga_regindexA2 = dat; + (void)port; + (void)dat; +} +static REG8 IOINPCALL cirrusvga_ifa2(UINT port) { + TRACEOUT(("CIRRUS VGA: get register index %02X", cirrusvga_regindex)); + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + } + return cirrusvga_regindexA2; +} +static void IOOUTCALL cirrusvga_ofa3(UINT port, REG8 dat) { + TRACEOUT(("CIRRUS VGA: out %04X d=%.2X", port, dat)); + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + } + switch(cirrusvga_regindexA2){ + case 0x00: + // 機種判定? + break; + case 0x01: + // VRAMウィンドウアドレス設定 + switch(dat){ + case 0x10: + np2clvga.VRAMWindowAddr2 = 0x0b0000; + break; + case 0x80: + np2clvga.VRAMWindowAddr2 = 0xf20000; + break; + case 0xA0: + np2clvga.VRAMWindowAddr2 = 0xf00000; + break; + case 0xC0: + np2clvga.VRAMWindowAddr2 = 0xf40000; + break; + case 0xE0: + np2clvga.VRAMWindowAddr2 = 0xf60000; + break; + } + break; + case 0x02: + // リニアVRAMアクセス用アドレス設定 + if(np2clvga.gd54xxtype != CIRRUS_98ID_PCI){ + if(np2clvga.gd54xxtype <= 0xff){ + if(dat!=0x00 && dat!=0xff) np2clvga.VRAMWindowAddr = (dat<<24); + } + } + break; + case 0x03: + // 出力切替リレー制御 + if((!!np2wab.relaystateint) != (!!(dat&0x2))){ + np2wab.relaystateint = dat & 0x2; + np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) + } + np2clvga.mmioenable = (dat&0x1); + break; + } + (void)port; + (void)dat; +} +static REG8 IOINPCALL cirrusvga_ifa3(UINT port) { + REG8 ret = 0xff; + + TRACEOUT(("CIRRUS VGA: inp %04X", port)); + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + } + switch(cirrusvga_regindexA2){ + case 0x00: + // 機種判定? + if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + ret = 0xff; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ + ret = (REG8)np2clvga.gd54xxtype; + }else{ + ret = 0xff; + } + break; + case 0x01: + // VRAMウィンドウアドレス設定 + //if(np2clvga.gd54xxtype <= 0xff){ + switch(np2clvga.VRAMWindowAddr2){ + case 0x0b0000: + ret = 0x10; + break; + case 0xf00000: + ret = 0xA0; + break; + case 0xf20000: + ret = 0x80; + break; + case 0xf40000: + ret = 0xC0; + break; + case 0xf60000: + ret = 0xE0; + break; + } + //}else{ + // ret = 0xff; + //} + break; + case 0x02: + // リニアVRAMアクセス用アドレス設定 + if(np2clvga.gd54xxtype <= 0xff){ + ret = (np2clvga.VRAMWindowAddr>>24)&0xff; + }else{ + ret = 0xff; + } + break; + case 0x03: + // 出力切替リレー制御 + ret = ((np2wab.relaystateint&0x2) ? 0x2 : 0x0) | np2clvga.mmioenable; + break; + case 0x04: + // ? + ret = 0x00; + break; + } + return ret; +} + +static void IOOUTCALL cirrusvga_ofaa(UINT port, REG8 dat) { + TRACEOUT(("CIRRUS VGA: set register index %02X", dat)); + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + } + cirrusvga_regindex = dat; + (void)port; + (void)dat; +} +static REG8 IOINPCALL cirrusvga_ifaa(UINT port) { + TRACEOUT(("CIRRUS VGA: get register index %02X", cirrusvga_regindex)); + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + } + return cirrusvga_regindex; +} +static void IOOUTCALL cirrusvga_ofab(UINT port, REG8 dat) { + TRACEOUT(("CIRRUS VGA: out %04X d=%.2X", port, dat)); + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + } + switch(cirrusvga_regindex){ + case 0x00: + // 機種判定 + break; + case 0x01: + // VRAMウィンドウアドレス設定 + switch(dat){ + case 0x10: + np2clvga.VRAMWindowAddr2 = 0x0b0000; + break; + case 0x80: + np2clvga.VRAMWindowAddr2 = 0xf20000; + break; + case 0xA0: + np2clvga.VRAMWindowAddr2 = 0xf00000; + break; + case 0xC0: + np2clvga.VRAMWindowAddr2 = 0xf40000; + break; + case 0xE0: + np2clvga.VRAMWindowAddr2 = 0xf60000; + break; + } + break; + case 0x02: + // リニアVRAMアクセス用アドレス設定 + if(dat!=0x00 && dat!=0xff) np2clvga.VRAMWindowAddr = (dat<<24); + //cirrusvga->vram_offset = np2clvga.VRAMWindowAddr; + break; + case 0x03: + // 出力切替リレー制御 + if((!!np2wab.relaystateint) != (!!(dat&0x2))){ + np2wab.relaystateint = dat & 0x2; + np2wab.relaystateext = dat & 0x2; // ( ̄∀ ̄;) + np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) + } + np2clvga.mmioenable = (dat&0x1); + break; + } + (void)port; + (void)dat; +} +static REG8 IOINPCALL cirrusvga_ifab(UINT port) { + REG8 ret = 0xff; + TRACEOUT(("CIRRUS VGA: inp %04X", port)); + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + } + switch(cirrusvga_regindex){ + case 0x00: + // 機種判定 + if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + ret = 0xff; + }else if(np2clvga.gd54xxtype <= 0xff){ + ret = (REG8)np2clvga.gd54xxtype;//0x5B; + }else{ + ret = 0xff; + } + break; + case 0x01: + // VRAMウィンドウアドレス設定 + if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + ret = 0x80; + }else{ + if(np2clvga.gd54xxtype <= 0xff){ + switch(np2clvga.VRAMWindowAddr2){ + case 0x0b0000: + ret = 0x10; + break; + case 0xf20000: + ret = 0x80; + break; + case 0xf00000: + ret = 0xA0; + break; + case 0xf40000: + ret = 0xC0; + break; + case 0xf60000: + ret = 0xE0; + break; + } + }else{ + ret = 0xff; + } + } + break; + case 0x02: + // リニアVRAMアクセス用アドレス設定 + if(np2clvga.gd54xxtype <= 0xff){ + ret = (np2clvga.VRAMWindowAddr>>24)&0xff; + }else{ + ret = 0xff; + } + break; + case 0x03: + // 出力切替リレー制御 + ret = (np2wab.relay ? 0x2 : 0x0) | np2clvga.mmioenable; + break; + } + return ret; +} + +int cirrusvga_videoenable = 0x00; +static void IOOUTCALL cirrusvga_off82(UINT port, REG8 dat) { + TRACEOUT(("CIRRUS VGA: out %04X d=%02X", port, dat)); + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + } + cirrusvga_videoenable = dat & 0x1; + (void)port; + (void)dat; +} +static REG8 IOINPCALL cirrusvga_iff82(UINT port) { + TRACEOUT(("CIRRUS VGA: inp %04X", port)); + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + np2clvga.gd54xxtype = CIRRUS_98ID_Xe10; + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + } + return cirrusvga_videoenable; +} + +int cirrusvga_reg0904 = 0x00; +static void IOOUTCALL cirrusvga_o0904(UINT port, REG8 dat) { + TRACEOUT(("CIRRUS VGA: out %04X d=%02X", port, dat)); + cirrusvga_reg0904 = dat; + (void)port; + (void)dat; +} +static REG8 IOINPCALL cirrusvga_i0904(UINT port) { + TRACEOUT(("CIRRUS VGA: inp %04X", port)); + return cirrusvga_reg0904; +} + +// WAB, WSN用 +static void cirrusvga_setAutoWABID() { + switch(np2clvga.defgd54xxtype){ + case CIRRUS_98ID_AUTO_XE_G1_PCI: + np2clvga.gd54xxtype = CIRRUS_98ID_GA98NBIC; + memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); + cirrusvga_wab_59e1 = 0x06; // d.c. + cirrusvga_wab_51e1 = 0xC2; // d.c. + cirrusvga_wab_5be1 = 0xf7; // d.c. + cirrusvga_wab_40e1 = 0xC2; // bit1=0:DRAM REFRESH MODE?? とりあえず初期値はC2hじゃないとWin95ドライバはボードを認識しない + cirrusvga_wab_42e1 = 0x18; // 存在しない + cirrusvga_wab_46e8 = 0x18; + break; + case CIRRUS_98ID_AUTO_XE_G2_PCI: + np2clvga.gd54xxtype = CIRRUS_98ID_GA98NBII; + memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); + cirrusvga_wab_59e1 = 0x06; // d.c. + cirrusvga_wab_51e1 = 0xC2; // d.c. + cirrusvga_wab_5be1 = 0xf7; // d.c. + cirrusvga_wab_40e1 = 0xC2; // bit1=0:DRAM REFRESH MODE?? とりあえず初期値はC2hじゃないとWin95ドライバはボードを認識しない + cirrusvga_wab_42e1 = 0x18; // 存在しない + cirrusvga_wab_46e8 = 0x18; + break; + case CIRRUS_98ID_AUTO_XE_G4_PCI: + np2clvga.gd54xxtype = CIRRUS_98ID_GA98NBIV; + memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); + cirrusvga_wab_59e1 = 0x06; // d.c. + cirrusvga_wab_51e1 = 0xC2; // d.c. + cirrusvga_wab_5be1 = 0xf7; // d.c. + cirrusvga_wab_40e1 = 0xC2; // bit1=0:DRAM REFRESH MODE?? とりあえず初期値はC2hじゃないとWin95ドライバはボードを認識しない + cirrusvga_wab_42e1 = 0x18; // 存在しない + cirrusvga_wab_46e8 = 0x18; + break; + case CIRRUS_98ID_AUTO_XE10_WABS: + case CIRRUS_98ID_AUTO_XE_WA_PCI: + np2clvga.gd54xxtype = CIRRUS_98ID_WAB; + break; + case CIRRUS_98ID_AUTO_XE10_WSN4: + case CIRRUS_98ID_AUTO_XE_W4_PCI: + np2clvga.gd54xxtype = CIRRUS_98ID_WSN; + break; + default: + np2clvga.gd54xxtype = CIRRUS_98ID_WSN_A2F; + break; + } + pc98_cirrus_setWABreg(); + pc98_cirrus_vga_setvramsize(); + pc98_cirrus_vga_initVRAMWindowAddr(); + cirrusvga_updated = 1; +} + +static REG8 IOINPCALL cirrusvga_i59e1(UINT port) { + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + cirrusvga_setAutoWABID(); + } + return cirrusvga_wab_59e1; +} +static REG8 IOINPCALL cirrusvga_i51e1(UINT port) { + REG8 ret = cirrusvga_wab_51e1; + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + cirrusvga_setAutoWABID(); + } + //if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ + // ret = 0xC2; + //} + if (port == 0x51e1) { + return 0xff; + } + else { + return ret; + } +} +static void IOOUTCALL cirrusvga_o51e1(UINT port, REG8 dat) { + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + cirrusvga_setAutoWABID(); + } + cirrusvga_wab_51e1 = dat; + (void)port; + (void)dat; +} +static REG8 IOINPCALL cirrusvga_i5be1(UINT port) { + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + cirrusvga_setAutoWABID(); + } +// return 0xf7; // XXX: 0x08 is VRAM 4M flag? + if (np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F) { + cirrusvga_wab_5be1 |= 0x08; + } + return cirrusvga_wab_5be1; +} +//static void IOOUTCALL cirrusvga_o5be3(UINT port, REG8 dat) { +// if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ +// cirrusvga_setAutoWABID(); +// } +// (void)port; +// (void)dat; +//} + +static REG8 IOINPCALL cirrusvga_i40e1(UINT port) { + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || + (np2clvga.defgd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK && (np2clvga.gd54xxtype == CIRRUS_98ID_Xe10 || np2clvga.gd54xxtype == CIRRUS_98ID_PCI)){ // 強制変更を許す + cirrusvga_setAutoWABID(); + } + //cirrusvga_wab_40e1--; + //TRACEOUT(("CIRRUS VGA: out %04X d=%02X", port, cirrusvga_wab_40e1)); + return cirrusvga_wab_40e1; +} +static void IOOUTCALL cirrusvga_o40e1(UINT port, REG8 dat) { + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + cirrusvga_setAutoWABID(); + } + cirrusvga_wab_40e1 = dat; + + np2wab.relaystateint = (np2wab.relaystateint & ~0x1) | (cirrusvga_wab_40e1 & 0x1); + np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) + (void)port; + (void)dat; +} +static REG8 IOINPCALL cirrusvga_i42e1(UINT port) { + if ((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK) { + cirrusvga_setAutoWABID(); + } + return cirrusvga_wab_42e1; +} +static void IOOUTCALL cirrusvga_o42e1(UINT port, REG8 dat) { + if ((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK) { + cirrusvga_setAutoWABID(); + } + cirrusvga_wab_42e1 = dat; + cirrus_update_memory_access(cirrusvga); + (void)port; + (void)dat; +} +static REG8 IOINPCALL cirrusvga_i46e8(UINT port) { + REG8 ret = cirrusvga_wab_46e8; + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + cirrusvga_setAutoWABID(); + } + //np2wab.relaystateint = (np2wab.relaystateint & ~0x1) | (cirrusvga_wab_40e1 & 0x1); + //np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) + return ret; +} +static void IOOUTCALL cirrusvga_o46e8(UINT port, REG8 dat) { + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + cirrusvga_setAutoWABID(); + } + cirrusvga_wab_46e8 = dat; + (void)port; + (void)dat; +} + +//int cirrusvga_wab_52E2 = 0x18; +//static REG8 IOINPCALL cirrusvga_i52E2(UINT port) { +// REG8 ret = cirrusvga_wab_52E2; +// return ret; +//} +//static void IOOUTCALL cirrusvga_o52E2(UINT port, REG8 dat) { +// cirrusvga_wab_52E2 = dat; +// (void)port; +// (void)dat; +//} +//int cirrusvga_wab_56E2 = 0x80; +//static REG8 IOINPCALL cirrusvga_i56E2(UINT port) { +// REG8 ret = cirrusvga_wab_56E2; +// return ret; +//} +//static void IOOUTCALL cirrusvga_o56E2(UINT port, REG8 dat) { +// cirrusvga_wab_56E2 = dat; +// (void)port; +// (void)dat; +//} +//int cirrusvga_wab_59E2 = 0x18; +//static REG8 IOINPCALL cirrusvga_i59E2(UINT port) { +// REG8 ret = cirrusvga_wab_59E2; +// return ret; +//} +//static void IOOUTCALL cirrusvga_o59E2(UINT port, REG8 dat) { +// cirrusvga_wab_59E2 = dat; +// (void)port; +// (void)dat; +//} +//int cirrusvga_wab_5BE2 = 0x18; +//static REG8 IOINPCALL cirrusvga_i5BE2(UINT port) { +// REG8 ret = cirrusvga_wab_5BE2; +// return ret; +//} +//static void IOOUTCALL cirrusvga_o5BE2(UINT port, REG8 dat) { +// cirrusvga_wab_5BE2 = dat; +// (void)port; +// (void)dat; +//} + +static void vga_dumb_update_retrace_info(VGAState *s) +{ + (void) s; +} + +// MMIOウィンドウを設定する +void pc98_cirrus_setMMIOWindowAddr(){ + if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ + cirrus_mmio_read[0] = cirrus_mmio_readb_wab; + cirrus_mmio_read[1] = cirrus_mmio_readw_wab; + cirrus_mmio_read[2] = cirrus_mmio_readl_wab; + cirrus_mmio_write[0] = cirrus_mmio_writeb_wab; + cirrus_mmio_write[1] = cirrus_mmio_writew_wab; + cirrus_mmio_write[2] = cirrus_mmio_writel_wab; + }else if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC) { + cirrus_mmio_read[0] = cirrus_mmio_readb_wab; + cirrus_mmio_read[1] = cirrus_mmio_readw_wab; + cirrus_mmio_read[2] = cirrus_mmio_readl_wab; + cirrus_mmio_write[0] = cirrus_mmio_writeb_wab; + cirrus_mmio_write[1] = cirrus_mmio_writew_wab; + cirrus_mmio_write[2] = cirrus_mmio_writel_wab; + }else{ + cirrus_mmio_read[0] = cirrus_mmio_readb; + cirrus_mmio_read[1] = cirrus_mmio_readw; + cirrus_mmio_read[2] = cirrus_mmio_readl; + cirrus_mmio_write[0] = cirrus_mmio_writeb; + cirrus_mmio_write[1] = cirrus_mmio_writew; + cirrus_mmio_write[2] = cirrus_mmio_writel; + } +} + +void pc98_cirrus_vga_updatePCIaddr(){ + if((np2clvga.gd54xxtype & CIRRUS_98ID_WABMASK) == CIRRUS_98ID_WAB || (np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + pc98_cirrus_setMMIOWindowAddr(); + return; + } +#if defined(SUPPORT_PCI) + if((pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[0] & 0xfffffff0) != ~pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[0]){ + np2clvga.pciLFB_Addr = pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[0] & 0xfffffff0; + np2clvga.pciLFB_Mask = ~pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[0]; + + cirrusvga->map_addr = cirrusvga->map_end = 0; + cirrusvga->lfb_addr = np2clvga.pciLFB_Addr & TARGET_PAGE_MASK; + cirrusvga->lfb_end = ((np2clvga.pciLFB_Addr + cirrusvga->real_vram_size) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; + /* account for overflow */ + if (cirrusvga->lfb_end < np2clvga.pciLFB_Addr + cirrusvga->real_vram_size) + cirrusvga->lfb_end = np2clvga.pciLFB_Addr + cirrusvga->real_vram_size; + }else{ + np2clvga.pciLFB_Addr = 0; + } + if((pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[1] & 0xfffffff0) != ~pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[1]){ + np2clvga.pciMMIO_Addr = pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[1] & 0xfffffff0; + np2clvga.pciMMIO_Mask = ~pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[1]; + }else{ + np2clvga.pciMMIO_Addr = 0; + } + + pc98_cirrus_setMMIOWindowAddr(); + cirrus_update_memory_access(cirrusvga); +#endif +} + +// VRAMウィンドウアドレスをデフォルト値に設定する +void pc98_cirrus_vga_initVRAMWindowAddr(){ + np2clvga.pciLFB_Addr = 0; + np2clvga.pciLFB_Mask = 0; + np2clvga.pciMMIO_Addr = 0; + np2clvga.pciMMIO_Mask = 0; +#if defined(SUPPORT_PCI) + pcidev.devices[pcidev_cirrus_deviceid].enable = 0; +#endif + if(np2clvga.gd54xxtype == CIRRUS_98ID_Be){ + np2clvga.VRAMWindowAddr = 0; + np2clvga.VRAMWindowAddr2 = 0xf00000; + np2clvga.VRAMWindowAddr3 = 0; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ + np2clvga.VRAMWindowAddr = 0; + np2clvga.VRAMWindowAddr2 = 0xf00000; + np2clvga.VRAMWindowAddr3 = 0; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + np2clvga.VRAMWindowAddr = 0; + np2clvga.VRAMWindowAddr2 = 0; + np2clvga.VRAMWindowAddr3 = 0; +#if defined(SUPPORT_PCI) + pcidev.devices[pcidev_cirrus_deviceid].enable = 1; +#endif + pc98_cirrus_vga_updatePCIaddr(); + }else if(np2clvga.gd54xxtype <= 0xff){ + np2clvga.VRAMWindowAddr = 0; + np2clvga.VRAMWindowAddr2 = 0xf60000; + np2clvga.VRAMWindowAddr3 = 0; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ + np2clvga.VRAMWindowAddr = 0; + np2clvga.VRAMWindowAddr2 = 0xE0000; + np2clvga.VRAMWindowAddr3 = 0xF00000; + np2clvga.pciMMIO_Addr = 0xf10000; + np2clvga.pciMMIO_Mask = ~(0x10000-1); + }else if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC) { + np2clvga.VRAMWindowAddr = 0; + np2clvga.VRAMWindowAddr2 = 0xE0000; + np2clvga.VRAMWindowAddr3 = 0xF00000; + np2clvga.pciMMIO_Addr = 0xf10000; + np2clvga.pciMMIO_Mask = ~(0x10000-1); + }else{ + np2clvga.VRAMWindowAddr = 0; + np2clvga.VRAMWindowAddr2 = 0; + np2clvga.VRAMWindowAddr3 = 0; + if(np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI){ +#if defined(SUPPORT_PCI) + pcidev.devices[pcidev_cirrus_deviceid].enable = 1; +#endif + pc98_cirrus_vga_updatePCIaddr(); + } + } + pc98_cirrus_setMMIOWindowAddr(); + cirrus_update_memory_access(cirrusvga); +} + +// ボード種類からVRAMサイズを決定する +void pc98_cirrus_vga_setvramsize(){ +#if defined(SUPPORT_IA32_HAXM) + // PCIメモリ割り当て解除 + i386hax_vm_removememoryarea(vramptr, mmio_mode_region2, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); + i386hax_vm_removememoryarea(vramptr, np2clvga.pciLFB_Addr, lastlinmmio ? cirrusvga->linear_mmio_mask : cirrusvga->real_vram_size); + lastlinmmio = 0; +#endif + + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK){ + cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ + cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_1MB; //(cirrusvga->device_id == CIRRUS_ID_CLGD5446) ? CIRRUS_VRAM_SIZE : CIRRUS_VRAM_SIZE; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_Be){ + cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_1MB; //(cirrusvga->device_id == CIRRUS_ID_CLGD5446) ? CIRRUS_VRAM_SIZE : CIRRUS_VRAM_SIZE; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_2MB; + }else if(np2clvga.gd54xxtype <= 0xff){ + cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE; //(cirrusvga->device_id == CIRRUS_ID_CLGD5446) ? CIRRUS_VRAM_SIZE : CIRRUS_VRAM_SIZE; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ + cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_WAB; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ + cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_2MB; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ + cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_4MB; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_GA98NBIC){ + cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_1MB; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_GA98NBII){ + cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_2MB; + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_GA98NBIV){ + cirrusvga->real_vram_size = CIRRUS_VRAM_SIZE_4MB; + }else{ + cirrusvga->real_vram_size = (cirrusvga->device_id == CIRRUS_ID_CLGD5446) ? CIRRUS_VRAM_SIZE : CIRRUS_VRAM_SIZE; + } + cirrusvga->vram_ptr = vramptr; + cirrusvga->vram_offset = 0; + cirrusvga->vram_size = cirrusvga->real_vram_size; + + /* XXX: s->vram_size must be a power of two */ + cirrusvga->cirrus_addr_mask = cirrusvga->real_vram_size - 1; + cirrusvga->linear_mmio_mask = cirrusvga->real_vram_size - 256; + +#if defined(SUPPORT_IA32_HAXM) + cirrus_linear_mmio_update(cirrusvga); +#endif +} +void pc98_cirrus_vga_setVRAMWindowAddr3(UINT32 addr) +{ + cirrusvga->sr[0x07] = (cirrusvga->sr[0x07] & 0x0f) | ((addr >> 16) & 0xf0); + cirrus_update_memory_access(cirrusvga); +} +static void pc98_cirrus_reset(CirrusVGAState * s, int device_id, int is_pci) +{ + //np2clvga.VRAMWindowAddr = (0x0F<<24); + //np2clvga.VRAMWindowAddr2 = (0xf20000); + + np2clvga.VRAMWindowAddr2 = 0; + np2clvga.VRAMWindowAddr3 = 0; + + pc98_cirrus_vga_initVRAMWindowAddr(); + + s->cirrus_rop = cirrus_bitblt_rop_nop; + + np2wab.relaystateext = 0; + np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); +#if defined(NP2_WINX) + ShowWindow(np2wabwnd.hWndWAB, SW_HIDE); // 設定変更対策 +#endif + + np2clvga.mmioenable = 0; + np2wab.paletteChanged = 1; +} +void pcidev_cirrus_cfgreg_w(UINT32 devNumber, UINT8 funcNumber, UINT8 cfgregOffset, UINT8 sizeinbytes, UINT32 value){ + if(0x10 <= cfgregOffset && cfgregOffset < 0x28){ + pc98_cirrus_vga_initVRAMWindowAddr(); + } +} +static void pc98_cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci) +{ + int i; + + for(i = 0;i < 256; i++) + rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */ + rop_to_index[CIRRUS_ROP_0] = 0; + rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1; + rop_to_index[CIRRUS_ROP_NOP] = 2; + rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3; + rop_to_index[CIRRUS_ROP_NOTDST] = 4; + rop_to_index[CIRRUS_ROP_SRC] = 5; + rop_to_index[CIRRUS_ROP_1] = 6; + rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7; + rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8; + rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9; + rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10; + rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11; + rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12; + rop_to_index[CIRRUS_ROP_NOTSRC] = 13; + rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14; + rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15; + s->device_id = device_id; + s->bustype = CIRRUS_BUSTYPE_ISA; + + cirrusvga_wab_46e8 = 0x18; // デフォルトで有効 + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype <= 0xff){ + // ONBOARD +#if defined(SUPPORT_PCI) + if(pcidev.enable && (np2clvga.gd54xxtype == CIRRUS_98ID_PCI || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI)){ + // Cirrus CL-GD5446 PCI + ZeroMemory(pcidev.devices+pcidev_cirrus_deviceid, sizeof(_PCIDEVICE)); + pcidev.devices[pcidev_cirrus_deviceid].enable = 1; + pcidev.devices[pcidev_cirrus_deviceid].skipirqtbl = 1; + pcidev.devices[pcidev_cirrus_deviceid].regwfn = &pcidev_cirrus_cfgreg_w; + pcidev.devices[pcidev_cirrus_deviceid].header.vendorID = 0x1013; + pcidev.devices[pcidev_cirrus_deviceid].header.deviceID = CIRRUS_ID_CLGD5446; + pcidev.devices[pcidev_cirrus_deviceid].header.command = 0x0003;//0x0006;//;0x0003; + pcidev.devices[pcidev_cirrus_deviceid].header.status = 0x0000;//0x0000;//0x0280; + pcidev.devices[pcidev_cirrus_deviceid].header.revisionID = 0x00; + pcidev.devices[pcidev_cirrus_deviceid].header.classcode[0] = 0x00; // レジスタレベルプログラミングインタフェース + pcidev.devices[pcidev_cirrus_deviceid].header.classcode[1] = 0x00; // サブクラスコード + pcidev.devices[pcidev_cirrus_deviceid].header.classcode[2] = 0x03; // ベースクラスコード + pcidev.devices[pcidev_cirrus_deviceid].header.cachelinesize = 0; + pcidev.devices[pcidev_cirrus_deviceid].header.latencytimer = 0x00; + pcidev.devices[pcidev_cirrus_deviceid].header.headertype = 0; + pcidev.devices[pcidev_cirrus_deviceid].header.BIST = 0x00; + pcidev.devices[pcidev_cirrus_deviceid].header.subsysID = 0x0000; + pcidev.devices[pcidev_cirrus_deviceid].header.subsysventorID = 0x0000; + pcidev.devices[pcidev_cirrus_deviceid].header.interruptpin = 0xff; + pcidev.devices[pcidev_cirrus_deviceid].header.interruptline = 0x00; +#if defined(SUPPORT_IA32_HAXM) + pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[0] = 0xFC000000; + pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[1] = 0xFE000000; +#else + pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[0] = 0xF0000000; + pcidev.devices[pcidev_cirrus_deviceid].header.baseaddrregs[1] = 0xF2000000; +#endif + pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[0] = 0x02000000-1; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[1] = CIRRUS_PNPMMIO_SIZE-1; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[2] = 0xffffffff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[3] = 0xffffffff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[4] = 0xffffffff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.baseaddrregs[5] = 0xffffffff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.expROMbaseaddr = 0xffffffff; + pc98_cirrus_vga_initVRAMWindowAddr(); + s->bustype = CIRRUS_BUSTYPE_PCI; + + // ROM領域設定 + pcidev.devices[pcidev_cirrus_deviceid].headerrom.vendorID = 0xffff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.deviceID = 0xffff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.status = 0xffff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.command = 0xffdd; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.revisionID = 0xff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.classcode[0] = 0xff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.classcode[1] = 0xff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.classcode[2] = 0xff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.subsysID = 0xffff; + pcidev.devices[pcidev_cirrus_deviceid].headerrom.subsysventorID = 0xffff; + + for(i=0;i<16;i++){ + iocore_attachout(0x3c0 + i, vga_ioport_write_wrap); + iocore_attachinp(0x3c0 + i, vga_ioport_read_wrap); + } + + iocore_attachout(0x3b4, vga_ioport_write_wrap); + iocore_attachinp(0x3b4, vga_ioport_read_wrap); + iocore_attachout(0x3b5, vga_ioport_write_wrap); + iocore_attachinp(0x3b5, vga_ioport_read_wrap); + iocore_attachout(0x3ba, vga_ioport_write_wrap); + iocore_attachinp(0x3ba, vga_ioport_read_wrap); + iocore_attachout(0x3d4, vga_ioport_write_wrap); + iocore_attachinp(0x3d4, vga_ioport_read_wrap); + iocore_attachout(0x3d5, vga_ioport_write_wrap); + iocore_attachinp(0x3d5, vga_ioport_read_wrap); + iocore_attachout(0x3da, vga_ioport_write_wrap); + iocore_attachinp(0x3da, vga_ioport_read_wrap); + + pcidev_updateRoutingTable(); + } + if(np2clvga.gd54xxtype != CIRRUS_98ID_PCI) +#endif + { + iocore_attachout(0xfa2, cirrusvga_ofa2); + iocore_attachinp(0xfa2, cirrusvga_ifa2); + + iocore_attachout(0xfa3, cirrusvga_ofa3); + iocore_attachinp(0xfa3, cirrusvga_ifa3); + + iocore_attachout(0xfaa, cirrusvga_ofaa); + iocore_attachinp(0xfaa, cirrusvga_ifaa); + + iocore_attachout(0xfab, cirrusvga_ofab); + iocore_attachinp(0xfab, cirrusvga_ifab); + + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype == CIRRUS_98ID_96){ + iocore_attachout(0x0902, cirrusvga_off82); + iocore_attachinp(0x0902, cirrusvga_iff82); + + // XXX: 102Access Control Register 0904h は無視 + + for(i=0;i<16;i++){ + iocore_attachout(0xc50 + i, vga_ioport_write_wrap); // 0x3C0 to 0x3CF + iocore_attachinp(0xc50 + i, vga_ioport_read_wrap); // 0x3C0 to 0x3CF + } + + // この辺のマッピング本当にあってる? + iocore_attachout(0xb54, vga_ioport_write_wrap); // 0x3B4 + iocore_attachinp(0xb54, vga_ioport_read_wrap); // 0x3B4 + iocore_attachout(0xb55, vga_ioport_write_wrap); // 0x3B5 + iocore_attachinp(0xb55, vga_ioport_read_wrap); // 0x3B5 + + iocore_attachout(0xd54, vga_ioport_write_wrap); // 0x3D4 + iocore_attachinp(0xd54, vga_ioport_read_wrap); // 0x3D4 + iocore_attachout(0xd55, vga_ioport_write_wrap); // 0x3D5 + iocore_attachinp(0xd55, vga_ioport_read_wrap); // 0x3D5 + + iocore_attachout(0xb5a, vga_ioport_write_wrap); // 0x3BA + iocore_attachinp(0xb5a, vga_ioport_read_wrap); // 0x3BA + + iocore_attachout(0xd5a, vga_ioport_write_wrap); // 0x3DA + iocore_attachinp(0xd5a, vga_ioport_read_wrap); // 0x3DA + + //iocore_attachout(0x46E8, cirrusvga_o46e8); + //iocore_attachinp(0x46E8, cirrusvga_i46e8); + } + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype != CIRRUS_98ID_96){ + iocore_attachout(0xff82, cirrusvga_off82); + iocore_attachinp(0xff82, cirrusvga_iff82); + + //iocore_attachout(0x904, cirrusvga_o0904); + //iocore_attachinp(0x904, cirrusvga_i0904); + + for(i=0;i<16;i++){ + iocore_attachout(0xca0 + i, vga_ioport_write_wrap); // 0x3C0 to 0x3CF + iocore_attachinp(0xca0 + i, vga_ioport_read_wrap); // 0x3C0 to 0x3CF + } + + // この辺のマッピング本当にあってる? + iocore_attachout(0xba4, vga_ioport_write_wrap); // 0x3B4 + iocore_attachinp(0xba4, vga_ioport_read_wrap); // 0x3B4 + iocore_attachout(0xba5, vga_ioport_write_wrap); // 0x3B5 + iocore_attachinp(0xba5, vga_ioport_read_wrap); // 0x3B5 + + iocore_attachout(0xda4, vga_ioport_write_wrap); // 0x3D4 + iocore_attachinp(0xda4, vga_ioport_read_wrap); // 0x3D4 + iocore_attachout(0xda5, vga_ioport_write_wrap); // 0x3D5 + iocore_attachinp(0xda5, vga_ioport_read_wrap); // 0x3D5 + + iocore_attachout(0xbaa, vga_ioport_write_wrap); // 0x3BA + iocore_attachinp(0xbaa, vga_ioport_read_wrap); // 0x3BA + + iocore_attachout(0xdaa, vga_ioport_write_wrap); // 0x3DA + iocore_attachinp(0xdaa, vga_ioport_read_wrap); // 0x3DA + } + } + } + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype > 0xff){ + // WAB, WSN, GA-98NB + for(i=0;i<0x1000;i+=0x100){ + iocore_attachout(0x40E0 + cirrusvga_melcowab_ofs + i, vga_ioport_write_wrap); // 0x3C0 to 0x3CF + iocore_attachinp(0x40E0 + cirrusvga_melcowab_ofs + i, vga_ioport_read_wrap); // 0x3C0 to 0x3CF + } + + // この辺のマッピング本当にあってる? + // | + // V + // Odd Address:ボード制御,FM音源,PCM音源(Melco) + // Even Address:CIRRUS (Melco,IO-Data) + // モノクロは自信無し,WSN Win95ドライバは58e2h,59e2hをアクセスしてレジスタが + // ffhになっている(カラーモードなので)ことを確認している + //****************************************************** + // port <<= 8; + // port &= 0x7f00; /* Mask 0111 1111 0000 0000 */ + // port |= 0xE0; + //****************************************************** + + iocore_attachout(0x58E0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3B4 これは使っている + iocore_attachinp(0x58E0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3B4 これは使っている + iocore_attachout(0x59E0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3B5 これは使っている + iocore_attachinp(0x59E0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3B5 これは使っている + ////iocore_attachout(0x3AE0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3BA 使ってないからいいや + ////iocore_attachinp(0x3AE0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3BA 使ってないからいいや + + iocore_attachout(0x54E0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3D4 + iocore_attachinp(0x54E0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3D4 + iocore_attachout(0x55E0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3D5 + iocore_attachinp(0x55E0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3D5 + iocore_attachout(0x5AE0 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3DA + iocore_attachinp(0x5AE0 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3DA + + //if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ + // iocore_attachout(0x5BE3, cirrusvga_o5be3); + // iocore_attachinp(0x5BE3, cirrusvga_i5be3); + //} + +// iocore_attachout(0x51E1 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3BA +// iocore_attachinp(0x51E1 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3BA + +// iocore_attachout(0x57E1 + cirrusvga_melcowab_ofs, vga_ioport_write_wrap); // 0x3DA +// iocore_attachinp(0x57E1 + cirrusvga_melcowab_ofs, vga_ioport_read_wrap); // 0x3DA + + iocore_attachout(0x40E1 + cirrusvga_melcowab_ofs, cirrusvga_o40e1); + iocore_attachinp(0x40E1 + cirrusvga_melcowab_ofs, cirrusvga_i40e1); + + iocore_attachout(0x46E8, cirrusvga_o46e8); + iocore_attachinp(0x46E8, cirrusvga_i46e8); + + // WSN + if ((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F) { + iocore_attachout(0x51E1, cirrusvga_o51e1); // CHECK IO 空振り用 + iocore_attachinp(0x51E1, cirrusvga_i51e1); + iocore_attachout(0x51E3, cirrusvga_o51e1); // CHECK IO + iocore_attachinp(0x51E3, cirrusvga_i51e1); + + ////iocore_attachinp(0x59E0 + cirrusvga_melcowab_ofs, cirrusvga_i59e0); + iocore_attachinp(0x59E1 + cirrusvga_melcowab_ofs, cirrusvga_i59e1); // これがないとドライバがNGを返す + iocore_attachinp(0x5BE1 + cirrusvga_melcowab_ofs, cirrusvga_i5be1); + + iocore_attachout(0x42E1 + cirrusvga_melcowab_ofs, cirrusvga_o42e1); + iocore_attachinp(0x42E1 + cirrusvga_melcowab_ofs, cirrusvga_i42e1); + } + + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) != CIRRUS_98ID_AUTOMSK){ + np2clvga.VRAMWindowAddr2 = 0xE0000; + } + + //// GA-98NB + //if (np2clvga.gd54xxtype == CIRRUS_98ID_GA98NB) { + // np2clvga.VRAMWindowAddr2 = 0xf00000; + //} + + if (np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE10_WSN2 || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE10_WSN4 || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI) { + cirrusvga_wab_59e1 = 0x06; // この値じゃないとWSN Win95ドライバがNGを返す + cirrusvga_wab_51e1 = 0xC2; // WSN CHECK IO RETURN VALUE + cirrusvga_wab_5be1 = 0xf7; // bit3:0=4M,1=2M ?????? + cirrusvga_wab_40e1 = 0x7b; + cirrusvga_wab_42e1 = 0x00; + cirrusvga_wab_46e8 = 0x18; // 最初からON + }else if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI) { + memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); + cirrusvga_wab_59e1 = 0x06; // d.c. + cirrusvga_wab_51e1 = 0xC2; // d.c. + cirrusvga_wab_5be1 = 0xf7; // d.c. + cirrusvga_wab_40e1 = 0xC2; // bit1=0:DRAM REFRESH MODE?? とりあえず初期値はC2hじゃないとWin95ドライバはボードを認識しない + cirrusvga_wab_42e1 = 0x18; // 存在しない + cirrusvga_wab_46e8 = 0x10; + cirrusvga_updated = 1; + } + + //np2clvga.VRAMWindowAddr3 = 0xF00000; // XXX + //np2clvga.VRAMWindowAddr3size = 256*1024; + + //iocore_attachout(0x52E2, cirrusvga_o52E2); + //iocore_attachinp(0x52E2, cirrusvga_i52E2); + // + //iocore_attachout(0x56E2, cirrusvga_o56E2); + //iocore_attachinp(0x56E2, cirrusvga_i56E2); + //iocore_attachout(0x56E3, cirrusvga_o56E2); + //iocore_attachinp(0x56E3, cirrusvga_i56E2); + // + //iocore_attachout(0x59E2, cirrusvga_o59E2); + //iocore_attachinp(0x59E2, cirrusvga_i59E2); + //iocore_attachout(0x59E3, cirrusvga_o59E2); + //iocore_attachinp(0x59E3, cirrusvga_i59E2); + // + //iocore_attachout(0x58E2, cirrusvga_o5BE2); + //iocore_attachinp(0x58E2, cirrusvga_i5BE2); + //iocore_attachout(0x5BE2, cirrusvga_o5BE2); + //iocore_attachinp(0x5BE2, cirrusvga_i5BE2); + } + + pc98_cirrus_vga_setvramsize(); + + s->get_bpp = cirrus_get_bpp; + s->get_offsets = cirrus_get_offsets; + s->get_resolution = cirrus_get_resolution; + s->cursor_invalidate = cirrus_cursor_invalidate; + s->cursor_draw_line = cirrus_cursor_draw_line; + + s->update_retrace_info = vga_dumb_update_retrace_info; + s->retrace = vga_dumb_retrace; + + qemu_register_reset(cirrus_reset, s); + cirrus_reset(s); + cirrus_update_memory_access(s); + //register_savevm("cirrus_vga", 0, 2, cirrus_vga_save, cirrus_vga_load, s);// XXX: + //if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB || np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ + // //s->sr[0x06] = 0x12; // Unlock Cirrus extensions by default + //} + cirrusvga_updated = 1; +} +static void pc98_cirrus_deinit_common(CirrusVGAState * s, int device_id, int is_pci) +{ + int i; + + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype <= 0xff){ + // ONBOARD +#if defined(SUPPORT_PCI) + if(pcidev.enable && (np2clvga.gd54xxtype == CIRRUS_98ID_PCI || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI)){ + // Cirrus CL-GD5446 PCI + pcidev.devices[pcidev_cirrus_deviceid].enable = 0; + for(i=0;i<16;i++){ + iocore_detachout(0x3c0 + i); + iocore_detachinp(0x3c0 + i); + } + iocore_detachout(0x3b4); + iocore_detachinp(0x3b4); + iocore_detachout(0x3ba); + iocore_detachinp(0x3ba); + iocore_detachout(0x3d4); + iocore_detachinp(0x3d4); + iocore_detachout(0x3da); + iocore_detachinp(0x3da); + } + if(np2clvga.gd54xxtype != CIRRUS_98ID_PCI) +#endif + { + iocore_detachout(0xfa2); + iocore_detachinp(0xfa2); + + iocore_detachout(0xfa3); + iocore_detachinp(0xfa3); + + iocore_detachout(0xfaa); + iocore_detachinp(0xfaa); + + iocore_detachout(0xfab); + iocore_detachinp(0xfab); + + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype == CIRRUS_98ID_96){ + iocore_detachout(0x0902); + iocore_detachinp(0x0902); + + // XXX: 102Access Control Register 0904h は無視 + + for(i=0;i<16;i++){ + iocore_detachout(0xc50 + i); // 0x3C0 to 0x3CF + iocore_detachinp(0xc50 + i); // 0x3C0 to 0x3CF + } + + // この辺のマッピング本当にあってる? + iocore_detachout(0xb54); // 0x3B4 + iocore_detachinp(0xb54); // 0x3B4 + iocore_detachout(0xb55); // 0x3B5 + iocore_detachinp(0xb55); // 0x3B5 + + iocore_detachout(0xd54); // 0x3D4 + iocore_detachinp(0xd54); // 0x3D4 + iocore_detachout(0xd55); // 0x3D5 + iocore_detachinp(0xd55); // 0x3D5 + + iocore_detachout(0xb5a); // 0x3BA + iocore_detachinp(0xb5a); // 0x3BA + + iocore_detachout(0xd5a); // 0x3DA + iocore_detachinp(0xd5a); // 0x3DA + } + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype != CIRRUS_98ID_96){ + iocore_detachout(0xff82); + iocore_detachinp(0xff82); + + for(i=0;i<16;i++){ + iocore_detachout(0xca0 + i); // 0x3C0 to 0x3CF + iocore_detachinp(0xca0 + i); // 0x3C0 to 0x3CF + } + + // この辺のマッピング本当にあってる? + iocore_detachout(0xba4); // 0x3B4 + iocore_detachinp(0xba4); // 0x3B4 + iocore_detachout(0xba5); // 0x3B5 + iocore_detachinp(0xba5); // 0x3B5 + + iocore_detachout(0xda4); // 0x3D4 + iocore_detachinp(0xda4); // 0x3D4 + iocore_detachout(0xda5); // 0x3D5 + iocore_detachinp(0xda5); // 0x3D5 + + iocore_detachout(0xbaa); // 0x3BA + iocore_detachinp(0xbaa); // 0x3BA + + iocore_detachout(0xdaa); // 0x3DA + iocore_detachinp(0xdaa); // 0x3DA + +#ifdef SUPPORT_VGA_MODEX + if(np2cfg.usemodex){ + for(i=0;i<16;i++){ + iocore_attachout(0x3c0 + i, vga_ioport_write_wrap); + iocore_attachinp(0x3c0 + i, vga_ioport_read_wrap); + } + + iocore_attachout(0x3b4, vga_ioport_write_wrap); + iocore_attachinp(0x3b4, vga_ioport_read_wrap); + iocore_attachout(0x3b5, vga_ioport_write_wrap); + iocore_attachinp(0x3b5, vga_ioport_read_wrap); + iocore_attachout(0x3ba, vga_ioport_write_wrap); + iocore_attachinp(0x3ba, vga_ioport_read_wrap); + iocore_attachout(0x3d4, vga_ioport_write_wrap); + iocore_attachinp(0x3d4, vga_ioport_read_wrap); + iocore_attachout(0x3d5, vga_ioport_write_wrap); + iocore_attachinp(0x3d5, vga_ioport_read_wrap); + iocore_attachout(0x3da, vga_ioport_write_wrap); + iocore_attachinp(0x3da, vga_ioport_read_wrap); + } +#endif + } + } + } + if((np2clvga.gd54xxtype & CIRRUS_98ID_AUTOMSK) == CIRRUS_98ID_AUTOMSK || np2clvga.gd54xxtype > 0xff){ + // WAB, WSN, GA-98NB + for(i=0;i<0x1000;i+=0x100){ + iocore_detachout(0x40E0 + cirrusvga_melcowab_ofs + i); // 0x3C0 to 0x3CF + iocore_detachinp(0x40E0 + cirrusvga_melcowab_ofs + i); // 0x3C0 to 0x3CF + } + + // この辺のマッピング本当にあってる? + iocore_detachout(0x58E0 + cirrusvga_melcowab_ofs); // 0x3B4 + iocore_detachinp(0x58E0 + cirrusvga_melcowab_ofs); // 0x3B4 + iocore_detachout(0x59E0 + cirrusvga_melcowab_ofs); // 0x3B5 + iocore_detachinp(0x59E0 + cirrusvga_melcowab_ofs); // 0x3B5 + ////iocore_detachout(0x3AE0 + cirrusvga_melcowab_ofs); // 0x3BA + ////iocore_detachinp(0x3AE0 + cirrusvga_melcowab_ofs); // 0x3BA + + iocore_detachout(0x54E0 + cirrusvga_melcowab_ofs); // 0x3D4 + iocore_detachinp(0x54E0 + cirrusvga_melcowab_ofs); // 0x3D4 + iocore_detachout(0x55E0 + cirrusvga_melcowab_ofs); // 0x3D5 + iocore_detachinp(0x55E0 + cirrusvga_melcowab_ofs); // 0x3D5 + iocore_detachout(0x5AE0 + cirrusvga_melcowab_ofs); // 0x3DA + iocore_detachinp(0x5AE0 + cirrusvga_melcowab_ofs); // 0x3DA + +// iocore_detachout(0x51E1 + cirrusvga_melcowab_ofs); // 0x3BA +// iocore_detachinp(0x51E1 + cirrusvga_melcowab_ofs); // 0x3BA + +// iocore_detachout(0x57E1 + cirrusvga_melcowab_ofs); // 0x3DA +// iocore_detachinp(0x57E1 + cirrusvga_melcowab_ofs); // 0x3DA + + iocore_detachout(0x40E1 + cirrusvga_melcowab_ofs); + iocore_detachinp(0x40E1 + cirrusvga_melcowab_ofs); + + iocore_detachout(0x46E8); + iocore_detachinp(0x46E8); + + iocore_detachout(0x51E1); + iocore_detachinp(0x51E1); + iocore_detachout(0x51E3); + iocore_detachinp(0x51E3); + + ////iocore_detachinp(0x59E0 + cirrusvga_melcowab_ofs); + iocore_detachinp(0x59E1 + cirrusvga_melcowab_ofs); + iocore_detachinp(0x5BE1 + cirrusvga_melcowab_ofs); + + iocore_detachinp(0x42E1 + cirrusvga_melcowab_ofs); + iocore_detachout(0x42E1 + cirrusvga_melcowab_ofs); + } +} + + +void pc98_cirrus_vga_init(void) +{ +#if defined(NP2_WIN) + HDC hdc; + UINT i; + WORD* PalIndexes; + //CirrusVGAState *s; + //HBITMAP hbmp; + //BOOL b; + + ga_bmpInfo = (BITMAPINFO*)calloc(1, sizeof(BITMAPINFO)+sizeof(WORD)*256); + PalIndexes = (WORD*)((char*)ga_bmpInfo + sizeof(BITMAPINFOHEADER)); + for (i = 0; i < 256; ++i) PalIndexes[i] = i; + + ga_bmpInfo_cursor = (BITMAPINFO*)calloc(1, sizeof(BITMAPINFO)); + +#if defined(SUPPORT_IA32_HAXM) + vramptr = (uint8_t*)_aligned_malloc(CIRRUS_VRAM_SIZE*2, 4096); // 2倍取っておく + vramptr_cmp = (uint8_t*)_aligned_malloc(CIRRUS_VRAM_SIZE * 2, 4096); // 2倍取っておく +#else + vramptr = (uint8_t*)malloc(CIRRUS_VRAM_SIZE*2); // 2倍取っておく +#endif + + ga_bmpInfo_cursor->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + ga_bmpInfo_cursor->bmiHeader.biPlanes = 1; + ga_bmpInfo_cursor->bmiHeader.biBitCount = 32; + ga_bmpInfo_cursor->bmiHeader.biCompression = BI_RGB; + ga_bmpInfo_cursor->bmiHeader.biWidth = 64; + ga_bmpInfo_cursor->bmiHeader.biHeight = 64; + ga_hbmp_cursor = CreateDIBSection(NULL, ga_bmpInfo_cursor, DIB_RGB_COLORS, (void **)(&cursorptr), NULL, 0); + hdc = GetDC(NULL); + ga_hdc_cursor = CreateCompatibleDC(hdc); + ReleaseDC(NULL, hdc); + SelectObject(ga_hdc_cursor, ga_hbmp_cursor); + + ds.surface = &np2vga_ds_surface; + ds.listeners = &np2vga_ds_listeners; + ds.mouse_set = np2vga_ds_mouse_set; + ds.cursor_define = np2vga_ds_cursor_define; + ds.next = NULL; + + ga_hFakeCursor = LoadCursor(NULL, IDC_ARROW); + +#else + vramptr = (uint8_t*)malloc(CIRRUS_VRAM_SIZE*2); // 2倍取っておく + + ds.surface = &np2vga_ds_surface; + ds.listeners = &np2vga_ds_listeners; + ds.mouse_set = np2vga_ds_mouse_set; + ds.cursor_define = np2vga_ds_cursor_define; + ds.next = NULL; +#endif + + if(cirrusvga_opaque){ + free(cirrusvga_opaque); + cirrusvga_opaque = cirrusvga = NULL; + } + + cirrusvga_opaque = cirrusvga = (CirrusVGAState*)calloc(1, sizeof(CirrusVGAState)); +} +void pc98_cirrus_vga_reset(const NP2CFG *pConfig) +{ + CirrusVGAState *s; + + np2clvga.enabled = np2cfg.usegd5430; + if(!np2clvga.enabled){ + TRACEOUT(("CL-GD54xx: Window Accelerator Disabled")); + return; + } + +#if defined(SUPPORT_IA32_HAXM) + if(!np2haxcore.allocwabmem){ + i386hax_vm_allocmemoryex(vramptr, CIRRUS_VRAM_SIZE*2); + np2haxcore.allocwabmem = 1; + } + mmio_mode = MMIO_MODE_MMIO; // 0==MMIO, 1==VRAM + mmio_mode_region1 = 0; // 0==MMIO, 1==VRAM + mmio_mode_region2 = 0; // 0==MMIO, 1==VRAM + lastlinmmio = 0; +#endif + +#if defined(SUPPORT_VGA_MODEX) + np2clvga.modex = 0; +#endif + np2clvga.defgd54xxtype = np2cfg.gd5430type; + np2clvga.gd54xxtype = np2cfg.gd5430type; + //np2clvga.defgd54xxtype = CIRRUS_98ID_PCI; + //np2clvga.gd54xxtype = CIRRUS_98ID_PCI; + + s = cirrusvga; + //memset(s, 0, sizeof(CirrusVGAState)); + if(np2clvga.gd54xxtype <= 0x57){ + pc98_cirrus_reset(s, CIRRUS_ID_CLGD5428, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ + pc98_cirrus_reset(s, CIRRUS_ID_CLGD5428, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + pc98_cirrus_reset(s, CIRRUS_ID_CLGD5446, 0); + }else if(np2clvga.gd54xxtype <= 0xff){ + pc98_cirrus_reset(s, CIRRUS_ID_CLGD5434, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ + pc98_cirrus_reset(s, CIRRUS_ID_CLGD5426, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ + pc98_cirrus_reset(s, CIRRUS_ID_CLGD5434, 0); + }else if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + pc98_cirrus_reset(s, CIRRUS_ID_CLGD5434, 0); + }else{ + pc98_cirrus_reset(s, CIRRUS_ID_CLGD5430, 0); + } + + cirrusvga_updated = 1; +} +void pc98_cirrus_vga_bind(void) +{ + CirrusVGAState *s; + if(!np2clvga.enabled){ + TRACEOUT(("CL-GD54xx: Window Accelerator Disabled")); + return; + } + if (np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE10_WSN2 || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE10_WSN4 || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI) { + cirrusvga_melcowab_ofs = 0x2; // WSNだけ2で固定 + } + else { + cirrusvga_melcowab_ofs = np2cfg.gd5430melofs; // WSN以外は自由選択可 + } + + s = cirrusvga; + //memset(s, 0, sizeof(CirrusVGAState)); + if(np2clvga.gd54xxtype <= 0x57){ + pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5428, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ + pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5428, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5446, 0); + }else if(np2clvga.gd54xxtype <= 0xff){ + pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ + pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5426, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ + pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5434, 0); + }else if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5434, 0); + }else{ + pc98_cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0); + } + s->ds = graphic_console_init(s->update, s->invalidate, s->screen_dump, s->text_update, s); + + np2wabwnd.drawframe = cirrusvga_drawGraphic; + +#if defined(NP2_WIN) + ga_bmpInfo->bmiHeader.biWidth = 0; + ga_bmpInfo->bmiHeader.biHeight = 0; +#endif + + TRACEOUT(("CL-GD54xx: Window Accelerator Enabled")); +} +void pc98_cirrus_vga_unbind(void) +{ + CirrusVGAState *s; + + s = cirrusvga; + if(np2clvga.gd54xxtype <= 0x57){ + pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5428, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_96){ + pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5428, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_PCI){ + pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5446, 0); + }else if(np2clvga.gd54xxtype <= 0xff){ + pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5430, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WAB){ + pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5426, 0); + }else if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F){ + pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5434, 0); + }else if((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC){ + pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5434, 0); + }else{ + pc98_cirrus_deinit_common(s, CIRRUS_ID_CLGD5430, 0); + } +} + +void pc98_cirrus_vga_shutdown(void) +{ + np2wabwnd.drawframe = NULL; +#if defined(NP2_WIN) + free(ga_bmpInfo_cursor); + free(ga_bmpInfo); +#endif +#if defined(SUPPORT_IA32_HAXM) +#if defined(NP2_WIN) + _aligned_free(vramptr); + _aligned_free(vramptr_cmp); +#else + free(vramptr); +#endif +#else + free(vramptr); +#endif +#if defined(NP2_WIN) + DeleteDC(ga_hdc_cursor); + DeleteObject(ga_hbmp_cursor); +#endif + if(cirrusvga_opaque){ + free(cirrusvga_opaque); + cirrusvga_opaque = cirrusvga = NULL; + } + //free(cursorptr); +} + +void pc98_cirrus_vga_resetresolution(void) +{ + if(!np2clvga.enabled) return; + + cirrusvga->cr[0x01] = 0; + cirrusvga->cr[0x12] = 0; + cirrusvga->cr[0x07] &= ~0x42; + // ついでにVRAMもクリア +// if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC || np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F) { + if (np2clvga.gd54xxtype == CIRRUS_98ID_WSN || np2clvga.gd54xxtype == CIRRUS_98ID_WSN_A2F) { + memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); + cirrusvga_wab_59e1 = 0x06; // この値じゃないとWSN Win95ドライバがNGを返す + cirrusvga_wab_51e1 = 0xC2; // WSN CHECK IO RETURN VALUE + cirrusvga_wab_5be1 = 0xf7; // bit3:0=4M,1=2M ?????? + cirrusvga_wab_40e1 = 0x7b; + cirrusvga_wab_42e1 = 0x00; + cirrusvga_wab_46e8 = 0x18; // 最初からON + }else if ((np2clvga.gd54xxtype & CIRRUS_98ID_GA98NBMASK) == CIRRUS_98ID_GA98NBIC) { + memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); + cirrusvga_wab_59e1 = 0x06; // d.c. + cirrusvga_wab_51e1 = 0xC2; // d.c. + cirrusvga_wab_5be1 = 0xf7; // d.c. + cirrusvga_wab_40e1 = 0xC2; // bit1=0:DRAM REFRESH MODE?? とりあえず初期値はC2hじゃないとWin95ドライバはボードを認識しない + cirrusvga_wab_42e1 = 0x18; // 存在しない + cirrusvga_wab_46e8 = 0x10; + }else{ + memset(cirrusvga->vram_ptr, 0x00, cirrusvga->real_vram_size); + cirrusvga_wab_46e8 = 0x18; + } +#if defined(SUPPORT_PCI) + // XXX: Win2000で動かすのに必要。理由は謎 + if(pcidev.enable && (np2clvga.gd54xxtype == CIRRUS_98ID_PCI || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WS_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_W4_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_WA_PCI || + np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G1_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G2_PCI || np2clvga.gd54xxtype == CIRRUS_98ID_AUTO_XE_G4_PCI)){ + cirrusvga->msr = 0x03; + cirrusvga->sr[0x08] = 0xFE; + } +#endif + cirrusvga_updated = 1; +} + +// MELCO WAB系ポートならTRUE +int pc98_cirrus_isWABport(UINT port){ + if((port & 0xF0FF) == (0x40E0 + cirrusvga_melcowab_ofs)) return 1; + if (port == 0x58E0 + cirrusvga_melcowab_ofs) return 1; + if (port == 0x59E0 + cirrusvga_melcowab_ofs) return 1; + ////if (port == 0x3AE0 + cirrusvga_melcowab_ofs) return 1; + if (port == 0x54E0 + cirrusvga_melcowab_ofs) return 1; + if (port == 0x55E0 + cirrusvga_melcowab_ofs) return 1; + if (port == 0x5AE0 + cirrusvga_melcowab_ofs) return 1; + return 0; +} + +// MELCO WAB / I-O DATA GA-98NB 自動選択 レジスタ設定 +void pc98_cirrus_setWABreg(){ + CirrusVGAState *s; + + s = cirrusvga; + switch(np2clvga.gd54xxtype){ + case CIRRUS_98ID_WAB: + s->device_id = CIRRUS_ID_CLGD5426; + s->bustype = CIRRUS_BUSTYPE_ISA; + s->cr[0x27] = s->device_id; + s->sr[0x0F] = CIRRUS_MEMSIZE_1M; + s->sr[0x15] = 0x02; + break; + case CIRRUS_98ID_WSN_A2F: + s->device_id = CIRRUS_ID_CLGD5434; + s->bustype = CIRRUS_BUSTYPE_ISA; + s->cr[0x27] = s->device_id; + //s->sr[0x1F] = 0x2d; // MemClock + //s->gr[0x18] = 0x0f; // fastest memory configuration + s->sr[0x0f] = CIRRUS_MEMSIZE_2M; + //s->sr[0x17] = 0x20; + s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ + //s->sr[0x0F] = 0x20; + break; + case CIRRUS_98ID_WSN: // WSN-A4F + s->device_id = CIRRUS_ID_CLGD5434; + s->bustype = CIRRUS_BUSTYPE_ISA; + s->cr[0x27] = s->device_id; + //s->sr[0x1F] = 0x2d; // MemClock + //s->gr[0x18] = 0x0f; // fastest memory configuration + s->sr[0x0f] = CIRRUS_MEMSIZE_2M | CIRRUS_MEMFLAGS_BANKSWITCH; + //s->sr[0x17] = 0x20; + s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */ + //s->sr[0x0F] = 0x20; + break; + + case CIRRUS_98ID_GA98NBIC: + s->device_id = CIRRUS_ID_CLGD5434; + s->bustype = CIRRUS_BUSTYPE_ISA; + s->cr[0x27] = s->device_id; + s->sr[0x0f] = CIRRUS_MEMSIZE_1M; + s->sr[0x15] = 0x02; + break; + case CIRRUS_98ID_GA98NBII: + s->device_id = CIRRUS_ID_CLGD5434; + s->bustype = CIRRUS_BUSTYPE_ISA; + s->cr[0x27] = s->device_id; + s->sr[0x0f] = CIRRUS_MEMSIZE_2M; + s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ + break; + case CIRRUS_98ID_GA98NBIV: + s->device_id = CIRRUS_ID_CLGD5434; + s->bustype = CIRRUS_BUSTYPE_ISA; + s->cr[0x27] = s->device_id; + s->sr[0x0f] = CIRRUS_MEMSIZE_2M | CIRRUS_MEMFLAGS_BANKSWITCH; + s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */ + break; + } +} + +#endif diff --git a/wab/cirrus_vga.h b/wab/cirrus_vga.h old mode 100755 new mode 100644 index 306df9f1..cfcbe81d --- a/wab/cirrus_vga.h +++ b/wab/cirrus_vga.h @@ -1,216 +1,216 @@ -/* - * QEMU Cirrus CLGD 54xx VGA Emulator. - * - * Copyright (c) 2004 Fabrice Bellard - * Copyright (c) 2004 Makoto Suzuki (suzu) - * - * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/* - * Reference: Finn Thogersons' VGADOC4b - * available at http://home.worldonline.dk/~finth/ - */ - -#pragma once -/* -#define cpu_to_le16wu(p, v) STOREINTELWORD(p, v) // XXX: -#define cpu_to_le32wu(p, v) STOREINTELDWORD(p, v) // XXX: - -#define le16_to_cpu(a) LOADINTELWORD(a) -#define le32_to_cpu(a) LOADINTELDWORD(a) -#define cpu_to_le16w(a,b) STOREINTELWORD(a,b) -#define cpu_to_le32w(a,b) STOREINTELDWORD(a,b) -*/ - -#define cpu_to_le16wu(p, v) STOREINTELWORD(p, v) // XXX: -#define cpu_to_le32wu(p, v) STOREINTELDWORD(p, v) // XXX: - -#define le16_to_cpu(a) ((UINT16)(a)) -#define le32_to_cpu(a) ((UINT32)(a)) -#define cpu_to_le16w(a,b) STOREINTELWORD(a,b) -#define cpu_to_le32w(a,b) STOREINTELDWORD(a,b) - -#define TARGET_PAGE_BITS 12 // i386 -#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS) -#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1) -#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK) - -#define xglue(x, y) x ## y -#define glue(x, y) xglue(x, y) -#define stringify(s) tostring(s) -#define tostring(s) #s - -#define IO_MEM_SHIFT 3 -#define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT)) - -#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */ -#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ -#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT) -#define IO_MEM_NOTDIRTY (3 << IO_MEM_SHIFT) - -typedef unsigned long console_ch_t; - -typedef void (*vga_hw_update_ptr)(void *); -typedef void (*vga_hw_invalidate_ptr)(void *); -typedef void (*vga_hw_screen_dump_ptr)(void *, const char *); -typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *); - -typedef struct PixelFormat { - uint8_t bits_per_pixel; - uint8_t bytes_per_pixel; - uint8_t depth; /* color depth in bits */ - uint32_t_ rmask, gmask, bmask, amask; - uint8_t rshift, gshift, bshift, ashift; - uint8_t rmax, gmax, bmax, amax; - uint8_t rbits, gbits, bbits, abits; -} PixelFormat; - -typedef struct DisplaySurface { - uint8_t flags; - int width; - int height; - int linesize; /* bytes per line */ - uint8_t *data; - - struct PixelFormat pf; -} DisplaySurface; - -typedef struct DisplayChangeListener { - int idle; - UINT64 gui_timer_interval; - - void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h); - void (*dpy_resize)(struct DisplayState *s); - void (*dpy_setdata)(struct DisplayState *s); - void (*dpy_refresh)(struct DisplayState *s); - void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, - int dst_x, int dst_y, int w, int h); - void (*dpy_fill)(struct DisplayState *s, int x, int y, - int w, int h, uint32_t_ c); - void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); - - struct DisplayChangeListener *next; -} DisplayChangeListener; - -struct DisplayState { - struct DisplaySurface *surface; - void *opaque; - //struct QEMUTimer *gui_timer; - - struct DisplayChangeListener* listeners; - - void (*mouse_set)(int x, int y, int on); - void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y, - uint8_t *image, uint8_t *mask); - - struct DisplayState *next; -}; -typedef struct DisplayState DisplayState; - -DisplayState *graphic_console_init(vga_hw_update_ptr update, - vga_hw_invalidate_ptr invalidate, - vga_hw_screen_dump_ptr screen_dump, - vga_hw_text_update_ptr text_update, - void *opaque); - -typedef void QEMUResetHandler(void *opaque); - -typedef void (IOPortWriteFunc)(void *opaque, uint32_t_ address, uint32_t_ data); -typedef uint32_t_ (IOPortReadFunc)(void *opaque, uint32_t_ address); - -struct QEMUFile { - int dummy; -}; -typedef struct QEMUFile QEMUFile; - - - -/// つくらんといかんね -target_phys_addr_t isa_mem_base = 0; - -static void cpu_physical_memory_set_dirty(ram_addr_t addr) -{ - //phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff; // XXX: -} - -void vga_hw_update(void){} - -void qemu_console_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h){} -/*{ - if (is_graphic_console()) { - dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h); - } -}*/ -void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr){} - -int register_ioport_write(int start, int length, int size, IOPortWriteFunc *func, void *opaque){return 0;} -int register_ioport_read(int start, int length, int size, IOPortReadFunc *func, void *opaque){return 0;} - -//int cpu_register_io_memory(int io_index, CPUReadMemoryFunc **mem_read, CPUWriteMemoryFunc **mem_write, void *opaque){return 0;} -int cpu_register_io_memory(int io_index, - CPUReadMemoryFunc **mem_read, - CPUWriteMemoryFunc **mem_write, - void *opaque) -{ - //int i, subwidth = 0; - - //if (io_index <= 0) { - // io_index = 0; - //} else { - // if (io_index >= IO_MEM_NB_ENTRIES) - // return -1; - //} - - //for(i = 0;i < 3; i++) { - // if (!mem_read[i] || !mem_write[i]) - // subwidth = IO_MEM_SUBWIDTH; - // io_mem_read[io_index][i] = mem_read[i]; - // io_mem_write[io_index][i] = mem_write[i]; - //} - //io_mem_opaque[io_index] = opaque; - //return (io_index << IO_MEM_SHIFT) | subwidth; - return 0; -} - -void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size){} - -CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index){return NULL;} -CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index){return NULL;} - -void qemu_register_reset(QEMUResetHandler *func, void *opaque){} - -void qemu_free(void *ptr) -{ - free(ptr); -} - -void *qemu_malloc(size_t size) -{ - return malloc(size); -} - -void *qemu_mallocz(size_t size) -{ - void *ptr; - ptr = qemu_malloc(size); - if (!ptr) - return NULL; - memset(ptr, 0, size); - return ptr; -} +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * Copyright (c) 2004 Makoto Suzuki (suzu) + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* + * Reference: Finn Thogersons' VGADOC4b + * available at http://home.worldonline.dk/~finth/ + */ + +#pragma once +/* +#define cpu_to_le16wu(p, v) STOREINTELWORD(p, v) // XXX: +#define cpu_to_le32wu(p, v) STOREINTELDWORD(p, v) // XXX: + +#define le16_to_cpu(a) LOADINTELWORD(a) +#define le32_to_cpu(a) LOADINTELDWORD(a) +#define cpu_to_le16w(a,b) STOREINTELWORD(a,b) +#define cpu_to_le32w(a,b) STOREINTELDWORD(a,b) +*/ + +#define cpu_to_le16wu(p, v) STOREINTELWORD(p, v) // XXX: +#define cpu_to_le32wu(p, v) STOREINTELDWORD(p, v) // XXX: + +#define le16_to_cpu(a) ((UINT16)(a)) +#define le32_to_cpu(a) ((UINT32)(a)) +#define cpu_to_le16w(a,b) STOREINTELWORD(a,b) +#define cpu_to_le32w(a,b) STOREINTELDWORD(a,b) + +#define TARGET_PAGE_BITS 12 // i386 +#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS) +#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1) +#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK) + +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) +#define stringify(s) tostring(s) +#define tostring(s) #s + +#define IO_MEM_SHIFT 3 +#define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT)) + +#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */ +#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ +#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT) +#define IO_MEM_NOTDIRTY (3 << IO_MEM_SHIFT) + +typedef unsigned long console_ch_t; + +typedef void (*vga_hw_update_ptr)(void *); +typedef void (*vga_hw_invalidate_ptr)(void *); +typedef void (*vga_hw_screen_dump_ptr)(void *, const char *); +typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *); + +typedef struct PixelFormat { + uint8_t bits_per_pixel; + uint8_t bytes_per_pixel; + uint8_t depth; /* color depth in bits */ + uint32_t_ rmask, gmask, bmask, amask; + uint8_t rshift, gshift, bshift, ashift; + uint8_t rmax, gmax, bmax, amax; + uint8_t rbits, gbits, bbits, abits; +} PixelFormat; + +typedef struct DisplaySurface { + uint8_t flags; + int width; + int height; + int linesize; /* bytes per line */ + uint8_t *data; + + struct PixelFormat pf; +} DisplaySurface; + +typedef struct DisplayChangeListener { + int idle; + UINT64 gui_timer_interval; + + void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h); + void (*dpy_resize)(struct DisplayState *s); + void (*dpy_setdata)(struct DisplayState *s); + void (*dpy_refresh)(struct DisplayState *s); + void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, + int dst_x, int dst_y, int w, int h); + void (*dpy_fill)(struct DisplayState *s, int x, int y, + int w, int h, uint32_t_ c); + void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); + + struct DisplayChangeListener *next; +} DisplayChangeListener; + +struct DisplayState { + struct DisplaySurface *surface; + void *opaque; + //struct QEMUTimer *gui_timer; + + struct DisplayChangeListener* listeners; + + void (*mouse_set)(int x, int y, int on); + void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y, + uint8_t *image, uint8_t *mask); + + struct DisplayState *next; +}; +typedef struct DisplayState DisplayState; + +DisplayState *graphic_console_init(vga_hw_update_ptr update, + vga_hw_invalidate_ptr invalidate, + vga_hw_screen_dump_ptr screen_dump, + vga_hw_text_update_ptr text_update, + void *opaque); + +typedef void QEMUResetHandler(void *opaque); + +typedef void (IOPortWriteFunc)(void *opaque, uint32_t_ address, uint32_t_ data); +typedef uint32_t_ (IOPortReadFunc)(void *opaque, uint32_t_ address); + +struct QEMUFile { + int dummy; +}; +typedef struct QEMUFile QEMUFile; + + + +/// つくらんといかんね +target_phys_addr_t isa_mem_base = 0; + +static void cpu_physical_memory_set_dirty(ram_addr_t addr) +{ + //phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff; // XXX: +} + +void vga_hw_update(void){} + +void qemu_console_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h){} +/*{ + if (is_graphic_console()) { + dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h); + } +}*/ +void cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr){} + +int register_ioport_write(int start, int length, int size, IOPortWriteFunc *func, void *opaque){return 0;} +int register_ioport_read(int start, int length, int size, IOPortReadFunc *func, void *opaque){return 0;} + +//int cpu_register_io_memory(int io_index, CPUReadMemoryFunc **mem_read, CPUWriteMemoryFunc **mem_write, void *opaque){return 0;} +int cpu_register_io_memory(int io_index, + CPUReadMemoryFunc **mem_read, + CPUWriteMemoryFunc **mem_write, + void *opaque) +{ + //int i, subwidth = 0; + + //if (io_index <= 0) { + // io_index = 0; + //} else { + // if (io_index >= IO_MEM_NB_ENTRIES) + // return -1; + //} + + //for(i = 0;i < 3; i++) { + // if (!mem_read[i] || !mem_write[i]) + // subwidth = IO_MEM_SUBWIDTH; + // io_mem_read[io_index][i] = mem_read[i]; + // io_mem_write[io_index][i] = mem_write[i]; + //} + //io_mem_opaque[io_index] = opaque; + //return (io_index << IO_MEM_SHIFT) | subwidth; + return 0; +} + +void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size){} + +CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index){return NULL;} +CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index){return NULL;} + +void qemu_register_reset(QEMUResetHandler *func, void *opaque){} + +void qemu_free(void *ptr) +{ + free(ptr); +} + +void *qemu_malloc(size_t size) +{ + return malloc(size); +} + +void *qemu_mallocz(size_t size) +{ + void *ptr; + ptr = qemu_malloc(size); + if (!ptr) + return NULL; + memset(ptr, 0, size); + return ptr; +} diff --git a/wab/cirrus_vga_extern.h b/wab/cirrus_vga_extern.h old mode 100755 new mode 100644 index 468085c3..dfe1bee4 --- a/wab/cirrus_vga_extern.h +++ b/wab/cirrus_vga_extern.h @@ -1,239 +1,239 @@ -/* - * QEMU Cirrus CLGD 54xx VGA Emulator. - * - * Copyright (c) 2004 Fabrice Bellard - * Copyright (c) 2004 Makoto Suzuki (suzu) - * - * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/* - * Reference: Finn Thogersons' VGADOC4b - * available at http://home.worldonline.dk/~finth/ - */ - -#pragma once - -#include - -#define CIRRUS_VRAM_SIZE_1MB (1024 * 1024) -#define CIRRUS_VRAM_SIZE_2MB (2048 * 1024) -#define CIRRUS_VRAM_SIZE_4MB (4096 * 1024) -#define CIRRUS_VRAM_SIZE CIRRUS_VRAM_SIZE_4MB -#define CIRRUS_VRAM_SIZE_WAB CIRRUS_VRAM_SIZE_1MB - -#define CIRRUS_98ID_96 0x60 -#define CIRRUS_98ID_Be 0x50 -#define CIRRUS_98ID_Xe 0x58 -#define CIRRUS_98ID_Cb 0x59 -#define CIRRUS_98ID_Cf 0x5A -#define CIRRUS_98ID_Xe10 0x5B -#define CIRRUS_98ID_Cb2 0x5C -#define CIRRUS_98ID_Cx2 0x5D -#define CIRRUS_98ID_PCI 0xA0 -#define CIRRUS_98ID_WAB 0x100 -#define CIRRUS_98ID_WSN_A2F 0x101 -#define CIRRUS_98ID_WSN 0x102 -#define CIRRUS_98ID_WABMASK 0xfffc -#define CIRRUS_98ID_GA98NBIC 0x200 -#define CIRRUS_98ID_GA98NBII 0x201 -#define CIRRUS_98ID_GA98NBIV 0x202 -#define CIRRUS_98ID_GA98NBMASK 0xfffc -#define CIRRUS_98ID_AUTOMSK 0xFFF0 -#define CIRRUS_98ID_AUTO_XE_G1_PCI 0xFFF7 -#define CIRRUS_98ID_AUTO_XE_G2_PCI 0xFFF8 -#define CIRRUS_98ID_AUTO_XE_G4_PCI 0xFFF9 -#define CIRRUS_98ID_AUTO_XE_WA_PCI 0xFFFA -#define CIRRUS_98ID_AUTO_XE_W4_PCI 0xFFFB -#define CIRRUS_98ID_AUTO_XE_WS_PCI 0xFFFC -#define CIRRUS_98ID_AUTO_XE10_WABS 0xFFFD -#define CIRRUS_98ID_AUTO_XE10_WSN2 0xFFFE -#define CIRRUS_98ID_AUTO_XE10_WSN4 0xFFFF - -#define VRAMWINDOW_SIZE 0x200000UL // VRAM マッピングサイズ -#define EXT_WINDOW_SIZE 0x200000UL // 謎 -#define EXT_WINDOW_SHFT 0x000000UL // 謎 -#define BBLTWINDOW_ADSH 0x200000UL // VRAM BITBLT -#define BBLTWINDOW_SIZE 0x000000UL // VRAM BITBLT マッピングサイズ -#define MMIOWINDOW_ADDR 0xF80000UL // MMIO マッピングアドレス(場所不明) -#define MMIOWINDOW_SIZE 0x000000UL // MMIO マッピングサイズ(サイズ不明) -#define VRA2WINDOW_ADDR 0x0F2000UL // VRAMウィンドウ マッピングアドレス(場所不明) -#define VRA2WINDOW_SIZE 0x000000UL // VRAMウィンドウ マッピングサイズ(サイズ不明) -#define VRA2WINDOW_SIZEX 0x8000UL // VRAMウィンドウ マッピングサイズ(サイズ不明) -#define VRA3WINDOW_SIZEX 0x10000UL // VRAMウィンドウ F00000 -#define CIRRUS_VRAMWND2_FUNC_rb(a,b) cirrus_linear_memwnd_readb(a,b) -#define CIRRUS_VRAMWND2_FUNC_rw(a,b) cirrus_linear_memwnd_readw(a,b) -#define CIRRUS_VRAMWND2_FUNC_rl(a,b) cirrus_linear_memwnd_readl(a,b) -#define CIRRUS_VRAMWND2_FUNC_wb(a,b,c) cirrus_linear_memwnd_writeb(a,b,c) -#define CIRRUS_VRAMWND2_FUNC_ww(a,b,c) cirrus_linear_memwnd_writew(a,b,c) -#define CIRRUS_VRAMWND2_FUNC_wl(a,b,c) cirrus_linear_memwnd_writel(a,b,c) -#define CIRRUS_VRAMWND3_FUNC_rb(a,b) cirrus_linear_memwnd3_readb(a,b) -#define CIRRUS_VRAMWND3_FUNC_rw(a,b) cirrus_linear_memwnd3_readw(a,b) -#define CIRRUS_VRAMWND3_FUNC_rl(a,b) cirrus_linear_memwnd3_readl(a,b) -#define CIRRUS_VRAMWND3_FUNC_wb(a,b,c) cirrus_linear_memwnd3_writeb(a,b,c) -#define CIRRUS_VRAMWND3_FUNC_ww(a,b,c) cirrus_linear_memwnd3_writew(a,b,c) -#define CIRRUS_VRAMWND3_FUNC_wl(a,b,c) cirrus_linear_memwnd3_writel(a,b,c) - -#define CIRRUS_VRAMWINDOW2MASK (~((np2clvga.gd54xxtype==CIRRUS_98ID_96||np2clvga.gd54xxtype==CIRRUS_98ID_Be ? VRA2WINDOW_SIZEX*2 : VRA2WINDOW_SIZEX)-1)) - -#define TEST_ADDR 0xF0000000 -#define TEST_ADDR_SIZE 0//0x8000 - -#define CIRRUS_MELCOWAB_OFS_DEFAULT 0x0 - -typedef uint16_t uint16_t_; -typedef uint32_t uint32_t_; - -typedef uint32_t_ ram_addr_t; -typedef uint32_t_ target_phys_addr_t; - -typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t_ value); -typedef uint32_t_ CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr); - -extern CPUWriteMemoryFunc *g_cirrus_linear_write[3]; - -extern int pcidev_cirrus_deviceid; - -extern int cirrusvga_wab_46e8; - -void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); - -uint32_t_ cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr); -void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); - -uint32_t_ cirrus_linear_readb(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_linear_readw(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_linear_readl(void *opaque, target_phys_addr_t addr); -void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_linear_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_linear_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); - -uint32_t_ cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr); -void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); - -uint32_t_ cirrus_linear_memwnd_readb(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_linear_memwnd_readw(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_linear_memwnd_readl(void *opaque, target_phys_addr_t addr); -void cirrus_linear_memwnd_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_linear_memwnd_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_linear_memwnd_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); - -uint32_t_ cirrus_linear_memwnd3_readb(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_linear_memwnd3_readw(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_linear_memwnd3_readl(void *opaque, target_phys_addr_t addr); -void cirrus_linear_memwnd3_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_linear_memwnd3_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_linear_memwnd3_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); - -uint32_t_ cirrus_mmio_readb(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_mmio_readw(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_mmio_readl(void *opaque, target_phys_addr_t addr); -void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); - -uint32_t_ cirrus_mmio_readb_wab(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_mmio_readw_wab(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_mmio_readl_wab(void *opaque, target_phys_addr_t addr); -void cirrus_mmio_writeb_wab(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_mmio_writew_wab(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_mmio_writel_wab(void *opaque, target_phys_addr_t addr, uint32_t_ val); - -uint32_t_ cirrus_mmio_readb_iodata(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_mmio_readw_iodata(void *opaque, target_phys_addr_t addr); -uint32_t_ cirrus_mmio_readl_iodata(void *opaque, target_phys_addr_t addr); -void cirrus_mmio_writeb_iodata(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_mmio_writew_iodata(void *opaque, target_phys_addr_t addr, uint32_t_ val); -void cirrus_mmio_writel_iodata(void *opaque, target_phys_addr_t addr, uint32_t_ val); - -extern CPUReadMemoryFunc *cirrus_mmio_read[3]; -extern CPUWriteMemoryFunc *cirrus_mmio_write[3]; - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - UINT8 enabled; - UINT32 VRAMWindowAddr; - UINT32 VRAMWindowAddr2; - UINT32 VRAMWindowAddr3; - //UINT32 VRAMWindowAddr3; - //UINT32 VRAMWindowAddr3size; - UINT32 pciLFB_Addr; - UINT32 pciLFB_Mask; - UINT32 pciMMIO_Addr; - UINT32 pciMMIO_Mask; - REG8 mmioenable; - UINT32 gd54xxtype; - UINT32 defgd54xxtype; - -#if defined(SUPPORT_VGA_MODEX) - UINT8 modex; -#endif -} NP2CLVGA; -//typedef struct { -//} NP2CLVGA2; - - -extern UINT8 cirrusvga_statsavebuf[CIRRUS_VRAM_SIZE + 1024 * 1024]; - -extern void *cirrusvga_opaque; -extern NP2CLVGA np2clvga; -//extern NP2CLVGA2 np2clvga; - -int cirrusvga_drawGraphic(void); - -// 無理矢理外から呼べるように -void pc98_cirrus_vga_init(void); -void pc98_cirrus_vga_reset(const NP2CFG *pConfig); -void pc98_cirrus_vga_bind(void); -void pc98_cirrus_vga_unbind(void); -void pc98_cirrus_vga_shutdown(void); -void pc98_cirrus_vga_resetresolution(void); - -void pc98_cirrus_vga_save(void); -void pc98_cirrus_vga_load(void); - -UINT IOOUTCALL cirrusvga_ioport_read_wrap16(UINT addr); -UINT IOOUTCALL cirrusvga_ioport_read_wrap32(UINT addr); -void IOOUTCALL cirrusvga_ioport_write_wrap16(UINT addr, UINT dat); -void IOOUTCALL cirrusvga_ioport_write_wrap32(UINT addr, UINT dat); - -int pc98_cirrus_isWABport(UINT port); - -void pc98_cirrus_vga_updatePCIaddr(); -void pc98_cirrus_vga_initVRAMWindowAddr(); -void pc98_cirrus_vga_setvramsize(); - -void pc98_cirrus_vga_setVRAMWindowAddr3(UINT32 addr); - -#ifdef __cplusplus -} -#endif - +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * Copyright (c) 2004 Makoto Suzuki (suzu) + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* + * Reference: Finn Thogersons' VGADOC4b + * available at http://home.worldonline.dk/~finth/ + */ + +#pragma once + +#include + +#define CIRRUS_VRAM_SIZE_1MB (1024 * 1024) +#define CIRRUS_VRAM_SIZE_2MB (2048 * 1024) +#define CIRRUS_VRAM_SIZE_4MB (4096 * 1024) +#define CIRRUS_VRAM_SIZE CIRRUS_VRAM_SIZE_4MB +#define CIRRUS_VRAM_SIZE_WAB CIRRUS_VRAM_SIZE_1MB + +#define CIRRUS_98ID_96 0x60 +#define CIRRUS_98ID_Be 0x50 +#define CIRRUS_98ID_Xe 0x58 +#define CIRRUS_98ID_Cb 0x59 +#define CIRRUS_98ID_Cf 0x5A +#define CIRRUS_98ID_Xe10 0x5B +#define CIRRUS_98ID_Cb2 0x5C +#define CIRRUS_98ID_Cx2 0x5D +#define CIRRUS_98ID_PCI 0xA0 +#define CIRRUS_98ID_WAB 0x100 +#define CIRRUS_98ID_WSN_A2F 0x101 +#define CIRRUS_98ID_WSN 0x102 +#define CIRRUS_98ID_WABMASK 0xfffc +#define CIRRUS_98ID_GA98NBIC 0x200 +#define CIRRUS_98ID_GA98NBII 0x201 +#define CIRRUS_98ID_GA98NBIV 0x202 +#define CIRRUS_98ID_GA98NBMASK 0xfffc +#define CIRRUS_98ID_AUTOMSK 0xFFF0 +#define CIRRUS_98ID_AUTO_XE_G1_PCI 0xFFF7 +#define CIRRUS_98ID_AUTO_XE_G2_PCI 0xFFF8 +#define CIRRUS_98ID_AUTO_XE_G4_PCI 0xFFF9 +#define CIRRUS_98ID_AUTO_XE_WA_PCI 0xFFFA +#define CIRRUS_98ID_AUTO_XE_W4_PCI 0xFFFB +#define CIRRUS_98ID_AUTO_XE_WS_PCI 0xFFFC +#define CIRRUS_98ID_AUTO_XE10_WABS 0xFFFD +#define CIRRUS_98ID_AUTO_XE10_WSN2 0xFFFE +#define CIRRUS_98ID_AUTO_XE10_WSN4 0xFFFF + +#define VRAMWINDOW_SIZE 0x200000UL // VRAM マッピングサイズ +#define EXT_WINDOW_SIZE 0x200000UL // 謎 +#define EXT_WINDOW_SHFT 0x000000UL // 謎 +#define BBLTWINDOW_ADSH 0x200000UL // VRAM BITBLT +#define BBLTWINDOW_SIZE 0x000000UL // VRAM BITBLT マッピングサイズ +#define MMIOWINDOW_ADDR 0xF80000UL // MMIO マッピングアドレス(場所不明) +#define MMIOWINDOW_SIZE 0x000000UL // MMIO マッピングサイズ(サイズ不明) +#define VRA2WINDOW_ADDR 0x0F2000UL // VRAMウィンドウ マッピングアドレス(場所不明) +#define VRA2WINDOW_SIZE 0x000000UL // VRAMウィンドウ マッピングサイズ(サイズ不明) +#define VRA2WINDOW_SIZEX 0x8000UL // VRAMウィンドウ マッピングサイズ(サイズ不明) +#define VRA3WINDOW_SIZEX 0x10000UL // VRAMウィンドウ F00000 +#define CIRRUS_VRAMWND2_FUNC_rb(a,b) cirrus_linear_memwnd_readb(a,b) +#define CIRRUS_VRAMWND2_FUNC_rw(a,b) cirrus_linear_memwnd_readw(a,b) +#define CIRRUS_VRAMWND2_FUNC_rl(a,b) cirrus_linear_memwnd_readl(a,b) +#define CIRRUS_VRAMWND2_FUNC_wb(a,b,c) cirrus_linear_memwnd_writeb(a,b,c) +#define CIRRUS_VRAMWND2_FUNC_ww(a,b,c) cirrus_linear_memwnd_writew(a,b,c) +#define CIRRUS_VRAMWND2_FUNC_wl(a,b,c) cirrus_linear_memwnd_writel(a,b,c) +#define CIRRUS_VRAMWND3_FUNC_rb(a,b) cirrus_linear_memwnd3_readb(a,b) +#define CIRRUS_VRAMWND3_FUNC_rw(a,b) cirrus_linear_memwnd3_readw(a,b) +#define CIRRUS_VRAMWND3_FUNC_rl(a,b) cirrus_linear_memwnd3_readl(a,b) +#define CIRRUS_VRAMWND3_FUNC_wb(a,b,c) cirrus_linear_memwnd3_writeb(a,b,c) +#define CIRRUS_VRAMWND3_FUNC_ww(a,b,c) cirrus_linear_memwnd3_writew(a,b,c) +#define CIRRUS_VRAMWND3_FUNC_wl(a,b,c) cirrus_linear_memwnd3_writel(a,b,c) + +#define CIRRUS_VRAMWINDOW2MASK (~((np2clvga.gd54xxtype==CIRRUS_98ID_96||np2clvga.gd54xxtype==CIRRUS_98ID_Be ? VRA2WINDOW_SIZEX*2 : VRA2WINDOW_SIZEX)-1)) + +#define TEST_ADDR 0xF0000000 +#define TEST_ADDR_SIZE 0//0x8000 + +#define CIRRUS_MELCOWAB_OFS_DEFAULT 0x0 + +typedef uint16_t uint16_t_; +typedef uint32_t uint32_t_; + +typedef uint32_t_ ram_addr_t; +typedef uint32_t_ target_phys_addr_t; + +typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t_ value); +typedef uint32_t_ CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr); + +extern CPUWriteMemoryFunc *g_cirrus_linear_write[3]; + +extern int pcidev_cirrus_deviceid; + +extern int cirrusvga_wab_46e8; + +void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); + +uint32_t_ cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr); +void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); + +uint32_t_ cirrus_linear_readb(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_linear_readw(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_linear_readl(void *opaque, target_phys_addr_t addr); +void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_linear_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_linear_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); + +uint32_t_ cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr); +void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); + +uint32_t_ cirrus_linear_memwnd_readb(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_linear_memwnd_readw(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_linear_memwnd_readl(void *opaque, target_phys_addr_t addr); +void cirrus_linear_memwnd_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_linear_memwnd_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_linear_memwnd_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); + +uint32_t_ cirrus_linear_memwnd3_readb(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_linear_memwnd3_readw(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_linear_memwnd3_readl(void *opaque, target_phys_addr_t addr); +void cirrus_linear_memwnd3_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_linear_memwnd3_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_linear_memwnd3_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); + +uint32_t_ cirrus_mmio_readb(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_mmio_readw(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_mmio_readl(void *opaque, target_phys_addr_t addr); +void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t_ val); + +uint32_t_ cirrus_mmio_readb_wab(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_mmio_readw_wab(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_mmio_readl_wab(void *opaque, target_phys_addr_t addr); +void cirrus_mmio_writeb_wab(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_mmio_writew_wab(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_mmio_writel_wab(void *opaque, target_phys_addr_t addr, uint32_t_ val); + +uint32_t_ cirrus_mmio_readb_iodata(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_mmio_readw_iodata(void *opaque, target_phys_addr_t addr); +uint32_t_ cirrus_mmio_readl_iodata(void *opaque, target_phys_addr_t addr); +void cirrus_mmio_writeb_iodata(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_mmio_writew_iodata(void *opaque, target_phys_addr_t addr, uint32_t_ val); +void cirrus_mmio_writel_iodata(void *opaque, target_phys_addr_t addr, uint32_t_ val); + +extern CPUReadMemoryFunc *cirrus_mmio_read[3]; +extern CPUWriteMemoryFunc *cirrus_mmio_write[3]; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + UINT8 enabled; + UINT32 VRAMWindowAddr; + UINT32 VRAMWindowAddr2; + UINT32 VRAMWindowAddr3; + //UINT32 VRAMWindowAddr3; + //UINT32 VRAMWindowAddr3size; + UINT32 pciLFB_Addr; + UINT32 pciLFB_Mask; + UINT32 pciMMIO_Addr; + UINT32 pciMMIO_Mask; + REG8 mmioenable; + UINT32 gd54xxtype; + UINT32 defgd54xxtype; + +#if defined(SUPPORT_VGA_MODEX) + UINT8 modex; +#endif +} NP2CLVGA; +//typedef struct { +//} NP2CLVGA2; + + +extern UINT8 cirrusvga_statsavebuf[CIRRUS_VRAM_SIZE + 1024 * 1024]; + +extern void *cirrusvga_opaque; +extern NP2CLVGA np2clvga; +//extern NP2CLVGA2 np2clvga; + +int cirrusvga_drawGraphic(void); + +// 無理矢理外から呼べるように +void pc98_cirrus_vga_init(void); +void pc98_cirrus_vga_reset(const NP2CFG *pConfig); +void pc98_cirrus_vga_bind(void); +void pc98_cirrus_vga_unbind(void); +void pc98_cirrus_vga_shutdown(void); +void pc98_cirrus_vga_resetresolution(void); + +void pc98_cirrus_vga_save(void); +void pc98_cirrus_vga_load(void); + +UINT IOOUTCALL cirrusvga_ioport_read_wrap16(UINT addr); +UINT IOOUTCALL cirrusvga_ioport_read_wrap32(UINT addr); +void IOOUTCALL cirrusvga_ioport_write_wrap16(UINT addr, UINT dat); +void IOOUTCALL cirrusvga_ioport_write_wrap32(UINT addr, UINT dat); + +int pc98_cirrus_isWABport(UINT port); + +void pc98_cirrus_vga_updatePCIaddr(); +void pc98_cirrus_vga_initVRAMWindowAddr(); +void pc98_cirrus_vga_setvramsize(); + +void pc98_cirrus_vga_setVRAMWindowAddr3(UINT32 addr); + +#ifdef __cplusplus +} +#endif + diff --git a/wab/cirrus_vga_rop.h b/wab/cirrus_vga_rop.h old mode 100755 new mode 100644 index 5fef45ac..df600613 --- a/wab/cirrus_vga_rop.h +++ b/wab/cirrus_vga_rop.h @@ -1,193 +1,193 @@ -/* - * QEMU Cirrus CLGD 54xx VGA Emulator. - * - * Copyright (c) 2004 Fabrice Bellard - * - * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -static void -glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - dstpitch -= bltwidth; - srcpitch -= bltwidth; - // if (dstpitch < 0){ - // /* is 0 valid? srcpitch == 0 could be useful */ - // return; - //} - //else - //if(srcpitch < 0 && s->gr[0x32]!=0 && s->gr[0x32]!=4 && s->gr[0x32]!=6) { - // /* is 0 valid? srcpitch == 0 could be useful */ - // return; - // } - //if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) { - // return; - //} - - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x++) { - ROP_OP(*dst, *src); - dst++; - src++; - } - dst += dstpitch; - src += srcpitch; - } -} - -static void -glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - dstpitch += bltwidth; - srcpitch += bltwidth; - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x++) { - ROP_OP(*dst, *src); - dst--; - src--; - } - dst += dstpitch; - src += srcpitch; - } -} - -static void -glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - uint8_t p; - dstpitch -= bltwidth; - srcpitch -= bltwidth; - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x++) { - p = *dst; - ROP_OP(p, *src); - if (p != s->gr[0x34]) *dst = p; - dst++; - src++; - } - dst += dstpitch; - src += srcpitch; - } -} - -static void -glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - uint8_t p; - dstpitch += bltwidth; - srcpitch += bltwidth; - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x++) { - p = *dst; - ROP_OP(p, *src); - if (p != s->gr[0x34]) *dst = p; - dst--; - src--; - } - dst += dstpitch; - src += srcpitch; - } -} - -static void -glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - uint8_t p1, p2; - dstpitch -= bltwidth; - srcpitch -= bltwidth; - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x+=2) { - p1 = *dst; - p2 = *(dst+1); - ROP_OP(p1, *src); - ROP_OP(p2, *(src+1)); - if ((p1 != s->gr[0x34]) || (p2 != s->gr[0x35])) { - *dst = p1; - *(dst+1) = p2; - } - dst+=2; - src+=2; - } - dst += dstpitch; - src += srcpitch; - } -} - -static void -glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) -{ - int x,y; - uint8_t p1, p2; - dstpitch += bltwidth; - srcpitch += bltwidth; - for (y = 0; y < bltheight; y++) { - for (x = 0; x < bltwidth; x+=2) { - p1 = *(dst-1); - p2 = *dst; - ROP_OP(p1, *(src-1)); - ROP_OP(p2, *src); - if ((p1 != s->gr[0x34]) || (p2 != s->gr[0x35])) { - *(dst-1) = p1; - *dst = p2; - } - dst-=2; - src-=2; - } - dst += dstpitch; - src += srcpitch; - } -} - -#define DEPTH 8 -#include "cirrus_vga_rop2.h" - -#define DEPTH 16 -#include "cirrus_vga_rop2.h" - -#define DEPTH 24 -#include "cirrus_vga_rop2.h" - -#define DEPTH 32 -#include "cirrus_vga_rop2.h" - -#undef ROP_NAME -#undef ROP_OP +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +static void +glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + // if (dstpitch < 0){ + // /* is 0 valid? srcpitch == 0 could be useful */ + // return; + //} + //else + //if(srcpitch < 0 && s->gr[0x32]!=0 && s->gr[0x32]!=4 && s->gr[0x32]!=6) { + // /* is 0 valid? srcpitch == 0 could be useful */ + // return; + // } + //if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) { + // return; + //} + + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + ROP_OP(*dst, *src); + dst++; + src++; + } + dst += dstpitch; + src += srcpitch; + } +} + +static void +glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + ROP_OP(*dst, *src); + dst--; + src--; + } + dst += dstpitch; + src += srcpitch; + } +} + +static void +glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + p = *dst; + ROP_OP(p, *src); + if (p != s->gr[0x34]) *dst = p; + dst++; + src++; + } + dst += dstpitch; + src += srcpitch; + } +} + +static void +glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + p = *dst; + ROP_OP(p, *src); + if (p != s->gr[0x34]) *dst = p; + dst--; + src--; + } + dst += dstpitch; + src += srcpitch; + } +} + +static void +glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p1, p2; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x+=2) { + p1 = *dst; + p2 = *(dst+1); + ROP_OP(p1, *src); + ROP_OP(p2, *(src+1)); + if ((p1 != s->gr[0x34]) || (p2 != s->gr[0x35])) { + *dst = p1; + *(dst+1) = p2; + } + dst+=2; + src+=2; + } + dst += dstpitch; + src += srcpitch; + } +} + +static void +glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + uint8_t p1, p2; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x+=2) { + p1 = *(dst-1); + p2 = *dst; + ROP_OP(p1, *(src-1)); + ROP_OP(p2, *src); + if ((p1 != s->gr[0x34]) || (p2 != s->gr[0x35])) { + *(dst-1) = p1; + *dst = p2; + } + dst-=2; + src-=2; + } + dst += dstpitch; + src += srcpitch; + } +} + +#define DEPTH 8 +#include "cirrus_vga_rop2.h" + +#define DEPTH 16 +#include "cirrus_vga_rop2.h" + +#define DEPTH 24 +#include "cirrus_vga_rop2.h" + +#define DEPTH 32 +#include "cirrus_vga_rop2.h" + +#undef ROP_NAME +#undef ROP_OP diff --git a/wab/cirrus_vga_rop2.h b/wab/cirrus_vga_rop2.h old mode 100755 new mode 100644 index 4be05d2c..571294cb --- a/wab/cirrus_vga_rop2.h +++ b/wab/cirrus_vga_rop2.h @@ -1,298 +1,298 @@ -/* - * QEMU Cirrus CLGD 54xx VGA Emulator. - * - * Copyright (c) 2004 Fabrice Bellard - * - * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if DEPTH == 8 -#define PUTPIXEL() ROP_OP(d[0], col) -#elif DEPTH == 16 -#define PUTPIXEL() ROP_OP(((uint16_t_ *)d)[0], col); -#elif DEPTH == 24 -#define PUTPIXEL() ROP_OP(d[0], col); \ - ROP_OP(d[1], (col >> 8)); \ - ROP_OP(d[2], (col >> 16)) -#elif DEPTH == 32 -#define PUTPIXEL() ROP_OP(((uint32_t_ *)d)[0], col) -#else -#error unsupported DEPTH -#endif - -static void -glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight) -{ - uint8_t *d; - int x, y, pattern_y, pattern_pitch, pattern_x; - unsigned int col; - const uint8_t *src1; -#if DEPTH == 24 - int skipleft = s->gr[0x2f] & 0x1f; -#else - int skipleft = (s->gr[0x2f] & 0x07) * (DEPTH / 8); -#endif - -#if DEPTH == 8 - pattern_pitch = 8; -#elif DEPTH == 16 - pattern_pitch = 16; -#else - pattern_pitch = 32; -#endif - pattern_y = s->cirrus_blt_srcaddr & 7; - for(y = 0; y < bltheight; y++) { - pattern_x = skipleft; - d = dst + skipleft; - src1 = src + pattern_y * pattern_pitch; - for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { -#if DEPTH == 8 - col = src1[pattern_x]; - pattern_x = (pattern_x + 1) & 7; -#elif DEPTH == 16 - col = ((uint16_t_ *)(src1 + pattern_x))[0]; - pattern_x = (pattern_x + 2) & 15; -#elif DEPTH == 24 - { - const uint8_t *src2 = src1 + pattern_x * 3; - col = src2[0] | (src2[1] << 8) | (src2[2] << 16); - pattern_x = (pattern_x + 1) & 7; - } -#else - col = ((uint32_t_ *)(src1 + pattern_x))[0]; - pattern_x = (pattern_x + 4) & 31; -#endif - PUTPIXEL(); - d += (DEPTH / 8); - } - pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; - } -} - -/* NOTE: srcpitch is ignored */ -static void -glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight) -{ - uint8_t *d; - int x, y; - unsigned bits, bits_xor; - unsigned int col; - unsigned bitmask; - unsigned index; -#if DEPTH == 24 - int dstskipleft = s->gr[0x2f] & 0x1f; - int srcskipleft = dstskipleft / 3; -#else - int srcskipleft = s->gr[0x2f] & 0x07; - int dstskipleft = srcskipleft * (DEPTH / 8); -#endif - - if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { - bits_xor = 0xff; - col = s->cirrus_blt_bgcol; - } else { - bits_xor = 0x00; - col = s->cirrus_blt_fgcol; - } - - for(y = 0; y < bltheight; y++) { - bitmask = 0x80 >> srcskipleft; - bits = *src++ ^ bits_xor; - d = dst + dstskipleft; - for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { - if ((bitmask & 0xff) == 0) { - bitmask = 0x80; - bits = *src++ ^ bits_xor; - } - index = (bits & bitmask); - if (index) { - PUTPIXEL(); - } - d += (DEPTH / 8); - bitmask >>= 1; - } - dst += dstpitch; - } -} - -static void -glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight) -{ - uint32_t_ colors[2]; - uint8_t *d; - int x, y; - unsigned bits; - unsigned int col; - unsigned bitmask; - int srcskipleft = s->gr[0x2f] & 0x07; - int dstskipleft = srcskipleft * (DEPTH / 8); - - colors[0] = s->cirrus_blt_bgcol; - colors[1] = s->cirrus_blt_fgcol; - for(y = 0; y < bltheight; y++) { - bitmask = 0x80 >> srcskipleft; - bits = *src++; - d = dst + dstskipleft; - for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { - if ((bitmask & 0xff) == 0) { - bitmask = 0x80; - bits = *src++; - } - col = colors[!!(bits & bitmask)]; - PUTPIXEL(); - d += (DEPTH / 8); - bitmask >>= 1; - } - dst += dstpitch; - } -} - -static void -glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight) -{ - uint8_t *d; - int x, y, bitpos, pattern_y; - unsigned int bits, bits_xor; - unsigned int col; -#if DEPTH == 24 - int dstskipleft = s->gr[0x2f] & 0x1f; - int srcskipleft = dstskipleft / 3; -#else - int srcskipleft = s->gr[0x2f] & 0x07; - int dstskipleft = srcskipleft * (DEPTH / 8); -#endif - - if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { - bits_xor = 0xff; - col = s->cirrus_blt_bgcol; - } else { - bits_xor = 0x00; - col = s->cirrus_blt_fgcol; - } - pattern_y = s->cirrus_blt_srcaddr & 7; - - for(y = 0; y < bltheight; y++) { - bits = src[pattern_y] ^ bits_xor; - bitpos = 7 - srcskipleft; - d = dst + dstskipleft; - for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { - if ((bits >> bitpos) & 1) { - PUTPIXEL(); - } - d += (DEPTH / 8); - bitpos = (bitpos - 1) & 7; - } - pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; - } -} - -static void -glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, - int dstpitch, int srcpitch, - int bltwidth, int bltheight) -{ - uint32_t_ colors[2]; - uint8_t *d; - int x, y, bitpos, pattern_y; - unsigned int bits; - unsigned int col; - int srcskipleft = s->gr[0x2f] & 0x07; - int dstskipleft = srcskipleft * (DEPTH / 8); - - colors[0] = s->cirrus_blt_bgcol; - colors[1] = s->cirrus_blt_fgcol; - pattern_y = s->cirrus_blt_srcaddr & 7; - - if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ - // XXX: WSN/WABだとビットパターンがおかしい・・・?(暫定対症療法) - bits = 0xff; - for(y = 0; y < bltheight; y++) { - bitpos = 7 - srcskipleft; - d = dst + dstskipleft; - for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { - col = colors[(bits >> bitpos) & 1]; - PUTPIXEL(); - d += (DEPTH / 8); - bitpos = (bitpos - 1) & 7; - } - pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; - } - }else{ - for(y = 0; y < bltheight; y++) { - bits = src[pattern_y]; - bitpos = 7 - srcskipleft; - d = dst + dstskipleft; - for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { - col = colors[(bits >> bitpos) & 1]; - PUTPIXEL(); - d += (DEPTH / 8); - bitpos = (bitpos - 1) & 7; - } - pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; - } - } -} - -static void -glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) - (CirrusVGAState *s, - uint8_t *dst, int dst_pitch, - int width, int height) -{ - uint8_t *d, *d1; - uint32_t_ col; - int x, y; - - col = s->cirrus_blt_fgcol; - - d1 = dst; - for(y = 0; y < height; y++) { - d = d1; - for(x = 0; x < width; x += (DEPTH / 8)) { - PUTPIXEL(); - d += (DEPTH / 8); - } - d1 += dst_pitch; - } -} - -#undef DEPTH -#undef PUTPIXEL +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if DEPTH == 8 +#define PUTPIXEL() ROP_OP(d[0], col) +#elif DEPTH == 16 +#define PUTPIXEL() ROP_OP(((uint16_t_ *)d)[0], col); +#elif DEPTH == 24 +#define PUTPIXEL() ROP_OP(d[0], col); \ + ROP_OP(d[1], (col >> 8)); \ + ROP_OP(d[2], (col >> 16)) +#elif DEPTH == 32 +#define PUTPIXEL() ROP_OP(((uint32_t_ *)d)[0], col) +#else +#error unsupported DEPTH +#endif + +static void +glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y, pattern_y, pattern_pitch, pattern_x; + unsigned int col; + const uint8_t *src1; +#if DEPTH == 24 + int skipleft = s->gr[0x2f] & 0x1f; +#else + int skipleft = (s->gr[0x2f] & 0x07) * (DEPTH / 8); +#endif + +#if DEPTH == 8 + pattern_pitch = 8; +#elif DEPTH == 16 + pattern_pitch = 16; +#else + pattern_pitch = 32; +#endif + pattern_y = s->cirrus_blt_srcaddr & 7; + for(y = 0; y < bltheight; y++) { + pattern_x = skipleft; + d = dst + skipleft; + src1 = src + pattern_y * pattern_pitch; + for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { +#if DEPTH == 8 + col = src1[pattern_x]; + pattern_x = (pattern_x + 1) & 7; +#elif DEPTH == 16 + col = ((uint16_t_ *)(src1 + pattern_x))[0]; + pattern_x = (pattern_x + 2) & 15; +#elif DEPTH == 24 + { + const uint8_t *src2 = src1 + pattern_x * 3; + col = src2[0] | (src2[1] << 8) | (src2[2] << 16); + pattern_x = (pattern_x + 1) & 7; + } +#else + col = ((uint32_t_ *)(src1 + pattern_x))[0]; + pattern_x = (pattern_x + 4) & 31; +#endif + PUTPIXEL(); + d += (DEPTH / 8); + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } +} + +/* NOTE: srcpitch is ignored */ +static void +glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y; + unsigned bits, bits_xor; + unsigned int col; + unsigned bitmask; + unsigned index; +#if DEPTH == 24 + int dstskipleft = s->gr[0x2f] & 0x1f; + int srcskipleft = dstskipleft / 3; +#else + int srcskipleft = s->gr[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); +#endif + + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { + bits_xor = 0xff; + col = s->cirrus_blt_bgcol; + } else { + bits_xor = 0x00; + col = s->cirrus_blt_fgcol; + } + + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; + bits = *src++ ^ bits_xor; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; + bits = *src++ ^ bits_xor; + } + index = (bits & bitmask); + if (index) { + PUTPIXEL(); + } + d += (DEPTH / 8); + bitmask >>= 1; + } + dst += dstpitch; + } +} + +static void +glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint32_t_ colors[2]; + uint8_t *d; + int x, y; + unsigned bits; + unsigned int col; + unsigned bitmask; + int srcskipleft = s->gr[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); + + colors[0] = s->cirrus_blt_bgcol; + colors[1] = s->cirrus_blt_fgcol; + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; + bits = *src++; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; + bits = *src++; + } + col = colors[!!(bits & bitmask)]; + PUTPIXEL(); + d += (DEPTH / 8); + bitmask >>= 1; + } + dst += dstpitch; + } +} + +static void +glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y, bitpos, pattern_y; + unsigned int bits, bits_xor; + unsigned int col; +#if DEPTH == 24 + int dstskipleft = s->gr[0x2f] & 0x1f; + int srcskipleft = dstskipleft / 3; +#else + int srcskipleft = s->gr[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); +#endif + + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { + bits_xor = 0xff; + col = s->cirrus_blt_bgcol; + } else { + bits_xor = 0x00; + col = s->cirrus_blt_fgcol; + } + pattern_y = s->cirrus_blt_srcaddr & 7; + + for(y = 0; y < bltheight; y++) { + bits = src[pattern_y] ^ bits_xor; + bitpos = 7 - srcskipleft; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + if ((bits >> bitpos) & 1) { + PUTPIXEL(); + } + d += (DEPTH / 8); + bitpos = (bitpos - 1) & 7; + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } +} + +static void +glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint32_t_ colors[2]; + uint8_t *d; + int x, y, bitpos, pattern_y; + unsigned int bits; + unsigned int col; + int srcskipleft = s->gr[0x2f] & 0x07; + int dstskipleft = srcskipleft * (DEPTH / 8); + + colors[0] = s->cirrus_blt_bgcol; + colors[1] = s->cirrus_blt_fgcol; + pattern_y = s->cirrus_blt_srcaddr & 7; + + if(np2clvga.gd54xxtype == CIRRUS_98ID_WSN){ + // XXX: WSN/WABだとビットパターンがおかしい・・・?(暫定対症療法) + bits = 0xff; + for(y = 0; y < bltheight; y++) { + bitpos = 7 - srcskipleft; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + col = colors[(bits >> bitpos) & 1]; + PUTPIXEL(); + d += (DEPTH / 8); + bitpos = (bitpos - 1) & 7; + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } + }else{ + for(y = 0; y < bltheight; y++) { + bits = src[pattern_y]; + bitpos = 7 - srcskipleft; + d = dst + dstskipleft; + for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { + col = colors[(bits >> bitpos) & 1]; + PUTPIXEL(); + d += (DEPTH / 8); + bitpos = (bitpos - 1) & 7; + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } + } +} + +static void +glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) + (CirrusVGAState *s, + uint8_t *dst, int dst_pitch, + int width, int height) +{ + uint8_t *d, *d1; + uint32_t_ col; + int x, y; + + col = s->cirrus_blt_fgcol; + + d1 = dst; + for(y = 0; y < height; y++) { + d = d1; + for(x = 0; x < width; x += (DEPTH / 8)) { + PUTPIXEL(); + d += (DEPTH / 8); + } + d1 += dst_pitch; + } +} + +#undef DEPTH +#undef PUTPIXEL diff --git a/wab/tgui9680.c b/wab/tgui9680.c index 1ca005b5..86606f59 100644 --- a/wab/tgui9680.c +++ b/wab/tgui9680.c @@ -1,1804 +1,1804 @@ -/** - * @file tgui9680.c - * @brief Implementation of the Trident TGUI9680 from PCem (vid_tgui9440.c) - */ - -#include "compiler.h" - -#if defined(SUPPORT_TRIDENT_TGUI) - -#include "pccore.h" -#include "wab.h" -#include "tgui9680_extern.h" -#include "tgui9680_wrapper.h" -#include "tgui9680.h" -#include "dosio.h" -#include "cpucore.h" -#include "pccore.h" -#include "iocore.h" -#include "soundmng.h" - -#if defined(SUPPORT_IA32_HAXM) -#include "i386hax/haxfunc.h" -#include "i386hax/haxcore.h" -#endif - -/*TGUI9400CXi has extended write modes, controlled by extended GDC registers : - - GDC[0x10] - Control - bit 0 - pixel width (1 = 16 bit, 0 = 8 bit) - bit 1 - mono->colour expansion (1 = enabled, 0 = disabled) - bit 2 - mono->colour expansion transparency (1 = tranparent, 0 = opaque) - bit 3 - extended latch copy - GDC[0x11] - Background colour (low byte) - GDC[0x12] - Background colour (high byte) - GDC[0x14] - Foreground colour (low byte) - GDC[0x15] - Foreground colour (high byte) - GDC[0x17] - Write mask (low byte) - GDC[0x18] - Write mask (high byte) - - Mono->colour expansion will expand written data 8:1 to 8/16 consecutive bytes. - MSB is processed first. On word writes, low byte is processed first. 1 bits write - foreground colour, 0 bits write background colour unless transparency is enabled. - If the relevant bit is clear in the write mask then the data is not written. - - With 16-bit pixel width, each bit still expands to one byte, so the TGUI driver - doubles up monochrome data. - - While there is room in the register map for three byte colours, I don't believe - 24-bit colour is supported. The TGUI9440 blitter has the same limitation. - - I don't think double word writes are supported. - - Extended latch copy uses an internal 16 byte latch. Reads load the latch, writing - writes out 16 bytes. I don't think the access size or host data has any affect, - but the Windows 3.1 driver always reads bytes and write words of 0xffff.*/ - -#define EXT_CTRL_16BIT 0x01 -#define EXT_CTRL_MONO_EXPANSION 0x02 -#define EXT_CTRL_MONO_TRANSPARENT 0x04 -#define EXT_CTRL_LATCH_COPY 0x08 - -#define FIFO_SIZE 65536 -#define FIFO_MASK (FIFO_SIZE - 1) -#define FIFO_ENTRY_SIZE (1 << 31) - -#define FIFO_ENTRIES (tgui->fifo_write_idx - tgui->fifo_read_idx) -#define FIFO_FULL ((tgui->fifo_write_idx - tgui->fifo_read_idx) >= FIFO_SIZE) -#define FIFO_EMPTY (tgui->fifo_read_idx == tgui->fifo_write_idx) - -#define FIFO_TYPE 0xff000000 -#define FIFO_ADDR 0x00ffffff - -enum -{ - TGUI_9400CXI = 0, - TGUI_9440 -}; - -enum -{ - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_BYTE = (0x01 << 24), - FIFO_WRITE_FB_BYTE = (0x04 << 24), - FIFO_WRITE_FB_WORD = (0x05 << 24), - FIFO_WRITE_FB_LONG = (0x06 << 24) -}; - -typedef struct -{ - uint32_t addr_type; - uint32_t val; -} fifo_entry_t; - -typedef struct tgui_t -{ - mem_mapping_t linear_mapping; - mem_mapping_t accel_mapping; - - rom_t bios_rom; - - svga_t svga; - - tkd8001_ramdac_t ramdac; /*TGUI9400CXi*/ - - int type; - - struct - { - uint16_t src_x, src_y; - uint16_t dst_x, dst_y; - uint16_t size_x, size_y; - uint16_t fg_col, bg_col; - uint8_t rop; - uint16_t flags; - uint8_t pattern[0x80]; - int command; - int offset; - uint8_t ger22; - - int x, y; - uint32_t src, dst, src_old, dst_old; - int pat_x, pat_y; - int use_src; - - int pitch, bpp; - - uint16_t tgui_pattern[8][8]; - } accel; - - uint8_t ext_gdc_regs[16]; /*TGUI9400CXi only*/ - uint8_t copy_latch[16]; - - uint8_t tgui_3d8, tgui_3d9; - int oldmode; - uint8_t oldctrl1; - uint8_t oldctrl2,newctrl2; - - uint32_t linear_base, linear_size; - - int ramdac_state; - uint8_t ramdac_ctrl; - - int clock_m, clock_n, clock_k; - - uint32_t vram_size, vram_mask; - - fifo_entry_t fifo[FIFO_SIZE]; - volatile int fifo_read_idx, fifo_write_idx; - - thread_t *fifo_thread; - event_t *wake_fifo_thread; - event_t *fifo_not_full_event; - - int blitter_busy; - uint64_t blitter_time; - uint64_t status_time; - - volatile int write_blitter; -} tgui_t; - -void tgui_recalcmapping(tgui_t *tgui); - -static void fifo_thread(void *param); - -uint8_t tgui_accel_read(uint32_t addr, void *priv); -uint16_t tgui_accel_read_w(uint32_t addr, void *priv); -uint32_t tgui_accel_read_l(uint32_t addr, void *priv); - -void tgui_accel_write(uint32_t addr, uint8_t val, void *priv); -void tgui_accel_write_w(uint32_t addr, uint16_t val, void *priv); -void tgui_accel_write_l(uint32_t addr, uint32_t val, void *priv); - -void tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *priv); -void tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *priv); -void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *priv); - -static uint8_t tgui_ext_linear_read(uint32_t addr, void *p); -static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p); -static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p); -static void tgui_ext_linear_writel(uint32_t addr, uint32_t val, void *p); - -static uint8_t tgui_ext_read(uint32_t addr, void *p); -static void tgui_ext_write(uint32_t addr, uint8_t val, void *p); -static void tgui_ext_writew(uint32_t addr, uint16_t val, void *p); -static void tgui_ext_writel(uint32_t addr, uint32_t val, void *p); - -void tgui_out(uint16_t addr, uint8_t val, void *p) -{ - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - - uint8_t old; - -// pclog("tgui_out : %04X %02X %04X:%04X %i\n", addr, val, CS,pc, svga->bpp); - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; - - switch (addr) - { - case 0x3C5: - switch (svga->seqaddr & 0xf) - { - case 0xB: - tgui->oldmode=1; - break; - case 0xC: - if (svga->seqregs[0xe] & 0x80) - svga->seqregs[0xc] = val; - break; - case 0xd: - if (tgui->oldmode) - tgui->oldctrl2 = val; - else - tgui->newctrl2=val; - break; - case 0xE: - if (tgui->oldmode) - tgui->oldctrl1 = val; - else - { - svga->seqregs[0xe] = val ^ 2; - svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536; - if (!(svga->gdcreg[0xf] & 1)) - svga->read_bank = svga->write_bank; - } - return; - } - break; - - case 0x3C6: - if (tgui->type == TGUI_9400CXI) - { - tkd8001_ramdac_out(addr, val, &tgui->ramdac, svga); - return; - } - if (tgui->ramdac_state == 4) - { - tgui->ramdac_state = 0; - tgui->ramdac_ctrl = val; - switch (tgui->ramdac_ctrl & 0xf0) - { - case 0x10: - svga->bpp = 15; - break; - case 0x30: - svga->bpp = 16; - break; - case 0xd0: - svga->bpp = 24; - break; - default: - svga->bpp = 8; - break; - } - return; - } - case 0x3C7: case 0x3C8: case 0x3C9: - if (tgui->type == TGUI_9400CXI) - { - tkd8001_ramdac_out(addr, val, &tgui->ramdac, svga); - return; - } - tgui->ramdac_state = 0; - break; - - case 0x3CF: - if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32) - { - old = tgui->ext_gdc_regs[svga->gdcaddr & 15]; - tgui->ext_gdc_regs[svga->gdcaddr & 15] = val; - if (svga->gdcaddr == 16) - tgui_recalcmapping(tgui); - return; - } - switch (svga->gdcaddr & 15) - { - case 0x6: - if (svga->gdcreg[6] != val) - { - svga->gdcreg[6] = val; - tgui_recalcmapping(tgui); - } - return; - - case 0xE: - svga->gdcreg[0xe] = val ^ 2; - if ((svga->gdcreg[0xf] & 1) == 1) - svga->read_bank = (svga->gdcreg[0xe] & 0xf) * 65536; - break; - case 0xF: - if (val & 1) svga->read_bank = (svga->gdcreg[0xe] & 0xf) *65536; - else svga->read_bank = (svga->seqregs[0xe] & 0xf) *65536; - svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536; - break; - } - break; - case 0x3D4: - svga->crtcreg = val & 0x7f; - return; - case 0x3D5: - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; -// if (svga->crtcreg != 0xE && svga->crtcreg != 0xF) pclog("CRTC R%02X = %02X\n", svga->crtcreg, val); - if (old != val) - { - if (svga->crtcreg < 0xE || svga->crtcreg > 0x10) - { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - switch (svga->crtcreg) - { - case 0x21: - if (old != val) - { - if (!PCI) - { - tgui->linear_base = ((val & 0xf) | ((val >> 2) & 0x30)) << 20; - tgui->linear_size = (val & 0x10) ? 0x200000 : 0x100000; - tgui->svga.decode_mask = (val & 0x10) ? 0x1fffff : 0xfffff; - } - tgui_recalcmapping(tgui); - } - break; - - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - if (tgui->type >= TGUI_9440) - { - svga->hwcursor.x = (svga->crtc[0x40] | (svga->crtc[0x41] << 8)) & 0x7ff; - svga->hwcursor.y = (svga->crtc[0x42] | (svga->crtc[0x43] << 8)) & 0x7ff; - svga->hwcursor.xoff = svga->crtc[0x46] & 0x3f; - svga->hwcursor.yoff = svga->crtc[0x47] & 0x3f; - svga->hwcursor.addr = (svga->crtc[0x44] << 10) | ((svga->crtc[0x45] & 0x7) << 18) | (svga->hwcursor.yoff * 8); - } - break; - - case 0x50: - if (tgui->type >= TGUI_9440) - { - svga->hwcursor.ena = val & 0x80; - svga->hwcursor.xsize = (val & 1) ? 64 : 32; - svga->hwcursor.ysize = (val & 1) ? 64 : 32; - } - break; - } - return; - case 0x3D8: - tgui->tgui_3d8 = val; - if (svga->gdcreg[0xf] & 4) - { - svga->write_bank = (val & 0x1f) * 65536; -// pclog("SVGAWBANK 3D8 %08X %04X:%04X\n",svgawbank,CS,pc); - if (!(svga->gdcreg[0xf] & 1)) - { - svga->read_bank = (val & 0x1f) * 65536; -// pclog("SVGARBANK 3D8 %08X %04X:%04X\n",svgarbank,CS,pc); - } - } - return; - case 0x3D9: - tgui->tgui_3d9 = val; - if ((svga->gdcreg[0xf] & 5) == 5) - { - svga->read_bank = (val & 0x1F) * 65536; -// pclog("SVGARBANK 3D9 %08X %04X:%04X\n",svgarbank,CS,pc); - } - return; - - case 0x43c8: - tgui->clock_n = val & 0x7f; - tgui->clock_m = (tgui->clock_m & ~1) | (val >> 7); - break; - case 0x43c9: - tgui->clock_m = (tgui->clock_m & ~0x1e) | ((val << 1) & 0x1e); - tgui->clock_k = (val & 0x10) >> 4; - break; - } - svga_out(addr, val, svga); -} - -uint8_t tgui_in(uint16_t addr, void *p) -{ - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - -// if (addr != 0x3da) pclog("tgui_in : %04X %04X:%04X\n", addr, CS,pc); - - if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; - - switch (addr) - { - case 0x3C5: - if ((svga->seqaddr & 0xf) == 0xb) - { -// printf("Read Trident ID %04X:%04X %04X\n",CS,pc,readmemw(ss,SP)); - tgui->oldmode = 0; - switch (tgui->type) - { - case TGUI_9400CXI: - return 0x93; /*TGUI9400CXi*/ - case TGUI_9440: - return 0xe3; /*TGUI9440AGi*/ - } - } - if ((svga->seqaddr & 0xf) == 0xc) - { -// printf("Read Trident Power Up 1 %04X:%04X %04X\n",CS,pc,readmemw(ss,SP)); -// return 0x20; /*2 DRAM banks*/ - } - if ((svga->seqaddr & 0xf) == 0xd) - { - if (tgui->oldmode) - return tgui->oldctrl2; - return tgui->newctrl2; - } - if ((svga->seqaddr & 0xf) == 0xe) - { - if (tgui->oldmode) - return tgui->oldctrl1; - } - break; - case 0x3C6: - if (tgui->type == TGUI_9400CXI) - return tkd8001_ramdac_in(addr, &tgui->ramdac, svga); - if (tgui->ramdac_state == 4) - return tgui->ramdac_ctrl; - tgui->ramdac_state++; - break; - case 0x3C7: case 0x3C8: case 0x3C9: - if (tgui->type == TGUI_9400CXI) - return tkd8001_ramdac_in(addr, &tgui->ramdac, svga); - tgui->ramdac_state = 0; - break; - case 0x3CF: - if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32) - return tgui->ext_gdc_regs[svga->gdcaddr & 15]; - break; - case 0x3D4: - return svga->crtcreg; - case 0x3D5: - return svga->crtc[svga->crtcreg]; - case 0x3d8: - return tgui->tgui_3d8; - case 0x3d9: - return tgui->tgui_3d9; - } - return svga_in(addr, svga); -} - -void tgui_recalctimings(svga_t *svga) -{ - tgui_t *tgui = (tgui_t *)svga->p; - - if (svga->crtc[0x29] & 0x10) - svga->rowoffset += 0x100; - - if (tgui->type >= TGUI_9440 && svga->bpp == 24) - svga->hdisp = (svga->crtc[1] + 1) * 8; - - if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000; - if ((svga->crtc[0x27] & 0x01) == 0x01) svga->ma_latch |= 0x20000; - if ((svga->crtc[0x27] & 0x02) == 0x02) svga->ma_latch |= 0x40000; - - if (tgui->oldctrl2 & 0x10) - svga->rowoffset <<= 1; - if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) - svga->ma_latch <<= 1; - - if (tgui->oldctrl2 & 0x10) /*I'm not convinced this is the right register for this function*/ - svga->lowres=0; - - svga->lowres = !(svga->crtc[0x2a] & 0x40); - - svga->interlace = svga->crtc[0x1e] & 4; - if (svga->interlace && tgui->type < TGUI_9440) - svga->rowoffset >>= 1; - - if (tgui->type >= TGUI_9440) - { - if (svga->miscout & 8) - svga->clock = (cpuclock * (double)(1ull << 32)) / (((tgui->clock_n + 8) * 14318180.0) / ((tgui->clock_m + 2) * (1 << tgui->clock_k))); - - if (svga->gdcreg[0xf] & 0x08) - svga->clock *= 2; - else if (svga->gdcreg[0xf] & 0x40) - svga->clock *= 3; - } - else - { - switch (((svga->miscout >> 2) & 3) | ((tgui->newctrl2 << 2) & 4) | ((tgui->newctrl2 >> 3) & 8)) - { - case 0x02: svga->clock = (cpuclock * (double)(1ull << 32)) / 44900000.0; break; - case 0x03: svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; break; - case 0x04: svga->clock = (cpuclock * (double)(1ull << 32)) / 57272000.0; break; - case 0x05: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break; - case 0x06: svga->clock = (cpuclock * (double)(1ull << 32)) / 50350000.0; break; - case 0x07: svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; break; - case 0x08: svga->clock = (cpuclock * (double)(1ull << 32)) / 88000000.0; break; - case 0x09: svga->clock = (cpuclock * (double)(1ull << 32)) / 98000000.0; break; - case 0x0a: svga->clock = (cpuclock * (double)(1ull << 32)) /118800000.0; break; - case 0x0b: svga->clock = (cpuclock * (double)(1ull << 32)) /108000000.0; break; - case 0x0c: svga->clock = (cpuclock * (double)(1ull << 32)) / 72000000.0; break; - case 0x0d: svga->clock = (cpuclock * (double)(1ull << 32)) / 77000000.0; break; - case 0x0e: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break; - case 0x0f: svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0; break; - } - if (svga->gdcreg[0xf] & 0x08) - { - svga->htotal *= 2; - svga->hdisp *= 2; - svga->hdisp_time *= 2; - } - } - - if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) - { - switch (svga->bpp) - { - case 8: - svga->render = svga_render_8bpp_highres; - break; - case 15: - svga->render = svga_render_15bpp_highres; - if (tgui->type < TGUI_9440) - svga->hdisp /= 2; - break; - case 16: - svga->render = svga_render_16bpp_highres; - if (tgui->type < TGUI_9440) - svga->hdisp /= 2; - break; - case 24: - svga->render = svga_render_24bpp_highres; - if (tgui->type < TGUI_9440) - svga->hdisp = (svga->hdisp * 2) / 3; - break; - } - } -} - -void tgui_recalcmapping(tgui_t *tgui) -{ - svga_t *svga = &tgui->svga; - -// pclog("tgui_recalcmapping : %02X %02X\n", svga->crtc[0x21], svga->gdcreg[6]); - - if (tgui->type == TGUI_9400CXI) - { - if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) - { - mem_mapping_set_handler(&tgui->linear_mapping, - tgui_ext_linear_read, NULL, NULL, - tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); - mem_mapping_set_handler(&svga->mapping, - tgui_ext_read, NULL, NULL, - tgui_ext_write, tgui_ext_writew, tgui_ext_writel); - } - else if (tgui->ext_gdc_regs[0] & EXT_CTRL_MONO_EXPANSION) - { - mem_mapping_set_handler(&tgui->linear_mapping, - svga_read_linear, svga_readw_linear, svga_readl_linear, - tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); - mem_mapping_set_handler(&svga->mapping, - svga_read, svga_readw, svga_readl, - tgui_ext_write, tgui_ext_writew, tgui_ext_writel); - } - else - { - mem_mapping_set_handler(&tgui->linear_mapping, - svga_read_linear, svga_readw_linear, svga_readl_linear, - svga_write_linear, svga_writew_linear, svga_writel_linear); - mem_mapping_set_handler(&svga->mapping, - svga_read, svga_readw, svga_readl, - svga_write, svga_writew, svga_writel); - } - } - - if (svga->crtc[0x21] & 0x20) - { - mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size); -// pclog("Trident linear framebuffer at %08X - size %06X\n", tgui->linear_base, tgui->linear_size); - if (tgui->type >= TGUI_9440) - { - mem_mapping_enable(&tgui->accel_mapping); - mem_mapping_disable(&svga->mapping); - } - else - { - switch (svga->gdcreg[6] & 0xC) - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - } - } - else - { -// pclog("Write mapping %02X\n", val); - mem_mapping_disable(&tgui->linear_mapping); - mem_mapping_disable(&tgui->accel_mapping); - switch (svga->gdcreg[6] & 0xC) - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_enable(&tgui->accel_mapping); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - } -} - -void tgui_hwcursor_draw(svga_t *svga, int displine) -{ - uint32_t dat[2]; - int xx; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - - if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 8; - - dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 24) | (svga->vram[svga->hwcursor_latch.addr + 1] << 16) | (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; - dat[1] = (svga->vram[svga->hwcursor_latch.addr + 4] << 24) | (svga->vram[svga->hwcursor_latch.addr + 5] << 16) | (svga->vram[svga->hwcursor_latch.addr + 6] << 8) | svga->vram[svga->hwcursor_latch.addr + 7]; - for (xx = 0; xx < 32; xx++) - { - if (offset >= svga->hwcursor_latch.x) - { - if (!(dat[0] & 0x80000000)) - ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x80000000) ? 0xffffff : 0; - else if (dat[1] & 0x80000000) - ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff; -// pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga_hwcursor_on, dat[0], dat[1]); - } - - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } - svga->hwcursor_latch.addr += 8; - - if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 8; -} - -uint8_t tgui_pci_read(int func, int addr, void *p) -{ - tgui_t *tgui = (tgui_t *)p; - -// pclog("Trident PCI read %08X\n", addr); - - switch (addr) - { - case 0x00: return 0x23; /*Trident*/ - case 0x01: return 0x10; - - case 0x02: return 0x40; /*TGUI9440 (9682)*/ - case 0x03: return 0x94; - - case 0x04: return 0x03; /*Respond to IO and memory accesses*/ - - case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ - - case 0x08: return 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ - - case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/ - case 0x0b: return 0x03; - - case 0x10: return 0x00; /*Linear frame buffer address*/ - case 0x11: return 0x00; - case 0x12: return tgui->linear_base >> 16; - case 0x13: return tgui->linear_base >> 24; - - case 0x30: return 0x01; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return 0x0C; - case 0x33: return 0x00; - } - return 0; -} - -void tgui_pci_write(int func, int addr, uint8_t val, void *p) -{ - tgui_t *tgui = (tgui_t *)p; - svga_t *svga = &tgui->svga; - -// pclog("Trident PCI write %08X %02X\n", addr, val); - - switch (addr) - { - case 0x12: - tgui->linear_base = (tgui->linear_base & 0xff000000) | ((val & 0xe0) << 16); - tgui->linear_size = 2 << 20; - tgui->svga.decode_mask = 0x1fffff; - svga->crtc[0x21] = (svga->crtc[0x21] & ~0xf) | (val >> 4); - tgui_recalcmapping(tgui); - break; - case 0x13: - tgui->linear_base = (tgui->linear_base & 0xe00000) | (val << 24); - tgui->linear_size = 2 << 20; - tgui->svga.decode_mask = 0x1fffff; - svga->crtc[0x21] = (svga->crtc[0x21] & ~0xc0) | (val >> 6); - tgui_recalcmapping(tgui); - break; - } -} - -static void *tgui_init(char *bios_fn, int type, int mem_size) -{ - tgui_t *tgui = malloc(sizeof(tgui_t)); - memset(tgui, 0, sizeof(tgui_t)); - - if (mem_size) - tgui->vram_size = mem_size; - else - tgui->vram_size = device_get_config_int("memory") << 20; - tgui->vram_mask = tgui->vram_size - 1; - - tgui->type = type; - - rom_init(&tgui->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - svga_init(&tgui->svga, tgui, tgui->vram_size, - tgui_recalctimings, - tgui_in, tgui_out, - tgui_hwcursor_draw, - NULL); - - mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_accel_write_fb_b, tgui_accel_write_fb_w, tgui_accel_write_fb_l, NULL, 0, &tgui->svga); - mem_mapping_add(&tgui->accel_mapping, 0xbc000, 0x4000, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, NULL, 0, tgui); - mem_mapping_disable(&tgui->accel_mapping); - - io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - if (tgui->type >= TGUI_9440) - io_sethandler(0x43c8, 0x0002, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - - if (tgui->type >= TGUI_9440) - pci_add(tgui_pci_read, tgui_pci_write, tgui); - - tgui->wake_fifo_thread = thread_create_event(); - tgui->fifo_not_full_event = thread_create_event(); - tgui->fifo_thread = thread_create(fifo_thread, tgui); - - return tgui; -} - -static void *tgui9400cxi_init() -{ - return tgui_init("9400CXI.vbi", TGUI_9400CXI, 0); -} - -static void *tgui9400cxi_elx_init() -{ - /*Try combined ROM dump first. If not present, use seperated dump*/ - FILE *f = romfopen("elx_pc425x/elx_pc425x.bin", "rb"); - if (f) - { - fclose(f); - return tgui_init("elx_pc425x/elx_pc425x.bin", TGUI_9400CXI, 512 << 10); - } - - return tgui_init("elx_pc425x/elx_pc425x_vbios.bin", TGUI_9400CXI, 512 << 10); -} - -static void *tgui9440_init() -{ - return tgui_init("9440.vbi", TGUI_9440, 0); -} - -static int tgui9400cxi_available() -{ - return rom_present("9400CXI.vbi"); -} - -static int tgui9440_available() -{ - return rom_present("9440.vbi"); -} - -void tgui_close(void *p) -{ - tgui_t *tgui = (tgui_t *)p; - - svga_close(&tgui->svga); - - thread_kill(tgui->fifo_thread); - thread_destroy_event(tgui->wake_fifo_thread); - thread_destroy_event(tgui->fifo_not_full_event); - - free(tgui); -} - -void tgui_speed_changed(void *p) -{ - tgui_t *tgui = (tgui_t *)p; - - svga_recalctimings(&tgui->svga); -} - -void tgui_force_redraw(void *p) -{ - tgui_t *tgui = (tgui_t *)p; - - tgui->svga.fullchange = changeframecount; -} - - -static uint8_t tgui_ext_linear_read(uint32_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; - int c; - - cycles -= video_timing_read_b; - cycles_lost += video_timing_read_b; - - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; - - addr &= ~0xf; - for (c = 0; c < 16; c++) - tgui->copy_latch[c] = svga->vram[addr+c]; - - return svga->vram[addr & svga->vram_mask]; -} - -static uint8_t tgui_ext_read(uint32_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - - addr = (addr & svga->banked_mask) + svga->read_bank; - - return tgui_ext_linear_read(addr, svga); -} - -static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; - int c; - uint8_t fg[2] = {tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5]}; - uint8_t bg[2] = {tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2]}; - uint8_t mask = tgui->ext_gdc_regs[7]; - - cycles -= video_timing_write_b; - cycles_lost += video_timing_write_b; - - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - addr &= ~0x7; - svga->changedvram[addr >> 12] = changeframecount; - - switch (tgui->ext_gdc_regs[0] & 0xf) - { - /*8-bit mono->colour expansion, unmasked*/ - case 2: - for (c = 7; c >= 0; c--) - { - if (mask & (1 << c)) - *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0]; - addr++; - } - break; - - /*16-bit mono->colour expansion, unmasked*/ - case 3: - for (c = 7; c >= 0; c--) - { - if (mask & (1 << c)) - *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1]; - addr++; - } - break; - - /*8-bit mono->colour expansion, masked*/ - case 6: - for (c = 7; c >= 0; c--) - { - if ((val & mask) & (1 << c)) - *(uint8_t *)&svga->vram[addr] = fg[0]; - addr++; - } - break; - - /*16-bit mono->colour expansion, masked*/ - case 7: - for (c = 7; c >= 0; c--) - { - if ((val & mask) & (1 << c)) - *(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1]; - addr++; - } - break; - - case 0x8: case 0x9: case 0xa: case 0xb: - case 0xc: case 0xd: case 0xe: case 0xf: - addr &= ~0xf; - for (c = 0; c < 16; c++) - *(uint8_t *)&svga->vram[addr+c] = tgui->copy_latch[c]; - break; - } -} - -static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; - int c; - uint8_t fg[2] = {tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5]}; - uint8_t bg[2] = {tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2]}; - uint16_t mask = (tgui->ext_gdc_regs[7] << 8) | tgui->ext_gdc_regs[8]; - - cycles -= video_timing_write_w; - cycles_lost += video_timing_write_w; - - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - addr &= ~0xf; - svga->changedvram[addr >> 12] = changeframecount; - - val = (val >> 8) | (val << 8); - - switch (tgui->ext_gdc_regs[0] & 0xf) - { - /*8-bit mono->colour expansion, unmasked*/ - case 2: - for (c = 15; c >= 0; c--) - { - if (mask & (1 << c)) - *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0]; - addr++; - } - break; - - /*16-bit mono->colour expansion, unmasked*/ - case 3: - for (c = 15; c >= 0; c--) - { - if (mask & (1 << c)) - *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1]; - addr++; - } - break; - - /*8-bit mono->colour expansion, masked*/ - case 6: - for (c = 15; c >= 0; c--) - { - if ((val & mask) & (1 << c)) - *(uint8_t *)&svga->vram[addr] = fg[0]; - addr++; - } - break; - - /*16-bit mono->colour expansion, masked*/ - case 7: - for (c = 15; c >= 0; c--) - { - if ((val & mask) & (1 << c)) - *(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1]; - addr++; - } - break; - - case 0x8: case 0x9: case 0xa: case 0xb: - case 0xc: case 0xd: case 0xe: case 0xf: - for (c = 0; c < 16; c++) - *(uint8_t *)&svga->vram[addr+c] = tgui->copy_latch[c]; - break; - } -} - -static void tgui_ext_linear_writel(uint32_t addr, uint32_t val, void *p) -{ - tgui_ext_linear_writew(addr, val, p); -} - -static void tgui_ext_write(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - - addr = (addr & svga->banked_mask) + svga->read_bank; - - tgui_ext_linear_write(addr, val, svga); -} -static void tgui_ext_writew(uint32_t addr, uint16_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - - addr = (addr & svga->banked_mask) + svga->read_bank; - - tgui_ext_linear_writew(addr, val, svga); -} -static void tgui_ext_writel(uint32_t addr, uint32_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - - addr = (addr & svga->banked_mask) + svga->read_bank; - - tgui_ext_linear_writel(addr, val, svga); -} - - -enum -{ - TGUI_BITBLT = 1 -}; - -enum -{ - TGUI_SRCCPU = 0, - - TGUI_SRCDISP = 0x04, /*Source is from display*/ - TGUI_PATMONO = 0x20, /*Pattern is monochrome and needs expansion*/ - TGUI_SRCMONO = 0x40, /*Source is monochrome from CPU and needs expansion*/ - TGUI_TRANSENA = 0x1000, /*Transparent (no draw when source == bg col)*/ - TGUI_TRANSREV = 0x2000, /*Reverse fg/bg for transparent*/ - TGUI_SOLIDFILL = 0x4000 /*Pattern all zero?*/ -}; - -#define READ(addr, dat) if (tgui->accel.bpp == 0) dat = svga->vram[addr & 0x1fffff]; \ - else dat = vram_w[addr & 0xfffff]; - -#define MIX() do \ - { \ - out = 0; \ - for (c=0;c<16;c++) \ - { \ - d=(dst_dat & (1<accel.rop & (1<accel.bpp == 0) \ - { \ - svga->vram[addr & 0x1fffff] = dat; \ - svga->changedvram[((addr) & 0x1fffff) >> 12] = changeframecount; \ - } \ - else \ - { \ - vram_w[addr & 0xfffff] = dat; \ - svga->changedvram[((addr) & 0xfffff) >> 11] = changeframecount; \ - } - -void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) -{ - svga_t *svga = &tgui->svga; - int x, y; - int c, d; - uint16_t src_dat, dst_dat, pat_dat; - uint16_t out; - int xdir = (tgui->accel.flags & 0x200) ? -1 : 1; - int ydir = (tgui->accel.flags & 0x100) ? -1 : 1; - uint16_t trans_col = (tgui->accel.flags & TGUI_TRANSREV) ? tgui->accel.fg_col : tgui->accel.bg_col; - uint16_t *vram_w = (uint16_t *)svga->vram; - - if (tgui->accel.bpp == 0) - trans_col &= 0xff; - - if (count != -1 && !tgui->accel.x && (tgui->accel.flags & TGUI_SRCMONO)) - { - count -= tgui->accel.offset; - cpu_dat <<= tgui->accel.offset; - } - if (count == -1) - { - tgui->accel.x = tgui->accel.y = 0; - } - if (tgui->accel.flags & TGUI_SOLIDFILL) - { -// pclog("SOLIDFILL\n"); - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tgui->accel.tgui_pattern[y][x] = tgui->accel.fg_col; - } - } - } - else if (tgui->accel.flags & TGUI_PATMONO) - { -// pclog("PATMONO\n"); - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tgui->accel.tgui_pattern[y][x] = (tgui->accel.pattern[y] & (1 << x)) ? tgui->accel.fg_col : tgui->accel.bg_col; - } - } - } - else - { - if (tgui->accel.bpp == 0) - { -// pclog("OTHER 8-bit\n"); - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tgui->accel.tgui_pattern[y][x] = tgui->accel.pattern[x + y*8]; - } - } - } - else - { -// pclog("OTHER 16-bit\n"); - for (y = 0; y < 8; y++) - { - for (x = 0; x < 8; x++) - { - tgui->accel.tgui_pattern[y][x] = tgui->accel.pattern[x*2 + y*16] | (tgui->accel.pattern[x*2 + y*16 + 1] << 8); - } - } - } - } -/* for (y = 0; y < 8; y++) - { - if (count == -1) pclog("Pattern %i : %02X %02X %02X %02X %02X %02X %02X %02X\n", y, tgui->accel.tgui_pattern[y][0], tgui->accel.tgui_pattern[y][1], tgui->accel.tgui_pattern[y][2], tgui->accel.tgui_pattern[y][3], tgui->accel.tgui_pattern[y][4], tgui->accel.tgui_pattern[y][5], tgui->accel.tgui_pattern[y][6], tgui->accel.tgui_pattern[y][7]); - }*/ -// if (count == -1) pclog("Command %i %i %p\n", tgui->accel.command, TGUI_BITBLT, tgui); - switch (tgui->accel.command) - { - case TGUI_BITBLT: -// if (count == -1) pclog("BITBLT src %i,%i dst %i,%i size %i,%i flags %04X\n", tgui->accel.src_x, tgui->accel.src_y, tgui->accel.dst_x, tgui->accel.dst_y, tgui->accel.size_x, tgui->accel.size_y, tgui->accel.flags); - if (count == -1) - { - tgui->accel.src = tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch); - tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch); - tgui->accel.pat_x = tgui->accel.dst_x; - tgui->accel.pat_y = tgui->accel.dst_y; - } - - switch (tgui->accel.flags & (TGUI_SRCMONO|TGUI_SRCDISP)) - { - case TGUI_SRCCPU: - if (count == -1) - { -// pclog("Blit start TGUI_SRCCPU\n"); - if (svga->crtc[0x21] & 0x20) - { - tgui->write_blitter = 1; - } - if (tgui->accel.use_src) - return; - } - else - count >>= 3; -// pclog("TGUI_SRCCPU\n"); - while (count) - { - if (tgui->accel.bpp == 0) - { - src_dat = cpu_dat >> 24; - cpu_dat <<= 8; - } - else - { - src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0xff00); - cpu_dat <<= 16; - count--; - } - READ(tgui->accel.dst, dst_dat); - pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7]; - - if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) - { - MIX(); - - WRITE(tgui->accel.dst, out); - } - -// pclog(" %i,%i %02X %02X %02X %02X\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out); - - tgui->accel.src += xdir; - tgui->accel.dst += xdir; - tgui->accel.pat_x += xdir; - - tgui->accel.x++; - if (tgui->accel.x > tgui->accel.size_x) - { - tgui->accel.x = 0; - tgui->accel.y++; - - tgui->accel.pat_x = tgui->accel.dst_x; - - tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); - tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); - tgui->accel.pat_y += ydir; - - if (tgui->accel.y > tgui->accel.size_y) - { - if (svga->crtc[0x21] & 0x20) - { - tgui->write_blitter = 0; - } - return; - } - if (tgui->accel.use_src) - return; - } - count--; - } - break; - - case TGUI_SRCMONO | TGUI_SRCCPU: - if (count == -1) - { -// pclog("Blit start TGUI_SRCMONO | TGUI_SRCCPU\n"); - if (svga->crtc[0x21] & 0x20) - { - tgui->write_blitter = 1; - } - -// pclog(" %i\n", tgui->accel.command); - if (tgui->accel.use_src) - return; - } -// pclog("TGUI_SRCMONO | TGUI_SRCCPU\n"); - while (count) - { - src_dat = ((cpu_dat >> 31) ? tgui->accel.fg_col : tgui->accel.bg_col); - if (tgui->accel.bpp == 0) - src_dat &= 0xff; - - READ(tgui->accel.dst, dst_dat); - pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7]; - - if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) - { - MIX(); - - WRITE(tgui->accel.dst, out); - } -// pclog(" %i,%i %02X %02X %02X %02X %i\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out, (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col)); - cpu_dat <<= 1; - tgui->accel.src += xdir; - tgui->accel.dst += xdir; - tgui->accel.pat_x += xdir; - - tgui->accel.x++; - if (tgui->accel.x > tgui->accel.size_x) - { - tgui->accel.x = 0; - tgui->accel.y++; - - tgui->accel.pat_x = tgui->accel.dst_x; - - tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); - tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); - tgui->accel.pat_y += ydir; - - if (tgui->accel.y > tgui->accel.size_y) - { - if (svga->crtc[0x21] & 0x20) - { - tgui->write_blitter = 0; - } - return; - } - if (tgui->accel.use_src) - return; - } - count--; - } - break; - - default: - while (count) - { - READ(tgui->accel.src, src_dat); - READ(tgui->accel.dst, dst_dat); - pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7]; - - if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) - { - MIX(); - - WRITE(tgui->accel.dst, out); - } -// pclog(" %i,%i %02X %02X %02X %02X\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out); - - tgui->accel.src += xdir; - tgui->accel.dst += xdir; - tgui->accel.pat_x += xdir; - - tgui->accel.x++; - if (tgui->accel.x > tgui->accel.size_x) - { - tgui->accel.x = 0; - tgui->accel.y++; - - tgui->accel.pat_x = tgui->accel.dst_x; - - tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); - tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); - tgui->accel.pat_y += ydir; - - if (tgui->accel.y > tgui->accel.size_y) - return; - } - count--; - } - break; - } - break; - } -} - -static void tgui_accel_write_fifo(tgui_t *tgui, uint32_t addr, uint8_t val) -{ - switch (addr & 0xff) - { - case 0x22: - tgui->accel.ger22 = val; - tgui->accel.pitch = 512 << ((val >> 2) & 3); - tgui->accel.bpp = (val & 3) ? 1 : 0; - tgui->accel.pitch >>= tgui->accel.bpp; - break; - - case 0x24: /*Command*/ - tgui->accel.command = val; - tgui_accel_command(-1, 0, tgui); - break; - - case 0x27: /*ROP*/ - tgui->accel.rop = val; - tgui->accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33); -// pclog("Write ROP %02X %i\n", val, tgui->accel.use_src); - break; - - case 0x28: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0xff00) | val; - break; - case 0x29: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0xff) | (val << 8); - break; - - case 0x2b: - tgui->accel.offset = val & 7; - break; - - case 0x2c: /*Foreground colour*/ - tgui->accel.fg_col = (tgui->accel.fg_col & 0xff00) | val; - break; - case 0x2d: /*Foreground colour*/ - tgui->accel.fg_col = (tgui->accel.fg_col & 0xff) | (val << 8); - break; - - case 0x30: /*Background colour*/ - tgui->accel.bg_col = (tgui->accel.bg_col & 0xff00) | val; - break; - case 0x31: /*Background colour*/ - tgui->accel.bg_col = (tgui->accel.bg_col & 0xff) | (val << 8); - break; - - case 0x38: /*Dest X*/ - tgui->accel.dst_x = (tgui->accel.dst_x & 0xff00) | val; - break; - case 0x39: /*Dest X*/ - tgui->accel.dst_x = (tgui->accel.dst_x & 0xff) | (val << 8); - break; - case 0x3a: /*Dest Y*/ - tgui->accel.dst_y = (tgui->accel.dst_y & 0xff00) | val; - break; - case 0x3b: /*Dest Y*/ - tgui->accel.dst_y = (tgui->accel.dst_y & 0xff) | (val << 8); - break; - - case 0x3c: /*Src X*/ - tgui->accel.src_x = (tgui->accel.src_x & 0xff00) | val; - break; - case 0x3d: /*Src X*/ - tgui->accel.src_x = (tgui->accel.src_x & 0xff) | (val << 8); - break; - case 0x3e: /*Src Y*/ - tgui->accel.src_y = (tgui->accel.src_y & 0xff00) | val; - break; - case 0x3f: /*Src Y*/ - tgui->accel.src_y = (tgui->accel.src_y & 0xff) | (val << 8); - break; - - case 0x40: /*Size X*/ - tgui->accel.size_x = (tgui->accel.size_x & 0xff00) | val; - break; - case 0x41: /*Size X*/ - tgui->accel.size_x = (tgui->accel.size_x & 0xff) | (val << 8); - break; - case 0x42: /*Size Y*/ - tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val; - break; - case 0x43: /*Size Y*/ - tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8); - break; - - case 0x80: case 0x81: case 0x82: case 0x83: - case 0x84: case 0x85: case 0x86: case 0x87: - case 0x88: case 0x89: case 0x8a: case 0x8b: - case 0x8c: case 0x8d: case 0x8e: case 0x8f: - case 0x90: case 0x91: case 0x92: case 0x93: - case 0x94: case 0x95: case 0x96: case 0x97: - case 0x98: case 0x99: case 0x9a: case 0x9b: - case 0x9c: case 0x9d: case 0x9e: case 0x9f: - case 0xa0: case 0xa1: case 0xa2: case 0xa3: - case 0xa4: case 0xa5: case 0xa6: case 0xa7: - case 0xa8: case 0xa9: case 0xaa: case 0xab: - case 0xac: case 0xad: case 0xae: case 0xaf: - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: - case 0xc0: case 0xc1: case 0xc2: case 0xc3: - case 0xc4: case 0xc5: case 0xc6: case 0xc7: - case 0xc8: case 0xc9: case 0xca: case 0xcb: - case 0xcc: case 0xcd: case 0xce: case 0xcf: - case 0xd0: case 0xd1: case 0xd2: case 0xd3: - case 0xd4: case 0xd5: case 0xd6: case 0xd7: - case 0xd8: case 0xd9: case 0xda: case 0xdb: - case 0xdc: case 0xdd: case 0xde: case 0xdf: - case 0xe0: case 0xe1: case 0xe2: case 0xe3: - case 0xe4: case 0xe5: case 0xe6: case 0xe7: - case 0xe8: case 0xe9: case 0xea: case 0xeb: - case 0xec: case 0xed: case 0xee: case 0xef: - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: - tgui->accel.pattern[addr & 0x7f] = val; - break; - } -} - -static void tgui_accel_write_fifo_fb_b(tgui_t *tgui, uint32_t addr, uint8_t val) -{ - tgui_accel_command(8, val << 24, tgui); -} -static void tgui_accel_write_fifo_fb_w(tgui_t *tgui, uint32_t addr, uint16_t val) -{ - tgui_accel_command(16, (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)) << 16, tgui); -} -static void tgui_accel_write_fifo_fb_l(tgui_t *tgui, uint32_t addr, uint32_t val) -{ - tgui_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), tgui); -} - -static void fifo_thread(void *param) -{ - tgui_t *tgui = (tgui_t *)param; - - while (1) - { - thread_set_event(tgui->fifo_not_full_event); - thread_wait_event(tgui->wake_fifo_thread, -1); - thread_reset_event(tgui->wake_fifo_thread); - tgui->blitter_busy = 1; - while (!FIFO_EMPTY) - { - uint64_t start_time = timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &tgui->fifo[tgui->fifo_read_idx & FIFO_MASK]; - - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITE_BYTE: - tgui_accel_write_fifo(tgui, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_FB_BYTE: - tgui_accel_write_fifo_fb_b(tgui, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_FB_WORD: - tgui_accel_write_fifo_fb_w(tgui, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_FB_LONG: - tgui_accel_write_fifo_fb_l(tgui, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - } - - tgui->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; - - if (FIFO_ENTRIES > 0xe000) - thread_set_event(tgui->fifo_not_full_event); - - end_time = timer_read(); - tgui->blitter_time += end_time - start_time; - } - tgui->blitter_busy = 0; - } -} - -static inline void wake_fifo_thread(tgui_t *tgui) -{ - thread_set_event(tgui->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ -} - -static void tgui_wait_fifo_idle(tgui_t *tgui) -{ - while (!FIFO_EMPTY) - { - wake_fifo_thread(tgui); - thread_wait_event(tgui->fifo_not_full_event, 1); - } -} - -static void tgui_queue(tgui_t *tgui, uint32_t addr, uint32_t val, uint32_t type) -{ - fifo_entry_t *fifo = &tgui->fifo[tgui->fifo_write_idx & FIFO_MASK]; - - if (FIFO_FULL) - { - thread_reset_event(tgui->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(tgui->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } - } - - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; - - tgui->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(tgui); -} - - -void tgui_accel_write(uint32_t addr, uint8_t val, void *p) -{ - tgui_t *tgui = (tgui_t *)p; -// pclog("tgui_accel_write : %08X %02X %04X(%08X):%08X %02X\n", addr, val, CS,cs,pc, opcode); - if ((addr & ~0xff) != 0xbff00) - return; - tgui_queue(tgui, addr, val, FIFO_WRITE_BYTE); -} - -void tgui_accel_write_w(uint32_t addr, uint16_t val, void *p) -{ - tgui_t *tgui = (tgui_t *)p; -// pclog("tgui_accel_write_w %08X %04X\n", addr, val); - tgui_accel_write(addr, val, tgui); - tgui_accel_write(addr + 1, val >> 8, tgui); -} - -void tgui_accel_write_l(uint32_t addr, uint32_t val, void *p) -{ - tgui_t *tgui = (tgui_t *)p; -// pclog("tgui_accel_write_l %08X %08X\n", addr, val); - tgui_accel_write(addr, val, tgui); - tgui_accel_write(addr + 1, val >> 8, tgui); - tgui_accel_write(addr + 2, val >> 16, tgui); - tgui_accel_write(addr + 3, val >> 24, tgui); -} - -uint8_t tgui_accel_read(uint32_t addr, void *p) -{ - tgui_t *tgui = (tgui_t *)p; -// pclog("tgui_accel_read : %08X\n", addr); - if ((addr & ~0xff) != 0xbff00) - return 0xff; - if ((addr & 0xff) != 0x20) - tgui_wait_fifo_idle(tgui); - switch (addr & 0xff) - { - case 0x20: /*Status*/ - if (!FIFO_EMPTY) - return 1 << 5; - return 0; - - case 0x27: /*ROP*/ - return tgui->accel.rop; - - case 0x28: /*Flags*/ - return tgui->accel.flags & 0xff; - case 0x29: /*Flags*/ - return tgui->accel.flags >> 8; - - case 0x2b: - return tgui->accel.offset; - - case 0x2c: /*Background colour*/ - return tgui->accel.bg_col & 0xff; - case 0x2d: /*Background colour*/ - return tgui->accel.bg_col >> 8; - - case 0x30: /*Foreground colour*/ - return tgui->accel.fg_col & 0xff; - case 0x31: /*Foreground colour*/ - return tgui->accel.fg_col >> 8; - - case 0x38: /*Dest X*/ - return tgui->accel.dst_x & 0xff; - case 0x39: /*Dest X*/ - return tgui->accel.dst_x >> 8; - case 0x3a: /*Dest Y*/ - return tgui->accel.dst_y & 0xff; - case 0x3b: /*Dest Y*/ - return tgui->accel.dst_y >> 8; - - case 0x3c: /*Src X*/ - return tgui->accel.src_x & 0xff; - case 0x3d: /*Src X*/ - return tgui->accel.src_x >> 8; - case 0x3e: /*Src Y*/ - return tgui->accel.src_y & 0xff; - case 0x3f: /*Src Y*/ - return tgui->accel.src_y >> 8; - - case 0x40: /*Size X*/ - return tgui->accel.size_x & 0xff; - case 0x41: /*Size X*/ - return tgui->accel.size_x >> 8; - case 0x42: /*Size Y*/ - return tgui->accel.size_y & 0xff; - case 0x43: /*Size Y*/ - return tgui->accel.size_y >> 8; - - case 0x80: case 0x81: case 0x82: case 0x83: - case 0x84: case 0x85: case 0x86: case 0x87: - case 0x88: case 0x89: case 0x8a: case 0x8b: - case 0x8c: case 0x8d: case 0x8e: case 0x8f: - case 0x90: case 0x91: case 0x92: case 0x93: - case 0x94: case 0x95: case 0x96: case 0x97: - case 0x98: case 0x99: case 0x9a: case 0x9b: - case 0x9c: case 0x9d: case 0x9e: case 0x9f: - case 0xa0: case 0xa1: case 0xa2: case 0xa3: - case 0xa4: case 0xa5: case 0xa6: case 0xa7: - case 0xa8: case 0xa9: case 0xaa: case 0xab: - case 0xac: case 0xad: case 0xae: case 0xaf: - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - case 0xb4: case 0xb5: case 0xb6: case 0xb7: - case 0xb8: case 0xb9: case 0xba: case 0xbb: - case 0xbc: case 0xbd: case 0xbe: case 0xbf: - case 0xc0: case 0xc1: case 0xc2: case 0xc3: - case 0xc4: case 0xc5: case 0xc6: case 0xc7: - case 0xc8: case 0xc9: case 0xca: case 0xcb: - case 0xcc: case 0xcd: case 0xce: case 0xcf: - case 0xd0: case 0xd1: case 0xd2: case 0xd3: - case 0xd4: case 0xd5: case 0xd6: case 0xd7: - case 0xd8: case 0xd9: case 0xda: case 0xdb: - case 0xdc: case 0xdd: case 0xde: case 0xdf: - case 0xe0: case 0xe1: case 0xe2: case 0xe3: - case 0xe4: case 0xe5: case 0xe6: case 0xe7: - case 0xe8: case 0xe9: case 0xea: case 0xeb: - case 0xec: case 0xed: case 0xee: case 0xef: - case 0xf0: case 0xf1: case 0xf2: case 0xf3: - case 0xf4: case 0xf5: case 0xf6: case 0xf7: - case 0xf8: case 0xf9: case 0xfa: case 0xfb: - case 0xfc: case 0xfd: case 0xfe: case 0xff: - return tgui->accel.pattern[addr & 0x7f]; - } - return 0xff; -} - -uint16_t tgui_accel_read_w(uint32_t addr, void *p) -{ - tgui_t *tgui = (tgui_t *)p; -// pclog("tgui_accel_read_w %08X\n", addr); - return tgui_accel_read(addr, tgui) | (tgui_accel_read(addr + 1, tgui) << 8); -} - -uint32_t tgui_accel_read_l(uint32_t addr, void *p) -{ - tgui_t *tgui = (tgui_t *)p; -// pclog("tgui_accel_read_l %08X\n", addr); - return tgui_accel_read_w(addr, tgui) | (tgui_accel_read_w(addr + 2, tgui) << 16); -} - -void tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; - - if (tgui->write_blitter) - tgui_queue(tgui, addr, val, FIFO_WRITE_FB_BYTE); - else - svga_write_linear(addr, val, svga); -} - -void tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; - - if (tgui->write_blitter) - tgui_queue(tgui, addr, val, FIFO_WRITE_FB_WORD); - else - svga_writew_linear(addr, val, svga); -} - -void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - tgui_t *tgui = (tgui_t *)svga->p; - - if (tgui->write_blitter) - tgui_queue(tgui, addr, val, FIFO_WRITE_FB_LONG); - else - svga_writel_linear(addr, val, svga); -} - -void tgui_add_status_info(char *s, int max_len, void *p) -{ - tgui_t *tgui = (tgui_t *)p; - char temps[256]; - uint64_t new_time = timer_read(); - uint64_t status_diff = new_time - tgui->status_time; - tgui->status_time = new_time; - - svga_add_status_info(s, max_len, &tgui->svga); - - sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)tgui->blitter_time * 100.0) / timer_freq, ((double)tgui->blitter_time * 100.0) / status_diff); - strncat(s, temps, max_len); - - tgui->blitter_time = 0; -} - -static device_config_t tgui9440_config[] = -{ - { - NULL, - NULL, - -1, - } -}; - -device_t tgui9400cxi_device = -{ - "Trident TGUI 9400CXi", - 0, - tgui9400cxi_init, - tgui_close, - tgui9400cxi_available, - tgui_speed_changed, - tgui_force_redraw, - tgui_add_status_info, - tgui9440_config -}; - -device_t tgui9400cxi_elx_device = -{ - "Trident TGUI 9400CXi (Elonex PC-425X)", - 0, - tgui9400cxi_elx_init, - tgui_close, - tgui9400cxi_available, - tgui_speed_changed, - tgui_force_redraw, - tgui_add_status_info, - tgui9440_config -}; - -device_t tgui9440_device = -{ - "Trident TGUI 9440", - 0, - tgui9440_init, - tgui_close, - tgui9440_available, - tgui_speed_changed, - tgui_force_redraw, - tgui_add_status_info, - tgui9440_config -}; - - +/** + * @file tgui9680.c + * @brief Implementation of the Trident TGUI9680 from PCem (vid_tgui9440.c) + */ + +#include "compiler.h" + +#if defined(SUPPORT_TRIDENT_TGUI) + +#include "pccore.h" +#include "wab.h" +#include "tgui9680_extern.h" +#include "tgui9680_wrapper.h" +#include "tgui9680.h" +#include "dosio.h" +#include "cpucore.h" +#include "pccore.h" +#include "iocore.h" +#include "soundmng.h" + +#if defined(SUPPORT_IA32_HAXM) +#include "i386hax/haxfunc.h" +#include "i386hax/haxcore.h" +#endif + +/*TGUI9400CXi has extended write modes, controlled by extended GDC registers : + + GDC[0x10] - Control + bit 0 - pixel width (1 = 16 bit, 0 = 8 bit) + bit 1 - mono->colour expansion (1 = enabled, 0 = disabled) + bit 2 - mono->colour expansion transparency (1 = tranparent, 0 = opaque) + bit 3 - extended latch copy + GDC[0x11] - Background colour (low byte) + GDC[0x12] - Background colour (high byte) + GDC[0x14] - Foreground colour (low byte) + GDC[0x15] - Foreground colour (high byte) + GDC[0x17] - Write mask (low byte) + GDC[0x18] - Write mask (high byte) + + Mono->colour expansion will expand written data 8:1 to 8/16 consecutive bytes. + MSB is processed first. On word writes, low byte is processed first. 1 bits write + foreground colour, 0 bits write background colour unless transparency is enabled. + If the relevant bit is clear in the write mask then the data is not written. + + With 16-bit pixel width, each bit still expands to one byte, so the TGUI driver + doubles up monochrome data. + + While there is room in the register map for three byte colours, I don't believe + 24-bit colour is supported. The TGUI9440 blitter has the same limitation. + + I don't think double word writes are supported. + + Extended latch copy uses an internal 16 byte latch. Reads load the latch, writing + writes out 16 bytes. I don't think the access size or host data has any affect, + but the Windows 3.1 driver always reads bytes and write words of 0xffff.*/ + +#define EXT_CTRL_16BIT 0x01 +#define EXT_CTRL_MONO_EXPANSION 0x02 +#define EXT_CTRL_MONO_TRANSPARENT 0x04 +#define EXT_CTRL_LATCH_COPY 0x08 + +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_ENTRY_SIZE (1 << 31) + +#define FIFO_ENTRIES (tgui->fifo_write_idx - tgui->fifo_read_idx) +#define FIFO_FULL ((tgui->fifo_write_idx - tgui->fifo_read_idx) >= FIFO_SIZE) +#define FIFO_EMPTY (tgui->fifo_read_idx == tgui->fifo_write_idx) + +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff + +enum +{ + TGUI_9400CXI = 0, + TGUI_9440 +}; + +enum +{ + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_BYTE = (0x01 << 24), + FIFO_WRITE_FB_BYTE = (0x04 << 24), + FIFO_WRITE_FB_WORD = (0x05 << 24), + FIFO_WRITE_FB_LONG = (0x06 << 24) +}; + +typedef struct +{ + uint32_t addr_type; + uint32_t val; +} fifo_entry_t; + +typedef struct tgui_t +{ + mem_mapping_t linear_mapping; + mem_mapping_t accel_mapping; + + rom_t bios_rom; + + svga_t svga; + + tkd8001_ramdac_t ramdac; /*TGUI9400CXi*/ + + int type; + + struct + { + uint16_t src_x, src_y; + uint16_t dst_x, dst_y; + uint16_t size_x, size_y; + uint16_t fg_col, bg_col; + uint8_t rop; + uint16_t flags; + uint8_t pattern[0x80]; + int command; + int offset; + uint8_t ger22; + + int x, y; + uint32_t src, dst, src_old, dst_old; + int pat_x, pat_y; + int use_src; + + int pitch, bpp; + + uint16_t tgui_pattern[8][8]; + } accel; + + uint8_t ext_gdc_regs[16]; /*TGUI9400CXi only*/ + uint8_t copy_latch[16]; + + uint8_t tgui_3d8, tgui_3d9; + int oldmode; + uint8_t oldctrl1; + uint8_t oldctrl2,newctrl2; + + uint32_t linear_base, linear_size; + + int ramdac_state; + uint8_t ramdac_ctrl; + + int clock_m, clock_n, clock_k; + + uint32_t vram_size, vram_mask; + + fifo_entry_t fifo[FIFO_SIZE]; + volatile int fifo_read_idx, fifo_write_idx; + + thread_t *fifo_thread; + event_t *wake_fifo_thread; + event_t *fifo_not_full_event; + + int blitter_busy; + uint64_t blitter_time; + uint64_t status_time; + + volatile int write_blitter; +} tgui_t; + +void tgui_recalcmapping(tgui_t *tgui); + +static void fifo_thread(void *param); + +uint8_t tgui_accel_read(uint32_t addr, void *priv); +uint16_t tgui_accel_read_w(uint32_t addr, void *priv); +uint32_t tgui_accel_read_l(uint32_t addr, void *priv); + +void tgui_accel_write(uint32_t addr, uint8_t val, void *priv); +void tgui_accel_write_w(uint32_t addr, uint16_t val, void *priv); +void tgui_accel_write_l(uint32_t addr, uint32_t val, void *priv); + +void tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *priv); +void tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *priv); +void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *priv); + +static uint8_t tgui_ext_linear_read(uint32_t addr, void *p); +static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p); +static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p); +static void tgui_ext_linear_writel(uint32_t addr, uint32_t val, void *p); + +static uint8_t tgui_ext_read(uint32_t addr, void *p); +static void tgui_ext_write(uint32_t addr, uint8_t val, void *p); +static void tgui_ext_writew(uint32_t addr, uint16_t val, void *p); +static void tgui_ext_writel(uint32_t addr, uint32_t val, void *p); + +void tgui_out(uint16_t addr, uint8_t val, void *p) +{ + tgui_t *tgui = (tgui_t *)p; + svga_t *svga = &tgui->svga; + + uint8_t old; + +// pclog("tgui_out : %04X %02X %04X:%04X %i\n", addr, val, CS,pc, svga->bpp); + if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; + + switch (addr) + { + case 0x3C5: + switch (svga->seqaddr & 0xf) + { + case 0xB: + tgui->oldmode=1; + break; + case 0xC: + if (svga->seqregs[0xe] & 0x80) + svga->seqregs[0xc] = val; + break; + case 0xd: + if (tgui->oldmode) + tgui->oldctrl2 = val; + else + tgui->newctrl2=val; + break; + case 0xE: + if (tgui->oldmode) + tgui->oldctrl1 = val; + else + { + svga->seqregs[0xe] = val ^ 2; + svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536; + if (!(svga->gdcreg[0xf] & 1)) + svga->read_bank = svga->write_bank; + } + return; + } + break; + + case 0x3C6: + if (tgui->type == TGUI_9400CXI) + { + tkd8001_ramdac_out(addr, val, &tgui->ramdac, svga); + return; + } + if (tgui->ramdac_state == 4) + { + tgui->ramdac_state = 0; + tgui->ramdac_ctrl = val; + switch (tgui->ramdac_ctrl & 0xf0) + { + case 0x10: + svga->bpp = 15; + break; + case 0x30: + svga->bpp = 16; + break; + case 0xd0: + svga->bpp = 24; + break; + default: + svga->bpp = 8; + break; + } + return; + } + case 0x3C7: case 0x3C8: case 0x3C9: + if (tgui->type == TGUI_9400CXI) + { + tkd8001_ramdac_out(addr, val, &tgui->ramdac, svga); + return; + } + tgui->ramdac_state = 0; + break; + + case 0x3CF: + if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32) + { + old = tgui->ext_gdc_regs[svga->gdcaddr & 15]; + tgui->ext_gdc_regs[svga->gdcaddr & 15] = val; + if (svga->gdcaddr == 16) + tgui_recalcmapping(tgui); + return; + } + switch (svga->gdcaddr & 15) + { + case 0x6: + if (svga->gdcreg[6] != val) + { + svga->gdcreg[6] = val; + tgui_recalcmapping(tgui); + } + return; + + case 0xE: + svga->gdcreg[0xe] = val ^ 2; + if ((svga->gdcreg[0xf] & 1) == 1) + svga->read_bank = (svga->gdcreg[0xe] & 0xf) * 65536; + break; + case 0xF: + if (val & 1) svga->read_bank = (svga->gdcreg[0xe] & 0xf) *65536; + else svga->read_bank = (svga->seqregs[0xe] & 0xf) *65536; + svga->write_bank = (svga->seqregs[0xe] & 0xf) * 65536; + break; + } + break; + case 0x3D4: + svga->crtcreg = val & 0x7f; + return; + case 0x3D5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; +// if (svga->crtcreg != 0xE && svga->crtcreg != 0xF) pclog("CRTC R%02X = %02X\n", svga->crtcreg, val); + if (old != val) + { + if (svga->crtcreg < 0xE || svga->crtcreg > 0x10) + { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + switch (svga->crtcreg) + { + case 0x21: + if (old != val) + { + if (!PCI) + { + tgui->linear_base = ((val & 0xf) | ((val >> 2) & 0x30)) << 20; + tgui->linear_size = (val & 0x10) ? 0x200000 : 0x100000; + tgui->svga.decode_mask = (val & 0x10) ? 0x1fffff : 0xfffff; + } + tgui_recalcmapping(tgui); + } + break; + + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x45: case 0x46: case 0x47: + if (tgui->type >= TGUI_9440) + { + svga->hwcursor.x = (svga->crtc[0x40] | (svga->crtc[0x41] << 8)) & 0x7ff; + svga->hwcursor.y = (svga->crtc[0x42] | (svga->crtc[0x43] << 8)) & 0x7ff; + svga->hwcursor.xoff = svga->crtc[0x46] & 0x3f; + svga->hwcursor.yoff = svga->crtc[0x47] & 0x3f; + svga->hwcursor.addr = (svga->crtc[0x44] << 10) | ((svga->crtc[0x45] & 0x7) << 18) | (svga->hwcursor.yoff * 8); + } + break; + + case 0x50: + if (tgui->type >= TGUI_9440) + { + svga->hwcursor.ena = val & 0x80; + svga->hwcursor.xsize = (val & 1) ? 64 : 32; + svga->hwcursor.ysize = (val & 1) ? 64 : 32; + } + break; + } + return; + case 0x3D8: + tgui->tgui_3d8 = val; + if (svga->gdcreg[0xf] & 4) + { + svga->write_bank = (val & 0x1f) * 65536; +// pclog("SVGAWBANK 3D8 %08X %04X:%04X\n",svgawbank,CS,pc); + if (!(svga->gdcreg[0xf] & 1)) + { + svga->read_bank = (val & 0x1f) * 65536; +// pclog("SVGARBANK 3D8 %08X %04X:%04X\n",svgarbank,CS,pc); + } + } + return; + case 0x3D9: + tgui->tgui_3d9 = val; + if ((svga->gdcreg[0xf] & 5) == 5) + { + svga->read_bank = (val & 0x1F) * 65536; +// pclog("SVGARBANK 3D9 %08X %04X:%04X\n",svgarbank,CS,pc); + } + return; + + case 0x43c8: + tgui->clock_n = val & 0x7f; + tgui->clock_m = (tgui->clock_m & ~1) | (val >> 7); + break; + case 0x43c9: + tgui->clock_m = (tgui->clock_m & ~0x1e) | ((val << 1) & 0x1e); + tgui->clock_k = (val & 0x10) >> 4; + break; + } + svga_out(addr, val, svga); +} + +uint8_t tgui_in(uint16_t addr, void *p) +{ + tgui_t *tgui = (tgui_t *)p; + svga_t *svga = &tgui->svga; + +// if (addr != 0x3da) pclog("tgui_in : %04X %04X:%04X\n", addr, CS,pc); + + if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; + + switch (addr) + { + case 0x3C5: + if ((svga->seqaddr & 0xf) == 0xb) + { +// printf("Read Trident ID %04X:%04X %04X\n",CS,pc,readmemw(ss,SP)); + tgui->oldmode = 0; + switch (tgui->type) + { + case TGUI_9400CXI: + return 0x93; /*TGUI9400CXi*/ + case TGUI_9440: + return 0xe3; /*TGUI9440AGi*/ + } + } + if ((svga->seqaddr & 0xf) == 0xc) + { +// printf("Read Trident Power Up 1 %04X:%04X %04X\n",CS,pc,readmemw(ss,SP)); +// return 0x20; /*2 DRAM banks*/ + } + if ((svga->seqaddr & 0xf) == 0xd) + { + if (tgui->oldmode) + return tgui->oldctrl2; + return tgui->newctrl2; + } + if ((svga->seqaddr & 0xf) == 0xe) + { + if (tgui->oldmode) + return tgui->oldctrl1; + } + break; + case 0x3C6: + if (tgui->type == TGUI_9400CXI) + return tkd8001_ramdac_in(addr, &tgui->ramdac, svga); + if (tgui->ramdac_state == 4) + return tgui->ramdac_ctrl; + tgui->ramdac_state++; + break; + case 0x3C7: case 0x3C8: case 0x3C9: + if (tgui->type == TGUI_9400CXI) + return tkd8001_ramdac_in(addr, &tgui->ramdac, svga); + tgui->ramdac_state = 0; + break; + case 0x3CF: + if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32) + return tgui->ext_gdc_regs[svga->gdcaddr & 15]; + break; + case 0x3D4: + return svga->crtcreg; + case 0x3D5: + return svga->crtc[svga->crtcreg]; + case 0x3d8: + return tgui->tgui_3d8; + case 0x3d9: + return tgui->tgui_3d9; + } + return svga_in(addr, svga); +} + +void tgui_recalctimings(svga_t *svga) +{ + tgui_t *tgui = (tgui_t *)svga->p; + + if (svga->crtc[0x29] & 0x10) + svga->rowoffset += 0x100; + + if (tgui->type >= TGUI_9440 && svga->bpp == 24) + svga->hdisp = (svga->crtc[1] + 1) * 8; + + if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000; + if ((svga->crtc[0x27] & 0x01) == 0x01) svga->ma_latch |= 0x20000; + if ((svga->crtc[0x27] & 0x02) == 0x02) svga->ma_latch |= 0x40000; + + if (tgui->oldctrl2 & 0x10) + svga->rowoffset <<= 1; + if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) + svga->ma_latch <<= 1; + + if (tgui->oldctrl2 & 0x10) /*I'm not convinced this is the right register for this function*/ + svga->lowres=0; + + svga->lowres = !(svga->crtc[0x2a] & 0x40); + + svga->interlace = svga->crtc[0x1e] & 4; + if (svga->interlace && tgui->type < TGUI_9440) + svga->rowoffset >>= 1; + + if (tgui->type >= TGUI_9440) + { + if (svga->miscout & 8) + svga->clock = (cpuclock * (double)(1ull << 32)) / (((tgui->clock_n + 8) * 14318180.0) / ((tgui->clock_m + 2) * (1 << tgui->clock_k))); + + if (svga->gdcreg[0xf] & 0x08) + svga->clock *= 2; + else if (svga->gdcreg[0xf] & 0x40) + svga->clock *= 3; + } + else + { + switch (((svga->miscout >> 2) & 3) | ((tgui->newctrl2 << 2) & 4) | ((tgui->newctrl2 >> 3) & 8)) + { + case 0x02: svga->clock = (cpuclock * (double)(1ull << 32)) / 44900000.0; break; + case 0x03: svga->clock = (cpuclock * (double)(1ull << 32)) / 36000000.0; break; + case 0x04: svga->clock = (cpuclock * (double)(1ull << 32)) / 57272000.0; break; + case 0x05: svga->clock = (cpuclock * (double)(1ull << 32)) / 65000000.0; break; + case 0x06: svga->clock = (cpuclock * (double)(1ull << 32)) / 50350000.0; break; + case 0x07: svga->clock = (cpuclock * (double)(1ull << 32)) / 40000000.0; break; + case 0x08: svga->clock = (cpuclock * (double)(1ull << 32)) / 88000000.0; break; + case 0x09: svga->clock = (cpuclock * (double)(1ull << 32)) / 98000000.0; break; + case 0x0a: svga->clock = (cpuclock * (double)(1ull << 32)) /118800000.0; break; + case 0x0b: svga->clock = (cpuclock * (double)(1ull << 32)) /108000000.0; break; + case 0x0c: svga->clock = (cpuclock * (double)(1ull << 32)) / 72000000.0; break; + case 0x0d: svga->clock = (cpuclock * (double)(1ull << 32)) / 77000000.0; break; + case 0x0e: svga->clock = (cpuclock * (double)(1ull << 32)) / 80000000.0; break; + case 0x0f: svga->clock = (cpuclock * (double)(1ull << 32)) / 75000000.0; break; + } + if (svga->gdcreg[0xf] & 0x08) + { + svga->htotal *= 2; + svga->hdisp *= 2; + svga->hdisp_time *= 2; + } + } + + if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) + { + switch (svga->bpp) + { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + if (tgui->type < TGUI_9440) + svga->hdisp /= 2; + break; + case 16: + svga->render = svga_render_16bpp_highres; + if (tgui->type < TGUI_9440) + svga->hdisp /= 2; + break; + case 24: + svga->render = svga_render_24bpp_highres; + if (tgui->type < TGUI_9440) + svga->hdisp = (svga->hdisp * 2) / 3; + break; + } + } +} + +void tgui_recalcmapping(tgui_t *tgui) +{ + svga_t *svga = &tgui->svga; + +// pclog("tgui_recalcmapping : %02X %02X\n", svga->crtc[0x21], svga->gdcreg[6]); + + if (tgui->type == TGUI_9400CXI) + { + if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) + { + mem_mapping_set_handler(&tgui->linear_mapping, + tgui_ext_linear_read, NULL, NULL, + tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); + mem_mapping_set_handler(&svga->mapping, + tgui_ext_read, NULL, NULL, + tgui_ext_write, tgui_ext_writew, tgui_ext_writel); + } + else if (tgui->ext_gdc_regs[0] & EXT_CTRL_MONO_EXPANSION) + { + mem_mapping_set_handler(&tgui->linear_mapping, + svga_read_linear, svga_readw_linear, svga_readl_linear, + tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); + mem_mapping_set_handler(&svga->mapping, + svga_read, svga_readw, svga_readl, + tgui_ext_write, tgui_ext_writew, tgui_ext_writel); + } + else + { + mem_mapping_set_handler(&tgui->linear_mapping, + svga_read_linear, svga_readw_linear, svga_readl_linear, + svga_write_linear, svga_writew_linear, svga_writel_linear); + mem_mapping_set_handler(&svga->mapping, + svga_read, svga_readw, svga_readl, + svga_write, svga_writew, svga_writel); + } + } + + if (svga->crtc[0x21] & 0x20) + { + mem_mapping_disable(&svga->mapping); + mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size); +// pclog("Trident linear framebuffer at %08X - size %06X\n", tgui->linear_base, tgui->linear_size); + if (tgui->type >= TGUI_9440) + { + mem_mapping_enable(&tgui->accel_mapping); + mem_mapping_disable(&svga->mapping); + } + else + { + switch (svga->gdcreg[6] & 0xC) + { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + } + } + else + { +// pclog("Write mapping %02X\n", val); + mem_mapping_disable(&tgui->linear_mapping); + mem_mapping_disable(&tgui->accel_mapping); + switch (svga->gdcreg[6] & 0xC) + { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_mapping_enable(&tgui->accel_mapping); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + } +} + +void tgui_hwcursor_draw(svga_t *svga, int displine) +{ + uint32_t dat[2]; + int xx; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 8; + + dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 24) | (svga->vram[svga->hwcursor_latch.addr + 1] << 16) | (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; + dat[1] = (svga->vram[svga->hwcursor_latch.addr + 4] << 24) | (svga->vram[svga->hwcursor_latch.addr + 5] << 16) | (svga->vram[svga->hwcursor_latch.addr + 6] << 8) | svga->vram[svga->hwcursor_latch.addr + 7]; + for (xx = 0; xx < 32; xx++) + { + if (offset >= svga->hwcursor_latch.x) + { + if (!(dat[0] & 0x80000000)) + ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x80000000) ? 0xffffff : 0; + else if (dat[1] & 0x80000000) + ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff; +// pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga_hwcursor_on, dat[0], dat[1]); + } + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + svga->hwcursor_latch.addr += 8; + + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 8; +} + +uint8_t tgui_pci_read(int func, int addr, void *p) +{ + tgui_t *tgui = (tgui_t *)p; + +// pclog("Trident PCI read %08X\n", addr); + + switch (addr) + { + case 0x00: return 0x23; /*Trident*/ + case 0x01: return 0x10; + + case 0x02: return 0x40; /*TGUI9440 (9682)*/ + case 0x03: return 0x94; + + case 0x04: return 0x03; /*Respond to IO and memory accesses*/ + + case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ + + case 0x08: return 0; /*Revision ID*/ + case 0x09: return 0; /*Programming interface*/ + + case 0x0a: return 0x01; /*Supports VGA interface, XGA compatible*/ + case 0x0b: return 0x03; + + case 0x10: return 0x00; /*Linear frame buffer address*/ + case 0x11: return 0x00; + case 0x12: return tgui->linear_base >> 16; + case 0x13: return tgui->linear_base >> 24; + + case 0x30: return 0x01; /*BIOS ROM address*/ + case 0x31: return 0x00; + case 0x32: return 0x0C; + case 0x33: return 0x00; + } + return 0; +} + +void tgui_pci_write(int func, int addr, uint8_t val, void *p) +{ + tgui_t *tgui = (tgui_t *)p; + svga_t *svga = &tgui->svga; + +// pclog("Trident PCI write %08X %02X\n", addr, val); + + switch (addr) + { + case 0x12: + tgui->linear_base = (tgui->linear_base & 0xff000000) | ((val & 0xe0) << 16); + tgui->linear_size = 2 << 20; + tgui->svga.decode_mask = 0x1fffff; + svga->crtc[0x21] = (svga->crtc[0x21] & ~0xf) | (val >> 4); + tgui_recalcmapping(tgui); + break; + case 0x13: + tgui->linear_base = (tgui->linear_base & 0xe00000) | (val << 24); + tgui->linear_size = 2 << 20; + tgui->svga.decode_mask = 0x1fffff; + svga->crtc[0x21] = (svga->crtc[0x21] & ~0xc0) | (val >> 6); + tgui_recalcmapping(tgui); + break; + } +} + +static void *tgui_init(char *bios_fn, int type, int mem_size) +{ + tgui_t *tgui = malloc(sizeof(tgui_t)); + memset(tgui, 0, sizeof(tgui_t)); + + if (mem_size) + tgui->vram_size = mem_size; + else + tgui->vram_size = device_get_config_int("memory") << 20; + tgui->vram_mask = tgui->vram_size - 1; + + tgui->type = type; + + rom_init(&tgui->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + svga_init(&tgui->svga, tgui, tgui->vram_size, + tgui_recalctimings, + tgui_in, tgui_out, + tgui_hwcursor_draw, + NULL); + + mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_accel_write_fb_b, tgui_accel_write_fb_w, tgui_accel_write_fb_l, NULL, 0, &tgui->svga); + mem_mapping_add(&tgui->accel_mapping, 0xbc000, 0x4000, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, NULL, 0, tgui); + mem_mapping_disable(&tgui->accel_mapping); + + io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + if (tgui->type >= TGUI_9440) + io_sethandler(0x43c8, 0x0002, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + + if (tgui->type >= TGUI_9440) + pci_add(tgui_pci_read, tgui_pci_write, tgui); + + tgui->wake_fifo_thread = thread_create_event(); + tgui->fifo_not_full_event = thread_create_event(); + tgui->fifo_thread = thread_create(fifo_thread, tgui); + + return tgui; +} + +static void *tgui9400cxi_init() +{ + return tgui_init("9400CXI.vbi", TGUI_9400CXI, 0); +} + +static void *tgui9400cxi_elx_init() +{ + /*Try combined ROM dump first. If not present, use seperated dump*/ + FILE *f = romfopen("elx_pc425x/elx_pc425x.bin", "rb"); + if (f) + { + fclose(f); + return tgui_init("elx_pc425x/elx_pc425x.bin", TGUI_9400CXI, 512 << 10); + } + + return tgui_init("elx_pc425x/elx_pc425x_vbios.bin", TGUI_9400CXI, 512 << 10); +} + +static void *tgui9440_init() +{ + return tgui_init("9440.vbi", TGUI_9440, 0); +} + +static int tgui9400cxi_available() +{ + return rom_present("9400CXI.vbi"); +} + +static int tgui9440_available() +{ + return rom_present("9440.vbi"); +} + +void tgui_close(void *p) +{ + tgui_t *tgui = (tgui_t *)p; + + svga_close(&tgui->svga); + + thread_kill(tgui->fifo_thread); + thread_destroy_event(tgui->wake_fifo_thread); + thread_destroy_event(tgui->fifo_not_full_event); + + free(tgui); +} + +void tgui_speed_changed(void *p) +{ + tgui_t *tgui = (tgui_t *)p; + + svga_recalctimings(&tgui->svga); +} + +void tgui_force_redraw(void *p) +{ + tgui_t *tgui = (tgui_t *)p; + + tgui->svga.fullchange = changeframecount; +} + + +static uint8_t tgui_ext_linear_read(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + tgui_t *tgui = (tgui_t *)svga->p; + int c; + + cycles -= video_timing_read_b; + cycles_lost += video_timing_read_b; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + + addr &= ~0xf; + for (c = 0; c < 16; c++) + tgui->copy_latch[c] = svga->vram[addr+c]; + + return svga->vram[addr & svga->vram_mask]; +} + +static uint8_t tgui_ext_read(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + + addr = (addr & svga->banked_mask) + svga->read_bank; + + return tgui_ext_linear_read(addr, svga); +} + +static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + tgui_t *tgui = (tgui_t *)svga->p; + int c; + uint8_t fg[2] = {tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5]}; + uint8_t bg[2] = {tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2]}; + uint8_t mask = tgui->ext_gdc_regs[7]; + + cycles -= video_timing_write_b; + cycles_lost += video_timing_write_b; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + addr &= ~0x7; + svga->changedvram[addr >> 12] = changeframecount; + + switch (tgui->ext_gdc_regs[0] & 0xf) + { + /*8-bit mono->colour expansion, unmasked*/ + case 2: + for (c = 7; c >= 0; c--) + { + if (mask & (1 << c)) + *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0]; + addr++; + } + break; + + /*16-bit mono->colour expansion, unmasked*/ + case 3: + for (c = 7; c >= 0; c--) + { + if (mask & (1 << c)) + *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1]; + addr++; + } + break; + + /*8-bit mono->colour expansion, masked*/ + case 6: + for (c = 7; c >= 0; c--) + { + if ((val & mask) & (1 << c)) + *(uint8_t *)&svga->vram[addr] = fg[0]; + addr++; + } + break; + + /*16-bit mono->colour expansion, masked*/ + case 7: + for (c = 7; c >= 0; c--) + { + if ((val & mask) & (1 << c)) + *(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1]; + addr++; + } + break; + + case 0x8: case 0x9: case 0xa: case 0xb: + case 0xc: case 0xd: case 0xe: case 0xf: + addr &= ~0xf; + for (c = 0; c < 16; c++) + *(uint8_t *)&svga->vram[addr+c] = tgui->copy_latch[c]; + break; + } +} + +static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + tgui_t *tgui = (tgui_t *)svga->p; + int c; + uint8_t fg[2] = {tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5]}; + uint8_t bg[2] = {tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2]}; + uint16_t mask = (tgui->ext_gdc_regs[7] << 8) | tgui->ext_gdc_regs[8]; + + cycles -= video_timing_write_w; + cycles_lost += video_timing_write_w; + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + addr &= ~0xf; + svga->changedvram[addr >> 12] = changeframecount; + + val = (val >> 8) | (val << 8); + + switch (tgui->ext_gdc_regs[0] & 0xf) + { + /*8-bit mono->colour expansion, unmasked*/ + case 2: + for (c = 15; c >= 0; c--) + { + if (mask & (1 << c)) + *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[0] : bg[0]; + addr++; + } + break; + + /*16-bit mono->colour expansion, unmasked*/ + case 3: + for (c = 15; c >= 0; c--) + { + if (mask & (1 << c)) + *(uint8_t *)&svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1]; + addr++; + } + break; + + /*8-bit mono->colour expansion, masked*/ + case 6: + for (c = 15; c >= 0; c--) + { + if ((val & mask) & (1 << c)) + *(uint8_t *)&svga->vram[addr] = fg[0]; + addr++; + } + break; + + /*16-bit mono->colour expansion, masked*/ + case 7: + for (c = 15; c >= 0; c--) + { + if ((val & mask) & (1 << c)) + *(uint8_t *)&svga->vram[addr] = fg[(c & 1) ^ 1]; + addr++; + } + break; + + case 0x8: case 0x9: case 0xa: case 0xb: + case 0xc: case 0xd: case 0xe: case 0xf: + for (c = 0; c < 16; c++) + *(uint8_t *)&svga->vram[addr+c] = tgui->copy_latch[c]; + break; + } +} + +static void tgui_ext_linear_writel(uint32_t addr, uint32_t val, void *p) +{ + tgui_ext_linear_writew(addr, val, p); +} + +static void tgui_ext_write(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + + addr = (addr & svga->banked_mask) + svga->read_bank; + + tgui_ext_linear_write(addr, val, svga); +} +static void tgui_ext_writew(uint32_t addr, uint16_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + + addr = (addr & svga->banked_mask) + svga->read_bank; + + tgui_ext_linear_writew(addr, val, svga); +} +static void tgui_ext_writel(uint32_t addr, uint32_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + + addr = (addr & svga->banked_mask) + svga->read_bank; + + tgui_ext_linear_writel(addr, val, svga); +} + + +enum +{ + TGUI_BITBLT = 1 +}; + +enum +{ + TGUI_SRCCPU = 0, + + TGUI_SRCDISP = 0x04, /*Source is from display*/ + TGUI_PATMONO = 0x20, /*Pattern is monochrome and needs expansion*/ + TGUI_SRCMONO = 0x40, /*Source is monochrome from CPU and needs expansion*/ + TGUI_TRANSENA = 0x1000, /*Transparent (no draw when source == bg col)*/ + TGUI_TRANSREV = 0x2000, /*Reverse fg/bg for transparent*/ + TGUI_SOLIDFILL = 0x4000 /*Pattern all zero?*/ +}; + +#define READ(addr, dat) if (tgui->accel.bpp == 0) dat = svga->vram[addr & 0x1fffff]; \ + else dat = vram_w[addr & 0xfffff]; + +#define MIX() do \ + { \ + out = 0; \ + for (c=0;c<16;c++) \ + { \ + d=(dst_dat & (1<accel.rop & (1<accel.bpp == 0) \ + { \ + svga->vram[addr & 0x1fffff] = dat; \ + svga->changedvram[((addr) & 0x1fffff) >> 12] = changeframecount; \ + } \ + else \ + { \ + vram_w[addr & 0xfffff] = dat; \ + svga->changedvram[((addr) & 0xfffff) >> 11] = changeframecount; \ + } + +void tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) +{ + svga_t *svga = &tgui->svga; + int x, y; + int c, d; + uint16_t src_dat, dst_dat, pat_dat; + uint16_t out; + int xdir = (tgui->accel.flags & 0x200) ? -1 : 1; + int ydir = (tgui->accel.flags & 0x100) ? -1 : 1; + uint16_t trans_col = (tgui->accel.flags & TGUI_TRANSREV) ? tgui->accel.fg_col : tgui->accel.bg_col; + uint16_t *vram_w = (uint16_t *)svga->vram; + + if (tgui->accel.bpp == 0) + trans_col &= 0xff; + + if (count != -1 && !tgui->accel.x && (tgui->accel.flags & TGUI_SRCMONO)) + { + count -= tgui->accel.offset; + cpu_dat <<= tgui->accel.offset; + } + if (count == -1) + { + tgui->accel.x = tgui->accel.y = 0; + } + if (tgui->accel.flags & TGUI_SOLIDFILL) + { +// pclog("SOLIDFILL\n"); + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + { + tgui->accel.tgui_pattern[y][x] = tgui->accel.fg_col; + } + } + } + else if (tgui->accel.flags & TGUI_PATMONO) + { +// pclog("PATMONO\n"); + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + { + tgui->accel.tgui_pattern[y][x] = (tgui->accel.pattern[y] & (1 << x)) ? tgui->accel.fg_col : tgui->accel.bg_col; + } + } + } + else + { + if (tgui->accel.bpp == 0) + { +// pclog("OTHER 8-bit\n"); + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + { + tgui->accel.tgui_pattern[y][x] = tgui->accel.pattern[x + y*8]; + } + } + } + else + { +// pclog("OTHER 16-bit\n"); + for (y = 0; y < 8; y++) + { + for (x = 0; x < 8; x++) + { + tgui->accel.tgui_pattern[y][x] = tgui->accel.pattern[x*2 + y*16] | (tgui->accel.pattern[x*2 + y*16 + 1] << 8); + } + } + } + } +/* for (y = 0; y < 8; y++) + { + if (count == -1) pclog("Pattern %i : %02X %02X %02X %02X %02X %02X %02X %02X\n", y, tgui->accel.tgui_pattern[y][0], tgui->accel.tgui_pattern[y][1], tgui->accel.tgui_pattern[y][2], tgui->accel.tgui_pattern[y][3], tgui->accel.tgui_pattern[y][4], tgui->accel.tgui_pattern[y][5], tgui->accel.tgui_pattern[y][6], tgui->accel.tgui_pattern[y][7]); + }*/ +// if (count == -1) pclog("Command %i %i %p\n", tgui->accel.command, TGUI_BITBLT, tgui); + switch (tgui->accel.command) + { + case TGUI_BITBLT: +// if (count == -1) pclog("BITBLT src %i,%i dst %i,%i size %i,%i flags %04X\n", tgui->accel.src_x, tgui->accel.src_y, tgui->accel.dst_x, tgui->accel.dst_y, tgui->accel.size_x, tgui->accel.size_y, tgui->accel.flags); + if (count == -1) + { + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch); + tgui->accel.pat_x = tgui->accel.dst_x; + tgui->accel.pat_y = tgui->accel.dst_y; + } + + switch (tgui->accel.flags & (TGUI_SRCMONO|TGUI_SRCDISP)) + { + case TGUI_SRCCPU: + if (count == -1) + { +// pclog("Blit start TGUI_SRCCPU\n"); + if (svga->crtc[0x21] & 0x20) + { + tgui->write_blitter = 1; + } + if (tgui->accel.use_src) + return; + } + else + count >>= 3; +// pclog("TGUI_SRCCPU\n"); + while (count) + { + if (tgui->accel.bpp == 0) + { + src_dat = cpu_dat >> 24; + cpu_dat <<= 8; + } + else + { + src_dat = (cpu_dat >> 24) | ((cpu_dat >> 8) & 0xff00); + cpu_dat <<= 16; + count--; + } + READ(tgui->accel.dst, dst_dat); + pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7]; + + if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) + { + MIX(); + + WRITE(tgui->accel.dst, out); + } + +// pclog(" %i,%i %02X %02X %02X %02X\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out); + + tgui->accel.src += xdir; + tgui->accel.dst += xdir; + tgui->accel.pat_x += xdir; + + tgui->accel.x++; + if (tgui->accel.x > tgui->accel.size_x) + { + tgui->accel.x = 0; + tgui->accel.y++; + + tgui->accel.pat_x = tgui->accel.dst_x; + + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); + tgui->accel.pat_y += ydir; + + if (tgui->accel.y > tgui->accel.size_y) + { + if (svga->crtc[0x21] & 0x20) + { + tgui->write_blitter = 0; + } + return; + } + if (tgui->accel.use_src) + return; + } + count--; + } + break; + + case TGUI_SRCMONO | TGUI_SRCCPU: + if (count == -1) + { +// pclog("Blit start TGUI_SRCMONO | TGUI_SRCCPU\n"); + if (svga->crtc[0x21] & 0x20) + { + tgui->write_blitter = 1; + } + +// pclog(" %i\n", tgui->accel.command); + if (tgui->accel.use_src) + return; + } +// pclog("TGUI_SRCMONO | TGUI_SRCCPU\n"); + while (count) + { + src_dat = ((cpu_dat >> 31) ? tgui->accel.fg_col : tgui->accel.bg_col); + if (tgui->accel.bpp == 0) + src_dat &= 0xff; + + READ(tgui->accel.dst, dst_dat); + pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7]; + + if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) + { + MIX(); + + WRITE(tgui->accel.dst, out); + } +// pclog(" %i,%i %02X %02X %02X %02X %i\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out, (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col)); + cpu_dat <<= 1; + tgui->accel.src += xdir; + tgui->accel.dst += xdir; + tgui->accel.pat_x += xdir; + + tgui->accel.x++; + if (tgui->accel.x > tgui->accel.size_x) + { + tgui->accel.x = 0; + tgui->accel.y++; + + tgui->accel.pat_x = tgui->accel.dst_x; + + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); + tgui->accel.pat_y += ydir; + + if (tgui->accel.y > tgui->accel.size_y) + { + if (svga->crtc[0x21] & 0x20) + { + tgui->write_blitter = 0; + } + return; + } + if (tgui->accel.use_src) + return; + } + count--; + } + break; + + default: + while (count) + { + READ(tgui->accel.src, src_dat); + READ(tgui->accel.dst, dst_dat); + pat_dat = tgui->accel.tgui_pattern[tgui->accel.pat_y & 7][tgui->accel.pat_x & 7]; + + if (!(tgui->accel.flags & TGUI_TRANSENA) || src_dat != trans_col) + { + MIX(); + + WRITE(tgui->accel.dst, out); + } +// pclog(" %i,%i %02X %02X %02X %02X\n", tgui->accel.x, tgui->accel.y, src_dat,dst_dat,pat_dat, out); + + tgui->accel.src += xdir; + tgui->accel.dst += xdir; + tgui->accel.pat_x += xdir; + + tgui->accel.x++; + if (tgui->accel.x > tgui->accel.size_x) + { + tgui->accel.x = 0; + tgui->accel.y++; + + tgui->accel.pat_x = tgui->accel.dst_x; + + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); + tgui->accel.pat_y += ydir; + + if (tgui->accel.y > tgui->accel.size_y) + return; + } + count--; + } + break; + } + break; + } +} + +static void tgui_accel_write_fifo(tgui_t *tgui, uint32_t addr, uint8_t val) +{ + switch (addr & 0xff) + { + case 0x22: + tgui->accel.ger22 = val; + tgui->accel.pitch = 512 << ((val >> 2) & 3); + tgui->accel.bpp = (val & 3) ? 1 : 0; + tgui->accel.pitch >>= tgui->accel.bpp; + break; + + case 0x24: /*Command*/ + tgui->accel.command = val; + tgui_accel_command(-1, 0, tgui); + break; + + case 0x27: /*ROP*/ + tgui->accel.rop = val; + tgui->accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33); +// pclog("Write ROP %02X %i\n", val, tgui->accel.use_src); + break; + + case 0x28: /*Flags*/ + tgui->accel.flags = (tgui->accel.flags & 0xff00) | val; + break; + case 0x29: /*Flags*/ + tgui->accel.flags = (tgui->accel.flags & 0xff) | (val << 8); + break; + + case 0x2b: + tgui->accel.offset = val & 7; + break; + + case 0x2c: /*Foreground colour*/ + tgui->accel.fg_col = (tgui->accel.fg_col & 0xff00) | val; + break; + case 0x2d: /*Foreground colour*/ + tgui->accel.fg_col = (tgui->accel.fg_col & 0xff) | (val << 8); + break; + + case 0x30: /*Background colour*/ + tgui->accel.bg_col = (tgui->accel.bg_col & 0xff00) | val; + break; + case 0x31: /*Background colour*/ + tgui->accel.bg_col = (tgui->accel.bg_col & 0xff) | (val << 8); + break; + + case 0x38: /*Dest X*/ + tgui->accel.dst_x = (tgui->accel.dst_x & 0xff00) | val; + break; + case 0x39: /*Dest X*/ + tgui->accel.dst_x = (tgui->accel.dst_x & 0xff) | (val << 8); + break; + case 0x3a: /*Dest Y*/ + tgui->accel.dst_y = (tgui->accel.dst_y & 0xff00) | val; + break; + case 0x3b: /*Dest Y*/ + tgui->accel.dst_y = (tgui->accel.dst_y & 0xff) | (val << 8); + break; + + case 0x3c: /*Src X*/ + tgui->accel.src_x = (tgui->accel.src_x & 0xff00) | val; + break; + case 0x3d: /*Src X*/ + tgui->accel.src_x = (tgui->accel.src_x & 0xff) | (val << 8); + break; + case 0x3e: /*Src Y*/ + tgui->accel.src_y = (tgui->accel.src_y & 0xff00) | val; + break; + case 0x3f: /*Src Y*/ + tgui->accel.src_y = (tgui->accel.src_y & 0xff) | (val << 8); + break; + + case 0x40: /*Size X*/ + tgui->accel.size_x = (tgui->accel.size_x & 0xff00) | val; + break; + case 0x41: /*Size X*/ + tgui->accel.size_x = (tgui->accel.size_x & 0xff) | (val << 8); + break; + case 0x42: /*Size Y*/ + tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val; + break; + case 0x43: /*Size Y*/ + tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8); + break; + + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + tgui->accel.pattern[addr & 0x7f] = val; + break; + } +} + +static void tgui_accel_write_fifo_fb_b(tgui_t *tgui, uint32_t addr, uint8_t val) +{ + tgui_accel_command(8, val << 24, tgui); +} +static void tgui_accel_write_fifo_fb_w(tgui_t *tgui, uint32_t addr, uint16_t val) +{ + tgui_accel_command(16, (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)) << 16, tgui); +} +static void tgui_accel_write_fifo_fb_l(tgui_t *tgui, uint32_t addr, uint32_t val) +{ + tgui_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), tgui); +} + +static void fifo_thread(void *param) +{ + tgui_t *tgui = (tgui_t *)param; + + while (1) + { + thread_set_event(tgui->fifo_not_full_event); + thread_wait_event(tgui->wake_fifo_thread, -1); + thread_reset_event(tgui->wake_fifo_thread); + tgui->blitter_busy = 1; + while (!FIFO_EMPTY) + { + uint64_t start_time = timer_read(); + uint64_t end_time; + fifo_entry_t *fifo = &tgui->fifo[tgui->fifo_read_idx & FIFO_MASK]; + + switch (fifo->addr_type & FIFO_TYPE) + { + case FIFO_WRITE_BYTE: + tgui_accel_write_fifo(tgui, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_FB_BYTE: + tgui_accel_write_fifo_fb_b(tgui, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_FB_WORD: + tgui_accel_write_fifo_fb_w(tgui, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_FB_LONG: + tgui_accel_write_fifo_fb_l(tgui, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + } + + tgui->fifo_read_idx++; + fifo->addr_type = FIFO_INVALID; + + if (FIFO_ENTRIES > 0xe000) + thread_set_event(tgui->fifo_not_full_event); + + end_time = timer_read(); + tgui->blitter_time += end_time - start_time; + } + tgui->blitter_busy = 0; + } +} + +static inline void wake_fifo_thread(tgui_t *tgui) +{ + thread_set_event(tgui->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ +} + +static void tgui_wait_fifo_idle(tgui_t *tgui) +{ + while (!FIFO_EMPTY) + { + wake_fifo_thread(tgui); + thread_wait_event(tgui->fifo_not_full_event, 1); + } +} + +static void tgui_queue(tgui_t *tgui, uint32_t addr, uint32_t val, uint32_t type) +{ + fifo_entry_t *fifo = &tgui->fifo[tgui->fifo_write_idx & FIFO_MASK]; + + if (FIFO_FULL) + { + thread_reset_event(tgui->fifo_not_full_event); + if (FIFO_FULL) + { + thread_wait_event(tgui->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + } + + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; + + tgui->fifo_write_idx++; + + if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) + wake_fifo_thread(tgui); +} + + +void tgui_accel_write(uint32_t addr, uint8_t val, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_write : %08X %02X %04X(%08X):%08X %02X\n", addr, val, CS,cs,pc, opcode); + if ((addr & ~0xff) != 0xbff00) + return; + tgui_queue(tgui, addr, val, FIFO_WRITE_BYTE); +} + +void tgui_accel_write_w(uint32_t addr, uint16_t val, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_write_w %08X %04X\n", addr, val); + tgui_accel_write(addr, val, tgui); + tgui_accel_write(addr + 1, val >> 8, tgui); +} + +void tgui_accel_write_l(uint32_t addr, uint32_t val, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_write_l %08X %08X\n", addr, val); + tgui_accel_write(addr, val, tgui); + tgui_accel_write(addr + 1, val >> 8, tgui); + tgui_accel_write(addr + 2, val >> 16, tgui); + tgui_accel_write(addr + 3, val >> 24, tgui); +} + +uint8_t tgui_accel_read(uint32_t addr, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_read : %08X\n", addr); + if ((addr & ~0xff) != 0xbff00) + return 0xff; + if ((addr & 0xff) != 0x20) + tgui_wait_fifo_idle(tgui); + switch (addr & 0xff) + { + case 0x20: /*Status*/ + if (!FIFO_EMPTY) + return 1 << 5; + return 0; + + case 0x27: /*ROP*/ + return tgui->accel.rop; + + case 0x28: /*Flags*/ + return tgui->accel.flags & 0xff; + case 0x29: /*Flags*/ + return tgui->accel.flags >> 8; + + case 0x2b: + return tgui->accel.offset; + + case 0x2c: /*Background colour*/ + return tgui->accel.bg_col & 0xff; + case 0x2d: /*Background colour*/ + return tgui->accel.bg_col >> 8; + + case 0x30: /*Foreground colour*/ + return tgui->accel.fg_col & 0xff; + case 0x31: /*Foreground colour*/ + return tgui->accel.fg_col >> 8; + + case 0x38: /*Dest X*/ + return tgui->accel.dst_x & 0xff; + case 0x39: /*Dest X*/ + return tgui->accel.dst_x >> 8; + case 0x3a: /*Dest Y*/ + return tgui->accel.dst_y & 0xff; + case 0x3b: /*Dest Y*/ + return tgui->accel.dst_y >> 8; + + case 0x3c: /*Src X*/ + return tgui->accel.src_x & 0xff; + case 0x3d: /*Src X*/ + return tgui->accel.src_x >> 8; + case 0x3e: /*Src Y*/ + return tgui->accel.src_y & 0xff; + case 0x3f: /*Src Y*/ + return tgui->accel.src_y >> 8; + + case 0x40: /*Size X*/ + return tgui->accel.size_x & 0xff; + case 0x41: /*Size X*/ + return tgui->accel.size_x >> 8; + case 0x42: /*Size Y*/ + return tgui->accel.size_y & 0xff; + case 0x43: /*Size Y*/ + return tgui->accel.size_y >> 8; + + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8a: case 0x8b: + case 0x8c: case 0x8d: case 0x8e: case 0x8f: + case 0x90: case 0x91: case 0x92: case 0x93: + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9a: case 0x9b: + case 0x9c: case 0x9d: case 0x9e: case 0x9f: + case 0xa0: case 0xa1: case 0xa2: case 0xa3: + case 0xa4: case 0xa5: case 0xa6: case 0xa7: + case 0xa8: case 0xa9: case 0xaa: case 0xab: + case 0xac: case 0xad: case 0xae: case 0xaf: + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + case 0xb4: case 0xb5: case 0xb6: case 0xb7: + case 0xb8: case 0xb9: case 0xba: case 0xbb: + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + case 0xc0: case 0xc1: case 0xc2: case 0xc3: + case 0xc4: case 0xc5: case 0xc6: case 0xc7: + case 0xc8: case 0xc9: case 0xca: case 0xcb: + case 0xcc: case 0xcd: case 0xce: case 0xcf: + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + case 0xe0: case 0xe1: case 0xe2: case 0xe3: + case 0xe4: case 0xe5: case 0xe6: case 0xe7: + case 0xe8: case 0xe9: case 0xea: case 0xeb: + case 0xec: case 0xed: case 0xee: case 0xef: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + case 0xfc: case 0xfd: case 0xfe: case 0xff: + return tgui->accel.pattern[addr & 0x7f]; + } + return 0xff; +} + +uint16_t tgui_accel_read_w(uint32_t addr, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_read_w %08X\n", addr); + return tgui_accel_read(addr, tgui) | (tgui_accel_read(addr + 1, tgui) << 8); +} + +uint32_t tgui_accel_read_l(uint32_t addr, void *p) +{ + tgui_t *tgui = (tgui_t *)p; +// pclog("tgui_accel_read_l %08X\n", addr); + return tgui_accel_read_w(addr, tgui) | (tgui_accel_read_w(addr + 2, tgui) << 16); +} + +void tgui_accel_write_fb_b(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + tgui_t *tgui = (tgui_t *)svga->p; + + if (tgui->write_blitter) + tgui_queue(tgui, addr, val, FIFO_WRITE_FB_BYTE); + else + svga_write_linear(addr, val, svga); +} + +void tgui_accel_write_fb_w(uint32_t addr, uint16_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + tgui_t *tgui = (tgui_t *)svga->p; + + if (tgui->write_blitter) + tgui_queue(tgui, addr, val, FIFO_WRITE_FB_WORD); + else + svga_writew_linear(addr, val, svga); +} + +void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + tgui_t *tgui = (tgui_t *)svga->p; + + if (tgui->write_blitter) + tgui_queue(tgui, addr, val, FIFO_WRITE_FB_LONG); + else + svga_writel_linear(addr, val, svga); +} + +void tgui_add_status_info(char *s, int max_len, void *p) +{ + tgui_t *tgui = (tgui_t *)p; + char temps[256]; + uint64_t new_time = timer_read(); + uint64_t status_diff = new_time - tgui->status_time; + tgui->status_time = new_time; + + svga_add_status_info(s, max_len, &tgui->svga); + + sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)tgui->blitter_time * 100.0) / timer_freq, ((double)tgui->blitter_time * 100.0) / status_diff); + strncat(s, temps, max_len); + + tgui->blitter_time = 0; +} + +static device_config_t tgui9440_config[] = +{ + { + NULL, + NULL, + -1, + } +}; + +device_t tgui9400cxi_device = +{ + "Trident TGUI 9400CXi", + 0, + tgui9400cxi_init, + tgui_close, + tgui9400cxi_available, + tgui_speed_changed, + tgui_force_redraw, + tgui_add_status_info, + tgui9440_config +}; + +device_t tgui9400cxi_elx_device = +{ + "Trident TGUI 9400CXi (Elonex PC-425X)", + 0, + tgui9400cxi_elx_init, + tgui_close, + tgui9400cxi_available, + tgui_speed_changed, + tgui_force_redraw, + tgui_add_status_info, + tgui9440_config +}; + +device_t tgui9440_device = +{ + "Trident TGUI 9440", + 0, + tgui9440_init, + tgui_close, + tgui9440_available, + tgui_speed_changed, + tgui_force_redraw, + tgui_add_status_info, + tgui9440_config +}; + + #endif \ No newline at end of file diff --git a/wab/tgui9680_wrapper.h b/wab/tgui9680_wrapper.h index f4e62ac8..fc47067d 100644 --- a/wab/tgui9680_wrapper.h +++ b/wab/tgui9680_wrapper.h @@ -1,308 +1,308 @@ -#pragma once - -#if defined(SUPPORT_TRIDENT_TGUI) - -typedef unsigned long long int uint64_t; -typedef unsigned long int uint32_t; -typedef unsigned short int uint16_t; -typedef unsigned char uint8_t; -typedef signed long long int int64_t; -typedef signed long int int32_t; -typedef signed short int int16_t; -typedef signed char int8_t; - -typedef struct mem_mapping_t -{ - struct mem_mapping_t *prev, *next; - - int enable; - - uint32_t base; - uint32_t size; - - uint8_t (*read_b)(uint32_t addr, void *priv); - uint16_t (*read_w)(uint32_t addr, void *priv); - uint32_t (*read_l)(uint32_t addr, void *priv); - void (*write_b)(uint32_t addr, uint8_t val, void *priv); - void (*write_w)(uint32_t addr, uint16_t val, void *priv); - void (*write_l)(uint32_t addr, uint32_t val, void *priv); - - uint8_t *exec; - - uint32_t flags; - - void *p; -} mem_mapping_t; - -typedef struct rom_t -{ - uint8_t *rom; - uint32_t mask; - mem_mapping_t mapping; -} rom_t; - -typedef struct -{ - uint8_t r, g, b; -} RGB; -typedef RGB PALETTE[256]; - -typedef struct pc_timer_t -{ - uint32_t ts_integer; - uint32_t ts_frac; - int enabled; - - void (*callback)(void *p); - void *p; - - struct pc_timer_t *prev, *next; -} pc_timer_t; - -typedef struct svga_t -{ - mem_mapping_t mapping; - - uint8_t crtcreg; - uint8_t crtc[128]; - uint8_t gdcreg[64]; - int gdcaddr; - uint8_t attrregs[32]; - int attraddr, attrff; - int attr_palette_enable; - uint8_t seqregs[64]; - int seqaddr; - - uint8_t miscout; - int vidclock; - - /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : - 0MB-1MB - VRAM - 1MB-2MB - VRAM mirror - 2MB-4MB - open bus - 4MB-xMB - mirror of above - - For the example memory map, decode_mask would be 4MB-1 (4MB address space), vram_max would be 2MB - (present video memory only responds to first 2MB), vram_mask would be 1MB-1 (video memory wraps at 1MB) - */ - uint32_t decode_mask; - uint32_t vram_max; - uint32_t vram_mask; - - uint8_t la, lb, lc, ld; - - uint8_t dac_mask, dac_status; - int dac_read, dac_write, dac_pos; - int dac_r, dac_g; - - uint8_t cgastat; - - uint8_t plane_mask; - - int fb_only; - - int fast; - uint8_t colourcompare, colournocare; - int readmode, writemode, readplane; - int chain4, chain2_write, chain2_read; - uint8_t writemask; - uint32_t charseta, charsetb; - - int set_reset_disabled; - - uint8_t egapal[16]; - uint32_t pallook[256]; - PALETTE vgapal; - - int ramdac_type; - - int vtotal, dispend, vsyncstart, split, vblankstart; - int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; - int lowres, interlace; - int linedbl, rowcount; - double clock; - uint32_t ma_latch; - int bpp; - - uint64_t dispontime, dispofftime; - pc_timer_t timer; - - uint8_t scrblank; - - int dispon; - int hdisp_on; - - uint32_t ma, maback, ca; - int vc; - int sc; - int linepos, vslines, linecountff, oddeven; - int con, cursoron, blink; - int scrollcache; - int char_width; - - int firstline, lastline; - int firstline_draw, lastline_draw; - int displine; - - uint8_t *vram; - uint8_t *changedvram; - uint32_t vram_display_mask; - uint32_t banked_mask; - - uint32_t write_bank, read_bank; - - int fullchange; - - int video_res_x, video_res_y, video_bpp; - int frames, fps; - - struct - { - int ena; - int x, y; - int xoff, yoff; - int xsize, ysize; - uint32_t addr; - uint32_t pitch; - int v_acc, h_acc; - } hwcursor, hwcursor_latch, overlay, overlay_latch; - - int hwcursor_on; - int overlay_on; - - int hwcursor_oddeven; - int overlay_oddeven; - - void (*render)(struct svga_t *svga); - void (*recalctimings_ex)(struct svga_t *svga); - - void (*video_out)(uint16_t addr, uint8_t val, void *p); - uint8_t (*video_in) (uint16_t addr, void *p); - - void (*hwcursor_draw)(struct svga_t *svga, int displine); - - void (*overlay_draw)(struct svga_t *svga, int displine); - - void (*vblank_start)(struct svga_t *svga); - - /*Called when VC=R18 and friends. If this returns zero then MA resetting - is skipped. Matrox Mystique in Power mode reuses this counter for - vertical line interrupt*/ - int (*line_compare)(struct svga_t *svga); - - /*Called at the start of vertical sync*/ - void (*vsync_callback)(struct svga_t *svga); - - /*If set then another device is driving the monitor output and the SVGA - card should not attempt to display anything */ - int override; - void *p; - - uint8_t ksc5601_sbyte_mask; - - int vertical_linedbl; - - /*Used to implement CRTC[0x17] bit 2 hsync divisor*/ - int hsync_divisor; -} svga_t; - -typedef struct tkd8001_ramdac_t -{ - int state; - uint8_t ctrl; -} tkd8001_ramdac_t; - -typedef void thread_t; -typedef void event_t; - -#define CONFIG_SELECTION 3 - -typedef struct device_config_selection_t -{ - char description[256]; - int value; -} device_config_selection_t; - -typedef struct device_config_t -{ - char name[256]; - char description[256]; - int type; - char default_string[256]; - int default_int; - device_config_selection_t selection[16]; -} device_config_t; - -typedef struct device_t -{ - char name[50]; - uint32_t flags; - void *(*init)(); - void (*close)(void *p); - int (*available)(); - void (*speed_changed)(void *p); - void (*force_redraw)(void *p); - void (*add_status_info)(char *s, int max_len, void *p); - device_config_t *config; -} device_t; - - -// function - -void tkd8001_ramdac_out(uint16_t addr, uint8_t val, tkd8001_ramdac_t *ramdac, svga_t *svga) -{ -// pclog("OUT RAMDAC %04X %02X %04X:%04X\n",addr,val,CS,pc); - switch (addr) - { - case 0x3C6: - if (ramdac->state == 4) - { - ramdac->state = 0; - ramdac->ctrl = val; - switch (val >> 5) - { - case 0: case 1: case 2: case 3: - svga->bpp = 8; - break; - case 5: - svga->bpp = 15; - break; - case 6: - svga->bpp = 24; - break; - case 7: - svga->bpp = 16; - break; - } - return; - } - // tkd8001_state = 0; - break; - case 0x3C7: case 0x3C8: case 0x3C9: - ramdac->state = 0; - break; - } - svga_out(addr, val, svga); -} - -uint8_t tkd8001_ramdac_in(uint16_t addr, tkd8001_ramdac_t *ramdac, svga_t *svga) -{ -// pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc); - switch (addr) - { - case 0x3C6: - if (ramdac->state == 4) - { - //tkd8001_state = 0; - return ramdac->ctrl; - } - ramdac->state++; - break; - case 0x3C7: case 0x3C8: case 0x3C9: - ramdac->state = 0; - break; - } - return svga_in(addr, svga); -} - -#endif +#pragma once + +#if defined(SUPPORT_TRIDENT_TGUI) + +typedef unsigned long long int uint64_t; +typedef unsigned long int uint32_t; +typedef unsigned short int uint16_t; +typedef unsigned char uint8_t; +typedef signed long long int int64_t; +typedef signed long int int32_t; +typedef signed short int int16_t; +typedef signed char int8_t; + +typedef struct mem_mapping_t +{ + struct mem_mapping_t *prev, *next; + + int enable; + + uint32_t base; + uint32_t size; + + uint8_t (*read_b)(uint32_t addr, void *priv); + uint16_t (*read_w)(uint32_t addr, void *priv); + uint32_t (*read_l)(uint32_t addr, void *priv); + void (*write_b)(uint32_t addr, uint8_t val, void *priv); + void (*write_w)(uint32_t addr, uint16_t val, void *priv); + void (*write_l)(uint32_t addr, uint32_t val, void *priv); + + uint8_t *exec; + + uint32_t flags; + + void *p; +} mem_mapping_t; + +typedef struct rom_t +{ + uint8_t *rom; + uint32_t mask; + mem_mapping_t mapping; +} rom_t; + +typedef struct +{ + uint8_t r, g, b; +} RGB; +typedef RGB PALETTE[256]; + +typedef struct pc_timer_t +{ + uint32_t ts_integer; + uint32_t ts_frac; + int enabled; + + void (*callback)(void *p); + void *p; + + struct pc_timer_t *prev, *next; +} pc_timer_t; + +typedef struct svga_t +{ + mem_mapping_t mapping; + + uint8_t crtcreg; + uint8_t crtc[128]; + uint8_t gdcreg[64]; + int gdcaddr; + uint8_t attrregs[32]; + int attraddr, attrff; + int attr_palette_enable; + uint8_t seqregs[64]; + int seqaddr; + + uint8_t miscout; + int vidclock; + + /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : + 0MB-1MB - VRAM + 1MB-2MB - VRAM mirror + 2MB-4MB - open bus + 4MB-xMB - mirror of above + + For the example memory map, decode_mask would be 4MB-1 (4MB address space), vram_max would be 2MB + (present video memory only responds to first 2MB), vram_mask would be 1MB-1 (video memory wraps at 1MB) + */ + uint32_t decode_mask; + uint32_t vram_max; + uint32_t vram_mask; + + uint8_t la, lb, lc, ld; + + uint8_t dac_mask, dac_status; + int dac_read, dac_write, dac_pos; + int dac_r, dac_g; + + uint8_t cgastat; + + uint8_t plane_mask; + + int fb_only; + + int fast; + uint8_t colourcompare, colournocare; + int readmode, writemode, readplane; + int chain4, chain2_write, chain2_read; + uint8_t writemask; + uint32_t charseta, charsetb; + + int set_reset_disabled; + + uint8_t egapal[16]; + uint32_t pallook[256]; + PALETTE vgapal; + + int ramdac_type; + + int vtotal, dispend, vsyncstart, split, vblankstart; + int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; + int lowres, interlace; + int linedbl, rowcount; + double clock; + uint32_t ma_latch; + int bpp; + + uint64_t dispontime, dispofftime; + pc_timer_t timer; + + uint8_t scrblank; + + int dispon; + int hdisp_on; + + uint32_t ma, maback, ca; + int vc; + int sc; + int linepos, vslines, linecountff, oddeven; + int con, cursoron, blink; + int scrollcache; + int char_width; + + int firstline, lastline; + int firstline_draw, lastline_draw; + int displine; + + uint8_t *vram; + uint8_t *changedvram; + uint32_t vram_display_mask; + uint32_t banked_mask; + + uint32_t write_bank, read_bank; + + int fullchange; + + int video_res_x, video_res_y, video_bpp; + int frames, fps; + + struct + { + int ena; + int x, y; + int xoff, yoff; + int xsize, ysize; + uint32_t addr; + uint32_t pitch; + int v_acc, h_acc; + } hwcursor, hwcursor_latch, overlay, overlay_latch; + + int hwcursor_on; + int overlay_on; + + int hwcursor_oddeven; + int overlay_oddeven; + + void (*render)(struct svga_t *svga); + void (*recalctimings_ex)(struct svga_t *svga); + + void (*video_out)(uint16_t addr, uint8_t val, void *p); + uint8_t (*video_in) (uint16_t addr, void *p); + + void (*hwcursor_draw)(struct svga_t *svga, int displine); + + void (*overlay_draw)(struct svga_t *svga, int displine); + + void (*vblank_start)(struct svga_t *svga); + + /*Called when VC=R18 and friends. If this returns zero then MA resetting + is skipped. Matrox Mystique in Power mode reuses this counter for + vertical line interrupt*/ + int (*line_compare)(struct svga_t *svga); + + /*Called at the start of vertical sync*/ + void (*vsync_callback)(struct svga_t *svga); + + /*If set then another device is driving the monitor output and the SVGA + card should not attempt to display anything */ + int override; + void *p; + + uint8_t ksc5601_sbyte_mask; + + int vertical_linedbl; + + /*Used to implement CRTC[0x17] bit 2 hsync divisor*/ + int hsync_divisor; +} svga_t; + +typedef struct tkd8001_ramdac_t +{ + int state; + uint8_t ctrl; +} tkd8001_ramdac_t; + +typedef void thread_t; +typedef void event_t; + +#define CONFIG_SELECTION 3 + +typedef struct device_config_selection_t +{ + char description[256]; + int value; +} device_config_selection_t; + +typedef struct device_config_t +{ + char name[256]; + char description[256]; + int type; + char default_string[256]; + int default_int; + device_config_selection_t selection[16]; +} device_config_t; + +typedef struct device_t +{ + char name[50]; + uint32_t flags; + void *(*init)(); + void (*close)(void *p); + int (*available)(); + void (*speed_changed)(void *p); + void (*force_redraw)(void *p); + void (*add_status_info)(char *s, int max_len, void *p); + device_config_t *config; +} device_t; + + +// function + +void tkd8001_ramdac_out(uint16_t addr, uint8_t val, tkd8001_ramdac_t *ramdac, svga_t *svga) +{ +// pclog("OUT RAMDAC %04X %02X %04X:%04X\n",addr,val,CS,pc); + switch (addr) + { + case 0x3C6: + if (ramdac->state == 4) + { + ramdac->state = 0; + ramdac->ctrl = val; + switch (val >> 5) + { + case 0: case 1: case 2: case 3: + svga->bpp = 8; + break; + case 5: + svga->bpp = 15; + break; + case 6: + svga->bpp = 24; + break; + case 7: + svga->bpp = 16; + break; + } + return; + } + // tkd8001_state = 0; + break; + case 0x3C7: case 0x3C8: case 0x3C9: + ramdac->state = 0; + break; + } + svga_out(addr, val, svga); +} + +uint8_t tkd8001_ramdac_in(uint16_t addr, tkd8001_ramdac_t *ramdac, svga_t *svga) +{ +// pclog("IN RAMDAC %04X %04X:%04X\n",addr,CS,pc); + switch (addr) + { + case 0x3C6: + if (ramdac->state == 4) + { + //tkd8001_state = 0; + return ramdac->ctrl; + } + ramdac->state++; + break; + case 0x3C7: case 0x3C8: case 0x3C9: + ramdac->state = 0; + break; + } + return svga_in(addr, svga); +} + +#endif diff --git a/wab/vga_int.h b/wab/vga_int.h old mode 100755 new mode 100644 index 0cf44ff3..16b1fe60 --- a/wab/vga_int.h +++ b/wab/vga_int.h @@ -1,523 +1,523 @@ -/* - * QEMU internal VGA defines. - * - * Copyright (c) 2003-2004 Fabrice Bellard - * - * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#define MSR_COLOR_EMULATION 0x01 -#define MSR_PAGE_SELECT 0x20 - -#define ST01_V_RETRACE 0x08 -#define ST01_DISP_ENABLE 0x01 - -/* bochs VBE support */ -#define CONFIG_BOCHS_VBE - -#define VBE_DISPI_MAX_XRES 1600 -#define VBE_DISPI_MAX_YRES 1200 -#define VBE_DISPI_MAX_BPP 32 - -#define VBE_DISPI_INDEX_ID 0x0 -#define VBE_DISPI_INDEX_XRES 0x1 -#define VBE_DISPI_INDEX_YRES 0x2 -#define VBE_DISPI_INDEX_BPP 0x3 -#define VBE_DISPI_INDEX_ENABLE 0x4 -#define VBE_DISPI_INDEX_BANK 0x5 -#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 -#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 -#define VBE_DISPI_INDEX_X_OFFSET 0x8 -#define VBE_DISPI_INDEX_Y_OFFSET 0x9 -#define VBE_DISPI_INDEX_NB 0xa - -#define VBE_DISPI_ID0 0xB0C0 -#define VBE_DISPI_ID1 0xB0C1 -#define VBE_DISPI_ID2 0xB0C2 -#define VBE_DISPI_ID3 0xB0C3 -#define VBE_DISPI_ID4 0xB0C4 - -#define VBE_DISPI_DISABLED 0x00 -#define VBE_DISPI_ENABLED 0x01 -#define VBE_DISPI_GETCAPS 0x02 -#define VBE_DISPI_8BIT_DAC 0x20 -#define VBE_DISPI_LFB_ENABLED 0x40 -#define VBE_DISPI_NOCLEARMEM 0x80 - -#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 - -#ifdef CONFIG_BOCHS_VBE - -#define VGA_STATE_COMMON_BOCHS_VBE \ - uint16_t_ vbe_index; \ - uint16_t_ vbe_regs[VBE_DISPI_INDEX_NB]; \ - uint32_t_ vbe_start_addr; \ - uint32_t_ vbe_line_offset; \ - uint32_t_ vbe_bank_mask; - -#else - -#define VGA_STATE_COMMON_BOCHS_VBE - -#endif /* !CONFIG_BOCHS_VBE */ - -#define CH_ATTR_SIZE (160 * 100) -#define VGA_MAX_HEIGHT 2048 - -struct vga_precise_retrace { - int64_t ticks_per_char; - int64_t total_chars; - int htotal; - int hstart; - int hend; - int vstart; - int vend; - int freq; -}; - -union vga_retrace { - struct vga_precise_retrace precise; -}; - -struct VGAState; -typedef uint8_t (* vga_retrace_fn)(struct VGAState *s); -typedef void (* vga_update_retrace_info_fn)(struct VGAState *s); - -#define VGA_STATE_COMMON \ - uint8_t *vram_ptr; \ - ram_addr_t vram_offset; \ - unsigned int vram_size; \ - uint32_t_ lfb_addr; \ - uint32_t_ lfb_end; \ - uint32_t_ map_addr; \ - uint32_t_ map_end; \ - uint32_t_ lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */ \ - unsigned long bios_offset; \ - unsigned int bios_size; \ - int it_shift; \ - /*PCIDevice *pci_dev;*/ \ - uint32_t_ latch; \ - uint8_t sr_index; \ - uint8_t sr[256]; \ - uint8_t gr_index; \ - uint8_t gr[256]; \ - uint8_t ar_index; \ - uint8_t ar[21]; \ - int ar_flip_flop; \ - uint8_t cr_index; \ - uint8_t cr[256]; /* CRT registers */ \ - uint8_t msr; /* Misc Output Register */ \ - uint8_t fcr; /* Feature Control Register */ \ - uint8_t st00; /* status 0 */ \ - uint8_t st01; /* status 1 */ \ - uint8_t dac_state; \ - uint8_t dac_sub_index; \ - uint8_t dac_read_index; \ - uint8_t dac_write_index; \ - uint8_t dac_cache[3]; /* used when writing */ \ - int dac_8bit; \ - uint8_t palette[768]; \ - int32_t bank_offset; \ - int vga_io_memory; \ - int (*get_bpp)(struct VGAState *s); \ - void (*get_offsets)(struct VGAState *s, \ - uint32_t_ *pline_offset, \ - uint32_t_ *pstart_addr, \ - uint32_t_ *pline_compare); \ - void (*get_resolution)(struct VGAState *s, \ - int *pwidth, \ - int *pheight); \ - VGA_STATE_COMMON_BOCHS_VBE \ - /* display refresh support */ \ - DisplayState *ds; \ - uint32_t_ font_offsets[2]; \ - int graphic_mode; \ - uint8_t shift_control; \ - uint8_t double_scan; \ - uint32_t_ line_offset; \ - uint32_t_ line_compare; \ - uint32_t_ start_addr; \ - uint32_t_ plane_updated; \ - uint32_t_ last_line_offset; \ - uint8_t last_cw, last_ch; \ - uint32_t_ last_width, last_height; /* in chars or pixels */ \ - uint32_t_ last_scr_width, last_scr_height; /* in pixels */ \ - uint32_t_ last_depth; /* in bits */ \ - uint8_t cursor_start, cursor_end; \ - uint32_t_ cursor_offset; \ - unsigned int (*rgb_to_pixel)(unsigned int r, \ - unsigned int g, unsigned b); \ - vga_hw_update_ptr update; \ - vga_hw_invalidate_ptr invalidate; \ - vga_hw_screen_dump_ptr screen_dump; \ - vga_hw_text_update_ptr text_update; \ - /* hardware mouse cursor support */ \ - uint32_t_ invalidated_y_table[VGA_MAX_HEIGHT / 32]; \ - void (*cursor_invalidate)(struct VGAState *s); \ - void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y); \ - /* tell for each page if it has been updated since the last time */ \ - uint32_t_ last_palette[256]; \ - uint32_t_ last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ \ - /* retrace */ \ - vga_retrace_fn retrace; \ - vga_update_retrace_info_fn update_retrace_info; \ - union vga_retrace retrace_info; - - -typedef struct VGAState { - VGA_STATE_COMMON -} VGAState; - -typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, const uint8_t *s, int width); - -static int c6_to_8(int v) -{ - int b; - v &= 0x3f; - b = v & 1; - return (v << 2) | (b << 1) | b; -} - -void vga_common_init(VGAState *s, uint8_t *vga_ram_base, ram_addr_t vga_ram_offset, int vga_ram_size){} -void vga_init(VGAState *s){} -void vga_reset(void *s){} - -void vga_dirty_log_start(VGAState *s){} -void vga_dirty_log_stop(VGAState *s){} - -#define cbswap_32(__x) \ -((uint32_t_)( \ - (((uint32_t_)(__x) & (uint32_t_)0x000000ffUL) << 24) | \ - (((uint32_t_)(__x) & (uint32_t_)0x0000ff00UL) << 8) | \ - (((uint32_t_)(__x) & (uint32_t_)0x00ff0000UL) >> 8) | \ - (((uint32_t_)(__x) & (uint32_t_)0xff000000UL) >> 24) )) - -#ifdef WORDS_BIGENDIAN -#define PAT(x) x -#else -#define PAT(x) cbswap_32(x) -#endif - -#ifdef WORDS_BIGENDIAN -#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff) -#else -#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff) -#endif - -static const uint32_t_ mask16[16] = { - PAT(0x00000000), - PAT(0x000000ff), - PAT(0x0000ff00), - PAT(0x0000ffff), - PAT(0x00ff0000), - PAT(0x00ff00ff), - PAT(0x00ffff00), - PAT(0x00ffffff), - PAT(0xff000000), - PAT(0xff0000ff), - PAT(0xff00ff00), - PAT(0xff00ffff), - PAT(0xffff0000), - PAT(0xffff00ff), - PAT(0xffffff00), - PAT(0xffffffff), -}; - -uint32_t_ vga_mem_readb(void *opaque, target_phys_addr_t addr){ - - VGAState *s = (VGAState *)opaque; - int memory_map_mode, plane; - uint32_t_ ret; - - /* convert to VGA memory offset */ - memory_map_mode = (s->gr[6] >> 2) & 3; - addr &= 0x1ffff; - switch(memory_map_mode) { - case 0: - break; - case 1: - if (addr >= 0x10000) - return 0xff; - addr += s->bank_offset; - break; - case 2: - addr -= 0x10000; - if (addr >= 0x8000) - return 0xff; - break; - default: - case 3: - addr -= 0x18000; - if (addr >= 0x8000) - return 0xff; - break; - } - - if (s->sr[4] & 0x08) { - /* chain 4 mode : simplest access */ - ret = s->vram_ptr[addr]; - } else if (s->gr[5] & 0x10) { - /* odd/even mode (aka text mode mapping) */ - plane = (s->gr[4] & 2) | (addr & 1); - ret = s->vram_ptr[((addr & ~1) << 1) | plane]; - } else { - /* standard VGA latched access */ - s->latch = ((uint32_t_ *)s->vram_ptr)[addr]; - - if (!(s->gr[5] & 0x08)) { - /* read mode 0 */ - plane = s->gr[4]; - ret = GET_PLANE(s->latch, plane); - } else { - /* read mode 1 */ - ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]]; - ret |= ret >> 16; - ret |= ret >> 8; - ret = (~ret) & 0xff; - } - } - return ret; -} -void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val){ - VGAState *s = (VGAState *)opaque; - int memory_map_mode, plane, write_mode, b, func_select, mask; - uint32_t_ write_mask, bit_mask, set_mask; - - ////val = ((val & 0x3) << 6) | ((val & 0xc) << 2) | ((val & 0x30) >> 2) | ((val & 0xc0) >> 4); - -#ifdef DEBUG_VGA_MEM - printf("vga: [0x%x] = 0x%02x\n", addr, val); -#endif - /* convert to VGA memory offset */ - memory_map_mode = (s->gr[6] >> 2) & 3; - addr &= 0x1ffff; - switch(memory_map_mode) { - case 0: - break; - case 1: - if (addr >= 0x10000) - return; - addr += s->bank_offset; - break; - case 2: - addr -= 0x10000; - if (addr >= 0x8000) - return; - break; - default: - case 3: - addr -= 0x18000; - if (addr >= 0x8000) - return; - break; - } - - if (s->sr[4] & 0x08) { - /* chain 4 mode : simplest access */ - plane = addr & 3; - mask = (1 << plane); - if (s->sr[2] & mask) { - s->vram_ptr[addr] = val; -#ifdef DEBUG_VGA_MEM - printf("vga: chain4: [0x%x]\n", addr); -#endif - s->plane_updated |= mask; /* only used to detect font change */ - cpu_physical_memory_set_dirty(s->vram_offset + addr); - } - } else if (s->gr[5] & 0x10) { - /* odd/even mode (aka text mode mapping) */ - plane = (s->gr[4] & 2) | (addr & 1); - mask = (1 << plane); - if (s->sr[2] & mask) { - addr = ((addr & ~1) << 1) | plane; - s->vram_ptr[addr] = val; -#ifdef DEBUG_VGA_MEM - printf("vga: odd/even: [0x%x]\n", addr); -#endif - s->plane_updated |= mask; /* only used to detect font change */ - cpu_physical_memory_set_dirty(s->vram_offset + addr); - } - } else { - /* standard VGA latched access */ - write_mode = s->gr[5] & 3; - switch(write_mode) { - default: - case 0: - /* rotate */ - b = s->gr[3] & 7; - val = ((val >> b) | (val << (8 - b))) & 0xff; - val |= val << 8; - val |= val << 16; - - /* apply set/reset mask */ - set_mask = mask16[s->gr[1]]; - val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask); - bit_mask = s->gr[8]; - break; - case 1: - val = s->latch; - goto do_write; - case 2: - val = mask16[val & 0x0f]; - bit_mask = s->gr[8]; - break; - case 3: - /* rotate */ - b = s->gr[3] & 7; - val = (val >> b) | (val << (8 - b)); - - bit_mask = s->gr[8] & val; - val = mask16[s->gr[0]]; - break; - } - - /* apply logical operation */ - func_select = s->gr[3] >> 3; - switch(func_select) { - case 0: - default: - /* nothing to do */ - break; - case 1: - /* and */ - val &= s->latch; - break; - case 2: - /* or */ - val |= s->latch; - break; - case 3: - /* xor */ - val ^= s->latch; - break; - } - - /* apply bit mask */ - bit_mask |= bit_mask << 8; - bit_mask |= bit_mask << 16; - val = (val & bit_mask) | (s->latch & ~bit_mask); - - do_write: - /* mask data according to sr[2] */ - mask = s->sr[2]; - s->plane_updated |= mask; /* only used to detect font change */ - write_mask = mask16[mask]; - write_mask = ((write_mask & 0xff) << 24) | ((write_mask & 0xff00) << 8) | ((write_mask & 0xff0000) >> 8) | ((write_mask & 0xff000000) >> 24); // XXX: なんかひっくり返さないと駄目 - ((uint32_t_ *)s->vram_ptr)[addr] = (((uint32_t_ *)s->vram_ptr)[addr] & ~write_mask) | (val & write_mask); -#ifdef DEBUG_VGA_MEM - printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", - addr * 4, write_mask, val); -#endif - cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2)); - } -} -void vga_invalidate_scanlines(VGAState *s, int y1, int y2){ - int y; - if (y1 >= VGA_MAX_HEIGHT) - return; - if (y2 >= VGA_MAX_HEIGHT) - y2 = VGA_MAX_HEIGHT; - for(y = y1; y < y2; y++) { - s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f); - } -} -int ppm_save(const char *filename, struct DisplaySurface *ds){return 0;} - -static void vga_draw_cursor_line(uint8_t *d1, - - const uint8_t *src1, - - int poffset, int w, - - unsigned int color0, - - unsigned int color1, - - unsigned int color_xor) - -{ - - const uint8_t *plane0, *plane1; - - int x, b0, b1; - - uint8_t *d; - - - - d = d1; - - plane0 = src1; - - plane1 = src1 + poffset; - - for (x = 0; x < w; x++) { - - b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1; - - b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1; - - switch (b0 | (b1 << 1)) { - - case 0: - - break; - - case 1: - - ((uint32_t_ *)d)[0] ^= color_xor; - ((uint32_t_ *)d)[0] |= 0xff000000; - - break; - - case 2: - - ((uint32_t_ *)d)[0] = color0; - ((uint32_t_ *)d)[0] |= 0xff000000; - break; - - case 3: - - ((uint32_t_ *)d)[0] = color1; - ((uint32_t_ *)d)[0] |= 0xff000000; - - break; - - } - - d += 4; - - } - -} -// -//void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1, -// int poffset, int w, -// unsigned int color0, unsigned int color1, -// unsigned int color_xor); -//void vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1, -// int poffset, int w, -// unsigned int color0, unsigned int color1, -// unsigned int color_xor); -//void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1, -// int poffset, int w, -// unsigned int color0, unsigned int color1, -// unsigned int color_xor); - -extern const uint8_t sr_mask[8]; -extern const uint8_t gr_mask[16]; +/* + * QEMU internal VGA defines. + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#define MSR_COLOR_EMULATION 0x01 +#define MSR_PAGE_SELECT 0x20 + +#define ST01_V_RETRACE 0x08 +#define ST01_DISP_ENABLE 0x01 + +/* bochs VBE support */ +#define CONFIG_BOCHS_VBE + +#define VBE_DISPI_MAX_XRES 1600 +#define VBE_DISPI_MAX_YRES 1200 +#define VBE_DISPI_MAX_BPP 32 + +#define VBE_DISPI_INDEX_ID 0x0 +#define VBE_DISPI_INDEX_XRES 0x1 +#define VBE_DISPI_INDEX_YRES 0x2 +#define VBE_DISPI_INDEX_BPP 0x3 +#define VBE_DISPI_INDEX_ENABLE 0x4 +#define VBE_DISPI_INDEX_BANK 0x5 +#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 +#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 +#define VBE_DISPI_INDEX_X_OFFSET 0x8 +#define VBE_DISPI_INDEX_Y_OFFSET 0x9 +#define VBE_DISPI_INDEX_NB 0xa + +#define VBE_DISPI_ID0 0xB0C0 +#define VBE_DISPI_ID1 0xB0C1 +#define VBE_DISPI_ID2 0xB0C2 +#define VBE_DISPI_ID3 0xB0C3 +#define VBE_DISPI_ID4 0xB0C4 + +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_GETCAPS 0x02 +#define VBE_DISPI_8BIT_DAC 0x20 +#define VBE_DISPI_LFB_ENABLED 0x40 +#define VBE_DISPI_NOCLEARMEM 0x80 + +#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 + +#ifdef CONFIG_BOCHS_VBE + +#define VGA_STATE_COMMON_BOCHS_VBE \ + uint16_t_ vbe_index; \ + uint16_t_ vbe_regs[VBE_DISPI_INDEX_NB]; \ + uint32_t_ vbe_start_addr; \ + uint32_t_ vbe_line_offset; \ + uint32_t_ vbe_bank_mask; + +#else + +#define VGA_STATE_COMMON_BOCHS_VBE + +#endif /* !CONFIG_BOCHS_VBE */ + +#define CH_ATTR_SIZE (160 * 100) +#define VGA_MAX_HEIGHT 2048 + +struct vga_precise_retrace { + int64_t ticks_per_char; + int64_t total_chars; + int htotal; + int hstart; + int hend; + int vstart; + int vend; + int freq; +}; + +union vga_retrace { + struct vga_precise_retrace precise; +}; + +struct VGAState; +typedef uint8_t (* vga_retrace_fn)(struct VGAState *s); +typedef void (* vga_update_retrace_info_fn)(struct VGAState *s); + +#define VGA_STATE_COMMON \ + uint8_t *vram_ptr; \ + ram_addr_t vram_offset; \ + unsigned int vram_size; \ + uint32_t_ lfb_addr; \ + uint32_t_ lfb_end; \ + uint32_t_ map_addr; \ + uint32_t_ map_end; \ + uint32_t_ lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */ \ + unsigned long bios_offset; \ + unsigned int bios_size; \ + int it_shift; \ + /*PCIDevice *pci_dev;*/ \ + uint32_t_ latch; \ + uint8_t sr_index; \ + uint8_t sr[256]; \ + uint8_t gr_index; \ + uint8_t gr[256]; \ + uint8_t ar_index; \ + uint8_t ar[21]; \ + int ar_flip_flop; \ + uint8_t cr_index; \ + uint8_t cr[256]; /* CRT registers */ \ + uint8_t msr; /* Misc Output Register */ \ + uint8_t fcr; /* Feature Control Register */ \ + uint8_t st00; /* status 0 */ \ + uint8_t st01; /* status 1 */ \ + uint8_t dac_state; \ + uint8_t dac_sub_index; \ + uint8_t dac_read_index; \ + uint8_t dac_write_index; \ + uint8_t dac_cache[3]; /* used when writing */ \ + int dac_8bit; \ + uint8_t palette[768]; \ + int32_t bank_offset; \ + int vga_io_memory; \ + int (*get_bpp)(struct VGAState *s); \ + void (*get_offsets)(struct VGAState *s, \ + uint32_t_ *pline_offset, \ + uint32_t_ *pstart_addr, \ + uint32_t_ *pline_compare); \ + void (*get_resolution)(struct VGAState *s, \ + int *pwidth, \ + int *pheight); \ + VGA_STATE_COMMON_BOCHS_VBE \ + /* display refresh support */ \ + DisplayState *ds; \ + uint32_t_ font_offsets[2]; \ + int graphic_mode; \ + uint8_t shift_control; \ + uint8_t double_scan; \ + uint32_t_ line_offset; \ + uint32_t_ line_compare; \ + uint32_t_ start_addr; \ + uint32_t_ plane_updated; \ + uint32_t_ last_line_offset; \ + uint8_t last_cw, last_ch; \ + uint32_t_ last_width, last_height; /* in chars or pixels */ \ + uint32_t_ last_scr_width, last_scr_height; /* in pixels */ \ + uint32_t_ last_depth; /* in bits */ \ + uint8_t cursor_start, cursor_end; \ + uint32_t_ cursor_offset; \ + unsigned int (*rgb_to_pixel)(unsigned int r, \ + unsigned int g, unsigned b); \ + vga_hw_update_ptr update; \ + vga_hw_invalidate_ptr invalidate; \ + vga_hw_screen_dump_ptr screen_dump; \ + vga_hw_text_update_ptr text_update; \ + /* hardware mouse cursor support */ \ + uint32_t_ invalidated_y_table[VGA_MAX_HEIGHT / 32]; \ + void (*cursor_invalidate)(struct VGAState *s); \ + void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y); \ + /* tell for each page if it has been updated since the last time */ \ + uint32_t_ last_palette[256]; \ + uint32_t_ last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ \ + /* retrace */ \ + vga_retrace_fn retrace; \ + vga_update_retrace_info_fn update_retrace_info; \ + union vga_retrace retrace_info; + + +typedef struct VGAState { + VGA_STATE_COMMON +} VGAState; + +typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, const uint8_t *s, int width); + +static int c6_to_8(int v) +{ + int b; + v &= 0x3f; + b = v & 1; + return (v << 2) | (b << 1) | b; +} + +void vga_common_init(VGAState *s, uint8_t *vga_ram_base, ram_addr_t vga_ram_offset, int vga_ram_size){} +void vga_init(VGAState *s){} +void vga_reset(void *s){} + +void vga_dirty_log_start(VGAState *s){} +void vga_dirty_log_stop(VGAState *s){} + +#define cbswap_32(__x) \ +((uint32_t_)( \ + (((uint32_t_)(__x) & (uint32_t_)0x000000ffUL) << 24) | \ + (((uint32_t_)(__x) & (uint32_t_)0x0000ff00UL) << 8) | \ + (((uint32_t_)(__x) & (uint32_t_)0x00ff0000UL) >> 8) | \ + (((uint32_t_)(__x) & (uint32_t_)0xff000000UL) >> 24) )) + +#ifdef WORDS_BIGENDIAN +#define PAT(x) x +#else +#define PAT(x) cbswap_32(x) +#endif + +#ifdef WORDS_BIGENDIAN +#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff) +#else +#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff) +#endif + +static const uint32_t_ mask16[16] = { + PAT(0x00000000), + PAT(0x000000ff), + PAT(0x0000ff00), + PAT(0x0000ffff), + PAT(0x00ff0000), + PAT(0x00ff00ff), + PAT(0x00ffff00), + PAT(0x00ffffff), + PAT(0xff000000), + PAT(0xff0000ff), + PAT(0xff00ff00), + PAT(0xff00ffff), + PAT(0xffff0000), + PAT(0xffff00ff), + PAT(0xffffff00), + PAT(0xffffffff), +}; + +uint32_t_ vga_mem_readb(void *opaque, target_phys_addr_t addr){ + + VGAState *s = (VGAState *)opaque; + int memory_map_mode, plane; + uint32_t_ ret; + + /* convert to VGA memory offset */ + memory_map_mode = (s->gr[6] >> 2) & 3; + addr &= 0x1ffff; + switch(memory_map_mode) { + case 0: + break; + case 1: + if (addr >= 0x10000) + return 0xff; + addr += s->bank_offset; + break; + case 2: + addr -= 0x10000; + if (addr >= 0x8000) + return 0xff; + break; + default: + case 3: + addr -= 0x18000; + if (addr >= 0x8000) + return 0xff; + break; + } + + if (s->sr[4] & 0x08) { + /* chain 4 mode : simplest access */ + ret = s->vram_ptr[addr]; + } else if (s->gr[5] & 0x10) { + /* odd/even mode (aka text mode mapping) */ + plane = (s->gr[4] & 2) | (addr & 1); + ret = s->vram_ptr[((addr & ~1) << 1) | plane]; + } else { + /* standard VGA latched access */ + s->latch = ((uint32_t_ *)s->vram_ptr)[addr]; + + if (!(s->gr[5] & 0x08)) { + /* read mode 0 */ + plane = s->gr[4]; + ret = GET_PLANE(s->latch, plane); + } else { + /* read mode 1 */ + ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]]; + ret |= ret >> 16; + ret |= ret >> 8; + ret = (~ret) & 0xff; + } + } + return ret; +} +void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t_ val){ + VGAState *s = (VGAState *)opaque; + int memory_map_mode, plane, write_mode, b, func_select, mask; + uint32_t_ write_mask, bit_mask, set_mask; + + ////val = ((val & 0x3) << 6) | ((val & 0xc) << 2) | ((val & 0x30) >> 2) | ((val & 0xc0) >> 4); + +#ifdef DEBUG_VGA_MEM + printf("vga: [0x%x] = 0x%02x\n", addr, val); +#endif + /* convert to VGA memory offset */ + memory_map_mode = (s->gr[6] >> 2) & 3; + addr &= 0x1ffff; + switch(memory_map_mode) { + case 0: + break; + case 1: + if (addr >= 0x10000) + return; + addr += s->bank_offset; + break; + case 2: + addr -= 0x10000; + if (addr >= 0x8000) + return; + break; + default: + case 3: + addr -= 0x18000; + if (addr >= 0x8000) + return; + break; + } + + if (s->sr[4] & 0x08) { + /* chain 4 mode : simplest access */ + plane = addr & 3; + mask = (1 << plane); + if (s->sr[2] & mask) { + s->vram_ptr[addr] = val; +#ifdef DEBUG_VGA_MEM + printf("vga: chain4: [0x%x]\n", addr); +#endif + s->plane_updated |= mask; /* only used to detect font change */ + cpu_physical_memory_set_dirty(s->vram_offset + addr); + } + } else if (s->gr[5] & 0x10) { + /* odd/even mode (aka text mode mapping) */ + plane = (s->gr[4] & 2) | (addr & 1); + mask = (1 << plane); + if (s->sr[2] & mask) { + addr = ((addr & ~1) << 1) | plane; + s->vram_ptr[addr] = val; +#ifdef DEBUG_VGA_MEM + printf("vga: odd/even: [0x%x]\n", addr); +#endif + s->plane_updated |= mask; /* only used to detect font change */ + cpu_physical_memory_set_dirty(s->vram_offset + addr); + } + } else { + /* standard VGA latched access */ + write_mode = s->gr[5] & 3; + switch(write_mode) { + default: + case 0: + /* rotate */ + b = s->gr[3] & 7; + val = ((val >> b) | (val << (8 - b))) & 0xff; + val |= val << 8; + val |= val << 16; + + /* apply set/reset mask */ + set_mask = mask16[s->gr[1]]; + val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask); + bit_mask = s->gr[8]; + break; + case 1: + val = s->latch; + goto do_write; + case 2: + val = mask16[val & 0x0f]; + bit_mask = s->gr[8]; + break; + case 3: + /* rotate */ + b = s->gr[3] & 7; + val = (val >> b) | (val << (8 - b)); + + bit_mask = s->gr[8] & val; + val = mask16[s->gr[0]]; + break; + } + + /* apply logical operation */ + func_select = s->gr[3] >> 3; + switch(func_select) { + case 0: + default: + /* nothing to do */ + break; + case 1: + /* and */ + val &= s->latch; + break; + case 2: + /* or */ + val |= s->latch; + break; + case 3: + /* xor */ + val ^= s->latch; + break; + } + + /* apply bit mask */ + bit_mask |= bit_mask << 8; + bit_mask |= bit_mask << 16; + val = (val & bit_mask) | (s->latch & ~bit_mask); + + do_write: + /* mask data according to sr[2] */ + mask = s->sr[2]; + s->plane_updated |= mask; /* only used to detect font change */ + write_mask = mask16[mask]; + write_mask = ((write_mask & 0xff) << 24) | ((write_mask & 0xff00) << 8) | ((write_mask & 0xff0000) >> 8) | ((write_mask & 0xff000000) >> 24); // XXX: なんかひっくり返さないと駄目 + ((uint32_t_ *)s->vram_ptr)[addr] = (((uint32_t_ *)s->vram_ptr)[addr] & ~write_mask) | (val & write_mask); +#ifdef DEBUG_VGA_MEM + printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", + addr * 4, write_mask, val); +#endif + cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2)); + } +} +void vga_invalidate_scanlines(VGAState *s, int y1, int y2){ + int y; + if (y1 >= VGA_MAX_HEIGHT) + return; + if (y2 >= VGA_MAX_HEIGHT) + y2 = VGA_MAX_HEIGHT; + for(y = y1; y < y2; y++) { + s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f); + } +} +int ppm_save(const char *filename, struct DisplaySurface *ds){return 0;} + +static void vga_draw_cursor_line(uint8_t *d1, + + const uint8_t *src1, + + int poffset, int w, + + unsigned int color0, + + unsigned int color1, + + unsigned int color_xor) + +{ + + const uint8_t *plane0, *plane1; + + int x, b0, b1; + + uint8_t *d; + + + + d = d1; + + plane0 = src1; + + plane1 = src1 + poffset; + + for (x = 0; x < w; x++) { + + b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1; + + b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1; + + switch (b0 | (b1 << 1)) { + + case 0: + + break; + + case 1: + + ((uint32_t_ *)d)[0] ^= color_xor; + ((uint32_t_ *)d)[0] |= 0xff000000; + + break; + + case 2: + + ((uint32_t_ *)d)[0] = color0; + ((uint32_t_ *)d)[0] |= 0xff000000; + break; + + case 3: + + ((uint32_t_ *)d)[0] = color1; + ((uint32_t_ *)d)[0] |= 0xff000000; + + break; + + } + + d += 4; + + } + +} +// +//void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1, +// int poffset, int w, +// unsigned int color0, unsigned int color1, +// unsigned int color_xor); +//void vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1, +// int poffset, int w, +// unsigned int color0, unsigned int color1, +// unsigned int color_xor); +//void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1, +// int poffset, int w, +// unsigned int color0, unsigned int color1, +// unsigned int color_xor); + +extern const uint8_t sr_mask[8]; +extern const uint8_t gr_mask[16]; diff --git a/wab/wab.c b/wab/wab.c old mode 100755 new mode 100644 index 834b961e..446eedb8 --- a/wab/wab.c +++ b/wab/wab.c @@ -1,1050 +1,1050 @@ -/** - * @file wab.c - * @brief Window Accelerator Board Interface - * - * @author $Author: SimK $ - */ - -#include - -#if defined(SUPPORT_WAB) - -#include "np2.h" -#if defined(NP2_WIN) -#include "np2mt.h" -#include "resource.h" -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(NP2_WIN) -#include "winkbd.h" -#include "winloc.h" -#endif -#include -#include "ini.h" -#include -#include -#include -#include -#if defined(NP2_WIN) -#include -#endif -#include -#if defined(NP2_X) -#include -#endif - -NP2WAB np2wab = {0}; -NP2WABWND np2wabwnd = {0}; -NP2WABCFG np2wabcfg; - -#if defined(NP2_WIN) -TCHAR g_Name[100] = _T("NP2 Window Accelerator"); -#else -char g_Name[100] = "NP2 Window Accelerator"; -#endif - -#if defined(NP2_WIN) -static HINSTANCE ga_hInstance = NULL; -static HANDLE ga_hThread = NULL; -#endif -static int ga_exitThread = 0; -#if defined(NP2_WIN) -static int ga_threadmode = 1; -#else -static int ga_threadmode = 0; -#endif -static int ga_lastwabwidth = 640; -static int ga_lastwabheight = 480; -static int ga_reqChangeWindowSize = 0; -static int ga_reqChangeWindowSize_w = 0; -static int ga_reqChangeWindowSize_h = 0; - -static int ga_lastscalemode = 0; -static int ga_lastrealwidth = 0; -static int ga_lastrealheight = 0; -static int ga_screenupdated = 0; - -#if defined(NP2_WIN) -static int wab_cs_initialized = 0; -static CRITICAL_SECTION wab_cs; -static HANDLE wab_thread_eventhandle = INVALID_HANDLE_VALUE; -#endif - -static int np2wab_forceupdateflag = 0; - -static BOOL wab_tryenter_criticalsection(void){ -#if defined(NP2_WIN) - if(!wab_cs_initialized) return TRUE; - return TryEnterCriticalSection(&wab_cs); -#else - return TRUE; -#endif -} -static void wab_enter_criticalsection(void){ -#if defined(NP2_WIN) - if(!wab_cs_initialized) return; - EnterCriticalSection(&wab_cs); -#endif -} -static void wab_leave_criticalsection(void){ -#if defined(NP2_WIN) - if(!wab_cs_initialized) return; - LeaveCriticalSection(&wab_cs); -#endif -} -static void wab_init_criticalsection(void){ -#if defined(NP2_WIN) - if(!wab_cs_initialized){ - memset(&wab_cs, 0, sizeof(wab_cs)); - wab_thread_eventhandle = CreateEvent(NULL, FALSE, FALSE, NULL); - InitializeCriticalSection(&wab_cs); - wab_cs_initialized = 1; - } -#endif -} -static void wab_delete_criticalsection(void){ -#if defined(NP2_WIN) - if(wab_cs_initialized){ - DeleteCriticalSection(&wab_cs); - CloseHandle(wab_thread_eventhandle); - wab_cs_initialized = 0; - } -#endif -} - -/** - * 設定 - */ -#if defined(NP2_WIN) -static const PFTBL s_wabwndini[] = -{ - PFVAL("WindposX", PFTYPE_SINT32, &np2wabcfg.posx), - PFVAL("WindposY", PFTYPE_SINT32, &np2wabcfg.posy), - PFVAL("MULTIWND", PFTYPE_BOOL, &np2wabcfg.multiwindow), - PFVAL("MULTHREAD",PFTYPE_BOOL, &np2wabcfg.multithread), - PFVAL("HALFTONE", PFTYPE_BOOL, &np2wabcfg.halftone), -}; -#else -static const INITBL s_wabwndini[] = -{ - {OEMTEXT("WindposX"), INITYPE_SINT32, &np2wabcfg.posx, 0}, - {OEMTEXT("WindposY"), INITYPE_SINT32, &np2wabcfg.posy, 0}, - {OEMTEXT("MULTIWND"), INITYPE_BOOL, &np2wabcfg.multiwindow, 0}, - {OEMTEXT("MULTHREAD"), INITYPE_BOOL, &np2wabcfg.multithread, 0}, - {OEMTEXT("HALFTONE"), INITYPE_BOOL, &np2wabcfg.halftone, 0}, -}; -#endif - -/** - * 設定読み込み - */ -void wabwin_readini() -{ - OEMCHAR szPath[MAX_PATH]; - -#if defined(NP2_WIN) - ZeroMemory(&np2wabcfg, sizeof(np2wabcfg)); - np2wabcfg.posx = CW_USEDEFAULT; - np2wabcfg.posy = CW_USEDEFAULT; - np2wabcfg.multithread = 1; -#else - memset(&np2wabcfg, 0, sizeof(np2wabcfg)); - np2wabcfg.posx = 0; - np2wabcfg.posy = 0; - np2wabcfg.multithread = 0; -#endif - np2wabcfg.multiwindow = 0; - np2wabcfg.halftone = 0; - -#if defined(NP2_WIN) - initgetfile(szPath, NELEMENTS(szPath)); -#else - milstr_ncpy(szPath, modulefile, sizeof(szPath)); -#endif - ini_read(szPath, g_Name, s_wabwndini, NELEMENTS(s_wabwndini)); -} - -/** - * 設定書き込み - */ -void np2wab_forceupdate() -{ - np2wab_forceupdateflag = 1; -} - -/** - * 設定書き込み - */ -void wabwin_writeini() -{ - if(!np2wabcfg.readonly){ - TCHAR szPath[MAX_PATH]; -#if defined(NP2_WIN) - initgetfile(szPath, NELEMENTS(szPath)); - ini_write(szPath, g_Name, s_wabwndini, NELEMENTS(s_wabwndini)); -#elif defined(NP2_X) - milstr_ncpy(szPath, modulefile, sizeof(szPath)); - ini_write(szPath, g_Name, s_wabwndini, NELEMENTS(s_wabwndini), FALSE); -#else - milstr_ncpy(szPath, modulefile, sizeof(szPath)); - ini_write(szPath, g_Name, s_wabwndini, NELEMENTS(s_wabwndini)); -#endif - } -} - -void scrnmng_updatefsres(void); -#ifdef EMSCRIPTEN -void scrnmng_blthdc(void); -#endif -void scrnmng_bltwab(void); - -/** - * 画面サイズ設定 - */ -void np2wab_setScreenSize(int width, int height) -{ - if(np2wabwnd.multiwindow){ -#if defined(NP2_WIN) - // 別窓モードなら別窓サイズを更新する - RECT rect = { 0, 0, width, height }; - np2wab.wndWidth = width; - np2wab.wndHeight = height; - AdjustWindowRectEx( &rect, WS_OVERLAPPEDWINDOW, FALSE, 0 ); - SetWindowPos( np2wabwnd.hWndWAB, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE|SWP_NOZORDER ); -#elif defined(NP2_X) - np2wab.wndWidth = width; - np2wab.wndHeight = height; - gtk_widget_set_size_request(np2wabwnd.pWABWnd, width, height); -#endif - }else{ - // 統合モードならエミュレーション領域サイズを更新する - np2wab.wndWidth = ga_lastwabwidth = width; - np2wab.wndHeight = ga_lastwabheight = height; - if(np2wab.relay & 0x3){ - if(width < 32 || height < 32){ -#if defined(NP2_WIN) - scrnmng_setsize(0, 0, 640, 480); -#else - scrnmng_setwidth(0, 640); - scrnmng_setheight(0, 480); -#endif - }else{ -#if defined(NP2_WIN) - scrnmng_setsize(0, 0, width, height); -#else - scrnmng_setwidth(0, width); - scrnmng_setheight(0, height); -#endif - } - scrnmng_updatefsres(); // フルスクリーン解像度更新 -#if defined(NP2_WIN) - mousemng_updateclip(); // マウスキャプチャのクリップ範囲を修正 -#endif - } - } - // とりあえずパレットは更新しておく - np2wab.paletteChanged = 1; - - // 画面更新 - np2wab_forceupdateflag = 1; -} -/** - * 画面サイズ設定マルチスレッド対応版(すぐに更新できない場合はnp2wab.ready=0に) - */ -void np2wab_setScreenSizeMT(int width, int height) -{ - if(!ga_threadmode){ - // マルチスレッドモードでなければ直接呼び出し - np2wab_setScreenSize(width, height); - ga_lastrealwidth = width; - ga_lastrealheight = height; - }else{ - // マルチスレッドモードなら画面サイズ変更要求を出す - ga_reqChangeWindowSize_w = width; - ga_reqChangeWindowSize_h = height; - ga_reqChangeWindowSize = 1; - np2wabwnd.ready = 0; // 更新待ち - } - - // 画面更新 - np2wab_forceupdateflag = 1; -} - -/** - * ウィンドウアクセラレータ別窓を等倍サイズに戻す - */ -void np2wab_resetscreensize() -{ - if(np2wabwnd.multiwindow){ -#if defined(NP2_WIN) - RECT rect = {0}; - rect.right = np2wab.wndWidth = np2wab.realWidth; - rect.bottom = np2wab.wndHeight = np2wab.realHeight; - AdjustWindowRectEx( &rect, WS_OVERLAPPEDWINDOW, FALSE, 0 ); - SetWindowPos( np2wabwnd.hWndWAB, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE|SWP_NOZORDER ); -#elif defined(NP2_X) - np2wab.wndWidth = np2wab.realWidth; - np2wab.wndHeight = np2wab.realHeight; - gtk_widget_set_size_request(np2wabwnd.pWABWnd, np2wab.realWidth, np2wab.realHeight); -#endif - } - - // 画面更新 - np2wab_forceupdateflag = 1; -} - -#if defined(NP2_WIN) -/** - * ウィンドウアクセラレータ別窓WndProc - */ -LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ - RECT rc; - HMENU hSysMenu; - HMENU hWabMenu; - MENUITEMINFO mii = {0}; - TCHAR szString[128]; - int scalemode; - - switch (msg) { - case WM_CREATE: - hSysMenu = GetSystemMenu(hWnd, FALSE); - hWabMenu = LoadMenu(ga_hInstance, MAKEINTRESOURCE(IDR_WABSYSMENU)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA; - mii.dwTypeData = szString; - mii.cch = NELEMENTS(szString); - GetMenuItemInfo(hWabMenu, 0, TRUE, &mii); - InsertMenuItem(hSysMenu, 0, TRUE, &mii); - mii.dwTypeData = szString; - mii.cch = NELEMENTS(szString); - GetMenuItemInfo(hWabMenu, 1, TRUE, &mii); - InsertMenuItem(hSysMenu, 0, TRUE, &mii); - CheckMenuItem(hSysMenu, IDM_WABSYSMENU_HALFTONE, MF_BYCOMMAND | (np2wabcfg.halftone ? MF_CHECKED : MF_UNCHECKED)); - DestroyMenu(hWabMenu); - - break; - - case WM_SYSCOMMAND: - switch(wParam) { - case IDM_WABSYSMENU_RESETSIZE: - np2wab_resetscreensize(); - break; - - case IDM_WABSYSMENU_HALFTONE: - np2wabcfg.halftone = !np2wabcfg.halftone; - hSysMenu = GetSystemMenu(hWnd, FALSE); - CheckMenuItem(hSysMenu, IDM_WABSYSMENU_HALFTONE, MF_BYCOMMAND | (np2wabcfg.halftone ? MF_CHECKED : MF_UNCHECKED)); - scalemode = np2wab.wndWidth!=np2wab.realWidth || np2wab.wndHeight!=np2wab.realHeight; - if(scalemode){ - SetStretchBltMode(np2wabwnd.hDCWAB, np2wabcfg.halftone ? HALFTONE : COLORONCOLOR); - SetBrushOrgEx(np2wabwnd.hDCWAB , 0 , 0 , NULL); - } - break; - - default: - return(DefWindowProc(hWnd, msg, wParam, lParam)); - } - break; - - case WM_MOVE: - GetWindowRect(hWnd, &rc); - if(np2wabwnd.multiwindow && !IsZoomed(hWnd) && !IsIconic(hWnd) && IsWindowVisible(hWnd)){ - np2wabcfg.posx = rc.left; - np2wabcfg.posy = rc.top; - } - break; - - case WM_ENTERSIZEMOVE: - break; - - case WM_MOVING: - break; - - case WM_SIZE: - np2wab_forceupdate(); - case WM_SIZING: - GetClientRect( hWnd, &rc ); - np2wab.wndWidth = rc.right - rc.left; - np2wab.wndHeight = rc.bottom - rc.top; - break; - - case WM_EXITSIZEMOVE: - break; - - case WM_KEYDOWN: - SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // 必殺丸投げ - break; - - case WM_KEYUP: - SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // 必殺丸投げ - break; - - case WM_SYSKEYDOWN: - SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // 必殺丸投げ - break; - - case WM_SYSKEYUP: - SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // 必殺丸投げ - break; - - case WM_MOUSEMOVE: - SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // 必殺丸投げ - break; - - case WM_LBUTTONDOWN: - if(np2wabwnd.multiwindow){ - SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // やはり丸投げ - } - break; - - case WM_LBUTTONUP: - if(np2wabwnd.multiwindow){ - SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // ここも丸投げ - } - break; - - case WM_RBUTTONDOWN: - if(np2wabwnd.multiwindow){ - SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // そのまま丸投げ - } - break; - - case WM_RBUTTONUP: - if(np2wabwnd.multiwindow){ - SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // なんでも丸投げ - } - break; - - case WM_MBUTTONDOWN: - SetForegroundWindow(np2wabwnd.hWndMain); - SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // とりあえず丸投げ - break; - - case WM_CLOSE: - return 0; - - case WM_DESTROY: - break; - - default: - return(DefWindowProc(hWnd, msg, wParam, lParam)); - } - return(0L); -} -#endif - -/** - * ウィンドウアクセラレータ画面転送 - * 別窓モード: GDI Device Independent Bitmap -> GDI Window - * 統合モード: GDI Device Independent Bitmap -> Direct3D/DirectDraw WAB surface ( call scrnmng_blthdc() ) - */ -#if defined(NP2_WIN) -void np2wab_drawWABWindow(HDC hdc) -#else -void np2wab_drawWABWindow(void) -#endif -{ - int scalemode = 0; - int srcwidth = np2wab.realWidth; - int srcheight = np2wab.realHeight; - if(ga_lastrealwidth != srcwidth || ga_lastrealheight != srcheight){ - // 解像度が変わっていたらウィンドウサイズも変える - if(!ga_reqChangeWindowSize){ - np2wab.paletteChanged = 1; - np2wab_setScreenSizeMT(srcwidth, srcheight); - } - if(!np2wabwnd.ready) return; - } - if(np2wabwnd.multiwindow){ // 別窓モード判定 - scalemode = np2wab.wndWidth!=srcwidth || np2wab.wndHeight!=srcheight; - if(ga_lastscalemode!=scalemode){ // 画面スケールが変わりました - if(scalemode){ - // 通常はCOLORONCOLOR。HALFTONEにも設定できるけど拡大の補間が微妙・・・ -#if defined(NP2_WIN) - SetStretchBltMode(np2wabwnd.hDCWAB, np2wabcfg.halftone ? HALFTONE : COLORONCOLOR); - SetBrushOrgEx(np2wabwnd.hDCWAB , 0 , 0 , NULL); -#endif - }else{ -#if defined(NP2_WIN) - SetStretchBltMode(np2wabwnd.hDCWAB, BLACKONWHITE); -#endif - } - ga_lastscalemode = scalemode; - np2wab.paletteChanged = 1; - } - if(scalemode){ - // 拡大縮小転送。とりあえず画面比は維持 - if(np2wab.wndWidth * srcheight > srcwidth * np2wab.wndHeight){ - // 横長 - int dstw = srcwidth * np2wab.wndHeight / srcheight; - int dsth = np2wab.wndHeight; - int mgnw = (np2wab.wndWidth - dstw); - int shx = 0; - if(mgnw&0x1) shx = 1; - mgnw = mgnw>>1; -#if defined(NP2_WIN) - BitBlt(np2wabwnd.hDCWAB, 0, 0, mgnw, np2wab.wndHeight, NULL, 0, 0, BLACKNESS); - BitBlt(np2wabwnd.hDCWAB, np2wab.wndWidth-mgnw-shx, 0, mgnw+shx, np2wab.wndHeight, NULL, 0, 0, BLACKNESS); - StretchBlt(np2wabwnd.hDCWAB, mgnw, 0, dstw, dsth, np2wabwnd.hDCBuf, 0, 0, srcwidth, srcheight, SRCCOPY); -#endif - }else if(np2wab.wndWidth * srcheight < srcwidth * np2wab.wndHeight){ - // 縦長 - int dstw = np2wab.wndWidth; - int dsth = srcheight * np2wab.wndWidth / srcwidth; - int mgnh = (np2wab.wndHeight - dsth); - int shy = 0; - if(mgnh&0x1) shy = 1; - mgnh = mgnh>>1; -#if defined(NP2_WIN) - BitBlt(np2wabwnd.hDCWAB, 0, 0, np2wab.wndWidth, mgnh, NULL, 0, 0, BLACKNESS); - BitBlt(np2wabwnd.hDCWAB, 0, np2wab.wndHeight-mgnh-shy, np2wab.wndWidth, mgnh+shy, NULL, 0, 0, BLACKNESS); - StretchBlt(np2wabwnd.hDCWAB, 0, mgnh, dstw, dsth, np2wabwnd.hDCBuf, 0, 0, srcwidth, srcheight, SRCCOPY); -#endif - }else{ -#if defined(NP2_WIN) - StretchBlt(np2wabwnd.hDCWAB, 0, 0, np2wab.wndWidth, np2wab.wndHeight, np2wabwnd.hDCBuf, 0, 0, srcwidth, srcheight, SRCCOPY); -#endif - } - }else{ - // 等倍転送 -#if defined(NP2_WIN) - BitBlt(np2wabwnd.hDCWAB, 0, 0, srcwidth, srcheight, np2wabwnd.hDCBuf, 0, 0, SRCCOPY); -#endif - } - }else{ - // DirectDrawに描かせる - //scrnmng_blthdc(np2wabwnd.hDCBuf); - // DirectDraw Surfaceに転送 -#if defined(NP2_WIN) - scrnmng_blthdc(np2wabwnd.hDCBuf); -#else - scrnmng_blthdc(); -#endif - } -} - -/** - * 同期描画(ga_threadmodeが偽) - */ -void np2wab_drawframe() -{ -#if defined(NP2_WIN) - if(!ga_threadmode){ - if(np2wabwnd.ready && np2wabwnd.hWndWAB!=NULL && (np2wab.relay&0x3)!=0){ -#endif - // マルチスレッドじゃない場合はここで描画処理 - if (np2wabwnd.drawframe()) - { -#if defined(NP2_WIN) - np2wab_drawWABWindow(np2wabwnd.hDCBuf); -#else - np2wab_drawWABWindow(); -#endif - if (!np2wabwnd.multiwindow) - { - scrnmng_bltwab(); - scrnmng_update(); - } - } -#if defined(NP2_WIN) - } - }else{ - if(np2wabwnd.hWndWAB!=NULL){ - if(ga_reqChangeWindowSize){ - // 画面サイズ変更要求が来ていたら画面サイズを変える - np2wab_setScreenSize(ga_reqChangeWindowSize_w, ga_reqChangeWindowSize_h); - ga_lastrealwidth = ga_reqChangeWindowSize_w; - ga_lastrealheight = ga_reqChangeWindowSize_h; - ga_reqChangeWindowSize = 0; - np2wabwnd.ready = 1; - } - if(np2wabwnd.ready && (np2wab.relay&0x3)!=0){ - if(ga_screenupdated){ - wab_enter_criticalsection(); - if(!np2wabwnd.multiwindow){ - //np2wab_drawWABWindow(np2wabwnd.hDCBuf); // ga_ThreadFuncでやる - scrnmng_bltwab(); - } - ga_screenupdated = 0; - if(!np2wabwnd.multiwindow){ - // XXX: ウィンドウアクセラレータ動作中は内蔵グラフィックを描画しない - scrnmng_update(); - } - wab_leave_criticalsection(); - } - SetEvent(wab_thread_eventhandle); - } - } - } -#endif -} - -#if defined(NP2_WIN) -/** - * 非同期描画(ga_threadmodeが真) - */ -unsigned int __stdcall ga_ThreadFunc(LPVOID vdParam) { - static int skipcounter = 0; - int timeleft = 0; - while (WaitForSingleObject(wab_thread_eventhandle, INFINITE) == WAIT_OBJECT_0) - { - if (ga_exitThread || !ga_threadmode) break; - - //wab_enter_criticalsection(); - //wab_leave_criticalsection(); - if(np2wabwnd.ready && np2wabwnd.hWndWAB!=NULL && np2wabwnd.drawframe!=NULL && (np2wab.relay&0x3)!=0){ - if (np2wabwnd.drawframe() || np2wab_forceupdateflag) - { - np2wab_forceupdateflag = 0; - np2wab_drawWABWindow(np2wabwnd.hDCBuf); - //// 画面転送待ち - ga_screenupdated = 1; - skipcounter = 0; - } - } - } - ga_threadmode = 0; - return 0; -} -#endif - -/** - * 画面出力リレー制御 - */ -static void IOOUTCALL np2wab_ofac(UINT port, REG8 dat) { - TRACEOUT(("WAB: out FACh set relay %04X d=%02X", port, dat)); - dat = dat & ~0xfc; - if(np2wab.relaystateext != dat){ - np2wab.relaystateext = dat & 0x3; - np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) - } - (void)port; - (void)dat; -} -static REG8 IOINPCALL np2wab_ifac(UINT port) { - //TRACEOUT(("WAB: inp FACh get relay %04X", port)); - return 0xfc | np2wab.relaystateext; -} - -// NP2起動時の処理 -#if defined(NP2_WIN) -void np2wab_init(HINSTANCE hInstance, HWND hWndMain) -#else -void np2wab_init(void) -#endif -{ -#if defined(NP2_WIN) - WNDCLASSEX wcex = {0}; - HDC hdc; -#endif - - // クリティカルセクション初期化 - wab_init_criticalsection(); - - //// 専用INIセクション読み取り - //wabwin_readini(); - -#if defined(NP2_WIN) - // 後々要る物を保存しておく - ga_hInstance = hInstance; - np2wabwnd.hWndMain = hWndMain; - - // ウィンドウアクセラレータ別窓を作る - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_HREDRAW | CS_VREDRAW | (np2wabwnd.multiwindow ? CS_DBLCLKS : 0); - wcex.lpfnWndProc = WndProc; - wcex.hInstance = ga_hInstance; - wcex.hIcon = LoadIcon(ga_hInstance, MAKEINTRESOURCE(IDI_ICON1)); - wcex.hCursor = LoadCursor(NULL, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); - wcex.lpszClassName = (TCHAR*)g_Name; - if(!RegisterClassEx(&wcex)) return; - np2wabwnd.hWndWAB = CreateWindowEx( - 0, - g_Name, g_Name, - WS_OVERLAPPEDWINDOW, - np2wabcfg.posx, np2wabcfg.posy, - 640, 480, - np2wabwnd.multiwindow ? NULL : np2wabwnd.hWndMain, - NULL, ga_hInstance, NULL - ); - if(!np2wabwnd.hWndWAB) return; - - // HWNDとかHDCとかバッファ用ビットマップとかを先に作っておく - np2wabwnd.hDCWAB = GetDC(np2wabwnd.hWndWAB); - hdc = np2wabwnd.multiwindow ? GetDC(NULL) : np2wabwnd.hDCWAB; - np2wabwnd.hBmpBuf = CreateCompatibleBitmap(hdc, WAB_MAX_WIDTH, WAB_MAX_HEIGHT); - np2wabwnd.hDCBuf = CreateCompatibleDC(hdc); - SelectObject(np2wabwnd.hDCBuf, np2wabwnd.hBmpBuf); -#elif defined(NP2_X) - np2wabwnd.pPixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, WAB_MAX_WIDTH, WAB_MAX_HEIGHT); -#else - np2wabwnd.pBuffer = (unsigned int*)malloc(WAB_MAX_WIDTH * WAB_MAX_HEIGHT * sizeof(unsigned int)); -#endif - -} -// リセット時に呼ばれる? -void np2wab_reset(const NP2CFG *pConfig) -{ -#if defined(NP2_WIN) - // マルチスレッドモードなら先にスレッド処理を終了させる - if(ga_threadmode && ga_hThread){ - ga_exitThread = 1; - //while(((int)ResumeThread(ga_hThread))>0); - //while(WaitForSingleObject(ga_hThread, 200)==WAIT_TIMEOUT){ - // ResumeThread(ga_hThread); - //} - SetEvent(wab_thread_eventhandle); - if(WaitForSingleObject(ga_hThread, 4000)==WAIT_TIMEOUT){ - TerminateThread(ga_hThread, 0); - } - CloseHandle(ga_hThread); - ga_hThread = NULL; - ga_exitThread = 0; - } -#endif - - // 描画を停止して設定初期化 - np2wabwnd.ready = 0; - ga_lastscalemode = 0; - ga_lastrealwidth = 0; - ga_lastrealheight = 0; - ga_screenupdated = 0; - np2wab.lastWidth = 0; - np2wab.lastHeight = 0; - np2wab.realWidth = 0; - np2wab.realHeight = 0; - np2wab.relaystateint = 0; - np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); - - // 設定値更新とか - np2wab.wndWidth = 640; - np2wab.wndHeight = 480; - np2wab.fps = 60; - ga_lastwabwidth = 640; - ga_lastwabheight = 480; - ga_reqChangeWindowSize = 0; - - // パレットを更新させる - np2wab.paletteChanged = 1; -} -// リセット時に呼ばれる?(np2net_resetより後・iocore_attach〜が使える) -void np2wab_bind(void) -{ -#if defined(NP2_WIN) - DWORD dwID; - - // マルチスレッドモードなら先にスレッド処理を終了させる - if(ga_threadmode && ga_hThread){ - ga_exitThread = 1; - //while(((int)ResumeThread(ga_hThread))>0); - //while(WaitForSingleObject(ga_hThread, 200)==WAIT_TIMEOUT){ - // ResumeThread(ga_hThread); - //} - SetEvent(wab_thread_eventhandle); - if(WaitForSingleObject(ga_hThread, 4000)==WAIT_TIMEOUT){ - TerminateThread(ga_hThread, 0); - } - CloseHandle(ga_hThread); - ga_hThread = NULL; - ga_exitThread = 0; - } -#endif - - // I/Oポートマッピング(FAChは内蔵リレー切り替え) - iocore_attachout(0xfac, np2wab_ofac); - iocore_attachinp(0xfac, np2wab_ifac); - - // 設定値更新とか - np2wabwnd.multiwindow = np2wabcfg.multiwindow; - ga_threadmode = np2wabcfg.multithread; - - //// 画面消去 - //BitBlt(np2wabwnd.hDCBuf , 0 , 0 , WAB_MAX_WIDTH , WAB_MAX_HEIGHT , NULL , 0 , 0 , BLACKNESS); - //scrnmng_blthdc(np2wabwnd.hDCBuf); - -#if defined(NP2_WIN) - // マルチスレッドモードならスレッド開始 - if(ga_threadmode){ - ga_hThread = (HANDLE)_beginthreadex(NULL , 0 , ga_ThreadFunc , NULL , 0 , &dwID); - } -#endif - - // パレットを更新させる - np2wab.paletteChanged = 1; - - // 描画再開 - np2wabwnd.ready = 1; -} -void np2wab_unbind(void) -{ - iocore_detachout(0xfac); - iocore_detachinp(0xfac); -} -// NP2終了時の処理 -void np2wab_shutdown() -{ -#if defined(NP2_WIN) - // マルチスレッドモードなら先にスレッド処理を終了させる - ga_exitThread = 1; - //while(((int)ResumeThread(ga_hThread))>0); - //if(WaitForSingleObject(ga_hThread, 1000)==WAIT_TIMEOUT){ - // ResumeThread(ga_hThread); - //} - SetEvent(wab_thread_eventhandle); - if(WaitForSingleObject(ga_hThread, 4000)==WAIT_TIMEOUT){ - TerminateThread(ga_hThread, 0); // 諦めて強制終了 - } - CloseHandle(ga_hThread); - ga_hThread = NULL; - - // いろいろ解放 - DeleteDC(np2wabwnd.hDCBuf); - DeleteObject(np2wabwnd.hBmpBuf); - ReleaseDC(np2wabwnd.hWndWAB, np2wabwnd.hDCWAB); - np2wabwnd.hDCWAB = NULL; - DestroyWindow(np2wabwnd.hWndWAB); - np2wabwnd.hWndWAB = NULL; -#elif defined(NP2_X) - g_object_unref(np2wabwnd.pPixbuf); -#else - free(np2wabwnd.pBuffer); -#endif - - // クリティカルセクション破棄 - wab_delete_criticalsection(); - - //// 専用INIセクション書き込み - //wabwin_writeini(); -} - -// 内蔵ディスプレイ切り替えリレー状態を設定する。stateのbit0は外部アクセラ(=1)/内蔵アクセラ(=0)切替、bit1は内蔵アクセラ(=1)/98グラフ(=0)切替。他は0。 -// 外部・内部の区別をしていないので事実上どちらかのビットが1ならアクセラレータ表示になる -void np2wab_setRelayState(REG8 state) -{ - // bit0,1が変化しているか確認 - if((np2wab.relay & 0x3) != (state & 0x3)){ - np2wab.relay = state & 0x3; - if(state&0x3){ - // リレーがON -#if defined(NP2_WIN) - if(!np2cfg.wabasw) soundmng_pcmplay(SOUND_RELAY1, FALSE); // カチッ -#else - if(!np2cfg.wabasw) wabrly_switch(); // カチッ -#endif - if(np2wabwnd.multiwindow){ - // 別窓モードなら別窓を出す -#if defined(NP2_WIN) - ShowWindow(np2wabwnd.hWndWAB, SW_SHOWNOACTIVATE); - SetWindowPos(np2wabwnd.hWndWAB, HWND_TOP, np2wabcfg.posx, np2wabcfg.posy, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOSENDCHANGING | SWP_SHOWWINDOW); -#endif - }else{ - // 統合モードなら画面を乗っ取る -#if defined(SUPPORT_MULTITHREAD) - if(np2_multithread_Enabled()){ - np2wab_setScreenSizeMT(ga_lastwabwidth, ga_lastwabheight); - }else -#endif - { - np2wab_setScreenSize(ga_lastwabwidth, ga_lastwabheight); - } - } - }else{ - // リレーがOFF -#if defined(NP2_WIN) - if(!np2cfg.wabasw) soundmng_pcmplay(SOUND_RELAY1, FALSE); // カチッ -#else - if(!np2cfg.wabasw) wabrly_switch(); // カチッ -#endif - if(np2wabwnd.multiwindow){ - // 別窓モードなら別窓を消す - np2wab.lastWidth = 0; - np2wab.lastHeight = 0; -#if defined(NP2_WIN) - ShowWindow(np2wabwnd.hWndWAB, SW_HIDE); -#endif - }else{ - // 統合モードなら画面を戻す - np2wab.lastWidth = 0; - np2wab.lastHeight = 0; -#if defined(NP2_WIN) - scrnmng_setsize(dsync.scrnxpos, 0, dsync.scrnxmax, dsync.scrnymax);// XXX: 画面サイズを乗っ取る前に戻す -#else - scrnmng_setwidth(dsync.scrnxpos, dsync.scrnxmax); // XXX: 画面幅を乗っ取る前に戻す - scrnmng_setheight(0, dsync.scrnymax); // XXX: 画面高さを乗っ取る前に戻す -#endif - scrnmng_updatefsres(); // フルスクリーン解像度更新 -#if defined(NP2_WIN) - mousemng_updateclip(); // マウスキャプチャのクリップ範囲を修正 -#endif - } - } - } -} - -/** - * ウィンドウアクセラレータ画面をBMPで取得 - */ -BRESULT np2wab_getbmp(BMPFILE *lpbf, BMPINFO *lpbi, UINT8 **lplppal, UINT8 **lplppixels) { - - BMPDATA bd; - BMPFILE bf; - UINT pos; - BMPINFO bi; - BMPINFO bitmp; - UINT align; - //int r; - //int x; - UINT8 *dstpix; -#if defined(NP2_WIN) - LPVOID lpbits; -#else - void* lpbits; -#endif - UINT8 *buf; -#if defined(NP2_WIN) - HBITMAP hBmpTmp; -#endif - - // 24bit固定 - bd.width = np2wab.wndWidth; - bd.height = np2wab.wndHeight; - bd.bpp = 24; - - // Bitmap File - ZeroMemory(&bf, sizeof(bf)); - bf.bfType[0] = 'B'; - bf.bfType[1] = 'M'; - pos = sizeof(BMPFILE) + sizeof(BMPINFO); - STOREINTELDWORD(bf.bfOffBits, pos); - - // Bitmap Info - bmpdata_setinfo(&bi, &bd); - STOREINTELDWORD(bi.biClrImportant, 0); - align = bmpdata_getalign(&bi); - CopyMemory(lpbi, &bi, sizeof(bi)); - *lplppal = (UINT8*)malloc(0); // freeで解放されても大丈夫なように(大抵NULLが入る) - - // Bitmap File (size) - STOREINTELDWORD(bf.bfSize, (sizeof(BMPFILE) + sizeof(BMPINFO) + 0 + bmpdata_getalign(&bi) * bd.height)); - CopyMemory(lpbf, &bf, sizeof(bf)); - - *lplppixels = (UINT8*)malloc(bmpdata_getalign(&bi) * bd.height); - dstpix = *lplppixels; - - // Copy Pixels - bitmp = bi; - STOREINTELDWORD(bitmp.biWidth, WAB_MAX_WIDTH); - STOREINTELDWORD(bitmp.biHeight, WAB_MAX_HEIGHT); -#if defined(NP2_WIN) - hBmpTmp = CreateDIBSection(NULL, (LPBITMAPINFO)&bitmp, DIB_RGB_COLORS, &lpbits, NULL, 0); - GetDIBits(np2wabwnd.hDCBuf, np2wabwnd.hBmpBuf, 0, WAB_MAX_HEIGHT, lpbits, (LPBITMAPINFO)&bitmp, DIB_RGB_COLORS); - buf = (UINT8*)(lpbits) + (WAB_MAX_HEIGHT - bd.height) * WAB_MAX_WIDTH*bd.bpp/8; -#elif defined(NP2_X) - buf = (UINT8*)(gdk_pixbuf_get_pixels(np2wabwnd.pPixbuf)) + (np2wab.wndHeight - 1) * WAB_MAX_WIDTH*bd.bpp/8; -#else - buf = (UINT8*)(np2wabwnd.pBuffer) + (np2wab.wndHeight - 1) * np2wab.wndWidth*4; -#endif - do { -#if defined(NP2_WIN) - CopyMemory(dstpix, buf, np2wab.wndWidth*bd.bpp/8); - dstpix += align; - buf += WAB_MAX_WIDTH*bd.bpp/8; -#elif defined(NP2_X) - CopyMemory(dstpix, buf, np2wab.wndWidth*bd.bpp/8); - dstpix += align; - buf -= WAB_MAX_WIDTH*bd.bpp/8; -#else - int i; - for(i = 0; i < np2wab.wndWidth; i++) { - ((UINT8*)dstpix)[i * 3 ] = ((UINT8*)buf)[i * 4 ]; - ((UINT8*)dstpix)[i * 3 + 1] = ((UINT8*)buf)[i * 4 + 1]; - ((UINT8*)dstpix)[i * 3 + 2] = ((UINT8*)buf)[i * 4 + 2]; - } - dstpix += np2wab.wndWidth*3; - buf -= np2wab.wndWidth*4; -#endif - } while(--bd.height); -#if defined(NP2_WIN) - DeleteObject(hBmpTmp); -#elif defined(NP2_X) - { - int i, j; - UINT8 tmp; - dstpix = *lplppixels; - for(j = 0; j < np2wab.wndHeight; j++) { - for(i = 0; i < np2wab.wndWidth; i++) { - tmp = dstpix[(j * np2wab.wndWidth + i) * 3]; - dstpix[(j * np2wab.wndWidth + i) * 3] = dstpix[(j * np2wab.wndWidth + i) * 3 + 2]; - dstpix[(j * np2wab.wndWidth + i) * 3 + 2] = tmp; - } - } - } -#endif - - return(SUCCESS); -} - -/** - * ウィンドウアクセラレータ画面をBMPで保存 - */ -BRESULT np2wab_writebmp(const OEMCHAR *filename) { - - FILEH fh; - BMPFILE bf; - BMPINFO bi; - UINT8 *lppal; - UINT8 *lppixels; - int pixelssize; - - fh = file_create(filename); - if (fh == FILEH_INVALID) { - goto sswb_err1; - } - - np2wab_getbmp(&bf, &bi, &lppal, &lppixels); - - // Bitmap File - if (file_write(fh, &bf, sizeof(bf)) != sizeof(bf)) { - goto sswb_err3; - } - - // Bitmap Info (パレット不要) - if (file_write(fh, &bi, sizeof(bi)) != sizeof(bi)) { - goto sswb_err3; - } - - // Pixels - pixelssize = bmpdata_getalign(&bi) * LOADINTELDWORD(bi.biHeight); - if (file_write(fh, lppixels, pixelssize) != pixelssize) { - goto sswb_err3; - } - - _MFREE(lppal); - _MFREE(lppixels); - - file_close(fh); - - return(SUCCESS); - -sswb_err3: - _MFREE(lppal); - _MFREE(lppixels); - -//sswb_err2: -// file_close(fh); -// file_delete(filename); - -sswb_err1: - return(FAILURE); -} - -#endif /* SUPPORT_WAB */ +/** + * @file wab.c + * @brief Window Accelerator Board Interface + * + * @author $Author: SimK $ + */ + +#include + +#if defined(SUPPORT_WAB) + +#include "np2.h" +#if defined(NP2_WIN) +#include "np2mt.h" +#include "resource.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(NP2_WIN) +#include "winkbd.h" +#include "winloc.h" +#endif +#include +#include "ini.h" +#include +#include +#include +#include +#if defined(NP2_WIN) +#include +#endif +#include +#if defined(NP2_X) +#include +#endif + +NP2WAB np2wab = {0}; +NP2WABWND np2wabwnd = {0}; +NP2WABCFG np2wabcfg; + +#if defined(NP2_WIN) +TCHAR g_Name[100] = _T("NP2 Window Accelerator"); +#else +char g_Name[100] = "NP2 Window Accelerator"; +#endif + +#if defined(NP2_WIN) +static HINSTANCE ga_hInstance = NULL; +static HANDLE ga_hThread = NULL; +#endif +static int ga_exitThread = 0; +#if defined(NP2_WIN) +static int ga_threadmode = 1; +#else +static int ga_threadmode = 0; +#endif +static int ga_lastwabwidth = 640; +static int ga_lastwabheight = 480; +static int ga_reqChangeWindowSize = 0; +static int ga_reqChangeWindowSize_w = 0; +static int ga_reqChangeWindowSize_h = 0; + +static int ga_lastscalemode = 0; +static int ga_lastrealwidth = 0; +static int ga_lastrealheight = 0; +static int ga_screenupdated = 0; + +#if defined(NP2_WIN) +static int wab_cs_initialized = 0; +static CRITICAL_SECTION wab_cs; +static HANDLE wab_thread_eventhandle = INVALID_HANDLE_VALUE; +#endif + +static int np2wab_forceupdateflag = 0; + +static BOOL wab_tryenter_criticalsection(void){ +#if defined(NP2_WIN) + if(!wab_cs_initialized) return TRUE; + return TryEnterCriticalSection(&wab_cs); +#else + return TRUE; +#endif +} +static void wab_enter_criticalsection(void){ +#if defined(NP2_WIN) + if(!wab_cs_initialized) return; + EnterCriticalSection(&wab_cs); +#endif +} +static void wab_leave_criticalsection(void){ +#if defined(NP2_WIN) + if(!wab_cs_initialized) return; + LeaveCriticalSection(&wab_cs); +#endif +} +static void wab_init_criticalsection(void){ +#if defined(NP2_WIN) + if(!wab_cs_initialized){ + memset(&wab_cs, 0, sizeof(wab_cs)); + wab_thread_eventhandle = CreateEvent(NULL, FALSE, FALSE, NULL); + InitializeCriticalSection(&wab_cs); + wab_cs_initialized = 1; + } +#endif +} +static void wab_delete_criticalsection(void){ +#if defined(NP2_WIN) + if(wab_cs_initialized){ + DeleteCriticalSection(&wab_cs); + CloseHandle(wab_thread_eventhandle); + wab_cs_initialized = 0; + } +#endif +} + +/** + * 設定 + */ +#if defined(NP2_WIN) +static const PFTBL s_wabwndini[] = +{ + PFVAL("WindposX", PFTYPE_SINT32, &np2wabcfg.posx), + PFVAL("WindposY", PFTYPE_SINT32, &np2wabcfg.posy), + PFVAL("MULTIWND", PFTYPE_BOOL, &np2wabcfg.multiwindow), + PFVAL("MULTHREAD",PFTYPE_BOOL, &np2wabcfg.multithread), + PFVAL("HALFTONE", PFTYPE_BOOL, &np2wabcfg.halftone), +}; +#else +static const INITBL s_wabwndini[] = +{ + {OEMTEXT("WindposX"), INITYPE_SINT32, &np2wabcfg.posx, 0}, + {OEMTEXT("WindposY"), INITYPE_SINT32, &np2wabcfg.posy, 0}, + {OEMTEXT("MULTIWND"), INITYPE_BOOL, &np2wabcfg.multiwindow, 0}, + {OEMTEXT("MULTHREAD"), INITYPE_BOOL, &np2wabcfg.multithread, 0}, + {OEMTEXT("HALFTONE"), INITYPE_BOOL, &np2wabcfg.halftone, 0}, +}; +#endif + +/** + * 設定読み込み + */ +void wabwin_readini() +{ + OEMCHAR szPath[MAX_PATH]; + +#if defined(NP2_WIN) + ZeroMemory(&np2wabcfg, sizeof(np2wabcfg)); + np2wabcfg.posx = CW_USEDEFAULT; + np2wabcfg.posy = CW_USEDEFAULT; + np2wabcfg.multithread = 1; +#else + memset(&np2wabcfg, 0, sizeof(np2wabcfg)); + np2wabcfg.posx = 0; + np2wabcfg.posy = 0; + np2wabcfg.multithread = 0; +#endif + np2wabcfg.multiwindow = 0; + np2wabcfg.halftone = 0; + +#if defined(NP2_WIN) + initgetfile(szPath, NELEMENTS(szPath)); +#else + milstr_ncpy(szPath, modulefile, sizeof(szPath)); +#endif + ini_read(szPath, g_Name, s_wabwndini, NELEMENTS(s_wabwndini)); +} + +/** + * 設定書き込み + */ +void np2wab_forceupdate() +{ + np2wab_forceupdateflag = 1; +} + +/** + * 設定書き込み + */ +void wabwin_writeini() +{ + if(!np2wabcfg.readonly){ + TCHAR szPath[MAX_PATH]; +#if defined(NP2_WIN) + initgetfile(szPath, NELEMENTS(szPath)); + ini_write(szPath, g_Name, s_wabwndini, NELEMENTS(s_wabwndini)); +#elif defined(NP2_X) + milstr_ncpy(szPath, modulefile, sizeof(szPath)); + ini_write(szPath, g_Name, s_wabwndini, NELEMENTS(s_wabwndini), FALSE); +#else + milstr_ncpy(szPath, modulefile, sizeof(szPath)); + ini_write(szPath, g_Name, s_wabwndini, NELEMENTS(s_wabwndini)); +#endif + } +} + +void scrnmng_updatefsres(void); +#ifdef EMSCRIPTEN +void scrnmng_blthdc(void); +#endif +void scrnmng_bltwab(void); + +/** + * 画面サイズ設定 + */ +void np2wab_setScreenSize(int width, int height) +{ + if(np2wabwnd.multiwindow){ +#if defined(NP2_WIN) + // 別窓モードなら別窓サイズを更新する + RECT rect = { 0, 0, width, height }; + np2wab.wndWidth = width; + np2wab.wndHeight = height; + AdjustWindowRectEx( &rect, WS_OVERLAPPEDWINDOW, FALSE, 0 ); + SetWindowPos( np2wabwnd.hWndWAB, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE|SWP_NOZORDER ); +#elif defined(NP2_X) + np2wab.wndWidth = width; + np2wab.wndHeight = height; + gtk_widget_set_size_request(np2wabwnd.pWABWnd, width, height); +#endif + }else{ + // 統合モードならエミュレーション領域サイズを更新する + np2wab.wndWidth = ga_lastwabwidth = width; + np2wab.wndHeight = ga_lastwabheight = height; + if(np2wab.relay & 0x3){ + if(width < 32 || height < 32){ +#if defined(NP2_WIN) + scrnmng_setsize(0, 0, 640, 480); +#else + scrnmng_setwidth(0, 640); + scrnmng_setheight(0, 480); +#endif + }else{ +#if defined(NP2_WIN) + scrnmng_setsize(0, 0, width, height); +#else + scrnmng_setwidth(0, width); + scrnmng_setheight(0, height); +#endif + } + scrnmng_updatefsres(); // フルスクリーン解像度更新 +#if defined(NP2_WIN) + mousemng_updateclip(); // マウスキャプチャのクリップ範囲を修正 +#endif + } + } + // とりあえずパレットは更新しておく + np2wab.paletteChanged = 1; + + // 画面更新 + np2wab_forceupdateflag = 1; +} +/** + * 画面サイズ設定マルチスレッド対応版(すぐに更新できない場合はnp2wab.ready=0に) + */ +void np2wab_setScreenSizeMT(int width, int height) +{ + if(!ga_threadmode){ + // マルチスレッドモードでなければ直接呼び出し + np2wab_setScreenSize(width, height); + ga_lastrealwidth = width; + ga_lastrealheight = height; + }else{ + // マルチスレッドモードなら画面サイズ変更要求を出す + ga_reqChangeWindowSize_w = width; + ga_reqChangeWindowSize_h = height; + ga_reqChangeWindowSize = 1; + np2wabwnd.ready = 0; // 更新待ち + } + + // 画面更新 + np2wab_forceupdateflag = 1; +} + +/** + * ウィンドウアクセラレータ別窓を等倍サイズに戻す + */ +void np2wab_resetscreensize() +{ + if(np2wabwnd.multiwindow){ +#if defined(NP2_WIN) + RECT rect = {0}; + rect.right = np2wab.wndWidth = np2wab.realWidth; + rect.bottom = np2wab.wndHeight = np2wab.realHeight; + AdjustWindowRectEx( &rect, WS_OVERLAPPEDWINDOW, FALSE, 0 ); + SetWindowPos( np2wabwnd.hWndWAB, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, SWP_NOMOVE|SWP_NOZORDER ); +#elif defined(NP2_X) + np2wab.wndWidth = np2wab.realWidth; + np2wab.wndHeight = np2wab.realHeight; + gtk_widget_set_size_request(np2wabwnd.pWABWnd, np2wab.realWidth, np2wab.realHeight); +#endif + } + + // 画面更新 + np2wab_forceupdateflag = 1; +} + +#if defined(NP2_WIN) +/** + * ウィンドウアクセラレータ別窓WndProc + */ +LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ + RECT rc; + HMENU hSysMenu; + HMENU hWabMenu; + MENUITEMINFO mii = {0}; + TCHAR szString[128]; + int scalemode; + + switch (msg) { + case WM_CREATE: + hSysMenu = GetSystemMenu(hWnd, FALSE); + hWabMenu = LoadMenu(ga_hInstance, MAKEINTRESOURCE(IDR_WABSYSMENU)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA; + mii.dwTypeData = szString; + mii.cch = NELEMENTS(szString); + GetMenuItemInfo(hWabMenu, 0, TRUE, &mii); + InsertMenuItem(hSysMenu, 0, TRUE, &mii); + mii.dwTypeData = szString; + mii.cch = NELEMENTS(szString); + GetMenuItemInfo(hWabMenu, 1, TRUE, &mii); + InsertMenuItem(hSysMenu, 0, TRUE, &mii); + CheckMenuItem(hSysMenu, IDM_WABSYSMENU_HALFTONE, MF_BYCOMMAND | (np2wabcfg.halftone ? MF_CHECKED : MF_UNCHECKED)); + DestroyMenu(hWabMenu); + + break; + + case WM_SYSCOMMAND: + switch(wParam) { + case IDM_WABSYSMENU_RESETSIZE: + np2wab_resetscreensize(); + break; + + case IDM_WABSYSMENU_HALFTONE: + np2wabcfg.halftone = !np2wabcfg.halftone; + hSysMenu = GetSystemMenu(hWnd, FALSE); + CheckMenuItem(hSysMenu, IDM_WABSYSMENU_HALFTONE, MF_BYCOMMAND | (np2wabcfg.halftone ? MF_CHECKED : MF_UNCHECKED)); + scalemode = np2wab.wndWidth!=np2wab.realWidth || np2wab.wndHeight!=np2wab.realHeight; + if(scalemode){ + SetStretchBltMode(np2wabwnd.hDCWAB, np2wabcfg.halftone ? HALFTONE : COLORONCOLOR); + SetBrushOrgEx(np2wabwnd.hDCWAB , 0 , 0 , NULL); + } + break; + + default: + return(DefWindowProc(hWnd, msg, wParam, lParam)); + } + break; + + case WM_MOVE: + GetWindowRect(hWnd, &rc); + if(np2wabwnd.multiwindow && !IsZoomed(hWnd) && !IsIconic(hWnd) && IsWindowVisible(hWnd)){ + np2wabcfg.posx = rc.left; + np2wabcfg.posy = rc.top; + } + break; + + case WM_ENTERSIZEMOVE: + break; + + case WM_MOVING: + break; + + case WM_SIZE: + np2wab_forceupdate(); + case WM_SIZING: + GetClientRect( hWnd, &rc ); + np2wab.wndWidth = rc.right - rc.left; + np2wab.wndHeight = rc.bottom - rc.top; + break; + + case WM_EXITSIZEMOVE: + break; + + case WM_KEYDOWN: + SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // 必殺丸投げ + break; + + case WM_KEYUP: + SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // 必殺丸投げ + break; + + case WM_SYSKEYDOWN: + SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // 必殺丸投げ + break; + + case WM_SYSKEYUP: + SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // 必殺丸投げ + break; + + case WM_MOUSEMOVE: + SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // 必殺丸投げ + break; + + case WM_LBUTTONDOWN: + if(np2wabwnd.multiwindow){ + SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // やはり丸投げ + } + break; + + case WM_LBUTTONUP: + if(np2wabwnd.multiwindow){ + SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // ここも丸投げ + } + break; + + case WM_RBUTTONDOWN: + if(np2wabwnd.multiwindow){ + SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // そのまま丸投げ + } + break; + + case WM_RBUTTONUP: + if(np2wabwnd.multiwindow){ + SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // なんでも丸投げ + } + break; + + case WM_MBUTTONDOWN: + SetForegroundWindow(np2wabwnd.hWndMain); + SendMessage(np2wabwnd.hWndMain, msg, wParam, lParam); // とりあえず丸投げ + break; + + case WM_CLOSE: + return 0; + + case WM_DESTROY: + break; + + default: + return(DefWindowProc(hWnd, msg, wParam, lParam)); + } + return(0L); +} +#endif + +/** + * ウィンドウアクセラレータ画面転送 + * 別窓モード: GDI Device Independent Bitmap -> GDI Window + * 統合モード: GDI Device Independent Bitmap -> Direct3D/DirectDraw WAB surface ( call scrnmng_blthdc() ) + */ +#if defined(NP2_WIN) +void np2wab_drawWABWindow(HDC hdc) +#else +void np2wab_drawWABWindow(void) +#endif +{ + int scalemode = 0; + int srcwidth = np2wab.realWidth; + int srcheight = np2wab.realHeight; + if(ga_lastrealwidth != srcwidth || ga_lastrealheight != srcheight){ + // 解像度が変わっていたらウィンドウサイズも変える + if(!ga_reqChangeWindowSize){ + np2wab.paletteChanged = 1; + np2wab_setScreenSizeMT(srcwidth, srcheight); + } + if(!np2wabwnd.ready) return; + } + if(np2wabwnd.multiwindow){ // 別窓モード判定 + scalemode = np2wab.wndWidth!=srcwidth || np2wab.wndHeight!=srcheight; + if(ga_lastscalemode!=scalemode){ // 画面スケールが変わりました + if(scalemode){ + // 通常はCOLORONCOLOR。HALFTONEにも設定できるけど拡大の補間が微妙・・・ +#if defined(NP2_WIN) + SetStretchBltMode(np2wabwnd.hDCWAB, np2wabcfg.halftone ? HALFTONE : COLORONCOLOR); + SetBrushOrgEx(np2wabwnd.hDCWAB , 0 , 0 , NULL); +#endif + }else{ +#if defined(NP2_WIN) + SetStretchBltMode(np2wabwnd.hDCWAB, BLACKONWHITE); +#endif + } + ga_lastscalemode = scalemode; + np2wab.paletteChanged = 1; + } + if(scalemode){ + // 拡大縮小転送。とりあえず画面比は維持 + if(np2wab.wndWidth * srcheight > srcwidth * np2wab.wndHeight){ + // 横長 + int dstw = srcwidth * np2wab.wndHeight / srcheight; + int dsth = np2wab.wndHeight; + int mgnw = (np2wab.wndWidth - dstw); + int shx = 0; + if(mgnw&0x1) shx = 1; + mgnw = mgnw>>1; +#if defined(NP2_WIN) + BitBlt(np2wabwnd.hDCWAB, 0, 0, mgnw, np2wab.wndHeight, NULL, 0, 0, BLACKNESS); + BitBlt(np2wabwnd.hDCWAB, np2wab.wndWidth-mgnw-shx, 0, mgnw+shx, np2wab.wndHeight, NULL, 0, 0, BLACKNESS); + StretchBlt(np2wabwnd.hDCWAB, mgnw, 0, dstw, dsth, np2wabwnd.hDCBuf, 0, 0, srcwidth, srcheight, SRCCOPY); +#endif + }else if(np2wab.wndWidth * srcheight < srcwidth * np2wab.wndHeight){ + // 縦長 + int dstw = np2wab.wndWidth; + int dsth = srcheight * np2wab.wndWidth / srcwidth; + int mgnh = (np2wab.wndHeight - dsth); + int shy = 0; + if(mgnh&0x1) shy = 1; + mgnh = mgnh>>1; +#if defined(NP2_WIN) + BitBlt(np2wabwnd.hDCWAB, 0, 0, np2wab.wndWidth, mgnh, NULL, 0, 0, BLACKNESS); + BitBlt(np2wabwnd.hDCWAB, 0, np2wab.wndHeight-mgnh-shy, np2wab.wndWidth, mgnh+shy, NULL, 0, 0, BLACKNESS); + StretchBlt(np2wabwnd.hDCWAB, 0, mgnh, dstw, dsth, np2wabwnd.hDCBuf, 0, 0, srcwidth, srcheight, SRCCOPY); +#endif + }else{ +#if defined(NP2_WIN) + StretchBlt(np2wabwnd.hDCWAB, 0, 0, np2wab.wndWidth, np2wab.wndHeight, np2wabwnd.hDCBuf, 0, 0, srcwidth, srcheight, SRCCOPY); +#endif + } + }else{ + // 等倍転送 +#if defined(NP2_WIN) + BitBlt(np2wabwnd.hDCWAB, 0, 0, srcwidth, srcheight, np2wabwnd.hDCBuf, 0, 0, SRCCOPY); +#endif + } + }else{ + // DirectDrawに描かせる + //scrnmng_blthdc(np2wabwnd.hDCBuf); + // DirectDraw Surfaceに転送 +#if defined(NP2_WIN) + scrnmng_blthdc(np2wabwnd.hDCBuf); +#else + scrnmng_blthdc(); +#endif + } +} + +/** + * 同期描画(ga_threadmodeが偽) + */ +void np2wab_drawframe() +{ +#if defined(NP2_WIN) + if(!ga_threadmode){ + if(np2wabwnd.ready && np2wabwnd.hWndWAB!=NULL && (np2wab.relay&0x3)!=0){ +#endif + // マルチスレッドじゃない場合はここで描画処理 + if (np2wabwnd.drawframe()) + { +#if defined(NP2_WIN) + np2wab_drawWABWindow(np2wabwnd.hDCBuf); +#else + np2wab_drawWABWindow(); +#endif + if (!np2wabwnd.multiwindow) + { + scrnmng_bltwab(); + scrnmng_update(); + } + } +#if defined(NP2_WIN) + } + }else{ + if(np2wabwnd.hWndWAB!=NULL){ + if(ga_reqChangeWindowSize){ + // 画面サイズ変更要求が来ていたら画面サイズを変える + np2wab_setScreenSize(ga_reqChangeWindowSize_w, ga_reqChangeWindowSize_h); + ga_lastrealwidth = ga_reqChangeWindowSize_w; + ga_lastrealheight = ga_reqChangeWindowSize_h; + ga_reqChangeWindowSize = 0; + np2wabwnd.ready = 1; + } + if(np2wabwnd.ready && (np2wab.relay&0x3)!=0){ + if(ga_screenupdated){ + wab_enter_criticalsection(); + if(!np2wabwnd.multiwindow){ + //np2wab_drawWABWindow(np2wabwnd.hDCBuf); // ga_ThreadFuncでやる + scrnmng_bltwab(); + } + ga_screenupdated = 0; + if(!np2wabwnd.multiwindow){ + // XXX: ウィンドウアクセラレータ動作中は内蔵グラフィックを描画しない + scrnmng_update(); + } + wab_leave_criticalsection(); + } + SetEvent(wab_thread_eventhandle); + } + } + } +#endif +} + +#if defined(NP2_WIN) +/** + * 非同期描画(ga_threadmodeが真) + */ +unsigned int __stdcall ga_ThreadFunc(LPVOID vdParam) { + static int skipcounter = 0; + int timeleft = 0; + while (WaitForSingleObject(wab_thread_eventhandle, INFINITE) == WAIT_OBJECT_0) + { + if (ga_exitThread || !ga_threadmode) break; + + //wab_enter_criticalsection(); + //wab_leave_criticalsection(); + if(np2wabwnd.ready && np2wabwnd.hWndWAB!=NULL && np2wabwnd.drawframe!=NULL && (np2wab.relay&0x3)!=0){ + if (np2wabwnd.drawframe() || np2wab_forceupdateflag) + { + np2wab_forceupdateflag = 0; + np2wab_drawWABWindow(np2wabwnd.hDCBuf); + //// 画面転送待ち + ga_screenupdated = 1; + skipcounter = 0; + } + } + } + ga_threadmode = 0; + return 0; +} +#endif + +/** + * 画面出力リレー制御 + */ +static void IOOUTCALL np2wab_ofac(UINT port, REG8 dat) { + TRACEOUT(("WAB: out FACh set relay %04X d=%02X", port, dat)); + dat = dat & ~0xfc; + if(np2wab.relaystateext != dat){ + np2wab.relaystateext = dat & 0x3; + np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); // リレーはORで・・・(暫定やっつけ修正) + } + (void)port; + (void)dat; +} +static REG8 IOINPCALL np2wab_ifac(UINT port) { + //TRACEOUT(("WAB: inp FACh get relay %04X", port)); + return 0xfc | np2wab.relaystateext; +} + +// NP2起動時の処理 +#if defined(NP2_WIN) +void np2wab_init(HINSTANCE hInstance, HWND hWndMain) +#else +void np2wab_init(void) +#endif +{ +#if defined(NP2_WIN) + WNDCLASSEX wcex = {0}; + HDC hdc; +#endif + + // クリティカルセクション初期化 + wab_init_criticalsection(); + + //// 専用INIセクション読み取り + //wabwin_readini(); + +#if defined(NP2_WIN) + // 後々要る物を保存しておく + ga_hInstance = hInstance; + np2wabwnd.hWndMain = hWndMain; + + // ウィンドウアクセラレータ別窓を作る + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW | (np2wabwnd.multiwindow ? CS_DBLCLKS : 0); + wcex.lpfnWndProc = WndProc; + wcex.hInstance = ga_hInstance; + wcex.hIcon = LoadIcon(ga_hInstance, MAKEINTRESOURCE(IDI_ICON1)); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); + wcex.lpszClassName = (TCHAR*)g_Name; + if(!RegisterClassEx(&wcex)) return; + np2wabwnd.hWndWAB = CreateWindowEx( + 0, + g_Name, g_Name, + WS_OVERLAPPEDWINDOW, + np2wabcfg.posx, np2wabcfg.posy, + 640, 480, + np2wabwnd.multiwindow ? NULL : np2wabwnd.hWndMain, + NULL, ga_hInstance, NULL + ); + if(!np2wabwnd.hWndWAB) return; + + // HWNDとかHDCとかバッファ用ビットマップとかを先に作っておく + np2wabwnd.hDCWAB = GetDC(np2wabwnd.hWndWAB); + hdc = np2wabwnd.multiwindow ? GetDC(NULL) : np2wabwnd.hDCWAB; + np2wabwnd.hBmpBuf = CreateCompatibleBitmap(hdc, WAB_MAX_WIDTH, WAB_MAX_HEIGHT); + np2wabwnd.hDCBuf = CreateCompatibleDC(hdc); + SelectObject(np2wabwnd.hDCBuf, np2wabwnd.hBmpBuf); +#elif defined(NP2_X) + np2wabwnd.pPixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, WAB_MAX_WIDTH, WAB_MAX_HEIGHT); +#else + np2wabwnd.pBuffer = (unsigned int*)malloc(WAB_MAX_WIDTH * WAB_MAX_HEIGHT * sizeof(unsigned int)); +#endif + +} +// リセット時に呼ばれる? +void np2wab_reset(const NP2CFG *pConfig) +{ +#if defined(NP2_WIN) + // マルチスレッドモードなら先にスレッド処理を終了させる + if(ga_threadmode && ga_hThread){ + ga_exitThread = 1; + //while(((int)ResumeThread(ga_hThread))>0); + //while(WaitForSingleObject(ga_hThread, 200)==WAIT_TIMEOUT){ + // ResumeThread(ga_hThread); + //} + SetEvent(wab_thread_eventhandle); + if(WaitForSingleObject(ga_hThread, 4000)==WAIT_TIMEOUT){ + TerminateThread(ga_hThread, 0); + } + CloseHandle(ga_hThread); + ga_hThread = NULL; + ga_exitThread = 0; + } +#endif + + // 描画を停止して設定初期化 + np2wabwnd.ready = 0; + ga_lastscalemode = 0; + ga_lastrealwidth = 0; + ga_lastrealheight = 0; + ga_screenupdated = 0; + np2wab.lastWidth = 0; + np2wab.lastHeight = 0; + np2wab.realWidth = 0; + np2wab.realHeight = 0; + np2wab.relaystateint = 0; + np2wab_setRelayState(np2wab.relaystateint|np2wab.relaystateext); + + // 設定値更新とか + np2wab.wndWidth = 640; + np2wab.wndHeight = 480; + np2wab.fps = 60; + ga_lastwabwidth = 640; + ga_lastwabheight = 480; + ga_reqChangeWindowSize = 0; + + // パレットを更新させる + np2wab.paletteChanged = 1; +} +// リセット時に呼ばれる?(np2net_resetより後・iocore_attach〜が使える) +void np2wab_bind(void) +{ +#if defined(NP2_WIN) + DWORD dwID; + + // マルチスレッドモードなら先にスレッド処理を終了させる + if(ga_threadmode && ga_hThread){ + ga_exitThread = 1; + //while(((int)ResumeThread(ga_hThread))>0); + //while(WaitForSingleObject(ga_hThread, 200)==WAIT_TIMEOUT){ + // ResumeThread(ga_hThread); + //} + SetEvent(wab_thread_eventhandle); + if(WaitForSingleObject(ga_hThread, 4000)==WAIT_TIMEOUT){ + TerminateThread(ga_hThread, 0); + } + CloseHandle(ga_hThread); + ga_hThread = NULL; + ga_exitThread = 0; + } +#endif + + // I/Oポートマッピング(FAChは内蔵リレー切り替え) + iocore_attachout(0xfac, np2wab_ofac); + iocore_attachinp(0xfac, np2wab_ifac); + + // 設定値更新とか + np2wabwnd.multiwindow = np2wabcfg.multiwindow; + ga_threadmode = np2wabcfg.multithread; + + //// 画面消去 + //BitBlt(np2wabwnd.hDCBuf , 0 , 0 , WAB_MAX_WIDTH , WAB_MAX_HEIGHT , NULL , 0 , 0 , BLACKNESS); + //scrnmng_blthdc(np2wabwnd.hDCBuf); + +#if defined(NP2_WIN) + // マルチスレッドモードならスレッド開始 + if(ga_threadmode){ + ga_hThread = (HANDLE)_beginthreadex(NULL , 0 , ga_ThreadFunc , NULL , 0 , &dwID); + } +#endif + + // パレットを更新させる + np2wab.paletteChanged = 1; + + // 描画再開 + np2wabwnd.ready = 1; +} +void np2wab_unbind(void) +{ + iocore_detachout(0xfac); + iocore_detachinp(0xfac); +} +// NP2終了時の処理 +void np2wab_shutdown() +{ +#if defined(NP2_WIN) + // マルチスレッドモードなら先にスレッド処理を終了させる + ga_exitThread = 1; + //while(((int)ResumeThread(ga_hThread))>0); + //if(WaitForSingleObject(ga_hThread, 1000)==WAIT_TIMEOUT){ + // ResumeThread(ga_hThread); + //} + SetEvent(wab_thread_eventhandle); + if(WaitForSingleObject(ga_hThread, 4000)==WAIT_TIMEOUT){ + TerminateThread(ga_hThread, 0); // 諦めて強制終了 + } + CloseHandle(ga_hThread); + ga_hThread = NULL; + + // いろいろ解放 + DeleteDC(np2wabwnd.hDCBuf); + DeleteObject(np2wabwnd.hBmpBuf); + ReleaseDC(np2wabwnd.hWndWAB, np2wabwnd.hDCWAB); + np2wabwnd.hDCWAB = NULL; + DestroyWindow(np2wabwnd.hWndWAB); + np2wabwnd.hWndWAB = NULL; +#elif defined(NP2_X) + g_object_unref(np2wabwnd.pPixbuf); +#else + free(np2wabwnd.pBuffer); +#endif + + // クリティカルセクション破棄 + wab_delete_criticalsection(); + + //// 専用INIセクション書き込み + //wabwin_writeini(); +} + +// 内蔵ディスプレイ切り替えリレー状態を設定する。stateのbit0は外部アクセラ(=1)/内蔵アクセラ(=0)切替、bit1は内蔵アクセラ(=1)/98グラフ(=0)切替。他は0。 +// 外部・内部の区別をしていないので事実上どちらかのビットが1ならアクセラレータ表示になる +void np2wab_setRelayState(REG8 state) +{ + // bit0,1が変化しているか確認 + if((np2wab.relay & 0x3) != (state & 0x3)){ + np2wab.relay = state & 0x3; + if(state&0x3){ + // リレーがON +#if defined(NP2_WIN) + if(!np2cfg.wabasw) soundmng_pcmplay(SOUND_RELAY1, FALSE); // カチッ +#else + if(!np2cfg.wabasw) wabrly_switch(); // カチッ +#endif + if(np2wabwnd.multiwindow){ + // 別窓モードなら別窓を出す +#if defined(NP2_WIN) + ShowWindow(np2wabwnd.hWndWAB, SW_SHOWNOACTIVATE); + SetWindowPos(np2wabwnd.hWndWAB, HWND_TOP, np2wabcfg.posx, np2wabcfg.posy, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOSENDCHANGING | SWP_SHOWWINDOW); +#endif + }else{ + // 統合モードなら画面を乗っ取る +#if defined(SUPPORT_MULTITHREAD) + if(np2_multithread_Enabled()){ + np2wab_setScreenSizeMT(ga_lastwabwidth, ga_lastwabheight); + }else +#endif + { + np2wab_setScreenSize(ga_lastwabwidth, ga_lastwabheight); + } + } + }else{ + // リレーがOFF +#if defined(NP2_WIN) + if(!np2cfg.wabasw) soundmng_pcmplay(SOUND_RELAY1, FALSE); // カチッ +#else + if(!np2cfg.wabasw) wabrly_switch(); // カチッ +#endif + if(np2wabwnd.multiwindow){ + // 別窓モードなら別窓を消す + np2wab.lastWidth = 0; + np2wab.lastHeight = 0; +#if defined(NP2_WIN) + ShowWindow(np2wabwnd.hWndWAB, SW_HIDE); +#endif + }else{ + // 統合モードなら画面を戻す + np2wab.lastWidth = 0; + np2wab.lastHeight = 0; +#if defined(NP2_WIN) + scrnmng_setsize(dsync.scrnxpos, 0, dsync.scrnxmax, dsync.scrnymax);// XXX: 画面サイズを乗っ取る前に戻す +#else + scrnmng_setwidth(dsync.scrnxpos, dsync.scrnxmax); // XXX: 画面幅を乗っ取る前に戻す + scrnmng_setheight(0, dsync.scrnymax); // XXX: 画面高さを乗っ取る前に戻す +#endif + scrnmng_updatefsres(); // フルスクリーン解像度更新 +#if defined(NP2_WIN) + mousemng_updateclip(); // マウスキャプチャのクリップ範囲を修正 +#endif + } + } + } +} + +/** + * ウィンドウアクセラレータ画面をBMPで取得 + */ +BRESULT np2wab_getbmp(BMPFILE *lpbf, BMPINFO *lpbi, UINT8 **lplppal, UINT8 **lplppixels) { + + BMPDATA bd; + BMPFILE bf; + UINT pos; + BMPINFO bi; + BMPINFO bitmp; + UINT align; + //int r; + //int x; + UINT8 *dstpix; +#if defined(NP2_WIN) + LPVOID lpbits; +#else + void* lpbits; +#endif + UINT8 *buf; +#if defined(NP2_WIN) + HBITMAP hBmpTmp; +#endif + + // 24bit固定 + bd.width = np2wab.wndWidth; + bd.height = np2wab.wndHeight; + bd.bpp = 24; + + // Bitmap File + ZeroMemory(&bf, sizeof(bf)); + bf.bfType[0] = 'B'; + bf.bfType[1] = 'M'; + pos = sizeof(BMPFILE) + sizeof(BMPINFO); + STOREINTELDWORD(bf.bfOffBits, pos); + + // Bitmap Info + bmpdata_setinfo(&bi, &bd); + STOREINTELDWORD(bi.biClrImportant, 0); + align = bmpdata_getalign(&bi); + CopyMemory(lpbi, &bi, sizeof(bi)); + *lplppal = (UINT8*)malloc(0); // freeで解放されても大丈夫なように(大抵NULLが入る) + + // Bitmap File (size) + STOREINTELDWORD(bf.bfSize, (sizeof(BMPFILE) + sizeof(BMPINFO) + 0 + bmpdata_getalign(&bi) * bd.height)); + CopyMemory(lpbf, &bf, sizeof(bf)); + + *lplppixels = (UINT8*)malloc(bmpdata_getalign(&bi) * bd.height); + dstpix = *lplppixels; + + // Copy Pixels + bitmp = bi; + STOREINTELDWORD(bitmp.biWidth, WAB_MAX_WIDTH); + STOREINTELDWORD(bitmp.biHeight, WAB_MAX_HEIGHT); +#if defined(NP2_WIN) + hBmpTmp = CreateDIBSection(NULL, (LPBITMAPINFO)&bitmp, DIB_RGB_COLORS, &lpbits, NULL, 0); + GetDIBits(np2wabwnd.hDCBuf, np2wabwnd.hBmpBuf, 0, WAB_MAX_HEIGHT, lpbits, (LPBITMAPINFO)&bitmp, DIB_RGB_COLORS); + buf = (UINT8*)(lpbits) + (WAB_MAX_HEIGHT - bd.height) * WAB_MAX_WIDTH*bd.bpp/8; +#elif defined(NP2_X) + buf = (UINT8*)(gdk_pixbuf_get_pixels(np2wabwnd.pPixbuf)) + (np2wab.wndHeight - 1) * WAB_MAX_WIDTH*bd.bpp/8; +#else + buf = (UINT8*)(np2wabwnd.pBuffer) + (np2wab.wndHeight - 1) * np2wab.wndWidth*4; +#endif + do { +#if defined(NP2_WIN) + CopyMemory(dstpix, buf, np2wab.wndWidth*bd.bpp/8); + dstpix += align; + buf += WAB_MAX_WIDTH*bd.bpp/8; +#elif defined(NP2_X) + CopyMemory(dstpix, buf, np2wab.wndWidth*bd.bpp/8); + dstpix += align; + buf -= WAB_MAX_WIDTH*bd.bpp/8; +#else + int i; + for(i = 0; i < np2wab.wndWidth; i++) { + ((UINT8*)dstpix)[i * 3 ] = ((UINT8*)buf)[i * 4 ]; + ((UINT8*)dstpix)[i * 3 + 1] = ((UINT8*)buf)[i * 4 + 1]; + ((UINT8*)dstpix)[i * 3 + 2] = ((UINT8*)buf)[i * 4 + 2]; + } + dstpix += np2wab.wndWidth*3; + buf -= np2wab.wndWidth*4; +#endif + } while(--bd.height); +#if defined(NP2_WIN) + DeleteObject(hBmpTmp); +#elif defined(NP2_X) + { + int i, j; + UINT8 tmp; + dstpix = *lplppixels; + for(j = 0; j < np2wab.wndHeight; j++) { + for(i = 0; i < np2wab.wndWidth; i++) { + tmp = dstpix[(j * np2wab.wndWidth + i) * 3]; + dstpix[(j * np2wab.wndWidth + i) * 3] = dstpix[(j * np2wab.wndWidth + i) * 3 + 2]; + dstpix[(j * np2wab.wndWidth + i) * 3 + 2] = tmp; + } + } + } +#endif + + return(SUCCESS); +} + +/** + * ウィンドウアクセラレータ画面をBMPで保存 + */ +BRESULT np2wab_writebmp(const OEMCHAR *filename) { + + FILEH fh; + BMPFILE bf; + BMPINFO bi; + UINT8 *lppal; + UINT8 *lppixels; + int pixelssize; + + fh = file_create(filename); + if (fh == FILEH_INVALID) { + goto sswb_err1; + } + + np2wab_getbmp(&bf, &bi, &lppal, &lppixels); + + // Bitmap File + if (file_write(fh, &bf, sizeof(bf)) != sizeof(bf)) { + goto sswb_err3; + } + + // Bitmap Info (パレット不要) + if (file_write(fh, &bi, sizeof(bi)) != sizeof(bi)) { + goto sswb_err3; + } + + // Pixels + pixelssize = bmpdata_getalign(&bi) * LOADINTELDWORD(bi.biHeight); + if (file_write(fh, lppixels, pixelssize) != pixelssize) { + goto sswb_err3; + } + + _MFREE(lppal); + _MFREE(lppixels); + + file_close(fh); + + return(SUCCESS); + +sswb_err3: + _MFREE(lppal); + _MFREE(lppixels); + +//sswb_err2: +// file_close(fh); +// file_delete(filename); + +sswb_err1: + return(FAILURE); +} + +#endif /* SUPPORT_WAB */ diff --git a/wab/wab.h b/wab/wab.h old mode 100755 new mode 100644 index 080d7ad0..174aea44 --- a/wab/wab.h +++ b/wab/wab.h @@ -1,97 +1,97 @@ -/** - * @file wab.h - * @brief Window Accelerator Board Interface - * - * @author $Author: SimK $ - */ - -#pragma once - -#if defined(NP2_X) -#include -#endif - -// XXX: 回転させても1600x1600以上にならないので差し当たってはこれで十分 -#define WAB_MAX_WIDTH 1600 -#define WAB_MAX_HEIGHT 1600 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - int posx; - int posy; - int multiwindow; - int multithread; - int halftone; - int forcevga; - int readonly; // from np2oscfg -} NP2WABCFG; - -typedef int NP2WAB_DrawFrame(); -typedef struct { - REG8 relay; // 画面出力リレー状態(bit0=内蔵ウィンドウアクセラレータ, bit1=RGB INスルー, それ以外のビットはReserved。bit0,1が00で98グラフィック - REG8 paletteChanged; // パレット要更新フラグ - int realWidth; // 画面解像度(幅) - int realHeight; // 画面解像度(高さ) - int wndWidth; // 描画領域サイズ(幅) - int wndHeight; // 描画領域サイズ(高さ) - int fps; // リフレッシュレート(大体合わせてくれるかもしれない・・・けど現時点で何もしていない) - int lastWidth; // 前回のウィンドウアクセラレータの横解像度(デバイス再作成判定用) - int lastHeight; // 前回のウィンドウアクセラレータの横解像度(デバイス再作成判定用) - - int relaystateint; - int relaystateext; - - int vramoffs; -} NP2WAB; - -typedef struct { - int multiwindow; // 別窓モード - int ready; // 0以外なら描いても良いよ -#if defined(NP2_WIN) - HWND hWndMain; // メインウィンドウのハンドル - HWND hWndWAB; // ウィンドウアクセラレータ別窓のハンドル - HDC hDCWAB; // ウィンドウアクセラレータ別窓のHDC - HBITMAP hBmpBuf; // バッファビットマップ(常に等倍) - HDC hDCBuf; // バッファのHDC -#elif defined(NP2_X) - GtkWidget *pWABWnd; - GdkPixbuf *pPixbuf; -#else - unsigned int* pBuffer; -#endif - NP2WAB_DrawFrame *drawframe; // 画面描画関数。hDCBufにアクセラレータ画面データを転送する。 -} NP2WABWND; - -#if defined(NP2_WIN) -void np2wab_init(HINSTANCE hInstance, HWND g_hWndMain); -#else -void np2wab_init(void); -#endif -void np2wab_reset(const NP2CFG *pConfig); -void np2wab_bind(void); -void np2wab_drawframe(void); -void np2wab_shutdown(void); - -void np2wab_setRelayState(REG8 state); -void np2wab_setScreenSize(int width, int height); -void np2wab_setScreenSizeMT(int width, int height); - -void wabwin_readini(void); -void wabwin_writeini(void); - -void np2wab_forceupdate(void); - -extern NP2WAB np2wab; -extern NP2WABCFG np2wabcfg; -extern NP2WABWND np2wabwnd; -// -//extern int np2wab.relaystateint; -//extern int np2wab.relaystateext; - -#ifdef __cplusplus -} -#endif - +/** + * @file wab.h + * @brief Window Accelerator Board Interface + * + * @author $Author: SimK $ + */ + +#pragma once + +#if defined(NP2_X) +#include +#endif + +// XXX: 回転させても1600x1600以上にならないので差し当たってはこれで十分 +#define WAB_MAX_WIDTH 1600 +#define WAB_MAX_HEIGHT 1600 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int posx; + int posy; + int multiwindow; + int multithread; + int halftone; + int forcevga; + int readonly; // from np2oscfg +} NP2WABCFG; + +typedef int NP2WAB_DrawFrame(); +typedef struct { + REG8 relay; // 画面出力リレー状態(bit0=内蔵ウィンドウアクセラレータ, bit1=RGB INスルー, それ以外のビットはReserved。bit0,1が00で98グラフィック + REG8 paletteChanged; // パレット要更新フラグ + int realWidth; // 画面解像度(幅) + int realHeight; // 画面解像度(高さ) + int wndWidth; // 描画領域サイズ(幅) + int wndHeight; // 描画領域サイズ(高さ) + int fps; // リフレッシュレート(大体合わせてくれるかもしれない・・・けど現時点で何もしていない) + int lastWidth; // 前回のウィンドウアクセラレータの横解像度(デバイス再作成判定用) + int lastHeight; // 前回のウィンドウアクセラレータの横解像度(デバイス再作成判定用) + + int relaystateint; + int relaystateext; + + int vramoffs; +} NP2WAB; + +typedef struct { + int multiwindow; // 別窓モード + int ready; // 0以外なら描いても良いよ +#if defined(NP2_WIN) + HWND hWndMain; // メインウィンドウのハンドル + HWND hWndWAB; // ウィンドウアクセラレータ別窓のハンドル + HDC hDCWAB; // ウィンドウアクセラレータ別窓のHDC + HBITMAP hBmpBuf; // バッファビットマップ(常に等倍) + HDC hDCBuf; // バッファのHDC +#elif defined(NP2_X) + GtkWidget *pWABWnd; + GdkPixbuf *pPixbuf; +#else + unsigned int* pBuffer; +#endif + NP2WAB_DrawFrame *drawframe; // 画面描画関数。hDCBufにアクセラレータ画面データを転送する。 +} NP2WABWND; + +#if defined(NP2_WIN) +void np2wab_init(HINSTANCE hInstance, HWND g_hWndMain); +#else +void np2wab_init(void); +#endif +void np2wab_reset(const NP2CFG *pConfig); +void np2wab_bind(void); +void np2wab_drawframe(void); +void np2wab_shutdown(void); + +void np2wab_setRelayState(REG8 state); +void np2wab_setScreenSize(int width, int height); +void np2wab_setScreenSizeMT(int width, int height); + +void wabwin_readini(void); +void wabwin_writeini(void); + +void np2wab_forceupdate(void); + +extern NP2WAB np2wab; +extern NP2WABCFG np2wabcfg; +extern NP2WABWND np2wabwnd; +// +//extern int np2wab.relaystateint; +//extern int np2wab.relaystateext; + +#ifdef __cplusplus +} +#endif + diff --git a/wab/wab_rly.h b/wab/wab_rly.h old mode 100755 new mode 100644 index 71f1edfd..72b2c296 --- a/wab/wab_rly.h +++ b/wab/wab_rly.h @@ -1,30 +1,30 @@ - -typedef struct { - UINT8 head[4]; - UINT nextevent; - UINT8 curevent; -} _WABRLY, *WABRLY; - - -#ifdef __cplusplus -extern "C" { -#endif - -void wabrly_initialize(void); -void wabrly_switch(void); - - -#if defined(SUPPORT_SWWABRLYSND) -void wabrlysnd_initialize(UINT rate); -void wabrlysnd_bind(void); -void wabrlysnd_deinitialize(void); -#else -#define wabrlysnd_initialize(r) -#define wabrlysnd_bind() -#define wabrlysnd_deinitialize() -#endif - -#ifdef __cplusplus -} -#endif - + +typedef struct { + UINT8 head[4]; + UINT nextevent; + UINT8 curevent; +} _WABRLY, *WABRLY; + + +#ifdef __cplusplus +extern "C" { +#endif + +void wabrly_initialize(void); +void wabrly_switch(void); + + +#if defined(SUPPORT_SWWABRLYSND) +void wabrlysnd_initialize(UINT rate); +void wabrlysnd_bind(void); +void wabrlysnd_deinitialize(void); +#else +#define wabrlysnd_initialize(r) +#define wabrlysnd_bind() +#define wabrlysnd_deinitialize() +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/wab/wabbmpsave.h b/wab/wabbmpsave.h old mode 100755 new mode 100644 index 41ac45b0..45ae4bda --- a/wab/wabbmpsave.h +++ b/wab/wabbmpsave.h @@ -1,22 +1,22 @@ -/** - * @file wabbmpsave.h - * @brief Window Accelerator Board BMP Save - * - * @author $Author: SimK $ - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -BRESULT np2wab_getbmp(BMPFILE *lpbf, BMPINFO *lpbi, UINT8 **lplppal, UINT8 **lplppixels); -BRESULT np2wab_writebmp(const OEMCHAR *filename); - -#ifdef __cplusplus -} -#endif - +/** + * @file wabbmpsave.h + * @brief Window Accelerator Board BMP Save + * + * @author $Author: SimK $ + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +BRESULT np2wab_getbmp(BMPFILE *lpbf, BMPINFO *lpbi, UINT8 **lplppal, UINT8 **lplppixels); +BRESULT np2wab_writebmp(const OEMCHAR *filename); + +#ifdef __cplusplus +} +#endif + diff --git a/windows/commng.cpp b/windows/commng.cpp index c1cd5007..4e7781a1 100644 --- a/windows/commng.cpp +++ b/windows/commng.cpp @@ -1,139 +1,139 @@ -/** - * @file commng.cpp - * @brief COM }l[W̓̒`s܂ - */ - -#include -#include -#include -#include "commng/cmmidi.h" -#include "commng/cmnull.h" -#include "commng/cmpara.h" -#include "commng/cmserial.h" -#if defined(SUPPORT_WACOM_TABLET) -#include "commng/cmwacom.h" -#endif -#if defined(SUPPORT_NAMED_PIPE) -#include "commng/cmpipe.h" -#endif -#include - -/** - * - */ -void commng_initialize(void) -{ - cmmidi_initailize(); -#if defined(SUPPORT_WACOM_TABLET) - cmwacom_initialize(); - cmwacom_setNCControl(!!np2oscfg.mouse_nc); -#endif -} -void commng_finalize(void) -{ -#if defined(SUPPORT_WACOM_TABLET) - cmwacom_finalize(); -#endif -} - -/** - * 쐬 - * @param[in] nDevice foCX - * @param[in] onReset ZbgǂiAPIPÊ݃ZbgɃI[vj - * @return nh - */ -COMMNG commng_create(UINT nDevice, BOOL onReset) -{ - COMMNG ret = NULL; - - COMCFG* pComCfg = NULL; - switch (nDevice) - { - case COMCREATE_SERIAL: - pComCfg = &np2oscfg.com1; - break; - - case COMCREATE_PC9861K1: - pComCfg = &np2oscfg.com2; - break; - - case COMCREATE_PC9861K2: - pComCfg = &np2oscfg.com3; - break; - - case COMCREATE_PRINTER: - if (np2oscfg.jastsnd) - { - ret = cmjasts_create(); - } - break; - - case COMCREATE_MPU98II: - pComCfg = &np2oscfg.mpu; - break; - -#if defined(SUPPORT_SMPU98) - case COMCREATE_SMPU98_A: - pComCfg = &np2oscfg.smpuA; - break; - - case COMCREATE_SMPU98_B: - pComCfg = &np2oscfg.smpuB; - break; -#endif - - default: - break; - } - - if (pComCfg) - { - if ((pComCfg->port >= COMPORT_COM1) && (pComCfg->port <= COMPORT_COM4)) - { - if(onReset) return NULL; - ret = CComSerial::CreateInstance(pComCfg->port - COMPORT_COM1 + 1, pComCfg->param, pComCfg->speed, pComCfg->fixedspeed, pComCfg->DSRcheck); - } - else if (pComCfg->port == COMPORT_MIDI) - { - if(onReset) return NULL; - ret = CComMidi::CreateInstance(pComCfg->mout, pComCfg->min, pComCfg->mdl); - if (ret) - { - ret->msg(ret, COMMSG_MIMPIDEFFILE, (INTPTR)pComCfg->def); - ret->msg(ret, COMMSG_MIMPIDEFEN, (INTPTR)pComCfg->def_en); - } - } -#if defined(SUPPORT_WACOM_TABLET) - else if (pComCfg->port == COMPORT_TABLET) - { - if(onReset) return NULL; - ret = CComWacom::CreateInstance(g_hWndMain); - } -#endif -#if defined(SUPPORT_NAMED_PIPE) - else if (pComCfg->port == COMPORT_PIPE) - { - ret = CComPipe::CreateInstance(pComCfg->pipename, pComCfg->pipeserv); - } -#endif - } - - if (ret == NULL) - { - if(onReset) return NULL; - ret = new CComNull; - } - return ret; -} - -/** - * j - * @param[in] hdl nh - */ -void commng_destroy(COMMNG hdl) -{ - if (hdl) - { - hdl->release(hdl); - } -} +/** + * @file commng.cpp + * @brief COM マネージャの動作の定義を行います + */ + +#include +#include +#include +#include "commng/cmmidi.h" +#include "commng/cmnull.h" +#include "commng/cmpara.h" +#include "commng/cmserial.h" +#if defined(SUPPORT_WACOM_TABLET) +#include "commng/cmwacom.h" +#endif +#if defined(SUPPORT_NAMED_PIPE) +#include "commng/cmpipe.h" +#endif +#include + +/** + * 初期化 + */ +void commng_initialize(void) +{ + cmmidi_initailize(); +#if defined(SUPPORT_WACOM_TABLET) + cmwacom_initialize(); + cmwacom_setNCControl(!!np2oscfg.mouse_nc); +#endif +} +void commng_finalize(void) +{ +#if defined(SUPPORT_WACOM_TABLET) + cmwacom_finalize(); +#endif +} + +/** + * 作成 + * @param[in] nDevice デバイス + * @param[in] onReset リセット時かどうか(現状、PIPEのみリセット時にオープンする) + * @return ハンドル + */ +COMMNG commng_create(UINT nDevice, BOOL onReset) +{ + COMMNG ret = NULL; + + COMCFG* pComCfg = NULL; + switch (nDevice) + { + case COMCREATE_SERIAL: + pComCfg = &np2oscfg.com1; + break; + + case COMCREATE_PC9861K1: + pComCfg = &np2oscfg.com2; + break; + + case COMCREATE_PC9861K2: + pComCfg = &np2oscfg.com3; + break; + + case COMCREATE_PRINTER: + if (np2oscfg.jastsnd) + { + ret = cmjasts_create(); + } + break; + + case COMCREATE_MPU98II: + pComCfg = &np2oscfg.mpu; + break; + +#if defined(SUPPORT_SMPU98) + case COMCREATE_SMPU98_A: + pComCfg = &np2oscfg.smpuA; + break; + + case COMCREATE_SMPU98_B: + pComCfg = &np2oscfg.smpuB; + break; +#endif + + default: + break; + } + + if (pComCfg) + { + if ((pComCfg->port >= COMPORT_COM1) && (pComCfg->port <= COMPORT_COM4)) + { + if(onReset) return NULL; + ret = CComSerial::CreateInstance(pComCfg->port - COMPORT_COM1 + 1, pComCfg->param, pComCfg->speed, pComCfg->fixedspeed, pComCfg->DSRcheck); + } + else if (pComCfg->port == COMPORT_MIDI) + { + if(onReset) return NULL; + ret = CComMidi::CreateInstance(pComCfg->mout, pComCfg->min, pComCfg->mdl); + if (ret) + { + ret->msg(ret, COMMSG_MIMPIDEFFILE, (INTPTR)pComCfg->def); + ret->msg(ret, COMMSG_MIMPIDEFEN, (INTPTR)pComCfg->def_en); + } + } +#if defined(SUPPORT_WACOM_TABLET) + else if (pComCfg->port == COMPORT_TABLET) + { + if(onReset) return NULL; + ret = CComWacom::CreateInstance(g_hWndMain); + } +#endif +#if defined(SUPPORT_NAMED_PIPE) + else if (pComCfg->port == COMPORT_PIPE) + { + ret = CComPipe::CreateInstance(pComCfg->pipename, pComCfg->pipeserv); + } +#endif + } + + if (ret == NULL) + { + if(onReset) return NULL; + ret = new CComNull; + } + return ret; +} + +/** + * 破棄 + * @param[in] hdl ハンドル + */ +void commng_destroy(COMMNG hdl) +{ + if (hdl) + { + hdl->release(hdl); + } +} diff --git a/windows/commng.h b/windows/commng.h old mode 100755 new mode 100644 index 585d01c1..7e9be009 --- a/windows/commng.h +++ b/windows/commng.h @@ -1,133 +1,133 @@ -/** - * @file commng.h - * @brief COM }l[W̐錾уC^[tFCX̒`܂ - */ - -#pragma once - -// ---- com manager interface - -enum { - COMCREATE_SERIAL = 0, - COMCREATE_PC9861K1, - COMCREATE_PC9861K2, - COMCREATE_PRINTER, - COMCREATE_MPU98II, -#if defined(SUPPORT_SMPU98) - COMCREATE_SMPU98_A, - COMCREATE_SMPU98_B, -#endif -#if defined(SUPPORT_WACOM_TABLET) - COMCREATE_TABLET, -#endif -#if defined(SUPPORT_NAMED_PIPE) - COMCREATE_PIPE, -#endif - COMCREATE_NULL = 0xffff, -}; - -enum { - COMCONNECT_OFF = 0, - COMCONNECT_SERIAL, - COMCONNECT_MIDI, - COMCONNECT_PARALLEL, -#if defined(SUPPORT_WACOM_TABLET) - COMCONNECT_TABLET, -#endif -#if defined(SUPPORT_NAMED_PIPE) - COMCONNECT_PIPE, -#endif - -}; - -enum { - COMMSG_MIDIRESET = 0, - COMMSG_SETFLAG, - COMMSG_GETFLAG, -#if defined(VAEG_FIX) - COMMSG_SETRSFLAG, -#endif - COMMSG_CHANGESPEED, - COMMSG_CHANGEMODE, - COMMSG_SETCOMMAND, - COMMSG_PURGE, - COMMSG_GETERROR, - COMMSG_CLRERROR, - COMMSG_USER = 0x80, -}; - -struct _commng; -typedef struct _commng _COMMNG; /*!< defines the instance of COMMNG */ -typedef struct _commng *COMMNG; /*!< defines the instance of COMMNG */ - -/** - * @brief COMMNG - */ -struct _commng -{ - UINT connect; /*!< flags */ - UINT (*read)(COMMNG self, UINT8 *data); /*!< read */ - UINT (*write)(COMMNG self, UINT8 data); /*!< write */ - UINT (*writeretry)(COMMNG self); /*!< write retry */ - void (*beginblocktranster)(COMMNG self); /*!< begin block transfer */ - void (*endblocktranster)(COMMNG self); /*!< end block transfer */ - UINT (*lastwritesuccess)(COMMNG self); /*!< last write success */ - UINT8 (*getstat)(COMMNG self); /*!< get status */ - INTPTR (*msg)(COMMNG self, UINT msg, INTPTR param); /*!< message */ - void (*release)(COMMNG self); /*!< release */ -}; - -typedef struct { - UINT32 size; - UINT32 sig; - UINT32 ver; - UINT32 param; -} _COMFLAG, *COMFLAG; - - -#ifdef __cplusplus -extern "C" -{ -#endif - -COMMNG commng_create(UINT device, BOOL onReset); -void commng_destroy(COMMNG hdl); - -#ifdef __cplusplus -} -#endif - - -// ---- com manager for windows - -enum { - COMPORT_NONE = 0, - COMPORT_COM1, - COMPORT_COM2, - COMPORT_COM3, - COMPORT_COM4, - COMPORT_MIDI, -#if defined(SUPPORT_WACOM_TABLET) - COMPORT_TABLET, -#endif -#if defined(SUPPORT_NAMED_PIPE) - COMPORT_PIPE, -#endif -}; - -enum { - COMSIG_COM1 = 0x314d4f43, - COMSIG_COM2 = 0x324d4f43, - COMSIG_COM3 = 0x334d4f43, - COMSIG_COM4 = 0x344d4f43, - COMSIG_MIDI = 0x4944494d, - COMSIG_TABLET = 0x5944494d // XXX: Ȃ -}; - -enum { - COMMSG_MIMPIDEFFILE = COMMSG_USER, - COMMSG_MIMPIDEFEN -}; - -void commng_initialize(void); -void commng_finalize(void); +/** + * @file commng.h + * @brief COM マネージャの宣言およびインターフェイスの定義をします + */ + +#pragma once + +// ---- com manager interface + +enum { + COMCREATE_SERIAL = 0, + COMCREATE_PC9861K1, + COMCREATE_PC9861K2, + COMCREATE_PRINTER, + COMCREATE_MPU98II, +#if defined(SUPPORT_SMPU98) + COMCREATE_SMPU98_A, + COMCREATE_SMPU98_B, +#endif +#if defined(SUPPORT_WACOM_TABLET) + COMCREATE_TABLET, +#endif +#if defined(SUPPORT_NAMED_PIPE) + COMCREATE_PIPE, +#endif + COMCREATE_NULL = 0xffff, +}; + +enum { + COMCONNECT_OFF = 0, + COMCONNECT_SERIAL, + COMCONNECT_MIDI, + COMCONNECT_PARALLEL, +#if defined(SUPPORT_WACOM_TABLET) + COMCONNECT_TABLET, +#endif +#if defined(SUPPORT_NAMED_PIPE) + COMCONNECT_PIPE, +#endif + +}; + +enum { + COMMSG_MIDIRESET = 0, + COMMSG_SETFLAG, + COMMSG_GETFLAG, +#if defined(VAEG_FIX) + COMMSG_SETRSFLAG, +#endif + COMMSG_CHANGESPEED, + COMMSG_CHANGEMODE, + COMMSG_SETCOMMAND, + COMMSG_PURGE, + COMMSG_GETERROR, + COMMSG_CLRERROR, + COMMSG_USER = 0x80, +}; + +struct _commng; +typedef struct _commng _COMMNG; /*!< defines the instance of COMMNG */ +typedef struct _commng *COMMNG; /*!< defines the instance of COMMNG */ + +/** + * @brief COMMNG + */ +struct _commng +{ + UINT connect; /*!< flags */ + UINT (*read)(COMMNG self, UINT8 *data); /*!< read */ + UINT (*write)(COMMNG self, UINT8 data); /*!< write */ + UINT (*writeretry)(COMMNG self); /*!< write retry */ + void (*beginblocktranster)(COMMNG self); /*!< begin block transfer */ + void (*endblocktranster)(COMMNG self); /*!< end block transfer */ + UINT (*lastwritesuccess)(COMMNG self); /*!< last write success */ + UINT8 (*getstat)(COMMNG self); /*!< get status */ + INTPTR (*msg)(COMMNG self, UINT msg, INTPTR param); /*!< message */ + void (*release)(COMMNG self); /*!< release */ +}; + +typedef struct { + UINT32 size; + UINT32 sig; + UINT32 ver; + UINT32 param; +} _COMFLAG, *COMFLAG; + + +#ifdef __cplusplus +extern "C" +{ +#endif + +COMMNG commng_create(UINT device, BOOL onReset); +void commng_destroy(COMMNG hdl); + +#ifdef __cplusplus +} +#endif + + +// ---- com manager for windows + +enum { + COMPORT_NONE = 0, + COMPORT_COM1, + COMPORT_COM2, + COMPORT_COM3, + COMPORT_COM4, + COMPORT_MIDI, +#if defined(SUPPORT_WACOM_TABLET) + COMPORT_TABLET, +#endif +#if defined(SUPPORT_NAMED_PIPE) + COMPORT_PIPE, +#endif +}; + +enum { + COMSIG_COM1 = 0x314d4f43, + COMSIG_COM2 = 0x324d4f43, + COMSIG_COM3 = 0x334d4f43, + COMSIG_COM4 = 0x344d4f43, + COMSIG_MIDI = 0x4944494d, + COMSIG_TABLET = 0x5944494d // XXX: なぞ +}; + +enum { + COMMSG_MIMPIDEFFILE = COMMSG_USER, + COMMSG_MIMPIDEFEN +}; + +void commng_initialize(void); +void commng_finalize(void); diff --git a/windows/commng/cmbase.cpp b/windows/commng/cmbase.cpp index 1e6d658d..8fbcfeac 100644 --- a/windows/commng/cmbase.cpp +++ b/windows/commng/cmbase.cpp @@ -1,123 +1,123 @@ -/** - * @file cmbase.h - * @brief commng NX̓̒`s܂ - */ - -#include -#include "cmbase.h" - -/** - * RXgN^ - * @param[in] nConnect ڑtO - */ -CComBase::CComBase(UINT nConnect) -{ - this->connect = nConnect; - this->read = cRead; - this->write = cWrite; - this->writeretry = cWriteRetry; - this->beginblocktranster = cBeginBlockTransfer; - this->endblocktranster = cEndBlockTransfer; - this->lastwritesuccess = cLastWriteSuccess; - this->getstat = cGetStat; - this->msg = cMessage; - this->release = cRelease; -} - -/** - * fXgN^ - */ -CComBase::~CComBase() -{ -} - -/** - * Read - * @param[in] cm COMMNG CX^X - * @param[out] pData - * @return result - */ -UINT CComBase::cRead(COMMNG cm, UINT8* pData) -{ - return static_cast(cm)->Read(pData); -} - -/** - * Write - * @param[in] cm COMMNG CX^X - * @param[in] cData - * @return result - */ -UINT CComBase::cWrite(COMMNG cm, UINT8 cData) -{ - return static_cast(cm)->Write(cData); -} - -/** - * Write Retry - * @param[in] cm COMMNG CX^X - * @return result - */ -UINT CComBase::cWriteRetry(COMMNG cm) -{ - return static_cast(cm)->WriteRetry(); -} - -/** - * Begin Block Transfer - * @param[in] cm COMMNG CX^X - * @return result - */ -void CComBase::cBeginBlockTransfer(COMMNG cm) -{ - return static_cast(cm)->BeginBlockTransfer(); -} -/** - * End Block Transfer - * @param[in] cm COMMNG CX^X - * @return result - */ -void CComBase::cEndBlockTransfer(COMMNG cm) -{ - return static_cast(cm)->EndBlockTransfer(); -} -/** - * Last Write Success - * @param[in] cm COMMNG CX^X - * @return result - */ -UINT CComBase::cLastWriteSuccess(COMMNG cm) -{ - return static_cast(cm)->LastWriteSuccess(); -} - -/** - * Xe[^X𓾂 - * @param[in] cm COMMNG CX^X - * @return Xe[^X - */ -UINT8 CComBase::cGetStat(COMMNG cm) -{ - return static_cast(cm)->GetStat(); -} - -/** - * bZ[W - * @param[in] cm COMMNG CX^X - * @param[in] nMessage bZ[W - * @param[in] nParam p^ - * @return Ug R[h - */ -INTPTR CComBase::cMessage(COMMNG cm, UINT nMessage, INTPTR nParam) -{ - return static_cast(cm)->Message(nMessage, nParam); -} - -/** - * [X - * @param[in] cm COMMNG CX^X - */ -void CComBase::cRelease(COMMNG cm) -{ - delete static_cast(cm); -} +/** + * @file cmbase.h + * @brief commng 基底クラスの動作の定義を行います + */ + +#include +#include "cmbase.h" + +/** + * コンストラクタ + * @param[in] nConnect 接続フラグ + */ +CComBase::CComBase(UINT nConnect) +{ + this->connect = nConnect; + this->read = cRead; + this->write = cWrite; + this->writeretry = cWriteRetry; + this->beginblocktranster = cBeginBlockTransfer; + this->endblocktranster = cEndBlockTransfer; + this->lastwritesuccess = cLastWriteSuccess; + this->getstat = cGetStat; + this->msg = cMessage; + this->release = cRelease; +} + +/** + * デストラクタ + */ +CComBase::~CComBase() +{ +} + +/** + * Read + * @param[in] cm COMMNG インスタンス + * @param[out] pData + * @return result + */ +UINT CComBase::cRead(COMMNG cm, UINT8* pData) +{ + return static_cast(cm)->Read(pData); +} + +/** + * Write + * @param[in] cm COMMNG インスタンス + * @param[in] cData + * @return result + */ +UINT CComBase::cWrite(COMMNG cm, UINT8 cData) +{ + return static_cast(cm)->Write(cData); +} + +/** + * Write Retry + * @param[in] cm COMMNG インスタンス + * @return result + */ +UINT CComBase::cWriteRetry(COMMNG cm) +{ + return static_cast(cm)->WriteRetry(); +} + +/** + * Begin Block Transfer + * @param[in] cm COMMNG インスタンス + * @return result + */ +void CComBase::cBeginBlockTransfer(COMMNG cm) +{ + return static_cast(cm)->BeginBlockTransfer(); +} +/** + * End Block Transfer + * @param[in] cm COMMNG インスタンス + * @return result + */ +void CComBase::cEndBlockTransfer(COMMNG cm) +{ + return static_cast(cm)->EndBlockTransfer(); +} +/** + * Last Write Success + * @param[in] cm COMMNG インスタンス + * @return result + */ +UINT CComBase::cLastWriteSuccess(COMMNG cm) +{ + return static_cast(cm)->LastWriteSuccess(); +} + +/** + * ステータスを得る + * @param[in] cm COMMNG インスタンス + * @return ステータス + */ +UINT8 CComBase::cGetStat(COMMNG cm) +{ + return static_cast(cm)->GetStat(); +} + +/** + * メッセージ + * @param[in] cm COMMNG インスタンス + * @param[in] nMessage メッセージ + * @param[in] nParam パラメタ + * @return リザルト コード + */ +INTPTR CComBase::cMessage(COMMNG cm, UINT nMessage, INTPTR nParam) +{ + return static_cast(cm)->Message(nMessage, nParam); +} + +/** + * リリース + * @param[in] cm COMMNG インスタンス + */ +void CComBase::cRelease(COMMNG cm) +{ + delete static_cast(cm); +} diff --git a/windows/commng/cmbase.h b/windows/commng/cmbase.h index 48d7c7bb..17279a39 100644 --- a/windows/commng/cmbase.h +++ b/windows/commng/cmbase.h @@ -1,84 +1,84 @@ -/** - * @file cmbase.h - * @brief commng NX̐錾уC^[tFCX̒`܂ - */ - -#pragma once - -#include - -/** - * @brief commng NX - */ -class CComBase : public _commng -{ -protected: - CComBase(UINT nConnect); - virtual ~CComBase(); - - /** - * Read - * @param[out] pData - * @return result - */ - virtual UINT Read(UINT8* pData) = 0; - - /** - * Write - * @param[in] cData - * @return result - */ - virtual UINT Write(UINT8 cData) = 0; - - /** - * Write Retry - * @return result - */ - virtual UINT WriteRetry(){ - return 1; // 펞 - } - - /** - * ubNPʓ]Jn - */ - virtual void BeginBlockTransfer(){ - } - /** - * ubNPʓ]I - */ - virtual void EndBlockTransfer(){ - } - - /** - * Last Write Success - * @return result - */ - virtual UINT LastWriteSuccess(){ - return 1; // 펞 - } - - /** - * Xe[^X𓾂 - * @return Xe[^X - */ - virtual UINT8 GetStat() = 0; - - /** - * bZ[W - * @param[in] nMessage bZ[W - * @param[in] nParam p^ - * @return Ug R[h - */ - virtual INTPTR Message(UINT nMessage, INTPTR nParam) = 0; - -private: - static UINT cRead(COMMNG cm, UINT8* pData); - static UINT cWrite(COMMNG cm, UINT8 cData); - static UINT cWriteRetry(COMMNG cm); - static void cBeginBlockTransfer(COMMNG cm); - static void cEndBlockTransfer(COMMNG cm); - static UINT cLastWriteSuccess(COMMNG cm); - static UINT8 cGetStat(COMMNG cm); - static INTPTR cMessage(COMMNG cm, UINT nMessage, INTPTR nParam); - static void cRelease(COMMNG cm); -}; +/** + * @file cmbase.h + * @brief commng 基底クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include + +/** + * @brief commng 基底クラス + */ +class CComBase : public _commng +{ +protected: + CComBase(UINT nConnect); + virtual ~CComBase(); + + /** + * Read + * @param[out] pData + * @return result + */ + virtual UINT Read(UINT8* pData) = 0; + + /** + * Write + * @param[in] cData + * @return result + */ + virtual UINT Write(UINT8 cData) = 0; + + /** + * Write Retry + * @return result + */ + virtual UINT WriteRetry(){ + return 1; // 常時成功扱い + } + + /** + * ブロック単位転送開始 + */ + virtual void BeginBlockTransfer(){ + } + /** + * ブロック単位転送終了 + */ + virtual void EndBlockTransfer(){ + } + + /** + * Last Write Success + * @return result + */ + virtual UINT LastWriteSuccess(){ + return 1; // 常時成功扱い + } + + /** + * ステータスを得る + * @return ステータス + */ + virtual UINT8 GetStat() = 0; + + /** + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParam パラメタ + * @return リザルト コード + */ + virtual INTPTR Message(UINT nMessage, INTPTR nParam) = 0; + +private: + static UINT cRead(COMMNG cm, UINT8* pData); + static UINT cWrite(COMMNG cm, UINT8 cData); + static UINT cWriteRetry(COMMNG cm); + static void cBeginBlockTransfer(COMMNG cm); + static void cEndBlockTransfer(COMMNG cm); + static UINT cLastWriteSuccess(COMMNG cm); + static UINT8 cGetStat(COMMNG cm); + static INTPTR cMessage(COMMNG cm, UINT nMessage, INTPTR nParam); + static void cRelease(COMMNG cm); +}; diff --git a/windows/commng/cmmidi.cpp b/windows/commng/cmmidi.cpp index eec63324..c1a83b15 100644 --- a/windows/commng/cmmidi.cpp +++ b/windows/commng/cmmidi.cpp @@ -1,6 +1,6 @@ /** * @file cmmidi.cpp - * @brief MIDI NX̓̒`s܂ + * @brief MIDI クラスの動作の定義を行います */ #include @@ -102,9 +102,9 @@ static unsigned int __stdcall ccommidi_activesenseThreadFroc(LPVOID vdParam) } /** - * W[ԍ𓾂 - * @param[in] lpModule W[ - * @return W[ԍ + * モジュール番号を得る + * @param[in] lpModule モジュール名 + * @return モジュール番号 */ UINT CComMidi::module2number(LPCTSTR lpModule) { @@ -121,7 +121,7 @@ UINT CComMidi::module2number(LPCTSTR lpModule) } /** - * I[ m[g It + * オール ノート オフ */ void CComMidi::midiallnoteoff() { @@ -140,7 +140,7 @@ void CComMidi::midiallnoteoff() } /** - * MIDI Zbg + * MIDI リセット */ void CComMidi::midireset() { @@ -190,7 +190,7 @@ void CComMidi::midireset() } /** - * p[^ݒ + * パラメータ設定 */ void CComMidi::midisetparam() { @@ -225,7 +225,7 @@ void CComMidi::midisetparam() } /** - * + * 初期化 */ void cmmidi_initailize(void) { @@ -238,11 +238,11 @@ void cmmidi_initailize(void) } /** - * CX^X쐬 - * @param[in] lpMidiOut MIDIOUT foCX - * @param[in] lpMidiIn MIDIIN foCX - * @param[in] lpModule W[ - * @return CX^X + * インスタンス作成 + * @param[in] lpMidiOut MIDIOUT デバイス + * @param[in] lpMidiIn MIDIIN デバイス + * @param[in] lpModule モジュール + * @return インスタンス */ CComMidi* CComMidi::CreateInstance(LPCTSTR lpMidiOut, LPCTSTR lpMidiIn, LPCTSTR lpModule) { @@ -256,7 +256,7 @@ CComMidi* CComMidi::CreateInstance(LPCTSTR lpMidiOut, LPCTSTR lpMidiIn, LPCTSTR } /** - * RXgN^ + * コンストラクタ */ CComMidi::CComMidi() : CComBase(COMCONNECT_MIDI) @@ -280,7 +280,7 @@ CComMidi::CComMidi() } /** - * fXgN^ + * デストラクタ */ CComMidi::~CComMidi() { @@ -290,7 +290,7 @@ CComMidi::~CComMidi() SetEvent(m_activesenseExitRequestEvent); if (WaitForSingleObject(m_activesenseExitEvent, 10000) == WAIT_TIMEOUT) { - TerminateThread(m_activesenseThread, 0); // ]rXbhׂ + TerminateThread(m_activesenseThread, 0); // ゾンビスレッド死すべし } CloseHandle(m_activesenseThread); CloseHandle(m_activesenseExitRequestEvent); @@ -312,12 +312,12 @@ CComMidi::~CComMidi() } /** - * - * @param[in] lpMidiOut MIDIOUT foCX - * @param[in] lpMidiIn MIDIIN foCX - * @param[in] lpModule W[ - * @retval true - * @retval false s + * 初期化 + * @param[in] lpMidiOut MIDIOUT デバイス + * @param[in] lpMidiIn MIDIIN デバイス + * @param[in] lpModule モジュール + * @retval true 成功 + * @retval false 失敗 */ bool CComMidi::Initialize(LPCTSTR lpMidiOut, LPCTSTR lpMidiIn, LPCTSTR lpModule) { @@ -343,8 +343,8 @@ bool CComMidi::Initialize(LPCTSTR lpMidiOut, LPCTSTR lpMidiIn, LPCTSTR lpModule) { m_pMidiOut = CComMidiOut32::CreateInstance(lpMidiOut); - // MIDI Active Sensing𑗂 - // WORKAROUND: ꕔ̃\tgMIDIVZʼn炩̃bZ[W𑗂ȂCPUُɎg̑΍Ɏgp + // MIDI Active Sensingを送る + // WORKAROUND: 一部のソフトMIDIシンセで何らかのメッセージを送らないとCPUを異常に使う問題の対策に使用 m_useactivesense = np2oscfg.midiasns; m_activesenseInterval = np2oscfg.midiaint; if (m_useactivesense && m_activesenseInterval > 0) @@ -378,9 +378,9 @@ bool CComMidi::Initialize(LPCTSTR lpMidiOut, LPCTSTR lpMidiIn, LPCTSTR lpModule) } /** - * ǂݍ - * @param[out] pData obt@ - * @return TCY + * 読み込み + * @param[out] pData バッファ + * @return サイズ */ UINT CComMidi::Read(UINT8* pData) { @@ -392,9 +392,9 @@ UINT CComMidi::Read(UINT8* pData) } /** - * - * @param[out] cData f[^ - * @return TCY + * 書き込み + * @param[out] cData データ + * @return サイズ */ UINT CComMidi::Write(UINT8 cData) { @@ -466,7 +466,7 @@ UINT CComMidi::Write(UINT8 cData) break; } } - else // Key-on݂̂ȋC񂾂ǖYꂽc + else // Key-onのみな気がしたんだけど忘れた… { // running status m_sBuffer[0] = m_cLastData; @@ -544,7 +544,7 @@ UINT CComMidi::Write(UINT8 cData) val = (UINT32)m_sBuffer[2] * np2cfg.vol_midi / 128; } if(val > 127) val = 127; - m_sBuffer[2] = (UINT8)val; //  + m_sBuffer[2] = (UINT8)val; // 無理矢理 } break; @@ -590,7 +590,7 @@ UINT CComMidi::Write(UINT8 cData) m_nMidiCtrl = MIDICTRL_READY; return m_nIndex; } - else if (m_nIndex >= sizeof(m_sBuffer)) // [΁[ӂ[ + else if (m_nIndex >= sizeof(m_sBuffer)) // おーばーふろー { m_nMidiCtrl = MIDICTRL_READY; } @@ -601,7 +601,7 @@ UINT CComMidi::Write(UINT8 cData) { if ((cData == 0x7e) || (cData == 0x7f)) { - // exclusiveƓłc + // exclusiveと同じでいい筈… m_nMidiCtrl = MIDICTRL_EXCLUSIVE; } else @@ -624,7 +624,7 @@ UINT CComMidi::Write(UINT8 cData) } /** - * Xe[^X𓾂 + * ステータスを得る * bit 7: ~CI (RI, RING) * bit 6: ~CS (CTS) * bit 5: ~CD (DCD, RLSD) @@ -633,7 +633,7 @@ UINT CComMidi::Write(UINT8 cData) * bit 2: reserved * bit 1: reserved * bit 0: ~DSR (DR) - * @return Xe[^X + * @return ステータス */ UINT8 CComMidi::GetStat() { @@ -641,10 +641,10 @@ UINT8 CComMidi::GetStat() } /** - * bZ[W - * @param[in] nMessage bZ[W - * @param[in] nParam p^ - * @return Ug R[h + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParam パラメタ + * @return リザルト コード */ INTPTR CComMidi::Message(UINT nMessage, INTPTR nParam) { @@ -696,7 +696,7 @@ INTPTR CComMidi::Message(UINT nMessage, INTPTR nParam) } /** - * Active Sensing𑗂 + * Active Sensingを送る */ void CComMidi::SendActive() { diff --git a/windows/commng/cmmidi.h b/windows/commng/cmmidi.h index 239b83a3..edbb9ef9 100644 --- a/windows/commng/cmmidi.h +++ b/windows/commng/cmmidi.h @@ -1,6 +1,6 @@ /** * @file cmmidi.h - * @brief MIDI NX̐錾уC^[tFCX̒`܂ + * @brief MIDI クラスの宣言およびインターフェイスの定義をします */ #pragma once @@ -24,7 +24,7 @@ class CComMidiIn32; class CComMidiOut; /** - * @brief commng MIDI foCX NX + * @brief commng MIDI デバイス クラス */ class CComMidi : public CComBase { @@ -32,10 +32,10 @@ class CComMidi : public CComBase static CComMidi* CreateInstance(LPCTSTR lpMidiOut, LPCTSTR lpMidiIn, LPCTSTR lpModule); virtual void SendActive(); - UINT8 m_useactivesense; /*!< ACTIVESENSE𑗂葱 */ - UINT32 m_activesenseInterval; /*!< ACTIVESENSE𑗂葱Ԋu */ - HANDLE m_activesenseExitRequestEvent; /*!< ACTIVESENSEMXbhINGXg */ - HANDLE m_activesenseExitEvent; /*!< ACTIVESENSEMXbhICxg */ + UINT8 m_useactivesense; /*!< ACTIVESENSEを送り続ける */ + UINT32 m_activesenseInterval; /*!< ACTIVESENSEを送り続ける間隔 */ + HANDLE m_activesenseExitRequestEvent; /*!< ACTIVESENSE送信スレッド終了リクエスト */ + HANDLE m_activesenseExitEvent; /*!< ACTIVESENSE送信スレッド終了イベント */ protected: CComMidi(); @@ -52,7 +52,7 @@ class CComMidi : public CComBase }; /** - * tFCY + * フェイズ */ enum tagMidiCtrl { @@ -77,17 +77,17 @@ class CComMidi : public CComBase CComMidiIn32* m_pMidiIn; /*!< MIDI IN */ CComMidiOut* m_pMidiOut; /*!< MIDI OUT */ - UINT m_nModule; /*!< W[ԍ */ - tagMidiCtrl m_nMidiCtrl; /*!< tF[Y */ - UINT m_nIndex; /*!< obt@ʒu */ - UINT m_nRecvSize; /*!< MTCY */ - UINT8 m_cLastData; /*!< Ō̃f[^ */ - bool m_bMimpiDef; /*!< MIMPIDEF L */ + UINT m_nModule; /*!< モジュール番号 */ + tagMidiCtrl m_nMidiCtrl; /*!< フェーズ */ + UINT m_nIndex; /*!< バッファ位置 */ + UINT m_nRecvSize; /*!< 受信サイズ */ + UINT8 m_cLastData; /*!< 最後のデータ */ + bool m_bMimpiDef; /*!< MIMPIDEF 有効 */ MIMPIDEF m_mimpiDef; /*!< MIMPIDEF */ MIDICH m_midich[16]; /*!< MIDI CH */ - UINT8 m_sBuffer[MIDI_BUFFER]; /*!< obt@ */ + UINT8 m_sBuffer[MIDI_BUFFER]; /*!< バッファ */ - HANDLE m_activesenseThread; /*!< ACTIVESENSEMXbh */ + HANDLE m_activesenseThread; /*!< ACTIVESENSE送信スレッド */ bool Initialize(LPCTSTR lpMidiOut, LPCTSTR lpMidiIn, LPCTSTR lpModule); static UINT module2number(LPCTSTR lpModule); diff --git a/windows/commng/cmmidiin32.cpp b/windows/commng/cmmidiin32.cpp old mode 100755 new mode 100644 index 2f07f1cf..e8061ff6 --- a/windows/commng/cmmidiin32.cpp +++ b/windows/commng/cmmidiin32.cpp @@ -1,200 +1,200 @@ -/** - * @file cmmidiin32.cpp - * @brief MIDI IN win32 クラスの動作の定義を行います - */ - -#include -#include "cmmidiin32.h" -#include - -#if !defined(__GNUC__) -#pragma comment(lib, "winmm.lib") -#endif // !defined(__GNUC__) - -/*!< ハンドル マップ */ -std::map CComMidiIn32::sm_midiinMap; - -/** - * インスタンスを作成 - * @param[in] lpMidiIn デバイス名 - * @return インスタンス - */ -CComMidiIn32* CComMidiIn32::CreateInstance(LPCTSTR lpMidiIn) -{ - UINT nId; - if (!GetId(lpMidiIn, &nId)) - { - return NULL; - } - - HMIDIIN hMidiIn = NULL; - if (::midiInOpen(&hMidiIn, nId, reinterpret_cast(g_hWndMain), 0, CALLBACK_WINDOW) != MMSYSERR_NOERROR) - { - return NULL; - } - return new CComMidiIn32(hMidiIn); -} - -/** - * コンストラクタ - * @param[in] hMidiIn ハンドル - */ -CComMidiIn32::CComMidiIn32(HMIDIIN hMidiIn) - : m_hMidiIn(hMidiIn) -{ - ::midiInReset(hMidiIn); - - sm_midiinMap[hMidiIn] = this; - - ZeroMemory(&m_midihdr, sizeof(m_midihdr)); - ZeroMemory(m_midiinBuffer, sizeof(m_midiinBuffer)); - - m_midihdr.lpData = m_midiinBuffer; - m_midihdr.dwBufferLength = sizeof(m_midiinBuffer); - ::midiInPrepareHeader(hMidiIn, &m_midihdr, sizeof(m_midihdr)); - ::midiInAddBuffer(hMidiIn, &m_midihdr, sizeof(m_midihdr)); - ::midiInStart(hMidiIn); -} - -/** - * デストラクタ - */ -CComMidiIn32::~CComMidiIn32() -{ - ::midiInStop(m_hMidiIn); - ::midiInUnprepareHeader(m_hMidiIn, &m_midihdr, sizeof(m_midihdr)); - sm_midiinMap.erase(m_hMidiIn); - - ::midiInReset(m_hMidiIn); - ::midiInClose(m_hMidiIn); -} - -/** - * 読み込み - * @param[out] pData バッファ - * @return サイズ - */ -UINT CComMidiIn32::Read(UINT8* pData) -{ - if (!m_buffer.empty()) - { - *pData = m_buffer.front(); - m_buffer.pop_front(); - return 1; - } - else - { - return 0; - } -} - -/** - * ID を得る - * @param[in] lpMidiIn デバイス名 - * @param[out] pId ID - * @retval true 成功 - * @retval false 失敗 - */ -bool CComMidiIn32::GetId(LPCTSTR lpMidiIn, UINT* pId) -{ - const UINT nNum = ::midiInGetNumDevs(); - for (UINT i = 0; i < nNum; i++) - { - MIDIINCAPS mic; - if (::midiInGetDevCaps(i, &mic, sizeof(mic)) != MMSYSERR_NOERROR) - { - continue; - } - if (!milstr_cmp(lpMidiIn, mic.szPname)) - { - *pId = i; - return true; - } - } - return false; -} - -/** - * インスタンスを検索 - * @param[in] hMidiIn ハンドル - * @return インスタンス - */ -CComMidiIn32* CComMidiIn32::GetInstance(HMIDIIN hMidiIn) -{ - std::map::iterator it = sm_midiinMap.find(hMidiIn); - if (it != sm_midiinMap.end()) - { - return it->second; - } - return NULL; -} - -/** - * メッセージ受信 - * @param[in] hMidiIn ハンドル - * @param[in] nMessage メッセージ - */ -void CComMidiIn32::RecvData(HMIDIIN hMidiIn, UINT nMessage) -{ - CComMidiIn32* pMidiIn32 = GetInstance(hMidiIn); - if (pMidiIn32) - { - pMidiIn32->OnRecvData(nMessage); - } -} - -/** - * メッセージ受信 - * @param[in] nMessage メッセージ - */ -void CComMidiIn32::OnRecvData(UINT nMessage) -{ - switch (nMessage & 0xf0) - { - case 0xc0: - case 0xd0: - m_buffer.push_back(static_cast(nMessage)); - m_buffer.push_back(static_cast(nMessage >> 8)); - break; - - case 0x80: - case 0x90: - case 0xa0: - case 0xb0: - case 0xe0: - m_buffer.push_back(static_cast(nMessage)); - m_buffer.push_back(static_cast(nMessage >> 8)); - m_buffer.push_back(static_cast(nMessage >> 16)); - break; - } -} - -/** - * メッセージ受信 - * @param[in] hMidiIn ハンドル - * @param[in] lpMidiHdr メッセージ - */ -void CComMidiIn32::RecvExcv(HMIDIIN hMidiIn, MIDIHDR* lpMidiHdr) -{ - CComMidiIn32* pMidiIn32 = GetInstance(hMidiIn); - if (pMidiIn32) - { - pMidiIn32->OnRecvExcv(lpMidiHdr); - } -} - -/** - * メッセージ受信 - * @param[in] lpMidiHdr メッセージ - */ -void CComMidiIn32::OnRecvExcv(MIDIHDR* lpMidiHdr) -{ - for (DWORD i = 0; i < lpMidiHdr->dwBytesRecorded; i++) - { - m_buffer.push_back(lpMidiHdr->lpData[i]); - } - - ::midiInUnprepareHeader(m_hMidiIn, &m_midihdr, sizeof(m_midihdr)); - ::midiInPrepareHeader(m_hMidiIn, &m_midihdr, sizeof(m_midihdr)); - ::midiInAddBuffer(m_hMidiIn, &m_midihdr, sizeof(m_midihdr)); -} +/** + * @file cmmidiin32.cpp + * @brief MIDI IN win32 クラスの動作の定義を行います + */ + +#include +#include "cmmidiin32.h" +#include + +#if !defined(__GNUC__) +#pragma comment(lib, "winmm.lib") +#endif // !defined(__GNUC__) + +/*!< ハンドル マップ */ +std::map CComMidiIn32::sm_midiinMap; + +/** + * インスタンスを作成 + * @param[in] lpMidiIn デバイス名 + * @return インスタンス + */ +CComMidiIn32* CComMidiIn32::CreateInstance(LPCTSTR lpMidiIn) +{ + UINT nId; + if (!GetId(lpMidiIn, &nId)) + { + return NULL; + } + + HMIDIIN hMidiIn = NULL; + if (::midiInOpen(&hMidiIn, nId, reinterpret_cast(g_hWndMain), 0, CALLBACK_WINDOW) != MMSYSERR_NOERROR) + { + return NULL; + } + return new CComMidiIn32(hMidiIn); +} + +/** + * コンストラクタ + * @param[in] hMidiIn ハンドル + */ +CComMidiIn32::CComMidiIn32(HMIDIIN hMidiIn) + : m_hMidiIn(hMidiIn) +{ + ::midiInReset(hMidiIn); + + sm_midiinMap[hMidiIn] = this; + + ZeroMemory(&m_midihdr, sizeof(m_midihdr)); + ZeroMemory(m_midiinBuffer, sizeof(m_midiinBuffer)); + + m_midihdr.lpData = m_midiinBuffer; + m_midihdr.dwBufferLength = sizeof(m_midiinBuffer); + ::midiInPrepareHeader(hMidiIn, &m_midihdr, sizeof(m_midihdr)); + ::midiInAddBuffer(hMidiIn, &m_midihdr, sizeof(m_midihdr)); + ::midiInStart(hMidiIn); +} + +/** + * デストラクタ + */ +CComMidiIn32::~CComMidiIn32() +{ + ::midiInStop(m_hMidiIn); + ::midiInUnprepareHeader(m_hMidiIn, &m_midihdr, sizeof(m_midihdr)); + sm_midiinMap.erase(m_hMidiIn); + + ::midiInReset(m_hMidiIn); + ::midiInClose(m_hMidiIn); +} + +/** + * 読み込み + * @param[out] pData バッファ + * @return サイズ + */ +UINT CComMidiIn32::Read(UINT8* pData) +{ + if (!m_buffer.empty()) + { + *pData = m_buffer.front(); + m_buffer.pop_front(); + return 1; + } + else + { + return 0; + } +} + +/** + * ID を得る + * @param[in] lpMidiIn デバイス名 + * @param[out] pId ID + * @retval true 成功 + * @retval false 失敗 + */ +bool CComMidiIn32::GetId(LPCTSTR lpMidiIn, UINT* pId) +{ + const UINT nNum = ::midiInGetNumDevs(); + for (UINT i = 0; i < nNum; i++) + { + MIDIINCAPS mic; + if (::midiInGetDevCaps(i, &mic, sizeof(mic)) != MMSYSERR_NOERROR) + { + continue; + } + if (!milstr_cmp(lpMidiIn, mic.szPname)) + { + *pId = i; + return true; + } + } + return false; +} + +/** + * インスタンスを検索 + * @param[in] hMidiIn ハンドル + * @return インスタンス + */ +CComMidiIn32* CComMidiIn32::GetInstance(HMIDIIN hMidiIn) +{ + std::map::iterator it = sm_midiinMap.find(hMidiIn); + if (it != sm_midiinMap.end()) + { + return it->second; + } + return NULL; +} + +/** + * メッセージ受信 + * @param[in] hMidiIn ハンドル + * @param[in] nMessage メッセージ + */ +void CComMidiIn32::RecvData(HMIDIIN hMidiIn, UINT nMessage) +{ + CComMidiIn32* pMidiIn32 = GetInstance(hMidiIn); + if (pMidiIn32) + { + pMidiIn32->OnRecvData(nMessage); + } +} + +/** + * メッセージ受信 + * @param[in] nMessage メッセージ + */ +void CComMidiIn32::OnRecvData(UINT nMessage) +{ + switch (nMessage & 0xf0) + { + case 0xc0: + case 0xd0: + m_buffer.push_back(static_cast(nMessage)); + m_buffer.push_back(static_cast(nMessage >> 8)); + break; + + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: + case 0xe0: + m_buffer.push_back(static_cast(nMessage)); + m_buffer.push_back(static_cast(nMessage >> 8)); + m_buffer.push_back(static_cast(nMessage >> 16)); + break; + } +} + +/** + * メッセージ受信 + * @param[in] hMidiIn ハンドル + * @param[in] lpMidiHdr メッセージ + */ +void CComMidiIn32::RecvExcv(HMIDIIN hMidiIn, MIDIHDR* lpMidiHdr) +{ + CComMidiIn32* pMidiIn32 = GetInstance(hMidiIn); + if (pMidiIn32) + { + pMidiIn32->OnRecvExcv(lpMidiHdr); + } +} + +/** + * メッセージ受信 + * @param[in] lpMidiHdr メッセージ + */ +void CComMidiIn32::OnRecvExcv(MIDIHDR* lpMidiHdr) +{ + for (DWORD i = 0; i < lpMidiHdr->dwBytesRecorded; i++) + { + m_buffer.push_back(lpMidiHdr->lpData[i]); + } + + ::midiInUnprepareHeader(m_hMidiIn, &m_midihdr, sizeof(m_midihdr)); + ::midiInPrepareHeader(m_hMidiIn, &m_midihdr, sizeof(m_midihdr)); + ::midiInAddBuffer(m_hMidiIn, &m_midihdr, sizeof(m_midihdr)); +} diff --git a/windows/commng/cmmidiin32.h b/windows/commng/cmmidiin32.h old mode 100755 new mode 100644 index bb8b918d..72e22189 --- a/windows/commng/cmmidiin32.h +++ b/windows/commng/cmmidiin32.h @@ -1,37 +1,37 @@ -/** - * @file cmmidiin32.h - * @brief MIDI IN win32 クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include - -/** - * @brief MIDI IN win32 クラス - */ -class CComMidiIn32 -{ -public: - static CComMidiIn32* CreateInstance(LPCTSTR lpMidiIn); - - CComMidiIn32(HMIDIIN hMidiIn); - ~CComMidiIn32(); - UINT Read(UINT8* pData); - static void RecvData(HMIDIIN hMidiIn, UINT nMessage); - static void RecvExcv(HMIDIIN hMidiIn, MIDIHDR* lpMidiHdr); - -private: - static std::map sm_midiinMap; /*!< ハンドル マップ */ - - HMIDIIN m_hMidiIn; /*!< MIDIIN ハンドル */ - MIDIHDR m_midihdr; /*!< MIDIHDR */ - std::deque m_buffer; /*!< 受信バッファ */ - char m_midiinBuffer[1024]; /*!< バッファ */ - - static bool GetId(LPCTSTR lpMidiIn, UINT* pId); - static CComMidiIn32* GetInstance(HMIDIIN hMidiIn); - void OnRecvData(UINT nMessage); - void OnRecvExcv(MIDIHDR* lpMidiHdr); -}; +/** + * @file cmmidiin32.h + * @brief MIDI IN win32 クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include + +/** + * @brief MIDI IN win32 クラス + */ +class CComMidiIn32 +{ +public: + static CComMidiIn32* CreateInstance(LPCTSTR lpMidiIn); + + CComMidiIn32(HMIDIIN hMidiIn); + ~CComMidiIn32(); + UINT Read(UINT8* pData); + static void RecvData(HMIDIIN hMidiIn, UINT nMessage); + static void RecvExcv(HMIDIIN hMidiIn, MIDIHDR* lpMidiHdr); + +private: + static std::map sm_midiinMap; /*!< ハンドル マップ */ + + HMIDIIN m_hMidiIn; /*!< MIDIIN ハンドル */ + MIDIHDR m_midihdr; /*!< MIDIHDR */ + std::deque m_buffer; /*!< 受信バッファ */ + char m_midiinBuffer[1024]; /*!< バッファ */ + + static bool GetId(LPCTSTR lpMidiIn, UINT* pId); + static CComMidiIn32* GetInstance(HMIDIIN hMidiIn); + void OnRecvData(UINT nMessage); + void OnRecvExcv(MIDIHDR* lpMidiHdr); +}; diff --git a/windows/commng/cmmidiout.h b/windows/commng/cmmidiout.h old mode 100755 new mode 100644 index 6cc5e1fb..7079626d --- a/windows/commng/cmmidiout.h +++ b/windows/commng/cmmidiout.h @@ -1,37 +1,37 @@ -/** - * @file cmmidiout.h - * @brief MIDI OUT 基底クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -/** - * @brief MIDI OUT 基底クラス - */ -class CComMidiOut -{ -public: - /** - * デストラクタ - */ - virtual ~CComMidiOut() - { - } - - /** - * ショート メッセージ - * @param[in] nMessage メッセージ - */ - virtual void Short(UINT32 nMessage) - { - } - - /** - * ロング メッセージ - * @param[in] lpMessage メッセージ ポインタ - * @param[in] cbMessage メッセージ サイズ - */ - virtual void Long(const UINT8* lpMessage, UINT cbMessage) - { - } -}; +/** + * @file cmmidiout.h + * @brief MIDI OUT 基底クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +/** + * @brief MIDI OUT 基底クラス + */ +class CComMidiOut +{ +public: + /** + * デストラクタ + */ + virtual ~CComMidiOut() + { + } + + /** + * ショート メッセージ + * @param[in] nMessage メッセージ + */ + virtual void Short(UINT32 nMessage) + { + } + + /** + * ロング メッセージ + * @param[in] lpMessage メッセージ ポインタ + * @param[in] cbMessage メッセージ サイズ + */ + virtual void Long(const UINT8* lpMessage, UINT cbMessage) + { + } +}; diff --git a/windows/commng/cmmidiout32.cpp b/windows/commng/cmmidiout32.cpp old mode 100755 new mode 100644 index e24f9b15..84f087bc --- a/windows/commng/cmmidiout32.cpp +++ b/windows/commng/cmmidiout32.cpp @@ -1,136 +1,136 @@ -/** - * @file cmmidiout32.cpp - * @brief MIDI OUT win32 クラスの動作の定義を行います - */ - -#include -#include "cmmidiout32.h" -#include "cmmidi.h" - -#if !defined(__GNUC__) -#pragma comment(lib, "winmm.lib") -#endif // !defined(__GNUC__) - -/** - * インスタンスを作成 - * @param[in] lpMidiOut デバイス名 - * @return インスタンス - */ -CComMidiOut32* CComMidiOut32::CreateInstance(LPCTSTR lpMidiOut) -{ - UINT nId; - if (!GetId(lpMidiOut, &nId)) - { - return NULL; - } - - HMIDIOUT hMidiOut = NULL; - if (::midiOutOpen(&hMidiOut, nId, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) - { - return NULL; - } - return new CComMidiOut32(hMidiOut); -} - -/** - * コンストラクタ - * @param[in] hMidiOut ハンドル - */ -CComMidiOut32::CComMidiOut32(HMIDIOUT hMidiOut) - : m_hMidiOut(hMidiOut) - , m_bWaitingSentExclusive(false) -{ - ZeroMemory(&m_midihdr, sizeof(m_midihdr)); - ::midiOutReset(m_hMidiOut); -} - -/** - * デストラクタ - */ -CComMidiOut32::~CComMidiOut32() -{ - WaitSentExclusive(); - ::midiOutReset(m_hMidiOut); - ::midiOutClose(m_hMidiOut); -} - -/** - * エクスクルーシブ送信完了を待つ - */ -void CComMidiOut32::WaitSentExclusive() -{ - if (m_bWaitingSentExclusive) - { - m_bWaitingSentExclusive = false; - while (midiOutUnprepareHeader(m_hMidiOut, &m_midihdr, sizeof(m_midihdr)) == MIDIERR_STILLPLAYING) - { - } - } -} - -/** - * ショート メッセージ - * @param[in] nMessage メッセージ - */ -void CComMidiOut32::Short(UINT32 nMessage) -{ - WaitSentExclusive(); - ::midiOutShortMsg(m_hMidiOut, nMessage); -} - -/** - * ロング メッセージ - * @param[in] lpMessage メッセージ ポインタ - * @param[in] cbMessage メッセージ サイズ - */ -void CComMidiOut32::Long(const UINT8* lpMessage, UINT cbMessage) -{ - if (cbMessage == 0) - { - return; - } - - WaitSentExclusive(); - - m_excvbuf.resize(cbMessage); - CopyMemory(&m_excvbuf[0], lpMessage, cbMessage); - - m_midihdr.lpData = &m_excvbuf[0]; - m_midihdr.dwFlags = 0; - m_midihdr.dwBufferLength = cbMessage; - ::midiOutPrepareHeader(m_hMidiOut, &m_midihdr, sizeof(m_midihdr)); - ::midiOutLongMsg(m_hMidiOut, &m_midihdr, sizeof(m_midihdr)); - m_bWaitingSentExclusive = true; -} - -/** - * ID を得る - * @param[in] lpMidiOut デバイス名 - * @param[out] pId ID - * @retval true 成功 - * @retval false 失敗 - */ -bool CComMidiOut32::GetId(LPCTSTR lpMidiOut, UINT* pId) -{ - const UINT nNum = ::midiOutGetNumDevs(); - for (UINT i = 0; i < nNum; i++) - { - MIDIOUTCAPS moc; - if (midiOutGetDevCaps(i, &moc, sizeof(moc)) != MMSYSERR_NOERROR) - { - continue; - } - if (!milstr_cmp(lpMidiOut, moc.szPname)) - { - *pId = i; - return true; - } - } - - if (!milstr_cmp(lpMidiOut, cmmidi_midimapper)) - { - *pId = MIDI_MAPPER; - return true; - } - return false; -} +/** + * @file cmmidiout32.cpp + * @brief MIDI OUT win32 クラスの動作の定義を行います + */ + +#include +#include "cmmidiout32.h" +#include "cmmidi.h" + +#if !defined(__GNUC__) +#pragma comment(lib, "winmm.lib") +#endif // !defined(__GNUC__) + +/** + * インスタンスを作成 + * @param[in] lpMidiOut デバイス名 + * @return インスタンス + */ +CComMidiOut32* CComMidiOut32::CreateInstance(LPCTSTR lpMidiOut) +{ + UINT nId; + if (!GetId(lpMidiOut, &nId)) + { + return NULL; + } + + HMIDIOUT hMidiOut = NULL; + if (::midiOutOpen(&hMidiOut, nId, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) + { + return NULL; + } + return new CComMidiOut32(hMidiOut); +} + +/** + * コンストラクタ + * @param[in] hMidiOut ハンドル + */ +CComMidiOut32::CComMidiOut32(HMIDIOUT hMidiOut) + : m_hMidiOut(hMidiOut) + , m_bWaitingSentExclusive(false) +{ + ZeroMemory(&m_midihdr, sizeof(m_midihdr)); + ::midiOutReset(m_hMidiOut); +} + +/** + * デストラクタ + */ +CComMidiOut32::~CComMidiOut32() +{ + WaitSentExclusive(); + ::midiOutReset(m_hMidiOut); + ::midiOutClose(m_hMidiOut); +} + +/** + * エクスクルーシブ送信完了を待つ + */ +void CComMidiOut32::WaitSentExclusive() +{ + if (m_bWaitingSentExclusive) + { + m_bWaitingSentExclusive = false; + while (midiOutUnprepareHeader(m_hMidiOut, &m_midihdr, sizeof(m_midihdr)) == MIDIERR_STILLPLAYING) + { + } + } +} + +/** + * ショート メッセージ + * @param[in] nMessage メッセージ + */ +void CComMidiOut32::Short(UINT32 nMessage) +{ + WaitSentExclusive(); + ::midiOutShortMsg(m_hMidiOut, nMessage); +} + +/** + * ロング メッセージ + * @param[in] lpMessage メッセージ ポインタ + * @param[in] cbMessage メッセージ サイズ + */ +void CComMidiOut32::Long(const UINT8* lpMessage, UINT cbMessage) +{ + if (cbMessage == 0) + { + return; + } + + WaitSentExclusive(); + + m_excvbuf.resize(cbMessage); + CopyMemory(&m_excvbuf[0], lpMessage, cbMessage); + + m_midihdr.lpData = &m_excvbuf[0]; + m_midihdr.dwFlags = 0; + m_midihdr.dwBufferLength = cbMessage; + ::midiOutPrepareHeader(m_hMidiOut, &m_midihdr, sizeof(m_midihdr)); + ::midiOutLongMsg(m_hMidiOut, &m_midihdr, sizeof(m_midihdr)); + m_bWaitingSentExclusive = true; +} + +/** + * ID を得る + * @param[in] lpMidiOut デバイス名 + * @param[out] pId ID + * @retval true 成功 + * @retval false 失敗 + */ +bool CComMidiOut32::GetId(LPCTSTR lpMidiOut, UINT* pId) +{ + const UINT nNum = ::midiOutGetNumDevs(); + for (UINT i = 0; i < nNum; i++) + { + MIDIOUTCAPS moc; + if (midiOutGetDevCaps(i, &moc, sizeof(moc)) != MMSYSERR_NOERROR) + { + continue; + } + if (!milstr_cmp(lpMidiOut, moc.szPname)) + { + *pId = i; + return true; + } + } + + if (!milstr_cmp(lpMidiOut, cmmidi_midimapper)) + { + *pId = MIDI_MAPPER; + return true; + } + return false; +} diff --git a/windows/commng/cmmidiout32.h b/windows/commng/cmmidiout32.h old mode 100755 new mode 100644 index 4bb0e05d..97a0f4e9 --- a/windows/commng/cmmidiout32.h +++ b/windows/commng/cmmidiout32.h @@ -1,32 +1,32 @@ -/** - * @file cmmidiout32.h - * @brief MIDI OUT win32 クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include "cmmidiout.h" - -/** - * @brief MIDI OUT win32 クラス - */ -class CComMidiOut32 : public CComMidiOut -{ -public: - static CComMidiOut32* CreateInstance(LPCTSTR lpMidiOut); - - CComMidiOut32(HMIDIOUT hMidiOut); - virtual ~CComMidiOut32(); - virtual void Short(UINT32 nMessage); - virtual void Long(const UINT8* lpMessage, UINT cbMessage); - static bool GetId(LPCTSTR lpMidiOut, UINT* pId); - -private: - HMIDIOUT m_hMidiOut; /*!< MIDIOUT ハンドル */ - MIDIHDR m_midihdr; /*!< MIDIHDR */ - bool m_bWaitingSentExclusive; /*!< エクスクルーシヴ送信中 */ - std::vector m_excvbuf; /*!< エクスクルーシヴ バッファ */ - - void WaitSentExclusive(); -}; +/** + * @file cmmidiout32.h + * @brief MIDI OUT win32 クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include "cmmidiout.h" + +/** + * @brief MIDI OUT win32 クラス + */ +class CComMidiOut32 : public CComMidiOut +{ +public: + static CComMidiOut32* CreateInstance(LPCTSTR lpMidiOut); + + CComMidiOut32(HMIDIOUT hMidiOut); + virtual ~CComMidiOut32(); + virtual void Short(UINT32 nMessage); + virtual void Long(const UINT8* lpMessage, UINT cbMessage); + static bool GetId(LPCTSTR lpMidiOut, UINT* pId); + +private: + HMIDIOUT m_hMidiOut; /*!< MIDIOUT ハンドル */ + MIDIHDR m_midihdr; /*!< MIDIHDR */ + bool m_bWaitingSentExclusive; /*!< エクスクルーシヴ送信中 */ + std::vector m_excvbuf; /*!< エクスクルーシヴ バッファ */ + + void WaitSentExclusive(); +}; diff --git a/windows/commng/cmmidioutmt32sound.cpp b/windows/commng/cmmidioutmt32sound.cpp old mode 100755 new mode 100644 index 95a0a54f..1220f6a3 --- a/windows/commng/cmmidioutmt32sound.cpp +++ b/windows/commng/cmmidioutmt32sound.cpp @@ -1,77 +1,77 @@ -/** - * @file cmmidioutmt32sound.cpp - * @brief MIDI OUT MT32Sound クラスの動作の定義を行います - */ - -#include -#include "cmmidioutmt32sound.h" - -#if defined(MT32SOUND_DLL) - -#include "ext\mt32snd.h" - -/** - * インスタンスを作成 - * @return インスタンス - */ -CComMidiOutMT32Sound* CComMidiOutMT32Sound::CreateInstance() -{ - MT32Sound* pMT32Sound = MT32Sound::GetInstance(); - if (!pMT32Sound->Open()) - { - return NULL; - } - return new CComMidiOutMT32Sound(pMT32Sound); -} - -/** - * コンストラクタ - * @param[in] pMT32Sound ハンドル - */ -CComMidiOutMT32Sound::CComMidiOutMT32Sound(MT32Sound* pMT32Sound) - : m_pMT32Sound(pMT32Sound) -{ - ::sound_streamregist(m_pMT32Sound, reinterpret_cast(GetPcm)); -} - -/** - * デストラクタ - */ -CComMidiOutMT32Sound::~CComMidiOutMT32Sound() -{ - m_pMT32Sound->Close(); -} - -/** - * ショート メッセージ - * @param[in] nMessage メッセージ - */ -void CComMidiOutMT32Sound::Short(UINT32 nMessage) -{ - sound_sync(); - m_pMT32Sound->ShortMsg(nMessage); -} - -/** - * ロング メッセージ - * @param[in] lpMessage メッセージ ポインタ - * @param[in] cbMessage メッセージ サイズ - */ -void CComMidiOutMT32Sound::Long(const UINT8* lpMessage, UINT cbMessage) -{ - sound_sync(); - m_pMT32Sound->LongMsg(lpMessage, cbMessage); -} - -/** - * プロセス - * @param[in] pMT32Sound ハンドル - * @param[out] lpBuffer バッファ - * @param[in] nBufferCount サンプル数 - */ -void SOUNDCALL CComMidiOutMT32Sound::GetPcm(MT32Sound* pMT32Sound, SINT32* lpBuffer, UINT nBufferCount) -{ - pMT32Sound->Mix(lpBuffer, nBufferCount); -} - -#endif // defined(MT32SOUND_DLL) +/** + * @file cmmidioutmt32sound.cpp + * @brief MIDI OUT MT32Sound クラスの動作の定義を行います + */ + +#include +#include "cmmidioutmt32sound.h" + +#if defined(MT32SOUND_DLL) + +#include "ext\mt32snd.h" + +/** + * インスタンスを作成 + * @return インスタンス + */ +CComMidiOutMT32Sound* CComMidiOutMT32Sound::CreateInstance() +{ + MT32Sound* pMT32Sound = MT32Sound::GetInstance(); + if (!pMT32Sound->Open()) + { + return NULL; + } + return new CComMidiOutMT32Sound(pMT32Sound); +} + +/** + * コンストラクタ + * @param[in] pMT32Sound ハンドル + */ +CComMidiOutMT32Sound::CComMidiOutMT32Sound(MT32Sound* pMT32Sound) + : m_pMT32Sound(pMT32Sound) +{ + ::sound_streamregist(m_pMT32Sound, reinterpret_cast(GetPcm)); +} + +/** + * デストラクタ + */ +CComMidiOutMT32Sound::~CComMidiOutMT32Sound() +{ + m_pMT32Sound->Close(); +} + +/** + * ショート メッセージ + * @param[in] nMessage メッセージ + */ +void CComMidiOutMT32Sound::Short(UINT32 nMessage) +{ + sound_sync(); + m_pMT32Sound->ShortMsg(nMessage); +} + +/** + * ロング メッセージ + * @param[in] lpMessage メッセージ ポインタ + * @param[in] cbMessage メッセージ サイズ + */ +void CComMidiOutMT32Sound::Long(const UINT8* lpMessage, UINT cbMessage) +{ + sound_sync(); + m_pMT32Sound->LongMsg(lpMessage, cbMessage); +} + +/** + * プロセス + * @param[in] pMT32Sound ハンドル + * @param[out] lpBuffer バッファ + * @param[in] nBufferCount サンプル数 + */ +void SOUNDCALL CComMidiOutMT32Sound::GetPcm(MT32Sound* pMT32Sound, SINT32* lpBuffer, UINT nBufferCount) +{ + pMT32Sound->Mix(lpBuffer, nBufferCount); +} + +#endif // defined(MT32SOUND_DLL) diff --git a/windows/commng/cmmidioutmt32sound.h b/windows/commng/cmmidioutmt32sound.h old mode 100755 new mode 100644 index ba07ebb5..6b0e9fc5 --- a/windows/commng/cmmidioutmt32sound.h +++ b/windows/commng/cmmidioutmt32sound.h @@ -1,33 +1,33 @@ -/** - * @file cmmidioutmt32sound.h - * @brief MIDI OUT MT32Sound クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#if defined(MT32SOUND_DLL) - -#include "cmmidiout.h" -#include - -class MT32Sound; - -/** - * @brief MIDI OUT MT32Sound クラス - */ -class CComMidiOutMT32Sound : public CComMidiOut -{ -public: - static CComMidiOutMT32Sound* CreateInstance(); - - CComMidiOutMT32Sound(MT32Sound* pMT32Sound); - virtual ~CComMidiOutMT32Sound(); - virtual void Short(UINT32 nMessage); - virtual void Long(const UINT8* lpMessage, UINT cbMessage); - -private: - MT32Sound* m_pMT32Sound; /*!< The instance of mt32sound */ - static void SOUNDCALL GetPcm(MT32Sound* pMT32Sound, SINT32* lpBuffer, UINT nBufferCount); -}; - -#endif // defined(MT32SOUND_DLL) +/** + * @file cmmidioutmt32sound.h + * @brief MIDI OUT MT32Sound クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#if defined(MT32SOUND_DLL) + +#include "cmmidiout.h" +#include + +class MT32Sound; + +/** + * @brief MIDI OUT MT32Sound クラス + */ +class CComMidiOutMT32Sound : public CComMidiOut +{ +public: + static CComMidiOutMT32Sound* CreateInstance(); + + CComMidiOutMT32Sound(MT32Sound* pMT32Sound); + virtual ~CComMidiOutMT32Sound(); + virtual void Short(UINT32 nMessage); + virtual void Long(const UINT8* lpMessage, UINT cbMessage); + +private: + MT32Sound* m_pMT32Sound; /*!< The instance of mt32sound */ + static void SOUNDCALL GetPcm(MT32Sound* pMT32Sound, SINT32* lpBuffer, UINT nBufferCount); +}; + +#endif // defined(MT32SOUND_DLL) diff --git a/windows/commng/cmmidioutvermouth.cpp b/windows/commng/cmmidioutvermouth.cpp old mode 100755 new mode 100644 index 00e4419c..a88aa791 --- a/windows/commng/cmmidioutvermouth.cpp +++ b/windows/commng/cmmidioutvermouth.cpp @@ -1,94 +1,94 @@ -/** - * @file cmmidioutvermouth.cpp - * @brief MIDI OUT Vermouth クラスの動作の定義を行います - */ - -#include -#include "cmmidioutvermouth.h" - -#if defined(VERMOUTH_LIB) - -//! ハンドル -extern MIDIMOD vermouth_module; - -/** - * インスタンスを作成 - * @return インスタンス - */ -CComMidiOutVermouth* CComMidiOutVermouth::CreateInstance() -{ - MIDIHDL vermouth = midiout_create(vermouth_module, 512); - if (vermouth == NULL) - { - return NULL; - } - return new CComMidiOutVermouth(vermouth); -} - -/** - * コンストラクタ - * @param[in] vermouth ハンドル - */ -CComMidiOutVermouth::CComMidiOutVermouth(MIDIHDL vermouth) - : m_vermouth(vermouth) -{ - ::sound_streamregist(m_vermouth, reinterpret_cast(GetPcm)); -} - -/** - * デストラクタ - */ -CComMidiOutVermouth::~CComMidiOutVermouth() -{ - ::midiout_destroy(m_vermouth); -} - -/** - * ショート メッセージ - * @param[in] nMessage メッセージ - */ -void CComMidiOutVermouth::Short(UINT32 nMessage) -{ - sound_sync(); - ::midiout_shortmsg(m_vermouth, nMessage); -} - -/** - * ロング メッセージ - * @param[in] lpMessage メッセージ ポインタ - * @param[in] cbMessage メッセージ サイズ - */ -void CComMidiOutVermouth::Long(const UINT8* lpMessage, UINT cbMessage) -{ - sound_sync(); - ::midiout_longmsg(m_vermouth, lpMessage, cbMessage); -} - -/** - * プロセス - * @param[in] vermouth ハンドル - * @param[out] lpBuffer バッファ - * @param[in] nBufferCount サンプル数 - */ -void SOUNDCALL CComMidiOutVermouth::GetPcm(MIDIHDL vermouth, SINT32* lpBuffer, UINT nBufferCount) -{ - while (nBufferCount) - { - UINT nSize = nBufferCount; - const SINT32* ptr = ::midiout_get(vermouth, &nSize); - if (ptr == NULL) - { - break; - } - nBufferCount -= nSize; - do - { - lpBuffer[0] += ptr[0]; - lpBuffer[1] += ptr[1]; - ptr += 2; - lpBuffer += 2; - } while (--nSize); - } -} - -#endif // defined(VERMOUTH_LIB) +/** + * @file cmmidioutvermouth.cpp + * @brief MIDI OUT Vermouth クラスの動作の定義を行います + */ + +#include +#include "cmmidioutvermouth.h" + +#if defined(VERMOUTH_LIB) + +//! ハンドル +extern MIDIMOD vermouth_module; + +/** + * インスタンスを作成 + * @return インスタンス + */ +CComMidiOutVermouth* CComMidiOutVermouth::CreateInstance() +{ + MIDIHDL vermouth = midiout_create(vermouth_module, 512); + if (vermouth == NULL) + { + return NULL; + } + return new CComMidiOutVermouth(vermouth); +} + +/** + * コンストラクタ + * @param[in] vermouth ハンドル + */ +CComMidiOutVermouth::CComMidiOutVermouth(MIDIHDL vermouth) + : m_vermouth(vermouth) +{ + ::sound_streamregist(m_vermouth, reinterpret_cast(GetPcm)); +} + +/** + * デストラクタ + */ +CComMidiOutVermouth::~CComMidiOutVermouth() +{ + ::midiout_destroy(m_vermouth); +} + +/** + * ショート メッセージ + * @param[in] nMessage メッセージ + */ +void CComMidiOutVermouth::Short(UINT32 nMessage) +{ + sound_sync(); + ::midiout_shortmsg(m_vermouth, nMessage); +} + +/** + * ロング メッセージ + * @param[in] lpMessage メッセージ ポインタ + * @param[in] cbMessage メッセージ サイズ + */ +void CComMidiOutVermouth::Long(const UINT8* lpMessage, UINT cbMessage) +{ + sound_sync(); + ::midiout_longmsg(m_vermouth, lpMessage, cbMessage); +} + +/** + * プロセス + * @param[in] vermouth ハンドル + * @param[out] lpBuffer バッファ + * @param[in] nBufferCount サンプル数 + */ +void SOUNDCALL CComMidiOutVermouth::GetPcm(MIDIHDL vermouth, SINT32* lpBuffer, UINT nBufferCount) +{ + while (nBufferCount) + { + UINT nSize = nBufferCount; + const SINT32* ptr = ::midiout_get(vermouth, &nSize); + if (ptr == NULL) + { + break; + } + nBufferCount -= nSize; + do + { + lpBuffer[0] += ptr[0]; + lpBuffer[1] += ptr[1]; + ptr += 2; + lpBuffer += 2; + } while (--nSize); + } +} + +#endif // defined(VERMOUTH_LIB) diff --git a/windows/commng/cmmidioutvermouth.h b/windows/commng/cmmidioutvermouth.h old mode 100755 new mode 100644 index f2b8859e..b1353792 --- a/windows/commng/cmmidioutvermouth.h +++ b/windows/commng/cmmidioutvermouth.h @@ -1,32 +1,32 @@ -/** - * @file cmmidioutvermouth.h - * @brief MIDI OUT Vermouth クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#if defined(VERMOUTH_LIB) - -#include "cmmidiout.h" -#include -#include "sound\vermouth\vermouth.h" - -/** - * @brief MIDI OUT Vermouthクラス - */ -class CComMidiOutVermouth : public CComMidiOut -{ -public: - static CComMidiOutVermouth* CreateInstance(); - - CComMidiOutVermouth(MIDIHDL vermouth); - virtual ~CComMidiOutVermouth(); - virtual void Short(UINT32 nMessage); - virtual void Long(const UINT8* lpMessage, UINT cbMessage); - -private: - MIDIHDL m_vermouth; /*!< The instance of vermouth */ - static void SOUNDCALL GetPcm(MIDIHDL vermouth, SINT32* lpBuffer, UINT nBufferCount); -}; - -#endif // defined(VERMOUTH_LIB) +/** + * @file cmmidioutvermouth.h + * @brief MIDI OUT Vermouth クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#if defined(VERMOUTH_LIB) + +#include "cmmidiout.h" +#include +#include "sound\vermouth\vermouth.h" + +/** + * @brief MIDI OUT Vermouthクラス + */ +class CComMidiOutVermouth : public CComMidiOut +{ +public: + static CComMidiOutVermouth* CreateInstance(); + + CComMidiOutVermouth(MIDIHDL vermouth); + virtual ~CComMidiOutVermouth(); + virtual void Short(UINT32 nMessage); + virtual void Long(const UINT8* lpMessage, UINT cbMessage); + +private: + MIDIHDL m_vermouth; /*!< The instance of vermouth */ + static void SOUNDCALL GetPcm(MIDIHDL vermouth, SINT32* lpBuffer, UINT nBufferCount); +}; + +#endif // defined(VERMOUTH_LIB) diff --git a/windows/commng/cmmidioutvst.cpp b/windows/commng/cmmidioutvst.cpp old mode 100755 new mode 100644 index 3b649121..0cdf15d3 --- a/windows/commng/cmmidioutvst.cpp +++ b/windows/commng/cmmidioutvst.cpp @@ -1,181 +1,181 @@ -/** - * @file cmmidioutvst.cpp - * @brief MIDI OUT VST クラスの動作の定義を行います - */ - -#include - -#if defined(SUPPORT_VSTi) - -#include "cmmidioutvst.h" -#include -#include -#include - -#pragma comment(lib, "shlwapi.lib") - -/** - * VSTi モジュール ファイル名を得る - * @param[out] lpModule VSTi モジュール ファイル名 - * @param[in] cchModule VSTi モジュール ファイル名のバッファの長さ - */ -static void GetPath(LPTSTR lpModule, UINT cchModule) -{ - ::ExpandEnvironmentStrings(np2oscfg.szVSTiFile, lpModule, cchModule); -} - -/** - * VSTi は有効か? - * @retval true 有効 - * @retval false 無効 - */ -bool CComMidiOutVst::IsEnabled() -{ - TCHAR szModule[MAX_PATH]; - GetPath(szModule, _countof(szModule)); - return (::PathFileExists(szModule) != FALSE); -} - -/** - * インスタンスを作成 - * @return インスタンス - */ -CComMidiOutVst* CComMidiOutVst::CreateInstance() -{ - CComMidiOutVst* pVst = new CComMidiOutVst; - - TCHAR szModule[MAX_PATH]; - GetPath(szModule, _countof(szModule)); - if (!pVst->Initialize(szModule)) - { - delete pVst; - pVst = NULL; - } - return pVst; -} - -/** - * コンストラクタ - */ -CComMidiOutVst::CComMidiOutVst() - : m_nBlockSize(128) - , m_nIndex(0) -{ -} - -/** - * デストラクタ - */ -CComMidiOutVst::~CComMidiOutVst() -{ - m_wnd.Destroy(); - m_effect.Unload(); -} - -/** - * 初期化 - * @param[in] lpPath パス - * @retval true 成功 - * @retval false 失敗 - */ -bool CComMidiOutVst::Initialize(LPCTSTR lpPath) -{ - if (soundcfg.rate == 0) - { - return false; - } - - if (!m_effect.Load(lpPath)) - { - printf("Cloudn't attach VSTi.\n"); - return false; - } - - // Effect をオープン - m_effect.open(); - - // サンプリング レートを設定 - m_effect.setSampleRate(static_cast(soundcfg.rate)); - - // ブロックサイズを設定 - m_effect.setBlockSize(m_nBlockSize); - m_effect.resume(); - - m_effect.beginSetProgram(); - m_effect.setProgram(0); - m_effect.endSetProgram(); - - m_input.Alloc(2, m_nBlockSize); - m_output.Alloc(2, m_nBlockSize); - - ::sound_streamregist(this, reinterpret_cast(GetPcm)); - - m_wnd.Create(&m_effect, TEXT("NP2 VSTi"), WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX); - - return true; -} - -/** - * ショート メッセージ - * @param[in] nMessage メッセージ - */ -void CComMidiOutVst::Short(UINT32 nMessage) -{ - sound_sync(); - m_event.ShortMessage(m_nIndex, nMessage); -} - -/** - * ロング メッセージ - * @param[in] lpMessage メッセージ ポインタ - * @param[in] cbMessage メッセージ サイズ - */ -void CComMidiOutVst::Long(const UINT8* lpMessage, UINT cbMessage) -{ - sound_sync(); - m_event.LongMessage(m_nIndex, lpMessage, cbMessage); -} - -/** - * プロセス - * @param[in] pVst ハンドル - * @param[out] lpBuffer バッファ - * @param[in] nBufferCount サンプル数 - */ -void SOUNDCALL CComMidiOutVst::GetPcm(CComMidiOutVst* pVst, SINT32* lpBuffer, UINT nBufferCount) -{ - pVst->Process32(lpBuffer, nBufferCount); -} - -/** - * プロセス (32bit) - * @param[out] lpBuffer バッファ - * @param[in] nBufferCount サンプル数 - */ -void CComMidiOutVst::Process32(SINT32* lpBuffer, UINT nBufferCount) -{ - while (nBufferCount) - { - if (m_nIndex >= m_nBlockSize) - { - m_nIndex = 0; - m_effect.processEvents(m_event.GetEvents()); - m_effect.processReplacing(m_input.GetBuffer(), m_output.GetBuffer(), m_nBlockSize); - m_event.Clear(); - } - - UINT nSize = m_nBlockSize - m_nIndex; - nSize = MIN(nSize, nBufferCount); - nBufferCount -= nSize; - float** output = m_output.GetBuffer(); - do - { - lpBuffer[0] += static_cast(output[0][m_nIndex] * 32767.0f - 0.5f); - lpBuffer[1] += static_cast(output[1][m_nIndex] * 32767.0f - 0.5f); - lpBuffer += 2; - m_nIndex++; - } while (--nSize); - } -} - -#endif // defined(SUPPORT_VSTi) +/** + * @file cmmidioutvst.cpp + * @brief MIDI OUT VST クラスの動作の定義を行います + */ + +#include + +#if defined(SUPPORT_VSTi) + +#include "cmmidioutvst.h" +#include +#include +#include + +#pragma comment(lib, "shlwapi.lib") + +/** + * VSTi モジュール ファイル名を得る + * @param[out] lpModule VSTi モジュール ファイル名 + * @param[in] cchModule VSTi モジュール ファイル名のバッファの長さ + */ +static void GetPath(LPTSTR lpModule, UINT cchModule) +{ + ::ExpandEnvironmentStrings(np2oscfg.szVSTiFile, lpModule, cchModule); +} + +/** + * VSTi は有効か? + * @retval true 有効 + * @retval false 無効 + */ +bool CComMidiOutVst::IsEnabled() +{ + TCHAR szModule[MAX_PATH]; + GetPath(szModule, _countof(szModule)); + return (::PathFileExists(szModule) != FALSE); +} + +/** + * インスタンスを作成 + * @return インスタンス + */ +CComMidiOutVst* CComMidiOutVst::CreateInstance() +{ + CComMidiOutVst* pVst = new CComMidiOutVst; + + TCHAR szModule[MAX_PATH]; + GetPath(szModule, _countof(szModule)); + if (!pVst->Initialize(szModule)) + { + delete pVst; + pVst = NULL; + } + return pVst; +} + +/** + * コンストラクタ + */ +CComMidiOutVst::CComMidiOutVst() + : m_nBlockSize(128) + , m_nIndex(0) +{ +} + +/** + * デストラクタ + */ +CComMidiOutVst::~CComMidiOutVst() +{ + m_wnd.Destroy(); + m_effect.Unload(); +} + +/** + * 初期化 + * @param[in] lpPath パス + * @retval true 成功 + * @retval false 失敗 + */ +bool CComMidiOutVst::Initialize(LPCTSTR lpPath) +{ + if (soundcfg.rate == 0) + { + return false; + } + + if (!m_effect.Load(lpPath)) + { + printf("Cloudn't attach VSTi.\n"); + return false; + } + + // Effect をオープン + m_effect.open(); + + // サンプリング レートを設定 + m_effect.setSampleRate(static_cast(soundcfg.rate)); + + // ブロックサイズを設定 + m_effect.setBlockSize(m_nBlockSize); + m_effect.resume(); + + m_effect.beginSetProgram(); + m_effect.setProgram(0); + m_effect.endSetProgram(); + + m_input.Alloc(2, m_nBlockSize); + m_output.Alloc(2, m_nBlockSize); + + ::sound_streamregist(this, reinterpret_cast(GetPcm)); + + m_wnd.Create(&m_effect, TEXT("NP2 VSTi"), WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX); + + return true; +} + +/** + * ショート メッセージ + * @param[in] nMessage メッセージ + */ +void CComMidiOutVst::Short(UINT32 nMessage) +{ + sound_sync(); + m_event.ShortMessage(m_nIndex, nMessage); +} + +/** + * ロング メッセージ + * @param[in] lpMessage メッセージ ポインタ + * @param[in] cbMessage メッセージ サイズ + */ +void CComMidiOutVst::Long(const UINT8* lpMessage, UINT cbMessage) +{ + sound_sync(); + m_event.LongMessage(m_nIndex, lpMessage, cbMessage); +} + +/** + * プロセス + * @param[in] pVst ハンドル + * @param[out] lpBuffer バッファ + * @param[in] nBufferCount サンプル数 + */ +void SOUNDCALL CComMidiOutVst::GetPcm(CComMidiOutVst* pVst, SINT32* lpBuffer, UINT nBufferCount) +{ + pVst->Process32(lpBuffer, nBufferCount); +} + +/** + * プロセス (32bit) + * @param[out] lpBuffer バッファ + * @param[in] nBufferCount サンプル数 + */ +void CComMidiOutVst::Process32(SINT32* lpBuffer, UINT nBufferCount) +{ + while (nBufferCount) + { + if (m_nIndex >= m_nBlockSize) + { + m_nIndex = 0; + m_effect.processEvents(m_event.GetEvents()); + m_effect.processReplacing(m_input.GetBuffer(), m_output.GetBuffer(), m_nBlockSize); + m_event.Clear(); + } + + UINT nSize = m_nBlockSize - m_nIndex; + nSize = MIN(nSize, nBufferCount); + nBufferCount -= nSize; + float** output = m_output.GetBuffer(); + do + { + lpBuffer[0] += static_cast(output[0][m_nIndex] * 32767.0f - 0.5f); + lpBuffer[1] += static_cast(output[1][m_nIndex] * 32767.0f - 0.5f); + lpBuffer += 2; + m_nIndex++; + } while (--nSize); + } +} + +#endif // defined(SUPPORT_VSTi) diff --git a/windows/commng/cmmidioutvst.h b/windows/commng/cmmidioutvst.h old mode 100755 new mode 100644 index 84bc800a..ae146f79 --- a/windows/commng/cmmidioutvst.h +++ b/windows/commng/cmmidioutvst.h @@ -1,45 +1,45 @@ -/** - * @file cmmidioutvst.h - * @brief MIDI OUT VST クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#if defined(SUPPORT_VSTi) - -#include "cmmidiout.h" -#include -#include "vsthost\vstbuffer.h" -#include "vsthost\vsteditwnd.h" -#include "vsthost\vsteffect.h" -#include "vsthost\vstmidievent.h" - -/** - * @brief MIDI OUT VST クラス - */ -class CComMidiOutVst : public CComMidiOut -{ -public: - static bool IsEnabled(); - static CComMidiOutVst* CreateInstance(); - - CComMidiOutVst(); - virtual ~CComMidiOutVst(); - virtual void Short(UINT32 nMessage); - virtual void Long(const UINT8* lpMessage, UINT cbMessage); - -private: - UINT m_nBlockSize; /*!< ブロック サイズ */ - UINT m_nIndex; /*!< 読み取りインデックス */ - CVstEffect m_effect; /*!< エフェクト */ - CVstEditWnd m_wnd; /*!< ウィンドウ */ - CVstMidiEvent m_event; /*!< イベント */ - CVstBuffer m_input; /*!< 入力バッファ */ - CVstBuffer m_output; /*!< 出力バッファ */ - - bool Initialize(LPCTSTR lpPath); - static void SOUNDCALL GetPcm(CComMidiOutVst*, SINT32* lpBuffer, UINT nBufferCount); - void Process32(SINT32* lpBuffer, UINT nBufferCount); -}; - -#endif // defined(SUPPORT_VSTi) +/** + * @file cmmidioutvst.h + * @brief MIDI OUT VST クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#if defined(SUPPORT_VSTi) + +#include "cmmidiout.h" +#include +#include "vsthost\vstbuffer.h" +#include "vsthost\vsteditwnd.h" +#include "vsthost\vsteffect.h" +#include "vsthost\vstmidievent.h" + +/** + * @brief MIDI OUT VST クラス + */ +class CComMidiOutVst : public CComMidiOut +{ +public: + static bool IsEnabled(); + static CComMidiOutVst* CreateInstance(); + + CComMidiOutVst(); + virtual ~CComMidiOutVst(); + virtual void Short(UINT32 nMessage); + virtual void Long(const UINT8* lpMessage, UINT cbMessage); + +private: + UINT m_nBlockSize; /*!< ブロック サイズ */ + UINT m_nIndex; /*!< 読み取りインデックス */ + CVstEffect m_effect; /*!< エフェクト */ + CVstEditWnd m_wnd; /*!< ウィンドウ */ + CVstMidiEvent m_event; /*!< イベント */ + CVstBuffer m_input; /*!< 入力バッファ */ + CVstBuffer m_output; /*!< 出力バッファ */ + + bool Initialize(LPCTSTR lpPath); + static void SOUNDCALL GetPcm(CComMidiOutVst*, SINT32* lpBuffer, UINT nBufferCount); + void Process32(SINT32* lpBuffer, UINT nBufferCount); +}; + +#endif // defined(SUPPORT_VSTi) diff --git a/windows/commng/cmnull.cpp b/windows/commng/cmnull.cpp old mode 100755 new mode 100644 index 9fb4feab..75dbc7cb --- a/windows/commng/cmnull.cpp +++ b/windows/commng/cmnull.cpp @@ -1,63 +1,63 @@ -/** - * @file cmnull.h - * @brief commng NULL デバイス クラスの動作の定義を行います - */ - -#include -#include "cmnull.h" - -/** - * コンストラクタ - */ -CComNull::CComNull() - : CComBase(COMCONNECT_OFF) -{ -} - -/** - * Read - * @param[out] pData - * @return result - */ -UINT CComNull::Read(UINT8* pData) -{ - return 0; -} - -/** - * Write - * @param[in] cData - * @return result - */ -UINT CComNull::Write(UINT8 cData) -{ - return 0; -} - -/** - * ステータスを得る - * bit 7: ‾CI (RI, RING) - * bit 6: ‾CS (CTS) - * bit 5: ‾CD (DCD, RLSD) - * bit 4: reserved - * bit 3: reserved - * bit 2: reserved - * bit 1: reserved - * bit 0: ‾DSR (DR) - * @return ステータス - */ -UINT8 CComNull::GetStat() -{ - return 0xf1; -} - -/** - * メッセージ - * @param[in] nMessage メッセージ - * @param[in] nParam パラメタ - * @return リザルト コード - */ -INTPTR CComNull::Message(UINT nMessage, INTPTR nParam) -{ - return 0; -} +/** + * @file cmnull.h + * @brief commng NULL デバイス クラスの動作の定義を行います + */ + +#include +#include "cmnull.h" + +/** + * コンストラクタ + */ +CComNull::CComNull() + : CComBase(COMCONNECT_OFF) +{ +} + +/** + * Read + * @param[out] pData + * @return result + */ +UINT CComNull::Read(UINT8* pData) +{ + return 0; +} + +/** + * Write + * @param[in] cData + * @return result + */ +UINT CComNull::Write(UINT8 cData) +{ + return 0; +} + +/** + * ステータスを得る + * bit 7: ‾CI (RI, RING) + * bit 6: ‾CS (CTS) + * bit 5: ‾CD (DCD, RLSD) + * bit 4: reserved + * bit 3: reserved + * bit 2: reserved + * bit 1: reserved + * bit 0: ‾DSR (DR) + * @return ステータス + */ +UINT8 CComNull::GetStat() +{ + return 0xf1; +} + +/** + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParam パラメタ + * @return リザルト コード + */ +INTPTR CComNull::Message(UINT nMessage, INTPTR nParam) +{ + return 0; +} diff --git a/windows/commng/cmnull.h b/windows/commng/cmnull.h old mode 100755 new mode 100644 index e06369a2..08593a99 --- a/windows/commng/cmnull.h +++ b/windows/commng/cmnull.h @@ -1,23 +1,23 @@ -/** - * @file cmnull.h - * @brief commng NULL デバイス クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "cmbase.h" - -/** - * @brief commng NULL デバイス クラス - */ -class CComNull : public CComBase -{ -public: - CComNull(); - -protected: - virtual UINT Read(UINT8* pData); - virtual UINT Write(UINT8 cData); - virtual UINT8 GetStat(); - virtual INTPTR Message(UINT nMessage, INTPTR nParam); -}; +/** + * @file cmnull.h + * @brief commng NULL デバイス クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "cmbase.h" + +/** + * @brief commng NULL デバイス クラス + */ +class CComNull : public CComBase +{ +public: + CComNull(); + +protected: + virtual UINT Read(UINT8* pData); + virtual UINT Write(UINT8 cData); + virtual UINT8 GetStat(); + virtual INTPTR Message(UINT nMessage, INTPTR nParam); +}; diff --git a/windows/commng/cmpara.cpp b/windows/commng/cmpara.cpp old mode 100755 new mode 100644 index 4d31ce60..b7744ec7 --- a/windows/commng/cmpara.cpp +++ b/windows/commng/cmpara.cpp @@ -1,107 +1,107 @@ -/** - * @file cmpara.cpp - * @brief パラレル クラスの動作の定義を行います - */ - -#include -#include "cmpara.h" - -/** - * インスタンス作成 - * @param[in] nPort ポート番号 - * @return インスタンス - */ -CComPara* CComPara::CreateInstance(UINT nPort) -{ - CComPara* pPara = new CComPara; - if (!pPara->Initialize(nPort)) - { - delete pPara; - pPara = NULL; - } - return pPara; -} - -/** - * コンストラクタ - */ -CComPara::CComPara() - : CComBase(COMCONNECT_PARALLEL) - , m_hParallel(INVALID_HANDLE_VALUE) -{ -} - -/** - * デストラクタ - */ -CComPara::~CComPara() -{ - if (m_hParallel != INVALID_HANDLE_VALUE) - { - ::CloseHandle(m_hParallel); - m_hParallel = INVALID_HANDLE_VALUE; - } -} - -/** - * 初期化 - * @param[in] nPort ポート番号 - * @retval true 成功 - * @retval false 失敗 - */ -bool CComPara::Initialize(UINT nPort) -{ - wchar_t wName[16]; - swprintf(wName, 16, L"LPT%u", nPort); - m_hParallel = CreateFileW(wName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL); - return (m_hParallel != INVALID_HANDLE_VALUE); -} - -/** - * 読み込み - * @param[out] pData バッファ - * @return サイズ - */ -UINT CComPara::Read(UINT8* pData) -{ - return 0; -} - -/** - * 書き込み - * @param[out] cData データ - * @return サイズ - */ -UINT CComPara::Write(UINT8 cData) -{ - DWORD dwWrittenSize; - return (::WriteFile(m_hParallel, &cData, 1, &dwWrittenSize, NULL)) ? 1 : 0; -} - -/** - * ステータスを得る - * bit 7: ‾CI (RI, RING) - * bit 6: ‾CS (CTS) - * bit 5: ‾CD (DCD, RLSD) - * bit 4: reserved - * bit 3: reserved - * bit 2: reserved - * bit 1: reserved - * bit 0: ‾DSR (DR) - * @return ステータス - */ -UINT8 CComPara::GetStat() -{ - return 0x00; -} - -/** - * メッセージ - * @param[in] nMessage メッセージ - * @param[in] nParam パラメタ - * @return リザルト コード - */ -INTPTR CComPara::Message(UINT nMessage, INTPTR nParam) -{ - return 0; -} +/** + * @file cmpara.cpp + * @brief パラレル クラスの動作の定義を行います + */ + +#include +#include "cmpara.h" + +/** + * インスタンス作成 + * @param[in] nPort ポート番号 + * @return インスタンス + */ +CComPara* CComPara::CreateInstance(UINT nPort) +{ + CComPara* pPara = new CComPara; + if (!pPara->Initialize(nPort)) + { + delete pPara; + pPara = NULL; + } + return pPara; +} + +/** + * コンストラクタ + */ +CComPara::CComPara() + : CComBase(COMCONNECT_PARALLEL) + , m_hParallel(INVALID_HANDLE_VALUE) +{ +} + +/** + * デストラクタ + */ +CComPara::~CComPara() +{ + if (m_hParallel != INVALID_HANDLE_VALUE) + { + ::CloseHandle(m_hParallel); + m_hParallel = INVALID_HANDLE_VALUE; + } +} + +/** + * 初期化 + * @param[in] nPort ポート番号 + * @retval true 成功 + * @retval false 失敗 + */ +bool CComPara::Initialize(UINT nPort) +{ + wchar_t wName[16]; + swprintf(wName, 16, L"LPT%u", nPort); + m_hParallel = CreateFileW(wName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL); + return (m_hParallel != INVALID_HANDLE_VALUE); +} + +/** + * 読み込み + * @param[out] pData バッファ + * @return サイズ + */ +UINT CComPara::Read(UINT8* pData) +{ + return 0; +} + +/** + * 書き込み + * @param[out] cData データ + * @return サイズ + */ +UINT CComPara::Write(UINT8 cData) +{ + DWORD dwWrittenSize; + return (::WriteFile(m_hParallel, &cData, 1, &dwWrittenSize, NULL)) ? 1 : 0; +} + +/** + * ステータスを得る + * bit 7: ‾CI (RI, RING) + * bit 6: ‾CS (CTS) + * bit 5: ‾CD (DCD, RLSD) + * bit 4: reserved + * bit 3: reserved + * bit 2: reserved + * bit 1: reserved + * bit 0: ‾DSR (DR) + * @return ステータス + */ +UINT8 CComPara::GetStat() +{ + return 0x00; +} + +/** + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParam パラメタ + * @return リザルト コード + */ +INTPTR CComPara::Message(UINT nMessage, INTPTR nParam) +{ + return 0; +} diff --git a/windows/commng/cmpara.h b/windows/commng/cmpara.h old mode 100755 new mode 100644 index c7b23d19..a4ae84eb --- a/windows/commng/cmpara.h +++ b/windows/commng/cmpara.h @@ -1,30 +1,30 @@ -/** - * @file cmpara.h - * @brief パラレル クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "cmbase.h" - -/** - * @brief commng パラレル デバイス クラス - */ -class CComPara : public CComBase -{ -public: - static CComPara* CreateInstance(UINT nPort); - -protected: - CComPara(); - virtual ~CComPara(); - virtual UINT Read(UINT8* pData); - virtual UINT Write(UINT8 cData); - virtual UINT8 GetStat(); - virtual INTPTR Message(UINT nMessage, INTPTR nParam); - -private: - HANDLE m_hParallel; /*!< パラレル ハンドル */ - - bool Initialize(UINT nPort); -}; +/** + * @file cmpara.h + * @brief パラレル クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "cmbase.h" + +/** + * @brief commng パラレル デバイス クラス + */ +class CComPara : public CComBase +{ +public: + static CComPara* CreateInstance(UINT nPort); + +protected: + CComPara(); + virtual ~CComPara(); + virtual UINT Read(UINT8* pData); + virtual UINT Write(UINT8 cData); + virtual UINT8 GetStat(); + virtual INTPTR Message(UINT nMessage, INTPTR nParam); + +private: + HANDLE m_hParallel; /*!< パラレル ハンドル */ + + bool Initialize(UINT nPort); +}; diff --git a/windows/commng/cmpipe.cpp b/windows/commng/cmpipe.cpp old mode 100755 new mode 100644 index 6f5746ca..2e00297f --- a/windows/commng/cmpipe.cpp +++ b/windows/commng/cmpipe.cpp @@ -1,313 +1,313 @@ -/** - * @file cmpipe.cpp - * @brief 名前付きパイプ シリアル クラスの動作の定義を行います - */ - -#include -#include "cmpipe.h" -#include - -#if defined(SUPPORT_NAMED_PIPE) - -/** - * インスタンス作成 - * @param[in] nPort ポート番号 - * @param[in] pipename パイプの名前 - * @param[in] servername サーバーの名前 - * @return インスタンス - */ -CComPipe* CComPipe::CreateInstance(LPCSTR pipename, LPCSTR servername) -{ - CComPipe* pSerial = new CComPipe; - if (!pSerial->Initialize(pipename, servername)) - { - delete pSerial; - pSerial = NULL; - } - return pSerial; -} - -/** - * コンストラクタ - */ -CComPipe::CComPipe() - : CComBase(COMCONNECT_SERIAL) - , m_hSerial(INVALID_HANDLE_VALUE) - , m_isserver(false) - , m_lastdata(0) - , m_lastdatafail(0) -{ -} - -/** - * デストラクタ - */ -CComPipe::~CComPipe() -{ - if (m_hSerial != INVALID_HANDLE_VALUE) - { - if(m_isserver){ - DisconnectNamedPipe(m_hSerial); - } - ::CloseHandle(m_hSerial); - m_hSerial = INVALID_HANDLE_VALUE; - } -} - -/** - * 初期化 - * @param[in] nPort ポート番号 - * @param[in] pipename パイプの名前 - * @param[in] servername サーバーの名前 - * @retval true 成功 - * @retval false 失敗 - */ -bool CComPipe::Initialize(LPCSTR pipename, LPCSTR servername) -{ - wchar_t wpipename[MAX_PATH]; - wchar_t wservername[MAX_PATH]; - wchar_t wName[MAX_PATH]; - if(pipename==NULL){ - // No pipe name - return false; - } - codecnv_utf8toucs2((UINT16*)wpipename, MAX_PATH, pipename, -1); - if(wcslen(wpipename) == 0){ - // No pipe name - return false; - } - codecnv_utf8toucs2((UINT16*)wservername, MAX_PATH, servername!=NULL ? servername : "", -1); - if(wcslen(wpipename) + wcslen(wservername) > MAX_PATH - 16){ - // too long pipe name - return false; - } - if(wcschr(wpipename, '\\') != NULL || wcschr(wservername, '\\') != NULL){ - // cannot use \ in pipe name - return false; - } - if(wservername && wcslen(wservername)!=0){ - swprintf(wName, MAX_PATH, L"\\\\%ls\\pipe\\%ls", wservername, wpipename); - }else{ - swprintf(wName, MAX_PATH, L"\\\\.\\pipe\\%ls", wpipename); - } - - if(m_hSerial != INVALID_HANDLE_VALUE){ - if(m_isserver){ - DisconnectNamedPipe(m_hSerial); - } - ::CloseHandle(m_hSerial); - m_hSerial = INVALID_HANDLE_VALUE; - } - - // クライアント接続をトライ - m_hSerial = CreateFileW(wName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (m_hSerial == INVALID_HANDLE_VALUE) { - // サーバーで再トライ - m_hSerial = CreateNamedPipeW(wName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_NOWAIT, 1, 1024, 1024, 500, NULL); - if (m_hSerial == INVALID_HANDLE_VALUE) { - return false; - } - m_isserver = true; - //ConnectNamedPipe(m_hSerial, NULL); // With a nonblocking-wait handle, the connect operation returns zero immediately, and the GetLastError function returns ERROR_PIPE_LISTENING. とのことなので常時0 - } - - _tcscpy(m_pipename, pipename); - _tcscpy(m_pipeserv, servername); - - return true; -} - -/** - * 読み込み - * @param[out] pData バッファ - * @return サイズ - */ -UINT CComPipe::Read(UINT8* pData) -{ - DWORD dwReadSize; - if (m_hSerial == INVALID_HANDLE_VALUE) { - return 0; - } - if (PeekNamedPipe(m_hSerial, NULL, 0, NULL, &dwReadSize, NULL)){ - if(dwReadSize > 0){ - if (::ReadFile(m_hSerial, pData, 1, &dwReadSize, NULL)) - { - return 1; - } - } - }else{ - DWORD err = GetLastError(); - if(m_isserver){ - if(err==ERROR_BROKEN_PIPE){ - DisconnectNamedPipe(m_hSerial); - ConnectNamedPipe(m_hSerial, NULL); - } - }else{ - if(err==ERROR_PIPE_NOT_CONNECTED){ - Initialize(m_pipename, m_pipeserv); - } - } - } - return 0; -} - -/** - * 書き込み - * @param[out] cData データ - * @return サイズ - */ -UINT CComPipe::Write(UINT8 cData) -{ - UINT ret; - DWORD dwWrittenSize; - if (m_hSerial == INVALID_HANDLE_VALUE) { - m_lastdatafail = 1; - return 0; - } - ret = (::WriteFile(m_hSerial, &cData, 1, &dwWrittenSize, NULL)) ? 1 : 0; - if(dwWrittenSize==0) { - DWORD err = GetLastError(); - if(m_isserver){ - if(err==ERROR_BROKEN_PIPE){ - return 0; - } - }else{ - if(err==ERROR_PIPE_NOT_CONNECTED){ - return 0; - } - } - if(m_lastdatafail && GetTickCount() - m_lastdatatime > 1000){ - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - return 1; // バッファデータが減りそうにないならあきらめる(毎秒1byte(8bit)は流石にあり得ない) - } - m_lastdatafail = 1; - m_lastdata = cData; - m_lastdatatime = GetTickCount(); - return 0; - }else{ - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - } - return ret; -} - -/** - * 書き込みリトライ - * @return サイズ - */ -UINT CComPipe::WriteRetry() -{ - UINT ret; - DWORD dwWrittenSize; - if(m_lastdatafail){ - if (m_hSerial == INVALID_HANDLE_VALUE) { - return 0; - } - ret = (::WriteFile(m_hSerial, &m_lastdata, 1, &dwWrittenSize, NULL)) ? 1 : 0; - if(dwWrittenSize==0) { - DWORD err = GetLastError(); - if(m_isserver){ - if(err==ERROR_BROKEN_PIPE){ - return 1; // 常時成功扱い - } - }else{ - if(err==ERROR_PIPE_NOT_CONNECTED){ - return 1; // 常時成功扱い - } - } - if(m_lastdatafail && GetTickCount() - m_lastdatatime > 1000){ - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - return 1; // バッファデータが減りそうにないならあきらめる(毎秒1byte(8bit)は流石にあり得ない) - } - return 0; - } - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - return ret; - } - return 1; -} - -/** - * 最後の書き込みが成功しているかチェック - * @return サイズ - */ -UINT CComPipe::LastWriteSuccess() -{ - if(m_lastdatafail && GetTickCount() - m_lastdatatime > 3000){ - return 1; // 3秒間バッファデータが減りそうにないならあきらめる - } - if(m_lastdatafail){ - return 0; - } - return 1; -} - -/** - * ステータスを得る - * bit 7: ‾CI (RI, RING) - * bit 6: ‾CS (CTS) - * bit 5: ‾CD (DCD, RLSD) - * bit 4: reserved - * bit 3: reserved - * bit 2: reserved - * bit 1: reserved - * bit 0: ‾DSR (DR) - * @return ステータス - */ -UINT8 CComPipe::GetStat() -{ - UINT8 ret = 0xa0; - DWORD dwReadSize; - if (m_hSerial == INVALID_HANDLE_VALUE) { - ret = 0xe1; - }else if (!PeekNamedPipe(m_hSerial, NULL, 0, NULL, &dwReadSize, NULL)){ - DWORD err = GetLastError(); - if(err==ERROR_BAD_PIPE){ - ret = 0xe1; - }else{ - if(m_isserver){ - if(err==ERROR_BROKEN_PIPE){ - ret = 0xe1; - } - }else{ - if(err==ERROR_PIPE_NOT_CONNECTED){ - ret = 0xe1; - } - } - } - } - return ret; -} - -/** - * メッセージ - * @param[in] nMessage メッセージ - * @param[in] nParam パラメタ - * @return リザルト コード - */ -INTPTR CComPipe::Message(UINT nMessage, INTPTR nParam) -{ - switch (nMessage) - { - case COMMSG_PURGE: - { - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - } - break; - - default: - break; - } - return 0; -} - -#endif +/** + * @file cmpipe.cpp + * @brief 名前付きパイプ シリアル クラスの動作の定義を行います + */ + +#include +#include "cmpipe.h" +#include + +#if defined(SUPPORT_NAMED_PIPE) + +/** + * インスタンス作成 + * @param[in] nPort ポート番号 + * @param[in] pipename パイプの名前 + * @param[in] servername サーバーの名前 + * @return インスタンス + */ +CComPipe* CComPipe::CreateInstance(LPCSTR pipename, LPCSTR servername) +{ + CComPipe* pSerial = new CComPipe; + if (!pSerial->Initialize(pipename, servername)) + { + delete pSerial; + pSerial = NULL; + } + return pSerial; +} + +/** + * コンストラクタ + */ +CComPipe::CComPipe() + : CComBase(COMCONNECT_SERIAL) + , m_hSerial(INVALID_HANDLE_VALUE) + , m_isserver(false) + , m_lastdata(0) + , m_lastdatafail(0) +{ +} + +/** + * デストラクタ + */ +CComPipe::~CComPipe() +{ + if (m_hSerial != INVALID_HANDLE_VALUE) + { + if(m_isserver){ + DisconnectNamedPipe(m_hSerial); + } + ::CloseHandle(m_hSerial); + m_hSerial = INVALID_HANDLE_VALUE; + } +} + +/** + * 初期化 + * @param[in] nPort ポート番号 + * @param[in] pipename パイプの名前 + * @param[in] servername サーバーの名前 + * @retval true 成功 + * @retval false 失敗 + */ +bool CComPipe::Initialize(LPCSTR pipename, LPCSTR servername) +{ + wchar_t wpipename[MAX_PATH]; + wchar_t wservername[MAX_PATH]; + wchar_t wName[MAX_PATH]; + if(pipename==NULL){ + // No pipe name + return false; + } + codecnv_utf8toucs2((UINT16*)wpipename, MAX_PATH, pipename, -1); + if(wcslen(wpipename) == 0){ + // No pipe name + return false; + } + codecnv_utf8toucs2((UINT16*)wservername, MAX_PATH, servername!=NULL ? servername : "", -1); + if(wcslen(wpipename) + wcslen(wservername) > MAX_PATH - 16){ + // too long pipe name + return false; + } + if(wcschr(wpipename, '\\') != NULL || wcschr(wservername, '\\') != NULL){ + // cannot use \ in pipe name + return false; + } + if(wservername && wcslen(wservername)!=0){ + swprintf(wName, MAX_PATH, L"\\\\%ls\\pipe\\%ls", wservername, wpipename); + }else{ + swprintf(wName, MAX_PATH, L"\\\\.\\pipe\\%ls", wpipename); + } + + if(m_hSerial != INVALID_HANDLE_VALUE){ + if(m_isserver){ + DisconnectNamedPipe(m_hSerial); + } + ::CloseHandle(m_hSerial); + m_hSerial = INVALID_HANDLE_VALUE; + } + + // クライアント接続をトライ + m_hSerial = CreateFileW(wName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (m_hSerial == INVALID_HANDLE_VALUE) { + // サーバーで再トライ + m_hSerial = CreateNamedPipeW(wName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE|PIPE_NOWAIT, 1, 1024, 1024, 500, NULL); + if (m_hSerial == INVALID_HANDLE_VALUE) { + return false; + } + m_isserver = true; + //ConnectNamedPipe(m_hSerial, NULL); // With a nonblocking-wait handle, the connect operation returns zero immediately, and the GetLastError function returns ERROR_PIPE_LISTENING. とのことなので常時0 + } + + _tcscpy(m_pipename, pipename); + _tcscpy(m_pipeserv, servername); + + return true; +} + +/** + * 読み込み + * @param[out] pData バッファ + * @return サイズ + */ +UINT CComPipe::Read(UINT8* pData) +{ + DWORD dwReadSize; + if (m_hSerial == INVALID_HANDLE_VALUE) { + return 0; + } + if (PeekNamedPipe(m_hSerial, NULL, 0, NULL, &dwReadSize, NULL)){ + if(dwReadSize > 0){ + if (::ReadFile(m_hSerial, pData, 1, &dwReadSize, NULL)) + { + return 1; + } + } + }else{ + DWORD err = GetLastError(); + if(m_isserver){ + if(err==ERROR_BROKEN_PIPE){ + DisconnectNamedPipe(m_hSerial); + ConnectNamedPipe(m_hSerial, NULL); + } + }else{ + if(err==ERROR_PIPE_NOT_CONNECTED){ + Initialize(m_pipename, m_pipeserv); + } + } + } + return 0; +} + +/** + * 書き込み + * @param[out] cData データ + * @return サイズ + */ +UINT CComPipe::Write(UINT8 cData) +{ + UINT ret; + DWORD dwWrittenSize; + if (m_hSerial == INVALID_HANDLE_VALUE) { + m_lastdatafail = 1; + return 0; + } + ret = (::WriteFile(m_hSerial, &cData, 1, &dwWrittenSize, NULL)) ? 1 : 0; + if(dwWrittenSize==0) { + DWORD err = GetLastError(); + if(m_isserver){ + if(err==ERROR_BROKEN_PIPE){ + return 0; + } + }else{ + if(err==ERROR_PIPE_NOT_CONNECTED){ + return 0; + } + } + if(m_lastdatafail && GetTickCount() - m_lastdatatime > 1000){ + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + return 1; // バッファデータが減りそうにないならあきらめる(毎秒1byte(8bit)は流石にあり得ない) + } + m_lastdatafail = 1; + m_lastdata = cData; + m_lastdatatime = GetTickCount(); + return 0; + }else{ + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + } + return ret; +} + +/** + * 書き込みリトライ + * @return サイズ + */ +UINT CComPipe::WriteRetry() +{ + UINT ret; + DWORD dwWrittenSize; + if(m_lastdatafail){ + if (m_hSerial == INVALID_HANDLE_VALUE) { + return 0; + } + ret = (::WriteFile(m_hSerial, &m_lastdata, 1, &dwWrittenSize, NULL)) ? 1 : 0; + if(dwWrittenSize==0) { + DWORD err = GetLastError(); + if(m_isserver){ + if(err==ERROR_BROKEN_PIPE){ + return 1; // 常時成功扱い + } + }else{ + if(err==ERROR_PIPE_NOT_CONNECTED){ + return 1; // 常時成功扱い + } + } + if(m_lastdatafail && GetTickCount() - m_lastdatatime > 1000){ + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + return 1; // バッファデータが減りそうにないならあきらめる(毎秒1byte(8bit)は流石にあり得ない) + } + return 0; + } + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + return ret; + } + return 1; +} + +/** + * 最後の書き込みが成功しているかチェック + * @return サイズ + */ +UINT CComPipe::LastWriteSuccess() +{ + if(m_lastdatafail && GetTickCount() - m_lastdatatime > 3000){ + return 1; // 3秒間バッファデータが減りそうにないならあきらめる + } + if(m_lastdatafail){ + return 0; + } + return 1; +} + +/** + * ステータスを得る + * bit 7: ‾CI (RI, RING) + * bit 6: ‾CS (CTS) + * bit 5: ‾CD (DCD, RLSD) + * bit 4: reserved + * bit 3: reserved + * bit 2: reserved + * bit 1: reserved + * bit 0: ‾DSR (DR) + * @return ステータス + */ +UINT8 CComPipe::GetStat() +{ + UINT8 ret = 0xa0; + DWORD dwReadSize; + if (m_hSerial == INVALID_HANDLE_VALUE) { + ret = 0xe1; + }else if (!PeekNamedPipe(m_hSerial, NULL, 0, NULL, &dwReadSize, NULL)){ + DWORD err = GetLastError(); + if(err==ERROR_BAD_PIPE){ + ret = 0xe1; + }else{ + if(m_isserver){ + if(err==ERROR_BROKEN_PIPE){ + ret = 0xe1; + } + }else{ + if(err==ERROR_PIPE_NOT_CONNECTED){ + ret = 0xe1; + } + } + } + } + return ret; +} + +/** + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParam パラメタ + * @return リザルト コード + */ +INTPTR CComPipe::Message(UINT nMessage, INTPTR nParam) +{ + switch (nMessage) + { + case COMMSG_PURGE: + { + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + } + break; + + default: + break; + } + return 0; +} + +#endif diff --git a/windows/commng/cmpipe.h b/windows/commng/cmpipe.h index 34e21ff6..7d8e1cc5 100644 --- a/windows/commng/cmpipe.h +++ b/windows/commng/cmpipe.h @@ -1,42 +1,42 @@ -/** - * @file cmpipe.h - * @brief OtpCv VA NX̐錾уC^[tFCX̒`܂ - */ - -#pragma once - -#include "cmbase.h" - -#if defined(SUPPORT_NAMED_PIPE) - -/** - * @brief commng VA foCX NX - */ -class CComPipe : public CComBase -{ -public: - static CComPipe* CreateInstance(LPCSTR pipename, LPCSTR servername); - -protected: - CComPipe(); - virtual ~CComPipe(); - virtual UINT Read(UINT8* pData); - virtual UINT Write(UINT8 cData); - virtual UINT WriteRetry(); // ݑȂĂď݂ - virtual UINT LastWriteSuccess(); // Ō݂̏Ă邩`FbN - virtual UINT8 GetStat(); - virtual INTPTR Message(UINT nMessage, INTPTR nParam); - -private: - HANDLE m_hSerial; /*!< OtpCv nh */ - bool m_isserver; /*!< T[o[ǂ */ - OEMCHAR m_pipename[MAX_PATH]; // The name of the named-pipe - OEMCHAR m_pipeserv[MAX_PATH]; // The server name of the named-pipe - UINT8 m_lastdata; // Ōɑ낤Ƃf[^ - UINT8 m_lastdatafail; // f[^𑗂̂ɎsĂ0ȊO - DWORD m_lastdatatime; // f[^𑗂̂Ɏsԁi܂ɂs悤Ȃ疳j - - bool Initialize(LPCSTR pipename, LPCSTR servername); -}; - -#endif +/** + * @file cmpipe.h + * @brief 名前付きパイプ シリアル クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "cmbase.h" + +#if defined(SUPPORT_NAMED_PIPE) + +/** + * @brief commng シリアル デバイス クラス + */ +class CComPipe : public CComBase +{ +public: + static CComPipe* CreateInstance(LPCSTR pipename, LPCSTR servername); + +protected: + CComPipe(); + virtual ~CComPipe(); + virtual UINT Read(UINT8* pData); + virtual UINT Write(UINT8 cData); + virtual UINT WriteRetry(); // 書き込み損なっていたら再書き込みする + virtual UINT LastWriteSuccess(); // 最後の書き込みが成功しているかチェック + virtual UINT8 GetStat(); + virtual INTPTR Message(UINT nMessage, INTPTR nParam); + +private: + HANDLE m_hSerial; /*!< 名前付きパイプ ハンドル */ + bool m_isserver; /*!< サーバーかどうか */ + OEMCHAR m_pipename[MAX_PATH]; // The name of the named-pipe + OEMCHAR m_pipeserv[MAX_PATH]; // The server name of the named-pipe + UINT8 m_lastdata; // 最後に送ろうとしたデータ + UINT8 m_lastdatafail; // データを送るのに失敗していたら0以外 + DWORD m_lastdatatime; // データを送るのに失敗した時間(あまりにも失敗し続けるようなら無視する) + + bool Initialize(LPCSTR pipename, LPCSTR servername); +}; + +#endif diff --git a/windows/commng/cmserial.cpp b/windows/commng/cmserial.cpp index 47fb5d45..dd877343 100644 --- a/windows/commng/cmserial.cpp +++ b/windows/commng/cmserial.cpp @@ -1,719 +1,719 @@ -/** - * @file cmserial.cpp - * @brief シリアル クラスの動作の定義を行います - */ - -#include -#include "cmserial.h" - -/** - * インスタンス作成 - * @param[in] nPort ポート番号 - * @param[in] cParam パラメタ - * @param[in] nSpeed スピード - * @return インスタンス - */ -CComSerial* CComSerial::CreateInstance(UINT nPort, UINT8 cParam, UINT32 nSpeed, UINT8 fixedspeed, UINT8 DSRcheck) -{ - CComSerial* pSerial = new CComSerial; - if (!pSerial->Initialize(nPort, cParam, nSpeed, fixedspeed, DSRcheck)) - { - delete pSerial; - pSerial = NULL; - } - return pSerial; -} - -/** - * コンストラクタ - */ -CComSerial::CComSerial() - : CComBase(COMCONNECT_SERIAL) - , m_readovl() - , m_readovl_pending(false) - , m_readovl_buf(0) - , m_blocktransfer(false) - , m_blockbuffer_pos(0) - , m_blockbuffer_size(0) - , m_fixedspeed(0) - , m_lastdata(0) - , m_lastdatafail(0) - , m_lastdatatime(0) - , m_errorstat(0) -{ - HANDLE hEvent; - - // Write OVERLAPPED作成 - for(int i=0;i= nSpeed) - { - dcb.BaudRate = cmserial_speed[i]; - break; - } - } - dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTR ON - dcb.fRtsControl = RTS_CONTROL_ENABLE; // RTS ON - dcb.ByteSize = (UINT8)(((cParam >> 2) & 3) + 5); - switch (cParam & 0x30) - { - case 0x10: - dcb.Parity = ODDPARITY; - break; - - case 0x30: - dcb.Parity = EVENPARITY; - break; - - default: - dcb.Parity = NOPARITY; - break; - } - switch (cParam & 0xc0) - { - case 0x80: - dcb.StopBits = ONE5STOPBITS; - break; - - case 0xc0: - dcb.StopBits = TWOSTOPBITS; - break; - - default: - dcb.StopBits = ONESTOPBIT; - break; - } - dcb.fOutX = FALSE; - dcb.fInX = FALSE; - dcb.fOutxCtsFlow = FALSE; - dcb.fOutxDsrFlow = FALSE; - dcb.fDsrSensitivity = (DSRcheck ? TRUE : FALSE); // TRUEにするとDSRビットが立っていないときの受信データを無視する - ::SetCommState(m_hSerial, &dcb); - - // タイムアウト設定(非同期待ちするので要らない気もする) - COMMTIMEOUTS tmo; - tmo.ReadIntervalTimeout = 20; - tmo.ReadTotalTimeoutConstant = 10; - tmo.ReadTotalTimeoutMultiplier = 100; - tmo.WriteTotalTimeoutConstant = 10; - tmo.WriteTotalTimeoutMultiplier = 100; - ::SetCommTimeouts(m_hSerial, &tmo); - - return true; -} - -/** - * エラー状態を設定 (bit0: パリティ, bit1: オーバーラン, bit2: フレーミング, bit3: ブレーク信号) - * @param[in] errorcode ClearCommErrorエラーコード - */ -void CComSerial::CheckCommError(DWORD errorcode) -{ - if(errorcode & CE_RXPARITY){ - m_errorstat |= 0x1; - } - if(errorcode & CE_RXOVER){ - m_errorstat |= 0x2; - } - if(errorcode & CE_FRAME){ - m_errorstat |= 0x4; - } - if(errorcode & CE_BREAK){ - m_errorstat |= 0x8; - } -} - -/** - * 読み込み - * @param[out] pData バッファ - * @return サイズ - */ -UINT CComSerial::Read(UINT8* pData) -{ - DWORD err; - COMSTAT ct; - ::ClearCommError(m_hSerial, &err, &ct); - CheckCommError(err); - if(m_readovl_pending){ - // 非同期I/O待ちの場合 - DWORD cbNumberOfBytesTransferred = 0; - if(GetOverlappedResult(m_hSerial, &m_readovl, &cbNumberOfBytesTransferred, FALSE)){ - *pData = m_readovl_buf; - m_readovl_pending = false; - return 1; - } - }else{ - if (ct.cbInQue) - { - DWORD dwReadSize; - if (::ReadFile(m_hSerial, &m_readovl_buf, 1, &dwReadSize, &m_readovl)) - { - *pData = m_readovl_buf; - return 1; - }else{ - // 非同期I/O待ち開始 バッファにデータが来るまでReadFileしないので基本的にここには来ない - DWORD lastError = GetLastError(); - if(lastError==ERROR_IO_PENDING){ - m_readovl_pending = true; - } - } - } - } - return 0; -} - -/** - * 書き込み - * @param[out] cData データ - * @return サイズ - */ -UINT CComSerial::Write(UINT8 cData) -{ - DWORD dwWrittenSize; - if (m_hSerial == INVALID_HANDLE_VALUE) { - m_lastdatafail = 1; - return 0; - } - int emptycount = 0; - int idx = -1; - for(int i=0;i 3000) { - // 3秒間バッファデータが減りそうにないならあきらめる - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - return 1; - } - return 0; - } - if(m_blocktransfer){ - // ブロック単位書き込み - if(m_blockbuffer_pos == m_blockbuffer_size){ - if(::WriteFile(m_hSerial, m_blockbuffer, m_blockbuffer_size, &dwWrittenSize, &m_writeovl[idx])){ - // 書き込めた場合 - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - m_blockbuffer_pos = 0; - return 1; - }else{ - // 非同期I/O待ち開始 - DWORD lastError = GetLastError(); - if(lastError==ERROR_IO_PENDING){ - m_writeovl_pending[idx] = true; - } - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - m_blockbuffer_pos = 0; - return 1; - } - }else{ - // 基本的にはここには来ないはず - m_blockbuffer[m_blockbuffer_pos] = m_lastdata; - m_blockbuffer_pos++; - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - } - return 1; - }else{ - // 1byte書き込み - if(::WriteFile(m_hSerial, &m_lastdata, 1, &dwWrittenSize, &m_writeovl[idx])){ - // 書き込めた場合 - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - return 1; - }else{ - // 非同期I/O待ち開始 - DWORD lastError = GetLastError(); - if(lastError==ERROR_IO_PENDING){ - m_writeovl_pending[idx] = true; - } - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - return 1; - } - } -} - -/** - * ブロック単位転送開始 - */ -void CComSerial::BeginBlockTransfer() -{ - if(!m_blocktransfer){ - DCB dcb; - ::GetCommState(m_hSerial, &dcb); - if(dcb.BaudRate >= 115200){ - m_blockbuffer_size = 64; - }else if(dcb.BaudRate >= 57600){ - m_blockbuffer_size = 32; - }else if(dcb.BaudRate >= 19200){ - m_blockbuffer_size = 16; - }else if(dcb.BaudRate >= 9600){ - m_blockbuffer_size = 8; - }else if(dcb.BaudRate >= 4800){ - m_blockbuffer_size = 4; - }else if(dcb.BaudRate >= 2400){ - m_blockbuffer_size = 2; - }else{ - return; // ブロック転送しない - } - m_blockbuffer_pos = 0; - if(!LastWriteSuccess()){ - m_blockbuffer[0] = m_lastdata; - m_blockbuffer_pos++; - m_lastdatafail = 0; - m_lastdata = 0; - m_lastdatatime = 0; - } - m_blocktransfer = true; - } -} -/** - * ブロック単位転送終了 - */ -void CComSerial::EndBlockTransfer() -{ - if(m_blocktransfer){ - DWORD dwWrittenSize; - if(m_blockbuffer_pos > 0){ - int emptycount = 0; - int idx = -1; - for(int i=0;i 3000){ - return 1; // 3秒間バッファデータが減りそうにないならあきらめる - } - if(m_lastdatafail){ - return 0; - } - return 1; -} - -/** - * ステータスを得る - * bit 7: ~CI (RI, RING) - * bit 6: ~CS (CTS) - * bit 5: ~CD (DCD, RLSD) - * bit 4: reserved - * bit 3: reserved - * bit 2: reserved - * bit 1: reserved - * bit 0: ~DSR (DR) - * @return ステータス - */ -UINT8 CComSerial::GetStat() -{ - UINT8 ret = 0; - DWORD modemStat; - if (m_hSerial == INVALID_HANDLE_VALUE) - { - return 0xf1; - } - if(::GetCommModemStatus(m_hSerial, &modemStat)){ - if(!(modemStat & MS_DSR_ON)){ - ret |= 0x01; - } - if(!(modemStat & MS_CTS_ON)){ - ret |= 0x40; - } - if(!(modemStat & MS_RING_ON)){ - ret |= 0x80; - } - if(!(modemStat & MS_RLSD_ON)){ - ret |= 0x20; - } - return ret; - }else{ - DWORD err; - COMSTAT ct; - ::ClearCommError(m_hSerial, &err, &ct); - CheckCommError(err); - if (ct.fDsrHold) - { - ret |= 0x01; - } - if (ct.fCtsHold) - { - ret |= 0x40; - } - if (ct.fRlsdHold) - { - ret |= 0x20; - } - return ret; - } -} - -/** - * メッセージ - * @param[in] nMessage メッセージ - * @param[in] nParam パラメタ - * @return リザルト コード - */ -INTPTR CComSerial::Message(UINT nMessage, INTPTR nParam) -{ - if (m_hSerial == INVALID_HANDLE_VALUE) - { - return 0; - } - switch (nMessage) - { - case COMMSG_CHANGESPEED: // 通信速度変更 - if(!m_fixedspeed){ - int newspeed = *(reinterpret_cast(nParam)); - for (UINT i = 0; i < NELEMENTS(cmserial_speed); i++) - { - if (cmserial_speed[i] >= newspeed) - { - DCB dcb; - ::GetCommState(m_hSerial, &dcb); - if(cmserial_speed[i] != dcb.BaudRate){ - dcb.BaudRate = cmserial_speed[i]; - ::SetCommState(m_hSerial, &dcb); - } - break; - } - } - } - break; - - case COMMSG_CHANGEMODE: // 通信モード変更 - if(!m_fixedspeed){ - bool changed = false; - UINT8 newmode = *(reinterpret_cast(nParam)); // I/O 32h モードセットのデータ - BYTE stopbits_value[] = {ONESTOPBIT, ONESTOPBIT, ONE5STOPBITS, TWOSTOPBITS}; - BYTE parity_value[] = {NOPARITY, ODDPARITY, NOPARITY, EVENPARITY}; - BYTE bytesize_value[] = {5, 6, 7, 8}; - DCB dcb; - ::GetCommState(m_hSerial, &dcb); - if(dcb.StopBits != stopbits_value[(newmode >> 6) & 0x3]){ - dcb.StopBits = stopbits_value[(newmode >> 6) & 0x3]; - changed = true; - } - if(dcb.Parity != parity_value[(newmode >> 4) & 0x3]){ - dcb.Parity = parity_value[(newmode >> 4) & 0x3]; - changed = true; - } - if(dcb.ByteSize != bytesize_value[(newmode >> 2) & 0x3]){ - dcb.ByteSize = bytesize_value[(newmode >> 2) & 0x3]; - changed = true; - } - if(changed){ - ::PurgeComm(m_hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); - ::SetCommState(m_hSerial, &dcb); - } - } - break; - - case COMMSG_SETCOMMAND: // RTSとDTRフラグのセット - { - UINT8 cmd = *(reinterpret_cast(nParam)); // I/O 32h コマンドセットのデータ - ::PurgeComm(m_hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); - if(cmd & 0x20){ // RTS - ::EscapeCommFunction(m_hSerial, SETRTS); - }else{ - ::EscapeCommFunction(m_hSerial, CLRRTS); - } - if(cmd & 0x02){ // DTR - ::EscapeCommFunction(m_hSerial, SETDTR); - }else{ - ::EscapeCommFunction(m_hSerial, CLRDTR); - } - } - break; - - case COMMSG_PURGE: // バッファデータ破棄 - { - ::PurgeComm(m_hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); - } - break; - - - case COMMSG_SETFLAG: - { - COMFLAG flag = reinterpret_cast(nParam); - if ((flag) && (flag->size == sizeof(_COMFLAG))) - { - return 1; - } - } - break; - - case COMMSG_GETFLAG: - { - // dummy data - COMFLAG flag = (COMFLAG)_MALLOC(sizeof(_COMFLAG), "RS232C FLAG"); - if (flag) - { - flag->size = sizeof(_COMFLAG); - flag->sig = COMSIG_COM1; - flag->ver = 0; - flag->param = 0; - return reinterpret_cast(flag); - } - } - break; - - case COMMSG_GETERROR: // 通信エラー取得 - { - // エラー状態 (bit0: パリティ, bit1: オーバーラン, bit2: フレーミング, bit3: ブレーク信号) - UINT8 *errflag = (reinterpret_cast(nParam)); // I/O 32h コマンドセットのデータ - if(errflag){ - *errflag = m_errorstat; - } - } - break; - - case COMMSG_CLRERROR: // 通信エラークリア - { - m_errorstat = 0; - } - break; - - default: - break; - } - return 0; -} - +/** + * @file cmserial.cpp + * @brief シリアル クラスの動作の定義を行います + */ + +#include +#include "cmserial.h" + +/** + * インスタンス作成 + * @param[in] nPort ポート番号 + * @param[in] cParam パラメタ + * @param[in] nSpeed スピード + * @return インスタンス + */ +CComSerial* CComSerial::CreateInstance(UINT nPort, UINT8 cParam, UINT32 nSpeed, UINT8 fixedspeed, UINT8 DSRcheck) +{ + CComSerial* pSerial = new CComSerial; + if (!pSerial->Initialize(nPort, cParam, nSpeed, fixedspeed, DSRcheck)) + { + delete pSerial; + pSerial = NULL; + } + return pSerial; +} + +/** + * コンストラクタ + */ +CComSerial::CComSerial() + : CComBase(COMCONNECT_SERIAL) + , m_readovl() + , m_readovl_pending(false) + , m_readovl_buf(0) + , m_blocktransfer(false) + , m_blockbuffer_pos(0) + , m_blockbuffer_size(0) + , m_fixedspeed(0) + , m_lastdata(0) + , m_lastdatafail(0) + , m_lastdatatime(0) + , m_errorstat(0) +{ + HANDLE hEvent; + + // Write OVERLAPPED作成 + for(int i=0;i= nSpeed) + { + dcb.BaudRate = cmserial_speed[i]; + break; + } + } + dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTR ON + dcb.fRtsControl = RTS_CONTROL_ENABLE; // RTS ON + dcb.ByteSize = (UINT8)(((cParam >> 2) & 3) + 5); + switch (cParam & 0x30) + { + case 0x10: + dcb.Parity = ODDPARITY; + break; + + case 0x30: + dcb.Parity = EVENPARITY; + break; + + default: + dcb.Parity = NOPARITY; + break; + } + switch (cParam & 0xc0) + { + case 0x80: + dcb.StopBits = ONE5STOPBITS; + break; + + case 0xc0: + dcb.StopBits = TWOSTOPBITS; + break; + + default: + dcb.StopBits = ONESTOPBIT; + break; + } + dcb.fOutX = FALSE; + dcb.fInX = FALSE; + dcb.fOutxCtsFlow = FALSE; + dcb.fOutxDsrFlow = FALSE; + dcb.fDsrSensitivity = (DSRcheck ? TRUE : FALSE); // TRUEにするとDSRビットが立っていないときの受信データを無視する + ::SetCommState(m_hSerial, &dcb); + + // タイムアウト設定(非同期待ちするので要らない気もする) + COMMTIMEOUTS tmo; + tmo.ReadIntervalTimeout = 20; + tmo.ReadTotalTimeoutConstant = 10; + tmo.ReadTotalTimeoutMultiplier = 100; + tmo.WriteTotalTimeoutConstant = 10; + tmo.WriteTotalTimeoutMultiplier = 100; + ::SetCommTimeouts(m_hSerial, &tmo); + + return true; +} + +/** + * エラー状態を設定 (bit0: パリティ, bit1: オーバーラン, bit2: フレーミング, bit3: ブレーク信号) + * @param[in] errorcode ClearCommErrorエラーコード + */ +void CComSerial::CheckCommError(DWORD errorcode) +{ + if(errorcode & CE_RXPARITY){ + m_errorstat |= 0x1; + } + if(errorcode & CE_RXOVER){ + m_errorstat |= 0x2; + } + if(errorcode & CE_FRAME){ + m_errorstat |= 0x4; + } + if(errorcode & CE_BREAK){ + m_errorstat |= 0x8; + } +} + +/** + * 読み込み + * @param[out] pData バッファ + * @return サイズ + */ +UINT CComSerial::Read(UINT8* pData) +{ + DWORD err; + COMSTAT ct; + ::ClearCommError(m_hSerial, &err, &ct); + CheckCommError(err); + if(m_readovl_pending){ + // 非同期I/O待ちの場合 + DWORD cbNumberOfBytesTransferred = 0; + if(GetOverlappedResult(m_hSerial, &m_readovl, &cbNumberOfBytesTransferred, FALSE)){ + *pData = m_readovl_buf; + m_readovl_pending = false; + return 1; + } + }else{ + if (ct.cbInQue) + { + DWORD dwReadSize; + if (::ReadFile(m_hSerial, &m_readovl_buf, 1, &dwReadSize, &m_readovl)) + { + *pData = m_readovl_buf; + return 1; + }else{ + // 非同期I/O待ち開始 バッファにデータが来るまでReadFileしないので基本的にここには来ない + DWORD lastError = GetLastError(); + if(lastError==ERROR_IO_PENDING){ + m_readovl_pending = true; + } + } + } + } + return 0; +} + +/** + * 書き込み + * @param[out] cData データ + * @return サイズ + */ +UINT CComSerial::Write(UINT8 cData) +{ + DWORD dwWrittenSize; + if (m_hSerial == INVALID_HANDLE_VALUE) { + m_lastdatafail = 1; + return 0; + } + int emptycount = 0; + int idx = -1; + for(int i=0;i 3000) { + // 3秒間バッファデータが減りそうにないならあきらめる + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + return 1; + } + return 0; + } + if(m_blocktransfer){ + // ブロック単位書き込み + if(m_blockbuffer_pos == m_blockbuffer_size){ + if(::WriteFile(m_hSerial, m_blockbuffer, m_blockbuffer_size, &dwWrittenSize, &m_writeovl[idx])){ + // 書き込めた場合 + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + m_blockbuffer_pos = 0; + return 1; + }else{ + // 非同期I/O待ち開始 + DWORD lastError = GetLastError(); + if(lastError==ERROR_IO_PENDING){ + m_writeovl_pending[idx] = true; + } + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + m_blockbuffer_pos = 0; + return 1; + } + }else{ + // 基本的にはここには来ないはず + m_blockbuffer[m_blockbuffer_pos] = m_lastdata; + m_blockbuffer_pos++; + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + } + return 1; + }else{ + // 1byte書き込み + if(::WriteFile(m_hSerial, &m_lastdata, 1, &dwWrittenSize, &m_writeovl[idx])){ + // 書き込めた場合 + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + return 1; + }else{ + // 非同期I/O待ち開始 + DWORD lastError = GetLastError(); + if(lastError==ERROR_IO_PENDING){ + m_writeovl_pending[idx] = true; + } + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + return 1; + } + } +} + +/** + * ブロック単位転送開始 + */ +void CComSerial::BeginBlockTransfer() +{ + if(!m_blocktransfer){ + DCB dcb; + ::GetCommState(m_hSerial, &dcb); + if(dcb.BaudRate >= 115200){ + m_blockbuffer_size = 64; + }else if(dcb.BaudRate >= 57600){ + m_blockbuffer_size = 32; + }else if(dcb.BaudRate >= 19200){ + m_blockbuffer_size = 16; + }else if(dcb.BaudRate >= 9600){ + m_blockbuffer_size = 8; + }else if(dcb.BaudRate >= 4800){ + m_blockbuffer_size = 4; + }else if(dcb.BaudRate >= 2400){ + m_blockbuffer_size = 2; + }else{ + return; // ブロック転送しない + } + m_blockbuffer_pos = 0; + if(!LastWriteSuccess()){ + m_blockbuffer[0] = m_lastdata; + m_blockbuffer_pos++; + m_lastdatafail = 0; + m_lastdata = 0; + m_lastdatatime = 0; + } + m_blocktransfer = true; + } +} +/** + * ブロック単位転送終了 + */ +void CComSerial::EndBlockTransfer() +{ + if(m_blocktransfer){ + DWORD dwWrittenSize; + if(m_blockbuffer_pos > 0){ + int emptycount = 0; + int idx = -1; + for(int i=0;i 3000){ + return 1; // 3秒間バッファデータが減りそうにないならあきらめる + } + if(m_lastdatafail){ + return 0; + } + return 1; +} + +/** + * ステータスを得る + * bit 7: ~CI (RI, RING) + * bit 6: ~CS (CTS) + * bit 5: ~CD (DCD, RLSD) + * bit 4: reserved + * bit 3: reserved + * bit 2: reserved + * bit 1: reserved + * bit 0: ~DSR (DR) + * @return ステータス + */ +UINT8 CComSerial::GetStat() +{ + UINT8 ret = 0; + DWORD modemStat; + if (m_hSerial == INVALID_HANDLE_VALUE) + { + return 0xf1; + } + if(::GetCommModemStatus(m_hSerial, &modemStat)){ + if(!(modemStat & MS_DSR_ON)){ + ret |= 0x01; + } + if(!(modemStat & MS_CTS_ON)){ + ret |= 0x40; + } + if(!(modemStat & MS_RING_ON)){ + ret |= 0x80; + } + if(!(modemStat & MS_RLSD_ON)){ + ret |= 0x20; + } + return ret; + }else{ + DWORD err; + COMSTAT ct; + ::ClearCommError(m_hSerial, &err, &ct); + CheckCommError(err); + if (ct.fDsrHold) + { + ret |= 0x01; + } + if (ct.fCtsHold) + { + ret |= 0x40; + } + if (ct.fRlsdHold) + { + ret |= 0x20; + } + return ret; + } +} + +/** + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParam パラメタ + * @return リザルト コード + */ +INTPTR CComSerial::Message(UINT nMessage, INTPTR nParam) +{ + if (m_hSerial == INVALID_HANDLE_VALUE) + { + return 0; + } + switch (nMessage) + { + case COMMSG_CHANGESPEED: // 通信速度変更 + if(!m_fixedspeed){ + int newspeed = *(reinterpret_cast(nParam)); + for (UINT i = 0; i < NELEMENTS(cmserial_speed); i++) + { + if (cmserial_speed[i] >= newspeed) + { + DCB dcb; + ::GetCommState(m_hSerial, &dcb); + if(cmserial_speed[i] != dcb.BaudRate){ + dcb.BaudRate = cmserial_speed[i]; + ::SetCommState(m_hSerial, &dcb); + } + break; + } + } + } + break; + + case COMMSG_CHANGEMODE: // 通信モード変更 + if(!m_fixedspeed){ + bool changed = false; + UINT8 newmode = *(reinterpret_cast(nParam)); // I/O 32h モードセットのデータ + BYTE stopbits_value[] = {ONESTOPBIT, ONESTOPBIT, ONE5STOPBITS, TWOSTOPBITS}; + BYTE parity_value[] = {NOPARITY, ODDPARITY, NOPARITY, EVENPARITY}; + BYTE bytesize_value[] = {5, 6, 7, 8}; + DCB dcb; + ::GetCommState(m_hSerial, &dcb); + if(dcb.StopBits != stopbits_value[(newmode >> 6) & 0x3]){ + dcb.StopBits = stopbits_value[(newmode >> 6) & 0x3]; + changed = true; + } + if(dcb.Parity != parity_value[(newmode >> 4) & 0x3]){ + dcb.Parity = parity_value[(newmode >> 4) & 0x3]; + changed = true; + } + if(dcb.ByteSize != bytesize_value[(newmode >> 2) & 0x3]){ + dcb.ByteSize = bytesize_value[(newmode >> 2) & 0x3]; + changed = true; + } + if(changed){ + ::PurgeComm(m_hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); + ::SetCommState(m_hSerial, &dcb); + } + } + break; + + case COMMSG_SETCOMMAND: // RTSとDTRフラグのセット + { + UINT8 cmd = *(reinterpret_cast(nParam)); // I/O 32h コマンドセットのデータ + ::PurgeComm(m_hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); + if(cmd & 0x20){ // RTS + ::EscapeCommFunction(m_hSerial, SETRTS); + }else{ + ::EscapeCommFunction(m_hSerial, CLRRTS); + } + if(cmd & 0x02){ // DTR + ::EscapeCommFunction(m_hSerial, SETDTR); + }else{ + ::EscapeCommFunction(m_hSerial, CLRDTR); + } + } + break; + + case COMMSG_PURGE: // バッファデータ破棄 + { + ::PurgeComm(m_hSerial, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); + } + break; + + + case COMMSG_SETFLAG: + { + COMFLAG flag = reinterpret_cast(nParam); + if ((flag) && (flag->size == sizeof(_COMFLAG))) + { + return 1; + } + } + break; + + case COMMSG_GETFLAG: + { + // dummy data + COMFLAG flag = (COMFLAG)_MALLOC(sizeof(_COMFLAG), "RS232C FLAG"); + if (flag) + { + flag->size = sizeof(_COMFLAG); + flag->sig = COMSIG_COM1; + flag->ver = 0; + flag->param = 0; + return reinterpret_cast(flag); + } + } + break; + + case COMMSG_GETERROR: // 通信エラー取得 + { + // エラー状態 (bit0: パリティ, bit1: オーバーラン, bit2: フレーミング, bit3: ブレーク信号) + UINT8 *errflag = (reinterpret_cast(nParam)); // I/O 32h コマンドセットのデータ + if(errflag){ + *errflag = m_errorstat; + } + } + break; + + case COMMSG_CLRERROR: // 通信エラークリア + { + m_errorstat = 0; + } + break; + + default: + break; + } + return 0; +} + diff --git a/windows/commng/cmserial.h b/windows/commng/cmserial.h index 4056e403..30f7495e 100644 --- a/windows/commng/cmserial.h +++ b/windows/commng/cmserial.h @@ -1,62 +1,62 @@ -/** - * @file cmserial.h - * @brief VA NX̐錾уC^[tFCX̒`܂ - */ - -#pragma once - -#include "cmbase.h" - -#define SERIAL_OVERLAP_COUNT 4 -#define SERIAL_BLOCKBUFFER_SIZE_MAX 128 - -/** - * xe[u - */ -const UINT32 cmserial_speed[] = {110, 300, 600, 1200, 2400, 4800, - 9600, 14400, 19200, 28800, 38400, 57600, 115200}; - -/** - * @brief commng VA foCX NX - */ -class CComSerial : public CComBase -{ -public: - static CComSerial* CreateInstance(UINT nPort, UINT8 cParam, UINT32 nSpeed, UINT8 fixedspeed, UINT8 DSRcheck); - -protected: - CComSerial(); - virtual ~CComSerial(); - virtual UINT Read(UINT8* pData); - virtual UINT Write(UINT8 cData); - virtual UINT WriteRetry(); - virtual UINT LastWriteSuccess(); // Ō݂̏Ă邩`FbN - virtual UINT8 GetStat(); - virtual INTPTR Message(UINT nMessage, INTPTR nParam); - virtual void BeginBlockTransfer(); - virtual void EndBlockTransfer(); - -private: - HANDLE m_hSerial; /*!< VA nh */ - - OVERLAPPED m_writeovl[SERIAL_OVERLAP_COUNT]; /*!< OVERLAPPED */ - OVERLAPPED m_readovl; /*!< ǂݍOVERLAPPED */ - bool m_writeovl_pending[SERIAL_OVERLAP_COUNT]; /*!< OVERLAPPEDҋ@ */ - bool m_readovl_pending; /*!< ǂݍOVERLAPPEDҋ@ */ - UINT8 m_readovl_buf; /*!< ǂݍOVERLAPPEDobt@ */ - - bool m_blocktransfer; /*!< ubNPʏ݃[h */ - UINT8 m_blockbuffer[SERIAL_BLOCKBUFFER_SIZE_MAX]; /*!< ubNobt@ */ - int m_blockbuffer_pos; /*!< ubNobt@݈ʒu */ - int m_blockbuffer_size; /*!< ubNobt@TCY */ - - bool m_fixedspeed; /*!< ʐMxŒ */ - UINT8 m_lastdata; // Ōɑ낤Ƃf[^ - UINT8 m_lastdatafail; // f[^𑗂̂ɎsĂ0ȊO - DWORD m_lastdatatime; // f[^𑗂̂Ɏsԁi܂ɂs悤Ȃ疳j - - UINT8 m_errorstat; // G[ (bit0: peB, bit1: I[o[, bit2: t[~O) - - bool Initialize(UINT nPort, UINT8 cParam, UINT32 nSpeed, UINT8 fixedspeed, UINT8 DSRcheck); - void CheckCommError(DWORD errorcode); -}; +/** + * @file cmserial.h + * @brief シリアル クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "cmbase.h" + +#define SERIAL_OVERLAP_COUNT 4 +#define SERIAL_BLOCKBUFFER_SIZE_MAX 128 + +/** + * 速度テーブル + */ +const UINT32 cmserial_speed[] = {110, 300, 600, 1200, 2400, 4800, + 9600, 14400, 19200, 28800, 38400, 57600, 115200}; + +/** + * @brief commng シリアル デバイス クラス + */ +class CComSerial : public CComBase +{ +public: + static CComSerial* CreateInstance(UINT nPort, UINT8 cParam, UINT32 nSpeed, UINT8 fixedspeed, UINT8 DSRcheck); + +protected: + CComSerial(); + virtual ~CComSerial(); + virtual UINT Read(UINT8* pData); + virtual UINT Write(UINT8 cData); + virtual UINT WriteRetry(); + virtual UINT LastWriteSuccess(); // 最後の書き込みが成功しているかチェック + virtual UINT8 GetStat(); + virtual INTPTR Message(UINT nMessage, INTPTR nParam); + virtual void BeginBlockTransfer(); + virtual void EndBlockTransfer(); + +private: + HANDLE m_hSerial; /*!< シリアル ハンドル */ + + OVERLAPPED m_writeovl[SERIAL_OVERLAP_COUNT]; /*!< 書き込みOVERLAPPED */ + OVERLAPPED m_readovl; /*!< 読み込みOVERLAPPED */ + bool m_writeovl_pending[SERIAL_OVERLAP_COUNT]; /*!< 書き込みOVERLAPPED待機中 */ + bool m_readovl_pending; /*!< 読み込みOVERLAPPED待機中 */ + UINT8 m_readovl_buf; /*!< 読み込みOVERLAPPEDバッファ */ + + bool m_blocktransfer; /*!< ブロック単位書き込みモード */ + UINT8 m_blockbuffer[SERIAL_BLOCKBUFFER_SIZE_MAX]; /*!< ブロックバッファ */ + int m_blockbuffer_pos; /*!< ブロックバッファ書き込み位置 */ + int m_blockbuffer_size; /*!< ブロックバッファサイズ */ + + bool m_fixedspeed; /*!< 通信速度固定 */ + UINT8 m_lastdata; // 最後に送ろうとしたデータ + UINT8 m_lastdatafail; // データを送るのに失敗していたら0以外 + DWORD m_lastdatatime; // データを送るのに失敗した時間(あまりにも失敗し続けるようなら無視する) + + UINT8 m_errorstat; // エラー状態 (bit0: パリティ, bit1: オーバーラン, bit2: フレーミング) + + bool Initialize(UINT nPort, UINT8 cParam, UINT32 nSpeed, UINT8 fixedspeed, UINT8 DSRcheck); + void CheckCommError(DWORD errorcode); +}; diff --git a/windows/commng/cmwacom.cpp b/windows/commng/cmwacom.cpp index 39761029..715d0a43 100644 --- a/windows/commng/cmwacom.cpp +++ b/windows/commng/cmwacom.cpp @@ -1,6 +1,6 @@ /** * @file cmwacom.cpp - * @brief Wacom Tablet NX̓̒`s܂ + * @brief Wacom Tablet クラスの動作の定義を行います */ #include "compiler.h" @@ -37,7 +37,7 @@ static SINT32 g_lastPosX = 0; static SINT32 g_lastPosY = 0; static bool g_lastPosValid = false; -static HCTX g_fakeContext = NULL; // ͂ςɂȂ̂C +static HCTX g_fakeContext = NULL; // 入力が変になるのを修正 void cmwacom_initialize(void){ if(!g_wacom_initialized){ @@ -110,7 +110,7 @@ LRESULT CALLBACK tabletWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam break; case WM_MOUSEMOVE: if(g_cmwacom->HandleMouseMoveMessage(hWnd, msg, wParam, lParam)){ - // tXN[j[ + // フルスクリーンメニュー if (scrnmng_isfullscreen()) { POINT p; @@ -121,7 +121,7 @@ LRESULT CALLBACK tabletWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam } if (np2oscfg.mouse_nc) { - // ΍W}EX + // 絶対座標マウス RECT rectClient; int xPos, yPos; int mouseon = 1; @@ -188,11 +188,11 @@ LRESULT CALLBACK tabletWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam /** - * CX^X쐬 - * @param[in] lpMidiOut MIDIOUT foCX - * @param[in] lpMidiIn MIDIIN foCX - * @param[in] lpModule W[ - * @return CX^X + * インスタンス作成 + * @param[in] lpMidiOut MIDIOUT デバイス + * @param[in] lpMidiIn MIDIIN デバイス + * @param[in] lpModule モジュール + * @return インスタンス */ CComWacom* CComWacom::CreateInstance(HWND hWnd) { @@ -206,7 +206,7 @@ CComWacom* CComWacom::CreateInstance(HWND hWnd) } /** - * RXgN^ + * コンストラクタ */ CComWacom::CComWacom() : CComBase(COMCONNECT_TABLET) @@ -240,7 +240,7 @@ CComWacom::CComWacom() } /** - * fXgN^ + * デストラクタ */ CComWacom::~CComWacom() { @@ -253,21 +253,21 @@ CComWacom::~CComWacom() } /** - * - * @retval true - * @retval false s + * 初期化 + * @retval true 成功 + * @retval false 失敗 */ bool CComWacom::Initialize(HWND hWnd) { if(!g_wacom_initialized){ - return false; // ĂȂ + return false; // 初期化されていない } if(g_wacom_allocated){ - return false; // ‚̗p͕s + return false; // 複数個の利用は不可 } if (!gpWTInfoA || !gpWTInfoA(0, 0, NULL)) { - return false; // WinTabgps + return false; // WinTab使用不可 } m_hwndMain = hWnd; @@ -300,30 +300,30 @@ void CComWacom::InitializeTabletDevice(){ AXIS rotAxis[3] = {0}; if(!g_wacom_initialized){ - return; // ĂȂ + return; // 初期化されていない } if(g_wacom_allocated){ - return; // ‚̗p͕s + return; // 複数個の利用は不可 } if (!gpWTInfoA(0, 0, NULL)) { - return; // WinTabgps + return; // WinTab使用不可 } if(m_exclusivemode){ gpWTInfoA(WTI_DEVICES, DVC_X, &axis); m_minX = axis.axMin; - m_maxX = axis.axMax; /* w̍őW */ - m_resX = axis.axResolution; /* wW̕\ P:line/inch */ + m_maxX = axis.axMax; /* X方向の最大座標 */ + m_resX = axis.axResolution; /* X座標の分解能 単位:line/inch */ gpWTInfoA(WTI_DEVICES, DVC_Y, &axis); m_minY = axis.axMin; - m_maxY = axis.axMax; /* x̍őW */ - m_resY = axis.axResolution; /* xW̕\ P:line/inch */ + m_maxY = axis.axMax; /* Y方向の最大座標 */ + m_resY = axis.axResolution; /* Y座標の分解能 単位:line/inch */ gpWTInfoA(WTI_DEFSYSCTX, 0, &lcMine); } gpWTInfoA(m_exclusivemode ? WTI_DEFCONTEXT : WTI_DEFSYSCTX, 0, &lcMine); - lcMine.lcOptions |= CXO_MESSAGES|CXO_MARGIN; /* Wintabүނn悤ɂ */ + lcMine.lcOptions |= CXO_MESSAGES|CXO_MARGIN; /* Wintabメッセージが渡されるようにする */ lcMine.lcMsgBase = WT_DEFBASE; lcMine.lcPktData = PACKETDATA; lcMine.lcPktMode = PACKETMODE; @@ -332,12 +332,12 @@ void CComWacom::InitializeTabletDevice(){ if(m_exclusivemode){ lcMine.lcInOrgX = m_minX; lcMine.lcInOrgY = m_minY; - lcMine.lcInExtX = m_maxX; /* گĂ̗L͈͑S𑀍رƂ܂ */ + lcMine.lcInExtX = m_maxX; /* タブレットの有効範囲全域を操作エリアとします */ lcMine.lcInExtY = m_maxY; lcMine.lcOutOrgX = 0; lcMine.lcOutOrgY = 0; - lcMine.lcOutExtX = m_maxX-m_minX; /* گĂ̕\Ɠް̕\ */ - lcMine.lcOutExtY = m_maxY-m_minY; /* 킹܂ */ + lcMine.lcOutExtX = m_maxX-m_minX; /* タブレットの分解能と入力データの分解能を */ + lcMine.lcOutExtY = m_maxY-m_minY; /* あわせます */ }else{ m_minX = lcMine.lcOutOrgX; @@ -353,7 +353,7 @@ void CComWacom::InitializeTabletDevice(){ { return; } - // WTI_DEVICESDVC_NPRESSURE擾 iMl̍őAŏj + // WTI_DEVICESのDVC_NPRESSUREを取得 (筆圧値の最大、最小) gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &pressAxis); m_rawPressureMax = pressAxis.axMax; m_rawPressureMin = pressAxis.axMin; @@ -374,7 +374,7 @@ void CComWacom::InitializeTabletDevice(){ gpWTMgrExt(m_hMgr, WTX_OBT, m_ObtBuf); } - // Ulastdata + // 偽lastdata m_lastdata[0] = 0xA0; m_lastdata[1] = 0x00; m_lastdata[2] = 0x00; @@ -388,7 +388,7 @@ void CComWacom::FinalizeTabletDevice(){ if (m_hTab) { if (m_hMgr) { - // Out of Bounds Tracking ̉ + // Out of Bounds Tracking の解除 m_ObtBuf[0] = 0; gpWTMgrExt(m_hMgr, WTX_OBT, m_ObtBuf); gpWTMgrClose(m_hMgr); @@ -432,14 +432,14 @@ bool CComWacom::HandlePacketMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM l proximityflag = true; } - m_skipmouseevent = 2; // WinTab̃oO + m_skipmouseevent = 2; // WinTabのバグ回避 - m_rawX = tPckt.pkX; /* fW^CÛwW */ - m_rawY = tPckt.pkY; /* fW^CÛxW */ - newbuttons = LOWORD(tPckt.pkButtons); /* {^ԍ */ + m_rawX = tPckt.pkX; /* デジタイザ上のX座標 */ + m_rawY = tPckt.pkY; /* デジタイザ上のY座標 */ + newbuttons = LOWORD(tPckt.pkButtons); /* ボタン番号 */ m_rawStatus = tPckt.pkStatus; - m_rawPressure = LOWORD(tPckt.pkNormalPressure); /* M */ + m_rawPressure = LOWORD(tPckt.pkNormalPressure); /* 筆圧 */ if(m_rawPressureMax-m_rawPressureMin > 0){ if(m_rawPressure <= m_rawPressureMin){ m_pressure = 0.0; @@ -504,7 +504,7 @@ bool CComWacom::HandlePacketMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM l SINT32 tablet_resY = TABLET_RAWMAX_Y * m_config.resolution_h / TABLET_BASERASOLUTION; char buf[32]; pktPressure = (UINT32)(m_pressure * 255); - // yON/OFFꂼ255iKi炵j + // ペンON/OFFそれぞれで255段階(らしい) if(!m_config.disablepressure){ if(m_pressure < 0.5){ m_rawButtons &= ~0x1; @@ -514,26 +514,26 @@ bool CComWacom::HandlePacketMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM l } } if(m_exclusivemode){ - // r[hi}EXLv`j + // 排他モード(マウスキャプチャ中) if(m_config.scrnsizemode){ tablet_resX = m_config.screen_w; tablet_resY = m_config.screen_h; } if(m_fixedaspect){ - // AXyNg䂪ArtPad IIƓɂȂ悤ɏC + // アスペクト比がArtPad IIと同じになるように修正 if(tablet_resX * (m_maxY - m_minY) > tablet_resY * (m_maxX - m_minX)){ pktXtmp = (m_rawX * tablet_resX / (m_maxX - m_minX)); - pktYtmp = tablet_resY - (m_rawY * tablet_resX / (m_maxX - m_minX)); // _łĂ + pktYtmp = tablet_resY - (m_rawY * tablet_resX / (m_maxX - m_minX)); // 左下原点ですってよ }else{ pktXtmp = (m_rawX * tablet_resY / (m_maxY - m_minY)); - pktYtmp = tablet_resY - (m_rawY * tablet_resY / (m_maxY - m_minY)); // _łĂ + pktYtmp = tablet_resY - (m_rawY * tablet_resY / (m_maxY - m_minY)); // 左下原点ですってよ } }else{ pktXtmp = (m_rawX * tablet_resX / (m_maxX - m_minX)); - pktYtmp = tablet_resY - (m_rawY * tablet_resY / (m_maxY - m_minY)); // _łĂ + pktYtmp = tablet_resY - (m_rawY * tablet_resY / (m_maxY - m_minY)); // 左下原点ですってよ } }else{ - // zXg}EXA[hi}EXLv`Ȃ샂[hj + // ホストマウス連動モード(マウスキャプチャなし操作モード) RECT rectClient; POINT pt; scrnmng_getrect(&rectClient); @@ -552,20 +552,20 @@ bool CComWacom::HandlePacketMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM l pktYtmp = m_rawY - pt.y; } if(pktXtmp < 0 || pktYtmp < 0 || pktXtmp > tablet_resX || pktYtmp > tablet_resY){ - // ͈͊O͈ړ̂݉ + // 範囲外は移動のみ可 m_rawButtons = m_rawButtons & 0x4; pktPressure = 0; proximityflag = true; } } - // ͂ݏoȂ悤ɍW͈͂C + // はみ出さないように座標範囲を修正 if(pktXtmp < 0) pktXtmp = 0; if(pktYtmp < 0) pktYtmp = 0; if(pktXtmp > tablet_resX) pktXtmp = tablet_resX; if(pktYtmp > tablet_resY) pktYtmp = tablet_resY; if(m_config.relmode){ - // ΍W[h + // 相対座標モード if(g_lastPosValid){ pktX = (SINT16)((SINT32)pktXtmp - g_lastPosX); pktY = (SINT16)((SINT32)pktYtmp - g_lastPosY); @@ -574,13 +574,13 @@ bool CComWacom::HandlePacketMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM l pktY = 0; } }else{ - // ΍W[h + // 絶対座標モード pktX = (UINT16)pktXtmp; pktY = (UINT16)pktYtmp; } if(m_config.disablepressure && m_config.csvmode){ - // CSVW[hiM[hłȂƎgȂj + // CSV座標モード(筆圧無効モードでないと使えない) int slen = sprintf(buf, "#,%05d,%05d,%02d\r\n", pktX, pktY, proximityflag ? 99 : m_rawButtons); if(slen > 0){ memcpy(m_lastdata, buf, slen); @@ -591,7 +591,7 @@ bool CComWacom::HandlePacketMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM l } }else{ if(m_config.disablepressure){ - // M[h + // 筆圧無効モード buf[0] = 0xe0|((pktX >> 14) & 0x3); buf[1] = ((pktX >> 7) & 0x7f); buf[2] = (pktX & 0x7f); @@ -600,7 +600,7 @@ bool CComWacom::HandlePacketMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM l buf[5] = (pktY & 0x7f); buf[6] = m_rawButtons; }else{ - // ʏ탂[h + // 通常モード buf[0] = (proximityflag ? 0xA0 : 0xE0)|((m_rawButtons & ~0x1) ? 0x8 : 0)|((pktX >> 14) & 0x3)|((((pktPressure) & 0) << 2)); buf[1] = ((pktX >> 7) & 0x7f); buf[2] = (pktX & 0x7f); @@ -667,13 +667,13 @@ bool CComWacom::SendDataToReadBuffer(const UINT8 *data, int len){ if(bufused + len >= WACOM_BUFFER){ #if defined(SUPPORT_RS232C_FIFO) if(rs232cfifo.port138 & 0x1){ - // ÑȂ + // 催促しない }else #endif { // Buffer Full if (sysport.c & 1) { - pic_setirq(4); // XXX: Ñ + pic_setirq(4); // XXX: 催促 } } return false; @@ -687,9 +687,9 @@ bool CComWacom::SendDataToReadBuffer(const UINT8 *data, int len){ } /** - * ǂݍ - * @param[out] pData obt@ - * @return TCY + * 読み込み + * @param[out] pData バッファ + * @return サイズ */ UINT CComWacom::Read(UINT8* pData) { @@ -701,7 +701,7 @@ UINT CComWacom::Read(UINT8* pData) return 0; } if(datatime - g_datatime > 500){ - // f[^Â̂Ŏ̂Ă܂傤 + // データが古いので捨てましょう m_sBuffer_rpos = m_sBuffer_wpos; g_datatime = datatime; return 0; @@ -714,7 +714,7 @@ UINT CComWacom::Read(UINT8* pData) return 1; }else{ nodatacounter++; - //// XXX: ԃf[^ȂWin9xłȂ悤Ȃ̂Ŏb΍ + //// XXX: 長期間データがないとWin9xでおかしくなるようなので暫定対策 //if(m_config.mode19200 && nodatacounter > 256){ // if(m_lastdatalen > 0){ // char buf[10]; @@ -734,9 +734,9 @@ UINT CComWacom::Read(UINT8* pData) } /** - * - * @param[out] cData f[^ - * @return TCY + * 書き込み + * @param[out] cData データ + * @return サイズ */ UINT CComWacom::Write(UINT8 cData) { @@ -747,11 +747,11 @@ UINT CComWacom::Write(UINT8 cData) } if (m_hTab) { - if(cData=='\r' || cData=='\n'){ // R}hI[̎iXXX: LFR}hI[Hj + if(cData=='\r' || cData=='\n'){ // コマンド終端の時(XXX: LFもコマンド終端扱い?) m_cmdbuf[m_cmdbuf_pos] = '\0'; if(strcmp(m_cmdbuf, "#")==0){ // Reset to protocol IV command set - m_sBuffer_rpos = m_sBuffer_wpos; // f[^ + m_sBuffer_rpos = m_sBuffer_wpos; // データ放棄 m_config.scrnsizemode = false; m_config.disablepressure = false; m_config.csvmode = false; @@ -760,7 +760,7 @@ UINT CComWacom::Write(UINT8 cData) m_config.mode19200 = false; }else if(strcmp(m_cmdbuf, "#~*F202C800")==0){ // 19200 bps mode - m_sBuffer_rpos = m_sBuffer_wpos; // f[^ + m_sBuffer_rpos = m_sBuffer_wpos; // データ放棄 m_config.scrnsizemode = false; m_config.disablepressure = false; m_config.csvmode = false; @@ -769,7 +769,7 @@ UINT CComWacom::Write(UINT8 cData) m_config.mode19200 = true; }else if(strncmp(m_cmdbuf, "~*F2039100,000,00,1000,1000", 3)==0){ // 19200 bps mode & Enable Pressure (win3.1) - m_sBuffer_rpos = m_sBuffer_wpos; // f[^ + m_sBuffer_rpos = m_sBuffer_wpos; // データ放棄 m_config.scrnsizemode = false; m_config.disablepressure = false; m_config.csvmode = false; @@ -778,7 +778,7 @@ UINT CComWacom::Write(UINT8 cData) m_config.mode19200 = true; }else if(strncmp(m_cmdbuf, "~*E2039100,000,00,1000,1000", 3)==0){ // 9600 bps mode & Enable Pressure (win3.1) - m_sBuffer_rpos = m_sBuffer_wpos; // f[^ + m_sBuffer_rpos = m_sBuffer_wpos; // データ放棄 m_config.scrnsizemode = false; m_config.disablepressure = false; m_config.csvmode = false; @@ -787,10 +787,10 @@ UINT CComWacom::Write(UINT8 cData) m_config.mode19200 = false; }else if(strcmp(m_cmdbuf, "$")==0){ // Reset to 9600 bps (sent at 19200 bps)? & Disable Pressure - m_sBuffer_rpos = m_sBuffer_wpos; // f[^ + m_sBuffer_rpos = m_sBuffer_wpos; // データ放棄 m_config.scrnsizemode = false; m_config.disablepressure = true; - m_config.mode19200 = false; // Ⴄ + m_config.mode19200 = false; // 違うかも }else if(strncmp(m_cmdbuf, "ST", 2)==0){ m_config.start = true; // Start sending coordinates }else if(strncmp(m_cmdbuf, "@ST", 2)==0){ @@ -851,10 +851,10 @@ UINT CComWacom::Write(UINT8 cData) char data[256]; if(strlen(m_cmdbuf) <= 2){ // TE only sprintf(data, "KT-0405-R00 V1.3-2 95/04/28 by WACOM\r\nI AM FINE.\r\n"); - }else{ // TExxxx 4ẑ͎Ă + }else{ // TExxxx 4文字を越えた部分は捨てる sprintf(data, "KT-0405-R00 V1.3-2 95/04/28 by WACOM\r\n%.4s\r\nI AM FINE.\r\n", m_cmdbuf + 2); } - m_sBuffer_rpos = m_sBuffer_wpos; //obt@ + m_sBuffer_rpos = m_sBuffer_wpos; //バッファ消す SendDataToReadBuffer(data, (int)strlen(data)); m_lastdatalen = 0; m_wait = sizeof(data); @@ -865,13 +865,13 @@ UINT CComWacom::Write(UINT8 cData) }else{ m_cmdbuf[m_cmdbuf_pos] = cData; m_cmdbuf_pos++; - if(m_cmdbuf_pos >= 2 && strncmp(&m_cmdbuf[m_cmdbuf_pos-2], "~#", 2)==0){ // OIɑ - m_sBuffer_rpos = m_sBuffer_wpos; //obt@ + if(m_cmdbuf_pos >= 2 && strncmp(&m_cmdbuf[m_cmdbuf_pos-2], "~#", 2)==0){ // 例外的に即応答 + m_sBuffer_rpos = m_sBuffer_wpos; //バッファ消す SendDataToReadBuffer(cmwacom_ModelData, sizeof(cmwacom_ModelData)); //if(m_wait < WACOM_BUFFER) m_wait += sizeof(cmwacom_ModelData)*2; //#if defined(SUPPORT_RS232C_FIFO) // if(rs232cfifo.port138 & 0x1){ -// // FIFO[hł̓EFCgȂ +// // FIFOモードではウェイトなし // m_wait = 0; // }else //#endif @@ -884,7 +884,7 @@ UINT CComWacom::Write(UINT8 cData) } //#if defined(SUPPORT_RS232C_FIFO) // if(rs232cfifo.port138 & 0x1){ -// // FIFO[hł̓EFCgȂ +// // FIFOモードではウェイトなし // m_wait = 0; // } //#endif @@ -893,7 +893,7 @@ UINT CComWacom::Write(UINT8 cData) } /** - * Xe[^X𓾂 + * ステータスを得る * bit 7: ~CI (RI, RING) * bit 6: ~CS (CTS) * bit 5: ~CD (DCD, RLSD) @@ -902,7 +902,7 @@ UINT CComWacom::Write(UINT8 cData) * bit 2: reserved * bit 1: reserved * bit 0: ~DSR (DR) - * @return Xe[^X + * @return ステータス */ UINT8 CComWacom::GetStat() { @@ -919,10 +919,10 @@ UINT8 CComWacom::GetStat() } /** - * bZ[W - * @param[in] nMessage bZ[W - * @param[in] nParam p^ - * @return Ug R[h + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParam パラメタ + * @return リザルト コード */ INTPTR CComWacom::Message(UINT nMessage, INTPTR nParam) { @@ -930,7 +930,7 @@ INTPTR CComWacom::Message(UINT nMessage, INTPTR nParam) { case COMMSG_PURGE: { - m_sBuffer_rpos = m_sBuffer_wpos; //obt@ + m_sBuffer_rpos = m_sBuffer_wpos; //バッファ消す } break; diff --git a/windows/commng/cmwacom.h b/windows/commng/cmwacom.h index a178e61f..df755054 100644 --- a/windows/commng/cmwacom.h +++ b/windows/commng/cmwacom.h @@ -1,163 +1,163 @@ -/** - * @file cmwacom.h - * @brief Wacom Tablet NX̐錾уC^[tFCX̒`܂ - */ - -#pragma once - -#include "cmbase.h" - -#ifdef SUPPORT_WACOM_TABLET - -#include "wintab/MSGPACK.H" -#include "wintab/WINTAB.H" -#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_STATUS | PK_TANGENT_PRESSURE | PK_ORIENTATION) -#define PACKETMODE 0 -#include "wintab/PKTDEF.H" -#include "wintab/Utils.h" - -#pragma pack(1) -typedef struct tagCMWACOM_CONFIG { - bool enable; // y^u[hLiL}EXsj - bool start; // STtrue, SPfalseiWMĊJ^ꎞ~Hj - bool scrnsizemode; // ʃTCYw胂[h - bool disablepressure; // M[hif[^`ςj - bool relmode; // ΍W[h - bool csvmode; // CSVW[hiM[hł̂ݗLj - bool suppress; // }[hiWl͑Ȃj - bool mode19200; // 19200bps[h - SINT32 resolution_w; - SINT32 resolution_h; - SINT32 screen_w; - SINT32 screen_h; -} CMWACOM_CONFIG; -#pragma pack() - -void cmwacom_initialize(void); -void cmwacom_reset(void); -void cmwacom_finalize(void); -bool cmwacom_skipMouseEvent(void); -void cmwacom_setNCControl(bool enable); - -/** - * @brief commng Wacom Tablet foCX NX - */ -class CComWacom : public CComBase -{ -public: - static CComWacom* CreateInstance(HWND hWnd); - void InitializeTabletDevice(); - void FinalizeTabletDevice(); - HCTX GetHTab(); - bool HandlePacketMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - bool HandleMouseMoveMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - bool HandleMouseUpMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - bool HandleMouseDownMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - bool SkipMouseEvent(); - void SetExclusiveMode(bool enable); - void SetNCControl(bool enable); - void GetConfig(CMWACOM_CONFIG *cfg); - void SetConfig(CMWACOM_CONFIG cfg); - - int m_skiptabletevent; - -protected: - CComWacom(); - virtual ~CComWacom(); - virtual UINT Read(UINT8* pData); - virtual UINT Write(UINT8 cData); - virtual UINT8 GetStat(); - virtual INTPTR Message(UINT msg, INTPTR param); - -private: - enum - { - WACOM_BUFFER = (1 << 6), - WACOM_CMDBUFFER = (1 << 8), - }; - - bool m_fixedaspect; - - HWND m_hwndMain; /*!< Main Window Handle */ - HCTX m_hTab; /*!< WinTab Handle */ - HMGR m_hMgr; - BOOL m_ObtBuf[64]; - UINT8 m_sBuffer[WACOM_BUFFER]; /*!< obt@ */ - SINT32 m_sBuffer_wpos; /*!< obt@݈ʒu */ - SINT32 m_sBuffer_rpos; /*!< obt@ǂݍ݈ʒu */ - - UINT8 m_lastdata[32]; - SINT32 m_lastdatalen; - - int m_skipmouseevent; - bool m_exclusivemode; - bool m_nccontrol; - - SINT32 m_wait; - bool m_sendlastdata; // Ō̃f[^đM - - SINT32 m_mousedown; - SINT32 m_mouseX; - SINT32 m_mouseY; - - char m_cmdbuf[WACOM_CMDBUFFER]; - SINT32 m_cmdbuf_pos; - - CMWACOM_CONFIG m_config; - //SINT32 m_resolution_w; - //SINT32 m_resolution_h; - - //bool m_scrnsizemode; - //SINT32 m_screen_w; - //SINT32 m_screen_h; - - SINT32 m_minX; - SINT32 m_maxX; - SINT32 m_resX; - SINT32 m_minY; - SINT32 m_maxY; - SINT32 m_resY; - - SINT32 m_rawX; - SINT32 m_rawY; - SINT32 m_rawButtons; - - SINT32 m_rawPressure; - SINT32 m_rawPressureMax; - SINT32 m_rawPressureMin; - double m_pressure; - - SINT32 m_rawTangentPressure; - SINT32 m_rawTangentPressureMax; - SINT32 m_rawTangentPressureMin; - double m_tangentPressure; - - SINT32 m_rawAzimuth; - SINT32 m_rawAzimuthMax; - SINT32 m_rawAzimuthMin; - double m_azimuth; - - SINT32 m_rawAltitude; - SINT32 m_rawAltitudeMax; - SINT32 m_rawAltitudeMin; - double m_altitude; - - SINT32 m_rawTwist; - SINT32 m_rawTwistMax; - SINT32 m_rawTwistMin; - double m_twist; - - double m_tiltX; - double m_tiltY; - - double m_rotationDeg; - - SINT32 m_rawStatus; - - bool Initialize(HWND hWnd); - - bool SendDataToReadBuffer(const char *data, int len); - bool SendDataToReadBuffer(const UINT8 *data, int len); -}; - -#endif +/** + * @file cmwacom.h + * @brief Wacom Tablet クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "cmbase.h" + +#ifdef SUPPORT_WACOM_TABLET + +#include "wintab/MSGPACK.H" +#include "wintab/WINTAB.H" +#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_STATUS | PK_TANGENT_PRESSURE | PK_ORIENTATION) +#define PACKETMODE 0 +#include "wintab/PKTDEF.H" +#include "wintab/Utils.h" + +#pragma pack(1) +typedef struct tagCMWACOM_CONFIG { + bool enable; // ペンタブモード有効(猫マウス操作不可) + bool start; // STでtrue, SPでfalse(座標送信再開/一時停止?) + bool scrnsizemode; // 画面サイズ指定モード + bool disablepressure; // 筆圧無効モード(データ形式が変わる) + bool relmode; // 相対座標モード + bool csvmode; // CSV座標モード(筆圧無効モードでのみ有効) + bool suppress; // 抑制モード(同じ座標値は送らない) + bool mode19200; // 19200bpsモード + SINT32 resolution_w; + SINT32 resolution_h; + SINT32 screen_w; + SINT32 screen_h; +} CMWACOM_CONFIG; +#pragma pack() + +void cmwacom_initialize(void); +void cmwacom_reset(void); +void cmwacom_finalize(void); +bool cmwacom_skipMouseEvent(void); +void cmwacom_setNCControl(bool enable); + +/** + * @brief commng Wacom Tablet デバイス クラス + */ +class CComWacom : public CComBase +{ +public: + static CComWacom* CreateInstance(HWND hWnd); + void InitializeTabletDevice(); + void FinalizeTabletDevice(); + HCTX GetHTab(); + bool HandlePacketMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + bool HandleMouseMoveMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + bool HandleMouseUpMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + bool HandleMouseDownMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + bool SkipMouseEvent(); + void SetExclusiveMode(bool enable); + void SetNCControl(bool enable); + void GetConfig(CMWACOM_CONFIG *cfg); + void SetConfig(CMWACOM_CONFIG cfg); + + int m_skiptabletevent; + +protected: + CComWacom(); + virtual ~CComWacom(); + virtual UINT Read(UINT8* pData); + virtual UINT Write(UINT8 cData); + virtual UINT8 GetStat(); + virtual INTPTR Message(UINT msg, INTPTR param); + +private: + enum + { + WACOM_BUFFER = (1 << 6), + WACOM_CMDBUFFER = (1 << 8), + }; + + bool m_fixedaspect; + + HWND m_hwndMain; /*!< Main Window Handle */ + HCTX m_hTab; /*!< WinTab Handle */ + HMGR m_hMgr; + BOOL m_ObtBuf[64]; + UINT8 m_sBuffer[WACOM_BUFFER]; /*!< バッファ */ + SINT32 m_sBuffer_wpos; /*!< バッファ書き込み位置 */ + SINT32 m_sBuffer_rpos; /*!< バッファ読み込み位置 */ + + UINT8 m_lastdata[32]; + SINT32 m_lastdatalen; + + int m_skipmouseevent; + bool m_exclusivemode; + bool m_nccontrol; + + SINT32 m_wait; + bool m_sendlastdata; // 最後のデータを再送信する + + SINT32 m_mousedown; + SINT32 m_mouseX; + SINT32 m_mouseY; + + char m_cmdbuf[WACOM_CMDBUFFER]; + SINT32 m_cmdbuf_pos; + + CMWACOM_CONFIG m_config; + //SINT32 m_resolution_w; + //SINT32 m_resolution_h; + + //bool m_scrnsizemode; + //SINT32 m_screen_w; + //SINT32 m_screen_h; + + SINT32 m_minX; + SINT32 m_maxX; + SINT32 m_resX; + SINT32 m_minY; + SINT32 m_maxY; + SINT32 m_resY; + + SINT32 m_rawX; + SINT32 m_rawY; + SINT32 m_rawButtons; + + SINT32 m_rawPressure; + SINT32 m_rawPressureMax; + SINT32 m_rawPressureMin; + double m_pressure; + + SINT32 m_rawTangentPressure; + SINT32 m_rawTangentPressureMax; + SINT32 m_rawTangentPressureMin; + double m_tangentPressure; + + SINT32 m_rawAzimuth; + SINT32 m_rawAzimuthMax; + SINT32 m_rawAzimuthMin; + double m_azimuth; + + SINT32 m_rawAltitude; + SINT32 m_rawAltitudeMax; + SINT32 m_rawAltitudeMin; + double m_altitude; + + SINT32 m_rawTwist; + SINT32 m_rawTwistMax; + SINT32 m_rawTwistMin; + double m_twist; + + double m_tiltX; + double m_tiltY; + + double m_rotationDeg; + + SINT32 m_rawStatus; + + bool Initialize(HWND hWnd); + + bool SendDataToReadBuffer(const char *data, int len); + bool SendDataToReadBuffer(const UINT8 *data, int len); +}; + +#endif diff --git a/windows/commng/vsthost/vstbuffer.cpp b/windows/commng/vsthost/vstbuffer.cpp index 4eea4626..cefc0a00 100644 --- a/windows/commng/vsthost/vstbuffer.cpp +++ b/windows/commng/vsthost/vstbuffer.cpp @@ -1,6 +1,6 @@ /** * @file vstbuffer.cpp - * @brief VST obt@ NX̓̒`s܂ + * @brief VST バッファ クラスの動作の定義を行います */ #include "compiler.h" @@ -9,7 +9,7 @@ #include "vstbuffer.h" /** - * RXgN^ + * コンストラクタ */ CVstBuffer::CVstBuffer() : m_nChannels(0) @@ -19,9 +19,9 @@ CVstBuffer::CVstBuffer() } /** - * RXgN^ - * @param[in] nChannels `l - * @param[in] nSamples Tv + * コンストラクタ + * @param[in] nChannels チャネル数 + * @param[in] nSamples サンプル数 */ CVstBuffer::CVstBuffer(UINT nChannels, UINT nSamples) : m_nChannels(0) @@ -33,7 +33,7 @@ CVstBuffer::CVstBuffer(UINT nChannels, UINT nSamples) } /** - * fXgN^ + * デストラクタ */ CVstBuffer::~CVstBuffer() { @@ -41,9 +41,9 @@ CVstBuffer::~CVstBuffer() } /** - * RXgN^ - * @param[in] nChannels `l - * @param[in] nSamples Tv + * コンストラクタ + * @param[in] nChannels チャネル数 + * @param[in] nSamples サンプル数 */ void CVstBuffer::Alloc(UINT nChannels, UINT nSamples) { @@ -69,7 +69,7 @@ void CVstBuffer::Alloc(UINT nChannels, UINT nSamples) } /** - * j + * 破棄 */ void CVstBuffer::Delloc() { @@ -100,8 +100,8 @@ void CVstBuffer::ZeroFill() } /** - * Tv𓾂 - * @param[out] lpBuffer obt@ + * サンプルを得る + * @param[out] lpBuffer バッファ */ void CVstBuffer::GetShort(short* lpBuffer) const { diff --git a/windows/commng/vsthost/vstbuffer.h b/windows/commng/vsthost/vstbuffer.h index f2b0d6b1..997a9ffb 100644 --- a/windows/commng/vsthost/vstbuffer.h +++ b/windows/commng/vsthost/vstbuffer.h @@ -1,12 +1,12 @@ /** * @file vstbuffer.h - * @brief VST obt@ NX̐錾уC^[tFCX̒`܂ + * @brief VST バッファ クラスの宣言およびインターフェイスの定義をします */ #pragma once /** - * @brief VST obt@ NX + * @brief VST バッファ クラス */ class CVstBuffer { @@ -21,14 +21,14 @@ class CVstBuffer void GetShort(short* lpBuffer) const; private: - UINT m_nChannels; /*!< `l */ - UINT m_nSamples; /*!< Tv */ - float** m_pBuffers; /*!< obt@ */ + UINT m_nChannels; /*!< チャンネル数 */ + UINT m_nSamples; /*!< サンプル数 */ + float** m_pBuffers; /*!< バッファ */ }; /** - * obt@𓾂 - * @return obt@ + * バッファを得る + * @return バッファ */ inline float** CVstBuffer::GetBuffer() { diff --git a/windows/commng/vsthost/vsteditwnd.cpp b/windows/commng/vsthost/vsteditwnd.cpp index b92ca244..b8bbe1a5 100644 --- a/windows/commng/vsthost/vsteditwnd.cpp +++ b/windows/commng/vsthost/vsteditwnd.cpp @@ -1,6 +1,6 @@ /** * @file vsteditwnd.cpp - * @brief VST edit EBhE NX̓̒`s܂ + * @brief VST edit ウィンドウ クラスの動作の定義を行います */ #include "compiler.h" @@ -10,20 +10,20 @@ #include "vsteditwnd.h" #include "vsteffect.h" -//! EBhE NX +//! ウィンドウ クラス名 static const TCHAR s_szClassName[] = TEXT("VstEffectWnd"); -//! CX^X +//! インスタンス HINSTANCE CVstEditWnd::sm_hInstance; -//! EBhE }bv +//! ウィンドウ マップ std::map CVstEditWnd::sm_wndMap; /** - * - * @param[in] hInstance AvP[V݂̌̃CX^X̃nh - * @retval true - * @retval false s + * 初期化 + * @param[in] hInstance アプリケーションの現在のインスタンスのハンドル + * @retval true 成功 + * @retval false 失敗 */ bool CVstEditWnd::Initialize(HINSTANCE hInstance) { @@ -46,7 +46,7 @@ bool CVstEditWnd::Initialize(HINSTANCE hInstance) } /** - * AChO + * アイドリング */ void CVstEditWnd::OnIdle() { @@ -57,7 +57,7 @@ void CVstEditWnd::OnIdle() } /** - * RXgN^ + * コンストラクタ */ CVstEditWnd::CVstEditWnd() : m_hWnd(NULL) @@ -66,21 +66,21 @@ CVstEditWnd::CVstEditWnd() } /** - * fXgN^ + * デストラクタ */ CVstEditWnd::~CVstEditWnd() { } /** - * 쐬 - * @param[in] pEffect GtFNg - * @param[in] lpszWindowName ^Cg - * @param[in] dwStyle X^C - * @param[in] x ʒu - * @param[in] y ʒu - * @retval true - * @retval false s + * 作成 + * @param[in] pEffect エフェクト + * @param[in] lpszWindowName タイトル + * @param[in] dwStyle スタイル + * @param[in] x 位置 + * @param[in] y 位置 + * @retval true 成功 + * @retval false 失敗 */ bool CVstEditWnd::Create(CVstEffect* pEffect, LPCTSTR lpszWindowName, DWORD dwStyle, LONG x, LONG y) { @@ -116,7 +116,7 @@ bool CVstEditWnd::Create(CVstEffect* pEffect, LPCTSTR lpszWindowName, DWORD dwSt } /** - * j + * 破棄 */ void CVstEditWnd::Destroy() { @@ -133,12 +133,12 @@ void CVstEditWnd::Destroy() } /** - * EBhE vV[W - * @param[in] hWnd EBhE nh - * @param[in] message Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * ウィンドウ プロシージャ + * @param[in] hWnd ウィンドウ ハンドル + * @param[in] message 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT CALLBACK CVstEditWnd::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -174,11 +174,11 @@ LRESULT CALLBACK CVstEditWnd::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP } /** - * CMainWnd IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] message Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CMainWnd オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] message 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT CVstEditWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { @@ -195,10 +195,10 @@ LRESULT CVstEditWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) } /** - * t[[ŃAWindows ̃EBhE [쐬] ܂ CreateEx ̃o[֐ĂяoƂɂč쐬ꂽAvP[VKvƂƁÃo[֐Ăяo܂ + * フレームワークは、Windows のウィンドウは [作成] または CreateEx のメンバー関数を呼び出すことによって作成されたアプリケーションが必要とすると、このメンバー関数を呼び出します * @param[in] lpCreateStruct CREATESTRUCT - * @retval 0 p - * @retval -1 j + * @retval 0 継続 + * @retval -1 破棄 */ int CVstEditWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) { @@ -211,11 +211,11 @@ int CVstEditWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) } /** - * TCY - * @param[in] nWidth - * @param[in] nHeight - * @retval true - * @retval false s + * リサイズ + * @param[in] nWidth 幅 + * @param[in] nHeight 高さ + * @retval true 成功 + * @retval false 失敗 */ bool CVstEditWnd::OnResize(int nWidth, int nHeight) { @@ -241,9 +241,9 @@ bool CVstEditWnd::OnResize(int nWidth, int nHeight) } /** - * ĕ`v - * @retval true - * @retval false s + * 再描画要求 + * @retval true 成功 + * @retval false 失敗 */ bool CVstEditWnd::OnUpdateDisplay() { diff --git a/windows/commng/vsthost/vsteditwnd.h b/windows/commng/vsthost/vsteditwnd.h index 7ae272d5..fb35378d 100644 --- a/windows/commng/vsthost/vsteditwnd.h +++ b/windows/commng/vsthost/vsteditwnd.h @@ -1,6 +1,6 @@ /** * @file vsteditwnd.h - * @brief VST edit EBhE NX̐錾уC^[tFCX̒`܂ + * @brief VST edit ウィンドウ クラスの宣言およびインターフェイスの定義をします */ #pragma once @@ -11,7 +11,7 @@ class CVstEffect; /** - * @brief VST effect EBhE NX + * @brief VST effect ウィンドウ クラス */ class CVstEditWnd : public IVstEditWnd { @@ -43,8 +43,8 @@ class CVstEditWnd : public IVstEditWnd }; /** - * EBhE nh𓾂 - * @return EBhE nh + * ウィンドウ ハンドルを得る + * @return ウィンドウ ハンドル */ inline HWND CVstEditWnd::GetHWnd() { @@ -52,8 +52,8 @@ inline HWND CVstEditWnd::GetHWnd() } /** - * GtFNg𓾂 - * @return GtFNg + * エフェクトを得る + * @return エフェクト */ inline CVstEffect* CVstEditWnd::GetEffect() { diff --git a/windows/commng/vsthost/vsteditwndbase.h b/windows/commng/vsthost/vsteditwndbase.h index 0cd9c76f..a17a22d5 100644 --- a/windows/commng/vsthost/vsteditwndbase.h +++ b/windows/commng/vsthost/vsteditwndbase.h @@ -1,12 +1,12 @@ /** * @file vsteditwndbase.h - * @brief VST edit EBhENX̐錾уC^[tFCX̒`܂ + * @brief VST edit ウィンドウ基底クラスの宣言およびインターフェイスの定義をします */ #pragma once /** - * @brief VST edit EBhENX + * @brief VST edit ウィンドウ基底クラス */ class IVstEditWnd { diff --git a/windows/commng/vsthost/vsteffect.cpp b/windows/commng/vsthost/vsteffect.cpp index d8c5ef76..efb83708 100644 --- a/windows/commng/vsthost/vsteffect.cpp +++ b/windows/commng/vsthost/vsteffect.cpp @@ -1,6 +1,6 @@ /** * @file vsteffect.cpp - * @brief VST effect NX̓̒`s܂ + * @brief VST effect クラスの動作の定義を行います */ #include "compiler.h" @@ -18,11 +18,11 @@ #include #endif // _WIN32 -/*! GtFNg nh[ */ +/*! エフェクト ハンドラー */ std::map CVstEffect::sm_effects; /** - * RXgN^ + * コンストラクタ */ CVstEffect::CVstEffect() : m_effect(NULL) @@ -33,7 +33,7 @@ CVstEffect::CVstEffect() } /** - * fXgN^ + * デストラクタ */ CVstEffect::~CVstEffect() { @@ -41,17 +41,17 @@ CVstEffect::~CVstEffect() } /** - * [h - * @param[in] lpVst vOC - * @retval true - * @retval false s + * ロードする + * @param[in] lpVst プラグイン + * @retval true 成功 + * @retval false 失敗 */ bool CVstEffect::Load(LPCTSTR lpVst) { Unload(); #ifdef _WIN32 - /* VSTiǂݍ */ + /* VSTi読み込み */ HMODULE hModule = ::LoadLibrary(lpVst); if (hModule == NULL) { @@ -69,7 +69,7 @@ bool CVstEffect::Load(LPCTSTR lpVst) return false; } - // + // 初期化 AEffect* effect = (*fnMain)(cAudioMasterCallback); if (effect == NULL) { @@ -91,7 +91,7 @@ bool CVstEffect::Load(LPCTSTR lpVst) #else // _WIN32 - /* VSTiǂݍ */ + /* VSTi読み込み */ void* hModule = ::dlopen(lpVst, 262); if (hModule == NULL) { @@ -109,7 +109,7 @@ bool CVstEffect::Load(LPCTSTR lpVst) return false; } - // + // 初期化 AEffect* effect = (*fnMain)(cAudioMasterCallback); if (effect == NULL) { @@ -145,7 +145,7 @@ bool CVstEffect::Load(LPCTSTR lpVst) } /** - * A[h + * アンロードする */ void CVstEffect::Unload() { @@ -171,9 +171,9 @@ void CVstEffect::Unload() } /** - * EBhE A^b` - * @param[in] pWnd nh - * @return ȑÕnh + * ウィンドウ アタッチ + * @param[in] pWnd ハンドル + * @return 以前のハンドル */ IVstEditWnd* CVstEffect::Attach(IVstEditWnd* pWnd) { @@ -183,7 +183,7 @@ IVstEditWnd* CVstEffect::Attach(IVstEditWnd* pWnd) } /** - * fBXpb` + * ディスパッチ * @param[in] opcode The operation code * @param[in] index The index * @param[in] value The value @@ -201,10 +201,10 @@ VstIntPtr CVstEffect::dispatcher(VstInt32 opcode, VstInt32 index, VstIntPtr valu } /** - * vZX - * @param[in] inputs - * @param[in] outputs o - * @param[in] sampleFrames Tv + * プロセス + * @param[in] inputs 入力 + * @param[in] outputs 出力 + * @param[in] sampleFrames サンプル数 */ void CVstEffect::processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames) { @@ -215,7 +215,7 @@ void CVstEffect::processReplacing(float** inputs, float** outputs, VstInt32 samp } /** - * R[obN + * コールバック * @param[in] effect The instance of effect * @param[in] opcode The operation code * @param[in] index The index @@ -244,7 +244,7 @@ VstIntPtr CVstEffect::cAudioMasterCallback(AEffect* effect, VstInt32 opcode, Vst } /** - * R[obN + * コールバック * @param[in] opcode The operation code * @param[in] index The index * @param[in] value The value diff --git a/windows/commng/vsthost/vsteffect.h b/windows/commng/vsthost/vsteffect.h index 6da63f58..912c1666 100644 --- a/windows/commng/vsthost/vsteffect.h +++ b/windows/commng/vsthost/vsteffect.h @@ -1,6 +1,6 @@ /** * @file vsteffect.h - * @brief VST effect NX̐錾уC^[tFCX̒`܂ + * @brief VST effect クラスの宣言およびインターフェイスの定義をします */ #pragma once @@ -11,7 +11,7 @@ class IVstEditWnd; /** - * @brief VST effect NX + * @brief VST effect クラス */ class CVstEffect { @@ -48,14 +48,14 @@ class CVstEffect private: #if _WIN32 - HMODULE m_hModule; /*!< W[ */ + HMODULE m_hModule; /*!< モジュール */ #else // _WIN32 - void* m_hModule; /*!< W[ */ + void* m_hModule; /*!< モジュール */ #endif - char* m_lpDir; /*!< fBNg */ + char* m_lpDir; /*!< ディレクトリ */ IVstEditWnd* m_pWnd; /*!< Window */ - static std::map sm_effects; /*!< GtFNg nh[ */ + static std::map sm_effects; /*!< エフェクト ハンドラー */ }; /** diff --git a/windows/commng/vsthost/vstmidievent.cpp b/windows/commng/vsthost/vstmidievent.cpp index a493d7f6..25b2f006 100644 --- a/windows/commng/vsthost/vstmidievent.cpp +++ b/windows/commng/vsthost/vstmidievent.cpp @@ -1,6 +1,6 @@ /** * @file vstmidievent.cpp - * @brief VST MIDI NX̓̒`s܂ + * @brief VST MIDI クラスの動作の定義を行います */ #include "compiler.h" @@ -10,7 +10,7 @@ #include "vstmidievent.h" /** - * RXgN^ + * コンストラクタ */ CVstMidiEvent::CVstMidiEvent() : m_nEvents(0) @@ -18,14 +18,14 @@ CVstMidiEvent::CVstMidiEvent() } /** - * fXgN^ + * デストラクタ */ CVstMidiEvent::~CVstMidiEvent() { } /** - * NA + * クリア */ void CVstMidiEvent::Clear() { @@ -35,9 +35,9 @@ void CVstMidiEvent::Clear() } /** - * V[g bZ[W - * @param[in] nTick eBbN - * @param[in] nMessage bZ[W + * ショート メッセージ + * @param[in] nTick ティック + * @param[in] nMessage メッセージ */ void CVstMidiEvent::ShortMessage(UINT nTick, UINT nMessage) { @@ -54,10 +54,10 @@ void CVstMidiEvent::ShortMessage(UINT nTick, UINT nMessage) } /** - * O bZ[W - * @param[in] nTick eBbN - * @param[in] lpMessage bZ[W - * @param[in] cbMessage bZ[W TCY + * ロング メッセージ + * @param[in] nTick ティック + * @param[in] lpMessage メッセージ + * @param[in] cbMessage メッセージ サイズ */ void CVstMidiEvent::LongMessage(UINT nTick, const void* lpMessage, UINT cbMessage) { @@ -72,10 +72,10 @@ void CVstMidiEvent::LongMessage(UINT nTick, const void* lpMessage, UINT cbMessag } /** - * Cxglj - * @param[in] pEvent Cxg - * @param[in] lpMessage ljbZ[W - * @param[in] cbMessage ljbZ[W TCY + * イベント追加 + * @param[in] pEvent イベント + * @param[in] lpMessage 追加メッセージ + * @param[in] cbMessage 追加メッセージ サイズ */ void CVstMidiEvent::Add(const VstEvent* pEvent, const void* lpMessage, UINT cbMessage) { @@ -89,8 +89,8 @@ void CVstMidiEvent::Add(const VstEvent* pEvent, const void* lpMessage, UINT cbMe } /** - * Cxg̍쐬 - * @return Cxg + * イベントの作成 + * @return イベント */ const VstEvents* CVstMidiEvent::GetEvents() { diff --git a/windows/commng/vsthost/vstmidievent.h b/windows/commng/vsthost/vstmidievent.h index 22db7134..f18b21cf 100644 --- a/windows/commng/vsthost/vstmidievent.h +++ b/windows/commng/vsthost/vstmidievent.h @@ -1,6 +1,6 @@ /** * @file vstmidievent.h - * @brief VST MIDI NX̐錾уC^[tFCX̒`܂ + * @brief VST MIDI クラスの宣言およびインターフェイスの定義をします */ #pragma once @@ -9,7 +9,7 @@ #include /** - * @brief VST MIDI NX + * @brief VST MIDI クラス */ class CVstMidiEvent { @@ -24,8 +24,8 @@ class CVstMidiEvent protected: private: - UINT m_nEvents; /*!< Cxg */ - std::vector m_header; /*!< wb_ */ - std::vector m_event; /*!< Cxg */ + UINT m_nEvents; /*!< イベント数 */ + std::vector m_header; /*!< ヘッダ */ + std::vector m_event; /*!< イベント */ void Add(const VstEvent* pEvent, const void* lpMessage = NULL, UINT cbMessage = 0); }; diff --git a/windows/commonfix.h b/windows/commonfix.h old mode 100755 new mode 100644 index e53151cc..ffd25a85 --- a/windows/commonfix.h +++ b/windows/commonfix.h @@ -1,467 +1,467 @@ -/************************************************************************ -* * -* commonfix.h v 2.10-- This module is supported Windows 95/98/Me/2000 * -* on VC++2005/2008/2010 * -* * -* Copyright (c) 2012, BlackWingCat/PFW . All rights reserved. * -* * -* Blog: http://blog.livedoor.jp/blackwingcat/ Twitter:BlackWingCat * -* Usage: * -*#define WINVER2 0x0400 // or 0x0410 or 0x0500 * -*#define DLLMODE // DLL * -*#include "commonfix.h" * -* Add Link Option /FILEALIGN:4096 /MT or /MTd * -* if you want run Win9x with VC2008/VC2010 * -* use fcwin enabled execute flag after link * -************************************************************************/ -#include -#ifdef __cplusplus -extern "C"{ -#endif -#ifdef _CONSOLE -#pragma comment(linker,"/entry:mainCRTStartup2") -#else -#pragma comment(linker,"/entry:WinMainCRTStartup2") -//#pragma comment(lib, "shlwapi.lib") -#endif - -#if (WINVER2 <= 0x0400) - #ifdef _CONSOLE - #pragma comment(linker,"/CONSOLE:Windows,4.00") - #else - #pragma comment(linker,"/SUBSYSTEM:Windows,4.00") - #endif -#else - #if (WINVER2 <= 0x0410) - #ifdef _CONSOLE - #pragma comment(linker,"/CONSOLE:Windows,4.10") - #else - #pragma comment(linker,"/SUBSYSTEM:Windows,4.10") - #endif - #else - #ifdef _CONSOLE - #pragma comment(linker,"/CONSOLE:Windows,5.00") - #else - #pragma comment(linker,"/SUBSYSTEM:Windows,5.00") - #endif - #endif -#endif - - -const char strKERNEL32DLL[]="KERNEL32.DLL"; -#if (WINVER2 <= 0x0400)//WIN95 -#if _MSC_VER >=1400 //VC2005 -const char strIsDebuggerPresent[]="IsDebuggerPresent"; -BOOL _declspec(naked ) WINAPI IsDebuggerPresent_stub(void) -{ - _asm{ - push offset strKERNEL32DLL - call DWORD PTR[GetModuleHandleA] - and eax,eax - jnz L1 - retn -L1: - push offset strIsDebuggerPresent - push eax - call DWORD PTR[GetProcAddress] - and eax,eax - jz L2 - call eax -L2: retn - } -} -int _declspec(naked ) WINAPI _imp__IsDebuggerPresent(void){ - _asm{ - _emit 0xc3 - _emit 0xc3 - _emit 0xc3 - _emit 0xc3 - } -} -#endif//VC2005 -#if _MSC_VER >=1600 //VC2010 -BOOL WINAPI IsProcessorFeaturePresent_stub(DWORD flg1){ - typedef BOOL (WINAPI *IPFP )(DWORD flg1); - IPFP PIPFP=NULL; - HINSTANCE hDll; - hDll=GetModuleHandleA(strKERNEL32DLL); - if(hDll){ - PIPFP=(IPFP)GetProcAddress(hDll,"IsProcessorFeaturePresent"); - } - if(PIPFP==NULL){ - int FP=0; -#define ACPI_FLAG 0x400000 - _asm{ - xor eax,eax - cpuid - cmp eax,0x756e6547 - jnz L1 - mov eax,1 - cpuid - and ah,0xf - cmp ah,5 - jnz L1 - and al,0xf0 - cmp al,0x20 - jz L2 - cmp al,0x70 - jnz L1 -L2: - or FP,1<=1500 //VC2008 - -typedef BOOL (WINAPI *ICSAC)(HANDLE flg1,int flg2); -BOOL WINAPI InitializeCriticalSectionAndSpinCount_stub(HANDLE flg1,DWORD flg2){ - ICSAC PICSAC=NULL; - HINSTANCE hDll; - hDll=GetModuleHandleA(strKERNEL32DLL); - if(hDll){ - PICSAC=(ICSAC)GetProcAddress(hDll,"InitializeCriticalSectionAndSpinCount"); - } - if((GetVersion()&0xf)<5 || PICSAC==NULL){ - InitializeCriticalSection((LPCRITICAL_SECTION)flg1); - return 1; - } - return PICSAC(flg1,flg2); -} -typedef BOOL (WINAPI *HSIS )(HANDLE flg1,int flg2,void *flg3,DWORD flg4); -BOOL WINAPI HeapSetInformation_stub(HANDLE flg1,int flg2,void *flg3,DWORD flg4){ - HSIS PHSIS; - HINSTANCE hDll; - hDll=GetModuleHandleA(strKERNEL32DLL); - if(hDll){ - PHSIS=(HSIS)GetProcAddress(hDll,"HeapSetInformation"); - if(PHSIS){ - return PHSIS(flg1,flg2,flg3,flg4); - } - } - return 0; - -} -typedef BOOL (WINAPI *HQIS )(HANDLE flg1,int flg2,void*flg3,DWORD flg4,DWORD *flg5); -BOOL WINAPI HeapQueryInformation_stub(HANDLE flg1,int flg2,void*flg3,DWORD flg4,DWORD *flg5){ - HQIS PHQIS; - HINSTANCE hDll; - hDll=GetModuleHandleA(strKERNEL32DLL); - if(hDll){ - PHQIS=(HQIS)GetProcAddress(hDll,"HeapQueryInformation"); - if(PHQIS){ - return PHQIS(flg1,flg2,flg3,flg4,flg5); - } - } - return 0; -} -int _declspec(naked ) WINAPI _imp__InitializeCriticalSectionAndSpinCount( void* flg1, - DWORD flg2) -{ - _asm{ - _emit 0x90 - _emit 0x90 - _emit 0xc3 - _emit 0x90 - } -} -int _declspec(naked ) WINAPI _imp__HeapSetInformation( HANDLE flg1,int flg2,void *flg3,DWORD flg4) -{ - _asm{ - _emit 0x33 - _emit 0xc0 - _emit 0xc3 - _emit 0x90 - } -} -int _declspec(naked ) WINAPI _imp__HeapQueryInformation( HANDLE flg1,int flg2,void*flg3,DWORD flg4,DWORD *flg5) -{ - _asm{ - _emit 0x33 - _emit 0xc0 - _emit 0x90 - _emit 0xc3 - } -} -#endif//VC2008 -#endif//WINME - - -#if _MSC_VER >=1600 //VC2010 -int _declspec(naked ) WINAPI _imp__FindActCtxSectionStringA( int flg1, - int flg2, - int flg3, - wchar_t *pszFilename, - void *data) -{ - _asm{ - _emit 0x33 - _emit 0xc0 - _emit 0xc3 - _emit 0xc3 - } -} -int _declspec(naked ) WINAPI _imp__FindActCtxSectionStringW( int flg1, - int flg2, - int flg3, - wchar_t *pszFilename, - void *data) -{ - _asm{ - _emit 0xc3 - _emit 0x33 - _emit 0xc0 - _emit 0xc3 - } -} -int _declspec(naked ) WINAPI _imp__EncodePointer( int flg1) -{ - _asm{ - _emit 0xc3 - _emit 0xc3 - _emit 0x33 - _emit 0xc0 - } -} -int _declspec(naked ) WINAPI _imp__DecodePointer( int flg1) -{ - _asm{ - _emit 0x33 - _emit 0xc0 - _emit 0x33 - _emit 0xc0 - } -} -#endif//VC2010 -#endif//Win2000 - -void initialize_findacx -(){ -// LoadLibraryA("unicows.lib"); - FARPROC i; - DWORD dw; -#if (WINVER2 <= 0x0400) //Win95 -#if _MSC_VER >=1400 //VC2005 - i=(FARPROC)&_imp__IsDebuggerPresent; - VirtualProtect(i, sizeof(FARPROC), PAGE_EXECUTE_READWRITE , &dw); - *(FARPROC*)i=(FARPROC)&IsDebuggerPresent_stub; - VirtualProtect(i, sizeof(FARPROC), dw, &dw); -#if _MSC_VER >=1600 //VC2010 - i=(FARPROC)&_imp__IsProcessorFeaturePresent; - VirtualProtect(i, sizeof(FARPROC), PAGE_EXECUTE_READWRITE , &dw); - *(FARPROC*)i=(FARPROC)&IsProcessorFeaturePresent_stub; - VirtualProtect(i, sizeof(FARPROC), dw, &dw); -#endif//VC2010 -#endif//VC2005 -#endif//Win95 - -#if _MSC_VER >=1600 //VC2010 - i=(FARPROC)& _imp__FindActCtxSectionStringW; - VirtualProtect(i, sizeof(FARPROC), PAGE_EXECUTE_READWRITE , &dw); - *(FARPROC*) - i=(FARPROC)&FindActCtxSectionStringW_stub; - VirtualProtect(i, sizeof(FARPROC), dw, &dw); - - i=(FARPROC)&_imp__FindActCtxSectionStringA; - VirtualProtect(i, sizeof(FARPROC), PAGE_EXECUTE_READWRITE , &dw); - *(FARPROC*)i=(FARPROC)&FindActCtxSectionStringA_stub; - VirtualProtect(i, sizeof(FARPROC), dw, &dw); - - i=(FARPROC)&_imp__EncodePointer; - VirtualProtect(i, sizeof(FARPROC), PAGE_EXECUTE_READWRITE , &dw); - *(FARPROC*)i=(FARPROC)&EncodePointer_stub; - VirtualProtect(i, sizeof(FARPROC), dw, &dw); - - i=(FARPROC)&_imp__DecodePointer; - VirtualProtect(i, sizeof(FARPROC),PAGE_EXECUTE_READWRITE , &dw); - *(FARPROC*)i=(FARPROC)&DecodePointer_stub; - VirtualProtect(i, sizeof(FARPROC), dw, &dw); -#endif //VC2010 -#if _MSC_VER >=1500 //VC2008 -#if (WINVER2 < 0x0500) //WinMe - i=(FARPROC)&_imp__HeapQueryInformation; - VirtualProtect(i, sizeof(FARPROC),PAGE_EXECUTE_READWRITE , &dw); - *(FARPROC*)i=(FARPROC)&HeapQueryInformation_stub; - VirtualProtect(i, sizeof(FARPROC), dw, &dw); - - i=(FARPROC)&_imp__HeapSetInformation; - VirtualProtect(i, sizeof(FARPROC),PAGE_EXECUTE_READWRITE , &dw); - *(FARPROC*)i=(FARPROC)&HeapSetInformation_stub; - VirtualProtect(i, sizeof(FARPROC), dw, &dw); - - i=(FARPROC)&_imp__InitializeCriticalSectionAndSpinCount; - VirtualProtect(i, sizeof(FARPROC),PAGE_EXECUTE_READWRITE , &dw); - *(FARPROC*)i=(FARPROC)&InitializeCriticalSectionAndSpinCount_stub; - VirtualProtect(i, sizeof(FARPROC), dw, &dw); -#endif//Me -#endif//VC2008 -} - -#ifdef DLLMODE -int WINAPI _DllMainCRTStartup(int hm,int rs,void *rev); -int WINAPI WinMainCRTStartup2(int hm,int rs,void *rev) -{ - if(rs==DLL_PROCESS_ATTACH) - initialize_findacx(); - return _DllMainCRTStartup(hm,rs,rev); - -} -#else -#ifdef _CONSOLE -extern void wmainCRTStartup(); -extern void mainCRTStartup(); -void mainCRTStartup2() -{ - initialize_findacx(); -#ifdef _UNICODE - wmainCRTStartup(); -#else - mainCRTStartup(); -#endif -} -#else/ /CONSOLE -//extern void wWinMainCRTStartup(); -extern void WinMainCRTStartup(); -void WinMainCRTStartup2() -{ - initialize_findacx(); -#ifdef _UNICODE - WinMainCRTStartup(); // Unicodeだけどw不要 -#else - WinMainCRTStartup(); -#endif -} -#endif - -#endif//DLLMODE - - -#ifdef __cplusplus -} -#endif - +/************************************************************************ +* * +* commonfix.h v 2.10-- This module is supported Windows 95/98/Me/2000 * +* on VC++2005/2008/2010 * +* * +* Copyright (c) 2012, BlackWingCat/PFW . All rights reserved. * +* * +* Blog: http://blog.livedoor.jp/blackwingcat/ Twitter:BlackWingCat * +* Usage: * +*#define WINVER2 0x0400 // or 0x0410 or 0x0500 * +*#define DLLMODE // DLL * +*#include "commonfix.h" * +* Add Link Option /FILEALIGN:4096 /MT or /MTd * +* if you want run Win9x with VC2008/VC2010 * +* use fcwin enabled execute flag after link * +************************************************************************/ +#include +#ifdef __cplusplus +extern "C"{ +#endif +#ifdef _CONSOLE +#pragma comment(linker,"/entry:mainCRTStartup2") +#else +#pragma comment(linker,"/entry:WinMainCRTStartup2") +//#pragma comment(lib, "shlwapi.lib") +#endif + +#if (WINVER2 <= 0x0400) + #ifdef _CONSOLE + #pragma comment(linker,"/CONSOLE:Windows,4.00") + #else + #pragma comment(linker,"/SUBSYSTEM:Windows,4.00") + #endif +#else + #if (WINVER2 <= 0x0410) + #ifdef _CONSOLE + #pragma comment(linker,"/CONSOLE:Windows,4.10") + #else + #pragma comment(linker,"/SUBSYSTEM:Windows,4.10") + #endif + #else + #ifdef _CONSOLE + #pragma comment(linker,"/CONSOLE:Windows,5.00") + #else + #pragma comment(linker,"/SUBSYSTEM:Windows,5.00") + #endif + #endif +#endif + + +const char strKERNEL32DLL[]="KERNEL32.DLL"; +#if (WINVER2 <= 0x0400)//WIN95 +#if _MSC_VER >=1400 //VC2005 +const char strIsDebuggerPresent[]="IsDebuggerPresent"; +BOOL _declspec(naked ) WINAPI IsDebuggerPresent_stub(void) +{ + _asm{ + push offset strKERNEL32DLL + call DWORD PTR[GetModuleHandleA] + and eax,eax + jnz L1 + retn +L1: + push offset strIsDebuggerPresent + push eax + call DWORD PTR[GetProcAddress] + and eax,eax + jz L2 + call eax +L2: retn + } +} +int _declspec(naked ) WINAPI _imp__IsDebuggerPresent(void){ + _asm{ + _emit 0xc3 + _emit 0xc3 + _emit 0xc3 + _emit 0xc3 + } +} +#endif//VC2005 +#if _MSC_VER >=1600 //VC2010 +BOOL WINAPI IsProcessorFeaturePresent_stub(DWORD flg1){ + typedef BOOL (WINAPI *IPFP )(DWORD flg1); + IPFP PIPFP=NULL; + HINSTANCE hDll; + hDll=GetModuleHandleA(strKERNEL32DLL); + if(hDll){ + PIPFP=(IPFP)GetProcAddress(hDll,"IsProcessorFeaturePresent"); + } + if(PIPFP==NULL){ + int FP=0; +#define ACPI_FLAG 0x400000 + _asm{ + xor eax,eax + cpuid + cmp eax,0x756e6547 + jnz L1 + mov eax,1 + cpuid + and ah,0xf + cmp ah,5 + jnz L1 + and al,0xf0 + cmp al,0x20 + jz L2 + cmp al,0x70 + jnz L1 +L2: + or FP,1<=1500 //VC2008 + +typedef BOOL (WINAPI *ICSAC)(HANDLE flg1,int flg2); +BOOL WINAPI InitializeCriticalSectionAndSpinCount_stub(HANDLE flg1,DWORD flg2){ + ICSAC PICSAC=NULL; + HINSTANCE hDll; + hDll=GetModuleHandleA(strKERNEL32DLL); + if(hDll){ + PICSAC=(ICSAC)GetProcAddress(hDll,"InitializeCriticalSectionAndSpinCount"); + } + if((GetVersion()&0xf)<5 || PICSAC==NULL){ + InitializeCriticalSection((LPCRITICAL_SECTION)flg1); + return 1; + } + return PICSAC(flg1,flg2); +} +typedef BOOL (WINAPI *HSIS )(HANDLE flg1,int flg2,void *flg3,DWORD flg4); +BOOL WINAPI HeapSetInformation_stub(HANDLE flg1,int flg2,void *flg3,DWORD flg4){ + HSIS PHSIS; + HINSTANCE hDll; + hDll=GetModuleHandleA(strKERNEL32DLL); + if(hDll){ + PHSIS=(HSIS)GetProcAddress(hDll,"HeapSetInformation"); + if(PHSIS){ + return PHSIS(flg1,flg2,flg3,flg4); + } + } + return 0; + +} +typedef BOOL (WINAPI *HQIS )(HANDLE flg1,int flg2,void*flg3,DWORD flg4,DWORD *flg5); +BOOL WINAPI HeapQueryInformation_stub(HANDLE flg1,int flg2,void*flg3,DWORD flg4,DWORD *flg5){ + HQIS PHQIS; + HINSTANCE hDll; + hDll=GetModuleHandleA(strKERNEL32DLL); + if(hDll){ + PHQIS=(HQIS)GetProcAddress(hDll,"HeapQueryInformation"); + if(PHQIS){ + return PHQIS(flg1,flg2,flg3,flg4,flg5); + } + } + return 0; +} +int _declspec(naked ) WINAPI _imp__InitializeCriticalSectionAndSpinCount( void* flg1, + DWORD flg2) +{ + _asm{ + _emit 0x90 + _emit 0x90 + _emit 0xc3 + _emit 0x90 + } +} +int _declspec(naked ) WINAPI _imp__HeapSetInformation( HANDLE flg1,int flg2,void *flg3,DWORD flg4) +{ + _asm{ + _emit 0x33 + _emit 0xc0 + _emit 0xc3 + _emit 0x90 + } +} +int _declspec(naked ) WINAPI _imp__HeapQueryInformation( HANDLE flg1,int flg2,void*flg3,DWORD flg4,DWORD *flg5) +{ + _asm{ + _emit 0x33 + _emit 0xc0 + _emit 0x90 + _emit 0xc3 + } +} +#endif//VC2008 +#endif//WINME + + +#if _MSC_VER >=1600 //VC2010 +int _declspec(naked ) WINAPI _imp__FindActCtxSectionStringA( int flg1, + int flg2, + int flg3, + wchar_t *pszFilename, + void *data) +{ + _asm{ + _emit 0x33 + _emit 0xc0 + _emit 0xc3 + _emit 0xc3 + } +} +int _declspec(naked ) WINAPI _imp__FindActCtxSectionStringW( int flg1, + int flg2, + int flg3, + wchar_t *pszFilename, + void *data) +{ + _asm{ + _emit 0xc3 + _emit 0x33 + _emit 0xc0 + _emit 0xc3 + } +} +int _declspec(naked ) WINAPI _imp__EncodePointer( int flg1) +{ + _asm{ + _emit 0xc3 + _emit 0xc3 + _emit 0x33 + _emit 0xc0 + } +} +int _declspec(naked ) WINAPI _imp__DecodePointer( int flg1) +{ + _asm{ + _emit 0x33 + _emit 0xc0 + _emit 0x33 + _emit 0xc0 + } +} +#endif//VC2010 +#endif//Win2000 + +void initialize_findacx +(){ +// LoadLibraryA("unicows.lib"); + FARPROC i; + DWORD dw; +#if (WINVER2 <= 0x0400) //Win95 +#if _MSC_VER >=1400 //VC2005 + i=(FARPROC)&_imp__IsDebuggerPresent; + VirtualProtect(i, sizeof(FARPROC), PAGE_EXECUTE_READWRITE , &dw); + *(FARPROC*)i=(FARPROC)&IsDebuggerPresent_stub; + VirtualProtect(i, sizeof(FARPROC), dw, &dw); +#if _MSC_VER >=1600 //VC2010 + i=(FARPROC)&_imp__IsProcessorFeaturePresent; + VirtualProtect(i, sizeof(FARPROC), PAGE_EXECUTE_READWRITE , &dw); + *(FARPROC*)i=(FARPROC)&IsProcessorFeaturePresent_stub; + VirtualProtect(i, sizeof(FARPROC), dw, &dw); +#endif//VC2010 +#endif//VC2005 +#endif//Win95 + +#if _MSC_VER >=1600 //VC2010 + i=(FARPROC)& _imp__FindActCtxSectionStringW; + VirtualProtect(i, sizeof(FARPROC), PAGE_EXECUTE_READWRITE , &dw); + *(FARPROC*) + i=(FARPROC)&FindActCtxSectionStringW_stub; + VirtualProtect(i, sizeof(FARPROC), dw, &dw); + + i=(FARPROC)&_imp__FindActCtxSectionStringA; + VirtualProtect(i, sizeof(FARPROC), PAGE_EXECUTE_READWRITE , &dw); + *(FARPROC*)i=(FARPROC)&FindActCtxSectionStringA_stub; + VirtualProtect(i, sizeof(FARPROC), dw, &dw); + + i=(FARPROC)&_imp__EncodePointer; + VirtualProtect(i, sizeof(FARPROC), PAGE_EXECUTE_READWRITE , &dw); + *(FARPROC*)i=(FARPROC)&EncodePointer_stub; + VirtualProtect(i, sizeof(FARPROC), dw, &dw); + + i=(FARPROC)&_imp__DecodePointer; + VirtualProtect(i, sizeof(FARPROC),PAGE_EXECUTE_READWRITE , &dw); + *(FARPROC*)i=(FARPROC)&DecodePointer_stub; + VirtualProtect(i, sizeof(FARPROC), dw, &dw); +#endif //VC2010 +#if _MSC_VER >=1500 //VC2008 +#if (WINVER2 < 0x0500) //WinMe + i=(FARPROC)&_imp__HeapQueryInformation; + VirtualProtect(i, sizeof(FARPROC),PAGE_EXECUTE_READWRITE , &dw); + *(FARPROC*)i=(FARPROC)&HeapQueryInformation_stub; + VirtualProtect(i, sizeof(FARPROC), dw, &dw); + + i=(FARPROC)&_imp__HeapSetInformation; + VirtualProtect(i, sizeof(FARPROC),PAGE_EXECUTE_READWRITE , &dw); + *(FARPROC*)i=(FARPROC)&HeapSetInformation_stub; + VirtualProtect(i, sizeof(FARPROC), dw, &dw); + + i=(FARPROC)&_imp__InitializeCriticalSectionAndSpinCount; + VirtualProtect(i, sizeof(FARPROC),PAGE_EXECUTE_READWRITE , &dw); + *(FARPROC*)i=(FARPROC)&InitializeCriticalSectionAndSpinCount_stub; + VirtualProtect(i, sizeof(FARPROC), dw, &dw); +#endif//Me +#endif//VC2008 +} + +#ifdef DLLMODE +int WINAPI _DllMainCRTStartup(int hm,int rs,void *rev); +int WINAPI WinMainCRTStartup2(int hm,int rs,void *rev) +{ + if(rs==DLL_PROCESS_ATTACH) + initialize_findacx(); + return _DllMainCRTStartup(hm,rs,rev); + +} +#else +#ifdef _CONSOLE +extern void wmainCRTStartup(); +extern void mainCRTStartup(); +void mainCRTStartup2() +{ + initialize_findacx(); +#ifdef _UNICODE + wmainCRTStartup(); +#else + mainCRTStartup(); +#endif +} +#else/ /CONSOLE +//extern void wWinMainCRTStartup(); +extern void WinMainCRTStartup(); +void WinMainCRTStartup2() +{ + initialize_findacx(); +#ifdef _UNICODE + WinMainCRTStartup(); // Unicodeだけどw不要 +#else + WinMainCRTStartup(); +#endif +} +#endif + +#endif//DLLMODE + + +#ifdef __cplusplus +} +#endif + diff --git a/windows/compiler.cpp b/windows/compiler.cpp old mode 100755 new mode 100644 index 1a029d0e..dd9152cb --- a/windows/compiler.cpp +++ b/windows/compiler.cpp @@ -1,5 +1,5 @@ -// compiler.cpp : 標準インクルードファイルを含むソース ファイル -// np2.pch : 生成されるプリコンパイル済ヘッダー -// compiler.obj : 生成されるプリコンパイル済タイプ情報 - -#include +// compiler.cpp : 標準インクルードファイルを含むソース ファイル +// np2.pch : 生成されるプリコンパイル済ヘッダー +// compiler.obj : 生成されるプリコンパイル済タイプ情報 + +#include diff --git a/windows/compiler.h b/windows/compiler.h old mode 100755 new mode 100644 index 2a8ed977..f318434b --- a/windows/compiler.h +++ b/windows/compiler.h @@ -1,81 +1,81 @@ -/** - * @file compiler.h - * @brief include file for standard system include files, - * or project specific include files that are used frequently, - * but are changed infrequently - * - * @author $Author: yui $ - * @date $Date: 2011/03/09 00:22:18 $ - */ - -#ifndef COMPILER_H -#define COMPILER_H - -#include "compiler_base.h" - -#include "targetver.h" -#define _USE_MATH_DEFINES -//#include -/* workaround for VC6 (definition missing in the header) */ -#if (_MSC_VER + 0) <= 1200 -# ifdef __cplusplus -extern "C" { -# endif -WINBASEAPI BOOL WINAPI SetFilePointerEx(HANDLE, LARGE_INTEGER, PLARGE_INTEGER, DWORD); -# ifdef __cplusplus -} -# endif -#endif -#if defined(TRACE) -#include -#endif - -#if !defined(LLONG_MIN) -# define LLONG_MIN (SINT64)(QWORD_CONST(1)<<63) -#endif - -#if !defined(__GNUC__) -#define sigjmp_buf jmp_buf -#define sigsetjmp(env, mask) setjmp(env) -#define siglongjmp(env, val) longjmp(env, val) -#endif // !defined(__GNUC__) -#define msgbox(title, msg) MessageBoxA(NULL, msg, title, MB_OK) - -#include "misc\tickcounter.h" -#include "misc\vc6macros.h" - -#define GETTICK() GetTickCounter() -#if defined(TRACE) -#define __ASSERT(s) assert(s) -#else -#define __ASSERT(s) -#endif - -#define LABEL __declspec(naked) -#define RELEASE(x) if (x) {(x)->Release(); (x) = NULL;} - -#if (_MSC_VER >= 1500) -#define SUPPORT_WASAPI -#endif /* (_MSC_VER >= 1500) */ - -#if defined(CPUCORE_IA32) -#pragma warning(disable: 4819) -#endif - -#if (_MSC_VER >= 1400) -#if defined _M_IX86 -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") -#elif defined _M_IA64 -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") -#elif defined _M_X64 -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") -#else -#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") -#endif -#endif /* (_MSC_VER >= 1400) */ - -#include -#include - -#endif // COMPILER_H - +/** + * @file compiler.h + * @brief include file for standard system include files, + * or project specific include files that are used frequently, + * but are changed infrequently + * + * @author $Author: yui $ + * @date $Date: 2011/03/09 00:22:18 $ + */ + +#ifndef COMPILER_H +#define COMPILER_H + +#include "compiler_base.h" + +#include "targetver.h" +#define _USE_MATH_DEFINES +//#include +/* workaround for VC6 (definition missing in the header) */ +#if (_MSC_VER + 0) <= 1200 +# ifdef __cplusplus +extern "C" { +# endif +WINBASEAPI BOOL WINAPI SetFilePointerEx(HANDLE, LARGE_INTEGER, PLARGE_INTEGER, DWORD); +# ifdef __cplusplus +} +# endif +#endif +#if defined(TRACE) +#include +#endif + +#if !defined(LLONG_MIN) +# define LLONG_MIN (SINT64)(QWORD_CONST(1)<<63) +#endif + +#if !defined(__GNUC__) +#define sigjmp_buf jmp_buf +#define sigsetjmp(env, mask) setjmp(env) +#define siglongjmp(env, val) longjmp(env, val) +#endif // !defined(__GNUC__) +#define msgbox(title, msg) MessageBoxA(NULL, msg, title, MB_OK) + +#include "misc\tickcounter.h" +#include "misc\vc6macros.h" + +#define GETTICK() GetTickCounter() +#if defined(TRACE) +#define __ASSERT(s) assert(s) +#else +#define __ASSERT(s) +#endif + +#define LABEL __declspec(naked) +#define RELEASE(x) if (x) {(x)->Release(); (x) = NULL;} + +#if (_MSC_VER >= 1500) +#define SUPPORT_WASAPI +#endif /* (_MSC_VER >= 1500) */ + +#if defined(CPUCORE_IA32) +#pragma warning(disable: 4819) +#endif + +#if (_MSC_VER >= 1400) +#if defined _M_IX86 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_IA64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_X64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#else +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif +#endif /* (_MSC_VER >= 1400) */ + +#include +#include + +#endif // COMPILER_H + diff --git a/windows/debuguty/view1mb.cpp b/windows/debuguty/view1mb.cpp old mode 100755 new mode 100644 index 4a0bdcb2..6b4ea770 --- a/windows/debuguty/view1mb.cpp +++ b/windows/debuguty/view1mb.cpp @@ -1,162 +1,162 @@ -/** - * @file view1mb.cpp - * @brief メイン メモリ表示クラスの動作の定義を行います - */ - -#include -#include "resource.h" -#include -#include "view1mb.h" -#include "viewer.h" -#include - -/** - * コンストラクタ - * @param[in] lpView ビューワ インスタンス - */ -CDebugUty1MB::CDebugUty1MB(CDebugUtyView* lpView) - : CDebugUtyItem(lpView, IDM_VIEWMODE1MB) -{ -} - -/** - * デストラクタ - */ -CDebugUty1MB::~CDebugUty1MB() -{ -} - -/** - * 初期化 - * @param[in] lpItem 基準となるアイテム - */ -void CDebugUty1MB::Initialize(const CDebugUtyItem* lpItem) -{ - m_lpView->SetVScroll(0, 0x10fff); -} - -/** - * 更新 - * @retval true 更新あり - * @retval false 更新なし - */ -bool CDebugUty1MB::Update() -{ - if (!m_buffer.empty()) - { - return false; - } - m_mem.Update(); - return true; -} - -/** - * ロック - * @retval true 成功 - * @retval false 失敗 - */ -bool CDebugUty1MB::Lock() -{ - m_buffer.resize(0x10fff0); - - m_mem.Update(); - m_mem.Read(0, &m_buffer.at(0), static_cast(m_buffer.size())); - return true; -} - -/** - * アンロック - */ -void CDebugUty1MB::Unlock() -{ - m_buffer.clear(); -} - -/** - * ロック中? - * @retval true ロック中である - * @retval false ロック中でない - */ -bool CDebugUty1MB::IsLocked() -{ - return (!m_buffer.empty()); -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - * @retval FALSE アプリケーションがこのメッセージを処理しなかった - */ -BOOL CDebugUty1MB::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDM_SEGCS: - SetSegment(CPU_CS); - break; - - case IDM_SEGDS: - SetSegment(CPU_DS); - break; - - case IDM_SEGES: - SetSegment(CPU_ES); - break; - - case IDM_SEGSS: - SetSegment(CPU_SS); - break; - - case IDM_SEGTEXT: - SetSegment(0xa000); - break; - - default: - return FALSE; - - } - return TRUE; -} - -/** - * セグメント変更 - * @param[in] nSegment セグメント - */ -void CDebugUty1MB::SetSegment(UINT nSegment) -{ - m_lpView->SetVScrollPos(nSegment); -} - -/** - * 描画 - * @param[in] hDC デバイス コンテキスト - * @param[in] rect 領域 - */ -void CDebugUty1MB::OnPaint(HDC hDC, const RECT& rect) -{ - UINT nIndex = m_lpView->GetVScrollPos(); - for (int y = 0; (y < rect.bottom) && (nIndex < 0x10fff); y += 16, nIndex++) - { - TCHAR szTmp[16]; - ::wsprintf(szTmp, _T("%08x:"), nIndex << 4); - ::TextOut(hDC, 0, y, szTmp, 9); - - unsigned char sBuf[16]; - if (!m_buffer.empty()) - { - CopyMemory(sBuf, &m_buffer.at(nIndex << 4), sizeof(sBuf)); - } - else - { - m_mem.Read(nIndex << 4, sBuf, sizeof(sBuf)); - } - for (int x = 0; x < 16; x++) - { - TCHAR szTmp[4]; - ::wsprintf(szTmp, TEXT("%02X"), sBuf[x]); - ::TextOut(hDC, ((x * 3) + 10) * 8, y, szTmp, 2); - } - } -} +/** + * @file view1mb.cpp + * @brief メイン メモリ表示クラスの動作の定義を行います + */ + +#include +#include "resource.h" +#include +#include "view1mb.h" +#include "viewer.h" +#include + +/** + * コンストラクタ + * @param[in] lpView ビューワ インスタンス + */ +CDebugUty1MB::CDebugUty1MB(CDebugUtyView* lpView) + : CDebugUtyItem(lpView, IDM_VIEWMODE1MB) +{ +} + +/** + * デストラクタ + */ +CDebugUty1MB::~CDebugUty1MB() +{ +} + +/** + * 初期化 + * @param[in] lpItem 基準となるアイテム + */ +void CDebugUty1MB::Initialize(const CDebugUtyItem* lpItem) +{ + m_lpView->SetVScroll(0, 0x10fff); +} + +/** + * 更新 + * @retval true 更新あり + * @retval false 更新なし + */ +bool CDebugUty1MB::Update() +{ + if (!m_buffer.empty()) + { + return false; + } + m_mem.Update(); + return true; +} + +/** + * ロック + * @retval true 成功 + * @retval false 失敗 + */ +bool CDebugUty1MB::Lock() +{ + m_buffer.resize(0x10fff0); + + m_mem.Update(); + m_mem.Read(0, &m_buffer.at(0), static_cast(m_buffer.size())); + return true; +} + +/** + * アンロック + */ +void CDebugUty1MB::Unlock() +{ + m_buffer.clear(); +} + +/** + * ロック中? + * @retval true ロック中である + * @retval false ロック中でない + */ +bool CDebugUty1MB::IsLocked() +{ + return (!m_buffer.empty()); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + * @retval FALSE アプリケーションがこのメッセージを処理しなかった + */ +BOOL CDebugUty1MB::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDM_SEGCS: + SetSegment(CPU_CS); + break; + + case IDM_SEGDS: + SetSegment(CPU_DS); + break; + + case IDM_SEGES: + SetSegment(CPU_ES); + break; + + case IDM_SEGSS: + SetSegment(CPU_SS); + break; + + case IDM_SEGTEXT: + SetSegment(0xa000); + break; + + default: + return FALSE; + + } + return TRUE; +} + +/** + * セグメント変更 + * @param[in] nSegment セグメント + */ +void CDebugUty1MB::SetSegment(UINT nSegment) +{ + m_lpView->SetVScrollPos(nSegment); +} + +/** + * 描画 + * @param[in] hDC デバイス コンテキスト + * @param[in] rect 領域 + */ +void CDebugUty1MB::OnPaint(HDC hDC, const RECT& rect) +{ + UINT nIndex = m_lpView->GetVScrollPos(); + for (int y = 0; (y < rect.bottom) && (nIndex < 0x10fff); y += 16, nIndex++) + { + TCHAR szTmp[16]; + ::wsprintf(szTmp, _T("%08x:"), nIndex << 4); + ::TextOut(hDC, 0, y, szTmp, 9); + + unsigned char sBuf[16]; + if (!m_buffer.empty()) + { + CopyMemory(sBuf, &m_buffer.at(nIndex << 4), sizeof(sBuf)); + } + else + { + m_mem.Read(nIndex << 4, sBuf, sizeof(sBuf)); + } + for (int x = 0; x < 16; x++) + { + TCHAR szTmp[4]; + ::wsprintf(szTmp, TEXT("%02X"), sBuf[x]); + ::TextOut(hDC, ((x * 3) + 10) * 8, y, szTmp, 2); + } + } +} diff --git a/windows/debuguty/view1mb.h b/windows/debuguty/view1mb.h old mode 100755 new mode 100644 index 306b8861..77d7675e --- a/windows/debuguty/view1mb.h +++ b/windows/debuguty/view1mb.h @@ -1,33 +1,33 @@ -/** - * @file view1mb.h - * @brief メイン メモリ レジスタ表示クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include "viewitem.h" -#include "viewmem.h" - -/** - * @brief メモリ レジスタ表示クラス - */ -class CDebugUty1MB : public CDebugUtyItem -{ -public: - CDebugUty1MB(CDebugUtyView* lpView); - virtual ~CDebugUty1MB(); - - virtual void Initialize(const CDebugUtyItem* lpItem = NULL); - virtual bool Update(); - virtual bool Lock(); - virtual void Unlock(); - virtual bool IsLocked(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual void OnPaint(HDC hDC, const RECT& rect); - -private: - DebugUtyViewMemory m_mem; //!< メモリ - std::vector m_buffer; //!< バッファ - void SetSegment(UINT nSegment); -}; +/** + * @file view1mb.h + * @brief メイン メモリ レジスタ表示クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include "viewitem.h" +#include "viewmem.h" + +/** + * @brief メモリ レジスタ表示クラス + */ +class CDebugUty1MB : public CDebugUtyItem +{ +public: + CDebugUty1MB(CDebugUtyView* lpView); + virtual ~CDebugUty1MB(); + + virtual void Initialize(const CDebugUtyItem* lpItem = NULL); + virtual bool Update(); + virtual bool Lock(); + virtual void Unlock(); + virtual bool IsLocked(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void OnPaint(HDC hDC, const RECT& rect); + +private: + DebugUtyViewMemory m_mem; //!< メモリ + std::vector m_buffer; //!< バッファ + void SetSegment(UINT nSegment); +}; diff --git a/windows/debuguty/viewasm.cpp b/windows/debuguty/viewasm.cpp old mode 100755 new mode 100644 index c7c1d937..f440dfc4 --- a/windows/debuguty/viewasm.cpp +++ b/windows/debuguty/viewasm.cpp @@ -1,182 +1,182 @@ -/** - * @file viewasm.cpp - * @brief アセンブラ リスト表示クラスの動作の定義を行います - */ - -#include -#include "resource.h" -#include -#include "viewasm.h" -#include "viewer.h" -#include -#include - -/** - * コンストラクタ - * @param[in] lpView ビューワ インスタンス - */ -CDebugUtyAsm::CDebugUtyAsm(CDebugUtyView* lpView) - : CDebugUtyItem(lpView, IDM_VIEWMODEASM) - , m_nSegment(0) - , m_nOffset(0) -{ -} - -/** - * デストラクタ - */ -CDebugUtyAsm::~CDebugUtyAsm() -{ -} - -/** - * 初期化 - * @param[in] lpItem 基準となるアイテム - */ -void CDebugUtyAsm::Initialize(const CDebugUtyItem* lpItem) -{ - m_nSegment = CPU_CS; - m_nOffset = CPU_IP; - m_lpView->SetVScroll(0, 0x1000); -} - -/** - * 更新 - * @retval true 更新あり - * @retval false 更新なし - */ -bool CDebugUtyAsm::Update() -{ - if (!m_buffer.empty()) - { - return false; - } - - m_nSegment = CPU_CS; - m_nOffset = CPU_IP; - m_lpView->SetVScrollPos(0); - m_mem.Update(); - m_address.clear(); - return true; -} - -/** - * ロック - * @retval true 成功 - * @retval false 失敗 - */ -bool CDebugUtyAsm::Lock() -{ - m_buffer.resize(0x10000); - m_address.clear(); - - m_mem.Update(); - m_mem.Read(m_nSegment << 4, &m_buffer.at(0), static_cast(m_buffer.size())); - return true; -} - -/** - * アンロック - */ -void CDebugUtyAsm::Unlock() -{ - m_buffer.clear(); - m_address.clear(); -} - -/** - * ロック中? - * @retval true ロック中である - * @retval false ロック中でない - */ -bool CDebugUtyAsm::IsLocked() -{ - return (!m_buffer.empty()); -} - -/** - * 描画 - * @param[in] hDC デバイス コンテキスト - * @param[in] rect 領域 - */ -void CDebugUtyAsm::OnPaint(HDC hDC, const RECT& rect) -{ - UINT nIndex = m_lpView->GetVScrollPos(); - - if (m_address.size() < nIndex) - { - UINT nOffset = (!m_address.empty()) ? m_address.back() : m_nOffset; - do - { - unsigned char sBuf[16]; - ReadMemory(nOffset, sBuf, sizeof(sBuf)); - - UINT nStep = ::unasm(NULL, sBuf, sizeof(sBuf), FALSE, nOffset); - if (nStep == 0) - { - return; - } - - nOffset = (nOffset + nStep) & 0xffff; - m_address.push_back(nOffset); - } while (m_address.size() < nIndex); - } - - UINT nOffset = (nIndex) ? m_address[nIndex - 1] : m_nOffset; - for (int y = 0; (y < rect.bottom) && (nIndex < 0x1000); y += 16, nIndex++) - { - TCHAR szTmp[16]; - ::wsprintf(szTmp, _T("%04x:%04x"), m_nSegment, nOffset); - ::TextOut(hDC, 0, y, szTmp, 9); - - unsigned char sBuf[16]; - ReadMemory(nOffset, sBuf, sizeof(sBuf)); - - _UNASM una; - UINT nStep = ::unasm(&una, sBuf, sizeof(sBuf), FALSE, nOffset); - if (nStep == 0) - { - return; - } - - ::TextOutA(hDC, 11 * 8, y, una.mnemonic, ::lstrlenA(una.mnemonic)); - if (una.operand[0]) - { - ::TextOutA(hDC, (11 + 7) * 8, y, una.operand, ::lstrlenA(una.operand)); - } - - nOffset = (nOffset + nStep) & 0xffff; - if (m_address.size() == nIndex) - { - m_address.push_back(nOffset); - } - } -} - -/** - * メモリ取得 - * @param[in] nOffset オフセット - * @param[out] lpBuffer バッファ - * @param[in] cbBuffer バッファ長 - */ -void CDebugUtyAsm::ReadMemory(UINT nOffset, unsigned char* lpBuffer, UINT cbBuffer) const -{ - while (cbBuffer) - { - const UINT nLimit = MIN(nOffset + cbBuffer, 0x10000); - const UINT nSize = nLimit - nOffset; - - if (!m_buffer.empty()) - { - CopyMemory(lpBuffer, &m_buffer.at(nOffset), nSize); - } - else - { - m_mem.Read((m_nSegment << 4) + nOffset, lpBuffer, nSize); - } - - nOffset = (nOffset + nSize) & 0xffff; - lpBuffer += nSize; - cbBuffer -= nSize; - } -} +/** + * @file viewasm.cpp + * @brief アセンブラ リスト表示クラスの動作の定義を行います + */ + +#include +#include "resource.h" +#include +#include "viewasm.h" +#include "viewer.h" +#include +#include + +/** + * コンストラクタ + * @param[in] lpView ビューワ インスタンス + */ +CDebugUtyAsm::CDebugUtyAsm(CDebugUtyView* lpView) + : CDebugUtyItem(lpView, IDM_VIEWMODEASM) + , m_nSegment(0) + , m_nOffset(0) +{ +} + +/** + * デストラクタ + */ +CDebugUtyAsm::~CDebugUtyAsm() +{ +} + +/** + * 初期化 + * @param[in] lpItem 基準となるアイテム + */ +void CDebugUtyAsm::Initialize(const CDebugUtyItem* lpItem) +{ + m_nSegment = CPU_CS; + m_nOffset = CPU_IP; + m_lpView->SetVScroll(0, 0x1000); +} + +/** + * 更新 + * @retval true 更新あり + * @retval false 更新なし + */ +bool CDebugUtyAsm::Update() +{ + if (!m_buffer.empty()) + { + return false; + } + + m_nSegment = CPU_CS; + m_nOffset = CPU_IP; + m_lpView->SetVScrollPos(0); + m_mem.Update(); + m_address.clear(); + return true; +} + +/** + * ロック + * @retval true 成功 + * @retval false 失敗 + */ +bool CDebugUtyAsm::Lock() +{ + m_buffer.resize(0x10000); + m_address.clear(); + + m_mem.Update(); + m_mem.Read(m_nSegment << 4, &m_buffer.at(0), static_cast(m_buffer.size())); + return true; +} + +/** + * アンロック + */ +void CDebugUtyAsm::Unlock() +{ + m_buffer.clear(); + m_address.clear(); +} + +/** + * ロック中? + * @retval true ロック中である + * @retval false ロック中でない + */ +bool CDebugUtyAsm::IsLocked() +{ + return (!m_buffer.empty()); +} + +/** + * 描画 + * @param[in] hDC デバイス コンテキスト + * @param[in] rect 領域 + */ +void CDebugUtyAsm::OnPaint(HDC hDC, const RECT& rect) +{ + UINT nIndex = m_lpView->GetVScrollPos(); + + if (m_address.size() < nIndex) + { + UINT nOffset = (!m_address.empty()) ? m_address.back() : m_nOffset; + do + { + unsigned char sBuf[16]; + ReadMemory(nOffset, sBuf, sizeof(sBuf)); + + UINT nStep = ::unasm(NULL, sBuf, sizeof(sBuf), FALSE, nOffset); + if (nStep == 0) + { + return; + } + + nOffset = (nOffset + nStep) & 0xffff; + m_address.push_back(nOffset); + } while (m_address.size() < nIndex); + } + + UINT nOffset = (nIndex) ? m_address[nIndex - 1] : m_nOffset; + for (int y = 0; (y < rect.bottom) && (nIndex < 0x1000); y += 16, nIndex++) + { + TCHAR szTmp[16]; + ::wsprintf(szTmp, _T("%04x:%04x"), m_nSegment, nOffset); + ::TextOut(hDC, 0, y, szTmp, 9); + + unsigned char sBuf[16]; + ReadMemory(nOffset, sBuf, sizeof(sBuf)); + + _UNASM una; + UINT nStep = ::unasm(&una, sBuf, sizeof(sBuf), FALSE, nOffset); + if (nStep == 0) + { + return; + } + + ::TextOutA(hDC, 11 * 8, y, una.mnemonic, ::lstrlenA(una.mnemonic)); + if (una.operand[0]) + { + ::TextOutA(hDC, (11 + 7) * 8, y, una.operand, ::lstrlenA(una.operand)); + } + + nOffset = (nOffset + nStep) & 0xffff; + if (m_address.size() == nIndex) + { + m_address.push_back(nOffset); + } + } +} + +/** + * メモリ取得 + * @param[in] nOffset オフセット + * @param[out] lpBuffer バッファ + * @param[in] cbBuffer バッファ長 + */ +void CDebugUtyAsm::ReadMemory(UINT nOffset, unsigned char* lpBuffer, UINT cbBuffer) const +{ + while (cbBuffer) + { + const UINT nLimit = MIN(nOffset + cbBuffer, 0x10000); + const UINT nSize = nLimit - nOffset; + + if (!m_buffer.empty()) + { + CopyMemory(lpBuffer, &m_buffer.at(nOffset), nSize); + } + else + { + m_mem.Read((m_nSegment << 4) + nOffset, lpBuffer, nSize); + } + + nOffset = (nOffset + nSize) & 0xffff; + lpBuffer += nSize; + cbBuffer -= nSize; + } +} diff --git a/windows/debuguty/viewasm.h b/windows/debuguty/viewasm.h old mode 100755 new mode 100644 index e36ff847..3a835ff8 --- a/windows/debuguty/viewasm.h +++ b/windows/debuguty/viewasm.h @@ -1,35 +1,35 @@ -/** - * @file viewasm.h - * @brief アセンブラ リスト表示クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include "viewitem.h" -#include "viewmem.h" - -/** - * @brief アセンブラ リスト表示クラス - */ -class CDebugUtyAsm : public CDebugUtyItem -{ -public: - CDebugUtyAsm(CDebugUtyView* lpView); - virtual ~CDebugUtyAsm(); - - virtual void Initialize(const CDebugUtyItem* lpItem = NULL); - virtual bool Update(); - virtual bool Lock(); - virtual void Unlock(); - virtual bool IsLocked(); - virtual void OnPaint(HDC hDC, const RECT& rect); - -private: - UINT m_nSegment; //!< セグメント - UINT m_nOffset; //!< セグメント - DebugUtyViewMemory m_mem; //!< メモリ - std::vector m_buffer; //!< バッファ - std::vector m_address; //!< アドレス バッファ - void ReadMemory(UINT nOffset, unsigned char* lpBuffer, UINT cbBuffer) const; -}; +/** + * @file viewasm.h + * @brief アセンブラ リスト表示クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include "viewitem.h" +#include "viewmem.h" + +/** + * @brief アセンブラ リスト表示クラス + */ +class CDebugUtyAsm : public CDebugUtyItem +{ +public: + CDebugUtyAsm(CDebugUtyView* lpView); + virtual ~CDebugUtyAsm(); + + virtual void Initialize(const CDebugUtyItem* lpItem = NULL); + virtual bool Update(); + virtual bool Lock(); + virtual void Unlock(); + virtual bool IsLocked(); + virtual void OnPaint(HDC hDC, const RECT& rect); + +private: + UINT m_nSegment; //!< セグメント + UINT m_nOffset; //!< セグメント + DebugUtyViewMemory m_mem; //!< メモリ + std::vector m_buffer; //!< バッファ + std::vector m_address; //!< アドレス バッファ + void ReadMemory(UINT nOffset, unsigned char* lpBuffer, UINT cbBuffer) const; +}; diff --git a/windows/debuguty/viewer.cpp b/windows/debuguty/viewer.cpp index df247968..3281d68d 100644 --- a/windows/debuguty/viewer.cpp +++ b/windows/debuguty/viewer.cpp @@ -1,6 +1,6 @@ /** * @file viewer.cpp - * @brief DebugUty pr[ NX̓̒`s܂ + * @brief DebugUty 用ビューワ クラスの動作の定義を行います */ #include "compiler.h" @@ -11,25 +11,25 @@ #include "cpucore.h" #include "mousemng.h" -//! CX^X +//! インスタンス static CDebugUtyView* g_np2view[NP2VIEW_MAX]; static CDebugUtyView* g_np2view_closed[NP2VIEW_MAX]; -//! r[ NX +//! ビュー クラス名 static const TCHAR s_szViewClass[] = TEXT("NP2-ViewWindow"); -//! tHg -static const TCHAR s_szViewFont[] = _T("lr SVbN"); +//! フォント +static const TCHAR s_szViewFont[] = _T("MS ゴシック"); -//! ŌTick +//! 最後のTick DWORD CDebugUtyView::sm_dwLastTick; -//! `FbN }N +//! チェック マクロ #define MFCHECK(bChecked) ((bChecked) ? MF_CHECKED : MF_UNCHECKED) /** - * - * @param[in] hInstance CX^X + * 初期化 + * @param[in] hInstance インスタンス */ void CDebugUtyView::Initialize(HINSTANCE hInstance) { @@ -43,7 +43,7 @@ void CDebugUtyView::Initialize(HINSTANCE hInstance) np2vc.lpfnWndProc = ::DefWindowProc; np2vc.cbClsExtra = 0; np2vc.cbWndExtra = 0; - np2vc.hInstance = sm_hInstance;//hInstance; // XXX: ꃊ\[XgƃfobO[eBeB\łȂȂ̂܂ np21w ver0.86 rev13 + np2vc.hInstance = sm_hInstance;//hInstance; // XXX: 言語リソースを使うとデバッグユーティリティが表示できなくなるのをごまかす np21w ver0.86 rev13 np2vc.hIcon = ::LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON2)); np2vc.hCursor = ::LoadCursor(NULL, IDC_ARROW); np2vc.hbrBackground = static_cast(NULL); @@ -53,7 +53,7 @@ void CDebugUtyView::Initialize(HINSTANCE hInstance) } /** - * VEBhE쐬 + * 新しいウィンドウを作成する */ void CDebugUtyView::New() { @@ -82,7 +82,7 @@ void CDebugUtyView::New() } } /** - * j + * メモリ破棄 */ void CDebugUtyView::DisposeAllClosedWindow() { @@ -97,7 +97,7 @@ void CDebugUtyView::DisposeAllClosedWindow() } /** - * ׂĕ‚ + * すべて閉じる */ void CDebugUtyView::AllClose() { @@ -113,8 +113,8 @@ void CDebugUtyView::AllClose() } /** - * ׂčXV - * @param[in] bForce IɍXV + * すべて更新 + * @param[in] bForce 強制的に更新する */ void CDebugUtyView::AllUpdate(bool bForce) { @@ -135,7 +135,7 @@ void CDebugUtyView::AllUpdate(bool bForce) } /** - * RXgN^ + * コンストラクタ */ CDebugUtyView::CDebugUtyView() : m_bActive(false) @@ -148,7 +148,7 @@ CDebugUtyView::CDebugUtyView() } /** - * fXgN^ + * デストラクタ */ CDebugUtyView::~CDebugUtyView() { @@ -156,7 +156,7 @@ CDebugUtyView::~CDebugUtyView() } /** - * fobO\[`؂藣 + * デバッグ表示ルーチンから切り離す */ void CDebugUtyView::DetachDebugView() { @@ -170,7 +170,7 @@ void CDebugUtyView::DetachDebugView() { if (g_np2view[i] == this) { - g_np2view_closed[i] = g_np2view[i]; // ‚ꂽEBhEƂēo^ + g_np2view_closed[i] = g_np2view[i]; // 閉じられたウィンドウとして登録 g_np2view[i] = NULL; UpdateActive(); break; @@ -179,7 +179,7 @@ void CDebugUtyView::DetachDebugView() } /** - * LvV̍XV + * キャプションの更新 */ void CDebugUtyView::UpdateCaption() { @@ -201,8 +201,8 @@ void CDebugUtyView::UpdateCaption() } /** - * V XN[ʒu̐ݒ - * @param[in] nPos Vʒu + * V スクロール位置の設定 + * @param[in] nPos 新しい位置 */ void CDebugUtyView::SetVScrollPos(UINT nPos) { @@ -215,9 +215,9 @@ void CDebugUtyView::SetVScrollPos(UINT nPos) } /** - * V XN[̐ݒ - * @param[in] nPos Vʒu - * @param[in] nLines C + * V スクロールの設定 + * @param[in] nPos 新しい位置 + * @param[in] nLines ライン数 */ void CDebugUtyView::SetVScroll(UINT nPos, UINT nLines) { @@ -232,7 +232,7 @@ void CDebugUtyView::SetVScroll(UINT nPos, UINT nLines) } /** - * V XN[o[̍XV + * V スクロールバーの更新 */ void CDebugUtyView::UpdateVScroll() { @@ -248,11 +248,11 @@ void CDebugUtyView::UpdateVScroll() } /** - * EBhE vV[W - * @param[in] message bZ[W - * @param[in] wParam p^ - * @param[in] lParam p^ - * @return Ug R[h + * ウィンドウ プロシージャ + * @param[in] message メッセージ + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @return リザルト コード */ LRESULT CDebugUtyView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { @@ -298,10 +298,10 @@ LRESULT CDebugUtyView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL CDebugUtyView::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -350,9 +350,9 @@ BOOL CDebugUtyView::OnCommand(WPARAM wParam, LPARAM lParam) } /** - * EBhE̍쐬ɁÃo[֐Ăяo܂ + * ウィンドウの作成時に、このメンバー関数を呼び出します * @param[in] lpCreateStruct - * @retval 0 + * @retval 0 成功 */ int CDebugUtyView::OnCreate(LPCREATESTRUCT lpCreateStruct) { @@ -362,10 +362,10 @@ int CDebugUtyView::OnCreate(LPCREATESTRUCT lpCreateStruct) } /** - * t[[ŃAEBhẼTCYςɂ̃o[֐Ăт܂ - * @param[in] nType TCYύX̎ - * @param[in] cx NCAg̈̐V - * @param[in] cy NCAg̈̐V + * フレームワークは、ウィンドウのサイズが変わった後にこのメンバー関数を呼びます + * @param[in] nType サイズ変更の種類 + * @param[in] cx クライアント領域の新しい幅 + * @param[in] cy クライアント領域の新しい高さ */ void CDebugUtyView::OnSize(UINT nType, int cx, int cy) { @@ -374,7 +374,7 @@ void CDebugUtyView::OnSize(UINT nType, int cx, int cy) } /** - * ĕ`vɁÃo[֐Ăяo܂ + * 再描画要求時に、このメンバー関数を呼び出します */ void CDebugUtyView::OnPaint() { @@ -409,10 +409,10 @@ void CDebugUtyView::OnPaint() } /** - * t[[ŃA[U[EBhEɐXN[ o[NbNƁÃo[֐Ăяo܂ - * @param[in] nSBCode [U[̗vXN[ o[ R[hw肵܂ - * @param[in] nPos ݂̃XN[ {bNẌʒu - * @param[in] hwndScrollBar XN[ o[ Rg[ + * フレームワークは、ユーザーがウィンドウに垂直スクロール バーをクリックすると、このメンバー関数を呼び出します + * @param[in] nSBCode ユーザーの要求を示すスクロール バー コードを指定します + * @param[in] nPos 現在のスクロール ボックスの位置 + * @param[in] hwndScrollBar スクロール バー コントロール */ void CDebugUtyView::OnVScroll(UINT nSBCode, UINT nPos, HWND hwndScrollBar) { @@ -495,10 +495,10 @@ void CDebugUtyView::OnEnterMenuLoop(BOOL bIsTrackPopupMenu) } /** - * t[[N CWnd ̃IuWFNgANeBu܂͔ANeBuꂽƂɂ̃o[֐Ăяo܂ - * @param[in] nState ANeBuɂȂĂ邩ANeBuɂȂĂ邩w肵܂ - * @param[in] hwndOther ANeBu܂͔ANeBuɂȂEBhE nh - * @param[in] bMinimized ANeBu܂͔ANeBuɂȂEBhE̍ŏ̏Ԃw肵܂ + * フレームワークは CWnd のオブジェクトがアクティブ化または非アクティブ化されたときにこのメンバー関数が呼び出されます + * @param[in] nState アクティブになっているか非アクティブになっているかを指定します + * @param[in] hwndOther アクティブまたは非アクティブになるウィンドウ ハンドル + * @param[in] bMinimized アクティブまたは非アクティブになるウィンドウの最小化の状態を指定します */ void CDebugUtyView::OnActivate(UINT nState, HWND hwndOther, BOOL bMinimized) { @@ -515,8 +515,8 @@ void CDebugUtyView::PostNcDestroy() } /** - * [hύX - * @param[in] nID [h + * モード変更 + * @param[in] nID モード */ void CDebugUtyView::SetMode(UINT nID) { @@ -530,7 +530,7 @@ void CDebugUtyView::SetMode(UINT nID) } /** - * r[XV + * ビュー更新 */ void CDebugUtyView::UpdateView() { @@ -541,11 +541,11 @@ void CDebugUtyView::UpdateView() } /** - * j[ ACeXV - * @param[in] hMenu j[ nh - * @param[in] nId j[ ID - * @param[in] lpSegment ZOg - * @param[in] nSegment ZOgl + * メニュー アイテムを更新 + * @param[in] hMenu メニュー ハンドル + * @param[in] nId メニュー ID + * @param[in] lpSegment セグメント名 + * @param[in] nSegment セグメント値 */ void CDebugUtyView::SetSegmentItem(HMENU hMenu, int nId, LPCTSTR lpSegment, UINT nSegment) { @@ -555,7 +555,7 @@ void CDebugUtyView::SetSegmentItem(HMENU hMenu, int nId, LPCTSTR lpSegment, UINT } /** - * ANeBu tOXV + * アクティブ フラグを更新 */ void CDebugUtyView::UpdateActive() { diff --git a/windows/debuguty/viewer.h b/windows/debuguty/viewer.h old mode 100755 new mode 100644 index 40faccef..d687ec5a --- a/windows/debuguty/viewer.h +++ b/windows/debuguty/viewer.h @@ -1,68 +1,68 @@ -/** - * @file viewer.h - * @brief DebugUty 用ビューワ クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "..\misc\WndProc.h" - -class CDebugUtyItem; - -//! ビュー最大数 -#define NP2VIEW_MAX 8 - -/** - * @brief ビュー クラス - */ -class CDebugUtyView : public CWndProc -{ -public: - static void Initialize(HINSTANCE hInstance); - static void New(); - static void DisposeAllClosedWindow(); - static void AllClose(); - static void AllUpdate(bool bForce); - - CDebugUtyView(); - virtual ~CDebugUtyView(); - void DetachDebugView(); - void UpdateCaption(); - UINT32 GetVScrollPos() const; - void SetVScrollPos(UINT nPos); - void SetVScroll(UINT nPos, UINT nLines); - void UpdateVScroll(); - -protected: - virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - int OnCreate(LPCREATESTRUCT lpCreateStruct); - void OnSize(UINT nType, int cx, int cy); - void OnPaint(); - void OnVScroll(UINT nSBCode, UINT nPos, HWND hwndScrollBar); - void OnEnterMenuLoop(BOOL bIsTrackPopupMenu); - void OnActivate(UINT nState, HWND hwndOther, BOOL bMinimized); - virtual void PostNcDestroy(); - -private: - bool m_bActive; //!< アクティブ フラグ - UINT m_nVPos; //!< 位置 - UINT m_nVLines; //!< ライン数 - UINT m_nVPage; //!< 1ページの表示数 - UINT m_nVMultiple; //!< 倍率 - CDebugUtyItem* m_lpItem; //!< 表示アイテム - static DWORD sm_dwLastTick; //!< 最後のTick - void SetMode(UINT nID); - void SetSegmentItem(HMENU hMenu, int nId, LPCTSTR lpSegment, UINT nSegment); - void UpdateView(); - static void UpdateActive(); -}; - -/** - * 現在の位置を返す - * @return 位置 - */ -inline UINT32 CDebugUtyView::GetVScrollPos() const -{ - return m_nVPos; -} +/** + * @file viewer.h + * @brief DebugUty 用ビューワ クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "..\misc\WndProc.h" + +class CDebugUtyItem; + +//! ビュー最大数 +#define NP2VIEW_MAX 8 + +/** + * @brief ビュー クラス + */ +class CDebugUtyView : public CWndProc +{ +public: + static void Initialize(HINSTANCE hInstance); + static void New(); + static void DisposeAllClosedWindow(); + static void AllClose(); + static void AllUpdate(bool bForce); + + CDebugUtyView(); + virtual ~CDebugUtyView(); + void DetachDebugView(); + void UpdateCaption(); + UINT32 GetVScrollPos() const; + void SetVScrollPos(UINT nPos); + void SetVScroll(UINT nPos, UINT nLines); + void UpdateVScroll(); + +protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + int OnCreate(LPCREATESTRUCT lpCreateStruct); + void OnSize(UINT nType, int cx, int cy); + void OnPaint(); + void OnVScroll(UINT nSBCode, UINT nPos, HWND hwndScrollBar); + void OnEnterMenuLoop(BOOL bIsTrackPopupMenu); + void OnActivate(UINT nState, HWND hwndOther, BOOL bMinimized); + virtual void PostNcDestroy(); + +private: + bool m_bActive; //!< アクティブ フラグ + UINT m_nVPos; //!< 位置 + UINT m_nVLines; //!< ライン数 + UINT m_nVPage; //!< 1ページの表示数 + UINT m_nVMultiple; //!< 倍率 + CDebugUtyItem* m_lpItem; //!< 表示アイテム + static DWORD sm_dwLastTick; //!< 最後のTick + void SetMode(UINT nID); + void SetSegmentItem(HMENU hMenu, int nId, LPCTSTR lpSegment, UINT nSegment); + void UpdateView(); + static void UpdateActive(); +}; + +/** + * 現在の位置を返す + * @return 位置 + */ +inline UINT32 CDebugUtyView::GetVScrollPos() const +{ + return m_nVPos; +} diff --git a/windows/debuguty/viewitem.cpp b/windows/debuguty/viewitem.cpp old mode 100755 new mode 100644 index 3a4b5a68..9dfd1de4 --- a/windows/debuguty/viewitem.cpp +++ b/windows/debuguty/viewitem.cpp @@ -1,141 +1,141 @@ -/** - * @file viewitem.cpp - * @brief DebugUty 用ビュー基底クラスの動作の定義を行います - */ - -#include -#include "resource.h" -#include -#include "viewitem.h" -#include "viewer.h" -#include "viewmem.h" -#include "viewreg.h" -#include "viewseg.h" -#include "view1mb.h" -#include "viewasm.h" -#include "viewsnd.h" - -/** - * インスタンス作成 - * @param[in] nID ビュー ID - * @param[in] lpView ビューワ インスタンス - * @param[in] lpItem 基準となるアイテム - * @return インスタンス - */ -CDebugUtyItem* CDebugUtyItem::New(UINT nID, CDebugUtyView* lpView, const CDebugUtyItem* lpItem) -{ - CDebugUtyItem* lpNewItem = NULL; - switch (nID) - { - case IDM_VIEWMODEREG: - lpNewItem = new CDebugUtyReg(lpView); - break; - - case IDM_VIEWMODESEG: - lpNewItem = new CDebugUtySeg(lpView); - break; - - case IDM_VIEWMODE1MB: - lpNewItem = new CDebugUty1MB(lpView); - break; - - case IDM_VIEWMODEASM: - lpNewItem = new CDebugUtyAsm(lpView); - break; - - case IDM_VIEWMODESND: - lpNewItem = new CDebugUtySnd(lpView); - break; - } - if (lpNewItem == NULL) - { - lpNewItem = new CDebugUtyItem(lpView, nID); - } - lpNewItem->Initialize(lpItem); - return lpNewItem; -} - -/** - * コンストラクタ - * @param[in] lpView ビューワ インスタンス - * @param[in] nID ビュー ID - */ -CDebugUtyItem::CDebugUtyItem(CDebugUtyView* lpView, UINT nID) - : m_lpView(lpView) - , m_nID(nID) -{ -} - -/** - * デストラクタ - */ -CDebugUtyItem::~CDebugUtyItem() -{ -} - -/** - * 初期化 - * @param[in] lpItem リファレンス - */ -void CDebugUtyItem::Initialize(const CDebugUtyItem* lpItem) -{ - m_lpView->SetVScroll(0, 0); -} - -/** - * 更新 - * @retval true 更新あり - * @retval false 更新なし - */ -bool CDebugUtyItem::Update() -{ - return false; -} - -/** - * ロック - * @retval true 成功 - * @retval false 失敗 - */ -bool CDebugUtyItem::Lock() -{ - return false; -} - -/** - * アンロック - */ -void CDebugUtyItem::Unlock() -{ -} - -/** - * ロック中? - * @retval true ロック中である - * @retval false ロック中でない - */ -bool CDebugUtyItem::IsLocked() -{ - return false; -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - * @retval FALSE アプリケーションがこのメッセージを処理しなかった - */ -BOOL CDebugUtyItem::OnCommand(WPARAM wParam, LPARAM lParam) -{ - return FALSE; -} - -/** - * 描画 - * @param[in] hDC デバイス コンテキスト - * @param[in] rect 領域 - */ -void CDebugUtyItem::OnPaint(HDC hDC, const RECT& rect) -{ -} +/** + * @file viewitem.cpp + * @brief DebugUty 用ビュー基底クラスの動作の定義を行います + */ + +#include +#include "resource.h" +#include +#include "viewitem.h" +#include "viewer.h" +#include "viewmem.h" +#include "viewreg.h" +#include "viewseg.h" +#include "view1mb.h" +#include "viewasm.h" +#include "viewsnd.h" + +/** + * インスタンス作成 + * @param[in] nID ビュー ID + * @param[in] lpView ビューワ インスタンス + * @param[in] lpItem 基準となるアイテム + * @return インスタンス + */ +CDebugUtyItem* CDebugUtyItem::New(UINT nID, CDebugUtyView* lpView, const CDebugUtyItem* lpItem) +{ + CDebugUtyItem* lpNewItem = NULL; + switch (nID) + { + case IDM_VIEWMODEREG: + lpNewItem = new CDebugUtyReg(lpView); + break; + + case IDM_VIEWMODESEG: + lpNewItem = new CDebugUtySeg(lpView); + break; + + case IDM_VIEWMODE1MB: + lpNewItem = new CDebugUty1MB(lpView); + break; + + case IDM_VIEWMODEASM: + lpNewItem = new CDebugUtyAsm(lpView); + break; + + case IDM_VIEWMODESND: + lpNewItem = new CDebugUtySnd(lpView); + break; + } + if (lpNewItem == NULL) + { + lpNewItem = new CDebugUtyItem(lpView, nID); + } + lpNewItem->Initialize(lpItem); + return lpNewItem; +} + +/** + * コンストラクタ + * @param[in] lpView ビューワ インスタンス + * @param[in] nID ビュー ID + */ +CDebugUtyItem::CDebugUtyItem(CDebugUtyView* lpView, UINT nID) + : m_lpView(lpView) + , m_nID(nID) +{ +} + +/** + * デストラクタ + */ +CDebugUtyItem::~CDebugUtyItem() +{ +} + +/** + * 初期化 + * @param[in] lpItem リファレンス + */ +void CDebugUtyItem::Initialize(const CDebugUtyItem* lpItem) +{ + m_lpView->SetVScroll(0, 0); +} + +/** + * 更新 + * @retval true 更新あり + * @retval false 更新なし + */ +bool CDebugUtyItem::Update() +{ + return false; +} + +/** + * ロック + * @retval true 成功 + * @retval false 失敗 + */ +bool CDebugUtyItem::Lock() +{ + return false; +} + +/** + * アンロック + */ +void CDebugUtyItem::Unlock() +{ +} + +/** + * ロック中? + * @retval true ロック中である + * @retval false ロック中でない + */ +bool CDebugUtyItem::IsLocked() +{ + return false; +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + * @retval FALSE アプリケーションがこのメッセージを処理しなかった + */ +BOOL CDebugUtyItem::OnCommand(WPARAM wParam, LPARAM lParam) +{ + return FALSE; +} + +/** + * 描画 + * @param[in] hDC デバイス コンテキスト + * @param[in] rect 領域 + */ +void CDebugUtyItem::OnPaint(HDC hDC, const RECT& rect) +{ +} diff --git a/windows/debuguty/viewitem.h b/windows/debuguty/viewitem.h old mode 100755 new mode 100644 index c78592d9..8c52be91 --- a/windows/debuguty/viewitem.h +++ b/windows/debuguty/viewitem.h @@ -1,42 +1,42 @@ -/** - * @file viewitem.h - * @brief DebugUty 用ビュー基底クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -class CDebugUtyView; - -/** - * @brief デバグ表示アイテムの基底クラス - */ -class CDebugUtyItem -{ -public: - static CDebugUtyItem* New(UINT nID, CDebugUtyView* lpView, const CDebugUtyItem* lpItem = NULL); - - CDebugUtyItem(CDebugUtyView* lpView, UINT nID); - virtual ~CDebugUtyItem(); - UINT GetID() const; - - virtual void Initialize(const CDebugUtyItem* lpItem = NULL); - virtual bool Update(); - virtual bool Lock(); - virtual void Unlock(); - virtual bool IsLocked(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual void OnPaint(HDC hDC, const RECT& rect); - -protected: - CDebugUtyView* m_lpView; //!< ビュー クラス - UINT m_nID; //!< ID -}; - -/** - * ID を返す - * @return ID - */ -inline UINT CDebugUtyItem::GetID() const -{ - return m_nID; -} +/** + * @file viewitem.h + * @brief DebugUty 用ビュー基底クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +class CDebugUtyView; + +/** + * @brief デバグ表示アイテムの基底クラス + */ +class CDebugUtyItem +{ +public: + static CDebugUtyItem* New(UINT nID, CDebugUtyView* lpView, const CDebugUtyItem* lpItem = NULL); + + CDebugUtyItem(CDebugUtyView* lpView, UINT nID); + virtual ~CDebugUtyItem(); + UINT GetID() const; + + virtual void Initialize(const CDebugUtyItem* lpItem = NULL); + virtual bool Update(); + virtual bool Lock(); + virtual void Unlock(); + virtual bool IsLocked(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void OnPaint(HDC hDC, const RECT& rect); + +protected: + CDebugUtyView* m_lpView; //!< ビュー クラス + UINT m_nID; //!< ID +}; + +/** + * ID を返す + * @return ID + */ +inline UINT CDebugUtyItem::GetID() const +{ + return m_nID; +} diff --git a/windows/debuguty/viewmem.cpp b/windows/debuguty/viewmem.cpp old mode 100755 new mode 100644 index 1dcb581d..1df40f6d --- a/windows/debuguty/viewmem.cpp +++ b/windows/debuguty/viewmem.cpp @@ -1,210 +1,210 @@ -/** - * @file viewmem.cpp - * @brief DebugUty 用メモリ読み込みクラスの動作の定義を行います - */ - -#include -#include "resource.h" -#include -#include "viewmem.h" -#include -#include -#include - -static void viewmem_read(const DebugUtyViewMemory* cfg, UINT32 adrs, UINT8 *buf, UINT32 size); - -/** - * 初期化 - */ -DebugUtyViewMemory::DebugUtyViewMemory() -{ - Update(); -} - -/** - * 状態を更新する - */ -void DebugUtyViewMemory::Update() -{ - this->vram = gdcs.disp; - this->itf = CPU_ITFBANK; - this->A20 = static_cast((CPU_ADRSMASK >> 20) & 1); -} - -/** - * メモリ リード - * @param[in] nAddress アドレス - * @param[in] lpBuffer バッファ - * @param[in] cbBuffer バッファ長 - */ -void DebugUtyViewMemory::Read(UINT32 nAddress, LPVOID lpBuffer, UINT32 cbBuffer) const -{ - viewmem_read(this, nAddress, static_cast(lpBuffer), cbBuffer); -} - -/** - * メモリ リード - * @param[in] cfg 設定 - * @param[in] adrs アドレス - * @param[in] buf バッファ - * @param[in] size バッファ長 - */ -static void viewmem_read(const DebugUtyViewMemory* cfg, UINT32 adrs, UINT8 *buf, UINT32 size) { - - if (!size) { - return; - } - - // Main Memory - if (adrs < 0xa4000) { - if ((adrs + size) <= 0xa4000) { - CopyMemory(buf, mem + adrs, size); - return; - } - else { - UINT32 len; - len = 0xa4000 - adrs; - CopyMemory(buf, mem + adrs, len); - buf += len; - size -= len; - adrs = 0xa4000; - } - } - - // CG-Windowは無視 - if (adrs < 0xa5000) { - if ((adrs + size) <= 0xa5000) { - ZeroMemory(buf, size); - return; - } - else { - UINT32 len; - len = 0xa5000 - adrs; - ZeroMemory(buf, len); - buf += len; - size -= len; - adrs = 0xa5000; - } - } - - // Main Memory - if (adrs < 0xa8000) { - if ((adrs + size) <= 0xa8000) { - CopyMemory(buf, mem + adrs, size); - return; - } - else { - UINT32 len; - len = 0xa8000 - adrs; - CopyMemory(buf, mem + adrs, len); - buf += len; - size -= len; - adrs = 0xa8000; - } - } - - // Video Memory - if (adrs < 0xc0000) { - UINT32 page; - page = ((cfg->vram)?VRAM_STEP:0); - if ((adrs + size) <= 0xc0000) { - CopyMemory(buf, mem + page + adrs, size); - return; - } - else { - UINT32 len; - len = 0xc0000 - adrs; - CopyMemory(buf, mem + page + adrs, len); - buf += len; - size -= len; - adrs = 0xc0000; - } - } - - // Main Memory - if (adrs < 0xe0000) { - if ((adrs + size) <= 0xe0000) { - CopyMemory(buf, mem + adrs, size); - return; - } - else { - UINT32 len; - len = 0xe0000 - adrs; - CopyMemory(buf, mem + adrs, len); - buf += len; - size -= len; - adrs = 0xe0000; - } - } - - // Video Memory - if (adrs < 0xe8000) { - UINT32 page; - page = ((cfg->vram)?VRAM_STEP:0); - if ((adrs + size) <= 0xe8000) { - CopyMemory(buf, mem + page + adrs, size); - return; - } - else { - UINT32 len; - len = 0xe8000 - adrs; - CopyMemory(buf, mem + page + adrs, len); - buf += len; - size -= len; - adrs = 0xe8000; - } - } - - // BIOS - if (adrs < 0x0f8000) { - if ((adrs + size) <= 0x0f8000) { - CopyMemory(buf, mem + adrs, size); - return; - } - else { - UINT32 len; - len = 0x0f8000 - adrs; - CopyMemory(buf, mem + adrs, len); - buf += len; - size -= len; - adrs = 0x0f8000; - } - } - - // BIOS/ITF - if (adrs < 0x100000) { - UINT32 page; - page = ((cfg->itf)?VRAM_STEP:0); - if ((adrs + size) <= 0x100000) { - CopyMemory(buf, mem + page + adrs, size); - return; - } - else { - UINT32 len; - len = 0x100000 - adrs; - CopyMemory(buf, mem + page + adrs, len); - buf += len; - size -= len; - adrs = 0x100000; - } - } - - // HMA - if (adrs < 0x10fff0) { - UINT32 adrs2; - adrs2 = adrs & 0xffff; - adrs2 += ((cfg->A20)?VRAM_STEP:0); - if ((adrs + size) <= 0x10fff0) { - CopyMemory(buf, mem + adrs2, size); - return; - } - else { - UINT32 len; - len = 0x10fff0 - adrs; - CopyMemory(buf, mem + adrs2, len); - buf += len; - size -= len; - adrs = 0x10fff0; - } - } -} +/** + * @file viewmem.cpp + * @brief DebugUty 用メモリ読み込みクラスの動作の定義を行います + */ + +#include +#include "resource.h" +#include +#include "viewmem.h" +#include +#include +#include + +static void viewmem_read(const DebugUtyViewMemory* cfg, UINT32 adrs, UINT8 *buf, UINT32 size); + +/** + * 初期化 + */ +DebugUtyViewMemory::DebugUtyViewMemory() +{ + Update(); +} + +/** + * 状態を更新する + */ +void DebugUtyViewMemory::Update() +{ + this->vram = gdcs.disp; + this->itf = CPU_ITFBANK; + this->A20 = static_cast((CPU_ADRSMASK >> 20) & 1); +} + +/** + * メモリ リード + * @param[in] nAddress アドレス + * @param[in] lpBuffer バッファ + * @param[in] cbBuffer バッファ長 + */ +void DebugUtyViewMemory::Read(UINT32 nAddress, LPVOID lpBuffer, UINT32 cbBuffer) const +{ + viewmem_read(this, nAddress, static_cast(lpBuffer), cbBuffer); +} + +/** + * メモリ リード + * @param[in] cfg 設定 + * @param[in] adrs アドレス + * @param[in] buf バッファ + * @param[in] size バッファ長 + */ +static void viewmem_read(const DebugUtyViewMemory* cfg, UINT32 adrs, UINT8 *buf, UINT32 size) { + + if (!size) { + return; + } + + // Main Memory + if (adrs < 0xa4000) { + if ((adrs + size) <= 0xa4000) { + CopyMemory(buf, mem + adrs, size); + return; + } + else { + UINT32 len; + len = 0xa4000 - adrs; + CopyMemory(buf, mem + adrs, len); + buf += len; + size -= len; + adrs = 0xa4000; + } + } + + // CG-Windowは無視 + if (adrs < 0xa5000) { + if ((adrs + size) <= 0xa5000) { + ZeroMemory(buf, size); + return; + } + else { + UINT32 len; + len = 0xa5000 - adrs; + ZeroMemory(buf, len); + buf += len; + size -= len; + adrs = 0xa5000; + } + } + + // Main Memory + if (adrs < 0xa8000) { + if ((adrs + size) <= 0xa8000) { + CopyMemory(buf, mem + adrs, size); + return; + } + else { + UINT32 len; + len = 0xa8000 - adrs; + CopyMemory(buf, mem + adrs, len); + buf += len; + size -= len; + adrs = 0xa8000; + } + } + + // Video Memory + if (adrs < 0xc0000) { + UINT32 page; + page = ((cfg->vram)?VRAM_STEP:0); + if ((adrs + size) <= 0xc0000) { + CopyMemory(buf, mem + page + adrs, size); + return; + } + else { + UINT32 len; + len = 0xc0000 - adrs; + CopyMemory(buf, mem + page + adrs, len); + buf += len; + size -= len; + adrs = 0xc0000; + } + } + + // Main Memory + if (adrs < 0xe0000) { + if ((adrs + size) <= 0xe0000) { + CopyMemory(buf, mem + adrs, size); + return; + } + else { + UINT32 len; + len = 0xe0000 - adrs; + CopyMemory(buf, mem + adrs, len); + buf += len; + size -= len; + adrs = 0xe0000; + } + } + + // Video Memory + if (adrs < 0xe8000) { + UINT32 page; + page = ((cfg->vram)?VRAM_STEP:0); + if ((adrs + size) <= 0xe8000) { + CopyMemory(buf, mem + page + adrs, size); + return; + } + else { + UINT32 len; + len = 0xe8000 - adrs; + CopyMemory(buf, mem + page + adrs, len); + buf += len; + size -= len; + adrs = 0xe8000; + } + } + + // BIOS + if (adrs < 0x0f8000) { + if ((adrs + size) <= 0x0f8000) { + CopyMemory(buf, mem + adrs, size); + return; + } + else { + UINT32 len; + len = 0x0f8000 - adrs; + CopyMemory(buf, mem + adrs, len); + buf += len; + size -= len; + adrs = 0x0f8000; + } + } + + // BIOS/ITF + if (adrs < 0x100000) { + UINT32 page; + page = ((cfg->itf)?VRAM_STEP:0); + if ((adrs + size) <= 0x100000) { + CopyMemory(buf, mem + page + adrs, size); + return; + } + else { + UINT32 len; + len = 0x100000 - adrs; + CopyMemory(buf, mem + page + adrs, len); + buf += len; + size -= len; + adrs = 0x100000; + } + } + + // HMA + if (adrs < 0x10fff0) { + UINT32 adrs2; + adrs2 = adrs & 0xffff; + adrs2 += ((cfg->A20)?VRAM_STEP:0); + if ((adrs + size) <= 0x10fff0) { + CopyMemory(buf, mem + adrs2, size); + return; + } + else { + UINT32 len; + len = 0x10fff0 - adrs; + CopyMemory(buf, mem + adrs2, len); + buf += len; + size -= len; + adrs = 0x10fff0; + } + } +} diff --git a/windows/debuguty/viewmem.h b/windows/debuguty/viewmem.h old mode 100755 new mode 100644 index 8cfda4bd..849e1712 --- a/windows/debuguty/viewmem.h +++ b/windows/debuguty/viewmem.h @@ -1,20 +1,20 @@ -/** - * @file viewmem.h - * @brief DebugUty 用メモリ読み込みクラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -/** - * @brief メモリ読み込み - */ -struct DebugUtyViewMemory -{ - UINT8 vram; //!< VRAM バンク - UINT8 itf; //!< ITF バンク - UINT8 A20; //!< A20 ライン - - DebugUtyViewMemory(); - void Update(); - void Read(UINT32 nAddress, LPVOID lpBuffer, UINT32 cbBuffer) const; -}; +/** + * @file viewmem.h + * @brief DebugUty 用メモリ読み込みクラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +/** + * @brief メモリ読み込み + */ +struct DebugUtyViewMemory +{ + UINT8 vram; //!< VRAM バンク + UINT8 itf; //!< ITF バンク + UINT8 A20; //!< A20 ライン + + DebugUtyViewMemory(); + void Update(); + void Read(UINT32 nAddress, LPVOID lpBuffer, UINT32 cbBuffer) const; +}; diff --git a/windows/debuguty/viewreg.cpp b/windows/debuguty/viewreg.cpp old mode 100755 new mode 100644 index 5b2912b5..2d3844f1 --- a/windows/debuguty/viewreg.cpp +++ b/windows/debuguty/viewreg.cpp @@ -1,203 +1,203 @@ -/** - * @file viewreg.cpp - * @brief レジスタ表示クラスの動作の定義を行います - */ - -#include -#include "resource.h" -#include -#include -#include "viewer.h" -#include "viewreg.h" -#include - -/** - * コンストラクタ - * @param[in] lpView ビューワ インスタンス - */ -CDebugUtyReg::CDebugUtyReg(CDebugUtyView* lpView) - : CDebugUtyItem(lpView, IDM_VIEWMODEREG) -{ -} - -/** - * デストラクタ - */ -CDebugUtyReg::~CDebugUtyReg() -{ -} - -/** - * 初期化 - * @param[in] lpItem 基準となるアイテム - */ -void CDebugUtyReg::Initialize(const CDebugUtyItem* lpItem) -{ - m_lpView->SetVScroll(0, 4); -} - -/** - * 更新 - * @retval true 更新あり - * @retval false 更新なし - */ -bool CDebugUtyReg::Update() -{ - return (m_buffer.empty()); -} - -/** - * ロック - * @retval true 成功 - * @retval false 失敗 - */ -bool CDebugUtyReg::Lock() -{ -#if defined(CPUCORE_IA32) - m_buffer.resize(sizeof(i386core.s)); - CopyMemory(&m_buffer.at(0), &i386core.s, sizeof(i386core.s)); -#elif defined(CPUCORE_V30) - m_buffer.resize(sizeof(v30core.s)); - CopyMemory(&m_buffer.at(0), &v30core.s, sizeof(v30core.s)); -#else - m_buffer.resize(sizeof(i286core.s)); - CopyMemory(&m_buffer.at(0), &i286core.s, sizeof(i286core.s)); -#endif - return true; -} - -/** - * アンロック - */ -void CDebugUtyReg::Unlock() -{ - m_buffer.clear(); -} - -/** - * ロック中? - * @retval true ロック中である - * @retval false ロック中でない - */ -bool CDebugUtyReg::IsLocked() -{ - return (!m_buffer.empty()); -} - -/** - * 描画 - * @param[in] hDC デバイス コンテキスト - * @param[in] rect 領域 - */ -void CDebugUtyReg::OnPaint(HDC hDC, const RECT& rect) -{ - UINT nIndex = m_lpView->GetVScrollPos(); - -#if defined(CPUCORE_IA32) - const I386STAT* r = &i386core.s; - if (!m_buffer.empty()) - { - r = reinterpret_cast(&m_buffer.at(0)); - } - - for (int y = 0; y < rect.bottom && nIndex < 4; y += 16, nIndex++) - { - TCHAR szTmp[128]; - switch (nIndex) - { - case 0: - ::wsprintf(szTmp, TEXT("EAX=%.8x EBX=%.8x ECX=%.8x EDX=%.8x"), - r->cpu_regs.reg[CPU_EAX_INDEX].d, - r->cpu_regs.reg[CPU_EBX_INDEX].d, - r->cpu_regs.reg[CPU_ECX_INDEX].d, - r->cpu_regs.reg[CPU_EDX_INDEX].d); - break; - - case 1: - ::wsprintf(szTmp, TEXT("ESP=%.8x EBP=%.8x ESI=%.8x EDI=%.8x"), - r->cpu_regs.reg[CPU_ESP_INDEX].d, - r->cpu_regs.reg[CPU_EBP_INDEX].d, - r->cpu_regs.reg[CPU_ESI_INDEX].d, - r->cpu_regs.reg[CPU_EDI_INDEX].d); - break; - - case 2: - ::wsprintf(szTmp, TEXT("CS=%.4x DS=%.4x ES=%.4x FS=%.4x GS=%.4x SS=%.4x"), - r->cpu_regs.sreg[CPU_CS_INDEX], - r->cpu_regs.sreg[CPU_DS_INDEX], - r->cpu_regs.sreg[CPU_ES_INDEX], - r->cpu_regs.sreg[CPU_FS_INDEX], - r->cpu_regs.sreg[CPU_GS_INDEX], - r->cpu_regs.sreg[CPU_SS_INDEX]); - break; - - case 3: - ::wsprintf(szTmp, TEXT("EIP=%.8x %s"), - r->cpu_regs.eip.d, - debugsub_flags(r->cpu_regs.eflags.d)); - break; - } - ::TextOut(hDC, 0, y, szTmp, ::lstrlen(szTmp)); - } -#elif defined(CPUCORE_V30) - const V30STAT* r = &v30core.s; - if (!m_buffer.empty()) - { - r = reinterpret_cast(&m_buffer.at(0)); - } - - for (int y = 0; (y < rect.bottom) && (nIndex < 4); y += 16, nIndex++) - { - TCHAR szTmp[128]; - switch (nIndex) - { - case 0: - ::wsprintf(szTmp, TEXT("AW=%.4x BW=%.4x CW=%.4x DW=%.4x"), r->r.w.aw, r->r.w.bw, r->r.w.cw, r->r.w.dw); - break; - - case 1: - ::wsprintf(szTmp, TEXT("SP=%.4x BP=%.4x IX=%.4x IY=%.4x"), r->r.w.sp, r->r.w.bp, r->r.w.ix, r->r.w.iy); - break; - - case 2: - ::wsprintf(szTmp, TEXT("PS=%.4x DS0=%.4x ES1=%.4x SS=%.4x"), r->r.w.ps, r->r.w.ds0, r->r.w.ds1, r->r.w.ss); - break; - - case 3: - ::wsprintf(szTmp, TEXT("PC=%.4x %s"), r->r.w.pc, debugsub_flags(r->r.w.psw)); - break; - } - ::TextOut(hDC, 0, y, szTmp, ::lstrlen(szTmp)); - } -#else - const I286STAT* r = &i286core.s; - if (!m_buffer.empty()) - { - r = reinterpret_cast(&m_buffer.at(0)); - } - - for (int y = 0; y < rect.bottom && nIndex < 4; y += 16, nIndex++) - { - TCHAR szTmp[128]; - switch (nIndex) - { - case 0: - ::wsprintf(szTmp, TEXT("AX=%.4x BX=%.4x CX=%.4x DX=%.4x"), r->r.w.ax, r->r.w.bx, r->r.w.cx, r->r.w.dx); - break; - - case 1: - ::wsprintf(szTmp, TEXT("SP=%.4x BP=%.4x SI=%.4x DI=%.4x"), r->r.w.sp, r->r.w.bp, r->r.w.si, r->r.w.di); - break; - - case 2: - ::wsprintf(szTmp, TEXT("CS=%.4x DS=%.4x ES=%.4x SS=%.4x"), r->r.w.cs, r->r.w.ds, r->r.w.es, r->r.w.ss); - break; - - case 3: - ::wsprintf(szTmp, TEXT("IP=%.4x %s"), r->r.w.ip, debugsub_flags(r->r.w.flag)); - break; - } - ::TextOut(hDC, 0, y, szTmp, ::lstrlen(szTmp)); - } -#endif -} +/** + * @file viewreg.cpp + * @brief レジスタ表示クラスの動作の定義を行います + */ + +#include +#include "resource.h" +#include +#include +#include "viewer.h" +#include "viewreg.h" +#include + +/** + * コンストラクタ + * @param[in] lpView ビューワ インスタンス + */ +CDebugUtyReg::CDebugUtyReg(CDebugUtyView* lpView) + : CDebugUtyItem(lpView, IDM_VIEWMODEREG) +{ +} + +/** + * デストラクタ + */ +CDebugUtyReg::~CDebugUtyReg() +{ +} + +/** + * 初期化 + * @param[in] lpItem 基準となるアイテム + */ +void CDebugUtyReg::Initialize(const CDebugUtyItem* lpItem) +{ + m_lpView->SetVScroll(0, 4); +} + +/** + * 更新 + * @retval true 更新あり + * @retval false 更新なし + */ +bool CDebugUtyReg::Update() +{ + return (m_buffer.empty()); +} + +/** + * ロック + * @retval true 成功 + * @retval false 失敗 + */ +bool CDebugUtyReg::Lock() +{ +#if defined(CPUCORE_IA32) + m_buffer.resize(sizeof(i386core.s)); + CopyMemory(&m_buffer.at(0), &i386core.s, sizeof(i386core.s)); +#elif defined(CPUCORE_V30) + m_buffer.resize(sizeof(v30core.s)); + CopyMemory(&m_buffer.at(0), &v30core.s, sizeof(v30core.s)); +#else + m_buffer.resize(sizeof(i286core.s)); + CopyMemory(&m_buffer.at(0), &i286core.s, sizeof(i286core.s)); +#endif + return true; +} + +/** + * アンロック + */ +void CDebugUtyReg::Unlock() +{ + m_buffer.clear(); +} + +/** + * ロック中? + * @retval true ロック中である + * @retval false ロック中でない + */ +bool CDebugUtyReg::IsLocked() +{ + return (!m_buffer.empty()); +} + +/** + * 描画 + * @param[in] hDC デバイス コンテキスト + * @param[in] rect 領域 + */ +void CDebugUtyReg::OnPaint(HDC hDC, const RECT& rect) +{ + UINT nIndex = m_lpView->GetVScrollPos(); + +#if defined(CPUCORE_IA32) + const I386STAT* r = &i386core.s; + if (!m_buffer.empty()) + { + r = reinterpret_cast(&m_buffer.at(0)); + } + + for (int y = 0; y < rect.bottom && nIndex < 4; y += 16, nIndex++) + { + TCHAR szTmp[128]; + switch (nIndex) + { + case 0: + ::wsprintf(szTmp, TEXT("EAX=%.8x EBX=%.8x ECX=%.8x EDX=%.8x"), + r->cpu_regs.reg[CPU_EAX_INDEX].d, + r->cpu_regs.reg[CPU_EBX_INDEX].d, + r->cpu_regs.reg[CPU_ECX_INDEX].d, + r->cpu_regs.reg[CPU_EDX_INDEX].d); + break; + + case 1: + ::wsprintf(szTmp, TEXT("ESP=%.8x EBP=%.8x ESI=%.8x EDI=%.8x"), + r->cpu_regs.reg[CPU_ESP_INDEX].d, + r->cpu_regs.reg[CPU_EBP_INDEX].d, + r->cpu_regs.reg[CPU_ESI_INDEX].d, + r->cpu_regs.reg[CPU_EDI_INDEX].d); + break; + + case 2: + ::wsprintf(szTmp, TEXT("CS=%.4x DS=%.4x ES=%.4x FS=%.4x GS=%.4x SS=%.4x"), + r->cpu_regs.sreg[CPU_CS_INDEX], + r->cpu_regs.sreg[CPU_DS_INDEX], + r->cpu_regs.sreg[CPU_ES_INDEX], + r->cpu_regs.sreg[CPU_FS_INDEX], + r->cpu_regs.sreg[CPU_GS_INDEX], + r->cpu_regs.sreg[CPU_SS_INDEX]); + break; + + case 3: + ::wsprintf(szTmp, TEXT("EIP=%.8x %s"), + r->cpu_regs.eip.d, + debugsub_flags(r->cpu_regs.eflags.d)); + break; + } + ::TextOut(hDC, 0, y, szTmp, ::lstrlen(szTmp)); + } +#elif defined(CPUCORE_V30) + const V30STAT* r = &v30core.s; + if (!m_buffer.empty()) + { + r = reinterpret_cast(&m_buffer.at(0)); + } + + for (int y = 0; (y < rect.bottom) && (nIndex < 4); y += 16, nIndex++) + { + TCHAR szTmp[128]; + switch (nIndex) + { + case 0: + ::wsprintf(szTmp, TEXT("AW=%.4x BW=%.4x CW=%.4x DW=%.4x"), r->r.w.aw, r->r.w.bw, r->r.w.cw, r->r.w.dw); + break; + + case 1: + ::wsprintf(szTmp, TEXT("SP=%.4x BP=%.4x IX=%.4x IY=%.4x"), r->r.w.sp, r->r.w.bp, r->r.w.ix, r->r.w.iy); + break; + + case 2: + ::wsprintf(szTmp, TEXT("PS=%.4x DS0=%.4x ES1=%.4x SS=%.4x"), r->r.w.ps, r->r.w.ds0, r->r.w.ds1, r->r.w.ss); + break; + + case 3: + ::wsprintf(szTmp, TEXT("PC=%.4x %s"), r->r.w.pc, debugsub_flags(r->r.w.psw)); + break; + } + ::TextOut(hDC, 0, y, szTmp, ::lstrlen(szTmp)); + } +#else + const I286STAT* r = &i286core.s; + if (!m_buffer.empty()) + { + r = reinterpret_cast(&m_buffer.at(0)); + } + + for (int y = 0; y < rect.bottom && nIndex < 4; y += 16, nIndex++) + { + TCHAR szTmp[128]; + switch (nIndex) + { + case 0: + ::wsprintf(szTmp, TEXT("AX=%.4x BX=%.4x CX=%.4x DX=%.4x"), r->r.w.ax, r->r.w.bx, r->r.w.cx, r->r.w.dx); + break; + + case 1: + ::wsprintf(szTmp, TEXT("SP=%.4x BP=%.4x SI=%.4x DI=%.4x"), r->r.w.sp, r->r.w.bp, r->r.w.si, r->r.w.di); + break; + + case 2: + ::wsprintf(szTmp, TEXT("CS=%.4x DS=%.4x ES=%.4x SS=%.4x"), r->r.w.cs, r->r.w.ds, r->r.w.es, r->r.w.ss); + break; + + case 3: + ::wsprintf(szTmp, TEXT("IP=%.4x %s"), r->r.w.ip, debugsub_flags(r->r.w.flag)); + break; + } + ::TextOut(hDC, 0, y, szTmp, ::lstrlen(szTmp)); + } +#endif +} diff --git a/windows/debuguty/viewreg.h b/windows/debuguty/viewreg.h old mode 100755 new mode 100644 index 2e887650..a5819e31 --- a/windows/debuguty/viewreg.h +++ b/windows/debuguty/viewreg.h @@ -1,29 +1,29 @@ -/** - * @file viewreg.h - * @brief レジスタ表示クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include "viewitem.h" - -/** - * @brief レジスタ表示クラス - */ -class CDebugUtyReg : public CDebugUtyItem -{ -public: - CDebugUtyReg(CDebugUtyView* lpView); - virtual ~CDebugUtyReg(); - - virtual void Initialize(const CDebugUtyItem* lpItem = NULL); - virtual bool Update(); - virtual bool Lock(); - virtual void Unlock(); - virtual bool IsLocked(); - virtual void OnPaint(HDC hDC, const RECT& rect); - -private: - std::vector m_buffer; //!< バッファ -}; +/** + * @file viewreg.h + * @brief レジスタ表示クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include "viewitem.h" + +/** + * @brief レジスタ表示クラス + */ +class CDebugUtyReg : public CDebugUtyItem +{ +public: + CDebugUtyReg(CDebugUtyView* lpView); + virtual ~CDebugUtyReg(); + + virtual void Initialize(const CDebugUtyItem* lpItem = NULL); + virtual bool Update(); + virtual bool Lock(); + virtual void Unlock(); + virtual bool IsLocked(); + virtual void OnPaint(HDC hDC, const RECT& rect); + +private: + std::vector m_buffer; //!< バッファ +}; diff --git a/windows/debuguty/viewseg.cpp b/windows/debuguty/viewseg.cpp old mode 100755 new mode 100644 index 8a7d6ccd..9119c2c3 --- a/windows/debuguty/viewseg.cpp +++ b/windows/debuguty/viewseg.cpp @@ -1,167 +1,167 @@ -/** - * @file viewreg.cpp - * @brief メモリ表示クラスの動作の定義を行います - */ - -#include -#include "resource.h" -#include -#include "viewseg.h" -#include "viewer.h" -#include - -/** - * コンストラクタ - * @param[in] lpView ビューワ インスタンス - */ -CDebugUtySeg::CDebugUtySeg(CDebugUtyView* lpView) - : CDebugUtyItem(lpView, IDM_VIEWMODESEG) - , m_nSegment(0) -{ -} - -/** - * デストラクタ - */ -CDebugUtySeg::~CDebugUtySeg() -{ -} - -/** - * 初期化 - * @param[in] lpItem 基準となるアイテム - */ -void CDebugUtySeg::Initialize(const CDebugUtyItem* lpItem) -{ - m_lpView->SetVScroll(0, 0x1000); -} - -/** - * 更新 - * @retval true 更新あり - * @retval false 更新なし - */ -bool CDebugUtySeg::Update() -{ - if (!m_buffer.empty()) - { - return false; - } - m_mem.Update(); - return true; -} - -/** - * ロック - * @retval true 成功 - * @retval false 失敗 - */ -bool CDebugUtySeg::Lock() -{ - m_buffer.resize(0x10000); - - m_mem.Update(); - m_mem.Read(m_nSegment << 4, &m_buffer.at(0), static_cast(m_buffer.size())); - return true; -} - -/** - * アンロック - */ -void CDebugUtySeg::Unlock() -{ - m_buffer.clear(); -} - -/** - * ロック中? - * @retval true ロック中である - * @retval false ロック中でない - */ -bool CDebugUtySeg::IsLocked() -{ - return (!m_buffer.empty()); -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - * @retval FALSE アプリケーションがこのメッセージを処理しなかった - */ -BOOL CDebugUtySeg::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDM_SEGCS: - SetSegment(CPU_CS); - break; - - case IDM_SEGDS: - SetSegment(CPU_DS); - break; - - case IDM_SEGES: - SetSegment(CPU_ES); - break; - - case IDM_SEGSS: - SetSegment(CPU_SS); - break; - - case IDM_SEGTEXT: - SetSegment(0xa000); - break; - - default: - return FALSE; - - } - return TRUE; -} - -/** - * セグメント変更 - * @param[in] nSegment セグメント - */ -void CDebugUtySeg::SetSegment(UINT nSegment) -{ - if (m_nSegment != nSegment) - { - m_nSegment = nSegment; - m_lpView->Invalidate(); - } -} - -/** - * 描画 - * @param[in] hDC デバイス コンテキスト - * @param[in] rect 領域 - */ -void CDebugUtySeg::OnPaint(HDC hDC, const RECT& rect) -{ - UINT nIndex = m_lpView->GetVScrollPos(); - for (int y = 0; (y < rect.bottom) && (nIndex < 0x1000); y += 16, nIndex++) - { - TCHAR szTmp[16]; - ::wsprintf(szTmp, _T("%04x:%04x"), m_nSegment, nIndex << 4); - ::TextOut(hDC, 0, y, szTmp, 9); - - unsigned char sBuf[16]; - if (!m_buffer.empty()) - { - CopyMemory(sBuf, &m_buffer.at(nIndex << 4), sizeof(sBuf)); - } - else - { - m_mem.Read((m_nSegment + nIndex) << 4, sBuf, sizeof(sBuf)); - } - for (int x = 0; x < 16; x++) - { - TCHAR szTmp[4]; - ::wsprintf(szTmp, TEXT("%02X"), sBuf[x]); - ::TextOut(hDC, ((x * 3) + 10) * 8, y, szTmp, 2); - } - } -} +/** + * @file viewreg.cpp + * @brief メモリ表示クラスの動作の定義を行います + */ + +#include +#include "resource.h" +#include +#include "viewseg.h" +#include "viewer.h" +#include + +/** + * コンストラクタ + * @param[in] lpView ビューワ インスタンス + */ +CDebugUtySeg::CDebugUtySeg(CDebugUtyView* lpView) + : CDebugUtyItem(lpView, IDM_VIEWMODESEG) + , m_nSegment(0) +{ +} + +/** + * デストラクタ + */ +CDebugUtySeg::~CDebugUtySeg() +{ +} + +/** + * 初期化 + * @param[in] lpItem 基準となるアイテム + */ +void CDebugUtySeg::Initialize(const CDebugUtyItem* lpItem) +{ + m_lpView->SetVScroll(0, 0x1000); +} + +/** + * 更新 + * @retval true 更新あり + * @retval false 更新なし + */ +bool CDebugUtySeg::Update() +{ + if (!m_buffer.empty()) + { + return false; + } + m_mem.Update(); + return true; +} + +/** + * ロック + * @retval true 成功 + * @retval false 失敗 + */ +bool CDebugUtySeg::Lock() +{ + m_buffer.resize(0x10000); + + m_mem.Update(); + m_mem.Read(m_nSegment << 4, &m_buffer.at(0), static_cast(m_buffer.size())); + return true; +} + +/** + * アンロック + */ +void CDebugUtySeg::Unlock() +{ + m_buffer.clear(); +} + +/** + * ロック中? + * @retval true ロック中である + * @retval false ロック中でない + */ +bool CDebugUtySeg::IsLocked() +{ + return (!m_buffer.empty()); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + * @retval FALSE アプリケーションがこのメッセージを処理しなかった + */ +BOOL CDebugUtySeg::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDM_SEGCS: + SetSegment(CPU_CS); + break; + + case IDM_SEGDS: + SetSegment(CPU_DS); + break; + + case IDM_SEGES: + SetSegment(CPU_ES); + break; + + case IDM_SEGSS: + SetSegment(CPU_SS); + break; + + case IDM_SEGTEXT: + SetSegment(0xa000); + break; + + default: + return FALSE; + + } + return TRUE; +} + +/** + * セグメント変更 + * @param[in] nSegment セグメント + */ +void CDebugUtySeg::SetSegment(UINT nSegment) +{ + if (m_nSegment != nSegment) + { + m_nSegment = nSegment; + m_lpView->Invalidate(); + } +} + +/** + * 描画 + * @param[in] hDC デバイス コンテキスト + * @param[in] rect 領域 + */ +void CDebugUtySeg::OnPaint(HDC hDC, const RECT& rect) +{ + UINT nIndex = m_lpView->GetVScrollPos(); + for (int y = 0; (y < rect.bottom) && (nIndex < 0x1000); y += 16, nIndex++) + { + TCHAR szTmp[16]; + ::wsprintf(szTmp, _T("%04x:%04x"), m_nSegment, nIndex << 4); + ::TextOut(hDC, 0, y, szTmp, 9); + + unsigned char sBuf[16]; + if (!m_buffer.empty()) + { + CopyMemory(sBuf, &m_buffer.at(nIndex << 4), sizeof(sBuf)); + } + else + { + m_mem.Read((m_nSegment + nIndex) << 4, sBuf, sizeof(sBuf)); + } + for (int x = 0; x < 16; x++) + { + TCHAR szTmp[4]; + ::wsprintf(szTmp, TEXT("%02X"), sBuf[x]); + ::TextOut(hDC, ((x * 3) + 10) * 8, y, szTmp, 2); + } + } +} diff --git a/windows/debuguty/viewseg.h b/windows/debuguty/viewseg.h old mode 100755 new mode 100644 index d50b1ec4..fc979d00 --- a/windows/debuguty/viewseg.h +++ b/windows/debuguty/viewseg.h @@ -1,34 +1,34 @@ -/** - * @file viewseg.h - * @brief メモリ レジスタ表示クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include "viewitem.h" -#include "viewmem.h" - -/** - * @brief メモリ レジスタ表示クラス - */ -class CDebugUtySeg : public CDebugUtyItem -{ -public: - CDebugUtySeg(CDebugUtyView* lpView); - virtual ~CDebugUtySeg(); - - virtual void Initialize(const CDebugUtyItem* lpItem = NULL); - virtual bool Update(); - virtual bool Lock(); - virtual void Unlock(); - virtual bool IsLocked(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual void OnPaint(HDC hDC, const RECT& rect); - -private: - UINT m_nSegment; //!< セグメント - DebugUtyViewMemory m_mem; //!< メモリ - std::vector m_buffer; //!< バッファ - void SetSegment(UINT nSegment); -}; +/** + * @file viewseg.h + * @brief メモリ レジスタ表示クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include "viewitem.h" +#include "viewmem.h" + +/** + * @brief メモリ レジスタ表示クラス + */ +class CDebugUtySeg : public CDebugUtyItem +{ +public: + CDebugUtySeg(CDebugUtyView* lpView); + virtual ~CDebugUtySeg(); + + virtual void Initialize(const CDebugUtyItem* lpItem = NULL); + virtual bool Update(); + virtual bool Lock(); + virtual void Unlock(); + virtual bool IsLocked(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void OnPaint(HDC hDC, const RECT& rect); + +private: + UINT m_nSegment; //!< セグメント + DebugUtyViewMemory m_mem; //!< メモリ + std::vector m_buffer; //!< バッファ + void SetSegment(UINT nSegment); +}; diff --git a/windows/debuguty/viewsnd.cpp b/windows/debuguty/viewsnd.cpp old mode 100755 new mode 100644 index cdacaefc..ad958000 --- a/windows/debuguty/viewsnd.cpp +++ b/windows/debuguty/viewsnd.cpp @@ -1,188 +1,188 @@ -/** - * @file viewsnd.cpp - * @brief サウンド レジスタ表示クラスの動作の定義を行います - */ - -#include -#include -#include "resource.h" -#include -#include "viewsnd.h" -#include "viewer.h" -#include -#include -#include -#include - -/** - * @brief 表示アイテム - */ -struct SoundRegisterTable -{ - LPCTSTR lpString; //!< 文字列 - UINT16 wAddress; //!< アドレス - UINT16 wMask; //!< 表示マスク -}; - -//! テーブル -static const SoundRegisterTable s_table[] = -{ - {TEXT("Sound-Board I"), 0, 0}, - {NULL, 0x0000, 0xffff}, - {NULL, 0x0010, 0x3f07}, - {NULL, 0x0020, 0x07f6}, - {NULL, 0x0030, 0x7777}, - {NULL, 0x0040, 0x7777}, - {NULL, 0x0050, 0x7777}, - {NULL, 0x0060, 0x7777}, - {NULL, 0x0070, 0x7777}, - {NULL, 0x0080, 0x7777}, - {NULL, 0x0090, 0x7777}, - {NULL, 0x00a0, 0x7777}, - {NULL, 0x00b0, 0x0077}, - {str_null, 0, 0}, - {NULL, 0x0100, 0xffff}, - {NULL, 0x0110, 0x0001}, - {NULL, 0x0130, 0x7777}, - {NULL, 0x0140, 0x7777}, - {NULL, 0x0150, 0x7777}, - {NULL, 0x0160, 0x7777}, - {NULL, 0x0170, 0x7777}, - {NULL, 0x0180, 0x7777}, - {NULL, 0x0190, 0x7777}, - {NULL, 0x01a0, 0x7777}, - {NULL, 0x01b0, 0x0077}, -#if 0 - {str_null, 0, 0}, - {TEXT("Sound-Board II"), 0, 0}, - {NULL, 0x0200, 0xffff}, - {NULL, 0x0220, 0x07e6}, - {NULL, 0x0230, 0x7777}, - {NULL, 0x0240, 0x7777}, - {NULL, 0x0250, 0x7777}, - {NULL, 0x0260, 0x7777}, - {NULL, 0x0270, 0x7777}, - {NULL, 0x0280, 0x7777}, - {NULL, 0x0290, 0x7777}, - {NULL, 0x02a0, 0x7777}, - {NULL, 0x02b0, 0x0077}, - {str_null, 0, 0}, - {NULL, 0x0230, 0x7777}, - {NULL, 0x0240, 0x7777}, - {NULL, 0x0250, 0x7777}, - {NULL, 0x0260, 0x7777}, - {NULL, 0x0270, 0x7777}, - {NULL, 0x0280, 0x7777}, - {NULL, 0x0290, 0x7777}, - {NULL, 0x02a0, 0x7777}, - {NULL, 0x02b0, 0x0077} -#endif -}; - -/** - * コンストラクタ - * @param[in] lpView ビューワ インスタンス - */ -CDebugUtySnd::CDebugUtySnd(CDebugUtyView* lpView) - : CDebugUtyItem(lpView, IDM_VIEWMODESND) -{ -} - -/** - * デストラクタ - */ -CDebugUtySnd::~CDebugUtySnd() -{ -} - -/** - * 初期化 - * @param[in] lpItem 基準となるアイテム - */ -void CDebugUtySnd::Initialize(const CDebugUtyItem* lpItem) -{ - m_lpView->SetVScroll(0, _countof(s_table)); -} - -/** - * 更新 - * @retval true 更新あり - * @retval false 更新なし - */ -bool CDebugUtySnd::Update() -{ - return m_buffer.empty(); -} - -/** - * ロック - * @retval true 成功 - * @retval false 失敗 - */ -bool CDebugUtySnd::Lock() -{ - m_buffer.resize(0x200); - CopyMemory(&m_buffer.at(0), g_opna[0].s.reg, 0x200); - return true; -} - -/** - * アンロック - */ -void CDebugUtySnd::Unlock() -{ - m_buffer.clear(); -} - -/** - * ロック中? - * @retval true ロック中である - * @retval false ロック中でない - */ -bool CDebugUtySnd::IsLocked() -{ - return (!m_buffer.empty()); -} - -/** - * 描画 - * @param[in] hDC デバイス コンテキスト - * @param[in] rect 領域 - */ -void CDebugUtySnd::OnPaint(HDC hDC, const RECT& rect) -{ - UINT nIndex = m_lpView->GetVScrollPos(); - for (int y = 0; (y < rect.bottom) && (nIndex < _countof(s_table)); y += 16, nIndex++) - { - const SoundRegisterTable& item = s_table[nIndex]; - if (item.lpString) - { - ::TextOut(hDC, 0, y, item.lpString, ::lstrlen(item.lpString)); - } - else - { - TCHAR szTmp[8]; - ::wsprintf(szTmp, TEXT("%04x"), item.wAddress); - TextOut(hDC, 8, y, szTmp, 4); - - const unsigned char* p = NULL; - if (!m_buffer.empty()) - { - p = &m_buffer.at(item.wAddress); - } - else - { - p = g_opna[0].s.reg + item.wAddress; - } - for (int x = 0; x < 16; x++) - { - if (item.wMask & (1 << x)) - { - TCHAR szTmp[4]; - ::wsprintf(szTmp, TEXT("%02X"), p[x]); - ::TextOut(hDC, ((x * 3) + 6) * 8, y, szTmp, 2); - } - } - } - } -} +/** + * @file viewsnd.cpp + * @brief サウンド レジスタ表示クラスの動作の定義を行います + */ + +#include +#include +#include "resource.h" +#include +#include "viewsnd.h" +#include "viewer.h" +#include +#include +#include +#include + +/** + * @brief 表示アイテム + */ +struct SoundRegisterTable +{ + LPCTSTR lpString; //!< 文字列 + UINT16 wAddress; //!< アドレス + UINT16 wMask; //!< 表示マスク +}; + +//! テーブル +static const SoundRegisterTable s_table[] = +{ + {TEXT("Sound-Board I"), 0, 0}, + {NULL, 0x0000, 0xffff}, + {NULL, 0x0010, 0x3f07}, + {NULL, 0x0020, 0x07f6}, + {NULL, 0x0030, 0x7777}, + {NULL, 0x0040, 0x7777}, + {NULL, 0x0050, 0x7777}, + {NULL, 0x0060, 0x7777}, + {NULL, 0x0070, 0x7777}, + {NULL, 0x0080, 0x7777}, + {NULL, 0x0090, 0x7777}, + {NULL, 0x00a0, 0x7777}, + {NULL, 0x00b0, 0x0077}, + {str_null, 0, 0}, + {NULL, 0x0100, 0xffff}, + {NULL, 0x0110, 0x0001}, + {NULL, 0x0130, 0x7777}, + {NULL, 0x0140, 0x7777}, + {NULL, 0x0150, 0x7777}, + {NULL, 0x0160, 0x7777}, + {NULL, 0x0170, 0x7777}, + {NULL, 0x0180, 0x7777}, + {NULL, 0x0190, 0x7777}, + {NULL, 0x01a0, 0x7777}, + {NULL, 0x01b0, 0x0077}, +#if 0 + {str_null, 0, 0}, + {TEXT("Sound-Board II"), 0, 0}, + {NULL, 0x0200, 0xffff}, + {NULL, 0x0220, 0x07e6}, + {NULL, 0x0230, 0x7777}, + {NULL, 0x0240, 0x7777}, + {NULL, 0x0250, 0x7777}, + {NULL, 0x0260, 0x7777}, + {NULL, 0x0270, 0x7777}, + {NULL, 0x0280, 0x7777}, + {NULL, 0x0290, 0x7777}, + {NULL, 0x02a0, 0x7777}, + {NULL, 0x02b0, 0x0077}, + {str_null, 0, 0}, + {NULL, 0x0230, 0x7777}, + {NULL, 0x0240, 0x7777}, + {NULL, 0x0250, 0x7777}, + {NULL, 0x0260, 0x7777}, + {NULL, 0x0270, 0x7777}, + {NULL, 0x0280, 0x7777}, + {NULL, 0x0290, 0x7777}, + {NULL, 0x02a0, 0x7777}, + {NULL, 0x02b0, 0x0077} +#endif +}; + +/** + * コンストラクタ + * @param[in] lpView ビューワ インスタンス + */ +CDebugUtySnd::CDebugUtySnd(CDebugUtyView* lpView) + : CDebugUtyItem(lpView, IDM_VIEWMODESND) +{ +} + +/** + * デストラクタ + */ +CDebugUtySnd::~CDebugUtySnd() +{ +} + +/** + * 初期化 + * @param[in] lpItem 基準となるアイテム + */ +void CDebugUtySnd::Initialize(const CDebugUtyItem* lpItem) +{ + m_lpView->SetVScroll(0, _countof(s_table)); +} + +/** + * 更新 + * @retval true 更新あり + * @retval false 更新なし + */ +bool CDebugUtySnd::Update() +{ + return m_buffer.empty(); +} + +/** + * ロック + * @retval true 成功 + * @retval false 失敗 + */ +bool CDebugUtySnd::Lock() +{ + m_buffer.resize(0x200); + CopyMemory(&m_buffer.at(0), g_opna[0].s.reg, 0x200); + return true; +} + +/** + * アンロック + */ +void CDebugUtySnd::Unlock() +{ + m_buffer.clear(); +} + +/** + * ロック中? + * @retval true ロック中である + * @retval false ロック中でない + */ +bool CDebugUtySnd::IsLocked() +{ + return (!m_buffer.empty()); +} + +/** + * 描画 + * @param[in] hDC デバイス コンテキスト + * @param[in] rect 領域 + */ +void CDebugUtySnd::OnPaint(HDC hDC, const RECT& rect) +{ + UINT nIndex = m_lpView->GetVScrollPos(); + for (int y = 0; (y < rect.bottom) && (nIndex < _countof(s_table)); y += 16, nIndex++) + { + const SoundRegisterTable& item = s_table[nIndex]; + if (item.lpString) + { + ::TextOut(hDC, 0, y, item.lpString, ::lstrlen(item.lpString)); + } + else + { + TCHAR szTmp[8]; + ::wsprintf(szTmp, TEXT("%04x"), item.wAddress); + TextOut(hDC, 8, y, szTmp, 4); + + const unsigned char* p = NULL; + if (!m_buffer.empty()) + { + p = &m_buffer.at(item.wAddress); + } + else + { + p = g_opna[0].s.reg + item.wAddress; + } + for (int x = 0; x < 16; x++) + { + if (item.wMask & (1 << x)) + { + TCHAR szTmp[4]; + ::wsprintf(szTmp, TEXT("%02X"), p[x]); + ::TextOut(hDC, ((x * 3) + 6) * 8, y, szTmp, 2); + } + } + } + } +} diff --git a/windows/debuguty/viewsnd.h b/windows/debuguty/viewsnd.h old mode 100755 new mode 100644 index 918ab690..28bc6df1 --- a/windows/debuguty/viewsnd.h +++ b/windows/debuguty/viewsnd.h @@ -1,29 +1,29 @@ -/** - * @file viewsnd.h - * @brief サウンド レジスタ表示クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include "viewitem.h" - -/** - * @brief サウンド レジスタ表示クラス - */ -class CDebugUtySnd : public CDebugUtyItem -{ -public: - CDebugUtySnd(CDebugUtyView* lpView); - virtual ~CDebugUtySnd(); - - virtual void Initialize(const CDebugUtyItem* lpItem = NULL); - virtual bool Update(); - virtual bool Lock(); - virtual void Unlock(); - virtual bool IsLocked(); - virtual void OnPaint(HDC hDC, const RECT& rect); - -private: - std::vector m_buffer; //!< バッファ -}; +/** + * @file viewsnd.h + * @brief サウンド レジスタ表示クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include "viewitem.h" + +/** + * @brief サウンド レジスタ表示クラス + */ +class CDebugUtySnd : public CDebugUtyItem +{ +public: + CDebugUtySnd(CDebugUtyView* lpView); + virtual ~CDebugUtySnd(); + + virtual void Initialize(const CDebugUtyItem* lpItem = NULL); + virtual bool Update(); + virtual bool Lock(); + virtual void Unlock(); + virtual bool IsLocked(); + virtual void OnPaint(HDC hDC, const RECT& rect); + +private: + std::vector m_buffer; //!< バッファ +}; diff --git a/windows/dialog/c_combodata.cpp b/windows/dialog/c_combodata.cpp old mode 100755 new mode 100644 index 450fa800..9dfcceb1 --- a/windows/dialog/c_combodata.cpp +++ b/windows/dialog/c_combodata.cpp @@ -1,136 +1,136 @@ -/** - * @file c_combodata.cpp - * @brief コンボ データ クラスの動作の定義を行います - */ - -#include -#include "c_combodata.h" - -/** - * 追加 - * @param[in] lpValues 値の配列 - * @param[in] cchValues 値の数 - */ -void CComboData::Add(const UINT32* lpValues, UINT cchValues) -{ - for (UINT i = 0; i < cchValues; i++) - { - Add(lpValues[i]); - } -} - -/** - * 追加 - * @param[in] lpValues 値の配列 - * @param[in] cchValues 値の数 - */ -void CComboData::Add(const Value* lpValues, UINT cchValues) -{ - for (UINT i = 0; i < cchValues; i++) - { - Add(lpValues[i].nNumber, lpValues[i].nItemData); - } -} - -/** - * 追加 - * @param[in] lpEntries エントリの配列 - * @param[in] cchEntries エントリの数 - */ -void CComboData::Add(const Entry* lpEntries, UINT cchEntries) -{ - for (UINT i = 0; i < cchEntries; i++) - { - std::tstring rString(LoadTString(lpEntries[i].lpcszString)); - Add(rString.c_str(), lpEntries[i].nItemData); - } -} - -/** - * 追加 - * @param[in] nValue 値 - * @return インデックス - */ -int CComboData::Add(UINT32 nValue) -{ - return Add(nValue, nValue); -} - -/** - * 追加 - * @param[in] nValue 値 - * @param[in] nItemData データ - * @return インデックス - */ -int CComboData::Add(UINT32 nValue, UINT32 nItemData) -{ - TCHAR szStr[16]; - wsprintf(szStr, TEXT("%u"), nValue); - return Add(szStr, nItemData); -} - -/** - * 追加 - * @param[in] lpString 表示名 - * @param[in] nItemData データ - * @return インデックス - */ -int CComboData::Add(LPCTSTR lpString, UINT32 nItemData) -{ - const int nIndex = AddString(lpString); - if (nIndex >= 0) - { - SetItemData(nIndex, static_cast(nItemData)); - } - return nIndex; -} - -/** - * アイテム検索 - * @param[in] nValue 値 - * @return インデックス - */ -int CComboData::FindItemData(UINT32 nValue) const -{ - const int nItems = GetCount(); - for (int i = 0; i < nItems; i++) - { - if (GetItemData(i) == nValue) - { - return i; - } - } - return CB_ERR; -} - -/** - * カーソル設定 - * @param[in] nValue 値 - * @retval true 成功 - * @retval false 失敗 - */ -bool CComboData::SetCurItemData(UINT32 nValue) -{ - const int nIndex = FindItemData(nValue); - if (nIndex == CB_ERR) - { - return false; - } - SetCurSel(nIndex); - return true; -} - -/** - * カーソルの値を取得 - * @param[in] nDefault デフォルト値 - * @return 値 - */ -UINT32 CComboData::GetCurItemData(UINT32 nDefault) const -{ - const int nIndex = GetCurSel(); - if (nIndex >= 0) - { - return static_cast(GetItemData(nIndex)); - } - return nDefault; -} +/** + * @file c_combodata.cpp + * @brief コンボ データ クラスの動作の定義を行います + */ + +#include +#include "c_combodata.h" + +/** + * 追加 + * @param[in] lpValues 値の配列 + * @param[in] cchValues 値の数 + */ +void CComboData::Add(const UINT32* lpValues, UINT cchValues) +{ + for (UINT i = 0; i < cchValues; i++) + { + Add(lpValues[i]); + } +} + +/** + * 追加 + * @param[in] lpValues 値の配列 + * @param[in] cchValues 値の数 + */ +void CComboData::Add(const Value* lpValues, UINT cchValues) +{ + for (UINT i = 0; i < cchValues; i++) + { + Add(lpValues[i].nNumber, lpValues[i].nItemData); + } +} + +/** + * 追加 + * @param[in] lpEntries エントリの配列 + * @param[in] cchEntries エントリの数 + */ +void CComboData::Add(const Entry* lpEntries, UINT cchEntries) +{ + for (UINT i = 0; i < cchEntries; i++) + { + std::tstring rString(LoadTString(lpEntries[i].lpcszString)); + Add(rString.c_str(), lpEntries[i].nItemData); + } +} + +/** + * 追加 + * @param[in] nValue 値 + * @return インデックス + */ +int CComboData::Add(UINT32 nValue) +{ + return Add(nValue, nValue); +} + +/** + * 追加 + * @param[in] nValue 値 + * @param[in] nItemData データ + * @return インデックス + */ +int CComboData::Add(UINT32 nValue, UINT32 nItemData) +{ + TCHAR szStr[16]; + wsprintf(szStr, TEXT("%u"), nValue); + return Add(szStr, nItemData); +} + +/** + * 追加 + * @param[in] lpString 表示名 + * @param[in] nItemData データ + * @return インデックス + */ +int CComboData::Add(LPCTSTR lpString, UINT32 nItemData) +{ + const int nIndex = AddString(lpString); + if (nIndex >= 0) + { + SetItemData(nIndex, static_cast(nItemData)); + } + return nIndex; +} + +/** + * アイテム検索 + * @param[in] nValue 値 + * @return インデックス + */ +int CComboData::FindItemData(UINT32 nValue) const +{ + const int nItems = GetCount(); + for (int i = 0; i < nItems; i++) + { + if (GetItemData(i) == nValue) + { + return i; + } + } + return CB_ERR; +} + +/** + * カーソル設定 + * @param[in] nValue 値 + * @retval true 成功 + * @retval false 失敗 + */ +bool CComboData::SetCurItemData(UINT32 nValue) +{ + const int nIndex = FindItemData(nValue); + if (nIndex == CB_ERR) + { + return false; + } + SetCurSel(nIndex); + return true; +} + +/** + * カーソルの値を取得 + * @param[in] nDefault デフォルト値 + * @return 値 + */ +UINT32 CComboData::GetCurItemData(UINT32 nDefault) const +{ + const int nIndex = GetCurSel(); + if (nIndex >= 0) + { + return static_cast(GetItemData(nIndex)); + } + return nDefault; +} diff --git a/windows/dialog/c_combodata.h b/windows/dialog/c_combodata.h old mode 100755 new mode 100644 index 7679f0cb..0af282f3 --- a/windows/dialog/c_combodata.h +++ b/windows/dialog/c_combodata.h @@ -1,43 +1,43 @@ -/** - * @file c_combodata.h - * @brief コンボ データ クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "misc/DlgProc.h" - -/** - * @brief コンボ データ クラス - */ -class CComboData : public CComboBoxProc -{ -public: - /** - * @brief エントリー - */ - struct Value - { - UINT32 nNumber; /*!< 数値 */ - UINT32 nItemData; /*!< 値 */ - }; - - /** - * @brief エントリー - */ - struct Entry - { - LPCTSTR lpcszString; /*!< 文字列 */ - UINT32 nItemData; /*!< 値 */ - }; - - void Add(const UINT32* lpValues, UINT cchValues); - void Add(const Value* lpValues, UINT cchValues); - void Add(const Entry* lpEntries, UINT cchEntries); - int Add(UINT32 nValue); - int Add(UINT32 nValue, UINT32 nItemData); - int Add(LPCTSTR lpString, UINT32 nItemData); - int FindItemData(UINT32 nValue) const; - bool SetCurItemData(UINT32 nValue); - UINT32 GetCurItemData(UINT32 nDefault) const; -}; +/** + * @file c_combodata.h + * @brief コンボ データ クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "misc/DlgProc.h" + +/** + * @brief コンボ データ クラス + */ +class CComboData : public CComboBoxProc +{ +public: + /** + * @brief エントリー + */ + struct Value + { + UINT32 nNumber; /*!< 数値 */ + UINT32 nItemData; /*!< 値 */ + }; + + /** + * @brief エントリー + */ + struct Entry + { + LPCTSTR lpcszString; /*!< 文字列 */ + UINT32 nItemData; /*!< 値 */ + }; + + void Add(const UINT32* lpValues, UINT cchValues); + void Add(const Value* lpValues, UINT cchValues); + void Add(const Entry* lpEntries, UINT cchEntries); + int Add(UINT32 nValue); + int Add(UINT32 nValue, UINT32 nItemData); + int Add(LPCTSTR lpString, UINT32 nItemData); + int FindItemData(UINT32 nValue) const; + bool SetCurItemData(UINT32 nValue); + UINT32 GetCurItemData(UINT32 nDefault) const; +}; diff --git a/windows/dialog/c_dipsw.cpp b/windows/dialog/c_dipsw.cpp old mode 100755 new mode 100644 index a5ad0110..b56d2017 --- a/windows/dialog/c_dipsw.cpp +++ b/windows/dialog/c_dipsw.cpp @@ -1,55 +1,55 @@ -/** - * @file c_dipsw.cpp - * @brief DIPSW コントロール クラス群の動作の定義を行います - */ - -#include -#include "c_dipsw.h" -#include - -/** - * 初期化 - */ -void CStaticDipSw::PreSubclassWindow() -{ - ModifyStyle(SS_TYPEMASK, SS_OWNERDRAW); -} - -/** - * 描画 - * @param[in] hdc デバイス コンテキスト - * @param[in] lpBitmap ビットマップ - */ -void CStaticDipSw::Draw(HDC hdc, const void* lpBitmap) -{ - if (lpBitmap == NULL) - { - return; - } - - const BMPFILE* lpBmpFile = static_cast(lpBitmap); - const BMPINFO* lpBmpInfo = reinterpret_cast(lpBmpFile + 1); - - BMPDATA inf; - if (::bmpdata_getinfo(lpBmpInfo, &inf) != SUCCESS) - { - return; - } - - void* pImage; - HBITMAP hBitmap = ::CreateDIBSection(hdc, reinterpret_cast(lpBmpInfo), DIB_RGB_COLORS, &pImage, NULL, 0); - if (hBitmap == NULL) - { - return; - } - CopyMemory(pImage, static_cast(lpBitmap) + (LOADINTELDWORD(lpBmpFile->bfOffBits)), ::bmpdata_getdatasize(lpBmpInfo)); - HDC hdcMem = CreateCompatibleDC(hdc); - ::SelectObject(hdcMem, hBitmap); - if (inf.height < 0) - { - inf.height *= -1; - } - ::BitBlt(hdc, 0, 0, inf.width, inf.height, hdcMem, 0, 0, SRCCOPY); - ::DeleteDC(hdcMem); - ::DeleteObject(hBitmap); -} +/** + * @file c_dipsw.cpp + * @brief DIPSW コントロール クラス群の動作の定義を行います + */ + +#include +#include "c_dipsw.h" +#include + +/** + * 初期化 + */ +void CStaticDipSw::PreSubclassWindow() +{ + ModifyStyle(SS_TYPEMASK, SS_OWNERDRAW); +} + +/** + * 描画 + * @param[in] hdc デバイス コンテキスト + * @param[in] lpBitmap ビットマップ + */ +void CStaticDipSw::Draw(HDC hdc, const void* lpBitmap) +{ + if (lpBitmap == NULL) + { + return; + } + + const BMPFILE* lpBmpFile = static_cast(lpBitmap); + const BMPINFO* lpBmpInfo = reinterpret_cast(lpBmpFile + 1); + + BMPDATA inf; + if (::bmpdata_getinfo(lpBmpInfo, &inf) != SUCCESS) + { + return; + } + + void* pImage; + HBITMAP hBitmap = ::CreateDIBSection(hdc, reinterpret_cast(lpBmpInfo), DIB_RGB_COLORS, &pImage, NULL, 0); + if (hBitmap == NULL) + { + return; + } + CopyMemory(pImage, static_cast(lpBitmap) + (LOADINTELDWORD(lpBmpFile->bfOffBits)), ::bmpdata_getdatasize(lpBmpInfo)); + HDC hdcMem = CreateCompatibleDC(hdc); + ::SelectObject(hdcMem, hBitmap); + if (inf.height < 0) + { + inf.height *= -1; + } + ::BitBlt(hdc, 0, 0, inf.width, inf.height, hdcMem, 0, 0, SRCCOPY); + ::DeleteDC(hdcMem); + ::DeleteObject(hBitmap); +} diff --git a/windows/dialog/c_dipsw.h b/windows/dialog/c_dipsw.h old mode 100755 new mode 100644 index 46209d6d..47545421 --- a/windows/dialog/c_dipsw.h +++ b/windows/dialog/c_dipsw.h @@ -1,18 +1,18 @@ -/** - * @file c_dipsw.h - * @brief DIPSW コントロール クラス群の宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "misc\WndProc.h" - -/** - * @brief MIDI デバイス クラス - */ -class CStaticDipSw : public CWndProc -{ -public: - virtual void PreSubclassWindow(); - static void Draw(HDC hdc, const void* lpBitmap); -}; +/** + * @file c_dipsw.h + * @brief DIPSW コントロール クラス群の宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "misc\WndProc.h" + +/** + * @brief MIDI デバイス クラス + */ +class CStaticDipSw : public CWndProc +{ +public: + virtual void PreSubclassWindow(); + static void Draw(HDC hdc, const void* lpBitmap); +}; diff --git a/windows/dialog/c_midi.cpp b/windows/dialog/c_midi.cpp old mode 100755 new mode 100644 index 47037d69..cf69daa1 --- a/windows/dialog/c_midi.cpp +++ b/windows/dialog/c_midi.cpp @@ -1,130 +1,130 @@ -/** - * @file c_midi.cpp - * @brief MIDI コントロール クラス群の動作の定義を行います - */ - -#include -#include "resource.h" -#include "c_midi.h" -#include "commng\cmmidi.h" -#if defined(SUPPORT_VSTi) -#include "commng\cmmidioutvst.h" -#endif // defined(SUPPORT_VSTi) -#if defined(MT32SOUND_DLL) -#include "..\ext\mt32snd.h" -#endif // defined(MT32SOUND_DLL) -#include "dialog/winfiledlg.h" - -/** - * MIDI デバイスの初期化 - */ -void CComboMidiDevice::PreSubclassWindow() -{ - // N/C - std::tstring rNC(LoadTString(IDS_NONCONNECT)); - AddString(rNC.c_str()); -} - -/** - * MIDI IN デバイスの列挙 - */ -void CComboMidiDevice::EnumerateMidiIn() -{ - const UINT nDevs = ::midiInGetNumDevs(); - for (UINT i = 0; i < nDevs; i++) - { - MIDIINCAPS mic; - if (::midiInGetDevCaps(i, &mic, sizeof(mic)) == MMSYSERR_NOERROR) - { - AddString(mic.szPname); - } - } -} - -/** - * MIDI OUT デバイスの列挙 - */ -void CComboMidiDevice::EnumerateMidiOut() -{ - // MIDI MAPPER - AddString(cmmidi_midimapper); - - // Vermouth -#if defined(VERMOUTH_LIB) - AddString(cmmidi_vermouth); -#endif // defined(VERMOUTH_LIB) - - // MT32Sound -#if defined(MT32SOUND_DLL) - if (MT32Sound::GetInstance()->IsEnabled()) - { - AddString(cmmidi_mt32sound); - } -#endif // defined(MT32SOUND_DLL) - -#if defined(SUPPORT_VSTi) - if (CComMidiOutVst::IsEnabled()) - { - AddString(cmmidi_midivst); - } -#endif // defined(SUPPORT_VSTi) - - const UINT nDevs = ::midiOutGetNumDevs(); - for (UINT i = 0; i +#include "resource.h" +#include "c_midi.h" +#include "commng\cmmidi.h" +#if defined(SUPPORT_VSTi) +#include "commng\cmmidioutvst.h" +#endif // defined(SUPPORT_VSTi) +#if defined(MT32SOUND_DLL) +#include "..\ext\mt32snd.h" +#endif // defined(MT32SOUND_DLL) +#include "dialog/winfiledlg.h" + +/** + * MIDI デバイスの初期化 + */ +void CComboMidiDevice::PreSubclassWindow() +{ + // N/C + std::tstring rNC(LoadTString(IDS_NONCONNECT)); + AddString(rNC.c_str()); +} + +/** + * MIDI IN デバイスの列挙 + */ +void CComboMidiDevice::EnumerateMidiIn() +{ + const UINT nDevs = ::midiInGetNumDevs(); + for (UINT i = 0; i < nDevs; i++) + { + MIDIINCAPS mic; + if (::midiInGetDevCaps(i, &mic, sizeof(mic)) == MMSYSERR_NOERROR) + { + AddString(mic.szPname); + } + } +} + +/** + * MIDI OUT デバイスの列挙 + */ +void CComboMidiDevice::EnumerateMidiOut() +{ + // MIDI MAPPER + AddString(cmmidi_midimapper); + + // Vermouth +#if defined(VERMOUTH_LIB) + AddString(cmmidi_vermouth); +#endif // defined(VERMOUTH_LIB) + + // MT32Sound +#if defined(MT32SOUND_DLL) + if (MT32Sound::GetInstance()->IsEnabled()) + { + AddString(cmmidi_mt32sound); + } +#endif // defined(MT32SOUND_DLL) + +#if defined(SUPPORT_VSTi) + if (CComMidiOutVst::IsEnabled()) + { + AddString(cmmidi_midivst); + } +#endif // defined(SUPPORT_VSTi) + + const UINT nDevs = ::midiOutGetNumDevs(); + for (UINT i = 0; i -#include "c_slidervalue.h" - -/** - * コンストラクタ - */ -CSliderValue::CSliderValue() - : m_nStaticId(0) -{ -} - -/** - * 範囲の設定 - * @param[in] nMin 最小値 - * @param[in] nMax 最大値 - * @param[in] bRedraw 再描画フラグ - */ -void CSliderValue::SetRange(int nMin, int nMax, BOOL bRedraw) -{ - SetRangeMin(nMin, FALSE); - SetRangeMax(nMax, bRedraw); -} - -/** - * 値の設定 - * @param[in] nPos 値 - */ -void CSliderValue::SetPos(int nPos) -{ - CSliderProc::SetPos(nPos); - UpdateValue(); -} - -/** - * 値の更新 - */ -void CSliderValue::UpdateValue() -{ - if (m_nStaticId) - { - GetParent().SetDlgItemInt(m_nStaticId, GetPos(), TRUE); - } -} +/** + * @file c_slidervalue.cpp + * @brief 値付きスライダー クラスの動作の定義を行います + */ + +#include +#include "c_slidervalue.h" + +/** + * コンストラクタ + */ +CSliderValue::CSliderValue() + : m_nStaticId(0) +{ +} + +/** + * 範囲の設定 + * @param[in] nMin 最小値 + * @param[in] nMax 最大値 + * @param[in] bRedraw 再描画フラグ + */ +void CSliderValue::SetRange(int nMin, int nMax, BOOL bRedraw) +{ + SetRangeMin(nMin, FALSE); + SetRangeMax(nMax, bRedraw); +} + +/** + * 値の設定 + * @param[in] nPos 値 + */ +void CSliderValue::SetPos(int nPos) +{ + CSliderProc::SetPos(nPos); + UpdateValue(); +} + +/** + * 値の更新 + */ +void CSliderValue::UpdateValue() +{ + if (m_nStaticId) + { + GetParent().SetDlgItemInt(m_nStaticId, GetPos(), TRUE); + } +} diff --git a/windows/dialog/c_slidervalue.h b/windows/dialog/c_slidervalue.h old mode 100755 new mode 100644 index 666def24..29df1225 --- a/windows/dialog/c_slidervalue.h +++ b/windows/dialog/c_slidervalue.h @@ -1,33 +1,33 @@ -/** - * @file c_slidervalue.h - * @brief 値付きスライダー クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "misc/DlgProc.h" - -/** - * @brief スライダー クラス - */ -class CSliderValue : public CSliderProc -{ -public: - CSliderValue(); - void SetRange(int nMin, int nMax, BOOL bRedraw = FALSE); - void SetPos(int nPos); - void SetStaticId(UINT nId); - void UpdateValue(); - -private: - UINT m_nStaticId; /*!< 値コントロール */ -}; - -/** - * 値コントロールの指定 - * @param[in] nId コントロール ID - */ -inline void CSliderValue::SetStaticId(UINT nId) -{ - m_nStaticId = nId; -} +/** + * @file c_slidervalue.h + * @brief 値付きスライダー クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "misc/DlgProc.h" + +/** + * @brief スライダー クラス + */ +class CSliderValue : public CSliderProc +{ +public: + CSliderValue(); + void SetRange(int nMin, int nMax, BOOL bRedraw = FALSE); + void SetPos(int nPos); + void SetStaticId(UINT nId); + void UpdateValue(); + +private: + UINT m_nStaticId; /*!< 値コントロール */ +}; + +/** + * 値コントロールの指定 + * @param[in] nId コントロール ID + */ +inline void CSliderValue::SetStaticId(UINT nId) +{ + m_nStaticId = nId; +} diff --git a/windows/dialog/d_about.cpp b/windows/dialog/d_about.cpp old mode 100755 new mode 100644 index 78948697..fef70d09 --- a/windows/dialog/d_about.cpp +++ b/windows/dialog/d_about.cpp @@ -1,141 +1,141 @@ -/** - * @file d_about.cpp - * @brief バージョン情報ダイアログ - */ - -#include -#include "resource.h" -#include "dialog.h" -#include "np2class.h" -#include -#include "misc/DlgProc.h" -#include -#include -#include - -//! タイトル -static const TCHAR s_np2title[] = TEXT(PROJECTNAME) TEXT(PROJECTSUBNAME) TEXT(" "); - -//! 情報 -static const TCHAR s_np2infostr[] = TEXT("CPU: %CPU% %CLOCK%\nMEM: %MEM1%\nFPU:%FPU%\nSIMD:%SIMD%\nGDC: %GDC%\n %GDC2%\nTEXT: %TEXT%\nGRPH: %GRPH%\nSOUND: %EXSND%\n\nBIOS: %BIOS%\nRHYTHM: %RHYTHM%\n\nSCREEN: %DISP%"); - -/** - * @brief バージョン情報ダイアログ - * @param[in] hwndParent 親ウィンドウ - */ -class CAboutDlg : public CDlgProc -{ -public: - CAboutDlg(HWND hwndParent); - -protected: - virtual BOOL OnInitDialog(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - -private: - SIZE m_szAbout; //!< ウィンドウのサイズ - void GetDlgItemRect(UINT nID, RECT& rect); -}; - -/** - * コンストラクタ - * @param[in] hwndParent 親ウィンドウ - */ -CAboutDlg::CAboutDlg(HWND hwndParent) - : CDlgProc(IDD_ABOUT, hwndParent) -{ - ZeroMemory(&m_szAbout, sizeof(m_szAbout)); -} - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL CAboutDlg::OnInitDialog() -{ - TCHAR szWork[256]; - milstr_ncpy(szWork, s_np2title, _countof(szWork)); -#if defined(NP2VER_WIN9X) - milstr_ncat(szWork, "\n", _countof(szWork)); - milstr_ncat(szWork, NP2VER_WIN9X, _countof(szWork)); -#endif - milstr_ncat(szWork, "\n", _countof(szWork)); - milstr_ncat(szWork, NP2KAI_GIT_TAG, _countof(szWork)); - milstr_ncat(szWork, " ", _countof(szWork)); - milstr_ncat(szWork, NP2KAI_GIT_HASH, _countof(szWork)); - SetDlgItemText(IDC_NP2VER, szWork); - - RECT rect; - GetWindowRect(&rect); - m_szAbout.cx = rect.right - rect.left; - m_szAbout.cy = rect.bottom - rect.top; - - - RECT rectMore; - GetDlgItemRect(IDC_MORE, rectMore); - RECT rectInfo; - GetDlgItemRect(IDC_NP2INFO, rectInfo); - const int nHeight = m_szAbout.cy - (rectInfo.bottom - rectMore.bottom); - - CWndBase wndParent = GetParent(); - wndParent.GetClientRect(&rect); - - POINT pt; - pt.x = (rect.right - rect.left - m_szAbout.cx) / 2; - pt.y = (rect.bottom - rect.top - m_szAbout.cy) / 2; - wndParent.ClientToScreen(&pt); - np2class_move(m_hWnd, pt.x, pt.y, m_szAbout.cx, nHeight); - - GetDlgItem(IDOK).SetFocus(); - - return TRUE; -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL CAboutDlg::OnCommand(WPARAM wParam, LPARAM lParam) -{ - if (LOWORD(wParam) == IDC_MORE) - { - TCHAR szInfo[4096]; - np2info(szInfo, s_np2infostr, _countof(szInfo), NULL); - - SetDlgItemText(IDC_NP2INFO, szInfo); - GetDlgItem(IDC_MORE).EnableWindow(FALSE); - - RECT rect; - GetWindowRect(&rect); - np2class_move(m_hWnd, rect.left, rect.top, m_szAbout.cx, m_szAbout.cy); - GetDlgItem(IDOK).SetFocus(); - - return TRUE; - } - return FALSE; -} - -/** - * アイテムの領域を得る - * @param[in] nID ID - * @param[out] rect 領域 - */ -void CAboutDlg::GetDlgItemRect(UINT nID, RECT& rect) -{ - CWndBase wnd = GetDlgItem(nID); - wnd.GetWindowRect(&rect); - ::MapWindowPoints(HWND_DESKTOP, m_hWnd, reinterpret_cast(&rect), 2); -} - -/** - * バージョン情報ダイアログ - * @param[in] hwndParent 親ウィンドウ - */ -void dialog_about(HWND hwndParent) -{ - CAboutDlg dlg(hwndParent); - dlg.DoModal(); -} +/** + * @file d_about.cpp + * @brief バージョン情報ダイアログ + */ + +#include +#include "resource.h" +#include "dialog.h" +#include "np2class.h" +#include +#include "misc/DlgProc.h" +#include +#include +#include + +//! タイトル +static const TCHAR s_np2title[] = TEXT(PROJECTNAME) TEXT(PROJECTSUBNAME) TEXT(" "); + +//! 情報 +static const TCHAR s_np2infostr[] = TEXT("CPU: %CPU% %CLOCK%\nMEM: %MEM1%\nFPU:%FPU%\nSIMD:%SIMD%\nGDC: %GDC%\n %GDC2%\nTEXT: %TEXT%\nGRPH: %GRPH%\nSOUND: %EXSND%\n\nBIOS: %BIOS%\nRHYTHM: %RHYTHM%\n\nSCREEN: %DISP%"); + +/** + * @brief バージョン情報ダイアログ + * @param[in] hwndParent 親ウィンドウ + */ +class CAboutDlg : public CDlgProc +{ +public: + CAboutDlg(HWND hwndParent); + +protected: + virtual BOOL OnInitDialog(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + +private: + SIZE m_szAbout; //!< ウィンドウのサイズ + void GetDlgItemRect(UINT nID, RECT& rect); +}; + +/** + * コンストラクタ + * @param[in] hwndParent 親ウィンドウ + */ +CAboutDlg::CAboutDlg(HWND hwndParent) + : CDlgProc(IDD_ABOUT, hwndParent) +{ + ZeroMemory(&m_szAbout, sizeof(m_szAbout)); +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL CAboutDlg::OnInitDialog() +{ + TCHAR szWork[256]; + milstr_ncpy(szWork, s_np2title, _countof(szWork)); +#if defined(NP2VER_WIN9X) + milstr_ncat(szWork, "\n", _countof(szWork)); + milstr_ncat(szWork, NP2VER_WIN9X, _countof(szWork)); +#endif + milstr_ncat(szWork, "\n", _countof(szWork)); + milstr_ncat(szWork, NP2KAI_GIT_TAG, _countof(szWork)); + milstr_ncat(szWork, " ", _countof(szWork)); + milstr_ncat(szWork, NP2KAI_GIT_HASH, _countof(szWork)); + SetDlgItemText(IDC_NP2VER, szWork); + + RECT rect; + GetWindowRect(&rect); + m_szAbout.cx = rect.right - rect.left; + m_szAbout.cy = rect.bottom - rect.top; + + + RECT rectMore; + GetDlgItemRect(IDC_MORE, rectMore); + RECT rectInfo; + GetDlgItemRect(IDC_NP2INFO, rectInfo); + const int nHeight = m_szAbout.cy - (rectInfo.bottom - rectMore.bottom); + + CWndBase wndParent = GetParent(); + wndParent.GetClientRect(&rect); + + POINT pt; + pt.x = (rect.right - rect.left - m_szAbout.cx) / 2; + pt.y = (rect.bottom - rect.top - m_szAbout.cy) / 2; + wndParent.ClientToScreen(&pt); + np2class_move(m_hWnd, pt.x, pt.y, m_szAbout.cx, nHeight); + + GetDlgItem(IDOK).SetFocus(); + + return TRUE; +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL CAboutDlg::OnCommand(WPARAM wParam, LPARAM lParam) +{ + if (LOWORD(wParam) == IDC_MORE) + { + TCHAR szInfo[4096]; + np2info(szInfo, s_np2infostr, _countof(szInfo), NULL); + + SetDlgItemText(IDC_NP2INFO, szInfo); + GetDlgItem(IDC_MORE).EnableWindow(FALSE); + + RECT rect; + GetWindowRect(&rect); + np2class_move(m_hWnd, rect.left, rect.top, m_szAbout.cx, m_szAbout.cy); + GetDlgItem(IDOK).SetFocus(); + + return TRUE; + } + return FALSE; +} + +/** + * アイテムの領域を得る + * @param[in] nID ID + * @param[out] rect 領域 + */ +void CAboutDlg::GetDlgItemRect(UINT nID, RECT& rect) +{ + CWndBase wnd = GetDlgItem(nID); + wnd.GetWindowRect(&rect); + ::MapWindowPoints(HWND_DESKTOP, m_hWnd, reinterpret_cast(&rect), 2); +} + +/** + * バージョン情報ダイアログ + * @param[in] hwndParent 親ウィンドウ + */ +void dialog_about(HWND hwndParent) +{ + CAboutDlg dlg(hwndParent); + dlg.DoModal(); +} diff --git a/windows/dialog/d_bmp.cpp b/windows/dialog/d_bmp.cpp old mode 100755 new mode 100644 index bb83d137..ae48754e --- a/windows/dialog/d_bmp.cpp +++ b/windows/dialog/d_bmp.cpp @@ -1,110 +1,110 @@ -/** - * @file d_bmp.cpp - * @brief bmp dialog - */ - -#include -#include "resource.h" -#include "dialog.h" -#include -#include -#include -#include "misc/DlgProc.h" -#include -#include -#include -#include -#include -#ifdef SUPPORT_WAB -#include -#include -#endif -#include "dialog/winfiledlg.h" - -/** フィルター */ -static const UINT s_nFilter[4] = -{ - IDS_BMPFILTER1, - IDS_BMPFILTER4, - IDS_BMPFILTER8, - IDS_BMPFILTER24 -}; - -/** - * デフォルト ファイルを得る - * @param[in] lpExt 拡張子 - * @param[out] lpFilename ファイル名 - * @param[in] cchFilename ファイル名長 - */ -static void GetDefaultFilename(LPCTSTR lpExt, LPTSTR lpFilename, UINT cchFilename) -{ - for (UINT i = 0; i < 10000; i++) - { - TCHAR szFilename[MAX_PATH]; - wsprintf(szFilename, TEXT("NP2_%04d.%s"), i, lpExt); - - file_cpyname(lpFilename, bmpfilefolder, cchFilename); - file_cutname(lpFilename); - file_catname(lpFilename, szFilename, cchFilename); - - if (file_attr(lpFilename) == -1) - { - break; - } - } -} - - -/** - * BMP 出力 - * @param[in] hWnd 親ウィンドウ - */ -void dialog_writebmp(HWND hWnd) -{ - SCRNSAVE ss = scrnsave_create(); - if (ss == NULL) - { - return; - } - int nType = scrnsave_gettype(ss); -#ifdef SUPPORT_WAB - if(np2wab.relay){ - nType = 3; - } -#endif - - std::tstring rExt(LoadTString(IDS_BMPEXT)); - std::tstring rFilter(LoadTString(s_nFilter[nType])); - std::tstring rTitle(LoadTString(IDS_BMPTITLE)); - - TCHAR szPath[MAX_PATH]; - TCHAR szName[MAX_PATH]; - GetDefaultFilename(rExt.c_str(), szPath, _countof(szPath)); - - OPENFILENAMEW ofnw; - if (WinFileDialogW(hWnd, &ofnw, WINFILEDIALOGW_MODE_SET, szPath, szName, rExt.c_str(), rTitle.c_str(), rFilter.c_str(), 1)) - { - LPCTSTR lpFilename = szPath; - file_cpyname(bmpfilefolder, lpFilename, _countof(bmpfilefolder)); - sysmng_update(SYS_UPDATEOSCFG); - - LPCTSTR lpExt = file_getext(szPath); - if ((nType <= SCRNSAVE_8BIT) && (!file_cmpname(lpExt, TEXT("gif")))) - { - scrnsave_writegif(ss, lpFilename, SCRNSAVE_AUTO); - } - else if (!file_cmpname(lpExt, str_bmp)) - { -#ifdef SUPPORT_WAB - if(np2wab.relay){ - np2wab_writebmp(lpFilename); - }else{ -#endif - scrnsave_writebmp(ss, lpFilename, SCRNSAVE_AUTO); -#ifdef SUPPORT_WAB - } -#endif - } - } - scrnsave_destroy(ss); -} +/** + * @file d_bmp.cpp + * @brief bmp dialog + */ + +#include +#include "resource.h" +#include "dialog.h" +#include +#include +#include +#include "misc/DlgProc.h" +#include +#include +#include +#include +#include +#ifdef SUPPORT_WAB +#include +#include +#endif +#include "dialog/winfiledlg.h" + +/** フィルター */ +static const UINT s_nFilter[4] = +{ + IDS_BMPFILTER1, + IDS_BMPFILTER4, + IDS_BMPFILTER8, + IDS_BMPFILTER24 +}; + +/** + * デフォルト ファイルを得る + * @param[in] lpExt 拡張子 + * @param[out] lpFilename ファイル名 + * @param[in] cchFilename ファイル名長 + */ +static void GetDefaultFilename(LPCTSTR lpExt, LPTSTR lpFilename, UINT cchFilename) +{ + for (UINT i = 0; i < 10000; i++) + { + TCHAR szFilename[MAX_PATH]; + wsprintf(szFilename, TEXT("NP2_%04d.%s"), i, lpExt); + + file_cpyname(lpFilename, bmpfilefolder, cchFilename); + file_cutname(lpFilename); + file_catname(lpFilename, szFilename, cchFilename); + + if (file_attr(lpFilename) == -1) + { + break; + } + } +} + + +/** + * BMP 出力 + * @param[in] hWnd 親ウィンドウ + */ +void dialog_writebmp(HWND hWnd) +{ + SCRNSAVE ss = scrnsave_create(); + if (ss == NULL) + { + return; + } + int nType = scrnsave_gettype(ss); +#ifdef SUPPORT_WAB + if(np2wab.relay){ + nType = 3; + } +#endif + + std::tstring rExt(LoadTString(IDS_BMPEXT)); + std::tstring rFilter(LoadTString(s_nFilter[nType])); + std::tstring rTitle(LoadTString(IDS_BMPTITLE)); + + TCHAR szPath[MAX_PATH]; + TCHAR szName[MAX_PATH]; + GetDefaultFilename(rExt.c_str(), szPath, _countof(szPath)); + + OPENFILENAMEW ofnw; + if (WinFileDialogW(hWnd, &ofnw, WINFILEDIALOGW_MODE_SET, szPath, szName, rExt.c_str(), rTitle.c_str(), rFilter.c_str(), 1)) + { + LPCTSTR lpFilename = szPath; + file_cpyname(bmpfilefolder, lpFilename, _countof(bmpfilefolder)); + sysmng_update(SYS_UPDATEOSCFG); + + LPCTSTR lpExt = file_getext(szPath); + if ((nType <= SCRNSAVE_8BIT) && (!file_cmpname(lpExt, TEXT("gif")))) + { + scrnsave_writegif(ss, lpFilename, SCRNSAVE_AUTO); + } + else if (!file_cmpname(lpExt, str_bmp)) + { +#ifdef SUPPORT_WAB + if(np2wab.relay){ + np2wab_writebmp(lpFilename); + }else{ +#endif + scrnsave_writebmp(ss, lpFilename, SCRNSAVE_AUTO); +#ifdef SUPPORT_WAB + } +#endif + } + } + scrnsave_destroy(ss); +} diff --git a/windows/dialog/d_cfgload.cpp b/windows/dialog/d_cfgload.cpp old mode 100755 new mode 100644 index ed024c02..dbe32d28 --- a/windows/dialog/d_cfgload.cpp +++ b/windows/dialog/d_cfgload.cpp @@ -1,88 +1,88 @@ -/** - * @file d_cfgload.cpp - * @brief load VM configuration dialog - */ - -#include -#include "resource.h" -#include "dialog.h" -#include -#include -#include -#include -#include "misc/DlgProc.h" -#include -#include -#include -#include -#include "np2arg.h" -#include -#include -#include "subwnd/toolwnd.h" -#include "subwnd/kdispwnd.h" -#include "subwnd/skbdwnd.h" -#include "subwnd/mdbgwnd.h" -#if defined(SUPPORT_WAB) -#include -#endif -#include "dialog/winfiledlg.h" - -/** フィルター */ -static const UINT s_nFilter[1] = -{ - IDS_CFGFILTER_L -}; - -static int messagebox(HWND hWnd, LPCTSTR lpcszText, UINT uType) -{ - LPCTSTR szCaption = np2oscfg.titles; - - std::tstring rText(LoadTString(lpcszText)); - return MessageBox(hWnd, rText.c_str(), szCaption, uType); -} - -/** - * VM configuration 読み込み - * @param[in] hWnd 親ウィンドウ - */ -int dialog_readnpcfg(HWND hWnd) -{ - std::tstring rExt(LoadTString(IDS_CFGEXT)); - std::tstring rFilter(LoadTString(s_nFilter[0])); - std::tstring rTitle(LoadTString(IDS_CFGTITLE_L)); - - TCHAR szPath[MAX_PATH] = {0}; - TCHAR szName[MAX_PATH] = {0}; - file_cpyname(szPath, npcfgfilefolder, _countof(szPath)); - - CFileDlg dlg(TRUE, rExt.c_str(), szPath, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, rFilter.c_str(), hWnd); - dlg.m_ofn.lpstrTitle = rTitle.c_str(); - dlg.m_ofn.nFilterIndex = 1; - OPENFILENAMEW ofnw; - if (WinFileDialogW(hWnd, &ofnw, WINFILEDIALOGW_MODE_GET1, szPath, szName, rExt.c_str(), rTitle.c_str(), rFilter.c_str(), 1)) - { - LPCTSTR lpFilename = dlg.GetPathName(); - file_cpyname(npcfgfilefolder, lpFilename, _countof(bmpfilefolder)); - sysmng_update(SYS_UPDATEOSCFG); - BOOL b = FALSE; - if (!np2oscfg.comfirm) { - b = TRUE; - } - else - { - if (messagebox(hWnd, MAKEINTRESOURCE(IDS_CONFIRM_EXIT), - MB_ICONQUESTION | MB_YESNO) == IDYES) - { - b = TRUE; - } - } - if (b) { - np2_multithread_Suspend(); - unloadNP2INI(); - loadNP2INI(lpFilename); - np2_multithread_Resume(); - return 1; - } - } - return 0; -} +/** + * @file d_cfgload.cpp + * @brief load VM configuration dialog + */ + +#include +#include "resource.h" +#include "dialog.h" +#include +#include +#include +#include +#include "misc/DlgProc.h" +#include +#include +#include +#include +#include "np2arg.h" +#include +#include +#include "subwnd/toolwnd.h" +#include "subwnd/kdispwnd.h" +#include "subwnd/skbdwnd.h" +#include "subwnd/mdbgwnd.h" +#if defined(SUPPORT_WAB) +#include +#endif +#include "dialog/winfiledlg.h" + +/** フィルター */ +static const UINT s_nFilter[1] = +{ + IDS_CFGFILTER_L +}; + +static int messagebox(HWND hWnd, LPCTSTR lpcszText, UINT uType) +{ + LPCTSTR szCaption = np2oscfg.titles; + + std::tstring rText(LoadTString(lpcszText)); + return MessageBox(hWnd, rText.c_str(), szCaption, uType); +} + +/** + * VM configuration 読み込み + * @param[in] hWnd 親ウィンドウ + */ +int dialog_readnpcfg(HWND hWnd) +{ + std::tstring rExt(LoadTString(IDS_CFGEXT)); + std::tstring rFilter(LoadTString(s_nFilter[0])); + std::tstring rTitle(LoadTString(IDS_CFGTITLE_L)); + + TCHAR szPath[MAX_PATH] = {0}; + TCHAR szName[MAX_PATH] = {0}; + file_cpyname(szPath, npcfgfilefolder, _countof(szPath)); + + CFileDlg dlg(TRUE, rExt.c_str(), szPath, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, rFilter.c_str(), hWnd); + dlg.m_ofn.lpstrTitle = rTitle.c_str(); + dlg.m_ofn.nFilterIndex = 1; + OPENFILENAMEW ofnw; + if (WinFileDialogW(hWnd, &ofnw, WINFILEDIALOGW_MODE_GET1, szPath, szName, rExt.c_str(), rTitle.c_str(), rFilter.c_str(), 1)) + { + LPCTSTR lpFilename = dlg.GetPathName(); + file_cpyname(npcfgfilefolder, lpFilename, _countof(bmpfilefolder)); + sysmng_update(SYS_UPDATEOSCFG); + BOOL b = FALSE; + if (!np2oscfg.comfirm) { + b = TRUE; + } + else + { + if (messagebox(hWnd, MAKEINTRESOURCE(IDS_CONFIRM_EXIT), + MB_ICONQUESTION | MB_YESNO) == IDYES) + { + b = TRUE; + } + } + if (b) { + np2_multithread_Suspend(); + unloadNP2INI(); + loadNP2INI(lpFilename); + np2_multithread_Resume(); + return 1; + } + } + return 0; +} diff --git a/windows/dialog/d_cfgsave.cpp b/windows/dialog/d_cfgsave.cpp old mode 100755 new mode 100644 index 18ba891c..e7612d41 --- a/windows/dialog/d_cfgsave.cpp +++ b/windows/dialog/d_cfgsave.cpp @@ -1,113 +1,113 @@ -/** - * @file d_cfgsave.cpp - * @brief save VM configuration dialog - */ - -#include -#include "resource.h" -#include "dialog.h" -#include -#include -#include -#include "misc/DlgProc.h" -#include -#include -#include -#include -#include "np2arg.h" -#include -#include -#include "subwnd/toolwnd.h" -#include "subwnd/kdispwnd.h" -#include "subwnd/skbdwnd.h" -#include "subwnd/mdbgwnd.h" -#if defined(SUPPORT_WAB) -#include -#endif -#include "dialog/winfiledlg.h" - -/** フィルター */ -static const UINT s_nFilter[1] = -{ - IDS_CFGFILTER -}; - -/** - * デフォルト ファイルを得る - * @param[in] lpExt 拡張子 - * @param[out] lpFilename ファイル名 - * @param[in] cchFilename ファイル名長 - */ -static void GetDefaultFilename(LPCTSTR lpExt, LPTSTR lpFilename, UINT cchFilename) -{ - if(np2cfg.fddfile[0][0] || np2cfg.sasihdd[0][0]){ - TCHAR szFilename[MAX_PATH]; - TCHAR *fname, *extpos; - if(np2cfg.fddfile[0][0]){ - fname = _tcsrchr(np2cfg.fddfile[0], '\\')+1; - }else if(np2cfg.sasihdd[0][0]){ - fname = _tcsrchr(np2cfg.sasihdd[0], '\\')+1; - } - extpos = _tcsrchr(fname, '.'); - if(extpos){ - *extpos = '\0'; - wsprintf(szFilename, TEXT("%s.%s"), fname, lpExt); - *extpos = '.'; - }else{ - wsprintf(szFilename, TEXT("%s.%s"), fname, lpExt); - } - file_cpyname(lpFilename, npcfgfilefolder, cchFilename); - file_cutname(lpFilename); - file_catname(lpFilename, szFilename, cchFilename); - }else{ - for (UINT i = 0; i < 10000; i++) - { - TCHAR szFilename[MAX_PATH]; - wsprintf(szFilename, TEXT("NP2_%04d.%s"), i, lpExt); - - file_cpyname(lpFilename, npcfgfilefolder, cchFilename); - file_cutname(lpFilename); - file_catname(lpFilename, szFilename, cchFilename); - - if (file_attr(lpFilename) == -1) - { - break; - } - } - } -} - -/** - * VM configuration 出力 - * @param[in] hWnd 親ウィンドウ - */ -void dialog_writenpcfg(HWND hWnd) -{ - std::tstring rExt(LoadTString(IDS_CFGEXT)); - std::tstring rFilter(LoadTString(s_nFilter[0])); - std::tstring rTitle(LoadTString(IDS_CFGTITLE)); - - TCHAR szPath[MAX_PATH]; - TCHAR szName[MAX_PATH]; - GetDefaultFilename(rExt.c_str(), szPath, _countof(szPath)); - - OPENFILENAMEW ofnw; - if (WinFileDialogW(hWnd, &ofnw, WINFILEDIALOGW_MODE_SET, szPath, szName, rExt.c_str(), rTitle.c_str(), rFilter.c_str(), 1)) - { - LPCTSTR lpFilename = szPath; - LPCTSTR lpExt = file_getext(szPath); - file_cpyname(npcfgfilefolder, lpFilename, _countof(bmpfilefolder)); - sysmng_update(SYS_UPDATEOSCFG); - LPTSTR lpFilenameBuf = (LPTSTR)malloc((_tcslen(lpFilename)+1)*sizeof(TCHAR)); - _tcscpy(lpFilenameBuf, lpFilename); - Np2Arg::GetInstance()->setiniFilename(lpFilenameBuf); - initsave(); - toolwin_writeini(); - kdispwin_writeini(); - skbdwin_writeini(); - mdbgwin_writeini(); -#if defined(SUPPORT_WAB) - wabwin_writeini(); -#endif // defined(SUPPORT_WAB) - } -} +/** + * @file d_cfgsave.cpp + * @brief save VM configuration dialog + */ + +#include +#include "resource.h" +#include "dialog.h" +#include +#include +#include +#include "misc/DlgProc.h" +#include +#include +#include +#include +#include "np2arg.h" +#include +#include +#include "subwnd/toolwnd.h" +#include "subwnd/kdispwnd.h" +#include "subwnd/skbdwnd.h" +#include "subwnd/mdbgwnd.h" +#if defined(SUPPORT_WAB) +#include +#endif +#include "dialog/winfiledlg.h" + +/** フィルター */ +static const UINT s_nFilter[1] = +{ + IDS_CFGFILTER +}; + +/** + * デフォルト ファイルを得る + * @param[in] lpExt 拡張子 + * @param[out] lpFilename ファイル名 + * @param[in] cchFilename ファイル名長 + */ +static void GetDefaultFilename(LPCTSTR lpExt, LPTSTR lpFilename, UINT cchFilename) +{ + if(np2cfg.fddfile[0][0] || np2cfg.sasihdd[0][0]){ + TCHAR szFilename[MAX_PATH]; + TCHAR *fname, *extpos; + if(np2cfg.fddfile[0][0]){ + fname = _tcsrchr(np2cfg.fddfile[0], '\\')+1; + }else if(np2cfg.sasihdd[0][0]){ + fname = _tcsrchr(np2cfg.sasihdd[0], '\\')+1; + } + extpos = _tcsrchr(fname, '.'); + if(extpos){ + *extpos = '\0'; + wsprintf(szFilename, TEXT("%s.%s"), fname, lpExt); + *extpos = '.'; + }else{ + wsprintf(szFilename, TEXT("%s.%s"), fname, lpExt); + } + file_cpyname(lpFilename, npcfgfilefolder, cchFilename); + file_cutname(lpFilename); + file_catname(lpFilename, szFilename, cchFilename); + }else{ + for (UINT i = 0; i < 10000; i++) + { + TCHAR szFilename[MAX_PATH]; + wsprintf(szFilename, TEXT("NP2_%04d.%s"), i, lpExt); + + file_cpyname(lpFilename, npcfgfilefolder, cchFilename); + file_cutname(lpFilename); + file_catname(lpFilename, szFilename, cchFilename); + + if (file_attr(lpFilename) == -1) + { + break; + } + } + } +} + +/** + * VM configuration 出力 + * @param[in] hWnd 親ウィンドウ + */ +void dialog_writenpcfg(HWND hWnd) +{ + std::tstring rExt(LoadTString(IDS_CFGEXT)); + std::tstring rFilter(LoadTString(s_nFilter[0])); + std::tstring rTitle(LoadTString(IDS_CFGTITLE)); + + TCHAR szPath[MAX_PATH]; + TCHAR szName[MAX_PATH]; + GetDefaultFilename(rExt.c_str(), szPath, _countof(szPath)); + + OPENFILENAMEW ofnw; + if (WinFileDialogW(hWnd, &ofnw, WINFILEDIALOGW_MODE_SET, szPath, szName, rExt.c_str(), rTitle.c_str(), rFilter.c_str(), 1)) + { + LPCTSTR lpFilename = szPath; + LPCTSTR lpExt = file_getext(szPath); + file_cpyname(npcfgfilefolder, lpFilename, _countof(bmpfilefolder)); + sysmng_update(SYS_UPDATEOSCFG); + LPTSTR lpFilenameBuf = (LPTSTR)malloc((_tcslen(lpFilename)+1)*sizeof(TCHAR)); + _tcscpy(lpFilenameBuf, lpFilename); + Np2Arg::GetInstance()->setiniFilename(lpFilenameBuf); + initsave(); + toolwin_writeini(); + kdispwin_writeini(); + skbdwin_writeini(); + mdbgwin_writeini(); +#if defined(SUPPORT_WAB) + wabwin_writeini(); +#endif // defined(SUPPORT_WAB) + } +} diff --git a/windows/dialog/d_clnd.cpp b/windows/dialog/d_clnd.cpp old mode 100755 new mode 100644 index 8d0b9c1b..becc2dda --- a/windows/dialog/d_clnd.cpp +++ b/windows/dialog/d_clnd.cpp @@ -1,217 +1,217 @@ -/** - * @file d_clnd.cpp - * @brief カレンダ設定ダイアログ - */ - -#include -#include "resource.h" -#include "dialog.h" -#include -#include -#include -#include "misc/DlgProc.h" -#include -#include -#include - -/** - * @brief カレンダ設定ダイアログ - * @param[in] hwndParent 親ウィンドウ - */ -class CCalendarDlg : public CDlgProc -{ -public: - CCalendarDlg(HWND hwndParent); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - -private: - void SetTime(const UINT8* cbuf); - void EnableVirtualCalendar(BOOL bEnabled); - static UINT8 getbcd(LPCTSTR str, int len); -}; - -/** - * @brief ダイアログ アイテム - */ -struct Item -{ - UINT16 res; //!< ID - UINT8 min; //!< 最小値 - UINT8 max; //!< 最大値 -}; - -/** - * アイテム - */ -static const Item s_vircal[6] = -{ - {IDC_VIRYEAR, 0x00, 0x99}, - {IDC_VIRMONTH, 0x01, 0x12}, - {IDC_VIRDAY, 0x01, 0x31}, - {IDC_VIRHOUR, 0x00, 0x23}, - {IDC_VIRMINUTE, 0x00, 0x59}, - {IDC_VIRSECOND, 0x00, 0x59} -}; - -/** - * コンストラクタ - * @param[in] hwndParent 親ウィンドウ - */ -CCalendarDlg::CCalendarDlg(HWND hwndParent) - : CDlgProc(IDD_CALENDAR, hwndParent) -{ -} - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL CCalendarDlg::OnInitDialog() -{ - // 時間をセット。 - UINT8 cbuf[6]; - calendar_getvir(cbuf); - SetTime(cbuf); - - const UINT nID = (np2cfg.calendar) ? IDC_CLNDREAL : IDC_CLNDVIR; - EnableVirtualCalendar((nID == IDC_CLNDVIR) ? TRUE : FALSE); - CheckDlgButton(nID, BST_CHECKED); - GetDlgItem(nID).SetFocus(); - return FALSE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void CCalendarDlg::OnOK() -{ - const UINT8 bMode = (IsDlgButtonChecked(IDC_CLNDREAL) != BST_UNCHECKED) ? 1 : 0; - if (np2cfg.calendar != bMode) - { - np2cfg.calendar = bMode; - sysmng_update(SYS_UPDATECFG); - } - - UINT8 cbuf[6]; - for (UINT i = 0; i < 6; i++) - { - TCHAR work[32]; - GetDlgItemText(s_vircal[i].res, work, NELEMENTS(work)); - UINT8 b = getbcd(work, 2); - if ((b >= s_vircal[i].min) && (b <= s_vircal[i].max)) - { - if (i == 1) - { - b = ((b & 0x10) * 10) + (b << 4); - } - cbuf[i] = b; - } - } - calendar_set(cbuf); - - CDlgProc::OnOK(); -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL CCalendarDlg::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_CLNDVIR: - EnableVirtualCalendar(TRUE); - return TRUE; - - case IDC_CLNDREAL: - EnableVirtualCalendar(FALSE); - return TRUE; - - case IDC_SETNOW: - { - UINT8 cbuf[6]; - calendar_getreal(cbuf); - SetTime(cbuf); - } - return TRUE; - } - return FALSE; -} - -/** - * 時間を設定する - * @param[in] cbuf カレンダ情報 - */ -void CCalendarDlg::SetTime(const UINT8* cbuf) -{ - for (UINT i = 0; i < 6; i++) - { - TCHAR work[8]; - if (i != 1) - { - wsprintf(work, str_2x, cbuf[i]); - } - else - { - wsprintf(work, str_2d, cbuf[1] >> 4); - } - SetDlgItemText(s_vircal[i].res, work); - } -} - -/** - * 仮想カレンダ アイテムの一括設定 - * @param[in] bEnabled 有効フラグ - */ -void CCalendarDlg::EnableVirtualCalendar(BOOL bEnabled) -{ - for (UINT i = 0; i < 6; i++) - { - GetDlgItem(s_vircal[i].res).EnableWindow(bEnabled); - } - GetDlgItem(IDC_SETNOW).EnableWindow(bEnabled); -} - -/** - * BCD を得る - * @param[in] str 文字列 - * @param[in] len 長さ - * @return 値 - */ -UINT8 CCalendarDlg::getbcd(LPCTSTR str, int len) -{ - UINT ret = 0; - while (len--) - { - TCHAR c = *str++; - if (!c) - { - break; - } - if ((c < '0') || (c > '9')) - { - return 0xff; - } - ret <<= 4; - ret |= (UINT)(c - '0'); - } - return static_cast(ret); -} - -/** - * カレンダ設定ダイアログ - * @param[in] hwndParent 親ウィンドウ - */ -void dialog_calendar(HWND hwndParent) -{ - CCalendarDlg dlg(hwndParent); - dlg.DoModal(); -} +/** + * @file d_clnd.cpp + * @brief カレンダ設定ダイアログ + */ + +#include +#include "resource.h" +#include "dialog.h" +#include +#include +#include +#include "misc/DlgProc.h" +#include +#include +#include + +/** + * @brief カレンダ設定ダイアログ + * @param[in] hwndParent 親ウィンドウ + */ +class CCalendarDlg : public CDlgProc +{ +public: + CCalendarDlg(HWND hwndParent); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + +private: + void SetTime(const UINT8* cbuf); + void EnableVirtualCalendar(BOOL bEnabled); + static UINT8 getbcd(LPCTSTR str, int len); +}; + +/** + * @brief ダイアログ アイテム + */ +struct Item +{ + UINT16 res; //!< ID + UINT8 min; //!< 最小値 + UINT8 max; //!< 最大値 +}; + +/** + * アイテム + */ +static const Item s_vircal[6] = +{ + {IDC_VIRYEAR, 0x00, 0x99}, + {IDC_VIRMONTH, 0x01, 0x12}, + {IDC_VIRDAY, 0x01, 0x31}, + {IDC_VIRHOUR, 0x00, 0x23}, + {IDC_VIRMINUTE, 0x00, 0x59}, + {IDC_VIRSECOND, 0x00, 0x59} +}; + +/** + * コンストラクタ + * @param[in] hwndParent 親ウィンドウ + */ +CCalendarDlg::CCalendarDlg(HWND hwndParent) + : CDlgProc(IDD_CALENDAR, hwndParent) +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL CCalendarDlg::OnInitDialog() +{ + // 時間をセット。 + UINT8 cbuf[6]; + calendar_getvir(cbuf); + SetTime(cbuf); + + const UINT nID = (np2cfg.calendar) ? IDC_CLNDREAL : IDC_CLNDVIR; + EnableVirtualCalendar((nID == IDC_CLNDVIR) ? TRUE : FALSE); + CheckDlgButton(nID, BST_CHECKED); + GetDlgItem(nID).SetFocus(); + return FALSE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void CCalendarDlg::OnOK() +{ + const UINT8 bMode = (IsDlgButtonChecked(IDC_CLNDREAL) != BST_UNCHECKED) ? 1 : 0; + if (np2cfg.calendar != bMode) + { + np2cfg.calendar = bMode; + sysmng_update(SYS_UPDATECFG); + } + + UINT8 cbuf[6]; + for (UINT i = 0; i < 6; i++) + { + TCHAR work[32]; + GetDlgItemText(s_vircal[i].res, work, NELEMENTS(work)); + UINT8 b = getbcd(work, 2); + if ((b >= s_vircal[i].min) && (b <= s_vircal[i].max)) + { + if (i == 1) + { + b = ((b & 0x10) * 10) + (b << 4); + } + cbuf[i] = b; + } + } + calendar_set(cbuf); + + CDlgProc::OnOK(); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL CCalendarDlg::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_CLNDVIR: + EnableVirtualCalendar(TRUE); + return TRUE; + + case IDC_CLNDREAL: + EnableVirtualCalendar(FALSE); + return TRUE; + + case IDC_SETNOW: + { + UINT8 cbuf[6]; + calendar_getreal(cbuf); + SetTime(cbuf); + } + return TRUE; + } + return FALSE; +} + +/** + * 時間を設定する + * @param[in] cbuf カレンダ情報 + */ +void CCalendarDlg::SetTime(const UINT8* cbuf) +{ + for (UINT i = 0; i < 6; i++) + { + TCHAR work[8]; + if (i != 1) + { + wsprintf(work, str_2x, cbuf[i]); + } + else + { + wsprintf(work, str_2d, cbuf[1] >> 4); + } + SetDlgItemText(s_vircal[i].res, work); + } +} + +/** + * 仮想カレンダ アイテムの一括設定 + * @param[in] bEnabled 有効フラグ + */ +void CCalendarDlg::EnableVirtualCalendar(BOOL bEnabled) +{ + for (UINT i = 0; i < 6; i++) + { + GetDlgItem(s_vircal[i].res).EnableWindow(bEnabled); + } + GetDlgItem(IDC_SETNOW).EnableWindow(bEnabled); +} + +/** + * BCD を得る + * @param[in] str 文字列 + * @param[in] len 長さ + * @return 値 + */ +UINT8 CCalendarDlg::getbcd(LPCTSTR str, int len) +{ + UINT ret = 0; + while (len--) + { + TCHAR c = *str++; + if (!c) + { + break; + } + if ((c < '0') || (c > '9')) + { + return 0xff; + } + ret <<= 4; + ret |= (UINT)(c - '0'); + } + return static_cast(ret); +} + +/** + * カレンダ設定ダイアログ + * @param[in] hwndParent 親ウィンドウ + */ +void dialog_calendar(HWND hwndParent) +{ + CCalendarDlg dlg(hwndParent); + dlg.DoModal(); +} diff --git a/windows/dialog/d_config.cpp b/windows/dialog/d_config.cpp index 70fc4fe4..9ffd504a 100644 --- a/windows/dialog/d_config.cpp +++ b/windows/dialog/d_config.cpp @@ -1,6 +1,6 @@ /** * @file d_config.cpp - * @brief ݒ_CAO + * @brief 設定ダイアログ */ #include "compiler.h" @@ -25,8 +25,8 @@ #endif /** - * @brief ݒ_CAO - * @param[in] hwndParent eEBhE + * @brief 設定ダイアログ + * @param[in] hwndParent 親ウィンドウ */ class CConfigureDlg : public CDlgProc { @@ -39,13 +39,13 @@ class CConfigureDlg : public CDlgProc virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); private: - CComboData m_baseClock; //!< x[X NbN - CComboData m_multiple; //!< { - CComboData m_cputype; //!< CPU - CComboData m_type; //!< ^Cv - CComboData m_name; //!< foCX - CComboData m_rate; //!< [g - CWndProc m_chk21port; //!< PC-9821|[g}bv + CComboData m_baseClock; //!< ベース クロック + CComboData m_multiple; //!< 倍率 + CComboData m_cputype; //!< CPU種類 + CComboData m_type; //!< タイプ + CComboData m_name; //!< デバイス名 + CComboData m_rate; //!< レート + CWndProc m_chk21port; //!< PC-9821ポートマップ std::vector m_dsound3; //!< DSound3 std::vector m_wasapi; //!< WASAPI std::vector m_asio; //!< ASIO @@ -56,14 +56,14 @@ class CConfigureDlg : public CDlgProc int SetCpuTypeIndex(UINT index); }; -//! R{ {bNX ACe +//! コンボ ボックス アイテム static const CComboData::Entry s_baseclock[] = { {MAKEINTRESOURCE(IDS_2_0MHZ), PCBASECLOCK20}, {MAKEINTRESOURCE(IDS_2_5MHZ), PCBASECLOCK25}, }; -//! CPU R{ {bNX ACe +//! CPU種類 コンボ ボックス アイテム static const CComboData::Entry s_cputype[] = { {MAKEINTRESOURCE(IDS_CPU_CUSTOM), 0}, @@ -94,19 +94,19 @@ static const CComboData::Entry s_cputype_286[] = {MAKEINTRESOURCE(IDS_CPU_80286), 0}, }; -//! {Xg +//! 倍率リスト static const UINT32 s_mulval[] = {1, 2, 4, 5, 6, 8, 10, 12, 16, 20, 24, 30, 32, 34, 36, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 100, 120, 140 }; -//! NbN tH[}bg +//! クロック フォーマット static const TCHAR str_clockfmt[] = _T("%2u.%.4u"); -//! TvO [g +//! サンプリング レート static const UINT32 s_nSamplingRate[] = {11025, 22050, 44100, 48000, 88200, 96000}; /** - * RXgN^ - * @param[in] hwndParent eEBhE + * コンストラクタ + * @param[in] hwndParent 親ウィンドウ */ CConfigureDlg::CConfigureDlg(HWND hwndParent) : CDlgProc(IDD_CONFIG, hwndParent) @@ -114,9 +114,9 @@ CConfigureDlg::CConfigureDlg(HWND hwndParent) } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL CConfigureDlg::OnInitDialog() { @@ -173,7 +173,7 @@ BOOL CConfigureDlg::OnInitDialog() m_chk21port.EnableWindow(FALSE); #endif - // TEh֌W + // サウンド関係 m_type.SubclassDlgItem(IDC_SOUND_DEVICE_TYPE, this); CSoundDeviceDSound3::EnumerateDevices(m_dsound3); @@ -276,7 +276,7 @@ BOOL CConfigureDlg::OnInitDialog() } /** - * XgXV + * リスト更新 */ void CConfigureDlg::UpdateDeviceList() { @@ -320,7 +320,7 @@ void CConfigureDlg::UpdateDeviceList() } /** - * np2cfg CPUID -> CPU type index ݕϊ + * np2cfg CPUID -> CPU type index 相互変換 */ int CConfigureDlg::GetCpuTypeIndex(){ #if defined(CPUCORE_IA32) @@ -835,7 +835,7 @@ int CConfigureDlg::SetCpuTypeIndex(UINT index){ strcpy(np2cfg.cpu_brandstring, CPU_BRAND_STRING_AMD_K10_PHENOM); np2cfg.cpu_brandid = CPU_BRAND_ID_AMD_K10_PHENOM; break; - case 255: // S@\gp + case 255: // 全機能使用可 np2cfg.cpu_family = 0; np2cfg.cpu_model = 0; np2cfg.cpu_stepping = 0; @@ -864,7 +864,7 @@ int CConfigureDlg::SetCpuTypeIndex(UINT index){ } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void CConfigureDlg::OnOK() { @@ -1012,10 +1012,10 @@ void CConfigureDlg::OnOK() } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL CConfigureDlg::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -1052,8 +1052,8 @@ BOOL CConfigureDlg::OnCommand(WPARAM wParam, LPARAM lParam) } /** - * NbNݒ肷 - * @param[in] nMultiple { + * クロックを設定する + * @param[in] nMultiple 倍率 */ void CConfigureDlg::SetClock(UINT nMultiple) { @@ -1073,8 +1073,8 @@ void CConfigureDlg::SetClock(UINT nMultiple) } /** - * ݒ_CAO - * @param[in] hwndParent eEBhE + * 設定ダイアログ + * @param[in] hwndParent 親ウィンドウ */ void dialog_configure(HWND hwndParent) { diff --git a/windows/dialog/d_disk.cpp b/windows/dialog/d_disk.cpp index 435002af..a92d14b2 100644 --- a/windows/dialog/d_disk.cpp +++ b/windows/dialog/d_disk.cpp @@ -28,14 +28,14 @@ extern "C" BOOL nvl_check(); #endif -// i\pij +// 進捗表示用(実装酷すぎ・・・) static int mt_progressvalue = 0; static int mt_progressmax = 100; /** - * FDD I_CAO - * @param[in] hWnd eEBhE - * @param[in] drv hCu + * FDD 選択ダイアログ + * @param[in] hWnd 親ウィンドウ + * @param[in] drv ドライブ */ void dialog_changefdd(HWND hWnd, REG8 drv) { @@ -70,9 +70,9 @@ void dialog_changefdd(HWND hWnd, REG8 drv) } /** - * HDD I_CAO - * @param[in] hWnd eEBhE - * @param[in] drv hCu + * HDD 選択ダイアログ + * @param[in] hWnd 親ウィンドウ + * @param[in] drv ドライブ */ void dialog_changehdd(HWND hWnd, REG8 drv) { @@ -178,21 +178,21 @@ void dialog_changehdd(HWND hWnd, REG8 drv) std::tstring rFilter(LoadTString(nFilter)); std::tstring rTitle(LoadTString(nTitle)); - if(nIndex==0){ // All supported filesi납2ԖځjI + if(nIndex==0){ // All supported files(後ろから2番目)を自動選択 int seppos = 0; int seppostmp; int sepcount = 0; - // ؂蕶̐𐔂 + // 区切り文字の数を数える while((seppostmp = (int)rFilter.find('|', seppos)) != std::string::npos){ if(seppostmp == std::string::npos) break; seppos = seppostmp + 1; sepcount++; } if(rFilter.back()!='|'){ - sepcount++; // |łȂ΂̂Ƃ + sepcount++; // 末尾が|でなければあるものとする } if((sepcount / 2) - 1 > 0){ - nIndex = (sepcount / 2) - 1; // ŌオAll filesȂ̂ň‘OI + nIndex = (sepcount / 2) - 1; // 最後がAll filesなので一つ前を選択 } } @@ -222,17 +222,17 @@ void dialog_changehdd(HWND hWnd, REG8 drv) // ---- newdisk -/** ftHg */ +/** デフォルト名 */ static const TCHAR str_newdisk[] = TEXT("newdisk"); -/** HDD TCY */ +/** HDD サイズ */ #ifdef SUPPORT_LARGE_HDD static const UINT32 s_hddsizetbl[] = {20, 41, 65, 80, 127, 255, 511, 1023, 2047, 4095, 8191}; #else static const UINT32 s_hddsizetbl[] = {20, 41, 65, 80, 127, 255, 511, 1023, 2047}; #endif -/** HDD TCY */ +/** HDD サイズ */ static const UINT32 s_hddCtbl[] = {16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65535}; static const UINT32 s_hddHtbl[] = { 8, 15, 16}; static const UINT32 s_hddStbl[] = {17, 63, 255}; @@ -257,16 +257,16 @@ static const SASIHDD s_sasihddtbl[] = { {33, 8, 615}}; // 40MB /** - * @brief VHDD + * @brief 新しいHDD */ class CNewHddDlg : public CDlgProc { public: /** - * RXgN^ - * @param[in] hwndParent eEBhE - * @param[in] nHddMinSize ŏTCY - * @param[in] nHddMaxSize őTCY + * コンストラクタ + * @param[in] hwndParent 親ウィンドウ + * @param[in] nHddMinSize 最小サイズ + * @param[in] nHddMaxSize 最大サイズ */ CNewHddDlg(HWND hwndParent, UINT32 nHddMinSize, UINT32 nHddMaxSize, UINT8 allowsasi, UINT8 isSCSI = 0) : CDlgProc(IDD_NEWHDDDISK, hwndParent) @@ -287,15 +287,15 @@ class CNewHddDlg : public CDlgProc } /** - * fXgN^ + * デストラクタ */ virtual ~CNewHddDlg() { } /** - * TCYԂ - * @return TCY + * サイズを返す + * @return サイズ */ UINT32 GetSize() const { @@ -303,8 +303,8 @@ class CNewHddDlg : public CDlgProc } /** - * V_Ԃ - * @return TCY + * シリンダ数を返す + * @return サイズ */ UINT GetC() const { @@ -312,8 +312,8 @@ class CNewHddDlg : public CDlgProc } /** - * wbhԂ - * @return TCY + * ヘッド数を返す + * @return サイズ */ UINT GetH() const { @@ -321,8 +321,8 @@ class CNewHddDlg : public CDlgProc } /** - * ZN^Ԃ - * @return TCY + * セクタ数を返す + * @return サイズ */ UINT GetS() const { @@ -330,8 +330,8 @@ class CNewHddDlg : public CDlgProc } /** - * ZN^TCYԂ - * @return TCY + * セクタサイズを返す + * @return サイズ */ UINT GetSS() const { @@ -339,8 +339,8 @@ class CNewHddDlg : public CDlgProc } /** - * ڍאݒ胂[hȂtrue - * @return ڍאݒ胂[h + * 詳細設定モードならtrue + * @return 詳細設定モード */ bool IsAdvancedMode() const { @@ -348,8 +348,8 @@ class CNewHddDlg : public CDlgProc } /** - * eʉ•σ[hȂtrue - * @return ڍאݒ胂[h + * 容量可変モードならtrue + * @return 詳細設定モード */ bool IsDynamicDisk() const { @@ -357,8 +357,8 @@ class CNewHddDlg : public CDlgProc } /** - * fBXN쐬Ȃtrue - * @return ڍאݒ胂[h + * 空ディスク作成ならtrue + * @return 詳細設定モード */ bool IsBlankDisk() const { @@ -366,7 +366,7 @@ class CNewHddDlg : public CDlgProc } /** - * gݒ + * 拡張設定を許可 * @return */ void EnableAdvancedOptions() @@ -376,7 +376,7 @@ class CNewHddDlg : public CDlgProc } /** - * ITCYfBXN(VHDp) + * 動的リサイズディスクを許可(VHD用) * @return */ void EnableDynamicSize() @@ -387,7 +387,7 @@ class CNewHddDlg : public CDlgProc } /** - * fBXNTCYCHS肵ĕ\ + * ディスクサイズからCHSを自動決定して表示する * @return */ void SetCHSfromSize() @@ -448,7 +448,7 @@ class CNewHddDlg : public CDlgProc } /** - * CHSfBXNTCYɕϊĕ\ + * CHSからディスクサイズに変換して表示する * @return */ void SetSizefromCHS() @@ -471,9 +471,9 @@ class CNewHddDlg : public CDlgProc } /** - * ACë̗𓾂 + * アイテムの領域を得る * @param[in] nID ID - * @param[out] rect ̈ + * @param[out] rect 領域 */ void GetDlgItemRect(UINT nID, RECT& rect) { @@ -484,9 +484,9 @@ class CNewHddDlg : public CDlgProc protected: /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ virtual BOOL OnInitDialog() { @@ -501,8 +501,8 @@ class CNewHddDlg : public CDlgProc for(int i=0;i NHD_MAXSIZE28 ? NHD_MAXSIZE28 : m_nHddMaxSize); // \28bit LBA + ::wsprintf(work, TEXT("(%u-%uMB)"), m_nHddMinSize, m_nHddMaxSize > NHD_MAXSIZE28 ? NHD_MAXSIZE28 : m_nHddMaxSize); // 表向き28bit LBA制限 SetDlgItemText(IDC_HDDLIMIT, work); m_rdbfixsize.SubclassDlgItem(IDC_HDDADVANCED_FIXSIZE, this); @@ -572,7 +572,7 @@ class CNewHddDlg : public CDlgProc } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ virtual void OnOK() { @@ -584,10 +584,10 @@ class CNewHddDlg : public CDlgProc } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL OnCommand(WPARAM wParam, LPARAM lParam) { @@ -627,7 +627,7 @@ class CNewHddDlg : public CDlgProc m_HddS = s_sasihddtbl[selindex].sectors; m_HddSS = 256; m_nHddSize = (UINT32)((FILELEN)m_HddC * m_HddH * m_HddS * m_HddSS / 1024 / 1024); - m_nHddSize = (m_nHddSize + 4) / 5 * 5; // 5MBPʂɂ + m_nHddSize = (m_nHddSize + 4) / 5 * 5; // 5MB単位にする SetDlgItemInt(IDC_HDDADVANCED_C, m_HddC, FALSE); SetDlgItemInt(IDC_HDDADVANCED_H, m_HddH, FALSE); SetDlgItemInt(IDC_HDDADVANCED_S, m_HddS, FALSE); @@ -719,54 +719,54 @@ class CNewHddDlg : public CDlgProc } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { return CDlgProc::WindowProc(nMsg, wParam, lParam); } private: - CComboData m_hddsize; /*!< HDD TCY Rg[ */ - UINT32 m_nHddSize; /*!< HDD TCY */ - UINT32 m_nHddMinSize; /*!< ŏTCY */ - UINT32 m_nHddMaxSize; /*!< őTCY */ + CComboData m_hddsize; /*!< HDD サイズ コントロール */ + UINT32 m_nHddSize; /*!< HDD サイズ */ + UINT32 m_nHddMinSize; /*!< 最小サイズ */ + UINT32 m_nHddMaxSize; /*!< 最大サイズ */ - SIZE m_szNewDisk; //!< EBhẼTCY - CWndProc m_btnAdvanced; /*!< ڍאݒ{^ */ - UINT8 m_advanced; /*!< ڍאݒ苖ƒtO */ - UINT8 m_isSCSI; /*!< SCSItO */ + SIZE m_szNewDisk; //!< ウィンドウのサイズ + CWndProc m_btnAdvanced; /*!< 詳細設定ボタン */ + UINT8 m_advanced; /*!< 詳細設定許可フラグ */ + UINT8 m_isSCSI; /*!< SCSIフラグ */ UINT32 m_HddC; /*!< Cylinder */ UINT16 m_HddH; /*!< Head */ UINT16 m_HddS; /*!< Sector */ UINT16 m_HddSS; /*!< Sector Size(Bytes) */ - CComboData m_cmbhddC; /*!< Cylinderl Rg[ */ - CComboData m_cmbhddH; /*!< Headl Rg[ */ - CComboData m_cmbhddS; /*!< Sectorl Rg[ */ - CComboData m_cmbhddSS; /*!< Sector Sizel Rg[ */ - UINT8 m_usedynsize; /*!< I蓖ċƒtO */ - UINT8 m_dynsize; /*!< I蓖ăfBXNiVHD̂݁j */ + CComboData m_cmbhddC; /*!< Cylinder値 コントロール */ + CComboData m_cmbhddH; /*!< Head値 コントロール */ + CComboData m_cmbhddS; /*!< Sector値 コントロール */ + CComboData m_cmbhddSS; /*!< Sector Size値 コントロール */ + UINT8 m_usedynsize; /*!< 動的割り当て許可フラグ */ + UINT8 m_dynsize; /*!< 動的割り当てディスク(VHDのみ) */ CWndProc m_rdbfixsize; //!< FIXED CWndProc m_rdbdynsize; //!< DYNAMIC - UINT8 m_blank; /*!< fBXN쐬tO */ - UINT8 m_allowsasi; /*!< SASI݊`쐬”\tO */ + UINT8 m_blank; /*!< 空ディスク作成フラグ */ + UINT8 m_allowsasi; /*!< SASI互換形式作成可能フラグ */ CWndProc m_chkblank; //!< BLANK }; /** - * @brief VHDD + * @brief 新しいHDD */ class CNewSasiDlg : public CDlgProc { public: /** - * RXgN^ - * @param[in] hwndParent eEBhE + * コンストラクタ + * @param[in] hwndParent 親ウィンドウ */ CNewSasiDlg(HWND hwndParent) : CDlgProc(IDD_NEWSASI, hwndParent) @@ -775,8 +775,8 @@ class CNewSasiDlg : public CDlgProc } /** - * HDD ^Cv𓾂 - * @return HDD ^Cv + * HDD タイプを得る + * @return HDD タイプ */ UINT GetType() const { @@ -785,9 +785,9 @@ class CNewSasiDlg : public CDlgProc protected: /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ virtual BOOL OnInitDialog() { @@ -796,7 +796,7 @@ class CNewSasiDlg : public CDlgProc } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ virtual void OnOK() { @@ -812,18 +812,18 @@ class CNewSasiDlg : public CDlgProc } private: - UINT m_nType; /*!< HDD ^Cv */ + UINT m_nType; /*!< HDD タイプ */ }; /** - * @brief VFDD + * @brief 新しいFDD */ class CNewFddDlg : public CDlgProc { public: /** - * RXgN^ - * @param[in] hwndParent eEBhE + * コンストラクタ + * @param[in] hwndParent 親ウィンドウ */ CNewFddDlg(HWND hwndParent) : CDlgProc((np2cfg.usefd144) ? IDD_NEWDISK2 : IDD_NEWDISK, hwndParent) @@ -832,8 +832,8 @@ class CNewFddDlg : public CDlgProc } /** - * ^Cv𓾂 - * @return ^Cv + * タイプを得る + * @return タイプ */ UINT8 GetType() const { @@ -841,8 +841,8 @@ class CNewFddDlg : public CDlgProc } /** - * x𓾂 - * @return x + * ラベルを得る + * @return ラベル */ LPCTSTR GetLabel() const { @@ -851,9 +851,9 @@ class CNewFddDlg : public CDlgProc protected: /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ virtual BOOL OnInitDialog() { @@ -878,7 +878,7 @@ class CNewFddDlg : public CDlgProc } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ virtual void OnOK() { @@ -903,21 +903,21 @@ class CNewFddDlg : public CDlgProc } private: - UINT m_nFdType; /*!< ^Cv */ - TCHAR m_szDiskLabel[16 + 1]; /*!< x */ + UINT m_nFdType; /*!< タイプ */ + TCHAR m_szDiskLabel[16 + 1]; /*!< ラベル */ }; /** - * @brief HDD쐬i + * @brief HDD作成進捗 */ class CNewHddDlgProg : public CDlgProc { public: /** - * RXgN^ - * @param[in] hwndParent eEBhE - * @param[in] nProgMax iől - * @param[in] nProgValue iݒl + * コンストラクタ + * @param[in] hwndParent 親ウィンドウ + * @param[in] nProgMax 進捗最大値 + * @param[in] nProgValue 進捗現在値 */ CNewHddDlgProg(HWND hwndParent, UINT32 nProgMax, UINT32 nProgValue) : CDlgProc(IDD_NEWHDDPROC, hwndParent) @@ -927,15 +927,15 @@ class CNewHddDlgProg : public CDlgProc } /** - * fXgN^ + * デストラクタ */ virtual ~CNewHddDlgProg() { } /** - * vOXo[őlݒ - * @return TCY + * プログレスバー最大値を設定 + * @return サイズ */ void SetProgressMax(UINT32 value) const { @@ -943,8 +943,8 @@ class CNewHddDlgProg : public CDlgProc } /** - * vOXo[ݒlݒ - * @return TCY + * プログレスバー現在値を設定 + * @return サイズ */ void SetProgressValue(UINT32 value) const { @@ -953,9 +953,9 @@ class CNewHddDlgProg : public CDlgProc protected: /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ virtual BOOL OnInitDialog() { @@ -964,10 +964,10 @@ class CNewHddDlgProg : public CDlgProc } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL OnCommand(WPARAM wParam, LPARAM lParam) { @@ -975,11 +975,11 @@ class CNewHddDlgProg : public CDlgProc } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -991,7 +991,7 @@ class CNewHddDlgProg : public CDlgProc SetProgressValue(mt_progressvalue); SetProgressMax(mt_progressmax); if(mt_progressvalue >= mt_progressmax){ - // I + // 処理終わり CDlgProc::OnOK(); } return 0; @@ -1001,7 +1001,7 @@ class CNewHddDlgProg : public CDlgProc private: }; -static HANDLE newdisk_hThread = NULL; // fBXN쐬pXbh +static HANDLE newdisk_hThread = NULL; // ディスク作成用スレッド static int _mt_cancel = 0; static int _mt_dyndisk = 0; static int _mt_blank = 0; @@ -1023,20 +1023,20 @@ static unsigned int __stdcall newdisk_ThreadFunc(LPVOID vdParam) else if (!file_cmpname(ext, str_nhd)) { if(_mt_diskSize){ - // Seʎw胂[h + // 全容量指定モード newdisk_nhd_ex(lpPath, _mt_diskSize, _mt_blank, &mt_progressvalue, &_mt_cancel); }else{ - // CHSw胂[h + // CHS指定モード newdisk_nhd_ex_CHS(lpPath, _mt_diskC, _mt_diskH, _mt_diskS, _mt_diskSS, _mt_blank, &mt_progressvalue, &_mt_cancel); } } else if (!file_cmpname(ext, str_hdi)) { if(_mt_diskSize){ - // Seʎw胂[h + // 全容量指定モード newdisk_hdi_ex(lpPath, _mt_diskSize, _mt_blank, &mt_progressvalue, &_mt_cancel); }else{ - // CHSw胂[h + // CHS指定モード newdisk_hdi_ex_CHS(lpPath, _mt_diskC, _mt_diskH, _mt_diskS, _mt_diskSS, _mt_blank, &mt_progressvalue, &_mt_cancel); } } @@ -1054,10 +1054,10 @@ static unsigned int __stdcall newdisk_ThreadFunc(LPVOID vdParam) else if (!file_cmpname(ext, str_vhd)) { if(_mt_diskSize){ - // Seʎw胂[h + // 全容量指定モード newdisk_vpcvhd_ex(lpPath, _mt_diskSize, _mt_dyndisk, _mt_blank, &mt_progressvalue, &_mt_cancel); }else{ - // CHSw胂[h + // CHS指定モード newdisk_vpcvhd_ex_CHS(lpPath, _mt_diskC, _mt_diskH, _mt_diskS, _mt_diskSS, _mt_dyndisk, _mt_blank, &mt_progressvalue, &_mt_cancel); } } @@ -1067,8 +1067,8 @@ static unsigned int __stdcall newdisk_ThreadFunc(LPVOID vdParam) } /** - * VKfBXN쐬 _CAO - * @param[in] hWnd eEBhE + * 新規ディスク作成 ダイアログ + * @param[in] hWnd 親ウィンドウ */ void dialog_newdisk_ex(HWND hWnd, int mode) { @@ -1283,8 +1283,8 @@ void dialog_newdisk_ex(HWND hWnd, int mode) } /** - * VKfBXN쐬 _CAO - * @param[in] hWnd eEBhE + * 新規ディスク作成 ダイアログ + * @param[in] hWnd 親ウィンドウ */ void dialog_newdisk(HWND hWnd) { diff --git a/windows/dialog/d_font.cpp b/windows/dialog/d_font.cpp index e16d5a3b..3b1ce1f5 100644 --- a/windows/dialog/d_font.cpp +++ b/windows/dialog/d_font.cpp @@ -15,8 +15,8 @@ #include "font/font.h" /** - * tHgI - * @param[in] hWnd eEBhE + * フォント選択 + * @param[in] hWnd 親ウィンドウ */ void dialog_font(HWND hWnd) { diff --git a/windows/dialog/d_hostdrv.cpp b/windows/dialog/d_hostdrv.cpp index 610460fd..e295d0dc 100644 --- a/windows/dialog/d_hostdrv.cpp +++ b/windows/dialog/d_hostdrv.cpp @@ -1,6 +1,6 @@ /** * @file d_hostdrv.cpp - * @brief HOSTDRV ݒ_CAO + * @brief HOSTDRV 設定ダイアログ */ #include "compiler.h" @@ -45,8 +45,8 @@ int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpDa } /** - * @brief HOSTDRV ݒ_CAO - * @param[in] hwndParent eEBhE + * @brief HOSTDRV 設定ダイアログ + * @param[in] hwndParent 親ウィンドウ */ class CHostdrvDlg : public CDlgProc { @@ -60,10 +60,10 @@ class CHostdrvDlg : public CDlgProc virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); private: - UINT8 m_hdrvenable; //!< L - TCHAR m_hdrvroot[MAX_PATH]; //!< LfBNg - UINT8 m_hdrvacc; //!< ANZX - UINT8 m_hdrvNTenable; //!< NTL + UINT8 m_hdrvenable; //!< 有効 + TCHAR m_hdrvroot[MAX_PATH]; //!< 共有ディレクトリ + UINT8 m_hdrvacc; //!< アクセス権限 + UINT8 m_hdrvNTenable; //!< NT有効 CWndProc m_chkenabled; //!< Enabled CComboData m_cmbdir; //!< Shared Directory CWndProc m_chkread; //!< Permission: Read @@ -73,8 +73,8 @@ class CHostdrvDlg : public CDlgProc }; /** - * RXgN^ - * @param[in] hwndParent eEBhE + * コンストラクタ + * @param[in] hwndParent 親ウィンドウ */ CHostdrvDlg::CHostdrvDlg(HWND hwndParent) : CDlgProc(IDD_HOSTDRV, hwndParent) @@ -82,9 +82,9 @@ CHostdrvDlg::CHostdrvDlg(HWND hwndParent) } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL CHostdrvDlg::OnInitDialog() { @@ -138,7 +138,7 @@ BOOL CHostdrvDlg::OnInitDialog() } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void CHostdrvDlg::OnOK() { @@ -165,10 +165,10 @@ void CHostdrvDlg::OnOK() } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL CHostdrvDlg::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -279,11 +279,11 @@ BOOL CHostdrvDlg::OnCommand(WPARAM wParam, LPARAM lParam) } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT CHostdrvDlg::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -291,8 +291,8 @@ LRESULT CHostdrvDlg::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) } /** - * RtBO _CAO - * @param[in] hwndParent eEBhE + * コンフィグ ダイアログ + * @param[in] hwndParent 親ウィンドウ */ void dialog_hostdrvopt(HWND hwndParent) { @@ -301,11 +301,11 @@ void dialog_hostdrvopt(HWND hwndParent) } -//! ^Cg +//! タイトル static const TCHAR s_hostdrvapp[] = TEXT("NP2 hostdrv"); /** - * ݒ + * 設定 */ static const PFTBL s_hostdrvini[] = { @@ -322,7 +322,7 @@ static const PFTBL s_hostdrvini[] = }; /** - * ݒǂݍ + * 設定読み込み */ void hostdrv_readini() { @@ -334,7 +334,7 @@ void hostdrv_readini() } /** - * ݒ菑 + * 設定書き込み */ void hostdrv_writeini() { @@ -346,7 +346,7 @@ void hostdrv_writeini() } /** - * w肵pXŏʂ + * 指定したパスを最上位に */ void hostdrv_setcurrentpath(const TCHAR* newpath) { diff --git a/windows/dialog/d_ide.cpp b/windows/dialog/d_ide.cpp old mode 100755 new mode 100644 index 1224aafa..f01c83ce --- a/windows/dialog/d_ide.cpp +++ b/windows/dialog/d_ide.cpp @@ -1,321 +1,321 @@ -/** - * @file d_ide.cpp - * @brief IDE 設定ダイアログ - */ - -#include -#include "resource.h" -#include "dialog.h" -#include "c_combodata.h" -#include -#include -#include -#include "misc/DlgProc.h" -#include -#include - -#ifdef SUPPORT_IDEIO - -#ifdef __cplusplus -extern "C" -{ -#endif - -#ifdef __cplusplus -} -#endif - - -/** - * @brief IDE 設定ダイアログ - * @param[in] hwndParent 親ウィンドウ - */ -class CIdeDlg : public CDlgProc -{ -public: - CIdeDlg(HWND hwndParent); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - CComboData m_cmbpm; //!< プライマリ マスタ - CComboData m_cmbps; //!< プライマリ スレーブ - CComboData m_cmbsm; //!< セカンダリ マスタ - CComboData m_cmbss; //!< セカンダリ スレーブ - CWndProc m_chkasynccd; //!< Use Async CD-ROM Access - CWndProc m_chkuseecc; //!< Use CD-ROM EDC/ECC Emulation - CWndProc m_chkallowtraycmd; //!< Allow CD Tray Open/Close Command - CWndProc m_chkidebios; //!< Use IDE BIOS - CWndProc m_chkautoidebios; //!< Auto IDE BIOS - CWndProc m_nudrwait; //!< 割り込み(書き込み)ディレイ - CWndProc m_nudwwait; //!< 割り込み(書き込み)ディレイ -}; - -/** - * 割り込みリスト - */ -static const CComboData::Entry s_type[] = -{ - {MAKEINTRESOURCE(IDS_IDETYPE_NONE ), 0}, - {MAKEINTRESOURCE(IDS_IDETYPE_HDD ), 1}, - {MAKEINTRESOURCE(IDS_IDETYPE_CDROM), 2}, -}; - -/** - * コンストラクタ - * @param[in] hwndParent 親ウィンドウ - */ -CIdeDlg::CIdeDlg(HWND hwndParent) - : CDlgProc(IDD_IDE, hwndParent) -{ -} - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL CIdeDlg::OnInitDialog() -{ - TCHAR numbuf[31]; - m_cmbpm.SubclassDlgItem(IDC_IDE1TYPE, this); - m_cmbpm.Add(s_type, _countof(s_type)); - m_cmbpm.SetCurItemData(np2cfg.idetype[0]); - - m_cmbps.SubclassDlgItem(IDC_IDE2TYPE, this); - m_cmbps.Add(s_type, _countof(s_type)); - m_cmbps.SetCurItemData(np2cfg.idetype[1]); - - m_cmbsm.SubclassDlgItem(IDC_IDE3TYPE, this); - m_cmbsm.Add(s_type, _countof(s_type)); - m_cmbsm.SetCurItemData(np2cfg.idetype[2]); - - m_cmbss.SubclassDlgItem(IDC_IDE4TYPE, this); - m_cmbss.Add(s_type, _countof(s_type)); - m_cmbss.SetCurItemData(np2cfg.idetype[3]); - - - m_chkasynccd.SubclassDlgItem(IDC_USEASYNCCD, this); - if(np2cfg.useasynccd){ - m_chkasynccd.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - }else{ - m_chkasynccd.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - } - - m_chkuseecc.SubclassDlgItem(IDC_USECDECC, this); - if(np2cfg.usecdecc){ - m_chkuseecc.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - }else{ - m_chkuseecc.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - } - - m_chkallowtraycmd.SubclassDlgItem(IDC_ALLOWCDTRAYOP, this); - if(np2cfg.allowcdtraycmd){ - m_chkallowtraycmd.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - }else{ - m_chkallowtraycmd.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - } - - m_nudrwait.SubclassDlgItem(IDC_IDERWAIT, this); - _stprintf(numbuf, _T("%d"), np2cfg.iderwait); - m_nudrwait.SetWindowText(numbuf); - - m_nudwwait.SubclassDlgItem(IDC_IDEWWAIT, this); - _stprintf(numbuf, _T("%d"), np2cfg.idewwait); - m_nudwwait.SetWindowText(numbuf); - - m_chkautoidebios.SubclassDlgItem(IDC_AUTOIDEBIOS, this); - if(np2cfg.autoidebios){ - m_chkautoidebios.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - }else{ - m_chkautoidebios.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - } - - m_chkidebios.SubclassDlgItem(IDC_USEIDEBIOS, this); - if(np2cfg.idebios){ - m_chkidebios.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - m_chkautoidebios.EnableWindow(TRUE); - }else{ - m_chkidebios.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - m_chkautoidebios.EnableWindow(FALSE); - } - - m_cmbpm.SetFocus(); - - return FALSE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void CIdeDlg::OnOK() -{ - UINT update = 0; - UINT32 valtmp; - TCHAR numbuf[31]; - - if (m_cmbpm.GetCurItemData(np2cfg.idetype[0])!=np2cfg.idetype[0]) - { - np2cfg.idetype[0] = m_cmbpm.GetCurItemData(np2cfg.idetype[0]); - update |= SYS_UPDATECFG | SYS_UPDATEHDD; - } - if (m_cmbps.GetCurItemData(np2cfg.idetype[1])!=np2cfg.idetype[1]) - { - np2cfg.idetype[1] = m_cmbps.GetCurItemData(np2cfg.idetype[1]); - update |= SYS_UPDATECFG | SYS_UPDATEHDD; - } - if (m_cmbsm.GetCurItemData(np2cfg.idetype[2])!=np2cfg.idetype[2]) - { - np2cfg.idetype[2] = m_cmbsm.GetCurItemData(np2cfg.idetype[2]); - update |= SYS_UPDATECFG | SYS_UPDATEHDD; - } - if (m_cmbss.GetCurItemData(np2cfg.idetype[3])!=np2cfg.idetype[3]) - { - np2cfg.idetype[3] = m_cmbss.GetCurItemData(np2cfg.idetype[3]); - update |= SYS_UPDATECFG | SYS_UPDATEHDD; - } - if (np2cfg.useasynccd != (m_chkasynccd.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0)) - { - np2cfg.useasynccd = (m_chkasynccd.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - update |= SYS_UPDATECFG; - } - if (np2cfg.usecdecc != (m_chkuseecc.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0)) - { - np2cfg.usecdecc = (m_chkuseecc.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - update |= SYS_UPDATECFG; - } - if (np2cfg.allowcdtraycmd != (m_chkallowtraycmd.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0)) - { - np2cfg.allowcdtraycmd = (m_chkallowtraycmd.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - update |= SYS_UPDATECFG; - } - m_nudrwait.GetWindowText(numbuf, 30); - valtmp = _ttol(numbuf); - if (valtmp < 0) valtmp = 0; - if (valtmp > 100000000) valtmp = 100000000; - if (valtmp != np2cfg.iderwait) - { - np2cfg.iderwait = valtmp; - update |= SYS_UPDATECFG; - } - m_nudwwait.GetWindowText(numbuf, 30); - valtmp = _ttol(numbuf); - if (valtmp < 0) valtmp = 0; - if (valtmp > 100000000) valtmp = 100000000; - if (valtmp != np2cfg.idewwait) - { - np2cfg.idewwait = valtmp; - update |= SYS_UPDATECFG; - } - if (np2cfg.idebios != (m_chkidebios.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0)) - { - np2cfg.idebios = (m_chkidebios.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - update |= SYS_UPDATECFG; - } - if (np2cfg.autoidebios != (m_chkautoidebios.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0)) - { - np2cfg.autoidebios = (m_chkautoidebios.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - update |= SYS_UPDATECFG; - } - - sysmng_update(update); - - CDlgProc::OnOK(); -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL CIdeDlg::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_IDE1TYPE: - case IDC_IDE2TYPE: - case IDC_IDE3TYPE: - case IDC_IDE4TYPE: - return TRUE; - case IDC_USEIDEBIOS: - m_chkautoidebios.EnableWindow((m_chkidebios.SendMessage(BM_GETCHECK , 0 , 0) ? TRUE : FALSE)); - return TRUE; - } - return FALSE; -} - -/** - * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT CIdeDlg::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - LPNMUPDOWN lpnud; - UINT32 nudnum; - TCHAR numbuf[31]; - switch(wParam) - { - case IDC_SPINIDERWAIT: - lpnud = (LPNMUPDOWN)lParam; - if(lpnud->hdr.code == UDN_DELTAPOS) - { - m_nudrwait.GetWindowText(numbuf, 30); - nudnum = _ttol(numbuf); - if(lpnud->iDelta > 0) - { - if(nudnum <= 0) nudnum = 0; - else nudnum--; - } - else if(lpnud->iDelta < 0) - { - if(nudnum >= 100000000) nudnum = 100000000; - else nudnum++; - } - _stprintf(numbuf, _T("%d"), nudnum); - m_nudrwait.SetWindowText(numbuf); - } - break; - case IDC_SPINIDEWWAIT: - lpnud = (LPNMUPDOWN)lParam; - if(lpnud->hdr.code == UDN_DELTAPOS) - { - m_nudwwait.GetWindowText(numbuf, 30); - nudnum = _ttol(numbuf); - if(lpnud->iDelta > 0) - { - if(nudnum <= 0) nudnum = 0; - else nudnum--; - } - else if(lpnud->iDelta < 0) - { - if(nudnum >= 100000000) nudnum = 100000000; - else nudnum++; - } - _stprintf(numbuf, _T("%d"), nudnum); - m_nudwwait.SetWindowText(numbuf); - } - break; - } - - return CDlgProc::WindowProc(nMsg, wParam, lParam); -} - -/** - * コンフィグ ダイアログ - * @param[in] hwndParent 親ウィンドウ - */ -void dialog_ideopt(HWND hwndParent) -{ - CIdeDlg dlg(hwndParent); - dlg.DoModal(); -} - -#endif +/** + * @file d_ide.cpp + * @brief IDE 設定ダイアログ + */ + +#include +#include "resource.h" +#include "dialog.h" +#include "c_combodata.h" +#include +#include +#include +#include "misc/DlgProc.h" +#include +#include + +#ifdef SUPPORT_IDEIO + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef __cplusplus +} +#endif + + +/** + * @brief IDE 設定ダイアログ + * @param[in] hwndParent 親ウィンドウ + */ +class CIdeDlg : public CDlgProc +{ +public: + CIdeDlg(HWND hwndParent); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + CComboData m_cmbpm; //!< プライマリ マスタ + CComboData m_cmbps; //!< プライマリ スレーブ + CComboData m_cmbsm; //!< セカンダリ マスタ + CComboData m_cmbss; //!< セカンダリ スレーブ + CWndProc m_chkasynccd; //!< Use Async CD-ROM Access + CWndProc m_chkuseecc; //!< Use CD-ROM EDC/ECC Emulation + CWndProc m_chkallowtraycmd; //!< Allow CD Tray Open/Close Command + CWndProc m_chkidebios; //!< Use IDE BIOS + CWndProc m_chkautoidebios; //!< Auto IDE BIOS + CWndProc m_nudrwait; //!< 割り込み(書き込み)ディレイ + CWndProc m_nudwwait; //!< 割り込み(書き込み)ディレイ +}; + +/** + * 割り込みリスト + */ +static const CComboData::Entry s_type[] = +{ + {MAKEINTRESOURCE(IDS_IDETYPE_NONE ), 0}, + {MAKEINTRESOURCE(IDS_IDETYPE_HDD ), 1}, + {MAKEINTRESOURCE(IDS_IDETYPE_CDROM), 2}, +}; + +/** + * コンストラクタ + * @param[in] hwndParent 親ウィンドウ + */ +CIdeDlg::CIdeDlg(HWND hwndParent) + : CDlgProc(IDD_IDE, hwndParent) +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL CIdeDlg::OnInitDialog() +{ + TCHAR numbuf[31]; + m_cmbpm.SubclassDlgItem(IDC_IDE1TYPE, this); + m_cmbpm.Add(s_type, _countof(s_type)); + m_cmbpm.SetCurItemData(np2cfg.idetype[0]); + + m_cmbps.SubclassDlgItem(IDC_IDE2TYPE, this); + m_cmbps.Add(s_type, _countof(s_type)); + m_cmbps.SetCurItemData(np2cfg.idetype[1]); + + m_cmbsm.SubclassDlgItem(IDC_IDE3TYPE, this); + m_cmbsm.Add(s_type, _countof(s_type)); + m_cmbsm.SetCurItemData(np2cfg.idetype[2]); + + m_cmbss.SubclassDlgItem(IDC_IDE4TYPE, this); + m_cmbss.Add(s_type, _countof(s_type)); + m_cmbss.SetCurItemData(np2cfg.idetype[3]); + + + m_chkasynccd.SubclassDlgItem(IDC_USEASYNCCD, this); + if(np2cfg.useasynccd){ + m_chkasynccd.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + }else{ + m_chkasynccd.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + } + + m_chkuseecc.SubclassDlgItem(IDC_USECDECC, this); + if(np2cfg.usecdecc){ + m_chkuseecc.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + }else{ + m_chkuseecc.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + } + + m_chkallowtraycmd.SubclassDlgItem(IDC_ALLOWCDTRAYOP, this); + if(np2cfg.allowcdtraycmd){ + m_chkallowtraycmd.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + }else{ + m_chkallowtraycmd.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + } + + m_nudrwait.SubclassDlgItem(IDC_IDERWAIT, this); + _stprintf(numbuf, _T("%d"), np2cfg.iderwait); + m_nudrwait.SetWindowText(numbuf); + + m_nudwwait.SubclassDlgItem(IDC_IDEWWAIT, this); + _stprintf(numbuf, _T("%d"), np2cfg.idewwait); + m_nudwwait.SetWindowText(numbuf); + + m_chkautoidebios.SubclassDlgItem(IDC_AUTOIDEBIOS, this); + if(np2cfg.autoidebios){ + m_chkautoidebios.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + }else{ + m_chkautoidebios.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + } + + m_chkidebios.SubclassDlgItem(IDC_USEIDEBIOS, this); + if(np2cfg.idebios){ + m_chkidebios.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + m_chkautoidebios.EnableWindow(TRUE); + }else{ + m_chkidebios.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + m_chkautoidebios.EnableWindow(FALSE); + } + + m_cmbpm.SetFocus(); + + return FALSE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void CIdeDlg::OnOK() +{ + UINT update = 0; + UINT32 valtmp; + TCHAR numbuf[31]; + + if (m_cmbpm.GetCurItemData(np2cfg.idetype[0])!=np2cfg.idetype[0]) + { + np2cfg.idetype[0] = m_cmbpm.GetCurItemData(np2cfg.idetype[0]); + update |= SYS_UPDATECFG | SYS_UPDATEHDD; + } + if (m_cmbps.GetCurItemData(np2cfg.idetype[1])!=np2cfg.idetype[1]) + { + np2cfg.idetype[1] = m_cmbps.GetCurItemData(np2cfg.idetype[1]); + update |= SYS_UPDATECFG | SYS_UPDATEHDD; + } + if (m_cmbsm.GetCurItemData(np2cfg.idetype[2])!=np2cfg.idetype[2]) + { + np2cfg.idetype[2] = m_cmbsm.GetCurItemData(np2cfg.idetype[2]); + update |= SYS_UPDATECFG | SYS_UPDATEHDD; + } + if (m_cmbss.GetCurItemData(np2cfg.idetype[3])!=np2cfg.idetype[3]) + { + np2cfg.idetype[3] = m_cmbss.GetCurItemData(np2cfg.idetype[3]); + update |= SYS_UPDATECFG | SYS_UPDATEHDD; + } + if (np2cfg.useasynccd != (m_chkasynccd.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0)) + { + np2cfg.useasynccd = (m_chkasynccd.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + update |= SYS_UPDATECFG; + } + if (np2cfg.usecdecc != (m_chkuseecc.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0)) + { + np2cfg.usecdecc = (m_chkuseecc.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + update |= SYS_UPDATECFG; + } + if (np2cfg.allowcdtraycmd != (m_chkallowtraycmd.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0)) + { + np2cfg.allowcdtraycmd = (m_chkallowtraycmd.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + update |= SYS_UPDATECFG; + } + m_nudrwait.GetWindowText(numbuf, 30); + valtmp = _ttol(numbuf); + if (valtmp < 0) valtmp = 0; + if (valtmp > 100000000) valtmp = 100000000; + if (valtmp != np2cfg.iderwait) + { + np2cfg.iderwait = valtmp; + update |= SYS_UPDATECFG; + } + m_nudwwait.GetWindowText(numbuf, 30); + valtmp = _ttol(numbuf); + if (valtmp < 0) valtmp = 0; + if (valtmp > 100000000) valtmp = 100000000; + if (valtmp != np2cfg.idewwait) + { + np2cfg.idewwait = valtmp; + update |= SYS_UPDATECFG; + } + if (np2cfg.idebios != (m_chkidebios.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0)) + { + np2cfg.idebios = (m_chkidebios.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + update |= SYS_UPDATECFG; + } + if (np2cfg.autoidebios != (m_chkautoidebios.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0)) + { + np2cfg.autoidebios = (m_chkautoidebios.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + update |= SYS_UPDATECFG; + } + + sysmng_update(update); + + CDlgProc::OnOK(); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL CIdeDlg::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_IDE1TYPE: + case IDC_IDE2TYPE: + case IDC_IDE3TYPE: + case IDC_IDE4TYPE: + return TRUE; + case IDC_USEIDEBIOS: + m_chkautoidebios.EnableWindow((m_chkidebios.SendMessage(BM_GETCHECK , 0 , 0) ? TRUE : FALSE)); + return TRUE; + } + return FALSE; +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CIdeDlg::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + LPNMUPDOWN lpnud; + UINT32 nudnum; + TCHAR numbuf[31]; + switch(wParam) + { + case IDC_SPINIDERWAIT: + lpnud = (LPNMUPDOWN)lParam; + if(lpnud->hdr.code == UDN_DELTAPOS) + { + m_nudrwait.GetWindowText(numbuf, 30); + nudnum = _ttol(numbuf); + if(lpnud->iDelta > 0) + { + if(nudnum <= 0) nudnum = 0; + else nudnum--; + } + else if(lpnud->iDelta < 0) + { + if(nudnum >= 100000000) nudnum = 100000000; + else nudnum++; + } + _stprintf(numbuf, _T("%d"), nudnum); + m_nudrwait.SetWindowText(numbuf); + } + break; + case IDC_SPINIDEWWAIT: + lpnud = (LPNMUPDOWN)lParam; + if(lpnud->hdr.code == UDN_DELTAPOS) + { + m_nudwwait.GetWindowText(numbuf, 30); + nudnum = _ttol(numbuf); + if(lpnud->iDelta > 0) + { + if(nudnum <= 0) nudnum = 0; + else nudnum--; + } + else if(lpnud->iDelta < 0) + { + if(nudnum >= 100000000) nudnum = 100000000; + else nudnum++; + } + _stprintf(numbuf, _T("%d"), nudnum); + m_nudwwait.SetWindowText(numbuf); + } + break; + } + + return CDlgProc::WindowProc(nMsg, wParam, lParam); +} + +/** + * コンフィグ ダイアログ + * @param[in] hwndParent 親ウィンドウ + */ +void dialog_ideopt(HWND hwndParent) +{ + CIdeDlg dlg(hwndParent); + dlg.DoModal(); +} + +#endif diff --git a/windows/dialog/d_mpu98.cpp b/windows/dialog/d_mpu98.cpp index d8f11143..f4222839 100644 --- a/windows/dialog/d_mpu98.cpp +++ b/windows/dialog/d_mpu98.cpp @@ -1,815 +1,815 @@ -/** - * @file d_mpu98.cpp - * @brief MIDI ݒ_CAO - */ - -#include -#include "resource.h" -#include "dialog.h" -#include "c_combodata.h" -#include "c_dipsw.h" -#include "c_midi.h" -#include "np2class.h" -#include -#include -#include -#include "misc/PropProc.h" -#include -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -extern COMMNG cm_mpu98; -extern COMMNG cm_smpu98[]; - -#ifdef __cplusplus -} -#endif - -/** - * 荞݃Xg - */ -static const CComboData::Entry s_int[] = -{ - {MAKEINTRESOURCE(IDS_INT0), 0}, - {MAKEINTRESOURCE(IDS_INT1), 1}, - {MAKEINTRESOURCE(IDS_INT2), 2}, - {MAKEINTRESOURCE(IDS_INT5), 3}, -}; - - -/** - * @brief MPU-PC98 ݒy[W - */ -class CMpu98Page : public CPropPageProc -{ -public: - CMpu98Page(); - virtual ~CMpu98Page(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - UINT8 m_mpuenable; //!< L - UINT8 m_mpu; //!< ݒl - CWndProc m_chkenable; //!< ENABLE - CComboData m_port; //!< IO - CComboData m_int; //!< INT - CStaticDipSw m_dipsw; //!< DIPSW - CComboMidiDevice m_midiin; //!< MIDI IN - CComboMidiDevice m_midiout; //!< MIDI OUT - CComboMidiModule m_module; //!< MIDI Module - CEditMimpiFile m_mimpifile; //!< MIMPI - void OnDipSw(); - void SetJumper(UINT8 cValue, UINT8 cBit); - void SetPort(UINT8 cValue); - UINT8 GetPort() const; - void SetInt(UINT8 cValue); - UINT8 GetInt() const; -}; - -/** - * RXgN^ - */ -CMpu98Page::CMpu98Page() - : CPropPageProc(IDD_MPUPC98) - , m_mpu(0) -{ -} - - -/** - * fXgN^ - */ -CMpu98Page::~CMpu98Page() -{ -} - -/** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ - */ -BOOL CMpu98Page::OnInitDialog() -{ - m_mpuenable = np2cfg.mpuenable; - m_mpu = np2cfg.mpuopt; - - m_chkenable.SubclassDlgItem(IDC_MPUENABLE, this); - if(m_mpuenable) - m_chkenable.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkenable.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_port.SubclassDlgItem(IDC_MPUIO, this); - for (UINT i = 0; i < 16; i++) - { - TCHAR szBuf[8]; - wsprintf(szBuf, str_4X, 0xC0D0 + (i << 10)); - m_port.Add(szBuf, i << 4); - } - SetPort(m_mpu); - - m_int.SubclassDlgItem(IDC_MPUINT, this); - m_int.Add(s_int, _countof(s_int)); - SetInt(m_mpu); - - m_dipsw.SubclassDlgItem(IDC_MPUDIP, this); - - m_midiout.SubclassDlgItem(IDC_MPU98MMAP, this); - m_midiout.EnumerateMidiOut(); - m_midiout.SetCurString(np2oscfg.mpu.mout); - - m_midiin.SubclassDlgItem(IDC_MPU98MDIN, this); - m_midiin.EnumerateMidiIn(); - m_midiin.SetCurString(np2oscfg.mpu.min); - - m_module.SubclassDlgItem(IDC_MPU98MMDL, this); - m_module.SetWindowText(np2oscfg.mpu.mdl); - CheckDlgButton(IDC_MPU98DEFE, (np2oscfg.mpu.def_en) ? BST_CHECKED : BST_UNCHECKED); - - m_mimpifile.SubclassDlgItem(IDC_MPU98DEFF, this); - m_mimpifile.SetWindowText(np2oscfg.mpu.def); - - m_port.SetFocus(); - - return FALSE; -} - -/** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ - */ -void CMpu98Page::OnOK() -{ - UINT update = 0; - - if (np2cfg.mpuenable != m_mpuenable) - { - np2cfg.mpuenable = m_mpuenable; - update |= SYS_UPDATECFG; - } - - if (np2cfg.mpuopt != m_mpu) - { - np2cfg.mpuopt = m_mpu; - update |= SYS_UPDATECFG | SYS_UPDATEMIDI; - } - - TCHAR mmap[MAXPNAMELEN]; - GetDlgItemText(IDC_MPU98MMAP, mmap, _countof(mmap)); - if (milstr_cmp(np2oscfg.mpu.mout, mmap)) { - milstr_ncpy(np2oscfg.mpu.mout, mmap, NELEMENTS(np2oscfg.mpu.mout)); - update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; - } - - TCHAR mdin[MAXPNAMELEN]; - GetDlgItemText(IDC_MPU98MDIN, mdin, _countof(mdin)); - if (milstr_cmp(np2oscfg.mpu.min, mdin)) - { - milstr_ncpy(np2oscfg.mpu.min, mdin, NELEMENTS(np2oscfg.mpu.min)); - update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; - } - - TCHAR mmdl[64]; - GetDlgItemText(IDC_MPU98MMDL, mmdl, _countof(mmdl)); - if (milstr_cmp(np2oscfg.mpu.mdl, mmdl)) - { - milstr_ncpy(np2oscfg.mpu.mdl, mmdl, NELEMENTS(np2oscfg.mpu.mdl)); - update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; - } - - np2oscfg.mpu.def_en = (IsDlgButtonChecked(IDC_MPU98DEFE) != BST_UNCHECKED) ? 1 : 0; - - if (cm_mpu98) - { - cm_mpu98->msg(cm_mpu98, COMMSG_MIMPIDEFEN, np2oscfg.mpu.def_en); - } - - TCHAR mdef[MAX_PATH]; - GetDlgItemText(IDC_MPU98DEFF, mdef, _countof(mdef)); - if (milstr_cmp(np2oscfg.mpu.def, mdef)) - { - milstr_ncpy(np2oscfg.mpu.def, mdef, NELEMENTS(np2oscfg.mpu.def)); - if (cm_mpu98) - { - cm_mpu98->msg(cm_mpu98, COMMSG_MIMPIDEFFILE, reinterpret_cast(mdef)); - } - update |= SYS_UPDATEOSCFG; - } - sysmng_update(update); -} - -/** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W - */ -BOOL CMpu98Page::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_MPUENABLE: - m_mpuenable = (m_chkenable.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - - case IDC_MPUIO: - SetJumper(GetPort(), 0xf0); - return TRUE; - - case IDC_MPUINT: - SetJumper(GetInt(), 0x03); - return TRUE; - - case IDC_MPUDEF: - m_mpu = 0x82; - SetPort(m_mpu); - SetInt(m_mpu); - m_dipsw.Invalidate(); - return TRUE; - - case IDC_MPUDIP: - OnDipSw(); - return TRUE; - - case IDC_MPU98DEFB: - m_mimpifile.Browse(); - return TRUE; - } - return FALSE; -} - -/** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ - */ -LRESULT CMpu98Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - switch (nMsg) - { - case WM_DRAWITEM: - if (LOWORD(wParam) == IDC_MPUDIP) - { - UINT8* pBitmap = dipswbmp_getmpu(m_mpu); - m_dipsw.Draw((reinterpret_cast(lParam))->hDC, pBitmap); - _MFREE(pBitmap); - } - return FALSE; - } - return CDlgProc::WindowProc(nMsg, wParam, lParam); -} - -/** - * fBbv XCb`NbN - */ -void CMpu98Page::OnDipSw() -{ - RECT rect1; - m_dipsw.GetWindowRect(&rect1); - RECT rect2; - m_dipsw.GetClientRect(&rect2); - POINT p; - GetCursorPos(&p); - - p.x += rect2.left - rect1.left; - p.y += rect2.top - rect1.top; - p.x /= 9; - p.y /= 9; - if ((p.y < 1) || (p.y >= 3)) - { - return; - } - - bool bRedraw = false; - if ((p.x >= 2) && (p.x < 6)) - { - UINT8 bit = 0x80 >> (p.x - 2); - m_mpu ^= bit; - SetPort(m_mpu); - bRedraw = true; - } - else if ((p.x >= 9) && (p.x < 13)) - { - UINT8 bit = (UINT8)(12 - p.x); - if ((m_mpu ^ bit) & 3) - { - m_mpu &= ~0x3; - m_mpu |= bit; - SetInt(m_mpu); - bRedraw = true; - } - } - if (bRedraw) - { - m_dipsw.Invalidate(); - } -} - -/** - * Wp[̒lݒ - * @param[in] cValue l - * @param[in] cBit }XN - */ -void CMpu98Page::SetJumper(UINT8 cValue, UINT8 cBit) -{ - if ((m_mpu ^ cValue) & cBit) - { - m_mpu &= ~cBit; - m_mpu |= cValue; - m_dipsw.Invalidate(); - } -} - -/** - * I/O ݒ - * @param[in] cValue ݒ - */ -void CMpu98Page::SetPort(UINT8 cValue) -{ - m_port.SetCurItemData(cValue & 0xf0); -} - -/** - * I/O 擾 - * @return I/O - */ -UINT8 CMpu98Page::GetPort() const -{ - return m_port.GetCurItemData(0x00); -} - -/** - * INT ݒ - * @param[in] cValue ݒ - */ -void CMpu98Page::SetInt(UINT8 cValue) -{ - m_int.SetCurItemData(cValue & 0x03); -} - -/** - * INT 擾 - * @return INT - */ -UINT8 CMpu98Page::GetInt() const -{ - return m_int.GetCurItemData(0x00); -} - - -#if defined(SUPPORT_SMPU98) - -/** - * @brief S-MPU ݒy[W - */ -class CSMpu98Page : public CPropPageProc -{ -public: - CSMpu98Page(); - virtual ~CSMpu98Page(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - UINT8 m_smpuenable; //!< L - UINT8 m_smpumuteB; //!< MPU-PC98G~[V[h̎|[gBɏo͂Ȃ - UINT8 m_smpu; //!< ݒl - CWndProc m_chkenable; //!< ENABLE - CWndProc m_chkmuteB; //!< MUTE PORT B during MPU-PC98 emulation mode - CComboData m_port; //!< IO - CComboData m_int; //!< INT - CStaticDipSw m_dipsw; //!< DIPSW - CComboMidiDevice m_midiinA; //!< MIDI IN A - CComboMidiDevice m_midioutA;//!< MIDI OUT A - CComboMidiModule m_moduleA; //!< MIDI Module A - CEditMimpiFile m_mimpifileA;//!< MIMPI A - CComboMidiDevice m_midiinB; //!< MIDI IN B - CComboMidiDevice m_midioutB;//!< MIDI OUT B - CComboMidiModule m_moduleB; //!< MIDI Module B - CEditMimpiFile m_mimpifileB;//!< MIMPI B - void OnDipSw(); - void SetJumper(UINT8 cValue, UINT8 cBit); - void SetPort(UINT8 cValue); - UINT8 GetPort() const; - void SetInt(UINT8 cValue); - UINT8 GetInt() const; -}; - -/** - * RXgN^ - */ -CSMpu98Page::CSMpu98Page() - : CPropPageProc(IDD_SMPU98) - , m_smpu(0) -{ -} - - -/** - * fXgN^ - */ -CSMpu98Page::~CSMpu98Page() -{ -} - -/** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ - */ -BOOL CSMpu98Page::OnInitDialog() -{ - m_smpuenable = np2cfg.smpuenable; - m_smpumuteB = np2cfg.smpumuteB; - m_smpu = np2cfg.smpuopt; - - m_chkenable.SubclassDlgItem(IDC_MPUENABLE, this); - if(m_smpuenable) - m_chkenable.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkenable.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_chkmuteB.SubclassDlgItem(IDC_MPUMUTEB, this); - if(m_smpumuteB) - m_chkmuteB.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkmuteB.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_port.SubclassDlgItem(IDC_MPUIO, this); - for (UINT i = 0; i < 16; i++) - { - TCHAR szBuf[8]; - wsprintf(szBuf, str_4X, 0xC0D0 + (i << 10)); - m_port.Add(szBuf, i << 4); - } - SetPort(m_smpu); - - m_int.SubclassDlgItem(IDC_MPUINT, this); - m_int.Add(s_int, _countof(s_int)); - SetInt(m_smpu); - - m_dipsw.SubclassDlgItem(IDC_MPUDIP, this); - - // Port A - m_midioutA.SubclassDlgItem(IDC_MPU98MMAP, this); - m_midioutA.EnumerateMidiOut(); - m_midioutA.SetCurString(np2oscfg.smpuA.mout); - - m_midiinA.SubclassDlgItem(IDC_MPU98MDIN, this); - m_midiinA.EnumerateMidiIn(); - m_midiinA.SetCurString(np2oscfg.smpuA.min); - - m_moduleA.SubclassDlgItem(IDC_MPU98MMDL, this); - m_moduleA.SetWindowText(np2oscfg.smpuA.mdl); - CheckDlgButton(IDC_MPU98DEFE, (np2oscfg.smpuA.def_en) ? BST_CHECKED : BST_UNCHECKED); - - m_mimpifileA.SubclassDlgItem(IDC_MPU98DEFF, this); - m_mimpifileA.SetWindowText(np2oscfg.smpuA.def); - - // Port B - m_midioutB.SubclassDlgItem(IDC_MPU98MMAP_B, this); - m_midioutB.EnumerateMidiOut(); - m_midioutB.SetCurString(np2oscfg.smpuB.mout); - - m_midiinB.SubclassDlgItem(IDC_MPU98MDIN_B, this); - m_midiinB.EnumerateMidiIn(); - m_midiinB.SetCurString(np2oscfg.smpuB.min); - - m_moduleB.SubclassDlgItem(IDC_MPU98MMDL_B, this); - m_moduleB.SetWindowText(np2oscfg.smpuB.mdl); - CheckDlgButton(IDC_MPU98DEFE_B, (np2oscfg.smpuB.def_en) ? BST_CHECKED : BST_UNCHECKED); - - m_mimpifileB.SubclassDlgItem(IDC_MPU98DEFF_B, this); - m_mimpifileB.SetWindowText(np2oscfg.smpuB.def); - - m_port.SetFocus(); - - return FALSE; -} - -/** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ - */ -void CSMpu98Page::OnOK() -{ - UINT update = 0; - - if (np2cfg.smpuenable != m_smpuenable) - { - np2cfg.smpuenable = m_smpuenable; - update |= SYS_UPDATECFG; - } - - if (np2cfg.smpumuteB != m_smpumuteB) - { - np2cfg.smpumuteB = m_smpumuteB; - update |= SYS_UPDATECFG; - } - - if (np2cfg.smpuopt != m_smpu) - { - np2cfg.smpuopt = m_smpu; - update |= SYS_UPDATECFG | SYS_UPDATEMIDI; - } - - // Port A - { - TCHAR mmap[MAXPNAMELEN]; - GetDlgItemText(IDC_MPU98MMAP, mmap, _countof(mmap)); - if (milstr_cmp(np2oscfg.smpuA.mout, mmap)) { - milstr_ncpy(np2oscfg.smpuA.mout, mmap, NELEMENTS(np2oscfg.smpuA.mout)); - update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; - } - - TCHAR mdin[MAXPNAMELEN]; - GetDlgItemText(IDC_MPU98MDIN, mdin, _countof(mdin)); - if (milstr_cmp(np2oscfg.smpuA.min, mdin)) - { - milstr_ncpy(np2oscfg.smpuA.min, mdin, NELEMENTS(np2oscfg.smpuA.min)); - update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; - } - - TCHAR mmdl[64]; - GetDlgItemText(IDC_MPU98MMDL, mmdl, _countof(mmdl)); - if (milstr_cmp(np2oscfg.smpuA.mdl, mmdl)) - { - milstr_ncpy(np2oscfg.smpuA.mdl, mmdl, NELEMENTS(np2oscfg.smpuA.mdl)); - update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; - } - - np2oscfg.smpuA.def_en = (IsDlgButtonChecked(IDC_MPU98DEFE) != BST_UNCHECKED) ? 1 : 0; - - if (cm_smpu98[0]) - { - cm_smpu98[0]->msg(cm_smpu98[0], COMMSG_MIMPIDEFEN, np2oscfg.smpuA.def_en); - } - - TCHAR mdef[MAX_PATH]; - GetDlgItemText(IDC_MPU98DEFF, mdef, _countof(mdef)); - if (milstr_cmp(np2oscfg.smpuA.def, mdef)) - { - milstr_ncpy(np2oscfg.smpuA.def, mdef, NELEMENTS(np2oscfg.smpuA.def)); - if (cm_smpu98[0]) - { - cm_smpu98[0]->msg(cm_smpu98[0], COMMSG_MIMPIDEFFILE, reinterpret_cast(mdef)); - } - update |= SYS_UPDATEOSCFG; - } - } - - // Port B - { - TCHAR mmap[MAXPNAMELEN]; - GetDlgItemText(IDC_MPU98MMAP_B, mmap, _countof(mmap)); - if (milstr_cmp(np2oscfg.smpuB.mout, mmap)) { - milstr_ncpy(np2oscfg.smpuB.mout, mmap, NELEMENTS(np2oscfg.smpuB.mout)); - update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; - } - - TCHAR mdin[MAXPNAMELEN]; - GetDlgItemText(IDC_MPU98MDIN_B, mdin, _countof(mdin)); - if (milstr_cmp(np2oscfg.smpuB.min, mdin)) - { - milstr_ncpy(np2oscfg.smpuB.min, mdin, NELEMENTS(np2oscfg.smpuB.min)); - update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; - } - - TCHAR mmdl[64]; - GetDlgItemText(IDC_MPU98MMDL_B, mmdl, _countof(mmdl)); - if (milstr_cmp(np2oscfg.smpuB.mdl, mmdl)) - { - milstr_ncpy(np2oscfg.smpuB.mdl, mmdl, NELEMENTS(np2oscfg.smpuB.mdl)); - update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; - } - - np2oscfg.smpuB.def_en = (IsDlgButtonChecked(IDC_MPU98DEFE_B) != BST_UNCHECKED) ? 1 : 0; - - if (cm_smpu98[1]) - { - cm_smpu98[1]->msg(cm_smpu98[1], COMMSG_MIMPIDEFEN, np2oscfg.smpuB.def_en); - } - - TCHAR mdef[MAX_PATH]; - GetDlgItemText(IDC_MPU98DEFF_B, mdef, _countof(mdef)); - if (milstr_cmp(np2oscfg.smpuB.def, mdef)) - { - milstr_ncpy(np2oscfg.smpuB.def, mdef, NELEMENTS(np2oscfg.smpuB.def)); - if (cm_smpu98[1]) - { - cm_smpu98[1]->msg(cm_smpu98[1], COMMSG_MIMPIDEFFILE, reinterpret_cast(mdef)); - } - update |= SYS_UPDATEOSCFG; - } - } - - sysmng_update(update); -} - -/** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W - */ -BOOL CSMpu98Page::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_MPUENABLE: - m_smpuenable = (m_chkenable.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - - case IDC_MPUMUTEB: - m_smpumuteB = (m_chkmuteB.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - - case IDC_MPUIO: - SetJumper(GetPort(), 0xf0); - return TRUE; - - case IDC_MPUINT: - SetJumper(GetInt(), 0x03); - return TRUE; - - case IDC_MPUDEF: - m_smpu = 0x82; - SetPort(m_smpu); - SetInt(m_smpu); - m_dipsw.Invalidate(); - return TRUE; - - case IDC_MPUDIP: - OnDipSw(); - return TRUE; - - case IDC_MPU98DEFB: - m_mimpifileA.Browse(); - return TRUE; - - case IDC_MPU98DEFB_B: - m_mimpifileB.Browse(); - return TRUE; - } - return FALSE; -} - -/** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ - */ -LRESULT CSMpu98Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - switch (nMsg) - { - case WM_DRAWITEM: - if (LOWORD(wParam) == IDC_MPUDIP) - { - UINT8* pBitmap = dipswbmp_getsmpu(m_smpu); - m_dipsw.Draw((reinterpret_cast(lParam))->hDC, pBitmap); - _MFREE(pBitmap); - } - return FALSE; - } - return CDlgProc::WindowProc(nMsg, wParam, lParam); -} - -/** - * fBbv XCb`NbN - */ -void CSMpu98Page::OnDipSw() -{ - RECT rect1; - m_dipsw.GetWindowRect(&rect1); - RECT rect2; - m_dipsw.GetClientRect(&rect2); - POINT p; - GetCursorPos(&p); - - p.x += rect2.left - rect1.left; - p.y += rect2.top - rect1.top; - p.x /= 9; - p.y /= 9; - if ((p.y < 1) || (p.y >= 3)) - { - return; - } - - bool bRedraw = false; - if ((p.x >= 2) && (p.x < 6)) - { - UINT8 bit = 0x10 << (p.x - 2); - m_smpu ^= bit; - SetPort(m_smpu); - bRedraw = true; - } - else if ((p.x >= 9) && (p.x < 13)) - { - UINT8 bit = (UINT8)(12 - p.x); - if ((m_smpu ^ bit) & 3) - { - m_smpu &= ~0x3; - m_smpu |= bit; - SetInt(m_smpu); - bRedraw = true; - } - } - if (bRedraw) - { - m_dipsw.Invalidate(); - } -} - -/** - * Wp[̒lݒ - * @param[in] cValue l - * @param[in] cBit }XN - */ -void CSMpu98Page::SetJumper(UINT8 cValue, UINT8 cBit) -{ - if ((m_smpu ^ cValue) & cBit) - { - m_smpu &= ~cBit; - m_smpu |= cValue; - m_dipsw.Invalidate(); - } -} - -/** - * I/O ݒ - * @param[in] cValue ݒ - */ -void CSMpu98Page::SetPort(UINT8 cValue) -{ - m_port.SetCurItemData(cValue & 0xf0); -} - -/** - * I/O 擾 - * @return I/O - */ -UINT8 CSMpu98Page::GetPort() const -{ - return m_port.GetCurItemData(0x00); -} - -/** - * INT ݒ - * @param[in] cValue ݒ - */ -void CSMpu98Page::SetInt(UINT8 cValue) -{ - m_int.SetCurItemData(cValue & 0x03); -} - -/** - * INT 擾 - * @return INT - */ -UINT8 CSMpu98Page::GetInt() const -{ - return m_int.GetCurItemData(0x00); -} - -#endif /* SUPPORT_SMPU98 */ - -/** - * RtBO _CAO - * @param[in] hwndParent eEBhE - */ -void dialog_mpu98(HWND hwndParent) -{ - CPropSheetProc prop(IDS_MIDIOPTION, hwndParent); - - CMpu98Page mpu98; - prop.AddPage(&mpu98); - -#if defined(SUPPORT_SMPU98) - CSMpu98Page smpu98; - prop.AddPage(&smpu98); -#endif /* SUPPORT_SMPU98 */ - - prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; - prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); - prop.m_psh.pfnCallback = np2class_propetysheet; - prop.DoModal(); - - InvalidateRect(hwndParent, NULL, TRUE); -} +/** + * @file d_mpu98.cpp + * @brief MIDI 設定ダイアログ + */ + +#include +#include "resource.h" +#include "dialog.h" +#include "c_combodata.h" +#include "c_dipsw.h" +#include "c_midi.h" +#include "np2class.h" +#include +#include +#include +#include "misc/PropProc.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern COMMNG cm_mpu98; +extern COMMNG cm_smpu98[]; + +#ifdef __cplusplus +} +#endif + +/** + * 割り込みリスト + */ +static const CComboData::Entry s_int[] = +{ + {MAKEINTRESOURCE(IDS_INT0), 0}, + {MAKEINTRESOURCE(IDS_INT1), 1}, + {MAKEINTRESOURCE(IDS_INT2), 2}, + {MAKEINTRESOURCE(IDS_INT5), 3}, +}; + + +/** + * @brief MPU-PC98 設定ページ + */ +class CMpu98Page : public CPropPageProc +{ +public: + CMpu98Page(); + virtual ~CMpu98Page(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + UINT8 m_mpuenable; //!< 有効 + UINT8 m_mpu; //!< 設定値 + CWndProc m_chkenable; //!< ENABLE + CComboData m_port; //!< IO + CComboData m_int; //!< INT + CStaticDipSw m_dipsw; //!< DIPSW + CComboMidiDevice m_midiin; //!< MIDI IN + CComboMidiDevice m_midiout; //!< MIDI OUT + CComboMidiModule m_module; //!< MIDI Module + CEditMimpiFile m_mimpifile; //!< MIMPI + void OnDipSw(); + void SetJumper(UINT8 cValue, UINT8 cBit); + void SetPort(UINT8 cValue); + UINT8 GetPort() const; + void SetInt(UINT8 cValue); + UINT8 GetInt() const; +}; + +/** + * コンストラクタ + */ +CMpu98Page::CMpu98Page() + : CPropPageProc(IDD_MPUPC98) + , m_mpu(0) +{ +} + + +/** + * デストラクタ + */ +CMpu98Page::~CMpu98Page() +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL CMpu98Page::OnInitDialog() +{ + m_mpuenable = np2cfg.mpuenable; + m_mpu = np2cfg.mpuopt; + + m_chkenable.SubclassDlgItem(IDC_MPUENABLE, this); + if(m_mpuenable) + m_chkenable.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkenable.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_port.SubclassDlgItem(IDC_MPUIO, this); + for (UINT i = 0; i < 16; i++) + { + TCHAR szBuf[8]; + wsprintf(szBuf, str_4X, 0xC0D0 + (i << 10)); + m_port.Add(szBuf, i << 4); + } + SetPort(m_mpu); + + m_int.SubclassDlgItem(IDC_MPUINT, this); + m_int.Add(s_int, _countof(s_int)); + SetInt(m_mpu); + + m_dipsw.SubclassDlgItem(IDC_MPUDIP, this); + + m_midiout.SubclassDlgItem(IDC_MPU98MMAP, this); + m_midiout.EnumerateMidiOut(); + m_midiout.SetCurString(np2oscfg.mpu.mout); + + m_midiin.SubclassDlgItem(IDC_MPU98MDIN, this); + m_midiin.EnumerateMidiIn(); + m_midiin.SetCurString(np2oscfg.mpu.min); + + m_module.SubclassDlgItem(IDC_MPU98MMDL, this); + m_module.SetWindowText(np2oscfg.mpu.mdl); + CheckDlgButton(IDC_MPU98DEFE, (np2oscfg.mpu.def_en) ? BST_CHECKED : BST_UNCHECKED); + + m_mimpifile.SubclassDlgItem(IDC_MPU98DEFF, this); + m_mimpifile.SetWindowText(np2oscfg.mpu.def); + + m_port.SetFocus(); + + return FALSE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void CMpu98Page::OnOK() +{ + UINT update = 0; + + if (np2cfg.mpuenable != m_mpuenable) + { + np2cfg.mpuenable = m_mpuenable; + update |= SYS_UPDATECFG; + } + + if (np2cfg.mpuopt != m_mpu) + { + np2cfg.mpuopt = m_mpu; + update |= SYS_UPDATECFG | SYS_UPDATEMIDI; + } + + TCHAR mmap[MAXPNAMELEN]; + GetDlgItemText(IDC_MPU98MMAP, mmap, _countof(mmap)); + if (milstr_cmp(np2oscfg.mpu.mout, mmap)) { + milstr_ncpy(np2oscfg.mpu.mout, mmap, NELEMENTS(np2oscfg.mpu.mout)); + update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; + } + + TCHAR mdin[MAXPNAMELEN]; + GetDlgItemText(IDC_MPU98MDIN, mdin, _countof(mdin)); + if (milstr_cmp(np2oscfg.mpu.min, mdin)) + { + milstr_ncpy(np2oscfg.mpu.min, mdin, NELEMENTS(np2oscfg.mpu.min)); + update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; + } + + TCHAR mmdl[64]; + GetDlgItemText(IDC_MPU98MMDL, mmdl, _countof(mmdl)); + if (milstr_cmp(np2oscfg.mpu.mdl, mmdl)) + { + milstr_ncpy(np2oscfg.mpu.mdl, mmdl, NELEMENTS(np2oscfg.mpu.mdl)); + update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; + } + + np2oscfg.mpu.def_en = (IsDlgButtonChecked(IDC_MPU98DEFE) != BST_UNCHECKED) ? 1 : 0; + + if (cm_mpu98) + { + cm_mpu98->msg(cm_mpu98, COMMSG_MIMPIDEFEN, np2oscfg.mpu.def_en); + } + + TCHAR mdef[MAX_PATH]; + GetDlgItemText(IDC_MPU98DEFF, mdef, _countof(mdef)); + if (milstr_cmp(np2oscfg.mpu.def, mdef)) + { + milstr_ncpy(np2oscfg.mpu.def, mdef, NELEMENTS(np2oscfg.mpu.def)); + if (cm_mpu98) + { + cm_mpu98->msg(cm_mpu98, COMMSG_MIMPIDEFFILE, reinterpret_cast(mdef)); + } + update |= SYS_UPDATEOSCFG; + } + sysmng_update(update); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL CMpu98Page::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_MPUENABLE: + m_mpuenable = (m_chkenable.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + + case IDC_MPUIO: + SetJumper(GetPort(), 0xf0); + return TRUE; + + case IDC_MPUINT: + SetJumper(GetInt(), 0x03); + return TRUE; + + case IDC_MPUDEF: + m_mpu = 0x82; + SetPort(m_mpu); + SetInt(m_mpu); + m_dipsw.Invalidate(); + return TRUE; + + case IDC_MPUDIP: + OnDipSw(); + return TRUE; + + case IDC_MPU98DEFB: + m_mimpifile.Browse(); + return TRUE; + } + return FALSE; +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CMpu98Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + switch (nMsg) + { + case WM_DRAWITEM: + if (LOWORD(wParam) == IDC_MPUDIP) + { + UINT8* pBitmap = dipswbmp_getmpu(m_mpu); + m_dipsw.Draw((reinterpret_cast(lParam))->hDC, pBitmap); + _MFREE(pBitmap); + } + return FALSE; + } + return CDlgProc::WindowProc(nMsg, wParam, lParam); +} + +/** + * ディップ スイッチをクリックした + */ +void CMpu98Page::OnDipSw() +{ + RECT rect1; + m_dipsw.GetWindowRect(&rect1); + RECT rect2; + m_dipsw.GetClientRect(&rect2); + POINT p; + GetCursorPos(&p); + + p.x += rect2.left - rect1.left; + p.y += rect2.top - rect1.top; + p.x /= 9; + p.y /= 9; + if ((p.y < 1) || (p.y >= 3)) + { + return; + } + + bool bRedraw = false; + if ((p.x >= 2) && (p.x < 6)) + { + UINT8 bit = 0x80 >> (p.x - 2); + m_mpu ^= bit; + SetPort(m_mpu); + bRedraw = true; + } + else if ((p.x >= 9) && (p.x < 13)) + { + UINT8 bit = (UINT8)(12 - p.x); + if ((m_mpu ^ bit) & 3) + { + m_mpu &= ~0x3; + m_mpu |= bit; + SetInt(m_mpu); + bRedraw = true; + } + } + if (bRedraw) + { + m_dipsw.Invalidate(); + } +} + +/** + * ジャンパーの値を設定 + * @param[in] cValue 値 + * @param[in] cBit マスク + */ +void CMpu98Page::SetJumper(UINT8 cValue, UINT8 cBit) +{ + if ((m_mpu ^ cValue) & cBit) + { + m_mpu &= ~cBit; + m_mpu |= cValue; + m_dipsw.Invalidate(); + } +} + +/** + * I/O を設定 + * @param[in] cValue 設定 + */ +void CMpu98Page::SetPort(UINT8 cValue) +{ + m_port.SetCurItemData(cValue & 0xf0); +} + +/** + * I/O を取得 + * @return I/O + */ +UINT8 CMpu98Page::GetPort() const +{ + return m_port.GetCurItemData(0x00); +} + +/** + * INT を設定 + * @param[in] cValue 設定 + */ +void CMpu98Page::SetInt(UINT8 cValue) +{ + m_int.SetCurItemData(cValue & 0x03); +} + +/** + * INT を取得 + * @return INT + */ +UINT8 CMpu98Page::GetInt() const +{ + return m_int.GetCurItemData(0x00); +} + + +#if defined(SUPPORT_SMPU98) + +/** + * @brief S-MPU 設定ページ + */ +class CSMpu98Page : public CPropPageProc +{ +public: + CSMpu98Page(); + virtual ~CSMpu98Page(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + UINT8 m_smpuenable; //!< 有効 + UINT8 m_smpumuteB; //!< MPU-PC98エミュレーションモードの時ポートBに出力しない + UINT8 m_smpu; //!< 設定値 + CWndProc m_chkenable; //!< ENABLE + CWndProc m_chkmuteB; //!< MUTE PORT B during MPU-PC98 emulation mode + CComboData m_port; //!< IO + CComboData m_int; //!< INT + CStaticDipSw m_dipsw; //!< DIPSW + CComboMidiDevice m_midiinA; //!< MIDI IN A + CComboMidiDevice m_midioutA;//!< MIDI OUT A + CComboMidiModule m_moduleA; //!< MIDI Module A + CEditMimpiFile m_mimpifileA;//!< MIMPI A + CComboMidiDevice m_midiinB; //!< MIDI IN B + CComboMidiDevice m_midioutB;//!< MIDI OUT B + CComboMidiModule m_moduleB; //!< MIDI Module B + CEditMimpiFile m_mimpifileB;//!< MIMPI B + void OnDipSw(); + void SetJumper(UINT8 cValue, UINT8 cBit); + void SetPort(UINT8 cValue); + UINT8 GetPort() const; + void SetInt(UINT8 cValue); + UINT8 GetInt() const; +}; + +/** + * コンストラクタ + */ +CSMpu98Page::CSMpu98Page() + : CPropPageProc(IDD_SMPU98) + , m_smpu(0) +{ +} + + +/** + * デストラクタ + */ +CSMpu98Page::~CSMpu98Page() +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL CSMpu98Page::OnInitDialog() +{ + m_smpuenable = np2cfg.smpuenable; + m_smpumuteB = np2cfg.smpumuteB; + m_smpu = np2cfg.smpuopt; + + m_chkenable.SubclassDlgItem(IDC_MPUENABLE, this); + if(m_smpuenable) + m_chkenable.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkenable.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_chkmuteB.SubclassDlgItem(IDC_MPUMUTEB, this); + if(m_smpumuteB) + m_chkmuteB.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkmuteB.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_port.SubclassDlgItem(IDC_MPUIO, this); + for (UINT i = 0; i < 16; i++) + { + TCHAR szBuf[8]; + wsprintf(szBuf, str_4X, 0xC0D0 + (i << 10)); + m_port.Add(szBuf, i << 4); + } + SetPort(m_smpu); + + m_int.SubclassDlgItem(IDC_MPUINT, this); + m_int.Add(s_int, _countof(s_int)); + SetInt(m_smpu); + + m_dipsw.SubclassDlgItem(IDC_MPUDIP, this); + + // Port A + m_midioutA.SubclassDlgItem(IDC_MPU98MMAP, this); + m_midioutA.EnumerateMidiOut(); + m_midioutA.SetCurString(np2oscfg.smpuA.mout); + + m_midiinA.SubclassDlgItem(IDC_MPU98MDIN, this); + m_midiinA.EnumerateMidiIn(); + m_midiinA.SetCurString(np2oscfg.smpuA.min); + + m_moduleA.SubclassDlgItem(IDC_MPU98MMDL, this); + m_moduleA.SetWindowText(np2oscfg.smpuA.mdl); + CheckDlgButton(IDC_MPU98DEFE, (np2oscfg.smpuA.def_en) ? BST_CHECKED : BST_UNCHECKED); + + m_mimpifileA.SubclassDlgItem(IDC_MPU98DEFF, this); + m_mimpifileA.SetWindowText(np2oscfg.smpuA.def); + + // Port B + m_midioutB.SubclassDlgItem(IDC_MPU98MMAP_B, this); + m_midioutB.EnumerateMidiOut(); + m_midioutB.SetCurString(np2oscfg.smpuB.mout); + + m_midiinB.SubclassDlgItem(IDC_MPU98MDIN_B, this); + m_midiinB.EnumerateMidiIn(); + m_midiinB.SetCurString(np2oscfg.smpuB.min); + + m_moduleB.SubclassDlgItem(IDC_MPU98MMDL_B, this); + m_moduleB.SetWindowText(np2oscfg.smpuB.mdl); + CheckDlgButton(IDC_MPU98DEFE_B, (np2oscfg.smpuB.def_en) ? BST_CHECKED : BST_UNCHECKED); + + m_mimpifileB.SubclassDlgItem(IDC_MPU98DEFF_B, this); + m_mimpifileB.SetWindowText(np2oscfg.smpuB.def); + + m_port.SetFocus(); + + return FALSE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void CSMpu98Page::OnOK() +{ + UINT update = 0; + + if (np2cfg.smpuenable != m_smpuenable) + { + np2cfg.smpuenable = m_smpuenable; + update |= SYS_UPDATECFG; + } + + if (np2cfg.smpumuteB != m_smpumuteB) + { + np2cfg.smpumuteB = m_smpumuteB; + update |= SYS_UPDATECFG; + } + + if (np2cfg.smpuopt != m_smpu) + { + np2cfg.smpuopt = m_smpu; + update |= SYS_UPDATECFG | SYS_UPDATEMIDI; + } + + // Port A + { + TCHAR mmap[MAXPNAMELEN]; + GetDlgItemText(IDC_MPU98MMAP, mmap, _countof(mmap)); + if (milstr_cmp(np2oscfg.smpuA.mout, mmap)) { + milstr_ncpy(np2oscfg.smpuA.mout, mmap, NELEMENTS(np2oscfg.smpuA.mout)); + update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; + } + + TCHAR mdin[MAXPNAMELEN]; + GetDlgItemText(IDC_MPU98MDIN, mdin, _countof(mdin)); + if (milstr_cmp(np2oscfg.smpuA.min, mdin)) + { + milstr_ncpy(np2oscfg.smpuA.min, mdin, NELEMENTS(np2oscfg.smpuA.min)); + update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; + } + + TCHAR mmdl[64]; + GetDlgItemText(IDC_MPU98MMDL, mmdl, _countof(mmdl)); + if (milstr_cmp(np2oscfg.smpuA.mdl, mmdl)) + { + milstr_ncpy(np2oscfg.smpuA.mdl, mmdl, NELEMENTS(np2oscfg.smpuA.mdl)); + update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; + } + + np2oscfg.smpuA.def_en = (IsDlgButtonChecked(IDC_MPU98DEFE) != BST_UNCHECKED) ? 1 : 0; + + if (cm_smpu98[0]) + { + cm_smpu98[0]->msg(cm_smpu98[0], COMMSG_MIMPIDEFEN, np2oscfg.smpuA.def_en); + } + + TCHAR mdef[MAX_PATH]; + GetDlgItemText(IDC_MPU98DEFF, mdef, _countof(mdef)); + if (milstr_cmp(np2oscfg.smpuA.def, mdef)) + { + milstr_ncpy(np2oscfg.smpuA.def, mdef, NELEMENTS(np2oscfg.smpuA.def)); + if (cm_smpu98[0]) + { + cm_smpu98[0]->msg(cm_smpu98[0], COMMSG_MIMPIDEFFILE, reinterpret_cast(mdef)); + } + update |= SYS_UPDATEOSCFG; + } + } + + // Port B + { + TCHAR mmap[MAXPNAMELEN]; + GetDlgItemText(IDC_MPU98MMAP_B, mmap, _countof(mmap)); + if (milstr_cmp(np2oscfg.smpuB.mout, mmap)) { + milstr_ncpy(np2oscfg.smpuB.mout, mmap, NELEMENTS(np2oscfg.smpuB.mout)); + update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; + } + + TCHAR mdin[MAXPNAMELEN]; + GetDlgItemText(IDC_MPU98MDIN_B, mdin, _countof(mdin)); + if (milstr_cmp(np2oscfg.smpuB.min, mdin)) + { + milstr_ncpy(np2oscfg.smpuB.min, mdin, NELEMENTS(np2oscfg.smpuB.min)); + update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; + } + + TCHAR mmdl[64]; + GetDlgItemText(IDC_MPU98MMDL_B, mmdl, _countof(mmdl)); + if (milstr_cmp(np2oscfg.smpuB.mdl, mmdl)) + { + milstr_ncpy(np2oscfg.smpuB.mdl, mmdl, NELEMENTS(np2oscfg.smpuB.mdl)); + update |= SYS_UPDATEOSCFG | SYS_UPDATEMIDI; + } + + np2oscfg.smpuB.def_en = (IsDlgButtonChecked(IDC_MPU98DEFE_B) != BST_UNCHECKED) ? 1 : 0; + + if (cm_smpu98[1]) + { + cm_smpu98[1]->msg(cm_smpu98[1], COMMSG_MIMPIDEFEN, np2oscfg.smpuB.def_en); + } + + TCHAR mdef[MAX_PATH]; + GetDlgItemText(IDC_MPU98DEFF_B, mdef, _countof(mdef)); + if (milstr_cmp(np2oscfg.smpuB.def, mdef)) + { + milstr_ncpy(np2oscfg.smpuB.def, mdef, NELEMENTS(np2oscfg.smpuB.def)); + if (cm_smpu98[1]) + { + cm_smpu98[1]->msg(cm_smpu98[1], COMMSG_MIMPIDEFFILE, reinterpret_cast(mdef)); + } + update |= SYS_UPDATEOSCFG; + } + } + + sysmng_update(update); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL CSMpu98Page::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_MPUENABLE: + m_smpuenable = (m_chkenable.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + + case IDC_MPUMUTEB: + m_smpumuteB = (m_chkmuteB.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + + case IDC_MPUIO: + SetJumper(GetPort(), 0xf0); + return TRUE; + + case IDC_MPUINT: + SetJumper(GetInt(), 0x03); + return TRUE; + + case IDC_MPUDEF: + m_smpu = 0x82; + SetPort(m_smpu); + SetInt(m_smpu); + m_dipsw.Invalidate(); + return TRUE; + + case IDC_MPUDIP: + OnDipSw(); + return TRUE; + + case IDC_MPU98DEFB: + m_mimpifileA.Browse(); + return TRUE; + + case IDC_MPU98DEFB_B: + m_mimpifileB.Browse(); + return TRUE; + } + return FALSE; +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CSMpu98Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + switch (nMsg) + { + case WM_DRAWITEM: + if (LOWORD(wParam) == IDC_MPUDIP) + { + UINT8* pBitmap = dipswbmp_getsmpu(m_smpu); + m_dipsw.Draw((reinterpret_cast(lParam))->hDC, pBitmap); + _MFREE(pBitmap); + } + return FALSE; + } + return CDlgProc::WindowProc(nMsg, wParam, lParam); +} + +/** + * ディップ スイッチをクリックした + */ +void CSMpu98Page::OnDipSw() +{ + RECT rect1; + m_dipsw.GetWindowRect(&rect1); + RECT rect2; + m_dipsw.GetClientRect(&rect2); + POINT p; + GetCursorPos(&p); + + p.x += rect2.left - rect1.left; + p.y += rect2.top - rect1.top; + p.x /= 9; + p.y /= 9; + if ((p.y < 1) || (p.y >= 3)) + { + return; + } + + bool bRedraw = false; + if ((p.x >= 2) && (p.x < 6)) + { + UINT8 bit = 0x10 << (p.x - 2); + m_smpu ^= bit; + SetPort(m_smpu); + bRedraw = true; + } + else if ((p.x >= 9) && (p.x < 13)) + { + UINT8 bit = (UINT8)(12 - p.x); + if ((m_smpu ^ bit) & 3) + { + m_smpu &= ~0x3; + m_smpu |= bit; + SetInt(m_smpu); + bRedraw = true; + } + } + if (bRedraw) + { + m_dipsw.Invalidate(); + } +} + +/** + * ジャンパーの値を設定 + * @param[in] cValue 値 + * @param[in] cBit マスク + */ +void CSMpu98Page::SetJumper(UINT8 cValue, UINT8 cBit) +{ + if ((m_smpu ^ cValue) & cBit) + { + m_smpu &= ~cBit; + m_smpu |= cValue; + m_dipsw.Invalidate(); + } +} + +/** + * I/O を設定 + * @param[in] cValue 設定 + */ +void CSMpu98Page::SetPort(UINT8 cValue) +{ + m_port.SetCurItemData(cValue & 0xf0); +} + +/** + * I/O を取得 + * @return I/O + */ +UINT8 CSMpu98Page::GetPort() const +{ + return m_port.GetCurItemData(0x00); +} + +/** + * INT を設定 + * @param[in] cValue 設定 + */ +void CSMpu98Page::SetInt(UINT8 cValue) +{ + m_int.SetCurItemData(cValue & 0x03); +} + +/** + * INT を取得 + * @return INT + */ +UINT8 CSMpu98Page::GetInt() const +{ + return m_int.GetCurItemData(0x00); +} + +#endif /* SUPPORT_SMPU98 */ + +/** + * コンフィグ ダイアログ + * @param[in] hwndParent 親ウィンドウ + */ +void dialog_mpu98(HWND hwndParent) +{ + CPropSheetProc prop(IDS_MIDIOPTION, hwndParent); + + CMpu98Page mpu98; + prop.AddPage(&mpu98); + +#if defined(SUPPORT_SMPU98) + CSMpu98Page smpu98; + prop.AddPage(&smpu98); +#endif /* SUPPORT_SMPU98 */ + + prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; + prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); + prop.m_psh.pfnCallback = np2class_propetysheet; + prop.DoModal(); + + InvalidateRect(hwndParent, NULL, TRUE); +} diff --git a/windows/dialog/d_network.cpp b/windows/dialog/d_network.cpp old mode 100755 new mode 100644 index 500dddeb..5278359b --- a/windows/dialog/d_network.cpp +++ b/windows/dialog/d_network.cpp @@ -1,528 +1,528 @@ -/** - * @file d_network.cpp - * @brief Network configure dialog procedure - * - * @author $Author: SimK $ - * @date $Date: 2016/03/11 $ - */ - -#include -#include "resource.h" -#include -#include "dialog.h" -#include "c_combodata.h" -#include "np2class.h" -#include -#include -#include -#include -#include "misc\PropProc.h" -#include -#include - -#if defined(SUPPORT_NET) - -/** - * @brief ネットワーク基本設定ページ - * @param[in] hwndParent 親ウィンドウ - */ -class CNetworkPage : public CPropPageProc -{ -public: - CNetworkPage(); - virtual ~CNetworkPage(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - TCHAR m_tap[300]; //!< TAP名 - UINT8 m_pmmenabled; //!< 負荷低減有効フラグ - CComboData m_cmbtap; //!< TAP NAME - CWndProc m_chkpmmenabled; //!< POWER MANAGEMENT ENABLED - void SetNetWorkDeviceNames(); -}; - -/** - * コンストラクタ - */ -CNetworkPage::CNetworkPage() - : CPropPageProc(IDD_NETWORK) -{ -} -/** - * デストラクタ - */ -CNetworkPage::~CNetworkPage() -{ -} - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL CNetworkPage::OnInitDialog() -{ - _tcscpy(m_tap, np2cfg.np2nettap); - - m_cmbtap.SubclassDlgItem(IDC_NETTAP, this); - SetNetWorkDeviceNames(); - - m_pmmenabled = np2cfg.np2netpmm; - m_chkpmmenabled.SubclassDlgItem(IDC_NETPMM, this); - if(m_pmmenabled) - m_chkpmmenabled.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkpmmenabled.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_cmbtap.SetFocus(); - - return FALSE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void CNetworkPage::OnOK() -{ - UINT update = 0; - - if (_tcscmp(np2cfg.np2nettap, m_tap)!=0 || m_pmmenabled!=np2cfg.np2netpmm) - { - _tcscpy(np2cfg.np2nettap, m_tap); - np2cfg.np2netpmm = m_pmmenabled; - update |= SYS_UPDATECFG; - } - ::sysmng_update(update); -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL CNetworkPage::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_NETTAP: - m_cmbtap.GetWindowText(m_tap, NELEMENTS(m_tap)); - return TRUE; - - case IDC_NETPMM: - m_pmmenabled = (m_chkpmmenabled.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - } - return FALSE; -} - -/** - * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT CNetworkPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - //switch (nMsg) - //{ - //} - return CDlgProc::WindowProc(nMsg, wParam, lParam); -} - -/** - * ネットワークデバイス表示名をコンボボックスデータに放り込む - * 参考文献: http://dsas.blog.klab.org/archives/51012690.html - */ -void CNetworkPage::SetNetWorkDeviceNames() -{ - CONST TCHAR *SUBKEY = _T("SYSTEM\\CurrentControlSet\\Control\\Network"); - -#define BUFSZ 256 - int index = 0; - int indexsel = -1; - HKEY hKey1, hKey2, hKey3; - LONG nResult; - DWORD dwIdx1, dwIdx2; - TCHAR szData[64], *pKeyName1, *pKeyName2, *pKeyName3, *pKeyName4; - DWORD dwSize, dwType = REG_SZ; - BOOL bDone = FALSE; - FILETIME ft; - - hKey1 = hKey2 = hKey3 = NULL; - pKeyName1 = pKeyName2 = pKeyName3 = pKeyName4 = NULL; - - // 主キーのオープン - nResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SUBKEY, 0, KEY_READ, &hKey1); - if (nResult != ERROR_SUCCESS) { - return; - } - pKeyName1 = (TCHAR*)malloc(sizeof(TCHAR)*BUFSZ); - pKeyName2 = (TCHAR*)malloc(sizeof(TCHAR)*BUFSZ); - pKeyName3 = (TCHAR*)malloc(sizeof(TCHAR)*BUFSZ); - pKeyName4 = (TCHAR*)malloc(sizeof(TCHAR)*BUFSZ); - - dwIdx1 = 0; - while (bDone != TRUE) { // {id1} を列挙するループ - - dwSize = BUFSZ; - nResult = RegEnumKeyEx(hKey1, dwIdx1++, pKeyName1, - &dwSize, NULL, NULL, NULL, &ft); - if (nResult == ERROR_NO_MORE_ITEMS) { - break; - } - - // SUBKEY\{id1} キーをオープン - _stprintf(pKeyName2, _T("%s\\%s"), SUBKEY, pKeyName1); - nResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pKeyName2, - 0, KEY_READ, &hKey2); - if (nResult != ERROR_SUCCESS) { - continue; - } - dwIdx2 = 0; - while (1) { // {id2} を列挙するループ - dwSize = BUFSZ; - nResult = RegEnumKeyEx(hKey2, dwIdx2++, pKeyName3, - &dwSize, NULL, NULL, NULL, &ft); - if (nResult == ERROR_NO_MORE_ITEMS) { - break; - } - - if (nResult != ERROR_SUCCESS) { - continue; - } - - // SUBKEY\{id1}\{id2]\Connection キーをオープン - _stprintf(pKeyName4, _T("%s\\%s\\%s"), - pKeyName2, pKeyName3, _T("Connection")); - nResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, - pKeyName4, 0, KEY_READ, &hKey3); - if (nResult != ERROR_SUCCESS) { - continue; - } - - // SUBKEY\{id1}\{id2]\Connection\PnpInstanceID 値を取得 - dwSize = sizeof(szData); - nResult = RegQueryValueEx(hKey3, _T("PnpInstanceID"), - 0, &dwType, (LPBYTE)szData, &dwSize); - - if (nResult == ERROR_SUCCESS) { - if(_tcslen(szData)>0){ - // SUBKEY\{id1}\{id2]\Connection\Name 値を取得 - dwSize = sizeof(szData); - nResult = RegQueryValueEx(hKey3, _T("Name"), - 0, &dwType, (LPBYTE)szData, &dwSize); - - if (nResult == ERROR_SUCCESS) { - if(_tcslen(szData)>0){ - m_cmbtap.Add(szData, index); - if(_tcscmp(szData, m_tap)==0){ - m_cmbtap.SetCurSel(index); - indexsel = index; - } - index++; - } - } - } - } - RegCloseKey(hKey3); - hKey3 = NULL; - } - RegCloseKey(hKey2); - hKey2 = NULL; - } - - if (hKey1) { RegCloseKey(hKey1); } - if (hKey2) { RegCloseKey(hKey2); } - if (hKey3) { RegCloseKey(hKey3); } - - if (pKeyName1) { free(pKeyName1); } - if (pKeyName2) { free(pKeyName2); } - if (pKeyName3) { free(pKeyName3); } - if (pKeyName4) { free(pKeyName4); } - - if(indexsel == -1){ - // カスタム接続名 - m_cmbtap.SetWindowText(m_tap); - } - - return; -} - -#if defined(SUPPORT_LGY98) - -/** - * @brief LGY-98 設定ページ - * @param[in] hwndParent 親ウィンドウ - */ -class CLgy98Page : public CPropPageProc -{ -public: - CLgy98Page(); - virtual ~CLgy98Page(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - UINT8 m_enabled; //!< 有効フラグ - UINT8 m_port; //!< PORT設定値 - UINT8 m_int; //!< INT設定値 - CWndProc m_chkenabled; //!< ENABLED - CComboData m_cmbport; //!< IO - CComboData m_cmbint; //!< INT - CWndProc m_btnreset; //!< RESET - UINT8 ConvertIrq2Int(UINT8 cValue); - UINT8 ConvertInt2Irq(UINT8 cValue); - void SetPort(UINT8 cValue); - UINT8 GetPort() const; - void SetInt(UINT8 cValue); - UINT8 GetInt() const; -}; - -/** - * ポートリスト - */ -static const CComboData::Entry s_port[] = -{ - {MAKEINTRESOURCE(IDS_00D0), 0x00}, - {MAKEINTRESOURCE(IDS_10D0), 0x10}, - {MAKEINTRESOURCE(IDS_20D0), 0x20}, - {MAKEINTRESOURCE(IDS_30D0), 0x30}, - {MAKEINTRESOURCE(IDS_40D0), 0x40}, - {MAKEINTRESOURCE(IDS_50D0), 0x50}, - {MAKEINTRESOURCE(IDS_60D0), 0x60}, - {MAKEINTRESOURCE(IDS_70D0), 0x70}, -}; - -/** - * 割り込みリスト - */ -static const CComboData::Entry s_int[] = -{ - {MAKEINTRESOURCE(IDS_INT0), 0}, - {MAKEINTRESOURCE(IDS_INT1), 1}, - {MAKEINTRESOURCE(IDS_INT2), 2}, - {MAKEINTRESOURCE(IDS_INT5), 5}, -}; - -/** - * コンストラクタ - */ -CLgy98Page::CLgy98Page() - : CPropPageProc(IDD_LGY98) - , m_port((UINT8)IDS_10D0), m_int((UINT8)IDS_INT1) -{ -} -/** - * デストラクタ - */ -CLgy98Page::~CLgy98Page() -{ -} - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL CLgy98Page::OnInitDialog() -{ - m_enabled = np2cfg.uselgy98; - m_port = (UINT8)(np2cfg.lgy98io>>8); - m_int = ConvertIrq2Int(np2cfg.lgy98irq); - - m_chkenabled.SubclassDlgItem(IDC_LGY98ENABLED, this); - if(m_enabled) - m_chkenabled.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkenabled.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_cmbport.SubclassDlgItem(IDC_LGY98IO, this); - m_cmbport.Add(s_port, _countof(s_port)); - SetPort(m_port); - - m_cmbint.SubclassDlgItem(IDC_LGY98INT, this); - m_cmbint.Add(s_int, _countof(s_int)); - SetInt(m_int); - - m_cmbport.SetFocus(); - - return FALSE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void CLgy98Page::OnOK() -{ - UINT update = 0; - - if (np2cfg.uselgy98 != m_enabled - || (np2cfg.lgy98io>>8) != m_port - || np2cfg.lgy98irq != ConvertInt2Irq(m_int)) - { - np2cfg.uselgy98 = m_enabled; - np2cfg.lgy98io = (m_port<<8)|0xD0; - np2cfg.lgy98irq = ConvertInt2Irq(m_int); - update |= SYS_UPDATECFG; - } - ::sysmng_update(update); -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL CLgy98Page::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_LGY98ENABLED: - m_enabled = (m_chkenabled.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - - case IDC_LGY98IO: - m_port = GetPort(); - return TRUE; - - case IDC_LGY98INT: - m_int = GetInt(); - return TRUE; - - case IDC_LGY98DEF: - m_port = 0x10; - m_int = 1; - SetPort(m_port); - SetInt(m_int); - return TRUE; - } - return FALSE; -} - -/** - * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT CLgy98Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - //switch (nMsg) - //{ - //} - return CDlgProc::WindowProc(nMsg, wParam, lParam); -} - -/** - * IRQ -> INT変換 - * @return INT - */ -UINT8 CLgy98Page::ConvertIrq2Int(UINT8 cValue) -{ - switch(cValue){ - case 3: - return 0; - case 5: - return 1; - case 6: - return 2; - case 12: - return 5; - } - return 0; -} -/** - * INT -> IRQ変換 - * @return IRQ - */ -UINT8 CLgy98Page::ConvertInt2Irq(UINT8 cValue) -{ - switch(cValue){ - case 0: - return 3; - case 1: - return 5; - case 2: - return 6; - case 5: - return 12; - } - return 0; -} - -/** - * I/O を設定 - * @param[in] cValue 設定 - */ -void CLgy98Page::SetPort(UINT8 cValue) -{ - m_cmbport.SetCurItemData(cValue); -} - -/** - * I/O を取得 - * @return I/O - */ -UINT8 CLgy98Page::GetPort() const -{ - return m_cmbport.GetCurItemData(0x01); -} - -/** - * INT を設定 - * @param[in] cValue 設定 - */ -void CLgy98Page::SetInt(UINT8 cValue) -{ - m_cmbint.SetCurItemData(cValue); -} - -/** - * INT を取得 - * @return INT - */ -UINT8 CLgy98Page::GetInt() const -{ - return m_cmbint.GetCurItemData(0x01); -} - -#endif - -/** - * コンフィグ ダイアログ - * @param[in] hwndParent 親ウィンドウ - */ -void dialog_netopt(HWND hwndParent) -{ - CPropSheetProc prop(IDS_NETWORKOPTION, hwndParent); - - CNetworkPage network; - prop.AddPage(&network); - -#if defined(SUPPORT_LGY98) - CLgy98Page lgy98; - prop.AddPage(&lgy98); -#endif - - prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; - prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); - prop.m_psh.pfnCallback = np2class_propetysheet; - prop.DoModal(); - - InvalidateRect(hwndParent, NULL, TRUE); -} - +/** + * @file d_network.cpp + * @brief Network configure dialog procedure + * + * @author $Author: SimK $ + * @date $Date: 2016/03/11 $ + */ + +#include +#include "resource.h" +#include +#include "dialog.h" +#include "c_combodata.h" +#include "np2class.h" +#include +#include +#include +#include +#include "misc\PropProc.h" +#include +#include + +#if defined(SUPPORT_NET) + +/** + * @brief ネットワーク基本設定ページ + * @param[in] hwndParent 親ウィンドウ + */ +class CNetworkPage : public CPropPageProc +{ +public: + CNetworkPage(); + virtual ~CNetworkPage(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + TCHAR m_tap[300]; //!< TAP名 + UINT8 m_pmmenabled; //!< 負荷低減有効フラグ + CComboData m_cmbtap; //!< TAP NAME + CWndProc m_chkpmmenabled; //!< POWER MANAGEMENT ENABLED + void SetNetWorkDeviceNames(); +}; + +/** + * コンストラクタ + */ +CNetworkPage::CNetworkPage() + : CPropPageProc(IDD_NETWORK) +{ +} +/** + * デストラクタ + */ +CNetworkPage::~CNetworkPage() +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL CNetworkPage::OnInitDialog() +{ + _tcscpy(m_tap, np2cfg.np2nettap); + + m_cmbtap.SubclassDlgItem(IDC_NETTAP, this); + SetNetWorkDeviceNames(); + + m_pmmenabled = np2cfg.np2netpmm; + m_chkpmmenabled.SubclassDlgItem(IDC_NETPMM, this); + if(m_pmmenabled) + m_chkpmmenabled.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkpmmenabled.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_cmbtap.SetFocus(); + + return FALSE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void CNetworkPage::OnOK() +{ + UINT update = 0; + + if (_tcscmp(np2cfg.np2nettap, m_tap)!=0 || m_pmmenabled!=np2cfg.np2netpmm) + { + _tcscpy(np2cfg.np2nettap, m_tap); + np2cfg.np2netpmm = m_pmmenabled; + update |= SYS_UPDATECFG; + } + ::sysmng_update(update); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL CNetworkPage::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_NETTAP: + m_cmbtap.GetWindowText(m_tap, NELEMENTS(m_tap)); + return TRUE; + + case IDC_NETPMM: + m_pmmenabled = (m_chkpmmenabled.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + } + return FALSE; +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CNetworkPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + //switch (nMsg) + //{ + //} + return CDlgProc::WindowProc(nMsg, wParam, lParam); +} + +/** + * ネットワークデバイス表示名をコンボボックスデータに放り込む + * 参考文献: http://dsas.blog.klab.org/archives/51012690.html + */ +void CNetworkPage::SetNetWorkDeviceNames() +{ + CONST TCHAR *SUBKEY = _T("SYSTEM\\CurrentControlSet\\Control\\Network"); + +#define BUFSZ 256 + int index = 0; + int indexsel = -1; + HKEY hKey1, hKey2, hKey3; + LONG nResult; + DWORD dwIdx1, dwIdx2; + TCHAR szData[64], *pKeyName1, *pKeyName2, *pKeyName3, *pKeyName4; + DWORD dwSize, dwType = REG_SZ; + BOOL bDone = FALSE; + FILETIME ft; + + hKey1 = hKey2 = hKey3 = NULL; + pKeyName1 = pKeyName2 = pKeyName3 = pKeyName4 = NULL; + + // 主キーのオープン + nResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SUBKEY, 0, KEY_READ, &hKey1); + if (nResult != ERROR_SUCCESS) { + return; + } + pKeyName1 = (TCHAR*)malloc(sizeof(TCHAR)*BUFSZ); + pKeyName2 = (TCHAR*)malloc(sizeof(TCHAR)*BUFSZ); + pKeyName3 = (TCHAR*)malloc(sizeof(TCHAR)*BUFSZ); + pKeyName4 = (TCHAR*)malloc(sizeof(TCHAR)*BUFSZ); + + dwIdx1 = 0; + while (bDone != TRUE) { // {id1} を列挙するループ + + dwSize = BUFSZ; + nResult = RegEnumKeyEx(hKey1, dwIdx1++, pKeyName1, + &dwSize, NULL, NULL, NULL, &ft); + if (nResult == ERROR_NO_MORE_ITEMS) { + break; + } + + // SUBKEY\{id1} キーをオープン + _stprintf(pKeyName2, _T("%s\\%s"), SUBKEY, pKeyName1); + nResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pKeyName2, + 0, KEY_READ, &hKey2); + if (nResult != ERROR_SUCCESS) { + continue; + } + dwIdx2 = 0; + while (1) { // {id2} を列挙するループ + dwSize = BUFSZ; + nResult = RegEnumKeyEx(hKey2, dwIdx2++, pKeyName3, + &dwSize, NULL, NULL, NULL, &ft); + if (nResult == ERROR_NO_MORE_ITEMS) { + break; + } + + if (nResult != ERROR_SUCCESS) { + continue; + } + + // SUBKEY\{id1}\{id2]\Connection キーをオープン + _stprintf(pKeyName4, _T("%s\\%s\\%s"), + pKeyName2, pKeyName3, _T("Connection")); + nResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + pKeyName4, 0, KEY_READ, &hKey3); + if (nResult != ERROR_SUCCESS) { + continue; + } + + // SUBKEY\{id1}\{id2]\Connection\PnpInstanceID 値を取得 + dwSize = sizeof(szData); + nResult = RegQueryValueEx(hKey3, _T("PnpInstanceID"), + 0, &dwType, (LPBYTE)szData, &dwSize); + + if (nResult == ERROR_SUCCESS) { + if(_tcslen(szData)>0){ + // SUBKEY\{id1}\{id2]\Connection\Name 値を取得 + dwSize = sizeof(szData); + nResult = RegQueryValueEx(hKey3, _T("Name"), + 0, &dwType, (LPBYTE)szData, &dwSize); + + if (nResult == ERROR_SUCCESS) { + if(_tcslen(szData)>0){ + m_cmbtap.Add(szData, index); + if(_tcscmp(szData, m_tap)==0){ + m_cmbtap.SetCurSel(index); + indexsel = index; + } + index++; + } + } + } + } + RegCloseKey(hKey3); + hKey3 = NULL; + } + RegCloseKey(hKey2); + hKey2 = NULL; + } + + if (hKey1) { RegCloseKey(hKey1); } + if (hKey2) { RegCloseKey(hKey2); } + if (hKey3) { RegCloseKey(hKey3); } + + if (pKeyName1) { free(pKeyName1); } + if (pKeyName2) { free(pKeyName2); } + if (pKeyName3) { free(pKeyName3); } + if (pKeyName4) { free(pKeyName4); } + + if(indexsel == -1){ + // カスタム接続名 + m_cmbtap.SetWindowText(m_tap); + } + + return; +} + +#if defined(SUPPORT_LGY98) + +/** + * @brief LGY-98 設定ページ + * @param[in] hwndParent 親ウィンドウ + */ +class CLgy98Page : public CPropPageProc +{ +public: + CLgy98Page(); + virtual ~CLgy98Page(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + UINT8 m_enabled; //!< 有効フラグ + UINT8 m_port; //!< PORT設定値 + UINT8 m_int; //!< INT設定値 + CWndProc m_chkenabled; //!< ENABLED + CComboData m_cmbport; //!< IO + CComboData m_cmbint; //!< INT + CWndProc m_btnreset; //!< RESET + UINT8 ConvertIrq2Int(UINT8 cValue); + UINT8 ConvertInt2Irq(UINT8 cValue); + void SetPort(UINT8 cValue); + UINT8 GetPort() const; + void SetInt(UINT8 cValue); + UINT8 GetInt() const; +}; + +/** + * ポートリスト + */ +static const CComboData::Entry s_port[] = +{ + {MAKEINTRESOURCE(IDS_00D0), 0x00}, + {MAKEINTRESOURCE(IDS_10D0), 0x10}, + {MAKEINTRESOURCE(IDS_20D0), 0x20}, + {MAKEINTRESOURCE(IDS_30D0), 0x30}, + {MAKEINTRESOURCE(IDS_40D0), 0x40}, + {MAKEINTRESOURCE(IDS_50D0), 0x50}, + {MAKEINTRESOURCE(IDS_60D0), 0x60}, + {MAKEINTRESOURCE(IDS_70D0), 0x70}, +}; + +/** + * 割り込みリスト + */ +static const CComboData::Entry s_int[] = +{ + {MAKEINTRESOURCE(IDS_INT0), 0}, + {MAKEINTRESOURCE(IDS_INT1), 1}, + {MAKEINTRESOURCE(IDS_INT2), 2}, + {MAKEINTRESOURCE(IDS_INT5), 5}, +}; + +/** + * コンストラクタ + */ +CLgy98Page::CLgy98Page() + : CPropPageProc(IDD_LGY98) + , m_port((UINT8)IDS_10D0), m_int((UINT8)IDS_INT1) +{ +} +/** + * デストラクタ + */ +CLgy98Page::~CLgy98Page() +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL CLgy98Page::OnInitDialog() +{ + m_enabled = np2cfg.uselgy98; + m_port = (UINT8)(np2cfg.lgy98io>>8); + m_int = ConvertIrq2Int(np2cfg.lgy98irq); + + m_chkenabled.SubclassDlgItem(IDC_LGY98ENABLED, this); + if(m_enabled) + m_chkenabled.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkenabled.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_cmbport.SubclassDlgItem(IDC_LGY98IO, this); + m_cmbport.Add(s_port, _countof(s_port)); + SetPort(m_port); + + m_cmbint.SubclassDlgItem(IDC_LGY98INT, this); + m_cmbint.Add(s_int, _countof(s_int)); + SetInt(m_int); + + m_cmbport.SetFocus(); + + return FALSE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void CLgy98Page::OnOK() +{ + UINT update = 0; + + if (np2cfg.uselgy98 != m_enabled + || (np2cfg.lgy98io>>8) != m_port + || np2cfg.lgy98irq != ConvertInt2Irq(m_int)) + { + np2cfg.uselgy98 = m_enabled; + np2cfg.lgy98io = (m_port<<8)|0xD0; + np2cfg.lgy98irq = ConvertInt2Irq(m_int); + update |= SYS_UPDATECFG; + } + ::sysmng_update(update); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL CLgy98Page::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_LGY98ENABLED: + m_enabled = (m_chkenabled.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + + case IDC_LGY98IO: + m_port = GetPort(); + return TRUE; + + case IDC_LGY98INT: + m_int = GetInt(); + return TRUE; + + case IDC_LGY98DEF: + m_port = 0x10; + m_int = 1; + SetPort(m_port); + SetInt(m_int); + return TRUE; + } + return FALSE; +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CLgy98Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + //switch (nMsg) + //{ + //} + return CDlgProc::WindowProc(nMsg, wParam, lParam); +} + +/** + * IRQ -> INT変換 + * @return INT + */ +UINT8 CLgy98Page::ConvertIrq2Int(UINT8 cValue) +{ + switch(cValue){ + case 3: + return 0; + case 5: + return 1; + case 6: + return 2; + case 12: + return 5; + } + return 0; +} +/** + * INT -> IRQ変換 + * @return IRQ + */ +UINT8 CLgy98Page::ConvertInt2Irq(UINT8 cValue) +{ + switch(cValue){ + case 0: + return 3; + case 1: + return 5; + case 2: + return 6; + case 5: + return 12; + } + return 0; +} + +/** + * I/O を設定 + * @param[in] cValue 設定 + */ +void CLgy98Page::SetPort(UINT8 cValue) +{ + m_cmbport.SetCurItemData(cValue); +} + +/** + * I/O を取得 + * @return I/O + */ +UINT8 CLgy98Page::GetPort() const +{ + return m_cmbport.GetCurItemData(0x01); +} + +/** + * INT を設定 + * @param[in] cValue 設定 + */ +void CLgy98Page::SetInt(UINT8 cValue) +{ + m_cmbint.SetCurItemData(cValue); +} + +/** + * INT を取得 + * @return INT + */ +UINT8 CLgy98Page::GetInt() const +{ + return m_cmbint.GetCurItemData(0x01); +} + +#endif + +/** + * コンフィグ ダイアログ + * @param[in] hwndParent 親ウィンドウ + */ +void dialog_netopt(HWND hwndParent) +{ + CPropSheetProc prop(IDS_NETWORKOPTION, hwndParent); + + CNetworkPage network; + prop.AddPage(&network); + +#if defined(SUPPORT_LGY98) + CLgy98Page lgy98; + prop.AddPage(&lgy98); +#endif + + prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; + prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); + prop.m_psh.pfnCallback = np2class_propetysheet; + prop.DoModal(); + + InvalidateRect(hwndParent, NULL, TRUE); +} + #endif \ No newline at end of file diff --git a/windows/dialog/d_pci.cpp b/windows/dialog/d_pci.cpp old mode 100755 new mode 100644 index 2ffc0cc3..7fdfcb3b --- a/windows/dialog/d_pci.cpp +++ b/windows/dialog/d_pci.cpp @@ -1,199 +1,199 @@ -/** - * @file d_pci.cpp - * @brief PCI 設定ダイアログ - */ - -#include -#include "resource.h" -#include -#include "dialog.h" -#include "c_combodata.h" -#include "np2class.h" -#include -#include -#include -#include -#include "misc\PropProc.h" -#include -#include - -#if defined(SUPPORT_PCI) - -/** - * @brief ウィンドウアクセラレータ基本設定ページ - * @param[in] hwndParent 親ウィンドウ - */ -class CPCIPage : public CPropPageProc -{ -public: - CPCIPage(); - virtual ~CPCIPage(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - UINT8 m_enable; //!< 有効 - UINT8 m_pcmctype; //!< PCMC種類設定 - UINT8 m_bios32; //!< BIOS32有効 - CWndProc m_chkenable; //!< PCI ENABLE - CComboData m_cmbpcmctype; //!< PCMC TYPE - CWndProc m_chkbios32; //!< BIOS32 ENABLE - void SetPCMCType(UINT16 cValue); - UINT8 GetPCMCType() const; -}; - -/** - * コンストラクタ - */ -CPCIPage::CPCIPage() - : CPropPageProc(IDD_PCI) -{ -} -/** - * デストラクタ - */ -CPCIPage::~CPCIPage() -{ -} - -/** - * 機種リスト - */ -static const CComboData::Entry s_type[] = -{ - {MAKEINTRESOURCE(IDS_PCI_PCMC_82434LX), PCI_PCMC_82434LX}, - {MAKEINTRESOURCE(IDS_PCI_PCMC_82441FX), PCI_PCMC_82441FX}, - {MAKEINTRESOURCE(IDS_PCI_PCMC_WILDCAT), PCI_PCMC_WILDCAT}, -}; - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL CPCIPage::OnInitDialog() -{ - m_enable = np2cfg.usepci; - m_pcmctype = np2cfg.pci_pcmc; - m_bios32 = np2cfg.pci_bios32; - - m_chkenable.SubclassDlgItem(IDC_PCIENABLE, this); - if(m_enable) - m_chkenable.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkenable.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_cmbpcmctype.SubclassDlgItem(IDC_PCIPCMCTYPE, this); - m_cmbpcmctype.Add(s_type, _countof(s_type)); - SetPCMCType(m_pcmctype); - - m_chkbios32.SubclassDlgItem(IDC_PCIBIOS32, this); - if(m_bios32) - m_chkbios32.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkbios32.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_chkenable.SetFocus(); - - return FALSE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void CPCIPage::OnOK() -{ - UINT update = 0; - - if (np2cfg.usepci != m_enable - || np2cfg.pci_pcmc != m_pcmctype - || np2cfg.pci_bios32 != m_bios32) - { - np2cfg.usepci = m_enable; - np2cfg.pci_pcmc = m_pcmctype; - np2cfg.pci_bios32 = m_bios32; - update |= SYS_UPDATECFG; - } - ::sysmng_update(update); -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL CPCIPage::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_PCIENABLE: - m_enable = (m_chkenable.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - - case IDC_PCIPCMCTYPE: - m_pcmctype = GetPCMCType(); - return TRUE; - - case IDC_PCIBIOS32: - m_bios32 = (m_chkbios32.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - } - return FALSE; -} - -/** - * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT CPCIPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - return CDlgProc::WindowProc(nMsg, wParam, lParam); -} - -/** - * 機種を設定 - * @param[in] cValue 設定 - */ -void CPCIPage::SetPCMCType(UINT16 cValue) -{ - m_cmbpcmctype.SetCurItemData(cValue); -} - -/** - * 機種を取得 - * @return I/O - */ -UINT8 CPCIPage::GetPCMCType() const -{ - return m_cmbpcmctype.GetCurItemData(PCI_PCMC_82434LX); -} - - -/** - * コンフィグ ダイアログ - * @param[in] hwndParent 親ウィンドウ - */ -void dialog_pciopt(HWND hwndParent) -{ - CPropSheetProc prop(IDS_PCIOPTION, hwndParent); - - CPCIPage pci; - prop.AddPage(&pci); - - prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; - prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); - prop.m_psh.pfnCallback = np2class_propetysheet; - prop.DoModal(); - - InvalidateRect(hwndParent, NULL, TRUE); -} - +/** + * @file d_pci.cpp + * @brief PCI 設定ダイアログ + */ + +#include +#include "resource.h" +#include +#include "dialog.h" +#include "c_combodata.h" +#include "np2class.h" +#include +#include +#include +#include +#include "misc\PropProc.h" +#include +#include + +#if defined(SUPPORT_PCI) + +/** + * @brief ウィンドウアクセラレータ基本設定ページ + * @param[in] hwndParent 親ウィンドウ + */ +class CPCIPage : public CPropPageProc +{ +public: + CPCIPage(); + virtual ~CPCIPage(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + UINT8 m_enable; //!< 有効 + UINT8 m_pcmctype; //!< PCMC種類設定 + UINT8 m_bios32; //!< BIOS32有効 + CWndProc m_chkenable; //!< PCI ENABLE + CComboData m_cmbpcmctype; //!< PCMC TYPE + CWndProc m_chkbios32; //!< BIOS32 ENABLE + void SetPCMCType(UINT16 cValue); + UINT8 GetPCMCType() const; +}; + +/** + * コンストラクタ + */ +CPCIPage::CPCIPage() + : CPropPageProc(IDD_PCI) +{ +} +/** + * デストラクタ + */ +CPCIPage::~CPCIPage() +{ +} + +/** + * 機種リスト + */ +static const CComboData::Entry s_type[] = +{ + {MAKEINTRESOURCE(IDS_PCI_PCMC_82434LX), PCI_PCMC_82434LX}, + {MAKEINTRESOURCE(IDS_PCI_PCMC_82441FX), PCI_PCMC_82441FX}, + {MAKEINTRESOURCE(IDS_PCI_PCMC_WILDCAT), PCI_PCMC_WILDCAT}, +}; + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL CPCIPage::OnInitDialog() +{ + m_enable = np2cfg.usepci; + m_pcmctype = np2cfg.pci_pcmc; + m_bios32 = np2cfg.pci_bios32; + + m_chkenable.SubclassDlgItem(IDC_PCIENABLE, this); + if(m_enable) + m_chkenable.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkenable.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_cmbpcmctype.SubclassDlgItem(IDC_PCIPCMCTYPE, this); + m_cmbpcmctype.Add(s_type, _countof(s_type)); + SetPCMCType(m_pcmctype); + + m_chkbios32.SubclassDlgItem(IDC_PCIBIOS32, this); + if(m_bios32) + m_chkbios32.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkbios32.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_chkenable.SetFocus(); + + return FALSE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void CPCIPage::OnOK() +{ + UINT update = 0; + + if (np2cfg.usepci != m_enable + || np2cfg.pci_pcmc != m_pcmctype + || np2cfg.pci_bios32 != m_bios32) + { + np2cfg.usepci = m_enable; + np2cfg.pci_pcmc = m_pcmctype; + np2cfg.pci_bios32 = m_bios32; + update |= SYS_UPDATECFG; + } + ::sysmng_update(update); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL CPCIPage::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_PCIENABLE: + m_enable = (m_chkenable.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + + case IDC_PCIPCMCTYPE: + m_pcmctype = GetPCMCType(); + return TRUE; + + case IDC_PCIBIOS32: + m_bios32 = (m_chkbios32.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + } + return FALSE; +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CPCIPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + return CDlgProc::WindowProc(nMsg, wParam, lParam); +} + +/** + * 機種を設定 + * @param[in] cValue 設定 + */ +void CPCIPage::SetPCMCType(UINT16 cValue) +{ + m_cmbpcmctype.SetCurItemData(cValue); +} + +/** + * 機種を取得 + * @return I/O + */ +UINT8 CPCIPage::GetPCMCType() const +{ + return m_cmbpcmctype.GetCurItemData(PCI_PCMC_82434LX); +} + + +/** + * コンフィグ ダイアログ + * @param[in] hwndParent 親ウィンドウ + */ +void dialog_pciopt(HWND hwndParent) +{ + CPropSheetProc prop(IDS_PCIOPTION, hwndParent); + + CPCIPage pci; + prop.AddPage(&pci); + + prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; + prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); + prop.m_psh.pfnCallback = np2class_propetysheet; + prop.DoModal(); + + InvalidateRect(hwndParent, NULL, TRUE); +} + #endif \ No newline at end of file diff --git a/windows/dialog/d_screen.cpp b/windows/dialog/d_screen.cpp old mode 100755 new mode 100644 index 0b665cbe..30463dba --- a/windows/dialog/d_screen.cpp +++ b/windows/dialog/d_screen.cpp @@ -1,764 +1,764 @@ -/** - * @file d_screen.cpp - * @brief スクリーン設定ダイアログ - */ - -#include -#include "resource.h" -#include "dialog.h" -#include "c_combodata.h" -#include "c_slidervalue.h" -#include "np2class.h" -#include -#include -#include -#ifdef SUPPORT_SCRN_DIRECT3D -#include "scrnmng_d3d.h" -#endif -#include -#include "misc\PropProc.h" -#include -#include -#include "common\strres.h" -#include "vram\scrndraw.h" -#include "vram\palettes.h" - -static int resetScreen = 0; - -/** - * @brief Video ページ - */ -class ScrOptVideoPage : public CPropPageProc -{ -public: - ScrOptVideoPage(); - virtual ~ScrOptVideoPage(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - CSliderValue m_skiplight; //!< スキップライン -}; - -/** - * コンストラクタ - */ -ScrOptVideoPage::ScrOptVideoPage() - : CPropPageProc(IDD_SCROPT1) -{ -} - -/** - * デストラクタ - */ -ScrOptVideoPage::~ScrOptVideoPage() -{ -} - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL ScrOptVideoPage::OnInitDialog() -{ - CheckDlgButton(IDC_LCD, (np2cfg.LCD_MODE & 1) ? BST_CHECKED : BST_UNCHECKED); - GetDlgItem(IDC_LCDX).EnableWindow((np2cfg.LCD_MODE & 1) ? TRUE : FALSE); - CheckDlgButton(IDC_LCDX, (np2cfg.LCD_MODE & 2) ? BST_CHECKED : BST_UNCHECKED); - - CheckDlgButton(IDC_SKIPLINE, (np2cfg.skipline) ? BST_CHECKED : BST_UNCHECKED); - - m_skiplight.SubclassDlgItem(IDC_SKIPLIGHT, this); - m_skiplight.SetStaticId(IDC_LIGHTSTR); - m_skiplight.SetRange(0, 255); - m_skiplight.SetPos(np2cfg.skiplight); - return TRUE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void ScrOptVideoPage::OnOK() -{ - bool bUpdated = false; - - const UINT8 cSkipLine = (IsDlgButtonChecked(IDC_SKIPLINE) != BST_UNCHECKED) ? 1 : 0; - if (np2cfg.skipline != cSkipLine) - { - np2cfg.skipline = cSkipLine; - bUpdated = true; - } - const UINT8 cSkipLight = static_cast(m_skiplight.GetPos()); - if (np2cfg.skiplight != cSkipLight) - { - np2cfg.skiplight = cSkipLight; - bUpdated = true; - } - if (bUpdated) - { - ::pal_makeskiptable(); - } - - UINT8 cMode = 0; - if (IsDlgButtonChecked(IDC_LCD) != BST_UNCHECKED) - { - cMode |= 1; - } - if (IsDlgButtonChecked(IDC_LCDX) != BST_UNCHECKED) - { - cMode |= 2; - } - if (np2cfg.LCD_MODE != cMode) - { - np2cfg.LCD_MODE = cMode; - pal_makelcdpal(); - bUpdated = true; - } - if (bUpdated) - { - ::scrndraw_redraw(); - ::sysmng_update(SYS_UPDATECFG); - } -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL ScrOptVideoPage::OnCommand(WPARAM wParam, LPARAM lParam) -{ - if (LOWORD(wParam) == IDC_LCD) - { - const BOOL bEnable = (IsDlgButtonChecked(IDC_LCD) != BST_UNCHECKED) ? TRUE : FALSE; - GetDlgItem(IDC_LCDX).EnableWindow(bEnable); - return TRUE; - } - return FALSE; -} - -/** - * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT ScrOptVideoPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - if (nMsg == WM_HSCROLL) - { - switch (::GetDlgCtrlID(reinterpret_cast(lParam))) - { - case IDC_SKIPLIGHT: - m_skiplight.UpdateValue(); - break; - - default: - break; - } - } - return CDlgProc::WindowProc(nMsg, wParam, lParam); -} - - - -// ---- -/** - * @brief Chip ページ - */ -class ScrOptChipPage : public CPropPageProc -{ -public: - ScrOptChipPage(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); -}; - -/** - * コンストラクタ - */ -ScrOptChipPage::ScrOptChipPage() - : CPropPageProc(IDD_SCROPT2) -{ -} - -//! GDC チップ -static const UINT s_gdcchip[4] = {IDC_GRCGNON, IDC_GRCG, IDC_GRCG2, IDC_EGC}; - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL ScrOptChipPage::OnInitDialog() -{ - CheckDlgButton((np2cfg.uPD72020) ? IDC_GDC72020 : IDC_GDC7220, BST_CHECKED); - CheckDlgButton(s_gdcchip[np2cfg.grcg & 3], BST_CHECKED); - CheckDlgButton(IDC_PC980124, (np2cfg.color16) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(IDC_PEGC, (np2cfg.usepegcplane) ? BST_CHECKED : BST_UNCHECKED); - -#if defined(SUPPORT_PC9821) - static const UINT s_disabled[] = - { - IDC_GCBOX, - IDC_GRCGNON, IDC_GRCG, IDC_GRCG2, IDC_EGC, - IDC_PC980124 - }; - for (UINT i = 0; i < _countof(s_disabled); i++) - { - GetDlgItem(s_disabled[i]).EnableWindow(FALSE); - } - CheckDlgButton(s_gdcchip[0], BST_UNCHECKED); - CheckDlgButton(s_gdcchip[1], BST_UNCHECKED); - CheckDlgButton(s_gdcchip[2], BST_UNCHECKED); - CheckDlgButton(s_gdcchip[3], BST_CHECKED); -#else - GetDlgItem(IDC_PEGC).EnableWindow(FALSE); - CheckDlgButton(IDC_PEGC, BST_UNCHECKED); -#endif // defined(SUPPORT_PC9821) - - return TRUE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void ScrOptChipPage::OnOK() -{ - bool bUpdated = false; - - const UINT8 cMode = (IsDlgButtonChecked(IDC_GDC72020) != BST_UNCHECKED) ? 1 : 0; - if (np2cfg.uPD72020 != cMode) - { - np2cfg.uPD72020 = cMode; - bUpdated = true; - gdc_restorekacmode(); - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - } - - for (UINT i = 0; i < _countof(s_gdcchip); i++) - { - if (IsDlgButtonChecked(s_gdcchip[i]) != BST_UNCHECKED) - { - const UINT8 cType = static_cast(i); - if (np2cfg.grcg != cType) - { - np2cfg.grcg = cType; - bUpdated = true; - gdcs.grphdisp |= GDCSCRN_ALLDRAW2; - } - break; - } - } - - const UINT8 cColor16 = (IsDlgButtonChecked(IDC_PC980124) != BST_UNCHECKED) ? 1 : 0; - if (np2cfg.color16 != cColor16) - { - np2cfg.color16 = cColor16; - bUpdated = true; - } - - const UINT8 cPEGC = (IsDlgButtonChecked(IDC_PEGC) != BST_UNCHECKED) ? 1 : 0; - if (np2cfg.usepegcplane != cPEGC) - { - np2cfg.usepegcplane = cPEGC; - bUpdated = true; - } - - if (bUpdated) - { - ::sysmng_update(SYS_UPDATECFG); - } -} - - - -// ---- - -/** - * @brief Timing ページ - */ -class ScrOptTimingPage : public CPropPageProc -{ -public: - ScrOptTimingPage(); - virtual ~ScrOptTimingPage(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - CSliderValue m_tram; //!< TRAM - CSliderValue m_vram; //!< VRAM - CSliderValue m_grcg; //!< GRCG - CSliderValue m_raster; //!< ラスタ -}; - -/** - * コンストラクタ - */ -ScrOptTimingPage::ScrOptTimingPage() - : CPropPageProc(IDD_SCROPT3) -{ -} - -/** - * デストラクタ - */ -ScrOptTimingPage::~ScrOptTimingPage() -{ -} - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL ScrOptTimingPage::OnInitDialog() -{ - m_tram.SubclassDlgItem(IDC_TRAMWAIT, this); - m_tram.SetStaticId(IDC_TRAMSTR); - m_tram.SetRange(0, 32); - m_tram.SetPos(np2cfg.wait[0]); - - m_vram.SubclassDlgItem(IDC_VRAMWAIT, this); - m_vram.SetStaticId(IDC_VRAMSTR); - m_vram.SetRange(0, 32); - m_vram.SetPos(np2cfg.wait[2]); - - m_grcg.SubclassDlgItem(IDC_GRCGWAIT, this); - m_grcg.SetStaticId(IDC_GRCGSTR); - m_grcg.SetRange(0, 32); - m_grcg.SetPos(np2cfg.wait[4]); - - m_raster.SubclassDlgItem(IDC_REALPAL, this); - m_raster.SetStaticId(IDC_REALPALSTR); - m_raster.SetRange(-32, 32); - m_raster.SetPos(np2cfg.realpal - 32); - - return TRUE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void ScrOptTimingPage::OnOK() -{ - bool bUpdated = false; - - UINT8 sWait[6]; - ZeroMemory(sWait, sizeof(sWait)); - sWait[0] = static_cast(m_tram.GetPos()); - sWait[2] = static_cast(m_vram.GetPos()); - sWait[4] = static_cast(m_grcg.GetPos()); - - sWait[1] = (sWait[0]) ? 1 : 0; - sWait[3] = (sWait[2]) ? 1 : 0; - sWait[5] = (sWait[4]) ? 1 : 0; - - for (UINT i = 0; i < 6; i++) - { - if (np2cfg.wait[i] != sWait[i]) - { - np2cfg.wait[i] = sWait[i]; - bUpdated = true; - } - } - - const UINT8 cRealPal = static_cast(m_raster.GetPos() + 32); - if (np2cfg.realpal != cRealPal) - { - np2cfg.realpal = cRealPal; - bUpdated = true; - } - - if (bUpdated) - { - ::sysmng_update(SYS_UPDATECFG); - } -} - -/** - * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT ScrOptTimingPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - if (nMsg == WM_HSCROLL) - { - switch (::GetDlgCtrlID(reinterpret_cast(lParam))) - { - case IDC_TRAMWAIT: - m_tram.UpdateValue(); - break; - - case IDC_VRAMWAIT: - m_vram.UpdateValue(); - break; - - case IDC_GRCGWAIT: - m_grcg.UpdateValue(); - break; - - case IDC_REALPAL: - m_raster.UpdateValue(); - break; - - default: - break; - } - } - return CDlgProc::WindowProc(nMsg, wParam, lParam); -} - - - -// ---- - -/** - * @brief Fullscreen ページ - */ -class ScrOptFullscreenPage : public CPropPageProc -{ -public: - ScrOptFullscreenPage(); - virtual ~ScrOptFullscreenPage(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - -private: - CComboData m_zoom; //!< ズーム -}; - -//! ズーム リスト -static const CComboData::Entry s_zoom[] = -{ - {MAKEINTRESOURCE(IDS_ZOOM_NONE), FSCRNMOD_NORESIZE}, - {MAKEINTRESOURCE(IDS_ZOOM_FIXEDASPECT), FSCRNMOD_ASPECTFIX8}, - {MAKEINTRESOURCE(IDS_ZOOM_ADJUSTASPECT), FSCRNMOD_ASPECTFIX}, - {MAKEINTRESOURCE(IDS_ZOOM_FULL), FSCRNMOD_LARGE}, - {MAKEINTRESOURCE(IDS_ZOOM_INTMULTIPLE), FSCRNMOD_INTMULTIPLE}, -}; - -/** - * コンストラクタ - */ -ScrOptFullscreenPage::ScrOptFullscreenPage() - : CPropPageProc(IDD_SCROPT_FULLSCREEN) -{ -} - -/** - * デストラクタ - */ -ScrOptFullscreenPage::~ScrOptFullscreenPage() -{ -} - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL ScrOptFullscreenPage::OnInitDialog() -{ - UINT8 c = FSCRNCFG_fscrnmod; -#if defined(SUPPORT_MULTITHREAD) - if(np2_multithread_Enabled()){ - CWndBase wndTemp; - wndTemp = GetDlgItem(IDC_FULLSCREEN_SAMEBPP); - if(wndTemp){ - wndTemp.EnableWindow(FALSE); - } - wndTemp = GetDlgItem(IDC_FULLSCREEN_SAMERES); - if(wndTemp){ - wndTemp.EnableWindow(FALSE); - } - c |= FSCRNMOD_SAMEBPP | FSCRNMOD_SAMERES; - } -#endif - - CheckDlgButton(IDC_FULLSCREEN_SAMEBPP, (c & FSCRNMOD_SAMEBPP) ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(IDC_FULLSCREEN_SAMERES, (c & FSCRNMOD_SAMERES) ? BST_CHECKED : BST_UNCHECKED); - - m_zoom.SubclassDlgItem(IDC_FULLSCREEN_ZOOM, this); - m_zoom.Add(s_zoom, _countof(s_zoom)); - m_zoom.SetCurItemData(c & FSCRNMOD_ASPECTMASK); - m_zoom.EnableWindow((c & FSCRNMOD_SAMERES) ? TRUE : FALSE); - - return TRUE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void ScrOptFullscreenPage::OnOK() -{ - UINT8 c = 0; - UINT8 c2 = 0; - if (IsDlgButtonChecked(IDC_FULLSCREEN_SAMEBPP) != BST_UNCHECKED) - { - c |= FSCRNMOD_SAMEBPP; - } - if (IsDlgButtonChecked(IDC_FULLSCREEN_SAMERES) != BST_UNCHECKED) - { - c |= FSCRNMOD_SAMERES; - } - c2 = c; - c |= m_zoom.GetCurItemData(FSCRNCFG_fscrnmod & FSCRNMOD_ASPECTMASK); - c2 |= m_zoom.GetCurItemData(np2oscfg.fscrnmod & FSCRNMOD_ASPECTMASK); - if ((np2oscfg.fsrescfg && (!scrnrescfg.hasfscfg || scrnrescfg.fscrnmod != c)) || np2oscfg.fscrnmod != c2) - { - if((np2oscfg.fsrescfg && (!scrnrescfg.hasfscfg || scrnrescfg.fscrnmod != c)) || (!np2oscfg.fsrescfg && np2oscfg.fscrnmod != c2)){ - resetScreen = 1; - } - if(np2oscfg.fsrescfg){ - scrnrescfg.fscrnmod = c; - scrnrescfg.hasfscfg = 1; - scrnres_writeini(); - } - np2oscfg.fscrnmod = c; - ::sysmng_update(SYS_UPDATEOSCFG); - } -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL ScrOptFullscreenPage::OnCommand(WPARAM wParam, LPARAM lParam) -{ - if (LOWORD(wParam) == IDC_FULLSCREEN_SAMERES) - { - m_zoom.EnableWindow((IsDlgButtonChecked(IDC_FULLSCREEN_SAMERES) != BST_UNCHECKED) ? TRUE : FALSE); - return TRUE; - } - return FALSE; -} - - - -#ifdef SUPPORT_SCRN_DIRECT3D -// ---- - -/** - * @brief Renderer ページ - */ -class ScrOptRendererPage : public CPropPageProc -{ -public: - ScrOptRendererPage(); - virtual ~ScrOptRendererPage(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - -private: - CComboData m_type; //!< 種類 - CComboData m_mode; //!< 補間モード - CWndProc m_chksoftrender; //!< USE DIRECTDRAW SOFTWARE RENDERING - CWndProc m_chkexclusive; //!< USE DIRECT3D FULLSCREEN EXCLUSIVE MODE -}; - -//! 種類 リスト -static const CComboData::Entry s_renderer_type[] = -{ - {MAKEINTRESOURCE(IDS_RENDERER_DIRECTDRAW), DRAWTYPE_DIRECTDRAW_HW}, - {MAKEINTRESOURCE(IDS_RENDERER_DIRECT3D), DRAWTYPE_DIRECT3D}, -}; -//! 補間モード リスト -static const CComboData::Entry s_renderer_mode[] = -{ - {MAKEINTRESOURCE(IDS_RENDERER_IMODE_NN), D3D_IMODE_NEAREST_NEIGHBOR}, - {MAKEINTRESOURCE(IDS_RENDERER_IMODE_LINEAR),D3D_IMODE_BILINEAR}, - {MAKEINTRESOURCE(IDS_RENDERER_IMODE_PIXEL), D3D_IMODE_PIXEL}, - {MAKEINTRESOURCE(IDS_RENDERER_IMODE_PIXEL2),D3D_IMODE_PIXEL2}, - {MAKEINTRESOURCE(IDS_RENDERER_IMODE_PIXEL3),D3D_IMODE_PIXEL3}, -}; - -/** - * コンストラクタ - */ -ScrOptRendererPage::ScrOptRendererPage() - : CPropPageProc(IDD_SCROPT_RENDERER) -{ -} - -/** - * デストラクタ - */ -ScrOptRendererPage::~ScrOptRendererPage() -{ -} - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL ScrOptRendererPage::OnInitDialog() -{ - m_type.SubclassDlgItem(IDC_RENDERER_TYPE, this); - m_type.Add(s_renderer_type, _countof(s_renderer_type)); - m_type.SetCurItemData(np2oscfg.drawtype); - - m_mode.SubclassDlgItem(IDC_RENDERER_IMODE, this); - m_mode.Add(s_renderer_mode, _countof(s_renderer_mode)); - m_mode.SetCurItemData(FSCRNCFG_d3d_imode); - m_mode.EnableWindow(np2oscfg.drawtype==DRAWTYPE_DIRECT3D ? TRUE : FALSE); - - CheckDlgButton(IDC_SOFTWARERENDERING, (np2oscfg.emuddraw) ? BST_CHECKED : BST_UNCHECKED); - - m_chksoftrender.SubclassDlgItem(IDC_SOFTWARERENDERING, this); - m_chksoftrender.SendMessage(BM_SETCHECK , (np2oscfg.emuddraw) ? BST_CHECKED : BST_UNCHECKED , 0); - - m_chkexclusive.SubclassDlgItem(IDC_RENDERER_EXCLUSIVE, this); - m_chkexclusive.SendMessage(BM_SETCHECK , (np2oscfg.d3d_exclusive) ? BST_CHECKED : BST_UNCHECKED , 0); - ::ShowWindow(m_chkexclusive.GetSafeHwnd(), SW_HIDE); - - return TRUE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void ScrOptRendererPage::OnOK() -{ - bool bUpdated = false; - UINT8 cMode = 0; - UINT32 tmp, tmp2; - tmp = m_type.GetCurItemData(np2oscfg.drawtype); - if (tmp != np2oscfg.drawtype) - { - if(tmp==DRAWTYPE_DIRECT3D){ - if(scrnmngD3D_check() != SUCCESS){ - MessageBox(g_hWndMain, _T("Failed to initialize Direct3D."), _T("Direct3D Error"), MB_OK|MB_ICONEXCLAMATION); - tmp = DRAWTYPE_DIRECTDRAW_HW; - } - } - np2oscfg.drawtype = tmp; - resetScreen = 1; - bUpdated = true; - } - tmp = m_mode.GetCurItemData(scrnrescfg.d3d_imode); - tmp2 = m_mode.GetCurItemData(np2oscfg.d3d_imode); - if ((np2oscfg.fsrescfg && (!scrnrescfg.hasfscfg || scrnrescfg.d3d_imode != tmp)) || np2oscfg.d3d_imode != tmp2) - { - if((np2oscfg.fsrescfg && (!scrnrescfg.hasfscfg || scrnrescfg.d3d_imode != tmp)) || (!np2oscfg.fsrescfg && np2oscfg.d3d_imode != tmp2)){ - resetScreen = 1; - } - if(np2oscfg.fsrescfg){ - scrnrescfg.d3d_imode = tmp; - scrnrescfg.hasfscfg = 1; - scrnres_writeini(); - } - np2oscfg.d3d_imode = tmp; - bUpdated = true; - } - cMode = (IsDlgButtonChecked(IDC_RENDERER_EXCLUSIVE) != BST_UNCHECKED); - if (!!cMode == !np2oscfg.d3d_exclusive) - { - np2oscfg.d3d_exclusive = cMode; - scrnmng_destroy(); - scrnmng_create(g_scrnmode); - resetScreen = 1; - bUpdated = true; - } - cMode = (IsDlgButtonChecked(IDC_SOFTWARERENDERING) != BST_UNCHECKED); - if (!!cMode == !np2oscfg.emuddraw) - { - np2oscfg.emuddraw = cMode; - scrnmng_destroy(); - scrnmng_create(g_scrnmode); - resetScreen = 1; - bUpdated = true; - } - if (bUpdated) - { - ::scrndraw_redraw(); - ::sysmng_update(SYS_UPDATEOSCFG); - } -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL ScrOptRendererPage::OnCommand(WPARAM wParam, LPARAM lParam) -{ - if (LOWORD(wParam) == IDC_RENDERER_TYPE) - { - UINT8 drawtype = (UINT8)m_type.GetCurItemData(np2oscfg.drawtype); - m_mode.EnableWindow(drawtype==DRAWTYPE_DIRECT3D ? TRUE : FALSE); - m_chkexclusive.EnableWindow(drawtype==DRAWTYPE_DIRECT3D ? TRUE : FALSE); - m_chksoftrender.EnableWindow((drawtype==DRAWTYPE_DIRECTDRAW_HW || drawtype==DRAWTYPE_DIRECTDRAW_SW) ? TRUE : FALSE); - return TRUE; - } - return FALSE; -} -#endif - - - -// ---- - -/** - * スクリーン設定 - * @param[in] hwndParent 親ウィンドウ - */ -void dialog_scropt(HWND hwndParent) -{ - CPropSheetProc prop(IDS_SCREENOPTION, hwndParent); - - ScrOptVideoPage video; - prop.AddPage(&video); - - ScrOptChipPage chip; - prop.AddPage(&chip); - - ScrOptTimingPage timing; - prop.AddPage(&timing); - - ScrOptFullscreenPage fullscreen; - prop.AddPage(&fullscreen); - -#ifdef SUPPORT_SCRN_DIRECT3D - ScrOptRendererPage renderer; - prop.AddPage(&renderer); -#endif - - prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; - prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); - prop.m_psh.pfnCallback = np2class_propetysheet; - prop.DoModal(); - - ::InvalidateRect(hwndParent, NULL, TRUE); - - // デバイス再作成 - if(resetScreen){ - scrnmng.forcereset = 1; - resetScreen = 0; - } -} +/** + * @file d_screen.cpp + * @brief スクリーン設定ダイアログ + */ + +#include +#include "resource.h" +#include "dialog.h" +#include "c_combodata.h" +#include "c_slidervalue.h" +#include "np2class.h" +#include +#include +#include +#ifdef SUPPORT_SCRN_DIRECT3D +#include "scrnmng_d3d.h" +#endif +#include +#include "misc\PropProc.h" +#include +#include +#include "common\strres.h" +#include "vram\scrndraw.h" +#include "vram\palettes.h" + +static int resetScreen = 0; + +/** + * @brief Video ページ + */ +class ScrOptVideoPage : public CPropPageProc +{ +public: + ScrOptVideoPage(); + virtual ~ScrOptVideoPage(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + CSliderValue m_skiplight; //!< スキップライン +}; + +/** + * コンストラクタ + */ +ScrOptVideoPage::ScrOptVideoPage() + : CPropPageProc(IDD_SCROPT1) +{ +} + +/** + * デストラクタ + */ +ScrOptVideoPage::~ScrOptVideoPage() +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL ScrOptVideoPage::OnInitDialog() +{ + CheckDlgButton(IDC_LCD, (np2cfg.LCD_MODE & 1) ? BST_CHECKED : BST_UNCHECKED); + GetDlgItem(IDC_LCDX).EnableWindow((np2cfg.LCD_MODE & 1) ? TRUE : FALSE); + CheckDlgButton(IDC_LCDX, (np2cfg.LCD_MODE & 2) ? BST_CHECKED : BST_UNCHECKED); + + CheckDlgButton(IDC_SKIPLINE, (np2cfg.skipline) ? BST_CHECKED : BST_UNCHECKED); + + m_skiplight.SubclassDlgItem(IDC_SKIPLIGHT, this); + m_skiplight.SetStaticId(IDC_LIGHTSTR); + m_skiplight.SetRange(0, 255); + m_skiplight.SetPos(np2cfg.skiplight); + return TRUE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void ScrOptVideoPage::OnOK() +{ + bool bUpdated = false; + + const UINT8 cSkipLine = (IsDlgButtonChecked(IDC_SKIPLINE) != BST_UNCHECKED) ? 1 : 0; + if (np2cfg.skipline != cSkipLine) + { + np2cfg.skipline = cSkipLine; + bUpdated = true; + } + const UINT8 cSkipLight = static_cast(m_skiplight.GetPos()); + if (np2cfg.skiplight != cSkipLight) + { + np2cfg.skiplight = cSkipLight; + bUpdated = true; + } + if (bUpdated) + { + ::pal_makeskiptable(); + } + + UINT8 cMode = 0; + if (IsDlgButtonChecked(IDC_LCD) != BST_UNCHECKED) + { + cMode |= 1; + } + if (IsDlgButtonChecked(IDC_LCDX) != BST_UNCHECKED) + { + cMode |= 2; + } + if (np2cfg.LCD_MODE != cMode) + { + np2cfg.LCD_MODE = cMode; + pal_makelcdpal(); + bUpdated = true; + } + if (bUpdated) + { + ::scrndraw_redraw(); + ::sysmng_update(SYS_UPDATECFG); + } +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL ScrOptVideoPage::OnCommand(WPARAM wParam, LPARAM lParam) +{ + if (LOWORD(wParam) == IDC_LCD) + { + const BOOL bEnable = (IsDlgButtonChecked(IDC_LCD) != BST_UNCHECKED) ? TRUE : FALSE; + GetDlgItem(IDC_LCDX).EnableWindow(bEnable); + return TRUE; + } + return FALSE; +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT ScrOptVideoPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + if (nMsg == WM_HSCROLL) + { + switch (::GetDlgCtrlID(reinterpret_cast(lParam))) + { + case IDC_SKIPLIGHT: + m_skiplight.UpdateValue(); + break; + + default: + break; + } + } + return CDlgProc::WindowProc(nMsg, wParam, lParam); +} + + + +// ---- +/** + * @brief Chip ページ + */ +class ScrOptChipPage : public CPropPageProc +{ +public: + ScrOptChipPage(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); +}; + +/** + * コンストラクタ + */ +ScrOptChipPage::ScrOptChipPage() + : CPropPageProc(IDD_SCROPT2) +{ +} + +//! GDC チップ +static const UINT s_gdcchip[4] = {IDC_GRCGNON, IDC_GRCG, IDC_GRCG2, IDC_EGC}; + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL ScrOptChipPage::OnInitDialog() +{ + CheckDlgButton((np2cfg.uPD72020) ? IDC_GDC72020 : IDC_GDC7220, BST_CHECKED); + CheckDlgButton(s_gdcchip[np2cfg.grcg & 3], BST_CHECKED); + CheckDlgButton(IDC_PC980124, (np2cfg.color16) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(IDC_PEGC, (np2cfg.usepegcplane) ? BST_CHECKED : BST_UNCHECKED); + +#if defined(SUPPORT_PC9821) + static const UINT s_disabled[] = + { + IDC_GCBOX, + IDC_GRCGNON, IDC_GRCG, IDC_GRCG2, IDC_EGC, + IDC_PC980124 + }; + for (UINT i = 0; i < _countof(s_disabled); i++) + { + GetDlgItem(s_disabled[i]).EnableWindow(FALSE); + } + CheckDlgButton(s_gdcchip[0], BST_UNCHECKED); + CheckDlgButton(s_gdcchip[1], BST_UNCHECKED); + CheckDlgButton(s_gdcchip[2], BST_UNCHECKED); + CheckDlgButton(s_gdcchip[3], BST_CHECKED); +#else + GetDlgItem(IDC_PEGC).EnableWindow(FALSE); + CheckDlgButton(IDC_PEGC, BST_UNCHECKED); +#endif // defined(SUPPORT_PC9821) + + return TRUE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void ScrOptChipPage::OnOK() +{ + bool bUpdated = false; + + const UINT8 cMode = (IsDlgButtonChecked(IDC_GDC72020) != BST_UNCHECKED) ? 1 : 0; + if (np2cfg.uPD72020 != cMode) + { + np2cfg.uPD72020 = cMode; + bUpdated = true; + gdc_restorekacmode(); + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + } + + for (UINT i = 0; i < _countof(s_gdcchip); i++) + { + if (IsDlgButtonChecked(s_gdcchip[i]) != BST_UNCHECKED) + { + const UINT8 cType = static_cast(i); + if (np2cfg.grcg != cType) + { + np2cfg.grcg = cType; + bUpdated = true; + gdcs.grphdisp |= GDCSCRN_ALLDRAW2; + } + break; + } + } + + const UINT8 cColor16 = (IsDlgButtonChecked(IDC_PC980124) != BST_UNCHECKED) ? 1 : 0; + if (np2cfg.color16 != cColor16) + { + np2cfg.color16 = cColor16; + bUpdated = true; + } + + const UINT8 cPEGC = (IsDlgButtonChecked(IDC_PEGC) != BST_UNCHECKED) ? 1 : 0; + if (np2cfg.usepegcplane != cPEGC) + { + np2cfg.usepegcplane = cPEGC; + bUpdated = true; + } + + if (bUpdated) + { + ::sysmng_update(SYS_UPDATECFG); + } +} + + + +// ---- + +/** + * @brief Timing ページ + */ +class ScrOptTimingPage : public CPropPageProc +{ +public: + ScrOptTimingPage(); + virtual ~ScrOptTimingPage(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + CSliderValue m_tram; //!< TRAM + CSliderValue m_vram; //!< VRAM + CSliderValue m_grcg; //!< GRCG + CSliderValue m_raster; //!< ラスタ +}; + +/** + * コンストラクタ + */ +ScrOptTimingPage::ScrOptTimingPage() + : CPropPageProc(IDD_SCROPT3) +{ +} + +/** + * デストラクタ + */ +ScrOptTimingPage::~ScrOptTimingPage() +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL ScrOptTimingPage::OnInitDialog() +{ + m_tram.SubclassDlgItem(IDC_TRAMWAIT, this); + m_tram.SetStaticId(IDC_TRAMSTR); + m_tram.SetRange(0, 32); + m_tram.SetPos(np2cfg.wait[0]); + + m_vram.SubclassDlgItem(IDC_VRAMWAIT, this); + m_vram.SetStaticId(IDC_VRAMSTR); + m_vram.SetRange(0, 32); + m_vram.SetPos(np2cfg.wait[2]); + + m_grcg.SubclassDlgItem(IDC_GRCGWAIT, this); + m_grcg.SetStaticId(IDC_GRCGSTR); + m_grcg.SetRange(0, 32); + m_grcg.SetPos(np2cfg.wait[4]); + + m_raster.SubclassDlgItem(IDC_REALPAL, this); + m_raster.SetStaticId(IDC_REALPALSTR); + m_raster.SetRange(-32, 32); + m_raster.SetPos(np2cfg.realpal - 32); + + return TRUE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void ScrOptTimingPage::OnOK() +{ + bool bUpdated = false; + + UINT8 sWait[6]; + ZeroMemory(sWait, sizeof(sWait)); + sWait[0] = static_cast(m_tram.GetPos()); + sWait[2] = static_cast(m_vram.GetPos()); + sWait[4] = static_cast(m_grcg.GetPos()); + + sWait[1] = (sWait[0]) ? 1 : 0; + sWait[3] = (sWait[2]) ? 1 : 0; + sWait[5] = (sWait[4]) ? 1 : 0; + + for (UINT i = 0; i < 6; i++) + { + if (np2cfg.wait[i] != sWait[i]) + { + np2cfg.wait[i] = sWait[i]; + bUpdated = true; + } + } + + const UINT8 cRealPal = static_cast(m_raster.GetPos() + 32); + if (np2cfg.realpal != cRealPal) + { + np2cfg.realpal = cRealPal; + bUpdated = true; + } + + if (bUpdated) + { + ::sysmng_update(SYS_UPDATECFG); + } +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT ScrOptTimingPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + if (nMsg == WM_HSCROLL) + { + switch (::GetDlgCtrlID(reinterpret_cast(lParam))) + { + case IDC_TRAMWAIT: + m_tram.UpdateValue(); + break; + + case IDC_VRAMWAIT: + m_vram.UpdateValue(); + break; + + case IDC_GRCGWAIT: + m_grcg.UpdateValue(); + break; + + case IDC_REALPAL: + m_raster.UpdateValue(); + break; + + default: + break; + } + } + return CDlgProc::WindowProc(nMsg, wParam, lParam); +} + + + +// ---- + +/** + * @brief Fullscreen ページ + */ +class ScrOptFullscreenPage : public CPropPageProc +{ +public: + ScrOptFullscreenPage(); + virtual ~ScrOptFullscreenPage(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + +private: + CComboData m_zoom; //!< ズーム +}; + +//! ズーム リスト +static const CComboData::Entry s_zoom[] = +{ + {MAKEINTRESOURCE(IDS_ZOOM_NONE), FSCRNMOD_NORESIZE}, + {MAKEINTRESOURCE(IDS_ZOOM_FIXEDASPECT), FSCRNMOD_ASPECTFIX8}, + {MAKEINTRESOURCE(IDS_ZOOM_ADJUSTASPECT), FSCRNMOD_ASPECTFIX}, + {MAKEINTRESOURCE(IDS_ZOOM_FULL), FSCRNMOD_LARGE}, + {MAKEINTRESOURCE(IDS_ZOOM_INTMULTIPLE), FSCRNMOD_INTMULTIPLE}, +}; + +/** + * コンストラクタ + */ +ScrOptFullscreenPage::ScrOptFullscreenPage() + : CPropPageProc(IDD_SCROPT_FULLSCREEN) +{ +} + +/** + * デストラクタ + */ +ScrOptFullscreenPage::~ScrOptFullscreenPage() +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL ScrOptFullscreenPage::OnInitDialog() +{ + UINT8 c = FSCRNCFG_fscrnmod; +#if defined(SUPPORT_MULTITHREAD) + if(np2_multithread_Enabled()){ + CWndBase wndTemp; + wndTemp = GetDlgItem(IDC_FULLSCREEN_SAMEBPP); + if(wndTemp){ + wndTemp.EnableWindow(FALSE); + } + wndTemp = GetDlgItem(IDC_FULLSCREEN_SAMERES); + if(wndTemp){ + wndTemp.EnableWindow(FALSE); + } + c |= FSCRNMOD_SAMEBPP | FSCRNMOD_SAMERES; + } +#endif + + CheckDlgButton(IDC_FULLSCREEN_SAMEBPP, (c & FSCRNMOD_SAMEBPP) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(IDC_FULLSCREEN_SAMERES, (c & FSCRNMOD_SAMERES) ? BST_CHECKED : BST_UNCHECKED); + + m_zoom.SubclassDlgItem(IDC_FULLSCREEN_ZOOM, this); + m_zoom.Add(s_zoom, _countof(s_zoom)); + m_zoom.SetCurItemData(c & FSCRNMOD_ASPECTMASK); + m_zoom.EnableWindow((c & FSCRNMOD_SAMERES) ? TRUE : FALSE); + + return TRUE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void ScrOptFullscreenPage::OnOK() +{ + UINT8 c = 0; + UINT8 c2 = 0; + if (IsDlgButtonChecked(IDC_FULLSCREEN_SAMEBPP) != BST_UNCHECKED) + { + c |= FSCRNMOD_SAMEBPP; + } + if (IsDlgButtonChecked(IDC_FULLSCREEN_SAMERES) != BST_UNCHECKED) + { + c |= FSCRNMOD_SAMERES; + } + c2 = c; + c |= m_zoom.GetCurItemData(FSCRNCFG_fscrnmod & FSCRNMOD_ASPECTMASK); + c2 |= m_zoom.GetCurItemData(np2oscfg.fscrnmod & FSCRNMOD_ASPECTMASK); + if ((np2oscfg.fsrescfg && (!scrnrescfg.hasfscfg || scrnrescfg.fscrnmod != c)) || np2oscfg.fscrnmod != c2) + { + if((np2oscfg.fsrescfg && (!scrnrescfg.hasfscfg || scrnrescfg.fscrnmod != c)) || (!np2oscfg.fsrescfg && np2oscfg.fscrnmod != c2)){ + resetScreen = 1; + } + if(np2oscfg.fsrescfg){ + scrnrescfg.fscrnmod = c; + scrnrescfg.hasfscfg = 1; + scrnres_writeini(); + } + np2oscfg.fscrnmod = c; + ::sysmng_update(SYS_UPDATEOSCFG); + } +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL ScrOptFullscreenPage::OnCommand(WPARAM wParam, LPARAM lParam) +{ + if (LOWORD(wParam) == IDC_FULLSCREEN_SAMERES) + { + m_zoom.EnableWindow((IsDlgButtonChecked(IDC_FULLSCREEN_SAMERES) != BST_UNCHECKED) ? TRUE : FALSE); + return TRUE; + } + return FALSE; +} + + + +#ifdef SUPPORT_SCRN_DIRECT3D +// ---- + +/** + * @brief Renderer ページ + */ +class ScrOptRendererPage : public CPropPageProc +{ +public: + ScrOptRendererPage(); + virtual ~ScrOptRendererPage(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + +private: + CComboData m_type; //!< 種類 + CComboData m_mode; //!< 補間モード + CWndProc m_chksoftrender; //!< USE DIRECTDRAW SOFTWARE RENDERING + CWndProc m_chkexclusive; //!< USE DIRECT3D FULLSCREEN EXCLUSIVE MODE +}; + +//! 種類 リスト +static const CComboData::Entry s_renderer_type[] = +{ + {MAKEINTRESOURCE(IDS_RENDERER_DIRECTDRAW), DRAWTYPE_DIRECTDRAW_HW}, + {MAKEINTRESOURCE(IDS_RENDERER_DIRECT3D), DRAWTYPE_DIRECT3D}, +}; +//! 補間モード リスト +static const CComboData::Entry s_renderer_mode[] = +{ + {MAKEINTRESOURCE(IDS_RENDERER_IMODE_NN), D3D_IMODE_NEAREST_NEIGHBOR}, + {MAKEINTRESOURCE(IDS_RENDERER_IMODE_LINEAR),D3D_IMODE_BILINEAR}, + {MAKEINTRESOURCE(IDS_RENDERER_IMODE_PIXEL), D3D_IMODE_PIXEL}, + {MAKEINTRESOURCE(IDS_RENDERER_IMODE_PIXEL2),D3D_IMODE_PIXEL2}, + {MAKEINTRESOURCE(IDS_RENDERER_IMODE_PIXEL3),D3D_IMODE_PIXEL3}, +}; + +/** + * コンストラクタ + */ +ScrOptRendererPage::ScrOptRendererPage() + : CPropPageProc(IDD_SCROPT_RENDERER) +{ +} + +/** + * デストラクタ + */ +ScrOptRendererPage::~ScrOptRendererPage() +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL ScrOptRendererPage::OnInitDialog() +{ + m_type.SubclassDlgItem(IDC_RENDERER_TYPE, this); + m_type.Add(s_renderer_type, _countof(s_renderer_type)); + m_type.SetCurItemData(np2oscfg.drawtype); + + m_mode.SubclassDlgItem(IDC_RENDERER_IMODE, this); + m_mode.Add(s_renderer_mode, _countof(s_renderer_mode)); + m_mode.SetCurItemData(FSCRNCFG_d3d_imode); + m_mode.EnableWindow(np2oscfg.drawtype==DRAWTYPE_DIRECT3D ? TRUE : FALSE); + + CheckDlgButton(IDC_SOFTWARERENDERING, (np2oscfg.emuddraw) ? BST_CHECKED : BST_UNCHECKED); + + m_chksoftrender.SubclassDlgItem(IDC_SOFTWARERENDERING, this); + m_chksoftrender.SendMessage(BM_SETCHECK , (np2oscfg.emuddraw) ? BST_CHECKED : BST_UNCHECKED , 0); + + m_chkexclusive.SubclassDlgItem(IDC_RENDERER_EXCLUSIVE, this); + m_chkexclusive.SendMessage(BM_SETCHECK , (np2oscfg.d3d_exclusive) ? BST_CHECKED : BST_UNCHECKED , 0); + ::ShowWindow(m_chkexclusive.GetSafeHwnd(), SW_HIDE); + + return TRUE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void ScrOptRendererPage::OnOK() +{ + bool bUpdated = false; + UINT8 cMode = 0; + UINT32 tmp, tmp2; + tmp = m_type.GetCurItemData(np2oscfg.drawtype); + if (tmp != np2oscfg.drawtype) + { + if(tmp==DRAWTYPE_DIRECT3D){ + if(scrnmngD3D_check() != SUCCESS){ + MessageBox(g_hWndMain, _T("Failed to initialize Direct3D."), _T("Direct3D Error"), MB_OK|MB_ICONEXCLAMATION); + tmp = DRAWTYPE_DIRECTDRAW_HW; + } + } + np2oscfg.drawtype = tmp; + resetScreen = 1; + bUpdated = true; + } + tmp = m_mode.GetCurItemData(scrnrescfg.d3d_imode); + tmp2 = m_mode.GetCurItemData(np2oscfg.d3d_imode); + if ((np2oscfg.fsrescfg && (!scrnrescfg.hasfscfg || scrnrescfg.d3d_imode != tmp)) || np2oscfg.d3d_imode != tmp2) + { + if((np2oscfg.fsrescfg && (!scrnrescfg.hasfscfg || scrnrescfg.d3d_imode != tmp)) || (!np2oscfg.fsrescfg && np2oscfg.d3d_imode != tmp2)){ + resetScreen = 1; + } + if(np2oscfg.fsrescfg){ + scrnrescfg.d3d_imode = tmp; + scrnrescfg.hasfscfg = 1; + scrnres_writeini(); + } + np2oscfg.d3d_imode = tmp; + bUpdated = true; + } + cMode = (IsDlgButtonChecked(IDC_RENDERER_EXCLUSIVE) != BST_UNCHECKED); + if (!!cMode == !np2oscfg.d3d_exclusive) + { + np2oscfg.d3d_exclusive = cMode; + scrnmng_destroy(); + scrnmng_create(g_scrnmode); + resetScreen = 1; + bUpdated = true; + } + cMode = (IsDlgButtonChecked(IDC_SOFTWARERENDERING) != BST_UNCHECKED); + if (!!cMode == !np2oscfg.emuddraw) + { + np2oscfg.emuddraw = cMode; + scrnmng_destroy(); + scrnmng_create(g_scrnmode); + resetScreen = 1; + bUpdated = true; + } + if (bUpdated) + { + ::scrndraw_redraw(); + ::sysmng_update(SYS_UPDATEOSCFG); + } +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL ScrOptRendererPage::OnCommand(WPARAM wParam, LPARAM lParam) +{ + if (LOWORD(wParam) == IDC_RENDERER_TYPE) + { + UINT8 drawtype = (UINT8)m_type.GetCurItemData(np2oscfg.drawtype); + m_mode.EnableWindow(drawtype==DRAWTYPE_DIRECT3D ? TRUE : FALSE); + m_chkexclusive.EnableWindow(drawtype==DRAWTYPE_DIRECT3D ? TRUE : FALSE); + m_chksoftrender.EnableWindow((drawtype==DRAWTYPE_DIRECTDRAW_HW || drawtype==DRAWTYPE_DIRECTDRAW_SW) ? TRUE : FALSE); + return TRUE; + } + return FALSE; +} +#endif + + + +// ---- + +/** + * スクリーン設定 + * @param[in] hwndParent 親ウィンドウ + */ +void dialog_scropt(HWND hwndParent) +{ + CPropSheetProc prop(IDS_SCREENOPTION, hwndParent); + + ScrOptVideoPage video; + prop.AddPage(&video); + + ScrOptChipPage chip; + prop.AddPage(&chip); + + ScrOptTimingPage timing; + prop.AddPage(&timing); + + ScrOptFullscreenPage fullscreen; + prop.AddPage(&fullscreen); + +#ifdef SUPPORT_SCRN_DIRECT3D + ScrOptRendererPage renderer; + prop.AddPage(&renderer); +#endif + + prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; + prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); + prop.m_psh.pfnCallback = np2class_propetysheet; + prop.DoModal(); + + ::InvalidateRect(hwndParent, NULL, TRUE); + + // デバイス再作成 + if(resetScreen){ + scrnmng.forcereset = 1; + resetScreen = 0; + } +} diff --git a/windows/dialog/d_serial.cpp b/windows/dialog/d_serial.cpp index ae0a3e9f..5ec4b3dd 100644 --- a/windows/dialog/d_serial.cpp +++ b/windows/dialog/d_serial.cpp @@ -1,854 +1,854 @@ -/** - * @file d_serial.cpp - * @brief Serial configure dialog procedure - */ - -#include -#include "resource.h" -#include "dialog.h" -#include "c_combodata.h" -#include "c_dipsw.h" -#include "c_midi.h" -#include "np2class.h" -#include "commng\cmserial.h" -#include -#include -#include -#include "misc\PropProc.h" -#include -#include -#include "cbus\pc9861k.h" -#include "common\strres.h" -#include "generic\dipswbmp.h" - -#ifdef __cplusplus -extern "C" -{ -#endif -extern COMMNG cm_rs232c; -extern COMMNG cm_pc9861ch1; -extern COMMNG cm_pc9861ch2; -#ifdef __cplusplus -} -#endif - -/** - * @brief COM ݒ - */ -class SerialOptComPage : public CPropPageProc -{ -public: - SerialOptComPage(UINT nCaption, COMMNG cm, COMCFG& cfg); - virtual ~SerialOptComPage(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - -private: - COMMNG m_cm; //!< p^ - COMCFG& m_cfg; //!< RtBO - UINT8 m_pentabfa; //!< y^uAXyNgŒ - CWndProc m_chkpentabfa; //!< Pen tablet fixed aspect mode - CWndProc m_chkfixedspeed; //!< Fixed speed mode - CWndProc m_chkDSRcheck; //!< Hardware DSR check mode - CComboData m_port; //!< Port - CComboData m_speed; //!< Speed - CComboData m_chars; //!< Chars - CComboData m_parity; //!< Parity - CComboData m_sbit; //!< Stop bits - CComboMidiDevice m_midiout; //!< MIDI OUT - CComboMidiModule m_module; //!< MIDI Module - CEditMimpiFile m_mimpifile; //!< MIMPI - CWndProc m_pipename; //!< Pipe name - CWndProc m_pipeserv; //!< Pipe server - void UpdateControls(); -}; - -//! |[g -static const CComboData::Entry s_port[] = -{ - {MAKEINTRESOURCE(IDS_NONCONNECT), COMPORT_NONE}, - {MAKEINTRESOURCE(IDS_COM1), COMPORT_COM1}, - {MAKEINTRESOURCE(IDS_COM2), COMPORT_COM2}, - {MAKEINTRESOURCE(IDS_COM3), COMPORT_COM3}, - {MAKEINTRESOURCE(IDS_COM4), COMPORT_COM4}, - {MAKEINTRESOURCE(IDS_MIDI), COMPORT_MIDI}, -#if defined(SUPPORT_WACOM_TABLET) - {MAKEINTRESOURCE(IDS_TABLET), COMPORT_TABLET}, -#endif -#if defined(SUPPORT_NAMED_PIPE) - {MAKEINTRESOURCE(IDS_PIPE), COMPORT_PIPE}, -#endif -}; - -//! LN^ TCY -static const CComboData::Value s_chars[] = -{ - {5, 0x00}, - {6, 0x04}, - {7, 0x08}, - {8, 0x0c}, -}; - -//! peB -static const CComboData::Entry s_parity[] = -{ - {MAKEINTRESOURCE(IDS_PARITY_NONE), 0x00}, - {MAKEINTRESOURCE(IDS_PARITY_ODD), 0x20}, - {MAKEINTRESOURCE(IDS_PARITY_EVEN), 0x30}, -}; - -//! Xgbv rbg -static const CComboData::Entry s_sbit[] = -{ - {MAKEINTRESOURCE(IDS_1), 0x40}, - {MAKEINTRESOURCE(IDS_1HALF), 0x80}, - {MAKEINTRESOURCE(IDS_2), 0xc0}, -}; - -/** - * RXgN^ - * @param[in] nCaption LvV ID - * @param[in] cm p[^ - * @param[in] cfg RtBO - */ -SerialOptComPage::SerialOptComPage(UINT nCaption, COMMNG cm, COMCFG& cfg) - : CPropPageProc(IDD_SERIAL1, nCaption) - , m_cm(cm) - , m_cfg(cfg) -{ -} - -/** - * fXgN^ - */ -SerialOptComPage::~SerialOptComPage() -{ -} - -/** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ - */ -BOOL SerialOptComPage::OnInitDialog() -{ - m_port.SubclassDlgItem(IDC_COM1PORT, this); - m_port.Add(s_port, _countof(s_port)); - m_port.SetCurItemData(m_cfg.port); - - m_speed.SubclassDlgItem(IDC_COM1SPEED, this); - m_speed.Add(cmserial_speed, _countof(cmserial_speed)); - m_speed.SetCurItemData(m_cfg.speed); - - m_chars.SubclassDlgItem(IDC_COM1CHARSIZE, this); - m_chars.Add(s_chars, _countof(s_chars)); - m_chars.SetCurItemData(m_cfg.param & 0x0c); - - m_parity.SubclassDlgItem(IDC_COM1PARITY, this); - m_parity.Add(s_parity, _countof(s_parity)); - const UINT8 cParity = m_cfg.param & 0x30; - m_parity.SetCurItemData((cParity & 0x20) ? cParity : 0); - - m_sbit.SubclassDlgItem(IDC_COM1STOPBIT, this); - m_sbit.Add(s_sbit, _countof(s_sbit)); - const UINT8 cSBit = m_cfg.param & 0xc0; - m_sbit.SetCurItemData((cSBit) ? cSBit : 0x40); - - m_midiout.SubclassDlgItem(IDC_COM1MMAP, this); - m_midiout.EnumerateMidiOut(); - m_midiout.SetCurString(m_cfg.mout); - - m_module.SubclassDlgItem(IDC_COM1MMDL, this); - m_module.SetWindowText(m_cfg.mdl); - CheckDlgButton(IDC_COM1DEFE, (m_cfg.def_en) ? BST_CHECKED : BST_UNCHECKED); - - m_mimpifile.SubclassDlgItem(IDC_COM1DEFF, this); - m_mimpifile.SetWindowText(m_cfg.def); - -#if defined(SUPPORT_WACOM_TABLET) - m_pentabfa = np2oscfg.pentabfa; -#else - m_pentabfa = 0; -#endif - m_chkpentabfa.SubclassDlgItem(IDC_COM1PENTABFA, this); - if(m_pentabfa) - m_chkpentabfa.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkpentabfa.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_chkfixedspeed.SubclassDlgItem(IDC_COM1FSPEED, this); - if(m_cm != cm_rs232c){ - m_chkfixedspeed.EnableWindow(FALSE); - m_chkfixedspeed.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - }else{ - m_chkfixedspeed.SendMessage(BM_SETCHECK , m_cfg.fixedspeed ? BST_CHECKED : BST_UNCHECKED , 0); - } - - m_chkDSRcheck.SubclassDlgItem(IDC_COM1DSRCHECK, this); - if(m_cm != cm_rs232c){ - m_chkDSRcheck.EnableWindow(FALSE); - m_chkDSRcheck.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - }else{ - m_chkDSRcheck.SendMessage(BM_SETCHECK , m_cfg.DSRcheck ? BST_CHECKED : BST_UNCHECKED , 0); - } - -#if defined(SUPPORT_NAMED_PIPE) - m_pipename.SubclassDlgItem(IDC_COM1PIPENAME, this); - m_pipename.SetWindowText(m_cfg.pipename); - m_pipeserv.SubclassDlgItem(IDC_COM1PIPESERV, this); - m_pipeserv.SetWindowText(m_cfg.pipeserv); - { - TCHAR pipecmd[MAX_PATH*3]; - _stprintf(pipecmd, _T("\\\\%s\\pipe\\%s"), m_cfg.pipeserv, m_cfg.pipename); - SetDlgItemText(IDC_COM1STR32, pipecmd); - } -#endif - - UpdateControls(); - - m_port.SetFocus(); - return FALSE; -} - -/** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ - */ -void SerialOptComPage::OnOK() -{ - UINT nUpdated = 0; - - const UINT8 cPort = static_cast(m_port.GetCurItemData(m_cfg.port)); - if (m_cfg.port != cPort) - { - m_cfg.port = cPort; - nUpdated |= SYS_UPDATEOSCFG | SYS_UPDATESERIAL1; - } - - const UINT32 nSpeed = m_speed.GetCurItemData(m_cfg.speed); - if (m_cfg.speed != nSpeed) - { - m_cfg.speed = nSpeed; - nUpdated |= SYS_UPDATEOSCFG | SYS_UPDATESERIAL1; - } - - const UINT8 cFSpeedEnable = (IsDlgButtonChecked(IDC_COM1FSPEED) != BST_UNCHECKED) ? 1 : 0; - if (m_cfg.fixedspeed != cFSpeedEnable) - { - m_cfg.fixedspeed = cFSpeedEnable; - nUpdated |= SYS_UPDATEOSCFG; - } - - const UINT8 cDSRcheckEnable = (IsDlgButtonChecked(IDC_COM1DSRCHECK) != BST_UNCHECKED) ? 1 : 0; - if (m_cfg.DSRcheck != cDSRcheckEnable) - { - m_cfg.DSRcheck = cDSRcheckEnable; - nUpdated |= SYS_UPDATEOSCFG; - } - - UINT8 cParam = 0; - cParam |= m_chars.GetCurItemData(m_cfg.param & 0x0c); - cParam |= m_parity.GetCurItemData(m_cfg.param & 0x30); - cParam |= m_sbit.GetCurItemData(m_cfg.param & 0xc3); - if (m_cfg.param != cParam) - { - m_cfg.param = cParam; - nUpdated |= SYS_UPDATEOSCFG | SYS_UPDATESERIAL1; - } - - TCHAR mmap[MAXPNAMELEN]; - GetDlgItemText(IDC_COM1MMAP, mmap, _countof(mmap)); - if (milstr_cmp(m_cfg.mout, mmap)) - { - milstr_ncpy(m_cfg.mout, mmap, _countof(m_cfg.mout)); - nUpdated |= SYS_UPDATEOSCFG | SYS_UPDATESERIAL1; - } - - TCHAR mmdl[64]; - GetDlgItemText(IDC_COM1MMDL, mmdl, _countof(mmdl)); - if (milstr_cmp(m_cfg.mdl, mmdl)) - { - milstr_ncpy(m_cfg.mdl, mmdl, _countof(m_cfg.mdl)); - nUpdated |= SYS_UPDATEOSCFG | SYS_UPDATESERIAL1; - } - - const UINT8 cDefEnable = (IsDlgButtonChecked(IDC_COM1DEFE) != BST_UNCHECKED) ? 1 : 0; - if (m_cfg.def_en != cDefEnable) - { - m_cfg.def_en = cDefEnable; - if (m_cm) - { - m_cm->msg(m_cm, COMMSG_MIMPIDEFEN, cDefEnable); - } - nUpdated |= SYS_UPDATEOSCFG; - } - - TCHAR mdef[MAX_PATH]; - GetDlgItemText(IDC_COM1DEFF, mdef, _countof(mdef)); - if (milstr_cmp(m_cfg.def, mdef)) - { - milstr_ncpy(m_cfg.def, mdef, _countof(m_cfg.def)); - if (m_cm) - { - m_cm->msg(m_cm, COMMSG_MIMPIDEFFILE, reinterpret_cast(mdef)); - } - nUpdated |= SYS_UPDATEOSCFG; - } - -#if defined(SUPPORT_WACOM_TABLET) - if (np2oscfg.pentabfa != m_pentabfa) - { - np2oscfg.pentabfa = m_pentabfa; - nUpdated |= SYS_UPDATEOSCFG; - } -#endif - -#if defined(SUPPORT_NAMED_PIPE) - TCHAR pipename[MAX_PATH]; - TCHAR pipeserv[MAX_PATH]; - GetDlgItemText(IDC_COM1PIPENAME, pipename, _countof(pipename)); - GetDlgItemText(IDC_COM1PIPESERV, pipeserv, _countof(pipeserv)); - if (milstr_cmp(m_cfg.pipename, pipename)) - { - milstr_ncpy(m_cfg.pipename, pipename, _countof(m_cfg.pipename)); - nUpdated |= SYS_UPDATEOSCFG; - } - if (milstr_cmp(m_cfg.pipeserv, pipeserv)) - { - milstr_ncpy(m_cfg.pipeserv, pipeserv, _countof(m_cfg.pipeserv)); - nUpdated |= SYS_UPDATEOSCFG; - } -#endif - - sysmng_update(nUpdated); -} - -/** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W - */ -BOOL SerialOptComPage::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_COM1PORT: - UpdateControls(); - return TRUE; - - case IDC_COM1DEFB: - m_mimpifile.Browse(); - return TRUE; - - case IDC_COM1PENTABFA: - m_pentabfa = (m_chkpentabfa.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - -#if defined(SUPPORT_NAMED_PIPE) - case IDC_COM1PIPENAME: - case IDC_COM1PIPESERV: - { - TCHAR pipename[MAX_PATH]; - TCHAR pipeserv[MAX_PATH]; - TCHAR pipecmd[MAX_PATH*3]; - GetDlgItemText(IDC_COM1PIPENAME, pipename, _countof(pipename)); - GetDlgItemText(IDC_COM1PIPESERV, pipeserv, _countof(pipeserv)); - _stprintf(pipecmd, _T("\\\\%s\\pipe\\%s"), pipeserv, pipename); - SetDlgItemText(IDC_COM1STR32, pipecmd); - return TRUE; - } -#endif - } - return FALSE; -} - -/** - * Rg[XV - */ -void SerialOptComPage::UpdateControls() -{ - const UINT nPort = m_port.GetCurItemData(m_cfg.port); - const bool bSerialShow = ((nPort >= COMPORT_COM1) && (nPort <= COMPORT_COM4)); - const bool bMidiShow = (nPort == COMPORT_MIDI); -#if defined(SUPPORT_WACOM_TABLET) - const bool bPentabShow = (nPort == COMPORT_TABLET); -#else - const bool bPentabShow = false; -#endif -#if defined(SUPPORT_NAMED_PIPE) - const bool bPipeShow = (nPort == COMPORT_PIPE); -#else - const bool bPipeShow = false; -#endif - - // Physical serial port - static const UINT serial[] = - { - IDC_COM1SPEED, IDC_COM1CHARSIZE, IDC_COM1PARITY, IDC_COM1STOPBIT, - IDC_COM1STR00, IDC_COM1STR01, IDC_COM1STR02, IDC_COM1STR03, - IDC_COM1STR04, IDC_COM1STR05, IDC_COM1STR06, IDC_COM1STR07 - }; - for (UINT i = 0; i < _countof(serial); i++) - { - CWndBase wnd = GetDlgItem(serial[i]); - wnd.EnableWindow(bSerialShow ? TRUE : FALSE); - wnd.ShowWindow(bSerialShow ? SW_SHOW : SW_HIDE); - } - if(m_cm != cm_rs232c){ - m_chkfixedspeed.EnableWindow(FALSE); - }else{ - m_chkfixedspeed.EnableWindow(bSerialShow ? TRUE : FALSE); - } - m_chkfixedspeed.ShowWindow(bSerialShow ? SW_SHOW : SW_HIDE); - m_chkDSRcheck.ShowWindow(bSerialShow ? SW_SHOW : SW_HIDE); - - // Serial MIDI emulation - static const UINT midi[] = - { - IDC_COM1MMAP, IDC_COM1MMDL, IDC_COM1DEFE, IDC_COM1DEFF, IDC_COM1DEFB, - IDC_COM1STR10, IDC_COM1STR11, IDC_COM1STR12 - }; - for (UINT i = 0; i < _countof(midi); i++) - { - CWndBase wnd = GetDlgItem(midi[i]); - wnd.EnableWindow(bMidiShow ? TRUE : FALSE); - wnd.ShowWindow(bMidiShow ? SW_SHOW : SW_HIDE); - } - - // Serial pen tablet emulation - m_chkpentabfa.EnableWindow(bPentabShow ? TRUE : FALSE); - m_chkpentabfa.ShowWindow(bPentabShow ? SW_SHOW : SW_HIDE); - - // Named-pipe - static const UINT pipe[] = - { - IDC_COM1PIPENAME, IDC_COM1PIPESERV, - IDC_COM1STR30, IDC_COM1STR31, IDC_COM1STR32 - }; - for (UINT i = 0; i < _countof(pipe); i++) - { - CWndBase wnd = GetDlgItem(pipe[i]); - wnd.EnableWindow(bPipeShow ? TRUE : FALSE); - wnd.ShowWindow(bPipeShow ? SW_SHOW : SW_HIDE); - } -} - - - -// ---- - -/** - * @brief 61 y[W - */ -class SerialOpt61Page : public CPropPageProc -{ -public: - SerialOpt61Page(); - virtual ~SerialOpt61Page(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - UINT8 m_sw[3]; //!< XCb` - UINT8 m_jmp[6]; //!< Wp - CComboData m_speed[2]; //!< Speed - CComboData m_int[2]; //!< INT - CComboData m_sync[2]; //!< Mode - CStaticDipSw m_dipsw; //!< DIPSW - void Set(const UINT8* sw, const UINT8* jmp); - UINT8 GetMode(UINT nIndex, UINT8 cMode); - void SetMode(UINT nIndex, UINT8 cMode); - void UpdateMode(UINT nIndex, UINT8& cMode); - void OnDipSw(); -}; - -enum -{ - PC9861S1_X = 1, - PC9861S2_X = 10, - PC9861S3_X = 17, - PC9861S_Y = 1, - - PC9861J1_X = 1, - PC9861J2_X = 9, - PC9861J3_X = 17, - PC9861J4_X = 1, - PC9861J5_X = 11, - PC9861J6_X = 19, - PC9861J1_Y = 4, - PC9861J4_Y = 7 -}; - -//! INT1 -static const CComboData::Value s_int1[] = -{ - {0, 0x00}, - {1, 0x02}, - {2, 0x01}, - {3, 0x03}, -}; - -//! INT2 -static const CComboData::Value s_int2[] = -{ - {0, 0x00}, - {4, 0x08}, - {5, 0x04}, - {6, 0x0c}, -}; - -//! @ -static const CComboData::Entry s_sync[] = -{ - {MAKEINTRESOURCE(IDS_SYNC), 0x03}, - {MAKEINTRESOURCE(IDS_ASYNC), 0x00}, - {MAKEINTRESOURCE(IDS_ASYNC16X), 0x01}, - {MAKEINTRESOURCE(IDS_ASYNC64X), 0x02}, -}; - -/** - * RXgN^ - */ -SerialOpt61Page::SerialOpt61Page() - : CPropPageProc(IDD_PC9861A) -{ - ZeroMemory(m_sw, sizeof(m_sw)); - ZeroMemory(m_jmp, sizeof(m_jmp)); -} - -/** - * fXgN^ - */ -SerialOpt61Page::~SerialOpt61Page() -{ -} - -/** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ - */ -BOOL SerialOpt61Page::OnInitDialog() -{ - CheckDlgButton(IDC_PC9861E, (np2cfg.pc9861enable) ? BST_CHECKED : BST_UNCHECKED); - - m_speed[0].SubclassDlgItem(IDC_CH1SPEED, this); - m_speed[0].Add(pc9861k_speed, _countof(pc9861k_speed)); - m_speed[1].SubclassDlgItem(IDC_CH2SPEED, this); - m_speed[1].Add(pc9861k_speed, _countof(pc9861k_speed)); - - m_int[0].SubclassDlgItem(IDC_CH1INT, this); - m_int[0].Add(s_int1, _countof(s_int1)); - m_int[1].SubclassDlgItem(IDC_CH2INT, this); - m_int[1].Add(s_int2, _countof(s_int2)); - - m_sync[0].SubclassDlgItem(IDC_CH1MODE, this); - m_sync[0].Add(s_sync, _countof(s_sync)); - m_sync[1].SubclassDlgItem(IDC_CH2MODE, this); - m_sync[1].Add(s_sync, _countof(s_sync)); - - Set(np2cfg.pc9861sw, np2cfg.pc9861jmp); - - m_dipsw.SubclassDlgItem(IDC_PC9861DIP, this); - - return TRUE; -} - -/** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ - */ -void SerialOpt61Page::OnOK() -{ - bool bUpdated = false; - - const UINT8 cEnabled = (IsDlgButtonChecked(IDC_PC9861E) != BST_UNCHECKED) ? 1 : 0; - if (np2cfg.pc9861enable != cEnabled) - { - np2cfg.pc9861enable = cEnabled; - bUpdated = true; - } - - if (memcmp(np2cfg.pc9861sw, m_sw, 3)) - { - CopyMemory(np2cfg.pc9861sw, m_sw, 3); - bUpdated = true; - } - if (memcmp(np2cfg.pc9861jmp, m_jmp, 6)) - { - CopyMemory(np2cfg.pc9861jmp, m_jmp, 6); - bUpdated = true; - } - - if (bUpdated) - { - ::sysmng_update(SYS_UPDATECFG); - } -} - -/** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W - */ -BOOL SerialOpt61Page::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_CH1SPEED: - case IDC_CH1MODE: - UpdateMode(0, m_sw[0]); - break; - - case IDC_CH2SPEED: - case IDC_CH2MODE: - UpdateMode(1, m_sw[2]); - break; - - case IDC_CH1INT: - case IDC_CH2INT: - { - UINT8 cMode = m_sw[1] & 0xf0; - cMode |= m_int[0].GetCurItemData(m_sw[1] & 0x03); - cMode |= m_int[1].GetCurItemData(m_sw[1] & 0x0c); - if (m_sw[1] != cMode) - { - m_sw[1] = cMode; - m_dipsw.Invalidate(); - } - } - break; - - case IDC_PC9861DIP: - OnDipSw(); - break; - } - return FALSE; -} - -/** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ - */ -LRESULT SerialOpt61Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - switch (nMsg) - { - case WM_DRAWITEM: - if (LOWORD(wParam) == IDC_PC9861DIP) - { - UINT8* pBitmap = dipswbmp_get9861(m_sw, m_jmp); - m_dipsw.Draw((reinterpret_cast(lParam))->hDC, pBitmap); - _MFREE(pBitmap); - } - return FALSE; - } - return CDlgProc::WindowProc(nMsg, wParam, lParam); -} - -/** - * Rg[ݒ - * @param[in] sw ݒl - * @param[in] jmp ݒl - */ -void SerialOpt61Page::Set(const UINT8* sw, const UINT8* jmp) -{ - CopyMemory(m_sw, sw, sizeof(m_sw)); - CopyMemory(m_jmp, jmp, sizeof(m_jmp)); - - SetMode(0, sw[0]); - SetMode(1, sw[2]); - m_int[0].SetCurItemData(sw[1] & 0x03); - m_int[1].SetCurItemData(sw[1] & 0x0c); -} - -/** - * [h𓾂 - * @param[in] nIndex |[g - * @param[in] cMode ftHgl - * @return [h - */ -UINT8 SerialOpt61Page::GetMode(UINT nIndex, UINT8 cMode) -{ - const UINT8 cSync = m_sync[nIndex].GetCurItemData(cMode & 0x03); - - UINT nSpeed = m_speed[nIndex].GetCurSel(); - if (nSpeed > (_countof(pc9861k_speed) - 1)) - { - nSpeed = _countof(pc9861k_speed) - 1; - } - if (cSync & 2) - { - nSpeed += 3; - } - else - { - if (nSpeed) - { - nSpeed--; - } - } - return (((~nSpeed) & 0x0f) << 2) | cSync; -} - -/** - * [hݒ - * @param[in] nIndex |[g - * @param[in] cMode [h - */ -void SerialOpt61Page::SetMode(UINT nIndex, UINT8 cMode) -{ - UINT nSpeed = (((~cMode) >> 2) & 0x0f) + 1; - if (cMode) - { - if (nSpeed > 4) - { - nSpeed -= 4; - } - else - { - nSpeed = 0; - } - } - if (nSpeed > (_countof(pc9861k_speed) - 1)) - { - nSpeed = _countof(pc9861k_speed) - 1; - } - m_speed[nIndex].SetCurSel(nSpeed); - m_sync[nIndex].SetCurItemData(cMode & 0x03); -} - -/** - * XV - * @param[in] nIndex |[g - * @param[out] cMode [h - */ -void SerialOpt61Page::UpdateMode(UINT nIndex, UINT8& cMode) -{ - const UINT8 cValue = GetMode(nIndex, cMode); - if (cMode != cValue) - { - cMode = cValue; - SetMode(nIndex, cMode); - m_dipsw.Invalidate(); - } -} - -/** - * DIPSW ^bv - */ -void SerialOpt61Page::OnDipSw() -{ - RECT rect1; - m_dipsw.GetWindowRect(&rect1); - - RECT rect2; - m_dipsw.GetClientRect(&rect2); - - POINT p; - ::GetCursorPos(&p); - p.x += rect2.left - rect1.left; - p.y += rect2.top - rect1.top; - p.x /= 9; - p.y /= 9; - - UINT8 sw[3]; - UINT8 jmp[6]; - CopyMemory(sw, m_sw, sizeof(sw)); - CopyMemory(jmp, m_jmp, sizeof(jmp)); - - if ((p.y >= 1) && (p.y < 3)) // 1i - { - if ((p.x >= 1) && (p.x < 7)) // S1 - { - sw[0] ^= (1 << (p.x - 1)); - } - else if ((p.x >= 10) && (p.x < 14)) // S2 - { - sw[1] ^= (1 << (p.x - 10)); - } - else if ((p.x >= 17) && (p.x < 23)) // S3 - { - sw[2] ^= (1 << (p.x - 17)); - } - } - else if ((p.y >= 4) && (p.y < 6)) // 2i - { - if ((p.x >= 1) && (p.x < 7)) // J1 - { - jmp[0] ^= (1 << (p.x - 1)); - } - else if ((p.x >= 9) && (p.x < 15)) // J2 - { - jmp[1] ^= (1 << (p.x - 9)); - } - else if ((p.x >= 17) && (p.x < 19)) // J3 - { - jmp[2] = (1 << (p.x - 17)); - } - } - else if ((p.y >= 7) && (p.y < 9)) // 3i - { - if ((p.x >= 1) && (p.x < 9)) // J4 - { - const UINT8 cBit = (1 << (p.x - 1)); - jmp[3] = (jmp[3] != cBit) ? cBit : 0; - } - else if ((p.x >= 11) && (p.x < 17)) // J5 - { - jmp[4] ^= (1 << (p.x - 11)); - } - else if ((p.x >= 19) && (p.x < 25)) // J6 - { - jmp[5] ^= (1 << (p.x - 19)); - } - } - - if ((memcmp(m_sw, sw, sizeof(sw)) != 0) || (memcmp(m_jmp, jmp, sizeof(jmp)) != 0)) - { - Set(sw, jmp); - m_dipsw.Invalidate(); - } -} - - - -// ---- - -/** - * VAݒ - * @param[in] hwndParent eEBhE - */ -void dialog_serial(HWND hwndParent) -{ - CPropSheetProc prop(IDS_SERIALOPTION, hwndParent); - - SerialOptComPage com1(IDS_SERIAL1, cm_rs232c, np2oscfg.com1); - prop.AddPage(&com1); - - SerialOpt61Page pc9861; - prop.AddPage(&pc9861); - - SerialOptComPage com2(IDS_PC9861B, cm_pc9861ch1, np2oscfg.com2); - prop.AddPage(&com2); - - SerialOptComPage com3(IDS_PC9861C, cm_pc9861ch2, np2oscfg.com3); - prop.AddPage(&com3); - - prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; - prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); - prop.m_psh.pfnCallback = np2class_propetysheet; - prop.DoModal(); - - ::InvalidateRect(hwndParent, NULL, TRUE); -} +/** + * @file d_serial.cpp + * @brief Serial configure dialog procedure + */ + +#include +#include "resource.h" +#include "dialog.h" +#include "c_combodata.h" +#include "c_dipsw.h" +#include "c_midi.h" +#include "np2class.h" +#include "commng\cmserial.h" +#include +#include +#include +#include "misc\PropProc.h" +#include +#include +#include "cbus\pc9861k.h" +#include "common\strres.h" +#include "generic\dipswbmp.h" + +#ifdef __cplusplus +extern "C" +{ +#endif +extern COMMNG cm_rs232c; +extern COMMNG cm_pc9861ch1; +extern COMMNG cm_pc9861ch2; +#ifdef __cplusplus +} +#endif + +/** + * @brief COM 設定 + */ +class SerialOptComPage : public CPropPageProc +{ +public: + SerialOptComPage(UINT nCaption, COMMNG cm, COMCFG& cfg); + virtual ~SerialOptComPage(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + +private: + COMMNG m_cm; //!< パラメタ + COMCFG& m_cfg; //!< コンフィグ + UINT8 m_pentabfa; //!< ペンタブアスペクト比固定 + CWndProc m_chkpentabfa; //!< Pen tablet fixed aspect mode + CWndProc m_chkfixedspeed; //!< Fixed speed mode + CWndProc m_chkDSRcheck; //!< Hardware DSR check mode + CComboData m_port; //!< Port + CComboData m_speed; //!< Speed + CComboData m_chars; //!< Chars + CComboData m_parity; //!< Parity + CComboData m_sbit; //!< Stop bits + CComboMidiDevice m_midiout; //!< MIDI OUT + CComboMidiModule m_module; //!< MIDI Module + CEditMimpiFile m_mimpifile; //!< MIMPI + CWndProc m_pipename; //!< Pipe name + CWndProc m_pipeserv; //!< Pipe server + void UpdateControls(); +}; + +//! ポート +static const CComboData::Entry s_port[] = +{ + {MAKEINTRESOURCE(IDS_NONCONNECT), COMPORT_NONE}, + {MAKEINTRESOURCE(IDS_COM1), COMPORT_COM1}, + {MAKEINTRESOURCE(IDS_COM2), COMPORT_COM2}, + {MAKEINTRESOURCE(IDS_COM3), COMPORT_COM3}, + {MAKEINTRESOURCE(IDS_COM4), COMPORT_COM4}, + {MAKEINTRESOURCE(IDS_MIDI), COMPORT_MIDI}, +#if defined(SUPPORT_WACOM_TABLET) + {MAKEINTRESOURCE(IDS_TABLET), COMPORT_TABLET}, +#endif +#if defined(SUPPORT_NAMED_PIPE) + {MAKEINTRESOURCE(IDS_PIPE), COMPORT_PIPE}, +#endif +}; + +//! キャラクタ サイズ +static const CComboData::Value s_chars[] = +{ + {5, 0x00}, + {6, 0x04}, + {7, 0x08}, + {8, 0x0c}, +}; + +//! パリティ +static const CComboData::Entry s_parity[] = +{ + {MAKEINTRESOURCE(IDS_PARITY_NONE), 0x00}, + {MAKEINTRESOURCE(IDS_PARITY_ODD), 0x20}, + {MAKEINTRESOURCE(IDS_PARITY_EVEN), 0x30}, +}; + +//! ストップ ビット +static const CComboData::Entry s_sbit[] = +{ + {MAKEINTRESOURCE(IDS_1), 0x40}, + {MAKEINTRESOURCE(IDS_1HALF), 0x80}, + {MAKEINTRESOURCE(IDS_2), 0xc0}, +}; + +/** + * コンストラクタ + * @param[in] nCaption キャプション ID + * @param[in] cm パラメータ + * @param[in] cfg コンフィグ + */ +SerialOptComPage::SerialOptComPage(UINT nCaption, COMMNG cm, COMCFG& cfg) + : CPropPageProc(IDD_SERIAL1, nCaption) + , m_cm(cm) + , m_cfg(cfg) +{ +} + +/** + * デストラクタ + */ +SerialOptComPage::~SerialOptComPage() +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL SerialOptComPage::OnInitDialog() +{ + m_port.SubclassDlgItem(IDC_COM1PORT, this); + m_port.Add(s_port, _countof(s_port)); + m_port.SetCurItemData(m_cfg.port); + + m_speed.SubclassDlgItem(IDC_COM1SPEED, this); + m_speed.Add(cmserial_speed, _countof(cmserial_speed)); + m_speed.SetCurItemData(m_cfg.speed); + + m_chars.SubclassDlgItem(IDC_COM1CHARSIZE, this); + m_chars.Add(s_chars, _countof(s_chars)); + m_chars.SetCurItemData(m_cfg.param & 0x0c); + + m_parity.SubclassDlgItem(IDC_COM1PARITY, this); + m_parity.Add(s_parity, _countof(s_parity)); + const UINT8 cParity = m_cfg.param & 0x30; + m_parity.SetCurItemData((cParity & 0x20) ? cParity : 0); + + m_sbit.SubclassDlgItem(IDC_COM1STOPBIT, this); + m_sbit.Add(s_sbit, _countof(s_sbit)); + const UINT8 cSBit = m_cfg.param & 0xc0; + m_sbit.SetCurItemData((cSBit) ? cSBit : 0x40); + + m_midiout.SubclassDlgItem(IDC_COM1MMAP, this); + m_midiout.EnumerateMidiOut(); + m_midiout.SetCurString(m_cfg.mout); + + m_module.SubclassDlgItem(IDC_COM1MMDL, this); + m_module.SetWindowText(m_cfg.mdl); + CheckDlgButton(IDC_COM1DEFE, (m_cfg.def_en) ? BST_CHECKED : BST_UNCHECKED); + + m_mimpifile.SubclassDlgItem(IDC_COM1DEFF, this); + m_mimpifile.SetWindowText(m_cfg.def); + +#if defined(SUPPORT_WACOM_TABLET) + m_pentabfa = np2oscfg.pentabfa; +#else + m_pentabfa = 0; +#endif + m_chkpentabfa.SubclassDlgItem(IDC_COM1PENTABFA, this); + if(m_pentabfa) + m_chkpentabfa.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkpentabfa.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_chkfixedspeed.SubclassDlgItem(IDC_COM1FSPEED, this); + if(m_cm != cm_rs232c){ + m_chkfixedspeed.EnableWindow(FALSE); + m_chkfixedspeed.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + }else{ + m_chkfixedspeed.SendMessage(BM_SETCHECK , m_cfg.fixedspeed ? BST_CHECKED : BST_UNCHECKED , 0); + } + + m_chkDSRcheck.SubclassDlgItem(IDC_COM1DSRCHECK, this); + if(m_cm != cm_rs232c){ + m_chkDSRcheck.EnableWindow(FALSE); + m_chkDSRcheck.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + }else{ + m_chkDSRcheck.SendMessage(BM_SETCHECK , m_cfg.DSRcheck ? BST_CHECKED : BST_UNCHECKED , 0); + } + +#if defined(SUPPORT_NAMED_PIPE) + m_pipename.SubclassDlgItem(IDC_COM1PIPENAME, this); + m_pipename.SetWindowText(m_cfg.pipename); + m_pipeserv.SubclassDlgItem(IDC_COM1PIPESERV, this); + m_pipeserv.SetWindowText(m_cfg.pipeserv); + { + TCHAR pipecmd[MAX_PATH*3]; + _stprintf(pipecmd, _T("\\\\%s\\pipe\\%s"), m_cfg.pipeserv, m_cfg.pipename); + SetDlgItemText(IDC_COM1STR32, pipecmd); + } +#endif + + UpdateControls(); + + m_port.SetFocus(); + return FALSE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void SerialOptComPage::OnOK() +{ + UINT nUpdated = 0; + + const UINT8 cPort = static_cast(m_port.GetCurItemData(m_cfg.port)); + if (m_cfg.port != cPort) + { + m_cfg.port = cPort; + nUpdated |= SYS_UPDATEOSCFG | SYS_UPDATESERIAL1; + } + + const UINT32 nSpeed = m_speed.GetCurItemData(m_cfg.speed); + if (m_cfg.speed != nSpeed) + { + m_cfg.speed = nSpeed; + nUpdated |= SYS_UPDATEOSCFG | SYS_UPDATESERIAL1; + } + + const UINT8 cFSpeedEnable = (IsDlgButtonChecked(IDC_COM1FSPEED) != BST_UNCHECKED) ? 1 : 0; + if (m_cfg.fixedspeed != cFSpeedEnable) + { + m_cfg.fixedspeed = cFSpeedEnable; + nUpdated |= SYS_UPDATEOSCFG; + } + + const UINT8 cDSRcheckEnable = (IsDlgButtonChecked(IDC_COM1DSRCHECK) != BST_UNCHECKED) ? 1 : 0; + if (m_cfg.DSRcheck != cDSRcheckEnable) + { + m_cfg.DSRcheck = cDSRcheckEnable; + nUpdated |= SYS_UPDATEOSCFG; + } + + UINT8 cParam = 0; + cParam |= m_chars.GetCurItemData(m_cfg.param & 0x0c); + cParam |= m_parity.GetCurItemData(m_cfg.param & 0x30); + cParam |= m_sbit.GetCurItemData(m_cfg.param & 0xc3); + if (m_cfg.param != cParam) + { + m_cfg.param = cParam; + nUpdated |= SYS_UPDATEOSCFG | SYS_UPDATESERIAL1; + } + + TCHAR mmap[MAXPNAMELEN]; + GetDlgItemText(IDC_COM1MMAP, mmap, _countof(mmap)); + if (milstr_cmp(m_cfg.mout, mmap)) + { + milstr_ncpy(m_cfg.mout, mmap, _countof(m_cfg.mout)); + nUpdated |= SYS_UPDATEOSCFG | SYS_UPDATESERIAL1; + } + + TCHAR mmdl[64]; + GetDlgItemText(IDC_COM1MMDL, mmdl, _countof(mmdl)); + if (milstr_cmp(m_cfg.mdl, mmdl)) + { + milstr_ncpy(m_cfg.mdl, mmdl, _countof(m_cfg.mdl)); + nUpdated |= SYS_UPDATEOSCFG | SYS_UPDATESERIAL1; + } + + const UINT8 cDefEnable = (IsDlgButtonChecked(IDC_COM1DEFE) != BST_UNCHECKED) ? 1 : 0; + if (m_cfg.def_en != cDefEnable) + { + m_cfg.def_en = cDefEnable; + if (m_cm) + { + m_cm->msg(m_cm, COMMSG_MIMPIDEFEN, cDefEnable); + } + nUpdated |= SYS_UPDATEOSCFG; + } + + TCHAR mdef[MAX_PATH]; + GetDlgItemText(IDC_COM1DEFF, mdef, _countof(mdef)); + if (milstr_cmp(m_cfg.def, mdef)) + { + milstr_ncpy(m_cfg.def, mdef, _countof(m_cfg.def)); + if (m_cm) + { + m_cm->msg(m_cm, COMMSG_MIMPIDEFFILE, reinterpret_cast(mdef)); + } + nUpdated |= SYS_UPDATEOSCFG; + } + +#if defined(SUPPORT_WACOM_TABLET) + if (np2oscfg.pentabfa != m_pentabfa) + { + np2oscfg.pentabfa = m_pentabfa; + nUpdated |= SYS_UPDATEOSCFG; + } +#endif + +#if defined(SUPPORT_NAMED_PIPE) + TCHAR pipename[MAX_PATH]; + TCHAR pipeserv[MAX_PATH]; + GetDlgItemText(IDC_COM1PIPENAME, pipename, _countof(pipename)); + GetDlgItemText(IDC_COM1PIPESERV, pipeserv, _countof(pipeserv)); + if (milstr_cmp(m_cfg.pipename, pipename)) + { + milstr_ncpy(m_cfg.pipename, pipename, _countof(m_cfg.pipename)); + nUpdated |= SYS_UPDATEOSCFG; + } + if (milstr_cmp(m_cfg.pipeserv, pipeserv)) + { + milstr_ncpy(m_cfg.pipeserv, pipeserv, _countof(m_cfg.pipeserv)); + nUpdated |= SYS_UPDATEOSCFG; + } +#endif + + sysmng_update(nUpdated); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL SerialOptComPage::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_COM1PORT: + UpdateControls(); + return TRUE; + + case IDC_COM1DEFB: + m_mimpifile.Browse(); + return TRUE; + + case IDC_COM1PENTABFA: + m_pentabfa = (m_chkpentabfa.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + +#if defined(SUPPORT_NAMED_PIPE) + case IDC_COM1PIPENAME: + case IDC_COM1PIPESERV: + { + TCHAR pipename[MAX_PATH]; + TCHAR pipeserv[MAX_PATH]; + TCHAR pipecmd[MAX_PATH*3]; + GetDlgItemText(IDC_COM1PIPENAME, pipename, _countof(pipename)); + GetDlgItemText(IDC_COM1PIPESERV, pipeserv, _countof(pipeserv)); + _stprintf(pipecmd, _T("\\\\%s\\pipe\\%s"), pipeserv, pipename); + SetDlgItemText(IDC_COM1STR32, pipecmd); + return TRUE; + } +#endif + } + return FALSE; +} + +/** + * コントロール更新 + */ +void SerialOptComPage::UpdateControls() +{ + const UINT nPort = m_port.GetCurItemData(m_cfg.port); + const bool bSerialShow = ((nPort >= COMPORT_COM1) && (nPort <= COMPORT_COM4)); + const bool bMidiShow = (nPort == COMPORT_MIDI); +#if defined(SUPPORT_WACOM_TABLET) + const bool bPentabShow = (nPort == COMPORT_TABLET); +#else + const bool bPentabShow = false; +#endif +#if defined(SUPPORT_NAMED_PIPE) + const bool bPipeShow = (nPort == COMPORT_PIPE); +#else + const bool bPipeShow = false; +#endif + + // Physical serial port + static const UINT serial[] = + { + IDC_COM1SPEED, IDC_COM1CHARSIZE, IDC_COM1PARITY, IDC_COM1STOPBIT, + IDC_COM1STR00, IDC_COM1STR01, IDC_COM1STR02, IDC_COM1STR03, + IDC_COM1STR04, IDC_COM1STR05, IDC_COM1STR06, IDC_COM1STR07 + }; + for (UINT i = 0; i < _countof(serial); i++) + { + CWndBase wnd = GetDlgItem(serial[i]); + wnd.EnableWindow(bSerialShow ? TRUE : FALSE); + wnd.ShowWindow(bSerialShow ? SW_SHOW : SW_HIDE); + } + if(m_cm != cm_rs232c){ + m_chkfixedspeed.EnableWindow(FALSE); + }else{ + m_chkfixedspeed.EnableWindow(bSerialShow ? TRUE : FALSE); + } + m_chkfixedspeed.ShowWindow(bSerialShow ? SW_SHOW : SW_HIDE); + m_chkDSRcheck.ShowWindow(bSerialShow ? SW_SHOW : SW_HIDE); + + // Serial MIDI emulation + static const UINT midi[] = + { + IDC_COM1MMAP, IDC_COM1MMDL, IDC_COM1DEFE, IDC_COM1DEFF, IDC_COM1DEFB, + IDC_COM1STR10, IDC_COM1STR11, IDC_COM1STR12 + }; + for (UINT i = 0; i < _countof(midi); i++) + { + CWndBase wnd = GetDlgItem(midi[i]); + wnd.EnableWindow(bMidiShow ? TRUE : FALSE); + wnd.ShowWindow(bMidiShow ? SW_SHOW : SW_HIDE); + } + + // Serial pen tablet emulation + m_chkpentabfa.EnableWindow(bPentabShow ? TRUE : FALSE); + m_chkpentabfa.ShowWindow(bPentabShow ? SW_SHOW : SW_HIDE); + + // Named-pipe + static const UINT pipe[] = + { + IDC_COM1PIPENAME, IDC_COM1PIPESERV, + IDC_COM1STR30, IDC_COM1STR31, IDC_COM1STR32 + }; + for (UINT i = 0; i < _countof(pipe); i++) + { + CWndBase wnd = GetDlgItem(pipe[i]); + wnd.EnableWindow(bPipeShow ? TRUE : FALSE); + wnd.ShowWindow(bPipeShow ? SW_SHOW : SW_HIDE); + } +} + + + +// ---- + +/** + * @brief 61 ページ + */ +class SerialOpt61Page : public CPropPageProc +{ +public: + SerialOpt61Page(); + virtual ~SerialOpt61Page(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + UINT8 m_sw[3]; //!< スイッチ + UINT8 m_jmp[6]; //!< ジャンパ + CComboData m_speed[2]; //!< Speed + CComboData m_int[2]; //!< INT + CComboData m_sync[2]; //!< Mode + CStaticDipSw m_dipsw; //!< DIPSW + void Set(const UINT8* sw, const UINT8* jmp); + UINT8 GetMode(UINT nIndex, UINT8 cMode); + void SetMode(UINT nIndex, UINT8 cMode); + void UpdateMode(UINT nIndex, UINT8& cMode); + void OnDipSw(); +}; + +enum +{ + PC9861S1_X = 1, + PC9861S2_X = 10, + PC9861S3_X = 17, + PC9861S_Y = 1, + + PC9861J1_X = 1, + PC9861J2_X = 9, + PC9861J3_X = 17, + PC9861J4_X = 1, + PC9861J5_X = 11, + PC9861J6_X = 19, + PC9861J1_Y = 4, + PC9861J4_Y = 7 +}; + +//! INT1 +static const CComboData::Value s_int1[] = +{ + {0, 0x00}, + {1, 0x02}, + {2, 0x01}, + {3, 0x03}, +}; + +//! INT2 +static const CComboData::Value s_int2[] = +{ + {0, 0x00}, + {4, 0x08}, + {5, 0x04}, + {6, 0x0c}, +}; + +//! 同期方法 +static const CComboData::Entry s_sync[] = +{ + {MAKEINTRESOURCE(IDS_SYNC), 0x03}, + {MAKEINTRESOURCE(IDS_ASYNC), 0x00}, + {MAKEINTRESOURCE(IDS_ASYNC16X), 0x01}, + {MAKEINTRESOURCE(IDS_ASYNC64X), 0x02}, +}; + +/** + * コンストラクタ + */ +SerialOpt61Page::SerialOpt61Page() + : CPropPageProc(IDD_PC9861A) +{ + ZeroMemory(m_sw, sizeof(m_sw)); + ZeroMemory(m_jmp, sizeof(m_jmp)); +} + +/** + * デストラクタ + */ +SerialOpt61Page::~SerialOpt61Page() +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL SerialOpt61Page::OnInitDialog() +{ + CheckDlgButton(IDC_PC9861E, (np2cfg.pc9861enable) ? BST_CHECKED : BST_UNCHECKED); + + m_speed[0].SubclassDlgItem(IDC_CH1SPEED, this); + m_speed[0].Add(pc9861k_speed, _countof(pc9861k_speed)); + m_speed[1].SubclassDlgItem(IDC_CH2SPEED, this); + m_speed[1].Add(pc9861k_speed, _countof(pc9861k_speed)); + + m_int[0].SubclassDlgItem(IDC_CH1INT, this); + m_int[0].Add(s_int1, _countof(s_int1)); + m_int[1].SubclassDlgItem(IDC_CH2INT, this); + m_int[1].Add(s_int2, _countof(s_int2)); + + m_sync[0].SubclassDlgItem(IDC_CH1MODE, this); + m_sync[0].Add(s_sync, _countof(s_sync)); + m_sync[1].SubclassDlgItem(IDC_CH2MODE, this); + m_sync[1].Add(s_sync, _countof(s_sync)); + + Set(np2cfg.pc9861sw, np2cfg.pc9861jmp); + + m_dipsw.SubclassDlgItem(IDC_PC9861DIP, this); + + return TRUE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void SerialOpt61Page::OnOK() +{ + bool bUpdated = false; + + const UINT8 cEnabled = (IsDlgButtonChecked(IDC_PC9861E) != BST_UNCHECKED) ? 1 : 0; + if (np2cfg.pc9861enable != cEnabled) + { + np2cfg.pc9861enable = cEnabled; + bUpdated = true; + } + + if (memcmp(np2cfg.pc9861sw, m_sw, 3)) + { + CopyMemory(np2cfg.pc9861sw, m_sw, 3); + bUpdated = true; + } + if (memcmp(np2cfg.pc9861jmp, m_jmp, 6)) + { + CopyMemory(np2cfg.pc9861jmp, m_jmp, 6); + bUpdated = true; + } + + if (bUpdated) + { + ::sysmng_update(SYS_UPDATECFG); + } +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL SerialOpt61Page::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_CH1SPEED: + case IDC_CH1MODE: + UpdateMode(0, m_sw[0]); + break; + + case IDC_CH2SPEED: + case IDC_CH2MODE: + UpdateMode(1, m_sw[2]); + break; + + case IDC_CH1INT: + case IDC_CH2INT: + { + UINT8 cMode = m_sw[1] & 0xf0; + cMode |= m_int[0].GetCurItemData(m_sw[1] & 0x03); + cMode |= m_int[1].GetCurItemData(m_sw[1] & 0x0c); + if (m_sw[1] != cMode) + { + m_sw[1] = cMode; + m_dipsw.Invalidate(); + } + } + break; + + case IDC_PC9861DIP: + OnDipSw(); + break; + } + return FALSE; +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT SerialOpt61Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + switch (nMsg) + { + case WM_DRAWITEM: + if (LOWORD(wParam) == IDC_PC9861DIP) + { + UINT8* pBitmap = dipswbmp_get9861(m_sw, m_jmp); + m_dipsw.Draw((reinterpret_cast(lParam))->hDC, pBitmap); + _MFREE(pBitmap); + } + return FALSE; + } + return CDlgProc::WindowProc(nMsg, wParam, lParam); +} + +/** + * コントロール設定 + * @param[in] sw 設定値 + * @param[in] jmp 設定値 + */ +void SerialOpt61Page::Set(const UINT8* sw, const UINT8* jmp) +{ + CopyMemory(m_sw, sw, sizeof(m_sw)); + CopyMemory(m_jmp, jmp, sizeof(m_jmp)); + + SetMode(0, sw[0]); + SetMode(1, sw[2]); + m_int[0].SetCurItemData(sw[1] & 0x03); + m_int[1].SetCurItemData(sw[1] & 0x0c); +} + +/** + * モードを得る + * @param[in] nIndex ポート + * @param[in] cMode デフォルト値 + * @return モード + */ +UINT8 SerialOpt61Page::GetMode(UINT nIndex, UINT8 cMode) +{ + const UINT8 cSync = m_sync[nIndex].GetCurItemData(cMode & 0x03); + + UINT nSpeed = m_speed[nIndex].GetCurSel(); + if (nSpeed > (_countof(pc9861k_speed) - 1)) + { + nSpeed = _countof(pc9861k_speed) - 1; + } + if (cSync & 2) + { + nSpeed += 3; + } + else + { + if (nSpeed) + { + nSpeed--; + } + } + return (((~nSpeed) & 0x0f) << 2) | cSync; +} + +/** + * モードを設定 + * @param[in] nIndex ポート + * @param[in] cMode モード + */ +void SerialOpt61Page::SetMode(UINT nIndex, UINT8 cMode) +{ + UINT nSpeed = (((~cMode) >> 2) & 0x0f) + 1; + if (cMode) + { + if (nSpeed > 4) + { + nSpeed -= 4; + } + else + { + nSpeed = 0; + } + } + if (nSpeed > (_countof(pc9861k_speed) - 1)) + { + nSpeed = _countof(pc9861k_speed) - 1; + } + m_speed[nIndex].SetCurSel(nSpeed); + m_sync[nIndex].SetCurItemData(cMode & 0x03); +} + +/** + * 更新 + * @param[in] nIndex ポート + * @param[out] cMode モード + */ +void SerialOpt61Page::UpdateMode(UINT nIndex, UINT8& cMode) +{ + const UINT8 cValue = GetMode(nIndex, cMode); + if (cMode != cValue) + { + cMode = cValue; + SetMode(nIndex, cMode); + m_dipsw.Invalidate(); + } +} + +/** + * DIPSW をタップした + */ +void SerialOpt61Page::OnDipSw() +{ + RECT rect1; + m_dipsw.GetWindowRect(&rect1); + + RECT rect2; + m_dipsw.GetClientRect(&rect2); + + POINT p; + ::GetCursorPos(&p); + p.x += rect2.left - rect1.left; + p.y += rect2.top - rect1.top; + p.x /= 9; + p.y /= 9; + + UINT8 sw[3]; + UINT8 jmp[6]; + CopyMemory(sw, m_sw, sizeof(sw)); + CopyMemory(jmp, m_jmp, sizeof(jmp)); + + if ((p.y >= 1) && (p.y < 3)) // 1段目 + { + if ((p.x >= 1) && (p.x < 7)) // S1 + { + sw[0] ^= (1 << (p.x - 1)); + } + else if ((p.x >= 10) && (p.x < 14)) // S2 + { + sw[1] ^= (1 << (p.x - 10)); + } + else if ((p.x >= 17) && (p.x < 23)) // S3 + { + sw[2] ^= (1 << (p.x - 17)); + } + } + else if ((p.y >= 4) && (p.y < 6)) // 2段目 + { + if ((p.x >= 1) && (p.x < 7)) // J1 + { + jmp[0] ^= (1 << (p.x - 1)); + } + else if ((p.x >= 9) && (p.x < 15)) // J2 + { + jmp[1] ^= (1 << (p.x - 9)); + } + else if ((p.x >= 17) && (p.x < 19)) // J3 + { + jmp[2] = (1 << (p.x - 17)); + } + } + else if ((p.y >= 7) && (p.y < 9)) // 3段目 + { + if ((p.x >= 1) && (p.x < 9)) // J4 + { + const UINT8 cBit = (1 << (p.x - 1)); + jmp[3] = (jmp[3] != cBit) ? cBit : 0; + } + else if ((p.x >= 11) && (p.x < 17)) // J5 + { + jmp[4] ^= (1 << (p.x - 11)); + } + else if ((p.x >= 19) && (p.x < 25)) // J6 + { + jmp[5] ^= (1 << (p.x - 19)); + } + } + + if ((memcmp(m_sw, sw, sizeof(sw)) != 0) || (memcmp(m_jmp, jmp, sizeof(jmp)) != 0)) + { + Set(sw, jmp); + m_dipsw.Invalidate(); + } +} + + + +// ---- + +/** + * シリアル設定 + * @param[in] hwndParent 親ウィンドウ + */ +void dialog_serial(HWND hwndParent) +{ + CPropSheetProc prop(IDS_SERIALOPTION, hwndParent); + + SerialOptComPage com1(IDS_SERIAL1, cm_rs232c, np2oscfg.com1); + prop.AddPage(&com1); + + SerialOpt61Page pc9861; + prop.AddPage(&pc9861); + + SerialOptComPage com2(IDS_PC9861B, cm_pc9861ch1, np2oscfg.com2); + prop.AddPage(&com2); + + SerialOptComPage com3(IDS_PC9861C, cm_pc9861ch2, np2oscfg.com3); + prop.AddPage(&com3); + + prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; + prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); + prop.m_psh.pfnCallback = np2class_propetysheet; + prop.DoModal(); + + ::InvalidateRect(hwndParent, NULL, TRUE); +} diff --git a/windows/dialog/d_sound.cpp b/windows/dialog/d_sound.cpp index 5b2153b7..bd583ea8 100644 --- a/windows/dialog/d_sound.cpp +++ b/windows/dialog/d_sound.cpp @@ -34,7 +34,7 @@ // ---- mixer /** - * @brief Mixer y[W + * @brief Mixer ページ */ class SndOptMixerPage : public CPropPageProc { @@ -49,19 +49,19 @@ class SndOptMixerPage : public CPropPageProc virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); private: - CSliderValue m_master; //!< }X^[ H[ - CSliderValue m_fm; //!< FM H[ - CSliderValue m_psg; //!< PSG H[ - CSliderValue m_adpcm; //!< ADPCM H[ - CSliderValue m_pcm; //!< PCM H[ - CSliderValue m_rhythm; //!< RHYTHM H[ - CSliderValue m_cdda; //!< CD-DA H[ - CSliderValue m_midi; //!< MIDI H[ - CSliderValue m_hardware; //!< n[h֌WiV[NE[j H[ + CSliderValue m_master; //!< マスター ヴォリューム + CSliderValue m_fm; //!< FM ヴォリューム + CSliderValue m_psg; //!< PSG ヴォリューム + CSliderValue m_adpcm; //!< ADPCM ヴォリューム + CSliderValue m_pcm; //!< PCM ヴォリューム + CSliderValue m_rhythm; //!< RHYTHM ヴォリューム + CSliderValue m_cdda; //!< CD-DA ヴォリューム + CSliderValue m_midi; //!< MIDI ヴォリューム + CSliderValue m_hardware; //!< ハード関係(シーク・リレー) ヴォリューム }; /** - * RXgN^ + * コンストラクタ */ SndOptMixerPage::SndOptMixerPage() : CPropPageProc(IDD_SNDMIX) @@ -69,16 +69,16 @@ SndOptMixerPage::SndOptMixerPage() } /** - * fXgN^ + * デストラクタ */ SndOptMixerPage::~SndOptMixerPage() { } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL SndOptMixerPage::OnInitDialog() { @@ -135,7 +135,7 @@ BOOL SndOptMixerPage::OnInitDialog() } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void SndOptMixerPage::OnOK() { @@ -254,10 +254,10 @@ void SndOptMixerPage::OnOK() } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL SndOptMixerPage::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -288,11 +288,11 @@ BOOL SndOptMixerPage::OnCommand(WPARAM wParam, LPARAM lParam) } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT SndOptMixerPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -348,7 +348,7 @@ LRESULT SndOptMixerPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) // ---- PC-9801-14 /** - * @brief 14 y[W + * @brief 14 ページ */ class SndOpt14Page : public CPropPageProc { @@ -363,19 +363,19 @@ class SndOpt14Page : public CPropPageProc private: /** - * @brief ACe + * @brief アイテム */ struct Item { - UINT nSlider; //!< XC_[ - UINT nStatic; //!< X^eBbN + UINT nSlider; //!< スライダー + UINT nStatic; //!< スタティック }; - CSliderValue m_vol[6]; //!< H[ + CSliderValue m_vol[6]; //!< ヴォリューム }; /** - * RXgN^ + * コンストラクタ */ SndOpt14Page::SndOpt14Page() : CPropPageProc(IDD_SND14) @@ -383,16 +383,16 @@ SndOpt14Page::SndOpt14Page() } /** - * fXgN^ + * デストラクタ */ SndOpt14Page::~SndOpt14Page() { } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL SndOpt14Page::OnInitDialog() { @@ -418,7 +418,7 @@ BOOL SndOpt14Page::OnInitDialog() } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void SndOpt14Page::OnOK() { @@ -442,11 +442,11 @@ void SndOpt14Page::OnOK() } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT SndOpt14Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -469,7 +469,7 @@ LRESULT SndOpt14Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) // ---- PC-9801-26 /** - * @brief 26 y[W + * @brief 26 ページ */ class SndOpt26Page : public CPropPageProc { @@ -484,7 +484,7 @@ class SndOpt26Page : public CPropPageProc virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); private: - UINT8 m_snd26; //!< ݒl + UINT8 m_snd26; //!< 設定値 CComboData m_io; //!< IO CComboData m_int; //!< INT CComboData m_rom; //!< ROM @@ -521,7 +521,7 @@ static const CComboData::Entry s_rom26[] = }; /** - * RXgN^ + * コンストラクタ */ SndOpt26Page::SndOpt26Page() : CPropPageProc(IDD_SND26) @@ -530,16 +530,16 @@ SndOpt26Page::SndOpt26Page() } /** - * fXgN^ + * デストラクタ */ SndOpt26Page::~SndOpt26Page() { } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL SndOpt26Page::OnInitDialog() { @@ -561,7 +561,7 @@ BOOL SndOpt26Page::OnInitDialog() } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void SndOpt26Page::OnOK() { @@ -573,10 +573,10 @@ void SndOpt26Page::OnOK() } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL SndOpt26Page::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -607,11 +607,11 @@ BOOL SndOpt26Page::OnCommand(WPARAM wParam, LPARAM lParam) } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT SndOpt26Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -630,8 +630,8 @@ LRESULT SndOpt26Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) } /** - * Rg[ݒ - * @param[in] cValue ݒl + * コントロール設定 + * @param[in] cValue 設定値 */ void SndOpt26Page::Set(UINT8 cValue) { @@ -645,9 +645,9 @@ void SndOpt26Page::Set(UINT8 cValue) } /** - * ݒ - * @param[in] nAdd ljrbg - * @param[in] nRemove 폜rbg + * 設定 + * @param[in] nAdd 追加ビット + * @param[in] nRemove 削除ビット */ void SndOpt26Page::SetJumper(UINT nAdd, UINT nRemove) { @@ -660,7 +660,7 @@ void SndOpt26Page::SetJumper(UINT nAdd, UINT nRemove) } /** - * DIPSW ^bv + * DIPSW をタップした */ void SndOpt26Page::OnDipSw() { @@ -721,7 +721,7 @@ void SndOpt26Page::OnDipSw() // ---- PC-9801-86 /** - * @brief 86 y[W + * @brief 86 ページ */ class SndOpt86Page : public CPropPageProc { @@ -736,7 +736,7 @@ class SndOpt86Page : public CPropPageProc virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); private: - UINT8 m_snd86; //!< ݒl + UINT8 m_snd86; //!< 設定値 CComboData m_io; //!< IO CComboData m_int; //!< INT CComboData m_id; //!< ID @@ -776,7 +776,7 @@ static const CComboData::Entry s_id86[] = }; /** - * RXgN^ + * コンストラクタ */ SndOpt86Page::SndOpt86Page() : CPropPageProc(IDD_SND86) @@ -785,16 +785,16 @@ SndOpt86Page::SndOpt86Page() } /** - * fXgN^ + * デストラクタ */ SndOpt86Page::~SndOpt86Page() { } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL SndOpt86Page::OnInitDialog() { @@ -816,7 +816,7 @@ BOOL SndOpt86Page::OnInitDialog() } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void SndOpt86Page::OnOK() { @@ -828,10 +828,10 @@ void SndOpt86Page::OnOK() } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL SndOpt86Page::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -870,11 +870,11 @@ BOOL SndOpt86Page::OnCommand(WPARAM wParam, LPARAM lParam) } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT SndOpt86Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -893,8 +893,8 @@ LRESULT SndOpt86Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) } /** - * Rg[ݒ - * @param[in] cValue ݒl + * コントロール設定 + * @param[in] cValue 設定値 */ void SndOpt86Page::Set(UINT8 cValue) { @@ -907,9 +907,9 @@ void SndOpt86Page::Set(UINT8 cValue) } /** - * ݒ - * @param[in] nAdd ljrbg - * @param[in] nRemove 폜rbg + * 設定 + * @param[in] nAdd 追加ビット + * @param[in] nRemove 削除ビット */ void SndOpt86Page::SetJumper(UINT nAdd, UINT nRemove) { @@ -922,7 +922,7 @@ void SndOpt86Page::SetJumper(UINT nAdd, UINT nRemove) } /** - * DIPSW ^bv + * DIPSW をタップした */ void SndOpt86Page::OnDipSw() { @@ -952,7 +952,7 @@ void SndOpt86Page::OnDipSw() // ---- PC-9801-118 /** - * @brief 118 y[W + * @brief 118 ページ */ class SndOpt118Page : public CPropPageProc { @@ -967,13 +967,13 @@ class SndOpt118Page : public CPropPageProc virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); private: - UINT16 m_snd118io; //!< IOݒl - UINT8 m_snd118id; //!< IDݒl - UINT8 m_snd118dma; //!< DMAݒl - UINT8 m_snd118irqf; //!< IRQ(FM)ݒl - UINT8 m_snd118irqp; //!< IRQ(PCM)ݒl - UINT8 m_snd118irqm; //!< IRQ(MIDI)ݒl - UINT8 m_snd118rom; //!< ROMݒl + UINT16 m_snd118io; //!< IO設定値 + UINT8 m_snd118id; //!< ID設定値 + UINT8 m_snd118dma; //!< DMA設定値 + UINT8 m_snd118irqf; //!< IRQ(FM)設定値 + UINT8 m_snd118irqp; //!< IRQ(PCM)設定値 + UINT8 m_snd118irqm; //!< IRQ(MIDI)設定値 + UINT8 m_snd118rom; //!< ROM設定値 CComboData m_cmbio; //!< IO CComboData m_cmbid; //!< ID CComboData m_cmbdma; //!< DMA @@ -1044,7 +1044,7 @@ static const CComboData::Entry s_int118m[] = }; /** - * RXgN^ + * コンストラクタ */ SndOpt118Page::SndOpt118Page() : CPropPageProc(IDD_SND118) @@ -1059,16 +1059,16 @@ SndOpt118Page::SndOpt118Page() } /** - * fXgN^ + * デストラクタ */ SndOpt118Page::~SndOpt118Page() { } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL SndOpt118Page::OnInitDialog() { @@ -1119,7 +1119,7 @@ BOOL SndOpt118Page::OnInitDialog() } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void SndOpt118Page::OnOK() { @@ -1161,10 +1161,10 @@ void SndOpt118Page::OnOK() } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL SndOpt118Page::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -1234,11 +1234,11 @@ BOOL SndOpt118Page::OnCommand(WPARAM wParam, LPARAM lParam) } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT SndOpt118Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -1257,11 +1257,11 @@ LRESULT SndOpt118Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) } /** - * DIPSW ^bv + * DIPSW をタップした */ void SndOpt118Page::OnDipSw() { - // TODO: JumperNbNƂ̓ + // TODO: Jumperをクリックしたときの動作を実装する m_jumper.Invalidate(); } @@ -1270,7 +1270,7 @@ void SndOpt118Page::OnDipSw() // ---- Mate-X PCM /** - * @brief Mate-X PCM(WSS) y[W + * @brief Mate-X PCM(WSS) ページ */ class SndOptWSSPage : public CPropPageProc { @@ -1285,16 +1285,16 @@ class SndOptWSSPage : public CPropPageProc virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); private: - UINT8 m_snd118id; //!< IDݒl - UINT8 m_snd118dma; //!< DMAݒl - UINT8 m_snd118irqp; //!< IRQݒl + UINT8 m_snd118id; //!< ID設定値 + UINT8 m_snd118dma; //!< DMA設定値 + UINT8 m_snd118irqp; //!< IRQ設定値 CComboData m_cmbid; //!< ID CComboData m_cmbdma; //!< DMA CComboData m_cmbirqp; //!< IRQ }; /** - * RXgN^ + * コンストラクタ */ SndOptWSSPage::SndOptWSSPage() : CPropPageProc(IDD_SNDWSS) @@ -1305,16 +1305,16 @@ SndOptWSSPage::SndOptWSSPage() } /** - * fXgN^ + * デストラクタ */ SndOptWSSPage::~SndOptWSSPage() { } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL SndOptWSSPage::OnInitDialog() { @@ -1341,7 +1341,7 @@ BOOL SndOptWSSPage::OnInitDialog() } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void SndOptWSSPage::OnOK() { @@ -1363,10 +1363,10 @@ void SndOptWSSPage::OnOK() } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL SndOptWSSPage::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -1397,11 +1397,11 @@ BOOL SndOptWSSPage::OnCommand(WPARAM wParam, LPARAM lParam) } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT SndOptWSSPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -1420,7 +1420,7 @@ LRESULT SndOptWSSPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) // ---- Sound Blaster 16(98) /** - * @brief SB16 y[W + * @brief SB16 ページ */ class SndOptSB16Page : public CPropPageProc { @@ -1435,9 +1435,9 @@ class SndOptSB16Page : public CPropPageProc virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); private: - UINT8 m_snd118io; //!< IOݒl - UINT8 m_snd118dma; //!< DMAݒl - UINT8 m_snd118irqf; //!< IRQݒl + UINT8 m_snd118io; //!< IO設定値 + UINT8 m_snd118dma; //!< DMA設定値 + UINT8 m_snd118irqf; //!< IRQ設定値 CComboData m_cmbio; //!< IO CComboData m_cmbdma; //!< DMA CComboData m_cmbirqf; //!< IRQ @@ -1472,7 +1472,7 @@ static const CComboData::Entry s_intsb16[] = }; /** - * RXgN^ + * コンストラクタ */ SndOptSB16Page::SndOptSB16Page() : CPropPageProc(IDD_SNDSB16) @@ -1483,16 +1483,16 @@ SndOptSB16Page::SndOptSB16Page() } /** - * fXgN^ + * デストラクタ */ SndOptSB16Page::~SndOptSB16Page() { } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL SndOptSB16Page::OnInitDialog() { @@ -1519,7 +1519,7 @@ BOOL SndOptSB16Page::OnInitDialog() } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void SndOptSB16Page::OnOK() { @@ -1541,10 +1541,10 @@ void SndOptSB16Page::OnOK() } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL SndOptSB16Page::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -1563,7 +1563,7 @@ BOOL SndOptSB16Page::OnCommand(WPARAM wParam, LPARAM lParam) return TRUE; case IDC_SND118DEF: - // {[hftHg IO:D2 DMA:3 IRQ:5(INT1) + // ボードデフォルト IO:D2 DMA:3 IRQ:5(INT1) m_snd118io = 0xd2; m_snd118dma = 3; m_snd118irqf = 5; @@ -1576,11 +1576,11 @@ BOOL SndOptSB16Page::OnCommand(WPARAM wParam, LPARAM lParam) } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT SndOptSB16Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -1599,7 +1599,7 @@ LRESULT SndOptSB16Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) // ---- Speak board /** - * @brief Speak board y[W + * @brief Speak board ページ */ class SndOptSpbPage : public CPropPageProc { @@ -1614,8 +1614,8 @@ class SndOptSpbPage : public CPropPageProc virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); private: - UINT8 m_spb; //!< ݒl - UINT8 m_vr; //!< VRݒl + UINT8 m_spb; //!< 設定値 + UINT8 m_vr; //!< VR設定値 CComboData m_io; //!< IO CComboData m_int; //!< INT CComboData m_rom; //!< ROM @@ -1627,7 +1627,7 @@ class SndOptSpbPage : public CPropPageProc }; /** - * RXgN^ + * コンストラクタ */ SndOptSpbPage::SndOptSpbPage() : CPropPageProc(IDD_SNDSPB) @@ -1637,16 +1637,16 @@ SndOptSpbPage::SndOptSpbPage() } /** - * fXgN^ + * デストラクタ */ SndOptSpbPage::~SndOptSpbPage() { } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL SndOptSpbPage::OnInitDialog() { @@ -1675,7 +1675,7 @@ BOOL SndOptSpbPage::OnInitDialog() } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void SndOptSpbPage::OnOK() { @@ -1713,10 +1713,10 @@ void SndOptSpbPage::OnOK() } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL SndOptSpbPage::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -1761,11 +1761,11 @@ BOOL SndOptSpbPage::OnCommand(WPARAM wParam, LPARAM lParam) } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT SndOptSpbPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -1784,9 +1784,9 @@ LRESULT SndOptSpbPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) } /** - * Rg[ݒ - * @param[in] cValue ݒl - * @param[in] cVR VR ݒl + * コントロール設定 + * @param[in] cValue 設定値 + * @param[in] cVR VR 設定値 */ void SndOptSpbPage::Set(UINT8 cValue, UINT8 cVR) { @@ -1804,9 +1804,9 @@ void SndOptSpbPage::Set(UINT8 cValue, UINT8 cVR) } /** - * ݒ - * @param[in] nAdd ljrbg - * @param[in] nRemove 폜rbg + * 設定 + * @param[in] nAdd 追加ビット + * @param[in] nRemove 削除ビット */ void SndOptSpbPage::SetJumper(UINT nAdd, UINT nRemove) { @@ -1819,7 +1819,7 @@ void SndOptSpbPage::SetJumper(UINT nAdd, UINT nRemove) } /** - * DIPSW ^bv + * DIPSW をタップした */ void SndOptSpbPage::OnDipSw() { @@ -1889,7 +1889,7 @@ void SndOptSpbPage::OnDipSw() // ---- JOYPAD /** - * @brief PAD y[W + * @brief PAD ページ */ class SndOptPadPage : public CPropPageProc { @@ -1905,7 +1905,7 @@ class SndOptPadPage : public CPropPageProc CComboData m_cmbid; //!< ID }; -//! {^ +//! ボタン static const UINT s_pad[4][3] = { {IDC_PAD1_1A, IDC_PAD1_2A, IDC_PAD1_RA}, @@ -1915,7 +1915,7 @@ static const UINT s_pad[4][3] = }; /** - * RXgN^ + * コンストラクタ */ SndOptPadPage::SndOptPadPage() : CPropPageProc(IDD_SNDPAD1) @@ -1923,9 +1923,9 @@ SndOptPadPage::SndOptPadPage() } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL SndOptPadPage::OnInitDialog() { @@ -2018,7 +2018,7 @@ BOOL SndOptPadPage::OnInitDialog() } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void SndOptPadPage::OnOK() { @@ -2082,10 +2082,10 @@ void SndOptPadPage::OnOK() } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL SndOptPadPage::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -2104,7 +2104,7 @@ BOOL SndOptPadPage::OnCommand(WPARAM wParam, LPARAM lParam) // ---- fmgen /** - * @brief fmgen y[W + * @brief fmgen ページ */ class SndOptFMGenPage : public CPropPageProc { @@ -2117,12 +2117,12 @@ class SndOptFMGenPage : public CPropPageProc virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); private: - UINT8 m_enable; //!< fmgeng + UINT8 m_enable; //!< fmgenを使うか CWndProc m_chkenable; //!< USE FMGEN }; /** - * RXgN^ + * コンストラクタ */ SndOptFMGenPage::SndOptFMGenPage() : CPropPageProc(IDD_SNDFMGEN) @@ -2130,9 +2130,9 @@ SndOptFMGenPage::SndOptFMGenPage() } /** - * ̃\bh WM_INITDIALOG ̃bZ[WɉČĂяo܂ - * @retval TRUE ŏ̃Rg[ɓ̓tH[JXݒ - * @retval FALSE ɐݒ + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 */ BOOL SndOptFMGenPage::OnInitDialog() { @@ -2148,7 +2148,7 @@ BOOL SndOptFMGenPage::OnInitDialog() } /** - * [U[ OK ̃{^ (IDOK ID ̃{^) NbNƌĂяo܂ + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます */ void SndOptFMGenPage::OnOK() { @@ -2163,10 +2163,10 @@ void SndOptFMGenPage::OnOK() } /** - * [U[j[̍ڂIƂɁAt[[NɂČĂяo܂ - * @param[in] wParam p^ - * @param[in] lParam p^ - * @retval TRUE AvP[ṼbZ[W + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した */ BOOL SndOptFMGenPage::OnCommand(WPARAM wParam, LPARAM lParam) { @@ -2185,8 +2185,8 @@ BOOL SndOptFMGenPage::OnCommand(WPARAM wParam, LPARAM lParam) // ---- /** - * TEhݒ - * @param[in] hwndParent eEBhE + * サウンド設定 + * @param[in] hwndParent 親ウィンドウ */ void dialog_sndopt(HWND hwndParent) { diff --git a/windows/dialog/d_soundlog.cpp b/windows/dialog/d_soundlog.cpp old mode 100755 new mode 100644 index 78711f07..cf9bc7c0 --- a/windows/dialog/d_soundlog.cpp +++ b/windows/dialog/d_soundlog.cpp @@ -1,133 +1,133 @@ -/** - * @file d_soundlog.cpp - * @brief soundlog dialog - */ - -#include -#include "resource.h" -#include "dialog.h" -#include -#include -#include -#if defined(SUPPORT_RECVIDEO) -#include "recvideo.h" -#endif // defined(SUPPORT_RECVIDEO) -#include "misc/DlgProc.h" -#if defined(SUPPORT_WAVEREC) -#include -#endif // defined(SUPPORT_WAVEREC) -#if defined(SUPPORT_S98) -#include -#endif // defined(SUPPORT_S98) -#include "dialog/winfiledlg.h" - -/** - * デフォルト ファイルを得る - * @param[in] lpExt 拡張子 - * @param[out] lpFilename ファイル名 - * @param[in] cchFilename ファイル名長 - */ -static void GetDefaultFilename(LPCTSTR lpExt, LPTSTR lpFilename, UINT cchFilename) -{ - for (UINT i = 0; i < 10000; i++) - { - TCHAR szFilename[MAX_PATH]; - wsprintf(szFilename, TEXT("NP2_%04d.%s"), i, lpExt); - - file_cpyname(lpFilename, bmpfilefolder, cchFilename); - file_cutname(lpFilename); - file_catname(lpFilename, szFilename, cchFilename); - - if (file_attr(lpFilename) == -1) - { - break; - } - } -} - -/** - * サウンド ログ - * @param[in] hWnd 親ウィンドウ - */ -void dialog_soundlog(HWND hWnd) -{ - UINT nExtId = 0; - std::tstring rFilter; - -#if defined(SUPPORT_S98) - S98_close(); - if (nExtId == 0) - { - nExtId = IDS_S98EXT; - } - rFilter += LoadTString(IDS_S98FILTER); -#endif // defined(SUPPORT_S98) - -#if defined(SUPPORT_WAVEREC) - sound_recstop(); - - if (nExtId == 0) - { - nExtId = IDS_WAVEEXT; - } - rFilter += LoadTString(IDS_WAVEFILTER); -#endif // defined(SUPPORT_WAVEREC) - -#if defined(SUPPORT_RECVIDEO) - recvideo_close(); -#endif // defined(SUPPORT_RECVIDEO) - - if (nExtId == 0) - { - return; - } - - std::tstring rExt(LoadTString(nExtId)); - std::tstring rTitle(LoadTString(IDS_WAVETITLE)); - - TCHAR szPath[MAX_PATH]; - TCHAR szName[MAX_PATH]; - GetDefaultFilename(rExt.c_str(), szPath, _countof(szPath)); - - OPENFILENAMEW ofnw; - if (WinFileDialogW(hWnd, &ofnw, WINFILEDIALOGW_MODE_SET, szPath, szName, rExt.c_str(), rTitle.c_str(), rFilter.c_str(), 1)) - { - return; - } - - LPCTSTR lpFilename = szPath; - file_cpyname(bmpfilefolder, lpFilename, _countof(bmpfilefolder)); - sysmng_update(SYS_UPDATEOSCFG); - - LPCTSTR lpExt = file_getext(lpFilename); - -#if defined(SUPPORT_S98) - if (file_cmpname(lpExt, TEXT("s98")) == 0) - { - S98_open(lpFilename); - return; - } -#endif // defined(SUPPORT_S98) - -#if defined(SUPPORT_WAVEREC) - if (file_cmpname(lpExt, TEXT("wav")) == 0) - { - sound_recstart(lpFilename); - return; - } -#endif // defined(SUPPORT_WAVEREC) - -#if defined(SUPPORT_RECVIDEO) - if (file_cmpname(lpExt, TEXT("avi")) == 0) - { - if (recvideo_open(hWnd, lpFilename)) - { - TCHAR szWaveFilename[MAX_PATH]; - file_cpyname(szWaveFilename, lpFilename, _countof(szWaveFilename)); - file_cutext(szWaveFilename); - file_catname(szWaveFilename, _T(".wav"), _countof(szWaveFilename)); - sound_recstart(szWaveFilename); - } - } -#endif // defined(SUPPORT_RECVIDEO) -} +/** + * @file d_soundlog.cpp + * @brief soundlog dialog + */ + +#include +#include "resource.h" +#include "dialog.h" +#include +#include +#include +#if defined(SUPPORT_RECVIDEO) +#include "recvideo.h" +#endif // defined(SUPPORT_RECVIDEO) +#include "misc/DlgProc.h" +#if defined(SUPPORT_WAVEREC) +#include +#endif // defined(SUPPORT_WAVEREC) +#if defined(SUPPORT_S98) +#include +#endif // defined(SUPPORT_S98) +#include "dialog/winfiledlg.h" + +/** + * デフォルト ファイルを得る + * @param[in] lpExt 拡張子 + * @param[out] lpFilename ファイル名 + * @param[in] cchFilename ファイル名長 + */ +static void GetDefaultFilename(LPCTSTR lpExt, LPTSTR lpFilename, UINT cchFilename) +{ + for (UINT i = 0; i < 10000; i++) + { + TCHAR szFilename[MAX_PATH]; + wsprintf(szFilename, TEXT("NP2_%04d.%s"), i, lpExt); + + file_cpyname(lpFilename, bmpfilefolder, cchFilename); + file_cutname(lpFilename); + file_catname(lpFilename, szFilename, cchFilename); + + if (file_attr(lpFilename) == -1) + { + break; + } + } +} + +/** + * サウンド ログ + * @param[in] hWnd 親ウィンドウ + */ +void dialog_soundlog(HWND hWnd) +{ + UINT nExtId = 0; + std::tstring rFilter; + +#if defined(SUPPORT_S98) + S98_close(); + if (nExtId == 0) + { + nExtId = IDS_S98EXT; + } + rFilter += LoadTString(IDS_S98FILTER); +#endif // defined(SUPPORT_S98) + +#if defined(SUPPORT_WAVEREC) + sound_recstop(); + + if (nExtId == 0) + { + nExtId = IDS_WAVEEXT; + } + rFilter += LoadTString(IDS_WAVEFILTER); +#endif // defined(SUPPORT_WAVEREC) + +#if defined(SUPPORT_RECVIDEO) + recvideo_close(); +#endif // defined(SUPPORT_RECVIDEO) + + if (nExtId == 0) + { + return; + } + + std::tstring rExt(LoadTString(nExtId)); + std::tstring rTitle(LoadTString(IDS_WAVETITLE)); + + TCHAR szPath[MAX_PATH]; + TCHAR szName[MAX_PATH]; + GetDefaultFilename(rExt.c_str(), szPath, _countof(szPath)); + + OPENFILENAMEW ofnw; + if (WinFileDialogW(hWnd, &ofnw, WINFILEDIALOGW_MODE_SET, szPath, szName, rExt.c_str(), rTitle.c_str(), rFilter.c_str(), 1)) + { + return; + } + + LPCTSTR lpFilename = szPath; + file_cpyname(bmpfilefolder, lpFilename, _countof(bmpfilefolder)); + sysmng_update(SYS_UPDATEOSCFG); + + LPCTSTR lpExt = file_getext(lpFilename); + +#if defined(SUPPORT_S98) + if (file_cmpname(lpExt, TEXT("s98")) == 0) + { + S98_open(lpFilename); + return; + } +#endif // defined(SUPPORT_S98) + +#if defined(SUPPORT_WAVEREC) + if (file_cmpname(lpExt, TEXT("wav")) == 0) + { + sound_recstart(lpFilename); + return; + } +#endif // defined(SUPPORT_WAVEREC) + +#if defined(SUPPORT_RECVIDEO) + if (file_cmpname(lpExt, TEXT("avi")) == 0) + { + if (recvideo_open(hWnd, lpFilename)) + { + TCHAR szWaveFilename[MAX_PATH]; + file_cpyname(szWaveFilename, lpFilename, _countof(szWaveFilename)); + file_cutext(szWaveFilename); + file_catname(szWaveFilename, _T(".wav"), _countof(szWaveFilename)); + sound_recstart(szWaveFilename); + } + } +#endif // defined(SUPPORT_RECVIDEO) +} diff --git a/windows/dialog/d_txt.cpp b/windows/dialog/d_txt.cpp old mode 100755 new mode 100644 index 4b609f48..85803054 --- a/windows/dialog/d_txt.cpp +++ b/windows/dialog/d_txt.cpp @@ -1,206 +1,206 @@ -/** - * @file d_txt.cpp - * @brief txt dialog - */ - -#include -#include "resource.h" -#include "dialog.h" -#include -#include -#include -#include "misc/DlgProc.h" -#include -#include -#include -#include -#include "dialog/winfiledlg.h" - -/** フィルター */ -static const UINT s_nFilter[1] = -{ - IDS_TXTFILTER -}; - -/** - * デフォルト ファイルを得る - * @param[in] lpExt 拡張子 - * @param[out] lpFilename ファイル名 - * @param[in] cchFilename ファイル名長 - */ -static void GetDefaultFilename(LPCTSTR lpExt, LPTSTR lpFilename, UINT cchFilename) -{ - for (UINT i = 0; i < 10000; i++) - { - TCHAR szFilename[MAX_PATH]; - wsprintf(szFilename, TEXT("NP2_%04d.%s"), i, lpExt); - - file_cpyname(lpFilename, bmpfilefolder, cchFilename); - file_cutname(lpFilename); - file_catname(lpFilename, szFilename, cchFilename); - - if (file_attr(lpFilename) == -1) - { - break; - } - } -} - -void convertJIStoSJIS(UINT8 buf[]) { - unsigned char high = buf[0]; - unsigned char low = buf[1]; - high -= 0x21; - if(high & 0x1){ - low += 0x7E; - }else{ - low += 0x1F; - if(low >= 0x7F){ - low++; - } - } - high = high >> 1; - if(high < 0x1F){ - high += 0x81; - }else{ - high += 0xC1; - } - buf[0] = high; - buf[1] = low; -} -void writetxt(const OEMCHAR *filename) { - int i; - int lpos = 0; - int cpos = 0; - //int kanjiMode = 0; // JISのままで保存する場合用 - UINT8 buf[5]; - FILEH fh; - if((fh = file_create(filename)) != FILEH_INVALID){ - for(i=0x0A0000;i<0x0A3FFF;i+=2){ - if(mem[i+1]){ - // 標準漢字 - //if(!kanjiMode){ - // buf[0] = 0x1b; - // buf[1] = 0x24; - // buf[2] = 0x40; - // file_write(fh, buf, 3); - //} - buf[0] = mem[i]+0x20; - buf[1] = mem[i+1]; - convertJIStoSJIS(buf); // JIS -> Shift-JIS - file_write(fh, buf, 2); - i+=2; - lpos+=2; - //kanjiMode = 1; - }else{ - // ASCII - //if(kanjiMode){ - // buf[0] = 0x1b; - // buf[1] = 0x28; - // buf[2] = 0x4a; - // file_write(fh, buf, 3); - //} - if(mem[i]<0x20 || (0x7F<=mem[i] && mem[i]<0xA0) || (0xE0<=mem[i] && mem[i]<0xFF)){ - // 空白に変換 - buf[0] = ' '; - }else{ - buf[0] = mem[i]; - } - file_write(fh, buf, 1); - //kanjiMode = 0; - lpos++; - } - if(lpos >= 80){ - cpos += lpos; - lpos -= 80; - if(cpos >= 80*25) break; - buf[0] = '\r'; - file_write(fh, buf, 1); - buf[0] = '\n'; - file_write(fh, buf, 1); - } - } - file_close(fh); - } -} -// XXX: もっと適切な場所に移すべき -void dialog_getTVRAM(OEMCHAR *buffer) { - int i; - int lpos = 0; - int cpos = 0; - //int kanjiMode = 0; // JISのままで保存する場合用 - UINT8 buf[5]; - char *dstbuf = (char*)buffer; - for(i=0x0A0000;i<0x0A3FFF;i+=2){ - if(mem[i+1]){ - // 標準漢字 - //if(!kanjiMode){ - // buf[0] = 0x1b; - // buf[1] = 0x24; - // buf[2] = 0x40; - // file_write(fh, buf, 3); - //} - buf[0] = mem[i]+0x20; - buf[1] = mem[i+1]; - convertJIStoSJIS(buf); // JIS -> Shift-JIS - memcpy(dstbuf, buf, 2); - i+=2; - lpos+=2; - dstbuf+=2; - //kanjiMode = 1; - }else{ - // ASCII - //if(kanjiMode){ - // buf[0] = 0x1b; - // buf[1] = 0x28; - // buf[2] = 0x4a; - // file_write(fh, buf, 3); - //} - if(mem[i]<0x20 || (0x7F<=mem[i] && mem[i]<0xA0) || (0xE0<=mem[i] && mem[i]<0xFF)){ - // 空白に変換 - buf[0] = ' '; - }else{ - buf[0] = mem[i]; - } - memcpy(dstbuf, buf, 1); - //kanjiMode = 0; - lpos++; - dstbuf++; - } - if(lpos >= 80){ - cpos += lpos; - lpos -= 80; - if(cpos >= 80*25) break; - buf[0] = '\r'; - buf[1] = '\n'; - memcpy(dstbuf, buf, 2); - dstbuf+=2; - } - } - dstbuf[0] = '\0'; -} - -/** - * TXT 出力 - * @param[in] hWnd 親ウィンドウ - */ -void dialog_writetxt(HWND hWnd) -{ - std::tstring rExt(LoadTString(IDS_TXTEXT)); - std::tstring rFilter(LoadTString(s_nFilter[0])); - std::tstring rTitle(LoadTString(IDS_TXTTITLE)); - - TCHAR szPath[MAX_PATH]; - TCHAR szName[MAX_PATH]; - GetDefaultFilename(rExt.c_str(), szPath, _countof(szPath)); - - CFileDlg dlg(FALSE, rExt.c_str(), szPath, OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY, rFilter.c_str(), hWnd); - dlg.m_ofn.lpstrTitle = rTitle.c_str(); - dlg.m_ofn.nFilterIndex = 1; - OPENFILENAMEW ofnw; - if (WinFileDialogW(hWnd, &ofnw, WINFILEDIALOGW_MODE_SET, szPath, szName, rExt.c_str(), rTitle.c_str(), rFilter.c_str(), 1)) - { - LPCTSTR lpFilename = szPath; - LPCTSTR lpExt = file_getext(szPath); - writetxt(lpFilename); - } -} +/** + * @file d_txt.cpp + * @brief txt dialog + */ + +#include +#include "resource.h" +#include "dialog.h" +#include +#include +#include +#include "misc/DlgProc.h" +#include +#include +#include +#include +#include "dialog/winfiledlg.h" + +/** フィルター */ +static const UINT s_nFilter[1] = +{ + IDS_TXTFILTER +}; + +/** + * デフォルト ファイルを得る + * @param[in] lpExt 拡張子 + * @param[out] lpFilename ファイル名 + * @param[in] cchFilename ファイル名長 + */ +static void GetDefaultFilename(LPCTSTR lpExt, LPTSTR lpFilename, UINT cchFilename) +{ + for (UINT i = 0; i < 10000; i++) + { + TCHAR szFilename[MAX_PATH]; + wsprintf(szFilename, TEXT("NP2_%04d.%s"), i, lpExt); + + file_cpyname(lpFilename, bmpfilefolder, cchFilename); + file_cutname(lpFilename); + file_catname(lpFilename, szFilename, cchFilename); + + if (file_attr(lpFilename) == -1) + { + break; + } + } +} + +void convertJIStoSJIS(UINT8 buf[]) { + unsigned char high = buf[0]; + unsigned char low = buf[1]; + high -= 0x21; + if(high & 0x1){ + low += 0x7E; + }else{ + low += 0x1F; + if(low >= 0x7F){ + low++; + } + } + high = high >> 1; + if(high < 0x1F){ + high += 0x81; + }else{ + high += 0xC1; + } + buf[0] = high; + buf[1] = low; +} +void writetxt(const OEMCHAR *filename) { + int i; + int lpos = 0; + int cpos = 0; + //int kanjiMode = 0; // JISのままで保存する場合用 + UINT8 buf[5]; + FILEH fh; + if((fh = file_create(filename)) != FILEH_INVALID){ + for(i=0x0A0000;i<0x0A3FFF;i+=2){ + if(mem[i+1]){ + // 標準漢字 + //if(!kanjiMode){ + // buf[0] = 0x1b; + // buf[1] = 0x24; + // buf[2] = 0x40; + // file_write(fh, buf, 3); + //} + buf[0] = mem[i]+0x20; + buf[1] = mem[i+1]; + convertJIStoSJIS(buf); // JIS -> Shift-JIS + file_write(fh, buf, 2); + i+=2; + lpos+=2; + //kanjiMode = 1; + }else{ + // ASCII + //if(kanjiMode){ + // buf[0] = 0x1b; + // buf[1] = 0x28; + // buf[2] = 0x4a; + // file_write(fh, buf, 3); + //} + if(mem[i]<0x20 || (0x7F<=mem[i] && mem[i]<0xA0) || (0xE0<=mem[i] && mem[i]<0xFF)){ + // 空白に変換 + buf[0] = ' '; + }else{ + buf[0] = mem[i]; + } + file_write(fh, buf, 1); + //kanjiMode = 0; + lpos++; + } + if(lpos >= 80){ + cpos += lpos; + lpos -= 80; + if(cpos >= 80*25) break; + buf[0] = '\r'; + file_write(fh, buf, 1); + buf[0] = '\n'; + file_write(fh, buf, 1); + } + } + file_close(fh); + } +} +// XXX: もっと適切な場所に移すべき +void dialog_getTVRAM(OEMCHAR *buffer) { + int i; + int lpos = 0; + int cpos = 0; + //int kanjiMode = 0; // JISのままで保存する場合用 + UINT8 buf[5]; + char *dstbuf = (char*)buffer; + for(i=0x0A0000;i<0x0A3FFF;i+=2){ + if(mem[i+1]){ + // 標準漢字 + //if(!kanjiMode){ + // buf[0] = 0x1b; + // buf[1] = 0x24; + // buf[2] = 0x40; + // file_write(fh, buf, 3); + //} + buf[0] = mem[i]+0x20; + buf[1] = mem[i+1]; + convertJIStoSJIS(buf); // JIS -> Shift-JIS + memcpy(dstbuf, buf, 2); + i+=2; + lpos+=2; + dstbuf+=2; + //kanjiMode = 1; + }else{ + // ASCII + //if(kanjiMode){ + // buf[0] = 0x1b; + // buf[1] = 0x28; + // buf[2] = 0x4a; + // file_write(fh, buf, 3); + //} + if(mem[i]<0x20 || (0x7F<=mem[i] && mem[i]<0xA0) || (0xE0<=mem[i] && mem[i]<0xFF)){ + // 空白に変換 + buf[0] = ' '; + }else{ + buf[0] = mem[i]; + } + memcpy(dstbuf, buf, 1); + //kanjiMode = 0; + lpos++; + dstbuf++; + } + if(lpos >= 80){ + cpos += lpos; + lpos -= 80; + if(cpos >= 80*25) break; + buf[0] = '\r'; + buf[1] = '\n'; + memcpy(dstbuf, buf, 2); + dstbuf+=2; + } + } + dstbuf[0] = '\0'; +} + +/** + * TXT 出力 + * @param[in] hWnd 親ウィンドウ + */ +void dialog_writetxt(HWND hWnd) +{ + std::tstring rExt(LoadTString(IDS_TXTEXT)); + std::tstring rFilter(LoadTString(s_nFilter[0])); + std::tstring rTitle(LoadTString(IDS_TXTTITLE)); + + TCHAR szPath[MAX_PATH]; + TCHAR szName[MAX_PATH]; + GetDefaultFilename(rExt.c_str(), szPath, _countof(szPath)); + + CFileDlg dlg(FALSE, rExt.c_str(), szPath, OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY, rFilter.c_str(), hWnd); + dlg.m_ofn.lpstrTitle = rTitle.c_str(); + dlg.m_ofn.nFilterIndex = 1; + OPENFILENAMEW ofnw; + if (WinFileDialogW(hWnd, &ofnw, WINFILEDIALOGW_MODE_SET, szPath, szName, rExt.c_str(), rTitle.c_str(), rFilter.c_str(), 1)) + { + LPCTSTR lpFilename = szPath; + LPCTSTR lpExt = file_getext(szPath); + writetxt(lpFilename); + } +} diff --git a/windows/dialog/d_wab.cpp b/windows/dialog/d_wab.cpp old mode 100755 new mode 100644 index e08726a9..9116d617 --- a/windows/dialog/d_wab.cpp +++ b/windows/dialog/d_wab.cpp @@ -1,385 +1,385 @@ -/** - * @file d_wab.cpp - * @brief Window Accelerator Board configure dialog procedure - * - * @author $Author: SimK $ - * @date $Date: 2016/03/11 $ - */ - -#include -#include "resource.h" -#include -#include "dialog.h" -#include "c_combodata.h" -#include "np2class.h" -#include -#include -#include -#include -#include "misc\PropProc.h" -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -#ifdef __cplusplus -} -#endif - -#if defined(SUPPORT_WAB) - -/** - * @brief ウィンドウアクセラレータ基本設定ページ - * @param[in] hwndParent 親ウィンドウ - */ -class CWABPage : public CPropPageProc -{ -public: - CWABPage(); - virtual ~CWABPage(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - UINT8 m_awitch; //!< アナログスイッチモード - UINT8 m_multiwindow; //!< 別窓モード - UINT8 m_multithread; //!< マルチスレッドモード - CWndProc m_chkawitch; //!< ANALOG SWITCH IC - CWndProc m_chkmultiwindow; //!< MULTI WINDOW - CWndProc m_chkmultithread; //!< MULTI THREAD -}; - -/** - * コンストラクタ - */ -CWABPage::CWABPage() - : CPropPageProc(IDD_WAB) -{ -} -/** - * デストラクタ - */ -CWABPage::~CWABPage() -{ -} - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL CWABPage::OnInitDialog() -{ - m_awitch = np2cfg.wabasw; - m_multiwindow = np2wabcfg.multiwindow; - m_multithread = np2wabcfg.multithread; - - m_chkawitch.SubclassDlgItem(IDC_WABASWITCH, this); - if(m_awitch) - m_chkawitch.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkawitch.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_chkmultiwindow.SubclassDlgItem(IDC_WABMULTIWIN, this); - if(m_multiwindow) - m_chkmultiwindow.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkmultiwindow.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_chkmultithread.SubclassDlgItem(IDC_WABMULTHREAD, this); - if(m_multithread) - m_chkmultithread.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkmultithread.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - - m_chkawitch.SetFocus(); - - return FALSE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void CWABPage::OnOK() -{ - UINT update = 0; - - if (np2cfg.wabasw != m_awitch || np2wabcfg.multiwindow != m_multiwindow || np2wabcfg.multithread != m_multithread) - { - np2cfg.wabasw = m_awitch; - np2wabcfg.multiwindow = m_multiwindow; - np2wabcfg.multithread = m_multithread; - update |= SYS_UPDATECFG; - } - ::sysmng_update(update); -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL CWABPage::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_WABASWITCH: - m_awitch = (m_chkawitch.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - - case IDC_WABMULTIWIN: - m_multiwindow = (m_chkmultiwindow.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - - case IDC_WABMULTHREAD: - m_multithread = (m_chkmultithread.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - } - return FALSE; -} - -/** - * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT CWABPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - return CDlgProc::WindowProc(nMsg, wParam, lParam); -} - - -#if defined(SUPPORT_CL_GD5430) - -/** - * @brief CL-GD5430 設定ページ - * @param[in] hwndParent 親ウィンドウ - */ -class CGD5430Page : public CPropPageProc -{ -public: - CGD5430Page(); - virtual ~CGD5430Page(); - -protected: - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - UINT8 m_enabled; //!< 有効フラグ - UINT16 m_type; //!< 機種設定 - UINT8 m_fakecur; //!< 仮ハードウェアカーソル - CWndProc m_chkenabled; //!< ENABLED - CComboData m_cmbtype; //!< 機種 - CWndProc m_chkfakecur; //!< FAKE HARDWARE CURSOR - CWndProc m_btnreset; //!< RESET - void SetWABType(UINT16 cValue); - UINT16 GetWABType() const; -}; - -/** - * コンストラクタ - */ -CGD5430Page::CGD5430Page() - : CPropPageProc(IDD_GD5430) -{ -} -/** - * デストラクタ - */ -CGD5430Page::~CGD5430Page() -{ -} - -/** - * 機種リスト - */ -static const CComboData::Entry s_type[] = -{ - {MAKEINTRESOURCE(IDS_GD5430_BE), CIRRUS_98ID_Be}, - {MAKEINTRESOURCE(IDS_GD5430_XE), CIRRUS_98ID_Xe}, - {MAKEINTRESOURCE(IDS_GD5430_CB), CIRRUS_98ID_Cb}, - {MAKEINTRESOURCE(IDS_GD5430_CF), CIRRUS_98ID_Cf}, - {MAKEINTRESOURCE(IDS_GD5430_XE10), CIRRUS_98ID_Xe10}, - {MAKEINTRESOURCE(IDS_GD5430_CB2), CIRRUS_98ID_Cb2}, - {MAKEINTRESOURCE(IDS_GD5430_CX2), CIRRUS_98ID_Cx2}, -#ifdef SUPPORT_PCI - {MAKEINTRESOURCE(IDS_GD5430_PCI), CIRRUS_98ID_PCI}, -#endif - {MAKEINTRESOURCE(IDS_GD5430_WAB), CIRRUS_98ID_WAB}, - {MAKEINTRESOURCE(IDS_GD5430_WSN_A2F), CIRRUS_98ID_WSN_A2F}, - {MAKEINTRESOURCE(IDS_GD5430_WSN), CIRRUS_98ID_WSN}, - {MAKEINTRESOURCE(IDS_GD5430_GA98NBIC), CIRRUS_98ID_GA98NBIC}, - {MAKEINTRESOURCE(IDS_GD5430_GA98NBII), CIRRUS_98ID_GA98NBII}, - {MAKEINTRESOURCE(IDS_GD5430_GA98NBIV), CIRRUS_98ID_GA98NBIV}, - {MAKEINTRESOURCE(IDS_GD5430_96), CIRRUS_98ID_96}, - {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_G1_PCI), CIRRUS_98ID_AUTO_XE_G1_PCI}, - {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_G2_PCI), CIRRUS_98ID_AUTO_XE_G2_PCI}, - {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_G4_PCI), CIRRUS_98ID_AUTO_XE_G4_PCI}, -#ifdef SUPPORT_PCI - {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_WA_PCI), CIRRUS_98ID_AUTO_XE_WA_PCI}, - {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_WS_PCI), CIRRUS_98ID_AUTO_XE_WS_PCI}, - {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_W4_PCI), CIRRUS_98ID_AUTO_XE_W4_PCI}, -#endif - {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE10_WABS), CIRRUS_98ID_AUTO_XE10_WABS}, - {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE10_WSN2), CIRRUS_98ID_AUTO_XE10_WSN2}, - {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE10_WSN4), CIRRUS_98ID_AUTO_XE10_WSN4}, -}; - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL CGD5430Page::OnInitDialog() -{ - m_enabled = np2cfg.usegd5430; - m_type = np2cfg.gd5430type; - m_fakecur = np2cfg.gd5430fakecur; - - m_chkenabled.SubclassDlgItem(IDC_GD5430ENABLED, this); - if(m_enabled) - m_chkenabled.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkenabled.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_cmbtype.SubclassDlgItem(IDC_GD5430TYPE, this); - m_cmbtype.Add(s_type, _countof(s_type)); - SetWABType(m_type); - - m_chkfakecur.SubclassDlgItem(IDC_GD5430FAKECURSOR, this); - if(m_fakecur) - m_chkfakecur.SendMessage(BM_SETCHECK , BST_CHECKED , 0); - else - m_chkfakecur.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); - - m_cmbtype.SetFocus(); - - return FALSE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void CGD5430Page::OnOK() -{ - UINT update = 0; - - if (np2cfg.usegd5430 != m_enabled - || np2cfg.gd5430type != m_type - || np2cfg.gd5430fakecur != m_fakecur) - { - np2cfg.usegd5430 = m_enabled; - np2cfg.gd5430type = m_type; - np2cfg.gd5430fakecur = m_fakecur; - update |= SYS_UPDATECFG; - } - ::sysmng_update(update); -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL CGD5430Page::OnCommand(WPARAM wParam, LPARAM lParam) -{ - switch (LOWORD(wParam)) - { - case IDC_GD5430ENABLED: - m_enabled = (m_chkenabled.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - - case IDC_GD5430TYPE: - m_type = GetWABType(); - return TRUE; - - case IDC_GD5430FAKECURSOR: - m_fakecur = (m_chkfakecur.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); - return TRUE; - - case IDC_GD5430DEF: - m_type = CIRRUS_98ID_Xe10; - SetWABType(m_type); - return TRUE; - } - return FALSE; -} - -/** - * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT CGD5430Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - //switch (nMsg) - //{ - //} - return CDlgProc::WindowProc(nMsg, wParam, lParam); -} - -/** - * 機種を設定 - * @param[in] cValue 設定 - */ -void CGD5430Page::SetWABType(UINT16 cValue) -{ - m_cmbtype.SetCurItemData(cValue); -} - -/** - * 機種を取得 - * @return I/O - */ -UINT16 CGD5430Page::GetWABType() const -{ - return m_cmbtype.GetCurItemData(CIRRUS_98ID_Xe10); -} - -#endif - - -/** - * コンフィグ ダイアログ - * @param[in] hwndParent 親ウィンドウ - */ -void dialog_wabopt(HWND hwndParent) -{ - CPropSheetProc prop(IDS_WABOPTION, hwndParent); - - CWABPage wab; - prop.AddPage(&wab); - -#if defined(SUPPORT_CL_GD5430) - CGD5430Page gd5430; - prop.AddPage(&gd5430); -#endif - - prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; - prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); - prop.m_psh.pfnCallback = np2class_propetysheet; - prop.DoModal(); - - InvalidateRect(hwndParent, NULL, TRUE); -} - +/** + * @file d_wab.cpp + * @brief Window Accelerator Board configure dialog procedure + * + * @author $Author: SimK $ + * @date $Date: 2016/03/11 $ + */ + +#include +#include "resource.h" +#include +#include "dialog.h" +#include "c_combodata.h" +#include "np2class.h" +#include +#include +#include +#include +#include "misc\PropProc.h" +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef __cplusplus +} +#endif + +#if defined(SUPPORT_WAB) + +/** + * @brief ウィンドウアクセラレータ基本設定ページ + * @param[in] hwndParent 親ウィンドウ + */ +class CWABPage : public CPropPageProc +{ +public: + CWABPage(); + virtual ~CWABPage(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + UINT8 m_awitch; //!< アナログスイッチモード + UINT8 m_multiwindow; //!< 別窓モード + UINT8 m_multithread; //!< マルチスレッドモード + CWndProc m_chkawitch; //!< ANALOG SWITCH IC + CWndProc m_chkmultiwindow; //!< MULTI WINDOW + CWndProc m_chkmultithread; //!< MULTI THREAD +}; + +/** + * コンストラクタ + */ +CWABPage::CWABPage() + : CPropPageProc(IDD_WAB) +{ +} +/** + * デストラクタ + */ +CWABPage::~CWABPage() +{ +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL CWABPage::OnInitDialog() +{ + m_awitch = np2cfg.wabasw; + m_multiwindow = np2wabcfg.multiwindow; + m_multithread = np2wabcfg.multithread; + + m_chkawitch.SubclassDlgItem(IDC_WABASWITCH, this); + if(m_awitch) + m_chkawitch.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkawitch.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_chkmultiwindow.SubclassDlgItem(IDC_WABMULTIWIN, this); + if(m_multiwindow) + m_chkmultiwindow.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkmultiwindow.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_chkmultithread.SubclassDlgItem(IDC_WABMULTHREAD, this); + if(m_multithread) + m_chkmultithread.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkmultithread.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + + m_chkawitch.SetFocus(); + + return FALSE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void CWABPage::OnOK() +{ + UINT update = 0; + + if (np2cfg.wabasw != m_awitch || np2wabcfg.multiwindow != m_multiwindow || np2wabcfg.multithread != m_multithread) + { + np2cfg.wabasw = m_awitch; + np2wabcfg.multiwindow = m_multiwindow; + np2wabcfg.multithread = m_multithread; + update |= SYS_UPDATECFG; + } + ::sysmng_update(update); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL CWABPage::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_WABASWITCH: + m_awitch = (m_chkawitch.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + + case IDC_WABMULTIWIN: + m_multiwindow = (m_chkmultiwindow.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + + case IDC_WABMULTHREAD: + m_multithread = (m_chkmultithread.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + } + return FALSE; +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CWABPage::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + return CDlgProc::WindowProc(nMsg, wParam, lParam); +} + + +#if defined(SUPPORT_CL_GD5430) + +/** + * @brief CL-GD5430 設定ページ + * @param[in] hwndParent 親ウィンドウ + */ +class CGD5430Page : public CPropPageProc +{ +public: + CGD5430Page(); + virtual ~CGD5430Page(); + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + UINT8 m_enabled; //!< 有効フラグ + UINT16 m_type; //!< 機種設定 + UINT8 m_fakecur; //!< 仮ハードウェアカーソル + CWndProc m_chkenabled; //!< ENABLED + CComboData m_cmbtype; //!< 機種 + CWndProc m_chkfakecur; //!< FAKE HARDWARE CURSOR + CWndProc m_btnreset; //!< RESET + void SetWABType(UINT16 cValue); + UINT16 GetWABType() const; +}; + +/** + * コンストラクタ + */ +CGD5430Page::CGD5430Page() + : CPropPageProc(IDD_GD5430) +{ +} +/** + * デストラクタ + */ +CGD5430Page::~CGD5430Page() +{ +} + +/** + * 機種リスト + */ +static const CComboData::Entry s_type[] = +{ + {MAKEINTRESOURCE(IDS_GD5430_BE), CIRRUS_98ID_Be}, + {MAKEINTRESOURCE(IDS_GD5430_XE), CIRRUS_98ID_Xe}, + {MAKEINTRESOURCE(IDS_GD5430_CB), CIRRUS_98ID_Cb}, + {MAKEINTRESOURCE(IDS_GD5430_CF), CIRRUS_98ID_Cf}, + {MAKEINTRESOURCE(IDS_GD5430_XE10), CIRRUS_98ID_Xe10}, + {MAKEINTRESOURCE(IDS_GD5430_CB2), CIRRUS_98ID_Cb2}, + {MAKEINTRESOURCE(IDS_GD5430_CX2), CIRRUS_98ID_Cx2}, +#ifdef SUPPORT_PCI + {MAKEINTRESOURCE(IDS_GD5430_PCI), CIRRUS_98ID_PCI}, +#endif + {MAKEINTRESOURCE(IDS_GD5430_WAB), CIRRUS_98ID_WAB}, + {MAKEINTRESOURCE(IDS_GD5430_WSN_A2F), CIRRUS_98ID_WSN_A2F}, + {MAKEINTRESOURCE(IDS_GD5430_WSN), CIRRUS_98ID_WSN}, + {MAKEINTRESOURCE(IDS_GD5430_GA98NBIC), CIRRUS_98ID_GA98NBIC}, + {MAKEINTRESOURCE(IDS_GD5430_GA98NBII), CIRRUS_98ID_GA98NBII}, + {MAKEINTRESOURCE(IDS_GD5430_GA98NBIV), CIRRUS_98ID_GA98NBIV}, + {MAKEINTRESOURCE(IDS_GD5430_96), CIRRUS_98ID_96}, + {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_G1_PCI), CIRRUS_98ID_AUTO_XE_G1_PCI}, + {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_G2_PCI), CIRRUS_98ID_AUTO_XE_G2_PCI}, + {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_G4_PCI), CIRRUS_98ID_AUTO_XE_G4_PCI}, +#ifdef SUPPORT_PCI + {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_WA_PCI), CIRRUS_98ID_AUTO_XE_WA_PCI}, + {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_WS_PCI), CIRRUS_98ID_AUTO_XE_WS_PCI}, + {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE_W4_PCI), CIRRUS_98ID_AUTO_XE_W4_PCI}, +#endif + {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE10_WABS), CIRRUS_98ID_AUTO_XE10_WABS}, + {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE10_WSN2), CIRRUS_98ID_AUTO_XE10_WSN2}, + {MAKEINTRESOURCE(IDS_GD5430_AUTO_XE10_WSN4), CIRRUS_98ID_AUTO_XE10_WSN4}, +}; + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL CGD5430Page::OnInitDialog() +{ + m_enabled = np2cfg.usegd5430; + m_type = np2cfg.gd5430type; + m_fakecur = np2cfg.gd5430fakecur; + + m_chkenabled.SubclassDlgItem(IDC_GD5430ENABLED, this); + if(m_enabled) + m_chkenabled.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkenabled.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_cmbtype.SubclassDlgItem(IDC_GD5430TYPE, this); + m_cmbtype.Add(s_type, _countof(s_type)); + SetWABType(m_type); + + m_chkfakecur.SubclassDlgItem(IDC_GD5430FAKECURSOR, this); + if(m_fakecur) + m_chkfakecur.SendMessage(BM_SETCHECK , BST_CHECKED , 0); + else + m_chkfakecur.SendMessage(BM_SETCHECK , BST_UNCHECKED , 0); + + m_cmbtype.SetFocus(); + + return FALSE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void CGD5430Page::OnOK() +{ + UINT update = 0; + + if (np2cfg.usegd5430 != m_enabled + || np2cfg.gd5430type != m_type + || np2cfg.gd5430fakecur != m_fakecur) + { + np2cfg.usegd5430 = m_enabled; + np2cfg.gd5430type = m_type; + np2cfg.gd5430fakecur = m_fakecur; + update |= SYS_UPDATECFG; + } + ::sysmng_update(update); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL CGD5430Page::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_GD5430ENABLED: + m_enabled = (m_chkenabled.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + + case IDC_GD5430TYPE: + m_type = GetWABType(); + return TRUE; + + case IDC_GD5430FAKECURSOR: + m_fakecur = (m_chkfakecur.SendMessage(BM_GETCHECK , 0 , 0) ? 1 : 0); + return TRUE; + + case IDC_GD5430DEF: + m_type = CIRRUS_98ID_Xe10; + SetWABType(m_type); + return TRUE; + } + return FALSE; +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CGD5430Page::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + //switch (nMsg) + //{ + //} + return CDlgProc::WindowProc(nMsg, wParam, lParam); +} + +/** + * 機種を設定 + * @param[in] cValue 設定 + */ +void CGD5430Page::SetWABType(UINT16 cValue) +{ + m_cmbtype.SetCurItemData(cValue); +} + +/** + * 機種を取得 + * @return I/O + */ +UINT16 CGD5430Page::GetWABType() const +{ + return m_cmbtype.GetCurItemData(CIRRUS_98ID_Xe10); +} + +#endif + + +/** + * コンフィグ ダイアログ + * @param[in] hwndParent 親ウィンドウ + */ +void dialog_wabopt(HWND hwndParent) +{ + CPropSheetProc prop(IDS_WABOPTION, hwndParent); + + CWABPage wab; + prop.AddPage(&wab); + +#if defined(SUPPORT_CL_GD5430) + CGD5430Page gd5430; + prop.AddPage(&gd5430); +#endif + + prop.m_psh.dwFlags |= PSH_NOAPPLYNOW | PSH_USEHICON | PSH_USECALLBACK; + prop.m_psh.hIcon = LoadIcon(CWndProc::GetResourceHandle(), MAKEINTRESOURCE(IDI_ICON2)); + prop.m_psh.pfnCallback = np2class_propetysheet; + prop.DoModal(); + + InvalidateRect(hwndParent, NULL, TRUE); +} + #endif \ No newline at end of file diff --git a/windows/dialog/dialog.h b/windows/dialog/dialog.h old mode 100755 new mode 100644 index 88f45521..8e9c60f7 --- a/windows/dialog/dialog.h +++ b/windows/dialog/dialog.h @@ -1,85 +1,85 @@ -/** - * @file dialog.h - * @breif ダイアログの宣言 - */ - -#pragma once - -enum { - NEWDISKMODE_ALL = 0, - NEWDISKMODE_FD = 1, - NEWDISKMODE_HD = 2, -}; - -// d_about.cpp -void dialog_about(HWND hwndParent); - -// d_bmp.cpp -void dialog_writebmp(HWND hWnd); - -// d_txt.cpp -void dialog_writetxt(HWND hWnd); -void dialog_getTVRAM(OEMCHAR *buffer); - -// d_cfgload.cpp -int dialog_readnpcfg(HWND hWnd); - -// d_cfgsave.cpp -void dialog_writenpcfg(HWND hWnd); - -// d_clnd.cpp -void dialog_calendar(HWND hwndParent); - -// d_config.cpp -void dialog_configure(HWND hwndParent); - -// d_disk.cpp -void dialog_changefdd(HWND hWnd, REG8 drv); -void dialog_changehdd(HWND hWnd, REG8 drv); -void dialog_newdisk_ex(HWND hWnd, int mode); -void dialog_newdisk(HWND hWnd); - -// d_font.cpp -void dialog_font(HWND hWnd); - -// d_mpu98.cpp -void dialog_mpu98(HWND hwndParent); - -// d_screen.cpp -void dialog_scropt(HWND hwndParent); - -// d_serial.cpp -void dialog_serial(HWND hWnd); - -// d_sound.cpp -void dialog_sndopt(HWND hwndParent); - -// d_soundlog.cpp -void dialog_soundlog(HWND hWnd); - -// d_network.cpp -#if defined(SUPPORT_NET) -void dialog_netopt(HWND hWnd); -#endif - -// d_wab.cpp -#if defined(SUPPORT_CL_GD5430) -void dialog_wabopt(HWND hWnd); -#endif - -// d_ide.cpp -#if defined(SUPPORT_IDEIO) -void dialog_ideopt(HWND hwndParent); -#endif - -// d_hostdrv.cpp -#if defined(SUPPORT_HOSTDRV) -void dialog_hostdrvopt(HWND hwndParent); -void hostdrv_readini(); // 暫定 hostdrv.cあたりに移動すべき? -void hostdrv_writeini(); // 暫定 hostdrv.cあたりに移動すべき? -#endif - -// d_pci.cpp -#if defined(SUPPORT_PCI) -void dialog_pciopt(HWND hWnd); -#endif +/** + * @file dialog.h + * @breif ダイアログの宣言 + */ + +#pragma once + +enum { + NEWDISKMODE_ALL = 0, + NEWDISKMODE_FD = 1, + NEWDISKMODE_HD = 2, +}; + +// d_about.cpp +void dialog_about(HWND hwndParent); + +// d_bmp.cpp +void dialog_writebmp(HWND hWnd); + +// d_txt.cpp +void dialog_writetxt(HWND hWnd); +void dialog_getTVRAM(OEMCHAR *buffer); + +// d_cfgload.cpp +int dialog_readnpcfg(HWND hWnd); + +// d_cfgsave.cpp +void dialog_writenpcfg(HWND hWnd); + +// d_clnd.cpp +void dialog_calendar(HWND hwndParent); + +// d_config.cpp +void dialog_configure(HWND hwndParent); + +// d_disk.cpp +void dialog_changefdd(HWND hWnd, REG8 drv); +void dialog_changehdd(HWND hWnd, REG8 drv); +void dialog_newdisk_ex(HWND hWnd, int mode); +void dialog_newdisk(HWND hWnd); + +// d_font.cpp +void dialog_font(HWND hWnd); + +// d_mpu98.cpp +void dialog_mpu98(HWND hwndParent); + +// d_screen.cpp +void dialog_scropt(HWND hwndParent); + +// d_serial.cpp +void dialog_serial(HWND hWnd); + +// d_sound.cpp +void dialog_sndopt(HWND hwndParent); + +// d_soundlog.cpp +void dialog_soundlog(HWND hWnd); + +// d_network.cpp +#if defined(SUPPORT_NET) +void dialog_netopt(HWND hWnd); +#endif + +// d_wab.cpp +#if defined(SUPPORT_CL_GD5430) +void dialog_wabopt(HWND hWnd); +#endif + +// d_ide.cpp +#if defined(SUPPORT_IDEIO) +void dialog_ideopt(HWND hwndParent); +#endif + +// d_hostdrv.cpp +#if defined(SUPPORT_HOSTDRV) +void dialog_hostdrvopt(HWND hwndParent); +void hostdrv_readini(); // 暫定 hostdrv.cあたりに移動すべき? +void hostdrv_writeini(); // 暫定 hostdrv.cあたりに移動すべき? +#endif + +// d_pci.cpp +#if defined(SUPPORT_PCI) +void dialog_pciopt(HWND hWnd); +#endif diff --git a/windows/dialog/np2class.cpp b/windows/dialog/np2class.cpp old mode 100755 new mode 100644 index 4808864d..293507ae --- a/windows/dialog/np2class.cpp +++ b/windows/dialog/np2class.cpp @@ -1,186 +1,186 @@ -#include -#include -#include "resource.h" -#include "winloc.h" -#include "np2class.h" -#include - - -const TCHAR np2dlgclass[] = _T("np2dialog"); - - -void np2class_initialize(HINSTANCE hinst) { - - WNDCLASS wc; - - ZeroMemory(&wc, sizeof(wc)); - wc.style = CS_SAVEBITS | CS_DBLCLKS; - wc.lpfnWndProc = DefDlgProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = DLGWINDOWEXTRA; - wc.hInstance = hinst; - wc.hIcon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_ICON2)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)NULL; - wc.lpszMenuName = NULL; - wc.lpszClassName = np2dlgclass; - RegisterClass(&wc); -} - -void np2class_deinitialize(HINSTANCE hinst) { - - UnregisterClass(np2dlgclass, hinst); -} - - -// ---- - -void np2class_move(HWND hWnd, int posx, int posy, int cx, int cy) { - - RECT workrc; - - SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); - // マルチモニタ暫定対応 ver0.86 rev30 - workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); - workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); - - if (workrc.right < (posx + cx)) { - posx = workrc.right - cx; - } - if (workrc.left > posx) { - posx = workrc.left; - } - if (workrc.bottom < (posy + cy)) { - posy = workrc.bottom - cy; - } - if (workrc.top > posy) { - posy = workrc.top; - } - MoveWindow(hWnd, posx, posy, cx, cy, TRUE); -} - -// ---- - -int CALLBACK np2class_propetysheet(HWND hWndDlg, UINT uMsg, LPARAM lParam) { - - if (uMsg == PSCB_INITIALIZED) { - SetWindowLong(hWndDlg, GWL_EXSTYLE, - GetWindowLong(hWndDlg, GWL_EXSTYLE) & (~WS_EX_CONTEXTHELP)); - } - return(0); -} - - -// ---- - -void np2class_wmcreate(HWND hWnd) { - - SetWindowLongPtr(hWnd, NP2GWLP_HMENU, 0); -} - -void np2class_wmdestroy(HWND hWnd) { - - HMENU hmenu; - - hmenu = (HMENU)GetWindowLongPtr(hWnd, NP2GWLP_HMENU); - if (hmenu != NULL) { - DestroyMenu(hmenu); - SetWindowLongPtr(hWnd, NP2GWLP_HMENU, 0); - } -} - -void np2class_enablemenu(HWND hWnd, BOOL enable) { - - HMENU hmenu; - BOOL draw; - - hmenu = (HMENU)GetWindowLongPtr(hWnd, NP2GWLP_HMENU); - draw = FALSE; - if (enable) { - if (hmenu) { - SetMenu(hWnd, hmenu); - hmenu = NULL; - draw = TRUE; - } - } - else { - if (hmenu == NULL) { - hmenu = GetMenu(hWnd); - if (hmenu) { - SetMenu(hWnd, NULL); - draw = TRUE; - } - } - } - SetWindowLongPtr(hWnd, NP2GWLP_HMENU, (LONG_PTR)hmenu); - if (draw) { - DrawMenuBar(hWnd); - } -} - -void np2class_windowtype(HWND hWnd, UINT8 type) { - - RECT rect; - DWORD style; - - GetClientRect(hWnd, &rect); - style = GetWindowLong(hWnd, GWL_STYLE); - switch(type) { - case 0: - default: - style |= WS_CAPTION; - np2class_enablemenu(hWnd, TRUE); - break; - - case 1: - style |= WS_CAPTION; - np2class_enablemenu(hWnd, FALSE); - break; - - case 2: - style &= ~WS_CAPTION; - np2class_enablemenu(hWnd, FALSE); - break; - } - SetWindowLong(hWnd, GWL_STYLE, style); - SetWindowPos(hWnd, 0, 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_DRAWFRAME | - SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); - winloc_setclientsize(hWnd, - rect.right - rect.left, rect.bottom - rect.top); -} - -void np2class_frametype(HWND hWnd, UINT8 thick) { - - RECT rect; - DWORD style; - - GetClientRect(hWnd, &rect); - style = GetWindowLong(hWnd, GWL_STYLE); - if (thick) { - style |= WS_THICKFRAME; - } - else { - style &= ~WS_THICKFRAME; - } - SetWindowLong(hWnd, GWL_STYLE, style); - SetWindowPos(hWnd, 0, 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_DRAWFRAME | - SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); - winloc_setclientsize(hWnd, - rect.right - rect.left, rect.bottom - rect.top); -} - - - -HMENU np2class_gethmenu(HWND hWnd) { - - HMENU ret; - - ret = (HMENU)GetWindowLongPtr(hWnd, NP2GWLP_HMENU); - if (ret == NULL) { - ret = GetMenu(hWnd); - } - return(ret); -} - +#include +#include +#include "resource.h" +#include "winloc.h" +#include "np2class.h" +#include + + +const TCHAR np2dlgclass[] = _T("np2dialog"); + + +void np2class_initialize(HINSTANCE hinst) { + + WNDCLASS wc; + + ZeroMemory(&wc, sizeof(wc)); + wc.style = CS_SAVEBITS | CS_DBLCLKS; + wc.lpfnWndProc = DefDlgProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = DLGWINDOWEXTRA; + wc.hInstance = hinst; + wc.hIcon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_ICON2)); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = np2dlgclass; + RegisterClass(&wc); +} + +void np2class_deinitialize(HINSTANCE hinst) { + + UnregisterClass(np2dlgclass, hinst); +} + + +// ---- + +void np2class_move(HWND hWnd, int posx, int posy, int cx, int cy) { + + RECT workrc; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); + // マルチモニタ暫定対応 ver0.86 rev30 + workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); + workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); + + if (workrc.right < (posx + cx)) { + posx = workrc.right - cx; + } + if (workrc.left > posx) { + posx = workrc.left; + } + if (workrc.bottom < (posy + cy)) { + posy = workrc.bottom - cy; + } + if (workrc.top > posy) { + posy = workrc.top; + } + MoveWindow(hWnd, posx, posy, cx, cy, TRUE); +} + +// ---- + +int CALLBACK np2class_propetysheet(HWND hWndDlg, UINT uMsg, LPARAM lParam) { + + if (uMsg == PSCB_INITIALIZED) { + SetWindowLong(hWndDlg, GWL_EXSTYLE, + GetWindowLong(hWndDlg, GWL_EXSTYLE) & (~WS_EX_CONTEXTHELP)); + } + return(0); +} + + +// ---- + +void np2class_wmcreate(HWND hWnd) { + + SetWindowLongPtr(hWnd, NP2GWLP_HMENU, 0); +} + +void np2class_wmdestroy(HWND hWnd) { + + HMENU hmenu; + + hmenu = (HMENU)GetWindowLongPtr(hWnd, NP2GWLP_HMENU); + if (hmenu != NULL) { + DestroyMenu(hmenu); + SetWindowLongPtr(hWnd, NP2GWLP_HMENU, 0); + } +} + +void np2class_enablemenu(HWND hWnd, BOOL enable) { + + HMENU hmenu; + BOOL draw; + + hmenu = (HMENU)GetWindowLongPtr(hWnd, NP2GWLP_HMENU); + draw = FALSE; + if (enable) { + if (hmenu) { + SetMenu(hWnd, hmenu); + hmenu = NULL; + draw = TRUE; + } + } + else { + if (hmenu == NULL) { + hmenu = GetMenu(hWnd); + if (hmenu) { + SetMenu(hWnd, NULL); + draw = TRUE; + } + } + } + SetWindowLongPtr(hWnd, NP2GWLP_HMENU, (LONG_PTR)hmenu); + if (draw) { + DrawMenuBar(hWnd); + } +} + +void np2class_windowtype(HWND hWnd, UINT8 type) { + + RECT rect; + DWORD style; + + GetClientRect(hWnd, &rect); + style = GetWindowLong(hWnd, GWL_STYLE); + switch(type) { + case 0: + default: + style |= WS_CAPTION; + np2class_enablemenu(hWnd, TRUE); + break; + + case 1: + style |= WS_CAPTION; + np2class_enablemenu(hWnd, FALSE); + break; + + case 2: + style &= ~WS_CAPTION; + np2class_enablemenu(hWnd, FALSE); + break; + } + SetWindowLong(hWnd, GWL_STYLE, style); + SetWindowPos(hWnd, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_DRAWFRAME | + SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); + winloc_setclientsize(hWnd, + rect.right - rect.left, rect.bottom - rect.top); +} + +void np2class_frametype(HWND hWnd, UINT8 thick) { + + RECT rect; + DWORD style; + + GetClientRect(hWnd, &rect); + style = GetWindowLong(hWnd, GWL_STYLE); + if (thick) { + style |= WS_THICKFRAME; + } + else { + style &= ~WS_THICKFRAME; + } + SetWindowLong(hWnd, GWL_STYLE, style); + SetWindowPos(hWnd, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_DRAWFRAME | + SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); + winloc_setclientsize(hWnd, + rect.right - rect.left, rect.bottom - rect.top); +} + + + +HMENU np2class_gethmenu(HWND hWnd) { + + HMENU ret; + + ret = (HMENU)GetWindowLongPtr(hWnd, NP2GWLP_HMENU); + if (ret == NULL) { + ret = GetMenu(hWnd); + } + return(ret); +} + diff --git a/windows/dialog/np2class.h b/windows/dialog/np2class.h old mode 100755 new mode 100644 index 77a4baa4..41fea7f4 --- a/windows/dialog/np2class.h +++ b/windows/dialog/np2class.h @@ -1,25 +1,25 @@ - -// 猫用、拡張クラス。 - - -extern const TCHAR np2dlgclass[]; - -void np2class_initialize(HINSTANCE hinst); -void np2class_deinitialize(void); - -void np2class_move(HWND hWnd, int posx, int posy, int cx, int cy); -int CALLBACK np2class_propetysheet(HWND hWndDlg, UINT uMsg, LPARAM lParam); - - -// ---- class - -#define NP2GWLP_HMENU (0 * sizeof(LONG_PTR)) -#define NP2GWLP_SIZE (1 * sizeof(LONG_PTR)) - -void np2class_wmcreate(HWND hWnd); -void np2class_wmdestroy(HWND hWnd); -void np2class_enablemenu(HWND hWnd, BOOL enable); -void np2class_windowtype(HWND hWnd, UINT8 type); -void np2class_frametype(HWND hWnd, UINT8 thick); -HMENU np2class_gethmenu(HWND hWnd); - + +// 猫用、拡張クラス。 + + +extern const TCHAR np2dlgclass[]; + +void np2class_initialize(HINSTANCE hinst); +void np2class_deinitialize(void); + +void np2class_move(HWND hWnd, int posx, int posy, int cx, int cy); +int CALLBACK np2class_propetysheet(HWND hWndDlg, UINT uMsg, LPARAM lParam); + + +// ---- class + +#define NP2GWLP_HMENU (0 * sizeof(LONG_PTR)) +#define NP2GWLP_SIZE (1 * sizeof(LONG_PTR)) + +void np2class_wmcreate(HWND hWnd); +void np2class_wmdestroy(HWND hWnd); +void np2class_enablemenu(HWND hWnd, BOOL enable); +void np2class_windowtype(HWND hWnd, UINT8 type); +void np2class_frametype(HWND hWnd, UINT8 thick); +HMENU np2class_gethmenu(HWND hWnd); + diff --git a/windows/dosio.cpp b/windows/dosio.cpp old mode 100755 new mode 100644 index 7eedfb87..60d54f91 --- a/windows/dosio.cpp +++ b/windows/dosio.cpp @@ -1,579 +1,579 @@ -/** - * @file dosio.cpp - * @brief ファイル アクセス関数群の動作の定義を行います - */ - -#include -#include -#include - -//! カレント パス バッファ -static OEMCHAR curpath[MAX_PATH]; -static wchar_t wcurpath[MAX_PATH]; - -//! ファイル名ポインタ -static OEMCHAR *curfilep = curpath; - -/** - * 初期化 - */ -void dosio_init(void) -{ -} - -/** - * 解放 - */ -void dosio_term(void) -{ -} - -/** - * ファイルを開きます - * @param[in] lpPathName ファイル名 - * @return ファイル ハンドル - */ -FILEH DOSIOCALL file_open(const OEMCHAR* lpPathName) -{ - wchar_t wPathName[MAX_PATH]; - codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); - FILEH hFile = ::CreateFileW(wPathName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - { - hFile = ::CreateFileW(wPathName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - } - return hFile; -} - -/** - * リード オンリーでファイルを開きます - * @param[in] lpPathName ファイル名 - * @return ファイル ハンドル - */ -FILEH DOSIOCALL file_open_rb(const OEMCHAR* lpPathName) -{ - wchar_t wPathName[MAX_PATH]; - codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); - return ::CreateFileW(wPathName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); -} - -/** - * ファイルを作成します - * @param[in] lpPathName ファイル名 - * @return ファイル ハンドル - */ -FILEH DOSIOCALL file_create(const OEMCHAR* lpPathName) -{ - wchar_t wPathName[MAX_PATH]; - codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); - return ::CreateFileW(wPathName, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); -} - -/** - * ファイルのシーク - * @param[in] hFile ファイル ハンドル - * @param[in] pointer 移動すべきバイト数 - * @param[in] method 開始点 - * @return ファイルの位置 - */ -FILEPOS DOSIOCALL file_seek(FILEH hFile, FILEPOS pointer, int method) -{ -#ifdef SUPPORT_LARGE_HDD - LARGE_INTEGER li, lires; - li.QuadPart = pointer; - ::SetFilePointerEx(hFile, li, &lires, method); - return lires.QuadPart; -#else - return static_cast(::SetFilePointer(hFile, pointer, 0, method)); -#endif -} - -/** - * ファイル読み込み - * @param[in] hFile ファイル ハンドル - * @param[out] lpBuffer バッファ - * @param[in] cbBuffer バッファ サイズ - * @return 読み込みサイズ - */ -UINT DOSIOCALL file_read(FILEH hFile, void* lpBuffer, UINT cbBuffer) -{ - DWORD dwReadSize; - if (::ReadFile(hFile, lpBuffer, cbBuffer, &dwReadSize, NULL)) - { - return dwReadSize; - } - return 0; -} - -/** - * ファイル書き込み - * @param[in] hFile ファイル ハンドル - * @param[in] lpBuffer バッファ - * @param[in] cbBuffer バッファ サイズ - * @return 書き込みサイズ - */ -UINT DOSIOCALL file_write(FILEH hFile, const void* lpBuffer, UINT cbBuffer) -{ - if (cbBuffer != 0) - { - DWORD dwWrittenSize; - if (::WriteFile(hFile, lpBuffer, cbBuffer, &dwWrittenSize, NULL)) - { - return dwWrittenSize; - } - } - else - { - ::SetEndOfFile(hFile); - } - return 0; -} - -/** - * ファイル ハンドルを閉じる - * @param[in] hFile ファイル ハンドル - * @retval 0 成功 - */ -short DOSIOCALL file_close(FILEH hFile) -{ - ::CloseHandle(hFile); - return 0; -} - -/** - * ファイル サイズを得る - * @param[in] hFile ファイル ハンドル - * @return ファイル サイズ - */ -FILELEN DOSIOCALL file_getsize(FILEH hFile) -{ -#ifdef SUPPORT_LARGE_HDD - LARGE_INTEGER lires; - ::GetFileSizeEx(hFile, &lires); - return lires.QuadPart; -#else - return ::GetFileSize(hFile, NULL); -#endif -} - -/** - * FILETIME を DOSDATE/DOSTIME に変換 - * @param[in] ft ファイル タイム - * @param[out] dosdate DOSDATE - * @param[out] dostime DOSTIME - * @retval true 成功 - * @retval false 失敗 - */ -static bool convertDateTime(const FILETIME& ft, DOSDATE* dosdate, DOSTIME* dostime) -{ - FILETIME ftLocalTime; - if (!::FileTimeToLocalFileTime(&ft, &ftLocalTime)) - { - return false; - } - - SYSTEMTIME st; - if (!::FileTimeToSystemTime(&ftLocalTime, &st)) - { - return false; - } - - if (dosdate) - { - dosdate->year = st.wYear; - dosdate->month = static_cast(st.wMonth); - dosdate->day = static_cast(st.wDay); - } - if (dostime) - { - dostime->hour = static_cast(st.wHour); - dostime->minute = static_cast(st.wMinute); - dostime->second = static_cast(st.wSecond); - } - return true; -} - -/** - * ファイルのタイム スタンプを得る - * @param[in] hFile ファイル ハンドル - * @param[out] dosdate DOSDATE - * @param[out] dostime DOSTIME - * @retval 0 成功 - * @retval -1 失敗 - */ -short DOSIOCALL file_getdatetime(FILEH hFile, DOSDATE* dosdate, DOSTIME* dostime) -{ - FILETIME ft; - if (!::GetFileTime(hFile, NULL, NULL, &ft)) - { - return -1; - } - return (convertDateTime(ft, dosdate, dostime)) ? 0 : -1; -} - -/** - * ファイルの削除 - * @param[in] lpPathName ファイル名 - * @retval 0 成功 - * @retval -1 失敗 - */ -short DOSIOCALL file_delete(const OEMCHAR* lpPathName) -{ - wchar_t wPathName[MAX_PATH]; - codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); - return (::DeleteFileW(wPathName)) ? 0 : -1; -} - -/** - * ファイルの属性を得る - * @param[in] lpPathName ファイル名 - * @return ファイル属性 - */ -short DOSIOCALL file_attr(const OEMCHAR* lpPathName) -{ - wchar_t wPathName[MAX_PATH]; - codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); - return static_cast(::GetFileAttributesW(wPathName)); -} - -/** - * ファイルの移動 - * @param[in] lpExistFile ファイル名 - * @param[in] lpNewFile ファイル名 - * @retval 0 成功 - * @retval -1 失敗 - */ -short DOSIOCALL file_rename(const OEMCHAR* lpExistFile, const OEMCHAR* lpNewFile) -{ - wchar_t wExistFile[MAX_PATH]; - wchar_t wNewFile[MAX_PATH]; - codecnv_utf8toucs2((UINT16*)wExistFile, MAX_PATH, lpExistFile, -1); - codecnv_utf8toucs2((UINT16*)wNewFile, MAX_PATH, lpNewFile, -1); - return (::MoveFileW(wExistFile, wNewFile)) ? 0 : -1; -} - -/** - * ディレクトリ作成 - * @param[in] lpPathName パス - * @retval 0 成功 - * @retval -1 失敗 - */ -short DOSIOCALL file_dircreate(const OEMCHAR* lpPathName) -{ - wchar_t wPathName[MAX_PATH]; - codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); - return (::CreateDirectoryW(wPathName, NULL)) ? 0 : -1; -} - -/** - * ディレクトリ削除 - * @param[in] lpPathName パス - * @retval 0 成功 - * @retval -1 失敗 - */ -short DOSIOCALL file_dirdelete(const OEMCHAR* lpPathName) -{ - wchar_t wPathName[MAX_PATH]; - codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); - return (::RemoveDirectoryW(wPathName)) ? 0 : -1; -} - - - -// ---- カレントファイル操作 - -/** - * カレント パス設定 - * @param[in] lpPathName カレント ファイル名 - */ -void DOSIOCALL file_setcd(const OEMCHAR* lpPathName) -{ - file_cpyname(curpath, lpPathName, NELEMENTS(curpath)); - curfilep = file_getname(curpath); - *curfilep = '\0'; -} - -/** - * カレント パス取得 - * @param[in] lpFilename ファイル名 - * @return パス - */ -OEMCHAR* DOSIOCALL file_getcd(const OEMCHAR* lpFilename) -{ - file_cpyname(curfilep, lpFilename, NELEMENTS(curpath) - (int)(curfilep - curpath)); - return curpath; -} - -/** - * カレント ファイルを開きます - * @param[in] lpFilename ファイル名 - * @return ファイル ハンドル - */ -FILEH DOSIOCALL file_open_c(const OEMCHAR* lpFilename) -{ - return file_open(file_getcd(lpFilename)); -} - -/** - * リード オンリーでカレント ファイルを開きます - * @param[in] lpFilename ファイル名 - * @return ファイル ハンドル - */ - -FILEH DOSIOCALL file_open_rb_c(const OEMCHAR* lpFilename) -{ - return file_open_rb(file_getcd(lpFilename)); -} - -/** - * カレント ファイルを作成します - * @param[in] lpFilename ファイル名 - * @return ファイル ハンドル - */ -FILEH DOSIOCALL file_create_c(const OEMCHAR* lpFilename) -{ - return file_create(file_getcd(lpFilename)); -} - -/** - * カレント ファイルの削除 - * @param[in] lpFilename ファイル名 - * @retval 0 成功 - * @retval -1 失敗 - */ -short DOSIOCALL file_delete_c(const OEMCHAR* lpFilename) -{ - return file_delete(file_getcd(lpFilename)); -} - -/** - * カレント ファイルの属性を得る - * @param[in] lpFilename ファイル名 - * @return ファイル属性 - */ -short DOSIOCALL file_attr_c(const OEMCHAR* lpFilename) -{ - return file_attr(file_getcd(lpFilename)); -} - - - -// ---- ファイル検索 - -/** - * WIN32_FIND_DATA を FLINFO に変換 - * @param[in] w32fd WIN32_FIND_DATA - * @param[out] fli FLINFO - * @retval true 成功 - * @retval false 失敗 - */ -static bool DOSIOCALL setFLInfo(const WIN32_FIND_DATAW& w32fd, FLINFO *fli) -{ -#if !defined(_WIN32_WCE) - if ((w32fd.dwFileAttributes & FILEATTR_DIRECTORY) && (w32fd.cFileName[0] == '.')) - { - return false; - } -#endif // !defined(_WIN32_WCE) - - if (fli) - { - fli->caps = FLICAPS_SIZE | FLICAPS_ATTR | FLICAPS_DATE | FLICAPS_TIME; - fli->size = w32fd.nFileSizeLow; - fli->attr = w32fd.dwFileAttributes; - convertDateTime(w32fd.ftLastWriteTime, &fli->date, &fli->time); - codecnv_ucs2toutf8(fli->path, MAX_PATH, (UINT16*)w32fd.cFileName, -1); - } - return true; -} - -/** - * ファイルの検索 - * @param[in] lpPathName パス - * @param[out] fli 検索結果 - * @return ファイル検索ハンドル - */ -FLISTH DOSIOCALL file_list1st(const OEMCHAR* lpPathName, FLINFO* fli) -{ - static const OEMCHAR s_szWildCard[] = OEMTEXT("*.*"); - - OEMCHAR szPath[MAX_PATH]; - file_cpyname(szPath, lpPathName, NELEMENTS(szPath)); - file_setseparator(szPath, NELEMENTS(szPath)); - file_catname(szPath, s_szWildCard, NELEMENTS(szPath)); - WIN32_FIND_DATAW w32fd; - wchar_t wPath[MAX_PATH]; - codecnv_utf8toucs2((UINT16*)wPath, MAX_PATH, szPath, -1); - HANDLE hFile = ::FindFirstFileW(wPath, &w32fd); - if (hFile != INVALID_HANDLE_VALUE) - { - do - { - if (setFLInfo(w32fd, fli)) - { - return hFile; - } - } while(::FindNextFileW(hFile, &w32fd)); - ::FindClose(hFile); - } - return FLISTH_INVALID; -} - -/** - * ファイルの検索 - * @param[in] hList ファイル検索ハンドル - * @param[out] fli 検索結果 - * @retval SUCCESS 成功 - * @retval FAILURE 失敗 - */ -BRESULT DOSIOCALL file_listnext(FLISTH hList, FLINFO* fli) -{ - WIN32_FIND_DATAW w32fd; - while (::FindNextFileW(hList, &w32fd)) - { - if (setFLInfo(w32fd, fli)) - { - return SUCCESS; - } - } - return FAILURE; -} - -/** - * ファイル検索ハンドルを閉じる - * @param[in] hList ファイル検索ハンドル - */ -void DOSIOCALL file_listclose(FLISTH hList) -{ - ::FindClose(hList); -} - - - -// ---- ファイル名操作 - -/** - * ファイル名のポインタを得る - * @param[in] lpPathName パス - * @return ポインタ - */ -OEMCHAR* DOSIOCALL file_getname(const OEMCHAR* lpPathName) -{ - const OEMCHAR* ret = lpPathName; - while (1 /* EVER */) - { - const int cch = milstr_charsize(lpPathName); - if (cch == 0) - { - break; - } - else if ((cch == 1) && ((*lpPathName == '\\') || (*lpPathName == '/') || (*lpPathName == ':'))) - { - ret = lpPathName + 1; - } - lpPathName += cch; - } - return const_cast(ret); -} - -/** - * ファイル名を削除 - * @param[in,out] lpPathName パス - */ -void DOSIOCALL file_cutname(OEMCHAR* lpPathName) -{ - OEMCHAR* p = file_getname(lpPathName); - p[0] = '\0'; -} - -/** - * 拡張子のポインタを得る - * @param[in] lpPathName パス - * @return ポインタ - */ -OEMCHAR* DOSIOCALL file_getext(const OEMCHAR* lpPathName) -{ - const OEMCHAR* p = file_getname(lpPathName); - const OEMCHAR* q = NULL; - while (1 /* EVER */) - { - const int cch = milstr_charsize(p); - if (cch == 0) - { - break; - } - else if ((cch == 1) && (*p == '.')) - { - q = p + 1; - } - p += cch; - } - if (q == NULL) - { - q = p; - } - return const_cast(q); -} - -/** - * 拡張子を削除 - * @param[in,out] lpPathName パス - */ -void DOSIOCALL file_cutext(OEMCHAR* lpPathName) -{ - OEMCHAR* p = file_getname(lpPathName); - OEMCHAR* q = NULL; - while (1 /* EVER */) - { - const int cch = milstr_charsize(p); - if (cch == 0) - { - break; - } - else if ((cch == 1) && (*p == '.')) - { - q = p; - } - p += cch; - } - if (q) - { - *q = '\0'; - } -} - -/** - * パス セパレータを削除 - * @param[in,out] lpPathName パス - */ -void DOSIOCALL file_cutseparator(OEMCHAR* lpPathName) -{ - const int pos = OEMSTRLEN(lpPathName) - 1; - if ((pos > 0) && // 2文字以上でー - (lpPathName[pos] == '\\') && // ケツが \ でー - (!milstr_kanji2nd(lpPathName, pos)) && // 漢字の2バイト目ぢゃなくてー - ((pos != 1) || (lpPathName[0] != '\\')) && // '\\' ではなくてー - ((pos != 2) || (lpPathName[1] != ':'))) // '?:\' ではなかったら - { - lpPathName[pos] = '\0'; - } -} - -/** - * パス セパレータを追加 - * @param[in,out] lpPathName パス - * @param[in] cchPathName バッファ長 - */ -void DOSIOCALL file_setseparator(OEMCHAR* lpPathName, int cchPathName) -{ - const int pos = OEMSTRLEN(lpPathName) - 1; - if ((pos < 0) || - ((pos == 1) && (lpPathName[1] == ':')) || - ((lpPathName[pos] == '\\') && (!milstr_kanji2nd(lpPathName, pos))) || - ((pos + 2) >= cchPathName)) - { - return; - } - lpPathName[pos + 1] = '\\'; - lpPathName[pos + 2] = '\0'; -} +/** + * @file dosio.cpp + * @brief ファイル アクセス関数群の動作の定義を行います + */ + +#include +#include +#include + +//! カレント パス バッファ +static OEMCHAR curpath[MAX_PATH]; +static wchar_t wcurpath[MAX_PATH]; + +//! ファイル名ポインタ +static OEMCHAR *curfilep = curpath; + +/** + * 初期化 + */ +void dosio_init(void) +{ +} + +/** + * 解放 + */ +void dosio_term(void) +{ +} + +/** + * ファイルを開きます + * @param[in] lpPathName ファイル名 + * @return ファイル ハンドル + */ +FILEH DOSIOCALL file_open(const OEMCHAR* lpPathName) +{ + wchar_t wPathName[MAX_PATH]; + codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); + FILEH hFile = ::CreateFileW(wPathName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + hFile = ::CreateFileW(wPathName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + } + return hFile; +} + +/** + * リード オンリーでファイルを開きます + * @param[in] lpPathName ファイル名 + * @return ファイル ハンドル + */ +FILEH DOSIOCALL file_open_rb(const OEMCHAR* lpPathName) +{ + wchar_t wPathName[MAX_PATH]; + codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); + return ::CreateFileW(wPathName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); +} + +/** + * ファイルを作成します + * @param[in] lpPathName ファイル名 + * @return ファイル ハンドル + */ +FILEH DOSIOCALL file_create(const OEMCHAR* lpPathName) +{ + wchar_t wPathName[MAX_PATH]; + codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); + return ::CreateFileW(wPathName, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); +} + +/** + * ファイルのシーク + * @param[in] hFile ファイル ハンドル + * @param[in] pointer 移動すべきバイト数 + * @param[in] method 開始点 + * @return ファイルの位置 + */ +FILEPOS DOSIOCALL file_seek(FILEH hFile, FILEPOS pointer, int method) +{ +#ifdef SUPPORT_LARGE_HDD + LARGE_INTEGER li, lires; + li.QuadPart = pointer; + ::SetFilePointerEx(hFile, li, &lires, method); + return lires.QuadPart; +#else + return static_cast(::SetFilePointer(hFile, pointer, 0, method)); +#endif +} + +/** + * ファイル読み込み + * @param[in] hFile ファイル ハンドル + * @param[out] lpBuffer バッファ + * @param[in] cbBuffer バッファ サイズ + * @return 読み込みサイズ + */ +UINT DOSIOCALL file_read(FILEH hFile, void* lpBuffer, UINT cbBuffer) +{ + DWORD dwReadSize; + if (::ReadFile(hFile, lpBuffer, cbBuffer, &dwReadSize, NULL)) + { + return dwReadSize; + } + return 0; +} + +/** + * ファイル書き込み + * @param[in] hFile ファイル ハンドル + * @param[in] lpBuffer バッファ + * @param[in] cbBuffer バッファ サイズ + * @return 書き込みサイズ + */ +UINT DOSIOCALL file_write(FILEH hFile, const void* lpBuffer, UINT cbBuffer) +{ + if (cbBuffer != 0) + { + DWORD dwWrittenSize; + if (::WriteFile(hFile, lpBuffer, cbBuffer, &dwWrittenSize, NULL)) + { + return dwWrittenSize; + } + } + else + { + ::SetEndOfFile(hFile); + } + return 0; +} + +/** + * ファイル ハンドルを閉じる + * @param[in] hFile ファイル ハンドル + * @retval 0 成功 + */ +short DOSIOCALL file_close(FILEH hFile) +{ + ::CloseHandle(hFile); + return 0; +} + +/** + * ファイル サイズを得る + * @param[in] hFile ファイル ハンドル + * @return ファイル サイズ + */ +FILELEN DOSIOCALL file_getsize(FILEH hFile) +{ +#ifdef SUPPORT_LARGE_HDD + LARGE_INTEGER lires; + ::GetFileSizeEx(hFile, &lires); + return lires.QuadPart; +#else + return ::GetFileSize(hFile, NULL); +#endif +} + +/** + * FILETIME を DOSDATE/DOSTIME に変換 + * @param[in] ft ファイル タイム + * @param[out] dosdate DOSDATE + * @param[out] dostime DOSTIME + * @retval true 成功 + * @retval false 失敗 + */ +static bool convertDateTime(const FILETIME& ft, DOSDATE* dosdate, DOSTIME* dostime) +{ + FILETIME ftLocalTime; + if (!::FileTimeToLocalFileTime(&ft, &ftLocalTime)) + { + return false; + } + + SYSTEMTIME st; + if (!::FileTimeToSystemTime(&ftLocalTime, &st)) + { + return false; + } + + if (dosdate) + { + dosdate->year = st.wYear; + dosdate->month = static_cast(st.wMonth); + dosdate->day = static_cast(st.wDay); + } + if (dostime) + { + dostime->hour = static_cast(st.wHour); + dostime->minute = static_cast(st.wMinute); + dostime->second = static_cast(st.wSecond); + } + return true; +} + +/** + * ファイルのタイム スタンプを得る + * @param[in] hFile ファイル ハンドル + * @param[out] dosdate DOSDATE + * @param[out] dostime DOSTIME + * @retval 0 成功 + * @retval -1 失敗 + */ +short DOSIOCALL file_getdatetime(FILEH hFile, DOSDATE* dosdate, DOSTIME* dostime) +{ + FILETIME ft; + if (!::GetFileTime(hFile, NULL, NULL, &ft)) + { + return -1; + } + return (convertDateTime(ft, dosdate, dostime)) ? 0 : -1; +} + +/** + * ファイルの削除 + * @param[in] lpPathName ファイル名 + * @retval 0 成功 + * @retval -1 失敗 + */ +short DOSIOCALL file_delete(const OEMCHAR* lpPathName) +{ + wchar_t wPathName[MAX_PATH]; + codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); + return (::DeleteFileW(wPathName)) ? 0 : -1; +} + +/** + * ファイルの属性を得る + * @param[in] lpPathName ファイル名 + * @return ファイル属性 + */ +short DOSIOCALL file_attr(const OEMCHAR* lpPathName) +{ + wchar_t wPathName[MAX_PATH]; + codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); + return static_cast(::GetFileAttributesW(wPathName)); +} + +/** + * ファイルの移動 + * @param[in] lpExistFile ファイル名 + * @param[in] lpNewFile ファイル名 + * @retval 0 成功 + * @retval -1 失敗 + */ +short DOSIOCALL file_rename(const OEMCHAR* lpExistFile, const OEMCHAR* lpNewFile) +{ + wchar_t wExistFile[MAX_PATH]; + wchar_t wNewFile[MAX_PATH]; + codecnv_utf8toucs2((UINT16*)wExistFile, MAX_PATH, lpExistFile, -1); + codecnv_utf8toucs2((UINT16*)wNewFile, MAX_PATH, lpNewFile, -1); + return (::MoveFileW(wExistFile, wNewFile)) ? 0 : -1; +} + +/** + * ディレクトリ作成 + * @param[in] lpPathName パス + * @retval 0 成功 + * @retval -1 失敗 + */ +short DOSIOCALL file_dircreate(const OEMCHAR* lpPathName) +{ + wchar_t wPathName[MAX_PATH]; + codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); + return (::CreateDirectoryW(wPathName, NULL)) ? 0 : -1; +} + +/** + * ディレクトリ削除 + * @param[in] lpPathName パス + * @retval 0 成功 + * @retval -1 失敗 + */ +short DOSIOCALL file_dirdelete(const OEMCHAR* lpPathName) +{ + wchar_t wPathName[MAX_PATH]; + codecnv_utf8toucs2((UINT16*)wPathName, MAX_PATH, lpPathName, -1); + return (::RemoveDirectoryW(wPathName)) ? 0 : -1; +} + + + +// ---- カレントファイル操作 + +/** + * カレント パス設定 + * @param[in] lpPathName カレント ファイル名 + */ +void DOSIOCALL file_setcd(const OEMCHAR* lpPathName) +{ + file_cpyname(curpath, lpPathName, NELEMENTS(curpath)); + curfilep = file_getname(curpath); + *curfilep = '\0'; +} + +/** + * カレント パス取得 + * @param[in] lpFilename ファイル名 + * @return パス + */ +OEMCHAR* DOSIOCALL file_getcd(const OEMCHAR* lpFilename) +{ + file_cpyname(curfilep, lpFilename, NELEMENTS(curpath) - (int)(curfilep - curpath)); + return curpath; +} + +/** + * カレント ファイルを開きます + * @param[in] lpFilename ファイル名 + * @return ファイル ハンドル + */ +FILEH DOSIOCALL file_open_c(const OEMCHAR* lpFilename) +{ + return file_open(file_getcd(lpFilename)); +} + +/** + * リード オンリーでカレント ファイルを開きます + * @param[in] lpFilename ファイル名 + * @return ファイル ハンドル + */ + +FILEH DOSIOCALL file_open_rb_c(const OEMCHAR* lpFilename) +{ + return file_open_rb(file_getcd(lpFilename)); +} + +/** + * カレント ファイルを作成します + * @param[in] lpFilename ファイル名 + * @return ファイル ハンドル + */ +FILEH DOSIOCALL file_create_c(const OEMCHAR* lpFilename) +{ + return file_create(file_getcd(lpFilename)); +} + +/** + * カレント ファイルの削除 + * @param[in] lpFilename ファイル名 + * @retval 0 成功 + * @retval -1 失敗 + */ +short DOSIOCALL file_delete_c(const OEMCHAR* lpFilename) +{ + return file_delete(file_getcd(lpFilename)); +} + +/** + * カレント ファイルの属性を得る + * @param[in] lpFilename ファイル名 + * @return ファイル属性 + */ +short DOSIOCALL file_attr_c(const OEMCHAR* lpFilename) +{ + return file_attr(file_getcd(lpFilename)); +} + + + +// ---- ファイル検索 + +/** + * WIN32_FIND_DATA を FLINFO に変換 + * @param[in] w32fd WIN32_FIND_DATA + * @param[out] fli FLINFO + * @retval true 成功 + * @retval false 失敗 + */ +static bool DOSIOCALL setFLInfo(const WIN32_FIND_DATAW& w32fd, FLINFO *fli) +{ +#if !defined(_WIN32_WCE) + if ((w32fd.dwFileAttributes & FILEATTR_DIRECTORY) && (w32fd.cFileName[0] == '.')) + { + return false; + } +#endif // !defined(_WIN32_WCE) + + if (fli) + { + fli->caps = FLICAPS_SIZE | FLICAPS_ATTR | FLICAPS_DATE | FLICAPS_TIME; + fli->size = w32fd.nFileSizeLow; + fli->attr = w32fd.dwFileAttributes; + convertDateTime(w32fd.ftLastWriteTime, &fli->date, &fli->time); + codecnv_ucs2toutf8(fli->path, MAX_PATH, (UINT16*)w32fd.cFileName, -1); + } + return true; +} + +/** + * ファイルの検索 + * @param[in] lpPathName パス + * @param[out] fli 検索結果 + * @return ファイル検索ハンドル + */ +FLISTH DOSIOCALL file_list1st(const OEMCHAR* lpPathName, FLINFO* fli) +{ + static const OEMCHAR s_szWildCard[] = OEMTEXT("*.*"); + + OEMCHAR szPath[MAX_PATH]; + file_cpyname(szPath, lpPathName, NELEMENTS(szPath)); + file_setseparator(szPath, NELEMENTS(szPath)); + file_catname(szPath, s_szWildCard, NELEMENTS(szPath)); + WIN32_FIND_DATAW w32fd; + wchar_t wPath[MAX_PATH]; + codecnv_utf8toucs2((UINT16*)wPath, MAX_PATH, szPath, -1); + HANDLE hFile = ::FindFirstFileW(wPath, &w32fd); + if (hFile != INVALID_HANDLE_VALUE) + { + do + { + if (setFLInfo(w32fd, fli)) + { + return hFile; + } + } while(::FindNextFileW(hFile, &w32fd)); + ::FindClose(hFile); + } + return FLISTH_INVALID; +} + +/** + * ファイルの検索 + * @param[in] hList ファイル検索ハンドル + * @param[out] fli 検索結果 + * @retval SUCCESS 成功 + * @retval FAILURE 失敗 + */ +BRESULT DOSIOCALL file_listnext(FLISTH hList, FLINFO* fli) +{ + WIN32_FIND_DATAW w32fd; + while (::FindNextFileW(hList, &w32fd)) + { + if (setFLInfo(w32fd, fli)) + { + return SUCCESS; + } + } + return FAILURE; +} + +/** + * ファイル検索ハンドルを閉じる + * @param[in] hList ファイル検索ハンドル + */ +void DOSIOCALL file_listclose(FLISTH hList) +{ + ::FindClose(hList); +} + + + +// ---- ファイル名操作 + +/** + * ファイル名のポインタを得る + * @param[in] lpPathName パス + * @return ポインタ + */ +OEMCHAR* DOSIOCALL file_getname(const OEMCHAR* lpPathName) +{ + const OEMCHAR* ret = lpPathName; + while (1 /* EVER */) + { + const int cch = milstr_charsize(lpPathName); + if (cch == 0) + { + break; + } + else if ((cch == 1) && ((*lpPathName == '\\') || (*lpPathName == '/') || (*lpPathName == ':'))) + { + ret = lpPathName + 1; + } + lpPathName += cch; + } + return const_cast(ret); +} + +/** + * ファイル名を削除 + * @param[in,out] lpPathName パス + */ +void DOSIOCALL file_cutname(OEMCHAR* lpPathName) +{ + OEMCHAR* p = file_getname(lpPathName); + p[0] = '\0'; +} + +/** + * 拡張子のポインタを得る + * @param[in] lpPathName パス + * @return ポインタ + */ +OEMCHAR* DOSIOCALL file_getext(const OEMCHAR* lpPathName) +{ + const OEMCHAR* p = file_getname(lpPathName); + const OEMCHAR* q = NULL; + while (1 /* EVER */) + { + const int cch = milstr_charsize(p); + if (cch == 0) + { + break; + } + else if ((cch == 1) && (*p == '.')) + { + q = p + 1; + } + p += cch; + } + if (q == NULL) + { + q = p; + } + return const_cast(q); +} + +/** + * 拡張子を削除 + * @param[in,out] lpPathName パス + */ +void DOSIOCALL file_cutext(OEMCHAR* lpPathName) +{ + OEMCHAR* p = file_getname(lpPathName); + OEMCHAR* q = NULL; + while (1 /* EVER */) + { + const int cch = milstr_charsize(p); + if (cch == 0) + { + break; + } + else if ((cch == 1) && (*p == '.')) + { + q = p; + } + p += cch; + } + if (q) + { + *q = '\0'; + } +} + +/** + * パス セパレータを削除 + * @param[in,out] lpPathName パス + */ +void DOSIOCALL file_cutseparator(OEMCHAR* lpPathName) +{ + const int pos = OEMSTRLEN(lpPathName) - 1; + if ((pos > 0) && // 2文字以上でー + (lpPathName[pos] == '\\') && // ケツが \ でー + (!milstr_kanji2nd(lpPathName, pos)) && // 漢字の2バイト目ぢゃなくてー + ((pos != 1) || (lpPathName[0] != '\\')) && // '\\' ではなくてー + ((pos != 2) || (lpPathName[1] != ':'))) // '?:\' ではなかったら + { + lpPathName[pos] = '\0'; + } +} + +/** + * パス セパレータを追加 + * @param[in,out] lpPathName パス + * @param[in] cchPathName バッファ長 + */ +void DOSIOCALL file_setseparator(OEMCHAR* lpPathName, int cchPathName) +{ + const int pos = OEMSTRLEN(lpPathName) - 1; + if ((pos < 0) || + ((pos == 1) && (lpPathName[1] == ':')) || + ((lpPathName[pos] == '\\') && (!milstr_kanji2nd(lpPathName, pos))) || + ((pos + 2) >= cchPathName)) + { + return; + } + lpPathName[pos + 1] = '\\'; + lpPathName[pos + 2] = '\0'; +} diff --git a/windows/dosio.h b/windows/dosio.h old mode 100755 new mode 100644 index a1dc4b97..5b9f0ff0 --- a/windows/dosio.h +++ b/windows/dosio.h @@ -1,143 +1,143 @@ -/** - * @file dosio.h - * @brief ファイル アクセス関数群の宣言およびインターフェイスの定義をします - */ - -#pragma once - -/*! コール規約 */ -#define DOSIOCALL __stdcall - - -#define FILEH HANDLE /*!< ファイル ハンドル */ -#define FILEH_INVALID (INVALID_HANDLE_VALUE) /*!< ファイル エラー値 */ - -#define FLISTH HANDLE /*!< ファイル検索ハンドル */ -#define FLISTH_INVALID (INVALID_HANDLE_VALUE) /*!< ファイル検索エラー値 */ - -/** - * ファイル ポインタ移動の開始点 - */ -enum -{ - FSEEK_SET = 0, /*!< ファイルの先頭 */ - FSEEK_CUR = 1, /*!< 現在の位置 */ - FSEEK_END = 2 /*!< ファイルの終わり */ -}; - -/** - * ファイル属性 - */ -enum -{ - FILEATTR_READONLY = 0x01, /*!< 読み取り専用 */ - FILEATTR_HIDDEN = 0x02, /*!< 隠しファイル */ - FILEATTR_SYSTEM = 0x04, /*!< システム ファイル */ - FILEATTR_VOLUME = 0x08, /*!< ヴォリューム */ - FILEATTR_DIRECTORY = 0x10, /*!< ディレクトリ */ - FILEATTR_ARCHIVE = 0x20, /*!< アーカイブ ファイル */ - FILEATTR_NORMAL = 0x80 -}; - -/** - * ファイル検索フラグ - */ -enum -{ - FLICAPS_SIZE = 0x0001, /*!< サイズ */ - FLICAPS_ATTR = 0x0002, /*!< 属性 */ - FLICAPS_DATE = 0x0004, /*!< 日付 */ - FLICAPS_TIME = 0x0008 /*!< 時刻 */ -}; - -/** - * @brief DOSDATE 構造体 - */ -struct _dosdate -{ - UINT16 year; /*!< cx 年 */ - UINT8 month; /*!< dh 月 */ - UINT8 day; /*!< dl 日 */ -}; -typedef struct _dosdate DOSDATE; /*!< DOSDATE 定義 */ - -/** - * @brief DOSTIME 構造体 - */ -struct _dostime -{ - UINT8 hour; /*!< ch 時 */ - UINT8 minute; /*!< cl 分 */ - UINT8 second; /*!< dh 秒 */ -}; -typedef struct _dostime DOSTIME; /*!< DOSTIME 定義 */ - -/** - * @brief ファイル検索結果 - */ -struct _flinfo -{ - UINT caps; /*!< フラグ */ - UINT32 size; /*!< サイズ */ - UINT32 attr; /*!< 属性 */ - DOSDATE date; /*!< 日付 */ - DOSTIME time; /*!< 時刻 */ - OEMCHAR path[MAX_PATH]; /*!< ファイル名 */ -}; -typedef struct _flinfo FLINFO; /*!< FLINFO 定義 */ - -/* DOSIO:関数の準備 */ -void dosio_init(void); -void dosio_term(void); - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* ファイル操作 */ -FILEH DOSIOCALL file_open(const OEMCHAR* lpPathName); -FILEH DOSIOCALL file_open_rb(const OEMCHAR* lpPathName); -FILEH DOSIOCALL file_create(const OEMCHAR* lpPathName); -FILEPOS DOSIOCALL file_seek(FILEH hFile, FILEPOS pointer, int method); -UINT DOSIOCALL file_read(FILEH hFile, void *data, UINT length); -UINT DOSIOCALL file_write(FILEH hFile, const void *data, UINT length); -short DOSIOCALL file_close(FILEH hFile); -FILELEN DOSIOCALL file_getsize(FILEH hFile); -short DOSIOCALL file_getdatetime(FILEH hFile, DOSDATE* dosdate, DOSTIME* dostime); -short DOSIOCALL file_delete(const OEMCHAR* lpPathName); -short DOSIOCALL file_attr(const OEMCHAR* lpPathName); -short DOSIOCALL file_rename(const OEMCHAR* lpExistFile, const OEMCHAR* lpNewFile); -short DOSIOCALL file_dircreate(const OEMCHAR* lpPathName); -short DOSIOCALL file_dirdelete(const OEMCHAR* lpPathName); - -/* カレントファイル操作 */ -void DOSIOCALL file_setcd(const OEMCHAR* lpPathName); -OEMCHAR* DOSIOCALL file_getcd(const OEMCHAR* lpPathName); -FILEH DOSIOCALL file_open_c(const OEMCHAR* lpFilename); -FILEH DOSIOCALL file_open_rb_c(const OEMCHAR* lpFilename); -FILEH DOSIOCALL file_create_c(const OEMCHAR* lpFilename); -short DOSIOCALL file_delete_c(const OEMCHAR* lpFilename); -short DOSIOCALL file_attr_c(const OEMCHAR* lpFilename); - -/* ファイル検索 */ -FLISTH DOSIOCALL file_list1st(const OEMCHAR* lpPathName, FLINFO* fli); -BRESULT DOSIOCALL file_listnext(FLISTH hList, FLINFO* fli); -void DOSIOCALL file_listclose(FLISTH hList); - -#define file_cpyname(a, b, c) milstr_ncpy(a, b, c) /*!< ファイル名コピー */ -#define file_catname(a, b, c) milstr_ncat(a, b, c) /*!< ファイル名追加 */ -#define file_cmpname(a, b) milstr_cmp(a, b) /*!< ファイル名比較 */ -OEMCHAR* DOSIOCALL file_getname(const OEMCHAR* lpPathName); -void DOSIOCALL file_cutname(OEMCHAR* lpPathName); -OEMCHAR* DOSIOCALL file_getext(const OEMCHAR* lpPathName); -void DOSIOCALL file_cutext(OEMCHAR* lpPathName); -void DOSIOCALL file_cutseparator(OEMCHAR* lpPathName); -void DOSIOCALL file_setseparator(OEMCHAR* lpPathName, int cchPathName); - -#ifdef __cplusplus -} -#endif - -#define file_createex(p, t) file_create(p) /*!< ファイル作成 */ -#define file_createex_c(p, t) file_create_c(p) /*!< ファイル作成 */ +/** + * @file dosio.h + * @brief ファイル アクセス関数群の宣言およびインターフェイスの定義をします + */ + +#pragma once + +/*! コール規約 */ +#define DOSIOCALL __stdcall + + +#define FILEH HANDLE /*!< ファイル ハンドル */ +#define FILEH_INVALID (INVALID_HANDLE_VALUE) /*!< ファイル エラー値 */ + +#define FLISTH HANDLE /*!< ファイル検索ハンドル */ +#define FLISTH_INVALID (INVALID_HANDLE_VALUE) /*!< ファイル検索エラー値 */ + +/** + * ファイル ポインタ移動の開始点 + */ +enum +{ + FSEEK_SET = 0, /*!< ファイルの先頭 */ + FSEEK_CUR = 1, /*!< 現在の位置 */ + FSEEK_END = 2 /*!< ファイルの終わり */ +}; + +/** + * ファイル属性 + */ +enum +{ + FILEATTR_READONLY = 0x01, /*!< 読み取り専用 */ + FILEATTR_HIDDEN = 0x02, /*!< 隠しファイル */ + FILEATTR_SYSTEM = 0x04, /*!< システム ファイル */ + FILEATTR_VOLUME = 0x08, /*!< ヴォリューム */ + FILEATTR_DIRECTORY = 0x10, /*!< ディレクトリ */ + FILEATTR_ARCHIVE = 0x20, /*!< アーカイブ ファイル */ + FILEATTR_NORMAL = 0x80 +}; + +/** + * ファイル検索フラグ + */ +enum +{ + FLICAPS_SIZE = 0x0001, /*!< サイズ */ + FLICAPS_ATTR = 0x0002, /*!< 属性 */ + FLICAPS_DATE = 0x0004, /*!< 日付 */ + FLICAPS_TIME = 0x0008 /*!< 時刻 */ +}; + +/** + * @brief DOSDATE 構造体 + */ +struct _dosdate +{ + UINT16 year; /*!< cx 年 */ + UINT8 month; /*!< dh 月 */ + UINT8 day; /*!< dl 日 */ +}; +typedef struct _dosdate DOSDATE; /*!< DOSDATE 定義 */ + +/** + * @brief DOSTIME 構造体 + */ +struct _dostime +{ + UINT8 hour; /*!< ch 時 */ + UINT8 minute; /*!< cl 分 */ + UINT8 second; /*!< dh 秒 */ +}; +typedef struct _dostime DOSTIME; /*!< DOSTIME 定義 */ + +/** + * @brief ファイル検索結果 + */ +struct _flinfo +{ + UINT caps; /*!< フラグ */ + UINT32 size; /*!< サイズ */ + UINT32 attr; /*!< 属性 */ + DOSDATE date; /*!< 日付 */ + DOSTIME time; /*!< 時刻 */ + OEMCHAR path[MAX_PATH]; /*!< ファイル名 */ +}; +typedef struct _flinfo FLINFO; /*!< FLINFO 定義 */ + +/* DOSIO:関数の準備 */ +void dosio_init(void); +void dosio_term(void); + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* ファイル操作 */ +FILEH DOSIOCALL file_open(const OEMCHAR* lpPathName); +FILEH DOSIOCALL file_open_rb(const OEMCHAR* lpPathName); +FILEH DOSIOCALL file_create(const OEMCHAR* lpPathName); +FILEPOS DOSIOCALL file_seek(FILEH hFile, FILEPOS pointer, int method); +UINT DOSIOCALL file_read(FILEH hFile, void *data, UINT length); +UINT DOSIOCALL file_write(FILEH hFile, const void *data, UINT length); +short DOSIOCALL file_close(FILEH hFile); +FILELEN DOSIOCALL file_getsize(FILEH hFile); +short DOSIOCALL file_getdatetime(FILEH hFile, DOSDATE* dosdate, DOSTIME* dostime); +short DOSIOCALL file_delete(const OEMCHAR* lpPathName); +short DOSIOCALL file_attr(const OEMCHAR* lpPathName); +short DOSIOCALL file_rename(const OEMCHAR* lpExistFile, const OEMCHAR* lpNewFile); +short DOSIOCALL file_dircreate(const OEMCHAR* lpPathName); +short DOSIOCALL file_dirdelete(const OEMCHAR* lpPathName); + +/* カレントファイル操作 */ +void DOSIOCALL file_setcd(const OEMCHAR* lpPathName); +OEMCHAR* DOSIOCALL file_getcd(const OEMCHAR* lpPathName); +FILEH DOSIOCALL file_open_c(const OEMCHAR* lpFilename); +FILEH DOSIOCALL file_open_rb_c(const OEMCHAR* lpFilename); +FILEH DOSIOCALL file_create_c(const OEMCHAR* lpFilename); +short DOSIOCALL file_delete_c(const OEMCHAR* lpFilename); +short DOSIOCALL file_attr_c(const OEMCHAR* lpFilename); + +/* ファイル検索 */ +FLISTH DOSIOCALL file_list1st(const OEMCHAR* lpPathName, FLINFO* fli); +BRESULT DOSIOCALL file_listnext(FLISTH hList, FLINFO* fli); +void DOSIOCALL file_listclose(FLISTH hList); + +#define file_cpyname(a, b, c) milstr_ncpy(a, b, c) /*!< ファイル名コピー */ +#define file_catname(a, b, c) milstr_ncat(a, b, c) /*!< ファイル名追加 */ +#define file_cmpname(a, b) milstr_cmp(a, b) /*!< ファイル名比較 */ +OEMCHAR* DOSIOCALL file_getname(const OEMCHAR* lpPathName); +void DOSIOCALL file_cutname(OEMCHAR* lpPathName); +OEMCHAR* DOSIOCALL file_getext(const OEMCHAR* lpPathName); +void DOSIOCALL file_cutext(OEMCHAR* lpPathName); +void DOSIOCALL file_cutseparator(OEMCHAR* lpPathName); +void DOSIOCALL file_setseparator(OEMCHAR* lpPathName, int cchPathName); + +#ifdef __cplusplus +} +#endif + +#define file_createex(p, t) file_create(p) /*!< ファイル作成 */ +#define file_createex_c(p, t) file_create_c(p) /*!< ファイル作成 */ diff --git a/windows/ext/c86ctl/c86ctl.h b/windows/ext/c86ctl/c86ctl.h old mode 100755 new mode 100644 index 56abf735..14e8c09f --- a/windows/ext/c86ctl/c86ctl.h +++ b/windows/ext/c86ctl/c86ctl.h @@ -1,185 +1,185 @@ -/*** - c86ctl - - Copyright (c) 2009-2012, honet. All rights reserved. - This software is licensed under the BSD license. - - honet.kk(at)gmail.com - */ - - -#ifndef _C86CTL_H -#define _C86CTL_H - -#include -#include "cbus_boardtype.h" - -#ifdef __cplusplus -namespace c86ctl{ -#endif - -/*----------------------------------------------------------------------------*/ -/* 定数定義 */ -/*----------------------------------------------------------------------------*/ -#define C86CTL_ERR_NONE 0 -#define C86CTL_ERR_UNKNOWN -1 -#define C86CTL_ERR_INVALID_PARAM -2 -#define C86CTL_ERR_UNSUPPORTED -3 -#define C86CTL_ERR_NODEVICE -1000 -#define C86CTL_ERR_NOT_IMPLEMENTED -9999 - -enum ChipType { - CHIP_UNKNOWN = 0x0000, - - CHIP_OPNA = 0x00001, - CHIP_YM2608 = 0x00001, - CHIP_YM2608NOADPCM = 0x10001, - CHIP_OPM = 0x00002, - CHIP_YM2151 = 0x00002, - CHIP_OPN3L = 0x00003, - CHIP_YMF288 = 0x00003, - CHIP_OPL3 = 0x00004, - CHIP_YMF262 = 0x00004, - CHIP_OPLL = 0x00005, - CHIP_YM2413 = 0x00005, - - CHIP_SN76489 = 0x00006, - CHIP_SN76496 = 0x10006, - CHIP_AY38910 = 0x00007, - CHIP_YM2149 = 0x10007, - CHIP_YM2203 = 0x00008, - CHIP_YM2612 = 0x00009, - CHIP_YM3526 = 0x0000a, - CHIP_YM3812 = 0x0000b, - CHIP_YMF271 = 0x0000c, - CHIP_YMF278B = 0x0000d, - CHIP_YMZ280B = 0x0000e, - CHIP_YMF297 = 0x0000f, - CHIP_YM2610B = 0x00010, - CHIP_Y8950 = 0x00020, - CHIP_Y8950ADPCM = 0x10020, - CHIP_YM3438 = 0x00021 -}; - - -/*----------------------------------------------------------------------------*/ -/* 構造体定義 */ -/*----------------------------------------------------------------------------*/ -struct Devinfo{ - char Devname[16]; - char Rev; - char Serial[15]; -}; - -/*----------------------------------------------------------------------------*/ -/* Interface定義 */ -/*----------------------------------------------------------------------------*/ -// IRealChipBase {5C457918-E66D-4AC1-8CB5-B91C4704DF79} -static const GUID IID_IRealChipBase = -{ 0x5c457918, 0xe66d, 0x4ac1, { 0x8c, 0xb5, 0xb9, 0x1c, 0x47, 0x4, 0xdf, 0x79 } }; - -interface IRealChipBase : public IUnknown -{ - virtual int __stdcall initialize(void) = 0; - virtual int __stdcall deinitialize(void) = 0; - virtual int __stdcall getNumberOfChip(void) = 0; - virtual HRESULT __stdcall getChipInterface( int id, REFIID riid, void** ppi ) = 0; -}; - -// --------------------------------------- -// DEPRECATED. use IRealChip3 instead. -// IRealChip {F959C007-6B4D-46F3-BB60-9B0897C7E642} -static const GUID IID_IRealChip = -{ 0xf959c007, 0x6b4d, 0x46f3, { 0xbb, 0x60, 0x9b, 0x8, 0x97, 0xc7, 0xe6, 0x42 } }; -interface IRealChip : public IUnknown -{ -public: - virtual int __stdcall reset(void) = 0; - virtual void __stdcall out( UINT addr, UCHAR data ) = 0; - virtual UCHAR __stdcall in( UINT addr ) = 0; -}; - -// DEPRECATED. use IRealChip3 instead. -// IRealChip2 {BEFA830A-0DF3-46E4-A79E-FABB78E80357} -static const GUID IID_IRealChip2 = -{ 0xbefa830a, 0xdf3, 0x46e4, { 0xa7, 0x9e, 0xfa, 0xbb, 0x78, 0xe8, 0x3, 0x57 } }; - -interface IRealChip2 : public IRealChip -{ - virtual int __stdcall getChipStatus( UINT addr, UCHAR *status ) = 0; - virtual void __stdcall directOut(UINT addr, UCHAR data) = 0; -}; - -// IRealChip3 {761DB10B-2432-4747-AC75-0EA6D9336797} -static const GUID IID_IRealChip3 = -{ 0x761db10b, 0x2432, 0x4747, { 0xac, 0x75, 0xe, 0xa6, 0xd9, 0x33, 0x67, 0x97 } }; - -interface IRealChip3 : public IRealChip2 -{ - virtual int __stdcall getChipType( enum ChipType *type ) = 0; -}; - - -// --------------------------------------- -// DEPRECATED. use IGimic2 instead. -// IGimic {175C7DA0-8AA5-4173-96DA-BB43B8EB8F17} -static const GUID IID_IGimic = -{ 0x175c7da0, 0x8aa5, 0x4173, { 0x96, 0xda, 0xbb, 0x43, 0xb8, 0xeb, 0x8f, 0x17 } }; -interface IGimic : public IUnknown -{ - virtual int __stdcall getFWVer( UINT *major, UINT *minor, UINT *revision, UINT *build ) = 0; - virtual int __stdcall getMBInfo( struct Devinfo *info ) = 0; - virtual int __stdcall getModuleInfo( struct Devinfo *info ) = 0; - virtual int __stdcall setSSGVolume(UCHAR vol) = 0; - virtual int __stdcall getSSGVolume(UCHAR *vol) = 0; - virtual int __stdcall setPLLClock(UINT clock) = 0; - virtual int __stdcall getPLLClock(UINT *clock) = 0; -}; - -// IGimic2 {47141A01-15F5-4BF5-9554-CA7AACD54BB8} -static const GUID IID_IGimic2 = -{ 0x47141a01, 0x15f5, 0x4bf5, { 0x95, 0x54, 0xca, 0x7a, 0xac, 0xd5, 0x4b, 0xb8 } }; -interface IGimic2 : public IGimic -{ - virtual int __stdcall getModuleType( enum ChipType *type ) = 0; -}; - - -// --------------------------------------- -// 仮定義です。まだ使えません・・・ごめん。 -// IC86Usb {312481E2-A93C-4A2F-87CA-CE3AC1096ED5} -static const GUID IID_IC86BOX = -{ 0x312481e2, 0xa93c, 0x4a2f, { 0x87, 0xca, 0xce, 0x3a, 0xc1, 0x9, 0x6e, 0xd5 } }; -interface IC86Box : public IUnknown -{ - virtual int __stdcall getFWVer(UINT *major, UINT *minor, UINT *revision, UINT *build) = 0; - virtual int __stdcall getBoardType(CBUS_BOARD_TYPE *type) = 0; - virtual int __stdcall getSlotIndex() = 0; - virtual int __stdcall writeBoardControl(UINT index, UINT val) = 0; -}; - - -/*----------------------------------------------------------------------------*/ -/* 公開関数定義 */ -/*----------------------------------------------------------------------------*/ -#ifdef __cplusplus -extern "C" { -#endif - -HRESULT WINAPI CreateInstance( REFIID riid, void** ppi ); - - -int WINAPI c86ctl_initialize(void); // DEPRECATED -int WINAPI c86ctl_deinitialize(void); // DEPRECATED -int WINAPI c86ctl_reset(void); // DEPRECATED -void WINAPI c86ctl_out( UINT addr, UCHAR data ); // DEPRECATED -UCHAR WINAPI c86ctl_in( UINT addr ); // DEPRECATED - - - -#ifdef __cplusplus -}; -}; -#endif - -#endif +/*** + c86ctl + + Copyright (c) 2009-2012, honet. All rights reserved. + This software is licensed under the BSD license. + + honet.kk(at)gmail.com + */ + + +#ifndef _C86CTL_H +#define _C86CTL_H + +#include +#include "cbus_boardtype.h" + +#ifdef __cplusplus +namespace c86ctl{ +#endif + +/*----------------------------------------------------------------------------*/ +/* 定数定義 */ +/*----------------------------------------------------------------------------*/ +#define C86CTL_ERR_NONE 0 +#define C86CTL_ERR_UNKNOWN -1 +#define C86CTL_ERR_INVALID_PARAM -2 +#define C86CTL_ERR_UNSUPPORTED -3 +#define C86CTL_ERR_NODEVICE -1000 +#define C86CTL_ERR_NOT_IMPLEMENTED -9999 + +enum ChipType { + CHIP_UNKNOWN = 0x0000, + + CHIP_OPNA = 0x00001, + CHIP_YM2608 = 0x00001, + CHIP_YM2608NOADPCM = 0x10001, + CHIP_OPM = 0x00002, + CHIP_YM2151 = 0x00002, + CHIP_OPN3L = 0x00003, + CHIP_YMF288 = 0x00003, + CHIP_OPL3 = 0x00004, + CHIP_YMF262 = 0x00004, + CHIP_OPLL = 0x00005, + CHIP_YM2413 = 0x00005, + + CHIP_SN76489 = 0x00006, + CHIP_SN76496 = 0x10006, + CHIP_AY38910 = 0x00007, + CHIP_YM2149 = 0x10007, + CHIP_YM2203 = 0x00008, + CHIP_YM2612 = 0x00009, + CHIP_YM3526 = 0x0000a, + CHIP_YM3812 = 0x0000b, + CHIP_YMF271 = 0x0000c, + CHIP_YMF278B = 0x0000d, + CHIP_YMZ280B = 0x0000e, + CHIP_YMF297 = 0x0000f, + CHIP_YM2610B = 0x00010, + CHIP_Y8950 = 0x00020, + CHIP_Y8950ADPCM = 0x10020, + CHIP_YM3438 = 0x00021 +}; + + +/*----------------------------------------------------------------------------*/ +/* 構造体定義 */ +/*----------------------------------------------------------------------------*/ +struct Devinfo{ + char Devname[16]; + char Rev; + char Serial[15]; +}; + +/*----------------------------------------------------------------------------*/ +/* Interface定義 */ +/*----------------------------------------------------------------------------*/ +// IRealChipBase {5C457918-E66D-4AC1-8CB5-B91C4704DF79} +static const GUID IID_IRealChipBase = +{ 0x5c457918, 0xe66d, 0x4ac1, { 0x8c, 0xb5, 0xb9, 0x1c, 0x47, 0x4, 0xdf, 0x79 } }; + +interface IRealChipBase : public IUnknown +{ + virtual int __stdcall initialize(void) = 0; + virtual int __stdcall deinitialize(void) = 0; + virtual int __stdcall getNumberOfChip(void) = 0; + virtual HRESULT __stdcall getChipInterface( int id, REFIID riid, void** ppi ) = 0; +}; + +// --------------------------------------- +// DEPRECATED. use IRealChip3 instead. +// IRealChip {F959C007-6B4D-46F3-BB60-9B0897C7E642} +static const GUID IID_IRealChip = +{ 0xf959c007, 0x6b4d, 0x46f3, { 0xbb, 0x60, 0x9b, 0x8, 0x97, 0xc7, 0xe6, 0x42 } }; +interface IRealChip : public IUnknown +{ +public: + virtual int __stdcall reset(void) = 0; + virtual void __stdcall out( UINT addr, UCHAR data ) = 0; + virtual UCHAR __stdcall in( UINT addr ) = 0; +}; + +// DEPRECATED. use IRealChip3 instead. +// IRealChip2 {BEFA830A-0DF3-46E4-A79E-FABB78E80357} +static const GUID IID_IRealChip2 = +{ 0xbefa830a, 0xdf3, 0x46e4, { 0xa7, 0x9e, 0xfa, 0xbb, 0x78, 0xe8, 0x3, 0x57 } }; + +interface IRealChip2 : public IRealChip +{ + virtual int __stdcall getChipStatus( UINT addr, UCHAR *status ) = 0; + virtual void __stdcall directOut(UINT addr, UCHAR data) = 0; +}; + +// IRealChip3 {761DB10B-2432-4747-AC75-0EA6D9336797} +static const GUID IID_IRealChip3 = +{ 0x761db10b, 0x2432, 0x4747, { 0xac, 0x75, 0xe, 0xa6, 0xd9, 0x33, 0x67, 0x97 } }; + +interface IRealChip3 : public IRealChip2 +{ + virtual int __stdcall getChipType( enum ChipType *type ) = 0; +}; + + +// --------------------------------------- +// DEPRECATED. use IGimic2 instead. +// IGimic {175C7DA0-8AA5-4173-96DA-BB43B8EB8F17} +static const GUID IID_IGimic = +{ 0x175c7da0, 0x8aa5, 0x4173, { 0x96, 0xda, 0xbb, 0x43, 0xb8, 0xeb, 0x8f, 0x17 } }; +interface IGimic : public IUnknown +{ + virtual int __stdcall getFWVer( UINT *major, UINT *minor, UINT *revision, UINT *build ) = 0; + virtual int __stdcall getMBInfo( struct Devinfo *info ) = 0; + virtual int __stdcall getModuleInfo( struct Devinfo *info ) = 0; + virtual int __stdcall setSSGVolume(UCHAR vol) = 0; + virtual int __stdcall getSSGVolume(UCHAR *vol) = 0; + virtual int __stdcall setPLLClock(UINT clock) = 0; + virtual int __stdcall getPLLClock(UINT *clock) = 0; +}; + +// IGimic2 {47141A01-15F5-4BF5-9554-CA7AACD54BB8} +static const GUID IID_IGimic2 = +{ 0x47141a01, 0x15f5, 0x4bf5, { 0x95, 0x54, 0xca, 0x7a, 0xac, 0xd5, 0x4b, 0xb8 } }; +interface IGimic2 : public IGimic +{ + virtual int __stdcall getModuleType( enum ChipType *type ) = 0; +}; + + +// --------------------------------------- +// 仮定義です。まだ使えません・・・ごめん。 +// IC86Usb {312481E2-A93C-4A2F-87CA-CE3AC1096ED5} +static const GUID IID_IC86BOX = +{ 0x312481e2, 0xa93c, 0x4a2f, { 0x87, 0xca, 0xce, 0x3a, 0xc1, 0x9, 0x6e, 0xd5 } }; +interface IC86Box : public IUnknown +{ + virtual int __stdcall getFWVer(UINT *major, UINT *minor, UINT *revision, UINT *build) = 0; + virtual int __stdcall getBoardType(CBUS_BOARD_TYPE *type) = 0; + virtual int __stdcall getSlotIndex() = 0; + virtual int __stdcall writeBoardControl(UINT index, UINT val) = 0; +}; + + +/*----------------------------------------------------------------------------*/ +/* 公開関数定義 */ +/*----------------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif + +HRESULT WINAPI CreateInstance( REFIID riid, void** ppi ); + + +int WINAPI c86ctl_initialize(void); // DEPRECATED +int WINAPI c86ctl_deinitialize(void); // DEPRECATED +int WINAPI c86ctl_reset(void); // DEPRECATED +void WINAPI c86ctl_out( UINT addr, UCHAR data ); // DEPRECATED +UCHAR WINAPI c86ctl_in( UINT addr ); // DEPRECATED + + + +#ifdef __cplusplus +}; +}; +#endif + +#endif diff --git a/windows/ext/c86ctl/c86ctlif.cpp b/windows/ext/c86ctl/c86ctlif.cpp old mode 100755 new mode 100644 index c0c7f1b9..10d67db1 --- a/windows/ext/c86ctl/c86ctlif.cpp +++ b/windows/ext/c86ctl/c86ctlif.cpp @@ -1,311 +1,311 @@ -/** - * @file c86ctlif.cpp - * @brief G.I.M.I.C アクセス クラスの動作の定義を行います - */ - -#include -#include "c86ctlif.h" -#include "c86ctl.h" - -using namespace c86ctl; - -/*! インタフェイス */ -typedef HRESULT (WINAPI * FnCreateInstance)(REFIID riid, LPVOID* ppi); - -/** - * コンストラクタ - */ -C86CtlIf::C86CtlIf() - : m_hModule(NULL) - , m_pChipBase(NULL) -{ -} - -/** - * デストラクタ - */ -C86CtlIf::~C86CtlIf() -{ - Deinitialize(); -} - -/** - * 初期化 - * @retval true 成功 - * @retval false 失敗 - */ -bool C86CtlIf::Initialize() -{ - if (m_hModule) - { - return false; - } - - do - { - /* DLL 読み込み */ - m_hModule = ::LoadLibrary(TEXT("c86ctl.dll")); - if (m_hModule == NULL) - { - break; - } - FnCreateInstance CreateInstance = reinterpret_cast(::GetProcAddress(m_hModule, "CreateInstance")); - if (CreateInstance == NULL) - { - break; - } - - /* インスタンス作成 */ - (*CreateInstance)(IID_IRealChipBase, reinterpret_cast(&m_pChipBase)); - if (m_pChipBase == NULL) - { - break; - } - - /* 初期化 */ - if (m_pChipBase->initialize() != C86CTL_ERR_NONE) - { - break; - } - return true; - - } while (0 /*CONSTCOND*/); - - Deinitialize(); - return false; -} - -/** - * 解放 - */ -void C86CtlIf::Deinitialize() -{ - if (m_pChipBase) - { - while (!m_chips.empty()) - { - std::map::iterator it = m_chips.begin(); - delete it->second; - } - - m_pChipBase->deinitialize(); - m_pChipBase = NULL; - } - - if (m_hModule) - { - ::FreeLibrary(m_hModule); - m_hModule = NULL; - } -} - -/** - * 音源リセット - */ -void C86CtlIf::Reset() -{ -} - -/** - * インターフェイス取得 - * @param[in] nChipType タイプ - * @param[in] nClock クロック - * @return インスタンス - */ -IExternalChip* C86CtlIf::GetInterface(IExternalChip::ChipType nChipType, UINT nClock) -{ - const bool bInitialized = Initialize(); - - do - { - if (m_pChipBase == NULL) - { - break; - } - - /* 音源を探す */ - const int nDeviceCount = m_pChipBase->getNumberOfChip(); - for (int i = 0; i < nDeviceCount; i++) - { - /* 使用中? */ - if (m_chips.find(i) != m_chips.end()) - { - continue; - } - - /* チップを探す */ - IRealChip* pRealChip = NULL; - m_pChipBase->getChipInterface(i, IID_IRealChip, reinterpret_cast(&pRealChip)); - if (pRealChip == NULL) - { - continue; - } - - /* G.I.M.I.C 判定 */ - IGimic* pGimic = NULL; - m_pChipBase->getChipInterface(i, IID_IGimic, reinterpret_cast(&pGimic)); - if (pGimic) - { - Devinfo info; - if (pGimic->getModuleInfo(&info) == C86CTL_ERR_NONE) - { - IExternalChip::ChipType nRealChipType = IExternalChip::kNone; - if (!memcmp(info.Devname, "GMC-OPN3L", 9)) - { - nRealChipType = IExternalChip::kYMF288; - } - else if (!memcmp(info.Devname, "GMC-OPNA", 8)) - { - nRealChipType = IExternalChip::kYM2608; - } - else if (!memcmp(info.Devname, "GMC-OPL3", 8)) - { - nRealChipType = IExternalChip::kYMF262; - } - else if (!memcmp(info.Devname, "GMC-OPM", 7)) - { - nRealChipType = IExternalChip::kYM2151; - } - - if (nChipType == nRealChipType) - { - /* サウンドチップ取得できた */ - Chip* pChip = new Chip(this, pRealChip, pGimic, nRealChipType, nClock); - m_chips[i] = pChip; - return pChip; - } - } - } - - /* その他の判定 */ - IRealChip3* pChip3 = NULL; - m_pChipBase->getChipInterface(i, IID_IRealChip3, reinterpret_cast(&pChip3)); - if (pChip3 != NULL) - { - c86ctl::ChipType nType = CHIP_UNKNOWN; - pChip3->getChipType(&nType); - - IExternalChip::ChipType nRealChipType = IExternalChip::kNone; - if (nType == CHIP_YM2203) - { - nRealChipType = IExternalChip::kYM2203; - } - else if (nType == CHIP_OPNA) - { - nRealChipType = IExternalChip::kYM2608; - } - else if ((nType == CHIP_YM2608NOADPCM) || (nType == CHIP_OPN3L)) - { - nRealChipType = IExternalChip::kYMF288; - } - else if (nType == CHIP_Y8950ADPCM) - { - nRealChipType = IExternalChip::kY8950; - } - if (nChipType == nRealChipType) - { - /* サウンドチップ取得できた */ - Chip* pChip = new Chip(this, pChip3, NULL, nRealChipType, nClock); - m_chips[i] = pChip; - return pChip; - } - } - } - } while (false /*CONSTCOND*/); - - if (bInitialized) - { -// Deinitialize(); - } - return NULL; -} - -/** - * 解放 - * @param[in] pChip チップ - */ -void C86CtlIf::Detach(C86CtlIf::Chip* pChip) -{ - std::map::iterator it = m_chips.begin(); - while (it != m_chips.end()) - { - if (it->second == pChip) - { - it = m_chips.erase(it); - } - else - { - ++it; - } - } -} - -/* ---- チップ */ - -/** - * コンストラクタ - * @param[in] pC86CtlIf C86CtlIf インスタンス - * @param[in] pRealChip チップ インスタンス - * @param[in] pGimic G.I.M.I.C インスタンス - * @param[in] nChipType チップ タイプ - * @param[in] nClock クロック - */ -C86CtlIf::Chip::Chip(C86CtlIf* pC86CtlIf, c86ctl::IRealChip* pRealChip, c86ctl::IGimic* pGimic, ChipType nChipType, UINT nClock) - : m_pC86CtlIf(pC86CtlIf) - , m_pRealChip(pRealChip) - , m_pGimic(pGimic) - , m_nChipType(nChipType) - , m_nClock(nClock) -{ -} - -/** - * デストラクタ - */ -C86CtlIf::Chip::~Chip() -{ - m_pC86CtlIf->Detach(this); -} - -/** - * Get chip type - * @return The type of the chip - */ -IExternalChip::ChipType C86CtlIf::Chip::GetChipType() -{ - return m_nChipType; -} - -/** - * リセット - */ -void C86CtlIf::Chip::Reset() -{ - m_pRealChip->reset(); - if (m_pGimic) - { - m_pGimic->setPLLClock(m_nClock); - m_pGimic->setSSGVolume(31); - } -} - -/** - * レジスタ書き込み - * @param[in] nAddr アドレス - * @param[in] cData データ - */ -void C86CtlIf::Chip::WriteRegister(UINT nAddr, UINT8 cData) -{ - m_pRealChip->out(nAddr, cData); -} - -/** - * メッセージ - * @param[in] nMessage メッセージ - * @param[in] nParameter パラメータ - * @return リザルト - */ -INTPTR C86CtlIf::Chip::Message(UINT nMessage, INTPTR nParameter) -{ - return 0; -} +/** + * @file c86ctlif.cpp + * @brief G.I.M.I.C アクセス クラスの動作の定義を行います + */ + +#include +#include "c86ctlif.h" +#include "c86ctl.h" + +using namespace c86ctl; + +/*! インタフェイス */ +typedef HRESULT (WINAPI * FnCreateInstance)(REFIID riid, LPVOID* ppi); + +/** + * コンストラクタ + */ +C86CtlIf::C86CtlIf() + : m_hModule(NULL) + , m_pChipBase(NULL) +{ +} + +/** + * デストラクタ + */ +C86CtlIf::~C86CtlIf() +{ + Deinitialize(); +} + +/** + * 初期化 + * @retval true 成功 + * @retval false 失敗 + */ +bool C86CtlIf::Initialize() +{ + if (m_hModule) + { + return false; + } + + do + { + /* DLL 読み込み */ + m_hModule = ::LoadLibrary(TEXT("c86ctl.dll")); + if (m_hModule == NULL) + { + break; + } + FnCreateInstance CreateInstance = reinterpret_cast(::GetProcAddress(m_hModule, "CreateInstance")); + if (CreateInstance == NULL) + { + break; + } + + /* インスタンス作成 */ + (*CreateInstance)(IID_IRealChipBase, reinterpret_cast(&m_pChipBase)); + if (m_pChipBase == NULL) + { + break; + } + + /* 初期化 */ + if (m_pChipBase->initialize() != C86CTL_ERR_NONE) + { + break; + } + return true; + + } while (0 /*CONSTCOND*/); + + Deinitialize(); + return false; +} + +/** + * 解放 + */ +void C86CtlIf::Deinitialize() +{ + if (m_pChipBase) + { + while (!m_chips.empty()) + { + std::map::iterator it = m_chips.begin(); + delete it->second; + } + + m_pChipBase->deinitialize(); + m_pChipBase = NULL; + } + + if (m_hModule) + { + ::FreeLibrary(m_hModule); + m_hModule = NULL; + } +} + +/** + * 音源リセット + */ +void C86CtlIf::Reset() +{ +} + +/** + * インターフェイス取得 + * @param[in] nChipType タイプ + * @param[in] nClock クロック + * @return インスタンス + */ +IExternalChip* C86CtlIf::GetInterface(IExternalChip::ChipType nChipType, UINT nClock) +{ + const bool bInitialized = Initialize(); + + do + { + if (m_pChipBase == NULL) + { + break; + } + + /* 音源を探す */ + const int nDeviceCount = m_pChipBase->getNumberOfChip(); + for (int i = 0; i < nDeviceCount; i++) + { + /* 使用中? */ + if (m_chips.find(i) != m_chips.end()) + { + continue; + } + + /* チップを探す */ + IRealChip* pRealChip = NULL; + m_pChipBase->getChipInterface(i, IID_IRealChip, reinterpret_cast(&pRealChip)); + if (pRealChip == NULL) + { + continue; + } + + /* G.I.M.I.C 判定 */ + IGimic* pGimic = NULL; + m_pChipBase->getChipInterface(i, IID_IGimic, reinterpret_cast(&pGimic)); + if (pGimic) + { + Devinfo info; + if (pGimic->getModuleInfo(&info) == C86CTL_ERR_NONE) + { + IExternalChip::ChipType nRealChipType = IExternalChip::kNone; + if (!memcmp(info.Devname, "GMC-OPN3L", 9)) + { + nRealChipType = IExternalChip::kYMF288; + } + else if (!memcmp(info.Devname, "GMC-OPNA", 8)) + { + nRealChipType = IExternalChip::kYM2608; + } + else if (!memcmp(info.Devname, "GMC-OPL3", 8)) + { + nRealChipType = IExternalChip::kYMF262; + } + else if (!memcmp(info.Devname, "GMC-OPM", 7)) + { + nRealChipType = IExternalChip::kYM2151; + } + + if (nChipType == nRealChipType) + { + /* サウンドチップ取得できた */ + Chip* pChip = new Chip(this, pRealChip, pGimic, nRealChipType, nClock); + m_chips[i] = pChip; + return pChip; + } + } + } + + /* その他の判定 */ + IRealChip3* pChip3 = NULL; + m_pChipBase->getChipInterface(i, IID_IRealChip3, reinterpret_cast(&pChip3)); + if (pChip3 != NULL) + { + c86ctl::ChipType nType = CHIP_UNKNOWN; + pChip3->getChipType(&nType); + + IExternalChip::ChipType nRealChipType = IExternalChip::kNone; + if (nType == CHIP_YM2203) + { + nRealChipType = IExternalChip::kYM2203; + } + else if (nType == CHIP_OPNA) + { + nRealChipType = IExternalChip::kYM2608; + } + else if ((nType == CHIP_YM2608NOADPCM) || (nType == CHIP_OPN3L)) + { + nRealChipType = IExternalChip::kYMF288; + } + else if (nType == CHIP_Y8950ADPCM) + { + nRealChipType = IExternalChip::kY8950; + } + if (nChipType == nRealChipType) + { + /* サウンドチップ取得できた */ + Chip* pChip = new Chip(this, pChip3, NULL, nRealChipType, nClock); + m_chips[i] = pChip; + return pChip; + } + } + } + } while (false /*CONSTCOND*/); + + if (bInitialized) + { +// Deinitialize(); + } + return NULL; +} + +/** + * 解放 + * @param[in] pChip チップ + */ +void C86CtlIf::Detach(C86CtlIf::Chip* pChip) +{ + std::map::iterator it = m_chips.begin(); + while (it != m_chips.end()) + { + if (it->second == pChip) + { + it = m_chips.erase(it); + } + else + { + ++it; + } + } +} + +/* ---- チップ */ + +/** + * コンストラクタ + * @param[in] pC86CtlIf C86CtlIf インスタンス + * @param[in] pRealChip チップ インスタンス + * @param[in] pGimic G.I.M.I.C インスタンス + * @param[in] nChipType チップ タイプ + * @param[in] nClock クロック + */ +C86CtlIf::Chip::Chip(C86CtlIf* pC86CtlIf, c86ctl::IRealChip* pRealChip, c86ctl::IGimic* pGimic, ChipType nChipType, UINT nClock) + : m_pC86CtlIf(pC86CtlIf) + , m_pRealChip(pRealChip) + , m_pGimic(pGimic) + , m_nChipType(nChipType) + , m_nClock(nClock) +{ +} + +/** + * デストラクタ + */ +C86CtlIf::Chip::~Chip() +{ + m_pC86CtlIf->Detach(this); +} + +/** + * Get chip type + * @return The type of the chip + */ +IExternalChip::ChipType C86CtlIf::Chip::GetChipType() +{ + return m_nChipType; +} + +/** + * リセット + */ +void C86CtlIf::Chip::Reset() +{ + m_pRealChip->reset(); + if (m_pGimic) + { + m_pGimic->setPLLClock(m_nClock); + m_pGimic->setSSGVolume(31); + } +} + +/** + * レジスタ書き込み + * @param[in] nAddr アドレス + * @param[in] cData データ + */ +void C86CtlIf::Chip::WriteRegister(UINT nAddr, UINT8 cData) +{ + m_pRealChip->out(nAddr, cData); +} + +/** + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParameter パラメータ + * @return リザルト + */ +INTPTR C86CtlIf::Chip::Message(UINT nMessage, INTPTR nParameter) +{ + return 0; +} diff --git a/windows/ext/c86ctl/c86ctlif.h b/windows/ext/c86ctl/c86ctlif.h old mode 100755 new mode 100644 index 4e205367..4141abc5 --- a/windows/ext/c86ctl/c86ctlif.h +++ b/windows/ext/c86ctl/c86ctlif.h @@ -1,59 +1,59 @@ -/** - * @file c86ctlif.h - * @brief G.I.M.I.C アクセス クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include "../externalchip.h" - -namespace c86ctl -{ - interface IRealChipBase; - interface IGimic; - interface IRealChip; -} - -/** - * @brief G.I.M.I.C アクセス クラス - */ -class C86CtlIf -{ -public: - C86CtlIf(); - ~C86CtlIf(); - bool Initialize(); - void Deinitialize(); - void Reset(); - IExternalChip* GetInterface(IExternalChip::ChipType nChipType, UINT nClock); - -private: - HMODULE m_hModule; /*!< モジュール ハンドル */ - c86ctl::IRealChipBase* m_pChipBase; /*!< チップ ベース インスタンス */ - - /** - * @brief チップ クラス - */ - class Chip : public IExternalChip - { - public: - Chip(C86CtlIf* pC86CtlIf, c86ctl::IRealChip* pRealChip, c86ctl::IGimic* pGimic, ChipType nChipType, UINT nClock); - virtual ~Chip(); - virtual ChipType GetChipType(); - virtual void Reset(); - virtual void WriteRegister(UINT nAddr, UINT8 cData); - virtual INTPTR Message(UINT nMessage, INTPTR nParameter = 0); - - private: - C86CtlIf* m_pC86CtlIf; /*!< C86Ctl インスタンス */ - c86ctl::IRealChip* m_pRealChip; /*!< チップ インスタンス */ - c86ctl::IGimic* m_pGimic; /*!< G.I.M.I.C インスタンス */ - ChipType m_nChipType; /*!< チップ タイプ */ - UINT m_nClock; /*!< チップ クロック */ - }; - - std::map m_chips; /*!< チップ */ - void Detach(Chip* pChip); - friend class Chip; -}; +/** + * @file c86ctlif.h + * @brief G.I.M.I.C アクセス クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include "../externalchip.h" + +namespace c86ctl +{ + interface IRealChipBase; + interface IGimic; + interface IRealChip; +} + +/** + * @brief G.I.M.I.C アクセス クラス + */ +class C86CtlIf +{ +public: + C86CtlIf(); + ~C86CtlIf(); + bool Initialize(); + void Deinitialize(); + void Reset(); + IExternalChip* GetInterface(IExternalChip::ChipType nChipType, UINT nClock); + +private: + HMODULE m_hModule; /*!< モジュール ハンドル */ + c86ctl::IRealChipBase* m_pChipBase; /*!< チップ ベース インスタンス */ + + /** + * @brief チップ クラス + */ + class Chip : public IExternalChip + { + public: + Chip(C86CtlIf* pC86CtlIf, c86ctl::IRealChip* pRealChip, c86ctl::IGimic* pGimic, ChipType nChipType, UINT nClock); + virtual ~Chip(); + virtual ChipType GetChipType(); + virtual void Reset(); + virtual void WriteRegister(UINT nAddr, UINT8 cData); + virtual INTPTR Message(UINT nMessage, INTPTR nParameter = 0); + + private: + C86CtlIf* m_pC86CtlIf; /*!< C86Ctl インスタンス */ + c86ctl::IRealChip* m_pRealChip; /*!< チップ インスタンス */ + c86ctl::IGimic* m_pGimic; /*!< G.I.M.I.C インスタンス */ + ChipType m_nChipType; /*!< チップ タイプ */ + UINT m_nClock; /*!< チップ クロック */ + }; + + std::map m_chips; /*!< チップ */ + void Detach(Chip* pChip); + friend class Chip; +}; diff --git a/windows/ext/c86ctl/cbus_boardtype.h b/windows/ext/c86ctl/cbus_boardtype.h old mode 100755 new mode 100644 index 8e383a59..acc98af6 --- a/windows/ext/c86ctl/cbus_boardtype.h +++ b/windows/ext/c86ctl/cbus_boardtype.h @@ -1,278 +1,278 @@ -/*** - c86ctl - - Copyright (c) 2009-2012, honet. All rights reserved. - This software is licensed under the BSD license. - - honet.kk(at)gmail.com - */ - -#ifndef CBUS_BOARDTYPE_H__ -#define CBUS_BOARDTYPE_H__ - -// CBUSボード種別定義 -// 上位16bit: アドレス種別などバリエーション -// 下位16bit: ボード種別 (うち下位4bitは搭載チップによる大雑把な分類) -typedef enum { - // 何だか分からない or 何も刺さっていない - CBUS_BOARD_UNKNOWN = 0x0, - - // PSG系 ========================================================= - // (未対応) NEC PC-9801-14 - // アドレスデコーダ: 14bit - CBUS_BOARD_14 = 0x00001, - - // (未対応) システムサコム AMD-98 - // アドレスデコーダ: 16bit(未検証) - // SOUNDID(0xA460) : 無し - // IDADDR: 0x00f0, 00xx x000 1101 xaaa (0x00d0~0x0df) - CBUS_BOARD_AMD98 = 0x00011, - - // YM2203(OPN)系 ================================================= - // NEC PC-9801-26, 26K - // アドレスデコーダ: 12bit - // SOUNDID(0xA460) : 無し - // IOADDR: 0188h/018Ah - CBUS_BOARD_26 = 0x00002, - - // (未テスト) SNE Sound Orchestra : YM2203, YM3812 - // アドレスデコーダ: 不明 - // SOUNDID(0xA460) : 無し - // IOADDR(OPN) : 0188h/018Ah or 0088h/008Ah - // IOADDR(YM3812): 018Ch/018Eh or 008Ch/008Eh - CBUS_BOARD_SOUND_ORCHESTRA = 0x00012, - CBUS_BOARD_SOUND_ORCHESTRA_0188H = 0x00012, - CBUS_BOARD_SOUND_ORCHESTRA_0088H = 0x10012, - - // (未テスト) SNE Sound Orchestra L : YM2203, YM3812 - // アドレスデコーダ: 12bit - // SOUNDID(0xA460) : 無し - // IOADDR(OPN) : 0188h/018Ah or 0088h/008Ah - // IOADDR(Y8950): 018Ch/018Eh or 008Ch/008Eh - CBUS_BOARD_SOUND_ORCHESTRA_L = 0x00022, - CBUS_BOARD_SOUND_ORCHESTRA_L_0188H = 0x00022, - CBUS_BOARD_SOUND_ORCHESTRA_L_0088H = 0x10022, - - // (未テスト) SNE Sound Orchestra V : YM2203, Y8950(w/ADPCM-RAM) - // アドレスデコーダ: 12bit - // SOUNDID(0xA460) : 無し - // IOADDR(OPN) : 0188h/018Ah or 0088h/008Ah - // IOADDR(Y8950): 018Ch/018Eh or 008Ch/008Eh - CBUS_BOARD_SOUND_ORCHESTRA_V = 0x00032, - CBUS_BOARD_SOUND_ORCHESTRA_V_0188H = 0x00032, - CBUS_BOARD_SOUND_ORCHESTRA_V_0088H = 0x10032, - - // (未テスト) SNE Sound Orchestra VS : YM2203, Y8950(w/ADPCM-RAM) - // アドレスデコーダ: 12bit - // SOUNDID(0xA460) : 無し - // IOADDR(OPN) : 0188h/018Ah or 0088h/008Ah - // IOADDR(Y8950): 018Ch/018Eh or 008Ch/008Eh - CBUS_BOARD_SOUND_ORCHESTRA_VS = 0x00042, - CBUS_BOARD_SOUND_ORCHESTRA_VS_0188H = 0x00042, - CBUS_BOARD_SOUND_ORCHESTRA_VS_0088H = 0x10042, - - // (未テスト) SNE Sound Orchestra LS : YM2203, Y8950 - // アドレスデコーダ: 不明 - // SOUNDID(0xA460) : 無し - // IOADDR(OPN): 0188h/018Ah or 0088h/008Ah - // IOADDR(Y8950): 018Ch/018Eh or 008Ch/008Eh - CBUS_BOARD_SOUND_ORCHESTRA_LS = 0x00052, - CBUS_BOARD_SOUND_ORCHESTRA_LS_0188H = 0x00052, - CBUS_BOARD_SOUND_ORCHESTRA_LS_0088H = 0x10052, - - // (未テスト) SNE Sound Orchestra MATE : YM2203, Y8950 - CBUS_BOARD_SOUND_ORCHESTRA_MATE = 0x00062, - // (未テスト) SNE Multimedia Orchestra : YM2203, YM262M - CBUS_BOARD_MULTIMEDIA_ORCHESTRA = 0x00072, - - // (未テスト) SNE Littele Orchestra : YM2203 - // アドレスデコーダ: 不明 - // SOUNDID(0xA460) : 無し - // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh - CBUS_BOARD_LITTLE_ORCHESTRA = 0x00082, - CBUS_BOARD_LITTLE_ORCHESTRA_0188H = 0x00082, - CBUS_BOARD_LITTLE_ORCHESTRA_0088H = 0x10082, - - // (未テスト) SNE Littele Orchestra L : YM2203 - // アドレスデコーダ: 不明 - // SOUNDID(0xA460) : 無し - // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh - CBUS_BOARD_LITTLE_ORCHESTRA_L = 0x00092, - CBUS_BOARD_LITTLE_ORCHESTRA_L_0188H = 0x00092, - CBUS_BOARD_LITTLE_ORCHESTRA_L_0088H = 0x01092, - - // (未テスト) SNE Littele Orchestra RS : YM2203 - // アドレスデコーダ: 不明 - // SOUNDID(0xA460) : 無し - // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh - CBUS_BOARD_LITTLE_ORCHESTRA_RS = 0x000a2, - CBUS_BOARD_LITTLE_ORCHESTRA_RS_0188H= 0x000a2, - CBUS_BOARD_LITTLE_ORCHESTRA_RS_0088H= 0x100a2, - - // (未テスト) SNE Littele Orchestra LS : YM2203 - // アドレスデコーダ: 不明 - // SOUNDID(0xA460) : 無し - // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh - CBUS_BOARD_LITTLE_ORCHESTRA_LS = 0x000b2, - CBUS_BOARD_LITTLE_ORCHESTRA_LS_0188H= 0x000b2, - CBUS_BOARD_LITTLE_ORCHESTRA_LS_0088H= 0x100b2, - - // (未テスト) SNE Littele Orchestra SS : YM2203 - CBUS_BOARD_LITTLE_ORCHESTRA_SS = 0x000c2, - // (未テスト) SNE Littele Orchestra MATE : YM2203 - CBUS_BOARD_LITTLE_ORCHESTRA_MATE = 0x000d2, - // (未テスト) SNE Littele Orchestra FELLOW : YM2203 - CBUS_BOARD_LITTLE_ORCHESTRA_FELLOW = 0x000e2, - // (未テスト) SNE JOY-2 : YM2203 - CBUS_BOARD_JOY2 = 0x000f2, - // (未テスト) SNE SOUND GRANPRI : YM2203 - CBUS_BOARD_SOUND_GRANPRI = 0x00102, - // (未テスト) 東京ニーズ TN-F3FM : YM2203C - CBUS_BOARD_TN_F3FM = 0x00112, - - - // YM2608(OPNA)系 ================================================= - // NEC PC-9801-73 - // アドレスデコーダ: 不明(16〜20bit) - // SOUNDID(0xA460) : 0x20 / 0x30 (86互換) - // IOADDR: 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh - CBUS_BOARD_73 = 0x00003, - CBUS_BOARD_73_0188H = 0x00003, - CBUS_BOARD_73_0288H = 0x10003, - - // NEC PC-9801-86 - // アドレスデコーダ: 不明(16〜20bit) - // SOUNDID(0xA460) : 0x40 / 0x50 (86互換) - // IOADDR: 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh - CBUS_BOARD_86 = 0x00023, - CBUS_BOARD_86_0188H = 0x00023, - CBUS_BOARD_86_0288H = 0x10023, - - // (未テスト) SIS アミューズメントサウンドボードASB-01 : YM2608 - // アドレスデコーダ: 不明 - // 0xA460 SOUNDID : 無し - // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh or 0388h/038Ah/038Ch/038Eh - CBUS_BOARD_ASB01 = 0x00043, - CBUS_BOARD_ASB01_0188H = 0x00043, - CBUS_BOARD_ASB01_0088H = 0x10043, - CBUS_BOARD_ASB01_0288H = 0x20043, - CBUS_BOARD_ASB01_0388H = 0x30043, - - // (未テスト) アイドルジャパン SpeakBoard : YM2608(w/ADPCM-RAM) - // アドレスデコーダ: 12bit - // IOADDR=0188h/018Ah/018Ch/018Eh or 0088h/008Ah/008Ch/008Eh - CBUS_BOARD_SPEAKBOARD = 0x00053, - CBUS_BOARD_SPEAKBOARD_188H = 0x00053, - CBUS_BOARD_SPEAKBOARD_088H = 0x10053, - - // (未テスト) コンピュータテクニカ SPB-98 : YM2608, YMF278 - CBUS_BOARD_SOUNDPLAYER98 = 0x00063, - - // (未対応) second-bus86 : YM2608, YMF278B-S - CBUS_BOARD_SECONDBUS86 = 0x00073, - - // (未対応) sound-edge : YAMAHA Sound Edge SW20-98 : YM2608B, YMF278B - CBUS_BOARD_SOUNDEDGE = 0x00083, - - // (未対応) win-duo : YM2608 - CBUS_BOARD_WINDUO = 0x00093, - - // (未テスト) MAD FACTORY 音美 : YM2608(w/ADPCM-RAM), YM3438 - // アドレスデコーダ: 不明 - // SOUNDID(0xA460) : 無し - // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh or 0388h/038Ah/038Ch/038Eh - // 0488h/048Ah/048Ch/048Eh or 0588h/058Ah/058Ch/058Eh or 0688h/068Ah/068Ch/068Eh or 0788h/078Ah/078Ch/078Eh - CBUS_BOARD_OTOMI = 0x000a3, - CBUS_BOARD_OTOMI_188H = 0x000a3, - CBUS_BOARD_OTOMI_088H = 0x100a3, - CBUS_BOARD_OTOMI_288H = 0x200a3, - CBUS_BOARD_OTOMI_388H = 0x300a3, - - // Q-Vision WaveMaster(86互換) : YM2608, CS4231 - // アドレスデコーダ: 16bit以上 - // SOUNDID(0xA460) : 0x40 / 0x50 (86互換) - // IOADDR: 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh - CBUS_BOARD_WAVEMASTER = 0x000b3, - CBUS_BOARD_WAVEMASTER_0188H = 0x000b3, - CBUS_BOARD_WAVEMASTER_0288H = 0x100b3, - - // Q-Vision WaveSMIT(86互換) : YMF288-S, CS4231 - // アドレスデコーダ: 16bit以上 - // SOUNDID(0xA460) : 0x40 / 0x50 (86互換) - // IOADDR: 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh - CBUS_BOARD_WAVESMIT = 0x000c3, - CBUS_BOARD_WAVESMIT_0188H = 0x000c3, - CBUS_BOARD_WAVESMIT_0288H = 0x100c3, - - // Q-Vision WaveStar(86互換) : YMF288-S, CS4231 - // アドレスデコーダ: 16bit以上 - // SOUNDID(0xA460) : 0x40 / 0x50 (86互換) - // IOADDR: 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh - CBUS_BOARD_WAVESTAR = 0x000d3, - CBUS_BOARD_WAVESTAR_0188H = 0x000d3, - CBUS_BOARD_WAVESTAR_0288H = 0x100d3, - - // (未対応) Buffalo WSN-A4F/A2F : YMF288-S - // アドレスデコーダ: 16bit以上 - // SOUNDID : 無し - // IOADDR : 0188h/018Ah/018Ch/018Eh - CBUS_BOARD_WSN_A4F = 0x000e3, - - // (未対応) SXM-F : YMF288-M - // アドレスデコーダ: 不明 - // SOUNDID : 無し - // IOADDR : 0188h/018Ah/018Ch/018Eh - CBUS_BOARD_SXM_F = 0x000f3, - - // (未対応) SRN-F : YMF288-M - // アドレスデコーダ: 16bit以上 - // SOUNDID : 無し - // IOADDR : 0188h/018Ah/018Ch/018Eh - CBUS_BOARD_SRN_F = 0x00103, - - - // YM262(OPL3)系 ================================================= - // (未対応) sound-blaster 16 (CT2720) : YMF262-F - // アドレスデコーダ : 不明(16bit以下) - // IOADDR(OPL3&PCM?): 20Dxh〜? (x=2/4/6/8/A/C/E) - CBUS_BOARD_SB16 = 0x00004, - - // (未対応) sound-blaster 16 with YM2203 (CT2720) : YMF262-F, YM2203 - // アドレスデコーダ : 不明(16bit以下) - // IOADDR(OPN) : 0088h/008Ah or 0188h/018Ah - // IOADDR(OPL3&PCM?): 20Dxh〜? (x=2/4/6/8/A/C/E) - CBUS_BOARD_SB16_2203 = 0x00014, - CBUS_BOARD_SB16_2203_0188H = 0x00014, - CBUS_BOARD_SB16_2203_0088H = 0x10014, - - // (未対応) sound-blaster 16Value (CT3720) : YMF262-F - // アドレスデコーダ : 不明(16bit以下) - CBUS_BOARD_SB16VALUE = 0x00024, - - // (未対応) canopus PowerWindow T64S : YMF262-M - CBUS_BOARD_POWERWINDOW_T64S = 0x00034, - // (未対応) EPSON PCSB2 : YMF262-M - CBUS_BOARD_PCSB2 = 0x00044, - // (未対応) コンピュータテクニカ : YMF262-M - CBUS_BOARD_WGS98S = 0x00054, - // (未対応) buffalo SRB-G : YMF264-F, YMZ263B-F - CBUS_BOARD_SRB_G = 0x00064, - // (未対応) SNE MIDI ORCHESTRA MIDI-3 : YM264F - CBUS_BOARD_MIDI_ORCHESTRA_MIDI3 = 0x00074, - - - // YM289系 ================================================= - // (未対応) SoundBlaster AWE32 (CT3610) : YMF289B-S - CBUS_BOARD_SB_AWE32 = 0x00005, - - // YM297系 ================================================= - // NEC PC-9801-118 : YMF297-F - // アドレスデコーダ: 不明(16〜20bit) - // SOUNDID(0xA460) : 0x80 - // IOADDR: 0188h/018Ah/018Ch/018Eh - CBUS_BOARD_118 = 0x00006 - -} CBUS_BOARD_TYPE; - - -#endif +/*** + c86ctl + + Copyright (c) 2009-2012, honet. All rights reserved. + This software is licensed under the BSD license. + + honet.kk(at)gmail.com + */ + +#ifndef CBUS_BOARDTYPE_H__ +#define CBUS_BOARDTYPE_H__ + +// CBUSボード種別定義 +// 上位16bit: アドレス種別などバリエーション +// 下位16bit: ボード種別 (うち下位4bitは搭載チップによる大雑把な分類) +typedef enum { + // 何だか分からない or 何も刺さっていない + CBUS_BOARD_UNKNOWN = 0x0, + + // PSG系 ========================================================= + // (未対応) NEC PC-9801-14 + // アドレスデコーダ: 14bit + CBUS_BOARD_14 = 0x00001, + + // (未対応) システムサコム AMD-98 + // アドレスデコーダ: 16bit(未検証) + // SOUNDID(0xA460) : 無し + // IDADDR: 0x00f0, 00xx x000 1101 xaaa (0x00d0~0x0df) + CBUS_BOARD_AMD98 = 0x00011, + + // YM2203(OPN)系 ================================================= + // NEC PC-9801-26, 26K + // アドレスデコーダ: 12bit + // SOUNDID(0xA460) : 無し + // IOADDR: 0188h/018Ah + CBUS_BOARD_26 = 0x00002, + + // (未テスト) SNE Sound Orchestra : YM2203, YM3812 + // アドレスデコーダ: 不明 + // SOUNDID(0xA460) : 無し + // IOADDR(OPN) : 0188h/018Ah or 0088h/008Ah + // IOADDR(YM3812): 018Ch/018Eh or 008Ch/008Eh + CBUS_BOARD_SOUND_ORCHESTRA = 0x00012, + CBUS_BOARD_SOUND_ORCHESTRA_0188H = 0x00012, + CBUS_BOARD_SOUND_ORCHESTRA_0088H = 0x10012, + + // (未テスト) SNE Sound Orchestra L : YM2203, YM3812 + // アドレスデコーダ: 12bit + // SOUNDID(0xA460) : 無し + // IOADDR(OPN) : 0188h/018Ah or 0088h/008Ah + // IOADDR(Y8950): 018Ch/018Eh or 008Ch/008Eh + CBUS_BOARD_SOUND_ORCHESTRA_L = 0x00022, + CBUS_BOARD_SOUND_ORCHESTRA_L_0188H = 0x00022, + CBUS_BOARD_SOUND_ORCHESTRA_L_0088H = 0x10022, + + // (未テスト) SNE Sound Orchestra V : YM2203, Y8950(w/ADPCM-RAM) + // アドレスデコーダ: 12bit + // SOUNDID(0xA460) : 無し + // IOADDR(OPN) : 0188h/018Ah or 0088h/008Ah + // IOADDR(Y8950): 018Ch/018Eh or 008Ch/008Eh + CBUS_BOARD_SOUND_ORCHESTRA_V = 0x00032, + CBUS_BOARD_SOUND_ORCHESTRA_V_0188H = 0x00032, + CBUS_BOARD_SOUND_ORCHESTRA_V_0088H = 0x10032, + + // (未テスト) SNE Sound Orchestra VS : YM2203, Y8950(w/ADPCM-RAM) + // アドレスデコーダ: 12bit + // SOUNDID(0xA460) : 無し + // IOADDR(OPN) : 0188h/018Ah or 0088h/008Ah + // IOADDR(Y8950): 018Ch/018Eh or 008Ch/008Eh + CBUS_BOARD_SOUND_ORCHESTRA_VS = 0x00042, + CBUS_BOARD_SOUND_ORCHESTRA_VS_0188H = 0x00042, + CBUS_BOARD_SOUND_ORCHESTRA_VS_0088H = 0x10042, + + // (未テスト) SNE Sound Orchestra LS : YM2203, Y8950 + // アドレスデコーダ: 不明 + // SOUNDID(0xA460) : 無し + // IOADDR(OPN): 0188h/018Ah or 0088h/008Ah + // IOADDR(Y8950): 018Ch/018Eh or 008Ch/008Eh + CBUS_BOARD_SOUND_ORCHESTRA_LS = 0x00052, + CBUS_BOARD_SOUND_ORCHESTRA_LS_0188H = 0x00052, + CBUS_BOARD_SOUND_ORCHESTRA_LS_0088H = 0x10052, + + // (未テスト) SNE Sound Orchestra MATE : YM2203, Y8950 + CBUS_BOARD_SOUND_ORCHESTRA_MATE = 0x00062, + // (未テスト) SNE Multimedia Orchestra : YM2203, YM262M + CBUS_BOARD_MULTIMEDIA_ORCHESTRA = 0x00072, + + // (未テスト) SNE Littele Orchestra : YM2203 + // アドレスデコーダ: 不明 + // SOUNDID(0xA460) : 無し + // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh + CBUS_BOARD_LITTLE_ORCHESTRA = 0x00082, + CBUS_BOARD_LITTLE_ORCHESTRA_0188H = 0x00082, + CBUS_BOARD_LITTLE_ORCHESTRA_0088H = 0x10082, + + // (未テスト) SNE Littele Orchestra L : YM2203 + // アドレスデコーダ: 不明 + // SOUNDID(0xA460) : 無し + // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh + CBUS_BOARD_LITTLE_ORCHESTRA_L = 0x00092, + CBUS_BOARD_LITTLE_ORCHESTRA_L_0188H = 0x00092, + CBUS_BOARD_LITTLE_ORCHESTRA_L_0088H = 0x01092, + + // (未テスト) SNE Littele Orchestra RS : YM2203 + // アドレスデコーダ: 不明 + // SOUNDID(0xA460) : 無し + // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh + CBUS_BOARD_LITTLE_ORCHESTRA_RS = 0x000a2, + CBUS_BOARD_LITTLE_ORCHESTRA_RS_0188H= 0x000a2, + CBUS_BOARD_LITTLE_ORCHESTRA_RS_0088H= 0x100a2, + + // (未テスト) SNE Littele Orchestra LS : YM2203 + // アドレスデコーダ: 不明 + // SOUNDID(0xA460) : 無し + // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh + CBUS_BOARD_LITTLE_ORCHESTRA_LS = 0x000b2, + CBUS_BOARD_LITTLE_ORCHESTRA_LS_0188H= 0x000b2, + CBUS_BOARD_LITTLE_ORCHESTRA_LS_0088H= 0x100b2, + + // (未テスト) SNE Littele Orchestra SS : YM2203 + CBUS_BOARD_LITTLE_ORCHESTRA_SS = 0x000c2, + // (未テスト) SNE Littele Orchestra MATE : YM2203 + CBUS_BOARD_LITTLE_ORCHESTRA_MATE = 0x000d2, + // (未テスト) SNE Littele Orchestra FELLOW : YM2203 + CBUS_BOARD_LITTLE_ORCHESTRA_FELLOW = 0x000e2, + // (未テスト) SNE JOY-2 : YM2203 + CBUS_BOARD_JOY2 = 0x000f2, + // (未テスト) SNE SOUND GRANPRI : YM2203 + CBUS_BOARD_SOUND_GRANPRI = 0x00102, + // (未テスト) 東京ニーズ TN-F3FM : YM2203C + CBUS_BOARD_TN_F3FM = 0x00112, + + + // YM2608(OPNA)系 ================================================= + // NEC PC-9801-73 + // アドレスデコーダ: 不明(16〜20bit) + // SOUNDID(0xA460) : 0x20 / 0x30 (86互換) + // IOADDR: 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh + CBUS_BOARD_73 = 0x00003, + CBUS_BOARD_73_0188H = 0x00003, + CBUS_BOARD_73_0288H = 0x10003, + + // NEC PC-9801-86 + // アドレスデコーダ: 不明(16〜20bit) + // SOUNDID(0xA460) : 0x40 / 0x50 (86互換) + // IOADDR: 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh + CBUS_BOARD_86 = 0x00023, + CBUS_BOARD_86_0188H = 0x00023, + CBUS_BOARD_86_0288H = 0x10023, + + // (未テスト) SIS アミューズメントサウンドボードASB-01 : YM2608 + // アドレスデコーダ: 不明 + // 0xA460 SOUNDID : 無し + // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh or 0388h/038Ah/038Ch/038Eh + CBUS_BOARD_ASB01 = 0x00043, + CBUS_BOARD_ASB01_0188H = 0x00043, + CBUS_BOARD_ASB01_0088H = 0x10043, + CBUS_BOARD_ASB01_0288H = 0x20043, + CBUS_BOARD_ASB01_0388H = 0x30043, + + // (未テスト) アイドルジャパン SpeakBoard : YM2608(w/ADPCM-RAM) + // アドレスデコーダ: 12bit + // IOADDR=0188h/018Ah/018Ch/018Eh or 0088h/008Ah/008Ch/008Eh + CBUS_BOARD_SPEAKBOARD = 0x00053, + CBUS_BOARD_SPEAKBOARD_188H = 0x00053, + CBUS_BOARD_SPEAKBOARD_088H = 0x10053, + + // (未テスト) コンピュータテクニカ SPB-98 : YM2608, YMF278 + CBUS_BOARD_SOUNDPLAYER98 = 0x00063, + + // (未対応) second-bus86 : YM2608, YMF278B-S + CBUS_BOARD_SECONDBUS86 = 0x00073, + + // (未対応) sound-edge : YAMAHA Sound Edge SW20-98 : YM2608B, YMF278B + CBUS_BOARD_SOUNDEDGE = 0x00083, + + // (未対応) win-duo : YM2608 + CBUS_BOARD_WINDUO = 0x00093, + + // (未テスト) MAD FACTORY 音美 : YM2608(w/ADPCM-RAM), YM3438 + // アドレスデコーダ: 不明 + // SOUNDID(0xA460) : 無し + // IOADDR: 0088h/008Ah/008Ch/008Eh or 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh or 0388h/038Ah/038Ch/038Eh + // 0488h/048Ah/048Ch/048Eh or 0588h/058Ah/058Ch/058Eh or 0688h/068Ah/068Ch/068Eh or 0788h/078Ah/078Ch/078Eh + CBUS_BOARD_OTOMI = 0x000a3, + CBUS_BOARD_OTOMI_188H = 0x000a3, + CBUS_BOARD_OTOMI_088H = 0x100a3, + CBUS_BOARD_OTOMI_288H = 0x200a3, + CBUS_BOARD_OTOMI_388H = 0x300a3, + + // Q-Vision WaveMaster(86互換) : YM2608, CS4231 + // アドレスデコーダ: 16bit以上 + // SOUNDID(0xA460) : 0x40 / 0x50 (86互換) + // IOADDR: 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh + CBUS_BOARD_WAVEMASTER = 0x000b3, + CBUS_BOARD_WAVEMASTER_0188H = 0x000b3, + CBUS_BOARD_WAVEMASTER_0288H = 0x100b3, + + // Q-Vision WaveSMIT(86互換) : YMF288-S, CS4231 + // アドレスデコーダ: 16bit以上 + // SOUNDID(0xA460) : 0x40 / 0x50 (86互換) + // IOADDR: 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh + CBUS_BOARD_WAVESMIT = 0x000c3, + CBUS_BOARD_WAVESMIT_0188H = 0x000c3, + CBUS_BOARD_WAVESMIT_0288H = 0x100c3, + + // Q-Vision WaveStar(86互換) : YMF288-S, CS4231 + // アドレスデコーダ: 16bit以上 + // SOUNDID(0xA460) : 0x40 / 0x50 (86互換) + // IOADDR: 0188h/018Ah/018Ch/018Eh or 0288h/028Ah/028Ch/028Eh + CBUS_BOARD_WAVESTAR = 0x000d3, + CBUS_BOARD_WAVESTAR_0188H = 0x000d3, + CBUS_BOARD_WAVESTAR_0288H = 0x100d3, + + // (未対応) Buffalo WSN-A4F/A2F : YMF288-S + // アドレスデコーダ: 16bit以上 + // SOUNDID : 無し + // IOADDR : 0188h/018Ah/018Ch/018Eh + CBUS_BOARD_WSN_A4F = 0x000e3, + + // (未対応) SXM-F : YMF288-M + // アドレスデコーダ: 不明 + // SOUNDID : 無し + // IOADDR : 0188h/018Ah/018Ch/018Eh + CBUS_BOARD_SXM_F = 0x000f3, + + // (未対応) SRN-F : YMF288-M + // アドレスデコーダ: 16bit以上 + // SOUNDID : 無し + // IOADDR : 0188h/018Ah/018Ch/018Eh + CBUS_BOARD_SRN_F = 0x00103, + + + // YM262(OPL3)系 ================================================= + // (未対応) sound-blaster 16 (CT2720) : YMF262-F + // アドレスデコーダ : 不明(16bit以下) + // IOADDR(OPL3&PCM?): 20Dxh〜? (x=2/4/6/8/A/C/E) + CBUS_BOARD_SB16 = 0x00004, + + // (未対応) sound-blaster 16 with YM2203 (CT2720) : YMF262-F, YM2203 + // アドレスデコーダ : 不明(16bit以下) + // IOADDR(OPN) : 0088h/008Ah or 0188h/018Ah + // IOADDR(OPL3&PCM?): 20Dxh〜? (x=2/4/6/8/A/C/E) + CBUS_BOARD_SB16_2203 = 0x00014, + CBUS_BOARD_SB16_2203_0188H = 0x00014, + CBUS_BOARD_SB16_2203_0088H = 0x10014, + + // (未対応) sound-blaster 16Value (CT3720) : YMF262-F + // アドレスデコーダ : 不明(16bit以下) + CBUS_BOARD_SB16VALUE = 0x00024, + + // (未対応) canopus PowerWindow T64S : YMF262-M + CBUS_BOARD_POWERWINDOW_T64S = 0x00034, + // (未対応) EPSON PCSB2 : YMF262-M + CBUS_BOARD_PCSB2 = 0x00044, + // (未対応) コンピュータテクニカ : YMF262-M + CBUS_BOARD_WGS98S = 0x00054, + // (未対応) buffalo SRB-G : YMF264-F, YMZ263B-F + CBUS_BOARD_SRB_G = 0x00064, + // (未対応) SNE MIDI ORCHESTRA MIDI-3 : YM264F + CBUS_BOARD_MIDI_ORCHESTRA_MIDI3 = 0x00074, + + + // YM289系 ================================================= + // (未対応) SoundBlaster AWE32 (CT3610) : YMF289B-S + CBUS_BOARD_SB_AWE32 = 0x00005, + + // YM297系 ================================================= + // NEC PC-9801-118 : YMF297-F + // アドレスデコーダ: 不明(16〜20bit) + // SOUNDID(0xA460) : 0x80 + // IOADDR: 0188h/018Ah/018Ch/018Eh + CBUS_BOARD_118 = 0x00006 + +} CBUS_BOARD_TYPE; + + +#endif diff --git a/windows/ext/externalchip.h b/windows/ext/externalchip.h old mode 100755 new mode 100644 index 2d6d30e7..fab8889d --- a/windows/ext/externalchip.h +++ b/windows/ext/externalchip.h @@ -1,75 +1,75 @@ -/** - * @file externalchip.h - * @brief Interface of thg external modules - */ - -#pragma once - -/** - * @brief The interface of thg external modules - */ -class IExternalChip -{ -public: - /** - * ChipType - */ - enum ChipType - { - kNone = 0, /*!< None */ - kAY8910, /*!< AY-3-8910 */ - - kYM2203, /*!< OPN */ - kYM2608, /*!< OPNA */ - kYM3438, /*!< OPN2 */ - kYMF288, /*!< OPN3 */ - - kYM3812, /*!< OPL2 */ - kYMF262, /*!< OPL3 */ - kY8950, /*!< Y8950 */ - - kYM2151 /*!< OPM */ - }; - - /** - * MessageType - */ - enum - { - kMute = 0, - kBusy - }; - - /** - * Destructor - */ - virtual ~IExternalChip() - { - } - - /** - * Get chip type - * @return The type of the chip - */ - virtual ChipType GetChipType() = 0; - - /** - * Reset - */ - virtual void Reset() = 0; - - /** - * Writes register - * @param[in] nAddr The address - * @param[in] cData The data - */ - virtual void WriteRegister(UINT nAddr, UINT8 cData) = 0; - - /** - * Message - * @param[in] nMessage The message - * @param[in] nParameter The parameter - * @return Result - */ - virtual INTPTR Message(UINT nMessage, INTPTR nParameter = 0) = 0; -}; +/** + * @file externalchip.h + * @brief Interface of thg external modules + */ + +#pragma once + +/** + * @brief The interface of thg external modules + */ +class IExternalChip +{ +public: + /** + * ChipType + */ + enum ChipType + { + kNone = 0, /*!< None */ + kAY8910, /*!< AY-3-8910 */ + + kYM2203, /*!< OPN */ + kYM2608, /*!< OPNA */ + kYM3438, /*!< OPN2 */ + kYMF288, /*!< OPN3 */ + + kYM3812, /*!< OPL2 */ + kYMF262, /*!< OPL3 */ + kY8950, /*!< Y8950 */ + + kYM2151 /*!< OPM */ + }; + + /** + * MessageType + */ + enum + { + kMute = 0, + kBusy + }; + + /** + * Destructor + */ + virtual ~IExternalChip() + { + } + + /** + * Get chip type + * @return The type of the chip + */ + virtual ChipType GetChipType() = 0; + + /** + * Reset + */ + virtual void Reset() = 0; + + /** + * Writes register + * @param[in] nAddr The address + * @param[in] cData The data + */ + virtual void WriteRegister(UINT nAddr, UINT8 cData) = 0; + + /** + * Message + * @param[in] nMessage The message + * @param[in] nParameter The parameter + * @return Result + */ + virtual INTPTR Message(UINT nMessage, INTPTR nParameter = 0) = 0; +}; diff --git a/windows/ext/externalchipmanager.cpp b/windows/ext/externalchipmanager.cpp old mode 100755 new mode 100644 index 091c4c35..a9a97471 --- a/windows/ext/externalchipmanager.cpp +++ b/windows/ext/externalchipmanager.cpp @@ -1,206 +1,206 @@ -/** - * @file externalchipmanager.cpp - * @brief 外部チップ管理クラスの動作の定義を行います - */ - -#include -#include "externalchipmanager.h" -#include -#include -#include "externalopl3.h" -#include "externalopm.h" -#include "externalopna.h" - -/*! 唯一のインスタンスです */ -CExternalChipManager CExternalChipManager::sm_instance; - -/** - * コンストラクタ - */ -CExternalChipManager::CExternalChipManager() -{ -} - -/** - * 初期化 - */ -void CExternalChipManager::Initialize() -{ -} - -/** - * 解放 - */ -void CExternalChipManager::Deinitialize() -{ - std::vector::iterator it = m_chips.begin(); - while (it != m_chips.end()) - { - IExternalChip* pChip = *it; - it = m_chips.erase(it); - - pChip->Reset(); - delete pChip; - } - - m_c86ctl.Deinitialize(); - m_juliet.Deinitialize(); - m_scci.Deinitialize(); - m_scci2.Deinitialize(); -} - -/** - * チップ確保 - * @param[in] nChipType チップ タイプ - * @param[in] nClock チップ クロック - * @return インスタンス - */ -IExternalChip* CExternalChipManager::GetInterface(IExternalChip::ChipType nChipType, UINT nClock) -{ - IExternalChip* pChip = GetInterfaceInner(nChipType, nClock); - if (pChip == NULL) - { - switch (nChipType) - { - case IExternalChip::kAY8910: - pChip = GetInterface(IExternalChip::kYM2203, nClock); - break; - - case IExternalChip::kYM2203: - pChip = GetInterface(IExternalChip::kYMF288, nClock * 2); - break; - - case IExternalChip::kYMF288: - pChip = GetInterface(IExternalChip::kYM2608, nClock); - break; - - case IExternalChip::kYM3438: - pChip = GetInterface(IExternalChip::kYMF288, nClock); - break; - - case IExternalChip::kY8950: - pChip = GetInterface(IExternalChip::kYM3812, nClock); - break; - - case IExternalChip::kYM3812: - pChip = GetInterface(IExternalChip::kYMF262, nClock * 4); - break; - - default: - break; - } - } - return pChip; -} - -/** - * チップ確保 (Inner) - * @param[in] nChipType チップ タイプ - * @param[in] nClock チップ クロック - * @return インスタンス - */ -IExternalChip* CExternalChipManager::GetInterfaceInner(IExternalChip::ChipType nChipType, UINT nClock) -{ - IExternalChip* pChip = NULL; - - /* ROMEO */ - if (np2oscfg.useromeo) - { - if (pChip == NULL) - { - pChip = m_juliet.GetInterface(nChipType, nClock); - } - } - - /* SCCI */ - if (pChip == NULL) - { - pChip = m_scci.GetInterface(nChipType, nClock); - } - - /* SCCI2 */ - if (pChip == NULL) - { - pChip = m_scci2.GetInterface(nChipType, nClock); - } - - /* G.I.M.I.C / C86BOX */ - if (pChip == NULL) - { - pChip = m_c86ctl.GetInterface(nChipType, nClock); - } - - /* ラッピング */ - if (pChip) - { - switch (nChipType) - { - case IExternalChip::kAY8910: - pChip = new CExternalPsg(pChip); - break; - - case IExternalChip::kYM2203: - case IExternalChip::kYM2608: - case IExternalChip::kYM3438: - case IExternalChip::kYMF288: - pChip = new CExternalOpna(pChip); - break; - - case IExternalChip::kYM3812: - case IExternalChip::kYMF262: - case IExternalChip::kY8950: - pChip = new CExternalOpl3(pChip); - break; - - case IExternalChip::kYM2151: - pChip = new CExternalOpm(pChip); - break; - - default: - break; - } - } - if (pChip) - { - m_chips.push_back(pChip); - } - return pChip; -} - -/** - * チップ解放 - * @param[in] pChip チップ - */ -void CExternalChipManager::Release(IExternalChip* pChip) -{ - std::vector::iterator it = std::find(m_chips.begin(), m_chips.end(), pChip); - if (it != m_chips.end()) - { - m_chips.erase(it); - pChip->Reset(); - delete pChip; - } -} - -/** - * 音源リセット - */ -void CExternalChipManager::Reset() -{ - for (std::vector::iterator it = m_chips.begin(); it != m_chips.end(); ++it) - { - (*it)->Reset(); - } -} - -/** - * ミュート - * @param[in] bMute ミュート - */ -void CExternalChipManager::Mute(bool bMute) -{ - for (std::vector::iterator it = m_chips.begin(); it != m_chips.end(); ++it) - { - (*it)->Message(IExternalChip::kMute, static_cast(bMute)); - } -} +/** + * @file externalchipmanager.cpp + * @brief 外部チップ管理クラスの動作の定義を行います + */ + +#include +#include "externalchipmanager.h" +#include +#include +#include "externalopl3.h" +#include "externalopm.h" +#include "externalopna.h" + +/*! 唯一のインスタンスです */ +CExternalChipManager CExternalChipManager::sm_instance; + +/** + * コンストラクタ + */ +CExternalChipManager::CExternalChipManager() +{ +} + +/** + * 初期化 + */ +void CExternalChipManager::Initialize() +{ +} + +/** + * 解放 + */ +void CExternalChipManager::Deinitialize() +{ + std::vector::iterator it = m_chips.begin(); + while (it != m_chips.end()) + { + IExternalChip* pChip = *it; + it = m_chips.erase(it); + + pChip->Reset(); + delete pChip; + } + + m_c86ctl.Deinitialize(); + m_juliet.Deinitialize(); + m_scci.Deinitialize(); + m_scci2.Deinitialize(); +} + +/** + * チップ確保 + * @param[in] nChipType チップ タイプ + * @param[in] nClock チップ クロック + * @return インスタンス + */ +IExternalChip* CExternalChipManager::GetInterface(IExternalChip::ChipType nChipType, UINT nClock) +{ + IExternalChip* pChip = GetInterfaceInner(nChipType, nClock); + if (pChip == NULL) + { + switch (nChipType) + { + case IExternalChip::kAY8910: + pChip = GetInterface(IExternalChip::kYM2203, nClock); + break; + + case IExternalChip::kYM2203: + pChip = GetInterface(IExternalChip::kYMF288, nClock * 2); + break; + + case IExternalChip::kYMF288: + pChip = GetInterface(IExternalChip::kYM2608, nClock); + break; + + case IExternalChip::kYM3438: + pChip = GetInterface(IExternalChip::kYMF288, nClock); + break; + + case IExternalChip::kY8950: + pChip = GetInterface(IExternalChip::kYM3812, nClock); + break; + + case IExternalChip::kYM3812: + pChip = GetInterface(IExternalChip::kYMF262, nClock * 4); + break; + + default: + break; + } + } + return pChip; +} + +/** + * チップ確保 (Inner) + * @param[in] nChipType チップ タイプ + * @param[in] nClock チップ クロック + * @return インスタンス + */ +IExternalChip* CExternalChipManager::GetInterfaceInner(IExternalChip::ChipType nChipType, UINT nClock) +{ + IExternalChip* pChip = NULL; + + /* ROMEO */ + if (np2oscfg.useromeo) + { + if (pChip == NULL) + { + pChip = m_juliet.GetInterface(nChipType, nClock); + } + } + + /* SCCI */ + if (pChip == NULL) + { + pChip = m_scci.GetInterface(nChipType, nClock); + } + + /* SCCI2 */ + if (pChip == NULL) + { + pChip = m_scci2.GetInterface(nChipType, nClock); + } + + /* G.I.M.I.C / C86BOX */ + if (pChip == NULL) + { + pChip = m_c86ctl.GetInterface(nChipType, nClock); + } + + /* ラッピング */ + if (pChip) + { + switch (nChipType) + { + case IExternalChip::kAY8910: + pChip = new CExternalPsg(pChip); + break; + + case IExternalChip::kYM2203: + case IExternalChip::kYM2608: + case IExternalChip::kYM3438: + case IExternalChip::kYMF288: + pChip = new CExternalOpna(pChip); + break; + + case IExternalChip::kYM3812: + case IExternalChip::kYMF262: + case IExternalChip::kY8950: + pChip = new CExternalOpl3(pChip); + break; + + case IExternalChip::kYM2151: + pChip = new CExternalOpm(pChip); + break; + + default: + break; + } + } + if (pChip) + { + m_chips.push_back(pChip); + } + return pChip; +} + +/** + * チップ解放 + * @param[in] pChip チップ + */ +void CExternalChipManager::Release(IExternalChip* pChip) +{ + std::vector::iterator it = std::find(m_chips.begin(), m_chips.end(), pChip); + if (it != m_chips.end()) + { + m_chips.erase(it); + pChip->Reset(); + delete pChip; + } +} + +/** + * 音源リセット + */ +void CExternalChipManager::Reset() +{ + for (std::vector::iterator it = m_chips.begin(); it != m_chips.end(); ++it) + { + (*it)->Reset(); + } +} + +/** + * ミュート + * @param[in] bMute ミュート + */ +void CExternalChipManager::Mute(bool bMute) +{ + for (std::vector::iterator it = m_chips.begin(); it != m_chips.end(); ++it) + { + (*it)->Message(IExternalChip::kMute, static_cast(bMute)); + } +} diff --git a/windows/ext/externalchipmanager.h b/windows/ext/externalchipmanager.h old mode 100755 new mode 100644 index 5cdef31b..4e81ed1a --- a/windows/ext/externalchipmanager.h +++ b/windows/ext/externalchipmanager.h @@ -1,49 +1,49 @@ -/** - * @file externalchipmanager.h - * @brief 外部チップ管理クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include "externalchip.h" -#include "c86ctl/c86ctlif.h" -#include "romeo/juliet.h" -#include "scci/scciif.h" -#include "scci2/scci2if.h" - -/** - * @brief 外部チップ管理クラス - */ -class CExternalChipManager -{ -public: - static CExternalChipManager* GetInstance(); - - CExternalChipManager(); - void Initialize(); - void Deinitialize(); - IExternalChip* GetInterface(IExternalChip::ChipType nChipType, UINT nClock); - void Release(IExternalChip* pChip); - void Reset(); - void Mute(bool bMute); - -private: - static CExternalChipManager sm_instance; /*!< 唯一のインスタンスです */ - std::vector m_chips; /*!< モジュール */ - - C86CtlIf m_c86ctl; /*!< C86Ctl インスタンス */ - CJuliet m_juliet; /*!< ROMEO インスタンス */ - CScciIf m_scci; /*!< SCCI インスタンス */ - CScci2If m_scci2; /*!< SCCI2 インスタンス */ - IExternalChip* GetInterfaceInner(IExternalChip::ChipType nChipType, UINT nClock); -}; - -/** - * インスタンスを得る - * @return インスタンス - */ -inline CExternalChipManager* CExternalChipManager::GetInstance() -{ - return &sm_instance; -} +/** + * @file externalchipmanager.h + * @brief 外部チップ管理クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include "externalchip.h" +#include "c86ctl/c86ctlif.h" +#include "romeo/juliet.h" +#include "scci/scciif.h" +#include "scci2/scci2if.h" + +/** + * @brief 外部チップ管理クラス + */ +class CExternalChipManager +{ +public: + static CExternalChipManager* GetInstance(); + + CExternalChipManager(); + void Initialize(); + void Deinitialize(); + IExternalChip* GetInterface(IExternalChip::ChipType nChipType, UINT nClock); + void Release(IExternalChip* pChip); + void Reset(); + void Mute(bool bMute); + +private: + static CExternalChipManager sm_instance; /*!< 唯一のインスタンスです */ + std::vector m_chips; /*!< モジュール */ + + C86CtlIf m_c86ctl; /*!< C86Ctl インスタンス */ + CJuliet m_juliet; /*!< ROMEO インスタンス */ + CScciIf m_scci; /*!< SCCI インスタンス */ + CScci2If m_scci2; /*!< SCCI2 インスタンス */ + IExternalChip* GetInterfaceInner(IExternalChip::ChipType nChipType, UINT nClock); +}; + +/** + * インスタンスを得る + * @return インスタンス + */ +inline CExternalChipManager* CExternalChipManager::GetInstance() +{ + return &sm_instance; +} diff --git a/windows/ext/externalopl3.cpp b/windows/ext/externalopl3.cpp old mode 100755 new mode 100644 index e4c4aa44..501c22e4 --- a/windows/ext/externalopl3.cpp +++ b/windows/ext/externalopl3.cpp @@ -1,105 +1,105 @@ -/** - * @file externalopl3.cpp - * @brief 外部 OPL3 演奏クラスの動作の定義を行います - */ - -#include -#include "externalopl3.h" - -/** - * コンストラクタ - * @param[in] pChip チップ - */ -CExternalOpl3::CExternalOpl3(IExternalChip* pChip) - : m_pChip(pChip) -{ - memset(m_cKon, 0x00, sizeof(m_cKon)); -} - -/** - * デストラクタ - */ -CExternalOpl3::~CExternalOpl3() -{ - delete m_pChip; -} - -/** - * チップ タイプを得る - * @return チップ タイプ - */ -IExternalChip::ChipType CExternalOpl3::GetChipType() -{ - return m_pChip->GetChipType(); -} - -/** - * 音源リセット - */ -void CExternalOpl3::Reset() -{ - m_pChip->Reset(); -} - -/** - * レジスタ書き込み - * @param[in] nAddr アドレス - * @param[in] cData データ - */ -void CExternalOpl3::WriteRegister(UINT nAddr, UINT8 cData) -{ - if ((nAddr & 0xf0) == 0xb0) - { - m_cKon[(nAddr & 0x100) >> 8][nAddr & 0x0f] = cData; - } - WriteRegisterInner(nAddr, cData); -} - -/** - * メッセージ - * @param[in] nMessage メッセージ - * @param[in] nParameter パラメータ - * @return 結果 - */ -INTPTR CExternalOpl3::Message(UINT nMessage, INTPTR nParameter) -{ - switch (nMessage) - { - case kMute: - Mute(nParameter != 0); - break; - } - return 0; -} - -/** - * ミュート - * @param[in] bMute ミュート - */ -void CExternalOpl3::Mute(bool bMute) -{ - if (bMute) - { - for (UINT i = 0; i < 2; i++) - { - for (UINT j = 0; j < 9; j++) - { - if (m_cKon[i][j] & 0x20) - { - m_cKon[i][j] &= 0xdf; - WriteRegisterInner((i * 0x100) + j + 0xb0, m_cKon[i][j]); - } - } - } - } -} - -/** - * レジスタ書き込み(内部) - * @param[in] nAddr アドレス - * @param[in] cData データ - */ -void CExternalOpl3::WriteRegisterInner(UINT nAddr, UINT8 cData) const -{ - m_pChip->WriteRegister(nAddr, cData); -} +/** + * @file externalopl3.cpp + * @brief 外部 OPL3 演奏クラスの動作の定義を行います + */ + +#include +#include "externalopl3.h" + +/** + * コンストラクタ + * @param[in] pChip チップ + */ +CExternalOpl3::CExternalOpl3(IExternalChip* pChip) + : m_pChip(pChip) +{ + memset(m_cKon, 0x00, sizeof(m_cKon)); +} + +/** + * デストラクタ + */ +CExternalOpl3::~CExternalOpl3() +{ + delete m_pChip; +} + +/** + * チップ タイプを得る + * @return チップ タイプ + */ +IExternalChip::ChipType CExternalOpl3::GetChipType() +{ + return m_pChip->GetChipType(); +} + +/** + * 音源リセット + */ +void CExternalOpl3::Reset() +{ + m_pChip->Reset(); +} + +/** + * レジスタ書き込み + * @param[in] nAddr アドレス + * @param[in] cData データ + */ +void CExternalOpl3::WriteRegister(UINT nAddr, UINT8 cData) +{ + if ((nAddr & 0xf0) == 0xb0) + { + m_cKon[(nAddr & 0x100) >> 8][nAddr & 0x0f] = cData; + } + WriteRegisterInner(nAddr, cData); +} + +/** + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParameter パラメータ + * @return 結果 + */ +INTPTR CExternalOpl3::Message(UINT nMessage, INTPTR nParameter) +{ + switch (nMessage) + { + case kMute: + Mute(nParameter != 0); + break; + } + return 0; +} + +/** + * ミュート + * @param[in] bMute ミュート + */ +void CExternalOpl3::Mute(bool bMute) +{ + if (bMute) + { + for (UINT i = 0; i < 2; i++) + { + for (UINT j = 0; j < 9; j++) + { + if (m_cKon[i][j] & 0x20) + { + m_cKon[i][j] &= 0xdf; + WriteRegisterInner((i * 0x100) + j + 0xb0, m_cKon[i][j]); + } + } + } + } +} + +/** + * レジスタ書き込み(内部) + * @param[in] nAddr アドレス + * @param[in] cData データ + */ +void CExternalOpl3::WriteRegisterInner(UINT nAddr, UINT8 cData) const +{ + m_pChip->WriteRegister(nAddr, cData); +} diff --git a/windows/ext/externalopl3.h b/windows/ext/externalopl3.h old mode 100755 new mode 100644 index 4689a319..b8382ca5 --- a/windows/ext/externalopl3.h +++ b/windows/ext/externalopl3.h @@ -1,29 +1,29 @@ -/** - * @file externalopl3.h - * @brief 外部 OPL3 演奏クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "externalchip.h" - -/** - * @brief 外部 OPL3 演奏クラス - */ -class CExternalOpl3 : public IExternalChip -{ -public: - CExternalOpl3(IExternalChip* pChip); - virtual ~CExternalOpl3(); - virtual ChipType GetChipType(); - virtual void Reset(); - virtual void WriteRegister(UINT nAddr, UINT8 cData); - virtual INTPTR Message(UINT nMessage, INTPTR nParameter); - -protected: - IExternalChip* m_pChip; /*!< チップ*/ - UINT8 m_cKon[2][16]; /*!< KON テーブル */ - - void Mute(bool bMute); - void WriteRegisterInner(UINT nAddr, UINT8 cData) const; -}; +/** + * @file externalopl3.h + * @brief 外部 OPL3 演奏クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "externalchip.h" + +/** + * @brief 外部 OPL3 演奏クラス + */ +class CExternalOpl3 : public IExternalChip +{ +public: + CExternalOpl3(IExternalChip* pChip); + virtual ~CExternalOpl3(); + virtual ChipType GetChipType(); + virtual void Reset(); + virtual void WriteRegister(UINT nAddr, UINT8 cData); + virtual INTPTR Message(UINT nMessage, INTPTR nParameter); + +protected: + IExternalChip* m_pChip; /*!< チップ*/ + UINT8 m_cKon[2][16]; /*!< KON テーブル */ + + void Mute(bool bMute); + void WriteRegisterInner(UINT nAddr, UINT8 cData) const; +}; diff --git a/windows/ext/externalopm.cpp b/windows/ext/externalopm.cpp old mode 100755 new mode 100644 index a4d407af..b83e8285 --- a/windows/ext/externalopm.cpp +++ b/windows/ext/externalopm.cpp @@ -1,135 +1,135 @@ -/** - * @file externalopm.cpp - * @brief 外部 OPM 演奏クラスの動作の定義を行います - */ - -#include -#include "externalopm.h" - -/** - * コンストラクタ - * @param[in] pChip チップ - */ -CExternalOpm::CExternalOpm(IExternalChip* pChip) - : m_pChip(pChip) -{ - memset(m_cAlgorithm, 0, sizeof(m_cAlgorithm)); - memset(m_cTtl, 0x7f, sizeof(m_cTtl)); -} - -/** - * デストラクタ - */ -CExternalOpm::~CExternalOpm() -{ - delete m_pChip; -} - -/** - * チップ タイプを得る - * @return チップ タイプ - */ -IExternalChip::ChipType CExternalOpm::GetChipType() -{ - return m_pChip->GetChipType(); -} - -/** - * 音源リセット - */ -void CExternalOpm::Reset() -{ - memset(m_cAlgorithm, 0, sizeof(m_cAlgorithm)); - memset(m_cTtl, 0x7f, sizeof(m_cTtl)); - m_pChip->Reset(); -} - -/** - * レジスタ書き込み - * @param[in] nAddr アドレス - * @param[in] cData データ - */ -void CExternalOpm::WriteRegister(UINT nAddr, UINT8 cData) -{ - if ((nAddr & 0xe0) == 0x60) // ttl - { - m_cTtl[nAddr & 0x1f] = cData; - } - else if ((nAddr & 0xf8) == 0x20) // algorithm - { - m_cAlgorithm[nAddr & 7] = cData; - } - WriteRegisterInner(nAddr, cData); -} - -/** - * メッセージ - * @param[in] nMessage メッセージ - * @param[in] nParameter パラメータ - * @return 結果 - */ -INTPTR CExternalOpm::Message(UINT nMessage, INTPTR nParameter) -{ - switch (nMessage) - { - case kMute: - Mute(nParameter != 0); - break; - } - return 0; -} - -/** - * ミュート - * @param[in] bMute ミュート - */ -void CExternalOpm::Mute(bool bMute) const -{ - const int nVolume = (bMute) ? -127 : 0; - for (UINT ch = 0; ch < 8; ch++) - { - SetVolume(ch, nVolume); - } -} - -/** - * レジスタ書き込み(内部) - * @param[in] nAddr アドレス - * @param[in] cData データ - */ -void CExternalOpm::WriteRegisterInner(UINT nAddr, UINT8 cData) const -{ - m_pChip->WriteRegister(nAddr, cData); -} - -/** - * ヴォリューム設定 - * @param[in] nChannel チャンネル - * @param[in] nVolume ヴォリューム値 - */ -void CExternalOpm::SetVolume(UINT nChannel, int nVolume) const -{ - /*! アルゴリズム スロット マスク */ - static const UINT8 s_opmask[] = {0x08, 0x08, 0x08, 0x08, 0x0c, 0x0e, 0x0e, 0x0f}; - UINT8 cMask = s_opmask[m_cAlgorithm[nChannel] & 7]; - - int nOffset = nChannel; - do - { - if (cMask & 1) - { - int nTtl = (m_cTtl[nOffset] & 0x7f) - nVolume; - if (nTtl < 0) - { - nTtl = 0; - } - else if (nTtl > 0x7f) - { - nTtl = 0x7f; - } - WriteRegisterInner(0x60 + nOffset, static_cast(nTtl)); - } - nOffset += 8; - cMask >>= 1; - } while (cMask != 0); -} +/** + * @file externalopm.cpp + * @brief 外部 OPM 演奏クラスの動作の定義を行います + */ + +#include +#include "externalopm.h" + +/** + * コンストラクタ + * @param[in] pChip チップ + */ +CExternalOpm::CExternalOpm(IExternalChip* pChip) + : m_pChip(pChip) +{ + memset(m_cAlgorithm, 0, sizeof(m_cAlgorithm)); + memset(m_cTtl, 0x7f, sizeof(m_cTtl)); +} + +/** + * デストラクタ + */ +CExternalOpm::~CExternalOpm() +{ + delete m_pChip; +} + +/** + * チップ タイプを得る + * @return チップ タイプ + */ +IExternalChip::ChipType CExternalOpm::GetChipType() +{ + return m_pChip->GetChipType(); +} + +/** + * 音源リセット + */ +void CExternalOpm::Reset() +{ + memset(m_cAlgorithm, 0, sizeof(m_cAlgorithm)); + memset(m_cTtl, 0x7f, sizeof(m_cTtl)); + m_pChip->Reset(); +} + +/** + * レジスタ書き込み + * @param[in] nAddr アドレス + * @param[in] cData データ + */ +void CExternalOpm::WriteRegister(UINT nAddr, UINT8 cData) +{ + if ((nAddr & 0xe0) == 0x60) // ttl + { + m_cTtl[nAddr & 0x1f] = cData; + } + else if ((nAddr & 0xf8) == 0x20) // algorithm + { + m_cAlgorithm[nAddr & 7] = cData; + } + WriteRegisterInner(nAddr, cData); +} + +/** + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParameter パラメータ + * @return 結果 + */ +INTPTR CExternalOpm::Message(UINT nMessage, INTPTR nParameter) +{ + switch (nMessage) + { + case kMute: + Mute(nParameter != 0); + break; + } + return 0; +} + +/** + * ミュート + * @param[in] bMute ミュート + */ +void CExternalOpm::Mute(bool bMute) const +{ + const int nVolume = (bMute) ? -127 : 0; + for (UINT ch = 0; ch < 8; ch++) + { + SetVolume(ch, nVolume); + } +} + +/** + * レジスタ書き込み(内部) + * @param[in] nAddr アドレス + * @param[in] cData データ + */ +void CExternalOpm::WriteRegisterInner(UINT nAddr, UINT8 cData) const +{ + m_pChip->WriteRegister(nAddr, cData); +} + +/** + * ヴォリューム設定 + * @param[in] nChannel チャンネル + * @param[in] nVolume ヴォリューム値 + */ +void CExternalOpm::SetVolume(UINT nChannel, int nVolume) const +{ + /*! アルゴリズム スロット マスク */ + static const UINT8 s_opmask[] = {0x08, 0x08, 0x08, 0x08, 0x0c, 0x0e, 0x0e, 0x0f}; + UINT8 cMask = s_opmask[m_cAlgorithm[nChannel] & 7]; + + int nOffset = nChannel; + do + { + if (cMask & 1) + { + int nTtl = (m_cTtl[nOffset] & 0x7f) - nVolume; + if (nTtl < 0) + { + nTtl = 0; + } + else if (nTtl > 0x7f) + { + nTtl = 0x7f; + } + WriteRegisterInner(0x60 + nOffset, static_cast(nTtl)); + } + nOffset += 8; + cMask >>= 1; + } while (cMask != 0); +} diff --git a/windows/ext/externalopm.h b/windows/ext/externalopm.h old mode 100755 new mode 100644 index c37be638..9d53e335 --- a/windows/ext/externalopm.h +++ b/windows/ext/externalopm.h @@ -1,31 +1,31 @@ -/** - * @file externalopm.h - * @brief 外部 OPM 演奏クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "externalchip.h" - -/** - * @brief 外部 OPM 演奏クラス - */ -class CExternalOpm : public IExternalChip -{ -public: - CExternalOpm(IExternalChip* pChip); - virtual ~CExternalOpm(); - virtual ChipType GetChipType(); - virtual void Reset(); - virtual void WriteRegister(UINT nAddr, UINT8 cData); - virtual INTPTR Message(UINT nMessage, INTPTR nParameter); - -protected: - IExternalChip* m_pChip; /*!< チップ */ - UINT8 m_cAlgorithm[8]; /*!< アルゴリズム テーブル */ - UINT8 m_cTtl[8 * 4]; /*!< TTL テーブル */ - - void Mute(bool bMute) const; - void WriteRegisterInner(UINT nAddr, UINT8 cData) const; - void SetVolume(UINT nChannel, int nVolume) const; -}; +/** + * @file externalopm.h + * @brief 外部 OPM 演奏クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "externalchip.h" + +/** + * @brief 外部 OPM 演奏クラス + */ +class CExternalOpm : public IExternalChip +{ +public: + CExternalOpm(IExternalChip* pChip); + virtual ~CExternalOpm(); + virtual ChipType GetChipType(); + virtual void Reset(); + virtual void WriteRegister(UINT nAddr, UINT8 cData); + virtual INTPTR Message(UINT nMessage, INTPTR nParameter); + +protected: + IExternalChip* m_pChip; /*!< チップ */ + UINT8 m_cAlgorithm[8]; /*!< アルゴリズム テーブル */ + UINT8 m_cTtl[8 * 4]; /*!< TTL テーブル */ + + void Mute(bool bMute) const; + void WriteRegisterInner(UINT nAddr, UINT8 cData) const; + void SetVolume(UINT nChannel, int nVolume) const; +}; diff --git a/windows/ext/externalopna.cpp b/windows/ext/externalopna.cpp old mode 100755 new mode 100644 index 309445ca..341a4685 --- a/windows/ext/externalopna.cpp +++ b/windows/ext/externalopna.cpp @@ -1,171 +1,171 @@ -/** - * @file externalopna.cpp - * @brief 外部 OPNA 演奏クラスの動作の定義を行います - */ - -#include -#include "externalopna.h" - -/** - * コンストラクタ - * @param[in] pChip チップ - */ -CExternalOpna::CExternalOpna(IExternalChip* pChip) - : CExternalPsg(pChip) - , m_bHasPsg(false) - , m_bHasExtend(false) - , m_bHasRhythm(false) - , m_bHasADPCM(false) - , m_cMode(0) -{ - memset(m_cAlgorithm, 0, sizeof(m_cAlgorithm)); - memset(m_cTtl, 0x7f, sizeof(m_cTtl)); - - switch (GetChipType()) - { - case IExternalChip::kYM2203: - m_bHasPsg = true; - break; - - case IExternalChip::kYM2608: - m_bHasPsg = true; - m_bHasExtend = true; - m_bHasRhythm = true; - m_bHasADPCM = true; - break; - - case IExternalChip::kYM3438: - m_bHasExtend = true; - break; - - case IExternalChip::kYMF288: - m_bHasPsg = true; - m_bHasExtend = true; - m_bHasRhythm = true; - break; - - default: - break; - } -} - -/** - * デストラクタ - */ -CExternalOpna::~CExternalOpna() -{ -} - -/** - * 音源リセット - */ -void CExternalOpna::Reset() -{ - m_cMode = 0; - memset(m_cAlgorithm, 0, sizeof(m_cAlgorithm)); - memset(m_cTtl, 0x7f, sizeof(m_cTtl)); - if (m_bHasPsg) - { - CExternalPsg::Reset(); - } - else - { - m_pChip->Reset(); - } -} - -/** - * レジスタ書き込み - * @param[in] nAddr アドレス - * @param[in] cData データ - */ -void CExternalOpna::WriteRegister(UINT nAddr, UINT8 cData) -{ - if (nAddr < 0x10) - { - if (m_bHasPsg) - { - CExternalPsg::WriteRegister(nAddr, cData); - } - } - else - { - if (nAddr == 0x27) - { - cData &= 0xc0; - if (m_cMode == cData) - { - return; - } - m_cMode = cData; - } - else if ((nAddr & 0xf0) == 0x40) - { - // ttl - m_cTtl[((nAddr & 0x100) >> 4) + (nAddr & 15)] = cData; - } - else if ((nAddr & 0xfc) == 0xb0) - { - // algorithm - m_cAlgorithm[((nAddr & 0x100) >> 6) + (nAddr & 3)] = cData; - } - WriteRegisterInner(nAddr, cData); - } -} - -/** - * ミュート - * @param[in] bMute ミュート - */ -void CExternalOpna::Mute(bool bMute) const -{ - if (m_bHasPsg) - { - CExternalPsg::Mute(bMute); - } - - const int nVolume = (bMute) ? -127 : 0; - for (UINT ch = 0; ch < 3; ch++) - { - SetVolume(ch + 0, nVolume); - if (m_bHasExtend) - { - SetVolume(ch + 4, nVolume); - } - } -} - -/** - * ヴォリューム設定 - * @param[in] nChannel チャンネル - * @param[in] nVolume ヴォリューム値 - */ -void CExternalOpna::SetVolume(UINT nChannel, int nVolume) const -{ - const UINT nBaseReg = (nChannel & 4) ? 0x140 : 0x40; - - /*! アルゴリズム スロット マスク */ - static const UINT8 s_opmask[] = {0x08, 0x08, 0x08, 0x08, 0x0c, 0x0e, 0x0e, 0x0f}; - UINT8 cMask = s_opmask[m_cAlgorithm[nChannel & 7] & 7]; - const UINT8* pTtl = m_cTtl + ((nChannel & 4) << 2); - - int nOffset = nChannel & 3; - do - { - if (cMask & 1) - { - int nTtl = (pTtl[nOffset] & 0x7f) - nVolume; - if (nTtl < 0) - { - nTtl = 0; - } - else if (nTtl > 0x7f) - { - nTtl = 0x7f; - } - WriteRegisterInner(nBaseReg + nOffset, static_cast(nTtl)); - } - nOffset += 4; - cMask >>= 1; - } while (cMask != 0); -} +/** + * @file externalopna.cpp + * @brief 外部 OPNA 演奏クラスの動作の定義を行います + */ + +#include +#include "externalopna.h" + +/** + * コンストラクタ + * @param[in] pChip チップ + */ +CExternalOpna::CExternalOpna(IExternalChip* pChip) + : CExternalPsg(pChip) + , m_bHasPsg(false) + , m_bHasExtend(false) + , m_bHasRhythm(false) + , m_bHasADPCM(false) + , m_cMode(0) +{ + memset(m_cAlgorithm, 0, sizeof(m_cAlgorithm)); + memset(m_cTtl, 0x7f, sizeof(m_cTtl)); + + switch (GetChipType()) + { + case IExternalChip::kYM2203: + m_bHasPsg = true; + break; + + case IExternalChip::kYM2608: + m_bHasPsg = true; + m_bHasExtend = true; + m_bHasRhythm = true; + m_bHasADPCM = true; + break; + + case IExternalChip::kYM3438: + m_bHasExtend = true; + break; + + case IExternalChip::kYMF288: + m_bHasPsg = true; + m_bHasExtend = true; + m_bHasRhythm = true; + break; + + default: + break; + } +} + +/** + * デストラクタ + */ +CExternalOpna::~CExternalOpna() +{ +} + +/** + * 音源リセット + */ +void CExternalOpna::Reset() +{ + m_cMode = 0; + memset(m_cAlgorithm, 0, sizeof(m_cAlgorithm)); + memset(m_cTtl, 0x7f, sizeof(m_cTtl)); + if (m_bHasPsg) + { + CExternalPsg::Reset(); + } + else + { + m_pChip->Reset(); + } +} + +/** + * レジスタ書き込み + * @param[in] nAddr アドレス + * @param[in] cData データ + */ +void CExternalOpna::WriteRegister(UINT nAddr, UINT8 cData) +{ + if (nAddr < 0x10) + { + if (m_bHasPsg) + { + CExternalPsg::WriteRegister(nAddr, cData); + } + } + else + { + if (nAddr == 0x27) + { + cData &= 0xc0; + if (m_cMode == cData) + { + return; + } + m_cMode = cData; + } + else if ((nAddr & 0xf0) == 0x40) + { + // ttl + m_cTtl[((nAddr & 0x100) >> 4) + (nAddr & 15)] = cData; + } + else if ((nAddr & 0xfc) == 0xb0) + { + // algorithm + m_cAlgorithm[((nAddr & 0x100) >> 6) + (nAddr & 3)] = cData; + } + WriteRegisterInner(nAddr, cData); + } +} + +/** + * ミュート + * @param[in] bMute ミュート + */ +void CExternalOpna::Mute(bool bMute) const +{ + if (m_bHasPsg) + { + CExternalPsg::Mute(bMute); + } + + const int nVolume = (bMute) ? -127 : 0; + for (UINT ch = 0; ch < 3; ch++) + { + SetVolume(ch + 0, nVolume); + if (m_bHasExtend) + { + SetVolume(ch + 4, nVolume); + } + } +} + +/** + * ヴォリューム設定 + * @param[in] nChannel チャンネル + * @param[in] nVolume ヴォリューム値 + */ +void CExternalOpna::SetVolume(UINT nChannel, int nVolume) const +{ + const UINT nBaseReg = (nChannel & 4) ? 0x140 : 0x40; + + /*! アルゴリズム スロット マスク */ + static const UINT8 s_opmask[] = {0x08, 0x08, 0x08, 0x08, 0x0c, 0x0e, 0x0e, 0x0f}; + UINT8 cMask = s_opmask[m_cAlgorithm[nChannel & 7] & 7]; + const UINT8* pTtl = m_cTtl + ((nChannel & 4) << 2); + + int nOffset = nChannel & 3; + do + { + if (cMask & 1) + { + int nTtl = (pTtl[nOffset] & 0x7f) - nVolume; + if (nTtl < 0) + { + nTtl = 0; + } + else if (nTtl > 0x7f) + { + nTtl = 0x7f; + } + WriteRegisterInner(nBaseReg + nOffset, static_cast(nTtl)); + } + nOffset += 4; + cMask >>= 1; + } while (cMask != 0); +} diff --git a/windows/ext/externalopna.h b/windows/ext/externalopna.h old mode 100755 new mode 100644 index b9fc21e9..42e5c9e1 --- a/windows/ext/externalopna.h +++ b/windows/ext/externalopna.h @@ -1,65 +1,65 @@ -/** - * @file externalopna.h - * @brief 外部 OPNA 演奏クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "externalpsg.h" - -/** - * @brief 外部 OPNA 演奏クラス - */ -class CExternalOpna : public CExternalPsg -{ -public: - CExternalOpna(IExternalChip* pChip); - virtual ~CExternalOpna(); - bool HasPsg() const; - bool HasRhythm() const; - bool HasADPCM() const; - virtual void Reset(); - virtual void WriteRegister(UINT nAddr, UINT8 cData); - -protected: - bool m_bHasPsg; /*!< PSG */ - bool m_bHasExtend; /*!< Extend */ - bool m_bHasRhythm; /*!< Rhythm */ - bool m_bHasADPCM; /*!< ADPCM */ - UINT8 m_cMode; /*!< モード */ - UINT8 m_cAlgorithm[8]; /*!< アルゴリズム テーブル */ - UINT8 m_cTtl[8 * 4]; /*!< TTL テーブル */ - - virtual void Mute(bool bMute) const; - void SetVolume(UINT nChannel, int nVolume) const; -}; - -/** - * PSG を持っている? - * @retval true 有効 - * @retval false 無効 - */ -inline bool CExternalOpna::HasPsg() const -{ - return m_bHasPsg; -} - -/** - * Rhythm を持っている? - * @retval true 有効 - * @retval false 無効 - */ -inline bool CExternalOpna::HasRhythm() const -{ - return m_bHasRhythm; -} - -/** - * ADPCM のバッファを持っている? - * @retval true 有効 - * @retval false 無効 - */ -inline bool CExternalOpna::HasADPCM() const -{ - return m_bHasADPCM; -} +/** + * @file externalopna.h + * @brief 外部 OPNA 演奏クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "externalpsg.h" + +/** + * @brief 外部 OPNA 演奏クラス + */ +class CExternalOpna : public CExternalPsg +{ +public: + CExternalOpna(IExternalChip* pChip); + virtual ~CExternalOpna(); + bool HasPsg() const; + bool HasRhythm() const; + bool HasADPCM() const; + virtual void Reset(); + virtual void WriteRegister(UINT nAddr, UINT8 cData); + +protected: + bool m_bHasPsg; /*!< PSG */ + bool m_bHasExtend; /*!< Extend */ + bool m_bHasRhythm; /*!< Rhythm */ + bool m_bHasADPCM; /*!< ADPCM */ + UINT8 m_cMode; /*!< モード */ + UINT8 m_cAlgorithm[8]; /*!< アルゴリズム テーブル */ + UINT8 m_cTtl[8 * 4]; /*!< TTL テーブル */ + + virtual void Mute(bool bMute) const; + void SetVolume(UINT nChannel, int nVolume) const; +}; + +/** + * PSG を持っている? + * @retval true 有効 + * @retval false 無効 + */ +inline bool CExternalOpna::HasPsg() const +{ + return m_bHasPsg; +} + +/** + * Rhythm を持っている? + * @retval true 有効 + * @retval false 無効 + */ +inline bool CExternalOpna::HasRhythm() const +{ + return m_bHasRhythm; +} + +/** + * ADPCM のバッファを持っている? + * @retval true 有効 + * @retval false 無効 + */ +inline bool CExternalOpna::HasADPCM() const +{ + return m_bHasADPCM; +} diff --git a/windows/ext/externalpsg.cpp b/windows/ext/externalpsg.cpp old mode 100755 new mode 100644 index f7c1f7cd..d261f144 --- a/windows/ext/externalpsg.cpp +++ b/windows/ext/externalpsg.cpp @@ -1,102 +1,102 @@ -/** - * @file externalpsg.cpp - * @brief 外部 PSG 演奏クラスの動作の定義を行います - */ - -#include -#include "externalpsg.h" - -/** - * コンストラクタ - * @param[in] pChip チップ - */ -CExternalPsg::CExternalPsg(IExternalChip* pChip) - : m_pChip(pChip) - , m_cPsgMix(0x3f) -{ -} - -/** - * デストラクタ - */ -CExternalPsg::~CExternalPsg() -{ - delete m_pChip; -} - -/** - * チップ タイプを得る - * @return チップ タイプ - */ -IExternalChip::ChipType CExternalPsg::GetChipType() -{ - return m_pChip->GetChipType(); -} - -/** - * 音源リセット - */ -void CExternalPsg::Reset() -{ - m_cPsgMix = 0x3f; - m_pChip->Reset(); -} - -/** - * レジスタ書き込み - * @param[in] nAddr アドレス - * @param[in] cData データ - */ -void CExternalPsg::WriteRegister(UINT nAddr, UINT8 cData) -{ - if (nAddr < 0x0e) - { - if (nAddr == 0x07) - { - // psg mix - cData &= 0x3f; - if (m_cPsgMix == cData) - { - return; - } - m_cPsgMix = cData; - } - WriteRegisterInner(nAddr, cData); - } -} - -/** - * メッセージ - * @param[in] nMessage メッセージ - * @param[in] nParameter パラメータ - * @return 結果 - */ -INTPTR CExternalPsg::Message(UINT nMessage, INTPTR nParameter) -{ - switch (nMessage) - { - case kMute: - Mute(nParameter != 0); - break; - } - return 0; -} - -/** - * ミュート - * @param[in] bMute ミュート - */ -void CExternalPsg::Mute(bool bMute) const -{ - WriteRegisterInner(0x07, (bMute) ? 0x3f : m_cPsgMix); -} - -/** - * レジスタ書き込み(内部) - * @param[in] nAddr アドレス - * @param[in] cData データ - */ -void CExternalPsg::WriteRegisterInner(UINT nAddr, UINT8 cData) const -{ - m_pChip->WriteRegister(nAddr, cData); -} +/** + * @file externalpsg.cpp + * @brief 外部 PSG 演奏クラスの動作の定義を行います + */ + +#include +#include "externalpsg.h" + +/** + * コンストラクタ + * @param[in] pChip チップ + */ +CExternalPsg::CExternalPsg(IExternalChip* pChip) + : m_pChip(pChip) + , m_cPsgMix(0x3f) +{ +} + +/** + * デストラクタ + */ +CExternalPsg::~CExternalPsg() +{ + delete m_pChip; +} + +/** + * チップ タイプを得る + * @return チップ タイプ + */ +IExternalChip::ChipType CExternalPsg::GetChipType() +{ + return m_pChip->GetChipType(); +} + +/** + * 音源リセット + */ +void CExternalPsg::Reset() +{ + m_cPsgMix = 0x3f; + m_pChip->Reset(); +} + +/** + * レジスタ書き込み + * @param[in] nAddr アドレス + * @param[in] cData データ + */ +void CExternalPsg::WriteRegister(UINT nAddr, UINT8 cData) +{ + if (nAddr < 0x0e) + { + if (nAddr == 0x07) + { + // psg mix + cData &= 0x3f; + if (m_cPsgMix == cData) + { + return; + } + m_cPsgMix = cData; + } + WriteRegisterInner(nAddr, cData); + } +} + +/** + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParameter パラメータ + * @return 結果 + */ +INTPTR CExternalPsg::Message(UINT nMessage, INTPTR nParameter) +{ + switch (nMessage) + { + case kMute: + Mute(nParameter != 0); + break; + } + return 0; +} + +/** + * ミュート + * @param[in] bMute ミュート + */ +void CExternalPsg::Mute(bool bMute) const +{ + WriteRegisterInner(0x07, (bMute) ? 0x3f : m_cPsgMix); +} + +/** + * レジスタ書き込み(内部) + * @param[in] nAddr アドレス + * @param[in] cData データ + */ +void CExternalPsg::WriteRegisterInner(UINT nAddr, UINT8 cData) const +{ + m_pChip->WriteRegister(nAddr, cData); +} diff --git a/windows/ext/externalpsg.h b/windows/ext/externalpsg.h old mode 100755 new mode 100644 index 956c0b0b..9a7579da --- a/windows/ext/externalpsg.h +++ b/windows/ext/externalpsg.h @@ -1,29 +1,29 @@ -/** - * @file externalpsg.h - * @brief 外部 PSG 演奏クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "externalchip.h" - -/** - * @brief 外部 PSG 演奏クラス - */ -class CExternalPsg : public IExternalChip -{ -public: - CExternalPsg(IExternalChip* pChip); - virtual ~CExternalPsg(); - virtual ChipType GetChipType(); - virtual void Reset(); - virtual void WriteRegister(UINT nAddr, UINT8 cData); - virtual INTPTR Message(UINT nMessage, INTPTR nParameter); - -protected: - IExternalChip* m_pChip; //!< チップ - UINT8 m_cPsgMix; //!< PSG ミキサー - - virtual void Mute(bool bMute) const; - void WriteRegisterInner(UINT nAddr, UINT8 cData) const; -}; +/** + * @file externalpsg.h + * @brief 外部 PSG 演奏クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "externalchip.h" + +/** + * @brief 外部 PSG 演奏クラス + */ +class CExternalPsg : public IExternalChip +{ +public: + CExternalPsg(IExternalChip* pChip); + virtual ~CExternalPsg(); + virtual ChipType GetChipType(); + virtual void Reset(); + virtual void WriteRegister(UINT nAddr, UINT8 cData); + virtual INTPTR Message(UINT nMessage, INTPTR nParameter); + +protected: + IExternalChip* m_pChip; //!< チップ + UINT8 m_cPsgMix; //!< PSG ミキサー + + virtual void Mute(bool bMute) const; + void WriteRegisterInner(UINT nAddr, UINT8 cData) const; +}; diff --git a/windows/ext/mt32snd.cpp b/windows/ext/mt32snd.cpp old mode 100755 new mode 100644 index ebb2039f..c540ed33 --- a/windows/ext/mt32snd.cpp +++ b/windows/ext/mt32snd.cpp @@ -1,209 +1,209 @@ -#include - -#if defined(MT32SOUND_DLL) - -#include "mt32snd.h" - -MT32Sound MT32Sound::sm_instance; - -// DLL名 -static const TCHAR s_szMT32SoundDll[] = TEXT("mt32sound.dll"); - -static const char fn_mt32soundopen[] = "MT32Sound_Open"; -static const char fn_mt32soundclose[] = "MT32Sound_Close"; -static const char fn_mt32soundwrite[] = "MT32Sound_Write"; -static const char fn_mt32soundmix[] = "MT32Sound_Mix"; - -/** - * コンストラクタ - */ -MT32Sound::MT32Sound() - : m_hModule(NULL) - , m_bOpened(false) - , m_nRate(0) - , m_fnOpen(NULL) - , m_fnClose(NULL) - , m_fnWrite(NULL) - , m_fnMix(NULL) -{ -} - -/** - * デストラクタ - */ -MT32Sound::~MT32Sound() -{ - Deinitialize(); -} - -/** - * 初期化 - * @retval true 成功 - * @retval false 失敗 - */ -bool MT32Sound::Initialize() -{ - Deinitialize(); - - m_hModule = ::LoadLibrary(s_szMT32SoundDll); - if (m_hModule == NULL) - { - return false; - } - - //! ロード関数リスト - static const ProcItem s_dllProc[] = - { - {fn_mt32soundopen, offsetof(MT32Sound, m_fnOpen)}, - {fn_mt32soundclose, offsetof(MT32Sound, m_fnClose)}, - {fn_mt32soundwrite, offsetof(MT32Sound, m_fnWrite)}, - {fn_mt32soundmix, offsetof(MT32Sound, m_fnMix)} - }; - - for (size_t i = 0; i < _countof(s_dllProc); i++) - { - FARPROC proc = ::GetProcAddress(m_hModule, s_dllProc[i].lpSymbol); - if (proc == NULL) - { - Deinitialize(); - return false; - } - *(reinterpret_cast(reinterpret_cast(this) + s_dllProc[i].nOffset)) = proc; - } - return true; -} - -/** - * 解放 - */ -void MT32Sound::Deinitialize() -{ - if (m_hModule) - { - ::FreeLibrary(m_hModule); - } - m_hModule = NULL; - m_bOpened = false; - m_fnOpen = NULL; - m_fnClose = NULL; - m_fnWrite = NULL; - m_fnMix = NULL; -} - -/** - * オープン - * @retval true 成功 - * @retval false 失敗 - */ -bool MT32Sound::Open() -{ - if ((m_fnOpen != NULL) && (!m_bOpened) && (m_nRate)) - { - (*m_fnOpen)(m_nRate, 0, 0, 0, 0, 0); - m_bOpened = true; - return true; - } - else - { - return false; - } -} - -/** - * クローズ - */ -void MT32Sound::Close() -{ - if (m_bOpened) - { - if (m_fnClose) - { - (*m_fnClose)(); - } - m_bOpened = false; - } -} - -/** - * ショート メッセージ - * @param[in] msg メッセージ - */ -void MT32Sound::ShortMsg(UINT32 msg) -{ - FnWrite fnWrite = m_fnWrite; - if (fnWrite == NULL) - { - return; - } - - switch ((msg >> 4) & (0xf0 >> 4)) - { - case 0xc0 >> 4: - case 0xd0 >> 4: - (*fnWrite)(static_cast(msg >> 0)); - (*fnWrite)(static_cast(msg >> 8)); - break; - - case 0x80 >> 4: - case 0x90 >> 4: - case 0xa0 >> 4: - case 0xb0 >> 4: - case 0xe0 >> 4: - (*fnWrite)(static_cast(msg >> 0)); - (*fnWrite)(static_cast(msg >> 8)); - (*fnWrite)(static_cast(msg >> 16)); - break; - } -} - -/** - * ロング メッセージ - * @param[in] lpBuffer バッファ - * @param[in] cchBuffer バッファ長 - */ -void MT32Sound::LongMsg(const UINT8* lpBuffer, UINT cchBuffer) -{ - if (lpBuffer == NULL) - { - return; - } - - FnWrite fnWrite = m_fnWrite; - if (fnWrite == NULL) - { - return; - } - - for (UINT i = 0; i < cchBuffer; i++) - { - (*fnWrite)(lpBuffer[i]); - } -} - -/** - * ミックス - * @param[in,out] lpBuffer バッファ - * @param[in] cchBuffer サンプル数 - * @return 出力サンプル数 - */ -UINT MT32Sound::Mix(SINT32* lpBuffer, UINT cchBuffer) -{ - - UINT ret = 0; - while (cchBuffer) - { - SINT16 sSamples[512 * 2]; - const UINT nLength = MIN(cchBuffer, 512); - (*m_fnMix)(sSamples, nLength); - for (UINT i = 0; i < nLength; i++) - { - lpBuffer[i * 2 + 0] += sSamples[i * 2 + 0] * 2; - lpBuffer[i * 2 + 1] += sSamples[i * 2 + 1] * 2; - } - lpBuffer += nLength * 2; - cchBuffer -= nLength; - ret += nLength; - } - return ret; -} -#endif +#include + +#if defined(MT32SOUND_DLL) + +#include "mt32snd.h" + +MT32Sound MT32Sound::sm_instance; + +// DLL名 +static const TCHAR s_szMT32SoundDll[] = TEXT("mt32sound.dll"); + +static const char fn_mt32soundopen[] = "MT32Sound_Open"; +static const char fn_mt32soundclose[] = "MT32Sound_Close"; +static const char fn_mt32soundwrite[] = "MT32Sound_Write"; +static const char fn_mt32soundmix[] = "MT32Sound_Mix"; + +/** + * コンストラクタ + */ +MT32Sound::MT32Sound() + : m_hModule(NULL) + , m_bOpened(false) + , m_nRate(0) + , m_fnOpen(NULL) + , m_fnClose(NULL) + , m_fnWrite(NULL) + , m_fnMix(NULL) +{ +} + +/** + * デストラクタ + */ +MT32Sound::~MT32Sound() +{ + Deinitialize(); +} + +/** + * 初期化 + * @retval true 成功 + * @retval false 失敗 + */ +bool MT32Sound::Initialize() +{ + Deinitialize(); + + m_hModule = ::LoadLibrary(s_szMT32SoundDll); + if (m_hModule == NULL) + { + return false; + } + + //! ロード関数リスト + static const ProcItem s_dllProc[] = + { + {fn_mt32soundopen, offsetof(MT32Sound, m_fnOpen)}, + {fn_mt32soundclose, offsetof(MT32Sound, m_fnClose)}, + {fn_mt32soundwrite, offsetof(MT32Sound, m_fnWrite)}, + {fn_mt32soundmix, offsetof(MT32Sound, m_fnMix)} + }; + + for (size_t i = 0; i < _countof(s_dllProc); i++) + { + FARPROC proc = ::GetProcAddress(m_hModule, s_dllProc[i].lpSymbol); + if (proc == NULL) + { + Deinitialize(); + return false; + } + *(reinterpret_cast(reinterpret_cast(this) + s_dllProc[i].nOffset)) = proc; + } + return true; +} + +/** + * 解放 + */ +void MT32Sound::Deinitialize() +{ + if (m_hModule) + { + ::FreeLibrary(m_hModule); + } + m_hModule = NULL; + m_bOpened = false; + m_fnOpen = NULL; + m_fnClose = NULL; + m_fnWrite = NULL; + m_fnMix = NULL; +} + +/** + * オープン + * @retval true 成功 + * @retval false 失敗 + */ +bool MT32Sound::Open() +{ + if ((m_fnOpen != NULL) && (!m_bOpened) && (m_nRate)) + { + (*m_fnOpen)(m_nRate, 0, 0, 0, 0, 0); + m_bOpened = true; + return true; + } + else + { + return false; + } +} + +/** + * クローズ + */ +void MT32Sound::Close() +{ + if (m_bOpened) + { + if (m_fnClose) + { + (*m_fnClose)(); + } + m_bOpened = false; + } +} + +/** + * ショート メッセージ + * @param[in] msg メッセージ + */ +void MT32Sound::ShortMsg(UINT32 msg) +{ + FnWrite fnWrite = m_fnWrite; + if (fnWrite == NULL) + { + return; + } + + switch ((msg >> 4) & (0xf0 >> 4)) + { + case 0xc0 >> 4: + case 0xd0 >> 4: + (*fnWrite)(static_cast(msg >> 0)); + (*fnWrite)(static_cast(msg >> 8)); + break; + + case 0x80 >> 4: + case 0x90 >> 4: + case 0xa0 >> 4: + case 0xb0 >> 4: + case 0xe0 >> 4: + (*fnWrite)(static_cast(msg >> 0)); + (*fnWrite)(static_cast(msg >> 8)); + (*fnWrite)(static_cast(msg >> 16)); + break; + } +} + +/** + * ロング メッセージ + * @param[in] lpBuffer バッファ + * @param[in] cchBuffer バッファ長 + */ +void MT32Sound::LongMsg(const UINT8* lpBuffer, UINT cchBuffer) +{ + if (lpBuffer == NULL) + { + return; + } + + FnWrite fnWrite = m_fnWrite; + if (fnWrite == NULL) + { + return; + } + + for (UINT i = 0; i < cchBuffer; i++) + { + (*fnWrite)(lpBuffer[i]); + } +} + +/** + * ミックス + * @param[in,out] lpBuffer バッファ + * @param[in] cchBuffer サンプル数 + * @return 出力サンプル数 + */ +UINT MT32Sound::Mix(SINT32* lpBuffer, UINT cchBuffer) +{ + + UINT ret = 0; + while (cchBuffer) + { + SINT16 sSamples[512 * 2]; + const UINT nLength = MIN(cchBuffer, 512); + (*m_fnMix)(sSamples, nLength); + for (UINT i = 0; i < nLength; i++) + { + lpBuffer[i * 2 + 0] += sSamples[i * 2 + 0] * 2; + lpBuffer[i * 2 + 1] += sSamples[i * 2 + 1] * 2; + } + lpBuffer += nLength * 2; + cchBuffer -= nLength; + ret += nLength; + } + return ret; +} +#endif diff --git a/windows/ext/mt32snd.h b/windows/ext/mt32snd.h old mode 100755 new mode 100644 index 429a3617..1c3b12c6 --- a/windows/ext/mt32snd.h +++ b/windows/ext/mt32snd.h @@ -1,84 +1,84 @@ -/** - * @file mt32snd.h - * @brief MT32Sound アクセス クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#if defined(MT32SOUND_DLL) - -/** - * @brief MT32Sound アクセス クラス - */ -class MT32Sound -{ -public: - static MT32Sound* GetInstance(); - - MT32Sound(); - ~MT32Sound(); - bool Initialize(); - void Deinitialize(); - bool IsEnabled() const; - void SetRate(UINT nRate); - - bool Open(); - void Close(); - void ShortMsg(UINT32 msg); - void LongMsg(const UINT8* lpBuffer, UINT cchBuffer); - UINT Mix(SINT32* lpBuffer, UINT cchBuffer); - -private: - static MT32Sound sm_instance; //!< 唯一のインスタンスです - - //! @brief ロード関数 - struct ProcItem - { - LPCSTR lpSymbol; //!< 関数名 - size_t nOffset; //!< オフセット - }; - - // 定義 - typedef int (*FnOpen)(int rate, int reverb, int def, int revtype, int revtime, int revlvl); /*!< オープン */ - typedef int (*FnClose)(void); /*!< クローズ */ - typedef int (*FnWrite)(unsigned char data); /*!< ライト */ - typedef int (*FnMix)(void *buff, unsigned long size); /*!< ミックス */ - - HMODULE m_hModule; /*!< モジュール */ - bool m_bOpened; /*!< オープン フラグ */ - UINT m_nRate; /*!< サンプリング レート */ - FnOpen m_fnOpen; /*!< オープン関数 */ - FnClose m_fnClose; /*!< クローズ関数 */ - FnWrite m_fnWrite; /*!< ライト関数 */ - FnMix m_fnMix; /*!< ミックス関数 */ -}; - -/** - * インスタンスを取得 - * @return インスタンス - */ -inline MT32Sound* MT32Sound::GetInstance() -{ - return &sm_instance; -} - -/** - * 有効? - * @retval true 有効 - * @retval false 無効 - */ -inline bool MT32Sound::IsEnabled() const -{ - return (m_hModule != NULL); -} - -/** - * サンプリング レートを設定 - * @param[in] nRate レート - */ -inline void MT32Sound::SetRate(UINT nRate) -{ - m_nRate = nRate; -} - -#endif +/** + * @file mt32snd.h + * @brief MT32Sound アクセス クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#if defined(MT32SOUND_DLL) + +/** + * @brief MT32Sound アクセス クラス + */ +class MT32Sound +{ +public: + static MT32Sound* GetInstance(); + + MT32Sound(); + ~MT32Sound(); + bool Initialize(); + void Deinitialize(); + bool IsEnabled() const; + void SetRate(UINT nRate); + + bool Open(); + void Close(); + void ShortMsg(UINT32 msg); + void LongMsg(const UINT8* lpBuffer, UINT cchBuffer); + UINT Mix(SINT32* lpBuffer, UINT cchBuffer); + +private: + static MT32Sound sm_instance; //!< 唯一のインスタンスです + + //! @brief ロード関数 + struct ProcItem + { + LPCSTR lpSymbol; //!< 関数名 + size_t nOffset; //!< オフセット + }; + + // 定義 + typedef int (*FnOpen)(int rate, int reverb, int def, int revtype, int revtime, int revlvl); /*!< オープン */ + typedef int (*FnClose)(void); /*!< クローズ */ + typedef int (*FnWrite)(unsigned char data); /*!< ライト */ + typedef int (*FnMix)(void *buff, unsigned long size); /*!< ミックス */ + + HMODULE m_hModule; /*!< モジュール */ + bool m_bOpened; /*!< オープン フラグ */ + UINT m_nRate; /*!< サンプリング レート */ + FnOpen m_fnOpen; /*!< オープン関数 */ + FnClose m_fnClose; /*!< クローズ関数 */ + FnWrite m_fnWrite; /*!< ライト関数 */ + FnMix m_fnMix; /*!< ミックス関数 */ +}; + +/** + * インスタンスを取得 + * @return インスタンス + */ +inline MT32Sound* MT32Sound::GetInstance() +{ + return &sm_instance; +} + +/** + * 有効? + * @retval true 有効 + * @retval false 無効 + */ +inline bool MT32Sound::IsEnabled() const +{ + return (m_hModule != NULL); +} + +/** + * サンプリング レートを設定 + * @param[in] nRate レート + */ +inline void MT32Sound::SetRate(UINT nRate) +{ + m_nRate = nRate; +} + +#endif diff --git a/windows/ext/opna.cpp b/windows/ext/opna.cpp index 61fd897a..6bf465db 100644 --- a/windows/ext/opna.cpp +++ b/windows/ext/opna.cpp @@ -1,847 +1,847 @@ -/** - * @file opna.cpp - * @brief Implementation of OPNA - */ - -#include -#include -#include "sound/opna.h" -#include -#include -#include -#include -#include -#include -#include "externalchipmanager.h" -#include "externalopna.h" -#if defined(SUPPORT_FMGEN) -#include -#endif /* SUPPORT_FMGEN */ - -static void writeRegister(POPNA opna, UINT nAddress, REG8 cData); -static void writeExtendedRegister(POPNA opna, UINT nAddress, REG8 cData); - -// dB = 20 log10( (音量0~1) * (pow(10, 最大dB値/20) - pow(10, 最小dB値/20)) + pow(10, 最小dB値/20) ) -//#define LINEAR2DB(a) (20 * log10((a) * (pow(10.0, 20/20) - pow(10.0, -192/20)) + pow(10.0, -192/20))) -#define LINEAR2DB(a) (pow(a,0.12)*(20+192) - 192) // XXX: fmgen音量と猫音源音量を一致させるための実験式・・・ - -#if defined(SUPPORT_FMGEN) -// XXX: 音量調整を出来るようにするためにとりあえず・・・ -POPNA opnalist[OPNA_MAX] = {0}; -int opnalistconunt = 0; -void opnalist_push(POPNA opna) -{ - int i; - for(i=0;ifmgen, (int)LINEAR2DB((double)lvol / 128)); - } -} -void opna_fmgen_setallvolumePSG_linear(int lvol) -{ - for(int i=0;ifmgen, (int)LINEAR2DB((double)lvol / 128)); - } -} -void opna_fmgen_setallvolumeADPCM_linear(int lvol) -{ - for(int i=0;ifmgen, (int)LINEAR2DB((double)lvol / 128)); - } -} -void opna_fmgen_setallvolumeRhythmTotal_linear(int lvol) -{ - for(int i=0;ifmgen, (int)LINEAR2DB((double)lvol / 128)); - } -} -#endif /* SUPPORT_FMGEN */ - -/** - * Initialize instance - * @param[in] opna The instance - */ -void opna_construct(POPNA opna) -{ -#if defined(SUPPORT_FMGEN) - if(opna->fmgen) OPNA_Destruct(opna->fmgen); -#endif /* SUPPORT_FMGEN */ - memset(opna, 0, sizeof(*opna)); -#if defined(SUPPORT_FMGEN) - opna->fmgen = OPNA_Construct(); - opnalist_push(opna); -#endif /* SUPPORT_FMGEN */ -} - -/** - * Deinitialize instance - * @param[in] opna The instance - */ -void opna_destruct(POPNA opna) -{ -#if defined(SUPPORT_FMGEN) - if(opna->fmgen) { - if(opna->fmgen) OPNA_Destruct(opna->fmgen); - opna->fmgen = NULL; - opnalist_remove(opna); - } -#endif /* SUPPORT_FMGEN */ - CExternalOpna* pExt = reinterpret_cast(opna->userdata); - CExternalChipManager::GetInstance()->Release(pExt); - opna->userdata = NULL; -} - -/** - * Reset - * @param[in] opna The instance - * @param[in] cCaps - */ -void opna_reset(POPNA opna, REG8 cCaps) -{ - memset(&opna->s, 0, sizeof(opna->s)); - opna->s.adpcmmask = ~(0x1c); - opna->s.cCaps = cCaps; - opna->s.irq = 0xff; - opna->s.reg[0x07] = 0xbf; - opna->s.reg[0x0e] = 0xff; - opna->s.reg[0x0f] = 0xff; - opna->s.reg[0xff] = (cCaps & OPNA_HAS_RHYTHM) ? 0x01 : 0x00; - for (UINT i = 0; i < 2; i++) - { - memset(opna->s.reg + (i * 0x100) + 0x30, 0xff, 0x60); - memset(opna->s.reg + (i * 0x100) + 0xb4, 0xc0, 0x04); - } - for (UINT i = 0; i < 7; i++) - { - opna->s.keyreg[i] = i & 7; - } -#if defined(SUPPORT_FMGEN) - if(np2cfg.usefmgen) { - OEMCHAR path[MAX_PATH]; - char strbuf[MAX_PATH]; - - OPNA_Init(opna->fmgen, OPNA_CLOCK*2, soundcfg.rate, false, ""); // サンプリングレート強制変更・・・ - getbiospath(path, OEMTEXT(""), NELEMENTS(path)); -#ifdef UNICODE - wcstombs(strbuf, path, MAX_PATH); -#else - strcpy(strbuf, path); -#endif - OPNA_LoadRhythmSample(opna->fmgen, strbuf); - OPNA_SetVolumeFM(opna->fmgen, (int)LINEAR2DB((double)np2cfg.vol_fm / 128 * np2cfg.vol_master / 100)); - OPNA_SetVolumePSG(opna->fmgen, (int)LINEAR2DB((double)np2cfg.vol_ssg / 128 * np2cfg.vol_master / 100)); - OPNA_SetVolumeADPCM(opna->fmgen, (int)LINEAR2DB((double)np2cfg.vol_adpcm / 128 * np2cfg.vol_master / 100)); - OPNA_SetVolumeRhythmTotal(opna->fmgen, (int)LINEAR2DB((double)np2cfg.vol_rhythm / 128 * np2cfg.vol_master / 100)); - OPNA_Reset(opna->fmgen); - OPNA_SetReg(opna->fmgen, 0x07, 0xbf); - OPNA_SetReg(opna->fmgen, 0x0e, 0xff); - OPNA_SetReg(opna->fmgen, 0x0f, 0xff); - OPNA_SetReg(opna->fmgen, 0xff, 0x01); - for (UINT i = 0; i < 2; i++) - { - for (UINT j = 0; j < 0x60; j++) { - OPNA_SetReg(opna->fmgen, (i * 0x100) + 0x30 + j, 0xff); - } - for (UINT j = 0; j < 0x04; j++) { - OPNA_SetReg(opna->fmgen, (i * 0x100) + 0xb4 + j, 0xc0); - } - } - opna->usefmgen = 1; - }else{ - opna->usefmgen = 0; // fmgenを使わない - } -#endif /* SUPPORT_FMGEN */ - - opngen_reset(&opna->opngen); - psggen_reset(&opna->psg); - rhythm_reset(&opna->rhythm); - adpcm_reset(&opna->adpcm); - - if (cCaps == 0) - { - CExternalOpna* pExt = reinterpret_cast(opna->userdata); - if (pExt) - { - CExternalChipManager::GetInstance()->Release(pExt); - opna->userdata = NULL; - } - } - - // 音量初期化 - opngen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); - psggen_setvol(np2cfg.vol_ssg * np2cfg.vol_master / 100); - rhythm_setvol(np2cfg.vol_rhythm * np2cfg.vol_master / 100); -#if defined(SUPPORT_FMGEN) - if(np2cfg.usefmgen) { - opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * np2cfg.vol_master / 100); - opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * np2cfg.vol_master / 100); - opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * np2cfg.vol_master / 100); - } -#endif /* SUPPORT_FMGEN */ - for (UINT i = 0; i < NELEMENTS(g_opna); i++) - { - rhythm_update(&g_opna[i].rhythm); - } -} - -/** - * Restore - * @param[in] opna The instance - */ -static void restore(POPNA opna) -{ - // FM - writeRegister(opna, 0x22, opna->s.reg[0x22]); - for (UINT i = 0x30; i < 0xa0; i++) - { - if ((i & 3) == 3) - { - continue; - } - writeRegister(opna, i, opna->s.reg[i]); - writeExtendedRegister(opna, i, opna->s.reg[i + 0x100]); - } - for (UINT i = 0xb0; i < 0xb8; i++) - { - if ((i & 3) == 3) - { - continue; - } - writeRegister(opna, i, opna->s.reg[i]); - writeExtendedRegister(opna, i, opna->s.reg[i + 0x100]); - } - for (UINT i = 0; i < 8; i++) - { - if ((i & 3) == 3) - { - continue; - } - writeRegister(opna, i + 0xa4, opna->s.reg[i + 0xa4]); - writeRegister(opna, i + 0xa0, opna->s.reg[i + 0xa0]); - writeExtendedRegister(opna, i + 0xa4, opna->s.reg[i + 0x1a4]); - writeExtendedRegister(opna, i + 0xa0, opna->s.reg[i + 0x1a0]); - } - for (UINT i = 0; i < 8; i++) - { - if ((i & 3) == 3) - { - continue; - } - writeRegister(opna, 0x28, opna->s.keyreg[i]); - } -#if defined(SUPPORT_FMGEN) - if(opna->usefmgen) { - OPNA_SetReg(opna->fmgen, 0x22, opna->s.reg[0x22]); - for (UINT i = 0x30; i < 0xa0; i++) - { - if ((i & 3) == 3) - { - continue; - } - OPNA_SetReg(opna->fmgen, i, opna->s.reg[i]); - OPNA_SetReg(opna->fmgen, i + 0x100, opna->s.reg[i + 0x100]); - } - for (UINT i = 0xb0; i < 0xb8; i++) - { - if ((i & 3) == 3) - { - continue; - } - OPNA_SetReg(opna->fmgen, i, opna->s.reg[i]); - OPNA_SetReg(opna->fmgen, i + 0x100, opna->s.reg[i + 0x100]); - } - for (UINT i = 0; i < 8; i++) - { - if ((i & 3) == 3) - { - continue; - } - OPNA_SetReg(opna->fmgen, i + 0xa4, opna->s.reg[i + 0xa4]); - OPNA_SetReg(opna->fmgen, i + 0xa0, opna->s.reg[i + 0xa0]); - OPNA_SetReg(opna->fmgen, i + 0x1a4, opna->s.reg[i + 0x1a4]); - OPNA_SetReg(opna->fmgen, i + 0x1a0, opna->s.reg[i + 0x1a0]); - } - for (UINT i = 0; i < 8; i++) - { - if ((i & 3) == 3) - { - continue; - } - OPNA_SetReg(opna->fmgen, 0x28, opna->s.keyreg[i]); - } - } -#endif /* SUPPORT_FMGEN */ - - // PSG - for (UINT i = 0; i < 0x10; i++) - { - writeRegister(opna, i, opna->s.reg[i]); - } -#if defined(SUPPORT_FMGEN) - if(opna->usefmgen) { - for (UINT i = 0; i < 0x10; i++) - { - OPNA_SetReg(opna->fmgen, i, opna->s.reg[i]); - } - } -#endif /* SUPPORT_FMGEN */ - - // Rhythm - writeRegister(opna, 0x11, opna->s.reg[0x11]); - for (UINT i = 0x18; i < 0x1e; i++) - { - writeRegister(opna, i, opna->s.reg[i]); - } -#if defined(SUPPORT_FMGEN) - if(opna->usefmgen) { - OPNA_SetReg(opna->fmgen, 0x11, opna->s.reg[0x11]); - for (UINT i = 0x18; i < 0x1e; i++) - { - OPNA_SetReg(opna->fmgen, i, opna->s.reg[i]); - } - } -#endif /* SUPPORT_FMGEN */ -} - -/** - * Bind - * @param[in] opna The instance - */ -void opna_bind(POPNA opna) -{ - UINT8 cCaps = opna->s.cCaps; - UINT nClock = 3993600; - - keydisp_bindopna(opna->s.reg, (cCaps & OPNA_HAS_EXTENDEDFM) ? 6 : 3, nClock); - if (cCaps & OPNA_HAS_PSG) - { - keydisp_bindpsg(opna->s.reg, nClock); - } - - CExternalOpna* pExt = reinterpret_cast(opna->userdata); - if (pExt == NULL) - { - IExternalChip::ChipType nChipType = IExternalChip::kYM2203; - if (cCaps & OPNA_HAS_EXTENDEDFM) - { - nChipType = IExternalChip::kYMF288; - nClock *= 2; - if (cCaps & OPNA_HAS_ADPCM) - { - nChipType = IExternalChip::kYM2608; - } - else if (cCaps == OPNA_MODE_3438) - { - nChipType = IExternalChip::kYM3438; - } - } - pExt = static_cast(CExternalChipManager::GetInstance()->GetInterface(nChipType, nClock)); - opna->userdata = reinterpret_cast(pExt); - } - if (pExt) - { - pExt->Reset(); - pExt->WriteRegister(0x22, 0x00); - pExt->WriteRegister(0x29, 0x80); - pExt->WriteRegister(0x10, 0xbf); - pExt->WriteRegister(0x11, 0x30); - pExt->WriteRegister(0x27, opna->s.reg[0x27]); - -#if defined(SUPPORT_FMGEN) - opna->usefmgen = 0; // 外部があればfmgenを使わない -#endif /* SUPPORT_FMGEN */ - } - else - { - opna->opngen.opnch[2].extop = opna->s.reg[0x27] & 0xc0; - } - restore(opna); - -#if defined(SUPPORT_FMGEN) - if(opna->usefmgen) { - if (!pExt) - { - sound_streamregist(opna->fmgen, (SOUNDCB)OPNA_Mix); - } - if (cCaps & OPNA_HAS_RHYTHM) - { - rhythm_bind(&opna->rhythm); - } - } else { -#endif /* SUPPORT_FMGEN */ - if (pExt) - { - if ((cCaps & OPNA_HAS_PSG) && (pExt->HasPsg())) - { - cCaps &= ~OPNA_HAS_PSG; - } - if ((cCaps & OPNA_HAS_RHYTHM) && (pExt->HasRhythm())) - { - cCaps &= ~OPNA_HAS_RHYTHM; - } - if ((cCaps & OPNA_HAS_ADPCM) && (pExt->HasADPCM())) - { - sound_streamregist(&opna->adpcm, (SOUNDCB)adpcm_getpcm_dummy); - cCaps &= ~OPNA_HAS_ADPCM; - } - } - - if (cCaps & OPNA_HAS_PSG) - { - sound_streamregist(&opna->psg, (SOUNDCB)psggen_getpcm); - } - if (cCaps & OPNA_HAS_VR) - { - sound_streamregist(&opna->opngen, (SOUNDCB)opngen_getpcmvr); - } - else - { - sound_streamregist(&opna->opngen, (SOUNDCB)opngen_getpcm); - } - if (cCaps & OPNA_HAS_RHYTHM) - { - rhythm_bind(&opna->rhythm); - } - if (cCaps & OPNA_HAS_ADPCM) - { - sound_streamregist(&opna->adpcm, (SOUNDCB)adpcm_getpcm); - } -#if defined(SUPPORT_FMGEN) - } -#endif /* SUPPORT_FMGEN */ -} - -/** - * Status - * @param[in] opna The instance - * @return Status - */ -REG8 opna_readStatus(POPNA opna) -{ - if (opna->s.cCaps & OPNA_HAS_TIMER) - { - return opna->s.status; - } - return 0; -} - -/** - * Status - * @param[in] opna The instance - * @return Status - */ -REG8 opna_readExtendedStatus(POPNA opna) -{ - const UINT8 cCaps = opna->s.cCaps; - REG8 ret = 0; - - if (cCaps & OPNA_HAS_ADPCM) - { - ret = adpcm_status(&opna->adpcm); - } - else - { - ret = opna->s.adpcmmask & 8; - } - - if (cCaps & OPNA_HAS_TIMER) - { - ret |= opna->s.status; - } - - return ret; -} - -/** - * Writes register - * @param[in] opna The instance - * @param[in] nAddress The address - * @param[in] cData The data - */ -void opna_writeRegister(POPNA opna, UINT nAddress, REG8 cData) -{ - opna->s.reg[nAddress] = cData; - - if (opna->s.cCaps & OPNA_S98) - { - S98_put(NORMAL2608, nAddress, cData); - } - - writeRegister(opna, nAddress, cData); -#if defined(SUPPORT_FMGEN) - if(opna->usefmgen) { - OPNA_SetReg(opna->fmgen, nAddress, cData); - } -#endif /* SUPPORT_FMGEN */ -} - -/** - * Writes register (Inner) - * @param[in] opna The instance - * @param[in] nAddress The address - * @param[in] cData The data - */ -static void writeRegister(POPNA opna, UINT nAddress, REG8 cData) -{ - const UINT8 cCaps = opna->s.cCaps; - CExternalOpna* pExt = reinterpret_cast(opna->userdata); - - if (nAddress < 0x10) - { - if (cCaps & OPNA_HAS_PSG) - { - keydisp_psg(opna->s.reg, nAddress); - if ((!pExt) || (!pExt->HasPsg())) - { - psggen_setreg(&opna->psg, nAddress, cData); - } - else - { - pExt->WriteRegister(nAddress, cData); - } - } - } - else if (nAddress < 0x20) - { - if (cCaps & OPNA_HAS_RHYTHM) - { - if ((cCaps & OPNA_HAS_VR) && (nAddress >= 0x18) && (nAddress <= 0x1d)) - { - switch (cData & 0xc0) - { - case 0x40: - case 0x80: - cData ^= 0xc0; - break; - } - } - if ((!pExt) || (!pExt->HasRhythm())) - { - rhythm_setreg(&opna->rhythm, nAddress, cData); - } - else - { - pExt->WriteRegister(nAddress, cData); - } - } - } - else if (nAddress < 0x30) - { - if (nAddress == 0x28) - { - REG8 cChannel = cData & 0x0f; - if (cChannel < 8) - { - opna->s.keyreg[cChannel] = cData; - } - if (cChannel < 3) - { - } - else if ((cCaps & OPNA_HAS_EXTENDEDFM) && (cChannel >= 4) && (cChannel < 7)) - { - cChannel--; - } - else - { - return; - } - - if (!pExt) - { - opngen_keyon(&opna->opngen, cChannel, cData); - } - else - { - pExt->WriteRegister(nAddress, cData); - } - keydisp_opnakeyon(opna->s.reg, cData); - } - else if (nAddress == 0x27) - { - if (cCaps & OPNA_HAS_TIMER) - { - opna_settimer(opna, cData); - } - - if (pExt) - { - pExt->WriteRegister(nAddress, cData); - } - else - { - opna->opngen.opnch[2].extop = cData & 0xc0; - } - } - else if (nAddress == 0x22) - { - if (pExt) - { - pExt->WriteRegister(nAddress, cData); - } - } - } - else if (nAddress < 0xc0) - { - if ((cCaps & OPNA_HAS_VR) && ((nAddress & 0xfc) == 0xb4)) - { - switch (cData & 0xc0) - { - case 0x40: - case 0x80: - cData ^= 0xc0; - break; - } - } - if (!pExt) - { - opngen_setreg(&opna->opngen, 0, nAddress, cData); - } - else - { - pExt->WriteRegister(nAddress, cData); - } - } -} - -/** - * Writes extended register - * @param[in] opna The instance - * @param[in] nAddress The address - * @param[in] cData The data - */ -void opna_writeExtendedRegister(POPNA opna, UINT nAddress, REG8 cData) -{ - opna->s.reg[nAddress + 0x100] = cData; - - if (opna->s.cCaps & OPNA_S98) - { - S98_put(EXTEND2608, nAddress, cData); - } - - writeExtendedRegister(opna, nAddress, cData); -#if defined(SUPPORT_FMGEN) - if(opna->usefmgen) { - OPNA_SetReg(opna->fmgen, nAddress + 0x100, cData); - } -#endif /* SUPPORT_FMGEN */ -} - -/** - * Writes extended register (Inner) - * @param[in] opna The instance - * @param[in] nAddress The address - * @param[in] cData The data - */ -static void writeExtendedRegister(POPNA opna, UINT nAddress, REG8 cData) -{ - const UINT8 cCaps = opna->s.cCaps; - CExternalOpna* pExt = reinterpret_cast(opna->userdata); - - if (nAddress < 0x12) - { - if (cCaps & OPNA_HAS_ADPCM) - { - if ((cCaps & OPNA_HAS_VR) && (nAddress == 0x01)) - { - switch (cData & 0xc0) - { - case 0x40: - case 0x80: - cData ^= 0xc0; - break; - } - } - adpcm_setreg(&opna->adpcm, nAddress, cData); - if ((pExt) && (pExt->HasADPCM())) - { - pExt->WriteRegister(nAddress + 0x100, cData); - } - } - else - { - if (nAddress == 0x10) - { - if (!(cData & 0x80)) - { - opna->s.adpcmmask = ~(cData & 0x1c); - } - } - } - } - else if (nAddress >= 0x30) - { - if (cCaps & OPNA_HAS_EXTENDEDFM) - { - if ((cCaps & OPNA_HAS_VR) && ((nAddress & 0xfc) == 0xb4)) - { - switch (cData & 0xc0) - { - case 0x40: - case 0x80: - cData ^= 0xc0; - break; - } - } - if (!pExt) - { - opngen_setreg(&opna->opngen, 3, nAddress, cData); - } - else - { - pExt->WriteRegister(nAddress + 0x100, cData); - } - } - } -} - -/** - * Reads register - * @param[in] opna The instance - * @param[in] nAddress The address - * @return data - */ -REG8 opna_readRegister(POPNA opna, UINT nAddress) -{ - if (nAddress < 0x10) - { - if (!(opna->s.cCaps & OPNA_HAS_PSG)) - { - return 0xff; - } - } - else if (nAddress < 0x20) - { - if (!(opna->s.cCaps & OPNA_HAS_RHYTHM)) - { - return 0xff; - } - } - else if (nAddress == 0xff) - { - return (opna->s.cCaps & OPNA_HAS_RHYTHM) ? 1 : 0; - } - return opna->s.reg[nAddress]; -} - -/** - * Reads extended register - * @param[in] opna The instance - * @param[in] nAddress The address - * @return data - */ -REG8 opna_readExtendedRegister(POPNA opna, UINT nAddress) -{ - if ((opna->s.cCaps & OPNA_HAS_ADPCM) && (nAddress == 0x08)) - { - return adpcm_readsample(&opna->adpcm); - } - return opna->s.reg[nAddress + 0x100]; -} - -/** - * Reads 3438 extended register - * @param[in] opna The instance - * @param[in] nAddress The address - * @return data - */ -REG8 opna_read3438ExtRegister(POPNA opna, UINT nAddress) -{ - return opna->s.reg[nAddress]; -} - - - -// ---- statsave - -/** - * Save - * @param[in] opna The instance - * @param[in] sfh The handle of statsave - * @param[in] tbl The item of statsave - * @return Error - */ -int opna_sfsave(PCOPNA opna, STFLAGH sfh, const SFENTRY *tbl) -{ - int ret = statflag_write(sfh, &opna->s, sizeof(opna->s)); - if (opna->s.cCaps & OPNA_HAS_ADPCM) - { - ret |= statflag_write(sfh, &opna->adpcm, sizeof(opna->adpcm)); - } -#if defined(SUPPORT_FMGEN) - ret |= statflag_write(sfh, &opna->usefmgen, sizeof(opna->usefmgen)); - if(opna->usefmgen) { - void* buf; - - buf = malloc(fmgen_opnadata_size); - OPNA_DataSave(opna->fmgen, buf); - ret |= statflag_write(sfh, buf, fmgen_opnadata_size); - free(buf); - } -#endif /* SUPPORT_FMGEN */ - - return ret; -} - -/** - * Load - * @param[in] opna The instance - * @param[in] sfh The handle of statsave - * @param[in] tbl The item of statsave - * @return Error - */ -int opna_sfload(POPNA opna, STFLAGH sfh, const SFENTRY *tbl) -{ - int ret = statflag_read(sfh, &opna->s, sizeof(opna->s)); - if (opna->s.cCaps & OPNA_HAS_ADPCM) - { - ret |= statflag_read(sfh, &opna->adpcm, sizeof(opna->adpcm)); - adpcm_update(&opna->adpcm); - } -#if defined(SUPPORT_FMGEN) - if(statflag_read(sfh, &opna->usefmgen, sizeof(opna->usefmgen))==STATFLAG_SUCCESS){ - if(opna->usefmgen) { - OEMCHAR path[MAX_PATH]; - char strbuf[MAX_PATH] = {0}; - void* buf; - buf = malloc(fmgen_opnadata_size); - ret |= statflag_read(sfh, buf, fmgen_opnadata_size); - OPNA_DataLoad(opna->fmgen, buf); - free(buf); - getbiospath(path, OEMTEXT(""), NELEMENTS(path)); -#ifdef UNICODE - wcstombs(strbuf, path, MAX_PATH); -#else - strcpy(strbuf, path); -#endif - OPNA_LoadRhythmSample(opna->fmgen, strbuf); - } - }else{ - opna->usefmgen = 0; - } -#endif /* SUPPORT_FMGEN */ - - return ret; -} +/** + * @file opna.cpp + * @brief Implementation of OPNA + */ + +#include +#include +#include "sound/opna.h" +#include +#include +#include +#include +#include +#include +#include "externalchipmanager.h" +#include "externalopna.h" +#if defined(SUPPORT_FMGEN) +#include +#endif /* SUPPORT_FMGEN */ + +static void writeRegister(POPNA opna, UINT nAddress, REG8 cData); +static void writeExtendedRegister(POPNA opna, UINT nAddress, REG8 cData); + +// dB = 20 log10( (音量0~1) * (pow(10, 最大dB値/20) - pow(10, 最小dB値/20)) + pow(10, 最小dB値/20) ) +//#define LINEAR2DB(a) (20 * log10((a) * (pow(10.0, 20/20) - pow(10.0, -192/20)) + pow(10.0, -192/20))) +#define LINEAR2DB(a) (pow(a,0.12)*(20+192) - 192) // XXX: fmgen音量と猫音源音量を一致させるための実験式・・・ + +#if defined(SUPPORT_FMGEN) +// XXX: 音量調整を出来るようにするためにとりあえず・・・ +POPNA opnalist[OPNA_MAX] = {0}; +int opnalistconunt = 0; +void opnalist_push(POPNA opna) +{ + int i; + for(i=0;ifmgen, (int)LINEAR2DB((double)lvol / 128)); + } +} +void opna_fmgen_setallvolumePSG_linear(int lvol) +{ + for(int i=0;ifmgen, (int)LINEAR2DB((double)lvol / 128)); + } +} +void opna_fmgen_setallvolumeADPCM_linear(int lvol) +{ + for(int i=0;ifmgen, (int)LINEAR2DB((double)lvol / 128)); + } +} +void opna_fmgen_setallvolumeRhythmTotal_linear(int lvol) +{ + for(int i=0;ifmgen, (int)LINEAR2DB((double)lvol / 128)); + } +} +#endif /* SUPPORT_FMGEN */ + +/** + * Initialize instance + * @param[in] opna The instance + */ +void opna_construct(POPNA opna) +{ +#if defined(SUPPORT_FMGEN) + if(opna->fmgen) OPNA_Destruct(opna->fmgen); +#endif /* SUPPORT_FMGEN */ + memset(opna, 0, sizeof(*opna)); +#if defined(SUPPORT_FMGEN) + opna->fmgen = OPNA_Construct(); + opnalist_push(opna); +#endif /* SUPPORT_FMGEN */ +} + +/** + * Deinitialize instance + * @param[in] opna The instance + */ +void opna_destruct(POPNA opna) +{ +#if defined(SUPPORT_FMGEN) + if(opna->fmgen) { + if(opna->fmgen) OPNA_Destruct(opna->fmgen); + opna->fmgen = NULL; + opnalist_remove(opna); + } +#endif /* SUPPORT_FMGEN */ + CExternalOpna* pExt = reinterpret_cast(opna->userdata); + CExternalChipManager::GetInstance()->Release(pExt); + opna->userdata = NULL; +} + +/** + * Reset + * @param[in] opna The instance + * @param[in] cCaps + */ +void opna_reset(POPNA opna, REG8 cCaps) +{ + memset(&opna->s, 0, sizeof(opna->s)); + opna->s.adpcmmask = ~(0x1c); + opna->s.cCaps = cCaps; + opna->s.irq = 0xff; + opna->s.reg[0x07] = 0xbf; + opna->s.reg[0x0e] = 0xff; + opna->s.reg[0x0f] = 0xff; + opna->s.reg[0xff] = (cCaps & OPNA_HAS_RHYTHM) ? 0x01 : 0x00; + for (UINT i = 0; i < 2; i++) + { + memset(opna->s.reg + (i * 0x100) + 0x30, 0xff, 0x60); + memset(opna->s.reg + (i * 0x100) + 0xb4, 0xc0, 0x04); + } + for (UINT i = 0; i < 7; i++) + { + opna->s.keyreg[i] = i & 7; + } +#if defined(SUPPORT_FMGEN) + if(np2cfg.usefmgen) { + OEMCHAR path[MAX_PATH]; + char strbuf[MAX_PATH]; + + OPNA_Init(opna->fmgen, OPNA_CLOCK*2, soundcfg.rate, false, ""); // サンプリングレート強制変更・・・ + getbiospath(path, OEMTEXT(""), NELEMENTS(path)); +#ifdef UNICODE + wcstombs(strbuf, path, MAX_PATH); +#else + strcpy(strbuf, path); +#endif + OPNA_LoadRhythmSample(opna->fmgen, strbuf); + OPNA_SetVolumeFM(opna->fmgen, (int)LINEAR2DB((double)np2cfg.vol_fm / 128 * np2cfg.vol_master / 100)); + OPNA_SetVolumePSG(opna->fmgen, (int)LINEAR2DB((double)np2cfg.vol_ssg / 128 * np2cfg.vol_master / 100)); + OPNA_SetVolumeADPCM(opna->fmgen, (int)LINEAR2DB((double)np2cfg.vol_adpcm / 128 * np2cfg.vol_master / 100)); + OPNA_SetVolumeRhythmTotal(opna->fmgen, (int)LINEAR2DB((double)np2cfg.vol_rhythm / 128 * np2cfg.vol_master / 100)); + OPNA_Reset(opna->fmgen); + OPNA_SetReg(opna->fmgen, 0x07, 0xbf); + OPNA_SetReg(opna->fmgen, 0x0e, 0xff); + OPNA_SetReg(opna->fmgen, 0x0f, 0xff); + OPNA_SetReg(opna->fmgen, 0xff, 0x01); + for (UINT i = 0; i < 2; i++) + { + for (UINT j = 0; j < 0x60; j++) { + OPNA_SetReg(opna->fmgen, (i * 0x100) + 0x30 + j, 0xff); + } + for (UINT j = 0; j < 0x04; j++) { + OPNA_SetReg(opna->fmgen, (i * 0x100) + 0xb4 + j, 0xc0); + } + } + opna->usefmgen = 1; + }else{ + opna->usefmgen = 0; // fmgenを使わない + } +#endif /* SUPPORT_FMGEN */ + + opngen_reset(&opna->opngen); + psggen_reset(&opna->psg); + rhythm_reset(&opna->rhythm); + adpcm_reset(&opna->adpcm); + + if (cCaps == 0) + { + CExternalOpna* pExt = reinterpret_cast(opna->userdata); + if (pExt) + { + CExternalChipManager::GetInstance()->Release(pExt); + opna->userdata = NULL; + } + } + + // 音量初期化 + opngen_setvol(np2cfg.vol_fm * np2cfg.vol_master / 100); + psggen_setvol(np2cfg.vol_ssg * np2cfg.vol_master / 100); + rhythm_setvol(np2cfg.vol_rhythm * np2cfg.vol_master / 100); +#if defined(SUPPORT_FMGEN) + if(np2cfg.usefmgen) { + opna_fmgen_setallvolumeFM_linear(np2cfg.vol_fm * np2cfg.vol_master / 100); + opna_fmgen_setallvolumePSG_linear(np2cfg.vol_ssg * np2cfg.vol_master / 100); + opna_fmgen_setallvolumeRhythmTotal_linear(np2cfg.vol_rhythm * np2cfg.vol_master / 100); + } +#endif /* SUPPORT_FMGEN */ + for (UINT i = 0; i < NELEMENTS(g_opna); i++) + { + rhythm_update(&g_opna[i].rhythm); + } +} + +/** + * Restore + * @param[in] opna The instance + */ +static void restore(POPNA opna) +{ + // FM + writeRegister(opna, 0x22, opna->s.reg[0x22]); + for (UINT i = 0x30; i < 0xa0; i++) + { + if ((i & 3) == 3) + { + continue; + } + writeRegister(opna, i, opna->s.reg[i]); + writeExtendedRegister(opna, i, opna->s.reg[i + 0x100]); + } + for (UINT i = 0xb0; i < 0xb8; i++) + { + if ((i & 3) == 3) + { + continue; + } + writeRegister(opna, i, opna->s.reg[i]); + writeExtendedRegister(opna, i, opna->s.reg[i + 0x100]); + } + for (UINT i = 0; i < 8; i++) + { + if ((i & 3) == 3) + { + continue; + } + writeRegister(opna, i + 0xa4, opna->s.reg[i + 0xa4]); + writeRegister(opna, i + 0xa0, opna->s.reg[i + 0xa0]); + writeExtendedRegister(opna, i + 0xa4, opna->s.reg[i + 0x1a4]); + writeExtendedRegister(opna, i + 0xa0, opna->s.reg[i + 0x1a0]); + } + for (UINT i = 0; i < 8; i++) + { + if ((i & 3) == 3) + { + continue; + } + writeRegister(opna, 0x28, opna->s.keyreg[i]); + } +#if defined(SUPPORT_FMGEN) + if(opna->usefmgen) { + OPNA_SetReg(opna->fmgen, 0x22, opna->s.reg[0x22]); + for (UINT i = 0x30; i < 0xa0; i++) + { + if ((i & 3) == 3) + { + continue; + } + OPNA_SetReg(opna->fmgen, i, opna->s.reg[i]); + OPNA_SetReg(opna->fmgen, i + 0x100, opna->s.reg[i + 0x100]); + } + for (UINT i = 0xb0; i < 0xb8; i++) + { + if ((i & 3) == 3) + { + continue; + } + OPNA_SetReg(opna->fmgen, i, opna->s.reg[i]); + OPNA_SetReg(opna->fmgen, i + 0x100, opna->s.reg[i + 0x100]); + } + for (UINT i = 0; i < 8; i++) + { + if ((i & 3) == 3) + { + continue; + } + OPNA_SetReg(opna->fmgen, i + 0xa4, opna->s.reg[i + 0xa4]); + OPNA_SetReg(opna->fmgen, i + 0xa0, opna->s.reg[i + 0xa0]); + OPNA_SetReg(opna->fmgen, i + 0x1a4, opna->s.reg[i + 0x1a4]); + OPNA_SetReg(opna->fmgen, i + 0x1a0, opna->s.reg[i + 0x1a0]); + } + for (UINT i = 0; i < 8; i++) + { + if ((i & 3) == 3) + { + continue; + } + OPNA_SetReg(opna->fmgen, 0x28, opna->s.keyreg[i]); + } + } +#endif /* SUPPORT_FMGEN */ + + // PSG + for (UINT i = 0; i < 0x10; i++) + { + writeRegister(opna, i, opna->s.reg[i]); + } +#if defined(SUPPORT_FMGEN) + if(opna->usefmgen) { + for (UINT i = 0; i < 0x10; i++) + { + OPNA_SetReg(opna->fmgen, i, opna->s.reg[i]); + } + } +#endif /* SUPPORT_FMGEN */ + + // Rhythm + writeRegister(opna, 0x11, opna->s.reg[0x11]); + for (UINT i = 0x18; i < 0x1e; i++) + { + writeRegister(opna, i, opna->s.reg[i]); + } +#if defined(SUPPORT_FMGEN) + if(opna->usefmgen) { + OPNA_SetReg(opna->fmgen, 0x11, opna->s.reg[0x11]); + for (UINT i = 0x18; i < 0x1e; i++) + { + OPNA_SetReg(opna->fmgen, i, opna->s.reg[i]); + } + } +#endif /* SUPPORT_FMGEN */ +} + +/** + * Bind + * @param[in] opna The instance + */ +void opna_bind(POPNA opna) +{ + UINT8 cCaps = opna->s.cCaps; + UINT nClock = 3993600; + + keydisp_bindopna(opna->s.reg, (cCaps & OPNA_HAS_EXTENDEDFM) ? 6 : 3, nClock); + if (cCaps & OPNA_HAS_PSG) + { + keydisp_bindpsg(opna->s.reg, nClock); + } + + CExternalOpna* pExt = reinterpret_cast(opna->userdata); + if (pExt == NULL) + { + IExternalChip::ChipType nChipType = IExternalChip::kYM2203; + if (cCaps & OPNA_HAS_EXTENDEDFM) + { + nChipType = IExternalChip::kYMF288; + nClock *= 2; + if (cCaps & OPNA_HAS_ADPCM) + { + nChipType = IExternalChip::kYM2608; + } + else if (cCaps == OPNA_MODE_3438) + { + nChipType = IExternalChip::kYM3438; + } + } + pExt = static_cast(CExternalChipManager::GetInstance()->GetInterface(nChipType, nClock)); + opna->userdata = reinterpret_cast(pExt); + } + if (pExt) + { + pExt->Reset(); + pExt->WriteRegister(0x22, 0x00); + pExt->WriteRegister(0x29, 0x80); + pExt->WriteRegister(0x10, 0xbf); + pExt->WriteRegister(0x11, 0x30); + pExt->WriteRegister(0x27, opna->s.reg[0x27]); + +#if defined(SUPPORT_FMGEN) + opna->usefmgen = 0; // 外部があればfmgenを使わない +#endif /* SUPPORT_FMGEN */ + } + else + { + opna->opngen.opnch[2].extop = opna->s.reg[0x27] & 0xc0; + } + restore(opna); + +#if defined(SUPPORT_FMGEN) + if(opna->usefmgen) { + if (!pExt) + { + sound_streamregist(opna->fmgen, (SOUNDCB)OPNA_Mix); + } + if (cCaps & OPNA_HAS_RHYTHM) + { + rhythm_bind(&opna->rhythm); + } + } else { +#endif /* SUPPORT_FMGEN */ + if (pExt) + { + if ((cCaps & OPNA_HAS_PSG) && (pExt->HasPsg())) + { + cCaps &= ~OPNA_HAS_PSG; + } + if ((cCaps & OPNA_HAS_RHYTHM) && (pExt->HasRhythm())) + { + cCaps &= ~OPNA_HAS_RHYTHM; + } + if ((cCaps & OPNA_HAS_ADPCM) && (pExt->HasADPCM())) + { + sound_streamregist(&opna->adpcm, (SOUNDCB)adpcm_getpcm_dummy); + cCaps &= ~OPNA_HAS_ADPCM; + } + } + + if (cCaps & OPNA_HAS_PSG) + { + sound_streamregist(&opna->psg, (SOUNDCB)psggen_getpcm); + } + if (cCaps & OPNA_HAS_VR) + { + sound_streamregist(&opna->opngen, (SOUNDCB)opngen_getpcmvr); + } + else + { + sound_streamregist(&opna->opngen, (SOUNDCB)opngen_getpcm); + } + if (cCaps & OPNA_HAS_RHYTHM) + { + rhythm_bind(&opna->rhythm); + } + if (cCaps & OPNA_HAS_ADPCM) + { + sound_streamregist(&opna->adpcm, (SOUNDCB)adpcm_getpcm); + } +#if defined(SUPPORT_FMGEN) + } +#endif /* SUPPORT_FMGEN */ +} + +/** + * Status + * @param[in] opna The instance + * @return Status + */ +REG8 opna_readStatus(POPNA opna) +{ + if (opna->s.cCaps & OPNA_HAS_TIMER) + { + return opna->s.status; + } + return 0; +} + +/** + * Status + * @param[in] opna The instance + * @return Status + */ +REG8 opna_readExtendedStatus(POPNA opna) +{ + const UINT8 cCaps = opna->s.cCaps; + REG8 ret = 0; + + if (cCaps & OPNA_HAS_ADPCM) + { + ret = adpcm_status(&opna->adpcm); + } + else + { + ret = opna->s.adpcmmask & 8; + } + + if (cCaps & OPNA_HAS_TIMER) + { + ret |= opna->s.status; + } + + return ret; +} + +/** + * Writes register + * @param[in] opna The instance + * @param[in] nAddress The address + * @param[in] cData The data + */ +void opna_writeRegister(POPNA opna, UINT nAddress, REG8 cData) +{ + opna->s.reg[nAddress] = cData; + + if (opna->s.cCaps & OPNA_S98) + { + S98_put(NORMAL2608, nAddress, cData); + } + + writeRegister(opna, nAddress, cData); +#if defined(SUPPORT_FMGEN) + if(opna->usefmgen) { + OPNA_SetReg(opna->fmgen, nAddress, cData); + } +#endif /* SUPPORT_FMGEN */ +} + +/** + * Writes register (Inner) + * @param[in] opna The instance + * @param[in] nAddress The address + * @param[in] cData The data + */ +static void writeRegister(POPNA opna, UINT nAddress, REG8 cData) +{ + const UINT8 cCaps = opna->s.cCaps; + CExternalOpna* pExt = reinterpret_cast(opna->userdata); + + if (nAddress < 0x10) + { + if (cCaps & OPNA_HAS_PSG) + { + keydisp_psg(opna->s.reg, nAddress); + if ((!pExt) || (!pExt->HasPsg())) + { + psggen_setreg(&opna->psg, nAddress, cData); + } + else + { + pExt->WriteRegister(nAddress, cData); + } + } + } + else if (nAddress < 0x20) + { + if (cCaps & OPNA_HAS_RHYTHM) + { + if ((cCaps & OPNA_HAS_VR) && (nAddress >= 0x18) && (nAddress <= 0x1d)) + { + switch (cData & 0xc0) + { + case 0x40: + case 0x80: + cData ^= 0xc0; + break; + } + } + if ((!pExt) || (!pExt->HasRhythm())) + { + rhythm_setreg(&opna->rhythm, nAddress, cData); + } + else + { + pExt->WriteRegister(nAddress, cData); + } + } + } + else if (nAddress < 0x30) + { + if (nAddress == 0x28) + { + REG8 cChannel = cData & 0x0f; + if (cChannel < 8) + { + opna->s.keyreg[cChannel] = cData; + } + if (cChannel < 3) + { + } + else if ((cCaps & OPNA_HAS_EXTENDEDFM) && (cChannel >= 4) && (cChannel < 7)) + { + cChannel--; + } + else + { + return; + } + + if (!pExt) + { + opngen_keyon(&opna->opngen, cChannel, cData); + } + else + { + pExt->WriteRegister(nAddress, cData); + } + keydisp_opnakeyon(opna->s.reg, cData); + } + else if (nAddress == 0x27) + { + if (cCaps & OPNA_HAS_TIMER) + { + opna_settimer(opna, cData); + } + + if (pExt) + { + pExt->WriteRegister(nAddress, cData); + } + else + { + opna->opngen.opnch[2].extop = cData & 0xc0; + } + } + else if (nAddress == 0x22) + { + if (pExt) + { + pExt->WriteRegister(nAddress, cData); + } + } + } + else if (nAddress < 0xc0) + { + if ((cCaps & OPNA_HAS_VR) && ((nAddress & 0xfc) == 0xb4)) + { + switch (cData & 0xc0) + { + case 0x40: + case 0x80: + cData ^= 0xc0; + break; + } + } + if (!pExt) + { + opngen_setreg(&opna->opngen, 0, nAddress, cData); + } + else + { + pExt->WriteRegister(nAddress, cData); + } + } +} + +/** + * Writes extended register + * @param[in] opna The instance + * @param[in] nAddress The address + * @param[in] cData The data + */ +void opna_writeExtendedRegister(POPNA opna, UINT nAddress, REG8 cData) +{ + opna->s.reg[nAddress + 0x100] = cData; + + if (opna->s.cCaps & OPNA_S98) + { + S98_put(EXTEND2608, nAddress, cData); + } + + writeExtendedRegister(opna, nAddress, cData); +#if defined(SUPPORT_FMGEN) + if(opna->usefmgen) { + OPNA_SetReg(opna->fmgen, nAddress + 0x100, cData); + } +#endif /* SUPPORT_FMGEN */ +} + +/** + * Writes extended register (Inner) + * @param[in] opna The instance + * @param[in] nAddress The address + * @param[in] cData The data + */ +static void writeExtendedRegister(POPNA opna, UINT nAddress, REG8 cData) +{ + const UINT8 cCaps = opna->s.cCaps; + CExternalOpna* pExt = reinterpret_cast(opna->userdata); + + if (nAddress < 0x12) + { + if (cCaps & OPNA_HAS_ADPCM) + { + if ((cCaps & OPNA_HAS_VR) && (nAddress == 0x01)) + { + switch (cData & 0xc0) + { + case 0x40: + case 0x80: + cData ^= 0xc0; + break; + } + } + adpcm_setreg(&opna->adpcm, nAddress, cData); + if ((pExt) && (pExt->HasADPCM())) + { + pExt->WriteRegister(nAddress + 0x100, cData); + } + } + else + { + if (nAddress == 0x10) + { + if (!(cData & 0x80)) + { + opna->s.adpcmmask = ~(cData & 0x1c); + } + } + } + } + else if (nAddress >= 0x30) + { + if (cCaps & OPNA_HAS_EXTENDEDFM) + { + if ((cCaps & OPNA_HAS_VR) && ((nAddress & 0xfc) == 0xb4)) + { + switch (cData & 0xc0) + { + case 0x40: + case 0x80: + cData ^= 0xc0; + break; + } + } + if (!pExt) + { + opngen_setreg(&opna->opngen, 3, nAddress, cData); + } + else + { + pExt->WriteRegister(nAddress + 0x100, cData); + } + } + } +} + +/** + * Reads register + * @param[in] opna The instance + * @param[in] nAddress The address + * @return data + */ +REG8 opna_readRegister(POPNA opna, UINT nAddress) +{ + if (nAddress < 0x10) + { + if (!(opna->s.cCaps & OPNA_HAS_PSG)) + { + return 0xff; + } + } + else if (nAddress < 0x20) + { + if (!(opna->s.cCaps & OPNA_HAS_RHYTHM)) + { + return 0xff; + } + } + else if (nAddress == 0xff) + { + return (opna->s.cCaps & OPNA_HAS_RHYTHM) ? 1 : 0; + } + return opna->s.reg[nAddress]; +} + +/** + * Reads extended register + * @param[in] opna The instance + * @param[in] nAddress The address + * @return data + */ +REG8 opna_readExtendedRegister(POPNA opna, UINT nAddress) +{ + if ((opna->s.cCaps & OPNA_HAS_ADPCM) && (nAddress == 0x08)) + { + return adpcm_readsample(&opna->adpcm); + } + return opna->s.reg[nAddress + 0x100]; +} + +/** + * Reads 3438 extended register + * @param[in] opna The instance + * @param[in] nAddress The address + * @return data + */ +REG8 opna_read3438ExtRegister(POPNA opna, UINT nAddress) +{ + return opna->s.reg[nAddress]; +} + + + +// ---- statsave + +/** + * Save + * @param[in] opna The instance + * @param[in] sfh The handle of statsave + * @param[in] tbl The item of statsave + * @return Error + */ +int opna_sfsave(PCOPNA opna, STFLAGH sfh, const SFENTRY *tbl) +{ + int ret = statflag_write(sfh, &opna->s, sizeof(opna->s)); + if (opna->s.cCaps & OPNA_HAS_ADPCM) + { + ret |= statflag_write(sfh, &opna->adpcm, sizeof(opna->adpcm)); + } +#if defined(SUPPORT_FMGEN) + ret |= statflag_write(sfh, &opna->usefmgen, sizeof(opna->usefmgen)); + if(opna->usefmgen) { + void* buf; + + buf = malloc(fmgen_opnadata_size); + OPNA_DataSave(opna->fmgen, buf); + ret |= statflag_write(sfh, buf, fmgen_opnadata_size); + free(buf); + } +#endif /* SUPPORT_FMGEN */ + + return ret; +} + +/** + * Load + * @param[in] opna The instance + * @param[in] sfh The handle of statsave + * @param[in] tbl The item of statsave + * @return Error + */ +int opna_sfload(POPNA opna, STFLAGH sfh, const SFENTRY *tbl) +{ + int ret = statflag_read(sfh, &opna->s, sizeof(opna->s)); + if (opna->s.cCaps & OPNA_HAS_ADPCM) + { + ret |= statflag_read(sfh, &opna->adpcm, sizeof(opna->adpcm)); + adpcm_update(&opna->adpcm); + } +#if defined(SUPPORT_FMGEN) + if(statflag_read(sfh, &opna->usefmgen, sizeof(opna->usefmgen))==STATFLAG_SUCCESS){ + if(opna->usefmgen) { + OEMCHAR path[MAX_PATH]; + char strbuf[MAX_PATH] = {0}; + void* buf; + buf = malloc(fmgen_opnadata_size); + ret |= statflag_read(sfh, buf, fmgen_opnadata_size); + OPNA_DataLoad(opna->fmgen, buf); + free(buf); + getbiospath(path, OEMTEXT(""), NELEMENTS(path)); +#ifdef UNICODE + wcstombs(strbuf, path, MAX_PATH); +#else + strcpy(strbuf, path); +#endif + OPNA_LoadRhythmSample(opna->fmgen, strbuf); + } + }else{ + opna->usefmgen = 0; + } +#endif /* SUPPORT_FMGEN */ + + return ret; +} diff --git a/windows/ext/romeo/juliet.cpp b/windows/ext/romeo/juliet.cpp old mode 100755 new mode 100644 index 8ef567ed..69da7e1a --- a/windows/ext/romeo/juliet.cpp +++ b/windows/ext/romeo/juliet.cpp @@ -1,339 +1,339 @@ -/** - * @file juliet.cpp - * @brief ROMEO アクセス クラスの動作の定義を行います - */ - -#include -#include "juliet.h" -#include -#include "romeo.h" - -//! DLL 名 -#define PCIDEBUG_DLL TEXT("pcidebug.dll") - -//! PCI デバイス アドレスを作成 -#define PCIBUSDEVFUNC(b, d, f) (((b) << 8) | ((d) << 3) | (f)) - -//! ベンダ/デバイスを作成 -#define DEVVEND(v, d) ((ULONG)((v) | ((d) << 16))) - -/** - * コンストラクタ - */ -CJuliet::CJuliet() - : m_hModule(NULL) - , m_fnRead32(NULL) - , m_fnOut8(NULL) - , m_fnOut32(NULL) - , m_fnIn8(NULL) - , m_ulAddress(0) - , m_ucIrq(0) - , m_nQueIndex(0) - , m_nQueCount(0) - , m_pChip288(NULL) -{ -} - -/** - * デストラクタ - */ -CJuliet::~CJuliet() -{ -} - -/** - * 初期化 - * @retval true 成功 - * @retval false 失敗 - */ -bool CJuliet::Initialize() -{ - if (m_hModule) - { - return false; - } - - m_hModule = ::LoadLibrary(PCIDEBUG_DLL); - if (m_hModule == NULL) - { - return false; - } - - //! ロード関数リスト - static const ProcItem s_dllProc[] = - { - {"_pciConfigReadLong", offsetof(CJuliet, m_fnRead32)}, - {"_MemWriteChar", offsetof(CJuliet, m_fnOut8)}, - {"_MemWriteLong", offsetof(CJuliet, m_fnOut32)}, - {"_MemReadChar", offsetof(CJuliet, m_fnIn8)}, - }; - - for (size_t i = 0; i < _countof(s_dllProc); i++) - { - FARPROC proc = ::GetProcAddress(m_hModule, s_dllProc[i].lpSymbol); - if (proc == NULL) - { - Deinitialize(); - return false; - } - *(reinterpret_cast(reinterpret_cast(this) + s_dllProc[i].nOffset)) = proc; - } - - const ULONG ulPciAddress = SearchRomeo(); - if (ulPciAddress == static_cast(-1)) - { - Deinitialize(); - return false; - } - m_ulAddress = (*m_fnRead32)(ulPciAddress, ROMEO_BASEADDRESS1); - m_ucIrq = static_cast((*m_fnRead32)(ulPciAddress, ROMEO_PCIINTERRUPT)); - if (!m_ulAddress) - { - Deinitialize(); - return false; - } - - Reset(); - Start(); - - return true; -} - -/** - * 解放 - */ -void CJuliet::Deinitialize() -{ - Stop(); - m_nQueIndex = 0; - m_nQueCount = 0; - - if (m_pChip288) - { - delete m_pChip288; - } - - if (m_hModule) - { - ::FreeLibrary(m_hModule); - m_hModule = NULL; - m_fnRead32 = NULL; - m_fnOut8 = NULL; - m_fnOut32 = NULL; - m_fnIn8 = NULL; - m_ulAddress = 0; - m_ucIrq = 0; - } -} - -/** - * ROMEO を探す - * @note pciFindPciDevice使うと、OS起動後一発目に見つけられないことが多いので、自前で検索する(矢野さん方式) - * @return バス アドレス - */ -ULONG CJuliet::SearchRomeo() const -{ - for (UINT bus = 0; bus < 0x100; bus++) - { - for (UINT dev = 0; dev < 0x20; dev++) - { - for (UINT func = 0; func < 0x08; func++) - { - const ULONG ulPciAddress = PCIBUSDEVFUNC(bus, dev, func); - const ULONG ulDeviceVendor = (*m_fnRead32)(ulPciAddress, 0x0000); - if ((ulDeviceVendor == DEVVEND(ROMEO_VENDORID, ROMEO_DEVICEID)) || (ulDeviceVendor == DEVVEND(ROMEO_VENDORID, ROMEO_DEVICEID2))) - { - return ulPciAddress; - } - } - } - } - return static_cast(-1); -} - -/** - * 音源リセット - */ -void CJuliet::Reset() -{ - m_queGuard.Enter(); - m_nQueIndex = 0; - m_nQueCount = 0; - m_queGuard.Leave(); - - m_pciGuard.Enter(); - if (m_fnOut32 != NULL) - { - (*m_fnOut32)(m_ulAddress + ROMEO_YMF288CTRL, 0x00); - ::Sleep(150); - - (*m_fnOut32)(m_ulAddress + ROMEO_YMF288CTRL, 0x80); - ::Sleep(150); - } - m_pciGuard.Leave(); -} - -/** - * インターフェイス取得 - * @param[in] nChipType タイプ - * @param[in] nClock クロック - * @return インスタンス - */ -IExternalChip* CJuliet::GetInterface(IExternalChip::ChipType nChipType, UINT nClock) -{ - const bool bInitialized = Initialize(); - - do - { - if (m_hModule == NULL) - { - break; - } - - if ((nChipType == IExternalChip::kYMF288) && (m_pChip288 == NULL)) - { - m_pChip288 = new Chip288(this); - return m_pChip288; - } - } while (false /*CONSTCOND*/); - - if (bInitialized) - { -// Deinitialize(); - } - - return NULL; -} - -/** - * 解放 - * @param[in] pChip チップ - */ -void CJuliet::Detach(IExternalChip* pChip) -{ - if (m_pChip288 == pChip) - { - m_pChip288 = NULL; - } -} - -/** - * Write - * @param[in] nAddr The address of registers - * @param[in] cData The data - */ -void CJuliet::Write288(UINT nAddr, UINT8 cData) -{ - m_queGuard.Enter(); - while (m_nQueCount >= _countof(m_que)) - { - m_queGuard.Leave(); - Delay(1000); - m_queGuard.Enter(); - } - - m_que[(m_nQueIndex + m_nQueCount) % _countof(m_que)] = ((nAddr & 0x1ff) << 8) | cData; - m_nQueCount++; - - m_queGuard.Leave(); -} - -/** - * Thread - * @retval true Cont. - */ -bool CJuliet::Task() -{ - m_queGuard.Enter(); - if (m_nQueCount == 0) - { - m_queGuard.Leave(); - Delay(1000); - } - else - { - while (m_nQueCount) - { - const UINT nData = m_que[m_nQueIndex]; - m_nQueIndex = (m_nQueIndex + 1) % _countof(m_que); - m_nQueCount--; - m_queGuard.Leave(); - - m_pciGuard.Enter(); - while (((*m_fnIn8)(m_ulAddress + ROMEO_YMF288ADDR1) & 0x80) != 0) - { - ::Sleep(0); - } - (*m_fnOut8)(m_ulAddress + ((nData & 0x10000) ? ROMEO_YMF288ADDR2 : ROMEO_YMF288ADDR1), static_cast(nData >> 8)); - - while (((*m_fnIn8)(m_ulAddress + ROMEO_YMF288ADDR1) & 0x80) != 0) - { - ::Sleep(0); - } - (*m_fnOut8)(m_ulAddress + ((nData & 0x10000) ? ROMEO_YMF288DATA2 : ROMEO_YMF288DATA1), static_cast(nData)); - m_pciGuard.Leave(); - - m_queGuard.Enter(); - } - m_queGuard.Leave(); - } - return true; -} - - - -// ---- チップ - -/** - * コンストラクタ - * @param[in] pJuliet 親インスタンス - */ -CJuliet::Chip288::Chip288(CJuliet* pJuliet) - : m_pJuliet(pJuliet) -{ -} - -/** - * デストラクタ - */ -CJuliet::Chip288::~Chip288() -{ - m_pJuliet->Detach(this); -} - -/** - * Get chip type - * @return The type of the chip - */ -IExternalChip::ChipType CJuliet::Chip288::GetChipType() -{ - return IExternalChip::kYMF288; -} - -/** - * リセット - */ -void CJuliet::Chip288::Reset() -{ -} - -/** - * レジスタ書き込み - * @param[in] nAddr アドレス - * @param[in] cData データ - */ -void CJuliet::Chip288::WriteRegister(UINT nAddr, UINT8 cData) -{ - m_pJuliet->Write288(nAddr, cData); -} - -/** - * メッセージ - * @param[in] nMessage メッセージ - * @param[in] nParameter パラメータ - * @return リザルト - */ -INTPTR CJuliet::Chip288::Message(UINT nMessage, INTPTR nParameter) -{ - return 0; -} +/** + * @file juliet.cpp + * @brief ROMEO アクセス クラスの動作の定義を行います + */ + +#include +#include "juliet.h" +#include +#include "romeo.h" + +//! DLL 名 +#define PCIDEBUG_DLL TEXT("pcidebug.dll") + +//! PCI デバイス アドレスを作成 +#define PCIBUSDEVFUNC(b, d, f) (((b) << 8) | ((d) << 3) | (f)) + +//! ベンダ/デバイスを作成 +#define DEVVEND(v, d) ((ULONG)((v) | ((d) << 16))) + +/** + * コンストラクタ + */ +CJuliet::CJuliet() + : m_hModule(NULL) + , m_fnRead32(NULL) + , m_fnOut8(NULL) + , m_fnOut32(NULL) + , m_fnIn8(NULL) + , m_ulAddress(0) + , m_ucIrq(0) + , m_nQueIndex(0) + , m_nQueCount(0) + , m_pChip288(NULL) +{ +} + +/** + * デストラクタ + */ +CJuliet::~CJuliet() +{ +} + +/** + * 初期化 + * @retval true 成功 + * @retval false 失敗 + */ +bool CJuliet::Initialize() +{ + if (m_hModule) + { + return false; + } + + m_hModule = ::LoadLibrary(PCIDEBUG_DLL); + if (m_hModule == NULL) + { + return false; + } + + //! ロード関数リスト + static const ProcItem s_dllProc[] = + { + {"_pciConfigReadLong", offsetof(CJuliet, m_fnRead32)}, + {"_MemWriteChar", offsetof(CJuliet, m_fnOut8)}, + {"_MemWriteLong", offsetof(CJuliet, m_fnOut32)}, + {"_MemReadChar", offsetof(CJuliet, m_fnIn8)}, + }; + + for (size_t i = 0; i < _countof(s_dllProc); i++) + { + FARPROC proc = ::GetProcAddress(m_hModule, s_dllProc[i].lpSymbol); + if (proc == NULL) + { + Deinitialize(); + return false; + } + *(reinterpret_cast(reinterpret_cast(this) + s_dllProc[i].nOffset)) = proc; + } + + const ULONG ulPciAddress = SearchRomeo(); + if (ulPciAddress == static_cast(-1)) + { + Deinitialize(); + return false; + } + m_ulAddress = (*m_fnRead32)(ulPciAddress, ROMEO_BASEADDRESS1); + m_ucIrq = static_cast((*m_fnRead32)(ulPciAddress, ROMEO_PCIINTERRUPT)); + if (!m_ulAddress) + { + Deinitialize(); + return false; + } + + Reset(); + Start(); + + return true; +} + +/** + * 解放 + */ +void CJuliet::Deinitialize() +{ + Stop(); + m_nQueIndex = 0; + m_nQueCount = 0; + + if (m_pChip288) + { + delete m_pChip288; + } + + if (m_hModule) + { + ::FreeLibrary(m_hModule); + m_hModule = NULL; + m_fnRead32 = NULL; + m_fnOut8 = NULL; + m_fnOut32 = NULL; + m_fnIn8 = NULL; + m_ulAddress = 0; + m_ucIrq = 0; + } +} + +/** + * ROMEO を探す + * @note pciFindPciDevice使うと、OS起動後一発目に見つけられないことが多いので、自前で検索する(矢野さん方式) + * @return バス アドレス + */ +ULONG CJuliet::SearchRomeo() const +{ + for (UINT bus = 0; bus < 0x100; bus++) + { + for (UINT dev = 0; dev < 0x20; dev++) + { + for (UINT func = 0; func < 0x08; func++) + { + const ULONG ulPciAddress = PCIBUSDEVFUNC(bus, dev, func); + const ULONG ulDeviceVendor = (*m_fnRead32)(ulPciAddress, 0x0000); + if ((ulDeviceVendor == DEVVEND(ROMEO_VENDORID, ROMEO_DEVICEID)) || (ulDeviceVendor == DEVVEND(ROMEO_VENDORID, ROMEO_DEVICEID2))) + { + return ulPciAddress; + } + } + } + } + return static_cast(-1); +} + +/** + * 音源リセット + */ +void CJuliet::Reset() +{ + m_queGuard.Enter(); + m_nQueIndex = 0; + m_nQueCount = 0; + m_queGuard.Leave(); + + m_pciGuard.Enter(); + if (m_fnOut32 != NULL) + { + (*m_fnOut32)(m_ulAddress + ROMEO_YMF288CTRL, 0x00); + ::Sleep(150); + + (*m_fnOut32)(m_ulAddress + ROMEO_YMF288CTRL, 0x80); + ::Sleep(150); + } + m_pciGuard.Leave(); +} + +/** + * インターフェイス取得 + * @param[in] nChipType タイプ + * @param[in] nClock クロック + * @return インスタンス + */ +IExternalChip* CJuliet::GetInterface(IExternalChip::ChipType nChipType, UINT nClock) +{ + const bool bInitialized = Initialize(); + + do + { + if (m_hModule == NULL) + { + break; + } + + if ((nChipType == IExternalChip::kYMF288) && (m_pChip288 == NULL)) + { + m_pChip288 = new Chip288(this); + return m_pChip288; + } + } while (false /*CONSTCOND*/); + + if (bInitialized) + { +// Deinitialize(); + } + + return NULL; +} + +/** + * 解放 + * @param[in] pChip チップ + */ +void CJuliet::Detach(IExternalChip* pChip) +{ + if (m_pChip288 == pChip) + { + m_pChip288 = NULL; + } +} + +/** + * Write + * @param[in] nAddr The address of registers + * @param[in] cData The data + */ +void CJuliet::Write288(UINT nAddr, UINT8 cData) +{ + m_queGuard.Enter(); + while (m_nQueCount >= _countof(m_que)) + { + m_queGuard.Leave(); + Delay(1000); + m_queGuard.Enter(); + } + + m_que[(m_nQueIndex + m_nQueCount) % _countof(m_que)] = ((nAddr & 0x1ff) << 8) | cData; + m_nQueCount++; + + m_queGuard.Leave(); +} + +/** + * Thread + * @retval true Cont. + */ +bool CJuliet::Task() +{ + m_queGuard.Enter(); + if (m_nQueCount == 0) + { + m_queGuard.Leave(); + Delay(1000); + } + else + { + while (m_nQueCount) + { + const UINT nData = m_que[m_nQueIndex]; + m_nQueIndex = (m_nQueIndex + 1) % _countof(m_que); + m_nQueCount--; + m_queGuard.Leave(); + + m_pciGuard.Enter(); + while (((*m_fnIn8)(m_ulAddress + ROMEO_YMF288ADDR1) & 0x80) != 0) + { + ::Sleep(0); + } + (*m_fnOut8)(m_ulAddress + ((nData & 0x10000) ? ROMEO_YMF288ADDR2 : ROMEO_YMF288ADDR1), static_cast(nData >> 8)); + + while (((*m_fnIn8)(m_ulAddress + ROMEO_YMF288ADDR1) & 0x80) != 0) + { + ::Sleep(0); + } + (*m_fnOut8)(m_ulAddress + ((nData & 0x10000) ? ROMEO_YMF288DATA2 : ROMEO_YMF288DATA1), static_cast(nData)); + m_pciGuard.Leave(); + + m_queGuard.Enter(); + } + m_queGuard.Leave(); + } + return true; +} + + + +// ---- チップ + +/** + * コンストラクタ + * @param[in] pJuliet 親インスタンス + */ +CJuliet::Chip288::Chip288(CJuliet* pJuliet) + : m_pJuliet(pJuliet) +{ +} + +/** + * デストラクタ + */ +CJuliet::Chip288::~Chip288() +{ + m_pJuliet->Detach(this); +} + +/** + * Get chip type + * @return The type of the chip + */ +IExternalChip::ChipType CJuliet::Chip288::GetChipType() +{ + return IExternalChip::kYMF288; +} + +/** + * リセット + */ +void CJuliet::Chip288::Reset() +{ +} + +/** + * レジスタ書き込み + * @param[in] nAddr アドレス + * @param[in] cData データ + */ +void CJuliet::Chip288::WriteRegister(UINT nAddr, UINT8 cData) +{ + m_pJuliet->Write288(nAddr, cData); +} + +/** + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParameter パラメータ + * @return リザルト + */ +INTPTR CJuliet::Chip288::Message(UINT nMessage, INTPTR nParameter) +{ + return 0; +} diff --git a/windows/ext/romeo/juliet.h b/windows/ext/romeo/juliet.h old mode 100755 new mode 100644 index 3c0fb778..1329cf49 --- a/windows/ext/romeo/juliet.h +++ b/windows/ext/romeo/juliet.h @@ -1,89 +1,89 @@ -/** - * @file juliet.h - * @brief ROMEO アクセス クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "..\externalchip.h" -#include "misc\guard.h" -#include "misc\threadbase.h" - -/** - * @brief ROMEO アクセス クラス - */ -class CJuliet : protected CThreadBase -{ -public: - CJuliet(); - ~CJuliet(); - bool Initialize(); - void Deinitialize(); - void Reset(); - IExternalChip* GetInterface(IExternalChip::ChipType nChipType, UINT nClock); - bool IsEnabled() const; - -protected: - virtual bool Task(); - -private: - //! @brief ロード関数 - struct ProcItem - { - LPCSTR lpSymbol; //!< 関数名 - size_t nOffset; //!< オフセット - }; - - // 定義 - typedef ULONG (WINAPI * FnRead32)(ULONG ulPciAddress, ULONG ulRegAddress); //!< コンフィグレーション読み取り関数定義 - typedef VOID (WINAPI * FnOut8)(ULONG ulAddress, UCHAR ucParam); //!< outp 関数定義 - typedef VOID (WINAPI * FnOut32)(ULONG ulAddress, ULONG ulParam); //!< outpd 関数定義 - typedef UCHAR (WINAPI * FnIn8)(ULONG ulAddress); //!< inp 関数定義 - - HMODULE m_hModule; //!< モジュール - FnRead32 m_fnRead32; //!< コンフィグレーション読み取り関数 - FnOut8 m_fnOut8; //!< outp 関数 - FnOut32 m_fnOut32; //!< outpd 関数 - FnIn8 m_fnIn8; //!< inp 関数 - ULONG m_ulAddress; //!< ROMEO ベース アドレス - UCHAR m_ucIrq; //!< ROMEO IRQ - CGuard m_pciGuard; /*!< The guard of PCI */ - CGuard m_queGuard; /*!< The guard of que */ - size_t m_nQueIndex; /*!< The position in que */ - size_t m_nQueCount; /*!< The count in que */ - UINT m_que[0x400]; /*!< que */ - - ULONG SearchRomeo() const; - void Write288(UINT nAddr, UINT8 cData); - - /** - * @brief チップ クラス - */ - class Chip288 : public IExternalChip - { - public: - Chip288(CJuliet* pJuliet); - virtual ~Chip288(); - virtual ChipType GetChipType(); - virtual void Reset(); - virtual void WriteRegister(UINT nAddr, UINT8 cData); - virtual INTPTR Message(UINT nMessage, INTPTR nParameter = 0); - - private: - CJuliet* m_pJuliet; //!< 親インスタンス - }; - IExternalChip* m_pChip288; //!< YMF288 インスタンス - - void Detach(IExternalChip* pChip); - friend class Chip288; -}; - -/** - * ROMEO は有効? - * @retval true 有効 - * @retval false 無効 - */ -inline bool CJuliet::IsEnabled() const -{ - return (m_hModule != NULL); -} +/** + * @file juliet.h + * @brief ROMEO アクセス クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "..\externalchip.h" +#include "misc\guard.h" +#include "misc\threadbase.h" + +/** + * @brief ROMEO アクセス クラス + */ +class CJuliet : protected CThreadBase +{ +public: + CJuliet(); + ~CJuliet(); + bool Initialize(); + void Deinitialize(); + void Reset(); + IExternalChip* GetInterface(IExternalChip::ChipType nChipType, UINT nClock); + bool IsEnabled() const; + +protected: + virtual bool Task(); + +private: + //! @brief ロード関数 + struct ProcItem + { + LPCSTR lpSymbol; //!< 関数名 + size_t nOffset; //!< オフセット + }; + + // 定義 + typedef ULONG (WINAPI * FnRead32)(ULONG ulPciAddress, ULONG ulRegAddress); //!< コンフィグレーション読み取り関数定義 + typedef VOID (WINAPI * FnOut8)(ULONG ulAddress, UCHAR ucParam); //!< outp 関数定義 + typedef VOID (WINAPI * FnOut32)(ULONG ulAddress, ULONG ulParam); //!< outpd 関数定義 + typedef UCHAR (WINAPI * FnIn8)(ULONG ulAddress); //!< inp 関数定義 + + HMODULE m_hModule; //!< モジュール + FnRead32 m_fnRead32; //!< コンフィグレーション読み取り関数 + FnOut8 m_fnOut8; //!< outp 関数 + FnOut32 m_fnOut32; //!< outpd 関数 + FnIn8 m_fnIn8; //!< inp 関数 + ULONG m_ulAddress; //!< ROMEO ベース アドレス + UCHAR m_ucIrq; //!< ROMEO IRQ + CGuard m_pciGuard; /*!< The guard of PCI */ + CGuard m_queGuard; /*!< The guard of que */ + size_t m_nQueIndex; /*!< The position in que */ + size_t m_nQueCount; /*!< The count in que */ + UINT m_que[0x400]; /*!< que */ + + ULONG SearchRomeo() const; + void Write288(UINT nAddr, UINT8 cData); + + /** + * @brief チップ クラス + */ + class Chip288 : public IExternalChip + { + public: + Chip288(CJuliet* pJuliet); + virtual ~Chip288(); + virtual ChipType GetChipType(); + virtual void Reset(); + virtual void WriteRegister(UINT nAddr, UINT8 cData); + virtual INTPTR Message(UINT nMessage, INTPTR nParameter = 0); + + private: + CJuliet* m_pJuliet; //!< 親インスタンス + }; + IExternalChip* m_pChip288; //!< YMF288 インスタンス + + void Detach(IExternalChip* pChip); + friend class Chip288; +}; + +/** + * ROMEO は有効? + * @retval true 有効 + * @retval false 無効 + */ +inline bool CJuliet::IsEnabled() const +{ + return (m_hModule != NULL); +} diff --git a/windows/ext/romeo/romeo.h b/windows/ext/romeo/romeo.h old mode 100755 new mode 100644 index 9395cab8..6726fa72 --- a/windows/ext/romeo/romeo.h +++ b/windows/ext/romeo/romeo.h @@ -1,51 +1,51 @@ -/** - * @file romeo.h - * @brief ROMEO 用の PCI 定義です - */ - -#pragma once - -#define ROMEO_VENDORID 0x6809 /*!< ベンダー ID */ -#define ROMEO_DEVICEID 0x2151 /*!< デバイス ID */ -#define ROMEO_DEVICEID2 0x8121 /*!< for Developer version */ - -/** - * PCIDEBUG リザルト コード - */ -enum -{ - PCIERR_SUCCESS = 0x00, /*!< 成功 */ - PCIERR_INVALIDCLASS = 0x83, /*!< 不正なデバイス クラス */ - PCIERR_DEVNOTFOUND = 0x86 /*!< デバイスが見つからない */ -}; - -/** - * コンフィグレーション レジスタ - */ -enum -{ - ROMEO_DEVICE_VENDOR = 0x00, /*!< ベンダ/デバイス ID */ - ROMEO_STATUS_COMMAND = 0x04, /*!< コマンド/ステータス レジスタ */ - ROMEO_CLASS_REVISON = 0x08, /*!< リビジョン ID / クラス コード */ - ROMEO_HEADTYPE = 0x0c, /*!< キャッシュ ライン サイズ / マスタ レイテンシ タイマ / ヘッダ タイプ */ - ROMEO_BASEADDRESS0 = 0x10, /*!< ベース アドレス 0 */ - ROMEO_BASEADDRESS1 = 0x14, /*!< ベース アドレス 1 */ - ROMEO_SUB_DEVICE_VENDOR = 0x2c, /*!< サブ システム ベンダID */ - ROMEO_PCIINTERRUPT = 0x3c /*!< インタラプト ライン / インタラプト ピン / 最小グラント / 最大レイテンシ */ -}; - -/** - * アドレス - */ -enum -{ - ROMEO_YM2151ADDR = 0x0000, /*!< YM2151 アドレス */ - ROMEO_YM2151DATA = 0x0004, /*!< YM2151 データ */ - ROMEO_CMDQUEUE = 0x0018, /*!< コマンド キュー */ - ROMEO_YM2151CTRL = 0x001c, /*!< YM2151 コントロール */ - ROMEO_YMF288ADDR1 = 0x0100, /*!< YMF288 アドレス */ - ROMEO_YMF288DATA1 = 0x0104, /*!< YMF288 データ */ - ROMEO_YMF288ADDR2 = 0x0108, /*!< YMF288 拡張アドレス */ - ROMEO_YMF288DATA2 = 0x010c, /*!< YMF288 拡張データ */ - ROMEO_YMF288CTRL = 0x011c /*!< YMF288 コントロール */ -}; +/** + * @file romeo.h + * @brief ROMEO 用の PCI 定義です + */ + +#pragma once + +#define ROMEO_VENDORID 0x6809 /*!< ベンダー ID */ +#define ROMEO_DEVICEID 0x2151 /*!< デバイス ID */ +#define ROMEO_DEVICEID2 0x8121 /*!< for Developer version */ + +/** + * PCIDEBUG リザルト コード + */ +enum +{ + PCIERR_SUCCESS = 0x00, /*!< 成功 */ + PCIERR_INVALIDCLASS = 0x83, /*!< 不正なデバイス クラス */ + PCIERR_DEVNOTFOUND = 0x86 /*!< デバイスが見つからない */ +}; + +/** + * コンフィグレーション レジスタ + */ +enum +{ + ROMEO_DEVICE_VENDOR = 0x00, /*!< ベンダ/デバイス ID */ + ROMEO_STATUS_COMMAND = 0x04, /*!< コマンド/ステータス レジスタ */ + ROMEO_CLASS_REVISON = 0x08, /*!< リビジョン ID / クラス コード */ + ROMEO_HEADTYPE = 0x0c, /*!< キャッシュ ライン サイズ / マスタ レイテンシ タイマ / ヘッダ タイプ */ + ROMEO_BASEADDRESS0 = 0x10, /*!< ベース アドレス 0 */ + ROMEO_BASEADDRESS1 = 0x14, /*!< ベース アドレス 1 */ + ROMEO_SUB_DEVICE_VENDOR = 0x2c, /*!< サブ システム ベンダID */ + ROMEO_PCIINTERRUPT = 0x3c /*!< インタラプト ライン / インタラプト ピン / 最小グラント / 最大レイテンシ */ +}; + +/** + * アドレス + */ +enum +{ + ROMEO_YM2151ADDR = 0x0000, /*!< YM2151 アドレス */ + ROMEO_YM2151DATA = 0x0004, /*!< YM2151 データ */ + ROMEO_CMDQUEUE = 0x0018, /*!< コマンド キュー */ + ROMEO_YM2151CTRL = 0x001c, /*!< YM2151 コントロール */ + ROMEO_YMF288ADDR1 = 0x0100, /*!< YMF288 アドレス */ + ROMEO_YMF288DATA1 = 0x0104, /*!< YMF288 データ */ + ROMEO_YMF288ADDR2 = 0x0108, /*!< YMF288 拡張アドレス */ + ROMEO_YMF288DATA2 = 0x010c, /*!< YMF288 拡張データ */ + ROMEO_YMF288CTRL = 0x011c /*!< YMF288 コントロール */ +}; diff --git a/windows/ext/scci2/readme.txt b/windows/ext/scci2/readme.txt index 71d8f420..11306d4f 100644 --- a/windows/ext/scci2/readme.txt +++ b/windows/ext/scci2/readme.txt @@ -1,4 +1,4 @@ -SCCI2̗p@yуCZXɂ‚Ă͌TCgmFB +SCCI2の利用方法及びライセンスについては公式サイトをご確認ください。 Please refer to the official website for information on how to use SCCI2 and its licensing terms. https://www.pyonpyon.jp/~gasshi/fm/ \ No newline at end of file diff --git a/windows/ext/scci2/scci2.h b/windows/ext/scci2/scci2.h index 05151aef..5a7985a7 100644 --- a/windows/ext/scci2/scci2.h +++ b/windows/ext/scci2/scci2.h @@ -18,8 +18,8 @@ typedef struct { DWORD dClock; // Sound Chip clock DWORD dCompatibleClock[2]; // Sound Chip clock BOOL bIsUsed; // Sound Chip Used Check - DWORD dBusID; // ڑoXID - DWORD dSoundLocation; // TEhP[V + DWORD dBusID; // 接続バスID + DWORD dSoundLocation; // サウンドロケーション } SCCI2_SOUND_CHIP_INFO; class Scci2SoundInterfaceManager; @@ -109,9 +109,9 @@ class Scci2SoundInterface{ virtual BOOL __stdcall reset() = 0; // initialize sound chips virtual BOOL __stdcall init() = 0; - // TEh`bv擾 + // サウンドチップ数取得 virtual DWORD __stdcall getSoundChipCount() = 0; - // TEh`bv擾 + // サウンドチップ取得 virtual Scci2SoundChip* __stdcall getSoundChip(DWORD dNum) = 0; }; @@ -171,51 +171,51 @@ enum SC2_CHIP_TYPE { SC2_TYPE_SCC, SC2_TYPE_SCCS, SC2_TYPE_Y8950, - SC2_TYPE_YM2164, // OPP:OPMƂ̓n[hEFALFO̐䂪Ⴄ - SC2_TYPE_YM2414, // OPZ:OPMƃsRp` - SC2_TYPE_AY8930, // APSG:gPSG - SC2_TYPE_YM2149, // SSG:PSGƂDACႤ(YM3439Ƃ͓Ƃ݂ĂƎv) - SC2_TYPE_YMZ294, // SSGL:SSGƂDACႤ(YMZ284Ƃ͓Ƃ݂ĂƎv) - SC2_TYPE_SN76496, // DCSG:76489Ƃ̓mCYWFl[^̐Ⴄ - SC2_TYPE_YM2420, // OPLL2:OPLLƂFnum̐ݒ@ႤB͓B - SC2_TYPE_YMF281, // OPLLP:OPLLƂ͓ROMFႤB͓B - SC2_TYPE_YMF276, // OPN2L:OPN2/OPN2CƂDACႤ - SC2_TYPE_YM2610B, // OPNB-B:OPNBƂFMchႤB - SC2_TYPE_YMF286, // OPNB-C:OPNBƂDACႤB - SC2_TYPE_YM2602, // 315-5124: 76489/76496Ƃ̓mCYWFl[^̐ႤBPOWONɔUȂB - SC2_TYPE_UM3567, // OPLL̃Rs[iiDIP24Ȃ̂ł̂܂܃v[XłȂj - SC2_TYPE_YMF274, // OPL4:얢 - SC2_TYPE_YM3806, // OPQ:\ - SC2_TYPE_YM2163, // DSG:쒆 - SC2_TYPE_YM7129, // OPK2:쒆 - SC2_TYPE_YMZ280, // PCM8:ADPCM8ch:\ - SC2_TYPE_YMZ705, // SSGS:SSG*2set+ADPCM8ch:쒆 - SC2_TYPE_YMZ735, // FMS:FM8ch+ADPCM8ch:쒆 - SC2_TYPE_YM2423, // YM2413̉FႢ + SC2_TYPE_YM2164, // OPP:OPMとはハードウェアLFOの制御が違う + SC2_TYPE_YM2414, // OPZ:OPMとピンコンパチ + SC2_TYPE_AY8930, // APSG:拡張PSG + SC2_TYPE_YM2149, // SSG:PSGとはDACが違う(YM3439とは同一とみていいと思う) + SC2_TYPE_YMZ294, // SSGL:SSGとはDACが違う(YMZ284とは同一とみていいと思う) + SC2_TYPE_SN76496, // DCSG:76489とはノイズジェネレータの生成式が違う + SC2_TYPE_YM2420, // OPLL2:OPLLとはFnumの設定方法が違う。音は同じ。 + SC2_TYPE_YMF281, // OPLLP:OPLLとは内蔵ROM音色が違う。制御は同じ。 + SC2_TYPE_YMF276, // OPN2L:OPN2/OPN2CとはDACが違う + SC2_TYPE_YM2610B, // OPNB-B:OPNBとはFM部のch数が違う。 + SC2_TYPE_YMF286, // OPNB-C:OPNBとはDACが違う。 + SC2_TYPE_YM2602, // 315-5124: 76489/76496とはノイズジェネレータの生成式が違う。POWON時に発振しない。 + SC2_TYPE_UM3567, // OPLLのコピー品(だけどDIP24なのでそのままリプレースできない) + SC2_TYPE_YMF274, // OPL4:試作未定 + SC2_TYPE_YM3806, // OPQ:試作予定 + SC2_TYPE_YM2163, // DSG:試作中 + SC2_TYPE_YM7129, // OPK2:試作中 + SC2_TYPE_YMZ280, // PCM8:ADPCM8ch:試作予定 + SC2_TYPE_YMZ705, // SSGS:SSG*2set+ADPCM8ch:試作中 + SC2_TYPE_YMZ735, // FMS:FM8ch+ADPCM8ch:試作中 + SC2_TYPE_YM2423, // YM2413の音色違い SC2_TYPE_SPC700, // SPC700 - SC2_TYPE_NBV4, // NBV4p - SC2_TYPE_AYB02, // AYB02p - SC2_TYPE_8253, // i8253iyь݊`bvpj - SC2_TYPE_315_5124, // DCSG݊`bv + SC2_TYPE_NBV4, // NBV4用 + SC2_TYPE_AYB02, // AYB02用 + SC2_TYPE_8253, // i8253(及び互換チップ用) + SC2_TYPE_315_5124, // DCSG互換チップ SC2_TYPE_SPPCM, // SPPCM - SC2_TYPE_C140, // NAMCO C140(SPPCMfoCXj - SC2_TYPE_SEGAPCM, // SEGAPCM(SPPCMfoCXj + SC2_TYPE_C140, // NAMCO C140(SPPCMデバイス) + SC2_TYPE_SEGAPCM, // SEGAPCM(SPPCMデバイス) SC2_TYPE_SPW, // SPW SC2_TYPE_SAM2695, // SAM2695 - SC2_TYPE_MIDI, // MIDIC^[tF[X + SC2_TYPE_MIDI, // MIDIインターフェース SC2_TYPE_MSCCX_SCC, // MSCCX Level Upper SCC(SLOT0) SC2_TYPE_MSCCX_SCCP, // MSCCX Level Upper SCC(SLOT0) SC2_TYPE_MSCCX_SCC_SCC, // MSCCX Level Upper SCC(SLOT0) SCC(SLOT1) SC2_TYPE_MSCCX_SCC_SCCP, // MSCCX Level Upper SCC(SLOT0) SCCP(SLOT1) SC2_TYPE_MSCCX_SCCP_SCC, // MSCCX Level Upper SCCP(SLOT0) SCC(SLOT1) SC2_TYPE_MSCCX_SCCP_SCCP, // MSCCX Level Upper SCCP(SLOT0) SCCP(SLOT1) - SC2_TYPE_MAX, // gp”\foCXMAXl - // ȍ~́Apn[hp + SC2_TYPE_MAX, // 使用可能デバイスMAX値 + // 以降は、専用ハード用 - // n[hp - SC2_TYPE_OTHER = 1000, // ̑foCXpAAhXA0-A3œ삷 - SC2_TYPE_UNKNOWN, // JfoCX - SC2_TYPE_YMF825, // YMF825ibj + // 実験ハード用 + SC2_TYPE_OTHER = 1000, // その他デバイス用、アドレスがA0-A3で動作する + SC2_TYPE_UNKNOWN, // 開発デバイス向け + SC2_TYPE_YMF825, // YMF825(暫定) }; // Sound chip clock list @@ -256,7 +256,7 @@ enum SC2_CHIP_LOCATION { #define SC2_CLOCK_RANGE_MODE_NEAR (0x00000000) #define SC2_CLOCK_RANGE_MODE_MATCH (0x00000001) -#define SC2_WAIT_REG (0xffffffff) // EFCƃR}hMif[^͑MR}hj -#define SC2_FLUSH_REG (0xfffffffe) // ݃f[^tbV҂ -#define SC2_DIRECT_BUS (0x80000000) // AhXoX_CNg[h +#define SC2_WAIT_REG (0xffffffff) // ウェイとコマンド送信(データは送信するコマンド数) +#define SC2_FLUSH_REG (0xfffffffe) // 書き込みデータフラッシュ待ち +#define SC2_DIRECT_BUS (0x80000000) // アドレスバスダイレクトモード diff --git a/windows/ext/scci2/scci2if.cpp b/windows/ext/scci2/scci2if.cpp index df255182..6d042411 100644 --- a/windows/ext/scci2/scci2if.cpp +++ b/windows/ext/scci2/scci2if.cpp @@ -1,6 +1,6 @@ /** * @file scciif.cpp - * @brief SCCI ANZX NX̓̒`s܂ + * @brief SCCI アクセス クラスの動作の定義を行います */ #include "compiler.h" @@ -8,7 +8,7 @@ #include "scci2.h" /** - * RXgN^ + * コンストラクタ */ CScci2If::CScci2If() : m_hModule(NULL) @@ -17,7 +17,7 @@ CScci2If::CScci2If() } /** - * fXgN^ + * デストラクタ */ CScci2If::~CScci2If() { @@ -25,9 +25,9 @@ CScci2If::~CScci2If() } /** - * - * @retval true - * @retval false s + * 初期化 + * @retval true 成功 + * @retval false 失敗 */ bool CScci2If::Initialize() { @@ -44,28 +44,28 @@ bool CScci2If::Initialize() break; } - /* TEhC^[tF[X}l[W[擾p֐AhX擾 */ + /* サウンドインターフェースマネージャー取得用関数アドレス取得 */ SCCIFUNC fnGetSoundInterfaceManager = reinterpret_cast(::GetProcAddress(m_hModule, "getSoundInterfaceManager")); if (fnGetSoundInterfaceManager == NULL) { break; } - /* TEhC^[tF[X}l[W[擾 */ + /* サウンドインターフェースマネージャー取得 */ m_pManager = (*fnGetSoundInterfaceManager)(); if (m_pManager == NULL) { break; } - /* TEhC^[tF[X}l[W[CX^X */ - /* KŏɎsĂ */ + /* サウンドインターフェースマネージャーインスタンス初期化 */ + /* 必ず最初に実行してください */ if (!m_pManager->initializeInstance()) { break; } - /* Zbgs */ + /* リセットを行う */ Reset(); return true; } while (false /*CONSTCOND*/); @@ -75,17 +75,17 @@ bool CScci2If::Initialize() } /** - * + * 解放 */ void CScci2If::Deinitialize() { if (m_pManager) { - /* ꊇJꍇi`bvꊇJ̏ꍇj */ + /* 一括開放する場合(チップ一括開放の場合) */ m_pManager->releaseAllSoundChip(); - /* TEhC^[tF[X}l[W[CX^XJ */ - /* FreeLibrarysOɕKĂяoĂ */ + /* サウンドインターフェースマネージャーインスタンス開放 */ + /* FreeLibraryを行う前に必ず呼び出ししてください */ m_pManager->releaseInstance(); m_pManager = NULL; @@ -99,22 +99,22 @@ void CScci2If::Deinitialize() } /** - * Zbg + * 音源リセット */ void CScci2If::Reset() { if (m_pManager) { - /* Zbgs */ + /* リセットを行う */ m_pManager->reset(); } } /** - * C^[tFCX擾 - * @param[in] nChipType ^Cv - * @param[in] nClock NbN - * @return CX^X + * インターフェイス取得 + * @param[in] nChipType タイプ + * @param[in] nClock クロック + * @return インスタンス */ IExternalChip* CScci2If::GetInterface(IExternalChip::ChipType nChipType, UINT nClock) { @@ -173,7 +173,7 @@ IExternalChip* CScci2If::GetInterface(IExternalChip::ChipType nChipType, UINT nC Scci2SoundChip* pSoundChip = m_pManager->getSoundChip(iSoundChipType, nClock); if (pSoundChip != NULL) { - /* TEh`bv擾ł */ + /* サウンドチップ取得できた */ return new Chip(this, pSoundChip); } } while (false /*CONSTCOND*/); @@ -186,24 +186,24 @@ IExternalChip* CScci2If::GetInterface(IExternalChip::ChipType nChipType, UINT nC } /** - * - * @param[in] pChip `bv + * 解放 + * @param[in] pChip チップ */ void CScci2If::Detach(CScci2If::Chip* pChip) { - /* `bv̊Ji`bvPʂŊJ̏ꍇj */ + /* チップの開放(チップ単位で開放の場合) */ if (m_pManager) { m_pManager->releaseSoundChip(*pChip); } } -/* ---- `bv */ +/* ---- チップ */ /** - * RXgN^ - * @param[in] pScciIf eCX^X - * @param[in] pSoundChip `bv CX^X + * コンストラクタ + * @param[in] pScciIf 親インスタンス + * @param[in] pSoundChip チップ インスタンス */ CScci2If::Chip::Chip(CScci2If* pScciIf, Scci2SoundChip* pSoundChip) : m_pScciIf(pScciIf) @@ -212,7 +212,7 @@ CScci2If::Chip::Chip(CScci2If* pScciIf, Scci2SoundChip* pSoundChip) } /** - * fXgN^ + * デストラクタ */ CScci2If::Chip::~Chip() { @@ -220,7 +220,7 @@ CScci2If::Chip::~Chip() } /** - * Iy[^ + * オペレータ */ CScci2If::Chip::operator Scci2SoundChip*() { @@ -277,16 +277,16 @@ IExternalChip::ChipType CScci2If::Chip::GetChipType() } /** - * Zbg + * リセット */ void CScci2If::Chip::Reset() { } /** - * WX^ - * @param[in] nAddr AhX - * @param[in] cData f[^ + * レジスタ書き込み + * @param[in] nAddr アドレス + * @param[in] cData データ */ void CScci2If::Chip::WriteRegister(UINT nAddr, UINT8 cData) { @@ -294,10 +294,10 @@ void CScci2If::Chip::WriteRegister(UINT nAddr, UINT8 cData) } /** - * bZ[W - * @param[in] nMessage bZ[W - * @param[in] nParameter p[^ - * @return Ug + * メッセージ + * @param[in] nMessage メッセージ + * @param[in] nParameter パラメータ + * @return リザルト */ INTPTR CScci2If::Chip::Message(UINT nMessage, INTPTR nParameter) { diff --git a/windows/ext/scci2/scci2if.h b/windows/ext/scci2/scci2if.h index 32566a9e..1d2dec7b 100644 --- a/windows/ext/scci2/scci2if.h +++ b/windows/ext/scci2/scci2if.h @@ -1,6 +1,6 @@ /** * @file scciif.h - * @brief SCCI ANZX NX̐錾уC^[tFCX̒`܂ + * @brief SCCI アクセス クラスの宣言およびインターフェイスの定義をします */ #pragma once @@ -11,7 +11,7 @@ class Scci2SoundChip; class Scci2SoundInterfaceManager; /** - * @brief SCCI ANZX NX + * @brief SCCI アクセス クラス */ class CScci2If { @@ -24,11 +24,11 @@ class CScci2If IExternalChip* GetInterface(IExternalChip::ChipType nChipType, UINT nClock); private: - HMODULE m_hModule; /*!< W[ */ - Scci2SoundInterfaceManager* m_pManager; /*!< }l[W */ + HMODULE m_hModule; /*!< モジュール */ + Scci2SoundInterfaceManager* m_pManager; /*!< マネージャ */ /** - * @brief `bv NX + * @brief チップ クラス */ class Chip : public IExternalChip { @@ -42,8 +42,8 @@ class CScci2If virtual INTPTR Message(UINT nMessage, INTPTR nParameter = 0); private: - CScci2If* m_pScciIf; /*!< eCX^X */ - Scci2SoundChip* m_pSoundChip; /*!< `bv CX^X */ + CScci2If* m_pScciIf; /*!< 親インスタンス */ + Scci2SoundChip* m_pSoundChip; /*!< チップ インスタンス */ }; void Detach(Chip* pChip); diff --git a/windows/fontmng.cpp b/windows/fontmng.cpp old mode 100755 new mode 100644 index a6de7f96..56b58e81 --- a/windows/fontmng.cpp +++ b/windows/fontmng.cpp @@ -1,314 +1,314 @@ -#include -#include -#include - -typedef struct { - int fontsize; - UINT fonttype; - int fontwidth; - int fontheight; - -// あとは拡張〜 - HDC hdcimage; - HBITMAP hBitmap; - UINT8 *image; - HFONT hfont; - RECT rect; - int bmpwidth; - int bmpheight; - int bmpalign; -} _FNTMNG, *FNTMNG; - - -static const OEMCHAR deffontface[] = OEMTEXT("MS ゴシック"); -static const OEMCHAR deffontface2[] = OEMTEXT("MS Pゴシック"); -static const OEMCHAR edeffontface[] = OEMTEXT("MS Gothic"); -static const OEMCHAR edeffontface2[] = OEMTEXT("MS PGothic"); - -static const OEMCHAR *deffont[4] = { - deffontface, deffontface2, - edeffontface, edeffontface2}; - -void *fontmng_create(int size, UINT type, const OEMCHAR *fontface) { - - int i; - int fontalign; - int allocsize; - FNTMNG ret; - BITMAPINFO *bi; - HDC hdc; - int fontwidth; - int fontheight; - int weight; - int deffontnum; - DWORD pitch; - DWORD charset; - - if (size < 0) { - size *= -1; - } - if (size < 6) { - size = 6; - } - else if (size > 128) { - size = 128; - } - fontwidth = size; - fontheight = size; - if (type & FDAT_BOLD) { - fontwidth++; - } - - fontalign = sizeof(_FNTDAT) + (fontwidth * fontheight); - fontalign = (fontalign + 3) & (~3); - - allocsize = sizeof(_FNTMNG); - allocsize += fontalign; - allocsize += sizeof(BITMAPINFOHEADER) + (4 * 2); - - ret = (FNTMNG)_MALLOC(allocsize, "font mng"); - if (ret == NULL) { - return(NULL); - } - ZeroMemory(ret, allocsize); - ret->fontsize = size; - ret->fonttype = type; - ret->fontwidth = fontwidth; - ret->fontheight = fontheight; - ret->bmpwidth = fontwidth; - ret->bmpheight = fontheight; - ret->bmpalign = (((ret->bmpwidth + 31) / 8) & ~3); - - - bi = (BITMAPINFO *)(((UINT8 *)(ret + 1)) + fontalign); - bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bi->bmiHeader.biWidth = ret->bmpwidth; - bi->bmiHeader.biHeight = ret->bmpheight; - bi->bmiHeader.biPlanes = 1; - bi->bmiHeader.biBitCount = 1; - bi->bmiHeader.biCompression = BI_RGB; - bi->bmiHeader.biSizeImage = ret->bmpalign * ret->bmpheight; - bi->bmiHeader.biXPelsPerMeter = 0; - bi->bmiHeader.biYPelsPerMeter = 0; - bi->bmiHeader.biClrUsed = 2; - bi->bmiHeader.biClrImportant = 2; - for (i=0; i<2; i++) { - bi->bmiColors[i].rgbRed = (i ^ 1) - 1; - bi->bmiColors[i].rgbGreen = (i ^ 1) - 1; - bi->bmiColors[i].rgbBlue = (i ^ 1) - 1; - bi->bmiColors[i].rgbReserved = PC_RESERVED; - } - - hdc = GetDC(NULL); - ret->hBitmap = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, - (void **)&ret->image, NULL, 0); - ret->hdcimage = CreateCompatibleDC(hdc); - ReleaseDC(NULL, hdc); - ret->hBitmap = (HBITMAP)SelectObject(ret->hdcimage, ret->hBitmap); - SetDIBColorTable(ret->hdcimage, 0, 2, bi->bmiColors); - - weight = (type & FDAT_BOLD)?FW_BOLD:FW_REGULAR; - pitch = (type & FDAT_PROPORTIONAL)?VARIABLE_PITCH:FIXED_PITCH; - if (fontface == NULL) { - deffontnum = (type & FDAT_PROPORTIONAL)?1:0; - if (GetOEMCP() != 932) { // !Japanese - deffontnum += 2; - } - fontface = deffont[deffontnum]; - } - charset = (type & FDAT_SHIFTJIS)?SHIFTJIS_CHARSET:DEFAULT_CHARSET; - ret->hfont = CreateFont(size, 0, - FW_DONTCARE, FW_DONTCARE, weight, - FALSE, FALSE, FALSE, charset, - OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, - NONANTIALIASED_QUALITY, pitch, fontface); - ret->hfont = (HFONT)SelectObject(ret->hdcimage, ret->hfont); - SetTextColor(ret->hdcimage, RGB(255, 255, 255)); - SetBkColor(ret->hdcimage, RGB(0, 0, 0)); - SetRect(&ret->rect, 0, 0, ret->bmpwidth, ret->bmpheight); - return(ret); -} - -void fontmng_destroy(void *hdl) { - - FNTMNG fhdl; - - fhdl = (FNTMNG)hdl; - if (fhdl) { - DeleteObject(SelectObject(fhdl->hdcimage, fhdl->hBitmap)); - DeleteObject(SelectObject(fhdl->hdcimage, fhdl->hfont)); - DeleteDC(fhdl->hdcimage); - _MFREE(hdl); - } -} - - -// ---- - -static void getlength1(FNTMNG fhdl, FNTDAT fdat, - const wchar_t *string, int length) { - - SIZE fntsize; - - if (GetTextExtentPoint32W(fhdl->hdcimage, string, length, &fntsize)) { - fntsize.cx = min(fntsize.cx, fhdl->bmpwidth); - fdat->width = fntsize.cx; - fdat->pitch = fntsize.cx; - } - else { - fdat->width = fhdl->fontwidth; - fdat->pitch = (fhdl->fontsize + 1) >> 1; - } - fdat->height = fhdl->fontheight; -} - -static void fontmng_getchar(FNTMNG fhdl, FNTDAT fdat, const OEMCHAR *string) { - - int leng; - UINT16 c[8]; - OEMCHAR* startstr = (OEMCHAR*)string; - - FillRect(fhdl->hdcimage, &fhdl->rect, - (HBRUSH)GetStockObject(BLACK_BRUSH)); - codecnv_utf8toucs2(c, 8, string, -1); - leng = codecnv_ucs2len(c); - TextOutW(fhdl->hdcimage, 0, 0, (wchar_t*)c, leng); - getlength1(fhdl, fdat, (wchar_t*)c, leng); -} - -BRESULT fontmng_getsize(void *hdl, const OEMCHAR *string, POINT_T *pt) { - - int width; - OEMCHAR buf[4]; - _FNTDAT fdat; - int leng; - UINT16 c[8]; - - if ((hdl == NULL) || (string == NULL)) { - goto fmgs_exit; - } - - width = 0; - while(1) { - leng = milstr_charsize(string); - if (!leng) { - break; - } - CopyMemory(buf, string, leng * sizeof(OEMCHAR)); - buf[leng] = '\0'; - string += leng; - codecnv_utf8toucs2(c, 8, buf, -1); - leng = codecnv_ucs2len(c); - getlength1((FNTMNG)hdl, &fdat, (wchar_t*)c, leng); - width += fdat.pitch; - } - - if (pt) { - pt->x = width; - pt->y = ((FNTMNG)hdl)->fontsize; - } - return(SUCCESS); - -fmgs_exit: - return(FAILURE); -} - -BRESULT fontmng_getdrawsize(void *hdl, const OEMCHAR *string, POINT_T *pt) { - - OEMCHAR buf[4]; - _FNTDAT fdat; - int width; - int posx; - int leng; - UINT16 c[8]; - - if ((hdl == NULL) || (string == NULL)) { - goto fmgds_exit; - } - - width = 0; - posx = 0; - while(1) { - leng = milstr_charsize(string); - if (!leng) { - break; - } - CopyMemory(buf, string, leng * sizeof(OEMCHAR)); - buf[leng] = '\0'; - string += leng; - codecnv_utf8toucs2(c, 8, buf, -1); - getlength1((FNTMNG)hdl, &fdat, (wchar_t*)c, leng); - width = posx + max(fdat.width, fdat.pitch); - posx += fdat.pitch; - } - - if (pt) { - pt->x = width; - pt->y = ((FNTMNG)hdl)->fontsize; - } - return(SUCCESS); - -fmgds_exit: - return(FAILURE); -} - -static void fontmng_setpat(FNTMNG fhdl, FNTDAT fdat) { - - UINT remx; - UINT remy; - UINT8 *src; - UINT8 *dst; - UINT8 *s; - UINT8 bit; - UINT8 b1 = 0; // for cygwin - int align; - - align = fhdl->bmpalign; - src = fhdl->image + (fhdl->rect.bottom * align); - if (fdat->width <= 0) { - goto fmsp_end; - } - - dst = (UINT8 *)(fdat + 1); - align *= -1; - - remy = fdat->height; - do { - src += align; - s = src; - remx = fdat->width; - bit = 0; - do { - if (bit == 0) { - bit = 0x80; - b1 = *s++; - } - *dst++ = (b1 & bit)?FDAT_DEPTH:0x00; - bit >>= 1; - } while(--remx); - } while(--remy); - -fmsp_end: - return; -} - - -// ---- - -FNTDAT fontmng_get(void *hdl, const OEMCHAR *string) { - - FNTMNG fhdl; - FNTDAT fdat; - if ((hdl == NULL) || (string == NULL)) { - goto ftmggt_err; - } - fhdl = (FNTMNG)hdl; - fdat = (FNTDAT)(fhdl + 1); - fontmng_getchar(fhdl, fdat, string); - fontmng_setpat(fhdl, fdat); - return(fdat); - -ftmggt_err: - return(NULL); -} - +#include +#include +#include + +typedef struct { + int fontsize; + UINT fonttype; + int fontwidth; + int fontheight; + +// あとは拡張〜 + HDC hdcimage; + HBITMAP hBitmap; + UINT8 *image; + HFONT hfont; + RECT rect; + int bmpwidth; + int bmpheight; + int bmpalign; +} _FNTMNG, *FNTMNG; + + +static const OEMCHAR deffontface[] = OEMTEXT("MS ゴシック"); +static const OEMCHAR deffontface2[] = OEMTEXT("MS Pゴシック"); +static const OEMCHAR edeffontface[] = OEMTEXT("MS Gothic"); +static const OEMCHAR edeffontface2[] = OEMTEXT("MS PGothic"); + +static const OEMCHAR *deffont[4] = { + deffontface, deffontface2, + edeffontface, edeffontface2}; + +void *fontmng_create(int size, UINT type, const OEMCHAR *fontface) { + + int i; + int fontalign; + int allocsize; + FNTMNG ret; + BITMAPINFO *bi; + HDC hdc; + int fontwidth; + int fontheight; + int weight; + int deffontnum; + DWORD pitch; + DWORD charset; + + if (size < 0) { + size *= -1; + } + if (size < 6) { + size = 6; + } + else if (size > 128) { + size = 128; + } + fontwidth = size; + fontheight = size; + if (type & FDAT_BOLD) { + fontwidth++; + } + + fontalign = sizeof(_FNTDAT) + (fontwidth * fontheight); + fontalign = (fontalign + 3) & (~3); + + allocsize = sizeof(_FNTMNG); + allocsize += fontalign; + allocsize += sizeof(BITMAPINFOHEADER) + (4 * 2); + + ret = (FNTMNG)_MALLOC(allocsize, "font mng"); + if (ret == NULL) { + return(NULL); + } + ZeroMemory(ret, allocsize); + ret->fontsize = size; + ret->fonttype = type; + ret->fontwidth = fontwidth; + ret->fontheight = fontheight; + ret->bmpwidth = fontwidth; + ret->bmpheight = fontheight; + ret->bmpalign = (((ret->bmpwidth + 31) / 8) & ~3); + + + bi = (BITMAPINFO *)(((UINT8 *)(ret + 1)) + fontalign); + bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi->bmiHeader.biWidth = ret->bmpwidth; + bi->bmiHeader.biHeight = ret->bmpheight; + bi->bmiHeader.biPlanes = 1; + bi->bmiHeader.biBitCount = 1; + bi->bmiHeader.biCompression = BI_RGB; + bi->bmiHeader.biSizeImage = ret->bmpalign * ret->bmpheight; + bi->bmiHeader.biXPelsPerMeter = 0; + bi->bmiHeader.biYPelsPerMeter = 0; + bi->bmiHeader.biClrUsed = 2; + bi->bmiHeader.biClrImportant = 2; + for (i=0; i<2; i++) { + bi->bmiColors[i].rgbRed = (i ^ 1) - 1; + bi->bmiColors[i].rgbGreen = (i ^ 1) - 1; + bi->bmiColors[i].rgbBlue = (i ^ 1) - 1; + bi->bmiColors[i].rgbReserved = PC_RESERVED; + } + + hdc = GetDC(NULL); + ret->hBitmap = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, + (void **)&ret->image, NULL, 0); + ret->hdcimage = CreateCompatibleDC(hdc); + ReleaseDC(NULL, hdc); + ret->hBitmap = (HBITMAP)SelectObject(ret->hdcimage, ret->hBitmap); + SetDIBColorTable(ret->hdcimage, 0, 2, bi->bmiColors); + + weight = (type & FDAT_BOLD)?FW_BOLD:FW_REGULAR; + pitch = (type & FDAT_PROPORTIONAL)?VARIABLE_PITCH:FIXED_PITCH; + if (fontface == NULL) { + deffontnum = (type & FDAT_PROPORTIONAL)?1:0; + if (GetOEMCP() != 932) { // !Japanese + deffontnum += 2; + } + fontface = deffont[deffontnum]; + } + charset = (type & FDAT_SHIFTJIS)?SHIFTJIS_CHARSET:DEFAULT_CHARSET; + ret->hfont = CreateFont(size, 0, + FW_DONTCARE, FW_DONTCARE, weight, + FALSE, FALSE, FALSE, charset, + OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + NONANTIALIASED_QUALITY, pitch, fontface); + ret->hfont = (HFONT)SelectObject(ret->hdcimage, ret->hfont); + SetTextColor(ret->hdcimage, RGB(255, 255, 255)); + SetBkColor(ret->hdcimage, RGB(0, 0, 0)); + SetRect(&ret->rect, 0, 0, ret->bmpwidth, ret->bmpheight); + return(ret); +} + +void fontmng_destroy(void *hdl) { + + FNTMNG fhdl; + + fhdl = (FNTMNG)hdl; + if (fhdl) { + DeleteObject(SelectObject(fhdl->hdcimage, fhdl->hBitmap)); + DeleteObject(SelectObject(fhdl->hdcimage, fhdl->hfont)); + DeleteDC(fhdl->hdcimage); + _MFREE(hdl); + } +} + + +// ---- + +static void getlength1(FNTMNG fhdl, FNTDAT fdat, + const wchar_t *string, int length) { + + SIZE fntsize; + + if (GetTextExtentPoint32W(fhdl->hdcimage, string, length, &fntsize)) { + fntsize.cx = min(fntsize.cx, fhdl->bmpwidth); + fdat->width = fntsize.cx; + fdat->pitch = fntsize.cx; + } + else { + fdat->width = fhdl->fontwidth; + fdat->pitch = (fhdl->fontsize + 1) >> 1; + } + fdat->height = fhdl->fontheight; +} + +static void fontmng_getchar(FNTMNG fhdl, FNTDAT fdat, const OEMCHAR *string) { + + int leng; + UINT16 c[8]; + OEMCHAR* startstr = (OEMCHAR*)string; + + FillRect(fhdl->hdcimage, &fhdl->rect, + (HBRUSH)GetStockObject(BLACK_BRUSH)); + codecnv_utf8toucs2(c, 8, string, -1); + leng = codecnv_ucs2len(c); + TextOutW(fhdl->hdcimage, 0, 0, (wchar_t*)c, leng); + getlength1(fhdl, fdat, (wchar_t*)c, leng); +} + +BRESULT fontmng_getsize(void *hdl, const OEMCHAR *string, POINT_T *pt) { + + int width; + OEMCHAR buf[4]; + _FNTDAT fdat; + int leng; + UINT16 c[8]; + + if ((hdl == NULL) || (string == NULL)) { + goto fmgs_exit; + } + + width = 0; + while(1) { + leng = milstr_charsize(string); + if (!leng) { + break; + } + CopyMemory(buf, string, leng * sizeof(OEMCHAR)); + buf[leng] = '\0'; + string += leng; + codecnv_utf8toucs2(c, 8, buf, -1); + leng = codecnv_ucs2len(c); + getlength1((FNTMNG)hdl, &fdat, (wchar_t*)c, leng); + width += fdat.pitch; + } + + if (pt) { + pt->x = width; + pt->y = ((FNTMNG)hdl)->fontsize; + } + return(SUCCESS); + +fmgs_exit: + return(FAILURE); +} + +BRESULT fontmng_getdrawsize(void *hdl, const OEMCHAR *string, POINT_T *pt) { + + OEMCHAR buf[4]; + _FNTDAT fdat; + int width; + int posx; + int leng; + UINT16 c[8]; + + if ((hdl == NULL) || (string == NULL)) { + goto fmgds_exit; + } + + width = 0; + posx = 0; + while(1) { + leng = milstr_charsize(string); + if (!leng) { + break; + } + CopyMemory(buf, string, leng * sizeof(OEMCHAR)); + buf[leng] = '\0'; + string += leng; + codecnv_utf8toucs2(c, 8, buf, -1); + getlength1((FNTMNG)hdl, &fdat, (wchar_t*)c, leng); + width = posx + max(fdat.width, fdat.pitch); + posx += fdat.pitch; + } + + if (pt) { + pt->x = width; + pt->y = ((FNTMNG)hdl)->fontsize; + } + return(SUCCESS); + +fmgds_exit: + return(FAILURE); +} + +static void fontmng_setpat(FNTMNG fhdl, FNTDAT fdat) { + + UINT remx; + UINT remy; + UINT8 *src; + UINT8 *dst; + UINT8 *s; + UINT8 bit; + UINT8 b1 = 0; // for cygwin + int align; + + align = fhdl->bmpalign; + src = fhdl->image + (fhdl->rect.bottom * align); + if (fdat->width <= 0) { + goto fmsp_end; + } + + dst = (UINT8 *)(fdat + 1); + align *= -1; + + remy = fdat->height; + do { + src += align; + s = src; + remx = fdat->width; + bit = 0; + do { + if (bit == 0) { + bit = 0x80; + b1 = *s++; + } + *dst++ = (b1 & bit)?FDAT_DEPTH:0x00; + bit >>= 1; + } while(--remx); + } while(--remy); + +fmsp_end: + return; +} + + +// ---- + +FNTDAT fontmng_get(void *hdl, const OEMCHAR *string) { + + FNTMNG fhdl; + FNTDAT fdat; + if ((hdl == NULL) || (string == NULL)) { + goto ftmggt_err; + } + fhdl = (FNTMNG)hdl; + fdat = (FNTDAT)(fhdl + 1); + fontmng_getchar(fhdl, fdat, string); + fontmng_setpat(fhdl, fdat); + return(fdat); + +ftmggt_err: + return(NULL); +} + diff --git a/windows/fontmng.h b/windows/fontmng.h old mode 100755 new mode 100644 index 8ee04fcb..c6c8f7a9 --- a/windows/fontmng.h +++ b/windows/fontmng.h @@ -1,35 +1,35 @@ - -enum { - FDAT_BOLD = 0x01, - FDAT_PROPORTIONAL = 0x02, - FDAT_ALIAS = 0x04, - FDAT_ANSI = 0x08, - FDAT_SHIFTJIS = 0x10 -}; - -enum { - FDAT_DEPTH = 64, - FDAT_DEPTHBIT = 6 -}; - -typedef struct { - int width; - int height; - int pitch; -} _FNTDAT, *FNTDAT; - -#ifdef __cplusplus -extern "C" { -#endif - -void *fontmng_create(int size, UINT type, const OEMCHAR *fontface); -void fontmng_destroy(void *hdl); - -BRESULT fontmng_getsize(void *hdl, const OEMCHAR *string, POINT_T *pt); -BRESULT fontmng_getdrawsize(void *hdl, const OEMCHAR *string, POINT_T *pt); -FNTDAT fontmng_get(void *hdl, const OEMCHAR *string); - -#ifdef __cplusplus -} -#endif - + +enum { + FDAT_BOLD = 0x01, + FDAT_PROPORTIONAL = 0x02, + FDAT_ALIAS = 0x04, + FDAT_ANSI = 0x08, + FDAT_SHIFTJIS = 0x10 +}; + +enum { + FDAT_DEPTH = 64, + FDAT_DEPTHBIT = 6 +}; + +typedef struct { + int width; + int height; + int pitch; +} _FNTDAT, *FNTDAT; + +#ifdef __cplusplus +extern "C" { +#endif + +void *fontmng_create(int size, UINT type, const OEMCHAR *fontface); +void fontmng_destroy(void *hdl); + +BRESULT fontmng_getsize(void *hdl, const OEMCHAR *string, POINT_T *pt); +BRESULT fontmng_getdrawsize(void *hdl, const OEMCHAR *string, POINT_T *pt); +FNTDAT fontmng_get(void *hdl, const OEMCHAR *string); + +#ifdef __cplusplus +} +#endif + diff --git a/windows/ini.cpp b/windows/ini.cpp index a257ccfe..48b2907a 100644 --- a/windows/ini.cpp +++ b/windows/ini.cpp @@ -1,888 +1,888 @@ -/** - * @file ini.cpp - * @brief 設定ファイル アクセスの動作の定義を行います - */ - -#include "compiler.h" -#include "strres.h" -#include "profile.h" -#include "np2.h" -#include "np2arg.h" -#include "dosio.h" -#include "ini.h" -#include "winkbd.h" -#include "pccore.h" - -// ---- user type - -/** - * 16ビット配列を読み込む - * @param[in] lpString 文字列 - * @param[out] ini 設定テーブル - */ -static void inirdargs16(LPCTSTR lpString, const PFTBL* ini) -{ - SINT16* lpDst = static_cast(ini->value); - const int nCount = ini->arg; - - for (int i = 0; i < nCount; i++) - { - while (*lpString == ' ') - { - lpString++; - } - - if (*lpString == '\0') - { - break; - } - - lpDst[i] = static_cast(milstr_solveINT(lpString)); - while (*lpString != '\0') - { - const TCHAR c = *lpString++; - if (c == ',') - { - break; - } - } - } -} - -/** - * 3バイトを読み込む - * @param[in] lpString 文字列 - * @param[out] ini 設定テーブル - */ -static void inirdbyte3(LPCTSTR lpString, const PFTBL* ini) -{ - for (int i = 0; i < 3; i++) - { - const TCHAR c = lpString[i]; - if (c == '\0') - { - break; - } - if ((((c - '0') & 0xff) < 9) || (((c - 'A') & 0xdf) < 26)) - { - (static_cast(ini->value))[i] = static_cast(c); - } - } -} - -/** - * キーボード設定を読み込む - * @param[in] lpString 文字列 - * @param[out] ini 設定テーブル - */ -static void inirdkb(LPCTSTR lpString, const PFTBL* ini) -{ - if ((!milstr_extendcmp(lpString, TEXT("PC98"))) || (!milstr_cmp(lpString, TEXT("98")))) - { - *(static_cast(ini->value)) = KEY_PC98; - } - else if ((!milstr_extendcmp(lpString, TEXT("DOS"))) || (!milstr_cmp(lpString, TEXT("PCAT"))) || (!milstr_cmp(lpString, TEXT("AT")))) - { - *(static_cast(ini->value)) = KEY_KEY106; - } - else if ((!milstr_extendcmp(lpString, TEXT("KEY101"))) || (!milstr_cmp(lpString, TEXT("101")))) - { - *(static_cast(ini->value)) = KEY_KEY101; - } -} - - -// ---- Use WinAPI - -#if !defined(_UNICODE) -/** - * ビットを設定 - * @param[in,out] lpBuffer バッファ - * @param[in] nPos 位置 - * @param[in] set セット or クリア - */ -static void bitmapset(void* lpBuffer, UINT nPos, BOOL set) -{ - const int nIndex = (nPos >> 3); - const UINT8 cBit = 1 << (nPos & 7); - if (set) - { - (static_cast(lpBuffer))[nIndex] |= cBit; - } - else - { - (static_cast(lpBuffer))[nIndex] &= ~cBit; - } -} - -/** - * ビットを得る - * @param[in] lpBuffer バッファ - * @param[in] nPos 位置 - * @return ビット - */ -static BOOL bitmapget(const void* lpBuffer, UINT nPos) -{ - const int nIndex = (nPos >> 3); - const UINT8 cBit = 1 << (nPos & 7); - return (((static_cast(lpBuffer))[nIndex]) & cBit) ? TRUE : FALSE; -} - -/** - * バイナリをアンシリアライズ - * @param[out] lpBin バイナリ - * @param[in] cbBin バイナリのサイズ - * @param[in] lpString 文字列バッファ - */ -static void binset(void* lpBin, UINT cbBin, LPCTSTR lpString) -{ - for (UINT i = 0; i < cbBin; i++) - { - while (*lpString == ' ') - { - lpString++; - } - - LPTSTR lpStringEnd; - const long lVal = _tcstol(lpString, &lpStringEnd, 16); - if (lpString == lpStringEnd) - { - break; - } - - (static_cast(lpBin))[i] = static_cast(lVal); - lpString = lpStringEnd; - } -} - -/** - * バイナリをシリアライズ - * @param[out] lpString 文字列バッファ - * @param[in] cchString 文字列バッファ長 - * @param[in] lpBin バイナリ - * @param[in] cbBin バイナリのサイズ - */ -static void binget(LPTSTR lpString, int cchString, const void* lpBin, UINT cbBin) -{ - - if (cbBin) - { - TCHAR tmp[8]; - wsprintf(tmp, TEXT("%.2x"), (static_cast(lpBin))[0]); - milstr_ncpy(lpString, tmp, cchString); - } - for (UINT i = 1; i < cbBin; i++) - { - TCHAR tmp[8]; - wsprintf(tmp, TEXT(" %.2x"), (static_cast(lpBin))[i]); - milstr_ncat(lpString, tmp, cchString); - } -} - -/** - * 設定読み出し - * @param[in] lpPath パス - * @param[in] lpTitle タイトル - * @param[in] lpTable 設定テーブル - * @param[in] nCount 設定テーブル アイテム数 - */ -void ini_read(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount) -{ - const PFTBL* p = lpTable; - const PFTBL* pTerminate = p + nCount; - while (p < pTerminate) - { - TCHAR szWork[512]; - UINT32 val; - switch (p->itemtype & PFTYPE_MASK) - { - case PFTYPE_STR: - GetPrivateProfileString(lpTitle, p->item, static_cast(p->value), static_cast(p->value), p->arg, lpPath); - break; - - case PFTYPE_BOOL: - GetPrivateProfileString(lpTitle, p->item, - (*(static_cast(p->value))) ? str_true : str_false, - szWork, NELEMENTS(szWork), lpPath); - *(static_cast(p->value)) = (!milstr_cmp(szWork, str_true)) ? 1 : 0; - break; - - case PFTYPE_BITMAP: - GetPrivateProfileString(lpTitle, p->item, - (bitmapget(p->value, p->arg)) ? str_true : str_false, - szWork, _countof(szWork), lpPath); - bitmapset(p->value, p->arg, (milstr_cmp(szWork, str_true) == 0)); - break; - - case PFTYPE_BIN: - GetPrivateProfileString(lpTitle, p->item, str_null, szWork, _countof(szWork), lpPath); - binset(p->value, p->arg, szWork); - break; - - case PFTYPE_SINT8: - case PFTYPE_UINT8: - val = GetPrivateProfileInt(lpTitle, p->item, *(static_cast(p->value)), lpPath); - *(static_cast(p->value)) = static_cast(val); - break; - - case PFTYPE_SINT16: - case PFTYPE_UINT16: - val = GetPrivateProfileInt(lpTitle, p->item, *(static_cast(p->value)), lpPath); - *(static_cast(p->value)) = static_cast(val); - break; - - case PFTYPE_SINT32: - case PFTYPE_UINT32: - val = GetPrivateProfileInt(lpTitle, p->item, *(static_cast(p->value)), lpPath); - *(static_cast(p->value)) = static_cast(val); - break; - - case PFTYPE_HEX8: - wsprintf(szWork, str_x, *(static_cast(p->value))); - GetPrivateProfileString(lpTitle, p->item, szWork, szWork, _countof(szWork), lpPath); - *(static_cast(p->value)) = static_cast(milstr_solveHEX(szWork)); - break; - - case PFTYPE_HEX16: - wsprintf(szWork, str_x, *(static_cast(p->value))); - GetPrivateProfileString(lpTitle, p->item, szWork, szWork, _countof(szWork), lpPath); - *(static_cast(p->value)) = static_cast(milstr_solveHEX(szWork)); - break; - - case PFTYPE_HEX32: - wsprintf(szWork, str_x, *(static_cast(p->value))); - GetPrivateProfileString(lpTitle, p->item, szWork, szWork, _countof(szWork), lpPath); - *(static_cast(p->value)) = static_cast(milstr_solveHEX(szWork)); - break; - - case PFTYPE_ARGS16: - GetPrivateProfileString(lpTitle, p->item, str_null, szWork, _countof(szWork), lpPath); - inirdargs16(szWork, p); - break; - - case PFTYPE_BYTE3: - GetPrivateProfileString(lpTitle, p->item, str_null, szWork, _countof(szWork), lpPath); - inirdbyte3(szWork, p); - break; - - case PFTYPE_KB: - GetPrivateProfileString(lpTitle, p->item, str_null, szWork, _countof(szWork), lpPath); - inirdkb(szWork, p); - break; - } - p++; - } -} - -/** - * 設定書き込み - * @param[in] lpPath パス - * @param[in] lpTitle タイトル - * @param[in] lpTable 設定テーブル - * @param[in] nCount 設定テーブル アイテム数 - */ -void ini_write(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount) -{ - const PFTBL* p = lpTable; - const PFTBL* pTerminate = p + nCount; - while (p < pTerminate) - { - if (!(p->itemtype & PFFLAG_RO)) - { - TCHAR szWork[512]; - szWork[0] = '\0'; - - LPCTSTR lpSet = szWork; - switch(p->itemtype & PFTYPE_MASK) { - case PFTYPE_STR: - lpSet = static_cast(p->value); - break; - - case PFTYPE_BOOL: - lpSet = (*(static_cast(p->value))) ? str_true : str_false; - break; - - case PFTYPE_BITMAP: - lpSet = (bitmapget(p->value, p->arg)) ? str_true : str_false; - break; - - case PFTYPE_BIN: - binget(szWork, _countof(szWork), p->value, p->arg); - break; - - case PFTYPE_SINT8: - wsprintf(szWork, str_d, *(static_cast(p->value))); - break; - - case PFTYPE_SINT16: - wsprintf(szWork, str_d, *(static_cast(p->value))); - break; - - case PFTYPE_SINT32: - wsprintf(szWork, str_d, *(static_cast(p->value))); - break; - - case PFTYPE_UINT8: - wsprintf(szWork, str_u, *(static_cast(p->value))); - break; - - case PFTYPE_UINT16: - wsprintf(szWork, str_u, *(static_cast(p->value))); - break; - - case PFTYPE_UINT32: - wsprintf(szWork, str_u, *(static_cast(p->value))); - break; - - case PFTYPE_HEX8: - wsprintf(szWork, str_x, *(static_cast(p->value))); - break; - - case PFTYPE_HEX16: - wsprintf(szWork, str_x, *(static_cast(p->value))); - break; - - case PFTYPE_HEX32: - wsprintf(szWork, str_x, *(static_cast(p->value))); - break; - - default: - lpSet = NULL; - break; - } - if (lpSet) - { - ::WritePrivateProfileString(lpTitle, p->item, lpSet, lpPath); - } - } - p++; - } -} - -#else // !defined(_UNICODE) - -// ---- Use profile.c - -/** - * コールバック - * @param[in] item アイテム - * @param[in] lpString 文字列 - */ -static void UserReadItem(const PFTBL* item, LPCTSTR lpString) -{ - switch (item->itemtype & PFTYPE_MASK) - { - case PFTYPE_ARGS16: - inirdargs16(lpString, item); - break; - - case PFTYPE_BYTE3: - inirdbyte3(lpString, item); - break; - - case PFTYPE_KB: - inirdkb(lpString, item); - break; - } -} - -/** - * 設定読み取り - * @param[in] lpPath パス - * @param[in] lpTitle タイトル - * @param[in] lpTable 設定テーブル - * @param[in] nCount 設定テーブル アイテム数 - */ -void ini_read(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount) -{ - profile_iniread(lpPath, lpTitle, lpTable, nCount, UserReadItem); -} - -/** - * 設定書き込み - * @param[in] lpPath パス - * @param[in] lpTitle タイトル - * @param[in] lpTable 設定テーブル - * @param[in] nCount 設定テーブル アイテム数 - */ -void ini_write(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount) -{ - profile_iniwrite(lpPath, lpTitle, lpTable, nCount, NULL); -} - -#endif // !defined(_UNICODE) - - -// ---- - -#if !defined(SUPPORT_PC9821) -static const TCHAR s_szIniTitle[] = TEXT("NekoProjectII"); //!< アプリ名 -#else -static const TCHAR s_szIniTitle[] = TEXT("NekoProject21"); //!< アプリ名 -#endif - -/** - * 追加設定 - */ -enum -{ - PFRO_STR = PFFLAG_RO + PFTYPE_STR, - PFRO_BOOL = PFFLAG_RO + PFTYPE_BOOL, - PFRO_BITMAP = PFFLAG_RO + PFTYPE_BITMAP, - PFRO_UINT8 = PFFLAG_RO + PFTYPE_UINT8, - PFRO_SINT32 = PFFLAG_RO + PFTYPE_SINT32, - PFRO_HEX8 = PFFLAG_RO + PFTYPE_HEX8, - PFRO_HEX32 = PFFLAG_RO + PFTYPE_HEX32, - PFRO_BYTE3 = PFFLAG_RO + PFTYPE_BYTE3, - PFRO_KB = PFFLAG_RO + PFTYPE_KB, -}; - -/** - * OS 設定 テーブル - */ -static const PFTBL s_IniItems[] = -{ - PFSTR("np2title", PFRO_STR, np2oscfg.titles), - PFVAL("np2winid", PFRO_BYTE3, np2oscfg.winid), - PFVAL("WindposX", PFTYPE_SINT32, &np2oscfg.winx), - PFVAL("WindposY", PFTYPE_SINT32, &np2oscfg.winy), - PFMAX("paddingx", PFRO_SINT32, &np2oscfg.paddingx, 32), - PFMAX("paddingy", PFRO_SINT32, &np2oscfg.paddingy, 32), - PFVAL("Win_Snap", PFTYPE_BOOL, &np2oscfg.WINSNAP), - - PFSTR("FDfolder", PFTYPE_STR, fddfolder), - PFSTR("HDfolder", PFTYPE_STR, hddfolder), - PFSTR("CDfolder", PFTYPE_STR, cdfolder), - PFSTR("bmap_Dir", PFTYPE_STR, bmpfilefolder), - PFSTR("npcfgDir", PFTYPE_STR, npcfgfilefolder), - PFSTR("fontfile", PFTYPE_STR, np2cfg.fontfile), - PFSTR("biospath", PFRO_STR, np2cfg.biospath), - -#if defined(SUPPORT_HOSTDRV) - PFVAL("use_hdrv", PFTYPE_BOOL, &np2cfg.hdrvenable), - PFSTR("hdrvroot", PFTYPE_STR, np2cfg.hdrvroot), - PFVAL("hdrv_acc", PFTYPE_UINT8, &np2cfg.hdrvacc), -#endif - - PFSTR("pc_model", PFTYPE_STR, np2cfg.model), - PFVAL("clk_base", PFTYPE_UINT32, &np2cfg.baseclock), - PFVAL("clk_mult", PFTYPE_UINT32, &np2cfg.multiple), - - PFEXT("DIPswtch", PFTYPE_BIN, np2cfg.dipsw, 3), - PFEXT("MEMswtch", PFTYPE_BIN, np2cfg.memsw, 8), -#if defined(SUPPORT_LARGE_MEMORY) - PFMAX("ExMemory", PFTYPE_UINT16, &np2cfg.EXTMEM, MEMORY_MAXSIZE), -#else - PFMAX("ExMemory", PFTYPE_UINT8, &np2cfg.EXTMEM, MEMORY_MAXSIZE), -#endif - PFVAL("ITF_WORK", PFTYPE_BOOL, &np2cfg.ITF_WORK), - - PFVAL("USE_BIOS", PFTYPE_BOOL, &np2cfg.usebios), // 実機BIOS使用 - - PFVAL("SVFDFILE", PFTYPE_BOOL, &np2cfg.savefddfile), - PFSTR("FDD1FILE", PFTYPE_STR, np2cfg.fddfile[0]), - PFSTR("FDD2FILE", PFTYPE_STR, np2cfg.fddfile[1]), - PFSTR("FDD3FILE", PFTYPE_STR, np2cfg.fddfile[2]), - PFSTR("FDD4FILE", PFTYPE_STR, np2cfg.fddfile[3]), - - PFSTR("HDD1FILE", PFTYPE_STR, np2cfg.sasihdd[0]), - PFSTR("HDD2FILE", PFTYPE_STR, np2cfg.sasihdd[1]), -#if defined(SUPPORT_SCSI) - PFSTR("SCSIHDD0", PFTYPE_STR, np2cfg.scsihdd[0]), - PFSTR("SCSIHDD1", PFTYPE_STR, np2cfg.scsihdd[1]), - PFSTR("SCSIHDD2", PFTYPE_STR, np2cfg.scsihdd[2]), - PFSTR("SCSIHDD3", PFTYPE_STR, np2cfg.scsihdd[3]), -#endif -#if defined(SUPPORT_IDEIO) - PFSTR("HDD3FILE", PFTYPE_STR, np2cfg.sasihdd[2]), - PFSTR("HDD4FILE", PFTYPE_STR, np2cfg.sasihdd[3]), - PFVAL("IDE1TYPE", PFTYPE_UINT8, &np2cfg.idetype[0]), - PFVAL("IDE2TYPE", PFTYPE_UINT8, &np2cfg.idetype[1]), - PFVAL("IDE3TYPE", PFTYPE_UINT8, &np2cfg.idetype[2]), - PFVAL("IDE4TYPE", PFTYPE_UINT8, &np2cfg.idetype[3]), - PFVAL("IDE_BIOS", PFTYPE_BOOL, &np2cfg.idebios), // 実機IDE BIOS使用 - PFVAL("AIDEBIOS", PFTYPE_BOOL, &np2cfg.autoidebios), // 実機IDE BIOS使用を自動設定する - PFVAL("IDERWAIT", PFTYPE_UINT32, &np2cfg.iderwait), - PFVAL("IDEWWAIT", PFTYPE_UINT32, &np2cfg.idewwait), - PFVAL("IDEMWAIT", PFTYPE_UINT32, &np2cfg.idemwait), - PFVAL("CD_ASYNC", PFTYPE_BOOL, &np2cfg.useasynccd), - PFVAL("CDTRAYOP", PFTYPE_BOOL, &np2cfg.allowcdtraycmd), - PFVAL("SVCDFILE", PFTYPE_BOOL, &np2cfg.savecdfile), - PFVAL("HD_ASYNC", PFRO_BOOL, &np2cfg.useasynchd), - PFSTR("CD1_FILE", PFTYPE_STR, np2cfg.idecd[0]), - PFSTR("CD2_FILE", PFTYPE_STR, np2cfg.idecd[1]), - PFSTR("CD3_FILE", PFTYPE_STR, np2cfg.idecd[2]), - PFSTR("CD4_FILE", PFTYPE_STR, np2cfg.idecd[3]), -#endif - - PFVAL("SampleHz", PFTYPE_UINT32, &np2cfg.samplingrate), - PFVAL("Latencys", PFTYPE_UINT16, &np2cfg.delayms), - PFVAL("SNDboard", PFTYPE_HEX8, &np2cfg.SOUND_SW), - PFAND("BEEP_vol", PFTYPE_UINT8, &np2cfg.BEEP_VOL, 3), - PFVAL("xspeaker", PFRO_BOOL, &np2cfg.snd_x), - - PFEXT("SND14vol", PFTYPE_BIN, np2cfg.vol14, 6), -// PFEXT("opt14BRD", PFTYPE_BIN, np2cfg.snd14opt, 3), - PFVAL("opt26BRD", PFTYPE_HEX8, &np2cfg.snd26opt), - PFVAL("opt86BRD", PFTYPE_HEX8, &np2cfg.snd86opt), - PFVAL("optSPBRD", PFTYPE_HEX8, &np2cfg.spbopt), - PFVAL("optSPBVR", PFTYPE_HEX8, &np2cfg.spb_vrc), - PFMAX("optSPBVL", PFTYPE_UINT8, &np2cfg.spb_vrl, 24), - PFVAL("optSPB_X", PFTYPE_BOOL, &np2cfg.spb_x), - PFVAL("USEMPU98", PFTYPE_BOOL, &np2cfg.mpuenable), - PFVAL("optMPU98", PFTYPE_HEX8, &np2cfg.mpuopt), - PFVAL("optMPUAT", PFTYPE_BOOL, &np2cfg.mpu_at), -#if defined(SUPPORT_SMPU98) - PFVAL("USE_SMPU", PFTYPE_BOOL, &np2cfg.smpuenable), - PFVAL("opt_SMPU", PFTYPE_HEX8, &np2cfg.smpuopt), - PFVAL("SMPUMUTB", PFTYPE_BOOL, &np2cfg.smpumuteB), -#endif - - PFVAL("opt118io", PFTYPE_HEX16, &np2cfg.snd118io), - PFVAL("opt118id", PFTYPE_HEX8, &np2cfg.snd118id), - PFVAL("opt118dm", PFTYPE_UINT8, &np2cfg.snd118dma), - PFVAL("opt118if", PFTYPE_UINT8, &np2cfg.snd118irqf), - PFVAL("opt118ip", PFTYPE_UINT8, &np2cfg.snd118irqp), - PFVAL("opt118im", PFTYPE_UINT8, &np2cfg.snd118irqm), - PFVAL("opt118ro", PFTYPE_UINT8, &np2cfg.snd118rom), - - PFVAL("optwssid", PFTYPE_HEX8, &np2cfg.sndwssid), - PFVAL("optwssdm", PFTYPE_UINT8, &np2cfg.sndwssdma), - PFVAL("optwssip", PFTYPE_UINT8, &np2cfg.sndwssirq), - -#if defined(SUPPORT_SOUND_SB16) - PFVAL("optsb16p", PFTYPE_HEX8, &np2cfg.sndsb16io), - PFVAL("optsb16d", PFTYPE_UINT8, &np2cfg.sndsb16dma), - PFVAL("optsb16i", PFTYPE_UINT8, &np2cfg.sndsb16irq), - PFVAL("optsb16A", PFTYPE_BOOL, &np2cfg.sndsb16at), -#endif /* SUPPORT_SOUND_SB16 */ - - PFMAX("volume_M", PFTYPE_UINT8, &np2cfg.vol_master, 100), - PFMAX("volume_F", PFTYPE_UINT8, &np2cfg.vol_fm, 128), - PFMAX("volume_S", PFTYPE_UINT8, &np2cfg.vol_ssg, 128), - PFMAX("volume_A", PFTYPE_UINT8, &np2cfg.vol_adpcm, 128), - PFMAX("volume_P", PFTYPE_UINT8, &np2cfg.vol_pcm, 128), - PFMAX("volume_R", PFTYPE_UINT8, &np2cfg.vol_rhythm, 128), - PFMAX("volume_V", PFTYPE_UINT8, &np2cfg.vol_midi, 128), - - PFVAL("Seek_Snd", PFTYPE_BOOL, &np2cfg.MOTOR), - PFMAX("Seek_Vol", PFTYPE_UINT8, &np2cfg.MOTORVOL, 100), - - PFVAL("btnRAPID", PFTYPE_BOOL, &np2cfg.BTN_RAPID), - PFVAL("btn_MODE", PFTYPE_BOOL, &np2cfg.BTN_MODE), - PFVAL("Mouse_sw", PFTYPE_BOOL, &np2oscfg.MOUSE_SW), - PFVAL("MS_RAPID", PFTYPE_BOOL, &np2cfg.MOUSERAPID), - - PFAND("backgrnd", PFTYPE_UINT8, &np2oscfg.background, 3), - PFEXT("VRAMwait", PFTYPE_BIN, np2cfg.wait, 6), - PFAND("DspClock", PFTYPE_UINT8, &np2oscfg.DISPCLK, 3), - PFVAL("DispSync", PFTYPE_BOOL, &np2cfg.DISPSYNC), - PFVAL("Real_Pal", PFTYPE_BOOL, &np2cfg.RASTER), - PFMAX("RPal_tim", PFTYPE_UINT8, &np2cfg.realpal, 64), - PFVAL("s_NOWAIT", PFTYPE_BOOL, &np2oscfg.NOWAIT), - PFVAL("SkpFrame", PFTYPE_UINT8, &np2oscfg.DRAW_SKIP), - PFVAL("uPD72020", PFTYPE_BOOL, &np2cfg.uPD72020), - PFAND("GRCG_EGC", PFTYPE_UINT8, &np2cfg.grcg, 3), - PFVAL("color16b", PFTYPE_BOOL, &np2cfg.color16), - PFVAL("skipline", PFTYPE_BOOL, &np2cfg.skipline), - PFVAL("skplight", PFTYPE_UINT16, &np2cfg.skiplight), - PFAND("LCD_MODE", PFTYPE_UINT8, &np2cfg.LCD_MODE, 0x03), - PFAND("BG_COLOR", PFRO_HEX32, &np2cfg.BG_COLOR, 0xffffff), - PFAND("FG_COLOR", PFRO_HEX32, &np2cfg.FG_COLOR, 0xffffff), - - PFVAL("pc9861_e", PFTYPE_BOOL, &np2cfg.pc9861enable), - PFEXT("pc9861_s", PFTYPE_BIN, np2cfg.pc9861sw, 3), - PFEXT("pc9861_j", PFTYPE_BIN, np2cfg.pc9861jmp, 6), - -#if defined(SUPPORT_FMGEN) - PFVAL("USEFMGEN", PFTYPE_BOOL, &np2cfg.usefmgen), -#endif /* SUPPORT_FMGEN */ - - PFVAL("calendar", PFTYPE_BOOL, &np2cfg.calendar), - PFVAL("USE144FD", PFTYPE_BOOL, &np2cfg.usefd144), - PFEXT("FDDRIVE1", PFRO_BITMAP, &np2cfg.fddequip, 0), - PFEXT("FDDRIVE2", PFRO_BITMAP, &np2cfg.fddequip, 1), - PFEXT("FDDRIVE3", PFRO_BITMAP, &np2cfg.fddequip, 2), - PFEXT("FDDRIVE4", PFRO_BITMAP, &np2cfg.fddequip, 3), - -#if defined(SUPPORT_NET) - PFSTR("NP2NETTAP", PFTYPE_STR, np2cfg.np2nettap), - PFVAL("NP2NETPMM", PFTYPE_BOOL, &np2cfg.np2netpmm), -#endif -#if defined(SUPPORT_LGY98) - PFVAL("USELGY98", PFTYPE_BOOL, &np2cfg.uselgy98), - PFVAL("LGY98_IO", PFTYPE_UINT16, &np2cfg.lgy98io), - PFVAL("LGY98IRQ", PFTYPE_UINT8, &np2cfg.lgy98irq), - PFEXT("LGY98MAC", PFTYPE_BIN, np2cfg.lgy98mac, 6), -#endif -#if defined(SUPPORT_WAB) - PFVAL("WAB_ANSW", PFTYPE_UINT8, &np2cfg.wabasw), -#endif -#if defined(SUPPORT_CL_GD5430) - PFVAL("USEGD5430", PFTYPE_BOOL, &np2cfg.usegd5430), - PFVAL("GD5430TYPE",PFTYPE_UINT16, &np2cfg.gd5430type), - PFVAL("GD5430FCUR",PFTYPE_BOOL, &np2cfg.gd5430fakecur), - PFVAL("GDMELOFS", PFTYPE_UINT8, &np2cfg.gd5430melofs), - PFVAL("GANBBSEX", PFTYPE_BOOL, &np2cfg.ga98nb_bigscrn_ex), -#endif -#if defined(SUPPORT_VGA_MODEX) - PFVAL("USEMODEX", PFTYPE_BOOL, &np2cfg.usemodex), -#endif -#if defined(SUPPORT_GPIB) - PFVAL("USE_GPIB", PFTYPE_BOOL, &np2cfg.usegpib), - PFVAL("GPIB_IRQ", PFTYPE_UINT8, &np2cfg.gpibirq), - PFVAL("GPIBMODE", PFTYPE_UINT8, &np2cfg.gpibmode), - PFVAL("GPIBADDR", PFTYPE_UINT8, &np2cfg.gpibaddr), - PFVAL("GPIBEXIO", PFTYPE_UINT8, &np2cfg.gpibexio), -#endif -#if defined(SUPPORT_PCI) - PFVAL("USE98PCI", PFTYPE_BOOL, &np2cfg.usepci), - PFVAL("P_BIOS32", PFTYPE_BOOL, &np2cfg.pci_bios32), - PFVAL("PCI_PCMC", PFTYPE_UINT8, &np2cfg.pci_pcmc), -#endif - - PFMAX("DAVOLUME", PFTYPE_UINT8, &np2cfg.davolume, 255), - PFMAX("MODELNUM", PFTYPE_HEX8, &np2cfg.modelnum, 255), - - PFVAL("TIMERFIX", PFTYPE_BOOL, &np2cfg.timerfix), - - PFVAL("WINNTFIX", PFTYPE_BOOL, &np2cfg.winntfix), - - PFVAL("SYSIOMSK", PFTYPE_HEX16, &np2cfg.sysiomsk), // システムIOマスク - - PFMAX("MEMCHKMX", PFTYPE_UINT8, &np2cfg.memchkmx, 0), // メモリチェックする最大サイズ(最小は15MB・0は制限無し・メモリチェックが長いのが嫌だけど見かけ上カウントだけはしておきたい人向け) - PFMAX("SBEEPLEN", PFTYPE_UINT8, &np2cfg.sbeeplen, 0), // ピポ音の長さ(0でデフォルト・4がNP2標準) - PFVAL("SBEEPADJ", PFTYPE_BOOL, &np2cfg.sbeepadj), // ピポ音の長さ自動調整 - - PFVAL("BIOSIOEM", PFTYPE_BOOL, &np2cfg.biosioemu), // np21w ver0.86 rev46 BIOS I/O emulation - - PFSTR("cpu_vend", PFRO_STR, np2cfg.cpu_vendor_o), - PFVAL("cpu_fami", PFTYPE_UINT32, &np2cfg.cpu_family), - PFVAL("cpu_mode", PFTYPE_UINT32, &np2cfg.cpu_model), - PFVAL("cpu_step", PFTYPE_UINT32, &np2cfg.cpu_stepping), - PFVAL("cpu_feat", PFTYPE_HEX32, &np2cfg.cpu_feature), - PFVAL("cpu_f_ex", PFTYPE_HEX32, &np2cfg.cpu_feature_ex), - PFSTR("cpu_bran", PFRO_STR, np2cfg.cpu_brandstring_o), - PFVAL("cpu_brid", PFTYPE_HEX32, &np2cfg.cpu_brandid), - PFVAL("cpu_fecx", PFTYPE_HEX32, &np2cfg.cpu_feature_ecx), - PFVAL("cpu_fxcx", PFTYPE_HEX32, &np2cfg.cpu_feature_ex_ecx), - PFVAL("cpu_eflg", PFTYPE_HEX32, &np2cfg.cpu_eflags_mask), - - PFVAL("FPU_TYPE", PFTYPE_UINT8, &np2cfg.fpu_type), // FPU種類 - -#if defined(SUPPORT_FAST_MEMORYCHECK) - PFVAL("memckspd", PFTYPE_UINT8, &np2cfg.memcheckspeed), -#endif - - PFVAL("USERAM_D", PFTYPE_BOOL, &np2cfg.useram_d), // EPSONでなくてもD0000h-DFFFFhをRAMに(ただしIDE BIOS D8000h-DBFFFhは駄目) - PFVAL("USEPEGCP", PFTYPE_BOOL, &np2cfg.usepegcplane), // PEGC プレーンモードサポート - - PFVAL("USECDECC", PFTYPE_BOOL, &np2cfg.usecdecc), // CD-ROM EDC/ECC エミュレーションサポート - PFVAL("CDDTSKIP", PFTYPE_BOOL, &np2cfg.cddtskip), // CD-ROM オーディオ再生時にデータトラックをスキップ - -#if defined(SUPPORT_ASYNC_CPU) - PFVAL("ASYNCCPU", PFTYPE_BOOL, &np2cfg.asynccpu), // 非同期CPUモード有効 -#endif - PFVAL("CONSTTSC", PFTYPE_BOOL, &np2cfg.consttsc), // RDTSCをクロック変更によらず一定間隔にする -#if defined(SUPPORT_IDEIO) - PFVAL("IDEBADDR", PFRO_HEX8, &np2cfg.idebaddr), // IDE BIOS アドレス(デフォルト:D8h(D8000h)) -#endif -#if defined(SUPPORT_GAMEPORT) - PFVAL("GAMEPORT", PFTYPE_BOOL, &np2cfg.gameport), -#endif - PFVAL("USEMOVCS", PFRO_BOOL, &np2cfg.allowMOVCS), - PFVAL("USETHOOK", PFRO_BOOL, &np2cfg.usetexthook), - PFVAL("RASCSI92", PFRO_BOOL, &np2cfg.rascsi92), - - - - // OS依存? - PFVAL("keyboard", PFRO_KB, &np2oscfg.KEYBOARD), - PFVAL("usenlock", PFTYPE_BOOL, &np2oscfg.USENUMLOCK), - PFVAL("F12_COPY", PFTYPE_UINT8, &np2oscfg.F12COPY), - PFVAL("Joystick", PFTYPE_BOOL, &np2oscfg.JOYPAD1), - PFEXT("Joy1_btn", PFTYPE_BIN, np2oscfg.JOY1BTN, 4), - PFMAX("Joy1_PID", PFTYPE_UINT8, &np2oscfg.JOYPAD1ID, 15), - - PFVAL("clocknow", PFTYPE_UINT8, &np2oscfg.clk_x), - PFVAL("clockfnt", PFTYPE_UINT8, &np2oscfg.clk_fnt), - PFAND("clock_up", PFRO_HEX32, &np2oscfg.clk_color1, 0xffffff), - PFAND("clock_dn", PFRO_HEX32, &np2oscfg.clk_color2, 0xffffff), - - PFVAL("comfirm_", PFTYPE_BOOL, &np2oscfg.comfirm), - PFVAL("shortcut", PFTYPE_HEX8, &np2oscfg.shortcut), - - PFSTR("mpu98map", PFTYPE_STR, np2oscfg.mpu.mout), - PFSTR("mpu98min", PFTYPE_STR, np2oscfg.mpu.min), - PFSTR("mpu98mdl", PFTYPE_STR, np2oscfg.mpu.mdl), - PFSTR("mpu98def", PFTYPE_STR, np2oscfg.mpu.def), - -#if defined(SUPPORT_SMPU98) - PFSTR("smpuAmap", PFTYPE_STR, np2oscfg.smpuA.mout), - PFSTR("smpuAmin", PFTYPE_STR, np2oscfg.smpuA.min), - PFSTR("smpuAmdl", PFTYPE_STR, np2oscfg.smpuA.mdl), - PFSTR("smpuAdef", PFTYPE_STR, np2oscfg.smpuA.def), - PFSTR("smpuBmap", PFTYPE_STR, np2oscfg.smpuB.mout), - PFSTR("smpuBmin", PFTYPE_STR, np2oscfg.smpuB.min), - PFSTR("smpuBmdl", PFTYPE_STR, np2oscfg.smpuB.mdl), - PFSTR("smpuBdef", PFTYPE_STR, np2oscfg.smpuB.def), -#endif - - PFMAX("com1port", PFTYPE_UINT8, &np2oscfg.com1.port, 5), - PFVAL("com1para", PFTYPE_UINT8, &np2oscfg.com1.param), - PFVAL("com1_bps", PFTYPE_UINT32, &np2oscfg.com1.speed), - PFVAL("com1fbps", PFTYPE_BOOL, &np2oscfg.com1.fixedspeed), - PFVAL("com1dsrc", PFTYPE_BOOL, &np2oscfg.com1.DSRcheck), - PFSTR("com1mmap", PFTYPE_STR, np2oscfg.com1.mout), - PFSTR("com1mmdl", PFTYPE_STR, np2oscfg.com1.mdl), - PFSTR("com1mdef", PFTYPE_STR, np2oscfg.com1.def), -#if defined(SUPPORT_NAMED_PIPE) - PFSTR("com1pnam", PFTYPE_STR, np2oscfg.com1.pipename), - PFSTR("com1psrv", PFTYPE_STR, np2oscfg.com1.pipeserv), -#endif - - PFMAX("com2port", PFTYPE_UINT8, &np2oscfg.com2.port, 5), - PFVAL("com2para", PFTYPE_UINT8, &np2oscfg.com2.param), - PFVAL("com2_bps", PFTYPE_UINT32, &np2oscfg.com2.speed), - PFVAL("com2fbps", PFTYPE_BOOL, &np2oscfg.com2.fixedspeed), - PFVAL("com2dsrc", PFTYPE_BOOL, &np2oscfg.com2.DSRcheck), - PFSTR("com2mmap", PFTYPE_STR, np2oscfg.com2.mout), - PFSTR("com2mmdl", PFTYPE_STR, np2oscfg.com2.mdl), - PFSTR("com2mdef", PFTYPE_STR, np2oscfg.com2.def), -#if defined(SUPPORT_NAMED_PIPE) - PFSTR("com2pnam", PFTYPE_STR, np2oscfg.com2.pipename), - PFSTR("com2psrv", PFTYPE_STR, np2oscfg.com2.pipeserv), -#endif - - PFMAX("com3port", PFTYPE_UINT8, &np2oscfg.com3.port, 5), - PFVAL("com3para", PFTYPE_UINT8, &np2oscfg.com3.param), - PFVAL("com3_bps", PFTYPE_UINT32, &np2oscfg.com3.speed), - PFVAL("com3fbps", PFTYPE_BOOL, &np2oscfg.com3.fixedspeed), - PFVAL("com3dsrc", PFTYPE_BOOL, &np2oscfg.com3.DSRcheck), - PFSTR("com3mmap", PFTYPE_STR, np2oscfg.com3.mout), - PFSTR("com3mmdl", PFTYPE_STR, np2oscfg.com3.mdl), - PFSTR("com3mdef", PFTYPE_STR, np2oscfg.com3.def), -#if defined(SUPPORT_NAMED_PIPE) - PFSTR("com3pnam", PFTYPE_STR, np2oscfg.com3.pipename), - PFSTR("com3psrv", PFTYPE_STR, np2oscfg.com3.pipeserv), -#endif - - PFVAL("force400", PFRO_BOOL, &np2oscfg.force400), - PFVAL("e_resume", PFTYPE_BOOL, &np2oscfg.resume), - PFVAL("STATSAVE", PFRO_BOOL, &np2oscfg.statsave), -#if !defined(_WIN64) - PFVAL("nousemmx", PFTYPE_BOOL, &np2oscfg.disablemmx), -#endif - PFVAL("windtype", PFTYPE_UINT8, &np2oscfg.wintype), - PFVAL("toolwind", PFTYPE_BOOL, &np2oscfg.toolwin), - PFVAL("keydispl", PFTYPE_BOOL, &np2oscfg.keydisp), - PFVAL("skbdwind", PFTYPE_BOOL, &np2oscfg.skbdwin), - PFVAL("I286SAVE", PFRO_BOOL, &np2oscfg.I286SAVE), - PFVAL("jast_snd", PFTYPE_BOOL, &np2oscfg.jastsnd), - PFVAL("useromeo", PFTYPE_BOOL, &np2oscfg.useromeo), - PFVAL("thickfrm", PFTYPE_BOOL, &np2oscfg.thickframe), - PFVAL("xrollkey", PFTYPE_BOOL, &np2oscfg.xrollkey), - PFVAL("fscrn_cx", PFRO_SINT32, &np2oscfg.fscrn_cx), - PFVAL("fscrn_cy", PFRO_SINT32, &np2oscfg.fscrn_cy), - PFVAL("fscrnbpp", PFRO_UINT8, &np2oscfg.fscrnbpp), - PFVAL("fscrnmod", PFTYPE_HEX8, &np2oscfg.fscrnmod), - PFVAL("fsrescfg", PFTYPE_BOOL, &np2oscfg.fsrescfg), // 解像度毎に設定保存する - -#if defined(SUPPORT_SCRN_DIRECT3D) - PFVAL("D3D_IMODE", PFTYPE_UINT8, &np2oscfg.d3d_imode), // Direct3D 拡大縮小補間モード - PFVAL("D3D_EXCLU", PFTYPE_BOOL, &np2oscfg.d3d_exclusive), // Direct3D 排他モード使用 -#endif - - PFVAL("snddev_t", PFTYPE_UINT8, &np2oscfg.cSoundDeviceType), - PFSTR("snddev_n", PFTYPE_STR, np2oscfg.szSoundDeviceName), - -#if defined(SUPPORT_VSTi) - PFSTR("VSTiFile", PFRO_STR, np2oscfg.szVSTiFile), -#endif // defined(SUPPORT_VSTi) - - PFVAL("EMUDDRAW", PFTYPE_BOOL, &np2oscfg.emuddraw), // 最近はEMULATIONONLYにした方速かったりする(特にピクセル操作する場合とか) - PFVAL("DRAWTYPE", PFTYPE_UINT8, &np2oscfg.drawtype), // 画面レンダラ (0: DirectDraw, 1: reserved(DirecrDraw), 2: Direct3D) - - PFVAL("DRAGDROP", PFRO_BOOL, &np2oscfg.dragdrop), // ドラッグアンドドロップサポート - PFVAL("MAKELHDD", PFRO_BOOL, &np2oscfg.makelhdd), // 巨大HDDイメージ作成サポート - PFVAL("SYSKHOOK", PFTYPE_BOOL, &np2oscfg.syskhook), // システムキーフックサポート - PFVAL("RAWMOUSE", PFTYPE_BOOL, &np2oscfg.rawmouse), // 直接マウスデータ読み取り - PFVAL("MOUSEMUL", PFTYPE_SINT16, &np2oscfg.mousemul), // マウススピード倍率(分子) - PFVAL("MOUSEDIV", PFTYPE_SINT16, &np2oscfg.mousediv), // マウススピード倍率(分母) - - PFVAL("SCRNMODE", PFTYPE_UINT8, &np2oscfg.scrnmode), // フルスクリーン設定 - PFVAL("SAVESCRN", PFTYPE_BOOL, &np2oscfg.savescrn), // フルスクリーン設定を保存・復元する - - PFVAL("SVSCRMUL", PFTYPE_BOOL, &np2oscfg.svscrmul), // 画面表示倍率を保存するか - PFVAL("SCRN_MUL", PFTYPE_UINT8, &np2oscfg.scrn_mul), // 画面表示倍率(8が等倍) - - PFVAL("MOUSE_NC", PFTYPE_BOOL, &np2oscfg.mouse_nc), // マウスキャプチャ無しコントロール - PFVAL("CPUSTABF", PFTYPE_UINT16, &np2oscfg.cpustabf), // クロック安定器適用限界時間(フレーム) - PFVAL("READONLY", PFRO_BOOL, &np2oscfg.readonly), // 変更を設定ファイルに書き込まない - PFVAL("TICKMODE", PFRO_UINT8, &np2oscfg.tickmode), // Tickカウンタのモードを強制的に設定する - PFVAL("USEWHEEL", PFTYPE_BOOL, &np2oscfg.usewheel), // マウスホイールによる音量・マウス速度設定を使用する - //PFVAL("USE_MVOL", PFRO_BOOL, &np2oscfg.usemastervolume), // マスタボリューム設定を使用する - PFVAL("USEMIDIV", PFRO_BOOL, &np2oscfg.usemidivolume), // MIDI疑似ボリューム設定を使用する - PFMAX("MVOL_MAX", PFRO_UINT8, &np2oscfg.mastervolumemax, 255), // マスタボリュームの最大値を設定する - - PFVAL("TWNDHIST", PFRO_UINT8, &np2oscfg.toolwndhistory), // ツールウィンドウのFDファイル履歴の記憶数 - -#if defined(SUPPORT_WACOM_TABLET) - PFVAL("PENTABFA", PFTYPE_BOOL, &np2oscfg.pentabfa), // ペンタブレット アスペクト比固定モード -#endif -#if defined(SUPPORT_MULTITHREAD) - PFVAL("MTENABLE", PFRO_BOOL, &np2oscfg.multithread), // マルチスレッドモード -#endif -}; - -//! .ini 拡張子 -static const TCHAR s_szExt[] = TEXT(".ini"); - -/** - * 設定ファイルのパスを得る - * @param[out] lpPath パス - * @param[in] cchPath パス バッファの長さ - */ -void initgetfile(LPTSTR lpPath, UINT cchPath) -{ - LPCTSTR lpIni = Np2Arg::GetInstance()->iniFilename(); - if (lpIni) - { - file_cpyname(lpPath, lpIni, cchPath); - //LPCTSTR lpExt = file_getext(lpPath); - //if (lpExt[0] != '\0') - //{ - // file_catname(lpPath, s_szExt, cchPath); - //} - } - else - { - file_cpyname(lpPath, modulefile, cchPath); - file_cutext(lpPath); - file_catname(lpPath, s_szExt, cchPath); - } -} - -/** - * 読み込み - */ -void initload(void) -{ - TCHAR szPath[MAX_PATH]; - - initgetfile(szPath, _countof(szPath)); - ini_read(szPath, s_szIniTitle, s_IniItems, _countof(s_IniItems)); -} - -/** - * 書き出し - */ -void initsave(void) -{ - if(!np2oscfg.readonly){ - TCHAR szPath[MAX_PATH]; - - initgetfile(szPath, _countof(szPath)); - ini_write(szPath, s_szIniTitle, s_IniItems, _countof(s_IniItems)); - } -} +/** + * @file ini.cpp + * @brief 設定ファイル アクセスの動作の定義を行います + */ + +#include "compiler.h" +#include "strres.h" +#include "profile.h" +#include "np2.h" +#include "np2arg.h" +#include "dosio.h" +#include "ini.h" +#include "winkbd.h" +#include "pccore.h" + +// ---- user type + +/** + * 16ビット配列を読み込む + * @param[in] lpString 文字列 + * @param[out] ini 設定テーブル + */ +static void inirdargs16(LPCTSTR lpString, const PFTBL* ini) +{ + SINT16* lpDst = static_cast(ini->value); + const int nCount = ini->arg; + + for (int i = 0; i < nCount; i++) + { + while (*lpString == ' ') + { + lpString++; + } + + if (*lpString == '\0') + { + break; + } + + lpDst[i] = static_cast(milstr_solveINT(lpString)); + while (*lpString != '\0') + { + const TCHAR c = *lpString++; + if (c == ',') + { + break; + } + } + } +} + +/** + * 3バイトを読み込む + * @param[in] lpString 文字列 + * @param[out] ini 設定テーブル + */ +static void inirdbyte3(LPCTSTR lpString, const PFTBL* ini) +{ + for (int i = 0; i < 3; i++) + { + const TCHAR c = lpString[i]; + if (c == '\0') + { + break; + } + if ((((c - '0') & 0xff) < 9) || (((c - 'A') & 0xdf) < 26)) + { + (static_cast(ini->value))[i] = static_cast(c); + } + } +} + +/** + * キーボード設定を読み込む + * @param[in] lpString 文字列 + * @param[out] ini 設定テーブル + */ +static void inirdkb(LPCTSTR lpString, const PFTBL* ini) +{ + if ((!milstr_extendcmp(lpString, TEXT("PC98"))) || (!milstr_cmp(lpString, TEXT("98")))) + { + *(static_cast(ini->value)) = KEY_PC98; + } + else if ((!milstr_extendcmp(lpString, TEXT("DOS"))) || (!milstr_cmp(lpString, TEXT("PCAT"))) || (!milstr_cmp(lpString, TEXT("AT")))) + { + *(static_cast(ini->value)) = KEY_KEY106; + } + else if ((!milstr_extendcmp(lpString, TEXT("KEY101"))) || (!milstr_cmp(lpString, TEXT("101")))) + { + *(static_cast(ini->value)) = KEY_KEY101; + } +} + + +// ---- Use WinAPI + +#if !defined(_UNICODE) +/** + * ビットを設定 + * @param[in,out] lpBuffer バッファ + * @param[in] nPos 位置 + * @param[in] set セット or クリア + */ +static void bitmapset(void* lpBuffer, UINT nPos, BOOL set) +{ + const int nIndex = (nPos >> 3); + const UINT8 cBit = 1 << (nPos & 7); + if (set) + { + (static_cast(lpBuffer))[nIndex] |= cBit; + } + else + { + (static_cast(lpBuffer))[nIndex] &= ~cBit; + } +} + +/** + * ビットを得る + * @param[in] lpBuffer バッファ + * @param[in] nPos 位置 + * @return ビット + */ +static BOOL bitmapget(const void* lpBuffer, UINT nPos) +{ + const int nIndex = (nPos >> 3); + const UINT8 cBit = 1 << (nPos & 7); + return (((static_cast(lpBuffer))[nIndex]) & cBit) ? TRUE : FALSE; +} + +/** + * バイナリをアンシリアライズ + * @param[out] lpBin バイナリ + * @param[in] cbBin バイナリのサイズ + * @param[in] lpString 文字列バッファ + */ +static void binset(void* lpBin, UINT cbBin, LPCTSTR lpString) +{ + for (UINT i = 0; i < cbBin; i++) + { + while (*lpString == ' ') + { + lpString++; + } + + LPTSTR lpStringEnd; + const long lVal = _tcstol(lpString, &lpStringEnd, 16); + if (lpString == lpStringEnd) + { + break; + } + + (static_cast(lpBin))[i] = static_cast(lVal); + lpString = lpStringEnd; + } +} + +/** + * バイナリをシリアライズ + * @param[out] lpString 文字列バッファ + * @param[in] cchString 文字列バッファ長 + * @param[in] lpBin バイナリ + * @param[in] cbBin バイナリのサイズ + */ +static void binget(LPTSTR lpString, int cchString, const void* lpBin, UINT cbBin) +{ + + if (cbBin) + { + TCHAR tmp[8]; + wsprintf(tmp, TEXT("%.2x"), (static_cast(lpBin))[0]); + milstr_ncpy(lpString, tmp, cchString); + } + for (UINT i = 1; i < cbBin; i++) + { + TCHAR tmp[8]; + wsprintf(tmp, TEXT(" %.2x"), (static_cast(lpBin))[i]); + milstr_ncat(lpString, tmp, cchString); + } +} + +/** + * 設定読み出し + * @param[in] lpPath パス + * @param[in] lpTitle タイトル + * @param[in] lpTable 設定テーブル + * @param[in] nCount 設定テーブル アイテム数 + */ +void ini_read(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount) +{ + const PFTBL* p = lpTable; + const PFTBL* pTerminate = p + nCount; + while (p < pTerminate) + { + TCHAR szWork[512]; + UINT32 val; + switch (p->itemtype & PFTYPE_MASK) + { + case PFTYPE_STR: + GetPrivateProfileString(lpTitle, p->item, static_cast(p->value), static_cast(p->value), p->arg, lpPath); + break; + + case PFTYPE_BOOL: + GetPrivateProfileString(lpTitle, p->item, + (*(static_cast(p->value))) ? str_true : str_false, + szWork, NELEMENTS(szWork), lpPath); + *(static_cast(p->value)) = (!milstr_cmp(szWork, str_true)) ? 1 : 0; + break; + + case PFTYPE_BITMAP: + GetPrivateProfileString(lpTitle, p->item, + (bitmapget(p->value, p->arg)) ? str_true : str_false, + szWork, _countof(szWork), lpPath); + bitmapset(p->value, p->arg, (milstr_cmp(szWork, str_true) == 0)); + break; + + case PFTYPE_BIN: + GetPrivateProfileString(lpTitle, p->item, str_null, szWork, _countof(szWork), lpPath); + binset(p->value, p->arg, szWork); + break; + + case PFTYPE_SINT8: + case PFTYPE_UINT8: + val = GetPrivateProfileInt(lpTitle, p->item, *(static_cast(p->value)), lpPath); + *(static_cast(p->value)) = static_cast(val); + break; + + case PFTYPE_SINT16: + case PFTYPE_UINT16: + val = GetPrivateProfileInt(lpTitle, p->item, *(static_cast(p->value)), lpPath); + *(static_cast(p->value)) = static_cast(val); + break; + + case PFTYPE_SINT32: + case PFTYPE_UINT32: + val = GetPrivateProfileInt(lpTitle, p->item, *(static_cast(p->value)), lpPath); + *(static_cast(p->value)) = static_cast(val); + break; + + case PFTYPE_HEX8: + wsprintf(szWork, str_x, *(static_cast(p->value))); + GetPrivateProfileString(lpTitle, p->item, szWork, szWork, _countof(szWork), lpPath); + *(static_cast(p->value)) = static_cast(milstr_solveHEX(szWork)); + break; + + case PFTYPE_HEX16: + wsprintf(szWork, str_x, *(static_cast(p->value))); + GetPrivateProfileString(lpTitle, p->item, szWork, szWork, _countof(szWork), lpPath); + *(static_cast(p->value)) = static_cast(milstr_solveHEX(szWork)); + break; + + case PFTYPE_HEX32: + wsprintf(szWork, str_x, *(static_cast(p->value))); + GetPrivateProfileString(lpTitle, p->item, szWork, szWork, _countof(szWork), lpPath); + *(static_cast(p->value)) = static_cast(milstr_solveHEX(szWork)); + break; + + case PFTYPE_ARGS16: + GetPrivateProfileString(lpTitle, p->item, str_null, szWork, _countof(szWork), lpPath); + inirdargs16(szWork, p); + break; + + case PFTYPE_BYTE3: + GetPrivateProfileString(lpTitle, p->item, str_null, szWork, _countof(szWork), lpPath); + inirdbyte3(szWork, p); + break; + + case PFTYPE_KB: + GetPrivateProfileString(lpTitle, p->item, str_null, szWork, _countof(szWork), lpPath); + inirdkb(szWork, p); + break; + } + p++; + } +} + +/** + * 設定書き込み + * @param[in] lpPath パス + * @param[in] lpTitle タイトル + * @param[in] lpTable 設定テーブル + * @param[in] nCount 設定テーブル アイテム数 + */ +void ini_write(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount) +{ + const PFTBL* p = lpTable; + const PFTBL* pTerminate = p + nCount; + while (p < pTerminate) + { + if (!(p->itemtype & PFFLAG_RO)) + { + TCHAR szWork[512]; + szWork[0] = '\0'; + + LPCTSTR lpSet = szWork; + switch(p->itemtype & PFTYPE_MASK) { + case PFTYPE_STR: + lpSet = static_cast(p->value); + break; + + case PFTYPE_BOOL: + lpSet = (*(static_cast(p->value))) ? str_true : str_false; + break; + + case PFTYPE_BITMAP: + lpSet = (bitmapget(p->value, p->arg)) ? str_true : str_false; + break; + + case PFTYPE_BIN: + binget(szWork, _countof(szWork), p->value, p->arg); + break; + + case PFTYPE_SINT8: + wsprintf(szWork, str_d, *(static_cast(p->value))); + break; + + case PFTYPE_SINT16: + wsprintf(szWork, str_d, *(static_cast(p->value))); + break; + + case PFTYPE_SINT32: + wsprintf(szWork, str_d, *(static_cast(p->value))); + break; + + case PFTYPE_UINT8: + wsprintf(szWork, str_u, *(static_cast(p->value))); + break; + + case PFTYPE_UINT16: + wsprintf(szWork, str_u, *(static_cast(p->value))); + break; + + case PFTYPE_UINT32: + wsprintf(szWork, str_u, *(static_cast(p->value))); + break; + + case PFTYPE_HEX8: + wsprintf(szWork, str_x, *(static_cast(p->value))); + break; + + case PFTYPE_HEX16: + wsprintf(szWork, str_x, *(static_cast(p->value))); + break; + + case PFTYPE_HEX32: + wsprintf(szWork, str_x, *(static_cast(p->value))); + break; + + default: + lpSet = NULL; + break; + } + if (lpSet) + { + ::WritePrivateProfileString(lpTitle, p->item, lpSet, lpPath); + } + } + p++; + } +} + +#else // !defined(_UNICODE) + +// ---- Use profile.c + +/** + * コールバック + * @param[in] item アイテム + * @param[in] lpString 文字列 + */ +static void UserReadItem(const PFTBL* item, LPCTSTR lpString) +{ + switch (item->itemtype & PFTYPE_MASK) + { + case PFTYPE_ARGS16: + inirdargs16(lpString, item); + break; + + case PFTYPE_BYTE3: + inirdbyte3(lpString, item); + break; + + case PFTYPE_KB: + inirdkb(lpString, item); + break; + } +} + +/** + * 設定読み取り + * @param[in] lpPath パス + * @param[in] lpTitle タイトル + * @param[in] lpTable 設定テーブル + * @param[in] nCount 設定テーブル アイテム数 + */ +void ini_read(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount) +{ + profile_iniread(lpPath, lpTitle, lpTable, nCount, UserReadItem); +} + +/** + * 設定書き込み + * @param[in] lpPath パス + * @param[in] lpTitle タイトル + * @param[in] lpTable 設定テーブル + * @param[in] nCount 設定テーブル アイテム数 + */ +void ini_write(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount) +{ + profile_iniwrite(lpPath, lpTitle, lpTable, nCount, NULL); +} + +#endif // !defined(_UNICODE) + + +// ---- + +#if !defined(SUPPORT_PC9821) +static const TCHAR s_szIniTitle[] = TEXT("NekoProjectII"); //!< アプリ名 +#else +static const TCHAR s_szIniTitle[] = TEXT("NekoProject21"); //!< アプリ名 +#endif + +/** + * 追加設定 + */ +enum +{ + PFRO_STR = PFFLAG_RO + PFTYPE_STR, + PFRO_BOOL = PFFLAG_RO + PFTYPE_BOOL, + PFRO_BITMAP = PFFLAG_RO + PFTYPE_BITMAP, + PFRO_UINT8 = PFFLAG_RO + PFTYPE_UINT8, + PFRO_SINT32 = PFFLAG_RO + PFTYPE_SINT32, + PFRO_HEX8 = PFFLAG_RO + PFTYPE_HEX8, + PFRO_HEX32 = PFFLAG_RO + PFTYPE_HEX32, + PFRO_BYTE3 = PFFLAG_RO + PFTYPE_BYTE3, + PFRO_KB = PFFLAG_RO + PFTYPE_KB, +}; + +/** + * OS 設定 テーブル + */ +static const PFTBL s_IniItems[] = +{ + PFSTR("np2title", PFRO_STR, np2oscfg.titles), + PFVAL("np2winid", PFRO_BYTE3, np2oscfg.winid), + PFVAL("WindposX", PFTYPE_SINT32, &np2oscfg.winx), + PFVAL("WindposY", PFTYPE_SINT32, &np2oscfg.winy), + PFMAX("paddingx", PFRO_SINT32, &np2oscfg.paddingx, 32), + PFMAX("paddingy", PFRO_SINT32, &np2oscfg.paddingy, 32), + PFVAL("Win_Snap", PFTYPE_BOOL, &np2oscfg.WINSNAP), + + PFSTR("FDfolder", PFTYPE_STR, fddfolder), + PFSTR("HDfolder", PFTYPE_STR, hddfolder), + PFSTR("CDfolder", PFTYPE_STR, cdfolder), + PFSTR("bmap_Dir", PFTYPE_STR, bmpfilefolder), + PFSTR("npcfgDir", PFTYPE_STR, npcfgfilefolder), + PFSTR("fontfile", PFTYPE_STR, np2cfg.fontfile), + PFSTR("biospath", PFRO_STR, np2cfg.biospath), + +#if defined(SUPPORT_HOSTDRV) + PFVAL("use_hdrv", PFTYPE_BOOL, &np2cfg.hdrvenable), + PFSTR("hdrvroot", PFTYPE_STR, np2cfg.hdrvroot), + PFVAL("hdrv_acc", PFTYPE_UINT8, &np2cfg.hdrvacc), +#endif + + PFSTR("pc_model", PFTYPE_STR, np2cfg.model), + PFVAL("clk_base", PFTYPE_UINT32, &np2cfg.baseclock), + PFVAL("clk_mult", PFTYPE_UINT32, &np2cfg.multiple), + + PFEXT("DIPswtch", PFTYPE_BIN, np2cfg.dipsw, 3), + PFEXT("MEMswtch", PFTYPE_BIN, np2cfg.memsw, 8), +#if defined(SUPPORT_LARGE_MEMORY) + PFMAX("ExMemory", PFTYPE_UINT16, &np2cfg.EXTMEM, MEMORY_MAXSIZE), +#else + PFMAX("ExMemory", PFTYPE_UINT8, &np2cfg.EXTMEM, MEMORY_MAXSIZE), +#endif + PFVAL("ITF_WORK", PFTYPE_BOOL, &np2cfg.ITF_WORK), + + PFVAL("USE_BIOS", PFTYPE_BOOL, &np2cfg.usebios), // 実機BIOS使用 + + PFVAL("SVFDFILE", PFTYPE_BOOL, &np2cfg.savefddfile), + PFSTR("FDD1FILE", PFTYPE_STR, np2cfg.fddfile[0]), + PFSTR("FDD2FILE", PFTYPE_STR, np2cfg.fddfile[1]), + PFSTR("FDD3FILE", PFTYPE_STR, np2cfg.fddfile[2]), + PFSTR("FDD4FILE", PFTYPE_STR, np2cfg.fddfile[3]), + + PFSTR("HDD1FILE", PFTYPE_STR, np2cfg.sasihdd[0]), + PFSTR("HDD2FILE", PFTYPE_STR, np2cfg.sasihdd[1]), +#if defined(SUPPORT_SCSI) + PFSTR("SCSIHDD0", PFTYPE_STR, np2cfg.scsihdd[0]), + PFSTR("SCSIHDD1", PFTYPE_STR, np2cfg.scsihdd[1]), + PFSTR("SCSIHDD2", PFTYPE_STR, np2cfg.scsihdd[2]), + PFSTR("SCSIHDD3", PFTYPE_STR, np2cfg.scsihdd[3]), +#endif +#if defined(SUPPORT_IDEIO) + PFSTR("HDD3FILE", PFTYPE_STR, np2cfg.sasihdd[2]), + PFSTR("HDD4FILE", PFTYPE_STR, np2cfg.sasihdd[3]), + PFVAL("IDE1TYPE", PFTYPE_UINT8, &np2cfg.idetype[0]), + PFVAL("IDE2TYPE", PFTYPE_UINT8, &np2cfg.idetype[1]), + PFVAL("IDE3TYPE", PFTYPE_UINT8, &np2cfg.idetype[2]), + PFVAL("IDE4TYPE", PFTYPE_UINT8, &np2cfg.idetype[3]), + PFVAL("IDE_BIOS", PFTYPE_BOOL, &np2cfg.idebios), // 実機IDE BIOS使用 + PFVAL("AIDEBIOS", PFTYPE_BOOL, &np2cfg.autoidebios), // 実機IDE BIOS使用を自動設定する + PFVAL("IDERWAIT", PFTYPE_UINT32, &np2cfg.iderwait), + PFVAL("IDEWWAIT", PFTYPE_UINT32, &np2cfg.idewwait), + PFVAL("IDEMWAIT", PFTYPE_UINT32, &np2cfg.idemwait), + PFVAL("CD_ASYNC", PFTYPE_BOOL, &np2cfg.useasynccd), + PFVAL("CDTRAYOP", PFTYPE_BOOL, &np2cfg.allowcdtraycmd), + PFVAL("SVCDFILE", PFTYPE_BOOL, &np2cfg.savecdfile), + PFVAL("HD_ASYNC", PFRO_BOOL, &np2cfg.useasynchd), + PFSTR("CD1_FILE", PFTYPE_STR, np2cfg.idecd[0]), + PFSTR("CD2_FILE", PFTYPE_STR, np2cfg.idecd[1]), + PFSTR("CD3_FILE", PFTYPE_STR, np2cfg.idecd[2]), + PFSTR("CD4_FILE", PFTYPE_STR, np2cfg.idecd[3]), +#endif + + PFVAL("SampleHz", PFTYPE_UINT32, &np2cfg.samplingrate), + PFVAL("Latencys", PFTYPE_UINT16, &np2cfg.delayms), + PFVAL("SNDboard", PFTYPE_HEX8, &np2cfg.SOUND_SW), + PFAND("BEEP_vol", PFTYPE_UINT8, &np2cfg.BEEP_VOL, 3), + PFVAL("xspeaker", PFRO_BOOL, &np2cfg.snd_x), + + PFEXT("SND14vol", PFTYPE_BIN, np2cfg.vol14, 6), +// PFEXT("opt14BRD", PFTYPE_BIN, np2cfg.snd14opt, 3), + PFVAL("opt26BRD", PFTYPE_HEX8, &np2cfg.snd26opt), + PFVAL("opt86BRD", PFTYPE_HEX8, &np2cfg.snd86opt), + PFVAL("optSPBRD", PFTYPE_HEX8, &np2cfg.spbopt), + PFVAL("optSPBVR", PFTYPE_HEX8, &np2cfg.spb_vrc), + PFMAX("optSPBVL", PFTYPE_UINT8, &np2cfg.spb_vrl, 24), + PFVAL("optSPB_X", PFTYPE_BOOL, &np2cfg.spb_x), + PFVAL("USEMPU98", PFTYPE_BOOL, &np2cfg.mpuenable), + PFVAL("optMPU98", PFTYPE_HEX8, &np2cfg.mpuopt), + PFVAL("optMPUAT", PFTYPE_BOOL, &np2cfg.mpu_at), +#if defined(SUPPORT_SMPU98) + PFVAL("USE_SMPU", PFTYPE_BOOL, &np2cfg.smpuenable), + PFVAL("opt_SMPU", PFTYPE_HEX8, &np2cfg.smpuopt), + PFVAL("SMPUMUTB", PFTYPE_BOOL, &np2cfg.smpumuteB), +#endif + + PFVAL("opt118io", PFTYPE_HEX16, &np2cfg.snd118io), + PFVAL("opt118id", PFTYPE_HEX8, &np2cfg.snd118id), + PFVAL("opt118dm", PFTYPE_UINT8, &np2cfg.snd118dma), + PFVAL("opt118if", PFTYPE_UINT8, &np2cfg.snd118irqf), + PFVAL("opt118ip", PFTYPE_UINT8, &np2cfg.snd118irqp), + PFVAL("opt118im", PFTYPE_UINT8, &np2cfg.snd118irqm), + PFVAL("opt118ro", PFTYPE_UINT8, &np2cfg.snd118rom), + + PFVAL("optwssid", PFTYPE_HEX8, &np2cfg.sndwssid), + PFVAL("optwssdm", PFTYPE_UINT8, &np2cfg.sndwssdma), + PFVAL("optwssip", PFTYPE_UINT8, &np2cfg.sndwssirq), + +#if defined(SUPPORT_SOUND_SB16) + PFVAL("optsb16p", PFTYPE_HEX8, &np2cfg.sndsb16io), + PFVAL("optsb16d", PFTYPE_UINT8, &np2cfg.sndsb16dma), + PFVAL("optsb16i", PFTYPE_UINT8, &np2cfg.sndsb16irq), + PFVAL("optsb16A", PFTYPE_BOOL, &np2cfg.sndsb16at), +#endif /* SUPPORT_SOUND_SB16 */ + + PFMAX("volume_M", PFTYPE_UINT8, &np2cfg.vol_master, 100), + PFMAX("volume_F", PFTYPE_UINT8, &np2cfg.vol_fm, 128), + PFMAX("volume_S", PFTYPE_UINT8, &np2cfg.vol_ssg, 128), + PFMAX("volume_A", PFTYPE_UINT8, &np2cfg.vol_adpcm, 128), + PFMAX("volume_P", PFTYPE_UINT8, &np2cfg.vol_pcm, 128), + PFMAX("volume_R", PFTYPE_UINT8, &np2cfg.vol_rhythm, 128), + PFMAX("volume_V", PFTYPE_UINT8, &np2cfg.vol_midi, 128), + + PFVAL("Seek_Snd", PFTYPE_BOOL, &np2cfg.MOTOR), + PFMAX("Seek_Vol", PFTYPE_UINT8, &np2cfg.MOTORVOL, 100), + + PFVAL("btnRAPID", PFTYPE_BOOL, &np2cfg.BTN_RAPID), + PFVAL("btn_MODE", PFTYPE_BOOL, &np2cfg.BTN_MODE), + PFVAL("Mouse_sw", PFTYPE_BOOL, &np2oscfg.MOUSE_SW), + PFVAL("MS_RAPID", PFTYPE_BOOL, &np2cfg.MOUSERAPID), + + PFAND("backgrnd", PFTYPE_UINT8, &np2oscfg.background, 3), + PFEXT("VRAMwait", PFTYPE_BIN, np2cfg.wait, 6), + PFAND("DspClock", PFTYPE_UINT8, &np2oscfg.DISPCLK, 3), + PFVAL("DispSync", PFTYPE_BOOL, &np2cfg.DISPSYNC), + PFVAL("Real_Pal", PFTYPE_BOOL, &np2cfg.RASTER), + PFMAX("RPal_tim", PFTYPE_UINT8, &np2cfg.realpal, 64), + PFVAL("s_NOWAIT", PFTYPE_BOOL, &np2oscfg.NOWAIT), + PFVAL("SkpFrame", PFTYPE_UINT8, &np2oscfg.DRAW_SKIP), + PFVAL("uPD72020", PFTYPE_BOOL, &np2cfg.uPD72020), + PFAND("GRCG_EGC", PFTYPE_UINT8, &np2cfg.grcg, 3), + PFVAL("color16b", PFTYPE_BOOL, &np2cfg.color16), + PFVAL("skipline", PFTYPE_BOOL, &np2cfg.skipline), + PFVAL("skplight", PFTYPE_UINT16, &np2cfg.skiplight), + PFAND("LCD_MODE", PFTYPE_UINT8, &np2cfg.LCD_MODE, 0x03), + PFAND("BG_COLOR", PFRO_HEX32, &np2cfg.BG_COLOR, 0xffffff), + PFAND("FG_COLOR", PFRO_HEX32, &np2cfg.FG_COLOR, 0xffffff), + + PFVAL("pc9861_e", PFTYPE_BOOL, &np2cfg.pc9861enable), + PFEXT("pc9861_s", PFTYPE_BIN, np2cfg.pc9861sw, 3), + PFEXT("pc9861_j", PFTYPE_BIN, np2cfg.pc9861jmp, 6), + +#if defined(SUPPORT_FMGEN) + PFVAL("USEFMGEN", PFTYPE_BOOL, &np2cfg.usefmgen), +#endif /* SUPPORT_FMGEN */ + + PFVAL("calendar", PFTYPE_BOOL, &np2cfg.calendar), + PFVAL("USE144FD", PFTYPE_BOOL, &np2cfg.usefd144), + PFEXT("FDDRIVE1", PFRO_BITMAP, &np2cfg.fddequip, 0), + PFEXT("FDDRIVE2", PFRO_BITMAP, &np2cfg.fddequip, 1), + PFEXT("FDDRIVE3", PFRO_BITMAP, &np2cfg.fddequip, 2), + PFEXT("FDDRIVE4", PFRO_BITMAP, &np2cfg.fddequip, 3), + +#if defined(SUPPORT_NET) + PFSTR("NP2NETTAP", PFTYPE_STR, np2cfg.np2nettap), + PFVAL("NP2NETPMM", PFTYPE_BOOL, &np2cfg.np2netpmm), +#endif +#if defined(SUPPORT_LGY98) + PFVAL("USELGY98", PFTYPE_BOOL, &np2cfg.uselgy98), + PFVAL("LGY98_IO", PFTYPE_UINT16, &np2cfg.lgy98io), + PFVAL("LGY98IRQ", PFTYPE_UINT8, &np2cfg.lgy98irq), + PFEXT("LGY98MAC", PFTYPE_BIN, np2cfg.lgy98mac, 6), +#endif +#if defined(SUPPORT_WAB) + PFVAL("WAB_ANSW", PFTYPE_UINT8, &np2cfg.wabasw), +#endif +#if defined(SUPPORT_CL_GD5430) + PFVAL("USEGD5430", PFTYPE_BOOL, &np2cfg.usegd5430), + PFVAL("GD5430TYPE",PFTYPE_UINT16, &np2cfg.gd5430type), + PFVAL("GD5430FCUR",PFTYPE_BOOL, &np2cfg.gd5430fakecur), + PFVAL("GDMELOFS", PFTYPE_UINT8, &np2cfg.gd5430melofs), + PFVAL("GANBBSEX", PFTYPE_BOOL, &np2cfg.ga98nb_bigscrn_ex), +#endif +#if defined(SUPPORT_VGA_MODEX) + PFVAL("USEMODEX", PFTYPE_BOOL, &np2cfg.usemodex), +#endif +#if defined(SUPPORT_GPIB) + PFVAL("USE_GPIB", PFTYPE_BOOL, &np2cfg.usegpib), + PFVAL("GPIB_IRQ", PFTYPE_UINT8, &np2cfg.gpibirq), + PFVAL("GPIBMODE", PFTYPE_UINT8, &np2cfg.gpibmode), + PFVAL("GPIBADDR", PFTYPE_UINT8, &np2cfg.gpibaddr), + PFVAL("GPIBEXIO", PFTYPE_UINT8, &np2cfg.gpibexio), +#endif +#if defined(SUPPORT_PCI) + PFVAL("USE98PCI", PFTYPE_BOOL, &np2cfg.usepci), + PFVAL("P_BIOS32", PFTYPE_BOOL, &np2cfg.pci_bios32), + PFVAL("PCI_PCMC", PFTYPE_UINT8, &np2cfg.pci_pcmc), +#endif + + PFMAX("DAVOLUME", PFTYPE_UINT8, &np2cfg.davolume, 255), + PFMAX("MODELNUM", PFTYPE_HEX8, &np2cfg.modelnum, 255), + + PFVAL("TIMERFIX", PFTYPE_BOOL, &np2cfg.timerfix), + + PFVAL("WINNTFIX", PFTYPE_BOOL, &np2cfg.winntfix), + + PFVAL("SYSIOMSK", PFTYPE_HEX16, &np2cfg.sysiomsk), // システムIOマスク + + PFMAX("MEMCHKMX", PFTYPE_UINT8, &np2cfg.memchkmx, 0), // メモリチェックする最大サイズ(最小は15MB・0は制限無し・メモリチェックが長いのが嫌だけど見かけ上カウントだけはしておきたい人向け) + PFMAX("SBEEPLEN", PFTYPE_UINT8, &np2cfg.sbeeplen, 0), // ピポ音の長さ(0でデフォルト・4がNP2標準) + PFVAL("SBEEPADJ", PFTYPE_BOOL, &np2cfg.sbeepadj), // ピポ音の長さ自動調整 + + PFVAL("BIOSIOEM", PFTYPE_BOOL, &np2cfg.biosioemu), // np21w ver0.86 rev46 BIOS I/O emulation + + PFSTR("cpu_vend", PFRO_STR, np2cfg.cpu_vendor_o), + PFVAL("cpu_fami", PFTYPE_UINT32, &np2cfg.cpu_family), + PFVAL("cpu_mode", PFTYPE_UINT32, &np2cfg.cpu_model), + PFVAL("cpu_step", PFTYPE_UINT32, &np2cfg.cpu_stepping), + PFVAL("cpu_feat", PFTYPE_HEX32, &np2cfg.cpu_feature), + PFVAL("cpu_f_ex", PFTYPE_HEX32, &np2cfg.cpu_feature_ex), + PFSTR("cpu_bran", PFRO_STR, np2cfg.cpu_brandstring_o), + PFVAL("cpu_brid", PFTYPE_HEX32, &np2cfg.cpu_brandid), + PFVAL("cpu_fecx", PFTYPE_HEX32, &np2cfg.cpu_feature_ecx), + PFVAL("cpu_fxcx", PFTYPE_HEX32, &np2cfg.cpu_feature_ex_ecx), + PFVAL("cpu_eflg", PFTYPE_HEX32, &np2cfg.cpu_eflags_mask), + + PFVAL("FPU_TYPE", PFTYPE_UINT8, &np2cfg.fpu_type), // FPU種類 + +#if defined(SUPPORT_FAST_MEMORYCHECK) + PFVAL("memckspd", PFTYPE_UINT8, &np2cfg.memcheckspeed), +#endif + + PFVAL("USERAM_D", PFTYPE_BOOL, &np2cfg.useram_d), // EPSONでなくてもD0000h-DFFFFhをRAMに(ただしIDE BIOS D8000h-DBFFFhは駄目) + PFVAL("USEPEGCP", PFTYPE_BOOL, &np2cfg.usepegcplane), // PEGC プレーンモードサポート + + PFVAL("USECDECC", PFTYPE_BOOL, &np2cfg.usecdecc), // CD-ROM EDC/ECC エミュレーションサポート + PFVAL("CDDTSKIP", PFTYPE_BOOL, &np2cfg.cddtskip), // CD-ROM オーディオ再生時にデータトラックをスキップ + +#if defined(SUPPORT_ASYNC_CPU) + PFVAL("ASYNCCPU", PFTYPE_BOOL, &np2cfg.asynccpu), // 非同期CPUモード有効 +#endif + PFVAL("CONSTTSC", PFTYPE_BOOL, &np2cfg.consttsc), // RDTSCをクロック変更によらず一定間隔にする +#if defined(SUPPORT_IDEIO) + PFVAL("IDEBADDR", PFRO_HEX8, &np2cfg.idebaddr), // IDE BIOS アドレス(デフォルト:D8h(D8000h)) +#endif +#if defined(SUPPORT_GAMEPORT) + PFVAL("GAMEPORT", PFTYPE_BOOL, &np2cfg.gameport), +#endif + PFVAL("USEMOVCS", PFRO_BOOL, &np2cfg.allowMOVCS), + PFVAL("USETHOOK", PFRO_BOOL, &np2cfg.usetexthook), + PFVAL("RASCSI92", PFRO_BOOL, &np2cfg.rascsi92), + + + + // OS依存? + PFVAL("keyboard", PFRO_KB, &np2oscfg.KEYBOARD), + PFVAL("usenlock", PFTYPE_BOOL, &np2oscfg.USENUMLOCK), + PFVAL("F12_COPY", PFTYPE_UINT8, &np2oscfg.F12COPY), + PFVAL("Joystick", PFTYPE_BOOL, &np2oscfg.JOYPAD1), + PFEXT("Joy1_btn", PFTYPE_BIN, np2oscfg.JOY1BTN, 4), + PFMAX("Joy1_PID", PFTYPE_UINT8, &np2oscfg.JOYPAD1ID, 15), + + PFVAL("clocknow", PFTYPE_UINT8, &np2oscfg.clk_x), + PFVAL("clockfnt", PFTYPE_UINT8, &np2oscfg.clk_fnt), + PFAND("clock_up", PFRO_HEX32, &np2oscfg.clk_color1, 0xffffff), + PFAND("clock_dn", PFRO_HEX32, &np2oscfg.clk_color2, 0xffffff), + + PFVAL("comfirm_", PFTYPE_BOOL, &np2oscfg.comfirm), + PFVAL("shortcut", PFTYPE_HEX8, &np2oscfg.shortcut), + + PFSTR("mpu98map", PFTYPE_STR, np2oscfg.mpu.mout), + PFSTR("mpu98min", PFTYPE_STR, np2oscfg.mpu.min), + PFSTR("mpu98mdl", PFTYPE_STR, np2oscfg.mpu.mdl), + PFSTR("mpu98def", PFTYPE_STR, np2oscfg.mpu.def), + +#if defined(SUPPORT_SMPU98) + PFSTR("smpuAmap", PFTYPE_STR, np2oscfg.smpuA.mout), + PFSTR("smpuAmin", PFTYPE_STR, np2oscfg.smpuA.min), + PFSTR("smpuAmdl", PFTYPE_STR, np2oscfg.smpuA.mdl), + PFSTR("smpuAdef", PFTYPE_STR, np2oscfg.smpuA.def), + PFSTR("smpuBmap", PFTYPE_STR, np2oscfg.smpuB.mout), + PFSTR("smpuBmin", PFTYPE_STR, np2oscfg.smpuB.min), + PFSTR("smpuBmdl", PFTYPE_STR, np2oscfg.smpuB.mdl), + PFSTR("smpuBdef", PFTYPE_STR, np2oscfg.smpuB.def), +#endif + + PFMAX("com1port", PFTYPE_UINT8, &np2oscfg.com1.port, 5), + PFVAL("com1para", PFTYPE_UINT8, &np2oscfg.com1.param), + PFVAL("com1_bps", PFTYPE_UINT32, &np2oscfg.com1.speed), + PFVAL("com1fbps", PFTYPE_BOOL, &np2oscfg.com1.fixedspeed), + PFVAL("com1dsrc", PFTYPE_BOOL, &np2oscfg.com1.DSRcheck), + PFSTR("com1mmap", PFTYPE_STR, np2oscfg.com1.mout), + PFSTR("com1mmdl", PFTYPE_STR, np2oscfg.com1.mdl), + PFSTR("com1mdef", PFTYPE_STR, np2oscfg.com1.def), +#if defined(SUPPORT_NAMED_PIPE) + PFSTR("com1pnam", PFTYPE_STR, np2oscfg.com1.pipename), + PFSTR("com1psrv", PFTYPE_STR, np2oscfg.com1.pipeserv), +#endif + + PFMAX("com2port", PFTYPE_UINT8, &np2oscfg.com2.port, 5), + PFVAL("com2para", PFTYPE_UINT8, &np2oscfg.com2.param), + PFVAL("com2_bps", PFTYPE_UINT32, &np2oscfg.com2.speed), + PFVAL("com2fbps", PFTYPE_BOOL, &np2oscfg.com2.fixedspeed), + PFVAL("com2dsrc", PFTYPE_BOOL, &np2oscfg.com2.DSRcheck), + PFSTR("com2mmap", PFTYPE_STR, np2oscfg.com2.mout), + PFSTR("com2mmdl", PFTYPE_STR, np2oscfg.com2.mdl), + PFSTR("com2mdef", PFTYPE_STR, np2oscfg.com2.def), +#if defined(SUPPORT_NAMED_PIPE) + PFSTR("com2pnam", PFTYPE_STR, np2oscfg.com2.pipename), + PFSTR("com2psrv", PFTYPE_STR, np2oscfg.com2.pipeserv), +#endif + + PFMAX("com3port", PFTYPE_UINT8, &np2oscfg.com3.port, 5), + PFVAL("com3para", PFTYPE_UINT8, &np2oscfg.com3.param), + PFVAL("com3_bps", PFTYPE_UINT32, &np2oscfg.com3.speed), + PFVAL("com3fbps", PFTYPE_BOOL, &np2oscfg.com3.fixedspeed), + PFVAL("com3dsrc", PFTYPE_BOOL, &np2oscfg.com3.DSRcheck), + PFSTR("com3mmap", PFTYPE_STR, np2oscfg.com3.mout), + PFSTR("com3mmdl", PFTYPE_STR, np2oscfg.com3.mdl), + PFSTR("com3mdef", PFTYPE_STR, np2oscfg.com3.def), +#if defined(SUPPORT_NAMED_PIPE) + PFSTR("com3pnam", PFTYPE_STR, np2oscfg.com3.pipename), + PFSTR("com3psrv", PFTYPE_STR, np2oscfg.com3.pipeserv), +#endif + + PFVAL("force400", PFRO_BOOL, &np2oscfg.force400), + PFVAL("e_resume", PFTYPE_BOOL, &np2oscfg.resume), + PFVAL("STATSAVE", PFRO_BOOL, &np2oscfg.statsave), +#if !defined(_WIN64) + PFVAL("nousemmx", PFTYPE_BOOL, &np2oscfg.disablemmx), +#endif + PFVAL("windtype", PFTYPE_UINT8, &np2oscfg.wintype), + PFVAL("toolwind", PFTYPE_BOOL, &np2oscfg.toolwin), + PFVAL("keydispl", PFTYPE_BOOL, &np2oscfg.keydisp), + PFVAL("skbdwind", PFTYPE_BOOL, &np2oscfg.skbdwin), + PFVAL("I286SAVE", PFRO_BOOL, &np2oscfg.I286SAVE), + PFVAL("jast_snd", PFTYPE_BOOL, &np2oscfg.jastsnd), + PFVAL("useromeo", PFTYPE_BOOL, &np2oscfg.useromeo), + PFVAL("thickfrm", PFTYPE_BOOL, &np2oscfg.thickframe), + PFVAL("xrollkey", PFTYPE_BOOL, &np2oscfg.xrollkey), + PFVAL("fscrn_cx", PFRO_SINT32, &np2oscfg.fscrn_cx), + PFVAL("fscrn_cy", PFRO_SINT32, &np2oscfg.fscrn_cy), + PFVAL("fscrnbpp", PFRO_UINT8, &np2oscfg.fscrnbpp), + PFVAL("fscrnmod", PFTYPE_HEX8, &np2oscfg.fscrnmod), + PFVAL("fsrescfg", PFTYPE_BOOL, &np2oscfg.fsrescfg), // 解像度毎に設定保存する + +#if defined(SUPPORT_SCRN_DIRECT3D) + PFVAL("D3D_IMODE", PFTYPE_UINT8, &np2oscfg.d3d_imode), // Direct3D 拡大縮小補間モード + PFVAL("D3D_EXCLU", PFTYPE_BOOL, &np2oscfg.d3d_exclusive), // Direct3D 排他モード使用 +#endif + + PFVAL("snddev_t", PFTYPE_UINT8, &np2oscfg.cSoundDeviceType), + PFSTR("snddev_n", PFTYPE_STR, np2oscfg.szSoundDeviceName), + +#if defined(SUPPORT_VSTi) + PFSTR("VSTiFile", PFRO_STR, np2oscfg.szVSTiFile), +#endif // defined(SUPPORT_VSTi) + + PFVAL("EMUDDRAW", PFTYPE_BOOL, &np2oscfg.emuddraw), // 最近はEMULATIONONLYにした方速かったりする(特にピクセル操作する場合とか) + PFVAL("DRAWTYPE", PFTYPE_UINT8, &np2oscfg.drawtype), // 画面レンダラ (0: DirectDraw, 1: reserved(DirecrDraw), 2: Direct3D) + + PFVAL("DRAGDROP", PFRO_BOOL, &np2oscfg.dragdrop), // ドラッグアンドドロップサポート + PFVAL("MAKELHDD", PFRO_BOOL, &np2oscfg.makelhdd), // 巨大HDDイメージ作成サポート + PFVAL("SYSKHOOK", PFTYPE_BOOL, &np2oscfg.syskhook), // システムキーフックサポート + PFVAL("RAWMOUSE", PFTYPE_BOOL, &np2oscfg.rawmouse), // 直接マウスデータ読み取り + PFVAL("MOUSEMUL", PFTYPE_SINT16, &np2oscfg.mousemul), // マウススピード倍率(分子) + PFVAL("MOUSEDIV", PFTYPE_SINT16, &np2oscfg.mousediv), // マウススピード倍率(分母) + + PFVAL("SCRNMODE", PFTYPE_UINT8, &np2oscfg.scrnmode), // フルスクリーン設定 + PFVAL("SAVESCRN", PFTYPE_BOOL, &np2oscfg.savescrn), // フルスクリーン設定を保存・復元する + + PFVAL("SVSCRMUL", PFTYPE_BOOL, &np2oscfg.svscrmul), // 画面表示倍率を保存するか + PFVAL("SCRN_MUL", PFTYPE_UINT8, &np2oscfg.scrn_mul), // 画面表示倍率(8が等倍) + + PFVAL("MOUSE_NC", PFTYPE_BOOL, &np2oscfg.mouse_nc), // マウスキャプチャ無しコントロール + PFVAL("CPUSTABF", PFTYPE_UINT16, &np2oscfg.cpustabf), // クロック安定器適用限界時間(フレーム) + PFVAL("READONLY", PFRO_BOOL, &np2oscfg.readonly), // 変更を設定ファイルに書き込まない + PFVAL("TICKMODE", PFRO_UINT8, &np2oscfg.tickmode), // Tickカウンタのモードを強制的に設定する + PFVAL("USEWHEEL", PFTYPE_BOOL, &np2oscfg.usewheel), // マウスホイールによる音量・マウス速度設定を使用する + //PFVAL("USE_MVOL", PFRO_BOOL, &np2oscfg.usemastervolume), // マスタボリューム設定を使用する + PFVAL("USEMIDIV", PFRO_BOOL, &np2oscfg.usemidivolume), // MIDI疑似ボリューム設定を使用する + PFMAX("MVOL_MAX", PFRO_UINT8, &np2oscfg.mastervolumemax, 255), // マスタボリュームの最大値を設定する + + PFVAL("TWNDHIST", PFRO_UINT8, &np2oscfg.toolwndhistory), // ツールウィンドウのFDファイル履歴の記憶数 + +#if defined(SUPPORT_WACOM_TABLET) + PFVAL("PENTABFA", PFTYPE_BOOL, &np2oscfg.pentabfa), // ペンタブレット アスペクト比固定モード +#endif +#if defined(SUPPORT_MULTITHREAD) + PFVAL("MTENABLE", PFRO_BOOL, &np2oscfg.multithread), // マルチスレッドモード +#endif +}; + +//! .ini 拡張子 +static const TCHAR s_szExt[] = TEXT(".ini"); + +/** + * 設定ファイルのパスを得る + * @param[out] lpPath パス + * @param[in] cchPath パス バッファの長さ + */ +void initgetfile(LPTSTR lpPath, UINT cchPath) +{ + LPCTSTR lpIni = Np2Arg::GetInstance()->iniFilename(); + if (lpIni) + { + file_cpyname(lpPath, lpIni, cchPath); + //LPCTSTR lpExt = file_getext(lpPath); + //if (lpExt[0] != '\0') + //{ + // file_catname(lpPath, s_szExt, cchPath); + //} + } + else + { + file_cpyname(lpPath, modulefile, cchPath); + file_cutext(lpPath); + file_catname(lpPath, s_szExt, cchPath); + } +} + +/** + * 読み込み + */ +void initload(void) +{ + TCHAR szPath[MAX_PATH]; + + initgetfile(szPath, _countof(szPath)); + ini_read(szPath, s_szIniTitle, s_IniItems, _countof(s_IniItems)); +} + +/** + * 書き出し + */ +void initsave(void) +{ + if(!np2oscfg.readonly){ + TCHAR szPath[MAX_PATH]; + + initgetfile(szPath, _countof(szPath)); + ini_write(szPath, s_szIniTitle, s_IniItems, _countof(s_IniItems)); + } +} diff --git a/windows/ini.h b/windows/ini.h old mode 100755 new mode 100644 index 7eb32ae7..7991064e --- a/windows/ini.h +++ b/windows/ini.h @@ -1,33 +1,33 @@ -/** - * @file ini.h - * @brief 設定ファイル アクセスの宣言およびインターフェイスの定義をします - */ - -#include - -/** - * 追加設定 - */ -enum -{ - PFTYPE_ARGS16 = PFTYPE_USER, /*!< 16ビット配列 */ - PFTYPE_ARGU32, /*!< 32ビット配列 */ - PFTYPE_BYTE3, /*!< 3バイト */ - PFTYPE_KB, /*!< キーボード設定 */ -}; - -#ifdef __cplusplus -extern "C" -{ -#endif - -void ini_read(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount); -void ini_write(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount); - -void initgetfile(LPTSTR lpPath, UINT cchPath); -void initload(void); -void initsave(void); - -#ifdef __cplusplus -} -#endif +/** + * @file ini.h + * @brief 設定ファイル アクセスの宣言およびインターフェイスの定義をします + */ + +#include + +/** + * 追加設定 + */ +enum +{ + PFTYPE_ARGS16 = PFTYPE_USER, /*!< 16ビット配列 */ + PFTYPE_ARGU32, /*!< 32ビット配列 */ + PFTYPE_BYTE3, /*!< 3バイト */ + PFTYPE_KB, /*!< キーボード設定 */ +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +void ini_read(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount); +void ini_write(LPCTSTR lpPath, LPCTSTR lpTitle, const PFTBL* lpTable, UINT nCount); + +void initgetfile(LPTSTR lpPath, UINT cchPath); +void initload(void); +void initsave(void); + +#ifdef __cplusplus +} +#endif diff --git a/windows/joymng.cpp b/windows/joymng.cpp index 19b39e1b..eeff4d5d 100644 --- a/windows/joymng.cpp +++ b/windows/joymng.cpp @@ -1,113 +1,113 @@ -/** - * @file joymng.cpp - * @brief Joystick manager - * - * @author $Author: yui $ - * @date $Date: 2011/03/07 09:54:11 $ - */ - -#include -#include -#include -#include "menu.h" - -#if !defined(__GNUC__) -#pragma comment(lib, "winmm.lib") -#endif // !defined(__GNUC__) - -enum { - JOY_LEFT_BIT = 0x04, - JOY_RIGHT_BIT = 0x08, - JOY_UP_BIT = 0x01, - JOY_DOWN_BIT = 0x02, - JOY_BTN1_BIT = 0x10, - JOY_BTN2_BIT = 0x20 -}; - -static REG8 joyflag = 0xff; -static UINT8 joypad1btn[4]; - -static REG8 joyavailable = 0; - -void joymng_initialize(void) { - - JOYINFO ji; - int i; - - if ((!joyGetNumDevs()) || - (joyGetPos(JOYSTICKID1 + np2oscfg.JOYPAD1ID, &ji) == JOYERR_UNPLUGGED)) { - np2oscfg.JOYPAD1 |= 2; - } - for (i=0; i<4; i++) { - joypad1btn[i] = 0xff ^ - ((np2oscfg.JOY1BTN[i] & 3) << ((np2oscfg.JOY1BTN[i] & 4)?4:6)); - } -} - -void joymng_sync(void) { - - np2oscfg.JOYPAD1 &= 0x7f; - joyflag = 0xff; -} - -REG8 joymng_getstat(void) { - - JOYINFOEX ji; - static DWORD nojoy_time = 0; - - if (np2oscfg.JOYPAD1 == 1){ - if(nojoy_time == 0 || GetTickCount() - nojoy_time > 5000){ - ji.dwSize = sizeof(JOYINFOEX); - ji.dwFlags = JOY_RETURNALL; - if(joyGetPosEx(JOYSTICKID1 + np2oscfg.JOYPAD1ID, &ji) == JOYERR_NOERROR) { - joyavailable = 1; - np2oscfg.JOYPAD1 |= 0x80; - joyflag = 0xff; - if (ji.dwXpos < 0x4000U) { - joyflag &= ~JOY_LEFT_BIT; - } - else if (ji.dwXpos > 0xc000U) { - joyflag &= ~JOY_RIGHT_BIT; - } - if (ji.dwYpos < 0x4000U) { - joyflag &= ~JOY_UP_BIT; - } - else if (ji.dwYpos > 0xc000U) { - joyflag &= ~JOY_DOWN_BIT; - } - if (ji.dwButtons & JOY_BUTTON1) { - joyflag &= joypad1btn[0]; // ver0.28 - } - if (ji.dwButtons & JOY_BUTTON2) { - joyflag &= joypad1btn[1]; // ver0.28 - } - if (ji.dwButtons & JOY_BUTTON3) { - joyflag &= joypad1btn[2]; // ver0.28 - } - if (ji.dwButtons & JOY_BUTTON4) { - joyflag &= joypad1btn[3]; // ver0.28 - } - nojoy_time = 0; - }else{ - nojoy_time = GetTickCount(); - joyavailable = 0; - } - }else{ - joyavailable = 0; - } - } - return(joyflag); -} -REG8 joymng_available(void) { - return(joyavailable); -} - -// joyflag bit:0 up -// bit:1 down -// bit:2 left -// bit:3 right -// bit:4 trigger1 (rapid) -// bit:5 trigger2 (rapid) -// bit:6 trigger1 -// bit:7 trigger2 - +/** + * @file joymng.cpp + * @brief Joystick manager + * + * @author $Author: yui $ + * @date $Date: 2011/03/07 09:54:11 $ + */ + +#include +#include +#include +#include "menu.h" + +#if !defined(__GNUC__) +#pragma comment(lib, "winmm.lib") +#endif // !defined(__GNUC__) + +enum { + JOY_LEFT_BIT = 0x04, + JOY_RIGHT_BIT = 0x08, + JOY_UP_BIT = 0x01, + JOY_DOWN_BIT = 0x02, + JOY_BTN1_BIT = 0x10, + JOY_BTN2_BIT = 0x20 +}; + +static REG8 joyflag = 0xff; +static UINT8 joypad1btn[4]; + +static REG8 joyavailable = 0; + +void joymng_initialize(void) { + + JOYINFO ji; + int i; + + if ((!joyGetNumDevs()) || + (joyGetPos(JOYSTICKID1 + np2oscfg.JOYPAD1ID, &ji) == JOYERR_UNPLUGGED)) { + np2oscfg.JOYPAD1 |= 2; + } + for (i=0; i<4; i++) { + joypad1btn[i] = 0xff ^ + ((np2oscfg.JOY1BTN[i] & 3) << ((np2oscfg.JOY1BTN[i] & 4)?4:6)); + } +} + +void joymng_sync(void) { + + np2oscfg.JOYPAD1 &= 0x7f; + joyflag = 0xff; +} + +REG8 joymng_getstat(void) { + + JOYINFOEX ji; + static DWORD nojoy_time = 0; + + if (np2oscfg.JOYPAD1 == 1){ + if(nojoy_time == 0 || GetTickCount() - nojoy_time > 5000){ + ji.dwSize = sizeof(JOYINFOEX); + ji.dwFlags = JOY_RETURNALL; + if(joyGetPosEx(JOYSTICKID1 + np2oscfg.JOYPAD1ID, &ji) == JOYERR_NOERROR) { + joyavailable = 1; + np2oscfg.JOYPAD1 |= 0x80; + joyflag = 0xff; + if (ji.dwXpos < 0x4000U) { + joyflag &= ~JOY_LEFT_BIT; + } + else if (ji.dwXpos > 0xc000U) { + joyflag &= ~JOY_RIGHT_BIT; + } + if (ji.dwYpos < 0x4000U) { + joyflag &= ~JOY_UP_BIT; + } + else if (ji.dwYpos > 0xc000U) { + joyflag &= ~JOY_DOWN_BIT; + } + if (ji.dwButtons & JOY_BUTTON1) { + joyflag &= joypad1btn[0]; // ver0.28 + } + if (ji.dwButtons & JOY_BUTTON2) { + joyflag &= joypad1btn[1]; // ver0.28 + } + if (ji.dwButtons & JOY_BUTTON3) { + joyflag &= joypad1btn[2]; // ver0.28 + } + if (ji.dwButtons & JOY_BUTTON4) { + joyflag &= joypad1btn[3]; // ver0.28 + } + nojoy_time = 0; + }else{ + nojoy_time = GetTickCount(); + joyavailable = 0; + } + }else{ + joyavailable = 0; + } + } + return(joyflag); +} +REG8 joymng_available(void) { + return(joyavailable); +} + +// joyflag bit:0 up +// bit:1 down +// bit:2 left +// bit:3 right +// bit:4 trigger1 (rapid) +// bit:5 trigger2 (rapid) +// bit:6 trigger1 +// bit:7 trigger2 + diff --git a/windows/joymng.h b/windows/joymng.h old mode 100755 new mode 100644 index 42b03e24..ad789ffe --- a/windows/joymng.h +++ b/windows/joymng.h @@ -1,18 +1,18 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -REG8 joymng_getstat(void); -REG8 joymng_available(void); - -#ifdef __cplusplus -} -#endif - - -// ---- - -void joymng_initialize(void); -void joymng_sync(void); - + +#ifdef __cplusplus +extern "C" { +#endif + +REG8 joymng_getstat(void); +REG8 joymng_available(void); + +#ifdef __cplusplus +} +#endif + + +// ---- + +void joymng_initialize(void); +void joymng_sync(void); + diff --git a/windows/menu.cpp b/windows/menu.cpp index 66daedcd..303293ca 100644 --- a/windows/menu.cpp +++ b/windows/menu.cpp @@ -1,541 +1,541 @@ -/** - * @file menu.cpp - * @brief メニューの宣言およびインターフェイスの定義をします - */ - -#include -#include "resource.h" -#include "menu.h" -#include -#include -#include -#include "misc\tstring.h" -#include "misc\WndProc.h" -#include -#if defined(SUPPORT_WAVEREC) -#include "sound\sound.h" -#endif -#if defined(SUPPORT_S98) -#include "sound\s98.h" -#endif -#include -#include - -extern UINT8 np2userpause; - -/** - * 検索 - * @param[in] hMenu メニュー ハンドル - * @param[in] uID ID - * @param[out] phmenuRet 見つかったメニュー - * @param[out] pnPos 見つかった位置 - * @retval true 見つかった - * @retval false 見つからなかった - */ -bool menu_searchmenu(HMENU hMenu, UINT uID, HMENU *phmenuRet, int *pnPos) -{ - int nCount = GetMenuItemCount(hMenu); - for (int i = 0; i < nCount; i++) - { - MENUITEMINFO mii; - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_ID | MIIM_SUBMENU; - if (GetMenuItemInfo(hMenu, i, TRUE, &mii)) - { - if (mii.wID == uID) - { - if (phmenuRet) - { - *phmenuRet = hMenu; - } - if (pnPos) - { - *pnPos = i; - } - return true; - } - else if ((mii.hSubMenu) && (menu_searchmenu(mii.hSubMenu, uID, phmenuRet, pnPos))) - { - return true; - } - } - } - return false; -} - -/** - * メニュー追加 - * @param[in] hMenu メニュー ハンドル - * @param[in] nPos 追加する位置 - * @param[in] hmenuAdd 追加するメニュー - * @param[in] bSeparator セパレータを追加する - * @return 追加数 - */ -int menu_addmenu(HMENU hMenu, int nPos, HMENU hmenuAdd, BOOL bSeparator) -{ - if (nPos < 0) - { - nPos = GetMenuItemCount(hMenu); - } - int nCount = GetMenuItemCount(hmenuAdd); - int nAdded = 0; - for (int i = 0; i < nCount; i++) - { - MENUITEMINFO mii; - ZeroMemory(&mii, sizeof(mii)); - - TCHAR szString[128]; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA; - mii.dwTypeData = szString; - mii.cch = _countof(szString); - if (GetMenuItemInfo(hmenuAdd, i, TRUE, &mii)) - { - if (mii.hSubMenu) - { - HMENU hmenuSub = CreatePopupMenu(); - (void)menu_addmenu(hmenuSub, 0, mii.hSubMenu, FALSE); - mii.hSubMenu = hmenuSub; - } - if (bSeparator) - { - bSeparator = FALSE; - InsertMenu(hMenu, nPos + nAdded, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); - nAdded++; - } - InsertMenuItem(hMenu, nPos + nAdded, TRUE, &mii); - nAdded++; - } - } - return nAdded; -} - -/** - * メニュー追加 - * @param[in] hMenu メニュー ハンドル - * @param[in] nPos 追加する位置 - * @param[in] uID メニュー ID - * @param[in] bSeparator セパレータを追加する - * @return 追加数 - */ -int menu_addmenures(HMENU hMenu, int nPos, UINT uID, BOOL bSeparator) -{ - int nCount = 0; - HINSTANCE hInstance = CWndProc::FindResourceHandle(MAKEINTRESOURCE(uID), RT_MENU); - HMENU hmenuAdd = LoadMenu(hInstance, MAKEINTRESOURCE(uID)); - if (hmenuAdd) - { - nCount = menu_addmenu(hMenu, nPos, hmenuAdd, bSeparator); - DestroyMenu(hmenuAdd); - } - return nCount; -} - -/** - * メニュー追加 - * @param[in] hMenu メニュー ハンドル - * @param[in] uByID メニュー位置 - * @param[in] uID メニュー ID - * @return 追加数 - */ -static int menu_addmenubyid(HMENU hMenu, UINT uByID, UINT uID) -{ - int nCount = 0; - - HMENU hmenuSub; - int nSubPos; - if (menu_searchmenu(hMenu, uByID, &hmenuSub, &nSubPos)) - { - nCount = menu_addmenures(hmenuSub, nSubPos + 1, uID, FALSE); - } - return nCount; -} - -/** - * メニュー追加 - * @param[in] hMenu メニューのハンドル - * @param[in] uPosition 新しい項目の直前に位置する項目 - * @param[in] uFlags オプション - * @param[in] uIDNewItem 識別子、メニュー、サブメニューのいずれか - * @param[in] lpNewItem メニュー 文字列 - * @return 関数が成功すると、0 以外の値が返ります - */ -static BOOL InsertMenuString(HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, UINT uStringID) -{ - std::tstring rString(LoadTString(uStringID)); - - BOOL bResult = FALSE; - if (!rString.empty()) - { - bResult = InsertMenu(hMenu, uPosition, uFlags, uIDNewItem, rString.c_str()); - } - return bResult; -} - -/** - * メニュー追加 (単純コピー) - * @param[in] popup コピー先 - * @param[in] menubar コピー元 - */ -void menu_addmenubar(HMENU popup, HMENU menubar) -{ - (void)menu_addmenu(popup, 0, menubar, FALSE); -} - - - -// ---- - -/** - * システム メニュー初期化 - * @param[in] hMenu メニュー ハンドル - */ -void sysmenu_initialize(HMENU hMenu) -{ - UINT uPos = 0; - -#if defined(SUPPORT_KEYDISP) - uPos += menu_addmenures(hMenu, uPos, IDR_SYSKEYDISP, FALSE); -#endif -#if defined(SUPPORT_SOFTKBD) - uPos += menu_addmenures(hMenu, uPos, IDR_SYSSOFTKBD, FALSE); -#endif - - uPos += menu_addmenures(hMenu, uPos, IDR_SYS, FALSE); - if (np2oscfg.I286SAVE) - { -#if defined(CPUCORE_IA32) && defined(SUPPORT_MEMDBG32) - uPos += menu_addmenures(hMenu, uPos, IDR_SYSDEBUG32, FALSE); -#endif - uPos += menu_addmenures(hMenu, uPos, IDR_SYSDEBUG, FALSE); - } -} - -/** - * システム メニュー更新 - * @param[in] hMenu メニュー ハンドル - */ -void sysmenu_update(HMENU hMenu) -{ - CheckMenuItem(hMenu, IDM_TOOLWIN, MF_BYCOMMAND | MFCHECK(np2oscfg.toolwin)); - CheckMenuItem(hMenu, IDM_KEYDISP, MF_BYCOMMAND | MFCHECK(np2oscfg.keydisp)); - CheckMenuItem(hMenu, IDM_SNAPENABLE, MF_BYCOMMAND | MFCHECK(np2oscfg.WINSNAP)); - - const UINT8 background = np2oscfg.background ^ 3; - EnableMenuItem(hMenu, IDM_BGSOUND, (background & 1) ? MF_ENABLED : MF_GRAYED); - CheckMenuItem(hMenu, IDM_BACKGROUND, MF_BYCOMMAND | MFCHECK(background & 1)); - CheckMenuItem(hMenu, IDM_BGSOUND, MF_BYCOMMAND | MFCHECK(background & 2)); - - const int scrnmul = scrnmng_getmultiple(); - CheckMenuItem(hMenu, IDM_SCRNMUL4, MF_BYCOMMAND | MFCHECK(scrnmul == 4)); - CheckMenuItem(hMenu, IDM_SCRNMUL6, MF_BYCOMMAND | MFCHECK(scrnmul == 6)); - CheckMenuItem(hMenu, IDM_SCRNMUL8, MF_BYCOMMAND | MFCHECK(scrnmul == 8)); - CheckMenuItem(hMenu, IDM_SCRNMUL10, MF_BYCOMMAND | MFCHECK(scrnmul == 10)); - CheckMenuItem(hMenu, IDM_SCRNMUL12, MF_BYCOMMAND | MFCHECK(scrnmul == 12)); - CheckMenuItem(hMenu, IDM_SCRNMUL16, MF_BYCOMMAND | MFCHECK(scrnmul == 16)); -} - - - -// ---- - -/** - * メニュー初期化 - * @param[in] メニュー ハンドル - */ -void xmenu_initialize(HMENU hMenu) -{ - int nPos = 1; -#if defined(SUPPORT_STATSAVE) - if (np2oscfg.statsave) - { - nPos += menu_addmenures(hMenu, nPos, IDR_STAT, FALSE); - } -#endif - - for (UINT i = 0; i < 4; i++) - { - if (np2cfg.fddequip & (1 << i)) - { - nPos += menu_addmenures(hMenu, nPos, IDR_FDD1MENU + i, FALSE); - } - } - - HMENU hmenuSub = CreatePopupMenu(); - if (hmenuSub) - { - int nSubPos = 0; -#if defined(SUPPORT_IDEIO) - nSubPos += menu_addmenures(hmenuSub, nSubPos, IDR_IDEMENU, FALSE); -#else - nSubPos += menu_addmenures(hmenuSub, nSubPos, IDR_SASIMENU, FALSE); -#endif -#if defined(SUPPORT_SCSI) - nSubPos += menu_addmenures(hmenuSub, nSubPos, IDR_SCSIMENU, TRUE); -#endif - InsertMenuString(hMenu, nPos, MF_BYPOSITION | MF_POPUP, (UINT_PTR)hmenuSub, IDS_HDD); - } - -#if defined(SUPPORT_PX) - (void)menu_addmenubyid(hMenu, IDM_SPARKBOARD, IDR_PXMENU); -#endif - -#ifndef SUPPORT_NET - EnableMenuItem(hMenu, IDM_NETOPT, MF_BYCOMMAND|MFS_GRAYED); -#endif - -#ifndef SUPPORT_CL_GD5430 - EnableMenuItem(hMenu, IDM_WABOPT, MF_BYCOMMAND|MFS_GRAYED); -#endif - -#ifndef SUPPORT_PCI - EnableMenuItem(hMenu, IDM_PCIOPT, MF_BYCOMMAND|MFS_GRAYED); -#endif - - if (np2oscfg.I286SAVE) - { -#if defined(SUPPORT_PC9821) - (void)menu_addmenubyid(hMenu, IDM_MSRAPID, IDR_CPUSAVE32); - (void)menu_addmenubyid(hMenu, IDM_SSTP, IDR_CPUSAVE32); -#else // defined(SUPPORT_PC9821) - (void)menu_addmenubyid(hMenu, IDM_MSRAPID, IDR_CPUSAVE16); - (void)menu_addmenubyid(hMenu, IDM_SSTP, IDR_CPUSAVE16); -#endif // defined(SUPPORT_PC9821) - } - -#if defined(SUPPORT_DEBUGSS) - if (np2cfg.debugss) { - menu_addmenures(hMenu, GetMenuItemCount(hMenu) - 1, IDR_DEBUGSS, FALSE); - } -#endif -} - -/** - * メニュー状態を更新する - * @param[in] hMenu メニュー ハンドル - */ -void xmenu_update(HMENU hMenu) -{ - if (hMenu == NULL) - { - return; - } - - // Emulate - CheckMenuItem(hMenu, IDM_PAUSE, MF_BYCOMMAND | MFCHECK(np2userpause)); - - // Screen - const bool bFullScreen = ((g_scrnmode & SCRNMODE_FULLSCREEN) != 0); - CheckMenuItem(hMenu, IDM_WINDOW, MF_BYCOMMAND | MFCHECK(!bFullScreen)); - CheckMenuItem(hMenu, IDM_FULLSCREEN, MF_BYCOMMAND | MFCHECK(bFullScreen)); - const UINT8 nRotateMode = g_scrnmode & SCRNMODE_ROTATEMASK; - CheckMenuItem(hMenu, IDM_ROLNORMAL, MF_BYCOMMAND | MFCHECK(nRotateMode == 0)); - CheckMenuItem(hMenu, IDM_ROLLEFT, MF_BYCOMMAND | MFCHECK(nRotateMode == SCRNMODE_ROTATELEFT)); - CheckMenuItem(hMenu, IDM_ROLRIGHT, MF_BYCOMMAND | MFCHECK(nRotateMode == SCRNMODE_ROTATERIGHT)); - CheckMenuItem(hMenu, IDM_DISPSYNC, MF_BYCOMMAND | MFCHECK(np2cfg.DISPSYNC)); - CheckMenuItem(hMenu, IDM_RASTER, MF_BYCOMMAND | MFCHECK(np2cfg.RASTER)); - CheckMenuItem(hMenu, IDM_NOWAIT, MF_BYCOMMAND | MFCHECK(np2oscfg.NOWAIT)); - CheckMenuItem(hMenu, IDM_CPUSTABILIZER, MF_BYCOMMAND | MFCHECK(np2oscfg.cpustabf != 0)); -#if defined(SUPPORT_ASYNC_CPU) - CheckMenuItem(hMenu, IDM_ASYNCCPU, MF_BYCOMMAND | MFCHECK(np2cfg.asynccpu != 0)); -#endif - const UINT8 DRAW_SKIP = CheckMenuItem(hMenu, IDM_AUTOFPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 0)); - CheckMenuItem(hMenu, IDM_60FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 1)); - CheckMenuItem(hMenu, IDM_30FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 2)); - CheckMenuItem(hMenu, IDM_20FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 3)); - CheckMenuItem(hMenu, IDM_15FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 4)); -DRAW_SKIP; - CheckMenuItem(hMenu, IDM_AUTOFPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 0)); - CheckMenuItem(hMenu, IDM_60FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 1)); - CheckMenuItem(hMenu, IDM_30FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 2)); - CheckMenuItem(hMenu, IDM_20FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 3)); - CheckMenuItem(hMenu, IDM_15FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 4)); -#if defined(SUPPORT_VIDEOFILTER) - CheckMenuItem(hMenu, IDM_VF1EN, MF_BYCOMMAND | MFCHECK(np2cfg.vf1_enable)); - CheckMenuItem(hMenu, IDM_VF1P0, MF_BYCOMMAND | MFCHECK(np2cfg.vf1_pno == 0)); - CheckMenuItem(hMenu, IDM_VF1P1, MF_BYCOMMAND | MFCHECK(np2cfg.vf1_pno == 1)); - CheckMenuItem(hMenu, IDM_VF1P2, MF_BYCOMMAND | MFCHECK(np2cfg.vf1_pno == 2)); - CheckMenuItem(hMenu, IDM_VF1BO, MF_BYCOMMAND | MFCHECK(np2cfg.vf1_bmponly)); -#endif - - // Device-Keyboard - const UINT8 KEY_MODE = np2cfg.KEY_MODE; - CheckMenuItem(hMenu, IDM_KEY, MF_BYCOMMAND | MFCHECK(KEY_MODE == 0)); - CheckMenuItem(hMenu, IDM_JOY1, MF_BYCOMMAND | MFCHECK(KEY_MODE == 1)); - CheckMenuItem(hMenu, IDM_JOY2, MF_BYCOMMAND | MFCHECK(KEY_MODE == 2)); - const UINT8 XSHIFT = np2cfg.XSHIFT; - CheckMenuItem(hMenu, IDM_XSHIFT, MF_BYCOMMAND | MFCHECK(XSHIFT & 1)); - CheckMenuItem(hMenu, IDM_XCTRL, MF_BYCOMMAND | MFCHECK(XSHIFT & 2)); - CheckMenuItem(hMenu, IDM_XGRPH, MF_BYCOMMAND | MFCHECK(XSHIFT & 4)); - const UINT8 F12COPY = np2oscfg.F12COPY; - CheckMenuItem(hMenu, IDM_F12MOUSE, MF_BYCOMMAND | MFCHECK(F12COPY == 0)); - CheckMenuItem(hMenu, IDM_F12COPY, MF_BYCOMMAND | MFCHECK(F12COPY == 1)); - CheckMenuItem(hMenu, IDM_F12STOP, MF_BYCOMMAND | MFCHECK(F12COPY == 2)); - CheckMenuItem(hMenu, IDM_F12EQU, MF_BYCOMMAND | MFCHECK(F12COPY == 3)); - CheckMenuItem(hMenu, IDM_F12COMMA, MF_BYCOMMAND | MFCHECK(F12COPY == 4)); - CheckMenuItem(hMenu, IDM_USERKEY1, MF_BYCOMMAND | MFCHECK(F12COPY == 5)); - CheckMenuItem(hMenu, IDM_USERKEY2, MF_BYCOMMAND | MFCHECK(F12COPY == 6)); - CheckMenuItem(hMenu, IDM_F12NOWAIT, MF_BYCOMMAND | MFCHECK(F12COPY == 7)); - CheckMenuItem(hMenu, IDM_F12NOWAIT2, MF_BYCOMMAND | MFCHECK(F12COPY == 8)); - if(!np2oscfg.I286SAVE){ - DeleteMenu(hMenu, IDM_F12WABRELAY, MF_BYCOMMAND); - }else{ - CheckMenuItem(hMenu, IDM_F12WABRELAY, MF_BYCOMMAND | MFCHECK(F12COPY == 9)); - } - CheckMenuItem(hMenu, IDM_USENUMLOCK, MF_BYCOMMAND | MFCHECK(np2oscfg.USENUMLOCK)); - CheckMenuItem(hMenu, IDM_SWAPPAGEUPDOWN, MF_BYCOMMAND | MFCHECK(np2oscfg.xrollkey)); - - // Device-Sound - const UINT8 BEEP_VOL = np2cfg.BEEP_VOL; - CheckMenuItem(hMenu, IDM_BEEPOFF, MF_BYCOMMAND | MFCHECK(BEEP_VOL == 0)); - CheckMenuItem(hMenu, IDM_BEEPLOW, MF_BYCOMMAND | MFCHECK(BEEP_VOL == 1)); - CheckMenuItem(hMenu, IDM_BEEPMID, MF_BYCOMMAND | MFCHECK(BEEP_VOL == 2)); - CheckMenuItem(hMenu, IDM_BEEPHIGH, MF_BYCOMMAND | MFCHECK(BEEP_VOL == 3)); - const UINT8 SOUND_SW = np2cfg.SOUND_SW; - CheckMenuItem(hMenu, IDM_NOSOUND, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_NONE)); - CheckMenuItem(hMenu, IDM_PC9801_14, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_14)); - CheckMenuItem(hMenu, IDM_PC9801_26K, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_26K)); - CheckMenuItem(hMenu, IDM_PC9801_86, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86)); - CheckMenuItem(hMenu, IDM_PC9801_26_86, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_26K)); - CheckMenuItem(hMenu, IDM_PC9801_86_CB, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_ADPCM)); - CheckMenuItem(hMenu, IDM_PC9801_118, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_118)); - CheckMenuItem(hMenu, IDM_PC9801_86_WSS, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_WSS)); - CheckMenuItem(hMenu, IDM_MATE_X_PCM, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_MATE_X_PCM)); - CheckMenuItem(hMenu, IDM_PC9801_86_118, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_118)); - CheckMenuItem(hMenu, IDM_SPEAKBOARD, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_SPEAKBOARD)); - CheckMenuItem(hMenu, IDM_86SPEAKBOARD, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_86_SPEAKBOARD)); - CheckMenuItem(hMenu, IDM_SPARKBOARD, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_SPARKBOARD)); -#if defined(SUPPORT_SOUND_SB16) - CheckMenuItem(hMenu, IDM_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_SB16)); - CheckMenuItem(hMenu, IDM_PC9801_86_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_SB16)); - CheckMenuItem(hMenu, IDM_WSS_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_WSS_SB16)); - CheckMenuItem(hMenu, IDM_PC9801_86_WSS_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_WSS_SB16)); - CheckMenuItem(hMenu, IDM_PC9801_118_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_118_SB16)); - CheckMenuItem(hMenu, IDM_PC9801_86_118_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_118_SB16)); -#endif // defined(SUPPORT_SOUND_SB16) -#if defined(SUPPORT_PX) - CheckMenuItem(hMenu, IDM_PX1, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PX1)); - CheckMenuItem(hMenu, IDM_PX2, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PX2)); -#endif // defined(SUPPORT_PX) - CheckMenuItem(hMenu, IDM_SOUNDORCHESTRA, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_SOUNDORCHESTRA)); - CheckMenuItem(hMenu, IDM_SOUNDORCHESTRAV, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_SOUNDORCHESTRAV)); - CheckMenuItem(hMenu, IDM_LITTLEORCHESTRAL, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_LITTLEORCHESTRAL)); - CheckMenuItem(hMenu, IDM_MMORCHESTRA, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_MMORCHESTRA)); - CheckMenuItem(hMenu, IDM_AMD98, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_AMD98)); - CheckMenuItem(hMenu, IDM_WAVESTAR, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_WAVESTAR)); - CheckMenuItem(hMenu, IDM_JASTSOUND, MF_BYCOMMAND | MFCHECK(np2oscfg.jastsnd)); - CheckMenuItem(hMenu, IDM_SEEKSND, MF_BYCOMMAND | MFCHECK(np2cfg.MOTOR)); - - // Device-Memory - const UINT16 EXTMEM = np2cfg.EXTMEM; - CheckMenuItem(hMenu, IDM_MEM640, MF_BYCOMMAND | MFCHECK(EXTMEM == 0)); - CheckMenuItem(hMenu, IDM_MEM16, MF_BYCOMMAND | MFCHECK(EXTMEM == 1)); - CheckMenuItem(hMenu, IDM_MEM36, MF_BYCOMMAND | MFCHECK(EXTMEM == 3)); - CheckMenuItem(hMenu, IDM_MEM76, MF_BYCOMMAND | MFCHECK(EXTMEM == 7)); - CheckMenuItem(hMenu, IDM_MEM116, MF_BYCOMMAND | MFCHECK(EXTMEM == 11)); - CheckMenuItem(hMenu, IDM_MEM136, MF_BYCOMMAND | MFCHECK(EXTMEM == 13)); - CheckMenuItem(hMenu, IDM_MEM166, MF_BYCOMMAND | MFCHECK(EXTMEM == 16)); - CheckMenuItem(hMenu, IDM_MEM326, MF_BYCOMMAND | MFCHECK(EXTMEM == 32)); - CheckMenuItem(hMenu, IDM_MEM646, MF_BYCOMMAND | MFCHECK(EXTMEM == 64)); - CheckMenuItem(hMenu, IDM_MEM1206, MF_BYCOMMAND | MFCHECK(EXTMEM == 120)); - CheckMenuItem(hMenu, IDM_MEM2306, MF_BYCOMMAND | MFCHECK(EXTMEM == 230)); - CheckMenuItem(hMenu, IDM_MEM5126, MF_BYCOMMAND | MFCHECK(EXTMEM == 512)); - CheckMenuItem(hMenu, IDM_MEM10246,MF_BYCOMMAND | MFCHECK(EXTMEM == 1024)); -#if !defined(CPUCORE_IA32) - EnableMenuItem(hMenu, IDM_MEM166, MF_GRAYED); - EnableMenuItem(hMenu, IDM_MEM326, MF_GRAYED); - EnableMenuItem(hMenu, IDM_MEM646, MF_GRAYED); - EnableMenuItem(hMenu, IDM_MEM1206,MF_GRAYED); - EnableMenuItem(hMenu, IDM_MEM2306,MF_GRAYED); - EnableMenuItem(hMenu, IDM_MEM5126,MF_GRAYED); - EnableMenuItem(hMenu, IDM_MEM10246,MF_GRAYED); -#endif - - // Device-FPU - const UINT8 fputype = np2cfg.fpu_type; - CheckMenuItem(hMenu, IDM_FPU80, MF_BYCOMMAND | MFCHECK(fputype == FPU_TYPE_SOFTFLOAT)); - CheckMenuItem(hMenu, IDM_FPU64, MF_BYCOMMAND | MFCHECK(fputype == FPU_TYPE_DOSBOX)); - CheckMenuItem(hMenu, IDM_FPU64INT, MF_BYCOMMAND | MFCHECK(fputype == FPU_TYPE_DOSBOX2)); - - // Device - CheckMenuItem(hMenu, IDM_MOUSE, MF_BYCOMMAND | MFCHECK(np2oscfg.MOUSE_SW)); - - // Device-Mouse - CheckMenuItem(hMenu, IDM_MOUSERAW, MF_BYCOMMAND | MFCHECK(np2oscfg.rawmouse)); - CheckMenuItem(hMenu, IDM_MOUSENC, MF_BYCOMMAND | MFCHECK(np2oscfg.mouse_nc)); - CheckMenuItem(hMenu, IDM_MOUSEWHEELCTL, MF_BYCOMMAND | MFCHECK(np2oscfg.usewheel)); - const UINT8 MMUL = (UINT8)np2oscfg.mousemul; - const UINT8 MDIV = (UINT8)np2oscfg.mousediv; - CheckMenuItem(hMenu, IDM_MOUSE30X, MF_BYCOMMAND | MFCHECK(MMUL == 3 && MDIV == 1)); - CheckMenuItem(hMenu, IDM_MOUSE20X, MF_BYCOMMAND | MFCHECK(MMUL == 2 && MDIV == 1)); - CheckMenuItem(hMenu, IDM_MOUSE15X, MF_BYCOMMAND | MFCHECK(MMUL == 3 && MDIV == 2)); - CheckMenuItem(hMenu, IDM_MOUSE10X, MF_BYCOMMAND | MFCHECK(MMUL == 1 && MDIV == 1)); - CheckMenuItem(hMenu, IDM_MOUSED2X, MF_BYCOMMAND | MFCHECK(MMUL == 1 && MDIV == 2)); - CheckMenuItem(hMenu, IDM_MOUSED3X, MF_BYCOMMAND | MFCHECK(MMUL == 1 && MDIV == 3)); - CheckMenuItem(hMenu, IDM_MOUSED4X, MF_BYCOMMAND | MFCHECK(MMUL == 1 && MDIV == 4)); - - // Other-ShortcutKey - const UINT8 shortcut = np2oscfg.shortcut; - CheckMenuItem(hMenu, IDM_ALTENTER, MF_BYCOMMAND | MFCHECK(shortcut & 1)); - CheckMenuItem(hMenu, IDM_ALTF4, MF_BYCOMMAND | MFCHECK(shortcut & 2)); - - CheckMenuItem(hMenu, IDM_SYSKHOOK,MF_BYCOMMAND | MFCHECK(np2oscfg.syskhook)); - - - // Other - bool bLogging = false; -#if defined(SUPPORT_S98) - if (S98_isopened()) - { - bLogging = true; - } -#endif -#if defined(SUPPORT_WAVEREC) - if (sound_isrecording()) - { - bLogging = true; - } -#endif - CheckMenuItem(hMenu, IDM_HF_ENABLE, MF_BYCOMMAND | MFCHECK(hf_enable)); - CheckMenuItem(hMenu, MF_BYCOMMAND | IDM_S98LOGGING, MFCHECK(bLogging)); - const UINT8 DISPCLK = np2oscfg.DISPCLK; - CheckMenuItem(hMenu, IDM_DISPCLOCK, MF_BYCOMMAND | MFCHECK(DISPCLK & 1)); - CheckMenuItem(hMenu, IDM_DISPFRAME, MF_BYCOMMAND | MFCHECK(DISPCLK & 2)); - CheckMenuItem(hMenu, IDM_JOYX, MF_BYCOMMAND | MFCHECK(np2cfg.BTN_MODE)); - CheckMenuItem(hMenu, IDM_RAPID, MF_BYCOMMAND | MFCHECK(np2cfg.BTN_RAPID)); - CheckMenuItem(hMenu, IDM_MSRAPID, MF_BYCOMMAND | MFCHECK(np2cfg.MOUSERAPID)); - CheckMenuItem(hMenu, IDM_SSTP, MF_BYCOMMAND | MFCHECK(np2oscfg.sstp)); - - CheckMenuItem(hMenu, IDM_ITFWORK, MF_BYCOMMAND | MFCHECK(np2cfg.ITF_WORK)); - CheckMenuItem(hMenu, IDM_TIMERFIX, MF_BYCOMMAND | MFCHECK(np2cfg.timerfix)); - CheckMenuItem(hMenu, IDM_SKIP16MEMCHK, MF_BYCOMMAND | MFCHECK(np2cfg.memchkmx != 0)); -#if defined(SUPPORT_FAST_MEMORYCHECK) - CheckMenuItem(hMenu, IDM_FASTMEMCHK, MF_BYCOMMAND | MFCHECK(np2cfg.memcheckspeed != 1)); -#endif -#if defined(SUPPORT_DEBUGSS) - CheckMenuItem(hMenu, IDM_EN_DBSS, MF_BYCOMMAND | MFCHECK(np2cfg.debugss)); -#endif - -#if !defined(SUPPORT_ASYNC_CPU) - EnableMenuItem(hMenu, IDM_ASYNCCPU, MF_GRAYED); -#endif -#if !defined(USE_FPU) - EnableMenuItem(hMenu, IDM_FPU80, MF_GRAYED); - EnableMenuItem(hMenu, IDM_FPU64, MF_GRAYED); - EnableMenuItem(hMenu, IDM_FPU64INT, MF_GRAYED); -#endif -#if !defined(SUPPORT_NET) - EnableMenuItem(hMenu, IDM_NETOPT, MF_GRAYED); -#endif -#if !defined(SUPPORT_WAB) - EnableMenuItem(hMenu, IDM_WABOPT, MF_GRAYED); -#endif -#if !defined(SUPPORT_PCI) - EnableMenuItem(hMenu, IDM_PCIOPT, MF_GRAYED); -#endif -#if !defined(SUPPORT_HOSTDRV) - EnableMenuItem(hMenu, IDM_HOSTDRVOPT, MF_GRAYED); -#endif - -} +/** + * @file menu.cpp + * @brief メニューの宣言およびインターフェイスの定義をします + */ + +#include +#include "resource.h" +#include "menu.h" +#include +#include +#include +#include "misc\tstring.h" +#include "misc\WndProc.h" +#include +#if defined(SUPPORT_WAVEREC) +#include "sound\sound.h" +#endif +#if defined(SUPPORT_S98) +#include "sound\s98.h" +#endif +#include +#include + +extern UINT8 np2userpause; + +/** + * 検索 + * @param[in] hMenu メニュー ハンドル + * @param[in] uID ID + * @param[out] phmenuRet 見つかったメニュー + * @param[out] pnPos 見つかった位置 + * @retval true 見つかった + * @retval false 見つからなかった + */ +bool menu_searchmenu(HMENU hMenu, UINT uID, HMENU *phmenuRet, int *pnPos) +{ + int nCount = GetMenuItemCount(hMenu); + for (int i = 0; i < nCount; i++) + { + MENUITEMINFO mii; + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_SUBMENU; + if (GetMenuItemInfo(hMenu, i, TRUE, &mii)) + { + if (mii.wID == uID) + { + if (phmenuRet) + { + *phmenuRet = hMenu; + } + if (pnPos) + { + *pnPos = i; + } + return true; + } + else if ((mii.hSubMenu) && (menu_searchmenu(mii.hSubMenu, uID, phmenuRet, pnPos))) + { + return true; + } + } + } + return false; +} + +/** + * メニュー追加 + * @param[in] hMenu メニュー ハンドル + * @param[in] nPos 追加する位置 + * @param[in] hmenuAdd 追加するメニュー + * @param[in] bSeparator セパレータを追加する + * @return 追加数 + */ +int menu_addmenu(HMENU hMenu, int nPos, HMENU hmenuAdd, BOOL bSeparator) +{ + if (nPos < 0) + { + nPos = GetMenuItemCount(hMenu); + } + int nCount = GetMenuItemCount(hmenuAdd); + int nAdded = 0; + for (int i = 0; i < nCount; i++) + { + MENUITEMINFO mii; + ZeroMemory(&mii, sizeof(mii)); + + TCHAR szString[128]; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA; + mii.dwTypeData = szString; + mii.cch = _countof(szString); + if (GetMenuItemInfo(hmenuAdd, i, TRUE, &mii)) + { + if (mii.hSubMenu) + { + HMENU hmenuSub = CreatePopupMenu(); + (void)menu_addmenu(hmenuSub, 0, mii.hSubMenu, FALSE); + mii.hSubMenu = hmenuSub; + } + if (bSeparator) + { + bSeparator = FALSE; + InsertMenu(hMenu, nPos + nAdded, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + nAdded++; + } + InsertMenuItem(hMenu, nPos + nAdded, TRUE, &mii); + nAdded++; + } + } + return nAdded; +} + +/** + * メニュー追加 + * @param[in] hMenu メニュー ハンドル + * @param[in] nPos 追加する位置 + * @param[in] uID メニュー ID + * @param[in] bSeparator セパレータを追加する + * @return 追加数 + */ +int menu_addmenures(HMENU hMenu, int nPos, UINT uID, BOOL bSeparator) +{ + int nCount = 0; + HINSTANCE hInstance = CWndProc::FindResourceHandle(MAKEINTRESOURCE(uID), RT_MENU); + HMENU hmenuAdd = LoadMenu(hInstance, MAKEINTRESOURCE(uID)); + if (hmenuAdd) + { + nCount = menu_addmenu(hMenu, nPos, hmenuAdd, bSeparator); + DestroyMenu(hmenuAdd); + } + return nCount; +} + +/** + * メニュー追加 + * @param[in] hMenu メニュー ハンドル + * @param[in] uByID メニュー位置 + * @param[in] uID メニュー ID + * @return 追加数 + */ +static int menu_addmenubyid(HMENU hMenu, UINT uByID, UINT uID) +{ + int nCount = 0; + + HMENU hmenuSub; + int nSubPos; + if (menu_searchmenu(hMenu, uByID, &hmenuSub, &nSubPos)) + { + nCount = menu_addmenures(hmenuSub, nSubPos + 1, uID, FALSE); + } + return nCount; +} + +/** + * メニュー追加 + * @param[in] hMenu メニューのハンドル + * @param[in] uPosition 新しい項目の直前に位置する項目 + * @param[in] uFlags オプション + * @param[in] uIDNewItem 識別子、メニュー、サブメニューのいずれか + * @param[in] lpNewItem メニュー 文字列 + * @return 関数が成功すると、0 以外の値が返ります + */ +static BOOL InsertMenuString(HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, UINT uStringID) +{ + std::tstring rString(LoadTString(uStringID)); + + BOOL bResult = FALSE; + if (!rString.empty()) + { + bResult = InsertMenu(hMenu, uPosition, uFlags, uIDNewItem, rString.c_str()); + } + return bResult; +} + +/** + * メニュー追加 (単純コピー) + * @param[in] popup コピー先 + * @param[in] menubar コピー元 + */ +void menu_addmenubar(HMENU popup, HMENU menubar) +{ + (void)menu_addmenu(popup, 0, menubar, FALSE); +} + + + +// ---- + +/** + * システム メニュー初期化 + * @param[in] hMenu メニュー ハンドル + */ +void sysmenu_initialize(HMENU hMenu) +{ + UINT uPos = 0; + +#if defined(SUPPORT_KEYDISP) + uPos += menu_addmenures(hMenu, uPos, IDR_SYSKEYDISP, FALSE); +#endif +#if defined(SUPPORT_SOFTKBD) + uPos += menu_addmenures(hMenu, uPos, IDR_SYSSOFTKBD, FALSE); +#endif + + uPos += menu_addmenures(hMenu, uPos, IDR_SYS, FALSE); + if (np2oscfg.I286SAVE) + { +#if defined(CPUCORE_IA32) && defined(SUPPORT_MEMDBG32) + uPos += menu_addmenures(hMenu, uPos, IDR_SYSDEBUG32, FALSE); +#endif + uPos += menu_addmenures(hMenu, uPos, IDR_SYSDEBUG, FALSE); + } +} + +/** + * システム メニュー更新 + * @param[in] hMenu メニュー ハンドル + */ +void sysmenu_update(HMENU hMenu) +{ + CheckMenuItem(hMenu, IDM_TOOLWIN, MF_BYCOMMAND | MFCHECK(np2oscfg.toolwin)); + CheckMenuItem(hMenu, IDM_KEYDISP, MF_BYCOMMAND | MFCHECK(np2oscfg.keydisp)); + CheckMenuItem(hMenu, IDM_SNAPENABLE, MF_BYCOMMAND | MFCHECK(np2oscfg.WINSNAP)); + + const UINT8 background = np2oscfg.background ^ 3; + EnableMenuItem(hMenu, IDM_BGSOUND, (background & 1) ? MF_ENABLED : MF_GRAYED); + CheckMenuItem(hMenu, IDM_BACKGROUND, MF_BYCOMMAND | MFCHECK(background & 1)); + CheckMenuItem(hMenu, IDM_BGSOUND, MF_BYCOMMAND | MFCHECK(background & 2)); + + const int scrnmul = scrnmng_getmultiple(); + CheckMenuItem(hMenu, IDM_SCRNMUL4, MF_BYCOMMAND | MFCHECK(scrnmul == 4)); + CheckMenuItem(hMenu, IDM_SCRNMUL6, MF_BYCOMMAND | MFCHECK(scrnmul == 6)); + CheckMenuItem(hMenu, IDM_SCRNMUL8, MF_BYCOMMAND | MFCHECK(scrnmul == 8)); + CheckMenuItem(hMenu, IDM_SCRNMUL10, MF_BYCOMMAND | MFCHECK(scrnmul == 10)); + CheckMenuItem(hMenu, IDM_SCRNMUL12, MF_BYCOMMAND | MFCHECK(scrnmul == 12)); + CheckMenuItem(hMenu, IDM_SCRNMUL16, MF_BYCOMMAND | MFCHECK(scrnmul == 16)); +} + + + +// ---- + +/** + * メニュー初期化 + * @param[in] メニュー ハンドル + */ +void xmenu_initialize(HMENU hMenu) +{ + int nPos = 1; +#if defined(SUPPORT_STATSAVE) + if (np2oscfg.statsave) + { + nPos += menu_addmenures(hMenu, nPos, IDR_STAT, FALSE); + } +#endif + + for (UINT i = 0; i < 4; i++) + { + if (np2cfg.fddequip & (1 << i)) + { + nPos += menu_addmenures(hMenu, nPos, IDR_FDD1MENU + i, FALSE); + } + } + + HMENU hmenuSub = CreatePopupMenu(); + if (hmenuSub) + { + int nSubPos = 0; +#if defined(SUPPORT_IDEIO) + nSubPos += menu_addmenures(hmenuSub, nSubPos, IDR_IDEMENU, FALSE); +#else + nSubPos += menu_addmenures(hmenuSub, nSubPos, IDR_SASIMENU, FALSE); +#endif +#if defined(SUPPORT_SCSI) + nSubPos += menu_addmenures(hmenuSub, nSubPos, IDR_SCSIMENU, TRUE); +#endif + InsertMenuString(hMenu, nPos, MF_BYPOSITION | MF_POPUP, (UINT_PTR)hmenuSub, IDS_HDD); + } + +#if defined(SUPPORT_PX) + (void)menu_addmenubyid(hMenu, IDM_SPARKBOARD, IDR_PXMENU); +#endif + +#ifndef SUPPORT_NET + EnableMenuItem(hMenu, IDM_NETOPT, MF_BYCOMMAND|MFS_GRAYED); +#endif + +#ifndef SUPPORT_CL_GD5430 + EnableMenuItem(hMenu, IDM_WABOPT, MF_BYCOMMAND|MFS_GRAYED); +#endif + +#ifndef SUPPORT_PCI + EnableMenuItem(hMenu, IDM_PCIOPT, MF_BYCOMMAND|MFS_GRAYED); +#endif + + if (np2oscfg.I286SAVE) + { +#if defined(SUPPORT_PC9821) + (void)menu_addmenubyid(hMenu, IDM_MSRAPID, IDR_CPUSAVE32); + (void)menu_addmenubyid(hMenu, IDM_SSTP, IDR_CPUSAVE32); +#else // defined(SUPPORT_PC9821) + (void)menu_addmenubyid(hMenu, IDM_MSRAPID, IDR_CPUSAVE16); + (void)menu_addmenubyid(hMenu, IDM_SSTP, IDR_CPUSAVE16); +#endif // defined(SUPPORT_PC9821) + } + +#if defined(SUPPORT_DEBUGSS) + if (np2cfg.debugss) { + menu_addmenures(hMenu, GetMenuItemCount(hMenu) - 1, IDR_DEBUGSS, FALSE); + } +#endif +} + +/** + * メニュー状態を更新する + * @param[in] hMenu メニュー ハンドル + */ +void xmenu_update(HMENU hMenu) +{ + if (hMenu == NULL) + { + return; + } + + // Emulate + CheckMenuItem(hMenu, IDM_PAUSE, MF_BYCOMMAND | MFCHECK(np2userpause)); + + // Screen + const bool bFullScreen = ((g_scrnmode & SCRNMODE_FULLSCREEN) != 0); + CheckMenuItem(hMenu, IDM_WINDOW, MF_BYCOMMAND | MFCHECK(!bFullScreen)); + CheckMenuItem(hMenu, IDM_FULLSCREEN, MF_BYCOMMAND | MFCHECK(bFullScreen)); + const UINT8 nRotateMode = g_scrnmode & SCRNMODE_ROTATEMASK; + CheckMenuItem(hMenu, IDM_ROLNORMAL, MF_BYCOMMAND | MFCHECK(nRotateMode == 0)); + CheckMenuItem(hMenu, IDM_ROLLEFT, MF_BYCOMMAND | MFCHECK(nRotateMode == SCRNMODE_ROTATELEFT)); + CheckMenuItem(hMenu, IDM_ROLRIGHT, MF_BYCOMMAND | MFCHECK(nRotateMode == SCRNMODE_ROTATERIGHT)); + CheckMenuItem(hMenu, IDM_DISPSYNC, MF_BYCOMMAND | MFCHECK(np2cfg.DISPSYNC)); + CheckMenuItem(hMenu, IDM_RASTER, MF_BYCOMMAND | MFCHECK(np2cfg.RASTER)); + CheckMenuItem(hMenu, IDM_NOWAIT, MF_BYCOMMAND | MFCHECK(np2oscfg.NOWAIT)); + CheckMenuItem(hMenu, IDM_CPUSTABILIZER, MF_BYCOMMAND | MFCHECK(np2oscfg.cpustabf != 0)); +#if defined(SUPPORT_ASYNC_CPU) + CheckMenuItem(hMenu, IDM_ASYNCCPU, MF_BYCOMMAND | MFCHECK(np2cfg.asynccpu != 0)); +#endif + const UINT8 DRAW_SKIP = CheckMenuItem(hMenu, IDM_AUTOFPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 0)); + CheckMenuItem(hMenu, IDM_60FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 1)); + CheckMenuItem(hMenu, IDM_30FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 2)); + CheckMenuItem(hMenu, IDM_20FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 3)); + CheckMenuItem(hMenu, IDM_15FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 4)); +DRAW_SKIP; + CheckMenuItem(hMenu, IDM_AUTOFPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 0)); + CheckMenuItem(hMenu, IDM_60FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 1)); + CheckMenuItem(hMenu, IDM_30FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 2)); + CheckMenuItem(hMenu, IDM_20FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 3)); + CheckMenuItem(hMenu, IDM_15FPS, MF_BYCOMMAND | MFCHECK(DRAW_SKIP == 4)); +#if defined(SUPPORT_VIDEOFILTER) + CheckMenuItem(hMenu, IDM_VF1EN, MF_BYCOMMAND | MFCHECK(np2cfg.vf1_enable)); + CheckMenuItem(hMenu, IDM_VF1P0, MF_BYCOMMAND | MFCHECK(np2cfg.vf1_pno == 0)); + CheckMenuItem(hMenu, IDM_VF1P1, MF_BYCOMMAND | MFCHECK(np2cfg.vf1_pno == 1)); + CheckMenuItem(hMenu, IDM_VF1P2, MF_BYCOMMAND | MFCHECK(np2cfg.vf1_pno == 2)); + CheckMenuItem(hMenu, IDM_VF1BO, MF_BYCOMMAND | MFCHECK(np2cfg.vf1_bmponly)); +#endif + + // Device-Keyboard + const UINT8 KEY_MODE = np2cfg.KEY_MODE; + CheckMenuItem(hMenu, IDM_KEY, MF_BYCOMMAND | MFCHECK(KEY_MODE == 0)); + CheckMenuItem(hMenu, IDM_JOY1, MF_BYCOMMAND | MFCHECK(KEY_MODE == 1)); + CheckMenuItem(hMenu, IDM_JOY2, MF_BYCOMMAND | MFCHECK(KEY_MODE == 2)); + const UINT8 XSHIFT = np2cfg.XSHIFT; + CheckMenuItem(hMenu, IDM_XSHIFT, MF_BYCOMMAND | MFCHECK(XSHIFT & 1)); + CheckMenuItem(hMenu, IDM_XCTRL, MF_BYCOMMAND | MFCHECK(XSHIFT & 2)); + CheckMenuItem(hMenu, IDM_XGRPH, MF_BYCOMMAND | MFCHECK(XSHIFT & 4)); + const UINT8 F12COPY = np2oscfg.F12COPY; + CheckMenuItem(hMenu, IDM_F12MOUSE, MF_BYCOMMAND | MFCHECK(F12COPY == 0)); + CheckMenuItem(hMenu, IDM_F12COPY, MF_BYCOMMAND | MFCHECK(F12COPY == 1)); + CheckMenuItem(hMenu, IDM_F12STOP, MF_BYCOMMAND | MFCHECK(F12COPY == 2)); + CheckMenuItem(hMenu, IDM_F12EQU, MF_BYCOMMAND | MFCHECK(F12COPY == 3)); + CheckMenuItem(hMenu, IDM_F12COMMA, MF_BYCOMMAND | MFCHECK(F12COPY == 4)); + CheckMenuItem(hMenu, IDM_USERKEY1, MF_BYCOMMAND | MFCHECK(F12COPY == 5)); + CheckMenuItem(hMenu, IDM_USERKEY2, MF_BYCOMMAND | MFCHECK(F12COPY == 6)); + CheckMenuItem(hMenu, IDM_F12NOWAIT, MF_BYCOMMAND | MFCHECK(F12COPY == 7)); + CheckMenuItem(hMenu, IDM_F12NOWAIT2, MF_BYCOMMAND | MFCHECK(F12COPY == 8)); + if(!np2oscfg.I286SAVE){ + DeleteMenu(hMenu, IDM_F12WABRELAY, MF_BYCOMMAND); + }else{ + CheckMenuItem(hMenu, IDM_F12WABRELAY, MF_BYCOMMAND | MFCHECK(F12COPY == 9)); + } + CheckMenuItem(hMenu, IDM_USENUMLOCK, MF_BYCOMMAND | MFCHECK(np2oscfg.USENUMLOCK)); + CheckMenuItem(hMenu, IDM_SWAPPAGEUPDOWN, MF_BYCOMMAND | MFCHECK(np2oscfg.xrollkey)); + + // Device-Sound + const UINT8 BEEP_VOL = np2cfg.BEEP_VOL; + CheckMenuItem(hMenu, IDM_BEEPOFF, MF_BYCOMMAND | MFCHECK(BEEP_VOL == 0)); + CheckMenuItem(hMenu, IDM_BEEPLOW, MF_BYCOMMAND | MFCHECK(BEEP_VOL == 1)); + CheckMenuItem(hMenu, IDM_BEEPMID, MF_BYCOMMAND | MFCHECK(BEEP_VOL == 2)); + CheckMenuItem(hMenu, IDM_BEEPHIGH, MF_BYCOMMAND | MFCHECK(BEEP_VOL == 3)); + const UINT8 SOUND_SW = np2cfg.SOUND_SW; + CheckMenuItem(hMenu, IDM_NOSOUND, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_NONE)); + CheckMenuItem(hMenu, IDM_PC9801_14, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_14)); + CheckMenuItem(hMenu, IDM_PC9801_26K, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_26K)); + CheckMenuItem(hMenu, IDM_PC9801_86, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86)); + CheckMenuItem(hMenu, IDM_PC9801_26_86, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_26K)); + CheckMenuItem(hMenu, IDM_PC9801_86_CB, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_ADPCM)); + CheckMenuItem(hMenu, IDM_PC9801_118, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_118)); + CheckMenuItem(hMenu, IDM_PC9801_86_WSS, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_WSS)); + CheckMenuItem(hMenu, IDM_MATE_X_PCM, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_MATE_X_PCM)); + CheckMenuItem(hMenu, IDM_PC9801_86_118, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_118)); + CheckMenuItem(hMenu, IDM_SPEAKBOARD, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_SPEAKBOARD)); + CheckMenuItem(hMenu, IDM_86SPEAKBOARD, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_86_SPEAKBOARD)); + CheckMenuItem(hMenu, IDM_SPARKBOARD, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_SPARKBOARD)); +#if defined(SUPPORT_SOUND_SB16) + CheckMenuItem(hMenu, IDM_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_SB16)); + CheckMenuItem(hMenu, IDM_PC9801_86_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_SB16)); + CheckMenuItem(hMenu, IDM_WSS_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_WSS_SB16)); + CheckMenuItem(hMenu, IDM_PC9801_86_WSS_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_WSS_SB16)); + CheckMenuItem(hMenu, IDM_PC9801_118_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_118_SB16)); + CheckMenuItem(hMenu, IDM_PC9801_86_118_SB16, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PC_9801_86_118_SB16)); +#endif // defined(SUPPORT_SOUND_SB16) +#if defined(SUPPORT_PX) + CheckMenuItem(hMenu, IDM_PX1, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PX1)); + CheckMenuItem(hMenu, IDM_PX2, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_PX2)); +#endif // defined(SUPPORT_PX) + CheckMenuItem(hMenu, IDM_SOUNDORCHESTRA, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_SOUNDORCHESTRA)); + CheckMenuItem(hMenu, IDM_SOUNDORCHESTRAV, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_SOUNDORCHESTRAV)); + CheckMenuItem(hMenu, IDM_LITTLEORCHESTRAL, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_LITTLEORCHESTRAL)); + CheckMenuItem(hMenu, IDM_MMORCHESTRA, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_MMORCHESTRA)); + CheckMenuItem(hMenu, IDM_AMD98, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_AMD98)); + CheckMenuItem(hMenu, IDM_WAVESTAR, MF_BYCOMMAND | MFCHECK(SOUND_SW == SOUNDID_WAVESTAR)); + CheckMenuItem(hMenu, IDM_JASTSOUND, MF_BYCOMMAND | MFCHECK(np2oscfg.jastsnd)); + CheckMenuItem(hMenu, IDM_SEEKSND, MF_BYCOMMAND | MFCHECK(np2cfg.MOTOR)); + + // Device-Memory + const UINT16 EXTMEM = np2cfg.EXTMEM; + CheckMenuItem(hMenu, IDM_MEM640, MF_BYCOMMAND | MFCHECK(EXTMEM == 0)); + CheckMenuItem(hMenu, IDM_MEM16, MF_BYCOMMAND | MFCHECK(EXTMEM == 1)); + CheckMenuItem(hMenu, IDM_MEM36, MF_BYCOMMAND | MFCHECK(EXTMEM == 3)); + CheckMenuItem(hMenu, IDM_MEM76, MF_BYCOMMAND | MFCHECK(EXTMEM == 7)); + CheckMenuItem(hMenu, IDM_MEM116, MF_BYCOMMAND | MFCHECK(EXTMEM == 11)); + CheckMenuItem(hMenu, IDM_MEM136, MF_BYCOMMAND | MFCHECK(EXTMEM == 13)); + CheckMenuItem(hMenu, IDM_MEM166, MF_BYCOMMAND | MFCHECK(EXTMEM == 16)); + CheckMenuItem(hMenu, IDM_MEM326, MF_BYCOMMAND | MFCHECK(EXTMEM == 32)); + CheckMenuItem(hMenu, IDM_MEM646, MF_BYCOMMAND | MFCHECK(EXTMEM == 64)); + CheckMenuItem(hMenu, IDM_MEM1206, MF_BYCOMMAND | MFCHECK(EXTMEM == 120)); + CheckMenuItem(hMenu, IDM_MEM2306, MF_BYCOMMAND | MFCHECK(EXTMEM == 230)); + CheckMenuItem(hMenu, IDM_MEM5126, MF_BYCOMMAND | MFCHECK(EXTMEM == 512)); + CheckMenuItem(hMenu, IDM_MEM10246,MF_BYCOMMAND | MFCHECK(EXTMEM == 1024)); +#if !defined(CPUCORE_IA32) + EnableMenuItem(hMenu, IDM_MEM166, MF_GRAYED); + EnableMenuItem(hMenu, IDM_MEM326, MF_GRAYED); + EnableMenuItem(hMenu, IDM_MEM646, MF_GRAYED); + EnableMenuItem(hMenu, IDM_MEM1206,MF_GRAYED); + EnableMenuItem(hMenu, IDM_MEM2306,MF_GRAYED); + EnableMenuItem(hMenu, IDM_MEM5126,MF_GRAYED); + EnableMenuItem(hMenu, IDM_MEM10246,MF_GRAYED); +#endif + + // Device-FPU + const UINT8 fputype = np2cfg.fpu_type; + CheckMenuItem(hMenu, IDM_FPU80, MF_BYCOMMAND | MFCHECK(fputype == FPU_TYPE_SOFTFLOAT)); + CheckMenuItem(hMenu, IDM_FPU64, MF_BYCOMMAND | MFCHECK(fputype == FPU_TYPE_DOSBOX)); + CheckMenuItem(hMenu, IDM_FPU64INT, MF_BYCOMMAND | MFCHECK(fputype == FPU_TYPE_DOSBOX2)); + + // Device + CheckMenuItem(hMenu, IDM_MOUSE, MF_BYCOMMAND | MFCHECK(np2oscfg.MOUSE_SW)); + + // Device-Mouse + CheckMenuItem(hMenu, IDM_MOUSERAW, MF_BYCOMMAND | MFCHECK(np2oscfg.rawmouse)); + CheckMenuItem(hMenu, IDM_MOUSENC, MF_BYCOMMAND | MFCHECK(np2oscfg.mouse_nc)); + CheckMenuItem(hMenu, IDM_MOUSEWHEELCTL, MF_BYCOMMAND | MFCHECK(np2oscfg.usewheel)); + const UINT8 MMUL = (UINT8)np2oscfg.mousemul; + const UINT8 MDIV = (UINT8)np2oscfg.mousediv; + CheckMenuItem(hMenu, IDM_MOUSE30X, MF_BYCOMMAND | MFCHECK(MMUL == 3 && MDIV == 1)); + CheckMenuItem(hMenu, IDM_MOUSE20X, MF_BYCOMMAND | MFCHECK(MMUL == 2 && MDIV == 1)); + CheckMenuItem(hMenu, IDM_MOUSE15X, MF_BYCOMMAND | MFCHECK(MMUL == 3 && MDIV == 2)); + CheckMenuItem(hMenu, IDM_MOUSE10X, MF_BYCOMMAND | MFCHECK(MMUL == 1 && MDIV == 1)); + CheckMenuItem(hMenu, IDM_MOUSED2X, MF_BYCOMMAND | MFCHECK(MMUL == 1 && MDIV == 2)); + CheckMenuItem(hMenu, IDM_MOUSED3X, MF_BYCOMMAND | MFCHECK(MMUL == 1 && MDIV == 3)); + CheckMenuItem(hMenu, IDM_MOUSED4X, MF_BYCOMMAND | MFCHECK(MMUL == 1 && MDIV == 4)); + + // Other-ShortcutKey + const UINT8 shortcut = np2oscfg.shortcut; + CheckMenuItem(hMenu, IDM_ALTENTER, MF_BYCOMMAND | MFCHECK(shortcut & 1)); + CheckMenuItem(hMenu, IDM_ALTF4, MF_BYCOMMAND | MFCHECK(shortcut & 2)); + + CheckMenuItem(hMenu, IDM_SYSKHOOK,MF_BYCOMMAND | MFCHECK(np2oscfg.syskhook)); + + + // Other + bool bLogging = false; +#if defined(SUPPORT_S98) + if (S98_isopened()) + { + bLogging = true; + } +#endif +#if defined(SUPPORT_WAVEREC) + if (sound_isrecording()) + { + bLogging = true; + } +#endif + CheckMenuItem(hMenu, IDM_HF_ENABLE, MF_BYCOMMAND | MFCHECK(hf_enable)); + CheckMenuItem(hMenu, MF_BYCOMMAND | IDM_S98LOGGING, MFCHECK(bLogging)); + const UINT8 DISPCLK = np2oscfg.DISPCLK; + CheckMenuItem(hMenu, IDM_DISPCLOCK, MF_BYCOMMAND | MFCHECK(DISPCLK & 1)); + CheckMenuItem(hMenu, IDM_DISPFRAME, MF_BYCOMMAND | MFCHECK(DISPCLK & 2)); + CheckMenuItem(hMenu, IDM_JOYX, MF_BYCOMMAND | MFCHECK(np2cfg.BTN_MODE)); + CheckMenuItem(hMenu, IDM_RAPID, MF_BYCOMMAND | MFCHECK(np2cfg.BTN_RAPID)); + CheckMenuItem(hMenu, IDM_MSRAPID, MF_BYCOMMAND | MFCHECK(np2cfg.MOUSERAPID)); + CheckMenuItem(hMenu, IDM_SSTP, MF_BYCOMMAND | MFCHECK(np2oscfg.sstp)); + + CheckMenuItem(hMenu, IDM_ITFWORK, MF_BYCOMMAND | MFCHECK(np2cfg.ITF_WORK)); + CheckMenuItem(hMenu, IDM_TIMERFIX, MF_BYCOMMAND | MFCHECK(np2cfg.timerfix)); + CheckMenuItem(hMenu, IDM_SKIP16MEMCHK, MF_BYCOMMAND | MFCHECK(np2cfg.memchkmx != 0)); +#if defined(SUPPORT_FAST_MEMORYCHECK) + CheckMenuItem(hMenu, IDM_FASTMEMCHK, MF_BYCOMMAND | MFCHECK(np2cfg.memcheckspeed != 1)); +#endif +#if defined(SUPPORT_DEBUGSS) + CheckMenuItem(hMenu, IDM_EN_DBSS, MF_BYCOMMAND | MFCHECK(np2cfg.debugss)); +#endif + +#if !defined(SUPPORT_ASYNC_CPU) + EnableMenuItem(hMenu, IDM_ASYNCCPU, MF_GRAYED); +#endif +#if !defined(USE_FPU) + EnableMenuItem(hMenu, IDM_FPU80, MF_GRAYED); + EnableMenuItem(hMenu, IDM_FPU64, MF_GRAYED); + EnableMenuItem(hMenu, IDM_FPU64INT, MF_GRAYED); +#endif +#if !defined(SUPPORT_NET) + EnableMenuItem(hMenu, IDM_NETOPT, MF_GRAYED); +#endif +#if !defined(SUPPORT_WAB) + EnableMenuItem(hMenu, IDM_WABOPT, MF_GRAYED); +#endif +#if !defined(SUPPORT_PCI) + EnableMenuItem(hMenu, IDM_PCIOPT, MF_GRAYED); +#endif +#if !defined(SUPPORT_HOSTDRV) + EnableMenuItem(hMenu, IDM_HOSTDRVOPT, MF_GRAYED); +#endif + +} diff --git a/windows/menu.h b/windows/menu.h old mode 100755 new mode 100644 index 5aad339e..fc6db74e --- a/windows/menu.h +++ b/windows/menu.h @@ -1,19 +1,19 @@ -/** - * @file menu.h - * @brief メニューの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#define MFCHECK(a) ((a) ? MF_CHECKED : MF_UNCHECKED) - -bool menu_searchmenu(HMENU hMenu, UINT uID, HMENU *phmenuRet, int *pnPos); -int menu_addmenu(HMENU hMenu, int nPos, HMENU hmenuAdd, BOOL bSeparator); -int menu_addmenures(HMENU hMenu, int nPos, UINT uID, BOOL bSeparator); -void menu_addmenubar(HMENU popup, HMENU menubar); - -void sysmenu_initialize(HMENU hMenu); -void sysmenu_update(HMENU hMenu); - -void xmenu_initialize(HMENU hMenu); -void xmenu_update(HMENU hMenu); +/** + * @file menu.h + * @brief メニューの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#define MFCHECK(a) ((a) ? MF_CHECKED : MF_UNCHECKED) + +bool menu_searchmenu(HMENU hMenu, UINT uID, HMENU *phmenuRet, int *pnPos); +int menu_addmenu(HMENU hMenu, int nPos, HMENU hmenuAdd, BOOL bSeparator); +int menu_addmenures(HMENU hMenu, int nPos, UINT uID, BOOL bSeparator); +void menu_addmenubar(HMENU popup, HMENU menubar); + +void sysmenu_initialize(HMENU hMenu); +void sysmenu_update(HMENU hMenu); + +void xmenu_initialize(HMENU hMenu); +void xmenu_update(HMENU hMenu); diff --git a/windows/misc/DlgProc.cpp b/windows/misc/DlgProc.cpp old mode 100755 new mode 100644 index f90d2d50..70c17aa2 --- a/windows/misc/DlgProc.cpp +++ b/windows/misc/DlgProc.cpp @@ -1,225 +1,225 @@ -/** - * @file DlgProc.cpp - * @brief ダイアログ クラスの動作の定義を行います - */ - -#include -#include "DlgProc.h" - -BOOL winloc_GetWindowRect(HWND hwnd, LPRECT lpRect); - -/** - * コンストラクタ - */ -CDlgProc::CDlgProc() - : m_lpszTemplateName(NULL) - , m_hwndParent(NULL) -{ -} - -/** - * コンストラクタ - * @param[in] nIDTemplate ダイアログ ボックス テンプレートのリソース id 番号を指定します - * @param[in] hwndParent 親ウィンドウ - */ -CDlgProc::CDlgProc(UINT nIDTemplate, HWND hwndParent) - : m_lpszTemplateName(MAKEINTRESOURCE(nIDTemplate)) - , m_hwndParent(hwndParent) -{ -} - -/** - * デストラクタ - */ -CDlgProc::~CDlgProc() -{ -} - -/** - * モーダル - * @return ダイアログ ボックスを閉じるために使用される、CDialog::EndDialog のメンバー関数に渡された nResult のパラメーター値を指定する int の値 - */ -INT_PTR CDlgProc::DoModal() -{ - HookWindowCreate(this); - - HINSTANCE hInstance = FindResourceHandle(m_lpszTemplateName, RT_DIALOG); - const INT_PTR nRet = ::DialogBox(hInstance, m_lpszTemplateName, m_hwndParent, DlgProc); - - if (!UnhookWindowCreate()) - { - PostNcDestroy(); - } - return nRet; -} - -/** - * ダイアログ プロシージャ - * @param[in] hWnd ウィンドウ ハンドル - * @param[in] message 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -#if defined(_WIN64) -INT_PTR CALLBACK CDlgProc::DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -#else // defined(_WIN64) -BOOL CALLBACK CDlgProc::DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -#endif // defined(_WIN64) -{ - if (message == WM_INITDIALOG) - { - CDlgProc* pDlg = static_cast(FromHandlePermanent(hWnd)); - if (pDlg != NULL) - { - return pDlg->OnInitDialog(); - } - else - { - return TRUE; - } - } - return FALSE; -} - -/** - * CDlgProc オブジェクトの Windows プロシージャ - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT CDlgProc::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - if (nMsg == WM_COMMAND) - { - switch (LOWORD(wParam)) - { - case IDOK: - OnOK(); - return TRUE; - - case IDCANCEL: - OnCancel(); - return TRUE; - } - }else if(nMsg == WM_INITDIALOG){ - RECT rect, rect2, rectparent; - GetWindowRect(&rect); - if(!winloc_GetWindowRect(m_hWnd,&rect2)){ - rect2 = rect; - } - - CWndBase wndParent = GetParent(); - wndParent.GetWindowRect(&rectparent); - - POINT pt; - pt.x = rectparent.left - (rect2.left - rect.left);//((rectparent.right - rectparent.left) - (rect.right - rect.left)) / 2; - pt.y = rectparent.top - (rect2.top - rect.top);//((rectparent.bottom - rectparent.top) - (rect.bottom - rect.top)) / 2; - MoveWindow(pt.x, pt.y, (rect.right - rect.left), (rect.bottom - rect.top), TRUE); - } - return CWndProc::WindowProc(nMsg, wParam, lParam); -} - -/** - * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます - * @retval TRUE 最初のコントロールに入力フォーカスを設定 - * @retval FALSE 既に設定済 - */ -BOOL CDlgProc::OnInitDialog() -{ - return TRUE; -} - -/** - * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます - */ -void CDlgProc::OnOK() -{ - EndDialog(IDOK); -} - -/** - * フレームワークは、ユーザーが [キャンセル] をクリックするか、モーダルまたはモードレス ダイアログ ボックスの Esc キーを押したときにこのメソッドを呼び出します - */ -void CDlgProc::OnCancel() -{ - EndDialog(IDCANCEL); -} - - - -/** - * コンストラクタ - * @param[in] bOpenFileDialog 作成するダイアログ ボックスを指定するパラメーター - * @param[in] lpszDefExt 既定のファイル名の拡張子です - * @param[in] lpszFileName ボックスに表示される初期ファイル名 - * @param[in] dwFlags フラグ - * @param[in] lpszFilter フィルター - * @param[in] hParentWnd 親ウィンドウ - */ -CFileDlg::CFileDlg(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, HWND hParentWnd) - : m_bOpenFileDialog(bOpenFileDialog) -{ - ZeroMemory(&m_ofn, sizeof(m_ofn)); - m_szFileName[0] = '\0'; - m_szFileTitle[0] = '\0'; - - m_ofn.lStructSize = sizeof(m_ofn); - m_ofn.lpstrFile = m_szFileName; - m_ofn.nMaxFile = _countof(m_szFileName); - m_ofn.lpstrDefExt = lpszDefExt; - m_ofn.lpstrFileTitle = m_szFileTitle; - m_ofn.nMaxFileTitle = _countof(m_szFileTitle); - m_ofn.Flags = dwFlags; - m_ofn.hwndOwner = hParentWnd; - - // setup initial file name - if (lpszFileName != NULL) - { - lstrcpyn(m_szFileName, lpszFileName, _countof(m_szFileName)); - } - - // Translate filter into commdlg format (lots of \0) - if (lpszFilter != NULL) - { - m_strFilter = lpszFilter; - for (std::tstring::iterator it = m_strFilter.begin(); it != m_strFilter.end(); ++it) - { -#if !defined(_UNICODE) - if (IsDBCSLeadByte(static_cast(*it))) - { - ++it; - if (it == m_strFilter.end()) - { - break; - } - continue; - } -#endif // !defined(_UNICODE) - if (*it == '|') - { - *it = '\0'; - } - } - m_ofn.lpstrFilter = m_strFilter.c_str(); - } -} - -/** - * モーダル - * @return リザルト コード - */ -int CFileDlg::DoModal() -{ - int nResult; - if (m_bOpenFileDialog) - { - nResult = ::GetOpenFileName(&m_ofn); - } - else - { - nResult = ::GetSaveFileName(&m_ofn); - } - return nResult; -} +/** + * @file DlgProc.cpp + * @brief ダイアログ クラスの動作の定義を行います + */ + +#include +#include "DlgProc.h" + +BOOL winloc_GetWindowRect(HWND hwnd, LPRECT lpRect); + +/** + * コンストラクタ + */ +CDlgProc::CDlgProc() + : m_lpszTemplateName(NULL) + , m_hwndParent(NULL) +{ +} + +/** + * コンストラクタ + * @param[in] nIDTemplate ダイアログ ボックス テンプレートのリソース id 番号を指定します + * @param[in] hwndParent 親ウィンドウ + */ +CDlgProc::CDlgProc(UINT nIDTemplate, HWND hwndParent) + : m_lpszTemplateName(MAKEINTRESOURCE(nIDTemplate)) + , m_hwndParent(hwndParent) +{ +} + +/** + * デストラクタ + */ +CDlgProc::~CDlgProc() +{ +} + +/** + * モーダル + * @return ダイアログ ボックスを閉じるために使用される、CDialog::EndDialog のメンバー関数に渡された nResult のパラメーター値を指定する int の値 + */ +INT_PTR CDlgProc::DoModal() +{ + HookWindowCreate(this); + + HINSTANCE hInstance = FindResourceHandle(m_lpszTemplateName, RT_DIALOG); + const INT_PTR nRet = ::DialogBox(hInstance, m_lpszTemplateName, m_hwndParent, DlgProc); + + if (!UnhookWindowCreate()) + { + PostNcDestroy(); + } + return nRet; +} + +/** + * ダイアログ プロシージャ + * @param[in] hWnd ウィンドウ ハンドル + * @param[in] message 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +#if defined(_WIN64) +INT_PTR CALLBACK CDlgProc::DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +#else // defined(_WIN64) +BOOL CALLBACK CDlgProc::DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +#endif // defined(_WIN64) +{ + if (message == WM_INITDIALOG) + { + CDlgProc* pDlg = static_cast(FromHandlePermanent(hWnd)); + if (pDlg != NULL) + { + return pDlg->OnInitDialog(); + } + else + { + return TRUE; + } + } + return FALSE; +} + +/** + * CDlgProc オブジェクトの Windows プロシージャ + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CDlgProc::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + if (nMsg == WM_COMMAND) + { + switch (LOWORD(wParam)) + { + case IDOK: + OnOK(); + return TRUE; + + case IDCANCEL: + OnCancel(); + return TRUE; + } + }else if(nMsg == WM_INITDIALOG){ + RECT rect, rect2, rectparent; + GetWindowRect(&rect); + if(!winloc_GetWindowRect(m_hWnd,&rect2)){ + rect2 = rect; + } + + CWndBase wndParent = GetParent(); + wndParent.GetWindowRect(&rectparent); + + POINT pt; + pt.x = rectparent.left - (rect2.left - rect.left);//((rectparent.right - rectparent.left) - (rect.right - rect.left)) / 2; + pt.y = rectparent.top - (rect2.top - rect.top);//((rectparent.bottom - rectparent.top) - (rect.bottom - rect.top)) / 2; + MoveWindow(pt.x, pt.y, (rect.right - rect.left), (rect.bottom - rect.top), TRUE); + } + return CWndProc::WindowProc(nMsg, wParam, lParam); +} + +/** + * このメソッドは WM_INITDIALOG のメッセージに応答して呼び出されます + * @retval TRUE 最初のコントロールに入力フォーカスを設定 + * @retval FALSE 既に設定済 + */ +BOOL CDlgProc::OnInitDialog() +{ + return TRUE; +} + +/** + * ユーザーが OK のボタン (IDOK ID がのボタン) をクリックすると呼び出されます + */ +void CDlgProc::OnOK() +{ + EndDialog(IDOK); +} + +/** + * フレームワークは、ユーザーが [キャンセル] をクリックするか、モーダルまたはモードレス ダイアログ ボックスの Esc キーを押したときにこのメソッドを呼び出します + */ +void CDlgProc::OnCancel() +{ + EndDialog(IDCANCEL); +} + + + +/** + * コンストラクタ + * @param[in] bOpenFileDialog 作成するダイアログ ボックスを指定するパラメーター + * @param[in] lpszDefExt 既定のファイル名の拡張子です + * @param[in] lpszFileName ボックスに表示される初期ファイル名 + * @param[in] dwFlags フラグ + * @param[in] lpszFilter フィルター + * @param[in] hParentWnd 親ウィンドウ + */ +CFileDlg::CFileDlg(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, HWND hParentWnd) + : m_bOpenFileDialog(bOpenFileDialog) +{ + ZeroMemory(&m_ofn, sizeof(m_ofn)); + m_szFileName[0] = '\0'; + m_szFileTitle[0] = '\0'; + + m_ofn.lStructSize = sizeof(m_ofn); + m_ofn.lpstrFile = m_szFileName; + m_ofn.nMaxFile = _countof(m_szFileName); + m_ofn.lpstrDefExt = lpszDefExt; + m_ofn.lpstrFileTitle = m_szFileTitle; + m_ofn.nMaxFileTitle = _countof(m_szFileTitle); + m_ofn.Flags = dwFlags; + m_ofn.hwndOwner = hParentWnd; + + // setup initial file name + if (lpszFileName != NULL) + { + lstrcpyn(m_szFileName, lpszFileName, _countof(m_szFileName)); + } + + // Translate filter into commdlg format (lots of \0) + if (lpszFilter != NULL) + { + m_strFilter = lpszFilter; + for (std::tstring::iterator it = m_strFilter.begin(); it != m_strFilter.end(); ++it) + { +#if !defined(_UNICODE) + if (IsDBCSLeadByte(static_cast(*it))) + { + ++it; + if (it == m_strFilter.end()) + { + break; + } + continue; + } +#endif // !defined(_UNICODE) + if (*it == '|') + { + *it = '\0'; + } + } + m_ofn.lpstrFilter = m_strFilter.c_str(); + } +} + +/** + * モーダル + * @return リザルト コード + */ +int CFileDlg::DoModal() +{ + int nResult; + if (m_bOpenFileDialog) + { + nResult = ::GetOpenFileName(&m_ofn); + } + else + { + nResult = ::GetSaveFileName(&m_ofn); + } + return nResult; +} diff --git a/windows/misc/DlgProc.h b/windows/misc/DlgProc.h old mode 100755 new mode 100644 index 8f49c86f..a94b3799 --- a/windows/misc/DlgProc.h +++ b/windows/misc/DlgProc.h @@ -1,236 +1,236 @@ -/** - * @file DlgProc.h - * @brief ダイアログ クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include -#include - -/** - * @brief ダイアログ クラス - */ -class CDlgProc : public CWndProc -{ -public: - CDlgProc(); - CDlgProc(UINT nIDTemplate, HWND hwndParent = NULL); - virtual ~CDlgProc(); - virtual INT_PTR DoModal(); - virtual BOOL OnInitDialog(); - - /** - * モーダル ダイアログ ボックスを終了する - * @param[in] nResult DoModalの呼び出し元に返す値 - */ - void EndDialog(int nResult) - { - ::EndDialog(m_hWnd, nResult); - } - -protected: - LPCTSTR m_lpszTemplateName; //!< テンプレート名 - HWND m_hwndParent; //!< 親ウィンドウ - - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - virtual void OnOK(); - virtual void OnCancel(); - -#if defined(_WIN64) - static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -#else // defined(_WIN64) - static BOOL CALLBACK DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -#endif // defined(_WIN64) -}; - - -/** - * @brief コンボ ボックス - */ -class CComboBoxProc : public CWndProc -{ -public: - /** - * コンボ ボックスのリスト ボックスに文字列を追加します - * @param[in] lpszString 追加された null で終わる文字列へのポインター - * @return 文字列が挿入された位置を示すインデックス - */ - int AddString(LPCTSTR lpszString) - { - return static_cast(::SendMessage(m_hWnd, CB_ADDSTRING, 0, reinterpret_cast(lpszString))); - } - - /** - * コンボ ボックスのリスト ボックス部分の項目数を取得するには、このメンバー関数を呼び出します - * @return 項目の数 - */ - int GetCount() const - { - return static_cast(::SendMessage(m_hWnd, CB_GETCOUNT, 0, 0)); - } - - /** - * コンボ ボックスのどの項目が選択されたかを判定するためにこのメンバー関数を呼び出します - * @return コンボ ボックスのリスト ボックスで現在選択されている項目のインデックス - */ - int GetCurSel() const - { - return static_cast(::SendMessage(m_hWnd, CB_GETCURSEL, 0, 0)); - } - - /** - * 指定したコンボ ボックスの項目に関連付けられたアプリケーションに用意された 32 ビット値を取得します - * @param[in] nIndex コンボ ボックスのリスト ボックスの項目のインデックス - * @return 32 ビット値 - */ - DWORD_PTR GetItemData(int nIndex) const - { - return static_cast(::SendMessage(m_hWnd, CB_GETITEMDATA, static_cast(nIndex), 0)); - } - - /** - * コンボ ボックスのリスト ボックスで指定されているプレフィックスを含む最初の文字列を検索します - * @param[in] nStartAfter 検索する最初の項目の前の項目のインデックス - * @param[in] lpszString 検索する文字列 - * @return インデックス - */ - int FindString(int nStartAfter, LPCTSTR lpszString) const - { - return static_cast(::SendMessage(m_hWnd, CB_FINDSTRING, nStartAfter, reinterpret_cast(lpszString))); - } - - /** - * コンボ ボックスのリスト ボックスで指定されている最初の文字列を検索します - * @param[in] nStartAfter 検索する最初の項目の前の項目のインデックス - * @param[in] lpszString 検索する文字列 - * @return インデックス - */ - int FindStringExact(int nStartAfter, LPCTSTR lpszString) const - { - return static_cast(::SendMessage(m_hWnd, CB_FINDSTRINGEXACT, nStartAfter, reinterpret_cast(lpszString))); - } - - /** - * コンボ ボックスのリスト ボックスに文字列を追加します - * @param[in] nIndex 文字列を受け取るリスト ボックスの位置 - * @param[in] lpszString 追加された null で終わる文字列へのポインター - * @return 文字列が挿入された位置を示すインデックス - */ - int InsertString(int nIndex, LPCTSTR lpszString) - { - return static_cast(::SendMessage(m_hWnd, CB_INSERTSTRING, static_cast(nIndex), reinterpret_cast(lpszString))); - } - - /** - * コンボ ボックスのリスト ボックスとエディット コントロールからすべての項目を削除します。 - */ - void ResetContent() - { - ::SendMessage(m_hWnd, CB_RESETCONTENT, 0, 0); - } - - /** - * 32 ビット値をコンボ ボックスの指定項目に関連付けられる - * @param[in] nIndex 項目に始まるインデックスを設定するためのメソッドが含まれます - * @param[in] dwItemData 新しい値を項目に関連付けるに含まれています - * @return エラーの時は CB_ERR - */ - int SetItemData(int nIndex, DWORD_PTR dwItemData) - { - return static_cast(::SendMessage(m_hWnd, CB_SETITEMDATA, static_cast(nIndex), static_cast(dwItemData))); - } - - /** - * コンボ ボックスのリスト ボックスの文字列を選択します - * @param[in] nSelect 文字列のインデックスを選択するように指定します - * @return メッセージが成功した場合は選択された項目のインデックス - */ - int SetCurSel(int nSelect) - { - return static_cast(::SendMessage(m_hWnd, CB_SETCURSEL, static_cast(nSelect), 0)); - } -}; - -/** - * @brief スライダー ボックス - */ -class CSliderProc : public CWndProc -{ -public: - /** - * スライダーの現在位置を取得します - * @return 現在位置を返します - */ - int GetPos() const - { - return static_cast(::SendMessage(m_hWnd, TBM_GETPOS, 0, 0)); - } - - /** - * スライダー コントロールでスライダーの最小範囲を設定します - * @param[in] nMin スライダーの最小の位置 - * @param[in] bRedraw 再描画のフラグ - */ - void SetRangeMin(int nMin, BOOL bRedraw) - { - ::SendMessage(m_hWnd, TBM_SETRANGEMIN, bRedraw, nMin); - } - - /** - * スライダー コントロールでスライダーの最大範囲を設定します - * @param[in] nMax スライダーの最大の位置 - * @param[in] bRedraw 再描画のフラグ - */ - void SetRangeMax(int nMax, BOOL bRedraw) - { - ::SendMessage(m_hWnd, TBM_SETRANGEMAX, bRedraw, nMax); - } - - /** - * スライダーの現在位置を設定します - * @param[in] nPos 新しいスライダーの位置を指定します - */ - void SetPos(int nPos) - { - ::SendMessage(m_hWnd, TBM_SETPOS, TRUE, nPos); - } -}; - -/** - * @brief ファイル選択 - */ -class CFileDlg -{ -public: - CFileDlg(BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, HWND hParentWnd = NULL); - int DoModal(); - - /** - * ファイル名の取得 - * @return full path and filename - */ - LPCTSTR GetPathName() const - { - return m_ofn.lpstrFile; - } - - /** - * Readoly? - * @return TRUE if readonly checked - */ - BOOL GetReadOnlyPref() const - { - return (m_ofn.Flags & OFN_READONLY) ? TRUE : FALSE; - } - -public: - OPENFILENAME m_ofn; //!< open file parameter block - -protected: - BOOL m_bOpenFileDialog; //!< TRUE for file open, FALSE for file save - std::tstring m_strFilter; //!< filter string - TCHAR m_szFileTitle[64]; //!< contains file title after return - TCHAR m_szFileName[_MAX_PATH]; //!< contains full path name after return -}; +/** + * @file DlgProc.h + * @brief ダイアログ クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include +#include + +/** + * @brief ダイアログ クラス + */ +class CDlgProc : public CWndProc +{ +public: + CDlgProc(); + CDlgProc(UINT nIDTemplate, HWND hwndParent = NULL); + virtual ~CDlgProc(); + virtual INT_PTR DoModal(); + virtual BOOL OnInitDialog(); + + /** + * モーダル ダイアログ ボックスを終了する + * @param[in] nResult DoModalの呼び出し元に返す値 + */ + void EndDialog(int nResult) + { + ::EndDialog(m_hWnd, nResult); + } + +protected: + LPCTSTR m_lpszTemplateName; //!< テンプレート名 + HWND m_hwndParent; //!< 親ウィンドウ + + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + virtual void OnOK(); + virtual void OnCancel(); + +#if defined(_WIN64) + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +#else // defined(_WIN64) + static BOOL CALLBACK DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +#endif // defined(_WIN64) +}; + + +/** + * @brief コンボ ボックス + */ +class CComboBoxProc : public CWndProc +{ +public: + /** + * コンボ ボックスのリスト ボックスに文字列を追加します + * @param[in] lpszString 追加された null で終わる文字列へのポインター + * @return 文字列が挿入された位置を示すインデックス + */ + int AddString(LPCTSTR lpszString) + { + return static_cast(::SendMessage(m_hWnd, CB_ADDSTRING, 0, reinterpret_cast(lpszString))); + } + + /** + * コンボ ボックスのリスト ボックス部分の項目数を取得するには、このメンバー関数を呼び出します + * @return 項目の数 + */ + int GetCount() const + { + return static_cast(::SendMessage(m_hWnd, CB_GETCOUNT, 0, 0)); + } + + /** + * コンボ ボックスのどの項目が選択されたかを判定するためにこのメンバー関数を呼び出します + * @return コンボ ボックスのリスト ボックスで現在選択されている項目のインデックス + */ + int GetCurSel() const + { + return static_cast(::SendMessage(m_hWnd, CB_GETCURSEL, 0, 0)); + } + + /** + * 指定したコンボ ボックスの項目に関連付けられたアプリケーションに用意された 32 ビット値を取得します + * @param[in] nIndex コンボ ボックスのリスト ボックスの項目のインデックス + * @return 32 ビット値 + */ + DWORD_PTR GetItemData(int nIndex) const + { + return static_cast(::SendMessage(m_hWnd, CB_GETITEMDATA, static_cast(nIndex), 0)); + } + + /** + * コンボ ボックスのリスト ボックスで指定されているプレフィックスを含む最初の文字列を検索します + * @param[in] nStartAfter 検索する最初の項目の前の項目のインデックス + * @param[in] lpszString 検索する文字列 + * @return インデックス + */ + int FindString(int nStartAfter, LPCTSTR lpszString) const + { + return static_cast(::SendMessage(m_hWnd, CB_FINDSTRING, nStartAfter, reinterpret_cast(lpszString))); + } + + /** + * コンボ ボックスのリスト ボックスで指定されている最初の文字列を検索します + * @param[in] nStartAfter 検索する最初の項目の前の項目のインデックス + * @param[in] lpszString 検索する文字列 + * @return インデックス + */ + int FindStringExact(int nStartAfter, LPCTSTR lpszString) const + { + return static_cast(::SendMessage(m_hWnd, CB_FINDSTRINGEXACT, nStartAfter, reinterpret_cast(lpszString))); + } + + /** + * コンボ ボックスのリスト ボックスに文字列を追加します + * @param[in] nIndex 文字列を受け取るリスト ボックスの位置 + * @param[in] lpszString 追加された null で終わる文字列へのポインター + * @return 文字列が挿入された位置を示すインデックス + */ + int InsertString(int nIndex, LPCTSTR lpszString) + { + return static_cast(::SendMessage(m_hWnd, CB_INSERTSTRING, static_cast(nIndex), reinterpret_cast(lpszString))); + } + + /** + * コンボ ボックスのリスト ボックスとエディット コントロールからすべての項目を削除します。 + */ + void ResetContent() + { + ::SendMessage(m_hWnd, CB_RESETCONTENT, 0, 0); + } + + /** + * 32 ビット値をコンボ ボックスの指定項目に関連付けられる + * @param[in] nIndex 項目に始まるインデックスを設定するためのメソッドが含まれます + * @param[in] dwItemData 新しい値を項目に関連付けるに含まれています + * @return エラーの時は CB_ERR + */ + int SetItemData(int nIndex, DWORD_PTR dwItemData) + { + return static_cast(::SendMessage(m_hWnd, CB_SETITEMDATA, static_cast(nIndex), static_cast(dwItemData))); + } + + /** + * コンボ ボックスのリスト ボックスの文字列を選択します + * @param[in] nSelect 文字列のインデックスを選択するように指定します + * @return メッセージが成功した場合は選択された項目のインデックス + */ + int SetCurSel(int nSelect) + { + return static_cast(::SendMessage(m_hWnd, CB_SETCURSEL, static_cast(nSelect), 0)); + } +}; + +/** + * @brief スライダー ボックス + */ +class CSliderProc : public CWndProc +{ +public: + /** + * スライダーの現在位置を取得します + * @return 現在位置を返します + */ + int GetPos() const + { + return static_cast(::SendMessage(m_hWnd, TBM_GETPOS, 0, 0)); + } + + /** + * スライダー コントロールでスライダーの最小範囲を設定します + * @param[in] nMin スライダーの最小の位置 + * @param[in] bRedraw 再描画のフラグ + */ + void SetRangeMin(int nMin, BOOL bRedraw) + { + ::SendMessage(m_hWnd, TBM_SETRANGEMIN, bRedraw, nMin); + } + + /** + * スライダー コントロールでスライダーの最大範囲を設定します + * @param[in] nMax スライダーの最大の位置 + * @param[in] bRedraw 再描画のフラグ + */ + void SetRangeMax(int nMax, BOOL bRedraw) + { + ::SendMessage(m_hWnd, TBM_SETRANGEMAX, bRedraw, nMax); + } + + /** + * スライダーの現在位置を設定します + * @param[in] nPos 新しいスライダーの位置を指定します + */ + void SetPos(int nPos) + { + ::SendMessage(m_hWnd, TBM_SETPOS, TRUE, nPos); + } +}; + +/** + * @brief ファイル選択 + */ +class CFileDlg +{ +public: + CFileDlg(BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, HWND hParentWnd = NULL); + int DoModal(); + + /** + * ファイル名の取得 + * @return full path and filename + */ + LPCTSTR GetPathName() const + { + return m_ofn.lpstrFile; + } + + /** + * Readoly? + * @return TRUE if readonly checked + */ + BOOL GetReadOnlyPref() const + { + return (m_ofn.Flags & OFN_READONLY) ? TRUE : FALSE; + } + +public: + OPENFILENAME m_ofn; //!< open file parameter block + +protected: + BOOL m_bOpenFileDialog; //!< TRUE for file open, FALSE for file save + std::tstring m_strFilter; //!< filter string + TCHAR m_szFileTitle[64]; //!< contains file title after return + TCHAR m_szFileName[_MAX_PATH]; //!< contains full path name after return +}; diff --git a/windows/misc/PropProc.cpp b/windows/misc/PropProc.cpp old mode 100755 new mode 100644 index e059e7e6..07d2de74 --- a/windows/misc/PropProc.cpp +++ b/windows/misc/PropProc.cpp @@ -1,257 +1,257 @@ -/** - * @file PropProc.cpp - * @brief プロパティ シート クラスの動作の定義を行います - */ - -#include -#include "PropProc.h" - -#if !defined(__GNUC__) -#pragma comment(lib, "comctl32.lib") -#endif // !defined(__GNUC__) - -// ---- プロパティ ページ - -/** - * コンストラクタ - * @param[in] nIDTemplate このページに使用するテンプレートの ID - * @param[in] nIDCaption このページのタブに設定される名前の ID - */ -CPropPageProc::CPropPageProc(UINT nIDTemplate, UINT nIDCaption) -{ - Construct(MAKEINTRESOURCE(nIDTemplate), nIDCaption); -} - -/** - * コンストラクタ - * @param[in] lpszTemplateName このページのテンプレートの名前を含む文字列へのポインター - * @param[in] nIDCaption このページのタブに設定される名前の ID - */ -CPropPageProc::CPropPageProc(LPCTSTR lpszTemplateName, UINT nIDCaption) -{ - Construct(lpszTemplateName, nIDCaption); -} - -/** - * デストラクタ - */ -CPropPageProc::~CPropPageProc() -{ - if (m_lpCaption) - { - free(m_lpCaption); - m_lpCaption = NULL; - } -} - -/** - * コンストラクト - * @param[in] nIDTemplate このページに使用するテンプレートの ID - * @param[in] nIDCaption このページのタブに設定される名前の ID - */ -void CPropPageProc::Construct(UINT nIDTemplate, UINT nIDCaption) -{ - Construct(MAKEINTRESOURCE(nIDTemplate), nIDCaption); -} - -/** - * コンストラクト - * @param[in] lpszTemplateName このページのテンプレートの名前を含む文字列へのポインター - * @param[in] nIDCaption このページのタブに設定される名前の ID - */ -void CPropPageProc::Construct(LPCTSTR lpszTemplateName, UINT nIDCaption) -{ - ZeroMemory(&m_psp, sizeof(m_psp)); - m_psp.dwSize = sizeof(m_psp); - m_psp.dwFlags = PSP_USECALLBACK; - m_psp.hInstance = FindResourceHandle(lpszTemplateName, RT_DIALOG); - m_psp.pszTemplate = lpszTemplateName; - m_psp.pfnDlgProc = DlgProc; - m_psp.lParam = reinterpret_cast(this); - m_psp.pfnCallback = PropPageCallback; - - m_lpCaption = NULL; - if (nIDCaption) - { - std::tstring rTitle(LoadTString(nIDCaption)); - m_lpCaption = _tcsdup(rTitle.c_str()); - m_psp.pszTitle = m_lpCaption; - m_psp.dwFlags |= PSP_USETITLE; - } -} - -/** - * プロパティ ページ プロシージャ - * @param[in] hWnd ウィンドウ ハンドル - * @param[in] message メッセージ - * @param[in] pPropPage このプロパティ シート ページのポインタ - * @return 0 - */ -UINT CALLBACK CPropPageProc::PropPageCallback(HWND hWnd, UINT message, LPPROPSHEETPAGE pPropPage) -{ - switch (message) - { - case PSPCB_CREATE: - HookWindowCreate(reinterpret_cast(pPropPage->lParam)); - return TRUE; - - case PSPCB_RELEASE: - UnhookWindowCreate(); - break; - } - return 0; -} - -/** - * フレームワークは、イベントがコントロールに発生する場合や、コントロールが一部の種類の情報を要求するコントロールを親ウィンドウに通知するために、このメンバー関数を呼び出します - * @param[in] wParam メッセージがコントロールからそのメッセージを送信するコントロールを識別します - * @param[in] lParam 通知コードと追加情報を含む通知メッセージ (NMHDR) の構造体へのポインター - * @param[out] pResult メッセージが処理されたとき結果を格納するコードする LRESULT の変数へのポインター - * @retval TRUE メッセージを処理した - * @retval FALSE メッセージを処理しなかった - */ -BOOL CPropPageProc::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) -{ - NMHDR* pNMHDR = reinterpret_cast(lParam); - - // allow message map to override - if (CDlgProc::OnNotify(wParam, lParam, pResult)) - { - return TRUE; - } - - // don't handle messages not from the page/sheet itself - if (pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd)) - { - return FALSE; - } - - // handle default - switch (pNMHDR->code) - { - case PSN_APPLY: - *pResult = OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE; - break; - - case PSN_RESET: - OnReset(); - break; - - default: - return FALSE; // not handled - } - - return TRUE; // handled -} - -/** - * このメンバー関数は、フレームワークによって OnKillActiveフレームワークがを呼び出した直後にユーザーが[OK]を選択するか、更新時に呼び出されます - * @retval TRUE 変更が承認された - * @retval FALSE 変更が承認されなかった - */ -BOOL CPropPageProc::OnApply() -{ - OnOK(); - return TRUE; -} - -/** - * このメンバー関数は、フレームワークによってユーザーが[キャンセル]を選択するときに呼び出されます。 - */ -void CPropPageProc::OnReset() -{ - OnCancel(); -} - -/** - * このメンバー関数は、フレームワークによって OnKillActiveフレームワークがを呼び出した直後にユーザーが[OK]を選択するか、更新時に呼び出されます - */ -void CPropPageProc::OnOK() -{ -} - -/** - * このメンバー関数は、フレームワークで[キャンセル]ボタンが選択されたときに呼び出されます - */ -void CPropPageProc::OnCancel() -{ -} - -// ---- プロパティ シート - -/** - * コンストラクタ - */ -CPropSheetProc::CPropSheetProc() -{ - CommonConstruct(NULL, 0); -} - -/** - * コンストラクタ - * @param[in] nIDCaption キャプション - * @param[in] hwndParent 親ウィンドウ - * @param[in] iSelectPage スタート ページ - */ -CPropSheetProc::CPropSheetProc(UINT nIDCaption, HWND hwndParent, UINT iSelectPage) -{ - m_strCaption = LoadTString(nIDCaption); - CommonConstruct(hwndParent, iSelectPage); -} - -/** - * コンストラクタ - * @param[in] pszCaption キャプション - * @param[in] hwndParent 親ウィンドウ - * @param[in] iSelectPage スタート ページ - */ -CPropSheetProc::CPropSheetProc(LPCTSTR pszCaption, HWND hwndParent, UINT iSelectPage) -{ - m_strCaption = pszCaption; - CommonConstruct(hwndParent, iSelectPage); -} - -/** - * コンストラクト - * @param[in] hwndParent 親ウィンドウ - * @param[in] iSelectPage スタート ページ - */ -void CPropSheetProc::CommonConstruct(HWND hwndParent, UINT iSelectPage) -{ - ZeroMemory(&m_psh, sizeof(m_psh)); - m_psh.dwSize = sizeof(m_psh); - m_psh.hwndParent = hwndParent; - m_psh.hInstance = CWndProc::GetResourceHandle(); - m_psh.nStartPage = iSelectPage; -} - -/** - * モーダル - * @return リザルト コード - */ -INT_PTR CPropSheetProc::DoModal() -{ - m_psh.pszCaption = m_strCaption.c_str(); - m_psh.nPages = static_cast(m_pages.size()); - m_psh.phpage = new HPROPSHEETPAGE[m_psh.nPages]; - for (UINT i = 0; i < m_pages.size(); i++) - { - m_psh.phpage[i] = ::CreatePropertySheetPage(&m_pages[i]->m_psp); - } - - const INT_PTR r = ::PropertySheet(&m_psh); - - delete[] m_psh.phpage; - m_psh.phpage = NULL; - - return r; -} - -/** - * ページの追加 - * @param[in] pPage ページ - */ -void CPropSheetProc::AddPage(CPropPageProc* pPage) -{ - m_pages.push_back(pPage); -} +/** + * @file PropProc.cpp + * @brief プロパティ シート クラスの動作の定義を行います + */ + +#include +#include "PropProc.h" + +#if !defined(__GNUC__) +#pragma comment(lib, "comctl32.lib") +#endif // !defined(__GNUC__) + +// ---- プロパティ ページ + +/** + * コンストラクタ + * @param[in] nIDTemplate このページに使用するテンプレートの ID + * @param[in] nIDCaption このページのタブに設定される名前の ID + */ +CPropPageProc::CPropPageProc(UINT nIDTemplate, UINT nIDCaption) +{ + Construct(MAKEINTRESOURCE(nIDTemplate), nIDCaption); +} + +/** + * コンストラクタ + * @param[in] lpszTemplateName このページのテンプレートの名前を含む文字列へのポインター + * @param[in] nIDCaption このページのタブに設定される名前の ID + */ +CPropPageProc::CPropPageProc(LPCTSTR lpszTemplateName, UINT nIDCaption) +{ + Construct(lpszTemplateName, nIDCaption); +} + +/** + * デストラクタ + */ +CPropPageProc::~CPropPageProc() +{ + if (m_lpCaption) + { + free(m_lpCaption); + m_lpCaption = NULL; + } +} + +/** + * コンストラクト + * @param[in] nIDTemplate このページに使用するテンプレートの ID + * @param[in] nIDCaption このページのタブに設定される名前の ID + */ +void CPropPageProc::Construct(UINT nIDTemplate, UINT nIDCaption) +{ + Construct(MAKEINTRESOURCE(nIDTemplate), nIDCaption); +} + +/** + * コンストラクト + * @param[in] lpszTemplateName このページのテンプレートの名前を含む文字列へのポインター + * @param[in] nIDCaption このページのタブに設定される名前の ID + */ +void CPropPageProc::Construct(LPCTSTR lpszTemplateName, UINT nIDCaption) +{ + ZeroMemory(&m_psp, sizeof(m_psp)); + m_psp.dwSize = sizeof(m_psp); + m_psp.dwFlags = PSP_USECALLBACK; + m_psp.hInstance = FindResourceHandle(lpszTemplateName, RT_DIALOG); + m_psp.pszTemplate = lpszTemplateName; + m_psp.pfnDlgProc = DlgProc; + m_psp.lParam = reinterpret_cast(this); + m_psp.pfnCallback = PropPageCallback; + + m_lpCaption = NULL; + if (nIDCaption) + { + std::tstring rTitle(LoadTString(nIDCaption)); + m_lpCaption = _tcsdup(rTitle.c_str()); + m_psp.pszTitle = m_lpCaption; + m_psp.dwFlags |= PSP_USETITLE; + } +} + +/** + * プロパティ ページ プロシージャ + * @param[in] hWnd ウィンドウ ハンドル + * @param[in] message メッセージ + * @param[in] pPropPage このプロパティ シート ページのポインタ + * @return 0 + */ +UINT CALLBACK CPropPageProc::PropPageCallback(HWND hWnd, UINT message, LPPROPSHEETPAGE pPropPage) +{ + switch (message) + { + case PSPCB_CREATE: + HookWindowCreate(reinterpret_cast(pPropPage->lParam)); + return TRUE; + + case PSPCB_RELEASE: + UnhookWindowCreate(); + break; + } + return 0; +} + +/** + * フレームワークは、イベントがコントロールに発生する場合や、コントロールが一部の種類の情報を要求するコントロールを親ウィンドウに通知するために、このメンバー関数を呼び出します + * @param[in] wParam メッセージがコントロールからそのメッセージを送信するコントロールを識別します + * @param[in] lParam 通知コードと追加情報を含む通知メッセージ (NMHDR) の構造体へのポインター + * @param[out] pResult メッセージが処理されたとき結果を格納するコードする LRESULT の変数へのポインター + * @retval TRUE メッセージを処理した + * @retval FALSE メッセージを処理しなかった + */ +BOOL CPropPageProc::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) +{ + NMHDR* pNMHDR = reinterpret_cast(lParam); + + // allow message map to override + if (CDlgProc::OnNotify(wParam, lParam, pResult)) + { + return TRUE; + } + + // don't handle messages not from the page/sheet itself + if (pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd)) + { + return FALSE; + } + + // handle default + switch (pNMHDR->code) + { + case PSN_APPLY: + *pResult = OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE; + break; + + case PSN_RESET: + OnReset(); + break; + + default: + return FALSE; // not handled + } + + return TRUE; // handled +} + +/** + * このメンバー関数は、フレームワークによって OnKillActiveフレームワークがを呼び出した直後にユーザーが[OK]を選択するか、更新時に呼び出されます + * @retval TRUE 変更が承認された + * @retval FALSE 変更が承認されなかった + */ +BOOL CPropPageProc::OnApply() +{ + OnOK(); + return TRUE; +} + +/** + * このメンバー関数は、フレームワークによってユーザーが[キャンセル]を選択するときに呼び出されます。 + */ +void CPropPageProc::OnReset() +{ + OnCancel(); +} + +/** + * このメンバー関数は、フレームワークによって OnKillActiveフレームワークがを呼び出した直後にユーザーが[OK]を選択するか、更新時に呼び出されます + */ +void CPropPageProc::OnOK() +{ +} + +/** + * このメンバー関数は、フレームワークで[キャンセル]ボタンが選択されたときに呼び出されます + */ +void CPropPageProc::OnCancel() +{ +} + +// ---- プロパティ シート + +/** + * コンストラクタ + */ +CPropSheetProc::CPropSheetProc() +{ + CommonConstruct(NULL, 0); +} + +/** + * コンストラクタ + * @param[in] nIDCaption キャプション + * @param[in] hwndParent 親ウィンドウ + * @param[in] iSelectPage スタート ページ + */ +CPropSheetProc::CPropSheetProc(UINT nIDCaption, HWND hwndParent, UINT iSelectPage) +{ + m_strCaption = LoadTString(nIDCaption); + CommonConstruct(hwndParent, iSelectPage); +} + +/** + * コンストラクタ + * @param[in] pszCaption キャプション + * @param[in] hwndParent 親ウィンドウ + * @param[in] iSelectPage スタート ページ + */ +CPropSheetProc::CPropSheetProc(LPCTSTR pszCaption, HWND hwndParent, UINT iSelectPage) +{ + m_strCaption = pszCaption; + CommonConstruct(hwndParent, iSelectPage); +} + +/** + * コンストラクト + * @param[in] hwndParent 親ウィンドウ + * @param[in] iSelectPage スタート ページ + */ +void CPropSheetProc::CommonConstruct(HWND hwndParent, UINT iSelectPage) +{ + ZeroMemory(&m_psh, sizeof(m_psh)); + m_psh.dwSize = sizeof(m_psh); + m_psh.hwndParent = hwndParent; + m_psh.hInstance = CWndProc::GetResourceHandle(); + m_psh.nStartPage = iSelectPage; +} + +/** + * モーダル + * @return リザルト コード + */ +INT_PTR CPropSheetProc::DoModal() +{ + m_psh.pszCaption = m_strCaption.c_str(); + m_psh.nPages = static_cast(m_pages.size()); + m_psh.phpage = new HPROPSHEETPAGE[m_psh.nPages]; + for (UINT i = 0; i < m_pages.size(); i++) + { + m_psh.phpage[i] = ::CreatePropertySheetPage(&m_pages[i]->m_psp); + } + + const INT_PTR r = ::PropertySheet(&m_psh); + + delete[] m_psh.phpage; + m_psh.phpage = NULL; + + return r; +} + +/** + * ページの追加 + * @param[in] pPage ページ + */ +void CPropSheetProc::AddPage(CPropPageProc* pPage) +{ + m_pages.push_back(pPage); +} diff --git a/windows/misc/PropProc.h b/windows/misc/PropProc.h old mode 100755 new mode 100644 index 5e28a088..950263de --- a/windows/misc/PropProc.h +++ b/windows/misc/PropProc.h @@ -1,59 +1,59 @@ -/** - * @file PropProc.h - * @brief プロパティ シート クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include "DlgProc.h" -#include "tstring.h" - -/** - * @brief プロパティ シート ページ - */ -class CPropPageProc : public CDlgProc -{ -public: - PROPSHEETPAGE m_psp; //!< プロパティ シート ページ構造体 - -public: - CPropPageProc(UINT nIDTemplate, UINT nIDCaption = 0); - CPropPageProc(LPCTSTR lpszTemplateName, UINT nIDCaption = 0); - virtual ~CPropPageProc(); - void Construct(UINT nIDTemplate, UINT nIDCaption = 0); - void Construct(LPCTSTR lpszTemplateName, UINT nIDCaption = 0); - -protected: - BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); - virtual BOOL OnApply(); - virtual void OnReset(); - virtual void OnOK(); - virtual void OnCancel(); - -private: - LPTSTR m_lpCaption; //!< キャプション - static UINT CALLBACK PropPageCallback(HWND hWnd, UINT message, LPPROPSHEETPAGE pPropPage); -}; - -/** - * @brief プロパティ シート - */ -class CPropSheetProc /* : public CWnd */ -{ -public: - PROPSHEETHEADER m_psh; //!< プロパティ シート ヘッダ構造体 - -public: - CPropSheetProc(); - CPropSheetProc(UINT nIDCaption, HWND hwndParent = NULL, UINT iSelectPage = 0); - CPropSheetProc(LPCTSTR pszCaption, HWND hwndParent = NULL, UINT iSelectPage = 0); - INT_PTR DoModal(); - void AddPage(CPropPageProc* pPage); - -protected: - std::vector m_pages; //!< The array of CPropPageProc pointers - std::tstring m_strCaption; //!< The caption - - void CommonConstruct(HWND hwndParent, UINT iSelectPage); -}; +/** + * @file PropProc.h + * @brief プロパティ シート クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include "DlgProc.h" +#include "tstring.h" + +/** + * @brief プロパティ シート ページ + */ +class CPropPageProc : public CDlgProc +{ +public: + PROPSHEETPAGE m_psp; //!< プロパティ シート ページ構造体 + +public: + CPropPageProc(UINT nIDTemplate, UINT nIDCaption = 0); + CPropPageProc(LPCTSTR lpszTemplateName, UINT nIDCaption = 0); + virtual ~CPropPageProc(); + void Construct(UINT nIDTemplate, UINT nIDCaption = 0); + void Construct(LPCTSTR lpszTemplateName, UINT nIDCaption = 0); + +protected: + BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + virtual BOOL OnApply(); + virtual void OnReset(); + virtual void OnOK(); + virtual void OnCancel(); + +private: + LPTSTR m_lpCaption; //!< キャプション + static UINT CALLBACK PropPageCallback(HWND hWnd, UINT message, LPPROPSHEETPAGE pPropPage); +}; + +/** + * @brief プロパティ シート + */ +class CPropSheetProc /* : public CWnd */ +{ +public: + PROPSHEETHEADER m_psh; //!< プロパティ シート ヘッダ構造体 + +public: + CPropSheetProc(); + CPropSheetProc(UINT nIDCaption, HWND hwndParent = NULL, UINT iSelectPage = 0); + CPropSheetProc(LPCTSTR pszCaption, HWND hwndParent = NULL, UINT iSelectPage = 0); + INT_PTR DoModal(); + void AddPage(CPropPageProc* pPage); + +protected: + std::vector m_pages; //!< The array of CPropPageProc pointers + std::tstring m_strCaption; //!< The caption + + void CommonConstruct(HWND hwndParent, UINT iSelectPage); +}; diff --git a/windows/misc/WndBase.h b/windows/misc/WndBase.h old mode 100755 new mode 100644 index 5afb70a9..8bba51fa --- a/windows/misc/WndBase.h +++ b/windows/misc/WndBase.h @@ -1,529 +1,529 @@ -/** - * @file WndBase.h - * @brief ウィンドウ基底クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -/** - * @brief ウィンドウ基底クラス - */ -class CWndBase -{ -public: - HWND m_hWnd; /*!< must be first data member */ - - CWndBase(HWND hWnd = NULL); - CWndBase& operator=(HWND hWnd); - void Attach(HWND hWnd); - HWND Detach(); -// BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu); -// BOOL DestroyWindow(); - - // Attributes - operator HWND() const; - DWORD GetStyle() const; - BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0); - - // Message Functions - LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0); - BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0); - - // Window Text Functions - BOOL SetWindowText(LPCTSTR lpString); - int GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const; - int GetWindowTextLength() const; - - // Font Functions - void SetFont(HFONT hFont, BOOL bRedraw = TRUE); - - // Menu Functions (non-child windows only) - HMENU GetMenu() const; - BOOL DrawMenuBar(); - HMENU GetSystemMenu(BOOL bRevert) const; - - // Window Size and Position Functions - void MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE); - - // Window Size and Position Functions - BOOL GetWindowRect(LPRECT lpRect) const; - BOOL GetClientRect(LPRECT lpRect) const; - - // Coordinate Mapping Functions - BOOL ClientToScreen(LPPOINT lpPoint) const; - int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const; - - // Update and Painting Functions - HDC BeginPaint(LPPAINTSTRUCT lpPaint); - void EndPaint(LPPAINTSTRUCT lpPaint); - BOOL UpdateWindow(); - BOOL Invalidate(BOOL bErase = TRUE); - BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE); - BOOL ShowWindow(int nCmdShow); - - // Window State Functions - BOOL EnableWindow(BOOL bEnable = TRUE); - HWND SetFocus(); - - // Dialog-Box Item Functions - BOOL CheckDlgButton(int nIDButton, UINT nCheck); - UINT GetDlgItemInt(int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE) const; - UINT GetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount) const; - UINT IsDlgButtonChecked(int nIDButton) const; - LRESULT SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0); - BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE); - BOOL SetDlgItemText(int nID, LPCTSTR lpszString); - - // Window Access Functions - CWndBase GetParent() const; - - // Window Tree Access - CWndBase GetDlgItem(int nID) const; - - // Misc. Operations - int SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE); - BOOL IsWindow() const; -}; - -/** - * コンストラクタ - * @param[in] hWnd ウィンドウ ハンドル - */ -inline CWndBase::CWndBase(HWND hWnd) - : m_hWnd(hWnd) -{ -} - -/** - * オペレータ - * @param[in] hWnd ウィンドウ ハンドル - * @return インスタンス - */ -inline CWndBase& CWndBase::operator=(HWND hWnd) -{ - m_hWnd = hWnd; - return *this; -} - -/** - * アタッチ - * @param[in] hWnd ウィンドウ ハンドル - */ -inline void CWndBase::Attach(HWND hWnd) -{ - m_hWnd = hWnd; -} - -/** - * デタッチ - * @return 以前のインスタンス - */ -inline HWND CWndBase::Detach() -{ - HWND hWnd = m_hWnd; - m_hWnd = NULL; - return hWnd; -} - -/** - * HWND オペレータ - * @return HWND - */ -inline CWndBase::operator HWND() const -{ - return m_hWnd; -} - -/** - * 現在のウィンドウ スタイルを返します - * @return ウィンドウのスタイル - */ -inline DWORD CWndBase::GetStyle() const -{ - return static_cast(::GetWindowLong(m_hWnd, GWL_STYLE)); -} - -/** - * ウィンドウ スタイルを変更します - * @param[in] dwRemove スタイルのリビジョン中に削除するウィンドウ スタイルを指定します - * @param[in] dwAdd スタイルのリビジョン中に追加するウィンドウ スタイルを指定します - * @param[in] nFlags SetWindowPosに渡すフラグ - * @retval TRUE 変更された - * @retval FALSE 変更されなかった - */ -inline BOOL CWndBase::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags) -{ - const DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE); - const DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd; - if (dwStyle == dwNewStyle) - { - return FALSE; - } - ::SetWindowLong(m_hWnd, GWL_STYLE, dwNewStyle); - if (nFlags != 0) - { - ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags); - } - return TRUE; -} - -/** - * このウィンドウに指定されたメッセージを送信します - * @param[in] message 送信されるメッセージを指定します - * @param[in] wParam 追加のメッセージ依存情報を指定します - * @param[in] lParam 追加のメッセージ依存情報を指定します - * @return メッセージの処理の結果 - */ -inline LRESULT CWndBase::SendMessage(UINT message, WPARAM wParam, LPARAM lParam) -{ - return ::SendMessage(m_hWnd, message, wParam, lParam); -} - -/** - * メッセージをウィンドウのメッセージ キューに置き、対応するウィンドウがメッセージを処理するのを待たずに返されます - * @param[in] message ポストするメッセージを指定します - * @param[in] wParam メッセージの付加情報を指定します - * @param[in] lParam メッセージの付加情報を指定します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::PostMessage(UINT message, WPARAM wParam, LPARAM lParam) -{ - return ::PostMessage(m_hWnd, message, wParam, lParam); -} - -/** - * 指定されたウィンドウのタイトルバーのテキストを変更します - * @param[in] lpString 新しいウィンドウタイトルまたはコントロールのテキストとして使われる、NULL で終わる文字列へのポインタを指定します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::SetWindowText(LPCTSTR lpString) -{ - return ::SetWindowText(m_hWnd, lpString); -} - -/** - * 指定されたウィンドウのタイトルバーのテキストをバッファへコピーします - * @param[in] lpszStringBuf バッファへのポインタを指定します。このバッファにテキストが格納されます - * @param[in] nMaxCount バッファにコピーする文字の最大数を指定します。テキストのこのサイズを超える部分は、切り捨てられます。NULL 文字も数に含められます - * @return コピーされた文字列の文字数が返ります (終端の NULL 文字は含められません) - */ -inline int CWndBase::GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const -{ - return ::GetWindowText(m_hWnd, lpszStringBuf, nMaxCount); -} - -/** - * 指定されたウィンドウのタイトルバーテキストの文字数を返します - * @return 関数が成功すると、テキストの文字数が返ります - */ -inline int CWndBase::GetWindowTextLength() const -{ - return ::GetWindowTextLength(m_hWnd); -} - -/** - * 指定したフォントを使用します - * @param[in] hFont フォント ハンドル - * @param[in] bRedraw メッセージを処理した直後にウィンドウを再描画する場合は TRUE - */ -inline void CWndBase::SetFont(HFONT hFont, BOOL bRedraw) -{ - ::SendMessage(m_hWnd, WM_SETFONT, reinterpret_cast(hFont), bRedraw); -} - -/** - * 指定されたウィンドウに割り当てられているメニューのハンドルを取得します - * @return メニューのハンドルが返ります - */ -inline HMENU CWndBase::GetMenu() const -{ - return ::GetMenu(m_hWnd); -} - -/** - * 指定されたウィンドウのメニューバーを再描画します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::DrawMenuBar() -{ - return ::DrawMenuBar(m_hWnd); -} - -/** - * 指定されたウィンドウに割り当てられているシステム メニューのハンドルを取得します - * @param[in] bRevert 実行されるアクションを指定します - * @return メニューのハンドルが返ります - */ -inline HMENU CWndBase::GetSystemMenu(BOOL bRevert) const -{ - return ::GetSystemMenu(m_hWnd, bRevert); -} - -/** - * 位置とサイズを変更します - * @param[in] x 左側の新しい位置を指定します - * @param[in] y 上側の新しい位置を指定します - * @param[in] nWidth 新しい幅を指定します - * @param[in] nHeight 新しい高さを指定します - * @param[in] bRepaint 再描画する必要があるかどうかを指定します - * @ - */ -inline void CWndBase::MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint) -{ - ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint); -} - -/** - * 指定されたウィンドウの左上端と右下端の座標をスクリーン座標で取得します - * @param[out] lpRect 構造体へのポインタを指定します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::GetWindowRect(LPRECT lpRect) const -{ - return ::GetWindowRect(m_hWnd, lpRect); -} - -/** - * lpRectが指す構造に CWnd のクライアント領域のクライアント座標をコピーします - * @param[out] lpRect 構造体へのポインタを指定します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::GetClientRect(LPRECT lpRect) const -{ - return ::GetClientRect(m_hWnd, lpRect); -} - -/** - * 指定された点を、クライアント座標からスクリーン座標へ変換します - * @param[in,out] lpPoint 変換対象のクライアント座標を保持している、1 個の 構造体へのポインタを指定します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::ClientToScreen(LPPOINT lpPoint) const -{ - return ::ClientToScreen(m_hWnd, lpPoint); -} - -/** - * 複数の点を、あるウィンドウを基準とする座標空間から、他のウィンドウを基準とする座標空間へ変換(マップ)します - * @param[in] hWndTo 変換後の点を保持する(変換先)ウィンドウのハンドルを指定します - * @param[in,out] lpPoint 変換対象の点の座標を保持している 構造体からなる 1 つの配列へのポインタを指定します - * @param[in] nCount lpPoint パラメータで、複数の POINT 構造体からなる 1 つの配列へのポインタを指定した場合、配列内の POINT 構造体の数を指定します - * @return 関数が成功すると、各点の移動距離を示す 32 ビット値が返ります - */ -inline int CWndBase::MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const -{ - return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount); -} - -/** - * 描画を開始します - * @param[out] lpPaint 描画情報へのポインタを指定します - * @return デバイス コンテキスト - */ -inline HDC CWndBase::BeginPaint(LPPAINTSTRUCT lpPaint) -{ - return ::BeginPaint(m_hWnd, lpPaint); -} - -/** - * 描画の終了します - * @param[in] lpPaint 描画情報へのポインタを指定します - */ -inline void CWndBase::EndPaint(LPPAINTSTRUCT lpPaint) -{ - ::EndPaint(m_hWnd, lpPaint); -} - -/** - * 指定されたウィンドウの更新リージョンが空ではない場合、ウィンドウへ メッセージを送信し、そのウィンドウのクライアント領域を更新します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::UpdateWindow() -{ - return ::UpdateWindow(m_hWnd); -} - -/** - * 指定されたウィンドウのすべてを更新リージョンにします - * @param[in] bErase 更新リージョンを処理するときに、更新リージョン内の背景を消去するかどうかを指定します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::Invalidate(BOOL bErase) -{ - return ::InvalidateRect(m_hWnd, NULL, bErase); -} - -/** - * 指定されたウィンドウの更新リージョンに1個の長方形を追加します - * @param[in] lpRect 更新リージョンへ追加したい長方形のクライアント座標を保持する1個の構造体へのポインタを指定します - * @param[in] bErase 更新リージョンを処理するときに、更新リージョン内の背景を消去するかどうかを指定します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::InvalidateRect(LPCRECT lpRect, BOOL bErase) -{ - return ::InvalidateRect(m_hWnd, lpRect, bErase); -} - -/** - * 指定されたウィンドウの表示状態を設定します - * @param[in] nCmdShow ウィンドウの表示方法を指定します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::ShowWindow(int nCmdShow) -{ - return ::ShowWindow(m_hWnd, nCmdShow); -} - -/** - * 指定されたウィンドウまたはコントロールで、マウス入力とキーボード入力を有効または無効にします - * @param[in] bEnable ウィンドウを有効にするか無効にするかを指定します - * @retval TRUE ウィンドウが既に無効になっている - * @retval FALSE ウィンドウが無効になっていなかった - */ -inline BOOL CWndBase::EnableWindow(BOOL bEnable) -{ - return ::EnableWindow(m_hWnd, bEnable); -} - -/** - * 入力フォーカスを要求します - * @return 直前に入力フォーカスを持っていたウィンドウ ハンドル - */ -inline HWND CWndBase::SetFocus() -{ - return ::SetFocus(m_hWnd); -} - -/** - * ボタンコントロールのチェック状態を変更します - * @param[in] nIDButton 状態を変更したいボタンの識別子を指定します - * @param[in] nCheck ボタンのチェック状態を指定します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::CheckDlgButton(int nIDButton, UINT nCheck) -{ - return ::CheckDlgButton(m_hWnd, nIDButton, nCheck); -} - -/** - * ダイアログボックス内の指定されたコントロールのテキストを、整数値へ変換します - * @param[in] nID 変換したいテキストを持つコントロールの識別子を指定します - * @param[in] lpTrans 成功か失敗の値を受け取る変数へのポインタを指定します - * @param[in] bSigned テキストを符号付きとして扱って符号付きの値を返すかどうかを指定します - * @return コントロールテキストに相当する整数値が返ります - */ -inline UINT CWndBase::GetDlgItemInt(int nID, BOOL* lpTrans, BOOL bSigned) const -{ - return ::GetDlgItemInt(m_hWnd, nID, lpTrans, bSigned); -} - -/** - * ダイアログボックス内の指定されたコントロールに関連付けられているタイトルまたはテキストを取得します - * @param[in] nID 取得したいタイトルまたはテキストを保持しているコントロールの識別子を指定します - * @param[out] lpStr タイトルまたはテキストを受け取るバッファへのポインタを指定します - * @param[in] nMaxCount lpStr パラメータが指すバッファへコピーされる文字列の最大の長さを TCHAR 単位で指定します - * @return バッファへコピーされた文字列の長さ( 終端の NULL を含まない)が TCHAR 単位で返ります - */ -inline UINT CWndBase::GetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount) const -{ - return ::GetDlgItemText(m_hWnd, nID, lpStr, nMaxCount); -} - -/** - * ボタンコントロールのチェック状態を取得します - * @param[in] nIDButton ボタンコントロールの識別子を指定します - * @return チェック状態 - */ -inline UINT CWndBase::IsDlgButtonChecked(int nIDButton) const -{ - return ::IsDlgButtonChecked(m_hWnd, nIDButton); -} - -/** - * ダイアログボックス内の指定されたコントロールへメッセージを送信します。 - * @param[in] nID メッセージを受け取るコントロールの識別子を指定します - * @param[in] message 送信したいメッセージを指定します - * @param[in] wParam メッセージの追加情報を指定します - * @param[in] lParam メッセージの追加情報を指定します - * @return メッセージ処理の結果が返ります - */ -inline LRESULT CWndBase::SendDlgItemMessage(int nID, UINT message, WPARAM wParam, LPARAM lParam) -{ - return ::SendDlgItemMessage(m_hWnd, nID, message, wParam, lParam); -} - -/** - * 指定された整数値を文字列へ変換し、ダイアログボックス内のコントロールにテキストとして設定します - * @param[in] nID 変更を加えたいコントロールの識別子を指定します - * @param[in] nValue 整数値を指定します - * @param[in] bSigned nValue パラメータの値が符号付きかどうかを指定します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::SetDlgItemInt(int nID, UINT nValue, BOOL bSigned) -{ - return ::SetDlgItemInt(m_hWnd, nID, nValue, bSigned); -} - -/** - * ダイアログボックス内のコントロールのタイトルまたはテキストを設定します - * @param[in] nID テキストを設定したいコントロールの識別子を指定します - * @param[in] lpszString コントロールへコピーしたいテキストを保持する、NULL で終わる文字列へのポインタを指定します - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -inline BOOL CWndBase::SetDlgItemText(int nID, LPCTSTR lpszString) -{ - return ::SetDlgItemText(m_hWnd, nID, lpszString); -} - -/** - * 指定された子ウィンドウの親ウィンドウまたはオーナーウィンドウのハンドルを返します - * @return 親ウィンドウのハンドル - */ -inline CWndBase CWndBase::GetParent() const -{ - return CWndBase(::GetParent(m_hWnd)); -} - -/** - * 指定されたダイアログボックス内のコントロールのハンドルを取得します - * @param[in] nID ハンドルを取得したいコントロールの識別子を指定します - * @return ウィンドウ - */ -inline CWndBase CWndBase::GetDlgItem(int nID) const -{ - return CWndBase(::GetDlgItem(m_hWnd, nID)); -} - -/** - * スクロールバーのさまざまなパラメータを設定します - * @param[in] nBar パラメータを設定するべきスクロールバーのタイプを指定します - * @param[in] lpScrollInfo 設定するべき情報を保持している、1個の構造体へのポインタを指定します - * @param[in] bRedraw スクロールバーを再描画するかどうかを指定します - * @return スクロールバーの現在のスクロール位置が返ります - */ -inline int CWndBase::SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw) -{ - return ::SetScrollInfo(m_hWnd, nBar, lpScrollInfo, bRedraw); -} - -/** - * ウィンドウが存在しているかどうかを調べます - * @return 指定したウィンドウハンドルを持つウィンドウが存在している場合は、0 以外の値が返ります - */ -inline BOOL CWndBase::IsWindow() const -{ - return ::IsWindow(m_hWnd); -} +/** + * @file WndBase.h + * @brief ウィンドウ基底クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +/** + * @brief ウィンドウ基底クラス + */ +class CWndBase +{ +public: + HWND m_hWnd; /*!< must be first data member */ + + CWndBase(HWND hWnd = NULL); + CWndBase& operator=(HWND hWnd); + void Attach(HWND hWnd); + HWND Detach(); +// BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu); +// BOOL DestroyWindow(); + + // Attributes + operator HWND() const; + DWORD GetStyle() const; + BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0); + + // Message Functions + LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0); + BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0); + + // Window Text Functions + BOOL SetWindowText(LPCTSTR lpString); + int GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const; + int GetWindowTextLength() const; + + // Font Functions + void SetFont(HFONT hFont, BOOL bRedraw = TRUE); + + // Menu Functions (non-child windows only) + HMENU GetMenu() const; + BOOL DrawMenuBar(); + HMENU GetSystemMenu(BOOL bRevert) const; + + // Window Size and Position Functions + void MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE); + + // Window Size and Position Functions + BOOL GetWindowRect(LPRECT lpRect) const; + BOOL GetClientRect(LPRECT lpRect) const; + + // Coordinate Mapping Functions + BOOL ClientToScreen(LPPOINT lpPoint) const; + int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const; + + // Update and Painting Functions + HDC BeginPaint(LPPAINTSTRUCT lpPaint); + void EndPaint(LPPAINTSTRUCT lpPaint); + BOOL UpdateWindow(); + BOOL Invalidate(BOOL bErase = TRUE); + BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE); + BOOL ShowWindow(int nCmdShow); + + // Window State Functions + BOOL EnableWindow(BOOL bEnable = TRUE); + HWND SetFocus(); + + // Dialog-Box Item Functions + BOOL CheckDlgButton(int nIDButton, UINT nCheck); + UINT GetDlgItemInt(int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE) const; + UINT GetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount) const; + UINT IsDlgButtonChecked(int nIDButton) const; + LRESULT SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0); + BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE); + BOOL SetDlgItemText(int nID, LPCTSTR lpszString); + + // Window Access Functions + CWndBase GetParent() const; + + // Window Tree Access + CWndBase GetDlgItem(int nID) const; + + // Misc. Operations + int SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE); + BOOL IsWindow() const; +}; + +/** + * コンストラクタ + * @param[in] hWnd ウィンドウ ハンドル + */ +inline CWndBase::CWndBase(HWND hWnd) + : m_hWnd(hWnd) +{ +} + +/** + * オペレータ + * @param[in] hWnd ウィンドウ ハンドル + * @return インスタンス + */ +inline CWndBase& CWndBase::operator=(HWND hWnd) +{ + m_hWnd = hWnd; + return *this; +} + +/** + * アタッチ + * @param[in] hWnd ウィンドウ ハンドル + */ +inline void CWndBase::Attach(HWND hWnd) +{ + m_hWnd = hWnd; +} + +/** + * デタッチ + * @return 以前のインスタンス + */ +inline HWND CWndBase::Detach() +{ + HWND hWnd = m_hWnd; + m_hWnd = NULL; + return hWnd; +} + +/** + * HWND オペレータ + * @return HWND + */ +inline CWndBase::operator HWND() const +{ + return m_hWnd; +} + +/** + * 現在のウィンドウ スタイルを返します + * @return ウィンドウのスタイル + */ +inline DWORD CWndBase::GetStyle() const +{ + return static_cast(::GetWindowLong(m_hWnd, GWL_STYLE)); +} + +/** + * ウィンドウ スタイルを変更します + * @param[in] dwRemove スタイルのリビジョン中に削除するウィンドウ スタイルを指定します + * @param[in] dwAdd スタイルのリビジョン中に追加するウィンドウ スタイルを指定します + * @param[in] nFlags SetWindowPosに渡すフラグ + * @retval TRUE 変更された + * @retval FALSE 変更されなかった + */ +inline BOOL CWndBase::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags) +{ + const DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE); + const DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd; + if (dwStyle == dwNewStyle) + { + return FALSE; + } + ::SetWindowLong(m_hWnd, GWL_STYLE, dwNewStyle); + if (nFlags != 0) + { + ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags); + } + return TRUE; +} + +/** + * このウィンドウに指定されたメッセージを送信します + * @param[in] message 送信されるメッセージを指定します + * @param[in] wParam 追加のメッセージ依存情報を指定します + * @param[in] lParam 追加のメッセージ依存情報を指定します + * @return メッセージの処理の結果 + */ +inline LRESULT CWndBase::SendMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + return ::SendMessage(m_hWnd, message, wParam, lParam); +} + +/** + * メッセージをウィンドウのメッセージ キューに置き、対応するウィンドウがメッセージを処理するのを待たずに返されます + * @param[in] message ポストするメッセージを指定します + * @param[in] wParam メッセージの付加情報を指定します + * @param[in] lParam メッセージの付加情報を指定します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::PostMessage(UINT message, WPARAM wParam, LPARAM lParam) +{ + return ::PostMessage(m_hWnd, message, wParam, lParam); +} + +/** + * 指定されたウィンドウのタイトルバーのテキストを変更します + * @param[in] lpString 新しいウィンドウタイトルまたはコントロールのテキストとして使われる、NULL で終わる文字列へのポインタを指定します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::SetWindowText(LPCTSTR lpString) +{ + return ::SetWindowText(m_hWnd, lpString); +} + +/** + * 指定されたウィンドウのタイトルバーのテキストをバッファへコピーします + * @param[in] lpszStringBuf バッファへのポインタを指定します。このバッファにテキストが格納されます + * @param[in] nMaxCount バッファにコピーする文字の最大数を指定します。テキストのこのサイズを超える部分は、切り捨てられます。NULL 文字も数に含められます + * @return コピーされた文字列の文字数が返ります (終端の NULL 文字は含められません) + */ +inline int CWndBase::GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const +{ + return ::GetWindowText(m_hWnd, lpszStringBuf, nMaxCount); +} + +/** + * 指定されたウィンドウのタイトルバーテキストの文字数を返します + * @return 関数が成功すると、テキストの文字数が返ります + */ +inline int CWndBase::GetWindowTextLength() const +{ + return ::GetWindowTextLength(m_hWnd); +} + +/** + * 指定したフォントを使用します + * @param[in] hFont フォント ハンドル + * @param[in] bRedraw メッセージを処理した直後にウィンドウを再描画する場合は TRUE + */ +inline void CWndBase::SetFont(HFONT hFont, BOOL bRedraw) +{ + ::SendMessage(m_hWnd, WM_SETFONT, reinterpret_cast(hFont), bRedraw); +} + +/** + * 指定されたウィンドウに割り当てられているメニューのハンドルを取得します + * @return メニューのハンドルが返ります + */ +inline HMENU CWndBase::GetMenu() const +{ + return ::GetMenu(m_hWnd); +} + +/** + * 指定されたウィンドウのメニューバーを再描画します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::DrawMenuBar() +{ + return ::DrawMenuBar(m_hWnd); +} + +/** + * 指定されたウィンドウに割り当てられているシステム メニューのハンドルを取得します + * @param[in] bRevert 実行されるアクションを指定します + * @return メニューのハンドルが返ります + */ +inline HMENU CWndBase::GetSystemMenu(BOOL bRevert) const +{ + return ::GetSystemMenu(m_hWnd, bRevert); +} + +/** + * 位置とサイズを変更します + * @param[in] x 左側の新しい位置を指定します + * @param[in] y 上側の新しい位置を指定します + * @param[in] nWidth 新しい幅を指定します + * @param[in] nHeight 新しい高さを指定します + * @param[in] bRepaint 再描画する必要があるかどうかを指定します + * @ + */ +inline void CWndBase::MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint) +{ + ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint); +} + +/** + * 指定されたウィンドウの左上端と右下端の座標をスクリーン座標で取得します + * @param[out] lpRect 構造体へのポインタを指定します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::GetWindowRect(LPRECT lpRect) const +{ + return ::GetWindowRect(m_hWnd, lpRect); +} + +/** + * lpRectが指す構造に CWnd のクライアント領域のクライアント座標をコピーします + * @param[out] lpRect 構造体へのポインタを指定します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::GetClientRect(LPRECT lpRect) const +{ + return ::GetClientRect(m_hWnd, lpRect); +} + +/** + * 指定された点を、クライアント座標からスクリーン座標へ変換します + * @param[in,out] lpPoint 変換対象のクライアント座標を保持している、1 個の 構造体へのポインタを指定します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::ClientToScreen(LPPOINT lpPoint) const +{ + return ::ClientToScreen(m_hWnd, lpPoint); +} + +/** + * 複数の点を、あるウィンドウを基準とする座標空間から、他のウィンドウを基準とする座標空間へ変換(マップ)します + * @param[in] hWndTo 変換後の点を保持する(変換先)ウィンドウのハンドルを指定します + * @param[in,out] lpPoint 変換対象の点の座標を保持している 構造体からなる 1 つの配列へのポインタを指定します + * @param[in] nCount lpPoint パラメータで、複数の POINT 構造体からなる 1 つの配列へのポインタを指定した場合、配列内の POINT 構造体の数を指定します + * @return 関数が成功すると、各点の移動距離を示す 32 ビット値が返ります + */ +inline int CWndBase::MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const +{ + return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount); +} + +/** + * 描画を開始します + * @param[out] lpPaint 描画情報へのポインタを指定します + * @return デバイス コンテキスト + */ +inline HDC CWndBase::BeginPaint(LPPAINTSTRUCT lpPaint) +{ + return ::BeginPaint(m_hWnd, lpPaint); +} + +/** + * 描画の終了します + * @param[in] lpPaint 描画情報へのポインタを指定します + */ +inline void CWndBase::EndPaint(LPPAINTSTRUCT lpPaint) +{ + ::EndPaint(m_hWnd, lpPaint); +} + +/** + * 指定されたウィンドウの更新リージョンが空ではない場合、ウィンドウへ メッセージを送信し、そのウィンドウのクライアント領域を更新します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::UpdateWindow() +{ + return ::UpdateWindow(m_hWnd); +} + +/** + * 指定されたウィンドウのすべてを更新リージョンにします + * @param[in] bErase 更新リージョンを処理するときに、更新リージョン内の背景を消去するかどうかを指定します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::Invalidate(BOOL bErase) +{ + return ::InvalidateRect(m_hWnd, NULL, bErase); +} + +/** + * 指定されたウィンドウの更新リージョンに1個の長方形を追加します + * @param[in] lpRect 更新リージョンへ追加したい長方形のクライアント座標を保持する1個の構造体へのポインタを指定します + * @param[in] bErase 更新リージョンを処理するときに、更新リージョン内の背景を消去するかどうかを指定します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::InvalidateRect(LPCRECT lpRect, BOOL bErase) +{ + return ::InvalidateRect(m_hWnd, lpRect, bErase); +} + +/** + * 指定されたウィンドウの表示状態を設定します + * @param[in] nCmdShow ウィンドウの表示方法を指定します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::ShowWindow(int nCmdShow) +{ + return ::ShowWindow(m_hWnd, nCmdShow); +} + +/** + * 指定されたウィンドウまたはコントロールで、マウス入力とキーボード入力を有効または無効にします + * @param[in] bEnable ウィンドウを有効にするか無効にするかを指定します + * @retval TRUE ウィンドウが既に無効になっている + * @retval FALSE ウィンドウが無効になっていなかった + */ +inline BOOL CWndBase::EnableWindow(BOOL bEnable) +{ + return ::EnableWindow(m_hWnd, bEnable); +} + +/** + * 入力フォーカスを要求します + * @return 直前に入力フォーカスを持っていたウィンドウ ハンドル + */ +inline HWND CWndBase::SetFocus() +{ + return ::SetFocus(m_hWnd); +} + +/** + * ボタンコントロールのチェック状態を変更します + * @param[in] nIDButton 状態を変更したいボタンの識別子を指定します + * @param[in] nCheck ボタンのチェック状態を指定します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::CheckDlgButton(int nIDButton, UINT nCheck) +{ + return ::CheckDlgButton(m_hWnd, nIDButton, nCheck); +} + +/** + * ダイアログボックス内の指定されたコントロールのテキストを、整数値へ変換します + * @param[in] nID 変換したいテキストを持つコントロールの識別子を指定します + * @param[in] lpTrans 成功か失敗の値を受け取る変数へのポインタを指定します + * @param[in] bSigned テキストを符号付きとして扱って符号付きの値を返すかどうかを指定します + * @return コントロールテキストに相当する整数値が返ります + */ +inline UINT CWndBase::GetDlgItemInt(int nID, BOOL* lpTrans, BOOL bSigned) const +{ + return ::GetDlgItemInt(m_hWnd, nID, lpTrans, bSigned); +} + +/** + * ダイアログボックス内の指定されたコントロールに関連付けられているタイトルまたはテキストを取得します + * @param[in] nID 取得したいタイトルまたはテキストを保持しているコントロールの識別子を指定します + * @param[out] lpStr タイトルまたはテキストを受け取るバッファへのポインタを指定します + * @param[in] nMaxCount lpStr パラメータが指すバッファへコピーされる文字列の最大の長さを TCHAR 単位で指定します + * @return バッファへコピーされた文字列の長さ( 終端の NULL を含まない)が TCHAR 単位で返ります + */ +inline UINT CWndBase::GetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount) const +{ + return ::GetDlgItemText(m_hWnd, nID, lpStr, nMaxCount); +} + +/** + * ボタンコントロールのチェック状態を取得します + * @param[in] nIDButton ボタンコントロールの識別子を指定します + * @return チェック状態 + */ +inline UINT CWndBase::IsDlgButtonChecked(int nIDButton) const +{ + return ::IsDlgButtonChecked(m_hWnd, nIDButton); +} + +/** + * ダイアログボックス内の指定されたコントロールへメッセージを送信します。 + * @param[in] nID メッセージを受け取るコントロールの識別子を指定します + * @param[in] message 送信したいメッセージを指定します + * @param[in] wParam メッセージの追加情報を指定します + * @param[in] lParam メッセージの追加情報を指定します + * @return メッセージ処理の結果が返ります + */ +inline LRESULT CWndBase::SendDlgItemMessage(int nID, UINT message, WPARAM wParam, LPARAM lParam) +{ + return ::SendDlgItemMessage(m_hWnd, nID, message, wParam, lParam); +} + +/** + * 指定された整数値を文字列へ変換し、ダイアログボックス内のコントロールにテキストとして設定します + * @param[in] nID 変更を加えたいコントロールの識別子を指定します + * @param[in] nValue 整数値を指定します + * @param[in] bSigned nValue パラメータの値が符号付きかどうかを指定します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::SetDlgItemInt(int nID, UINT nValue, BOOL bSigned) +{ + return ::SetDlgItemInt(m_hWnd, nID, nValue, bSigned); +} + +/** + * ダイアログボックス内のコントロールのタイトルまたはテキストを設定します + * @param[in] nID テキストを設定したいコントロールの識別子を指定します + * @param[in] lpszString コントロールへコピーしたいテキストを保持する、NULL で終わる文字列へのポインタを指定します + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +inline BOOL CWndBase::SetDlgItemText(int nID, LPCTSTR lpszString) +{ + return ::SetDlgItemText(m_hWnd, nID, lpszString); +} + +/** + * 指定された子ウィンドウの親ウィンドウまたはオーナーウィンドウのハンドルを返します + * @return 親ウィンドウのハンドル + */ +inline CWndBase CWndBase::GetParent() const +{ + return CWndBase(::GetParent(m_hWnd)); +} + +/** + * 指定されたダイアログボックス内のコントロールのハンドルを取得します + * @param[in] nID ハンドルを取得したいコントロールの識別子を指定します + * @return ウィンドウ + */ +inline CWndBase CWndBase::GetDlgItem(int nID) const +{ + return CWndBase(::GetDlgItem(m_hWnd, nID)); +} + +/** + * スクロールバーのさまざまなパラメータを設定します + * @param[in] nBar パラメータを設定するべきスクロールバーのタイプを指定します + * @param[in] lpScrollInfo 設定するべき情報を保持している、1個の構造体へのポインタを指定します + * @param[in] bRedraw スクロールバーを再描画するかどうかを指定します + * @return スクロールバーの現在のスクロール位置が返ります + */ +inline int CWndBase::SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw) +{ + return ::SetScrollInfo(m_hWnd, nBar, lpScrollInfo, bRedraw); +} + +/** + * ウィンドウが存在しているかどうかを調べます + * @return 指定したウィンドウハンドルを持つウィンドウが存在している場合は、0 以外の値が返ります + */ +inline BOOL CWndBase::IsWindow() const +{ + return ::IsWindow(m_hWnd); +} diff --git a/windows/misc/WndProc.cpp b/windows/misc/WndProc.cpp old mode 100755 new mode 100644 index cea51370..80f276b2 --- a/windows/misc/WndProc.cpp +++ b/windows/misc/WndProc.cpp @@ -1,512 +1,512 @@ -/** - * @file WndProc.cpp - * @brief プロシージャ クラスの動作の定義を行います - */ - -#include -#include "WndProc.h" -#include -#define ASSERT assert /*!< assert */ - -//! 基底クラス名 -// static const TCHAR s_szClassName[] = TEXT("WndProcBase"); - -//! インスタンス -HINSTANCE CWndProc::sm_hInstance; -//! リソース -HINSTANCE CWndProc::sm_hResource; - -DWORD CWndProc::sm_dwThreadId; //!< 自分のスレッド ID -HHOOK CWndProc::sm_hHookOldCbtFilter = NULL; //!< フック フィルター -CWndProc* CWndProc::sm_pWndInit = NULL; //!< 初期化中のインスタンス -std::map* CWndProc::sm_pWndMap = NULL; //!< ウィンドウ マップ - -/** - * 初期化 - * @param[in] hInstance インスタンス - */ -void CWndProc::Initialize(HINSTANCE hInstance) -{ - sm_hInstance = hInstance; - sm_hResource = hInstance; - - sm_dwThreadId = ::GetCurrentThreadId(); - sm_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT, CbtFilterHook, NULL, sm_dwThreadId); - - sm_pWndMap = new std::map; - -#if 0 - WNDCLASS wc; - ZeroMemory(&wc, sizeof(wc)); - wc.style = CS_BYTEALIGNCLIENT | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; - wc.lpfnWndProc = WndProc; - wc.hInstance = hInstance; - wc.hIcon = ::LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON2)); - wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = static_cast(::GetStockObject(NULL_BRUSH)); - wc.lpszClassName = s_szClassName; - ::RegisterClass(&wc); -#endif // 0 -} - -/** - * 解放 - */ -void CWndProc::Deinitialize() -{ - if (sm_hHookOldCbtFilter != NULL) - { - ::UnhookWindowsHookEx(sm_hHookOldCbtFilter); - sm_hHookOldCbtFilter = NULL; - } - if(sm_pWndMap != NULL){ - delete sm_pWndMap; - sm_pWndMap = NULL; - } -} - -/** - * リソースの検索 - * @param[in] lpszName リソース ID - * @param[in] lpszType リソースの型へのポインタ - * @return インスタンス - */ -HINSTANCE CWndProc::FindResourceHandle(LPCTSTR lpszName, LPCTSTR lpszType) -{ - HINSTANCE hInst = GetResourceHandle(); - if ((hInst != GetInstanceHandle()) && (::FindResource(hInst, lpszName, lpszType) != NULL)) - { - return hInst; - } - return GetInstanceHandle(); -} - -/** - * コンストラクタ - */ -CWndProc::CWndProc() - : CWndBase(NULL) - , m_pfnSuper(NULL) -{ -} - -/** - * デストラクタ - */ -CWndProc::~CWndProc() -{ - DestroyWindow(); -} - -/** - * ウィンドウのハンドルが指定されている場合、CWndProc オブジェクトへのポインターを返します - * @param[in] hWnd ウィンドウ ハンドル - * @return ポインタ - */ -CWndProc* CWndProc::FromHandlePermanent(HWND hWnd) -{ - std::map* pMap = sm_pWndMap; - if (pMap) - { - std::map::iterator it = pMap->find(hWnd); - if (it != pMap->end()) - { - return it->second; - } - } - return NULL; -} - -/** - * Windows のウィンドウをアタッチします - * @param[in] hWndNew ウィンドウ ハンドル - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -BOOL CWndProc::Attach(HWND hWndNew) -{ - std::map* pMap = sm_pWndMap; - if ((hWndNew != NULL) && (pMap)) - { - (*pMap)[hWndNew] = this; - m_hWnd = hWndNew; - return TRUE; - } - else - { - return FALSE; - } -} - -/** - * Windows のハンドルを切り離し、そのハンドルを返します - * @return ウィンドウ ハンドル - */ -HWND CWndProc::Detach() -{ - HWND hWnd = m_hWnd; - if (hWnd != NULL) - { - std::map* pMap = sm_pWndMap; - if (pMap) - { - std::map::iterator it = pMap->find(hWnd); - if (it != pMap->end()) - { - pMap->erase(it); - } - } - m_hWnd = NULL; - } - return hWnd; -} - -/** - * このメンバー関数はウィンドウがサブクラス化する前に、ほかのサブクラス化に必要な操作を許可するためにフレームワークから呼ばれます - */ -void CWndProc::PreSubclassWindow() -{ - // no default processing -} - -/** - * ウィンドウを動的サブクラス化し、CWnd オブジェクトに結び付けるためにこのメンバー関数を呼び出します - * @param[in] hWnd ウィンドウ ハンドル - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -BOOL CWndProc::SubclassWindow(HWND hWnd) -{ - if (!Attach(hWnd)) - { - return FALSE; - } - - PreSubclassWindow(); - - WNDPROC newWndProc = &CWndProc::WndProc; - WNDPROC oldWndProc = reinterpret_cast(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(newWndProc))); - if ((m_pfnSuper == NULL) && (oldWndProc != newWndProc)) - { - m_pfnSuper = oldWndProc; - } - return TRUE; -} - -/** - * コントロールを動的サブクラス化し、CWnd オブジェクトに結び付けるためにこのメンバー関数を呼び出します - * @param[in] nID コントロール ID - * @param[in] pParent コントロールの親 - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -BOOL CWndProc::SubclassDlgItem(UINT nID, CWndProc* pParent) -{ - HWND hWndControl = ::GetDlgItem(pParent->m_hWnd, nID); - if (hWndControl != NULL) - { - return SubclassWindow(hWndControl); - } - return FALSE; -} - -/** - * WndProc に元の値を設定して CWnd オブジェクトから HWND で識別されるウィンドウを切り離すために、このメンバー関数を呼び出します - * @return 非サブクラス化されたウィンドウへのハンドル - */ -HWND CWndProc::UnsubclassWindow() -{ - if (m_pfnSuper != NULL) - { - ::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, reinterpret_cast(m_pfnSuper)); - m_pfnSuper = NULL; - } - return Detach(); -} - -/** - * 指定されたウィンドウを作成し、それを CWndProc オブジェクトにアタッチします - * @param[in] dwExStyle 拡張ウィンドウ スタイル - * @param[in] lpszClassName 登録されているシステム ウィンドウ クラスの名前 - * @param[in] lpszWindowName ウィンドウの表示名 - * @param[in] dwStyle ウィンドウ スタイル - * @param[in] x 画面または親ウィンドウの左端からウィンドウの初期位置までの水平方向の距離 - * @param[in] y 画面または親ウィンドウの上端からウィンドウの初期位置までの垂直方向の距離 - * @param[in] nWidth ウィンドウの幅 (ピクセル単位) - * @param[in] nHeight ウィンドウの高さ (ピクセル単位) - * @param[in] hwndParent 親ウィンドウへのハンドル - * @param[in] nIDorHMenu ウィンドウ ID - * @param[in] lpParam ユーザー データ - * @retval TRUE 成功 - * @retval FALSE 失敗 - */ -BOOL CWndProc::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu, LPVOID lpParam) -{ - // 同じスレッドのみ許す - if (sm_dwThreadId != ::GetCurrentThreadId()) - { - PostNcDestroy(); - return FALSE; - } - - CREATESTRUCT cs; - cs.dwExStyle = dwExStyle; - cs.lpszClass = lpszClassName; - cs.lpszName = lpszWindowName; - cs.style = dwStyle; - cs.x = x; - cs.y = y; - cs.cx = nWidth; - cs.cy = nHeight; - cs.hwndParent = hwndParent; - cs.hMenu = nIDorHMenu; - cs.hInstance = sm_hInstance; - cs.lpCreateParams = lpParam; - - if (!PreCreateWindow(cs)) - { - PostNcDestroy(); - return FALSE; - } - - HookWindowCreate(this); - HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams); - if (!UnhookWindowCreate()) - { - PostNcDestroy(); - } - - return (hWnd != NULL) ? TRUE : FALSE; -} - -/** - * CWnd オブジェクトに結び付けられた Windows のウィンドウが作成される前に、フレームワークから呼び出されます - * @param[in,out] cs CREATESTRUCT の構造 - * @retval TRUE 継続 - */ -BOOL CWndProc::PreCreateWindow(CREATESTRUCT& cs) -{ - return TRUE; -} - -/** - * ウィンドウ作成をフック - * @param[in] pWnd ウィンドウ - */ -void CWndProc::HookWindowCreate(CWndProc* pWnd) -{ - // 同じスレッドのみ許す - ASSERT(sm_dwThreadId == ::GetCurrentThreadId()); - - if (sm_pWndInit == pWnd) - { - return; - } - - ASSERT(sm_hHookOldCbtFilter != NULL); - ASSERT(pWnd != NULL); - ASSERT(pWnd->m_hWnd == NULL); - ASSERT(sm_pWndInit == NULL); - sm_pWndInit = pWnd; -} - -/** - * ウィンドウ作成をアンフック - * @retval true フックした - * @retval false フックしなかった - */ -bool CWndProc::UnhookWindowCreate() -{ - if (sm_pWndInit != NULL) - { - sm_pWndInit = NULL; - return false; - } - return true; -} - -/** - * フック フィルタ - * @param[in] nCode コード - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @return リザルト コード - */ -LRESULT CALLBACK CWndProc::CbtFilterHook(int nCode, WPARAM wParam, LPARAM lParam) -{ - if (nCode == HCBT_CREATEWND) - { - HWND hWnd = reinterpret_cast(wParam); - LPCREATESTRUCT lpcs = reinterpret_cast(lParam)->lpcs; - - CWndProc* pWndInit = sm_pWndInit; - if (pWndInit != NULL) - { - pWndInit->Attach(hWnd); - pWndInit->PreSubclassWindow(); - - WNDPROC newWndProc = &CWndProc::WndProc; - WNDPROC oldWndProc = reinterpret_cast(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(newWndProc))); - if (oldWndProc != newWndProc) - { - pWndInit->m_pfnSuper = oldWndProc; - } - sm_pWndInit = NULL; - } - } - return ::CallNextHookEx(sm_hHookOldCbtFilter, nCode, wParam, lParam); -} - -/** - * CWndProc オブジェクトに関連付けられた Windows のウィンドウを破棄します - * @return ウィンドウが破棄された場合は 0 以外を返します。それ以外の場合は 0 を返します - */ -BOOL CWndProc::DestroyWindow() -{ - if (m_hWnd == NULL) - { - return FALSE; - } - - CWndProc* pWnd = FromHandlePermanent(m_hWnd); - - HWND oldhWnd = m_hWnd; - if (pWnd != NULL) - { - UnsubclassWindow(); // 兼 Detach(); - } - - const BOOL bResult = ::DestroyWindow(oldhWnd); - - return bResult; -} - -/** - * ウィンドウ プロシージャ - * @param[in] hWnd ウィンドウ ハンドル - * @param[in] message 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT CALLBACK CWndProc::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - CWndProc* pWnd = FromHandlePermanent(hWnd); - if (pWnd == NULL) - { - return ::DefWindowProc(hWnd, message, wParam, lParam); - } - else - { - return pWnd->WindowProc(message, wParam, lParam); - } -} - -/** - * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT CWndProc::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - if (nMsg == WM_COMMAND) - { - if (OnCommand(wParam, lParam)) - { - return 0; - } - } - else if (nMsg == WM_NOTIFY) - { - NMHDR* pNMHDR = reinterpret_cast(lParam); - if (pNMHDR->hwndFrom != NULL) - { - LRESULT lResult = 0; - if (OnNotify(wParam, lParam, &lResult)) - { - return lResult; - } - } - } - else if (nMsg == WM_NCDESTROY) - { - OnNcDestroy(wParam, lParam); - return 0; - } - return DefWindowProc(nMsg, wParam, lParam); -} - -/** - * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - * @retval TRUE アプリケーションがこのメッセージを処理した - */ -BOOL CWndProc::OnCommand(WPARAM wParam, LPARAM lParam) -{ - return FALSE; -} - -/** - * フレームワークは、イベントがコントロールに発生する場合や、コントロールが一部の種類の情報を要求するコントロールを親ウィンドウに通知するために、このメンバー関数を呼び出します - * @param[in] wParam メッセージがコントロールからそのメッセージを送信するコントロールを識別します - * @param[in] lParam 通知コードと追加情報を含む通知メッセージ (NMHDR) の構造体へのポインター - * @param[out] pResult メッセージが処理されたとき結果を格納するコードする LRESULT の変数へのポインター - * @retval TRUE メッセージを処理した - * @retval FALSE メッセージを処理しなかった - */ -BOOL CWndProc::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) -{ - return FALSE; -} - -/** - * Windows のウィンドウが破棄されるときに非クライアント領域が破棄されると、最後に呼び出されたメンバー関数は、フレームワークによって呼び出されます - * @param[in] wParam パラメタ - * @param[in] lParam パラメタ - */ -void CWndProc::OnNcDestroy(WPARAM wParam, LPARAM lParam) -{ - LONG_PTR pfnWndProc = ::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC); - DefWindowProc(WM_NCDESTROY, wParam, lParam); - if (::GetWindowLong(m_hWnd, GWLP_WNDPROC) == pfnWndProc) - { - if (m_pfnSuper != NULL) - { - ::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, reinterpret_cast(m_pfnSuper)); - m_pfnSuper = NULL; - } - } - Detach(); - - // call special post-cleanup routine - PostNcDestroy(); -} - -/** - * ウィンドウが破棄された後に既定の OnNcDestroy のメンバー関数によって呼び出されます - */ -void CWndProc::PostNcDestroy() -{ -} - -/** - * 既定のウィンドウ プロシージャを呼び出します - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージ依存の追加情報を指定します - * @param[in] lParam メッセージ依存の追加情報を指定します - * @return 送られたメッセージに依存します - */ -LRESULT CWndProc::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - if (m_pfnSuper != NULL) - { - return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam); - } - else - { - return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam); - } -} +/** + * @file WndProc.cpp + * @brief プロシージャ クラスの動作の定義を行います + */ + +#include +#include "WndProc.h" +#include +#define ASSERT assert /*!< assert */ + +//! 基底クラス名 +// static const TCHAR s_szClassName[] = TEXT("WndProcBase"); + +//! インスタンス +HINSTANCE CWndProc::sm_hInstance; +//! リソース +HINSTANCE CWndProc::sm_hResource; + +DWORD CWndProc::sm_dwThreadId; //!< 自分のスレッド ID +HHOOK CWndProc::sm_hHookOldCbtFilter = NULL; //!< フック フィルター +CWndProc* CWndProc::sm_pWndInit = NULL; //!< 初期化中のインスタンス +std::map* CWndProc::sm_pWndMap = NULL; //!< ウィンドウ マップ + +/** + * 初期化 + * @param[in] hInstance インスタンス + */ +void CWndProc::Initialize(HINSTANCE hInstance) +{ + sm_hInstance = hInstance; + sm_hResource = hInstance; + + sm_dwThreadId = ::GetCurrentThreadId(); + sm_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT, CbtFilterHook, NULL, sm_dwThreadId); + + sm_pWndMap = new std::map; + +#if 0 + WNDCLASS wc; + ZeroMemory(&wc, sizeof(wc)); + wc.style = CS_BYTEALIGNCLIENT | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; + wc.lpfnWndProc = WndProc; + wc.hInstance = hInstance; + wc.hIcon = ::LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON2)); + wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = static_cast(::GetStockObject(NULL_BRUSH)); + wc.lpszClassName = s_szClassName; + ::RegisterClass(&wc); +#endif // 0 +} + +/** + * 解放 + */ +void CWndProc::Deinitialize() +{ + if (sm_hHookOldCbtFilter != NULL) + { + ::UnhookWindowsHookEx(sm_hHookOldCbtFilter); + sm_hHookOldCbtFilter = NULL; + } + if(sm_pWndMap != NULL){ + delete sm_pWndMap; + sm_pWndMap = NULL; + } +} + +/** + * リソースの検索 + * @param[in] lpszName リソース ID + * @param[in] lpszType リソースの型へのポインタ + * @return インスタンス + */ +HINSTANCE CWndProc::FindResourceHandle(LPCTSTR lpszName, LPCTSTR lpszType) +{ + HINSTANCE hInst = GetResourceHandle(); + if ((hInst != GetInstanceHandle()) && (::FindResource(hInst, lpszName, lpszType) != NULL)) + { + return hInst; + } + return GetInstanceHandle(); +} + +/** + * コンストラクタ + */ +CWndProc::CWndProc() + : CWndBase(NULL) + , m_pfnSuper(NULL) +{ +} + +/** + * デストラクタ + */ +CWndProc::~CWndProc() +{ + DestroyWindow(); +} + +/** + * ウィンドウのハンドルが指定されている場合、CWndProc オブジェクトへのポインターを返します + * @param[in] hWnd ウィンドウ ハンドル + * @return ポインタ + */ +CWndProc* CWndProc::FromHandlePermanent(HWND hWnd) +{ + std::map* pMap = sm_pWndMap; + if (pMap) + { + std::map::iterator it = pMap->find(hWnd); + if (it != pMap->end()) + { + return it->second; + } + } + return NULL; +} + +/** + * Windows のウィンドウをアタッチします + * @param[in] hWndNew ウィンドウ ハンドル + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +BOOL CWndProc::Attach(HWND hWndNew) +{ + std::map* pMap = sm_pWndMap; + if ((hWndNew != NULL) && (pMap)) + { + (*pMap)[hWndNew] = this; + m_hWnd = hWndNew; + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * Windows のハンドルを切り離し、そのハンドルを返します + * @return ウィンドウ ハンドル + */ +HWND CWndProc::Detach() +{ + HWND hWnd = m_hWnd; + if (hWnd != NULL) + { + std::map* pMap = sm_pWndMap; + if (pMap) + { + std::map::iterator it = pMap->find(hWnd); + if (it != pMap->end()) + { + pMap->erase(it); + } + } + m_hWnd = NULL; + } + return hWnd; +} + +/** + * このメンバー関数はウィンドウがサブクラス化する前に、ほかのサブクラス化に必要な操作を許可するためにフレームワークから呼ばれます + */ +void CWndProc::PreSubclassWindow() +{ + // no default processing +} + +/** + * ウィンドウを動的サブクラス化し、CWnd オブジェクトに結び付けるためにこのメンバー関数を呼び出します + * @param[in] hWnd ウィンドウ ハンドル + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +BOOL CWndProc::SubclassWindow(HWND hWnd) +{ + if (!Attach(hWnd)) + { + return FALSE; + } + + PreSubclassWindow(); + + WNDPROC newWndProc = &CWndProc::WndProc; + WNDPROC oldWndProc = reinterpret_cast(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(newWndProc))); + if ((m_pfnSuper == NULL) && (oldWndProc != newWndProc)) + { + m_pfnSuper = oldWndProc; + } + return TRUE; +} + +/** + * コントロールを動的サブクラス化し、CWnd オブジェクトに結び付けるためにこのメンバー関数を呼び出します + * @param[in] nID コントロール ID + * @param[in] pParent コントロールの親 + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +BOOL CWndProc::SubclassDlgItem(UINT nID, CWndProc* pParent) +{ + HWND hWndControl = ::GetDlgItem(pParent->m_hWnd, nID); + if (hWndControl != NULL) + { + return SubclassWindow(hWndControl); + } + return FALSE; +} + +/** + * WndProc に元の値を設定して CWnd オブジェクトから HWND で識別されるウィンドウを切り離すために、このメンバー関数を呼び出します + * @return 非サブクラス化されたウィンドウへのハンドル + */ +HWND CWndProc::UnsubclassWindow() +{ + if (m_pfnSuper != NULL) + { + ::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, reinterpret_cast(m_pfnSuper)); + m_pfnSuper = NULL; + } + return Detach(); +} + +/** + * 指定されたウィンドウを作成し、それを CWndProc オブジェクトにアタッチします + * @param[in] dwExStyle 拡張ウィンドウ スタイル + * @param[in] lpszClassName 登録されているシステム ウィンドウ クラスの名前 + * @param[in] lpszWindowName ウィンドウの表示名 + * @param[in] dwStyle ウィンドウ スタイル + * @param[in] x 画面または親ウィンドウの左端からウィンドウの初期位置までの水平方向の距離 + * @param[in] y 画面または親ウィンドウの上端からウィンドウの初期位置までの垂直方向の距離 + * @param[in] nWidth ウィンドウの幅 (ピクセル単位) + * @param[in] nHeight ウィンドウの高さ (ピクセル単位) + * @param[in] hwndParent 親ウィンドウへのハンドル + * @param[in] nIDorHMenu ウィンドウ ID + * @param[in] lpParam ユーザー データ + * @retval TRUE 成功 + * @retval FALSE 失敗 + */ +BOOL CWndProc::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu, LPVOID lpParam) +{ + // 同じスレッドのみ許す + if (sm_dwThreadId != ::GetCurrentThreadId()) + { + PostNcDestroy(); + return FALSE; + } + + CREATESTRUCT cs; + cs.dwExStyle = dwExStyle; + cs.lpszClass = lpszClassName; + cs.lpszName = lpszWindowName; + cs.style = dwStyle; + cs.x = x; + cs.y = y; + cs.cx = nWidth; + cs.cy = nHeight; + cs.hwndParent = hwndParent; + cs.hMenu = nIDorHMenu; + cs.hInstance = sm_hInstance; + cs.lpCreateParams = lpParam; + + if (!PreCreateWindow(cs)) + { + PostNcDestroy(); + return FALSE; + } + + HookWindowCreate(this); + HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams); + if (!UnhookWindowCreate()) + { + PostNcDestroy(); + } + + return (hWnd != NULL) ? TRUE : FALSE; +} + +/** + * CWnd オブジェクトに結び付けられた Windows のウィンドウが作成される前に、フレームワークから呼び出されます + * @param[in,out] cs CREATESTRUCT の構造 + * @retval TRUE 継続 + */ +BOOL CWndProc::PreCreateWindow(CREATESTRUCT& cs) +{ + return TRUE; +} + +/** + * ウィンドウ作成をフック + * @param[in] pWnd ウィンドウ + */ +void CWndProc::HookWindowCreate(CWndProc* pWnd) +{ + // 同じスレッドのみ許す + ASSERT(sm_dwThreadId == ::GetCurrentThreadId()); + + if (sm_pWndInit == pWnd) + { + return; + } + + ASSERT(sm_hHookOldCbtFilter != NULL); + ASSERT(pWnd != NULL); + ASSERT(pWnd->m_hWnd == NULL); + ASSERT(sm_pWndInit == NULL); + sm_pWndInit = pWnd; +} + +/** + * ウィンドウ作成をアンフック + * @retval true フックした + * @retval false フックしなかった + */ +bool CWndProc::UnhookWindowCreate() +{ + if (sm_pWndInit != NULL) + { + sm_pWndInit = NULL; + return false; + } + return true; +} + +/** + * フック フィルタ + * @param[in] nCode コード + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @return リザルト コード + */ +LRESULT CALLBACK CWndProc::CbtFilterHook(int nCode, WPARAM wParam, LPARAM lParam) +{ + if (nCode == HCBT_CREATEWND) + { + HWND hWnd = reinterpret_cast(wParam); + LPCREATESTRUCT lpcs = reinterpret_cast(lParam)->lpcs; + + CWndProc* pWndInit = sm_pWndInit; + if (pWndInit != NULL) + { + pWndInit->Attach(hWnd); + pWndInit->PreSubclassWindow(); + + WNDPROC newWndProc = &CWndProc::WndProc; + WNDPROC oldWndProc = reinterpret_cast(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(newWndProc))); + if (oldWndProc != newWndProc) + { + pWndInit->m_pfnSuper = oldWndProc; + } + sm_pWndInit = NULL; + } + } + return ::CallNextHookEx(sm_hHookOldCbtFilter, nCode, wParam, lParam); +} + +/** + * CWndProc オブジェクトに関連付けられた Windows のウィンドウを破棄します + * @return ウィンドウが破棄された場合は 0 以外を返します。それ以外の場合は 0 を返します + */ +BOOL CWndProc::DestroyWindow() +{ + if (m_hWnd == NULL) + { + return FALSE; + } + + CWndProc* pWnd = FromHandlePermanent(m_hWnd); + + HWND oldhWnd = m_hWnd; + if (pWnd != NULL) + { + UnsubclassWindow(); // 兼 Detach(); + } + + const BOOL bResult = ::DestroyWindow(oldhWnd); + + return bResult; +} + +/** + * ウィンドウ プロシージャ + * @param[in] hWnd ウィンドウ ハンドル + * @param[in] message 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CALLBACK CWndProc::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + CWndProc* pWnd = FromHandlePermanent(hWnd); + if (pWnd == NULL) + { + return ::DefWindowProc(hWnd, message, wParam, lParam); + } + else + { + return pWnd->WindowProc(message, wParam, lParam); + } +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CWndProc::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + if (nMsg == WM_COMMAND) + { + if (OnCommand(wParam, lParam)) + { + return 0; + } + } + else if (nMsg == WM_NOTIFY) + { + NMHDR* pNMHDR = reinterpret_cast(lParam); + if (pNMHDR->hwndFrom != NULL) + { + LRESULT lResult = 0; + if (OnNotify(wParam, lParam, &lResult)) + { + return lResult; + } + } + } + else if (nMsg == WM_NCDESTROY) + { + OnNcDestroy(wParam, lParam); + return 0; + } + return DefWindowProc(nMsg, wParam, lParam); +} + +/** + * ユーザーがメニューの項目を選択したときに、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + * @retval TRUE アプリケーションがこのメッセージを処理した + */ +BOOL CWndProc::OnCommand(WPARAM wParam, LPARAM lParam) +{ + return FALSE; +} + +/** + * フレームワークは、イベントがコントロールに発生する場合や、コントロールが一部の種類の情報を要求するコントロールを親ウィンドウに通知するために、このメンバー関数を呼び出します + * @param[in] wParam メッセージがコントロールからそのメッセージを送信するコントロールを識別します + * @param[in] lParam 通知コードと追加情報を含む通知メッセージ (NMHDR) の構造体へのポインター + * @param[out] pResult メッセージが処理されたとき結果を格納するコードする LRESULT の変数へのポインター + * @retval TRUE メッセージを処理した + * @retval FALSE メッセージを処理しなかった + */ +BOOL CWndProc::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) +{ + return FALSE; +} + +/** + * Windows のウィンドウが破棄されるときに非クライアント領域が破棄されると、最後に呼び出されたメンバー関数は、フレームワークによって呼び出されます + * @param[in] wParam パラメタ + * @param[in] lParam パラメタ + */ +void CWndProc::OnNcDestroy(WPARAM wParam, LPARAM lParam) +{ + LONG_PTR pfnWndProc = ::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC); + DefWindowProc(WM_NCDESTROY, wParam, lParam); + if (::GetWindowLong(m_hWnd, GWLP_WNDPROC) == pfnWndProc) + { + if (m_pfnSuper != NULL) + { + ::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, reinterpret_cast(m_pfnSuper)); + m_pfnSuper = NULL; + } + } + Detach(); + + // call special post-cleanup routine + PostNcDestroy(); +} + +/** + * ウィンドウが破棄された後に既定の OnNcDestroy のメンバー関数によって呼び出されます + */ +void CWndProc::PostNcDestroy() +{ +} + +/** + * 既定のウィンドウ プロシージャを呼び出します + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージ依存の追加情報を指定します + * @param[in] lParam メッセージ依存の追加情報を指定します + * @return 送られたメッセージに依存します + */ +LRESULT CWndProc::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + if (m_pfnSuper != NULL) + { + return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam); + } + else + { + return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam); + } +} diff --git a/windows/misc/WndProc.h b/windows/misc/WndProc.h old mode 100755 new mode 100644 index 077d83b9..814bec80 --- a/windows/misc/WndProc.h +++ b/windows/misc/WndProc.h @@ -1,111 +1,111 @@ -/** - * @file WndProc.h - * @brief プロシージャ クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include "WndBase.h" - -/** - * @brief プロシージャ クラス - */ -class CWndProc : public CWndBase -{ -public: - static void Initialize(HINSTANCE hInstance); - static void Deinitialize(); - static HINSTANCE GetInstanceHandle(); - static void SetResourceHandle(HINSTANCE hInstance); - static HINSTANCE GetResourceHandle(); - static HINSTANCE FindResourceHandle(LPCTSTR lpszName, LPCTSTR lpszType); - - CWndProc(); - virtual ~CWndProc(); - - operator HWND() const; - HWND GetSafeHwnd() const; - static CWndProc* FromHandlePermanent(HWND hWnd); - BOOL Attach(HWND hWndNew); - HWND Detach(); - - virtual void PreSubclassWindow(); - BOOL SubclassWindow(HWND hWnd); - BOOL SubclassDlgItem(UINT nID, CWndProc* pParent); - HWND UnsubclassWindow(); - - BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu, LPVOID lpParam = NULL); - virtual BOOL DestroyWindow(); - virtual BOOL PreCreateWindow(CREATESTRUCT& cs); - -protected: - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); - virtual void OnNcDestroy(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - LRESULT DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - virtual void PostNcDestroy(); - -protected: - static HINSTANCE sm_hInstance; //!< インスタンス ハンドル - static HINSTANCE sm_hResource; //!< リソース ハンドル - static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - - static void HookWindowCreate(CWndProc* pWnd); - static bool UnhookWindowCreate(); - -private: - static DWORD sm_dwThreadId; //!< 自分のスレッド ID - static HHOOK sm_hHookOldCbtFilter; //!< フック フィルター - static CWndProc* sm_pWndInit; //!< 初期化中のインスタンス - static std::map* sm_pWndMap; //!< ウィンドウ マップ - WNDPROC m_pfnSuper; //!< 下位プロシージャ - static LRESULT CALLBACK CbtFilterHook(int nCode, WPARAM wParam, LPARAM lParam); -}; - -/** - * インスタンス ハンドルを取得 - * @return インスタンス ハンドル - */ -inline HINSTANCE CWndProc::GetInstanceHandle() -{ - return sm_hInstance; -} - -/** - * リソース ハンドルを設定 - * @param[in] hInstance リソース ハンドル - */ -inline void CWndProc::SetResourceHandle(HINSTANCE hInstance) -{ - sm_hResource = hInstance; -} - -/** - * リソース ハンドルを取得 - * @return リソース ハンドル - */ -inline HINSTANCE CWndProc::GetResourceHandle() -{ - return sm_hResource; -} - -/** - * HWND オペレータ - * @return HWND - */ -inline CWndProc::operator HWND() const -{ - return m_hWnd; -} - -/** - * ウィンドウのウィンドウ ハンドルを返します - * @return ウィンドウ ハンドル - */ -inline HWND CWndProc::GetSafeHwnd() const -{ - return (this != NULL) ? m_hWnd : NULL; -} - +/** + * @file WndProc.h + * @brief プロシージャ クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include "WndBase.h" + +/** + * @brief プロシージャ クラス + */ +class CWndProc : public CWndBase +{ +public: + static void Initialize(HINSTANCE hInstance); + static void Deinitialize(); + static HINSTANCE GetInstanceHandle(); + static void SetResourceHandle(HINSTANCE hInstance); + static HINSTANCE GetResourceHandle(); + static HINSTANCE FindResourceHandle(LPCTSTR lpszName, LPCTSTR lpszType); + + CWndProc(); + virtual ~CWndProc(); + + operator HWND() const; + HWND GetSafeHwnd() const; + static CWndProc* FromHandlePermanent(HWND hWnd); + BOOL Attach(HWND hWndNew); + HWND Detach(); + + virtual void PreSubclassWindow(); + BOOL SubclassWindow(HWND hWnd); + BOOL SubclassDlgItem(UINT nID, CWndProc* pParent); + HWND UnsubclassWindow(); + + BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu, LPVOID lpParam = NULL); + virtual BOOL DestroyWindow(); + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + +protected: + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + virtual void OnNcDestroy(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + LRESULT DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + virtual void PostNcDestroy(); + +protected: + static HINSTANCE sm_hInstance; //!< インスタンス ハンドル + static HINSTANCE sm_hResource; //!< リソース ハンドル + static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + + static void HookWindowCreate(CWndProc* pWnd); + static bool UnhookWindowCreate(); + +private: + static DWORD sm_dwThreadId; //!< 自分のスレッド ID + static HHOOK sm_hHookOldCbtFilter; //!< フック フィルター + static CWndProc* sm_pWndInit; //!< 初期化中のインスタンス + static std::map* sm_pWndMap; //!< ウィンドウ マップ + WNDPROC m_pfnSuper; //!< 下位プロシージャ + static LRESULT CALLBACK CbtFilterHook(int nCode, WPARAM wParam, LPARAM lParam); +}; + +/** + * インスタンス ハンドルを取得 + * @return インスタンス ハンドル + */ +inline HINSTANCE CWndProc::GetInstanceHandle() +{ + return sm_hInstance; +} + +/** + * リソース ハンドルを設定 + * @param[in] hInstance リソース ハンドル + */ +inline void CWndProc::SetResourceHandle(HINSTANCE hInstance) +{ + sm_hResource = hInstance; +} + +/** + * リソース ハンドルを取得 + * @return リソース ハンドル + */ +inline HINSTANCE CWndProc::GetResourceHandle() +{ + return sm_hResource; +} + +/** + * HWND オペレータ + * @return HWND + */ +inline CWndProc::operator HWND() const +{ + return m_hWnd; +} + +/** + * ウィンドウのウィンドウ ハンドルを返します + * @return ウィンドウ ハンドル + */ +inline HWND CWndProc::GetSafeHwnd() const +{ + return (this != NULL) ? m_hWnd : NULL; +} + diff --git a/windows/misc/extrom.cpp b/windows/misc/extrom.cpp old mode 100755 new mode 100644 index d57690b7..c7ffd39c --- a/windows/misc/extrom.cpp +++ b/windows/misc/extrom.cpp @@ -1,239 +1,239 @@ -/** - * @file extrom.cpp - * @brief EXTROM リソース クラスの動作の定義を行います - */ - -#include -#include "ExtRom.h" -#include -#include "WndProc.h" -#include -#include - - -//! リソース名 -static const TCHAR s_szExtRom[] = TEXT("EXTROM"); - -/** - * コンストラクタ - */ -CExtRom::CExtRom() - : m_hGlobal(NULL) - , m_lpRes(NULL) - , m_nSize(0) - , m_nPointer(0) -{ -} - -/** - * デストラクタ - */ -CExtRom::~CExtRom() -{ - Close(); -} - -/** - * オープン - * @param[in] lpFilename ファイル名 - * @retval true 成功 - * @retval false 失敗 - */ -bool CExtRom::Open(LPCTSTR lpFilename) -{ - Close(); - - HINSTANCE hInstance = CWndProc::FindResourceHandle(lpFilename, s_szExtRom); - HRSRC hRsrc = ::FindResource(hInstance, lpFilename, s_szExtRom); - if (hRsrc == NULL) - { - return false; - } - - m_hGlobal = ::LoadResource(hInstance, hRsrc); - m_lpRes = ::LockResource(m_hGlobal); - m_nSize = ::SizeofResource(hInstance, hRsrc); - m_nPointer = 0; - return true; -} - -/** - * オープン - * @param[in] lpFilename ファイル名 - * @param[in] extlen ファイル名の後ろ何文字を拡張子扱いするか - * @retval true 成功 - * @retval false 失敗 - */ -bool CExtRom::Open(LPCTSTR lpFilename, DWORD extlen) -{ - TCHAR tmpfilesname[MAX_PATH]; - TCHAR tmpfilesname2[MAX_PATH]; - FILEH fh; - - Close(); - - _tcscpy(tmpfilesname, lpFilename); - int fnamelen = (int)_tcslen(tmpfilesname); - for (int i=0; i<(int)extlen+1; i++) - { - tmpfilesname[fnamelen+1-i] = tmpfilesname[fnamelen+1-i-1]; - } - tmpfilesname[fnamelen-extlen] = '.'; - getbiospath(tmpfilesname2, tmpfilesname, NELEMENTS(tmpfilesname2)); - fh = file_open_rb(tmpfilesname2); - if (fh != FILEH_INVALID) - { - m_nSize = (UINT)file_getsize(fh); - m_lpRes = malloc(m_nSize); - file_read(fh, m_lpRes, m_nSize); - m_hGlobal = NULL; - m_nPointer = 0; - m_isfile = 1; - file_close(fh); - } - else - { - HINSTANCE hInstance = CWndProc::FindResourceHandle(lpFilename, s_szExtRom); - HRSRC hRsrc = ::FindResource(hInstance, lpFilename, s_szExtRom); - if (hRsrc == NULL) - { - return false; - } - - m_hGlobal = ::LoadResource(hInstance, hRsrc); - m_lpRes = ::LockResource(m_hGlobal); - m_nSize = ::SizeofResource(hInstance, hRsrc); - m_nPointer = 0; - } - - return true; -} - -/** - * オープン - * @param[in] lpFilename ファイル名 - * @param[in] lpExt 外部ファイルの場合の拡張子 - * @retval true 成功 - * @retval false 失敗 - */ -bool CExtRom::Open(LPCTSTR lpFilename, LPCTSTR lpExt) -{ - TCHAR tmpfilesname[MAX_PATH]; - TCHAR tmpfilesname2[MAX_PATH]; - FILEH fh; - - Close(); - - _tcscpy(tmpfilesname, lpFilename); - _tcscat(tmpfilesname, lpExt); - getbiospath(tmpfilesname2, tmpfilesname, NELEMENTS(tmpfilesname2)); - fh = file_open_rb(tmpfilesname2); - if (fh != FILEH_INVALID) - { - m_nSize = (UINT)file_getsize(fh); - m_lpRes = malloc(m_nSize); - file_read(fh, m_lpRes, m_nSize); - m_hGlobal = NULL; - m_nPointer = 0; - m_isfile = 1; - file_close(fh); - } - else - { - HINSTANCE hInstance = CWndProc::FindResourceHandle(lpFilename, s_szExtRom); - HRSRC hRsrc = ::FindResource(hInstance, lpFilename, s_szExtRom); - if (hRsrc == NULL) - { - return false; - } - - m_hGlobal = ::LoadResource(hInstance, hRsrc); - m_lpRes = ::LockResource(m_hGlobal); - m_nSize = ::SizeofResource(hInstance, hRsrc); - m_nPointer = 0; - } - - return true; -} - -/** - * クローズ - */ -void CExtRom::Close() -{ - if (m_isfile) - { - if (m_lpRes) - { - free(m_lpRes); - } - m_isfile = 0; - } - else - { - if (m_hGlobal) - { - ::FreeResource(m_hGlobal); - m_hGlobal = NULL; - } - } - m_lpRes = NULL; - m_nSize = 0; - m_nPointer = 0; -} - -/** - * 読み込み - * @param[out] lpBuffer バッファ - * @param[out] cbBuffer バッファ長 - * @return サイズ - */ -UINT CExtRom::Read(LPVOID lpBuffer, UINT cbBuffer) -{ - UINT nLength = m_nSize - m_nPointer; - nLength = min(nLength, cbBuffer); - if (nLength) - { - if (lpBuffer) - { - CopyMemory(lpBuffer, static_cast(m_lpRes) + m_nPointer, nLength); - } - m_nPointer += nLength; - } - return nLength; -} - -/** - * シーク - * @param[in] lDistanceToMove ファイルポインタの移動バイト数 - * @param[in] dwMoveMethod ファイルポインタを移動するための開始点(基準点)を指定します - * @return 現在の位置 - */ -LONG CExtRom::Seek(LONG lDistanceToMove, DWORD dwMoveMethod) -{ - switch (dwMoveMethod) - { - case FILE_BEGIN: - default: - break; - - case FILE_CURRENT: - lDistanceToMove += m_nPointer; - break; - - case FILE_END: - lDistanceToMove += m_nSize; - break; - } - - if (lDistanceToMove < 0) - { - lDistanceToMove = 0; - } - else if (static_cast(lDistanceToMove) > m_nSize) - { - lDistanceToMove = m_nSize; - } - m_nPointer = lDistanceToMove; - return lDistanceToMove; -} +/** + * @file extrom.cpp + * @brief EXTROM リソース クラスの動作の定義を行います + */ + +#include +#include "ExtRom.h" +#include +#include "WndProc.h" +#include +#include + + +//! リソース名 +static const TCHAR s_szExtRom[] = TEXT("EXTROM"); + +/** + * コンストラクタ + */ +CExtRom::CExtRom() + : m_hGlobal(NULL) + , m_lpRes(NULL) + , m_nSize(0) + , m_nPointer(0) +{ +} + +/** + * デストラクタ + */ +CExtRom::~CExtRom() +{ + Close(); +} + +/** + * オープン + * @param[in] lpFilename ファイル名 + * @retval true 成功 + * @retval false 失敗 + */ +bool CExtRom::Open(LPCTSTR lpFilename) +{ + Close(); + + HINSTANCE hInstance = CWndProc::FindResourceHandle(lpFilename, s_szExtRom); + HRSRC hRsrc = ::FindResource(hInstance, lpFilename, s_szExtRom); + if (hRsrc == NULL) + { + return false; + } + + m_hGlobal = ::LoadResource(hInstance, hRsrc); + m_lpRes = ::LockResource(m_hGlobal); + m_nSize = ::SizeofResource(hInstance, hRsrc); + m_nPointer = 0; + return true; +} + +/** + * オープン + * @param[in] lpFilename ファイル名 + * @param[in] extlen ファイル名の後ろ何文字を拡張子扱いするか + * @retval true 成功 + * @retval false 失敗 + */ +bool CExtRom::Open(LPCTSTR lpFilename, DWORD extlen) +{ + TCHAR tmpfilesname[MAX_PATH]; + TCHAR tmpfilesname2[MAX_PATH]; + FILEH fh; + + Close(); + + _tcscpy(tmpfilesname, lpFilename); + int fnamelen = (int)_tcslen(tmpfilesname); + for (int i=0; i<(int)extlen+1; i++) + { + tmpfilesname[fnamelen+1-i] = tmpfilesname[fnamelen+1-i-1]; + } + tmpfilesname[fnamelen-extlen] = '.'; + getbiospath(tmpfilesname2, tmpfilesname, NELEMENTS(tmpfilesname2)); + fh = file_open_rb(tmpfilesname2); + if (fh != FILEH_INVALID) + { + m_nSize = (UINT)file_getsize(fh); + m_lpRes = malloc(m_nSize); + file_read(fh, m_lpRes, m_nSize); + m_hGlobal = NULL; + m_nPointer = 0; + m_isfile = 1; + file_close(fh); + } + else + { + HINSTANCE hInstance = CWndProc::FindResourceHandle(lpFilename, s_szExtRom); + HRSRC hRsrc = ::FindResource(hInstance, lpFilename, s_szExtRom); + if (hRsrc == NULL) + { + return false; + } + + m_hGlobal = ::LoadResource(hInstance, hRsrc); + m_lpRes = ::LockResource(m_hGlobal); + m_nSize = ::SizeofResource(hInstance, hRsrc); + m_nPointer = 0; + } + + return true; +} + +/** + * オープン + * @param[in] lpFilename ファイル名 + * @param[in] lpExt 外部ファイルの場合の拡張子 + * @retval true 成功 + * @retval false 失敗 + */ +bool CExtRom::Open(LPCTSTR lpFilename, LPCTSTR lpExt) +{ + TCHAR tmpfilesname[MAX_PATH]; + TCHAR tmpfilesname2[MAX_PATH]; + FILEH fh; + + Close(); + + _tcscpy(tmpfilesname, lpFilename); + _tcscat(tmpfilesname, lpExt); + getbiospath(tmpfilesname2, tmpfilesname, NELEMENTS(tmpfilesname2)); + fh = file_open_rb(tmpfilesname2); + if (fh != FILEH_INVALID) + { + m_nSize = (UINT)file_getsize(fh); + m_lpRes = malloc(m_nSize); + file_read(fh, m_lpRes, m_nSize); + m_hGlobal = NULL; + m_nPointer = 0; + m_isfile = 1; + file_close(fh); + } + else + { + HINSTANCE hInstance = CWndProc::FindResourceHandle(lpFilename, s_szExtRom); + HRSRC hRsrc = ::FindResource(hInstance, lpFilename, s_szExtRom); + if (hRsrc == NULL) + { + return false; + } + + m_hGlobal = ::LoadResource(hInstance, hRsrc); + m_lpRes = ::LockResource(m_hGlobal); + m_nSize = ::SizeofResource(hInstance, hRsrc); + m_nPointer = 0; + } + + return true; +} + +/** + * クローズ + */ +void CExtRom::Close() +{ + if (m_isfile) + { + if (m_lpRes) + { + free(m_lpRes); + } + m_isfile = 0; + } + else + { + if (m_hGlobal) + { + ::FreeResource(m_hGlobal); + m_hGlobal = NULL; + } + } + m_lpRes = NULL; + m_nSize = 0; + m_nPointer = 0; +} + +/** + * 読み込み + * @param[out] lpBuffer バッファ + * @param[out] cbBuffer バッファ長 + * @return サイズ + */ +UINT CExtRom::Read(LPVOID lpBuffer, UINT cbBuffer) +{ + UINT nLength = m_nSize - m_nPointer; + nLength = min(nLength, cbBuffer); + if (nLength) + { + if (lpBuffer) + { + CopyMemory(lpBuffer, static_cast(m_lpRes) + m_nPointer, nLength); + } + m_nPointer += nLength; + } + return nLength; +} + +/** + * シーク + * @param[in] lDistanceToMove ファイルポインタの移動バイト数 + * @param[in] dwMoveMethod ファイルポインタを移動するための開始点(基準点)を指定します + * @return 現在の位置 + */ +LONG CExtRom::Seek(LONG lDistanceToMove, DWORD dwMoveMethod) +{ + switch (dwMoveMethod) + { + case FILE_BEGIN: + default: + break; + + case FILE_CURRENT: + lDistanceToMove += m_nPointer; + break; + + case FILE_END: + lDistanceToMove += m_nSize; + break; + } + + if (lDistanceToMove < 0) + { + lDistanceToMove = 0; + } + else if (static_cast(lDistanceToMove) > m_nSize) + { + lDistanceToMove = m_nSize; + } + m_nPointer = lDistanceToMove; + return lDistanceToMove; +} diff --git a/windows/misc/extrom.h b/windows/misc/extrom.h old mode 100755 new mode 100644 index 1568f5c8..a23f7f74 --- a/windows/misc/extrom.h +++ b/windows/misc/extrom.h @@ -1,29 +1,29 @@ -/** - * @file extrom.h - * @brief EXTROM リソース クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -/** - * @brief EXTROM リソース クラス - */ -class CExtRom -{ -public: - CExtRom(); - ~CExtRom(); - bool Open(LPCTSTR lpFilename); - bool Open(LPCTSTR lpFilename, DWORD extlen); - bool Open(LPCTSTR lpFilename, LPCTSTR lpExt); - void Close(); - UINT Read(LPVOID lpBuffer, UINT cbBuffer); - LONG Seek(LONG lDistanceToMove, DWORD dwMoveMethod); - -private: - HGLOBAL m_hGlobal; //!< ハンドル - LPVOID m_lpRes; //!< リソース - UINT m_nSize; //!< サイズ - UINT m_nPointer; //!< ポインタ - UINT m_isfile; //!< 外部ファイルかどうか -}; +/** + * @file extrom.h + * @brief EXTROM リソース クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +/** + * @brief EXTROM リソース クラス + */ +class CExtRom +{ +public: + CExtRom(); + ~CExtRom(); + bool Open(LPCTSTR lpFilename); + bool Open(LPCTSTR lpFilename, DWORD extlen); + bool Open(LPCTSTR lpFilename, LPCTSTR lpExt); + void Close(); + UINT Read(LPVOID lpBuffer, UINT cbBuffer); + LONG Seek(LONG lDistanceToMove, DWORD dwMoveMethod); + +private: + HGLOBAL m_hGlobal; //!< ハンドル + LPVOID m_lpRes; //!< リソース + UINT m_nSize; //!< サイズ + UINT m_nPointer; //!< ポインタ + UINT m_isfile; //!< 外部ファイルかどうか +}; diff --git a/windows/misc/guard.h b/windows/misc/guard.h old mode 100755 new mode 100644 index d9cf2c64..0b401cb4 --- a/windows/misc/guard.h +++ b/windows/misc/guard.h @@ -1,28 +1,28 @@ -/*! - * @file guard.h - * @brief クリティカル セクション クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -/*! - * @brief クリティカル セクション クラス - */ -class CGuard -{ -public: - /*! コンストラクタ */ - CGuard() { ::InitializeCriticalSection(&m_cs); } - - /*! デストラクタ */ - ~CGuard() { ::DeleteCriticalSection(&m_cs); } - - /*! クリティカル セクション開始 */ - void Enter() { ::EnterCriticalSection(&m_cs); } - - /*! クリティカル セクション終了 */ - void Leave() { ::LeaveCriticalSection(&m_cs); } - -private: - CRITICAL_SECTION m_cs; //!< クリティカル セクション情報 -}; +/*! + * @file guard.h + * @brief クリティカル セクション クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +/*! + * @brief クリティカル セクション クラス + */ +class CGuard +{ +public: + /*! コンストラクタ */ + CGuard() { ::InitializeCriticalSection(&m_cs); } + + /*! デストラクタ */ + ~CGuard() { ::DeleteCriticalSection(&m_cs); } + + /*! クリティカル セクション開始 */ + void Enter() { ::EnterCriticalSection(&m_cs); } + + /*! クリティカル セクション終了 */ + void Leave() { ::LeaveCriticalSection(&m_cs); } + +private: + CRITICAL_SECTION m_cs; //!< クリティカル セクション情報 +}; diff --git a/windows/misc/threadbase.cpp b/windows/misc/threadbase.cpp old mode 100755 new mode 100644 index c34fb5b3..36881e73 --- a/windows/misc/threadbase.cpp +++ b/windows/misc/threadbase.cpp @@ -1,103 +1,103 @@ -/*! - * @file threadbase.cpp - * @brief スレッド基底クラスの動作の定義を行います - */ - -#include -#include "threadbase.h" -#include - -/*! - * @brief コンストラクタ - */ -CThreadBase::CThreadBase() - : m_hThread(INVALID_HANDLE_VALUE) - , m_dwThreadId(0) - , m_bAbort(false) - , m_bDone(false) - , m_nStackSize(0) -{ -} - -/*! - * @brief デストラクタ - */ -CThreadBase::~CThreadBase() -{ - Stop(); -} - -/*! - * @brief スレッド開始 - * - * @retval true 成功 - */ -bool CThreadBase::Start() -{ - if (m_hThread != INVALID_HANDLE_VALUE) - { - return false; - } - - m_bAbort = false; - m_bDone = false; - //DWORD dwThreadId = 0; - unsigned int dwThreadId = 0; - //HANDLE hThread = ::CreateThread(NULL, m_nStackSize, &ThreadProc, this, 0, &dwThreadId); - HANDLE hThread = (HANDLE)_beginthreadex(NULL, m_nStackSize, &ThreadProc, this, 0, &dwThreadId); - if (hThread == INVALID_HANDLE_VALUE) - { - return false; - } - - m_hThread = hThread; - m_dwThreadId = dwThreadId; - return true; -} - -/*! - * @brief スレッド終了 - * - * @retval true 成功 - */ -void CThreadBase::Stop() -{ - if (m_hThread != INVALID_HANDLE_VALUE) - { - m_bAbort = true; - ::WaitForSingleObject(m_hThread, INFINITE); - ::CloseHandle(m_hThread); - m_hThread = INVALID_HANDLE_VALUE; - } -} - -/*! - * @brief スレッド再開 - * - * @retval true 成功 - */ -bool CThreadBase::Restart() -{ - if ((m_hThread != INVALID_HANDLE_VALUE) && (m_bDone)) - { - Stop(); - } - return Start(); -} - -/*! - * スレッド処理 - * @param[in] pParam this ポインタ - * @retval 0 常に0 - */ -//DWORD __stdcall CThreadBase::ThreadProc(LPVOID pParam) -unsigned int __stdcall CThreadBase::ThreadProc(LPVOID pParam) -{ - CThreadBase& obj = *(static_cast(pParam)); - while ((!obj.m_bAbort) && (obj.Task())) - { - } - - obj.m_bDone = true; - return 0; -} +/*! + * @file threadbase.cpp + * @brief スレッド基底クラスの動作の定義を行います + */ + +#include +#include "threadbase.h" +#include + +/*! + * @brief コンストラクタ + */ +CThreadBase::CThreadBase() + : m_hThread(INVALID_HANDLE_VALUE) + , m_dwThreadId(0) + , m_bAbort(false) + , m_bDone(false) + , m_nStackSize(0) +{ +} + +/*! + * @brief デストラクタ + */ +CThreadBase::~CThreadBase() +{ + Stop(); +} + +/*! + * @brief スレッド開始 + * + * @retval true 成功 + */ +bool CThreadBase::Start() +{ + if (m_hThread != INVALID_HANDLE_VALUE) + { + return false; + } + + m_bAbort = false; + m_bDone = false; + //DWORD dwThreadId = 0; + unsigned int dwThreadId = 0; + //HANDLE hThread = ::CreateThread(NULL, m_nStackSize, &ThreadProc, this, 0, &dwThreadId); + HANDLE hThread = (HANDLE)_beginthreadex(NULL, m_nStackSize, &ThreadProc, this, 0, &dwThreadId); + if (hThread == INVALID_HANDLE_VALUE) + { + return false; + } + + m_hThread = hThread; + m_dwThreadId = dwThreadId; + return true; +} + +/*! + * @brief スレッド終了 + * + * @retval true 成功 + */ +void CThreadBase::Stop() +{ + if (m_hThread != INVALID_HANDLE_VALUE) + { + m_bAbort = true; + ::WaitForSingleObject(m_hThread, INFINITE); + ::CloseHandle(m_hThread); + m_hThread = INVALID_HANDLE_VALUE; + } +} + +/*! + * @brief スレッド再開 + * + * @retval true 成功 + */ +bool CThreadBase::Restart() +{ + if ((m_hThread != INVALID_HANDLE_VALUE) && (m_bDone)) + { + Stop(); + } + return Start(); +} + +/*! + * スレッド処理 + * @param[in] pParam this ポインタ + * @retval 0 常に0 + */ +//DWORD __stdcall CThreadBase::ThreadProc(LPVOID pParam) +unsigned int __stdcall CThreadBase::ThreadProc(LPVOID pParam) +{ + CThreadBase& obj = *(static_cast(pParam)); + while ((!obj.m_bAbort) && (obj.Task())) + { + } + + obj.m_bDone = true; + return 0; +} diff --git a/windows/misc/threadbase.h b/windows/misc/threadbase.h old mode 100755 new mode 100644 index fede87ca..d9f97a87 --- a/windows/misc/threadbase.h +++ b/windows/misc/threadbase.h @@ -1,52 +1,52 @@ -/*! - * @file threadbase.h - * @brief スレッド基底クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -/*! - * @brief スレッド基底クラス - */ -class CThreadBase -{ -public: - CThreadBase(); - virtual ~CThreadBase(); - - bool Start(); - void Stop(); - bool Restart(); - void SetStackSize(unsigned int nStackSize); - static void Delay(unsigned int usec); - -protected: - virtual bool Task() = 0; //!< スレッド タスク - -private: - HANDLE m_hThread; //!< スレッド ハンドル - DWORD m_dwThreadId; //!< スレッド ID - bool m_bAbort; //!< 中断フラグ - bool m_bDone; //!< 完了フラグ - unsigned int m_nStackSize; //!< スタック サイズ - //static DWORD __stdcall ThreadProc(LPVOID pParam); - static unsigned int __stdcall ThreadProc(LPVOID pParam); -}; - -/** - * スタック サイズの設定 - * @param[in] nStackSize スタック サイズ - */ -inline void CThreadBase::SetStackSize(unsigned int nStackSize) -{ - m_nStackSize = nStackSize; -} - -/** - * スリープ - * @param[in] usec マイクロ秒 - */ -inline void CThreadBase::Delay(unsigned int usec) -{ - ::Sleep((usec + 999) / 1000); -} +/*! + * @file threadbase.h + * @brief スレッド基底クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +/*! + * @brief スレッド基底クラス + */ +class CThreadBase +{ +public: + CThreadBase(); + virtual ~CThreadBase(); + + bool Start(); + void Stop(); + bool Restart(); + void SetStackSize(unsigned int nStackSize); + static void Delay(unsigned int usec); + +protected: + virtual bool Task() = 0; //!< スレッド タスク + +private: + HANDLE m_hThread; //!< スレッド ハンドル + DWORD m_dwThreadId; //!< スレッド ID + bool m_bAbort; //!< 中断フラグ + bool m_bDone; //!< 完了フラグ + unsigned int m_nStackSize; //!< スタック サイズ + //static DWORD __stdcall ThreadProc(LPVOID pParam); + static unsigned int __stdcall ThreadProc(LPVOID pParam); +}; + +/** + * スタック サイズの設定 + * @param[in] nStackSize スタック サイズ + */ +inline void CThreadBase::SetStackSize(unsigned int nStackSize) +{ + m_nStackSize = nStackSize; +} + +/** + * スリープ + * @param[in] usec マイクロ秒 + */ +inline void CThreadBase::Delay(unsigned int usec) +{ + ::Sleep((usec + 999) / 1000); +} diff --git a/windows/misc/tickcounter.cpp b/windows/misc/tickcounter.cpp old mode 100755 new mode 100644 index de1d0f15..244d0da1 --- a/windows/misc/tickcounter.cpp +++ b/windows/misc/tickcounter.cpp @@ -1,206 +1,206 @@ -/** - * @file tickcounter.cpp - * @brief TICK カウンタの動作の定義を行います - */ - -#include -#include "tickcounter.h" - -/** - * @brief TICK カウンター クラス - */ -class TickCounter -{ -public: - TickCounter(); - DWORD Get(); - LARGE_INTEGER Get_rawclock(); - LARGE_INTEGER Get_clockpersec(); - void SetMode(int mode); - int GetMode(); - -private: - LARGE_INTEGER m_nFreq; //!< 周波数 - LARGE_INTEGER m_nLast; //!< 最後のカウンタ - DWORD m_dwLastTick; //!< 最後の TICK - int m_mode; //!< カウンタモード -}; - -/** - * コンストラクタ - */ -TickCounter::TickCounter() -{ - m_nFreq.QuadPart = 0; - ::QueryPerformanceFrequency(&m_nFreq); - if (m_nFreq.QuadPart) - { - ::QueryPerformanceCounter(&m_nLast); - m_mode = TCMODE_PERFORMANCECOUNTER; - } - else - { - m_mode = TCMODE_TIMEGETTIME; - } - m_dwLastTick = ::timeGetTime(); - //m_dwLastTick = ::GetTickCount(); -} - -/** - * TICK を得る - * @return TICK - */ -DWORD TickCounter::Get() -{ - switch(m_mode) - { - case TCMODE_GETTICKCOUNT: - return ::GetTickCount(); - - case TCMODE_TIMEGETTIME: - return ::timeGetTime(); - - case TCMODE_PERFORMANCECOUNTER: - { - LARGE_INTEGER nNow; - ::QueryPerformanceCounter(&nNow); - const ULONGLONG nPast = nNow.QuadPart - m_nLast.QuadPart; - - const DWORD dwTick = static_cast((nPast * 1000U) / m_nFreq.QuadPart); - const DWORD dwRet = m_dwLastTick + dwTick; - if (dwTick >= 1000) - { - const DWORD dwSeconds = dwTick / 1000; - m_nLast.QuadPart += m_nFreq.QuadPart * dwSeconds; - m_dwLastTick += dwSeconds * 1000; - } - return dwRet; - } - } - return ::GetTickCount(); -} - -LARGE_INTEGER TickCounter::Get_rawclock() -{ - LARGE_INTEGER nNow = {0}; - switch(m_mode) - { - case TCMODE_GETTICKCOUNT: - nNow.LowPart = ::GetTickCount(); - return nNow; - - case TCMODE_TIMEGETTIME: - nNow.LowPart = ::timeGetTime(); - return nNow; - - case TCMODE_PERFORMANCECOUNTER: - { - ::QueryPerformanceCounter(&nNow); - return nNow; - } - } - nNow.LowPart = ::GetTickCount(); - return nNow; -} -LARGE_INTEGER TickCounter::Get_clockpersec() -{ - LARGE_INTEGER nClk = {0}; - switch(m_mode) - { - case TCMODE_GETTICKCOUNT: - nClk.LowPart = 1000; - return nClk; - - case TCMODE_TIMEGETTIME: - nClk.LowPart = 1000; - return nClk; - - case TCMODE_PERFORMANCECOUNTER: - { - ::QueryPerformanceFrequency(&nClk); - return nClk; - } - } - nClk.LowPart = 1000; - return nClk; -} - -/** - * モード強制設定 - */ -void TickCounter::SetMode(int mode) -{ - if (mode==TCMODE_DEFAULT) - { - mode = TCMODE_PERFORMANCECOUNTER; - } - if (mode==TCMODE_PERFORMANCECOUNTER && m_nFreq.QuadPart==0) - { - mode = TCMODE_TIMEGETTIME; - } - switch(mode) - { - case TCMODE_GETTICKCOUNT: - m_mode = mode; - m_dwLastTick = ::GetTickCount(); - break; - - case TCMODE_TIMEGETTIME: - m_mode = mode; - m_dwLastTick = ::timeGetTime(); - break; - - case TCMODE_PERFORMANCECOUNTER: - m_mode = mode; - ::QueryPerformanceCounter(&m_nLast); - break; - } -} -int TickCounter::GetMode() -{ - return m_mode; -} - - -// ---- C インタフェイス - -//! カウンタ インスタンス -static TickCounter s_tick; - -/** - * カウンタを得る - * @return TICK - */ -DWORD GetTickCounter() -{ - return s_tick.Get(); -} - -/** - * カウンタモード設定 - */ -void SetTickCounterMode(int mode) -{ - s_tick.SetMode(mode); -} -int GetTickCounterMode() -{ - return s_tick.GetMode(); -} - -/** - * クロックを得る - * @return TICK - */ -LARGE_INTEGER GetTickCounter_Clock() -{ - return s_tick.Get_rawclock(); -} - -/** - * 1秒あたりのクロックを得る - */ -LARGE_INTEGER GetTickCounter_ClockPerSec() -{ - return s_tick.Get_clockpersec(); -} +/** + * @file tickcounter.cpp + * @brief TICK カウンタの動作の定義を行います + */ + +#include +#include "tickcounter.h" + +/** + * @brief TICK カウンター クラス + */ +class TickCounter +{ +public: + TickCounter(); + DWORD Get(); + LARGE_INTEGER Get_rawclock(); + LARGE_INTEGER Get_clockpersec(); + void SetMode(int mode); + int GetMode(); + +private: + LARGE_INTEGER m_nFreq; //!< 周波数 + LARGE_INTEGER m_nLast; //!< 最後のカウンタ + DWORD m_dwLastTick; //!< 最後の TICK + int m_mode; //!< カウンタモード +}; + +/** + * コンストラクタ + */ +TickCounter::TickCounter() +{ + m_nFreq.QuadPart = 0; + ::QueryPerformanceFrequency(&m_nFreq); + if (m_nFreq.QuadPart) + { + ::QueryPerformanceCounter(&m_nLast); + m_mode = TCMODE_PERFORMANCECOUNTER; + } + else + { + m_mode = TCMODE_TIMEGETTIME; + } + m_dwLastTick = ::timeGetTime(); + //m_dwLastTick = ::GetTickCount(); +} + +/** + * TICK を得る + * @return TICK + */ +DWORD TickCounter::Get() +{ + switch(m_mode) + { + case TCMODE_GETTICKCOUNT: + return ::GetTickCount(); + + case TCMODE_TIMEGETTIME: + return ::timeGetTime(); + + case TCMODE_PERFORMANCECOUNTER: + { + LARGE_INTEGER nNow; + ::QueryPerformanceCounter(&nNow); + const ULONGLONG nPast = nNow.QuadPart - m_nLast.QuadPart; + + const DWORD dwTick = static_cast((nPast * 1000U) / m_nFreq.QuadPart); + const DWORD dwRet = m_dwLastTick + dwTick; + if (dwTick >= 1000) + { + const DWORD dwSeconds = dwTick / 1000; + m_nLast.QuadPart += m_nFreq.QuadPart * dwSeconds; + m_dwLastTick += dwSeconds * 1000; + } + return dwRet; + } + } + return ::GetTickCount(); +} + +LARGE_INTEGER TickCounter::Get_rawclock() +{ + LARGE_INTEGER nNow = {0}; + switch(m_mode) + { + case TCMODE_GETTICKCOUNT: + nNow.LowPart = ::GetTickCount(); + return nNow; + + case TCMODE_TIMEGETTIME: + nNow.LowPart = ::timeGetTime(); + return nNow; + + case TCMODE_PERFORMANCECOUNTER: + { + ::QueryPerformanceCounter(&nNow); + return nNow; + } + } + nNow.LowPart = ::GetTickCount(); + return nNow; +} +LARGE_INTEGER TickCounter::Get_clockpersec() +{ + LARGE_INTEGER nClk = {0}; + switch(m_mode) + { + case TCMODE_GETTICKCOUNT: + nClk.LowPart = 1000; + return nClk; + + case TCMODE_TIMEGETTIME: + nClk.LowPart = 1000; + return nClk; + + case TCMODE_PERFORMANCECOUNTER: + { + ::QueryPerformanceFrequency(&nClk); + return nClk; + } + } + nClk.LowPart = 1000; + return nClk; +} + +/** + * モード強制設定 + */ +void TickCounter::SetMode(int mode) +{ + if (mode==TCMODE_DEFAULT) + { + mode = TCMODE_PERFORMANCECOUNTER; + } + if (mode==TCMODE_PERFORMANCECOUNTER && m_nFreq.QuadPart==0) + { + mode = TCMODE_TIMEGETTIME; + } + switch(mode) + { + case TCMODE_GETTICKCOUNT: + m_mode = mode; + m_dwLastTick = ::GetTickCount(); + break; + + case TCMODE_TIMEGETTIME: + m_mode = mode; + m_dwLastTick = ::timeGetTime(); + break; + + case TCMODE_PERFORMANCECOUNTER: + m_mode = mode; + ::QueryPerformanceCounter(&m_nLast); + break; + } +} +int TickCounter::GetMode() +{ + return m_mode; +} + + +// ---- C インタフェイス + +//! カウンタ インスタンス +static TickCounter s_tick; + +/** + * カウンタを得る + * @return TICK + */ +DWORD GetTickCounter() +{ + return s_tick.Get(); +} + +/** + * カウンタモード設定 + */ +void SetTickCounterMode(int mode) +{ + s_tick.SetMode(mode); +} +int GetTickCounterMode() +{ + return s_tick.GetMode(); +} + +/** + * クロックを得る + * @return TICK + */ +LARGE_INTEGER GetTickCounter_Clock() +{ + return s_tick.Get_rawclock(); +} + +/** + * 1秒あたりのクロックを得る + */ +LARGE_INTEGER GetTickCounter_ClockPerSec() +{ + return s_tick.Get_clockpersec(); +} diff --git a/windows/misc/tickcounter.h b/windows/misc/tickcounter.h old mode 100755 new mode 100644 index ac6e41b3..224fb182 --- a/windows/misc/tickcounter.h +++ b/windows/misc/tickcounter.h @@ -1,28 +1,28 @@ -/** - * @file tickcounter.h - * @brief TICK カウンタの宣言およびインターフェイスの定義をします - */ - -#pragma once - -enum { - TCMODE_DEFAULT = 0, - TCMODE_GETTICKCOUNT = 1, - TCMODE_TIMEGETTIME = 2, - TCMODE_PERFORMANCECOUNTER = 3, -}; - -#ifdef __cplusplus -extern "C" -{ -#endif // __cplusplus - -DWORD GetTickCounter(); -void SetTickCounterMode(int mode); -int GetTickCounterMode(); -LARGE_INTEGER GetTickCounter_Clock(); -LARGE_INTEGER GetTickCounter_ClockPerSec(); - -#ifdef __cplusplus -} -#endif // __cplusplus +/** + * @file tickcounter.h + * @brief TICK カウンタの宣言およびインターフェイスの定義をします + */ + +#pragma once + +enum { + TCMODE_DEFAULT = 0, + TCMODE_GETTICKCOUNT = 1, + TCMODE_TIMEGETTIME = 2, + TCMODE_PERFORMANCECOUNTER = 3, +}; + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +DWORD GetTickCounter(); +void SetTickCounterMode(int mode); +int GetTickCounterMode(); +LARGE_INTEGER GetTickCounter_Clock(); +LARGE_INTEGER GetTickCounter_ClockPerSec(); + +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/windows/misc/trace.cpp b/windows/misc/trace.cpp old mode 100755 new mode 100644 index 21e9fd0b..453460c3 --- a/windows/misc/trace.cpp +++ b/windows/misc/trace.cpp @@ -1,483 +1,483 @@ -/** - * @file trace.cpp - * @brief トレース クラスの動作の定義を行います - */ - -#include -#include -#include -#include -#include "resource.h" -#include "WndProc.h" -#include -#include -#include -#include -#include "menu.h" - -#ifdef TRACE - -#define VIEW_FGCOLOR 0x000000 -#define VIEW_BGCOLOR 0xffffff -#define VIEW_TEXT "MS ゴシック" -#define VIEW_SIZE 12 - -/** - * @brief トレース ウィンドウ クラス - */ -class CTraceWnd : public CWndProc -{ -public: - static CTraceWnd* GetInstance(); - - CTraceWnd(); - void Initialize(); - void Deinitialize(); - bool IsTrace() const; - bool IsVerbose() const; - bool IsEnabled() const; - void AddChar(char c); - void AddFormat(LPCSTR lpFormat, va_list argptr); - void AddString(LPCTSTR lpString); - -protected: - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - int OnCreate(LPCREATESTRUCT lpCreateStruct); - void OnSysCommand(UINT nID, LPARAM lParam); - void OnEnterMenuLoop(BOOL bIsTrackPopupMenu); - -private: - static CTraceWnd sm_instance; /*!< 唯一のインスタンスです */ - UINT8 m_nFlags; /*!< フラグ */ - TEXTFILEH m_tfh; /*!< テキスト ファイル ハンドル */ - HBRUSH m_hBrush; /*!< ブラシ */ - HFONT m_hFont; /*!< フォント */ - CWndProc m_wndView; /*!< テキスト コントロール */ - std::string m_lineBuffer; /*!< ライン バッファ */ -}; - -struct TRACECFG -{ - int posx; - int posy; - int width; - int height; -}; - -static const TCHAR s_szTitle[] = TEXT("console"); -static const TCHAR s_szClassName[] = TEXT("TRACE-console"); -static const TCHAR s_szViewFont[] = TEXT(VIEW_TEXT); - -static const OEMCHAR crlf[] = OEMTEXT("\r\n"); - -static TRACECFG tracecfg; - -static const OEMCHAR np2trace[] = OEMTEXT("np2trace.ini"); -static const OEMCHAR inititle[] = OEMTEXT("TRACE"); -static const PFTBL initbl[4] = -{ - PFVAL("posx", PFTYPE_SINT32, &tracecfg.posx), - PFVAL("posy", PFTYPE_SINT32, &tracecfg.posy), - PFVAL("width", PFTYPE_SINT32, &tracecfg.width), - PFVAL("height", PFTYPE_SINT32, &tracecfg.height) -}; - -//! 唯一のインスタンスです -CTraceWnd CTraceWnd::sm_instance; - -/** - * インスタンスを得る - * @return インスタンス - */ -inline CTraceWnd* CTraceWnd::GetInstance() -{ - return &sm_instance; -} - -/** - * コンストラクタ - */ -CTraceWnd::CTraceWnd() - : m_nFlags(0) - , m_tfh(NULL) - , m_hBrush(NULL) - , m_hFont(NULL) -{ -} - -/** - * 初期化 - */ -void CTraceWnd::Initialize() -{ - WNDCLASS wc; - ZeroMemory(&wc, sizeof(wc)); - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = ::DefWindowProc; - wc.hInstance = GetInstanceHandle(); - wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = static_cast(::GetStockObject(WHITE_BRUSH)); - wc.lpszClassName = s_szClassName; - if (!::RegisterClass(&wc)) - { - return; - } - -#if 1 - m_nFlags = 4; -#else - m_nFlags = 1; - m_tfh = textfile_create(OEMTEXT("traceout.txt"), 0x800); -#endif - - tracecfg.posx = CW_USEDEFAULT; - tracecfg.posy = CW_USEDEFAULT; - tracecfg.width = CW_USEDEFAULT; - tracecfg.height = CW_USEDEFAULT; - ini_read(file_getcd(np2trace), inititle, initbl, NELEMENTS(initbl)); - - if (!CreateEx(WS_EX_CONTROLPARENT, s_szClassName, s_szTitle, WS_OVERLAPPEDWINDOW, tracecfg.posx, tracecfg.posy, tracecfg.width, tracecfg.height, NULL, NULL)) - { - return; - } - ShowWindow(SW_SHOW); - UpdateWindow(); -} - -/** - * 解放 - */ -void CTraceWnd::Deinitialize() -{ - if (m_tfh != NULL) - { - textfile_close(m_tfh); - m_tfh = NULL; - } - - DestroyWindow(); - ini_write(file_getcd(np2trace), inititle, initbl, NELEMENTS(initbl)); -} - -/** - * Trace は有効? - * @retval true 有効 - * @retval false 無効 - */ -inline bool CTraceWnd::IsTrace() const -{ - return ((m_nFlags & 1) != 0); -} - -/** - * Verbose は有効? - * @retval true 有効 - * @retval false 無効 - */ -inline bool CTraceWnd::IsVerbose() const -{ - return ((m_nFlags & 2) != 0); -} - -/** - * 有効? - * @retval true 有効 - * @retval false 無効 - */ -inline bool CTraceWnd::IsEnabled() const -{ - return ((m_nFlags & 4) || (m_tfh != NULL)); -} - -/** - * ログ追加 - * @param[in] c 文字 - */ -void CTraceWnd::AddChar(char c) -{ - if ((c == 0x0a) || (c == 0x0d)) - { - if (!m_lineBuffer.empty()) - { - USES_CONVERSION; - AddString(A2CT(m_lineBuffer.c_str())); - m_lineBuffer.erase(); - } - } - else - { - m_lineBuffer += c; - } -} - -/** - * ログ追加 - * @param[in] lpFormat フォーマット - * @param[in] argptr 引数 - */ -void CTraceWnd::AddFormat(LPCSTR lpFormat, va_list argptr) -{ - USES_CONVERSION; - - TCHAR szBuf[4096]; - _vstprintf(szBuf, A2CT(lpFormat), argptr); - AddString(szBuf); -} - -/** - * ログ追加 - * @param[in] lpString 文字列 - */ -void CTraceWnd::AddString(LPCTSTR lpString) -{ - if ((m_nFlags & 4) && (m_wndView.IsWindow())) - { - UINT nStart = 0; - UINT nEnd = 0; - m_wndView.SendMessage(EM_GETSEL, reinterpret_cast(&nStart), reinterpret_cast(&nEnd)); - - const UINT nLength = m_wndView.GetWindowTextLength(); - m_wndView.SendMessage(EM_SETSEL, static_cast(nLength), static_cast(nLength)); - - m_wndView.SendMessage(EM_REPLACESEL, FALSE, reinterpret_cast(lpString)); - m_wndView.SendMessage(EM_REPLACESEL, FALSE, reinterpret_cast(crlf)); - - // 増えすぎたら消す - if(nLength>20000){ - TCHAR temp[1] = {0}; - int llength = m_wndView.SendMessage(EM_LINELENGTH, static_cast(1), NULL); - m_wndView.SendMessage(EM_SETSEL, static_cast(0), static_cast(nLength)); - m_wndView.SendMessage(EM_REPLACESEL, FALSE, reinterpret_cast(temp)); - } - - m_wndView.SendMessage(EM_SETSEL, static_cast(nStart), static_cast(nEnd)); - - //UINT nStart = 0; - //UINT nEnd = 0; - //m_wndView.SendMessage(EM_GETSEL, reinterpret_cast(&nStart), reinterpret_cast(&nEnd)); - - //const UINT nLength = m_wndView.GetWindowTextLength(); - //m_wndView.SendMessage(EM_SETSEL, static_cast(nLength), static_cast(nLength)); - - //m_wndView.SendMessage(EM_REPLACESEL, FALSE, reinterpret_cast(lpString)); - //m_wndView.SendMessage(EM_REPLACESEL, FALSE, reinterpret_cast(crlf)); - //m_wndView.SendMessage(EM_SETSEL, static_cast(nStart), static_cast(nEnd)); - } - if (m_tfh != NULL) - { - textfile_write(m_tfh, lpString); - textfile_write(m_tfh, crlf); - } -} - -/** - * Windows プロシージャ (WindowProc) を提供します - * @param[in] message 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理に使用する追加情報を提供します - * @param[in] lParam メッセージの処理に使用する追加情報を提供します - * @return 戻り値は、メッセージによって異なります - */ -LRESULT CTraceWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - switch (nMsg) - { - case WM_CREATE: - return OnCreate(reinterpret_cast(lParam)); - - case WM_SYSCOMMAND: - OnSysCommand(wParam, lParam); - return DefWindowProc(nMsg, wParam, lParam); - - case WM_ENTERMENULOOP: - OnEnterMenuLoop(wParam); - break; - - case WM_MOVE: - if (!(GetStyle() & (WS_MAXIMIZE | WS_MINIMIZE))) - { - RECT rc; - GetWindowRect(&rc); - tracecfg.posx = rc.left; - tracecfg.posy = rc.top; - } - break; - - case WM_SIZE: // window resize - if (!(GetStyle() & (WS_MAXIMIZE | WS_MINIMIZE))) - { - RECT rc; - GetWindowRect(&rc); - tracecfg.width = rc.right - rc.left; - tracecfg.height = rc.bottom - rc.top; - } - m_wndView.MoveWindow(0, 0, LOWORD(lParam), HIWORD(lParam)); - break; - - case WM_SETFOCUS: - m_wndView.SetFocus(); - break; - - case WM_CTLCOLORSTATIC: - case WM_CTLCOLOREDIT: - SetTextColor((HDC)wParam, VIEW_FGCOLOR); - SetBkColor((HDC)wParam, VIEW_BGCOLOR); - return reinterpret_cast(m_hBrush); - - case WM_CLOSE: - break; - - case WM_DESTROY: - if (m_hBrush) - { - ::DeleteObject(m_hBrush); - m_hBrush = NULL; - } - if (m_hFont) - { - ::DeleteObject(m_hFont); - m_hFont = NULL; - } - break; -#if 0 - case WM_ENTERSIZEMOVE: - winloc_movingstart(); - break; - - case WM_MOVING: - winloc_movingproc((RECT *)lParam); - break; - - case WM_ERASEBKGND: - break; -#endif - default: - return DefWindowProc(nMsg, wParam, lParam); - } - return FALSE; -} - -/** - * フレームワークは、Windows のウィンドウは [作成] または CreateEx のメンバー関数を呼び出すことによって作成されたアプリケーションが必要とすると、このメンバー関数を呼び出します - * @param[in] lpCreateStruct 作成されたオブジェクトに関する情報が含まれています。 - * @retval 0 成功 - * @retval -1 失敗 - */ -int CTraceWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) -{ - HMENU hMenu = GetSystemMenu(FALSE); - menu_addmenures(hMenu, 0, IDR_TRACE, FALSE); - - m_hBrush = ::CreateSolidBrush(VIEW_BGCOLOR); - - RECT rc; - GetClientRect(&rc); - if (m_wndView.CreateEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), NULL, WS_CHILD | WS_VISIBLE | ES_READONLY | ES_LEFT | ES_MULTILINE | WS_VSCROLL | ES_AUTOVSCROLL, 0, 0, rc.right, rc.bottom, m_hWnd, NULL)) - { - m_hFont = ::CreateFont(VIEW_SIZE, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, s_szViewFont); - if (m_hFont) - { - m_wndView.SetFont(m_hFont); - } - m_wndView.SetFocus(); - } - - return 0; -} - -/** - * フレームワークは、ユーザーがコントロール メニューからコマンドを選択したとき、または最大化または最小化ボタンを選択すると、このメンバー関数を呼び出します - * @param[in] nID 必要なシステム コマンドの種類を指定します - * @param[in] lParam カーソルの座標 - */ -void CTraceWnd::OnSysCommand(UINT nID, LPARAM lParam) -{ - switch (nID) - { - case IDM_TRACE_TRACE: - m_nFlags ^= 1; - break; - - case IDM_TRACE_VERBOSE: - m_nFlags ^= 2; - break; - - case IDM_TRACE_ENABLE: - m_nFlags ^= 4; - break; - - case IDM_TRACE_FILEOUT: - if (m_tfh != NULL) - { - textfile_close(m_tfh); - m_tfh = NULL; - } - else - { - m_tfh = textfile_create(OEMTEXT("traceout.txt"), 0x800); - } - break; - - case IDM_TRACE_CLEAR: - m_wndView.SetWindowText(TEXT("")); - break; - } -} - -/** - * フレームワークは、メニュー ループ開始時に、このメンバー関数を呼び出します - * @param[in] bIsTrackPopupMenu TrackPopupMenu 関数を利用した場合 TRUE - */ -void CTraceWnd::OnEnterMenuLoop(BOOL bIsTrackPopupMenu) -{ - HMENU hMenu = GetSystemMenu(FALSE); - ::CheckMenuItem(hMenu, IDM_TRACE_TRACE, (m_nFlags & 1) ? MF_CHECKED : MF_UNCHECKED); - ::CheckMenuItem(hMenu, IDM_TRACE_VERBOSE, (m_nFlags & 2) ? MF_CHECKED : MF_UNCHECKED); - ::CheckMenuItem(hMenu, IDM_TRACE_ENABLE, (m_nFlags & 4) ? MF_CHECKED:MF_UNCHECKED); - ::CheckMenuItem(hMenu, IDM_TRACE_FILEOUT, (m_tfh != NULL) ? MF_CHECKED : MF_UNCHECKED); -} - - - -// ---- - -void trace_init(void) -{ - CTraceWnd::GetInstance()->Initialize(); -} - -void trace_term(void) -{ - CTraceWnd::GetInstance()->Deinitialize(); -} - -void trace_fmt(const char *fmt, ...) -{ - CTraceWnd* pWnd = CTraceWnd::GetInstance(); - - if ((pWnd->IsTrace()) && (pWnd->IsEnabled())) - { - va_list ap; - va_start(ap, fmt); - pWnd->AddFormat(fmt, ap); - va_end(ap); - } -} - -void trace_fmt2(const char *fmt, ...) -{ - CTraceWnd* pWnd = CTraceWnd::GetInstance(); - - if ((pWnd->IsVerbose()) && (pWnd->IsEnabled())) - { - va_list ap; - va_start(ap, fmt); - pWnd->AddFormat(fmt, ap); - va_end(ap); - } -} - -void trace_char(char c) -{ - CTraceWnd::GetInstance()->AddChar(c); -} -#endif +/** + * @file trace.cpp + * @brief トレース クラスの動作の定義を行います + */ + +#include +#include +#include +#include +#include "resource.h" +#include "WndProc.h" +#include +#include +#include +#include +#include "menu.h" + +#ifdef TRACE + +#define VIEW_FGCOLOR 0x000000 +#define VIEW_BGCOLOR 0xffffff +#define VIEW_TEXT "MS ゴシック" +#define VIEW_SIZE 12 + +/** + * @brief トレース ウィンドウ クラス + */ +class CTraceWnd : public CWndProc +{ +public: + static CTraceWnd* GetInstance(); + + CTraceWnd(); + void Initialize(); + void Deinitialize(); + bool IsTrace() const; + bool IsVerbose() const; + bool IsEnabled() const; + void AddChar(char c); + void AddFormat(LPCSTR lpFormat, va_list argptr); + void AddString(LPCTSTR lpString); + +protected: + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + int OnCreate(LPCREATESTRUCT lpCreateStruct); + void OnSysCommand(UINT nID, LPARAM lParam); + void OnEnterMenuLoop(BOOL bIsTrackPopupMenu); + +private: + static CTraceWnd sm_instance; /*!< 唯一のインスタンスです */ + UINT8 m_nFlags; /*!< フラグ */ + TEXTFILEH m_tfh; /*!< テキスト ファイル ハンドル */ + HBRUSH m_hBrush; /*!< ブラシ */ + HFONT m_hFont; /*!< フォント */ + CWndProc m_wndView; /*!< テキスト コントロール */ + std::string m_lineBuffer; /*!< ライン バッファ */ +}; + +struct TRACECFG +{ + int posx; + int posy; + int width; + int height; +}; + +static const TCHAR s_szTitle[] = TEXT("console"); +static const TCHAR s_szClassName[] = TEXT("TRACE-console"); +static const TCHAR s_szViewFont[] = TEXT(VIEW_TEXT); + +static const OEMCHAR crlf[] = OEMTEXT("\r\n"); + +static TRACECFG tracecfg; + +static const OEMCHAR np2trace[] = OEMTEXT("np2trace.ini"); +static const OEMCHAR inititle[] = OEMTEXT("TRACE"); +static const PFTBL initbl[4] = +{ + PFVAL("posx", PFTYPE_SINT32, &tracecfg.posx), + PFVAL("posy", PFTYPE_SINT32, &tracecfg.posy), + PFVAL("width", PFTYPE_SINT32, &tracecfg.width), + PFVAL("height", PFTYPE_SINT32, &tracecfg.height) +}; + +//! 唯一のインスタンスです +CTraceWnd CTraceWnd::sm_instance; + +/** + * インスタンスを得る + * @return インスタンス + */ +inline CTraceWnd* CTraceWnd::GetInstance() +{ + return &sm_instance; +} + +/** + * コンストラクタ + */ +CTraceWnd::CTraceWnd() + : m_nFlags(0) + , m_tfh(NULL) + , m_hBrush(NULL) + , m_hFont(NULL) +{ +} + +/** + * 初期化 + */ +void CTraceWnd::Initialize() +{ + WNDCLASS wc; + ZeroMemory(&wc, sizeof(wc)); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = ::DefWindowProc; + wc.hInstance = GetInstanceHandle(); + wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = static_cast(::GetStockObject(WHITE_BRUSH)); + wc.lpszClassName = s_szClassName; + if (!::RegisterClass(&wc)) + { + return; + } + +#if 1 + m_nFlags = 4; +#else + m_nFlags = 1; + m_tfh = textfile_create(OEMTEXT("traceout.txt"), 0x800); +#endif + + tracecfg.posx = CW_USEDEFAULT; + tracecfg.posy = CW_USEDEFAULT; + tracecfg.width = CW_USEDEFAULT; + tracecfg.height = CW_USEDEFAULT; + ini_read(file_getcd(np2trace), inititle, initbl, NELEMENTS(initbl)); + + if (!CreateEx(WS_EX_CONTROLPARENT, s_szClassName, s_szTitle, WS_OVERLAPPEDWINDOW, tracecfg.posx, tracecfg.posy, tracecfg.width, tracecfg.height, NULL, NULL)) + { + return; + } + ShowWindow(SW_SHOW); + UpdateWindow(); +} + +/** + * 解放 + */ +void CTraceWnd::Deinitialize() +{ + if (m_tfh != NULL) + { + textfile_close(m_tfh); + m_tfh = NULL; + } + + DestroyWindow(); + ini_write(file_getcd(np2trace), inititle, initbl, NELEMENTS(initbl)); +} + +/** + * Trace は有効? + * @retval true 有効 + * @retval false 無効 + */ +inline bool CTraceWnd::IsTrace() const +{ + return ((m_nFlags & 1) != 0); +} + +/** + * Verbose は有効? + * @retval true 有効 + * @retval false 無効 + */ +inline bool CTraceWnd::IsVerbose() const +{ + return ((m_nFlags & 2) != 0); +} + +/** + * 有効? + * @retval true 有効 + * @retval false 無効 + */ +inline bool CTraceWnd::IsEnabled() const +{ + return ((m_nFlags & 4) || (m_tfh != NULL)); +} + +/** + * ログ追加 + * @param[in] c 文字 + */ +void CTraceWnd::AddChar(char c) +{ + if ((c == 0x0a) || (c == 0x0d)) + { + if (!m_lineBuffer.empty()) + { + USES_CONVERSION; + AddString(A2CT(m_lineBuffer.c_str())); + m_lineBuffer.erase(); + } + } + else + { + m_lineBuffer += c; + } +} + +/** + * ログ追加 + * @param[in] lpFormat フォーマット + * @param[in] argptr 引数 + */ +void CTraceWnd::AddFormat(LPCSTR lpFormat, va_list argptr) +{ + USES_CONVERSION; + + TCHAR szBuf[4096]; + _vstprintf(szBuf, A2CT(lpFormat), argptr); + AddString(szBuf); +} + +/** + * ログ追加 + * @param[in] lpString 文字列 + */ +void CTraceWnd::AddString(LPCTSTR lpString) +{ + if ((m_nFlags & 4) && (m_wndView.IsWindow())) + { + UINT nStart = 0; + UINT nEnd = 0; + m_wndView.SendMessage(EM_GETSEL, reinterpret_cast(&nStart), reinterpret_cast(&nEnd)); + + const UINT nLength = m_wndView.GetWindowTextLength(); + m_wndView.SendMessage(EM_SETSEL, static_cast(nLength), static_cast(nLength)); + + m_wndView.SendMessage(EM_REPLACESEL, FALSE, reinterpret_cast(lpString)); + m_wndView.SendMessage(EM_REPLACESEL, FALSE, reinterpret_cast(crlf)); + + // 増えすぎたら消す + if(nLength>20000){ + TCHAR temp[1] = {0}; + int llength = m_wndView.SendMessage(EM_LINELENGTH, static_cast(1), NULL); + m_wndView.SendMessage(EM_SETSEL, static_cast(0), static_cast(nLength)); + m_wndView.SendMessage(EM_REPLACESEL, FALSE, reinterpret_cast(temp)); + } + + m_wndView.SendMessage(EM_SETSEL, static_cast(nStart), static_cast(nEnd)); + + //UINT nStart = 0; + //UINT nEnd = 0; + //m_wndView.SendMessage(EM_GETSEL, reinterpret_cast(&nStart), reinterpret_cast(&nEnd)); + + //const UINT nLength = m_wndView.GetWindowTextLength(); + //m_wndView.SendMessage(EM_SETSEL, static_cast(nLength), static_cast(nLength)); + + //m_wndView.SendMessage(EM_REPLACESEL, FALSE, reinterpret_cast(lpString)); + //m_wndView.SendMessage(EM_REPLACESEL, FALSE, reinterpret_cast(crlf)); + //m_wndView.SendMessage(EM_SETSEL, static_cast(nStart), static_cast(nEnd)); + } + if (m_tfh != NULL) + { + textfile_write(m_tfh, lpString); + textfile_write(m_tfh, crlf); + } +} + +/** + * Windows プロシージャ (WindowProc) を提供します + * @param[in] message 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理に使用する追加情報を提供します + * @param[in] lParam メッセージの処理に使用する追加情報を提供します + * @return 戻り値は、メッセージによって異なります + */ +LRESULT CTraceWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + switch (nMsg) + { + case WM_CREATE: + return OnCreate(reinterpret_cast(lParam)); + + case WM_SYSCOMMAND: + OnSysCommand(wParam, lParam); + return DefWindowProc(nMsg, wParam, lParam); + + case WM_ENTERMENULOOP: + OnEnterMenuLoop(wParam); + break; + + case WM_MOVE: + if (!(GetStyle() & (WS_MAXIMIZE | WS_MINIMIZE))) + { + RECT rc; + GetWindowRect(&rc); + tracecfg.posx = rc.left; + tracecfg.posy = rc.top; + } + break; + + case WM_SIZE: // window resize + if (!(GetStyle() & (WS_MAXIMIZE | WS_MINIMIZE))) + { + RECT rc; + GetWindowRect(&rc); + tracecfg.width = rc.right - rc.left; + tracecfg.height = rc.bottom - rc.top; + } + m_wndView.MoveWindow(0, 0, LOWORD(lParam), HIWORD(lParam)); + break; + + case WM_SETFOCUS: + m_wndView.SetFocus(); + break; + + case WM_CTLCOLORSTATIC: + case WM_CTLCOLOREDIT: + SetTextColor((HDC)wParam, VIEW_FGCOLOR); + SetBkColor((HDC)wParam, VIEW_BGCOLOR); + return reinterpret_cast(m_hBrush); + + case WM_CLOSE: + break; + + case WM_DESTROY: + if (m_hBrush) + { + ::DeleteObject(m_hBrush); + m_hBrush = NULL; + } + if (m_hFont) + { + ::DeleteObject(m_hFont); + m_hFont = NULL; + } + break; +#if 0 + case WM_ENTERSIZEMOVE: + winloc_movingstart(); + break; + + case WM_MOVING: + winloc_movingproc((RECT *)lParam); + break; + + case WM_ERASEBKGND: + break; +#endif + default: + return DefWindowProc(nMsg, wParam, lParam); + } + return FALSE; +} + +/** + * フレームワークは、Windows のウィンドウは [作成] または CreateEx のメンバー関数を呼び出すことによって作成されたアプリケーションが必要とすると、このメンバー関数を呼び出します + * @param[in] lpCreateStruct 作成されたオブジェクトに関する情報が含まれています。 + * @retval 0 成功 + * @retval -1 失敗 + */ +int CTraceWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + HMENU hMenu = GetSystemMenu(FALSE); + menu_addmenures(hMenu, 0, IDR_TRACE, FALSE); + + m_hBrush = ::CreateSolidBrush(VIEW_BGCOLOR); + + RECT rc; + GetClientRect(&rc); + if (m_wndView.CreateEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), NULL, WS_CHILD | WS_VISIBLE | ES_READONLY | ES_LEFT | ES_MULTILINE | WS_VSCROLL | ES_AUTOVSCROLL, 0, 0, rc.right, rc.bottom, m_hWnd, NULL)) + { + m_hFont = ::CreateFont(VIEW_SIZE, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, s_szViewFont); + if (m_hFont) + { + m_wndView.SetFont(m_hFont); + } + m_wndView.SetFocus(); + } + + return 0; +} + +/** + * フレームワークは、ユーザーがコントロール メニューからコマンドを選択したとき、または最大化または最小化ボタンを選択すると、このメンバー関数を呼び出します + * @param[in] nID 必要なシステム コマンドの種類を指定します + * @param[in] lParam カーソルの座標 + */ +void CTraceWnd::OnSysCommand(UINT nID, LPARAM lParam) +{ + switch (nID) + { + case IDM_TRACE_TRACE: + m_nFlags ^= 1; + break; + + case IDM_TRACE_VERBOSE: + m_nFlags ^= 2; + break; + + case IDM_TRACE_ENABLE: + m_nFlags ^= 4; + break; + + case IDM_TRACE_FILEOUT: + if (m_tfh != NULL) + { + textfile_close(m_tfh); + m_tfh = NULL; + } + else + { + m_tfh = textfile_create(OEMTEXT("traceout.txt"), 0x800); + } + break; + + case IDM_TRACE_CLEAR: + m_wndView.SetWindowText(TEXT("")); + break; + } +} + +/** + * フレームワークは、メニュー ループ開始時に、このメンバー関数を呼び出します + * @param[in] bIsTrackPopupMenu TrackPopupMenu 関数を利用した場合 TRUE + */ +void CTraceWnd::OnEnterMenuLoop(BOOL bIsTrackPopupMenu) +{ + HMENU hMenu = GetSystemMenu(FALSE); + ::CheckMenuItem(hMenu, IDM_TRACE_TRACE, (m_nFlags & 1) ? MF_CHECKED : MF_UNCHECKED); + ::CheckMenuItem(hMenu, IDM_TRACE_VERBOSE, (m_nFlags & 2) ? MF_CHECKED : MF_UNCHECKED); + ::CheckMenuItem(hMenu, IDM_TRACE_ENABLE, (m_nFlags & 4) ? MF_CHECKED:MF_UNCHECKED); + ::CheckMenuItem(hMenu, IDM_TRACE_FILEOUT, (m_tfh != NULL) ? MF_CHECKED : MF_UNCHECKED); +} + + + +// ---- + +void trace_init(void) +{ + CTraceWnd::GetInstance()->Initialize(); +} + +void trace_term(void) +{ + CTraceWnd::GetInstance()->Deinitialize(); +} + +void trace_fmt(const char *fmt, ...) +{ + CTraceWnd* pWnd = CTraceWnd::GetInstance(); + + if ((pWnd->IsTrace()) && (pWnd->IsEnabled())) + { + va_list ap; + va_start(ap, fmt); + pWnd->AddFormat(fmt, ap); + va_end(ap); + } +} + +void trace_fmt2(const char *fmt, ...) +{ + CTraceWnd* pWnd = CTraceWnd::GetInstance(); + + if ((pWnd->IsVerbose()) && (pWnd->IsEnabled())) + { + va_list ap; + va_start(ap, fmt); + pWnd->AddFormat(fmt, ap); + va_end(ap); + } +} + +void trace_char(char c) +{ + CTraceWnd::GetInstance()->AddChar(c); +} +#endif diff --git a/windows/misc/trace.h b/windows/misc/trace.h old mode 100755 new mode 100644 index 3329bad0..c4999723 --- a/windows/misc/trace.h +++ b/windows/misc/trace.h @@ -1,39 +1,39 @@ -/** - * @file trace.h - * @brief トレース クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#ifndef TRACE - -#define TRACEINIT() -#define TRACETERM() -#define TRACEOUT(a) -#define VERBOSE(a) -#define APPDEVOUT(a) - -#else - -#ifdef __cplusplus -extern "C" { -#endif - -void trace_init(void); -void trace_term(void); -void trace_fmt(const char *str, ...); -void trace_fmt2(const char *str, ...); -void trace_char(char c); -void trace_fileout(const OEMCHAR *fname); - -#ifdef __cplusplus -} -#endif - -#define TRACEINIT() trace_init() -#define TRACETERM() trace_term() -#define TRACEOUT(arg) trace_fmt arg -#define VERBOSE(arg) trace_fmt2 arg -#define APPDEVOUT(arg) trace_char(arg) - -#endif +/** + * @file trace.h + * @brief トレース クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#ifndef TRACE + +#define TRACEINIT() +#define TRACETERM() +#define TRACEOUT(a) +#define VERBOSE(a) +#define APPDEVOUT(a) + +#else + +#ifdef __cplusplus +extern "C" { +#endif + +void trace_init(void); +void trace_term(void); +void trace_fmt(const char *str, ...); +void trace_fmt2(const char *str, ...); +void trace_char(char c); +void trace_fileout(const OEMCHAR *fname); + +#ifdef __cplusplus +} +#endif + +#define TRACEINIT() trace_init() +#define TRACETERM() trace_term() +#define TRACEOUT(arg) trace_fmt arg +#define VERBOSE(arg) trace_fmt2 arg +#define APPDEVOUT(arg) trace_char(arg) + +#endif diff --git a/windows/misc/tstring.cpp b/windows/misc/tstring.cpp old mode 100755 new mode 100644 index 02070391..e60eed32 --- a/windows/misc/tstring.cpp +++ b/windows/misc/tstring.cpp @@ -1,87 +1,87 @@ -/** - * @file tstring.cpp - * @brief 文字列クラスの動作の定義を行います - */ - -#include -#include "tstring.h" -#include "WndProc.h" - -/** - * リソースから文字列をロード - * @param[in] uID リソース識別子 - * @return 文字列 - */ -std::tstring LoadTString(UINT uID) -{ - std::tstring ret; - - do - { - HINSTANCE hInstance = CWndProc::FindResourceHandle(MAKEINTRESOURCE((uID >> 4) + 1), RT_STRING); - HRSRC hRsrc = ::FindResource(hInstance, MAKEINTRESOURCE((uID >> 4) + 1), RT_STRING); - if (hRsrc == NULL) - { - break; - } - - DWORD dwResSize = ::SizeofResource(hInstance, hRsrc); - HGLOBAL hGlobal = ::LoadResource(hInstance, hRsrc); - if (hGlobal == NULL) - { - break; - } - - LPCWSTR pRes = static_cast(::LockResource(hGlobal)); - DWORD dwPos = 0; - uID = uID & 15; - while ((uID) && (dwPos < dwResSize)) - { - dwPos += pRes[dwPos] + 1; - uID--; - } - if (dwPos >= dwResSize) - { - break; - } - - UINT nLength = pRes[dwPos++]; - nLength = MIN(nLength, (dwResSize - dwPos)); - -#if defined(_UNICODE) - - ret = std::wstring(pRes + dwPos, nLength); - -#else // defined(_UNICODE) - - UINT nSize = ::WideCharToMultiByte(CP_ACP, 0, pRes + dwPos, nLength, NULL, 0, NULL, NULL); - if (nSize) - { - ret.resize(nSize); - nSize = ::WideCharToMultiByte(CP_ACP, 0, pRes + dwPos, nLength, &ret.at(0), nSize, NULL, NULL); - ret.resize(nSize); - } - -#endif // defined(_UNICODE) - - } while (false /*CONSTCOND*/); - - return ret; -} - -/** - * リソースから文字列をロード - * @param[in] lpString 文字列ID - * @return 文字列 - */ -std::tstring LoadTString(LPCTSTR lpString) -{ - if (HIWORD(lpString)) - { - return std::tstring(lpString); - } - else - { - return LoadTString(static_cast(LOWORD(lpString))); - } -} +/** + * @file tstring.cpp + * @brief 文字列クラスの動作の定義を行います + */ + +#include +#include "tstring.h" +#include "WndProc.h" + +/** + * リソースから文字列をロード + * @param[in] uID リソース識別子 + * @return 文字列 + */ +std::tstring LoadTString(UINT uID) +{ + std::tstring ret; + + do + { + HINSTANCE hInstance = CWndProc::FindResourceHandle(MAKEINTRESOURCE((uID >> 4) + 1), RT_STRING); + HRSRC hRsrc = ::FindResource(hInstance, MAKEINTRESOURCE((uID >> 4) + 1), RT_STRING); + if (hRsrc == NULL) + { + break; + } + + DWORD dwResSize = ::SizeofResource(hInstance, hRsrc); + HGLOBAL hGlobal = ::LoadResource(hInstance, hRsrc); + if (hGlobal == NULL) + { + break; + } + + LPCWSTR pRes = static_cast(::LockResource(hGlobal)); + DWORD dwPos = 0; + uID = uID & 15; + while ((uID) && (dwPos < dwResSize)) + { + dwPos += pRes[dwPos] + 1; + uID--; + } + if (dwPos >= dwResSize) + { + break; + } + + UINT nLength = pRes[dwPos++]; + nLength = MIN(nLength, (dwResSize - dwPos)); + +#if defined(_UNICODE) + + ret = std::wstring(pRes + dwPos, nLength); + +#else // defined(_UNICODE) + + UINT nSize = ::WideCharToMultiByte(CP_ACP, 0, pRes + dwPos, nLength, NULL, 0, NULL, NULL); + if (nSize) + { + ret.resize(nSize); + nSize = ::WideCharToMultiByte(CP_ACP, 0, pRes + dwPos, nLength, &ret.at(0), nSize, NULL, NULL); + ret.resize(nSize); + } + +#endif // defined(_UNICODE) + + } while (false /*CONSTCOND*/); + + return ret; +} + +/** + * リソースから文字列をロード + * @param[in] lpString 文字列ID + * @return 文字列 + */ +std::tstring LoadTString(LPCTSTR lpString) +{ + if (HIWORD(lpString)) + { + return std::tstring(lpString); + } + else + { + return LoadTString(static_cast(LOWORD(lpString))); + } +} diff --git a/windows/misc/tstring.h b/windows/misc/tstring.h old mode 100755 new mode 100644 index 52d87538..0328ae75 --- a/windows/misc/tstring.h +++ b/windows/misc/tstring.h @@ -1,20 +1,20 @@ -/** - * @file tstring.h - * @brief 文字列クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include - -namespace std -{ -#ifdef _UNICODE -typedef wstring tstring; //!< tchar string 型定義 -#else // _UNICODE -typedef string tstring; //!< tchar string型定義 -#endif // _UNICODE -} - -std::tstring LoadTString(UINT uID); -std::tstring LoadTString(LPCTSTR lpString); +/** + * @file tstring.h + * @brief 文字列クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include + +namespace std +{ +#ifdef _UNICODE +typedef wstring tstring; //!< tchar string 型定義 +#else // _UNICODE +typedef string tstring; //!< tchar string型定義 +#endif // _UNICODE +} + +std::tstring LoadTString(UINT uID); +std::tstring LoadTString(LPCTSTR lpString); diff --git a/windows/misc/vc6macros.h b/windows/misc/vc6macros.h old mode 100755 new mode 100644 index 7c2aa7cf..c5267c6e --- a/windows/misc/vc6macros.h +++ b/windows/misc/vc6macros.h @@ -1,63 +1,63 @@ -/** - * @file vc6macros.h - * @brief VC6 用マクロ - */ - -#pragma once - -#ifdef __cplusplus - -#ifndef _countof -#define _countof(x) (sizeof((x)) / sizeof((x)[0])) /*!< countof */ -#endif /* _countof */ - -#if (_MSC_VER < 1300) -#define for if (0 /*NEVER*/) { /* no process */ } else for /*!< for scope */ -#endif /* (_MSC_VER < 1300) */ - -#endif /* __cplusplus */ - -#ifndef GET_X_LPARAM -#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) /*!< x-coordinate from LPARAM */ -#endif -#ifndef GET_Y_LPARAM -#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) /*!< y-coordinate from LPARAM */ -#endif - -// for VC6SDK -#if (_MSC_VER < 1300) -#ifndef LONG_PTR -#define LONG_PTR LONG /*!< LONG_PTR */ -#endif -#ifndef DWORD_PTR -#define DWORD_PTR DWORD /*!< DWORD_PTR */ -#endif -#ifndef GetWindowLongPtr -#define GetWindowLongPtr GetWindowLong /*!< Retrieves information about the specified window */ -#endif -#ifndef SetWindowLongPtr -#define SetWindowLongPtr SetWindowLong /*!< Changes an attribute of the specified window */ -#endif -#ifndef GWLP_WNDPROC -#define GWLP_WNDPROC GWL_WNDPROC /*!< Retrieves the pointer to the window procedure */ -#endif -#ifndef GWLP_HINSTANCE -#define GWLP_HINSTANCE GWL_HINSTANCE /*!< Retrieves a handle to the application instance */ -#endif -#ifndef GWLP_HWNDPARENT -#define GWLP_HWNDPARENT GWL_HWNDPARENT /*!< Retrieves a handle to the parent window */ -#endif -#ifndef GWLP_USERDATA -#define GWLP_USERDATA GWL_USERDATA /*!< Retrieves the user data associated with the window */ -#endif -#ifndef GWLP_ID -#define GWLP_ID GWL_ID /*!< Retrieves the identifier of the window */ -#endif -#endif - -#if (_MSC_VER < 1300) -#if defined(_USE_MATH_DEFINES) && !defined(_MATH_DEFINES_DEFINED) -#define _MATH_DEFINES_DEFINED -#define M_PI 3.14159265358979323846 -#endif -#endif +/** + * @file vc6macros.h + * @brief VC6 用マクロ + */ + +#pragma once + +#ifdef __cplusplus + +#ifndef _countof +#define _countof(x) (sizeof((x)) / sizeof((x)[0])) /*!< countof */ +#endif /* _countof */ + +#if (_MSC_VER < 1300) +#define for if (0 /*NEVER*/) { /* no process */ } else for /*!< for scope */ +#endif /* (_MSC_VER < 1300) */ + +#endif /* __cplusplus */ + +#ifndef GET_X_LPARAM +#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) /*!< x-coordinate from LPARAM */ +#endif +#ifndef GET_Y_LPARAM +#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) /*!< y-coordinate from LPARAM */ +#endif + +// for VC6SDK +#if (_MSC_VER < 1300) +#ifndef LONG_PTR +#define LONG_PTR LONG /*!< LONG_PTR */ +#endif +#ifndef DWORD_PTR +#define DWORD_PTR DWORD /*!< DWORD_PTR */ +#endif +#ifndef GetWindowLongPtr +#define GetWindowLongPtr GetWindowLong /*!< Retrieves information about the specified window */ +#endif +#ifndef SetWindowLongPtr +#define SetWindowLongPtr SetWindowLong /*!< Changes an attribute of the specified window */ +#endif +#ifndef GWLP_WNDPROC +#define GWLP_WNDPROC GWL_WNDPROC /*!< Retrieves the pointer to the window procedure */ +#endif +#ifndef GWLP_HINSTANCE +#define GWLP_HINSTANCE GWL_HINSTANCE /*!< Retrieves a handle to the application instance */ +#endif +#ifndef GWLP_HWNDPARENT +#define GWLP_HWNDPARENT GWL_HWNDPARENT /*!< Retrieves a handle to the parent window */ +#endif +#ifndef GWLP_USERDATA +#define GWLP_USERDATA GWL_USERDATA /*!< Retrieves the user data associated with the window */ +#endif +#ifndef GWLP_ID +#define GWLP_ID GWL_ID /*!< Retrieves the identifier of the window */ +#endif +#endif + +#if (_MSC_VER < 1300) +#if defined(_USE_MATH_DEFINES) && !defined(_MATH_DEFINES_DEFINED) +#define _MATH_DEFINES_DEFINED +#define M_PI 3.14159265358979323846 +#endif +#endif diff --git a/windows/mousemng.cpp b/windows/mousemng.cpp index 4419fa6b..da696883 100644 --- a/windows/mousemng.cpp +++ b/windows/mousemng.cpp @@ -1,573 +1,573 @@ -#define DIRECTINPUT_VERSION 0x0800 - -#include -#include -#include -#include -#include - -#include -//#pragma comment(lib, "dinput8.lib") - -#define DIDFT_OPTIONAL 0x80000000 - -#ifdef SUPPORT_WACOM_TABLET -bool cmwacom_skipMouseEvent(void); -void cmwacom_setExclusiveMode(bool enable); -#endif - -#define MOUSEMNG_RANGE 128 - - -typedef struct { - SINT16 x; - SINT16 y; - UINT8 btn; - UINT flag; -} MOUSEMNG; - -static MOUSEMNG mousemng; -MOUSEMNGSTAT mousemngstat; -static int mousecaptureflg = 0; - -static int mousecursorcurhide = 0; -static int lastmouseon = 0; -static int mousecursorhidepending = 0; - -static int mouseMul = 1; // マウススピード倍率(分子) -static int mouseDiv = 1; // マウススピード倍率(分母) - -static int mousebufX = 0; // マウス移動バッファ(X) -static int mousebufY = 0; // マウス移動バッファ(Y) - -static int mouseposX = 0; // マウス絶対位置(X) 0〜65535 -static int mouseposY = 0; // マウス絶対位置 0〜65535 - -// RAWマウス入力対応 np21w ver0.86 rev13 -static LPDIRECTINPUT8 dinput = NULL; -static LPDIRECTINPUTDEVICE8 diRawMouse = NULL; -static int mouseRawDeltaX = 0; -static int mouseRawDeltaY = 0; - -typedef HRESULT (WINAPI *FN_DIRECTINPUT8CREATE)(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter); - -static HMODULE hModuleDI8 = NULL; -static FN_DIRECTINPUT8CREATE fndi8create = NULL; - -static DWORD mousemng_UIthreadID = 0; -static bool mousemng_requestCreateInput = false; -static bool mousemng_requestAcquire = false; -static CRITICAL_SECTION mousemng_multithread_deviceinit_cs = { 0 }; - -extern UINT8 np2userpause; - -BRESULT mousemng_checkdinput8(){ - if (mousemng_UIthreadID != GetCurrentThreadId()) return FAILURE; // 別のスレッドからのアクセスは不可 - - // DirectInput8が使用できるかチェック - LPDIRECTINPUT8 test_dinput = NULL; - LPDIRECTINPUTDEVICE8 test_didevice = NULL; - - if(fndi8create) return(SUCCESS); - - hModuleDI8 = LoadLibrary(_T("dinput8.dll")); - if(!hModuleDI8){ - goto scre_err; - } - - fndi8create = (FN_DIRECTINPUT8CREATE)GetProcAddress(hModuleDI8, "DirectInput8Create"); - if(!fndi8create){ - goto scre_err2; - } - if(FAILED(fndi8create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&test_dinput, NULL))){ - goto scre_err2; - } - if(FAILED(test_dinput->CreateDevice(GUID_SysMouse, &test_didevice, NULL))){ - goto scre_err3; - } - - // デバイス作成まで出来そうならOKとする - test_didevice->Release(); - test_dinput->Release(); - - return(SUCCESS); -scre_err3: - test_dinput->Release(); -scre_err2: - FreeLibrary(hModuleDI8); -scre_err: - hModuleDI8 = NULL; - fndi8create = NULL; - return(FAILURE); -} - -UINT8 mousemng_getstat(SINT16 *x, SINT16 *y, int clear) { -#ifdef SUPPORT_WACOM_TABLET - if(cmwacom_skipMouseEvent()){ - mousemng.x = 0; - mousemng.y = 0; - } -#endif - *x = mousemng.x; - *y = mousemng.y; - if (clear) { - mousemng.x = 0; - mousemng.y = 0; - } - return(mousemng.btn); -} -void mousemng_setstat(SINT16 x, SINT16 y, UINT8 btn) { - if (mousemng.flag){ - mousemng.x = x; - mousemng.y = y; - mousemng.btn = btn; - } -} - -UINT8 mousemng_supportrawinput() { - return(dinput && diRawMouse); -} - -void mousemng_updatespeed() { - np2_multithread_EnterCriticalSection(); - mouseMul = np2oscfg.mousemul != 0 ? np2oscfg.mousemul : 1; - mouseDiv = np2oscfg.mousediv != 0 ? np2oscfg.mousediv : 1; - np2_multithread_LeaveCriticalSection(); -} - -UINT8 mousemng_getabspos(int* x, int* y) -{ - if (mousecaptureflg || !np2oscfg.mouse_nc) - { - return 0; // キャプチャ中やキャプチャなし操作無効の場合は絶対座標不可 - } -#ifdef SUPPORT_WACOM_TABLET - if (cmwacom_skipMouseEvent()) - { - mousemng.x = 0; - mousemng.y = 0; - } -#endif - np2_multithread_EnterCriticalSection(); - *x = mouseposX; - *y = mouseposY; - mouseDiv = np2oscfg.mousediv != 0 ? np2oscfg.mousediv : 1; - np2_multithread_LeaveCriticalSection(); - return 1; -} -void mousemng_setabspos(int x, int y) -{ - np2_multithread_EnterCriticalSection(); - mouseposX = x; - mouseposY = y; - np2_multithread_LeaveCriticalSection(); -} - -// ---- - -static void getmaincenter(POINT *cp) { - - RECT rct; - - GetWindowRect(g_hWndMain, &rct); - cp->x = (rct.right + rct.left) / 2; - cp->y = (rct.bottom + rct.top) / 2; -} - -static void initDirectInput(){ - if (mousemng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 - - HRESULT hr; - DIOBJECTDATAFORMAT obj[7]; - DIDATAFORMAT dimouse_format; - dimouse_format.dwSize = sizeof(DIDATAFORMAT); - dimouse_format.dwObjSize = sizeof(DIOBJECTDATAFORMAT); - dimouse_format.dwFlags = DIDF_RELAXIS; - dimouse_format.dwDataSize = 16; - dimouse_format.dwNumObjs = 7; - dimouse_format.rgodf = obj; - obj[0].dwOfs = 0; - obj[0].pguid = &GUID_XAxis; - obj[0].dwType = DIDFT_ANYINSTANCE | DIDFT_AXIS; - obj[0].dwFlags = 0; - obj[1].dwOfs = 4; - obj[1].pguid = &GUID_YAxis; - obj[1].dwType = DIDFT_ANYINSTANCE | DIDFT_AXIS; - obj[1].dwFlags = 0; - obj[2].dwOfs = 8; - obj[2].pguid = &GUID_ZAxis; - obj[2].dwType = DIDFT_ANYINSTANCE | DIDFT_OPTIONAL | DIDFT_AXIS; - obj[2].dwFlags = 0; - obj[3].dwOfs = 12; - obj[3].pguid = NULL; - obj[3].dwType = DIDFT_ANYINSTANCE | DIDFT_BUTTON; - obj[3].dwFlags = 0; - obj[4].dwOfs = 13; - obj[4].pguid = NULL; - obj[4].dwType = DIDFT_ANYINSTANCE | DIDFT_BUTTON; - obj[4].dwFlags = 0; - obj[5].dwOfs = 14; - obj[5].pguid = NULL; - obj[5].dwType = DIDFT_ANYINSTANCE | DIDFT_OPTIONAL | DIDFT_BUTTON; - obj[5].dwFlags = 0; - obj[6].dwOfs = 15; - obj[6].pguid = NULL; - obj[6].dwType = DIDFT_ANYINSTANCE | DIDFT_OPTIONAL | DIDFT_BUTTON; - obj[6].dwFlags = 0; - - EnterCriticalSection(&mousemng_multithread_deviceinit_cs); - if(fndi8create && !dinput){ - //hr = DirectInputCreateEx(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput7, (void**)&dinput, NULL); - //hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&dinput, NULL); // 関数名変えてやがった( ゚д゚) - hr = fndi8create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&dinput, NULL); - if (!FAILED(hr)){ - hr = dinput->CreateDevice(GUID_SysMouse, &diRawMouse, NULL); - if (!FAILED(hr)){ - // データフォーマット設定 - hr = diRawMouse->SetDataFormat(&dimouse_format); - if (!FAILED(hr)){ - // 協調レベル設定 - hr = diRawMouse->SetCooperativeLevel(g_hWndMain, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); - } - if (!FAILED(hr)){ - // デバイス設定 - DIPROPDWORD diprop; - diprop.diph.dwSize = sizeof(diprop); - diprop.diph.dwHeaderSize = sizeof(diprop.diph); - diprop.diph.dwObj = 0; - diprop.diph.dwHow = DIPH_DEVICE; - diprop.dwData = DIPROPAXISMODE_REL; // 相対値モード - hr = diRawMouse->SetProperty(DIPROP_AXISMODE, &diprop.diph); - } - if (!FAILED(hr)) { - // 入力開始 - hr = diRawMouse->Acquire(); - }else{ - // 失敗・・・ - diRawMouse->Release(); - diRawMouse = NULL; - dinput->Release(); - dinput = NULL; - } - }else{ - // 失敗・・・ - diRawMouse = NULL; - dinput->Release(); - dinput = NULL; - } - }else{ - // 失敗・・・ - dinput = NULL; - } - }else{ - if (diRawMouse) - { - hr = diRawMouse->Acquire(); - } - } - LeaveCriticalSection(&mousemng_multithread_deviceinit_cs); -} -static void destroyDirectInput(){ - if (mousemng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 - - EnterCriticalSection(&mousemng_multithread_deviceinit_cs); - if(diRawMouse){ - diRawMouse->Release(); - diRawMouse = NULL; - } - if(dinput){ - dinput->Release(); - dinput = NULL; - } - if(hModuleDI8){ - FreeLibrary(hModuleDI8); - hModuleDI8 = NULL; - fndi8create = NULL; - } - LeaveCriticalSection(&mousemng_multithread_deviceinit_cs); -} - -static void mousecapture(BOOL capture) { - if (mousemng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 - - LONG style; - POINT cp; - RECT rct; - -#ifdef SUPPORT_WACOM_TABLET - cmwacom_setExclusiveMode(capture ? true : false); -#endif - - if(np2oscfg.rawmouse){ - if(mousemng_checkdinput8()!=SUCCESS){ - np2_multithread_LeaveCriticalSection(); - np2oscfg.rawmouse = 0; - MessageBox(g_hWndMain, _T("Failed to initialize DirectInput8."), _T("DirectInput Error"), MB_OK|MB_ICONEXCLAMATION); - return; - } - } - - mousemng_updatespeed(); - - style = GetClassLong(g_hWndMain, GCL_STYLE); - if (capture) { - ShowCursor(FALSE); - getmaincenter(&cp); - rct.left = cp.x - MOUSEMNG_RANGE; - rct.right = cp.x + MOUSEMNG_RANGE; - rct.top = cp.y - MOUSEMNG_RANGE; - rct.bottom = cp.y + MOUSEMNG_RANGE; - SetCursorPos(cp.x, cp.y); - ClipCursor(&rct); - style &= ‾(CS_DBLCLKS); - mousecaptureflg = 1; - if(np2oscfg.rawmouse && fndi8create){ - initDirectInput(); - } - } - else { - ShowCursor(TRUE); - ClipCursor(NULL); - if (np2oscfg.mouse_nc) { - style &= ‾(CS_DBLCLKS); - } - else { - style |= CS_DBLCLKS; - } - mousecaptureflg = 0; - EnterCriticalSection(&mousemng_multithread_deviceinit_cs); - if(np2oscfg.rawmouse && fndi8create && diRawMouse){ - diRawMouse->Unacquire(); - //destroyDirectInput(); - } - LeaveCriticalSection(&mousemng_multithread_deviceinit_cs); - } - SetClassLong(g_hWndMain, GCL_STYLE, style); -} - -void mousemng_initialize(void) { - - InitializeCriticalSection(&mousemng_multithread_deviceinit_cs); - - mousemng_UIthreadID = GetCurrentThreadId(); - - np2_multithread_EnterCriticalSection(); - ZeroMemory(&mousemng, sizeof(mousemng)); - mousemng.btn = uPD8255A_LEFTBIT | uPD8255A_RIGHTBIT; - mousemng.flag = (1 << MOUSEPROC_SYSTEM); - np2_multithread_LeaveCriticalSection(); - - mousemng_updatespeed(); -} - -void mousemng_reset(void) -{ - mousemng_setautohidecursor(0); -} - -void mousemng_destroy(void) { - if (mousemng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 - - destroyDirectInput(); - - DeleteCriticalSection(&mousemng_multithread_deviceinit_cs); -} - -void mousemng_UIThreadSync() -{ - if (mousemng_requestCreateInput) - { - mousemng_requestCreateInput = false; - destroyDirectInput(); - initDirectInput(); - } - if (mousemng_requestAcquire) - { - mousemng_requestAcquire = false; - EnterCriticalSection(&mousemng_multithread_deviceinit_cs); - if (diRawMouse) - { - diRawMouse->Acquire(); - } - LeaveCriticalSection(&mousemng_multithread_deviceinit_cs); - } - if (mousecursorhidepending) - { - mousecursorhidepending = 0; - mousemng_updatemouseon(lastmouseon); - } -} - -void mousemng_sync(void) { - POINT p; - POINT cp; - - if ((!mousemng.flag) && (GetCursorPos(&p))) { - getmaincenter(&cp); - if (np2oscfg.rawmouse && fndi8create && dinput == NULL) - { - mousemng_requestCreateInput = true; - PostMessage(g_hWndMain, WM_NULL, 0, 0); - } - EnterCriticalSection(&mousemng_multithread_deviceinit_cs); - if(np2oscfg.rawmouse && fndi8create && mousemng_supportrawinput()){ - DIMOUSESTATE diMouseState = {0}; - HRESULT hr; - hr = diRawMouse->GetDeviceState(sizeof(DIMOUSESTATE), &diMouseState); - if (hr != DI_OK){ - switch(hr){ - case E_PENDING: - break; - case DIERR_INPUTLOST: - case DIERR_NOTACQUIRED: - mousemng_requestAcquire = true; - PostMessage(g_hWndMain, WM_NULL, 0, 0); - break; - case DIERR_NOTINITIALIZED: - case DIERR_INVALIDPARAM: - default: - mousemng_requestCreateInput = true; - PostMessage(g_hWndMain, WM_NULL, 0, 0); - break; - } - }else{ - mousebufX += (diMouseState.lX*mouseMul); - mousebufY += (diMouseState.lY*mouseMul); - } - }else{ - mousebufX += (p.x - cp.x)*mouseMul; - mousebufY += (p.y - cp.y)*mouseMul; - } - LeaveCriticalSection(&mousemng_multithread_deviceinit_cs); - if(mousebufX >= mouseDiv || mousebufX <= -mouseDiv){ - mousemng.x += (SINT16)(mousebufX / mouseDiv); - mousebufX = mousebufX % mouseDiv; - } - if(mousebufY >= mouseDiv || mousebufY <= -mouseDiv){ - mousemng.y += (SINT16)(mousebufY / mouseDiv); - mousebufY = mousebufY % mouseDiv; - } - //mousemng.x += (SINT16)((p.x - cp.x));// / 2); - //mousemng.y += (SINT16)((p.y - cp.y));// / 2); - SetCursorPos(cp.x, cp.y); - } -} - -BOOL mousemng_buttonevent(UINT event) { - - np2_multithread_EnterCriticalSection(); - if (!mousemng.flag || (np2oscfg.mouse_nc/* && !scrnmng_isfullscreen()*/ && mousemng.flag)) { - switch(event) { - case MOUSEMNG_LEFTDOWN: - mousemng.btn &= ‾(uPD8255A_LEFTBIT); - break; - - case MOUSEMNG_LEFTUP: - mousemng.btn |= uPD8255A_LEFTBIT; - break; - - case MOUSEMNG_RIGHTDOWN: - mousemng.btn &= ‾(uPD8255A_RIGHTBIT); - break; - - case MOUSEMNG_RIGHTUP: - mousemng.btn |= uPD8255A_RIGHTBIT; - break; - } - np2_multithread_LeaveCriticalSection(); - return(TRUE); - } - else { - np2_multithread_LeaveCriticalSection(); - return(FALSE); - } -} - -void mousemng_enable(UINT proc) { - - UINT bit; - - np2_multithread_EnterCriticalSection(); - bit = 1 << proc; - if (mousemng.flag & bit) { - mousemng.flag &= ‾bit; - if (!mousemng.flag) { - mousecapture(TRUE); - } - } - np2_multithread_LeaveCriticalSection(); -} - -void mousemng_disable(UINT proc) { - - np2_multithread_EnterCriticalSection(); - if (!mousemng.flag) { - mousecapture(FALSE); - } - mousemng.flag |= (1 << proc); - np2_multithread_LeaveCriticalSection(); -} - -void mousemng_toggle(UINT proc) { - - np2_multithread_EnterCriticalSection(); - if (!mousemng.flag) { - mousecapture(FALSE); - } - mousemng.flag ^= (1 << proc); - if (!mousemng.flag) { - mousecapture(TRUE); - } - np2_multithread_LeaveCriticalSection(); -} - -void mousemng_updateclip(){ - //np2_multithread_EnterCriticalSection(); - if(mousecaptureflg){ - mousecapture(FALSE); - mousecapture(TRUE); // キャプチャし直し - } - //np2_multithread_LeaveCriticalSection(); -} - -void mousemng_setautohidecursor(int autohide) -{ - mousemngstat.autohide = autohide ? 1 : 0; - mousecursorhidepending = 1; -} -int mousemng_getautohidecursor(void) -{ - return mousemngstat.autohide; -} -void mousemng_updateautohidecursor(void) -{ - mousecursorhidepending = 1; -} - -void mousemng_updatemouseon(int mouseon) -{ - int newmousecursorcurhide = mousecursorcurhide; - - lastmouseon = mouseon; - if (mouseon && mousemngstat.autohide && np2oscfg.mouse_nc && !np2userpause) - { - newmousecursorcurhide = 1; - } - else - { - newmousecursorcurhide = 0; - } - - if (mousecursorcurhide != newmousecursorcurhide) - { - mousecursorcurhide = newmousecursorcurhide; - if (mousecursorcurhide) - { - ShowCursor(FALSE); - } - else - { - ShowCursor(TRUE); - } - } +#define DIRECTINPUT_VERSION 0x0800 + +#include +#include +#include +#include +#include + +#include +//#pragma comment(lib, "dinput8.lib") + +#define DIDFT_OPTIONAL 0x80000000 + +#ifdef SUPPORT_WACOM_TABLET +bool cmwacom_skipMouseEvent(void); +void cmwacom_setExclusiveMode(bool enable); +#endif + +#define MOUSEMNG_RANGE 128 + + +typedef struct { + SINT16 x; + SINT16 y; + UINT8 btn; + UINT flag; +} MOUSEMNG; + +static MOUSEMNG mousemng; +MOUSEMNGSTAT mousemngstat; +static int mousecaptureflg = 0; + +static int mousecursorcurhide = 0; +static int lastmouseon = 0; +static int mousecursorhidepending = 0; + +static int mouseMul = 1; // マウススピード倍率(分子) +static int mouseDiv = 1; // マウススピード倍率(分母) + +static int mousebufX = 0; // マウス移動バッファ(X) +static int mousebufY = 0; // マウス移動バッファ(Y) + +static int mouseposX = 0; // マウス絶対位置(X) 0〜65535 +static int mouseposY = 0; // マウス絶対位置 0〜65535 + +// RAWマウス入力対応 np21w ver0.86 rev13 +static LPDIRECTINPUT8 dinput = NULL; +static LPDIRECTINPUTDEVICE8 diRawMouse = NULL; +static int mouseRawDeltaX = 0; +static int mouseRawDeltaY = 0; + +typedef HRESULT (WINAPI *FN_DIRECTINPUT8CREATE)(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter); + +static HMODULE hModuleDI8 = NULL; +static FN_DIRECTINPUT8CREATE fndi8create = NULL; + +static DWORD mousemng_UIthreadID = 0; +static bool mousemng_requestCreateInput = false; +static bool mousemng_requestAcquire = false; +static CRITICAL_SECTION mousemng_multithread_deviceinit_cs = { 0 }; + +extern UINT8 np2userpause; + +BRESULT mousemng_checkdinput8(){ + if (mousemng_UIthreadID != GetCurrentThreadId()) return FAILURE; // 別のスレッドからのアクセスは不可 + + // DirectInput8が使用できるかチェック + LPDIRECTINPUT8 test_dinput = NULL; + LPDIRECTINPUTDEVICE8 test_didevice = NULL; + + if(fndi8create) return(SUCCESS); + + hModuleDI8 = LoadLibrary(_T("dinput8.dll")); + if(!hModuleDI8){ + goto scre_err; + } + + fndi8create = (FN_DIRECTINPUT8CREATE)GetProcAddress(hModuleDI8, "DirectInput8Create"); + if(!fndi8create){ + goto scre_err2; + } + if(FAILED(fndi8create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&test_dinput, NULL))){ + goto scre_err2; + } + if(FAILED(test_dinput->CreateDevice(GUID_SysMouse, &test_didevice, NULL))){ + goto scre_err3; + } + + // デバイス作成まで出来そうならOKとする + test_didevice->Release(); + test_dinput->Release(); + + return(SUCCESS); +scre_err3: + test_dinput->Release(); +scre_err2: + FreeLibrary(hModuleDI8); +scre_err: + hModuleDI8 = NULL; + fndi8create = NULL; + return(FAILURE); +} + +UINT8 mousemng_getstat(SINT16 *x, SINT16 *y, int clear) { +#ifdef SUPPORT_WACOM_TABLET + if(cmwacom_skipMouseEvent()){ + mousemng.x = 0; + mousemng.y = 0; + } +#endif + *x = mousemng.x; + *y = mousemng.y; + if (clear) { + mousemng.x = 0; + mousemng.y = 0; + } + return(mousemng.btn); +} +void mousemng_setstat(SINT16 x, SINT16 y, UINT8 btn) { + if (mousemng.flag){ + mousemng.x = x; + mousemng.y = y; + mousemng.btn = btn; + } +} + +UINT8 mousemng_supportrawinput() { + return(dinput && diRawMouse); +} + +void mousemng_updatespeed() { + np2_multithread_EnterCriticalSection(); + mouseMul = np2oscfg.mousemul != 0 ? np2oscfg.mousemul : 1; + mouseDiv = np2oscfg.mousediv != 0 ? np2oscfg.mousediv : 1; + np2_multithread_LeaveCriticalSection(); +} + +UINT8 mousemng_getabspos(int* x, int* y) +{ + if (mousecaptureflg || !np2oscfg.mouse_nc) + { + return 0; // キャプチャ中やキャプチャなし操作無効の場合は絶対座標不可 + } +#ifdef SUPPORT_WACOM_TABLET + if (cmwacom_skipMouseEvent()) + { + mousemng.x = 0; + mousemng.y = 0; + } +#endif + np2_multithread_EnterCriticalSection(); + *x = mouseposX; + *y = mouseposY; + mouseDiv = np2oscfg.mousediv != 0 ? np2oscfg.mousediv : 1; + np2_multithread_LeaveCriticalSection(); + return 1; +} +void mousemng_setabspos(int x, int y) +{ + np2_multithread_EnterCriticalSection(); + mouseposX = x; + mouseposY = y; + np2_multithread_LeaveCriticalSection(); +} + +// ---- + +static void getmaincenter(POINT *cp) { + + RECT rct; + + GetWindowRect(g_hWndMain, &rct); + cp->x = (rct.right + rct.left) / 2; + cp->y = (rct.bottom + rct.top) / 2; +} + +static void initDirectInput(){ + if (mousemng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 + + HRESULT hr; + DIOBJECTDATAFORMAT obj[7]; + DIDATAFORMAT dimouse_format; + dimouse_format.dwSize = sizeof(DIDATAFORMAT); + dimouse_format.dwObjSize = sizeof(DIOBJECTDATAFORMAT); + dimouse_format.dwFlags = DIDF_RELAXIS; + dimouse_format.dwDataSize = 16; + dimouse_format.dwNumObjs = 7; + dimouse_format.rgodf = obj; + obj[0].dwOfs = 0; + obj[0].pguid = &GUID_XAxis; + obj[0].dwType = DIDFT_ANYINSTANCE | DIDFT_AXIS; + obj[0].dwFlags = 0; + obj[1].dwOfs = 4; + obj[1].pguid = &GUID_YAxis; + obj[1].dwType = DIDFT_ANYINSTANCE | DIDFT_AXIS; + obj[1].dwFlags = 0; + obj[2].dwOfs = 8; + obj[2].pguid = &GUID_ZAxis; + obj[2].dwType = DIDFT_ANYINSTANCE | DIDFT_OPTIONAL | DIDFT_AXIS; + obj[2].dwFlags = 0; + obj[3].dwOfs = 12; + obj[3].pguid = NULL; + obj[3].dwType = DIDFT_ANYINSTANCE | DIDFT_BUTTON; + obj[3].dwFlags = 0; + obj[4].dwOfs = 13; + obj[4].pguid = NULL; + obj[4].dwType = DIDFT_ANYINSTANCE | DIDFT_BUTTON; + obj[4].dwFlags = 0; + obj[5].dwOfs = 14; + obj[5].pguid = NULL; + obj[5].dwType = DIDFT_ANYINSTANCE | DIDFT_OPTIONAL | DIDFT_BUTTON; + obj[5].dwFlags = 0; + obj[6].dwOfs = 15; + obj[6].pguid = NULL; + obj[6].dwType = DIDFT_ANYINSTANCE | DIDFT_OPTIONAL | DIDFT_BUTTON; + obj[6].dwFlags = 0; + + EnterCriticalSection(&mousemng_multithread_deviceinit_cs); + if(fndi8create && !dinput){ + //hr = DirectInputCreateEx(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput7, (void**)&dinput, NULL); + //hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&dinput, NULL); // 関数名変えてやがった( ゚д゚) + hr = fndi8create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&dinput, NULL); + if (!FAILED(hr)){ + hr = dinput->CreateDevice(GUID_SysMouse, &diRawMouse, NULL); + if (!FAILED(hr)){ + // データフォーマット設定 + hr = diRawMouse->SetDataFormat(&dimouse_format); + if (!FAILED(hr)){ + // 協調レベル設定 + hr = diRawMouse->SetCooperativeLevel(g_hWndMain, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND); + } + if (!FAILED(hr)){ + // デバイス設定 + DIPROPDWORD diprop; + diprop.diph.dwSize = sizeof(diprop); + diprop.diph.dwHeaderSize = sizeof(diprop.diph); + diprop.diph.dwObj = 0; + diprop.diph.dwHow = DIPH_DEVICE; + diprop.dwData = DIPROPAXISMODE_REL; // 相対値モード + hr = diRawMouse->SetProperty(DIPROP_AXISMODE, &diprop.diph); + } + if (!FAILED(hr)) { + // 入力開始 + hr = diRawMouse->Acquire(); + }else{ + // 失敗・・・ + diRawMouse->Release(); + diRawMouse = NULL; + dinput->Release(); + dinput = NULL; + } + }else{ + // 失敗・・・ + diRawMouse = NULL; + dinput->Release(); + dinput = NULL; + } + }else{ + // 失敗・・・ + dinput = NULL; + } + }else{ + if (diRawMouse) + { + hr = diRawMouse->Acquire(); + } + } + LeaveCriticalSection(&mousemng_multithread_deviceinit_cs); +} +static void destroyDirectInput(){ + if (mousemng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 + + EnterCriticalSection(&mousemng_multithread_deviceinit_cs); + if(diRawMouse){ + diRawMouse->Release(); + diRawMouse = NULL; + } + if(dinput){ + dinput->Release(); + dinput = NULL; + } + if(hModuleDI8){ + FreeLibrary(hModuleDI8); + hModuleDI8 = NULL; + fndi8create = NULL; + } + LeaveCriticalSection(&mousemng_multithread_deviceinit_cs); +} + +static void mousecapture(BOOL capture) { + if (mousemng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 + + LONG style; + POINT cp; + RECT rct; + +#ifdef SUPPORT_WACOM_TABLET + cmwacom_setExclusiveMode(capture ? true : false); +#endif + + if(np2oscfg.rawmouse){ + if(mousemng_checkdinput8()!=SUCCESS){ + np2_multithread_LeaveCriticalSection(); + np2oscfg.rawmouse = 0; + MessageBox(g_hWndMain, _T("Failed to initialize DirectInput8."), _T("DirectInput Error"), MB_OK|MB_ICONEXCLAMATION); + return; + } + } + + mousemng_updatespeed(); + + style = GetClassLong(g_hWndMain, GCL_STYLE); + if (capture) { + ShowCursor(FALSE); + getmaincenter(&cp); + rct.left = cp.x - MOUSEMNG_RANGE; + rct.right = cp.x + MOUSEMNG_RANGE; + rct.top = cp.y - MOUSEMNG_RANGE; + rct.bottom = cp.y + MOUSEMNG_RANGE; + SetCursorPos(cp.x, cp.y); + ClipCursor(&rct); + style &= ‾(CS_DBLCLKS); + mousecaptureflg = 1; + if(np2oscfg.rawmouse && fndi8create){ + initDirectInput(); + } + } + else { + ShowCursor(TRUE); + ClipCursor(NULL); + if (np2oscfg.mouse_nc) { + style &= ‾(CS_DBLCLKS); + } + else { + style |= CS_DBLCLKS; + } + mousecaptureflg = 0; + EnterCriticalSection(&mousemng_multithread_deviceinit_cs); + if(np2oscfg.rawmouse && fndi8create && diRawMouse){ + diRawMouse->Unacquire(); + //destroyDirectInput(); + } + LeaveCriticalSection(&mousemng_multithread_deviceinit_cs); + } + SetClassLong(g_hWndMain, GCL_STYLE, style); +} + +void mousemng_initialize(void) { + + InitializeCriticalSection(&mousemng_multithread_deviceinit_cs); + + mousemng_UIthreadID = GetCurrentThreadId(); + + np2_multithread_EnterCriticalSection(); + ZeroMemory(&mousemng, sizeof(mousemng)); + mousemng.btn = uPD8255A_LEFTBIT | uPD8255A_RIGHTBIT; + mousemng.flag = (1 << MOUSEPROC_SYSTEM); + np2_multithread_LeaveCriticalSection(); + + mousemng_updatespeed(); +} + +void mousemng_reset(void) +{ + mousemng_setautohidecursor(0); +} + +void mousemng_destroy(void) { + if (mousemng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 + + destroyDirectInput(); + + DeleteCriticalSection(&mousemng_multithread_deviceinit_cs); +} + +void mousemng_UIThreadSync() +{ + if (mousemng_requestCreateInput) + { + mousemng_requestCreateInput = false; + destroyDirectInput(); + initDirectInput(); + } + if (mousemng_requestAcquire) + { + mousemng_requestAcquire = false; + EnterCriticalSection(&mousemng_multithread_deviceinit_cs); + if (diRawMouse) + { + diRawMouse->Acquire(); + } + LeaveCriticalSection(&mousemng_multithread_deviceinit_cs); + } + if (mousecursorhidepending) + { + mousecursorhidepending = 0; + mousemng_updatemouseon(lastmouseon); + } +} + +void mousemng_sync(void) { + POINT p; + POINT cp; + + if ((!mousemng.flag) && (GetCursorPos(&p))) { + getmaincenter(&cp); + if (np2oscfg.rawmouse && fndi8create && dinput == NULL) + { + mousemng_requestCreateInput = true; + PostMessage(g_hWndMain, WM_NULL, 0, 0); + } + EnterCriticalSection(&mousemng_multithread_deviceinit_cs); + if(np2oscfg.rawmouse && fndi8create && mousemng_supportrawinput()){ + DIMOUSESTATE diMouseState = {0}; + HRESULT hr; + hr = diRawMouse->GetDeviceState(sizeof(DIMOUSESTATE), &diMouseState); + if (hr != DI_OK){ + switch(hr){ + case E_PENDING: + break; + case DIERR_INPUTLOST: + case DIERR_NOTACQUIRED: + mousemng_requestAcquire = true; + PostMessage(g_hWndMain, WM_NULL, 0, 0); + break; + case DIERR_NOTINITIALIZED: + case DIERR_INVALIDPARAM: + default: + mousemng_requestCreateInput = true; + PostMessage(g_hWndMain, WM_NULL, 0, 0); + break; + } + }else{ + mousebufX += (diMouseState.lX*mouseMul); + mousebufY += (diMouseState.lY*mouseMul); + } + }else{ + mousebufX += (p.x - cp.x)*mouseMul; + mousebufY += (p.y - cp.y)*mouseMul; + } + LeaveCriticalSection(&mousemng_multithread_deviceinit_cs); + if(mousebufX >= mouseDiv || mousebufX <= -mouseDiv){ + mousemng.x += (SINT16)(mousebufX / mouseDiv); + mousebufX = mousebufX % mouseDiv; + } + if(mousebufY >= mouseDiv || mousebufY <= -mouseDiv){ + mousemng.y += (SINT16)(mousebufY / mouseDiv); + mousebufY = mousebufY % mouseDiv; + } + //mousemng.x += (SINT16)((p.x - cp.x));// / 2); + //mousemng.y += (SINT16)((p.y - cp.y));// / 2); + SetCursorPos(cp.x, cp.y); + } +} + +BOOL mousemng_buttonevent(UINT event) { + + np2_multithread_EnterCriticalSection(); + if (!mousemng.flag || (np2oscfg.mouse_nc/* && !scrnmng_isfullscreen()*/ && mousemng.flag)) { + switch(event) { + case MOUSEMNG_LEFTDOWN: + mousemng.btn &= ‾(uPD8255A_LEFTBIT); + break; + + case MOUSEMNG_LEFTUP: + mousemng.btn |= uPD8255A_LEFTBIT; + break; + + case MOUSEMNG_RIGHTDOWN: + mousemng.btn &= ‾(uPD8255A_RIGHTBIT); + break; + + case MOUSEMNG_RIGHTUP: + mousemng.btn |= uPD8255A_RIGHTBIT; + break; + } + np2_multithread_LeaveCriticalSection(); + return(TRUE); + } + else { + np2_multithread_LeaveCriticalSection(); + return(FALSE); + } +} + +void mousemng_enable(UINT proc) { + + UINT bit; + + np2_multithread_EnterCriticalSection(); + bit = 1 << proc; + if (mousemng.flag & bit) { + mousemng.flag &= ‾bit; + if (!mousemng.flag) { + mousecapture(TRUE); + } + } + np2_multithread_LeaveCriticalSection(); +} + +void mousemng_disable(UINT proc) { + + np2_multithread_EnterCriticalSection(); + if (!mousemng.flag) { + mousecapture(FALSE); + } + mousemng.flag |= (1 << proc); + np2_multithread_LeaveCriticalSection(); +} + +void mousemng_toggle(UINT proc) { + + np2_multithread_EnterCriticalSection(); + if (!mousemng.flag) { + mousecapture(FALSE); + } + mousemng.flag ^= (1 << proc); + if (!mousemng.flag) { + mousecapture(TRUE); + } + np2_multithread_LeaveCriticalSection(); +} + +void mousemng_updateclip(){ + //np2_multithread_EnterCriticalSection(); + if(mousecaptureflg){ + mousecapture(FALSE); + mousecapture(TRUE); // キャプチャし直し + } + //np2_multithread_LeaveCriticalSection(); +} + +void mousemng_setautohidecursor(int autohide) +{ + mousemngstat.autohide = autohide ? 1 : 0; + mousecursorhidepending = 1; +} +int mousemng_getautohidecursor(void) +{ + return mousemngstat.autohide; +} +void mousemng_updateautohidecursor(void) +{ + mousecursorhidepending = 1; +} + +void mousemng_updatemouseon(int mouseon) +{ + int newmousecursorcurhide = mousecursorcurhide; + + lastmouseon = mouseon; + if (mouseon && mousemngstat.autohide && np2oscfg.mouse_nc && !np2userpause) + { + newmousecursorcurhide = 1; + } + else + { + newmousecursorcurhide = 0; + } + + if (mousecursorcurhide != newmousecursorcurhide) + { + mousecursorcurhide = newmousecursorcurhide; + if (mousecursorcurhide) + { + ShowCursor(FALSE); + } + else + { + ShowCursor(TRUE); + } + } } \ No newline at end of file diff --git a/windows/mousemng.h b/windows/mousemng.h old mode 100755 new mode 100644 index 35e6316d..8276859b --- a/windows/mousemng.h +++ b/windows/mousemng.h @@ -1,70 +1,70 @@ - -enum { - uPD8255A_LEFTBIT = 0x80, - uPD8255A_RIGHTBIT = 0x20 -}; - - -typedef struct -{ - UINT32 autohide; -} MOUSEMNGSTAT; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern MOUSEMNGSTAT mousemngstat; - -BRESULT mousemng_checkdinput8(); - -UINT8 mousemng_getstat(SINT16 *x, SINT16 *y, int clear); -void mousemng_setstat(SINT16 x, SINT16 y, UINT8 btn); - -#ifdef __cplusplus -} -#endif - - -// ---- for windows - -enum { - MOUSEMNG_LEFTDOWN = 0, - MOUSEMNG_LEFTUP, - MOUSEMNG_RIGHTDOWN, - MOUSEMNG_RIGHTUP -}; - -enum { - MOUSEPROC_SYSTEM = 0, - MOUSEPROC_WINUI, - MOUSEPROC_BG -}; - -void mousemng_initialize(void); -void mousemng_UIThreadSync(void); -void mousemng_sync(void); -BOOL mousemng_buttonevent(UINT event); -void mousemng_enable(UINT proc); -void mousemng_disable(UINT proc); -void mousemng_toggle(UINT proc); -void mousemng_destroy(void); - -UINT8 mousemng_supportrawinput(); // 生データ入力サポート -void mousemng_updatespeed(); // 生データ入力サポート - -#ifdef __cplusplus -extern "C" { -#endif -void mousemng_updateclip(); -UINT8 mousemng_getabspos(int* x, int* y); -void mousemng_setabspos(int x, int y); -void mousemng_reset(void); -void mousemng_setautohidecursor(int autohide); -int mousemng_getautohidecursor(void); -void mousemng_updateautohidecursor(void); -void mousemng_updatemouseon(int mouseon); -#ifdef __cplusplus -} + +enum { + uPD8255A_LEFTBIT = 0x80, + uPD8255A_RIGHTBIT = 0x20 +}; + + +typedef struct +{ + UINT32 autohide; +} MOUSEMNGSTAT; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern MOUSEMNGSTAT mousemngstat; + +BRESULT mousemng_checkdinput8(); + +UINT8 mousemng_getstat(SINT16 *x, SINT16 *y, int clear); +void mousemng_setstat(SINT16 x, SINT16 y, UINT8 btn); + +#ifdef __cplusplus +} +#endif + + +// ---- for windows + +enum { + MOUSEMNG_LEFTDOWN = 0, + MOUSEMNG_LEFTUP, + MOUSEMNG_RIGHTDOWN, + MOUSEMNG_RIGHTUP +}; + +enum { + MOUSEPROC_SYSTEM = 0, + MOUSEPROC_WINUI, + MOUSEPROC_BG +}; + +void mousemng_initialize(void); +void mousemng_UIThreadSync(void); +void mousemng_sync(void); +BOOL mousemng_buttonevent(UINT event); +void mousemng_enable(UINT proc); +void mousemng_disable(UINT proc); +void mousemng_toggle(UINT proc); +void mousemng_destroy(void); + +UINT8 mousemng_supportrawinput(); // 生データ入力サポート +void mousemng_updatespeed(); // 生データ入力サポート + +#ifdef __cplusplus +extern "C" { +#endif +void mousemng_updateclip(); +UINT8 mousemng_getabspos(int* x, int* y); +void mousemng_setabspos(int x, int y); +void mousemng_reset(void); +void mousemng_setautohidecursor(int autohide); +int mousemng_getautohidecursor(void); +void mousemng_updateautohidecursor(void); +void mousemng_updatemouseon(int mouseon); +#ifdef __cplusplus +} #endif \ No newline at end of file diff --git a/windows/np2.cpp b/windows/np2.cpp index b75c4000..0cfc8704 100644 --- a/windows/np2.cpp +++ b/windows/np2.cpp @@ -1,4713 +1,4713 @@ -/** - * @file np2.cpp - * @brief main window - * - * @author $Author: yui $ - * @date $Date: 2011/02/17 10:36:05 $ - */ - -#include - -// Win2000で動くようにする -#if defined(SUPPORT_WIN2000HOST) -#ifdef _WINDOWS -#ifndef _WIN64 -#define WINVER2 0x0500 -#include "commonfix.h" -#endif -#endif -#endif - -#include -#include -#ifndef __GNUC__ -#include -#endif -#include "resource.h" -#include -#include -#include -#include "np2mt.h" -#include "misc/WndProc.h" -#include "debuguty/viewer.h" -#include "np2arg.h" -#include -#include -#include -#include "misc/tstring.h" -#include -#include "commng/cmmidiin32.h" -#if defined(SUPPORT_VSTi) -#include "commng/vsthost/vsteditwnd.h" -#endif // defined(SUPPORT_VSTi) -#include -#include -#include -#include -#include -#include "winkbd.h" -#include -#include "menu.h" -#include "winloc.h" -#include "sstp.h" -#include "sstpmsg.h" -#include "dialog/np2class.h" -#include "dialog/dialog.h" -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_SMPU98) -#include -#endif -#include -#if defined(SUPPORT_VIDEOFILTER) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(SUPPORT_DEBUGSS) -#include -#endif -#include "subwnd/kdispwnd.h" -#include "subwnd/mdbgwnd.h" -#include "subwnd/skbdwnd.h" -#include "subwnd/subwnd.h" -#include "subwnd/toolwnd.h" -#include -#include -#include -#if !defined(_WIN64) -#include "cputype.h" -#endif -#if defined(SUPPORT_DCLOCK) -#include "subwnd/dclock.h" -#endif -#include "recvideo.h" -#if defined(SUPPORT_IDEIO) -#include -#endif -#if defined(SUPPORT_NET) -#include -#endif -#if defined(SUPPORT_WAB) -#include -#include -#endif -#if defined(SUPPORT_CL_GD5430) -#include -#endif -#include -#include -#if defined(SUPPORT_PHYSICAL_CDDRV) -#include "Dbt.h" -#endif - -#if defined(SUPPORT_IA32_HAXM) -#include -#include -#endif - -#include - -#if defined(CPUCORE_IA32) -extern "C" UINT8 cpu_drawskip; -extern "C" UINT8 cpu_nowait; -#if defined(SUPPORT_ASYNC_CPU) -extern "C" double np2cpu_lastTimingValue; -int np2cpu_lastTimingValid = 0; -#endif -#endif -extern bool scrnmng_create_pending; // グラフィックレンダラ生成保留中 - - -#ifdef SUPPORT_WACOM_TABLET -void cmwacom_setNCControl(bool enable); -#endif - -#ifdef BETA_RELEASE -#define OPENING_WAIT 1500 -#endif - -static TCHAR szClassName[] = _T("NP2-MainWindow"); - HWND g_hWndMain; - HINSTANCE g_hInstance; -#if !defined(_WIN64) - int mmxflag; -#endif - UINT8 np2break = 0; // ver0.30 - BOOL winui_en; - UINT8 g_scrnmode; - - NP2OSCFG np2oscfg = { - OEMTEXT(PROJECTNAME) OEMTEXT(PROJECTSUBNAME), - OEMTEXT("NP2"), - CW_USEDEFAULT, CW_USEDEFAULT, 1, 1, 0, 0, 0, 1, 0, 1, - 0, 1, KEY_UNKNOWN, 0, 0, - 0, 0, 0, {1, 2, 2, 1}, {1, 2, 2, 1}, 0, 1, - {5, 0, 0x3e, 19200, - OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, -#if defined(SUPPORT_NAMED_PIPE) - OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), -#endif - }, -#if defined(SUPPORT_SMPU98) - {5, 0, 0x3e, 19200, - OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, -#if defined(SUPPORT_NAMED_PIPE) - OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), -#endif - }, - {5, 0, 0x3e, 19200, - OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, -#if defined(SUPPORT_NAMED_PIPE) - OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), -#endif - }, -#endif - {0, 0, 0x3e, 19200, - OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, -#if defined(SUPPORT_NAMED_PIPE) - OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), -#endif - }, - {0, 0, 0x3e, 19200, - OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, -#if defined(SUPPORT_NAMED_PIPE) - OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), -#endif - }, - {0, 0, 0x3e, 19200, - OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, -#if defined(SUPPORT_NAMED_PIPE) - OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), -#endif - }, - 0xffffff, 0xffbf6a, 0, 0, - 0, 1, 0, 9801, - 0, 0, -#if !defined(_WIN64) - 0, -#endif - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, FSCRNMOD_SAMEBPP | FSCRNMOD_SAMERES | FSCRNMOD_ASPECTFIX8, 0, - -#if defined(SUPPORT_SCRN_DIRECT3D) - 0, 0, -#endif - - CSoundMng::kDSound3, TEXT(""), - -#if defined(SUPPORT_VSTi) - TEXT("%ProgramFiles%\\Roland\\Sound Canvas VA\\SOUND Canvas VA.dll"), -#endif // defined(SUPPORT_VSTi) - 0, - DRAWTYPE_DIRECTDRAW_HW, - 0, 0, 1, 0, 1, 1, - 0, 0, - 0, 8, - 1, 0, 0, 0, TCMODE_DEFAULT, 0, 100, - 0, -#if defined(SUPPORT_WACOM_TABLET) - 0, -#endif // defined(SUPPORT_WACOM_TABLET) -#if defined(SUPPORT_MULTITHREAD) - 0, -#endif // defined(SUPPORT_MULTITHREAD) - }; - - OEMCHAR fddfolder[MAX_PATH]; - OEMCHAR hddfolder[MAX_PATH]; - OEMCHAR cdfolder[MAX_PATH]; - OEMCHAR bmpfilefolder[MAX_PATH]; - OEMCHAR npcfgfilefolder[MAX_PATH]; - OEMCHAR modulefile[MAX_PATH]; - -static UINT framecnt = 0; -static UINT framecntUI = 0; -static UINT waitcnt = 0; -static UINT framemax = 1; -static UINT8 np2stopemulate = 0; - UINT8 np2userpause = 0; -static int np2opening = 1; -static int np2quitmsg = 0; -static WINLOCEX smwlex; -static HMODULE s_hModResource; -static UINT lateframecount; // フレーム遅れ数 - -static void np2_SetUserPause(UINT8 pause){ - if(np2userpause && !pause){ - CSoundMng::GetInstance()->Enable(SNDPROC_USER); - }else if(!np2userpause && pause){ - CSoundMng::GetInstance()->Disable(SNDPROC_USER); - } - np2userpause = pause; -} - -static void np2_DynamicChangeClockMul(int newClockMul) { - UINT8 oldclockmul = pccore.maxmultiple; - UINT8 oldclockmult = pccore.multiple; - - pccore.multiple = newClockMul; - pccore.maxmultiple = newClockMul; - pccore.realclock = pccore.baseclock * pccore.multiple; - - pcm86_changeclock(oldclockmult); - sound_changeclock(); - beep_changeclock(); - mpu98ii_changeclock(); -#if defined(SUPPORT_SMPU98) - smpu98_changeclock(); -#endif - keyboard_changeclock(); - mouseif_changeclock(); - gdc_updateclock(); -} - -static const OEMCHAR np2help[] = OEMTEXT("np2.chm"); -static const OEMCHAR np2flagext[] = OEMTEXT("S%02d"); -#if defined(_WIN64) -static const OEMCHAR szNp2ResDll[] = OEMTEXT("np2kai_%u_x86_64.dll"); -#else // defined(_WIN64) -static const OEMCHAR szNp2ResDll[] = OEMTEXT("np2kai_%u_i386.dll"); -#endif // defined(_WIN64) - -// ASCII -> 98キーコード表(np21w ver0.86 rev22) -char vkeylist[256] = {0}; -char shift_on[256] = {0}; - -// マルチスレッド用 -#if defined(SUPPORT_MULTITHREAD) -static int np2_multithread_enable = 0; // マルチスレッドモード有効フラグ -static BOOL np2_multithread_initialized = 0; // マルチスレッドモード初期化済みフラグ -static HANDLE np2_multithread_hThread = NULL; // エミュレーション用スレッド -static CRITICAL_SECTION np2_multithread_hThread_cs = {0}; // エミュレーション用スレッド クリティカルセクション -static BOOL np2_multithread_hThread_requestexit = FALSE; // エミュレーション用スレッド 終了要求フラグ -static bool np2_multithread_pauseemulation = false; // エミュレーション一時停止フラグ -static bool np2_multithread_pausing = false; // エミュレーション一時停止中フラグ -static void np2_multithread_Initialize(){ - if(!np2_multithread_initialized){ - InitializeCriticalSection(&np2_multithread_hThread_cs); - np2_multithread_initialized = TRUE; - } -} -static void np2_multithread_fakeWndProc(){ - // グラフィック周りがWndProcが処理される前提になっているので無理やり - MSG msg; - if(PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) - { - if(msg.message != WM_QUIT && msg.message != WM_CLOSE && msg.message != WM_DESTROY){ - GetMessage(&msg, NULL, 0, 0); - if ((msg.hwnd != g_hWndMain) || - ((msg.message != WM_SYSKEYDOWN) && - (msg.message != WM_SYSKEYUP))) { - TranslateMessage(&msg); - } - DispatchMessage(&msg); - } - } -} -void np2_multithread_Suspend(){ - if(!np2_multithread_pauseemulation){ - np2_multithread_pauseemulation = true; - if(np2_multithread_initialized){ - if(np2_multithread_enable && np2_multithread_hThread){ - int workaroundCounter = 0; - Sleep(10); - while(np2_multithread_hThread && !np2_multithread_pausing){ - if(workaroundCounter >= 30){ - np2_multithread_fakeWndProc(); - }else{ - workaroundCounter++; - } - Sleep(10); - } - } - } - } -} -void np2_multithread_Resume(){ - if(np2_multithread_pauseemulation){ - np2_multithread_pauseemulation = false; - if(np2_multithread_initialized){ - if(np2_multithread_enable && np2_multithread_hThread){ - int workaroundCounter = 0; - Sleep(10); - while(np2_multithread_hThread && np2_multithread_pausing){ - if(workaroundCounter >= 30){ - np2_multithread_fakeWndProc(); - }else{ - workaroundCounter++; - } - Sleep(10); - } - } - } - } -} -static void np2_multithread_WaitForExitThread(){ - if(np2_multithread_initialized){ - if(np2_multithread_hThread){ - np2_multithread_Suspend(); - np2_multithread_hThread_requestexit = TRUE; - if(WaitForSingleObject(np2_multithread_hThread, 20000) == WAIT_TIMEOUT){ - TerminateThread(np2_multithread_hThread, 0); - } - CloseHandle(np2_multithread_hThread); - np2_multithread_hThread = NULL; - np2_multithread_pauseemulation = false; - } - } -} -static void np2_multithread_Finalize(){ - if(np2_multithread_initialized){ - np2_multithread_WaitForExitThread(); - DeleteCriticalSection(&np2_multithread_hThread_cs); - np2_multithread_initialized = FALSE; - } -} -void np2_multithread_EnterCriticalSection(){ - if(np2_multithread_initialized && np2_multithread_enable){ - EnterCriticalSection(&np2_multithread_hThread_cs); - } -} -void np2_multithread_LeaveCriticalSection(){ - if(np2_multithread_initialized && np2_multithread_enable){ - LeaveCriticalSection(&np2_multithread_hThread_cs); - } -} -int np2_multithread_Enabled(){ - return np2_multithread_initialized && np2_multithread_enable; -} -#else -void np2_multithread_Suspend(){ - // nothing to do -} -void np2_multithread_Resume(){ - // nothing to do -} -void np2_multithread_EnterCriticalSection(){ - // nothing to do -} -void np2_multithread_LeaveCriticalSection(){ - // nothing to do -} -int np2_multithread_Enabled(){ - return 0; -} -#endif - -// コピペ用(np21w ver0.86 rev22) -char *autokey_sendbuffer = NULL; -int autokey_sendbufferlen = 0; -int autokey_sendbufferpos = 0; -int autokey_lastkanastate = 0; -int autokey_kanjimode = 1; // 0=漢字無視, 1=BASIC, 2=DOS - -// オートラン抑制用 -static int WM_QueryCancelAutoPlay; - -// システムキーフック用 -#ifdef HOOK_SYSKEY -static HANDLE np2_hThreadKeyHook = NULL; // キーフック用スレッド -static int np2_hThreadKeyHookexit = 0; // スレッド終了フラグ -static HWND np2_hThreadKeyHookhWnd = 0; -LRESULT CALLBACK LowLevelKeyboardProc(INT nCode, WPARAM wParam, LPARAM lParam); -HHOOK hHook = NULL; -LRESULT CALLBACK np2_ThreadFuncKeyHook_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ - switch(msg){ - case WM_CLOSE: - if(!np2_hThreadKeyHookexit) return 0; - break; - case WM_DESTROY: - PostQuitMessage(0); - return 0; - } - return DefWindowProc(hWnd, msg, wParam, lParam); -} -static unsigned int __stdcall np2_ThreadFuncKeyHook(LPVOID vdParam) -{ - MSG msg; - LPCTSTR wndclassname = _T("NP2 Key Hook"); - - WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, np2_ThreadFuncKeyHook_WndProc, 0, 0, g_hInstance, NULL, NULL, (HBRUSH)(COLOR_WINDOW), NULL, wndclassname, NULL}; - - if(!RegisterClassEx(&wcex)) return 0; - - if(!(np2_hThreadKeyHookhWnd = CreateWindow(wndclassname, _T("NP2 Key Hook"), WS_POPUPWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, g_hInstance, NULL))) return 0; - - ShowWindow( np2_hThreadKeyHookhWnd, SW_HIDE ); // 念のため - - if(!hHook){ - hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, g_hInstance, 0); - } - // メイン メッセージ ループ - while( GetMessage(&msg, NULL, 0, 0) > 0 ) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - if(hHook){ - UnhookWindowsHookEx(hHook); - hHook = NULL; - } - np2_hThreadKeyHookhWnd = NULL; - np2_hThreadKeyHook = NULL; - UnregisterClass(wndclassname, g_hInstance); - return 0; -} -static void start_hook_systemkey() -{ - unsigned int dwID; - if(!np2_hThreadKeyHook){ - np2_hThreadKeyHook = (HANDLE)_beginthreadex(NULL, 0, np2_ThreadFuncKeyHook, NULL, 0, &dwID); - } - //if(!hHook){ - // hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, g_hInstance, 0); - //} -} -static void stop_hook_systemkey() -{ - if(np2_hThreadKeyHook && np2_hThreadKeyHookhWnd){ - np2_hThreadKeyHookexit = 1; - SendMessage(np2_hThreadKeyHookhWnd , WM_CLOSE , 0 , 0); - WaitForSingleObject(np2_hThreadKeyHook, INFINITE); - CloseHandle(np2_hThreadKeyHook); - np2_hThreadKeyHook = NULL; - np2_hThreadKeyHookexit = 0; - } - //if(hHook){ - // UnhookWindowsHookEx(hHook); - // hHook = NULL; - //} -} -#endif - -// タイトルバーの音量・マウス速度 自動非表示用 -#define TMRSYSMNG_ID 9898 // 他と被らないようにすること -UINT_PTR tmrSysMngHide = 0; -VOID CALLBACK SysMngHideTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { - sys_miscinfo.showvolume = 0; - sys_miscinfo.showmousespeed = 0; - sysmng_updatecaption(SYS_UPDATECAPTION_MISC); - KillTimer(hwnd , tmrSysMngHide); - tmrSysMngHide = 0; -} - - -// ---- - -static int messagebox(HWND hWnd, LPCTSTR lpcszText, UINT uType) -{ - LPCTSTR szCaption = np2oscfg.titles; - - std::tstring rText(LoadTString(lpcszText)); - return MessageBox(hWnd, rText.c_str(), szCaption, uType); -} - -// ---- - -/** - * リソース DLL をロード - * @param[in] hInstance 元のインスタンス - * @return インスタンス - */ -static HINSTANCE LoadExternalResource(HINSTANCE hInstance) -{ - OEMCHAR szDllName[32]; - OEMSPRINTF(szDllName, szNp2ResDll, GetOEMCP()); - - TCHAR szPath[MAX_PATH]; - file_cpyname(szPath, modulefile, _countof(szPath)); - file_cutname(szPath); - file_catname(szPath, szDllName, _countof(szPath)); - - HMODULE hModule = LoadLibrary(szPath); - s_hModResource = hModule; - if (hModule != NULL) - { - hInstance = static_cast(hModule); - } - return hInstance; -} - -/** - * リソースのアンロード - */ -static void UnloadExternalResource() -{ - HMODULE hModule = s_hModResource; - s_hModResource = NULL; - if (hModule) - { - FreeLibrary(hModule); - } -} - - -// ---- - -static void winuienter(void) { - - winui_en = TRUE; - if(!np2_multithread_Enabled()){ - CSoundMng::GetInstance()->Disable(SNDPROC_MAIN); - } - scrnmng_topwinui(); -} - -static void winuileave(void) { - - scrnmng_clearwinui(); - if(!np2_multithread_Enabled()){ - CSoundMng::GetInstance()->Enable(SNDPROC_MAIN); - } - winui_en = FALSE; -} - -WINLOCEX np2_winlocexallwin(HWND base) { - - UINT i; - UINT cnt; - HWND list[10]; - - cnt = 0; - list[cnt++] = g_hWndMain; - list[cnt++] = toolwin_gethwnd(); - list[cnt++] = kdispwin_gethwnd(); - list[cnt++] = skbdwin_gethwnd(); - list[cnt++] = mdbgwin_gethwnd(); - if(FindWindow(OEMTEXT("Shell_TrayWnd"), NULL)){ - list[cnt++] = FindWindow(OEMTEXT("Shell_TrayWnd"), NULL); - } - for (i=0; i> 3) >= devmode.dmPelsWidth-64 || (DWORD)((scrnstat.height * scrnstat.multiple) >> 3) >= devmode.dmPelsHeight-64){ - scrnstat.multiple--; - if(scrnstat.multiple==1) break; - } - } - } - if (scrnmng_create(newmode) == SUCCESS) { - g_scrnmode = newmode; - if(np2oscfg.scrnmode != g_scrnmode){ - np2oscfg.scrnmode = g_scrnmode; // Screen状態保存 - sysmng_update(SYS_UPDATEOSCFG); - } - } - else { - if (scrnmng_create(g_scrnmode) != SUCCESS) { - scrnmng_create_pending = true; - //PostQuitMessage(0); - np2_multithread_Resume(); - return; - } - } - scrndraw_redraw(); - if (renewal & SCRNMODE_FULLSCREEN) { - if (!scrnmng_isfullscreen()) { - if (np2oscfg.toolwin) { - toolwin_create(); - } - if (np2oscfg.keydisp) { - kdispwin_create(); - } - } - } - else if (renewal & SCRNMODE_ROTATEMASK) { - winlocex_move(wlex); - winlocex_destroy(wlex); - } - mousemng_enable(MOUSEPROC_WINUI); - soundmng_play(); - } - else { - g_scrnmode = newmode; - } - - np2_multithread_LeaveCriticalSection(); - np2_multithread_Resume(); -} - -static void wincentering(HWND hWnd) { - - RECT rc; - int width; - int height; - - GetWindowRect(hWnd, &rc); - width = rc.right - rc.left; - height = rc.bottom - rc.top; - np2oscfg.winx = (GetSystemMetrics(SM_CXSCREEN) - width) / 2; - np2oscfg.winy = (GetSystemMetrics(SM_CYSCREEN) - height) / 2; - if (np2oscfg.winx < 0) { - np2oscfg.winx = 0; - } - if (np2oscfg.winy < 0) { - np2oscfg.winy = 0; - } - sysmng_update(SYS_UPDATEOSCFG); - MoveWindow(g_hWndMain, np2oscfg.winx, np2oscfg.winy, width, height, TRUE); -} - -void np2active_renewal(void) { // ver0.30 - - if (np2break & (~NP2BREAK_MAIN)) { - np2stopemulate = 2; - CSoundMng::GetInstance()->Disable(SNDPROC_MASTER); - } - else if (np2break & NP2BREAK_MAIN) { - if (np2oscfg.background & 1) { - np2stopemulate = 1; - } - else { - np2stopemulate = 0; - } - if (np2oscfg.background) { - CSoundMng::GetInstance()->Disable(SNDPROC_MASTER); - } - else { - CSoundMng::GetInstance()->Enable(SNDPROC_MASTER); - } - } - else { - np2stopemulate = 0; - CSoundMng::GetInstance()->Enable(SNDPROC_MASTER); - } -} - - -// ---- resume and statsave - -#if defined(SUPPORT_RESUME) || defined(SUPPORT_STATSAVE) -static void getstatfilename(OEMCHAR *path, const OEMCHAR *ext, int size) { - - initgetfile(path, size); - //file_cpyname(path, modulefile, size); - file_cutext(path); - file_catname(path, str_dot, size); - file_catname(path, ext, size); -} - -static int flagsave(const OEMCHAR *ext) { - - int ret; - OEMCHAR path[MAX_PATH]; - - np2_multithread_Suspend(); - getstatfilename(path, ext, NELEMENTS(path)); - soundmng_stop(); - ret = statsave_save(path); - if (ret) { - file_delete(path); - } - soundmng_play(); - np2_multithread_Resume(); - return(ret); -} - -static void flagdelete(const OEMCHAR *ext) { - - OEMCHAR path[MAX_PATH]; - - getstatfilename(path, ext, NELEMENTS(path)); - file_delete(path); -} - -static int flagload(HWND hWnd, const OEMCHAR *ext, LPCTSTR title, BOOL force) -{ - int nRet; - int nID; - OEMCHAR szPath[MAX_PATH]; - OEMCHAR szStat[1024]; - TCHAR szMessage[1024 + 256]; - - getstatfilename(szPath, ext, NELEMENTS(szPath)); - np2_multithread_Suspend(); - winuienter(); - nID = IDYES; - nRet = statsave_check(szPath, szStat, NELEMENTS(szStat)); - if (nRet & (~STATFLAG_DISKCHG)) - { - messagebox(hWnd, MAKEINTRESOURCE(IDS_ERROR_RESUME), - MB_OK | MB_ICONSTOP); - nID = IDNO; - } - else if ((!force) && (nRet & STATFLAG_DISKCHG)) - { - std::tstring rFormat(LoadTString(IDS_CONFIRM_RESUME)); - wsprintf(szMessage, rFormat.c_str(), szStat); - nID = messagebox(hWnd, szMessage, MB_YESNOCANCEL | MB_ICONQUESTION); - } - if (nID == IDYES) - { - statsave_load(szPath); - toolwin_setfdd(0, fdd_diskname(0)); - toolwin_setfdd(1, fdd_diskname(1)); - } - sysmng_workclockreset(); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - winuileave(); - np2_multithread_Resume(); - return nID; -} -#endif - -/** - * サウンドデバイスの再オープン - * @param[in] hWnd ウィンドウ ハンドル - */ -static void OpenSoundDevice(HWND hWnd) -{ - CSoundMng* pSoundMng = CSoundMng::GetInstance(); - if (pSoundMng->Open(static_cast(np2oscfg.cSoundDeviceType), np2oscfg.szSoundDeviceName, hWnd)) - { - pSoundMng->LoadPCM(SOUND_PCMSEEK, TEXT("SEEKWAV")); - pSoundMng->LoadPCM(SOUND_PCMSEEK1, TEXT("SEEK1WAV")); - pSoundMng->LoadPCM(SOUND_RELAY1, TEXT("RELAY1WAV")); - pSoundMng->SetPCMVolume(SOUND_PCMSEEK, np2cfg.MOTORVOL); - pSoundMng->SetPCMVolume(SOUND_PCMSEEK1, np2cfg.MOTORVOL); - pSoundMng->SetPCMVolume(SOUND_RELAY1, np2cfg.MOTORVOL); - pSoundMng->SetMasterVolume(np2cfg.vol_master); - } -} - -// ---- proc - -static void np2popup(HWND hWnd, LPARAM lp) { - - HMENU mainmenu; - HMENU hMenu; - HMENU hMenuEdit; - POINT pt; - - mainmenu = (HMENU)GetWindowLongPtr(hWnd, NP2GWLP_HMENU); - hMenu = CreatePopupMenu(); - hMenuEdit = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_COPYPASTEPOPUP)); -#if defined(SUPPORT_WAB) - EnableMenuItem(hMenuEdit, IDM_COPYPASTE_COPYWABMEM, 0); -#endif - menu_addmenubar(hMenu, hMenuEdit); - if (mainmenu) { - InsertMenu(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); - menu_addmenubar(hMenu, mainmenu); - } - xmenu_update(hMenu); - pt.x = LOWORD(lp); - pt.y = HIWORD(lp); - ClientToScreen(hWnd, &pt); - TrackPopupMenu(hMenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hWnd, NULL); - DestroyMenu(hMenu); -} - -#ifdef SUPPORT_PHYSICAL_CDDRV -static void np2updatemenu() { - static char drvMenuVisible[4][26] = {0}; // 実ドライブメニューの表示状態 - char drvAvailable[26] = {0}; // 使える実ドライブ - - REG8 drv; - HMENU hMenu = np2class_gethmenu(g_hWndMain); - HMENU hMenuTgt; - int hMenuTgtPos; - MENUITEMINFO mii = {0}; - - DWORD dwDrive; - int nDrive; - TCHAR szBuff2[] = OEMTEXT("A:\\"); - - // 有効なCDドライブのドライブ文字を調べる - dwDrive = GetLogicalDrives(); - for ( nDrive = 0 ; nDrive < 26 ; nDrive++ ){ - if ( dwDrive & (1 << nDrive) ){ - szBuff2[0] = nDrive + 'A'; - if(GetDriveType(szBuff2)==DRIVE_CDROM){ - drvAvailable[nDrive] = 1; - } - } - } - szBuff2[2] = 0; -#if defined(SUPPORT_IDEIO) - for (drv = 0x00; drv < 0x04; drv++) - { - int mnupos = 1; - if(menu_searchmenu(hMenu, IDM_IDE0OPEN+drv, &hMenuTgt, &hMenuTgtPos)){ - // 一旦全部消す - for ( nDrive = 0 ; nDrive < 26 ; nDrive++ ){ - if(drvMenuVisible[drv][nDrive]){ - DeleteMenu(hMenuTgt, IDM_IDE0PHYSICALDRV_ID0 + 26*drv + nDrive, MF_BYCOMMAND); - drvMenuVisible[drv][nDrive] = 0; - } - } - if(np2cfg.idetype[drv]==SXSIDEV_CDROM){ - // 再追加 - for ( nDrive = 0 ; nDrive < 26 ; nDrive++ ){ - if(drvAvailable[nDrive]){ - TCHAR mnuText[200] = {0}; - szBuff2[0] = nDrive + 'A'; - if(!LoadString(g_hInstance, IDS_PHYSICALDRIVE, mnuText, sizeof(mnuText)/sizeof(mnuText[0]) - sizeof(szBuff2)/sizeof(szBuff2[0]))){ - _tcscpy(mnuText, OEMTEXT("&Physical Drive ")); - } - _tcscat(mnuText, szBuff2); - InsertMenu(hMenuTgt, mnupos++, MF_BYPOSITION, IDM_IDE0PHYSICALDRV_ID0 + 26*drv + nDrive, mnuText); - drvMenuVisible[drv][nDrive] = 1; - } - } - } - } - //if(np2cfg.idetype[drv]==SXSIDEV_CDROM) - //{ - // EnableMenuItem(hMenu, IDM_IDE0PHYSICALDRV+drv, MF_BYCOMMAND|MFS_ENABLED); - //} - //else - //{ - // EnableMenuItem(hMenu, IDM_IDE0PHYSICALDRV+drv, MF_BYCOMMAND|MFS_GRAYED); - //} - } -#endif -} -#endif - -static void OnCommand(HWND hWnd, WPARAM wParam) -{ - UINT update; - UINT uID; - BOOL b; - - static UINT16 oldcpustabf = 90; - - update = 0; - uID = LOWORD(wParam); -#if defined(SUPPORT_IDEIO) -#if defined(SUPPORT_PHYSICAL_CDDRV) - if(IDM_IDE0PHYSICALDRV_ID0 <= uID && uID < IDM_IDE0PHYSICALDRV_ID0 + 26*4){ - TCHAR szBuff[] = OEMTEXT("\\\\.\\A:"); - int idedrv = (uID - IDM_IDE0PHYSICALDRV_ID0) / 26; - int drvnum = (uID - IDM_IDE0PHYSICALDRV_ID0) % 26; - szBuff[4] = drvnum + 'A'; - sysmng_update(SYS_UPDATEOSCFG); - diskdrv_setsxsi(idedrv, szBuff); - } -#endif -#endif - switch(uID) - { - case IDM_RESET: - b = FALSE; - if (!np2oscfg.comfirm) - { - b = TRUE; - } - else if (sstpconfirm_reset()) - { - winuienter(); - if (messagebox(hWnd, MAKEINTRESOURCE(IDS_CONFIRM_RESET), MB_ICONQUESTION | MB_YESNO) == IDYES) - { - b = TRUE; - } - winuileave(); - } - if (b) - { - if (sys_updates & SYS_UPDATESNDDEV) - { - sys_updates &= ~SYS_UPDATESNDDEV; - OpenSoundDevice(hWnd); - } -#ifdef HOOK_SYSKEY - stop_hook_systemkey(); -#endif - np2_multithread_Suspend(); - sstpmsg_reset(); - pccore_cfgupdate(); - if(nevent_iswork(NEVENT_CDWAIT)){ - nevent_forceexecute(NEVENT_CDWAIT); - } - pccore_reset(); - np2_SetUserPause(0); - np2_multithread_Resume(); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); -#ifdef SUPPORT_PHYSICAL_CDDRV - np2updatemenu(); -#endif -#ifdef HOOK_SYSKEY - start_hook_systemkey(); -#endif - } - break; - case IDM_PAUSE: - np2_SetUserPause(!np2userpause); - update |= SYS_UPDATECFG; - break; - case IDM_CONFIG: - winuienter(); - sstpmsg_config(); - dialog_configure(hWnd); - if (!scrnmng_isfullscreen()) { - UINT8 thick; - thick = (GetWindowLong(hWnd, GWL_STYLE) & WS_THICKFRAME)?1:0; - if (thick != np2oscfg.thickframe) { - WINLOCEX wlex; - wlex = np2_winlocexallwin(hWnd); - winlocex_setholdwnd(wlex, hWnd); - np2class_frametype(hWnd, np2oscfg.thickframe); - winlocex_move(wlex); - winlocex_destroy(wlex); - } - } - winuileave(); - break; - - case IDM_CHANGECLK_X2: - np2_DynamicChangeClockMul(2); - break; - case IDM_CHANGECLK_X8: - np2_DynamicChangeClockMul(8); - break; - case IDM_CHANGECLK_X16: - np2_DynamicChangeClockMul(16); - break; - case IDM_CHANGECLK_X30: - np2_DynamicChangeClockMul(30); - break; - case IDM_CHANGECLK_X42: - np2_DynamicChangeClockMul(42); - break; - case IDM_CHANGECLK_RESTORE: - np2_DynamicChangeClockMul(np2cfg.multiple); - break; - - case IDM_NEWDISK: - winuienter(); - dialog_newdisk(hWnd); - winuileave(); - break; - - case IDM_NEWDISKFD: - winuienter(); - dialog_newdisk_ex(hWnd, NEWDISKMODE_FD); - winuileave(); - break; - - case IDM_NEWDISKHD: - winuienter(); - dialog_newdisk_ex(hWnd, NEWDISKMODE_HD); - winuileave(); - break; - - case IDM_CHANGEFONT: - winuienter(); - dialog_font(hWnd); - winuileave(); - break; - - case IDM_LOADVMCFG: - winuienter(); - dialog_readnpcfg(hWnd); - winuileave(); - - break; - - case IDM_SAVEVMCFG: - winuienter(); - dialog_writenpcfg(hWnd); - winuileave(); - break; - - case IDM_EXIT: - SendMessage(hWnd, WM_CLOSE, 0, 0L); - break; - - case IDM_FDD1OPEN: - winuienter(); - dialog_changefdd(hWnd, 0); - winuileave(); - break; - - case IDM_FDD1EJECT: - diskdrv_setfdd(0, NULL, 0); - toolwin_setfdd(0, NULL); - break; - - case IDM_FDD2OPEN: - winuienter(); - dialog_changefdd(hWnd, 1); - winuileave(); - break; - - case IDM_FDD2EJECT: - diskdrv_setfdd(1, NULL, 0); - toolwin_setfdd(1, NULL); - break; - - case IDM_FDD3OPEN: - winuienter(); - dialog_changefdd(hWnd, 2); - winuileave(); - break; - - case IDM_FDD3EJECT: - diskdrv_setfdd(2, NULL, 0); - toolwin_setfdd(2, NULL); - break; - - case IDM_FDD4OPEN: - winuienter(); - dialog_changefdd(hWnd, 3); - winuileave(); - break; - - case IDM_FDD4EJECT: - diskdrv_setfdd(3, NULL, 0); - toolwin_setfdd(3, NULL); - break; - - case IDM_IDE0OPEN: - winuienter(); - dialog_changehdd(hWnd, 0x00); - winuileave(); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - break; - - case IDM_IDE0EJECT: - diskdrv_setsxsi(0x00, NULL); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - break; - - case IDM_IDE1OPEN: - winuienter(); - dialog_changehdd(hWnd, 0x01); - winuileave(); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - break; - - case IDM_IDE1EJECT: - diskdrv_setsxsi(0x01, NULL); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - break; - -#if defined(SUPPORT_IDEIO) - case IDM_IDE2OPEN: - winuienter(); - dialog_changehdd(hWnd, 0x02); - winuileave(); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - break; - - case IDM_IDE2EJECT: - diskdrv_setsxsi(0x02, NULL); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - break; - - case IDM_IDE3OPEN: - winuienter(); - dialog_changehdd(hWnd, 0x03); - winuileave(); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - break; - - case IDM_IDE3EJECT: - diskdrv_setsxsi(0x03, NULL); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - break; - - case IDM_IDEOPT: - winuienter(); - dialog_ideopt(hWnd); - winuileave(); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - break; -#endif - - case IDM_IDE0STATE: - case IDM_IDE1STATE: - case IDM_IDE2STATE: - case IDM_IDE3STATE: - { - const OEMCHAR *fname; - fname = sxsi_getfilename(uID - IDM_IDE0STATE); - if(!fname || !(*fname)){ -#if defined(SUPPORT_IDEIO) - if(np2cfg.idetype[uID - IDM_IDE0STATE]==SXSIDEV_CDROM){ - fname = np2cfg.idecd[uID - IDM_IDE0STATE]; - }else{ -#endif - fname = diskdrv_getsxsi(uID - IDM_IDE0STATE); -#if defined(SUPPORT_IDEIO) - } -#endif - } - if(_tcsnicmp(fname, OEMTEXT("\\\\.\\"), 4)==0){ - fname += 4; - } - if(fname && *fname){ - TCHAR seltmp[500]; - _tcscpy(seltmp, OEMTEXT("/select,")); - _tcscat(seltmp, fname); - ShellExecute(NULL, NULL, OEMTEXT("explorer.exe"), seltmp, NULL, SW_SHOWNORMAL); - } - } - break; - -#if defined(SUPPORT_SCSI) - case IDM_SCSI0OPEN: - winuienter(); - dialog_changehdd(hWnd, 0x20); - winuileave(); - break; - - case IDM_SCSI0EJECT: - diskdrv_setsxsi(0x20, NULL); - break; - - case IDM_SCSI1OPEN: - winuienter(); - dialog_changehdd(hWnd, 0x21); - winuileave(); - break; - - case IDM_SCSI1EJECT: - diskdrv_setsxsi(0x21, NULL); - break; - - case IDM_SCSI2OPEN: - winuienter(); - dialog_changehdd(hWnd, 0x22); - winuileave(); - break; - - case IDM_SCSI2EJECT: - diskdrv_setsxsi(0x22, NULL); - break; - - case IDM_SCSI3OPEN: - winuienter(); - dialog_changehdd(hWnd, 0x23); - winuileave(); - break; - - case IDM_SCSI3EJECT: - diskdrv_setsxsi(0x23, NULL); - break; - - case IDM_SCSI0STATE: - case IDM_SCSI1STATE: - case IDM_SCSI2STATE: - case IDM_SCSI3STATE: - { - const OEMCHAR *fname; - fname = sxsi_getfilename(uID - IDM_SCSI0STATE + 0x20); - if(!fname || !(*fname)){ - fname = diskdrv_getsxsi(uID - IDM_IDE0STATE + 0x20); - } - if(fname && *fname){ - TCHAR seltmp[500]; - _tcscpy(seltmp, OEMTEXT("/select,")); - _tcscat(seltmp, fname); - ShellExecute(NULL, NULL, OEMTEXT("explorer.exe"), seltmp, NULL, SW_SHOWNORMAL); - } - } - break; -#endif - - case IDM_WINDOW: - changescreen(g_scrnmode & (~SCRNMODE_FULLSCREEN)); - break; - - case IDM_FULLSCREEN: - changescreen(g_scrnmode | SCRNMODE_FULLSCREEN); - break; - - case IDM_ROLNORMAL: - changescreen(g_scrnmode & (~SCRNMODE_ROTATEMASK)); - break; - - case IDM_ROLLEFT: - changescreen((g_scrnmode & (~SCRNMODE_ROTATEMASK)) | SCRNMODE_ROTATELEFT); - break; - - case IDM_ROLRIGHT: - changescreen((g_scrnmode & (~SCRNMODE_ROTATEMASK)) | SCRNMODE_ROTATERIGHT); - break; - - case IDM_DISPSYNC: - np2cfg.DISPSYNC = !np2cfg.DISPSYNC; - update |= SYS_UPDATECFG; - break; - - case IDM_RASTER: - np2cfg.RASTER = !np2cfg.RASTER; - if (np2cfg.RASTER) - { - changescreen(g_scrnmode | SCRNMODE_HIGHCOLOR); - } - else - { - changescreen(g_scrnmode & (~SCRNMODE_HIGHCOLOR)); - } - update |= SYS_UPDATECFG; - break; - - case IDM_NOWAIT: - np2oscfg.NOWAIT = !np2oscfg.NOWAIT; - update |= SYS_UPDATECFG; - break; - - case IDM_CPUSTABILIZER: - if(np2oscfg.cpustabf == 0){ - np2oscfg.cpustabf = oldcpustabf; - }else{ - oldcpustabf = np2oscfg.cpustabf; - np2oscfg.cpustabf = 0; - } - update |= SYS_UPDATECFG; - break; - -#if defined(SUPPORT_ASYNC_CPU) - case IDM_ASYNCCPU: - np2cfg.asynccpu = !np2cfg.asynccpu; - update |= SYS_UPDATECFG; - break; -#endif - - case IDM_AUTOFPS: - np2oscfg.DRAW_SKIP = 0; - update |= SYS_UPDATECFG; - break; - - case IDM_60FPS: - np2oscfg.DRAW_SKIP = 1; - update |= SYS_UPDATECFG; - break; - - case IDM_30FPS: - np2oscfg.DRAW_SKIP = 2; - update |= SYS_UPDATECFG; - break; - - case IDM_20FPS: - np2oscfg.DRAW_SKIP = 3; - update |= SYS_UPDATECFG; - break; - - case IDM_15FPS: - np2oscfg.DRAW_SKIP = 4; - update |= SYS_UPDATECFG; - break; - -#if defined(SUPPORT_VIDEOFILTER) - case IDM_VF1EN: - np2cfg.vf1_enable ^= 1; - VideoFilter_SetEnable(hVFMng1, np2cfg.vf1_enable); - update |= SYS_UPDATECFG; - break; - - case IDM_VF1P0: - np2cfg.vf1_pno = 0; - VideoFilter_SetProfileNo(hVFMng1, 0); - update |= SYS_UPDATECFG; - break; - - case IDM_VF1P1: - np2cfg.vf1_pno = 1; - VideoFilter_SetProfileNo(hVFMng1, 1); - update |= SYS_UPDATECFG; - break; - - case IDM_VF1P2: - np2cfg.vf1_pno = 2; - VideoFilter_SetProfileNo(hVFMng1, 2); - update |= SYS_UPDATECFG; - break; - - case IDM_VF1BO: - np2cfg.vf1_bmponly ^= 1; - update |= SYS_UPDATECFG; - break; -#endif - - case IDM_SCREENOPT: - winuienter(); - dialog_scropt(hWnd); - winuileave(); - break; - - case IDM_KEY: - np2cfg.KEY_MODE = 0; - keystat_resetjoykey(); - update |= SYS_UPDATECFG; - break; - - case IDM_JOY1: - np2cfg.KEY_MODE = 1; - keystat_resetjoykey(); - update |= SYS_UPDATECFG; - break; - - case IDM_JOY2: - np2cfg.KEY_MODE = 2; - keystat_resetjoykey(); - update |= SYS_UPDATECFG; - break; - - case IDM_XSHIFT: - np2cfg.XSHIFT ^= 1; - keystat_forcerelease(0x70); - update |= SYS_UPDATECFG; - break; - - case IDM_XCTRL: - np2cfg.XSHIFT ^= 2; - keystat_forcerelease(0x74); - update |= SYS_UPDATECFG; - break; - - case IDM_XGRPH: - np2cfg.XSHIFT ^= 4; - keystat_forcerelease(0x73); - update |= SYS_UPDATECFG; - break; - - case IDM_SENDCAD: - keystat_senddata(0x73); - keystat_senddata(0x74); - keystat_senddata(0x39); - keystat_senddata(0x73 | 0x80); - keystat_senddata(0x74 | 0x80); - keystat_senddata(0x39 | 0x80); - break; - - case IDM_USENUMLOCK: - np2oscfg.USENUMLOCK = !np2oscfg.USENUMLOCK; - update |= SYS_UPDATEOSCFG; - break; - - case IDM_SWAPPAGEUPDOWN: - np2oscfg.xrollkey = !np2oscfg.xrollkey; - winkbd_roll(np2oscfg.KEYBOARD==KEY_PC98 ? np2oscfg.xrollkey : !np2oscfg.xrollkey); - update |= SYS_UPDATEOSCFG; - break; - - case IDM_F12MOUSE: - np2oscfg.F12COPY = 0; - winkbd_resetf12(); - winkbd_setf12(0); - update |= SYS_UPDATEOSCFG; - break; - - case IDM_F12COPY: - np2oscfg.F12COPY = 1; - winkbd_resetf12(); - winkbd_setf12(1); - update |= SYS_UPDATEOSCFG; - break; - - case IDM_F12STOP: - np2oscfg.F12COPY = 2; - winkbd_resetf12(); - winkbd_setf12(2); - update |= SYS_UPDATEOSCFG; - break; - - case IDM_F12EQU: - np2oscfg.F12COPY = 3; - winkbd_resetf12(); - winkbd_setf12(3); - update |= SYS_UPDATEOSCFG; - break; - - case IDM_F12COMMA: - np2oscfg.F12COPY = 4; - winkbd_resetf12(); - winkbd_setf12(4); - update |= SYS_UPDATEOSCFG; - break; - - case IDM_USERKEY1: - np2oscfg.F12COPY = 5; - winkbd_resetf12(); - winkbd_setf12(5); - update |= SYS_UPDATEOSCFG; - break; - - case IDM_USERKEY2: - np2oscfg.F12COPY = 6; - winkbd_resetf12(); - winkbd_setf12(6); - update |= SYS_UPDATEOSCFG; - break; - - case IDM_F12NOWAIT: - np2oscfg.F12COPY = 7; - winkbd_resetf12(); - winkbd_setf12(7); - update |= SYS_UPDATEOSCFG; - break; - - case IDM_F12NOWAIT2: - np2oscfg.F12COPY = 8; - winkbd_resetf12(); - winkbd_setf12(8); - update |= SYS_UPDATEOSCFG; - break; - - case IDM_F12WABRELAY: - np2oscfg.F12COPY = 9; - winkbd_resetf12(); - winkbd_setf12(9); - update |= SYS_UPDATEOSCFG; - break; - - case IDM_BEEPOFF: - np2cfg.BEEP_VOL = 0; - beep_setvol(0); - update |= SYS_UPDATECFG; - break; - - case IDM_BEEPLOW: - np2cfg.BEEP_VOL = 1; - beep_setvol(1); - update |= SYS_UPDATECFG; - break; - - case IDM_BEEPMID: - np2cfg.BEEP_VOL = 2; - beep_setvol(2); - update |= SYS_UPDATECFG; - break; - - case IDM_BEEPHIGH: - np2cfg.BEEP_VOL = 3; - beep_setvol(3); - update |= SYS_UPDATECFG; - break; - - case IDM_NOSOUND: - np2cfg.SOUND_SW = 0x00; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_14: - np2cfg.SOUND_SW = 0x01; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_26K: - np2cfg.SOUND_SW = 0x02; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_86: - np2cfg.SOUND_SW = 0x04; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_26_86: - np2cfg.SOUND_SW = 0x06; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_86_CB: - np2cfg.SOUND_SW = 0x14; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_118: - np2cfg.SOUND_SW = 0x08; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_86_WSS: - np2cfg.SOUND_SW = SOUNDID_PC_9801_86_WSS; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_86_118: - np2cfg.SOUND_SW = SOUNDID_PC_9801_86_118; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_MATE_X_PCM: - np2cfg.SOUND_SW = SOUNDID_MATE_X_PCM; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_SPEAKBOARD: - np2cfg.SOUND_SW = SOUNDID_SPEAKBOARD; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_86SPEAKBOARD: - np2cfg.SOUND_SW = SOUNDID_86_SPEAKBOARD; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_SPARKBOARD: - np2cfg.SOUND_SW = 0x40; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - -#if defined(SUPPORT_SOUND_SB16) - case IDM_SB16: - np2cfg.SOUND_SW = SOUNDID_SB16; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_86_SB16: - np2cfg.SOUND_SW = SOUNDID_PC_9801_86_SB16; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_WSS_SB16: - np2cfg.SOUND_SW = SOUNDID_WSS_SB16; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_86_WSS_SB16: - np2cfg.SOUND_SW = SOUNDID_PC_9801_86_WSS_SB16; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_118_SB16: - np2cfg.SOUND_SW = SOUNDID_PC_9801_118_SB16; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PC9801_86_118_SB16: - np2cfg.SOUND_SW = SOUNDID_PC_9801_86_118_SB16; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; -#endif // defined(SUPPORT_SOUND_SB16) - -#if defined(SUPPORT_PX) - case IDM_PX1: - np2cfg.SOUND_SW = 0x30; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_PX2: - np2cfg.SOUND_SW = 0x50; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; -#endif // defined(SUPPORT_PX) - - case IDM_SOUNDORCHESTRA: - np2cfg.SOUND_SW = 0x32; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_SOUNDORCHESTRAV: - np2cfg.SOUND_SW = 0x82; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_LITTLEORCHESTRAL: - np2cfg.SOUND_SW = SOUNDID_LITTLEORCHESTRAL; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_AMD98: - np2cfg.SOUND_SW = 0x80; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_WAVESTAR: - np2cfg.SOUND_SW = SOUNDID_WAVESTAR; - update |= SYS_UPDATECFG | SYS_UPDATESBOARD; - break; - - case IDM_JASTSOUND: - np2oscfg.jastsnd = !np2oscfg.jastsnd; - update |= SYS_UPDATEOSCFG; - break; - - case IDM_SEEKSND: - np2cfg.MOTOR = !np2cfg.MOTOR; - update |= SYS_UPDATECFG; - break; - - case IDM_MEM640: - np2cfg.EXTMEM = 0; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - - case IDM_MEM16: - np2cfg.EXTMEM = 1; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - - case IDM_MEM36: - np2cfg.EXTMEM = 3; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - - case IDM_MEM76: - np2cfg.EXTMEM = 7; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - - case IDM_MEM116: - np2cfg.EXTMEM = 11; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - - case IDM_MEM136: - np2cfg.EXTMEM = 13; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - - case IDM_MEM166: - np2cfg.EXTMEM = 16; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - - case IDM_MEM326: - np2cfg.EXTMEM = 32; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - - case IDM_MEM646: - np2cfg.EXTMEM = 64; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - - case IDM_MEM1206: - np2cfg.EXTMEM = 120; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - - case IDM_MEM2306: - np2cfg.EXTMEM = 230; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - -#if defined(SUPPORT_LARGE_MEMORY) - case IDM_MEM5126: - np2cfg.EXTMEM = 512; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; - - case IDM_MEM10246: - np2cfg.EXTMEM = 1024; - update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; - break; -#endif - - case IDM_FPU80: - np2cfg.fpu_type = FPU_TYPE_SOFTFLOAT; - update |= SYS_UPDATECFG; - break; - - case IDM_FPU64: - np2cfg.fpu_type = FPU_TYPE_DOSBOX; - update |= SYS_UPDATECFG; - break; - - case IDM_FPU64INT: - np2cfg.fpu_type = FPU_TYPE_DOSBOX2; - update |= SYS_UPDATECFG; - break; - - case IDM_MOUSE: - mousemng_toggle(MOUSEPROC_SYSTEM); - np2oscfg.MOUSE_SW = !np2oscfg.MOUSE_SW; - update |= SYS_UPDATECFG; - break; - - case IDM_MOUSENC: - np2oscfg.mouse_nc = !np2oscfg.mouse_nc; - if(np2oscfg.mouse_nc){ - SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); - if (np2oscfg.wintype != 0) { - // XXX: メニューが出せなくなって詰むのを回避(暫定) - if (!scrnmng_isfullscreen()) { - WINLOCEX wlex; - np2oscfg.wintype = 0; - wlex = np2_winlocexallwin(hWnd); - winlocex_setholdwnd(wlex, hWnd); - np2class_windowtype(hWnd, np2oscfg.wintype); - winlocex_move(wlex); - winlocex_destroy(wlex); - sysmng_update(SYS_UPDATEOSCFG); - } - } - }else{ - SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) | CS_DBLCLKS); - } -#ifdef SUPPORT_WACOM_TABLET - cmwacom_setNCControl(!!np2oscfg.mouse_nc); -#endif - break; - - case IDM_MOUSEWHEELCTL: - np2oscfg.usewheel = !np2oscfg.usewheel; - break; - - case IDM_MOUSERAW: - np2oscfg.rawmouse = !np2oscfg.rawmouse; - mousemng_updateclip(); // キャプチャし直す - break; - - case IDM_MOUSE30X: - np2oscfg.mousemul = 3; - np2oscfg.mousediv = 1; - mousemng_updatespeed(); - break; - - case IDM_MOUSE20X: - np2oscfg.mousemul = 2; - np2oscfg.mousediv = 1; - mousemng_updatespeed(); - break; - - case IDM_MOUSE15X: - np2oscfg.mousemul = 3; - np2oscfg.mousediv = 2; - mousemng_updatespeed(); - break; - - case IDM_MOUSE10X: - np2oscfg.mousemul = 1; - np2oscfg.mousediv = 1; - mousemng_updatespeed(); - break; - - case IDM_MOUSED2X: - np2oscfg.mousemul = 1; - np2oscfg.mousediv = 2; - mousemng_updatespeed(); - break; - - case IDM_MOUSED3X: - np2oscfg.mousemul = 1; - np2oscfg.mousediv = 3; - mousemng_updatespeed(); - break; - - case IDM_MOUSED4X: - np2oscfg.mousemul = 1; - np2oscfg.mousediv = 4; - mousemng_updatespeed(); - break; - - case IDM_SERIAL1: - winuienter(); - dialog_serial(hWnd); - winuileave(); - break; - - case IDM_MPUPC98: - winuienter(); - dialog_mpu98(hWnd); - winuileave(); - break; - - case IDM_MIDIPANIC: - rs232c_midipanic(); - mpu98ii_midipanic(); -#if defined(SUPPORT_SMPU98) - smpu98_midipanic(); -#endif - pc9861k_midipanic(); - break; - - case IDM_SNDOPT: - winuienter(); - dialog_sndopt(hWnd); - winuileave(); - break; - -#if defined(SUPPORT_NET) - case IDM_NETOPT: - winuienter(); - dialog_netopt(hWnd); - winuileave(); - break; -#endif -#if defined(SUPPORT_CL_GD5430) - case IDM_WABOPT: - winuienter(); - dialog_wabopt(hWnd); - winuileave(); - break; -#endif -#if defined(SUPPORT_HOSTDRV) - case IDM_HOSTDRVOPT: - winuienter(); - dialog_hostdrvopt(hWnd); - winuileave(); - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - break; -#endif -#if defined(SUPPORT_PCI) - case IDM_PCIOPT: - winuienter(); - dialog_pciopt(hWnd); - winuileave(); - break; -#endif - - case IDM_BMPSAVE: - winuienter(); - dialog_writebmp(hWnd); - winuileave(); - break; - - case IDM_TXTSAVE: - winuienter(); - dialog_writetxt(hWnd); - winuileave(); - break; - - case IDM_S98LOGGING: - winuienter(); - dialog_soundlog(hWnd); - winuileave(); - break; - - case IDM_CALENDAR: - winuienter(); - dialog_calendar(hWnd); - winuileave(); - break; - - case IDM_ALTENTER: - np2oscfg.shortcut ^= 1; - update |= SYS_UPDATECFG; - break; - - case IDM_ALTF4: - np2oscfg.shortcut ^= 2; - update |= SYS_UPDATECFG; - break; - -#ifdef HOOK_SYSKEY - case IDM_SYSKHOOK: - np2oscfg.syskhook = !np2oscfg.syskhook; - if(np2oscfg.syskhook){ - start_hook_systemkey(); - }else{ - stop_hook_systemkey(); - } - update |= SYS_UPDATECFG; - break; -#endif - - case IDM_DISPCLOCK: - np2oscfg.DISPCLK ^= 1; - update |= SYS_UPDATECFG; - sysmng_workclockrenewal(); - sysmng_updatecaption(SYS_UPDATECAPTION_CLK); - break; - - case IDM_DISPFRAME: - np2oscfg.DISPCLK ^= 2; - update |= SYS_UPDATECFG; - sysmng_workclockrenewal(); - sysmng_updatecaption(SYS_UPDATECAPTION_CLK); - break; - - case IDM_JOYX: - np2cfg.BTN_MODE = !np2cfg.BTN_MODE; - update |= SYS_UPDATECFG; - break; - - case IDM_RAPID: - np2cfg.BTN_RAPID = !np2cfg.BTN_RAPID; - update |= SYS_UPDATECFG; - break; - - case IDM_MSRAPID: - np2cfg.MOUSERAPID = !np2cfg.MOUSERAPID; - update |= SYS_UPDATECFG; - break; - - case IDM_SSTP: - np2oscfg.sstp = !np2oscfg.sstp; - update |= SYS_UPDATEOSCFG; - break; - - case IDM_CPUSAVE: - debugsub_status(); - break; - - case IDM_HELP: - ShellExecute(hWnd, NULL, file_getcd(np2help), NULL, NULL, SW_SHOWNORMAL); - break; - - case IDM_ABOUT: - np2_multithread_Suspend(); - sstpmsg_about(); - if (sstp_result() != SSTP_SENDING) { - winuienter(); - CSoundMng::GetInstance()->Disable(SNDPROC_MAIN); - dialog_about(hWnd); - CSoundMng::GetInstance()->Enable(SNDPROC_MAIN); - winuileave(); - } - np2_multithread_Resume(); - break; - - case IDM_ITFWORK: - np2cfg.ITF_WORK = !np2cfg.ITF_WORK; - update |= SYS_UPDATECFG; - break; - - case IDM_TIMERFIX: - np2cfg.timerfix= !np2cfg.timerfix; - update |= SYS_UPDATECFG; - break; - - case IDM_SKIP16MEMCHK: - if(np2cfg.memchkmx != 0){ - np2cfg.memchkmx = 0; - }else{ - np2cfg.memchkmx = 15; - } - update |= SYS_UPDATECFG; - break; - - case IDM_FASTMEMCHK: -#if defined(SUPPORT_FAST_MEMORYCHECK) - if(np2cfg.memcheckspeed==1){ - np2cfg.memcheckspeed = 8; - }else{ - np2cfg.memcheckspeed = 1; - } - update |= SYS_UPDATECFG; -#endif - break; - - case IDM_EN_DBSS: - { -#if defined(SUPPORT_DEBUGSS) - HMENU hMenu = np2class_gethmenu(g_hWndMain); - if (np2cfg.debugss == 0) { - np2cfg.debugss = 1; - menu_addmenures(hMenu, GetMenuItemCount(hMenu), IDR_DEBUGSS, FALSE); - } - else { - np2cfg.debugss = 0; - //DeleteMenu(hMenu, IDR_DEBUGSS, MF_BYCOMMAND); - DeleteMenu(hMenu, GetMenuItemCount(hMenu) - 1, MF_BYPOSITION); - } - DrawMenuBar(hWnd); - update |= SYS_UPDATECFG; - break; -#endif - } - - case IDM_RESTOREBORDER: - if(np2oscfg.wintype!=0){ - WINLOCEX wlex; - np2oscfg.wintype = 0; - wlex = np2_winlocexallwin(hWnd); - winlocex_setholdwnd(wlex, hWnd); - np2class_windowtype(hWnd, np2oscfg.wintype); - winlocex_move(wlex); - winlocex_destroy(wlex); - sysmng_update(SYS_UPDATEOSCFG); - } - break; - - case IDM_COPYPASTE_COPYTVRAM: - { - HGLOBAL hMem; - OEMCHAR *lpMem; - hMem = GlobalAlloc(GHND,0x4000); // アトリビュート分小さくなるので0x4000で十分 - lpMem = (OEMCHAR*)GlobalLock(hMem); - dialog_getTVRAM(lpMem); - GlobalUnlock(hMem); - if(OpenClipboard(hWnd)){ - // クリップボード奪取成功 - EmptyClipboard(); - SetClipboardData(CF_TEXT, hMem); - CloseClipboard(); - }else{ - // クリップボード奪取失敗・・・ - GlobalFree(hMem); - } - pcm86_setnextintr(); - } - break; - - case IDM_COPYPASTE_COPYGVRAM: - case IDM_COPYPASTE_COPYWABMEM: -#ifdef SUPPORT_WAB - { - BMPFILE bf; - BMPINFO bi; - UINT8 *lppal; - UINT8 *lppixels; - HDC hDC; - DWORD dwHeaderSize; - BITMAPINFO *lpbinfo; - HBITMAP hBmp; - SCRNSAVE ss = scrnsave_create(); - if(uID == IDM_COPYPASTE_COPYWABMEM){ - np2wab_getbmp(&bf, &bi, &lppal, &lppixels); - }else{ - scrnsave_getbmp(ss, &bf, &bi, &lppal, &lppixels, SCRNSAVE_AUTO); - } - hDC = GetDC(NULL); - dwHeaderSize = LOADINTELDWORD(bf.bfOffBits) - sizeof(BMPFILE); - lpbinfo = (BITMAPINFO*)malloc(dwHeaderSize); - CopyMemory(lpbinfo, &bi, sizeof(BMPINFO)); - if(LOADINTELWORD(bi.biBitCount) <= 8){ - CopyMemory(lpbinfo->bmiColors, lppal, 4 << LOADINTELWORD(bi.biBitCount)); - hBmp = CreateDIBitmap(hDC, &(lpbinfo->bmiHeader), CBM_INIT, lppixels, lpbinfo, DIB_RGB_COLORS); - }else{ - hBmp = CreateDIBitmap(hDC, &(lpbinfo->bmiHeader), CBM_INIT, lppixels, lpbinfo, DIB_RGB_COLORS); - } - ReleaseDC(NULL, hDC); - free(lppal); - free(lppixels); - free(lpbinfo); - if(OpenClipboard(hWnd)){ - // クリップボード奪取成功 - EmptyClipboard(); - SetClipboardData(CF_BITMAP,hBmp); - CloseClipboard(); - }else{ - // クリップボード奪取失敗・・・ - DeleteObject(hBmp); - } - scrnsave_destroy(ss); - } -#endif - break; - - case IDM_COPYPASTE_PASTE: - { - int txtlen; - HGLOBAL hg; - char *strClip; - //char *strText; - if(autokey_sendbuffer==NULL){ - if (OpenClipboard(hWnd)){ - if((hg = GetClipboardData(CF_TEXT))!=NULL) { - txtlen = (int)GlobalSize(hg); - autokey_sendbufferlen = 0; - autokey_sendbuffer = (char*)malloc(txtlen + 10); - memset(autokey_sendbuffer, 0, txtlen + 10); - strClip = (char*)GlobalLock(hg); - strcpy(autokey_sendbuffer , strClip); - GlobalUnlock(hg); - CloseClipboard(); - autokey_lastkanastate = keyctrl.kanaref; - autokey_sendbufferlen = (int)strlen(autokey_sendbuffer); - autokey_sendbufferpos = 0; - keystat_senddata(0x80|0x70); - }else{ - CloseClipboard(); - } - } - }else{ - // 強制終了 - autokey_sendbufferpos = autokey_sendbufferlen; - } - } - break; - - default: -#if defined(SUPPORT_STATSAVE) - if ((uID >= IDM_FLAGSAVE) && (uID < (IDM_FLAGSAVE + SUPPORT_STATSAVE))) - { - OEMCHAR ext[4]; - OEMSPRINTF(ext, np2flagext, uID - IDM_FLAGSAVE); - flagsave(ext); - } - else if ((uID >= IDM_FLAGLOAD) && (uID < (IDM_FLAGLOAD + SUPPORT_STATSAVE))) - { - OEMCHAR ext[4]; - OEMSPRINTF(ext, np2flagext, uID - IDM_FLAGLOAD); - flagload(hWnd, ext, _T("Status Load"), TRUE); - } -#endif -#if defined(SUPPORT_DEBUGSS) - if ((uID >= IDM_DBSSSAVE0) && (uID <= IDM_DBSSSAVE3)) - { - debugsnapshot_save(uID - IDM_DBSSSAVE0); - } - else if ((uID >= IDM_DBSSLOAD0) && (uID <= IDM_DBSSLOAD3)) - { - debugsnapshot_load(uID - IDM_DBSSLOAD0); - } -#endif - break; - } - sysmng_update(update); -} - -LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - - PAINTSTRUCT ps; - RECT rc; - HDC hdc; - BOOL b; - UINT update; - HWND subwin; - WINLOCEX wlex; - - static int lastmx = -1; - static int lastmy = -1; - static int lastbtn = -1; - - switch (msg) { - // イメージファイルのD&Dに対応(Kai1) - case WM_DROPFILES: - np2_multithread_EnterCriticalSection(); - if(np2oscfg.dragdrop){ - int files; // Kai1追加 - OEMCHAR fname[MAX_PATH]; // Kai1追加 - const OEMCHAR *ext; // Kai1追加 - files = DragQueryFile((HDROP)wParam, (UINT)-1, NULL, 0); - REG8 hddrv_IDE = 0x00; - REG8 hddrv_IDECD = 0x00; - REG8 hddrv_SCSI = 0x20; - REG8 fddrv = 0x00; - UINT8 i; - -#if defined(SUPPORT_IDEIO) - while(hddrv_IDE <= 0x03 && np2cfg.idetype[hddrv_IDE]!=0x01) hddrv_IDE++; - while(hddrv_IDECD <= 0x03 && np2cfg.idetype[hddrv_IDECD]!=0x02) hddrv_IDECD++; -#endif // SUPPORT_IDEIO - for (i = 0; i < files; i++) { -#if defined(OSLANG_UTF8) - wchar_t wchr[MAX_PATH]; - DragQueryFileW((HDROP)wParam, i, wchr, NELEMENTS(wchr)); - codecnv_ucs2toutf8(fname, MAX_PATH, (UINT16*)wchr, -1); -#else - DragQueryFile((HDROP)wParam, i, fname, NELEMENTS(fname)); -#endif - ext = file_getext(fname); -#if defined(SUPPORT_IDEIO) - // CDイメージ? - if ((!file_cmpname(ext, OEMTEXT("iso"))) || - (!file_cmpname(ext, OEMTEXT("cue"))) || - (!file_cmpname(ext, OEMTEXT("ccd"))) || - (!file_cmpname(ext, OEMTEXT("cdm"))) || - (!file_cmpname(ext, OEMTEXT("mds"))) || - (!file_cmpname(ext, OEMTEXT("nrg")))) { - diskdrv_setsxsi(hddrv_IDECD, fname); - while(hddrv_IDECD <= 0x03 && np2cfg.idetype[hddrv_IDECD]!=0x02) hddrv_IDECD++; - continue; - } -#endif // SUPPORT_IDEIO - // HDイメージ? - if ((!file_cmpname(ext, str_hdi)) || - (!file_cmpname(ext, str_thd)) || - (!file_cmpname(ext, str_nhd))) { -#if defined(SUPPORT_IDEIO) - if (hddrv_IDE <= 0x03) { - diskdrv_setsxsi(hddrv_IDE, fname); - while(hddrv_IDE <= 0x03 && np2cfg.idetype[hddrv_IDE]!=0x01) hddrv_IDE++; - } -#else - if (hddrv_IDE <= 0x01) { - diskdrv_setsxsi(hddrv_IDE, fname); - hddrv_IDE++; - } -#endif - continue; - } - if (!file_cmpname(ext, str_hdd)) { - if (hddrv_SCSI <= 0x23) { - diskdrv_setsxsi(hddrv_SCSI, fname); - hddrv_SCSI++; - } - continue; - } - // FDイメージ…? - if (fddrv <= 0x02) { - diskdrv_setfdd(fddrv, fname, 0); - sysmng_update(SYS_UPDATEOSCFG); - toolwin_setfdd(fddrv, fname); - fddrv++; - } - } - DragFinish((HDROP)wParam); - if (GetKeyState(VK_SHIFT) & 0x8000) { - // Shiftキーが押下されていればリセット - pccore_cfgupdate(); -#ifdef HOOK_SYSKEY - stop_hook_systemkey(); -#endif - np2_multithread_Suspend(); - if(nevent_iswork(NEVENT_CDWAIT)){ - nevent_forceexecute(NEVENT_CDWAIT); - } - pccore_reset(); - np2_SetUserPause(0); - np2_multithread_Resume(); -#ifdef HOOK_SYSKEY - start_hook_systemkey(); -#endif - } - } - np2_multithread_LeaveCriticalSection(); - break; - - case WM_CREATE: - g_hWndMain = hWnd; - np2class_wmcreate(hWnd); - np2class_windowtype(hWnd, np2oscfg.wintype); - sstp_construct(hWnd); -#ifndef __GNUC__ - WINNLSEnableIME(hWnd, FALSE); -#endif - break; - - case WM_SYSCOMMAND: - update = 0; - switch(wParam) { - case IDM_TOOLWIN: - np2oscfg.toolwin = !np2oscfg.toolwin; - if (np2oscfg.toolwin) { - toolwin_create(); - } - else { - toolwin_destroy(); - } - update |= SYS_UPDATEOSCFG; - break; - -#if defined(SUPPORT_KEYDISP) - case IDM_KEYDISP: - np2oscfg.keydisp = !np2oscfg.keydisp; - if (np2oscfg.keydisp) { - kdispwin_create(); - } - else { - kdispwin_destroy(); - } - update |= SYS_UPDATEOSCFG; - break; -#endif -#if defined(SUPPORT_SOFTKBD) - case IDM_SOFTKBD: - np2oscfg.skbdwin = !np2oscfg.skbdwin; - if (np2oscfg.skbdwin) { - skbdwin_create(); - } - else { - skbdwin_destroy(); - } - update |= SYS_UPDATEOSCFG; - break; -#endif -#if defined(CPUCORE_IA32) && defined(SUPPORT_MEMDBG32) - case IDM_MEMDBG32: - mdbgwin_create(); - break; -#endif - case IDM_SCREENCENTER: - if ((!scrnmng_isfullscreen()) && - (!(GetWindowLong(hWnd, GWL_STYLE) & - (WS_MAXIMIZE | WS_MINIMIZE)))) { - wlex = np2_winlocexallwin(hWnd); - wincentering(hWnd); - winlocex_move(wlex); - winlocex_destroy(wlex); - } - break; - - case IDM_SNAPENABLE: - np2oscfg.WINSNAP = !np2oscfg.WINSNAP; - update |= SYS_UPDATEOSCFG; - break; - - case IDM_BACKGROUND: - np2oscfg.background ^= 1; - update |= SYS_UPDATEOSCFG; - break; - - case IDM_BGSOUND: - np2oscfg.background ^= 2; - update |= SYS_UPDATEOSCFG; - break; - - case IDM_RESTOREBORDER: - if(np2oscfg.wintype!=0){ - WINLOCEX wlex; - np2oscfg.wintype = 0; - wlex = np2_winlocexallwin(hWnd); - winlocex_setholdwnd(wlex, hWnd); - np2class_windowtype(hWnd, np2oscfg.wintype); - winlocex_move(wlex); - winlocex_destroy(wlex); - sysmng_update(SYS_UPDATEOSCFG); - } - break; - - case IDM_MEMORYDUMP: - debugsub_memorydump(); - break; - - case IDM_DEBUGUTY: - CDebugUtyView::New(); - break; - - case IDM_SCRNMUL4: - case IDM_SCRNMUL6: - case IDM_SCRNMUL8: - case IDM_SCRNMUL10: - case IDM_SCRNMUL12: - case IDM_SCRNMUL16: - if ((!scrnmng_isfullscreen()) && - !(GetWindowLong(g_hWndMain, GWL_STYLE) & WS_MINIMIZE)) - { - np2_multithread_EnterCriticalSection(); - scrnmng_setmultiple((int)(wParam - IDM_SCRNMUL)); - np2_multithread_LeaveCriticalSection(); - } - break; - - case SC_MINIMIZE: - wlex = np2_winlocexallwin(hWnd); - winlocex_close(wlex); - winlocex_destroy(wlex); - return(DefWindowProc(hWnd, msg, wParam, lParam)); - - case SC_RESTORE: - subwin = toolwin_gethwnd(); - if (subwin) { - ShowWindow(subwin, SW_SHOWNOACTIVATE); - } - subwin = kdispwin_gethwnd(); - if (subwin) { - ShowWindow(subwin, SW_SHOWNOACTIVATE); - } - subwin = skbdwin_gethwnd(); - if (subwin) { - ShowWindow(subwin, SW_SHOWNOACTIVATE); - } - subwin = mdbgwin_gethwnd(); - if (subwin) { - ShowWindow(subwin, SW_SHOWNOACTIVATE); - } - return(DefWindowProc(hWnd, msg, wParam, lParam)); - - default: - return(DefWindowProc(hWnd, msg, wParam, lParam)); - } - sysmng_update(update); - break; - - case WM_COMMAND: - np2_multithread_EnterCriticalSection(); - OnCommand(hWnd, wParam); - np2_multithread_LeaveCriticalSection(); - break; - - case WM_ACTIVATE: - if (LOWORD(wParam) != WA_INACTIVE) { - np2break &= ~NP2BREAK_MAIN; - scrndraw_redraw(); - if (np2stopemulate || np2userpause) { - scrndraw_draw(1); - } - np2_multithread_EnterCriticalSection(); - keystat_allrelease(); - mousemng_enable(MOUSEPROC_BG); - np2_multithread_LeaveCriticalSection(); - } - else { - np2break |= NP2BREAK_MAIN; - np2_multithread_EnterCriticalSection(); - mousemng_disable(MOUSEPROC_BG); - np2_multithread_LeaveCriticalSection(); - } - np2active_renewal(); - break; - - case WM_PAINT: - hdc = BeginPaint(hWnd, &ps); - if (np2opening) { - RECT rect; - int width; - int height; - HBITMAP hbmp; - BITMAP bmp; - HDC hmdc; - HBRUSH hbrush; - GetClientRect(hWnd, &rect); - width = rect.right - rect.left; - height = rect.bottom - rect.top; - HINSTANCE hInstance = CWndProc::FindResourceHandle(TEXT("NP2BMP"), RT_BITMAP); - hbmp = LoadBitmap(hInstance, TEXT("NP2BMP")); - GetObject(hbmp, sizeof(BITMAP), &bmp); - hbrush = (HBRUSH)SelectObject(hdc, - GetStockObject(BLACK_BRUSH)); - PatBlt(hdc, 0, 0, width, height, PATCOPY); - SelectObject(hdc, hbrush); - hmdc = CreateCompatibleDC(hdc); - SelectObject(hmdc, hbmp); - BitBlt(hdc, (width - bmp.bmWidth) / 2, - (height - bmp.bmHeight) / 2, - bmp.bmWidth, bmp.bmHeight, hmdc, 0, 0, SRCCOPY); - DeleteDC(hmdc); - DeleteObject(hbmp); - } - else { -// scrnmng_update(); - scrndraw_redraw(); - if (np2stopemulate || np2userpause) { - scrndraw_draw(1); - } - } - EndPaint(hWnd, &ps); - break; - - case WM_QUERYNEWPALETTE: - np2_multithread_EnterCriticalSection(); - scrnmng_querypalette(); - np2_multithread_LeaveCriticalSection(); - break; - - case WM_MOVE: - if ((!scrnmng_isfullscreen()) && - (!(GetWindowLong(hWnd, GWL_STYLE) & - (WS_MAXIMIZE | WS_MINIMIZE)))) { - GetWindowRect(hWnd, &rc); - np2oscfg.winx = rc.left; - np2oscfg.winy = rc.top; - sysmng_update(SYS_UPDATEOSCFG); - } - break; - - case WM_SIZE: - np2wab_forceupdate(); - break; - - case WM_ENTERMENULOOP: - if(!np2_multithread_Enabled()) - { - winuienter(); - } - sysmenu_update(GetSystemMenu(hWnd, FALSE)); - xmenu_update(GetMenu(hWnd)); - if (scrnmng_isfullscreen()) { - DrawMenuBar(hWnd); - } - break; - - case WM_EXITMENULOOP: - if(!np2_multithread_Enabled()) - { - winuileave(); - } - break; - - case WM_ENTERSIZEMOVE: - np2_multithread_EnterCriticalSection(); - if(!np2_multithread_Enabled()) - { - CSoundMng::GetInstance()->Disable(SNDPROC_MAIN); - } - mousemng_disable(MOUSEPROC_WINUI); - np2_multithread_LeaveCriticalSection(); - winlocex_destroy(smwlex); - smwlex = np2_winlocexallwin(hWnd); - scrnmng_entersizing(); - break; - - case WM_MOVING: - if (np2oscfg.WINSNAP) { - winlocex_moving(smwlex, (RECT *)lParam); - } - break; - - case WM_SIZING: - scrnmng_sizing((UINT)wParam, (RECT *)lParam); - break; - - case WM_EXITSIZEMOVE: - scrnmng_exitsizing(); - winlocex_move(smwlex); - winlocex_destroy(smwlex); - smwlex = NULL; - np2_multithread_EnterCriticalSection(); - mousemng_enable(MOUSEPROC_WINUI); - if(!np2_multithread_Enabled()) - { - CSoundMng::GetInstance()->Enable(SNDPROC_MAIN); - } - np2_multithread_LeaveCriticalSection(); - break; - - case WM_KEYDOWN: - autokey_sendbufferpos = autokey_sendbufferlen; // コピペ強制終了 np21w ver0.86 rev22 - if (wParam == VK_F11) { - np2class_enablemenu(g_hWndMain, TRUE); - return(DefWindowProc(hWnd, WM_SYSKEYDOWN, VK_F10, lParam)); - } - if ((wParam == VK_F12) && (!np2oscfg.F12COPY)) { - mousemng_toggle(MOUSEPROC_SYSTEM); - np2oscfg.MOUSE_SW = !np2oscfg.MOUSE_SW; - if(!np2oscfg.mouse_nc){ - SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) | CS_DBLCLKS); - }else/* if (!scrnmng_isfullscreen())*/ { - SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); - if (np2oscfg.wintype != 0) { - // XXX: メニューが出せなくなって詰むのを回避(暫定) - if (!scrnmng_isfullscreen()) { - WINLOCEX wlex; - np2oscfg.wintype = 0; - wlex = np2_winlocexallwin(hWnd); - winlocex_setholdwnd(wlex, hWnd); - np2class_windowtype(hWnd, np2oscfg.wintype); - winlocex_move(wlex); - winlocex_destroy(wlex); - sysmng_update(SYS_UPDATEOSCFG); - } - } - } - sysmng_update(SYS_UPDATECFG); - } - else if ((wParam == VK_F12) && (np2oscfg.F12COPY==7)) { - np2oscfg.NOWAIT = 1; - update |= SYS_UPDATECFG; - } - else if ((wParam == VK_F12) && (np2oscfg.F12COPY==8)) { - np2oscfg.NOWAIT = !np2oscfg.NOWAIT; - update |= SYS_UPDATECFG; - } -#if defined(SUPPORT_CL_GD5430) && defined(SUPPORT_WAB) - else if ((wParam == VK_F12) && (np2oscfg.F12COPY==9)) { - np2_multithread_EnterCriticalSection(); - if(np2clvga.enabled && cirrusvga_opaque){ - np2wab_setRelayState(np2wab.relay ? 0 : 1); - } - np2_multithread_LeaveCriticalSection(); - } -#endif -#ifdef HOOK_SYSKEY - else if ((wParam == VK_SNAPSHOT) && (np2oscfg.syskhook)) { - // nothing to do - } -#endif - else { - if (!np2userpause) { - np2_multithread_EnterCriticalSection(); - winkbd_keydown(wParam, lParam); - np2_multithread_LeaveCriticalSection(); - } - } - break; - - case WM_KEYUP: - if (wParam == VK_F11) { - return(DefWindowProc(hWnd, WM_SYSKEYUP, VK_F10, lParam)); - } - if ((wParam == VK_F12) && (np2oscfg.F12COPY==7)) { - np2oscfg.NOWAIT = 0; - update |= SYS_UPDATECFG; - } - else if ((wParam != VK_F12) || (np2oscfg.F12COPY && np2oscfg.F12COPY!=7)) { - if (!np2userpause) { - np2_multithread_EnterCriticalSection(); - winkbd_keyup(wParam, lParam); - np2_multithread_LeaveCriticalSection(); - } - } - break; - - case WM_SYSKEYDOWN: - autokey_sendbufferpos = autokey_sendbufferlen; // コピペ強制終了 np21w ver0.86 rev22 -#ifdef HOOK_SYSKEY - if (GetAsyncKeyState (VK_RMENU) >> ((sizeof(SHORT) * 8) - 1)) { // np21w ver0.86 rev6 -#else - if (lParam & 0x20000000) { // ver0.30 -#endif - if ((np2oscfg.shortcut & 1) && (wParam == VK_RETURN)) { - changescreen(g_scrnmode ^ SCRNMODE_FULLSCREEN); - break; - } - if ((np2oscfg.shortcut & 2) && (wParam == VK_F4)) { - SendMessage(hWnd, WM_CLOSE, 0, 0L); - break; - } - if (np2oscfg.mouse_nc && np2oscfg.wintype != 0) { - // XXX: メニューが出せなくなって詰むのを回避(暫定) - if (!scrnmng_isfullscreen()) { - np2oscfg.wintype = 0; - wlex = np2_winlocexallwin(hWnd); - winlocex_setholdwnd(wlex, hWnd); - np2class_windowtype(hWnd, np2oscfg.wintype); - winlocex_move(wlex); - winlocex_destroy(wlex); - sysmng_update(SYS_UPDATEOSCFG); - break; - } - } - } - if (!np2userpause) { - np2_multithread_EnterCriticalSection(); - winkbd_keydown(wParam, lParam); - np2_multithread_LeaveCriticalSection(); - } - break; - - case WM_SYSKEYUP: - if (!np2userpause) { - np2_multithread_EnterCriticalSection(); - winkbd_keyup(wParam, lParam); - np2_multithread_LeaveCriticalSection(); - } - break; - - case WM_MOUSEMOVE: - np2_multithread_EnterCriticalSection(); - if (scrnmng_isfullscreen()) { - POINT p; - if (GetCursorPos(&p)) { - scrnmng_fullscrnmenu(p.y); - } - } - if(np2oscfg.mouse_nc/* && !scrnmng_isfullscreen()*/){ - static int mousebufX = 0; // マウス移動バッファ(X) - static int mousebufY = 0; // マウス移動バッファ(Y) - int x = LOWORD(lParam); - int y = HIWORD(lParam); - - SINT16 dx, dy; - UINT8 btn; - btn = mousemng_getstat(&dx, &dy, 0); - if(lastmx == -1 || lastmy == -1){ - lastmx = x; - lastmy = y; - } - if((x-lastmx) || (y-lastmy)){ - RECT r; - int mouse_edge_sh_x = 100; - int mouse_edge_sh_y = 100; - int dxmul, dymul; - GetClientRect(hWnd, &r); - mouse_edge_sh_x = (r.right-r.left)/8; - mouse_edge_sh_y = (r.bottom-r.top)/8; - mousebufX += ((x-lastmx)*np2oscfg.mousemul); - mousebufY += ((y-lastmy)*np2oscfg.mousemul); - if(mousebufX >= np2oscfg.mousediv || mousebufX <= -np2oscfg.mousediv){ - dx += (SINT16)(mousebufX / np2oscfg.mousediv); - mousebufX = mousebufX % np2oscfg.mousediv; - } - if(mousebufY >= np2oscfg.mousediv || mousebufY <= -np2oscfg.mousediv){ - dy += (SINT16)(mousebufY / np2oscfg.mousediv); - mousebufY = mousebufY % np2oscfg.mousediv; - } - // XXX: 端実験 -#define MOUSE_EDGE_ACM 4 - if(x 0){ - dxmul = 1+(mouse_edge_sh_x - (r.right-x))*MOUSE_EDGE_ACM/mouse_edge_sh_x; - }else{ - dxmul = 1; - } - if(y 0){ - dymul = 1+(mouse_edge_sh_y - (r.bottom-y))*MOUSE_EDGE_ACM/mouse_edge_sh_y; - }else{ - dymul = 1; - } - dxmul = (int)dx * dxmul; - dymul = (int)dy * dymul; - if(dxmul < -128) dxmul = -128; - if(dxmul > +127) dxmul = +127; - if(dymul < -128) dymul = -128; - if(dymul > +127) dymul = +127; - dx = (SINT16)dxmul; - dy = (SINT16)dymul; - mousemng_setstat(dx, dy, btn); - lastmx = x; - lastmy = y; - } - } - np2_multithread_LeaveCriticalSection(); - break; - - case WM_LBUTTONDOWN: - np2_multithread_EnterCriticalSection(); - autokey_sendbufferpos = autokey_sendbufferlen; // コピペ強制終了 np21w ver0.86 rev22 - if (!mousemng_buttonevent(MOUSEMNG_LEFTDOWN)) { - if (!scrnmng_isfullscreen()) { - if (np2oscfg.wintype == 2) { - np2_multithread_LeaveCriticalSection(); - return(SendMessage(hWnd, WM_NCLBUTTONDOWN, - HTCAPTION, 0L)); - } - } -#if defined(SUPPORT_DCLOCK) - else { - POINT p; - if ((GetCursorPos(&p)) && - (scrnmng_isdispclockclick(&p))) { - np2oscfg.clk_x++; - sysmng_update(SYS_UPDATEOSCFG); - DispClock::GetInstance()->Reset(); - } - } -#endif - np2_multithread_LeaveCriticalSection(); - return(DefWindowProc(hWnd, msg, wParam, lParam)); - } - np2_multithread_LeaveCriticalSection(); - break; - - case WM_LBUTTONUP: - np2_multithread_EnterCriticalSection(); - if (!mousemng_buttonevent(MOUSEMNG_LEFTUP)) { - np2_multithread_LeaveCriticalSection(); - return(DefWindowProc(hWnd, msg, wParam, lParam)); - } - np2_multithread_LeaveCriticalSection(); - break; - - case WM_MBUTTONDOWN: - np2_multithread_EnterCriticalSection(); - autokey_sendbufferpos = autokey_sendbufferlen; // コピペ強制終了 np21w ver0.86 rev22 - mousemng_toggle(MOUSEPROC_SYSTEM); - np2oscfg.MOUSE_SW = !np2oscfg.MOUSE_SW; - sysmng_update(SYS_UPDATECFG); - if (!np2oscfg.MOUSE_SW) { - if(!np2oscfg.mouse_nc){ - SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) | CS_DBLCLKS); - }else/* if (!scrnmng_isfullscreen())*/ { - SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); - if (np2oscfg.wintype != 0) { - // XXX: メニューが出せなくなって詰むのを回避(暫定) - if (!scrnmng_isfullscreen()) { - WINLOCEX wlex; - np2oscfg.wintype = 0; - wlex = np2_winlocexallwin(hWnd); - winlocex_setholdwnd(wlex, hWnd); - np2class_windowtype(hWnd, np2oscfg.wintype); - winlocex_move(wlex); - winlocex_destroy(wlex); - sysmng_update(SYS_UPDATEOSCFG); - } - } - } - }else{ - SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); - } - np2_multithread_LeaveCriticalSection(); - break; - - case WM_RBUTTONDOWN: - np2_multithread_EnterCriticalSection(); - autokey_sendbufferpos = autokey_sendbufferlen; // コピペ強制終了 np21w ver0.86 rev22 - if (!mousemng_buttonevent(MOUSEMNG_RIGHTDOWN)) { - if (!scrnmng_isfullscreen()) { - np2popup(hWnd, lParam); - } -#if defined(SUPPORT_DCLOCK) - else { - POINT p; - if ((GetCursorPos(&p)) && - (scrnmng_isdispclockclick(&p)) && - (np2oscfg.clk_x)) { - np2oscfg.clk_fnt++; - sysmng_update(SYS_UPDATEOSCFG); - DispClock::GetInstance()->Reset(); - } - } -#endif - np2_multithread_LeaveCriticalSection(); - return(DefWindowProc(hWnd, msg, wParam, lParam)); - } - np2_multithread_LeaveCriticalSection(); - break; - - case WM_RBUTTONUP: - np2_multithread_EnterCriticalSection(); - if (!mousemng_buttonevent(MOUSEMNG_RIGHTUP)) { - np2_multithread_LeaveCriticalSection(); - return(DefWindowProc(hWnd, msg, wParam, lParam)); - } - np2_multithread_LeaveCriticalSection(); - break; - - case WM_LBUTTONDBLCLK: - if (!np2oscfg.MOUSE_SW) { - if(!np2oscfg.mouse_nc){ - if (!scrnmng_isfullscreen()) { - np2oscfg.wintype++; - if (np2oscfg.wintype >= 3) { - np2oscfg.wintype = 0; - } - wlex = np2_winlocexallwin(hWnd); - winlocex_setholdwnd(wlex, hWnd); - np2class_windowtype(hWnd, np2oscfg.wintype); - winlocex_move(wlex); - winlocex_destroy(wlex); - sysmng_update(SYS_UPDATEOSCFG); - } - }else if (!scrnmng_isfullscreen()) { - SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); - if (np2oscfg.wintype != 0) { - // XXX: メニューが出せなくなって詰むのを回避(暫定) - if (!scrnmng_isfullscreen()) { - WINLOCEX wlex; - np2oscfg.wintype = 0; - wlex = np2_winlocexallwin(hWnd); - winlocex_setholdwnd(wlex, hWnd); - np2class_windowtype(hWnd, np2oscfg.wintype); - winlocex_move(wlex); - winlocex_destroy(wlex); - sysmng_update(SYS_UPDATEOSCFG); - } - } - } - }else{ - SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); - } - break; - - case WM_RBUTTONDBLCLK: - if (!np2oscfg.MOUSE_SW) { - if(!np2oscfg.mouse_nc){ - }else/* if (!scrnmng_isfullscreen())*/ { - SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); - if (np2oscfg.wintype != 0) { - // XXX: メニューが出せなくなって詰むのを回避(暫定) - if (!scrnmng_isfullscreen()) { - WINLOCEX wlex; - np2oscfg.wintype = 0; - wlex = np2_winlocexallwin(hWnd); - winlocex_setholdwnd(wlex, hWnd); - np2class_windowtype(hWnd, np2oscfg.wintype); - winlocex_move(wlex); - winlocex_destroy(wlex); - sysmng_update(SYS_UPDATEOSCFG); - } - } - } - }else{ - SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); - } - break; - - case WM_MOUSEWHEEL: - if(np2oscfg.usewheel){ - if ((wParam & (MK_CONTROL|MK_SHIFT)) == (MK_CONTROL|MK_SHIFT)) { - int mmul = np2oscfg.mousemul; - int mdiv = np2oscfg.mousediv; - // 面倒なので x/2にする - if(mdiv == 1) { - mdiv *= 2; - mmul *= 2; - } - if(GET_WHEEL_DELTA_WPARAM(wParam) > 0){ - if(mdiv <= 2){ - mdiv = 2; - mmul++; - }else{ - mdiv--; - } - }else{ - if(mmul <= 2){ - mmul = 2; - mdiv++; - }else{ - mmul--; - } - } - if(mmul > 8) mmul = 8; - if(mdiv > 8) mdiv = 8; - // 2で割れるなら割っておく - if(mdiv == 2 && mmul%2 == 0) { - mdiv /= 2; - mmul /= 2; - } - np2oscfg.mousemul = mmul; - np2oscfg.mousediv = mdiv; - mousemng_updatespeed(); - sys_miscinfo.showmousespeed = 1; - sysmng_updatecaption(SYS_UPDATECAPTION_MISC); - tmrSysMngHide = SetTimer(hWnd, TMRSYSMNG_ID, 5000, SysMngHideTimerProc); - }else{ - //if(np2oscfg.usemastervolume){ - int cMaster = np2cfg.vol_master; - cMaster += GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA * 2; - if(cMaster < 0) cMaster = 0; - if(cMaster > np2oscfg.mastervolumemax) cMaster = np2oscfg.mastervolumemax; - if (np2cfg.vol_master != cMaster) - { - np2_multithread_EnterCriticalSection(); - np2cfg.vol_master = cMaster; - soundmng_setvolume(cMaster); - fmboard_updatevolume(); - np2_multithread_LeaveCriticalSection(); - } - sys_miscinfo.showvolume = 1; - sysmng_updatecaption(SYS_UPDATECAPTION_MISC); - tmrSysMngHide = SetTimer(hWnd, TMRSYSMNG_ID, 5000, SysMngHideTimerProc); - //} - } - } - break; - -#if defined(SUPPORT_SCRN_DIRECT3D) - case WM_SETFOCUS: - if (scrnmng_isfullscreen() && scrnmng_current_drawtype==DRAWTYPE_DIRECT3D && !np2oscfg.d3d_exclusive && !winui_en) { - ShowWindow( hWnd, SW_RESTORE ); - } - break; - - case WM_KILLFOCUS: - if (scrnmng_isfullscreen() && scrnmng_current_drawtype==DRAWTYPE_DIRECT3D && !np2oscfg.d3d_exclusive && !winui_en) { - ShowWindow( hWnd, SW_MINIMIZE ); - } - break; -#endif - - case WM_CLOSE: - b = FALSE; - if (!np2oscfg.comfirm) { - b = TRUE; - } - else if (sstpconfirm_exit()) - { - winuienter(); - if (messagebox(hWnd, MAKEINTRESOURCE(IDS_CONFIRM_EXIT), - MB_ICONQUESTION | MB_YESNO) == IDYES) - { - b = TRUE; - } - winuileave(); - } - if (b) { - // 初期画面サイズに戻す - np2_multithread_EnterCriticalSection(); - scrnmng_setsize(0, 0, 640, 400); - np2_multithread_LeaveCriticalSection(); - if (np2oscfg.WINSNAP) { - RECT currect; - GetWindowRect(hWnd, &currect); - winlocex_moving(smwlex, &currect); - } - - CDebugUtyView::AllClose(); - CDebugUtyView::DisposeAllClosedWindow(); - DestroyWindow(hWnd); - } - break; - - case WM_DESTROY: - np2class_wmdestroy(hWnd); - PostQuitMessage(0); - break; - - case WM_NP2CMD: - np2_multithread_EnterCriticalSection(); - switch(LOWORD(lParam)) { - case NP2CMD_EXIT: - np2quitmsg = 1; - PostQuitMessage(0); - break; - - case NP2CMD_EXIT2: - np2quitmsg = 2; - PostQuitMessage(0); - break; - - case NP2CMD_RESET: - pccore_cfgupdate(); -#ifdef HOOK_SYSKEY - stop_hook_systemkey(); -#endif - np2_multithread_Suspend(); - if(nevent_iswork(NEVENT_CDWAIT)){ - nevent_forceexecute(NEVENT_CDWAIT); - } - pccore_reset(); - np2_SetUserPause(0); - np2_multithread_Resume(); -#ifdef HOOK_SYSKEY - start_hook_systemkey(); -#endif - break; - } - np2_multithread_LeaveCriticalSection(); - break; - - case WM_SSTP: - switch(LOWORD(lParam)) { - case FD_CONNECT: - if (!HIWORD(lParam)) { - sstp_connect(); - } - break; - case FD_READ: - if (!HIWORD(lParam)) { - sstp_readSocket(); - } - break; - case FD_WRITE: - if (!HIWORD(lParam)) { -// sstp_writeSokect(); - } - break; - case FD_CLOSE: - if (!HIWORD(lParam)) { - sstp_disconnect(); - } - break; - } - break; - - case MM_MIM_DATA: - CComMidiIn32::RecvData(reinterpret_cast(wParam), static_cast(lParam)); - break; - - case MM_MIM_LONGDATA: - CComMidiIn32::RecvExcv(reinterpret_cast(wParam), reinterpret_cast(lParam)); - break; - -#if defined(SUPPORT_IDEIO) -#ifdef SUPPORT_PHYSICAL_CDDRV - case WM_DEVICECHANGE: - { - PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam; - switch(wParam) - { - case DBT_DEVICEARRIVAL: - case DBT_DEVICEREMOVECOMPLETE: - // See if a CD-ROM or DVD was inserted into a drive. - if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME) - { - PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb; - - if (lpdbv -> dbcv_flags & DBTF_MEDIA) - { - int i; - int drvlnum; - int unitmask = lpdbv ->dbcv_unitmask; - OEMCHAR *fname; - OEMCHAR fnamebuf[MAX_PATH]; - OEMCHAR drvstr[] = OEMTEXT("x:"); - for (drvlnum = 0; drvlnum < 26; ++drvlnum) - { - if (unitmask & 0x1) - break; - unitmask = unitmask >> 1; - } - drvstr[0] = 'A' + drvlnum; - np2_multithread_EnterCriticalSection(); - for(i=0;i<4;i++){ - if(sxsi_getdevtype(i)==SXSIDEV_CDROM){ - fname = np2cfg.idecd[i]; - if(_tcsnicmp(fname, OEMTEXT("\\\\.\\"), 4)==0){ - fname += 4; - if(_tcsicmp(fname, drvstr)==0){ - _tcscpy(fnamebuf, np2cfg.idecd[i]); - if(wParam == DBT_DEVICEARRIVAL){ - // CD挿入 - diskdrv_setsxsi(i, fnamebuf); - }else{ - // CD取出 XXX: 中身が空でもマウントは継続 - diskdrv_setsxsi(i, NULL); - _tcscpy(np2cfg.idecd[i], fnamebuf); - } - sysmng_updatecaption(SYS_UPDATECAPTION_FDD); - } - } - } - } - np2_multithread_LeaveCriticalSection(); - } - } - break; - } - } - break; -#endif -#endif - - default: -#ifdef SUPPORT_IDEIO - if(msg == WM_QueryCancelAutoPlay){ - int i; - for(i=0;i<4;i++){ - if(sxsi_getdevtype(i)==SXSIDEV_CDROM){ - if ((np2cfg.idecd[i][0]==_T('\0') || np2cfg.idecd[i][0]==_T('\\')) && np2cfg.idecd[i][1]==_T('\\') && np2cfg.idecd[i][2]==_T('.') && np2cfg.idecd[i][3]==_T('\\')) { - return 1; - } - } - } - } -#endif - - return(DefWindowProc(hWnd, msg, wParam, lParam)); - } - return(0L); -} - -// --- auto sendkey - -static unsigned short sjis_to_jis(unsigned short sjis) -{ - int h = sjis >> 8; - int l = sjis & 0xff; - - if (h <= 0x9f) - { - if (l < 0x9f) - h = (h << 1) - 0xe1; - else - h = (h << 1) - 0xe0; - } - else - { - if (l < 0x9f) - h = (h << 1) - 0x161; - else - h = (h << 1) - 0x160; - } - - if (l < 0x7f) - l -= 0x1f; - else if (l < 0x9f) - l -= 0x20; - else - l -= 0x7e; - return h << 8 | l; -} - -void autoSendKey(){ - static int shift = 0; - static int kanjimode = 0; - static DWORD lastsendtime = 0; - int capslock = 0; - //int i; - DWORD curtime = 0; - - // 送るものなし - if (autokey_sendbufferlen == 0) - { - return; - } - - // 10文字だけ送る(入力速度制御付き) - curtime = GetTickCount(); - if(curtime - lastsendtime > 256/pccore.multiple+8){ - int i; - int maxkey = 1;//((int)pccore.multiple-20)/16; - if(maxkey <= 0) maxkey = 1; - for(i=0;i> 12) & 0xf)]]); - keystat_senddata(0x80 | vkeylist[hexToAsc[((jiscode >> 12) & 0xf)]]); - keystat_senddata(0x00 | vkeylist[hexToAsc[((jiscode >> 8) & 0xf)]]); - keystat_senddata(0x80 | vkeylist[hexToAsc[((jiscode >> 8) & 0xf)]]); - keystat_senddata(0x00 | vkeylist[hexToAsc[((jiscode >> 4) & 0xf)]]); - keystat_senddata(0x80 | vkeylist[hexToAsc[((jiscode >> 4) & 0xf)]]); - keystat_senddata(0x00 | vkeylist[hexToAsc[((jiscode) & 0xf)]]); - keystat_senddata(0x80 | vkeylist[hexToAsc[((jiscode) & 0xf)]]); - if (autokey_kanjimode == 2) - { - // DOSは1文字毎に解除される - kanjimode = 0; - } - i += 16; - } - autokey_sendbufferpos++; - } - else - { - i--; - } - np2_multithread_LeaveCriticalSection(); - } - autokey_sendbufferpos++; - //if (isKanji) - //{ - // // 漢字は慎重に送る - // break; - //} - if (keybrd.buffers > KB_BUF * 3 / 4) - { - // 溢れそうなので一旦逃げる - break; - } - } - } - lastsendtime = curtime; - } - - // 送信完了したら - if(autokey_sendbufferpos >= autokey_sendbufferlen){ - if (kanjimode) - { - keystat_senddata(0x00 | 0x74); - keystat_senddata(0x00 | 0x35); - keystat_senddata(0x80 | 0x35); - keystat_senddata(0x80 | 0x74); - kanjimode = 0; - } - if (autokey_lastkanastate != 0xff && keyctrl.kanaref == 0xff || autokey_lastkanastate == 0xff && keyctrl.kanaref != 0xff) - { - keystat_senddata(0x00 | 0x72); - keystat_senddata(0x80 | 0x72); - } - keystat_senddata(0x80|0x70); - autokey_sendbufferlen = 0; - autokey_sendbufferpos = 0; - _MFREE(autokey_sendbuffer); - autokey_sendbuffer = NULL; - shift = 0; - } -} - -// キーコード表作成 -void createAsciiTo98KeyCodeList(){ - int i; - // キーコード表作成(暫定) - char numkeys[] = {0,'!', '"','#','$','%','&','\'','(',')'}; - for(i='0';i<='9';i++){ - vkeylist[i] = i-'0'; - if(i=='0') vkeylist[i] = 0x0a; - vkeylist[numkeys[i-'0']] = vkeylist[i]; - shift_on[numkeys[i-'0']] = 1; - } - char asckeycode[] = {0x1d,0x2d,0x2b,0x1f,0x12,0x20,0x21,0x22,0x17,0x23,0x24,0x25,0x2f,0x2e,0x18,0x19,0x10,0x13,0x1e,0x14,0x16,0x2c,0x11,0x2a,0x15,0x29}; - for(i='A';i<='Z';i++){ - vkeylist[i] = asckeycode[i-'A']; - shift_on[i] = 1; - vkeylist[i+0x20] = vkeylist[i]; - } - char spkeyascii[] = { '-', '^','\\', '@', '[', ';', ':', ']', ',', '.', '/', '_'}; - char spshascii[] = { '=', '`', '|', '~', '{', '+', '*', '}', '<', '>', '?', '_'}; - char spkeycode[] = {0x0B,0x0C,0x0D,0x1A,0x1B,0x26,0x27,0x28,0x30,0x31,0x32,0x33}; - vkeylist[' '] = 0x34; - vkeylist['\t'] = 0x0f; - vkeylist['\n'] = 0x1c; - for(i=0;i<=sizeof(spkeyascii)/sizeof(spkeyascii[0]);i++){ - vkeylist[spkeyascii[i]] = spkeycode[i]; - vkeylist[ spshascii[i]] = spkeycode[i]; - shift_on[ spshascii[i]] = 1; - } - char kanakeycode[] = { 0x31,0x1b,0x28,0x30,0x32,0x0a,0x03,0x12,0x04,0x05,0x06,0x07,0x08,0x09,0x29,0x0d,0x03,0x12,0x04,0x05,0x06,0x14,0x21,0x22,0x27,0x2d,0x2a,0x1f,0x13,0x19,0x2b,0x10,0x1d,0x29,0x11,0x1e,0x16,0x17,0x01,0x30,0x24,0x20,0x2c,0x02,0x0c,0x0b,0x23,0x2e,0x28,0x32,0x2f,0x07,0x08,0x09,0x18,0x25,0x31,0x26,0x33,0x0a,0x15,0x1a,0x1b }; - for (i = 0xa1; i <= 0xdf; i++) - { - vkeylist[i] = kanakeycode[i - 0xa1]; - if (i <= 0xaf) - { - shift_on[i] = 1; - } - else - { - shift_on[i] = 0; - } - } -} - -#ifdef HOOK_SYSKEY -// システムショートカットキー -LRESULT CALLBACK LowLevelKeyboardProc(INT nCode, WPARAM wParam, LPARAM lParam) -{ - if(np2oscfg.syskhook){ - // By returning a non-zero value from the hook procedure, the - // message does not get passed to the target window - KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam; - BOOL bControlKeyDown = 0; - BOOL bShiftKeyDown = 0; - BOOL bAltKeyDown = 0; - - switch (nCode) - { - case HC_ACTION: - { - if(GetForegroundWindow()==g_hWndMain){ - KBDLLHOOKSTRUCT *kbstruct = (KBDLLHOOKSTRUCT*)lParam; - // Check to see if the CTRL,DHIFT,ALT key is pressed - bControlKeyDown = GetAsyncKeyState (VK_LCONTROL) >> ((sizeof(SHORT) * 8) - 1); - bShiftKeyDown = GetAsyncKeyState (VK_LSHIFT) >> ((sizeof(SHORT) * 8) - 1); - bAltKeyDown = GetAsyncKeyState (VK_LMENU) >> ((sizeof(SHORT) * 8) - 1); - - // Disable CTRL+ESC, ALT+TAB, ALT+ESC - if (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown - || pkbhs->vkCode == VK_TAB && bAltKeyDown - || pkbhs->vkCode == VK_ESCAPE && bAltKeyDown - || pkbhs->vkCode == VK_LWIN - || pkbhs->vkCode == VK_APPS){ - - switch((int)wParam){ - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - //np2_multithread_EnterCriticalSection(); - winkbd_keydown(kbstruct->vkCode, ((kbstruct->flags)<<24)|(kbstruct->scanCode<<16)); - //np2_multithread_LeaveCriticalSection(); - break; - case WM_KEYUP: - case WM_SYSKEYUP: - //np2_multithread_EnterCriticalSection(); - winkbd_keyup(kbstruct->vkCode, ((kbstruct->flags)<<24)|(kbstruct->scanCode<<16)); - //np2_multithread_LeaveCriticalSection(); - break; - } - return 1; - } - if(pkbhs->vkCode == VK_SCROLL && bAltKeyDown && bControlKeyDown){ - // Ctrl+Alt+ScrollLock → Ctrl+Alt+Delete - switch((int)wParam){ - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - //np2_multithread_EnterCriticalSection(); - keystat_keydown(0x39); - //np2_multithread_LeaveCriticalSection(); - break; - case WM_KEYUP: - case WM_SYSKEYUP: - //np2_multithread_EnterCriticalSection(); - keystat_keyup(0x39); - //np2_multithread_LeaveCriticalSection(); - break; - } - return 1; - } -#ifdef HOOK_SYSKEY - else if ((pkbhs->vkCode == VK_SNAPSHOT) && (np2oscfg.syskhook)) { - // PrintScreen -> COPY - switch((int)wParam){ - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - //np2_multithread_EnterCriticalSection(); - keystat_keydown(0x61); - //np2_multithread_LeaveCriticalSection(); - break; - case WM_KEYUP: - case WM_SYSKEYUP: - ////np2_multithread_EnterCriticalSection(); - keystat_keyup(0x61); - //np2_multithread_LeaveCriticalSection(); - break; - } - } -#endif - } - break; - } - - default: - break; - } - } - return CallNextHookEx (hHook, nCode, wParam, lParam); -} -#endif - -/** - * 1フレーム実行 - * @param[in] bDraw 描画フラグ - */ -static void ExecuteOneFrame_MT_EmulateThread(BOOL bDraw) -{ - if (recvideo_isEnabled()) - { - bDraw = TRUE; - } - - pccore_exec(bDraw); - - joymng_sync(); - mousemng_sync(); - recvideo_write(); -} -static void ExecuteOneFrame(BOOL bDraw) -{ - if (recvideo_isEnabled()) - { - bDraw = TRUE; - } - - joymng_sync(); - mousemng_sync(); - pccore_exec(bDraw); - recvideo_write(); -#if defined(SUPPORT_DCLOCK) - DispClock::GetInstance()->Update(); -#endif -#if defined(SUPPORT_VSTi) - CVstEditWnd::OnIdle(); -#endif // defined(SUPPORT_VSTi) -} - -static void framereset_MT_EmulateThread(UINT cnt) { - - framecnt = 0; -} -static void framereset_MT_UIThread(UINT cnt) { - - framecntUI = 0; -#if defined(SUPPORT_DCLOCK) - scrnmng_dispclock(); -#endif - kdispwin_draw((UINT8)cnt); - sysmng_requestupdatecheck(); - skbdwin_process(); - mdbgwin_process(); - toolwin_draw((UINT8)cnt); - CDebugUtyView::AllUpdate(false); - if (np2oscfg.DISPCLK & 3) { - if (sysmng_workclockrenewal()) { - sysmng_updatecaption(SYS_UPDATECAPTION_CLK); - } - } -} -static void framereset_ALL(UINT cnt) { - framereset_MT_EmulateThread(cnt); - framereset_MT_UIThread(cnt); -} - -static void (*framereset)(UINT cnt) = framereset_ALL; - -static void processwait(UINT cnt) { - - static int averageskipcounter = 0; - static int skipnext = 0; - static int incskip = 0; - - UINT count = timing_getcount(); -#if defined(CPUCORE_IA32) -#if defined(SUPPORT_ASYNC_CPU) - if (!np2cpu_lastTimingValid) { - np2cpu_lastTimingValue = timing_getcount_raw(); - np2cpu_lastTimingValid = 1; - } -#endif -#endif - if (count+lateframecount >= cnt) { - lateframecount = lateframecount + count - cnt; -#if defined(SUPPORT_IA32_HAXM) - if (np2hax.enable) { - np2haxcore.hurryup = 0; - lateframecount = 0; - } -#endif - if(lateframecount > np2oscfg.cpustabf) lateframecount = np2oscfg.cpustabf; - timing_setcount(0); - framereset(cnt); - if(skipnext > 0){ - if(averageskipcounter <= 1){ - skipnext = 0; - } - } - incskip = 0; - averageskipcounter = 0; -#if defined(CPUCORE_IA32) -#if defined(SUPPORT_ASYNC_CPU) - np2cpu_lastTimingValid = 0; -#endif -#endif - } - else { - if(lateframecount){ - Sleep(0); - if(skipnext > 0) skipnext--; - }else{ - if(skipnext > 0 && averageskipcounter==0){ - Sleep(skipnext); // 休めるだけ休む - }else{ - Sleep(0); - } - if(averageskipcounter>1){ - if(!incskip && skipnext < 10) skipnext++; - incskip = 1; - } - averageskipcounter++; - } - } -} - -void unloadNP2INI(){ - // 旧INI片付け - - // 画面表示倍率を保存 - np2oscfg.scrn_mul = scrnmng_getmultiple(); - toolwin_destroy(); - kdispwin_destroy(); - skbdwin_destroy(); - mdbgwin_destroy(); - - pccore_cfgupdate(); - - mousemng_disable(MOUSEPROC_WINUI); - S98_trash(); - -#if defined(SUPPORT_RESUME) - if (np2oscfg.resume) { - flagsave(str_sav); - } - else { - flagdelete(str_sav); - } -#endif - - sxsi_alltrash(); - pccore_term(); - - CSoundMng::GetInstance()->Close(); - CSoundMng::Deinitialize(); - scrnmng_destroy(); - recvideo_close(); - - mousemng_destroy(); - - if (sys_updates & (SYS_UPDATECFG | SYS_UPDATEOSCFG)) { - initsave(); - toolwin_writeini(); - kdispwin_writeini(); - skbdwin_writeini(); - mdbgwin_writeini(); - } -#if defined(SUPPORT_HOSTDRV) - hostdrv_writeini(); -#endif // defined(SUPPORT_HOSTDRV) -#if defined(SUPPORT_WAB) - wabwin_writeini(); -#endif // defined(SUPPORT_WAB) - skbdwin_deinitialize(); - - np2opening = 1; - - InvalidateRect( g_hWndMain, NULL, FALSE ); - UpdateWindow( g_hWndMain ); -} -void loadNP2INI(const OEMCHAR *fname){ - HINSTANCE hInstance; - BOOL xrollkey; - //WNDCLASS wc; - HWND hWnd; - DWORD style; - int i; -#ifdef OPENING_WAIT - DWORD tick; -#endif - -#ifdef HOOK_SYSKEY - stop_hook_systemkey(); -#endif - - LPTSTR lpFilenameBuf = (LPTSTR)malloc((_tcslen(fname)+1)*sizeof(TCHAR)); - _tcscpy(lpFilenameBuf, fname); - hInstance = g_hInstance; - - // 新INI読み込み - Np2Arg::GetInstance()->setiniFilename(lpFilenameBuf); - - initload(); - toolwin_readini(); - kdispwin_readini(); - skbdwin_readini(); - mdbgwin_readini(); -#if defined(SUPPORT_WAB) - wabwin_readini(); - np2wabcfg.readonly = np2oscfg.readonly; -#endif // defined(SUPPORT_WAB) -#if defined(SUPPORT_HOSTDRV) - hostdrv_readini(); -#endif // defined(SUPPORT_HOSTDRV) - toolwin_readini(); - - rand_setseed((unsigned)time(NULL)); - - szClassName[0] = (TCHAR)np2oscfg.winid[0]; - szClassName[1] = (TCHAR)np2oscfg.winid[1]; - szClassName[2] = (TCHAR)np2oscfg.winid[2]; - -#if !defined(_WIN64) - mmxflag = (havemmx())?0:MMXFLAG_NOTSUPPORT; - mmxflag += (np2oscfg.disablemmx)?MMXFLAG_DISABLE:0; -#endif - TRACEINIT(); - - xrollkey = (np2oscfg.xrollkey == 0); - if (np2oscfg.KEYBOARD >= KEY_TYPEMAX) { - int keytype = GetKeyboardType(1); - if ((keytype & 0xff00) == 0x0d00) { - np2oscfg.KEYBOARD = KEY_PC98; - xrollkey = !xrollkey; - } - else if (!keytype) { - np2oscfg.KEYBOARD = KEY_KEY101; - } - else { - np2oscfg.KEYBOARD = KEY_KEY106; - } - } - winkbd_roll(xrollkey); - winkbd_setf12(np2oscfg.F12COPY); - keystat_initialize(); - - np2class_initialize(hInstance); - kdispwin_initialize(); - skbdwin_initialize(); - mdbgwin_initialize(); - CDebugUtyView::Initialize(hInstance); - - style = WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX; - if (np2oscfg.thickframe) { - style |= WS_THICKFRAME; - } - hWnd = g_hWndMain; - - mousemng_initialize(); - - scrnmng_initialize(); - - if(np2oscfg.dragdrop) - DragAcceptFiles(hWnd, TRUE); // イメージファイルのD&Dに対応(Kai1) - else - DragAcceptFiles(hWnd, FALSE); - - UpdateWindow(hWnd); - -#ifdef OPENING_WAIT - tick = GetTickCount(); -#endif - - HMENU hSysMenu = GetSystemMenu(hWnd, FALSE); - //sysmenu_initialize(hSysMenu); // 対応面倒くさい - - HMENU hMenu = np2class_gethmenu(hWnd); - //xmenu_initialize(hMenu); // 対応面倒くさい - xmenu_update(hMenu); - if (file_attr_c(np2help) == -1) // ver0.30 - { - EnableMenuItem(hMenu, IDM_HELP, MF_GRAYED); - } - DrawMenuBar(hWnd); - - if(np2oscfg.savescrn){ - g_scrnmode = np2oscfg.scrnmode; - }else{ - g_scrnmode = np2oscfg.scrnmode = 0; - } - if (Np2Arg::GetInstance()->fullscreen()) - { - g_scrnmode |= SCRNMODE_FULLSCREEN; - } - if (np2cfg.RASTER) { - g_scrnmode |= SCRNMODE_HIGHCOLOR; - } - if (scrnmng_create(g_scrnmode) != SUCCESS) { - g_scrnmode ^= SCRNMODE_FULLSCREEN; - if (scrnmng_create(g_scrnmode) != SUCCESS) { - messagebox(hWnd, MAKEINTRESOURCE(IDS_ERROR_DIRECTDRAW), MB_OK | MB_ICONSTOP); - UnloadExternalResource(); - TRACETERM(); - dosio_term(); - SendMessage(hWnd, WM_CLOSE, 0, 0L); - return; - } - } - - CSoundMng::Initialize(); - OpenSoundDevice(hWnd); - - if (CSoundMng::GetInstance()->Open(static_cast(np2oscfg.cSoundDeviceType), np2oscfg.szSoundDeviceName, hWnd)) - { - CSoundMng::GetInstance()->LoadPCM(SOUND_PCMSEEK, TEXT("SEEKWAV")); - CSoundMng::GetInstance()->LoadPCM(SOUND_PCMSEEK1, TEXT("SEEK1WAV")); - CSoundMng::GetInstance()->LoadPCM(SOUND_RELAY1, TEXT("RELAY1WAV")); - CSoundMng::GetInstance()->SetPCMVolume(SOUND_PCMSEEK, np2cfg.MOTORVOL); - CSoundMng::GetInstance()->SetPCMVolume(SOUND_PCMSEEK1, np2cfg.MOTORVOL); - CSoundMng::GetInstance()->SetPCMVolume(SOUND_RELAY1, np2cfg.MOTORVOL); - } - - if (np2oscfg.MOUSE_SW) { // ver0.30 - mousemng_enable(MOUSEPROC_SYSTEM); - } - - commng_initialize(); - sysmng_initialize(); - - joymng_initialize(); - pccore_init(); - S98_init(); - -#ifdef OPENING_WAIT - while((GetTickCount() - tick) < OPENING_WAIT); -#endif - -#ifdef SUPPORT_NET - //np2net_init(); -#endif -#ifdef SUPPORT_WAB - //np2wab_init(g_hInstance, g_hWndMain); -#endif -#ifdef SUPPORT_CL_GD5430 - //pc98_cirrus_vga_init(); -#endif - -#ifdef SUPPORT_PHYSICAL_CDDRV - np2updatemenu(); -#endif - - SetTickCounterMode(np2oscfg.tickmode); - pccore_reset(); - np2_SetUserPause(0); - - // スナップ位置の復元のため先に作成 - if (!(g_scrnmode & SCRNMODE_FULLSCREEN)) { - if (np2oscfg.toolwin) { - toolwin_create(); - } - if (np2oscfg.keydisp) { - kdispwin_create(); - } - if (np2oscfg.skbdwin) { - skbdwin_create(); - } - } - - // れじうむ -#if defined(SUPPORT_RESUME) - if (np2oscfg.resume) { - int id; - - id = flagload(hWnd, str_sav, _T("Resume"), FALSE); - if (id == IDYES) - { - Np2Arg::GetInstance()->ClearDisk(); - } - else if (id == IDCANCEL) { - DestroyWindow(hWnd); - mousemng_disable(MOUSEPROC_WINUI); - S98_trash(); - pccore_term(); - CSoundMng::GetInstance()->Close(); - CSoundMng::Deinitialize(); - scrnmng_destroy(); - UnloadExternalResource(); - TRACETERM(); - dosio_term(); - SendMessage(hWnd, WM_CLOSE, 0, 0L); - return; - } - } -#endif - soundmng_setvolume(np2cfg.vol_master); - - // 画面表示倍率を復元 - if(np2oscfg.svscrmul){ - scrnmng_setmultiple(np2oscfg.scrn_mul); - } -// リセットしてから… - // INIに記録されたディスクを挿入 - if(np2cfg.savefddfile){ - for (i = 0; i < 4; i++) - { - LPCTSTR lpDisk = np2cfg.fddfile[i]; - if (lpDisk) - { - diskdrv_readyfdd((REG8)i, lpDisk, 0); - toolwin_setfdd((REG8)i, lpDisk); - } - } - } -#if defined(SUPPORT_IDEIO) - // INIに記録されたCDを挿入 - if (np2cfg.savecdfile) { - for (i = 0; i < 4; i++) - { - if (np2cfg.idetype[i] == IDETYPE_CDROM) { - LPCTSTR lpDisk = np2cfg.idecd[i]; - if (lpDisk) - { - diskdrv_setsxsi(i, lpDisk); - } - } - } - } -#endif - - scrndraw_redraw(); - - np2opening = 0; - - sysmng_workclockreset(); - sysmng_updatecaption(SYS_UPDATECAPTION_ALL); - -#ifdef HOOK_SYSKEY - start_hook_systemkey(); -#endif -} - -#if defined(SUPPORT_MULTITHREAD) -static unsigned int __stdcall np2_multithread_EmulatorThreadMain(LPVOID vdParam){ - while (!np2_multithread_hThread_requestexit) { - if (!np2stopemulate && !np2_multithread_pauseemulation && !np2userpause) { - UINT8 drawskip = (np2oscfg.DRAW_SKIP == 0 ? 1 : np2oscfg.DRAW_SKIP); -#if defined(CPUCORE_IA32) - cpu_drawskip = drawskip; - cpu_nowait = np2oscfg.NOWAIT; -#endif - np2_multithread_pausing = false; - if (np2oscfg.NOWAIT) { - ExecuteOneFrame_MT_EmulateThread(framecnt == 0); - if (drawskip) { // nowait frame skip - framecnt++; - if (framecnt >= drawskip) { - processwait(0); - soundmng_sync(); - } - } - else { // nowait auto skip - framecnt = 1; - if (timing_getcount()) { - processwait(0); - soundmng_sync(); - } - } - } - else if (drawskip) { // frame skip - if (framecnt < drawskip) { - ExecuteOneFrame_MT_EmulateThread(framecnt == 0); - framecnt++; - } - else { - processwait(drawskip); - soundmng_sync(); - } - } - else { // auto skip - if (!waitcnt) { - UINT cnt; - ExecuteOneFrame_MT_EmulateThread(framecnt == 0); - framecnt++; - cnt = timing_getcount(); - if (framecnt > cnt) { - waitcnt = framecnt; - if (framemax > 1) { - framemax--; - } - } - else if (framecnt >= framemax) { - if (framemax < 12) { - framemax++; - } - if (cnt >= 12) { - timing_reset(); - } - else { - timing_setcount(cnt - framecnt); - } - framereset_MT_EmulateThread(0); - } - } - else { - processwait(waitcnt); - soundmng_sync(); - waitcnt = framecnt; - } - } - if(autokey_sendbufferlen > 0) - autoSendKey(); // 自動キー送信 - - scrnmng_delaychangemode(); - } - else if (np2_multithread_pauseemulation == 1) { - np2_multithread_pausing = true; - Sleep(100); - } - else if (np2stopemulate == 1 || np2userpause) { // background sleep - np2_multithread_pausing = false; - Sleep(100); - }else{ - np2_multithread_pausing = false; - } - } - return 0; -} -void np2_multithread_StartThread(){ - if(np2_multithread_initialized){ - unsigned int dwID; - np2_multithread_hThread_requestexit = FALSE; - np2_multithread_hThread = (HANDLE)_beginthreadex(NULL, 0, np2_multithread_EmulatorThreadMain, NULL, 0, &dwID); - SetThreadPriority(np2_multithread_hThread, THREAD_PRIORITY_ABOVE_NORMAL); - } -} -#endif - -int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, - LPSTR lpszCmdLine, int nCmdShow) { - WNDCLASS wc; - MSG msg; - HWND hWnd; - UINT i; - DWORD style; -#ifdef OPENING_WAIT - UINT32 tick; -#endif - BOOL xrollkey; - int winx, winy; - -#ifdef _DEBUG - // 使うときはstdlib.hとcrtdbg.hをインクルードする - _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); - //_CrtSetBreakAlloc(499); -#endif - -#if defined(SUPPORT_WIN2000HOST) -#ifdef _WINDOWS -#ifndef _WIN64 -#define WINVER2 0x0500 - initialize_findacx(); -#endif -#endif -#endif - - winloc_InitDwmFunc(); - - WM_QueryCancelAutoPlay = RegisterWindowMessage(_T("QueryCancelAutoPlay")); - - createAsciiTo98KeyCodeList(); - - _MEM_INIT(); - CWndProc::Initialize(hInstance); - CSubWndBase::Initialize(hInstance); -#if defined(SUPPORT_VSTi) - CVstEditWnd::Initialize(hInstance); -#endif // defined(SUPPORT_VSTi) - - GetModuleFileName(NULL, modulefile, NELEMENTS(modulefile)); - dosio_init(); - file_setcd(modulefile); - Np2Arg::GetInstance()->Parse(); - initload(); - toolwin_readini(); - kdispwin_readini(); - skbdwin_readini(); - mdbgwin_readini(); -#if defined(SUPPORT_WAB) - wabwin_readini(); - np2wabcfg.readonly = np2oscfg.readonly; -#endif // defined(SUPPORT_WAB) -#if defined(SUPPORT_HOSTDRV) - hostdrv_readini(); -#endif // defined(SUPPORT_HOSTDRV) - -#if defined(SUPPORT_MULTITHREAD) - np2_multithread_enable = np2oscfg.multithread; - np2_multithread_Initialize(); -#endif - - rand_setseed((unsigned)time(NULL)); - - szClassName[0] = (TCHAR)np2oscfg.winid[0]; - szClassName[1] = (TCHAR)np2oscfg.winid[1]; - szClassName[2] = (TCHAR)np2oscfg.winid[2]; - -#ifndef ALLOW_MULTIRUN - if ((hWnd = FindWindow(szClassName, NULL)) != NULL) { - sstpmsg_running(); - ShowWindow(hWnd, SW_RESTORE); - SetForegroundWindow(hWnd); - dosio_term(); - return(FALSE); - } -#else - if ((hWnd = FindWindow(szClassName, NULL)) != NULL && np2oscfg.resume) { - // レジュームの時は複数起動するとやばいので・・・ - ShowWindow(hWnd, SW_RESTORE); - SetForegroundWindow(hWnd); - dosio_term(); - return(FALSE); - } -#endif - - g_hInstance = hInstance = LoadExternalResource(hInstance); - CWndProc::SetResourceHandle(hInstance); - -#if !defined(_WIN64) - mmxflag = (havemmx())?0:MMXFLAG_NOTSUPPORT; - mmxflag += (np2oscfg.disablemmx)?MMXFLAG_DISABLE:0; -#endif - TRACEINIT(); - - xrollkey = (np2oscfg.xrollkey == 0); - if (np2oscfg.KEYBOARD >= KEY_TYPEMAX) { - int keytype = GetKeyboardType(1); - if ((keytype & 0xff00) == 0x0d00) { - np2oscfg.KEYBOARD = KEY_PC98; - xrollkey = !xrollkey; - } - else if (!keytype) { - np2oscfg.KEYBOARD = KEY_KEY101; - } - else { - np2oscfg.KEYBOARD = KEY_KEY106; - } - } - winkbd_roll(xrollkey); - winkbd_setf12(np2oscfg.F12COPY); - keystat_initialize(); - - np2class_initialize(hInstance); - if (!hPrevInst) { - if(np2oscfg.mouse_nc/* && !scrnmng_isfullscreen()*/){ - wc.style = CS_BYTEALIGNCLIENT | CS_HREDRAW | CS_VREDRAW; - }else{ - wc.style = CS_BYTEALIGNCLIENT | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; - } - wc.lpfnWndProc = WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = NP2GWLP_SIZE; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); - wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAIN); - wc.lpszClassName = szClassName; - if (!RegisterClass(&wc)) { - UnloadExternalResource(); - TRACETERM(); - dosio_term(); - return(FALSE); - } - - kdispwin_initialize(); - skbdwin_initialize(); - mdbgwin_initialize(); - CDebugUtyView::Initialize(hInstance); - } - - style = WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX; - if (np2oscfg.thickframe) { - style |= WS_THICKFRAME; - } - - winx = np2oscfg.winx; - winy = np2oscfg.winy; - hWnd = CreateWindowEx(0, szClassName, np2oscfg.titles, style, - winx, winy, 640, 400, - NULL, NULL, hInstance, NULL); - g_hWndMain = hWnd; - - //{ - // HMODULE modUsedr32 = LoadLibraryA("User32.dll"); - // if(modUsedr32){ - // BOOL (WINAPI *pfnRegisterTouchWindow)(__in HWND hwnd, __in ULONG ulFlags); - // pfnRegisterTouchWindow = (BOOL (WINAPI *)(__in HWND hwnd, __in ULONG ulFlags))GetProcAddress(modUsedr32, "RegisterTouchWindow"); - // if(pfnRegisterTouchWindow){ - // (*pfnRegisterTouchWindow)(g_hWndMain, 0x00000001); - // } - // FreeLibrary(modUsedr32); - // } - //} - - mousemng_initialize(); // 場所移動 np21w ver0.96 rev13 - - scrnmng_initialize(); - - if(np2oscfg.dragdrop) - DragAcceptFiles(hWnd, TRUE); // イメージファイルのD&Dに対応(Kai1) - - ShowWindow(hWnd, nCmdShow); - UpdateWindow(hWnd); - - SetWindowPos(hWnd, NULL, winx, winy, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED); // Win10環境でウィンドウ位置がずれる問題の対策 - -#ifdef OPENING_WAIT - tick = GetTickCount(); -#endif - - sysmenu_initialize(GetSystemMenu(hWnd, FALSE)); - - HMENU hMenu = np2class_gethmenu(hWnd); - xmenu_initialize(hMenu); - xmenu_update(hMenu); - if (file_attr_c(np2help) == -1) // ver0.30 - { - EnableMenuItem(hMenu, IDM_HELP, MF_GRAYED); - } - DrawMenuBar(hWnd); - - if(np2oscfg.savescrn){ - g_scrnmode = np2oscfg.scrnmode; - }else{ - g_scrnmode = np2oscfg.scrnmode = 0; - } - if (Np2Arg::GetInstance()->fullscreen()) - { - g_scrnmode |= SCRNMODE_FULLSCREEN; - } - if (np2cfg.RASTER) { - g_scrnmode |= SCRNMODE_HIGHCOLOR; - } - if (scrnmng_create(g_scrnmode) != SUCCESS) { - g_scrnmode ^= SCRNMODE_FULLSCREEN; - if (scrnmng_create(g_scrnmode) != SUCCESS) { - if (sstpmsg_dxerror()) - { - messagebox(hWnd, MAKEINTRESOURCE(IDS_ERROR_DIRECTDRAW), MB_OK | MB_ICONSTOP); - } - UnloadExternalResource(); - TRACETERM(); - dosio_term(); - return(FALSE); - } - } - /* - // XXX: Direct3D絡みのエラー対策 - { - MSG msg; - while(PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) - { - if (!GetMessage(&msg, NULL, 0, 0)) { - break; - } - if ((msg.hwnd != hWnd) || - ((msg.message != WM_SYSKEYDOWN) && - (msg.message != WM_SYSKEYUP))) { - TranslateMessage(&msg); - } - DispatchMessage(&msg); - } - }*/ - - CSoundMng::Initialize(); - OpenSoundDevice(hWnd); - - if (CSoundMng::GetInstance()->Open(static_cast(np2oscfg.cSoundDeviceType), np2oscfg.szSoundDeviceName, hWnd)) - { - CSoundMng::GetInstance()->LoadPCM(SOUND_PCMSEEK, TEXT("SEEKWAV")); - CSoundMng::GetInstance()->LoadPCM(SOUND_PCMSEEK1, TEXT("SEEK1WAV")); - CSoundMng::GetInstance()->LoadPCM(SOUND_RELAY1, TEXT("RELAY1WAV")); - CSoundMng::GetInstance()->SetPCMVolume(SOUND_PCMSEEK, np2cfg.MOTORVOL); - CSoundMng::GetInstance()->SetPCMVolume(SOUND_PCMSEEK1, np2cfg.MOTORVOL); - CSoundMng::GetInstance()->SetPCMVolume(SOUND_RELAY1, np2cfg.MOTORVOL); - } - - if (np2oscfg.MOUSE_SW) { // ver0.30 - if(GetForegroundWindow() == hWnd){ - mousemng_enable(MOUSEPROC_SYSTEM); - }else{ - np2oscfg.MOUSE_SW = 0; - } - } - - commng_initialize(); - sysmng_initialize(); - - joymng_initialize(); - pccore_init(); - S98_init(); - - sstpmsg_welcome(); - -#ifdef SUPPORT_NET - np2net_init(); -#endif -#ifdef SUPPORT_WAB - np2wab_init(g_hInstance, g_hWndMain); -#endif -#ifdef SUPPORT_CL_GD5430 - pc98_cirrus_vga_init(); -#endif - -#ifdef SUPPORT_PHYSICAL_CDDRV - np2updatemenu(); -#endif - - SetTickCounterMode(np2oscfg.tickmode); - pccore_reset(); - np2_SetUserPause(0); - - // スナップ位置の復元のため先に作成 - if (!(g_scrnmode & SCRNMODE_FULLSCREEN)) { - if (np2oscfg.toolwin) { - toolwin_create(); - } - if (np2oscfg.keydisp) { - kdispwin_create(); - } - if (np2oscfg.skbdwin) { - skbdwin_create(); - } - } - - // れじうむ -#if defined(SUPPORT_RESUME) - if (np2oscfg.resume) { - int id; - - id = flagload(hWnd, str_sav, _T("Resume"), FALSE); - if (id == IDYES) - { - Np2Arg::GetInstance()->ClearDisk(); - } - else if (id == IDCANCEL) { - DestroyWindow(hWnd); - mousemng_disable(MOUSEPROC_WINUI); - S98_trash(); - pccore_term(); - sstp_destruct(); - CSoundMng::GetInstance()->Close(); - CSoundMng::Deinitialize(); - scrnmng_destroy(); - scrnmng_shutdown(); - UnloadExternalResource(); - TRACETERM(); - dosio_term(); - return(FALSE); - } - } -#endif - soundmng_setvolume(np2cfg.vol_master); - - // 画面表示倍率を復元 - if(np2oscfg.svscrmul){ - scrnmng_setmultiple(np2oscfg.scrn_mul); - } -// リセットしてから… - // INIに記録されたディスクを挿入 - if(np2cfg.savefddfile){ - for (i = 0; i < 4; i++) - { - LPCTSTR lpDisk = np2cfg.fddfile[i]; - if (lpDisk) - { - diskdrv_readyfdd((REG8)i, lpDisk, 0); - toolwin_setfdd((REG8)i, lpDisk); - } - } - } - // コマンドラインのディスク挿入。 - for (i = 0; i < 4; i++) - { - LPCTSTR lpDisk = Np2Arg::GetInstance()->disk(i); - if (lpDisk) - { - diskdrv_readyfdd((REG8)i, lpDisk, 0); - toolwin_setfdd((REG8)i, lpDisk); - } - } - // コマンドラインのディスク挿入。 - for (i = 0; i < 4; i++) - { - LPCTSTR lpDisk = Np2Arg::GetInstance()->disk(i); - if (lpDisk) - { - diskdrv_readyfdd((REG8)i, lpDisk, 0); - } - } -#ifdef SUPPORT_IDEIO - if (Np2Arg::GetInstance()->cdisk(0)) - { - int cdiskidx = 0; - for (i = 0; i < 4; i++) - { - if (np2cfg.idetype[i] == IDETYPE_CDROM) - { - for (; cdiskidx < 4; cdiskidx++) - { - LPCTSTR lpDisk = Np2Arg::GetInstance()->cdisk(cdiskidx); - if (lpDisk) - { - diskdrv_setsxsi(i, NULL); - diskdrv_setsxsi(i, lpDisk); - break; - } - } - } - } - } -#endif - -#ifdef OPENING_WAIT - while((GetTickCount() - tick) < OPENING_WAIT); -#endif - np2opening = 0; - - scrndraw_redraw(); - - sysmng_workclockreset(); - sysmng_updatecaption(SYS_UPDATECAPTION_ALL); - -#ifdef HOOK_SYSKEY - start_hook_systemkey(); -#endif - - timeBeginPeriod(1); - -#if defined(SUPPORT_MULTITHREAD) - if(np2_multithread_enable){ - UINT_PTR tmrID; - const int tmrInterval = 50; - // マルチスレッドモード - framereset = framereset_MT_EmulateThread; - np2_multithread_StartThread(); - tmrID = SetTimer(hWnd, 23545, tmrInterval, NULL); - while(1) { - if (!GetMessage(&msg, NULL, 0, 0)) { - break; - } - if ((msg.hwnd != hWnd) || - ((msg.message != WM_SYSKEYDOWN) && - (msg.message != WM_SYSKEYUP))) { - if(msg.message == WM_TIMER && msg.wParam == tmrID){ - framereset_MT_UIThread(1); -#if defined(SUPPORT_DCLOCK) - DispClock::GetInstance()->Update(); -#endif -#if defined(SUPPORT_VSTi) - CVstEditWnd::OnIdle(); -#endif // defined(SUPPORT_VSTi) - } - TranslateMessage(&msg); - } - DispatchMessage(&msg); - mousemng_UIThreadSync(); - scrnmng_UIThreadProc(); - } - KillTimer(hWnd, tmrID); - }else -#endif - { - lateframecount = 0; - while(1) { - if(g_u8ControlState == 1) { - statsave_save_d(); - } else if(g_u8ControlState == 2) { - statsave_load_d(); - } - g_u8ControlState = 0; - - if (!np2stopemulate && !np2userpause) { - if (PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) { - if (!GetMessage(&msg, NULL, 0, 0)) { - break; - } - if ((msg.hwnd != hWnd) || - ((msg.message != WM_SYSKEYDOWN) && - (msg.message != WM_SYSKEYUP))) { - TranslateMessage(&msg); - } - DispatchMessage(&msg); - } - else { - UINT8 drawskip = (np2oscfg.DRAW_SKIP == 0 ? 1 : np2oscfg.DRAW_SKIP); -#if defined(CPUCORE_IA32) - cpu_drawskip = drawskip; - cpu_nowait = np2oscfg.NOWAIT; -#endif - if (np2oscfg.NOWAIT) { - ExecuteOneFrame(framecnt == 0); - if (drawskip) { // nowait frame skip - framecnt++; - if (framecnt >= drawskip) { - processwait(0); - soundmng_sync(); - } - } - else { // nowait auto skip - framecnt = 1; - if (timing_getcount()) { - processwait(0); - soundmng_sync(); - } - } - } - else if (drawskip) { // frame skip - if (framecnt < drawskip) { - ExecuteOneFrame(framecnt == 0); - framecnt++; - } - else { - processwait(drawskip); - soundmng_sync(); - } - } - else { // auto skip - if (!waitcnt) { - UINT cnt; - ExecuteOneFrame(framecnt == 0); - framecnt++; - cnt = timing_getcount(); - if (framecnt > cnt) { - waitcnt = framecnt; - if (framemax > 1) { - framemax--; - } - } - else if (framecnt >= framemax) { - if (framemax < 12) { - framemax++; - } - if (cnt >= 12) { - timing_reset(); - } - else { - timing_setcount(cnt - framecnt); - } - framereset(0); - } - } - else { - processwait(waitcnt); - soundmng_sync(); - waitcnt = framecnt; - } - } - if(autokey_sendbufferlen > 0) - autoSendKey(); // 自動キー送信 - } - scrnmng_delaychangemode(); - mousemng_UIThreadSync(); - scrnmng_UIThreadProc(); - } - else if ((np2stopemulate == 1 || np2userpause) || // background sleep - (PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE))) { - if(np2stopemulate == 1) { - lateframecount = 0; - timing_setcount(0); - } - if (!GetMessage(&msg, NULL, 0, 0)) { - break; - } - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - } -#if defined(SUPPORT_MULTITHREAD) - np2_multithread_WaitForExitThread(); -#endif - - timeEndPeriod(1); - -#ifdef HOOK_SYSKEY - stop_hook_systemkey(); -#endif - - // 画面表示倍率を保存 - np2oscfg.scrn_mul = scrnmng_getmultiple(); - - toolwin_destroy(); - kdispwin_destroy(); - skbdwin_destroy(); - mdbgwin_destroy(); - - pccore_cfgupdate(); - - mousemng_disable(MOUSEPROC_WINUI); - S98_trash(); - -#if defined(SUPPORT_RESUME) - if (np2oscfg.resume) { - flagsave(str_sav); - } - else { - flagdelete(str_sav); - } -#endif - -#ifdef SUPPORT_CL_GD5430 - pc98_cirrus_vga_shutdown(); -#endif - - pccore_term(); - - sstp_destruct(); - -#ifdef SUPPORT_WAB - np2wab_shutdown(); -#endif -#ifdef SUPPORT_NET - np2net_shutdown(); -#endif - - CSoundMng::GetInstance()->Close(); - CSoundMng::Deinitialize(); - scrnmng_destroy(); - scrnmng_shutdown(); - commng_finalize(); - recvideo_close(); - mousemng_destroy(); - - if (sys_updates & (SYS_UPDATECFG | SYS_UPDATEOSCFG)) { - initsave(); - toolwin_writeini(); - kdispwin_writeini(); - skbdwin_writeini(); - mdbgwin_writeini(); - } -#if defined(SUPPORT_HOSTDRV) - hostdrv_writeini(); -#endif // defined(SUPPORT_HOSTDRV) -#if defined(SUPPORT_WAB) - wabwin_writeini(); -#endif // defined(SUPPORT_WAB) - skbdwin_deinitialize(); - - CSubWndBase::Deinitialize(); - CWndProc::Deinitialize(); - - winloc_DisposeDwmFunc(); - - UnloadExternalResource(); - - TRACETERM(); - _MEM_USED(TEXT("report.txt")); - dosio_term(); - - Np2Arg::Release(); - -#if defined(SUPPORT_MULTITHREAD) - np2_multithread_Finalize(); -#endif - - //_CrtDumpMemoryLeaks(); - - return((int)msg.wParam); -} +/** + * @file np2.cpp + * @brief main window + * + * @author $Author: yui $ + * @date $Date: 2011/02/17 10:36:05 $ + */ + +#include + +// Win2000で動くようにする +#if defined(SUPPORT_WIN2000HOST) +#ifdef _WINDOWS +#ifndef _WIN64 +#define WINVER2 0x0500 +#include "commonfix.h" +#endif +#endif +#endif + +#include +#include +#ifndef __GNUC__ +#include +#endif +#include "resource.h" +#include +#include +#include +#include "np2mt.h" +#include "misc/WndProc.h" +#include "debuguty/viewer.h" +#include "np2arg.h" +#include +#include +#include +#include "misc/tstring.h" +#include +#include "commng/cmmidiin32.h" +#if defined(SUPPORT_VSTi) +#include "commng/vsthost/vsteditwnd.h" +#endif // defined(SUPPORT_VSTi) +#include +#include +#include +#include +#include +#include "winkbd.h" +#include +#include "menu.h" +#include "winloc.h" +#include "sstp.h" +#include "sstpmsg.h" +#include "dialog/np2class.h" +#include "dialog/dialog.h" +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_SMPU98) +#include +#endif +#include +#if defined(SUPPORT_VIDEOFILTER) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SUPPORT_DEBUGSS) +#include +#endif +#include "subwnd/kdispwnd.h" +#include "subwnd/mdbgwnd.h" +#include "subwnd/skbdwnd.h" +#include "subwnd/subwnd.h" +#include "subwnd/toolwnd.h" +#include +#include +#include +#if !defined(_WIN64) +#include "cputype.h" +#endif +#if defined(SUPPORT_DCLOCK) +#include "subwnd/dclock.h" +#endif +#include "recvideo.h" +#if defined(SUPPORT_IDEIO) +#include +#endif +#if defined(SUPPORT_NET) +#include +#endif +#if defined(SUPPORT_WAB) +#include +#include +#endif +#if defined(SUPPORT_CL_GD5430) +#include +#endif +#include +#include +#if defined(SUPPORT_PHYSICAL_CDDRV) +#include "Dbt.h" +#endif + +#if defined(SUPPORT_IA32_HAXM) +#include +#include +#endif + +#include + +#if defined(CPUCORE_IA32) +extern "C" UINT8 cpu_drawskip; +extern "C" UINT8 cpu_nowait; +#if defined(SUPPORT_ASYNC_CPU) +extern "C" double np2cpu_lastTimingValue; +int np2cpu_lastTimingValid = 0; +#endif +#endif +extern bool scrnmng_create_pending; // グラフィックレンダラ生成保留中 + + +#ifdef SUPPORT_WACOM_TABLET +void cmwacom_setNCControl(bool enable); +#endif + +#ifdef BETA_RELEASE +#define OPENING_WAIT 1500 +#endif + +static TCHAR szClassName[] = _T("NP2-MainWindow"); + HWND g_hWndMain; + HINSTANCE g_hInstance; +#if !defined(_WIN64) + int mmxflag; +#endif + UINT8 np2break = 0; // ver0.30 + BOOL winui_en; + UINT8 g_scrnmode; + + NP2OSCFG np2oscfg = { + OEMTEXT(PROJECTNAME) OEMTEXT(PROJECTSUBNAME), + OEMTEXT("NP2"), + CW_USEDEFAULT, CW_USEDEFAULT, 1, 1, 0, 0, 0, 1, 0, 1, + 0, 1, KEY_UNKNOWN, 0, 0, + 0, 0, 0, {1, 2, 2, 1}, {1, 2, 2, 1}, 0, 1, + {5, 0, 0x3e, 19200, + OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, +#if defined(SUPPORT_NAMED_PIPE) + OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), +#endif + }, +#if defined(SUPPORT_SMPU98) + {5, 0, 0x3e, 19200, + OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, +#if defined(SUPPORT_NAMED_PIPE) + OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), +#endif + }, + {5, 0, 0x3e, 19200, + OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, +#if defined(SUPPORT_NAMED_PIPE) + OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), +#endif + }, +#endif + {0, 0, 0x3e, 19200, + OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, +#if defined(SUPPORT_NAMED_PIPE) + OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), +#endif + }, + {0, 0, 0x3e, 19200, + OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, +#if defined(SUPPORT_NAMED_PIPE) + OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), +#endif + }, + {0, 0, 0x3e, 19200, + OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), OEMTEXT(""), 0, 1, +#if defined(SUPPORT_NAMED_PIPE) + OEMTEXT("NP2-NamedPipe"), OEMTEXT("."), +#endif + }, + 0xffffff, 0xffbf6a, 0, 0, + 0, 1, 0, 9801, + 0, 0, +#if !defined(_WIN64) + 0, +#endif + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, FSCRNMOD_SAMEBPP | FSCRNMOD_SAMERES | FSCRNMOD_ASPECTFIX8, 0, + +#if defined(SUPPORT_SCRN_DIRECT3D) + 0, 0, +#endif + + CSoundMng::kDSound3, TEXT(""), + +#if defined(SUPPORT_VSTi) + TEXT("%ProgramFiles%\\Roland\\Sound Canvas VA\\SOUND Canvas VA.dll"), +#endif // defined(SUPPORT_VSTi) + 0, + DRAWTYPE_DIRECTDRAW_HW, + 0, 0, 1, 0, 1, 1, + 0, 0, + 0, 8, + 1, 0, 0, 0, TCMODE_DEFAULT, 0, 100, + 0, +#if defined(SUPPORT_WACOM_TABLET) + 0, +#endif // defined(SUPPORT_WACOM_TABLET) +#if defined(SUPPORT_MULTITHREAD) + 0, +#endif // defined(SUPPORT_MULTITHREAD) + }; + + OEMCHAR fddfolder[MAX_PATH]; + OEMCHAR hddfolder[MAX_PATH]; + OEMCHAR cdfolder[MAX_PATH]; + OEMCHAR bmpfilefolder[MAX_PATH]; + OEMCHAR npcfgfilefolder[MAX_PATH]; + OEMCHAR modulefile[MAX_PATH]; + +static UINT framecnt = 0; +static UINT framecntUI = 0; +static UINT waitcnt = 0; +static UINT framemax = 1; +static UINT8 np2stopemulate = 0; + UINT8 np2userpause = 0; +static int np2opening = 1; +static int np2quitmsg = 0; +static WINLOCEX smwlex; +static HMODULE s_hModResource; +static UINT lateframecount; // フレーム遅れ数 + +static void np2_SetUserPause(UINT8 pause){ + if(np2userpause && !pause){ + CSoundMng::GetInstance()->Enable(SNDPROC_USER); + }else if(!np2userpause && pause){ + CSoundMng::GetInstance()->Disable(SNDPROC_USER); + } + np2userpause = pause; +} + +static void np2_DynamicChangeClockMul(int newClockMul) { + UINT8 oldclockmul = pccore.maxmultiple; + UINT8 oldclockmult = pccore.multiple; + + pccore.multiple = newClockMul; + pccore.maxmultiple = newClockMul; + pccore.realclock = pccore.baseclock * pccore.multiple; + + pcm86_changeclock(oldclockmult); + sound_changeclock(); + beep_changeclock(); + mpu98ii_changeclock(); +#if defined(SUPPORT_SMPU98) + smpu98_changeclock(); +#endif + keyboard_changeclock(); + mouseif_changeclock(); + gdc_updateclock(); +} + +static const OEMCHAR np2help[] = OEMTEXT("np2.chm"); +static const OEMCHAR np2flagext[] = OEMTEXT("S%02d"); +#if defined(_WIN64) +static const OEMCHAR szNp2ResDll[] = OEMTEXT("np2kai_%u_x86_64.dll"); +#else // defined(_WIN64) +static const OEMCHAR szNp2ResDll[] = OEMTEXT("np2kai_%u_i386.dll"); +#endif // defined(_WIN64) + +// ASCII -> 98キーコード表(np21w ver0.86 rev22) +char vkeylist[256] = {0}; +char shift_on[256] = {0}; + +// マルチスレッド用 +#if defined(SUPPORT_MULTITHREAD) +static int np2_multithread_enable = 0; // マルチスレッドモード有効フラグ +static BOOL np2_multithread_initialized = 0; // マルチスレッドモード初期化済みフラグ +static HANDLE np2_multithread_hThread = NULL; // エミュレーション用スレッド +static CRITICAL_SECTION np2_multithread_hThread_cs = {0}; // エミュレーション用スレッド クリティカルセクション +static BOOL np2_multithread_hThread_requestexit = FALSE; // エミュレーション用スレッド 終了要求フラグ +static bool np2_multithread_pauseemulation = false; // エミュレーション一時停止フラグ +static bool np2_multithread_pausing = false; // エミュレーション一時停止中フラグ +static void np2_multithread_Initialize(){ + if(!np2_multithread_initialized){ + InitializeCriticalSection(&np2_multithread_hThread_cs); + np2_multithread_initialized = TRUE; + } +} +static void np2_multithread_fakeWndProc(){ + // グラフィック周りがWndProcが処理される前提になっているので無理やり + MSG msg; + if(PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) + { + if(msg.message != WM_QUIT && msg.message != WM_CLOSE && msg.message != WM_DESTROY){ + GetMessage(&msg, NULL, 0, 0); + if ((msg.hwnd != g_hWndMain) || + ((msg.message != WM_SYSKEYDOWN) && + (msg.message != WM_SYSKEYUP))) { + TranslateMessage(&msg); + } + DispatchMessage(&msg); + } + } +} +void np2_multithread_Suspend(){ + if(!np2_multithread_pauseemulation){ + np2_multithread_pauseemulation = true; + if(np2_multithread_initialized){ + if(np2_multithread_enable && np2_multithread_hThread){ + int workaroundCounter = 0; + Sleep(10); + while(np2_multithread_hThread && !np2_multithread_pausing){ + if(workaroundCounter >= 30){ + np2_multithread_fakeWndProc(); + }else{ + workaroundCounter++; + } + Sleep(10); + } + } + } + } +} +void np2_multithread_Resume(){ + if(np2_multithread_pauseemulation){ + np2_multithread_pauseemulation = false; + if(np2_multithread_initialized){ + if(np2_multithread_enable && np2_multithread_hThread){ + int workaroundCounter = 0; + Sleep(10); + while(np2_multithread_hThread && np2_multithread_pausing){ + if(workaroundCounter >= 30){ + np2_multithread_fakeWndProc(); + }else{ + workaroundCounter++; + } + Sleep(10); + } + } + } + } +} +static void np2_multithread_WaitForExitThread(){ + if(np2_multithread_initialized){ + if(np2_multithread_hThread){ + np2_multithread_Suspend(); + np2_multithread_hThread_requestexit = TRUE; + if(WaitForSingleObject(np2_multithread_hThread, 20000) == WAIT_TIMEOUT){ + TerminateThread(np2_multithread_hThread, 0); + } + CloseHandle(np2_multithread_hThread); + np2_multithread_hThread = NULL; + np2_multithread_pauseemulation = false; + } + } +} +static void np2_multithread_Finalize(){ + if(np2_multithread_initialized){ + np2_multithread_WaitForExitThread(); + DeleteCriticalSection(&np2_multithread_hThread_cs); + np2_multithread_initialized = FALSE; + } +} +void np2_multithread_EnterCriticalSection(){ + if(np2_multithread_initialized && np2_multithread_enable){ + EnterCriticalSection(&np2_multithread_hThread_cs); + } +} +void np2_multithread_LeaveCriticalSection(){ + if(np2_multithread_initialized && np2_multithread_enable){ + LeaveCriticalSection(&np2_multithread_hThread_cs); + } +} +int np2_multithread_Enabled(){ + return np2_multithread_initialized && np2_multithread_enable; +} +#else +void np2_multithread_Suspend(){ + // nothing to do +} +void np2_multithread_Resume(){ + // nothing to do +} +void np2_multithread_EnterCriticalSection(){ + // nothing to do +} +void np2_multithread_LeaveCriticalSection(){ + // nothing to do +} +int np2_multithread_Enabled(){ + return 0; +} +#endif + +// コピペ用(np21w ver0.86 rev22) +char *autokey_sendbuffer = NULL; +int autokey_sendbufferlen = 0; +int autokey_sendbufferpos = 0; +int autokey_lastkanastate = 0; +int autokey_kanjimode = 1; // 0=漢字無視, 1=BASIC, 2=DOS + +// オートラン抑制用 +static int WM_QueryCancelAutoPlay; + +// システムキーフック用 +#ifdef HOOK_SYSKEY +static HANDLE np2_hThreadKeyHook = NULL; // キーフック用スレッド +static int np2_hThreadKeyHookexit = 0; // スレッド終了フラグ +static HWND np2_hThreadKeyHookhWnd = 0; +LRESULT CALLBACK LowLevelKeyboardProc(INT nCode, WPARAM wParam, LPARAM lParam); +HHOOK hHook = NULL; +LRESULT CALLBACK np2_ThreadFuncKeyHook_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ + switch(msg){ + case WM_CLOSE: + if(!np2_hThreadKeyHookexit) return 0; + break; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + return DefWindowProc(hWnd, msg, wParam, lParam); +} +static unsigned int __stdcall np2_ThreadFuncKeyHook(LPVOID vdParam) +{ + MSG msg; + LPCTSTR wndclassname = _T("NP2 Key Hook"); + + WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, np2_ThreadFuncKeyHook_WndProc, 0, 0, g_hInstance, NULL, NULL, (HBRUSH)(COLOR_WINDOW), NULL, wndclassname, NULL}; + + if(!RegisterClassEx(&wcex)) return 0; + + if(!(np2_hThreadKeyHookhWnd = CreateWindow(wndclassname, _T("NP2 Key Hook"), WS_POPUPWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, g_hInstance, NULL))) return 0; + + ShowWindow( np2_hThreadKeyHookhWnd, SW_HIDE ); // 念のため + + if(!hHook){ + hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, g_hInstance, 0); + } + // メイン メッセージ ループ + while( GetMessage(&msg, NULL, 0, 0) > 0 ) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + if(hHook){ + UnhookWindowsHookEx(hHook); + hHook = NULL; + } + np2_hThreadKeyHookhWnd = NULL; + np2_hThreadKeyHook = NULL; + UnregisterClass(wndclassname, g_hInstance); + return 0; +} +static void start_hook_systemkey() +{ + unsigned int dwID; + if(!np2_hThreadKeyHook){ + np2_hThreadKeyHook = (HANDLE)_beginthreadex(NULL, 0, np2_ThreadFuncKeyHook, NULL, 0, &dwID); + } + //if(!hHook){ + // hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, g_hInstance, 0); + //} +} +static void stop_hook_systemkey() +{ + if(np2_hThreadKeyHook && np2_hThreadKeyHookhWnd){ + np2_hThreadKeyHookexit = 1; + SendMessage(np2_hThreadKeyHookhWnd , WM_CLOSE , 0 , 0); + WaitForSingleObject(np2_hThreadKeyHook, INFINITE); + CloseHandle(np2_hThreadKeyHook); + np2_hThreadKeyHook = NULL; + np2_hThreadKeyHookexit = 0; + } + //if(hHook){ + // UnhookWindowsHookEx(hHook); + // hHook = NULL; + //} +} +#endif + +// タイトルバーの音量・マウス速度 自動非表示用 +#define TMRSYSMNG_ID 9898 // 他と被らないようにすること +UINT_PTR tmrSysMngHide = 0; +VOID CALLBACK SysMngHideTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { + sys_miscinfo.showvolume = 0; + sys_miscinfo.showmousespeed = 0; + sysmng_updatecaption(SYS_UPDATECAPTION_MISC); + KillTimer(hwnd , tmrSysMngHide); + tmrSysMngHide = 0; +} + + +// ---- + +static int messagebox(HWND hWnd, LPCTSTR lpcszText, UINT uType) +{ + LPCTSTR szCaption = np2oscfg.titles; + + std::tstring rText(LoadTString(lpcszText)); + return MessageBox(hWnd, rText.c_str(), szCaption, uType); +} + +// ---- + +/** + * リソース DLL をロード + * @param[in] hInstance 元のインスタンス + * @return インスタンス + */ +static HINSTANCE LoadExternalResource(HINSTANCE hInstance) +{ + OEMCHAR szDllName[32]; + OEMSPRINTF(szDllName, szNp2ResDll, GetOEMCP()); + + TCHAR szPath[MAX_PATH]; + file_cpyname(szPath, modulefile, _countof(szPath)); + file_cutname(szPath); + file_catname(szPath, szDllName, _countof(szPath)); + + HMODULE hModule = LoadLibrary(szPath); + s_hModResource = hModule; + if (hModule != NULL) + { + hInstance = static_cast(hModule); + } + return hInstance; +} + +/** + * リソースのアンロード + */ +static void UnloadExternalResource() +{ + HMODULE hModule = s_hModResource; + s_hModResource = NULL; + if (hModule) + { + FreeLibrary(hModule); + } +} + + +// ---- + +static void winuienter(void) { + + winui_en = TRUE; + if(!np2_multithread_Enabled()){ + CSoundMng::GetInstance()->Disable(SNDPROC_MAIN); + } + scrnmng_topwinui(); +} + +static void winuileave(void) { + + scrnmng_clearwinui(); + if(!np2_multithread_Enabled()){ + CSoundMng::GetInstance()->Enable(SNDPROC_MAIN); + } + winui_en = FALSE; +} + +WINLOCEX np2_winlocexallwin(HWND base) { + + UINT i; + UINT cnt; + HWND list[10]; + + cnt = 0; + list[cnt++] = g_hWndMain; + list[cnt++] = toolwin_gethwnd(); + list[cnt++] = kdispwin_gethwnd(); + list[cnt++] = skbdwin_gethwnd(); + list[cnt++] = mdbgwin_gethwnd(); + if(FindWindow(OEMTEXT("Shell_TrayWnd"), NULL)){ + list[cnt++] = FindWindow(OEMTEXT("Shell_TrayWnd"), NULL); + } + for (i=0; i> 3) >= devmode.dmPelsWidth-64 || (DWORD)((scrnstat.height * scrnstat.multiple) >> 3) >= devmode.dmPelsHeight-64){ + scrnstat.multiple--; + if(scrnstat.multiple==1) break; + } + } + } + if (scrnmng_create(newmode) == SUCCESS) { + g_scrnmode = newmode; + if(np2oscfg.scrnmode != g_scrnmode){ + np2oscfg.scrnmode = g_scrnmode; // Screen状態保存 + sysmng_update(SYS_UPDATEOSCFG); + } + } + else { + if (scrnmng_create(g_scrnmode) != SUCCESS) { + scrnmng_create_pending = true; + //PostQuitMessage(0); + np2_multithread_Resume(); + return; + } + } + scrndraw_redraw(); + if (renewal & SCRNMODE_FULLSCREEN) { + if (!scrnmng_isfullscreen()) { + if (np2oscfg.toolwin) { + toolwin_create(); + } + if (np2oscfg.keydisp) { + kdispwin_create(); + } + } + } + else if (renewal & SCRNMODE_ROTATEMASK) { + winlocex_move(wlex); + winlocex_destroy(wlex); + } + mousemng_enable(MOUSEPROC_WINUI); + soundmng_play(); + } + else { + g_scrnmode = newmode; + } + + np2_multithread_LeaveCriticalSection(); + np2_multithread_Resume(); +} + +static void wincentering(HWND hWnd) { + + RECT rc; + int width; + int height; + + GetWindowRect(hWnd, &rc); + width = rc.right - rc.left; + height = rc.bottom - rc.top; + np2oscfg.winx = (GetSystemMetrics(SM_CXSCREEN) - width) / 2; + np2oscfg.winy = (GetSystemMetrics(SM_CYSCREEN) - height) / 2; + if (np2oscfg.winx < 0) { + np2oscfg.winx = 0; + } + if (np2oscfg.winy < 0) { + np2oscfg.winy = 0; + } + sysmng_update(SYS_UPDATEOSCFG); + MoveWindow(g_hWndMain, np2oscfg.winx, np2oscfg.winy, width, height, TRUE); +} + +void np2active_renewal(void) { // ver0.30 + + if (np2break & (~NP2BREAK_MAIN)) { + np2stopemulate = 2; + CSoundMng::GetInstance()->Disable(SNDPROC_MASTER); + } + else if (np2break & NP2BREAK_MAIN) { + if (np2oscfg.background & 1) { + np2stopemulate = 1; + } + else { + np2stopemulate = 0; + } + if (np2oscfg.background) { + CSoundMng::GetInstance()->Disable(SNDPROC_MASTER); + } + else { + CSoundMng::GetInstance()->Enable(SNDPROC_MASTER); + } + } + else { + np2stopemulate = 0; + CSoundMng::GetInstance()->Enable(SNDPROC_MASTER); + } +} + + +// ---- resume and statsave + +#if defined(SUPPORT_RESUME) || defined(SUPPORT_STATSAVE) +static void getstatfilename(OEMCHAR *path, const OEMCHAR *ext, int size) { + + initgetfile(path, size); + //file_cpyname(path, modulefile, size); + file_cutext(path); + file_catname(path, str_dot, size); + file_catname(path, ext, size); +} + +static int flagsave(const OEMCHAR *ext) { + + int ret; + OEMCHAR path[MAX_PATH]; + + np2_multithread_Suspend(); + getstatfilename(path, ext, NELEMENTS(path)); + soundmng_stop(); + ret = statsave_save(path); + if (ret) { + file_delete(path); + } + soundmng_play(); + np2_multithread_Resume(); + return(ret); +} + +static void flagdelete(const OEMCHAR *ext) { + + OEMCHAR path[MAX_PATH]; + + getstatfilename(path, ext, NELEMENTS(path)); + file_delete(path); +} + +static int flagload(HWND hWnd, const OEMCHAR *ext, LPCTSTR title, BOOL force) +{ + int nRet; + int nID; + OEMCHAR szPath[MAX_PATH]; + OEMCHAR szStat[1024]; + TCHAR szMessage[1024 + 256]; + + getstatfilename(szPath, ext, NELEMENTS(szPath)); + np2_multithread_Suspend(); + winuienter(); + nID = IDYES; + nRet = statsave_check(szPath, szStat, NELEMENTS(szStat)); + if (nRet & (~STATFLAG_DISKCHG)) + { + messagebox(hWnd, MAKEINTRESOURCE(IDS_ERROR_RESUME), + MB_OK | MB_ICONSTOP); + nID = IDNO; + } + else if ((!force) && (nRet & STATFLAG_DISKCHG)) + { + std::tstring rFormat(LoadTString(IDS_CONFIRM_RESUME)); + wsprintf(szMessage, rFormat.c_str(), szStat); + nID = messagebox(hWnd, szMessage, MB_YESNOCANCEL | MB_ICONQUESTION); + } + if (nID == IDYES) + { + statsave_load(szPath); + toolwin_setfdd(0, fdd_diskname(0)); + toolwin_setfdd(1, fdd_diskname(1)); + } + sysmng_workclockreset(); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + winuileave(); + np2_multithread_Resume(); + return nID; +} +#endif + +/** + * サウンドデバイスの再オープン + * @param[in] hWnd ウィンドウ ハンドル + */ +static void OpenSoundDevice(HWND hWnd) +{ + CSoundMng* pSoundMng = CSoundMng::GetInstance(); + if (pSoundMng->Open(static_cast(np2oscfg.cSoundDeviceType), np2oscfg.szSoundDeviceName, hWnd)) + { + pSoundMng->LoadPCM(SOUND_PCMSEEK, TEXT("SEEKWAV")); + pSoundMng->LoadPCM(SOUND_PCMSEEK1, TEXT("SEEK1WAV")); + pSoundMng->LoadPCM(SOUND_RELAY1, TEXT("RELAY1WAV")); + pSoundMng->SetPCMVolume(SOUND_PCMSEEK, np2cfg.MOTORVOL); + pSoundMng->SetPCMVolume(SOUND_PCMSEEK1, np2cfg.MOTORVOL); + pSoundMng->SetPCMVolume(SOUND_RELAY1, np2cfg.MOTORVOL); + pSoundMng->SetMasterVolume(np2cfg.vol_master); + } +} + +// ---- proc + +static void np2popup(HWND hWnd, LPARAM lp) { + + HMENU mainmenu; + HMENU hMenu; + HMENU hMenuEdit; + POINT pt; + + mainmenu = (HMENU)GetWindowLongPtr(hWnd, NP2GWLP_HMENU); + hMenu = CreatePopupMenu(); + hMenuEdit = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_COPYPASTEPOPUP)); +#if defined(SUPPORT_WAB) + EnableMenuItem(hMenuEdit, IDM_COPYPASTE_COPYWABMEM, 0); +#endif + menu_addmenubar(hMenu, hMenuEdit); + if (mainmenu) { + InsertMenu(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + menu_addmenubar(hMenu, mainmenu); + } + xmenu_update(hMenu); + pt.x = LOWORD(lp); + pt.y = HIWORD(lp); + ClientToScreen(hWnd, &pt); + TrackPopupMenu(hMenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hWnd, NULL); + DestroyMenu(hMenu); +} + +#ifdef SUPPORT_PHYSICAL_CDDRV +static void np2updatemenu() { + static char drvMenuVisible[4][26] = {0}; // 実ドライブメニューの表示状態 + char drvAvailable[26] = {0}; // 使える実ドライブ + + REG8 drv; + HMENU hMenu = np2class_gethmenu(g_hWndMain); + HMENU hMenuTgt; + int hMenuTgtPos; + MENUITEMINFO mii = {0}; + + DWORD dwDrive; + int nDrive; + TCHAR szBuff2[] = OEMTEXT("A:\\"); + + // 有効なCDドライブのドライブ文字を調べる + dwDrive = GetLogicalDrives(); + for ( nDrive = 0 ; nDrive < 26 ; nDrive++ ){ + if ( dwDrive & (1 << nDrive) ){ + szBuff2[0] = nDrive + 'A'; + if(GetDriveType(szBuff2)==DRIVE_CDROM){ + drvAvailable[nDrive] = 1; + } + } + } + szBuff2[2] = 0; +#if defined(SUPPORT_IDEIO) + for (drv = 0x00; drv < 0x04; drv++) + { + int mnupos = 1; + if(menu_searchmenu(hMenu, IDM_IDE0OPEN+drv, &hMenuTgt, &hMenuTgtPos)){ + // 一旦全部消す + for ( nDrive = 0 ; nDrive < 26 ; nDrive++ ){ + if(drvMenuVisible[drv][nDrive]){ + DeleteMenu(hMenuTgt, IDM_IDE0PHYSICALDRV_ID0 + 26*drv + nDrive, MF_BYCOMMAND); + drvMenuVisible[drv][nDrive] = 0; + } + } + if(np2cfg.idetype[drv]==SXSIDEV_CDROM){ + // 再追加 + for ( nDrive = 0 ; nDrive < 26 ; nDrive++ ){ + if(drvAvailable[nDrive]){ + TCHAR mnuText[200] = {0}; + szBuff2[0] = nDrive + 'A'; + if(!LoadString(g_hInstance, IDS_PHYSICALDRIVE, mnuText, sizeof(mnuText)/sizeof(mnuText[0]) - sizeof(szBuff2)/sizeof(szBuff2[0]))){ + _tcscpy(mnuText, OEMTEXT("&Physical Drive ")); + } + _tcscat(mnuText, szBuff2); + InsertMenu(hMenuTgt, mnupos++, MF_BYPOSITION, IDM_IDE0PHYSICALDRV_ID0 + 26*drv + nDrive, mnuText); + drvMenuVisible[drv][nDrive] = 1; + } + } + } + } + //if(np2cfg.idetype[drv]==SXSIDEV_CDROM) + //{ + // EnableMenuItem(hMenu, IDM_IDE0PHYSICALDRV+drv, MF_BYCOMMAND|MFS_ENABLED); + //} + //else + //{ + // EnableMenuItem(hMenu, IDM_IDE0PHYSICALDRV+drv, MF_BYCOMMAND|MFS_GRAYED); + //} + } +#endif +} +#endif + +static void OnCommand(HWND hWnd, WPARAM wParam) +{ + UINT update; + UINT uID; + BOOL b; + + static UINT16 oldcpustabf = 90; + + update = 0; + uID = LOWORD(wParam); +#if defined(SUPPORT_IDEIO) +#if defined(SUPPORT_PHYSICAL_CDDRV) + if(IDM_IDE0PHYSICALDRV_ID0 <= uID && uID < IDM_IDE0PHYSICALDRV_ID0 + 26*4){ + TCHAR szBuff[] = OEMTEXT("\\\\.\\A:"); + int idedrv = (uID - IDM_IDE0PHYSICALDRV_ID0) / 26; + int drvnum = (uID - IDM_IDE0PHYSICALDRV_ID0) % 26; + szBuff[4] = drvnum + 'A'; + sysmng_update(SYS_UPDATEOSCFG); + diskdrv_setsxsi(idedrv, szBuff); + } +#endif +#endif + switch(uID) + { + case IDM_RESET: + b = FALSE; + if (!np2oscfg.comfirm) + { + b = TRUE; + } + else if (sstpconfirm_reset()) + { + winuienter(); + if (messagebox(hWnd, MAKEINTRESOURCE(IDS_CONFIRM_RESET), MB_ICONQUESTION | MB_YESNO) == IDYES) + { + b = TRUE; + } + winuileave(); + } + if (b) + { + if (sys_updates & SYS_UPDATESNDDEV) + { + sys_updates &= ~SYS_UPDATESNDDEV; + OpenSoundDevice(hWnd); + } +#ifdef HOOK_SYSKEY + stop_hook_systemkey(); +#endif + np2_multithread_Suspend(); + sstpmsg_reset(); + pccore_cfgupdate(); + if(nevent_iswork(NEVENT_CDWAIT)){ + nevent_forceexecute(NEVENT_CDWAIT); + } + pccore_reset(); + np2_SetUserPause(0); + np2_multithread_Resume(); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); +#ifdef SUPPORT_PHYSICAL_CDDRV + np2updatemenu(); +#endif +#ifdef HOOK_SYSKEY + start_hook_systemkey(); +#endif + } + break; + case IDM_PAUSE: + np2_SetUserPause(!np2userpause); + update |= SYS_UPDATECFG; + break; + case IDM_CONFIG: + winuienter(); + sstpmsg_config(); + dialog_configure(hWnd); + if (!scrnmng_isfullscreen()) { + UINT8 thick; + thick = (GetWindowLong(hWnd, GWL_STYLE) & WS_THICKFRAME)?1:0; + if (thick != np2oscfg.thickframe) { + WINLOCEX wlex; + wlex = np2_winlocexallwin(hWnd); + winlocex_setholdwnd(wlex, hWnd); + np2class_frametype(hWnd, np2oscfg.thickframe); + winlocex_move(wlex); + winlocex_destroy(wlex); + } + } + winuileave(); + break; + + case IDM_CHANGECLK_X2: + np2_DynamicChangeClockMul(2); + break; + case IDM_CHANGECLK_X8: + np2_DynamicChangeClockMul(8); + break; + case IDM_CHANGECLK_X16: + np2_DynamicChangeClockMul(16); + break; + case IDM_CHANGECLK_X30: + np2_DynamicChangeClockMul(30); + break; + case IDM_CHANGECLK_X42: + np2_DynamicChangeClockMul(42); + break; + case IDM_CHANGECLK_RESTORE: + np2_DynamicChangeClockMul(np2cfg.multiple); + break; + + case IDM_NEWDISK: + winuienter(); + dialog_newdisk(hWnd); + winuileave(); + break; + + case IDM_NEWDISKFD: + winuienter(); + dialog_newdisk_ex(hWnd, NEWDISKMODE_FD); + winuileave(); + break; + + case IDM_NEWDISKHD: + winuienter(); + dialog_newdisk_ex(hWnd, NEWDISKMODE_HD); + winuileave(); + break; + + case IDM_CHANGEFONT: + winuienter(); + dialog_font(hWnd); + winuileave(); + break; + + case IDM_LOADVMCFG: + winuienter(); + dialog_readnpcfg(hWnd); + winuileave(); + + break; + + case IDM_SAVEVMCFG: + winuienter(); + dialog_writenpcfg(hWnd); + winuileave(); + break; + + case IDM_EXIT: + SendMessage(hWnd, WM_CLOSE, 0, 0L); + break; + + case IDM_FDD1OPEN: + winuienter(); + dialog_changefdd(hWnd, 0); + winuileave(); + break; + + case IDM_FDD1EJECT: + diskdrv_setfdd(0, NULL, 0); + toolwin_setfdd(0, NULL); + break; + + case IDM_FDD2OPEN: + winuienter(); + dialog_changefdd(hWnd, 1); + winuileave(); + break; + + case IDM_FDD2EJECT: + diskdrv_setfdd(1, NULL, 0); + toolwin_setfdd(1, NULL); + break; + + case IDM_FDD3OPEN: + winuienter(); + dialog_changefdd(hWnd, 2); + winuileave(); + break; + + case IDM_FDD3EJECT: + diskdrv_setfdd(2, NULL, 0); + toolwin_setfdd(2, NULL); + break; + + case IDM_FDD4OPEN: + winuienter(); + dialog_changefdd(hWnd, 3); + winuileave(); + break; + + case IDM_FDD4EJECT: + diskdrv_setfdd(3, NULL, 0); + toolwin_setfdd(3, NULL); + break; + + case IDM_IDE0OPEN: + winuienter(); + dialog_changehdd(hWnd, 0x00); + winuileave(); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + break; + + case IDM_IDE0EJECT: + diskdrv_setsxsi(0x00, NULL); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + break; + + case IDM_IDE1OPEN: + winuienter(); + dialog_changehdd(hWnd, 0x01); + winuileave(); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + break; + + case IDM_IDE1EJECT: + diskdrv_setsxsi(0x01, NULL); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + break; + +#if defined(SUPPORT_IDEIO) + case IDM_IDE2OPEN: + winuienter(); + dialog_changehdd(hWnd, 0x02); + winuileave(); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + break; + + case IDM_IDE2EJECT: + diskdrv_setsxsi(0x02, NULL); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + break; + + case IDM_IDE3OPEN: + winuienter(); + dialog_changehdd(hWnd, 0x03); + winuileave(); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + break; + + case IDM_IDE3EJECT: + diskdrv_setsxsi(0x03, NULL); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + break; + + case IDM_IDEOPT: + winuienter(); + dialog_ideopt(hWnd); + winuileave(); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + break; +#endif + + case IDM_IDE0STATE: + case IDM_IDE1STATE: + case IDM_IDE2STATE: + case IDM_IDE3STATE: + { + const OEMCHAR *fname; + fname = sxsi_getfilename(uID - IDM_IDE0STATE); + if(!fname || !(*fname)){ +#if defined(SUPPORT_IDEIO) + if(np2cfg.idetype[uID - IDM_IDE0STATE]==SXSIDEV_CDROM){ + fname = np2cfg.idecd[uID - IDM_IDE0STATE]; + }else{ +#endif + fname = diskdrv_getsxsi(uID - IDM_IDE0STATE); +#if defined(SUPPORT_IDEIO) + } +#endif + } + if(_tcsnicmp(fname, OEMTEXT("\\\\.\\"), 4)==0){ + fname += 4; + } + if(fname && *fname){ + TCHAR seltmp[500]; + _tcscpy(seltmp, OEMTEXT("/select,")); + _tcscat(seltmp, fname); + ShellExecute(NULL, NULL, OEMTEXT("explorer.exe"), seltmp, NULL, SW_SHOWNORMAL); + } + } + break; + +#if defined(SUPPORT_SCSI) + case IDM_SCSI0OPEN: + winuienter(); + dialog_changehdd(hWnd, 0x20); + winuileave(); + break; + + case IDM_SCSI0EJECT: + diskdrv_setsxsi(0x20, NULL); + break; + + case IDM_SCSI1OPEN: + winuienter(); + dialog_changehdd(hWnd, 0x21); + winuileave(); + break; + + case IDM_SCSI1EJECT: + diskdrv_setsxsi(0x21, NULL); + break; + + case IDM_SCSI2OPEN: + winuienter(); + dialog_changehdd(hWnd, 0x22); + winuileave(); + break; + + case IDM_SCSI2EJECT: + diskdrv_setsxsi(0x22, NULL); + break; + + case IDM_SCSI3OPEN: + winuienter(); + dialog_changehdd(hWnd, 0x23); + winuileave(); + break; + + case IDM_SCSI3EJECT: + diskdrv_setsxsi(0x23, NULL); + break; + + case IDM_SCSI0STATE: + case IDM_SCSI1STATE: + case IDM_SCSI2STATE: + case IDM_SCSI3STATE: + { + const OEMCHAR *fname; + fname = sxsi_getfilename(uID - IDM_SCSI0STATE + 0x20); + if(!fname || !(*fname)){ + fname = diskdrv_getsxsi(uID - IDM_IDE0STATE + 0x20); + } + if(fname && *fname){ + TCHAR seltmp[500]; + _tcscpy(seltmp, OEMTEXT("/select,")); + _tcscat(seltmp, fname); + ShellExecute(NULL, NULL, OEMTEXT("explorer.exe"), seltmp, NULL, SW_SHOWNORMAL); + } + } + break; +#endif + + case IDM_WINDOW: + changescreen(g_scrnmode & (~SCRNMODE_FULLSCREEN)); + break; + + case IDM_FULLSCREEN: + changescreen(g_scrnmode | SCRNMODE_FULLSCREEN); + break; + + case IDM_ROLNORMAL: + changescreen(g_scrnmode & (~SCRNMODE_ROTATEMASK)); + break; + + case IDM_ROLLEFT: + changescreen((g_scrnmode & (~SCRNMODE_ROTATEMASK)) | SCRNMODE_ROTATELEFT); + break; + + case IDM_ROLRIGHT: + changescreen((g_scrnmode & (~SCRNMODE_ROTATEMASK)) | SCRNMODE_ROTATERIGHT); + break; + + case IDM_DISPSYNC: + np2cfg.DISPSYNC = !np2cfg.DISPSYNC; + update |= SYS_UPDATECFG; + break; + + case IDM_RASTER: + np2cfg.RASTER = !np2cfg.RASTER; + if (np2cfg.RASTER) + { + changescreen(g_scrnmode | SCRNMODE_HIGHCOLOR); + } + else + { + changescreen(g_scrnmode & (~SCRNMODE_HIGHCOLOR)); + } + update |= SYS_UPDATECFG; + break; + + case IDM_NOWAIT: + np2oscfg.NOWAIT = !np2oscfg.NOWAIT; + update |= SYS_UPDATECFG; + break; + + case IDM_CPUSTABILIZER: + if(np2oscfg.cpustabf == 0){ + np2oscfg.cpustabf = oldcpustabf; + }else{ + oldcpustabf = np2oscfg.cpustabf; + np2oscfg.cpustabf = 0; + } + update |= SYS_UPDATECFG; + break; + +#if defined(SUPPORT_ASYNC_CPU) + case IDM_ASYNCCPU: + np2cfg.asynccpu = !np2cfg.asynccpu; + update |= SYS_UPDATECFG; + break; +#endif + + case IDM_AUTOFPS: + np2oscfg.DRAW_SKIP = 0; + update |= SYS_UPDATECFG; + break; + + case IDM_60FPS: + np2oscfg.DRAW_SKIP = 1; + update |= SYS_UPDATECFG; + break; + + case IDM_30FPS: + np2oscfg.DRAW_SKIP = 2; + update |= SYS_UPDATECFG; + break; + + case IDM_20FPS: + np2oscfg.DRAW_SKIP = 3; + update |= SYS_UPDATECFG; + break; + + case IDM_15FPS: + np2oscfg.DRAW_SKIP = 4; + update |= SYS_UPDATECFG; + break; + +#if defined(SUPPORT_VIDEOFILTER) + case IDM_VF1EN: + np2cfg.vf1_enable ^= 1; + VideoFilter_SetEnable(hVFMng1, np2cfg.vf1_enable); + update |= SYS_UPDATECFG; + break; + + case IDM_VF1P0: + np2cfg.vf1_pno = 0; + VideoFilter_SetProfileNo(hVFMng1, 0); + update |= SYS_UPDATECFG; + break; + + case IDM_VF1P1: + np2cfg.vf1_pno = 1; + VideoFilter_SetProfileNo(hVFMng1, 1); + update |= SYS_UPDATECFG; + break; + + case IDM_VF1P2: + np2cfg.vf1_pno = 2; + VideoFilter_SetProfileNo(hVFMng1, 2); + update |= SYS_UPDATECFG; + break; + + case IDM_VF1BO: + np2cfg.vf1_bmponly ^= 1; + update |= SYS_UPDATECFG; + break; +#endif + + case IDM_SCREENOPT: + winuienter(); + dialog_scropt(hWnd); + winuileave(); + break; + + case IDM_KEY: + np2cfg.KEY_MODE = 0; + keystat_resetjoykey(); + update |= SYS_UPDATECFG; + break; + + case IDM_JOY1: + np2cfg.KEY_MODE = 1; + keystat_resetjoykey(); + update |= SYS_UPDATECFG; + break; + + case IDM_JOY2: + np2cfg.KEY_MODE = 2; + keystat_resetjoykey(); + update |= SYS_UPDATECFG; + break; + + case IDM_XSHIFT: + np2cfg.XSHIFT ^= 1; + keystat_forcerelease(0x70); + update |= SYS_UPDATECFG; + break; + + case IDM_XCTRL: + np2cfg.XSHIFT ^= 2; + keystat_forcerelease(0x74); + update |= SYS_UPDATECFG; + break; + + case IDM_XGRPH: + np2cfg.XSHIFT ^= 4; + keystat_forcerelease(0x73); + update |= SYS_UPDATECFG; + break; + + case IDM_SENDCAD: + keystat_senddata(0x73); + keystat_senddata(0x74); + keystat_senddata(0x39); + keystat_senddata(0x73 | 0x80); + keystat_senddata(0x74 | 0x80); + keystat_senddata(0x39 | 0x80); + break; + + case IDM_USENUMLOCK: + np2oscfg.USENUMLOCK = !np2oscfg.USENUMLOCK; + update |= SYS_UPDATEOSCFG; + break; + + case IDM_SWAPPAGEUPDOWN: + np2oscfg.xrollkey = !np2oscfg.xrollkey; + winkbd_roll(np2oscfg.KEYBOARD==KEY_PC98 ? np2oscfg.xrollkey : !np2oscfg.xrollkey); + update |= SYS_UPDATEOSCFG; + break; + + case IDM_F12MOUSE: + np2oscfg.F12COPY = 0; + winkbd_resetf12(); + winkbd_setf12(0); + update |= SYS_UPDATEOSCFG; + break; + + case IDM_F12COPY: + np2oscfg.F12COPY = 1; + winkbd_resetf12(); + winkbd_setf12(1); + update |= SYS_UPDATEOSCFG; + break; + + case IDM_F12STOP: + np2oscfg.F12COPY = 2; + winkbd_resetf12(); + winkbd_setf12(2); + update |= SYS_UPDATEOSCFG; + break; + + case IDM_F12EQU: + np2oscfg.F12COPY = 3; + winkbd_resetf12(); + winkbd_setf12(3); + update |= SYS_UPDATEOSCFG; + break; + + case IDM_F12COMMA: + np2oscfg.F12COPY = 4; + winkbd_resetf12(); + winkbd_setf12(4); + update |= SYS_UPDATEOSCFG; + break; + + case IDM_USERKEY1: + np2oscfg.F12COPY = 5; + winkbd_resetf12(); + winkbd_setf12(5); + update |= SYS_UPDATEOSCFG; + break; + + case IDM_USERKEY2: + np2oscfg.F12COPY = 6; + winkbd_resetf12(); + winkbd_setf12(6); + update |= SYS_UPDATEOSCFG; + break; + + case IDM_F12NOWAIT: + np2oscfg.F12COPY = 7; + winkbd_resetf12(); + winkbd_setf12(7); + update |= SYS_UPDATEOSCFG; + break; + + case IDM_F12NOWAIT2: + np2oscfg.F12COPY = 8; + winkbd_resetf12(); + winkbd_setf12(8); + update |= SYS_UPDATEOSCFG; + break; + + case IDM_F12WABRELAY: + np2oscfg.F12COPY = 9; + winkbd_resetf12(); + winkbd_setf12(9); + update |= SYS_UPDATEOSCFG; + break; + + case IDM_BEEPOFF: + np2cfg.BEEP_VOL = 0; + beep_setvol(0); + update |= SYS_UPDATECFG; + break; + + case IDM_BEEPLOW: + np2cfg.BEEP_VOL = 1; + beep_setvol(1); + update |= SYS_UPDATECFG; + break; + + case IDM_BEEPMID: + np2cfg.BEEP_VOL = 2; + beep_setvol(2); + update |= SYS_UPDATECFG; + break; + + case IDM_BEEPHIGH: + np2cfg.BEEP_VOL = 3; + beep_setvol(3); + update |= SYS_UPDATECFG; + break; + + case IDM_NOSOUND: + np2cfg.SOUND_SW = 0x00; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_14: + np2cfg.SOUND_SW = 0x01; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_26K: + np2cfg.SOUND_SW = 0x02; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_86: + np2cfg.SOUND_SW = 0x04; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_26_86: + np2cfg.SOUND_SW = 0x06; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_86_CB: + np2cfg.SOUND_SW = 0x14; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_118: + np2cfg.SOUND_SW = 0x08; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_86_WSS: + np2cfg.SOUND_SW = SOUNDID_PC_9801_86_WSS; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_86_118: + np2cfg.SOUND_SW = SOUNDID_PC_9801_86_118; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_MATE_X_PCM: + np2cfg.SOUND_SW = SOUNDID_MATE_X_PCM; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_SPEAKBOARD: + np2cfg.SOUND_SW = SOUNDID_SPEAKBOARD; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_86SPEAKBOARD: + np2cfg.SOUND_SW = SOUNDID_86_SPEAKBOARD; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_SPARKBOARD: + np2cfg.SOUND_SW = 0x40; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + +#if defined(SUPPORT_SOUND_SB16) + case IDM_SB16: + np2cfg.SOUND_SW = SOUNDID_SB16; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_86_SB16: + np2cfg.SOUND_SW = SOUNDID_PC_9801_86_SB16; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_WSS_SB16: + np2cfg.SOUND_SW = SOUNDID_WSS_SB16; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_86_WSS_SB16: + np2cfg.SOUND_SW = SOUNDID_PC_9801_86_WSS_SB16; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_118_SB16: + np2cfg.SOUND_SW = SOUNDID_PC_9801_118_SB16; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PC9801_86_118_SB16: + np2cfg.SOUND_SW = SOUNDID_PC_9801_86_118_SB16; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; +#endif // defined(SUPPORT_SOUND_SB16) + +#if defined(SUPPORT_PX) + case IDM_PX1: + np2cfg.SOUND_SW = 0x30; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_PX2: + np2cfg.SOUND_SW = 0x50; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; +#endif // defined(SUPPORT_PX) + + case IDM_SOUNDORCHESTRA: + np2cfg.SOUND_SW = 0x32; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_SOUNDORCHESTRAV: + np2cfg.SOUND_SW = 0x82; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_LITTLEORCHESTRAL: + np2cfg.SOUND_SW = SOUNDID_LITTLEORCHESTRAL; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_AMD98: + np2cfg.SOUND_SW = 0x80; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_WAVESTAR: + np2cfg.SOUND_SW = SOUNDID_WAVESTAR; + update |= SYS_UPDATECFG | SYS_UPDATESBOARD; + break; + + case IDM_JASTSOUND: + np2oscfg.jastsnd = !np2oscfg.jastsnd; + update |= SYS_UPDATEOSCFG; + break; + + case IDM_SEEKSND: + np2cfg.MOTOR = !np2cfg.MOTOR; + update |= SYS_UPDATECFG; + break; + + case IDM_MEM640: + np2cfg.EXTMEM = 0; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + + case IDM_MEM16: + np2cfg.EXTMEM = 1; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + + case IDM_MEM36: + np2cfg.EXTMEM = 3; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + + case IDM_MEM76: + np2cfg.EXTMEM = 7; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + + case IDM_MEM116: + np2cfg.EXTMEM = 11; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + + case IDM_MEM136: + np2cfg.EXTMEM = 13; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + + case IDM_MEM166: + np2cfg.EXTMEM = 16; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + + case IDM_MEM326: + np2cfg.EXTMEM = 32; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + + case IDM_MEM646: + np2cfg.EXTMEM = 64; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + + case IDM_MEM1206: + np2cfg.EXTMEM = 120; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + + case IDM_MEM2306: + np2cfg.EXTMEM = 230; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + +#if defined(SUPPORT_LARGE_MEMORY) + case IDM_MEM5126: + np2cfg.EXTMEM = 512; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; + + case IDM_MEM10246: + np2cfg.EXTMEM = 1024; + update |= SYS_UPDATECFG | SYS_UPDATEMEMORY; + break; +#endif + + case IDM_FPU80: + np2cfg.fpu_type = FPU_TYPE_SOFTFLOAT; + update |= SYS_UPDATECFG; + break; + + case IDM_FPU64: + np2cfg.fpu_type = FPU_TYPE_DOSBOX; + update |= SYS_UPDATECFG; + break; + + case IDM_FPU64INT: + np2cfg.fpu_type = FPU_TYPE_DOSBOX2; + update |= SYS_UPDATECFG; + break; + + case IDM_MOUSE: + mousemng_toggle(MOUSEPROC_SYSTEM); + np2oscfg.MOUSE_SW = !np2oscfg.MOUSE_SW; + update |= SYS_UPDATECFG; + break; + + case IDM_MOUSENC: + np2oscfg.mouse_nc = !np2oscfg.mouse_nc; + if(np2oscfg.mouse_nc){ + SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); + if (np2oscfg.wintype != 0) { + // XXX: メニューが出せなくなって詰むのを回避(暫定) + if (!scrnmng_isfullscreen()) { + WINLOCEX wlex; + np2oscfg.wintype = 0; + wlex = np2_winlocexallwin(hWnd); + winlocex_setholdwnd(wlex, hWnd); + np2class_windowtype(hWnd, np2oscfg.wintype); + winlocex_move(wlex); + winlocex_destroy(wlex); + sysmng_update(SYS_UPDATEOSCFG); + } + } + }else{ + SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) | CS_DBLCLKS); + } +#ifdef SUPPORT_WACOM_TABLET + cmwacom_setNCControl(!!np2oscfg.mouse_nc); +#endif + break; + + case IDM_MOUSEWHEELCTL: + np2oscfg.usewheel = !np2oscfg.usewheel; + break; + + case IDM_MOUSERAW: + np2oscfg.rawmouse = !np2oscfg.rawmouse; + mousemng_updateclip(); // キャプチャし直す + break; + + case IDM_MOUSE30X: + np2oscfg.mousemul = 3; + np2oscfg.mousediv = 1; + mousemng_updatespeed(); + break; + + case IDM_MOUSE20X: + np2oscfg.mousemul = 2; + np2oscfg.mousediv = 1; + mousemng_updatespeed(); + break; + + case IDM_MOUSE15X: + np2oscfg.mousemul = 3; + np2oscfg.mousediv = 2; + mousemng_updatespeed(); + break; + + case IDM_MOUSE10X: + np2oscfg.mousemul = 1; + np2oscfg.mousediv = 1; + mousemng_updatespeed(); + break; + + case IDM_MOUSED2X: + np2oscfg.mousemul = 1; + np2oscfg.mousediv = 2; + mousemng_updatespeed(); + break; + + case IDM_MOUSED3X: + np2oscfg.mousemul = 1; + np2oscfg.mousediv = 3; + mousemng_updatespeed(); + break; + + case IDM_MOUSED4X: + np2oscfg.mousemul = 1; + np2oscfg.mousediv = 4; + mousemng_updatespeed(); + break; + + case IDM_SERIAL1: + winuienter(); + dialog_serial(hWnd); + winuileave(); + break; + + case IDM_MPUPC98: + winuienter(); + dialog_mpu98(hWnd); + winuileave(); + break; + + case IDM_MIDIPANIC: + rs232c_midipanic(); + mpu98ii_midipanic(); +#if defined(SUPPORT_SMPU98) + smpu98_midipanic(); +#endif + pc9861k_midipanic(); + break; + + case IDM_SNDOPT: + winuienter(); + dialog_sndopt(hWnd); + winuileave(); + break; + +#if defined(SUPPORT_NET) + case IDM_NETOPT: + winuienter(); + dialog_netopt(hWnd); + winuileave(); + break; +#endif +#if defined(SUPPORT_CL_GD5430) + case IDM_WABOPT: + winuienter(); + dialog_wabopt(hWnd); + winuileave(); + break; +#endif +#if defined(SUPPORT_HOSTDRV) + case IDM_HOSTDRVOPT: + winuienter(); + dialog_hostdrvopt(hWnd); + winuileave(); + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + break; +#endif +#if defined(SUPPORT_PCI) + case IDM_PCIOPT: + winuienter(); + dialog_pciopt(hWnd); + winuileave(); + break; +#endif + + case IDM_BMPSAVE: + winuienter(); + dialog_writebmp(hWnd); + winuileave(); + break; + + case IDM_TXTSAVE: + winuienter(); + dialog_writetxt(hWnd); + winuileave(); + break; + + case IDM_S98LOGGING: + winuienter(); + dialog_soundlog(hWnd); + winuileave(); + break; + + case IDM_CALENDAR: + winuienter(); + dialog_calendar(hWnd); + winuileave(); + break; + + case IDM_ALTENTER: + np2oscfg.shortcut ^= 1; + update |= SYS_UPDATECFG; + break; + + case IDM_ALTF4: + np2oscfg.shortcut ^= 2; + update |= SYS_UPDATECFG; + break; + +#ifdef HOOK_SYSKEY + case IDM_SYSKHOOK: + np2oscfg.syskhook = !np2oscfg.syskhook; + if(np2oscfg.syskhook){ + start_hook_systemkey(); + }else{ + stop_hook_systemkey(); + } + update |= SYS_UPDATECFG; + break; +#endif + + case IDM_DISPCLOCK: + np2oscfg.DISPCLK ^= 1; + update |= SYS_UPDATECFG; + sysmng_workclockrenewal(); + sysmng_updatecaption(SYS_UPDATECAPTION_CLK); + break; + + case IDM_DISPFRAME: + np2oscfg.DISPCLK ^= 2; + update |= SYS_UPDATECFG; + sysmng_workclockrenewal(); + sysmng_updatecaption(SYS_UPDATECAPTION_CLK); + break; + + case IDM_JOYX: + np2cfg.BTN_MODE = !np2cfg.BTN_MODE; + update |= SYS_UPDATECFG; + break; + + case IDM_RAPID: + np2cfg.BTN_RAPID = !np2cfg.BTN_RAPID; + update |= SYS_UPDATECFG; + break; + + case IDM_MSRAPID: + np2cfg.MOUSERAPID = !np2cfg.MOUSERAPID; + update |= SYS_UPDATECFG; + break; + + case IDM_SSTP: + np2oscfg.sstp = !np2oscfg.sstp; + update |= SYS_UPDATEOSCFG; + break; + + case IDM_CPUSAVE: + debugsub_status(); + break; + + case IDM_HELP: + ShellExecute(hWnd, NULL, file_getcd(np2help), NULL, NULL, SW_SHOWNORMAL); + break; + + case IDM_ABOUT: + np2_multithread_Suspend(); + sstpmsg_about(); + if (sstp_result() != SSTP_SENDING) { + winuienter(); + CSoundMng::GetInstance()->Disable(SNDPROC_MAIN); + dialog_about(hWnd); + CSoundMng::GetInstance()->Enable(SNDPROC_MAIN); + winuileave(); + } + np2_multithread_Resume(); + break; + + case IDM_ITFWORK: + np2cfg.ITF_WORK = !np2cfg.ITF_WORK; + update |= SYS_UPDATECFG; + break; + + case IDM_TIMERFIX: + np2cfg.timerfix= !np2cfg.timerfix; + update |= SYS_UPDATECFG; + break; + + case IDM_SKIP16MEMCHK: + if(np2cfg.memchkmx != 0){ + np2cfg.memchkmx = 0; + }else{ + np2cfg.memchkmx = 15; + } + update |= SYS_UPDATECFG; + break; + + case IDM_FASTMEMCHK: +#if defined(SUPPORT_FAST_MEMORYCHECK) + if(np2cfg.memcheckspeed==1){ + np2cfg.memcheckspeed = 8; + }else{ + np2cfg.memcheckspeed = 1; + } + update |= SYS_UPDATECFG; +#endif + break; + + case IDM_EN_DBSS: + { +#if defined(SUPPORT_DEBUGSS) + HMENU hMenu = np2class_gethmenu(g_hWndMain); + if (np2cfg.debugss == 0) { + np2cfg.debugss = 1; + menu_addmenures(hMenu, GetMenuItemCount(hMenu), IDR_DEBUGSS, FALSE); + } + else { + np2cfg.debugss = 0; + //DeleteMenu(hMenu, IDR_DEBUGSS, MF_BYCOMMAND); + DeleteMenu(hMenu, GetMenuItemCount(hMenu) - 1, MF_BYPOSITION); + } + DrawMenuBar(hWnd); + update |= SYS_UPDATECFG; + break; +#endif + } + + case IDM_RESTOREBORDER: + if(np2oscfg.wintype!=0){ + WINLOCEX wlex; + np2oscfg.wintype = 0; + wlex = np2_winlocexallwin(hWnd); + winlocex_setholdwnd(wlex, hWnd); + np2class_windowtype(hWnd, np2oscfg.wintype); + winlocex_move(wlex); + winlocex_destroy(wlex); + sysmng_update(SYS_UPDATEOSCFG); + } + break; + + case IDM_COPYPASTE_COPYTVRAM: + { + HGLOBAL hMem; + OEMCHAR *lpMem; + hMem = GlobalAlloc(GHND,0x4000); // アトリビュート分小さくなるので0x4000で十分 + lpMem = (OEMCHAR*)GlobalLock(hMem); + dialog_getTVRAM(lpMem); + GlobalUnlock(hMem); + if(OpenClipboard(hWnd)){ + // クリップボード奪取成功 + EmptyClipboard(); + SetClipboardData(CF_TEXT, hMem); + CloseClipboard(); + }else{ + // クリップボード奪取失敗・・・ + GlobalFree(hMem); + } + pcm86_setnextintr(); + } + break; + + case IDM_COPYPASTE_COPYGVRAM: + case IDM_COPYPASTE_COPYWABMEM: +#ifdef SUPPORT_WAB + { + BMPFILE bf; + BMPINFO bi; + UINT8 *lppal; + UINT8 *lppixels; + HDC hDC; + DWORD dwHeaderSize; + BITMAPINFO *lpbinfo; + HBITMAP hBmp; + SCRNSAVE ss = scrnsave_create(); + if(uID == IDM_COPYPASTE_COPYWABMEM){ + np2wab_getbmp(&bf, &bi, &lppal, &lppixels); + }else{ + scrnsave_getbmp(ss, &bf, &bi, &lppal, &lppixels, SCRNSAVE_AUTO); + } + hDC = GetDC(NULL); + dwHeaderSize = LOADINTELDWORD(bf.bfOffBits) - sizeof(BMPFILE); + lpbinfo = (BITMAPINFO*)malloc(dwHeaderSize); + CopyMemory(lpbinfo, &bi, sizeof(BMPINFO)); + if(LOADINTELWORD(bi.biBitCount) <= 8){ + CopyMemory(lpbinfo->bmiColors, lppal, 4 << LOADINTELWORD(bi.biBitCount)); + hBmp = CreateDIBitmap(hDC, &(lpbinfo->bmiHeader), CBM_INIT, lppixels, lpbinfo, DIB_RGB_COLORS); + }else{ + hBmp = CreateDIBitmap(hDC, &(lpbinfo->bmiHeader), CBM_INIT, lppixels, lpbinfo, DIB_RGB_COLORS); + } + ReleaseDC(NULL, hDC); + free(lppal); + free(lppixels); + free(lpbinfo); + if(OpenClipboard(hWnd)){ + // クリップボード奪取成功 + EmptyClipboard(); + SetClipboardData(CF_BITMAP,hBmp); + CloseClipboard(); + }else{ + // クリップボード奪取失敗・・・ + DeleteObject(hBmp); + } + scrnsave_destroy(ss); + } +#endif + break; + + case IDM_COPYPASTE_PASTE: + { + int txtlen; + HGLOBAL hg; + char *strClip; + //char *strText; + if(autokey_sendbuffer==NULL){ + if (OpenClipboard(hWnd)){ + if((hg = GetClipboardData(CF_TEXT))!=NULL) { + txtlen = (int)GlobalSize(hg); + autokey_sendbufferlen = 0; + autokey_sendbuffer = (char*)malloc(txtlen + 10); + memset(autokey_sendbuffer, 0, txtlen + 10); + strClip = (char*)GlobalLock(hg); + strcpy(autokey_sendbuffer , strClip); + GlobalUnlock(hg); + CloseClipboard(); + autokey_lastkanastate = keyctrl.kanaref; + autokey_sendbufferlen = (int)strlen(autokey_sendbuffer); + autokey_sendbufferpos = 0; + keystat_senddata(0x80|0x70); + }else{ + CloseClipboard(); + } + } + }else{ + // 強制終了 + autokey_sendbufferpos = autokey_sendbufferlen; + } + } + break; + + default: +#if defined(SUPPORT_STATSAVE) + if ((uID >= IDM_FLAGSAVE) && (uID < (IDM_FLAGSAVE + SUPPORT_STATSAVE))) + { + OEMCHAR ext[4]; + OEMSPRINTF(ext, np2flagext, uID - IDM_FLAGSAVE); + flagsave(ext); + } + else if ((uID >= IDM_FLAGLOAD) && (uID < (IDM_FLAGLOAD + SUPPORT_STATSAVE))) + { + OEMCHAR ext[4]; + OEMSPRINTF(ext, np2flagext, uID - IDM_FLAGLOAD); + flagload(hWnd, ext, _T("Status Load"), TRUE); + } +#endif +#if defined(SUPPORT_DEBUGSS) + if ((uID >= IDM_DBSSSAVE0) && (uID <= IDM_DBSSSAVE3)) + { + debugsnapshot_save(uID - IDM_DBSSSAVE0); + } + else if ((uID >= IDM_DBSSLOAD0) && (uID <= IDM_DBSSLOAD3)) + { + debugsnapshot_load(uID - IDM_DBSSLOAD0); + } +#endif + break; + } + sysmng_update(update); +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { + + PAINTSTRUCT ps; + RECT rc; + HDC hdc; + BOOL b; + UINT update; + HWND subwin; + WINLOCEX wlex; + + static int lastmx = -1; + static int lastmy = -1; + static int lastbtn = -1; + + switch (msg) { + // イメージファイルのD&Dに対応(Kai1) + case WM_DROPFILES: + np2_multithread_EnterCriticalSection(); + if(np2oscfg.dragdrop){ + int files; // Kai1追加 + OEMCHAR fname[MAX_PATH]; // Kai1追加 + const OEMCHAR *ext; // Kai1追加 + files = DragQueryFile((HDROP)wParam, (UINT)-1, NULL, 0); + REG8 hddrv_IDE = 0x00; + REG8 hddrv_IDECD = 0x00; + REG8 hddrv_SCSI = 0x20; + REG8 fddrv = 0x00; + UINT8 i; + +#if defined(SUPPORT_IDEIO) + while(hddrv_IDE <= 0x03 && np2cfg.idetype[hddrv_IDE]!=0x01) hddrv_IDE++; + while(hddrv_IDECD <= 0x03 && np2cfg.idetype[hddrv_IDECD]!=0x02) hddrv_IDECD++; +#endif // SUPPORT_IDEIO + for (i = 0; i < files; i++) { +#if defined(OSLANG_UTF8) + wchar_t wchr[MAX_PATH]; + DragQueryFileW((HDROP)wParam, i, wchr, NELEMENTS(wchr)); + codecnv_ucs2toutf8(fname, MAX_PATH, (UINT16*)wchr, -1); +#else + DragQueryFile((HDROP)wParam, i, fname, NELEMENTS(fname)); +#endif + ext = file_getext(fname); +#if defined(SUPPORT_IDEIO) + // CDイメージ? + if ((!file_cmpname(ext, OEMTEXT("iso"))) || + (!file_cmpname(ext, OEMTEXT("cue"))) || + (!file_cmpname(ext, OEMTEXT("ccd"))) || + (!file_cmpname(ext, OEMTEXT("cdm"))) || + (!file_cmpname(ext, OEMTEXT("mds"))) || + (!file_cmpname(ext, OEMTEXT("nrg")))) { + diskdrv_setsxsi(hddrv_IDECD, fname); + while(hddrv_IDECD <= 0x03 && np2cfg.idetype[hddrv_IDECD]!=0x02) hddrv_IDECD++; + continue; + } +#endif // SUPPORT_IDEIO + // HDイメージ? + if ((!file_cmpname(ext, str_hdi)) || + (!file_cmpname(ext, str_thd)) || + (!file_cmpname(ext, str_nhd))) { +#if defined(SUPPORT_IDEIO) + if (hddrv_IDE <= 0x03) { + diskdrv_setsxsi(hddrv_IDE, fname); + while(hddrv_IDE <= 0x03 && np2cfg.idetype[hddrv_IDE]!=0x01) hddrv_IDE++; + } +#else + if (hddrv_IDE <= 0x01) { + diskdrv_setsxsi(hddrv_IDE, fname); + hddrv_IDE++; + } +#endif + continue; + } + if (!file_cmpname(ext, str_hdd)) { + if (hddrv_SCSI <= 0x23) { + diskdrv_setsxsi(hddrv_SCSI, fname); + hddrv_SCSI++; + } + continue; + } + // FDイメージ…? + if (fddrv <= 0x02) { + diskdrv_setfdd(fddrv, fname, 0); + sysmng_update(SYS_UPDATEOSCFG); + toolwin_setfdd(fddrv, fname); + fddrv++; + } + } + DragFinish((HDROP)wParam); + if (GetKeyState(VK_SHIFT) & 0x8000) { + // Shiftキーが押下されていればリセット + pccore_cfgupdate(); +#ifdef HOOK_SYSKEY + stop_hook_systemkey(); +#endif + np2_multithread_Suspend(); + if(nevent_iswork(NEVENT_CDWAIT)){ + nevent_forceexecute(NEVENT_CDWAIT); + } + pccore_reset(); + np2_SetUserPause(0); + np2_multithread_Resume(); +#ifdef HOOK_SYSKEY + start_hook_systemkey(); +#endif + } + } + np2_multithread_LeaveCriticalSection(); + break; + + case WM_CREATE: + g_hWndMain = hWnd; + np2class_wmcreate(hWnd); + np2class_windowtype(hWnd, np2oscfg.wintype); + sstp_construct(hWnd); +#ifndef __GNUC__ + WINNLSEnableIME(hWnd, FALSE); +#endif + break; + + case WM_SYSCOMMAND: + update = 0; + switch(wParam) { + case IDM_TOOLWIN: + np2oscfg.toolwin = !np2oscfg.toolwin; + if (np2oscfg.toolwin) { + toolwin_create(); + } + else { + toolwin_destroy(); + } + update |= SYS_UPDATEOSCFG; + break; + +#if defined(SUPPORT_KEYDISP) + case IDM_KEYDISP: + np2oscfg.keydisp = !np2oscfg.keydisp; + if (np2oscfg.keydisp) { + kdispwin_create(); + } + else { + kdispwin_destroy(); + } + update |= SYS_UPDATEOSCFG; + break; +#endif +#if defined(SUPPORT_SOFTKBD) + case IDM_SOFTKBD: + np2oscfg.skbdwin = !np2oscfg.skbdwin; + if (np2oscfg.skbdwin) { + skbdwin_create(); + } + else { + skbdwin_destroy(); + } + update |= SYS_UPDATEOSCFG; + break; +#endif +#if defined(CPUCORE_IA32) && defined(SUPPORT_MEMDBG32) + case IDM_MEMDBG32: + mdbgwin_create(); + break; +#endif + case IDM_SCREENCENTER: + if ((!scrnmng_isfullscreen()) && + (!(GetWindowLong(hWnd, GWL_STYLE) & + (WS_MAXIMIZE | WS_MINIMIZE)))) { + wlex = np2_winlocexallwin(hWnd); + wincentering(hWnd); + winlocex_move(wlex); + winlocex_destroy(wlex); + } + break; + + case IDM_SNAPENABLE: + np2oscfg.WINSNAP = !np2oscfg.WINSNAP; + update |= SYS_UPDATEOSCFG; + break; + + case IDM_BACKGROUND: + np2oscfg.background ^= 1; + update |= SYS_UPDATEOSCFG; + break; + + case IDM_BGSOUND: + np2oscfg.background ^= 2; + update |= SYS_UPDATEOSCFG; + break; + + case IDM_RESTOREBORDER: + if(np2oscfg.wintype!=0){ + WINLOCEX wlex; + np2oscfg.wintype = 0; + wlex = np2_winlocexallwin(hWnd); + winlocex_setholdwnd(wlex, hWnd); + np2class_windowtype(hWnd, np2oscfg.wintype); + winlocex_move(wlex); + winlocex_destroy(wlex); + sysmng_update(SYS_UPDATEOSCFG); + } + break; + + case IDM_MEMORYDUMP: + debugsub_memorydump(); + break; + + case IDM_DEBUGUTY: + CDebugUtyView::New(); + break; + + case IDM_SCRNMUL4: + case IDM_SCRNMUL6: + case IDM_SCRNMUL8: + case IDM_SCRNMUL10: + case IDM_SCRNMUL12: + case IDM_SCRNMUL16: + if ((!scrnmng_isfullscreen()) && + !(GetWindowLong(g_hWndMain, GWL_STYLE) & WS_MINIMIZE)) + { + np2_multithread_EnterCriticalSection(); + scrnmng_setmultiple((int)(wParam - IDM_SCRNMUL)); + np2_multithread_LeaveCriticalSection(); + } + break; + + case SC_MINIMIZE: + wlex = np2_winlocexallwin(hWnd); + winlocex_close(wlex); + winlocex_destroy(wlex); + return(DefWindowProc(hWnd, msg, wParam, lParam)); + + case SC_RESTORE: + subwin = toolwin_gethwnd(); + if (subwin) { + ShowWindow(subwin, SW_SHOWNOACTIVATE); + } + subwin = kdispwin_gethwnd(); + if (subwin) { + ShowWindow(subwin, SW_SHOWNOACTIVATE); + } + subwin = skbdwin_gethwnd(); + if (subwin) { + ShowWindow(subwin, SW_SHOWNOACTIVATE); + } + subwin = mdbgwin_gethwnd(); + if (subwin) { + ShowWindow(subwin, SW_SHOWNOACTIVATE); + } + return(DefWindowProc(hWnd, msg, wParam, lParam)); + + default: + return(DefWindowProc(hWnd, msg, wParam, lParam)); + } + sysmng_update(update); + break; + + case WM_COMMAND: + np2_multithread_EnterCriticalSection(); + OnCommand(hWnd, wParam); + np2_multithread_LeaveCriticalSection(); + break; + + case WM_ACTIVATE: + if (LOWORD(wParam) != WA_INACTIVE) { + np2break &= ~NP2BREAK_MAIN; + scrndraw_redraw(); + if (np2stopemulate || np2userpause) { + scrndraw_draw(1); + } + np2_multithread_EnterCriticalSection(); + keystat_allrelease(); + mousemng_enable(MOUSEPROC_BG); + np2_multithread_LeaveCriticalSection(); + } + else { + np2break |= NP2BREAK_MAIN; + np2_multithread_EnterCriticalSection(); + mousemng_disable(MOUSEPROC_BG); + np2_multithread_LeaveCriticalSection(); + } + np2active_renewal(); + break; + + case WM_PAINT: + hdc = BeginPaint(hWnd, &ps); + if (np2opening) { + RECT rect; + int width; + int height; + HBITMAP hbmp; + BITMAP bmp; + HDC hmdc; + HBRUSH hbrush; + GetClientRect(hWnd, &rect); + width = rect.right - rect.left; + height = rect.bottom - rect.top; + HINSTANCE hInstance = CWndProc::FindResourceHandle(TEXT("NP2BMP"), RT_BITMAP); + hbmp = LoadBitmap(hInstance, TEXT("NP2BMP")); + GetObject(hbmp, sizeof(BITMAP), &bmp); + hbrush = (HBRUSH)SelectObject(hdc, + GetStockObject(BLACK_BRUSH)); + PatBlt(hdc, 0, 0, width, height, PATCOPY); + SelectObject(hdc, hbrush); + hmdc = CreateCompatibleDC(hdc); + SelectObject(hmdc, hbmp); + BitBlt(hdc, (width - bmp.bmWidth) / 2, + (height - bmp.bmHeight) / 2, + bmp.bmWidth, bmp.bmHeight, hmdc, 0, 0, SRCCOPY); + DeleteDC(hmdc); + DeleteObject(hbmp); + } + else { +// scrnmng_update(); + scrndraw_redraw(); + if (np2stopemulate || np2userpause) { + scrndraw_draw(1); + } + } + EndPaint(hWnd, &ps); + break; + + case WM_QUERYNEWPALETTE: + np2_multithread_EnterCriticalSection(); + scrnmng_querypalette(); + np2_multithread_LeaveCriticalSection(); + break; + + case WM_MOVE: + if ((!scrnmng_isfullscreen()) && + (!(GetWindowLong(hWnd, GWL_STYLE) & + (WS_MAXIMIZE | WS_MINIMIZE)))) { + GetWindowRect(hWnd, &rc); + np2oscfg.winx = rc.left; + np2oscfg.winy = rc.top; + sysmng_update(SYS_UPDATEOSCFG); + } + break; + + case WM_SIZE: + np2wab_forceupdate(); + break; + + case WM_ENTERMENULOOP: + if(!np2_multithread_Enabled()) + { + winuienter(); + } + sysmenu_update(GetSystemMenu(hWnd, FALSE)); + xmenu_update(GetMenu(hWnd)); + if (scrnmng_isfullscreen()) { + DrawMenuBar(hWnd); + } + break; + + case WM_EXITMENULOOP: + if(!np2_multithread_Enabled()) + { + winuileave(); + } + break; + + case WM_ENTERSIZEMOVE: + np2_multithread_EnterCriticalSection(); + if(!np2_multithread_Enabled()) + { + CSoundMng::GetInstance()->Disable(SNDPROC_MAIN); + } + mousemng_disable(MOUSEPROC_WINUI); + np2_multithread_LeaveCriticalSection(); + winlocex_destroy(smwlex); + smwlex = np2_winlocexallwin(hWnd); + scrnmng_entersizing(); + break; + + case WM_MOVING: + if (np2oscfg.WINSNAP) { + winlocex_moving(smwlex, (RECT *)lParam); + } + break; + + case WM_SIZING: + scrnmng_sizing((UINT)wParam, (RECT *)lParam); + break; + + case WM_EXITSIZEMOVE: + scrnmng_exitsizing(); + winlocex_move(smwlex); + winlocex_destroy(smwlex); + smwlex = NULL; + np2_multithread_EnterCriticalSection(); + mousemng_enable(MOUSEPROC_WINUI); + if(!np2_multithread_Enabled()) + { + CSoundMng::GetInstance()->Enable(SNDPROC_MAIN); + } + np2_multithread_LeaveCriticalSection(); + break; + + case WM_KEYDOWN: + autokey_sendbufferpos = autokey_sendbufferlen; // コピペ強制終了 np21w ver0.86 rev22 + if (wParam == VK_F11) { + np2class_enablemenu(g_hWndMain, TRUE); + return(DefWindowProc(hWnd, WM_SYSKEYDOWN, VK_F10, lParam)); + } + if ((wParam == VK_F12) && (!np2oscfg.F12COPY)) { + mousemng_toggle(MOUSEPROC_SYSTEM); + np2oscfg.MOUSE_SW = !np2oscfg.MOUSE_SW; + if(!np2oscfg.mouse_nc){ + SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) | CS_DBLCLKS); + }else/* if (!scrnmng_isfullscreen())*/ { + SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); + if (np2oscfg.wintype != 0) { + // XXX: メニューが出せなくなって詰むのを回避(暫定) + if (!scrnmng_isfullscreen()) { + WINLOCEX wlex; + np2oscfg.wintype = 0; + wlex = np2_winlocexallwin(hWnd); + winlocex_setholdwnd(wlex, hWnd); + np2class_windowtype(hWnd, np2oscfg.wintype); + winlocex_move(wlex); + winlocex_destroy(wlex); + sysmng_update(SYS_UPDATEOSCFG); + } + } + } + sysmng_update(SYS_UPDATECFG); + } + else if ((wParam == VK_F12) && (np2oscfg.F12COPY==7)) { + np2oscfg.NOWAIT = 1; + update |= SYS_UPDATECFG; + } + else if ((wParam == VK_F12) && (np2oscfg.F12COPY==8)) { + np2oscfg.NOWAIT = !np2oscfg.NOWAIT; + update |= SYS_UPDATECFG; + } +#if defined(SUPPORT_CL_GD5430) && defined(SUPPORT_WAB) + else if ((wParam == VK_F12) && (np2oscfg.F12COPY==9)) { + np2_multithread_EnterCriticalSection(); + if(np2clvga.enabled && cirrusvga_opaque){ + np2wab_setRelayState(np2wab.relay ? 0 : 1); + } + np2_multithread_LeaveCriticalSection(); + } +#endif +#ifdef HOOK_SYSKEY + else if ((wParam == VK_SNAPSHOT) && (np2oscfg.syskhook)) { + // nothing to do + } +#endif + else { + if (!np2userpause) { + np2_multithread_EnterCriticalSection(); + winkbd_keydown(wParam, lParam); + np2_multithread_LeaveCriticalSection(); + } + } + break; + + case WM_KEYUP: + if (wParam == VK_F11) { + return(DefWindowProc(hWnd, WM_SYSKEYUP, VK_F10, lParam)); + } + if ((wParam == VK_F12) && (np2oscfg.F12COPY==7)) { + np2oscfg.NOWAIT = 0; + update |= SYS_UPDATECFG; + } + else if ((wParam != VK_F12) || (np2oscfg.F12COPY && np2oscfg.F12COPY!=7)) { + if (!np2userpause) { + np2_multithread_EnterCriticalSection(); + winkbd_keyup(wParam, lParam); + np2_multithread_LeaveCriticalSection(); + } + } + break; + + case WM_SYSKEYDOWN: + autokey_sendbufferpos = autokey_sendbufferlen; // コピペ強制終了 np21w ver0.86 rev22 +#ifdef HOOK_SYSKEY + if (GetAsyncKeyState (VK_RMENU) >> ((sizeof(SHORT) * 8) - 1)) { // np21w ver0.86 rev6 +#else + if (lParam & 0x20000000) { // ver0.30 +#endif + if ((np2oscfg.shortcut & 1) && (wParam == VK_RETURN)) { + changescreen(g_scrnmode ^ SCRNMODE_FULLSCREEN); + break; + } + if ((np2oscfg.shortcut & 2) && (wParam == VK_F4)) { + SendMessage(hWnd, WM_CLOSE, 0, 0L); + break; + } + if (np2oscfg.mouse_nc && np2oscfg.wintype != 0) { + // XXX: メニューが出せなくなって詰むのを回避(暫定) + if (!scrnmng_isfullscreen()) { + np2oscfg.wintype = 0; + wlex = np2_winlocexallwin(hWnd); + winlocex_setholdwnd(wlex, hWnd); + np2class_windowtype(hWnd, np2oscfg.wintype); + winlocex_move(wlex); + winlocex_destroy(wlex); + sysmng_update(SYS_UPDATEOSCFG); + break; + } + } + } + if (!np2userpause) { + np2_multithread_EnterCriticalSection(); + winkbd_keydown(wParam, lParam); + np2_multithread_LeaveCriticalSection(); + } + break; + + case WM_SYSKEYUP: + if (!np2userpause) { + np2_multithread_EnterCriticalSection(); + winkbd_keyup(wParam, lParam); + np2_multithread_LeaveCriticalSection(); + } + break; + + case WM_MOUSEMOVE: + np2_multithread_EnterCriticalSection(); + if (scrnmng_isfullscreen()) { + POINT p; + if (GetCursorPos(&p)) { + scrnmng_fullscrnmenu(p.y); + } + } + if(np2oscfg.mouse_nc/* && !scrnmng_isfullscreen()*/){ + static int mousebufX = 0; // マウス移動バッファ(X) + static int mousebufY = 0; // マウス移動バッファ(Y) + int x = LOWORD(lParam); + int y = HIWORD(lParam); + + SINT16 dx, dy; + UINT8 btn; + btn = mousemng_getstat(&dx, &dy, 0); + if(lastmx == -1 || lastmy == -1){ + lastmx = x; + lastmy = y; + } + if((x-lastmx) || (y-lastmy)){ + RECT r; + int mouse_edge_sh_x = 100; + int mouse_edge_sh_y = 100; + int dxmul, dymul; + GetClientRect(hWnd, &r); + mouse_edge_sh_x = (r.right-r.left)/8; + mouse_edge_sh_y = (r.bottom-r.top)/8; + mousebufX += ((x-lastmx)*np2oscfg.mousemul); + mousebufY += ((y-lastmy)*np2oscfg.mousemul); + if(mousebufX >= np2oscfg.mousediv || mousebufX <= -np2oscfg.mousediv){ + dx += (SINT16)(mousebufX / np2oscfg.mousediv); + mousebufX = mousebufX % np2oscfg.mousediv; + } + if(mousebufY >= np2oscfg.mousediv || mousebufY <= -np2oscfg.mousediv){ + dy += (SINT16)(mousebufY / np2oscfg.mousediv); + mousebufY = mousebufY % np2oscfg.mousediv; + } + // XXX: 端実験 +#define MOUSE_EDGE_ACM 4 + if(x 0){ + dxmul = 1+(mouse_edge_sh_x - (r.right-x))*MOUSE_EDGE_ACM/mouse_edge_sh_x; + }else{ + dxmul = 1; + } + if(y 0){ + dymul = 1+(mouse_edge_sh_y - (r.bottom-y))*MOUSE_EDGE_ACM/mouse_edge_sh_y; + }else{ + dymul = 1; + } + dxmul = (int)dx * dxmul; + dymul = (int)dy * dymul; + if(dxmul < -128) dxmul = -128; + if(dxmul > +127) dxmul = +127; + if(dymul < -128) dymul = -128; + if(dymul > +127) dymul = +127; + dx = (SINT16)dxmul; + dy = (SINT16)dymul; + mousemng_setstat(dx, dy, btn); + lastmx = x; + lastmy = y; + } + } + np2_multithread_LeaveCriticalSection(); + break; + + case WM_LBUTTONDOWN: + np2_multithread_EnterCriticalSection(); + autokey_sendbufferpos = autokey_sendbufferlen; // コピペ強制終了 np21w ver0.86 rev22 + if (!mousemng_buttonevent(MOUSEMNG_LEFTDOWN)) { + if (!scrnmng_isfullscreen()) { + if (np2oscfg.wintype == 2) { + np2_multithread_LeaveCriticalSection(); + return(SendMessage(hWnd, WM_NCLBUTTONDOWN, + HTCAPTION, 0L)); + } + } +#if defined(SUPPORT_DCLOCK) + else { + POINT p; + if ((GetCursorPos(&p)) && + (scrnmng_isdispclockclick(&p))) { + np2oscfg.clk_x++; + sysmng_update(SYS_UPDATEOSCFG); + DispClock::GetInstance()->Reset(); + } + } +#endif + np2_multithread_LeaveCriticalSection(); + return(DefWindowProc(hWnd, msg, wParam, lParam)); + } + np2_multithread_LeaveCriticalSection(); + break; + + case WM_LBUTTONUP: + np2_multithread_EnterCriticalSection(); + if (!mousemng_buttonevent(MOUSEMNG_LEFTUP)) { + np2_multithread_LeaveCriticalSection(); + return(DefWindowProc(hWnd, msg, wParam, lParam)); + } + np2_multithread_LeaveCriticalSection(); + break; + + case WM_MBUTTONDOWN: + np2_multithread_EnterCriticalSection(); + autokey_sendbufferpos = autokey_sendbufferlen; // コピペ強制終了 np21w ver0.86 rev22 + mousemng_toggle(MOUSEPROC_SYSTEM); + np2oscfg.MOUSE_SW = !np2oscfg.MOUSE_SW; + sysmng_update(SYS_UPDATECFG); + if (!np2oscfg.MOUSE_SW) { + if(!np2oscfg.mouse_nc){ + SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) | CS_DBLCLKS); + }else/* if (!scrnmng_isfullscreen())*/ { + SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); + if (np2oscfg.wintype != 0) { + // XXX: メニューが出せなくなって詰むのを回避(暫定) + if (!scrnmng_isfullscreen()) { + WINLOCEX wlex; + np2oscfg.wintype = 0; + wlex = np2_winlocexallwin(hWnd); + winlocex_setholdwnd(wlex, hWnd); + np2class_windowtype(hWnd, np2oscfg.wintype); + winlocex_move(wlex); + winlocex_destroy(wlex); + sysmng_update(SYS_UPDATEOSCFG); + } + } + } + }else{ + SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); + } + np2_multithread_LeaveCriticalSection(); + break; + + case WM_RBUTTONDOWN: + np2_multithread_EnterCriticalSection(); + autokey_sendbufferpos = autokey_sendbufferlen; // コピペ強制終了 np21w ver0.86 rev22 + if (!mousemng_buttonevent(MOUSEMNG_RIGHTDOWN)) { + if (!scrnmng_isfullscreen()) { + np2popup(hWnd, lParam); + } +#if defined(SUPPORT_DCLOCK) + else { + POINT p; + if ((GetCursorPos(&p)) && + (scrnmng_isdispclockclick(&p)) && + (np2oscfg.clk_x)) { + np2oscfg.clk_fnt++; + sysmng_update(SYS_UPDATEOSCFG); + DispClock::GetInstance()->Reset(); + } + } +#endif + np2_multithread_LeaveCriticalSection(); + return(DefWindowProc(hWnd, msg, wParam, lParam)); + } + np2_multithread_LeaveCriticalSection(); + break; + + case WM_RBUTTONUP: + np2_multithread_EnterCriticalSection(); + if (!mousemng_buttonevent(MOUSEMNG_RIGHTUP)) { + np2_multithread_LeaveCriticalSection(); + return(DefWindowProc(hWnd, msg, wParam, lParam)); + } + np2_multithread_LeaveCriticalSection(); + break; + + case WM_LBUTTONDBLCLK: + if (!np2oscfg.MOUSE_SW) { + if(!np2oscfg.mouse_nc){ + if (!scrnmng_isfullscreen()) { + np2oscfg.wintype++; + if (np2oscfg.wintype >= 3) { + np2oscfg.wintype = 0; + } + wlex = np2_winlocexallwin(hWnd); + winlocex_setholdwnd(wlex, hWnd); + np2class_windowtype(hWnd, np2oscfg.wintype); + winlocex_move(wlex); + winlocex_destroy(wlex); + sysmng_update(SYS_UPDATEOSCFG); + } + }else if (!scrnmng_isfullscreen()) { + SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); + if (np2oscfg.wintype != 0) { + // XXX: メニューが出せなくなって詰むのを回避(暫定) + if (!scrnmng_isfullscreen()) { + WINLOCEX wlex; + np2oscfg.wintype = 0; + wlex = np2_winlocexallwin(hWnd); + winlocex_setholdwnd(wlex, hWnd); + np2class_windowtype(hWnd, np2oscfg.wintype); + winlocex_move(wlex); + winlocex_destroy(wlex); + sysmng_update(SYS_UPDATEOSCFG); + } + } + } + }else{ + SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); + } + break; + + case WM_RBUTTONDBLCLK: + if (!np2oscfg.MOUSE_SW) { + if(!np2oscfg.mouse_nc){ + }else/* if (!scrnmng_isfullscreen())*/ { + SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); + if (np2oscfg.wintype != 0) { + // XXX: メニューが出せなくなって詰むのを回避(暫定) + if (!scrnmng_isfullscreen()) { + WINLOCEX wlex; + np2oscfg.wintype = 0; + wlex = np2_winlocexallwin(hWnd); + winlocex_setholdwnd(wlex, hWnd); + np2class_windowtype(hWnd, np2oscfg.wintype); + winlocex_move(wlex); + winlocex_destroy(wlex); + sysmng_update(SYS_UPDATEOSCFG); + } + } + } + }else{ + SetClassLong(g_hWndMain, GCL_STYLE, GetClassLong(g_hWndMain, GCL_STYLE) & ~CS_DBLCLKS); + } + break; + + case WM_MOUSEWHEEL: + if(np2oscfg.usewheel){ + if ((wParam & (MK_CONTROL|MK_SHIFT)) == (MK_CONTROL|MK_SHIFT)) { + int mmul = np2oscfg.mousemul; + int mdiv = np2oscfg.mousediv; + // 面倒なので x/2にする + if(mdiv == 1) { + mdiv *= 2; + mmul *= 2; + } + if(GET_WHEEL_DELTA_WPARAM(wParam) > 0){ + if(mdiv <= 2){ + mdiv = 2; + mmul++; + }else{ + mdiv--; + } + }else{ + if(mmul <= 2){ + mmul = 2; + mdiv++; + }else{ + mmul--; + } + } + if(mmul > 8) mmul = 8; + if(mdiv > 8) mdiv = 8; + // 2で割れるなら割っておく + if(mdiv == 2 && mmul%2 == 0) { + mdiv /= 2; + mmul /= 2; + } + np2oscfg.mousemul = mmul; + np2oscfg.mousediv = mdiv; + mousemng_updatespeed(); + sys_miscinfo.showmousespeed = 1; + sysmng_updatecaption(SYS_UPDATECAPTION_MISC); + tmrSysMngHide = SetTimer(hWnd, TMRSYSMNG_ID, 5000, SysMngHideTimerProc); + }else{ + //if(np2oscfg.usemastervolume){ + int cMaster = np2cfg.vol_master; + cMaster += GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA * 2; + if(cMaster < 0) cMaster = 0; + if(cMaster > np2oscfg.mastervolumemax) cMaster = np2oscfg.mastervolumemax; + if (np2cfg.vol_master != cMaster) + { + np2_multithread_EnterCriticalSection(); + np2cfg.vol_master = cMaster; + soundmng_setvolume(cMaster); + fmboard_updatevolume(); + np2_multithread_LeaveCriticalSection(); + } + sys_miscinfo.showvolume = 1; + sysmng_updatecaption(SYS_UPDATECAPTION_MISC); + tmrSysMngHide = SetTimer(hWnd, TMRSYSMNG_ID, 5000, SysMngHideTimerProc); + //} + } + } + break; + +#if defined(SUPPORT_SCRN_DIRECT3D) + case WM_SETFOCUS: + if (scrnmng_isfullscreen() && scrnmng_current_drawtype==DRAWTYPE_DIRECT3D && !np2oscfg.d3d_exclusive && !winui_en) { + ShowWindow( hWnd, SW_RESTORE ); + } + break; + + case WM_KILLFOCUS: + if (scrnmng_isfullscreen() && scrnmng_current_drawtype==DRAWTYPE_DIRECT3D && !np2oscfg.d3d_exclusive && !winui_en) { + ShowWindow( hWnd, SW_MINIMIZE ); + } + break; +#endif + + case WM_CLOSE: + b = FALSE; + if (!np2oscfg.comfirm) { + b = TRUE; + } + else if (sstpconfirm_exit()) + { + winuienter(); + if (messagebox(hWnd, MAKEINTRESOURCE(IDS_CONFIRM_EXIT), + MB_ICONQUESTION | MB_YESNO) == IDYES) + { + b = TRUE; + } + winuileave(); + } + if (b) { + // 初期画面サイズに戻す + np2_multithread_EnterCriticalSection(); + scrnmng_setsize(0, 0, 640, 400); + np2_multithread_LeaveCriticalSection(); + if (np2oscfg.WINSNAP) { + RECT currect; + GetWindowRect(hWnd, &currect); + winlocex_moving(smwlex, &currect); + } + + CDebugUtyView::AllClose(); + CDebugUtyView::DisposeAllClosedWindow(); + DestroyWindow(hWnd); + } + break; + + case WM_DESTROY: + np2class_wmdestroy(hWnd); + PostQuitMessage(0); + break; + + case WM_NP2CMD: + np2_multithread_EnterCriticalSection(); + switch(LOWORD(lParam)) { + case NP2CMD_EXIT: + np2quitmsg = 1; + PostQuitMessage(0); + break; + + case NP2CMD_EXIT2: + np2quitmsg = 2; + PostQuitMessage(0); + break; + + case NP2CMD_RESET: + pccore_cfgupdate(); +#ifdef HOOK_SYSKEY + stop_hook_systemkey(); +#endif + np2_multithread_Suspend(); + if(nevent_iswork(NEVENT_CDWAIT)){ + nevent_forceexecute(NEVENT_CDWAIT); + } + pccore_reset(); + np2_SetUserPause(0); + np2_multithread_Resume(); +#ifdef HOOK_SYSKEY + start_hook_systemkey(); +#endif + break; + } + np2_multithread_LeaveCriticalSection(); + break; + + case WM_SSTP: + switch(LOWORD(lParam)) { + case FD_CONNECT: + if (!HIWORD(lParam)) { + sstp_connect(); + } + break; + case FD_READ: + if (!HIWORD(lParam)) { + sstp_readSocket(); + } + break; + case FD_WRITE: + if (!HIWORD(lParam)) { +// sstp_writeSokect(); + } + break; + case FD_CLOSE: + if (!HIWORD(lParam)) { + sstp_disconnect(); + } + break; + } + break; + + case MM_MIM_DATA: + CComMidiIn32::RecvData(reinterpret_cast(wParam), static_cast(lParam)); + break; + + case MM_MIM_LONGDATA: + CComMidiIn32::RecvExcv(reinterpret_cast(wParam), reinterpret_cast(lParam)); + break; + +#if defined(SUPPORT_IDEIO) +#ifdef SUPPORT_PHYSICAL_CDDRV + case WM_DEVICECHANGE: + { + PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam; + switch(wParam) + { + case DBT_DEVICEARRIVAL: + case DBT_DEVICEREMOVECOMPLETE: + // See if a CD-ROM or DVD was inserted into a drive. + if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME) + { + PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb; + + if (lpdbv -> dbcv_flags & DBTF_MEDIA) + { + int i; + int drvlnum; + int unitmask = lpdbv ->dbcv_unitmask; + OEMCHAR *fname; + OEMCHAR fnamebuf[MAX_PATH]; + OEMCHAR drvstr[] = OEMTEXT("x:"); + for (drvlnum = 0; drvlnum < 26; ++drvlnum) + { + if (unitmask & 0x1) + break; + unitmask = unitmask >> 1; + } + drvstr[0] = 'A' + drvlnum; + np2_multithread_EnterCriticalSection(); + for(i=0;i<4;i++){ + if(sxsi_getdevtype(i)==SXSIDEV_CDROM){ + fname = np2cfg.idecd[i]; + if(_tcsnicmp(fname, OEMTEXT("\\\\.\\"), 4)==0){ + fname += 4; + if(_tcsicmp(fname, drvstr)==0){ + _tcscpy(fnamebuf, np2cfg.idecd[i]); + if(wParam == DBT_DEVICEARRIVAL){ + // CD挿入 + diskdrv_setsxsi(i, fnamebuf); + }else{ + // CD取出 XXX: 中身が空でもマウントは継続 + diskdrv_setsxsi(i, NULL); + _tcscpy(np2cfg.idecd[i], fnamebuf); + } + sysmng_updatecaption(SYS_UPDATECAPTION_FDD); + } + } + } + } + np2_multithread_LeaveCriticalSection(); + } + } + break; + } + } + break; +#endif +#endif + + default: +#ifdef SUPPORT_IDEIO + if(msg == WM_QueryCancelAutoPlay){ + int i; + for(i=0;i<4;i++){ + if(sxsi_getdevtype(i)==SXSIDEV_CDROM){ + if ((np2cfg.idecd[i][0]==_T('\0') || np2cfg.idecd[i][0]==_T('\\')) && np2cfg.idecd[i][1]==_T('\\') && np2cfg.idecd[i][2]==_T('.') && np2cfg.idecd[i][3]==_T('\\')) { + return 1; + } + } + } + } +#endif + + return(DefWindowProc(hWnd, msg, wParam, lParam)); + } + return(0L); +} + +// --- auto sendkey + +static unsigned short sjis_to_jis(unsigned short sjis) +{ + int h = sjis >> 8; + int l = sjis & 0xff; + + if (h <= 0x9f) + { + if (l < 0x9f) + h = (h << 1) - 0xe1; + else + h = (h << 1) - 0xe0; + } + else + { + if (l < 0x9f) + h = (h << 1) - 0x161; + else + h = (h << 1) - 0x160; + } + + if (l < 0x7f) + l -= 0x1f; + else if (l < 0x9f) + l -= 0x20; + else + l -= 0x7e; + return h << 8 | l; +} + +void autoSendKey(){ + static int shift = 0; + static int kanjimode = 0; + static DWORD lastsendtime = 0; + int capslock = 0; + //int i; + DWORD curtime = 0; + + // 送るものなし + if (autokey_sendbufferlen == 0) + { + return; + } + + // 10文字だけ送る(入力速度制御付き) + curtime = GetTickCount(); + if(curtime - lastsendtime > 256/pccore.multiple+8){ + int i; + int maxkey = 1;//((int)pccore.multiple-20)/16; + if(maxkey <= 0) maxkey = 1; + for(i=0;i> 12) & 0xf)]]); + keystat_senddata(0x80 | vkeylist[hexToAsc[((jiscode >> 12) & 0xf)]]); + keystat_senddata(0x00 | vkeylist[hexToAsc[((jiscode >> 8) & 0xf)]]); + keystat_senddata(0x80 | vkeylist[hexToAsc[((jiscode >> 8) & 0xf)]]); + keystat_senddata(0x00 | vkeylist[hexToAsc[((jiscode >> 4) & 0xf)]]); + keystat_senddata(0x80 | vkeylist[hexToAsc[((jiscode >> 4) & 0xf)]]); + keystat_senddata(0x00 | vkeylist[hexToAsc[((jiscode) & 0xf)]]); + keystat_senddata(0x80 | vkeylist[hexToAsc[((jiscode) & 0xf)]]); + if (autokey_kanjimode == 2) + { + // DOSは1文字毎に解除される + kanjimode = 0; + } + i += 16; + } + autokey_sendbufferpos++; + } + else + { + i--; + } + np2_multithread_LeaveCriticalSection(); + } + autokey_sendbufferpos++; + //if (isKanji) + //{ + // // 漢字は慎重に送る + // break; + //} + if (keybrd.buffers > KB_BUF * 3 / 4) + { + // 溢れそうなので一旦逃げる + break; + } + } + } + lastsendtime = curtime; + } + + // 送信完了したら + if(autokey_sendbufferpos >= autokey_sendbufferlen){ + if (kanjimode) + { + keystat_senddata(0x00 | 0x74); + keystat_senddata(0x00 | 0x35); + keystat_senddata(0x80 | 0x35); + keystat_senddata(0x80 | 0x74); + kanjimode = 0; + } + if (autokey_lastkanastate != 0xff && keyctrl.kanaref == 0xff || autokey_lastkanastate == 0xff && keyctrl.kanaref != 0xff) + { + keystat_senddata(0x00 | 0x72); + keystat_senddata(0x80 | 0x72); + } + keystat_senddata(0x80|0x70); + autokey_sendbufferlen = 0; + autokey_sendbufferpos = 0; + _MFREE(autokey_sendbuffer); + autokey_sendbuffer = NULL; + shift = 0; + } +} + +// キーコード表作成 +void createAsciiTo98KeyCodeList(){ + int i; + // キーコード表作成(暫定) + char numkeys[] = {0,'!', '"','#','$','%','&','\'','(',')'}; + for(i='0';i<='9';i++){ + vkeylist[i] = i-'0'; + if(i=='0') vkeylist[i] = 0x0a; + vkeylist[numkeys[i-'0']] = vkeylist[i]; + shift_on[numkeys[i-'0']] = 1; + } + char asckeycode[] = {0x1d,0x2d,0x2b,0x1f,0x12,0x20,0x21,0x22,0x17,0x23,0x24,0x25,0x2f,0x2e,0x18,0x19,0x10,0x13,0x1e,0x14,0x16,0x2c,0x11,0x2a,0x15,0x29}; + for(i='A';i<='Z';i++){ + vkeylist[i] = asckeycode[i-'A']; + shift_on[i] = 1; + vkeylist[i+0x20] = vkeylist[i]; + } + char spkeyascii[] = { '-', '^','\\', '@', '[', ';', ':', ']', ',', '.', '/', '_'}; + char spshascii[] = { '=', '`', '|', '~', '{', '+', '*', '}', '<', '>', '?', '_'}; + char spkeycode[] = {0x0B,0x0C,0x0D,0x1A,0x1B,0x26,0x27,0x28,0x30,0x31,0x32,0x33}; + vkeylist[' '] = 0x34; + vkeylist['\t'] = 0x0f; + vkeylist['\n'] = 0x1c; + for(i=0;i<=sizeof(spkeyascii)/sizeof(spkeyascii[0]);i++){ + vkeylist[spkeyascii[i]] = spkeycode[i]; + vkeylist[ spshascii[i]] = spkeycode[i]; + shift_on[ spshascii[i]] = 1; + } + char kanakeycode[] = { 0x31,0x1b,0x28,0x30,0x32,0x0a,0x03,0x12,0x04,0x05,0x06,0x07,0x08,0x09,0x29,0x0d,0x03,0x12,0x04,0x05,0x06,0x14,0x21,0x22,0x27,0x2d,0x2a,0x1f,0x13,0x19,0x2b,0x10,0x1d,0x29,0x11,0x1e,0x16,0x17,0x01,0x30,0x24,0x20,0x2c,0x02,0x0c,0x0b,0x23,0x2e,0x28,0x32,0x2f,0x07,0x08,0x09,0x18,0x25,0x31,0x26,0x33,0x0a,0x15,0x1a,0x1b }; + for (i = 0xa1; i <= 0xdf; i++) + { + vkeylist[i] = kanakeycode[i - 0xa1]; + if (i <= 0xaf) + { + shift_on[i] = 1; + } + else + { + shift_on[i] = 0; + } + } +} + +#ifdef HOOK_SYSKEY +// システムショートカットキー +LRESULT CALLBACK LowLevelKeyboardProc(INT nCode, WPARAM wParam, LPARAM lParam) +{ + if(np2oscfg.syskhook){ + // By returning a non-zero value from the hook procedure, the + // message does not get passed to the target window + KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam; + BOOL bControlKeyDown = 0; + BOOL bShiftKeyDown = 0; + BOOL bAltKeyDown = 0; + + switch (nCode) + { + case HC_ACTION: + { + if(GetForegroundWindow()==g_hWndMain){ + KBDLLHOOKSTRUCT *kbstruct = (KBDLLHOOKSTRUCT*)lParam; + // Check to see if the CTRL,DHIFT,ALT key is pressed + bControlKeyDown = GetAsyncKeyState (VK_LCONTROL) >> ((sizeof(SHORT) * 8) - 1); + bShiftKeyDown = GetAsyncKeyState (VK_LSHIFT) >> ((sizeof(SHORT) * 8) - 1); + bAltKeyDown = GetAsyncKeyState (VK_LMENU) >> ((sizeof(SHORT) * 8) - 1); + + // Disable CTRL+ESC, ALT+TAB, ALT+ESC + if (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown + || pkbhs->vkCode == VK_TAB && bAltKeyDown + || pkbhs->vkCode == VK_ESCAPE && bAltKeyDown + || pkbhs->vkCode == VK_LWIN + || pkbhs->vkCode == VK_APPS){ + + switch((int)wParam){ + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + //np2_multithread_EnterCriticalSection(); + winkbd_keydown(kbstruct->vkCode, ((kbstruct->flags)<<24)|(kbstruct->scanCode<<16)); + //np2_multithread_LeaveCriticalSection(); + break; + case WM_KEYUP: + case WM_SYSKEYUP: + //np2_multithread_EnterCriticalSection(); + winkbd_keyup(kbstruct->vkCode, ((kbstruct->flags)<<24)|(kbstruct->scanCode<<16)); + //np2_multithread_LeaveCriticalSection(); + break; + } + return 1; + } + if(pkbhs->vkCode == VK_SCROLL && bAltKeyDown && bControlKeyDown){ + // Ctrl+Alt+ScrollLock → Ctrl+Alt+Delete + switch((int)wParam){ + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + //np2_multithread_EnterCriticalSection(); + keystat_keydown(0x39); + //np2_multithread_LeaveCriticalSection(); + break; + case WM_KEYUP: + case WM_SYSKEYUP: + //np2_multithread_EnterCriticalSection(); + keystat_keyup(0x39); + //np2_multithread_LeaveCriticalSection(); + break; + } + return 1; + } +#ifdef HOOK_SYSKEY + else if ((pkbhs->vkCode == VK_SNAPSHOT) && (np2oscfg.syskhook)) { + // PrintScreen -> COPY + switch((int)wParam){ + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + //np2_multithread_EnterCriticalSection(); + keystat_keydown(0x61); + //np2_multithread_LeaveCriticalSection(); + break; + case WM_KEYUP: + case WM_SYSKEYUP: + ////np2_multithread_EnterCriticalSection(); + keystat_keyup(0x61); + //np2_multithread_LeaveCriticalSection(); + break; + } + } +#endif + } + break; + } + + default: + break; + } + } + return CallNextHookEx (hHook, nCode, wParam, lParam); +} +#endif + +/** + * 1フレーム実行 + * @param[in] bDraw 描画フラグ + */ +static void ExecuteOneFrame_MT_EmulateThread(BOOL bDraw) +{ + if (recvideo_isEnabled()) + { + bDraw = TRUE; + } + + pccore_exec(bDraw); + + joymng_sync(); + mousemng_sync(); + recvideo_write(); +} +static void ExecuteOneFrame(BOOL bDraw) +{ + if (recvideo_isEnabled()) + { + bDraw = TRUE; + } + + joymng_sync(); + mousemng_sync(); + pccore_exec(bDraw); + recvideo_write(); +#if defined(SUPPORT_DCLOCK) + DispClock::GetInstance()->Update(); +#endif +#if defined(SUPPORT_VSTi) + CVstEditWnd::OnIdle(); +#endif // defined(SUPPORT_VSTi) +} + +static void framereset_MT_EmulateThread(UINT cnt) { + + framecnt = 0; +} +static void framereset_MT_UIThread(UINT cnt) { + + framecntUI = 0; +#if defined(SUPPORT_DCLOCK) + scrnmng_dispclock(); +#endif + kdispwin_draw((UINT8)cnt); + sysmng_requestupdatecheck(); + skbdwin_process(); + mdbgwin_process(); + toolwin_draw((UINT8)cnt); + CDebugUtyView::AllUpdate(false); + if (np2oscfg.DISPCLK & 3) { + if (sysmng_workclockrenewal()) { + sysmng_updatecaption(SYS_UPDATECAPTION_CLK); + } + } +} +static void framereset_ALL(UINT cnt) { + framereset_MT_EmulateThread(cnt); + framereset_MT_UIThread(cnt); +} + +static void (*framereset)(UINT cnt) = framereset_ALL; + +static void processwait(UINT cnt) { + + static int averageskipcounter = 0; + static int skipnext = 0; + static int incskip = 0; + + UINT count = timing_getcount(); +#if defined(CPUCORE_IA32) +#if defined(SUPPORT_ASYNC_CPU) + if (!np2cpu_lastTimingValid) { + np2cpu_lastTimingValue = timing_getcount_raw(); + np2cpu_lastTimingValid = 1; + } +#endif +#endif + if (count+lateframecount >= cnt) { + lateframecount = lateframecount + count - cnt; +#if defined(SUPPORT_IA32_HAXM) + if (np2hax.enable) { + np2haxcore.hurryup = 0; + lateframecount = 0; + } +#endif + if(lateframecount > np2oscfg.cpustabf) lateframecount = np2oscfg.cpustabf; + timing_setcount(0); + framereset(cnt); + if(skipnext > 0){ + if(averageskipcounter <= 1){ + skipnext = 0; + } + } + incskip = 0; + averageskipcounter = 0; +#if defined(CPUCORE_IA32) +#if defined(SUPPORT_ASYNC_CPU) + np2cpu_lastTimingValid = 0; +#endif +#endif + } + else { + if(lateframecount){ + Sleep(0); + if(skipnext > 0) skipnext--; + }else{ + if(skipnext > 0 && averageskipcounter==0){ + Sleep(skipnext); // 休めるだけ休む + }else{ + Sleep(0); + } + if(averageskipcounter>1){ + if(!incskip && skipnext < 10) skipnext++; + incskip = 1; + } + averageskipcounter++; + } + } +} + +void unloadNP2INI(){ + // 旧INI片付け + + // 画面表示倍率を保存 + np2oscfg.scrn_mul = scrnmng_getmultiple(); + toolwin_destroy(); + kdispwin_destroy(); + skbdwin_destroy(); + mdbgwin_destroy(); + + pccore_cfgupdate(); + + mousemng_disable(MOUSEPROC_WINUI); + S98_trash(); + +#if defined(SUPPORT_RESUME) + if (np2oscfg.resume) { + flagsave(str_sav); + } + else { + flagdelete(str_sav); + } +#endif + + sxsi_alltrash(); + pccore_term(); + + CSoundMng::GetInstance()->Close(); + CSoundMng::Deinitialize(); + scrnmng_destroy(); + recvideo_close(); + + mousemng_destroy(); + + if (sys_updates & (SYS_UPDATECFG | SYS_UPDATEOSCFG)) { + initsave(); + toolwin_writeini(); + kdispwin_writeini(); + skbdwin_writeini(); + mdbgwin_writeini(); + } +#if defined(SUPPORT_HOSTDRV) + hostdrv_writeini(); +#endif // defined(SUPPORT_HOSTDRV) +#if defined(SUPPORT_WAB) + wabwin_writeini(); +#endif // defined(SUPPORT_WAB) + skbdwin_deinitialize(); + + np2opening = 1; + + InvalidateRect( g_hWndMain, NULL, FALSE ); + UpdateWindow( g_hWndMain ); +} +void loadNP2INI(const OEMCHAR *fname){ + HINSTANCE hInstance; + BOOL xrollkey; + //WNDCLASS wc; + HWND hWnd; + DWORD style; + int i; +#ifdef OPENING_WAIT + DWORD tick; +#endif + +#ifdef HOOK_SYSKEY + stop_hook_systemkey(); +#endif + + LPTSTR lpFilenameBuf = (LPTSTR)malloc((_tcslen(fname)+1)*sizeof(TCHAR)); + _tcscpy(lpFilenameBuf, fname); + hInstance = g_hInstance; + + // 新INI読み込み + Np2Arg::GetInstance()->setiniFilename(lpFilenameBuf); + + initload(); + toolwin_readini(); + kdispwin_readini(); + skbdwin_readini(); + mdbgwin_readini(); +#if defined(SUPPORT_WAB) + wabwin_readini(); + np2wabcfg.readonly = np2oscfg.readonly; +#endif // defined(SUPPORT_WAB) +#if defined(SUPPORT_HOSTDRV) + hostdrv_readini(); +#endif // defined(SUPPORT_HOSTDRV) + toolwin_readini(); + + rand_setseed((unsigned)time(NULL)); + + szClassName[0] = (TCHAR)np2oscfg.winid[0]; + szClassName[1] = (TCHAR)np2oscfg.winid[1]; + szClassName[2] = (TCHAR)np2oscfg.winid[2]; + +#if !defined(_WIN64) + mmxflag = (havemmx())?0:MMXFLAG_NOTSUPPORT; + mmxflag += (np2oscfg.disablemmx)?MMXFLAG_DISABLE:0; +#endif + TRACEINIT(); + + xrollkey = (np2oscfg.xrollkey == 0); + if (np2oscfg.KEYBOARD >= KEY_TYPEMAX) { + int keytype = GetKeyboardType(1); + if ((keytype & 0xff00) == 0x0d00) { + np2oscfg.KEYBOARD = KEY_PC98; + xrollkey = !xrollkey; + } + else if (!keytype) { + np2oscfg.KEYBOARD = KEY_KEY101; + } + else { + np2oscfg.KEYBOARD = KEY_KEY106; + } + } + winkbd_roll(xrollkey); + winkbd_setf12(np2oscfg.F12COPY); + keystat_initialize(); + + np2class_initialize(hInstance); + kdispwin_initialize(); + skbdwin_initialize(); + mdbgwin_initialize(); + CDebugUtyView::Initialize(hInstance); + + style = WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX; + if (np2oscfg.thickframe) { + style |= WS_THICKFRAME; + } + hWnd = g_hWndMain; + + mousemng_initialize(); + + scrnmng_initialize(); + + if(np2oscfg.dragdrop) + DragAcceptFiles(hWnd, TRUE); // イメージファイルのD&Dに対応(Kai1) + else + DragAcceptFiles(hWnd, FALSE); + + UpdateWindow(hWnd); + +#ifdef OPENING_WAIT + tick = GetTickCount(); +#endif + + HMENU hSysMenu = GetSystemMenu(hWnd, FALSE); + //sysmenu_initialize(hSysMenu); // 対応面倒くさい + + HMENU hMenu = np2class_gethmenu(hWnd); + //xmenu_initialize(hMenu); // 対応面倒くさい + xmenu_update(hMenu); + if (file_attr_c(np2help) == -1) // ver0.30 + { + EnableMenuItem(hMenu, IDM_HELP, MF_GRAYED); + } + DrawMenuBar(hWnd); + + if(np2oscfg.savescrn){ + g_scrnmode = np2oscfg.scrnmode; + }else{ + g_scrnmode = np2oscfg.scrnmode = 0; + } + if (Np2Arg::GetInstance()->fullscreen()) + { + g_scrnmode |= SCRNMODE_FULLSCREEN; + } + if (np2cfg.RASTER) { + g_scrnmode |= SCRNMODE_HIGHCOLOR; + } + if (scrnmng_create(g_scrnmode) != SUCCESS) { + g_scrnmode ^= SCRNMODE_FULLSCREEN; + if (scrnmng_create(g_scrnmode) != SUCCESS) { + messagebox(hWnd, MAKEINTRESOURCE(IDS_ERROR_DIRECTDRAW), MB_OK | MB_ICONSTOP); + UnloadExternalResource(); + TRACETERM(); + dosio_term(); + SendMessage(hWnd, WM_CLOSE, 0, 0L); + return; + } + } + + CSoundMng::Initialize(); + OpenSoundDevice(hWnd); + + if (CSoundMng::GetInstance()->Open(static_cast(np2oscfg.cSoundDeviceType), np2oscfg.szSoundDeviceName, hWnd)) + { + CSoundMng::GetInstance()->LoadPCM(SOUND_PCMSEEK, TEXT("SEEKWAV")); + CSoundMng::GetInstance()->LoadPCM(SOUND_PCMSEEK1, TEXT("SEEK1WAV")); + CSoundMng::GetInstance()->LoadPCM(SOUND_RELAY1, TEXT("RELAY1WAV")); + CSoundMng::GetInstance()->SetPCMVolume(SOUND_PCMSEEK, np2cfg.MOTORVOL); + CSoundMng::GetInstance()->SetPCMVolume(SOUND_PCMSEEK1, np2cfg.MOTORVOL); + CSoundMng::GetInstance()->SetPCMVolume(SOUND_RELAY1, np2cfg.MOTORVOL); + } + + if (np2oscfg.MOUSE_SW) { // ver0.30 + mousemng_enable(MOUSEPROC_SYSTEM); + } + + commng_initialize(); + sysmng_initialize(); + + joymng_initialize(); + pccore_init(); + S98_init(); + +#ifdef OPENING_WAIT + while((GetTickCount() - tick) < OPENING_WAIT); +#endif + +#ifdef SUPPORT_NET + //np2net_init(); +#endif +#ifdef SUPPORT_WAB + //np2wab_init(g_hInstance, g_hWndMain); +#endif +#ifdef SUPPORT_CL_GD5430 + //pc98_cirrus_vga_init(); +#endif + +#ifdef SUPPORT_PHYSICAL_CDDRV + np2updatemenu(); +#endif + + SetTickCounterMode(np2oscfg.tickmode); + pccore_reset(); + np2_SetUserPause(0); + + // スナップ位置の復元のため先に作成 + if (!(g_scrnmode & SCRNMODE_FULLSCREEN)) { + if (np2oscfg.toolwin) { + toolwin_create(); + } + if (np2oscfg.keydisp) { + kdispwin_create(); + } + if (np2oscfg.skbdwin) { + skbdwin_create(); + } + } + + // れじうむ +#if defined(SUPPORT_RESUME) + if (np2oscfg.resume) { + int id; + + id = flagload(hWnd, str_sav, _T("Resume"), FALSE); + if (id == IDYES) + { + Np2Arg::GetInstance()->ClearDisk(); + } + else if (id == IDCANCEL) { + DestroyWindow(hWnd); + mousemng_disable(MOUSEPROC_WINUI); + S98_trash(); + pccore_term(); + CSoundMng::GetInstance()->Close(); + CSoundMng::Deinitialize(); + scrnmng_destroy(); + UnloadExternalResource(); + TRACETERM(); + dosio_term(); + SendMessage(hWnd, WM_CLOSE, 0, 0L); + return; + } + } +#endif + soundmng_setvolume(np2cfg.vol_master); + + // 画面表示倍率を復元 + if(np2oscfg.svscrmul){ + scrnmng_setmultiple(np2oscfg.scrn_mul); + } +// リセットしてから… + // INIに記録されたディスクを挿入 + if(np2cfg.savefddfile){ + for (i = 0; i < 4; i++) + { + LPCTSTR lpDisk = np2cfg.fddfile[i]; + if (lpDisk) + { + diskdrv_readyfdd((REG8)i, lpDisk, 0); + toolwin_setfdd((REG8)i, lpDisk); + } + } + } +#if defined(SUPPORT_IDEIO) + // INIに記録されたCDを挿入 + if (np2cfg.savecdfile) { + for (i = 0; i < 4; i++) + { + if (np2cfg.idetype[i] == IDETYPE_CDROM) { + LPCTSTR lpDisk = np2cfg.idecd[i]; + if (lpDisk) + { + diskdrv_setsxsi(i, lpDisk); + } + } + } + } +#endif + + scrndraw_redraw(); + + np2opening = 0; + + sysmng_workclockreset(); + sysmng_updatecaption(SYS_UPDATECAPTION_ALL); + +#ifdef HOOK_SYSKEY + start_hook_systemkey(); +#endif +} + +#if defined(SUPPORT_MULTITHREAD) +static unsigned int __stdcall np2_multithread_EmulatorThreadMain(LPVOID vdParam){ + while (!np2_multithread_hThread_requestexit) { + if (!np2stopemulate && !np2_multithread_pauseemulation && !np2userpause) { + UINT8 drawskip = (np2oscfg.DRAW_SKIP == 0 ? 1 : np2oscfg.DRAW_SKIP); +#if defined(CPUCORE_IA32) + cpu_drawskip = drawskip; + cpu_nowait = np2oscfg.NOWAIT; +#endif + np2_multithread_pausing = false; + if (np2oscfg.NOWAIT) { + ExecuteOneFrame_MT_EmulateThread(framecnt == 0); + if (drawskip) { // nowait frame skip + framecnt++; + if (framecnt >= drawskip) { + processwait(0); + soundmng_sync(); + } + } + else { // nowait auto skip + framecnt = 1; + if (timing_getcount()) { + processwait(0); + soundmng_sync(); + } + } + } + else if (drawskip) { // frame skip + if (framecnt < drawskip) { + ExecuteOneFrame_MT_EmulateThread(framecnt == 0); + framecnt++; + } + else { + processwait(drawskip); + soundmng_sync(); + } + } + else { // auto skip + if (!waitcnt) { + UINT cnt; + ExecuteOneFrame_MT_EmulateThread(framecnt == 0); + framecnt++; + cnt = timing_getcount(); + if (framecnt > cnt) { + waitcnt = framecnt; + if (framemax > 1) { + framemax--; + } + } + else if (framecnt >= framemax) { + if (framemax < 12) { + framemax++; + } + if (cnt >= 12) { + timing_reset(); + } + else { + timing_setcount(cnt - framecnt); + } + framereset_MT_EmulateThread(0); + } + } + else { + processwait(waitcnt); + soundmng_sync(); + waitcnt = framecnt; + } + } + if(autokey_sendbufferlen > 0) + autoSendKey(); // 自動キー送信 + + scrnmng_delaychangemode(); + } + else if (np2_multithread_pauseemulation == 1) { + np2_multithread_pausing = true; + Sleep(100); + } + else if (np2stopemulate == 1 || np2userpause) { // background sleep + np2_multithread_pausing = false; + Sleep(100); + }else{ + np2_multithread_pausing = false; + } + } + return 0; +} +void np2_multithread_StartThread(){ + if(np2_multithread_initialized){ + unsigned int dwID; + np2_multithread_hThread_requestexit = FALSE; + np2_multithread_hThread = (HANDLE)_beginthreadex(NULL, 0, np2_multithread_EmulatorThreadMain, NULL, 0, &dwID); + SetThreadPriority(np2_multithread_hThread, THREAD_PRIORITY_ABOVE_NORMAL); + } +} +#endif + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, + LPSTR lpszCmdLine, int nCmdShow) { + WNDCLASS wc; + MSG msg; + HWND hWnd; + UINT i; + DWORD style; +#ifdef OPENING_WAIT + UINT32 tick; +#endif + BOOL xrollkey; + int winx, winy; + +#ifdef _DEBUG + // 使うときはstdlib.hとcrtdbg.hをインクルードする + _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + //_CrtSetBreakAlloc(499); +#endif + +#if defined(SUPPORT_WIN2000HOST) +#ifdef _WINDOWS +#ifndef _WIN64 +#define WINVER2 0x0500 + initialize_findacx(); +#endif +#endif +#endif + + winloc_InitDwmFunc(); + + WM_QueryCancelAutoPlay = RegisterWindowMessage(_T("QueryCancelAutoPlay")); + + createAsciiTo98KeyCodeList(); + + _MEM_INIT(); + CWndProc::Initialize(hInstance); + CSubWndBase::Initialize(hInstance); +#if defined(SUPPORT_VSTi) + CVstEditWnd::Initialize(hInstance); +#endif // defined(SUPPORT_VSTi) + + GetModuleFileName(NULL, modulefile, NELEMENTS(modulefile)); + dosio_init(); + file_setcd(modulefile); + Np2Arg::GetInstance()->Parse(); + initload(); + toolwin_readini(); + kdispwin_readini(); + skbdwin_readini(); + mdbgwin_readini(); +#if defined(SUPPORT_WAB) + wabwin_readini(); + np2wabcfg.readonly = np2oscfg.readonly; +#endif // defined(SUPPORT_WAB) +#if defined(SUPPORT_HOSTDRV) + hostdrv_readini(); +#endif // defined(SUPPORT_HOSTDRV) + +#if defined(SUPPORT_MULTITHREAD) + np2_multithread_enable = np2oscfg.multithread; + np2_multithread_Initialize(); +#endif + + rand_setseed((unsigned)time(NULL)); + + szClassName[0] = (TCHAR)np2oscfg.winid[0]; + szClassName[1] = (TCHAR)np2oscfg.winid[1]; + szClassName[2] = (TCHAR)np2oscfg.winid[2]; + +#ifndef ALLOW_MULTIRUN + if ((hWnd = FindWindow(szClassName, NULL)) != NULL) { + sstpmsg_running(); + ShowWindow(hWnd, SW_RESTORE); + SetForegroundWindow(hWnd); + dosio_term(); + return(FALSE); + } +#else + if ((hWnd = FindWindow(szClassName, NULL)) != NULL && np2oscfg.resume) { + // レジュームの時は複数起動するとやばいので・・・ + ShowWindow(hWnd, SW_RESTORE); + SetForegroundWindow(hWnd); + dosio_term(); + return(FALSE); + } +#endif + + g_hInstance = hInstance = LoadExternalResource(hInstance); + CWndProc::SetResourceHandle(hInstance); + +#if !defined(_WIN64) + mmxflag = (havemmx())?0:MMXFLAG_NOTSUPPORT; + mmxflag += (np2oscfg.disablemmx)?MMXFLAG_DISABLE:0; +#endif + TRACEINIT(); + + xrollkey = (np2oscfg.xrollkey == 0); + if (np2oscfg.KEYBOARD >= KEY_TYPEMAX) { + int keytype = GetKeyboardType(1); + if ((keytype & 0xff00) == 0x0d00) { + np2oscfg.KEYBOARD = KEY_PC98; + xrollkey = !xrollkey; + } + else if (!keytype) { + np2oscfg.KEYBOARD = KEY_KEY101; + } + else { + np2oscfg.KEYBOARD = KEY_KEY106; + } + } + winkbd_roll(xrollkey); + winkbd_setf12(np2oscfg.F12COPY); + keystat_initialize(); + + np2class_initialize(hInstance); + if (!hPrevInst) { + if(np2oscfg.mouse_nc/* && !scrnmng_isfullscreen()*/){ + wc.style = CS_BYTEALIGNCLIENT | CS_HREDRAW | CS_VREDRAW; + }else{ + wc.style = CS_BYTEALIGNCLIENT | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; + } + wc.lpfnWndProc = WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = NP2GWLP_SIZE; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); + wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAIN); + wc.lpszClassName = szClassName; + if (!RegisterClass(&wc)) { + UnloadExternalResource(); + TRACETERM(); + dosio_term(); + return(FALSE); + } + + kdispwin_initialize(); + skbdwin_initialize(); + mdbgwin_initialize(); + CDebugUtyView::Initialize(hInstance); + } + + style = WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX; + if (np2oscfg.thickframe) { + style |= WS_THICKFRAME; + } + + winx = np2oscfg.winx; + winy = np2oscfg.winy; + hWnd = CreateWindowEx(0, szClassName, np2oscfg.titles, style, + winx, winy, 640, 400, + NULL, NULL, hInstance, NULL); + g_hWndMain = hWnd; + + //{ + // HMODULE modUsedr32 = LoadLibraryA("User32.dll"); + // if(modUsedr32){ + // BOOL (WINAPI *pfnRegisterTouchWindow)(__in HWND hwnd, __in ULONG ulFlags); + // pfnRegisterTouchWindow = (BOOL (WINAPI *)(__in HWND hwnd, __in ULONG ulFlags))GetProcAddress(modUsedr32, "RegisterTouchWindow"); + // if(pfnRegisterTouchWindow){ + // (*pfnRegisterTouchWindow)(g_hWndMain, 0x00000001); + // } + // FreeLibrary(modUsedr32); + // } + //} + + mousemng_initialize(); // 場所移動 np21w ver0.96 rev13 + + scrnmng_initialize(); + + if(np2oscfg.dragdrop) + DragAcceptFiles(hWnd, TRUE); // イメージファイルのD&Dに対応(Kai1) + + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + SetWindowPos(hWnd, NULL, winx, winy, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED); // Win10環境でウィンドウ位置がずれる問題の対策 + +#ifdef OPENING_WAIT + tick = GetTickCount(); +#endif + + sysmenu_initialize(GetSystemMenu(hWnd, FALSE)); + + HMENU hMenu = np2class_gethmenu(hWnd); + xmenu_initialize(hMenu); + xmenu_update(hMenu); + if (file_attr_c(np2help) == -1) // ver0.30 + { + EnableMenuItem(hMenu, IDM_HELP, MF_GRAYED); + } + DrawMenuBar(hWnd); + + if(np2oscfg.savescrn){ + g_scrnmode = np2oscfg.scrnmode; + }else{ + g_scrnmode = np2oscfg.scrnmode = 0; + } + if (Np2Arg::GetInstance()->fullscreen()) + { + g_scrnmode |= SCRNMODE_FULLSCREEN; + } + if (np2cfg.RASTER) { + g_scrnmode |= SCRNMODE_HIGHCOLOR; + } + if (scrnmng_create(g_scrnmode) != SUCCESS) { + g_scrnmode ^= SCRNMODE_FULLSCREEN; + if (scrnmng_create(g_scrnmode) != SUCCESS) { + if (sstpmsg_dxerror()) + { + messagebox(hWnd, MAKEINTRESOURCE(IDS_ERROR_DIRECTDRAW), MB_OK | MB_ICONSTOP); + } + UnloadExternalResource(); + TRACETERM(); + dosio_term(); + return(FALSE); + } + } + /* + // XXX: Direct3D絡みのエラー対策 + { + MSG msg; + while(PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) + { + if (!GetMessage(&msg, NULL, 0, 0)) { + break; + } + if ((msg.hwnd != hWnd) || + ((msg.message != WM_SYSKEYDOWN) && + (msg.message != WM_SYSKEYUP))) { + TranslateMessage(&msg); + } + DispatchMessage(&msg); + } + }*/ + + CSoundMng::Initialize(); + OpenSoundDevice(hWnd); + + if (CSoundMng::GetInstance()->Open(static_cast(np2oscfg.cSoundDeviceType), np2oscfg.szSoundDeviceName, hWnd)) + { + CSoundMng::GetInstance()->LoadPCM(SOUND_PCMSEEK, TEXT("SEEKWAV")); + CSoundMng::GetInstance()->LoadPCM(SOUND_PCMSEEK1, TEXT("SEEK1WAV")); + CSoundMng::GetInstance()->LoadPCM(SOUND_RELAY1, TEXT("RELAY1WAV")); + CSoundMng::GetInstance()->SetPCMVolume(SOUND_PCMSEEK, np2cfg.MOTORVOL); + CSoundMng::GetInstance()->SetPCMVolume(SOUND_PCMSEEK1, np2cfg.MOTORVOL); + CSoundMng::GetInstance()->SetPCMVolume(SOUND_RELAY1, np2cfg.MOTORVOL); + } + + if (np2oscfg.MOUSE_SW) { // ver0.30 + if(GetForegroundWindow() == hWnd){ + mousemng_enable(MOUSEPROC_SYSTEM); + }else{ + np2oscfg.MOUSE_SW = 0; + } + } + + commng_initialize(); + sysmng_initialize(); + + joymng_initialize(); + pccore_init(); + S98_init(); + + sstpmsg_welcome(); + +#ifdef SUPPORT_NET + np2net_init(); +#endif +#ifdef SUPPORT_WAB + np2wab_init(g_hInstance, g_hWndMain); +#endif +#ifdef SUPPORT_CL_GD5430 + pc98_cirrus_vga_init(); +#endif + +#ifdef SUPPORT_PHYSICAL_CDDRV + np2updatemenu(); +#endif + + SetTickCounterMode(np2oscfg.tickmode); + pccore_reset(); + np2_SetUserPause(0); + + // スナップ位置の復元のため先に作成 + if (!(g_scrnmode & SCRNMODE_FULLSCREEN)) { + if (np2oscfg.toolwin) { + toolwin_create(); + } + if (np2oscfg.keydisp) { + kdispwin_create(); + } + if (np2oscfg.skbdwin) { + skbdwin_create(); + } + } + + // れじうむ +#if defined(SUPPORT_RESUME) + if (np2oscfg.resume) { + int id; + + id = flagload(hWnd, str_sav, _T("Resume"), FALSE); + if (id == IDYES) + { + Np2Arg::GetInstance()->ClearDisk(); + } + else if (id == IDCANCEL) { + DestroyWindow(hWnd); + mousemng_disable(MOUSEPROC_WINUI); + S98_trash(); + pccore_term(); + sstp_destruct(); + CSoundMng::GetInstance()->Close(); + CSoundMng::Deinitialize(); + scrnmng_destroy(); + scrnmng_shutdown(); + UnloadExternalResource(); + TRACETERM(); + dosio_term(); + return(FALSE); + } + } +#endif + soundmng_setvolume(np2cfg.vol_master); + + // 画面表示倍率を復元 + if(np2oscfg.svscrmul){ + scrnmng_setmultiple(np2oscfg.scrn_mul); + } +// リセットしてから… + // INIに記録されたディスクを挿入 + if(np2cfg.savefddfile){ + for (i = 0; i < 4; i++) + { + LPCTSTR lpDisk = np2cfg.fddfile[i]; + if (lpDisk) + { + diskdrv_readyfdd((REG8)i, lpDisk, 0); + toolwin_setfdd((REG8)i, lpDisk); + } + } + } + // コマンドラインのディスク挿入。 + for (i = 0; i < 4; i++) + { + LPCTSTR lpDisk = Np2Arg::GetInstance()->disk(i); + if (lpDisk) + { + diskdrv_readyfdd((REG8)i, lpDisk, 0); + toolwin_setfdd((REG8)i, lpDisk); + } + } + // コマンドラインのディスク挿入。 + for (i = 0; i < 4; i++) + { + LPCTSTR lpDisk = Np2Arg::GetInstance()->disk(i); + if (lpDisk) + { + diskdrv_readyfdd((REG8)i, lpDisk, 0); + } + } +#ifdef SUPPORT_IDEIO + if (Np2Arg::GetInstance()->cdisk(0)) + { + int cdiskidx = 0; + for (i = 0; i < 4; i++) + { + if (np2cfg.idetype[i] == IDETYPE_CDROM) + { + for (; cdiskidx < 4; cdiskidx++) + { + LPCTSTR lpDisk = Np2Arg::GetInstance()->cdisk(cdiskidx); + if (lpDisk) + { + diskdrv_setsxsi(i, NULL); + diskdrv_setsxsi(i, lpDisk); + break; + } + } + } + } + } +#endif + +#ifdef OPENING_WAIT + while((GetTickCount() - tick) < OPENING_WAIT); +#endif + np2opening = 0; + + scrndraw_redraw(); + + sysmng_workclockreset(); + sysmng_updatecaption(SYS_UPDATECAPTION_ALL); + +#ifdef HOOK_SYSKEY + start_hook_systemkey(); +#endif + + timeBeginPeriod(1); + +#if defined(SUPPORT_MULTITHREAD) + if(np2_multithread_enable){ + UINT_PTR tmrID; + const int tmrInterval = 50; + // マルチスレッドモード + framereset = framereset_MT_EmulateThread; + np2_multithread_StartThread(); + tmrID = SetTimer(hWnd, 23545, tmrInterval, NULL); + while(1) { + if (!GetMessage(&msg, NULL, 0, 0)) { + break; + } + if ((msg.hwnd != hWnd) || + ((msg.message != WM_SYSKEYDOWN) && + (msg.message != WM_SYSKEYUP))) { + if(msg.message == WM_TIMER && msg.wParam == tmrID){ + framereset_MT_UIThread(1); +#if defined(SUPPORT_DCLOCK) + DispClock::GetInstance()->Update(); +#endif +#if defined(SUPPORT_VSTi) + CVstEditWnd::OnIdle(); +#endif // defined(SUPPORT_VSTi) + } + TranslateMessage(&msg); + } + DispatchMessage(&msg); + mousemng_UIThreadSync(); + scrnmng_UIThreadProc(); + } + KillTimer(hWnd, tmrID); + }else +#endif + { + lateframecount = 0; + while(1) { + if(g_u8ControlState == 1) { + statsave_save_d(); + } else if(g_u8ControlState == 2) { + statsave_load_d(); + } + g_u8ControlState = 0; + + if (!np2stopemulate && !np2userpause) { + if (PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) { + if (!GetMessage(&msg, NULL, 0, 0)) { + break; + } + if ((msg.hwnd != hWnd) || + ((msg.message != WM_SYSKEYDOWN) && + (msg.message != WM_SYSKEYUP))) { + TranslateMessage(&msg); + } + DispatchMessage(&msg); + } + else { + UINT8 drawskip = (np2oscfg.DRAW_SKIP == 0 ? 1 : np2oscfg.DRAW_SKIP); +#if defined(CPUCORE_IA32) + cpu_drawskip = drawskip; + cpu_nowait = np2oscfg.NOWAIT; +#endif + if (np2oscfg.NOWAIT) { + ExecuteOneFrame(framecnt == 0); + if (drawskip) { // nowait frame skip + framecnt++; + if (framecnt >= drawskip) { + processwait(0); + soundmng_sync(); + } + } + else { // nowait auto skip + framecnt = 1; + if (timing_getcount()) { + processwait(0); + soundmng_sync(); + } + } + } + else if (drawskip) { // frame skip + if (framecnt < drawskip) { + ExecuteOneFrame(framecnt == 0); + framecnt++; + } + else { + processwait(drawskip); + soundmng_sync(); + } + } + else { // auto skip + if (!waitcnt) { + UINT cnt; + ExecuteOneFrame(framecnt == 0); + framecnt++; + cnt = timing_getcount(); + if (framecnt > cnt) { + waitcnt = framecnt; + if (framemax > 1) { + framemax--; + } + } + else if (framecnt >= framemax) { + if (framemax < 12) { + framemax++; + } + if (cnt >= 12) { + timing_reset(); + } + else { + timing_setcount(cnt - framecnt); + } + framereset(0); + } + } + else { + processwait(waitcnt); + soundmng_sync(); + waitcnt = framecnt; + } + } + if(autokey_sendbufferlen > 0) + autoSendKey(); // 自動キー送信 + } + scrnmng_delaychangemode(); + mousemng_UIThreadSync(); + scrnmng_UIThreadProc(); + } + else if ((np2stopemulate == 1 || np2userpause) || // background sleep + (PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE))) { + if(np2stopemulate == 1) { + lateframecount = 0; + timing_setcount(0); + } + if (!GetMessage(&msg, NULL, 0, 0)) { + break; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } +#if defined(SUPPORT_MULTITHREAD) + np2_multithread_WaitForExitThread(); +#endif + + timeEndPeriod(1); + +#ifdef HOOK_SYSKEY + stop_hook_systemkey(); +#endif + + // 画面表示倍率を保存 + np2oscfg.scrn_mul = scrnmng_getmultiple(); + + toolwin_destroy(); + kdispwin_destroy(); + skbdwin_destroy(); + mdbgwin_destroy(); + + pccore_cfgupdate(); + + mousemng_disable(MOUSEPROC_WINUI); + S98_trash(); + +#if defined(SUPPORT_RESUME) + if (np2oscfg.resume) { + flagsave(str_sav); + } + else { + flagdelete(str_sav); + } +#endif + +#ifdef SUPPORT_CL_GD5430 + pc98_cirrus_vga_shutdown(); +#endif + + pccore_term(); + + sstp_destruct(); + +#ifdef SUPPORT_WAB + np2wab_shutdown(); +#endif +#ifdef SUPPORT_NET + np2net_shutdown(); +#endif + + CSoundMng::GetInstance()->Close(); + CSoundMng::Deinitialize(); + scrnmng_destroy(); + scrnmng_shutdown(); + commng_finalize(); + recvideo_close(); + mousemng_destroy(); + + if (sys_updates & (SYS_UPDATECFG | SYS_UPDATEOSCFG)) { + initsave(); + toolwin_writeini(); + kdispwin_writeini(); + skbdwin_writeini(); + mdbgwin_writeini(); + } +#if defined(SUPPORT_HOSTDRV) + hostdrv_writeini(); +#endif // defined(SUPPORT_HOSTDRV) +#if defined(SUPPORT_WAB) + wabwin_writeini(); +#endif // defined(SUPPORT_WAB) + skbdwin_deinitialize(); + + CSubWndBase::Deinitialize(); + CWndProc::Deinitialize(); + + winloc_DisposeDwmFunc(); + + UnloadExternalResource(); + + TRACETERM(); + _MEM_USED(TEXT("report.txt")); + dosio_term(); + + Np2Arg::Release(); + +#if defined(SUPPORT_MULTITHREAD) + np2_multithread_Finalize(); +#endif + + //_CrtDumpMemoryLeaks(); + + return((int)msg.wParam); +} diff --git a/windows/np2.h b/windows/np2.h old mode 100755 new mode 100644 index 81e8b4cc..4b43c974 --- a/windows/np2.h +++ b/windows/np2.h @@ -1,205 +1,205 @@ -#ifndef _NP2_H_ -#define _NP2_H_ - -#if !defined(SUPPORT_PC9821) -#define PROJECTNAME "Neko Project II kai" -#else -#define PROJECTNAME "Neko Project 21 kai" -#endif - -#if !defined(_WIN64) -#define PROJECTSUBNAME "" -#else -#define PROJECTSUBNAME " x64" -#endif - -#if defined(__cplusplus) -extern "C" { -#endif - -typedef struct { - UINT8 port; - UINT8 def_en; - UINT8 param; - UINT32 speed; - OEMCHAR mout[MAXPNAMELEN]; - OEMCHAR min[MAXPNAMELEN]; - OEMCHAR mdl[64]; - OEMCHAR def[MAX_PATH]; - UINT8 fixedspeed; - UINT8 DSRcheck; -#if defined(SUPPORT_NAMED_PIPE) - OEMCHAR pipename[MAX_PATH]; // The name of the named-pipe - OEMCHAR pipeserv[MAX_PATH]; // The server name of the named-pipe -#endif -} COMCFG; - -typedef struct { - OEMCHAR titles[256]; - OEMCHAR winid[4]; - - int winx; - int winy; - UINT paddingx; - UINT paddingy; - UINT fscrn_cx; - UINT fscrn_cy; - UINT8 force400; - UINT8 WINSNAP; - UINT8 NOWAIT; - UINT8 DRAW_SKIP; - - UINT8 background; - UINT8 DISPCLK; - UINT8 KEYBOARD; - UINT8 F12COPY; - UINT8 USENUMLOCK; - - UINT8 MOUSE_SW; - UINT8 JOYPAD1; - UINT8 JOYPAD2; - UINT8 JOY1BTN[4]; - UINT8 JOY2BTN[4]; - UINT8 JOYPAD1ID; - UINT8 JOYPAD2ID; - - COMCFG mpu; -#if defined(SUPPORT_SMPU98) - COMCFG smpuA; - COMCFG smpuB; -#endif - COMCFG com1; - COMCFG com2; - COMCFG com3; - - UINT32 clk_color1; - UINT32 clk_color2; - UINT8 clk_x; - UINT8 clk_fnt; - - UINT8 comfirm; - UINT8 shortcut; // ver0.30 - - UINT8 sstp; - UINT16 sstpport; - - UINT8 resume; // ver0.30 - UINT8 statsave; -#if !defined(_WIN64) - UINT8 disablemmx; -#endif - UINT8 wintype; - UINT8 toolwin; - UINT8 keydisp; - UINT8 skbdwin; - UINT8 I286SAVE; - UINT8 hostdrv_write; - UINT8 jastsnd; - UINT8 useromeo; - UINT8 thickframe; - UINT8 xrollkey; - UINT8 fscrnbpp; - UINT8 fscrnmod; - UINT8 fsrescfg; - -#if defined(SUPPORT_SCRN_DIRECT3D) - UINT8 d3d_imode; // Direct3D interpolation mode - UINT8 d3d_exclusive; // Direct3D fullscreen exclusive mode -#endif - - UINT8 cSoundDeviceType; - TCHAR szSoundDeviceName[MAX_PATH]; - -#if defined(SUPPORT_VSTi) - TCHAR szVSTiFile[MAX_PATH]; -#endif // defined(SUPPORT_VSTi) - - UINT8 emuddraw; // DirectDraw Emulation Only - UINT8 drawtype; // Screen renderer type (0: DirectDraw, 1: reserved(DirecrDraw), 2: Direct3D) - UINT8 dragdrop; // Drag and drop support - UINT8 makelhdd; // Large HDD creation support - UINT8 syskhook; // Low-level keyboard hook support - UINT8 rawmouse; // Raw mouse input support - SINT16 mousemul; // Mouse speed (mul) - SINT16 mousediv; // Mouse speed (div) - - UINT8 scrnmode; // Screen Mode - UINT8 savescrn; // Save ScreenMode - - UINT8 svscrmul; // Save Screen Size Multiplying Value - UINT8 scrn_mul; // Screen Size Multiplying Value (8: default) - - UINT8 mouse_nc; // Always notify mouse event - UINT16 cpustabf; // CPU clock stabilizer frame - UINT8 readonly; // No save changed settings - UINT8 usewheel; // Use mouse wheel - UINT8 tickmode; // Force Set Tick Counter Mode - //UINT8 usemastervolume; // Use Master Volume - UINT8 usemidivolume; // Use MIDI Volume - UINT8 mastervolumemax; // Maxmum Master Volume - - UINT8 toolwndhistory; // Number of data of recently opened FD image list in Tool Window - -#ifdef SUPPORT_WACOM_TABLET - UINT8 pentabfa; // Pen tablet fixed aspect mode -#endif // defined(SUPPORT_WACOM_TABLET) - -#if defined(SUPPORT_MULTITHREAD) - UINT8 multithread; // Multi Thread Mode -#endif -} NP2OSCFG; - - -enum { - FULLSCREEN_WIDTH = 640, - FULLSCREEN_HEIGHT = 480 -}; - -enum { - NP2BREAK_MAIN = 0x01, - NP2BREAK_DEBUG = 0x02 -}; - -enum { - WM_NP2CMD = (WM_USER + 200), - WM_SSTP = (WM_USER + 201) -}; - -enum { - NP2CMD_EXIT = 0, - NP2CMD_RESET = 1, - NP2CMD_EXIT2 = 0x0100, - NP2CMD_DUMMY = 0xffff -}; - -enum { - MMXFLAG_DISABLE = 1, - MMXFLAG_NOTSUPPORT = 2 -}; - - -extern NP2OSCFG np2oscfg; -extern HWND g_hWndMain; -extern UINT8 np2break; -extern BOOL winui_en; -extern UINT8 g_scrnmode; -#if !defined(_WIN64) -extern int mmxflag; -#endif - -extern OEMCHAR modulefile[MAX_PATH]; -extern OEMCHAR fddfolder[MAX_PATH]; -extern OEMCHAR hddfolder[MAX_PATH]; -extern OEMCHAR cdfolder[MAX_PATH]; -extern OEMCHAR bmpfilefolder[MAX_PATH]; -extern OEMCHAR npcfgfilefolder[MAX_PATH]; - -void np2active_renewal(void); -void unloadNP2INI(); -void loadNP2INI(const OEMCHAR *fname); - -#if defined(__cplusplus) -} -#endif - -#endif // _NP2_H_ +#ifndef _NP2_H_ +#define _NP2_H_ + +#if !defined(SUPPORT_PC9821) +#define PROJECTNAME "Neko Project II kai" +#else +#define PROJECTNAME "Neko Project 21 kai" +#endif + +#if !defined(_WIN64) +#define PROJECTSUBNAME "" +#else +#define PROJECTSUBNAME " x64" +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef struct { + UINT8 port; + UINT8 def_en; + UINT8 param; + UINT32 speed; + OEMCHAR mout[MAXPNAMELEN]; + OEMCHAR min[MAXPNAMELEN]; + OEMCHAR mdl[64]; + OEMCHAR def[MAX_PATH]; + UINT8 fixedspeed; + UINT8 DSRcheck; +#if defined(SUPPORT_NAMED_PIPE) + OEMCHAR pipename[MAX_PATH]; // The name of the named-pipe + OEMCHAR pipeserv[MAX_PATH]; // The server name of the named-pipe +#endif +} COMCFG; + +typedef struct { + OEMCHAR titles[256]; + OEMCHAR winid[4]; + + int winx; + int winy; + UINT paddingx; + UINT paddingy; + UINT fscrn_cx; + UINT fscrn_cy; + UINT8 force400; + UINT8 WINSNAP; + UINT8 NOWAIT; + UINT8 DRAW_SKIP; + + UINT8 background; + UINT8 DISPCLK; + UINT8 KEYBOARD; + UINT8 F12COPY; + UINT8 USENUMLOCK; + + UINT8 MOUSE_SW; + UINT8 JOYPAD1; + UINT8 JOYPAD2; + UINT8 JOY1BTN[4]; + UINT8 JOY2BTN[4]; + UINT8 JOYPAD1ID; + UINT8 JOYPAD2ID; + + COMCFG mpu; +#if defined(SUPPORT_SMPU98) + COMCFG smpuA; + COMCFG smpuB; +#endif + COMCFG com1; + COMCFG com2; + COMCFG com3; + + UINT32 clk_color1; + UINT32 clk_color2; + UINT8 clk_x; + UINT8 clk_fnt; + + UINT8 comfirm; + UINT8 shortcut; // ver0.30 + + UINT8 sstp; + UINT16 sstpport; + + UINT8 resume; // ver0.30 + UINT8 statsave; +#if !defined(_WIN64) + UINT8 disablemmx; +#endif + UINT8 wintype; + UINT8 toolwin; + UINT8 keydisp; + UINT8 skbdwin; + UINT8 I286SAVE; + UINT8 hostdrv_write; + UINT8 jastsnd; + UINT8 useromeo; + UINT8 thickframe; + UINT8 xrollkey; + UINT8 fscrnbpp; + UINT8 fscrnmod; + UINT8 fsrescfg; + +#if defined(SUPPORT_SCRN_DIRECT3D) + UINT8 d3d_imode; // Direct3D interpolation mode + UINT8 d3d_exclusive; // Direct3D fullscreen exclusive mode +#endif + + UINT8 cSoundDeviceType; + TCHAR szSoundDeviceName[MAX_PATH]; + +#if defined(SUPPORT_VSTi) + TCHAR szVSTiFile[MAX_PATH]; +#endif // defined(SUPPORT_VSTi) + + UINT8 emuddraw; // DirectDraw Emulation Only + UINT8 drawtype; // Screen renderer type (0: DirectDraw, 1: reserved(DirecrDraw), 2: Direct3D) + UINT8 dragdrop; // Drag and drop support + UINT8 makelhdd; // Large HDD creation support + UINT8 syskhook; // Low-level keyboard hook support + UINT8 rawmouse; // Raw mouse input support + SINT16 mousemul; // Mouse speed (mul) + SINT16 mousediv; // Mouse speed (div) + + UINT8 scrnmode; // Screen Mode + UINT8 savescrn; // Save ScreenMode + + UINT8 svscrmul; // Save Screen Size Multiplying Value + UINT8 scrn_mul; // Screen Size Multiplying Value (8: default) + + UINT8 mouse_nc; // Always notify mouse event + UINT16 cpustabf; // CPU clock stabilizer frame + UINT8 readonly; // No save changed settings + UINT8 usewheel; // Use mouse wheel + UINT8 tickmode; // Force Set Tick Counter Mode + //UINT8 usemastervolume; // Use Master Volume + UINT8 usemidivolume; // Use MIDI Volume + UINT8 mastervolumemax; // Maxmum Master Volume + + UINT8 toolwndhistory; // Number of data of recently opened FD image list in Tool Window + +#ifdef SUPPORT_WACOM_TABLET + UINT8 pentabfa; // Pen tablet fixed aspect mode +#endif // defined(SUPPORT_WACOM_TABLET) + +#if defined(SUPPORT_MULTITHREAD) + UINT8 multithread; // Multi Thread Mode +#endif +} NP2OSCFG; + + +enum { + FULLSCREEN_WIDTH = 640, + FULLSCREEN_HEIGHT = 480 +}; + +enum { + NP2BREAK_MAIN = 0x01, + NP2BREAK_DEBUG = 0x02 +}; + +enum { + WM_NP2CMD = (WM_USER + 200), + WM_SSTP = (WM_USER + 201) +}; + +enum { + NP2CMD_EXIT = 0, + NP2CMD_RESET = 1, + NP2CMD_EXIT2 = 0x0100, + NP2CMD_DUMMY = 0xffff +}; + +enum { + MMXFLAG_DISABLE = 1, + MMXFLAG_NOTSUPPORT = 2 +}; + + +extern NP2OSCFG np2oscfg; +extern HWND g_hWndMain; +extern UINT8 np2break; +extern BOOL winui_en; +extern UINT8 g_scrnmode; +#if !defined(_WIN64) +extern int mmxflag; +#endif + +extern OEMCHAR modulefile[MAX_PATH]; +extern OEMCHAR fddfolder[MAX_PATH]; +extern OEMCHAR hddfolder[MAX_PATH]; +extern OEMCHAR cdfolder[MAX_PATH]; +extern OEMCHAR bmpfilefolder[MAX_PATH]; +extern OEMCHAR npcfgfilefolder[MAX_PATH]; + +void np2active_renewal(void); +void unloadNP2INI(); +void loadNP2INI(const OEMCHAR *fname); + +#if defined(__cplusplus) +} +#endif + +#endif // _NP2_H_ diff --git a/windows/np2arg.cpp b/windows/np2arg.cpp old mode 100755 new mode 100644 index 75fb2b16..e05806b8 --- a/windows/np2arg.cpp +++ b/windows/np2arg.cpp @@ -1,122 +1,122 @@ -/** - * @file np2arg.cpp - * @brief 引数情報クラスの動作の定義を行います - */ - -#include -#include "np2arg.h" -#include - -#define MAXARG 32 //!< 最大引数エントリ数 -#define ARG_BASE 1 //!< win32 の lpszCmdLine の場合の開始エントリ - -//! 唯一のインスタンスです -Np2Arg Np2Arg::sm_instance; - -/** - * コンストラクタ - */ -Np2Arg::Np2Arg() -{ - ZeroMemory(this, sizeof(*this)); -} - -/** - * デストラクタ - */ -Np2Arg::~Np2Arg() -{ - if(m_lpArg){ - free(m_lpArg); - m_lpArg = NULL; - } - if(m_lpIniFile){ - free(m_lpIniFile); // np21w ver0.86 rev8 - m_lpIniFile = NULL; - } -} - -/** - * パース - */ -void Np2Arg::Parse() -{ - LPCTSTR lpIniFile = NULL; - - // 引数読み出し - if(m_lpArg) { - free(m_lpArg); - } - m_lpArg = _tcsdup(::GetCommandLine()); - - LPTSTR argv[MAXARG]; - const int argc = ::milstr_getarg(m_lpArg, argv, _countof(argv)); - - int nDrive = 0; - int nCDrive = 0; - - for (int i = ARG_BASE; i < argc; i++) - { - LPCTSTR lpArg = argv[i]; - if ((lpArg[0] == TEXT('/')) || (lpArg[0] == TEXT('-'))) - { - switch (_totlower(lpArg[1])) - { - case 'f': - m_fFullscreen = true; - break; - - case 'i': - lpIniFile = &lpArg[2]; - break; - } - } - else - { - LPCTSTR lpExt = ::file_getext(lpArg); - if (::file_cmpname(lpExt, TEXT("ini")) == 0 || ::file_cmpname(lpExt, TEXT("npc")) == 0 || ::file_cmpname(lpExt, TEXT("npcfg")) == 0 || ::file_cmpname(lpExt, TEXT("np2cfg")) == 0 || ::file_cmpname(lpExt, TEXT("np21cfg")) == 0 || ::file_cmpname(lpExt, TEXT("np21wcfg")) == 0) - { - lpIniFile = lpArg; - } - else if (::file_cmpname(lpExt, TEXT("iso")) == 0 || ::file_cmpname(lpExt, TEXT("cue")) == 0 || ::file_cmpname(lpExt, TEXT("ccd")) == 0 || ::file_cmpname(lpExt, TEXT("cdm")) == 0 || ::file_cmpname(lpExt, TEXT("mds")) == 0 || ::file_cmpname(lpExt, TEXT("nrg")) == 0) - { - // CDぽい - if (nCDrive < _countof(m_lpCDisk)) - { - m_lpCDisk[nCDrive++] = lpArg; - } - } - else - { - // ディスク扱い - if (nDrive < _countof(m_lpDisk)) - { - m_lpDisk[nDrive++] = lpArg; - } - } - } - } - if(lpIniFile){ // np21w ver0.86 rev8 - LPTSTR strbuf; - strbuf = (LPTSTR)calloc(500, sizeof(TCHAR)); - if(!(_tcsstr(lpIniFile,_T(":"))!=NULL || (lpIniFile[0]=='¥¥'))){ - // ファイル名のみの指定っぽかったら現在のディレクトリを結合 - //getcwd(pathname, 300); - GetCurrentDirectory(500, strbuf); - if(strbuf[_tcslen(strbuf)-1]!='¥¥'){ - _tcscat(strbuf, _T("¥¥")); // XXX: Linuxとかだったらスラッシュじゃないと駄目だよね? -> Win専用だから問題ない - } - } - _tcscat(strbuf, lpIniFile); - m_lpIniFile = strbuf; - } -} - -/** - * ディスク情報をクリア - */ -void Np2Arg::ClearDisk() -{ - ZeroMemory(m_lpDisk, sizeof(m_lpDisk)); - ZeroMemory(m_lpCDisk, sizeof(m_lpCDisk)); -} +/** + * @file np2arg.cpp + * @brief 引数情報クラスの動作の定義を行います + */ + +#include +#include "np2arg.h" +#include + +#define MAXARG 32 //!< 最大引数エントリ数 +#define ARG_BASE 1 //!< win32 の lpszCmdLine の場合の開始エントリ + +//! 唯一のインスタンスです +Np2Arg Np2Arg::sm_instance; + +/** + * コンストラクタ + */ +Np2Arg::Np2Arg() +{ + ZeroMemory(this, sizeof(*this)); +} + +/** + * デストラクタ + */ +Np2Arg::~Np2Arg() +{ + if(m_lpArg){ + free(m_lpArg); + m_lpArg = NULL; + } + if(m_lpIniFile){ + free(m_lpIniFile); // np21w ver0.86 rev8 + m_lpIniFile = NULL; + } +} + +/** + * パース + */ +void Np2Arg::Parse() +{ + LPCTSTR lpIniFile = NULL; + + // 引数読み出し + if(m_lpArg) { + free(m_lpArg); + } + m_lpArg = _tcsdup(::GetCommandLine()); + + LPTSTR argv[MAXARG]; + const int argc = ::milstr_getarg(m_lpArg, argv, _countof(argv)); + + int nDrive = 0; + int nCDrive = 0; + + for (int i = ARG_BASE; i < argc; i++) + { + LPCTSTR lpArg = argv[i]; + if ((lpArg[0] == TEXT('/')) || (lpArg[0] == TEXT('-'))) + { + switch (_totlower(lpArg[1])) + { + case 'f': + m_fFullscreen = true; + break; + + case 'i': + lpIniFile = &lpArg[2]; + break; + } + } + else + { + LPCTSTR lpExt = ::file_getext(lpArg); + if (::file_cmpname(lpExt, TEXT("ini")) == 0 || ::file_cmpname(lpExt, TEXT("npc")) == 0 || ::file_cmpname(lpExt, TEXT("npcfg")) == 0 || ::file_cmpname(lpExt, TEXT("np2cfg")) == 0 || ::file_cmpname(lpExt, TEXT("np21cfg")) == 0 || ::file_cmpname(lpExt, TEXT("np21wcfg")) == 0) + { + lpIniFile = lpArg; + } + else if (::file_cmpname(lpExt, TEXT("iso")) == 0 || ::file_cmpname(lpExt, TEXT("cue")) == 0 || ::file_cmpname(lpExt, TEXT("ccd")) == 0 || ::file_cmpname(lpExt, TEXT("cdm")) == 0 || ::file_cmpname(lpExt, TEXT("mds")) == 0 || ::file_cmpname(lpExt, TEXT("nrg")) == 0) + { + // CDぽい + if (nCDrive < _countof(m_lpCDisk)) + { + m_lpCDisk[nCDrive++] = lpArg; + } + } + else + { + // ディスク扱い + if (nDrive < _countof(m_lpDisk)) + { + m_lpDisk[nDrive++] = lpArg; + } + } + } + } + if(lpIniFile){ // np21w ver0.86 rev8 + LPTSTR strbuf; + strbuf = (LPTSTR)calloc(500, sizeof(TCHAR)); + if(!(_tcsstr(lpIniFile,_T(":"))!=NULL || (lpIniFile[0]=='¥¥'))){ + // ファイル名のみの指定っぽかったら現在のディレクトリを結合 + //getcwd(pathname, 300); + GetCurrentDirectory(500, strbuf); + if(strbuf[_tcslen(strbuf)-1]!='¥¥'){ + _tcscat(strbuf, _T("¥¥")); // XXX: Linuxとかだったらスラッシュじゃないと駄目だよね? -> Win専用だから問題ない + } + } + _tcscat(strbuf, lpIniFile); + m_lpIniFile = strbuf; + } +} + +/** + * ディスク情報をクリア + */ +void Np2Arg::ClearDisk() +{ + ZeroMemory(m_lpDisk, sizeof(m_lpDisk)); + ZeroMemory(m_lpCDisk, sizeof(m_lpCDisk)); +} diff --git a/windows/np2arg.h b/windows/np2arg.h old mode 100755 new mode 100644 index c359d294..99b227ef --- a/windows/np2arg.h +++ b/windows/np2arg.h @@ -1,112 +1,112 @@ -/** - * @file np2arg.h - * @brief 引数情報クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -/** - * @brief 引数情報クラス - */ -class Np2Arg -{ -public: - static Np2Arg* GetInstance(); - static void Release(); - - Np2Arg(); - ~Np2Arg(); - void Parse(); - void ClearDisk(); - LPCTSTR disk(int nDrive) const; - LPCTSTR cdisk(int nDrive) const; - LPCTSTR iniFilename() const; - bool fullscreen() const; - void setiniFilename(LPTSTR newfile); - -private: - static Np2Arg sm_instance; //!< 唯一のインスタンスです - - LPCTSTR m_lpDisk[4]; //!< ディスク - LPCTSTR m_lpCDisk[4]; //!< CD - LPTSTR m_lpIniFile; //!< 設定ファイル - bool m_fFullscreen; //!< フルスクリーン モード - LPTSTR m_lpArg; //!< ワーク -}; - -/** - * インスタンスを得る - * @return インスタンス - */ -inline Np2Arg* Np2Arg::GetInstance() -{ - return &sm_instance; -} - -/** - * メモリ解放 - */ -inline void Np2Arg::Release() -{ - if(sm_instance.m_lpArg){ - free(sm_instance.m_lpArg); - sm_instance.m_lpArg = NULL; - } - if(sm_instance.m_lpIniFile){ - free(sm_instance.m_lpIniFile); // np21w ver0.86 rev8 - sm_instance.m_lpIniFile = NULL; - } -} - -/** - * ディスク パスを得る - * @param[in] nDrive ドライブ - * @return ディスク パス - */ -inline LPCTSTR Np2Arg::disk(int nDrive) const -{ - return m_lpDisk[nDrive]; -} - -/** - * CD パスを得る - * @param[in] nDrive ドライブ - * @return ディスク パス - */ -inline LPCTSTR Np2Arg::cdisk(int nDrive) const -{ - return m_lpCDisk[nDrive]; -} - -/** - * INI パスを得る - * @return INI パス - */ -inline LPCTSTR Np2Arg::iniFilename() const -{ - return m_lpIniFile; -} - -/** - * フルスクリーンかを得る - * @retval true フルスクリーン モード - * @retval false ウィンドウ モード - */ -inline bool Np2Arg::fullscreen() const -{ - return m_fFullscreen; -} - -/** - * INI パスを得る - * @return INI パス - */ -inline void Np2Arg::setiniFilename(LPTSTR newfile) -{ - if(m_lpIniFile){ - free(m_lpIniFile); - m_lpIniFile = NULL; - } - m_lpIniFile = newfile; -} - +/** + * @file np2arg.h + * @brief 引数情報クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +/** + * @brief 引数情報クラス + */ +class Np2Arg +{ +public: + static Np2Arg* GetInstance(); + static void Release(); + + Np2Arg(); + ~Np2Arg(); + void Parse(); + void ClearDisk(); + LPCTSTR disk(int nDrive) const; + LPCTSTR cdisk(int nDrive) const; + LPCTSTR iniFilename() const; + bool fullscreen() const; + void setiniFilename(LPTSTR newfile); + +private: + static Np2Arg sm_instance; //!< 唯一のインスタンスです + + LPCTSTR m_lpDisk[4]; //!< ディスク + LPCTSTR m_lpCDisk[4]; //!< CD + LPTSTR m_lpIniFile; //!< 設定ファイル + bool m_fFullscreen; //!< フルスクリーン モード + LPTSTR m_lpArg; //!< ワーク +}; + +/** + * インスタンスを得る + * @return インスタンス + */ +inline Np2Arg* Np2Arg::GetInstance() +{ + return &sm_instance; +} + +/** + * メモリ解放 + */ +inline void Np2Arg::Release() +{ + if(sm_instance.m_lpArg){ + free(sm_instance.m_lpArg); + sm_instance.m_lpArg = NULL; + } + if(sm_instance.m_lpIniFile){ + free(sm_instance.m_lpIniFile); // np21w ver0.86 rev8 + sm_instance.m_lpIniFile = NULL; + } +} + +/** + * ディスク パスを得る + * @param[in] nDrive ドライブ + * @return ディスク パス + */ +inline LPCTSTR Np2Arg::disk(int nDrive) const +{ + return m_lpDisk[nDrive]; +} + +/** + * CD パスを得る + * @param[in] nDrive ドライブ + * @return ディスク パス + */ +inline LPCTSTR Np2Arg::cdisk(int nDrive) const +{ + return m_lpCDisk[nDrive]; +} + +/** + * INI パスを得る + * @return INI パス + */ +inline LPCTSTR Np2Arg::iniFilename() const +{ + return m_lpIniFile; +} + +/** + * フルスクリーンかを得る + * @retval true フルスクリーン モード + * @retval false ウィンドウ モード + */ +inline bool Np2Arg::fullscreen() const +{ + return m_fFullscreen; +} + +/** + * INI パスを得る + * @return INI パス + */ +inline void Np2Arg::setiniFilename(LPTSTR newfile) +{ + if(m_lpIniFile){ + free(m_lpIniFile); + m_lpIniFile = NULL; + } + m_lpIniFile = newfile; +} + diff --git a/windows/np2mt.h b/windows/np2mt.h index d53f9fe5..f55148c3 100644 --- a/windows/np2mt.h +++ b/windows/np2mt.h @@ -1,12 +1,12 @@ - -#ifdef __cplusplus -extern "C" { -#endif -void np2_multithread_Suspend(); -void np2_multithread_Resume(); -void np2_multithread_EnterCriticalSection(); -void np2_multithread_LeaveCriticalSection(); -int np2_multithread_Enabled(); -#ifdef __cplusplus -} + +#ifdef __cplusplus +extern "C" { +#endif +void np2_multithread_Suspend(); +void np2_multithread_Resume(); +void np2_multithread_EnterCriticalSection(); +void np2_multithread_LeaveCriticalSection(); +int np2_multithread_Enabled(); +#ifdef __cplusplus +} #endif \ No newline at end of file diff --git a/windows/oemtext.cpp b/windows/oemtext.cpp old mode 100755 new mode 100644 index a17a9721..8c364fcd --- a/windows/oemtext.cpp +++ b/windows/oemtext.cpp @@ -1,258 +1,258 @@ -#include -#include "oemtext.h" -#include "codecnv/textcnv.h" - - -// Use WinAPI version - -UINT oemtext_mbtoucs2(UINT cp, wchar_t *dst, UINT dcnt, const char *src, UINT scnt) { - - int srccnt; - int dstcnt; - int r; - - if (((SINT)scnt) > 0) { - srccnt = scnt; - } - else { - srccnt = -1; - } - if (((SINT)dcnt) > 0) { - dstcnt = dcnt; - if (srccnt < 0) { - dstcnt = dstcnt - 1; - if (dstcnt == 0) { - if (dst) { - dst[0] = '\0'; - } - return(1); - } - } - } - else { - dstcnt = 0; - } - r = MultiByteToWideChar(cp, MB_PRECOMPOSED, src, srccnt, dst, dstcnt); - if ((r == 0) && (dstcnt != 0)) { - r = dstcnt; - if (srccnt < 0) { - if (dst) { - dst[r] = '\0'; - } - r++; - } - } - return(r); -} - -UINT oemtext_ucs2tomb(UINT cp, char *dst, UINT dcnt, const wchar_t *src, UINT scnt) { - - int srccnt; - int dstcnt; - int r; - - if (((SINT)scnt) > 0) { - srccnt = scnt; - } - else { - srccnt = -1; - } - if (((SINT)dcnt) > 0) { - dstcnt = dcnt; - if (srccnt < 0) { - dstcnt = dstcnt - 1; - if (dstcnt == 0) { - if (dst) { - dst[0] = '\0'; - } - return(1); - } - } - } - else { - dstcnt = 0; - } - r = WideCharToMultiByte(cp, 0, src, srccnt, dst, dstcnt, NULL, NULL); - if ((r == 0) && (dstcnt != 0)) { - r = dstcnt; - if (srccnt < 0) { - if (dst) { - dst[r] = '\0'; - } - r++; - } - } - return(r); -} - -UINT oemtext_mbtoutf8(UINT cp, char *dst, UINT dcnt, const char *src, UINT scnt) { - - UINT leng; - wchar_t *ucs2; - UINT ret; - - (void)scnt; - - leng = MultiByteToWideChar(cp, MB_PRECOMPOSED, src, scnt, NULL, 0); - if (leng == 0) { - return(0); - } - ucs2 = (wchar_t *)_MALLOC(leng * sizeof(wchar_t), ""); - if (ucs2 == NULL) { - return(0); - } - MultiByteToWideChar(cp, MB_PRECOMPOSED, src, scnt, ucs2, leng); - if (((SINT)scnt) < 0) { - leng = (UINT)-1; - } - ret = codecnv_ucs2toutf8(dst, dcnt, (UINT16 *)ucs2, leng); - _MFREE(ucs2); - return(ret); -} - -UINT oemtext_utf8tomb(UINT cp, char *dst, UINT dcnt, const char *src, UINT scnt) { - - UINT leng; - wchar_t *ucs2; - UINT ret; - - (void)scnt; - - leng = codecnv_utf8toucs2(NULL, 0, src, scnt); - if (leng == 0) { - return(0); - } - ucs2 = (wchar_t *)_MALLOC(leng * sizeof(wchar_t), ""); - if (ucs2 == NULL) { - return(0); - } - codecnv_utf8toucs2((UINT16 *)ucs2, leng, src, scnt); - if (((SINT)scnt) < 0) { - leng = (UINT)-1; - } - ret = WideCharToMultiByte(cp, 0, ucs2, leng, dst, dcnt, NULL, NULL); - _MFREE(ucs2); - return(ret); -} - - -// ---- - -UINT oemtext_chartoucs2(wchar_t *dst, UINT dcnt, const char *src, UINT scnt) { - - return(oemtext_mbtoucs2(CP_ACP, dst, dcnt, src, scnt)); -} - -UINT oemtext_ucs2tochar(char *dst, UINT dcnt, const wchar_t *src, UINT scnt) { - - return(oemtext_ucs2tomb(CP_ACP, dst, dcnt, src, scnt)); -} - -UINT oemtext_chartoutf8(char *dst, UINT dcnt, const char *src, UINT scnt) { - - return(oemtext_mbtoutf8(CP_ACP, dst, dcnt, src, scnt)); -} - -UINT oemtext_utf8tochar(char *dst, UINT dcnt, const char *src, UINT scnt) { - - return(oemtext_utf8tomb(CP_ACP, dst, dcnt, src, scnt)); -} - - -// ---- textcnv - -UINT textcnv_getinfo(TCINF *inf, const UINT8 *hdr, UINT hdrsize) { - - UINT textcode; - TCINF info; - - textcode = TEXTCNV_DEFAULT; - ZeroMemory(&info, sizeof(info)); - if ((hdrsize >= 3) && - (hdr[0] == 0xef) && (hdr[1] == 0xbb) && (hdr[2] == 0xbf)) { - // UTF-8 - textcode = TEXTCNV_UTF8; - info.width = 1; - info.hdrsize = 3; - } - else if ((hdrsize >= 2) && (hdr[0] == 0xff) && (hdr[1] == 0xfe)) { - // UCSLE - textcode = TEXTCNV_UCS2; -#if defined(BYTESEX_BIG) - info.xendian = 1; -#endif - info.width = 2; - info.hdrsize = 2; - } - else if ((hdrsize >= 2) && (hdr[0] == 0xfe) && (hdr[1] == 0xff)) { - // UCS2BE - // UCSLE - textcode = TEXTCNV_UCS2; -#if defined(BYTESEX_LITTLE) - info.xendian = 1; -#endif - info.width = 2; - info.hdrsize = 2; - } - else { - info.width = 1; - } - -#if defined(OSLANG_SJIS) - switch(textcode) { - case TEXTCNV_DEFAULT: - case TEXTCNV_SJIS: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - break; - - case TEXTCNV_UTF8: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - info.tooem = (TCTOOEM)oemtext_utf8tochar; - info.fromoem = (TCFROMOEM)oemtext_chartoutf8; - break; - - case TEXTCNV_UCS2: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - info.tooem = (TCTOOEM)oemtext_ucs2tochar; - info.fromoem = (TCFROMOEM)oemtext_chartoucs2; - break; - } -#elif defined(OSLANG_EUC) - switch(textcode) { - case TEXTCNV_DEFAULT: - case TEXTCNV_EUC: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - break; - } -#elif defined(OSLANG_UCS2) - switch(textcode) { - case TEXTCNV_DEFAULT: - case TEXTCNV_SJIS: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - info.tooem = (TCTOOEM)oemtext_chartoucs2; - info.fromoem = (TCFROMOEM)oemtext_ucs2tochar; - break; - - case TEXTCNV_UTF8: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - info.tooem = (TCTOOEM)codecnv_utf8toucs2; - info.fromoem = (TCFROMOEM)codecnv_ucs2toutf8; - break; - - case TEXTCNV_UCS2: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - break; - } -#else // defined(OSLANG_*) - switch(textcode) { - case TEXTCNV_DEFAULT: - info.caps = TEXTCNV_READ | TEXTCNV_WRITE; - break; - } -#endif // defined(OSLANG_*) - if (inf) { - *inf = info; - } - return(info.caps); -} - +#include +#include "oemtext.h" +#include "codecnv/textcnv.h" + + +// Use WinAPI version + +UINT oemtext_mbtoucs2(UINT cp, wchar_t *dst, UINT dcnt, const char *src, UINT scnt) { + + int srccnt; + int dstcnt; + int r; + + if (((SINT)scnt) > 0) { + srccnt = scnt; + } + else { + srccnt = -1; + } + if (((SINT)dcnt) > 0) { + dstcnt = dcnt; + if (srccnt < 0) { + dstcnt = dstcnt - 1; + if (dstcnt == 0) { + if (dst) { + dst[0] = '\0'; + } + return(1); + } + } + } + else { + dstcnt = 0; + } + r = MultiByteToWideChar(cp, MB_PRECOMPOSED, src, srccnt, dst, dstcnt); + if ((r == 0) && (dstcnt != 0)) { + r = dstcnt; + if (srccnt < 0) { + if (dst) { + dst[r] = '\0'; + } + r++; + } + } + return(r); +} + +UINT oemtext_ucs2tomb(UINT cp, char *dst, UINT dcnt, const wchar_t *src, UINT scnt) { + + int srccnt; + int dstcnt; + int r; + + if (((SINT)scnt) > 0) { + srccnt = scnt; + } + else { + srccnt = -1; + } + if (((SINT)dcnt) > 0) { + dstcnt = dcnt; + if (srccnt < 0) { + dstcnt = dstcnt - 1; + if (dstcnt == 0) { + if (dst) { + dst[0] = '\0'; + } + return(1); + } + } + } + else { + dstcnt = 0; + } + r = WideCharToMultiByte(cp, 0, src, srccnt, dst, dstcnt, NULL, NULL); + if ((r == 0) && (dstcnt != 0)) { + r = dstcnt; + if (srccnt < 0) { + if (dst) { + dst[r] = '\0'; + } + r++; + } + } + return(r); +} + +UINT oemtext_mbtoutf8(UINT cp, char *dst, UINT dcnt, const char *src, UINT scnt) { + + UINT leng; + wchar_t *ucs2; + UINT ret; + + (void)scnt; + + leng = MultiByteToWideChar(cp, MB_PRECOMPOSED, src, scnt, NULL, 0); + if (leng == 0) { + return(0); + } + ucs2 = (wchar_t *)_MALLOC(leng * sizeof(wchar_t), ""); + if (ucs2 == NULL) { + return(0); + } + MultiByteToWideChar(cp, MB_PRECOMPOSED, src, scnt, ucs2, leng); + if (((SINT)scnt) < 0) { + leng = (UINT)-1; + } + ret = codecnv_ucs2toutf8(dst, dcnt, (UINT16 *)ucs2, leng); + _MFREE(ucs2); + return(ret); +} + +UINT oemtext_utf8tomb(UINT cp, char *dst, UINT dcnt, const char *src, UINT scnt) { + + UINT leng; + wchar_t *ucs2; + UINT ret; + + (void)scnt; + + leng = codecnv_utf8toucs2(NULL, 0, src, scnt); + if (leng == 0) { + return(0); + } + ucs2 = (wchar_t *)_MALLOC(leng * sizeof(wchar_t), ""); + if (ucs2 == NULL) { + return(0); + } + codecnv_utf8toucs2((UINT16 *)ucs2, leng, src, scnt); + if (((SINT)scnt) < 0) { + leng = (UINT)-1; + } + ret = WideCharToMultiByte(cp, 0, ucs2, leng, dst, dcnt, NULL, NULL); + _MFREE(ucs2); + return(ret); +} + + +// ---- + +UINT oemtext_chartoucs2(wchar_t *dst, UINT dcnt, const char *src, UINT scnt) { + + return(oemtext_mbtoucs2(CP_ACP, dst, dcnt, src, scnt)); +} + +UINT oemtext_ucs2tochar(char *dst, UINT dcnt, const wchar_t *src, UINT scnt) { + + return(oemtext_ucs2tomb(CP_ACP, dst, dcnt, src, scnt)); +} + +UINT oemtext_chartoutf8(char *dst, UINT dcnt, const char *src, UINT scnt) { + + return(oemtext_mbtoutf8(CP_ACP, dst, dcnt, src, scnt)); +} + +UINT oemtext_utf8tochar(char *dst, UINT dcnt, const char *src, UINT scnt) { + + return(oemtext_utf8tomb(CP_ACP, dst, dcnt, src, scnt)); +} + + +// ---- textcnv + +UINT textcnv_getinfo(TCINF *inf, const UINT8 *hdr, UINT hdrsize) { + + UINT textcode; + TCINF info; + + textcode = TEXTCNV_DEFAULT; + ZeroMemory(&info, sizeof(info)); + if ((hdrsize >= 3) && + (hdr[0] == 0xef) && (hdr[1] == 0xbb) && (hdr[2] == 0xbf)) { + // UTF-8 + textcode = TEXTCNV_UTF8; + info.width = 1; + info.hdrsize = 3; + } + else if ((hdrsize >= 2) && (hdr[0] == 0xff) && (hdr[1] == 0xfe)) { + // UCSLE + textcode = TEXTCNV_UCS2; +#if defined(BYTESEX_BIG) + info.xendian = 1; +#endif + info.width = 2; + info.hdrsize = 2; + } + else if ((hdrsize >= 2) && (hdr[0] == 0xfe) && (hdr[1] == 0xff)) { + // UCS2BE + // UCSLE + textcode = TEXTCNV_UCS2; +#if defined(BYTESEX_LITTLE) + info.xendian = 1; +#endif + info.width = 2; + info.hdrsize = 2; + } + else { + info.width = 1; + } + +#if defined(OSLANG_SJIS) + switch(textcode) { + case TEXTCNV_DEFAULT: + case TEXTCNV_SJIS: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + break; + + case TEXTCNV_UTF8: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + info.tooem = (TCTOOEM)oemtext_utf8tochar; + info.fromoem = (TCFROMOEM)oemtext_chartoutf8; + break; + + case TEXTCNV_UCS2: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + info.tooem = (TCTOOEM)oemtext_ucs2tochar; + info.fromoem = (TCFROMOEM)oemtext_chartoucs2; + break; + } +#elif defined(OSLANG_EUC) + switch(textcode) { + case TEXTCNV_DEFAULT: + case TEXTCNV_EUC: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + break; + } +#elif defined(OSLANG_UCS2) + switch(textcode) { + case TEXTCNV_DEFAULT: + case TEXTCNV_SJIS: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + info.tooem = (TCTOOEM)oemtext_chartoucs2; + info.fromoem = (TCFROMOEM)oemtext_ucs2tochar; + break; + + case TEXTCNV_UTF8: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + info.tooem = (TCTOOEM)codecnv_utf8toucs2; + info.fromoem = (TCFROMOEM)codecnv_ucs2toutf8; + break; + + case TEXTCNV_UCS2: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + break; + } +#else // defined(OSLANG_*) + switch(textcode) { + case TEXTCNV_DEFAULT: + info.caps = TEXTCNV_READ | TEXTCNV_WRITE; + break; + } +#endif // defined(OSLANG_*) + if (inf) { + *inf = info; + } + return(info.caps); +} + diff --git a/windows/oemtext.h b/windows/oemtext.h old mode 100755 new mode 100644 index cb64ab5c..62f46ffd --- a/windows/oemtext.h +++ b/windows/oemtext.h @@ -1,32 +1,32 @@ -/** - * @file oemtext.h - * @breif Interface of the text converter - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -UINT oemtext_mbtoucs2(UINT cp, wchar_t *dst, UINT dcnt, const char *src, UINT scnt); -UINT oemtext_ucs2tomb(UINT cp, char *dst, UINT dcnt, const wchar_t *src, UINT scnt); -UINT oemtext_mbtoutf8(UINT cp, char *dst, UINT dcnt, const char *src, UINT scnt); -UINT oemtext_utf8tomb(UINT cp, char *dst, UINT dcnt, const char *src, UINT scnt); - -UINT oemtext_chartoucs2(wchar_t *dst, UINT dcnt, const char *src, UINT scnt); -UINT oemtext_ucs2tochar(char *dst, UINT dcnt, const wchar_t *src, UINT scnt); -UINT oemtext_chartoutf8(char *dst, UINT dcnt, const char *src, UINT scnt); -UINT oemtext_utf8tochar(char *dst, UINT dcnt, const char *src, UINT scnt); - -#ifdef __cplusplus -} -#endif - -#if defined(OSLANG_UTF8) -#define oemtext_sjistooem(a, b, c, d) oemtext_mbtoutf8(932, a, b, c, d) -#define oemtext_oemtosjis(a, b, c, d) oemtext_utf8tomb(932, a, b, c, d) -#endif +/** + * @file oemtext.h + * @breif Interface of the text converter + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +UINT oemtext_mbtoucs2(UINT cp, wchar_t *dst, UINT dcnt, const char *src, UINT scnt); +UINT oemtext_ucs2tomb(UINT cp, char *dst, UINT dcnt, const wchar_t *src, UINT scnt); +UINT oemtext_mbtoutf8(UINT cp, char *dst, UINT dcnt, const char *src, UINT scnt); +UINT oemtext_utf8tomb(UINT cp, char *dst, UINT dcnt, const char *src, UINT scnt); + +UINT oemtext_chartoucs2(wchar_t *dst, UINT dcnt, const char *src, UINT scnt); +UINT oemtext_ucs2tochar(char *dst, UINT dcnt, const wchar_t *src, UINT scnt); +UINT oemtext_chartoutf8(char *dst, UINT dcnt, const char *src, UINT scnt); +UINT oemtext_utf8tochar(char *dst, UINT dcnt, const char *src, UINT scnt); + +#ifdef __cplusplus +} +#endif + +#if defined(OSLANG_UTF8) +#define oemtext_sjistooem(a, b, c, d) oemtext_mbtoutf8(932, a, b, c, d) +#define oemtext_oemtosjis(a, b, c, d) oemtext_utf8tomb(932, a, b, c, d) +#endif diff --git a/windows/readme.txt b/windows/readme.txt old mode 100755 new mode 100644 index 9d0517d8..ce893cca --- a/windows/readme.txt +++ b/windows/readme.txt @@ -1,283 +1,283 @@ - - Neko Project II - NP2 developer team, 1999-2001,2003,2004 - - - -・概要 - -  PC-9801VX21をベースとして、PC-9801シリーズの主要な機能をソフトウェアで -  再現するエミュレータです。 - -  ねこープロジェクトIIが再現するのは PC-9801シリーズの標準的なハードウェアと -  一部のBIOSとCバスデバイスのみです。 -  このため、MS-DOS等は動作しますが、N88-BASICやLIO等のROMを使用するものは -  標準で動作しません。これらを動作させるためには実機より ROMを取得する必要が -  あります。 - - - -・最低動作環境 - -  486DX2以上のプロセッサ -  Microsoft-Windows 4.00(Windows95/NT4) -  DirectX2以上 - -  ・サウンドを再生するには DirectX3以上が必要です。 - -  ・ヘルプを使用するには IE4.01以上が必要です。 -    IE4.01が利用できない場合にはこちらをご覧ください。 -     http://www.yui.ne.jp/np2/help.html - - - -・推奨動作環境 - -  Celeron 300A以降のプロセッサ -  MS-Windows98 / MS-Windows2000 -  DirectX3以上 - - - -・使用方法 - -  ねこープロジェクトIIを使うには フロッピーイメージが必要です。 -  webの情報を基にイメージ化を行なって下さい。 - -  その後 np2.exeを起動します。 - -  フロッピーベースのソフトウェアを起動するには、メニューの -  [FDD1 - Open], [FDD2 - Open]を選択しディスクイメージを挿入した後に -  リセットしてください。 - -  ハードディスクを使用するには [Emulate - Newdisk] より、ハードディスク -  イメージを作成してから [HardDisk - SASI-1 - Open]よりイメージファイルを -  選択したのち、リセットしてください。 -  ハードディスクイメージの使用情報は記憶されますので、イメージファイルを -  変更するしない限りは この操作は必要ありません。 - -  メニューは F11キーでアクティブになります。 -  マウス切替えは F12キー、もしくは マウス中ボタンで行ないます。 - -  CPUは 80286(リアルモードのみ)です。 -  環境を構築する場合、プロテクトモードを扱えない事に注意して下さい。 -  また DIP SW3-8 OFFで V30ぽい動きをするようにしています。 -  CPUスピードは Configureで変更出来ます。 - -  実行し、設定を変えると np2.iniファイルが作成されます。 - - - -・メニュー - -  Emulate -   Reset ハードウェアリセットします。 -   Configure 設定を開きます。 -   NewDisk ブランクディスクイメージを作成します。 -   Font フォントファイルを選択します。 -   Exit ねこープロジェクトIIを終了します。 - -  FDD1 -   Open ドライブ1のディスクイメージを選択します。 -   Eject ドライブ1のディスクイメージを取出します。 - -  FDD2 -   Open ドライブ2のディスクイメージを選択します。 -   Eject ドライブ2のディスクイメージを取出します。 - -  HardDisk -   SASI-1 -    Open SASI-1のハードディスクイメージを選択します。 -    Remove SASI-1を未設続状態に戻します。 -   SASI-2 -    Open SASI-2のハードディスクイメージを選択します。 -    Remove SASI-2を未設続状態に戻します。 - -  Screen -   Window ウィンドウモードになります。 -   FullScreen フルスクリーンモードになります。 -   Normal 画面を回転させません。 -   Left Rotated 画面を左に90度回転させます。 -   Right Rotated 画面を右に90度回転させます。 -   Disp Vsync 描画タイミング (チェックでVsync時) -   Real Palettes パレット更新タイミング (チェックでラスタごと) -   No Wait タイミングを取りません。 -   Auto frame 表示タイミングを自動的に決定します。 -   Full frame 全てのフレームを表示します。 -   1/2 frame 2回に1度描画します。 -   1/3 frame 3回に1度描画します。 -   1/4 frame 4回に1度描画します。 -   Screen option スクリーン設定を開きます。 - -  Device -   Keyboard -    Keyboard テンキーをキーボードとして扱います。 -    JoyKey-1 テンキーをジョイスティック1に割り当てます。 -    JoyKey-2 テンキーをジョイスティック2に割り当てます。 -    mechanical SHIFT ノート風メカニカルシフトにします。 -    mechanical CTRL ノート風メカニカルコントロールにします。 -    mechanical GRPH ノート風メカニカルグラフキーにします。 -    F12 = Mouse F12キーをマウス切替えにアサインします。 -    F12 = Copy F12キーをCopyキーにアサインします。 -    F12 = Stop F12キーをStopキーにアサインします。 -    F12 = tenkey [=] F12キーをテンキーの=キーにアサインします。 -    F12 = tenkey [,] F12キーをテンキーの,キーにアサインします。 -   Sound -    Beep off ビープを無音にします。 -    Beep low ビープ音量を小にします。 -    Beep mid ビープ音量を中にします。 -    Beep high ビープ音量を大にします。 -    Disable boards FM音源ボードを使用しません。 -    PC-9801-14 ミュージックジェネレータボードを使用します。 -    PC-9801-26K PC-9801-26Kボードを使用します。 -    PC-9801-86 PC-9801-86ボードを使用します。 -    PC-9801-26K + 86 PC-9801-26Kと86ボードを使用します。 -    PC-9801-86 + Chibi-oto PC-9801-86ボードとちびおとを使用します。 -    PC-9801-118 PC-9801-118ボードを使用します。 -    Speak board スピークボードを使用します。 -    Spark board スパークボードを使用します。 -    AMD-98 AMD-98を使用します。 -    JAST SOUND JAST SOUNDを使用します。 -    Seek Sound ディスクシークタイミングを取ります。 -   Memory -    640KB メモリをメインメモリのみ使用します。 -    1.6MB メインメモリと拡張メモリ1MBを使用します。 -    3.6MB メインメモリと拡張メモリ3MBを使用します。 -    7.6MB メインメモリと拡張メモリ7MBを使用します。 -   Mouse マウス操作を切替えます。 -   Serial option シリアル設定を開きます。 -   MIDI option MIDI設定を開きます。 -   MIDI panic MIDIを消音します。 -   Sound option サウンド設定を開きます。 - -  Other -   BMP Save エミュレーション中の画面をBMP形式で保存します。 -   S98 logging S98ログを取ります。 -   Calendar カレンダ設定を開きます。 -   Shortcut Key -    ALT+Enter ALT+Enterをスクリーン切替えにアサインします。 -    ALT+F4 ALT+F4をアプリケーション終了にアサインします。 -   Clock Disp クロック数を表示します。 -   Frame Disp フレーム数を表示します。 -   Joy Reverse ジョイスティックのボタンを入れ換えます。 -   Joy Rapid ジョイスティックのボタンを連射状態にします。 -   Mouse Rapid マウスのボタンを連射状態にします。 -   Use SSTP SSTPプロトコルを使用します。 -   Help ヘルプを表示します。 -   About バージョンを表示します。 - - - -・設定ダイアログ - -  Configue -   CPU -    Base Clock CPUのベースクロックを指定します。 -    Multiple CPUのクロック倍率を指定します。 -   Architecture -    PC-9801VM V30以前のCPUを搭載したNEC仕様となります。 -    PC-9801VX i286以降のCPUを搭載したNEC仕様となります。 -    PC-286 EPSON互換機仕様となります。 -   Sound -    Sampling Rate サウンドの出力周波数を指定します。 -    Buffer サウンドのバッファサイズを指定します。 - Disable MMX MMX命令を使用しません。 - Comfirm Dialog リセット/終了時に確認ダイアログを表示します。 - Resume レジューム機能を使用します。 - -  Screen option -   Video -    LCD PC-98ノートの液晶モードになります。 -    Reverse 液晶表示を反転します。 -    Use skipline rev スキップラインを補正します。 -    Ratio スキップラインの明るさを指定します。 -   Chip -    GDC GDCチップを指定します。 -    GRCG GRCGチップを指定します。 -    Enable 16color アナログ16色カラーを有効にします。 -   Timing -    T-RAM テキストRAMアクセスウェイト値を指定します。 -    V-RAM ヴィデオRAMアクセスウェイト値を指定します。 -    GRCG GRCG使用時のアクセスウェイト値を指定します。 -    RealPalettes Adjust RealPalettes時のタイミングを調整します。 - -  Serial option -   COM1 RS-232Cのシリアルポートを指定します。 -   PC-9861K PC-9861Kのディップスイッチを設定します。 -   CH.1 PC-9861Kのチャネル1のポートを指定します。 -   CH.2 PC-9861Kのチャネル2のポートを指定します。 - -  MIDI option - MPU-PC98II MPU-PC98IIのディップスイッチを設定します。 - -  Sound option -   Mixer 各種チップのヴォリュームを設定します。 -   PC-9801-14 PC-9801-14のヴォリュームを設定します。 -   26 PC-9801-26Kのジャンパを設定します。 -   86 PC-9801-86のディップスイッチを設定します。 -   SPB スピークボードのジャンパを設定します。 -   JoyPad ジョイパッドの設定を行います。 - -  Calendar -   Real 常に現実と同じ時刻になります。 -   Virtual Calendar 仮想カレンダーを使用します。 - - - -・ディスクイメージ - -  以下にイメージ対応しています。 -   FDD - D88形式, XDF(ベタイメージ)形式 -   SASI - THD形式(T98), HDI形式(Anex86) -   SCSI - HDD形式(Virtual98) - - - -・キー設定について -  bios.romとかと同じフォルダに(機種によって異なるのでこんな書き方…) -  key.txtという名前でテキストファイルを作成して、キー設定を記入して下さい。 - -  書式) -   [keyname] = [key1] (key2) (key3) -   [keyname] [TAB] [key1] (key2) (key3) -   userkey[1-2] = [key1] (key2) (key3) ... (key15) -    フルキー 0〜9 A〜Z - ^ \ @ [ ] ; : , . / _ -     STOP COPY ESC TAB BS RET SPC XFER NFER - INS DEL RLUP RLDN HMCL HELP -    ファンク F1〜F10 VF1〜VF5 -    テンキー [0]〜[9] [-] [/] [*] [+] [=] [,] [.] -    シフト SHIFT CAPS KANA GRPH CTRL - -   通常キーは3個、userkeyは15個の同時押し設定が可能です。 -   [=] キーは = で区切られてしまうので TABで区切るか [EQU]として下さい。 - -   例: - ----------------------- key.txt - -    W = UP (ダイアモンドキーをカーソルにしてみたり…) -    S = LEFT -    D = RIGHT -    X = DOWN -    [7] = [4] [8] (テンキー斜め同時押しにしてみたり…) -    [9] = [6] [8] -    [1] = [4] [2] -    [3] = [6] [2] -    userkey1 = CTRL XFER (CTRL+XFER FEP切り替え) -    userkey2 = D O A Z (D+O+A+Z 同時押し) - - ----------------------- - - - -・ROMEOについて - -  ROMEOを使用するには、np2.exeと同じフォルダに pcidebug.dllと -  pcidbg95.vxd(Win95/98) / pcidbgnt.sys(WinNT4/2000/XP)を置いて、 -  np2.iniのuseromeoを trueにしてください。 - -  PC-9801-118音源のYMF288部分がROMEOから出力されます。 - - - -                  email: np2@yui.ne.jp -                  webpage: http://www.yui.ne.jp/np2/ + + Neko Project II + NP2 developer team, 1999-2001,2003,2004 + + + +・概要 + +  PC-9801VX21をベースとして、PC-9801シリーズの主要な機能をソフトウェアで +  再現するエミュレータです。 + +  ねこープロジェクトIIが再現するのは PC-9801シリーズの標準的なハードウェアと +  一部のBIOSとCバスデバイスのみです。 +  このため、MS-DOS等は動作しますが、N88-BASICやLIO等のROMを使用するものは +  標準で動作しません。これらを動作させるためには実機より ROMを取得する必要が +  あります。 + + + +・最低動作環境 + +  486DX2以上のプロセッサ +  Microsoft-Windows 4.00(Windows95/NT4) +  DirectX2以上 + +  ・サウンドを再生するには DirectX3以上が必要です。 + +  ・ヘルプを使用するには IE4.01以上が必要です。 +    IE4.01が利用できない場合にはこちらをご覧ください。 +     http://www.yui.ne.jp/np2/help.html + + + +・推奨動作環境 + +  Celeron 300A以降のプロセッサ +  MS-Windows98 / MS-Windows2000 +  DirectX3以上 + + + +・使用方法 + +  ねこープロジェクトIIを使うには フロッピーイメージが必要です。 +  webの情報を基にイメージ化を行なって下さい。 + +  その後 np2.exeを起動します。 + +  フロッピーベースのソフトウェアを起動するには、メニューの +  [FDD1 - Open], [FDD2 - Open]を選択しディスクイメージを挿入した後に +  リセットしてください。 + +  ハードディスクを使用するには [Emulate - Newdisk] より、ハードディスク +  イメージを作成してから [HardDisk - SASI-1 - Open]よりイメージファイルを +  選択したのち、リセットしてください。 +  ハードディスクイメージの使用情報は記憶されますので、イメージファイルを +  変更するしない限りは この操作は必要ありません。 + +  メニューは F11キーでアクティブになります。 +  マウス切替えは F12キー、もしくは マウス中ボタンで行ないます。 + +  CPUは 80286(リアルモードのみ)です。 +  環境を構築する場合、プロテクトモードを扱えない事に注意して下さい。 +  また DIP SW3-8 OFFで V30ぽい動きをするようにしています。 +  CPUスピードは Configureで変更出来ます。 + +  実行し、設定を変えると np2.iniファイルが作成されます。 + + + +・メニュー + +  Emulate +   Reset ハードウェアリセットします。 +   Configure 設定を開きます。 +   NewDisk ブランクディスクイメージを作成します。 +   Font フォントファイルを選択します。 +   Exit ねこープロジェクトIIを終了します。 + +  FDD1 +   Open ドライブ1のディスクイメージを選択します。 +   Eject ドライブ1のディスクイメージを取出します。 + +  FDD2 +   Open ドライブ2のディスクイメージを選択します。 +   Eject ドライブ2のディスクイメージを取出します。 + +  HardDisk +   SASI-1 +    Open SASI-1のハードディスクイメージを選択します。 +    Remove SASI-1を未設続状態に戻します。 +   SASI-2 +    Open SASI-2のハードディスクイメージを選択します。 +    Remove SASI-2を未設続状態に戻します。 + +  Screen +   Window ウィンドウモードになります。 +   FullScreen フルスクリーンモードになります。 +   Normal 画面を回転させません。 +   Left Rotated 画面を左に90度回転させます。 +   Right Rotated 画面を右に90度回転させます。 +   Disp Vsync 描画タイミング (チェックでVsync時) +   Real Palettes パレット更新タイミング (チェックでラスタごと) +   No Wait タイミングを取りません。 +   Auto frame 表示タイミングを自動的に決定します。 +   Full frame 全てのフレームを表示します。 +   1/2 frame 2回に1度描画します。 +   1/3 frame 3回に1度描画します。 +   1/4 frame 4回に1度描画します。 +   Screen option スクリーン設定を開きます。 + +  Device +   Keyboard +    Keyboard テンキーをキーボードとして扱います。 +    JoyKey-1 テンキーをジョイスティック1に割り当てます。 +    JoyKey-2 テンキーをジョイスティック2に割り当てます。 +    mechanical SHIFT ノート風メカニカルシフトにします。 +    mechanical CTRL ノート風メカニカルコントロールにします。 +    mechanical GRPH ノート風メカニカルグラフキーにします。 +    F12 = Mouse F12キーをマウス切替えにアサインします。 +    F12 = Copy F12キーをCopyキーにアサインします。 +    F12 = Stop F12キーをStopキーにアサインします。 +    F12 = tenkey [=] F12キーをテンキーの=キーにアサインします。 +    F12 = tenkey [,] F12キーをテンキーの,キーにアサインします。 +   Sound +    Beep off ビープを無音にします。 +    Beep low ビープ音量を小にします。 +    Beep mid ビープ音量を中にします。 +    Beep high ビープ音量を大にします。 +    Disable boards FM音源ボードを使用しません。 +    PC-9801-14 ミュージックジェネレータボードを使用します。 +    PC-9801-26K PC-9801-26Kボードを使用します。 +    PC-9801-86 PC-9801-86ボードを使用します。 +    PC-9801-26K + 86 PC-9801-26Kと86ボードを使用します。 +    PC-9801-86 + Chibi-oto PC-9801-86ボードとちびおとを使用します。 +    PC-9801-118 PC-9801-118ボードを使用します。 +    Speak board スピークボードを使用します。 +    Spark board スパークボードを使用します。 +    AMD-98 AMD-98を使用します。 +    JAST SOUND JAST SOUNDを使用します。 +    Seek Sound ディスクシークタイミングを取ります。 +   Memory +    640KB メモリをメインメモリのみ使用します。 +    1.6MB メインメモリと拡張メモリ1MBを使用します。 +    3.6MB メインメモリと拡張メモリ3MBを使用します。 +    7.6MB メインメモリと拡張メモリ7MBを使用します。 +   Mouse マウス操作を切替えます。 +   Serial option シリアル設定を開きます。 +   MIDI option MIDI設定を開きます。 +   MIDI panic MIDIを消音します。 +   Sound option サウンド設定を開きます。 + +  Other +   BMP Save エミュレーション中の画面をBMP形式で保存します。 +   S98 logging S98ログを取ります。 +   Calendar カレンダ設定を開きます。 +   Shortcut Key +    ALT+Enter ALT+Enterをスクリーン切替えにアサインします。 +    ALT+F4 ALT+F4をアプリケーション終了にアサインします。 +   Clock Disp クロック数を表示します。 +   Frame Disp フレーム数を表示します。 +   Joy Reverse ジョイスティックのボタンを入れ換えます。 +   Joy Rapid ジョイスティックのボタンを連射状態にします。 +   Mouse Rapid マウスのボタンを連射状態にします。 +   Use SSTP SSTPプロトコルを使用します。 +   Help ヘルプを表示します。 +   About バージョンを表示します。 + + + +・設定ダイアログ + +  Configue +   CPU +    Base Clock CPUのベースクロックを指定します。 +    Multiple CPUのクロック倍率を指定します。 +   Architecture +    PC-9801VM V30以前のCPUを搭載したNEC仕様となります。 +    PC-9801VX i286以降のCPUを搭載したNEC仕様となります。 +    PC-286 EPSON互換機仕様となります。 +   Sound +    Sampling Rate サウンドの出力周波数を指定します。 +    Buffer サウンドのバッファサイズを指定します。 + Disable MMX MMX命令を使用しません。 + Comfirm Dialog リセット/終了時に確認ダイアログを表示します。 + Resume レジューム機能を使用します。 + +  Screen option +   Video +    LCD PC-98ノートの液晶モードになります。 +    Reverse 液晶表示を反転します。 +    Use skipline rev スキップラインを補正します。 +    Ratio スキップラインの明るさを指定します。 +   Chip +    GDC GDCチップを指定します。 +    GRCG GRCGチップを指定します。 +    Enable 16color アナログ16色カラーを有効にします。 +   Timing +    T-RAM テキストRAMアクセスウェイト値を指定します。 +    V-RAM ヴィデオRAMアクセスウェイト値を指定します。 +    GRCG GRCG使用時のアクセスウェイト値を指定します。 +    RealPalettes Adjust RealPalettes時のタイミングを調整します。 + +  Serial option +   COM1 RS-232Cのシリアルポートを指定します。 +   PC-9861K PC-9861Kのディップスイッチを設定します。 +   CH.1 PC-9861Kのチャネル1のポートを指定します。 +   CH.2 PC-9861Kのチャネル2のポートを指定します。 + +  MIDI option + MPU-PC98II MPU-PC98IIのディップスイッチを設定します。 + +  Sound option +   Mixer 各種チップのヴォリュームを設定します。 +   PC-9801-14 PC-9801-14のヴォリュームを設定します。 +   26 PC-9801-26Kのジャンパを設定します。 +   86 PC-9801-86のディップスイッチを設定します。 +   SPB スピークボードのジャンパを設定します。 +   JoyPad ジョイパッドの設定を行います。 + +  Calendar +   Real 常に現実と同じ時刻になります。 +   Virtual Calendar 仮想カレンダーを使用します。 + + + +・ディスクイメージ + +  以下にイメージ対応しています。 +   FDD - D88形式, XDF(ベタイメージ)形式 +   SASI - THD形式(T98), HDI形式(Anex86) +   SCSI - HDD形式(Virtual98) + + + +・キー設定について +  bios.romとかと同じフォルダに(機種によって異なるのでこんな書き方…) +  key.txtという名前でテキストファイルを作成して、キー設定を記入して下さい。 + +  書式) +   [keyname] = [key1] (key2) (key3) +   [keyname] [TAB] [key1] (key2) (key3) +   userkey[1-2] = [key1] (key2) (key3) ... (key15) +    フルキー 0〜9 A〜Z - ^ \ @ [ ] ; : , . / _ +     STOP COPY ESC TAB BS RET SPC XFER NFER + INS DEL RLUP RLDN HMCL HELP +    ファンク F1〜F10 VF1〜VF5 +    テンキー [0]〜[9] [-] [/] [*] [+] [=] [,] [.] +    シフト SHIFT CAPS KANA GRPH CTRL + +   通常キーは3個、userkeyは15個の同時押し設定が可能です。 +   [=] キーは = で区切られてしまうので TABで区切るか [EQU]として下さい。 + +   例: + ----------------------- key.txt + +    W = UP (ダイアモンドキーをカーソルにしてみたり…) +    S = LEFT +    D = RIGHT +    X = DOWN +    [7] = [4] [8] (テンキー斜め同時押しにしてみたり…) +    [9] = [6] [8] +    [1] = [4] [2] +    [3] = [6] [2] +    userkey1 = CTRL XFER (CTRL+XFER FEP切り替え) +    userkey2 = D O A Z (D+O+A+Z 同時押し) + + ----------------------- + + + +・ROMEOについて + +  ROMEOを使用するには、np2.exeと同じフォルダに pcidebug.dllと +  pcidbg95.vxd(Win95/98) / pcidbgnt.sys(WinNT4/2000/XP)を置いて、 +  np2.iniのuseromeoを trueにしてください。 + +  PC-9801-118音源のYMF288部分がROMEOから出力されます。 + + + +                  email: np2@yui.ne.jp +                  webpage: http://www.yui.ne.jp/np2/ diff --git a/windows/recvideo.cpp b/windows/recvideo.cpp old mode 100755 new mode 100644 index 8c28a504..1e4a27cd --- a/windows/recvideo.cpp +++ b/windows/recvideo.cpp @@ -1,390 +1,390 @@ -/*! - * @file revcideo.cpp - * @brief 録画クラスの宣言およびインターフェイスの定義をします - */ - -#include - -#if defined(SUPPORT_RECVIDEO) - -#include "recvideo.h" -#include -#include -#include -#include -#include -#include - -#pragma comment(lib, "vfw32.lib") - -#define VIDEO_WIDTH 640 -#define VIDEO_HEIGHT 400 -#define VIDEO_FPS 30 - -RecodeVideo RecodeVideo::sm_instance; - -/** - * ヘッダー定義 - */ -static const BITMAPINFOHEADER s_bmih = -{ - sizeof(BITMAPINFOHEADER), - VIDEO_WIDTH, VIDEO_HEIGHT, 1, 24, BI_RGB, - VIDEO_WIDTH * VIDEO_HEIGHT * 3, 0, 0, 0, 0 -}; - -// ---- - -/** - * コンストラクタ - */ -RecodeVideo::RecodeVideo() - : m_bEnabled(false) - , m_bDirty(false) - , m_nStep(0) - , m_pWork8(NULL) - , m_pWork24(NULL) - , m_pAvi(NULL) - , m_pStm(NULL) - , m_pStmTmp(NULL) - , m_nFrame(0) -#if defined(AVI_SPLIT_SIZE) - , m_nNumber(0) - , m_dwSize(0) -#endif // defined(AVI_SPLIT_SIZE) -{ - ::AVIFileInit(); - - ZeroMemory(&m_bmih, sizeof(m_bmih)); - ZeroMemory(&m_cv, sizeof(m_cv)); - -#if defined(AVI_SPLIT_SIZE) - ZeroMemory(m_szPath, sizeof(m_szPath)); -#endif // defined(AVI_SPLIT_SIZE) -} - -/** - * デストラクタ - */ -RecodeVideo::~RecodeVideo() -{ - Close(); - ::AVIFileExit(); -} - -/** - * ファイル オープン - * @param[in] lpFilename ファイル名 - * @retval true 成功 - * @retval false 失敗 - */ -bool RecodeVideo::OpenFile(LPCTSTR lpFilename) -{ -#if defined(AVI_SPLIT_SIZE) - if (lpFilename) - { - m_nNumber = 0; - ::file_cpyname(m_szPath, lpFilename, NELEMENTS(m_szPath)); - } - - TCHAR szExt[16]; - ::wsprintf(szExt, _T("_%04d.avi"), m_nNumber); - - TCHAR szPath[MAX_PATH]; - ::file_cpyname(szPath, m_szPath, NELEMENTS(szPath)); - ::file_cutext(szPath); - ::file_catname(szPath, szExt, NELEMENTS(szPath)); - - lpFilename = szPath; -#endif // defined(AVI_SPLIT_SIZE) - - if (::AVIFileOpen(&m_pAvi, lpFilename, OF_CREATE | OF_WRITE | OF_SHARE_DENY_NONE, NULL) != 0) - { - return false; - } - - AVISTREAMINFO si = - { - streamtypeVIDEO, - comptypeDIB, - 0, 0, 0, 0, - 1, VIDEO_FPS, - 0, (DWORD)-1, 0, 0, (DWORD)-1, 0, - {0, 0, VIDEO_WIDTH, VIDEO_HEIGHT}, 0, 0, _T("Video #1") - }; - si.fccHandler = m_cv.fccHandler; - - if (::AVIFileCreateStream(m_pAvi, &m_pStm, &si) != 0) - { - return false; - } - - AVICOMPRESSOPTIONS opt; - opt.fccType = streamtypeVIDEO; - opt.fccHandler = m_cv.fccHandler; - opt.dwKeyFrameEvery = m_cv.lKey; - opt.dwQuality = m_cv.lQ; - opt.dwBytesPerSecond = m_cv.lDataRate; - opt.dwFlags = (m_cv.lDataRate > 0) ? AVICOMPRESSF_DATARATE : 0; - opt.dwFlags |= (m_cv.lKey > 0) ? AVICOMPRESSF_KEYFRAMES : 0; - opt.lpFormat = NULL; - opt.cbFormat = 0; - opt.lpParms = m_cv.lpState; - opt.cbParms = m_cv.cbState; - opt.dwInterleaveEvery = 0; - if (::AVIMakeCompressedStream(&m_pStmTmp, m_pStm, &opt, NULL) != AVIERR_OK) - { - return false; - } - if (::AVIStreamSetFormat(m_pStmTmp, 0, &m_bmih, sizeof(m_bmih)) != 0) - { - return false; - } - - m_bEnabled = true; - - m_bDirty = true; - - m_nFrame = 0; - -#if defined(AVI_SPLIT_SIZE) - m_nNumber++; - m_dwSize = 0; -#endif // defined(AVI_SPLIT_SIZE) - - return true; -} - -/** - * ファイル クローズ - */ -void RecodeVideo::CloseFile() -{ - m_bEnabled = false; - - if (m_pStmTmp) - { - ::AVIStreamRelease(m_pStmTmp); - m_pStmTmp = NULL; - } - if (m_pStm) - { - ::AVIStreamRelease(m_pStm); - m_pStm = NULL; - } - if (m_pAvi) - { - ::AVIFileRelease(m_pAvi); - m_pAvi = NULL; - } -} - -/** - * 開く - * @param[in] hWnd ウィンドウ ハンドル - * @param[in] lpFilename ファイル名 - * @retval true 成功 - * @retval false 失敗 - */ -bool RecodeVideo::Open(HWND hWnd, LPCTSTR lpFilename) -{ - ZeroMemory(&m_cv, sizeof(m_cv)); - m_cv.cbSize = sizeof(m_cv); - m_cv.dwFlags = ICMF_COMPVARS_VALID; - m_cv.fccHandler = comptypeDIB; - m_cv.lQ = ICQUALITY_DEFAULT; - - m_bmih = s_bmih; - if (!::ICCompressorChoose(hWnd, ICMF_CHOOSE_DATARATE | ICMF_CHOOSE_KEYFRAME, &m_bmih, NULL, &m_cv, NULL)) - { - return false; - } - - m_pWork8 = new UINT8 [SURFACE_WIDTH * SURFACE_HEIGHT]; - ZeroMemory(m_pWork8, SURFACE_WIDTH * SURFACE_HEIGHT); - - m_pWork24 = new UINT8 [VIDEO_WIDTH * VIDEO_HEIGHT * 3]; - ZeroMemory(m_pWork24, VIDEO_WIDTH * VIDEO_HEIGHT * 3); - - m_nStep = 0; - - return OpenFile(lpFilename); -} - -/** - * 閉じる - */ -void RecodeVideo::Close() -{ - CloseFile(); - - ::ICCompressorFree(&m_cv); - ZeroMemory(&m_cv, sizeof(m_cv)); - - if (m_pWork8) - { - delete[] m_pWork8; - m_pWork8 = NULL; - } - if (m_pWork24) - { - delete[] m_pWork24; - m_pWork24 = NULL; - } -} - -/** - * フレームを書き込む - */ -void RecodeVideo::Write() -{ - if (!m_bEnabled) - { - return; - } - - while (m_nStep >= 0) - { - UINT8* pBuffer = m_pWork24; - UINT nBufferSize = 0; - DWORD dwFlags = 0; - if (m_bDirty) - { - nBufferSize = VIDEO_WIDTH * VIDEO_HEIGHT * 3; - dwFlags = AVIIF_KEYFRAME; - } - LONG lSize = 0; - if (::AVIStreamWrite(m_pStmTmp, m_nFrame, 1, pBuffer, nBufferSize, dwFlags, NULL, &lSize) != 0) - { - break; - } - m_bDirty = false; - m_nStep -= 21052600 / 8; - m_nFrame++; - -#if defined(AVI_SPLIT_SIZE) - m_dwSize += lSize; - if (m_dwSize >= AVI_SPLIT_SIZE) - { - CloseFile(); - OpenFile(NULL); - } -#endif // defined(AVI_SPLIT_SIZE) - } - m_nStep += 106 * 440 * VIDEO_FPS; -} - -// ---- - -static void screenmix1(UINT8* dest, const UINT8* src1, const UINT8* src2) -{ - for (int i = 0; i < (SURFACE_WIDTH * SURFACE_HEIGHT); i++) - { - dest[i] = src1[i] + src2[i] + NP2PAL_GRPH; - } -} - -static void screenmix2(UINT8* dest, const UINT8* src1, const UINT8* src2) -{ - for (int y = 0; y < (SURFACE_HEIGHT / 2); y++) - { - for (int x1 = 0; x1 < SURFACE_WIDTH; x1++) - { - dest[x1] = src1[x1] + src2[x1] + NP2PAL_GRPH; - } - dest += SURFACE_WIDTH; - src1 += SURFACE_WIDTH; - src2 += SURFACE_WIDTH; - for (int x2 = 0; x2 < SURFACE_WIDTH; x2++) - { - dest[x2] = (src1[x2] >> 4) + NP2PAL_TEXT; - } - dest += SURFACE_WIDTH; - src1 += SURFACE_WIDTH; - src2 += SURFACE_WIDTH; - } -} - -static void screenmix3(UINT8* dest, const UINT8* src1, const UINT8* src2) -{ - for (int y = 0; y < (SURFACE_HEIGHT / 2); y++) - { - // dest == src1, dest == src2 の時があるので… - for (int x = 0; x < SURFACE_WIDTH; x++) - { - UINT8 c = (src1[x + SURFACE_WIDTH]) >> 4; - if (c == 0) - { - c = src2[x] + NP2PAL_SKIP; - } - dest[x + SURFACE_WIDTH] = c; - dest[x] = src1[x] + src2[x] + NP2PAL_GRPH; - } - dest += SURFACE_WIDTH * 2; - src1 += SURFACE_WIDTH * 2; - src2 += SURFACE_WIDTH * 2; - } -} - -/** - * フレームを更新 - */ -void RecodeVideo::Update() -{ - if (!m_bEnabled) - { - return; - } - - void (*fnMix)(UINT8 *dest, const UINT8* src1, const UINT8* src2) = NULL; - if (!(gdc.mode1 & 0x10)) - { - fnMix = screenmix1; - } - else if (!np2cfg.skipline) - { - fnMix = screenmix2; - } - else - { - fnMix = screenmix3; - } - - ZeroMemory(m_pWork8, SURFACE_WIDTH * SURFACE_HEIGHT); - UINT8* p = m_pWork8; - UINT8* q = m_pWork8; - if (gdc.mode1 & 0x80) - { - if (gdcs.textdisp & 0x80) - { - p = np2_tram; - } - if (gdcs.grphdisp & 0x80) - { - q = np2_vram[gdcs.disp]; - } - } - (*fnMix)(m_pWork8, p, q); - - const int nWidth = min(dsync.scrnxmax, VIDEO_WIDTH); - const int nHeight = min(dsync.scrnymax, VIDEO_HEIGHT); - p = m_pWork8; - q = m_pWork24 + (VIDEO_WIDTH * nHeight * 3); - for (int y = 0; y < nHeight; y++) - { - q -= VIDEO_WIDTH * 3; - UINT8* r = q; - for (int x = 0; x < nWidth; x++) - { - const RGB32* pPal = np2_pal32 + p[x]; - r[0] = pPal->p.b; - r[1] = pPal->p.g; - r[2] = pPal->p.r; - r += 3; - } - p += SURFACE_WIDTH; - } - m_bDirty = true; -} - -#endif // defined(SUPPORT_RECVIDEO) +/*! + * @file revcideo.cpp + * @brief 録画クラスの宣言およびインターフェイスの定義をします + */ + +#include + +#if defined(SUPPORT_RECVIDEO) + +#include "recvideo.h" +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "vfw32.lib") + +#define VIDEO_WIDTH 640 +#define VIDEO_HEIGHT 400 +#define VIDEO_FPS 30 + +RecodeVideo RecodeVideo::sm_instance; + +/** + * ヘッダー定義 + */ +static const BITMAPINFOHEADER s_bmih = +{ + sizeof(BITMAPINFOHEADER), + VIDEO_WIDTH, VIDEO_HEIGHT, 1, 24, BI_RGB, + VIDEO_WIDTH * VIDEO_HEIGHT * 3, 0, 0, 0, 0 +}; + +// ---- + +/** + * コンストラクタ + */ +RecodeVideo::RecodeVideo() + : m_bEnabled(false) + , m_bDirty(false) + , m_nStep(0) + , m_pWork8(NULL) + , m_pWork24(NULL) + , m_pAvi(NULL) + , m_pStm(NULL) + , m_pStmTmp(NULL) + , m_nFrame(0) +#if defined(AVI_SPLIT_SIZE) + , m_nNumber(0) + , m_dwSize(0) +#endif // defined(AVI_SPLIT_SIZE) +{ + ::AVIFileInit(); + + ZeroMemory(&m_bmih, sizeof(m_bmih)); + ZeroMemory(&m_cv, sizeof(m_cv)); + +#if defined(AVI_SPLIT_SIZE) + ZeroMemory(m_szPath, sizeof(m_szPath)); +#endif // defined(AVI_SPLIT_SIZE) +} + +/** + * デストラクタ + */ +RecodeVideo::~RecodeVideo() +{ + Close(); + ::AVIFileExit(); +} + +/** + * ファイル オープン + * @param[in] lpFilename ファイル名 + * @retval true 成功 + * @retval false 失敗 + */ +bool RecodeVideo::OpenFile(LPCTSTR lpFilename) +{ +#if defined(AVI_SPLIT_SIZE) + if (lpFilename) + { + m_nNumber = 0; + ::file_cpyname(m_szPath, lpFilename, NELEMENTS(m_szPath)); + } + + TCHAR szExt[16]; + ::wsprintf(szExt, _T("_%04d.avi"), m_nNumber); + + TCHAR szPath[MAX_PATH]; + ::file_cpyname(szPath, m_szPath, NELEMENTS(szPath)); + ::file_cutext(szPath); + ::file_catname(szPath, szExt, NELEMENTS(szPath)); + + lpFilename = szPath; +#endif // defined(AVI_SPLIT_SIZE) + + if (::AVIFileOpen(&m_pAvi, lpFilename, OF_CREATE | OF_WRITE | OF_SHARE_DENY_NONE, NULL) != 0) + { + return false; + } + + AVISTREAMINFO si = + { + streamtypeVIDEO, + comptypeDIB, + 0, 0, 0, 0, + 1, VIDEO_FPS, + 0, (DWORD)-1, 0, 0, (DWORD)-1, 0, + {0, 0, VIDEO_WIDTH, VIDEO_HEIGHT}, 0, 0, _T("Video #1") + }; + si.fccHandler = m_cv.fccHandler; + + if (::AVIFileCreateStream(m_pAvi, &m_pStm, &si) != 0) + { + return false; + } + + AVICOMPRESSOPTIONS opt; + opt.fccType = streamtypeVIDEO; + opt.fccHandler = m_cv.fccHandler; + opt.dwKeyFrameEvery = m_cv.lKey; + opt.dwQuality = m_cv.lQ; + opt.dwBytesPerSecond = m_cv.lDataRate; + opt.dwFlags = (m_cv.lDataRate > 0) ? AVICOMPRESSF_DATARATE : 0; + opt.dwFlags |= (m_cv.lKey > 0) ? AVICOMPRESSF_KEYFRAMES : 0; + opt.lpFormat = NULL; + opt.cbFormat = 0; + opt.lpParms = m_cv.lpState; + opt.cbParms = m_cv.cbState; + opt.dwInterleaveEvery = 0; + if (::AVIMakeCompressedStream(&m_pStmTmp, m_pStm, &opt, NULL) != AVIERR_OK) + { + return false; + } + if (::AVIStreamSetFormat(m_pStmTmp, 0, &m_bmih, sizeof(m_bmih)) != 0) + { + return false; + } + + m_bEnabled = true; + + m_bDirty = true; + + m_nFrame = 0; + +#if defined(AVI_SPLIT_SIZE) + m_nNumber++; + m_dwSize = 0; +#endif // defined(AVI_SPLIT_SIZE) + + return true; +} + +/** + * ファイル クローズ + */ +void RecodeVideo::CloseFile() +{ + m_bEnabled = false; + + if (m_pStmTmp) + { + ::AVIStreamRelease(m_pStmTmp); + m_pStmTmp = NULL; + } + if (m_pStm) + { + ::AVIStreamRelease(m_pStm); + m_pStm = NULL; + } + if (m_pAvi) + { + ::AVIFileRelease(m_pAvi); + m_pAvi = NULL; + } +} + +/** + * 開く + * @param[in] hWnd ウィンドウ ハンドル + * @param[in] lpFilename ファイル名 + * @retval true 成功 + * @retval false 失敗 + */ +bool RecodeVideo::Open(HWND hWnd, LPCTSTR lpFilename) +{ + ZeroMemory(&m_cv, sizeof(m_cv)); + m_cv.cbSize = sizeof(m_cv); + m_cv.dwFlags = ICMF_COMPVARS_VALID; + m_cv.fccHandler = comptypeDIB; + m_cv.lQ = ICQUALITY_DEFAULT; + + m_bmih = s_bmih; + if (!::ICCompressorChoose(hWnd, ICMF_CHOOSE_DATARATE | ICMF_CHOOSE_KEYFRAME, &m_bmih, NULL, &m_cv, NULL)) + { + return false; + } + + m_pWork8 = new UINT8 [SURFACE_WIDTH * SURFACE_HEIGHT]; + ZeroMemory(m_pWork8, SURFACE_WIDTH * SURFACE_HEIGHT); + + m_pWork24 = new UINT8 [VIDEO_WIDTH * VIDEO_HEIGHT * 3]; + ZeroMemory(m_pWork24, VIDEO_WIDTH * VIDEO_HEIGHT * 3); + + m_nStep = 0; + + return OpenFile(lpFilename); +} + +/** + * 閉じる + */ +void RecodeVideo::Close() +{ + CloseFile(); + + ::ICCompressorFree(&m_cv); + ZeroMemory(&m_cv, sizeof(m_cv)); + + if (m_pWork8) + { + delete[] m_pWork8; + m_pWork8 = NULL; + } + if (m_pWork24) + { + delete[] m_pWork24; + m_pWork24 = NULL; + } +} + +/** + * フレームを書き込む + */ +void RecodeVideo::Write() +{ + if (!m_bEnabled) + { + return; + } + + while (m_nStep >= 0) + { + UINT8* pBuffer = m_pWork24; + UINT nBufferSize = 0; + DWORD dwFlags = 0; + if (m_bDirty) + { + nBufferSize = VIDEO_WIDTH * VIDEO_HEIGHT * 3; + dwFlags = AVIIF_KEYFRAME; + } + LONG lSize = 0; + if (::AVIStreamWrite(m_pStmTmp, m_nFrame, 1, pBuffer, nBufferSize, dwFlags, NULL, &lSize) != 0) + { + break; + } + m_bDirty = false; + m_nStep -= 21052600 / 8; + m_nFrame++; + +#if defined(AVI_SPLIT_SIZE) + m_dwSize += lSize; + if (m_dwSize >= AVI_SPLIT_SIZE) + { + CloseFile(); + OpenFile(NULL); + } +#endif // defined(AVI_SPLIT_SIZE) + } + m_nStep += 106 * 440 * VIDEO_FPS; +} + +// ---- + +static void screenmix1(UINT8* dest, const UINT8* src1, const UINT8* src2) +{ + for (int i = 0; i < (SURFACE_WIDTH * SURFACE_HEIGHT); i++) + { + dest[i] = src1[i] + src2[i] + NP2PAL_GRPH; + } +} + +static void screenmix2(UINT8* dest, const UINT8* src1, const UINT8* src2) +{ + for (int y = 0; y < (SURFACE_HEIGHT / 2); y++) + { + for (int x1 = 0; x1 < SURFACE_WIDTH; x1++) + { + dest[x1] = src1[x1] + src2[x1] + NP2PAL_GRPH; + } + dest += SURFACE_WIDTH; + src1 += SURFACE_WIDTH; + src2 += SURFACE_WIDTH; + for (int x2 = 0; x2 < SURFACE_WIDTH; x2++) + { + dest[x2] = (src1[x2] >> 4) + NP2PAL_TEXT; + } + dest += SURFACE_WIDTH; + src1 += SURFACE_WIDTH; + src2 += SURFACE_WIDTH; + } +} + +static void screenmix3(UINT8* dest, const UINT8* src1, const UINT8* src2) +{ + for (int y = 0; y < (SURFACE_HEIGHT / 2); y++) + { + // dest == src1, dest == src2 の時があるので… + for (int x = 0; x < SURFACE_WIDTH; x++) + { + UINT8 c = (src1[x + SURFACE_WIDTH]) >> 4; + if (c == 0) + { + c = src2[x] + NP2PAL_SKIP; + } + dest[x + SURFACE_WIDTH] = c; + dest[x] = src1[x] + src2[x] + NP2PAL_GRPH; + } + dest += SURFACE_WIDTH * 2; + src1 += SURFACE_WIDTH * 2; + src2 += SURFACE_WIDTH * 2; + } +} + +/** + * フレームを更新 + */ +void RecodeVideo::Update() +{ + if (!m_bEnabled) + { + return; + } + + void (*fnMix)(UINT8 *dest, const UINT8* src1, const UINT8* src2) = NULL; + if (!(gdc.mode1 & 0x10)) + { + fnMix = screenmix1; + } + else if (!np2cfg.skipline) + { + fnMix = screenmix2; + } + else + { + fnMix = screenmix3; + } + + ZeroMemory(m_pWork8, SURFACE_WIDTH * SURFACE_HEIGHT); + UINT8* p = m_pWork8; + UINT8* q = m_pWork8; + if (gdc.mode1 & 0x80) + { + if (gdcs.textdisp & 0x80) + { + p = np2_tram; + } + if (gdcs.grphdisp & 0x80) + { + q = np2_vram[gdcs.disp]; + } + } + (*fnMix)(m_pWork8, p, q); + + const int nWidth = min(dsync.scrnxmax, VIDEO_WIDTH); + const int nHeight = min(dsync.scrnymax, VIDEO_HEIGHT); + p = m_pWork8; + q = m_pWork24 + (VIDEO_WIDTH * nHeight * 3); + for (int y = 0; y < nHeight; y++) + { + q -= VIDEO_WIDTH * 3; + UINT8* r = q; + for (int x = 0; x < nWidth; x++) + { + const RGB32* pPal = np2_pal32 + p[x]; + r[0] = pPal->p.b; + r[1] = pPal->p.g; + r[2] = pPal->p.r; + r += 3; + } + p += SURFACE_WIDTH; + } + m_bDirty = true; +} + +#endif // defined(SUPPORT_RECVIDEO) diff --git a/windows/recvideo.h b/windows/recvideo.h old mode 100755 new mode 100644 index 8032f78c..980ef116 --- a/windows/recvideo.h +++ b/windows/recvideo.h @@ -1,91 +1,91 @@ -/** - * @file recvideo.h - * @brief 録画クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#if defined(SUPPORT_RECVIDEO) - -#include - -// #define AVI_SPLIT_SIZE (1024 * 1024 * 1024) /**< 分割サイズ */ - -/** - * @brief 録画クラス - */ -class RecodeVideo -{ -public: - static RecodeVideo& GetInstance(); - - RecodeVideo(); - ~RecodeVideo(); - bool Open(HWND hWnd, LPCTSTR lpFilename); - void Close(); - void Write(); - void Update(); - bool IsEnabled() const; - -private: - static RecodeVideo sm_instance; /**< 唯一のインスタンスです */ - - bool m_bEnabled; /**< 有効フラグ */ - bool m_bDirty; /**< ダーティ フラグ */ - - int m_nStep; /**< クロック */ - UINT8* m_pWork8; /**< ワーク */ - UINT8* m_pWork24; /**< ワーク */ - - PAVIFILE m_pAvi; /**< AVIFILE */ - PAVISTREAM m_pStm; /**< AVISTREAM */ - PAVISTREAM m_pStmTmp; /**< AVISTREAM */ - UINT m_nFrame; /**< フレーム数 */ - - BITMAPINFOHEADER m_bmih; /**< BITMAPINFOHEADER */ - COMPVARS m_cv; /**< COMPVARS */ - -#if defined(AVI_SPLIT_SIZE) - int m_nNumber; /**< ファイル番号 */ - DWORD m_dwSize; /**< サイズ */ - TCHAR m_szPath[MAX_PATH]; /**< ベース パス */ -#endif // defined(AVI_SPLIT_SIZE) - - bool OpenFile(LPCTSTR lpFilename); - void CloseFile(); -}; - -/** - * インスタンスを得る - * @return インスタンス - */ -inline RecodeVideo& RecodeVideo::GetInstance() -{ - return sm_instance; -} - -/** - * 有効? - * @retval true 有効 - * @retval false 無効 - */ -inline bool RecodeVideo::IsEnabled() const -{ - return m_bEnabled; -} - -#define recvideo_open RecodeVideo::GetInstance().Open -#define recvideo_close RecodeVideo::GetInstance().Close -#define recvideo_write RecodeVideo::GetInstance().Write -#define recvideo_update RecodeVideo::GetInstance().Update -#define recvideo_isEnabled RecodeVideo::GetInstance().IsEnabled - -#else // defined(SUPPORT_RECVIDEO) - -static inline bool recvideo_open(HWND hWnd, LPCTSTR f) { return false; } -static inline void recvideo_close() { } -static inline void recvideo_write() { } -static inline void recvideo_update() { } -static inline bool recvideo_isEnabled() { return false; } - -#endif // defined(SUPPORT_RECVIDEO) +/** + * @file recvideo.h + * @brief 録画クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#if defined(SUPPORT_RECVIDEO) + +#include + +// #define AVI_SPLIT_SIZE (1024 * 1024 * 1024) /**< 分割サイズ */ + +/** + * @brief 録画クラス + */ +class RecodeVideo +{ +public: + static RecodeVideo& GetInstance(); + + RecodeVideo(); + ~RecodeVideo(); + bool Open(HWND hWnd, LPCTSTR lpFilename); + void Close(); + void Write(); + void Update(); + bool IsEnabled() const; + +private: + static RecodeVideo sm_instance; /**< 唯一のインスタンスです */ + + bool m_bEnabled; /**< 有効フラグ */ + bool m_bDirty; /**< ダーティ フラグ */ + + int m_nStep; /**< クロック */ + UINT8* m_pWork8; /**< ワーク */ + UINT8* m_pWork24; /**< ワーク */ + + PAVIFILE m_pAvi; /**< AVIFILE */ + PAVISTREAM m_pStm; /**< AVISTREAM */ + PAVISTREAM m_pStmTmp; /**< AVISTREAM */ + UINT m_nFrame; /**< フレーム数 */ + + BITMAPINFOHEADER m_bmih; /**< BITMAPINFOHEADER */ + COMPVARS m_cv; /**< COMPVARS */ + +#if defined(AVI_SPLIT_SIZE) + int m_nNumber; /**< ファイル番号 */ + DWORD m_dwSize; /**< サイズ */ + TCHAR m_szPath[MAX_PATH]; /**< ベース パス */ +#endif // defined(AVI_SPLIT_SIZE) + + bool OpenFile(LPCTSTR lpFilename); + void CloseFile(); +}; + +/** + * インスタンスを得る + * @return インスタンス + */ +inline RecodeVideo& RecodeVideo::GetInstance() +{ + return sm_instance; +} + +/** + * 有効? + * @retval true 有効 + * @retval false 無効 + */ +inline bool RecodeVideo::IsEnabled() const +{ + return m_bEnabled; +} + +#define recvideo_open RecodeVideo::GetInstance().Open +#define recvideo_close RecodeVideo::GetInstance().Close +#define recvideo_write RecodeVideo::GetInstance().Write +#define recvideo_update RecodeVideo::GetInstance().Update +#define recvideo_isEnabled RecodeVideo::GetInstance().IsEnabled + +#else // defined(SUPPORT_RECVIDEO) + +static inline bool recvideo_open(HWND hWnd, LPCTSTR f) { return false; } +static inline void recvideo_close() { } +static inline void recvideo_write() { } +static inline void recvideo_update() { } +static inline bool recvideo_isEnabled() { return false; } + +#endif // defined(SUPPORT_RECVIDEO) diff --git a/windows/resource.h b/windows/resource.h index eae03b4b..a570da37 100644 --- a/windows/resource.h +++ b/windows/resource.h @@ -1,870 +1,870 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by H:\projects\vcp\np21w-0.86\win9x\resources\932\np2.rc -// -#define IDR_MANIFEST 1 -#define IRT_MANIFEST 24 -#define IDI_ICON1 101 -#define IDI_ICON2 102 -#define IDI_ICON3 103 -#define IDD_CONFIG 111 -#define IDD_NEWDISK 121 -#define IDD_NEWHDDDISK 122 -#define IDD_NEWSASI 123 -#define IDD_NEWDISK2 124 -#define IDD_NEWHDDPROC 125 -#define IDD_SCROPT1 131 -#define IDD_SCROPT_FULLSCREEN 132 -#define IDD_SCROPT2 133 -#define IDD_SCROPT3 134 -#define IDD_SCROPT_RENDERER 135 -#define IDD_SERIAL1 141 -#define IDD_PC9861A 142 -#define IDD_MPUPC98 151 -#define IDD_SNDMIX 152 -#define IDD_SND14 153 -#define IDD_SND26 154 -#define IDD_SND86 155 -#define IDD_SNDSPB 156 -#define IDD_SNDPAD1 157 -#define IDD_SNDFMGEN 158 -#define IDD_SND118 159 -#define IDD_SNDWSS 160 -#define IDD_CALENDAR 161 -#define IDD_SNDSB16 162 -#define IDD_SMPU98 163 -#define IDD_ABOUT 171 -#define IDD_BMS 172 -#define IDD_LGY98 180 -#define IDD_NETWORK 181 -#define IDD_GD5430 190 -#define IDD_WAB 191 -#define IDD_PCI 197 -#define IDD_HOSTDRV 198 -#define IDD_IDE 199 -#define IDR_SYS 201 -#define IDR_SYSKEYDISP 202 -#define IDR_SYSSOFTKBD 203 -#define IDR_SYSDEBUG32 204 -#define IDR_SYSDEBUG 205 -#define IDR_MAIN 211 -#define IDR_STAT 212 -#define IDR_DEBUGSS 213 -#define IDR_FDD1MENU 221 -#define IDR_FDD2MENU 222 -#define IDR_FDD3MENU 223 -#define IDR_FDD4MENU 224 -#define IDR_IDEMENU 231 -#define IDR_SASIMENU 232 -#define IDR_SCSIMENU 233 -#define IDR_PXMENU 241 -#define IDR_WAVEREC 251 -#define IDR_CPUSAVE16 252 -#define IDR_CPUSAVE32 253 -#define IDR_CLOSE 301 -#define IDR_TOOLWIN 311 -#define IDR_KEYDISP 321 -#define IDR_VIEW 331 -#define IDR_TRACE 341 -#define IDR_COPYPASTEPOPUP 351 -#define IDR_WABSYSMENU 361 -#define IDR_IDE 400 -#define RESOURCE_VERSION 830 -#define IDC_BASECLOCK 11101 -#define IDC_MULTIPLE 11102 -#define IDC_CLOCKMSG 11103 -#define IDC_MODELVM 11104 -#define IDC_MODELVX 11105 -#define IDC_MODELEPSON 11106 -#define IDC_MODEL21 11107 -#define IDC_CPU_TYPE 11109 -#define IDC_SOUND_BUFFER 11110 -#define IDC_ALLOWRESIZE 11111 -#define IDC_DISABLEMMX 11112 -#define IDC_COMFIRM 11113 -#define IDC_RESUME 11114 -#define IDC_SOUND_RATE 11115 -#define IDC_SOUND_DEVICE_TYPE 11116 -#define IDC_SOUND_DEVICE_NAME 11117 -#define IDC_SAVEWINDOWSIZE 11118 -#define IDC_DISKLABEL 12101 -#define IDC_MAKE2DD 12102 -#define IDC_MAKE2HD 12103 -#define IDC_MAKE144 12104 -#define IDC_HDDSIZE 12201 -#define IDC_HDDLIMIT 12202 -#define IDC_HDDADVANCED 12203 -#define IDC_HDDADVANCED_C 12204 -#define IDC_HDDADVANCED_H 12205 -#define IDC_HDDADVANCED_S 12206 -#define IDC_HDDADVANCED_SS 12207 -#define IDC_HDDADVANCED_FIXSIZE 12210 -#define IDC_HDDADVANCED_DYNSIZE 12211 -#define IDC_HDDADVANCED_BLANK 12212 -#define IDC_HDDCREATE_PROGRESS 12290 -#define IDC_HDDCREATE_VAL 12291 -#define IDC_NEWSASI5MB 12301 -#define IDC_NEWSASI10MB 12302 -#define IDC_NEWSASI15MB 12303 -#define IDC_NEWSASI20MB 12304 -#define IDC_NEWSASI30MB 12305 -#define IDC_NEWSASI40MB 12306 -#define IDC_LCD 13101 -#define IDC_LCDX 13102 -#define IDC_SKIPLINE 13103 -#define IDC_SKIPLIGHT 13104 -#define IDC_LIGHTSTR 13105 -#define IDC_SOFTWARERENDERING 13106 -#define IDC_1DOTTEXTSCRSHIFT 13107 -#define IDC_FULLSCREEN_SAMEBPP 13201 -#define IDC_FULLSCREEN_SAMERES 13202 -#define IDC_FULLSCREEN_ZOOM 13203 -#define IDC_RENDERER_TYPE 13210 -#define IDC_RENDERER_IMODE 13211 -#define IDC_RENDERER_EXCLUSIVE 13212 -#define IDC_GDC7220 13301 -#define IDC_GDC72020 13302 -#define IDC_GCBOX 13303 -#define IDC_GRCGNON 13304 -#define IDC_GRCG 13305 -#define IDC_GRCG2 13306 -#define IDC_EGC 13307 -#define IDC_PC980124 13308 -#define IDC_PEGC 13309 -#define IDC_TRAMWAIT 13401 -#define IDC_TRAMSTR 13402 -#define IDC_VRAMWAIT 13403 -#define IDC_VRAMSTR 13404 -#define IDC_GRCGWAIT 13405 -#define IDC_GRCGSTR 13406 -#define IDC_REALPAL 13407 -#define IDC_REALPALSTR 13408 -#define IDC_COM1PORT 14101 -#define IDC_COM1STR00 14102 -#define IDC_COM1STR01 14103 -#define IDC_COM1STR02 14104 -#define IDC_COM1STR03 14105 -#define IDC_COM1STR04 14106 -#define IDC_COM1STR05 14107 -#define IDC_COM1STR06 14108 -#define IDC_COM1STR07 14109 -#define IDC_COM1SPEED 14110 -#define IDC_COM1CHARSIZE 14111 -#define IDC_COM1PARITY 14112 -#define IDC_COM1STOPBIT 14113 -#define IDC_COM1STR10 14114 -#define IDC_COM1STR11 14115 -#define IDC_COM1STR12 14116 -#define IDC_COM1MMAP 14117 -#define IDC_COM1MMDL 14118 -#define IDC_COM1DEFE 14119 -#define IDC_COM1DEFF 14120 -#define IDC_COM1DEFB 14121 -#define IDC_COM1PENTABFA 14122 -#define IDC_COM1FSPEED 14123 -#define IDC_COM1STR30 14124 -#define IDC_COM1STR31 14125 -#define IDC_COM1PIPENAME 14126 -#define IDC_COM1PIPESERV 14127 -#define IDC_COM1STR32 14128 -#define IDC_COM1DSRCHECK 14129 -#define IDC_PC9861E 14201 -#define IDC_CH1SPEED 14202 -#define IDC_CH1INT 14203 -#define IDC_CH1MODE 14204 -#define IDC_CH2SPEED 14205 -#define IDC_CH2INT 14206 -#define IDC_CH2MODE 14207 -#define IDC_PC9861DIP 14208 -#define IDC_MPUIO 15101 -#define IDC_MPUINT 15102 -#define IDC_MPUDEF 15103 -#define IDC_MPUDIP 15104 -#define IDC_MPU98MMDL 15105 -#define IDC_MPU98MMAP 15106 -#define IDC_MPU98DEFE 15107 -#define IDC_MPU98DEFF 15108 -#define IDC_MPU98DEFB 15109 -#define IDC_MPU98MDIN 15110 -#define IDC_MPU98MMDL_B 15111 -#define IDC_MPU98MMAP_B 15112 -#define IDC_MPU98DEFE_B 15113 -#define IDC_MPU98DEFF_B 15114 -#define IDC_MPU98DEFB_B 15115 -#define IDC_MPU98MDIN_B 15116 -#define IDC_MPUENABLE 15117 -#define IDC_MPUMUTEB 15118 -#define IDC_VOLFM 15201 -#define IDC_VOLFMSTR 15202 -#define IDC_VOLPSG 15203 -#define IDC_VOLPSGSTR 15204 -#define IDC_VOLADPCM 15205 -#define IDC_VOLADPCMSTR 15206 -#define IDC_VOLPCM 15207 -#define IDC_VOLPCMSTR 15208 -#define IDC_VOLRHYTHM 15209 -#define IDC_VOLRHYTHMSTR 15210 -#define IDC_SNDMIXDEF 15211 -#define IDC_SNDMIXDEF2 15212 -#define IDC_VOLMASTER 15213 -#define IDC_VOLMASTERSTR 15214 -#define IDC_VOLCDDA 15220 -#define IDC_VOLCDDASTR 15221 -#define IDC_VOLMIDI 15222 -#define IDC_VOLMIDISTR 15223 -#define IDC_VOLHW 15224 -#define IDC_VOLHWSTR 15225 -#define IDC_VOL14L 15301 -#define IDC_VOL14LSTR 15302 -#define IDC_VOL14R 15303 -#define IDC_VOL14RSTR 15304 -#define IDC_VOLF2 15305 -#define IDC_VOLF2STR 15306 -#define IDC_VOLF4 15307 -#define IDC_VOLF4STR 15308 -#define IDC_VOLF8 15309 -#define IDC_VOLF8STR 15310 -#define IDC_VOLF16 15311 -#define IDC_VOLF16STR 15312 -#define IDC_SND26IO 15401 -#define IDC_SND26INT 15402 -#define IDC_SND26ROM 15403 -#define IDC_SND26JMP 15404 -#define IDC_SND26DEF 15405 -#define IDC_SND86IO 15501 -#define IDC_SND86INT 15502 -#define IDC_SND86INTA 15503 -#define IDC_SND86ID 15504 -#define IDC_SND86ROM 15505 -#define IDC_SND86DIP 15506 -#define IDC_SND86DEF 15507 -#define IDC_SND118IO 15551 -#define IDC_SND118ID 15502 -#define IDC_SND118DMA 15553 -#define IDC_SND118INTF 15554 -#define IDC_SND118INTP 15555 -#define IDC_SND118INTM 15556 -#define IDC_SND118DEF 15557 -#define IDC_SND118ROM 15558 -#define IDC_SND118JMP 15559 -#define IDC_SPBIO 15601 -#define IDC_SPBINT 15602 -#define IDC_SPBROM 15603 -#define IDC_SPBJMP 15604 -#define IDC_SPBDEF 15605 -#define IDC_SPBVRL 15606 -#define IDC_SPBVRR 15607 -#define IDC_SPBVRLEVEL 15608 -#define IDC_SPBREVERSE 15609 -#define IDC_JOYPAD1 15701 -#define IDC_PAD1_1A 15702 -#define IDC_PAD1_1B 15703 -#define IDC_PAD1_1C 15704 -#define IDC_PAD1_1D 15705 -#define IDC_PAD1_2A 15706 -#define IDC_PAD1_2B 15707 -#define IDC_PAD1_2C 15708 -#define IDC_PAD1_2D 15709 -#define IDC_PAD1_RA 15710 -#define IDC_PAD1_RB 15711 -#define IDC_PAD1_RC 15712 -#define IDC_PAD1_RD 15713 -#define IDC_PAD1_ID 15714 -#define IDC_USEFMGEN 15801 -#define IDC_CLNDREAL 16101 -#define IDC_CLNDVIR 16102 -#define IDC_VIRYEAR 16103 -#define IDC_VIRMONTH 16104 -#define IDC_VIRDAY 16105 -#define IDC_VIRHOUR 16106 -#define IDC_VIRMINUTE 16107 -#define IDC_VIRSECOND 16108 -#define IDC_SETNOW 16109 -#define IDC_NP2ICON 17101 -#define IDC_NP2VER 17102 -#define IDC_MORE 17103 -#define IDC_NP2INFO 17104 -#define IDC_NP2STR 17105 -#define IDC_BMSIO 17209 -#define IDC_BMS 17210 -#define IDC_BMSIOBANK 17210 -#define IDC_BMSBANKS 17211 -#define IDC_TOOL_HDDACC 18001 -#define IDC_TOOL_FDD1ACC 18002 -#define IDC_TOOL_FDD1LIST 18003 -#define IDC_TOOL_FDD1BROWSE 18004 -#define IDC_TOOL_FDD1EJECT 18005 -#define IDC_TOOL_FDD2ACC 18006 -#define IDC_TOOL_FDD2LIST 18007 -#define IDC_TOOL_FDD2BROWSE 18008 -#define IDC_TOOL_FDD2EJECT 18009 -#define IDC_TOOL_RESET 18010 -#define IDC_TOOL_POWER 18011 -#define IDC_LGY98ENABLED 19001 -#define IDC_LGY98IO 19002 -#define IDC_LGY98INT 19003 -#define IDC_NETTAP 19004 -#define IDC_LGY98DEF 19005 -#define IDC_NETPMM 19006 -#define IDC_GD5430ENABLED 19011 -#define IDC_GD5430TYPE 19012 -#define IDC_GD5430DEF 19013 -#define IDC_WABASWITCH 19014 -#define IDC_WABMULTIWIN 19015 -#define IDC_WABMULTHREAD 19016 -#define IDC_GD5430FAKECURSOR 19017 -#define IDC_PCIENABLE 19070 -#define IDC_PCIPCMCTYPE 19071 -#define IDC_PCIBIOS32 19072 -#define IDC_HOSTDRVENABLE 19090 -#define IDC_HOSTDRVDIR 19091 -#define IDC_HOSTDRVREAD 19092 -#define IDC_HOSTDRVWRITE 19093 -#define IDC_HOSTDRVDELETE 19094 -#define IDC_HOSTDRVBROWSE 19099 -#define IDC_IDE1TYPE 19100 -#define IDC_IDE2TYPE 19101 -#define IDC_IDE3TYPE 19102 -#define IDC_IDE4TYPE 19103 -#define IDC_IDEWWAIT 19104 -#define IDC_SPINIDEWWAIT 19105 -#define IDC_IDERWAIT 19106 -#define IDC_SPINIDERWAIT 19107 -#define IDC_USEIDEBIOS 19108 -#define IDC_AUTOIDEBIOS 19109 -#define IDC_USEASYNCCD 19110 -#define IDC_ALLOWCDTRAYOP 19111 -#define IDC_USECDECC 19112 -#define IDS_APP_NAME2 30001 -#define IDS_APP_NAME21 30002 -#define IDS_FILENAME_HELP 30003 -#define IDS_FONTFACE 30011 -#define IDS_PFONTFACE 30012 -#define IDS_FONTFACE_PRIMARY 30013 -#define IDS_PFONTFACE_PRIMARY 30014 -#define IDS_FONTFACE_SECONDARY 30015 -#define IDS_PFONTFACE_SECONDARY 30016 -#define IDS_CAPTION_TOOL 30021 -#define IDS_CAPTION_KEYDISP 30022 -#define IDS_CAPTION_SOFTKEY 30023 -#define IDS_HDD 30031 -#define IDS_SCREENOPTION 30041 -#define IDS_SOUNDOPTION 30042 -#define IDS_SERIALOPTION 30043 -#define IDS_NETWORKOPTION 30044 -#define IDS_WABOPTION 30045 -#define IDS_PCIOPTION 30046 -#define IDS_MIDIOPTION 30047 -#define IDS_CAPTION_FDD1 30051 -#define IDS_CAPTION_FDD2 30052 -#define IDS_CAPTION_FDD3 30053 -#define IDS_CAPTION_FDD4 30054 -#define IDS_CAPTION_SEPALATOR 30055 -#define IDS_CAPTION_FRAME 30056 -#define IDS_CAPTION_CLOCK 30057 -#define IDS_ERROR_DIRECTDRAW 30061 -#define IDS_CONFIRM_RESET 30062 -#define IDS_CONFIRM_EXIT 30063 -#define IDS_CONFIRM_RESUME 30064 -#define IDS_ERROR_RESUME 30065 -#define IDS_NONCONNECT 30101 -#define IDS_1 30111 -#define IDS_1HALF 30112 -#define IDS_2 30113 -#define IDS_INT0 30141 -#define IDS_INT1 30142 -#define IDS_INT2 30143 -#define IDS_INT3 30144 -#define IDS_INT41 30145 -#define IDS_INT42 30146 -#define IDS_INT5 30147 -#define IDS_INT6 30148 -#define IDS_C8000 30159 -#define IDS_CC000 30163 -#define IDS_D0000 30167 -#define IDS_D4000 30171 -#define IDS_SERIAL1 30181 -#define IDS_PC9861B 30182 -#define IDS_PC9861C 30183 -#define IDS_COM1 30191 -#define IDS_COM2 30192 -#define IDS_COM3 30193 -#define IDS_COM4 30194 -#define IDS_MIDI 30195 -#define IDS_TABLET 30196 -#define IDS_PIPE 30197 -#define IDS_2_0MHZ 30201 -#define IDS_2_5MHZ 30202 -#define IDS_CLOCKFORMAT 30203 -#define IDS_HDDSIZERANGE 30211 -#define IDS_ZOOM_NONE 30301 -#define IDS_ZOOM_FIXEDASPECT 30302 -#define IDS_ZOOM_ADJUSTASPECT 30303 -#define IDS_ZOOM_FULL 30304 -#define IDS_ZOOM_INTMULTIPLE 30305 -#define IDS_0088 30401 -#define IDS_0188 30402 -#define IDS_0288 30403 -#define IDS_0388 30404 -#define IDS_0X 30411 -#define IDS_1X 30412 -#define IDS_2X 30413 -#define IDS_3X 30414 -#define IDS_4X 30415 -#define IDS_5X 30416 -#define IDS_6X 30417 -#define IDS_7X 30418 -#define IDS_8X 30419 -#define IDS_00D0 30421 -#define IDS_10D0 30422 -#define IDS_20D0 30423 -#define IDS_30D0 30424 -#define IDS_40D0 30425 -#define IDS_50D0 30426 -#define IDS_60D0 30427 -#define IDS_70D0 30428 -#define IDS_20D2 30430 -#define IDS_20D4 30431 -#define IDS_20D6 30432 -#define IDS_20D8 30433 -#define IDS_20DA 30434 -#define IDS_20DC 30435 -#define IDS_20DE 30436 -#define IDS_PARITY_NONE 30501 -#define IDS_PARITY_ODD 30502 -#define IDS_PARITY_EVEN 30503 -#define IDS_SYNC 30511 -#define IDS_ASYNC 30512 -#define IDS_ASYNC16X 30513 -#define IDS_ASYNC64X 30514 -#define IDS_GD5430_BE 30600 -#define IDS_GD5430_XE 30601 -#define IDS_GD5430_CB 30602 -#define IDS_GD5430_CF 30603 -#define IDS_GD5430_XE10 30604 -#define IDS_GD5430_CB2 30605 -#define IDS_GD5430_CX2 30606 -#define IDS_GD5430_PCI 30609 -#define IDS_GD5430_WAB 30610 -#define IDS_GD5430_WSN_A2F 30611 -#define IDS_GD5430_WSN 30612 -#define IDS_GD5430_GA98NBIC 30620 -#define IDS_GD5430_GA98NBII 30621 -#define IDS_GD5430_GA98NBIV 30622 -#define IDS_GD5430_AUTO_XE_G1_PCI 30690 -#define IDS_GD5430_AUTO_XE_G2_PCI 30691 -#define IDS_GD5430_AUTO_XE_G4_PCI 30692 -#define IDS_GD5430_AUTO_XE_WA_PCI 30693 -#define IDS_GD5430_AUTO_XE_W4_PCI 30694 -#define IDS_GD5430_AUTO_XE_WS_PCI 30695 -#define IDS_GD5430_96 30696 -#define IDS_GD5430_AUTO_XE10_WABS 30697 -#define IDS_GD5430_AUTO_XE10_WSN2 30698 -#define IDS_GD5430_AUTO_XE10_WSN4 30699 -#define IDS_IDETYPE_NONE 30700 -#define IDS_IDETYPE_HDD 30701 -#define IDS_IDETYPE_CDROM 30702 -#define IDS_PHYSICALDRIVE 30710 -#define IDS_PCI_PCMC_82434LX 30800 -#define IDS_PCI_PCMC_82441FX 30801 -#define IDS_PCI_PCMC_WILDCAT 30802 -#define IDS_FONTTITLE 31001 -#define IDS_FONTEXT 31002 -#define IDS_FONTFILTER 31003 -#define IDS_BMPTITLE 31011 -#define IDS_BMPEXT 31012 -#define IDS_BMPFILTER1 31013 -#define IDS_BMPFILTER4 31014 -#define IDS_BMPFILTER8 31015 -#define IDS_BMPFILTER24 31016 -#define IDS_MIMPITITLE 31021 -#define IDS_MIMPIEXT 31022 -#define IDS_MIMPIFILTER 31023 -#define IDS_FDDTITLE 31031 -#define IDS_FDDEXT 31032 -#define IDS_FDDFILTER 31033 -#define IDS_HDDTITLE 31041 -#define IDS_HDDEXT 31042 -#define IDS_HDDFILTER 31043 -#define IDS_SASITITLE 31044 -#define IDS_IDETITLE 31045 -#define IDS_HDDFILTER_NVL 31046 -#define IDS_ISOTITLE 31051 -#define IDS_ISOEXT 31052 -#define IDS_ISOFILTER 31053 -#define IDS_SCSITITLE 31061 -#define IDS_SCSIEXT 31062 -#define IDS_SCSIFILTER 31063 -#define IDS_NEWDISKTITLE 31071 -#define IDS_NEWDISKEXT 31072 -#define IDS_NEWDISKFILTER 31073 -#define IDS_NEWDISKFILTER2 31074 -#define IDS_NEWDISKHDFILTER 31075 -#define IDS_NEWDISKHDFILTER2 31076 -#define IDS_NEWDISKFDFILTER 31077 -#define IDS_S98TITLE 31081 -#define IDS_S98EXT 31082 -#define IDS_S98FILTER 31083 -#define IDS_WAVETITLE 31091 -#define IDS_WAVEEXT 31092 -#define IDS_WAVEFILTER 31093 -#define IDS_SKINTITLE 31101 -#define IDS_SKINEXT 31102 -#define IDS_SKINFILTER 31103 -#define IDS_TXTTITLE 31111 -#define IDS_TXTEXT 31112 -#define IDS_TXTFILTER 31113 -#define IDS_CFGTITLE 31121 -#define IDS_CFGEXT 31122 -#define IDS_CFGFILTER 31123 -#define IDS_CFGTITLE_L 31124 -#define IDS_CFGFILTER_L 31126 -#define IDS_DISABLE 32000 -#define IDS_INT0IRQ3 32001 -#define IDS_INT1IRQ5 32002 -#define IDS_INT2IRQ6 32003 -#define IDS_INT3IRQ9 32004 -#define IDS_INT41IRQ10 32005 -#define IDS_INT42IRQ11 32006 -#define IDS_INT5IRQ12 32007 -#define IDS_INT6IRQ13 32008 -#define IDS_DMA0 32009 -#define IDS_DMA1 32010 -#define IDS_DMA2 32011 -#define IDS_DMA3 32012 -#define IDS_CPU_CUSTOM 32020 -#define IDS_CPU_I486SX 32021 -#define IDS_CPU_I486DX 32022 -#define IDS_CPU_PENTIUM 32023 -#define IDS_CPU_MMXPENTIUM 32024 -#define IDS_CPU_PENTIUMPRO 32025 -#define IDS_CPU_PENTIUMII 32026 -#define IDS_CPU_PENTIUMIII 32027 -#define IDS_CPU_PENTIUMM 32028 -#define IDS_CPU_PENTIUM4 32029 -#define IDS_CPU_CORE_2_DUO 32030 -#define IDS_CPU_CORE_2_DUOW 32031 -#define IDS_CPU_CORE_I 32032 -#define IDS_CPU_AMD_K6_2 32035 -#define IDS_CPU_AMD_K6_III 32036 -#define IDS_CPU_AMD_K7_ATHLON 32037 -#define IDS_CPU_AMD_K7_ATHLONXP 32038 -#define IDS_CPU_AMD_K8_ATHLON64 32039 -#define IDS_CPU_AMD_K8_ATHLON64X2 32042 -#define IDS_CPU_AMD_K10_PHENOM 32043 -#define IDS_CPU_80286 32040 -#define IDS_CPU_80386 32041 -#define IDS_CPU_NEKOPRO 32049 -#define IDS_RENDERER_DIRECTDRAW 32100 -#define IDS_RENDERER_DIRECT3D 32101 -#define IDS_RENDERER_IMODE_NN 32110 -#define IDS_RENDERER_IMODE_LINEAR 32111 -#define IDS_RENDERER_IMODE_PIXEL 32112 -#define IDS_RENDERER_IMODE_PIXEL2 32113 -#define IDS_RENDERER_IMODE_PIXEL3 32114 -#define IDM_TOOLWIN 40001 -#define IDM_KEYDISP 40002 -#define IDM_SOFTKBD 40003 -#define IDM_MEMDBG32 40004 -#define IDM_SCREENCENTER 40005 -#define IDM_SNAPENABLE 40006 -#define IDM_BACKGROUND 40007 -#define IDM_BGSOUND 40008 -#define IDM_TRACEONOFF 40009 -#define IDM_MEMORYDUMP 40010 -#define IDM_DEBUGUTY 40011 -#define IDM_VIEWER 40012 -#define IDM_RESTOREBORDER 40013 -#define IDM_SCRNMUL 40050 -#define IDM_SCRNMUL4 40054 -#define IDM_SCRNMUL6 40056 -#define IDM_SCRNMUL8 40058 -#define IDM_SCRNMUL10 40060 -#define IDM_SCRNMUL12 40062 -#define IDM_SCRNMUL16 40066 -#define IDM_RESET 40101 -#define IDM_CONFIG 40102 -#define IDM_NEWDISK 40103 -#define IDM_CHANGEFONT 40104 -#define IDM_EXIT 40105 -#define IDM_SAVEVMCFG 40106 -#define IDM_LOADVMCFG 40107 -#define IDM_NEWDISKFD 40108 -#define IDM_NEWDISKHD 40109 -#define IDM_PAUSE 40110 -#define IDM_CHANGECLK_X2 40111 -#define IDM_CHANGECLK_X8 40112 -#define IDM_CHANGECLK_X16 40113 -#define IDM_CHANGECLK_X30 40114 -#define IDM_CHANGECLK_X42 40115 -#define IDM_CHANGECLK_RESTORE 40119 -#define IDM_FLAGSAVE 40201 -#define IDM_FLAGSAVE0 40201 -#define IDM_FLAGSAVE1 40202 -#define IDM_FLAGSAVE2 40203 -#define IDM_FLAGSAVE3 40204 -#define IDM_FLAGSAVE4 40205 -#define IDM_FLAGSAVE5 40206 -#define IDM_FLAGSAVE6 40207 -#define IDM_FLAGSAVE7 40208 -#define IDM_FLAGSAVE8 40209 -#define IDM_FLAGSAVE9 40210 -#define IDM_FLAGLOAD 40251 -#define IDM_FLAGLOAD0 40251 -#define IDM_FLAGLOAD1 40252 -#define IDM_FLAGLOAD2 40253 -#define IDM_FLAGLOAD3 40254 -#define IDM_FLAGLOAD4 40255 -#define IDM_FLAGLOAD5 40256 -#define IDM_FLAGLOAD6 40257 -#define IDM_FLAGLOAD7 40258 -#define IDM_FLAGLOAD8 40259 -#define IDM_FLAGLOAD9 40260 -#define IDM_DBSSSAVE0 40270 -#define IDM_DBSSSAVE1 40271 -#define IDM_DBSSSAVE2 40272 -#define IDM_DBSSSAVE3 40273 -#define IDM_DBSSLOAD0 40274 -#define IDM_DBSSLOAD1 40275 -#define IDM_DBSSLOAD2 40276 -#define IDM_DBSSLOAD3 40277 -#define IDM_FDD1OPEN 40301 -#define IDM_FDD2OPEN 40302 -#define IDM_FDD3OPEN 40303 -#define IDM_FDD4OPEN 40304 -#define IDM_FDD1EJECT 40311 -#define IDM_FDD2EJECT 40312 -#define IDM_FDD3EJECT 40313 -#define IDM_FDD4EJECT 40314 -#define IDM_IDE0OPEN 40401 -#define IDM_IDE1OPEN 40402 -#define IDM_IDE2OPEN 40403 -#define IDM_IDE3OPEN 40404 -#define IDM_IDE0EJECT 40411 -#define IDM_IDE1EJECT 40412 -#define IDM_IDE2EJECT 40413 -#define IDM_IDE3EJECT 40414 -#define IDM_SCSI0OPEN 40421 -#define IDM_SCSI1OPEN 40422 -#define IDM_SCSI2OPEN 40423 -#define IDM_SCSI3OPEN 40424 -#define IDM_SCSI4OPEN 40425 -#define IDM_SCSI5OPEN 40426 -#define IDM_SCSI6OPEN 40427 -#define IDM_SCSI7OPEN 40428 -#define IDM_SCSI0EJECT 40431 -#define IDM_SCSI1EJECT 40432 -#define IDM_SCSI2EJECT 40433 -#define IDM_SCSI3EJECT 40434 -#define IDM_SCSI4EJECT 40435 -#define IDM_SCSI5EJECT 40436 -#define IDM_SCSI6EJECT 40437 -#define IDM_SCSI7EJECT 40438 -#define IDM_SXSIOPTION 40441 -#define IDM_IDE0STATE 40451 -#define IDM_IDE1STATE 40452 -#define IDM_IDE2STATE 40453 -#define IDM_IDE3STATE 40454 -#define IDM_IDE0PHYSICALDRV 40461 -#define IDM_IDE1PHYSICALDRV 40462 -#define IDM_IDE2PHYSICALDRV 40463 -#define IDM_IDE3PHYSICALDRV 40464 -#define IDM_SCSI0STATE 40471 -#define IDM_SCSI1STATE 40472 -#define IDM_SCSI2STATE 40473 -#define IDM_SCSI3STATE 40474 -#define IDM_SCSI4STATE 40475 -#define IDM_SCSI5STATE 40476 -#define IDM_SCSI6STATE 40477 -#define IDM_SCSI7STATE 40478 -#define IDM_WINDOW 40501 -#define IDM_FULLSCREEN 40502 -#define IDM_ROLNORMAL 40503 -#define IDM_ROLLEFT 40504 -#define IDM_ROLRIGHT 40505 -#define IDM_DISPSYNC 40506 -#define IDM_RASTER 40507 -#define IDM_NOWAIT 40508 -#define IDM_AUTOFPS 40509 -#define IDM_60FPS 40510 -#define IDM_30FPS 40511 -#define IDM_20FPS 40512 -#define IDM_15FPS 40513 -#define IDM_VF1EN 40517 -#define IDM_VF1P0 40518 -#define IDM_VF1P1 40519 -#define IDM_VF1P2 40520 -#define IDM_VF1BO 40521 -#define IDM_SCREENOPT 40514 -#define IDM_CPUSTABILIZER 40515 -#define IDM_ASYNCCPU 40516 -#define IDM_KEY 40601 -#define IDM_JOY1 40602 -#define IDM_JOY2 40603 -#define IDM_KEYMOUSE 40604 -#define IDM_XSHIFT 40611 -#define IDM_XCTRL 40612 -#define IDM_XGRPH 40613 -#define IDM_SENDCAD 40614 -#define IDM_USENUMLOCK 40615 -#define IDM_SWAPPAGEUPDOWN 40616 -#define IDM_F12MOUSE 40621 -#define IDM_F12COPY 40622 -#define IDM_F12STOP 40623 -#define IDM_F12EQU 40624 -#define IDM_F12COMMA 40625 -#define IDM_USERKEY1 40626 -#define IDM_USERKEY2 40627 -#define IDM_F12NOWAIT 40628 -#define IDM_F12NOWAIT2 40629 -#define IDM_F12WABRELAY 40630 -#define IDM_BEEPOFF 40631 -#define IDM_BEEPLOW 40632 -#define IDM_BEEPMID 40633 -#define IDM_BEEPHIGH 40634 -#define IDM_NOSOUND 40641 -#define IDM_PC9801_14 40642 -#define IDM_PC9801_26K 40643 -#define IDM_PC9801_86 40644 -#define IDM_PC9801_26_86 40645 -#define IDM_PC9801_86_CB 40646 -#define IDM_PC9801_118 40647 -#define IDM_SPEAKBOARD 40648 -#define IDM_SPARKBOARD 40649 -#define IDM_PX1 40650 -#define IDM_PX2 40651 -#define IDM_AMD98 40652 -#define IDM_JASTSOUND 40653 -#define IDM_SEEKSND 40654 -#define IDM_SOUNDORCHESTRA 40655 -#define IDM_SOUNDORCHESTRAV 40656 -#define IDM_PC9801_86_WSS 40657 -#define IDM_MATE_X_PCM 40658 -#define IDM_SB16 40659 -#define IDM_LITTLEORCHESTRAL 40810 -#define IDM_MMORCHESTRA 40811 -#define IDM_PC9801_86_118 49650 -#define IDM_86SPEAKBOARD 49651 -#define IDM_WAVESTAR 49652 -#define IDM_PC9801_118_SB16 49655 -#define IDM_PC9801_86_118_SB16 49656 -#define IDM_PC9801_86_WSS_SB16 49657 -#define IDM_WSS_SB16 49658 -#define IDM_PC9801_86_SB16 49659 -#define IDM_MEM640 40661 -#define IDM_MEM16 40662 -#define IDM_MEM36 40663 -#define IDM_MEM76 40664 -#define IDM_MEM116 40665 -#define IDM_MEM136 40666 -#define IDM_MEM166 40667 -#define IDM_MEM326 40668 -#define IDM_MEM646 40669 -#define IDM_MEM1206 40670 -#define IDM_MEM2306 49671 -#define IDM_MEM5126 49672 -#define IDM_MEM10246 49673 -#define IDM_MOUSE 40671 -#define IDM_SERIAL1 40672 -#define IDM_MPUPC98 40673 -#define IDM_MIDIPANIC 40674 -#define IDM_SNDOPT 40675 -#define IDM_NETOPT 40676 -#define IDM_WABOPT 40677 -#define IDM_HOSTDRVOPT 40678 -#define IDM_PCIOPT 40679 -#define IDM_FPU80 49680 -#define IDM_FPU64 49681 -#define IDM_FPU64INT 49682 -#define IDM_MOUSEWHEELCTL 40688 -#define IDM_MOUSENC 40689 -#define IDM_MOUSERAW 40690 -#define IDM_MOUSE30X 40691 -#define IDM_MOUSE20X 40692 -#define IDM_MOUSE15X 40693 -#define IDM_MOUSE10X 40694 -#define IDM_MOUSED2X 40695 -#define IDM_MOUSED3X 40696 -#define IDM_MOUSED4X 40697 -#define IDM_BMPSAVE 40701 -#define IDM_S98LOGGING 40702 -#define IDM_WAVEREC 40703 -#define IDM_CALENDAR 40704 -#define IDM_DISPCLOCK 40705 -#define IDM_DISPFRAME 40706 -#define IDM_JOYX 40707 -#define IDM_RAPID 40708 -#define IDM_MSRAPID 40709 -#define IDM_SSTP 40710 -#define IDM_CPUSAVE 40711 -#define IDM_HELP 40712 -#define IDM_ABOUT 40713 -#define IDM_ITFWORK 40714 -#define IDM_TXTSAVE 40715 -#define IDM_TIMERFIX 40716 -#define IDM_SKIP16MEMCHK 40717 -#define IDM_FASTMEMCHK 40718 -#define IDM_ALTENTER 40721 -#define IDM_ALTF4 40722 -#define IDM_SYSKHOOK 40729 -#define IDM_HF_ENABLE 40730 -#define IDM_HF_ADDITIONAL 40731 -#define IDM_EN_DBSS 40732 -#define IDM_IDEOPT 40800 -#define IDM_CLOSE 41001 -#define IDM_TOOL_SKIN 41101 -#define IDM_TOOL_SKINSEL 41111 -#define IDM_TOOL_SKINDEF 41112 -#define IDM_TOOL_SKINMRU 41151 -#define IDM_TOOL_SKINMRU1 41152 -#define IDM_TOOL_SKINMRU2 41153 -#define IDM_TOOL_SKINMRU3 41154 -#define IDM_BMS 41155 -#define IDM_KDISPFM 42001 -#define IDM_KDISPMIDI 42002 -#define IDM_VIEWWINNEW 43001 -#define IDM_VIEWWINCLOSE 43002 -#define IDM_VIEWWINALLCLOSE 43003 -#define IDM_VIEWMODEREG 43011 -#define IDM_VIEWMODESEG 43012 -#define IDM_VIEWMODE1MB 43013 -#define IDM_VIEWMODEASM 43014 -#define IDM_VIEWMODESND 43015 -#define IDM_VIEWMODELOCK 43016 -#define IDM_SETSEG 43021 -#define IDM_SEGCS 43022 -#define IDM_SEGDS 43023 -#define IDM_SEGES 43024 -#define IDM_SEGSS 43025 -#define IDM_SEGTEXT 43026 -#define IDM_RELOAD 43027 -#define IDM_VRAM0 43031 -#define IDM_VRAM1 43032 -#define IDM_BIOS 43033 -#define IDM_ITF 43034 -#define IDM_A20LINE 43035 -#define IDM_TRACE_TRACE 43101 -#define IDM_TRACE_VERBOSE 43102 -#define IDM_TRACE_ENABLE 43103 -#define IDM_TRACE_FILEOUT 43104 -#define IDM_TRACE_CLEAR 43105 -#define IDM_COPYPASTE_COPYTVRAM 43201 -#define IDM_COPYPASTE_COPYGVRAM 43202 -#define IDM_COPYPASTE_COPYWABMEM 43203 -#define IDM_COPYPASTE_PASTE 43210 -#define IDM_WABSYSMENU_RESETSIZE 43301 -#define IDM_WABSYSMENU_HALFTONE 43302 -#define IDM_IDE0PHYSICALDRV_ID0 43400 // size = 26*4 -#define IDM_IDE0PHYSICALDRV_LAST 43503 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40135 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by H:\projects\vcp\np21w-0.86\win9x\resources\932\np2.rc +// +#define IDR_MANIFEST 1 +#define IRT_MANIFEST 24 +#define IDI_ICON1 101 +#define IDI_ICON2 102 +#define IDI_ICON3 103 +#define IDD_CONFIG 111 +#define IDD_NEWDISK 121 +#define IDD_NEWHDDDISK 122 +#define IDD_NEWSASI 123 +#define IDD_NEWDISK2 124 +#define IDD_NEWHDDPROC 125 +#define IDD_SCROPT1 131 +#define IDD_SCROPT_FULLSCREEN 132 +#define IDD_SCROPT2 133 +#define IDD_SCROPT3 134 +#define IDD_SCROPT_RENDERER 135 +#define IDD_SERIAL1 141 +#define IDD_PC9861A 142 +#define IDD_MPUPC98 151 +#define IDD_SNDMIX 152 +#define IDD_SND14 153 +#define IDD_SND26 154 +#define IDD_SND86 155 +#define IDD_SNDSPB 156 +#define IDD_SNDPAD1 157 +#define IDD_SNDFMGEN 158 +#define IDD_SND118 159 +#define IDD_SNDWSS 160 +#define IDD_CALENDAR 161 +#define IDD_SNDSB16 162 +#define IDD_SMPU98 163 +#define IDD_ABOUT 171 +#define IDD_BMS 172 +#define IDD_LGY98 180 +#define IDD_NETWORK 181 +#define IDD_GD5430 190 +#define IDD_WAB 191 +#define IDD_PCI 197 +#define IDD_HOSTDRV 198 +#define IDD_IDE 199 +#define IDR_SYS 201 +#define IDR_SYSKEYDISP 202 +#define IDR_SYSSOFTKBD 203 +#define IDR_SYSDEBUG32 204 +#define IDR_SYSDEBUG 205 +#define IDR_MAIN 211 +#define IDR_STAT 212 +#define IDR_DEBUGSS 213 +#define IDR_FDD1MENU 221 +#define IDR_FDD2MENU 222 +#define IDR_FDD3MENU 223 +#define IDR_FDD4MENU 224 +#define IDR_IDEMENU 231 +#define IDR_SASIMENU 232 +#define IDR_SCSIMENU 233 +#define IDR_PXMENU 241 +#define IDR_WAVEREC 251 +#define IDR_CPUSAVE16 252 +#define IDR_CPUSAVE32 253 +#define IDR_CLOSE 301 +#define IDR_TOOLWIN 311 +#define IDR_KEYDISP 321 +#define IDR_VIEW 331 +#define IDR_TRACE 341 +#define IDR_COPYPASTEPOPUP 351 +#define IDR_WABSYSMENU 361 +#define IDR_IDE 400 +#define RESOURCE_VERSION 830 +#define IDC_BASECLOCK 11101 +#define IDC_MULTIPLE 11102 +#define IDC_CLOCKMSG 11103 +#define IDC_MODELVM 11104 +#define IDC_MODELVX 11105 +#define IDC_MODELEPSON 11106 +#define IDC_MODEL21 11107 +#define IDC_CPU_TYPE 11109 +#define IDC_SOUND_BUFFER 11110 +#define IDC_ALLOWRESIZE 11111 +#define IDC_DISABLEMMX 11112 +#define IDC_COMFIRM 11113 +#define IDC_RESUME 11114 +#define IDC_SOUND_RATE 11115 +#define IDC_SOUND_DEVICE_TYPE 11116 +#define IDC_SOUND_DEVICE_NAME 11117 +#define IDC_SAVEWINDOWSIZE 11118 +#define IDC_DISKLABEL 12101 +#define IDC_MAKE2DD 12102 +#define IDC_MAKE2HD 12103 +#define IDC_MAKE144 12104 +#define IDC_HDDSIZE 12201 +#define IDC_HDDLIMIT 12202 +#define IDC_HDDADVANCED 12203 +#define IDC_HDDADVANCED_C 12204 +#define IDC_HDDADVANCED_H 12205 +#define IDC_HDDADVANCED_S 12206 +#define IDC_HDDADVANCED_SS 12207 +#define IDC_HDDADVANCED_FIXSIZE 12210 +#define IDC_HDDADVANCED_DYNSIZE 12211 +#define IDC_HDDADVANCED_BLANK 12212 +#define IDC_HDDCREATE_PROGRESS 12290 +#define IDC_HDDCREATE_VAL 12291 +#define IDC_NEWSASI5MB 12301 +#define IDC_NEWSASI10MB 12302 +#define IDC_NEWSASI15MB 12303 +#define IDC_NEWSASI20MB 12304 +#define IDC_NEWSASI30MB 12305 +#define IDC_NEWSASI40MB 12306 +#define IDC_LCD 13101 +#define IDC_LCDX 13102 +#define IDC_SKIPLINE 13103 +#define IDC_SKIPLIGHT 13104 +#define IDC_LIGHTSTR 13105 +#define IDC_SOFTWARERENDERING 13106 +#define IDC_1DOTTEXTSCRSHIFT 13107 +#define IDC_FULLSCREEN_SAMEBPP 13201 +#define IDC_FULLSCREEN_SAMERES 13202 +#define IDC_FULLSCREEN_ZOOM 13203 +#define IDC_RENDERER_TYPE 13210 +#define IDC_RENDERER_IMODE 13211 +#define IDC_RENDERER_EXCLUSIVE 13212 +#define IDC_GDC7220 13301 +#define IDC_GDC72020 13302 +#define IDC_GCBOX 13303 +#define IDC_GRCGNON 13304 +#define IDC_GRCG 13305 +#define IDC_GRCG2 13306 +#define IDC_EGC 13307 +#define IDC_PC980124 13308 +#define IDC_PEGC 13309 +#define IDC_TRAMWAIT 13401 +#define IDC_TRAMSTR 13402 +#define IDC_VRAMWAIT 13403 +#define IDC_VRAMSTR 13404 +#define IDC_GRCGWAIT 13405 +#define IDC_GRCGSTR 13406 +#define IDC_REALPAL 13407 +#define IDC_REALPALSTR 13408 +#define IDC_COM1PORT 14101 +#define IDC_COM1STR00 14102 +#define IDC_COM1STR01 14103 +#define IDC_COM1STR02 14104 +#define IDC_COM1STR03 14105 +#define IDC_COM1STR04 14106 +#define IDC_COM1STR05 14107 +#define IDC_COM1STR06 14108 +#define IDC_COM1STR07 14109 +#define IDC_COM1SPEED 14110 +#define IDC_COM1CHARSIZE 14111 +#define IDC_COM1PARITY 14112 +#define IDC_COM1STOPBIT 14113 +#define IDC_COM1STR10 14114 +#define IDC_COM1STR11 14115 +#define IDC_COM1STR12 14116 +#define IDC_COM1MMAP 14117 +#define IDC_COM1MMDL 14118 +#define IDC_COM1DEFE 14119 +#define IDC_COM1DEFF 14120 +#define IDC_COM1DEFB 14121 +#define IDC_COM1PENTABFA 14122 +#define IDC_COM1FSPEED 14123 +#define IDC_COM1STR30 14124 +#define IDC_COM1STR31 14125 +#define IDC_COM1PIPENAME 14126 +#define IDC_COM1PIPESERV 14127 +#define IDC_COM1STR32 14128 +#define IDC_COM1DSRCHECK 14129 +#define IDC_PC9861E 14201 +#define IDC_CH1SPEED 14202 +#define IDC_CH1INT 14203 +#define IDC_CH1MODE 14204 +#define IDC_CH2SPEED 14205 +#define IDC_CH2INT 14206 +#define IDC_CH2MODE 14207 +#define IDC_PC9861DIP 14208 +#define IDC_MPUIO 15101 +#define IDC_MPUINT 15102 +#define IDC_MPUDEF 15103 +#define IDC_MPUDIP 15104 +#define IDC_MPU98MMDL 15105 +#define IDC_MPU98MMAP 15106 +#define IDC_MPU98DEFE 15107 +#define IDC_MPU98DEFF 15108 +#define IDC_MPU98DEFB 15109 +#define IDC_MPU98MDIN 15110 +#define IDC_MPU98MMDL_B 15111 +#define IDC_MPU98MMAP_B 15112 +#define IDC_MPU98DEFE_B 15113 +#define IDC_MPU98DEFF_B 15114 +#define IDC_MPU98DEFB_B 15115 +#define IDC_MPU98MDIN_B 15116 +#define IDC_MPUENABLE 15117 +#define IDC_MPUMUTEB 15118 +#define IDC_VOLFM 15201 +#define IDC_VOLFMSTR 15202 +#define IDC_VOLPSG 15203 +#define IDC_VOLPSGSTR 15204 +#define IDC_VOLADPCM 15205 +#define IDC_VOLADPCMSTR 15206 +#define IDC_VOLPCM 15207 +#define IDC_VOLPCMSTR 15208 +#define IDC_VOLRHYTHM 15209 +#define IDC_VOLRHYTHMSTR 15210 +#define IDC_SNDMIXDEF 15211 +#define IDC_SNDMIXDEF2 15212 +#define IDC_VOLMASTER 15213 +#define IDC_VOLMASTERSTR 15214 +#define IDC_VOLCDDA 15220 +#define IDC_VOLCDDASTR 15221 +#define IDC_VOLMIDI 15222 +#define IDC_VOLMIDISTR 15223 +#define IDC_VOLHW 15224 +#define IDC_VOLHWSTR 15225 +#define IDC_VOL14L 15301 +#define IDC_VOL14LSTR 15302 +#define IDC_VOL14R 15303 +#define IDC_VOL14RSTR 15304 +#define IDC_VOLF2 15305 +#define IDC_VOLF2STR 15306 +#define IDC_VOLF4 15307 +#define IDC_VOLF4STR 15308 +#define IDC_VOLF8 15309 +#define IDC_VOLF8STR 15310 +#define IDC_VOLF16 15311 +#define IDC_VOLF16STR 15312 +#define IDC_SND26IO 15401 +#define IDC_SND26INT 15402 +#define IDC_SND26ROM 15403 +#define IDC_SND26JMP 15404 +#define IDC_SND26DEF 15405 +#define IDC_SND86IO 15501 +#define IDC_SND86INT 15502 +#define IDC_SND86INTA 15503 +#define IDC_SND86ID 15504 +#define IDC_SND86ROM 15505 +#define IDC_SND86DIP 15506 +#define IDC_SND86DEF 15507 +#define IDC_SND118IO 15551 +#define IDC_SND118ID 15502 +#define IDC_SND118DMA 15553 +#define IDC_SND118INTF 15554 +#define IDC_SND118INTP 15555 +#define IDC_SND118INTM 15556 +#define IDC_SND118DEF 15557 +#define IDC_SND118ROM 15558 +#define IDC_SND118JMP 15559 +#define IDC_SPBIO 15601 +#define IDC_SPBINT 15602 +#define IDC_SPBROM 15603 +#define IDC_SPBJMP 15604 +#define IDC_SPBDEF 15605 +#define IDC_SPBVRL 15606 +#define IDC_SPBVRR 15607 +#define IDC_SPBVRLEVEL 15608 +#define IDC_SPBREVERSE 15609 +#define IDC_JOYPAD1 15701 +#define IDC_PAD1_1A 15702 +#define IDC_PAD1_1B 15703 +#define IDC_PAD1_1C 15704 +#define IDC_PAD1_1D 15705 +#define IDC_PAD1_2A 15706 +#define IDC_PAD1_2B 15707 +#define IDC_PAD1_2C 15708 +#define IDC_PAD1_2D 15709 +#define IDC_PAD1_RA 15710 +#define IDC_PAD1_RB 15711 +#define IDC_PAD1_RC 15712 +#define IDC_PAD1_RD 15713 +#define IDC_PAD1_ID 15714 +#define IDC_USEFMGEN 15801 +#define IDC_CLNDREAL 16101 +#define IDC_CLNDVIR 16102 +#define IDC_VIRYEAR 16103 +#define IDC_VIRMONTH 16104 +#define IDC_VIRDAY 16105 +#define IDC_VIRHOUR 16106 +#define IDC_VIRMINUTE 16107 +#define IDC_VIRSECOND 16108 +#define IDC_SETNOW 16109 +#define IDC_NP2ICON 17101 +#define IDC_NP2VER 17102 +#define IDC_MORE 17103 +#define IDC_NP2INFO 17104 +#define IDC_NP2STR 17105 +#define IDC_BMSIO 17209 +#define IDC_BMS 17210 +#define IDC_BMSIOBANK 17210 +#define IDC_BMSBANKS 17211 +#define IDC_TOOL_HDDACC 18001 +#define IDC_TOOL_FDD1ACC 18002 +#define IDC_TOOL_FDD1LIST 18003 +#define IDC_TOOL_FDD1BROWSE 18004 +#define IDC_TOOL_FDD1EJECT 18005 +#define IDC_TOOL_FDD2ACC 18006 +#define IDC_TOOL_FDD2LIST 18007 +#define IDC_TOOL_FDD2BROWSE 18008 +#define IDC_TOOL_FDD2EJECT 18009 +#define IDC_TOOL_RESET 18010 +#define IDC_TOOL_POWER 18011 +#define IDC_LGY98ENABLED 19001 +#define IDC_LGY98IO 19002 +#define IDC_LGY98INT 19003 +#define IDC_NETTAP 19004 +#define IDC_LGY98DEF 19005 +#define IDC_NETPMM 19006 +#define IDC_GD5430ENABLED 19011 +#define IDC_GD5430TYPE 19012 +#define IDC_GD5430DEF 19013 +#define IDC_WABASWITCH 19014 +#define IDC_WABMULTIWIN 19015 +#define IDC_WABMULTHREAD 19016 +#define IDC_GD5430FAKECURSOR 19017 +#define IDC_PCIENABLE 19070 +#define IDC_PCIPCMCTYPE 19071 +#define IDC_PCIBIOS32 19072 +#define IDC_HOSTDRVENABLE 19090 +#define IDC_HOSTDRVDIR 19091 +#define IDC_HOSTDRVREAD 19092 +#define IDC_HOSTDRVWRITE 19093 +#define IDC_HOSTDRVDELETE 19094 +#define IDC_HOSTDRVBROWSE 19099 +#define IDC_IDE1TYPE 19100 +#define IDC_IDE2TYPE 19101 +#define IDC_IDE3TYPE 19102 +#define IDC_IDE4TYPE 19103 +#define IDC_IDEWWAIT 19104 +#define IDC_SPINIDEWWAIT 19105 +#define IDC_IDERWAIT 19106 +#define IDC_SPINIDERWAIT 19107 +#define IDC_USEIDEBIOS 19108 +#define IDC_AUTOIDEBIOS 19109 +#define IDC_USEASYNCCD 19110 +#define IDC_ALLOWCDTRAYOP 19111 +#define IDC_USECDECC 19112 +#define IDS_APP_NAME2 30001 +#define IDS_APP_NAME21 30002 +#define IDS_FILENAME_HELP 30003 +#define IDS_FONTFACE 30011 +#define IDS_PFONTFACE 30012 +#define IDS_FONTFACE_PRIMARY 30013 +#define IDS_PFONTFACE_PRIMARY 30014 +#define IDS_FONTFACE_SECONDARY 30015 +#define IDS_PFONTFACE_SECONDARY 30016 +#define IDS_CAPTION_TOOL 30021 +#define IDS_CAPTION_KEYDISP 30022 +#define IDS_CAPTION_SOFTKEY 30023 +#define IDS_HDD 30031 +#define IDS_SCREENOPTION 30041 +#define IDS_SOUNDOPTION 30042 +#define IDS_SERIALOPTION 30043 +#define IDS_NETWORKOPTION 30044 +#define IDS_WABOPTION 30045 +#define IDS_PCIOPTION 30046 +#define IDS_MIDIOPTION 30047 +#define IDS_CAPTION_FDD1 30051 +#define IDS_CAPTION_FDD2 30052 +#define IDS_CAPTION_FDD3 30053 +#define IDS_CAPTION_FDD4 30054 +#define IDS_CAPTION_SEPALATOR 30055 +#define IDS_CAPTION_FRAME 30056 +#define IDS_CAPTION_CLOCK 30057 +#define IDS_ERROR_DIRECTDRAW 30061 +#define IDS_CONFIRM_RESET 30062 +#define IDS_CONFIRM_EXIT 30063 +#define IDS_CONFIRM_RESUME 30064 +#define IDS_ERROR_RESUME 30065 +#define IDS_NONCONNECT 30101 +#define IDS_1 30111 +#define IDS_1HALF 30112 +#define IDS_2 30113 +#define IDS_INT0 30141 +#define IDS_INT1 30142 +#define IDS_INT2 30143 +#define IDS_INT3 30144 +#define IDS_INT41 30145 +#define IDS_INT42 30146 +#define IDS_INT5 30147 +#define IDS_INT6 30148 +#define IDS_C8000 30159 +#define IDS_CC000 30163 +#define IDS_D0000 30167 +#define IDS_D4000 30171 +#define IDS_SERIAL1 30181 +#define IDS_PC9861B 30182 +#define IDS_PC9861C 30183 +#define IDS_COM1 30191 +#define IDS_COM2 30192 +#define IDS_COM3 30193 +#define IDS_COM4 30194 +#define IDS_MIDI 30195 +#define IDS_TABLET 30196 +#define IDS_PIPE 30197 +#define IDS_2_0MHZ 30201 +#define IDS_2_5MHZ 30202 +#define IDS_CLOCKFORMAT 30203 +#define IDS_HDDSIZERANGE 30211 +#define IDS_ZOOM_NONE 30301 +#define IDS_ZOOM_FIXEDASPECT 30302 +#define IDS_ZOOM_ADJUSTASPECT 30303 +#define IDS_ZOOM_FULL 30304 +#define IDS_ZOOM_INTMULTIPLE 30305 +#define IDS_0088 30401 +#define IDS_0188 30402 +#define IDS_0288 30403 +#define IDS_0388 30404 +#define IDS_0X 30411 +#define IDS_1X 30412 +#define IDS_2X 30413 +#define IDS_3X 30414 +#define IDS_4X 30415 +#define IDS_5X 30416 +#define IDS_6X 30417 +#define IDS_7X 30418 +#define IDS_8X 30419 +#define IDS_00D0 30421 +#define IDS_10D0 30422 +#define IDS_20D0 30423 +#define IDS_30D0 30424 +#define IDS_40D0 30425 +#define IDS_50D0 30426 +#define IDS_60D0 30427 +#define IDS_70D0 30428 +#define IDS_20D2 30430 +#define IDS_20D4 30431 +#define IDS_20D6 30432 +#define IDS_20D8 30433 +#define IDS_20DA 30434 +#define IDS_20DC 30435 +#define IDS_20DE 30436 +#define IDS_PARITY_NONE 30501 +#define IDS_PARITY_ODD 30502 +#define IDS_PARITY_EVEN 30503 +#define IDS_SYNC 30511 +#define IDS_ASYNC 30512 +#define IDS_ASYNC16X 30513 +#define IDS_ASYNC64X 30514 +#define IDS_GD5430_BE 30600 +#define IDS_GD5430_XE 30601 +#define IDS_GD5430_CB 30602 +#define IDS_GD5430_CF 30603 +#define IDS_GD5430_XE10 30604 +#define IDS_GD5430_CB2 30605 +#define IDS_GD5430_CX2 30606 +#define IDS_GD5430_PCI 30609 +#define IDS_GD5430_WAB 30610 +#define IDS_GD5430_WSN_A2F 30611 +#define IDS_GD5430_WSN 30612 +#define IDS_GD5430_GA98NBIC 30620 +#define IDS_GD5430_GA98NBII 30621 +#define IDS_GD5430_GA98NBIV 30622 +#define IDS_GD5430_AUTO_XE_G1_PCI 30690 +#define IDS_GD5430_AUTO_XE_G2_PCI 30691 +#define IDS_GD5430_AUTO_XE_G4_PCI 30692 +#define IDS_GD5430_AUTO_XE_WA_PCI 30693 +#define IDS_GD5430_AUTO_XE_W4_PCI 30694 +#define IDS_GD5430_AUTO_XE_WS_PCI 30695 +#define IDS_GD5430_96 30696 +#define IDS_GD5430_AUTO_XE10_WABS 30697 +#define IDS_GD5430_AUTO_XE10_WSN2 30698 +#define IDS_GD5430_AUTO_XE10_WSN4 30699 +#define IDS_IDETYPE_NONE 30700 +#define IDS_IDETYPE_HDD 30701 +#define IDS_IDETYPE_CDROM 30702 +#define IDS_PHYSICALDRIVE 30710 +#define IDS_PCI_PCMC_82434LX 30800 +#define IDS_PCI_PCMC_82441FX 30801 +#define IDS_PCI_PCMC_WILDCAT 30802 +#define IDS_FONTTITLE 31001 +#define IDS_FONTEXT 31002 +#define IDS_FONTFILTER 31003 +#define IDS_BMPTITLE 31011 +#define IDS_BMPEXT 31012 +#define IDS_BMPFILTER1 31013 +#define IDS_BMPFILTER4 31014 +#define IDS_BMPFILTER8 31015 +#define IDS_BMPFILTER24 31016 +#define IDS_MIMPITITLE 31021 +#define IDS_MIMPIEXT 31022 +#define IDS_MIMPIFILTER 31023 +#define IDS_FDDTITLE 31031 +#define IDS_FDDEXT 31032 +#define IDS_FDDFILTER 31033 +#define IDS_HDDTITLE 31041 +#define IDS_HDDEXT 31042 +#define IDS_HDDFILTER 31043 +#define IDS_SASITITLE 31044 +#define IDS_IDETITLE 31045 +#define IDS_HDDFILTER_NVL 31046 +#define IDS_ISOTITLE 31051 +#define IDS_ISOEXT 31052 +#define IDS_ISOFILTER 31053 +#define IDS_SCSITITLE 31061 +#define IDS_SCSIEXT 31062 +#define IDS_SCSIFILTER 31063 +#define IDS_NEWDISKTITLE 31071 +#define IDS_NEWDISKEXT 31072 +#define IDS_NEWDISKFILTER 31073 +#define IDS_NEWDISKFILTER2 31074 +#define IDS_NEWDISKHDFILTER 31075 +#define IDS_NEWDISKHDFILTER2 31076 +#define IDS_NEWDISKFDFILTER 31077 +#define IDS_S98TITLE 31081 +#define IDS_S98EXT 31082 +#define IDS_S98FILTER 31083 +#define IDS_WAVETITLE 31091 +#define IDS_WAVEEXT 31092 +#define IDS_WAVEFILTER 31093 +#define IDS_SKINTITLE 31101 +#define IDS_SKINEXT 31102 +#define IDS_SKINFILTER 31103 +#define IDS_TXTTITLE 31111 +#define IDS_TXTEXT 31112 +#define IDS_TXTFILTER 31113 +#define IDS_CFGTITLE 31121 +#define IDS_CFGEXT 31122 +#define IDS_CFGFILTER 31123 +#define IDS_CFGTITLE_L 31124 +#define IDS_CFGFILTER_L 31126 +#define IDS_DISABLE 32000 +#define IDS_INT0IRQ3 32001 +#define IDS_INT1IRQ5 32002 +#define IDS_INT2IRQ6 32003 +#define IDS_INT3IRQ9 32004 +#define IDS_INT41IRQ10 32005 +#define IDS_INT42IRQ11 32006 +#define IDS_INT5IRQ12 32007 +#define IDS_INT6IRQ13 32008 +#define IDS_DMA0 32009 +#define IDS_DMA1 32010 +#define IDS_DMA2 32011 +#define IDS_DMA3 32012 +#define IDS_CPU_CUSTOM 32020 +#define IDS_CPU_I486SX 32021 +#define IDS_CPU_I486DX 32022 +#define IDS_CPU_PENTIUM 32023 +#define IDS_CPU_MMXPENTIUM 32024 +#define IDS_CPU_PENTIUMPRO 32025 +#define IDS_CPU_PENTIUMII 32026 +#define IDS_CPU_PENTIUMIII 32027 +#define IDS_CPU_PENTIUMM 32028 +#define IDS_CPU_PENTIUM4 32029 +#define IDS_CPU_CORE_2_DUO 32030 +#define IDS_CPU_CORE_2_DUOW 32031 +#define IDS_CPU_CORE_I 32032 +#define IDS_CPU_AMD_K6_2 32035 +#define IDS_CPU_AMD_K6_III 32036 +#define IDS_CPU_AMD_K7_ATHLON 32037 +#define IDS_CPU_AMD_K7_ATHLONXP 32038 +#define IDS_CPU_AMD_K8_ATHLON64 32039 +#define IDS_CPU_AMD_K8_ATHLON64X2 32042 +#define IDS_CPU_AMD_K10_PHENOM 32043 +#define IDS_CPU_80286 32040 +#define IDS_CPU_80386 32041 +#define IDS_CPU_NEKOPRO 32049 +#define IDS_RENDERER_DIRECTDRAW 32100 +#define IDS_RENDERER_DIRECT3D 32101 +#define IDS_RENDERER_IMODE_NN 32110 +#define IDS_RENDERER_IMODE_LINEAR 32111 +#define IDS_RENDERER_IMODE_PIXEL 32112 +#define IDS_RENDERER_IMODE_PIXEL2 32113 +#define IDS_RENDERER_IMODE_PIXEL3 32114 +#define IDM_TOOLWIN 40001 +#define IDM_KEYDISP 40002 +#define IDM_SOFTKBD 40003 +#define IDM_MEMDBG32 40004 +#define IDM_SCREENCENTER 40005 +#define IDM_SNAPENABLE 40006 +#define IDM_BACKGROUND 40007 +#define IDM_BGSOUND 40008 +#define IDM_TRACEONOFF 40009 +#define IDM_MEMORYDUMP 40010 +#define IDM_DEBUGUTY 40011 +#define IDM_VIEWER 40012 +#define IDM_RESTOREBORDER 40013 +#define IDM_SCRNMUL 40050 +#define IDM_SCRNMUL4 40054 +#define IDM_SCRNMUL6 40056 +#define IDM_SCRNMUL8 40058 +#define IDM_SCRNMUL10 40060 +#define IDM_SCRNMUL12 40062 +#define IDM_SCRNMUL16 40066 +#define IDM_RESET 40101 +#define IDM_CONFIG 40102 +#define IDM_NEWDISK 40103 +#define IDM_CHANGEFONT 40104 +#define IDM_EXIT 40105 +#define IDM_SAVEVMCFG 40106 +#define IDM_LOADVMCFG 40107 +#define IDM_NEWDISKFD 40108 +#define IDM_NEWDISKHD 40109 +#define IDM_PAUSE 40110 +#define IDM_CHANGECLK_X2 40111 +#define IDM_CHANGECLK_X8 40112 +#define IDM_CHANGECLK_X16 40113 +#define IDM_CHANGECLK_X30 40114 +#define IDM_CHANGECLK_X42 40115 +#define IDM_CHANGECLK_RESTORE 40119 +#define IDM_FLAGSAVE 40201 +#define IDM_FLAGSAVE0 40201 +#define IDM_FLAGSAVE1 40202 +#define IDM_FLAGSAVE2 40203 +#define IDM_FLAGSAVE3 40204 +#define IDM_FLAGSAVE4 40205 +#define IDM_FLAGSAVE5 40206 +#define IDM_FLAGSAVE6 40207 +#define IDM_FLAGSAVE7 40208 +#define IDM_FLAGSAVE8 40209 +#define IDM_FLAGSAVE9 40210 +#define IDM_FLAGLOAD 40251 +#define IDM_FLAGLOAD0 40251 +#define IDM_FLAGLOAD1 40252 +#define IDM_FLAGLOAD2 40253 +#define IDM_FLAGLOAD3 40254 +#define IDM_FLAGLOAD4 40255 +#define IDM_FLAGLOAD5 40256 +#define IDM_FLAGLOAD6 40257 +#define IDM_FLAGLOAD7 40258 +#define IDM_FLAGLOAD8 40259 +#define IDM_FLAGLOAD9 40260 +#define IDM_DBSSSAVE0 40270 +#define IDM_DBSSSAVE1 40271 +#define IDM_DBSSSAVE2 40272 +#define IDM_DBSSSAVE3 40273 +#define IDM_DBSSLOAD0 40274 +#define IDM_DBSSLOAD1 40275 +#define IDM_DBSSLOAD2 40276 +#define IDM_DBSSLOAD3 40277 +#define IDM_FDD1OPEN 40301 +#define IDM_FDD2OPEN 40302 +#define IDM_FDD3OPEN 40303 +#define IDM_FDD4OPEN 40304 +#define IDM_FDD1EJECT 40311 +#define IDM_FDD2EJECT 40312 +#define IDM_FDD3EJECT 40313 +#define IDM_FDD4EJECT 40314 +#define IDM_IDE0OPEN 40401 +#define IDM_IDE1OPEN 40402 +#define IDM_IDE2OPEN 40403 +#define IDM_IDE3OPEN 40404 +#define IDM_IDE0EJECT 40411 +#define IDM_IDE1EJECT 40412 +#define IDM_IDE2EJECT 40413 +#define IDM_IDE3EJECT 40414 +#define IDM_SCSI0OPEN 40421 +#define IDM_SCSI1OPEN 40422 +#define IDM_SCSI2OPEN 40423 +#define IDM_SCSI3OPEN 40424 +#define IDM_SCSI4OPEN 40425 +#define IDM_SCSI5OPEN 40426 +#define IDM_SCSI6OPEN 40427 +#define IDM_SCSI7OPEN 40428 +#define IDM_SCSI0EJECT 40431 +#define IDM_SCSI1EJECT 40432 +#define IDM_SCSI2EJECT 40433 +#define IDM_SCSI3EJECT 40434 +#define IDM_SCSI4EJECT 40435 +#define IDM_SCSI5EJECT 40436 +#define IDM_SCSI6EJECT 40437 +#define IDM_SCSI7EJECT 40438 +#define IDM_SXSIOPTION 40441 +#define IDM_IDE0STATE 40451 +#define IDM_IDE1STATE 40452 +#define IDM_IDE2STATE 40453 +#define IDM_IDE3STATE 40454 +#define IDM_IDE0PHYSICALDRV 40461 +#define IDM_IDE1PHYSICALDRV 40462 +#define IDM_IDE2PHYSICALDRV 40463 +#define IDM_IDE3PHYSICALDRV 40464 +#define IDM_SCSI0STATE 40471 +#define IDM_SCSI1STATE 40472 +#define IDM_SCSI2STATE 40473 +#define IDM_SCSI3STATE 40474 +#define IDM_SCSI4STATE 40475 +#define IDM_SCSI5STATE 40476 +#define IDM_SCSI6STATE 40477 +#define IDM_SCSI7STATE 40478 +#define IDM_WINDOW 40501 +#define IDM_FULLSCREEN 40502 +#define IDM_ROLNORMAL 40503 +#define IDM_ROLLEFT 40504 +#define IDM_ROLRIGHT 40505 +#define IDM_DISPSYNC 40506 +#define IDM_RASTER 40507 +#define IDM_NOWAIT 40508 +#define IDM_AUTOFPS 40509 +#define IDM_60FPS 40510 +#define IDM_30FPS 40511 +#define IDM_20FPS 40512 +#define IDM_15FPS 40513 +#define IDM_VF1EN 40517 +#define IDM_VF1P0 40518 +#define IDM_VF1P1 40519 +#define IDM_VF1P2 40520 +#define IDM_VF1BO 40521 +#define IDM_SCREENOPT 40514 +#define IDM_CPUSTABILIZER 40515 +#define IDM_ASYNCCPU 40516 +#define IDM_KEY 40601 +#define IDM_JOY1 40602 +#define IDM_JOY2 40603 +#define IDM_KEYMOUSE 40604 +#define IDM_XSHIFT 40611 +#define IDM_XCTRL 40612 +#define IDM_XGRPH 40613 +#define IDM_SENDCAD 40614 +#define IDM_USENUMLOCK 40615 +#define IDM_SWAPPAGEUPDOWN 40616 +#define IDM_F12MOUSE 40621 +#define IDM_F12COPY 40622 +#define IDM_F12STOP 40623 +#define IDM_F12EQU 40624 +#define IDM_F12COMMA 40625 +#define IDM_USERKEY1 40626 +#define IDM_USERKEY2 40627 +#define IDM_F12NOWAIT 40628 +#define IDM_F12NOWAIT2 40629 +#define IDM_F12WABRELAY 40630 +#define IDM_BEEPOFF 40631 +#define IDM_BEEPLOW 40632 +#define IDM_BEEPMID 40633 +#define IDM_BEEPHIGH 40634 +#define IDM_NOSOUND 40641 +#define IDM_PC9801_14 40642 +#define IDM_PC9801_26K 40643 +#define IDM_PC9801_86 40644 +#define IDM_PC9801_26_86 40645 +#define IDM_PC9801_86_CB 40646 +#define IDM_PC9801_118 40647 +#define IDM_SPEAKBOARD 40648 +#define IDM_SPARKBOARD 40649 +#define IDM_PX1 40650 +#define IDM_PX2 40651 +#define IDM_AMD98 40652 +#define IDM_JASTSOUND 40653 +#define IDM_SEEKSND 40654 +#define IDM_SOUNDORCHESTRA 40655 +#define IDM_SOUNDORCHESTRAV 40656 +#define IDM_PC9801_86_WSS 40657 +#define IDM_MATE_X_PCM 40658 +#define IDM_SB16 40659 +#define IDM_LITTLEORCHESTRAL 40810 +#define IDM_MMORCHESTRA 40811 +#define IDM_PC9801_86_118 49650 +#define IDM_86SPEAKBOARD 49651 +#define IDM_WAVESTAR 49652 +#define IDM_PC9801_118_SB16 49655 +#define IDM_PC9801_86_118_SB16 49656 +#define IDM_PC9801_86_WSS_SB16 49657 +#define IDM_WSS_SB16 49658 +#define IDM_PC9801_86_SB16 49659 +#define IDM_MEM640 40661 +#define IDM_MEM16 40662 +#define IDM_MEM36 40663 +#define IDM_MEM76 40664 +#define IDM_MEM116 40665 +#define IDM_MEM136 40666 +#define IDM_MEM166 40667 +#define IDM_MEM326 40668 +#define IDM_MEM646 40669 +#define IDM_MEM1206 40670 +#define IDM_MEM2306 49671 +#define IDM_MEM5126 49672 +#define IDM_MEM10246 49673 +#define IDM_MOUSE 40671 +#define IDM_SERIAL1 40672 +#define IDM_MPUPC98 40673 +#define IDM_MIDIPANIC 40674 +#define IDM_SNDOPT 40675 +#define IDM_NETOPT 40676 +#define IDM_WABOPT 40677 +#define IDM_HOSTDRVOPT 40678 +#define IDM_PCIOPT 40679 +#define IDM_FPU80 49680 +#define IDM_FPU64 49681 +#define IDM_FPU64INT 49682 +#define IDM_MOUSEWHEELCTL 40688 +#define IDM_MOUSENC 40689 +#define IDM_MOUSERAW 40690 +#define IDM_MOUSE30X 40691 +#define IDM_MOUSE20X 40692 +#define IDM_MOUSE15X 40693 +#define IDM_MOUSE10X 40694 +#define IDM_MOUSED2X 40695 +#define IDM_MOUSED3X 40696 +#define IDM_MOUSED4X 40697 +#define IDM_BMPSAVE 40701 +#define IDM_S98LOGGING 40702 +#define IDM_WAVEREC 40703 +#define IDM_CALENDAR 40704 +#define IDM_DISPCLOCK 40705 +#define IDM_DISPFRAME 40706 +#define IDM_JOYX 40707 +#define IDM_RAPID 40708 +#define IDM_MSRAPID 40709 +#define IDM_SSTP 40710 +#define IDM_CPUSAVE 40711 +#define IDM_HELP 40712 +#define IDM_ABOUT 40713 +#define IDM_ITFWORK 40714 +#define IDM_TXTSAVE 40715 +#define IDM_TIMERFIX 40716 +#define IDM_SKIP16MEMCHK 40717 +#define IDM_FASTMEMCHK 40718 +#define IDM_ALTENTER 40721 +#define IDM_ALTF4 40722 +#define IDM_SYSKHOOK 40729 +#define IDM_HF_ENABLE 40730 +#define IDM_HF_ADDITIONAL 40731 +#define IDM_EN_DBSS 40732 +#define IDM_IDEOPT 40800 +#define IDM_CLOSE 41001 +#define IDM_TOOL_SKIN 41101 +#define IDM_TOOL_SKINSEL 41111 +#define IDM_TOOL_SKINDEF 41112 +#define IDM_TOOL_SKINMRU 41151 +#define IDM_TOOL_SKINMRU1 41152 +#define IDM_TOOL_SKINMRU2 41153 +#define IDM_TOOL_SKINMRU3 41154 +#define IDM_BMS 41155 +#define IDM_KDISPFM 42001 +#define IDM_KDISPMIDI 42002 +#define IDM_VIEWWINNEW 43001 +#define IDM_VIEWWINCLOSE 43002 +#define IDM_VIEWWINALLCLOSE 43003 +#define IDM_VIEWMODEREG 43011 +#define IDM_VIEWMODESEG 43012 +#define IDM_VIEWMODE1MB 43013 +#define IDM_VIEWMODEASM 43014 +#define IDM_VIEWMODESND 43015 +#define IDM_VIEWMODELOCK 43016 +#define IDM_SETSEG 43021 +#define IDM_SEGCS 43022 +#define IDM_SEGDS 43023 +#define IDM_SEGES 43024 +#define IDM_SEGSS 43025 +#define IDM_SEGTEXT 43026 +#define IDM_RELOAD 43027 +#define IDM_VRAM0 43031 +#define IDM_VRAM1 43032 +#define IDM_BIOS 43033 +#define IDM_ITF 43034 +#define IDM_A20LINE 43035 +#define IDM_TRACE_TRACE 43101 +#define IDM_TRACE_VERBOSE 43102 +#define IDM_TRACE_ENABLE 43103 +#define IDM_TRACE_FILEOUT 43104 +#define IDM_TRACE_CLEAR 43105 +#define IDM_COPYPASTE_COPYTVRAM 43201 +#define IDM_COPYPASTE_COPYGVRAM 43202 +#define IDM_COPYPASTE_COPYWABMEM 43203 +#define IDM_COPYPASTE_PASTE 43210 +#define IDM_WABSYSMENU_RESETSIZE 43301 +#define IDM_WABSYSMENU_HALFTONE 43302 +#define IDM_IDE0PHYSICALDRV_ID0 43400 // size = 26*4 +#define IDM_IDE0PHYSICALDRV_LAST 43503 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40135 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/windows/resources/resource.cpp b/windows/resources/resource.cpp old mode 100755 new mode 100644 index 827c29ce..a75e95b6 --- a/windows/resources/resource.cpp +++ b/windows/resources/resource.cpp @@ -1,12 +1,12 @@ -#include - -#pragma comment(linker, "/nodefaultlib") - -#ifdef __cplusplus -extern "C" -#endif -BOOL APIENTRY _DllMainCRTStartup(HANDLE hModule, DWORD ulReasonForCall, LPVOID lpvReserved) -{ - return TRUE; -} - +#include + +#pragma comment(linker, "/nodefaultlib") + +#ifdef __cplusplus +extern "C" +#endif +BOOL APIENTRY _DllMainCRTStartup(HANDLE hModule, DWORD ulReasonForCall, LPVOID lpvReserved) +{ + return TRUE; +} + diff --git a/windows/scrnmng.cpp b/windows/scrnmng.cpp index 0da60b9a..8010b8bf 100644 --- a/windows/scrnmng.cpp +++ b/windows/scrnmng.cpp @@ -43,8 +43,8 @@ SCRNRESCFG scrnrescfg = {0}; int d3davailable = 0; -static BOOL scrnmng_cs_initialized = 0; // Screen Manager NeBJZNV ς݃tO -static CRITICAL_SECTION scrnmng_cs = {0}; // Screen Manager surflock in/out NeBJZNV +static BOOL scrnmng_cs_initialized = 0; // Screen Manager クリティカルセクション 初期化済みフラグ +static CRITICAL_SECTION scrnmng_cs = {0}; // Screen Manager surflock in/out クリティカルセクション static void scrnmng_cs_Initialize(){ if(!scrnmng_cs_initialized){ InitializeCriticalSection(&scrnmng_cs); @@ -71,9 +71,9 @@ void scrnmng_cs_LeaveModeChangeCriticalSection(){ // ---- UINT8 scrnmng_current_drawtype = DRAWTYPE_INVALID; -bool scrnmng_create_pending = false; // OtBbN_ۗ +bool scrnmng_create_pending = false; // グラフィックレンダラ生成保留中 bool scrnmng_restore_pending = false; -static bool scrnmng_changemode_pending = false; // ʃ[hύXۗ +static bool scrnmng_changemode_pending = false; // 画面モード変更保留中 static int scrnmng_changemode_posx = INT_MAX; static int scrnmng_changemode_posy = INT_MAX; static int scrnmng_changemode_width = INT_MAX; @@ -84,7 +84,7 @@ static bool scrnmng_changemode_updatefsres = false; static DWORD scrnmng_UIthreadID = 0; /** - * ݒ + * 設定 */ static const PFTBL s_scrnresini[] = { @@ -95,7 +95,7 @@ static const PFTBL s_scrnresini[] = }; /** - * ݒǂݍ + * 設定読み込み */ void scrnres_readini() { @@ -121,7 +121,7 @@ void scrnres_readini_res(int width, int height) } /** - * ݒ菑 + * 設定書き込み */ void scrnres_writeini() { @@ -143,7 +143,7 @@ void scrnmng_setwindowsize(HWND hWnd, int width, int height) const int scx = GetSystemMetrics(SM_CXSCREEN); const int scy = GetSystemMetrics(SM_CYSCREEN); - // }`j^bΉ ver0.86 rev30 + // マルチモニタ暫定対応 ver0.86 rev30 workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); @@ -152,7 +152,7 @@ void scrnmng_setwindowsize(HWND hWnd, int width, int height) { RECT rectwindow; int marginX, marginY; - winloc_getDWMmargin(hWnd, &marginX, &marginY); // Win10‹p̑΍ + winloc_getDWMmargin(hWnd, &marginX, &marginY); // Win10環境用の対策 GetWindowRect(hWnd, &rectwindow); RECT rectclient; GetClientRect(hWnd, &rectclient); @@ -219,7 +219,7 @@ void scrnmng_initialize(void) { BRESULT scrnmng_create(UINT8 scrnmode) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return 1; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return 1; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D scrnmng_current_drawtype = np2oscfg.drawtype; @@ -247,7 +247,7 @@ BRESULT scrnmng_create(UINT8 scrnmode) { void scrnmng_destroy(void) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_DIRECT3D){ @@ -272,7 +272,7 @@ void scrnmng_shutdown(void) { void scrnmng_querypalette(void) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_INVALID) {return;} @@ -287,7 +287,7 @@ void scrnmng_querypalette(void) { RGB16 scrnmng_makepal16(RGB32 pal32) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return 0; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return 0; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_INVALID) {return 0;} @@ -302,7 +302,7 @@ RGB16 scrnmng_makepal16(RGB32 pal32) { void scrnmng_fullscrnmenu(int y) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_INVALID) {return;} @@ -319,7 +319,7 @@ void scrnmng_fullscrnmenu(int y) { void scrnmng_topwinui(void) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_INVALID) {return;} @@ -336,7 +336,7 @@ void scrnmng_topwinui(void) { void scrnmng_clearwinui(void) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_INVALID) {return;} @@ -354,7 +354,7 @@ void scrnmng_clearwinui(void) { void scrnmng_setwidth(int posx, int width) { if(scrnmng_UIthreadID != GetCurrentThreadId()){ - // ʂ̃Xbh̃ANZX̏ꍇAxύX + // 別のスレッドからのアクセスの場合、遅延変更 scrnmng_cs_EnterModeChangeCriticalSection(); scrnmng_changemode_posx = posx; scrnmng_changemode_width = width; @@ -383,7 +383,7 @@ void scrnmng_setwidth(int posx, int width) { void scrnmng_setextend(int extend) { if(scrnmng_UIthreadID != GetCurrentThreadId()){ - // ʂ̃Xbh̃ANZX̏ꍇAxύX + // 別のスレッドからのアクセスの場合、遅延変更 scrnmng_cs_EnterModeChangeCriticalSection(); scrnmng_changemode_extend = extend; scrnmng_changemode_pending = true; @@ -406,7 +406,7 @@ void scrnmng_setextend(int extend) { void scrnmng_setheight(int posy, int height) { if(scrnmng_UIthreadID != GetCurrentThreadId()){ - // ʂ̃Xbh̃ANZX̏ꍇAxύX + // 別のスレッドからのアクセスの場合、遅延変更 scrnmng_cs_EnterModeChangeCriticalSection(); scrnmng_changemode_posy = posy; scrnmng_changemode_height = height; @@ -435,7 +435,7 @@ void scrnmng_setheight(int posy, int height) { void scrnmng_setsize(int posx, int posy, int width, int height) { if(scrnmng_UIthreadID != GetCurrentThreadId()){ - // ʂ̃Xbh̃ANZX̏ꍇAxύX + // 別のスレッドからのアクセスの場合、遅延変更 scrnmng_cs_EnterModeChangeCriticalSection(); scrnmng_changemode_posx = posx; scrnmng_changemode_posy = posy; @@ -507,7 +507,7 @@ void scrnmng_update(void) { void scrnmng_setmultiple(int multiple) { if(scrnmng_UIthreadID != GetCurrentThreadId()){ - // ʂ̃Xbh̃ANZX̏ꍇAxύX + // 別のスレッドからのアクセスの場合、遅延変更 scrnmng_cs_EnterModeChangeCriticalSection(); scrnmng_changemode_multiple = multiple; scrnmng_changemode_pending = true; @@ -559,7 +559,7 @@ int scrnmng_getmultiple(void) #if defined(SUPPORT_DCLOCK) BOOL scrnmng_isdispclockclick(const POINT *pt) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return FALSE; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return FALSE; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_INVALID) {return FALSE;} @@ -574,7 +574,7 @@ BOOL scrnmng_isdispclockclick(const POINT *pt) { void scrnmng_dispclock(void) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_INVALID) {return;} @@ -593,7 +593,7 @@ void scrnmng_dispclock(void) void scrnmng_entersizing(void) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_DIRECT3D){ @@ -609,7 +609,7 @@ void scrnmng_entersizing(void) { void scrnmng_sizing(UINT side, RECT *rect) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_DIRECT3D){ @@ -625,7 +625,7 @@ void scrnmng_sizing(UINT side, RECT *rect) { void scrnmng_exitsizing(void) { - if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_DIRECT3D){ @@ -639,10 +639,10 @@ void scrnmng_exitsizing(void) } } -// tXN[𑜓x +// フルスクリーン解像度調整 void scrnmng_updatefsres(void) { if(scrnmng_UIthreadID != GetCurrentThreadId()){ - // ʂ̃Xbh̃ANZX̏ꍇAxύX + // 別のスレッドからのアクセスの場合、遅延変更 scrnmng_cs_EnterModeChangeCriticalSection(); scrnmng_changemode_updatefsres = true; scrnmng_changemode_pending = true; @@ -661,7 +661,7 @@ void scrnmng_updatefsres(void) { } } -// EBhEANZ[^ʓ] +// ウィンドウアクセラレータ画面転送 void scrnmng_blthdc(HDC hdc) { #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_DIRECT3D){ @@ -684,7 +684,7 @@ void scrnmng_bltwab() { } void scrnmng_getrect(RECT *lpRect){ - if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // ʂ̃Xbh̃ANZX͕s + if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 #ifdef SUPPORT_SCRN_DIRECT3D if(scrnmng_current_drawtype==DRAWTYPE_DIRECT3D){ @@ -697,7 +697,7 @@ void scrnmng_getrect(RECT *lpRect){ } void scrnmng_delaychangemode(void){ - //if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // ʂ̃Xbh̃ANZX͕s + //if(scrnmng_UIthreadID != GetCurrentThreadId()) return; // 別のスレッドからのアクセスは不可 if(scrnmng_changemode_pending){ DWORD oldThreadID; diff --git a/windows/scrnmng.h b/windows/scrnmng.h index c19795dd..756ff140 100644 --- a/windows/scrnmng.h +++ b/windows/scrnmng.h @@ -1,162 +1,162 @@ -#ifndef _SCRNMNG_H_ -#define _SCRNMNG_H_ - -enum { - RGB24_B = 0, - RGB24_G = 1, - RGB24_R = 2 -}; - -typedef struct { - UINT8 *ptr; - int xalign; - int yalign; - int width; - int height; - UINT bpp; - int extend; -} SCRNSURF; - -enum { - DRAWTYPE_DIRECTDRAW_HW = 0x00, - DRAWTYPE_DIRECTDRAW_SW = 0x01, - DRAWTYPE_DIRECT3D = 0x02, - DRAWTYPE_INVALID = 0xff -}; - -enum { - D3D_IMODE_NEAREST_NEIGHBOR = 0x00, - D3D_IMODE_BILINEAR = 0x01, - D3D_IMODE_PIXEL = 0x02, - D3D_IMODE_PIXEL2 = 0x03, - D3D_IMODE_PIXEL3 = 0x04, -}; - -enum { - SCRNMODE_FULLSCREEN = 0x01, - SCRNMODE_HIGHCOLOR = 0x02, - SCRNMODE_ROTATE = 0x10, - SCRNMODE_ROTATEDIR = 0x20, - SCRNMODE_ROTATELEFT = (SCRNMODE_ROTATE + 0), - SCRNMODE_ROTATERIGHT = (SCRNMODE_ROTATE + SCRNMODE_ROTATEDIR), - SCRNMODE_ROTATEMASK = 0x30, -}; - -enum { - SCRNFLAG_FULLSCREEN = 0x01, - SCRNFLAG_HAVEEXTEND = 0x02, - SCRNFLAG_ENABLE = 0x80 -}; - -enum { - FSCRNMOD_NORESIZE = 0x00, - FSCRNMOD_ASPECTFIX8 = 0x01, - FSCRNMOD_ASPECTFIX = 0x02, - FSCRNMOD_LARGE = 0x03, - FSCRNMOD_ASPECTMASK = 0x13, - FSCRNMOD_SAMERES = 0x04, - FSCRNMOD_SAMEBPP = 0x08, - FSCRNMOD_INTMULTIPLE = 0x10, - FSCRNMOD_FORCE43 = 0x11 -}; - -typedef struct { - UINT8 flag; - UINT8 bpp; - UINT8 allflash; - UINT8 palchanged; - UINT8 forcereset; -} SCRNMNG; - -typedef struct { - int width; - int height; - int extend; - int multiple; -} SCRNSTAT; - -typedef struct { - UINT8 hasfscfg; - UINT8 fscrnmod; - UINT8 scrn_mul; - UINT8 d3d_imode; -} SCRNRESCFG; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern SCRNMNG scrnmng; // マクロ用 -extern SCRNSTAT scrnstat; -extern SCRNRESCFG scrnrescfg; - -#define FSCRNCFG_fscrnmod (np2oscfg.fsrescfg && scrnrescfg.hasfscfg ? scrnrescfg.fscrnmod : np2oscfg.fscrnmod) -#define FSCRNCFG_d3d_imode (np2oscfg.fsrescfg && scrnrescfg.hasfscfg ? scrnrescfg.d3d_imode : np2oscfg.d3d_imode) - -void scrnres_readini(); -void scrnres_readini_res(int width, int height); -void scrnres_writeini(); - -extern UINT8 scrnmng_current_drawtype; - -void scrnmng_setwindowsize(HWND hWnd, int width, int height); - -void scrnmng_initialize(void); -BRESULT scrnmng_create(UINT8 scrnmode); -void scrnmng_destroy(void); -void scrnmng_shutdown(void); - -void scrnmng_setwidth(int posx, int width); -void scrnmng_setextend(int extend); -void scrnmng_setheight(int posy, int height); -void scrnmng_setsize(int posx, int posy, int width, int height); -#define scrnmng_setbpp(commendablebpp) -const SCRNSURF *scrnmng_surflock(void); -void scrnmng_surfunlock(const SCRNSURF *surf); -void scrnmng_update(void); - -#define scrnmng_isfullscreen() (scrnmng.flag & SCRNFLAG_FULLSCREEN) -#define scrnmng_haveextend() (scrnmng.flag & SCRNFLAG_HAVEEXTEND) -#define scrnmng_getbpp() (scrnmng.bpp) -#define scrnmng_allflash() scrnmng.allflash = TRUE -#define scrnmng_palchanged() scrnmng.palchanged = TRUE - -RGB16 scrnmng_makepal16(RGB32 pal32); - - -// ---- for windows - -void scrnmng_setmultiple(int multiple); -int scrnmng_getmultiple(void); -void scrnmng_querypalette(void); -void scrnmng_setdefaultres(void); -void scrnmng_setfullscreen(BOOL fullscreen); -void scrnmng_setrotatemode(UINT type); -void scrnmng_fullscrnmenu(int y); -void scrnmng_topwinui(void); -void scrnmng_clearwinui(void); - -void scrnmng_entersizing(void); -void scrnmng_sizing(UINT side, RECT *rect); -void scrnmng_exitsizing(void); - -void scrnmng_updatefsres(void); -void scrnmng_blthdc(HDC hdc); -void scrnmng_bltwab(void); - -void scrnmng_getrect(RECT *lpRect); - -void scrnmng_delaychangemode(); -void scrnmng_UIThreadProc(); - -#if defined(SUPPORT_DCLOCK) -BOOL scrnmng_isdispclockclick(const POINT *pt); -void scrnmng_dispclock(void); -#endif - -#ifdef __cplusplus -} -#endif - -#endif // _SCRNMNG_H_ +#ifndef _SCRNMNG_H_ +#define _SCRNMNG_H_ + +enum { + RGB24_B = 0, + RGB24_G = 1, + RGB24_R = 2 +}; + +typedef struct { + UINT8 *ptr; + int xalign; + int yalign; + int width; + int height; + UINT bpp; + int extend; +} SCRNSURF; + +enum { + DRAWTYPE_DIRECTDRAW_HW = 0x00, + DRAWTYPE_DIRECTDRAW_SW = 0x01, + DRAWTYPE_DIRECT3D = 0x02, + DRAWTYPE_INVALID = 0xff +}; + +enum { + D3D_IMODE_NEAREST_NEIGHBOR = 0x00, + D3D_IMODE_BILINEAR = 0x01, + D3D_IMODE_PIXEL = 0x02, + D3D_IMODE_PIXEL2 = 0x03, + D3D_IMODE_PIXEL3 = 0x04, +}; + +enum { + SCRNMODE_FULLSCREEN = 0x01, + SCRNMODE_HIGHCOLOR = 0x02, + SCRNMODE_ROTATE = 0x10, + SCRNMODE_ROTATEDIR = 0x20, + SCRNMODE_ROTATELEFT = (SCRNMODE_ROTATE + 0), + SCRNMODE_ROTATERIGHT = (SCRNMODE_ROTATE + SCRNMODE_ROTATEDIR), + SCRNMODE_ROTATEMASK = 0x30, +}; + +enum { + SCRNFLAG_FULLSCREEN = 0x01, + SCRNFLAG_HAVEEXTEND = 0x02, + SCRNFLAG_ENABLE = 0x80 +}; + +enum { + FSCRNMOD_NORESIZE = 0x00, + FSCRNMOD_ASPECTFIX8 = 0x01, + FSCRNMOD_ASPECTFIX = 0x02, + FSCRNMOD_LARGE = 0x03, + FSCRNMOD_ASPECTMASK = 0x13, + FSCRNMOD_SAMERES = 0x04, + FSCRNMOD_SAMEBPP = 0x08, + FSCRNMOD_INTMULTIPLE = 0x10, + FSCRNMOD_FORCE43 = 0x11 +}; + +typedef struct { + UINT8 flag; + UINT8 bpp; + UINT8 allflash; + UINT8 palchanged; + UINT8 forcereset; +} SCRNMNG; + +typedef struct { + int width; + int height; + int extend; + int multiple; +} SCRNSTAT; + +typedef struct { + UINT8 hasfscfg; + UINT8 fscrnmod; + UINT8 scrn_mul; + UINT8 d3d_imode; +} SCRNRESCFG; + + +#ifdef __cplusplus +extern "C" { +#endif + +extern SCRNMNG scrnmng; // マクロ用 +extern SCRNSTAT scrnstat; +extern SCRNRESCFG scrnrescfg; + +#define FSCRNCFG_fscrnmod (np2oscfg.fsrescfg && scrnrescfg.hasfscfg ? scrnrescfg.fscrnmod : np2oscfg.fscrnmod) +#define FSCRNCFG_d3d_imode (np2oscfg.fsrescfg && scrnrescfg.hasfscfg ? scrnrescfg.d3d_imode : np2oscfg.d3d_imode) + +void scrnres_readini(); +void scrnres_readini_res(int width, int height); +void scrnres_writeini(); + +extern UINT8 scrnmng_current_drawtype; + +void scrnmng_setwindowsize(HWND hWnd, int width, int height); + +void scrnmng_initialize(void); +BRESULT scrnmng_create(UINT8 scrnmode); +void scrnmng_destroy(void); +void scrnmng_shutdown(void); + +void scrnmng_setwidth(int posx, int width); +void scrnmng_setextend(int extend); +void scrnmng_setheight(int posy, int height); +void scrnmng_setsize(int posx, int posy, int width, int height); +#define scrnmng_setbpp(commendablebpp) +const SCRNSURF *scrnmng_surflock(void); +void scrnmng_surfunlock(const SCRNSURF *surf); +void scrnmng_update(void); + +#define scrnmng_isfullscreen() (scrnmng.flag & SCRNFLAG_FULLSCREEN) +#define scrnmng_haveextend() (scrnmng.flag & SCRNFLAG_HAVEEXTEND) +#define scrnmng_getbpp() (scrnmng.bpp) +#define scrnmng_allflash() scrnmng.allflash = TRUE +#define scrnmng_palchanged() scrnmng.palchanged = TRUE + +RGB16 scrnmng_makepal16(RGB32 pal32); + + +// ---- for windows + +void scrnmng_setmultiple(int multiple); +int scrnmng_getmultiple(void); +void scrnmng_querypalette(void); +void scrnmng_setdefaultres(void); +void scrnmng_setfullscreen(BOOL fullscreen); +void scrnmng_setrotatemode(UINT type); +void scrnmng_fullscrnmenu(int y); +void scrnmng_topwinui(void); +void scrnmng_clearwinui(void); + +void scrnmng_entersizing(void); +void scrnmng_sizing(UINT side, RECT *rect); +void scrnmng_exitsizing(void); + +void scrnmng_updatefsres(void); +void scrnmng_blthdc(HDC hdc); +void scrnmng_bltwab(void); + +void scrnmng_getrect(RECT *lpRect); + +void scrnmng_delaychangemode(); +void scrnmng_UIThreadProc(); + +#if defined(SUPPORT_DCLOCK) +BOOL scrnmng_isdispclockclick(const POINT *pt); +void scrnmng_dispclock(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // _SCRNMNG_H_ diff --git a/windows/scrnmng_d3d.cpp b/windows/scrnmng_d3d.cpp index c0957833..d2acceaa 100644 --- a/windows/scrnmng_d3d.cpp +++ b/windows/scrnmng_d3d.cpp @@ -42,7 +42,7 @@ #pragma comment( lib, "d3d9.lib" ) #endif // !defined(__GNUC__) -//! 8BPP pbg +//! 8BPP パレット数 #define PALLETES_8BPP NP2PAL_TEXT3 #define CREATEDEVICE_RETRY_MAX 3 @@ -52,7 +52,7 @@ static int nvidia_fixflag = 0; static int devicelostflag = 0; static int req_enter_criticalsection = 0; -extern bool scrnmng_create_pending; // OtBbN_ۗ +extern bool scrnmng_create_pending; // グラフィックレンダラ生成保留中 extern bool scrnmng_restore_pending; extern WINLOCEX np2_winlocexallwin(HWND base); @@ -228,7 +228,7 @@ static void renewalclientsize(BOOL winloc) { extend = 0; - // `͈́` + // 描画範囲~ if (d3d.scrnmode & SCRNMODE_FULLSCREEN) { d3d.rect.right = width; d3d.rect.bottom = height; @@ -245,7 +245,7 @@ static void renewalclientsize(BOOL winloc) { d3d.scrn.right = d3d.scrn.left + scrnwidth; d3d.scrn.bottom = d3d.scrn.top + scrnheight; - // j[\̕`̈ + // メニュー表示時の描画領域 d3d.rectclip = d3d.rect; d3d.scrnclip = d3d.scrn; if (d3d.scrnclip.top < d3d.menusize) { @@ -272,7 +272,7 @@ static void renewalclientsize(BOOL winloc) { } d3d.scrnclip.bottom = d3d.menusize + tmpcy; } - // Direct3D̓j[Oς݃TCY̂ߏC + // Direct3Dはメニュー除外済みサイズが基準のため修正 d3d.scrnclip.top -= d3d.menusize; d3d.scrnclip.bottom -= d3d.menusize; d3d.scrnclip.top += d3d.menusize * d3d.scrnclip.top / d3d.height; @@ -507,7 +507,7 @@ void scrnmngD3D_restoresurfaces() { D3DSURFACE_DESC d3dsdesc; if(devicelostflag==2 || devicelostflag==3 || d3d.d3ddev==NULL){ - // č쐬 + // 強制再作成 if(devicelostflag==2){ devicelostflag = 0; scrnmngD3D_destroy(); @@ -534,7 +534,7 @@ void scrnmngD3D_restoresurfaces() { #endif #if defined(SUPPORT_WAB) if (d3d.wabsurf) { - mt_wabpausedrawing = 1; // MultiThread΍ + mt_wabpausedrawing = 1; // MultiThread対策 while(mt_wabdrawing) Sleep(10); d3d.wabsurf->GetDesc(&d3dsdesc); @@ -609,7 +609,7 @@ void scrnmngD3D_restoresurfaces() { } } -// 𑜓xgp”\`FbN +// 解像度が使用可能かをチェック static int checkResolution(int width, int height) { UINT count; UINT i; @@ -675,7 +675,7 @@ static BOOL CALLBACK monitorInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRE typedef IDirect3D9 * (WINAPI *TEST_DIRECT3DCREATE9)(UINT SDKVersion); BRESULT scrnmngD3D_check() { - // Direct3Dgpł邩`FbN + x_mF + // Direct3Dが使用できるかチェック + ベンダ確認 HMODULE hModule; TEST_DIRECT3DCREATE9 fnd3dcreate9; LPDIRECT3D9 test_d3d; @@ -724,7 +724,7 @@ BRESULT scrnmngD3D_check() { } } } - // foCX쐬܂ŏoȂOKƂ + // デバイス作成まで出来そうならOKとする test_d3ddev->Release(); test_d3d->Release(); FreeLibrary(hModule); @@ -754,7 +754,7 @@ BRESULT scrnmngD3D_create(UINT8 scrnmode) { int bufwidth, bufheight; int k = 0; - np2oscfg.d3d_exclusive = 0;// r[h͔p~ + np2oscfg.d3d_exclusive = 0;// 排他モードは廃止 if(devicelostflag) return(FAILURE); @@ -802,7 +802,7 @@ BRESULT scrnmngD3D_create(UINT8 scrnmode) { winstyle &= ~CS_DBLCLKS; if (np2oscfg.wintype != 0) { WINLOCEX wlex; - // XXX: j[oȂȂċlނ̂ibj + // XXX: メニューが出せなくなって詰むのを回避(暫定) np2oscfg.wintype = 0; np2oscfg.wintype = 0; wlex = np2_winlocexallwin(g_hWndMain); @@ -881,23 +881,23 @@ BRESULT scrnmngD3D_create(UINT8 scrnmode) { fscrnmod = FSCRNCFG_fscrnmod; - // r[hgȂƂ + // 排他モードを使わないとき if(!np2oscfg.d3d_exclusive){ MONITORINFOENUMDATA mondata = {0}; - fscrnmod |= FSCRNMOD_SAMERES | FSCRNMOD_SAMEBPP; // r[hgȂƂA𑜓xύXȂƂɂiłȂ͂Ȃʓ|ȂƂ̏Ȃj - GetWindowRect(g_hWndMain, &mondata.np2windowrect); // LEBhËʒuƃTCY擾 - EnumDisplayMonitors(NULL, NULL, (MONITORENUMPROC)monitorInfoEnumProc, (LPARAM)&mondata); // L̂郂j^[T + fscrnmod |= FSCRNMOD_SAMERES | FSCRNMOD_SAMEBPP; // 排他モードを使わないとき、解像度変更しないことにする(できなくはないが面倒なことこの上ない) + GetWindowRect(g_hWndMain, &mondata.np2windowrect); // 猫ウィンドウの位置とサイズを取得 + EnumDisplayMonitors(NULL, NULL, (MONITORENUMPROC)monitorInfoEnumProc, (LPARAM)&mondata); // 猫のいるモニターを探す if(!mondata.found){ - // LǂɂȂɂ̓vC}j^ + // 猫どこにもいない時にはプライマリモニタで mondata.monitorrect.left = mondata.monitorrect.top = 0; mondata.monitorrect.right = GetSystemMetrics(SM_CXSCREEN); mondata.monitorrect.bottom = GetSystemMetrics(SM_CYSCREEN); } MoveWindow(g_hWndMain, mondata.monitorrect.left, mondata.monitorrect.top, - mondata.monitorrect.right - mondata.monitorrect.left, mondata.monitorrect.bottom - mondata.monitorrect.top, TRUE); // EBhETCYSʂɕς + mondata.monitorrect.right - mondata.monitorrect.left, mondata.monitorrect.bottom - mondata.monitorrect.top, TRUE); // ウィンドウサイズを全画面に変える } if(np2_multithread_Enabled()){ - fscrnmod |= FSCRNMOD_SAMERES | FSCRNMOD_SAMEBPP; // }`Xbh[ĥƂ𑜓xύXȂƂɂi蔲j + fscrnmod |= FSCRNMOD_SAMERES | FSCRNMOD_SAMEBPP; // マルチスレッドモードのときも解像度変更しないことにする(手抜き) } if(!(fscrnmod & FSCRNMOD_SAMERES)){ @@ -975,15 +975,15 @@ BRESULT scrnmngD3D_create(UINT8 scrnmode) { #ifdef SUPPORT_WAB //if(!np2wabwnd.multiwindow && (np2wab.relay&0x3)!=0 && np2wab.realWidth>=640 && np2wab.realHeight>=400){ if(!np2wabwnd.multiwindow && (np2wab.relay&0x3)!=0 && scrnstat.width>=640 && scrnstat.height>=400){ - // TCY + // 実サイズに width = wabwidth = bufwidth = scrnstat.width;//np2wab.realWidth; height = wabheight = bufheight = scrnstat.height;//np2wab.realHeight; if (scrnmode & SCRNMODE_ROTATE) { wabwidth = bufwidth = scrnstat.height; wabheight = bufheight = scrnstat.width; } - bufwidth++; // +1ȂƑʖڂ炵 - bufheight++; // +1ȂƑʖڂ炵 + bufwidth++; // +1しないと駄目らしい + bufheight++; // +1しないと駄目らしい }else{ if (!(scrnmode & SCRNMODE_ROTATE)) { wabwidth = 640; @@ -1062,12 +1062,12 @@ BRESULT scrnmngD3D_create(UINT8 scrnmode) { d3d.height = height; d3d.cliping = 0; //if (scrnmode & SCRNMODE_FULLSCREEN) { - renewalclientsize(TRUE); // XXX: XibvN̂ŎbTRUE + renewalclientsize(TRUE); // XXX: スナップ解除等が起こるので暫定TRUE //} lastscrnmode = scrnmode; // screenupdate = 3; // update! #if defined(SUPPORT_WAB) - mt_wabpausedrawing = 0; // MultiThread΍ + mt_wabpausedrawing = 0; // MultiThread対策 #endif d3d_leave_criticalsection(); @@ -1094,7 +1094,7 @@ void scrnmngD3D_destroy(void) { #endif #if defined(SUPPORT_WAB) if (d3d.wabsurf) { - mt_wabpausedrawing = 1; // MultiThread΍ + mt_wabpausedrawing = 1; // MultiThread対策 while(mt_wabdrawing) Sleep(10); d3d.wabsurf->Release(); @@ -1503,39 +1503,39 @@ void scrnmngD3D_update(void) { RECT lastrect = *rect; RECT lastscrn = *scrn; - rect->right++; // Ȃ̒ - scrn->left -= scrnoffset; // Ȃ̒ + rect->right++; // なぞの調整 + scrn->left -= scrnoffset; // なぞの調整 if(scrn->left < 0){ // for full mode - rect->left++; // Ȃ̒ - scrn->left += scrnoffset; // Ȃ̒ + rect->left++; // なぞの調整 + scrn->left += scrnoffset; // なぞの調整 } rectbuf.right = (rect->right - rect->left) * d3d.backsurf2mul; rectbuf.bottom = (rect->bottom - rect->top) * d3d.backsurf2mul; if(d3d.backsurf2mul > 1){ - // ]1pxY΍ + // 転送時の1pxズレ対策 rectsrcbuf = *rect; rectdstbuf = rectbuf; if(nvidia_fixflag){ rectsrcbuf.left = rectsrcbuf.right - 1; rectdstbuf.left = rectdstbuf.right - ((1 << (d3d.backsurf2mul-1)) >> 1); rectdstbuf.bottom -= ((1 << (d3d.backsurf2mul-1)) >> 1); - r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // E[ + r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // 右端 rectsrcbuf = *rect; rectdstbuf = rectbuf; rectsrcbuf.top = rectsrcbuf.bottom - 1; rectdstbuf.top = rectdstbuf.bottom - ((1 << (d3d.backsurf2mul-1)) >> 1); rectdstbuf.right -= ((1 << (d3d.backsurf2mul-1)) >> 1); - r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // [ + r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // 下端 rectsrcbuf = *rect; rectdstbuf = rectbuf; rectsrcbuf.left = rectsrcbuf.right - 1; rectdstbuf.left = rectdstbuf.right - ((1 << (d3d.backsurf2mul-1)) >> 1); rectsrcbuf.top = rectsrcbuf.bottom - 1; rectdstbuf.top = rectdstbuf.bottom - ((1 << (d3d.backsurf2mul-1)) >> 1); - r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // E + r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // 右下隅 rectsrcbuf = *rect; rectdstbuf = rectbuf; rectdstbuf.right -= ((1 << (d3d.backsurf2mul-1)) >> 1); @@ -1570,27 +1570,27 @@ void scrnmngD3D_update(void) { rectbuf.bottom = (d3d.rect.bottom - d3d.rect.top) * d3d.backsurf2mul; if(d3d.backsurf2mul > 1){ - // ]1pxY΍ + // 転送時の1pxズレ対策 rectsrcbuf = d3d.rect; rectdstbuf = rectbuf; if(nvidia_fixflag){ rectsrcbuf.left = rectsrcbuf.right - 1; rectdstbuf.left = rectdstbuf.right - ((1 << (d3d.backsurf2mul-1)) >> 1); rectdstbuf.bottom -= ((1 << (d3d.backsurf2mul-1)) >> 1); - r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // E[ + r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // 右端 rectsrcbuf = d3d.rect; rectdstbuf = rectbuf; rectsrcbuf.top = rectsrcbuf.bottom - 1; rectdstbuf.top = rectdstbuf.bottom - ((1 << (d3d.backsurf2mul-1)) >> 1); rectdstbuf.right -= ((1 << (d3d.backsurf2mul-1)) >> 1); - r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // [ + r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // 下端 rectsrcbuf = d3d.rect; rectdstbuf = rectbuf; rectsrcbuf.left = rectsrcbuf.right - 1; rectdstbuf.left = rectdstbuf.right - ((1 << (d3d.backsurf2mul-1)) >> 1); rectsrcbuf.top = rectsrcbuf.bottom - 1; rectdstbuf.top = rectdstbuf.bottom - ((1 << (d3d.backsurf2mul-1)) >> 1); - r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // E + r = d3d.d3ddev->StretchRect(d3d.backsurf, &rectsrcbuf, d3d.backsurf2, &rectdstbuf, D3DTEXF_POINT); // 右下隅 rectsrcbuf = d3d.rect; rectdstbuf = rectbuf; rectdstbuf.right -= ((1 << (d3d.backsurf2mul-1)) >> 1); @@ -1637,15 +1637,15 @@ void scrnmngD3D_update(void) { RECT lastrect = *rect; RECT lastscrn = *scrn; if(nvidia_fixflag){ - rect->right++; // Ȃ̒ - scrn->left -= scrnoffset; // Ȃ̒ + rect->right++; // なぞの調整 + scrn->left -= scrnoffset; // なぞの調整 scrn->right -= ((1 << (scrnoffset-1)) >> 1); scrn->bottom -= ((1 << (scrnoffset-1)) >> 1); } if(scrn->left < 0){ // for full mode - rect->left++; // Ȃ̒ - scrn->left += scrnoffset; // Ȃ̒ + rect->left++; // なぞの調整 + scrn->left += scrnoffset; // なぞの調整 } r = d3d.d3ddev->StretchRect(d3d.backsurf, rect, d3d.d3dbacksurf, scrn, d3dtexf); *rect = lastrect; @@ -1916,7 +1916,7 @@ void scrnmngD3D_exitsizing(void) InvalidateRect(g_hWndMain, NULL, TRUE); // ugh } -// tXN[𑜓x +// フルスクリーン解像度調整 void scrnmngD3D_updatefsres(void) { #ifdef SUPPORT_WAB RECT rect; @@ -1966,7 +1966,7 @@ void scrnmngD3D_updatefsres(void) { g_scrnmode = g_scrnmode | SCRNMODE_FULLSCREEN; } else { - // EBhEŃgC + // ウィンドウでリトライ if (scrnmngD3D_create(g_scrnmode) != SUCCESS) { //PostQuitMessage(0); scrnmng_create_pending = true; @@ -1977,7 +1977,7 @@ void scrnmngD3D_updatefsres(void) { }else if(d3d.width != width || d3d.height != height){ scrnmngD3D_destroy(); if (scrnmngD3D_create(g_scrnmode) != SUCCESS) { - //if (scrnmngD3D_create(g_scrnmode | SCRNMODE_FULLSCREEN) != SUCCESS) { // tXN[ŃgC + //if (scrnmngD3D_create(g_scrnmode | SCRNMODE_FULLSCREEN) != SUCCESS) { // フルスクリーンでリトライ //PostQuitMessage(0); scrnmng_create_pending = true; d3d_leave_criticalsection(); @@ -1995,7 +1995,7 @@ void scrnmngD3D_updatefsres(void) { #endif } -// EBhEANZ[^ʓ] GDI Device Independent Bitmap -> Direct3D WAB surface +// ウィンドウアクセラレータ画面転送 GDI Device Independent Bitmap -> Direct3D WAB surface void scrnmngD3D_blthdc(HDC hdc) { #if defined(SUPPORT_WAB) HRESULT r; @@ -2049,7 +2049,7 @@ void scrnmngD3D_blthdc(HDC hdc) { d3d_leave_criticalsection(); }else{ if(!d3d.d3dbacksurf){ - // v + // 生成要求 scrnmng_create_pending = true; Sleep(1000); } @@ -2057,7 +2057,7 @@ void scrnmngD3D_blthdc(HDC hdc) { #endif } -// EBhEANZ[^ʓ] Direct3D WAB surface -> Direct3D back surface +// ウィンドウアクセラレータ画面転送 Direct3D WAB surface -> Direct3D back surface void scrnmngD3D_bltwab() { #if defined(SUPPORT_WAB) RECT *dst; @@ -2098,7 +2098,7 @@ void scrnmngD3D_bltwab() { d3d_leave_criticalsection(); }else{ if(!d3d.d3dbacksurf){ - // v + // 生成要求 scrnmng_create_pending = true; Sleep(1000); } @@ -2106,7 +2106,7 @@ void scrnmngD3D_bltwab() { #endif } -// `͈̈̔͂NCAgWŎ擾 +// 描画領域の範囲をクライアント座標で取得 void scrnmngD3D_getrect(RECT *lpRect) { if (d3d.scrnmode & SCRNMODE_FULLSCREEN) { if (GetWindowLongPtr(g_hWndMain, NP2GWLP_HMENU)) { diff --git a/windows/scrnmng_d3d.h b/windows/scrnmng_d3d.h index 94b01292..54f8f8be 100644 --- a/windows/scrnmng_d3d.h +++ b/windows/scrnmng_d3d.h @@ -1,54 +1,54 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT scrnmngD3D_check(void); - -BRESULT scrnmngD3D_create(UINT8 scrnmode); -void scrnmngD3D_destroy(void); -void scrnmngD3D_shutdown(void); -void scrnmngD3D_restoresurfaces(void); - -void scrnmngD3D_setwidth(int posx, int width); -void scrnmngD3D_setextend(int extend); -void scrnmngD3D_setheight(int posy, int height); -void scrnmngD3D_setsize(int posx, int posy, int width, int height); -#define scrnmngD3D_setbpp(commendablebpp) -const SCRNSURF *scrnmngD3D_surflock(void); -void scrnmngD3D_surfunlock(const SCRNSURF *surf); -void scrnmngD3D_update(void); - -RGB16 scrnmngD3D_makepal16(RGB32 pal32); - - -// ---- for windows - -void scrnmngD3D_setmultiple(int multiple); -int scrnmngD3D_getmultiple(void); -void scrnmngD3D_querypalette(void); -void scrnmngD3D_setdefaultres(void); -void scrnmngD3D_setfullscreen(BOOL fullscreen); -void scrnmngD3D_setrotatemode(UINT type); -void scrnmngD3D_fullscrnmenu(int y); -void scrnmngD3D_topwinui(void); -void scrnmngD3D_clearwinui(void); - -void scrnmngD3D_entersizing(void); -void scrnmngD3D_sizing(UINT side, RECT *rect); -void scrnmngD3D_exitsizing(void); - -void scrnmngD3D_updatefsres(void); -void scrnmngD3D_blthdc(HDC hdc); -void scrnmngD3D_bltwab(void); - -void scrnmngD3D_getrect(RECT *lpRect); - -#if defined(SUPPORT_DCLOCK) -BOOL scrnmngD3D_isdispclockclick(const POINT *pt); -void scrnmngD3D_dispclock(void); -#endif - -#ifdef __cplusplus -} -#endif + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT scrnmngD3D_check(void); + +BRESULT scrnmngD3D_create(UINT8 scrnmode); +void scrnmngD3D_destroy(void); +void scrnmngD3D_shutdown(void); +void scrnmngD3D_restoresurfaces(void); + +void scrnmngD3D_setwidth(int posx, int width); +void scrnmngD3D_setextend(int extend); +void scrnmngD3D_setheight(int posy, int height); +void scrnmngD3D_setsize(int posx, int posy, int width, int height); +#define scrnmngD3D_setbpp(commendablebpp) +const SCRNSURF *scrnmngD3D_surflock(void); +void scrnmngD3D_surfunlock(const SCRNSURF *surf); +void scrnmngD3D_update(void); + +RGB16 scrnmngD3D_makepal16(RGB32 pal32); + + +// ---- for windows + +void scrnmngD3D_setmultiple(int multiple); +int scrnmngD3D_getmultiple(void); +void scrnmngD3D_querypalette(void); +void scrnmngD3D_setdefaultres(void); +void scrnmngD3D_setfullscreen(BOOL fullscreen); +void scrnmngD3D_setrotatemode(UINT type); +void scrnmngD3D_fullscrnmenu(int y); +void scrnmngD3D_topwinui(void); +void scrnmngD3D_clearwinui(void); + +void scrnmngD3D_entersizing(void); +void scrnmngD3D_sizing(UINT side, RECT *rect); +void scrnmngD3D_exitsizing(void); + +void scrnmngD3D_updatefsres(void); +void scrnmngD3D_blthdc(HDC hdc); +void scrnmngD3D_bltwab(void); + +void scrnmngD3D_getrect(RECT *lpRect); + +#if defined(SUPPORT_DCLOCK) +BOOL scrnmngD3D_isdispclockclick(const POINT *pt); +void scrnmngD3D_dispclock(void); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/windows/scrnmng_dd.cpp b/windows/scrnmng_dd.cpp index 8374771b..60b08d62 100644 --- a/windows/scrnmng_dd.cpp +++ b/windows/scrnmng_dd.cpp @@ -40,14 +40,14 @@ #pragma comment(lib, "dxguid.lib") #endif // !defined(__GNUC__) -//! 8BPP pbg +//! 8BPP パレット数 #define PALLETES_8BPP NP2PAL_TEXT3 #define FILLSURF_SIZE 32 static int req_enter_criticalsection = 0; -extern bool scrnmng_create_pending; // OtBbN_ۗ +extern bool scrnmng_create_pending; // グラフィックレンダラ生成保留中 extern bool scrnmng_restore_pending; extern WINLOCEX np2_winlocexallwin(HWND base); @@ -108,7 +108,7 @@ static void dd_leave_criticalsection(void){ LeaveCriticalSection(&dd_cs); } -// vC}T[tFCXDirectDraw DDBLT_COLORFILLŗOo‹悤Ȃ̂ő +// プライマリサーフェイスのDirectDraw DDBLT_COLORFILLで例外が出る環境があるようなので代替 #define DDBLT_COLORFILL_FIX #ifdef DDBLT_COLORFILL_FIX @@ -146,7 +146,7 @@ static void renewalclientsize(BOOL winloc) { extend = 0; - // `͈́` + // 描画範囲~ if (ddraw.scrnmode & SCRNMODE_FULLSCREEN) { ddraw.rect.right = width; ddraw.rect.bottom = height; @@ -204,7 +204,7 @@ static void renewalclientsize(BOOL winloc) { ddraw.scrn.right = ddraw.scrn.left + scrnwidth; ddraw.scrn.bottom = ddraw.scrn.top + scrnheight; - // j[\̕`̈ + // メニュー表示時の描画領域 ddraw.rectclip = ddraw.rect; ddraw.scrnclip = ddraw.scrn; if (ddraw.scrnclip.top < ddraw.menusize) { @@ -556,7 +556,7 @@ BRESULT scrnmngDD_create(UINT8 scrnmode) { winstyle &= ~CS_DBLCLKS; if (np2oscfg.wintype != 0) { WINLOCEX wlex; - // XXX: j[oȂȂċlނ̂ibj + // XXX: メニューが出せなくなって詰むのを回避(暫定) np2oscfg.wintype = 0; np2oscfg.wintype = 0; wlex = np2_winlocexallwin(g_hWndMain); @@ -588,16 +588,16 @@ BRESULT scrnmngDD_create(UINT8 scrnmode) { } strcat(szModulePath, "\\ddraw.dll"); if(PathFileExistsA(szModulePath) && !PathIsDirectoryA(szModulePath)){ - // DXGLgĂȂ̂őfȃR[hɕύX + // DXGLが使われていそうなので素直なコードに変更 SetWindowLong(g_hWndMain, GWL_STYLE, winstyle); SetWindowLong(g_hWndMain, GWL_EXSTYLE, winstyleex); }else{ - ShowWindow(g_hWndMain, SW_HIDE); // AeroȊ‹ŃtXN[EBhE̎ɃVXeACR΍̂߂̂܂Ȃi1j + ShowWindow(g_hWndMain, SW_HIDE); // Aeroな環境でフルスクリーン→ウィンドウの時にシステムアイコンが消える対策のためのおまじない(その1) SetWindowLong(g_hWndMain, GWL_STYLE, winstyle); SetWindowLong(g_hWndMain, GWL_EXSTYLE, winstyleex); - ShowWindow(g_hWndMain, SW_SHOWNORMAL); // AeroȊ‹(ryi2j - ShowWindow(g_hWndMain, SW_HIDE); // AeroȊ‹(ryi3j - ShowWindow(g_hWndMain, SW_SHOWNORMAL); // AeroȊ‹(ryi4j + ShowWindow(g_hWndMain, SW_SHOWNORMAL); // Aeroな環境で(ry(その2) + ShowWindow(g_hWndMain, SW_HIDE); // Aeroな環境で(ry(その3) + ShowWindow(g_hWndMain, SW_SHOWNORMAL); // Aeroな環境で(ry(その4) } SetWindowPlacement(g_hWndMain, &wp); }else{ @@ -619,7 +619,7 @@ BRESULT scrnmngDD_create(UINT8 scrnmode) { } } if ((r = DirectDrawCreate(devlpguid, &ddraw.ddraw1, NULL)) != DD_OK) { - // vC}ōĒ + // プライマリで再挑戦 if (DirectDrawCreate(np2oscfg.emuddraw ? (LPGUID)DDCREATE_EMULATIONONLY : NULL, &ddraw.ddraw1, NULL) != DD_OK) { goto scre_err; } @@ -671,7 +671,7 @@ BRESULT scrnmngDD_create(UINT8 scrnmode) { } if (!((fscrnmod & FSCRNMOD_SAMERES) || np2_multithread_Enabled())) { - // 𑜓xς郂[hȂA + // 解像度変えるモードなら帰る if (ddraw2->SetDisplayMode(width, height, bitcolor, 0, 0) != DD_OK) { width = 640; @@ -713,7 +713,7 @@ BRESULT scrnmngDD_create(UINT8 scrnmode) { ddsd.dwHeight = (WAB_MAX_HEIGHT > maxy ? maxy : WAB_MAX_HEIGHT); }else{ if((np2wab.relay&0x3)!=0 && np2wab.realWidth>=640 && np2wab.realHeight>=400){ - // TCY + // 実サイズに ddsd.dwWidth = np2wab.realWidth; ddsd.dwHeight = np2wab.realHeight; }else{ @@ -810,14 +810,14 @@ BRESULT scrnmngDD_create(UINT8 scrnmode) { ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; #ifdef SUPPORT_WAB if(!np2wabwnd.multiwindow && (np2wab.relay&0x3)!=0 && np2wab.realWidth>=640 && np2wab.realHeight>=400){ - // TCY + // 実サイズに width = ddsd.dwWidth = scrnstat.width;//np2wab.realWidth; height = ddsd.dwHeight = scrnstat.height;//np2wab.realHeight; if (scrnmode & SCRNMODE_ROTATE) { ddsd.dwWidth = scrnstat.height; ddsd.dwHeight = scrnstat.width; } - ddsd.dwWidth++; // +1ȂƑʖڂ炵 + ddsd.dwWidth++; // +1しないと駄目らしい }else{ if (!(scrnmode & SCRNMODE_ROTATE)) { ddsd.dwWidth = 640 + 1; @@ -888,11 +888,11 @@ BRESULT scrnmngDD_create(UINT8 scrnmode) { ddraw.width = width; ddraw.height = height; ddraw.cliping = 0; - renewalclientsize(TRUE); // XXX: XibvN̂ŎbTRUE + renewalclientsize(TRUE); // XXX: スナップ解除等が起こるので暫定TRUE lastscrnmode = scrnmode; // screenupdate = 3; // update! #if defined(SUPPORT_WAB) - mt_wabpausedrawing = 0; // MultiThread΍ + mt_wabpausedrawing = 0; // MultiThread対策 #endif dd_leave_criticalsection(); return(SUCCESS); @@ -921,7 +921,7 @@ void scrnmngDD_destroy(void) { } #if defined(SUPPORT_WAB) if (ddraw.wabsurf) { - mt_wabpausedrawing = 1; // MultiThread΍ + mt_wabpausedrawing = 1; // MultiThread対策 while(mt_wabdrawing) Sleep(10); ddraw.wabsurf->Release(); @@ -1423,7 +1423,7 @@ void scrnmngDD_exitsizing(void) InvalidateRect(g_hWndMain, NULL, TRUE); // ugh } -// tXN[𑜓x +// フルスクリーン解像度調整 void scrnmngDD_updatefsres(void) { #ifdef SUPPORT_WAB RECT rect; @@ -1478,7 +1478,7 @@ void scrnmngDD_updatefsres(void) { }else if(ddraw.width < width || ddraw.height < height){ scrnmngDD_destroy(); if (scrnmngDD_create(g_scrnmode) != SUCCESS) { - if (scrnmngDD_create(g_scrnmode | SCRNMODE_FULLSCREEN) != SUCCESS) { // tXN[ŃgC + if (scrnmngDD_create(g_scrnmode | SCRNMODE_FULLSCREEN) != SUCCESS) { // フルスクリーンでリトライ scrnmng_create_pending = true; //PostQuitMessage(0); dd_leave_criticalsection(); @@ -1495,7 +1495,7 @@ void scrnmngDD_updatefsres(void) { #endif } -// EBhEANZ[^ʓ] +// ウィンドウアクセラレータ画面転送 void scrnmngDD_blthdc(HDC hdc) { #if defined(SUPPORT_WAB) HRESULT r; @@ -1594,7 +1594,7 @@ void scrnmngDD_bltwab() { #endif } -// `͈̈̔͂NCAgWŎ擾 +// 描画領域の範囲をクライアント座標で取得 void scrnmngDD_getrect(RECT *lpRect) { if (ddraw.scrnmode & SCRNMODE_FULLSCREEN) { if (GetWindowLongPtr(g_hWndMain, NP2GWLP_HMENU)) { diff --git a/windows/scrnmng_dd.h b/windows/scrnmng_dd.h index a1b5a6ec..fdfe6e4c 100644 --- a/windows/scrnmng_dd.h +++ b/windows/scrnmng_dd.h @@ -1,53 +1,53 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT scrnmngDD_create(UINT8 scrnmode); -void scrnmngDD_destroy(void); -void scrnmngDD_shutdown(void); -void scrnmngDD_restoresurfaces(void); - -void scrnmngDD_setwidth(int posx, int width); -void scrnmngDD_setextend(int extend); -void scrnmngDD_setheight(int posy, int height); -void scrnmngDD_setsize(int posx, int posy, int width, int height); -#define scrnmngDD_setbpp(commendablebpp) -const SCRNSURF *scrnmngDD_surflock(void); -void scrnmngDD_surfunlock(const SCRNSURF *surf); -void scrnmngDD_update(void); - -RGB16 scrnmngDD_makepal16(RGB32 pal32); - - -// ---- for windows - -void scrnmngDD_setmultiple(int multiple); -int scrnmngDD_getmultiple(void); -void scrnmngDD_querypalette(void); -void scrnmngDD_setdefaultres(void); -void scrnmngDD_setfullscreen(BOOL fullscreen); -void scrnmngDD_setrotatemode(UINT type); -void scrnmngDD_fullscrnmenu(int y); -void scrnmngDD_topwinui(void); -void scrnmngDD_clearwinui(void); - -void scrnmngDD_entersizing(void); -void scrnmngDD_sizing(UINT side, RECT *rect); -void scrnmngDD_exitsizing(void); - -void scrnmngDD_updatefsres(void); -void scrnmngDD_blthdc(HDC hdc); -void scrnmngDD_bltwab(void); - -void scrnmngDD_getrect(RECT *lpRect); - -#if defined(SUPPORT_DCLOCK) -BOOL scrnmngDD_isdispclockclick(const POINT *pt); -void scrnmngDD_dispclock(void); -#endif - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT scrnmngDD_create(UINT8 scrnmode); +void scrnmngDD_destroy(void); +void scrnmngDD_shutdown(void); +void scrnmngDD_restoresurfaces(void); + +void scrnmngDD_setwidth(int posx, int width); +void scrnmngDD_setextend(int extend); +void scrnmngDD_setheight(int posy, int height); +void scrnmngDD_setsize(int posx, int posy, int width, int height); +#define scrnmngDD_setbpp(commendablebpp) +const SCRNSURF *scrnmngDD_surflock(void); +void scrnmngDD_surfunlock(const SCRNSURF *surf); +void scrnmngDD_update(void); + +RGB16 scrnmngDD_makepal16(RGB32 pal32); + + +// ---- for windows + +void scrnmngDD_setmultiple(int multiple); +int scrnmngDD_getmultiple(void); +void scrnmngDD_querypalette(void); +void scrnmngDD_setdefaultres(void); +void scrnmngDD_setfullscreen(BOOL fullscreen); +void scrnmngDD_setrotatemode(UINT type); +void scrnmngDD_fullscrnmenu(int y); +void scrnmngDD_topwinui(void); +void scrnmngDD_clearwinui(void); + +void scrnmngDD_entersizing(void); +void scrnmngDD_sizing(UINT side, RECT *rect); +void scrnmngDD_exitsizing(void); + +void scrnmngDD_updatefsres(void); +void scrnmngDD_blthdc(HDC hdc); +void scrnmngDD_bltwab(void); + +void scrnmngDD_getrect(RECT *lpRect); + +#if defined(SUPPORT_DCLOCK) +BOOL scrnmngDD_isdispclockclick(const POINT *pt); +void scrnmngDD_dispclock(void); +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/windows/soundmng.cpp b/windows/soundmng.cpp index 4d2cbe68..f9021590 100644 --- a/windows/soundmng.cpp +++ b/windows/soundmng.cpp @@ -1,626 +1,626 @@ -/** - * @file soundmng.cpp - * @brief サウンド マネージャ クラスの動作の定義を行います - */ - -#include -#include -#include -#if defined(SUPPORT_ROMEO) -#include "ext/externalchipmanager.h" -#endif -#if defined(MT32SOUND_DLL) -#include "ext/mt32snd.h" -#endif -#if defined(SUPPORT_ASIO) -#include "soundmng/sdasio.h" -#endif // defined(SUPPORT_ASIO) -#include "soundmng/sddsound3.h" -#if defined(SUPPORT_WASAPI) -#include "soundmng/sdwasapi.h" -#endif // defined(SUPPORT_WASAPI) -#include "common/parts.h" -#include "sound/sound.h" -#if defined(VERMOUTH_LIB) -#include "sound/vermouth/vermouth.h" -#endif -#include - -#if !defined(_WIN64) -#ifdef __cplusplus -extern "C" -{ -#endif -/** - * satuation - * @param[out] dst 出力バッファ - * @param[in] src 入力バッファ - * @param[in] size サイズ - */ -void __fastcall satuation_s16mmx(SINT16 *dst, const SINT32 *src, UINT size); -#ifdef __cplusplus -} -#endif -#endif - -#if defined(VERMOUTH_LIB) - MIDIMOD vermouth_module = NULL; -#endif - -//! 唯一のインスタンスです -CSoundMng CSoundMng::sm_instance; - -/** - * 初期化 - */ -void CSoundMng::Initialize() -{ -#if defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) - ::CoInitializeEx(NULL, COINIT_MULTITHREADED); -#endif // defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) - - CSoundDeviceDSound3::s_mastervol_available = true;//np2oscfg.usemastervolume ? true : false; - CSoundDeviceDSound3::Initialize(); -#if defined(SUPPORT_WASAPI) - CSoundDeviceWasapi::Initialize(); -#endif // defined(SUPPORT_WASAPI) - -#if defined(SUPPORT_ASIO) - CSoundDeviceAsio::Initialize(); -#endif // defined(SUPPORT_ASIO) - -#if defined(SUPPORT_ROMEO) - CExternalChipManager::GetInstance()->Initialize(); -#endif // defined(SUPPORT_ROMEO) - - CSoundMng::GetInstance()->InitializeSoundCriticalSection(); -} - -/** - * 解放 - */ -void CSoundMng::Deinitialize() -{ -#if defined(SUPPORT_ROMEO) - CExternalChipManager::GetInstance()->Deinitialize(); -#endif // defined(SUPPORT_ROMEO) - -#if defined(SUPPORT_WASAPI) - CSoundDeviceWasapi::Deinitialize(); -#endif // defined(SUPPORT_WASAPI) - -#if defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) - ::CoUninitialize(); -#endif // defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) - - CSoundMng::GetInstance()->FinalizeSoundCriticalSection(); -} - -/** - * コンストラクタ - */ -CSoundMng::CSoundMng() - : m_pSoundDevice(NULL) - , m_nMute(0) - , m_sound_cs_initialized(false) -{ - SetReverse(false); -} - -/** - * オープン - * @param[in] nType デバイス タイプ - * @param[in] lpName デバイス名 - * @param[in] hWnd ウィンドウ ハンドル - * @retval true 成功 - * @retval false 失敗 - */ -bool CSoundMng::Open(DeviceType nType, LPCTSTR lpName, HWND hWnd) -{ - EnterAllCriticalSection(); - - Close(); - - CSoundDeviceBase* pSoundDevice = NULL; - switch (nType) - { - case kDefault: - pSoundDevice = new CSoundDeviceDSound3; - lpName = NULL; - break; - - case kDSound3: - pSoundDevice = new CSoundDeviceDSound3; - break; - -#if defined(SUPPORT_WASAPI) - case kWasapi: - pSoundDevice = new CSoundDeviceWasapi; - break; -#endif // defined(SUPPORT_WASAPI) - -#if defined(SUPPORT_ASIO) - case kAsio: - pSoundDevice = new CSoundDeviceAsio; - break; -#endif // defined(SUPPORT_ASIO) - } - - if (pSoundDevice) - { - if (!pSoundDevice->Open(lpName, hWnd)) - { - delete pSoundDevice; - pSoundDevice = NULL; - } - } - - if (pSoundDevice == NULL) - { - LeaveSoundCriticalSection(); - return false; - } - - m_pSoundDevice = pSoundDevice; - -#if defined(MT32SOUND_DLL) - MT32Sound::GetInstance()->Initialize(); -#endif - - LeaveAllCriticalSection(); - return true; -} - -/** - * クローズ - */ -void CSoundMng::Close() -{ - EnterAllCriticalSection(); - if (m_pSoundDevice) - { - m_pSoundDevice->Close(); - delete m_pSoundDevice; - m_pSoundDevice = NULL; - } - -#if defined(MT32SOUND_DLL) - MT32Sound::GetInstance()->Deinitialize(); -#endif - LeaveAllCriticalSection(); -} - -/** - * サウンド有効 - * @param[in] nProc プロシージャ - */ -void CSoundMng::Enable(SoundProc nProc) -{ - EnterSoundCriticalSection(); - const UINT nBit = 1 << nProc; - if (!(m_nMute & nBit)) - { - LeaveSoundCriticalSection(); - return; - } - m_nMute &= ~nBit; - if (!m_nMute) - { - if (m_pSoundDevice) - { - m_pSoundDevice->PlayStream(); - } -#if defined(SUPPORT_ROMEO) - CExternalChipManager::GetInstance()->Mute(false); -#endif // defined(SUPPORT_ROMEO) - } - LeaveSoundCriticalSection(); -} - -/** - * サウンド無効 - * @param[in] nProc プロシージャ - */ -void CSoundMng::Disable(SoundProc nProc) -{ - EnterSoundCriticalSection(); - if (!m_nMute) - { - if (m_pSoundDevice) - { - m_pSoundDevice->StopStream(); - m_pSoundDevice->StopAllPCM(); - } -#if defined(SUPPORT_ROMEO) - CExternalChipManager::GetInstance()->Mute(true); -#endif // defined(SUPPORT_ROMEO) - } - m_nMute |= (1 << nProc); - LeaveSoundCriticalSection(); -} - -/** - * ストリームを作成 - * @param[in] nSamplingRate サンプリング レート - * @param[in] ms バッファ長(ミリ秒) - * @return バッファ数 - */ -UINT CSoundMng::CreateStream(UINT nSamplingRate, UINT ms) -{ - EnterAllCriticalSection(); - if (m_pSoundDevice == NULL) - { - LeaveSoundCriticalSection(); - return 0; - } - - if (ms < 40) - { - ms = 40; - } - else if (ms > 1000) - { - ms = 1000; - } - UINT nBuffer = (nSamplingRate * ms) / 2000; - nBuffer = (nBuffer + 1) & (~1); - - nBuffer = m_pSoundDevice->CreateStream(nSamplingRate, 2, nBuffer); - if (nBuffer == 0) - { - LeaveSoundCriticalSection(); - return 0; - } - m_pSoundDevice->SetStreamData(this); - -#if defined(VERMOUTH_LIB) - vermouth_module = midimod_create(nSamplingRate); - midimod_loadall(vermouth_module); -#endif - -#if defined(MT32SOUND_DLL) - MT32Sound::GetInstance()->SetRate(nSamplingRate); -#endif - - LeaveAllCriticalSection(); - return nBuffer; -} - -/** - * ストリームを破棄 - */ -inline void CSoundMng::DestroyStream() -{ - if (m_pSoundDevice) - { - m_pSoundDevice->DestroyStream(); - } - -#if defined(VERMOUTH_LIB) - midimod_destroy(vermouth_module); - vermouth_module = NULL; -#endif -#if defined(MT32SOUND_DLL) - MT32Sound::GetInstance()->SetRate(0); -#endif -} - -/** - * ストリームのリセット - */ -inline void CSoundMng::ResetStream() -{ - EnterSoundCriticalSection(); - if (m_pSoundDevice) - { - m_pSoundDevice->ResetStream(); - } - LeaveSoundCriticalSection(); -} - -/** - * ストリームの再生 - */ -inline void CSoundMng::PlayStream() -{ - EnterSoundCriticalSection(); - if (!m_nMute) - { - if (m_pSoundDevice) - { - m_pSoundDevice->PlayStream(); - } - } - LeaveSoundCriticalSection(); -} - -/** - * ストリームの停止 - */ -inline void CSoundMng::StopStream() -{ - EnterSoundCriticalSection(); - if (!m_nMute) - { - if (m_pSoundDevice) - { - m_pSoundDevice->StopStream(); - } - } - LeaveSoundCriticalSection(); -} - -/** - * ストリームを得る - * @param[out] lpBuffer バッファ - * @param[in] nBufferCount バッファ カウント - * @return サンプル数 - */ -UINT CSoundMng::Get16(SINT16* lpBuffer, UINT nBufferCount) -{ - EnterSoundCriticalSection(); - const SINT32* lpSource = ::sound_pcmlock(); - if (lpSource) - { - (*m_fnMix)(lpBuffer, lpSource, nBufferCount * 4); - ::sound_pcmunlock(lpSource); - LeaveSoundCriticalSection(); - return nBufferCount; - } - else - { - LeaveSoundCriticalSection(); - return 0; - } -} - -/** - * パン反転を設定する - * @param[in] bReverse 反転フラグ - */ -inline void CSoundMng::SetReverse(bool bReverse) -{ - EnterSoundCriticalSection(); - if (!bReverse) - { -#if !defined(_WIN64) - if (mmxflag) - { - m_fnMix = satuation_s16; - } - else { - m_fnMix = satuation_s16mmx; - } -#else - m_fnMix = satuation_s16; -#endif - } - else - { - m_fnMix = satuation_s16x; - } - LeaveSoundCriticalSection(); -} - -/** - * マスター ヴォリューム設定 - * @param[in] nVolume ヴォリューム - */ -void CSoundMng::SetMasterVolume(int nVolume) -{ - EnterSoundCriticalSection(); - if (m_pSoundDevice) - { - m_pSoundDevice->SetMasterVolume(nVolume); - } - LeaveSoundCriticalSection(); -} - -/** - * PCM データ読み込み - * @param[in] nNum PCM 番号 - * @param[in] lpFilename ファイル名 - */ -void CSoundMng::LoadPCM(SoundPCMNumber nNum, LPCTSTR lpFilename) -{ - EnterSoundCriticalSection(); - if (m_pSoundDevice) - { - m_pSoundDevice->LoadPCM(nNum, lpFilename); - } - LeaveSoundCriticalSection(); -} - -/** - * PCM データ再読み込み - * @param[in] nNum PCM 番号 - * @param[in] lpFilename ファイル名 - */ -void CSoundMng::ReloadPCM(SoundPCMNumber nNum) -{ - EnterSoundCriticalSection(); - if (m_pSoundDevice) - { - m_pSoundDevice->ReloadPCM(nNum); - } - LeaveSoundCriticalSection(); -} - -/** - * PCM ヴォリューム設定 - * @param[in] nNum PCM 番号 - * @param[in] nVolume ヴォリューム - */ -void CSoundMng::SetPCMVolume(SoundPCMNumber nNum, int nVolume) -{ - EnterSoundCriticalSection(); - if (m_pSoundDevice) - { - m_pSoundDevice->SetPCMVolume(nNum, nVolume); - } - LeaveSoundCriticalSection(); -} - -/** - * PCM 再生 - * @param[in] nNum PCM 番号 - * @param[in] bLoop ループ フラグ - * @retval true 成功 - * @retval false 失敗 - */ -inline bool CSoundMng::PlayPCM(SoundPCMNumber nNum, BOOL bLoop) -{ - EnterSoundCriticalSection(); - if (!m_nMute) - { - if (m_pSoundDevice) - { - LeaveSoundCriticalSection(); - return m_pSoundDevice->PlayPCM(nNum, bLoop); - } - } - LeaveSoundCriticalSection(); - return false; -} - -/** - * PCM 停止 - * @param[in] nNum PCM 番号 - */ -inline void CSoundMng::StopPCM(SoundPCMNumber nNum) -{ - EnterSoundCriticalSection(); - if (m_pSoundDevice) - { - m_pSoundDevice->StopPCM(nNum); - } - LeaveSoundCriticalSection(); -} - -// クリティカルセクション関連 -void CSoundMng::InitializeSoundCriticalSection() -{ - if(!m_sound_cs_initialized){ - InitializeCriticalSection(&m_sound_cs); - m_sound_cs_initialized = true; - } -} -void CSoundMng::FinalizeSoundCriticalSection() -{ - if(m_sound_cs_initialized){ - DeleteCriticalSection(&m_sound_cs); - m_sound_cs_initialized = false; - } -} -void CSoundMng::EnterSoundCriticalSection() -{ - if(m_sound_cs_initialized){ - EnterCriticalSection(&m_sound_cs); - } -} -void CSoundMng::LeaveSoundCriticalSection() -{ - if(m_sound_cs_initialized){ - LeaveCriticalSection(&m_sound_cs); - } -} -void CSoundMng::EnterAllCriticalSection() -{ - np2_multithread_EnterCriticalSection(); - EnterSoundCriticalSection(); -} -void CSoundMng::LeaveAllCriticalSection() -{ - LeaveSoundCriticalSection(); - np2_multithread_LeaveCriticalSection(); -} - -// ---- C ラッパー - -/** - * ストリーム作成 - * @param[in] rate サンプリング レート - * @param[in] ms バッファ長(ミリ秒) - * @return バッファ サイズ - */ -UINT soundmng_create(UINT rate, UINT ms) -{ - UINT result; - result = CSoundMng::GetInstance()->CreateStream(rate, ms); - return result; -} - -/** - * ストリーム破棄 - */ -void soundmng_destroy(void) -{ - CSoundMng::GetInstance()->DestroyStream(); -} - -/** - * ストリーム リセット - */ -void soundmng_reset(void) -{ - CSoundMng::GetInstance()->ResetStream(); -} - -/** - * ストリーム開始 - */ -void soundmng_play(void) -{ - CSoundMng::GetInstance()->PlayStream(); -} - -/** - * ストリーム停止 - */ -void soundmng_stop(void) -{ - CSoundMng::GetInstance()->StopStream(); -} - -/** - * ストリーム パン反転設定 - * @param[in] bReverse 反転 - */ -void soundmng_setreverse(BOOL bReverse) -{ - CSoundMng::GetInstance()->SetReverse((bReverse) ? true : false); -} - -/** - * ボリューム設定 - * @param[in] nVolume ボリューム(最小 0 〜 100 最大) - */ -void soundmng_setvolume(int nVolume) -{ - CSoundMng::GetInstance()->SetMasterVolume(nVolume); -} - -/** - * PCM 再生 - * @param[in] nNum PCM 番号 - * @param[in] bLoop ループ - * @retval SUCCESS 成功 - * @retval FAILURE 失敗 - */ -BRESULT soundmng_pcmplay(enum SoundPCMNumber nNum, BOOL bLoop) -{ - BRESULT result; - result = (CSoundMng::GetInstance()->PlayPCM(nNum, bLoop)) ? SUCCESS : FAILURE; - return result; -} - -/** - * PCM 停止 - * @param[in] nNum PCM 番号 - */ -void soundmng_pcmstop(enum SoundPCMNumber nNum) -{ - CSoundMng::GetInstance()->StopPCM(nNum); -} - - +/** + * @file soundmng.cpp + * @brief サウンド マネージャ クラスの動作の定義を行います + */ + +#include +#include +#include +#if defined(SUPPORT_ROMEO) +#include "ext/externalchipmanager.h" +#endif +#if defined(MT32SOUND_DLL) +#include "ext/mt32snd.h" +#endif +#if defined(SUPPORT_ASIO) +#include "soundmng/sdasio.h" +#endif // defined(SUPPORT_ASIO) +#include "soundmng/sddsound3.h" +#if defined(SUPPORT_WASAPI) +#include "soundmng/sdwasapi.h" +#endif // defined(SUPPORT_WASAPI) +#include "common/parts.h" +#include "sound/sound.h" +#if defined(VERMOUTH_LIB) +#include "sound/vermouth/vermouth.h" +#endif +#include + +#if !defined(_WIN64) +#ifdef __cplusplus +extern "C" +{ +#endif +/** + * satuation + * @param[out] dst 出力バッファ + * @param[in] src 入力バッファ + * @param[in] size サイズ + */ +void __fastcall satuation_s16mmx(SINT16 *dst, const SINT32 *src, UINT size); +#ifdef __cplusplus +} +#endif +#endif + +#if defined(VERMOUTH_LIB) + MIDIMOD vermouth_module = NULL; +#endif + +//! 唯一のインスタンスです +CSoundMng CSoundMng::sm_instance; + +/** + * 初期化 + */ +void CSoundMng::Initialize() +{ +#if defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) + ::CoInitializeEx(NULL, COINIT_MULTITHREADED); +#endif // defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) + + CSoundDeviceDSound3::s_mastervol_available = true;//np2oscfg.usemastervolume ? true : false; + CSoundDeviceDSound3::Initialize(); +#if defined(SUPPORT_WASAPI) + CSoundDeviceWasapi::Initialize(); +#endif // defined(SUPPORT_WASAPI) + +#if defined(SUPPORT_ASIO) + CSoundDeviceAsio::Initialize(); +#endif // defined(SUPPORT_ASIO) + +#if defined(SUPPORT_ROMEO) + CExternalChipManager::GetInstance()->Initialize(); +#endif // defined(SUPPORT_ROMEO) + + CSoundMng::GetInstance()->InitializeSoundCriticalSection(); +} + +/** + * 解放 + */ +void CSoundMng::Deinitialize() +{ +#if defined(SUPPORT_ROMEO) + CExternalChipManager::GetInstance()->Deinitialize(); +#endif // defined(SUPPORT_ROMEO) + +#if defined(SUPPORT_WASAPI) + CSoundDeviceWasapi::Deinitialize(); +#endif // defined(SUPPORT_WASAPI) + +#if defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) + ::CoUninitialize(); +#endif // defined(SUPPORT_ASIO) || defined(SUPPORT_WASAPI) + + CSoundMng::GetInstance()->FinalizeSoundCriticalSection(); +} + +/** + * コンストラクタ + */ +CSoundMng::CSoundMng() + : m_pSoundDevice(NULL) + , m_nMute(0) + , m_sound_cs_initialized(false) +{ + SetReverse(false); +} + +/** + * オープン + * @param[in] nType デバイス タイプ + * @param[in] lpName デバイス名 + * @param[in] hWnd ウィンドウ ハンドル + * @retval true 成功 + * @retval false 失敗 + */ +bool CSoundMng::Open(DeviceType nType, LPCTSTR lpName, HWND hWnd) +{ + EnterAllCriticalSection(); + + Close(); + + CSoundDeviceBase* pSoundDevice = NULL; + switch (nType) + { + case kDefault: + pSoundDevice = new CSoundDeviceDSound3; + lpName = NULL; + break; + + case kDSound3: + pSoundDevice = new CSoundDeviceDSound3; + break; + +#if defined(SUPPORT_WASAPI) + case kWasapi: + pSoundDevice = new CSoundDeviceWasapi; + break; +#endif // defined(SUPPORT_WASAPI) + +#if defined(SUPPORT_ASIO) + case kAsio: + pSoundDevice = new CSoundDeviceAsio; + break; +#endif // defined(SUPPORT_ASIO) + } + + if (pSoundDevice) + { + if (!pSoundDevice->Open(lpName, hWnd)) + { + delete pSoundDevice; + pSoundDevice = NULL; + } + } + + if (pSoundDevice == NULL) + { + LeaveSoundCriticalSection(); + return false; + } + + m_pSoundDevice = pSoundDevice; + +#if defined(MT32SOUND_DLL) + MT32Sound::GetInstance()->Initialize(); +#endif + + LeaveAllCriticalSection(); + return true; +} + +/** + * クローズ + */ +void CSoundMng::Close() +{ + EnterAllCriticalSection(); + if (m_pSoundDevice) + { + m_pSoundDevice->Close(); + delete m_pSoundDevice; + m_pSoundDevice = NULL; + } + +#if defined(MT32SOUND_DLL) + MT32Sound::GetInstance()->Deinitialize(); +#endif + LeaveAllCriticalSection(); +} + +/** + * サウンド有効 + * @param[in] nProc プロシージャ + */ +void CSoundMng::Enable(SoundProc nProc) +{ + EnterSoundCriticalSection(); + const UINT nBit = 1 << nProc; + if (!(m_nMute & nBit)) + { + LeaveSoundCriticalSection(); + return; + } + m_nMute &= ~nBit; + if (!m_nMute) + { + if (m_pSoundDevice) + { + m_pSoundDevice->PlayStream(); + } +#if defined(SUPPORT_ROMEO) + CExternalChipManager::GetInstance()->Mute(false); +#endif // defined(SUPPORT_ROMEO) + } + LeaveSoundCriticalSection(); +} + +/** + * サウンド無効 + * @param[in] nProc プロシージャ + */ +void CSoundMng::Disable(SoundProc nProc) +{ + EnterSoundCriticalSection(); + if (!m_nMute) + { + if (m_pSoundDevice) + { + m_pSoundDevice->StopStream(); + m_pSoundDevice->StopAllPCM(); + } +#if defined(SUPPORT_ROMEO) + CExternalChipManager::GetInstance()->Mute(true); +#endif // defined(SUPPORT_ROMEO) + } + m_nMute |= (1 << nProc); + LeaveSoundCriticalSection(); +} + +/** + * ストリームを作成 + * @param[in] nSamplingRate サンプリング レート + * @param[in] ms バッファ長(ミリ秒) + * @return バッファ数 + */ +UINT CSoundMng::CreateStream(UINT nSamplingRate, UINT ms) +{ + EnterAllCriticalSection(); + if (m_pSoundDevice == NULL) + { + LeaveSoundCriticalSection(); + return 0; + } + + if (ms < 40) + { + ms = 40; + } + else if (ms > 1000) + { + ms = 1000; + } + UINT nBuffer = (nSamplingRate * ms) / 2000; + nBuffer = (nBuffer + 1) & (~1); + + nBuffer = m_pSoundDevice->CreateStream(nSamplingRate, 2, nBuffer); + if (nBuffer == 0) + { + LeaveSoundCriticalSection(); + return 0; + } + m_pSoundDevice->SetStreamData(this); + +#if defined(VERMOUTH_LIB) + vermouth_module = midimod_create(nSamplingRate); + midimod_loadall(vermouth_module); +#endif + +#if defined(MT32SOUND_DLL) + MT32Sound::GetInstance()->SetRate(nSamplingRate); +#endif + + LeaveAllCriticalSection(); + return nBuffer; +} + +/** + * ストリームを破棄 + */ +inline void CSoundMng::DestroyStream() +{ + if (m_pSoundDevice) + { + m_pSoundDevice->DestroyStream(); + } + +#if defined(VERMOUTH_LIB) + midimod_destroy(vermouth_module); + vermouth_module = NULL; +#endif +#if defined(MT32SOUND_DLL) + MT32Sound::GetInstance()->SetRate(0); +#endif +} + +/** + * ストリームのリセット + */ +inline void CSoundMng::ResetStream() +{ + EnterSoundCriticalSection(); + if (m_pSoundDevice) + { + m_pSoundDevice->ResetStream(); + } + LeaveSoundCriticalSection(); +} + +/** + * ストリームの再生 + */ +inline void CSoundMng::PlayStream() +{ + EnterSoundCriticalSection(); + if (!m_nMute) + { + if (m_pSoundDevice) + { + m_pSoundDevice->PlayStream(); + } + } + LeaveSoundCriticalSection(); +} + +/** + * ストリームの停止 + */ +inline void CSoundMng::StopStream() +{ + EnterSoundCriticalSection(); + if (!m_nMute) + { + if (m_pSoundDevice) + { + m_pSoundDevice->StopStream(); + } + } + LeaveSoundCriticalSection(); +} + +/** + * ストリームを得る + * @param[out] lpBuffer バッファ + * @param[in] nBufferCount バッファ カウント + * @return サンプル数 + */ +UINT CSoundMng::Get16(SINT16* lpBuffer, UINT nBufferCount) +{ + EnterSoundCriticalSection(); + const SINT32* lpSource = ::sound_pcmlock(); + if (lpSource) + { + (*m_fnMix)(lpBuffer, lpSource, nBufferCount * 4); + ::sound_pcmunlock(lpSource); + LeaveSoundCriticalSection(); + return nBufferCount; + } + else + { + LeaveSoundCriticalSection(); + return 0; + } +} + +/** + * パン反転を設定する + * @param[in] bReverse 反転フラグ + */ +inline void CSoundMng::SetReverse(bool bReverse) +{ + EnterSoundCriticalSection(); + if (!bReverse) + { +#if !defined(_WIN64) + if (mmxflag) + { + m_fnMix = satuation_s16; + } + else { + m_fnMix = satuation_s16mmx; + } +#else + m_fnMix = satuation_s16; +#endif + } + else + { + m_fnMix = satuation_s16x; + } + LeaveSoundCriticalSection(); +} + +/** + * マスター ヴォリューム設定 + * @param[in] nVolume ヴォリューム + */ +void CSoundMng::SetMasterVolume(int nVolume) +{ + EnterSoundCriticalSection(); + if (m_pSoundDevice) + { + m_pSoundDevice->SetMasterVolume(nVolume); + } + LeaveSoundCriticalSection(); +} + +/** + * PCM データ読み込み + * @param[in] nNum PCM 番号 + * @param[in] lpFilename ファイル名 + */ +void CSoundMng::LoadPCM(SoundPCMNumber nNum, LPCTSTR lpFilename) +{ + EnterSoundCriticalSection(); + if (m_pSoundDevice) + { + m_pSoundDevice->LoadPCM(nNum, lpFilename); + } + LeaveSoundCriticalSection(); +} + +/** + * PCM データ再読み込み + * @param[in] nNum PCM 番号 + * @param[in] lpFilename ファイル名 + */ +void CSoundMng::ReloadPCM(SoundPCMNumber nNum) +{ + EnterSoundCriticalSection(); + if (m_pSoundDevice) + { + m_pSoundDevice->ReloadPCM(nNum); + } + LeaveSoundCriticalSection(); +} + +/** + * PCM ヴォリューム設定 + * @param[in] nNum PCM 番号 + * @param[in] nVolume ヴォリューム + */ +void CSoundMng::SetPCMVolume(SoundPCMNumber nNum, int nVolume) +{ + EnterSoundCriticalSection(); + if (m_pSoundDevice) + { + m_pSoundDevice->SetPCMVolume(nNum, nVolume); + } + LeaveSoundCriticalSection(); +} + +/** + * PCM 再生 + * @param[in] nNum PCM 番号 + * @param[in] bLoop ループ フラグ + * @retval true 成功 + * @retval false 失敗 + */ +inline bool CSoundMng::PlayPCM(SoundPCMNumber nNum, BOOL bLoop) +{ + EnterSoundCriticalSection(); + if (!m_nMute) + { + if (m_pSoundDevice) + { + LeaveSoundCriticalSection(); + return m_pSoundDevice->PlayPCM(nNum, bLoop); + } + } + LeaveSoundCriticalSection(); + return false; +} + +/** + * PCM 停止 + * @param[in] nNum PCM 番号 + */ +inline void CSoundMng::StopPCM(SoundPCMNumber nNum) +{ + EnterSoundCriticalSection(); + if (m_pSoundDevice) + { + m_pSoundDevice->StopPCM(nNum); + } + LeaveSoundCriticalSection(); +} + +// クリティカルセクション関連 +void CSoundMng::InitializeSoundCriticalSection() +{ + if(!m_sound_cs_initialized){ + InitializeCriticalSection(&m_sound_cs); + m_sound_cs_initialized = true; + } +} +void CSoundMng::FinalizeSoundCriticalSection() +{ + if(m_sound_cs_initialized){ + DeleteCriticalSection(&m_sound_cs); + m_sound_cs_initialized = false; + } +} +void CSoundMng::EnterSoundCriticalSection() +{ + if(m_sound_cs_initialized){ + EnterCriticalSection(&m_sound_cs); + } +} +void CSoundMng::LeaveSoundCriticalSection() +{ + if(m_sound_cs_initialized){ + LeaveCriticalSection(&m_sound_cs); + } +} +void CSoundMng::EnterAllCriticalSection() +{ + np2_multithread_EnterCriticalSection(); + EnterSoundCriticalSection(); +} +void CSoundMng::LeaveAllCriticalSection() +{ + LeaveSoundCriticalSection(); + np2_multithread_LeaveCriticalSection(); +} + +// ---- C ラッパー + +/** + * ストリーム作成 + * @param[in] rate サンプリング レート + * @param[in] ms バッファ長(ミリ秒) + * @return バッファ サイズ + */ +UINT soundmng_create(UINT rate, UINT ms) +{ + UINT result; + result = CSoundMng::GetInstance()->CreateStream(rate, ms); + return result; +} + +/** + * ストリーム破棄 + */ +void soundmng_destroy(void) +{ + CSoundMng::GetInstance()->DestroyStream(); +} + +/** + * ストリーム リセット + */ +void soundmng_reset(void) +{ + CSoundMng::GetInstance()->ResetStream(); +} + +/** + * ストリーム開始 + */ +void soundmng_play(void) +{ + CSoundMng::GetInstance()->PlayStream(); +} + +/** + * ストリーム停止 + */ +void soundmng_stop(void) +{ + CSoundMng::GetInstance()->StopStream(); +} + +/** + * ストリーム パン反転設定 + * @param[in] bReverse 反転 + */ +void soundmng_setreverse(BOOL bReverse) +{ + CSoundMng::GetInstance()->SetReverse((bReverse) ? true : false); +} + +/** + * ボリューム設定 + * @param[in] nVolume ボリューム(最小 0 〜 100 最大) + */ +void soundmng_setvolume(int nVolume) +{ + CSoundMng::GetInstance()->SetMasterVolume(nVolume); +} + +/** + * PCM 再生 + * @param[in] nNum PCM 番号 + * @param[in] bLoop ループ + * @retval SUCCESS 成功 + * @retval FAILURE 失敗 + */ +BRESULT soundmng_pcmplay(enum SoundPCMNumber nNum, BOOL bLoop) +{ + BRESULT result; + result = (CSoundMng::GetInstance()->PlayPCM(nNum, bLoop)) ? SUCCESS : FAILURE; + return result; +} + +/** + * PCM 停止 + * @param[in] nNum PCM 番号 + */ +void soundmng_pcmstop(enum SoundPCMNumber nNum) +{ + CSoundMng::GetInstance()->StopPCM(nNum); +} + + diff --git a/windows/soundmng.h b/windows/soundmng.h index a64665ae..f9ea333b 100644 --- a/windows/soundmng.h +++ b/windows/soundmng.h @@ -1,124 +1,124 @@ -/** - * @file soundmng.h - * @brief サウンド マネージャ クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -/** - * PCM 番号 - */ -enum SoundPCMNumber -{ - SOUND_PCMSEEK = 0, /*!< ヘッド移動 */ - SOUND_PCMSEEK1, /*!< 1クラスタ移動 */ - SOUND_RELAY1 /*!< リレー */ -}; - -#ifdef __cplusplus -extern "C" -{ -#endif - -UINT soundmng_create(UINT rate, UINT ms); -void soundmng_destroy(void); -void soundmng_reset(void); -void soundmng_play(void); -void soundmng_stop(void); -#define soundmng_sync() -void soundmng_setreverse(BOOL bReverse); -void soundmng_setvolume(int nVolume); - -BRESULT soundmng_pcmplay(enum SoundPCMNumber nNum, BOOL bLoop); -void soundmng_pcmstop(enum SoundPCMNumber nNum); - -#ifdef __cplusplus -} - -#include "soundmng/sdbase.h" - -/** - * サウンド プロシージャ - */ -enum SoundProc -{ - SNDPROC_MASTER = 0, - SNDPROC_MAIN, - SNDPROC_TOOL, - SNDPROC_SUBWIND, - SNDPROC_USER -}; - -/** - * @brief サウンド マネージャ クラス - */ -class CSoundMng : public ISoundData -{ -public: - /** - * デバイス タイプ - */ - enum DeviceType - { - kDefault = 0, /*!< Default */ - kDSound3, /*!< Direct Sound3 */ - kWasapi, /*!< WASAPI */ - kAsio /*!< ASIO */ - }; - - static CSoundMng* GetInstance(); - static void Initialize(); - static void Deinitialize(); - - CSoundMng(); - bool Open(DeviceType nType, LPCTSTR lpName, HWND hWnd); - void Close(); - void Enable(SoundProc nProc); - void Disable(SoundProc nProc); - UINT CreateStream(UINT nSamplingRate, UINT ms); - void DestroyStream(); - void ResetStream(); - void PlayStream(); - void StopStream(); - void SetReverse(bool bReverse); - void SetMasterVolume(int nVolume); - void LoadPCM(SoundPCMNumber nNum, LPCTSTR lpFilename); - void ReloadPCM(SoundPCMNumber nNum); - void SetPCMVolume(SoundPCMNumber nNum, int nVolume); - bool PlayPCM(SoundPCMNumber nNum, BOOL bLoop); - void StopPCM(SoundPCMNumber nNum); - virtual UINT Get16(SINT16* lpBuffer, UINT nBufferCount); - -private: - static CSoundMng sm_instance; //!< 唯一のインスタンスです - - void InitializeSoundCriticalSection(); - void FinalizeSoundCriticalSection(); - void EnterSoundCriticalSection(); - void LeaveSoundCriticalSection(); - void EnterAllCriticalSection(); - void LeaveAllCriticalSection(); - - /** - * satuation関数型宣言 - */ - typedef void (PARTSCALL * FNMIX)(SINT16*, const SINT32*, UINT); - - CSoundDeviceBase* m_pSoundDevice; //!< サウンド デバイス - UINT m_nMute; //!< ミュート フラグ - FNMIX m_fnMix; //!< satuation関数ポインタ - - bool m_sound_cs_initialized; //!< クリティカルセクション 初期化済みフラグ - CRITICAL_SECTION m_sound_cs; //!< クリティカルセクション -}; - -/** - * インスタンスを得る - * @return インスタンス - */ -inline CSoundMng* CSoundMng::GetInstance() -{ - return &sm_instance; -} - -#endif +/** + * @file soundmng.h + * @brief サウンド マネージャ クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +/** + * PCM 番号 + */ +enum SoundPCMNumber +{ + SOUND_PCMSEEK = 0, /*!< ヘッド移動 */ + SOUND_PCMSEEK1, /*!< 1クラスタ移動 */ + SOUND_RELAY1 /*!< リレー */ +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +UINT soundmng_create(UINT rate, UINT ms); +void soundmng_destroy(void); +void soundmng_reset(void); +void soundmng_play(void); +void soundmng_stop(void); +#define soundmng_sync() +void soundmng_setreverse(BOOL bReverse); +void soundmng_setvolume(int nVolume); + +BRESULT soundmng_pcmplay(enum SoundPCMNumber nNum, BOOL bLoop); +void soundmng_pcmstop(enum SoundPCMNumber nNum); + +#ifdef __cplusplus +} + +#include "soundmng/sdbase.h" + +/** + * サウンド プロシージャ + */ +enum SoundProc +{ + SNDPROC_MASTER = 0, + SNDPROC_MAIN, + SNDPROC_TOOL, + SNDPROC_SUBWIND, + SNDPROC_USER +}; + +/** + * @brief サウンド マネージャ クラス + */ +class CSoundMng : public ISoundData +{ +public: + /** + * デバイス タイプ + */ + enum DeviceType + { + kDefault = 0, /*!< Default */ + kDSound3, /*!< Direct Sound3 */ + kWasapi, /*!< WASAPI */ + kAsio /*!< ASIO */ + }; + + static CSoundMng* GetInstance(); + static void Initialize(); + static void Deinitialize(); + + CSoundMng(); + bool Open(DeviceType nType, LPCTSTR lpName, HWND hWnd); + void Close(); + void Enable(SoundProc nProc); + void Disable(SoundProc nProc); + UINT CreateStream(UINT nSamplingRate, UINT ms); + void DestroyStream(); + void ResetStream(); + void PlayStream(); + void StopStream(); + void SetReverse(bool bReverse); + void SetMasterVolume(int nVolume); + void LoadPCM(SoundPCMNumber nNum, LPCTSTR lpFilename); + void ReloadPCM(SoundPCMNumber nNum); + void SetPCMVolume(SoundPCMNumber nNum, int nVolume); + bool PlayPCM(SoundPCMNumber nNum, BOOL bLoop); + void StopPCM(SoundPCMNumber nNum); + virtual UINT Get16(SINT16* lpBuffer, UINT nBufferCount); + +private: + static CSoundMng sm_instance; //!< 唯一のインスタンスです + + void InitializeSoundCriticalSection(); + void FinalizeSoundCriticalSection(); + void EnterSoundCriticalSection(); + void LeaveSoundCriticalSection(); + void EnterAllCriticalSection(); + void LeaveAllCriticalSection(); + + /** + * satuation関数型宣言 + */ + typedef void (PARTSCALL * FNMIX)(SINT16*, const SINT32*, UINT); + + CSoundDeviceBase* m_pSoundDevice; //!< サウンド デバイス + UINT m_nMute; //!< ミュート フラグ + FNMIX m_fnMix; //!< satuation関数ポインタ + + bool m_sound_cs_initialized; //!< クリティカルセクション 初期化済みフラグ + CRITICAL_SECTION m_sound_cs; //!< クリティカルセクション +}; + +/** + * インスタンスを得る + * @return インスタンス + */ +inline CSoundMng* CSoundMng::GetInstance() +{ + return &sm_instance; +} + +#endif diff --git a/windows/soundmng/asio/asiodriverlist.cpp b/windows/soundmng/asio/asiodriverlist.cpp old mode 100755 new mode 100644 index 73f2a15c..99de92e8 --- a/windows/soundmng/asio/asiodriverlist.cpp +++ b/windows/soundmng/asio/asiodriverlist.cpp @@ -1,121 +1,121 @@ -/** - * @file asiodriverlist.cpp - * @brief ASIO ドライバ リスト クラスの動作の定義を行います - */ - -#include -#include "asiodriverlist.h" -#include -#include -#include "asiosdk.h" - -#pragma comment(lib, "shlwapi.lib") - -/** - * ドライバを列挙する - */ -void AsioDriverList::EnumerateDrivers() -{ - clear(); - CRegKey asio; - if (asio.Open(HKEY_LOCAL_MACHINE, TEXT("software\\asio"), KEY_ENUMERATE_SUB_KEYS) == ERROR_SUCCESS) - { - for (DWORD dwIndex = 0; ; dwIndex++) - { - TCHAR szKeyName[MAX_PATH]; - if (::RegEnumKey(asio, dwIndex, szKeyName, _countof(szKeyName)) != ERROR_SUCCESS) - { - break; - } - - AsioDriverInfo info; - ZeroMemory(&info, sizeof(info)); - - CRegKey drv; - if (drv.Open(asio, szKeyName, KEY_READ) != ERROR_SUCCESS) - { - continue; - } - - TCHAR szClsId[256]; - ULONG nSize = _countof(szClsId); - if (drv.QueryValue(szClsId, TEXT("clsid"), &nSize) != ERROR_SUCCESS) - { - continue; - } - if (!FindDrvPath(szClsId, info.szDllPath, _countof(info.szDllPath))) - { - continue; - } - - USES_CONVERSION; - CLSID clsid; - if (CLSIDFromString(T2W(szClsId), &clsid) == S_OK) - { - info.clsid = clsid; - } - - nSize = _countof(info.szDriverName); - if (drv.QueryValue(info.szDriverName, TEXT("description"), &nSize) != ERROR_SUCCESS) - { - ::lstrcpyn(info.szDriverName, szKeyName, _countof(info.szDriverName)); - } - push_back(info); - } - } -} - -/** - * デバイス パスを取得 - * @param[in] lpClsId クラス ID - * @param[out] lpDllPath DLL パス - * @param[in] cchDllPath DLL バッファ長さ - * @retval true 成功 - * @retval false 失敗 - */ -bool AsioDriverList::FindDrvPath(LPCTSTR lpClsId, LPTSTR lpDllPath, UINT cchDllPath) -{ - TCHAR szPath[MAX_PATH]; - wsprintf(szPath, TEXT("clsid\\%s\\InprocServer32"), lpClsId); - - CRegKey inproc; - if (inproc.Open(HKEY_CLASSES_ROOT, szPath, KEY_READ) != ERROR_SUCCESS) - { - return false; - } - - ULONG nSize = cchDllPath; - if (inproc.QueryValue(lpDllPath, NULL, &nSize) != ERROR_SUCCESS) - { - return false; - } - - if (!::PathFileExists(lpDllPath)) - { - return false; - } - return true; -} - -/** - * ドライバをロード - * @param[in] lpDriverName ドライバ名 - * @return インスタンス - */ -IASIO* AsioDriverList::OpenDriver(LPCTSTR lpDriverName) -{ - AsioDriverList::const_iterator it = begin(); - while ((it != end()) && (::lstrcmpi(it->szDriverName, lpDriverName) != 0)) - { - ++it; - } - if (it != end()) - { - VOID* pAsio = NULL; - if (::CoCreateInstance(it->clsid, 0, CLSCTX_INPROC_SERVER, it->clsid, &pAsio) == S_OK) - { - return static_cast(pAsio); - } - } - return NULL; -} +/** + * @file asiodriverlist.cpp + * @brief ASIO ドライバ リスト クラスの動作の定義を行います + */ + +#include +#include "asiodriverlist.h" +#include +#include +#include "asiosdk.h" + +#pragma comment(lib, "shlwapi.lib") + +/** + * ドライバを列挙する + */ +void AsioDriverList::EnumerateDrivers() +{ + clear(); + CRegKey asio; + if (asio.Open(HKEY_LOCAL_MACHINE, TEXT("software\\asio"), KEY_ENUMERATE_SUB_KEYS) == ERROR_SUCCESS) + { + for (DWORD dwIndex = 0; ; dwIndex++) + { + TCHAR szKeyName[MAX_PATH]; + if (::RegEnumKey(asio, dwIndex, szKeyName, _countof(szKeyName)) != ERROR_SUCCESS) + { + break; + } + + AsioDriverInfo info; + ZeroMemory(&info, sizeof(info)); + + CRegKey drv; + if (drv.Open(asio, szKeyName, KEY_READ) != ERROR_SUCCESS) + { + continue; + } + + TCHAR szClsId[256]; + ULONG nSize = _countof(szClsId); + if (drv.QueryValue(szClsId, TEXT("clsid"), &nSize) != ERROR_SUCCESS) + { + continue; + } + if (!FindDrvPath(szClsId, info.szDllPath, _countof(info.szDllPath))) + { + continue; + } + + USES_CONVERSION; + CLSID clsid; + if (CLSIDFromString(T2W(szClsId), &clsid) == S_OK) + { + info.clsid = clsid; + } + + nSize = _countof(info.szDriverName); + if (drv.QueryValue(info.szDriverName, TEXT("description"), &nSize) != ERROR_SUCCESS) + { + ::lstrcpyn(info.szDriverName, szKeyName, _countof(info.szDriverName)); + } + push_back(info); + } + } +} + +/** + * デバイス パスを取得 + * @param[in] lpClsId クラス ID + * @param[out] lpDllPath DLL パス + * @param[in] cchDllPath DLL バッファ長さ + * @retval true 成功 + * @retval false 失敗 + */ +bool AsioDriverList::FindDrvPath(LPCTSTR lpClsId, LPTSTR lpDllPath, UINT cchDllPath) +{ + TCHAR szPath[MAX_PATH]; + wsprintf(szPath, TEXT("clsid\\%s\\InprocServer32"), lpClsId); + + CRegKey inproc; + if (inproc.Open(HKEY_CLASSES_ROOT, szPath, KEY_READ) != ERROR_SUCCESS) + { + return false; + } + + ULONG nSize = cchDllPath; + if (inproc.QueryValue(lpDllPath, NULL, &nSize) != ERROR_SUCCESS) + { + return false; + } + + if (!::PathFileExists(lpDllPath)) + { + return false; + } + return true; +} + +/** + * ドライバをロード + * @param[in] lpDriverName ドライバ名 + * @return インスタンス + */ +IASIO* AsioDriverList::OpenDriver(LPCTSTR lpDriverName) +{ + AsioDriverList::const_iterator it = begin(); + while ((it != end()) && (::lstrcmpi(it->szDriverName, lpDriverName) != 0)) + { + ++it; + } + if (it != end()) + { + VOID* pAsio = NULL; + if (::CoCreateInstance(it->clsid, 0, CLSCTX_INPROC_SERVER, it->clsid, &pAsio) == S_OK) + { + return static_cast(pAsio); + } + } + return NULL; +} diff --git a/windows/soundmng/asio/asiodriverlist.h b/windows/soundmng/asio/asiodriverlist.h old mode 100755 new mode 100644 index b272a5bf..60c8e055 --- a/windows/soundmng/asio/asiodriverlist.h +++ b/windows/soundmng/asio/asiodriverlist.h @@ -1,33 +1,33 @@ -/** - * @file asiodriverlist.h - * @brief ASIO ドライバ リスト クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include - -interface IASIO; - -/** - * ASIO ドライバ情報 - */ -struct AsioDriverInfo -{ - CLSID clsid; /*!< クラス ID */ - TCHAR szDllPath[MAX_PATH]; /*!< DLL パス */ - TCHAR szDriverName[128]; /*!< ドライバ名 */ -}; - -/** - * @brief ASIO ドライバ リスト クラス - */ -class AsioDriverList : public std::vector -{ -public: - void EnumerateDrivers(); - IASIO* OpenDriver(LPCTSTR lpDriverName); - -private: - static bool FindDrvPath(LPCTSTR lpClsId, LPTSTR lpDllPath, UINT cchDllPath); -}; +/** + * @file asiodriverlist.h + * @brief ASIO ドライバ リスト クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include + +interface IASIO; + +/** + * ASIO ドライバ情報 + */ +struct AsioDriverInfo +{ + CLSID clsid; /*!< クラス ID */ + TCHAR szDllPath[MAX_PATH]; /*!< DLL パス */ + TCHAR szDriverName[128]; /*!< ドライバ名 */ +}; + +/** + * @brief ASIO ドライバ リスト クラス + */ +class AsioDriverList : public std::vector +{ +public: + void EnumerateDrivers(); + IASIO* OpenDriver(LPCTSTR lpDriverName); + +private: + static bool FindDrvPath(LPCTSTR lpClsId, LPTSTR lpDllPath, UINT cchDllPath); +}; diff --git a/windows/soundmng/asio/asiosdk.h b/windows/soundmng/asio/asiosdk.h old mode 100755 new mode 100644 index 15da1b25..816e8845 --- a/windows/soundmng/asio/asiosdk.h +++ b/windows/soundmng/asio/asiosdk.h @@ -1,157 +1,157 @@ -/** - * @file asiosdk.h - */ - -#pragma once - -/** - * Boolean values - */ -typedef long ASIOBool; - -/** - * Boolean values - */ -enum -{ - ASIOFalse = 0, - ASIOTrue = 1 -}; - -/** - * Error code - */ -typedef long ASIOError; - -/** - * Error code - */ -enum -{ - ASE_OK = 0, //!< This value will be returned whenever the call succeeded - ASE_SUCCESS = 0x3f4847a0, //!< unique success return value for ASIOFuture calls - ASE_NotPresent = -1000, //!< hardware input or output is not present or available - ASE_HWMalfunction, //!< hardware is malfunctioning (can be returned by any ASIO function) - ASE_InvalidParameter, //!< input parameter invalid - ASE_InvalidMode, //!< hardware is in a bad mode or used in a bad mode - ASE_SPNotAdvancing, //!< hardware is not running when sample position is inquired - ASE_NoClock, //!< sample clock or rate cannot be determined or is not present - ASE_NoMemory //!< not enough memory for completing the request -}; - -/** - * Sample rate - */ -typedef double ASIOSampleRate; - -struct ASIOClockSource; -struct ASIOSamples; -struct ASIOTimeStamp; - -/** - * Sample Types - */ -typedef long ASIOSampleType; - -/** - * Sample Types - */ -enum -{ - ASIOSTInt16MSB = 0, //!< 16 bit data word - ASIOSTInt24MSB = 1, //!< This is the packed 24 bit format. used for 20 bits as well - ASIOSTInt32MSB = 2, - ASIOSTFloat32MSB = 3, // IEEE 754 32 bit float - ASIOSTFloat64MSB = 4, // IEEE 754 64 bit double float - - // these are used for 32 bit data buffer, with different alignment of the data inside - // 32 bit PCI bus systems can be more easily used with these - ASIOSTInt32MSB16 = 8, // 32 bit data with 16 bit alignment - ASIOSTInt32MSB18 = 9, // 32 bit data with 18 bit alignment - ASIOSTInt32MSB20 = 10, // 32 bit data with 20 bit alignment - ASIOSTInt32MSB24 = 11, // 32 bit data with 24 bit alignment - - ASIOSTInt16LSB = 16, - ASIOSTInt24LSB = 17, // used for 20 bits as well - ASIOSTInt32LSB = 18, - ASIOSTFloat32LSB = 19, // IEEE 754 32 bit float, as found on Intel x86 architecture - ASIOSTFloat64LSB = 20, // IEEE 754 64 bit double float, as found on Intel x86 architecture - - // these are used for 32 bit data buffer, with different alignment of the data inside - // 32 bit PCI bus systems can more easily used with these - ASIOSTInt32LSB16 = 24, // 32 bit data with 18 bit alignment - ASIOSTInt32LSB18 = 25, // 32 bit data with 18 bit alignment - ASIOSTInt32LSB20 = 26, // 32 bit data with 20 bit alignment - ASIOSTInt32LSB24 = 27, // 32 bit data with 24 bit alignment - - // ASIO DSD format. - ASIOSTDSDInt8LSB1 = 32, // DSD 1 bit data, 8 samples per byte. First sample in Least significant bit. - ASIOSTDSDInt8MSB1 = 33, // DSD 1 bit data, 8 samples per byte. First sample in Most significant bit. - ASIOSTDSDInt8NER8 = 40, // DSD 8 bit data, 1 sample per byte. No Endianness required. - - ASIOSTLastEntry -}; - -/** - * @brief Channel info - */ -struct ASIOChannelInfo -{ - long channel; //!< on input, channel index - ASIOBool isInput; //!< on input - ASIOBool isActive; //!< on exit - long channelGroup; //!< dto - ASIOSampleType type; //!< dto - char name[32]; //!< dto -}; - -/** - * @brief Buffer info - */ -struct ASIOBufferInfo -{ - ASIOBool isInput; //!< on input: ASIOTrue: input, else output - long channelNum; //!< on input: channel index - void* buffers[2]; //!< on output: double buffer addresses -}; - -struct ASIOTime; - -/** - * @brief Callback - */ -struct ASIOCallbacks -{ - void (*bufferSwitch)(long doubleBufferIndex, ASIOBool directProcess); - void (*sampleRateDidChange)(ASIOSampleRate sRate); - long (*asioMessage)(long selector, long value, void* message, double* opt); - ASIOTime* (*bufferSwitchTimeInfo)(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess); -}; - -/** - * @brief ASIO インタフェイス - */ -interface IASIO : public IUnknown -{ - virtual ASIOBool init(void* sysHandle) = 0; - virtual void getDriverName(char* name) = 0; - virtual long getDriverVersion() = 0; - virtual void getErrorMessage(char* string) = 0; - virtual ASIOError start() = 0; - virtual ASIOError stop() = 0; - virtual ASIOError getChannels(long* numInputChannels, long* numOutputChannels) = 0; - virtual ASIOError getLatencies(long* inputLatency, long* outputLatency) = 0; - virtual ASIOError getBufferSize(long* minSize, long* maxSize, long* preferredSize, long* granularity) = 0; - virtual ASIOError canSampleRate(ASIOSampleRate sampleRate) = 0; - virtual ASIOError getSampleRate(ASIOSampleRate* sampleRate) = 0; - virtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0; - virtual ASIOError getClockSources(ASIOClockSource* clocks, long* numSources) = 0; - virtual ASIOError setClockSource(long reference) = 0; - virtual ASIOError getSamplePosition(ASIOSamples* sPos, ASIOTimeStamp* tStamp) = 0; - virtual ASIOError getChannelInfo(ASIOChannelInfo* info) = 0; - virtual ASIOError createBuffers(ASIOBufferInfo* bufferInfos, long numChannels, long bufferSize, ASIOCallbacks* callbacks) = 0; - virtual ASIOError disposeBuffers() = 0; - virtual ASIOError controlPanel() = 0; - virtual ASIOError future(long selector, void* opt) = 0; - virtual ASIOError outputReady() = 0; -}; +/** + * @file asiosdk.h + */ + +#pragma once + +/** + * Boolean values + */ +typedef long ASIOBool; + +/** + * Boolean values + */ +enum +{ + ASIOFalse = 0, + ASIOTrue = 1 +}; + +/** + * Error code + */ +typedef long ASIOError; + +/** + * Error code + */ +enum +{ + ASE_OK = 0, //!< This value will be returned whenever the call succeeded + ASE_SUCCESS = 0x3f4847a0, //!< unique success return value for ASIOFuture calls + ASE_NotPresent = -1000, //!< hardware input or output is not present or available + ASE_HWMalfunction, //!< hardware is malfunctioning (can be returned by any ASIO function) + ASE_InvalidParameter, //!< input parameter invalid + ASE_InvalidMode, //!< hardware is in a bad mode or used in a bad mode + ASE_SPNotAdvancing, //!< hardware is not running when sample position is inquired + ASE_NoClock, //!< sample clock or rate cannot be determined or is not present + ASE_NoMemory //!< not enough memory for completing the request +}; + +/** + * Sample rate + */ +typedef double ASIOSampleRate; + +struct ASIOClockSource; +struct ASIOSamples; +struct ASIOTimeStamp; + +/** + * Sample Types + */ +typedef long ASIOSampleType; + +/** + * Sample Types + */ +enum +{ + ASIOSTInt16MSB = 0, //!< 16 bit data word + ASIOSTInt24MSB = 1, //!< This is the packed 24 bit format. used for 20 bits as well + ASIOSTInt32MSB = 2, + ASIOSTFloat32MSB = 3, // IEEE 754 32 bit float + ASIOSTFloat64MSB = 4, // IEEE 754 64 bit double float + + // these are used for 32 bit data buffer, with different alignment of the data inside + // 32 bit PCI bus systems can be more easily used with these + ASIOSTInt32MSB16 = 8, // 32 bit data with 16 bit alignment + ASIOSTInt32MSB18 = 9, // 32 bit data with 18 bit alignment + ASIOSTInt32MSB20 = 10, // 32 bit data with 20 bit alignment + ASIOSTInt32MSB24 = 11, // 32 bit data with 24 bit alignment + + ASIOSTInt16LSB = 16, + ASIOSTInt24LSB = 17, // used for 20 bits as well + ASIOSTInt32LSB = 18, + ASIOSTFloat32LSB = 19, // IEEE 754 32 bit float, as found on Intel x86 architecture + ASIOSTFloat64LSB = 20, // IEEE 754 64 bit double float, as found on Intel x86 architecture + + // these are used for 32 bit data buffer, with different alignment of the data inside + // 32 bit PCI bus systems can more easily used with these + ASIOSTInt32LSB16 = 24, // 32 bit data with 18 bit alignment + ASIOSTInt32LSB18 = 25, // 32 bit data with 18 bit alignment + ASIOSTInt32LSB20 = 26, // 32 bit data with 20 bit alignment + ASIOSTInt32LSB24 = 27, // 32 bit data with 24 bit alignment + + // ASIO DSD format. + ASIOSTDSDInt8LSB1 = 32, // DSD 1 bit data, 8 samples per byte. First sample in Least significant bit. + ASIOSTDSDInt8MSB1 = 33, // DSD 1 bit data, 8 samples per byte. First sample in Most significant bit. + ASIOSTDSDInt8NER8 = 40, // DSD 8 bit data, 1 sample per byte. No Endianness required. + + ASIOSTLastEntry +}; + +/** + * @brief Channel info + */ +struct ASIOChannelInfo +{ + long channel; //!< on input, channel index + ASIOBool isInput; //!< on input + ASIOBool isActive; //!< on exit + long channelGroup; //!< dto + ASIOSampleType type; //!< dto + char name[32]; //!< dto +}; + +/** + * @brief Buffer info + */ +struct ASIOBufferInfo +{ + ASIOBool isInput; //!< on input: ASIOTrue: input, else output + long channelNum; //!< on input: channel index + void* buffers[2]; //!< on output: double buffer addresses +}; + +struct ASIOTime; + +/** + * @brief Callback + */ +struct ASIOCallbacks +{ + void (*bufferSwitch)(long doubleBufferIndex, ASIOBool directProcess); + void (*sampleRateDidChange)(ASIOSampleRate sRate); + long (*asioMessage)(long selector, long value, void* message, double* opt); + ASIOTime* (*bufferSwitchTimeInfo)(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess); +}; + +/** + * @brief ASIO インタフェイス + */ +interface IASIO : public IUnknown +{ + virtual ASIOBool init(void* sysHandle) = 0; + virtual void getDriverName(char* name) = 0; + virtual long getDriverVersion() = 0; + virtual void getErrorMessage(char* string) = 0; + virtual ASIOError start() = 0; + virtual ASIOError stop() = 0; + virtual ASIOError getChannels(long* numInputChannels, long* numOutputChannels) = 0; + virtual ASIOError getLatencies(long* inputLatency, long* outputLatency) = 0; + virtual ASIOError getBufferSize(long* minSize, long* maxSize, long* preferredSize, long* granularity) = 0; + virtual ASIOError canSampleRate(ASIOSampleRate sampleRate) = 0; + virtual ASIOError getSampleRate(ASIOSampleRate* sampleRate) = 0; + virtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0; + virtual ASIOError getClockSources(ASIOClockSource* clocks, long* numSources) = 0; + virtual ASIOError setClockSource(long reference) = 0; + virtual ASIOError getSamplePosition(ASIOSamples* sPos, ASIOTimeStamp* tStamp) = 0; + virtual ASIOError getChannelInfo(ASIOChannelInfo* info) = 0; + virtual ASIOError createBuffers(ASIOBufferInfo* bufferInfos, long numChannels, long bufferSize, ASIOCallbacks* callbacks) = 0; + virtual ASIOError disposeBuffers() = 0; + virtual ASIOError controlPanel() = 0; + virtual ASIOError future(long selector, void* opt) = 0; + virtual ASIOError outputReady() = 0; +}; diff --git a/windows/soundmng/sdasio.cpp b/windows/soundmng/sdasio.cpp old mode 100755 new mode 100644 index 3de0cfa0..2426e389 --- a/windows/soundmng/sdasio.cpp +++ b/windows/soundmng/sdasio.cpp @@ -1,352 +1,352 @@ -/** - * @file sdasio.cpp - * @brief ASIO オーディオ クラスの動作の定義を行います - */ - -#include -#include "sdasio.h" - -/*! 唯一のインスタンスです */ -CSoundDeviceAsio* CSoundDeviceAsio::sm_pInstance; - -/*! ドライバ リスト */ -AsioDriverList CSoundDeviceAsio::sm_asioDriverList; - -/** - * 初期化 - */ -void CSoundDeviceAsio::Initialize() -{ - sm_asioDriverList.EnumerateDrivers(); -} - -/** - * 列挙 - * @param[out] devices デバイス リスト - */ -void CSoundDeviceAsio::EnumerateDevices(std::vector& devices) -{ - for (AsioDriverList::const_iterator it = sm_asioDriverList.begin(); it != sm_asioDriverList.end(); ++it) - { - devices.push_back(it->szDriverName); - } -} - -/** - * コンストラクタ - */ -CSoundDeviceAsio::CSoundDeviceAsio() - : m_pAsioDriver(NULL) - , m_nBufferLength(0) -{ -} - -/** - * デストラクタ - */ -CSoundDeviceAsio::~CSoundDeviceAsio() -{ - Close(); -} - -/** - * 初期化 - * @param[in] lpDevice デバイス名 - * @param[in] hWnd ウィンドウ ハンドル - * @retval true 成功 - * @retval false 失敗 - */ -bool CSoundDeviceAsio::Open(LPCTSTR lpDevice, HWND hWnd) -{ - if (lpDevice == NULL) - { - return false; - } - - if (m_pAsioDriver != NULL) - { - return false; - } - - m_pAsioDriver = sm_asioDriverList.OpenDriver(lpDevice); - if (m_pAsioDriver == NULL) - { - return false; - } - - if (m_pAsioDriver->init(hWnd) == ASIOFalse) - { - Close(); - return false; - } - return true; -} - -/** - * 解放 - */ -void CSoundDeviceAsio::Close() -{ - DestroyStream(); - if (m_pAsioDriver) - { - m_pAsioDriver->Release(); - m_pAsioDriver = NULL; - } -} - -/** - * オープン - * @param[in] nSamplingRate サンプリング レート - * @param[in] nChannels チャネル数 - * @param[in] nBufferSize バッファ サイズ - * @return バッファ サイズ - */ -UINT CSoundDeviceAsio::CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize) -{ - if (m_pAsioDriver == NULL) - { - return 0; - } - - do - { - long minSize; - long maxSize; - long preferredSize; - long granularity; - if (m_pAsioDriver->getBufferSize(&minSize, &maxSize, &preferredSize, &granularity) != ASE_OK) - { - break; - } - - ZeroMemory(&m_callback, sizeof(m_callback)); - m_callback.bufferSwitch = cBufferSwitch; - m_callback.sampleRateDidChange = cSampleRateDidChange; - m_callback.asioMessage = cAsioMessage; - m_callback.bufferSwitchTimeInfo = cBufferSwitchTimeInfo; - - m_bufferInfo.clear(); - for (UINT i = 0; i < nChannels; i++) - { - ASIOBufferInfo bufferInfo; - ZeroMemory(&bufferInfo, sizeof(bufferInfo)); - bufferInfo.isInput = ASIOFalse; - bufferInfo.channelNum = i; - m_bufferInfo.push_back(bufferInfo); - } - - m_nBufferLength = preferredSize; - m_pAsioDriver->createBuffers(&m_bufferInfo.at(0), static_cast(m_bufferInfo.size()), preferredSize, &m_callback); - - //! サンプルレートを設定する. - m_pAsioDriver->setSampleRate(nSamplingRate); - - sm_pInstance = this; - return m_nBufferLength; - } while(false /*CONSTCOND*/); - - Close(); - return 0; -} - -/** - * 破棄 - */ -void CSoundDeviceAsio::DestroyStream() -{ - if (sm_pInstance == this) - { - sm_pInstance = NULL; - } - - StopStream(); - if (m_pAsioDriver) - { - m_pAsioDriver->disposeBuffers(); - } - - m_bufferInfo.clear(); - m_nBufferLength = 0; -} - -/** - * 再生 - * @retval true 成功 - * @retval false 失敗 - */ -bool CSoundDeviceAsio::PlayStream() -{ - return (m_pAsioDriver) && (m_pAsioDriver->start() == ASE_OK); -} - -/** - * 停止 - */ -void CSoundDeviceAsio::StopStream() -{ - if (m_pAsioDriver) - { - m_pAsioDriver->stop(); - } -} - -/** - * Processing - * @param[in] doubleBufferIndex The current buffer half index (0 or 1) - * @param[in] directProcess immediately start processing - */ -void CSoundDeviceAsio::cBufferSwitch(long doubleBufferIndex, ASIOBool directProcess) -{ - if (sm_pInstance) - { - sm_pInstance->BufferSwitch(doubleBufferIndex, directProcess); - } -} - -/** - * Informs the host application that a sample rate change was detected - * @param[in] sRate The detected sample rate - */ -void CSoundDeviceAsio::cSampleRateDidChange(ASIOSampleRate sRate) -{ -} - -/** - * Generic callback use for various purposes - * @param[in] selector What kind of message is send - * @param[in] value The single value - * @param[in] message The message parameter - * @param[in] opt The optional parameter - * @return Specific to the selector - */ -long CSoundDeviceAsio::cAsioMessage(long selector, long value, void* message, double* opt) -{ - return 0; -} -/** - * Indicates that both input and output are to be processed - * @param[in] params The pointer to ASIOTime structure - * @param[in] doubleBufferIndex The current buffer half index (0 or 1) - * @param[in] directProcess immediately start processing - * @return The pointer to ASIOTime structure with "output" time code information - */ -ASIOTime* CSoundDeviceAsio::cBufferSwitchTimeInfo(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess) -{ - return NULL; -} - -/** - * Processing - * @param[in] doubleBufferIndex The current buffer half index (0 or 1) - * @param[in] directProcess immediately start processing - */ -void CSoundDeviceAsio::BufferSwitch(long doubleBufferIndex, ASIOBool directProcess) -{ - if (m_nBufferLength == 0) - { - return; - } - - UINT nStreamLength = 0; - std::vector stream(m_nBufferLength * m_bufferInfo.size()); - if (m_pSoundData) - { - nStreamLength = m_pSoundData->Get16(&stream.at(0), m_nBufferLength); - } - - const short* lpStream = &stream.at(0); - const UINT nAlign = static_cast(m_bufferInfo.size()); - - for (std::vector::iterator it = m_bufferInfo.begin(); it != m_bufferInfo.end(); ++it) - { - void* lpBuffer = it->buffers[doubleBufferIndex]; - - ASIOChannelInfo info; - info.channel = it->channelNum; - info.isInput = it->isInput; - m_pAsioDriver->getChannelInfo(&info); - - switch (info.type) - { - case ASIOSTInt16LSB: - { - short* lpOutput = static_cast(lpBuffer); - for (UINT i = 0; i < nStreamLength; i++) - { - lpOutput[i] = lpStream[i * nAlign]; - } - if (nStreamLength != m_nBufferLength) - { - memset(lpOutput + nStreamLength, 0, (m_nBufferLength - nStreamLength) * sizeof(short)); - } - } - break; - - case ASIOSTInt24LSB: - { - char* lpOutput = static_cast(lpBuffer); - for (UINT i = 0; i < nStreamLength; i++) - { - const short wSample = lpStream[i * nAlign]; - lpOutput[i * 3 + 0] = static_cast(wSample >> 8); - lpOutput[i * 3 + 1] = static_cast(wSample >> 0); - lpOutput[i * 3 + 2] = static_cast(wSample >> 8); - } - if (nStreamLength != m_nBufferLength) - { - memset(lpOutput + nStreamLength * 3, 0, (m_nBufferLength - nStreamLength) * sizeof(char) * 3); - } - } - memset(lpBuffer, 0, m_nBufferLength * 3); - break; - - case ASIOSTInt32LSB: - { - short* lpOutput = static_cast(lpBuffer); - for (UINT i = 0; i < nStreamLength; i++) - { - const short wSample = lpStream[i * nAlign]; - lpOutput[i * 2 + 0] = wSample; - lpOutput[i * 2 + 1] = wSample; - } - if (nStreamLength != m_nBufferLength) - { - memset(lpOutput + nStreamLength * 2, 0, (m_nBufferLength - nStreamLength) * sizeof(short) * 2); - } - } - break; - - case ASIOSTInt32LSB16: - case ASIOSTInt32LSB18: - case ASIOSTInt32LSB20: - case ASIOSTInt32LSB24: - case ASIOSTFloat32LSB: - case ASIOSTInt32MSB: - case ASIOSTInt32MSB16: - case ASIOSTInt32MSB18: - case ASIOSTInt32MSB20: - case ASIOSTInt32MSB24: - case ASIOSTFloat32MSB: - memset(lpBuffer, 0, m_nBufferLength * 4); - break; - - case ASIOSTFloat64LSB: - case ASIOSTFloat64MSB: - memset(lpBuffer, 0, m_nBufferLength * 8); - break; - - case ASIOSTInt16MSB: - memset(lpBuffer, 0, m_nBufferLength * 2); - break; - - case ASIOSTInt24MSB: - memset(lpBuffer, 0, m_nBufferLength * 3); - break; - } - - lpStream++; - } - - m_pAsioDriver->outputReady(); -} +/** + * @file sdasio.cpp + * @brief ASIO オーディオ クラスの動作の定義を行います + */ + +#include +#include "sdasio.h" + +/*! 唯一のインスタンスです */ +CSoundDeviceAsio* CSoundDeviceAsio::sm_pInstance; + +/*! ドライバ リスト */ +AsioDriverList CSoundDeviceAsio::sm_asioDriverList; + +/** + * 初期化 + */ +void CSoundDeviceAsio::Initialize() +{ + sm_asioDriverList.EnumerateDrivers(); +} + +/** + * 列挙 + * @param[out] devices デバイス リスト + */ +void CSoundDeviceAsio::EnumerateDevices(std::vector& devices) +{ + for (AsioDriverList::const_iterator it = sm_asioDriverList.begin(); it != sm_asioDriverList.end(); ++it) + { + devices.push_back(it->szDriverName); + } +} + +/** + * コンストラクタ + */ +CSoundDeviceAsio::CSoundDeviceAsio() + : m_pAsioDriver(NULL) + , m_nBufferLength(0) +{ +} + +/** + * デストラクタ + */ +CSoundDeviceAsio::~CSoundDeviceAsio() +{ + Close(); +} + +/** + * 初期化 + * @param[in] lpDevice デバイス名 + * @param[in] hWnd ウィンドウ ハンドル + * @retval true 成功 + * @retval false 失敗 + */ +bool CSoundDeviceAsio::Open(LPCTSTR lpDevice, HWND hWnd) +{ + if (lpDevice == NULL) + { + return false; + } + + if (m_pAsioDriver != NULL) + { + return false; + } + + m_pAsioDriver = sm_asioDriverList.OpenDriver(lpDevice); + if (m_pAsioDriver == NULL) + { + return false; + } + + if (m_pAsioDriver->init(hWnd) == ASIOFalse) + { + Close(); + return false; + } + return true; +} + +/** + * 解放 + */ +void CSoundDeviceAsio::Close() +{ + DestroyStream(); + if (m_pAsioDriver) + { + m_pAsioDriver->Release(); + m_pAsioDriver = NULL; + } +} + +/** + * オープン + * @param[in] nSamplingRate サンプリング レート + * @param[in] nChannels チャネル数 + * @param[in] nBufferSize バッファ サイズ + * @return バッファ サイズ + */ +UINT CSoundDeviceAsio::CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize) +{ + if (m_pAsioDriver == NULL) + { + return 0; + } + + do + { + long minSize; + long maxSize; + long preferredSize; + long granularity; + if (m_pAsioDriver->getBufferSize(&minSize, &maxSize, &preferredSize, &granularity) != ASE_OK) + { + break; + } + + ZeroMemory(&m_callback, sizeof(m_callback)); + m_callback.bufferSwitch = cBufferSwitch; + m_callback.sampleRateDidChange = cSampleRateDidChange; + m_callback.asioMessage = cAsioMessage; + m_callback.bufferSwitchTimeInfo = cBufferSwitchTimeInfo; + + m_bufferInfo.clear(); + for (UINT i = 0; i < nChannels; i++) + { + ASIOBufferInfo bufferInfo; + ZeroMemory(&bufferInfo, sizeof(bufferInfo)); + bufferInfo.isInput = ASIOFalse; + bufferInfo.channelNum = i; + m_bufferInfo.push_back(bufferInfo); + } + + m_nBufferLength = preferredSize; + m_pAsioDriver->createBuffers(&m_bufferInfo.at(0), static_cast(m_bufferInfo.size()), preferredSize, &m_callback); + + //! サンプルレートを設定する. + m_pAsioDriver->setSampleRate(nSamplingRate); + + sm_pInstance = this; + return m_nBufferLength; + } while(false /*CONSTCOND*/); + + Close(); + return 0; +} + +/** + * 破棄 + */ +void CSoundDeviceAsio::DestroyStream() +{ + if (sm_pInstance == this) + { + sm_pInstance = NULL; + } + + StopStream(); + if (m_pAsioDriver) + { + m_pAsioDriver->disposeBuffers(); + } + + m_bufferInfo.clear(); + m_nBufferLength = 0; +} + +/** + * 再生 + * @retval true 成功 + * @retval false 失敗 + */ +bool CSoundDeviceAsio::PlayStream() +{ + return (m_pAsioDriver) && (m_pAsioDriver->start() == ASE_OK); +} + +/** + * 停止 + */ +void CSoundDeviceAsio::StopStream() +{ + if (m_pAsioDriver) + { + m_pAsioDriver->stop(); + } +} + +/** + * Processing + * @param[in] doubleBufferIndex The current buffer half index (0 or 1) + * @param[in] directProcess immediately start processing + */ +void CSoundDeviceAsio::cBufferSwitch(long doubleBufferIndex, ASIOBool directProcess) +{ + if (sm_pInstance) + { + sm_pInstance->BufferSwitch(doubleBufferIndex, directProcess); + } +} + +/** + * Informs the host application that a sample rate change was detected + * @param[in] sRate The detected sample rate + */ +void CSoundDeviceAsio::cSampleRateDidChange(ASIOSampleRate sRate) +{ +} + +/** + * Generic callback use for various purposes + * @param[in] selector What kind of message is send + * @param[in] value The single value + * @param[in] message The message parameter + * @param[in] opt The optional parameter + * @return Specific to the selector + */ +long CSoundDeviceAsio::cAsioMessage(long selector, long value, void* message, double* opt) +{ + return 0; +} +/** + * Indicates that both input and output are to be processed + * @param[in] params The pointer to ASIOTime structure + * @param[in] doubleBufferIndex The current buffer half index (0 or 1) + * @param[in] directProcess immediately start processing + * @return The pointer to ASIOTime structure with "output" time code information + */ +ASIOTime* CSoundDeviceAsio::cBufferSwitchTimeInfo(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess) +{ + return NULL; +} + +/** + * Processing + * @param[in] doubleBufferIndex The current buffer half index (0 or 1) + * @param[in] directProcess immediately start processing + */ +void CSoundDeviceAsio::BufferSwitch(long doubleBufferIndex, ASIOBool directProcess) +{ + if (m_nBufferLength == 0) + { + return; + } + + UINT nStreamLength = 0; + std::vector stream(m_nBufferLength * m_bufferInfo.size()); + if (m_pSoundData) + { + nStreamLength = m_pSoundData->Get16(&stream.at(0), m_nBufferLength); + } + + const short* lpStream = &stream.at(0); + const UINT nAlign = static_cast(m_bufferInfo.size()); + + for (std::vector::iterator it = m_bufferInfo.begin(); it != m_bufferInfo.end(); ++it) + { + void* lpBuffer = it->buffers[doubleBufferIndex]; + + ASIOChannelInfo info; + info.channel = it->channelNum; + info.isInput = it->isInput; + m_pAsioDriver->getChannelInfo(&info); + + switch (info.type) + { + case ASIOSTInt16LSB: + { + short* lpOutput = static_cast(lpBuffer); + for (UINT i = 0; i < nStreamLength; i++) + { + lpOutput[i] = lpStream[i * nAlign]; + } + if (nStreamLength != m_nBufferLength) + { + memset(lpOutput + nStreamLength, 0, (m_nBufferLength - nStreamLength) * sizeof(short)); + } + } + break; + + case ASIOSTInt24LSB: + { + char* lpOutput = static_cast(lpBuffer); + for (UINT i = 0; i < nStreamLength; i++) + { + const short wSample = lpStream[i * nAlign]; + lpOutput[i * 3 + 0] = static_cast(wSample >> 8); + lpOutput[i * 3 + 1] = static_cast(wSample >> 0); + lpOutput[i * 3 + 2] = static_cast(wSample >> 8); + } + if (nStreamLength != m_nBufferLength) + { + memset(lpOutput + nStreamLength * 3, 0, (m_nBufferLength - nStreamLength) * sizeof(char) * 3); + } + } + memset(lpBuffer, 0, m_nBufferLength * 3); + break; + + case ASIOSTInt32LSB: + { + short* lpOutput = static_cast(lpBuffer); + for (UINT i = 0; i < nStreamLength; i++) + { + const short wSample = lpStream[i * nAlign]; + lpOutput[i * 2 + 0] = wSample; + lpOutput[i * 2 + 1] = wSample; + } + if (nStreamLength != m_nBufferLength) + { + memset(lpOutput + nStreamLength * 2, 0, (m_nBufferLength - nStreamLength) * sizeof(short) * 2); + } + } + break; + + case ASIOSTInt32LSB16: + case ASIOSTInt32LSB18: + case ASIOSTInt32LSB20: + case ASIOSTInt32LSB24: + case ASIOSTFloat32LSB: + case ASIOSTInt32MSB: + case ASIOSTInt32MSB16: + case ASIOSTInt32MSB18: + case ASIOSTInt32MSB20: + case ASIOSTInt32MSB24: + case ASIOSTFloat32MSB: + memset(lpBuffer, 0, m_nBufferLength * 4); + break; + + case ASIOSTFloat64LSB: + case ASIOSTFloat64MSB: + memset(lpBuffer, 0, m_nBufferLength * 8); + break; + + case ASIOSTInt16MSB: + memset(lpBuffer, 0, m_nBufferLength * 2); + break; + + case ASIOSTInt24MSB: + memset(lpBuffer, 0, m_nBufferLength * 3); + break; + } + + lpStream++; + } + + m_pAsioDriver->outputReady(); +} diff --git a/windows/soundmng/sdasio.h b/windows/soundmng/sdasio.h old mode 100755 new mode 100644 index 480193dc..5dd9cad3 --- a/windows/soundmng/sdasio.h +++ b/windows/soundmng/sdasio.h @@ -1,42 +1,42 @@ -/** - * @file sdasio.h - * @brief ASIO オーディオ クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "asio\asiosdk.h" -#include "asio\asiodriverlist.h" -#include "sdbase.h" - -/** - * @brief ASIO オーディオ クラス - */ -class CSoundDeviceAsio : public CSoundDeviceBase -{ -public: - static void Initialize(); - static void EnumerateDevices(std::vector& devices); - - CSoundDeviceAsio(); - virtual ~CSoundDeviceAsio(); - virtual bool Open(LPCTSTR lpDevice = NULL, HWND hWnd = NULL); - virtual void Close(); - virtual UINT CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize = 0); - virtual void DestroyStream(); - virtual bool PlayStream(); - virtual void StopStream(); - -private: - static CSoundDeviceAsio* sm_pInstance; /*!< 現在のインスタンス */ - IASIO* m_pAsioDriver; /*!< ASIO ドライバ */ - UINT m_nBufferLength; /*!< バッファ サイズ */ - std::vector m_bufferInfo; /*!< バッファ */ - ASIOCallbacks m_callback; /*!< コールバック */ - static AsioDriverList sm_asioDriverList; /*!< ドライバ リスト */ - static void cBufferSwitch(long doubleBufferIndex, ASIOBool directProcess); - static void cSampleRateDidChange(ASIOSampleRate sRate); - static long cAsioMessage(long selector, long value, void* message, double* opt); - static ASIOTime* cBufferSwitchTimeInfo(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess); - void BufferSwitch(long doubleBufferIndex, ASIOBool directProcess); -}; +/** + * @file sdasio.h + * @brief ASIO オーディオ クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "asio\asiosdk.h" +#include "asio\asiodriverlist.h" +#include "sdbase.h" + +/** + * @brief ASIO オーディオ クラス + */ +class CSoundDeviceAsio : public CSoundDeviceBase +{ +public: + static void Initialize(); + static void EnumerateDevices(std::vector& devices); + + CSoundDeviceAsio(); + virtual ~CSoundDeviceAsio(); + virtual bool Open(LPCTSTR lpDevice = NULL, HWND hWnd = NULL); + virtual void Close(); + virtual UINT CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize = 0); + virtual void DestroyStream(); + virtual bool PlayStream(); + virtual void StopStream(); + +private: + static CSoundDeviceAsio* sm_pInstance; /*!< 現在のインスタンス */ + IASIO* m_pAsioDriver; /*!< ASIO ドライバ */ + UINT m_nBufferLength; /*!< バッファ サイズ */ + std::vector m_bufferInfo; /*!< バッファ */ + ASIOCallbacks m_callback; /*!< コールバック */ + static AsioDriverList sm_asioDriverList; /*!< ドライバ リスト */ + static void cBufferSwitch(long doubleBufferIndex, ASIOBool directProcess); + static void cSampleRateDidChange(ASIOSampleRate sRate); + static long cAsioMessage(long selector, long value, void* message, double* opt); + static ASIOTime* cBufferSwitchTimeInfo(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess); + void BufferSwitch(long doubleBufferIndex, ASIOBool directProcess); +}; diff --git a/windows/soundmng/sdbase.h b/windows/soundmng/sdbase.h old mode 100755 new mode 100644 index d183aa88..ec5530f4 --- a/windows/soundmng/sdbase.h +++ b/windows/soundmng/sdbase.h @@ -1,178 +1,178 @@ -/** - * @file sdbase.h - * @brief サウンド デバイス基底クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -/** - * @brief サウンド データ取得インタフェイス - */ -class ISoundData -{ -public: - /** - * ストリーム データを得る - * @param[out] lpBuffer バッファ - * @param[in] nBufferCount バッファ カウント - * @return サンプル数 - */ - virtual UINT Get16(SINT16* lpBuffer, UINT nBufferCount) = 0; -}; - -/** - * @brief サウンド デバイス基底クラス - */ -class CSoundDeviceBase -{ -public: - /** - * コンストラクタ - */ - CSoundDeviceBase() - : m_pSoundData(NULL) - { - } - - /** - * デストラクタ - */ - virtual ~CSoundDeviceBase() - { - } - - /** - * ストリーム データの設定 - * @param[in] pSoundData サウンド データ - */ - void SetStreamData(ISoundData* pSoundData) - { - m_pSoundData = pSoundData; - } - - /** - * オープン - * @param[in] lpDevice デバイス名 - * @param[in] hWnd ウィンドウ ハンドル - * @retval true 成功 - * @retval false 失敗 - */ - virtual bool Open(LPCTSTR lpDevice = NULL, HWND hWnd = NULL) = 0; - - /** - * クローズ - */ - virtual void Close() = 0; - - /** - * ストリームの作成 - * @param[in] nSamplingRate サンプリング レート - * @param[in] nChannels チャネル数 - * @param[in] nBufferSize バッファ サイズ - * @return バッファ サイズ - */ - virtual UINT CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize = 0) = 0; - - /** - * ストリームを破棄 - */ - virtual void DestroyStream() = 0; - - /** - * ストリームをリセット - */ - virtual void ResetStream() - { - } - - /** - * ストリームの再生 - * @retval true 成功 - * @retval false 失敗 - */ - virtual bool PlayStream() = 0; - - /** - * ストリームの停止 - */ - virtual void StopStream() = 0; - - /** - * ストリーム ヴォリューム設定 - * @param[in] nVolume ヴォリューム(max 100) - */ - virtual void SetMasterVolume(int nVolume) - { - } - - /** - * PCM データ読み込み - * @param[in] nNum PCM 番号 - * @param[in] lpFilename ファイル名 - * @retval true 成功 - * @retval false 失敗 - */ - virtual bool LoadPCM(UINT nNum, LPCTSTR lpFilename) - { - return false; - } - - /** - * PCM データ再読み込み - * @param[in] nNum PCM 番号 - * @param[in] lpFilename ファイル名 - * @retval true 成功 - * @retval false 失敗 - */ - virtual bool ReloadPCM(UINT nNum) - { - return false; - } - - /** - * PCM をアンロード - * @param[in] nNum PCM 番号 - */ - virtual void UnloadPCM(UINT nNum) - { - } - - /** - * PCM ヴォリューム設定 - * @param[in] nNum PCM 番号 - * @param[in] nVolume ヴォリューム - */ - virtual void SetPCMVolume(UINT nNum, int nVolume) - { - } - - /** - * PCM 再生 - * @param[in] nNum PCM 番号 - * @param[in] bLoop ループ フラグ - * @retval true 成功 - * @retval false 失敗 - */ - virtual bool PlayPCM(UINT nNum, BOOL bLoop) - { - return false; - } - - /** - * PCM 停止 - * @param[in] nNum PCM 番号 - */ - virtual void StopPCM(UINT nNum) - { - } - - /** - * PCM をストップ - */ - virtual void StopAllPCM() - { - } - -protected: - ISoundData* m_pSoundData; /*!< サウンド データ インスタンス */ -}; +/** + * @file sdbase.h + * @brief サウンド デバイス基底クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +/** + * @brief サウンド データ取得インタフェイス + */ +class ISoundData +{ +public: + /** + * ストリーム データを得る + * @param[out] lpBuffer バッファ + * @param[in] nBufferCount バッファ カウント + * @return サンプル数 + */ + virtual UINT Get16(SINT16* lpBuffer, UINT nBufferCount) = 0; +}; + +/** + * @brief サウンド デバイス基底クラス + */ +class CSoundDeviceBase +{ +public: + /** + * コンストラクタ + */ + CSoundDeviceBase() + : m_pSoundData(NULL) + { + } + + /** + * デストラクタ + */ + virtual ~CSoundDeviceBase() + { + } + + /** + * ストリーム データの設定 + * @param[in] pSoundData サウンド データ + */ + void SetStreamData(ISoundData* pSoundData) + { + m_pSoundData = pSoundData; + } + + /** + * オープン + * @param[in] lpDevice デバイス名 + * @param[in] hWnd ウィンドウ ハンドル + * @retval true 成功 + * @retval false 失敗 + */ + virtual bool Open(LPCTSTR lpDevice = NULL, HWND hWnd = NULL) = 0; + + /** + * クローズ + */ + virtual void Close() = 0; + + /** + * ストリームの作成 + * @param[in] nSamplingRate サンプリング レート + * @param[in] nChannels チャネル数 + * @param[in] nBufferSize バッファ サイズ + * @return バッファ サイズ + */ + virtual UINT CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize = 0) = 0; + + /** + * ストリームを破棄 + */ + virtual void DestroyStream() = 0; + + /** + * ストリームをリセット + */ + virtual void ResetStream() + { + } + + /** + * ストリームの再生 + * @retval true 成功 + * @retval false 失敗 + */ + virtual bool PlayStream() = 0; + + /** + * ストリームの停止 + */ + virtual void StopStream() = 0; + + /** + * ストリーム ヴォリューム設定 + * @param[in] nVolume ヴォリューム(max 100) + */ + virtual void SetMasterVolume(int nVolume) + { + } + + /** + * PCM データ読み込み + * @param[in] nNum PCM 番号 + * @param[in] lpFilename ファイル名 + * @retval true 成功 + * @retval false 失敗 + */ + virtual bool LoadPCM(UINT nNum, LPCTSTR lpFilename) + { + return false; + } + + /** + * PCM データ再読み込み + * @param[in] nNum PCM 番号 + * @param[in] lpFilename ファイル名 + * @retval true 成功 + * @retval false 失敗 + */ + virtual bool ReloadPCM(UINT nNum) + { + return false; + } + + /** + * PCM をアンロード + * @param[in] nNum PCM 番号 + */ + virtual void UnloadPCM(UINT nNum) + { + } + + /** + * PCM ヴォリューム設定 + * @param[in] nNum PCM 番号 + * @param[in] nVolume ヴォリューム + */ + virtual void SetPCMVolume(UINT nNum, int nVolume) + { + } + + /** + * PCM 再生 + * @param[in] nNum PCM 番号 + * @param[in] bLoop ループ フラグ + * @retval true 成功 + * @retval false 失敗 + */ + virtual bool PlayPCM(UINT nNum, BOOL bLoop) + { + return false; + } + + /** + * PCM 停止 + * @param[in] nNum PCM 番号 + */ + virtual void StopPCM(UINT nNum) + { + } + + /** + * PCM をストップ + */ + virtual void StopAllPCM() + { + } + +protected: + ISoundData* m_pSoundData; /*!< サウンド データ インスタンス */ +}; diff --git a/windows/soundmng/sddsound3.cpp b/windows/soundmng/sddsound3.cpp index 144bb427..2f244145 100644 --- a/windows/soundmng/sddsound3.cpp +++ b/windows/soundmng/sddsound3.cpp @@ -1,756 +1,756 @@ -/** - * @file sddsound3.cpp - * @brief DSound3 I[fBI NX̓̒`s܂ - */ - -#include -#include "compiler.h" -#include "sddsound3.h" -#include "soundmng.h" -#include "misc\extrom.h" - -#if !defined(__GNUC__) -#pragma comment(lib, "dxguid.lib") -#pragma comment(lib, "dsound.lib") -#endif // !defined(__GNUC__) - -#ifndef DSBVOLUME_MAX -#define DSBVOLUME_MAX 0 /*!< H[ől */ -#endif -#ifndef DSBVOLUME_MIN -#define DSBVOLUME_MIN (-10000) /*!< H[ŏl */ -#endif - -#define NP2VOLUME2DSDB(a) ((LONG)(10*log((a)/100.0f)/log(2.0)*100)) - -//! foCX Xg -std::vector CSoundDeviceDSound3::sm_devices; - -//! }X^{[gp”\H -bool CSoundDeviceDSound3::s_mastervol_available = true; - - -/** - * @brief RIFF chunk - */ -struct RiffChunk -{ - UINT32 riff; /*!< 'RIFF' */ - UINT32 nFileSize; /*!< fileSize */ - UINT32 nFileType; /*!< fileType */ -}; - -/** - * @brief chunk - */ -struct Chunk -{ - UINT32 id; /*!< chunkID */ - UINT32 nSize; /*!< chunkSize */ -}; - -/** - * - */ -void CSoundDeviceDSound3::Initialize() -{ - ::DirectSoundEnumerate(EnumCallback, NULL); -} - -/** - * foCX񋓃R[obN - * @param[in] lpGuid GUID - * @param[in] lpcstrDescription foCX - * @param[in] lpcstrModule W[ - * @param[in] lpContext ReLXg - * @retval TRUE p - */ -BOOL CALLBACK CSoundDeviceDSound3::EnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext) -{ - if (lpGuid != NULL) - { - DSound3Device device; - ZeroMemory(&device, sizeof(device)); - device.guid = *lpGuid; - ::lstrcpyn(device.szDevice, lpcstrDescription, _countof(device.szDevice)); - sm_devices.push_back(device); - } - return TRUE; -} - -/** - * - * @param[out] devices foCX Xg - */ -void CSoundDeviceDSound3::EnumerateDevices(std::vector& devices) -{ - for (std::vector::const_iterator it = sm_devices.begin(); it != sm_devices.end(); ++it) - { - devices.push_back(it->szDevice); - } -} - -/** - * RXgN^ - */ -CSoundDeviceDSound3::CSoundDeviceDSound3() - : m_lpDSound(NULL) - , m_lpDSStream(NULL) - , m_nChannels(0) - , m_nBufferSize(0) - , m_dwHalfBufferSize(0) - , m_mastervolume(100) -{ - ZeroMemory(m_hEvents, sizeof(m_hEvents)); - ZeroMemory(m_pcmvolume, sizeof(m_pcmvolume)); -} - -/** - * fXgN^ - */ -CSoundDeviceDSound3::~CSoundDeviceDSound3() -{ - Close(); -} - -/** - * I[v - * @param[in] lpDevice foCX - * @param[in] hWnd EBhE nh - * @retval true - * @retval false s - */ -bool CSoundDeviceDSound3::Open(LPCTSTR lpDevice, HWND hWnd) -{ - if (hWnd == NULL) - { - return false; - } - - LPGUID lpGuid = NULL; - if ((lpDevice) && (lpDevice[0] != '\0')) - { - std::vector::const_iterator it = sm_devices.begin(); - while ((it != sm_devices.end()) && (::lstrcmpi(lpDevice, it->szDevice) != 0)) - { - ++it; - } - if (it == sm_devices.end()) - { - return false; - } - lpGuid = const_cast(&it->guid); - } - - // DirectSound̏ - LPDIRECTSOUND lpDSound; - if (FAILED(DirectSoundCreate(lpGuid, &lpDSound, 0))) - { - return false; - } - if (FAILED(lpDSound->SetCooperativeLevel(hWnd, DSSCL_PRIORITY))) - { - if (FAILED(lpDSound->SetCooperativeLevel(hWnd, DSSCL_NORMAL))) - { - lpDSound->Release(); - return false; - } - } - - m_lpDSound = lpDSound; - return true; -} - -/** - * N[Y - */ -void CSoundDeviceDSound3::Close() -{ - DestroyAllPCM(); - DestroyStream(); - - if (m_lpDSound) - { - m_lpDSound->Release(); - m_lpDSound = NULL; - } -} - -/** - * Xg[̍쐬 - * @param[in] nSamplingRate TvO [g - * @param[in] nChannels `l - * @param[in] nBufferSize obt@ TCY - * @return obt@ TCY - */ -UINT CSoundDeviceDSound3::CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize) -{ - if (m_lpDSound == NULL) - { - return 0; - } - - if (nBufferSize == 0) - { - nBufferSize = nSamplingRate / 10; - } - - m_nChannels = nChannels; - m_nBufferSize = nBufferSize; - m_dwHalfBufferSize = nBufferSize * nChannels * sizeof(short); - - PCMWAVEFORMAT pcmwf; - ZeroMemory(&pcmwf, sizeof(pcmwf)); - pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM; - pcmwf.wf.nChannels = nChannels; - pcmwf.wf.nSamplesPerSec = nSamplingRate; - pcmwf.wBitsPerSample = 16; - pcmwf.wf.nBlockAlign = nChannels * (pcmwf.wBitsPerSample / 8); - pcmwf.wf.nAvgBytesPerSec = nSamplingRate * pcmwf.wf.nBlockAlign; - - DSBUFFERDESC dsbdesc; - ZeroMemory(&dsbdesc, sizeof(dsbdesc)); - dsbdesc.dwSize = sizeof(dsbdesc); - dsbdesc.dwFlags = DSBCAPS_CTRLPAN /*| (s_mastervol_available ? DSBCAPS_CTRLVOLUME : 0)*/ | - DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPOSITIONNOTIFY | - DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; - dsbdesc.lpwfxFormat = reinterpret_cast(&pcmwf); - dsbdesc.dwBufferBytes = m_dwHalfBufferSize * 2; - HRESULT hr = m_lpDSound->CreateSoundBuffer(&dsbdesc, &m_lpDSStream, NULL); - if (FAILED(hr)) - { - dsbdesc.dwSize = (sizeof(DWORD) * 4) + sizeof(LPWAVEFORMATEX); - hr = m_lpDSound->CreateSoundBuffer(&dsbdesc, &m_lpDSStream, NULL); - } - if (FAILED(hr)) - { - DestroyStream(); - return 0; - } - - LPDIRECTSOUNDNOTIFY pNotify; - if (FAILED(m_lpDSStream->QueryInterface(IID_IDirectSoundNotify, reinterpret_cast(&pNotify)))) - { - DestroyStream(); - return 0; - } - - for (UINT i = 0; i < _countof(m_hEvents); i++) - { - m_hEvents[i] = ::CreateEvent(NULL, FALSE, FALSE, NULL); - } - - DSBPOSITIONNOTIFY pos[2]; - ZeroMemory(pos, sizeof(pos)); - for (UINT i = 0; i < _countof(pos); i++) - { - pos[i].dwOffset = m_dwHalfBufferSize * i; - pos[i].hEventNotify = m_hEvents[0]; - } - pNotify->SetNotificationPositions(_countof(pos), pos); - pNotify->Release(); - - SetMasterVolume(m_mastervolume); - - ResetStream(); - CThreadBase::Start(); - return nBufferSize; -} - -/** - * Xg[j - */ -void CSoundDeviceDSound3::DestroyStream() -{ - if (m_hEvents[1]) - { - ::SetEvent(m_hEvents[1]); - } - CThreadBase::Stop(); - - if (m_lpDSStream) - { - m_lpDSStream->Stop(); - m_lpDSStream->Release(); - m_lpDSStream = NULL; - } - - m_nChannels = 0; - m_nBufferSize = 0; - m_dwHalfBufferSize = 0; - for (UINT i = 0; i < _countof(m_hEvents); i++) - { - if (m_hEvents[i]) - { - ::CloseHandle(m_hEvents[i]); - m_hEvents[i] = NULL; - } - } -} - -/** - * Xg[Zbg - */ -void CSoundDeviceDSound3::ResetStream() -{ - if (m_lpDSStream) - { - LPVOID lpBlock1; - DWORD cbBlock1; - LPVOID lpBlock2; - DWORD cbBlock2; - if (SUCCEEDED(m_lpDSStream->Lock(0, m_dwHalfBufferSize * 2, &lpBlock1, &cbBlock1, &lpBlock2, &cbBlock2, 0))) - { - ZeroMemory(lpBlock1, cbBlock1); - if ((lpBlock2) && (cbBlock2)) - { - ZeroMemory(lpBlock2, cbBlock2); - } - m_lpDSStream->Unlock(lpBlock1, cbBlock1, lpBlock2, cbBlock2); - m_lpDSStream->SetCurrentPosition(0); - } - } -} - -/** - * Xg[̍Đ - * @retval true - * @retval false s - */ -bool CSoundDeviceDSound3::PlayStream() -{ - if (m_lpDSStream) - { - m_lpDSStream->Play(0, 0, DSBPLAY_LOOPING); - return true; - } - else - { - return false; - } -} - -/** - * Xg[̒~ - */ -void CSoundDeviceDSound3::StopStream() -{ - if (m_lpDSStream) - { - m_lpDSStream->Stop(); - } -} - -/** - * Xg[ H[ݒ - * @param[in] nVolume H[(max 100) - */ -void CSoundDeviceDSound3::SetMasterVolume(int nVolume) -{ - - m_mastervolume = nVolume; - if(s_mastervol_available){ - int numlen = m_pcm.size(); - UINT *nums = new UINT[numlen]; - int i = 0; - for( auto it = m_pcm.begin(); it != m_pcm.end() ; ++it ) { - nums[i] = it->first; - i++; - } - for(i=0; iGetCurrentPosition(&dwCurrentPlayCursor, &dwCurrentWriteCursor))) - { - const DWORD dwPos = (dwCurrentPlayCursor >= m_dwHalfBufferSize) ? 0 : m_dwHalfBufferSize; - FillStream(dwPos); - } - } - break; - - case WAIT_OBJECT_0 + 1: - return false; - - default: - break; - } - return true; -} - -/** - * Xg[XV - * @param[in] dwPosition XVʒu - */ -void CSoundDeviceDSound3::FillStream(DWORD dwPosition) -{ - LPVOID lpBlock1; - DWORD cbBlock1; - LPVOID lpBlock2; - DWORD cbBlock2; - HRESULT hr = m_lpDSStream->Lock(dwPosition, m_dwHalfBufferSize, &lpBlock1, &cbBlock1, &lpBlock2, &cbBlock2, 0); - if (hr == DSERR_BUFFERLOST) - { - m_lpDSStream->Restore(); - hr = m_lpDSStream->Lock(dwPosition, m_dwHalfBufferSize, &lpBlock1, &cbBlock1, &lpBlock2, &cbBlock2, 0); - } - if (SUCCEEDED(hr)) - { - UINT nStreamLength = 0; - if (m_pSoundData) - { - nStreamLength = m_pSoundData->Get16(static_cast(lpBlock1), m_nBufferSize); - } - if (nStreamLength != m_nBufferSize) - { - ZeroMemory(static_cast(lpBlock1) + nStreamLength * m_nChannels, (m_nBufferSize - nStreamLength) * m_nChannels * sizeof(short)); - } - m_lpDSStream->Unlock(lpBlock1, cbBlock1, lpBlock2, cbBlock2); - } -} - -/** - * PCM obt@j - */ -void CSoundDeviceDSound3::DestroyAllPCM() -{ - for (std::map::iterator it = m_pcm.begin(); it != m_pcm.begin(); ++it) - { - LPDIRECTSOUNDBUFFER lpDSBuffer = it->second; - lpDSBuffer->Stop(); - lpDSBuffer->Release(); - } - m_pcm.clear(); - for (std::map::iterator it = m_pcmfile.begin(); it != m_pcmfile.begin(); ++it) - { - TCHAR* lpFilename = it->second; - delete[] lpFilename; - } - m_pcmfile.clear(); -} - -/** - * PCM Xgbv - */ -void CSoundDeviceDSound3::StopAllPCM() -{ - for (std::map::iterator it = m_pcm.begin(); it != m_pcm.begin(); ++it) - { - LPDIRECTSOUNDBUFFER lpDSBuffer = it->second; - lpDSBuffer->Stop(); - } -} - -/** - * PCM f[^ǂݍ - * @param[in] nNum PCM ԍ - * @param[in] lpFilename t@C - * @retval true - * @retval false s - */ -bool CSoundDeviceDSound3::LoadPCM(UINT nNum, LPCTSTR lpFilename) -{ - UnloadPCM(nNum); - - int nVolume = 100; - if(nNum < PCMVOLUME_MAXCOUNT){ - nVolume = m_pcmvolume[nNum]; - } - nVolume = nVolume * m_mastervolume / 100; - LPDIRECTSOUNDBUFFER lpDSBuffer = CreateWaveBuffer(lpFilename, nVolume); - if (lpDSBuffer) - { - m_pcm[nNum] = lpDSBuffer; - if(m_pcmfile.find(nNum)==m_pcmfile.end()){ - // VK쐬 - TCHAR *filename = new TCHAR[OEMSTRLEN(lpFilename)+1]; - _tcscpy(filename, lpFilename); - m_pcmfile[nNum] = filename; - }else{ - // XV - _tcscpy(m_pcmfile[nNum], lpFilename); - } - return true; - } - else - { - return false; - } -} - -/** - * PCM f[^ēǂݍ - * @param[in] nNum PCM ԍ - * @param[in] lpFilename t@C - * @retval true - * @retval false s - */ -bool CSoundDeviceDSound3::ReloadPCM(UINT nNum) -{ - if(m_pcm.find(nNum) == m_pcm.end()) return false; // ݂ĂȂ - - UnloadPCM(nNum); - - int nVolume = 100; - if(nNum < PCMVOLUME_MAXCOUNT){ - nVolume = m_pcmvolume[nNum]; - } - nVolume = nVolume * m_mastervolume / 100; - LPDIRECTSOUNDBUFFER lpDSBuffer = CreateWaveBuffer(m_pcmfile[nNum], nVolume); - if (lpDSBuffer) - { - m_pcm[nNum] = lpDSBuffer; - return true; - } - else - { - return false; - } -} - -/** - * PCM f[^ǂݍ - * @param[in] lpFilename t@C - * @return obt@ - */ -LPDIRECTSOUNDBUFFER CSoundDeviceDSound3::CreateWaveBuffer(LPCTSTR lpFilename, int volume100) -{ - LPDIRECTSOUNDBUFFER lpDSBuffer = NULL; - CExtRom extrom; - - do - { - if (!extrom.Open(lpFilename, 3)) - { - break; - } - - RiffChunk riff; - if (extrom.Read(&riff, sizeof(riff)) != sizeof(riff)) - { - break; - } - if ((riff.riff != MAKEFOURCC('R','I','F','F')) || (riff.nFileType != MAKEFOURCC('W','A','V','E'))) - { - break; - } - - bool bValid = false; - Chunk chunk; - PCMWAVEFORMAT pcmwf = {0}; - while (true /*CONSTCOND*/) - { - if (extrom.Read(&chunk, sizeof(chunk)) != sizeof(chunk)) - { - bValid = false; - break; - } - if (chunk.id == MAKEFOURCC('f','m','t',' ')) - { - if (chunk.nSize >= sizeof(pcmwf)) - { - if (extrom.Read(&pcmwf, sizeof(pcmwf)) != sizeof(pcmwf)) - { - bValid = false; - break; - } - chunk.nSize -= sizeof(pcmwf); - bValid = true; - } - } - else if (chunk.id == MAKEFOURCC('d','a','t','a')) - { - break; - } - if (chunk.nSize) - { - extrom.Seek(chunk.nSize, FILE_CURRENT); - } - } - if (!bValid) - { - break; - } - - if (pcmwf.wf.wFormatTag != WAVE_FORMAT_PCM) - { - break; - } - - DSBUFFERDESC dsbdesc; - ZeroMemory(&dsbdesc, sizeof(dsbdesc)); - dsbdesc.dwSize = sizeof(dsbdesc); - dsbdesc.dwFlags = DSBCAPS_CTRLPAN /*| (s_mastervol_available ? DSBCAPS_CTRLVOLUME : 0) */| DSBCAPS_CTRLFREQUENCY | DSBCAPS_STATIC | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; - dsbdesc.dwBufferBytes = chunk.nSize; - dsbdesc.lpwfxFormat = reinterpret_cast(&pcmwf); - - HRESULT hr = m_lpDSound->CreateSoundBuffer(&dsbdesc, &lpDSBuffer, NULL); - if (FAILED(hr)) - { - dsbdesc.dwSize = (sizeof(DWORD) * 4) + sizeof(LPWAVEFORMATEX); - hr = m_lpDSound->CreateSoundBuffer(&dsbdesc, &lpDSBuffer, NULL); - } - if (FAILED(hr)) - { - break; - } - - LPVOID lpBlock1; - DWORD cbBlock1; - LPVOID lpBlock2; - DWORD cbBlock2; - hr = lpDSBuffer->Lock(0, chunk.nSize, &lpBlock1, &cbBlock1, &lpBlock2, &cbBlock2, 0); - if (hr == DSERR_BUFFERLOST) - { - lpDSBuffer->Restore(); - hr = lpDSBuffer->Lock(0, chunk.nSize, &lpBlock1, &cbBlock1, &lpBlock2, &cbBlock2, 0); - } - if (FAILED(hr)) - { - lpDSBuffer->Release(); - lpDSBuffer = NULL; - break; - } - - if(pcmwf.wBitsPerSample==8) - { - unsigned char *buf = new unsigned char[cbBlock1]; - extrom.Read(buf, cbBlock1); - for(DWORD i=0;iUnlock(lpBlock1, cbBlock1, lpBlock2, cbBlock2); - } while (0 /*CONSTCOND*/); - - return lpDSBuffer; -} - -/** - * PCM A[h - * @param[in] nNum PCM ԍ - */ -void CSoundDeviceDSound3::UnloadPCM(UINT nNum) -{ - std::map::iterator it = m_pcm.find(nNum); - if (it != m_pcm.end()) - { - LPDIRECTSOUNDBUFFER lpDSBuffer = it->second; - m_pcm.erase(it); - - lpDSBuffer->Stop(); - lpDSBuffer->Release(); - } -} - -/** - * PCM H[ݒ - * @param[in] nNum PCM ԍ - * @param[in] nVolume H[ - */ -void CSoundDeviceDSound3::SetPCMVolume(UINT nNum, int nVolume) -{ - if(s_mastervol_available){ - int volume = nVolume; - if(nNum < PCMVOLUME_MAXCOUNT){ - m_pcmvolume[nNum] = nVolume; - } - ReloadPCM(nNum); - } -} - -/** - * PCM Đ - * @param[in] nNum PCM ԍ - * @param[in] bLoop [v tO - * @retval true - * @retval false s - */ -bool CSoundDeviceDSound3::PlayPCM(UINT nNum, BOOL bLoop) -{ - std::map::iterator it = m_pcm.find(nNum); - if (it != m_pcm.end()) - { - LPDIRECTSOUNDBUFFER lpDSBuffer = it->second; -// lpDSBuffer->SetCurrentPosition(0); - lpDSBuffer->Play(0, 0, (bLoop) ? DSBPLAY_LOOPING : 0); - return true; - } - return false; -} - -/** - * PCM ~ - * @param[in] nNum PCM ԍ - */ -void CSoundDeviceDSound3::StopPCM(UINT nNum) -{ - std::map::iterator it = m_pcm.find(nNum); - if (it != m_pcm.end()) - { - LPDIRECTSOUNDBUFFER lpDSBuffer = it->second; - lpDSBuffer->Stop(); - } -} +/** + * @file sddsound3.cpp + * @brief DSound3 オーディオ クラスの動作の定義を行います + */ + +#include +#include "compiler.h" +#include "sddsound3.h" +#include "soundmng.h" +#include "misc\extrom.h" + +#if !defined(__GNUC__) +#pragma comment(lib, "dxguid.lib") +#pragma comment(lib, "dsound.lib") +#endif // !defined(__GNUC__) + +#ifndef DSBVOLUME_MAX +#define DSBVOLUME_MAX 0 /*!< ヴォリューム最大値 */ +#endif +#ifndef DSBVOLUME_MIN +#define DSBVOLUME_MIN (-10000) /*!< ヴォリューム最小値 */ +#endif + +#define NP2VOLUME2DSDB(a) ((LONG)(10*log((a)/100.0f)/log(2.0)*100)) + +//! デバイス リスト +std::vector CSoundDeviceDSound3::sm_devices; + +//! マスタボリューム使用可能? +bool CSoundDeviceDSound3::s_mastervol_available = true; + + +/** + * @brief RIFF chunk + */ +struct RiffChunk +{ + UINT32 riff; /*!< 'RIFF' */ + UINT32 nFileSize; /*!< fileSize */ + UINT32 nFileType; /*!< fileType */ +}; + +/** + * @brief chunk + */ +struct Chunk +{ + UINT32 id; /*!< chunkID */ + UINT32 nSize; /*!< chunkSize */ +}; + +/** + * 初期化 + */ +void CSoundDeviceDSound3::Initialize() +{ + ::DirectSoundEnumerate(EnumCallback, NULL); +} + +/** + * デバイス列挙コールバック + * @param[in] lpGuid GUID + * @param[in] lpcstrDescription デバイス名 + * @param[in] lpcstrModule モジュール名 + * @param[in] lpContext コンテキスト + * @retval TRUE 継続 + */ +BOOL CALLBACK CSoundDeviceDSound3::EnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext) +{ + if (lpGuid != NULL) + { + DSound3Device device; + ZeroMemory(&device, sizeof(device)); + device.guid = *lpGuid; + ::lstrcpyn(device.szDevice, lpcstrDescription, _countof(device.szDevice)); + sm_devices.push_back(device); + } + return TRUE; +} + +/** + * 列挙 + * @param[out] devices デバイス リスト + */ +void CSoundDeviceDSound3::EnumerateDevices(std::vector& devices) +{ + for (std::vector::const_iterator it = sm_devices.begin(); it != sm_devices.end(); ++it) + { + devices.push_back(it->szDevice); + } +} + +/** + * コンストラクタ + */ +CSoundDeviceDSound3::CSoundDeviceDSound3() + : m_lpDSound(NULL) + , m_lpDSStream(NULL) + , m_nChannels(0) + , m_nBufferSize(0) + , m_dwHalfBufferSize(0) + , m_mastervolume(100) +{ + ZeroMemory(m_hEvents, sizeof(m_hEvents)); + ZeroMemory(m_pcmvolume, sizeof(m_pcmvolume)); +} + +/** + * デストラクタ + */ +CSoundDeviceDSound3::~CSoundDeviceDSound3() +{ + Close(); +} + +/** + * オープン + * @param[in] lpDevice デバイス名 + * @param[in] hWnd ウィンドウ ハンドル + * @retval true 成功 + * @retval false 失敗 + */ +bool CSoundDeviceDSound3::Open(LPCTSTR lpDevice, HWND hWnd) +{ + if (hWnd == NULL) + { + return false; + } + + LPGUID lpGuid = NULL; + if ((lpDevice) && (lpDevice[0] != '\0')) + { + std::vector::const_iterator it = sm_devices.begin(); + while ((it != sm_devices.end()) && (::lstrcmpi(lpDevice, it->szDevice) != 0)) + { + ++it; + } + if (it == sm_devices.end()) + { + return false; + } + lpGuid = const_cast(&it->guid); + } + + // DirectSoundの初期化 + LPDIRECTSOUND lpDSound; + if (FAILED(DirectSoundCreate(lpGuid, &lpDSound, 0))) + { + return false; + } + if (FAILED(lpDSound->SetCooperativeLevel(hWnd, DSSCL_PRIORITY))) + { + if (FAILED(lpDSound->SetCooperativeLevel(hWnd, DSSCL_NORMAL))) + { + lpDSound->Release(); + return false; + } + } + + m_lpDSound = lpDSound; + return true; +} + +/** + * クローズ + */ +void CSoundDeviceDSound3::Close() +{ + DestroyAllPCM(); + DestroyStream(); + + if (m_lpDSound) + { + m_lpDSound->Release(); + m_lpDSound = NULL; + } +} + +/** + * ストリームの作成 + * @param[in] nSamplingRate サンプリング レート + * @param[in] nChannels チャネル数 + * @param[in] nBufferSize バッファ サイズ + * @return バッファ サイズ + */ +UINT CSoundDeviceDSound3::CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize) +{ + if (m_lpDSound == NULL) + { + return 0; + } + + if (nBufferSize == 0) + { + nBufferSize = nSamplingRate / 10; + } + + m_nChannels = nChannels; + m_nBufferSize = nBufferSize; + m_dwHalfBufferSize = nBufferSize * nChannels * sizeof(short); + + PCMWAVEFORMAT pcmwf; + ZeroMemory(&pcmwf, sizeof(pcmwf)); + pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM; + pcmwf.wf.nChannels = nChannels; + pcmwf.wf.nSamplesPerSec = nSamplingRate; + pcmwf.wBitsPerSample = 16; + pcmwf.wf.nBlockAlign = nChannels * (pcmwf.wBitsPerSample / 8); + pcmwf.wf.nAvgBytesPerSec = nSamplingRate * pcmwf.wf.nBlockAlign; + + DSBUFFERDESC dsbdesc; + ZeroMemory(&dsbdesc, sizeof(dsbdesc)); + dsbdesc.dwSize = sizeof(dsbdesc); + dsbdesc.dwFlags = DSBCAPS_CTRLPAN /*| (s_mastervol_available ? DSBCAPS_CTRLVOLUME : 0)*/ | + DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; + dsbdesc.lpwfxFormat = reinterpret_cast(&pcmwf); + dsbdesc.dwBufferBytes = m_dwHalfBufferSize * 2; + HRESULT hr = m_lpDSound->CreateSoundBuffer(&dsbdesc, &m_lpDSStream, NULL); + if (FAILED(hr)) + { + dsbdesc.dwSize = (sizeof(DWORD) * 4) + sizeof(LPWAVEFORMATEX); + hr = m_lpDSound->CreateSoundBuffer(&dsbdesc, &m_lpDSStream, NULL); + } + if (FAILED(hr)) + { + DestroyStream(); + return 0; + } + + LPDIRECTSOUNDNOTIFY pNotify; + if (FAILED(m_lpDSStream->QueryInterface(IID_IDirectSoundNotify, reinterpret_cast(&pNotify)))) + { + DestroyStream(); + return 0; + } + + for (UINT i = 0; i < _countof(m_hEvents); i++) + { + m_hEvents[i] = ::CreateEvent(NULL, FALSE, FALSE, NULL); + } + + DSBPOSITIONNOTIFY pos[2]; + ZeroMemory(pos, sizeof(pos)); + for (UINT i = 0; i < _countof(pos); i++) + { + pos[i].dwOffset = m_dwHalfBufferSize * i; + pos[i].hEventNotify = m_hEvents[0]; + } + pNotify->SetNotificationPositions(_countof(pos), pos); + pNotify->Release(); + + SetMasterVolume(m_mastervolume); + + ResetStream(); + CThreadBase::Start(); + return nBufferSize; +} + +/** + * ストリームを破棄 + */ +void CSoundDeviceDSound3::DestroyStream() +{ + if (m_hEvents[1]) + { + ::SetEvent(m_hEvents[1]); + } + CThreadBase::Stop(); + + if (m_lpDSStream) + { + m_lpDSStream->Stop(); + m_lpDSStream->Release(); + m_lpDSStream = NULL; + } + + m_nChannels = 0; + m_nBufferSize = 0; + m_dwHalfBufferSize = 0; + for (UINT i = 0; i < _countof(m_hEvents); i++) + { + if (m_hEvents[i]) + { + ::CloseHandle(m_hEvents[i]); + m_hEvents[i] = NULL; + } + } +} + +/** + * ストリームをリセット + */ +void CSoundDeviceDSound3::ResetStream() +{ + if (m_lpDSStream) + { + LPVOID lpBlock1; + DWORD cbBlock1; + LPVOID lpBlock2; + DWORD cbBlock2; + if (SUCCEEDED(m_lpDSStream->Lock(0, m_dwHalfBufferSize * 2, &lpBlock1, &cbBlock1, &lpBlock2, &cbBlock2, 0))) + { + ZeroMemory(lpBlock1, cbBlock1); + if ((lpBlock2) && (cbBlock2)) + { + ZeroMemory(lpBlock2, cbBlock2); + } + m_lpDSStream->Unlock(lpBlock1, cbBlock1, lpBlock2, cbBlock2); + m_lpDSStream->SetCurrentPosition(0); + } + } +} + +/** + * ストリームの再生 + * @retval true 成功 + * @retval false 失敗 + */ +bool CSoundDeviceDSound3::PlayStream() +{ + if (m_lpDSStream) + { + m_lpDSStream->Play(0, 0, DSBPLAY_LOOPING); + return true; + } + else + { + return false; + } +} + +/** + * ストリームの停止 + */ +void CSoundDeviceDSound3::StopStream() +{ + if (m_lpDSStream) + { + m_lpDSStream->Stop(); + } +} + +/** + * ストリーム ヴォリューム設定 + * @param[in] nVolume ヴォリューム(max 100) + */ +void CSoundDeviceDSound3::SetMasterVolume(int nVolume) +{ + + m_mastervolume = nVolume; + if(s_mastervol_available){ + int numlen = m_pcm.size(); + UINT *nums = new UINT[numlen]; + int i = 0; + for( auto it = m_pcm.begin(); it != m_pcm.end() ; ++it ) { + nums[i] = it->first; + i++; + } + for(i=0; iGetCurrentPosition(&dwCurrentPlayCursor, &dwCurrentWriteCursor))) + { + const DWORD dwPos = (dwCurrentPlayCursor >= m_dwHalfBufferSize) ? 0 : m_dwHalfBufferSize; + FillStream(dwPos); + } + } + break; + + case WAIT_OBJECT_0 + 1: + return false; + + default: + break; + } + return true; +} + +/** + * ストリームを更新する + * @param[in] dwPosition 更新位置 + */ +void CSoundDeviceDSound3::FillStream(DWORD dwPosition) +{ + LPVOID lpBlock1; + DWORD cbBlock1; + LPVOID lpBlock2; + DWORD cbBlock2; + HRESULT hr = m_lpDSStream->Lock(dwPosition, m_dwHalfBufferSize, &lpBlock1, &cbBlock1, &lpBlock2, &cbBlock2, 0); + if (hr == DSERR_BUFFERLOST) + { + m_lpDSStream->Restore(); + hr = m_lpDSStream->Lock(dwPosition, m_dwHalfBufferSize, &lpBlock1, &cbBlock1, &lpBlock2, &cbBlock2, 0); + } + if (SUCCEEDED(hr)) + { + UINT nStreamLength = 0; + if (m_pSoundData) + { + nStreamLength = m_pSoundData->Get16(static_cast(lpBlock1), m_nBufferSize); + } + if (nStreamLength != m_nBufferSize) + { + ZeroMemory(static_cast(lpBlock1) + nStreamLength * m_nChannels, (m_nBufferSize - nStreamLength) * m_nChannels * sizeof(short)); + } + m_lpDSStream->Unlock(lpBlock1, cbBlock1, lpBlock2, cbBlock2); + } +} + +/** + * PCM バッファを破棄する + */ +void CSoundDeviceDSound3::DestroyAllPCM() +{ + for (std::map::iterator it = m_pcm.begin(); it != m_pcm.begin(); ++it) + { + LPDIRECTSOUNDBUFFER lpDSBuffer = it->second; + lpDSBuffer->Stop(); + lpDSBuffer->Release(); + } + m_pcm.clear(); + for (std::map::iterator it = m_pcmfile.begin(); it != m_pcmfile.begin(); ++it) + { + TCHAR* lpFilename = it->second; + delete[] lpFilename; + } + m_pcmfile.clear(); +} + +/** + * PCM をストップ + */ +void CSoundDeviceDSound3::StopAllPCM() +{ + for (std::map::iterator it = m_pcm.begin(); it != m_pcm.begin(); ++it) + { + LPDIRECTSOUNDBUFFER lpDSBuffer = it->second; + lpDSBuffer->Stop(); + } +} + +/** + * PCM データ読み込み + * @param[in] nNum PCM 番号 + * @param[in] lpFilename ファイル名 + * @retval true 成功 + * @retval false 失敗 + */ +bool CSoundDeviceDSound3::LoadPCM(UINT nNum, LPCTSTR lpFilename) +{ + UnloadPCM(nNum); + + int nVolume = 100; + if(nNum < PCMVOLUME_MAXCOUNT){ + nVolume = m_pcmvolume[nNum]; + } + nVolume = nVolume * m_mastervolume / 100; + LPDIRECTSOUNDBUFFER lpDSBuffer = CreateWaveBuffer(lpFilename, nVolume); + if (lpDSBuffer) + { + m_pcm[nNum] = lpDSBuffer; + if(m_pcmfile.find(nNum)==m_pcmfile.end()){ + // 新規作成 + TCHAR *filename = new TCHAR[OEMSTRLEN(lpFilename)+1]; + _tcscpy(filename, lpFilename); + m_pcmfile[nNum] = filename; + }else{ + // 更新 + _tcscpy(m_pcmfile[nNum], lpFilename); + } + return true; + } + else + { + return false; + } +} + +/** + * PCM データ再読み込み + * @param[in] nNum PCM 番号 + * @param[in] lpFilename ファイル名 + * @retval true 成功 + * @retval false 失敗 + */ +bool CSoundDeviceDSound3::ReloadPCM(UINT nNum) +{ + if(m_pcm.find(nNum) == m_pcm.end()) return false; // 存在していない + + UnloadPCM(nNum); + + int nVolume = 100; + if(nNum < PCMVOLUME_MAXCOUNT){ + nVolume = m_pcmvolume[nNum]; + } + nVolume = nVolume * m_mastervolume / 100; + LPDIRECTSOUNDBUFFER lpDSBuffer = CreateWaveBuffer(m_pcmfile[nNum], nVolume); + if (lpDSBuffer) + { + m_pcm[nNum] = lpDSBuffer; + return true; + } + else + { + return false; + } +} + +/** + * PCM データ読み込み + * @param[in] lpFilename ファイル名 + * @return バッファ + */ +LPDIRECTSOUNDBUFFER CSoundDeviceDSound3::CreateWaveBuffer(LPCTSTR lpFilename, int volume100) +{ + LPDIRECTSOUNDBUFFER lpDSBuffer = NULL; + CExtRom extrom; + + do + { + if (!extrom.Open(lpFilename, 3)) + { + break; + } + + RiffChunk riff; + if (extrom.Read(&riff, sizeof(riff)) != sizeof(riff)) + { + break; + } + if ((riff.riff != MAKEFOURCC('R','I','F','F')) || (riff.nFileType != MAKEFOURCC('W','A','V','E'))) + { + break; + } + + bool bValid = false; + Chunk chunk; + PCMWAVEFORMAT pcmwf = {0}; + while (true /*CONSTCOND*/) + { + if (extrom.Read(&chunk, sizeof(chunk)) != sizeof(chunk)) + { + bValid = false; + break; + } + if (chunk.id == MAKEFOURCC('f','m','t',' ')) + { + if (chunk.nSize >= sizeof(pcmwf)) + { + if (extrom.Read(&pcmwf, sizeof(pcmwf)) != sizeof(pcmwf)) + { + bValid = false; + break; + } + chunk.nSize -= sizeof(pcmwf); + bValid = true; + } + } + else if (chunk.id == MAKEFOURCC('d','a','t','a')) + { + break; + } + if (chunk.nSize) + { + extrom.Seek(chunk.nSize, FILE_CURRENT); + } + } + if (!bValid) + { + break; + } + + if (pcmwf.wf.wFormatTag != WAVE_FORMAT_PCM) + { + break; + } + + DSBUFFERDESC dsbdesc; + ZeroMemory(&dsbdesc, sizeof(dsbdesc)); + dsbdesc.dwSize = sizeof(dsbdesc); + dsbdesc.dwFlags = DSBCAPS_CTRLPAN /*| (s_mastervol_available ? DSBCAPS_CTRLVOLUME : 0) */| DSBCAPS_CTRLFREQUENCY | DSBCAPS_STATIC | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; + dsbdesc.dwBufferBytes = chunk.nSize; + dsbdesc.lpwfxFormat = reinterpret_cast(&pcmwf); + + HRESULT hr = m_lpDSound->CreateSoundBuffer(&dsbdesc, &lpDSBuffer, NULL); + if (FAILED(hr)) + { + dsbdesc.dwSize = (sizeof(DWORD) * 4) + sizeof(LPWAVEFORMATEX); + hr = m_lpDSound->CreateSoundBuffer(&dsbdesc, &lpDSBuffer, NULL); + } + if (FAILED(hr)) + { + break; + } + + LPVOID lpBlock1; + DWORD cbBlock1; + LPVOID lpBlock2; + DWORD cbBlock2; + hr = lpDSBuffer->Lock(0, chunk.nSize, &lpBlock1, &cbBlock1, &lpBlock2, &cbBlock2, 0); + if (hr == DSERR_BUFFERLOST) + { + lpDSBuffer->Restore(); + hr = lpDSBuffer->Lock(0, chunk.nSize, &lpBlock1, &cbBlock1, &lpBlock2, &cbBlock2, 0); + } + if (FAILED(hr)) + { + lpDSBuffer->Release(); + lpDSBuffer = NULL; + break; + } + + if(pcmwf.wBitsPerSample==8) + { + unsigned char *buf = new unsigned char[cbBlock1]; + extrom.Read(buf, cbBlock1); + for(DWORD i=0;iUnlock(lpBlock1, cbBlock1, lpBlock2, cbBlock2); + } while (0 /*CONSTCOND*/); + + return lpDSBuffer; +} + +/** + * PCM をアンロード + * @param[in] nNum PCM 番号 + */ +void CSoundDeviceDSound3::UnloadPCM(UINT nNum) +{ + std::map::iterator it = m_pcm.find(nNum); + if (it != m_pcm.end()) + { + LPDIRECTSOUNDBUFFER lpDSBuffer = it->second; + m_pcm.erase(it); + + lpDSBuffer->Stop(); + lpDSBuffer->Release(); + } +} + +/** + * PCM ヴォリューム設定 + * @param[in] nNum PCM 番号 + * @param[in] nVolume ヴォリューム + */ +void CSoundDeviceDSound3::SetPCMVolume(UINT nNum, int nVolume) +{ + if(s_mastervol_available){ + int volume = nVolume; + if(nNum < PCMVOLUME_MAXCOUNT){ + m_pcmvolume[nNum] = nVolume; + } + ReloadPCM(nNum); + } +} + +/** + * PCM 再生 + * @param[in] nNum PCM 番号 + * @param[in] bLoop ループ フラグ + * @retval true 成功 + * @retval false 失敗 + */ +bool CSoundDeviceDSound3::PlayPCM(UINT nNum, BOOL bLoop) +{ + std::map::iterator it = m_pcm.find(nNum); + if (it != m_pcm.end()) + { + LPDIRECTSOUNDBUFFER lpDSBuffer = it->second; +// lpDSBuffer->SetCurrentPosition(0); + lpDSBuffer->Play(0, 0, (bLoop) ? DSBPLAY_LOOPING : 0); + return true; + } + return false; +} + +/** + * PCM 停止 + * @param[in] nNum PCM 番号 + */ +void CSoundDeviceDSound3::StopPCM(UINT nNum) +{ + std::map::iterator it = m_pcm.find(nNum); + if (it != m_pcm.end()) + { + LPDIRECTSOUNDBUFFER lpDSBuffer = it->second; + lpDSBuffer->Stop(); + } +} diff --git a/windows/soundmng/sddsound3.h b/windows/soundmng/sddsound3.h old mode 100755 new mode 100644 index 3d5806c4..cbf7a0f1 --- a/windows/soundmng/sddsound3.h +++ b/windows/soundmng/sddsound3.h @@ -1,75 +1,75 @@ -/** - * @file sddsound3.h - * @brief DSound3 オーディオ クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include -#include -#include "sdbase.h" -#include "misc\threadbase.h" - -#define PCMVOLUME_MAXCOUNT 64 - -/** - * @brief デバイス - */ -struct DSound3Device -{ - GUID guid; //!< GUID - TCHAR szDevice[MAX_PATH]; //!< デバイス -}; - -/** - * @brief Direct Sound3 クラス - */ -class CSoundDeviceDSound3 : public CSoundDeviceBase, protected CThreadBase -{ -public: - static bool s_mastervol_available; //!< マスタボリューム使用可能? - - static void Initialize(); - static void EnumerateDevices(std::vector& devices); - - CSoundDeviceDSound3(); - virtual ~CSoundDeviceDSound3(); - virtual bool Open(LPCTSTR lpDevice = NULL, HWND hWnd = NULL); - virtual void Close(); - virtual UINT CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize = 0); - virtual void DestroyStream(); - virtual void ResetStream(); - virtual bool PlayStream(); - virtual void StopStream(); - virtual void SetMasterVolume(int nVolume); - virtual bool LoadPCM(UINT nNum, LPCTSTR lpFilename = NULL); - virtual bool ReloadPCM(UINT nNum); - virtual void SetPCMVolume(UINT nNum, int nVolume); - virtual bool PlayPCM(UINT nNum, BOOL bLoop); - virtual void StopPCM(UINT nNum); - virtual void StopAllPCM(); - -protected: - virtual bool Task(); - -private: - static std::vector sm_devices; //!< デバイス リスト - - LPDIRECTSOUND m_lpDSound; //!< Direct Sound インタフェイス - LPDIRECTSOUNDBUFFER m_lpDSStream; //!< ストリーム バッファ - UINT m_nChannels; //!< チャネル数 - UINT m_nBufferSize; //!< バッファ サイズ - UINT m_dwHalfBufferSize; //!< バッファ バイト - HANDLE m_hEvents[2]; //!< イベント - std::map m_pcm; //!< PCM バッファ - std::map m_pcmfile; //!< PCM ファイル名 - int m_mastervolume; //!< マスタボリューム - int m_pcmvolume[PCMVOLUME_MAXCOUNT]; //!< PCMボリューム - - static BOOL CALLBACK EnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext); - void FillStream(DWORD dwPosition); - void UnloadPCM(UINT nNum); - void DestroyAllPCM(); - LPDIRECTSOUNDBUFFER CreateWaveBuffer(LPCTSTR lpFilename, int volume100); -}; +/** + * @file sddsound3.h + * @brief DSound3 オーディオ クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include +#include +#include "sdbase.h" +#include "misc\threadbase.h" + +#define PCMVOLUME_MAXCOUNT 64 + +/** + * @brief デバイス + */ +struct DSound3Device +{ + GUID guid; //!< GUID + TCHAR szDevice[MAX_PATH]; //!< デバイス +}; + +/** + * @brief Direct Sound3 クラス + */ +class CSoundDeviceDSound3 : public CSoundDeviceBase, protected CThreadBase +{ +public: + static bool s_mastervol_available; //!< マスタボリューム使用可能? + + static void Initialize(); + static void EnumerateDevices(std::vector& devices); + + CSoundDeviceDSound3(); + virtual ~CSoundDeviceDSound3(); + virtual bool Open(LPCTSTR lpDevice = NULL, HWND hWnd = NULL); + virtual void Close(); + virtual UINT CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize = 0); + virtual void DestroyStream(); + virtual void ResetStream(); + virtual bool PlayStream(); + virtual void StopStream(); + virtual void SetMasterVolume(int nVolume); + virtual bool LoadPCM(UINT nNum, LPCTSTR lpFilename = NULL); + virtual bool ReloadPCM(UINT nNum); + virtual void SetPCMVolume(UINT nNum, int nVolume); + virtual bool PlayPCM(UINT nNum, BOOL bLoop); + virtual void StopPCM(UINT nNum); + virtual void StopAllPCM(); + +protected: + virtual bool Task(); + +private: + static std::vector sm_devices; //!< デバイス リスト + + LPDIRECTSOUND m_lpDSound; //!< Direct Sound インタフェイス + LPDIRECTSOUNDBUFFER m_lpDSStream; //!< ストリーム バッファ + UINT m_nChannels; //!< チャネル数 + UINT m_nBufferSize; //!< バッファ サイズ + UINT m_dwHalfBufferSize; //!< バッファ バイト + HANDLE m_hEvents[2]; //!< イベント + std::map m_pcm; //!< PCM バッファ + std::map m_pcmfile; //!< PCM ファイル名 + int m_mastervolume; //!< マスタボリューム + int m_pcmvolume[PCMVOLUME_MAXCOUNT]; //!< PCMボリューム + + static BOOL CALLBACK EnumCallback(LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext); + void FillStream(DWORD dwPosition); + void UnloadPCM(UINT nNum); + void DestroyAllPCM(); + LPDIRECTSOUNDBUFFER CreateWaveBuffer(LPCTSTR lpFilename, int volume100); +}; diff --git a/windows/soundmng/sdwasapi.cpp b/windows/soundmng/sdwasapi.cpp old mode 100755 new mode 100644 index 8ca3fcad..fb8367c5 --- a/windows/soundmng/sdwasapi.cpp +++ b/windows/soundmng/sdwasapi.cpp @@ -1,436 +1,436 @@ -/** - * @file sdwasapi.cpp - * @brief WASAPI オーディオ クラスの動作の定義を行います - */ - -#include -#include "sdwasapi.h" -#include -#include - -//! デバイス リスト -std::vector CSoundDeviceWasapi::sm_devices; - -//! MMDeviceEnumerator -const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); - -//! IMMDeviceEnumerator -const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); - -//! IAudioClient -const IID IID_IAudioClient = __uuidof(IAudioClient); - -//! IAudioRenderClient -const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient); - -/** - * 初期化 - */ -void CSoundDeviceWasapi::Initialize() -{ - IMMDeviceEnumerator* pEnumerator = NULL; - if (SUCCEEDED(::CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast(&pEnumerator)))) - { - IMMDeviceCollection* pDevices = NULL; - if (SUCCEEDED(pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices))) - { - UINT nNumDevices = 0; - if (SUCCEEDED(pDevices->GetCount(&nNumDevices))) - { - for (UINT i = 0; i < nNumDevices; i++) - { - IMMDevice* pDevice = NULL; - if (FAILED(pDevices->Item(i, &pDevice))) - { - continue; - } - - WasapiDevice dev; - ZeroMemory(&dev, sizeof(dev)); - if (FAILED(pDevice->GetId(&dev.id))) - { - pDevice->Release(); - continue; - } - - IPropertyStore* pPropStore = NULL; - if (SUCCEEDED(pDevice->OpenPropertyStore(STGM_READ, &pPropStore))) - { - PROPVARIANT varName; - ::PropVariantInit(&varName); - pPropStore->GetValue(PKEY_Device_FriendlyName, &varName); - - USES_CONVERSION; - ::lstrcpyn(dev.szDevice, W2CT(varName.pwszVal), _countof(dev.szDevice)); - ::PropVariantClear(&varName); - pPropStore->Release(); - } - pDevice->Release(); - - sm_devices.push_back(dev); - } - } - pDevices->Release(); - } - pEnumerator->Release(); - } -} - -/** - * 解放 - */ -void CSoundDeviceWasapi::Deinitialize() -{ - if (!sm_devices.empty()) - { - for (std::vector::iterator it = sm_devices.begin(); it != sm_devices.end(); ++it) - { - ::CoTaskMemFree(it->id); - } - sm_devices.clear(); - } -} - -/** - * 列挙 - * @param[out] devices デバイス リスト - */ -void CSoundDeviceWasapi::EnumerateDevices(std::vector& devices) -{ - for (std::vector::const_iterator it = sm_devices.begin(); it != sm_devices.end(); ++it) - { - devices.push_back(it->szDevice); - } -} - -/** - * コンストラクタ - */ -CSoundDeviceWasapi::CSoundDeviceWasapi() - : m_pEnumerator(NULL) - , m_pDevice(NULL) - , m_pAudioClient(NULL) - , m_pwfx(NULL) - , m_pRenderClient(NULL) - , m_nBufferSize(0) - , m_mastervolume(100) -{ - ZeroMemory(m_hEvents, sizeof(m_hEvents)); -} - -/** - * デストラクタ - */ -CSoundDeviceWasapi::~CSoundDeviceWasapi() -{ - Close(); -} - -/** - * オープン - * @param[in] lpDevice デバイス名 - * @param[in] hWnd ウィンドウ ハンドル - * @retval true 成功 - * @retval false 失敗 - */ -bool CSoundDeviceWasapi::Open(LPCTSTR lpDevice, HWND hWnd) -{ - if (FAILED(::CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast(&m_pEnumerator)))) - { - return false; - } - - HRESULT hr = E_FAIL; - if ((lpDevice) && (lpDevice[0] != '\0')) - { - for (std::vector::const_iterator it = sm_devices.begin(); it != sm_devices.end(); ++it) - { - if (::lstrcmpi(lpDevice, it->szDevice) == 0) - { - hr = m_pEnumerator->GetDevice(it->id, &m_pDevice); - break; - } - } - } - else - { - hr = m_pEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &m_pDevice); - } - - if (FAILED(hr)) - { - Close(); - return false; - } - return true; -} - -/** - * クローズ - */ -void CSoundDeviceWasapi::Close() -{ - DestroyStream(); - - if (m_pDevice) - { - m_pDevice->Release(); - m_pDevice = NULL; - } - if (m_pEnumerator) - { - m_pEnumerator->Release(); - m_pEnumerator = NULL; - } -} - -/** - * ストリームの作成 - * @param[in] nSamplingRate サンプリング レート - * @param[in] nChannels チャネル数 - * @param[in] nBufferSize バッファ サイズ - * @return バッファ サイズ - */ -UINT CSoundDeviceWasapi::CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize) -{ - do - { - if (m_pDevice == NULL) - { - break; - } - - if (FAILED(m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, reinterpret_cast(&m_pAudioClient)))) - { - break; - } - - m_pwfx = static_cast(::CoTaskMemAlloc(sizeof(WAVEFORMATEX))); - if (m_pwfx == NULL) - { - break; - } - - ZeroMemory(m_pwfx, sizeof(*m_pwfx)); - m_pwfx->wFormatTag = WAVE_FORMAT_PCM; - m_pwfx->nChannels = nChannels; - m_pwfx->nSamplesPerSec = nSamplingRate; - m_pwfx->nAvgBytesPerSec = nSamplingRate * nChannels * (16 / 8); - m_pwfx->nBlockAlign = (16 / 8) * nChannels; - m_pwfx->wBitsPerSample = 16; - - if (FAILED(m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, m_pwfx, NULL))) - { - // printf("invalid format\n"); - break; - } - - REFERENCE_TIME hnsRequestedDuration = 0; - if (nBufferSize == 0) - { - m_pAudioClient->GetDevicePeriod(&hnsRequestedDuration, NULL); - } - else - { - hnsRequestedDuration = static_cast(((nBufferSize * 10000000.0) / nSamplingRate) + 0.5); - } - HRESULT hr = m_pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, hnsRequestedDuration, hnsRequestedDuration, m_pwfx, NULL); - if (hr == AUDCLNT_ERR(0x019) /* AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED */) - { - UINT32 nCurrentBufferSize = 0; - if (FAILED(m_pAudioClient->GetBufferSize(&nCurrentBufferSize))) - { - break; - } - hnsRequestedDuration = static_cast(((nCurrentBufferSize * 10000000.0) / nSamplingRate) + 0.5); - hr = m_pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, hnsRequestedDuration, hnsRequestedDuration, m_pwfx, NULL); - } - if (FAILED(hr)) - { - printf("Failed initiaziling (%x)\n", hr); - break; - } - - if (FAILED(m_pAudioClient->GetBufferSize(&m_nBufferSize))) - { - break; - } - - m_hEvents[0] = ::CreateEvent(NULL, FALSE, FALSE, NULL); - if (FAILED(m_pAudioClient->SetEventHandle(m_hEvents[0]))) - { - break; - } - - if (FAILED(m_pAudioClient->GetService(IID_IAudioRenderClient, reinterpret_cast(&m_pRenderClient)))) - { - break; - } - - SetMasterVolume(m_mastervolume); - - ResetStream(); - - m_hEvents[1] = ::CreateEvent(NULL, FALSE, FALSE, NULL); - CThreadBase::Start(); - - return m_nBufferSize; - - } while (false /*CONSTCOND*/); - - DestroyStream(); - return 0; -} - -/** - * ストリームを破棄 - */ -void CSoundDeviceWasapi::DestroyStream() -{ - if (m_hEvents[1]) - { - ::SetEvent(m_hEvents[1]); - CThreadBase::Stop(); - } - - if (m_pAudioClient) - { - m_pAudioClient->Stop(); - m_pAudioClient->Release(); - m_pAudioClient = NULL; - } - - if (m_pRenderClient) - { - m_pRenderClient->Release(); - m_pRenderClient = NULL; - } - - if (m_pwfx) - { - ::CoTaskMemFree(m_pwfx); - m_pwfx = NULL; - } - - for (UINT i = 0; i < _countof(m_hEvents); i++) - { - if (m_hEvents[i]) - { - ::CloseHandle(m_hEvents[i]); - m_hEvents[i] = NULL; - } - } -} - -/** - * ストリームをリセット - */ -void CSoundDeviceWasapi::ResetStream() -{ - if (m_pRenderClient) - { - // Grab the entire buffer for the initial fill operation. - BYTE* pData = NULL; - HRESULT hr = m_pRenderClient->GetBuffer(m_nBufferSize, &pData); - if (SUCCEEDED(hr)) - { - ZeroMemory(pData, m_nBufferSize * m_pwfx->nBlockAlign); - m_pRenderClient->ReleaseBuffer(m_nBufferSize, AUDCLNT_BUFFERFLAGS_SILENT); - } - } -} - -/** - * ストリームの再生 - * @retval true 成功 - * @retval false 失敗 - */ -bool CSoundDeviceWasapi::PlayStream() -{ - if (m_pAudioClient) - { - if (SUCCEEDED(m_pAudioClient->Start())) - { - return true; - } - } - return false; -} - -/** - * ストリームの停止 - */ -void CSoundDeviceWasapi::StopStream() -{ - if (m_pAudioClient) - { - m_pAudioClient->Stop(); - } -} - -/** - * ストリーム ヴォリューム設定 - * @param[in] nVolume ヴォリューム(max 100) - */ -void CSoundDeviceWasapi::SetMasterVolume(int nVolume) -{ - m_mastervolume = nVolume; - if (m_pAudioClient) - { - // TODO: マスタボリューム設定 - } -} - -/** - * 同期 - * @retval true 継続 - * @retval false 終了 - */ -bool CSoundDeviceWasapi::Task() -{ - if(!m_hEvents[0] || !m_hEvents[1]){ - return false; - } - switch (::WaitForMultipleObjects(_countof(m_hEvents), m_hEvents, 0, INFINITE)) - { - case WAIT_OBJECT_0 + 0: - FillStream(); - break; - - case WAIT_OBJECT_0 + 1: - return false; - - default: - break; - } - return true; -} - -/** - * ストリームを更新する - */ -void CSoundDeviceWasapi::FillStream() -{ - if (m_pRenderClient) - { - BYTE* pData = NULL; - HRESULT hr = m_pRenderClient->GetBuffer(m_nBufferSize, &pData); - if (SUCCEEDED(hr)) - { - UINT nStreamLength = 0; - if (m_pSoundData) - { - nStreamLength = m_pSoundData->Get16(reinterpret_cast(pData), m_nBufferSize); - } - if (nStreamLength != m_nBufferSize) - { - ZeroMemory(pData + (nStreamLength * m_pwfx->nBlockAlign), (m_nBufferSize - nStreamLength) * m_pwfx->nBlockAlign); - } - m_pRenderClient->ReleaseBuffer(m_nBufferSize, 0); - } - else - { - printf("err.\n"); - } - } -} +/** + * @file sdwasapi.cpp + * @brief WASAPI オーディオ クラスの動作の定義を行います + */ + +#include +#include "sdwasapi.h" +#include +#include + +//! デバイス リスト +std::vector CSoundDeviceWasapi::sm_devices; + +//! MMDeviceEnumerator +const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); + +//! IMMDeviceEnumerator +const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); + +//! IAudioClient +const IID IID_IAudioClient = __uuidof(IAudioClient); + +//! IAudioRenderClient +const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient); + +/** + * 初期化 + */ +void CSoundDeviceWasapi::Initialize() +{ + IMMDeviceEnumerator* pEnumerator = NULL; + if (SUCCEEDED(::CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast(&pEnumerator)))) + { + IMMDeviceCollection* pDevices = NULL; + if (SUCCEEDED(pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices))) + { + UINT nNumDevices = 0; + if (SUCCEEDED(pDevices->GetCount(&nNumDevices))) + { + for (UINT i = 0; i < nNumDevices; i++) + { + IMMDevice* pDevice = NULL; + if (FAILED(pDevices->Item(i, &pDevice))) + { + continue; + } + + WasapiDevice dev; + ZeroMemory(&dev, sizeof(dev)); + if (FAILED(pDevice->GetId(&dev.id))) + { + pDevice->Release(); + continue; + } + + IPropertyStore* pPropStore = NULL; + if (SUCCEEDED(pDevice->OpenPropertyStore(STGM_READ, &pPropStore))) + { + PROPVARIANT varName; + ::PropVariantInit(&varName); + pPropStore->GetValue(PKEY_Device_FriendlyName, &varName); + + USES_CONVERSION; + ::lstrcpyn(dev.szDevice, W2CT(varName.pwszVal), _countof(dev.szDevice)); + ::PropVariantClear(&varName); + pPropStore->Release(); + } + pDevice->Release(); + + sm_devices.push_back(dev); + } + } + pDevices->Release(); + } + pEnumerator->Release(); + } +} + +/** + * 解放 + */ +void CSoundDeviceWasapi::Deinitialize() +{ + if (!sm_devices.empty()) + { + for (std::vector::iterator it = sm_devices.begin(); it != sm_devices.end(); ++it) + { + ::CoTaskMemFree(it->id); + } + sm_devices.clear(); + } +} + +/** + * 列挙 + * @param[out] devices デバイス リスト + */ +void CSoundDeviceWasapi::EnumerateDevices(std::vector& devices) +{ + for (std::vector::const_iterator it = sm_devices.begin(); it != sm_devices.end(); ++it) + { + devices.push_back(it->szDevice); + } +} + +/** + * コンストラクタ + */ +CSoundDeviceWasapi::CSoundDeviceWasapi() + : m_pEnumerator(NULL) + , m_pDevice(NULL) + , m_pAudioClient(NULL) + , m_pwfx(NULL) + , m_pRenderClient(NULL) + , m_nBufferSize(0) + , m_mastervolume(100) +{ + ZeroMemory(m_hEvents, sizeof(m_hEvents)); +} + +/** + * デストラクタ + */ +CSoundDeviceWasapi::~CSoundDeviceWasapi() +{ + Close(); +} + +/** + * オープン + * @param[in] lpDevice デバイス名 + * @param[in] hWnd ウィンドウ ハンドル + * @retval true 成功 + * @retval false 失敗 + */ +bool CSoundDeviceWasapi::Open(LPCTSTR lpDevice, HWND hWnd) +{ + if (FAILED(::CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast(&m_pEnumerator)))) + { + return false; + } + + HRESULT hr = E_FAIL; + if ((lpDevice) && (lpDevice[0] != '\0')) + { + for (std::vector::const_iterator it = sm_devices.begin(); it != sm_devices.end(); ++it) + { + if (::lstrcmpi(lpDevice, it->szDevice) == 0) + { + hr = m_pEnumerator->GetDevice(it->id, &m_pDevice); + break; + } + } + } + else + { + hr = m_pEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &m_pDevice); + } + + if (FAILED(hr)) + { + Close(); + return false; + } + return true; +} + +/** + * クローズ + */ +void CSoundDeviceWasapi::Close() +{ + DestroyStream(); + + if (m_pDevice) + { + m_pDevice->Release(); + m_pDevice = NULL; + } + if (m_pEnumerator) + { + m_pEnumerator->Release(); + m_pEnumerator = NULL; + } +} + +/** + * ストリームの作成 + * @param[in] nSamplingRate サンプリング レート + * @param[in] nChannels チャネル数 + * @param[in] nBufferSize バッファ サイズ + * @return バッファ サイズ + */ +UINT CSoundDeviceWasapi::CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize) +{ + do + { + if (m_pDevice == NULL) + { + break; + } + + if (FAILED(m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, reinterpret_cast(&m_pAudioClient)))) + { + break; + } + + m_pwfx = static_cast(::CoTaskMemAlloc(sizeof(WAVEFORMATEX))); + if (m_pwfx == NULL) + { + break; + } + + ZeroMemory(m_pwfx, sizeof(*m_pwfx)); + m_pwfx->wFormatTag = WAVE_FORMAT_PCM; + m_pwfx->nChannels = nChannels; + m_pwfx->nSamplesPerSec = nSamplingRate; + m_pwfx->nAvgBytesPerSec = nSamplingRate * nChannels * (16 / 8); + m_pwfx->nBlockAlign = (16 / 8) * nChannels; + m_pwfx->wBitsPerSample = 16; + + if (FAILED(m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, m_pwfx, NULL))) + { + // printf("invalid format\n"); + break; + } + + REFERENCE_TIME hnsRequestedDuration = 0; + if (nBufferSize == 0) + { + m_pAudioClient->GetDevicePeriod(&hnsRequestedDuration, NULL); + } + else + { + hnsRequestedDuration = static_cast(((nBufferSize * 10000000.0) / nSamplingRate) + 0.5); + } + HRESULT hr = m_pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, hnsRequestedDuration, hnsRequestedDuration, m_pwfx, NULL); + if (hr == AUDCLNT_ERR(0x019) /* AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED */) + { + UINT32 nCurrentBufferSize = 0; + if (FAILED(m_pAudioClient->GetBufferSize(&nCurrentBufferSize))) + { + break; + } + hnsRequestedDuration = static_cast(((nCurrentBufferSize * 10000000.0) / nSamplingRate) + 0.5); + hr = m_pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, hnsRequestedDuration, hnsRequestedDuration, m_pwfx, NULL); + } + if (FAILED(hr)) + { + printf("Failed initiaziling (%x)\n", hr); + break; + } + + if (FAILED(m_pAudioClient->GetBufferSize(&m_nBufferSize))) + { + break; + } + + m_hEvents[0] = ::CreateEvent(NULL, FALSE, FALSE, NULL); + if (FAILED(m_pAudioClient->SetEventHandle(m_hEvents[0]))) + { + break; + } + + if (FAILED(m_pAudioClient->GetService(IID_IAudioRenderClient, reinterpret_cast(&m_pRenderClient)))) + { + break; + } + + SetMasterVolume(m_mastervolume); + + ResetStream(); + + m_hEvents[1] = ::CreateEvent(NULL, FALSE, FALSE, NULL); + CThreadBase::Start(); + + return m_nBufferSize; + + } while (false /*CONSTCOND*/); + + DestroyStream(); + return 0; +} + +/** + * ストリームを破棄 + */ +void CSoundDeviceWasapi::DestroyStream() +{ + if (m_hEvents[1]) + { + ::SetEvent(m_hEvents[1]); + CThreadBase::Stop(); + } + + if (m_pAudioClient) + { + m_pAudioClient->Stop(); + m_pAudioClient->Release(); + m_pAudioClient = NULL; + } + + if (m_pRenderClient) + { + m_pRenderClient->Release(); + m_pRenderClient = NULL; + } + + if (m_pwfx) + { + ::CoTaskMemFree(m_pwfx); + m_pwfx = NULL; + } + + for (UINT i = 0; i < _countof(m_hEvents); i++) + { + if (m_hEvents[i]) + { + ::CloseHandle(m_hEvents[i]); + m_hEvents[i] = NULL; + } + } +} + +/** + * ストリームをリセット + */ +void CSoundDeviceWasapi::ResetStream() +{ + if (m_pRenderClient) + { + // Grab the entire buffer for the initial fill operation. + BYTE* pData = NULL; + HRESULT hr = m_pRenderClient->GetBuffer(m_nBufferSize, &pData); + if (SUCCEEDED(hr)) + { + ZeroMemory(pData, m_nBufferSize * m_pwfx->nBlockAlign); + m_pRenderClient->ReleaseBuffer(m_nBufferSize, AUDCLNT_BUFFERFLAGS_SILENT); + } + } +} + +/** + * ストリームの再生 + * @retval true 成功 + * @retval false 失敗 + */ +bool CSoundDeviceWasapi::PlayStream() +{ + if (m_pAudioClient) + { + if (SUCCEEDED(m_pAudioClient->Start())) + { + return true; + } + } + return false; +} + +/** + * ストリームの停止 + */ +void CSoundDeviceWasapi::StopStream() +{ + if (m_pAudioClient) + { + m_pAudioClient->Stop(); + } +} + +/** + * ストリーム ヴォリューム設定 + * @param[in] nVolume ヴォリューム(max 100) + */ +void CSoundDeviceWasapi::SetMasterVolume(int nVolume) +{ + m_mastervolume = nVolume; + if (m_pAudioClient) + { + // TODO: マスタボリューム設定 + } +} + +/** + * 同期 + * @retval true 継続 + * @retval false 終了 + */ +bool CSoundDeviceWasapi::Task() +{ + if(!m_hEvents[0] || !m_hEvents[1]){ + return false; + } + switch (::WaitForMultipleObjects(_countof(m_hEvents), m_hEvents, 0, INFINITE)) + { + case WAIT_OBJECT_0 + 0: + FillStream(); + break; + + case WAIT_OBJECT_0 + 1: + return false; + + default: + break; + } + return true; +} + +/** + * ストリームを更新する + */ +void CSoundDeviceWasapi::FillStream() +{ + if (m_pRenderClient) + { + BYTE* pData = NULL; + HRESULT hr = m_pRenderClient->GetBuffer(m_nBufferSize, &pData); + if (SUCCEEDED(hr)) + { + UINT nStreamLength = 0; + if (m_pSoundData) + { + nStreamLength = m_pSoundData->Get16(reinterpret_cast(pData), m_nBufferSize); + } + if (nStreamLength != m_nBufferSize) + { + ZeroMemory(pData + (nStreamLength * m_pwfx->nBlockAlign), (m_nBufferSize - nStreamLength) * m_pwfx->nBlockAlign); + } + m_pRenderClient->ReleaseBuffer(m_nBufferSize, 0); + } + else + { + printf("err.\n"); + } + } +} diff --git a/windows/soundmng/sdwasapi.h b/windows/soundmng/sdwasapi.h old mode 100755 new mode 100644 index c9f9244d..24eb9dbd --- a/windows/soundmng/sdwasapi.h +++ b/windows/soundmng/sdwasapi.h @@ -1,60 +1,60 @@ -/** - * @file sdwasapi.h - * @brief WASAPI オーディオ クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include -#include -#include -#include -#include "sdbase.h" -#include "misc\threadbase.h" - -/** - * @brief デバイス - */ -struct WasapiDevice -{ - LPWSTR id; //!< ID - TCHAR szDevice[MAX_PATH]; //!< デバイス -}; - -/** - * @brief WASAPI クラス - */ -class CSoundDeviceWasapi : public CSoundDeviceBase, protected CThreadBase -{ -public: - static void Initialize(); - static void Deinitialize(); - static void EnumerateDevices(std::vector& devices); - - CSoundDeviceWasapi(); - virtual ~CSoundDeviceWasapi(); - virtual bool Open(LPCTSTR lpDevice = NULL, HWND hWnd = NULL); - virtual void Close(); - virtual UINT CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize = 0); - virtual void DestroyStream(); - virtual bool PlayStream(); - virtual void StopStream(); - virtual void SetMasterVolume(int nVolume); - -protected: - virtual bool Task(); - -private: - static std::vector sm_devices; //!< デバイス リスト - int m_mastervolume; //!< マスタボリューム - - IMMDeviceEnumerator* m_pEnumerator; //!< デバイス列挙インスタンス - IMMDevice* m_pDevice; //!< デバイス インスタンス - IAudioClient* m_pAudioClient; //!< オーディオ クライアント インスタンス - WAVEFORMATEX* m_pwfx; //!< フォーマット - IAudioRenderClient* m_pRenderClient; //!< オーディオ レンダラー クライアント インスタンス - UINT32 m_nBufferSize; //!< バッファ サイズ - HANDLE m_hEvents[2]; //!< イベント - void ResetStream(); - void FillStream(); -}; +/** + * @file sdwasapi.h + * @brief WASAPI オーディオ クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include +#include +#include +#include +#include "sdbase.h" +#include "misc\threadbase.h" + +/** + * @brief デバイス + */ +struct WasapiDevice +{ + LPWSTR id; //!< ID + TCHAR szDevice[MAX_PATH]; //!< デバイス +}; + +/** + * @brief WASAPI クラス + */ +class CSoundDeviceWasapi : public CSoundDeviceBase, protected CThreadBase +{ +public: + static void Initialize(); + static void Deinitialize(); + static void EnumerateDevices(std::vector& devices); + + CSoundDeviceWasapi(); + virtual ~CSoundDeviceWasapi(); + virtual bool Open(LPCTSTR lpDevice = NULL, HWND hWnd = NULL); + virtual void Close(); + virtual UINT CreateStream(UINT nSamplingRate, UINT nChannels, UINT nBufferSize = 0); + virtual void DestroyStream(); + virtual bool PlayStream(); + virtual void StopStream(); + virtual void SetMasterVolume(int nVolume); + +protected: + virtual bool Task(); + +private: + static std::vector sm_devices; //!< デバイス リスト + int m_mastervolume; //!< マスタボリューム + + IMMDeviceEnumerator* m_pEnumerator; //!< デバイス列挙インスタンス + IMMDevice* m_pDevice; //!< デバイス インスタンス + IAudioClient* m_pAudioClient; //!< オーディオ クライアント インスタンス + WAVEFORMATEX* m_pwfx; //!< フォーマット + IAudioRenderClient* m_pRenderClient; //!< オーディオ レンダラー クライアント インスタンス + UINT32 m_nBufferSize; //!< バッファ サイズ + HANDLE m_hEvents[2]; //!< イベント + void ResetStream(); + void FillStream(); +}; diff --git a/windows/subwnd/dclock.cpp b/windows/subwnd/dclock.cpp old mode 100755 new mode 100644 index 956792a1..ce94cd3c --- a/windows/subwnd/dclock.cpp +++ b/windows/subwnd/dclock.cpp @@ -1,669 +1,669 @@ -/** - * @file dclock.cpp - * @brief 時刻表示クラスの動作の定義を行います - */ - -#include -#include "dclock.h" -#include -#include -#include -#include -#include -#include - -//! 唯一のインスタンスです -DispClock DispClock::sm_instance; - -/** - * @brief パターン構造体 - */ -struct DispClockPattern -{ - UINT8 cWidth; /*!< フォント サイズ */ - UINT8 cMask; /*!< マスク */ - UINT8 cPosition[6]; /*!< 位置 */ - void (*fnInitialize)(UINT8* lpBuffer, UINT8 nDegits); /*!< 初期化関数 */ - UINT8 font[11][16]; /*!< フォント */ -}; - -/** - * 初期化-1 - * @param[out] lpBuffer バッファ - * @param[in] nDegits 桁数 - */ -static void InitializeFont1(UINT8* lpBuffer, UINT8 nDegits) -{ - if (nDegits) - { - const UINT32 pat = (nDegits <= 4) ? 0x00008001 : 0x30008001; - *(UINT32 *)(lpBuffer + 1 + ( 4 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + ( 5 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + ( 9 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; - } -} - -/** - * 初期化-2 - * @param[out] lpBuffer バッファ - * @param[in] nDegits 桁数 - */ -static void InitializeFont2(UINT8* lpBuffer, UINT8 nDegits) -{ - if (nDegits) - { - UINT32 pat = (nDegits <= 4) ? 0x00000002 : 0x00020002; - *(UINT32 *)(lpBuffer + 1 + ( 4 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + ( 5 * DCLOCK_YALIGN)) = pat; - pat <<= 1; - *(UINT32 *)(lpBuffer + 1 + ( 9 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; - } -} - -/** - * 初期化-3 - * @param[out] lpBuffer バッファ - * @param[in] nDegits 桁数 - */ -static void InitializeFont3(UINT8* lpBuffer, UINT8 nDegits) -{ - if (nDegits) - { - const UINT32 pat = (nDegits <= 4) ? 0x00000010 : 0x00400010; - *(UINT32 *)(lpBuffer + 1 + ( 4 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + ( 5 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + ( 9 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; - } -} - -/** - * 初期化-4 - * @param[out] lpBuffer バッファ - * @param[in] nDegits 桁数 - */ -static void InitializeFont4(UINT8* lpBuffer, UINT8 nDegits) -{ - if (nDegits) - { - const UINT32 pat = (nDegits <= 4) ? 0x00000004 : 0x00040004; - *(UINT32 *)(lpBuffer + 1 + ( 5 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + ( 6 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + ( 9 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; - } -} - -/** - * 初期化-5 - * @param[out] lpBuffer バッファ - * @param[in] nDegits 桁数 - */ -static void InitializeFont5(UINT8* lpBuffer, UINT8 nDegits) -{ - if (nDegits) - { - const UINT32 pat = (nDegits <= 4) ? 0x00000006 : 0x00030006; - *(UINT32 *)(lpBuffer + 1 + ( 6 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + ( 7 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + ( 9 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; - } -} - -/** - * 初期化-6 - * @param[out] lpBuffer バッファ - * @param[in] nDegits 桁数 - */ -static void InitializeFont6(UINT8* lpBuffer, UINT8 nDegits) -{ - if (nDegits) - { - const UINT32 pat = (nDegits <= 4) ? 0x00000020 : 0x00000220; - *(UINT32 *)(lpBuffer + 1 + ( 8 * DCLOCK_YALIGN)) = pat; - *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; - } -} - -/** - * パターン - */ -static const DispClockPattern s_pattern[6] = -{ - // FONT-1 - { - 6, 0xfc, - {0, 7, 19, 26, 38, 45}, - InitializeFont1, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - {0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78,}, - {0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,}, - {0x78, 0xcc, 0xcc, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfc,}, - {0xfc, 0x18, 0x30, 0x70, 0x18, 0x0c, 0x0c, 0xcc, 0x78,}, - {0x18, 0x38, 0x78, 0xd8, 0xd8, 0xfc, 0x18, 0x18, 0x18,}, - {0xfc, 0xc0, 0xc0, 0xf8, 0x0c, 0x0c, 0x0c, 0x8c, 0x78,}, - {0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x78,}, - {0xfc, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30,}, - {0x78, 0xcc, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0xcc, 0x78,}, - {0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70,} - } - }, - - // FONT-2 - { - 6, 0xfc, - {0, 6, 16, 22, 32, 38}, - InitializeFont2, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - {0x00, 0x00, 0x30, 0x48, 0x88, 0x88, 0x88, 0x88, 0x70,}, - {0x10, 0x30, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20,}, - {0x38, 0x44, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xf8,}, - {0x7c, 0x08, 0x10, 0x30, 0x10, 0x08, 0x08, 0x90, 0x60,}, - {0x20, 0x40, 0x40, 0x88, 0x88, 0x90, 0x78, 0x10, 0x20,}, - {0x3c, 0x20, 0x20, 0x70, 0x08, 0x08, 0x08, 0x90, 0x60,}, - {0x10, 0x10, 0x20, 0x70, 0x48, 0x88, 0x88, 0x90, 0x60,}, - {0x7c, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40,}, - {0x38, 0x44, 0x44, 0x48, 0x30, 0x48, 0x88, 0x88, 0x70,}, - {0x18, 0x24, 0x40, 0x44, 0x48, 0x38, 0x10, 0x20, 0x20,} - } - }, - - // FONT-3 - { - 4, 0xf0, - {0, 5, 14, 19, 28, 33}, - InitializeFont3, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - {0x60, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x60,}, - {0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,}, - {0x60, 0x90, 0x90, 0x10, 0x20, 0x40, 0x40, 0x80, 0xf0,}, - {0x60, 0x90, 0x90, 0x10, 0x60, 0x10, 0x90, 0x90, 0x60,}, - {0x20, 0x60, 0x60, 0xa0, 0xa0, 0xa0, 0xf0, 0x20, 0x20,}, - {0xf0, 0x80, 0x80, 0xe0, 0x90, 0x10, 0x90, 0x90, 0x60,}, - {0x60, 0x90, 0x90, 0x80, 0xe0, 0x90, 0x90, 0x90, 0x60,}, - {0xf0, 0x10, 0x10, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40,}, - {0x60, 0x90, 0x90, 0x90, 0x60, 0x90, 0x90, 0x90, 0x60,}, - {0x60, 0x90, 0x90, 0x90, 0x70, 0x10, 0x90, 0x90, 0x60,} - } - }, - - // FONT-4 - { - 5, 0xf8, - {0, 6, 16, 22, 32, 38}, - InitializeFont4, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - {0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70,}, - {0x00, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70,}, - {0x00, 0x70, 0x88, 0x08, 0x08, 0x30, 0x40, 0x88, 0xf8,}, - {0x00, 0x70, 0x88, 0x08, 0x30, 0x08, 0x08, 0x08, 0xf0,}, - {0x00, 0x10, 0x30, 0x50, 0x50, 0x90, 0xf8, 0x10, 0x10,}, - {0x00, 0x38, 0x40, 0x60, 0x10, 0x08, 0x08, 0x08, 0xf0,}, - {0x00, 0x18, 0x20, 0x40, 0xb0, 0xc8, 0x88, 0x88, 0x70,}, - {0x00, 0x70, 0x88, 0x88, 0x10, 0x10, 0x10, 0x20, 0x20,}, - {0x00, 0x70, 0x88, 0x88, 0x70, 0x50, 0x88, 0x88, 0x70,}, - {0x00, 0x70, 0x88, 0x88, 0x88, 0x78, 0x10, 0x20, 0xc0,} - } - }, - - // FONT-5 - { - 5, 0xf8, - {0, 6, 17, 23, 34, 40}, - InitializeFont5, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - {0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70,}, - {0x00, 0x00, 0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20,}, - {0x00, 0x00, 0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xf8,}, - {0x00, 0x00, 0xf8, 0x10, 0x20, 0x10, 0x08, 0x88, 0x70,}, - {0x00, 0x00, 0x30, 0x50, 0x50, 0x90, 0xf8, 0x10, 0x10,}, - {0x00, 0x00, 0xf8, 0x80, 0xf0, 0x08, 0x08, 0x88, 0x70,}, - {0x00, 0x00, 0x30, 0x40, 0xf0, 0x88, 0x88, 0x88, 0x70,}, - {0x00, 0x00, 0xf8, 0x08, 0x10, 0x20, 0x20, 0x40, 0x40,}, - {0x00, 0x00, 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70,}, - {0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x78, 0x10, 0x60,} - } - }, - - // FONT-6 - { - 4, 0xf0, - {0, 5, 12, 17, 24, 29}, - InitializeFont6, - { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, - {0x00, 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x90, 0x60,}, - {0x00, 0x00, 0x00, 0x20, 0x60, 0x20, 0x20, 0x20, 0x20,}, - {0x00, 0x00, 0x00, 0x60, 0x90, 0x10, 0x20, 0x40, 0xf0,}, - {0x00, 0x00, 0x00, 0xf0, 0x20, 0x60, 0x10, 0x90, 0x60,}, - {0x00, 0x00, 0x00, 0x40, 0x80, 0xa0, 0xa0, 0xf0, 0x20,}, - {0x00, 0x00, 0x00, 0xf0, 0x80, 0x60, 0x10, 0x90, 0x60,}, - {0x00, 0x00, 0x00, 0x40, 0x80, 0xe0, 0x90, 0x90, 0x60,}, - {0x00, 0x00, 0x00, 0xe0, 0x10, 0x10, 0x20, 0x20, 0x40,}, - {0x00, 0x00, 0x00, 0x60, 0x90, 0x60, 0x90, 0x90, 0x60,}, - {0x00, 0x00, 0x00, 0x60, 0x90, 0x90, 0x70, 0x20, 0x40,} - } - } -}; - -/** - * コンストラクタ - */ -DispClock::DispClock() -{ - ZeroMemory(this, sizeof(*this)); -} - -/** - * 初期化 - */ -void DispClock::Initialize() -{ - ::pal_makegrad(m_pal32, 4, np2oscfg.clk_color1, np2oscfg.clk_color2); -} - -/** - * パレット設定 - * @param[in] bpp 色 - */ -void DispClock::SetPalettes(UINT bpp) -{ - switch (bpp) - { - case 8: - SetPalette8(); - break; - - case 16: - SetPalette16(); - break; - } -} - -/** - * 8bpp パレット設定 - */ -void DispClock::SetPalette8() -{ - for (UINT i = 0; i < 16; i++) - { - UINT nBits = 0; - for (UINT j = 1; j < 0x10; j <<= 1) - { - nBits <<= 8; - if (i & j) - { - nBits |= 1; - } - } - for (UINT j = 0; j < 4; j++) - { - m_pal8[j][i] = nBits * (START_PALORG + j); - } - } -} - -/** - * 16bpp パレット設定 - */ -void DispClock::SetPalette16() -{ - for (UINT i = 0; i < 4; i++) - { - m_pal16[i] = scrnmng_makepal16(m_pal32[i]); - } -} - -/** - * リセット - */ -void DispClock::Reset() -{ - if (np2oscfg.clk_x) - { - if (np2oscfg.clk_x <= 4) - { - np2oscfg.clk_x = 4; - } - else if (np2oscfg.clk_x <= 6) - { - np2oscfg.clk_x = 6; - } - else - { - np2oscfg.clk_x = 0; - } - } - if (np2oscfg.clk_fnt >= _countof(s_pattern)) - { - np2oscfg.clk_fnt = 0; - } - - ZeroMemory(m_cTime, sizeof(m_cTime)); - ZeroMemory(m_cLastTime, sizeof(m_cLastTime)); - ZeroMemory(m_buffer, sizeof(m_buffer)); - m_pPattern = &s_pattern[np2oscfg.clk_fnt]; - m_cCharaters = np2oscfg.clk_x; - (*m_pPattern->fnInitialize)(m_buffer, m_cCharaters); - Update(); - Redraw(); -} - -/** - * 更新 - */ -void DispClock::Update() -{ - if ((scrnmng_isfullscreen()) && (m_cCharaters)) - { - _SYSTIME st; - timemng_gettime(&st); - - UINT8 buf[6]; - buf[0] = (st.hour / 10) + 1; - buf[1] = (st.hour % 10) + 1; - buf[2] = (st.minute / 10) + 1; - buf[3] = (st.minute % 10) + 1; - if (m_cCharaters > 4) - { - buf[4] = (st.second / 10) + 1; - buf[5] = (st.second % 10) + 1; - } - - UINT8 count = 13; - for (int i = m_cCharaters; i--; ) - { - if (m_cTime[i] != buf[i]) - { - m_cTime[i] = buf[i]; - m_nCounter.b[i] = count; - m_cDirty |= (1 << i); - count += 4; - } - } - } -} - -/** - * 再描画 - */ -void DispClock::Redraw() -{ - m_cDirty = 0x3f; -} - -/** - * 描画が必要? - * @retval true 描画中 - * @retval false 非描画 - */ -bool DispClock::IsDisplayed() const -{ - return ((m_cDirty != 0) || (m_nCounter.q != 0)); -} - -//! オフセット テーブル -static const UINT8 s_dclocky[13] = {0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3}; - -/** - * 位置計算 - * @param[in] nCount カウント値 - * @return オフセット - */ -UINT8 DispClock::CountPos(UINT nCount) -{ - if (nCount < _countof(s_dclocky)) - { - return s_dclocky[nCount]; - } - else - { - return 255; - } -} - -/** - * カウントダウン処理 - * @param[in] nFrames フレーム数 - */ -void DispClock::CountDown(UINT nFrames) -{ - if ((m_cCharaters == 0) || (m_nCounter.q == 0)) - { - return; - } - - if (nFrames == 0) - { - nFrames = 1; - } - - for (UINT i = 0; i < m_cCharaters; i++) - { - UINT nRemain = m_nCounter.b[i]; - if (nRemain == 0) - { - continue; - } - const UINT8 y = CountPos(nRemain); - - if (nFrames < nRemain) - { - nRemain -= nFrames; - } - else - { - nRemain = 0; - } - if (y != CountPos(nRemain)) - { - m_cDirty |= (1 << i); - } - m_nCounter.b[i] = nRemain; - } -} - -/** - * バッファに描画 - * @retval true 更新あり - * @retval false 更新なし - */ -bool DispClock::Make() -{ - if ((m_cCharaters == 0) || (m_cDirty == 0)) - { - return false; - } - - for (UINT i = 0; i < m_cCharaters; i++) - { - if ((m_cDirty & (1 << i)) == 0) - { - continue; - } - - UINT nNumber = m_cTime[i]; - UINT nPadding = 3; - - const UINT nRemain = m_nCounter.b[i]; - if (nRemain == 0) - { - m_cLastTime[i] = nNumber; - } - else if (nRemain < _countof(s_dclocky)) - { - nPadding -= s_dclocky[nRemain]; - } - else - { - nNumber = this->m_cLastTime[i]; - } - - UINT8* q = m_buffer + (m_pPattern->cPosition[i] >> 3); - const UINT8 cShifter = m_pPattern->cPosition[i] & 7; - const UINT8 cMask0 = ~(m_pPattern->cMask >> cShifter); - const UINT8 cMask1 = ~(m_pPattern->cMask << (8 - cShifter)); - for (UINT y = 0; y < nPadding; y++) - { - q[0] = (q[0] & cMask0); - q[1] = (q[1] & cMask1); - q += DCLOCK_YALIGN; - } - - const UINT8* p = m_pPattern->font[nNumber]; - for (UINT y = 0; y < 9; y++) - { - q[0] = (q[0] & cMask0) | (p[y] >> cShifter); - q[1] = (q[1] & cMask1) | (p[y] << (8 - cShifter)); - q += DCLOCK_YALIGN; - } - } - m_cDirty = 0; - return true; -} - -/** - * 描画 - * @param[in] nBpp 色数 - * @param[out] lpBuffer 描画ポインタ - * @param[in] nYAlign アライメント - */ -void DispClock::Draw(UINT nBpp, void* lpBuffer, int nYAlign) const -{ - switch (nBpp) - { - case 8: - Draw8(lpBuffer, nYAlign); - break; - - case 16: - Draw16(lpBuffer, nYAlign); - break; - - case 24: - Draw24(lpBuffer, nYAlign); - break; - - case 32: - Draw32(lpBuffer, nYAlign); - break; - } -} - -/** - * 描画(8bpp) - * @param[out] lpBuffer 描画ポインタ - * @param[in] nYAlign アライメント - */ -void DispClock::Draw8(void* lpBuffer, int nYAlign) const -{ - const UINT8* p = m_buffer; - - for (UINT i = 0; i < 4; i++) - { - const UINT32* pPattern = m_pal8[i]; - for (UINT j = 0; j < 3; j++) - { - for (UINT x = 0; x < DCLOCK_YALIGN; x++) - { - (static_cast(lpBuffer))[x * 2 + 0] = pPattern[p[x] >> 4]; - (static_cast(lpBuffer))[x * 2 + 1] = pPattern[p[x] & 15]; - } - p += DCLOCK_YALIGN; - lpBuffer = reinterpret_cast(reinterpret_cast(lpBuffer) + nYAlign); - } - } -} - -/** - * 描画(16bpp) - * @param[out] lpBuffer 描画ポインタ - * @param[in] nYAlign アライメント - */ -void DispClock::Draw16(void* lpBuffer, int nYAlign) const -{ - const UINT8* p = m_buffer; - - for (UINT i = 0; i < 4; i++) - { - const RGB16 pal = m_pal16[i]; - for (UINT j = 0; j < 3; j++) - { - for (UINT x = 0; x < (8 * DCLOCK_YALIGN); x++) - { - (static_cast(lpBuffer))[x] = (p[x >> 3] & (0x80 >> (x & 7))) ? pal : 0; - } - p += DCLOCK_YALIGN; - lpBuffer = reinterpret_cast(reinterpret_cast(lpBuffer) + nYAlign); - } - } -} - -/** - * 描画(24bpp) - * @param[out] lpBuffer 描画ポインタ - * @param[in] nYAlign アライメント - */ -void DispClock::Draw24(void* lpBuffer, int nYAlign) const -{ - const UINT8* p = m_buffer; - UINT8* q = static_cast(lpBuffer); - - for (UINT i = 0; i < 4; i++) - { - const RGB32 pal = m_pal32[i]; - for (UINT j = 0; j < 3; j++) - { - for (UINT x = 0; x < (8 * DCLOCK_YALIGN); x++) - { - if (p[x >> 3] & (0x80 >> (x & 7))) - { - q[0] = pal.p.b; - q[1] = pal.p.g; - q[2] = pal.p.g; - } - else - { - q[0] = 0; - q[1] = 1; - q[2] = 2; - } - q += 3; - } - p += DCLOCK_YALIGN; - q += nYAlign - (8 * DCLOCK_YALIGN) * 3; - } - } -} - -/** - * 描画(32bpp) - * @param[out] lpBuffer 描画ポインタ - * @param[in] nYAlign アライメント - */ -void DispClock::Draw32(void* lpBuffer, int nYAlign) const -{ - const UINT8* p = m_buffer; - - for (UINT i = 0; i < 4; i++) - { - const UINT32 pal = m_pal32[i].d; - for (UINT j = 0; j < 3; j++) - { - for (UINT x = 0; x < (8 * DCLOCK_YALIGN); x++) - { - (static_cast(lpBuffer))[x] = (p[x >> 3] & (0x80 >> (x & 7))) ? pal : 0; - } - p += DCLOCK_YALIGN; - lpBuffer = reinterpret_cast(reinterpret_cast(lpBuffer) + nYAlign); - } - } -} +/** + * @file dclock.cpp + * @brief 時刻表示クラスの動作の定義を行います + */ + +#include +#include "dclock.h" +#include +#include +#include +#include +#include +#include + +//! 唯一のインスタンスです +DispClock DispClock::sm_instance; + +/** + * @brief パターン構造体 + */ +struct DispClockPattern +{ + UINT8 cWidth; /*!< フォント サイズ */ + UINT8 cMask; /*!< マスク */ + UINT8 cPosition[6]; /*!< 位置 */ + void (*fnInitialize)(UINT8* lpBuffer, UINT8 nDegits); /*!< 初期化関数 */ + UINT8 font[11][16]; /*!< フォント */ +}; + +/** + * 初期化-1 + * @param[out] lpBuffer バッファ + * @param[in] nDegits 桁数 + */ +static void InitializeFont1(UINT8* lpBuffer, UINT8 nDegits) +{ + if (nDegits) + { + const UINT32 pat = (nDegits <= 4) ? 0x00008001 : 0x30008001; + *(UINT32 *)(lpBuffer + 1 + ( 4 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + ( 5 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + ( 9 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; + } +} + +/** + * 初期化-2 + * @param[out] lpBuffer バッファ + * @param[in] nDegits 桁数 + */ +static void InitializeFont2(UINT8* lpBuffer, UINT8 nDegits) +{ + if (nDegits) + { + UINT32 pat = (nDegits <= 4) ? 0x00000002 : 0x00020002; + *(UINT32 *)(lpBuffer + 1 + ( 4 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + ( 5 * DCLOCK_YALIGN)) = pat; + pat <<= 1; + *(UINT32 *)(lpBuffer + 1 + ( 9 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; + } +} + +/** + * 初期化-3 + * @param[out] lpBuffer バッファ + * @param[in] nDegits 桁数 + */ +static void InitializeFont3(UINT8* lpBuffer, UINT8 nDegits) +{ + if (nDegits) + { + const UINT32 pat = (nDegits <= 4) ? 0x00000010 : 0x00400010; + *(UINT32 *)(lpBuffer + 1 + ( 4 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + ( 5 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + ( 9 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; + } +} + +/** + * 初期化-4 + * @param[out] lpBuffer バッファ + * @param[in] nDegits 桁数 + */ +static void InitializeFont4(UINT8* lpBuffer, UINT8 nDegits) +{ + if (nDegits) + { + const UINT32 pat = (nDegits <= 4) ? 0x00000004 : 0x00040004; + *(UINT32 *)(lpBuffer + 1 + ( 5 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + ( 6 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + ( 9 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; + } +} + +/** + * 初期化-5 + * @param[out] lpBuffer バッファ + * @param[in] nDegits 桁数 + */ +static void InitializeFont5(UINT8* lpBuffer, UINT8 nDegits) +{ + if (nDegits) + { + const UINT32 pat = (nDegits <= 4) ? 0x00000006 : 0x00030006; + *(UINT32 *)(lpBuffer + 1 + ( 6 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + ( 7 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + ( 9 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; + } +} + +/** + * 初期化-6 + * @param[out] lpBuffer バッファ + * @param[in] nDegits 桁数 + */ +static void InitializeFont6(UINT8* lpBuffer, UINT8 nDegits) +{ + if (nDegits) + { + const UINT32 pat = (nDegits <= 4) ? 0x00000020 : 0x00000220; + *(UINT32 *)(lpBuffer + 1 + ( 8 * DCLOCK_YALIGN)) = pat; + *(UINT32 *)(lpBuffer + 1 + (10 * DCLOCK_YALIGN)) = pat; + } +} + +/** + * パターン + */ +static const DispClockPattern s_pattern[6] = +{ + // FONT-1 + { + 6, 0xfc, + {0, 7, 19, 26, 38, 45}, + InitializeFont1, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + {0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78,}, + {0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,}, + {0x78, 0xcc, 0xcc, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfc,}, + {0xfc, 0x18, 0x30, 0x70, 0x18, 0x0c, 0x0c, 0xcc, 0x78,}, + {0x18, 0x38, 0x78, 0xd8, 0xd8, 0xfc, 0x18, 0x18, 0x18,}, + {0xfc, 0xc0, 0xc0, 0xf8, 0x0c, 0x0c, 0x0c, 0x8c, 0x78,}, + {0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x78,}, + {0xfc, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30,}, + {0x78, 0xcc, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0xcc, 0x78,}, + {0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70,} + } + }, + + // FONT-2 + { + 6, 0xfc, + {0, 6, 16, 22, 32, 38}, + InitializeFont2, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + {0x00, 0x00, 0x30, 0x48, 0x88, 0x88, 0x88, 0x88, 0x70,}, + {0x10, 0x30, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20,}, + {0x38, 0x44, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xf8,}, + {0x7c, 0x08, 0x10, 0x30, 0x10, 0x08, 0x08, 0x90, 0x60,}, + {0x20, 0x40, 0x40, 0x88, 0x88, 0x90, 0x78, 0x10, 0x20,}, + {0x3c, 0x20, 0x20, 0x70, 0x08, 0x08, 0x08, 0x90, 0x60,}, + {0x10, 0x10, 0x20, 0x70, 0x48, 0x88, 0x88, 0x90, 0x60,}, + {0x7c, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40,}, + {0x38, 0x44, 0x44, 0x48, 0x30, 0x48, 0x88, 0x88, 0x70,}, + {0x18, 0x24, 0x40, 0x44, 0x48, 0x38, 0x10, 0x20, 0x20,} + } + }, + + // FONT-3 + { + 4, 0xf0, + {0, 5, 14, 19, 28, 33}, + InitializeFont3, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + {0x60, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x60,}, + {0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,}, + {0x60, 0x90, 0x90, 0x10, 0x20, 0x40, 0x40, 0x80, 0xf0,}, + {0x60, 0x90, 0x90, 0x10, 0x60, 0x10, 0x90, 0x90, 0x60,}, + {0x20, 0x60, 0x60, 0xa0, 0xa0, 0xa0, 0xf0, 0x20, 0x20,}, + {0xf0, 0x80, 0x80, 0xe0, 0x90, 0x10, 0x90, 0x90, 0x60,}, + {0x60, 0x90, 0x90, 0x80, 0xe0, 0x90, 0x90, 0x90, 0x60,}, + {0xf0, 0x10, 0x10, 0x20, 0x20, 0x20, 0x40, 0x40, 0x40,}, + {0x60, 0x90, 0x90, 0x90, 0x60, 0x90, 0x90, 0x90, 0x60,}, + {0x60, 0x90, 0x90, 0x90, 0x70, 0x10, 0x90, 0x90, 0x60,} + } + }, + + // FONT-4 + { + 5, 0xf8, + {0, 6, 16, 22, 32, 38}, + InitializeFont4, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + {0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70,}, + {0x00, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70,}, + {0x00, 0x70, 0x88, 0x08, 0x08, 0x30, 0x40, 0x88, 0xf8,}, + {0x00, 0x70, 0x88, 0x08, 0x30, 0x08, 0x08, 0x08, 0xf0,}, + {0x00, 0x10, 0x30, 0x50, 0x50, 0x90, 0xf8, 0x10, 0x10,}, + {0x00, 0x38, 0x40, 0x60, 0x10, 0x08, 0x08, 0x08, 0xf0,}, + {0x00, 0x18, 0x20, 0x40, 0xb0, 0xc8, 0x88, 0x88, 0x70,}, + {0x00, 0x70, 0x88, 0x88, 0x10, 0x10, 0x10, 0x20, 0x20,}, + {0x00, 0x70, 0x88, 0x88, 0x70, 0x50, 0x88, 0x88, 0x70,}, + {0x00, 0x70, 0x88, 0x88, 0x88, 0x78, 0x10, 0x20, 0xc0,} + } + }, + + // FONT-5 + { + 5, 0xf8, + {0, 6, 17, 23, 34, 40}, + InitializeFont5, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + {0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70,}, + {0x00, 0x00, 0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20,}, + {0x00, 0x00, 0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xf8,}, + {0x00, 0x00, 0xf8, 0x10, 0x20, 0x10, 0x08, 0x88, 0x70,}, + {0x00, 0x00, 0x30, 0x50, 0x50, 0x90, 0xf8, 0x10, 0x10,}, + {0x00, 0x00, 0xf8, 0x80, 0xf0, 0x08, 0x08, 0x88, 0x70,}, + {0x00, 0x00, 0x30, 0x40, 0xf0, 0x88, 0x88, 0x88, 0x70,}, + {0x00, 0x00, 0xf8, 0x08, 0x10, 0x20, 0x20, 0x40, 0x40,}, + {0x00, 0x00, 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70,}, + {0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x78, 0x10, 0x60,} + } + }, + + // FONT-6 + { + 4, 0xf0, + {0, 5, 12, 17, 24, 29}, + InitializeFont6, + { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, + {0x00, 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x90, 0x60,}, + {0x00, 0x00, 0x00, 0x20, 0x60, 0x20, 0x20, 0x20, 0x20,}, + {0x00, 0x00, 0x00, 0x60, 0x90, 0x10, 0x20, 0x40, 0xf0,}, + {0x00, 0x00, 0x00, 0xf0, 0x20, 0x60, 0x10, 0x90, 0x60,}, + {0x00, 0x00, 0x00, 0x40, 0x80, 0xa0, 0xa0, 0xf0, 0x20,}, + {0x00, 0x00, 0x00, 0xf0, 0x80, 0x60, 0x10, 0x90, 0x60,}, + {0x00, 0x00, 0x00, 0x40, 0x80, 0xe0, 0x90, 0x90, 0x60,}, + {0x00, 0x00, 0x00, 0xe0, 0x10, 0x10, 0x20, 0x20, 0x40,}, + {0x00, 0x00, 0x00, 0x60, 0x90, 0x60, 0x90, 0x90, 0x60,}, + {0x00, 0x00, 0x00, 0x60, 0x90, 0x90, 0x70, 0x20, 0x40,} + } + } +}; + +/** + * コンストラクタ + */ +DispClock::DispClock() +{ + ZeroMemory(this, sizeof(*this)); +} + +/** + * 初期化 + */ +void DispClock::Initialize() +{ + ::pal_makegrad(m_pal32, 4, np2oscfg.clk_color1, np2oscfg.clk_color2); +} + +/** + * パレット設定 + * @param[in] bpp 色 + */ +void DispClock::SetPalettes(UINT bpp) +{ + switch (bpp) + { + case 8: + SetPalette8(); + break; + + case 16: + SetPalette16(); + break; + } +} + +/** + * 8bpp パレット設定 + */ +void DispClock::SetPalette8() +{ + for (UINT i = 0; i < 16; i++) + { + UINT nBits = 0; + for (UINT j = 1; j < 0x10; j <<= 1) + { + nBits <<= 8; + if (i & j) + { + nBits |= 1; + } + } + for (UINT j = 0; j < 4; j++) + { + m_pal8[j][i] = nBits * (START_PALORG + j); + } + } +} + +/** + * 16bpp パレット設定 + */ +void DispClock::SetPalette16() +{ + for (UINT i = 0; i < 4; i++) + { + m_pal16[i] = scrnmng_makepal16(m_pal32[i]); + } +} + +/** + * リセット + */ +void DispClock::Reset() +{ + if (np2oscfg.clk_x) + { + if (np2oscfg.clk_x <= 4) + { + np2oscfg.clk_x = 4; + } + else if (np2oscfg.clk_x <= 6) + { + np2oscfg.clk_x = 6; + } + else + { + np2oscfg.clk_x = 0; + } + } + if (np2oscfg.clk_fnt >= _countof(s_pattern)) + { + np2oscfg.clk_fnt = 0; + } + + ZeroMemory(m_cTime, sizeof(m_cTime)); + ZeroMemory(m_cLastTime, sizeof(m_cLastTime)); + ZeroMemory(m_buffer, sizeof(m_buffer)); + m_pPattern = &s_pattern[np2oscfg.clk_fnt]; + m_cCharaters = np2oscfg.clk_x; + (*m_pPattern->fnInitialize)(m_buffer, m_cCharaters); + Update(); + Redraw(); +} + +/** + * 更新 + */ +void DispClock::Update() +{ + if ((scrnmng_isfullscreen()) && (m_cCharaters)) + { + _SYSTIME st; + timemng_gettime(&st); + + UINT8 buf[6]; + buf[0] = (st.hour / 10) + 1; + buf[1] = (st.hour % 10) + 1; + buf[2] = (st.minute / 10) + 1; + buf[3] = (st.minute % 10) + 1; + if (m_cCharaters > 4) + { + buf[4] = (st.second / 10) + 1; + buf[5] = (st.second % 10) + 1; + } + + UINT8 count = 13; + for (int i = m_cCharaters; i--; ) + { + if (m_cTime[i] != buf[i]) + { + m_cTime[i] = buf[i]; + m_nCounter.b[i] = count; + m_cDirty |= (1 << i); + count += 4; + } + } + } +} + +/** + * 再描画 + */ +void DispClock::Redraw() +{ + m_cDirty = 0x3f; +} + +/** + * 描画が必要? + * @retval true 描画中 + * @retval false 非描画 + */ +bool DispClock::IsDisplayed() const +{ + return ((m_cDirty != 0) || (m_nCounter.q != 0)); +} + +//! オフセット テーブル +static const UINT8 s_dclocky[13] = {0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3}; + +/** + * 位置計算 + * @param[in] nCount カウント値 + * @return オフセット + */ +UINT8 DispClock::CountPos(UINT nCount) +{ + if (nCount < _countof(s_dclocky)) + { + return s_dclocky[nCount]; + } + else + { + return 255; + } +} + +/** + * カウントダウン処理 + * @param[in] nFrames フレーム数 + */ +void DispClock::CountDown(UINT nFrames) +{ + if ((m_cCharaters == 0) || (m_nCounter.q == 0)) + { + return; + } + + if (nFrames == 0) + { + nFrames = 1; + } + + for (UINT i = 0; i < m_cCharaters; i++) + { + UINT nRemain = m_nCounter.b[i]; + if (nRemain == 0) + { + continue; + } + const UINT8 y = CountPos(nRemain); + + if (nFrames < nRemain) + { + nRemain -= nFrames; + } + else + { + nRemain = 0; + } + if (y != CountPos(nRemain)) + { + m_cDirty |= (1 << i); + } + m_nCounter.b[i] = nRemain; + } +} + +/** + * バッファに描画 + * @retval true 更新あり + * @retval false 更新なし + */ +bool DispClock::Make() +{ + if ((m_cCharaters == 0) || (m_cDirty == 0)) + { + return false; + } + + for (UINT i = 0; i < m_cCharaters; i++) + { + if ((m_cDirty & (1 << i)) == 0) + { + continue; + } + + UINT nNumber = m_cTime[i]; + UINT nPadding = 3; + + const UINT nRemain = m_nCounter.b[i]; + if (nRemain == 0) + { + m_cLastTime[i] = nNumber; + } + else if (nRemain < _countof(s_dclocky)) + { + nPadding -= s_dclocky[nRemain]; + } + else + { + nNumber = this->m_cLastTime[i]; + } + + UINT8* q = m_buffer + (m_pPattern->cPosition[i] >> 3); + const UINT8 cShifter = m_pPattern->cPosition[i] & 7; + const UINT8 cMask0 = ~(m_pPattern->cMask >> cShifter); + const UINT8 cMask1 = ~(m_pPattern->cMask << (8 - cShifter)); + for (UINT y = 0; y < nPadding; y++) + { + q[0] = (q[0] & cMask0); + q[1] = (q[1] & cMask1); + q += DCLOCK_YALIGN; + } + + const UINT8* p = m_pPattern->font[nNumber]; + for (UINT y = 0; y < 9; y++) + { + q[0] = (q[0] & cMask0) | (p[y] >> cShifter); + q[1] = (q[1] & cMask1) | (p[y] << (8 - cShifter)); + q += DCLOCK_YALIGN; + } + } + m_cDirty = 0; + return true; +} + +/** + * 描画 + * @param[in] nBpp 色数 + * @param[out] lpBuffer 描画ポインタ + * @param[in] nYAlign アライメント + */ +void DispClock::Draw(UINT nBpp, void* lpBuffer, int nYAlign) const +{ + switch (nBpp) + { + case 8: + Draw8(lpBuffer, nYAlign); + break; + + case 16: + Draw16(lpBuffer, nYAlign); + break; + + case 24: + Draw24(lpBuffer, nYAlign); + break; + + case 32: + Draw32(lpBuffer, nYAlign); + break; + } +} + +/** + * 描画(8bpp) + * @param[out] lpBuffer 描画ポインタ + * @param[in] nYAlign アライメント + */ +void DispClock::Draw8(void* lpBuffer, int nYAlign) const +{ + const UINT8* p = m_buffer; + + for (UINT i = 0; i < 4; i++) + { + const UINT32* pPattern = m_pal8[i]; + for (UINT j = 0; j < 3; j++) + { + for (UINT x = 0; x < DCLOCK_YALIGN; x++) + { + (static_cast(lpBuffer))[x * 2 + 0] = pPattern[p[x] >> 4]; + (static_cast(lpBuffer))[x * 2 + 1] = pPattern[p[x] & 15]; + } + p += DCLOCK_YALIGN; + lpBuffer = reinterpret_cast(reinterpret_cast(lpBuffer) + nYAlign); + } + } +} + +/** + * 描画(16bpp) + * @param[out] lpBuffer 描画ポインタ + * @param[in] nYAlign アライメント + */ +void DispClock::Draw16(void* lpBuffer, int nYAlign) const +{ + const UINT8* p = m_buffer; + + for (UINT i = 0; i < 4; i++) + { + const RGB16 pal = m_pal16[i]; + for (UINT j = 0; j < 3; j++) + { + for (UINT x = 0; x < (8 * DCLOCK_YALIGN); x++) + { + (static_cast(lpBuffer))[x] = (p[x >> 3] & (0x80 >> (x & 7))) ? pal : 0; + } + p += DCLOCK_YALIGN; + lpBuffer = reinterpret_cast(reinterpret_cast(lpBuffer) + nYAlign); + } + } +} + +/** + * 描画(24bpp) + * @param[out] lpBuffer 描画ポインタ + * @param[in] nYAlign アライメント + */ +void DispClock::Draw24(void* lpBuffer, int nYAlign) const +{ + const UINT8* p = m_buffer; + UINT8* q = static_cast(lpBuffer); + + for (UINT i = 0; i < 4; i++) + { + const RGB32 pal = m_pal32[i]; + for (UINT j = 0; j < 3; j++) + { + for (UINT x = 0; x < (8 * DCLOCK_YALIGN); x++) + { + if (p[x >> 3] & (0x80 >> (x & 7))) + { + q[0] = pal.p.b; + q[1] = pal.p.g; + q[2] = pal.p.g; + } + else + { + q[0] = 0; + q[1] = 1; + q[2] = 2; + } + q += 3; + } + p += DCLOCK_YALIGN; + q += nYAlign - (8 * DCLOCK_YALIGN) * 3; + } + } +} + +/** + * 描画(32bpp) + * @param[out] lpBuffer 描画ポインタ + * @param[in] nYAlign アライメント + */ +void DispClock::Draw32(void* lpBuffer, int nYAlign) const +{ + const UINT8* p = m_buffer; + + for (UINT i = 0; i < 4; i++) + { + const UINT32 pal = m_pal32[i].d; + for (UINT j = 0; j < 3; j++) + { + for (UINT x = 0; x < (8 * DCLOCK_YALIGN); x++) + { + (static_cast(lpBuffer))[x] = (p[x >> 3] & (0x80 >> (x & 7))) ? pal : 0; + } + p += DCLOCK_YALIGN; + lpBuffer = reinterpret_cast(reinterpret_cast(lpBuffer) + nYAlign); + } + } +} diff --git a/windows/subwnd/dclock.h b/windows/subwnd/dclock.h old mode 100755 new mode 100644 index dd2bbe74..7b045895 --- a/windows/subwnd/dclock.h +++ b/windows/subwnd/dclock.h @@ -1,86 +1,86 @@ -/** - * @file dclock.h - * @brief 時刻表示クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -enum -{ - DCLOCK_WIDTH = 56, - DCLOCK_HEIGHT = 12, - DCLOCK_YALIGN = (56 / 8) -}; - -struct DispClockPattern; - -/** - * @brief 時刻表示クラス - */ -class DispClock -{ -public: - static DispClock* GetInstance(); - - DispClock(); - void Initialize(); - void SetPalettes(UINT bpp); - const RGB32* GetPalettes() const; - void Reset(); - void Update(); - void Redraw(); - bool IsDisplayed() const; - void CountDown(UINT nFrames); - bool Make(); - void Draw(UINT nBpp, void* lpBuffer, int nYAlign) const; - -private: - static DispClock sm_instance; //!< 唯一のインスタンスです - - /** - * @brief QuadBytes - */ - union QuadBytes - { - UINT8 b[8]; //!< bytes - UINT64 q; //!< quad - }; - - const DispClockPattern* m_pPattern; //!< パターン - QuadBytes m_nCounter; //!< カウンタ - UINT8 m_cTime[8]; //!< 現在時間 - UINT8 m_cLastTime[8]; //!< 最後の時間 - UINT8 m_cDirty; //!< 描画フラグ drawing; - UINT8 m_cCharaters; //!< 文字数 - RGB32 m_pal32[4]; //!< パレット - RGB16 m_pal16[4]; //!< パレット - UINT32 m_pal8[4][16]; //!< パレット パターン - UINT8 m_buffer[(DCLOCK_HEIGHT * DCLOCK_YALIGN) + 4]; /*!< バッファ */ - -private: - void SetPalette8(); - void SetPalette16(); - static UINT8 CountPos(UINT nCount); - void Draw8(void* lpBuffer, int nYAlign) const; - void Draw16(void* lpBuffer, int nYAlign) const; - void Draw24(void* lpBuffer, int nYAlign) const; - void Draw32(void* lpBuffer, int nYAlign) const; -}; - -/** - * インスタンスを得る - * @return インスタンス - */ -inline DispClock* DispClock::GetInstance() -{ - return &sm_instance; -} - -/** - * パレットを得る - * @return パレット - */ -inline const RGB32* DispClock::GetPalettes() const -{ - return m_pal32; -} +/** + * @file dclock.h + * @brief 時刻表示クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +enum +{ + DCLOCK_WIDTH = 56, + DCLOCK_HEIGHT = 12, + DCLOCK_YALIGN = (56 / 8) +}; + +struct DispClockPattern; + +/** + * @brief 時刻表示クラス + */ +class DispClock +{ +public: + static DispClock* GetInstance(); + + DispClock(); + void Initialize(); + void SetPalettes(UINT bpp); + const RGB32* GetPalettes() const; + void Reset(); + void Update(); + void Redraw(); + bool IsDisplayed() const; + void CountDown(UINT nFrames); + bool Make(); + void Draw(UINT nBpp, void* lpBuffer, int nYAlign) const; + +private: + static DispClock sm_instance; //!< 唯一のインスタンスです + + /** + * @brief QuadBytes + */ + union QuadBytes + { + UINT8 b[8]; //!< bytes + UINT64 q; //!< quad + }; + + const DispClockPattern* m_pPattern; //!< パターン + QuadBytes m_nCounter; //!< カウンタ + UINT8 m_cTime[8]; //!< 現在時間 + UINT8 m_cLastTime[8]; //!< 最後の時間 + UINT8 m_cDirty; //!< 描画フラグ drawing; + UINT8 m_cCharaters; //!< 文字数 + RGB32 m_pal32[4]; //!< パレット + RGB16 m_pal16[4]; //!< パレット + UINT32 m_pal8[4][16]; //!< パレット パターン + UINT8 m_buffer[(DCLOCK_HEIGHT * DCLOCK_YALIGN) + 4]; /*!< バッファ */ + +private: + void SetPalette8(); + void SetPalette16(); + static UINT8 CountPos(UINT nCount); + void Draw8(void* lpBuffer, int nYAlign) const; + void Draw16(void* lpBuffer, int nYAlign) const; + void Draw24(void* lpBuffer, int nYAlign) const; + void Draw32(void* lpBuffer, int nYAlign) const; +}; + +/** + * インスタンスを得る + * @return インスタンス + */ +inline DispClock* DispClock::GetInstance() +{ + return &sm_instance; +} + +/** + * パレットを得る + * @return パレット + */ +inline const RGB32* DispClock::GetPalettes() const +{ + return m_pal32; +} diff --git a/windows/subwnd/dd2.cpp b/windows/subwnd/dd2.cpp index 286020e5..ee548660 100644 --- a/windows/subwnd/dd2.cpp +++ b/windows/subwnd/dd2.cpp @@ -1,6 +1,6 @@ /** * @file dd2.cpp - * @brief DirectDraw2 `NX̓̒`s܂ + * @brief DirectDraw2 描画クラスの動作の定義を行います */ #include "compiler.h" @@ -12,7 +12,7 @@ #endif // !defined(__GNUC__) /** - * RXgN^ + * コンストラクタ */ DD2Surface::DD2Surface() : m_hWnd(NULL) @@ -32,7 +32,7 @@ DD2Surface::DD2Surface() } /** - * fXgN^ + * デストラクタ */ DD2Surface::~DD2Surface() { @@ -40,12 +40,12 @@ DD2Surface::~DD2Surface() } /** - * 쐬 - * @param[in] hWnd EBhE nh - * @param[in] nWidth - * @param[in] nHeight - * @retval true - * @retval false s + * 作成 + * @param[in] hWnd ウィンドウ ハンドル + * @param[in] nWidth 幅 + * @param[in] nHeight 高さ + * @retval true 成功 + * @retval false 失敗 */ bool DD2Surface::Create(HWND hWnd, int nWidth, int nHeight) { @@ -158,7 +158,7 @@ bool DD2Surface::Create(HWND hWnd, int nWidth, int nHeight) } /** - * + * 解放 */ void DD2Surface::Release() { @@ -195,8 +195,8 @@ void DD2Surface::Release() } /** - * obt@ bN - * @return obt@ + * バッファ ロック + * @return バッファ */ CMNVRAM* DD2Surface::Lock() { @@ -223,7 +223,7 @@ CMNVRAM* DD2Surface::Lock() } /** - * obt@ AbN + * バッファ アンロック */ void DD2Surface::Unlock() { @@ -235,8 +235,8 @@ void DD2Surface::Unlock() /** * blt - * @param[in] pt ʒu - * @param[in] lpRect ̈ + * @param[in] pt 位置 + * @param[in] lpRect 領域 */ void DD2Surface::Blt(const POINT* pt, const RECT* lpRect) { @@ -268,8 +268,8 @@ void DD2Surface::Blt(const POINT* pt, const RECT* lpRect) /** * blt - * @param[in] pt ʒu - * @param[in] lpRect ̈ + * @param[in] pt 位置 + * @param[in] lpRect 領域 */ void DD2Surface::Blt(const POINT* pt, const RECT* lpDstRect, const RECT* lpSrcRect) { @@ -300,9 +300,9 @@ void DD2Surface::Blt(const POINT* pt, const RECT* lpDstRect, const RECT* lpSrcRe } /** - * 16BPP F𓾂 - * @param[in] pal F - * @return 16BPPF + * 16BPP 色を得る + * @param[in] pal 色 + * @return 16BPP色 */ UINT16 DD2Surface::GetPalette16(RGB32 pal) const { diff --git a/windows/subwnd/dd2.h b/windows/subwnd/dd2.h index 98fe7cb0..b582612e 100644 --- a/windows/subwnd/dd2.h +++ b/windows/subwnd/dd2.h @@ -1,6 +1,6 @@ /** * @file dd2.h - * @brief DirectDraw2 `NX̐錾уC^[tFCX̒`܂ + * @brief DirectDraw2 描画クラスの宣言およびインターフェイスの定義をします */ #pragma once @@ -26,17 +26,17 @@ class DD2Surface UINT16 GetPalette16(RGB32 pal) const; protected: - HWND m_hWnd; /*!< EBhE nh */ - LPDIRECTDRAW m_pDDraw; /*!< DirectDraw CX^X */ - LPDIRECTDRAW2 m_pDDraw2; /*!< DirectDraw2 CX^X */ - LPDIRECTDRAWSURFACE m_pPrimarySurface; /*!< vC} T[tFX */ - LPDIRECTDRAWSURFACE m_pBackSurface; /*!< obN T[tFX */ - LPDIRECTDRAWCLIPPER m_pClipper; /*!< Nbp[ */ - LPDIRECTDRAWPALETTE m_pPalette; /*!< pbg */ - RGB32 m_pal16; /*!< 16BPP}XN */ - UINT8 m_r16b; /*!< B Vtg */ - UINT8 m_l16r; /*!< R Vtg */ - UINT8 m_l16g; /*!< G Vtg */ + HWND m_hWnd; /*!< ウィンドウ ハンドル */ + LPDIRECTDRAW m_pDDraw; /*!< DirectDraw インスタンス */ + LPDIRECTDRAW2 m_pDDraw2; /*!< DirectDraw2 インスタンス */ + LPDIRECTDRAWSURFACE m_pPrimarySurface; /*!< プライマリ サーフェス */ + LPDIRECTDRAWSURFACE m_pBackSurface; /*!< バック サーフェス */ + LPDIRECTDRAWCLIPPER m_pClipper; /*!< クリッパー */ + LPDIRECTDRAWPALETTE m_pPalette; /*!< パレット */ + RGB32 m_pal16; /*!< 16BPPマスク */ + UINT8 m_r16b; /*!< B シフト量 */ + UINT8 m_l16r; /*!< R シフト量 */ + UINT8 m_l16g; /*!< G シフト量 */ CMNVRAM m_vram; /*!< VRAM */ - PALETTEENTRY m_pal[256]; /*!< pbg */ + PALETTEENTRY m_pal[256]; /*!< パレット */ }; diff --git a/windows/subwnd/kdispwnd.cpp b/windows/subwnd/kdispwnd.cpp old mode 100755 new mode 100644 index e2474bdd..e5b8a884 --- a/windows/subwnd/kdispwnd.cpp +++ b/windows/subwnd/kdispwnd.cpp @@ -1,419 +1,419 @@ -/** - * @file kdispwnd.cpp - * @brief キーボード クラスの動作の定義を行います - */ - -#include -#include "resource.h" -#include "kdispwnd.h" -#include -#include -#include "menu.h" -#include "winloc.h" -#include -#include -#include - -extern WINLOCEX np2_winlocexallwin(HWND base); - -#if defined(SUPPORT_KEYDISP) - -//! 唯一のインスタンスです -CKeyDisplayWnd CKeyDisplayWnd::sm_instance; - -/** - * モード - */ -enum -{ - KDISPCFG_FM = 0x00, - KDISPCFG_MIDI = 0x80 -}; - -/** - * @brief コンフィグ - */ -struct KeyDisplayConfig -{ - int posx; //!< X - int posy; //!< Y - UINT8 mode; //!< モード - UINT8 type; //!< ウィンドウ タイプ -}; - -//! コンフィグ -static KeyDisplayConfig s_kdispcfg; - -//! タイトル -static const TCHAR s_kdispapp[] = TEXT("Key Display"); - -/** - * 設定 - */ -static const PFTBL s_kdispini[] = -{ - PFVAL("WindposX", PFTYPE_SINT32, &s_kdispcfg.posx), - PFVAL("WindposY", PFTYPE_SINT32, &s_kdispcfg.posy), - PFVAL("keydmode", PFTYPE_UINT8, &s_kdispcfg.mode), - PFVAL("windtype", PFTYPE_BOOL, &s_kdispcfg.type) -}; - -//! パレット -static const UINT32 s_kdisppal[KEYDISP_PALS] = {0x00000000, 0xffffffff, 0xf9ff0000}; - -/** - * 初期化 - */ -void CKeyDisplayWnd::Initialize() -{ - keydisp_initialize(); -} - -/** - * 解放 - */ -void CKeyDisplayWnd::Deinitialize() -{ -} - -/** - * コンストラクタ - */ -CKeyDisplayWnd::CKeyDisplayWnd() -{ -} - -/** - * デストラクタ - */ -CKeyDisplayWnd::~CKeyDisplayWnd() -{ -} - -/** - * 8bpp色を返す - * @param[in] self インスタンス - * @param[in] num パレット番号 - * @return 色 - */ -static UINT8 kdgetpal8(CMNPALFN* self, UINT num) -{ - if (num < KEYDISP_PALS) - { - return s_kdisppal[num] >> 24; - } - return 0; -} - -/** - * 16bpp色を返す - * @param[in] self インスタンス - * @param[in] pal32 パレット - * @return 色 - */ -static UINT16 kdcnvpal16(CMNPALFN* self, RGB32 pal32) -{ - return (reinterpret_cast(self->userdata))->GetPalette16(pal32); -} - -/** - * 32bpp色を返す - * @param[in] self インスタンス - * @param[in] num パレット番号 - * @return 色 - */ -static UINT32 kdgetpal32(CMNPALFN* self, UINT num) -{ - if (num < KEYDISP_PALS) - { - return s_kdisppal[num] & 0xffffff; - } - return 0; -} - -/** - * 作成 - */ -void CKeyDisplayWnd::Create() -{ - if (m_hWnd != NULL) - { - return; - } - - HINSTANCE hInstance = FindResourceHandle(MAKEINTRESOURCE(IDR_KEYDISP), RT_MENU); - HMENU hMenu = ::LoadMenu(hInstance, MAKEINTRESOURCE(IDR_KEYDISP)); - if (!CSubWndBase::Create(IDS_CAPTION_KEYDISP, WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, s_kdispcfg.posx, s_kdispcfg.posy, KEYDISP_WIDTH, KEYDISP_HEIGHT, NULL, hMenu)) - { - np2oscfg.keydisp = 0; - sysmng_update(SYS_UPDATEOSCFG); - return; - } - - UINT8 mode; - switch (s_kdispcfg.mode) - { - case KDISPCFG_FM: - default: - mode = KEYDISP_MODEFM; - break; - - case KDISPCFG_MIDI: - mode = KEYDISP_MODEMIDI; - break; - } - SetDispMode(mode); - ShowWindow(SW_SHOWNOACTIVATE); - UpdateWindow(); - - if (!m_dd2.Create(m_hWnd, KEYDISP_WIDTH, KEYDISP_HEIGHT)) - { - DestroyWindow(); - return; - } - - CMNPALFN palfn; - palfn.get8 = kdgetpal8; - palfn.get32 = kdgetpal32; - palfn.cnv16 = kdcnvpal16; - palfn.userdata = reinterpret_cast(&m_dd2); - keydisp_setpal(&palfn); - kdispwin_draw(0); - ::SetForegroundWindow(g_hWndMain); -} - -/** - * 描画する - * @param[in] cnt 進んだフレーム - */ -void CKeyDisplayWnd::Draw(UINT8 cnt) -{ - if (m_hWnd) - { - if (!cnt) - { - cnt = 1; - } - UINT8 flag = keydisp_process(cnt); - if (flag & KEYDISP_FLAGSIZING) - { - OnResize(); - } - OnDraw(FALSE); - } -} - -/** - * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT CKeyDisplayWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - switch (nMsg) - { - case WM_CREATE: - np2class_wmcreate(m_hWnd); - np2class_windowtype(m_hWnd, (s_kdispcfg.type & 1) << 1); - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDM_KDISPFM: - s_kdispcfg.mode = KDISPCFG_FM; - sysmng_update(SYS_UPDATEOSCFG); - SetDispMode(KEYDISP_MODEFM); - break; - - case IDM_KDISPMIDI: - s_kdispcfg.mode = KDISPCFG_MIDI; - sysmng_update(SYS_UPDATEOSCFG); - SetDispMode(KEYDISP_MODEMIDI); - break; - - case IDM_CLOSE: - return SendMessage(WM_CLOSE, 0, 0); - } - break; - - case WM_PAINT: - OnPaint(); - break; - - case WM_LBUTTONDOWN: - if (s_kdispcfg.type & 1) - { - return SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, 0L); - } - break; - - case WM_RBUTTONDOWN: - { - POINT pt; - pt.x = GET_X_LPARAM(lParam); - pt.y = GET_Y_LPARAM(lParam); - OnRButtonDown(static_cast(wParam), pt); - } - break; - - case WM_LBUTTONDBLCLK: - s_kdispcfg.type ^= 1; - SetWndType((s_kdispcfg.type & 1) << 1); - sysmng_update(SYS_UPDATEOSCFG); - break; - - case WM_MOVE: - if (!(GetWindowLong(m_hWnd, GWL_STYLE) & (WS_MAXIMIZE | WS_MINIMIZE))) - { - RECT rc; - GetWindowRect(&rc); - s_kdispcfg.posx = rc.left; - s_kdispcfg.posy = rc.top; - sysmng_update(SYS_UPDATEOSCFG); - } - break; - - case WM_CLOSE: - np2oscfg.keydisp = 0; - sysmng_update(SYS_UPDATEOSCFG); - DestroyWindow(); - break; - - case WM_DESTROY: - OnDestroy(); - break; - - default: - return CSubWndBase::WindowProc(nMsg, wParam, lParam); - } - return 0L; -} - -/** - * ウィンドウ破棄の時に呼ばれる - */ -void CKeyDisplayWnd::OnDestroy() -{ - ::np2class_wmdestroy(m_hWnd); - m_dd2.Release(); - SetDispMode(KEYDISP_MODENONE); -} - -/** - * フレームワークは、ユーザーがマウスの右ボタンを押すと、このメンバー関数を呼び出します - * @param[in] nFlags 仮想キーが押されているかどうかを示します - * @param[in] point カーソルの x 座標と y 座標を指定します - */ -void CKeyDisplayWnd::OnRButtonDown(UINT nFlags, POINT point) -{ - HMENU hMenu = CreatePopupMenu(); - menu_addmenu(hMenu, 0, np2class_gethmenu(m_hWnd), FALSE); - menu_addmenures(hMenu, -1, IDR_CLOSE, TRUE); - - ClientToScreen(&point); - ::TrackPopupMenu(hMenu, TPM_LEFTALIGN, point.x, point.y, 0, m_hWnd, NULL); - ::DestroyMenu(hMenu); -} - -/** - * 描画の時に呼ばれる - */ -void CKeyDisplayWnd::OnPaint() -{ - PAINTSTRUCT ps; - HDC hdc = BeginPaint(&ps); - OnDraw(TRUE); - EndPaint(&ps); -} - -/** - * 描画 - * @param[in] redraw 再描画 - */ -void CKeyDisplayWnd::OnDraw(BOOL redraw) -{ - RECT rect; - GetClientRect(&rect); - - RECT draw; - draw.left = 0; - draw.top = 0; - draw.right = min(KEYDISP_WIDTH, rect.right - rect.left); - draw.bottom = min(KEYDISP_HEIGHT, rect.bottom - rect.top); - if ((draw.right <= 0) || (draw.bottom <= 0)) - { - return; - } - CMNVRAM* vram = m_dd2.Lock(); - if (vram) - { - keydisp_paint(vram, redraw); - m_dd2.Unlock(); - m_dd2.Blt(NULL, &draw); - } -} - -/** - * リサイズ - */ -void CKeyDisplayWnd::OnResize() -{ - WINLOCEX wlex = np2_winlocexallwin(g_hWndMain); - winlocex_setholdwnd(wlex, m_hWnd); - - int width; - int height; - keydisp_getsize(&width, &height); - winloc_setclientsize(m_hWnd, width, height); - winlocex_move(wlex); - winlocex_destroy(wlex); -} - -/** - * モード チェンジ - * @param[in] mode モード - */ -void CKeyDisplayWnd::SetDispMode(UINT8 mode) -{ - keydisp_setmode(mode); - - HMENU hMenu = np2class_gethmenu(m_hWnd); - CheckMenuItem(hMenu, IDM_KDISPFM, ((mode == KEYDISP_MODEFM) ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(hMenu, IDM_KDISPMIDI, ((mode == KEYDISP_MODEMIDI) ? MF_CHECKED : MF_UNCHECKED)); -} - -void kdispwin_create(){ - keydisp_setresizeflag(); - CKeyDisplayWnd::GetInstance()->Create(); -} - -/** - * 設定読み込み - */ -void kdispwin_readini() -{ - ZeroMemory(&s_kdispcfg, sizeof(s_kdispcfg)); - s_kdispcfg.posx = CW_USEDEFAULT; - s_kdispcfg.posy = CW_USEDEFAULT; - - TCHAR szPath[MAX_PATH]; - initgetfile(szPath, _countof(szPath)); - ini_read(szPath, s_kdispapp, s_kdispini, _countof(s_kdispini)); -} - -/** - * 設定書き込み - */ -void kdispwin_writeini() -{ - if(!np2oscfg.readonly){ - TCHAR szPath[MAX_PATH]; - - initgetfile(szPath, _countof(szPath)); - ini_write(szPath, s_kdispapp, s_kdispini, _countof(s_kdispini)); - } -} -#endif +/** + * @file kdispwnd.cpp + * @brief キーボード クラスの動作の定義を行います + */ + +#include +#include "resource.h" +#include "kdispwnd.h" +#include +#include +#include "menu.h" +#include "winloc.h" +#include +#include +#include + +extern WINLOCEX np2_winlocexallwin(HWND base); + +#if defined(SUPPORT_KEYDISP) + +//! 唯一のインスタンスです +CKeyDisplayWnd CKeyDisplayWnd::sm_instance; + +/** + * モード + */ +enum +{ + KDISPCFG_FM = 0x00, + KDISPCFG_MIDI = 0x80 +}; + +/** + * @brief コンフィグ + */ +struct KeyDisplayConfig +{ + int posx; //!< X + int posy; //!< Y + UINT8 mode; //!< モード + UINT8 type; //!< ウィンドウ タイプ +}; + +//! コンフィグ +static KeyDisplayConfig s_kdispcfg; + +//! タイトル +static const TCHAR s_kdispapp[] = TEXT("Key Display"); + +/** + * 設定 + */ +static const PFTBL s_kdispini[] = +{ + PFVAL("WindposX", PFTYPE_SINT32, &s_kdispcfg.posx), + PFVAL("WindposY", PFTYPE_SINT32, &s_kdispcfg.posy), + PFVAL("keydmode", PFTYPE_UINT8, &s_kdispcfg.mode), + PFVAL("windtype", PFTYPE_BOOL, &s_kdispcfg.type) +}; + +//! パレット +static const UINT32 s_kdisppal[KEYDISP_PALS] = {0x00000000, 0xffffffff, 0xf9ff0000}; + +/** + * 初期化 + */ +void CKeyDisplayWnd::Initialize() +{ + keydisp_initialize(); +} + +/** + * 解放 + */ +void CKeyDisplayWnd::Deinitialize() +{ +} + +/** + * コンストラクタ + */ +CKeyDisplayWnd::CKeyDisplayWnd() +{ +} + +/** + * デストラクタ + */ +CKeyDisplayWnd::~CKeyDisplayWnd() +{ +} + +/** + * 8bpp色を返す + * @param[in] self インスタンス + * @param[in] num パレット番号 + * @return 色 + */ +static UINT8 kdgetpal8(CMNPALFN* self, UINT num) +{ + if (num < KEYDISP_PALS) + { + return s_kdisppal[num] >> 24; + } + return 0; +} + +/** + * 16bpp色を返す + * @param[in] self インスタンス + * @param[in] pal32 パレット + * @return 色 + */ +static UINT16 kdcnvpal16(CMNPALFN* self, RGB32 pal32) +{ + return (reinterpret_cast(self->userdata))->GetPalette16(pal32); +} + +/** + * 32bpp色を返す + * @param[in] self インスタンス + * @param[in] num パレット番号 + * @return 色 + */ +static UINT32 kdgetpal32(CMNPALFN* self, UINT num) +{ + if (num < KEYDISP_PALS) + { + return s_kdisppal[num] & 0xffffff; + } + return 0; +} + +/** + * 作成 + */ +void CKeyDisplayWnd::Create() +{ + if (m_hWnd != NULL) + { + return; + } + + HINSTANCE hInstance = FindResourceHandle(MAKEINTRESOURCE(IDR_KEYDISP), RT_MENU); + HMENU hMenu = ::LoadMenu(hInstance, MAKEINTRESOURCE(IDR_KEYDISP)); + if (!CSubWndBase::Create(IDS_CAPTION_KEYDISP, WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, s_kdispcfg.posx, s_kdispcfg.posy, KEYDISP_WIDTH, KEYDISP_HEIGHT, NULL, hMenu)) + { + np2oscfg.keydisp = 0; + sysmng_update(SYS_UPDATEOSCFG); + return; + } + + UINT8 mode; + switch (s_kdispcfg.mode) + { + case KDISPCFG_FM: + default: + mode = KEYDISP_MODEFM; + break; + + case KDISPCFG_MIDI: + mode = KEYDISP_MODEMIDI; + break; + } + SetDispMode(mode); + ShowWindow(SW_SHOWNOACTIVATE); + UpdateWindow(); + + if (!m_dd2.Create(m_hWnd, KEYDISP_WIDTH, KEYDISP_HEIGHT)) + { + DestroyWindow(); + return; + } + + CMNPALFN palfn; + palfn.get8 = kdgetpal8; + palfn.get32 = kdgetpal32; + palfn.cnv16 = kdcnvpal16; + palfn.userdata = reinterpret_cast(&m_dd2); + keydisp_setpal(&palfn); + kdispwin_draw(0); + ::SetForegroundWindow(g_hWndMain); +} + +/** + * 描画する + * @param[in] cnt 進んだフレーム + */ +void CKeyDisplayWnd::Draw(UINT8 cnt) +{ + if (m_hWnd) + { + if (!cnt) + { + cnt = 1; + } + UINT8 flag = keydisp_process(cnt); + if (flag & KEYDISP_FLAGSIZING) + { + OnResize(); + } + OnDraw(FALSE); + } +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CKeyDisplayWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + switch (nMsg) + { + case WM_CREATE: + np2class_wmcreate(m_hWnd); + np2class_windowtype(m_hWnd, (s_kdispcfg.type & 1) << 1); + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDM_KDISPFM: + s_kdispcfg.mode = KDISPCFG_FM; + sysmng_update(SYS_UPDATEOSCFG); + SetDispMode(KEYDISP_MODEFM); + break; + + case IDM_KDISPMIDI: + s_kdispcfg.mode = KDISPCFG_MIDI; + sysmng_update(SYS_UPDATEOSCFG); + SetDispMode(KEYDISP_MODEMIDI); + break; + + case IDM_CLOSE: + return SendMessage(WM_CLOSE, 0, 0); + } + break; + + case WM_PAINT: + OnPaint(); + break; + + case WM_LBUTTONDOWN: + if (s_kdispcfg.type & 1) + { + return SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, 0L); + } + break; + + case WM_RBUTTONDOWN: + { + POINT pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + OnRButtonDown(static_cast(wParam), pt); + } + break; + + case WM_LBUTTONDBLCLK: + s_kdispcfg.type ^= 1; + SetWndType((s_kdispcfg.type & 1) << 1); + sysmng_update(SYS_UPDATEOSCFG); + break; + + case WM_MOVE: + if (!(GetWindowLong(m_hWnd, GWL_STYLE) & (WS_MAXIMIZE | WS_MINIMIZE))) + { + RECT rc; + GetWindowRect(&rc); + s_kdispcfg.posx = rc.left; + s_kdispcfg.posy = rc.top; + sysmng_update(SYS_UPDATEOSCFG); + } + break; + + case WM_CLOSE: + np2oscfg.keydisp = 0; + sysmng_update(SYS_UPDATEOSCFG); + DestroyWindow(); + break; + + case WM_DESTROY: + OnDestroy(); + break; + + default: + return CSubWndBase::WindowProc(nMsg, wParam, lParam); + } + return 0L; +} + +/** + * ウィンドウ破棄の時に呼ばれる + */ +void CKeyDisplayWnd::OnDestroy() +{ + ::np2class_wmdestroy(m_hWnd); + m_dd2.Release(); + SetDispMode(KEYDISP_MODENONE); +} + +/** + * フレームワークは、ユーザーがマウスの右ボタンを押すと、このメンバー関数を呼び出します + * @param[in] nFlags 仮想キーが押されているかどうかを示します + * @param[in] point カーソルの x 座標と y 座標を指定します + */ +void CKeyDisplayWnd::OnRButtonDown(UINT nFlags, POINT point) +{ + HMENU hMenu = CreatePopupMenu(); + menu_addmenu(hMenu, 0, np2class_gethmenu(m_hWnd), FALSE); + menu_addmenures(hMenu, -1, IDR_CLOSE, TRUE); + + ClientToScreen(&point); + ::TrackPopupMenu(hMenu, TPM_LEFTALIGN, point.x, point.y, 0, m_hWnd, NULL); + ::DestroyMenu(hMenu); +} + +/** + * 描画の時に呼ばれる + */ +void CKeyDisplayWnd::OnPaint() +{ + PAINTSTRUCT ps; + HDC hdc = BeginPaint(&ps); + OnDraw(TRUE); + EndPaint(&ps); +} + +/** + * 描画 + * @param[in] redraw 再描画 + */ +void CKeyDisplayWnd::OnDraw(BOOL redraw) +{ + RECT rect; + GetClientRect(&rect); + + RECT draw; + draw.left = 0; + draw.top = 0; + draw.right = min(KEYDISP_WIDTH, rect.right - rect.left); + draw.bottom = min(KEYDISP_HEIGHT, rect.bottom - rect.top); + if ((draw.right <= 0) || (draw.bottom <= 0)) + { + return; + } + CMNVRAM* vram = m_dd2.Lock(); + if (vram) + { + keydisp_paint(vram, redraw); + m_dd2.Unlock(); + m_dd2.Blt(NULL, &draw); + } +} + +/** + * リサイズ + */ +void CKeyDisplayWnd::OnResize() +{ + WINLOCEX wlex = np2_winlocexallwin(g_hWndMain); + winlocex_setholdwnd(wlex, m_hWnd); + + int width; + int height; + keydisp_getsize(&width, &height); + winloc_setclientsize(m_hWnd, width, height); + winlocex_move(wlex); + winlocex_destroy(wlex); +} + +/** + * モード チェンジ + * @param[in] mode モード + */ +void CKeyDisplayWnd::SetDispMode(UINT8 mode) +{ + keydisp_setmode(mode); + + HMENU hMenu = np2class_gethmenu(m_hWnd); + CheckMenuItem(hMenu, IDM_KDISPFM, ((mode == KEYDISP_MODEFM) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(hMenu, IDM_KDISPMIDI, ((mode == KEYDISP_MODEMIDI) ? MF_CHECKED : MF_UNCHECKED)); +} + +void kdispwin_create(){ + keydisp_setresizeflag(); + CKeyDisplayWnd::GetInstance()->Create(); +} + +/** + * 設定読み込み + */ +void kdispwin_readini() +{ + ZeroMemory(&s_kdispcfg, sizeof(s_kdispcfg)); + s_kdispcfg.posx = CW_USEDEFAULT; + s_kdispcfg.posy = CW_USEDEFAULT; + + TCHAR szPath[MAX_PATH]; + initgetfile(szPath, _countof(szPath)); + ini_read(szPath, s_kdispapp, s_kdispini, _countof(s_kdispini)); +} + +/** + * 設定書き込み + */ +void kdispwin_writeini() +{ + if(!np2oscfg.readonly){ + TCHAR szPath[MAX_PATH]; + + initgetfile(szPath, _countof(szPath)); + ini_write(szPath, s_kdispapp, s_kdispini, _countof(s_kdispini)); + } +} +#endif diff --git a/windows/subwnd/kdispwnd.h b/windows/subwnd/kdispwnd.h old mode 100755 new mode 100644 index c1920b46..ce34d7ee --- a/windows/subwnd/kdispwnd.h +++ b/windows/subwnd/kdispwnd.h @@ -1,68 +1,68 @@ -/** - * @file kdispwnd.h - * @brief キーボード クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#if defined(SUPPORT_KEYDISP) - -#include "dd2.h" -#include "subwnd.h" - -/** - * @brief キーボード - */ -class CKeyDisplayWnd : public CSubWndBase -{ -public: - static CKeyDisplayWnd* GetInstance(); - static void Initialize(); - static void Deinitialize(); - CKeyDisplayWnd(); - virtual ~CKeyDisplayWnd(); - void Create(); - void Draw(UINT8 cnt); - -protected: - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - void OnDestroy(); - void OnRButtonDown(UINT nFlags, POINT point); - void OnPaint(); - -private: - static CKeyDisplayWnd sm_instance; //!< インスタンス - DD2Surface m_dd2; //!< DirectDraw2 インスタンス - void OnDraw(BOOL redraw); - void OnResize(); - void SetDispMode(UINT8 mode); -}; - -/** - * インスタンスを返す - * @return インスタンス - */ -inline CKeyDisplayWnd* CKeyDisplayWnd::GetInstance() -{ - return &sm_instance; -} - -#define kdispwin_initialize CKeyDisplayWnd::Initialize -void kdispwin_create(); -#define kdispwin_destroy CKeyDisplayWnd::GetInstance()->DestroyWindow -#define kdispwin_gethwnd CKeyDisplayWnd::GetInstance()->GetSafeHwnd -#define kdispwin_draw CKeyDisplayWnd::GetInstance()->Draw -void kdispwin_readini(); -void kdispwin_writeini(); - -#else - -#define kdispwin_initialize() -#define kdispwin_create() -#define kdispwin_destroy() -#define kdispwin_gethwnd() (NULL) -#define kdispwin_draw(c) -#define kdispwin_readini() -#define kdispwin_writeini() - -#endif +/** + * @file kdispwnd.h + * @brief キーボード クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#if defined(SUPPORT_KEYDISP) + +#include "dd2.h" +#include "subwnd.h" + +/** + * @brief キーボード + */ +class CKeyDisplayWnd : public CSubWndBase +{ +public: + static CKeyDisplayWnd* GetInstance(); + static void Initialize(); + static void Deinitialize(); + CKeyDisplayWnd(); + virtual ~CKeyDisplayWnd(); + void Create(); + void Draw(UINT8 cnt); + +protected: + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + void OnDestroy(); + void OnRButtonDown(UINT nFlags, POINT point); + void OnPaint(); + +private: + static CKeyDisplayWnd sm_instance; //!< インスタンス + DD2Surface m_dd2; //!< DirectDraw2 インスタンス + void OnDraw(BOOL redraw); + void OnResize(); + void SetDispMode(UINT8 mode); +}; + +/** + * インスタンスを返す + * @return インスタンス + */ +inline CKeyDisplayWnd* CKeyDisplayWnd::GetInstance() +{ + return &sm_instance; +} + +#define kdispwin_initialize CKeyDisplayWnd::Initialize +void kdispwin_create(); +#define kdispwin_destroy CKeyDisplayWnd::GetInstance()->DestroyWindow +#define kdispwin_gethwnd CKeyDisplayWnd::GetInstance()->GetSafeHwnd +#define kdispwin_draw CKeyDisplayWnd::GetInstance()->Draw +void kdispwin_readini(); +void kdispwin_writeini(); + +#else + +#define kdispwin_initialize() +#define kdispwin_create() +#define kdispwin_destroy() +#define kdispwin_gethwnd() (NULL) +#define kdispwin_draw(c) +#define kdispwin_readini() +#define kdispwin_writeini() + +#endif diff --git a/windows/subwnd/mdbgwnd.cpp b/windows/subwnd/mdbgwnd.cpp old mode 100755 new mode 100644 index 2a07816b..ab812727 --- a/windows/subwnd/mdbgwnd.cpp +++ b/windows/subwnd/mdbgwnd.cpp @@ -1,272 +1,272 @@ -/** - * @file mdbgwnd.cpp - * @brief メモリ デバガ クラスの動作の定義を行います - */ - -#include -#include "resource.h" -#include "mdbgwnd.h" -#include -#include -#include -#include "dialog/np2class.h" -#include - -#if defined(CPUCORE_IA32) && defined(SUPPORT_MEMDBG32) - -//! 唯一のインスタンスです -CMemDebugWnd CMemDebugWnd::sm_instance; - -/** - * @brief コンフィグ - */ -struct MemDebugConfig -{ - int posx; - int posy; - UINT8 type; -}; - -//! コンフィグ -static MemDebugConfig s_mdbgcfg; - -//! タイトル -static const TCHAR s_mdbgapp[] = _T("Memory Map"); - -/** - * 設定 - */ -static const PFTBL s_mdbgini[] = -{ - PFVAL("WindposX", PFTYPE_SINT32, &s_mdbgcfg.posx), - PFVAL("WindposY", PFTYPE_SINT32, &s_mdbgcfg.posy), - PFVAL("windtype", PFTYPE_BOOL, &s_mdbgcfg.type) -}; - -/** - * 初期化 - */ -void CMemDebugWnd::Initialize() -{ - memdbg32_initialize(); -} - -/** - * 解放 - */ -void CMemDebugWnd::Deinitialize() -{ -} - -/** - * コンストラクタ - */ -CMemDebugWnd::CMemDebugWnd() - : m_nWidth(0) - , m_nHeight(0) -{ -} - -/** - * デストラクタ - */ -CMemDebugWnd::~CMemDebugWnd() -{ -} - -/** - * 作成 - */ -void CMemDebugWnd::Create() -{ - if (m_hWnd != NULL) - { - return; - } - - memdbg32_getsize(&m_nWidth, &m_nHeight); - if (!CSubWndBase::Create(s_mdbgapp, WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, s_mdbgcfg.posx, s_mdbgcfg.posy, m_nWidth, m_nHeight, NULL, NULL)) - { - return; - } - ShowWindow(SW_SHOWNOACTIVATE); - UpdateWindow(); - - if (!m_dd2.Create(m_hWnd, m_nWidth, m_nHeight)) - { - DestroyWindow(); - return; - } - Invalidate(); - SetForegroundWindow(g_hWndMain); -} - -/** - * アイドル処理 - */ -void CMemDebugWnd::OnIdle() -{ - if ((m_hWnd) && (memdbg32_process())) - { - OnDraw(FALSE); - } -} - -/** - * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています - * @param[in] nMsg 処理される Windows メッセージを指定します - * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します - * @return メッセージに依存する値を返します - */ -LRESULT CMemDebugWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) -{ - switch (nMsg) - { - case WM_CREATE: - np2class_wmcreate(m_hWnd); - winloc_setclientsize(m_hWnd, m_nWidth, m_nHeight); - np2class_windowtype(m_hWnd, (s_mdbgcfg.type & 1) + 1); - break; - - case WM_PAINT: - OnPaint(); - break; - - case WM_LBUTTONDOWN: - if (s_mdbgcfg.type & 1) - { - return SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, 0L); - } - break; - - case WM_LBUTTONDBLCLK: - s_mdbgcfg.type ^= 1; - SetWndType((s_mdbgcfg.type & 1) + 1); - sysmng_update(SYS_UPDATEOSCFG); - break; - - case WM_MOVE: - if (!(GetWindowLong(m_hWnd, GWL_STYLE) & (WS_MAXIMIZE | WS_MINIMIZE))) - { - RECT rc; - GetWindowRect(&rc); - s_mdbgcfg.posx = rc.left; - s_mdbgcfg.posy = rc.top; - sysmng_update(SYS_UPDATEOSCFG); - } - break; - - case WM_DESTROY: - OnDestroy(); - break; - - default: - return CSubWndBase::WindowProc(nMsg, wParam, lParam); - } - return(0); -} - -/** - * ウィンドウ破棄の時に呼ばれる - */ -void CMemDebugWnd::OnDestroy() -{ - ::np2class_wmdestroy(m_hWnd); - m_dd2.Release(); -} - -/** - * 描画の時に呼ばれる - */ -void CMemDebugWnd::OnPaint() -{ - PAINTSTRUCT ps; - HDC hdc = BeginPaint(&ps); - OnDraw(TRUE); - EndPaint(&ps); -} - -/** - * 描画 - * @param[in] redraw 再描画 - */ -void CMemDebugWnd::OnDraw(BOOL redraw) -{ - RECT rect; - GetClientRect(&rect); - - RECT draw; - draw.left = 0; - draw.top = 0; - draw.right = min(m_nWidth, rect.right - rect.left); - draw.bottom = min(m_nHeight, rect.bottom - rect.top); - CMNVRAM* vram = m_dd2.Lock(); - if (vram) - { - memdbg32_paint(vram, mdpalcnv, redraw); - m_dd2.Unlock(); - m_dd2.Blt(NULL, &draw); - } -} - -/** - * パレット変換コールバック - * @param[out] dst 出力先 - * @param[in] src パレット - * @param[in] pals パレット数 - * @param[in] bpp 色数 - */ -void CMemDebugWnd::mdpalcnv(CMNPAL *dst, const RGB32 *src, UINT pals, UINT bpp) -{ - switch (bpp) - { -#if defined(SUPPORT_16BPP) - case 16: - for (UINT i = 0; i < pals; i++) - { - dst[i].pal16 = CMemDebugWnd::GetInstance()->m_dd2.GetPalette16(src[i]); - } - break; -#endif -#if defined(SUPPORT_24BPP) - case 24: -#endif -#if defined(SUPPORT_32BPP) - case 32: -#endif -#if defined(SUPPORT_24BPP) || defined(SUPPORT_32BPP) - for (UINT i = 0; i < pals; i++) - { - dst[i].pal32.d = src[i].d; - } - break; -#endif - } -} - -/** - * 設定読み込み - */ -void mdbgwin_readini() -{ - s_mdbgcfg.posx = CW_USEDEFAULT; - s_mdbgcfg.posy = CW_USEDEFAULT; - - OEMCHAR szPath[MAX_PATH]; - initgetfile(szPath, _countof(szPath)); - ini_read(szPath, s_mdbgapp, s_mdbgini, _countof(s_mdbgini)); -} - -/** - * 設定書き込み - */ -void mdbgwin_writeini() -{ - if(!np2oscfg.readonly){ - TCHAR szPath[MAX_PATH]; - initgetfile(szPath, _countof(szPath)); - ini_write(szPath, s_mdbgapp, s_mdbgini, _countof(s_mdbgini)); - } -} -#endif +/** + * @file mdbgwnd.cpp + * @brief メモリ デバガ クラスの動作の定義を行います + */ + +#include +#include "resource.h" +#include "mdbgwnd.h" +#include +#include +#include +#include "dialog/np2class.h" +#include + +#if defined(CPUCORE_IA32) && defined(SUPPORT_MEMDBG32) + +//! 唯一のインスタンスです +CMemDebugWnd CMemDebugWnd::sm_instance; + +/** + * @brief コンフィグ + */ +struct MemDebugConfig +{ + int posx; + int posy; + UINT8 type; +}; + +//! コンフィグ +static MemDebugConfig s_mdbgcfg; + +//! タイトル +static const TCHAR s_mdbgapp[] = _T("Memory Map"); + +/** + * 設定 + */ +static const PFTBL s_mdbgini[] = +{ + PFVAL("WindposX", PFTYPE_SINT32, &s_mdbgcfg.posx), + PFVAL("WindposY", PFTYPE_SINT32, &s_mdbgcfg.posy), + PFVAL("windtype", PFTYPE_BOOL, &s_mdbgcfg.type) +}; + +/** + * 初期化 + */ +void CMemDebugWnd::Initialize() +{ + memdbg32_initialize(); +} + +/** + * 解放 + */ +void CMemDebugWnd::Deinitialize() +{ +} + +/** + * コンストラクタ + */ +CMemDebugWnd::CMemDebugWnd() + : m_nWidth(0) + , m_nHeight(0) +{ +} + +/** + * デストラクタ + */ +CMemDebugWnd::~CMemDebugWnd() +{ +} + +/** + * 作成 + */ +void CMemDebugWnd::Create() +{ + if (m_hWnd != NULL) + { + return; + } + + memdbg32_getsize(&m_nWidth, &m_nHeight); + if (!CSubWndBase::Create(s_mdbgapp, WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, s_mdbgcfg.posx, s_mdbgcfg.posy, m_nWidth, m_nHeight, NULL, NULL)) + { + return; + } + ShowWindow(SW_SHOWNOACTIVATE); + UpdateWindow(); + + if (!m_dd2.Create(m_hWnd, m_nWidth, m_nHeight)) + { + DestroyWindow(); + return; + } + Invalidate(); + SetForegroundWindow(g_hWndMain); +} + +/** + * アイドル処理 + */ +void CMemDebugWnd::OnIdle() +{ + if ((m_hWnd) && (memdbg32_process())) + { + OnDraw(FALSE); + } +} + +/** + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します + */ +LRESULT CMemDebugWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) +{ + switch (nMsg) + { + case WM_CREATE: + np2class_wmcreate(m_hWnd); + winloc_setclientsize(m_hWnd, m_nWidth, m_nHeight); + np2class_windowtype(m_hWnd, (s_mdbgcfg.type & 1) + 1); + break; + + case WM_PAINT: + OnPaint(); + break; + + case WM_LBUTTONDOWN: + if (s_mdbgcfg.type & 1) + { + return SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, 0L); + } + break; + + case WM_LBUTTONDBLCLK: + s_mdbgcfg.type ^= 1; + SetWndType((s_mdbgcfg.type & 1) + 1); + sysmng_update(SYS_UPDATEOSCFG); + break; + + case WM_MOVE: + if (!(GetWindowLong(m_hWnd, GWL_STYLE) & (WS_MAXIMIZE | WS_MINIMIZE))) + { + RECT rc; + GetWindowRect(&rc); + s_mdbgcfg.posx = rc.left; + s_mdbgcfg.posy = rc.top; + sysmng_update(SYS_UPDATEOSCFG); + } + break; + + case WM_DESTROY: + OnDestroy(); + break; + + default: + return CSubWndBase::WindowProc(nMsg, wParam, lParam); + } + return(0); +} + +/** + * ウィンドウ破棄の時に呼ばれる + */ +void CMemDebugWnd::OnDestroy() +{ + ::np2class_wmdestroy(m_hWnd); + m_dd2.Release(); +} + +/** + * 描画の時に呼ばれる + */ +void CMemDebugWnd::OnPaint() +{ + PAINTSTRUCT ps; + HDC hdc = BeginPaint(&ps); + OnDraw(TRUE); + EndPaint(&ps); +} + +/** + * 描画 + * @param[in] redraw 再描画 + */ +void CMemDebugWnd::OnDraw(BOOL redraw) +{ + RECT rect; + GetClientRect(&rect); + + RECT draw; + draw.left = 0; + draw.top = 0; + draw.right = min(m_nWidth, rect.right - rect.left); + draw.bottom = min(m_nHeight, rect.bottom - rect.top); + CMNVRAM* vram = m_dd2.Lock(); + if (vram) + { + memdbg32_paint(vram, mdpalcnv, redraw); + m_dd2.Unlock(); + m_dd2.Blt(NULL, &draw); + } +} + +/** + * パレット変換コールバック + * @param[out] dst 出力先 + * @param[in] src パレット + * @param[in] pals パレット数 + * @param[in] bpp 色数 + */ +void CMemDebugWnd::mdpalcnv(CMNPAL *dst, const RGB32 *src, UINT pals, UINT bpp) +{ + switch (bpp) + { +#if defined(SUPPORT_16BPP) + case 16: + for (UINT i = 0; i < pals; i++) + { + dst[i].pal16 = CMemDebugWnd::GetInstance()->m_dd2.GetPalette16(src[i]); + } + break; +#endif +#if defined(SUPPORT_24BPP) + case 24: +#endif +#if defined(SUPPORT_32BPP) + case 32: +#endif +#if defined(SUPPORT_24BPP) || defined(SUPPORT_32BPP) + for (UINT i = 0; i < pals; i++) + { + dst[i].pal32.d = src[i].d; + } + break; +#endif + } +} + +/** + * 設定読み込み + */ +void mdbgwin_readini() +{ + s_mdbgcfg.posx = CW_USEDEFAULT; + s_mdbgcfg.posy = CW_USEDEFAULT; + + OEMCHAR szPath[MAX_PATH]; + initgetfile(szPath, _countof(szPath)); + ini_read(szPath, s_mdbgapp, s_mdbgini, _countof(s_mdbgini)); +} + +/** + * 設定書き込み + */ +void mdbgwin_writeini() +{ + if(!np2oscfg.readonly){ + TCHAR szPath[MAX_PATH]; + initgetfile(szPath, _countof(szPath)); + ini_write(szPath, s_mdbgapp, s_mdbgini, _countof(s_mdbgini)); + } +} +#endif diff --git a/windows/subwnd/mdbgwnd.h b/windows/subwnd/mdbgwnd.h old mode 100755 new mode 100644 index d91e9109..1ffe6611 --- a/windows/subwnd/mdbgwnd.h +++ b/windows/subwnd/mdbgwnd.h @@ -1,68 +1,68 @@ -/** - * @file mdbgwnd.h - * @brief メモリ デバガ クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#if defined(CPUCORE_IA32) && defined(SUPPORT_MEMDBG32) - -#include "dd2.h" -#include "subwnd.h" - -/** - * @brief メモリ デバガ - */ -class CMemDebugWnd : public CSubWndBase -{ -public: - static CMemDebugWnd* GetInstance(); - static void Initialize(); - static void Deinitialize(); - CMemDebugWnd(); - virtual ~CMemDebugWnd(); - void Create(); - void OnIdle(); - -protected: - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - void OnDestroy(); - void OnPaint(); - -private: - static CMemDebugWnd sm_instance; //!< インスタンス - DD2Surface m_dd2; //!< DirectDraw2 インスタンス - int m_nWidth; //!< 幅 - int m_nHeight; //!< 高さ - void OnDraw(BOOL redraw); - static void mdpalcnv(CMNPAL *dst, const RGB32 *src, UINT pals, UINT bpp); -}; - -/** - * インスタンスを返す - * @return インスタンス - */ -inline CMemDebugWnd* CMemDebugWnd::GetInstance() -{ - return &sm_instance; -} - -#define mdbgwin_initialize CMemDebugWnd::Initialize -#define mdbgwin_create CMemDebugWnd::GetInstance()->Create -#define mdbgwin_destroy CMemDebugWnd::GetInstance()->DestroyWindow -#define mdbgwin_process CMemDebugWnd::GetInstance()->OnIdle -#define mdbgwin_gethwnd CMemDebugWnd::GetInstance()->GetSafeHwnd -void mdbgwin_readini(); -void mdbgwin_writeini(); - -#else - -#define mdbgwin_initialize() -#define mdbgwin_create(i) -#define mdbgwin_destroy() -#define mdbgwin_process() -#define mdbgwin_gethwnd() (NULL) -#define mdbgwin_readini() -#define mdbgwin_writeini() - -#endif +/** + * @file mdbgwnd.h + * @brief メモリ デバガ クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#if defined(CPUCORE_IA32) && defined(SUPPORT_MEMDBG32) + +#include "dd2.h" +#include "subwnd.h" + +/** + * @brief メモリ デバガ + */ +class CMemDebugWnd : public CSubWndBase +{ +public: + static CMemDebugWnd* GetInstance(); + static void Initialize(); + static void Deinitialize(); + CMemDebugWnd(); + virtual ~CMemDebugWnd(); + void Create(); + void OnIdle(); + +protected: + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + void OnDestroy(); + void OnPaint(); + +private: + static CMemDebugWnd sm_instance; //!< インスタンス + DD2Surface m_dd2; //!< DirectDraw2 インスタンス + int m_nWidth; //!< 幅 + int m_nHeight; //!< 高さ + void OnDraw(BOOL redraw); + static void mdpalcnv(CMNPAL *dst, const RGB32 *src, UINT pals, UINT bpp); +}; + +/** + * インスタンスを返す + * @return インスタンス + */ +inline CMemDebugWnd* CMemDebugWnd::GetInstance() +{ + return &sm_instance; +} + +#define mdbgwin_initialize CMemDebugWnd::Initialize +#define mdbgwin_create CMemDebugWnd::GetInstance()->Create +#define mdbgwin_destroy CMemDebugWnd::GetInstance()->DestroyWindow +#define mdbgwin_process CMemDebugWnd::GetInstance()->OnIdle +#define mdbgwin_gethwnd CMemDebugWnd::GetInstance()->GetSafeHwnd +void mdbgwin_readini(); +void mdbgwin_writeini(); + +#else + +#define mdbgwin_initialize() +#define mdbgwin_create(i) +#define mdbgwin_destroy() +#define mdbgwin_process() +#define mdbgwin_gethwnd() (NULL) +#define mdbgwin_readini() +#define mdbgwin_writeini() + +#endif diff --git a/windows/subwnd/skbdwnd.cpp b/windows/subwnd/skbdwnd.cpp index 810bcd99..8e5d0d4a 100644 --- a/windows/subwnd/skbdwnd.cpp +++ b/windows/subwnd/skbdwnd.cpp @@ -1,6 +1,6 @@ /** * @file skbdwnd.cpp - * @brief \tgEFA L[{[h NX̓̒`s܂ + * @brief ソフトウェア キーボード クラスの動作の定義を行います */ #include "compiler.h" @@ -15,11 +15,11 @@ #if defined(SUPPORT_SOFTKBD) -//! B̃CX^Xł +//! 唯一のインスタンスです CSoftKeyboardWnd CSoftKeyboardWnd::sm_instance; /** - * @brief RtBO + * @brief コンフィグ */ struct SoftKeyboardConfig { @@ -27,17 +27,17 @@ struct SoftKeyboardConfig int posy; //!< Y int width; //!< Width 0=Invalid int height; //!< Height 0=Invalid - UINT8 type; //!< EBhE ^Cv + UINT8 type; //!< ウィンドウ タイプ }; -//! RtBO +//! コンフィグ static SoftKeyboardConfig s_skbdcfg; -//! ^Cg +//! タイトル static const TCHAR s_skbdapp[] = TEXT("Soft Keyboard"); /** - * ݒ + * 設定 */ static const PFTBL s_skbdini[] = { @@ -49,7 +49,7 @@ static const PFTBL s_skbdini[] = }; /** - * + * 初期化 */ void CSoftKeyboardWnd::Initialize() { @@ -57,7 +57,7 @@ void CSoftKeyboardWnd::Initialize() } /** - * + * 解放 */ void CSoftKeyboardWnd::Deinitialize() { @@ -65,7 +65,7 @@ void CSoftKeyboardWnd::Deinitialize() } /** - * RXgN^ + * コンストラクタ */ CSoftKeyboardWnd::CSoftKeyboardWnd() : m_nWidth(0) @@ -74,14 +74,14 @@ CSoftKeyboardWnd::CSoftKeyboardWnd() } /** - * fXgN^ + * デストラクタ */ CSoftKeyboardWnd::~CSoftKeyboardWnd() { } /** - * 쐬 + * 作成 */ void CSoftKeyboardWnd::Create() { @@ -115,7 +115,7 @@ void CSoftKeyboardWnd::Create() } /** - * ACh + * アイドル処理 */ void CSoftKeyboardWnd::OnIdle() { @@ -138,11 +138,11 @@ void CSoftKeyboardWnd::ConvertClientPointToSoftkbdPoint(int &x, int &y) } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT CSoftKeyboardWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -155,7 +155,7 @@ LRESULT CSoftKeyboardWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) winloc_setclientsize(m_hWnd, s_skbdcfg.width, s_skbdcfg.height); np2class_windowtype(m_hWnd, (s_skbdcfg.type & 1) + 1); - // VXej[lj + // システムメニュー追加 { HMENU hMenu = GetSystemMenu(FALSE); int pos = menu_addmenures(hMenu, 0, IDR_SOFTKBD_SYS, FALSE); @@ -223,7 +223,7 @@ LRESULT CSoftKeyboardWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) case WM_GETMINMAXINFO: { MINMAXINFO* pInfo = (MINMAXINFO*)lParam; - RECT rc = { 0, 0, m_nWidth, m_nHeight }; // ŏTCY + RECT rc = { 0, 0, m_nWidth, m_nHeight }; // 最小サイズ AdjustWindowRectEx( &rc, GetWindowLong(m_hWnd, GWL_STYLE), @@ -272,7 +272,7 @@ LRESULT CSoftKeyboardWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) } /** - * EBhEj̎ɌĂ΂ + * ウィンドウ破棄の時に呼ばれる */ void CSoftKeyboardWnd::OnDestroy() { @@ -281,7 +281,7 @@ void CSoftKeyboardWnd::OnDestroy() } /** - * `̎ɌĂ΂ + * 描画の時に呼ばれる */ void CSoftKeyboardWnd::OnPaint() { @@ -292,8 +292,8 @@ void CSoftKeyboardWnd::OnPaint() } /** - * ` - * @param[in] redraw ĕ` + * 描画 + * @param[in] redraw 再描画 */ void CSoftKeyboardWnd::OnDraw(BOOL redraw) { @@ -320,11 +320,11 @@ void CSoftKeyboardWnd::OnDraw(BOOL redraw) } /** - * pbgϊR[obN - * @param[out] dst o͐ - * @param[in] src pbg - * @param[in] pals pbg - * @param[in] bpp F + * パレット変換コールバック + * @param[out] dst 出力先 + * @param[in] src パレット + * @param[in] pals パレット数 + * @param[in] bpp 色数 */ void CSoftKeyboardWnd::skpalcnv(CMNPAL *dst, const RGB32 *src, UINT pals, UINT bpp) { @@ -355,7 +355,7 @@ void CSoftKeyboardWnd::skpalcnv(CMNPAL *dst, const RGB32 *src, UINT pals, UINT b } /** - * ݒǂݍ + * 設定読み込み */ void skbdwin_readini() { @@ -370,7 +370,7 @@ void skbdwin_readini() } /** - * ݒ菑 + * 設定書き込み */ void skbdwin_writeini() { diff --git a/windows/subwnd/skbdwnd.h b/windows/subwnd/skbdwnd.h index 1aaddc93..f523c8f3 100644 --- a/windows/subwnd/skbdwnd.h +++ b/windows/subwnd/skbdwnd.h @@ -1,6 +1,6 @@ /** * @file skbdwnd.h - * @brief \tgEFA L[{[h NX̐錾уC^[tFCX̒`܂ + * @brief ソフトウェア キーボード クラスの宣言およびインターフェイスの定義をします */ #pragma once @@ -11,7 +11,7 @@ #include "subwnd.h" /** - * @brief \tgEFA L[{[h + * @brief ソフトウェア キーボード */ class CSoftKeyboardWnd : public CSubWndBase { @@ -30,18 +30,18 @@ class CSoftKeyboardWnd : public CSubWndBase void OnPaint(); private: - static CSoftKeyboardWnd sm_instance; //!< CX^X - DD2Surface m_dd2; //!< DirectDraw2 CX^X - int m_nWidth; //!< Dot by dot - int m_nHeight; //!< Dot by dot + static CSoftKeyboardWnd sm_instance; //!< インスタンス + DD2Surface m_dd2; //!< DirectDraw2 インスタンス + int m_nWidth; //!< Dot by dot幅 + int m_nHeight; //!< Dot by dot高さ void OnDraw(BOOL redraw); static void skpalcnv(CMNPAL *dst, const RGB32 *src, UINT pals, UINT bpp); void ConvertClientPointToSoftkbdPoint(int& x, int& y); }; /** - * CX^XԂ - * @return CX^X + * インスタンスを返す + * @return インスタンス */ inline CSoftKeyboardWnd* CSoftKeyboardWnd::GetInstance() { diff --git a/windows/subwnd/subwnd.cpp b/windows/subwnd/subwnd.cpp index 7fb1c257..00747f8f 100644 --- a/windows/subwnd/subwnd.cpp +++ b/windows/subwnd/subwnd.cpp @@ -1,6 +1,6 @@ /** * @file subwnd.cpp - * @brief Tu EBhE̊NX̓̒`s܂ + * @brief サブ ウィンドウの基底クラスの動作の定義を行います */ #include "compiler.h" @@ -16,12 +16,12 @@ extern WINLOCEX np2_winlocexallwin(HWND base); -//! NX +//! クラス名 static const TCHAR s_szClassName[] = TEXT("NP2-SubWnd"); /** - * - * @param[in] hInstance CX^X + * 初期化 + * @param[in] hInstance インスタンス */ void CSubWndBase::Initialize(HINSTANCE hInstance) { @@ -39,7 +39,7 @@ void CSubWndBase::Initialize(HINSTANCE hInstance) } /** - * RXgN^ + * コンストラクタ */ CSubWndBase::CSubWndBase() : m_wlex(NULL) @@ -47,24 +47,24 @@ CSubWndBase::CSubWndBase() } /** - * fXgN^ + * デストラクタ */ CSubWndBase::~CSubWndBase() { } /** - * EBhE쐬 - * @param[in] nCaptionID LvV ID - * @param[in] dwStyle X^C - * @param[in] x XW - * @param[in] y YW - * @param[in] nWidth - * @param[in] nHeight - * @param[in] hwndParent eEBhE - * @param[in] nIDorHMenu ID j[ - * @retval TRUE - * @retval FALSE s + * ウィンドウ作成 + * @param[in] nCaptionID キャプション ID + * @param[in] dwStyle スタイル + * @param[in] x X座標 + * @param[in] y Y座標 + * @param[in] nWidth 幅 + * @param[in] nHeight 高さ + * @param[in] hwndParent 親ウィンドウ + * @param[in] nIDorHMenu ID もしくは メニュー + * @retval TRUE 成功 + * @retval FALSE 失敗 */ BOOL CSubWndBase::Create(UINT nCaptionID, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu) { @@ -76,17 +76,17 @@ BOOL CSubWndBase::Create(UINT nCaptionID, DWORD dwStyle, int x, int y, int nWidt } /** - * EBhE쐬 - * @param[in] lpCaption LvV - * @param[in] dwStyle X^C - * @param[in] x XW - * @param[in] y YW - * @param[in] nWidth - * @param[in] nHeight - * @param[in] hwndParent eEBhE - * @param[in] nIDorHMenu ID j[ - * @retval TRUE - * @retval FALSE s + * ウィンドウ作成 + * @param[in] lpCaption キャプション + * @param[in] dwStyle スタイル + * @param[in] x X座標 + * @param[in] y Y座標 + * @param[in] nWidth 幅 + * @param[in] nHeight 高さ + * @param[in] hwndParent 親ウィンドウ + * @param[in] nIDorHMenu ID もしくは メニュー + * @retval TRUE 成功 + * @retval FALSE 失敗 */ BOOL CSubWndBase::Create(LPCTSTR lpCaption, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu) { @@ -96,8 +96,8 @@ BOOL CSubWndBase::Create(LPCTSTR lpCaption, DWORD dwStyle, int x, int y, int nWi } /** - * EBhE ^Cv̐ݒ - * @param[in] nType ^Cv + * ウィンドウ タイプの設定 + * @param[in] nType タイプ */ void CSubWndBase::SetWndType(UINT8 nType) { @@ -109,11 +109,11 @@ void CSubWndBase::SetWndType(UINT8 nType) } /** - * CWndProc IuWFNg Windows vV[W (WindowProc) pӂĂ܂ - * @param[in] nMsg Windows bZ[Ww肵܂ - * @param[in] wParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @param[in] lParam bZ[W̏Ŏgt񋟂܂B̃p[^̒l̓bZ[WɈˑ܂ - * @return bZ[WɈˑlԂ܂ + * CWndProc オブジェクトの Windows プロシージャ (WindowProc) が用意されています + * @param[in] nMsg 処理される Windows メッセージを指定します + * @param[in] wParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @param[in] lParam メッセージの処理で使う付加情報を提供します。このパラメータの値はメッセージに依存します + * @return メッセージに依存する値を返します */ LRESULT CSubWndBase::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) { @@ -148,7 +148,7 @@ LRESULT CSubWndBase::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) break; case WM_MOVING: - if (np2oscfg.WINSNAP) { // Xibvݒʂ np21w ver0.86 rev22 + if (np2oscfg.WINSNAP) { // スナップ設定を共通に np21w ver0.86 rev22 winlocex_moving(m_wlex, reinterpret_cast(lParam)); } break; diff --git a/windows/subwnd/subwnd.h b/windows/subwnd/subwnd.h old mode 100755 new mode 100644 index b7cece7c..4c7f9eca --- a/windows/subwnd/subwnd.h +++ b/windows/subwnd/subwnd.h @@ -1,30 +1,30 @@ -/** - * @file subwnd.h - * @brief サブ ウィンドウの基底クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "winloc.h" -#include "misc\WndProc.h" - -/** - * @brief サブ ウィンドウの基底クラス - */ -class CSubWndBase : public CWndProc -{ -public: - static void Initialize(HINSTANCE hInstance); - - CSubWndBase(); - virtual ~CSubWndBase(); - BOOL Create(UINT nCaptionID, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu); - BOOL Create(LPCTSTR lpCaption, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu); - void SetWndType(UINT8 nType); - -protected: - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - -private: - WINLOCEX m_wlex; /*!< ウィンドウ ロケータ */ -}; +/** + * @file subwnd.h + * @brief サブ ウィンドウの基底クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "winloc.h" +#include "misc\WndProc.h" + +/** + * @brief サブ ウィンドウの基底クラス + */ +class CSubWndBase : public CWndProc +{ +public: + static void Initialize(HINSTANCE hInstance); + + CSubWndBase(); + virtual ~CSubWndBase(); + BOOL Create(UINT nCaptionID, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu); + BOOL Create(LPCTSTR lpCaption, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu); + void SetWndType(UINT8 nType); + +protected: + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + +private: + WINLOCEX m_wlex; /*!< ウィンドウ ロケータ */ +}; diff --git a/windows/subwnd/toolwnd.cpp b/windows/subwnd/toolwnd.cpp index 65c2a761..352f5944 100644 --- a/windows/subwnd/toolwnd.cpp +++ b/windows/subwnd/toolwnd.cpp @@ -68,11 +68,11 @@ static const DISKACC diskacc[3] = { {IDC_TOOLFDD2ACC, &toolwin.m_fddaccess[1]}, {IDC_TOOLHDDACC, &toolwin.m_hddaccess}}; -static UINT fdlistlen = FDDLIST_DEFAULT; // FDt@C +static UINT fdlistlen = FDDLIST_DEFAULT; // FDファイル履歴数 /** - * CX^XԂ - * @return CX^X + * インスタンスを返す + * @return インスタンス */ CToolWnd* CToolWnd::GetInstance() { @@ -80,14 +80,14 @@ CToolWnd* CToolWnd::GetInstance() } /** - * RXgN^ + * コンストラクタ */ CToolWnd::CToolWnd() { } /** - * fXgN^ + * デストラクタ */ CToolWnd::~CToolWnd() { @@ -469,10 +469,10 @@ void CToolWnd::DestroySubItems() if (sub) { if(m_subproc[i]){ - SetWindowLongPtr(sub, GWLP_WNDPROC, (LONG_PTR)m_subproc[i]); // ꉞ߂ĂĂ܂傤 + SetWindowLongPtr(sub, GWLP_WNDPROC, (LONG_PTR)m_subproc[i]); // 一応戻しておいてあげましょう } m_subproc[i] = NULL; - ::SetParent(sub, NULL); // qEBhE + ::SetParent(sub, NULL); // 子ウィンドウ解除 ::DestroyWindow(sub); } } @@ -832,7 +832,7 @@ LRESULT CToolWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) break; #if 0 - case WM_KEYDOWN: // TABɕA + case WM_KEYDOWN: // TABを押した時に復帰 if ((short)wParam == VK_TAB) { UINT idc = (UINT)GetWindowLongPtr(m_hWnd, GTWLP_FOCUS); @@ -942,7 +942,7 @@ LRESULT CToolWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam) } /** - * 쐬 + * 作成 */ void CToolWnd::Create() { @@ -1096,11 +1096,11 @@ const DISKACC *accterm; // ---- -//! ^Cg +//! タイトル static const TCHAR s_toolwndapp[] = TEXT("NP2 tool"); /** - * ݒ + * 設定 */ static const PFTBL s_toolwndini[] = { @@ -1158,7 +1158,7 @@ int gettoolwndini(PFTBL **ptoolwndini) } /** - * ݒǂݍ + * 設定読み込み */ void toolwin_readini() { @@ -1180,7 +1180,7 @@ void toolwin_readini() } /** - * ݒ菑 + * 設定書き込み */ void toolwin_writeini() { diff --git a/windows/subwnd/toolwnd.h b/windows/subwnd/toolwnd.h old mode 100755 new mode 100644 index d2d16baa..702cbf0a --- a/windows/subwnd/toolwnd.h +++ b/windows/subwnd/toolwnd.h @@ -1,106 +1,106 @@ -/** - * @file toolwnd.h - * @brief ツール ウィンドウ クラスの宣言およびインターフェイスの定義をします - */ - -#pragma once - -#include "subwnd.h" - -#define FDDLIST_DEFAULT 8 // デフォルトは8件記憶 - -enum { - SKINMRU_MAX = 4, - FDDLIST_DRV = 2, - FDDLIST_MAX = 64 -}; - -typedef struct { - int insert; - UINT cnt; - UINT pos[FDDLIST_MAX]; - OEMCHAR name[FDDLIST_MAX][MAX_PATH]; -} TOOLFDD; - -typedef struct { - int posx; - int posy; - BOOL type; - TOOLFDD fdd[FDDLIST_DRV]; - OEMCHAR skin[MAX_PATH]; - OEMCHAR skinmru[SKINMRU_MAX][MAX_PATH]; -} NP2TOOL; - -enum -{ - IDC_TOOLHDDACC = 0, - IDC_TOOLFDD1ACC, - IDC_TOOLFDD1LIST, - IDC_TOOLFDD1BROWSE, - IDC_TOOLFDD1EJECT, - IDC_TOOLFDD2ACC, - IDC_TOOLFDD2LIST, - IDC_TOOLFDD2BROWSE, - IDC_TOOLFDD2EJECT, - IDC_TOOLRESET, - IDC_TOOLPOWER, - IDC_MAXITEMS -}; - -/** - * @brief ツール ウィンドウ クラス - */ -class CToolWnd : public CSubWndBase -{ -public: - static CToolWnd* GetInstance(); - CToolWnd(); - virtual ~CToolWnd(); - void Create(); - -protected: - virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); - int OnCreate(LPCREATESTRUCT lpCreateStruct); - void OnDestroy(); - void OnPaint(); - void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct); - -private: - void OnDraw(BOOL redraw); - void OpenPopUp(LPARAM lParam); - void InitializeSubItems(); - void CreateSubItems(); - void DestroySubItems(); - void ChangeSkin(); - -public: - HBITMAP m_hbmp; - UINT8 m_fddaccess[2]; - UINT8 m_hddaccess; - UINT8 m_padding; - HFONT m_hfont; - HDC m_hdcfont; - HBRUSH m_access[2]; - HWND m_sub[IDC_MAXITEMS]; - WNDPROC m_subproc[IDC_MAXITEMS]; -}; - -#define toolwin_create CToolWnd::GetInstance()->Create -#define toolwin_destroy CToolWnd::GetInstance()->DestroyWindow -#define toolwin_gethwnd CToolWnd::GetInstance()->GetSafeHwnd - -void toolwin_setfdd(UINT8 drv, const OEMCHAR *name); - -#ifdef __cplusplus -extern "C" -{ -#endif -void toolwin_fddaccess(UINT8 drv); -void toolwin_hddaccess(UINT8 drv); -#ifdef __cplusplus -} -#endif -void toolwin_draw(UINT8 frame); - -void toolwin_readini(); -void toolwin_writeini(); +/** + * @file toolwnd.h + * @brief ツール ウィンドウ クラスの宣言およびインターフェイスの定義をします + */ + +#pragma once + +#include "subwnd.h" + +#define FDDLIST_DEFAULT 8 // デフォルトは8件記憶 + +enum { + SKINMRU_MAX = 4, + FDDLIST_DRV = 2, + FDDLIST_MAX = 64 +}; + +typedef struct { + int insert; + UINT cnt; + UINT pos[FDDLIST_MAX]; + OEMCHAR name[FDDLIST_MAX][MAX_PATH]; +} TOOLFDD; + +typedef struct { + int posx; + int posy; + BOOL type; + TOOLFDD fdd[FDDLIST_DRV]; + OEMCHAR skin[MAX_PATH]; + OEMCHAR skinmru[SKINMRU_MAX][MAX_PATH]; +} NP2TOOL; + +enum +{ + IDC_TOOLHDDACC = 0, + IDC_TOOLFDD1ACC, + IDC_TOOLFDD1LIST, + IDC_TOOLFDD1BROWSE, + IDC_TOOLFDD1EJECT, + IDC_TOOLFDD2ACC, + IDC_TOOLFDD2LIST, + IDC_TOOLFDD2BROWSE, + IDC_TOOLFDD2EJECT, + IDC_TOOLRESET, + IDC_TOOLPOWER, + IDC_MAXITEMS +}; + +/** + * @brief ツール ウィンドウ クラス + */ +class CToolWnd : public CSubWndBase +{ +public: + static CToolWnd* GetInstance(); + CToolWnd(); + virtual ~CToolWnd(); + void Create(); + +protected: + virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam); + int OnCreate(LPCREATESTRUCT lpCreateStruct); + void OnDestroy(); + void OnPaint(); + void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct); + +private: + void OnDraw(BOOL redraw); + void OpenPopUp(LPARAM lParam); + void InitializeSubItems(); + void CreateSubItems(); + void DestroySubItems(); + void ChangeSkin(); + +public: + HBITMAP m_hbmp; + UINT8 m_fddaccess[2]; + UINT8 m_hddaccess; + UINT8 m_padding; + HFONT m_hfont; + HDC m_hdcfont; + HBRUSH m_access[2]; + HWND m_sub[IDC_MAXITEMS]; + WNDPROC m_subproc[IDC_MAXITEMS]; +}; + +#define toolwin_create CToolWnd::GetInstance()->Create +#define toolwin_destroy CToolWnd::GetInstance()->DestroyWindow +#define toolwin_gethwnd CToolWnd::GetInstance()->GetSafeHwnd + +void toolwin_setfdd(UINT8 drv, const OEMCHAR *name); + +#ifdef __cplusplus +extern "C" +{ +#endif +void toolwin_fddaccess(UINT8 drv); +void toolwin_hddaccess(UINT8 drv); +#ifdef __cplusplus +} +#endif +void toolwin_draw(UINT8 frame); + +void toolwin_readini(); +void toolwin_writeini(); diff --git a/windows/sysmng.cpp b/windows/sysmng.cpp index 2d2b810d..da704d05 100644 --- a/windows/sysmng.cpp +++ b/windows/sysmng.cpp @@ -1,327 +1,327 @@ -#include "compiler.h" -#include "np2.h" -#include "dosio.h" -#include "sysmng.h" -#include "cpucore.h" -#include "pccore.h" -#include "diskimage/fddfile.h" -#include "fdd/diskdrv.h" -#if defined(SUPPORT_IDEIO)||defined(SUPPORT_SCSI) -#include "fdd/sxsi.h" -#include "resource.h" -#include "windows/dialog/np2class.h" -#include "windows/menu.h" -#endif - -extern UINT8 np2userpause; - -extern "C" REG8 cdchange_drv; - - UINT sys_updates; - - SYSMNGMISCINFO sys_miscinfo = {0}; - - -// ---- - -static UINT8 requestupdate = 0; - -static OEMCHAR title[2048] = {0}; -static OEMCHAR clock[256] = {0}; -static OEMCHAR misc[256] = {0}; - -static struct { - UINT32 tick; - UINT32 clock; - UINT32 draws; - SINT32 fps; - SINT32 khz; -} workclock; - -void sysmng_workclockreset(void) { - - workclock.tick = GETTICK(); - workclock.clock = CPU_CLOCK; - workclock.draws = drawcount; -} - -BOOL sysmng_workclockrenewal(void) { - - SINT32 tick; - - tick = GETTICK() - workclock.tick; - if (tick < 2000) { - return(FALSE); - } - workclock.tick += tick; - workclock.fps = ((drawcount - workclock.draws) * 10000) / tick; - workclock.draws = drawcount; - workclock.khz = (CPU_CLOCK - workclock.clock) / tick; - workclock.clock = CPU_CLOCK; - return(TRUE); -} - -OEMCHAR* DOSIOCALL sysmng_file_getname(OEMCHAR* lpPathName){ - if(_tcsnicmp(lpPathName, OEMTEXT("¥¥¥¥.¥¥"), 4)==0){ - return lpPathName; - }else{ - return file_getname(lpPathName); - } -} - -void sysmng_updatecaption(UINT8 flag) { - -#if defined(SUPPORT_IDEIO)||defined(SUPPORT_SCSI) - int i, cddrvnum = 1; -#endif - static OEMCHAR hddimgmenustrorg[4][MAX_PATH] = {0}; - static OEMCHAR hddimgmenustr[4][MAX_PATH] = {0}; -#if defined(SUPPORT_SCSI) - static OEMCHAR scsiimgmenustrorg[4][MAX_PATH] = {0}; - static OEMCHAR scsiimgmenustr[4][MAX_PATH] = {0}; -#endif - OEMCHAR work[2048] = {0}; - OEMCHAR fddtext[16] = {0}; - - if (flag & 1) { - title[0] = '¥0'; - for(i=0;i<4;i++){ - OEMSPRINTF(fddtext, OEMTEXT(" FDD%d:"), i+1); - if (fdd_diskready(i)) { - milstr_ncat(title, fddtext, NELEMENTS(title)); - milstr_ncat(title, file_getname(fdd_diskname(i)), NELEMENTS(title)); - } - } -#ifdef SUPPORT_IDEIO - for(i=0;i<4;i++){ - if(sxsi_getdevtype(i)==SXSIDEV_CDROM){ - OEMSPRINTF(work, OEMTEXT(" CD%d:"), cddrvnum); - if (sxsi_getdevtype(i)==SXSIDEV_CDROM){ - if(*(np2cfg.idecd[i])) { - milstr_ncat(title, work, NELEMENTS(title)); - milstr_ncat(title, sysmng_file_getname(np2cfg.idecd[i]), NELEMENTS(title)); - }else if(i==cdchange_drv && g_nevent.item[NEVENT_CDWAIT].clock > 0){ - milstr_ncat(title, work, NELEMENTS(title)); - milstr_ncat(title, OEMTEXT("Now Loading..."), NELEMENTS(title)); - } - } - cddrvnum++; - } - if(g_hWndMain){ - OEMCHAR newtext[MAX_PATH*2+100]; - OEMCHAR *fname; - OEMCHAR *fnamenext; - OEMCHAR *fnametmp; - OEMCHAR *fnamenexttmp; - HMENU hMenu = np2class_gethmenu(g_hWndMain); - HMENU hMenuTgt; - int hMenuTgtPos; - MENUITEMINFO mii = {0}; - menu_searchmenu(hMenu, IDM_IDE0STATE+i, &hMenuTgt, &hMenuTgtPos); - if(hMenu){ - mii.cbSize = sizeof(MENUITEMINFO); - if(!hddimgmenustrorg[i][0]){ - GetMenuString(hMenuTgt, IDM_IDE0STATE+i, hddimgmenustrorg[i], NELEMENTS(hddimgmenustrorg[0]), MF_BYCOMMAND); - } - if(np2cfg.idetype[i]==SXSIDEV_NC){ - _tcscpy(newtext, hddimgmenustrorg[i]); - _tcscat(newtext, OEMTEXT("[disabled]")); - }else{ - fname = sxsi_getfilename(i); - if(np2cfg.idetype[i]==SXSIDEV_CDROM){ - fnamenext = np2cfg.idecd[i]; - }else{ - fnamenext = (OEMCHAR*)diskdrv_getsxsi(i); - } - if(fname && *fname && fnamenext && *fnamenext && (fnametmp = sysmng_file_getname(fname))!=NULL && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ - _tcscpy(newtext, hddimgmenustrorg[i]); - _tcscat(newtext, fnametmp); - if(_tcscmp(fname, fnamenext)){ - _tcscat(newtext, OEMTEXT(" -> ")); - _tcscat(newtext, fnamenexttmp); - } - }else if(fnamenext && *fnamenext && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ - _tcscpy(newtext, hddimgmenustrorg[i]); - _tcscat(newtext, OEMTEXT("[none] -> ")); - _tcscat(newtext, fnamenexttmp); - }else if(fname && *fname && (fnametmp = sysmng_file_getname(fname))!=NULL){ - _tcscpy(newtext, hddimgmenustrorg[i]); - _tcscat(newtext, fnametmp); - _tcscat(newtext, OEMTEXT(" -> [none]")); - }else{ - _tcscpy(newtext, hddimgmenustrorg[i]); - _tcscat(newtext, OEMTEXT("[none]")); - } - } - if(_tcscmp(newtext, hddimgmenustr[i])){ - _tcscpy(hddimgmenustr[i], newtext); - mii.fMask = MIIM_TYPE; - mii.fType = MFT_STRING; - mii.dwTypeData = hddimgmenustr[i]; - mii.cch = (UINT)_tcslen(hddimgmenustr[i]); - SetMenuItemInfo(hMenuTgt, IDM_IDE0STATE+i, MF_BYCOMMAND, &mii); - } - } - } - } -#else - for(i=0;i<2;i++){ - if(g_hWndMain){ - OEMCHAR newtext[MAX_PATH*2+100]; - OEMCHAR *fname; - OEMCHAR *fnamenext; - OEMCHAR *fnametmp; - OEMCHAR *fnamenexttmp; - HMENU hMenu = np2class_gethmenu(g_hWndMain); - HMENU hMenuTgt; - int hMenuTgtPos; - MENUITEMINFO mii = {0}; - menu_searchmenu(hMenu, IDM_IDE0STATE+i, &hMenuTgt, &hMenuTgtPos); - if(hMenu){ - mii.cbSize = sizeof(MENUITEMINFO); - if(!hddimgmenustrorg[i][0]){ - GetMenuString(hMenuTgt, IDM_IDE0STATE+i, hddimgmenustrorg[i], NELEMENTS(hddimgmenustrorg[0]), MF_BYCOMMAND); - } - fname = sxsi_getfilename(i); - fnamenext = (OEMCHAR*)diskdrv_getsxsi(i); - if(fname && *fname && fnamenext && *fnamenext && (fnametmp = sysmng_file_getname(fname))!=NULL && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ - _tcscpy(newtext, hddimgmenustrorg[i]); - _tcscat(newtext, fnametmp); - if(_tcscmp(fname, fnamenext)){ - _tcscat(newtext, OEMTEXT(" -> ")); - _tcscat(newtext, fnamenexttmp); - } - }else if(fnamenext && *fnamenext && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ - _tcscpy(newtext, hddimgmenustrorg[i]); - _tcscat(newtext, OEMTEXT("[none] -> ")); - _tcscat(newtext, fnamenexttmp); - }else if(fname && *fname && (fnametmp = sysmng_file_getname(fname))!=NULL){ - _tcscpy(newtext, hddimgmenustrorg[i]); - _tcscat(newtext, fnametmp); - _tcscat(newtext, OEMTEXT(" -> [none]")); - }else{ - _tcscpy(newtext, hddimgmenustrorg[i]); - _tcscat(newtext, OEMTEXT("[none]")); - } - if(_tcscmp(newtext, hddimgmenustr[i])){ - _tcscpy(hddimgmenustr[i], newtext); - mii.fMask = MIIM_TYPE; - mii.fType = MFT_STRING; - mii.dwTypeData = hddimgmenustr[i]; - mii.cch = (UINT)_tcslen(hddimgmenustr[i]); - SetMenuItemInfo(hMenuTgt, IDM_IDE0STATE+i, MF_BYCOMMAND, &mii); - } - } - } - } -#endif -#ifdef SUPPORT_SCSI - for(i=0;i<4;i++){ - if(g_hWndMain){ - OEMCHAR newtext[MAX_PATH*2+100]; - OEMCHAR *fname; - OEMCHAR *fnamenext; - OEMCHAR *fnametmp; - OEMCHAR *fnamenexttmp; - HMENU hMenu = np2class_gethmenu(g_hWndMain); - HMENU hMenuTgt; - int hMenuTgtPos; - MENUITEMINFO mii = {0}; - menu_searchmenu(hMenu, IDM_SCSI0STATE+i, &hMenuTgt, &hMenuTgtPos); - if(hMenu){ - mii.cbSize = sizeof(MENUITEMINFO); - if(!scsiimgmenustrorg[i][0]){ - GetMenuString(hMenuTgt, IDM_SCSI0STATE+i, scsiimgmenustrorg[i], NELEMENTS(scsiimgmenustrorg[0]), MF_BYCOMMAND); - } - fname = sxsi_getfilename(i+0x20); - fnamenext = (OEMCHAR*)diskdrv_getsxsi(i+0x20); - if(fname && *fname && fnamenext && *fnamenext && (fnametmp = sysmng_file_getname(fname))!=NULL && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ - _tcscpy(newtext, scsiimgmenustrorg[i]); - _tcscat(newtext, fnametmp); - if(_tcscmp(fname, fnamenext)){ - _tcscat(newtext, OEMTEXT(" -> ")); - _tcscat(newtext, fnamenexttmp); - } - }else if(fnamenext && *fnamenext && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ - _tcscpy(newtext, scsiimgmenustrorg[i]); - _tcscat(newtext, OEMTEXT("[none] -> ")); - _tcscat(newtext, fnamenexttmp); - }else if(fname && *fname && (fnametmp = sysmng_file_getname(fname))!=NULL){ - _tcscpy(newtext, scsiimgmenustrorg[i]); - _tcscat(newtext, fnametmp); - _tcscat(newtext, OEMTEXT(" -> [none]")); - }else{ - _tcscpy(newtext, scsiimgmenustrorg[i]); - _tcscat(newtext, OEMTEXT("[none]")); - } - if(_tcscmp(newtext, scsiimgmenustr[i])){ - _tcscpy(scsiimgmenustr[i], newtext); - mii.fMask = MIIM_TYPE; - mii.fType = MFT_STRING; - mii.dwTypeData = scsiimgmenustr[i]; - mii.cch = (UINT)_tcslen(scsiimgmenustr[i]); - SetMenuItemInfo(hMenuTgt, IDM_SCSI0STATE+i, MF_BYCOMMAND, &mii); - } - } - } - } -#endif - } - - if (flag & 2) { - clock[0] = '¥0'; - if (np2oscfg.DISPCLK & 2) { - if (workclock.fps) { - OEMSPRINTF(clock, OEMTEXT(" - %u.%1uFPS"), - workclock.fps / 10, workclock.fps % 10); - } - else { - milstr_ncpy(clock, OEMTEXT(" - 0FPS"), NELEMENTS(clock)); - } - } - if (!np2userpause && (np2oscfg.DISPCLK & 1)) { - OEMSPRINTF(work, OEMTEXT(" %2u.%03uMHz"), - workclock.khz / 1000, workclock.khz % 1000); - if (clock[0] == '¥0') { - milstr_ncpy(clock, OEMTEXT(" -"), NELEMENTS(clock)); - } - milstr_ncat(clock, work, NELEMENTS(clock)); -#if 0 - OEMSPRINTF(work, OEMTEXT(" (debug: OPN %d / PSG %s)"), - opngen.playing, - (g_psg1.mixer & 0x3f)?OEMTEXT("ON"):OEMTEXT("OFF")); - milstr_ncat(clock, work, NELEMENTS(clock)); -#endif - } - } - - if (flag & 4) { - misc[0] = '¥0'; - if(sys_miscinfo.showvolume && sys_miscinfo.showmousespeed){ - OEMSPRINTF(misc, OEMTEXT(" (Volume: %d%%, Mouse speed: %d%%)"), np2cfg.vol_master, 100 * np2oscfg.mousemul/np2oscfg.mousediv); - }else if(sys_miscinfo.showvolume){ - OEMSPRINTF(misc, OEMTEXT(" (Volume: %d%%)"), np2cfg.vol_master); - }else if(sys_miscinfo.showmousespeed){ - OEMSPRINTF(misc, OEMTEXT(" (Mouse speed: %d%%)"), 100 * np2oscfg.mousemul/np2oscfg.mousediv); - } - } - - milstr_ncpy(work, np2oscfg.titles, NELEMENTS(work)); - milstr_ncat(work, misc, NELEMENTS(work)); - if(np2userpause){ - milstr_ncat(work, OEMTEXT(" [PAUSED]"), NELEMENTS(work)); - } - milstr_ncat(work, title, NELEMENTS(work)); - milstr_ncat(work, clock, NELEMENTS(work)); - SetWindowText(g_hWndMain, work); -} - -void sysmng_requestupdatecaption(UINT8 flag) { - requestupdate |= flag; // マルチスレッド呼び出し対策・・・ -} -void sysmng_requestupdatecheck() { - if(requestupdate != 0){ - sysmng_updatecaption(requestupdate); - requestupdate = 0; - }; -} +#include "compiler.h" +#include "np2.h" +#include "dosio.h" +#include "sysmng.h" +#include "cpucore.h" +#include "pccore.h" +#include "diskimage/fddfile.h" +#include "fdd/diskdrv.h" +#if defined(SUPPORT_IDEIO)||defined(SUPPORT_SCSI) +#include "fdd/sxsi.h" +#include "resource.h" +#include "windows/dialog/np2class.h" +#include "windows/menu.h" +#endif + +extern UINT8 np2userpause; + +extern "C" REG8 cdchange_drv; + + UINT sys_updates; + + SYSMNGMISCINFO sys_miscinfo = {0}; + + +// ---- + +static UINT8 requestupdate = 0; + +static OEMCHAR title[2048] = {0}; +static OEMCHAR clock[256] = {0}; +static OEMCHAR misc[256] = {0}; + +static struct { + UINT32 tick; + UINT32 clock; + UINT32 draws; + SINT32 fps; + SINT32 khz; +} workclock; + +void sysmng_workclockreset(void) { + + workclock.tick = GETTICK(); + workclock.clock = CPU_CLOCK; + workclock.draws = drawcount; +} + +BOOL sysmng_workclockrenewal(void) { + + SINT32 tick; + + tick = GETTICK() - workclock.tick; + if (tick < 2000) { + return(FALSE); + } + workclock.tick += tick; + workclock.fps = ((drawcount - workclock.draws) * 10000) / tick; + workclock.draws = drawcount; + workclock.khz = (CPU_CLOCK - workclock.clock) / tick; + workclock.clock = CPU_CLOCK; + return(TRUE); +} + +OEMCHAR* DOSIOCALL sysmng_file_getname(OEMCHAR* lpPathName){ + if(_tcsnicmp(lpPathName, OEMTEXT("¥¥¥¥.¥¥"), 4)==0){ + return lpPathName; + }else{ + return file_getname(lpPathName); + } +} + +void sysmng_updatecaption(UINT8 flag) { + +#if defined(SUPPORT_IDEIO)||defined(SUPPORT_SCSI) + int i, cddrvnum = 1; +#endif + static OEMCHAR hddimgmenustrorg[4][MAX_PATH] = {0}; + static OEMCHAR hddimgmenustr[4][MAX_PATH] = {0}; +#if defined(SUPPORT_SCSI) + static OEMCHAR scsiimgmenustrorg[4][MAX_PATH] = {0}; + static OEMCHAR scsiimgmenustr[4][MAX_PATH] = {0}; +#endif + OEMCHAR work[2048] = {0}; + OEMCHAR fddtext[16] = {0}; + + if (flag & 1) { + title[0] = '¥0'; + for(i=0;i<4;i++){ + OEMSPRINTF(fddtext, OEMTEXT(" FDD%d:"), i+1); + if (fdd_diskready(i)) { + milstr_ncat(title, fddtext, NELEMENTS(title)); + milstr_ncat(title, file_getname(fdd_diskname(i)), NELEMENTS(title)); + } + } +#ifdef SUPPORT_IDEIO + for(i=0;i<4;i++){ + if(sxsi_getdevtype(i)==SXSIDEV_CDROM){ + OEMSPRINTF(work, OEMTEXT(" CD%d:"), cddrvnum); + if (sxsi_getdevtype(i)==SXSIDEV_CDROM){ + if(*(np2cfg.idecd[i])) { + milstr_ncat(title, work, NELEMENTS(title)); + milstr_ncat(title, sysmng_file_getname(np2cfg.idecd[i]), NELEMENTS(title)); + }else if(i==cdchange_drv && g_nevent.item[NEVENT_CDWAIT].clock > 0){ + milstr_ncat(title, work, NELEMENTS(title)); + milstr_ncat(title, OEMTEXT("Now Loading..."), NELEMENTS(title)); + } + } + cddrvnum++; + } + if(g_hWndMain){ + OEMCHAR newtext[MAX_PATH*2+100]; + OEMCHAR *fname; + OEMCHAR *fnamenext; + OEMCHAR *fnametmp; + OEMCHAR *fnamenexttmp; + HMENU hMenu = np2class_gethmenu(g_hWndMain); + HMENU hMenuTgt; + int hMenuTgtPos; + MENUITEMINFO mii = {0}; + menu_searchmenu(hMenu, IDM_IDE0STATE+i, &hMenuTgt, &hMenuTgtPos); + if(hMenu){ + mii.cbSize = sizeof(MENUITEMINFO); + if(!hddimgmenustrorg[i][0]){ + GetMenuString(hMenuTgt, IDM_IDE0STATE+i, hddimgmenustrorg[i], NELEMENTS(hddimgmenustrorg[0]), MF_BYCOMMAND); + } + if(np2cfg.idetype[i]==SXSIDEV_NC){ + _tcscpy(newtext, hddimgmenustrorg[i]); + _tcscat(newtext, OEMTEXT("[disabled]")); + }else{ + fname = sxsi_getfilename(i); + if(np2cfg.idetype[i]==SXSIDEV_CDROM){ + fnamenext = np2cfg.idecd[i]; + }else{ + fnamenext = (OEMCHAR*)diskdrv_getsxsi(i); + } + if(fname && *fname && fnamenext && *fnamenext && (fnametmp = sysmng_file_getname(fname))!=NULL && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ + _tcscpy(newtext, hddimgmenustrorg[i]); + _tcscat(newtext, fnametmp); + if(_tcscmp(fname, fnamenext)){ + _tcscat(newtext, OEMTEXT(" -> ")); + _tcscat(newtext, fnamenexttmp); + } + }else if(fnamenext && *fnamenext && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ + _tcscpy(newtext, hddimgmenustrorg[i]); + _tcscat(newtext, OEMTEXT("[none] -> ")); + _tcscat(newtext, fnamenexttmp); + }else if(fname && *fname && (fnametmp = sysmng_file_getname(fname))!=NULL){ + _tcscpy(newtext, hddimgmenustrorg[i]); + _tcscat(newtext, fnametmp); + _tcscat(newtext, OEMTEXT(" -> [none]")); + }else{ + _tcscpy(newtext, hddimgmenustrorg[i]); + _tcscat(newtext, OEMTEXT("[none]")); + } + } + if(_tcscmp(newtext, hddimgmenustr[i])){ + _tcscpy(hddimgmenustr[i], newtext); + mii.fMask = MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = hddimgmenustr[i]; + mii.cch = (UINT)_tcslen(hddimgmenustr[i]); + SetMenuItemInfo(hMenuTgt, IDM_IDE0STATE+i, MF_BYCOMMAND, &mii); + } + } + } + } +#else + for(i=0;i<2;i++){ + if(g_hWndMain){ + OEMCHAR newtext[MAX_PATH*2+100]; + OEMCHAR *fname; + OEMCHAR *fnamenext; + OEMCHAR *fnametmp; + OEMCHAR *fnamenexttmp; + HMENU hMenu = np2class_gethmenu(g_hWndMain); + HMENU hMenuTgt; + int hMenuTgtPos; + MENUITEMINFO mii = {0}; + menu_searchmenu(hMenu, IDM_IDE0STATE+i, &hMenuTgt, &hMenuTgtPos); + if(hMenu){ + mii.cbSize = sizeof(MENUITEMINFO); + if(!hddimgmenustrorg[i][0]){ + GetMenuString(hMenuTgt, IDM_IDE0STATE+i, hddimgmenustrorg[i], NELEMENTS(hddimgmenustrorg[0]), MF_BYCOMMAND); + } + fname = sxsi_getfilename(i); + fnamenext = (OEMCHAR*)diskdrv_getsxsi(i); + if(fname && *fname && fnamenext && *fnamenext && (fnametmp = sysmng_file_getname(fname))!=NULL && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ + _tcscpy(newtext, hddimgmenustrorg[i]); + _tcscat(newtext, fnametmp); + if(_tcscmp(fname, fnamenext)){ + _tcscat(newtext, OEMTEXT(" -> ")); + _tcscat(newtext, fnamenexttmp); + } + }else if(fnamenext && *fnamenext && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ + _tcscpy(newtext, hddimgmenustrorg[i]); + _tcscat(newtext, OEMTEXT("[none] -> ")); + _tcscat(newtext, fnamenexttmp); + }else if(fname && *fname && (fnametmp = sysmng_file_getname(fname))!=NULL){ + _tcscpy(newtext, hddimgmenustrorg[i]); + _tcscat(newtext, fnametmp); + _tcscat(newtext, OEMTEXT(" -> [none]")); + }else{ + _tcscpy(newtext, hddimgmenustrorg[i]); + _tcscat(newtext, OEMTEXT("[none]")); + } + if(_tcscmp(newtext, hddimgmenustr[i])){ + _tcscpy(hddimgmenustr[i], newtext); + mii.fMask = MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = hddimgmenustr[i]; + mii.cch = (UINT)_tcslen(hddimgmenustr[i]); + SetMenuItemInfo(hMenuTgt, IDM_IDE0STATE+i, MF_BYCOMMAND, &mii); + } + } + } + } +#endif +#ifdef SUPPORT_SCSI + for(i=0;i<4;i++){ + if(g_hWndMain){ + OEMCHAR newtext[MAX_PATH*2+100]; + OEMCHAR *fname; + OEMCHAR *fnamenext; + OEMCHAR *fnametmp; + OEMCHAR *fnamenexttmp; + HMENU hMenu = np2class_gethmenu(g_hWndMain); + HMENU hMenuTgt; + int hMenuTgtPos; + MENUITEMINFO mii = {0}; + menu_searchmenu(hMenu, IDM_SCSI0STATE+i, &hMenuTgt, &hMenuTgtPos); + if(hMenu){ + mii.cbSize = sizeof(MENUITEMINFO); + if(!scsiimgmenustrorg[i][0]){ + GetMenuString(hMenuTgt, IDM_SCSI0STATE+i, scsiimgmenustrorg[i], NELEMENTS(scsiimgmenustrorg[0]), MF_BYCOMMAND); + } + fname = sxsi_getfilename(i+0x20); + fnamenext = (OEMCHAR*)diskdrv_getsxsi(i+0x20); + if(fname && *fname && fnamenext && *fnamenext && (fnametmp = sysmng_file_getname(fname))!=NULL && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ + _tcscpy(newtext, scsiimgmenustrorg[i]); + _tcscat(newtext, fnametmp); + if(_tcscmp(fname, fnamenext)){ + _tcscat(newtext, OEMTEXT(" -> ")); + _tcscat(newtext, fnamenexttmp); + } + }else if(fnamenext && *fnamenext && (fnamenexttmp = sysmng_file_getname(fnamenext))!=NULL){ + _tcscpy(newtext, scsiimgmenustrorg[i]); + _tcscat(newtext, OEMTEXT("[none] -> ")); + _tcscat(newtext, fnamenexttmp); + }else if(fname && *fname && (fnametmp = sysmng_file_getname(fname))!=NULL){ + _tcscpy(newtext, scsiimgmenustrorg[i]); + _tcscat(newtext, fnametmp); + _tcscat(newtext, OEMTEXT(" -> [none]")); + }else{ + _tcscpy(newtext, scsiimgmenustrorg[i]); + _tcscat(newtext, OEMTEXT("[none]")); + } + if(_tcscmp(newtext, scsiimgmenustr[i])){ + _tcscpy(scsiimgmenustr[i], newtext); + mii.fMask = MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = scsiimgmenustr[i]; + mii.cch = (UINT)_tcslen(scsiimgmenustr[i]); + SetMenuItemInfo(hMenuTgt, IDM_SCSI0STATE+i, MF_BYCOMMAND, &mii); + } + } + } + } +#endif + } + + if (flag & 2) { + clock[0] = '¥0'; + if (np2oscfg.DISPCLK & 2) { + if (workclock.fps) { + OEMSPRINTF(clock, OEMTEXT(" - %u.%1uFPS"), + workclock.fps / 10, workclock.fps % 10); + } + else { + milstr_ncpy(clock, OEMTEXT(" - 0FPS"), NELEMENTS(clock)); + } + } + if (!np2userpause && (np2oscfg.DISPCLK & 1)) { + OEMSPRINTF(work, OEMTEXT(" %2u.%03uMHz"), + workclock.khz / 1000, workclock.khz % 1000); + if (clock[0] == '¥0') { + milstr_ncpy(clock, OEMTEXT(" -"), NELEMENTS(clock)); + } + milstr_ncat(clock, work, NELEMENTS(clock)); +#if 0 + OEMSPRINTF(work, OEMTEXT(" (debug: OPN %d / PSG %s)"), + opngen.playing, + (g_psg1.mixer & 0x3f)?OEMTEXT("ON"):OEMTEXT("OFF")); + milstr_ncat(clock, work, NELEMENTS(clock)); +#endif + } + } + + if (flag & 4) { + misc[0] = '¥0'; + if(sys_miscinfo.showvolume && sys_miscinfo.showmousespeed){ + OEMSPRINTF(misc, OEMTEXT(" (Volume: %d%%, Mouse speed: %d%%)"), np2cfg.vol_master, 100 * np2oscfg.mousemul/np2oscfg.mousediv); + }else if(sys_miscinfo.showvolume){ + OEMSPRINTF(misc, OEMTEXT(" (Volume: %d%%)"), np2cfg.vol_master); + }else if(sys_miscinfo.showmousespeed){ + OEMSPRINTF(misc, OEMTEXT(" (Mouse speed: %d%%)"), 100 * np2oscfg.mousemul/np2oscfg.mousediv); + } + } + + milstr_ncpy(work, np2oscfg.titles, NELEMENTS(work)); + milstr_ncat(work, misc, NELEMENTS(work)); + if(np2userpause){ + milstr_ncat(work, OEMTEXT(" [PAUSED]"), NELEMENTS(work)); + } + milstr_ncat(work, title, NELEMENTS(work)); + milstr_ncat(work, clock, NELEMENTS(work)); + SetWindowText(g_hWndMain, work); +} + +void sysmng_requestupdatecaption(UINT8 flag) { + requestupdate |= flag; // マルチスレッド呼び出し対策・・・ +} +void sysmng_requestupdatecheck() { + if(requestupdate != 0){ + sysmng_updatecaption(requestupdate); + requestupdate = 0; + }; +} diff --git a/windows/sysmng.h b/windows/sysmng.h index ee7d2291..ff5555fc 100644 --- a/windows/sysmng.h +++ b/windows/sysmng.h @@ -1,84 +1,84 @@ - -// ǁ[łʒmn - -enum { - SYS_UPDATECFG = 0x0001, - SYS_UPDATEOSCFG = 0x0002, - SYS_UPDATECLOCK = 0x0004, - SYS_UPDATERATE = 0x0008, - SYS_UPDATESBUF = 0x0010, - SYS_UPDATEMIDI = 0x0020, - SYS_UPDATESBOARD = 0x0040, - SYS_UPDATEFDD = 0x0080, - SYS_UPDATEHDD = 0x0100, - SYS_UPDATEMEMORY = 0x0200, - SYS_UPDATESERIAL1 = 0x0400, - - SYS_UPDATESNDDEV = 0x1000 -}; - -enum { - SYS_UPDATECAPTION_FDD = 0x01, - SYS_UPDATECAPTION_CLK = 0x02, - SYS_UPDATECAPTION_MISC = 0x04, - - SYS_UPDATECAPTION_ALL = 0xff, -}; - -typedef struct { - UINT8 showvolume; - UINT8 showmousespeed; -} SYSMNGMISCINFO; - -#ifdef __cplusplus -extern "C" { -#endif - -extern UINT sys_updates; - -extern SYSMNGMISCINFO sys_miscinfo; - -#if 0 -void sysmng_initialize(void); -void sysmng_update(UINT bitmap); -void sysmng_cpureset(void); -void sysmng_fddaccess(UINT8 drv); -void sysmng_hddaccess(UINT8 drv); -#else - -// }N(PɊ֐R[Ȃ) -#define sysmng_initialize() \ - sys_updates = 0 - -#define sysmng_update(a) \ - sys_updates |= (a); \ - if ((a) & SYS_UPDATEFDD) sysmng_updatecaption(SYS_UPDATECAPTION_FDD) - -#define sysmng_cpureset() \ - sys_updates &= (SYS_UPDATECFG | SYS_UPDATEOSCFG); \ - sysmng_workclockreset() - -#define sysmng_fddaccess(a) \ - toolwin_fddaccess((a)) - -#define sysmng_hddaccess(a) \ - toolwin_hddaccess((a)); - -#endif - - -// ---- ƂOSˑ - -void sysmng_workclockreset(void); -BOOL sysmng_workclockrenewal(void); -void sysmng_updatecaption(UINT8 flag); -void sysmng_requestupdatecaption(UINT8 flag); -void sysmng_requestupdatecheck(void); - -void toolwin_fddaccess(UINT8 drv); -void toolwin_hddaccess(UINT8 drv); - -#ifdef __cplusplus -} -#endif - + +// どーでもいい通知系 + +enum { + SYS_UPDATECFG = 0x0001, + SYS_UPDATEOSCFG = 0x0002, + SYS_UPDATECLOCK = 0x0004, + SYS_UPDATERATE = 0x0008, + SYS_UPDATESBUF = 0x0010, + SYS_UPDATEMIDI = 0x0020, + SYS_UPDATESBOARD = 0x0040, + SYS_UPDATEFDD = 0x0080, + SYS_UPDATEHDD = 0x0100, + SYS_UPDATEMEMORY = 0x0200, + SYS_UPDATESERIAL1 = 0x0400, + + SYS_UPDATESNDDEV = 0x1000 +}; + +enum { + SYS_UPDATECAPTION_FDD = 0x01, + SYS_UPDATECAPTION_CLK = 0x02, + SYS_UPDATECAPTION_MISC = 0x04, + + SYS_UPDATECAPTION_ALL = 0xff, +}; + +typedef struct { + UINT8 showvolume; + UINT8 showmousespeed; +} SYSMNGMISCINFO; + +#ifdef __cplusplus +extern "C" { +#endif + +extern UINT sys_updates; + +extern SYSMNGMISCINFO sys_miscinfo; + +#if 0 +void sysmng_initialize(void); +void sysmng_update(UINT bitmap); +void sysmng_cpureset(void); +void sysmng_fddaccess(UINT8 drv); +void sysmng_hddaccess(UINT8 drv); +#else + +// マクロ(単に関数コールしたくないだけ) +#define sysmng_initialize() \ + sys_updates = 0 + +#define sysmng_update(a) \ + sys_updates |= (a); \ + if ((a) & SYS_UPDATEFDD) sysmng_updatecaption(SYS_UPDATECAPTION_FDD) + +#define sysmng_cpureset() \ + sys_updates &= (SYS_UPDATECFG | SYS_UPDATEOSCFG); \ + sysmng_workclockreset() + +#define sysmng_fddaccess(a) \ + toolwin_fddaccess((a)) + +#define sysmng_hddaccess(a) \ + toolwin_hddaccess((a)); + +#endif + + +// ---- あとはOS依存部 + +void sysmng_workclockreset(void); +BOOL sysmng_workclockrenewal(void); +void sysmng_updatecaption(UINT8 flag); +void sysmng_requestupdatecaption(UINT8 flag); +void sysmng_requestupdatecheck(void); + +void toolwin_fddaccess(UINT8 drv); +void toolwin_hddaccess(UINT8 drv); + +#ifdef __cplusplus +} +#endif + diff --git a/windows/targetver.h b/windows/targetver.h old mode 100755 new mode 100644 index 59bc6a68..14c76145 --- a/windows/targetver.h +++ b/windows/targetver.h @@ -1,25 +1,25 @@ -#pragma once - -// The following macros define the minimum required platform. The minimum required platform -// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run -// your application. The macros work by enabling all features available on platform versions up to and -// including the version specified. - -// Modify the following defines if you have to target a platform prior to the ones specified below. -// Refer to MSDN for the latest info on corresponding values for different platforms. - -#ifndef WINVER // Specifies that the minimum required platform is Windows 95. -#define WINVER 0x0500 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows NT4.0 SP3. -#define _WIN32_WINNT 0x0403 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 95. -#define _WIN32_WINDOWS 0x0400 // Change this to the appropriate value to target Windows 98 or later. -#endif - -#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 2.0. -#define _WIN32_IE 0x0200 // Change this to the appropriate value to target other versions of IE. -#endif +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. + +#ifndef WINVER // Specifies that the minimum required platform is Windows 95. +#define WINVER 0x0500 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows NT4.0 SP3. +#define _WIN32_WINNT 0x0403 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 95. +#define _WIN32_WINDOWS 0x0400 // Change this to the appropriate value to target Windows 98 or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 2.0. +#define _WIN32_IE 0x0200 // Change this to the appropriate value to target other versions of IE. +#endif diff --git a/windows/taskmng.cpp b/windows/taskmng.cpp index f32232a2..44ee13bd 100644 --- a/windows/taskmng.cpp +++ b/windows/taskmng.cpp @@ -1,15 +1,15 @@ -#include -#include -#if defined(SUPPORT_MULTITHREAD) -#include "np2.h" -#endif - -void taskmng_exit(void) { - -#if defined(SUPPORT_MULTITHREAD) - PostMessage(g_hWndMain, WM_CLOSE, 0, 0); -#else - PostQuitMessage(0); -#endif -} - +#include +#include +#if defined(SUPPORT_MULTITHREAD) +#include "np2.h" +#endif + +void taskmng_exit(void) { + +#if defined(SUPPORT_MULTITHREAD) + PostMessage(g_hWndMain, WM_CLOSE, 0, 0); +#else + PostQuitMessage(0); +#endif +} + diff --git a/windows/taskmng.h b/windows/taskmng.h old mode 100755 new mode 100644 index a306164f..1587b219 --- a/windows/taskmng.h +++ b/windows/taskmng.h @@ -1,11 +1,11 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -void taskmng_exit(void); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +void taskmng_exit(void); + +#ifdef __cplusplus +} +#endif + diff --git a/windows/timemng.cpp b/windows/timemng.cpp old mode 100755 new mode 100644 index 0513eb98..8d27e602 --- a/windows/timemng.cpp +++ b/windows/timemng.cpp @@ -1,10 +1,10 @@ -#include -#include - - -BRESULT timemng_gettime(_SYSTIME *systime) { - - GetLocalTime((SYSTEMTIME *)systime); - return(SUCCESS); -} - +#include +#include + + +BRESULT timemng_gettime(_SYSTIME *systime) { + + GetLocalTime((SYSTEMTIME *)systime); + return(SUCCESS); +} + diff --git a/windows/timemng.h b/windows/timemng.h old mode 100755 new mode 100644 index 7489551e..a7412363 --- a/windows/timemng.h +++ b/windows/timemng.h @@ -1,26 +1,26 @@ - - -// Win32 SYSTEMTIME ストラクチャ - -typedef struct { - UINT16 year; - UINT16 month; - UINT16 week; - UINT16 day; - UINT16 hour; - UINT16 minute; - UINT16 second; - UINT16 milli; -} _SYSTIME; - - -#ifdef __cplusplus -extern "C" { -#endif - -BRESULT timemng_gettime(_SYSTIME *systime); - -#ifdef __cplusplus -} -#endif - + + +// Win32 SYSTEMTIME ストラクチャ + +typedef struct { + UINT16 year; + UINT16 month; + UINT16 week; + UINT16 day; + UINT16 hour; + UINT16 minute; + UINT16 second; + UINT16 milli; +} _SYSTIME; + + +#ifdef __cplusplus +extern "C" { +#endif + +BRESULT timemng_gettime(_SYSTIME *systime); + +#ifdef __cplusplus +} +#endif + diff --git a/windows/winkbd.cpp b/windows/winkbd.cpp index 819ad8ad..5ea4c39d 100644 --- a/windows/winkbd.cpp +++ b/windows/winkbd.cpp @@ -1,273 +1,273 @@ -#include -#include -#include "winkbd.h" -#include -#include - - -#define NC 0xff - -static UINT8 key106[256] = { - // , , ,STOP, , , , ; 0x00 - NC, NC, NC,0x60, NC, NC, NC, NC, - // BS, TAB, , , CLR, ENT, , ; 0x08 - 0x0e,0x0f, NC, NC, NC,0x1c, NC, NC, - // SFT,CTRL, ALT,PAUS,CAPS,KANA, , ; 0x10 - 0x70,0x74,0x73,0x60,0x71,0x72, NC, NC, - // FIN, KAN, , ESC,XFER,NFER, , MD ; 0x18 - NC, NC, NC,0x00,0x35,0x51, NC, NC, - // SPC,RLUP,RLDN, END,HOME, ←, ↑, → ; 0x20 - 0x34,0x37,0x36,0x3f,0x3e,0x3b,0x3a,0x3c, - // ↓, SEL, PNT, EXE,COPY, INS, DEL, HLP ; 0x28 - 0x3d, NC, NC, NC, NC,0x38,0x39, NC, - // 0, 1, 2, 3, 4, 5, 6, 7 ; 0x30 - 0x0a,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - // 8, 9, , , , , , ; 0x38 - 0x08,0x09, NC, NC, NC, NC, NC, NC, - // , A, B, C, D, E, F, G ; 0x40 - NC,0x1d,0x2d,0x2b,0x1f,0x12,0x20,0x21, - // H, I, J, K, L, M, N, O ; 0x48 - 0x22,0x17,0x23,0x24,0x25,0x2f,0x2e,0x18, - // P, Q, R, S, T, U, V, W ; 0x50 - 0x19,0x10,0x13,0x1e,0x14,0x16,0x2c,0x11, - // X, Y, Z,LWIN,RWIN, APP, , ; 0x58 -#ifdef SUPPORT_PC9801_119 - 0x2a,0x15,0x29,0x78,0x77,0x79, NC, NC, -#else - 0x2a,0x15,0x29, NC, NC, NC, NC, NC, -#endif - // <0>,<1>,<2>,<3>,<4>,<5>,<6>,<7> ; 0x60 - 0x4e,0x4a,0x4b,0x4c,0x46,0x47,0x48,0x42, - // <8>,<9>,<*>,<+>,<,>,<−>,<.>,</> ; 0x68 - 0x43,0x44,0x45,0x49,0x4f,0x40,0x50,0x41, - // f.1, f.2, f.3, f.4, f.5, f.6, f.7, f.8 ; 0x70 - 0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69, - // f.9, f10, f11, f12, f13, f14, f15, f16 ; 0x78 - 0x6a,0x6b, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0x80 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0x88 - NC, NC, NC, NC, NC, NC, NC, NC, - // HELP, ALT,<=>, , , , , ; 0x90 - NC, NC,0x4d, NC, NC, NC, NC, NC, // ver0.28 -// NC,0x73,0x4d, NC, NC, NC, NC, NC, // ver0.28 - // , , , , , , , ; 0x98 - NC, NC, NC, NC, NC, NC, NC, NC, - // SFTL,SFTR, , , , , , ; 0xa0 - 0x70,0x7d, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xa8 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xb0 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , :, ;, ,, −, ., / ; 0xb8 - NC, NC,0x27,0x26,0x30,0x0b,0x31,0x32, - // @, , , , , , , ; 0xc0 - 0x1a, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xc8 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xd0 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , [, ¥, ], ^, _ ; 0xd8 - NC, NC, NC,0x1b,0x0d,0x28,0x0c,0x33, - // , , _, , , , , ; 0xe0 - NC, NC,0x33, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xe8 - NC, NC, NC, NC, NC, NC, NC, NC, - // CAPS, ,KANA, , , , , ; 0xf0 - 0x71, NC,0x72, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xf8 - NC, NC, NC, NC, NC, NC, NC, NC}; - -static const UINT8 key106ext[256] = { - // , , ,STOP, , , , ; 0x00 - NC, NC, NC, NC, NC, NC, NC, NC, - // BS, TAB, , , CLR, ENT, , ; 0x08 - NC, NC, NC, NC, NC, NC, NC, NC, - // SFT,CTRL, ALT,PAUS,CAPS,KANA, , ; 0x10 - NC, NC, NC, NC, NC, NC, NC, NC, - // FIN, KAN, , ESC,XFER,NFER, , MD ; 0x18 - NC, NC, NC, NC, NC, NC, NC, NC, - // SPC,RLUP,RLDN, END,HOME, ←, ↑, → ; 0x20 - NC,0x44,0x4c,0x4a,0x42,0x46,0x43,0x48, - // ↓, SEL, PNT, EXE,COPY, INS, DEL, HLP ; 0x28 - 0x4b, NC, NC, NC, NC,0x4e,0x50, NC, - // 0, 1, 2, 3, 4, 5, 6, 7 ; 0x30 - NC, NC, NC, NC, NC, NC, NC, NC, - // 8, 9, , , , , , ; 0x38 - NC, NC, NC, NC, NC, NC, NC, NC, - // , A, B, C, D, E, F, G ; 0x40 - NC, NC, NC, NC, NC, NC, NC, NC, - // H, I, J, K, L, M, N, O ; 0x48 - NC, NC, NC, NC, NC, NC, NC, NC, - // P, Q, R, S, T, U, V, W ; 0x50 - NC, NC, NC, NC, NC, NC, NC, NC, - // X, Y, Z,LWIN,RWIN, APP, , ; 0x58 - NC, NC, NC, NC, NC, NC, NC, NC, - // <0>,<1>,<2>,<3>,<4>,<5>,<6>,<7> ; 0x60 - NC, NC, NC, NC, NC, NC, NC, NC, - // <8>,<9>,<*>,<+>,<,>,<−>,<.>,</> ; 0x68 - NC, NC, NC, NC, NC, NC, NC, NC, - // f.1, f.2, f.3, f.4, f.5, f.6, f.7, f.8 ; 0x70 - NC, NC, NC, NC, NC, NC, NC, NC, - // f.9, f10, f11, f12, f13, f14, f15, f16 ; 0x78 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0x80 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0x88 - NC, NC, NC, NC, NC, NC, NC, NC, - // HELP, ALT,<=>, , , , , ; 0x90 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0x98 - NC, NC, NC, NC, NC, NC, NC, NC, - // SFTL,SFTR, , , , , , ; 0xa0 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xa8 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xb0 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , :, ;, ,, −, ., / ; 0xb8 - NC, NC, NC, NC, NC, NC, NC, NC, - // @, , , , , , , ; 0xc0 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xc8 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xd0 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , [, ¥, ], ^, ; 0xd8 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , _, , , , , ; 0xe0 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xe8 - NC, NC, NC, NC, NC, NC, NC, NC, - // CAPS, ,KANA, , , , , ; 0xf0 - NC, NC, NC, NC, NC, NC, NC, NC, - // , , , , , , , ; 0xf8 - NC, NC, NC, NC, NC, NC, NC, NC}; - -static const UINT8 f12keys[] = { - 0x61, 0x60, 0x4d, 0x4f, 0x76, 0x77, 0xff, 0xff, 0xff, 0xff, 0xff}; - - -void winkbd_keydown(WPARAM wParam, LPARAM lParam) { - - UINT8 data; - - np2_multithread_EnterCriticalSection(); - if (wParam == VK_SHIFT) { - UINT scancode = (lParam & 0x00ff0000) >> 16; - wParam = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); - } - - data = key106[wParam & 0xff]; - if (data != NC) { - if ((data == 0x73) && - (np2oscfg.KEYBOARD == KEY_KEY101) && - (lParam & 0x01000000)) { - data = 0x72; - } - else if ((np2oscfg.KEYBOARD != KEY_PC98) && - (!(lParam & 0x01000000)) && - (key106ext[wParam & 0xff] != NC) && - (!np2oscfg.USENUMLOCK)) { // ver0.28 - keystat_senddata(0x70); // PC/AT only! - data = key106ext[wParam & 0xff]; - } - if ((np2oscfg.KEYBOARD == KEY_KEY106 && data == 0x79)) - { - // APPキー特例 - keystat_senddataraw(data); - } - else - { - keystat_senddata(data); - } - } - else { // ver0.28 - if ((!np2oscfg.KEYBOARD != KEY_PC98) && (wParam == 0x0c)) { - keystat_senddata(0x70); // PC/AT only - keystat_senddata(0x47); - } - } - np2_multithread_LeaveCriticalSection(); -} - -void winkbd_keyup(WPARAM wParam, LPARAM lParam) { - - UINT8 data; - - np2_multithread_EnterCriticalSection(); - if (wParam == VK_SHIFT) { - UINT scancode = (lParam & 0x00ff0000) >> 16; - wParam = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); - } - - data = key106[wParam & 0xff]; - if (data != NC) { - if ((data == 0x73) && - (np2oscfg.KEYBOARD == KEY_KEY101) && - (lParam & 0x01000000)) { - ; // none ! - } - else if ((np2oscfg.KEYBOARD != KEY_PC98) && - (!(lParam & 0x01000000)) && - (key106ext[wParam & 0xff] != NC) && - (!np2oscfg.USENUMLOCK)) { // ver0.28 - keystat_senddata(0x70 | 0x80); // PC/AT only - data = key106ext[wParam & 0xff]; - } - if (((np2oscfg.KEYBOARD != KEY_PC98) && data == 0x79)) - { - // APPキー特例 - keystat_senddataraw((UINT8)(data | 0x80)); - } - else - { - keystat_senddata((UINT8)(data | 0x80)); - } - } - else { // ver0.28 - if ((np2oscfg.KEYBOARD != KEY_PC98) && (wParam == 0x0c)) { - keystat_senddata(0x70 | 0x80); // PC/AT only - keystat_senddata(0x47 | 0x80); - } - } - np2_multithread_LeaveCriticalSection(); -} - -void winkbd_roll(BOOL pcat) { - - if (pcat) { - key106[0x21] = 0x36; - key106[0x22] = 0x37; - } - else { - key106[0x21] = 0x37; - key106[0x22] = 0x36; - } -} - -void winkbd_setf12(UINT f12key) { - - UINT8 key; - - f12key--; - if (f12key < NELEMENTS(f12keys)) { - key = f12keys[f12key]; - } - else { - key = NC; - } - key106[0x7b] = key; -} - -void winkbd_resetf12(void) { - - UINT i; - - np2_multithread_EnterCriticalSection(); - for (i=0; i +#include +#include "winkbd.h" +#include +#include + + +#define NC 0xff + +static UINT8 key106[256] = { + // , , ,STOP, , , , ; 0x00 + NC, NC, NC,0x60, NC, NC, NC, NC, + // BS, TAB, , , CLR, ENT, , ; 0x08 + 0x0e,0x0f, NC, NC, NC,0x1c, NC, NC, + // SFT,CTRL, ALT,PAUS,CAPS,KANA, , ; 0x10 + 0x70,0x74,0x73,0x60,0x71,0x72, NC, NC, + // FIN, KAN, , ESC,XFER,NFER, , MD ; 0x18 + NC, NC, NC,0x00,0x35,0x51, NC, NC, + // SPC,RLUP,RLDN, END,HOME, ←, ↑, → ; 0x20 + 0x34,0x37,0x36,0x3f,0x3e,0x3b,0x3a,0x3c, + // ↓, SEL, PNT, EXE,COPY, INS, DEL, HLP ; 0x28 + 0x3d, NC, NC, NC, NC,0x38,0x39, NC, + // 0, 1, 2, 3, 4, 5, 6, 7 ; 0x30 + 0x0a,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + // 8, 9, , , , , , ; 0x38 + 0x08,0x09, NC, NC, NC, NC, NC, NC, + // , A, B, C, D, E, F, G ; 0x40 + NC,0x1d,0x2d,0x2b,0x1f,0x12,0x20,0x21, + // H, I, J, K, L, M, N, O ; 0x48 + 0x22,0x17,0x23,0x24,0x25,0x2f,0x2e,0x18, + // P, Q, R, S, T, U, V, W ; 0x50 + 0x19,0x10,0x13,0x1e,0x14,0x16,0x2c,0x11, + // X, Y, Z,LWIN,RWIN, APP, , ; 0x58 +#ifdef SUPPORT_PC9801_119 + 0x2a,0x15,0x29,0x78,0x77,0x79, NC, NC, +#else + 0x2a,0x15,0x29, NC, NC, NC, NC, NC, +#endif + // <0>,<1>,<2>,<3>,<4>,<5>,<6>,<7> ; 0x60 + 0x4e,0x4a,0x4b,0x4c,0x46,0x47,0x48,0x42, + // <8>,<9>,<*>,<+>,<,>,<−>,<.>,</> ; 0x68 + 0x43,0x44,0x45,0x49,0x4f,0x40,0x50,0x41, + // f.1, f.2, f.3, f.4, f.5, f.6, f.7, f.8 ; 0x70 + 0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69, + // f.9, f10, f11, f12, f13, f14, f15, f16 ; 0x78 + 0x6a,0x6b, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0x80 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0x88 + NC, NC, NC, NC, NC, NC, NC, NC, + // HELP, ALT,<=>, , , , , ; 0x90 + NC, NC,0x4d, NC, NC, NC, NC, NC, // ver0.28 +// NC,0x73,0x4d, NC, NC, NC, NC, NC, // ver0.28 + // , , , , , , , ; 0x98 + NC, NC, NC, NC, NC, NC, NC, NC, + // SFTL,SFTR, , , , , , ; 0xa0 + 0x70,0x7d, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xa8 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xb0 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , :, ;, ,, −, ., / ; 0xb8 + NC, NC,0x27,0x26,0x30,0x0b,0x31,0x32, + // @, , , , , , , ; 0xc0 + 0x1a, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xc8 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xd0 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , [, ¥, ], ^, _ ; 0xd8 + NC, NC, NC,0x1b,0x0d,0x28,0x0c,0x33, + // , , _, , , , , ; 0xe0 + NC, NC,0x33, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xe8 + NC, NC, NC, NC, NC, NC, NC, NC, + // CAPS, ,KANA, , , , , ; 0xf0 + 0x71, NC,0x72, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xf8 + NC, NC, NC, NC, NC, NC, NC, NC}; + +static const UINT8 key106ext[256] = { + // , , ,STOP, , , , ; 0x00 + NC, NC, NC, NC, NC, NC, NC, NC, + // BS, TAB, , , CLR, ENT, , ; 0x08 + NC, NC, NC, NC, NC, NC, NC, NC, + // SFT,CTRL, ALT,PAUS,CAPS,KANA, , ; 0x10 + NC, NC, NC, NC, NC, NC, NC, NC, + // FIN, KAN, , ESC,XFER,NFER, , MD ; 0x18 + NC, NC, NC, NC, NC, NC, NC, NC, + // SPC,RLUP,RLDN, END,HOME, ←, ↑, → ; 0x20 + NC,0x44,0x4c,0x4a,0x42,0x46,0x43,0x48, + // ↓, SEL, PNT, EXE,COPY, INS, DEL, HLP ; 0x28 + 0x4b, NC, NC, NC, NC,0x4e,0x50, NC, + // 0, 1, 2, 3, 4, 5, 6, 7 ; 0x30 + NC, NC, NC, NC, NC, NC, NC, NC, + // 8, 9, , , , , , ; 0x38 + NC, NC, NC, NC, NC, NC, NC, NC, + // , A, B, C, D, E, F, G ; 0x40 + NC, NC, NC, NC, NC, NC, NC, NC, + // H, I, J, K, L, M, N, O ; 0x48 + NC, NC, NC, NC, NC, NC, NC, NC, + // P, Q, R, S, T, U, V, W ; 0x50 + NC, NC, NC, NC, NC, NC, NC, NC, + // X, Y, Z,LWIN,RWIN, APP, , ; 0x58 + NC, NC, NC, NC, NC, NC, NC, NC, + // <0>,<1>,<2>,<3>,<4>,<5>,<6>,<7> ; 0x60 + NC, NC, NC, NC, NC, NC, NC, NC, + // <8>,<9>,<*>,<+>,<,>,<−>,<.>,</> ; 0x68 + NC, NC, NC, NC, NC, NC, NC, NC, + // f.1, f.2, f.3, f.4, f.5, f.6, f.7, f.8 ; 0x70 + NC, NC, NC, NC, NC, NC, NC, NC, + // f.9, f10, f11, f12, f13, f14, f15, f16 ; 0x78 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0x80 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0x88 + NC, NC, NC, NC, NC, NC, NC, NC, + // HELP, ALT,<=>, , , , , ; 0x90 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0x98 + NC, NC, NC, NC, NC, NC, NC, NC, + // SFTL,SFTR, , , , , , ; 0xa0 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xa8 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xb0 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , :, ;, ,, −, ., / ; 0xb8 + NC, NC, NC, NC, NC, NC, NC, NC, + // @, , , , , , , ; 0xc0 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xc8 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xd0 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , [, ¥, ], ^, ; 0xd8 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , _, , , , , ; 0xe0 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xe8 + NC, NC, NC, NC, NC, NC, NC, NC, + // CAPS, ,KANA, , , , , ; 0xf0 + NC, NC, NC, NC, NC, NC, NC, NC, + // , , , , , , , ; 0xf8 + NC, NC, NC, NC, NC, NC, NC, NC}; + +static const UINT8 f12keys[] = { + 0x61, 0x60, 0x4d, 0x4f, 0x76, 0x77, 0xff, 0xff, 0xff, 0xff, 0xff}; + + +void winkbd_keydown(WPARAM wParam, LPARAM lParam) { + + UINT8 data; + + np2_multithread_EnterCriticalSection(); + if (wParam == VK_SHIFT) { + UINT scancode = (lParam & 0x00ff0000) >> 16; + wParam = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); + } + + data = key106[wParam & 0xff]; + if (data != NC) { + if ((data == 0x73) && + (np2oscfg.KEYBOARD == KEY_KEY101) && + (lParam & 0x01000000)) { + data = 0x72; + } + else if ((np2oscfg.KEYBOARD != KEY_PC98) && + (!(lParam & 0x01000000)) && + (key106ext[wParam & 0xff] != NC) && + (!np2oscfg.USENUMLOCK)) { // ver0.28 + keystat_senddata(0x70); // PC/AT only! + data = key106ext[wParam & 0xff]; + } + if ((np2oscfg.KEYBOARD == KEY_KEY106 && data == 0x79)) + { + // APPキー特例 + keystat_senddataraw(data); + } + else + { + keystat_senddata(data); + } + } + else { // ver0.28 + if ((!np2oscfg.KEYBOARD != KEY_PC98) && (wParam == 0x0c)) { + keystat_senddata(0x70); // PC/AT only + keystat_senddata(0x47); + } + } + np2_multithread_LeaveCriticalSection(); +} + +void winkbd_keyup(WPARAM wParam, LPARAM lParam) { + + UINT8 data; + + np2_multithread_EnterCriticalSection(); + if (wParam == VK_SHIFT) { + UINT scancode = (lParam & 0x00ff0000) >> 16; + wParam = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); + } + + data = key106[wParam & 0xff]; + if (data != NC) { + if ((data == 0x73) && + (np2oscfg.KEYBOARD == KEY_KEY101) && + (lParam & 0x01000000)) { + ; // none ! + } + else if ((np2oscfg.KEYBOARD != KEY_PC98) && + (!(lParam & 0x01000000)) && + (key106ext[wParam & 0xff] != NC) && + (!np2oscfg.USENUMLOCK)) { // ver0.28 + keystat_senddata(0x70 | 0x80); // PC/AT only + data = key106ext[wParam & 0xff]; + } + if (((np2oscfg.KEYBOARD != KEY_PC98) && data == 0x79)) + { + // APPキー特例 + keystat_senddataraw((UINT8)(data | 0x80)); + } + else + { + keystat_senddata((UINT8)(data | 0x80)); + } + } + else { // ver0.28 + if ((np2oscfg.KEYBOARD != KEY_PC98) && (wParam == 0x0c)) { + keystat_senddata(0x70 | 0x80); // PC/AT only + keystat_senddata(0x47 | 0x80); + } + } + np2_multithread_LeaveCriticalSection(); +} + +void winkbd_roll(BOOL pcat) { + + if (pcat) { + key106[0x21] = 0x36; + key106[0x22] = 0x37; + } + else { + key106[0x21] = 0x37; + key106[0x22] = 0x36; + } +} + +void winkbd_setf12(UINT f12key) { + + UINT8 key; + + f12key--; + if (f12key < NELEMENTS(f12keys)) { + key = f12keys[f12key]; + } + else { + key = NC; + } + key106[0x7b] = key; +} + +void winkbd_resetf12(void) { + + UINT i; + + np2_multithread_EnterCriticalSection(); + for (i=0; i -#include "winloc.h" - - -enum { - SNAPDOTPULL = 12, - SNAPDOTREL = 16 -}; -typedef HRESULT (WINAPI *pfnDwmIsCompositionEnabled)( - BOOL *pfEnabled -); -typedef HRESULT (WINAPI *pfnDwmGetWindowAttribute)( - HWND hwnd, - DWORD dwAttribute, - PVOID pvAttribute, - DWORD cbAttribute -); -typedef enum _DWMWINDOWATTRIBUTE { - DWMWA_NCRENDERING_ENABLED = 1, - DWMWA_NCRENDERING_POLICY, - DWMWA_TRANSITIONS_FORCEDISABLED, - DWMWA_ALLOW_NCPAINT, - DWMWA_CAPTION_BUTTON_BOUNDS, - DWMWA_NONCLIENT_RTL_LAYOUT, - DWMWA_FORCE_ICONIC_REPRESENTATION, - DWMWA_FLIP3D_POLICY, - DWMWA_EXTENDED_FRAME_BOUNDS, - DWMWA_HAS_ICONIC_BITMAP, - DWMWA_DISALLOW_PEEK, - DWMWA_EXCLUDED_FROM_PEEK, - DWMWA_CLOAK, - DWMWA_CLOAKED, - DWMWA_FREEZE_REPRESENTATION, - DWMWA_LAST -} DWMWINDOWATTRIBUTE; - -static pfnDwmIsCompositionEnabled F_DwmIsCompositionEnabled = NULL; -static pfnDwmGetWindowAttribute F_DwmGetWindowAttribute = NULL; -static HMODULE hDwmModule = NULL; -static int noDWM = 0; - -BOOL winloc_GetWindowRect(HWND hwnd, LPRECT lpRect); - -BOOL winloc_InitDwmFunc() { - RECT r = {0}; - - if(noDWM){ - // DWM環境でない - return FALSE; - }else{ - if(!hDwmModule){ - hDwmModule = LoadLibrary(_T("dwmapi.dll")); - if(!hDwmModule){ - // DWM環境でない - noDWM = 1; - return FALSE; - } - F_DwmIsCompositionEnabled = (pfnDwmIsCompositionEnabled)GetProcAddress(hDwmModule, "DwmIsCompositionEnabled"); - F_DwmGetWindowAttribute = (pfnDwmGetWindowAttribute)GetProcAddress(hDwmModule, "DwmGetWindowAttribute"); - if(!F_DwmIsCompositionEnabled || !F_DwmGetWindowAttribute){ - // 何故かDwmGetWindowAttributeやDwmIsCompositionEnabledが無い? - FreeLibrary(hDwmModule); - hDwmModule = NULL; - F_DwmGetWindowAttribute = NULL; - noDWM = 1; - return FALSE; - } - } - // DWM環境 - return TRUE; - } -} -void winloc_DisposeDwmFunc() { - if(hDwmModule){ - F_DwmIsCompositionEnabled = NULL; - F_DwmGetWindowAttribute = NULL; - FreeLibrary(hDwmModule); - hDwmModule = NULL; - } -} - -BOOL winloc_GetWindowRect(HWND hwnd, LPRECT lpRect) { - if(F_DwmGetWindowAttribute){ - HRESULT hr = 0; - BOOL dwmenable = FALSE; - hr = F_DwmIsCompositionEnabled(&dwmenable); - if(SUCCEEDED(hr) && dwmenable){ - // DWM環境 - hr = F_DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, lpRect, sizeof(RECT)); - if(SUCCEEDED(hr)){ - return 1; - }else{ - return GetWindowRect(hwnd, lpRect); - } - }else{ - // コンポジションOFF - return GetWindowRect(hwnd, lpRect); - } - }else{ - // DWM環境でない - return GetWindowRect(hwnd, lpRect); - } -} - -void winloc_getDWMmargin(HWND hwnd, int *ofsx, int *ofsy) { - RECT rDWM, r; - winloc_GetWindowRect(hwnd, &rDWM); - GetWindowRect(hwnd, &r); - *ofsx = rDWM.left - r.left; - *ofsy = rDWM.top - r.top; -} - -void winloc_setclientsize(HWND hwnd, int width, int height) { - - RECT rectDisktop; - int scx; - int scy; - UINT cnt; - RECT rectWindow; - RECT rectClient; - int x, y, w, h; - - SystemParametersInfo(SPI_GETWORKAREA, 0, &rectDisktop, 0); - scx = GetSystemMetrics(SM_CXSCREEN); - scy = GetSystemMetrics(SM_CYSCREEN); - // マルチモニタ暫定対応 ver0.86 rev30 - rectDisktop.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); - rectDisktop.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); - - cnt = 2; - do { - winloc_GetWindowRect(hwnd, &rectWindow); - GetClientRect(hwnd, &rectClient); - w = width + (rectWindow.right - rectWindow.left) - - (rectClient.right - rectClient.left); - h = height + (rectWindow.bottom - rectWindow.top) - - (rectClient.bottom - rectClient.top); - - x = rectWindow.left; - y = rectWindow.top; - if (scx < w) { - x = (scx - w) / 2; - } - else { - if ((x + w) > rectDisktop.right) { - x = rectDisktop.right - w; - } - if (x < rectDisktop.left) { - x = rectDisktop.left; - } - } - if (scy < h) { - y = (scy - h) / 2; - } - else { - if ((y + h) > rectDisktop.bottom) { - y = rectDisktop.bottom - h; - } - if (y < rectDisktop.top) { - y = rectDisktop.top; - } - } - if(!noDWM){ - // DWM補正 - RECT rectmp1; - RECT rectmp2; - GetWindowRect(hwnd, &rectmp1); - winloc_GetWindowRect(hwnd, &rectmp2); - x -= rectmp2.left - rectmp1.left; - y -= rectmp2.top - rectmp1.top; - w = width + (rectmp1.right - rectmp1.left) - - (rectClient.right - rectClient.left); - h = height + (rectmp1.bottom - rectmp1.top) - - (rectClient.bottom - rectClient.top); - } - MoveWindow(hwnd, x, y, w, h, TRUE); - } while(--cnt); -} - - -// ---- - -void winloc_movingstart(WINLOC *wl) { - - ZeroMemory(wl, sizeof(WINLOC)); -} - -void winloc_movingproc(WINLOC *wl, RECT *rect) { - - RECT workrc; - int winlx; - int winly; - int d; - RECT rectmp1; - RECT rectmp2; - if(!noDWM){ - // DWM補正 - GetWindowRect(GetActiveWindow(), &rectmp1); - winloc_GetWindowRect(GetActiveWindow(), &rectmp2); - rect->left += rectmp2.left - rectmp1.left; - rect->top += rectmp2.top - rectmp1.top; - rect->right += rectmp2.right - rectmp1.right; - rect->bottom += rectmp2.bottom - rectmp1.bottom; - } - - SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); - winlx = rect->right - rect->left; - winly = rect->bottom - rect->top; - // マルチモニタ暫定対応 ver0.86 rev30 - workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); - workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); - - if ((winlx > (workrc.right - workrc.left)) || - (winly > (workrc.bottom - workrc.top))) { - if(!noDWM){ - // DWM補正 - rect->left -= rectmp2.left - rectmp1.left; - rect->top -= rectmp2.top - rectmp1.top; - rect->right -= rectmp2.right - rectmp1.right; - rect->bottom -= rectmp2.bottom - rectmp1.bottom; - } - return; - } - - if (wl->flag & 1) { - wl->gx += rect->left - wl->tx; - rect->left = wl->tx; - if ((wl->gx >= SNAPDOTREL) || (wl->gx <= -SNAPDOTREL)) { - wl->flag &= ~1; - rect->left += wl->gx; - wl->gx = 0; - } - rect->right = rect->left + winlx; - } - if (wl->flag & 2) { - wl->gy += rect->top - wl->ty; - rect->top = wl->ty; - if ((wl->gy >= SNAPDOTREL) || (wl->gy <= -SNAPDOTREL)) { - wl->flag &= ~2; - rect->top += wl->gy; - wl->gy = 0; - } - rect->bottom = rect->top + winly; - } - - if (!(wl->flag & 1)) { - do { - d = rect->left - workrc.left; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - d = rect->right - workrc.right; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - } while(0); - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - rect->left -= d; - rect->right = rect->left + winlx; - wl->flag |= 1; - wl->gx = d; - wl->tx = rect->left; - } - } - if (!(wl->flag & 2)) { - do { - d = rect->top - workrc.top; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - d = rect->bottom - workrc.bottom; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - } while(0); - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - rect->top -= d; - rect->bottom = rect->top + winly; - wl->flag |= 2; - wl->gy = d; - wl->ty = rect->top; - } - } - if(!noDWM){ - // DWM補正 - rect->left -= rectmp2.left - rectmp1.left; - rect->top -= rectmp2.top - rectmp1.top; - rect->right -= rectmp2.right - rectmp1.right; - rect->bottom -= rectmp2.bottom - rectmp1.bottom; - } -} - - -// ---- - -static UINT8 isconnect(const RECT *parent, const RECT *self) { - - UINT8 connect; - - connect = 0; - if ((self->bottom >= parent->top) && (self->top <= parent->bottom)) { - if (self->right == parent->left) { - connect += 1; - } - else if (self->left == parent->right) { - connect += 2; - } - } - if ((!(connect & 0x0f)) && - ((self->bottom == parent->top) || (self->top == parent->bottom))) { - if (self->left == parent->left) { - connect += 3; - } - else if (self->right == parent->right) { - connect += 4; - } - } - - if ((self->right >= parent->left) && (self->left <= parent->right)) { - if (self->bottom == parent->top) { - connect += 1 << 4; - } - else if (self->top == parent->bottom) { - connect += 2 << 4; - } - } - if ((!(connect & 0xf0)) && - ((self->right == parent->left) || (self->left == parent->right))) { - if (self->top == parent->top) { - connect += 3 << 4; - } - else if (self->bottom == parent->bottom) { - connect += 4 << 4; - } - } - return(connect); -} - -WINLOCEX winlocex_create(HWND base, const HWND *child, UINT count) { - - WINLOCEX ret; - HWND *list; - UINT inlist; - UINT i; - UINT j; - HWND hwnd; - UINT allocsize; - WLEXWND *wnd; - RECT rect; - UINT8 connect; - WLEXWND *p; - - if (child == NULL) { - count = 0; - } - ret = NULL; - list = NULL; - inlist = 0; - if (count) { - list = (HWND *)_MALLOC(count * sizeof(HWND *), "wnd list"); - if (list == NULL) { - goto wlecre_err1; - } - for (i=0; i= inlist) { - list[inlist++] = hwnd; - } - } - } - } - allocsize = sizeof(_WINLOCEX) + (sizeof(WLEXWND) * inlist); - ret = (WINLOCEX)_MALLOC(allocsize, "winlocex"); - if (ret == NULL) { - goto wlecre_err2; - } - ZeroMemory(ret, allocsize); - wnd = (WLEXWND *)(ret + 1); - - if (base) { - // 親と接続されてる? - ret->base = base; - winloc_GetWindowRect(base, &ret->rect); - for (i=0; irect, &rect); - if (connect) { - list[i] = NULL; - wnd->hwnd = hwnd; - CopyMemory(&wnd->rect, &rect, sizeof(RECT)); - wnd->connect = connect; -// wnd->parent = 0; - wnd++; - ret->count++; - } - } - } - // 子と接続されてる? - p = (WLEXWND *)(ret + 1); - for (i=0; icount; i++, p++) { - for (j=0; jrect, &rect); - if (connect) { - list[j] = NULL; - wnd->hwnd = hwnd; - CopyMemory(&wnd->rect, &rect, sizeof(RECT)); - wnd->connect = connect; - wnd->parent = i + 1; - wnd++; - ret->count++; - } - } - } - } - } - - for (i=0; ihwnd = hwnd; - winloc_GetWindowRect(hwnd, &wnd->rect); - wnd++; - ret->count++; - } - } - -wlecre_err2: - if (list) { - _MFREE(list); - } - -wlecre_err1: - return(ret); -} - -void winlocex_destroy(WINLOCEX wle) { - - if (wle) { - _MFREE(wle); - } -} - -void winlocex_setholdwnd(WINLOCEX wle, HWND hold) { - - RECT workrc; - RECT rect; - UINT flag; - - if ((wle == NULL) || (hold == NULL)) { - return; - } - SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); - // マルチモニタ暫定対応 ver0.86 rev30 - workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); - workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); - - winloc_GetWindowRect(hold, &rect); - flag = 0; - if (workrc.left == rect.left) { - flag = 1; - } - else if (workrc.right == rect.right) { - flag = 2; - } - if (workrc.top == rect.top) { - flag += 1 << 4; - } - else if (workrc.bottom == rect.bottom) { - flag += 2 << 4; - } - wle->hold = hold; - wle->holdflag = flag; -} - -static BOOL gravityx(WINLOCEX wle, RECT *rect) { - - int d; - WLEXWND *wnd; - UINT i; - RECT workrc; - - d = SNAPDOTPULL; - wnd = (WLEXWND *)(wle + 1); - for (i=0; icount; i++, wnd++) { - winloc_GetWindowRect(wnd->hwnd, &wnd->rect); - if (!wnd->connect) { - if ((rect->bottom >= wnd->rect.top) && - (rect->top <= wnd->rect.bottom)) { - d = rect->left - wnd->rect.right; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - d = rect->right - wnd->rect.left; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - } - if ((rect->bottom == wnd->rect.top) || - (rect->top == wnd->rect.bottom)) { - d = rect->left - wnd->rect.left; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - d = rect->right - wnd->rect.right; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - } - } - } - if (i < wle->count) { - wle->flagx = i + 1; - rect->left -= d; - rect->right -= d; - wle->gx = d; - wle->tx = rect->left; - return(TRUE); - } - - SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); - // マルチモニタ暫定対応 ver0.86 rev30 - workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); - workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); - - wnd = (WLEXWND *)(wle + 1); - for (i=0; icount; i++, wnd++) { - if (wnd->connect) { - d = wnd->rect.left + (rect->left - wle->rect.left) - - workrc.left; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - d = wnd->rect.right + (rect->right - wle->rect.right) - - workrc.right; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - } - } - if (i < wle->count) { - wle->flagx = (i + 1) << 16; - rect->left -= d; - rect->right -= d; - wle->gx = d; - wle->tx = rect->left; - return(TRUE); - } - - d = rect->left - workrc.left; - if ((d >= SNAPDOTPULL) || (d <= -SNAPDOTPULL)) { - d = rect->right - workrc.right; - } - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - wle->flagx = (UINT)-1; - rect->left -= d; - rect->right -= d; - wle->gx = d; - wle->tx = rect->left; - return(TRUE); - } - return(FALSE); -} - -static BOOL gravityy(WINLOCEX wle, RECT *rect) { - - int d; - WLEXWND *wnd; - UINT i; - RECT workrc; - - d = SNAPDOTPULL; - wnd = (WLEXWND *)(wle + 1); - for (i=0; icount; i++, wnd++) { - if (!wnd->connect) { - if ((rect->right >= wnd->rect.left) && - (rect->left <= wnd->rect.right)) { - d = rect->top - wnd->rect.bottom; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - d = rect->bottom - wnd->rect.top; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - } - if ((rect->right == wnd->rect.left) || - (rect->left == wnd->rect.right)) { - d = rect->top - wnd->rect.top; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - d = rect->bottom - wnd->rect.bottom; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - } - } - } - if (i < wle->count) { - wle->flagy = i + 1; - rect->top -= d; - rect->bottom -= d; - wle->gy = d; - wle->ty = rect->top; - return(TRUE); - } - - SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); - // マルチモニタ暫定対応 ver0.86 rev30 - workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); - workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); - - wnd = (WLEXWND *)(wle + 1); - for (i=0; icount; i++, wnd++) { - if (wnd->connect) { - d = wnd->rect.top + (rect->top - wle->rect.top) - - workrc.top; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - d = wnd->rect.bottom + (rect->bottom - wle->rect.bottom) - - workrc.bottom; - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - break; - } - } - } - if (i < wle->count) { - wle->flagy = (i + 1) << 16; - rect->top -= d; - rect->bottom -= d; - wle->gy = d; - wle->ty = rect->top; - return(TRUE); - } - - d = rect->top - workrc.top; - if ((d >= SNAPDOTPULL) || (d <= -SNAPDOTPULL)) { - d = rect->bottom - workrc.bottom; - } - if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { - wle->flagy = (UINT)-1; - rect->top -= d; - rect->bottom -= d; - wle->gy = d; - wle->ty = rect->top; - return(TRUE); - } - return(FALSE); -} - -void winlocex_moving(WINLOCEX wle, RECT *rect) { - - int d; - UINT num; - RECT *rc; - BOOL changes; - RECT rectmp1 = {0}; - RECT rectmp2 = {0}; - - if (wle == NULL) { - return; - } - - if(!noDWM){ - // DWM補正 - GetWindowRect(GetActiveWindow(), &rectmp1); - winloc_GetWindowRect(GetActiveWindow(), &rectmp2); - rect->left += rectmp2.left - rectmp1.left; - rect->top += rectmp2.top - rectmp1.top; - rect->right += rectmp2.right - rectmp1.right; - rect->bottom += rectmp2.bottom - rectmp1.bottom; - } - - // ひっついてた時 - if (wle->flagx) { - d = rect->left - wle->tx; - wle->gx += d; - rect->left -= d; - rect->right -= d; - if ((wle->gx >= SNAPDOTREL) || (wle->gx <= -SNAPDOTREL)) { - wle->flagx = 0; - rect->left += wle->gx; - rect->right += wle->gx; - wle->gx = 0; - } - } - if (wle->flagy) { - d = rect->top - wle->ty; - wle->gy += d; - rect->top -= d; - rect->bottom -= d; - if ((wle->gy >= SNAPDOTREL) || (wle->gy <= -SNAPDOTREL)) { - wle->flagy = 0; - rect->top += wle->gy; - rect->bottom += wle->gy; - wle->gy = 0; - } - } - - // リリース処理 - num = wle->flagx - 1; - if (num < wle->count) { - rc = &(((WLEXWND *)(wle + 1))[num].rect); - if ((rect->left > rc->right) || (rect->right < rc->left) || - (rect->top > rc->bottom) || (rect->bottom < rc->top)) { - rect->left += wle->gx; - rect->right += wle->gx; - wle->flagx = 0; - wle->gx = 0; - } - } - num = wle->flagy - 1; - if (num < wle->count) { - rc = &(((WLEXWND *)(wle + 1))[num].rect); - if ((rect->left > rc->right) || (rect->right < rc->left) || - (rect->top > rc->bottom) || (rect->bottom < rc->top)) { - rect->top += wle->gy; - rect->bottom += wle->gy; - wle->flagy = 0; - wle->gy = 0; - } - } - - // 重力 - do { - changes = FALSE; - if (!wle->flagx) { - changes = gravityx(wle, rect); - } - if (!wle->flagy) { - changes = gravityy(wle, rect); - } - } while(changes); - - if(!noDWM){ - // DWM補正 - rect->left -= rectmp2.left - rectmp1.left; - rect->top -= rectmp2.top - rectmp1.top; - rect->right -= rectmp2.right - rectmp1.right; - rect->bottom -= rectmp2.bottom - rectmp1.bottom; - } -} - -void winlocex_move(WINLOCEX wle) { - - RECT workrc; - WLEXWND *wnd; - UINT i; - RECT rect; - int cx; - int cy; - RECT baserect; - int dx; - int dy; - UINT num; - RECT *rc; - - if ((wle == NULL) || (wle->base == NULL)) { - return; - } - - wnd = (WLEXWND *)(wle + 1); - for (i=0; icount; i++) { - if ((wle->hold == wnd->hwnd) && (wnd->connect)) { - break; - } - } - if ((i >= wle->count) && (wle->holdflag)) { - SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); - // マルチモニタ暫定対応 ver0.86 rev30 - workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); - workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); - - winloc_GetWindowRect(wle->hold, &rect); - cx = rect.right - rect.left; - cy = rect.bottom - rect.top; - switch(wle->holdflag & 0x0f) { - case 1: - rect.left = workrc.left; - break; - - case 2: - rect.left = workrc.right - cx; - break; - } - switch(wle->holdflag >> 4) { - case 1: - rect.top = workrc.top; - break; - - case 2: - rect.top = workrc.bottom - cy; - break; - } - if(!noDWM){ - // DWM補正 - RECT rectmp1; - RECT rectmp2; - GetWindowRect(wle->hold, &rectmp1); - winloc_GetWindowRect(wle->hold, &rectmp2); - rect.left -= rectmp2.left - rectmp1.left; - rect.top -= rectmp2.top - rectmp1.top; - rect.right -= rectmp2.right - rectmp1.right; - rect.bottom -= rectmp2.bottom - rectmp1.bottom; - cx -= (rectmp1.left - rectmp2.left) - (rectmp1.right - rectmp2.right); - cy -= (rectmp1.top - rectmp2.top) - (rectmp1.bottom - rectmp2.bottom); - } - MoveWindow(wle->hold, rect.left, rect.top, cx, cy, TRUE); - } - - winloc_GetWindowRect(wle->base, &baserect); - dx = baserect.left - wle->rect.left; - dy = baserect.top - wle->rect.top; - wnd = (WLEXWND *)(wle + 1); - for (i=0; icount; i++, wnd++) { - if (wnd->connect) { - winloc_GetWindowRect(wnd->hwnd, &rect); - cx = rect.right - rect.left; - cy = rect.bottom - rect.top; - rect.left += dx; - rect.top += dy; - num = wnd->parent - 1; - if (num < wle->count) { - rc = &(((WLEXWND *)(wle + 1))[num].rect); - } - else { - rc = &baserect; - } - switch(wnd->connect & 0x0f) { - case 1: - rect.left = rc->left - cx; - break; - - case 2: - rect.left = rc->right; - break; - - case 3: - rect.left = rc->left; - break; - - case 4: - rect.left = rc->right - cx; - break; - } - switch((wnd->connect >> 4) & 0x0f) { - case 1: - rect.top = rc->top - cy; - break; - - case 2: - rect.top = rc->bottom; - break; - - case 3: - rect.top = rc->top; - break; - - case 4: - rect.top = rc->bottom - cy; - break; - } - if(!noDWM){ - // DWM補正 - RECT rectmp1; - RECT rectmp2; - GetWindowRect(wnd->hwnd, &rectmp1); - winloc_GetWindowRect(wnd->hwnd, &rectmp2); - rect.left -= rectmp2.left - rectmp1.left; - rect.top -= rectmp2.top - rectmp1.top; - rect.right -= rectmp2.right - rectmp1.right; - rect.bottom -= rectmp2.bottom - rectmp1.bottom; - cx -= (rectmp1.left - rectmp2.left) - (rectmp1.right - rectmp2.right); - cy -= (rectmp1.top - rectmp2.top) - (rectmp1.bottom - rectmp2.bottom); - } - MoveWindow(wnd->hwnd, rect.left, rect.top, cx, cy, TRUE); - wnd->rect.left = rect.left; - wnd->rect.top = rect.top; - wnd->rect.right = rect.left + cx; - wnd->rect.bottom = rect.top + cy; - } - } -} - -void winlocex_close(WINLOCEX wle) { - - WLEXWND *wnd; - UINT i; - - if ((wle == NULL) || (wle->base == NULL)) { - return; - } - wnd = (WLEXWND *)(wle + 1); - for (i=0; icount; i++) { - if (wnd->connect) { - CloseWindow(wnd->hwnd); - } - wnd++; - } -} - +#include +#include "winloc.h" + + +enum { + SNAPDOTPULL = 12, + SNAPDOTREL = 16 +}; +typedef HRESULT (WINAPI *pfnDwmIsCompositionEnabled)( + BOOL *pfEnabled +); +typedef HRESULT (WINAPI *pfnDwmGetWindowAttribute)( + HWND hwnd, + DWORD dwAttribute, + PVOID pvAttribute, + DWORD cbAttribute +); +typedef enum _DWMWINDOWATTRIBUTE { + DWMWA_NCRENDERING_ENABLED = 1, + DWMWA_NCRENDERING_POLICY, + DWMWA_TRANSITIONS_FORCEDISABLED, + DWMWA_ALLOW_NCPAINT, + DWMWA_CAPTION_BUTTON_BOUNDS, + DWMWA_NONCLIENT_RTL_LAYOUT, + DWMWA_FORCE_ICONIC_REPRESENTATION, + DWMWA_FLIP3D_POLICY, + DWMWA_EXTENDED_FRAME_BOUNDS, + DWMWA_HAS_ICONIC_BITMAP, + DWMWA_DISALLOW_PEEK, + DWMWA_EXCLUDED_FROM_PEEK, + DWMWA_CLOAK, + DWMWA_CLOAKED, + DWMWA_FREEZE_REPRESENTATION, + DWMWA_LAST +} DWMWINDOWATTRIBUTE; + +static pfnDwmIsCompositionEnabled F_DwmIsCompositionEnabled = NULL; +static pfnDwmGetWindowAttribute F_DwmGetWindowAttribute = NULL; +static HMODULE hDwmModule = NULL; +static int noDWM = 0; + +BOOL winloc_GetWindowRect(HWND hwnd, LPRECT lpRect); + +BOOL winloc_InitDwmFunc() { + RECT r = {0}; + + if(noDWM){ + // DWM環境でない + return FALSE; + }else{ + if(!hDwmModule){ + hDwmModule = LoadLibrary(_T("dwmapi.dll")); + if(!hDwmModule){ + // DWM環境でない + noDWM = 1; + return FALSE; + } + F_DwmIsCompositionEnabled = (pfnDwmIsCompositionEnabled)GetProcAddress(hDwmModule, "DwmIsCompositionEnabled"); + F_DwmGetWindowAttribute = (pfnDwmGetWindowAttribute)GetProcAddress(hDwmModule, "DwmGetWindowAttribute"); + if(!F_DwmIsCompositionEnabled || !F_DwmGetWindowAttribute){ + // 何故かDwmGetWindowAttributeやDwmIsCompositionEnabledが無い? + FreeLibrary(hDwmModule); + hDwmModule = NULL; + F_DwmGetWindowAttribute = NULL; + noDWM = 1; + return FALSE; + } + } + // DWM環境 + return TRUE; + } +} +void winloc_DisposeDwmFunc() { + if(hDwmModule){ + F_DwmIsCompositionEnabled = NULL; + F_DwmGetWindowAttribute = NULL; + FreeLibrary(hDwmModule); + hDwmModule = NULL; + } +} + +BOOL winloc_GetWindowRect(HWND hwnd, LPRECT lpRect) { + if(F_DwmGetWindowAttribute){ + HRESULT hr = 0; + BOOL dwmenable = FALSE; + hr = F_DwmIsCompositionEnabled(&dwmenable); + if(SUCCEEDED(hr) && dwmenable){ + // DWM環境 + hr = F_DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, lpRect, sizeof(RECT)); + if(SUCCEEDED(hr)){ + return 1; + }else{ + return GetWindowRect(hwnd, lpRect); + } + }else{ + // コンポジションOFF + return GetWindowRect(hwnd, lpRect); + } + }else{ + // DWM環境でない + return GetWindowRect(hwnd, lpRect); + } +} + +void winloc_getDWMmargin(HWND hwnd, int *ofsx, int *ofsy) { + RECT rDWM, r; + winloc_GetWindowRect(hwnd, &rDWM); + GetWindowRect(hwnd, &r); + *ofsx = rDWM.left - r.left; + *ofsy = rDWM.top - r.top; +} + +void winloc_setclientsize(HWND hwnd, int width, int height) { + + RECT rectDisktop; + int scx; + int scy; + UINT cnt; + RECT rectWindow; + RECT rectClient; + int x, y, w, h; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &rectDisktop, 0); + scx = GetSystemMetrics(SM_CXSCREEN); + scy = GetSystemMetrics(SM_CYSCREEN); + // マルチモニタ暫定対応 ver0.86 rev30 + rectDisktop.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); + rectDisktop.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); + + cnt = 2; + do { + winloc_GetWindowRect(hwnd, &rectWindow); + GetClientRect(hwnd, &rectClient); + w = width + (rectWindow.right - rectWindow.left) + - (rectClient.right - rectClient.left); + h = height + (rectWindow.bottom - rectWindow.top) + - (rectClient.bottom - rectClient.top); + + x = rectWindow.left; + y = rectWindow.top; + if (scx < w) { + x = (scx - w) / 2; + } + else { + if ((x + w) > rectDisktop.right) { + x = rectDisktop.right - w; + } + if (x < rectDisktop.left) { + x = rectDisktop.left; + } + } + if (scy < h) { + y = (scy - h) / 2; + } + else { + if ((y + h) > rectDisktop.bottom) { + y = rectDisktop.bottom - h; + } + if (y < rectDisktop.top) { + y = rectDisktop.top; + } + } + if(!noDWM){ + // DWM補正 + RECT rectmp1; + RECT rectmp2; + GetWindowRect(hwnd, &rectmp1); + winloc_GetWindowRect(hwnd, &rectmp2); + x -= rectmp2.left - rectmp1.left; + y -= rectmp2.top - rectmp1.top; + w = width + (rectmp1.right - rectmp1.left) + - (rectClient.right - rectClient.left); + h = height + (rectmp1.bottom - rectmp1.top) + - (rectClient.bottom - rectClient.top); + } + MoveWindow(hwnd, x, y, w, h, TRUE); + } while(--cnt); +} + + +// ---- + +void winloc_movingstart(WINLOC *wl) { + + ZeroMemory(wl, sizeof(WINLOC)); +} + +void winloc_movingproc(WINLOC *wl, RECT *rect) { + + RECT workrc; + int winlx; + int winly; + int d; + RECT rectmp1; + RECT rectmp2; + if(!noDWM){ + // DWM補正 + GetWindowRect(GetActiveWindow(), &rectmp1); + winloc_GetWindowRect(GetActiveWindow(), &rectmp2); + rect->left += rectmp2.left - rectmp1.left; + rect->top += rectmp2.top - rectmp1.top; + rect->right += rectmp2.right - rectmp1.right; + rect->bottom += rectmp2.bottom - rectmp1.bottom; + } + + SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); + winlx = rect->right - rect->left; + winly = rect->bottom - rect->top; + // マルチモニタ暫定対応 ver0.86 rev30 + workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); + workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); + + if ((winlx > (workrc.right - workrc.left)) || + (winly > (workrc.bottom - workrc.top))) { + if(!noDWM){ + // DWM補正 + rect->left -= rectmp2.left - rectmp1.left; + rect->top -= rectmp2.top - rectmp1.top; + rect->right -= rectmp2.right - rectmp1.right; + rect->bottom -= rectmp2.bottom - rectmp1.bottom; + } + return; + } + + if (wl->flag & 1) { + wl->gx += rect->left - wl->tx; + rect->left = wl->tx; + if ((wl->gx >= SNAPDOTREL) || (wl->gx <= -SNAPDOTREL)) { + wl->flag &= ~1; + rect->left += wl->gx; + wl->gx = 0; + } + rect->right = rect->left + winlx; + } + if (wl->flag & 2) { + wl->gy += rect->top - wl->ty; + rect->top = wl->ty; + if ((wl->gy >= SNAPDOTREL) || (wl->gy <= -SNAPDOTREL)) { + wl->flag &= ~2; + rect->top += wl->gy; + wl->gy = 0; + } + rect->bottom = rect->top + winly; + } + + if (!(wl->flag & 1)) { + do { + d = rect->left - workrc.left; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + d = rect->right - workrc.right; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + } while(0); + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + rect->left -= d; + rect->right = rect->left + winlx; + wl->flag |= 1; + wl->gx = d; + wl->tx = rect->left; + } + } + if (!(wl->flag & 2)) { + do { + d = rect->top - workrc.top; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + d = rect->bottom - workrc.bottom; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + } while(0); + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + rect->top -= d; + rect->bottom = rect->top + winly; + wl->flag |= 2; + wl->gy = d; + wl->ty = rect->top; + } + } + if(!noDWM){ + // DWM補正 + rect->left -= rectmp2.left - rectmp1.left; + rect->top -= rectmp2.top - rectmp1.top; + rect->right -= rectmp2.right - rectmp1.right; + rect->bottom -= rectmp2.bottom - rectmp1.bottom; + } +} + + +// ---- + +static UINT8 isconnect(const RECT *parent, const RECT *self) { + + UINT8 connect; + + connect = 0; + if ((self->bottom >= parent->top) && (self->top <= parent->bottom)) { + if (self->right == parent->left) { + connect += 1; + } + else if (self->left == parent->right) { + connect += 2; + } + } + if ((!(connect & 0x0f)) && + ((self->bottom == parent->top) || (self->top == parent->bottom))) { + if (self->left == parent->left) { + connect += 3; + } + else if (self->right == parent->right) { + connect += 4; + } + } + + if ((self->right >= parent->left) && (self->left <= parent->right)) { + if (self->bottom == parent->top) { + connect += 1 << 4; + } + else if (self->top == parent->bottom) { + connect += 2 << 4; + } + } + if ((!(connect & 0xf0)) && + ((self->right == parent->left) || (self->left == parent->right))) { + if (self->top == parent->top) { + connect += 3 << 4; + } + else if (self->bottom == parent->bottom) { + connect += 4 << 4; + } + } + return(connect); +} + +WINLOCEX winlocex_create(HWND base, const HWND *child, UINT count) { + + WINLOCEX ret; + HWND *list; + UINT inlist; + UINT i; + UINT j; + HWND hwnd; + UINT allocsize; + WLEXWND *wnd; + RECT rect; + UINT8 connect; + WLEXWND *p; + + if (child == NULL) { + count = 0; + } + ret = NULL; + list = NULL; + inlist = 0; + if (count) { + list = (HWND *)_MALLOC(count * sizeof(HWND *), "wnd list"); + if (list == NULL) { + goto wlecre_err1; + } + for (i=0; i= inlist) { + list[inlist++] = hwnd; + } + } + } + } + allocsize = sizeof(_WINLOCEX) + (sizeof(WLEXWND) * inlist); + ret = (WINLOCEX)_MALLOC(allocsize, "winlocex"); + if (ret == NULL) { + goto wlecre_err2; + } + ZeroMemory(ret, allocsize); + wnd = (WLEXWND *)(ret + 1); + + if (base) { + // 親と接続されてる? + ret->base = base; + winloc_GetWindowRect(base, &ret->rect); + for (i=0; irect, &rect); + if (connect) { + list[i] = NULL; + wnd->hwnd = hwnd; + CopyMemory(&wnd->rect, &rect, sizeof(RECT)); + wnd->connect = connect; +// wnd->parent = 0; + wnd++; + ret->count++; + } + } + } + // 子と接続されてる? + p = (WLEXWND *)(ret + 1); + for (i=0; icount; i++, p++) { + for (j=0; jrect, &rect); + if (connect) { + list[j] = NULL; + wnd->hwnd = hwnd; + CopyMemory(&wnd->rect, &rect, sizeof(RECT)); + wnd->connect = connect; + wnd->parent = i + 1; + wnd++; + ret->count++; + } + } + } + } + } + + for (i=0; ihwnd = hwnd; + winloc_GetWindowRect(hwnd, &wnd->rect); + wnd++; + ret->count++; + } + } + +wlecre_err2: + if (list) { + _MFREE(list); + } + +wlecre_err1: + return(ret); +} + +void winlocex_destroy(WINLOCEX wle) { + + if (wle) { + _MFREE(wle); + } +} + +void winlocex_setholdwnd(WINLOCEX wle, HWND hold) { + + RECT workrc; + RECT rect; + UINT flag; + + if ((wle == NULL) || (hold == NULL)) { + return; + } + SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); + // マルチモニタ暫定対応 ver0.86 rev30 + workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); + workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); + + winloc_GetWindowRect(hold, &rect); + flag = 0; + if (workrc.left == rect.left) { + flag = 1; + } + else if (workrc.right == rect.right) { + flag = 2; + } + if (workrc.top == rect.top) { + flag += 1 << 4; + } + else if (workrc.bottom == rect.bottom) { + flag += 2 << 4; + } + wle->hold = hold; + wle->holdflag = flag; +} + +static BOOL gravityx(WINLOCEX wle, RECT *rect) { + + int d; + WLEXWND *wnd; + UINT i; + RECT workrc; + + d = SNAPDOTPULL; + wnd = (WLEXWND *)(wle + 1); + for (i=0; icount; i++, wnd++) { + winloc_GetWindowRect(wnd->hwnd, &wnd->rect); + if (!wnd->connect) { + if ((rect->bottom >= wnd->rect.top) && + (rect->top <= wnd->rect.bottom)) { + d = rect->left - wnd->rect.right; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + d = rect->right - wnd->rect.left; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + } + if ((rect->bottom == wnd->rect.top) || + (rect->top == wnd->rect.bottom)) { + d = rect->left - wnd->rect.left; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + d = rect->right - wnd->rect.right; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + } + } + } + if (i < wle->count) { + wle->flagx = i + 1; + rect->left -= d; + rect->right -= d; + wle->gx = d; + wle->tx = rect->left; + return(TRUE); + } + + SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); + // マルチモニタ暫定対応 ver0.86 rev30 + workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); + workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); + + wnd = (WLEXWND *)(wle + 1); + for (i=0; icount; i++, wnd++) { + if (wnd->connect) { + d = wnd->rect.left + (rect->left - wle->rect.left) + - workrc.left; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + d = wnd->rect.right + (rect->right - wle->rect.right) + - workrc.right; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + } + } + if (i < wle->count) { + wle->flagx = (i + 1) << 16; + rect->left -= d; + rect->right -= d; + wle->gx = d; + wle->tx = rect->left; + return(TRUE); + } + + d = rect->left - workrc.left; + if ((d >= SNAPDOTPULL) || (d <= -SNAPDOTPULL)) { + d = rect->right - workrc.right; + } + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + wle->flagx = (UINT)-1; + rect->left -= d; + rect->right -= d; + wle->gx = d; + wle->tx = rect->left; + return(TRUE); + } + return(FALSE); +} + +static BOOL gravityy(WINLOCEX wle, RECT *rect) { + + int d; + WLEXWND *wnd; + UINT i; + RECT workrc; + + d = SNAPDOTPULL; + wnd = (WLEXWND *)(wle + 1); + for (i=0; icount; i++, wnd++) { + if (!wnd->connect) { + if ((rect->right >= wnd->rect.left) && + (rect->left <= wnd->rect.right)) { + d = rect->top - wnd->rect.bottom; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + d = rect->bottom - wnd->rect.top; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + } + if ((rect->right == wnd->rect.left) || + (rect->left == wnd->rect.right)) { + d = rect->top - wnd->rect.top; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + d = rect->bottom - wnd->rect.bottom; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + } + } + } + if (i < wle->count) { + wle->flagy = i + 1; + rect->top -= d; + rect->bottom -= d; + wle->gy = d; + wle->ty = rect->top; + return(TRUE); + } + + SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); + // マルチモニタ暫定対応 ver0.86 rev30 + workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); + workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); + + wnd = (WLEXWND *)(wle + 1); + for (i=0; icount; i++, wnd++) { + if (wnd->connect) { + d = wnd->rect.top + (rect->top - wle->rect.top) + - workrc.top; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + d = wnd->rect.bottom + (rect->bottom - wle->rect.bottom) + - workrc.bottom; + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + break; + } + } + } + if (i < wle->count) { + wle->flagy = (i + 1) << 16; + rect->top -= d; + rect->bottom -= d; + wle->gy = d; + wle->ty = rect->top; + return(TRUE); + } + + d = rect->top - workrc.top; + if ((d >= SNAPDOTPULL) || (d <= -SNAPDOTPULL)) { + d = rect->bottom - workrc.bottom; + } + if ((d < SNAPDOTPULL) && (d > -SNAPDOTPULL)) { + wle->flagy = (UINT)-1; + rect->top -= d; + rect->bottom -= d; + wle->gy = d; + wle->ty = rect->top; + return(TRUE); + } + return(FALSE); +} + +void winlocex_moving(WINLOCEX wle, RECT *rect) { + + int d; + UINT num; + RECT *rc; + BOOL changes; + RECT rectmp1 = {0}; + RECT rectmp2 = {0}; + + if (wle == NULL) { + return; + } + + if(!noDWM){ + // DWM補正 + GetWindowRect(GetActiveWindow(), &rectmp1); + winloc_GetWindowRect(GetActiveWindow(), &rectmp2); + rect->left += rectmp2.left - rectmp1.left; + rect->top += rectmp2.top - rectmp1.top; + rect->right += rectmp2.right - rectmp1.right; + rect->bottom += rectmp2.bottom - rectmp1.bottom; + } + + // ひっついてた時 + if (wle->flagx) { + d = rect->left - wle->tx; + wle->gx += d; + rect->left -= d; + rect->right -= d; + if ((wle->gx >= SNAPDOTREL) || (wle->gx <= -SNAPDOTREL)) { + wle->flagx = 0; + rect->left += wle->gx; + rect->right += wle->gx; + wle->gx = 0; + } + } + if (wle->flagy) { + d = rect->top - wle->ty; + wle->gy += d; + rect->top -= d; + rect->bottom -= d; + if ((wle->gy >= SNAPDOTREL) || (wle->gy <= -SNAPDOTREL)) { + wle->flagy = 0; + rect->top += wle->gy; + rect->bottom += wle->gy; + wle->gy = 0; + } + } + + // リリース処理 + num = wle->flagx - 1; + if (num < wle->count) { + rc = &(((WLEXWND *)(wle + 1))[num].rect); + if ((rect->left > rc->right) || (rect->right < rc->left) || + (rect->top > rc->bottom) || (rect->bottom < rc->top)) { + rect->left += wle->gx; + rect->right += wle->gx; + wle->flagx = 0; + wle->gx = 0; + } + } + num = wle->flagy - 1; + if (num < wle->count) { + rc = &(((WLEXWND *)(wle + 1))[num].rect); + if ((rect->left > rc->right) || (rect->right < rc->left) || + (rect->top > rc->bottom) || (rect->bottom < rc->top)) { + rect->top += wle->gy; + rect->bottom += wle->gy; + wle->flagy = 0; + wle->gy = 0; + } + } + + // 重力 + do { + changes = FALSE; + if (!wle->flagx) { + changes = gravityx(wle, rect); + } + if (!wle->flagy) { + changes = gravityy(wle, rect); + } + } while(changes); + + if(!noDWM){ + // DWM補正 + rect->left -= rectmp2.left - rectmp1.left; + rect->top -= rectmp2.top - rectmp1.top; + rect->right -= rectmp2.right - rectmp1.right; + rect->bottom -= rectmp2.bottom - rectmp1.bottom; + } +} + +void winlocex_move(WINLOCEX wle) { + + RECT workrc; + WLEXWND *wnd; + UINT i; + RECT rect; + int cx; + int cy; + RECT baserect; + int dx; + int dy; + UINT num; + RECT *rc; + + if ((wle == NULL) || (wle->base == NULL)) { + return; + } + + wnd = (WLEXWND *)(wle + 1); + for (i=0; icount; i++) { + if ((wle->hold == wnd->hwnd) && (wnd->connect)) { + break; + } + } + if ((i >= wle->count) && (wle->holdflag)) { + SystemParametersInfo(SPI_GETWORKAREA, 0, &workrc, 0); + // マルチモニタ暫定対応 ver0.86 rev30 + workrc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); + workrc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); + + winloc_GetWindowRect(wle->hold, &rect); + cx = rect.right - rect.left; + cy = rect.bottom - rect.top; + switch(wle->holdflag & 0x0f) { + case 1: + rect.left = workrc.left; + break; + + case 2: + rect.left = workrc.right - cx; + break; + } + switch(wle->holdflag >> 4) { + case 1: + rect.top = workrc.top; + break; + + case 2: + rect.top = workrc.bottom - cy; + break; + } + if(!noDWM){ + // DWM補正 + RECT rectmp1; + RECT rectmp2; + GetWindowRect(wle->hold, &rectmp1); + winloc_GetWindowRect(wle->hold, &rectmp2); + rect.left -= rectmp2.left - rectmp1.left; + rect.top -= rectmp2.top - rectmp1.top; + rect.right -= rectmp2.right - rectmp1.right; + rect.bottom -= rectmp2.bottom - rectmp1.bottom; + cx -= (rectmp1.left - rectmp2.left) - (rectmp1.right - rectmp2.right); + cy -= (rectmp1.top - rectmp2.top) - (rectmp1.bottom - rectmp2.bottom); + } + MoveWindow(wle->hold, rect.left, rect.top, cx, cy, TRUE); + } + + winloc_GetWindowRect(wle->base, &baserect); + dx = baserect.left - wle->rect.left; + dy = baserect.top - wle->rect.top; + wnd = (WLEXWND *)(wle + 1); + for (i=0; icount; i++, wnd++) { + if (wnd->connect) { + winloc_GetWindowRect(wnd->hwnd, &rect); + cx = rect.right - rect.left; + cy = rect.bottom - rect.top; + rect.left += dx; + rect.top += dy; + num = wnd->parent - 1; + if (num < wle->count) { + rc = &(((WLEXWND *)(wle + 1))[num].rect); + } + else { + rc = &baserect; + } + switch(wnd->connect & 0x0f) { + case 1: + rect.left = rc->left - cx; + break; + + case 2: + rect.left = rc->right; + break; + + case 3: + rect.left = rc->left; + break; + + case 4: + rect.left = rc->right - cx; + break; + } + switch((wnd->connect >> 4) & 0x0f) { + case 1: + rect.top = rc->top - cy; + break; + + case 2: + rect.top = rc->bottom; + break; + + case 3: + rect.top = rc->top; + break; + + case 4: + rect.top = rc->bottom - cy; + break; + } + if(!noDWM){ + // DWM補正 + RECT rectmp1; + RECT rectmp2; + GetWindowRect(wnd->hwnd, &rectmp1); + winloc_GetWindowRect(wnd->hwnd, &rectmp2); + rect.left -= rectmp2.left - rectmp1.left; + rect.top -= rectmp2.top - rectmp1.top; + rect.right -= rectmp2.right - rectmp1.right; + rect.bottom -= rectmp2.bottom - rectmp1.bottom; + cx -= (rectmp1.left - rectmp2.left) - (rectmp1.right - rectmp2.right); + cy -= (rectmp1.top - rectmp2.top) - (rectmp1.bottom - rectmp2.bottom); + } + MoveWindow(wnd->hwnd, rect.left, rect.top, cx, cy, TRUE); + wnd->rect.left = rect.left; + wnd->rect.top = rect.top; + wnd->rect.right = rect.left + cx; + wnd->rect.bottom = rect.top + cy; + } + } +} + +void winlocex_close(WINLOCEX wle) { + + WLEXWND *wnd; + UINT i; + + if ((wle == NULL) || (wle->base == NULL)) { + return; + } + wnd = (WLEXWND *)(wle + 1); + for (i=0; icount; i++) { + if (wnd->connect) { + CloseWindow(wnd->hwnd); + } + wnd++; + } +} + diff --git a/windows/winloc.h b/windows/winloc.h old mode 100755 new mode 100644 index ff7eaac2..a87b4620 --- a/windows/winloc.h +++ b/windows/winloc.h @@ -1,56 +1,56 @@ - -#pragma once - -void winloc_setclientsize(HWND hwnd, int width, int height); - -void winloc_getDWMmargin(HWND hwnd, int *ofsx, int *ofsy); - - -// ---- - -typedef struct { - UINT flag; - int gx; - int gy; - int tx; - int ty; -} WINLOC; - -void winloc_movingstart(WINLOC *wl); -void winloc_movingproc(WINLOC *wl, RECT *rect); - - -// ---- - -typedef struct { - HWND hwnd; - RECT rect; - UINT8 connect; - UINT8 padding; - UINT16 parent; -} WLEXWND; - -typedef struct { - UINT flagx; - UINT flagy; - int gx; - int gy; - int tx; - int ty; - HWND base; - RECT rect; - HWND hold; - UINT holdflag; - UINT count; -} _WINLOCEX, *WINLOCEX; - -WINLOCEX winlocex_create(HWND base, const HWND *child, UINT count); -void winlocex_destroy(WINLOCEX wle); -void winlocex_setholdwnd(WINLOCEX wle, HWND hold); -void winlocex_moving(WINLOCEX wle, RECT *rect); -void winlocex_move(WINLOCEX wle); -void winlocex_close(WINLOCEX wle); - -BOOL winloc_InitDwmFunc(); -void winloc_DisposeDwmFunc(); - + +#pragma once + +void winloc_setclientsize(HWND hwnd, int width, int height); + +void winloc_getDWMmargin(HWND hwnd, int *ofsx, int *ofsy); + + +// ---- + +typedef struct { + UINT flag; + int gx; + int gy; + int tx; + int ty; +} WINLOC; + +void winloc_movingstart(WINLOC *wl); +void winloc_movingproc(WINLOC *wl, RECT *rect); + + +// ---- + +typedef struct { + HWND hwnd; + RECT rect; + UINT8 connect; + UINT8 padding; + UINT16 parent; +} WLEXWND; + +typedef struct { + UINT flagx; + UINT flagy; + int gx; + int gy; + int tx; + int ty; + HWND base; + RECT rect; + HWND hold; + UINT holdflag; + UINT count; +} _WINLOCEX, *WINLOCEX; + +WINLOCEX winlocex_create(HWND base, const HWND *child, UINT count); +void winlocex_destroy(WINLOCEX wle); +void winlocex_setholdwnd(WINLOCEX wle, HWND hold); +void winlocex_moving(WINLOCEX wle, RECT *rect); +void winlocex_move(WINLOCEX wle); +void winlocex_close(WINLOCEX wle); + +BOOL winloc_InitDwmFunc(); +void winloc_DisposeDwmFunc(); + diff --git a/windows/x64/pccore.inc b/windows/x64/pccore.inc old mode 100755 new mode 100644 index e7dfbdbf..4152fc6f --- a/windows/x64/pccore.inc +++ b/windows/x64/pccore.inc @@ -1,8 +1,8 @@ - - struc np2cfg_t -.uPD72020 resb 1 -.DISPSYNC resb 1 -.RASTER resb 1 -.realpal resb 1 - endstruc - + + struc np2cfg_t +.uPD72020 resb 1 +.DISPSYNC resb 1 +.RASTER resb 1 +.realpal resb 1 + endstruc + diff --git a/windows/x64/vram.inc b/windows/x64/vram.inc old mode 100755 new mode 100644 index 2b21e39f..a5248f0f --- a/windows/x64/vram.inc +++ b/windows/x64/vram.inc @@ -1,25 +1,25 @@ - -SCRN_BUFSIZE equ 0x4b000 - - - struc vramop_t -.operate resd 1 -.tramwait resd 1 -.vramwait resd 1 -.grcgwait resd 1 - endstruc - - struc dsync_t -.text_vbp resd 1 -.textymax resd 1 -.grph_vbp resd 1 -.grphymax resd 1 - -.scrnxpos resd 1 -.scrnxmax resd 1 -.scrnxextend resd 1 -.scrnymax resd 1 -.textvad resd 1 -.grphvad resd 1 - endstruc - + +SCRN_BUFSIZE equ 0x4b000 + + + struc vramop_t +.operate resd 1 +.tramwait resd 1 +.vramwait resd 1 +.grcgwait resd 1 + endstruc + + struc dsync_t +.text_vbp resd 1 +.textymax resd 1 +.grph_vbp resd 1 +.grphymax resd 1 + +.scrnxpos resd 1 +.scrnxmax resd 1 +.scrnxextend resd 1 +.scrnymax resd 1 +.textvad resd 1 +.grphvad resd 1 + endstruc + diff --git a/windows/x64/vs2019/x64.xml b/windows/x64/vs2019/x64.xml old mode 100755 new mode 100644 index 26be1308..971b7385 --- a/windows/x64/vs2019/x64.xml +++ b/windows/x64/vs2019/x64.xml @@ -1,157 +1,157 @@ - - - - - - - - - - General - - - - - Command Line - - - - - - - - - - - - - - - - Execute Before - - - Specifies the targets for the build customization to run before. - - - - - - - - - - - Execute After - - - Specifies the targets for the build customization to run after. - - - - - - - - - - - - - - Additional Options - - - Additional Options - - - - - - + + + + + + + + + + General + + + + + Command Line + + + + + + + + + + + + + + + + Execute Before + + + Specifies the targets for the build customization to run before. + + + + + + + + + + + Execute After + + + Specifies the targets for the build customization to run after. + + + + + + + + + + + + + + Additional Options + + + Additional Options + + + + + + \ No newline at end of file diff --git a/windows/x86/cputype.h b/windows/x86/cputype.h old mode 100755 new mode 100644 index 164423f3..10d1fed8 --- a/windows/x86/cputype.h +++ b/windows/x86/cputype.h @@ -1,11 +1,11 @@ - -#ifdef __cplusplus -extern "C" { -#endif - -int havemmx(void); - -#ifdef __cplusplus -} -#endif - + +#ifdef __cplusplus +extern "C" { +#endif + +int havemmx(void); + +#ifdef __cplusplus +} +#endif + diff --git a/windows/x86/cputype.x86 b/windows/x86/cputype.x86 old mode 100755 new mode 100644 index 6b027609..6900909c --- a/windows/x86/cputype.x86 +++ b/windows/x86/cputype.x86 @@ -1,25 +1,25 @@ - -section .text - - global _havemmx - - align 16 -_havemmx: pushfd - pop eax - mov edx, eax - xor eax, 00200000h - push eax - popfd - pushfd - pop eax - sub eax, edx - je short nocpuid - xor eax, eax - inc eax - push ebx - cpuid - pop ebx - mov eax, edx - and eax, 00800000h -nocpuid: ret - + +section .text + + global _havemmx + + align 16 +_havemmx: pushfd + pop eax + mov edx, eax + xor eax, 00200000h + push eax + popfd + pushfd + pop eax + sub eax, edx + je short nocpuid + xor eax, eax + inc eax + push ebx + cpuid + pop ebx + mov eax, edx + and eax, 00800000h +nocpuid: ret + diff --git a/windows/x86/makegrph.x86 b/windows/x86/makegrph.x86 old mode 100755 new mode 100644 index 521c1cdc..ae43bf64 --- a/windows/x86/makegrph.x86 +++ b/windows/x86/makegrph.x86 @@ -1,255 +1,255 @@ - -%include 'pccore.inc' -%include 'cpucore.inc' -%include 'iocore.inc' -%include 'vram.inc' - -section .bss - - extern _np2cfg - extern _mem - extern _np2_vram - extern _renewal_line - extern _dsync - extern _vramupdate - global _grph_table - -_grph_table resd 4*256*2 - - -%define GDC_S_SYNC _gdc + gdc_t.s + gdcd_t.para -%define GDC_S_ZOOM (GDC_S_SYNC+8) -%define GDC_S_CSRFORM (GDC_S_ZOOM+1) -%define GDC_S_SCROLL (GDC_S_CSRFORM+3) -%define GDC_S_TEXTW (GDC_S_SCROLL+8) -%define GDC_S_PITCH (GDC_S_TEXTW+8) -%define GDC_S_LPEN (GDC_S_PITCH+1) -%define GDC_S_VECTW (GDC_S_LPEN+3) -%define GDC_S_CSRW (GDC_S_VECTW+11) -%define GDC_S_MASK (GDC_S_CSRW+3) -%define GDC_S_CSRR (GDC_S_MASK+2) -%define GDC_S_WRITE (GDC_S_CSRR+5) - - - -section .text - - align 16 - global _makegrph_initialize - -_makegrph_initialize: - pushad - xor edx, edx - mov ebp, 4 - -maketbl_0: mov ecx, ebp - mov ebx, 1 -maketbl_1: shl eax, 8 - test edx, ebx - setnz al - add ebx, ebx - loop maketbl_1 - - mov ecx, ebp - lea esi, [_grph_table + edx*8 + 4] -maketbl_2: mov [esi], eax - add eax, eax - add esi, 512*4 - loop maketbl_2 - - mov ecx, ebp -maketbl_3: shl eax, 8 - test edx, ebx - setnz al - add ebx, ebx - loop maketbl_3 - - mov ecx, ebp - sub esi, 512*4*4+4 -maketbl_4: mov [esi], eax - add eax, eax - add esi, 512*4 - loop maketbl_4 - - inc edx - cmp edx, 256 - jb short maketbl_0 - popad - ret - - - - - -; GRP_LR = eax [esp+28] -; LINE_WIDTH = esp [esp+12] -; DISPPAGE = dh [esp+21] -; ALL_DRAWFLAG = dl [esp+20] - - align 16 - global @makegrph@8 - -@makegrph@8: pushad - mov edi, _np2_vram - add edi, [_dsync + dsync_t.grphvad] - and ecx, 1 - je short .adjustpage - add edi, SCRN_BUFSIZE -.adjustpage: inc cl - mov byte [esp+21], cl ; DISPPAGE - mov ch, cl - movzx eax, cx - shl eax, 16 - mov ax, cx - - cmp dl, 0 - je short calc_maxline - mov ecx, 2000h - mov ebx, _vramupdate -dirtyfill_lp: or [ebx], eax - add ebx, byte 4 - loop dirtyfill_lp - -calc_maxline: push eax - movzx eax, byte [GDC_S_CSRFORM] - and eax, byte 01fh - mov [esp+28+4], eax ; GRP_LR - - mov ebx, [_dsync + dsync_t.grph_vbp] -draw_lp: movzx esi, word [GDC_S_SCROLL+ 0+0] - movzx ecx, word [GDC_S_SCROLL+ 0+2] - call grphputlines - movzx esi, word [GDC_S_SCROLL+ 4+0] - movzx ecx, word [GDC_S_SCROLL+ 4+2] - call grphputlines - cmp byte [_np2cfg + np2cfg_t.uPD72020], 0 - jne short draw_lp - movzx esi, word [GDC_S_SCROLL+ 8+0] - movzx ecx, word [GDC_S_SCROLL+ 8+2] - call grphputlines - movzx esi, word [GDC_S_SCROLL+12+0] - movzx ecx, word [GDC_S_SCROLL+12+2] - push dword draw_lp - -grphputlines: movzx eax, byte [GDC_S_PITCH] - test ecx, 4000h - jne short .storewidth - add eax, eax -.storewidth: and eax, 0000feh ; uPD72020で確認… - mov [esp+12+8], eax ; LINE_WIDTH - - and esi, 3fffh - add esi, esi - shr ecx, 4 - and ecx, 03ffh - jne short grphlineput_st - mov ecx, 0400h -grphlineput_st: push ecx - -grphlineput_lp: mov ecx, [esp+28+12] ; GRP_LR -grphline1_lp: test bl, 1 - je short grph_putline - test byte [_gdc + gdc_t.mode1], 10h - je short grph_putline - add edi, 640 - cmp byte [esp+20+12], 0 ; ALL_DRAWFLAG - je near putline_end - mov al, [esp+21+12] ; DISPPAGE - or [_renewal_line + ebx], al - jmp near putline_end - -grph_putline: push esi - push ecx - mov ebp, 80 - cmp byte [esp+21+20], 1 ; DISPPAGE - jne near bank1_linelp -bank0_linelp: test byte [_vramupdate + esi], 1 - je short bank0_nodirty - or byte [_renewal_line + ebx], 1 - movzx edx, byte [_mem + esi + VRAM0_B] - mov eax, [_grph_table + edx*8+0*0x800+0] - mov ecx, [_grph_table + edx*8+0*0x800+4] - movzx edx, byte [_mem + esi + VRAM0_R] - or eax, [_grph_table + edx*8+1*0x800+0] - or ecx, [_grph_table + edx*8+1*0x800+4] - movzx edx, byte [_mem + esi + VRAM0_G] - or eax, [_grph_table + edx*8+2*0x800+0] - or ecx, [_grph_table + edx*8+2*0x800+4] - movzx edx, byte [_mem + esi + VRAM0_E] - or eax, [_grph_table + edx*8+3*0x800+0] - or ecx, [_grph_table + edx*8+3*0x800+4] - mov [edi], eax - mov [edi+4], ecx -bank0_nodirty: inc esi - and esi, 07fffh - add edi, byte 8 - dec ebp - jne short bank0_linelp - jmp short bankputend - - align 4 -bank1_linelp: test byte [_vramupdate + esi], 2 - je short bank1_nodirty - or byte [_renewal_line + ebx], 2 - movzx edx, byte [_mem + esi + VRAM1_B] - mov eax, [_grph_table + edx*8+0*0x800+0] - mov ecx, [_grph_table + edx*8+0*0x800+4] - movzx edx, byte [_mem + esi + VRAM1_R] - or eax, [_grph_table + edx*8+1*0x800+0] - or ecx, [_grph_table + edx*8+1*0x800+4] - movzx edx, byte [_mem + esi + VRAM1_G] - or eax, [_grph_table + edx*8+2*0x800+0] - or ecx, [_grph_table + edx*8+2*0x800+4] - movzx edx, byte [_mem + esi + VRAM1_E] - or eax, [_grph_table + edx*8+3*0x800+0] - or ecx, [_grph_table + edx*8+3*0x800+4] - mov [edi], eax - mov [edi+4], ecx -bank1_nodirty: inc esi - and esi, 07fffh - add edi, byte 8 - dec ebp - jne short bank1_linelp -bankputend: pop ecx - pop esi - -putline_end: inc ebx - cmp ebx, [_dsync + dsync_t.grphymax] - jnc short grph_break - dec dword [esp] - je short grphline1_ed - dec ecx - jns near grphline1_lp - add esi, [esp+12+12] ; LINE_WIDTH - and esi, 7fffh - jmp near grphlineput_lp - align 4 -grphline1_ed: pop ecx - ret - -grph_break: add esp, byte 8 - pop edx - cmp byte [esp+20], 0 ; ALL_DRAWFLAG - je short deldirty - - cmp ebx, [_dsync + dsync_t.scrnymax] - jae short deldirty - xor eax, eax -bottomfill0_lp: or [_renewal_line + ebx], dl - mov ecx, 640/4 -bottomfill1_lp: mov [edi], eax - add edi, byte 4 - loop bottomfill1_lp - inc ebx - cmp ebx, [_dsync + dsync_t.scrnymax] - jb bottomfill0_lp - -deldirty: mov ecx, 2000h - mov ebx, dword _vramupdate - not edx -deldirty_lp: and [ebx], edx - add ebx, byte 4 - loop deldirty_lp - popad - ret - + +%include 'pccore.inc' +%include 'cpucore.inc' +%include 'iocore.inc' +%include 'vram.inc' + +section .bss + + extern _np2cfg + extern _mem + extern _np2_vram + extern _renewal_line + extern _dsync + extern _vramupdate + global _grph_table + +_grph_table resd 4*256*2 + + +%define GDC_S_SYNC _gdc + gdc_t.s + gdcd_t.para +%define GDC_S_ZOOM (GDC_S_SYNC+8) +%define GDC_S_CSRFORM (GDC_S_ZOOM+1) +%define GDC_S_SCROLL (GDC_S_CSRFORM+3) +%define GDC_S_TEXTW (GDC_S_SCROLL+8) +%define GDC_S_PITCH (GDC_S_TEXTW+8) +%define GDC_S_LPEN (GDC_S_PITCH+1) +%define GDC_S_VECTW (GDC_S_LPEN+3) +%define GDC_S_CSRW (GDC_S_VECTW+11) +%define GDC_S_MASK (GDC_S_CSRW+3) +%define GDC_S_CSRR (GDC_S_MASK+2) +%define GDC_S_WRITE (GDC_S_CSRR+5) + + + +section .text + + align 16 + global _makegrph_initialize + +_makegrph_initialize: + pushad + xor edx, edx + mov ebp, 4 + +maketbl_0: mov ecx, ebp + mov ebx, 1 +maketbl_1: shl eax, 8 + test edx, ebx + setnz al + add ebx, ebx + loop maketbl_1 + + mov ecx, ebp + lea esi, [_grph_table + edx*8 + 4] +maketbl_2: mov [esi], eax + add eax, eax + add esi, 512*4 + loop maketbl_2 + + mov ecx, ebp +maketbl_3: shl eax, 8 + test edx, ebx + setnz al + add ebx, ebx + loop maketbl_3 + + mov ecx, ebp + sub esi, 512*4*4+4 +maketbl_4: mov [esi], eax + add eax, eax + add esi, 512*4 + loop maketbl_4 + + inc edx + cmp edx, 256 + jb short maketbl_0 + popad + ret + + + + + +; GRP_LR = eax [esp+28] +; LINE_WIDTH = esp [esp+12] +; DISPPAGE = dh [esp+21] +; ALL_DRAWFLAG = dl [esp+20] + + align 16 + global @makegrph@8 + +@makegrph@8: pushad + mov edi, _np2_vram + add edi, [_dsync + dsync_t.grphvad] + and ecx, 1 + je short .adjustpage + add edi, SCRN_BUFSIZE +.adjustpage: inc cl + mov byte [esp+21], cl ; DISPPAGE + mov ch, cl + movzx eax, cx + shl eax, 16 + mov ax, cx + + cmp dl, 0 + je short calc_maxline + mov ecx, 2000h + mov ebx, _vramupdate +dirtyfill_lp: or [ebx], eax + add ebx, byte 4 + loop dirtyfill_lp + +calc_maxline: push eax + movzx eax, byte [GDC_S_CSRFORM] + and eax, byte 01fh + mov [esp+28+4], eax ; GRP_LR + + mov ebx, [_dsync + dsync_t.grph_vbp] +draw_lp: movzx esi, word [GDC_S_SCROLL+ 0+0] + movzx ecx, word [GDC_S_SCROLL+ 0+2] + call grphputlines + movzx esi, word [GDC_S_SCROLL+ 4+0] + movzx ecx, word [GDC_S_SCROLL+ 4+2] + call grphputlines + cmp byte [_np2cfg + np2cfg_t.uPD72020], 0 + jne short draw_lp + movzx esi, word [GDC_S_SCROLL+ 8+0] + movzx ecx, word [GDC_S_SCROLL+ 8+2] + call grphputlines + movzx esi, word [GDC_S_SCROLL+12+0] + movzx ecx, word [GDC_S_SCROLL+12+2] + push dword draw_lp + +grphputlines: movzx eax, byte [GDC_S_PITCH] + test ecx, 4000h + jne short .storewidth + add eax, eax +.storewidth: and eax, 0000feh ; uPD72020で確認… + mov [esp+12+8], eax ; LINE_WIDTH + + and esi, 3fffh + add esi, esi + shr ecx, 4 + and ecx, 03ffh + jne short grphlineput_st + mov ecx, 0400h +grphlineput_st: push ecx + +grphlineput_lp: mov ecx, [esp+28+12] ; GRP_LR +grphline1_lp: test bl, 1 + je short grph_putline + test byte [_gdc + gdc_t.mode1], 10h + je short grph_putline + add edi, 640 + cmp byte [esp+20+12], 0 ; ALL_DRAWFLAG + je near putline_end + mov al, [esp+21+12] ; DISPPAGE + or [_renewal_line + ebx], al + jmp near putline_end + +grph_putline: push esi + push ecx + mov ebp, 80 + cmp byte [esp+21+20], 1 ; DISPPAGE + jne near bank1_linelp +bank0_linelp: test byte [_vramupdate + esi], 1 + je short bank0_nodirty + or byte [_renewal_line + ebx], 1 + movzx edx, byte [_mem + esi + VRAM0_B] + mov eax, [_grph_table + edx*8+0*0x800+0] + mov ecx, [_grph_table + edx*8+0*0x800+4] + movzx edx, byte [_mem + esi + VRAM0_R] + or eax, [_grph_table + edx*8+1*0x800+0] + or ecx, [_grph_table + edx*8+1*0x800+4] + movzx edx, byte [_mem + esi + VRAM0_G] + or eax, [_grph_table + edx*8+2*0x800+0] + or ecx, [_grph_table + edx*8+2*0x800+4] + movzx edx, byte [_mem + esi + VRAM0_E] + or eax, [_grph_table + edx*8+3*0x800+0] + or ecx, [_grph_table + edx*8+3*0x800+4] + mov [edi], eax + mov [edi+4], ecx +bank0_nodirty: inc esi + and esi, 07fffh + add edi, byte 8 + dec ebp + jne short bank0_linelp + jmp short bankputend + + align 4 +bank1_linelp: test byte [_vramupdate + esi], 2 + je short bank1_nodirty + or byte [_renewal_line + ebx], 2 + movzx edx, byte [_mem + esi + VRAM1_B] + mov eax, [_grph_table + edx*8+0*0x800+0] + mov ecx, [_grph_table + edx*8+0*0x800+4] + movzx edx, byte [_mem + esi + VRAM1_R] + or eax, [_grph_table + edx*8+1*0x800+0] + or ecx, [_grph_table + edx*8+1*0x800+4] + movzx edx, byte [_mem + esi + VRAM1_G] + or eax, [_grph_table + edx*8+2*0x800+0] + or ecx, [_grph_table + edx*8+2*0x800+4] + movzx edx, byte [_mem + esi + VRAM1_E] + or eax, [_grph_table + edx*8+3*0x800+0] + or ecx, [_grph_table + edx*8+3*0x800+4] + mov [edi], eax + mov [edi+4], ecx +bank1_nodirty: inc esi + and esi, 07fffh + add edi, byte 8 + dec ebp + jne short bank1_linelp +bankputend: pop ecx + pop esi + +putline_end: inc ebx + cmp ebx, [_dsync + dsync_t.grphymax] + jnc short grph_break + dec dword [esp] + je short grphline1_ed + dec ecx + jns near grphline1_lp + add esi, [esp+12+12] ; LINE_WIDTH + and esi, 7fffh + jmp near grphlineput_lp + align 4 +grphline1_ed: pop ecx + ret + +grph_break: add esp, byte 8 + pop edx + cmp byte [esp+20], 0 ; ALL_DRAWFLAG + je short deldirty + + cmp ebx, [_dsync + dsync_t.scrnymax] + jae short deldirty + xor eax, eax +bottomfill0_lp: or [_renewal_line + ebx], dl + mov ecx, 640/4 +bottomfill1_lp: mov [edi], eax + add edi, byte 4 + loop bottomfill1_lp + inc ebx + cmp ebx, [_dsync + dsync_t.scrnymax] + jb bottomfill0_lp + +deldirty: mov ecx, 2000h + mov ebx, dword _vramupdate + not edx +deldirty_lp: and [ebx], edx + add ebx, byte 4 + loop deldirty_lp + popad + ret + diff --git a/windows/x86/np2asm.inc b/windows/x86/np2asm.inc old mode 100755 new mode 100644 index 26c337a3..1e1d03f3 --- a/windows/x86/np2asm.inc +++ b/windows/x86/np2asm.inc @@ -1,13 +1,13 @@ - -%define USE_EGCASM 1 - -%define EARG1 4 -%define EARG2 (EARG1+4) -%define EARG3 (EARG2+4) -%define EARG4 (EARG3+4) - -%define FC_ARG3 4 -%define FC_ARG4 (FC_ARG3+4) -%define FC_ARG5 (FC_ARG4+4) -%define FC_ARG6 (FC_ARG5+4) - + +%define USE_EGCASM 1 + +%define EARG1 4 +%define EARG2 (EARG1+4) +%define EARG3 (EARG2+4) +%define EARG4 (EARG3+4) + +%define FC_ARG3 4 +%define FC_ARG4 (FC_ARG3+4) +%define FC_ARG5 (FC_ARG4+4) +%define FC_ARG6 (FC_ARG5+4) + diff --git a/windows/x86/opngeng.x86 b/windows/x86/opngeng.x86 old mode 100755 new mode 100644 index a11a143f..c3b15df0 --- a/windows/x86/opngeng.x86 +++ b/windows/x86/opngeng.x86 @@ -1,502 +1,502 @@ - -%define OPNGENX86 - -%define FMDIV_BITS 10 -%define FMDIV_ENT (1 << FMDIV_BITS) -%define FMVOL_SFTBIT 4 - -%ifdef OPNGENX86 -%define SIN_BITS 11 -%define EVC_BITS 10 -%define ENV_BITS 16 -%define KF_BITS 6 -%define FREQ_BITS 21 -%define ENVTBL_BIT 14 -%define SINTBL_BIT 14 -%else -%define SIN_BITS 10 -%define EVC_BITS 10 -%define ENV_BITS 16 -%define KF_BITS 6 -%define FREQ_BITS 21 -%define ENVTBL_BIT 14 -%define SINTBL_BIT 15 -%endif - -%define TL_BITS (FREQ_BITS+2) -%define OPM_OUTSB (TL_BITS + 2 - 16) - -%define SIN_ENT (1 << SIN_BITS) -%define EVC_ENT (1 << EVC_BITS) - -%define EC_ATTACK 0 -%define EC_DECAY (EVC_ENT << ENV_BITS) -%define EC_OFF ((2 * EVC_ENT) << ENV_BITS) - -%define EM_ATTACK 4 -%define EM_DECAY1 3 -%define EM_DECAY2 2 -%define EM_RELEASE 1 -%define EM_OFF 0 - - - struc slot_t -.detune1 resd 1 ; 00 -.totallevel resd 1 ; 04 -.decaylevel resd 1 ; 08 -.attack resd 1 ; 0c -.decay1 resd 1 ; 10 -.decay2 resd 1 ; 14 -.release resd 1 ; 18 -.freq_cnt resd 1 ; 1c -.freq_inc resd 1 ; 20 -.multiple resd 1 ; 24 -.keyscale resb 1 ; 28 -.env_mode resb 1 ; 29 -.envraito resb 1 ; 2a -.ssgeg1 resb 1 ; 2b -.env_cnt resd 1 ; 2c -.env_end resd 1 ; 30 -.env_inc resd 1 ; 34 -.env_inc_attack resd 1 ; 38 -.env_inc_decay1 resd 1 ; 3c -.env_inc_decay2 resd 1 ; 40 -.env_inc_rel resd 1 ; 44 - endstruc - - struc ch_t -.slot resb (slot_t_size * 4) -.algorithm resb 1 -.feedback resb 1 -.playing resb 1 -.outslot resb 1 -.op1fb resd 1 -.connect1 resd 1 -.connect3 resd 1 -.connect2 resd 1 -.connect4 resd 1 -.keynote resd 4 - -.keyfunc resb 4 -.kcode resb 4 -.pan resb 1 -.extop resb 1 -.stereo resb 1 -.keyreg resb 1 - endstruc - - struc opngen_t -.playchannels resd 1 -.playing resd 1 -.feedback2 resd 1 -.feedback3 resd 1 -.feedback4 resd 1 -.outdl resd 1 -.outdc resd 1 -.outdr resd 1 -.calcremain resd 1 -.opnch resb 0 - endstruc - - struc opncfg_t -.calc1024 resd 1 -.fmvol resd 1 -.ratebit resd 1 -.vr_en resd 1 -.vr_l resd 1 -.vr_r resd 1 - -.sintable resd SIN_ENT -.envtable resd EVC_ENT -.envcurve resd (EVC_ENT*2 + 1) - endstruc - - -section .text - - extern _opncfg - -%ifdef OPNGENX86 - extern _sinshift - extern _envshift -%endif - -%define ENVCURVE (_opncfg + opncfg_t.envcurve) -%define SINTABLE (_opncfg + opncfg_t.sintable) -%define ENVTABLE (_opncfg + opncfg_t.envtable) - - - global @opngen_getpcm@12 - global @opngen_getpcmvr@12 - -%macro op_out 0 - add eax, [edi + slot_t.freq_cnt] - shr eax, (FREQ_BITS - SIN_BITS) - and eax, (SIN_ENT - 1) -%ifdef OPNGENX86 - mov cl, [_sinshift + eax] -%endif - mov eax, [SINTABLE + eax*4] -%ifdef OPNGENX86 - add cl, [_envshift + edx] -%endif - imul eax, [ENVTABLE + edx*4] -%ifdef OPNGENX86 - sar eax, cl -%else - sar eax, (ENVTBL_BIT + SINTBL_BIT - TL_BITS) -%endif -%endmacro - -%macro calcenv 2 - mov eax, [edi + slot_t.freq_inc] - add [edi + slot_t.freq_cnt], eax - mov eax, [edi + slot_t.env_cnt] - add eax, [edi + slot_t.env_inc] - cmp eax, [edi + slot_t.env_end] - jae near %1 -%2: mov [edi + slot_t.env_cnt], eax - shr eax, ENV_BITS - mov edx, [edi + slot_t.totallevel] - sub edx, [ENVCURVE + eax*4] -%endmacro - -%macro setenv 3 -%1: mov dl, [edi + slot_t.env_mode] - dec dl - je short %%setrr - dec dl - je short %%setd2 - dec dl - je short %%setd1 - dec dl - jne short %%envret - mov byte [edi + slot_t.env_mode], EM_DECAY1 - mov eax, [edi + slot_t.decaylevel] - mov [edi + slot_t.env_end], eax - mov eax, [edi + slot_t.env_inc_decay1] - mov [edi + slot_t.env_inc], eax - mov eax, EC_DECAY -%%envret: jmp near %2 -%%setd1: mov byte [edi + slot_t.env_mode], EM_DECAY2 - mov dword [edi + slot_t.env_end], EC_OFF - mov eax, [edi + slot_t.env_inc_decay2] - mov [edi + slot_t.env_inc], eax - mov eax, [edi + slot_t.decaylevel] - jmp near %2 -%%setrr: mov byte [edi + slot_t.env_mode], EM_OFF -%%setd2: mov dword [edi + slot_t.env_end], EC_OFF + 1 - and dword [edi + slot_t.env_inc], byte 0 - and byte [edi - (slot_t_size * %3) + ch_t.playing], ~(1 << %3) - mov eax, EC_OFF - jmp near %2 -%endmacro - - - align 16 -@opngen_getpcm@12: - cmp dword [esp+4], byte 0 - je near og_noupdate - cmp dword [ecx + opngen_t.playing], byte 0 - je near og_noupdate - - push ebx - push esi - push edi - push ebp - sub esp, byte 8 - -%define OPN_SAMPL 0 -%define OPN_SAMPR 4 -%define OPN_LENG 16 + 8 + 4 - - mov esi, ecx - mov ebp, edx - mov ebx, [esi + opngen_t.calcremain] -og_fmout_st: mov eax, FMDIV_ENT - and dword [esp + OPN_SAMPL], byte 0 - and dword [esp + OPN_SAMPR], byte 0 - sub ebx, eax - jnc near og_nextsamp - lea eax, [eax + ebx] - neg ebx -og_fmout_lp: mov edx, eax - imul eax, [esi + opngen_t.outdl] - imul edx, [esi + opngen_t.outdr] - add [esp + OPN_SAMPL], eax - add [esp + OPN_SAMPR], edx - mov [esi + opngen_t.calcremain], ebx - and dword [esi + opngen_t.playing], byte 0 - and dword [esi + opngen_t.outdl], byte 0 - and dword [esi + opngen_t.outdc], byte 0 - and dword [esi + opngen_t.outdr], byte 0 - mov ch, [esi + opngen_t.playchannels] - lea edi, [esi + opngen_t.opnch] -og_calcch_lp: mov cl, [edi + ch_t.outslot] - test cl, [edi + ch_t.playing] - je near og_calcch_nt - and dword [esi + opngen_t.feedback2], byte 0 - and dword [esi + opngen_t.feedback3], byte 0 - and dword [esi + opngen_t.feedback4], byte 0 - calcenv envcalc1, envret1 ; slot1 calculate - jl near og_calcslot3 - mov cl, [edi + ch_t.feedback] - test cl, cl - je short og_nofeed - mov eax, [edi + ch_t.op1fb] ; with feedback - mov ebx, eax - shr eax, cl - op_out - mov [edi + ch_t.op1fb], eax - add eax, ebx - sar eax, 1 - jmp short og_algchk -og_nofeed: xor eax, eax ; without feedback - op_out -og_algchk: cmp byte [edi + ch_t.algorithm], 5 - jne short og_calcalg5 - mov [esi + opngen_t.feedback2], eax ; case ALG == 5 - mov [esi + opngen_t.feedback3], eax - mov [esi + opngen_t.feedback4], eax - jmp short og_calcslot3 -og_calcalg5: mov ebx, [edi + ch_t.connect1] ; case ALG != 5 - add [ebx], eax -og_calcslot3: add edi, byte slot_t_size ; slot3 calculate - calcenv envcalc2, envret2 - jl short og_calcslot2 - mov eax, [esi + opngen_t.feedback2] - op_out - mov ebx, [edi - (slot_t_size * 1) + ch_t.connect2] - add [ebx], eax -og_calcslot2: add edi, byte slot_t_size ; slot2 calculate - calcenv envcalc3, envret3 - jl short og_calcslot4 - mov eax, [esi + opngen_t.feedback3] - op_out - mov ebx, [edi - (slot_t_size * 2) + ch_t.connect3] - add [ebx], eax -og_calcslot4: add edi, byte slot_t_size ; slot4 calculate - calcenv envcalc4, envret4 - jl short og_calcsloted - mov eax, [esi + opngen_t.feedback4] - op_out - mov ebx, [edi - (slot_t_size * 3) + ch_t.connect4] - add [ebx], eax -og_calcsloted: sub edi, (slot_t_size * 3) - inc dword [esi + opngen_t.playing] -og_calcch_nt: add edi, ch_t_size - dec ch - jne near og_calcch_lp - mov eax, [esi + opngen_t.outdc] - add [esi + opngen_t.outdl], eax - add [esi + opngen_t.outdr], eax - sar dword [esi + opngen_t.outdl], FMVOL_SFTBIT - sar dword [esi + opngen_t.outdr], FMVOL_SFTBIT - mov ebx, [esi + opngen_t.calcremain] - mov eax, [_opncfg + opncfg_t.calc1024] - sub ebx, eax - ja near og_fmout_lp - lea eax, [eax + ebx] - neg ebx -og_nextsamp: mov ecx, eax -%ifdef OPNGENX86 - imul eax, [esi + opngen_t.outdl] - imul ecx, [esi + opngen_t.outdr] - add eax, [esp + OPN_SAMPL] - add ecx, [esp + OPN_SAMPR] - imul dword [_opncfg + opncfg_t.fmvol] - mov eax, ecx - add [ebp], edx - imul dword [_opncfg + opncfg_t.fmvol] - mov [esi + opngen_t.calcremain], ebx - add [ebp+4], edx -%else - mov edx, [_opncfg + opncfg_t.fmvol] - mov [esi + opngen_t.calcremain], ebx - imul eax, [esi + opngen_t.outdl] - imul ecx, [esi + opngen_t.outdr] - add eax, [esp + OPN_SAMPL] - add ecx, [esp + OPN_SAMPR] - sar eax, 8 - sar ecx, 8 - imul eax, edx - imul ecx, edx - sar eax, (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8) - sar ecx, (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8) - add [ebp], eax - add [ebp+4], ecx -%endif - add ebp, byte 8 - dec dword [esp + OPN_LENG] - jne near og_fmout_st - add esp, byte 8 - pop ebp - pop edi - pop esi - pop ebx -og_noupdate: ret 4 - - setenv envcalc1, envret1, 0 - setenv envcalc2, envret2, 1 - setenv envcalc3, envret3, 2 - setenv envcalc4, envret4, 3 - - - align 16 -@opngen_getpcmvr@12: - cmp dword [_opncfg + opncfg_t.vr_en], byte 0 - je near @opngen_getpcm@12 - - cmp dword [esp+4], byte 0 - je near ogv_noupdate - - push ebx - push esi - push edi - push ebp - sub esp, byte 8 - -%define OPNV_SAMPL equ 0 -%define OPNV_SAMPR equ 4 -%define OPNV_LENG equ 16 + 8 + 4 - - mov esi, ecx - mov ebp, edx - mov ebx, [esi + opngen_t.calcremain] -ogv_fmout_st: mov eax, FMDIV_ENT - and dword [esp + OPNV_SAMPL], byte 0 - and dword [esp + OPNV_SAMPR], byte 0 - sub ebx, eax - jnc near ogv_nextsamp - lea eax, [eax + ebx] - neg ebx -ogv_fmout_lp: mov edx, eax - imul eax, [esi + opngen_t.outdl] - imul edx, [esi + opngen_t.outdr] - add [esp + OPNV_SAMPL], eax - add [esp + OPNV_SAMPR], edx - xor eax, eax - mov [esi + opngen_t.calcremain], ebx - mov [esi + opngen_t.outdl], eax - mov [esi + opngen_t.outdc], eax - mov [esi + opngen_t.outdr], eax - mov ch, [esi + opngen_t.playchannels] - lea edi, [esi + opngen_t.opnch] -ogv_calcch_lp: xor eax, eax - mov [esi + opngen_t.feedback2], eax - mov [esi + opngen_t.feedback3], eax - mov [esi + opngen_t.feedback4], eax - calcenv vrenvcalc1, vrenvret1 ; slot1 calculate - jl near ogv_calcslot3 - mov cl, [edi + ch_t.feedback] - test cl, cl - je short ogv_nofeed - mov eax, [edi + ch_t.op1fb] ; with feedback - mov ebx, eax - shr eax, cl - op_out - mov [edi + ch_t.op1fb], eax - add eax, ebx - sar eax, 1 - jmp short ogv_algchk -ogv_nofeed: xor eax, eax ; without feedback - op_out -ogv_algchk: cmp byte [edi + ch_t.algorithm], 5 - jne short ogv_calcalg5 - mov [esi + opngen_t.feedback2], eax ; case ALG == 5 - mov [esi + opngen_t.feedback3], eax - mov [esi + opngen_t.feedback4], eax - jmp short ogv_calcslot3 -ogv_calcalg5: mov ebx, [edi + ch_t.connect1] ; case ALG != 5 - add [ebx], eax -ogv_calcslot3: add edi, byte slot_t_size ; slot3 calculate - calcenv vrenvcalc2, vrenvret2 - jl short ogv_calcslot2 - mov eax, [esi + opngen_t.feedback2] - op_out - mov ebx, [edi - (slot_t_size * 1) + ch_t.connect2] - add [ebx], eax -ogv_calcslot2: add edi, byte slot_t_size ; slot2 calculate - calcenv vrenvcalc3, vrenvret3 - jl short ogv_calcslot4 - mov eax, [esi + opngen_t.feedback3] - op_out - mov ebx, [edi - (slot_t_size * 2) + ch_t.connect3] - add [ebx], eax -ogv_calcslot4: add edi, byte slot_t_size ; slot4 calculate - calcenv vrenvcalc4, vrenvret4 - jl short ogv_calcsloted - mov eax, [esi + opngen_t.feedback4] - op_out - mov ebx, [edi - (slot_t_size * 3) + ch_t.connect4] - add [ebx], eax -ogv_calcsloted: add edi, byte (ch_t_size - (slot_t_size * 3)) - dec ch - jne near ogv_calcch_lp - mov eax, [esi + opngen_t.outdl] - mov edx, [esi + opngen_t.outdc] - imul eax, [_opncfg + opncfg_t.vr_l] - mov ebx, edx - sar eax, 5 - add ebx, eax - sar eax, 2 - add edx, eax - mov eax, [esi + opngen_t.outdr] - imul eax, [_opncfg + opncfg_t.vr_r] - sar eax, 5 - add edx, eax - sar eax, 2 - add ebx, eax - add [esi + opngen_t.outdl], edx - add [esi + opngen_t.outdr], ebx - sar dword [esi + opngen_t.outdl], FMVOL_SFTBIT - sar dword [esi + opngen_t.outdr], FMVOL_SFTBIT - mov ebx, [esi + opngen_t.calcremain] - mov eax, [_opncfg + opncfg_t.calc1024] - sub ebx, eax - ja near ogv_fmout_lp - lea eax, [eax + ebx] - neg ebx -ogv_nextsamp: mov ecx, eax -%ifdef OPNGENX86 - imul eax, [esi + opngen_t.outdl] - imul ecx, [esi + opngen_t.outdr] - add eax, [esp + OPNV_SAMPL] - add ecx, [esp + OPNV_SAMPR] - imul dword [_opncfg + opncfg_t.fmvol] - mov eax, ecx - add [ebp], edx - imul dword [_opncfg + opncfg_t.fmvol] - mov [esi + opngen_t.calcremain], ebx - add [ebp+4], edx -%else - mov edx, [_opncfg + opncfg_t.fmvol] - mov [esi + opngen_t.calcremain], ebx - imul eax, [esi + opngen_t.outdl] - imul ecx, [esi + opngen_t.outdr] - add eax, [esp + OPN_SAMPL] - add ecx, [esp + OPN_SAMPR] - sar eax, 8 - sar ecx, 8 - imul eax, edx - imul ecx, edx - sar eax, (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8) - sar ecx, (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8) - add [ebp], eax - add [ebp+4], ecx -%endif - add ebp, byte 8 - dec dword [esp + OPNV_LENG] - jne near ogv_fmout_st - add esp, byte 8 - pop ebp - pop edi - pop esi - pop ebx -ogv_noupdate: ret 4 - - setenv vrenvcalc1, vrenvret1, 0 - setenv vrenvcalc2, vrenvret2, 1 - setenv vrenvcalc3, vrenvret3, 2 - setenv vrenvcalc4, vrenvret4, 3 - + +%define OPNGENX86 + +%define FMDIV_BITS 10 +%define FMDIV_ENT (1 << FMDIV_BITS) +%define FMVOL_SFTBIT 4 + +%ifdef OPNGENX86 +%define SIN_BITS 11 +%define EVC_BITS 10 +%define ENV_BITS 16 +%define KF_BITS 6 +%define FREQ_BITS 21 +%define ENVTBL_BIT 14 +%define SINTBL_BIT 14 +%else +%define SIN_BITS 10 +%define EVC_BITS 10 +%define ENV_BITS 16 +%define KF_BITS 6 +%define FREQ_BITS 21 +%define ENVTBL_BIT 14 +%define SINTBL_BIT 15 +%endif + +%define TL_BITS (FREQ_BITS+2) +%define OPM_OUTSB (TL_BITS + 2 - 16) + +%define SIN_ENT (1 << SIN_BITS) +%define EVC_ENT (1 << EVC_BITS) + +%define EC_ATTACK 0 +%define EC_DECAY (EVC_ENT << ENV_BITS) +%define EC_OFF ((2 * EVC_ENT) << ENV_BITS) + +%define EM_ATTACK 4 +%define EM_DECAY1 3 +%define EM_DECAY2 2 +%define EM_RELEASE 1 +%define EM_OFF 0 + + + struc slot_t +.detune1 resd 1 ; 00 +.totallevel resd 1 ; 04 +.decaylevel resd 1 ; 08 +.attack resd 1 ; 0c +.decay1 resd 1 ; 10 +.decay2 resd 1 ; 14 +.release resd 1 ; 18 +.freq_cnt resd 1 ; 1c +.freq_inc resd 1 ; 20 +.multiple resd 1 ; 24 +.keyscale resb 1 ; 28 +.env_mode resb 1 ; 29 +.envraito resb 1 ; 2a +.ssgeg1 resb 1 ; 2b +.env_cnt resd 1 ; 2c +.env_end resd 1 ; 30 +.env_inc resd 1 ; 34 +.env_inc_attack resd 1 ; 38 +.env_inc_decay1 resd 1 ; 3c +.env_inc_decay2 resd 1 ; 40 +.env_inc_rel resd 1 ; 44 + endstruc + + struc ch_t +.slot resb (slot_t_size * 4) +.algorithm resb 1 +.feedback resb 1 +.playing resb 1 +.outslot resb 1 +.op1fb resd 1 +.connect1 resd 1 +.connect3 resd 1 +.connect2 resd 1 +.connect4 resd 1 +.keynote resd 4 + +.keyfunc resb 4 +.kcode resb 4 +.pan resb 1 +.extop resb 1 +.stereo resb 1 +.keyreg resb 1 + endstruc + + struc opngen_t +.playchannels resd 1 +.playing resd 1 +.feedback2 resd 1 +.feedback3 resd 1 +.feedback4 resd 1 +.outdl resd 1 +.outdc resd 1 +.outdr resd 1 +.calcremain resd 1 +.opnch resb 0 + endstruc + + struc opncfg_t +.calc1024 resd 1 +.fmvol resd 1 +.ratebit resd 1 +.vr_en resd 1 +.vr_l resd 1 +.vr_r resd 1 + +.sintable resd SIN_ENT +.envtable resd EVC_ENT +.envcurve resd (EVC_ENT*2 + 1) + endstruc + + +section .text + + extern _opncfg + +%ifdef OPNGENX86 + extern _sinshift + extern _envshift +%endif + +%define ENVCURVE (_opncfg + opncfg_t.envcurve) +%define SINTABLE (_opncfg + opncfg_t.sintable) +%define ENVTABLE (_opncfg + opncfg_t.envtable) + + + global @opngen_getpcm@12 + global @opngen_getpcmvr@12 + +%macro op_out 0 + add eax, [edi + slot_t.freq_cnt] + shr eax, (FREQ_BITS - SIN_BITS) + and eax, (SIN_ENT - 1) +%ifdef OPNGENX86 + mov cl, [_sinshift + eax] +%endif + mov eax, [SINTABLE + eax*4] +%ifdef OPNGENX86 + add cl, [_envshift + edx] +%endif + imul eax, [ENVTABLE + edx*4] +%ifdef OPNGENX86 + sar eax, cl +%else + sar eax, (ENVTBL_BIT + SINTBL_BIT - TL_BITS) +%endif +%endmacro + +%macro calcenv 2 + mov eax, [edi + slot_t.freq_inc] + add [edi + slot_t.freq_cnt], eax + mov eax, [edi + slot_t.env_cnt] + add eax, [edi + slot_t.env_inc] + cmp eax, [edi + slot_t.env_end] + jae near %1 +%2: mov [edi + slot_t.env_cnt], eax + shr eax, ENV_BITS + mov edx, [edi + slot_t.totallevel] + sub edx, [ENVCURVE + eax*4] +%endmacro + +%macro setenv 3 +%1: mov dl, [edi + slot_t.env_mode] + dec dl + je short %%setrr + dec dl + je short %%setd2 + dec dl + je short %%setd1 + dec dl + jne short %%envret + mov byte [edi + slot_t.env_mode], EM_DECAY1 + mov eax, [edi + slot_t.decaylevel] + mov [edi + slot_t.env_end], eax + mov eax, [edi + slot_t.env_inc_decay1] + mov [edi + slot_t.env_inc], eax + mov eax, EC_DECAY +%%envret: jmp near %2 +%%setd1: mov byte [edi + slot_t.env_mode], EM_DECAY2 + mov dword [edi + slot_t.env_end], EC_OFF + mov eax, [edi + slot_t.env_inc_decay2] + mov [edi + slot_t.env_inc], eax + mov eax, [edi + slot_t.decaylevel] + jmp near %2 +%%setrr: mov byte [edi + slot_t.env_mode], EM_OFF +%%setd2: mov dword [edi + slot_t.env_end], EC_OFF + 1 + and dword [edi + slot_t.env_inc], byte 0 + and byte [edi - (slot_t_size * %3) + ch_t.playing], ~(1 << %3) + mov eax, EC_OFF + jmp near %2 +%endmacro + + + align 16 +@opngen_getpcm@12: + cmp dword [esp+4], byte 0 + je near og_noupdate + cmp dword [ecx + opngen_t.playing], byte 0 + je near og_noupdate + + push ebx + push esi + push edi + push ebp + sub esp, byte 8 + +%define OPN_SAMPL 0 +%define OPN_SAMPR 4 +%define OPN_LENG 16 + 8 + 4 + + mov esi, ecx + mov ebp, edx + mov ebx, [esi + opngen_t.calcremain] +og_fmout_st: mov eax, FMDIV_ENT + and dword [esp + OPN_SAMPL], byte 0 + and dword [esp + OPN_SAMPR], byte 0 + sub ebx, eax + jnc near og_nextsamp + lea eax, [eax + ebx] + neg ebx +og_fmout_lp: mov edx, eax + imul eax, [esi + opngen_t.outdl] + imul edx, [esi + opngen_t.outdr] + add [esp + OPN_SAMPL], eax + add [esp + OPN_SAMPR], edx + mov [esi + opngen_t.calcremain], ebx + and dword [esi + opngen_t.playing], byte 0 + and dword [esi + opngen_t.outdl], byte 0 + and dword [esi + opngen_t.outdc], byte 0 + and dword [esi + opngen_t.outdr], byte 0 + mov ch, [esi + opngen_t.playchannels] + lea edi, [esi + opngen_t.opnch] +og_calcch_lp: mov cl, [edi + ch_t.outslot] + test cl, [edi + ch_t.playing] + je near og_calcch_nt + and dword [esi + opngen_t.feedback2], byte 0 + and dword [esi + opngen_t.feedback3], byte 0 + and dword [esi + opngen_t.feedback4], byte 0 + calcenv envcalc1, envret1 ; slot1 calculate + jl near og_calcslot3 + mov cl, [edi + ch_t.feedback] + test cl, cl + je short og_nofeed + mov eax, [edi + ch_t.op1fb] ; with feedback + mov ebx, eax + shr eax, cl + op_out + mov [edi + ch_t.op1fb], eax + add eax, ebx + sar eax, 1 + jmp short og_algchk +og_nofeed: xor eax, eax ; without feedback + op_out +og_algchk: cmp byte [edi + ch_t.algorithm], 5 + jne short og_calcalg5 + mov [esi + opngen_t.feedback2], eax ; case ALG == 5 + mov [esi + opngen_t.feedback3], eax + mov [esi + opngen_t.feedback4], eax + jmp short og_calcslot3 +og_calcalg5: mov ebx, [edi + ch_t.connect1] ; case ALG != 5 + add [ebx], eax +og_calcslot3: add edi, byte slot_t_size ; slot3 calculate + calcenv envcalc2, envret2 + jl short og_calcslot2 + mov eax, [esi + opngen_t.feedback2] + op_out + mov ebx, [edi - (slot_t_size * 1) + ch_t.connect2] + add [ebx], eax +og_calcslot2: add edi, byte slot_t_size ; slot2 calculate + calcenv envcalc3, envret3 + jl short og_calcslot4 + mov eax, [esi + opngen_t.feedback3] + op_out + mov ebx, [edi - (slot_t_size * 2) + ch_t.connect3] + add [ebx], eax +og_calcslot4: add edi, byte slot_t_size ; slot4 calculate + calcenv envcalc4, envret4 + jl short og_calcsloted + mov eax, [esi + opngen_t.feedback4] + op_out + mov ebx, [edi - (slot_t_size * 3) + ch_t.connect4] + add [ebx], eax +og_calcsloted: sub edi, (slot_t_size * 3) + inc dword [esi + opngen_t.playing] +og_calcch_nt: add edi, ch_t_size + dec ch + jne near og_calcch_lp + mov eax, [esi + opngen_t.outdc] + add [esi + opngen_t.outdl], eax + add [esi + opngen_t.outdr], eax + sar dword [esi + opngen_t.outdl], FMVOL_SFTBIT + sar dword [esi + opngen_t.outdr], FMVOL_SFTBIT + mov ebx, [esi + opngen_t.calcremain] + mov eax, [_opncfg + opncfg_t.calc1024] + sub ebx, eax + ja near og_fmout_lp + lea eax, [eax + ebx] + neg ebx +og_nextsamp: mov ecx, eax +%ifdef OPNGENX86 + imul eax, [esi + opngen_t.outdl] + imul ecx, [esi + opngen_t.outdr] + add eax, [esp + OPN_SAMPL] + add ecx, [esp + OPN_SAMPR] + imul dword [_opncfg + opncfg_t.fmvol] + mov eax, ecx + add [ebp], edx + imul dword [_opncfg + opncfg_t.fmvol] + mov [esi + opngen_t.calcremain], ebx + add [ebp+4], edx +%else + mov edx, [_opncfg + opncfg_t.fmvol] + mov [esi + opngen_t.calcremain], ebx + imul eax, [esi + opngen_t.outdl] + imul ecx, [esi + opngen_t.outdr] + add eax, [esp + OPN_SAMPL] + add ecx, [esp + OPN_SAMPR] + sar eax, 8 + sar ecx, 8 + imul eax, edx + imul ecx, edx + sar eax, (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8) + sar ecx, (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8) + add [ebp], eax + add [ebp+4], ecx +%endif + add ebp, byte 8 + dec dword [esp + OPN_LENG] + jne near og_fmout_st + add esp, byte 8 + pop ebp + pop edi + pop esi + pop ebx +og_noupdate: ret 4 + + setenv envcalc1, envret1, 0 + setenv envcalc2, envret2, 1 + setenv envcalc3, envret3, 2 + setenv envcalc4, envret4, 3 + + + align 16 +@opngen_getpcmvr@12: + cmp dword [_opncfg + opncfg_t.vr_en], byte 0 + je near @opngen_getpcm@12 + + cmp dword [esp+4], byte 0 + je near ogv_noupdate + + push ebx + push esi + push edi + push ebp + sub esp, byte 8 + +%define OPNV_SAMPL equ 0 +%define OPNV_SAMPR equ 4 +%define OPNV_LENG equ 16 + 8 + 4 + + mov esi, ecx + mov ebp, edx + mov ebx, [esi + opngen_t.calcremain] +ogv_fmout_st: mov eax, FMDIV_ENT + and dword [esp + OPNV_SAMPL], byte 0 + and dword [esp + OPNV_SAMPR], byte 0 + sub ebx, eax + jnc near ogv_nextsamp + lea eax, [eax + ebx] + neg ebx +ogv_fmout_lp: mov edx, eax + imul eax, [esi + opngen_t.outdl] + imul edx, [esi + opngen_t.outdr] + add [esp + OPNV_SAMPL], eax + add [esp + OPNV_SAMPR], edx + xor eax, eax + mov [esi + opngen_t.calcremain], ebx + mov [esi + opngen_t.outdl], eax + mov [esi + opngen_t.outdc], eax + mov [esi + opngen_t.outdr], eax + mov ch, [esi + opngen_t.playchannels] + lea edi, [esi + opngen_t.opnch] +ogv_calcch_lp: xor eax, eax + mov [esi + opngen_t.feedback2], eax + mov [esi + opngen_t.feedback3], eax + mov [esi + opngen_t.feedback4], eax + calcenv vrenvcalc1, vrenvret1 ; slot1 calculate + jl near ogv_calcslot3 + mov cl, [edi + ch_t.feedback] + test cl, cl + je short ogv_nofeed + mov eax, [edi + ch_t.op1fb] ; with feedback + mov ebx, eax + shr eax, cl + op_out + mov [edi + ch_t.op1fb], eax + add eax, ebx + sar eax, 1 + jmp short ogv_algchk +ogv_nofeed: xor eax, eax ; without feedback + op_out +ogv_algchk: cmp byte [edi + ch_t.algorithm], 5 + jne short ogv_calcalg5 + mov [esi + opngen_t.feedback2], eax ; case ALG == 5 + mov [esi + opngen_t.feedback3], eax + mov [esi + opngen_t.feedback4], eax + jmp short ogv_calcslot3 +ogv_calcalg5: mov ebx, [edi + ch_t.connect1] ; case ALG != 5 + add [ebx], eax +ogv_calcslot3: add edi, byte slot_t_size ; slot3 calculate + calcenv vrenvcalc2, vrenvret2 + jl short ogv_calcslot2 + mov eax, [esi + opngen_t.feedback2] + op_out + mov ebx, [edi - (slot_t_size * 1) + ch_t.connect2] + add [ebx], eax +ogv_calcslot2: add edi, byte slot_t_size ; slot2 calculate + calcenv vrenvcalc3, vrenvret3 + jl short ogv_calcslot4 + mov eax, [esi + opngen_t.feedback3] + op_out + mov ebx, [edi - (slot_t_size * 2) + ch_t.connect3] + add [ebx], eax +ogv_calcslot4: add edi, byte slot_t_size ; slot4 calculate + calcenv vrenvcalc4, vrenvret4 + jl short ogv_calcsloted + mov eax, [esi + opngen_t.feedback4] + op_out + mov ebx, [edi - (slot_t_size * 3) + ch_t.connect4] + add [ebx], eax +ogv_calcsloted: add edi, byte (ch_t_size - (slot_t_size * 3)) + dec ch + jne near ogv_calcch_lp + mov eax, [esi + opngen_t.outdl] + mov edx, [esi + opngen_t.outdc] + imul eax, [_opncfg + opncfg_t.vr_l] + mov ebx, edx + sar eax, 5 + add ebx, eax + sar eax, 2 + add edx, eax + mov eax, [esi + opngen_t.outdr] + imul eax, [_opncfg + opncfg_t.vr_r] + sar eax, 5 + add edx, eax + sar eax, 2 + add ebx, eax + add [esi + opngen_t.outdl], edx + add [esi + opngen_t.outdr], ebx + sar dword [esi + opngen_t.outdl], FMVOL_SFTBIT + sar dword [esi + opngen_t.outdr], FMVOL_SFTBIT + mov ebx, [esi + opngen_t.calcremain] + mov eax, [_opncfg + opncfg_t.calc1024] + sub ebx, eax + ja near ogv_fmout_lp + lea eax, [eax + ebx] + neg ebx +ogv_nextsamp: mov ecx, eax +%ifdef OPNGENX86 + imul eax, [esi + opngen_t.outdl] + imul ecx, [esi + opngen_t.outdr] + add eax, [esp + OPNV_SAMPL] + add ecx, [esp + OPNV_SAMPR] + imul dword [_opncfg + opncfg_t.fmvol] + mov eax, ecx + add [ebp], edx + imul dword [_opncfg + opncfg_t.fmvol] + mov [esi + opngen_t.calcremain], ebx + add [ebp+4], edx +%else + mov edx, [_opncfg + opncfg_t.fmvol] + mov [esi + opngen_t.calcremain], ebx + imul eax, [esi + opngen_t.outdl] + imul ecx, [esi + opngen_t.outdr] + add eax, [esp + OPN_SAMPL] + add ecx, [esp + OPN_SAMPR] + sar eax, 8 + sar ecx, 8 + imul eax, edx + imul ecx, edx + sar eax, (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8) + sar ecx, (OPM_OUTSB + FMDIV_BITS + 1 + 6 - FMVOL_SFTBIT - 8) + add [ebp], eax + add [ebp+4], ecx +%endif + add ebp, byte 8 + dec dword [esp + OPNV_LENG] + jne near ogv_fmout_st + add esp, byte 8 + pop ebp + pop edi + pop esi + pop ebx +ogv_noupdate: ret 4 + + setenv vrenvcalc1, vrenvret1, 0 + setenv vrenvcalc2, vrenvret2, 1 + setenv vrenvcalc3, vrenvret3, 2 + setenv vrenvcalc4, vrenvret4, 3 + diff --git a/windows/x86/parts.x86 b/windows/x86/parts.x86 old mode 100755 new mode 100644 index d66e2ca6..fdd044e0 --- a/windows/x86/parts.x86 +++ b/windows/x86/parts.x86 @@ -1,139 +1,139 @@ - -section .text - - global @rand_setseed@4 - global @rand_get@0 - global @AdjustAfterMultiply@4 - global @AdjustBeforeDivision@4 - global @sjis2jis@4 - global @jis2sjis@4 - global @satuation_s16@12 - global @satuation_s16x@12 - global @satuation_s16mmx@12 - - align 16 -@rand_get@0: mov eax, dword [_randseed] - imul eax, 343fdh - add eax, 269ec3h - mov dword [_randseed], eax - sar eax, 16 - ret - -@rand_setseed@4:mov dword [_randseed], ecx - ret - - align 16 -@AdjustAfterMultiply@4: - mov al, cl - aam - shl ah, 4 - add al, ah - ret - - align 16 -@AdjustBeforeDivision@4: - mov al, cl - mov ah, al - and al, 0fh - shr ah, 4 - aad - ret - - align 16 -@sjis2jis@4: mov eax, ecx - shl ah, 1 - sub al, 1fh - js sjis2jis1a - cmp al, 61h - adc al, 0deh -sjis2jis1a: add ax, 1fa1h - and eax, 7f7fh - ret - - align 16 -@jis2sjis@4: mov eax, ecx - and eax, 7f7fh - add ah, 21h - shr ah, 1 - jnc short jis2sjis1a - add al, 5eh -jis2sjis1a: cmp al, 60h - sbb al, 0e0h - xor ah, 0a0h - ret - - align 16 -@satuation_s16@12: - push ebx - mov ebx, [esp+8] - shr ebx, 1 - je short ss16_ed -ss16_lp: mov eax, [edx] - cmp eax, 000008000h - jl short ss16_min - mov ax, 7fffh - jmp short ss16_set -ss16_min: cmp eax, 0ffff8000h - jg short ss16_set - mov ax, 8001h -ss16_set: lea edx, [edx+4] - mov [ecx], ax - dec ebx - lea ecx, [ecx+2] - jne short ss16_lp -ss16_ed: pop ebx - ret 4 - - align 16 -@satuation_s16x@12: - push ebx - mov ebx, [esp+8] - shr ebx, 2 - je short ss16x_ed -ss16x_lp: mov eax, [edx] - cmp eax, 000008000h - jl short ss16xl_min - mov ax, 7fffh - jmp short ss16xl_set -ss16xl_min: cmp eax, 0ffff8000h - jg short ss16xl_set - mov ax, 8001h -ss16xl_set: mov [ecx+2], ax - mov eax, [edx+4] - cmp eax, 000008000h - jl short ss16xr_min - mov ax, 7fffh - jmp short ss16xr_set -ss16xr_min: cmp eax, 0ffff8000h - jg short ss16xr_set - mov ax, 8001h -ss16xr_set: mov [ecx], ax - lea edx, [edx+8] - dec ebx - lea ecx, [ecx+4] - jne short ss16x_lp -ss16x_ed: pop ebx - ret 4 - - align 16 -@satuation_s16mmx@12: - mov eax, [esp+4] - shr eax, 3 - je short ss16m_ed - pxor mm0, mm0 -ss16m_lp: movq mm1, [edx] - movq mm2, [edx+8] - packssdw mm1, mm2 - lea edx, [edx+16] - movq [ecx], mm1 - lea ecx, [ecx+8] - dec eax - jne short ss16m_lp - emms -ss16m_ed: ret 4 - - -section .data - -_randseed dd 1 - + +section .text + + global @rand_setseed@4 + global @rand_get@0 + global @AdjustAfterMultiply@4 + global @AdjustBeforeDivision@4 + global @sjis2jis@4 + global @jis2sjis@4 + global @satuation_s16@12 + global @satuation_s16x@12 + global @satuation_s16mmx@12 + + align 16 +@rand_get@0: mov eax, dword [_randseed] + imul eax, 343fdh + add eax, 269ec3h + mov dword [_randseed], eax + sar eax, 16 + ret + +@rand_setseed@4:mov dword [_randseed], ecx + ret + + align 16 +@AdjustAfterMultiply@4: + mov al, cl + aam + shl ah, 4 + add al, ah + ret + + align 16 +@AdjustBeforeDivision@4: + mov al, cl + mov ah, al + and al, 0fh + shr ah, 4 + aad + ret + + align 16 +@sjis2jis@4: mov eax, ecx + shl ah, 1 + sub al, 1fh + js sjis2jis1a + cmp al, 61h + adc al, 0deh +sjis2jis1a: add ax, 1fa1h + and eax, 7f7fh + ret + + align 16 +@jis2sjis@4: mov eax, ecx + and eax, 7f7fh + add ah, 21h + shr ah, 1 + jnc short jis2sjis1a + add al, 5eh +jis2sjis1a: cmp al, 60h + sbb al, 0e0h + xor ah, 0a0h + ret + + align 16 +@satuation_s16@12: + push ebx + mov ebx, [esp+8] + shr ebx, 1 + je short ss16_ed +ss16_lp: mov eax, [edx] + cmp eax, 000008000h + jl short ss16_min + mov ax, 7fffh + jmp short ss16_set +ss16_min: cmp eax, 0ffff8000h + jg short ss16_set + mov ax, 8001h +ss16_set: lea edx, [edx+4] + mov [ecx], ax + dec ebx + lea ecx, [ecx+2] + jne short ss16_lp +ss16_ed: pop ebx + ret 4 + + align 16 +@satuation_s16x@12: + push ebx + mov ebx, [esp+8] + shr ebx, 2 + je short ss16x_ed +ss16x_lp: mov eax, [edx] + cmp eax, 000008000h + jl short ss16xl_min + mov ax, 7fffh + jmp short ss16xl_set +ss16xl_min: cmp eax, 0ffff8000h + jg short ss16xl_set + mov ax, 8001h +ss16xl_set: mov [ecx+2], ax + mov eax, [edx+4] + cmp eax, 000008000h + jl short ss16xr_min + mov ax, 7fffh + jmp short ss16xr_set +ss16xr_min: cmp eax, 0ffff8000h + jg short ss16xr_set + mov ax, 8001h +ss16xr_set: mov [ecx], ax + lea edx, [edx+8] + dec ebx + lea ecx, [ecx+4] + jne short ss16x_lp +ss16x_ed: pop ebx + ret 4 + + align 16 +@satuation_s16mmx@12: + mov eax, [esp+4] + shr eax, 3 + je short ss16m_ed + pxor mm0, mm0 +ss16m_lp: movq mm1, [edx] + movq mm2, [edx+8] + packssdw mm1, mm2 + lea edx, [edx+16] + movq [ecx], mm1 + lea ecx, [ecx+8] + dec eax + jne short ss16m_lp + emms +ss16m_ed: ret 4 + + +section .data + +_randseed dd 1 + diff --git a/windows/x86/pccore.inc b/windows/x86/pccore.inc old mode 100755 new mode 100644 index e7dfbdbf..4152fc6f --- a/windows/x86/pccore.inc +++ b/windows/x86/pccore.inc @@ -1,8 +1,8 @@ - - struc np2cfg_t -.uPD72020 resb 1 -.DISPSYNC resb 1 -.RASTER resb 1 -.realpal resb 1 - endstruc - + + struc np2cfg_t +.uPD72020 resb 1 +.DISPSYNC resb 1 +.RASTER resb 1 +.realpal resb 1 + endstruc + diff --git a/windows/x86/vram.inc b/windows/x86/vram.inc old mode 100755 new mode 100644 index 6bfe2055..972f2672 --- a/windows/x86/vram.inc +++ b/windows/x86/vram.inc @@ -1,25 +1,25 @@ - -%define SCRN_BUFSIZE 0x4b000 - - - struc vramop_t -.operate resd 1 -.tramwait resd 1 -.vramwait resd 1 -.grcgwait resd 1 - endstruc - - struc dsync_t -.text_vbp resd 1 -.textymax resd 1 -.grph_vbp resd 1 -.grphymax resd 1 - -.scrnxpos resd 1 -.scrnxmax resd 1 -.scrnxextend resd 1 -.scrnymax resd 1 -.textvad resd 1 -.grphvad resd 1 - endstruc - + +%define SCRN_BUFSIZE 0x4b000 + + + struc vramop_t +.operate resd 1 +.tramwait resd 1 +.vramwait resd 1 +.grcgwait resd 1 + endstruc + + struc dsync_t +.text_vbp resd 1 +.textymax resd 1 +.grph_vbp resd 1 +.grphymax resd 1 + +.scrnxpos resd 1 +.scrnxmax resd 1 +.scrnxextend resd 1 +.scrnymax resd 1 +.textvad resd 1 +.grphvad resd 1 + endstruc + diff --git a/windows/x86/vs2019/x86.xml b/windows/x86/vs2019/x86.xml old mode 100755 new mode 100644 index fb9c73cb..d311f389 --- a/windows/x86/vs2019/x86.xml +++ b/windows/x86/vs2019/x86.xml @@ -1,181 +1,181 @@ - - - - - - - - - - General - - - - - Command Line - - - - - - - - - - - - - - - - - - - Execute Before - - - Specifies the targets for the build customization to run before. - - - - - - - - - - - Execute After - - - Specifies the targets for the build customization to run after. - - - - - - - - - - - - - - Additional Options - - - Additional Options - - - - - - + + + + + + + + + + General + + + + + Command Line + + + + + + + + + + + + + + + + + + + Execute Before + + + Specifies the targets for the build customization to run before. + + + + + + + + + + + Execute After + + + Specifies the targets for the build customization to run after. + + + + + + + + + + + + + + Additional Options + + + Additional Options + + + + + + \ No newline at end of file From ae1de0eedb4d3003750f43e9912a8a642e04795e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Mon, 9 Mar 2026 19:01:03 +0200 Subject: [PATCH 2/2] =?UTF-8?q?Normalize=20=C2=A5=20to=20\=20and=20?= =?UTF-8?q?=E2=80=BE=20to=20~=20in=20program=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 0 bios/bios.c | 2 +- cbus/atapicmd.c | 2 +- cbus/boardsb16.c | 2 +- cbus/ct1741io.c | 2 +- cbus/ct1745io.c | 6 ++-- cbus/ideio.c | 6 ++-- cbus/pcm86io.c | 2 +- cbus/scsiio.c | 2 +- font/font.c | 4 +-- generic/hostdrv.c | 2 +- generic/hostdrvnt.c | 74 ++++++++++++++++++++++---------------------- i386hax/haxcore.c | 46 +++++++++++++-------------- io/cgrom.c | 12 +++---- io/np2sysp.c | 4 +-- io/pit.c | 2 +- io/upd4990.c | 2 +- network/net.c | 6 ++-- nevent.c | 4 +-- sound/pcm86.h | 24 +++++++------- sound/pcm86c.c | 2 +- sound/pcm86g.c | 2 +- wab/cirrus_vga.c | 2 +- windows/mousemng.cpp | 10 +++--- windows/np2arg.cpp | 6 ++-- windows/sysmng.cpp | 10 +++--- 26 files changed, 118 insertions(+), 118 deletions(-) mode change 100755 => 100644 README.md mode change 100755 => 100644 bios/bios.c mode change 100755 => 100644 font/font.c diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/bios/bios.c b/bios/bios.c old mode 100755 new mode 100644 index 59758cab..949b6a78 --- a/bios/bios.c +++ b/bios/bios.c @@ -60,7 +60,7 @@ static void trace_fmt_ex(const char *fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } diff --git a/cbus/atapicmd.c b/cbus/atapicmd.c index 649b4fc7..84fc1382 100644 --- a/cbus/atapicmd.c +++ b/cbus/atapicmd.c @@ -8,7 +8,7 @@ static void trace_fmt_ex(const char* fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } diff --git a/cbus/boardsb16.c b/cbus/boardsb16.c index 3ca8bd14..d22fad21 100644 --- a/cbus/boardsb16.c +++ b/cbus/boardsb16.c @@ -25,7 +25,7 @@ static void trace_fmt_ex(const char *fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } diff --git a/cbus/ct1741io.c b/cbus/ct1741io.c index 028591aa..9f0f403a 100644 --- a/cbus/ct1741io.c +++ b/cbus/ct1741io.c @@ -25,7 +25,7 @@ static void trace_fmt_ex(const char* fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } diff --git a/cbus/ct1745io.c b/cbus/ct1745io.c index ef3b78c4..b6b031c4 100644 --- a/cbus/ct1745io.c +++ b/cbus/ct1745io.c @@ -19,7 +19,7 @@ static void trace_fmt_ex(const char *fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } @@ -61,7 +61,7 @@ static void IOOUTCALL sb16_o2400(UINT port, REG8 dat) { g_sb16.mixsel = dat; } static void IOOUTCALL sb16_o2500(UINT port, REG8 dat) { -//printf("mixer port write %x %x¥n",dat,g_sb16.mixsel); +//printf("mixer port write %x %x\n",dat,g_sb16.mixsel); if (g_sb16.mixsel >= MIXER_VOL_START && g_sb16.mixsel <= MIXER_VOL_END) { g_sb16.mixreg[g_sb16.mixsel] = dat; @@ -150,7 +150,7 @@ static REG8 IOINPCALL sb16_i2400(UINT port) { return g_sb16.mixsel; } static REG8 IOINPCALL sb16_i2500(UINT port) { -//printf("mixer port read %x %x¥n",g_sb16.mixreg[g_sb16.mixsel],g_sb16.mixsel); +//printf("mixer port read %x %x\n",g_sb16.mixreg[g_sb16.mixsel],g_sb16.mixsel); if (g_sb16.mixsel >= MIXER_VOL_START && g_sb16.mixsel <= MIXER_VOL_END) { return g_sb16.mixreg[g_sb16.mixsel]; } diff --git a/cbus/ideio.c b/cbus/ideio.c index 5c81e916..64875ddc 100644 --- a/cbus/ideio.c +++ b/cbus/ideio.c @@ -9,7 +9,7 @@ // va_list ap; // va_start(ap, fmt); // vsprintf(stmp, fmt, ap); -// strcat(stmp, "¥n"); +// strcat(stmp, "\n"); // va_end(ap); // OutputDebugStringA(stmp); //} @@ -606,7 +606,7 @@ static void IOOUTCALL ideio_o430(UINT port, REG8 dat) { // 430h ideio.bank[(port >> 1) & 1] = dat & 0x71; } - //sprintf(buf, "0x%x¥n", dat); + //sprintf(buf, "0x%x\n", dat); //OutputDebugStringA(buf); } @@ -668,7 +668,7 @@ static REG8 IOINPCALL ideio_i433(UINT port) { if(ret == 0x2 && ideio.dev[1].drv[0].device==IDETYPE_NONE && ideio.dev[1].drv[1].device==IDETYPE_NONE){ ret = 0; } - //OutputDebugStringA("IN 433h¥n"); + //OutputDebugStringA("IN 433h\n"); return(ret); } diff --git a/cbus/pcm86io.c b/cbus/pcm86io.c index a801274c..d350c771 100644 --- a/cbus/pcm86io.c +++ b/cbus/pcm86io.c @@ -16,7 +16,7 @@ static void trace_fmt_ex(const char* fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } diff --git a/cbus/scsiio.c b/cbus/scsiio.c index 5d5e4366..8cf18f88 100644 --- a/cbus/scsiio.c +++ b/cbus/scsiio.c @@ -219,7 +219,7 @@ static void trace_fmt_ex(const char* fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } diff --git a/font/font.c b/font/font.c old mode 100755 new mode 100644 index a09dbed4..7b3f00b2 --- a/font/font.c +++ b/font/font.c @@ -430,7 +430,7 @@ unsigned short font_Jis2Sjis( unsigned short jis ) if (SJis > 0x8775 && SJis < 0x877E) return 0; if (SJis > 0x879C && SJis < 0x889F) return 0; - th[0] = ubyte; th[1] = lbyte; th[2] = '¥0'; + th[0] = ubyte; th[1] = lbyte; th[2] = '\0'; lstrlenA((char*)th); return SJis; @@ -488,7 +488,7 @@ unsigned short font_Jis2Sjis2( unsigned short jis ) if (SJis > 0x8775 && SJis < 0x877E) return 0; if (SJis > 0x879C && SJis < 0x889F) return 0; - th[0] = ubyte; th[1] = lbyte; th[2] = '¥0'; + th[0] = ubyte; th[1] = lbyte; th[2] = '\0'; CharNextA((char*)th); return SJis; diff --git a/generic/hostdrv.c b/generic/hostdrv.c index abcf406a..b384481d 100644 --- a/generic/hostdrv.c +++ b/generic/hostdrv.c @@ -961,7 +961,7 @@ static void get_fileattr(INTRST intrst) { } TRACEOUT(("get_fileattr: ->%s", intrst->fcbname_ptr)); - isRoot = intrst->filename_ptr[0] == '¥0' || (intrst->filename_ptr[0] == OEMPATHDIVC && intrst->filename_ptr[1] == '¥0'); + isRoot = intrst->filename_ptr[0] == '\0' || (intrst->filename_ptr[0] == OEMPATHDIVC && intrst->filename_ptr[1] == '\0'); if(!isRoot && (strcmp(intrst->fcbname_ptr, "???????????") || intrst->filename_ptr[0])){ // XXX: Win用特例 if (is_wildcards(intrst->fcbname_ptr) || (hostdrvs_getrealpath(&hdp, intrst->filename_ptr) != ERR_NOERROR)) { diff --git a/generic/hostdrvnt.c b/generic/hostdrvnt.c index 692b7b01..4db8af97 100644 --- a/generic/hostdrvnt.c +++ b/generic/hostdrvnt.c @@ -42,7 +42,7 @@ static void trace_fmt_ex(const char* fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } @@ -53,7 +53,7 @@ static void trace_fmt_exw(const WCHAR* fmt, ...) va_list ap; va_start(ap, fmt); vswprintf(stmp, 2048, fmt, ap); - wcscat(stmp, L"¥n"); + wcscat(stmp, L"\n"); va_end(ap); OutputDebugStringW(stmp); } @@ -198,7 +198,7 @@ void hostdrvNT_updateHDrvRoot(void) // パス長さが制限オーバーならエラー if (_tcslen(np2cfg.hdrvroot) >= MAX_PATH) { - s_hdrvRoot[0] = '¥0'; + s_hdrvRoot[0] = '\0'; s_hdrvAcc = 0; return; } @@ -212,7 +212,7 @@ void hostdrvNT_updateHDrvRoot(void) int lengthUnicode = MultiByteToWideChar(CP_ACP, 0, np2cfg.hdrvroot, strlen(np2cfg.hdrvroot) + 1, NULL, 0); if (lengthUnicode < 0 || lengthUnicode > MAX_PATH) { - s_hdrvRoot[0] = '¥0'; + s_hdrvRoot[0] = '\0'; s_hdrvAcc = 0; return; } @@ -222,9 +222,9 @@ void hostdrvNT_updateHDrvRoot(void) // 最後の文字が¥なら除去 slen = wcslen(s_hdrvRoot); - if (slen > 0 && s_hdrvRoot[slen - 1] == '¥¥') + if (slen > 0 && s_hdrvRoot[slen - 1] == '\\') { - s_hdrvRoot[slen - 1] = '¥0'; + s_hdrvRoot[slen - 1] = '\0'; } s_hdrvAcc = np2cfg.hdrvacc; @@ -349,8 +349,8 @@ static int hostdrvNT_getHostPath(WCHAR* virPath, WCHAR* hostPath, UINT8* isRoot, hdrvPathLen = wcslen(hdrvPath); // ホストのパスと結合 - if (virPath[0] == '¥¥') virPath++; - hostPath[0] = '¥0'; + if (virPath[0] == '\\') virPath++; + hostPath[0] = '\0'; if (!PathCombineW(pathTmp, hdrvPath, virPath)) { return 1; @@ -368,7 +368,7 @@ static int hostdrvNT_getHostPath(WCHAR* virPath, WCHAR* hostPath, UINT8* isRoot, if (wcslen(hostPath) > hdrvPathLen + 1) { UINT32 vlen = wcslen(hostPath + hdrvPathLen + 1); - *isRoot = (vlen == 0 || (vlen == 1 && *(hostPath + hdrvPathLen + 1) == '¥¥')); + *isRoot = (vlen == 0 || (vlen == 1 && *(hostPath + hdrvPathLen + 1) == '\\')); } else { @@ -386,10 +386,10 @@ static int hostdrvNT_getHostPath(WCHAR* virPath, WCHAR* hostPath, UINT8* isRoot, else { // 最後の区切り文字以降を削除 - WCHAR* sepaPos = wcsrchr(hostPath, '¥¥'); + WCHAR* sepaPos = wcsrchr(hostPath, '\\'); if (sepaPos != NULL) { - *sepaPos = '¥0'; + *sepaPos = '\0'; } } } @@ -401,7 +401,7 @@ static int hostdrvNT_hasInvalidWildcard(WCHAR* name) { int i; int hasWildcard = 0; - for (i = 0; name[i] != '¥0'; i++) + for (i = 0; name[i] != '\0'; i++) { WCHAR c = name[i]; if (!hasWildcard) @@ -413,7 +413,7 @@ static int hostdrvNT_hasInvalidWildcard(WCHAR* name) } else { - if ((c == L'¥¥')) + if ((c == L'\\')) { return 1; } @@ -650,18 +650,18 @@ static void hostdrvNT_notifyChange(WCHAR* changedHostFileName, UINT32 action, UI { // ファイルなら最後のドライブ区切り文字以降をカット WCHAR* hostSepa; - if (hostSepa = wcsrchr(changedHostDir, '¥¥')) + if (hostSepa = wcsrchr(changedHostDir, '\\')) { - *hostSepa = '¥0'; + *hostSepa = '\0'; } } else { // ディレクトリなら最後の文字が¥の時カット UINT32 changedHostDirLen = wcslen(changedHostDir); - if (changedHostDirLen >= 1 && changedHostDir[changedHostDirLen - 1] == '¥¥') + if (changedHostDirLen >= 1 && changedHostDir[changedHostDirLen - 1] == '\\') { - changedHostDir[changedHostDirLen - 1] = '¥0'; + changedHostDir[changedHostDirLen - 1] = '\0'; } } @@ -756,9 +756,9 @@ static int hostdrvNT_getOneEntry(NP2HOSTDRVNT_FILEINFO* fi, NP2_FILE_BOTH_DIR_IN findPathLen = wcslen(findPath); if (fi->isDirectory) { - if (findPath[findPathLen - 1] != '¥¥') + if (findPath[findPathLen - 1] != '\\') { - wcscat(findPath, L"¥¥"); + wcscat(findPath, L"\\"); } wcscat(findPath, pattern); } @@ -809,7 +809,7 @@ static int hostdrvNT_getOneEntry(NP2HOSTDRVNT_FILEINFO* fi, NP2_FILE_BOTH_DIR_IN // WCHAR *shortFileName; // UINT32 shortLen; // // 最後の区切り文字以降を採用 - // shortFileName = wcsrchr(shortPath, '¥¥'); + // shortFileName = wcsrchr(shortPath, '\\'); // if (shortFileName == NULL) // { // shortFileName = shortPath; @@ -847,7 +847,7 @@ static int hostdrvNT_getOneEntry(NP2HOSTDRVNT_FILEINFO* fi, NP2_FILE_BOTH_DIR_IN // WCHAR* shortFileName; // UINT32 shortLen; // // 最後の区切り文字以降を採用 - // shortFileName = wcsrchr(shortPath, '¥¥'); + // shortFileName = wcsrchr(shortPath, '\\'); // if (shortFileName == NULL) // { // shortFileName = shortPath; @@ -986,9 +986,9 @@ static void hostdrvNT_IRP_MJ_CREATE(HOSTDRVNT_INVOKEINFO *invokeInfo) { WCHAR *pathTmp; UINT32 combineLen; - if (dirName[dirNameLen - 1] == '¥¥') + if (dirName[dirNameLen - 1] == '\\') { - dirName[dirNameLen - 1] = '¥0'; + dirName[dirNameLen - 1] = '\0'; } combineLen = wcslen(dirName) + 1 + wcslen(fileName); if (combineLen >= MAX_PATH) @@ -1008,7 +1008,7 @@ static void hostdrvNT_IRP_MJ_CREATE(HOSTDRVNT_INVOKEINFO *invokeInfo) return; } wcscpy(pathTmp, dirName); - wcscat(pathTmp, L"¥¥"); + wcscat(pathTmp, L"\\"); wcscat(pathTmp, fileName); free(fileName); fileName = pathTmp; // ディレクトリ付きに入れ替え @@ -1022,7 +1022,7 @@ static void hostdrvNT_IRP_MJ_CREATE(HOSTDRVNT_INVOKEINFO *invokeInfo) hostdrvDesiredAccess = cpu_kmemoryread_d(invokeInfo->stack.parameters.create.securityContext + 4 * 2); // DesiredAccessはポインタの先の3番目の変数 } hostdrvOptions = invokeInfo->stack.parameters.create.options; - hostdrvFileAttributes = (UCHAR)(invokeInfo->stack.parameters.create.fileAttributes & ‾FILE_ATTRIBUTE_NORMAL); + hostdrvFileAttributes = (UCHAR)(invokeInfo->stack.parameters.create.fileAttributes & ~FILE_ATTRIBUTE_NORMAL); hostdrvShareAccess = invokeInfo->stack.parameters.create.shareAccess; hostdrvEALength = invokeInfo->stack.parameters.create.eaLength; @@ -1131,7 +1131,7 @@ static void hostdrvNT_IRP_MJ_CREATE(HOSTDRVNT_INVOKEINFO *invokeInfo) DWORD attrs; // パスに無効な文字が含まれる場合はSTATUS_OBJECT_NAME_INVALID ここでSTATUS_OBJECT_NAME_NOT_FOUNDを返すとワイルドカード付きcopyコマンドなどがうまく動かない - if (wcschr(fileName, '?') || wcschr(fileName, '*') || wcschr(fileName, '¥"') || wcschr(fileName, '|') || wcschr(fileName, '<') || wcschr(fileName, '>')) + if (wcschr(fileName, '?') || wcschr(fileName, '*') || wcschr(fileName, '\"') || wcschr(fileName, '|') || wcschr(fileName, '<') || wcschr(fileName, '>')) { TRACEOUTW((L"INVALID PATH", fileName)); cpu_kmemorywrite_d(invokeInfo->statusAddr, NP2_STATUS_OBJECT_NAME_INVALID); // Status STATUS_OBJECT_NAME_INVALID @@ -1164,9 +1164,9 @@ static void hostdrvNT_IRP_MJ_CREATE(HOSTDRVNT_INVOKEINFO *invokeInfo) // パスの末尾が¥なら除去 hostPathLength = wcslen(hostPath); - if (hostPathLength > 0 && hostPath[hostPathLength - 1] == '¥¥') + if (hostPathLength > 0 && hostPath[hostPathLength - 1] == '\\') { - hostPath[hostPathLength - 1] = '¥0'; + hostPath[hostPathLength - 1] = '\0'; } // とりあえずオープン @@ -2019,9 +2019,9 @@ static void hostdrvNT_IRP_MJ_QUERY_INFORMATION(HOSTDRVNT_INVOKEINFO* invokeInfo) // ディレクトリ内の全ファイル検索 wcscpy(findPath, fi->hostFileName); findPathLen = wcslen(findPath); - if (findPath[findPathLen - 1] != '¥¥') + if (findPath[findPathLen - 1] != '\\') { - wcscat(findPath, L"¥¥"); + wcscat(findPath, L"\\"); } wcscat(findPath, L"*"); @@ -2204,7 +2204,7 @@ static void hostdrvNT_IRP_MJ_SET_INFORMATION(HOSTDRVNT_INVOKEINFO* invokeInfo) fileInfo.dwFileAttributes = basicInfo.FileAttributes; if (fi->isDirectory) { - fileInfo.dwFileAttributes &= ‾FILE_ATTRIBUTE_DIRECTORY; // エラーになるので付けない + fileInfo.dwFileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; // エラーになるので付けない } else if (fileInfo.dwFileAttributes == 0) { @@ -2499,7 +2499,7 @@ static void hostdrvNT_IRP_MJ_SET_INFORMATION(HOSTDRVNT_INVOKEINFO* invokeInfo) hostdrvNT_memread(invokeInfo->inBufferAddr + 4 + 4 + 4, newPath, renameInfo.FileNameLength); // 新ファイルパスを¥??¥の形式で指定された場合、特例 - if (wcsnicmp(newPath, L"¥¥??¥¥", 4) == 0) + if (wcsnicmp(newPath, L"\\??\\", 4) == 0) { // ドライブ文字がないタイプならNG if (wcslen(newPath) < 5) @@ -2514,7 +2514,7 @@ static void hostdrvNT_IRP_MJ_SET_INFORMATION(HOSTDRVNT_INVOKEINFO* invokeInfo) newPath[4] = 'z'; // ¥??¥Z:¥の形式のパスが来た場合、特例で¥??¥Z:¥をカットして新ファイルパスとする - if (wcsnicmp(newPath, L"¥¥??¥¥z:¥¥", 7) == 0) + if (wcsnicmp(newPath, L"\\??\\z:\\", 7) == 0) { WCHAR* pathTmp = newPath; while (*(pathTmp + 7)) @@ -2534,13 +2534,13 @@ static void hostdrvNT_IRP_MJ_SET_INFORMATION(HOSTDRVNT_INVOKEINFO* invokeInfo) } } // 新ファイルパスを¥DosDevices¥z:¥の形式で指定された場合、特例 - if (wcslen(newPath) >= 15 && wcsnicmp(newPath, L"¥¥DosDevices¥¥", 12) == 0 && newPath[13]==':') + if (wcslen(newPath) >= 15 && wcsnicmp(newPath, L"\\DosDevices\\", 12) == 0 && newPath[13]==':') { // ¥DosDevices¥Z:¥の形式のパスを前提に、ドライブ文字部分を適当にzに書き換え newPath[12] = 'z'; // ¥DosDevices¥Z:¥の形式のパスが来た場合、特例で¥DosDevices¥Z:¥をカットして新ファイルパスとする - if (wcsnicmp(newPath, L"¥¥DosDevices¥¥z:¥¥", 15) == 0) + if (wcsnicmp(newPath, L"\\DosDevices\\z:\\", 15) == 0) { WCHAR* pathTmp = newPath; while (*(pathTmp + 15)) @@ -3087,7 +3087,7 @@ static void hostdrvNT_invoke() { HOSTDRVNT_INVOKEINFO invokeInfo; - if ((s_hdrvRoot[0] == '¥0') || (!np2cfg.hdrvenable)) + if ((s_hdrvRoot[0] == '\0') || (!np2cfg.hdrvenable)) { // 無効の場合何もせずに抜ける return; @@ -3256,7 +3256,7 @@ static void hostdrvNT_invokeNotify() { HOSTDRVNT_INVOKEINFO invokeInfo; - if ((s_hdrvRoot[0] == '¥0') || (!np2cfg.hdrvenable)) + if ((s_hdrvRoot[0] == '\0') || (!np2cfg.hdrvenable)) { // 無効の場合何もせずに抜ける return; diff --git a/i386hax/haxcore.c b/i386hax/haxcore.c index be8d1aa3..a8bdb787 100644 --- a/i386hax/haxcore.c +++ b/i386hax/haxcore.c @@ -45,7 +45,7 @@ static void trace_fmt_ex(const char *fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } @@ -66,10 +66,10 @@ NP2_HAX_STAT np2haxstat = {0}; NP2_HAX_CORE np2haxcore = {0}; static void make_vm_str(OEMCHAR* buf, UINT32 vm_id){ - _stprintf(buf, OEMTEXT("¥¥¥¥.¥¥hax_vm%02d"), vm_id); + _stprintf(buf, OEMTEXT("\\\\.\\hax_vm%02d"), vm_id); } static void make_vcpu_str(OEMCHAR* buf, UINT32 vm_id, UINT32 vcpu_id){ - _stprintf(buf, OEMTEXT("¥¥¥¥.¥¥hax_vm%02d_vcpu%02d"), vm_id, vcpu_id); + _stprintf(buf, OEMTEXT("\\\\.\\hax_vm%02d_vcpu%02d"), vm_id, vcpu_id); } // HAXMが使えそうかチェック @@ -80,7 +80,7 @@ UINT8 i386hax_check(void) { HAX_CAPINFO haxcap = {0}; // HAXMカーネルモードドライバを開く - np2hax.hDevice = CreateFile(OEMTEXT("¥¥¥¥.¥¥HAX"), + np2hax.hDevice = CreateFile(OEMTEXT("\\\\.\\HAX"), GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); @@ -164,7 +164,7 @@ void i386hax_initialize(void) { i386hax_deinitialize(); // HAXMカーネルモードドライバを開く - np2hax.hDevice = CreateFile(OEMTEXT("¥¥¥¥.¥¥HAX"), + np2hax.hDevice = CreateFile(OEMTEXT("\\\\.\\HAX"), GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); @@ -598,7 +598,7 @@ ia32hax_copyregNP2toHAX(void) np2haxstat.state._cs.type = CPU_CS_DESC.flag; np2haxstat.state._cs.desc = CPU_CS_DESC.s; np2haxstat.state._cs.dpl = CPU_CS_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._cs.selector = (np2haxstat.state._cs.selector & ‾0x3) | CPU_CS_DESC.rpl; + //if(wacounter > 10)np2haxstat.state._cs.selector = (np2haxstat.state._cs.selector & ~0x3) | CPU_CS_DESC.rpl; np2haxstat.state._cs.present = CPU_CS_DESC.valid; np2haxstat.state._cs.available = CPU_CS_DESC.p; np2haxstat.state._cs.operand_size = CPU_CS_DESC.d; @@ -609,7 +609,7 @@ ia32hax_copyregNP2toHAX(void) np2haxstat.state._ds.type = CPU_DS_DESC.flag; np2haxstat.state._ds.desc = CPU_DS_DESC.s; np2haxstat.state._ds.dpl = CPU_DS_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._ds.selector = (np2haxstat.state._ds.selector & ‾0x3) | CPU_CS_DESC.rpl; + //if(wacounter > 10)np2haxstat.state._ds.selector = (np2haxstat.state._ds.selector & ~0x3) | CPU_CS_DESC.rpl; np2haxstat.state._ds.present = CPU_DS_DESC.valid; np2haxstat.state._ds.available = CPU_DS_DESC.p; np2haxstat.state._ds.operand_size = CPU_DS_DESC.d; @@ -620,7 +620,7 @@ ia32hax_copyregNP2toHAX(void) np2haxstat.state._es.type = CPU_ES_DESC.flag; np2haxstat.state._es.desc = CPU_ES_DESC.s; np2haxstat.state._es.dpl = CPU_ES_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._es.selector = (np2haxstat.state._es.selector & ‾0x3) | CPU_CS_DESC.rpl; + //if(wacounter > 10)np2haxstat.state._es.selector = (np2haxstat.state._es.selector & ~0x3) | CPU_CS_DESC.rpl; np2haxstat.state._es.present = CPU_ES_DESC.valid; np2haxstat.state._es.available = CPU_ES_DESC.p; np2haxstat.state._es.operand_size = CPU_ES_DESC.d; @@ -631,7 +631,7 @@ ia32hax_copyregNP2toHAX(void) np2haxstat.state._ss.type = CPU_SS_DESC.flag; np2haxstat.state._ss.desc = CPU_SS_DESC.s; np2haxstat.state._ss.dpl = CPU_SS_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._ss.selector = (np2haxstat.state._ss.selector & ‾0x3) | CPU_CS_DESC.rpl; + //if(wacounter > 10)np2haxstat.state._ss.selector = (np2haxstat.state._ss.selector & ~0x3) | CPU_CS_DESC.rpl; np2haxstat.state._ss.present = CPU_SS_DESC.valid; np2haxstat.state._ss.available = CPU_SS_DESC.p; np2haxstat.state._ss.operand_size = CPU_SS_DESC.d; @@ -642,7 +642,7 @@ ia32hax_copyregNP2toHAX(void) np2haxstat.state._fs.type = CPU_FS_DESC.flag; np2haxstat.state._fs.desc = CPU_FS_DESC.s; np2haxstat.state._fs.dpl = CPU_FS_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._fs.selector = (np2haxstat.state._fs.selector & ‾0x3) | CPU_CS_DESC.rpl; + //if(wacounter > 10)np2haxstat.state._fs.selector = (np2haxstat.state._fs.selector & ~0x3) | CPU_CS_DESC.rpl; np2haxstat.state._fs.present = CPU_FS_DESC.valid; np2haxstat.state._fs.available = CPU_FS_DESC.p; np2haxstat.state._fs.operand_size = CPU_FS_DESC.d; @@ -653,7 +653,7 @@ ia32hax_copyregNP2toHAX(void) np2haxstat.state._gs.type = CPU_GS_DESC.flag; np2haxstat.state._gs.desc = CPU_GS_DESC.s; np2haxstat.state._gs.dpl = CPU_GS_DESC.dpl; - //if(wacounter > 10)np2haxstat.state._gs.selector = (np2haxstat.state._gs.selector & ‾0x3) | CPU_CS_DESC.rpl; + //if(wacounter > 10)np2haxstat.state._gs.selector = (np2haxstat.state._gs.selector & ~0x3) | CPU_CS_DESC.rpl; np2haxstat.state._gs.present = CPU_GS_DESC.valid; np2haxstat.state._gs.available = CPU_GS_DESC.p; np2haxstat.state._gs.operand_size = CPU_GS_DESC.d; @@ -895,7 +895,7 @@ void i386hax_vm_exec_part(void) { // CPU実行再開のための処理(高速処理が要るもの) switch (exitstatus) { case HAX_EXIT_IO: // I/Oポートへのアクセス - //printf("HAX_EXIT_IO¥n"); + //printf("HAX_EXIT_IO\n"); oldremclock = CPU_REMCLOCK; switch(tunnel->io._direction){ // 入力 or 出力 case HAX_IO_OUT: // 出力 @@ -1009,7 +1009,7 @@ void i386hax_vm_exec_part(void) { //} break; case HAX_EXIT_FAST_MMIO: // メモリマップドI/Oへのアクセス - //printf("HAX_EXIT_FAST_MMIO¥n"); + //printf("HAX_EXIT_FAST_MMIO\n"); { HAX_FASTMMIO *mmio = (HAX_FASTMMIO*)np2hax.tunnel.io_va; @@ -1082,18 +1082,18 @@ void i386hax_vm_exec_part(void) { // CPU実行再開のための処理(処理速度はどうでもいい物) switch (exitstatus) { case HAX_EXIT_MMIO: // メモリマップドI/Oへのアクセス(旧式・もう呼ばれないと思う) - //printf("HAX_EXIT_MMIO¥n"); + //printf("HAX_EXIT_MMIO\n"); break; case HAX_EXIT_REALMODE: // 事前設定をするとリアルモードの時に呼ばれるらしい - //printf("HAX_EXIT_REALMODE¥n"); + //printf("HAX_EXIT_REALMODE\n"); break; case HAX_EXIT_INTERRUPT: // 割り込み・・・? - //printf("HAX_EXIT_INTERRUPT¥n"); + //printf("HAX_EXIT_INTERRUPT\n"); // リセット可能フラグを立てる np2haxcore.ready_for_reset = 1; break; case HAX_EXIT_UNKNOWN: // 謎 - //printf("HAX_EXIT_UNKNOWN¥n"); + //printf("HAX_EXIT_UNKNOWN\n"); //if(!CPU_RESETREQ){ // np2hax.emumode = 1; // CPU_REMCLOCK = 0; @@ -1109,7 +1109,7 @@ void i386hax_vm_exec_part(void) { break; case HAX_EXIT_HLT: // HLT命令が実行されたとき np2haxcore.hltflag = 1; - //printf("HAX_EXIT_HLT¥n"); + //printf("HAX_EXIT_HLT\n"); // リセット可能フラグを立てる np2haxcore.ready_for_reset = 1; // リアルモード or 仮想86 @@ -1132,7 +1132,7 @@ void i386hax_vm_exec_part(void) { } break; case HAX_EXIT_STATECHANGE: // CPU状態が変わったとき・・・と言いつつ、事実上CPUが実行不能(panic)になったときしか呼ばれない - //printf("HAX_EXIT_STATECHANGE¥n"); + //printf("HAX_EXIT_STATECHANGE\n"); // リセット可能フラグを立てる np2haxcore.ready_for_reset = 1; //if(!CPU_RESETREQ){ @@ -1154,7 +1154,7 @@ void i386hax_vm_exec_part(void) { // UINT8 memdump[0x100]; // UINT32 baseaddr; // addr = CPU_EIP + (CPU_CS << 4); - // baseaddr = addr & ‾0xff; + // baseaddr = addr & ~0xff; // for(i=0;i<0x100;i++){ // memdumpa[i] = baseaddr + i; // memdump[i] = memp_read8(memdumpa[i]); @@ -1165,15 +1165,15 @@ void i386hax_vm_exec_part(void) { //} break; case HAX_EXIT_PAUSED: // 一時停止? - //printf("HAX_EXIT_PAUSED¥n"); + //printf("HAX_EXIT_PAUSED\n"); // リセット可能フラグを立てる np2haxcore.ready_for_reset = 1; break; case HAX_EXIT_PAGEFAULT: // ページフォールト? - //printf("HAX_EXIT_PAGEFAULT¥n"); + //printf("HAX_EXIT_PAGEFAULT\n"); break; case HAX_EXIT_DEBUG: // デバッグ命令(INT3 CCh)が呼ばれたとき - //printf("HAX_EXIT_DEBUG¥n"); + //printf("HAX_EXIT_DEBUG\n"); // リセット可能フラグを立てる np2haxcore.ready_for_reset = 1; break; diff --git a/io/cgrom.c b/io/cgrom.c index d65abaa3..836aa606 100644 --- a/io/cgrom.c +++ b/io/cgrom.c @@ -70,10 +70,10 @@ static void IOOUTCALL cgrom_oa1(UINT port, REG8 dat) { // UINT16 SJis; // UINT8 th[3]; // UINT16 thw[2]; -// thw[1]='¥0'; +// thw[1]='\0'; // SJis = font_Jis2Sjis(((cr->code + 0x20) << 8) | (cr->code >> 8)); // if(SJis){ -// th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '¥0'; +// th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '\0'; // codecnv_sjistoucs2(thw, 1, (const char*)th, 2); // font_outhooktest((wchar_t*)thw); // } @@ -98,10 +98,10 @@ static void IOOUTCALL cgrom_oa3(UINT port, REG8 dat) { UINT16 SJis; UINT8 th[3]; UINT16 thw[2]; - thw[1]='¥0'; + thw[1]='\0'; SJis = font_Jis2Sjis(((cr->code + 0x20) << 8) | (cr->code >> 8)); if(SJis){ - th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '¥0'; + th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '\0'; codecnv_sjistoucs2(thw, 1, (const char*)th, 2); font_outhooktest((wchar_t*)thw); } @@ -124,10 +124,10 @@ static void IOOUTCALL cgrom_oa5(UINT port, REG8 dat) { UINT16 SJis; UINT8 th[3]; UINT16 thw[2]; - thw[1]='¥0'; + thw[1]='\0'; SJis = font_Jis2Sjis(((cr->code + 0x20) << 8) | (cr->code >> 8)); if(SJis){ - th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '¥0'; + th[0] = SJis >> 8; th[1] = SJis & 0x00ff; th[2] = '\0'; codecnv_sjistoucs2(thw, 1, (const char*)th, 2); font_outhooktest((wchar_t*)thw); } diff --git a/io/np2sysp.c b/io/np2sysp.c index 2b9507e5..2850b26f 100644 --- a/io/np2sysp.c +++ b/io/np2sysp.c @@ -54,7 +54,7 @@ static void trace_fmt_ex(const char* fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } @@ -65,7 +65,7 @@ static void trace_fmt_exw(const WCHAR* fmt, ...) va_list ap; va_start(ap, fmt); vswprintf(stmp, 2048, fmt, ap); - wcscat(stmp, L"¥n"); + wcscat(stmp, L"\n"); va_end(ap); OutputDebugStringW(stmp); } diff --git a/io/pit.c b/io/pit.c index 3e32d4f2..b7d6c697 100644 --- a/io/pit.c +++ b/io/pit.c @@ -131,7 +131,7 @@ void rs232ctimer(NEVENTITEM item) { if (item->flag & NEVENT_SETEVENT) { pitch = pit.ch + 2; if (pitch->flag & PIT_FLAG_I) { - //pitch->flag &= ‾PIT_FLAG_I; + //pitch->flag &= ~PIT_FLAG_I; rs232c_callback(); } #if defined(SUPPORT_RS232C_FIFO) diff --git a/io/upd4990.c b/io/upd4990.c index 3d310e24..91f159b9 100644 --- a/io/upd4990.c +++ b/io/upd4990.c @@ -151,7 +151,7 @@ void upd4990_hrtimer_count(void) { // hrtimertimeuint = LOADINTELDWORD(mem+0x04F1); // hrtimertimeuint++; // if((hrtimertimeuint & 0x3fffff) >= 24*60*60*32){ - // hrtimertimeuint = ((hrtimertimeuint & ‾0x3fffff) + 0x400000) & 0xffffff; // 日付変わった + // hrtimertimeuint = ((hrtimertimeuint & ~0x3fffff) + 0x400000) & 0xffffff; // 日付変わった // } // STOREINTELDWORD(mem+0x04F1, hrtimertimeuint); // XXX: 04F4にも書いちゃってるけど差し当たっては問題なさそうなので・・・ // } diff --git a/network/net.c b/network/net.c index d34fed19..7066e90d 100644 --- a/network/net.c +++ b/network/net.c @@ -194,13 +194,13 @@ static int doWriteTap(HANDLE hTap, const UCHAR *pSendBuf, DWORD len, OVERLAPPED return 1; } } else { - TRACEOUT(("LGY-98: WriteFile err=0x%08X¥n", err)); + TRACEOUT(("LGY-98: WriteFile err=0x%08X\n", err)); return -1; } }else{ np2net_cs_LeaveCriticalSection(); } - //TRACEOUT(("LGY-98: send %u bytes¥n", dwWriteLen)); + //TRACEOUT(("LGY-98: send %u bytes\n", dwWriteLen)); return 0; } #else @@ -334,7 +334,7 @@ static unsigned int __stdcall np2net_ThreadFuncR(LPVOID vdParam) { Sleep(0); } if(dwLen>0){ - //TRACEOUT(("LGY-98: recieve %u bytes¥n", dwLen)); + //TRACEOUT(("LGY-98: recieve %u bytes\n", dwLen)); np2net.recieve_packet((UINT8*)np2net_Buf, dwLen); // 受信できたので通知する } } else { diff --git a/nevent.c b/nevent.c index 78b7c329..435ef3e7 100644 --- a/nevent.c +++ b/nevent.c @@ -18,7 +18,7 @@ static void trace_fmt_ex(const char* fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } @@ -184,7 +184,7 @@ void nevent_progress(void) // NEVENT_FLAMESが消える問題に暫定対処 if(!fevtchk){ - //printf("NEVENT_FLAMES is missing!!¥n"); + //printf("NEVENT_FLAMES is missing!!\n"); pcstat.screendispflag = 0; } #if defined(SUPPORT_MULTITHREAD) diff --git a/sound/pcm86.h b/sound/pcm86.h index 34fadd7f..e2139261 100644 --- a/sound/pcm86.h +++ b/sound/pcm86.h @@ -23,18 +23,18 @@ enum { #define PCM86_REALBUFSIZE (PCM86_LOGICALBUF + PCM86_EXTBUF) void RECALC_NOWCLKWAIT(UINT64 cnt); -//#define RECALC_NOWCLKWAIT(cnt) ¥ -// do ¥ -// { ¥ -// SINT64 decvalue =(SINT64)(cnt << g_pcm86.stepbit); ¥ -// if (g_pcm86.virbuf - decvalue < g_pcm86.virbuf) ¥ -// { ¥ -// g_pcm86.virbuf -= decvalue; ¥ -// } ¥ -// if (g_pcm86.virbuf < 0) ¥ -// { ¥ -// g_pcm86.virbuf &= g_pcm86.stepmask; ¥ -// } ¥ +//#define RECALC_NOWCLKWAIT(cnt) \ +// do \ +// { \ +// SINT64 decvalue =(SINT64)(cnt << g_pcm86.stepbit); \ +// if (g_pcm86.virbuf - decvalue < g_pcm86.virbuf) \ +// { \ +// g_pcm86.virbuf -= decvalue; \ +// } \ +// if (g_pcm86.virbuf < 0) \ +// { \ +// g_pcm86.virbuf &= g_pcm86.stepmask; \ +// } \ // } while (0 /*CONSTCOND*/) typedef struct { diff --git a/sound/pcm86c.c b/sound/pcm86c.c index ef69f268..b7874b7b 100644 --- a/sound/pcm86c.c +++ b/sound/pcm86c.c @@ -18,7 +18,7 @@ static void trace_fmt_ex(const char *fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } diff --git a/sound/pcm86g.c b/sound/pcm86g.c index 679cc090..89156260 100644 --- a/sound/pcm86g.c +++ b/sound/pcm86g.c @@ -15,7 +15,7 @@ static void trace_fmt_ex(const char* fmt, ...) va_list ap; va_start(ap, fmt); vsprintf(stmp, fmt, ap); - strcat(stmp, "¥n"); + strcat(stmp, "\n"); va_end(ap); OutputDebugStringA(stmp); } diff --git a/wab/cirrus_vga.c b/wab/cirrus_vga.c index e493cb30..c83eacad 100644 --- a/wab/cirrus_vga.c +++ b/wab/cirrus_vga.c @@ -77,7 +77,7 @@ // va_list ap; // va_start(ap, fmt); // vsprintf(stmp, fmt, ap); -// strcat(stmp, "¥n"); +// strcat(stmp, "\n"); // va_end(ap); // OutputDebugStringA(stmp); //} diff --git a/windows/mousemng.cpp b/windows/mousemng.cpp index da696883..691f5662 100644 --- a/windows/mousemng.cpp +++ b/windows/mousemng.cpp @@ -319,7 +319,7 @@ static void mousecapture(BOOL capture) { rct.bottom = cp.y + MOUSEMNG_RANGE; SetCursorPos(cp.x, cp.y); ClipCursor(&rct); - style &= ‾(CS_DBLCLKS); + style &= ~(CS_DBLCLKS); mousecaptureflg = 1; if(np2oscfg.rawmouse && fndi8create){ initDirectInput(); @@ -329,7 +329,7 @@ static void mousecapture(BOOL capture) { ShowCursor(TRUE); ClipCursor(NULL); if (np2oscfg.mouse_nc) { - style &= ‾(CS_DBLCLKS); + style &= ~(CS_DBLCLKS); } else { style |= CS_DBLCLKS; @@ -459,7 +459,7 @@ BOOL mousemng_buttonevent(UINT event) { if (!mousemng.flag || (np2oscfg.mouse_nc/* && !scrnmng_isfullscreen()*/ && mousemng.flag)) { switch(event) { case MOUSEMNG_LEFTDOWN: - mousemng.btn &= ‾(uPD8255A_LEFTBIT); + mousemng.btn &= ~(uPD8255A_LEFTBIT); break; case MOUSEMNG_LEFTUP: @@ -467,7 +467,7 @@ BOOL mousemng_buttonevent(UINT event) { break; case MOUSEMNG_RIGHTDOWN: - mousemng.btn &= ‾(uPD8255A_RIGHTBIT); + mousemng.btn &= ~(uPD8255A_RIGHTBIT); break; case MOUSEMNG_RIGHTUP: @@ -490,7 +490,7 @@ void mousemng_enable(UINT proc) { np2_multithread_EnterCriticalSection(); bit = 1 << proc; if (mousemng.flag & bit) { - mousemng.flag &= ‾bit; + mousemng.flag &= ~bit; if (!mousemng.flag) { mousecapture(TRUE); } diff --git a/windows/np2arg.cpp b/windows/np2arg.cpp index e05806b8..ef34a87a 100644 --- a/windows/np2arg.cpp +++ b/windows/np2arg.cpp @@ -99,12 +99,12 @@ void Np2Arg::Parse() if(lpIniFile){ // np21w ver0.86 rev8 LPTSTR strbuf; strbuf = (LPTSTR)calloc(500, sizeof(TCHAR)); - if(!(_tcsstr(lpIniFile,_T(":"))!=NULL || (lpIniFile[0]=='¥¥'))){ + if(!(_tcsstr(lpIniFile,_T(":"))!=NULL || (lpIniFile[0]=='\\'))){ // ファイル名のみの指定っぽかったら現在のディレクトリを結合 //getcwd(pathname, 300); GetCurrentDirectory(500, strbuf); - if(strbuf[_tcslen(strbuf)-1]!='¥¥'){ - _tcscat(strbuf, _T("¥¥")); // XXX: Linuxとかだったらスラッシュじゃないと駄目だよね? -> Win専用だから問題ない + if(strbuf[_tcslen(strbuf)-1]!='\\'){ + _tcscat(strbuf, _T("\\")); // XXX: Linuxとかだったらスラッシュじゃないと駄目だよね? -> Win専用だから問題ない } } _tcscat(strbuf, lpIniFile); diff --git a/windows/sysmng.cpp b/windows/sysmng.cpp index da704d05..c0c126bd 100644 --- a/windows/sysmng.cpp +++ b/windows/sysmng.cpp @@ -62,7 +62,7 @@ BOOL sysmng_workclockrenewal(void) { } OEMCHAR* DOSIOCALL sysmng_file_getname(OEMCHAR* lpPathName){ - if(_tcsnicmp(lpPathName, OEMTEXT("¥¥¥¥.¥¥"), 4)==0){ + if(_tcsnicmp(lpPathName, OEMTEXT("\\\\.\\"), 4)==0){ return lpPathName; }else{ return file_getname(lpPathName); @@ -84,7 +84,7 @@ void sysmng_updatecaption(UINT8 flag) { OEMCHAR fddtext[16] = {0}; if (flag & 1) { - title[0] = '¥0'; + title[0] = '\0'; for(i=0;i<4;i++){ OEMSPRINTF(fddtext, OEMTEXT(" FDD%d:"), i+1); if (fdd_diskready(i)) { @@ -269,7 +269,7 @@ void sysmng_updatecaption(UINT8 flag) { } if (flag & 2) { - clock[0] = '¥0'; + clock[0] = '\0'; if (np2oscfg.DISPCLK & 2) { if (workclock.fps) { OEMSPRINTF(clock, OEMTEXT(" - %u.%1uFPS"), @@ -282,7 +282,7 @@ void sysmng_updatecaption(UINT8 flag) { if (!np2userpause && (np2oscfg.DISPCLK & 1)) { OEMSPRINTF(work, OEMTEXT(" %2u.%03uMHz"), workclock.khz / 1000, workclock.khz % 1000); - if (clock[0] == '¥0') { + if (clock[0] == '\0') { milstr_ncpy(clock, OEMTEXT(" -"), NELEMENTS(clock)); } milstr_ncat(clock, work, NELEMENTS(clock)); @@ -296,7 +296,7 @@ void sysmng_updatecaption(UINT8 flag) { } if (flag & 4) { - misc[0] = '¥0'; + misc[0] = '\0'; if(sys_miscinfo.showvolume && sys_miscinfo.showmousespeed){ OEMSPRINTF(misc, OEMTEXT(" (Volume: %d%%, Mouse speed: %d%%)"), np2cfg.vol_master, 100 * np2oscfg.mousemul/np2oscfg.mousediv); }else if(sys_miscinfo.showvolume){